Merge mozilla-central to autoland a=merge on a CLOSED TREE

This commit is contained in:
Alexandru Michis 2021-08-04 12:41:22 +03:00
Родитель 6c3cce394e 4b49a0dc50
Коммит 4f28e79ca9
39 изменённых файлов: 436 добавлений и 1241 удалений

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

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

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

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