Bug 1330822 - Remove CPOWs from browser_context_menu_iframe.js. r=Gijs
authorBlake Kaplan <mrbkap@gmail.com>
Fri, 11 Nov 2016 15:07:18 -0800
changeset 374994 21fd0eb4fa62eab86314598734eb2e2bff08c939
parent 374993 79079769f4c9f345a8f7fdc6f878247135280e2c
child 374995 2e3c8dc20f2c3bf3567dbfb4f9123db047810217
push id6996
push userjlorenzo@mozilla.com
push dateMon, 06 Mar 2017 20:48:21 +0000
treeherdermozilla-beta@d89512dab048 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersGijs
bugs1330822
milestone53.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 1330822 - Remove CPOWs from browser_context_menu_iframe.js. r=Gijs This was tricky because synthesizeMouse would compute the incorrect coordinates if the requested event target was in a sub-frame. With this patch, we deal correctly with sub-frames. MozReview-Commit-ID: KpUKxFXKMrl
testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
testing/mochitest/tests/SimpleTest/AsyncUtilsContent.js
toolkit/components/passwordmgr/test/browser/browser_context_menu_iframe.js
--- a/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
+++ b/testing/mochitest/BrowserTestUtils/BrowserTestUtils.jsm
@@ -733,21 +733,25 @@ this.BrowserTestUtils = {
    * @param {Browser} browser
    *        Browser element, must not be null
    *
    * @returns {Promise}
    * @resolves True if the mouse event was cancelled.
    */
   synthesizeMouse(target, offsetX, offsetY, event, browser)
   {
-    return new Promise(resolve => {
+    return new Promise((resolve, reject) => {
       let mm = browser.messageManager;
       mm.addMessageListener("Test:SynthesizeMouseDone", function mouseMsg(message) {
         mm.removeMessageListener("Test:SynthesizeMouseDone", mouseMsg);
-        resolve(message.data.defaultPrevented);
+        if (message.data.hasOwnProperty("defaultPrevented")) {
+          resolve(message.data.defaultPrevented);
+        } else {
+          reject(new Error(message.data.error));
+        }
       });
 
       let cpowObject = null;
       let targetFn = null;
       if (typeof target == "function") {
         targetFn = target.toString();
         target = null;
       } else if (typeof target != "string") {
--- a/testing/mochitest/tests/SimpleTest/AsyncUtilsContent.js
+++ b/testing/mochitest/tests/SimpleTest/AsyncUtilsContent.js
@@ -32,16 +32,37 @@ addMessageListener("Test:SynthesizeMouse
   }
   else {
     target = message.objects.object;
   }
 
   let left = data.x;
   let top = data.y;
   if (target) {
+    if (target.ownerDocument !== content.document) {
+      // Account for nodes found in iframes.
+      let cur = target;
+      do {
+        let frame = cur.ownerDocument.defaultView.frameElement;
+        let rect = frame.getBoundingClientRect();
+
+        left += rect.left;
+        top += rect.top;
+
+        cur = frame;
+      } while (cur && cur.ownerDocument !== content.document);
+
+      // node must be in this document tree.
+      if (!cur) {
+        sendAsyncMessage("Test:SynthesizeMouseDone",
+                         { error: "target must be in the main document tree" });
+        return;
+      }
+    }
+
     let rect = target.getBoundingClientRect();
     left += rect.left;
     top += rect.top;
 
     if (data.event.centered) {
       left += rect.width / 2;
       top += rect.height / 2;
     }
--- a/toolkit/components/passwordmgr/test/browser/browser_context_menu_iframe.js
+++ b/toolkit/components/passwordmgr/test/browser/browser_context_menu_iframe.js
@@ -28,60 +28,68 @@ add_task(function* test_initialize() {
  * Check if the password field is correctly filled when it's in an iframe.
  */
 add_task(function* test_context_menu_iframe_fill() {
   Services.prefs.setBoolPref("signon.schemeUpgrades", true);
   yield BrowserTestUtils.withNewTab({
     gBrowser,
     url: TEST_HOSTNAME + IFRAME_PAGE_PATH
   }, function* (browser) {
-    let iframe = browser.contentWindow.document.getElementById("test-iframe");
-    let passwordInput = iframe.contentDocument.getElementById("form-basic-password");
+    function getPasswordInput() {
+      let frame = content.document.getElementById("test-iframe");
+      return frame.contentDocument.getElementById("form-basic-password");
+    }
 
     let contextMenuShownPromise = BrowserTestUtils.waitForEvent(window, "popupshown");
     let eventDetails = {type: "contextmenu", button: 2};
 
     // To click at the right point we have to take into account the iframe offset.
-    let iframeRect = iframe.getBoundingClientRect();
-    let inputRect = passwordInput.getBoundingClientRect();
-    let clickPos = {
-      offsetX: iframeRect.left + inputRect.width / 2,
-      offsetY: iframeRect.top + inputRect.height / 2,
-    };
-
     // Synthesize a right mouse click over the password input element.
-    BrowserTestUtils.synthesizeMouse(passwordInput, clickPos.offsetX, clickPos.offsetY, eventDetails, browser);
+    BrowserTestUtils.synthesizeMouseAtCenter(getPasswordInput, eventDetails, browser);
     yield contextMenuShownPromise;
 
     // Synthesize a mouse click over the fill login menu header.
     let popupHeader = document.getElementById("fill-login");
     let popupShownPromise = BrowserTestUtils.waitForEvent(popupHeader, "popupshown");
     EventUtils.synthesizeMouseAtCenter(popupHeader, {});
     yield popupShownPromise;
 
     let popupMenu = document.getElementById("fill-login-popup");
 
     // Stores the original value of username
-    let usernameInput = iframe.contentDocument.getElementById("form-basic-username");
-    let usernameOriginalValue = usernameInput.value;
+    function promiseFrameInputValue(name) {
+      return ContentTask.spawn(browser, name, function(inputname) {
+        let iframe = content.document.getElementById("test-iframe");
+        let input = iframe.contentDocument.getElementById(inputname);
+        return input.value;
+      });
+    }
+    let usernameOriginalValue = yield promiseFrameInputValue("form-basic-username");
 
     // Execute the command of the first login menuitem found at the context menu.
+    let passwordChangedPromise = ContentTask.spawn(browser, null, function* () {
+      let frame = content.document.getElementById("test-iframe");
+      let passwordInput = frame.contentDocument.getElementById("form-basic-password");
+      yield ContentTaskUtils.waitForEvent(passwordInput, "input");
+    });
+
     let firstLoginItem = popupMenu.getElementsByClassName("context-login-item")[0];
     firstLoginItem.doCommand();
 
-    yield BrowserTestUtils.waitForEvent(passwordInput, "input", "Password input value changed");
+    yield passwordChangedPromise;
 
     // Find the used login by it's username.
     let login = getLoginFromUsername(firstLoginItem.label);
-
-    Assert.equal(login.password, passwordInput.value, "Password filled and correct.");
+    let passwordValue = yield promiseFrameInputValue("form-basic-password");
+    is(login.password, passwordValue, "Password filled and correct.");
 
-    Assert.equal(usernameOriginalValue,
-                 usernameInput.value,
-                 "Username value was not changed.");
+    let usernameNewValue = yield promiseFrameInputValue("form-basic-username");
+    is(usernameOriginalValue,
+       usernameNewValue,
+       "Username value was not changed.");
 
     let contextMenu = document.getElementById("contentAreaContextMenu");
     contextMenu.hidePopup();
   });
 });
 
 /**
  * Search for a login by it's username.