Bug 1595154, add a test for form fillin that uses a child iframe loaded in a separate process, r=MattN

Differential Revision: https://phabricator.services.mozilla.com/D52723

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Neil Deakin 2019-12-11 13:38:13 +00:00
Родитель c93677f198
Коммит a3b79c2f38
8 изменённых файлов: 287 добавлений и 25 удалений

Просмотреть файл

@ -2,6 +2,7 @@
head = head.js
support-files =
../fixtures/autocomplete_basic.html
../fixtures/autocomplete_iframe.html
../fixtures/autocomplete_simple_basic.html
[browser_autocomplete_footer.js]
@ -15,6 +16,7 @@ skip-if = (verify && (os == 'win' || os == 'mac'))
[browser_first_time_use_doorhanger.js]
skip-if = verify
[browser_manageAddressesDialog.js]
[browser_remoteiframe.js]
[browser_submission_in_private_mode.js]
[browser_update_doorhanger.js]
skip-if = true # bug 1426981 # Bug 1445538

Просмотреть файл

@ -3,20 +3,6 @@
const URL = BASE_URL + "autocomplete_basic.html";
const PRIVACY_PREF_URL = "about:preferences#privacy";
async function expectWarningText(browser, expectedText) {
const {
autoCompletePopup: { richlistbox: itemsBox },
} = browser;
const warningBox = itemsBox.querySelector(
".autocomplete-richlistitem:last-child"
)._warningTextBox;
await BrowserTestUtils.waitForCondition(() => {
return warningBox.textContent == expectedText;
}, `Waiting for expected warning text: ${expectedText}, Got ${warningBox.textContent}`);
ok(true, `Got expected warning text: ${expectedText}`);
}
add_task(async function setup_storage() {
await saveAddress(TEST_ADDRESS_2);
await saveAddress(TEST_ADDRESS_3);

Просмотреть файл

@ -0,0 +1,139 @@
/* eslint-disable mozilla/no-arbitrary-setTimeout */
"use strict";
const IFRAME_URL_PATH = BASE_URL + "autocomplete_iframe.html";
const PRIVACY_PREF_URL = "about:preferences#privacy";
// Start by adding a few addresses to storage.
add_task(async function setup_storage() {
await saveAddress(TEST_ADDRESS_2);
await saveAddress(TEST_ADDRESS_4);
await saveAddress(TEST_ADDRESS_5);
});
// Verify that form fillin works in a remote iframe, and that changing
// a field updates storage.
add_task(async function test_iframe_autocomplete() {
await SpecialPowers.pushPrefEnv({
set: [[CREDITCARDS_USED_STATUS_PREF, 0]],
});
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
IFRAME_URL_PATH,
true
);
let browser = tab.linkedBrowser;
let iframeBC = browser.browsingContext.getChildren()[1];
await openPopupForSubframe(browser, iframeBC, "#street-address");
// Highlight the first item in the list. We want to verify
// that the warning text is correct to ensure that the preview is
// performed properly.
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, iframeBC);
await expectWarningText(browser, "Autofills address");
// Highlight and select the second item in the list
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, iframeBC);
await expectWarningText(browser, "Also autofills organization, email");
EventUtils.synthesizeKey("VK_RETURN", {});
let promiseShown = BrowserTestUtils.waitForEvent(
PopupNotifications.panel,
"popupshown"
);
await new Promise(resolve => setTimeout(resolve, 1000));
let loadPromise = BrowserTestUtils.browserLoaded(browser, true);
await SpecialPowers.spawn(iframeBC, [], async function() {
Assert.equal(
content.document.getElementById("street-address").value,
"32 Vassar Street MIT Room 32-G524"
);
Assert.equal(content.document.getElementById("country").value, "US");
let org = content.document.getElementById("organization");
Assert.equal(org.value, "World Wide Web Consortium");
// Now, modify the organization.
org.setUserInput("Example Inc.");
await new Promise(resolve => content.setTimeout(resolve, 1000));
content.document.querySelector("input[type=submit]").click();
});
await loadPromise;
await promiseShown;
let onChanged = TestUtils.topicObserved("formautofill-storage-changed");
await clickDoorhangerButton(MAIN_BUTTON);
await onChanged;
// Check that the organization was updated properly.
let addresses = await getAddresses();
is(addresses.length, 3, "Still 1 address in storage");
is(
addresses[1].organization,
"Example Inc.",
"Verify the organization field"
);
// Fill in the details again and then clear the form from the dropdown.
await openPopupForSubframe(browser, iframeBC, "#street-address");
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, iframeBC);
EventUtils.synthesizeKey("VK_RETURN", {});
await new Promise(resolve => setTimeout(resolve, 1000));
// Open the dropdown and select the Clear Form item.
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, iframeBC);
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, iframeBC);
EventUtils.synthesizeKey("VK_RETURN", {});
await new Promise(resolve => setTimeout(resolve, 1000));
await SpecialPowers.spawn(iframeBC, [], async function() {
Assert.equal(content.document.getElementById("street-address").value, "");
Assert.equal(content.document.getElementById("country").value, "");
Assert.equal(content.document.getElementById("organization").value, "");
});
await BrowserTestUtils.removeTab(tab);
});
// Choose preferences from the autocomplete dropdown within an iframe.
add_task(async function test_iframe_autocomplete_preferences() {
await SpecialPowers.pushPrefEnv({
set: [[CREDITCARDS_USED_STATUS_PREF, 0]],
});
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
IFRAME_URL_PATH,
true
);
let browser = tab.linkedBrowser;
let iframeBC = browser.browsingContext.getChildren()[1];
await openPopupForSubframe(browser, iframeBC, "#organization");
await expectWarningText(browser, "Also autofills address, email");
const prefTabPromise = BrowserTestUtils.waitForNewTab(
gBrowser,
PRIVACY_PREF_URL
);
// Select the preferences item.
EventUtils.synthesizeKey("VK_DOWN", {});
EventUtils.synthesizeKey("VK_DOWN", {});
EventUtils.synthesizeKey("VK_RETURN", {});
info(`expecting tab: about:preferences#privacy opened`);
const prefTab = await prefTabPromise;
info(`expecting tab: about:preferences#privacy removed`);
BrowserTestUtils.removeTab(prefTab);
await BrowserTestUtils.removeTab(tab);
});

Просмотреть файл

@ -6,6 +6,7 @@ support-files =
../head.js
!/browser/extensions/formautofill/test/fixtures/autocomplete_basic.html
../../fixtures/autocomplete_creditcard_basic.html
../../fixtures/autocomplete_creditcard_iframe.html
head_cc.js
[browser_creditCard_doorhanger.js]

Просмотреть файл

@ -149,6 +149,61 @@ add_task(async function test_submit_untouched_creditCard_form() {
await removeAllRecords();
});
add_task(async function test_submit_untouched_creditCard_form_iframe() {
if (!OSKeyStoreTestUtils.canTestOSKeyStoreLogin()) {
todo(
OSKeyStoreTestUtils.canTestOSKeyStoreLogin(),
"Cannot test OS key store login on official builds."
);
return;
}
await SpecialPowers.pushPrefEnv({
set: [[CREDITCARDS_USED_STATUS_PREF, 0]],
});
await saveCreditCard(TEST_CREDIT_CARD_1);
let creditCards = await getCreditCards();
is(creditCards.length, 1, "1 credit card in storage");
let osKeyStoreLoginShown = OSKeyStoreTestUtils.waitForOSKeyStoreLogin(true);
let onUsed = TestUtils.topicObserved(
"formautofill-storage-changed",
(subject, data) => data == "notifyUsed"
);
await BrowserTestUtils.withNewTab(
{ gBrowser, url: CREDITCARD_FORM_IFRAME_URL },
async function(browser) {
let iframeBC = browser.browsingContext.getChildren()[0];
await openPopupForSubframe(browser, iframeBC, "form #cc-name");
EventUtils.synthesizeKey("VK_DOWN", {});
EventUtils.synthesizeKey("VK_RETURN", {});
await osKeyStoreLoginShown;
await SpecialPowers.spawn(iframeBC, [], async function() {
let form = content.document.getElementById("form");
// Wait 1000ms before submission to make sure the input value applied
await new Promise(resolve => content.setTimeout(resolve, 1000));
form.querySelector("input[type=submit]").click();
});
await sleep(1000);
is(PopupNotifications.panel.state, "closed", "Doorhanger is hidden");
}
);
await onUsed;
creditCards = await getCreditCards();
is(creditCards.length, 1, "Still 1 credit card");
is(creditCards[0].timesUsed, 1, "timesUsed field set to 1");
is(
SpecialPowers.getIntPref(CREDITCARDS_USED_STATUS_PREF),
3,
"User has used autofill"
);
SpecialPowers.clearUserPref(CREDITCARDS_USED_STATUS_PREF);
await removeAllRecords();
});
add_task(async function test_submit_changed_subset_creditCard_form() {
await SpecialPowers.pushPrefEnv({
set: [[CREDITCARDS_USED_STATUS_PREF, 0]],

Просмотреть файл

@ -1,15 +1,15 @@
/* exported MANAGE_ADDRESSES_DIALOG_URL, MANAGE_CREDIT_CARDS_DIALOG_URL, EDIT_ADDRESS_DIALOG_URL, EDIT_CREDIT_CARD_DIALOG_URL,
BASE_URL, TEST_ADDRESS_1, TEST_ADDRESS_2, TEST_ADDRESS_3, TEST_ADDRESS_4, TEST_ADDRESS_5, TEST_ADDRESS_CA_1, TEST_ADDRESS_DE_1,
TEST_ADDRESS_IE_1,
TEST_CREDIT_CARD_1, TEST_CREDIT_CARD_2, TEST_CREDIT_CARD_3, FORM_URL, CREDITCARD_FORM_URL,
TEST_CREDIT_CARD_1, TEST_CREDIT_CARD_2, TEST_CREDIT_CARD_3, FORM_URL, CREDITCARD_FORM_URL, CREDITCARD_FORM_IFRAME_URL
FTU_PREF, ENABLED_AUTOFILL_ADDRESSES_PREF, AUTOFILL_CREDITCARDS_AVAILABLE_PREF, ENABLED_AUTOFILL_CREDITCARDS_PREF,
SUPPORTED_COUNTRIES_PREF,
SYNC_USERNAME_PREF, SYNC_ADDRESSES_PREF, SYNC_CREDITCARDS_PREF, SYNC_CREDITCARDS_AVAILABLE_PREF, CREDITCARDS_USED_STATUS_PREF,
DEFAULT_REGION_PREF,
sleep, expectPopupOpen, openPopupOn, expectPopupClose, closePopup, clickDoorhangerButton,
getAddresses, saveAddress, removeAddresses, saveCreditCard,
sleep, expectPopupOpen, openPopupOn, openPopupForSubframe, expectPopupClose, closePopup, closePopupForSubframe,
clickDoorhangerButton, getAddresses, saveAddress, removeAddresses, saveCreditCard,
getDisplayedPopupItems, getDoorhangerCheckbox,
getNotification, getDoorhangerButton, removeAllRecords, testDialog */
getNotification, getDoorhangerButton, removeAllRecords, expectWarningText, testDialog */
"use strict";
@ -32,6 +32,10 @@ const CREDITCARD_FORM_URL =
"https://example.org" +
HTTP_TEST_PATH +
"creditCard/autocomplete_creditcard_basic.html";
const CREDITCARD_FORM_IFRAME_URL =
"https://example.org" +
HTTP_TEST_PATH +
"creditCard/autocomplete_creditcard_iframe.html";
const FTU_PREF = "extensions.formautofill.firstTimeUse";
const CREDITCARDS_USED_STATUS_PREF = "extensions.formautofill.creditCards.used";
@ -175,7 +179,7 @@ async function sleep(ms = 500) {
await new Promise(resolve => setTimeout(resolve, ms));
}
async function focusAndWaitForFieldsIdentified(browser, selector) {
async function focusAndWaitForFieldsIdentified(browserOrContext, selector) {
info("expecting the target input being focused and identified");
/* eslint no-shadow: ["error", { "allow": ["selector", "previouslyFocused", "previouslyIdentified"] }] */
@ -197,10 +201,10 @@ async function focusAndWaitForFieldsIdentified(browser, selector) {
FormAutofillParent.addMessageObserver(fieldsIdentifiedObserver);
});
const { previouslyFocused, previouslyIdentified } = await ContentTask.spawn(
browser,
{ selector },
async function({ selector }) {
const { previouslyFocused, previouslyIdentified } = await SpecialPowers.spawn(
browserOrContext,
[selector],
async function(selector) {
const { FormLikeFactory } = ChromeUtils.import(
"resource://gre/modules/FormLikeFactory.jsm"
);
@ -225,6 +229,20 @@ async function focusAndWaitForFieldsIdentified(browser, selector) {
info("!previouslyFocused");
}
// If a browsing context was supplied, focus its parent frame as well.
if (
browserOrContext instanceof BrowsingContext &&
browserOrContext.parent != browserOrContext
) {
await SpecialPowers.spawn(
browserOrContext.parent,
[browserOrContext],
async function(browsingContext) {
browsingContext.embedderElement.focus();
}
);
}
if (previouslyIdentified) {
info("previouslyIdentified");
return;
@ -236,7 +254,7 @@ async function focusAndWaitForFieldsIdentified(browser, selector) {
FormAutofillParent.removeMessageObserver(fieldsIdentifiedObserver);
await sleep();
await ContentTask.spawn(browser, {}, async function() {
await SpecialPowers.spawn(browserOrContext, [], async function() {
const { FormLikeFactory } = ChromeUtils.import(
"resource://gre/modules/FormLikeFactory.jsm"
);
@ -277,6 +295,14 @@ async function openPopupOn(browser, selector) {
await expectPopupOpen(browser);
}
async function openPopupForSubframe(browser, frameBrowsingContext, selector) {
await SimpleTest.promiseFocus(browser);
await focusAndWaitForFieldsIdentified(frameBrowsingContext, selector);
info("openPopupOn: before VK_DOWN");
await BrowserTestUtils.synthesizeKey("VK_DOWN", {}, frameBrowsingContext);
await expectPopupOpen(browser);
}
async function expectPopupClose(browser) {
await BrowserTestUtils.waitForCondition(
() => !browser.autoCompletePopup.popupOpen,
@ -285,7 +311,15 @@ async function expectPopupClose(browser) {
}
async function closePopup(browser) {
await ContentTask.spawn(browser, {}, async function() {
await SpecialPowers.spawn(browser, [], async function() {
content.document.activeElement.blur();
});
await expectPopupClose(browser);
}
async function closePopupForSubframe(browser, frameBrowsingContext) {
await SpecialPowers.spawn(frameBrowsingContext, [], async function() {
content.document.activeElement.blur();
});
@ -415,6 +449,26 @@ async function waitForFocusAndFormReady(win) {
]);
}
// Verify that the warning in the autocomplete popup has the expected text.
async function expectWarningText(browser, expectedText) {
const {
autoCompletePopup: { richlistbox: itemsBox },
} = browser;
let warningBox = itemsBox.querySelector(
".autocomplete-richlistitem:last-child"
);
while (warningBox.collapsed) {
warningBox = warningBox.previousSibling;
}
warningBox = warningBox._warningTextBox;
await BrowserTestUtils.waitForCondition(() => {
return warningBox.textContent == expectedText;
}, `Waiting for expected warning text: ${expectedText}, Got ${warningBox.textContent}`);
ok(true, `Got expected warning text: ${expectedText}`);
}
async function testDialog(url, testFn, arg = undefined) {
// Skip this step for test cards that lack an encrypted
// number since they will fail to decrypt.

Просмотреть файл

@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Form Autofill Credit Card With Remote IFrame Demo Page</title>
</head>
<body>
<iframe src="https://test1.example.com:443/browser/browser/extensions/formautofill/test/browser/creditCard/autocomplete_creditcard_basic.html" width="400" height="400">
</iframe>
</body>
</html>

Просмотреть файл

@ -0,0 +1,13 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Form Autofill With Remote IFrame Demo Page</title>
</head>
<body>
<iframe id="unused" src="data:text/html,<body>Just here to ensure code doesn't always pick the first child iframe.</body>"></iframe>
<iframe src="https://test1.example.com:443/browser/browser/extensions/formautofill/test/browser/autocomplete_basic.html" width="400" height="400">
</iframe>
</body>
</html>