Bug 1543786 - Ensure that we revoke a top frame's storage access when it is navigated away; r=baku

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Ehsan Akhgari 2019-04-17 15:01:53 +00:00
Родитель b3529e64b7
Коммит 0ad9b25d34
7 изменённых файлов: 124 добавлений и 5 удалений

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

@ -2669,8 +2669,8 @@ nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) {
RecomputeCanExecuteScripts(); RecomputeCanExecuteScripts();
// Inform windows when they're being removed from their parent. // Inform windows when they're being removed from their parent.
if (!aParent && mScriptGlobal) { if (!aParent) {
mScriptGlobal->ParentWindowChanged(); MaybeClearStorageAccessFlag();
} }
NS_ASSERTION(mInheritPrivateBrowsingId || wasPrivate == UsePrivateBrowsing(), NS_ASSERTION(mInheritPrivateBrowsingId || wasPrivate == UsePrivateBrowsing(),
@ -2679,6 +2679,22 @@ nsresult nsDocShell::SetDocLoaderParent(nsDocLoader* aParent) {
return NS_OK; return NS_OK;
} }
void nsDocShell::MaybeClearStorageAccessFlag() {
if (mScriptGlobal) {
// Tell our window that the parent has now changed.
mScriptGlobal->ParentWindowChanged();
// Tell all of our children about the change recursively as well.
nsTObserverArray<nsDocLoader*>::ForwardIterator iter(mChildList);
while (iter.HasMore()) {
nsCOMPtr<nsIDocShell> child = do_QueryObject(iter.GetNext());
if (child) {
static_cast<nsDocShell*>(child.get())->MaybeClearStorageAccessFlag();
}
}
}
}
NS_IMETHODIMP NS_IMETHODIMP
nsDocShell::GetSameTypeParent(nsIDocShellTreeItem** aParent) { nsDocShell::GetSameTypeParent(nsIDocShellTreeItem** aParent) {
NS_ENSURE_ARG_POINTER(aParent); NS_ENSURE_ARG_POINTER(aParent);

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

@ -401,6 +401,9 @@ class nsDocShell final : public nsDocLoader,
nsresult InternalLoad(nsDocShellLoadState* aLoadState, nsresult InternalLoad(nsDocShellLoadState* aLoadState,
nsIDocShell** aDocShell, nsIRequest** aRequest); nsIDocShell** aDocShell, nsIRequest** aRequest);
// Clear the document's storage access flag if needed.
void MaybeClearStorageAccessFlag();
private: // member functions private: // member functions
friend class nsDSURIContentListener; friend class nsDSURIContentListener;
friend class FramingChecker; friend class FramingChecker;

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

@ -577,6 +577,12 @@ nsresult nsFrameLoader::ReallyStartLoadingInternal() {
return NS_OK; return NS_OK;
} }
if (GetDocShell()) {
// If we already have a docshell, ensure that the docshell's storage access
// flag is cleared.
GetDocShell()->MaybeClearStorageAccessFlag();
}
nsresult rv = MaybeCreateDocShell(); nsresult rv = MaybeCreateDocShell();
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
return rv; return rv;
@ -1108,6 +1114,8 @@ void nsFrameLoader::Hide() {
return; return;
} }
GetDocShell()->MaybeClearStorageAccessFlag();
nsCOMPtr<nsIContentViewer> contentViewer; nsCOMPtr<nsIContentViewer> contentViewer;
GetDocShell()->GetContentViewer(getter_AddRefs(contentViewer)); GetDocShell()->GetContentViewer(getter_AddRefs(contentViewer));
if (contentViewer) contentViewer->SetSticky(false); if (contentViewer) contentViewer->SetSticky(false);

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

@ -1052,14 +1052,19 @@ mozilla::ipc::IPCResult TabChild::RecvLoadURL(const nsCString& aURI,
nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP | nsIWebNavigation::LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP |
nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL; nsIWebNavigation::LOAD_FLAGS_DISALLOW_INHERIT_PRINCIPAL;
nsresult rv = nsIWebNavigation* webNav = WebNavigation();
WebNavigation()->LoadURI(NS_ConvertUTF8toUTF16(aURI), loadURIOptions); nsresult rv = webNav->LoadURI(NS_ConvertUTF8toUTF16(aURI), loadURIOptions);
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
NS_WARNING( NS_WARNING(
"WebNavigation()->LoadURI failed. Eating exception, what else can I " "WebNavigation()->LoadURI failed. Eating exception, what else can I "
"do?"); "do?");
} }
nsCOMPtr<nsIDocShell> docShell = do_GetInterface(WebNavigation());
if (docShell) {
nsDocShell::Cast(docShell)->MaybeClearStorageAccessFlag();
}
CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::URL, aURI); CrashReporter::AnnotateCrashReport(CrashReporter::Annotation::URL, aURI);
return IPC_OK(); return IPC_OK();

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

@ -335,7 +335,7 @@ this.AntiTracking = {
} else { } else {
thirdPartyPage = TEST_3RD_PARTY_PAGE; thirdPartyPage = TEST_3RD_PARTY_PAGE;
} }
await ContentTask.spawn(browser, let id = await ContentTask.spawn(browser,
{ page: thirdPartyPage, { page: thirdPartyPage,
nextPage: TEST_4TH_PARTY_PAGE, nextPage: TEST_4TH_PARTY_PAGE,
callback: options.callback.toString(), callback: options.callback.toString(),
@ -420,14 +420,57 @@ this.AntiTracking = {
ifr.src = obj.nextPage; ifr.src = obj.nextPage;
}); });
case "navigate-topframe":
// pass-through
break; break;
default: default:
ok(false, "Unexpected accessRemoval code passed: " + obj.accessRemoval); ok(false, "Unexpected accessRemoval code passed: " + obj.accessRemoval);
break; break;
} }
} }
return id;
}); });
if (doAccessRemovalChecks &&
options.accessRemoval == "navigate-topframe") {
await BrowserTestUtils.loadURI(browser, TEST_4TH_PARTY_PAGE);
await BrowserTestUtils.browserLoaded(browser);
let pageshow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
gBrowser.goBack();
await pageshow;
await ContentTask.spawn(browser,
{ id,
callbackAfterRemoval: options.callbackAfterRemoval ?
options.callbackAfterRemoval.toString() : null,
},
async function(obj) {
let ifr = content.document.getElementById(obj.id);
ifr.contentWindow.postMessage(obj.callbackAfterRemoval, "*");
content.addEventListener("message", function msg(event) {
if (event.data.type == "finish") {
content.removeEventListener("message", msg);
return;
}
if (event.data.type == "ok") {
ok(event.data.what, event.data.msg);
return;
}
if (event.data.type == "info") {
info(event.data.msg);
return;
}
ok(false, "Unknown message");
});
});
}
if (options.allowList) { if (options.allowList) {
info("Enabling content blocking for this page"); info("Enabling content blocking for this page");
win.ContentBlocking.enableForCurrentPage(); win.ContentBlocking.enableForCurrentPage();

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

@ -79,6 +79,8 @@ skip-if = serviceworker_e10s
[browser_storageAccessPromiseResolveHandlerUserInteraction.js] [browser_storageAccessPromiseResolveHandlerUserInteraction.js]
[browser_storageAccessRemovalNavigateSubframe.js] [browser_storageAccessRemovalNavigateSubframe.js]
skip-if = serviceworker_e10s skip-if = serviceworker_e10s
[browser_storageAccessRemovalNavigateTopframe.js]
skip-if = serviceworker_e10s
[browser_storageAccessSandboxed.js] [browser_storageAccessSandboxed.js]
skip-if = serviceworker_e10s skip-if = serviceworker_e10s
[browser_storageAccessWithHeuristics.js] [browser_storageAccessWithHeuristics.js]

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

@ -0,0 +1,42 @@
/* import-globals-from antitracking_head.js */
AntiTracking.runTest("Storage Access is removed when topframe navigates",
// blocking callback
async _ => {
/* import-globals-from storageAccessAPIHelpers.js */
await noStorageAccessInitially();
},
// non-blocking callback
async _ => {
/* import-globals-from storageAccessAPIHelpers.js */
if (allowListed) {
await hasStorageAccessInitially();
} else {
await noStorageAccessInitially();
}
/* import-globals-from storageAccessAPIHelpers.js */
let [threw, rejected] = await callRequestStorageAccess();
ok(!threw, "requestStorageAccess should not throw");
ok(!rejected, "requestStorageAccess should be available");
},
// cleanup function
async _ => {
await new Promise(resolve => {
Services.clearData.deleteData(Ci.nsIClearDataService.CLEAR_ALL, value => resolve());
});
},
null, // extra prefs
false, // no window open test
false, // no user-interaction test
0, // no blocking notifications
false, // run in normal window
null, // no iframe sandbox
"navigate-topframe", // access removal type
// after-removal callback
async _ => {
/* import-globals-from storageAccessAPIHelpers.js */
await noStorageAccessInitially();
}
);