зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1567175, add a test that verifies that a cross process iframe with a password field saves the password on submit and page navigation, r=MattN
Differential Revision: https://phabricator.services.mozilla.com/D49704 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
fc3aa270bf
Коммит
ca34a940cf
|
@ -247,7 +247,9 @@ class LoginManagerParent extends JSWindowActorParent {
|
|||
formid: data.formid,
|
||||
});
|
||||
if (gListenerForTests) {
|
||||
gListenerForTests("FormProcessed", {});
|
||||
gListenerForTests("FormProcessed", {
|
||||
browsingContext: this.browsingContext,
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -32,6 +32,10 @@ support-files =
|
|||
subtst_notifications_9.html
|
||||
subtst_notifications_10.html
|
||||
subtst_notifications_change_p.html
|
||||
[browser_capture_doorhanger_crossframe.js]
|
||||
support-files =
|
||||
form_crossframe.html
|
||||
form_crossframe_inner.html
|
||||
[browser_capture_doorhanger_empty_password.js]
|
||||
skip-if = true # Bug 1272849
|
||||
[browser_capture_doorhanger_httpsUpgrade.js]
|
||||
|
@ -93,3 +97,4 @@ support-files =
|
|||
subtst_privbrowsing_1.html
|
||||
form_password_change.html
|
||||
[browser_promptToChangePassword.js]
|
||||
|
||||
|
|
|
@ -0,0 +1,187 @@
|
|||
const OUTER_URL =
|
||||
"https://test1.example.com:443" + DIRECTORY_PATH + "form_crossframe.html";
|
||||
|
||||
async function acceptPasswordSave() {
|
||||
let notif = await getCaptureDoorhangerThatMayOpen("password-save");
|
||||
let promiseNewSavedPassword = TestUtils.topicObserved(
|
||||
"LoginStats:NewSavedPassword",
|
||||
(subject, data) => subject == gBrowser.selectedBrowser
|
||||
);
|
||||
clickDoorhangerButton(notif, REMEMBER_BUTTON);
|
||||
await promiseNewSavedPassword;
|
||||
}
|
||||
|
||||
function checkFormFields(browsingContext, prefix, username, password) {
|
||||
return SpecialPowers.spawn(
|
||||
browsingContext,
|
||||
[prefix, username, password],
|
||||
(formPrefix, expectedUsername, expectedPassword) => {
|
||||
let doc = content.document;
|
||||
Assert.equal(
|
||||
doc.getElementById(formPrefix + "-username").value,
|
||||
expectedUsername,
|
||||
"username matches"
|
||||
);
|
||||
Assert.equal(
|
||||
doc.getElementById(formPrefix + "-password").value,
|
||||
expectedPassword,
|
||||
"password matches"
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function listenForNotifications(count) {
|
||||
return new Promise(resolve => {
|
||||
let notifications = [];
|
||||
LoginManagerParent.setListenerForTests((msg, data) => {
|
||||
if (msg == "FormProcessed") {
|
||||
notifications.push("FormProcessed: " + data.browsingContext.id);
|
||||
} else if (msg == "FormSubmit") {
|
||||
notifications.push("FormSubmit: " + data.usernameField.name);
|
||||
}
|
||||
if (notifications.length == count) {
|
||||
resolve(notifications);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
async function verifyNotifications(notifyPromise, expected) {
|
||||
let actual = await notifyPromise;
|
||||
|
||||
is(actual.length, expected.length, "Extra notification(s) sent");
|
||||
let expectedItem;
|
||||
while ((expectedItem = expected.pop())) {
|
||||
let index = actual.indexOf(expectedItem);
|
||||
if (index >= 0) {
|
||||
actual.splice(index, 1);
|
||||
} else {
|
||||
ok(false, "Expected notification '" + expectedItem + "' not sent");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* In this test, a frame is loaded with a document that contains a username
|
||||
* and password field. This frame also contains another child iframe that
|
||||
* itself contains a username and password field. This inner frame is loaded
|
||||
* from a different domain than the first.
|
||||
*
|
||||
* locationMode should be false to submit forms, or true to click a button
|
||||
* which changes the location instead. The latter should still save the
|
||||
* username and password.
|
||||
*/
|
||||
async function submitSomeCrossSiteFrames(locationMode) {
|
||||
info("Check with location mode " + locationMode);
|
||||
let notifyPromise = listenForNotifications(2);
|
||||
|
||||
let firsttab = await BrowserTestUtils.openNewForegroundTab(
|
||||
gBrowser,
|
||||
OUTER_URL
|
||||
);
|
||||
|
||||
let outerFrameBC = firsttab.linkedBrowser.browsingContext;
|
||||
let innerFrameBC = outerFrameBC.getChildren()[0];
|
||||
|
||||
await verifyNotifications(notifyPromise, [
|
||||
"FormProcessed: " + outerFrameBC.id,
|
||||
"FormProcessed: " + innerFrameBC.id,
|
||||
]);
|
||||
|
||||
// Fill in the username and password for both the outer and inner frame
|
||||
// and submit the inner frame.
|
||||
notifyPromise = listenForNotifications(1);
|
||||
info("submit page after changing inner form");
|
||||
|
||||
await SpecialPowers.spawn(outerFrameBC, [], () => {
|
||||
let doc = content.document;
|
||||
doc.getElementById("outer-username").value = "outer";
|
||||
doc.getElementById("outer-password").value = "outerpass";
|
||||
});
|
||||
|
||||
await SpecialPowers.spawn(innerFrameBC, [locationMode], doClick => {
|
||||
let doc = content.document;
|
||||
doc.getElementById("inner-username").value = "inner";
|
||||
doc.getElementById("inner-password").value = "innerpass";
|
||||
if (doClick) {
|
||||
doc.getElementById("inner-gobutton").click();
|
||||
} else {
|
||||
doc.getElementById("inner-form").submit();
|
||||
}
|
||||
});
|
||||
|
||||
await acceptPasswordSave();
|
||||
|
||||
await verifyNotifications(notifyPromise, ["FormSubmit: username"]);
|
||||
|
||||
// Next, open a second tab with the same page in it to verify that the data gets filled properly.
|
||||
notifyPromise = listenForNotifications(2);
|
||||
let secondtab = await BrowserTestUtils.openNewForegroundTab(
|
||||
gBrowser,
|
||||
OUTER_URL
|
||||
);
|
||||
|
||||
let outerFrameBC2 = secondtab.linkedBrowser.browsingContext;
|
||||
let innerFrameBC2 = outerFrameBC2.getChildren()[0];
|
||||
await verifyNotifications(notifyPromise, [
|
||||
"FormProcessed: " + outerFrameBC2.id,
|
||||
"FormProcessed: " + innerFrameBC2.id,
|
||||
]);
|
||||
|
||||
await checkFormFields(outerFrameBC2, "outer", "", "");
|
||||
await checkFormFields(innerFrameBC2, "inner", "inner", "innerpass");
|
||||
|
||||
// Next, change the username and password fields in the outer frame and submit.
|
||||
notifyPromise = listenForNotifications(1);
|
||||
info("submit page after changing outer form");
|
||||
|
||||
await SpecialPowers.spawn(outerFrameBC2, [locationMode], doClick => {
|
||||
let doc = content.document;
|
||||
doc.getElementById("outer-username").value = "outer2";
|
||||
doc.getElementById("outer-password").value = "outerpass2";
|
||||
if (doClick) {
|
||||
doc.getElementById("outer-gobutton").click();
|
||||
} else {
|
||||
doc.getElementById("outer-form").submit();
|
||||
}
|
||||
|
||||
doc.getElementById("outer-form").submit();
|
||||
});
|
||||
|
||||
await acceptPasswordSave();
|
||||
await verifyNotifications(notifyPromise, ["FormSubmit: outer-username"]);
|
||||
|
||||
// Finally, open a third tab with the same page in it to verify that the data gets filled properly.
|
||||
notifyPromise = listenForNotifications(2);
|
||||
let thirdtab = await BrowserTestUtils.openNewForegroundTab(
|
||||
gBrowser,
|
||||
OUTER_URL
|
||||
);
|
||||
|
||||
let outerFrameBC3 = thirdtab.linkedBrowser.browsingContext;
|
||||
let innerFrameBC3 = outerFrameBC3.getChildren()[0];
|
||||
await verifyNotifications(notifyPromise, [
|
||||
"FormProcessed: " + outerFrameBC3.id,
|
||||
"FormProcessed: " + innerFrameBC3.id,
|
||||
]);
|
||||
|
||||
await checkFormFields(outerFrameBC3, "outer", "outer2", "outerpass2");
|
||||
await checkFormFields(innerFrameBC3, "inner", "inner", "innerpass");
|
||||
|
||||
LoginManagerParent.setListenerForTests(null);
|
||||
|
||||
await BrowserTestUtils.removeTab(firsttab);
|
||||
await BrowserTestUtils.removeTab(secondtab);
|
||||
await BrowserTestUtils.removeTab(thirdtab);
|
||||
|
||||
LoginTestUtils.clearData();
|
||||
}
|
||||
|
||||
add_task(async function cross_site_frames_submit() {
|
||||
await submitSomeCrossSiteFrames(false);
|
||||
});
|
||||
|
||||
add_task(async function cross_site_frames_changelocation() {
|
||||
await submitSomeCrossSiteFrames(true);
|
||||
});
|
|
@ -0,0 +1,13 @@
|
|||
<html><body>
|
||||
|
||||
<button onclick="window.location = 'about:blank'">Next</button>
|
||||
<iframe src="https://test2.example.org:443/browser/toolkit/components/passwordmgr/test/browser/form_crossframe_inner.html"
|
||||
width="300" height="300"></iframe>
|
||||
<form id="outer-form" action="formsubmit.sjs">
|
||||
<input id="outer-username" name="outer-username">
|
||||
<input id="outer-password" name="outer-password" type="password">
|
||||
<input id="outer-submit" type="submit">
|
||||
<button id="outer-gobutton" onclick="this.location = 'about:blank'">Go</button>
|
||||
</form>
|
||||
|
||||
</body></html>
|
|
@ -0,0 +1,13 @@
|
|||
<!DOCTYPE html><html><head><meta charset="utf-8"></head><body>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
|
||||
<!-- Form for use inside a frame. -->
|
||||
<form id="inner-form" action="formsubmit.sjs">
|
||||
<input id="inner-username" name="username">
|
||||
<input id="inner-password" name="password" type="password">
|
||||
<input id="inner-submit" type="submit">
|
||||
</form>
|
||||
<button id="inner-gobutton" onclick="document.location = 'about:blank'">Go</button>
|
||||
|
||||
</body></html>
|
Загрузка…
Ссылка в новой задаче