autogcd

package module
v0.0.0-...-8039288 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 8, 2018 License: MIT Imports: 14 Imported by: 1

README

Automating Google Chrome Debugger (autogcd)

Autogcd is a wrapper around the gcd library to enable automation of Google Chrome. It some what mimics the functionality offered by WebDriver but allows more low level access via the debugger service.

Changelog

See the CHANGELOG.

Dependencies

autogcd requires gcd, gcdapi and gcdmessage packages.

The API

Autogcd is comprised of four components:

  • autogcd.go - The wrapper around gcd.Gcd.
  • settings.go - For managing startup of autogcd.
  • tab.go - Individual chrome tabs
  • element.go - Elements that make up the page (includes iframes, #documents as well)

API Documentation

Documentation

Usage

See the examples or the various testcases.

Notes

The chrome debugger service uses internal nodeIds for identifying unique elements/nodes in the DOM. In most cases you will not need to use this identifier directly, however if you plan on calling gcdapi related features you will probably need it. The most common example of when you'll need them is for getting access to a nested #document element inside of an iframe. To run query selectors on nested documents, the nodeId of the iframe #document must be known.

Elements

The Chrome Debugger by nature is far more asynchronous than WebDriver. It is possible to work with elements even though the debugger has not yet notified us of their existence. To deal with this, Elements can be in multiple states; Ready, NotReady or Invalid. Only certain features are available when an Element is in a Ready state. If an Element is Invalid, it should no longer be used and references to it should be discarded.

Frames

If you need to search elements (by id or by a selector) of a frame's #document, you'll need to get an Element reference that is the iframe's #document. This can be done by doing a tab.GetElementsBySelector("iframe"), iterating over the results and calling element.GetFrameDocumentNodeId(). This will return the internal document node id which you can then pass to tab.GetDocumentElementsBySelector(iframeDocNodeId, "#whatever").

Windows

The major limitation of using the Google Chrome Remote Debugger is when working with windows. Since each tab must have the debugger enabled, calls to window.open will open a new window prior to us being able to attach a debugger. To get around this, you'll need to get a list of tabs AutoGcd.GetAllTabs(), then call AutoGcd.RefreshTabList() which will connect each tab to an autogcd.Tab. You'd then need to reload the tab get begin working with it.

Stability & Waiting

There are a few ways you can test for stability or if an Element is ready. Element.WaitForReady() will not return until the debugger service has populated the element's information. If you are waiting for a page to stabilize, you can use the tab.WaitStable() method which won't return until it hasn't seen any DOM nodes being added/removed for a configurable (tab.SetStabilityTime(...)) amount of time.

Finally, you can use the tab.WaitFor method, which takes a ConditionalFunc type and repeatedly calls it until it returns true, or times out.

For example/simple ConditionalFuncs see the conditionals.go source. Of course you can use whatever you want as long as it matches the ConditionalFunc signature.

Navigation Errors

Unlike WebDriver, we can determine if navigation fails, *at least in chromium. After tab.Navigate(url), calling tab.DidNavigationFail() will return a true/false return value along with a string of the failure type if one did occur. It is strongly recommended you pass the following flags: --test-type, --ignore-certificate-errors on start up of autogcd if you wish to ignore certificate errors.

* This does not appear to work in chrome in windows or osx.

Input

Only a limited set of input functions have been implemented. Clicking and sending keys. You can use Element.SendKeys() or send the keys to whatever is focused by using Tab.SendKeys(). Only Enter ("\n"), Tab ("\t") and Backspace ("\b") were implemented, to use them, simply add them to your SendKeys argument Element.SendKeys("enter text hit enter\n") where \n will cause the enter key to be pressed.

Listeners

Four listener functions have been implemented, GetConsoleMessages, GetNetworkTraffic, GetStorageEvents, GetDOMChanges.

GetConsoleMessages

Pass in a ConsoleMessageFunc handler to begin receiving console messages from the tab. Use StopConsoleMessages to stop receiving them.

GetNetworkTraffic

Pass in either a NetworkRequestHandlerFunc, NetworkResponseHandlerFunc or NetworkFinishedHandlerFunc handler (or all three) to receive network traffic events. NetworkFinishedHandler should be used to signal your application that it's safe to get the response body of the request. While calling GetResponseBody may work from NetworkResponseHandlerFunc, it will in many cases fail as the debugger service isn't ready to return the data yet. Use StopNetworkTraffic to stop receiving them.

GetStorageEvents

Pass in a StorageFunc handler to recieve cleared, removed, added and updated storage events. Use StopStorageEvents to stop receiving them.

GetDOMChanges

Pass in a DomChangeHandlerFunc to receive various dom change events. Call it with a nil handler to stop receiving them.

Calling gcd directly

AutoGcd has not implemented all of the Google Chrome Debugger protocol methods and features because I don't see any point in wrapping a lot of them. However, you are not out of luck, all gcd components are bound to each Tab object. I'd suggest reviewing the gcdapi package if there is a particular component you wish to use. All components are bound to the Tab so it should be as simple as calling Tab.{component}.{method}.

Overriding gcd

Take a look at api_overrides.go for an example of overriding gcd methods. In some cases the protocol.json specification is incorrect, in which case you may need to override specific methods. Since I designed the packages to use an intermediary gcdmessage package for requests and responses you're completely free to override anything necessary.

Internals

I'll admit, I do not fully like the design of the Elements. I have to track state updates very carefully and I chose to use sync.RWMutex locks. I couldn't see an obvious method of using channels to synchronize access to the DOMNodes. I'm very open to new architectures/designs if someone has a better method of keeping Element objects up to date as Chrome notifies autogcd of new values.

As mentioned in the Elements section, Chrome Debugger Protocol is fully asynchronous. The debugger is only notified of elements when the page first loads (and even then only a few of the top level elements). It also occurs when an element has been modified, or when you request them with DOM.requestChildNodes. Autogcd tries to manage all of this for you, but there may be a case where you search for elements that chrome has not notified the debugger client yet. In this case the Element will be, in autogcd terminology, NotReady. This means you can sort of work with it because we know its nodeId but we may not know much else (even what type of node it is). Internally almost all chrome debugger methods take nodeIds.

This package has been heavily tested in the real world. It was used to scan the top 1 million websites from Alexa. I found numerous goroutine leaks that have been subsequently fixed. After running my scan I no longer see any leaks. It should also be completely safe to kill the browser at any point and not have any runaway go routines since I have channels waiting for close messages at any point a channel is sending or receiving.

Reporting Bugs & Requesting Features

Found a bug? Great! Tell me what version of chrome/chromium you are using and how to reproduce and I'll get to it when I can. Keep in mind this is a side project for me. Same goes for new features. Patches obviously welcome.

License

The MIT License (MIT)

Copyright (c) 2016 isaac dawson

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Documentation

Overview

Autogcd - An automation interface for https://github.com/wirepair/gcd. Contains most functionality found in WebDriver and extends it to offer more low level features. This library was built due to WebDriver/Chromedriver also using the debugger service. Since it is not possible to attach to a Page's debugger twice, automating a custom extension with WebDriver turned out to not be possible.

The Chrome Debugger by nature is far more asynchronous than WebDriver. It is possible to work with elements even though the debugger has not yet notified us of their existence. To deal with this, Elements can be in multiple states; Ready, NotReady or Invalid. Only certain features are available when an Element is in a Ready state. If an Element is Invalid, it should no longer be used and references to it should be discarded.

Dealing with frames is also different than WebDriver. There is no SwitchToFrame, you simply pass in the frameId to certain methods that require it. You can lookup the these frame documents by finding frame/iframe Elements and requesting the document NodeId reference via the GetFrameDocumentNodeId method.

Lastly, dealing with windows... doesn't really work since they open a new tab. A possible solution would be to monitor the list of tabs by calling AutoGcd.RefreshTabs() and doing a diff of known versus new. You could then do a Tab.Reload() to refresh the page. It is recommended that you clear cache on the tab first so it is possible to trap the various network events. There are other dirty hacks you could do as well, such as injecting script to override window.open, or rewriting links etc.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type AutoGcd

type AutoGcd struct {
	// contains filtered or unexported fields
}

func NewAutoGcd

func NewAutoGcd(settings *Settings) *AutoGcd

Creates a new AutoGcd based off the provided settings.

func (*AutoGcd) ActivateTab

func (auto *AutoGcd) ActivateTab(tab *Tab) error

Activate the tab in the chrome UI

func (*AutoGcd) ActivateTabById

func (auto *AutoGcd) ActivateTabById(id string) error

Activate the tab in the chrome UI, by tab id

func (*AutoGcd) CloseTab

func (auto *AutoGcd) CloseTab(tab *Tab) error

Closes the provided tab.

func (*AutoGcd) CloseTabById

func (auto *AutoGcd) CloseTabById(id string) error

Closes a tab based off the tab id.

func (*AutoGcd) GetAllTabs

func (auto *AutoGcd) GetAllTabs() map[string]*Tab

Returns a safe copy of tabs

func (*AutoGcd) GetChromeRevision

func (auto *AutoGcd) GetChromeRevision() string

func (*AutoGcd) GetTab

func (auto *AutoGcd) GetTab() (*Tab, error)

Returns the first "visual" tab.

func (*AutoGcd) NewTab

func (auto *AutoGcd) NewTab() (*Tab, error)

Creates a new tab

func (*AutoGcd) RefreshTabList

func (auto *AutoGcd) RefreshTabList() (map[string]*Tab, error)

Refreshs our internal list of tabs and return all tabs

func (*AutoGcd) SetTerminationHandler

func (auto *AutoGcd) SetTerminationHandler(handler gcd.TerminatedHandler)

Allow callers to handle chrome terminating.

func (*AutoGcd) Shutdown

func (auto *AutoGcd) Shutdown() error

Closes all tabs and shuts down the browser.

func (*AutoGcd) Start

func (auto *AutoGcd) Start() error

Starts Google Chrome with debugging enabled.

type ChangeEventType

type ChangeEventType uint16

Document/Node change event types

const (
	DocumentUpdatedEvent        ChangeEventType = 0x0
	SetChildNodesEvent          ChangeEventType = 0x1
	AttributeModifiedEvent      ChangeEventType = 0x2
	AttributeRemovedEvent       ChangeEventType = 0x3
	InlineStyleInvalidatedEvent ChangeEventType = 0x4
	CharacterDataModifiedEvent  ChangeEventType = 0x5
	ChildNodeCountUpdatedEvent  ChangeEventType = 0x6
	ChildNodeInsertedEvent      ChangeEventType = 0x7
	ChildNodeRemovedEvent       ChangeEventType = 0x8
)

func (ChangeEventType) String

func (evt ChangeEventType) String() string

type ConditionalFunc

type ConditionalFunc func(tab *Tab) bool

ConditionalFunc function to iteratively call until returns without error

func ElementAttributeEquals

func ElementAttributeEquals(tab *Tab, element *Element, name, value string) ConditionalFunc

Returns true when the element's attribute of name equals value.

func ElementByIdReady

func ElementByIdReady(tab *Tab, elementAttributeId string) ConditionalFunc

Returns true when the element exists and is ready

func ElementsBySelectorNotEmpty

func ElementsBySelectorNotEmpty(tab *Tab, elementSelector string) ConditionalFunc

Returns true when a selector returns a valid list of elements.

func TitleContains

func TitleContains(tab *Tab, searchTitle string) ConditionalFunc

Returns true if the searchTitle is contained within the page title.

func TitleEquals

func TitleEquals(tab *Tab, equalsTitle string) ConditionalFunc

Returns true when the page title equals the provided equalsTitle

func UrlContains

func UrlContains(tab *Tab, containsUrl string) ConditionalFunc

Returns true when the current url contains the containsUrl

func UrlEquals

func UrlEquals(tab *Tab, equalsUrl string) ConditionalFunc

Returns true when the current url equals the equalsUrl

type ConsoleMessageFunc

type ConsoleMessageFunc func(tab *Tab, message *gcdapi.ConsoleConsoleMessage)

ConsoleMessageFunc function for handling console messages

type DomChangeHandlerFunc

type DomChangeHandlerFunc func(tab *Tab, change *NodeChangeEvent)

DomChangeHandlerFunc function to listen for DOM Node Change Events

type Element

type Element struct {
	// contains filtered or unexported fields
}

An abstraction over a DOM element, it can be in three modes NotReady - it's data has not been returned to us by the debugger yet. Ready - the debugger has given us the DOMNode reference. Invalidated - The Element has been destroyed. Certain actions require that the Element be populated (getting nodename/type) If you need this information, wait for IsReady() to return true

func (*Element) Clear

func (e *Element) Clear() error

Works like WebDriver's clear(), simply sets the attribute value for input or clears the value for textarea. This element must be ready so we can properly read the nodeName value.

func (*Element) Click

func (e *Element) Click() error

Clicks the center of the element.

func (*Element) Dimensions

func (e *Element) Dimensions() ([]float64, error)

Returns the dimensions of the element.

func (*Element) DoubleClick

func (e *Element) DoubleClick() error

Double clicks the center of the element.

func (*Element) Focus

func (e *Element) Focus() error

Focus on the element.

func (*Element) FrameId

func (e *Element) FrameId() (string, error)

If this is a #document, returns the underlying chrome frameId.

func (*Element) GetAttribute

func (e *Element) GetAttribute(name string) string

Gets a single attribute by name, returns empty string if it does not exist or is empty.

func (*Element) GetAttributes

func (e *Element) GetAttributes() (map[string]string, error)

Get attributes of the node returning a map of name,value pairs.

func (*Element) GetCharacterData

func (e *Element) GetCharacterData() (string, error)

Returns the character data if the element is in a ready state.

func (*Element) GetChildNodeIds

func (e *Element) GetChildNodeIds() ([]int, error)

Get child node ids, returns nil if node is not ready

func (*Element) GetComputedCssStyle

func (e *Element) GetComputedCssStyle() (map[string]string, error)

Returns all of the computed css styles in form of name value map.

func (*Element) GetCssInlineStyleText

func (e *Element) GetCssInlineStyleText() (string, string, error)

Returns the CSS Style Text of the element, returns the inline style first and the attribute style second, or error.

func (*Element) GetDebuggerDOMNode

func (e *Element) GetDebuggerDOMNode() (*gcdapi.DOMNode, error)

Returns the underlying DOMNode for this element. Note this is potentially unsafe to access as we give up the ability to lock.

func (*Element) GetEventListeners

func (e *Element) GetEventListeners() ([]*gcdapi.DOMDebuggerEventListener, error)

Returns event listeners for the element, both static and dynamically bound.

func (*Element) GetFrameDocumentNodeId

func (e *Element) GetFrameDocumentNodeId() (int, error)

If this element is a frame or iframe, return the ContentDocument node id

func (*Element) GetNodeType

func (e *Element) GetNodeType() (int, error)

Returns the node type if the element is in a ready state.

func (*Element) GetSource

func (e *Element) GetSource() (string, error)

Returns the outer html of the element.

func (*Element) GetTagName

func (e *Element) GetTagName() (string, error)

Returns the tag name (input, div etc) if the element is in a ready state.

func (*Element) HasAttribute

func (e *Element) HasAttribute(name string) bool

Similar to above, but works for boolean properties (checked, async etc) Returns true if the attribute is set in our known list of attributes for this element.

func (*Element) IsDocument

func (e *Element) IsDocument() (bool, error)

Is this Element a #document?

func (*Element) IsEnabled

func (e *Element) IsEnabled() (bool, error)

Returns true if the node is enabled, only makes sense for form controls. Element must be in a ready state.

func (*Element) IsInvalid

func (e *Element) IsInvalid() bool

Has the debugger invalidated (removed) the element from the DOM?

func (*Element) IsReady

func (e *Element) IsReady() bool

Has the Chrome Debugger notified us of this Elements data yet?

func (*Element) IsReadyInvalid

func (e *Element) IsReadyInvalid() bool

Has Chrome notified us, but the element is invalid?

func (*Element) IsSelected

func (e *Element) IsSelected() (bool, error)

Simulate WebDrivers checked propertyname check

func (*Element) MouseOver

func (e *Element) MouseOver() error

moves the mouse over the center of the element.

func (*Element) NodeId

func (e *Element) NodeId() int

Returns the underlying chrome debugger node id of this Element

func (*Element) SendKeys

func (e *Element) SendKeys(text string) error

SendKeys - sends each individual character after focusing (clicking) on the element. Extremely basic, doesn't take into account most/all system keys except enter, tab or backspace.

func (*Element) SetAttributeValue

func (e *Element) SetAttributeValue(name, value string) error

SetAttributeValue sets an element's attribute with name to value.

func (*Element) String

func (e *Element) String() string

Gnarly output mode activated

func (*Element) WaitForReady

func (e *Element) WaitForReady() error

If we are ready, just return, if we are not, wait for the readyGate to be closed or for the timeout timer to fired.

type ElementHasNoChildrenErr

type ElementHasNoChildrenErr struct {
}

The element has no children

func (*ElementHasNoChildrenErr) Error

func (e *ElementHasNoChildrenErr) Error() string

type ElementNotFoundErr

type ElementNotFoundErr struct {
	Message string
}

ElementNotFoundErr when we are unable to find an element/nodeId

func (*ElementNotFoundErr) Error

func (e *ElementNotFoundErr) Error() string

type ElementNotReadyErr

type ElementNotReadyErr struct {
}

When we have an element that has not been populated with data yet.

func (*ElementNotReadyErr) Error

func (e *ElementNotReadyErr) Error() string

type GcdResponseFunc

type GcdResponseFunc func(target *gcd.ChromeTarget, payload []byte)

GcdResponseFunc internal response function type

type IncorrectElementTypeErr

type IncorrectElementTypeErr struct {
	NodeName     string
	ExpectedName string
}

An attempt was made to execute a method for which the element type is incorrect

func (*IncorrectElementTypeErr) Error

func (e *IncorrectElementTypeErr) Error() string

type InvalidDimensionsErr

type InvalidDimensionsErr struct {
	Message string
}

When the dimensions of an element are incorrect to calculate the centroid

func (*InvalidDimensionsErr) Error

func (e *InvalidDimensionsErr) Error() string

type InvalidElementErr

type InvalidElementErr struct {
}

The element has been removed from the DOM

func (*InvalidElementErr) Error

func (e *InvalidElementErr) Error() string

type InvalidNavigationErr

type InvalidNavigationErr struct {
	Message string
}

InvalidNavigationErr when unable to navigate Forward or Back

func (*InvalidNavigationErr) Error

func (e *InvalidNavigationErr) Error() string

type InvalidTabErr

type InvalidTabErr struct {
	Message string
}

InvalidTabErr when we are unable to access a tab

func (*InvalidTabErr) Error

func (e *InvalidTabErr) Error() string

type NetworkFinishedHandlerFunc

type NetworkFinishedHandlerFunc func(tab *Tab, requestId string, dataLength, timeStamp float64)

NetworkFinishedHandlerFunc function for handling network finished, meaning it's safe to call Network.GetResponseBody

type NetworkRequest

type NetworkRequest struct {
	RequestId        string                   // Internal chrome request id
	FrameId          string                   // frame that the request went out on
	LoaderId         string                   // internal chrome loader id
	DocumentURL      string                   // url of the frame
	Request          *gcdapi.NetworkRequest   // underlying Request object
	Timestamp        float64                  // time the request was dispatched
	Initiator        *gcdapi.NetworkInitiator // who initiated the request
	RedirectResponse *gcdapi.NetworkResponse  // non-nil if it was a redirect
	Type             string                   // Document, Stylesheet, Image, Media, Font, Script, TextTrack, XHR, Fetch, EventSource, WebSocket, Other
}

Outbound network requests

type NetworkRequestHandlerFunc

type NetworkRequestHandlerFunc func(tab *Tab, request *NetworkRequest)

NetworkRequestHandlerFunc function for handling network requests

type NetworkResponse

type NetworkResponse struct {
	RequestId string                  // Internal chrome request id
	FrameId   string                  // frame that the request went out on
	LoaderId  string                  // internal chrome loader id
	Response  *gcdapi.NetworkResponse // underlying Response object
	Timestamp float64                 // time the request was received
	Type      string                  // Document, Stylesheet, Image, Media, Font, Script, TextTrack, XHR, Fetch, EventSource, WebSocket, Other
}

Inbound network responses

type NetworkResponseHandlerFunc

type NetworkResponseHandlerFunc func(tab *Tab, response *NetworkResponse)

NetworkResponseHandlerFunc function for handling network responses

type NodeChangeEvent

type NodeChangeEvent struct {
	EventType      ChangeEventType   // the type of node change event
	NodeId         int               // nodeid of change
	NodeIds        []int             // nodeid of changes for inlinestyleinvalidated
	ChildNodeCount int               // updated childnodecount event
	Nodes          []*gcdapi.DOMNode // Child nodes array. for setChildNodesEvent
	Node           *gcdapi.DOMNode   // node for child node inserted event
	Name           string            // attribute name
	Value          string            // attribute value
	CharacterData  string            // new text value for characterDataModified events
	ParentNodeId   int               // node id for setChildNodesEvent, childNodeInsertedEvent and childNodeRemovedEvent
	PreviousNodeId int               // previous node id for childNodeInsertedEvent

}

For handling DOM updating nodes

type NodeType

type NodeType uint8

Common node types

const (
	ELEMENT_NODE                NodeType = 0x1
	TEXT_NODE                   NodeType = 0x3
	PROCESSING_INSTRUCTION_NODE NodeType = 0x7
	COMMENT_NODE                NodeType = 0x8
	DOCUMENT_NODE               NodeType = 0x9
	DOCUMENT_TYPE_NODE          NodeType = 0x10
	DOCUMENT_FRAGMENT_NODE      NodeType = 0x11
)

type PromptHandlerFunc

type PromptHandlerFunc func(tab *Tab, message, promptType string)

PromptHandlerFunc function to handle javascript dialog prompts as they occur, pass to SetJavaScriptPromptHandler Internally this should call tab.Page.HandleJavaScriptDialog(accept bool, promptText string)

type ScriptEvaluationErr

type ScriptEvaluationErr struct {
	Message          string
	ExceptionText    string
	ExceptionDetails *gcdapi.RuntimeExceptionDetails
}

ScriptEvaluationErr returned when an injected script caused an error

func (*ScriptEvaluationErr) Error

func (e *ScriptEvaluationErr) Error() string

type Settings

type Settings struct {
	// contains filtered or unexported fields
}

func NewSettings

func NewSettings(chromePath, userDir string) *Settings

Creates a new settings object to start Chrome and enable remote debugging

func (*Settings) AddEnvironmentVars

func (s *Settings) AddEnvironmentVars(env []string)

func (*Settings) AddExtension

func (s *Settings) AddExtension(paths []string)

Adds a custom extension to launch with chrome. Note this extension MAY NOT USE the chrome.debugger API since you can not attach debuggers to a Tab twice.

func (*Settings) AddStartupFlags

func (s *Settings) AddStartupFlags(flags []string)

Adds custom flags when starting the chrome process

func (*Settings) RemoveUserDir

func (s *Settings) RemoveUserDir(shouldRemove bool)

On Shutdown, deletes the userDir and files if true.

func (*Settings) SetChromeHost

func (s *Settings) SetChromeHost(host string)

Can really only be localhost, but this may change in the future so support it anyways.

func (*Settings) SetDebuggerPort

func (s *Settings) SetDebuggerPort(chromePort string)

Sets the chrome debugger port.

func (*Settings) SetInstance

func (s *Settings) SetInstance(host, port string)

Set a instance to connect to other than start a new process

func (*Settings) SetStartTimeout

func (s *Settings) SetStartTimeout(timeout time.Duration)

How long to wait for chrome to startup and allow us to connect.

type StorageEvent

type StorageEvent struct {
	IsLocalStorage bool   // if true, local storage, false session storage
	SecurityOrigin string // origin that this event occurred on
	Key            string // storage key
	NewValue       string // new storage value
	OldValue       string // old storage value
}

type StorageEventType

type StorageEventType uint16

For storage related events.

type StorageFunc

type StorageFunc func(tab *Tab, eventType string, eventDetails *StorageEvent)

StorageFunc function for ListenStorageEvents returns the eventType of cleared, updated, removed or added.

type Tab

type Tab struct {
	*gcd.ChromeTarget // underlying chrometarget
	// contains filtered or unexported fields
}

Tab object for driving a specific tab and gathering elements.

func (*Tab) Back

func (t *Tab) Back() error

Looks up the previous navigation entry from the history and navigates to it. Returns error if we could not find the previous entry or navigation failed

func (*Tab) BackEntry

func (t *Tab) BackEntry() (*gcdapi.PageNavigationEntry, error)

Returns the previous entry in our navigation history for this tab.

func (*Tab) Click

func (t *Tab) Click(x, y float64) error

Issues a left button mousePressed then mouseReleased on the x, y coords provided.

func (*Tab) Debug

func (t *Tab) Debug(enabled bool)

Debug enable or disable internal debug printing

func (*Tab) DeleteCookie

func (t *Tab) DeleteCookie(cookieName, url string) error

Deletes the cookie from the browser

func (*Tab) DidNavigationFail

func (t *Tab) DidNavigationFail() (bool, string)

An undocumented method of determining if chromium failed to load a page due to DNS or connection timeouts.

func (*Tab) DoubleClick

func (t *Tab) DoubleClick(x, y float64) error

Issues a double click on the x, y coords provided.

func (*Tab) EvaluatePromiseScript

func (t *Tab) EvaluatePromiseScript(scriptSource string) (*gcdapi.RuntimeRemoteObject, error)

Evaluates script in the global context.

func (*Tab) EvaluateScript

func (t *Tab) EvaluateScript(scriptSource string) (*gcdapi.RuntimeRemoteObject, error)

Evaluates script in the global context.

func (*Tab) Forward

func (t *Tab) Forward() error

Looks up the next navigation entry from the history and navigates to it. Returns error if we could not find the next entry or navigation failed

func (*Tab) ForwardEntry

func (t *Tab) ForwardEntry() (*gcdapi.PageNavigationEntry, error)

Returns the next entry in our navigation history for this tab.

func (*Tab) GetAllElements

func (t *Tab) GetAllElements() map[int]*Element

Returns a copy of all currently known elements. Note that modifications to elements maybe unsafe.

func (*Tab) GetChildElements

func (t *Tab) GetChildElements(element *Element) []*Element

Gets all elements of a child

func (*Tab) GetChildElementsOfType

func (t *Tab) GetChildElementsOfType(element *Element, tagType string) []*Element

Returns all elements of a specific tag type.

func (*Tab) GetChildrensCharacterData

func (t *Tab) GetChildrensCharacterData(element *Element) string

Returns the #text values of the element's children.

func (*Tab) GetConsoleMessages

func (t *Tab) GetConsoleMessages(messageHandler ConsoleMessageFunc)

Registers chrome to start retrieving console messages, caller must pass in call back function to handle it.

func (*Tab) GetCookies

func (t *Tab) GetCookies() ([]*gcdapi.NetworkCookie, error)

Returns the cookies from the tab.

func (*Tab) GetCurrentUrl

func (t *Tab) GetCurrentUrl() (string, error)

Returns the current url of the top level document

func (*Tab) GetDOMChanges

func (t *Tab) GetDOMChanges(domHandlerFn DomChangeHandlerFunc)

Allow the caller to be notified of DOM NodeChangeEvents. Simply call this with a nil function handler to stop receiving dom event changes.

func (*Tab) GetDocument

func (t *Tab) GetDocument() (*Element, error)

Returns the top level document element for this tab.

func (*Tab) GetDocumentCurrentUrl

func (t *Tab) GetDocumentCurrentUrl(docNodeId int) (string, error)

Returns the current url of the provided docNodeId

func (*Tab) GetDocumentElementById

func (t *Tab) GetDocumentElementById(docNodeId int, attributeId string) (*Element, bool, error)

Returns an element from a specific Document.

func (*Tab) GetDocumentElementsBySelector

func (t *Tab) GetDocumentElementsBySelector(docNodeId int, selector string) ([]*Element, error)

Same as GetChildElementsBySelector

func (*Tab) GetElementById

func (t *Tab) GetElementById(attributeId string) (*Element, bool, error)

Returns the element by searching the top level document for an element with attributeId Does not work on frames.

func (*Tab) GetElementByLocation

func (t *Tab) GetElementByLocation(x, y int) (*Element, error)

Returns the element given the x, y coordinates on the page, or returns error.

func (*Tab) GetElementByNodeId

func (t *Tab) GetElementByNodeId(nodeId int) (*Element, bool)

Returns either an element from our list of ready/known nodeIds or a new un-ready element If it's not ready we return false. Note this does have a side effect of adding a potentially invalid element to our list of known elements. But it is assumed this method will be called with a valid nodeId that chrome has not informed us about yet. Once we are informed, we need to update it via our list and not some reference that could disappear.

func (*Tab) GetElementsBySearch

func (t *Tab) GetElementsBySearch(selector string, includeUserAgentShadowDOM bool) ([]*Element, error)

Get all elements that match a CSS or XPath selector

func (*Tab) GetElementsBySelector

func (t *Tab) GetElementsBySelector(selector string) ([]*Element, error)

Get all elements that match a selector from the top level document

func (*Tab) GetFrameDocuments

func (t *Tab) GetFrameDocuments() []*Element

Returns all documents as elements that are known.

func (*Tab) GetFrameResources

func (t *Tab) GetFrameResources() (map[string]string, error)

Gets all frame ids and urls from the top level document.

func (*Tab) GetFrameSource

func (t *Tab) GetFrameSource(frameId, url string) (string, bool, error)

Returns the raw source (non-serialized DOM) of the frame. If you want the visible source, call GetPageSource, passing in the frame's nodeId. Make sure you wait for the element's WaitForReady() to return without error first.

func (*Tab) GetFullPageScreenShot

func (t *Tab) GetFullPageScreenShot() ([]byte, error)

Takes a full sized screenshot of the currently loaded page

func (*Tab) GetNetworkTraffic

func (t *Tab) GetNetworkTraffic(requestHandlerFn NetworkRequestHandlerFunc, responseHandlerFn NetworkResponseHandlerFunc, finishedHandlerFn NetworkFinishedHandlerFunc) error

Listens to network traffic, each handler can be nil in which case we'll only call the handlers defined.

func (*Tab) GetPageSource

func (t *Tab) GetPageSource(docNodeId int) (string, error)

Returns the document's source, as visible, if docId is 0, returns top document source.

func (*Tab) GetScreenShot

func (t *Tab) GetScreenShot() ([]byte, error)

Takes a screenshot of the currently loaded page (only the dimensions visible in browser window)

func (*Tab) GetScriptSource

func (t *Tab) GetScriptSource(scriptId string) (string, error)

Returns the source of a script by its scriptId.

func (*Tab) GetStorageEvents

func (t *Tab) GetStorageEvents(storageFn StorageFunc) error

Listens for storage events, storageFn should switch on type of cleared, removed, added or updated. cleared holds IsLocalStorage and SecurityOrigin values only. removed contains above plus Key. added contains above plus NewValue. updated contains above plus OldValue.

func (*Tab) GetTitle

func (t *Tab) GetTitle() (string, error)

Returns the top document title

func (*Tab) GetTopFrameId

func (t *Tab) GetTopFrameId() string

GetTopFrameId return the top frame id of this tab

func (*Tab) GetTopNodeId

func (t *Tab) GetTopNodeId() int

GetTopNodeId returns the current top node id of this Tab.

func (*Tab) InjectScriptOnLoad

func (t *Tab) InjectScriptOnLoad(scriptSource string) (string, error)

Injects custom javascript prior to the page loading on all frames. Returns scriptId which can be used to remove the script. If you only want the script to interact with the top document, you'll need to do checks in the injected script such as testing location.href.

Alternatively, you can use Tab.EvaluateScript to only work on the global context.

func (*Tab) IsNavigating

func (t *Tab) IsNavigating() bool

IsNavigating answers if we currently navigating

func (*Tab) IsShuttingDown

func (t *Tab) IsShuttingDown() bool

IsShuttingDown answers if we are shutting down or not

func (*Tab) IsTransitioning

func (t *Tab) IsTransitioning() bool

IsTransitioning returns true if we are transitioning to a new page. This is not set when Navigate is called.

func (*Tab) MoveMouse

func (t *Tab) MoveMouse(x, y float64) error

Moves the mouse to the x, y coords provided.

func (*Tab) Navigate

func (t *Tab) Navigate(url string) (string, string, error)

Navigate to a URL and does not return until the Page.loadEventFired event as well as all setChildNode events have completed. If successful, returns frameId. If failed, returns frameId, friendly error text, and the error.

func (*Tab) NavigationHistory

func (t *Tab) NavigationHistory() (int, []*gcdapi.PageNavigationEntry, error)

Returns the current navigation index, history entries or error

func (*Tab) Reload

func (t *Tab) Reload(ignoreCache bool, evalScript string) error

Reloads the page injecting evalScript to run on load. set ignoreCache to true to have it act like ctrl+f5.

func (*Tab) RemoveScriptFromOnLoad

func (t *Tab) RemoveScriptFromOnLoad(scriptId string) error

Removes the script by the scriptId.

func (*Tab) SendKeys

func (t *Tab) SendKeys(text string) error

Sends keystrokes to whatever is focused, best called from Element.SendKeys which will try to focus on the element first. Use \n for Enter, \b for backspace or \t for Tab.

func (*Tab) SetDisconnectedHandler

func (t *Tab) SetDisconnectedHandler(handlerFn TabDisconnectedHandler)

SetDisconnectedHandler so caller can trap when the debugger was disconnected/crashed.

func (*Tab) SetElementWaitTimeout

func (t *Tab) SetElementWaitTimeout(timeout time.Duration)

SetElementWaitTimeout to wait in seconds for ele.WaitForReady() before giving up, default is 5 seconds

func (*Tab) SetJavaScriptPromptHandler

func (t *Tab) SetJavaScriptPromptHandler(promptHandlerFn PromptHandlerFunc)

Set a handler for javascript prompts, most likely you should call tab.Page.HandleJavaScriptDialog(accept bool, msg string) to actually handle the prompt, otherwise the tab will be blocked waiting for input and never return additional events.

func (*Tab) SetNavigationTimeout

func (t *Tab) SetNavigationTimeout(timeout time.Duration)

SetNavigationTimeout to wait in seconds for navigations before giving up, default is 30 seconds

func (*Tab) SetStabilityTime

func (t *Tab) SetStabilityTime(stableAfter time.Duration)

SetStabilityTime to wait for no node changes before we consider the DOM stable. Note that stability timeout will fire if the DOM is constantly changing. The deafult stableAfter is 300 ms.

func (*Tab) SetStabilityTimeout

func (t *Tab) SetStabilityTimeout(timeout time.Duration)

SetStabilityTimeout to wait for WaitStable() to return, default is 2 seconds.

func (*Tab) SetUserAgent

func (t *Tab) SetUserAgent(userAgent string) error

Override the user agent for requests going out.

func (*Tab) StopConsoleMessages

func (t *Tab) StopConsoleMessages(shouldDisable bool) error

Stops the debugger service from sending console messages and closes the channel Pass shouldDisable as true if you wish to disable Console debugger

func (*Tab) StopNetworkTraffic

func (t *Tab) StopNetworkTraffic(shouldDisable bool) error

Unsubscribes from network request/response events and disables the Network debugger. Pass shouldDisable as true if you wish to disable the network service.

func (*Tab) StopStorageEvents

func (t *Tab) StopStorageEvents(shouldDisable bool) error

Stops listening for storage events, set shouldDisable to true if you wish to disable DOMStorage debugging.

func (*Tab) WaitFor

func (t *Tab) WaitFor(rate, timeout time.Duration, conditionFn ConditionalFunc) error

Calls a function every tick until conditionFn returns true or timeout occurs.

func (*Tab) WaitStable

func (t *Tab) WaitStable() error

A very rudementary stability check, compare current time with lastNodeChangeTime and see if it is greater than the stableAfter duration. If it is, that means we haven't seen any activity over the minimum allowed time, in which case we consider the DOM stable. Note this will most likely not work for sites that insert and remove elements on timer/intervals as it will constantly update our lastNodeChangeTime value. However, for most cases this should be enough. This should only be necessary to call when a navigation event occurs under the page's control (not a direct tab.Navigate) call. Common examples would be submitting an XHR based form that does a history.pushState and does *not* actually load a new page but simply inserts and removes elements dynamically. Returns error only if we timed out.

type TabDisconnectedHandler

type TabDisconnectedHandler func(tab *Tab, reason string)

TabDisconnectedHandler is called when the tab crashes or the inspector was disconnected

type TimeoutErr

type TimeoutErr struct {
	Message string
}

TimeoutErr when Tab.Navigate has timed out

func (*TimeoutErr) Error

func (e *TimeoutErr) Error() string

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL