support using BrowserOption in NewContext
While at it, remove the error return from BrowserOption, to make it consistent with all the other option func types. We don't have a good test for this feature yet, but at least we check that it doesn't crash or error via an example. Fixes #292.
This commit is contained in:
parent
a29b1ec1d6
commit
b8efcf0691
|
@ -20,7 +20,7 @@ type Allocator interface {
|
||||||
// Allocate creates a new browser. It can be cancelled via the provided
|
// Allocate creates a new browser. It can be cancelled via the provided
|
||||||
// context, at which point all the resources used by the browser (such
|
// context, at which point all the resources used by the browser (such
|
||||||
// as temporary directories) will be freed.
|
// as temporary directories) will be freed.
|
||||||
Allocate(context.Context) (*Browser, error)
|
Allocate(context.Context, ...BrowserOption) (*Browser, error)
|
||||||
|
|
||||||
// TODO: Wait should probably return an error, which can then be
|
// TODO: Wait should probably return an error, which can then be
|
||||||
// retrieved by the user if just calling cancel().
|
// retrieved by the user if just calling cancel().
|
||||||
|
@ -73,7 +73,7 @@ type ExecAllocator struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Allocate satisfies the Allocator interface.
|
// Allocate satisfies the Allocator interface.
|
||||||
func (p *ExecAllocator) Allocate(ctx context.Context) (*Browser, error) {
|
func (p *ExecAllocator) Allocate(ctx context.Context, opts ...BrowserOption) (*Browser, error) {
|
||||||
c := FromContext(ctx)
|
c := FromContext(ctx)
|
||||||
if c == nil {
|
if c == nil {
|
||||||
return nil, ErrInvalidContext
|
return nil, ErrInvalidContext
|
||||||
|
@ -152,7 +152,7 @@ func (p *ExecAllocator) Allocate(ctx context.Context) (*Browser, error) {
|
||||||
}
|
}
|
||||||
stderr.Close()
|
stderr.Close()
|
||||||
|
|
||||||
browser, err := NewBrowser(ctx, wsURL)
|
browser, err := NewBrowser(ctx, wsURL, opts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
27
browser.go
27
browser.go
|
@ -78,9 +78,7 @@ func NewBrowser(ctx context.Context, urlstr string, opts ...BrowserOption) (*Bro
|
||||||
|
|
||||||
// apply options
|
// apply options
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
if err := o(b); err != nil {
|
o(b)
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// ensure errf is set
|
// ensure errf is set
|
||||||
|
@ -322,29 +320,22 @@ func (b *Browser) run(ctx context.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// BrowserOption is a browser option.
|
// BrowserOption is a browser option.
|
||||||
type BrowserOption func(*Browser) error
|
type BrowserOption func(*Browser)
|
||||||
|
|
||||||
// WithLogf is a browser option to specify a func to receive general logging.
|
// WithBrowserLogf is a browser option to specify a func to receive general logging.
|
||||||
func WithLogf(f func(string, ...interface{})) BrowserOption {
|
func WithBrowserLogf(f func(string, ...interface{})) BrowserOption {
|
||||||
return func(b *Browser) error {
|
return func(b *Browser) { b.logf = f }
|
||||||
b.logf = f
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithErrorf is a browser option to specify a func to receive error logging.
|
// WithBrowserErrorf is a browser option to specify a func to receive error logging.
|
||||||
func WithErrorf(f func(string, ...interface{})) BrowserOption {
|
func WithBrowserErrorf(f func(string, ...interface{})) BrowserOption {
|
||||||
return func(b *Browser) error {
|
return func(b *Browser) { b.errf = f }
|
||||||
b.errf = f
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithConsolef is a browser option to specify a func to receive chrome log events.
|
// WithConsolef is a browser option to specify a func to receive chrome log events.
|
||||||
//
|
//
|
||||||
// Note: NOT YET IMPLEMENTED.
|
// Note: NOT YET IMPLEMENTED.
|
||||||
func WithConsolef(f func(string, ...interface{})) BrowserOption {
|
func WithConsolef(f func(string, ...interface{})) BrowserOption {
|
||||||
return func(b *Browser) error {
|
return func(b *Browser) {
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
38
chromedp.go
38
chromedp.go
|
@ -36,6 +36,11 @@ type Context struct {
|
||||||
// have its own unique Target pointing to a separate browser tab (page).
|
// have its own unique Target pointing to a separate browser tab (page).
|
||||||
Target *Target
|
Target *Target
|
||||||
|
|
||||||
|
// browserOpts holds the browser options passed to NewContext via
|
||||||
|
// WithBrowserOption, so that they can later be used when allocating a
|
||||||
|
// browser in Run.
|
||||||
|
browserOpts []BrowserOption
|
||||||
|
|
||||||
// cancel simply cancels the context that was used to start Browser.
|
// cancel simply cancels the context that was used to start Browser.
|
||||||
// This is useful to stop all activity and avoid deadlocks if we detect
|
// This is useful to stop all activity and avoid deadlocks if we detect
|
||||||
// that the browser was closed or happened to crash. Note that this
|
// that the browser was closed or happened to crash. Note that this
|
||||||
|
@ -56,12 +61,14 @@ type Context struct {
|
||||||
func NewContext(parent context.Context, opts ...ContextOption) (context.Context, context.CancelFunc) {
|
func NewContext(parent context.Context, opts ...ContextOption) (context.Context, context.CancelFunc) {
|
||||||
ctx, cancel := context.WithCancel(parent)
|
ctx, cancel := context.WithCancel(parent)
|
||||||
|
|
||||||
c := &Context{cancel: cancel}
|
c := &Context{cancel: cancel, first: true}
|
||||||
if pc := FromContext(parent); pc != nil {
|
if pc := FromContext(parent); pc != nil {
|
||||||
c.Allocator = pc.Allocator
|
c.Allocator = pc.Allocator
|
||||||
c.Browser = pc.Browser
|
c.Browser = pc.Browser
|
||||||
// don't inherit SessionID, so that NewContext can be used to
|
// don't inherit SessionID, so that NewContext can be used to
|
||||||
// create a new tab on the same browser.
|
// create a new tab on the same browser.
|
||||||
|
|
||||||
|
c.first = c.Browser == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, o := range opts {
|
for _, o := range opts {
|
||||||
|
@ -127,12 +134,11 @@ func Run(ctx context.Context, actions ...Action) error {
|
||||||
return ErrInvalidContext
|
return ErrInvalidContext
|
||||||
}
|
}
|
||||||
if c.Browser == nil {
|
if c.Browser == nil {
|
||||||
browser, err := c.Allocator.Allocate(ctx)
|
browser, err := c.Allocator.Allocate(ctx, c.browserOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
c.Browser = browser
|
c.Browser = browser
|
||||||
c.first = true
|
|
||||||
}
|
}
|
||||||
if c.Target == nil {
|
if c.Target == nil {
|
||||||
if err := c.newSession(ctx); err != nil {
|
if err := c.newSession(ctx); err != nil {
|
||||||
|
@ -197,8 +203,31 @@ func (c *Context) newSession(ctx context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ContextOption is a context option.
|
||||||
type ContextOption func(*Context)
|
type ContextOption func(*Context)
|
||||||
|
|
||||||
|
// WithLogf is a shortcut for WithBrowserOption(WithBrowserLogf(f)).
|
||||||
|
func WithLogf(f func(string, ...interface{})) ContextOption {
|
||||||
|
return WithBrowserOption(WithBrowserLogf(f))
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithErrorf is a shortcut for WithBrowserOption(WithBrowserErrorf(f)).
|
||||||
|
func WithErrorf(f func(string, ...interface{})) ContextOption {
|
||||||
|
return WithBrowserOption(WithBrowserErrorf(f))
|
||||||
|
}
|
||||||
|
|
||||||
|
// WithBrowserOption allows passing a number of browser options to the allocator
|
||||||
|
// when allocating a new browser. As such, this context option can only be used
|
||||||
|
// when NewContext is allocating a new browser.
|
||||||
|
func WithBrowserOption(opts ...BrowserOption) ContextOption {
|
||||||
|
return func(c *Context) {
|
||||||
|
if !c.first {
|
||||||
|
panic("WithBrowserOption can only be used when allocating a new browser")
|
||||||
|
}
|
||||||
|
c.browserOpts = append(c.browserOpts, opts...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Targets lists all the targets in the browser attached to the given context.
|
// Targets lists all the targets in the browser attached to the given context.
|
||||||
func Targets(ctx context.Context) ([]*target.Info, error) {
|
func Targets(ctx context.Context) ([]*target.Info, error) {
|
||||||
// Don't rely on Run, as that needs to be able to call Targets, and we
|
// Don't rely on Run, as that needs to be able to call Targets, and we
|
||||||
|
@ -209,12 +238,11 @@ func Targets(ctx context.Context) ([]*target.Info, error) {
|
||||||
return nil, ErrInvalidContext
|
return nil, ErrInvalidContext
|
||||||
}
|
}
|
||||||
if c.Browser == nil {
|
if c.Browser == nil {
|
||||||
browser, err := c.Allocator.Allocate(ctx)
|
browser, err := c.Allocator.Allocate(ctx, c.browserOpts...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
c.Browser = browser
|
c.Browser = browser
|
||||||
c.first = true
|
|
||||||
}
|
}
|
||||||
return target.GetTargets().Do(ctx, c.Browser)
|
return target.GetTargets().Do(ctx, c.Browser)
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
@ -48,7 +49,8 @@ func ExampleExecAllocator() {
|
||||||
allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
|
allocCtx, cancel := chromedp.NewExecAllocator(context.Background(), opts...)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
taskCtx, cancel := chromedp.NewContext(allocCtx)
|
// also set up a custom logger
|
||||||
|
taskCtx, cancel := chromedp.NewContext(allocCtx, chromedp.WithLogf(log.Printf))
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// ensure that the browser process is started
|
// ensure that the browser process is started
|
||||||
|
|
Loading…
Reference in New Issue
Block a user