Backed out 7 changesets (bug 1650089) for causing xpcshell failures in test_ext_cookieBehaviors.js

Backed out changeset 336d6eb2fc15 (bug 1650089)
Backed out changeset 283ba29cdbeb (bug 1650089)
Backed out changeset c470e4c65117 (bug 1650089)
Backed out changeset 8fc2f428694d (bug 1650089)
Backed out changeset 37e5185dae14 (bug 1650089)
Backed out changeset a26afdc56d91 (bug 1650089)
Backed out changeset 32e207558b3d (bug 1650089)
This commit is contained in:
Alexandru Michis 2021-08-04 12:32:07 +03:00
parent d589982ead
commit 5ca72bfc53
39 changed files with 436 additions and 1241 deletions

View File

@ -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);

View File

@ -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");
}

View File

@ -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")
);
});

View File

@ -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")
);
});

View File

@ -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],

View File

@ -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) {

View File

@ -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);
}

View File

@ -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));

View File

@ -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 {

View File

@ -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(
@ -2516,7 +2516,7 @@ void CanonicalBrowsingContext::SetTouchEventsOverride(
void CanonicalBrowsingContext::CloneDocumentTreeInto(
CanonicalBrowsingContext* aSource, const nsACString& aRemoteType,
embedding::PrintData&& aPrintData) {
NavigationIsolationOptions options;
RemotenessChangeOptions options;
options.mRemoteType = aRemoteType;
mClonePromise =

View File

@ -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);
@ -371,7 +380,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);
@ -394,7 +403,7 @@ class CanonicalBrowsingContext final : public BrowsingContext {
RefPtr<BrowsingContextGroup> mSpecificGroup;
uint64_t mPendingSwitchId;
NavigationIsolationOptions mOptions;
RemotenessChangeOptions mOptions;
};
struct RestoreState {

View File

@ -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;
}

View File

@ -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__ */

View File

@ -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.

View File

@ -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

View File

@ -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()) {

View File

@ -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)

View File

@ -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());

View File

@ -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);

View File

@ -303,8 +303,6 @@ struct DocShellLoadStateInit
bool IsMetaRefresh;
nsIURI UnstrippedURI;
nsCString? RemoteTypeOverride;
};
struct TimedChannelInfo

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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",

View File

@ -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;
};

View File

@ -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);

View File

@ -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.

View File

@ -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");

View File

@ -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);
}

View File

@ -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));
}
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;
}
}
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 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);
}
// We only reset the window name for content.
mLoadingSessionHistoryInfo->mForceMaybeResetName.emplace(
StaticPrefs::privacy_window_name_update_enabled() &&
browsingContext->IsContent() && !sameOrigin);
// Get information about the current document loaded in our BrowsingContext.
nsCOMPtr<nsIPrincipal> currentPrincipal;
RefPtr<WindowGlobalParent> wgp = browsingContext->GetCurrentWindowGlobal();
if (wgp) {
currentPrincipal = wgp->DocumentPrincipal();
}
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()));
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() &&
(!currentPrincipal ||
!currentPrincipal->EqualsConsideringDomain(resultPrincipal)));
}
}
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",
options.mRemoteType.get()));
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,
("Process Switch: Got invalid BrowsingContext from object "
"upgrade!"));
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,18 +1763,15 @@ 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'",
currentRemoteType.get(), aOptions.mRemoteType.get()));
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
// the listeners in the old process.
@ -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);

View File

@ -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) {

View File

@ -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);
}

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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");
});

View File

@ -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)

View File

@ -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,

View File

@ -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.