Documentation
¶
Overview ¶
Package browserhost manages Chrome processes that browser steps keep alive between step executions: their durable records, reachability probes, and cleanup.
Index ¶
- Constants
- Variables
- func BrowserID(ctx context.Context, cdpURL string) (string, error)
- func BrowserProcessID(ctx context.Context, cdpURL string) (int, error)
- func ChooseFiles(ctx context.Context, cdpURL string, paths []string, wait time.Duration, ...) error
- func CloseBrowser(ctx context.Context, cdpURL string) error
- func DenyDownloads(ctx context.Context, cdpURL string) error
- func Probe(ctx context.Context, cdpURL string) error
- func RecordID(dagRunID, stepName string) string
- func Release(ctx context.Context, store *Store, record Record) error
- func RetireAbandoned(ctx context.Context, store *Store, id string, now time.Time) (bool, error)
- func RunReaper(ctx context.Context, browserDataDir string, resumable ResumableFunc)
- func Sweep(ctx context.Context, store *Store, now time.Time, resumable ResumableFunc) error
- func SweepAll(ctx context.Context, browserDataDir string, now time.Time, ...) error
- func UsesProfile(ctx context.Context, cdpURL, dir string) (bool, error)
- type BlockedRequestWatcher
- type Dialog
- type DialogWatcher
- type Download
- type DownloadWatcher
- type Extension
- type PageResponse
- type PageResponseWatcher
- type Record
- type ResumableFunc
- type Slot
- type State
- type Store
- func (s *Store) Delete(id string) error
- func (s *Store) List() ([]Record, error)
- func (s *Store) Load(id string) (Record, error)
- func (s *Store) Purge(id string) error
- func (s *Store) Save(record Record) error
- func (s *Store) SessionLock(id string) dirlock.DirLock
- func (s *Store) WorkDir(id string) string
- type Version
Constants ¶
const ( // AgentProvider identifies browser steps in agent sessions. AgentProvider = "browser" // DataDirName is the directory under the Dagu data directory that holds // browser state. DataDirName = "browser" )
const BotCheckCloudflare = "cloudflare"
BotCheckCloudflare names Cloudflare's check of whether a browser is run by a person, which a site behind Cloudflare answers with in place of the page.
const ( // ReapInterval is how often a long-lived process sweeps browser sessions. ReapInterval = time.Minute )
const SessionRetention = 24 * time.Hour
SessionRetention is how long a browser session's history is kept after its browser closed on its own.
const StagehandExtensionName = "Stagehand Runtime"
StagehandExtensionName is the name the Stagehand runtime extension reports to Chrome.
Variables ¶
var ErrExtensionNotFound = errors.New("stagehand runtime extension is not loaded")
ErrExtensionNotFound reports that the connected browser has no enabled Stagehand runtime extension.
var ErrNoFileChooser = errors.New("no file picker opened")
ErrNoFileChooser reports that no file picker opened.
var ErrSingleFileChooser = errors.New("the file picker takes one file")
ErrSingleFileChooser reports a file picker that takes one file when it was to be given several.
var ErrUnreachable = errors.New("browser is not running")
ErrUnreachable reports that nothing accepts connections at a browser's DevTools address, so the browser is no longer running.
Functions ¶
func BrowserID ¶
BrowserID identifies the browser answering at cdpURL. A browser started later on the same address has another identity. The error wraps ErrUnreachable when nothing accepts connections there.
func BrowserProcessID ¶
BrowserProcessID returns the process ID of the browser at cdpURL.
func ChooseFiles ¶
func ChooseFiles(ctx context.Context, cdpURL string, paths []string, wait time.Duration, open func(context.Context) error) error
ChooseFiles gives the files at paths, which must be absolute, to the first file picker a page or frame of the browser at cdpURL opens while open runs or within wait after it returns. Pickers are intercepted, so none is shown. It returns ErrNoFileChooser when no picker opens, and ErrSingleFileChooser, giving nothing, when the picker takes one file and paths holds several.
func CloseBrowser ¶
CloseBrowser asks the browser at cdpURL to exit. A browser that no longer answers is treated as already closed.
func DenyDownloads ¶
DenyDownloads makes the browser at cdpURL refuse every download.
func Release ¶
Release closes the browser described by record, deletes the files it owns, and removes the record.
func RetireAbandoned ¶
RetireAbandoned retires the browser session id when nothing will use its browser again, unless one of its commands holds it. It reports whether the session was retired.
func RunReaper ¶
func RunReaper(ctx context.Context, browserDataDir string, resumable ResumableFunc)
RunReaper sweeps the browsers steps keep and the browser sessions under the browser data directory until ctx is cancelled.
func Sweep ¶
Sweep closes browsers that no step can resume and removes their records: running sessions whose owner process is gone, detached sessions past their deadline, detached sessions whose step can no longer resume, and browsers whose write gate is gone.
Types ¶
type BlockedRequestWatcher ¶ added in v2.17.2
type BlockedRequestWatcher struct {
// contains filtered or unexported fields
}
BlockedRequestWatcher counts the requests of a browser's pages and frames that a DevTools client blocked, by host.
func WatchBlockedRequests ¶ added in v2.17.2
func WatchBlockedRequests(ctx context.Context, cdpURL string) (*BlockedRequestWatcher, error)
WatchBlockedRequests counts blocked requests in the pages of the browser at cdpURL, including pages and frames opened later, until the watcher is closed.
func (*BlockedRequestWatcher) Close ¶ added in v2.17.2
func (w *BlockedRequestWatcher) Close() error
Close stops watching.
func (*BlockedRequestWatcher) Take ¶ added in v2.17.2
func (w *BlockedRequestWatcher) Take() (map[string]int, error)
Take returns the number of requests blocked per host since the previous call, or nil when none were. Its error reports that the watcher lost its connection and counts no further requests.
type Dialog ¶
type Dialog struct {
// Type is alert, confirm, prompt, or beforeunload.
Type string
Message string
}
Dialog is a JavaScript dialog a page opened and the watcher accepted.
type DialogWatcher ¶
type DialogWatcher struct {
// contains filtered or unexported fields
}
DialogWatcher accepts the JavaScript dialogs a browser's pages open. An open dialog blocks its page until it is answered.
func WatchDialogs ¶
func WatchDialogs(ctx context.Context, cdpURL string) (*DialogWatcher, error)
WatchDialogs accepts every dialog in the pages of the browser at cdpURL, including pages opened later, until the watcher is closed. A prompt is answered with its default text.
func (*DialogWatcher) Close ¶
func (w *DialogWatcher) Close() error
Close stops watching. Dialogs opened afterwards stay open.
func (*DialogWatcher) Take ¶
func (w *DialogWatcher) Take() []Dialog
Take returns the dialogs accepted since the previous call.
type DownloadWatcher ¶
type DownloadWatcher struct {
// contains filtered or unexported fields
}
DownloadWatcher saves the browser's downloads into a directory and tracks which are still in progress.
func WatchDownloads ¶
func WatchDownloads(ctx context.Context, cdpURL, dir string) (*DownloadWatcher, error)
WatchDownloads saves downloads from the browser at cdpURL into dir until the watcher is closed.
func (*DownloadWatcher) Close ¶
func (w *DownloadWatcher) Close() error
Close stops watching. Downloads still in progress are left to the browser.
func (*DownloadWatcher) Wait ¶
func (w *DownloadWatcher) Wait(ctx context.Context, grace, timeout time.Duration) ([]Download, error)
Wait returns the downloads completed since the previous call. It first allows grace for a download to begin, then waits until none is in progress. It fails when a download was canceled or is still running when timeout passes.
type Extension ¶
type Extension struct {
ID string `json:"id"`
Name string `json:"name"`
Path string `json:"path"`
Enabled bool `json:"enabled"`
}
Extension describes an unpacked extension loaded into a browser.
type PageResponse ¶
type PageResponse struct {
Status int
// BotCheck names the check the site answered with in place of the page,
// such as BotCheckCloudflare, or is empty.
BotCheck string
}
PageResponse is how a site answered the document a page loaded.
type PageResponseWatcher ¶
type PageResponseWatcher struct {
// contains filtered or unexported fields
}
PageResponseWatcher keeps how sites answered the documents a browser's pages loaded, by host.
func WatchPageResponses ¶
func WatchPageResponses(ctx context.Context, cdpURL string) (*PageResponseWatcher, error)
WatchPageResponses keeps how sites answer the documents the pages of the browser at cdpURL load, including pages opened later, until the watcher is closed. A document a frame loads is not a page's.
func (*PageResponseWatcher) Close ¶
func (w *PageResponseWatcher) Close() error
Close stops watching.
func (*PageResponseWatcher) Response ¶
func (w *PageResponseWatcher) Response(host string) (PageResponse, bool)
Response returns how host last answered a document a page loaded.
type Record ¶
type Record struct {
ID string `json:"id"`
DAGName string `json:"dagName"`
DAGRunID string `json:"dagRunId"`
StepName string `json:"stepName"`
// Generation is the agent-session generation that owns the browser.
Generation int `json:"generation"`
State State `json:"state"`
// Deadline bounds how long a detached browser waits to be resumed.
Deadline time.Time `json:"deadline,omitzero"`
CDPURL string `json:"cdpUrl"`
ExtensionID string `json:"extensionId,omitempty"`
ExtensionDir string `json:"extensionDir,omitempty"`
UserDataDir string `json:"userDataDir,omitempty"`
OwnsUserDataDir bool `json:"ownsUserDataDir,omitempty"`
Profile string `json:"profile,omitempty"`
DownloadsDir string `json:"downloadsDir,omitempty"`
// BrowserPID and BrowserStartedAt identify the browser process, so it can
// be ended when it no longer answers on its DevTools address.
BrowserPID int `json:"browserPid,omitempty"`
BrowserStartedAt int64 `json:"browserStartedAt,omitempty"`
// CertProxyURL locates the proxy presenting the browser's client
// certificates, which runs while the browser does; CertProxyPID and
// CertProxyStartedAt identify its process, so it can be ended with the
// browser.
CertProxyURL string `json:"certProxyUrl,omitempty"`
CertProxyPID int `json:"certProxyPid,omitempty"`
CertProxyStartedAt int64 `json:"certProxyStartedAt,omitempty"`
// WriteGateURL locates the gate deciding the browser's writes;
// WriteGatePID and WriteGateStartedAt identify its process. A browser
// whose gate is gone sends writes nothing decides, so it is closed.
// WriteGateSeq is the last of the gate's events reported.
WriteGateURL string `json:"writeGateUrl,omitempty"`
WriteGatePID int `json:"writeGatePid,omitempty"`
WriteGateStartedAt int64 `json:"writeGateStartedAt,omitempty"`
WriteGateSeq int64 `json:"writeGateSeq,omitempty"`
// OwnerPID and OwnerStartedAt identify the process driving a running
// browser, so a crashed owner can be detected even after PID reuse.
OwnerPID int `json:"ownerPid,omitempty"`
OwnerStartedAt int64 `json:"ownerStartedAt,omitempty"`
// Cursor is the index of the next operation a resumed step runs.
Cursor int `json:"cursor"`
// Outputs holds values extracted before the step detached.
Outputs map[string]any `json:"outputs,omitempty"`
// ReplayPending and ReplayUsed carry the step's replay cache changes
// across the wait: the act operations it recorded or dropped, applied
// only if the step succeeds, and the recordings it replayed, as they
// were read.
ReplayPending map[string]json.RawMessage `json:"replayPending,omitempty"`
ReplayUsed map[string]json.RawMessage `json:"replayUsed,omitempty"`
// WorkDir holds the files a browser session owns, such as its
// screenshots and downloads. It is removed with the browser.
WorkDir string `json:"workDir,omitempty"`
// Interactive is a browser session's own state, which the browser
// runtime defines.
Interactive json.RawMessage `json:"interactive,omitempty"`
}
Record is the durable description of one browser session kept by a step.
type ResumableFunc ¶
ResumableFunc reports whether a detached session still belongs to a step that can resume it. A nil ResumableFunc treats every unexpired session as resumable.
type Slot ¶
type Slot struct {
// contains filtered or unexported fields
}
Slot is a place for one open browser among the few a host allows. Until the browser starts, the process opening it holds the slot; after Hold, the browser process does, so a browser kept open after its step still counts until it exits.
func TakeSlot ¶
TakeSlot reserves a place for one more browser under browserDir, waiting while limit browsers are open there. A limit below one sets no limit and returns a nil Slot, whose methods do nothing. waiting runs once, when the browser first has to wait.
type State ¶
type State string
State describes who currently holds a browser session.
const ( // StateRunning means a step execution, or a browser session command, is // driving the browser. StateRunning State = "running" // StateDetached means the browser waits for a step to resume it. StateDetached State = "detached" // StateInteractive means a browser session's browser waits for the // session's next command. StateInteractive State = "interactive" // StateEnded means a browser session's browser is closed. Its record // keeps the session's history until its deadline. StateEnded State = "ended" )
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store persists browser session records as private files.
func NewInteractiveStore ¶
NewInteractiveStore returns the store of browser sessions, rooted under the browser data directory. It is kept apart from the steps' store, whose sweeps release records in states they do not know.
func NewStore ¶
NewStore returns the store of the browsers steps keep, rooted under the browser data directory.
func (*Store) SessionLock ¶
SessionLock returns the lock held by whatever uses the browser of the session id: one of its commands, or a sweep closing it.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package certproxy presents TLS client certificates on behalf of a browser.
|
Package certproxy presents TLS client certificates on behalf of a browser. |
|
Package writegate decides every write a browser sends: it lets the write through, or blocks it and keeps what it would have sent.
|
Package writegate decides every write a browser sends: it lets the write through, or blocks it and keeps what it would have sent. |