Path: blob/trunk/javascript/selenium-webdriver/chromium.js
2884 views
// Licensed to the Software Freedom Conservancy (SFC) under one1// or more contributor license agreements. See the NOTICE file2// distributed with this work for additional information3// regarding copyright ownership. The SFC licenses this file4// to you under the Apache License, Version 2.0 (the5// "License"); you may not use this file except in compliance6// with the License. You may obtain a copy of the License at7//8// http://www.apache.org/licenses/LICENSE-2.09//10// Unless required by applicable law or agreed to in writing,11// software distributed under the License is distributed on an12// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY13// KIND, either express or implied. See the License for the14// specific language governing permissions and limitations15// under the License.1617/**18* @fileoverview Defines an abstract {@linkplain Driver WebDriver} client for19* Chromium-based web browsers. These classes should not be instantiated20* directly.21*22* There are three primary classes exported by this module:23*24* 1. {@linkplain ServiceBuilder}: configures the25* {@link selenium-webdriver/remote.DriverService remote.DriverService}26* that manages a WebDriver server child process.27*28* 2. {@linkplain Options}: defines configuration options for each new Chromium29* session, such as which {@linkplain Options#setProxy proxy} to use,30* what {@linkplain Options#addExtensions extensions} to install, or31* what {@linkplain Options#addArguments command-line switches} to use when32* starting the browser.33*34* 3. {@linkplain Driver}: the WebDriver client; each new instance will control35* a unique browser session with a clean user profile (unless otherwise36* configured through the {@link Options} class).37*38* let chrome = require('selenium-webdriver/chrome');39* let {Builder} = require('selenium-webdriver');40*41* let driver = new Builder()42* .forBrowser('chrome')43* .setChromeOptions(new chrome.Options())44* .build();45*46* __Customizing the Chromium WebDriver Server__ <a id="custom-server"></a>47*48* Subclasses of {@link Driver} are expected to provide a static49* getDefaultService method. By default, this method will be called every time50* a {@link Driver} instance is created to obtain the default driver service51* for that specific browser (e.g. Chrome or Chromium Edge). Subclasses are52* responsible for managing the lifetime of the default service.53*54* You may also create a {@link Driver} with its own driver service. This is55* useful if you need to capture the server's log output for a specific session:56*57* let chrome = require('selenium-webdriver/chrome');58*59* let service = new chrome.ServiceBuilder()60* .loggingTo('/my/log/file.txt')61* .enableVerboseLogging()62* .build();63*64* let options = new chrome.Options();65* // configure browser options ...66*67* let driver = chrome.Driver.createSession(options, service);68*69* @module selenium-webdriver/chromium70*/7172'use strict'7374const http = require('./http')75const io = require('./io')76const { Capabilities, Capability } = require('./lib/capabilities')77const command = require('./lib/command')78const error = require('./lib/error')79const Symbols = require('./lib/symbols')80const webdriver = require('./lib/webdriver')81const remote = require('./remote')82const { getBinaryPaths } = require('./common/driverFinder')8384/**85* Custom command names supported by Chromium WebDriver.86* @enum {string}87*/88const Command = {89LAUNCH_APP: 'launchApp',90GET_NETWORK_CONDITIONS: 'getNetworkConditions',91SET_NETWORK_CONDITIONS: 'setNetworkConditions',92DELETE_NETWORK_CONDITIONS: 'deleteNetworkConditions',93SEND_DEVTOOLS_COMMAND: 'sendDevToolsCommand',94SEND_AND_GET_DEVTOOLS_COMMAND: 'sendAndGetDevToolsCommand',95SET_PERMISSION: 'setPermission',96GET_CAST_SINKS: 'getCastSinks',97SET_CAST_SINK_TO_USE: 'setCastSinkToUse',98START_CAST_DESKTOP_MIRRORING: 'startDesktopMirroring',99START_CAST_TAB_MIRRORING: 'setCastTabMirroring',100GET_CAST_ISSUE_MESSAGE: 'getCastIssueMessage',101STOP_CASTING: 'stopCasting',102}103104/**105* Creates a command executor with support for Chromium's custom commands.106* @param {!Promise<string>} url The server's URL.107* @param vendorPrefix108* @return {!command.Executor} The new command executor.109*/110function createExecutor(url, vendorPrefix) {111const agent = new http.Agent({ keepAlive: true })112const client = url.then((url) => new http.HttpClient(url, agent))113const executor = new http.Executor(client)114configureExecutor(executor, vendorPrefix)115return executor116}117118/**119* Configures the given executor with Chromium-specific commands.120* @param {!http.Executor} executor the executor to configure.121*/122function configureExecutor(executor, vendorPrefix) {123executor.defineCommand(Command.LAUNCH_APP, 'POST', '/session/:sessionId/chromium/launch_app')124executor.defineCommand(Command.GET_NETWORK_CONDITIONS, 'GET', '/session/:sessionId/chromium/network_conditions')125executor.defineCommand(Command.SET_NETWORK_CONDITIONS, 'POST', '/session/:sessionId/chromium/network_conditions')126executor.defineCommand(Command.DELETE_NETWORK_CONDITIONS, 'DELETE', '/session/:sessionId/chromium/network_conditions')127executor.defineCommand(Command.SEND_DEVTOOLS_COMMAND, 'POST', '/session/:sessionId/chromium/send_command')128executor.defineCommand(129Command.SEND_AND_GET_DEVTOOLS_COMMAND,130'POST',131'/session/:sessionId/chromium/send_command_and_get_result',132)133executor.defineCommand(Command.SET_PERMISSION, 'POST', '/session/:sessionId/permissions')134executor.defineCommand(Command.GET_CAST_SINKS, 'GET', `/session/:sessionId/${vendorPrefix}/cast/get_sinks`)135executor.defineCommand(136Command.SET_CAST_SINK_TO_USE,137'POST',138`/session/:sessionId/${vendorPrefix}/cast/set_sink_to_use`,139)140executor.defineCommand(141Command.START_CAST_DESKTOP_MIRRORING,142'POST',143`/session/:sessionId/${vendorPrefix}/cast/start_desktop_mirroring`,144)145executor.defineCommand(146Command.START_CAST_TAB_MIRRORING,147'POST',148`/session/:sessionId/${vendorPrefix}/cast/start_tab_mirroring`,149)150executor.defineCommand(151Command.GET_CAST_ISSUE_MESSAGE,152'GET',153`/session/:sessionId/${vendorPrefix}/cast/get_issue_message`,154)155executor.defineCommand(Command.STOP_CASTING, 'POST', `/session/:sessionId/${vendorPrefix}/cast/stop_casting`)156}157158/**159* Creates {@link selenium-webdriver/remote.DriverService} instances that manage160* a WebDriver server in a child process.161*/162class ServiceBuilder extends remote.DriverService.Builder {163/**164* @param {string=} exe Path to the server executable to use. Subclasses165* should ensure a valid path to the appropriate exe is provided.166*/167constructor(exe) {168super(exe)169this.setLoopback(true) // Required170}171172/**173* Sets which port adb is listening to. _The driver will connect to adb174* if an {@linkplain Options#androidPackage Android session} is requested, but175* adb **must** be started beforehand._176*177* @param {number} port Which port adb is running on.178* @return {!ServiceBuilder} A self reference.179*/180setAdbPort(port) {181return this.addArguments('--adb-port=' + port)182}183184/**185* Sets the path of the log file the driver should log to. If a log file is186* not specified, the driver will log to stderr.187* @param {string} path Path of the log file to use.188* @return {!ServiceBuilder} A self reference.189*/190loggingTo(path) {191return this.addArguments('--log-path=' + path)192}193194/**195* Enables Chrome logging.196* @returns {!ServiceBuilder} A self reference.197*/198enableChromeLogging() {199return this.addArguments('--enable-chrome-logs')200}201202/**203* Enables verbose logging.204* @return {!ServiceBuilder} A self reference.205*/206enableVerboseLogging() {207return this.addArguments('--verbose')208}209210/**211* Sets the number of threads the driver should use to manage HTTP requests.212* By default, the driver will use 4 threads.213* @param {number} n The number of threads to use.214* @return {!ServiceBuilder} A self reference.215*/216setNumHttpThreads(n) {217return this.addArguments('--http-threads=' + n)218}219220/**221* @override222*/223setPath(path) {224super.setPath(path)225return this.addArguments('--url-base=' + path)226}227}228229/**230* Class for managing WebDriver options specific to a Chromium-based browser.231*/232class Options extends Capabilities {233/**234* @param {(Capabilities|Map<string, ?>|Object)=} other Another set of235* capabilities to initialize this instance from.236*/237constructor(other = undefined) {238super(other)239240/** @private {!Object} */241this.options_ = this.get(this.CAPABILITY_KEY) || {}242243this.setBrowserName(this.BROWSER_NAME_VALUE)244this.set(this.CAPABILITY_KEY, this.options_)245}246247/**248* Add additional command line arguments to use when launching the browser.249* Each argument may be specified with or without the "--" prefix250* (e.g. "--foo" and "foo"). Arguments with an associated value should be251* delimited by an "=": "foo=bar".252*253* @param {...(string|!Array<string>)} args The arguments to add.254* @return {!Options} A self reference.255*/256addArguments(...args) {257let newArgs = (this.options_.args || []).concat(...args)258if (newArgs.length) {259this.options_.args = newArgs260}261return this262}263264/**265* Sets the address of a Chromium remote debugging server to connect to.266* Address should be of the form "{hostname|IP address}:port"267* (e.g. "localhost:9222").268*269* @param {string} address The address to connect to.270* @return {!Options} A self reference.271*/272debuggerAddress(address) {273this.options_.debuggerAddress = address274return this275}276277/**278* Sets the initial window size.279*280* @param {{width: number, height: number}} size The desired window size.281* @return {!Options} A self reference.282* @throws {TypeError} if width or height is unspecified, not a number, or283* less than or equal to 0.284*/285windowSize({ width, height }) {286function checkArg(arg) {287if (typeof arg !== 'number' || arg <= 0) {288throw TypeError('Arguments must be {width, height} with numbers > 0')289}290}291292checkArg(width)293checkArg(height)294return this.addArguments(`window-size=${width},${height}`)295}296297/**298* List of Chrome command line switches to exclude that ChromeDriver by default299* passes when starting Chrome. Do not prefix switches with "--".300*301* @param {...(string|!Array<string>)} args The switches to exclude.302* @return {!Options} A self reference.303*/304excludeSwitches(...args) {305let switches = (this.options_.excludeSwitches || []).concat(...args)306if (switches.length) {307this.options_.excludeSwitches = switches308}309return this310}311312/**313* Add additional extensions to install when launching the browser. Each extension314* should be specified as the path to the packed CRX file, or a Buffer for an315* extension.316* @param {...(string|!Buffer|!Array<(string|!Buffer)>)} args The317* extensions to add.318* @return {!Options} A self reference.319*/320addExtensions(...args) {321let extensions = this.options_.extensions || new Extensions()322extensions.add(...args)323if (extensions.length) {324this.options_.extensions = extensions325}326return this327}328329/**330* Sets the path to the browser binary to use. On Mac OS X, this path should331* reference the actual Chromium executable, not just the application binary332* (e.g. "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome").333*334* The binary path can be absolute or relative to the WebDriver server335* executable, but it must exist on the machine that will launch the browser.336*337* @param {string} path The path to the browser binary to use.338* @return {!Options} A self reference.339*/340setBinaryPath(path) {341this.options_.binary = path342return this343}344345/**346* Sets whether to leave the started browser process running if the controlling347* driver service is killed before {@link webdriver.WebDriver#quit()} is348* called.349* @param {boolean} detach Whether to leave the browser running if the350* driver service is killed before the session.351* @return {!Options} A self reference.352*/353detachDriver(detach) {354this.options_.detach = detach355return this356}357358/**359* Sets the user preferences for Chrome's user profile. See the "Preferences"360* file in Chrome's user data directory for examples.361* @param {!Object} prefs Dictionary of user preferences to use.362* @return {!Options} A self reference.363*/364setUserPreferences(prefs) {365this.options_.prefs = prefs366return this367}368369/**370* Sets the performance logging preferences. Options include:371*372* - `enableNetwork`: Whether or not to collect events from Network domain.373* - `enablePage`: Whether or not to collect events from Page domain.374* - `enableTimeline`: Whether or not to collect events from Timeline domain.375* Note: when tracing is enabled, Timeline domain is implicitly disabled,376* unless `enableTimeline` is explicitly set to true.377* - `traceCategories`: A comma-separated string of Chromium tracing378* categories for which trace events should be collected. An unspecified379* or empty string disables tracing.380* - `bufferUsageReportingInterval`: The requested number of milliseconds381* between DevTools trace buffer usage events. For example, if 1000, then382* once per second, DevTools will report how full the trace buffer is. If383* a report indicates the buffer usage is 100%, a warning will be issued.384*385* @param {{enableNetwork: boolean,386* enablePage: boolean,387* enableTimeline: boolean,388* traceCategories: string,389* bufferUsageReportingInterval: number}} prefs The performance390* logging preferences.391* @return {!Options} A self reference.392*/393setPerfLoggingPrefs(prefs) {394this.options_.perfLoggingPrefs = prefs395return this396}397398/**399* Sets preferences for the "Local State" file in Chrome's user data400* directory.401* @param {!Object} state Dictionary of local state preferences.402* @return {!Options} A self reference.403*/404setLocalState(state) {405this.options_.localState = state406return this407}408409/**410* Sets the name of the activity hosting a Chrome-based Android WebView. This411* option must be set to connect to an [Android WebView](412* https://chromedriver.chromium.org/getting-started/getting-started---android)413*414* @param {string} name The activity name.415* @return {!Options} A self reference.416*/417androidActivity(name) {418this.options_.androidActivity = name419return this420}421422/**423* Sets the device serial number to connect to via ADB. If not specified, the424* WebDriver server will select an unused device at random. An error will be425* returned if all devices already have active sessions.426*427* @param {string} serial The device serial number to connect to.428* @return {!Options} A self reference.429*/430androidDeviceSerial(serial) {431this.options_.androidDeviceSerial = serial432return this433}434435/**436* Sets the package name of the Chrome or WebView app.437*438* @param {?string} pkg The package to connect to, or `null` to disable Android439* and switch back to using desktop browser.440* @return {!Options} A self reference.441*/442androidPackage(pkg) {443this.options_.androidPackage = pkg444return this445}446447/**448* Sets the process name of the Activity hosting the WebView (as given by449* `ps`). If not specified, the process name is assumed to be the same as450* {@link #androidPackage}.451*452* @param {string} processName The main activity name.453* @return {!Options} A self reference.454*/455androidProcess(processName) {456this.options_.androidProcess = processName457return this458}459460/**461* Sets whether to connect to an already-running instead of the specified462* {@linkplain #androidProcess app} instead of launching the app with a clean463* data directory.464*465* @param {boolean} useRunning Whether to connect to a running instance.466* @return {!Options} A self reference.467*/468androidUseRunningApp(useRunning) {469this.options_.androidUseRunningApp = useRunning470return this471}472473/**474* Sets the path to the browser's log file. This path should exist on the machine475* that will launch the browser.476* @param {string} path Path to the log file to use.477* @return {!Options} A self reference.478*/479setBrowserLogFile(path) {480this.options_.logPath = path481return this482}483484/**485* Sets the directory to store browser minidumps in. This option is only486* supported when the driver is running on Linux.487* @param {string} path The directory path.488* @return {!Options} A self reference.489*/490setBrowserMinidumpPath(path) {491this.options_.minidumpPath = path492return this493}494495/**496* Configures the browser to emulate a mobile device. For more information, refer497* to the ChromeDriver project page on [mobile emulation][em]. Configuration498* options include:499*500* - `deviceName`: The name of a pre-configured [emulated device][devem]501* - `width`: screen width, in pixels502* - `height`: screen height, in pixels503* - `pixelRatio`: screen pixel ratio504*505* __Example 1: Using a Pre-configured Device__506*507* let options = new chrome.Options().setMobileEmulation(508* {deviceName: 'Google Nexus 5'});509*510* let driver = chrome.Driver.createSession(options);511*512* __Example 2: Using Custom Screen Configuration__513*514* let options = new chrome.Options().setMobileEmulation({deviceMetrics: {515* width: 360,516* height: 640,517* pixelRatio: 3.0518* }});519*520* let driver = chrome.Driver.createSession(options);521*522*523* [em]: https://chromedriver.chromium.org/mobile-emulation524* [devem]: https://developer.chrome.com/devtools/docs/device-mode525*526* @param {?({deviceName: string}|527* {width: number, height: number, pixelRatio: number})} config The528* mobile emulation configuration, or `null` to disable emulation.529* @return {!Options} A self reference.530*/531setMobileEmulation(config) {532this.options_.mobileEmulation = config533return this534}535536/**537* Sets a list of the window types that will appear when getting window538* handles. For access to <webview> elements, include "webview" in the list.539* @param {...(string|!Array<string>)} args The window types that will appear540* when getting window handles.541* @return {!Options} A self reference.542*/543windowTypes(...args) {544let windowTypes = (this.options_.windowTypes || []).concat(...args)545if (windowTypes.length) {546this.options_.windowTypes = windowTypes547}548return this549}550551/**552* Enable bidi connection553* @returns {!Capabilities}554*/555enableBidi() {556return this.set('webSocketUrl', true)557}558}559560/**561* A list of extensions to install when launching the browser.562*/563class Extensions {564constructor() {565this.extensions = []566}567568/**569* @return {number} The length of the extensions list.570*/571get length() {572return this.extensions.length573}574575/**576* Add additional extensions to install when launching the browser. Each577* extension should be specified as the path to the packed CRX file, or a578* Buffer for an extension.579*580* @param {...(string|!Buffer|!Array<(string|!Buffer)>)} args The581* extensions to add.582*/583add(...args) {584this.extensions = this.extensions.concat(...args)585}586587/**588* @return {!Object} A serialized representation of this Extensions object.589*/590[Symbols.serialize]() {591return this.extensions.map(function (extension) {592if (Buffer.isBuffer(extension)) {593return extension.toString('base64')594}595return io.read(/** @type {string} */ (extension)).then((buffer) => buffer.toString('base64'))596})597}598}599600/**601* Creates a new WebDriver client for Chromium-based browsers.602*/603class Driver extends webdriver.WebDriver {604/**605* Creates a new session with the WebDriver server.606*607* @param {(Capabilities|Options)=} caps The configuration options.608* @param {(remote.DriverService|http.Executor)=} opt_serviceExecutor Either609* a DriverService to use for the remote end, or a preconfigured executor610* for an externally managed endpoint. If neither is provided, the611* {@linkplain ##getDefaultService default service} will be used by612* default.613* @param vendorPrefix Either 'goog' or 'ms'614* @param vendorCapabilityKey Either 'goog:chromeOptions' or 'ms:edgeOptions'615* @return {!Driver} A new driver instance.616*/617static createSession(caps, opt_serviceExecutor, vendorPrefix = '', vendorCapabilityKey = '') {618let executor619let onQuit620if (opt_serviceExecutor instanceof http.Executor) {621executor = opt_serviceExecutor622configureExecutor(executor, vendorPrefix)623} else {624let service = opt_serviceExecutor || this.getDefaultService()625if (!service.getExecutable()) {626const { driverPath, browserPath } = getBinaryPaths(caps)627service.setExecutable(driverPath)628if (browserPath) {629const vendorOptions = caps.get(vendorCapabilityKey)630if (vendorOptions) {631vendorOptions['binary'] = browserPath632caps.set(vendorCapabilityKey, vendorOptions)633} else {634caps.set(vendorCapabilityKey, { binary: browserPath })635}636caps.delete(Capability.BROWSER_VERSION)637}638}639onQuit = () => service.kill()640executor = createExecutor(service.start(), vendorPrefix)641}642643// W3C spec requires noProxy value to be an array of strings, but Chromium644// expects a single host as a string.645let proxy = caps.get(Capability.PROXY)646if (proxy && Array.isArray(proxy.noProxy)) {647proxy.noProxy = proxy.noProxy[0]648if (!proxy.noProxy) {649proxy.noProxy = undefined650}651}652653return /** @type {!Driver} */ (super.createSession(executor, caps, onQuit))654}655656/**657* This function is a no-op as file detectors are not supported by this658* implementation.659* @override660*/661setFileDetector() {}662663/**664* Schedules a command to launch Chrome App with given ID.665* @param {string} id ID of the App to launch.666* @return {!Promise<void>} A promise that will be resolved667* when app is launched.668*/669launchApp(id) {670return this.execute(new command.Command(Command.LAUNCH_APP).setParameter('id', id))671}672673/**674* Schedules a command to get Chromium network emulation settings.675* @return {!Promise} A promise that will be resolved when network676* emulation settings are retrieved.677*/678getNetworkConditions() {679return this.execute(new command.Command(Command.GET_NETWORK_CONDITIONS))680}681682/**683* Schedules a command to delete Chromium network emulation settings.684* @return {!Promise} A promise that will be resolved when network685* emulation settings have been deleted.686*/687deleteNetworkConditions() {688return this.execute(new command.Command(Command.DELETE_NETWORK_CONDITIONS))689}690691/**692* Schedules a command to set Chromium network emulation settings.693*694* __Sample Usage:__695*696* driver.setNetworkConditions({697* offline: false,698* latency: 5, // Additional latency (ms).699* download_throughput: 500 * 1024, // Maximal aggregated download throughput.700* upload_throughput: 500 * 1024 // Maximal aggregated upload throughput.701* });702*703* @param {Object} spec Defines the network conditions to set704* @return {!Promise<void>} A promise that will be resolved when network705* emulation settings are set.706*/707setNetworkConditions(spec) {708if (!spec || typeof spec !== 'object') {709throw TypeError('setNetworkConditions called with non-network-conditions parameter')710}711return this.execute(new command.Command(Command.SET_NETWORK_CONDITIONS).setParameter('network_conditions', spec))712}713714/**715* Sends an arbitrary devtools command to the browser.716*717* @param {string} cmd The name of the command to send.718* @param {Object=} params The command parameters.719* @return {!Promise<void>} A promise that will be resolved when the command720* has finished.721* @see <https://chromedevtools.github.io/devtools-protocol/>722*/723sendDevToolsCommand(cmd, params = {}) {724return this.execute(725new command.Command(Command.SEND_DEVTOOLS_COMMAND).setParameter('cmd', cmd).setParameter('params', params),726)727}728729/**730* Sends an arbitrary devtools command to the browser and get the result.731*732* @param {string} cmd The name of the command to send.733* @param {Object=} params The command parameters.734* @return {!Promise<string>} A promise that will be resolved when the command735* has finished.736* @see <https://chromedevtools.github.io/devtools-protocol/>737*/738sendAndGetDevToolsCommand(cmd, params = {}) {739return this.execute(740new command.Command(Command.SEND_AND_GET_DEVTOOLS_COMMAND)741.setParameter('cmd', cmd)742.setParameter('params', params),743)744}745746/**747* Set a permission state to the given value.748*749* @param {string} name A name of the permission to update.750* @param {("granted"|"denied"|"prompt")} state State to set permission to.751* @returns {!Promise<Object>} A promise that will be resolved when the752* command has finished.753* @see <https://w3c.github.io/permissions/#permission-registry> for valid754* names755*/756setPermission(name, state) {757return this.execute(758new command.Command(Command.SET_PERMISSION).setParameter('descriptor', { name }).setParameter('state', state),759)760}761762/**763* Sends a DevTools command to change the browser's download directory.764*765* @param {string} path The desired download directory.766* @return {!Promise<void>} A promise that will be resolved when the command767* has finished.768* @see #sendDevToolsCommand769*/770async setDownloadPath(path) {771if (!path || typeof path !== 'string') {772throw new error.InvalidArgumentError('invalid download path')773}774const stat = await io.stat(path)775if (!stat.isDirectory()) {776throw new error.InvalidArgumentError('not a directory: ' + path)777}778return this.sendDevToolsCommand('Page.setDownloadBehavior', {779behavior: 'allow',780downloadPath: path,781})782}783784/**785* Returns the list of cast sinks (Cast devices) available to the Chrome media router.786*787* @return {!promise.Thenable<void>} A promise that will be resolved with an array of Strings788* containing the friendly device names of available cast sink targets.789*/790getCastSinks() {791return this.execute(new command.Command(Command.GET_CAST_SINKS))792}793794/**795* Selects a cast sink (Cast device) as the recipient of media router intents (connect or play).796*797* @param {String} deviceName name of the target device.798* @return {!promise.Thenable<void>} A promise that will be resolved799* when the target device has been selected to respond further webdriver commands.800*/801setCastSinkToUse(deviceName) {802return this.execute(new command.Command(Command.SET_CAST_SINK_TO_USE).setParameter('sinkName', deviceName))803}804805/**806* Initiates desktop mirroring for the current browser tab on the specified device.807*808* @param {String} deviceName name of the target device.809* @return {!promise.Thenable<void>} A promise that will be resolved810* when the mirror command has been issued to the device.811*/812startDesktopMirroring(deviceName) {813return this.execute(new command.Command(Command.START_CAST_DESKTOP_MIRRORING).setParameter('sinkName', deviceName))814}815816/**817* Initiates tab mirroring for the current browser tab on the specified device.818*819* @param {String} deviceName name of the target device.820* @return {!promise.Thenable<void>} A promise that will be resolved821* when the mirror command has been issued to the device.822*/823startCastTabMirroring(deviceName) {824return this.execute(new command.Command(Command.START_CAST_TAB_MIRRORING).setParameter('sinkName', deviceName))825}826827/**828* Returns an error message when there is any issue in a Cast session.829* @return {!promise.Thenable<void>} A promise that will be resolved830* when the mirror command has been issued to the device.831*/832getCastIssueMessage() {833return this.execute(new command.Command(Command.GET_CAST_ISSUE_MESSAGE))834}835836/**837* Stops casting from media router to the specified device, if connected.838*839* @param {String} deviceName name of the target device.840* @return {!promise.Thenable<void>} A promise that will be resolved841* when the stop command has been issued to the device.842*/843stopCasting(deviceName) {844return this.execute(new command.Command(Command.STOP_CASTING).setParameter('sinkName', deviceName))845}846}847848// PUBLIC API849850module.exports = {851Driver,852Options,853ServiceBuilder,854}855856857