Backed out 3 changesets (bug 1435871) for mochitest crashes. CLOSED TREE
authorDorel Luca <dluca@mozilla.com>
Wed, 17 Oct 2018 23:06:14 +0300
changeset 500262 0623ed3cb752851d5f96618b6a5f7c3048b49b60
parent 500261 63248a593eae0a14ffc33ab0057cf41d3ecb8018
child 500263 b67ac3f5e1aca5c8348375497fb7a0108a576179
push id1864
push userffxbld-merge
push dateMon, 03 Dec 2018 15:51:40 +0000
treeherdermozilla-release@f040763d99ad [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1435871
milestone64.0a1
backs out8eab3320b8c5fdda47ceb1c45e59628c7439f76d
29777ddd9def409cde9edd50570982ea23d07568
afdc3066f12cf33cfcf05cd4524b6d72b215acb2
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
Backed out 3 changesets (bug 1435871) for mochitest crashes. CLOSED TREE Backed out changeset 8eab3320b8c5 (bug 1435871) Backed out changeset 29777ddd9def (bug 1435871) Backed out changeset afdc3066f12c (bug 1435871)
browser/base/content/tabbrowser.js
browser/components/payments/content/paymentDialogWrapper.js
browser/components/payments/paymentUIService.js
browser/components/payments/res/containers/payment-dialog.js
browser/components/payments/res/paymentRequest.js
browser/components/payments/test/PaymentTestUtils.jsm
browser/components/payments/test/browser/browser_dropdowns.js
browser/components/payments/test/browser/browser_openPreferences.js
browser/components/payments/test/browser/browser_show_dialog.js
browser/components/payments/test/browser/head.js
toolkit/components/prompts/content/tabprompts.css
toolkit/themes/osx/global/tabprompts.css
toolkit/themes/windows/global/tabprompts.css
--- a/browser/base/content/tabbrowser.js
+++ b/browser/base/content/tabbrowser.js
@@ -1089,23 +1089,18 @@ window._gBrowser = {
       return;
 
     let newBrowser = this.getBrowserForTab(newTab);
 
     // If there's a tabmodal prompt showing, focus it.
     if (newBrowser.hasAttribute("tabmodalPromptShowing")) {
       let prompts = newBrowser.parentNode.getElementsByTagNameNS(this._XUL_NS, "tabmodalprompt");
       let prompt = prompts[prompts.length - 1];
-      // @tabmodalPromptShowing is also set for other tab modal prompts
-      // (e.g. the Payment Request dialog) so there may not be a <tabmodalprompt>.
-      // Bug 1492814 will implement this for the Payment Request dialog.
-      if (prompt) {
-        prompt.Dialog.setDefaultFocus();
-        return;
-      }
+      prompt.Dialog.setDefaultFocus();
+      return;
     }
 
     // Focus the location bar if it was previously focused for that tab.
     // In full screen mode, only bother making the location bar visible
     // if the tab is a blank one.
     if (newBrowser._urlbarFocused && gURLBar) {
       // Explicitly close the popup if the URL bar retains focus
       gURLBar.closePopup();
--- a/browser/components/payments/content/paymentDialogWrapper.js
+++ b/browser/components/payments/content/paymentDialogWrapper.js
@@ -7,25 +7,20 @@
  * own scope.
  */
 
 "use strict";
 
 const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"]
                      .getService(Ci.nsIPaymentRequestService);
 
-const paymentUISrv = Cc["@mozilla.org/dom/payments/payment-ui-service;1"]
-                     .getService(Ci.nsIPaymentUIService);
-
 ChromeUtils.import("resource://gre/modules/AppConstants.jsm");
 ChromeUtils.import("resource://gre/modules/Services.jsm");
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
 
-ChromeUtils.defineModuleGetter(this, "BrowserWindowTracker",
-                               "resource:///modules/BrowserWindowTracker.jsm");
 ChromeUtils.defineModuleGetter(this, "OSKeyStore",
                                "resource://formautofill/OSKeyStore.jsm");
 ChromeUtils.defineModuleGetter(this, "PrivateBrowsingUtils",
                                "resource://gre/modules/PrivateBrowsingUtils.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "formAutofillStorage", () => {
   let storage;
   try {
@@ -216,17 +211,17 @@ var paymentDialogWrapper = {
     this.mm.addMessageListener("paymentContentToChrome", this);
     this.mm.loadFrameScript("chrome://payments/content/paymentDialogFrameScript.js", true);
     // Until we have bug 1446164 and bug 1407418 we use form autofill's temporary
     // shim for data-localization* attributes.
     this.mm.loadFrameScript("chrome://formautofill/content/l10n.js", true);
     if (AppConstants.platform == "win") {
       this.frame.setAttribute("selectmenulist", "ContentSelectDropdown-windows");
     }
-    this.frame.setAttribute("src", "resource://payments/paymentRequest.xhtml");
+    this.frame.loadURI("resource://payments/paymentRequest.xhtml");
 
     this.temporaryStore = {
       addresses: new TempCollection("addresses"),
       creditCards: new TempCollection("creditCards"),
     };
   },
 
   createShowResponse({
@@ -452,17 +447,17 @@ var paymentDialogWrapper = {
     }
     return obj;
   },
 
   async initializeFrame() {
     Services.obs.addObserver(this, "formautofill-storage-changed", true);
 
     let requestSerialized = this._serializeRequest(this.request);
-    let chromeWindow = window.frameElement.ownerGlobal;
+    let chromeWindow = Services.wm.getMostRecentWindow("navigator:browser");
     let isPrivate = PrivateBrowsingUtils.isWindowPrivate(chromeWindow);
 
     let [savedAddresses, savedBasicCards] =
       await Promise.all([this.fetchSavedAddresses(), this.fetchSavedPaymentCards()]);
 
     this.sendMessageToContent("showPaymentRequest", {
       request: requestSerialized,
       savedAddresses,
@@ -474,35 +469,38 @@ var paymentDialogWrapper = {
   },
 
   debugFrame() {
     // To avoid self-XSS-type attacks, ensure that Browser Chrome debugging is enabled.
     if (!Services.prefs.getBoolPref("devtools.chrome.enabled", false)) {
       Cu.reportError("devtools.chrome.enabled must be enabled to debug the frame");
       return;
     }
+    let chromeWindow = Services.wm.getMostRecentWindow(null);
     let {
       gDevToolsBrowser,
     } = ChromeUtils.import("resource://devtools/client/framework/gDevTools.jsm", {});
     gDevToolsBrowser.openContentProcessToolbox({
-      selectedBrowser: document.getElementById("paymentRequestFrame").frameLoader,
+      selectedBrowser: chromeWindow.document.getElementById("paymentRequestFrame").frameLoader,
     });
   },
 
   onOpenPreferences() {
-    BrowserWindowTracker.getTopWindow().openPreferences("privacy-form-autofill");
+    let prefsURL = Cc["@mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
+    prefsURL.data = "about:preferences#privacy-form-autofill";
+    Services.ww.openWindow(null, AppConstants.BROWSER_CHROME_URL, "_blank", "chrome,all,dialog=no",
+                           prefsURL);
   },
 
   onPaymentCancel() {
     const showResponse = this.createShowResponse({
       acceptStatus: Ci.nsIPaymentActionResponse.PAYMENT_REJECTED,
     });
-
     paymentSrv.respondPayment(showResponse);
-    paymentUISrv.closePayment(this.request.requestId);
+    window.close();
   },
 
   async onPay({
     selectedPayerAddressGUID: payerGUID,
     selectedPaymentCardGUID: paymentCardGUID,
     selectedPaymentCardSecurityCode: cardSecurityCode,
   }) {
     let methodData;
@@ -572,17 +570,17 @@ var paymentDialogWrapper = {
     // the dialog before the onChangeShippingOption is called, thus
     // deleting the request and making the requestId invalid. Unclear
     // why we aren't seeing the same issue with onChangeShippingAddress.
     paymentSrv.changeShippingOption(this.request.requestId, optionID);
   },
 
   onCloseDialogMessage() {
     // The PR is complete(), just close the dialog
-    paymentUISrv.closePayment(this.request.requestId);
+    window.close();
   },
 
   async onUpdateAutofillRecord(collectionName, record, guid, messageID) {
     let responseMessage = {
       guid,
       messageID,
       stateChange: {},
     };
@@ -682,33 +680,24 @@ var paymentDialogWrapper = {
       case "openPreferences": {
         this.onOpenPreferences();
         break;
       }
       case "paymentCancel": {
         this.onPaymentCancel();
         break;
       }
-      case "paymentDialogReady": {
-        window.dispatchEvent(new Event("tabmodaldialogready", {
-          bubbles: true,
-        }));
-        break;
-      }
       case "pay": {
         this.onPay(data);
         break;
       }
       case "updateAutofillRecord": {
         this.onUpdateAutofillRecord(data.collectionName, data.record, data.guid, data.messageID);
         break;
       }
-      default: {
-        throw new Error(`paymentDialogWrapper: Unexpected messageType: ${messageType}`);
-      }
     }
   },
 };
 
 if ("document" in this) {
   // Running in a browser, not a unit test
   let frame = document.getElementById("paymentRequestFrame");
   let requestId = (new URLSearchParams(window.location.search)).get("requestId");
--- a/browser/components/payments/paymentUIService.js
+++ b/browser/components/payments/paymentUIService.js
@@ -10,84 +10,64 @@
  * PaymentUIService is started by the DOM code lazily.
  *
  * For now the UI is shown in a native dialog but that is likely to change.
  * Tests should try to avoid relying on that implementation detail.
  */
 
 "use strict";
 
-const XHTML_NS = "http://www.w3.org/1999/xhtml";
-
 ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
-
-ChromeUtils.defineModuleGetter(this, "BrowserWindowTracker",
-                               "resource:///modules/BrowserWindowTracker.jsm");
+ChromeUtils.import("resource://gre/modules/Services.jsm");
 
 XPCOMUtils.defineLazyServiceGetter(this,
                                    "paymentSrv",
                                    "@mozilla.org/dom/payments/payment-request-service;1",
                                    "nsIPaymentRequestService");
 
 function PaymentUIService() {
   this.wrappedJSObject = this;
   XPCOMUtils.defineLazyGetter(this, "log", () => {
     let {ConsoleAPI} = ChromeUtils.import("resource://gre/modules/Console.jsm", {});
     return new ConsoleAPI({
       maxLogLevelPref: "dom.payments.loglevel",
       prefix: "Payment UI Service",
     });
   });
+  Services.wm.addListener(this);
   this.log.debug("constructor");
 }
 
 PaymentUIService.prototype = {
   classID: Components.ID("{01f8bd55-9017-438b-85ec-7c15d2b35cdc}"),
   QueryInterface: ChromeUtils.generateQI([Ci.nsIPaymentUIService]),
   DIALOG_URL: "chrome://payments/content/paymentDialogWrapper.xul",
   REQUEST_ID_PREFIX: "paymentRequest-",
 
+  // nsIWindowMediatorListener implementation:
+
+  onOpenWindow(aWindow) {},
+  onCloseWindow(aWindow) {
+    let domWindow = aWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindow);
+    let requestId = this.requestIdForWindow(domWindow);
+    if (!requestId || !paymentSrv.getPaymentRequestById(requestId)) {
+      return;
+    }
+    this.log.debug(`onCloseWindow, close of window for active requestId: ${requestId}`);
+    this.rejectPaymentForClosedDialog(requestId);
+  },
+
   // nsIPaymentUIService implementation:
 
   showPayment(requestId) {
     this.log.debug("showPayment:", requestId);
-    let request = paymentSrv.getPaymentRequestById(requestId);
-    let merchantBrowser = this.findBrowserByTabId(request.tabId);
-    let chromeWindow = merchantBrowser.ownerGlobal;
-    let {gBrowser} = chromeWindow;
-    let browserContainer = gBrowser.getBrowserContainer(merchantBrowser);
-    let container = chromeWindow.document.createElementNS(XHTML_NS, "div");
-    container.dataset.requestId = requestId;
-    container.classList.add("paymentDialogContainer");
-    container.hidden = true;
-    let paymentsBrowser = chromeWindow.document.createElementNS(XHTML_NS, "iframe");
-    paymentsBrowser.classList.add("paymentDialogContainerFrame");
-    paymentsBrowser.setAttribute("type", "content");
-    paymentsBrowser.setAttribute("remote", "true");
-    paymentsBrowser.setAttribute("src", `${this.DIALOG_URL}?requestId=${requestId}`);
-    // append the frame to start the loading
-    container.appendChild(paymentsBrowser);
-    browserContainer.prepend(container);
-
-    // Only show the frame and change the UI when the dialog is ready to show.
-    paymentsBrowser.addEventListener("tabmodaldialogready", function readyToShow() {
-      container.hidden = false;
-
-      // Prevent focusing or interacting with the <browser>.
-      merchantBrowser.setAttribute("tabmodalPromptShowing", "true");
-
-      // Darken the merchant content area.
-      let tabModalBackground = chromeWindow.document.createElement("box");
-      tabModalBackground.classList.add("tab-modal-background", "payment-dialog-background");
-      // Insert the same way as <tabmodalprompt>.
-      merchantBrowser.parentNode.insertBefore(tabModalBackground,
-                                              merchantBrowser.nextElementSibling);
-    }, {
-      once: true,
-    });
+    let chromeWindow = Services.wm.getMostRecentWindow("navigator:browser");
+    chromeWindow.openDialog(`${this.DIALOG_URL}?requestId=${requestId}`,
+                            `${this.REQUEST_ID_PREFIX}${requestId}`,
+                            "modal,dialog,centerscreen,resizable=no");
   },
 
   abortPayment(requestId) {
     this.log.debug("abortPayment:", requestId);
     let abortResponse = Cc["@mozilla.org/dom/payments/payment-abort-action-response;1"]
                           .createInstance(Ci.nsIPaymentAbortActionResponse);
     let found = this.closeDialog(requestId);
 
@@ -96,113 +76,104 @@ PaymentUIService.prototype = {
     let response = found ?
       Ci.nsIPaymentActionResponse.ABORT_SUCCEEDED :
       Ci.nsIPaymentActionResponse.ABORT_FAILED;
 
     abortResponse.init(requestId, response);
     paymentSrv.respondPayment(abortResponse);
   },
 
+  rejectPaymentForClosedDialog(requestId) {
+    this.log.debug("rejectPaymentForClosedDialog:", requestId);
+    const rejectResponse = Cc["@mozilla.org/dom/payments/payment-show-action-response;1"]
+                            .createInstance(Ci.nsIPaymentShowActionResponse);
+    rejectResponse.init(requestId,
+                        Ci.nsIPaymentActionResponse.PAYMENT_REJECTED,
+                        "", // payment method
+                        null, // payment method data
+                        "", // payer name
+                        "", // payer email
+                        "");// payer phone
+    paymentSrv.respondPayment(rejectResponse);
+  },
+
   completePayment(requestId) {
     // completeStatus should be one of "timeout", "success", "fail", ""
     let {completeStatus} = paymentSrv.getPaymentRequestById(requestId);
     this.log.debug(`completePayment: requestId: ${requestId}, completeStatus: ${completeStatus}`);
 
     let closed;
     switch (completeStatus) {
       case "fail":
       case "timeout":
         break;
       default:
         closed = this.closeDialog(requestId);
         break;
     }
-
-    let dialogContainer;
-    if (!closed) {
-      // We need to call findDialog before we respond below as getPaymentRequestById
-      // may fail due to the request being removed upon completion.
-      dialogContainer = this.findDialog(requestId).dialogContainer;
-      if (!dialogContainer) {
-        this.log.error("completePayment: no dialog found");
-        return;
-      }
-    }
-
     let responseCode = closed ?
         Ci.nsIPaymentActionResponse.COMPLETE_SUCCEEDED :
         Ci.nsIPaymentActionResponse.COMPLETE_FAILED;
     let completeResponse = Cc["@mozilla.org/dom/payments/payment-complete-action-response;1"]
                              .createInstance(Ci.nsIPaymentCompleteActionResponse);
     completeResponse.init(requestId, responseCode);
     paymentSrv.respondPayment(completeResponse.QueryInterface(Ci.nsIPaymentActionResponse));
 
     if (!closed) {
-      dialogContainer.querySelector("iframe").contentWindow.paymentDialogWrapper.updateRequest();
+      let dialog = this.findDialog(requestId);
+      if (!dialog) {
+        this.log.error("completePayment: no dialog found");
+        return;
+      }
+      dialog.paymentDialogWrapper.updateRequest();
     }
   },
 
   updatePayment(requestId) {
-    let {dialogContainer} = this.findDialog(requestId);
+    let dialog = this.findDialog(requestId);
     this.log.debug("updatePayment:", requestId);
-    if (!dialogContainer) {
+    if (!dialog) {
       this.log.error("updatePayment: no dialog found");
       return;
     }
-    dialogContainer.querySelector("iframe").contentWindow.paymentDialogWrapper.updateRequest();
+    dialog.paymentDialogWrapper.updateRequest();
   },
 
   closePayment(requestId) {
     this.closeDialog(requestId);
   },
 
   // other helper methods
 
   /**
    * @param {string} requestId - Payment Request ID of the dialog to close.
    * @returns {boolean} whether the specified dialog was closed.
    */
   closeDialog(requestId) {
-    let {
-      browser,
-      dialogContainer,
-    } = this.findDialog(requestId);
-    if (!dialogContainer) {
+    let win = this.findDialog(requestId);
+    if (!win) {
       return false;
     }
-    this.log.debug(`closing: ${requestId}`);
-    dialogContainer.remove();
-    browser.parentElement.querySelector(".payment-dialog-background").remove();
+    this.log.debug(`closing: ${win.name}`);
+    win.close();
     return true;
   },
 
   findDialog(requestId) {
-    for (let win of BrowserWindowTracker.orderedWindows) {
-      for (let dialogContainer of win.document.querySelectorAll(".paymentDialogContainer")) {
-        if (dialogContainer.dataset.requestId == requestId) {
-          return {
-            dialogContainer,
-            browser: dialogContainer.parentElement.querySelector("browser"),
-          };
-        }
-      }
-    }
-    return {};
-  },
-
-  findBrowserByTabId(tabId) {
-    for (let win of BrowserWindowTracker.orderedWindows) {
-      for (let browser of win.gBrowser.browsers) {
-        if (!browser.frameLoader || !browser.frameLoader.tabParent) {
-          continue;
-        }
-        if (browser.frameLoader.tabParent.tabId == tabId) {
-          return browser;
-        }
+    for (let win of Services.wm.getEnumerator(null)) {
+      if (win.name == `${this.REQUEST_ID_PREFIX}${requestId}`) {
+        return win;
       }
     }
 
-    this.log.error("findBrowserByTabId: No browser found for tabId:", tabId);
     return null;
   },
+
+  requestIdForWindow(window) {
+    let windowName = window.name;
+
+    return windowName.startsWith(this.REQUEST_ID_PREFIX) ?
+      windowName.replace(this.REQUEST_ID_PREFIX, "") : // returns suffix, which is the requestId
+      null;
+  },
 };
 
 this.NSGetFactory = XPCOMUtils.generateNSGetFactory([PaymentUIService]);
--- a/browser/components/payments/res/containers/payment-dialog.js
+++ b/browser/components/payments/res/containers/payment-dialog.js
@@ -380,17 +380,17 @@ export default class PaymentDialog exten
     this._renderPayerFields(state);
 
     let isMac = /mac/i.test(navigator.platform);
     for (let manageTextEl of this._manageText.children) {
       manageTextEl.hidden = manageTextEl.dataset.os == "mac" ? !isMac : isMac;
       let link = manageTextEl.querySelector("a");
       // The href is only set to be exposed to accessibility tools so users know what will open.
       // The actual opening happens from the click event listener.
-      link.href = "about:preferences#privacy-form-autofill";
+      link.href = "about:preferences#privacy-address-autofill";
     }
 
     this._renderPayButton(state);
 
     for (let page of this._mainContainer.querySelectorAll(":scope > .page")) {
       page.hidden = state.page.id != page.id;
     }
 
--- a/browser/components/payments/res/paymentRequest.js
+++ b/browser/components/payments/res/paymentRequest.js
@@ -104,16 +104,17 @@ var paymentRequest = {
         break;
       }
     }
   },
 
   onPaymentRequestLoad() {
     log.debug("onPaymentRequestLoad");
     window.addEventListener("unload", this, {once: true});
+    this.sendMessageToChrome("paymentDialogReady");
 
     // Automatically show the debugging console if loaded with a truthy `debug` query parameter.
     if (new URLSearchParams(location.search).get("debug")) {
       this.toggleDebuggingConsole();
     }
   },
 
   async onShowPaymentRequest(detail) {
@@ -164,18 +165,16 @@ var paymentRequest = {
     } else if (!hasSavedCards) {
       state.page = {
         id: "basic-card-page",
         onboardingWizard: true,
       };
     }
 
     paymentDialog.setStateFromParent(state);
-
-    this.sendMessageToChrome("paymentDialogReady");
   },
 
   openPreferences() {
     this.sendMessageToChrome("openPreferences");
   },
 
   cancel() {
     this.sendMessageToChrome("paymentCancel");
--- a/browser/components/payments/test/PaymentTestUtils.jsm
+++ b/browser/components/payments/test/PaymentTestUtils.jsm
@@ -107,29 +107,38 @@ var PaymentTestUtils = {
 
     /**
      * Create a new payment request cached as `rq` and then show it.
      *
      * @param {Object} args
      * @param {PaymentMethodData[]} methodData
      * @param {PaymentDetailsInit} details
      * @param {PaymentOptions} options
-     * @returns {Object}
      */
     createAndShowRequest: ({methodData, details, options}) => {
       const rq = new content.PaymentRequest(Cu.cloneInto(methodData, content), details, options);
       content.rq = rq; // assign it so we can retrieve it later
 
       const handle = content.windowUtils.setHandlingUserInput(true);
       content.showPromise = rq.show();
 
       handle.destruct();
-      return {
-        requestId: rq.id,
-      };
+    },
+
+    /**
+     * Add a rejection handler for the `showPromise` created by createAndShowRequest
+     * and stash details of any eventual exception or response in `rqResult`
+     */
+    catchShowPromiseRejection: () => {
+      content.rqResult = {};
+      content.showPromise.then(res => content.rqResult.response = res)
+                         .catch(ex => content.rqResult.showException = {
+                           name: ex.name,
+                           message: ex.message,
+                         });
     },
   },
 
   DialogContentTasks: {
     getShippingOptions: () => {
       let picker = content.document.querySelector("shipping-option-picker");
       let popupBox = Cu.waiveXrays(picker).dropdown.popupBox;
       let selectedOptionIndex = popupBox.selectedIndex;
--- a/browser/components/payments/test/browser/browser_dropdowns.js
+++ b/browser/components/payments/test/browser/browser_dropdowns.js
@@ -40,16 +40,14 @@ add_task(async function test_dropdown() 
 
     let event = await popupshownPromise;
     let expectedPopupID = "ContentSelectDropdown";
     if (AppConstants.platform == "win") {
       expectedPopupID = "ContentSelectDropdown-windows";
     }
     is(event.target.parentElement.id, expectedPopupID, "Checked menulist of opened popup");
 
-    event.target.hidePopup(true);
-
     info("clicking cancel");
     spawnPaymentDialogTask(frame, PTU.DialogContentTasks.manuallyClickCancel);
 
     await BrowserTestUtils.waitForCondition(() => win.closed, "dialog should be closed");
   });
 });
--- a/browser/components/payments/test/browser/browser_openPreferences.js
+++ b/browser/components/payments/test/browser/browser_openPreferences.js
@@ -15,18 +15,19 @@ add_task(async function test_openPrefere
     url: BLANK_PAGE_URL,
   }, async browser => {
     let {win, frame} = await setupPaymentDialog(browser, {
       methodData,
       details,
       merchantTaskFn: PTU.ContentTasks.createAndShowRequest,
     });
 
-    let prefsTabPromise = BrowserTestUtils.waitForNewTab(gBrowser,
-                                                         "about:preferences#privacy-form-autofill");
+    let prefsWindowPromise = BrowserTestUtils.waitForNewWindow({
+      url: "about:preferences#privacy",
+    });
 
     let prefsLoadedPromise = TestUtils.topicObserved("sync-pane-loaded");
 
     await spawnPaymentDialogTask(frame, function verifyPrefsLink({isMac}) {
       let manageTextEl = content.document.querySelector(".manage-text");
 
       let expectedVisibleEl;
       if (isMac) {
@@ -43,18 +44,18 @@ add_task(async function test_openPrefere
       let prefsLink = expectedVisibleEl.querySelector("a");
       ok(prefsLink, "Preferences link should exist");
       prefsLink.scrollIntoView();
       EventUtils.synthesizeMouseAtCenter(prefsLink, {}, content);
     }, {
       isMac: AppConstants.platform == "macosx",
     });
 
-    let prefsTab = await prefsTabPromise;
-    ok(prefsTab, "Ensure a tab was opened");
+    let browserWin = await prefsWindowPromise;
+    ok(browserWin, "Ensure a window was opened");
     await prefsLoadedPromise;
 
-    await BrowserTestUtils.removeTab(prefsTab);
+    await BrowserTestUtils.closeWindow(browserWin);
 
     spawnPaymentDialogTask(frame, PTU.DialogContentTasks.manuallyClickCancel);
     await BrowserTestUtils.waitForCondition(() => win.closed, "dialog should be closed");
   });
 });
--- a/browser/components/payments/test/browser/browser_show_dialog.js
+++ b/browser/components/payments/test/browser/browser_show_dialog.js
@@ -138,16 +138,41 @@ add_task(async function test_show_comple
     let result = await ContentTask.spawn(browser, {}, PTU.ContentTasks.addCompletionHandler);
 
     is(result.response.shippingOption, "1", "Check shipping option");
 
     await BrowserTestUtils.waitForCondition(() => win.closed, "dialog should be closed");
   });
 });
 
+add_task(async function test_show_closeReject_dialog() {
+  await BrowserTestUtils.withNewTab({
+    gBrowser,
+    url: BLANK_PAGE_URL,
+  }, async browser => {
+    let {win} =
+      await setupPaymentDialog(browser, {
+        methodData,
+        details,
+        merchantTaskFn: PTU.ContentTasks.createAndShowRequest,
+      }
+    );
+    await ContentTask.spawn(browser, null, PTU.ContentTasks.catchShowPromiseRejection);
+
+    info("Closing the dialog to reject the payment request");
+    BrowserTestUtils.closeWindow(win);
+    await BrowserTestUtils.waitForCondition(() => win.closed, "dialog should be closed");
+
+    let result = await ContentTask.spawn(browser, null, async () => content.rqResult);
+    ok(result.showException, "Expected promise rejection from the rq.show() promise");
+    ok(!result.response,
+       "rq.show() shouldn't resolve to a response");
+  });
+});
+
 add_task(async function test_localized() {
   await BrowserTestUtils.withNewTab({
     gBrowser,
     url: BLANK_PAGE_URL,
   }, async browser => {
     let {win, frame} =
       await setupPaymentDialog(browser, {
         methodData,
@@ -246,73 +271,8 @@ add_task(async function test_supportedNe
     await spawnPaymentDialogTask(frame, async () => {
       ok(!content.document.getElementById("pay").disabled, "pay button should not be disabled");
     });
 
     spawnPaymentDialogTask(frame, PTU.DialogContentTasks.manuallyClickCancel);
     await BrowserTestUtils.waitForCondition(() => win.closed, "dialog should be closed");
   });
 });
-
-add_task(async function test_tab_modal() {
-  await BrowserTestUtils.withNewTab({
-    gBrowser,
-    url: BLANK_PAGE_URL,
-  }, async browser => {
-    let {win, frame} = await setupPaymentDialog(browser, {
-      methodData,
-      details,
-      merchantTaskFn: PTU.ContentTasks.createAndShowRequest,
-    });
-
-    await TestUtils.waitForCondition(() => {
-      return !document.querySelector(".paymentDialogContainer").hidden;
-    }, "Waiting for container to be visible after the dialog's ready");
-
-    ok(!EventUtils.isHidden(win.frameElement), "Frame should be visible");
-
-    let {
-      bottom: toolboxBottom,
-    } = document.getElementById("navigator-toolbox").getBoundingClientRect();
-
-    let {x, y} = win.frameElement.getBoundingClientRect();
-    ok(y > 0, "Frame should have y > 0");
-    // Inset by 10px since the corner point doesn't return the frame due to the
-    // border-radius.
-    is(document.elementFromPoint(x + 10, y + 10), win.frameElement,
-       "Check .paymentDialogContainerFrame is visible");
-
-    info("Click to the left of the dialog over the content area");
-    isnot(document.elementFromPoint(x - 10, y + 50), browser,
-          "Check clicks on the merchant content area don't go to the browser");
-    is(document.elementFromPoint(x - 10, y + 50),
-       document.querySelector(".payment-dialog-background"),
-       "Check clicks on the merchant content area go to the payment dialog background");
-
-    ok(y < toolboxBottom - 2, "Dialog should overlap the toolbox by at least 2px");
-
-    await BrowserTestUtils.withNewTab({
-      gBrowser,
-      url: BLANK_PAGE_URL,
-    }, async newBrowser => {
-      let {
-        x: x2,
-        y: y2,
-      } = win.frameElement.getBoundingClientRect();
-      is(x2, x, "Check x-coordinate is the same");
-      is(y2, y, "Check y-coordinate is the same");
-      isnot(document.elementFromPoint(x + 10, y + 10), win.frameElement,
-            "Check .paymentDialogContainerFrame is hidden");
-    });
-
-    let {
-      x: x3,
-      y: y3,
-    } = win.frameElement.getBoundingClientRect();
-    is(x3, x, "Check x-coordinate is the same again");
-    is(y3, y, "Check y-coordinate is the same again");
-    is(document.elementFromPoint(x + 10, y + 10), win.frameElement,
-       "Check .paymentDialogContainerFrame is visible again");
-
-    spawnPaymentDialogTask(frame, PTU.DialogContentTasks.manuallyClickCancel);
-    await BrowserTestUtils.waitForCondition(() => win.closed, "dialog should be closed");
-  });
-});
--- a/browser/components/payments/test/browser/head.js
+++ b/browser/components/payments/test/browser/head.js
@@ -12,48 +12,43 @@ const BLANK_PAGE_PATH = "/browser/browse
 const BLANK_PAGE_URL = "https://example.com" + BLANK_PAGE_PATH;
 const RESPONSE_TIMEOUT_PREF = "dom.payments.response.timeout";
 const SAVE_CREDITCARD_DEFAULT_PREF = "dom.payments.defaults.saveCreditCard";
 const SAVE_ADDRESS_DEFAULT_PREF = "dom.payments.defaults.saveAddress";
 
 const paymentSrv = Cc["@mozilla.org/dom/payments/payment-request-service;1"]
                      .getService(Ci.nsIPaymentRequestService);
 const paymentUISrv = Cc["@mozilla.org/dom/payments/payment-ui-service;1"]
-                     .getService(Ci.nsIPaymentUIService).wrappedJSObject;
+                     .getService().wrappedJSObject;
 const {AppConstants} = ChromeUtils.import("resource://gre/modules/AppConstants.jsm", {});
 const {formAutofillStorage} = ChromeUtils.import(
   "resource://formautofill/FormAutofillStorage.jsm", {});
 const {PaymentTestUtils: PTU} = ChromeUtils.import(
   "resource://testing-common/PaymentTestUtils.jsm", {});
-ChromeUtils.import("resource:///modules/BrowserWindowTracker.jsm");
 ChromeUtils.import("resource://gre/modules/CreditCard.jsm");
 
 function getPaymentRequests() {
   return Array.from(paymentSrv.enumerate());
 }
 
 /**
  * Return the container (e.g. dialog or overlay) that the payment request contents are shown in.
- * This abstracts away the details of the widget used so that this can more easily transition to
- * another kind of dialog/overlay.
- * @param {string} requestId
+ * This abstracts away the details of the widget used so that this can more earily transition from a
+ * dialog to another kind of overlay.
+ * Consumers shouldn't rely on a dialog window being returned.
  * @returns {Promise}
  */
-async function getPaymentWidget(requestId) {
-  return BrowserTestUtils.waitForCondition(() => {
-    let {dialogContainer} = paymentUISrv.findDialog(requestId);
-    if (!dialogContainer) {
-      return false;
-    }
-    let browserIFrame = dialogContainer.querySelector("iframe");
-    if (!browserIFrame) {
-      return false;
-    }
-    return browserIFrame.contentWindow;
-  }, "payment dialog should be opened");
+async function getPaymentWidget() {
+  let win;
+  await BrowserTestUtils.waitForCondition(() => {
+    win = Services.wm.getMostRecentWindow(null);
+    return win.name.startsWith(paymentUISrv.REQUEST_ID_PREFIX);
+  }, "payment dialog should be the most recent");
+
+  return win;
 }
 
 async function getPaymentFrame(widget) {
   return widget.document.getElementById("paymentRequestFrame");
 }
 
 function waitForMessageFromWidget(messageType, widget = null) {
   info("waitForMessageFromWidget: " + messageType);
@@ -237,28 +232,29 @@ function checkPaymentMethodDetailsMatche
  * @param {Object} options.methodData
  * @param {Object} options.details
  * @param {Object} options.options
  * @param {Function} options.merchantTaskFn
  * @returns {Object} References to the window, requestId, and frame
  */
 async function setupPaymentDialog(browser, {methodData, details, options, merchantTaskFn}) {
   let dialogReadyPromise = waitForWidgetReady();
-  let {requestId} = await ContentTask.spawn(browser,
-                                            {
-                                              methodData,
-                                              details,
-                                              options,
-                                            },
-                                            merchantTaskFn);
-  ok(requestId, "requestId should be defined");
+  await ContentTask.spawn(browser,
+                          {
+                            methodData,
+                            details,
+                            options,
+                          },
+                          merchantTaskFn);
 
   // get a reference to the UI dialog and the requestId
-  let [win] = await Promise.all([getPaymentWidget(requestId), dialogReadyPromise]);
+  let [win] = await Promise.all([getPaymentWidget(), dialogReadyPromise]);
   ok(win, "Got payment widget");
+  let requestId = paymentUISrv.requestIdForWindow(win);
+  ok(requestId, "requestId should be defined");
   is(win.closed, false, "dialog should not be closed");
 
   let frame = await getPaymentFrame(win);
   ok(frame, "Got payment frame");
 
   await dialogReadyPromise;
   info("dialog ready");
 
--- a/toolkit/components/prompts/content/tabprompts.css
+++ b/toolkit/components/prompts/content/tabprompts.css
@@ -1,14 +1,13 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* Tab Modal Prompt boxes */
-.tab-modal-background,
 tabmodalprompt {
   width: 100%;
   height: 100%;
   -moz-box-pack: center;
   -moz-box-orient: vertical;
 }
 
 .tabmodalprompt-mainContainer {
@@ -29,24 +28,8 @@ tabmodalprompt {
   cursor: text !important;
   white-space: pre-wrap;
   unicode-bidi: plaintext;
 }
 
 tabmodalprompt label[value=""] {
   visibility: collapse;
 }
-
-/* Tab-Modal Payment Request widget */
-.paymentDialogContainer {
-  position: absolute;
-}
-
-.paymentDialogContainerFrame {
-  box-sizing: border-box;
-  height: 500px;
-  /* Center the dialog with 20% on the left/right and 60% width for content */
-  left: 20%;
-  position: absolute;
-  /* Overlap the chrome */
-  top: -6px;
-  width: 60%;
-}
--- a/toolkit/themes/osx/global/tabprompts.css
+++ b/toolkit/themes/osx/global/tabprompts.css
@@ -1,24 +1,19 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* Tab Modal Prompt boxes */
-.tab-modal-background,
 tabmodalprompt {
   background-color: hsla(0,0%,10%,.5);
-}
-
-tabmodalprompt {
   font-family: sans-serif; /* use content font not system UI font */
   font-size: 110%;
 }
 
-.paymentDialogContainerFrame,
 .tabmodalprompt-mainContainer {
   color: black;
   background-color: hsla(0,0%,100%,.95);
   background-clip: padding-box;
   border-radius: 2px;
   border: 1px solid hsla(0,0%,0%,.5);
 }
 
--- a/toolkit/themes/windows/global/tabprompts.css
+++ b/toolkit/themes/windows/global/tabprompts.css
@@ -1,23 +1,18 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /* Tab Modal Prompt boxes */
-.tab-modal-background,
 tabmodalprompt {
   background-color: hsla(0,0%,10%,.5);
-}
-
-tabmodalprompt {
   font-family: sans-serif; /* use content font not system UI font */
 }
 
-.paymentDialogContainerFrame,
 .tabmodalprompt-mainContainer {
   color: -moz-fieldText;
   background-color: -moz-field;
   border-radius: 2px;
   border: 1px solid threeDDarkShadow;
 }
 
 .tabmodalprompt-topContainer {