Backed out 2 changesets (bug 1435871) for multiple browser-chrome failures on payments. CLOSED TREE
authorBrindusan Cristian <cbrindusan@mozilla.com>
Fri, 19 Oct 2018 12:36:13 +0300
changeset 490436 ad81b437f8604c61701ae3a3112b8490577308eb
parent 490435 462a889b96ca175b528d6d5a00966dd68ae66fae
child 490437 1030155f208e08a4a4673655c8b6b343c1b920a1
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
bugs1435871
milestone64.0a1
backs out0f7592b662e27238b8ebc442fa755e5e891cdef9
039f6d65036e99c6ba885de5506a89e722c4e348
Backed out 2 changesets (bug 1435871) for multiple browser-chrome failures on payments. CLOSED TREE Backed out changeset 0f7592b662e2 (bug 1435871) Backed out changeset 039f6d65036e (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, "MasterPassword",
                                "resource://formautofill/MasterPassword.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 = await this._convertProfileBasicCardToPaymentMethodData(paymentCardGUID,
@@ -564,17 +562,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: {},
     };
@@ -674,33 +672,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,22 +10,18 @@
  * 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;
@@ -44,54 +40,20 @@ PaymentUIService.prototype = {
   QueryInterface: ChromeUtils.generateQI([Ci.nsIPaymentUIService]),
   DIALOG_URL: "chrome://payments/content/paymentDialogWrapper.xul",
   REQUEST_ID_PREFIX: "paymentRequest-",
 
   // 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() {
-      if (!container) {
-        // The dialog was closed by the DOM code before it was ready to be shown.
-        return;
-      }
-      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("tabModalBackground", "paymentDialogBackground");
-      // 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);
 
@@ -114,107 +76,76 @@ PaymentUIService.prototype = {
     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();
-    if (!dialogContainer.hidden) {
-      // If the container is no longer hidden then the background was added after
-      // `tabmodaldialogready` so remove it.
-      browser.parentElement.querySelector(".paymentDialogBackground").remove();
-
-      if (!browser.tabModalPromptBox || browser.tabModalPromptBox.listPrompts().length == 0) {
-        browser.removeAttribute("tabmodalPromptShowing");
-      }
-    }
+    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,25 @@ 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,
-      };
     },
   },
 
   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
@@ -246,80 +246,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(".paymentDialogBackground"),
-       "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");
-
-    ok(browser.hasAttribute("tabmodalPromptShowing"), "Check browser has @tabmodalPromptShowing");
-
-    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");
-      ok(!newBrowser.hasAttribute("tabmodalPromptShowing"),
-         "Check second browser doesn't have @tabmodalPromptShowing");
-    });
-
-    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");
-
-    await BrowserTestUtils.waitForCondition(() => !browser.hasAttribute("tabmodalPromptShowing"),
-                                            "Check @tabmodalPromptShowing was removed");
-  });
-});
--- 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 */
-.tabModalBackground,
 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 */
-.tabModalBackground,
 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 */
-.tabModalBackground,
 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 {