diff --git a/dom/ipc/LoginDetectionService.cpp b/dom/ipc/LoginDetectionService.cpp index 9a55a5e30752..28342e430cc6 100644 --- a/dom/ipc/LoginDetectionService.cpp +++ b/dom/ipc/LoginDetectionService.cpp @@ -46,6 +46,7 @@ already_AddRefed LoginDetectionService::GetSingleton() { return do_AddRef(gLoginDetectionService); } +LoginDetectionService::LoginDetectionService() : mIsLoginsLoaded(false) {} LoginDetectionService::~LoginDetectionService() { UnregisterObserver(); } void LoginDetectionService::MaybeStartMonitoring() { @@ -111,6 +112,17 @@ NS_IMETHODIMP LoginDetectionService::Init() { return NS_OK; } +NS_IMETHODIMP LoginDetectionService::IsLoginsLoaded(bool* aResult) { + if (IsIsolateHighValueSiteEnabled()) { + *aResult = mIsLoginsLoaded; + } else { + // When the feature is disabled, just returns true so testcases don't + // block on waiting for us to load logins. + *aResult = true; + } + return NS_OK; +} + /////////////////////////////////////////////////////////////////////////////// // nsILoginSearchObserver implementation NS_IMETHODIMP @@ -125,6 +137,7 @@ LoginDetectionService::OnSearchComplete( mozilla::dom::kHighValueHasSavedLoginPermission); } + mIsLoginsLoaded = true; return NS_OK; } diff --git a/dom/ipc/LoginDetectionService.h b/dom/ipc/LoginDetectionService.h index 208cea023d45..b0fd17085533 100644 --- a/dom/ipc/LoginDetectionService.h +++ b/dom/ipc/LoginDetectionService.h @@ -40,7 +40,7 @@ class LoginDetectionService final : public nsILoginDetectionService, void MaybeStartMonitoring(); private: - LoginDetectionService() = default; + LoginDetectionService(); virtual ~LoginDetectionService(); // Fetch saved logins from the password manager. @@ -50,6 +50,9 @@ class LoginDetectionService final : public nsILoginDetectionService, void UnregisterObserver(); nsCOMPtr mObs; + + // Used by testcase to make sure logins are fetched. + bool mIsLoginsLoaded; }; } // namespace mozilla::dom diff --git a/dom/ipc/nsILoginDetectionService.idl b/dom/ipc/nsILoginDetectionService.idl index 66912189ea83..a0b1ae90a7d8 100644 --- a/dom/ipc/nsILoginDetectionService.idl +++ b/dom/ipc/nsILoginDetectionService.idl @@ -13,4 +13,10 @@ interface nsILoginDetectionService : nsISupports * called to initialize the login detection service. */ void init(); + + /** + * Returns true if we have loaded logins from the password manager. + * This is now used by testcase only. + */ + bool isLoginsLoaded(); }; diff --git a/dom/ipc/tests/browser_web_process_isolation.js b/dom/ipc/tests/browser_web_process_isolation.js index f1e09396fdab..5ffc2cb12a05 100644 --- a/dom/ipc/tests/browser_web_process_isolation.js +++ b/dom/ipc/tests/browser_web_process_isolation.js @@ -142,86 +142,164 @@ function mkTestPage({ }; } +const heuristics = [ + { + name: "coop", + setup_com: async expected => { + // Set the COOP header, and load + await testTreeRemoteTypes( + "com_set_coop", + mkTestPage({ + topOrigin: COM_ORIGIN, + topHeaders: { "Cross-Origin-Opener-Policy": "same-origin" }, + comRemoteType: expected.com_high, + orgRemoteType: expected.org_normal, + mozRemoteType: expected.moz_normal, + }) + ); + }, + run_extra_test: async expected => { + // Load with both the COOP and COEP headers set. + await testTreeRemoteTypes( + "com_coop_coep", + mkTestPage({ + topOrigin: COM_ORIGIN, + topHeaders: { + "Cross-Origin-Opener-Policy": "same-origin", + "Cross-Origin-Embedder-Policy": "require-corp", + }, + frameHeaders: { + "Cross-Origin-Embedder-Policy": "require-corp", + "Cross-Origin-Resource-Policy": "cross-origin", + }, + comRemoteType: expected.com_coop_coep, + orgRemoteType: expected.org_coop_coep, + mozRemoteType: expected.moz_coop_coep, + }) + ); + }, + }, + { + name: "hasSavedLogin", + setup_com: async expected => { + // add .com to the password manager + let LoginInfo = new Components.Constructor( + "@mozilla.org/login-manager/loginInfo;1", + Ci.nsILoginInfo, + "init" + ); + Services.logins.addLogin( + new LoginInfo(COM_ORIGIN, "", null, "username", "password", "", "") + ); + + // Init login detection service to trigger fetching logins + let loginDetection = Cc[ + "@mozilla.org/login-detection-service;1" + ].createInstance(Ci.nsILoginDetectionService); + loginDetection.init(); + + await TestUtils.waitForCondition(() => { + let x = loginDetection.isLoginsLoaded(); + return x; + }, "waiting for loading logins from the password manager"); + }, + }, + { + name: "isLoggedIn", + setup_com: async expected => { + let p = new Promise(resolve => { + Services.obs.addObserver(function obs() { + Services.obs.removeObserver( + obs, + "passwordmgr-form-submission-detected" + ); + resolve(); + }, "passwordmgr-form-submission-detected"); + }); + + const TEST_URL = documentURL( + COM_ORIGIN, + {}, + `
+ + + +
` + ); + + // submit the form to simulate the login behavior + await BrowserTestUtils.withNewTab(TEST_URL, async browser => { + await SpecialPowers.spawn(browser, [], async () => { + content.document.querySelector("form").submit(); + }); + }); + await p; + }, + }, +]; + async function do_tests(expected) { - // Clear all site-specific data, as we don't want to have any high-value site - // permissions from any previous iterations. - await new Promise(resolve => - Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, resolve) - ); + for (let heuristic of heuristics) { + info(`Starting ${heuristic.name} test`); + // Clear all site-specific data, as we don't want to have any high-value site + // permissions from any previous iterations. + await new Promise(resolve => + Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, resolve) + ); - // Loads for basic URLs with no special headers set. - await testTreeRemoteTypes( - "basic_com", - mkTestPage({ - topOrigin: COM_ORIGIN, - comRemoteType: expected.com_normal, - orgRemoteType: expected.org_normal, - mozRemoteType: expected.moz_normal, - }) - ); + // Loads for basic URLs with no special headers set. + await testTreeRemoteTypes( + "basic_com", + mkTestPage({ + topOrigin: COM_ORIGIN, + comRemoteType: expected.com_normal, + orgRemoteType: expected.org_normal, + mozRemoteType: expected.moz_normal, + }) + ); - await testTreeRemoteTypes( - "basic_org", - mkTestPage({ - topOrigin: ORG_ORIGIN, - comRemoteType: expected.com_normal, - orgRemoteType: expected.org_normal, - mozRemoteType: expected.moz_normal, - }) - ); + await testTreeRemoteTypes( + "basic_org", + mkTestPage({ + topOrigin: ORG_ORIGIN, + comRemoteType: expected.com_normal, + orgRemoteType: expected.org_normal, + mozRemoteType: expected.moz_normal, + }) + ); - // Set the COOP header, and load - await testTreeRemoteTypes( - "com_set_coop", - mkTestPage({ - topOrigin: COM_ORIGIN, - topHeaders: { "Cross-Origin-Opener-Policy": "same-origin" }, - comRemoteType: expected.com_high, - orgRemoteType: expected.org_normal, - mozRemoteType: expected.moz_normal, - }) - ); + info(`Setting up ${heuristic.name} test`); + await heuristic.setup_com(expected); - // Load again after setting the COOP header - await testTreeRemoteTypes( - "com_after_coop", - mkTestPage({ - topOrigin: COM_ORIGIN, - comRemoteType: expected.com_high, - orgRemoteType: expected.org_normal, - mozRemoteType: expected.moz_normal, - }) - ); + // Load again after the heuristic is triggered + info(`Running ${heuristic.name} tests after setup`); + await testTreeRemoteTypes( + `com_after_${heuristic.name}`, + mkTestPage({ + topOrigin: COM_ORIGIN, + comRemoteType: expected.com_high, + orgRemoteType: expected.org_normal, + mozRemoteType: expected.moz_normal, + }) + ); - // Load again after setting the COOP header, with a .org toplevel - await testTreeRemoteTypes( - "org_after_coop", - mkTestPage({ - topOrigin: ORG_ORIGIN, - comRemoteType: expected.com_high, - orgRemoteType: expected.org_normal, - mozRemoteType: expected.moz_normal, - }) - ); + // Load again with a .org toplevel + await testTreeRemoteTypes( + `org_after_${heuristic.name}`, + mkTestPage({ + topOrigin: ORG_ORIGIN, + comRemoteType: expected.com_high, + orgRemoteType: expected.org_normal, + mozRemoteType: expected.moz_normal, + }) + ); - // Load with both the COOP and COEP headers set. - await testTreeRemoteTypes( - "com_coop_coep", - mkTestPage({ - topOrigin: COM_ORIGIN, - topHeaders: { - "Cross-Origin-Opener-Policy": "same-origin", - "Cross-Origin-Embedder-Policy": "require-corp", - }, - frameHeaders: { - "Cross-Origin-Embedder-Policy": "require-corp", - "Cross-Origin-Resource-Policy": "cross-origin", - }, - comRemoteType: expected.com_coop_coep, - orgRemoteType: expected.org_coop_coep, - mozRemoteType: expected.moz_coop_coep, - }) - ); + // Run heuristic dependent tests + if (heuristic.run_extra_test) { + info(`Running extra tests for ${heuristic.name}`); + await heuristic.run_extra_test(expected); + } + } } add_task(async function test_isolate_nothing() {