Best JavaScript code snippet using appium-base-driver
driver.js
Source:driver.js
1/* This Source Code Form is subject to the terms of the Mozilla Public2 * License, v. 2.0. If a copy of the MPL was not distributed with this file,3 * You can obtain one at http://mozilla.org/MPL/2.0/. */4"use strict";5/* global XPCNativeWrapper */6var {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;7var loader = Cc["@mozilla.org/moz/jssubscript-loader;1"]8 .getService(Ci.mozIJSSubScriptLoader);9Cu.import("resource://gre/modules/Log.jsm");10Cu.import("resource://gre/modules/Preferences.jsm");11Cu.import("resource://gre/modules/Services.jsm");12Cu.import("resource://gre/modules/XPCOMUtils.jsm");13Cu.import("chrome://marionette/content/accessibility.js");14Cu.import("chrome://marionette/content/addon.js");15Cu.import("chrome://marionette/content/assert.js");16Cu.import("chrome://marionette/content/atom.js");17Cu.import("chrome://marionette/content/browser.js");18Cu.import("chrome://marionette/content/capture.js");19Cu.import("chrome://marionette/content/cert.js");20Cu.import("chrome://marionette/content/cookie.js");21Cu.import("chrome://marionette/content/element.js");22const {23 ElementNotInteractableError,24 error,25 InsecureCertificateError,26 InvalidArgumentError,27 InvalidCookieDomainError,28 InvalidSelectorError,29 NoAlertOpenError,30 NoSuchFrameError,31 NoSuchWindowError,32 SessionNotCreatedError,33 UnknownError,34 UnsupportedOperationError,35 WebDriverError,36} = Cu.import("chrome://marionette/content/error.js", {});37Cu.import("chrome://marionette/content/evaluate.js");38Cu.import("chrome://marionette/content/event.js");39Cu.import("chrome://marionette/content/interaction.js");40Cu.import("chrome://marionette/content/l10n.js");41Cu.import("chrome://marionette/content/legacyaction.js");42Cu.import("chrome://marionette/content/modal.js");43Cu.import("chrome://marionette/content/proxy.js");44Cu.import("chrome://marionette/content/reftest.js");45Cu.import("chrome://marionette/content/session.js");46Cu.import("chrome://marionette/content/wait.js");47Cu.importGlobalProperties(["URL"]);48this.EXPORTED_SYMBOLS = ["GeckoDriver", "Context"];49var FRAME_SCRIPT = "chrome://marionette/content/listener.js";50const CLICK_TO_START_PREF = "marionette.debugging.clicktostart";51const CONTENT_LISTENER_PREF = "marionette.contentListener";52const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";53const SUPPORTED_STRATEGIES = new Set([54 element.Strategy.ClassName,55 element.Strategy.Selector,56 element.Strategy.ID,57 element.Strategy.TagName,58 element.Strategy.XPath,59 element.Strategy.Anon,60 element.Strategy.AnonAttribute,61]);62const logger = Log.repository.getLogger("Marionette");63const globalMessageManager = Cc["@mozilla.org/globalmessagemanager;1"]64 .getService(Ci.nsIMessageBroadcaster);65/**66 * The Marionette WebDriver services provides a standard conforming67 * implementation of the W3C WebDriver specification.68 *69 * @see {@link https://w3c.github.io/webdriver/webdriver-spec.html}70 * @namespace driver71 */72// This is used to prevent newSession from returning before the telephony73// API's are ready; see bug 792647. This assumes that marionette-server.js74// will be loaded before the 'system-message-listener-ready' message75// is fired. If this stops being true, this approach will have to change.76var systemMessageListenerReady = false;77Services.obs.addObserver(function() {78 systemMessageListenerReady = true;79}, "system-message-listener-ready");80/**81 * @enum82 * @memberof driver83 */84this.Context = {85 CHROME: "chrome",86 CONTENT: "content",87};88/** @memberof driver */89this.Context.fromString = function(s) {90 s = s.toUpperCase();91 if (s in this) {92 return this[s];93 }94 return null;95};96/**97 * Helper function for converting a {@link nsISimpleEnumerator} to a98 * JavaScript iterator.99 *100 * @memberof driver101 *102 * @param {nsISimpleEnumerator} enumerator103 * Enumerator to turn into iterator.104 *105 * @return {Iterable}106 * Iterator.107 */108function* enumeratorIterator(enumerator) {109 while (enumerator.hasMoreElements()) {110 yield enumerator.getNext();111 }112}113/**114 * Implements (parts of) the W3C WebDriver protocol. GeckoDriver lives115 * in chrome space and mediates calls to the message listener of the current116 * browsing context's content frame message listener via ListenerProxy.117 *118 * Throughout this prototype, functions with the argument <var>cmd</var>'s119 * documentation refers to the contents of the <code>cmd.parameter</code>}120 * object.121 *122 * @class GeckoDriver123 *124 * @param {string} appName125 * Description of the product, for example "Firefox".126 * @param {MarionetteServer} server127 * The instance of Marionette server.128 */129this.GeckoDriver = function(appName, server) {130 this.appName = appName;131 this._server = server;132 this.sessionId = null;133 this.wins = new browser.Windows();134 this.browsers = {};135 // points to current browser136 this.curBrowser = null;137 // topmost chrome frame138 this.mainFrame = null;139 // chrome iframe that currently has focus140 this.curFrame = null;141 this.mozBrowserClose = null;142 this.currentFrameElement = null;143 // frame ID of the current remote frame, used for mozbrowserclose events144 this.oopFrameId = null;145 this.observing = null;146 this._browserIds = new WeakMap();147 // The curent context decides if commands should affect chrome- or148 // content space.149 this.context = Context.CONTENT;150 this.sandboxes = new Sandboxes(() => this.getCurrentWindow());151 this.legacyactions = new legacyaction.Chain();152 this.timer = null;153 this.inactivityTimer = null;154 this.testName = null;155 this.capabilities = new session.Capabilities();156 this.mm = globalMessageManager;157 this.listener = proxy.toListener(() => this.mm, this.sendAsync.bind(this),158 () => this.curBrowser);159 // points to an alert instance if a modal dialog is present160 this.dialog = null;161 this.dialogHandler = this.globalModalDialogHandler.bind(this);162};163Object.defineProperty(GeckoDriver.prototype, "a11yChecks", {164 get() {165 return this.capabilities.get("moz:accessibilityChecks");166 },167});168/**169 * Returns the current URL of the ChromeWindow or content browser,170 * depending on context.171 *172 * @return {URL}173 * Read-only property containing the currently loaded URL.174 */175Object.defineProperty(GeckoDriver.prototype, "currentURL", {176 get() {177 switch (this.context) {178 case Context.CHROME:179 let chromeWin = this.getCurrentWindow();180 return new URL(chromeWin.location.href);181 case Context.CONTENT:182 return new URL(this.curBrowser.currentURI.spec);183 default:184 throw TypeError(`Unknown context: ${this.context}`);185 }186 },187});188Object.defineProperty(GeckoDriver.prototype, "title", {189 get() {190 switch (this.context) {191 case Context.CHROME:192 let chromeWin = this.getCurrentWindow();193 return chromeWin.document.documentElement.getAttribute("title");194 case Context.CONTENT:195 return this.curBrowser.currentTitle;196 default:197 throw TypeError(`Unknown context: ${this.context}`);198 }199 },200});201Object.defineProperty(GeckoDriver.prototype, "proxy", {202 get() {203 return this.capabilities.get("proxy");204 },205});206Object.defineProperty(GeckoDriver.prototype, "secureTLS", {207 get() {208 return !this.capabilities.get("acceptInsecureCerts");209 },210});211Object.defineProperty(GeckoDriver.prototype, "timeouts", {212 get() {213 return this.capabilities.get("timeouts");214 },215 set(newTimeouts) {216 this.capabilities.set("timeouts", newTimeouts);217 },218});219Object.defineProperty(GeckoDriver.prototype, "windows", {220 get() {221 return enumeratorIterator(Services.wm.getEnumerator(null));222 },223});224Object.defineProperty(GeckoDriver.prototype, "windowHandles", {225 get() {226 let hs = [];227 for (let win of this.windows) {228 let tabBrowser = browser.getTabBrowser(win);229 // Only return handles for browser windows230 if (tabBrowser && tabBrowser.tabs) {231 tabBrowser.tabs.forEach(tab => {232 let winId = this.getIdForBrowser(browser.getBrowserForTab(tab));233 if (winId !== null) {234 hs.push(winId);235 }236 });237 }238 }239 return hs;240 },241});242Object.defineProperty(GeckoDriver.prototype, "chromeWindowHandles", {243 get() {244 let hs = [];245 for (let win of this.windows) {246 hs.push(getOuterWindowId(win));247 }248 return hs;249 },250});251GeckoDriver.prototype.QueryInterface = XPCOMUtils.generateQI([252 Ci.nsIMessageListener,253 Ci.nsIObserver,254 Ci.nsISupportsWeakReference,255]);256/**257 * Callback used to observe the creation of new modal or tab modal dialogs258 * during the session's lifetime.259 */260GeckoDriver.prototype.globalModalDialogHandler = function(subject, topic) {261 let winr;262 if (topic === modal.COMMON_DIALOG_LOADED) {263 // Always keep a weak reference to the current dialog264 winr = Cu.getWeakReference(subject);265 }266 this.dialog = new modal.Dialog(() => this.curBrowser, winr);267};268/**269 * Switches to the global ChromeMessageBroadcaster, potentially replacing270 * a frame-specific ChromeMessageSender. Has no effect if the global271 * ChromeMessageBroadcaster is already in use. If this replaces a272 * frame-specific ChromeMessageSender, it removes the message listeners273 * from that sender, and then puts the corresponding frame script "to274 * sleep", which removes most of the message listeners from it as well.275 */276GeckoDriver.prototype.switchToGlobalMessageManager = function() {277 if (this.curBrowser &&278 this.curBrowser.frameManager.currentRemoteFrame !== null) {279 this.curBrowser.frameManager.removeMessageManagerListeners(this.mm);280 this.sendAsync("sleepSession");281 this.curBrowser.frameManager.currentRemoteFrame = null;282 }283 this.mm = globalMessageManager;284};285/**286 * Helper method to send async messages to the content listener.287 * Correct usage is to pass in the name of a function in listener.js,288 * a serialisable object, and optionally the current command's ID289 * when not using the modern dispatching technique.290 *291 * @param {string} name292 * Suffix of the targetted message listener293 * <tt>Marionette:SUFFIX</tt>.294 * @param {Object=} msg295 * Optional JSON serialisable object to send to the listener.296 * @param {number=} commandID297 * Optional command ID to ensure synchronisity.298 */299GeckoDriver.prototype.sendAsync = function(name, data, commandID) {300 name = "Marionette:" + name;301 let payload = copy(data);302 // TODO(ato): When proxy.AsyncMessageChannel303 // is used for all chrome <-> content communication304 // this can be removed.305 if (commandID) {306 payload.command_id = commandID;307 }308 if (!this.curBrowser.frameManager.currentRemoteFrame) {309 this.broadcastDelayedAsyncMessage_(name, payload);310 } else {311 this.sendTargettedAsyncMessage_(name, payload);312 }313};314// eslint-disable-next-line315GeckoDriver.prototype.broadcastDelayedAsyncMessage_ = function(name, payload) {316 this.curBrowser.executeWhenReady(() => {317 if (this.curBrowser.curFrameId) {318 const target = name + this.curBrowser.curFrameId;319 this.mm.broadcastAsyncMessage(target, payload);320 } else {321 throw new NoSuchWindowError(322 "No such content frame; perhaps the listener was not registered?");323 }324 });325};326GeckoDriver.prototype.sendTargettedAsyncMessage_ = function(name, payload) {327 const curRemoteFrame = this.curBrowser.frameManager.currentRemoteFrame;328 const target = name + curRemoteFrame.targetFrameId;329 try {330 this.mm.sendAsyncMessage(target, payload);331 } catch (e) {332 switch (e.result) {333 case Cr.NS_ERROR_FAILURE:334 case Cr.NS_ERROR_NOT_INITIALIZED:335 throw new NoSuchWindowError();336 default:337 throw new WebDriverError(e);338 }339 }340};341/**342 * Get the session's current top-level browsing context.343 *344 * It will return the outer {@link ChromeWindow} previously selected by345 * window handle through {@link #switchToWindow}, or the first window that346 * was registered.347 *348 * @param {Context=} forcedContext349 * Optional name of the context to use for finding the window.350 * It will be required if a command always needs a specific context,351 * whether which context is currently set. Defaults to the current352 * context.353 *354 * @return {ChromeWindow}355 * The current top-level browsing context.356 */357GeckoDriver.prototype.getCurrentWindow = function(forcedContext = undefined) {358 let context = typeof forcedContext == "undefined" ? this.context : forcedContext;359 let win = null;360 switch (context) {361 case Context.CHROME:362 if (this.curFrame !== null) {363 win = this.curFrame;364 } else if (this.curBrowser !== null) {365 win = this.curBrowser.window;366 }367 break;368 case Context.CONTENT:369 if (this.curFrame !== null) {370 win = this.curFrame;371 } else if (this.curBrowser !== null && this.curBrowser.contentBrowser) {372 win = this.curBrowser.window;373 }374 break;375 }376 return win;377};378GeckoDriver.prototype.isReftestBrowser = function(element) {379 return this._reftest &&380 element &&381 element.tagName === "xul:browser" &&382 element.parentElement &&383 element.parentElement.id === "reftest";384};385GeckoDriver.prototype.addFrameCloseListener = function(action) {386 let win = this.getCurrentWindow();387 this.mozBrowserClose = e => {388 if (e.target.id == this.oopFrameId) {389 win.removeEventListener("mozbrowserclose", this.mozBrowserClose, true);390 this.switchToGlobalMessageManager();391 throw new NoSuchWindowError("The window closed during action: " + action);392 }393 };394 win.addEventListener("mozbrowserclose", this.mozBrowserClose, true);395};396/**397 * Create a new browsing context for window and add to known browsers.398 *399 * @param {nsIDOMWindow} win400 * Window for which we will create a browsing context.401 *402 * @return {string}403 * Returns the unique server-assigned ID of the window.404 */405GeckoDriver.prototype.addBrowser = function(win) {406 let bc = new browser.Context(win, this);407 let winId = getOuterWindowId(win);408 this.browsers[winId] = bc;409 this.curBrowser = this.browsers[winId];410 if (!this.wins.has(winId)) {411 // add this to seenItems so we can guarantee412 // the user will get winId as this window's id413 this.wins.set(winId, win);414 }415};416/**417 * Registers a new browser, win, with Marionette.418 *419 * If we have not seen the browser content window before, the listener420 * frame script will be loaded into it. If isNewSession is true, we will421 * switch focus to the start frame when it registers.422 *423 * @param {nsIDOMWindow} win424 * Window whose browser we need to access.425 * @param {boolean=} [false] isNewSession426 * True if this is the first time we're talking to this browser.427 */428GeckoDriver.prototype.startBrowser = function(win, isNewSession = false) {429 this.mainFrame = win;430 this.curFrame = null;431 this.addBrowser(win);432 this.curBrowser.isNewSession = isNewSession;433 this.whenBrowserStarted(win, isNewSession);434};435/**436 * Callback invoked after a new session has been started in a browser.437 * Loads the Marionette frame script into the browser if needed.438 *439 * @param {nsIDOMWindow} win440 * Window whose browser we need to access.441 * @param {boolean} isNewSession442 * True if this is the first time we're talking to this browser.443 */444GeckoDriver.prototype.whenBrowserStarted = function(win, isNewSession) {445 let mm = win.window.messageManager;446 if (mm) {447 if (!isNewSession) {448 // Loading the frame script corresponds to a situation we need to449 // return to the server. If the messageManager is a message broadcaster450 // with no children, we don't have a hope of coming back from this451 // call, so send the ack here. Otherwise, make a note of how many452 // child scripts will be loaded so we known when it's safe to return.453 // Child managers may not have child scripts yet (e.g. socialapi),454 // only count child managers that have children, but only count the top455 // level children as they are the ones that we expect a response from.456 if (mm.childCount !== 0) {457 this.curBrowser.frameRegsPending = 0;458 for (let i = 0; i < mm.childCount; i++) {459 if (mm.getChildAt(i).childCount !== 0) {460 this.curBrowser.frameRegsPending += 1;461 }462 }463 }464 }465 if (!Preferences.get(CONTENT_LISTENER_PREF) || !isNewSession) {466 // load listener into the remote frame467 // and any applicable new frames468 // opened after this call469 mm.loadFrameScript(FRAME_SCRIPT, true);470 Preferences.set(CONTENT_LISTENER_PREF, true);471 }472 } else {473 logger.error(474 `Could not load listener into content for page ${win.location.href}`);475 }476};477/**478 * Recursively get all labeled text.479 *480 * @param {nsIDOMElement} el481 * The parent element.482 * @param {Array.<string>} lines483 * Array that holds the text lines.484 */485GeckoDriver.prototype.getVisibleText = function(el, lines) {486 try {487 if (atom.isElementDisplayed(el, this.getCurrentWindow())) {488 if (el.value) {489 lines.push(el.value);490 }491 for (let child in el.childNodes) {492 this.getVisibleText(el.childNodes[child], lines);493 }494 }495 } catch (e) {496 if (el.nodeName == "#text") {497 lines.push(el.textContent);498 }499 }500};501/**502 * Handles registration of new content listener browsers. Depending on503 * their type they are either accepted or ignored.504 */505GeckoDriver.prototype.registerBrowser = function(id, be) {506 let nullPrevious = this.curBrowser.curFrameId === null;507 let listenerWindow = Services.wm.getOuterWindowWithId(id);508 // go in here if we're already in a remote frame509 if (this.curBrowser.frameManager.currentRemoteFrame !== null &&510 (!listenerWindow || this.mm == this.curBrowser.frameManager511 .currentRemoteFrame.messageManager.get())) {512 // The outerWindowID from an OOP frame will not be meaningful to513 // the parent process here, since each process maintains its own514 // independent window list. So, it will either be null (!listenerWindow)515 // if we're already in a remote frame, or it will point to some516 // random window, which will hopefully cause an href mismatch.517 // Currently this only happens in B2G for OOP frames registered in518 // Marionette:switchToFrame, so we'll acknowledge the switchToFrame519 // message here.520 //521 // TODO: Should have a better way of determining that this message522 // is from a remote frame.523 this.curBrowser.frameManager.currentRemoteFrame.targetFrameId = id;524 }525 // We want to ignore frames that are XUL browsers that aren't in the "main"526 // tabbrowser, but accept things on Fennec (which doesn't have a527 // xul:tabbrowser), and accept HTML iframes (because tests depend on it),528 // as well as XUL frames. Ideally this should be cleaned up and we should529 // keep track of browsers a different way.530 if (this.appName != "Firefox" || be.namespaceURI != XUL_NS ||531 be.nodeName != "browser" || be.getTabBrowser()) {532 // curBrowser holds all the registered frames in knownFrames533 this.curBrowser.register(id, be);534 }535 this.wins.set(id, listenerWindow);536 if (nullPrevious && (this.curBrowser.curFrameId !== null)) {537 this.sendAsync(538 "newSession",539 this.capabilities.toJSON(),540 this.newSessionCommandId);541 if (this.curBrowser.isNewSession) {542 this.newSessionCommandId = null;543 }544 }545 return [id, this.capabilities.toJSON()];546};547GeckoDriver.prototype.registerPromise = function() {548 const li = "Marionette:register";549 return new Promise(resolve => {550 let cb = msg => {551 let wid = msg.json.value;552 let be = msg.target;553 let rv = this.registerBrowser(wid, be);554 if (this.curBrowser.frameRegsPending > 0) {555 this.curBrowser.frameRegsPending--;556 }557 if (this.curBrowser.frameRegsPending === 0) {558 this.mm.removeMessageListener(li, cb);559 resolve();560 }561 // this is a sync message and listeners expect the ID back562 return rv;563 };564 this.mm.addMessageListener(li, cb);565 });566};567GeckoDriver.prototype.listeningPromise = function() {568 const li = "Marionette:listenersAttached";569 return new Promise(resolve => {570 let cb = msg => {571 if (msg.json.listenerId === this.curBrowser.curFrameId) {572 this.mm.removeMessageListener(li, cb);573 resolve();574 }575 };576 this.mm.addMessageListener(li, cb);577 });578};579/** Create a new session. */580GeckoDriver.prototype.newSession = function* (cmd, resp) {581 if (this.sessionId) {582 throw new SessionNotCreatedError("Maximum number of active sessions");583 }584 this.sessionId = cmd.parameters.sessionId ||585 cmd.parameters.session_id ||586 element.generateUUID();587 this.newSessionCommandId = cmd.id;588 try {589 this.capabilities = session.Capabilities.fromJSON(590 cmd.parameters.capabilities, {merge: true});591 logger.config("Matched capabilities: " +592 JSON.stringify(this.capabilities));593 } catch (e) {594 throw new SessionNotCreatedError(e);595 }596 if (!this.secureTLS) {597 logger.warn("TLS certificate errors will be ignored for this session");598 let acceptAllCerts = new cert.InsecureSweepingOverride();599 cert.installOverride(acceptAllCerts);600 }601 if (this.proxy.init()) {602 logger.info("Proxy settings initialised: " + JSON.stringify(this.proxy));603 }604 // If we are testing accessibility with marionette, start a11y service in605 // chrome first. This will ensure that we do not have any content-only606 // services hanging around.607 if (this.a11yChecks && accessibility.service) {608 logger.info("Preemptively starting accessibility service in Chrome");609 }610 let registerBrowsers = this.registerPromise();611 let browserListening = this.listeningPromise();612 let waitForWindow = function() {613 let win = Services.wm.getMostRecentWindow("navigator:browser");614 if (!win) {615 // if the window isn't even created, just poll wait for it616 let checkTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);617 checkTimer.initWithCallback(waitForWindow.bind(this), 100,618 Ci.nsITimer.TYPE_ONE_SHOT);619 } else if (win.document.readyState != "complete") {620 // otherwise, wait for it to be fully loaded before proceeding621 let listener = ev => {622 // ensure that we proceed, on the top level document load event623 // (not an iframe one...)624 if (ev.target != win.document) {625 return;626 }627 win.removeEventListener("load", listener);628 waitForWindow.call(this);629 };630 win.addEventListener("load", listener, true);631 } else {632 let clickToStart = Preferences.get(CLICK_TO_START_PREF);633 if (clickToStart) {634 Services.prompt.alert(win, "", "Click to start execution of marionette tests");635 }636 this.startBrowser(win, true);637 }638 };639 if (!Preferences.get(CONTENT_LISTENER_PREF)) {640 waitForWindow.call(this);641 } else if (this.appName != "Firefox" && this.curBrowser === null) {642 // if there is a content listener, then we just wake it up643 let win = this.getCurrentWindow();644 this.addBrowser(win);645 this.whenBrowserStarted(win, false);646 this.mm.broadcastAsyncMessage("Marionette:restart", {});647 } else {648 throw new WebDriverError("Session already running");649 }650 this.switchToGlobalMessageManager();651 yield registerBrowsers;652 yield browserListening;653 if (this.curBrowser.tab) {654 this.curBrowser.contentBrowser.focus();655 }656 // Setup global listener for modal dialogs, and check if there is already657 // one open for the currently selected browser window.658 modal.addHandler(this.dialogHandler);659 this.dialog = modal.findModalDialogs(this.curBrowser);660 return {661 sessionId: this.sessionId,662 capabilities: this.capabilities,663 };664};665/**666 * Send the current session's capabilities to the client.667 *668 * Capabilities informs the client of which WebDriver features are669 * supported by Firefox and Marionette. They are immutable for the670 * length of the session.671 *672 * The return value is an immutable map of string keys673 * ("capabilities") to values, which may be of types boolean,674 * numerical or string.675 */676GeckoDriver.prototype.getSessionCapabilities = function(cmd, resp) {677 resp.body.capabilities = this.capabilities;678};679/**680 * Sets the context of the subsequent commands to be either "chrome" or681 * "content".682 *683 * @param {string} value684 * Name of the context to be switched to. Must be one of "chrome" or685 * "content".686 */687GeckoDriver.prototype.setContext = function(cmd, resp) {688 let val = cmd.parameters.value;689 let ctx = Context.fromString(val);690 if (ctx === null) {691 throw new WebDriverError(`Invalid context: ${val}`);692 }693 this.context = ctx;694};695/** Gets the context of the server, either "chrome" or "content". */696GeckoDriver.prototype.getContext = function(cmd, resp) {697 resp.body.value = this.context.toString();698};699/**700 * Executes a JavaScript function in the context of the current browsing701 * context, if in content space, or in chrome space otherwise, and returns702 * the return value of the function.703 *704 * It is important to note that if the <var>sandboxName</var> parameter705 * is left undefined, the script will be evaluated in a mutable sandbox,706 * causing any change it makes on the global state of the document to have707 * lasting side-effects.708 *709 * @param {string} script710 * Script to evaluate as a function body.711 * @param {Array.<(string|boolean|number|object|WebElement)>} args712 * Arguments exposed to the script in <code>arguments</code>.713 * The array items must be serialisable to the WebDriver protocol.714 * @param {number} scriptTimeout715 * Duration in milliseconds of when to interrupt and abort the716 * script evaluation.717 * @param {string=} sandbox718 * Name of the sandbox to evaluate the script in. The sandbox is719 * cached for later re-use on the same Window object if720 * <var>newSandbox</var> is false. If he parameter is undefined,721 * the script is evaluated in a mutable sandbox. If the parameter722 * is "system", it will be evaluted in a sandbox with elevated system723 * privileges, equivalent to chrome space.724 * @param {boolean=} newSandbox725 * Forces the script to be evaluated in a fresh sandbox. Note that if726 * it is undefined, the script will normally be evaluted in a fresh727 * sandbox.728 * @param {string=} filename729 * Filename of the client's program where this script is evaluated.730 * @param {number=} line731 * Line in the client's program where this script is evaluated.732 * @param {boolean=} debug_script733 * Attach an <code>onerror</code> event handler on the {@link Window}734 * object. It does not differentiate content errors from chrome errors.735 * @param {boolean=} directInject736 * Evaluate the script without wrapping it in a function.737 *738 * @return {(string|boolean|number|object|WebElement)}739 * Return value from the script, or null which signifies either the740 * JavaScript notion of null or undefined.741 *742 * @throws {ScriptTimeoutError}743 * If the script was interrupted due to reaching the744 * <var>scriptTimeout</var> or default timeout.745 * @throws {JavaScriptError}746 * If an {@link Error} was thrown whilst evaluating the script.747 */748GeckoDriver.prototype.executeScript = function*(cmd, resp) {749 assert.window(this.getCurrentWindow());750 let {script, args, scriptTimeout} = cmd.parameters;751 scriptTimeout = scriptTimeout || this.timeouts.script;752 let opts = {753 sandboxName: cmd.parameters.sandbox,754 newSandbox: !!(typeof cmd.parameters.newSandbox == "undefined") ||755 cmd.parameters.newSandbox,756 file: cmd.parameters.filename,757 line: cmd.parameters.line,758 debug: cmd.parameters.debug_script,759 };760 resp.body.value = yield this.execute_(script, args, scriptTimeout, opts);761};762/**763 * Executes a JavaScript function in the context of the current browsing764 * context, if in content space, or in chrome space otherwise, and returns765 * the object passed to the callback.766 *767 * The callback is always the last argument to the <var>arguments</var>768 * list passed to the function scope of the script. It can be retrieved769 * as such:770 *771 * <pre><code>772 * let callback = arguments[arguments.length - 1];773 * callback("foo");774 * // "foo" is returned775 * </code></pre>776 *777 * It is important to note that if the <var>sandboxName</var> parameter778 * is left undefined, the script will be evaluated in a mutable sandbox,779 * causing any change it makes on the global state of the document to have780 * lasting side-effects.781 *782 * @param {string} script783 * Script to evaluate as a function body.784 * @param {Array.<(string|boolean|number|object|WebElement)>} args785 * Arguments exposed to the script in <code>arguments</code>.786 * The array items must be serialisable to the WebDriver protocol.787 * @param {number} scriptTimeout788 * Duration in milliseconds of when to interrupt and abort the789 * script evaluation.790 * @param {string=} sandbox791 * Name of the sandbox to evaluate the script in. The sandbox is792 * cached for later re-use on the same Window object if793 * <var>newSandbox</var> is false. If the parameter is undefined,794 * the script is evaluated in a mutable sandbox. If the parameter795 * is "system", it will be evaluted in a sandbox with elevated system796 * privileges, equivalent to chrome space.797 * @param {boolean=} newSandbox798 * Forces the script to be evaluated in a fresh sandbox. Note that if799 * it is undefined, the script will normally be evaluted in a fresh800 * sandbox.801 * @param {string=} filename802 * Filename of the client's program where this script is evaluated.803 * @param {number=} line804 * Line in the client's program where this script is evaluated.805 * @param {boolean=} debug_script806 * Attach an <code>onerror</code> event handler on the {@link Window}807 * object. It does not differentiate content errors from chrome errors.808 * @param {boolean=} directInject809 * Evaluate the script without wrapping it in a function.810 *811 * @return {(string|boolean|number|object|WebElement)}812 * Return value from the script, or null which signifies either the813 * JavaScript notion of null or undefined.814 *815 * @throws {ScriptTimeoutError}816 * If the script was interrupted due to reaching the817 * <var>scriptTimeout</var> or default timeout.818 * @throws {JavaScriptError}819 * If an Error was thrown whilst evaluating the script.820 */821GeckoDriver.prototype.executeAsyncScript = function* (cmd, resp) {822 assert.window(this.getCurrentWindow());823 let {script, args, scriptTimeout} = cmd.parameters;824 scriptTimeout = scriptTimeout || this.timeouts.script;825 let opts = {826 sandboxName: cmd.parameters.sandbox,827 newSandbox: !!(typeof cmd.parameters.newSandbox == "undefined") ||828 cmd.parameters.newSandbox,829 file: cmd.parameters.filename,830 line: cmd.parameters.line,831 debug: cmd.parameters.debug_script,832 async: true,833 };834 resp.body.value = yield this.execute_(script, args, scriptTimeout, opts);835};836GeckoDriver.prototype.execute_ = function(script, args, timeout, opts = {}) {837 switch (this.context) {838 case Context.CONTENT:839 // evaluate in content with lasting side-effects840 if (!opts.sandboxName) {841 return this.listener.execute(script, args, timeout, opts)842 .then(evaluate.toJSON);843 }844 // evaluate in content with sandbox845 return this.listener.executeInSandbox(script, args, timeout, opts)846 .then(evaluate.toJSON);847 case Context.CHROME:848 let sb = this.sandboxes.get(opts.sandboxName, opts.newSandbox);849 opts.timeout = timeout;850 let wargs = evaluate.fromJSON(args, this.curBrowser.seenEls, sb.window);851 return evaluate.sandbox(sb, script, wargs, opts)852 .then(res => evaluate.toJSON(res, this.curBrowser.seenEls));853 default:854 throw new TypeError(`Unknown context: ${this.context}`);855 }856};857/**858 * Navigate to given URL.859 *860 * Navigates the current browsing context to the given URL and waits for861 * the document to load or the session's page timeout duration to elapse862 * before returning.863 *864 * The command will return with a failure if there is an error loading865 * the document or the URL is blocked. This can occur if it fails to866 * reach host, the URL is malformed, or if there is a certificate issue867 * to name some examples.868 *869 * The document is considered successfully loaded when the870 * DOMContentLoaded event on the frame element associated with the871 * current window triggers and document.readyState is "complete".872 *873 * In chrome context it will change the current window's location to874 * the supplied URL and wait until document.readyState equals "complete"875 * or the page timeout duration has elapsed.876 *877 * @param {string} url878 * URL to navigate to.879 *880 * @throws {UnsupportedOperationError}881 * Not available in current context.882 * @throws {NoSuchWindowError}883 * Top-level browsing context has been discarded.884 * @throws {UnexpectedAlertOpenError}885 * A modal dialog is open, blocking this operation.886 */887GeckoDriver.prototype.get = function* (cmd, resp) {888 assert.content(this.context);889 assert.window(this.getCurrentWindow());890 assert.noUserPrompt(this.dialog);891 let url = cmd.parameters.url;892 let get = this.listener.get({url, pageTimeout: this.timeouts.pageLoad});893 // If a reload of the frame script interrupts our page load, this will894 // never return. We need to re-issue this request to correctly poll for895 // readyState and send errors.896 this.curBrowser.pendingCommands.push(() => {897 let parameters = {898 // TODO(ato): Bug 1242595899 command_id: this.listener.activeMessageId,900 pageTimeout: this.timeouts.pageLoad,901 startTime: new Date().getTime(),902 };903 this.mm.broadcastAsyncMessage(904 "Marionette:waitForPageLoaded" + this.curBrowser.curFrameId,905 parameters);906 });907 yield get;908 this.curBrowser.contentBrowser.focus();909};910/**911 * Get a string representing the current URL.912 *913 * On Desktop this returns a string representation of the URL of the914 * current top level browsing context. This is equivalent to915 * document.location.href.916 *917 * When in the context of the chrome, this returns the canonical URL918 * of the current resource.919 *920 * @throws {NoSuchWindowError}921 * Top-level browsing context has been discarded.922 * @throws {UnexpectedAlertOpenError}923 * A modal dialog is open, blocking this operation.924 */925GeckoDriver.prototype.getCurrentUrl = function(cmd) {926 assert.window(this.getCurrentWindow());927 assert.noUserPrompt(this.dialog);928 return this.currentURL.toString();929};930/**931 * Gets the current title of the window.932 *933 * @return {string}934 * Document title of the top-level browsing context.935 *936 * @throws {NoSuchWindowError}937 * Top-level browsing context has been discarded.938 * @throws {UnexpectedAlertOpenError}939 * A modal dialog is open, blocking this operation.940 */941GeckoDriver.prototype.getTitle = function* (cmd, resp) {942 assert.window(this.getCurrentWindow());943 assert.noUserPrompt(this.dialog);944 return this.title;945};946/** Gets the current type of the window. */947GeckoDriver.prototype.getWindowType = function(cmd, resp) {948 let win = assert.window(this.getCurrentWindow());949 resp.body.value = win.document.documentElement.getAttribute("windowtype");950};951/**952 * Gets the page source of the content document.953 *954 * @return {string}955 * String serialisation of the DOM of the current browsing context's956 * active document.957 *958 * @throws {NoSuchWindowError}959 * Top-level browsing context has been discarded.960 * @throws {UnexpectedAlertOpenError}961 * A modal dialog is open, blocking this operation.962 */963GeckoDriver.prototype.getPageSource = function* (cmd, resp) {964 const win = assert.window(this.getCurrentWindow());965 assert.noUserPrompt(this.dialog);966 switch (this.context) {967 case Context.CHROME:968 let s = new win.XMLSerializer();969 resp.body.value = s.serializeToString(win.document);970 break;971 case Context.CONTENT:972 resp.body.value = yield this.listener.getPageSource();973 break;974 }975};976/**977 * Cause the browser to traverse one step backward in the joint history978 * of the current browsing context.979 *980 * @throws {UnsupportedOperationError}981 * Not available in current context.982 * @throws {NoSuchWindowError}983 * Top-level browsing context has been discarded.984 * @throws {UnexpectedAlertOpenError}985 * A modal dialog is open, blocking this operation.986 */987GeckoDriver.prototype.goBack = function* (cmd, resp) {988 assert.content(this.context);989 assert.contentBrowser(this.curBrowser);990 assert.noUserPrompt(this.dialog);991 // If there is no history, just return992 if (!this.curBrowser.contentBrowser.webNavigation.canGoBack) {993 return;994 }995 let lastURL = this.currentURL;996 let goBack = this.listener.goBack({pageTimeout: this.timeouts.pageLoad});997 // If a reload of the frame script interrupts our page load, this will998 // never return. We need to re-issue this request to correctly poll for999 // readyState and send errors.1000 this.curBrowser.pendingCommands.push(() => {1001 let parameters = {1002 // TODO(ato): Bug 12425951003 command_id: this.listener.activeMessageId,1004 lastSeenURL: lastURL.toString(),1005 pageTimeout: this.timeouts.pageLoad,1006 startTime: new Date().getTime(),1007 };1008 this.mm.broadcastAsyncMessage(1009 "Marionette:waitForPageLoaded" + this.curBrowser.curFrameId,1010 parameters);1011 });1012 yield goBack;1013};1014/**1015 * Cause the browser to traverse one step forward in the joint history1016 * of the current browsing context.1017 *1018 * @throws {UnsupportedOperationError}1019 * Not available in current context.1020 * @throws {NoSuchWindowError}1021 * Top-level browsing context has been discarded.1022 * @throws {UnexpectedAlertOpenError}1023 * A modal dialog is open, blocking this operation.1024 */1025GeckoDriver.prototype.goForward = function* (cmd, resp) {1026 assert.content(this.context);1027 assert.contentBrowser(this.curBrowser);1028 assert.noUserPrompt(this.dialog);1029 // If there is no history, just return1030 if (!this.curBrowser.contentBrowser.webNavigation.canGoForward) {1031 return;1032 }1033 let lastURL = this.currentURL;1034 let goForward = this.listener.goForward(1035 {pageTimeout: this.timeouts.pageLoad});1036 // If a reload of the frame script interrupts our page load, this will1037 // never return. We need to re-issue this request to correctly poll for1038 // readyState and send errors.1039 this.curBrowser.pendingCommands.push(() => {1040 let parameters = {1041 // TODO(ato): Bug 12425951042 command_id: this.listener.activeMessageId,1043 lastSeenURL: lastURL.toString(),1044 pageTimeout: this.timeouts.pageLoad,1045 startTime: new Date().getTime(),1046 };1047 this.mm.broadcastAsyncMessage(1048 "Marionette:waitForPageLoaded" + this.curBrowser.curFrameId,1049 parameters);1050 });1051 yield goForward;1052};1053/**1054 * Causes the browser to reload the page in current top-level browsing1055 * context.1056 *1057 * @throws {UnsupportedOperationError}1058 * Not available in current context.1059 * @throws {NoSuchWindowError}1060 * Top-level browsing context has been discarded.1061 * @throws {UnexpectedAlertOpenError}1062 * A modal dialog is open, blocking this operation.1063 */1064GeckoDriver.prototype.refresh = function* (cmd, resp) {1065 assert.content(this.context);1066 assert.window(this.getCurrentWindow());1067 assert.noUserPrompt(this.dialog);1068 let refresh = this.listener.refresh(1069 {pageTimeout: this.timeouts.pageLoad});1070 // If a reload of the frame script interrupts our page load, this will1071 // never return. We need to re-issue this request to correctly poll for1072 // readyState and send errors.1073 this.curBrowser.pendingCommands.push(() => {1074 let parameters = {1075 // TODO(ato): Bug 12425951076 command_id: this.listener.activeMessageId,1077 pageTimeout: this.timeouts.pageLoad,1078 startTime: new Date().getTime(),1079 };1080 this.mm.broadcastAsyncMessage(1081 "Marionette:waitForPageLoaded" + this.curBrowser.curFrameId,1082 parameters);1083 });1084 yield refresh;1085};1086/**1087 * Forces an update for the given browser's id.1088 */1089GeckoDriver.prototype.updateIdForBrowser = function(browser, newId) {1090 this._browserIds.set(browser.permanentKey, newId);1091};1092/**1093 * Retrieves a listener id for the given xul browser element. In case1094 * the browser is not known, an attempt is made to retrieve the id from1095 * a CPOW, and null is returned if this fails.1096 */1097GeckoDriver.prototype.getIdForBrowser = function(browser) {1098 if (browser === null) {1099 return null;1100 }1101 let permKey = browser.permanentKey;1102 if (this._browserIds.has(permKey)) {1103 return this._browserIds.get(permKey);1104 }1105 let winId = browser.outerWindowID;1106 if (winId) {1107 this._browserIds.set(permKey, winId);1108 return winId;1109 }1110 return null;1111},1112/**1113 * Get the current window's handle. On desktop this typically corresponds1114 * to the currently selected tab.1115 *1116 * Return an opaque server-assigned identifier to this window that1117 * uniquely identifies it within this Marionette instance. This can1118 * be used to switch to this window at a later point.1119 *1120 * @return {string}1121 * Unique window handle.1122 *1123 * @throws {NoSuchWindowError}1124 * Top-level browsing context has been discarded.1125 */1126GeckoDriver.prototype.getWindowHandle = function(cmd, resp) {1127 assert.contentBrowser(this.curBrowser);1128 return this.curBrowser.curFrameId.toString();1129};1130/**1131 * Get a list of top-level browsing contexts. On desktop this typically1132 * corresponds to the set of open tabs for browser windows, or the window1133 * itself for non-browser chrome windows.1134 *1135 * Each window handle is assigned by the server and is guaranteed unique,1136 * however the return array does not have a specified ordering.1137 *1138 * @return {Array.<string>}1139 * Unique window handles.1140 */1141GeckoDriver.prototype.getWindowHandles = function(cmd, resp) {1142 return this.windowHandles.map(String);1143};1144/**1145 * Get the current window's handle. This corresponds to a window that1146 * may itself contain tabs.1147 *1148 * Return an opaque server-assigned identifier to this window that1149 * uniquely identifies it within this Marionette instance. This can1150 * be used to switch to this window at a later point.1151 *1152 * @return {string}1153 * Unique window handle.1154 *1155 * @throws {NoSuchWindowError}1156 * Top-level browsing context has been discarded.1157 */1158GeckoDriver.prototype.getChromeWindowHandle = function(cmd, resp) {1159 assert.window(this.getCurrentWindow(Context.CHROME));1160 for (let i in this.browsers) {1161 if (this.curBrowser == this.browsers[i]) {1162 resp.body.value = i;1163 return;1164 }1165 }1166};1167/**1168 * Returns identifiers for each open chrome window for tests interested in1169 * managing a set of chrome windows and tabs separately.1170 *1171 * @return {Array.<string>}1172 * Unique window handles.1173 */1174GeckoDriver.prototype.getChromeWindowHandles = function(cmd, resp) {1175 return this.chromeWindowHandles.map(String);1176};1177/**1178 * Get the current position and size of the browser window currently in focus.1179 *1180 * Will return the current browser window size in pixels. Refers to1181 * window outerWidth and outerHeight values, which include scroll bars,1182 * title bars, etc.1183 *1184 * @return {Object.<string, number>}1185 * Object with |x| and |y| coordinates, and |width| and |height|1186 * of browser window.1187 *1188 * @throws {NoSuchWindowError}1189 * Top-level browsing context has been discarded.1190 * @throws {UnexpectedAlertOpenError}1191 * A modal dialog is open, blocking this operation.1192 */1193GeckoDriver.prototype.getWindowRect = function(cmd, resp) {1194 assert.window(this.getCurrentWindow());1195 assert.noUserPrompt(this.dialog);1196 return this.curBrowser.rect;1197};1198/**1199 * Set the window position and size of the browser on the operating1200 * system window manager.1201 *1202 * The supplied |width| and |height| values refer to the window outerWidth1203 * and outerHeight values, which include browser chrome and OS-level1204 * window borders.1205 *1206 * @param {number} x1207 * X coordinate of the top/left of the window that it will be1208 * moved to.1209 * @param {number} y1210 * Y coordinate of the top/left of the window that it will be1211 * moved to.1212 * @param {number} width1213 * Width to resize the window to.1214 * @param {number} height1215 * Height to resize the window to.1216 *1217 * @return {Object.<string, number>}1218 * Object with |x| and |y| coordinates and |width| and |height|1219 * dimensions.1220 *1221 * @throws {UnsupportedOperationError}1222 * Not applicable to application.1223 * @throws {NoSuchWindowError}1224 * Top-level browsing context has been discarded.1225 * @throws {UnexpectedAlertOpenError}1226 * A modal dialog is open, blocking this operation.1227 */1228GeckoDriver.prototype.setWindowRect = async function(cmd, resp) {1229 assert.firefox();1230 const win = assert.window(this.getCurrentWindow());1231 assert.noUserPrompt(this.dialog);1232 let {x, y, width, height} = cmd.parameters;1233 let origRect = this.curBrowser.rect;1234 // Throttle resize event by forcing the event queue to flush and delay1235 // until the main thread is idle.1236 function optimisedResize(resolve) {1237 return () => Services.tm.idleDispatchToMainThread(() => {1238 win.requestAnimationFrame(resolve);1239 });1240 }1241 // Exit fullscreen and wait for window to resize.1242 async function exitFullscreen() {1243 return new Promise(resolve => {1244 win.addEventListener("sizemodechange", optimisedResize(resolve), {once: true});1245 win.fullScreen = false;1246 });1247 }1248 // Synchronous resize to |width| and |height| dimensions.1249 async function resizeWindow(width, height) {1250 return new Promise(resolve => {1251 win.addEventListener("resize", optimisedResize(resolve), {once: true});1252 win.resizeTo(width, height);1253 });1254 }1255 // Wait until window size has changed. We can't wait for the1256 // user-requested window size as this may not be achievable on the1257 // current system.1258 const windowResizeChange = async () => {1259 return wait.until((resolve, reject) => {1260 let curRect = this.curBrowser.rect;1261 if (curRect.width != origRect.width &&1262 curRect.height != origRect.height) {1263 resolve();1264 } else {1265 reject();1266 }1267 });1268 };1269 // Wait for the window position to change.1270 async function windowPosition(x, y) {1271 return wait.until((resolve, reject) => {1272 if ((x == win.screenX && y == win.screenY) ||1273 (win.screenX != origRect.x || win.screenY != origRect.y)) {1274 resolve();1275 } else {1276 reject();1277 }1278 });1279 }1280 if (win.windowState == win.STATE_FULLSCREEN) {1281 await exitFullscreen();1282 }1283 if (height != null && width != null) {1284 assert.positiveInteger(height);1285 assert.positiveInteger(width);1286 if (win.outerWidth != width || win.outerHeight != height) {1287 await resizeWindow(width, height);1288 await windowResizeChange();1289 }1290 }1291 if (x != null && y != null) {1292 assert.integer(x);1293 assert.integer(y);1294 win.moveTo(x, y);1295 await windowPosition(x, y);1296 }1297 return this.curBrowser.rect;1298};1299/**1300 * Switch current top-level browsing context by name or server-assigned1301 * ID. Searches for windows by name, then ID. Content windows take1302 * precedence.1303 *1304 * @param {string} name1305 * Target name or ID of the window to switch to.1306 * @param {boolean=} focus1307 * A boolean value which determines whether to focus1308 * the window. Defaults to true.1309 */1310GeckoDriver.prototype.switchToWindow = function* (cmd, resp) {1311 let focus = true;1312 if (typeof cmd.parameters.focus != "undefined") {1313 focus = cmd.parameters.focus;1314 }1315 // Window IDs are internally handled as numbers, but here it could1316 // also be the name of the window.1317 let switchTo = parseInt(cmd.parameters.name);1318 if (isNaN(switchTo)) {1319 switchTo = cmd.parameters.name;1320 }1321 let byNameOrId = function(win, windowId) {1322 return switchTo === win.name || switchTo === windowId;1323 };1324 let found = this.findWindow(this.windows, byNameOrId);1325 if (found) {1326 yield this.setWindowHandle(found, focus);1327 } else {1328 throw new NoSuchWindowError(`Unable to locate window: ${switchTo}`);1329 }1330};1331/**1332 * Find a specific window according to some filter function.1333 *1334 * @param {Iterable.<Window>} winIterable1335 * Iterable that emits Windows.1336 * @param {function(Window, number): boolean} filter1337 * A callback function taking two arguments; the window and1338 * the outerId of the window, and returning a boolean indicating1339 * whether the window is the target.1340 *1341 * @return {Object}1342 * A window handle object containing the window and some1343 * associated metadata.1344 */1345GeckoDriver.prototype.findWindow = function(winIterable, filter) {1346 for (let win of winIterable) {1347 let outerId = getOuterWindowId(win);1348 let tabBrowser = browser.getTabBrowser(win);1349 // In case the wanted window is a chrome window, we are done.1350 if (filter(win, outerId)) {1351 return {win, outerId, hasTabBrowser: !!tabBrowser};1352 // Otherwise check if the chrome window has a tab browser, and that it1353 // contains a tab with the wanted window handle.1354 } else if (tabBrowser && tabBrowser.tabs) {1355 for (let i = 0; i < tabBrowser.tabs.length; ++i) {1356 let contentBrowser = browser.getBrowserForTab(tabBrowser.tabs[i]);1357 let contentWindowId = this.getIdForBrowser(contentBrowser);1358 if (filter(win, contentWindowId)) {1359 return {1360 win,1361 outerId,1362 hasTabBrowser: true,1363 tabIndex: i,1364 };1365 }1366 }1367 }1368 }1369 return null;1370};1371/**1372 * Switch the marionette window to a given window. If the browser in1373 * the window is unregistered, registers that browser and waits for1374 * the registration is complete. If |focus| is true then set the focus1375 * on the window.1376 *1377 * @param {Object} winProperties1378 * Object containing window properties such as returned from1379 * GeckoDriver#findWindow1380 * @param {boolean=} focus1381 * A boolean value which determines whether to focus the window.1382 * Defaults to true.1383 */1384GeckoDriver.prototype.setWindowHandle = function* (1385 winProperties, focus = true) {1386 if (!(winProperties.outerId in this.browsers)) {1387 // Initialise Marionette if the current chrome window has not been seen1388 // before. Also register the initial tab, if one exists.1389 let registerBrowsers, browserListening;1390 if (winProperties.hasTabBrowser) {1391 registerBrowsers = this.registerPromise();1392 browserListening = this.listeningPromise();1393 }1394 this.startBrowser(winProperties.win, false /* isNewSession */);1395 if (registerBrowsers && browserListening) {1396 yield registerBrowsers;1397 yield browserListening;1398 }1399 } else {1400 // Otherwise switch to the known chrome window, and activate the tab1401 // if it's a content browser.1402 this.curBrowser = this.browsers[winProperties.outerId];1403 if ("tabIndex" in winProperties) {1404 this.curBrowser.switchToTab(1405 winProperties.tabIndex, winProperties.win, focus);1406 }1407 }1408};1409GeckoDriver.prototype.getActiveFrame = function(cmd, resp) {1410 assert.window(this.getCurrentWindow());1411 switch (this.context) {1412 case Context.CHROME:1413 // no frame means top-level1414 resp.body.value = null;1415 if (this.curFrame) {1416 let elRef = this.curBrowser.seenEls1417 .add(this.curFrame.frameElement);1418 let el = element.makeWebElement(elRef);1419 resp.body.value = el;1420 }1421 break;1422 case Context.CONTENT:1423 resp.body.value = null;1424 if (this.currentFrameElement !== null) {1425 let el = element.makeWebElement(this.currentFrameElement);1426 resp.body.value = el;1427 }1428 break;1429 }1430};1431/**1432 * Set the current browsing context for future commands to the parent1433 * of the current browsing context.1434 *1435 * @throws {NoSuchWindowError}1436 * Top-level browsing context has been discarded.1437 * @throws {UnexpectedAlertOpenError}1438 * A modal dialog is open, blocking this operation.1439 */1440GeckoDriver.prototype.switchToParentFrame = function* (cmd, resp) {1441 assert.window(this.getCurrentWindow());1442 assert.noUserPrompt(this.dialog);1443 yield this.listener.switchToParentFrame();1444};1445/**1446 * Switch to a given frame within the current window.1447 *1448 * @param {Object} element1449 * A web element reference to the element to switch to.1450 * @param {(string|number)} id1451 * If element is not defined, then this holds either the id, name,1452 * or index of the frame to switch to.1453 *1454 * @throws {NoSuchWindowError}1455 * Top-level browsing context has been discarded.1456 * @throws {UnexpectedAlertOpenError}1457 * A modal dialog is open, blocking this operation.1458 */1459GeckoDriver.prototype.switchToFrame = function* (cmd, resp) {1460 assert.window(this.getCurrentWindow());1461 assert.noUserPrompt(this.dialog);1462 let {id, element, focus} = cmd.parameters;1463 const otherErrorsExpr = /about:.+(error)|(blocked)\?/;1464 const checkTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);1465 let curWindow = this.getCurrentWindow();1466 let checkLoad = function() {1467 let win = this.getCurrentWindow();1468 if (win.document.readyState == "complete") {1469 return;1470 } else if (win.document.readyState == "interactive") {1471 let documentURI = win.document.documentURI;1472 if (documentURI.startsWith("about:certerror")) {1473 throw new InsecureCertificateError();1474 } else if (otherErrorsExpr.exec(documentURI)) {1475 throw new UnknownError("Reached error page: " + documentURI);1476 }1477 }1478 checkTimer.initWithCallback(1479 checkLoad.bind(this), 100, Ci.nsITimer.TYPE_ONE_SHOT);1480 };1481 if (this.context == Context.CHROME) {1482 let foundFrame = null;1483 // just focus1484 if (typeof id == "undefined" && typeof element == "undefined") {1485 this.curFrame = null;1486 if (focus) {1487 this.mainFrame.focus();1488 }1489 checkTimer.initWithCallback(1490 checkLoad.bind(this), 100, Ci.nsITimer.TYPE_ONE_SHOT);1491 return;1492 }1493 // by element1494 if (this.curBrowser.seenEls.has(element)) {1495 // HTMLIFrameElement1496 let wantedFrame = this.curBrowser.seenEls.get(1497 element, {frame: curWindow});1498 // Deal with an embedded xul:browser case1499 if (wantedFrame.tagName == "xul:browser" ||1500 wantedFrame.tagName == "browser") {1501 curWindow = wantedFrame.contentWindow;1502 this.curFrame = curWindow;1503 if (focus) {1504 this.curFrame.focus();1505 }1506 checkTimer.initWithCallback(1507 checkLoad.bind(this), 100, Ci.nsITimer.TYPE_ONE_SHOT);1508 return;1509 }1510 // Check if the frame is XBL anonymous1511 let parent = curWindow.document.getBindingParent(wantedFrame);1512 // Shadow nodes also show up in getAnonymousNodes, we should1513 // ignore them.1514 if (parent &&1515 !(parent.shadowRoot && parent.shadowRoot.contains(wantedFrame))) {1516 const doc = curWindow.document;1517 let anonNodes = [...doc.getAnonymousNodes(parent) || []];1518 if (anonNodes.length > 0) {1519 let el = wantedFrame;1520 while (el) {1521 if (anonNodes.indexOf(el) > -1) {1522 curWindow = wantedFrame.contentWindow;1523 this.curFrame = curWindow;1524 if (focus) {1525 this.curFrame.focus();1526 }1527 checkTimer.initWithCallback(1528 checkLoad.bind(this), 100, Ci.nsITimer.TYPE_ONE_SHOT);1529 return;1530 }1531 el = el.parentNode;1532 }1533 }1534 }1535 // else, assume iframe1536 let frames = curWindow.document.getElementsByTagName("iframe");1537 let numFrames = frames.length;1538 for (let i = 0; i < numFrames; i++) {1539 let wrappedEl = new XPCNativeWrapper(frames[i]);1540 let wrappedWanted = new XPCNativeWrapper(wantedFrame);1541 if (wrappedEl == wrappedWanted) {1542 curWindow = frames[i].contentWindow;1543 this.curFrame = curWindow;1544 if (focus) {1545 this.curFrame.focus();1546 }1547 checkTimer.initWithCallback(1548 checkLoad.bind(this), 100, Ci.nsITimer.TYPE_ONE_SHOT);1549 return;1550 }1551 }1552 }1553 switch (typeof id) {1554 case "string" :1555 let foundById = null;1556 let frames = curWindow.document.getElementsByTagName("iframe");1557 let numFrames = frames.length;1558 for (let i = 0; i < numFrames; i++) {1559 // give precedence to name1560 let frame = frames[i];1561 if (frame.getAttribute("name") == id) {1562 foundFrame = i;1563 curWindow = frame.contentWindow;1564 break;1565 } else if (foundById === null && frame.id == id) {1566 foundById = i;1567 }1568 }1569 if (foundFrame === null && foundById !== null) {1570 foundFrame = foundById;1571 curWindow = frames[foundById].contentWindow;1572 }1573 break;1574 case "number":1575 if (typeof curWindow.frames[id] != "undefined") {1576 foundFrame = id;1577 let frameEl = curWindow.frames[foundFrame].frameElement;1578 curWindow = frameEl.contentWindow;1579 }1580 break;1581 }1582 if (foundFrame !== null) {1583 this.curFrame = curWindow;1584 if (focus) {1585 this.curFrame.focus();1586 }1587 checkTimer.initWithCallback(1588 checkLoad.bind(this), 100, Ci.nsITimer.TYPE_ONE_SHOT);1589 } else {1590 throw new NoSuchFrameError(`Unable to locate frame: ${id}`);1591 }1592 } else if (this.context == Context.CONTENT) {1593 if (!id && !element &&1594 this.curBrowser.frameManager.currentRemoteFrame !== null) {1595 // We're currently using a ChromeMessageSender for a remote frame,1596 // so this request indicates we need to switch back to the top-level1597 // (parent) frame. We'll first switch to the parent's (global)1598 // ChromeMessageBroadcaster, so we send the message to the right1599 // listener.1600 this.switchToGlobalMessageManager();1601 }1602 cmd.command_id = cmd.id;1603 let res = yield this.listener.switchToFrame(cmd.parameters);1604 if (res) {1605 let {win: winId, frame: frameId} = res;1606 this.mm = this.curBrowser.frameManager.getFrameMM(winId, frameId);1607 let registerBrowsers = this.registerPromise();1608 let browserListening = this.listeningPromise();1609 this.oopFrameId =1610 this.curBrowser.frameManager.switchToFrame(winId, frameId);1611 yield registerBrowsers;1612 yield browserListening;1613 }1614 }1615};1616GeckoDriver.prototype.getTimeouts = function(cmd, resp) {1617 return this.timeouts;1618};1619/**1620 * Set timeout for page loading, searching, and scripts.1621 *1622 * @param {Object.<string, number>}1623 * Dictionary of timeout types and their new value, where all timeout1624 * types are optional.1625 *1626 * @throws {InvalidArgumentError}1627 * If timeout type key is unknown, or the value provided with it is1628 * not an integer.1629 */1630GeckoDriver.prototype.setTimeouts = function(cmd, resp) {1631 // merge with existing timeouts1632 let merged = Object.assign(this.timeouts.toJSON(), cmd.parameters);1633 this.timeouts = session.Timeouts.fromJSON(merged);1634};1635/** Single tap. */1636GeckoDriver.prototype.singleTap = function*(cmd, resp) {1637 assert.window(this.getCurrentWindow());1638 let {id, x, y} = cmd.parameters;1639 switch (this.context) {1640 case Context.CHROME:1641 throw new UnsupportedOperationError(1642 "Command 'singleTap' is not yet available in chrome context");1643 case Context.CONTENT:1644 this.addFrameCloseListener("tap");1645 yield this.listener.singleTap(id, x, y);1646 break;1647 }1648};1649/**1650 * Perform a series of grouped actions at the specified points in time.1651 *1652 * @param {Array.<?>} actions1653 * Array of objects that each represent an action sequence.1654 *1655 * @throws {UnsupportedOperationError}1656 * Not yet available in current context.1657 * @throws {NoSuchWindowError}1658 * Top-level browsing context has been discarded.1659 * @throws {UnexpectedAlertOpenError}1660 * A modal dialog is open, blocking this operation.1661 */1662GeckoDriver.prototype.performActions = function* (cmd, resp) {1663 assert.content(this.context,1664 "Command 'performActions' is not yet available in chrome context");1665 assert.window(this.getCurrentWindow());1666 assert.noUserPrompt(this.dialog);1667 let actions = cmd.parameters.actions;1668 yield this.listener.performActions({"actions": actions});1669};1670/**1671 * Release all the keys and pointer buttons that are currently depressed.1672 *1673 * @throws {UnsupportedOperationError}1674 * Not available in current context.1675 * @throws {NoSuchWindowError}1676 * Top-level browsing context has been discarded.1677 * @throws {UnexpectedAlertOpenError}1678 * A modal dialog is open, blocking this operation.1679 */1680GeckoDriver.prototype.releaseActions = function*(cmd, resp) {1681 assert.content(this.context);1682 assert.window(this.getCurrentWindow());1683 assert.noUserPrompt(this.dialog);1684 yield this.listener.releaseActions();1685};1686/**1687 * An action chain.1688 *1689 * @param {Object} value1690 * A nested array where the inner array represents each event,1691 * and the outer array represents a collection of events.1692 *1693 * @return {number}1694 * Last touch ID.1695 *1696 * @throws {UnsupportedOperationError}1697 * Not applicable to application.1698 * @throws {NoSuchWindowError}1699 * Top-level browsing context has been discarded.1700 * @throws {UnexpectedAlertOpenError}1701 * A modal dialog is open, blocking this operation.1702 */1703GeckoDriver.prototype.actionChain = function*(cmd, resp) {1704 const win = assert.window(this.getCurrentWindow());1705 assert.noUserPrompt(this.dialog);1706 let {chain, nextId} = cmd.parameters;1707 switch (this.context) {1708 case Context.CHROME:1709 // be conservative until this has a use case and is established1710 // to work as expected in Fennec1711 assert.firefox();1712 resp.body.value = yield this.legacyactions.dispatchActions(1713 chain, nextId, {frame: win}, this.curBrowser.seenEls);1714 break;1715 case Context.CONTENT:1716 this.addFrameCloseListener("action chain");1717 resp.body.value = yield this.listener.actionChain(chain, nextId);1718 break;1719 }1720};1721/**1722 * A multi-action chain.1723 *1724 * @param {Object} value1725 * A nested array where the inner array represents eache vent,1726 * the middle array represents a collection of events for each1727 * finger, and the outer array represents all fingers.1728 *1729 * @throws {UnsupportedOperationError}1730 * Not available in current context.1731 * @throws {NoSuchWindowError}1732 * Top-level browsing context has been discarded.1733 * @throws {UnexpectedAlertOpenError}1734 * A modal dialog is open, blocking this operation.1735 */1736GeckoDriver.prototype.multiAction = function* (cmd, resp) {1737 assert.content(this.context);1738 assert.window(this.getCurrentWindow());1739 assert.noUserPrompt(this.dialog);1740 let {value, max_length} = cmd.parameters;1741 this.addFrameCloseListener("multi action chain");1742 yield this.listener.multiAction(value, max_length);1743};1744/**1745 * Find an element using the indicated search strategy.1746 *1747 * @param {string} using1748 * Indicates which search method to use.1749 * @param {string} value1750 * Value the client is looking for.1751 *1752 * @throws {NoSuchWindowError}1753 * Top-level browsing context has been discarded.1754 * @throws {UnexpectedAlertOpenError}1755 * A modal dialog is open, blocking this operation.1756 */1757GeckoDriver.prototype.findElement = function* (cmd, resp) {1758 const win = assert.window(this.getCurrentWindow());1759 assert.noUserPrompt(this.dialog);1760 let strategy = cmd.parameters.using;1761 let expr = cmd.parameters.value;1762 let opts = {1763 startNode: cmd.parameters.element,1764 timeout: this.timeouts.implicit,1765 all: false,1766 };1767 switch (this.context) {1768 case Context.CHROME:1769 if (!SUPPORTED_STRATEGIES.has(strategy)) {1770 throw new InvalidSelectorError(`Strategy not supported: ${strategy}`);1771 }1772 let container = {frame: win};1773 if (opts.startNode) {1774 opts.startNode = this.curBrowser.seenEls.get(1775 opts.startNode, container);1776 }1777 let el = yield element.find(container, strategy, expr, opts);1778 let elRef = this.curBrowser.seenEls.add(el);1779 let webEl = element.makeWebElement(elRef);1780 resp.body.value = webEl;1781 break;1782 case Context.CONTENT:1783 resp.body.value = yield this.listener.findElementContent(1784 strategy,1785 expr,1786 opts);1787 break;1788 }1789};1790/**1791 * Find elements using the indicated search strategy.1792 *1793 * @param {string} using1794 * Indicates which search method to use.1795 * @param {string} value1796 * Value the client is looking for.1797 */1798GeckoDriver.prototype.findElements = function*(cmd, resp) {1799 let win = assert.window(this.getCurrentWindow());1800 let strategy = cmd.parameters.using;1801 let expr = cmd.parameters.value;1802 let opts = {1803 startNode: cmd.parameters.element,1804 timeout: this.timeouts.implicit,1805 all: true,1806 };1807 switch (this.context) {1808 case Context.CHROME:1809 if (!SUPPORTED_STRATEGIES.has(strategy)) {1810 throw new InvalidSelectorError(`Strategy not supported: ${strategy}`);1811 }1812 let container = {frame: win};1813 if (opts.startNode) {1814 opts.startNode = this.curBrowser.seenEls.get(1815 opts.startNode, container);1816 }1817 let els = yield element.find(container, strategy, expr, opts);1818 let elRefs = this.curBrowser.seenEls.addAll(els);1819 let webEls = elRefs.map(element.makeWebElement);1820 resp.body = webEls;1821 break;1822 case Context.CONTENT:1823 resp.body = yield this.listener.findElementsContent(1824 cmd.parameters.using,1825 cmd.parameters.value,1826 opts);1827 break;1828 }1829};1830/**1831 * Return the active element on the page.1832 *1833 * @return {WebElement}1834 * Active element of the current browsing context's document element.1835 *1836 * @throws {UnsupportedOperationError}1837 * Not available in current context.1838 * @throws {NoSuchWindowError}1839 * Top-level browsing context has been discarded.1840 * @throws {UnexpectedAlertOpenError}1841 * A modal dialog is open, blocking this operation.1842 */1843GeckoDriver.prototype.getActiveElement = function* (cmd, resp) {1844 assert.content(this.context);1845 assert.window(this.getCurrentWindow());1846 assert.noUserPrompt(this.dialog);1847 resp.body.value = yield this.listener.getActiveElement();1848};1849/**1850 * Send click event to element.1851 *1852 * @param {string} id1853 * Reference ID to the element that will be clicked.1854 *1855 * @throws {NoSuchWindowError}1856 * Top-level browsing context has been discarded.1857 * @throws {UnexpectedAlertOpenError}1858 * A modal dialog is open, blocking this operation.1859 */1860GeckoDriver.prototype.clickElement = function* (cmd, resp) {1861 const win = assert.window(this.getCurrentWindow());1862 assert.noUserPrompt(this.dialog);1863 let id = cmd.parameters.id;1864 switch (this.context) {1865 case Context.CHROME:1866 let el = this.curBrowser.seenEls.get(id, {frame: win});1867 yield interaction.clickElement(el, this.a11yChecks);1868 break;1869 case Context.CONTENT:1870 // We need to protect against the click causing an OOP frame1871 // to close. This fires the mozbrowserclose event when it closes1872 // so we need to listen for it and then just send an error back.1873 // The person making the call should be aware something is not right1874 // and handle accordingly.1875 this.addFrameCloseListener("click");1876 let click = this.listener.clickElement(1877 {id, pageTimeout: this.timeouts.pageLoad});1878 // If a reload of the frame script interrupts our page load, this will1879 // never return. We need to re-issue this request to correctly poll for1880 // readyState and send errors.1881 this.curBrowser.pendingCommands.push(() => {1882 let parameters = {1883 // TODO(ato): Bug 12425951884 command_id: this.listener.activeMessageId,1885 pageTimeout: this.timeouts.pageLoad,1886 startTime: new Date().getTime(),1887 };1888 this.mm.broadcastAsyncMessage(1889 "Marionette:waitForPageLoaded" + this.curBrowser.curFrameId,1890 parameters);1891 });1892 yield click;1893 break;1894 }1895};1896/**1897 * Get a given attribute of an element.1898 *1899 * @param {string} id1900 * Web element reference ID to the element that will be inspected.1901 * @param {string} name1902 * Name of the attribute which value to retrieve.1903 *1904 * @return {string}1905 * Value of the attribute.1906 *1907 * @throws {NoSuchWindowError}1908 * Top-level browsing context has been discarded.1909 * @throws {UnexpectedAlertOpenError}1910 * A modal dialog is open, blocking this operation.1911 */1912GeckoDriver.prototype.getElementAttribute = function*(cmd, resp) {1913 const win = assert.window(this.getCurrentWindow());1914 assert.noUserPrompt(this.dialog);1915 let {id, name} = cmd.parameters;1916 switch (this.context) {1917 case Context.CHROME:1918 let el = this.curBrowser.seenEls.get(id, {frame: win});1919 resp.body.value = el.getAttribute(name);1920 break;1921 case Context.CONTENT:1922 resp.body.value = yield this.listener.getElementAttribute(id, name);1923 break;1924 }1925};1926/**1927 * Returns the value of a property associated with given element.1928 *1929 * @param {string} id1930 * Web element reference ID to the element that will be inspected.1931 * @param {string} name1932 * Name of the property which value to retrieve.1933 *1934 * @return {string}1935 * Value of the property.1936 *1937 * @throws {NoSuchWindowError}1938 * Top-level browsing context has been discarded.1939 * @throws {UnexpectedAlertOpenError}1940 * A modal dialog is open, blocking this operation.1941 */1942GeckoDriver.prototype.getElementProperty = function*(cmd, resp) {1943 const win = assert.window(this.getCurrentWindow());1944 assert.noUserPrompt(this.dialog);1945 let {id, name} = cmd.parameters;1946 switch (this.context) {1947 case Context.CHROME:1948 let el = this.curBrowser.seenEls.get(id, {frame: win});1949 resp.body.value = el[name];1950 break;1951 case Context.CONTENT:1952 resp.body.value = yield this.listener.getElementProperty(id, name);1953 break;1954 }1955};1956/**1957 * Get the text of an element, if any. Includes the text of all child1958 * elements.1959 *1960 * @param {string} id1961 * Reference ID to the element that will be inspected.1962 *1963 * @return {string}1964 * Element's text "as rendered".1965 *1966 * @throws {NoSuchWindowError}1967 * Top-level browsing context has been discarded.1968 * @throws {UnexpectedAlertOpenError}1969 * A modal dialog is open, blocking this operation.1970 */1971GeckoDriver.prototype.getElementText = function*(cmd, resp) {1972 const win = assert.window(this.getCurrentWindow());1973 assert.noUserPrompt(this.dialog);1974 let id = cmd.parameters.id;1975 switch (this.context) {1976 case Context.CHROME:1977 // for chrome, we look at text nodes, and any node with a "label" field1978 let el = this.curBrowser.seenEls.get(id, {frame: win});1979 let lines = [];1980 this.getVisibleText(el, lines);1981 resp.body.value = lines.join("\n");1982 break;1983 case Context.CONTENT:1984 resp.body.value = yield this.listener.getElementText(id);1985 break;1986 }1987};1988/**1989 * Get the tag name of the element.1990 *1991 * @param {string} id1992 * Reference ID to the element that will be inspected.1993 *1994 * @return {string}1995 * Local tag name of element.1996 *1997 * @throws {NoSuchWindowError}1998 * Top-level browsing context has been discarded.1999 * @throws {UnexpectedAlertOpenError}2000 * A modal dialog is open, blocking this operation.2001 */2002GeckoDriver.prototype.getElementTagName = function*(cmd, resp) {2003 const win = assert.window(this.getCurrentWindow());2004 assert.noUserPrompt(this.dialog);2005 let id = cmd.parameters.id;2006 switch (this.context) {2007 case Context.CHROME:2008 let el = this.curBrowser.seenEls.get(id, {frame: win});2009 resp.body.value = el.tagName.toLowerCase();2010 break;2011 case Context.CONTENT:2012 resp.body.value = yield this.listener.getElementTagName(id);2013 break;2014 }2015};2016/**2017 * Check if element is displayed.2018 *2019 * @param {string} id2020 * Reference ID to the element that will be inspected.2021 *2022 * @return {boolean}2023 * True if displayed, false otherwise.2024 *2025 * @throws {NoSuchWindowError}2026 * Top-level browsing context has been discarded.2027 * @throws {UnexpectedAlertOpenError}2028 * A modal dialog is open, blocking this operation.2029 */2030GeckoDriver.prototype.isElementDisplayed = function*(cmd, resp) {2031 const win = assert.window(this.getCurrentWindow());2032 assert.noUserPrompt(this.dialog);2033 let id = cmd.parameters.id;2034 switch (this.context) {2035 case Context.CHROME:2036 let el = this.curBrowser.seenEls.get(id, {frame: win});2037 resp.body.value = yield interaction.isElementDisplayed(2038 el, this.a11yChecks);2039 break;2040 case Context.CONTENT:2041 resp.body.value = yield this.listener.isElementDisplayed(id);2042 break;2043 }2044};2045/**2046 * Return the property of the computed style of an element.2047 *2048 * @param {string} id2049 * Reference ID to the element that will be checked.2050 * @param {string} propertyName2051 * CSS rule that is being requested.2052 *2053 * @return {string}2054 * Value of |propertyName|.2055 *2056 * @throws {NoSuchWindowError}2057 * Top-level browsing context has been discarded.2058 * @throws {UnexpectedAlertOpenError}2059 * A modal dialog is open, blocking this operation.2060 */2061GeckoDriver.prototype.getElementValueOfCssProperty = function*(cmd, resp) {2062 const win = assert.window(this.getCurrentWindow());2063 assert.noUserPrompt(this.dialog);2064 let {id, propertyName: prop} = cmd.parameters;2065 switch (this.context) {2066 case Context.CHROME:2067 let el = this.curBrowser.seenEls.get(id, {frame: win});2068 let sty = win.document.defaultView.getComputedStyle(el);2069 resp.body.value = sty.getPropertyValue(prop);2070 break;2071 case Context.CONTENT:2072 resp.body.value = yield this.listener2073 .getElementValueOfCssProperty(id, prop);2074 break;2075 }2076};2077/**2078 * Check if element is enabled.2079 *2080 * @param {string} id2081 * Reference ID to the element that will be checked.2082 *2083 * @return {boolean}2084 * True if enabled, false if disabled.2085 *2086 * @throws {NoSuchWindowError}2087 * Top-level browsing context has been discarded.2088 * @throws {UnexpectedAlertOpenError}2089 * A modal dialog is open, blocking this operation.2090 */2091GeckoDriver.prototype.isElementEnabled = function*(cmd, resp) {2092 const win = assert.window(this.getCurrentWindow());2093 assert.noUserPrompt(this.dialog);2094 let id = cmd.parameters.id;2095 switch (this.context) {2096 case Context.CHROME:2097 // Selenium atom doesn't quite work here2098 let el = this.curBrowser.seenEls.get(id, {frame: win});2099 resp.body.value = yield interaction.isElementEnabled(2100 el, this.a11yChecks);2101 break;2102 case Context.CONTENT:2103 resp.body.value = yield this.listener.isElementEnabled(id);2104 break;2105 }2106};2107/**2108 * Check if element is selected.2109 *2110 * @param {string} id2111 * Reference ID to the element that will be checked.2112 *2113 * @return {boolean}2114 * True if selected, false if unselected.2115 *2116 * @throws {NoSuchWindowError}2117 * Top-level browsing context has been discarded.2118 * @throws {UnexpectedAlertOpenError}2119 * A modal dialog is open, blocking this operation.2120 */2121GeckoDriver.prototype.isElementSelected = function*(cmd, resp) {2122 const win = assert.window(this.getCurrentWindow());2123 assert.noUserPrompt(this.dialog);2124 let id = cmd.parameters.id;2125 switch (this.context) {2126 case Context.CHROME:2127 // Selenium atom doesn't quite work here2128 let el = this.curBrowser.seenEls.get(id, {frame: win});2129 resp.body.value = yield interaction.isElementSelected(2130 el, this.a11yChecks);2131 break;2132 case Context.CONTENT:2133 resp.body.value = yield this.listener.isElementSelected(id);2134 break;2135 }2136};2137/**2138 * @throws {NoSuchWindowError}2139 * Top-level browsing context has been discarded.2140 * @throws {UnexpectedAlertOpenError}2141 * A modal dialog is open, blocking this operation.2142 */2143GeckoDriver.prototype.getElementRect = function*(cmd, resp) {2144 const win = assert.window(this.getCurrentWindow());2145 assert.noUserPrompt(this.dialog);2146 let id = cmd.parameters.id;2147 switch (this.context) {2148 case Context.CHROME:2149 let el = this.curBrowser.seenEls.get(id, {frame: win});2150 let rect = el.getBoundingClientRect();2151 resp.body = {2152 x: rect.x + win.pageXOffset,2153 y: rect.y + win.pageYOffset,2154 width: rect.width,2155 height: rect.height,2156 };2157 break;2158 case Context.CONTENT:2159 resp.body = yield this.listener.getElementRect(id);2160 break;2161 }2162};2163/**2164 * Send key presses to element after focusing on it.2165 *2166 * @param {string} id2167 * Reference ID to the element that will be checked.2168 * @param {string} value2169 * Value to send to the element.2170 *2171 * @throws {NoSuchWindowError}2172 * Top-level browsing context has been discarded.2173 * @throws {UnexpectedAlertOpenError}2174 * A modal dialog is open, blocking this operation.2175 */2176GeckoDriver.prototype.sendKeysToElement = function*(cmd, resp) {2177 const win = assert.window(this.getCurrentWindow());2178 assert.noUserPrompt(this.dialog);2179 let {id, text} = cmd.parameters;2180 assert.string(text);2181 switch (this.context) {2182 case Context.CHROME:2183 let el = this.curBrowser.seenEls.get(id, {frame: win});2184 yield interaction.sendKeysToElement(2185 el, text, true, this.a11yChecks);2186 break;2187 case Context.CONTENT:2188 yield this.listener.sendKeysToElement(id, text);2189 break;2190 }2191};2192/**2193 * Clear the text of an element.2194 *2195 * @param {string} id2196 * Reference ID to the element that will be cleared.2197 *2198 * @throws {NoSuchWindowError}2199 * Top-level browsing context has been discarded.2200 * @throws {UnexpectedAlertOpenError}2201 * A modal dialog is open, blocking this operation.2202 */2203GeckoDriver.prototype.clearElement = function*(cmd, resp) {2204 const win = assert.window(this.getCurrentWindow());2205 assert.noUserPrompt(this.dialog);2206 let id = cmd.parameters.id;2207 switch (this.context) {2208 case Context.CHROME:2209 // the selenium atom doesn't work here2210 let el = this.curBrowser.seenEls.get(id, {frame: win});2211 if (el.nodeName == "textbox") {2212 el.value = "";2213 } else if (el.nodeName == "checkbox") {2214 el.checked = false;2215 }2216 break;2217 case Context.CONTENT:2218 yield this.listener.clearElement(id);2219 break;2220 }2221};2222/**2223 * Switch to shadow root of the given host element.2224 *2225 * @param {string} id element id.2226 */2227GeckoDriver.prototype.switchToShadowRoot = function*(cmd, resp) {2228 assert.content(this.context);2229 assert.window(this.getCurrentWindow());2230 let id = cmd.parameters.id;2231 yield this.listener.switchToShadowRoot(id);2232};2233/**2234 * Add a single cookie to the cookie store associated with the active2235 * document's address.2236 *2237 * @param {Map.<string, (string|number|boolean)> cookie2238 * Cookie object.2239 *2240 * @throws {UnsupportedOperationError}2241 * Not available in current context.2242 * @throws {NoSuchWindowError}2243 * Top-level browsing context has been discarded.2244 * @throws {UnexpectedAlertOpenError}2245 * A modal dialog is open, blocking this operation.2246 * @throws {InvalidCookieDomainError}2247 * If <var>cookie</var> is for a different domain than the active2248 * document's host.2249 */2250GeckoDriver.prototype.addCookie = function(cmd, resp) {2251 assert.content(this.context);2252 assert.window(this.getCurrentWindow());2253 assert.noUserPrompt(this.dialog);2254 let {protocol, hostname} = this.currentURL;2255 const networkSchemes = ["ftp:", "http:", "https:"];2256 if (!networkSchemes.includes(protocol)) {2257 throw new InvalidCookieDomainError("Document is cookie-averse");2258 }2259 let newCookie = cookie.fromJSON(cmd.parameters.cookie);2260 if (typeof newCookie.domain == "undefined") {2261 newCookie.domain = hostname;2262 }2263 cookie.add(newCookie, {restrictToHost: hostname});2264};2265/**2266 * Get all the cookies for the current domain.2267 *2268 * This is the equivalent of calling <code>document.cookie</code> and2269 * parsing the result.2270 *2271 * @throws {UnsupportedOperationError}2272 * Not available in current context.2273 * @throws {NoSuchWindowError}2274 * Top-level browsing context has been discarded.2275 * @throws {UnexpectedAlertOpenError}2276 * A modal dialog is open, blocking this operation.2277 */2278GeckoDriver.prototype.getCookies = function(cmd, resp) {2279 assert.content(this.context);2280 assert.window(this.getCurrentWindow());2281 assert.noUserPrompt(this.dialog);2282 let {hostname, pathname} = this.currentURL;2283 resp.body = [...cookie.iter(hostname, pathname)];2284};2285/**2286 * Delete all cookies that are visible to a document.2287 *2288 * @throws {UnsupportedOperationError}2289 * Not available in current context.2290 * @throws {NoSuchWindowError}2291 * Top-level browsing context has been discarded.2292 * @throws {UnexpectedAlertOpenError}2293 * A modal dialog is open, blocking this operation.2294 */2295GeckoDriver.prototype.deleteAllCookies = function(cmd, resp) {2296 assert.content(this.context);2297 assert.window(this.getCurrentWindow());2298 assert.noUserPrompt(this.dialog);2299 let {hostname, pathname} = this.currentURL;2300 for (let toDelete of cookie.iter(hostname, pathname)) {2301 cookie.remove(toDelete);2302 }2303};2304/**2305 * Delete a cookie by name.2306 *2307 * @throws {UnsupportedOperationError}2308 * Not available in current context.2309 * @throws {NoSuchWindowError}2310 * Top-level browsing context has been discarded.2311 * @throws {UnexpectedAlertOpenError}2312 * A modal dialog is open, blocking this operation.2313 */2314GeckoDriver.prototype.deleteCookie = function(cmd, resp) {2315 assert.content(this.context);2316 assert.window(this.getCurrentWindow());2317 assert.noUserPrompt(this.dialog);2318 let {hostname, pathname} = this.currentURL;2319 let candidateName = assert.string(cmd.parameters.name);2320 for (let toDelete of cookie.iter(hostname, pathname)) {2321 if (toDelete.name === candidateName) {2322 return cookie.remove(toDelete);2323 }2324 }2325 throw UnknownError("Unable to find cookie");2326};2327/**2328 * Close the currently selected tab/window.2329 *2330 * With multiple open tabs present the currently selected tab will2331 * be closed. Otherwise the window itself will be closed. If it is the2332 * last window currently open, the window will not be closed to prevent2333 * a shutdown of the application. Instead the returned list of window2334 * handles is empty.2335 *2336 * @return {Array.<string>}2337 * Unique window handles of remaining windows.2338 *2339 * @throws {NoSuchWindowError}2340 * Top-level browsing context has been discarded.2341 * @throws {UnexpectedAlertOpenError}2342 * A modal dialog is open, blocking this operation.2343 */2344GeckoDriver.prototype.close = function(cmd, resp) {2345 assert.contentBrowser(this.curBrowser);2346 assert.noUserPrompt(this.dialog);2347 let nwins = 0;2348 for (let win of this.windows) {2349 // For browser windows count the tabs. Otherwise take the window itself.2350 let tabbrowser = browser.getTabBrowser(win);2351 if (tabbrowser && tabbrowser.tabs) {2352 nwins += tabbrowser.tabs.length;2353 } else {2354 nwins += 1;2355 }2356 }2357 // If there is only one window left, do not close it. Instead return2358 // a faked empty array of window handles. This will instruct geckodriver2359 // to terminate the application.2360 if (nwins === 1) {2361 return [];2362 }2363 if (this.mm != globalMessageManager) {2364 this.mm.removeDelayedFrameScript(FRAME_SCRIPT);2365 }2366 return this.curBrowser.closeTab()2367 .then(() => this.windowHandles.map(String));2368};2369/**2370 * Close the currently selected chrome window.2371 *2372 * If it is the last window currently open, the chrome window will not be2373 * closed to prevent a shutdown of the application. Instead the returned2374 * list of chrome window handles is empty.2375 *2376 * @return {Array.<string>}2377 * Unique chrome window handles of remaining chrome windows.2378 */2379GeckoDriver.prototype.closeChromeWindow = function(cmd, resp) {2380 assert.firefox();2381 assert.window(this.getCurrentWindow(Context.CHROME));2382 let nwins = 0;2383 // eslint-disable-next-line2384 for (let _ of this.windows) {2385 nwins++;2386 }2387 // If there is only one window left, do not close it. Instead return2388 // a faked empty array of window handles. This will instruct geckodriver2389 // to terminate the application.2390 if (nwins == 1) {2391 return [];2392 }2393 // reset frame to the top-most frame2394 this.curFrame = null;2395 if (this.mm != globalMessageManager) {2396 this.mm.removeDelayedFrameScript(FRAME_SCRIPT);2397 }2398 return this.curBrowser.closeWindow()2399 .then(() => this.chromeWindowHandles.map(String));2400};2401/** Delete Marionette session. */2402GeckoDriver.prototype.deleteSession = function(cmd, resp) {2403 if (this.curBrowser !== null) {2404 // frame scripts can be safely reused2405 Preferences.set(CONTENT_LISTENER_PREF, false);2406 // delete session in each frame in each browser2407 for (let win in this.browsers) {2408 let browser = this.browsers[win];2409 for (let i in browser.knownFrames) {2410 globalMessageManager.broadcastAsyncMessage(2411 "Marionette:deleteSession" + browser.knownFrames[i], {});2412 }2413 }2414 for (let win of this.windows) {2415 if (win.messageManager) {2416 win.messageManager.removeDelayedFrameScript(FRAME_SCRIPT);2417 } else {2418 logger.error(2419 `Could not remove listener from page ${win.location.href}`);2420 }2421 }2422 this.curBrowser.frameManager.removeMessageManagerListeners(2423 globalMessageManager);2424 }2425 this.switchToGlobalMessageManager();2426 // reset frame to the top-most frame2427 this.curFrame = null;2428 if (this.mainFrame) {2429 try {2430 this.mainFrame.focus();2431 } catch (e) {2432 this.mainFrame = null;2433 }2434 }2435 if (this.observing !== null) {2436 for (let topic in this.observing) {2437 Services.obs.removeObserver(this.observing[topic], topic);2438 }2439 this.observing = null;2440 }2441 modal.removeHandler(this.dialogHandler);2442 this.sandboxes.clear();2443 cert.uninstallOverride();2444 this.sessionId = null;2445 this.capabilities = new session.Capabilities();2446};2447/**2448 * Takes a screenshot of a web element, current frame, or viewport.2449 *2450 * The screen capture is returned as a lossless PNG image encoded as2451 * a base 64 string.2452 *2453 * If called in the content context, the |id| argument is not null and2454 * refers to a present and visible web element's ID, the capture area will2455 * be limited to the bounding box of that element. Otherwise, the capture2456 * area will be the bounding box of the current frame.2457 *2458 * If called in the chrome context, the screenshot will always represent2459 * the entire viewport.2460 *2461 * @param {string=} id2462 * Optional web element reference to take a screenshot of.2463 * If undefined, a screenshot will be taken of the document element.2464 * @param {Array.<string>=} highlights2465 * List of web elements to highlight.2466 * @param {boolean} full2467 * True to take a screenshot of the entire document element. Is not2468 * considered if <var>id</var> is not defined. Defaults to true.2469 * @param {boolean=} hash2470 * True if the user requests a hash of the image data.2471 * @param {boolean=} scroll2472 * Scroll to element if |id| is provided. If undefined, it will2473 * scroll to the element.2474 *2475 * @return {string}2476 * If <var>hash</var> is false, PNG image encoded as Base64 encoded2477 * string. If <var>hash</var> is true, hex digest of the SHA-2562478 * hash of the Base64 encoded string.2479 */2480GeckoDriver.prototype.takeScreenshot = function(cmd, resp) {2481 let win = assert.window(this.getCurrentWindow());2482 let {id, highlights, full, hash} = cmd.parameters;2483 highlights = highlights || [];2484 let format = hash ? capture.Format.Hash : capture.Format.Base64;2485 switch (this.context) {2486 case Context.CHROME:2487 let container = {frame: win.document.defaultView};2488 let highlightEls = highlights.map(2489 ref => this.curBrowser.seenEls.get(ref, container));2490 // viewport2491 let canvas;2492 if (!id && !full) {2493 canvas = capture.viewport(container.frame, highlightEls);2494 // element or full document element2495 } else {2496 let node;2497 if (id) {2498 node = this.curBrowser.seenEls.get(id, container);2499 } else {2500 node = container.frame.document.documentElement;2501 }2502 canvas = capture.element(node, highlightEls);2503 }2504 switch (format) {2505 case capture.Format.Hash:2506 return capture.toHash(canvas);2507 case capture.Format.Base64:2508 return capture.toBase64(canvas);2509 }2510 break;2511 case Context.CONTENT:2512 return this.listener.takeScreenshot(format, cmd.parameters);2513 }2514 throw new TypeError(`Unknown context: ${this.context}`);2515};2516/**2517 * Get the current browser orientation.2518 *2519 * Will return one of the valid primary orientation values2520 * portrait-primary, landscape-primary, portrait-secondary, or2521 * landscape-secondary.2522 */2523GeckoDriver.prototype.getScreenOrientation = function(cmd, resp) {2524 assert.fennec();2525 let win = assert.window(this.getCurrentWindow());2526 resp.body.value = win.screen.mozOrientation;2527};2528/**2529 * Set the current browser orientation.2530 *2531 * The supplied orientation should be given as one of the valid2532 * orientation values. If the orientation is unknown, an error will2533 * be raised.2534 *2535 * Valid orientations are "portrait" and "landscape", which fall2536 * back to "portrait-primary" and "landscape-primary" respectively,2537 * and "portrait-secondary" as well as "landscape-secondary".2538 */2539GeckoDriver.prototype.setScreenOrientation = function(cmd, resp) {2540 assert.fennec();2541 let win = assert.window(this.getCurrentWindow());2542 const ors = [2543 "portrait", "landscape",2544 "portrait-primary", "landscape-primary",2545 "portrait-secondary", "landscape-secondary",2546 ];2547 let or = String(cmd.parameters.orientation);2548 assert.string(or);2549 let mozOr = or.toLowerCase();2550 if (!ors.includes(mozOr)) {2551 throw new InvalidArgumentError(`Unknown screen orientation: ${or}`);2552 }2553 if (!win.screen.mozLockOrientation(mozOr)) {2554 throw new WebDriverError(`Unable to set screen orientation: ${or}`);2555 }2556};2557/**2558 * Synchronously minimizes the user agent window as if the user pressed2559 * the minimize button, or restores it if it is already minimized.2560 *2561 * Not supported on Fennec.2562 *2563 * @return {Object.<string, number>}2564 * Window rect and window state.2565 *2566 * @throws {UnsupportedOperationError}2567 * Not available for current application.2568 * @throws {NoSuchWindowError}2569 * Top-level browsing context has been discarded.2570 * @throws {UnexpectedAlertOpenError}2571 * A modal dialog is open, blocking this operation.2572 */2573GeckoDriver.prototype.minimizeWindow = function* (cmd, resp) {2574 assert.firefox();2575 const win = assert.window(this.getCurrentWindow());2576 assert.noUserPrompt(this.dialog);2577 let state;2578 yield new Promise(resolve => {2579 win.addEventListener("sizemodechange", resolve, {once: true});2580 if (win.windowState == win.STATE_MINIMIZED) {2581 win.restore();2582 state = "normal";2583 } else {2584 win.minimize();2585 state = "minimized";2586 }2587 });2588 resp.body = {2589 x: win.screenX,2590 y: win.screenY,2591 width: win.outerWidth,2592 height: win.outerHeight,2593 state,2594 };2595};2596/**2597 * Synchronously maximizes the user agent window as if the user pressed2598 * the maximize button, or restores it if it is already maximized.2599 *2600 * Not supported on Fennec.2601 *2602 * @return {Map.<string, number>}2603 * Window rect.2604 *2605 * @throws {UnsupportedOperationError}2606 * Not available for current application.2607 * @throws {NoSuchWindowError}2608 * Top-level browsing context has been discarded.2609 * @throws {UnexpectedAlertOpenError}2610 * A modal dialog is open, blocking this operation.2611 */2612GeckoDriver.prototype.maximizeWindow = function* (cmd, resp) {2613 assert.firefox();2614 const win = assert.window(this.getCurrentWindow());2615 assert.noUserPrompt(this.dialog);2616 yield new Promise(resolve => {2617 win.addEventListener("resize", resolve, {once: true});2618 if (win.windowState == win.STATE_MAXIMIZED) {2619 win.restore();2620 } else {2621 win.maximize();2622 }2623 });2624 resp.body = {2625 x: win.screenX,2626 y: win.screenY,2627 width: win.outerWidth,2628 height: win.outerHeight,2629 };2630};2631/**2632 * Synchronously sets the user agent window to full screen as if the user2633 * had done "View > Enter Full Screen", or restores it if it is already2634 * in full screen.2635 *2636 * Not supported on Fennec.2637 *2638 * @return {Map.<string, number>}2639 * Window rect.2640 *2641 * @throws {UnsupportedOperationError}2642 * Not available for current application.2643 * @throws {NoSuchWindowError}2644 * Top-level browsing context has been discarded.2645 * @throws {UnexpectedAlertOpenError}2646 * A modal dialog is open, blocking this operation.2647 */2648GeckoDriver.prototype.fullscreen = function* (cmd, resp) {2649 assert.firefox();2650 const win = assert.window(this.getCurrentWindow());2651 assert.noUserPrompt(this.dialog);2652 yield new Promise(resolve => {2653 win.addEventListener("sizemodechange", resolve, {once: true});2654 win.fullScreen = !win.fullScreen;2655 });2656 resp.body = {2657 x: win.screenX,2658 y: win.screenY,2659 width: win.outerWidth,2660 height: win.outerHeight,2661 };2662};2663/**2664 * Dismisses a currently displayed tab modal, or returns no such alert if2665 * no modal is displayed.2666 */2667GeckoDriver.prototype.dismissDialog = function(cmd, resp) {2668 assert.window(this.getCurrentWindow());2669 this._checkIfAlertIsPresent();2670 let {button0, button1} = this.dialog.ui;2671 (button1 ? button1 : button0).click();2672 this.dialog = null;2673};2674/**2675 * Accepts a currently displayed tab modal, or returns no such alert if2676 * no modal is displayed.2677 */2678GeckoDriver.prototype.acceptDialog = function(cmd, resp) {2679 assert.window(this.getCurrentWindow());2680 this._checkIfAlertIsPresent();2681 let {button0} = this.dialog.ui;2682 button0.click();2683 this.dialog = null;2684};2685/**2686 * Returns the message shown in a currently displayed modal, or returns2687 * a no such alert error if no modal is currently displayed.2688 */2689GeckoDriver.prototype.getTextFromDialog = function(cmd, resp) {2690 assert.window(this.getCurrentWindow());2691 this._checkIfAlertIsPresent();2692 let {infoBody} = this.dialog.ui;2693 resp.body.value = infoBody.textContent;2694};2695/**2696 * Set the user prompt's value field.2697 *2698 * Sends keys to the input field of a currently displayed modal, or2699 * returns a no such alert error if no modal is currently displayed. If2700 * a tab modal is currently displayed but has no means for text input,2701 * an element not visible error is returned.2702 *2703 * @param {string} text2704 * Input to the user prompt's value field.2705 *2706 * @throws {ElementNotInteractableError}2707 * If the current user prompt is an alert or confirm.2708 * @throws {NoSuchAlertError}2709 * If there is no current user prompt.2710 * @throws {UnsupportedOperationError}2711 * If the current user prompt is something other than an alert,2712 * confirm, or a prompt.2713 */2714GeckoDriver.prototype.sendKeysToDialog = function(cmd, resp) {2715 let win = assert.window(this.getCurrentWindow());2716 this._checkIfAlertIsPresent();2717 // see toolkit/components/prompts/content/commonDialog.js2718 let {loginContainer, loginTextbox} = this.dialog.ui;2719 if (loginContainer.hidden) {2720 throw new ElementNotInteractableError(2721 "This prompt does not accept text input");2722 }2723 event.sendKeysToElement(2724 cmd.parameters.text,2725 loginTextbox,2726 {ignoreVisibility: true},2727 this.dialog.window ? this.dialog.window : win);2728};2729GeckoDriver.prototype._checkIfAlertIsPresent = function() {2730 if (!this.dialog || !this.dialog.ui) {2731 throw new NoAlertOpenError("No modal dialog is currently open");2732 }2733};2734/**2735 * Enables or disables accepting new socket connections.2736 *2737 * By calling this method with `false` the server will not accept any2738 * further connections, but existing connections will not be forcible2739 * closed. Use `true` to re-enable accepting connections.2740 *2741 * Please note that when closing the connection via the client you can2742 * end-up in a non-recoverable state if it hasn't been enabled before.2743 *2744 * This method is used for custom in application shutdowns via2745 * marionette.quit() or marionette.restart(), like File -> Quit.2746 *2747 * @param {boolean} state2748 * True if the server should accept new socket connections.2749 */2750GeckoDriver.prototype.acceptConnections = function(cmd, resp) {2751 assert.boolean(cmd.parameters.value);2752 this._server.acceptConnections = cmd.parameters.value;2753};2754/**2755 * Quits the application with the provided flags.2756 *2757 * Marionette will stop accepting new connections before ending the2758 * current session, and finally attempting to quit the application.2759 *2760 * Optional {@link nsIAppStartup} flags may be provided as2761 * an array of masks, and these will be combined by ORing2762 * them with a bitmask. The available masks are defined in2763 * https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIAppStartup.2764 *2765 * Crucially, only one of the *Quit flags can be specified. The |eRestart|2766 * flag may be bit-wise combined with one of the *Quit flags to cause2767 * the application to restart after it quits.2768 *2769 * @param {Array.<string>=} flags2770 * Constant name of masks to pass to |Services.startup.quit|.2771 * If empty or undefined, |nsIAppStartup.eAttemptQuit| is used.2772 *2773 * @return {string}2774 * Explaining the reason why the application quit. This can be2775 * in response to a normal shutdown or restart, yielding "shutdown"2776 * or "restart", respectively.2777 *2778 * @throws {InvalidArgumentError}2779 * If |flags| contains unknown or incompatible flags, for example2780 * multiple Quit flags.2781 */2782GeckoDriver.prototype.quit = function* (cmd, resp) {2783 const quits = ["eConsiderQuit", "eAttemptQuit", "eForceQuit"];2784 let flags = [];2785 if (typeof cmd.parameters.flags != "undefined") {2786 flags = assert.array(cmd.parameters.flags);2787 }2788 // bug 12989212789 assert.firefox();2790 let quitSeen;2791 let mode = 0;2792 if (flags.length > 0) {2793 for (let k of flags) {2794 assert.in(k, Ci.nsIAppStartup);2795 if (quits.includes(k)) {2796 if (quitSeen) {2797 throw new InvalidArgumentError(2798 `${k} cannot be combined with ${quitSeen}`);2799 }2800 quitSeen = k;2801 }2802 mode |= Ci.nsIAppStartup[k];2803 }2804 } else {2805 mode = Ci.nsIAppStartup.eAttemptQuit;2806 }2807 this._server.acceptConnections = false;2808 this.deleteSession();2809 // delay response until the application is about to quit2810 let quitApplication = new Promise(resolve => {2811 Services.obs.addObserver(2812 (subject, topic, data) => resolve(data),2813 "quit-application");2814 });2815 Services.startup.quit(mode);2816 yield quitApplication2817 .then(cause => resp.body.cause = cause)2818 .then(() => resp.send());2819};2820GeckoDriver.prototype.installAddon = function(cmd, resp) {2821 assert.firefox();2822 let path = cmd.parameters.path;2823 let temp = cmd.parameters.temporary || false;2824 if (typeof path == "undefined" || typeof path != "string" ||2825 typeof temp != "boolean") {2826 throw InvalidArgumentError();2827 }2828 return addon.install(path, temp);2829};2830GeckoDriver.prototype.uninstallAddon = function(cmd, resp) {2831 assert.firefox();2832 let id = cmd.parameters.id;2833 if (typeof id == "undefined" || typeof id != "string") {2834 throw new InvalidArgumentError();2835 }2836 return addon.uninstall(id);2837};2838/** Receives all messages from content messageManager. */2839/* eslint-disable consistent-return */2840GeckoDriver.prototype.receiveMessage = function(message) {2841 switch (message.name) {2842 case "Marionette:ok":2843 case "Marionette:done":2844 case "Marionette:error":2845 // check if we need to remove the mozbrowserclose listener2846 if (this.mozBrowserClose !== null) {2847 let win = this.getCurrentWindow();2848 win.removeEventListener("mozbrowserclose", this.mozBrowserClose, true);2849 this.mozBrowserClose = null;2850 }2851 break;2852 case "Marionette:log":2853 // log server-side messages2854 logger.info(message.json.message);2855 break;2856 case "Marionette:switchToModalOrigin":2857 this.curBrowser.frameManager.switchToModalOrigin(message);2858 this.mm = this.curBrowser.frameManager2859 .currentRemoteFrame.messageManager.get();2860 break;2861 case "Marionette:switchedToFrame":2862 if (message.json.restorePrevious) {2863 this.currentFrameElement = this.previousFrameElement;2864 } else {2865 // we don't arbitrarily save previousFrameElement, since2866 // we allow frame switching after modals appear, which would2867 // override this value and we'd lose our reference2868 if (message.json.storePrevious) {2869 this.previousFrameElement = this.currentFrameElement;2870 }2871 this.currentFrameElement = message.json.frameValue;2872 }2873 break;2874 case "Marionette:emitTouchEvent":2875 globalMessageManager.broadcastAsyncMessage(2876 "MarionetteMainListener:emitTouchEvent", message.json);2877 break;2878 case "Marionette:register":2879 let wid = message.json.value;2880 let be = message.target;2881 let rv = this.registerBrowser(wid, be);2882 return rv;2883 case "Marionette:listenersAttached":2884 if (message.json.listenerId === this.curBrowser.curFrameId) {2885 // If the frame script gets reloaded we need to call newSession.2886 // In the case of desktop this just sets up a small amount of state2887 // that doesn't change over the course of a session.2888 this.sendAsync("newSession", this.capabilities.toJSON());2889 this.curBrowser.flushPendingCommands();2890 }2891 break;2892 }2893};2894/* eslint-enable consistent-return */2895GeckoDriver.prototype.responseCompleted = function() {2896 if (this.curBrowser !== null) {2897 this.curBrowser.pendingCommands = [];2898 }2899};2900/**2901 * Retrieve the localized string for the specified entity id.2902 *2903 * Example:2904 * localizeEntity(["chrome://global/locale/about.dtd"], "about.version")2905 *2906 * @param {Array.<string>} urls2907 * Array of .dtd URLs.2908 * @param {string} id2909 * The ID of the entity to retrieve the localized string for.2910 *2911 * @return {string}2912 * The localized string for the requested entity.2913 */2914GeckoDriver.prototype.localizeEntity = function(cmd, resp) {2915 let {urls, id} = cmd.parameters;2916 if (!Array.isArray(urls)) {2917 throw new InvalidArgumentError("Value of `urls` should be of type 'Array'");2918 }2919 if (typeof id != "string") {2920 throw new InvalidArgumentError("Value of `id` should be of type 'string'");2921 }2922 resp.body.value = l10n.localizeEntity(urls, id);2923};2924/**2925 * Retrieve the localized string for the specified property id.2926 *2927 * Example:2928 *2929 * localizeProperty(2930 * ["chrome://global/locale/findbar.properties"], "FastFind");2931 *2932 * @param {Array.<string>} urls2933 * Array of .properties URLs.2934 * @param {string} id2935 * The ID of the property to retrieve the localized string for.2936 *2937 * @return {string}2938 * The localized string for the requested property.2939 */2940GeckoDriver.prototype.localizeProperty = function(cmd, resp) {2941 let {urls, id} = cmd.parameters;2942 if (!Array.isArray(urls)) {2943 throw new InvalidArgumentError("Value of `urls` should be of type 'Array'");2944 }2945 if (typeof id != "string") {2946 throw new InvalidArgumentError("Value of `id` should be of type 'string'");2947 }2948 resp.body.value = l10n.localizeProperty(urls, id);2949};2950/**2951 * Initialize the reftest mode2952 */2953GeckoDriver.prototype.setupReftest = function* (cmd, resp) {2954 if (this._reftest) {2955 throw new UnsupportedOperationError("Called reftest:setup with a reftest session already active");2956 }2957 if (this.context !== Context.CHROME) {2958 throw new UnsupportedOperationError("Must set chrome context before running reftests");2959 }2960 let {urlCount = {}, screenshot = "unexpected"} = cmd.parameters;2961 if (!["always", "fail", "unexpected"].includes(screenshot)) {2962 throw new InvalidArgumentError("Value of `screenshot` should be 'always', 'fail' or 'unexpected'");2963 }2964 this._reftest = new reftest.Runner(this);2965 yield this._reftest.setup(urlCount, screenshot);2966};2967/**2968 * Run a reftest2969 */2970GeckoDriver.prototype.runReftest = function* (cmd, resp) {2971 let {test, references, expected, timeout} = cmd.parameters;2972 if (!this._reftest) {2973 throw new UnsupportedOperationError("Called reftest:run before reftest:start");2974 }2975 assert.string(test);2976 assert.string(expected);2977 assert.array(references);2978 let result = yield this._reftest.run(test, references, expected, timeout);2979 resp.body.value = result;2980};2981/**2982 * End a reftest run2983 *2984 * Closes the reftest window (without changing the current window handle),2985 * and removes cached canvases.2986 */2987GeckoDriver.prototype.teardownReftest = function* (cmd, resp) {2988 if (!this._reftest) {2989 throw new UnsupportedOperationError("Called reftest:teardown before reftest:start");2990 }2991 this._reftest.abort();2992 this._reftest = null;2993};2994GeckoDriver.prototype.commands = {2995 // Marionette service2996 "Marionette:SetContext": GeckoDriver.prototype.setContext,2997 "setContext": GeckoDriver.prototype.setContext, // deprecated, remove in Firefox 602998 "Marionette:GetContext": GeckoDriver.prototype.getContext,2999 "getContext": GeckoDriver.prototype.getContext,3000 "Marionette:AcceptConnections": GeckoDriver.prototype.acceptConnections,3001 "acceptConnections": GeckoDriver.prototype.acceptConnections, // deprecated, remove in Firefox 603002 "Marionette:Quit": GeckoDriver.prototype.quit,3003 "quit": GeckoDriver.prototype.quit, // deprecated, remove in Firefox 603004 "quitApplication": GeckoDriver.prototype.quit, // deprecated, remove in Firefox 603005 // Addon service3006 "Addon:Install": GeckoDriver.prototype.installAddon,3007 "addon:install": GeckoDriver.prototype.installAddon, // deprecated, remove in Firefox 603008 "Addon:Uninstall": GeckoDriver.prototype.uninstallAddon,3009 "addon:uninstall": GeckoDriver.prototype.uninstallAddon, // deprecated, remove in Firefox 603010 // L10n service3011 "L10n:LocalizeEntity": GeckoDriver.prototype.localizeEntity,3012 "localization:l10n:localizeEntity": GeckoDriver.prototype.localizeEntity, // deprecated, remove in Firefox 603013 "L10n:LocalizeProperty": GeckoDriver.prototype.localizeProperty,3014 "localization:l10n:localizeProperty": GeckoDriver.prototype.localizeProperty, // deprecated, remove in Firefox 603015 // Reftest service3016 "reftest:setup": GeckoDriver.prototype.setupReftest,3017 "reftest:run": GeckoDriver.prototype.runReftest,3018 "reftest:teardown": GeckoDriver.prototype.teardownReftest,3019 // WebDriver service3020 "WebDriver:AcceptDialog": GeckoDriver.prototype.acceptDialog,3021 "WebDriver:AddCookie": GeckoDriver.prototype.addCookie,3022 "WebDriver:Back": GeckoDriver.prototype.goBack,3023 "WebDriver:CloseChromeWindow": GeckoDriver.prototype.closeChromeWindow,3024 "WebDriver:CloseWindow": GeckoDriver.prototype.close,3025 "WebDriver:DeleteAllCookies": GeckoDriver.prototype.deleteAllCookies,3026 "WebDriver:DeleteCookie": GeckoDriver.prototype.deleteCookie,3027 "WebDriver:DeleteSession": GeckoDriver.prototype.deleteSession,3028 "WebDriver:DismissAlert": GeckoDriver.prototype.dismissDialog,3029 "WebDriver:ElementClear": GeckoDriver.prototype.clearElement,3030 "WebDriver:ElementClick": GeckoDriver.prototype.clickElement,3031 "WebDriver:ElementSendKeys": GeckoDriver.prototype.sendKeysToElement,3032 "WebDriver:ExecuteAsyncScript": GeckoDriver.prototype.executeAsyncScript,3033 "WebDriver:ExecuteScript": GeckoDriver.prototype.executeScript,3034 "WebDriver:FindElement": GeckoDriver.prototype.findElement,3035 "WebDriver:FindElements": GeckoDriver.prototype.findElements,3036 "WebDriver:Forward": GeckoDriver.prototype.goForward,3037 "WebDriver:FullscreenWindow": GeckoDriver.prototype.fullscreen,3038 "WebDriver:GetActiveElement": GeckoDriver.prototype.getActiveElement,3039 "WebDriver:GetActiveFrame": GeckoDriver.prototype.getActiveFrame,3040 "WebDriver:GetAlertText": GeckoDriver.prototype.getTextFromDialog,3041 "WebDriver:GetCapabilities": GeckoDriver.prototype.getSessionCapabilities,3042 "WebDriver:GetChromeWindowHandle": GeckoDriver.prototype.getChromeWindowHandle,3043 "WebDriver:GetChromeWindowHandles": GeckoDriver.prototype.getChromeWindowHandles,3044 "WebDriver:GetCookies": GeckoDriver.prototype.getCookies,3045 "WebDriver:GetCurrentChromeWindowHandle": GeckoDriver.prototype.getChromeWindowHandle,3046 "WebDriver:GetCurrentURL": GeckoDriver.prototype.getCurrentUrl,3047 "WebDriver:GetElementAttribute": GeckoDriver.prototype.getElementAttribute,3048 "WebDriver:GetElementCSSValue": GeckoDriver.prototype.getElementValueOfCssProperty,3049 "WebDriver:GetElementProperty": GeckoDriver.prototype.getElementProperty,3050 "WebDriver:GetElementRect": GeckoDriver.prototype.getElementRect,3051 "WebDriver:GetElementTagName": GeckoDriver.prototype.getElementTagName,3052 "WebDriver:GetElementText": GeckoDriver.prototype.getElementText,3053 "WebDriver:GetPageSource": GeckoDriver.prototype.getPageSource,3054 "WebDriver:GetScreenOrientation": GeckoDriver.prototype.getScreenOrientation,3055 "WebDriver:GetTimeouts": GeckoDriver.prototype.getTimeouts,3056 "WebDriver:GetTitle": GeckoDriver.prototype.getTitle,3057 "WebDriver:GetWindowHandle": GeckoDriver.prototype.getWindowHandle,3058 "WebDriver:GetWindowHandles": GeckoDriver.prototype.getWindowHandles,3059 "WebDriver:GetWindowRect": GeckoDriver.prototype.getWindowRect,3060 "WebDriver:GetWindowType": GeckoDriver.prototype.getWindowType,3061 "WebDriver:IsElementDisplayed": GeckoDriver.prototype.isElementDisplayed,3062 "WebDriver:IsElementEnabled": GeckoDriver.prototype.isElementEnabled,3063 "WebDriver:IsElementSelected": GeckoDriver.prototype.isElementSelected,3064 "WebDriver:MinimizeWindow": GeckoDriver.prototype.minimizeWindow,3065 "WebDriver:MaximizeWindow": GeckoDriver.prototype.maximizeWindow,3066 "WebDriver:Navigate": GeckoDriver.prototype.get,3067 "WebDriver:NewSession": GeckoDriver.prototype.newSession,3068 "WebDriver:PerformActions": GeckoDriver.prototype.performActions,3069 "WebDriver:Refresh": GeckoDriver.prototype.refresh,3070 "WebDriver:ReleaseActions": GeckoDriver.prototype.releaseActions,3071 "WebDriver:SendAlertText": GeckoDriver.prototype.sendKeysToDialog,3072 "WebDriver:SetScreenOrientation": GeckoDriver.prototype.setScreenOrientation,3073 "WebDriver:SetTimeouts": GeckoDriver.prototype.setTimeouts,3074 "WebDriver:SetWindowRect": GeckoDriver.prototype.setWindowRect,3075 "WebDriver:SwitchToFrame": GeckoDriver.prototype.switchToFrame,3076 "WebDriver:SwitchToParentFrame": GeckoDriver.prototype.switchToParentFrame,3077 "WebDriver:SwitchToShadowRoot": GeckoDriver.prototype.switchToShadowRoot,3078 "WebDriver:SwitchToWindow": GeckoDriver.prototype.switchToWindow,3079 "WebDriver:TakeScreenshot": GeckoDriver.prototype.takeScreenshot,3080 // deprecated WebDriver commands, remove in Firefox 603081 "acceptDialog": GeckoDriver.prototype.acceptDialog,3082 "actionChain": GeckoDriver.prototype.actionChain,3083 "addCookie": GeckoDriver.prototype.addCookie,3084 "clearElement": GeckoDriver.prototype.clearElement,3085 "clickElement": GeckoDriver.prototype.clickElement,3086 "closeChromeWindow": GeckoDriver.prototype.closeChromeWindow,3087 "close": GeckoDriver.prototype.close,3088 "deleteAllCookies": GeckoDriver.prototype.deleteAllCookies,3089 "deleteCookie": GeckoDriver.prototype.deleteCookie,3090 "deleteSession": GeckoDriver.prototype.deleteSession,3091 "dismissDialog": GeckoDriver.prototype.dismissDialog,3092 "executeAsyncScript": GeckoDriver.prototype.executeAsyncScript,3093 "executeScript": GeckoDriver.prototype.executeScript,3094 "findElement": GeckoDriver.prototype.findElement,3095 "findElements": GeckoDriver.prototype.findElements,3096 "fullscreen": GeckoDriver.prototype.fullscreen,3097 "getActiveElement": GeckoDriver.prototype.getActiveElement,3098 "getActiveFrame": GeckoDriver.prototype.getActiveFrame,3099 "getChromeWindowHandle": GeckoDriver.prototype.getChromeWindowHandle,3100 "getChromeWindowHandles": GeckoDriver.prototype.getChromeWindowHandles,3101 "getCookies": GeckoDriver.prototype.getCookies,3102 "getCurrentChromeWindowHandle": GeckoDriver.prototype.getChromeWindowHandle,3103 "getCurrentUrl": GeckoDriver.prototype.getCurrentUrl,3104 "getElementAttribute": GeckoDriver.prototype.getElementAttribute,3105 "getElementProperty": GeckoDriver.prototype.getElementProperty,3106 "getElementRect": GeckoDriver.prototype.getElementRect,3107 "getElementTagName": GeckoDriver.prototype.getElementTagName,3108 "getElementText": GeckoDriver.prototype.getElementText,3109 "getElementValueOfCssProperty": GeckoDriver.prototype.getElementValueOfCssProperty,3110 "get": GeckoDriver.prototype.get,3111 "getPageSource": GeckoDriver.prototype.getPageSource,3112 "getScreenOrientation": GeckoDriver.prototype.getScreenOrientation,3113 "getSessionCapabilities": GeckoDriver.prototype.getSessionCapabilities,3114 "getTextFromDialog": GeckoDriver.prototype.getTextFromDialog,3115 "getTimeouts": GeckoDriver.prototype.getTimeouts,3116 "getTitle": GeckoDriver.prototype.getTitle,3117 "getWindowHandle": GeckoDriver.prototype.getWindowHandle,3118 "getWindowHandles": GeckoDriver.prototype.getWindowHandles,3119 "getWindowPosition": GeckoDriver.prototype.getWindowRect, // redirect for compatibility3120 "getWindowRect": GeckoDriver.prototype.getWindowRect,3121 "getWindowSize": GeckoDriver.prototype.getWindowRect, // redirect for compatibility3122 "getWindowType": GeckoDriver.prototype.getWindowType,3123 "goBack": GeckoDriver.prototype.goBack,3124 "goForward": GeckoDriver.prototype.goForward,3125 "isElementDisplayed": GeckoDriver.prototype.isElementDisplayed,3126 "isElementEnabled": GeckoDriver.prototype.isElementEnabled,3127 "isElementSelected": GeckoDriver.prototype.isElementSelected,3128 "maximizeWindow": GeckoDriver.prototype.maximizeWindow,3129 "multiAction": GeckoDriver.prototype.multiAction,3130 "newSession": GeckoDriver.prototype.newSession,3131 "performActions": GeckoDriver.prototype.performActions,3132 "refresh": GeckoDriver.prototype.refresh,3133 "releaseActions": GeckoDriver.prototype.releaseActions,3134 "sendKeysToDialog": GeckoDriver.prototype.sendKeysToDialog,3135 "sendKeysToElement": GeckoDriver.prototype.sendKeysToElement,3136 "setScreenOrientation": GeckoDriver.prototype.setScreenOrientation,3137 "setTimeouts": GeckoDriver.prototype.setTimeouts,3138 "setWindowPosition": GeckoDriver.prototype.setWindowRect, // redirect for compatibility3139 "setWindowRect": GeckoDriver.prototype.setWindowRect,3140 "setWindowSize": GeckoDriver.prototype.setWindowRect, // redirect for compatibility3141 "singleTap": GeckoDriver.prototype.singleTap,3142 "switchToFrame": GeckoDriver.prototype.switchToFrame,3143 "switchToParentFrame": GeckoDriver.prototype.switchToParentFrame,3144 "switchToShadowRoot": GeckoDriver.prototype.switchToShadowRoot,3145 "switchToWindow": GeckoDriver.prototype.switchToWindow,3146 "takeScreenshot": GeckoDriver.prototype.takeScreenshot,3147};3148function copy(obj) {3149 if (Array.isArray(obj)) {3150 return obj.slice();3151 } else if (typeof obj == "object") {3152 return Object.assign({}, obj);3153 }3154 return obj;3155}3156/**3157 * Get the outer window ID for the specified window.3158 *3159 * @param {nsIDOMWindow} win3160 * Window whose browser we need to access.3161 *3162 * @return {string}3163 * Returns the unique window ID.3164 */3165function getOuterWindowId(win) {3166 return win.QueryInterface(Ci.nsIInterfaceRequestor)3167 .getInterface(Ci.nsIDOMWindowUtils)3168 .outerWindowID;...
driver-e2e-tests.js
Source:driver-e2e-tests.js
...314 }315 });316 it('should execute a webdriverio script in the context of session', async function () {317 const script = `318 const timeouts = await driver.getTimeouts();319 const status = await driver.status();320 return [timeouts, status];321 `;322 const {value} = (await axios({323 url: `http://localhost:8181/wd/hub/session/${sessionId}/appium/execute_driver`,324 method: 'POST',325 data: {script, type: 'webdriverio'},326 })).data;327 const expectedTimeouts = {command: 250, implicit: 0};328 const expectedStatus = {};329 value.result.should.eql([expectedTimeouts, expectedStatus]);330 });331 it('should fail with any script type other than webdriverio currently', async function () {332 const script = `return 'foo'`;...
testdrive.js
Source:testdrive.js
...45 await driver.sleep(3000)46 await driver.navigateTo('http://usejsdoc.org')47 var article = await driver.findElementCss('article')48 console.log('Article:', article)49 console.log('TIMEOUTS:', await driver.getTimeouts())50 // console.log('SETTIMEOUTS:', await driver.setTimeouts({ implicit: 0, pageLoad: 300000, script: 30000 }))51 console.log('TIMEOUTS AGAIN:', await driver.getTimeouts())52 var dts = await article.findElementsCss('dt')53 var dt0Text = await dts[0].getText()54 console.log('TEXT', dt0Text)55 var actions = new Actions(new Actions.Pointer('mouse'), new Actions.Keyboard('keyboard'))56 // var actions = new Actions()57 console.log('BEFORE:', actions, '\n\nAND:', actions.actions, '\n\n')58 actions.tick.mouseDown().keyboardDown('R')59 actions.tick.mouseMove({ origin: dts[3], x: 10, y: 20, duration: 1000 })60 actions.tick.mouseDown().keyboardUp('r')61 actions.tick.mouseUp().tick.keyboardDown('p')62 actions.tick.keyboardUp('p')63 actions.compile()64 await driver.performActions(actions)65 /*66 console.log('Maximize:')67 await driver.maximizeWindow()68 console.log('(done)')69 await driver.sleep(2000)70 console.log('Minimize:')71 await driver.minimizeWindow()72 console.log('(done)')73 await driver.sleep(2000)74 console.log('Maximize again:')75 await driver.maximizeWindow()76 console.log('(done)')77 await driver.sleep(2000)78 console.log('Full screen:')79 await driver.fullScreenWindow()80 console.log('(done)')81 await driver.sleep(2000)82 */83 console.log('Selected:', await dts[0].isSelected())84 console.log('Enabled:', await dts[0].isEnabled())85 var h2 = await driver.findElementCss('h2#block-tags')86 console.log('SEE ATTR:', await h2.getAttribute('id'))87 // console.log('SEE PROP:', await h2.getProperty('id'))88 console.log('SEE CSS VAL:', await h2.getCssValue('height'))89 console.log('SEE TAG NAME VAL:', await h2.getTagName())90 // console.log('SEE RECT:', await h2.getRect())91 console.log('SEE CLICK:', await h2.click())92 // console.log('SEE CLEAR:', await h2.clear())93 // console.log('SEE SCREENSHOT:', await h2.takeScreenshot())94 await driver.waitFor(6000).navigateTo('http://www.google.com')95 console.log('PAGE SOURCE:', await driver.getPageSource())96 // var q = await driver.findElementCss('[name=q]')97 // await q.sendKeys('stocazzo' + Element.KEY.ENTER)98 // console.log('WTF', q, q.id, q.ELEMENT)99 // console.log('EXECUTE 0 PRETEND:')100 // await driver.sleep(5000)101 /*102 console.log('EXECUTE 0:', await driver.executeScript('prompt('pippo');return 'Hello ' + arguments[0];', ['tony']))103 await driver.sleep(2000)104 console.log('Alert text:', await driver.getAlertText())105 await driver.sendAlertText('aaaaa')106 // await driver.dismissAlert()107 await driver.sleep(2000)108 */109 var el2 = await driver.getActiveElement()110 console.log('Active Element:', el2)111 var elsc = await el2.takeScreenshot(true)112 console.log('Active Element screenshot:', elsc)113 var sc = await driver.takeScreenshot()114 console.log('Screenshot:', sc)115 var fs = require('fs')116 fs.writeFileSync('/tmp/elsc.png', elsc)117 fs.writeFileSync('/tmp/sc.png', sc)118 console.log('EXECUTE 1:', await driver.executeAsyncScript("var name = arguments[0];var cb = arguments[1];cb('Hello ' + name);", ['tony']))119 console.log('Cookies', await driver.getAllCookies())120 console.log('Cookie named', await driver.getNamedCookie('NID'))121 console.log('Deleting cookie named', await driver.deleteCookie('NID'))122 console.log('ALL Cookies again', await driver.getAllCookies())123 console.log('Deleting ALL cookies', await driver.deleteAllCookies())124 console.log('ALL Cookies again 2', await driver.getAllCookies())125 console.log('Set cookie', await driver.addCookie({126 name: 'test',127 value: 'a test',128 path: '/',129 domain: 'google.com.au',130 expiry: 1732569047,131 secure: true,132 httpOnly: true133 }))134 console.log('Cookie named test', await driver.getNamedCookie('test'))135 // console.log('EXECUTE 1:', await driver.executeAsyncScript("var a = arguments; var name = a[0]; var cb = a[1]; alert('Hello ' + name); setTimeout( () => { cb('ahah!') }, 2000);", ['tony']))136 // console.log('EXECUTE:', await driver.executeScript("alert('Stocazzo! '+ arguments[0])", ['a', 'b', 'c']))137 console.log('Window handleS:', await driver.getWindowHandles())138 // console.log('Switch to frame:', await driver.switchToFrame(q))139 console.log('Switch to parent frame:', await driver.switchToParentFrame())140 console.log('STATUS:', await driver.status())141 console.log('TITLE:', await driver.getTitle())142 console.log('RECT:', await driver.getWindowRect())143 console.log('SET RECT:', await driver.setWindowRect({x: 10, y: 10, width: 800, height: 800}))144 console.log('CURRNET URL:', await driver.getCurrentUrl())145 console.log('BACK:')146 await driver.back()147 console.log('CURRNET URL:', await driver.getCurrentUrl())148 console.log('BACK:')149 await driver.forward()150 console.log('CURRNET URL:', await driver.getCurrentUrl())151 console.log('Refreshing...')152 await driver.refresh()153 console.log('Window handle:', await driver.getWindowHandle())154 var wn = await driver.getWindowHandle()155 console.log('Switch to window:')156 await driver.switchToWindow(wn)157 console.log('Maximize:')158 await driver.maximizeWindow()159 await driver.sleep(1000)160 console.log('Minimize:')161 await driver.minimizeWindow()162 await driver.sleep(1000)163 console.log('Maximize again:')164 await driver.maximizeWindow()165 await driver.sleep(1000)166 console.log('Full screen:')167 await driver.fullScreenWindow()168 await driver.sleep(1000)169 // await driver.closeWindow()170 await driver.sleep(5000)171 // console.log('TIMEOUTS:', await driver.getTimeouts())172 // console.log('And:', await driver.getCurrentUrl())173 // console.log('EXECUTE:', await driver.closeWindow())174 await driver.deleteSession()175 } catch (e) {176 console.log('ERROR:', e)177 }...
Using AI Code Generation
1const wdio = require('webdriverio');2const opts = {3 capabilities: {4 }5};6const client = wdio.remote(opts);7 .init()8 .getTimeouts()9 .then((timeouts) => {10 console.log(timeouts);11 })12 .catch((err) => {13 console.log(err);14 });15const wdio = require('webdriverio');16const opts = {17 capabilities: {18 }19};20const client = wdio.remote(opts);21 .init()22 .setTimeouts({23 })24 .then((timeouts) => {25 console.log(timeouts);26 })27 .catch((err) => {28 console.log(err);29 });30const wdio = require('webdriverio');31const opts = {32 capabilities: {33 }34};35const client = wdio.remote(opts);36 .init()37 .getDeviceTime()38 .then((time) => {39 console.log(time);40 })41 .catch((err) => {42 console.log(err);43 });44const wdio = require('webdriverio');45const opts = {46 capabilities: {
Using AI Code Generation
1var wd = require('wd');2var assert = require('assert');3var serverConfig = {4};5var desired = {6};7var driver = wd.promiseChainRemote(serverConfig);8 .init(desired)9 .getTimeouts()10 .then(function(timeout) {11 console.log(timeout);12 })13 .fin(function() { return driver.quit(); })14 .done();15{ script: 60000, pageLoad: 300000, implicit: 0 }16var wd = require('wd');17var assert = require('assert');18var serverConfig = {19};20var desired = {21};22var driver = wd.promiseChainRemote(serverConfig);23 .init(desired)24 .getPageSource()25 .then(function(source) {26 console.log(source);27 })28 .fin(function() { return driver.quit(); })29 .done();
Using AI Code Generation
1describe('Test', function() {2 it('should get timeouts', async function() {3 const timeouts = await driver.getTimeouts();4 console.log(timeouts);5 });6});7describe('Test', function() {8 it('should set timeouts', async function() {9 const timeouts = await driver.setTimeouts({10 });11 console.log(timeouts);12 });13});14describe('Test', function() {15 it('should set implicit timeout', async function() {16 const timeouts = await driver.setImplicitTimeout(10000);17 console.log(timeouts);18 });19});20describe('Test', function() {21 it('should get page source', async function() {22 const pageSource = await driver.getPageSource();23 console.log(pageSource);24 });25});26describe('Test', function() {27 it('should get orientation', async function() {28 const orientation = await driver.getOrientation();29 console.log(orientation);30 });31});32describe('Test', function() {33 it('should set orientation', async function() {34 const orientation = await driver.setOrientation('LANDSCAPE');35 console.log(orientation);36 });37});38describe('Test', function() {39 it('should get geo location', async function() {40 const geoLocation = await driver.getGeoLocation();41 console.log(geoLocation);42 });43});44describe('Test', function() {45 it('should set geo location', async function() {46 const geoLocation = await driver.setGeoLocation({47 });48 console.log(geoLocation);49 });50});51describe('Test', function() {52 it('should get network connection', async function() {53 const networkConnection = await driver.getNetworkConnection();54 console.log(networkConnection);55 });56});
Using AI Code Generation
1var webdriver = require('selenium-webdriver');2var driver = new webdriver.Builder()3 .withCapabilities({4 })5 .build();6driver.getTimeouts().then(function (timeouts) {7 console.log(timeouts);8});9driver.quit();10{ implicit: 0, pageLoad: 300000, script: 30000 }11How to Use Driver.manage().timeouts().setScriptTimeout() in Appium?12How to Use Driver.manage().timeouts().setPageLoadTimeout() in Appium?13How to Use Driver.manage().timeouts().implicitlyWait() in Appium?14How to Use Driver.manage().timeouts().pageLoadTimeout() in Appium?15How to Use Driver.manage().timeouts().setScriptTimeout() in Appium?16How to Use Driver.manage().timeouts().setPageLoadTimeout() in Appium?17How to Use Driver.manage().timeouts().implicitlyWait() in Appium?18How to Use Driver.manage().timeouts().pageLoadTimeout() in Appium?19How to Use Driver.manage().timeouts().setScriptTimeout() in Appium?20How to Use Driver.manage().timeouts().setPageLoadTimeout() in Appium?21How to Use Driver.manage().timeouts().implicitlyWait() in Appium?22How to Use Driver.manage().timeouts().pageLoadTimeout() in Appium?23How to Use Driver.manage().timeouts().setScriptTimeout() in Appium?24How to Use Driver.manage().timeouts().setPageLoadTimeout() in Appium?25How to Use Driver.manage().timeouts().implicitlyWait() in Appium?26How to Use Driver.manage().timeouts().pageLoadTimeout() in Appium?27How to Use Driver.manage().timeouts().setScriptTimeout() in Appium?28How to Use Driver.manage().timeouts().setPageLoadTimeout() in Appium?
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!