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
--- 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.