...
1 package playwright
2
3 import (
4 "encoding/json"
5 "fmt"
6 "io/ioutil"
7 )
8
9 type browserImpl struct {
10 channelOwner
11 isConnected bool
12 isClosedOrClosing bool
13 isConnectedOverWebSocket bool
14 contexts []BrowserContext
15 }
16
17 func (b *browserImpl) IsConnected() bool {
18 b.RLock()
19 defer b.RUnlock()
20 return b.isConnected
21 }
22
23 func (b *browserImpl) NewContext(options ...BrowserNewContextOptions) (BrowserContext, error) {
24 overrides := map[string]interface{}{}
25 if len(options) == 1 {
26 if options[0].ExtraHttpHeaders != nil {
27 overrides["extraHTTPHeaders"] = serializeMapToNameAndValue(options[0].ExtraHttpHeaders)
28 options[0].ExtraHttpHeaders = nil
29 }
30 if options[0].StorageStatePath != nil {
31 var storageState *BrowserNewContextOptionsStorageState
32 storageString, err := ioutil.ReadFile(*options[0].StorageStatePath)
33 if err != nil {
34 return nil, fmt.Errorf("could not read storage state file: %w", err)
35 }
36 err = json.Unmarshal(storageString, &storageState)
37 if err != nil {
38 return nil, fmt.Errorf("could not parse storage state file: %w", err)
39 }
40 options[0].StorageState = storageState
41 options[0].StorageStatePath = nil
42 }
43 if options[0].NoViewport != nil && *options[0].NoViewport {
44 overrides["noDefaultViewport"] = true
45 options[0].NoViewport = nil
46 }
47 }
48 channel, err := b.channel.Send("newContext", overrides, options)
49 if err != nil {
50 return nil, fmt.Errorf("could not send message: %w", err)
51 }
52 context := fromChannel(channel).(*browserContextImpl)
53 if len(options) == 1 {
54 context.options = &options[0]
55 }
56 context.browser = b
57 b.Lock()
58 b.contexts = append(b.contexts, context)
59 b.Unlock()
60 return context, nil
61 }
62
63 func (b *browserImpl) NewPage(options ...BrowserNewContextOptions) (Page, error) {
64 context, err := b.NewContext(options...)
65 if err != nil {
66 return nil, err
67 }
68 page, err := context.NewPage()
69 if err != nil {
70 return nil, err
71 }
72 page.(*pageImpl).ownedContext = context
73 context.(*browserContextImpl).ownedPage = page
74 return page, nil
75 }
76
77 func (b *browserImpl) NewBrowserCDPSession() (CDPSession, error) {
78 channel, err := b.channel.Send("newBrowserCDPSession")
79 if err != nil {
80 return nil, fmt.Errorf("could not send message: %w", err)
81 }
82
83 cdpSession := fromChannel(channel).(*cdpSessionImpl)
84
85 return cdpSession, nil
86 }
87
88 func (b *browserImpl) Contexts() []BrowserContext {
89 b.Lock()
90 defer b.Unlock()
91 return b.contexts
92 }
93
94 func (b *browserImpl) Close() error {
95 _, err := b.channel.Send("close")
96 if err != nil {
97 return fmt.Errorf("could not send message: %w", err)
98 }
99 if b.isConnectedOverWebSocket {
100 return b.connection.Stop()
101 }
102 return nil
103 }
104
105 func (b *browserImpl) Version() string {
106 return b.initializer["version"].(string)
107 }
108
109 func (b *browserImpl) onClose() {
110 b.Lock()
111 if !b.isClosedOrClosing {
112 b.isConnected = false
113 b.isClosedOrClosing = true
114 b.Emit("disconnected")
115 }
116 b.Unlock()
117 }
118
119 func newBrowser(parent *channelOwner, objectType string, guid string, initializer map[string]interface{}) *browserImpl {
120 bt := &browserImpl{
121 isConnected: true,
122 contexts: make([]BrowserContext, 0),
123 }
124 bt.createChannelOwner(bt, parent, objectType, guid, initializer)
125 bt.channel.On("close", bt.onClose)
126 return bt
127 }
128
View as plain text