@@ -23,7 +23,6 @@ package common
23
23
import (
24
24
"context"
25
25
"fmt"
26
- "regexp"
27
26
"strings"
28
27
"sync"
29
28
"sync/atomic"
@@ -36,7 +35,6 @@ import (
36
35
"github.com/dop251/goja"
37
36
"github.com/gorilla/websocket"
38
37
"github.com/grafana/xk6-browser/api"
39
- k6lib "go.k6.io/k6/lib"
40
38
)
41
39
42
40
// Ensure Browser implements the EventEmitter and Browser interfaces
@@ -85,9 +83,7 @@ type Browser struct {
85
83
}
86
84
87
85
// NewBrowser creates a new browser
88
- func NewBrowser (ctx context.Context , cancelFn context.CancelFunc , browserProc * BrowserProcess , launchOpts * LaunchOptions ) (* Browser , error ) {
89
- state := k6lib .GetState (ctx )
90
- reCategoryFilter , _ := regexp .Compile (launchOpts .LogCategoryFilter )
86
+ func NewBrowser (ctx context.Context , cancelFn context.CancelFunc , browserProc * BrowserProcess , launchOpts * LaunchOptions , logger * Logger ) (* Browser , error ) {
91
87
b := Browser {
92
88
BaseEventEmitter : NewBaseEventEmitter (ctx ),
93
89
ctx : ctx ,
@@ -103,7 +99,7 @@ func NewBrowser(ctx context.Context, cancelFn context.CancelFunc, browserProc *B
103
99
pages : make (map [target.ID ]* Page ),
104
100
sessionIDtoTargetIDMu : sync.RWMutex {},
105
101
sessionIDtoTargetID : make (map [target.SessionID ]target.ID ),
106
- logger : NewLogger ( ctx , state . Logger , launchOpts . Debug , reCategoryFilter ) ,
102
+ logger : logger ,
107
103
}
108
104
if err := b .connect (); err != nil {
109
105
return nil , err
@@ -112,6 +108,7 @@ func NewBrowser(ctx context.Context, cancelFn context.CancelFunc, browserProc *B
112
108
}
113
109
114
110
func (b * Browser ) connect () error {
111
+ b .logger .Debugf ("Browser:connect" , "wsURL:%v" , b .browserProc .WsURL ())
115
112
var err error
116
113
b .conn , err = NewConnection (b .ctx , b .browserProc .WsURL (), b .logger )
117
114
if err != nil {
@@ -126,6 +123,7 @@ func (b *Browser) connect() error {
126
123
}
127
124
128
125
func (b * Browser ) disposeContext (id cdp.BrowserContextID ) error {
126
+ b .logger .Debugf ("Browser:disposeContext" , "bctxid:%v" , id )
129
127
action := target .DisposeBrowserContext (id )
130
128
if err := action .Do (cdp .WithExecutor (b .ctx , b .conn )); err != nil {
131
129
return fmt .Errorf ("unable to dispose browser context %T: %w" , action , err )
@@ -164,10 +162,14 @@ func (b *Browser) initEvents() error {
164
162
return
165
163
case event := <- chHandler :
166
164
if ev , ok := event .data .(* target.EventAttachedToTarget ); ok {
165
+ b .logger .Debugf ("Browser:initEvents:onAttachedToTarget" , "sid:%v tid:%v" , ev .SessionID , ev .TargetInfo .TargetID )
167
166
go b .onAttachedToTarget (ev )
168
167
} else if ev , ok := event .data .(* target.EventDetachedFromTarget ); ok {
168
+ b .logger .Debugf ("Browser:initEvents:onDetachedFromTarget" , "sid:%v" , ev .SessionID )
169
169
go b .onDetachedFromTarget (ev )
170
170
} else if event .typ == EventConnectionClose {
171
+ b .logger .Debugf ("Browser:initEvents:EventConnectionClose" , "" )
172
+
171
173
b .connMu .Lock ()
172
174
b .connected = false
173
175
b .connMu .Unlock ()
@@ -197,31 +199,38 @@ func (b *Browser) initEvents() error {
197
199
func (b * Browser ) onAttachedToTarget (ev * target.EventAttachedToTarget ) {
198
200
b .contextsMu .RLock ()
199
201
var browserCtx * BrowserContext = b .defaultContext
200
- if b , ok := b .contexts [ev .TargetInfo .BrowserContextID ]; ok {
201
- browserCtx = b
202
+ bctx , ok := b .contexts [ev .TargetInfo .BrowserContextID ]
203
+ if ok {
204
+ browserCtx = bctx
202
205
}
206
+ b .logger .Debugf ("Browser:onAttachedToTarget" , "sid:%v tid:%v bcid:%v bctx nil=%t" , ev .SessionID , ev .TargetInfo .TargetID , ev .TargetInfo .BrowserContextID , bctx == nil )
203
207
b .contextsMu .RUnlock ()
204
208
205
209
// We're not interested in the top-level browser target, other targets or DevTools targets right now.
206
210
isDevTools := strings .HasPrefix (ev .TargetInfo .URL , "devtools://devtools" )
207
211
if ev .TargetInfo .Type == "browser" || ev .TargetInfo .Type == "other" || isDevTools {
212
+ b .logger .Debugf ("Browser:onAttachedToTarget" , "sid:%v tid:%v, returns: devtools" , ev .SessionID , ev .TargetInfo .TargetID )
208
213
return
209
214
}
210
215
211
216
if ev .TargetInfo .Type == "background_page" {
212
- p , err := NewPage (b .ctx , b .conn .getSession (ev .SessionID ), browserCtx , ev .TargetInfo .TargetID , nil , false )
217
+ p , err := NewPage (b .ctx , b .conn .getSession (ev .SessionID ), browserCtx , ev .TargetInfo .TargetID , nil , false , b . logger )
213
218
if err != nil {
214
219
isRunning := atomic .LoadInt64 (& b .state ) == BrowserStateOpen && b .IsConnected () //b.conn.isConnected()
215
220
if _ , ok := err .(* websocket.CloseError ); ! ok && ! isRunning {
216
221
// If we're no longer connected to browser, then ignore WebSocket errors
222
+ b .logger .Debugf ("Browser:onAttachedToTarget:background_page" , "sid:%v tid:%v, returns: websocket err: %v" ,
223
+ ev .SessionID , ev .TargetInfo .TargetID , err )
217
224
return
218
225
}
219
226
k6Throw (b .ctx , "cannot create NewPage for background_page event: %w" , err )
220
227
}
221
228
b .pagesMu .Lock ()
229
+ b .logger .Debugf ("Browser:onAttachedToTarget:background_page" , "sid:%v tid:%v, adding tid" , ev .SessionID , ev .TargetInfo .TargetID )
222
230
b .pages [ev .TargetInfo .TargetID ] = p
223
231
b .pagesMu .Unlock ()
224
232
b .sessionIDtoTargetIDMu .Lock ()
233
+ b .logger .Debugf ("Browser:onAttachedToTarget:background_page" , "sid:%v tid:%v, adding sid" , ev .SessionID , ev .TargetInfo .TargetID )
225
234
b .sessionIDtoTargetID [ev .SessionID ] = ev .TargetInfo .TargetID
226
235
b .sessionIDtoTargetIDMu .Unlock ()
227
236
} else if ev .TargetInfo .Type == "page" {
@@ -230,20 +239,24 @@ func (b *Browser) onAttachedToTarget(ev *target.EventAttachedToTarget) {
230
239
if t , ok := b .pages [ev .TargetInfo .OpenerID ]; ok {
231
240
opener = t
232
241
}
242
+ b .logger .Debugf ("Browser:onAttachedToTarget:page" , "sid:%v tid:%v opener nil:%t" , ev .SessionID , ev .TargetInfo .TargetID , opener == nil )
233
243
b .pagesMu .RUnlock ()
234
- p , err := NewPage (b .ctx , b .conn .getSession (ev .SessionID ), browserCtx , ev .TargetInfo .TargetID , opener , true )
244
+ p , err := NewPage (b .ctx , b .conn .getSession (ev .SessionID ), browserCtx , ev .TargetInfo .TargetID , opener , true , b . logger )
235
245
if err != nil {
236
246
isRunning := atomic .LoadInt64 (& b .state ) == BrowserStateOpen && b .IsConnected () //b.conn.isConnected()
237
247
if _ , ok := err .(* websocket.CloseError ); ! ok && ! isRunning {
238
248
// If we're no longer connected to browser, then ignore WebSocket errors
249
+ b .logger .Debugf ("Browser:onAttachedToTarget:page" , "sid:%v tid:%v, returns: websocket error" , ev .SessionID , ev .TargetInfo .TargetID )
239
250
return
240
251
}
241
252
k6Throw (b .ctx , "cannot create NewPage for page event: %w" , err )
242
253
}
243
254
b .pagesMu .Lock ()
255
+ b .logger .Debugf ("Browser:onAttachedToTarget:page" , "sid:%v tid:%v, adding page as a target" , ev .SessionID , ev .TargetInfo .TargetID )
244
256
b .pages [ev .TargetInfo .TargetID ] = p
245
257
b .pagesMu .Unlock ()
246
258
b .sessionIDtoTargetIDMu .Lock ()
259
+ b .logger .Debugf ("Browser:onAttachedToTarget:page" , "sid:%v tid:%v, changing sid to tid" , ev .SessionID , ev .TargetInfo .TargetID )
247
260
b .sessionIDtoTargetID [ev .SessionID ] = ev .TargetInfo .TargetID
248
261
b .sessionIDtoTargetIDMu .Unlock ()
249
262
browserCtx .emit (EventBrowserContextPage , p )
@@ -253,15 +266,18 @@ func (b *Browser) onAttachedToTarget(ev *target.EventAttachedToTarget) {
253
266
func (b * Browser ) onDetachedFromTarget (ev * target.EventDetachedFromTarget ) {
254
267
b .sessionIDtoTargetIDMu .RLock ()
255
268
targetID , ok := b .sessionIDtoTargetID [ev .SessionID ]
269
+ b .logger .Debugf ("Browser:onDetachedFromTarget" , "sid:%v tid:%v" , ev .SessionID , targetID )
256
270
b .sessionIDtoTargetIDMu .RUnlock ()
257
271
if ! ok {
272
+ b .logger .Debugf ("Browser:onDetachedFromTarget" , "sid:%v tid:%v, returns" , ev .SessionID , targetID )
258
273
// We don't track targets of type "browser", "other" and "devtools", so ignore if we don't recognize target.
259
274
return
260
275
}
261
276
262
277
b .pagesMu .Lock ()
263
278
defer b .pagesMu .Unlock ()
264
279
if t , ok := b .pages [targetID ]; ok {
280
+ b .logger .Debugf ("Browser:onDetachedFromTarget" , "tid:%v, delete page" , targetID )
265
281
delete (b .pages , targetID )
266
282
t .didClose ()
267
283
}
@@ -276,8 +292,9 @@ func (b *Browser) newPageInContext(id cdp.BrowserContextID) (*Page, error) {
276
292
}
277
293
278
294
var (
279
- mu sync.RWMutex // protects targetID
280
- targetID target.ID
295
+ mu sync.RWMutex // protects targetID
296
+ targetID target.ID
297
+ localTargetID target.ID // sync free access for logging
281
298
282
299
err error
283
300
)
@@ -286,6 +303,7 @@ func (b *Browser) newPageInContext(id cdp.BrowserContextID) (*Page, error) {
286
303
func (data interface {}) bool {
287
304
mu .RLock ()
288
305
defer mu .RUnlock ()
306
+ b .logger .Debugf ("Browser:newPageInContext" , "tid:%v bcid:%v, createWaitForEventHandler" , targetID , id )
289
307
return data .(* Page ).targetID == targetID
290
308
},
291
309
)
@@ -295,15 +313,21 @@ func (b *Browser) newPageInContext(id cdp.BrowserContextID) (*Page, error) {
295
313
action := target .CreateTarget ("about:blank" ).WithBrowserContextID (id )
296
314
mu .Lock ()
297
315
defer mu .Unlock ()
316
+ localTargetID = targetID
317
+ b .logger .Debugf ("Browser:newPageInContext" , "tid:%v bcid:%v, CreateTarget(blank)" , localTargetID , id )
298
318
if targetID , err = action .Do (cdp .WithExecutor (b .ctx , b .conn )); err != nil {
299
319
errCh <- fmt .Errorf ("unable to execute %T: %w" , action , err )
300
320
}
301
321
}()
302
322
select {
303
323
case <- b .ctx .Done ():
324
+ b .logger .Debugf ("Browser:newPageInContext:<-b.ctx.Done" , "tid:%v bcid:%v" , localTargetID , id )
304
325
case <- time .After (b .launchOpts .Timeout ):
305
- case <- ch :
326
+ b .logger .Debugf ("Browser:newPageInContext:timeout" , "tid:%v bcid:%v timeout:%s" , localTargetID , id , b .launchOpts .Timeout )
327
+ case c := <- ch :
328
+ b .logger .Debugf ("Browser:newPageInContext:<-ch" , "tid:%v bcid:%v, c:%v" , localTargetID , id , c )
306
329
case err := <- errCh :
330
+ b .logger .Debugf ("Browser:newPageInContext:<-errCh" , "tid:%v bcid:%v, err:%v" , localTargetID , id , err )
307
331
return nil , err
308
332
}
309
333
b .pagesMu .RLock ()
@@ -313,8 +337,10 @@ func (b *Browser) newPageInContext(id cdp.BrowserContextID) (*Page, error) {
313
337
314
338
// Close shuts down the browser
315
339
func (b * Browser ) Close () {
340
+ b .logger .Debugf ("Browser:Close" , "" )
316
341
if ! atomic .CompareAndSwapInt64 (& b .state , b .state , BrowserStateClosing ) {
317
342
// If we're already in a closing state then no need to continue.
343
+ b .logger .Debugf ("Browser:Close" , "already in a closing state" )
318
344
return
319
345
}
320
346
b .browserProc .GracefulClose ()
@@ -350,6 +376,7 @@ func (b *Browser) IsConnected() bool {
350
376
func (b * Browser ) NewContext (opts goja.Value ) api.BrowserContext {
351
377
action := target .CreateBrowserContext ().WithDisposeOnDetach (true )
352
378
browserContextID , err := action .Do (cdp .WithExecutor (b .ctx , b .conn ))
379
+ b .logger .Debugf ("Browser:NewContext" , "browserContextID: %v" , browserContextID )
353
380
if err != nil {
354
381
k6Throw (b .ctx , "unable to execute %T: %w" , action , err )
355
382
}
@@ -361,6 +388,7 @@ func (b *Browser) NewContext(opts goja.Value) api.BrowserContext {
361
388
362
389
b .contextsMu .Lock ()
363
390
defer b .contextsMu .Unlock ()
391
+ b .logger .Debugf ("Browser:NewContext" , "NewBrowserContext: %v" , browserContextID )
364
392
browserCtx := NewBrowserContext (b .ctx , b .conn , b , browserContextID , browserCtxOpts , b .logger )
365
393
b .contexts [browserContextID ] = browserCtx
366
394
0 commit comments