Skip to content

Commit 08c2b5f

Browse files
committed
v2
1 parent 4148acb commit 08c2b5f

32 files changed

+2748
-2206
lines changed

README.md

Lines changed: 35 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -11,76 +11,65 @@ _Warning_ This is an experimental project, backward compatibility is not guarant
1111
Here is an example of using:
1212

1313
```go
14-
package main
15-
16-
import (
17-
"context"
18-
"log"
19-
"time"
20-
21-
"github.com/ecwid/control"
22-
"github.com/ecwid/control/chrome"
23-
)
24-
2514
func main() {
26-
chromium, err := chrome.Launch(context.TODO(), "--disable-popup-blocking") // you can specify more startup parameters for chrome
27-
if err != nil {
28-
panic(err)
29-
}
30-
defer chromium.Close()
31-
ctrl := control.New(chromium.GetClient())
32-
33-
session, err := ctrl.CreatePageTarget("")
15+
session, cancel, err := control.Take("--no-startup-window")
3416
if err != nil {
3517
panic(err)
3618
}
19+
defer cancel()
3720

38-
var page = session.Page() // main frame
39-
err = page.Navigate("https://surfparadise.ecwid.com/", control.LifecycleIdleNetwork, time.Second*60)
40-
if err != nil {
41-
panic(err)
21+
retrier := retry.Static{
22+
Timeout: 10 * time.Second,
23+
Delay: 500 * time.Millisecond, // delay between attempts
4224
}
4325

44-
items, err := page.QuerySelectorAll(".grid-product__title-inner")
26+
session.Frame.MustNavigate("https://zoid.ecwid.com")
27+
28+
var products []string
29+
err = retry.Func(retrier, func() error {
30+
products = []string{}
31+
return session.Frame.QueryAll(".grid-product__title-inner").Then(func(nl control.NodeList) error {
32+
return nl.Foreach(func(n *control.Node) error {
33+
return n.GetText().Then(func(s string) error {
34+
products = append(products, s)
35+
return nil
36+
})
37+
})
38+
})
39+
})
4540
if err != nil {
4641
panic(err)
4742
}
48-
for _, i := range items {
49-
title, err := i.GetText()
50-
if err != nil {
51-
panic(err)
52-
}
53-
log.Print(title)
43+
44+
// "must way" throws panic on an error
45+
46+
for _, node := range session.Frame.MustQueryAll(".grid-product__title-inner") {
47+
log.Println(node.MustGetText())
5448
}
5549
}
5650
```
5751

5852
You can call any CDP method implemented in protocol package using a session
5953
```go
60-
err = security.SetIgnoreCertificateErrors(sess, security.SetIgnoreCertificateErrorsArgs{
54+
err = security.SetIgnoreCertificateErrors(session, security.SetIgnoreCertificateErrorsArgs{
6155
Ignore: true,
6256
})
6357
```
6458

65-
or even call a custom method
59+
or call a custom unimplemented method
6660
```go
67-
err = sess.Call("Security.setIgnoreCertificateErrors", sendStruct, receiveStruct)
61+
err = session.Call("Security.setIgnoreCertificateErrors", sendStruct, receiveStruct)
6862
```
6963

70-
Subscribe on domain event
64+
Subscribe on the domain event
7165
```go
72-
cancel := sess.Subscribe("Overlay.screenshotRequested", func(e observe.Value) {
73-
v := overlay.ScreenshotRequested{}
74-
_= json.Unmarshal(e.Params, &v)
75-
doSomething(v.Viewport.Height)
66+
future := control.Subscribe(session, "Target.targetCreated", func(t target.TargetCreated) bool {
67+
return t.TargetInfo.Type == "page"
7668
})
77-
defer cancel()
69+
defer future.Cancel()
7870

79-
// Subscribe on all incoming events
80-
sess.Subscribe("*", func(e observe.Value) {
81-
switch e.Method {
82-
case "Overlay.screenshotRequested":
83-
}
84-
})
71+
// do something here ...
8572

86-
```
73+
ctx, cancel := context.WithTimeout(context.TODO(), time.Second*10)
74+
result /* target.TargetCreated */, err := future.Get(ctx)
75+
```

atoms.go

Lines changed: 0 additions & 26 deletions
This file was deleted.

browser.go

Lines changed: 0 additions & 121 deletions
This file was deleted.

cdp/broker.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
package cdp
2+
3+
import (
4+
"sync"
5+
)
6+
7+
var BrokerChannelSize = 50000
8+
9+
type subscriber struct {
10+
sessionID string
11+
channel chan Message
12+
}
13+
14+
type broker struct {
15+
cancel chan struct{}
16+
messages chan Message
17+
sub chan subscriber
18+
unsub chan chan Message
19+
lock *sync.Mutex
20+
}
21+
22+
func makeBroker() broker {
23+
return broker{
24+
cancel: make(chan struct{}),
25+
messages: make(chan Message),
26+
sub: make(chan subscriber),
27+
unsub: make(chan chan Message),
28+
lock: &sync.Mutex{},
29+
}
30+
}
31+
32+
func (b broker) run() {
33+
var value = map[chan Message]subscriber{}
34+
for {
35+
select {
36+
37+
case sub := <-b.sub:
38+
value[sub.channel] = sub
39+
40+
case channel := <-b.unsub:
41+
if _, ok := value[channel]; ok {
42+
delete(value, channel)
43+
close(channel)
44+
}
45+
46+
case <-b.cancel:
47+
for msgCh := range value {
48+
close(msgCh)
49+
}
50+
close(b.sub)
51+
close(b.unsub)
52+
close(b.messages)
53+
return
54+
55+
case message := <-b.messages:
56+
for _, subscriber := range value {
57+
if message.SessionID == "" || subscriber.sessionID == "" || message.SessionID == subscriber.sessionID {
58+
subscriber.channel <- message
59+
}
60+
}
61+
}
62+
}
63+
}
64+
65+
func (b broker) subscribe(sessionID string) chan Message {
66+
b.lock.Lock()
67+
defer b.lock.Unlock()
68+
69+
select {
70+
case <-b.cancel:
71+
return nil
72+
default:
73+
sub := subscriber{
74+
sessionID: sessionID,
75+
channel: make(chan Message, BrokerChannelSize),
76+
}
77+
b.sub <- sub
78+
return sub.channel
79+
}
80+
}
81+
82+
func (b broker) unsubscribe(value chan Message) {
83+
b.lock.Lock()
84+
select {
85+
case <-b.cancel:
86+
default:
87+
b.unsub <- value
88+
}
89+
b.lock.Unlock()
90+
}
91+
92+
func (b broker) publish(msg Message) {
93+
b.messages <- msg
94+
}
95+
96+
func (b broker) Cancel() {
97+
b.lock.Lock()
98+
close(b.cancel)
99+
b.lock.Unlock()
100+
}

0 commit comments

Comments
 (0)