Bug 1681249 - unbreak subframes navigating ancestor frames to custom protocols, r=nika

Differential Revision: https://phabricator.services.mozilla.com/D101238
This commit is contained in:
Gijs Kruitbosch 2021-01-14 20:17:44 +00:00
parent fa00168092
commit b3aec77f8f
2 changed files with 65 additions and 0 deletions

View file

@ -1089,6 +1089,20 @@ nsExternalHelperAppService::LoadURI(nsIURI* aURI,
bc = parent;
wgp = parent->Canonical()->GetCurrentWindowGlobal();
}
if (!foundAccessibleFrame) {
// See if this navigation could have come from a subframe.
nsTArray<RefPtr<BrowsingContext>> contexts;
aBrowsingContext->GetAllBrowsingContextsInSubtree(contexts);
for (const auto& kid : contexts) {
wgp = kid->Canonical()->GetCurrentWindowGlobal();
if (wgp && aTriggeringPrincipal->Subsumes(wgp->DocumentPrincipal())) {
foundAccessibleFrame = true;
break;
}
}
}
if (!foundAccessibleFrame) {
return NS_OK; // deny the load.
}

View file

@ -345,3 +345,54 @@ add_task(async function test_oop_iframe() {
await dialogClosedPromise;
ok(!dialog._frame.contentWindow, "The dialog should have been closed.");
});
/**
* Check that a cross-origin iframe can navigate the top frame
* to an external protocol.
*/
add_task(async function xorigin_iframe_can_navigate_top() {
let tab = await BrowserTestUtils.openNewForegroundTab(
gBrowser,
"https://example.com/"
);
// Ensure we notice the dialog opening:
let dialogWindowPromise = waitForProtocolAppChooserDialog(
tab.linkedBrowser,
true
);
let innerLoaded = BrowserTestUtils.browserLoaded(
tab.linkedBrowser,
true,
"https://example.org/"
);
info("Constructing frame");
await SpecialPowers.spawn(tab.linkedBrowser, [], function() {
let frame = content.document.createElement("iframe");
frame.src = "https://example.org/"; // cross-origin frame.
content.document.body.prepend(frame);
});
await innerLoaded;
info("Navigating top bc from frame");
let parentBC = tab.linkedBrowser.browsingContext;
await SpecialPowers.spawn(parentBC.children[0], [], async function() {
content.eval("window.top.location.href = 'mailto:example@example.com';");
});
let dialog = await dialogWindowPromise;
is(
dialog._frame.contentDocument.location.href,
CONTENT_HANDLING_URL,
"Dialog opens as expected for navigating the top frame from an x-origin frame."
);
// Close the dialog:
let dialogClosedPromise = waitForProtocolAppChooserDialog(
tab.linkedBrowser,
false
);
dialog.close();
await dialogClosedPromise;
gBrowser.removeTab(tab);
});