Documentation
¶
Overview ¶
Package cdp for application layer communication with browser.
Example (Customize_cdp_log) ¶
package main
import (
"fmt"
"github.com/headlesslab/wand/lib/cdp"
"github.com/headlesslab/wand/lib/launcher"
"github.com/headlesslab/wand/lib/proto"
"github.com/headlesslab/wand/lib/utils"
)
func main() {
l := launcher.New()
defer l.Cleanup()
ws := cdp.MustConnectWS(l.MustLaunch())
client := cdp.New().
// Here we can customize how to log the requests, responses and events.
// This one reports the browser shutdown only, so that the example's
// output is the same on every run.
Logger(utils.Log(func(args ...interface{}) {
switch v := args[0].(type) {
case *cdp.Request:
if v.Method == "Browser.close" {
fmt.Printf("request: %s\n", v.Method)
}
}
})).
Start(ws)
_ = proto.BrowserClose{}.Call(client)
}
Output: request: Browser.close
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrCtxDestroyed = &Error{
Code: -32000,
Message: "Execution context was destroyed.",
}
ErrCtxDestroyed type. It matches both messages Chrome has used for an evaluation interrupted by a navigation: Chromium 128 reports "Execution context was destroyed." from V8, Chrome 152 "Inspected target navigated or closed" from the DevTools session. ErrCtxNotFound, a stale context id, stays a separate error.
var ErrCtxNotFound = &Error{
Code: -32000,
Message: "Cannot find context with specified id",
}
ErrCtxNotFound type.
var ErrNodeNotFoundAtPos = &Error{
Code: -32000,
Message: "No node found at given location",
}
ErrNodeNotFoundAtPos type.
var ErrNotAttachedToActivePage = &Error{
Code: -32000,
Message: "Not attached to an active page",
}
ErrNotAttachedToActivePage type.
var ErrObjNotFound = &Error{
Code: -32000,
Message: "Could not find object with given id",
}
ErrObjNotFound type.
var ErrSearchSessionNotFound = &Error{
Code: -32000,
Message: "No search session with given id found",
}
ErrSearchSessionNotFound type.
var ErrSessionNotFound = &Error{
Code: -32001,
Message: "Session with given id not found.",
}
ErrSessionNotFound type.
Functions ¶
This section is empty.
Types ¶
type BadHandshakeError ¶
BadHandshakeError type.
func (*BadHandshakeError) Error ¶
func (e *BadHandshakeError) Error() string
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client is a devtools protocol connection instance.
Example ¶
package main
import (
"context"
"fmt"
"path/filepath"
"github.com/headlesslab/lazyjson"
"github.com/headlesslab/wand/lib/cdp"
"github.com/headlesslab/wand/lib/launcher"
"github.com/headlesslab/wand/lib/proto"
"github.com/headlesslab/wand/lib/utils"
)
func main() {
ctx := context.Background()
// launch a browser
l := launcher.New()
defer l.Cleanup()
// create a controller
client := cdp.New().Start(cdp.MustConnectWS(l.MustLaunch()))
go func() {
for range client.Event() {
// you must consume the events
utils.Noop()
}
}()
// A page of this package, so that the example runs with no network.
page, err := filepath.Abs(filepath.FromSlash("fixtures/basic.html"))
utils.E(err)
// Such as call this endpoint on the api doc:
// https://chromedevtools.github.io/devtools-protocol/tot/Page#method-navigate
// This will create a new tab and navigate to the page
res, err := client.Call(ctx, "", "Target.createTarget", map[string]string{
"url": "file://" + page,
})
utils.E(err)
fmt.Println(len(lazyjson.New(res).Get("targetId").Str()))
// close browser by using the proto lib to encode json
_ = proto.BrowserClose{}.Call(client)
}
Output: 32
func MustStartWithURL ¶
MustStartWithURL helper for ConnectURL.
func New ¶
func New() *Client
New creates a cdp connection, all messages from Client.Event must be received or they will block the client.
func StartWithURL ¶
StartWithURL helper to connect to the u with the default websocket lib.
func (*Client) Call ¶
func (cdp *Client) Call(ctx context.Context, sessionID, method string, params interface{}) ([]byte, error)
Call a method and wait for its response. A context that has ended before the call sends nothing and answers with its error. A reply that has arrived by the time the context ends is the call's answer, since the browser has done the work: the reply to Page.close and the detach that ends the page's context arrive together, and a select between the two would take either.
func (*Client) Event ¶
Event returns a channel that will emit browser devtools protocol events. Must be consumed or will block producer.
type CloseError ¶
CloseError is the error Read returns once the peer has sent a close frame (RFC 6455 section 5.5.1): the connection is over, and Code and Reason are what the peer gave for it. Code is 1005 when the frame carried none.
func (*CloseError) Error ¶
func (e *CloseError) Error() string
type Dialer ¶
type Dialer interface {
DialContext(ctx context.Context, network, address string) (net.Conn, error)
}
Dialer interface for WebSocket connection.
type Error ¶
type Error struct {
Code int `json:"code"`
Message string `json:"message"`
Data string `json:"data"`
}
Error of the Response.
type Event ¶
type Event struct {
SessionID string `json:"sessionId,omitempty"`
Method string `json:"method"`
Params json.RawMessage `json:"params,omitempty"`
}
Event from browser.
type Request ¶
type Request struct {
ID int `json:"id"`
SessionID string `json:"sessionId,omitempty"`
Method string `json:"method"`
Params interface{} `json:"params,omitempty"`
}
Request to send to browser.
type Response ¶
type Response struct {
ID int `json:"id"`
Result json.RawMessage `json:"result,omitempty"`
Error *Error `json:"error,omitempty"`
}
Response from browser.
type WebSocket ¶
type WebSocket struct {
// Dialer is usually used for proxy
Dialer Dialer
// contains filtered or unexported fields
}
WebSocket client for chromium. It only implements a subset of WebSocket protocol: text frames in one piece each way, masked with a fixed key, the control frames handled inside Read, no extensions, and the peer's framing taken on trust. Both the Read and Write are thread-safe. Limitation: https://bugs.chromium.org/p/chromium/issues/detail?id=1069431 Ref: https://tools.ietf.org/html/rfc6455
func (*WebSocket) Read ¶
Read a message from browser. Control frames never come back as messages (rod #1187): a ping is answered with a pong carrying its payload, a pong is dropped, and a close frame is answered with a close frame and ends the connection with a CloseError. Chrome sends none of them, other CDP servers and proxies do.
type WebSocketable ¶
type WebSocketable interface {
// Send text message only
Send(data []byte) error
// Read returns text message only
Read() ([]byte, error)
}
WebSocketable enables you to choose the websocket lib you want to use. Such as you can easily wrap gorilla/websocket and use it as the transport layer.
func MustConnectWS ¶
func MustConnectWS(wsURL string) WebSocketable
MustConnectWS helper to make a websocket connection.