Bug 1535699 - Propagate redirect mode across cross-process redirects. r=asuth

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

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Perry Jiang 2019-05-02 20:46:34 +00:00
Родитель d25f704ddf
Коммит cf811f1da6
6 изменённых файлов: 146 добавлений и 4 удалений

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

@ -3555,7 +3555,8 @@ mozilla::ipc::IPCResult ContentChild::RecvSaveRecording(
mozilla::ipc::IPCResult ContentChild::RecvCrossProcessRedirect( mozilla::ipc::IPCResult ContentChild::RecvCrossProcessRedirect(
const uint32_t& aRegistrarId, nsIURI* aURI, const uint32_t& aNewLoadFlags, const uint32_t& aRegistrarId, nsIURI* aURI, const uint32_t& aNewLoadFlags,
const Maybe<LoadInfoArgs>& aLoadInfo, const uint64_t& aChannelId, const Maybe<LoadInfoArgs>& aLoadInfo, const uint64_t& aChannelId,
nsIURI* aOriginalURI, const uint64_t& aIdentifier) { nsIURI* aOriginalURI, const uint64_t& aIdentifier,
const uint32_t& aRedirectMode) {
nsCOMPtr<nsILoadInfo> loadInfo; nsCOMPtr<nsILoadInfo> loadInfo;
nsresult rv = nsresult rv =
mozilla::ipc::LoadInfoArgsToLoadInfo(aLoadInfo, getter_AddRefs(loadInfo)); mozilla::ipc::LoadInfoArgsToLoadInfo(aLoadInfo, getter_AddRefs(loadInfo));
@ -3594,6 +3595,11 @@ mozilla::ipc::IPCResult ContentChild::RecvCrossProcessRedirect(
return IPC_OK(); return IPC_OK();
} }
rv = httpChild->SetRedirectMode(aRedirectMode);
if (NS_FAILED(rv)) {
return IPC_OK();
}
// connect parent. // connect parent.
rv = httpChild->ConnectParent(aRegistrarId); // creates parent channel rv = httpChild->ConnectParent(aRegistrarId); // creates parent channel
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {

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

@ -667,7 +667,8 @@ class ContentChild final : public PContentChild,
mozilla::ipc::IPCResult RecvCrossProcessRedirect( mozilla::ipc::IPCResult RecvCrossProcessRedirect(
const uint32_t& aRegistrarId, nsIURI* aURI, const uint32_t& aNewLoadFlags, const uint32_t& aRegistrarId, nsIURI* aURI, const uint32_t& aNewLoadFlags,
const Maybe<LoadInfoArgs>& aLoadInfoForwarder, const uint64_t& aChannelId, const Maybe<LoadInfoArgs>& aLoadInfoForwarder, const uint64_t& aChannelId,
nsIURI* aOriginalURI, const uint64_t& aIdentifier); nsIURI* aOriginalURI, const uint64_t& aIdentifier,
const uint32_t& aRedirectMode);
mozilla::ipc::IPCResult RecvStartDelayedAutoplayMediaComponents( mozilla::ipc::IPCResult RecvStartDelayedAutoplayMediaComponents(
BrowsingContext* aContext); BrowsingContext* aContext);

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

@ -791,7 +791,8 @@ child:
LoadInfoArgs? aLoadInfo, LoadInfoArgs? aLoadInfo,
uint64_t aChannelId, uint64_t aChannelId,
nsIURI aOriginalURI, nsIURI aOriginalURI,
uint64_t aIdentifier); uint64_t aIdentifier,
uint32_t aRedirectMode);
/** /**
* This method is used to notifty content process to start delayed autoplay * This method is used to notifty content process to start delayed autoplay

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

@ -14,6 +14,7 @@ support-files =
empty_with_utils.html empty_with_utils.html
empty.js empty.js
page_post_controlled.html page_post_controlled.html
redirect.sjs
storage_recovery_worker.sjs storage_recovery_worker.sjs
utils.js utils.js
@ -25,6 +26,8 @@ skip-if = serviceworker_e10s
[browser_download.js] [browser_download.js]
[browser_download_canceled.js] [browser_download_canceled.js]
skip-if = verify skip-if = verify
[browser_navigation_process_swap.js]
skip-if = !e10s || verify # Bug 1548643
[browser_storage_permission.js] [browser_storage_permission.js]
skip-if = (verify && debug && (os == 'win' || os == 'mac')) skip-if = (verify && debug && (os == 'win' || os == 'mac'))
[browser_storage_recovery.js] [browser_storage_recovery.js]

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

@ -0,0 +1,124 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
"use strict";
/**
* This test tests a navigation request to a Service Worker-controlled origin &
* scope that results in a cross-origin redirect to a
* non-Service Worker-controlled scope which additionally participates in
* cross-process redirect.
*
* On success, the test will not crash.
*/
const ORIGIN = 'http://mochi.test:8888';
const TEST_ROOT = getRootDirectory(gTestPath)
.replace('chrome://mochitests/content', ORIGIN);
const SW_REGISTER_PAGE_URL = `${TEST_ROOT}empty_with_utils.html`;
const SW_SCRIPT_URL = `${TEST_ROOT}empty.js`;
const FILE_URL = (() => {
// Get the file as an nsIFile.
const file = getChromeDir(getResolvedURI(gTestPath));
file.append('empty.html');
// Convert the nsIFile to an nsIURI to access the path.
return Services.io.newFileURI(file).spec;
})();
const CROSS_ORIGIN = 'http://example.com';
const CROSS_ORIGIN_URL = SW_REGISTER_PAGE_URL.replace(ORIGIN, CROSS_ORIGIN);
const CROSS_ORIGIN_REDIRECT_URL =
`${TEST_ROOT}redirect.sjs?${CROSS_ORIGIN_URL}`;
async function loadURI(aXULBrowser, aURI) {
const browserLoadedPromise = BrowserTestUtils.browserLoaded(aXULBrowser);
await BrowserTestUtils.loadURI(aXULBrowser, aURI);
return browserLoadedPromise;
}
async function runTest() {
// Step 1: register a Service Worker under `ORIGIN` so that all subsequent
// requests to `ORIGIN` will be marked as controlled.
await SpecialPowers.pushPrefEnv({
'set': [
['dom.serviceWorkers.enabled', true],
['dom.serviceWorkers.exemptFromPerDomainMax', true],
['dom.serviceWorkers.testing.enabled', true],
['devtools.console.stdout.content', true],
],
});
info(`Loading tab with page ${SW_REGISTER_PAGE_URL}`);
const tab = await BrowserTestUtils.openNewForegroundTab({
gBrowser,
opening: SW_REGISTER_PAGE_URL,
});
info(`Loaded page ${SW_REGISTER_PAGE_URL}`);
info(`Registering Service Worker ${SW_SCRIPT_URL}`);
await ContentTask.spawn(
tab.linkedBrowser,
{ scriptURL: SW_SCRIPT_URL },
async ({ scriptURL }) =>
await content.wrappedJSObject.registerAndWaitForActive(scriptURL),
);
info(`Registered and activated Service Worker ${SW_SCRIPT_URL}`);
// Step 2: open a page over file:// and navigate to trigger a process swap
// for the response.
info(`Loading ${FILE_URL}`)
await loadURI(tab.linkedBrowser, FILE_URL);
Assert.equal(tab.linkedBrowser.remoteType, E10SUtils.FILE_REMOTE_TYPE,
`${FILE_URL} should load in a file process`);
info(`Dynamically creating ${FILE_URL}'s link`);
await ContentTask.spawn(
tab.linkedBrowser,
{ href: CROSS_ORIGIN_REDIRECT_URL },
({ href }) => {
const { document } = content;
const link = document.createElement('a');
link.href = href;
link.id = 'link';
link.appendChild(document.createTextNode(href));
document.body.appendChild(link);
},
);
const redirectPromise = BrowserTestUtils.waitForLocationChange(
gBrowser, CROSS_ORIGIN_URL);
info('Starting navigation')
await BrowserTestUtils.synthesizeMouseAtCenter('#link', {},
tab.linkedBrowser);
info(`Waiting for location to change to ${CROSS_ORIGIN_URL}`);
await redirectPromise;
info('Waiting for the browser to stop')
await BrowserTestUtils.browserStopped(tab.linkedBrowser);
Assert.equal(tab.linkedBrowser.remoteType, E10SUtils.WEB_REMOTE_TYPE,
`${CROSS_ORIGIN_URL} should load in a web-content process`);
// Step 3: cleanup.
info('Loading initial page to unregister all Service Workers');
await loadURI(tab.linkedBrowser, SW_REGISTER_PAGE_URL);
info('Unregistering all Service Workers');
await ContentTask.spawn(
tab.linkedBrowser,
null,
async () => await content.wrappedJSObject.unregisterAll(),
)
info('Closing tab');
BrowserTestUtils.removeTab(tab);
}
add_task(runTest);

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

@ -192,10 +192,17 @@ nsresult HttpChannelParentListener::TriggerCrossProcessRedirect(
uint64_t channelId; uint64_t channelId;
MOZ_ALWAYS_SUCCEEDS(httpChannel->GetChannelId(&channelId)); MOZ_ALWAYS_SUCCEEDS(httpChannel->GetChannelId(&channelId));
uint32_t redirectMode = nsIHttpChannelInternal::REDIRECT_MODE_FOLLOW;
nsCOMPtr<nsIHttpChannelInternal> internalChannel =
do_QueryInterface(channel);
if (internalChannel) {
MOZ_ALWAYS_SUCCEEDS(internalChannel->GetRedirectMode(&redirectMode));
}
dom::BrowserParent* browserParent = dom::BrowserParent::GetFrom(tp); dom::BrowserParent* browserParent = dom::BrowserParent::GetFrom(tp);
auto result = browserParent->Manager()->SendCrossProcessRedirect( auto result = browserParent->Manager()->SendCrossProcessRedirect(
self->mRedirectChannelId, uri, newLoadFlags, loadInfoArgs, self->mRedirectChannelId, uri, newLoadFlags, loadInfoArgs,
channelId, originalURI, aIdentifier); channelId, originalURI, aIdentifier, redirectMode);
MOZ_ASSERT(result, "SendCrossProcessRedirect failed"); MOZ_ASSERT(result, "SendCrossProcessRedirect failed");