зеркало из https://github.com/mozilla/gecko-dev.git
Merge mozilla-central to autoland a=merge on a CLOSED TREE
This commit is contained in:
Коммит
4f28e79ca9
|
@ -1482,14 +1482,8 @@ function _loadURI(browser, uri, params = {}) {
|
|||
uri = "about:blank";
|
||||
}
|
||||
|
||||
let {
|
||||
triggeringPrincipal,
|
||||
referrerInfo,
|
||||
postData,
|
||||
userContextId,
|
||||
csp,
|
||||
remoteTypeOverride,
|
||||
} = params || {};
|
||||
let { triggeringPrincipal, referrerInfo, postData, userContextId, csp } =
|
||||
params || {};
|
||||
let loadFlags =
|
||||
params.loadFlags || params.flags || Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
|
||||
let hasValidUserGestureActivation =
|
||||
|
@ -1534,7 +1528,6 @@ function _loadURI(browser, uri, params = {}) {
|
|||
referrerInfo,
|
||||
postData,
|
||||
hasValidUserGestureActivation,
|
||||
remoteTypeOverride,
|
||||
};
|
||||
try {
|
||||
browser.webNavigation.loadURI(uri, loadURIOptions);
|
||||
|
@ -3161,7 +3154,6 @@ async function BrowserViewSourceOfDocument(args) {
|
|||
preferredRemoteType,
|
||||
initialBrowsingContextGroupId,
|
||||
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
skipLoad: true,
|
||||
});
|
||||
args.viewSourceBrowser = tabBrowser.getBrowserForTab(tab);
|
||||
top.gViewSourceUtils.viewSourceInBrowser(args);
|
||||
|
|
|
@ -2095,6 +2095,7 @@
|
|||
|
||||
const defaultBrowserAttributes = {
|
||||
contextmenu: "contentAreaContextMenu",
|
||||
maychangeremoteness: "true",
|
||||
message: "true",
|
||||
messagemanagergroup: "browsers",
|
||||
selectmenulist: "ContentSelectDropdown",
|
||||
|
@ -2105,10 +2106,6 @@
|
|||
b.setAttribute(attribute, defaultBrowserAttributes[attribute]);
|
||||
}
|
||||
|
||||
if (gMultiProcessBrowser || remoteType) {
|
||||
b.setAttribute("maychangeremoteness", "true");
|
||||
}
|
||||
|
||||
if (!initiallyActive) {
|
||||
b.setAttribute("initiallyactive", "false");
|
||||
}
|
||||
|
|
|
@ -80,9 +80,7 @@ async function setupPage(htmlPageName, blockedPage) {
|
|||
let iframe = content.document.getElementById("theIframe");
|
||||
|
||||
await ContentTaskUtils.waitForCondition(() =>
|
||||
SpecialPowers.spawn(iframe, [], () =>
|
||||
content.document.body.classList.contains("neterror")
|
||||
)
|
||||
iframe.contentDocument.body.classList.contains("neterror")
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -80,9 +80,7 @@ async function setupPage(htmlPageName, blockedPage) {
|
|||
let iframe = content.document.getElementById("theIframe");
|
||||
|
||||
await ContentTaskUtils.waitForCondition(() =>
|
||||
SpecialPowers.spawn(iframe, [], () =>
|
||||
content.document.body.classList.contains("neterror")
|
||||
)
|
||||
iframe.contentDocument.body.classList.contains("neterror")
|
||||
);
|
||||
});
|
||||
|
||||
|
|
|
@ -80,7 +80,7 @@ add_task(async function process_switching_through_loading_in_the_same_tab() {
|
|||
|
||||
for (let [url, remoteType] of [
|
||||
[ABOUT_NEWTAB, E10SUtils.PRIVILEGEDABOUT_REMOTE_TYPE],
|
||||
[ABOUT_BLANK, E10SUtils.WEB_REMOTE_TYPE],
|
||||
[ABOUT_BLANK, E10SUtils.PRIVILEGEDABOUT_REMOTE_TYPE],
|
||||
[TEST_HTTP, E10SUtils.WEB_REMOTE_TYPE],
|
||||
[ABOUT_HOME, E10SUtils.PRIVILEGEDABOUT_REMOTE_TYPE],
|
||||
[TEST_HTTP, E10SUtils.WEB_REMOTE_TYPE],
|
||||
|
|
|
@ -42,7 +42,9 @@ function getToolbarNodeForItemGuid(aItemGuid) {
|
|||
}
|
||||
|
||||
function waitForLoad(browser, url) {
|
||||
return BrowserTestUtils.browserLoaded(browser, false, url);
|
||||
return BrowserTestUtils.browserLoaded(browser, false, url).then(() => {
|
||||
return BrowserTestUtils.loadURI(browser, "about:blank");
|
||||
});
|
||||
}
|
||||
|
||||
function waitForNewTab(url, inBackground) {
|
||||
|
|
|
@ -218,10 +218,6 @@ ContentRestoreInternal.prototype = {
|
|||
let loadURIOptions = {
|
||||
triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(),
|
||||
loadFlags: Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY,
|
||||
// Specify an override to force the load to finish in the current
|
||||
// process, as tests rely on this behaviour for non-fission session
|
||||
// restore.
|
||||
remoteTypeOverride: Services.appinfo.remoteType,
|
||||
};
|
||||
webNavigation.loadURI("about:blank", loadURIOptions);
|
||||
}
|
||||
|
|
|
@ -3657,7 +3657,6 @@ var SessionStoreInternal = {
|
|||
triggeringPrincipal: Services.scriptSecurityManager.createNullPrincipal({
|
||||
userContextId: aTab.userContextId,
|
||||
}),
|
||||
remoteTypeOverride: E10SUtils.NOT_REMOTE,
|
||||
});
|
||||
|
||||
let data = TabState.collect(aTab, TAB_CUSTOM_VALUES.get(aTab));
|
||||
|
|
|
@ -3,13 +3,8 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
// FIXME(bug 1709267): This test used to test navigations between `about:home`
|
||||
// and `about:blank`. Some process switch changes during Fission (bug 1650089)
|
||||
// meant that this navigation now leads to a process switch. Unfortunately,
|
||||
// about:debugging is not resillient to process switches, so the URLs were
|
||||
// changed to both load within the same content process.
|
||||
const ORIGINAL_URL = "http://example.com/document-builder.sjs?html=page1";
|
||||
const OTHER_URL = "http://example.com/document-builder.sjs?html=page2";
|
||||
const ORIGINAL_URL = "about:home";
|
||||
const OTHER_URL = "about:blank";
|
||||
|
||||
async function waitForUrl(url, toolbox, browserTab, win) {
|
||||
const {
|
||||
|
|
|
@ -279,7 +279,7 @@ void CanonicalBrowsingContext::MaybeAddAsProgressListener(
|
|||
|
||||
void CanonicalBrowsingContext::ReplacedBy(
|
||||
CanonicalBrowsingContext* aNewContext,
|
||||
const NavigationIsolationOptions& aRemotenessOptions) {
|
||||
const RemotenessChangeOptions& aRemotenessOptions) {
|
||||
MOZ_ASSERT(!aNewContext->mWebProgress);
|
||||
MOZ_ASSERT(!aNewContext->mSessionHistory);
|
||||
MOZ_ASSERT(IsTop() && aNewContext->IsTop());
|
||||
|
@ -1696,7 +1696,7 @@ void CanonicalBrowsingContext::PendingRemotenessChange::Clear() {
|
|||
|
||||
CanonicalBrowsingContext::PendingRemotenessChange::PendingRemotenessChange(
|
||||
CanonicalBrowsingContext* aTarget, RemotenessPromise::Private* aPromise,
|
||||
uint64_t aPendingSwitchId, const NavigationIsolationOptions& aOptions)
|
||||
uint64_t aPendingSwitchId, const RemotenessChangeOptions& aOptions)
|
||||
: mTarget(aTarget),
|
||||
mPromise(aPromise),
|
||||
mPendingSwitchId(aPendingSwitchId),
|
||||
|
@ -1732,7 +1732,7 @@ void CanonicalBrowsingContext::SetCurrentBrowserParent(
|
|||
|
||||
RefPtr<CanonicalBrowsingContext::RemotenessPromise>
|
||||
CanonicalBrowsingContext::ChangeRemoteness(
|
||||
const NavigationIsolationOptions& aOptions, uint64_t aPendingSwitchId) {
|
||||
const RemotenessChangeOptions& aOptions, uint64_t aPendingSwitchId) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(IsContent(),
|
||||
"cannot change the process of chrome contexts");
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
|
@ -2530,7 +2530,7 @@ void CanonicalBrowsingContext::RemovePageAwakeRequest() {
|
|||
void CanonicalBrowsingContext::CloneDocumentTreeInto(
|
||||
CanonicalBrowsingContext* aSource, const nsACString& aRemoteType,
|
||||
embedding::PrintData&& aPrintData) {
|
||||
NavigationIsolationOptions options;
|
||||
RemotenessChangeOptions options;
|
||||
options.mRemoteType = aRemoteType;
|
||||
|
||||
mClonePromise =
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
#include "mozilla/dom/BrowsingContext.h"
|
||||
#include "mozilla/dom/MediaControlKeySource.h"
|
||||
#include "mozilla/dom/BrowsingContextWebProgress.h"
|
||||
#include "mozilla/dom/ProcessIsolation.h"
|
||||
#include "mozilla/dom/Promise.h"
|
||||
#include "mozilla/dom/SessionHistoryEntry.h"
|
||||
#include "mozilla/dom/SessionStoreRestoreData.h"
|
||||
|
@ -56,6 +55,16 @@ struct LoadingSessionHistoryInfo;
|
|||
class SSCacheCopy;
|
||||
class WindowGlobalParent;
|
||||
|
||||
// RemotenessChangeOptions is passed through the methods to store the state
|
||||
// of the possible remoteness change.
|
||||
struct RemotenessChangeOptions {
|
||||
nsCString mRemoteType;
|
||||
bool mReplaceBrowsingContext = false;
|
||||
uint64_t mSpecificGroupId = 0;
|
||||
bool mTryUseBFCache = false;
|
||||
RefPtr<SessionHistoryEntry> mActiveSessionHistoryEntry;
|
||||
};
|
||||
|
||||
// CanonicalBrowsingContext is a BrowsingContext living in the parent
|
||||
// process, with whatever extra data that a BrowsingContext in the
|
||||
// parent needs.
|
||||
|
@ -224,7 +233,7 @@ class CanonicalBrowsingContext final : public BrowsingContext {
|
|||
// the parent process, and the method will resolve with a null BrowserParent.
|
||||
using RemotenessPromise = MozPromise<RefPtr<BrowserParent>, nsresult, false>;
|
||||
RefPtr<RemotenessPromise> ChangeRemoteness(
|
||||
const NavigationIsolationOptions& aOptions, uint64_t aPendingSwitchId);
|
||||
const RemotenessChangeOptions& aOptions, uint64_t aPendingSwitchId);
|
||||
|
||||
// Return a media controller from the top-level browsing context that can
|
||||
// control all media belonging to this browsing context tree. Return nullptr
|
||||
|
@ -263,7 +272,7 @@ class CanonicalBrowsingContext final : public BrowsingContext {
|
|||
// aNewContext is the newly created BrowsingContext that is replacing
|
||||
// us.
|
||||
void ReplacedBy(CanonicalBrowsingContext* aNewContext,
|
||||
const NavigationIsolationOptions& aRemotenessOptions);
|
||||
const RemotenessChangeOptions& aRemotenessOptions);
|
||||
|
||||
bool HasHistoryEntry(nsISHEntry* aEntry);
|
||||
|
||||
|
@ -379,7 +388,7 @@ class CanonicalBrowsingContext final : public BrowsingContext {
|
|||
PendingRemotenessChange(CanonicalBrowsingContext* aTarget,
|
||||
RemotenessPromise::Private* aPromise,
|
||||
uint64_t aPendingSwitchId,
|
||||
const NavigationIsolationOptions& aOptions);
|
||||
const RemotenessChangeOptions& aOptions);
|
||||
|
||||
void Cancel(nsresult aRv);
|
||||
|
||||
|
@ -402,7 +411,7 @@ class CanonicalBrowsingContext final : public BrowsingContext {
|
|||
RefPtr<BrowsingContextGroup> mSpecificGroup;
|
||||
|
||||
uint64_t mPendingSwitchId;
|
||||
NavigationIsolationOptions mOptions;
|
||||
RemotenessChangeOptions mOptions;
|
||||
};
|
||||
|
||||
struct RestoreState {
|
||||
|
|
|
@ -88,7 +88,6 @@ nsDocShellLoadState::nsDocShellLoadState(
|
|||
aLoadState.loadingSessionHistoryInfo().ref());
|
||||
}
|
||||
mUnstrippedURI = aLoadState.UnstrippedURI();
|
||||
mRemoteTypeOverride = aLoadState.RemoteTypeOverride();
|
||||
}
|
||||
|
||||
nsDocShellLoadState::nsDocShellLoadState(const nsDocShellLoadState& aOther)
|
||||
|
@ -134,8 +133,7 @@ nsDocShellLoadState::nsDocShellLoadState(const nsDocShellLoadState& aOther)
|
|||
mLoadIdentifier(aOther.mLoadIdentifier),
|
||||
mChannelInitialized(aOther.mChannelInitialized),
|
||||
mIsMetaRefresh(aOther.mIsMetaRefresh),
|
||||
mUnstrippedURI(aOther.mUnstrippedURI),
|
||||
mRemoteTypeOverride(aOther.mRemoteTypeOverride) {
|
||||
mUnstrippedURI(aOther.mUnstrippedURI) {
|
||||
if (aOther.mLoadingSessionHistoryInfo) {
|
||||
mLoadingSessionHistoryInfo = MakeUnique<LoadingSessionHistoryInfo>(
|
||||
*aOther.mLoadingSessionHistoryInfo);
|
||||
|
@ -371,11 +369,6 @@ nsresult nsDocShellLoadState::CreateFromLoadURIOptions(
|
|||
nsDocShell::MaybeNotifyKeywordSearchLoading(searchProvider, keyword);
|
||||
}
|
||||
|
||||
if (aLoadURIOptions.mRemoteTypeOverride.WasPassed()) {
|
||||
loadState->SetRemoteTypeOverride(
|
||||
aLoadURIOptions.mRemoteTypeOverride.Value());
|
||||
}
|
||||
|
||||
loadState.forget(aResult);
|
||||
return NS_OK;
|
||||
}
|
||||
|
@ -1053,7 +1046,6 @@ DocShellLoadStateInit nsDocShellLoadState::Serialize() {
|
|||
loadState.loadingSessionHistoryInfo().emplace(*mLoadingSessionHistoryInfo);
|
||||
}
|
||||
loadState.UnstrippedURI() = mUnstrippedURI;
|
||||
loadState.RemoteTypeOverride() = mRemoteTypeOverride;
|
||||
return loadState;
|
||||
}
|
||||
|
||||
|
|
|
@ -304,14 +304,6 @@ class nsDocShellLoadState final {
|
|||
|
||||
bool IsMetaRefresh() const { return mIsMetaRefresh; }
|
||||
|
||||
const mozilla::Maybe<nsCString>& GetRemoteTypeOverride() const {
|
||||
return mRemoteTypeOverride;
|
||||
}
|
||||
|
||||
void SetRemoteTypeOverride(const nsCString& aRemoteTypeOverride) {
|
||||
mRemoteTypeOverride = mozilla::Some(aRemoteTypeOverride);
|
||||
}
|
||||
|
||||
// When loading a document through nsDocShell::LoadURI(), a special set of
|
||||
// flags needs to be set based on other values in nsDocShellLoadState. This
|
||||
// function calculates those flags, before the LoadState is passed to
|
||||
|
@ -532,9 +524,6 @@ class nsDocShellLoadState final {
|
|||
// The original URI before query stripping happened. If it's present, it shows
|
||||
// the query stripping happened. Otherwise, it will be a nullptr.
|
||||
nsCOMPtr<nsIURI> mUnstrippedURI;
|
||||
|
||||
// If set, the remote type which the load should be completed within.
|
||||
mozilla::Maybe<nsCString> mRemoteTypeOverride;
|
||||
};
|
||||
|
||||
#endif /* nsDocShellLoadState_h__ */
|
||||
|
|
|
@ -1235,7 +1235,7 @@ static void FinishRestore(CanonicalBrowsingContext* aBrowsingContext,
|
|||
// ReplacedBy will swap the entry back.
|
||||
aBrowsingContext->SetActiveSessionHistoryEntry(aEntry);
|
||||
loadingBC->SetActiveSessionHistoryEntry(nullptr);
|
||||
NavigationIsolationOptions options;
|
||||
RemotenessChangeOptions options;
|
||||
aBrowsingContext->ReplacedBy(loadingBC, options);
|
||||
|
||||
// Assuming we still have the session history, update the index.
|
||||
|
|
|
@ -5,17 +5,16 @@ function test() {
|
|||
var iteration = 1;
|
||||
const uris = ["", "about:blank"];
|
||||
var uri;
|
||||
var origWgp;
|
||||
var origDoc;
|
||||
|
||||
function testLoad() {
|
||||
let wgp = w.gBrowser.selectedBrowser.browsingContext.currentWindowGlobal;
|
||||
if (wgp == origWgp) {
|
||||
if (w.document == origDoc) {
|
||||
// Go back to polling
|
||||
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
|
||||
setTimeout(testLoad, 10);
|
||||
return;
|
||||
}
|
||||
var prin = wgp.documentPrincipal;
|
||||
var prin = w.document.nodePrincipal;
|
||||
isnot(prin, null, "Loaded principal must not be null when adding " + uri);
|
||||
isnot(
|
||||
prin,
|
||||
|
@ -40,9 +39,8 @@ function test() {
|
|||
function doTest() {
|
||||
uri = uris[iteration - 1];
|
||||
window.open(uri, "_blank", "width=10,height=10,noopener");
|
||||
w = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
origWgp = w.gBrowser.selectedBrowser.browsingContext.currentWindowGlobal;
|
||||
var prin = origWgp.documentPrincipal;
|
||||
w = Services.wm.getMostRecentWindow("navigator:browser").content;
|
||||
var prin = w.document.nodePrincipal;
|
||||
if (!uri) {
|
||||
uri = undefined;
|
||||
}
|
||||
|
@ -63,6 +61,7 @@ function test() {
|
|||
++iteration;
|
||||
doTest();
|
||||
} else {
|
||||
origDoc = w.document;
|
||||
// Need to poll, because load listeners on the content window won't
|
||||
// survive the load.
|
||||
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
|
||||
|
|
|
@ -481,7 +481,7 @@ already_AddRefed<nsFrameLoader> nsFrameLoader::Create(
|
|||
already_AddRefed<nsFrameLoader> nsFrameLoader::Recreate(
|
||||
mozilla::dom::Element* aOwner, BrowsingContext* aContext,
|
||||
BrowsingContextGroup* aSpecificGroup,
|
||||
const NavigationIsolationOptions& aRemotenessOptions, bool aIsRemote,
|
||||
const RemotenessChangeOptions& aRemotenessOptions, bool aIsRemote,
|
||||
bool aNetworkCreated, bool aPreserveContext) {
|
||||
NS_ENSURE_TRUE(aOwner, nullptr);
|
||||
|
||||
|
@ -719,16 +719,6 @@ nsresult nsFrameLoader::ReallyStartLoadingInternal() {
|
|||
loadState->SetLoadFlags(flags);
|
||||
|
||||
loadState->SetFirstParty(false);
|
||||
|
||||
// If we're loading the default about:blank document in a <browser> element,
|
||||
// prevent the load from causing a process switch by explicitly overriding
|
||||
// remote type selection.
|
||||
if (mPendingBrowsingContext->IsTopContent() &&
|
||||
mOwnerContent->IsXULElement(nsGkAtoms::browser) &&
|
||||
NS_IsAboutBlank(mURIToLoad) &&
|
||||
loadState->TriggeringPrincipal()->IsSystemPrincipal()) {
|
||||
loadState->SetRemoteTypeOverride(mRemoteType);
|
||||
}
|
||||
}
|
||||
|
||||
if (IsRemoteFrame()) {
|
||||
|
|
|
@ -72,7 +72,7 @@ class MutableTabContext;
|
|||
class BrowserBridgeChild;
|
||||
class RemoteBrowser;
|
||||
struct RemotenessOptions;
|
||||
struct NavigationIsolationOptions;
|
||||
struct RemotenessChangeOptions;
|
||||
class SessionStoreChangeListener;
|
||||
|
||||
namespace ipc {
|
||||
|
@ -123,7 +123,7 @@ class nsFrameLoader final : public nsStubMutationObserver,
|
|||
// FrameLoaders.
|
||||
static already_AddRefed<nsFrameLoader> Recreate(
|
||||
Element* aOwner, BrowsingContext* aContext, BrowsingContextGroup* aGroup,
|
||||
const mozilla::dom::NavigationIsolationOptions& aRemotenessOptions,
|
||||
const mozilla::dom::RemotenessChangeOptions& aRemotenessOptions,
|
||||
bool aIsRemote, bool aNetworkCreated, bool aPreserveContext);
|
||||
|
||||
NS_DECLARE_STATIC_IID_ACCESSOR(NS_FRAMELOADER_IID)
|
||||
|
|
|
@ -92,7 +92,7 @@ nsFrameLoaderOwner::ShouldPreserveBrowsingContext(
|
|||
|
||||
void nsFrameLoaderOwner::ChangeRemotenessCommon(
|
||||
const ChangeRemotenessContextType& aContextType,
|
||||
const NavigationIsolationOptions& aOptions, bool aSwitchingInProgressLoad,
|
||||
const RemotenessChangeOptions& aOptions, bool aSwitchingInProgressLoad,
|
||||
bool aIsRemote, BrowsingContextGroup* aGroup,
|
||||
std::function<void()>& aFrameLoaderInit, mozilla::ErrorResult& aRv) {
|
||||
MOZ_ASSERT_IF(aGroup, aContextType != ChangeRemotenessContextType::PRESERVE);
|
||||
|
@ -263,7 +263,7 @@ void nsFrameLoaderOwner::ChangeRemoteness(
|
|||
|
||||
auto shouldPreserve = ShouldPreserveBrowsingContext(
|
||||
isRemote, /* replaceBrowsingContext */ false);
|
||||
NavigationIsolationOptions options;
|
||||
RemotenessChangeOptions options;
|
||||
ChangeRemotenessCommon(shouldPreserve, options,
|
||||
aOptions.mSwitchingInProgressLoad, isRemote,
|
||||
/* group */ nullptr, frameLoaderInit, rv);
|
||||
|
@ -284,7 +284,7 @@ void nsFrameLoaderOwner::ChangeRemotenessWithBridge(BrowserBridgeChild* aBridge,
|
|||
mFrameLoader->mRemoteBrowser = host;
|
||||
};
|
||||
|
||||
NavigationIsolationOptions options;
|
||||
RemotenessChangeOptions options;
|
||||
ChangeRemotenessCommon(ChangeRemotenessContextType::PRESERVE, options,
|
||||
/* inProgress */ true,
|
||||
/* isRemote */ true, /* group */ nullptr,
|
||||
|
@ -292,7 +292,7 @@ void nsFrameLoaderOwner::ChangeRemotenessWithBridge(BrowserBridgeChild* aBridge,
|
|||
}
|
||||
|
||||
void nsFrameLoaderOwner::ChangeRemotenessToProcess(
|
||||
ContentParent* aContentParent, const NavigationIsolationOptions& aOptions,
|
||||
ContentParent* aContentParent, const RemotenessChangeOptions& aOptions,
|
||||
BrowsingContextGroup* aGroup, mozilla::ErrorResult& rv) {
|
||||
MOZ_ASSERT(XRE_IsParentProcess());
|
||||
MOZ_ASSERT_IF(aGroup, aOptions.mReplaceBrowsingContext);
|
||||
|
@ -335,7 +335,7 @@ void nsFrameLoaderOwner::SubframeCrashed() {
|
|||
}));
|
||||
};
|
||||
|
||||
NavigationIsolationOptions options;
|
||||
RemotenessChangeOptions options;
|
||||
ChangeRemotenessCommon(ChangeRemotenessContextType::PRESERVE, options,
|
||||
/* inProgress */ false, /* isRemote */ false,
|
||||
/* group */ nullptr, frameLoaderInit, IgnoreErrors());
|
||||
|
|
|
@ -20,7 +20,7 @@ class BrowserBridgeChild;
|
|||
class ContentParent;
|
||||
class Element;
|
||||
struct RemotenessOptions;
|
||||
struct NavigationIsolationOptions;
|
||||
struct RemotenessChangeOptions;
|
||||
} // namespace dom
|
||||
} // namespace mozilla
|
||||
|
||||
|
@ -75,7 +75,7 @@ class nsFrameLoaderOwner : public nsISupports {
|
|||
// disabled for this process switch.
|
||||
void ChangeRemotenessToProcess(
|
||||
mozilla::dom::ContentParent* aContentParent,
|
||||
const mozilla::dom::NavigationIsolationOptions& aOptions,
|
||||
const mozilla::dom::RemotenessChangeOptions& aOptions,
|
||||
mozilla::dom::BrowsingContextGroup* aGroup, mozilla::ErrorResult& rv);
|
||||
|
||||
void SubframeCrashed();
|
||||
|
@ -104,7 +104,7 @@ class nsFrameLoaderOwner : public nsISupports {
|
|||
|
||||
void ChangeRemotenessCommon(
|
||||
const ChangeRemotenessContextType& aContextType,
|
||||
const mozilla::dom::NavigationIsolationOptions& aOptions,
|
||||
const mozilla::dom::RemotenessChangeOptions& aOptions,
|
||||
bool aSwitchingInProgressLoad, bool aIsRemote,
|
||||
mozilla::dom::BrowsingContextGroup* aGroup,
|
||||
std::function<void()>& aFrameLoaderInit, mozilla::ErrorResult& aRv);
|
||||
|
|
|
@ -303,8 +303,6 @@ struct DocShellLoadStateInit
|
|||
bool IsMetaRefresh;
|
||||
|
||||
nsIURI UnstrippedURI;
|
||||
|
||||
nsCString? RemoteTypeOverride;
|
||||
};
|
||||
|
||||
struct TimedChannelInfo
|
||||
|
|
|
@ -1,819 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set sw=2 ts=8 et tw=80 : */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#include "mozilla/dom/ProcessIsolation.h"
|
||||
|
||||
#include "mozilla/Assertions.h"
|
||||
#include "mozilla/dom/BrowsingContextGroup.h"
|
||||
#include "mozilla/dom/CanonicalBrowsingContext.h"
|
||||
#include "mozilla/dom/ContentChild.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/Element.h"
|
||||
#include "mozilla/dom/RemoteType.h"
|
||||
#include "mozilla/dom/WindowGlobalParent.h"
|
||||
#include "mozilla/extensions/WebExtensionPolicy.h"
|
||||
#include "mozilla/BasePrincipal.h"
|
||||
#include "mozilla/ClearOnShutdown.h"
|
||||
#include "mozilla/ContentPrincipal.h"
|
||||
#include "mozilla/ExtensionPolicyService.h"
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/NullPrincipal.h"
|
||||
#include "mozilla/Preferences.h"
|
||||
#include "mozilla/RefPtr.h"
|
||||
#include "mozilla/StaticPrefs_browser.h"
|
||||
#include "mozilla/StaticPtr.h"
|
||||
#include "nsAboutProtocolUtils.h"
|
||||
#include "nsDocShell.h"
|
||||
#include "nsError.h"
|
||||
#include "nsIChromeRegistry.h"
|
||||
#include "nsIHttpChannel.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIProtocolHandler.h"
|
||||
#include "nsIXULRuntime.h"
|
||||
#include "nsNetUtil.h"
|
||||
#include "nsServiceManagerUtils.h"
|
||||
#include "nsSHistory.h"
|
||||
#include "nsURLHelper.h"
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
mozilla::LazyLogModule gProcessIsolationLog{"ProcessIsolation"};
|
||||
|
||||
namespace {
|
||||
|
||||
/**
|
||||
* Helper class for caching the result of splitting prefs which are represented
|
||||
* as a comma-separated list of strings.
|
||||
*/
|
||||
struct CommaSeparatedPref {
|
||||
public:
|
||||
explicit constexpr CommaSeparatedPref(nsLiteralCString aPrefName)
|
||||
: mPrefName(aPrefName) {}
|
||||
|
||||
void OnChange() {
|
||||
if (mValues) {
|
||||
mValues->Clear();
|
||||
nsAutoCString prefValue;
|
||||
if (NS_SUCCEEDED(Preferences::GetCString(mPrefName.get(), prefValue))) {
|
||||
for (const auto& value :
|
||||
nsCCharSeparatedTokenizer(prefValue, ',').ToRange()) {
|
||||
mValues->EmplaceBack(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const nsTArray<nsCString>& Get() {
|
||||
if (!mValues) {
|
||||
mValues = new nsTArray<nsCString>;
|
||||
Preferences::RegisterCallbackAndCall(
|
||||
[](const char*, void* aData) {
|
||||
static_cast<CommaSeparatedPref*>(aData)->OnChange();
|
||||
},
|
||||
mPrefName, this);
|
||||
RunOnShutdown([this] {
|
||||
delete this->mValues;
|
||||
this->mValues = nullptr;
|
||||
});
|
||||
}
|
||||
return *mValues;
|
||||
}
|
||||
|
||||
auto begin() { return Get().cbegin(); }
|
||||
auto end() { return Get().cend(); }
|
||||
|
||||
private:
|
||||
nsLiteralCString mPrefName;
|
||||
nsTArray<nsCString>* MOZ_OWNING_REF mValues = nullptr;
|
||||
};
|
||||
|
||||
CommaSeparatedPref sSeparatedMozillaDomains{
|
||||
"browser.tabs.remote.separatedMozillaDomains"_ns};
|
||||
|
||||
/**
|
||||
* Certain URIs have special isolation behaviour, and need to be loaded within
|
||||
* specific process types.
|
||||
*/
|
||||
enum class IsolationBehavior {
|
||||
// This URI loads web content and should be treated as a content load, being
|
||||
// isolated based on the response principal.
|
||||
WebContent,
|
||||
// Forcibly load in a process with the "web" remote type.
|
||||
ForceWebRemoteType,
|
||||
// Load this URI in the privileged about content process.
|
||||
PrivilegedAbout,
|
||||
// Load this URI in the extension process.
|
||||
Extension,
|
||||
// Load this URI in the file content process.
|
||||
File,
|
||||
// Load this URI in the priviliged mozilla content process.
|
||||
PrivilegedMozilla,
|
||||
// Load this URI explicitly in the parent process.
|
||||
Parent,
|
||||
// Load this URI wherever the browsing context is currently loaded. This is
|
||||
// generally used for error pages.
|
||||
Anywhere,
|
||||
// May only be returned for subframes. Inherits the remote type of the parent
|
||||
// document which is embedding this document.
|
||||
Inherit,
|
||||
// Special case for the `about:reader` URI which should be loaded in the same
|
||||
// process which would be used for the "url" query parameter.
|
||||
AboutReader,
|
||||
// There was a fatal error, and the load should be aborted.
|
||||
Error,
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a static string with the name of the given isolation behaviour. For
|
||||
* use in logging code.
|
||||
*/
|
||||
static const char* IsolationBehaviorName(IsolationBehavior aBehavior) {
|
||||
switch (aBehavior) {
|
||||
case IsolationBehavior::WebContent:
|
||||
return "WebContent";
|
||||
case IsolationBehavior::ForceWebRemoteType:
|
||||
return "ForceWebRemoteType";
|
||||
case IsolationBehavior::PrivilegedAbout:
|
||||
return "PrivilegedAbout";
|
||||
case IsolationBehavior::Extension:
|
||||
return "Extension";
|
||||
case IsolationBehavior::File:
|
||||
return "File";
|
||||
case IsolationBehavior::PrivilegedMozilla:
|
||||
return "PrivilegedMozilla";
|
||||
case IsolationBehavior::Parent:
|
||||
return "Parent";
|
||||
case IsolationBehavior::Anywhere:
|
||||
return "Anywhere";
|
||||
case IsolationBehavior::Inherit:
|
||||
return "Inherit";
|
||||
case IsolationBehavior::AboutReader:
|
||||
return "AboutReader";
|
||||
case IsolationBehavior::Error:
|
||||
return "Error";
|
||||
default:
|
||||
return "Unknown";
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a given URI has specialized process isolation behaviour, such as
|
||||
* needing to be loaded within a specific type of content process.
|
||||
*
|
||||
* When handling a navigation, this method will be called twice: first with the
|
||||
* channel's creation URI, and then it will be called with a result principal's
|
||||
* URI.
|
||||
*/
|
||||
static IsolationBehavior IsolationBehaviorForURI(nsIURI* aURI, bool aIsSubframe,
|
||||
bool aForChannelCreationURI) {
|
||||
nsAutoCString scheme;
|
||||
MOZ_ALWAYS_SUCCEEDS(aURI->GetScheme(scheme));
|
||||
|
||||
if (scheme == "chrome"_ns) {
|
||||
// `chrome://` URIs are always loaded in the parent process, unless they
|
||||
// have opted in to loading in a content process. This is currently only
|
||||
// done in tests.
|
||||
//
|
||||
// FIXME: These flags should be removed from `chrome` URIs at some point.
|
||||
nsCOMPtr<nsIXULChromeRegistry> chromeReg =
|
||||
do_GetService("@mozilla.org/chrome/chrome-registry;1");
|
||||
bool mustLoadRemotely = false;
|
||||
if (NS_SUCCEEDED(chromeReg->MustLoadURLRemotely(aURI, &mustLoadRemotely)) &&
|
||||
mustLoadRemotely) {
|
||||
return IsolationBehavior::ForceWebRemoteType;
|
||||
}
|
||||
bool canLoadRemotely = false;
|
||||
if (NS_SUCCEEDED(chromeReg->CanLoadURLRemotely(aURI, &canLoadRemotely)) &&
|
||||
canLoadRemotely) {
|
||||
return IsolationBehavior::Anywhere;
|
||||
}
|
||||
return IsolationBehavior::Parent;
|
||||
}
|
||||
|
||||
if (scheme == "about"_ns) {
|
||||
nsAutoCString path;
|
||||
MOZ_ALWAYS_SUCCEEDS(NS_GetAboutModuleName(aURI, path));
|
||||
|
||||
// The `about:blank` and `about:srcdoc` pages are loaded by normal web
|
||||
// content, and should be allocated processes based on their simple content
|
||||
// principals.
|
||||
if (path == "blank"_ns || path == "srcdoc"_ns) {
|
||||
return IsolationBehavior::WebContent;
|
||||
}
|
||||
|
||||
// If we're loading an `about:reader` URI, perform isolation based on the
|
||||
// principal of the URI being loaded.
|
||||
if (path == "reader"_ns && aForChannelCreationURI) {
|
||||
return IsolationBehavior::AboutReader;
|
||||
}
|
||||
|
||||
// Otherwise, we're going to be loading an about: page. Consult the module.
|
||||
nsCOMPtr<nsIAboutModule> aboutModule;
|
||||
if (NS_FAILED(NS_GetAboutModule(aURI, getter_AddRefs(aboutModule))) ||
|
||||
!aboutModule) {
|
||||
// If we don't know of an about: module for this load, it's going to end
|
||||
// up being a network error. Allow the load to finish as normal.
|
||||
return IsolationBehavior::WebContent;
|
||||
}
|
||||
|
||||
// NOTE: about modules can be implemented in JS, so this may run script, and
|
||||
// therefore can spuriously fail.
|
||||
uint32_t flags = 0;
|
||||
if (NS_FAILED(aboutModule->GetURIFlags(aURI, &flags))) {
|
||||
NS_WARNING(
|
||||
"nsIAboutModule::GetURIFlags unexpectedly failed. Abort the load");
|
||||
return IsolationBehavior::Error;
|
||||
}
|
||||
|
||||
if (flags & nsIAboutModule::URI_MUST_LOAD_IN_EXTENSION_PROCESS) {
|
||||
return IsolationBehavior::Extension;
|
||||
}
|
||||
|
||||
if (flags & nsIAboutModule::URI_MUST_LOAD_IN_CHILD) {
|
||||
if (flags & nsIAboutModule::URI_CAN_LOAD_IN_PRIVILEGEDABOUT_PROCESS) {
|
||||
return IsolationBehavior::PrivilegedAbout;
|
||||
}
|
||||
return IsolationBehavior::ForceWebRemoteType;
|
||||
}
|
||||
|
||||
if (flags & nsIAboutModule::URI_CAN_LOAD_IN_CHILD) {
|
||||
return IsolationBehavior::Anywhere;
|
||||
}
|
||||
|
||||
return IsolationBehavior::Parent;
|
||||
}
|
||||
|
||||
// If the test-only `dataUriInDefaultWebProcess` pref is enabled, dump all
|
||||
// `data:` URIs in a "web" content process, rather than loading them in
|
||||
// content processes based on their precursor origins.
|
||||
if (StaticPrefs::browser_tabs_remote_dataUriInDefaultWebProcess() &&
|
||||
scheme == "data"_ns) {
|
||||
return IsolationBehavior::ForceWebRemoteType;
|
||||
}
|
||||
|
||||
// Make sure to unwrap nested URIs before we early return for channel creation
|
||||
// URI. The checks past this point are intended to operate on the principal,
|
||||
// which has it's origin constructed from the innermost URI.
|
||||
nsCOMPtr<nsIURI> inner;
|
||||
if (nsCOMPtr<nsINestedURI> nested = do_QueryInterface(aURI);
|
||||
nested && NS_SUCCEEDED(nested->GetInnerURI(getter_AddRefs(inner)))) {
|
||||
return IsolationBehaviorForURI(inner, aIsSubframe, aForChannelCreationURI);
|
||||
}
|
||||
|
||||
// If we're doing the initial check based on the channel creation URI, stop
|
||||
// here as we want to only perform the following checks on the true channel
|
||||
// result principal.
|
||||
if (aForChannelCreationURI) {
|
||||
return IsolationBehavior::WebContent;
|
||||
}
|
||||
|
||||
// Protocols used by Thunderbird to display email messages.
|
||||
if (scheme == "imap"_ns || scheme == "mailbox"_ns || scheme == "news"_ns ||
|
||||
scheme == "nntp"_ns || scheme == "snews"_ns) {
|
||||
return IsolationBehavior::Parent;
|
||||
}
|
||||
|
||||
// There is more handling for extension content processes in the caller, but
|
||||
// they should load in an extension content process unless we're loading a
|
||||
// subframe.
|
||||
if (scheme == "moz-extension"_ns) {
|
||||
if (aIsSubframe) {
|
||||
// As a temporary measure, extension iframes must be loaded within the
|
||||
// same process as their parent document.
|
||||
return IsolationBehavior::Inherit;
|
||||
}
|
||||
return IsolationBehavior::Extension;
|
||||
}
|
||||
|
||||
if (scheme == "file"_ns) {
|
||||
return IsolationBehavior::File;
|
||||
}
|
||||
|
||||
// Check if the URI is listed as a privileged mozilla content process.
|
||||
if (scheme == "https"_ns &&
|
||||
StaticPrefs::
|
||||
browser_tabs_remote_separatePrivilegedMozillaWebContentProcess()) {
|
||||
nsAutoCString host;
|
||||
if (NS_SUCCEEDED(aURI->GetAsciiHost(host))) {
|
||||
for (const auto& separatedDomain : sSeparatedMozillaDomains) {
|
||||
// If the domain exactly matches our host, or our host ends with "." +
|
||||
// separatedDomain, we consider it matching.
|
||||
if (separatedDomain == host ||
|
||||
(separatedDomain.Length() < host.Length() &&
|
||||
host.CharAt(host.Length() - separatedDomain.Length() - 1) == '.' &&
|
||||
StringEndsWith(host, separatedDomain))) {
|
||||
return IsolationBehavior::PrivilegedMozilla;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIScriptSecurityManager> secMan =
|
||||
nsContentUtils::GetSecurityManager();
|
||||
bool inFileURIAllowList = false;
|
||||
if (NS_SUCCEEDED(secMan->InFileURIAllowlist(aURI, &inFileURIAllowList)) &&
|
||||
inFileURIAllowList) {
|
||||
return IsolationBehavior::File;
|
||||
}
|
||||
|
||||
return IsolationBehavior::WebContent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method for logging the origin of a principal as a string.
|
||||
*/
|
||||
static nsAutoCString OriginString(nsIPrincipal* aPrincipal) {
|
||||
nsAutoCString origin;
|
||||
aPrincipal->GetOrigin(origin);
|
||||
return origin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given an about:reader URI, extract the "url" query parameter, and use it to
|
||||
* construct a principal which should be sed for process selection.
|
||||
*/
|
||||
static already_AddRefed<BasePrincipal> GetAboutReaderURLPrincipal(
|
||||
nsIURI* aURI, const OriginAttributes& aAttrs) {
|
||||
#ifdef DEBUG
|
||||
MOZ_ASSERT(aURI->SchemeIs("about"));
|
||||
nsAutoCString path;
|
||||
MOZ_ALWAYS_SUCCEEDS(NS_GetAboutModuleName(aURI, path));
|
||||
MOZ_ASSERT(path == "reader"_ns);
|
||||
#endif
|
||||
|
||||
nsAutoCString query;
|
||||
MOZ_ALWAYS_SUCCEEDS(aURI->GetQuery(query));
|
||||
|
||||
// Extract the "url" parameter from the `about:reader`'s query parameters,
|
||||
// and recover a content principal from it.
|
||||
nsAutoString readerSpec;
|
||||
if (URLParams::Extract(query, u"url"_ns, readerSpec)) {
|
||||
nsCOMPtr<nsIURI> readerUri;
|
||||
if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(readerUri), readerSpec))) {
|
||||
return BasePrincipal::CreateContentPrincipal(readerUri, aAttrs);
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the given load has the `Large-Allocation` header set, and the header
|
||||
* is enabled.
|
||||
*/
|
||||
static bool IsLargeAllocationLoad(CanonicalBrowsingContext* aBrowsingContext,
|
||||
nsIChannel* aChannel) {
|
||||
if (!StaticPrefs::dom_largeAllocationHeader_enabled() ||
|
||||
aBrowsingContext->UseRemoteSubframes()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
|
||||
if (!httpChannel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoCString ignoredHeaderValue;
|
||||
nsresult rv =
|
||||
httpChannel->GetResponseHeader("Large-Allocation"_ns, ignoredHeaderValue);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// On all platforms other than win32, LargeAllocation is disabled by default,
|
||||
// and has to be force-enabled using `dom.largeAllocation.forceEnable`.
|
||||
#if defined(XP_WIN) && defined(_X86_)
|
||||
return true;
|
||||
#else
|
||||
return StaticPrefs::dom_largeAllocation_forceEnable();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns `true` if loads for this site should be isolated on a per-site basis.
|
||||
* If `aTopBC` is nullptr, this is being called to check if a shared or service
|
||||
* worker should be isolated.
|
||||
*/
|
||||
static bool ShouldIsolateSite(nsIPrincipal* aPrincipal,
|
||||
CanonicalBrowsingContext* aTopBC) {
|
||||
// non-content principals currently can't have webIsolated remote types
|
||||
// assigned to them, so should not be isolated.
|
||||
if (!aPrincipal->GetIsContentPrincipal()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME: This should contain logic to allow enabling/disabling whether a
|
||||
// particular site should be isolated for e.g. android, where we may want to
|
||||
// turn on/off isolating certain sites at runtime.
|
||||
if (aTopBC) {
|
||||
return aTopBC->UseRemoteSubframes();
|
||||
}
|
||||
return mozilla::FissionAutostart();
|
||||
}
|
||||
|
||||
enum class WebProcessType {
|
||||
Web,
|
||||
WebIsolated,
|
||||
WebCoopCoep,
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
Result<NavigationIsolationOptions, nsresult> IsolationOptionsForNavigation(
|
||||
CanonicalBrowsingContext* aTopBC, WindowGlobalParent* aParentWindow,
|
||||
nsIURI* aChannelCreationURI, nsIChannel* aChannel,
|
||||
const nsACString& aCurrentRemoteType, bool aHasCOOPMismatch,
|
||||
uint32_t aLoadStateLoadType, const Maybe<uint64_t>& aChannelId,
|
||||
const Maybe<nsCString>& aRemoteTypeOverride) {
|
||||
// Get the final principal, used to select which process to load into.
|
||||
nsCOMPtr<nsIPrincipal> resultPrincipal;
|
||||
nsresult rv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
|
||||
aChannel, getter_AddRefs(resultPrincipal));
|
||||
if (NS_FAILED(rv)) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Error,
|
||||
("failed to get channel result principal"));
|
||||
return Err(rv);
|
||||
}
|
||||
|
||||
MOZ_LOG(
|
||||
gProcessIsolationLog, LogLevel::Verbose,
|
||||
("IsolationOptionsForNavigation principal:%s, uri:%s, parentUri:%s",
|
||||
OriginString(resultPrincipal).get(),
|
||||
aChannelCreationURI->GetSpecOrDefault().get(),
|
||||
aParentWindow ? aParentWindow->GetDocumentURI()->GetSpecOrDefault().get()
|
||||
: ""));
|
||||
|
||||
// If we're loading a null principal, we can't easily make a process
|
||||
// selection decision off ot it. Instead, we'll use our null principal's
|
||||
// precursor principal to make process selection decisions.
|
||||
bool principalIsSandboxed = false;
|
||||
nsCOMPtr<nsIPrincipal> resultOrPrecursor(resultPrincipal);
|
||||
if (nsCOMPtr<nsIPrincipal> precursor =
|
||||
resultOrPrecursor->GetPrecursorPrincipal()) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
|
||||
("using null principal precursor origin %s",
|
||||
OriginString(precursor).get()));
|
||||
resultOrPrecursor = precursor;
|
||||
principalIsSandboxed = true;
|
||||
}
|
||||
|
||||
NavigationIsolationOptions options;
|
||||
options.mReplaceBrowsingContext = aHasCOOPMismatch;
|
||||
|
||||
// Check if this load has an explicit remote type override. This is used to
|
||||
// perform an about:blank load within a specific content process.
|
||||
if (aRemoteTypeOverride) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
NS_IsAboutBlank(aChannelCreationURI),
|
||||
"Should only have aRemoteTypeOverride for about:blank URIs");
|
||||
if (NS_WARN_IF(!resultPrincipal->GetIsNullPrincipal())) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Error,
|
||||
("invalid remote type override on non-null principal"));
|
||||
return Err(NS_ERROR_DOM_SECURITY_ERR);
|
||||
}
|
||||
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
|
||||
("using remote type override (%s) for load",
|
||||
aRemoteTypeOverride->get()));
|
||||
options.mRemoteType = *aRemoteTypeOverride;
|
||||
return options;
|
||||
}
|
||||
|
||||
// First, check for any special cases which should be handled using the
|
||||
// channel creation URI, and handle them.
|
||||
auto behavior = IsolationBehaviorForURI(aChannelCreationURI, aParentWindow,
|
||||
/* aForChannelCreationURI */ true);
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
|
||||
("Channel Creation Isolation Behavior: %s",
|
||||
IsolationBehaviorName(behavior)));
|
||||
|
||||
// In the about:reader special case, we want to fetch the relevant information
|
||||
// from the URI, an then treat it as a normal web content load.
|
||||
if (behavior == IsolationBehavior::AboutReader) {
|
||||
if (RefPtr<BasePrincipal> readerURIPrincipal = GetAboutReaderURLPrincipal(
|
||||
aChannelCreationURI, resultOrPrecursor->OriginAttributesRef())) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
|
||||
("using about:reader's url origin %s",
|
||||
OriginString(readerURIPrincipal).get()));
|
||||
resultOrPrecursor = readerURIPrincipal;
|
||||
}
|
||||
behavior = IsolationBehavior::WebContent;
|
||||
}
|
||||
|
||||
// If we're loading for a specific extension, we'll need to perform a
|
||||
// BCG-switching load to get our toplevel extension window in the correct
|
||||
// BrowsingContextGroup.
|
||||
if (auto* addonPolicy =
|
||||
BasePrincipal::Cast(resultOrPrecursor)->AddonPolicy()) {
|
||||
if (aParentWindow) {
|
||||
// As a temporary measure, extension iframes must be loaded within the
|
||||
// same process as their parent document.
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
|
||||
("Loading extension subframe in same process as parent"));
|
||||
behavior = IsolationBehavior::Inherit;
|
||||
} else {
|
||||
MOZ_LOG(
|
||||
gProcessIsolationLog, LogLevel::Verbose,
|
||||
("Found extension frame with addon policy. Will use group id %" PRIx64
|
||||
" (currentId: %" PRIx64 ")",
|
||||
addonPolicy->GetBrowsingContextGroupId(), aTopBC->Group()->Id()));
|
||||
behavior = IsolationBehavior::Extension;
|
||||
if (aTopBC->Group()->Id() != addonPolicy->GetBrowsingContextGroupId()) {
|
||||
options.mReplaceBrowsingContext = true;
|
||||
options.mSpecificGroupId = addonPolicy->GetBrowsingContextGroupId();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Do a second run of `GetIsolationBehavior`, this time using the
|
||||
// principal's URI to handle additional special cases such as the file and
|
||||
// privilegedmozilla content process.
|
||||
if (behavior == IsolationBehavior::WebContent) {
|
||||
if (resultOrPrecursor->IsSystemPrincipal()) {
|
||||
// We're loading something with a system principal which isn't caught in
|
||||
// one of our other edge-cases. If the load started in the parent process,
|
||||
// and it's safe for it to end in the parent process, we should finish the
|
||||
// load there.
|
||||
bool isUIResource = false;
|
||||
if (aCurrentRemoteType.IsEmpty() &&
|
||||
(aChannelCreationURI->SchemeIs("about") ||
|
||||
(NS_SUCCEEDED(NS_URIChainHasFlags(
|
||||
aChannelCreationURI, nsIProtocolHandler::URI_IS_UI_RESOURCE,
|
||||
&isUIResource)) &&
|
||||
isUIResource))) {
|
||||
behavior = IsolationBehavior::Parent;
|
||||
} else {
|
||||
// In general, we don't want to load documents with a system principal
|
||||
// in a content process, however we need to in some cases, such as when
|
||||
// loading blob: URLs created by system code. We can force the load to
|
||||
// finish in a content process instead.
|
||||
behavior = IsolationBehavior::ForceWebRemoteType;
|
||||
}
|
||||
} else if (nsCOMPtr<nsIURI> principalURI = resultOrPrecursor->GetURI()) {
|
||||
behavior = IsolationBehaviorForURI(principalURI, aParentWindow,
|
||||
/* aForChannelCreationURI */ false);
|
||||
}
|
||||
}
|
||||
|
||||
// If we're currently loaded in the extension process, and are going to switch
|
||||
// to some other remote type, make sure we leave the extension's BCG which we
|
||||
// may have entered earlier to separate extension and non-extension BCGs from
|
||||
// each-other.
|
||||
if (!aParentWindow && aCurrentRemoteType == EXTENSION_REMOTE_TYPE &&
|
||||
behavior != IsolationBehavior::Extension &&
|
||||
behavior != IsolationBehavior::Anywhere) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
|
||||
("Forcing BC replacement to leave extension BrowsingContextGroup "
|
||||
"%" PRIx64 " on navigation",
|
||||
aTopBC->Group()->Id()));
|
||||
options.mReplaceBrowsingContext = true;
|
||||
}
|
||||
|
||||
// We don't want to load documents with sandboxed null principals, like
|
||||
// `data:` URIs, in the parent process, even if they were created by a
|
||||
// document which would otherwise be loaded in the parent process.
|
||||
if (behavior == IsolationBehavior::Parent && principalIsSandboxed) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Debug,
|
||||
("Ensuring sandboxed null-principal load doesn't occur in the "
|
||||
"parent process"));
|
||||
behavior = IsolationBehavior::ForceWebRemoteType;
|
||||
}
|
||||
|
||||
MOZ_LOG(
|
||||
gProcessIsolationLog, LogLevel::Debug,
|
||||
("Using IsolationBehavior %s for %s (original uri %s)",
|
||||
IsolationBehaviorName(behavior), OriginString(resultOrPrecursor).get(),
|
||||
aChannelCreationURI->GetSpecOrDefault().get()));
|
||||
|
||||
// Check if we can put the previous document into the BFCache.
|
||||
if (mozilla::BFCacheInParent() && nsSHistory::GetMaxTotalViewers() > 0 &&
|
||||
!aParentWindow && !aTopBC->HadOriginalOpener() &&
|
||||
behavior != IsolationBehavior::Parent &&
|
||||
(ExtensionPolicyService::GetSingleton().UseRemoteExtensions() ||
|
||||
behavior != IsolationBehavior::Extension) &&
|
||||
!aCurrentRemoteType.IsEmpty() &&
|
||||
aTopBC->GetHasLoadedNonInitialDocument() &&
|
||||
(aLoadStateLoadType == LOAD_NORMAL ||
|
||||
aLoadStateLoadType == LOAD_HISTORY || aLoadStateLoadType == LOAD_LINK ||
|
||||
aLoadStateLoadType == LOAD_STOP_CONTENT ||
|
||||
aLoadStateLoadType == LOAD_STOP_CONTENT_AND_REPLACE) &&
|
||||
(!aTopBC->GetActiveSessionHistoryEntry() ||
|
||||
aTopBC->GetActiveSessionHistoryEntry()->GetSaveLayoutStateFlag())) {
|
||||
if (nsCOMPtr<nsIURI> uri = aTopBC->GetCurrentURI()) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
|
||||
("current uri: %s", uri->GetSpecOrDefault().get()));
|
||||
}
|
||||
options.mTryUseBFCache = aTopBC->AllowedInBFCache(aChannelId);
|
||||
if (options.mTryUseBFCache) {
|
||||
options.mReplaceBrowsingContext = true;
|
||||
options.mActiveSessionHistoryEntry =
|
||||
aTopBC->GetActiveSessionHistoryEntry();
|
||||
}
|
||||
}
|
||||
|
||||
// If the load has any special remote type handling, do so at this point.
|
||||
if (behavior != IsolationBehavior::WebContent) {
|
||||
switch (behavior) {
|
||||
case IsolationBehavior::ForceWebRemoteType:
|
||||
options.mRemoteType = WEB_REMOTE_TYPE;
|
||||
break;
|
||||
case IsolationBehavior::PrivilegedAbout:
|
||||
// The privileged about: content process cannot be disabled, as it
|
||||
// causes various actors to break.
|
||||
options.mRemoteType = PRIVILEGEDABOUT_REMOTE_TYPE;
|
||||
break;
|
||||
case IsolationBehavior::Extension:
|
||||
if (ExtensionPolicyService::GetSingleton().UseRemoteExtensions()) {
|
||||
options.mRemoteType = EXTENSION_REMOTE_TYPE;
|
||||
} else {
|
||||
options.mRemoteType = NOT_REMOTE_TYPE;
|
||||
}
|
||||
break;
|
||||
case IsolationBehavior::File:
|
||||
if (StaticPrefs::browser_tabs_remote_separateFileUriProcess()) {
|
||||
options.mRemoteType = FILE_REMOTE_TYPE;
|
||||
} else {
|
||||
options.mRemoteType = WEB_REMOTE_TYPE;
|
||||
}
|
||||
break;
|
||||
case IsolationBehavior::PrivilegedMozilla:
|
||||
options.mRemoteType = PRIVILEGEDMOZILLA_REMOTE_TYPE;
|
||||
break;
|
||||
case IsolationBehavior::Parent:
|
||||
options.mRemoteType = NOT_REMOTE_TYPE;
|
||||
break;
|
||||
case IsolationBehavior::Anywhere:
|
||||
options.mRemoteType = aCurrentRemoteType;
|
||||
break;
|
||||
case IsolationBehavior::Inherit:
|
||||
MOZ_DIAGNOSTIC_ASSERT(aParentWindow);
|
||||
options.mRemoteType = aParentWindow->GetRemoteType();
|
||||
break;
|
||||
|
||||
case IsolationBehavior::WebContent:
|
||||
case IsolationBehavior::AboutReader:
|
||||
MOZ_ASSERT_UNREACHABLE();
|
||||
return Err(NS_ERROR_UNEXPECTED);
|
||||
|
||||
case IsolationBehavior::Error:
|
||||
return Err(NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
|
||||
if (options.mRemoteType != aCurrentRemoteType &&
|
||||
(options.mRemoteType.IsEmpty() || aCurrentRemoteType.IsEmpty())) {
|
||||
options.mReplaceBrowsingContext = true;
|
||||
}
|
||||
|
||||
MOZ_LOG(
|
||||
gProcessIsolationLog, LogLevel::Debug,
|
||||
("Selecting specific remote type (%s) due to a special case isolation "
|
||||
"behavior %s",
|
||||
options.mRemoteType.get(), IsolationBehaviorName(behavior)));
|
||||
return options;
|
||||
}
|
||||
|
||||
// At this point we're definitely not going to be loading in the parent
|
||||
// process anymore, so we're definitely going to be replacing BrowsingContext
|
||||
// if we're in the parent process.
|
||||
if (aCurrentRemoteType.IsEmpty()) {
|
||||
MOZ_ASSERT(!aParentWindow);
|
||||
options.mReplaceBrowsingContext = true;
|
||||
}
|
||||
|
||||
// Handle the deprecated Large-Allocation header.
|
||||
if (!aTopBC->UseRemoteSubframes()) {
|
||||
MOZ_ASSERT(!aParentWindow,
|
||||
"subframe switch when `UseRemoteSubframes()` is false?");
|
||||
bool singleToplevel = aTopBC->Group()->Toplevels().Length() == 1;
|
||||
bool isLargeAllocLoad = IsLargeAllocationLoad(aTopBC, aChannel);
|
||||
// If we're starting a large-alloc load and have no opener relationships,
|
||||
// force the load to finish in the large-allocation remote type.
|
||||
if (isLargeAllocLoad && singleToplevel) {
|
||||
options.mRemoteType = LARGE_ALLOCATION_REMOTE_TYPE;
|
||||
options.mReplaceBrowsingContext = true;
|
||||
return options;
|
||||
}
|
||||
if (aCurrentRemoteType == LARGE_ALLOCATION_REMOTE_TYPE) {
|
||||
// If we're doing a non-large-alloc load, we may still need to finish in
|
||||
// the large-allocation remote type if we have opener relationships.
|
||||
if (!singleToplevel) {
|
||||
options.mRemoteType = LARGE_ALLOCATION_REMOTE_TYPE;
|
||||
return options;
|
||||
}
|
||||
options.mReplaceBrowsingContext = true;
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoCString siteOriginNoSuffix;
|
||||
MOZ_TRY(resultOrPrecursor->GetSiteOriginNoSuffix(siteOriginNoSuffix));
|
||||
|
||||
// Check if we've already loaded a document with the given principal in some
|
||||
// content process. We want to finish the load in the same process in that
|
||||
// case.
|
||||
//
|
||||
// The exception to that is with extension loads and the system principal,
|
||||
// where we may have multiple documents with the same principal in different
|
||||
// processes. Those have been handled above, and will not be reaching here.
|
||||
//
|
||||
// If we're doing a replace load, we won't be staying in the same
|
||||
// BrowsingContext, so ignore this step.
|
||||
if (!options.mReplaceBrowsingContext) {
|
||||
// Helper for efficiently determining if a given origin is same-site. This
|
||||
// will attempt to do a fast equality check, and will only fall back to
|
||||
// computing the site-origin for content principals.
|
||||
auto principalIsSameSite = [&](nsIPrincipal* aDocumentPrincipal) -> bool {
|
||||
// If we're working with a null principal with a precursor, compare
|
||||
// precursors, as `resultOrPrecursor` has already been stripped to its
|
||||
// precursor.
|
||||
nsCOMPtr<nsIPrincipal> documentPrincipal(aDocumentPrincipal);
|
||||
if (nsCOMPtr<nsIPrincipal> precursor =
|
||||
documentPrincipal->GetPrecursorPrincipal()) {
|
||||
documentPrincipal = precursor;
|
||||
}
|
||||
|
||||
// First, attempt to use `Equals` to compare principals, and if that
|
||||
// fails compare siteOrigins. Only compare siteOrigin for content
|
||||
// principals, as non-content principals will never have siteOrigin !=
|
||||
// origin.
|
||||
nsAutoCString documentSiteOrigin;
|
||||
return resultOrPrecursor->Equals(documentPrincipal) ||
|
||||
(documentPrincipal->GetIsContentPrincipal() &&
|
||||
resultOrPrecursor->GetIsContentPrincipal() &&
|
||||
NS_SUCCEEDED(documentPrincipal->GetSiteOriginNoSuffix(
|
||||
documentSiteOrigin)) &&
|
||||
documentSiteOrigin == siteOriginNoSuffix);
|
||||
};
|
||||
|
||||
// XXX: Consider also checking in-flight process switches to see if any have
|
||||
// matching principals?
|
||||
AutoTArray<RefPtr<BrowsingContext>, 8> contexts;
|
||||
aTopBC->Group()->GetToplevels(contexts);
|
||||
while (!contexts.IsEmpty()) {
|
||||
auto bc = contexts.PopLastElement();
|
||||
for (const auto& wc : bc->GetWindowContexts()) {
|
||||
WindowGlobalParent* wgp = wc->Canonical();
|
||||
|
||||
// Check if this WindowGlobalParent has the given resultPrincipal, and
|
||||
// if it does, we need to load in that process.
|
||||
if (!wgp->GetRemoteType().IsEmpty() &&
|
||||
principalIsSameSite(wgp->DocumentPrincipal())) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Debug,
|
||||
("Found existing frame with matching principal "
|
||||
"(remoteType:(%s), origin:%s)",
|
||||
PromiseFlatCString(wgp->GetRemoteType()).get(),
|
||||
OriginString(wgp->DocumentPrincipal()).get()));
|
||||
options.mRemoteType = wgp->GetRemoteType();
|
||||
return options;
|
||||
}
|
||||
|
||||
// Also enumerate over this WindowContexts' subframes.
|
||||
contexts.AppendElements(wc->Children());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsAutoCString originSuffix;
|
||||
OriginAttributes attrs = resultOrPrecursor->OriginAttributesRef();
|
||||
attrs.StripAttributes(OriginAttributes::STRIP_FIRST_PARTY_DOMAIN |
|
||||
OriginAttributes::STRIP_PARITION_KEY);
|
||||
attrs.CreateSuffix(originSuffix);
|
||||
|
||||
WebProcessType webProcessType = WebProcessType::Web;
|
||||
if (ShouldIsolateSite(resultOrPrecursor, aTopBC)) {
|
||||
webProcessType = WebProcessType::WebIsolated;
|
||||
}
|
||||
|
||||
// Check if we should be loading in a webCOOP+COEP remote type due to our COOP
|
||||
// status.
|
||||
nsILoadInfo::CrossOriginOpenerPolicy coop =
|
||||
nsILoadInfo::OPENER_POLICY_UNSAFE_NONE;
|
||||
if (aParentWindow) {
|
||||
coop = aTopBC->GetOpenerPolicy();
|
||||
} else if (nsCOMPtr<nsIHttpChannelInternal> httpChannel =
|
||||
do_QueryInterface(aChannel)) {
|
||||
MOZ_ALWAYS_SUCCEEDS(httpChannel->GetCrossOriginOpenerPolicy(&coop));
|
||||
}
|
||||
if (coop ==
|
||||
nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP) {
|
||||
webProcessType = WebProcessType::WebCoopCoep;
|
||||
}
|
||||
|
||||
switch (webProcessType) {
|
||||
case WebProcessType::Web:
|
||||
options.mRemoteType = WEB_REMOTE_TYPE;
|
||||
break;
|
||||
case WebProcessType::WebIsolated:
|
||||
options.mRemoteType =
|
||||
FISSION_WEB_REMOTE_TYPE "="_ns + siteOriginNoSuffix + originSuffix;
|
||||
break;
|
||||
case WebProcessType::WebCoopCoep:
|
||||
options.mRemoteType =
|
||||
WITH_COOP_COEP_REMOTE_TYPE "="_ns + siteOriginNoSuffix + originSuffix;
|
||||
break;
|
||||
}
|
||||
return options;
|
||||
}
|
||||
|
||||
} // namespace mozilla::dom
|
|
@ -1,58 +0,0 @@
|
|||
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
||||
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
* You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
#ifndef mozilla_dom_ProcessIsolation_h
|
||||
#define mozilla_dom_ProcessIsolation_h
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "mozilla/Logging.h"
|
||||
#include "mozilla/dom/RemoteType.h"
|
||||
#include "mozilla/dom/SessionHistoryEntry.h"
|
||||
#include "nsString.h"
|
||||
|
||||
class nsIURI;
|
||||
class nsIPrincipal;
|
||||
|
||||
namespace mozilla::dom {
|
||||
|
||||
class CanonicalBrowsingContext;
|
||||
class WindowGlobalParent;
|
||||
|
||||
extern mozilla::LazyLogModule gProcessIsolationLog;
|
||||
|
||||
// NavigationIsolationOptions is passed through the methods to store the state
|
||||
// of the possible process and/or browsing context change.
|
||||
struct NavigationIsolationOptions {
|
||||
nsCString mRemoteType;
|
||||
bool mReplaceBrowsingContext = false;
|
||||
uint64_t mSpecificGroupId = 0;
|
||||
bool mTryUseBFCache = false;
|
||||
RefPtr<SessionHistoryEntry> mActiveSessionHistoryEntry;
|
||||
};
|
||||
|
||||
/**
|
||||
* Given a specific channel, determines which process the navigation should
|
||||
* complete in, and whether or not to perform a BrowsingContext-replace load
|
||||
* or enter the BFCache.
|
||||
*
|
||||
* This method will always return a `NavigationIsolationOptions` even if the
|
||||
* current remote type is compatible. Compatibility with the current process
|
||||
* should be checked at the call-site. An error should only be returned in
|
||||
* exceptional circumstances, and should lead to the load being cancelled.
|
||||
*
|
||||
* This method is only intended for use with document navigations.
|
||||
*/
|
||||
Result<NavigationIsolationOptions, nsresult> IsolationOptionsForNavigation(
|
||||
CanonicalBrowsingContext* aTopBC, WindowGlobalParent* aParentWindow,
|
||||
nsIURI* aChannelCreationURI, nsIChannel* aChannel,
|
||||
const nsACString& aCurrentRemoteType, bool aHasCOOPMismatch,
|
||||
uint32_t aLoadStateLoadType, const Maybe<uint64_t>& aChannelId,
|
||||
const Maybe<nsCString>& aRemoteTypeOverride);
|
||||
|
||||
} // namespace mozilla::dom
|
||||
|
||||
#endif
|
|
@ -15,17 +15,14 @@
|
|||
// ContentChild:RecvRemoteType. Add your value there too or it will be called
|
||||
// "Web Content".
|
||||
#define PREALLOC_REMOTE_TYPE "prealloc"_ns
|
||||
#define WEB_REMOTE_TYPE "web"_ns
|
||||
#define DEFAULT_REMOTE_TYPE "web"_ns
|
||||
#define FILE_REMOTE_TYPE "file"_ns
|
||||
#define EXTENSION_REMOTE_TYPE "extension"_ns
|
||||
#define PRIVILEGEDABOUT_REMOTE_TYPE "privilegedabout"_ns
|
||||
#define PRIVILEGEDMOZILLA_REMOTE_TYPE "privilegedmozilla"_ns
|
||||
|
||||
#define DEFAULT_REMOTE_TYPE WEB_REMOTE_TYPE
|
||||
|
||||
// These must start with the WEB_REMOTE_TYPE above.
|
||||
// These must start with the DEFAULT_REMOTE_TYPE above.
|
||||
#define FISSION_WEB_REMOTE_TYPE "webIsolated"_ns
|
||||
#define WITH_COOP_COEP_REMOTE_TYPE "webCOOP+COEP"_ns
|
||||
#define WITH_COOP_COEP_REMOTE_TYPE_PREFIX "webCOOP+COEP="_ns
|
||||
#define LARGE_ALLOCATION_REMOTE_TYPE "webLargeAllocation"_ns
|
||||
|
||||
|
|
|
@ -58,7 +58,6 @@ EXPORTS.mozilla.dom += [
|
|||
"NativeThreadId.h",
|
||||
"PermissionMessageUtils.h",
|
||||
"ProcessActor.h",
|
||||
"ProcessIsolation.h",
|
||||
"PropertyBagUtils.h",
|
||||
"ReferrerInfoUtils.h",
|
||||
"RefMessageBodyService.h",
|
||||
|
@ -112,7 +111,6 @@ UNIFIED_SOURCES += [
|
|||
"PermissionMessageUtils.cpp",
|
||||
"PreallocatedProcessManager.cpp",
|
||||
"ProcessActor.cpp",
|
||||
"ProcessIsolation.cpp",
|
||||
"ProcessPriorityManager.cpp",
|
||||
"PropertyBagUtils.cpp",
|
||||
"ReferrerInfoUtils.cpp",
|
||||
|
|
|
@ -79,14 +79,4 @@ dictionary LoadURIOptions {
|
|||
* when initiating the load.
|
||||
*/
|
||||
long cancelContentJSEpoch = 0;
|
||||
|
||||
/**
|
||||
* If this is passed, it will control which remote type is used to finish this
|
||||
* load. Ignored for non-`about:` loads.
|
||||
*
|
||||
* NOTE: This is _NOT_ defaulted to `null`, as `null` is the value for
|
||||
* `NOT_REMOTE_TYPE`, and we need to determine the difference between no
|
||||
* `remoteTypeOverride` and a `remoteTypeOverride` of `NOT_REMOTE_TYPE`.
|
||||
*/
|
||||
UTF8String? remoteTypeOverride;
|
||||
};
|
||||
|
|
|
@ -653,3 +653,4 @@ pref("browser.tabs.remote.enforceRemoteTypeRestrictions", false);
|
|||
|
||||
// Allow Web Authentication
|
||||
pref("security.webauth.webauthn_enable_android_fido2", true);
|
||||
pref("browser.tabs.remote.separatePrivilegedMozillaWebContentProcess", false);
|
||||
|
|
|
@ -1270,13 +1270,6 @@
|
|||
value: false
|
||||
mirror: always
|
||||
|
||||
# Testing-only pref which makes data: URIs be loaded in a "web" content process
|
||||
# instead of within a process based on the URI's loader.
|
||||
- name: browser.tabs.remote.dataUriInDefaultWebProcess
|
||||
type: bool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
- name: browser.tabs.remote.desktopbehavior
|
||||
type: bool
|
||||
value: false
|
||||
|
@ -1320,14 +1313,6 @@
|
|||
#endif
|
||||
mirror: always
|
||||
|
||||
# Pref to control whether we use a separate privileged content process
|
||||
# for certain mozilla webpages (which are listed in the pref
|
||||
# browser.tabs.remote.separatedMozillaDomains).
|
||||
- name: browser.tabs.remote.separatePrivilegedMozillaWebContentProcess
|
||||
type: bool
|
||||
value: false
|
||||
mirror: always
|
||||
|
||||
# When this pref is enabled, opaque response is only allowed to enter the
|
||||
# content process if it's a response for media (audio, image, video), CSS, or
|
||||
# JavaScript.
|
||||
|
|
|
@ -2476,6 +2476,10 @@ pref("dom.ipc.processCount.webLargeAllocation", 10);
|
|||
// Disable e10s for Gecko by default. This is overridden in firefox.js.
|
||||
pref("browser.tabs.remote.autostart", false);
|
||||
|
||||
// Pref to control whether we put all data: uri's in the default
|
||||
// web process when running with fission.
|
||||
pref("browser.tabs.remote.dataUriInDefaultWebProcess", false);
|
||||
|
||||
// This pref will cause assertions when a remoteType triggers a process switch
|
||||
// to a new remoteType it should not be able to trigger.
|
||||
pref("browser.tabs.remote.enforceRemoteTypeRestrictions", false);
|
||||
|
@ -2485,6 +2489,10 @@ pref("browser.tabs.remote.enforceRemoteTypeRestrictions", false);
|
|||
// types of privileged content processes, each with different privileges.
|
||||
pref("browser.tabs.remote.separatePrivilegedContentProcess", false);
|
||||
|
||||
// Pref to control whether we use a separate privileged content process
|
||||
// for certain mozilla webpages (which are listed in the following pref).
|
||||
pref("browser.tabs.remote.separatePrivilegedMozillaWebContentProcess", false);
|
||||
|
||||
// The domains we will isolate into the Mozilla Content Process. Comma-separated
|
||||
// full domains: any subdomains of the domains listed will also be allowed.
|
||||
pref("browser.tabs.remote.separatedMozillaDomains", "addons.mozilla.org,accounts.firefox.com");
|
||||
|
|
|
@ -36,9 +36,6 @@ bool DocumentChannelParent::Init(dom::CanonicalBrowsingContext* aContext,
|
|||
LOG(("DocumentChannelParent Init [this=%p, uri=%s]", this,
|
||||
loadState->URI()->GetSpecOrDefault().get()));
|
||||
|
||||
ContentParent* contentParent =
|
||||
static_cast<ContentParent*>(Manager()->Manager());
|
||||
|
||||
RefPtr<DocumentLoadListener::OpenPromise> promise;
|
||||
if (loadState->GetChannelInitialized()) {
|
||||
promise = DocumentLoadListener::ClaimParentLoad(
|
||||
|
@ -65,7 +62,7 @@ bool DocumentChannelParent::Init(dom::CanonicalBrowsingContext* aContext,
|
|||
loadState, aArgs.cacheKey(), Some(aArgs.channelId()),
|
||||
aArgs.asyncOpenTime(), aArgs.timing().refOr(nullptr),
|
||||
std::move(clientInfo), Some(docArgs.uriModified()),
|
||||
Some(docArgs.isXFOError()), contentParent, &rv);
|
||||
Some(docArgs.isXFOError()), IProtocol::OtherPid(), &rv);
|
||||
} else {
|
||||
const ObjectCreationArgs& objectArgs = aArgs.elementCreationArgs();
|
||||
|
||||
|
@ -74,7 +71,7 @@ bool DocumentChannelParent::Init(dom::CanonicalBrowsingContext* aContext,
|
|||
aArgs.asyncOpenTime(), aArgs.timing().refOr(nullptr),
|
||||
std::move(clientInfo), objectArgs.embedderInnerWindowId(),
|
||||
objectArgs.loadFlags(), objectArgs.contentPolicyType(),
|
||||
objectArgs.isUrgentStart(), contentParent,
|
||||
objectArgs.isUrgentStart(), IProtocol::OtherPid(),
|
||||
this /* ObjectUpgradeHandler */, &rv);
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
#include "mozilla/dom/ClientChannelHelper.h"
|
||||
#include "mozilla/dom/ContentParent.h"
|
||||
#include "mozilla/dom/ContentProcessManager.h"
|
||||
#include "mozilla/dom/ProcessIsolation.h"
|
||||
#include "mozilla/dom/SessionHistoryEntry.h"
|
||||
#include "mozilla/dom/WindowGlobalParent.h"
|
||||
#include "mozilla/dom/ipc/IdType.h"
|
||||
|
@ -37,6 +36,7 @@
|
|||
#include "nsExternalHelperAppService.h"
|
||||
#include "nsHttpChannel.h"
|
||||
#include "nsIBrowser.h"
|
||||
#include "nsIE10SUtils.h"
|
||||
#include "nsIHttpChannelInternal.h"
|
||||
#include "nsIStreamConverterService.h"
|
||||
#include "nsIViewSourceChannel.h"
|
||||
|
@ -79,10 +79,6 @@ using namespace mozilla::dom;
|
|||
namespace mozilla {
|
||||
namespace net {
|
||||
|
||||
static ContentParentId GetContentProcessId(ContentParent* aContentParent) {
|
||||
return aContentParent ? aContentParent->ChildID() : ContentParentId{0};
|
||||
}
|
||||
|
||||
static void SetNeedToAddURIVisit(nsIChannel* aChannel,
|
||||
bool aNeedToAddURIVisit) {
|
||||
nsCOMPtr<nsIWritablePropertyBag2> props(do_QueryInterface(aChannel));
|
||||
|
@ -520,8 +516,8 @@ auto DocumentLoadListener::Open(nsDocShellLoadState* aLoadState,
|
|||
const TimeStamp& aAsyncOpenTime,
|
||||
nsDOMNavigationTiming* aTiming,
|
||||
Maybe<ClientInfo>&& aInfo, bool aUrgentStart,
|
||||
dom::ContentParent* aContentParent,
|
||||
nsresult* aRv) -> RefPtr<OpenPromise> {
|
||||
base::ProcessId aPid, nsresult* aRv)
|
||||
-> RefPtr<OpenPromise> {
|
||||
auto* loadingContext = GetLoadingBrowsingContext();
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT_IF(loadingContext->GetParent(),
|
||||
|
@ -542,44 +538,6 @@ auto DocumentLoadListener::Open(nsDocShellLoadState* aLoadState,
|
|||
}
|
||||
}
|
||||
|
||||
if (aLoadState->GetRemoteTypeOverride()) {
|
||||
if (!mIsDocumentLoad || !NS_IsAboutBlank(aLoadState->URI()) ||
|
||||
!loadingContext->IsTopContent()) {
|
||||
LOG(
|
||||
("DocumentLoadListener::Open with invalid remoteTypeOverride "
|
||||
"[this=%p]",
|
||||
this));
|
||||
*aRv = NS_ERROR_DOM_SECURITY_ERR;
|
||||
mParentChannelListener = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
mRemoteTypeOverride = aLoadState->GetRemoteTypeOverride();
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(!loadingContext->IsOwnedByProcess(
|
||||
GetContentProcessId(aContentParent)))) {
|
||||
LOG(
|
||||
("DocumentLoadListener::Open called from non-current content process "
|
||||
"[this=%p, current=%" PRIu64 ", caller=%" PRIu64 "]",
|
||||
this, loadingContext->OwnerProcessId(),
|
||||
uint64_t(GetContentProcessId(aContentParent))));
|
||||
*aRv = NS_BINDING_ABORTED;
|
||||
mParentChannelListener = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (mIsDocumentLoad && loadingContext->IsContent() &&
|
||||
NS_WARN_IF(loadingContext->IsReplaced())) {
|
||||
LOG(
|
||||
("DocumentLoadListener::Open called from replaced BrowsingContext "
|
||||
"[this=%p, browserid=%" PRIx64 ", bcid=%" PRIx64 "]",
|
||||
this, loadingContext->BrowserId(), loadingContext->Id()));
|
||||
*aRv = NS_BINDING_ABORTED;
|
||||
mParentChannelListener = nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
if (!nsDocShell::CreateAndConfigureRealChannelForLoadState(
|
||||
loadingContext, aLoadState, aLoadInfo, mParentChannelListener,
|
||||
nullptr, attrs, aLoadFlags, aCacheKey, *aRv,
|
||||
|
@ -739,7 +697,7 @@ auto DocumentLoadListener::Open(nsDocShellLoadState* aLoadState,
|
|||
// after opening the document channel we have to kick off countermeasures.
|
||||
nsHTTPSOnlyUtils::PotentiallyFireHttpRequestToShortenTimout(this);
|
||||
|
||||
mContentParent = aContentParent;
|
||||
mOtherPid = aPid;
|
||||
mChannelCreationURI = aLoadState->URI();
|
||||
mLoadStateExternalLoadFlags = aLoadState->LoadFlags();
|
||||
mLoadStateInternalLoadFlags = aLoadState->InternalLoadFlags();
|
||||
|
@ -770,8 +728,8 @@ auto DocumentLoadListener::OpenDocument(
|
|||
nsDocShellLoadState* aLoadState, uint32_t aCacheKey,
|
||||
const Maybe<uint64_t>& aChannelId, const TimeStamp& aAsyncOpenTime,
|
||||
nsDOMNavigationTiming* aTiming, Maybe<dom::ClientInfo>&& aInfo,
|
||||
Maybe<bool> aUriModified, Maybe<bool> aIsXFOError,
|
||||
dom::ContentParent* aContentParent, nsresult* aRv) -> RefPtr<OpenPromise> {
|
||||
Maybe<bool> aUriModified, Maybe<bool> aIsXFOError, base::ProcessId aPid,
|
||||
nsresult* aRv) -> RefPtr<OpenPromise> {
|
||||
LOG(("DocumentLoadListener [%p] OpenDocument [uri=%s]", this,
|
||||
aLoadState->URI()->GetSpecOrDefault().get()));
|
||||
|
||||
|
@ -790,8 +748,7 @@ auto DocumentLoadListener::OpenDocument(
|
|||
browsingContext, std::move(aUriModified), std::move(aIsXFOError));
|
||||
|
||||
return Open(aLoadState, loadInfo, loadFlags, aCacheKey, aChannelId,
|
||||
aAsyncOpenTime, aTiming, std::move(aInfo), false, aContentParent,
|
||||
aRv);
|
||||
aAsyncOpenTime, aTiming, std::move(aInfo), false, aPid, aRv);
|
||||
}
|
||||
|
||||
auto DocumentLoadListener::OpenObject(
|
||||
|
@ -800,9 +757,8 @@ auto DocumentLoadListener::OpenObject(
|
|||
nsDOMNavigationTiming* aTiming, Maybe<dom::ClientInfo>&& aInfo,
|
||||
uint64_t aInnerWindowId, nsLoadFlags aLoadFlags,
|
||||
nsContentPolicyType aContentPolicyType, bool aUrgentStart,
|
||||
dom::ContentParent* aContentParent,
|
||||
ObjectUpgradeHandler* aObjectUpgradeHandler, nsresult* aRv)
|
||||
-> RefPtr<OpenPromise> {
|
||||
base::ProcessId aPid, ObjectUpgradeHandler* aObjectUpgradeHandler,
|
||||
nsresult* aRv) -> RefPtr<OpenPromise> {
|
||||
LOG(("DocumentLoadListener [%p] OpenObject [uri=%s]", this,
|
||||
aLoadState->URI()->GetSpecOrDefault().get()));
|
||||
|
||||
|
@ -816,8 +772,8 @@ auto DocumentLoadListener::OpenObject(
|
|||
mObjectUpgradeHandler = aObjectUpgradeHandler;
|
||||
|
||||
return Open(aLoadState, loadInfo, aLoadFlags, aCacheKey, aChannelId,
|
||||
aAsyncOpenTime, aTiming, std::move(aInfo), aUrgentStart,
|
||||
aContentParent, aRv);
|
||||
aAsyncOpenTime, aTiming, std::move(aInfo), aUrgentStart, aPid,
|
||||
aRv);
|
||||
}
|
||||
|
||||
auto DocumentLoadListener::OpenInParent(nsDocShellLoadState* aLoadState,
|
||||
|
@ -896,11 +852,7 @@ auto DocumentLoadListener::OpenInParent(nsDocShellLoadState* aLoadState,
|
|||
nsresult rv;
|
||||
return Open(loadState, loadInfo, loadFlags, cacheKey, channelId,
|
||||
TimeStamp::Now(), timing, std::move(initialClientInfo), false,
|
||||
browsingContext->GetContentParent(), &rv);
|
||||
}
|
||||
|
||||
base::ProcessId DocumentLoadListener::OtherPid() const {
|
||||
return mContentParent ? mContentParent->OtherPid() : base::ProcessId{0};
|
||||
browsingContext->GetContentParent()->OtherPid(), &rv);
|
||||
}
|
||||
|
||||
void DocumentLoadListener::FireStateChange(uint32_t aStateFlags,
|
||||
|
@ -1473,28 +1425,52 @@ void DocumentLoadListener::SerializeRedirectData(
|
|||
}
|
||||
}
|
||||
|
||||
static bool IsLargeAllocationLoad(CanonicalBrowsingContext* aBrowsingContext,
|
||||
nsIChannel* aChannel) {
|
||||
if (!StaticPrefs::dom_largeAllocationHeader_enabled() ||
|
||||
aBrowsingContext->UseRemoteSubframes()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIHttpChannel> httpChannel = do_QueryInterface(aChannel);
|
||||
if (!httpChannel) {
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoCString ignoredHeaderValue;
|
||||
nsresult rv =
|
||||
httpChannel->GetResponseHeader("Large-Allocation"_ns, ignoredHeaderValue);
|
||||
if (NS_FAILED(rv)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// On all platforms other than win32, LargeAllocation is disabled by default,
|
||||
// and has to be force-enabled using `dom.largeAllocation.forceEnable`.
|
||||
#if defined(XP_WIN) && defined(_X86_)
|
||||
return true;
|
||||
#else
|
||||
return StaticPrefs::dom_largeAllocation_forceEnable();
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool ContextCanProcessSwitch(CanonicalBrowsingContext* aBrowsingContext,
|
||||
WindowGlobalParent* aParentWindow) {
|
||||
if (NS_WARN_IF(!aBrowsingContext)) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Warning,
|
||||
("Process Switch Abort: no browsing context"));
|
||||
LOG(("Process Switch Abort: no browsing context"));
|
||||
return false;
|
||||
}
|
||||
if (!aBrowsingContext->IsContent()) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Warning,
|
||||
("Process Switch Abort: non-content browsing context"));
|
||||
LOG(("Process Switch Abort: non-content browsing context"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aParentWindow && !aBrowsingContext->UseRemoteSubframes()) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Warning,
|
||||
("Process Switch Abort: remote subframes disabled"));
|
||||
LOG(("Process Switch Abort: remote subframes disabled"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (aParentWindow && aParentWindow->IsInProcess()) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Warning,
|
||||
("Process Switch Abort: Subframe with in-process parent"));
|
||||
LOG(("Process Switch Abort: Subframe with in-process parent"));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1502,14 +1478,12 @@ static bool ContextCanProcessSwitch(CanonicalBrowsingContext* aBrowsingContext,
|
|||
// <browser> element.
|
||||
Element* browserElement = aBrowsingContext->Top()->GetEmbedderElement();
|
||||
if (!browserElement) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Warning,
|
||||
("Process Switch Abort: cannot get embedder element"));
|
||||
LOG(("Process Switch Abort: cannot get embedder element"));
|
||||
return false;
|
||||
}
|
||||
nsCOMPtr<nsIBrowser> browser = browserElement->AsBrowser();
|
||||
if (!browser) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Warning,
|
||||
("Process Switch Abort: not loaded within nsIBrowser"));
|
||||
LOG(("Process Switch Abort: not loaded within nsIBrowser"));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1519,22 +1493,19 @@ static bool ContextCanProcessSwitch(CanonicalBrowsingContext* aBrowsingContext,
|
|||
if (NS_FAILED(rv)) {
|
||||
MOZ_ASSERT_UNREACHABLE(
|
||||
"nsIBrowser::GetProcessSwitchBehavior shouldn't fail");
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Warning,
|
||||
("Process Switch Abort: failed to get process switch behavior"));
|
||||
LOG(("Process Switch Abort: failed to get process switch behavior"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the process switch we're considering is disabled by the
|
||||
// <browser>'s process behavior.
|
||||
if (processBehavior == nsIBrowser::PROCESS_BEHAVIOR_DISABLED) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Warning,
|
||||
("Process Switch Abort: switch disabled by <browser>"));
|
||||
LOG(("Process Switch Abort: switch disabled by <browser>"));
|
||||
return false;
|
||||
}
|
||||
if (!aParentWindow &&
|
||||
processBehavior == nsIBrowser::PROCESS_BEHAVIOR_SUBFRAME_ONLY) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Warning,
|
||||
("Process Switch Abort: toplevel switch disabled by <browser>"));
|
||||
LOG(("Process Switch Abort: toplevel switch disabled by <browser>"));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1550,18 +1521,13 @@ bool DocumentLoadListener::MaybeTriggerProcessSwitch(
|
|||
MOZ_DIAGNOSTIC_ASSERT(mParentChannelListener);
|
||||
MOZ_DIAGNOSTIC_ASSERT(aWillSwitchToRemote);
|
||||
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
|
||||
("DocumentLoadListener MaybeTriggerProcessSwitch [this=%p, uri=%s, "
|
||||
"browserid=%" PRIx64 "]",
|
||||
this, mChannelCreationURI->GetSpecOrDefault().get(),
|
||||
GetLoadingBrowsingContext()->Top()->BrowserId()));
|
||||
LOG(("DocumentLoadListener MaybeTriggerProcessSwitch [this=%p]", this));
|
||||
|
||||
// If we're doing an <object>/<embed> load, we may be doing a document load at
|
||||
// this point. We never need to do a process switch for a non-document
|
||||
// <object> or <embed> load.
|
||||
if (!mIsDocumentLoad && !mChannel->IsDocument()) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
|
||||
("Process Switch Abort: non-document load"));
|
||||
LOG(("Process Switch Abort: non-document load"));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1580,77 +1546,173 @@ bool DocumentLoadListener::MaybeTriggerProcessSwitch(
|
|||
return false;
|
||||
}
|
||||
|
||||
if (!browsingContext->IsOwnedByProcess(GetContentProcessId(mContentParent))) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Error,
|
||||
("Process Switch Abort: context no longer owned by creator"));
|
||||
Cancel(NS_BINDING_ABORTED);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (browsingContext->IsReplaced()) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Warning,
|
||||
("Process Switch Abort: replaced browsing context"));
|
||||
Cancel(NS_BINDING_ABORTED);
|
||||
// Get the final principal, used to select which process to load into.
|
||||
nsCOMPtr<nsIPrincipal> resultPrincipal;
|
||||
nsresult rv = nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
|
||||
mChannel, getter_AddRefs(resultPrincipal));
|
||||
if (NS_FAILED(rv)) {
|
||||
LOG(("Process Switch Abort: failed to get channel result principal"));
|
||||
return false;
|
||||
}
|
||||
|
||||
nsAutoCString currentRemoteType(NOT_REMOTE_TYPE);
|
||||
if (mContentParent) {
|
||||
currentRemoteType = mContentParent->GetRemoteType();
|
||||
if (RefPtr<ContentParent> contentParent =
|
||||
browsingContext->GetContentParent()) {
|
||||
currentRemoteType = contentParent->GetRemoteType();
|
||||
}
|
||||
MOZ_ASSERT_IF(currentRemoteType.IsEmpty(), !OtherPid());
|
||||
|
||||
// Determine what type of content process this load should finish in.
|
||||
nsAutoCString preferredRemoteType(currentRemoteType);
|
||||
RemotenessChangeOptions options;
|
||||
|
||||
// Update the preferred final process for our load based on the
|
||||
// Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy headers.
|
||||
{
|
||||
bool isCOOPSwitch = HasCrossOriginOpenerPolicyMismatch();
|
||||
options.mReplaceBrowsingContext |= isCOOPSwitch;
|
||||
|
||||
// Determine our COOP status, which will be used to determine our preferred
|
||||
// remote type.
|
||||
nsILoadInfo::CrossOriginOpenerPolicy coop =
|
||||
nsILoadInfo::OPENER_POLICY_UNSAFE_NONE;
|
||||
if (parentWindow) {
|
||||
coop = browsingContext->Top()->GetOpenerPolicy();
|
||||
} else if (nsCOMPtr<nsIHttpChannelInternal> httpChannel =
|
||||
do_QueryInterface(mChannel)) {
|
||||
MOZ_ALWAYS_SUCCEEDS(httpChannel->GetCrossOriginOpenerPolicy(&coop));
|
||||
}
|
||||
|
||||
auto optionsResult = IsolationOptionsForNavigation(
|
||||
browsingContext->Top(), parentWindow, mChannelCreationURI, mChannel,
|
||||
currentRemoteType, HasCrossOriginOpenerPolicyMismatch(),
|
||||
mLoadStateLoadType, mDocumentChannelId, mRemoteTypeOverride);
|
||||
if (optionsResult.isErr()) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Error,
|
||||
("Process Switch Abort: CheckIsolationForNavigation Failed with %s",
|
||||
GetStaticErrorName(optionsResult.inspectErr())));
|
||||
Cancel(optionsResult.unwrapErr());
|
||||
if (coop ==
|
||||
nsILoadInfo::OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP) {
|
||||
// We want documents with SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP COOP
|
||||
// policy to be loaded in a separate process in which we can enable
|
||||
// high-resolution timers.
|
||||
nsAutoCString siteOrigin;
|
||||
resultPrincipal->GetSiteOrigin(siteOrigin);
|
||||
preferredRemoteType = WITH_COOP_COEP_REMOTE_TYPE_PREFIX;
|
||||
preferredRemoteType.Append(siteOrigin);
|
||||
} else if (isCOOPSwitch) {
|
||||
// If we're doing a COOP switch, we do not need any affinity to the
|
||||
// current remote type. Clear it back to the default value.
|
||||
preferredRemoteType = DEFAULT_REMOTE_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
// If we're performing a large allocation load, override the remote type
|
||||
// with `LARGE_ALLOCATION_REMOTE_TYPE` to move it into an exclusive content
|
||||
// process. If we're already in one, and don't otherwise we force ourselves
|
||||
// out of that content process.
|
||||
if (!parentWindow && browsingContext->Group()->Toplevels().Length() == 1) {
|
||||
if (IsLargeAllocationLoad(browsingContext, mChannel)) {
|
||||
preferredRemoteType = LARGE_ALLOCATION_REMOTE_TYPE;
|
||||
options.mReplaceBrowsingContext = true;
|
||||
} else if (preferredRemoteType == LARGE_ALLOCATION_REMOTE_TYPE) {
|
||||
preferredRemoteType = DEFAULT_REMOTE_TYPE;
|
||||
options.mReplaceBrowsingContext = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Put toplevel BrowsingContexts which load within the extension process into
|
||||
// a specific BrowsingContextGroup.
|
||||
if (auto* addonPolicy = BasePrincipal::Cast(resultPrincipal)->AddonPolicy()) {
|
||||
if (!parentWindow) {
|
||||
// Toplevel extension BrowsingContexts must be loaded in the extension
|
||||
// browsing context group, within the extension content process.
|
||||
if (ExtensionPolicyService::GetSingleton().UseRemoteExtensions()) {
|
||||
preferredRemoteType = EXTENSION_REMOTE_TYPE;
|
||||
} else {
|
||||
preferredRemoteType = NOT_REMOTE_TYPE;
|
||||
}
|
||||
|
||||
if (browsingContext->Group()->Id() !=
|
||||
addonPolicy->GetBrowsingContextGroupId()) {
|
||||
options.mReplaceBrowsingContext = true;
|
||||
options.mSpecificGroupId = addonPolicy->GetBrowsingContextGroupId();
|
||||
}
|
||||
} else {
|
||||
// As a temporary measure, extension iframes must be loaded within the
|
||||
// same process as their parent document.
|
||||
preferredRemoteType = parentWindow->GetRemoteType();
|
||||
}
|
||||
}
|
||||
|
||||
LOG(
|
||||
("DocumentLoadListener GetRemoteTypeForPrincipal "
|
||||
"[this=%p, contentParent=%s, preferredRemoteType=%s]",
|
||||
this, currentRemoteType.get(), preferredRemoteType.get()));
|
||||
|
||||
nsCOMPtr<nsIE10SUtils> e10sUtils = do_ImportModule(
|
||||
"resource://gre/modules/E10SUtils.jsm", "E10SUtils", fallible);
|
||||
if (!e10sUtils) {
|
||||
LOG(("Process Switch Abort: Could not import E10SUtils"));
|
||||
return false;
|
||||
}
|
||||
|
||||
NavigationIsolationOptions options = optionsResult.unwrap();
|
||||
|
||||
if (options.mTryUseBFCache) {
|
||||
MOZ_ASSERT(!parentWindow, "Can only BFCache toplevel windows");
|
||||
bool sameOrigin = false;
|
||||
if (auto* wgp = browsingContext->GetCurrentWindowGlobal()) {
|
||||
nsCOMPtr<nsIPrincipal> resultPrincipal;
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
nsContentUtils::GetSecurityManager()->GetChannelResultPrincipal(
|
||||
mChannel, getter_AddRefs(resultPrincipal)));
|
||||
sameOrigin =
|
||||
wgp->DocumentPrincipal()->EqualsConsideringDomain(resultPrincipal);
|
||||
// Get information about the current document loaded in our BrowsingContext.
|
||||
nsCOMPtr<nsIPrincipal> currentPrincipal;
|
||||
RefPtr<WindowGlobalParent> wgp = browsingContext->GetCurrentWindowGlobal();
|
||||
if (wgp) {
|
||||
currentPrincipal = wgp->DocumentPrincipal();
|
||||
}
|
||||
|
||||
rv = e10sUtils->GetRemoteTypeForPrincipal(
|
||||
resultPrincipal, mChannelCreationURI, browsingContext->UseRemoteTabs(),
|
||||
browsingContext->UseRemoteSubframes(), preferredRemoteType,
|
||||
currentPrincipal, parentWindow, options.mRemoteType);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
LOG(("Process Switch Abort: getRemoteTypeForPrincipal threw an exception"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the final decision is to switch from an 'extension' remote type to any
|
||||
// other remote type, ensure the browsing context is replaced so that we leave
|
||||
// the extension-specific BrowsingContextGroup.
|
||||
if (!parentWindow && currentRemoteType != options.mRemoteType &&
|
||||
currentRemoteType == EXTENSION_REMOTE_TYPE) {
|
||||
options.mReplaceBrowsingContext = true;
|
||||
}
|
||||
|
||||
if (mozilla::BFCacheInParent() && nsSHistory::GetMaxTotalViewers() > 0 &&
|
||||
!parentWindow && !browsingContext->HadOriginalOpener() &&
|
||||
!options.mRemoteType.IsEmpty() &&
|
||||
browsingContext->GetHasLoadedNonInitialDocument() &&
|
||||
(mLoadStateLoadType == LOAD_NORMAL ||
|
||||
mLoadStateLoadType == LOAD_HISTORY || mLoadStateLoadType == LOAD_LINK ||
|
||||
mLoadStateLoadType == LOAD_STOP_CONTENT ||
|
||||
mLoadStateLoadType == LOAD_STOP_CONTENT_AND_REPLACE) &&
|
||||
(!browsingContext->GetActiveSessionHistoryEntry() ||
|
||||
browsingContext->GetActiveSessionHistoryEntry()
|
||||
->GetSaveLayoutStateFlag())) {
|
||||
MOZ_ASSERT(mIsDocumentLoad);
|
||||
options.mTryUseBFCache =
|
||||
browsingContext->AllowedInBFCache(mDocumentChannelId);
|
||||
if (options.mTryUseBFCache) {
|
||||
options.mReplaceBrowsingContext = true;
|
||||
options.mActiveSessionHistoryEntry =
|
||||
browsingContext->GetActiveSessionHistoryEntry();
|
||||
// We only reset the window name for content.
|
||||
mLoadingSessionHistoryInfo->mForceMaybeResetName.emplace(
|
||||
StaticPrefs::privacy_window_name_update_enabled() &&
|
||||
browsingContext->IsContent() && !sameOrigin);
|
||||
browsingContext->IsContent() &&
|
||||
(!currentPrincipal ||
|
||||
!currentPrincipal->EqualsConsideringDomain(resultPrincipal)));
|
||||
}
|
||||
}
|
||||
|
||||
MOZ_LOG(
|
||||
gProcessIsolationLog, LogLevel::Verbose,
|
||||
("CheckIsolationForNavigation -> current:(%s) remoteType:(%s) replace:%d "
|
||||
"group:%" PRIx64 " bfcache:%d shentry:%p",
|
||||
currentRemoteType.get(), options.mRemoteType.get(),
|
||||
options.mReplaceBrowsingContext, options.mSpecificGroupId,
|
||||
options.mTryUseBFCache, options.mActiveSessionHistoryEntry.get()));
|
||||
LOG(("GetRemoteTypeForPrincipal -> current:%s remoteType:%s",
|
||||
currentRemoteType.get(), options.mRemoteType.get()));
|
||||
|
||||
// Check if a process switch is needed.
|
||||
if (currentRemoteType == options.mRemoteType &&
|
||||
!options.mReplaceBrowsingContext) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Info,
|
||||
("Process Switch Abort: type (%s) is compatible",
|
||||
LOG(("Process Switch Abort: type (%s) is compatible",
|
||||
options.mRemoteType.get()));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(parentWindow && options.mRemoteType.IsEmpty())) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Error,
|
||||
("Process Switch Abort: non-remote target process for subframe"));
|
||||
LOG(("Process Switch Abort: non-remote target process for subframe"));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -1667,32 +1729,29 @@ bool DocumentLoadListener::MaybeTriggerProcessSwitch(
|
|||
// object load. We need a BrowsingContext to perform the switch in, so will
|
||||
// trigger an upgrade.
|
||||
if (!mObjectUpgradeHandler) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Warning,
|
||||
("Process Switch Abort: no object upgrade handler"));
|
||||
LOG(("Process Switch Abort: no object upgrade handler"));
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!StaticPrefs::fission_remoteObjectEmbed()) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
|
||||
("Process Switch Abort: remote <object>/<embed> disabled"));
|
||||
LOG(("Process Switch Abort: remote <object>/<embed> disabled"));
|
||||
return false;
|
||||
}
|
||||
|
||||
mObjectUpgradeHandler->UpgradeObjectLoad()->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[self = RefPtr{this}, options, parentWindow](
|
||||
const RefPtr<CanonicalBrowsingContext>& aBrowsingContext) mutable {
|
||||
[self = RefPtr{this}, options,
|
||||
wgp](const RefPtr<CanonicalBrowsingContext>& aBrowsingContext) mutable {
|
||||
if (aBrowsingContext->IsDiscarded() ||
|
||||
parentWindow != aBrowsingContext->GetParentWindowContext()) {
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Error,
|
||||
wgp != aBrowsingContext->GetParentWindowContext()) {
|
||||
LOG(
|
||||
("Process Switch: Got invalid BrowsingContext from object "
|
||||
"upgrade!"));
|
||||
self->RedirectToRealChannelFinished(NS_ERROR_FAILURE);
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
|
||||
("Process Switch: Upgraded Object to Document Load"));
|
||||
LOG(("Process Switch: Upgraded Object to Document Load"));
|
||||
self->TriggerProcessSwitch(aBrowsingContext, options);
|
||||
},
|
||||
[self = RefPtr{this}](nsresult aStatusCode) {
|
||||
|
@ -1704,17 +1763,14 @@ bool DocumentLoadListener::MaybeTriggerProcessSwitch(
|
|||
|
||||
void DocumentLoadListener::TriggerProcessSwitch(
|
||||
CanonicalBrowsingContext* aContext,
|
||||
const NavigationIsolationOptions& aOptions) {
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
aContext->IsOwnedByProcess(GetContentProcessId(mContentParent)),
|
||||
"not owned by creator process anymore?");
|
||||
const RemotenessChangeOptions& aOptions) {
|
||||
nsAutoCString currentRemoteType(NOT_REMOTE_TYPE);
|
||||
if (mContentParent) {
|
||||
currentRemoteType = mContentParent->GetRemoteType();
|
||||
if (RefPtr<ContentParent> contentParent = aContext->GetContentParent()) {
|
||||
currentRemoteType = contentParent->GetRemoteType();
|
||||
}
|
||||
MOZ_ASSERT_IF(currentRemoteType.IsEmpty(), !OtherPid());
|
||||
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Info,
|
||||
("Process Switch: Changing Remoteness from '%s' to '%s'",
|
||||
LOG(("Process Switch: Changing Remoteness from '%s' to '%s'",
|
||||
currentRemoteType.get(), aOptions.mRemoteType.get()));
|
||||
|
||||
// We're now committing to a process switch, so we can disconnect from
|
||||
|
@ -1723,16 +1779,15 @@ void DocumentLoadListener::TriggerProcessSwitch(
|
|||
|
||||
DisconnectListeners(NS_BINDING_ABORTED, NS_BINDING_ABORTED, true);
|
||||
|
||||
MOZ_LOG(gProcessIsolationLog, LogLevel::Verbose,
|
||||
("Process Switch: Calling ChangeRemoteness"));
|
||||
LOG(("Process Switch: Calling ChangeRemoteness"));
|
||||
aContext->ChangeRemoteness(aOptions, mLoadIdentifier)
|
||||
->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[self = RefPtr{this}](BrowserParent* aBrowserParent) {
|
||||
MOZ_ASSERT(self->mChannel,
|
||||
"Something went wrong, channel got cancelled");
|
||||
self->TriggerRedirectToRealChannel(
|
||||
Some(aBrowserParent ? aBrowserParent->Manager() : nullptr));
|
||||
self->TriggerRedirectToRealChannel(Some(
|
||||
aBrowserParent ? aBrowserParent->Manager()->ChildID() : 0));
|
||||
},
|
||||
[self = RefPtr{this}](nsresult aStatusCode) {
|
||||
MOZ_ASSERT(NS_FAILED(aStatusCode), "Status should be error");
|
||||
|
@ -1780,7 +1835,7 @@ DocumentLoadListener::RedirectToParentProcess(uint32_t aRedirectFlags,
|
|||
RefPtr<PDocumentChannelParent::RedirectToRealChannelPromise>
|
||||
DocumentLoadListener::RedirectToRealChannel(
|
||||
uint32_t aRedirectFlags, uint32_t aLoadFlags,
|
||||
const Maybe<ContentParent*>& aDestinationProcess,
|
||||
const Maybe<uint64_t>& aDestinationProcess,
|
||||
nsTArray<ParentEndpoint>&& aStreamFilterEndpoints) {
|
||||
LOG(
|
||||
("DocumentLoadListener RedirectToRealChannel [this=%p] "
|
||||
|
@ -1812,19 +1867,20 @@ DocumentLoadListener::RedirectToRealChannel(
|
|||
MOZ_ALWAYS_SUCCEEDS(registrar->RegisterChannel(chan, mRedirectChannelId));
|
||||
|
||||
if (aDestinationProcess) {
|
||||
RefPtr<ContentParent> cp = *aDestinationProcess;
|
||||
if (!cp) {
|
||||
if (!*aDestinationProcess) {
|
||||
MOZ_ASSERT(aStreamFilterEndpoints.IsEmpty());
|
||||
return RedirectToParentProcess(aRedirectFlags, aLoadFlags);
|
||||
}
|
||||
|
||||
if (!cp->CanSend()) {
|
||||
dom::ContentParent* cp =
|
||||
dom::ContentProcessManager::GetSingleton()->GetContentProcessById(
|
||||
ContentParentId{*aDestinationProcess});
|
||||
if (!cp) {
|
||||
return PDocumentChannelParent::RedirectToRealChannelPromise::
|
||||
CreateAndReject(ipc::ResponseRejectReason::SendError, __func__);
|
||||
}
|
||||
|
||||
RedirectToRealChannelArgs args;
|
||||
SerializeRedirectData(args, /* aIsCrossProcess */ true, aRedirectFlags,
|
||||
SerializeRedirectData(args, !!aDestinationProcess, aRedirectFlags,
|
||||
aLoadFlags, cp);
|
||||
if (mTiming) {
|
||||
mTiming->Anonymize(args.uri());
|
||||
|
@ -1875,7 +1931,7 @@ DocumentLoadListener::RedirectToRealChannel(
|
|||
}
|
||||
|
||||
void DocumentLoadListener::TriggerRedirectToRealChannel(
|
||||
const Maybe<ContentParent*>& aDestinationProcess) {
|
||||
const Maybe<uint64_t>& aDestinationProcess) {
|
||||
LOG((
|
||||
"DocumentLoadListener::TriggerRedirectToRealChannel [this=%p] "
|
||||
"aDestinationProcess=%" PRId64,
|
||||
|
@ -1893,8 +1949,19 @@ void DocumentLoadListener::TriggerRedirectToRealChannel(
|
|||
|
||||
nsTArray<ParentEndpoint> parentEndpoints(mStreamFilterRequests.Length());
|
||||
if (!mStreamFilterRequests.IsEmpty()) {
|
||||
ContentParent* cp = aDestinationProcess.valueOr(mContentParent);
|
||||
base::ProcessId pid = cp ? cp->OtherPid() : base::ProcessId{0};
|
||||
base::ProcessId pid = OtherPid();
|
||||
if (aDestinationProcess) {
|
||||
if (*aDestinationProcess) {
|
||||
dom::ContentParent* cp =
|
||||
dom::ContentProcessManager::GetSingleton()->GetContentProcessById(
|
||||
ContentParentId(*aDestinationProcess));
|
||||
if (cp) {
|
||||
pid = cp->OtherPid();
|
||||
}
|
||||
} else {
|
||||
pid = 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (StreamFilterRequest& request : mStreamFilterRequests) {
|
||||
if (!pid) {
|
||||
|
@ -2161,23 +2228,18 @@ DocumentLoadListener::OnStartRequest(nsIRequest* aRequest) {
|
|||
if (!DocShellWillDisplayContent(status) ||
|
||||
!MaybeTriggerProcessSwitch(&willBeRemote)) {
|
||||
if (!mSupportsRedirectToRealChannel) {
|
||||
RefPtr<BrowserParent> browserParent = loadingContext->GetBrowserParent();
|
||||
if (browserParent->Manager() != mContentParent) {
|
||||
LOG(
|
||||
("DocumentLoadListener::RedirectToRealChannel failed because "
|
||||
"browsingContext no longer owned by creator"));
|
||||
Cancel(NS_BINDING_ABORTED);
|
||||
return NS_OK;
|
||||
}
|
||||
MOZ_DIAGNOSTIC_ASSERT(
|
||||
browserParent->GetBrowsingContext() == loadingContext,
|
||||
"make sure the load is going to the right place");
|
||||
|
||||
// If the existing process is right for this load, but the bridge doesn't
|
||||
// support redirects, then we need to do it manually, by faking a process
|
||||
// switch.
|
||||
mDoingProcessSwitch = true;
|
||||
|
||||
// If we're not going to process switch, then we must have an existing
|
||||
// window global, right?
|
||||
MOZ_ASSERT(loadingContext->GetCurrentWindowGlobal());
|
||||
|
||||
RefPtr<BrowserParent> browserParent =
|
||||
loadingContext->GetCurrentWindowGlobal()->GetBrowserParent();
|
||||
|
||||
// XXX(anny) This is currently a dead code path because parent-controlled
|
||||
// DC pref is off. When we enable the pref, we might get extra STATE_START
|
||||
// progress events
|
||||
|
@ -2188,13 +2250,13 @@ DocumentLoadListener::OnStartRequest(nsIRequest* aRequest) {
|
|||
|
||||
// Use the current process ID to run the 'process switch' path and connect
|
||||
// the channel into the current process.
|
||||
TriggerRedirectToRealChannel(Some(mContentParent));
|
||||
TriggerRedirectToRealChannel(Some(loadingContext->OwnerProcessId()));
|
||||
} else {
|
||||
TriggerRedirectToRealChannel(Nothing());
|
||||
}
|
||||
|
||||
// If we're not switching, then check if we're currently remote.
|
||||
if (mContentParent) {
|
||||
if (loadingContext->GetContentParent()) {
|
||||
willBeRemote = true;
|
||||
}
|
||||
}
|
||||
|
@ -2450,10 +2512,6 @@ DocumentLoadListener::AsyncOnChannelRedirect(
|
|||
// the new URI and set these again.
|
||||
mIParentChannelFunctions.Clear();
|
||||
|
||||
// If we had a remote type override, ensure it's been cleared after a
|
||||
// redirect, as it can't apply anymore.
|
||||
mRemoteTypeOverride.reset();
|
||||
|
||||
#ifdef ANDROID
|
||||
nsCOMPtr<nsIURI> uriBeingLoaded =
|
||||
AntiTrackingUtils::MaybeGetDocumentURIBeingLoaded(mChannel);
|
||||
|
|
|
@ -36,7 +36,7 @@
|
|||
namespace mozilla {
|
||||
namespace dom {
|
||||
class CanonicalBrowsingContext;
|
||||
struct NavigationIsolationOptions;
|
||||
struct RemotenessChangeOptions;
|
||||
} // namespace dom
|
||||
namespace net {
|
||||
using ChildEndpointPromise =
|
||||
|
@ -152,15 +152,15 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
const TimeStamp& aAsyncOpenTime,
|
||||
nsDOMNavigationTiming* aTiming,
|
||||
Maybe<dom::ClientInfo>&& aInfo, bool aUrgentStart,
|
||||
dom::ContentParent* aContentParent, nsresult* aRv);
|
||||
base::ProcessId aPid, nsresult* aRv);
|
||||
|
||||
public:
|
||||
RefPtr<OpenPromise> OpenDocument(
|
||||
nsDocShellLoadState* aLoadState, uint32_t aCacheKey,
|
||||
const Maybe<uint64_t>& aChannelId, const TimeStamp& aAsyncOpenTime,
|
||||
nsDOMNavigationTiming* aTiming, Maybe<dom::ClientInfo>&& aInfo,
|
||||
Maybe<bool> aUriModified, Maybe<bool> aIsXFOError,
|
||||
dom::ContentParent* aContentParent, nsresult* aRv);
|
||||
Maybe<bool> aUriModified, Maybe<bool> aIsXFOError, base::ProcessId aPid,
|
||||
nsresult* aRv);
|
||||
|
||||
RefPtr<OpenPromise> OpenObject(
|
||||
nsDocShellLoadState* aLoadState, uint32_t aCacheKey,
|
||||
|
@ -168,8 +168,8 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
nsDOMNavigationTiming* aTiming, Maybe<dom::ClientInfo>&& aInfo,
|
||||
uint64_t aInnerWindowId, nsLoadFlags aLoadFlags,
|
||||
nsContentPolicyType aContentPolicyType, bool aUrgentStart,
|
||||
dom::ContentParent* aContentParent,
|
||||
ObjectUpgradeHandler* aObjectUpgradeHandler, nsresult* aRv);
|
||||
base::ProcessId aPid, ObjectUpgradeHandler* aObjectUpgradeHandler,
|
||||
nsresult* aRv);
|
||||
|
||||
// Creates a DocumentLoadListener entirely in the parent process and opens it,
|
||||
// and never needs a DocumentChannel to connect to an existing docshell.
|
||||
|
@ -262,13 +262,7 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// The content process corresponding to this DocumentLoadListener, or nullptr
|
||||
// if connected to the parent process.
|
||||
dom::ContentParent* GetContentParent() const { return mContentParent; }
|
||||
|
||||
// The process id of the content process that we are being called from
|
||||
// or 0 initiated from a parent process load.
|
||||
base::ProcessId OtherPid() const;
|
||||
base::ProcessId OtherPid() const { return mOtherPid; }
|
||||
|
||||
[[nodiscard]] RefPtr<ChildEndpointPromise> AttachStreamFilter(
|
||||
base::ProcessId aChildProcessId);
|
||||
|
@ -308,8 +302,7 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
// Initiates the switch from DocumentChannel to the real protocol-specific
|
||||
// channel, and ensures that RedirectToRealChannelFinished is called when
|
||||
// this is complete.
|
||||
void TriggerRedirectToRealChannel(
|
||||
const Maybe<dom::ContentParent*>& aDestinationProcess);
|
||||
void TriggerRedirectToRealChannel(const Maybe<uint64_t>& aDestinationProcess);
|
||||
|
||||
// Called once the content-process side on setting up a replacement
|
||||
// channel is complete. May wait for the new parent channel to
|
||||
|
@ -329,7 +322,7 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
// and that the new remote type will be something other than NOT_REMOTE
|
||||
bool MaybeTriggerProcessSwitch(bool* aWillSwitchToRemote);
|
||||
void TriggerProcessSwitch(dom::CanonicalBrowsingContext* aContext,
|
||||
const dom::NavigationIsolationOptions& aOptions);
|
||||
const dom::RemotenessChangeOptions& aOptions);
|
||||
|
||||
// A helper for TriggerRedirectToRealChannel that abstracts over
|
||||
// the same-process and cross-process switch cases and returns
|
||||
|
@ -338,7 +331,7 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
mozilla::ipc::Endpoint<extensions::PStreamFilterParent>;
|
||||
RefPtr<PDocumentChannelParent::RedirectToRealChannelPromise>
|
||||
RedirectToRealChannel(uint32_t aRedirectFlags, uint32_t aLoadFlags,
|
||||
const Maybe<dom::ContentParent*>& aDestinationProcess,
|
||||
const Maybe<uint64_t>& aDestinationProcess,
|
||||
nsTArray<ParentEndpoint>&& aStreamFilterEndpoints);
|
||||
|
||||
// A helper for RedirectToRealChannel that handles the case where we started
|
||||
|
@ -551,11 +544,9 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
|
||||
bool mSupportsRedirectToRealChannel = true;
|
||||
|
||||
Maybe<nsCString> mRemoteTypeOverride;
|
||||
|
||||
// The ContentParent which this channel is currently connected to, or nullptr
|
||||
// if connected to the parent process.
|
||||
RefPtr<dom::ContentParent> mContentParent;
|
||||
// The process id of the content process that we are being called from
|
||||
// or 0 initiated from a parent process load.
|
||||
base::ProcessId mOtherPid = 0;
|
||||
|
||||
void RejectOpenPromise(nsresult aStatus, nsresult aLoadGroupStatus,
|
||||
bool aSwitchedProcess, const char* aLocation) {
|
||||
|
|
|
@ -173,13 +173,13 @@ NS_IMETHODIMP ParentProcessDocumentChannel::AsyncOpen(
|
|||
promise = mDocumentLoadListener->OpenDocument(
|
||||
mLoadState, mCacheKey, Some(mChannelId), mAsyncOpenTime, mTiming,
|
||||
std::move(initialClientInfo), Some(mUriModified), Some(mIsXFOError),
|
||||
nullptr /* ContentParent */, &rv);
|
||||
0 /* ProcessId */, &rv);
|
||||
} else {
|
||||
promise = mDocumentLoadListener->OpenObject(
|
||||
mLoadState, mCacheKey, Some(mChannelId), mAsyncOpenTime, mTiming,
|
||||
std::move(initialClientInfo), InnerWindowIDForExtantDoc(docShell),
|
||||
mLoadFlags, mLoadInfo->InternalContentPolicyType(),
|
||||
UserActivation::IsHandlingUserInput(), nullptr /* ContentParent */,
|
||||
UserActivation::IsHandlingUserInput(), 0 /* ProcessId */,
|
||||
nullptr /* ObjectUpgradeHandler */, &rv);
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
[coop-coep-sandbox.https.html]
|
||||
bug:
|
||||
if fission: https://bugzilla.mozilla.org/show_bug.cgi?id=1712649
|
||||
expected:
|
||||
if fission: TIMEOUT
|
||||
[<iframe sandbox="allow-popups allow-scripts allow-popups-to-escape-sandbox"> Sandboxed Cross-Origin-Opener-Policy popup should result in a network error]
|
||||
bug:
|
||||
if fission: https://bugzilla.mozilla.org/show_bug.cgi?id=1712649
|
||||
expected:
|
||||
if fission: TIMEOUT
|
|
@ -1,10 +1,5 @@
|
|||
[cross-origin-iframe.sub.html]
|
||||
[First rAF]
|
||||
expected:
|
||||
if fission: FAIL
|
||||
if debug: PASS
|
||||
[PASS, FAIL]
|
||||
[topDocument.scrollingElement.scrollTop = 100]
|
||||
expected:
|
||||
if fission: FAIL
|
||||
PASS
|
||||
|
|
|
@ -195,18 +195,8 @@ add_task(async function test_webnav_unresolved_uri_on_expected_URI_scheme() {
|
|||
for (let data of testFilterScenarios) {
|
||||
info(`Prepare the new test scenario: ${JSON.stringify(data)}`);
|
||||
|
||||
win.location = "about:blank";
|
||||
|
||||
// Wait for the about:blank load to finish before continuing, in case this
|
||||
// load is causing a process switch back into our process.
|
||||
await SimpleTest.promiseWaitForCondition(() => {
|
||||
try {
|
||||
return win.location.href == "about:blank" &&
|
||||
win.document.readyState == "complete";
|
||||
} catch (e) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
// Bug 1589102: using plain "about:blank" crashes here in fission+debug.
|
||||
win.location = "about:blank?2";
|
||||
|
||||
extension.sendMessage("test-filters", EVENTS, data);
|
||||
await extension.awaitMessage("test-filter-ready");
|
||||
|
|
|
@ -271,7 +271,8 @@ add_task(async function test_protocol() {
|
|||
PRINT_POSTDATA
|
||||
);
|
||||
|
||||
ok(E10SUtils.isWebRemoteType(respExtRedirect.remoteType), "process switch");
|
||||
// TODO: Processes should be switched due to navigation of different origins.
|
||||
is(respExtRedirect.remoteType, "extension", "process switch");
|
||||
is(respExtRedirect.location, DATA_URL, "correct location");
|
||||
is(respExtRedirect.body, DATA_STRING, "correct POST body");
|
||||
});
|
||||
|
|
|
@ -814,7 +814,6 @@
|
|||
postData,
|
||||
headers,
|
||||
csp,
|
||||
remoteTypeOverride,
|
||||
} = aParams;
|
||||
let loadFlags =
|
||||
aParams.loadFlags ||
|
||||
|
@ -827,7 +826,6 @@
|
|||
loadFlags,
|
||||
postData,
|
||||
headers,
|
||||
remoteTypeOverride,
|
||||
};
|
||||
this._wrapURIChangeCall(() =>
|
||||
this.webNavigation.loadURI(aURI, loadURIOptions)
|
||||
|
|
|
@ -17,6 +17,12 @@ XPCOMUtils.defineLazyPreferenceGetter(
|
|||
"browser.tabs.remote.separateFileUriProcess",
|
||||
false
|
||||
);
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
"useSeparateDataUriProcess",
|
||||
"browser.tabs.remote.dataUriInDefaultWebProcess",
|
||||
false
|
||||
);
|
||||
XPCOMUtils.defineLazyPreferenceGetter(
|
||||
this,
|
||||
"useSeparatePrivilegedAboutContentProcess",
|
||||
|
@ -616,6 +622,74 @@ var E10SUtils = {
|
|||
}
|
||||
},
|
||||
|
||||
getRemoteTypeForPrincipal(
|
||||
aPrincipal,
|
||||
aOriginalURI,
|
||||
aMultiProcess,
|
||||
aRemoteSubframes,
|
||||
aPreferredRemoteType = DEFAULT_REMOTE_TYPE,
|
||||
aCurrentPrincipal,
|
||||
aIsSubframe
|
||||
) {
|
||||
if (!aMultiProcess) {
|
||||
return NOT_REMOTE;
|
||||
}
|
||||
|
||||
// We want to use the original URI for "about:" (except for "about:srcdoc"
|
||||
// and "about:blank") and "chrome://" scheme, so that we can properly
|
||||
// determine the remote type.
|
||||
let useOriginalURI;
|
||||
if (aOriginalURI.scheme == "about") {
|
||||
useOriginalURI = !["about:srcdoc", "about:blank"].includes(
|
||||
aOriginalURI.spec
|
||||
);
|
||||
} else {
|
||||
useOriginalURI = aOriginalURI.scheme == "chrome";
|
||||
}
|
||||
|
||||
if (!useOriginalURI) {
|
||||
// We can't pick a process based on a system principal or expanded
|
||||
// principal.
|
||||
if (aPrincipal.isSystemPrincipal || aPrincipal.isExpandedPrincipal) {
|
||||
throw Components.Exception("", Cr.NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
|
||||
// Null principals can be loaded in any remote process, but when
|
||||
// using fission we add the option to force them into the default
|
||||
// web process for better test coverage.
|
||||
if (aPrincipal.isNullPrincipal) {
|
||||
if (aOriginalURI.spec == "about:blank") {
|
||||
useOriginalURI = true;
|
||||
} else if (
|
||||
(aRemoteSubframes && useSeparateDataUriProcess) ||
|
||||
aPreferredRemoteType == NOT_REMOTE
|
||||
) {
|
||||
return WEB_REMOTE_TYPE;
|
||||
}
|
||||
return aPreferredRemoteType;
|
||||
}
|
||||
}
|
||||
// We might care about the currently loaded URI. Pull it out of our current
|
||||
// principal. We never care about the current URI when working with a
|
||||
// non-content principal.
|
||||
let currentURI =
|
||||
aCurrentPrincipal && aCurrentPrincipal.isContentPrincipal
|
||||
? Services.io.newURI(aCurrentPrincipal.spec)
|
||||
: null;
|
||||
|
||||
return E10SUtils.getRemoteTypeForURIObject(
|
||||
useOriginalURI ? aOriginalURI : Services.io.newURI(aPrincipal.spec),
|
||||
aMultiProcess,
|
||||
aRemoteSubframes,
|
||||
aPreferredRemoteType,
|
||||
currentURI,
|
||||
aPrincipal,
|
||||
aIsSubframe,
|
||||
false, //aIsWorker
|
||||
aPrincipal.originAttributes
|
||||
);
|
||||
},
|
||||
|
||||
getRemoteTypeForWorkerPrincipal(
|
||||
aPrincipal,
|
||||
aWorkerType,
|
||||
|
|
|
@ -20,6 +20,31 @@ interface nsIE10SUtils : nsISupports {
|
|||
REMOTE_WORKER_TYPE_SERVICE,
|
||||
};
|
||||
|
||||
/**
|
||||
* Determine what remote type should be used to load a document with the given
|
||||
* principal.
|
||||
*
|
||||
* @param aPrincipal The result principal for the document being loaded.
|
||||
* @param aChannelOriginalURI. The original URI being loaded
|
||||
* (which isn't always the same as the Principal's
|
||||
* URI)
|
||||
* @param aMultiProcess Does the browser have remote tabs enabled.
|
||||
* @param aRemoteSubframes Does the browser have remote subframes enabled.
|
||||
* @param aPreferredRemoteType If multiple remote types are compatible with
|
||||
* the load, prefer staying in this remote type.
|
||||
* @param aCurrentPrincipal The principal of the currently loaded document.
|
||||
* @param aIsSubframe Is the process switch occuring in a subframe.
|
||||
*
|
||||
* @return The remote type to complete this load in.
|
||||
*/
|
||||
AUTF8String getRemoteTypeForPrincipal(in nsIPrincipal aPrincipal,
|
||||
in nsIURI aChannelOriginalURI,
|
||||
in boolean aMultiProcess,
|
||||
in boolean aRemoteSubframes,
|
||||
in AUTF8String aPreferredRemoteType,
|
||||
in nsIPrincipal aCurrentPrincipal,
|
||||
in boolean aIsSubframe);
|
||||
|
||||
/**
|
||||
* Determine what remote type should be used to launch a worker script with
|
||||
* the given principal.
|
||||
|
|
Загрузка…
Ссылка в новой задаче