Bug 1479368 - [marionette] Wait for tab modal dialog to disappear.
authorHenrik Skupin <mail@hskupin.info>
Wed, 22 Aug 2018 22:24:39 +0200
changeset 488723 0509419ea0856d78031fcaccce1b2693a86064b1
parent 488722 3cd4ee02dfc35984f84fddc0d04c724e2c53a4a3
child 488724 1132c5e406a2a6220f71f54668401a22e6eff3a5
push id9734
push usershindli@mozilla.com
push dateThu, 30 Aug 2018 12:18:07 +0000
treeherdermozilla-beta@71c71ab3afae [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1479368
milestone63.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1479368 - [marionette] Wait for tab modal dialog to disappear. Both "WebDriver:AcceptAlert" and "WebDriver:DismissAlert" have to wait until the tab modal dialog has been closed.
testing/marionette/driver.js
testing/web-platform/meta/webdriver/tests/element_send_keys/user_prompts.py.ini
--- a/testing/marionette/driver.js
+++ b/testing/marionette/driver.js
@@ -964,17 +964,17 @@ GeckoDriver.prototype.execute_ = async f
       async = false,
     } = {}) {
 
   if (typeof timeout == "undefined" || timeout === null) {
     timeout = this.timeouts.script;
   }
 
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   assert.string(script, pprint`Expected "script" to be a string: ${script}`);
   assert.array(args, pprint`Expected script args to be an array: ${args}`);
   assert.positiveInteger(timeout, pprint`Expected script timeout to be a positive integer: ${timeout}`);
   if (sandboxName !== null) {
     assert.string(sandboxName, pprint`Expected sandbox name to be a string: ${sandboxName}`);
   }
   assert.boolean(newSandbox, pprint`Expected newSandbox to be boolean: ${newSandbox}`);
@@ -1048,17 +1048,17 @@ GeckoDriver.prototype.execute_ = async f
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.get = async function(cmd) {
   assert.content(this.context);
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let url = cmd.parameters.url;
 
   let get = this.listener.get({url, pageTimeout: this.timeouts.pageLoad});
 
   // If a reload of the frame script interrupts our page load, this will
   // never return. We need to re-issue this request to correctly poll for
   // readyState and send errors.
@@ -1088,37 +1088,37 @@ GeckoDriver.prototype.get = async functi
  * When in the context of the chrome, this returns the canonical URL
  * of the current resource.
  *
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
-GeckoDriver.prototype.getCurrentUrl = function() {
+GeckoDriver.prototype.getCurrentUrl = async function() {
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   return this.currentURL.toString();
 };
 
 /**
  * Gets the current title of the window.
  *
  * @return {string}
  *     Document title of the top-level browsing context.
  *
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
-GeckoDriver.prototype.getTitle = function() {
+GeckoDriver.prototype.getTitle = async function() {
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   return this.title;
 };
 
 /** Gets the current type of the window. */
 GeckoDriver.prototype.getWindowType = function() {
   assert.open(this.getCurrentWindow());
 
@@ -1134,17 +1134,17 @@ GeckoDriver.prototype.getWindowType = fu
  *
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.getPageSource = async function() {
   const win = assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   switch (this.context) {
     case Context.Chrome:
       let s = new win.XMLSerializer();
       return s.serializeToString(win.document);
 
     case Context.Content:
       return this.listener.getPageSource();
@@ -1163,17 +1163,17 @@ GeckoDriver.prototype.getPageSource = as
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.goBack = async function() {
   assert.content(this.context);
   assert.open(this.curBrowser);
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   // If there is no history, just return
   if (!this.curBrowser.contentBrowser.webNavigation.canGoBack) {
     return;
   }
 
   let lastURL = this.currentURL;
   let goBack = this.listener.goBack({pageTimeout: this.timeouts.pageLoad});
@@ -1205,17 +1205,17 @@ GeckoDriver.prototype.goBack = async fun
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.goForward = async function() {
   assert.content(this.context);
   assert.open(this.curBrowser);
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   // If there is no history, just return
   if (!this.curBrowser.contentBrowser.webNavigation.canGoForward) {
     return;
   }
 
   let lastURL = this.currentURL;
   let goForward = this.listener.goForward(
@@ -1248,17 +1248,17 @@ GeckoDriver.prototype.goForward = async 
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.refresh = async function() {
   assert.content(this.context);
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let refresh = this.listener.refresh(
       {pageTimeout: this.timeouts.pageLoad});
 
   // If a reload of the frame script interrupts our page load, this will
   // never return. We need to re-issue this request to correctly poll for
   // readyState and send errors.
   this.curBrowser.pendingCommands.push(() => {
@@ -1389,19 +1389,19 @@ GeckoDriver.prototype.getChromeWindowHan
  *     Object with |x| and |y| coordinates, and |width| and |height|
  *     of browser window.
  *
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
-GeckoDriver.prototype.getWindowRect = function() {
+GeckoDriver.prototype.getWindowRect = async function() {
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   return this.curBrowser.rect;
 };
 
 /**
  * Set the window position and size of the browser on the operating
  * system window manager.
  *
@@ -1429,17 +1429,17 @@ GeckoDriver.prototype.getWindowRect = fu
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.setWindowRect = async function(cmd) {
   assert.firefox();
   const win = assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let {x, y, width, height} = cmd.parameters;
   let origRect = this.curBrowser.rect;
 
   // Synchronous resize to |width| and |height| dimensions.
   async function resizeWindow(width, height) {
     return new Promise(resolve => {
       win.addEventListener("resize", whenIdle(win, resolve), {once: true});
@@ -1657,17 +1657,17 @@ GeckoDriver.prototype.getActiveFrame = f
  *
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.switchToParentFrame = async function() {
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   await this.listener.switchToParentFrame();
 };
 
 /**
  * Switch to a given frame within the current window.
  *
  * @param {Object} element
@@ -1678,17 +1678,17 @@ GeckoDriver.prototype.switchToParentFram
  *
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.switchToFrame = async function(cmd) {
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let {id, focus} = cmd.parameters;
 
   // TODO(ato): element can be either string (deprecated) or a web
   // element JSON Object.  Can be removed with Firefox 60.
   let byFrame;
   if (typeof cmd.parameters.element == "string") {
     byFrame = WebElement.fromUUID(cmd.parameters.element, Context.Chrome);
@@ -1893,17 +1893,17 @@ GeckoDriver.prototype.singleTap = async 
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.performActions = async function(cmd) {
   assert.content(this.context,
       "Command 'performActions' is not yet available in chrome context");
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let actions = cmd.parameters.actions;
   await this.listener.performActions({"actions": actions});
 };
 
 /**
  * Release all the keys and pointer buttons that are currently depressed.
  *
@@ -1912,17 +1912,17 @@ GeckoDriver.prototype.performActions = a
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.releaseActions = async function() {
   assert.content(this.context);
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   await this.listener.releaseActions();
 };
 
 /**
  * An action chain.
  *
  * @param {Object} value
@@ -1936,17 +1936,17 @@ GeckoDriver.prototype.releaseActions = a
  *     Not applicable to application.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.actionChain = async function(cmd) {
   const win = assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let {chain, nextId} = cmd.parameters;
 
   switch (this.context) {
     case Context.Chrome:
       // be conservative until this has a use case and is established
       // to work as expected in Fennec
       assert.firefox();
@@ -1975,17 +1975,17 @@ GeckoDriver.prototype.actionChain = asyn
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.multiAction = async function(cmd) {
   assert.content(this.context);
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let {value, max_length} = cmd.parameters; // eslint-disable-line camelcase
   await this.listener.multiAction(value, max_length);
 };
 
 /**
  * Find an element using the indicated search strategy.
  *
@@ -1996,17 +1996,17 @@ GeckoDriver.prototype.multiAction = asyn
  *
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.findElement = async function(cmd) {
   const win = assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let {using, value} = cmd.parameters;
   let startNode;
   if (typeof cmd.parameters.element != "undefined") {
     startNode = WebElement.fromUUID(cmd.parameters.element, this.context);
   }
 
   let opts = {
@@ -2095,17 +2095,17 @@ GeckoDriver.prototype.findElements = asy
  *     A modal dialog is open, blocking this operation.
  * @throws {NoSuchElementError}
  *     If the document does not have an active element, i.e. if
  *     its document element has been deleted.
  */
 GeckoDriver.prototype.getActiveElement = async function() {
   assert.content(this.context);
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   return this.listener.getActiveElement();
 };
 
 /**
  * Send click event to element.
  *
  * @param {string} id
@@ -2117,17 +2117,17 @@ GeckoDriver.prototype.getActiveElement =
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.clickElement = async function(cmd) {
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let id = assert.string(cmd.parameters.id);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       let el = this.curBrowser.seenEls.get(webEl);
       await interaction.clickElement(el, this.a11yChecks);
@@ -2176,17 +2176,17 @@ GeckoDriver.prototype.clickElement = asy
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.getElementAttribute = async function(cmd) {
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let id = assert.string(cmd.parameters.id);
   let name = assert.string(cmd.parameters.name);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       let el = this.curBrowser.seenEls.get(webEl);
@@ -2217,17 +2217,17 @@ GeckoDriver.prototype.getElementAttribut
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.getElementProperty = async function(cmd) {
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let id = assert.string(cmd.parameters.id);
   let name = assert.string(cmd.parameters.name);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       let el = this.curBrowser.seenEls.get(webEl);
@@ -2257,17 +2257,17 @@ GeckoDriver.prototype.getElementProperty
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.getElementText = async function(cmd) {
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let id = assert.string(cmd.parameters.id);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       // for chrome, we look at text nodes, and any node with a "label" field
       let el = this.curBrowser.seenEls.get(webEl);
@@ -2298,17 +2298,17 @@ GeckoDriver.prototype.getElementText = a
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.getElementTagName = async function(cmd) {
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let id = assert.string(cmd.parameters.id);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       let el = this.curBrowser.seenEls.get(webEl);
       return el.tagName.toLowerCase();
@@ -2336,17 +2336,17 @@ GeckoDriver.prototype.getElementTagName 
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.isElementDisplayed = async function(cmd) {
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let id = assert.string(cmd.parameters.id);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       let el = this.curBrowser.seenEls.get(webEl);
       return interaction.isElementDisplayed(el, this.a11yChecks);
@@ -2376,17 +2376,17 @@ GeckoDriver.prototype.isElementDisplayed
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.getElementValueOfCssProperty = async function(cmd) {
   const win = assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let id = assert.string(cmd.parameters.id);
   let prop = assert.string(cmd.parameters.propertyName);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       let el = this.curBrowser.seenEls.get(webEl);
@@ -2416,17 +2416,17 @@ GeckoDriver.prototype.getElementValueOfC
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.isElementEnabled = async function(cmd) {
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let id = assert.string(cmd.parameters.id);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       // Selenium atom doesn't quite work here
       let el = this.curBrowser.seenEls.get(webEl);
@@ -2455,17 +2455,17 @@ GeckoDriver.prototype.isElementEnabled =
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.isElementSelected = async function(cmd) {
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let id = assert.string(cmd.parameters.id);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       // Selenium atom doesn't quite work here
       let el = this.curBrowser.seenEls.get(webEl);
@@ -2486,17 +2486,17 @@ GeckoDriver.prototype.isElementSelected 
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.getElementRect = async function(cmd) {
   const win = assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let id = assert.string(cmd.parameters.id);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       let el = this.curBrowser.seenEls.get(webEl);
       let rect = el.getBoundingClientRect();
@@ -2529,17 +2529,17 @@ GeckoDriver.prototype.getElementRect = a
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.sendKeysToElement = async function(cmd) {
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let id = assert.string(cmd.parameters.id);
   let text = assert.string(cmd.parameters.text);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       let el = this.curBrowser.seenEls.get(webEl);
@@ -2567,17 +2567,17 @@ GeckoDriver.prototype.sendKeysToElement 
  *     If element represented by reference <var>id</var> is unknown.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.clearElement = async function(cmd) {
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let id = assert.string(cmd.parameters.id);
   let webEl = WebElement.fromUUID(id, this.context);
 
   switch (this.context) {
     case Context.Chrome:
       // the selenium atom doesn't work here
       let el = this.curBrowser.seenEls.get(webEl);
@@ -2633,20 +2633,20 @@ GeckoDriver.prototype.switchToShadowRoot
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  * @throws {InvalidCookieDomainError}
  *     If <var>cookie</var> is for a different domain than the active
  *     document's host.
  */
-GeckoDriver.prototype.addCookie = function(cmd) {
+GeckoDriver.prototype.addCookie = async function(cmd) {
   assert.content(this.context);
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let {protocol, hostname} = this.currentURL;
 
   const networkSchemes = ["ftp:", "http:", "https:"];
   if (!networkSchemes.includes(protocol)) {
     throw new InvalidCookieDomainError("Document is cookie-averse");
   }
 
@@ -2663,39 +2663,39 @@ GeckoDriver.prototype.addCookie = functi
  *
  * @throws {UnsupportedOperationError}
  *     Not available in current context.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
-GeckoDriver.prototype.getCookies = function() {
+GeckoDriver.prototype.getCookies = async function() {
   assert.content(this.context);
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let {hostname, pathname} = this.currentURL;
   return [...cookie.iter(hostname, pathname)];
 };
 
 /**
  * Delete all cookies that are visible to a document.
  *
  * @throws {UnsupportedOperationError}
  *     Not available in current context.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
-GeckoDriver.prototype.deleteAllCookies = function() {
+GeckoDriver.prototype.deleteAllCookies = async function() {
   assert.content(this.context);
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let {hostname, pathname} = this.currentURL;
   for (let toDelete of cookie.iter(hostname, pathname)) {
     cookie.remove(toDelete);
   }
 };
 
 /**
@@ -2703,20 +2703,20 @@ GeckoDriver.prototype.deleteAllCookies =
  *
  * @throws {UnsupportedOperationError}
  *     Not available in current context.
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
-GeckoDriver.prototype.deleteCookie = function(cmd) {
+GeckoDriver.prototype.deleteCookie = async function(cmd) {
   assert.content(this.context);
   assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let {hostname, pathname} = this.currentURL;
   let name = assert.string(cmd.parameters.name);
   for (let c of cookie.iter(hostname, pathname)) {
     if (c.name === name) {
       cookie.remove(c);
     }
   }
@@ -2736,17 +2736,17 @@ GeckoDriver.prototype.deleteCookie = fun
  *
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.close = async function() {
   assert.open(this.getCurrentWindow(Context.Content));
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   let nwins = 0;
 
   for (let win of this.windows) {
     // For browser windows count the tabs. Otherwise take the window itself.
     let tabbrowser = browser.getTabBrowser(win);
     if (tabbrowser && tabbrowser.tabs) {
       nwins += tabbrowser.tabs.length;
@@ -2989,17 +2989,17 @@ GeckoDriver.prototype.setScreenOrientati
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.minimizeWindow = async function() {
   assert.firefox();
   const win = assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   if (WindowState.from(win.windowState) == WindowState.Fullscreen) {
     await exitFullscreen(win);
   }
 
   if (WindowState.from(win.windowState) != WindowState.Minimized) {
     await new Promise(resolve => {
       this.curBrowser.eventObserver.addEventListener("visibilitychange", resolve, {once: true});
@@ -3026,17 +3026,17 @@ GeckoDriver.prototype.minimizeWindow = a
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.maximizeWindow = async function() {
   assert.firefox();
   const win = assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   switch (WindowState.from(win.windowState)) {
     case WindowState.Fullscreen:
       await exitFullscreen(win);
       break;
 
     case WindowState.Minimized:
       await restoreWindow(win, this.curBrowser.eventObserver);
@@ -3112,17 +3112,17 @@ GeckoDriver.prototype.maximizeWindow = a
  * @throws {NoSuchWindowError}
  *     Top-level browsing context has been discarded.
  * @throws {UnexpectedAlertOpenError}
  *     A modal dialog is open, blocking this operation.
  */
 GeckoDriver.prototype.fullscreenWindow = async function() {
   assert.firefox();
   const win = assert.open(this.getCurrentWindow());
-  this._handleUserPrompts();
+  await this._handleUserPrompts();
 
   if (WindowState.from(win.windowState) == WindowState.Minimized) {
     await restoreWindow(win, this.curBrowser.eventObserver);
   }
 
   if (WindowState.from(win.windowState) != WindowState.Fullscreen) {
     await new Promise(resolve => {
       win.addEventListener("sizemodechange", resolve, {once: true});
@@ -3132,36 +3132,48 @@ GeckoDriver.prototype.fullscreenWindow =
 
   return this.curBrowser.rect;
 };
 
 /**
  * Dismisses a currently displayed tab modal, or returns no such alert if
  * no modal is displayed.
  */
-GeckoDriver.prototype.dismissDialog = function() {
-  assert.open(this.getCurrentWindow());
+GeckoDriver.prototype.dismissDialog = async function() {
+  let win = assert.open(this.getCurrentWindow());
   this._checkIfAlertIsPresent();
 
-  let {button0, button1} = this.dialog.ui;
-  (button1 ? button1 : button0).click();
-  this.dialog = null;
+  await new Promise(resolve => {
+    win.addEventListener("DOMModalDialogClosed", whenIdle(win, () => {
+      this.dialog = null;
+      resolve();
+    }), {once: true});
+
+    let {button0, button1} = this.dialog.ui;
+    (button1 ? button1 : button0).click();
+  });
 };
 
 /**
  * Accepts a currently displayed tab modal, or returns no such alert if
  * no modal is displayed.
  */
-GeckoDriver.prototype.acceptDialog = function() {
-  assert.open(this.getCurrentWindow());
+GeckoDriver.prototype.acceptDialog = async function() {
+  let win = assert.open(this.getCurrentWindow());
   this._checkIfAlertIsPresent();
 
-  let {button0} = this.dialog.ui;
-  button0.click();
-  this.dialog = null;
+  await new Promise(resolve => {
+    win.addEventListener("DOMModalDialogClosed", whenIdle(win, () => {
+      this.dialog = null;
+      resolve();
+    }), {once: true});
+
+    let {button0} = this.dialog.ui;
+    button0.click();
+  });
 };
 
 /**
  * Returns the message shown in a currently displayed modal, or returns
  * a no such alert error if no modal is currently displayed.
  */
 GeckoDriver.prototype.getTextFromDialog = function() {
   assert.open(this.getCurrentWindow());
@@ -3200,37 +3212,37 @@ GeckoDriver.prototype.sendKeysToDialog =
 };
 
 GeckoDriver.prototype._checkIfAlertIsPresent = function() {
   if (!this.dialog || !this.dialog.ui) {
     throw new NoSuchAlertError();
   }
 };
 
-GeckoDriver.prototype._handleUserPrompts = function() {
+GeckoDriver.prototype._handleUserPrompts = async function() {
   if (!this.dialog || !this.dialog.ui) {
     return;
   }
 
   let behavior = this.capabilities.get("unhandledPromptBehavior");
   switch (behavior) {
     case UnhandledPromptBehavior.Accept:
-      this.acceptDialog();
+      await this.acceptDialog();
       break;
 
     case UnhandledPromptBehavior.AcceptAndNotify:
-      this.acceptDialog();
+      await this.acceptDialog();
       throw new UnexpectedAlertOpenError();
 
     case UnhandledPromptBehavior.Dismiss:
-      this.dismissDialog();
+      await this.dismissDialog();
       break;
 
     case UnhandledPromptBehavior.DismissAndNotify:
-      this.dismissDialog();
+      await this.dismissDialog();
       throw new UnexpectedAlertOpenError();
 
     case UnhandledPromptBehavior.Ignore:
       throw new UnexpectedAlertOpenError();
 
     default:
       throw new TypeError(`Unknown unhandledPromptBehavior "${behavior}"`);
   }
deleted file mode 100644
--- a/testing/web-platform/meta/webdriver/tests/element_send_keys/user_prompts.py.ini
+++ /dev/null
@@ -1,24 +0,0 @@
-[user_prompts.py]
-  [test_accept[capabilities0-alert-None\]]
-    expected: FAIL
-    bug: 1479368
-
-  [test_accept[capabilities0-confirm-True\]]
-    expected: FAIL
-    bug: 1479368
-
-  [test_accept[capabilities0-prompt-\]]
-    expected: FAIL
-    bug: 1479368
-
-  [test_dismiss[capabilities0-alert-None\]]
-    expected: FAIL
-    bug: 1479368
-
-  [test_dismiss[capabilities0-confirm-False\]]
-    expected: FAIL
-    bug: 1479368
-
-  [test_dismiss[capabilities0-prompt-None\]]
-    expected: FAIL
-    bug: 1479368