This specification defines the WebDriver API, a platform and language-neutral interface and associated wire protocol that allows programs or scripts to introspect into, and control the behaviour of, a web browser. The WebDriver API is primarily intended to allow developers to write tests that automate a browser from a separate controlling process, but may also be implemented in such a way as to allow in-browser scripts to control a — possibly separate — browser.

The WebDriver API is defined by a wire protocol and a set of interfaces to discover and manipulate DOM elements on a page, and to control the behaviour of the containing browser.

This specification also includes a normative reference serialisation (to JSON over HTTP) of the interface's invocations and responses that are to be used by browser vendors to ensure interoperability.

If you wish to make comments regarding this document, please email feedback to public-browser-tools-testing@w3.org. All feedback is welcome, and the editors will read and consider all feedback.

This specification is still under active development and may not be stable. Any implementors who are not actively participating in the preparation of this specification may find unexpected changes occurring. It is suggested that any implementors join the WG for this specification. Despite not being stable, it should be noted that this specification is strongly based on an existing Open Source project — Selenium WebDriver — and the existing implementations of the API defined within that project.

Introduction

The WebDriver API aims to provide a synchronous API that can be used for a variety of use cases, though it is primarily designed to support automated testing of web apps.

Intended Audience

This specification is intended for implementors of the WebDriver API. It is not intended as light bed time reading.

Relationship of WebDriver API and Existing Specifications

Where possible and appropriate, the WebDriver API references existing specifications. For example, the list of boolean attributes for elements is drawn from the HTML specification. When references are made, this specification will link to the relevant sections.

Naming the Two Sides of the API

The WebDriver API can be thought of as a client/server process. However, implementation details can mean that this terminology becomes confusing. For this reason, the two sides of the API are called the "local" and the "remote" ends.

Local
The user-facing API. Command objects are sent and Response objects are consumed by the local end of the WebDriver API. It can be thought of as being "local" to the user of the API.
Remote
The implementation of the user-facing API. Command objects are consumed and Response objects are sent by the remote end of the WebDriver API. The implementation of the remote end may be on a machine remote from the user of the local end.

There is no requirement that the local and remote ends be in different processes. The IDLs given in this specification SHOULD be used as the basis for any conforming local end implementation.

Conformance Requirements

All diagrams, examples, and notes in this specification are non-normative, as are all sections explicitly marked non-normative. Everything else in this specification is normative.

The key words "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in the normative parts of this document are to be interpreted as described in [[!RFC2119]]. The key word "OPTIONALLY" in the normative parts of this document is to be interpreted with the same normative meaning as "MAY" and "OPTIONAL".

Conformance requirements phrased as algorithms or specific steps may be implemented in any manner, so long as the end result is equivalent.

The IDL fragments in this specification must be interpreted as required for conforming IDL fragments, as described in the Web IDL specification [[!WEBIDL]].

Conformance Classes

This specification describes the conformance criteria for both local (relevant to creating bindings for languages) and remote end implementations (relevant to browser vendors and server implementors). A final conformance class — intermediate node — is also specified. These represent those nodes situated between the local and remote ends.

Commands and Responses

The communication between the remote and local ends is performed via Command and Response objects. How these are encoded and transmitted between the remote and local ends is left undefined.

Command

interface Command {
  attribute DOMString name;
  attribute object parameters;
  attribute DOMString sessionId;
};

A command represents a call to a remote end to the session identified by the sessionId attribute. By default, the sessionId is null. The only time the null value is a valid sessionId is before a call to newSession. The name of the command to execute is held in the name, and this MUST be handled case-sensitively. It defaults to the null value. The parameters attribute is a map of named parameters to objects representing the value of the parameter. The default value is an empty array and this field MUST NOT be null.

Response

interface Response {
  readonly attribute DOMString sessionId;
  readonly attribute DOMString status;
  readonly attribute object value;
};

A Response represents the value returned from the remote end of the WebDriver API after executing a Command from the session identified by the sessionId attribute. The default value for the sessionId MUST be the sessionId used in the command that this is a response to, unless the command's sessionId was the null value, in which case a unique sessionId MUST be assigned (see newSession for how this is achieved).

Each Response has a status that indicates the success or failure of the method. Anything other than "success" indicates a failure. Each command lists the status strings it can return in the section of this specification in which it is defined, but the normative list of expected statuses is given below in the Status Codes section. This list MAY be extended by implementors of the specification, provided they follow the guidelines about extending the protocol.

The meat of the Response is in the value attribute. It's type is determined by the command that has been executed. In this specification, each command definition will make clear what the expected return type is. The default value is the null value. In the case where the status indicates failure, the value is commonly the error text explaining the cause of the problem.

In the case where a failure is indicated and the language used for implementing the local end supports throwing exceptions, the value is often used as the exception's message.

There is no requirement that implementations of command and Response exhibit any behaviour: they MAY be simple data structures. Reading of values MUST be idempotent, and writing any particular value MUST NOT cause any other values on the command or Response to change.

Processing Additional Fields on Commands and Responses

Any command or Response MAY contain additional fields than those listed above. The content of fields MUST be maintained, unaltered by any intermediate nodes. There is no requirement to maintain the ordering of fields.

This requirement exists to allow for extension of the protocol, and to allow implementors to decorate Commands and Responses with additional information, perhaps giving context to a series of messages or providing security information.

Status Codes

The WebDriver API indicates the success or failure of a command invocation via Response.status. The following values are used and have the following meanings.

Status Code Detail
element not selectable An attempt was made to select an element that cannot be selected.
element not visible An element command could not be completed because the element is not visible on the page.
ime engine activation failed An IME engine could not be started.
ime not available IME was not available.
invalid cookie domain An illegal attempt was made to set a cookie under a different domain than the current page.
invalid element coordinates The coordinates provided to an interactions operation are invalid.
invalid element state An element command could not be completed because the element is in an invalid state (e.g. attempting to click an element that is no longer attached to the Document).
invalid selector Argument was an invalid selector (e.g. XPath/CSS).
javascript error An error occurred while executing user supplied JavaScript.
move target out of bounds The target for mouse interaction is not in the browser's viewport and cannot be brought into that viewport.
no such alert An attempt was made to operate on a modal dialog when one was not open.
no such element An element could not be located on the page using the given search parameters.
no such frame A request to switch to a frame could not be satisfied because the frame could not be found.
no such window A request to switch to a different window could not be satisfied because the window could not be found.
script timeout A script did not complete before its timeout expired.
session not created A new session could not be created.
stale element reference An element command failed because the referenced element is no longer attached to the Document.
success The command executed successfully.
timeout An operation did not complete before its timeout expired.
unable to set cookie A request to set a cookie's value could not be satisfied.
unexpected alert open A modal dialog was open, blocking this operation.
unknown command A command could not be executed because the remote end is not aware of it.
unknown error An unknown error occurred in the remote end while processing the command.
unsupported operation Indicates that a command that should have executed properly cannot be supported for some reason.

Handling of Status Codes at the Local End

Status codes are returned from the remote end to the local end. The local end SHOULD convert these into a form appropriate for the implementation language. For example, in C the status codes might be converted to constant integer values, whereas in Java various exceptions could be thrown.

Implementations of the local end written in languages that support exceptions SHOULD make use of an exception hierarchy rooted on a WebDriverException (or similarly named base exception class). Where references to WebDriverException are made in this specification, we are referring to this local end conversion of status codes to local end exceptions.

The reason for this is to allow users of the local end to easily handle the all expected failure modes of a local WebDriver implementation by catching the WebDriverException.

It is strongly recommended that the WebDriverException contain as much diagnostic information as possible, including version numbers and details about the remote end. This is because experience suggests that when reporting errors from tests using WebDriver, users will simply cut-and-paste a stack trace of an exception. Adding this information to the exception makes the task of debugging problems considerably easier.

The JSON Wire Protocol

Although the encoding and transport mechanism is left undefined in this specification, implementors of the remote end MUST provide an implementation suitable for acting as the server-side of the JSON and HTTP protocol (the "JSON Wire Protocol") defined in this specification and summarized non-normatively in Appendix G. This MAY take the form of a standalone executable that translates the JSON over HTTP protocol to the encoding and transport mechanism used by the remote end.

When describing the URL to use for each Command this specification will use URI paths encoded using the scheme described in [[!URI-TEMPLATE]]. The following substitutions are commonly made:

{sessionId}
The sessionId of the selected session.
{id}
The id of the WebElement instance being referred to

The URLs given in this specification MUST have the same path prefix. Implementations are free to redirect those as necessary.

The reason for doing this is to reduce the complexity of local-end implementations. They need only append the path to a base URL in order to create a working implementation.

JSON Encoding of Commands

A Command instance MUST be encoded using UTF-8 and MUST be mapped to the following JSON structure:
  {
    "sessionId" : "string value",
    "name" : "string value",
    "parameters" : {}
  }

The "parameters" fields depends on the "name" of the Command, and will be documented by the definition of each Command in this specification.

JSON Encoding of Responses

A Response instance MUST be encoded using UTF-8 and MUST be mapped to the following JSON structure:

  {
    "sessionId" : "string value",
    "status": "string value",
    "value" : {}
  }

The value of the "value" field will be defined beside each Command in this specification.

Browser Capabilities

Different browsers support different levels of various specifications. For example, some support SVG or the [[!SELECTORS-API]], but only browsers that implement [[!WEBSTORAGE]] will support LocalStorage. The WebDriver API provides a mechanism to query the supported capabilities of a browser. Each broad area of functionality within the WebDriver API has an associated capability string. Whether a particular capability MUST or MAY be supported — as well as fallback mechanisms for handling those cases where a capability is not supported — is discussed where the capability string is defined.

Capabilities

readonly attribute dictionary capabilities
The underlying collection of capabilities, represented as a dictionary mapping strings to values which may be of type boolean, numerical or DOMString. The default value is an empty dictionary.
boolean has(DOMString capabilityName)
Queries the underlying capabilities to see whether the value is set. This MUST return true if the capabilities contain a key with the given capabilityName and the value of that key is defined. If the value is a boolean, this function MUST return that boolean value. If the value is null, an empty string or a 0 then this method MUST return false.
(DOMString or boolean or long)? get(DOMString capabilityName)
Get the value of the key matching capabilityName in the underlying capabilities or null if no value is defined.

A Capabilities instance MUST be immutable. If a mutable Capabilities instance is required, then the MutableCapabilities MUST be used instead.

The "has" method is designed to provide a quick boolean check on whether or not a particular capability is set and can be used in an "if" statement in many languages. The "get" method returns the exact value. In the case of boolean values, this will be the same result as if "truthy" values are used (that is: get('falseValue') and get('unsetValue') are both false).

MutableCapabilities

void set(DOMString capabilityName, (DOMString or boolean or long)? value)
Set the value of the given capabilityName to the given value. If the value is not a boolean, numerical type, a DOMString or the null value a WebDriverException SHOULD be thrown.

In the case where the local and remote end are in the same process, it SHOULD be acceptable to use other types with the set method. If this is allowed, the value MUST be serialized to one of the acceptable types (boolean, numerical type, a string or the null value) before being sent out of process (such as transmitting from the local to the remote end). If this serialization is not possible, a WebDriverException MUST be thrown.

As an example, perhaps the browser being automated supports user profiles. This may be modelled in code as a "Profile" object, leading to code such as:

		profile = Profile("some/user/directory")
		capabilities = MutableCapabilities()
		capabilities.set('profile', profile)
		driver = RemoteDriver(capabilities)
    

In this example, the profile represents a directory on the local disk. One way to serialize this would be to zip the contents of this profile and then encode it using base64 to allow it to be passed as a string.

Sessions

Non-normative summary: A session is equivalent to a single instantiation of a particular browser, including all child windows. The WebDriver API gives each session a unique ID stored as an opaque string that can be used to differentiate one session from another, allowing multiple browsers to be controlled on the same machine if needed, and allowing sessions to be routed via a multiplexer. This ID is sent with every Command and returned with every Response and is stored on the sessionId field.

Creating a Session

The process for successfully creating a session MUST be:

  1. The local end creates a new Capabilities or MutableCapabilities instance describing the desired capabilities for the session. The Capabilities object MUST be defined but MAY be empty.
  2. The local end MUST create a new Command with the "name" being "newSession" and the "parameters" containing an entry named "desiredCapabilities" with the value set to the Capabilities instance from the previous step. An optional "requiredCapabilities" entry MAY also be created and populated with a Capabilities instance. The "sessionId" fields SHOULD be left empty.
  3. The Command is transmitted to the remote end.
  4. The remote end MUST examine the "requiredCapabilities" parameter if specified, SHOULD examine the "desiredCapabilities" parameter, and MUST create a new session matching as many of the Capabilities as possible. How the new session is created depends on the implementation of this specification.
    • If any of the "requiredCapabilities" cannot be fulfilled by the new session, the remote end MUST quit the session and return the session not created error code. The sessionId of the Response object MUST be left as the default value unless the Command had the sessionId set, in which case that value MUST be used. The error message SHOULD list all unmet required capabilities though only a single required capability MUST be given.
    • If a capability is listed in both the requiredCapabilities and desiredCapabilities, the value in the requiredCapabilities MUST be used.
  5. The session MUST be assigned a sessionId which MUST be unique for each session (a UUID SHOULD be used). Generating the sessionId MAY occur before the session is created. If the Command object had the "sessionId" field set, this MAY be discarded in favour of the freshly generated sessionId. Because of this, it is recommended that sessionId generation be done on the remote end. If the sessionId has already been used, a Response MUST be sent with the status code set to session not created and the value being an explanation that the sessionId has previously been used.
  6. The remote end MUST create a new Response object, with the following fields MUST be set to:
    • "sessionId": the sessionId associated with this session.
    • "value": a Capabilities instance. The keys of this Capabilities instance MUST be the strings given in each of the supported capabilities as defined in the relevant sections of this specification. Supported functionality MUST be included in this Capabilities instance, while unsupported functionality MAY be omitted.
    • "status": the success error code.
  7. The Response is returned to the local end.

There is no requirement for the local end to validate that some or all of the fields sent on the Capabilities associated with the Command match those returned in the Response.

As stated, when returning the value of the Response, the remote end MUST include the capability names and values of all supported capabilities from this specification. They MAY also include any additional capability names and values of supported capabilities implemented independently of this specification. Local ends MAY choose to ignore this additional information. Intermediate nodes between the local and remote ends MAY interpret the capabilities being returned.

If the browserName is given as a desired capability and omitted from the required capabilities, and the returned browserName value does not match the requested one, local ends SHOULD issue a warning to the user. How this warning is issued is undefined, but one implementation could be a log message. In this particular case, local ends MAY chose to change the Response's status code to session not created, and modify the value to explain the cause, including the value originally returned as the browserName capability. If this is done, the local end MUST ensure that the remote end quits the session.

Capability Names

The following keys SHOULD be used in the Capabilities instances. They all default to the null string.

browserName
The name of the desired browser as a string.
browserVersion
The version number of the browser, given as a string.
platformName
The OS that the browser is running on, matching any of the platform names given below.
platformVersion
The version of the OS that the browser is running on as a string.

Platform Names

The following platform names are defined and MUST be used, case sensitively, for the "platformName" unless the actual platform being used is not given in this list:

  • android
  • ios
  • linux
  • mac
  • unix
  • windows

In addition "any" MAY be used to indicate the underlying OS is either unknown or does not matter.

Implementors MAY add additional platform names. Until these are standardized, these MUST follow the conventions outlined in extending the protocol section with the exception that the vendor prefix SHOULD omit the leading "-" character.

For example, Mozilla's Firefox OS could be described as either "-MOZ-FIREFOXOS" or "MOZ-FIREFOX". The latter makes it easier for local ends to specify an enum of supported platforms and is therefore recommended in this case.

Error Handling

The following status codes MUST be returned by the "newSession" command:

success
The session was successfully created. The "value" field of the Response MUST contain a Capabilities object describing the session.
timeout
The new session could not be created within the time allowed for command execution on the remote end. This time MAY be infinite (in which case this status won't be seen). The "value" field of the Response SHOULD contain a string explaining that a timeout has occurred, but it MAY be left as the null value or filled with the empty string.
unknown error
An unhandled error of some sort has occurred. The "value" field of the Response SHOULD contain a more detailed description of the error as a string.

Remote End Matching of Capabilities

This section is non-normative.

The suggested order for comparing keys in the Capabilities instance when creating a session is:

  1. browserName
  2. browserVersion
  3. platformName
  4. platformVersion

For all comparisons, if the key is missing (as determined by a call to Capability.has() returning "false"), that particular criteria shall not factor into the comparison.

Navigation

Almost all usages of the WebDriver API begin by navigating to a particular URL. This section not only describes the commands used for navigation, but also describes when commands must be processed.

All WebDriver implementations MUST support navigating between different HTTP domains and between HTTPS and HTTP domains if the underlying browser supports this.

Page Load Strategies

Capability NameType
pageLoadingStrategyDOMString

It is possible to request a particular strategy be used for detecting when the next command should be processed by a remote end implementation by modifying the page load strategy that is used. The following are the expected values that MAY be used when creating a new session:

const DOMString CONSERVATIVE = 'conservative'
The remote end MUST wait until all frames and iframes in the window currently being used to process commands that contain an HTML document are at document.readyState equals 'complete' and there are no outstanding HTTP requests, other than those caused by XMLHttpRequests. If a frame or iframe does not contain an HTML document, the remote end SHOULD wait until all HTTP traffic to that frame is complete. Put in non-normative terms, this implies that the onload event has fired on every frame.
const DOMString NORMAL = 'normal'
The remote end MUST wait until the "document.readyState" of the frame currently handling commands equals "complete", or there are no more outstanding network requests other than XMLHttpRequests.
const DOMString EAGER = 'eager'
The remote end MUST wait until the "document.readyState" of frame currently handling equals "interactive" or "complete", or there are no more outstanding network requests.
const DOMString NONE = 'none'
The remote end does not do any checks to see if a page load is currently active.

All WebDriver implementations MUST support the normal and eager modes and SHOULD support the conservative and none modes. If no page loading strategy is chosen, then normal MUST be the default. In addition, implementors MAY add additional page loading strategies.

Navigation Commands

Conformance tests for this section can be found in the webdriver module under the "navigation" folder.

void get()
HTTP Method Path Template Notes
POST /session/{sessionId}/url

The "get" command is used to cause the browser to navigate to a new location, and is named after the HTTP verb. From a user's point of view, this is as if they have entered the "url" into the URL bar. When the command returns is based on the page load strategy that the user has selected with the following exceptions when the strategy is not "none":

  • HTTP redirects MUST be automatically followed without responding to the command.
  • When a page contains a META tag with the "http-equiv" attribute set to "refresh", a response MUST be returned if the timeout is greater than 1 second and the other criteria for determining whether a page is loaded are met. When the refresh period is 1 second or less and the page loading strategy is "normal" or "conservative" implementations MUST wait for the refresh to complete before responding.
  • If any modal dialog box, such as those opened by on window.onbeforeunload or window.alert, is opened at any point in the page load, a response MUST be sent.
  • If a 401 response is seen by the browser, a response MUST be sent. That is, if BASIC, DIGEST, NTLM or similar authentication is required, the page load is assumed to be complete. This does not include FORM-based authentication.
DOMString url
URL that the browser will navigate to
DOMString getCurrentUrl()
HTTP Method Path Template Notes
GET /session/{sessionId}/url

WebDriver implementations MUST allow the users to be able to get the current URL. In the case of a Nested Browsing Context WebDriver should return the [[html51]] top level browsering context. The returned value should be the equivalent to returning document.location.href for the [[html51]] top level browsering context.

If the window currently receiving commands is no longer open a no such window MUST be raised.

void goBack()
HTTP Method Path Template Notes
POST /session/{sessionId}/back

The "goBack" command is equivalent to a user hitting the "back" button in their browser, and MUST behave as a traversal of the browser history by a delta of -1 (as defined in [[!html51]]). If a user calls "goBack" when there are no further pages in the browser's history stack, then this call MUST be a no-op.

If the page takes too long as specified by the timeouts a timeout MUST be raised. If the window currently receiving commands is no longer open a no such window MUST be raised.

void goForward()
HTTP Method Path Template Notes
POST /session/{sessionId}/forward

The "goForward" command is equivalent to a user hitting the "forward" button in their browser, and MUST behave as a traversal of the browser history by a delta of +1 (as defined in [[!html51]]). If a user calls "goForward" when there are no further pages in the browser's history stack, then this call MUST be a no-op.

If the page takes too long as specified by the timeouts a timeout MUST be raised. If the window currently receiving commands is no longer open a no such window MUST be raised

void refresh()
HTTP Method Path Template Notes
POST /session/{sessionId}/refresh

"refresh" emulates the user hitting the "refresh" or "reload" button in their browser, causing the current page to be reloaded.

If the page takes too long as specified by the timeouts a timeout MUST be raised. If the window currently receiving commands is no longer open a no such window MUST be raised.

Invalid SSL Certificates

Capability NameType
secureSslboolean

WebDriver implementations MUST support users accessing sites served via HTTPS. Access to those sites using self-signed or invalid certificates, and where the certificate does not match the serving domain MUST be the same as if the HTTPS was configured properly.

The reason for this is that implementations of this spec are often used for testing. It's a sorry fact that many QA engineers and testers are asked to verify that apps work on sites that have insecure HTTPS configurations

The exception to requirement is if the Capabilities used to initialize has the WebDriver session had the capability secureSsl set to true. In this case, implementations MAY choose to make accessing a site with bad HTTPS configurations cause a WebDriverException to be thrown. Remote end implementations MUST return an unknown error status in this case. If this is the case, the Capabilities describing the session MUST also set the secureSsl capability to "true".

Detecting When to Handle Commands

Commands MUST only be processed when the page loading strategy being used indicates that page loading is complete.

If a remote end receives a new Command for a session while still waiting to finish an existing Command for that session it MAY choose to queue the command for execution as soon as possible, it MAY throw a WebDriverException or it MAY leave the remote end in an inconsistent state. Because of this, local ends SHOULD NOT attempt to send a new Command to a session until the previous Command has returned.

Controlling Windows

Defining "window" and "frame"

Within this specification, a window equates to [[!html51]]'s top level browsing context. Put another way, within this spec browser tabs are counted as separate windows.

TODO: define "frame"

Window Handles

DOMString getWindowHandle()

Each window has a "window handle" associated with it. This is an opaque string which MUST uniquely identify the window within the session and MUST NOT be "current". This MAY be a UUID. The "getWindowHandle" command can be used to obtain the window handle for the window that commands are currently acting upon.

Iterating Over Windows

sequence<DOMString> getWindowHandles()

This array of returned strings MUST contain a handle for every window associated with the browser session and no others. For each returned window handle the javascript expression "window.top.closed" (or equivalent) MUST evaluate to false at the time the command is being executed.

The ordering of the array elements is not defined, but MAY be determined by iterating over each top level browser window and returning the tabs within that window before iterating over the tabs of the next top level browser window. For example, in the diagram below, the window handles should be returned as the handles for: win1tab1, win1tab2, win2.

Two top level windows. The first window has two tabs, lablled win1tab1 and win1tab2. The second window has only one tab labelled win2

This implies that the correct way to determine whether or not a particular interaction with the browser opens a new window is done by obtaining the set of window handles before the interaction is performed and comparing with the set after the action is performed.

Closing Windows

void close()

The close command closes the window that Commands are currently being sent to. If this means that a call to get the list of window handles would return an empty list, then this close command MUST be the equivalent of calling "quit". That is, if the final window of a session is closed, then the session quits.

Once the window has closed, future commands MUST return a status code of no such window until a new window is selected for receiving commands.

Resizing and Positioning Windows

All commands MUST be handled by the window that ultimately owns the current context.

double height
The height of the window in pixels
double width
The width of the window in pixels
void setWindowSize()
Resizes the Browser window to have the height and width passed in as parameters.

If a request is made to resize a window to a size which cannot be performed (e.g. the browser has a minimum, or fixed window size, or the operating system does not support resizing windows at all as is the case in many phone OSs), an unsupported operation status code MUST be returned.

After setWindowSize, the browser window MUST NOT be in the maximised state.

unsigned short width
The "width" value refer to the javascript "window.outerwidth" property. For those browsers that do not support these properties, these represent the width of the whole browser window including window chrome and window resizing borders/handles.
unsigned short height
The "height" value refer to the javascript "window.outerheight" property. For those browsers that do not support these properties, these represent the height of the whole browser window including window chrome and window resizing borders/handles.
WindowSize getWindowSize()
Return a WindowSize dictionary containing the hieght and width of the window in pixels
void maximizeWindow()

After maximizeWindow, the browser window MUST be left as if the maximise button had been pressed if, and only if, the window manager of the OS supports this concept; it is not sufficient to leave the window "restored", but with the full screen dimensions.

If a request is made to resize a window to a size which cannot be performed (e.g. the browser has a minimum, or fixed window size, or the operating system does not support resizing windows at all as is the case in many phone OSs), an unsupported operation status code MUST be returned.

void fullscreenWindow()

After fullscreenWindow, the browser window MUST be in full-screen mode. For those operating systems that support the concept, this MUST be equivalent to if the user requested the window be full screen. If the OS does not support the concept of full-screen, then this command is a synonym for "maximizeWindow".

If a request is made to resize a window to a size which cannot be performed (e.g. the browser has a minimum, or fixed window size, or the operating system does not support resizing windows at all as is the case in many phone OSs), an unsupported operation status code MUST be returned.

Scaling the Content of Windows

TODO

Where Commands Are Handled

Web applications can be composed of multiple windows and/or frames. For a normal user, the context in which an operation is performed is obvious: it's the window or frame that currently has OS focus and which has just received user input. The WebDriver API does not follow this convention. There is an expectation that many browsers using the WebDriver API may be used at the same time on the same machine. This section describes how WebDriver tracks which window or frame is currently the context in which commands are being executed.

Default Content

WebDriver's default content is [[!html51]]'s top level browsing context for the window that is currently receiving WebDriver commands.

When a WebDriver instance is started and a single browser window is opened, the default content of that window is automatically selected for receiving further commands. If more than one window is opened when the session starts, then the user MUST first select which window to act upon using the switchToWindow command. Until the user selects a window, all commands must return a status code of no such window.

Switching Windows

void switchToWindow()
DOMString name
The identifier used for a window

The "switchToWindow" command is used to select which window MUST be used as the context for processing commands. In order to determine which window should be used for accepting commands, the "switchToWindow" command MUST iterate over all windows. For each window, the following MUST be compared — in this order — with the "name" parameter:

  1. A window handle, obtained from "getWindowHandles" or "getWindowHandle".
  2. The window name, as defined when the window was opened (the value of "window.name")

If no windows match, then a "no such window" status code MUST be returned, otherwise the "default content" of the first window to match will be selected for accepting commands.

Switching Frames

void switchToFrame()
HTTP Method Path Template Notes
POST /session/{sessionId}/frame
WebElement or unsigned short? id
The identifier used for a frame.

The "switchToFrame" command is used to select which frame within a window MUST be used as the context for handling future commands. All frame switching is taken from the current context from which commands are currently being handled. The "id" parameter can be an unsigned short or a WebElement. WebDriver implementations MUST determine which frame to select using the following algorithm:

  1. If the "id" is a unsigned short the current context is set to the equivalent of the JS expression "window.frames[n]" where "n" is the number and "window" is the Document window represented by the current context.
  2. If the "id" is null, the current context is set to the default content.
  3. If the "id" represents a WebElement, and the corresponding Document element represents a FRAME or an IFRAME, and the WebElement is part of the current context, the "window" property of that Document element becomes the current context.

In all cases if no match is made a "no such frame" status code MUST be returned.

If the indicated frame exists, frame switching MUST succeed even if doing so would violate the normal security constraints in place within the Javascript sandbox.

void switchToParentFrame()
HTTP Method Path Template Notes
POST /session/{sessionId}/frame/parent

The "switchToParentFrame" command MUST set the context of future commands to the window.parent. If the current context is the [[!html51]]'s top level browsing context, the context remains unchanged.

Running Without Window Focus

All browsers must comply with the focus section of the [[!html51]] spec. In particular, the requirement that the active element within a top-level browsing context be independent of whether or not the top-level browsing context itself has system focus MUST be followed.

This requirement is put in place to allow efficient machine utilization when using the WebDriver API to control several browsers independently on the same desktop

Elements

Conformance tests for this section can be found in the webdriver module under the "element_location" folder.

One of the key abstractions of the WebDriver API is the WebElement interface. Each instance of this interface represents an Element as defined in the [[!DOM4]] specification. Because the WebDriver API is designed to allow users to interact with apps as if they were actual users, the capabilities offered by the WebElement interface are somewhat different from those offered by the Document Element interface.

Each WebElement instance must have an ID, which is distinct from the value of the Document Element's "id" property. The ID for every WebElement representing the same underlying Document Element MUST be the same. The IDs used to refer to different underlying Document Elements MUST be unique within the session over the entire duration of the session.

This requirement around WebElement IDs allows for efficient equality checks when the WebDriver API is being used out of process.

readonly attribute DOMString id
The WebDriver ID of this particular element. This SHOULD be a UUID.

This section of the specification covers finding elements. Later sections deal with querying and interacting with these located elements. The primary interface used by the WebDriver API for locating elements is the SearchContext.

Lists of WebElements

The primary grouping of WebElement instances is an array of WebElement instances

A reference to an WebElement is obtained via a SearchContext. The key interfaces are:

readonly attribute DOMString strategy
The name of the strategy that should be used to locate elements. The default value is the null value
readonly attribute DOMString value
The value to pass to the element finding strategy. The default value is the null value.
WebElement[] findElements(in Locator locator)
WebElement findElement(in Locator locator)

Element Location Strategies

All element location strategies MUST return elements in the order in which they appear in the current document.

CSS Selectors

Strategy name: css selector

If a browser supports the CSS Selectors API ([[!SELECTORS-API]]) it MUST support locating elements by CSS Selector. If the browser does not support the browser CSS Selector spec it MAY choose to implement locating by this mechanism. If the browser can support locating elements by CSS Selector, it MUST set the "cssSelector" capability to boolean true when responding to the "newSession" command. Elements MUST be returned in the same order as if "querySelectorAll" had been called with the Locator's value. Compound selectors are allowed.

ECMAScript

Finding elements by ecmascript is covered in the ecmascript part of this spec.

Element ID

Strategy name: id

This strategy MUST be supported by all WebDriver implementations.

The HTML specification ([[!html51]]) states that element IDs must be unique within their home subtree. Sadly, this uniqueness requirement is not always met. Consequently, this strategy is equally valid for finding a single element or groups of elements. In the case of finding a single WebElement, this MUST be functionally identical to a call to "document.getElementById()" from the [[!DOM4]]. When finding multiple elements, this is equivalent to an CSS query of "#value" where "value" is the ID being searched for with all "'" characters being properly escaped..

Link Text

Strategy name: link text

This strategy MUST be supported by all WebDriver implementations.

This strategy MUST return all "a" elements with visible text exactly and case sensitively equal to the term being searched for.

This is equivalent to:

		  elements = driver.find_elements(by = By.TAG_NAME, value = "a")
		  result = []
		  for element in elements:
		    text = element.text
		    if text == search_term:
		      result.append(element)
		

Where "search_term" is the link text being searched for, and "result" contains the list of elements to return.

Partial Link Text

Strategy name: partial link text

This strategy MUST be supported by all WebDriver implementations.

This strategy is very similar to link text, but rather than matching the entire string, only a subset needs to match. That is, this MUST return all "a" elements with visible text that partially or completely and case sensitively matches the term being searched for.

This is equivalent to:

		  elements = driver.find_elements(by = By.TAG_NAME, value = "a")
		  result = []
		  for element in elements:
		    text = element.text
		    if text.search(seach_term) != -1:
		      result.append(element)
		

Where "search_term" is the link text being searched for, and "result" contains the list of elements to return.

XPath

Strategy name: xpath

All WebDriver implementations MUST support finding elements by XPath 1.0 [[!XPATH]] with the edits from section 3.3 of the [[!html51]] specification made. If no native support is present in the browser, a pure JS implementation MAY be used. When called, the returned values MUST be equivalent of calling "evaluate" function from [[DOM-LEVEL-3-XPATH]] with the result type set to "ORDERED_NODE_SNAPSHOT_TYPE (7).

Reading Element State

Conformance tests for this section can be found in the webdriver module under the "element_state" folder.

Determining if an element is displayed

The following steps MUST be used to determine if an element is displayed to a user. This specification refers to this as the element being "shown".

Essentially, this attempts to model whether or not a user of the browser could possibly find a way to view the WebElement without resizing the browser window.

The common usage pattern for isDisplayed is typically something similar to (in python):

        element = driver.find_element(by = TAG_NAME, value= = "button")
        if element.is_displayed():
            element.click()
        else
            # So other deep magic of the unseen ages.
      
boolean isDisplayed()
If isDisplayed returns true, then the element MUST also be interactable should it meet the other criteria for being interactable. If any part of the BODY can be brought into the current viewport, this MUST return true.

This implies that isDisplayed MUST return true if the centre of the element could be brought into the viewport. The exception to this would be the BODY element, which is generally assumed to always be displayed by users of the WebDriver spec. It is possible to interact with elements which may not have the centre point brought into the viewport by using the low level commands. This means that if any part of the element could be brought into the viewport by user action and its position could be used by low-level commands then a WebDriver implementation MAY return true.

DOMString id
The ID of the WebElement. If the element is no longer attached to the document then a stale element reference MUST be raised.

Determining Whether a WebElement Is Selected

The remote end MUST determine whether a WebElement is selected using the following algorithm:

  1. If the item is not "selectable", the WebElement is not selected. A selectable element is either an OPTION element or an INPUT element of type "checkbox" or "radio".
  2. If the Document node represented by the WebElement is an OPTION element, the "selectedness" of the element, as defined in [[!html51]] determines whether the element is selected.
  3. Otherwise, the value of the Document node's "checked" property determines whether the element is selected. This MUST reflect the element's "checkedness" as defined in [[!html51]].
boolean isSelected()

The remote end MUST determine whether a WebElement is selected using the following algorithm:

  1. If the item is not "selectable", the WebElement is not selected. A selectable element is either an OPTION element or an INPUT element of type "checkbox" or "radio".
  2. If the Document node represented by the WebElement is an OPTION element, the "selectedness" of the element, as defined in [[!html51]] determines whether the element is selected.
  3. Otherwise, the value of the Document node's "checked" property determines whether the element is selected. This MUST reflect the element's "checkedness" as defined in [[!html51]].
DOMString id
The ID of the WebElement. If the element is no longer attached to the document then a stale element reference MUST be raised.

Reading Attributes and Properties

Although the [[!html51]] spec is very clear about the difference between the properties and attributes of a Document element, users are frequently confused between the two. Because of this, the WebDriver API offers a single command ("getElementAttribute") which covers the case of returning either of the value of a Document element's property or attribute. If a user wishes to refer specifically to an attribute or a property, they should evaluate Javascript in order to be unambiguous.

DOMString getElementAttribute()

The algorithm to implement this MUST be (where name refers to the name parameter of the getElementAttribute command):

  1. If name case insensitively matches "style", the value returned MUST be serialized as defined in the [[!CSSOM-VIEW]] spec. Notably, css property names MUST be cased the same as specified in in section 6.5.1 of the [[!CSSOM-VIEW]] spec.
    • It SHOULD be equivalent to obtaining the "cssText" property, with the additional constraint that the same value MUST be returned after a round trip through "executeScript". That is, the following pseudo-code MUST be true (where "driver" is a WebDriver instance, and "element" is a WebElement):
      style = element.get_attribute('style');
      self.driver.execute_script('arguments[0].style = arguments[1]', element, style);
      var recovered = element.get_attribute('style');
      assertEquals(style, recovered);
      
    • Color property values MUST be standardized to rgba format, matching the regular expression: rgba(\d+,\s*\d+,\s*\d+\s*(,\s*(1|0(\.\d+)?))).
  2. If the result of a Javascript call to "hasAttribute(name)" (as defined in [[!DOM4]]) returns true:
    1. Store the result of the Javascript call to "getAttribute(name)" in result
    2. If the attribute name is defined as a boolean attribute, the string 'true' MUST be returned if result is true, or null otherwise
    3. Otherwise, fall through to the final step in this algorithm.
  3. If the element is an OPTION element and name case insensitively matches "value":
    1. If a Javascript call to hasAttribute(name) returns true, then the result of a Javascript call to getAttribute(name) MUST be returned.
    2. Otherwise, the text content of the OPTION, as returned by a call to getElementText, MUST be returned.
  4. If the element is selectable and name case insensitively matches "selected", and the element in an INPUT element of type "checkbox" or "radio", the string "true" MUST be returned if the element is checked or null otherwise.
  5. If the value is expected to be a URL, return the property named name, i.e. a fully resolved URL. A non-normative set of these properties is given below:
    Tag name "name" value
    A href
    IMG src
  6. If name is in the table below, and the above stages have not yielded a defined, non-null value, the value of the aliased attribute in the table MUST be used as the argument to a recursive call to getElementAttribute and the result returned. This is to allow for common mis-captitalizations:
    Original property name Aliased property name
    class className
    readonly readOnly
  7. Finally, attempt the following steps in order, ceasing when one returns a value:
    1. Attempt to determine the property of the element with the given name. If this is defined and is not an object, then the named property of the object coerced to a string MUST be returned.
    2. If a Javascript call to "hasAttribute(name)" returns "true", the result of a Javascript call to "getAttribute(name)" MUST be returned.
    3. The null value MUST be returned.
DOMString id
The ID of the WebElement on which to operate.
DOMString name
The name of the property or attribute to return.

Rendering Text

All WebDriver implementations MUST support getting the displayed text of a WebElement, with excess whitespace compressed.

The following definitions are used in this section:

Whitespace
Any text that matches the ECMAScript regular expression class \s.
Whitespace excluding non-breaking spaces
Any text that matches the ECMAScript regular expression [^\S\xa0]
Block level element
A block-level element is one which is not a table cell, and whose effective CSS display style is not in the set ['inline', 'inline-block', 'inline-table', 'none', 'table-cell', 'table-column', 'table-column-group']
Horizontal whitespace characters
Horizontal whitespace characters are defined by the ECMAScript regular expression [\x20\t\u2028\u2029].

The expected return value is roughly what a text-only browser would display. The algorithm for determining this text is as follows:

Let lines equal an empty array. Then:

  1. if the element is in the head element of the document, return an empty string otherwise carry on with the algorithm below.
  2. For each descendent of node, at time of execution, in order:
    1. Get whitespace, text-transform, and then, if descendent is:
      • a node which is not displayed, do nothing
      • a [[!DOM4]] text node let text equal the nodeValue property of descendent. Then:
        1. Remove any zero-width spaces (\u200b), form feeds (\f) or vertical tab feeds (\v) from text.
        2. Canonicalize any recognized single newline sequence in text to a single newline (greedily matching (\r\n|\r|\n) to a single \n)
        3. If the parent's effective CSS whitespace style is 'normal' or 'nowrap' replace each newline (\n) in text with a single space character (\x20). If the parent's effective CSS whitespace style is 'pre' or 'pre-wrap' replace each horizontal whitespace character with a non-breaking space character (\xa0). Otherwise replace each sequence of horizontal whitespace characters except non-breaking spaces (\xa0) with a single space character
        4. Apply the parent's effective CSS text-transform style as per the CSS 2.1 specification ([[!CSS21]])
        5. If last(lines) ends with a space character and text starts with a space character, trim the first character of text.
        6. Append text to last(lines) in-place
      • an element which is displayed. If the element is a:
        • BR element: Push '' to lines and continue
        • Block-level element and if last(lines) is not '', push '' to lines.
        And then recurse depth-first to step 1 at the beginning of the algorithm with descendent set to the current element
      • If element is a TD element, or the effective CSS display style is 'table-cell', and last(lines) is not '', and last(lines) does not end with whitespace append a single space character to last(lines) [Note: Most innerText implementations append a \t here]
      • If element is a block-level element: push '' to lines
  3. The string MUST then have the white space normalised as defined in the [[!XPATH]] normalize-space function which is then returned.

Executing Javascript

Open questions: What happens if a user's JS triggers a modal dialog? Blocking seems like a reasonable idea, but there is an assumption that WebDriver is not threadsafe. What happens to unhandled JS errors? Caused by a user's JS? Caused by JS on a page? How does a user of the API obtain the list of errors? Is that list cleared upon read?

Conformance tests for this section can be found in the webdriver module under the "ecmascript" folder.

Javascript Command Parameters

readonly attribute DOMString script
The JavaScript to execute, in the form of a Function body.
readonly attribute sequence<Argument> args
The parameters to the function defined by script.

When executing Javascript, it MUST be possible to reference the args parameter using the function's arguments object. The arguments MUST be in the same order as defined in args. Each WebDriver implementation MUST preprocess the values in args using the following algorithm:

For each index, index in args, if args[index] is...

  1. a long, boolean, DOMString, or null, then let args[index] = args[index].
  2. a sequence, then recursively apply this algorithm to args[index] and assign the result to args[index].
  3. an object, then recursively apply this algorithm to each value in args[index] and assign the result to args[index].
  4. a WebElement, then:
    1. If the element's ID does not represent a Document Element, or it represents a Document Element that is no longer attached to the document's tree, then the WebDriver implementation MUST immediately abort the command and return a stale element reference error.
    2. Otherwise, let args[index] be the underlying Document Element.
  5. Otherwise WebDriver implementations MAY throw an unknown error indicating the index of the unhandled parameter but SHOULD attempt to convert the value into a dictionary.

Synchronous Javascript Execution

Argument? executeScript()
DOMString script
The script to execute.
sequence<Argument>? args
The script arguments.

When executing JavaScript, the WebDriver implementations MUST use the following algorithm:

  1. Let window be the Window object for WebDriver's current command context.
  2. Let script be the DOMString from the command's script parameter.
  3. Let fn be the Function object created by executing new Function(script);
  4. Let args be the sequence created by the pre-processing algorithm defined above.
  5. Invoke fn.apply(window, args);
  6. If the previous step errors then:
    1. Let error be the thrown value.
    2. Set the response status to javascript error.
    3. Set the response value to a dictionary, dict.
    4. If error is an Error, then set a "message" entry in dict whose value is the DOMString defined by error.message.
    5. Otherwise, set a "message" entry in dict whose value is the DOMString representation of error.
  7. Otherwise:
    1. Let result be the value returned by the function in step #5.
    2. Set the command's response status to success.
    3. Let value be the result of the following algorithm:
      1. If result is:
        1. undefined or null, return null.
        2. a long, boolean, or DOMString, return result.
        3. a Document Element, then return the corresponding WebElement for that Document Element.
        4. a Sequence <Node> nodes, then return the result of recursively applying this algorithm to result.
        5. an object, then return the dictionary created by recursively applying this algorithm to each property in result.
    4. Set the response value to value.
  8. Return the response.

Asynchronous Javascript Execution

Argument? executeAsyncScript()
DOMString script
The script to execute.
sequence<Argument>? args
The script arguments.

When executing asynchronous JavaScript, the WebDriver implementation MUST use the following algorithm:

  1. Let timeout be the value of the last "script" timeout command, or 0 if no such commands have been received.
  2. Let window be the Window object for WebDriver's current command context.
  3. Let script be the DOMString from the command's script parameter.
  4. Let fn be the Function object created by executing new Function(script);
  5. Let args be the sequence created by the pre-processing algorithm defined above.
  6. Let callback be a Function object pushed to the end of args.
  7. Register a one-shot timer on window set to fire timeout milliseconds in the future.
  8. Invoke fn.apply(window, args);
  9. If the previous step errors then:
    1. Let error be the thrown value.
    2. Set the response status to javascript error.
    3. Set the response value to a dictionary, dict.
    4. If error is an Error, then set a "message" entry in dict whose value is the DOMString defined by error.message.
    5. Otherwise, set a "message" entry in dict whose value is the DOMString representation of error.
  10. Otherwise, the WebDriver implementation MUST wait for one of the following to occur:
    1. if the one-shot timer that was set on the window fires , the WebDriver implementation MUST immediately set the response status to timeout and return.
    2. if the window fires an unload event, the WebDriver implementation MUST immediately set the response status to JavascriptError and return with the error message set to "Javascript execution context no longer exists.".
    3. if the callback function is invoked, then:
      1. Let result be the first argument passed to callback.
      2. Set the command's response status to Success.
      3. Let value be the result of the following algorithm:
        1. If result is:
          1. undefined or null, return null.
          2. a long, boolean, or DOMString, return result.
          3. a Document Element, then return the corresponding WebElement for that Document Element.
          4. a Sequence <Node> Nodes, then return the result by recursively applying this algorithm to result. WebDriver implementations SHOULD limit the recursion depth.
          5. an object, then return the dictionary created by recursively applying this algorithm to each property in result.
      4. Set the command's response value to value.
    4. Return the response.

Reporting Errors

Cookies

This section describes the interaction with cookies as described in the HTML Specification ([[!html51]]). When retrieving and setting a cookie it MUST be in the format of a Cookie.

Conformance tests for this section can be found in the webdriver module under the "cookies" folder.

Cookie

When returning Cookie objects, the server SHOULD include all optional fields it is capable of providing the information for.

DOMString name
The name of the cookie. This MUST be set.
DOMString value
The cookie value. This MUST be set.
DOMString path
The cookie path. This SHOULD be set or MUST be the null value if unknown.
DOMString domain
The domain the cookie is visible to. This SHOULD be set or MUST be the null value if unknown.
Date expiry
When the cookie expires, specified in milliseconds since midnight, January 1, 1970 UTC. This SHOULD be set or MUST be null if unknown.
boolean httpOnly
True if this represents an HTTP-Only cookie, false otherwise. If this value is missing, local ends MUST interpret this as being false.
sequence<Cookie> getCookie()
Remote ends MUST return all cookies that are available in document.cookie via Javascript. In addition, remote ends SHOULD return any HTTP-Only cookies that are associated with the current page. Possible errors that can be returned:
optional DOMString? name
The name (e.g. name=) of the cookie that needs to be returned.
void addCookie()
Set a cookie. If the cookie path is not specified, it should be set to "/". Likewise, if the domain is omitted, it should default to the current page's domain. Possible errors that can be returned:
  • invalid cookie domain - If the cookie's domain is not visible from the current page.
  • unable to set cookie If attempting to set a cookie on a page that does not support cookies (e.g. pages with mime-type text/plain)
Cookie cookie
A Cookie defining the cookie to be added. If the cookie exists already on the page update it with the relevant details. If a cookie is to be deleted set the expiration date in the past.

Timeouts

This section describes how timeouts and implicit waits are handled within WebDriver

The "timeouts" command is used to set the value of a timeout that a command can execute for.

void timeouts()
  • implicit - Set the amount of time the driver should wait when searching for elements. When searching for a single element, the driver should poll the page until an element is found or the timeout expires, whichever occurs first. When searching for multiple elements, the driver should poll the page until at least one element is found or the timeout expires, at which point it should return an empty list.
    If this command is never sent, the driver MUST default to an implicit wait of 0ms.
  • page load - Set the amount of time the driver should wait before returning when the page load stratgey is not "none". If this limit is exceeded, the get() command MUST return a "timeout" response status.
  • script - Set the amount of time the driver should wait after calling executeAsyncScript for the callback to have executed before returning a timeout Response.
DOMString type
The type of operation to set the timeout for. Valid values are: "implicit", "page load", "script"
unsigned short ms
The amount of time, in milliseconds, that time-limited commands are permitted to run.

User Input

The WebDriver API offers two ways of interacting with elements, either with a set of low-level "do as I say" commands, or a high-level "do as I mean" set of commands. The former are offered to allow precise emulation of user input. The latter are offered as a convenience to cover the common case, and can conceivably be implemented on top of the lower level primitive operations.

Interactable elements

Some user actions require the element to be interactable. The following conditions must be met for the element to be considered interactable:

Low Level Commands

The low level commands provide a mechanism for precisely stating how a user can interact with the browser.

Activation triggers generated by the WebDriver API User SHOULD be indistinguishable from those generated by a real user interacting with the browser. It is therefore recommended that input events SHOULD NOT be generated at the document level using the "createEvent" API from [[!DOM4]] or similar and should use trusted events as described in [[DOM-LEVEL-3-EVENTS]]. The order of preference for methods to implement WebDriver's emulatation of user input is:

  1. Create trusted events as described in [[DOM-LEVEL-3-EVENTS]] in the browser.
  2. Sending OS-specific input messages to the browser's window. This has the disadvantage that the browser being automated may not be properly isolated from a user accidentally modifying input device state.
  3. Use of Javascript to inject events at the document level.
  4. Use of an OS-level accessibility API. The disadvantage of this method is that the browser's window must be focused. As a result, multiple tests cannot run in parallel.

Actions

Actions are a way of executing a chain of low-level commands to emulate a user action. For example, if you wish to automate a drag and drop action in a browser, you would chain the clickAndHoldAction, moveMouseAction and buttonReleaseAction commands together. This implies chaining actions together to form a user action.

The remote side will receive the actions, and execute them, returning a response to the local end once the entire action sequence has been performed. Actions will be created by chaining the low-level commands together on either a MouseAction or TouchAction object. Each action's sequence MUST be sent over to the remote end with one call with the entire sequence in the Command when the perform() method is called.

Mouse Interactions

LEFT
The left button on a mouse
MIDDLE
The middle button on a mouse
RIGHT
The right button on a mouse
void buttonDown()
Click any mouse button (at the coordinates set by the last moveto command). Note that calling this command after calling buttondown and before calling button up (or any out-of-order interactions sequence) will yield undefined behaviour).

The possible errors for this command:

optional Button button
The button that will start the chain of events being fired. If no argument is passed in then the User Agent should default to LEFT
void buttonUp()
Releases the mouse button previously held (where the mouse is currently at). Must be called once for every buttondown command issued. See the note in click and buttondown about implications of out-of-order commands.
optional Button button
The button that will start the chain of events being fired. If no argument is passed in then the User Agent should default to LEFT
void click ()
Click any mouse button (at the coordinates set by the last moveto command). Note that calling this command after calling buttondown and before calling button up (or any out-of-order interactions sequence) will yield undefined behaviour).
optional Button button
The button that will start the chain of events being fired. If no argument is passed in then the User Agent should default to LEFT
void doubleClick ()
Double-clicks at the current mouse coordinates (set by moveTo)
void moveTo ()
Move the mouse by an offset of the specificed element. If no element is specified, the move is relative to the current mouse cursor. If an element is provided but no offset, the mouse will be moved to the center of the element. If the element is not visible, it will be scrolled into view.
optional WebElement? id
The ID of the WebElement on which to operate.
optional number x
The x-coordinate offset to send the touch event, from the top-left coordinate of the given WebElement.
optional number y
The y-coordinate offset to send the touch event, from the top-left coordinate of the given WebElement.
void perform ()
Perform should be implemented to allow for the execution of segmented Interactions, so one call to perform() will execute everything in the actions object, and provided that either release() or mouseup() have not been called, then the MouseAction or TouchAction object can still be used, so more actions can be added, and perform() can be called as many times as necessary. This enables you to use webdriver for other tasks during a gesture. For example, if you want to hold down an element, then wait for an element to appear, then mouse over onto the new element, you can use one MouseAction chain to start the mousedown event, call perform, then call findElement, then use the same MouseAction chain to add a mousemove event to the newly found element and another event to release the button, and then call perform.

action_chain = MouseAction()
action_chain.mouseDown(element1).perform()
element2 = webdriver.findElement(some_locator)
action_chain.mouseMove(element2).buttonRelease().perform()

Touch Gestures

By the nature of touch events, all touch events are dispatched using the target of the initial WebElement that receives the events. You cannot have more than one touch action active at one time with single Action chains. If multi-finger gestures are needed, use MultiAction chains.

void press()
Tap and hold in the middle of the WebElement or at coordinates (x, y) relative to the top-left corner of the target WebElement. The middle of the element is defined as the middle of the box returned by calling getBoundingClientRect on the underlying document Element, according to the [[!CSSOM-VIEW]] spec. If the element is outside the viewport (according to the [[!CSS21]] spec), the implementation SHOULD bring the element into view first. The implementation MAY invoke scrollIntoView on the underlying document Element.

The possible errors for this command:
WebElement id
The ID of the WebElement on which to operate.
optional Long x
The x-coordinate offset to send the touch event, from the top-left coordinate of the given WebElement.
optional Long y
The y-coordinate offset to send the touch event, from the top-left coordinate of the given WebElement.
void release ()
This is the equivalent of the user removing their finger from the touch screen. All the relevant events MUST fire when this happens. If there is another release() call then this should be ignored until either longPress() or press() is called again.
void moveTo ()
Drag the WebElement to another WebElement that has the id equal to what is passed in as an argument. The drag starts from the centre of the WebElement

In a chain where element1 is pressed, resulting in a touchstart event on coordinates (x1,y1), and is followed by MoveByOffset with coordinates (x2, y2), then the touchmove event will be dispatched at (x1+x2, y1+y2).



The possible errors for this command:
WebElement id
The ID of the WebElement on which to operate.
optional Long x
The x-coordinate offset to send the touch event, from the top-left coordinate of the given WebElement
optional Long y
The y-coordinate offset to send the touch event, from the top-left coordinate of the given WebElement
void tap ()
Tap in the middle of the WebElement or at coordinates (x, y) relative to the top-left corner of the target WebElement. The middle of the element is defined as the middle of the box returned by calling getBoundingClientRect on the underlying document Element, according to the [[!CSSOM-VIEW]] spec. If the element is outside the viewport (according to the [[!CSS21]] spec), the implementation SHOULD bring the element into view first. The implementation MAY invoke scrollIntoView on the underlying document Element.

If count is greater than one then the necessary events should be fired at the WebElement.

The possible errors for this command:

WebElement id
The ID of the WebElement on which to operate.
optional Long x
The x-coordinate offset to send the touch event, from the top-left coordinate of the given WebElement.
optional Long y
The y-coordinate offset to send the touch event, from the top-left coordinate of the given WebElement.
UnsignedShort? count
The number of taps that will be performed before returning to the local end. If count is null or no argument is passed in then 1 tap MUST be executed.
void wait ()
Pause execution of action chain for the given number of milliseconds. Defaults to zero so that it can be used for synchronising actions. If null is passed into the method the User Agent MUST treat it as though it was zero.
optional number? ms
The time in milliseconds to wait before performing next action
void longPress ()
Tap in the middle of the WebElement or at coordinates (x, y) relative to the top-left corner of the target WebElement and hold until the contextmenu event has fired. The middle of the element is defined as the middle of the box returned by calling getBoundingClientRect on the underlying document Element, according to the [[!CSSOM-VIEW]] spec. If the element is outside the viewport (according to the [[!CSS21]] spec), the implementation SHOULD bring the element into view first. The implementation MAY invoke scrollIntoView on the underlying document Element.

The possible errors for this command:
WebElement id
The ID of the WebElement on which to operate.
optional number x
The x-coordinate offset to send the touch event, from the top-left coordinate of the given WebElement.
optional number y
The y-coordinate offset to send the touch event, from the top-left coordinate of the given WebElement.
void cancel ()
The User Agent MUST cancel the current touch action being executed.
void perform ()
Perform should be implemented to allow for the execution of segmented Interactions, so one call to perform() will execute everything in the actions object, and provided that either release() or mouseup() have not been called, then the TouchAction object can still be used, so more actions can be added, and perform() can be called as many times as necessary. This enables you to use webdriver for other tasks during a gesture. For example, if you want to hold down an element, then wait for an element to appear, then mouse over onto the new element, you can use one TouchAction chain to start the mousedown event, call perform, then call findElement, then use the same TouchAction chain to add a mousemove event to the newly found element and another event to release the button, and then call perform.

action_chain = TouchAction()
action_chain.press().perform()
element2 = webdriver.findElement(some_locator)
action_chain.move_to(element2).release().perform()

MultiActions

Automating gestures is different from automating mouse interactions since we can have any number of fingers simultaneously acting on the touch surface. A typical 'scroll' action requires two fingers, but it is possible that we may have multi-finger gestures, or in an extrapolated case, that more than one person will operate the same touch surface, say in the case of a competitive multiplayer game. These cases mean we must allow for any number of actions occuring simulateously. This demands a MultiAction. By having a TouchAction represent the gestures of one finger, we can perform multi-finger gestures by adding these single finger gestures together, using MultiAction:

void add (TouchAction touchAction)
The local end must add the TouchAction sequence to an array which can then be serialised when perform() is called.

TouchAction touchAction
A touchAction object that has been populated with the action sequence that the user would like to execute on the remote end
void perform ()

MultiAction can take in as many TouchAction objects as needed, by using the add command. When perform is called, the remote end is responsible for executing the individual actions from each TouchAction in the right group, and in the correct order. Note, the "right group" is used to denote "in the same execution group", and is not meant to denote dispatching the events at exactly the same time. For example, to automate a gesture where one finger presses, holds and releases an element while another finger moves from one element to another:

action1 = TouchAction()
action2 = TouchAction()
action1.press(element1).wait(5).release(element1)
action2.press(element2).move(element3).release(element3)
multi = MultiAction()
multi.add(action1).add(action2)
multi.perform()

In this example, the remote end will find the first actions in each action object, and will perform them as part of the same execution group. This means the first execution group will be press(element1) and press(element2). After these events are dispatched, the remote end will will find the next execution group to perform. It will execute wait(5) and move(element3). Then it will find the next execution group, in this case, it is just release(element1) and release(element3). When there are no more actions to perform on any of the TouchAction objects, then perform() will return.

MultiAction objects do not demand that all of its member TouchActions have the same number of actions. It is possible for one TouchAction object to have more actions than another. The perform function iterates over the actions in order, and it is possible to have only one action in an execution group like so:

action = TouchAction()
action = TouchAction()
action.press(element1).wait(5).release(element1)
action.press(element2).release(element3)
multi = MultiAction()
multi.add(action1).add(action2)
multi.perform()

In this case, there will be three execution groups, the last one having only release(element1) in it.

Note: In addition to the wait command being used to indicate how long to wait, if used without arguments, it is used to indicate that nothing should be done for one TouchAction during an execution group. For example:

action1 = TouchAction()
action2 = TouchAction()
action1.press(element1).move(element2).release(element2)
action2.press(element3).wait().release(element3)
multi = MultiAction()
multi.add(action1).add(action2)
multi.perform()

Here wait() is used to indicate to the remote end that nothing should be done for action2 in the second execution group. So the second execution group will just be move(element2), but the third group will be release(element2) and release(element3)

High Level Commands

These higher level commands SHOULD be built on top of the low level commands, and implement a user friendly way of interacting with a page in a way that models common user expectations.

Clicking

void click()
Click in the middle of the WebElement instance. The middle of the element is defined as the middle of the box returned by calling getBoundingClientRect on the underlying document Element, according to the [[!CSSOM-VIEW]] spec. If the element is outside the viewport (according to the [[!CSS21]] spec), the implementation SHOULD bring the element into view first. The implementation MAY invoke scrollIntoView on the underlying document Element. The element MUST be displayed. See the note below for when the element is obscured by another element. Exceptions:
  • Links (A elements): Clicking happens in the middle of the first displayed bounding client rectangle. This is to overcome overflowing links where the middle of the bounding client rectangle does not actually fall on a clickable part of the link.
  • SELECT elements without the "multiple" attribute set. Clicking on the select element SHOULD open the drop down menu. The next click, on any element, MUST close this menu.
  • Clicking directly on an OPTION element (without clicking on the parent SELECT element previously) MUST open a selection menu, as if the SELECT option was clicked first, then click on the OPTION before finally closing the SELECT element's menu. The SELECT menu MUST be closed once the action is complete.

The possible errors for this command:

This command MUST use either the mouse or touch mechanisms for emulating the user input. In the case where the browser being automated supports only mouse input or both mouse and touch input, the low-level mouse mechanisms MUST be used. If the browser only supports touch input, the low level touch inputs MUST be used.

As the goal is to emulate users as closely as possible, the implementation SHOULD NOT allow clicking on elements that are obscured by other elements. If the implementation forbids clicking on obscured elements, an element not visible response MUST be returned and this SHOULD have an explantory message explaining the reason. The implementation SHOULD try to scroll the element into view, but in case it is fully obscured, it SHOULD NOT be clickable.

Touch

This section defines the low level commands used when manipulating touch-enabled devices. These are the building blocks of touch interaction chains.

Capability NameType
touchEnabledboolean


void tap ()
Tap in the middle of the WebElement. The middle of the element is defined as the middle of the box returned by calling getBoundingClientRect on the underlying document Element, according to the [[!CSSOM-VIEW]] spec. If the element is outside the viewport (according to the [[!CSS21]] spec), the implementation SHOULD bring the element into view first. The implementation MAY invoke scrollIntoView on the underlying document Element. Exceptions:
  • Links (A elements): Clicking happens in the middle of the first displayed bounding client rectangle. This is to overcome overflowing links where the middle of the bounding client rectangle does not actually fall on a clickable part of the link.
  • SELECT elements without the "multiple" attribute set. Clicking on the select element SHOULD open the drop down menu. The next click, on any element, MUST close this menu.
  • Clicking directly on an OPTION element (without clicking on the parent SELECT element previously) MUST open a selection menu, as if the SELECT option was clicked first, then click on the OPTION before finally closing the SELECT element's menu. The SELECT menu MUST be closed once the action is complete.

The possible errors for this command:

Typing keys

A requirement for key-based interaction with an element is that it is interactable. Typing into an element is permitted if one of the following conditions is met:

  • The element is focusable as defined in the editing section of the [[!html51]] spec.
  • The element is allowed to be the activeElement. In addition to focusable elements, this allows typing to the BODY element.
  • In an HTML document, the element is editable as a result of having its contentEditable attribute set or the containing document is in designMode.
  • The underlying browser implementation would allow keyboard input to directed to the element (eg. an HTML document with a DIV marked as being contentEditable)

Prior to any keyboard interaction, an attempt to shift focus to the element MUST be attempted if the element does not currently have the focus. This is the case if one of the following holds:

  • The element is not already the document's active element.
  • The owner document of the element to be interacted with is not the focused document.

In case focusing is needed, the implementation MUST follow the focusing steps as described in the focus management section of the [[!html51]] spec. The focus MUST NOT leave the element at the end of the interaction, other than as a result of the interaction itself (i.e. when the tab key is sent).

void clear()
Clears the value of the element.
void sendKeys(string[] keysToSend)
Sends a sequence of keyboard events representing the keys in the keysToSend parameter.

Caret positioning: If focusing was needed, after following the focusing steps, the caret MUST be positioned at the end of the text currently in the element. At the end of the interaction, the caret MUST be positioned at the end of the typed text sequence, unless the keys sent position it otherwise (e.g. using the LEFT key).

There are four different types of keys that are emulated:

  • Character literals - lower-case symbols.
  • Uppercase letters and symbols requiring the SHIFT key for typing.
  • Modifier keys
  • Special keys
The rest of this section details the values used to represent the different keys, as well as the expected behaviour for each key type.

When emulating user input, the implementation MUST generate the same sequence of events that would have been produced if a real user was sitting in front of the keyboard and typing the sequence of characters. In cases where there is more than one way to type this sequence, the implementation MUST choose one of the valid ways. For example, typing AB may be achieved by:

  • Holding down the Shift key
  • Pressing the letter 'a'
  • Pressing the letter 'b'
  • Releasing the Shift key
Alternatively, it can be achieved by:
  • Holding down the Shift key
  • Pressing the letter 'a'
  • Releasing the Shift key
  • Holding down the Shift key
  • Pressing the letter 'b'
  • Releasing the Shift key

Or by simply turning on the CAPS LOCK first.

The implementation MAY use the following algorithm to generate the events. If the implementation is using a different algorithm, it MUST adhere to the requirements listed below.

For each key, key in keysToSend, do

  1. If key is a lower-case symbol:
    1. If the Shift key is not pressed:
      1. Generate a sequence of keydown, keypress and keyup events with key as the character to emulate
    2. else (The Shift key is pressed)
      1. let uppercaseKey be the upper-case character matching key
      2. Generate a sequence of keydown, keypress and keyup events with uppercaseKey as the character to emulate
  2. Else if key is an upper-case symbol:
    1. If the Shift key is not pressed:
      1. Generate a keydown event of the Shift key.
      2. Generate a sequence of keydown, keypress and keyup events with key as the character to emulate
      3. Generate a keyup event of the Shift key.
    2. else (The Shift key is pressed)
      1. Generate a sequence of keydown, keypress and keyup events with key as the character to emulate
  3. Else if key represents a modifier key:
    1. let modifier be the modifier key represented by key
    2. If modifier is currently held down:
      1. Generate a keyup event of modifier
    3. Else:
      1. Generate a keydown event of modifier
    4. Maintain this key state and use it to modify the input until it is pressed again.
  4. Else if key represents the NULL key:
    1. Generate keyup events of all modifier keys currently held down.
    2. All modifier keys are now assumed to be released.
  5. Else if key represents a special key:
    1. Translate key to the special key it represents
    2. Generate a sequence of keydown, keypress and keyup events for the special key.

Once keyboard input is complete, an implicit NULL key is sent unless the final character is the NULL key.

Any implementation MUST comply with these requirements:

  • For uppercase letters and symbols that require the Shift key to be pressed, there are two options:
    • A single Shift keydown event is generated before the entire sequence of uppercase letters.
    • Before each such letter or symbol, a Shift keydown event is generated. After each letter or symbol, a Shift keyup event is generated.
  • A user-specified Shift press implies capitalization of all following characters.
  • If a user-specified Shift press precedes uppercase letters and symbols, a second Shift keydown event MUST NOT be generated. In that case, a Shift keyup event MUST NOT be generated implicitly by the implementation.
  • The NULL key releases all currently held down modifier keys.
  • The state of all modifier keys must be reset at the end of each sendKeys call and the appropriate keyup events generated

Character types

The keysToSend parameter contains a mix of printable characters and pressable keys that aren't text. Pressable keys that aren't text are stored in the Unicode PUA (Private Use Area) code points, 0xE000-0xF8FF. The following table describes the mapping between PUA and key:

Key Code Type
NULL\uE000NULL
CANCEL\uE001Special key
HELP\uE002Special key
BACK_SPACE\uE003Special key
TAB\uE004Special key
CLEAR\uE005Special key
RETURN\uE006Special key
ENTER\uE007Special key
SHIFT\uE008Modifier
LEFT_SHIFT\uE008Modifier
CONTROL\uE009Modifier
LEFT_CONTROL\uE009Modifier
ALT\uE00AModifier
LEFT_ALT\uE00AModifier
PAUSE\uE00BSpecial key
ESCAPE\uE00CSpecial key
SPACE\uE00DSpecial key
PAGE_UP\uE00ESpecial key
PAGE_DOWN\uE00FSpecial key
END\uE010Special key
HOME\uE011Special key
LEFT\uE012Special key
ARROW_LEFT\uE012Special key
UP\uE013Special key
ARROW_UP\uE013Special key
RIGHT\uE014Special key
ARROW_RIGHT\uE014Special key
DOWN\uE015Special key
ARROW_DOWN\uE015Special key
INSERT\uE016Special key
DELETE\uE017Special key
SEMICOLON\uE018Special key
EQUALS\uE019Special key
NUMPAD0\uE01ASpecial key
NUMPAD1\uE01BSpecial key
NUMPAD2\uE01CSpecial key
NUMPAD3\uE01DSpecial key
NUMPAD4\uE01ESpecial key
NUMPAD5\uE01FSpecial key
NUMPAD6\uE020Special key
NUMPAD7\uE021Special key
NUMPAD8\uE022Special key
NUMPAD9\uE023Special key
MULTIPLY\uE024Special key
ADD\uE025Special key
SEPARATOR\uE026Special key
SUBTRACT\uE027Special key
DECIMAL\uE028Special key
DIVIDE\uE029Special key
F1\uE031Special key
F2\uE032Special key
F3\uE033Special key
F4\uE034Special key
F5\uE035Special key
F6\uE036Special key
F7\uE037Special key
F8\uE038Special key
F9\uE039Special key
F10\uE03ASpecial key
F11\uE03BSpecial key
F12\uE03CSpecial key
META\uE03DSpecial key
COMMAND\uE03DSpecial key
ZENKAKU_HANKAKU\uE040Special key

The keys considered upper-case symbols are either defined by the current keyboard locale or are derived from the US 104 keys Windows keyboard layout, which are:

  • A - Z
  • !$^*()+{}:?|~@#%_\" & < >

When the user input is emulated natively (see note below), the implementation SHOULD use the current keyboard locale to determine which symbols are upper case. In all other cases, the implementation MUST use the US 104 key Windows keyboard layout to determine those symbols.

The state of the physical keyboard MUST NOT affect emulated user input.

Internationalized input

Non-latin symbols: TBD

Complex scripts using Input Method Editor (IME): TBD

Modals

This section describes how modal dialogs should be handled using the WebDriver API.

Conformance tests for this section can be found in the webdriver module under the "modals" folder.

window.alert, window.prompt and window.confirm

When the remote end is has a modal dialog such as those produced from window.alert, window.prompt and window.confirm it should allow the interrogation of the dialogues as using the following interface.

void dismiss()
This will dismiss the modal. If the modal is an alert, this MUST be equivalent to calling accept() on the dialog. If no alert is present a no such alert error MUST be raised.
void accept()
This will accept the modal. If the modal is from a window.prompt it is the equivalent of clicking the OK button. If no modal is present then a no such alert error MUST be raised.
DOMString getText()
This will return the text that is currently in the modal.
void sendKeys()
This MUST act in the same manner as in sendKeys to an element. If the modal has no means for text input it should throw a Element not visible error. If no modal is present then a no such alert error MUST be raised.
DOMString keysToSend
Keys to send to the modal. If the modal has no means of acceptiing text input it MUST raise a element not visible error

If a modal dialog is created from a onbeforeunload event the remote end MUST handle the dialog by either using accept or dismiss. These calls should either come from the local end or should be handled as an unexpected modal dialog as described below.

The remote end SHOULD have a mechanism to allow unexpected modal dialogs to be closed to prevent the remote end from becoming unusable. The default for this should be dismiss. The local end SHOULD allow a capability to be set that allows the default value to be overridden with accept. The local end SHOULD also allow setting the default behaviour to wait for a command to handle the modal. If the next command does not interact with the modal it MUST return a Unexpected alert open error to the local end.

Modal Windows

If a browser supports Modal Windows, as created by document.showModalDialog(), it MUST support handling of Modal Windows via the WebDriver API. Model Windows can then be iterated over in the same approach as normal windows.

If close() is called from the client end to the parent window that has modal windows open then the remote end SHOULD iterate over modal dialogs closing them before it closes the remaining windows so that it does not block the future commands to the remote end

Screenshots

Screenshots are a powerful mechanism for providing information to users of WebDriver, particularly once a particular WebDriver instance has been disposed of. In different circumstances, users want different types of screenshot. Note that the WebDriver spec does not provide a mechanism for taking a screenshot of the entire screen.

In all cases, screenshots MUST be returned as lossless PNG images encoded using Base64. Local ends MUST provide the user with access to the PNG images without requiring the user to decode the Base64. This access MUST be via at least one of a binary blob or a file.

All commands within this section are implemented using the "TakesScreenshot" interface:

DOMString takeScreenshot()
Take a screenshot as determined by the CommandName and return a lossless PNG encoded using Base64.

The possible errors for this command:

optional WebElement? element
The ID of the WebElement on which to operate. If this argument is not populated or null

Current Window

Capability NameType
takesScreenshotboolean

If this capability is supported, local end MUST add the TakesScreenshot interface to the WebDriver interface.

This command will take a screenshot of the current window. Implementations of the remote end SHOULD capture the entire Document, even if this would require a user to scroll the browser window. That is, the returned PNG SHOULD have the same width and height as returned by a call to getSize of the BODY element and MUST contain all visible content on the page, and this SHOULD be done without resizing the browser window. If the remote end is unable to capture the entire Document, then the part of the Document currently displayed in UI of the browser MUST be captured without additional chrome such as scrollbars and browser chrome.

One way to think of capturing the entire Document is that the user has an infinitely large monitor and has resized the window to allow all content to be visible. One of those monitors would be very cool.

Nested frames MUST be sized as if the user has resized the window to the dimensions of the PNG being returned. This often means that not all potentially visible content within the nested frames is captured.

Remote ends MUST NOT attempt to track changes in window size as the screenshot is being taken. In particular this means that in the case of a page that makes use of "infinite scrolling" (where an AJAX call is used to populate additional content as the user scrolls down) or in some other way resizes content as the window size is changed only the content that was originally contained in the Document when the command is executed will be captured.

Element

Capability NameType
takeElementScreenshotboolean

If this capability is supported, local end MUST add the TakesScreenshot interface to the WebElement interface.

Remote ends SHOULD take a screenshot of the area bounded by the clientBoundingRect of the Document element represented by the WebElement, returning it as a Base64 encoded, lossless PNG. Local ends MUST make the PNG available directly to the user as at least one of a binary blob or a file. If the remote end cannot capture the entire clientBoundingRect, they MUST scroll as much of the element into the current browser viewport as possible and capture the maximum visible area without additional browser chrome.

If the WebElement represents a FRAME or IFRAME element, this is equivalent of taking a screenshot of the frame's BODY element.

Handling non-HTML Content

Non-HTML content MUST be treated in the same manner as HTML if the Non-HTML if the browser creates a Document object for the content of the document. If a Document Object is not created then how it handled SHOULD be non-normative

XML

This section describes XML documents as described in [[XML10]]. For XHTML documents the remote end should treat them as HTML documents and not have the caveats, below, applied.

Since Browsers create a Document object for XML pages it is expected that we can interogate them as a normal HTML document however the following differences should be noted:

SVG

This section described SVG documents in a browser as described by [[SVG2]]. Since browsers create a Document tree for SVG documents it is expected that WebDriver can interrogate the Document as a normal HTML document.

Working with Accessibility APIs

Many accessibility APIs represent the UI as a series of nested nodes. It is possible to map these nodes to WebElement instances. In order to function properly, it is likely that additional element locating strategies will be required.

This is one way in which it might be possible to test mobile applications that marry a native wrapper around a series of HTML views.

Extending the Protocol

Vendor-specific Extensions

The WebDriver protocol is designed to allow extension to meet vendor-specific needs, such as interacting with the chrome of a browser. Vendor-specific extensions are implemented by appending a prefix to the command name. This should be of the form:

        '-' + vendor prefix + '-' + command name
      

For example: "-o-open-bookmark" or "-moz-install-extension".

It is guaranteed that no command name in this or future versions of the WebDriver specification will be prefixed with a leading dash.

It is suggested that vendors use the same vendor identifier as in [[!CSS21]] (notably, section 4.1.2.2)

Extending the JSON/HTTP Protocol

This section is non-normative.

The wire protocol (see Appendix XXX) makes use of URLs to distinguish command names. When extending the protocol by adding new URLs, vendors should use their vendor prefix without additional characters to prevent any potential clashes with other implementations. This leads to URLs of the form: http://host:port/session/somekey/moz/extension.

Command Summary

This is an exhaustive list of the commands listed in this specification.

Capabilities

This section is non-normative.

Capabilities are used by WebDriver implementations to enumerate the parts of this specification that they support. They are also used when establishing a new session to descrive the required or desired capabilities. This appendix collects the capabilities mentioned in this spec into one place.

Command Format

This is essentially the content at the start of the json wire protocol

Thread Safety

There is no requirement for local or remote implementations to be thread safe. Local ends SHOULD support serialized access from multiple threads.

Logging

Security and Privacy

The following section is non-normative.

Privacy

The local end SHOULD create a new profile when creating a new session. If a new profile can be created it MUST NOT copy the profile in use and MUST create a fresh profile. By creating a new profile the user agent will prevent any unexpected behaviour when the remote end is accessing content.

Security

The remote end SHOULD have a specific command line argument when starting the browser up if it is connecting to a browser (e.g. firefox.exe --webdriver ) and SHOULD have user agent configuration preference that is tested when the user agent starts up

When the local end creates a new session the remote end MUST limit connections to 127.0.0.1 IPV4 address or ::1 IPV6 address. This will prevent new sessions being created without having a specific proxy installed on the remote end.

Some devices will require the device to be placed into a 'developer' mode. This allows unix sockets to be forwarded on to the device while the device is connected to a host. An example of this is if the local end needed to go through a remote debugger protocol.

If any of these fail then a session not created error MUST be thrown when the local end tries to create a new session.

Fingerprinting

The following will allow web sites to know that the user interacting with the content is not a real user. This can be used to prevent denial of service attacks.

When the user agent creates a new session it MUST add a read only property to window.navigator.webdriver. The value should be set to true when WebDriver has an active session. When WebDriver does not have an active session then the value is equal to false or the property is removed.

Mapping to HTTP and JSON

Acknowledgements

Many thanks to Robin Berjon for making our lives so much easier with his cool tool. Thanks to Jason Leyba, Malcolm Rowe and Ross Patterson for proof reading and suggesting areas for improvement. Thanks to Jason Leyba, Eran Messeri, Daniel Wagner-Hall, Malini Das and Luke Inman-Semerau for contributing sections to this document. Also thanks to the following people for their contribution of patches and test cases:

These links are only here until we have fixed ReSpec.js to avoid creating anchors to things that don't exist.