зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1625513) for bc failures in browser/base/content/test/siteIdentity/browser_identity_UI.js on a CLOSED TREE
Backed out changeset 876b33334577 (bug 1625513) Backed out changeset 69f75d37ae8e (bug 1625513) --HG-- extra : rebase_source : e8752080577e762777eff9cda7a695bfa2ccd4cf
This commit is contained in:
Родитель
87d90e34dd
Коммит
90abf0bc61
|
@ -5671,51 +5671,6 @@
|
|||
}
|
||||
}
|
||||
},
|
||||
|
||||
async performProcessSwitch(
|
||||
aBrowser,
|
||||
aRemoteType,
|
||||
aSwitchId,
|
||||
aReplaceBrowsingContext
|
||||
) {
|
||||
E10SUtils.log().info(
|
||||
`performing switch from ${aBrowser.remoteType} to ${aRemoteType}`
|
||||
);
|
||||
|
||||
// Don't try to switch tabs before delayed startup is completed.
|
||||
await window.delayedStartupPromise;
|
||||
|
||||
// Perform a navigateAndRestore to trigger the process switch.
|
||||
let tab = this.getTabForBrowser(aBrowser);
|
||||
let loadArguments = {
|
||||
newFrameloader: true, // Switch even if remoteType hasn't changed.
|
||||
remoteType: aRemoteType, // Don't derive remoteType to switch to.
|
||||
|
||||
// Information about which channel should be performing the load.
|
||||
redirectLoadSwitchId: aSwitchId,
|
||||
|
||||
// True if this is a process switch due to a policy mismatch, means we
|
||||
// shouldn't preserve our browsing context.
|
||||
replaceBrowsingContext: aReplaceBrowsingContext,
|
||||
};
|
||||
|
||||
await SessionStore.navigateAndRestore(tab, loadArguments, -1);
|
||||
|
||||
// If the process switch seems to have failed, send an error over to our
|
||||
// caller, to give it a chance to kill our channel.
|
||||
if (
|
||||
aBrowser.remoteType != aRemoteType ||
|
||||
!aBrowser.frameLoader ||
|
||||
!aBrowser.frameLoader.remoteTab
|
||||
) {
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Tell our caller to redirect the load into this newly created process.
|
||||
let remoteTab = aBrowser.frameLoader.remoteTab;
|
||||
E10SUtils.log().debug(`new tabID: ${remoteTab.tabId}`);
|
||||
return remoteTab.contentProcessId;
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -54,6 +54,7 @@ const OBSERVING = [
|
|||
"browser:purge-session-history-for-domain",
|
||||
"idle-daily",
|
||||
"clear-origin-attributes-data",
|
||||
"channel-on-may-change-process",
|
||||
];
|
||||
|
||||
// XUL Window properties to (re)store
|
||||
|
@ -518,6 +519,9 @@ var SessionStoreInternal = {
|
|||
// A counter to be used to generate a unique ID for each closed tab or window.
|
||||
_nextClosedId: 0,
|
||||
|
||||
// A monotonic value used to generate a unique ID for each process switch.
|
||||
_switchIdMonotonic: 0,
|
||||
|
||||
// During the initial restore and setBrowserState calls tracks the number of
|
||||
// windows yet to be restored
|
||||
_restoreCount: -1,
|
||||
|
@ -943,6 +947,9 @@ var SessionStoreInternal = {
|
|||
this._forgetTabsWithUserContextId(userContextId);
|
||||
}
|
||||
break;
|
||||
case "channel-on-may-change-process":
|
||||
this.onMayChangeProcess(aSubject);
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -2912,6 +2919,237 @@ var SessionStoreInternal = {
|
|||
}
|
||||
},
|
||||
|
||||
async _doTabProcessSwitch(
|
||||
aBrowser,
|
||||
aRemoteType,
|
||||
aChannel,
|
||||
aSwitchId,
|
||||
aReplaceBrowsingContext
|
||||
) {
|
||||
E10SUtils.log().info(
|
||||
`performing switch from ${aBrowser.remoteType} to ${aRemoteType}`
|
||||
);
|
||||
|
||||
// Don't try to switch tabs before delayed startup is completed.
|
||||
await aBrowser.ownerGlobal.delayedStartupPromise;
|
||||
|
||||
// Perform a navigateAndRestore to trigger the process switch.
|
||||
let tab = aBrowser.ownerGlobal.gBrowser.getTabForBrowser(aBrowser);
|
||||
let loadArguments = {
|
||||
newFrameloader: true, // Switch even if remoteType hasn't changed.
|
||||
remoteType: aRemoteType, // Don't derive remoteType to switch to.
|
||||
|
||||
// Information about which channel should be performing the load.
|
||||
redirectLoadSwitchId: aSwitchId,
|
||||
|
||||
// True if this is a process switch due to a policy mismatch, means we
|
||||
// shouldn't preserve our browsing context.
|
||||
replaceBrowsingContext: aReplaceBrowsingContext,
|
||||
};
|
||||
|
||||
await SessionStore.navigateAndRestore(tab, loadArguments, -1);
|
||||
|
||||
// If the process switch seems to have failed, send an error over to our
|
||||
// caller, to give it a chance to kill our channel.
|
||||
if (
|
||||
aBrowser.remoteType != aRemoteType ||
|
||||
!aBrowser.frameLoader ||
|
||||
!aBrowser.frameLoader.remoteTab
|
||||
) {
|
||||
throw Cr.NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
// Tell our caller to redirect the load into this newly created process.
|
||||
let remoteTab = aBrowser.frameLoader.remoteTab;
|
||||
E10SUtils.log().debug(`new tabID: ${remoteTab.tabId}`);
|
||||
return remoteTab.contentProcessId;
|
||||
},
|
||||
|
||||
/**
|
||||
* Perform a destructive process switch into a distinct process.
|
||||
* This method is asynchronous, as it requires multiple calls into content
|
||||
* processes.
|
||||
*/
|
||||
async _doProcessSwitch(
|
||||
aBrowsingContext,
|
||||
aRemoteType,
|
||||
aChannel,
|
||||
aSwitchId,
|
||||
aReplaceBrowsingContext
|
||||
) {
|
||||
// There are two relevant cases when performing a process switch for a
|
||||
// browsing context: in-process and out-of-process embedders.
|
||||
|
||||
// If our embedder is in-process (e.g. we're a xul:browser element embedded
|
||||
// within <tabbrowser>), then we can perform a process switch using the
|
||||
// traditional mechanism.
|
||||
if (aBrowsingContext.embedderElement) {
|
||||
return this._doTabProcessSwitch(
|
||||
aBrowsingContext.embedderElement,
|
||||
aRemoteType,
|
||||
aChannel,
|
||||
aSwitchId,
|
||||
aReplaceBrowsingContext
|
||||
);
|
||||
}
|
||||
|
||||
return aBrowsingContext.changeFrameRemoteness(aRemoteType, aSwitchId);
|
||||
},
|
||||
|
||||
// Examine the channel response to see if we should change the process
|
||||
// performing the given load. aRequestor implements nsIProcessSwitchRequestor
|
||||
onMayChangeProcess(aRequestor) {
|
||||
if (!E10SUtils.documentChannel()) {
|
||||
throw new Error("This code is only used by document channel");
|
||||
}
|
||||
|
||||
let switchRequestor;
|
||||
try {
|
||||
switchRequestor = aRequestor.QueryInterface(Ci.nsIProcessSwitchRequestor);
|
||||
} catch (e) {
|
||||
E10SUtils.log().warn(`object not compatible with process switching `);
|
||||
return;
|
||||
}
|
||||
|
||||
const channel = switchRequestor.channel;
|
||||
if (!channel.isDocument || !channel.loadInfo) {
|
||||
return; // Not a document load.
|
||||
}
|
||||
|
||||
// Check that the document has a corresponding BrowsingContext.
|
||||
let browsingContext = channel.loadInfo.targetBrowsingContext;
|
||||
let isSubframe =
|
||||
channel.loadInfo.externalContentPolicyType !=
|
||||
Ci.nsIContentPolicy.TYPE_DOCUMENT;
|
||||
|
||||
if (!browsingContext) {
|
||||
E10SUtils.log().debug(`no BrowsingContext - ignoring`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine if remote subframes should be used for this load.
|
||||
let topBC = browsingContext.top;
|
||||
if (!topBC.embedderElement) {
|
||||
E10SUtils.log().debug(`no embedder for top - ignoring`);
|
||||
return;
|
||||
}
|
||||
|
||||
let topDocShell = topBC.embedderElement.ownerGlobal.docShell;
|
||||
let { useRemoteSubframes } = topDocShell.QueryInterface(Ci.nsILoadContext);
|
||||
if (!useRemoteSubframes && isSubframe) {
|
||||
E10SUtils.log().debug(`remote subframes disabled - ignoring`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get principal for a document already loaded in the BrowsingContext.
|
||||
let currentPrincipal = null;
|
||||
if (browsingContext.currentWindowGlobal) {
|
||||
currentPrincipal = browsingContext.currentWindowGlobal.documentPrincipal;
|
||||
}
|
||||
|
||||
// We can only perform a process switch on in-process frames if they are
|
||||
// embedded within a normal tab. We can't do one of these swaps for a
|
||||
// cross-origin frame.
|
||||
if (browsingContext.embedderElement) {
|
||||
let tabbrowser = browsingContext.embedderElement.getTabBrowser();
|
||||
if (!tabbrowser) {
|
||||
E10SUtils.log().debug(
|
||||
`cannot find tabbrowser for loading tab - ignoring`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
let tab = tabbrowser.getTabForBrowser(browsingContext.embedderElement);
|
||||
if (!tab) {
|
||||
E10SUtils.log().debug(
|
||||
`not a normal tab, so cannot swap processes - ignoring`
|
||||
);
|
||||
return;
|
||||
}
|
||||
} else if (!browsingContext.parent) {
|
||||
E10SUtils.log().debug(
|
||||
`no parent or in-process embedder element - ignoring`
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get the current remote type for the BrowsingContext.
|
||||
let currentRemoteType = browsingContext.currentRemoteType;
|
||||
if (currentRemoteType == E10SUtils.NOT_REMOTE) {
|
||||
E10SUtils.log().debug(`currently not remote - ignoring`);
|
||||
return;
|
||||
}
|
||||
|
||||
// Determine the process type the load should be performed in.
|
||||
let resultPrincipal = Services.scriptSecurityManager.getChannelResultPrincipal(
|
||||
channel
|
||||
);
|
||||
|
||||
const isCOOPSwitch =
|
||||
E10SUtils.useCrossOriginOpenerPolicy() &&
|
||||
switchRequestor.hasCrossOriginOpenerPolicyMismatch();
|
||||
|
||||
let preferredRemoteType = currentRemoteType;
|
||||
if (
|
||||
E10SUtils.useCrossOriginOpenerPolicy() &&
|
||||
switchRequestor.crossOriginOpenerPolicy ==
|
||||
Ci.nsILoadInfo.OPENER_POLICY_SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP
|
||||
) {
|
||||
// We want documents with a SAME_ORIGIN_EMBEDDER_POLICY_REQUIRE_CORP
|
||||
// COOP policy to be loaded in a separate process for which we can enable
|
||||
// high resolution timers.
|
||||
preferredRemoteType =
|
||||
E10SUtils.WEB_REMOTE_COOP_COEP_TYPE_PREFIX + resultPrincipal.siteOrigin;
|
||||
} else if (isCOOPSwitch) {
|
||||
// If it is a coop switch, but doesn't have this flag, we want to switch
|
||||
// to a default remoteType
|
||||
preferredRemoteType = E10SUtils.DEFAULT_REMOTE_TYPE;
|
||||
}
|
||||
E10SUtils.log().info(
|
||||
`currentRemoteType (${currentRemoteType}) preferredRemoteType: ${preferredRemoteType}`
|
||||
);
|
||||
|
||||
let remoteType = E10SUtils.getRemoteTypeForPrincipal(
|
||||
resultPrincipal,
|
||||
true,
|
||||
useRemoteSubframes,
|
||||
preferredRemoteType,
|
||||
currentPrincipal,
|
||||
isSubframe
|
||||
);
|
||||
|
||||
E10SUtils.log().debug(
|
||||
`${currentRemoteType}, ${remoteType}, ${isCOOPSwitch}`
|
||||
);
|
||||
|
||||
if (currentRemoteType == remoteType && !isCOOPSwitch) {
|
||||
E10SUtils.log().debug(`type (${remoteType}) is compatible - ignoring`);
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
remoteType == E10SUtils.NOT_REMOTE ||
|
||||
currentRemoteType == E10SUtils.NOT_REMOTE
|
||||
) {
|
||||
E10SUtils.log().debug(`non-remote source/target - ignoring`);
|
||||
return;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// DANGER ZONE: Perform a process switch into the new process. This is
|
||||
// destructive.
|
||||
// ------------------------------------------------------------------------
|
||||
let identifier = ++this._switchIdMonotonic;
|
||||
let tabPromise = this._doProcessSwitch(
|
||||
browsingContext,
|
||||
remoteType,
|
||||
channel,
|
||||
identifier,
|
||||
isCOOPSwitch
|
||||
);
|
||||
switchRequestor.switchProcessTo(tabPromise, identifier);
|
||||
},
|
||||
|
||||
/* ........ nsISessionStore API .............. */
|
||||
|
||||
getBrowserState: function ssi_getBrowserState() {
|
||||
|
|
|
@ -501,6 +501,25 @@ CanonicalBrowsingContext::ChangeFrameRemoteness(const nsAString& aRemoteType,
|
|||
return promise.forget();
|
||||
}
|
||||
|
||||
already_AddRefed<Promise> CanonicalBrowsingContext::ChangeFrameRemoteness(
|
||||
const nsAString& aRemoteType, uint64_t aPendingSwitchId, ErrorResult& aRv) {
|
||||
nsIGlobalObject* global = xpc::NativeGlobal(xpc::PrivilegedJunkScope());
|
||||
|
||||
RefPtr<Promise> promise = Promise::Create(global, aRv);
|
||||
if (aRv.Failed()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ChangeFrameRemoteness(aRemoteType, aPendingSwitchId)
|
||||
->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[promise](BrowserParent* aBrowserParent) {
|
||||
promise->MaybeResolve(aBrowserParent->Manager()->ChildID());
|
||||
},
|
||||
[promise](nsresult aRv) { promise->MaybeReject(aRv); });
|
||||
return promise.forget();
|
||||
}
|
||||
|
||||
MediaController* CanonicalBrowsingContext::GetMediaController() {
|
||||
// We would only create one media controller per tab, so accessing the
|
||||
// controller via the top-level browsing context.
|
||||
|
|
|
@ -102,6 +102,12 @@ class CanonicalBrowsingContext final : public BrowsingContext {
|
|||
RefPtr<RemotenessPromise> ChangeFrameRemoteness(const nsAString& aRemoteType,
|
||||
uint64_t aPendingSwitchId);
|
||||
|
||||
// Helper version for WebIDL - resolves to the PID where the load is being
|
||||
// resumed.
|
||||
already_AddRefed<Promise> ChangeFrameRemoteness(const nsAString& aRemoteType,
|
||||
uint64_t aPendingSwitchId,
|
||||
ErrorResult& aRv);
|
||||
|
||||
// Return a media controller from the top-level browsing context that can
|
||||
// control all media belonging to this browsing context tree. Return nullptr
|
||||
// if the top-level browsing context has been discarded.
|
||||
|
|
|
@ -98,6 +98,10 @@ interface CanonicalBrowsingContext : BrowsingContext {
|
|||
[Throws]
|
||||
void loadURI(DOMString aURI, optional LoadURIOptions aOptions = {});
|
||||
|
||||
[Throws]
|
||||
Promise<unsigned long long> changeFrameRemoteness(
|
||||
DOMString remoteType, unsigned long long pendingSwitchId);
|
||||
|
||||
readonly attribute nsISHistory? sessionHistory;
|
||||
};
|
||||
|
||||
|
|
|
@ -173,40 +173,4 @@ interface nsIBrowser : nsISupports
|
|||
void updateSecurityUIForSecurityChange(in nsITransportSecurityInfo aSecurityInfo,
|
||||
in uint32_t aState,
|
||||
in boolean aIsSecureContext);
|
||||
|
||||
/**
|
||||
* Called by Gecko when it wants to change the process which is currently
|
||||
* being used to render content in this tab.
|
||||
*
|
||||
* Returns a promise which will be resolved with the ChildID of the new
|
||||
* process.
|
||||
*
|
||||
* @param aRemoteType the new remote type to switch this browser into
|
||||
* @param aPendingSwitchId unique identifier for the ongoing
|
||||
* process-switching load
|
||||
* @param aReplaceBrowsingContext if true, do not preserve the
|
||||
* BrowsingContext loaded inside this
|
||||
* browser after changing processes.
|
||||
*/
|
||||
Promise performProcessSwitch(in AString aRemoteType,
|
||||
in uint64_t aPendingSwitchId,
|
||||
in boolean aReplaceBrowsingContext);
|
||||
|
||||
/** If `true`, this browser supports the `performProcessSwitch` method */
|
||||
readonly attribute bool canPerformProcessSwitch;
|
||||
|
||||
/**
|
||||
* Helper method for invoking `E10SUtils.getRemoteTypeForPrincipal` from
|
||||
* `DocumentLoadListener`.
|
||||
*
|
||||
* FIXME: DocumentLoadListener should make process selection decisions without
|
||||
* an `nsIBrowser`, as the implementation does not depend on which browser
|
||||
* it's being called on.
|
||||
*/
|
||||
AString getRemoteTypeForPrincipal(in nsIPrincipal aPrincipal,
|
||||
in boolean aRemoteTabs,
|
||||
in boolean aRemoteSubframes,
|
||||
in AString aPreferredRemoteType,
|
||||
in nsIPrincipal aCurrentPrincipal,
|
||||
in boolean aIsSubframe);
|
||||
};
|
||||
|
|
|
@ -75,6 +75,7 @@ XPIDL_SOURCES += [
|
|||
'nsIPermission.idl',
|
||||
'nsIPermissionManager.idl',
|
||||
'nsIPrivateBrowsingChannel.idl',
|
||||
'nsIProcessSwitchRequestor.idl',
|
||||
'nsIProgressEventSink.idl',
|
||||
'nsIPrompt.idl',
|
||||
'nsIProtocolHandler.idl',
|
||||
|
|
|
@ -0,0 +1,52 @@
|
|||
/* -*- Mode: IDL; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* 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 "nsIChannel.idl"
|
||||
|
||||
/**
|
||||
* The nsIProcessSwitchRequestor interface allows clients to instruct
|
||||
* SessionStore.jsm that a channel setup has completed and a process switch
|
||||
* may be required. This works alongside the on-may-change-process observer
|
||||
* notification.
|
||||
* This interface must be used only from the XPCOM main thread.
|
||||
*/
|
||||
[scriptable, uuid(fce8497b-c57c-4557-b360-3efefc83eff5)]
|
||||
interface nsIProcessSwitchRequestor : nsISupports
|
||||
{
|
||||
/**
|
||||
* The underlying channel object that was intercepted and that could trigger
|
||||
* a process.
|
||||
*/
|
||||
readonly attribute nsIChannel channel;
|
||||
|
||||
/**
|
||||
* Instructs the callee to be loaded in a new process. Like 'redirectTo'
|
||||
* this can only be used on channels that have not yet called their
|
||||
* listener's OnStartRequest(). Can only be called during the
|
||||
* channel-on-may-change-process observer notification.
|
||||
*
|
||||
* @param aTabPromise a promise which resolves to a nsIRemotTab object
|
||||
* which the load will proceed in.
|
||||
* @param aIdentifier a 64-bit ID which will be provided to the
|
||||
* ChildProcessChannelListener.
|
||||
*/
|
||||
[must_use] void switchProcessTo(in Promise aTabPromise,
|
||||
in unsigned long long aIdentifier);
|
||||
|
||||
/**
|
||||
* Used to determine if there is a Cross-Origin-Opener-Policy mismatch
|
||||
* that would require switching the channel to another process.
|
||||
* @throws NS_ERROR_NOT_AVAILABLE if we don't have a responseHead
|
||||
*/
|
||||
[must_use] boolean hasCrossOriginOpenerPolicyMismatch();
|
||||
|
||||
/**
|
||||
* Returns a cached CrossOriginOpenerPolicy that is computed just before we
|
||||
* determine if there is a policy mismatch.
|
||||
* @throws NS_ERROR_NOT_AVAILABLE if called before onStartRequest
|
||||
*/
|
||||
[must_use, binaryname(CachedCrossOriginOpenerPolicy)] readonly attribute nsILoadInfo_CrossOriginOpenerPolicy crossOriginOpenerPolicy;
|
||||
};
|
|
@ -39,7 +39,6 @@
|
|||
#include "nsIOService.h"
|
||||
#include "mozilla/dom/WindowGlobalParent.h"
|
||||
#include "mozilla/StaticPrefs_security.h"
|
||||
#include "nsIBrowser.h"
|
||||
|
||||
mozilla::LazyLogModule gDocumentChannelLog("DocumentChannel");
|
||||
#define LOG(fmt) MOZ_LOG(gDocumentChannelLog, mozilla::LogLevel::Verbose, fmt)
|
||||
|
@ -233,6 +232,7 @@ NS_INTERFACE_MAP_BEGIN(DocumentLoadListener)
|
|||
NS_INTERFACE_MAP_ENTRY(nsIParentChannel)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectReadyCallback)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIProcessSwitchRequestor)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIMultiPartChannelListener)
|
||||
NS_INTERFACE_MAP_ENTRY_CONCRETE(DocumentLoadListener)
|
||||
NS_INTERFACE_MAP_END
|
||||
|
@ -826,187 +826,26 @@ void DocumentLoadListener::SerializeRedirectData(
|
|||
aArgs.loadStateLoadType() = mLoadStateLoadType;
|
||||
}
|
||||
|
||||
bool DocumentLoadListener::MaybeTriggerProcessSwitch() {
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mDoingProcessSwitch,
|
||||
"Already in the middle of switching?");
|
||||
MOZ_DIAGNOSTIC_ASSERT(mChannel);
|
||||
MOZ_DIAGNOSTIC_ASSERT(mParentChannelListener);
|
||||
void DocumentLoadListener::TriggerCrossProcessSwitch() {
|
||||
MOZ_ASSERT(mRedirectContentProcessIdPromise);
|
||||
MOZ_ASSERT(!mDoingProcessSwitch, "Already in the middle of switching?");
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
LOG(("DocumentLoadListener MaybeTriggerProcessSwitch [this=%p]", this));
|
||||
LOG(("DocumentLoadListener TriggerCrossProcessSwitch [this=%p]", this));
|
||||
|
||||
// Get the BrowsingContext which will be switching processes.
|
||||
RefPtr<CanonicalBrowsingContext> browsingContext =
|
||||
mParentChannelListener->GetBrowsingContext();
|
||||
if (NS_WARN_IF(!browsingContext)) {
|
||||
LOG(("Process Switch Abort: no browsing context"));
|
||||
return false;
|
||||
}
|
||||
if (!browsingContext->IsContent()) {
|
||||
LOG(("Process Switch Abort: non-content browsing context"));
|
||||
return false;
|
||||
}
|
||||
if (browsingContext->GetParent() && !browsingContext->UseRemoteSubframes()) {
|
||||
LOG(("Process Switch Abort: remote subframes disabled"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// We currently can't switch processes for toplevel loads unless they're
|
||||
// loaded within a browser tab. We also enforce this for non-toplevel tabs, as
|
||||
// otherwise cross-origin subframes could get out of sync.
|
||||
// FIXME: Ideally we won't do this in the future.
|
||||
Element* browserElement = browsingContext->Top()->GetEmbedderElement();
|
||||
if (!browserElement) {
|
||||
LOG(("Process Switch Abort: cannot get browser element"));
|
||||
return false;
|
||||
}
|
||||
nsCOMPtr<nsIBrowser> browser = browserElement->AsBrowser();
|
||||
if (!browser) {
|
||||
LOG(("Process Switch Abort: not loaded within nsIBrowser"));
|
||||
return false;
|
||||
}
|
||||
bool loadedInTab = false;
|
||||
if (NS_FAILED(browser->GetCanPerformProcessSwitch(&loadedInTab)) ||
|
||||
!loadedInTab) {
|
||||
LOG(("Process Switch Abort: browser is not loaded in a tab"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get information about the current document loaded in our BrowsingContext.
|
||||
nsCOMPtr<nsIPrincipal> currentPrincipal;
|
||||
if (RefPtr<WindowGlobalParent> wgp =
|
||||
browsingContext->GetCurrentWindowGlobal()) {
|
||||
currentPrincipal = wgp->DocumentPrincipal();
|
||||
}
|
||||
RefPtr<ContentParent> currentProcess = browsingContext->GetContentParent();
|
||||
if (!currentProcess) {
|
||||
LOG(("Process Switch Abort: frame currently not remote"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
if (resultPrincipal->IsSystemPrincipal()) {
|
||||
LOG(("Process Switch Abort: cannot switch process for system principal"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Determine our COOP status, which will be used to determine our preferred
|
||||
// remote type.
|
||||
bool isCOOPSwitch = HasCrossOriginOpenerPolicyMismatch();
|
||||
nsILoadInfo::CrossOriginOpenerPolicy coop =
|
||||
nsILoadInfo::OPENER_POLICY_UNSAFE_NONE;
|
||||
if (RefPtr<nsHttpChannel> httpChannel = do_QueryObject(mChannel)) {
|
||||
MOZ_ALWAYS_SUCCEEDS(httpChannel->GetCrossOriginOpenerPolicy(&coop));
|
||||
}
|
||||
|
||||
nsAutoString preferredRemoteType(currentProcess->GetRemoteType());
|
||||
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.Assign(
|
||||
NS_LITERAL_STRING(WITH_COOP_COEP_REMOTE_TYPE_PREFIX));
|
||||
preferredRemoteType.Append(NS_ConvertUTF8toUTF16(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.Assign(NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE));
|
||||
}
|
||||
MOZ_DIAGNOSTIC_ASSERT(!preferredRemoteType.IsEmpty(),
|
||||
"Unexpected empty remote type!");
|
||||
|
||||
LOG(
|
||||
("DocumentLoadListener GetRemoteTypeForPrincipal "
|
||||
"[this=%p, currentProcess=%s, preferredRemoteType=%s]",
|
||||
this, NS_ConvertUTF16toUTF8(currentProcess->GetRemoteType()).get(),
|
||||
NS_ConvertUTF16toUTF8(preferredRemoteType).get()));
|
||||
|
||||
nsAutoString remoteType;
|
||||
rv = browser->GetRemoteTypeForPrincipal(
|
||||
resultPrincipal, browsingContext->UseRemoteTabs(),
|
||||
browsingContext->UseRemoteSubframes(), preferredRemoteType,
|
||||
currentPrincipal, browsingContext->GetParent(), remoteType);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
LOG(("Process Switch Abort: getRemoteTypeForPrincipal threw an exception"));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if a process switch is needed.
|
||||
if (currentProcess->GetRemoteType() == remoteType && !isCOOPSwitch) {
|
||||
LOG(("Process Switch Abort: type (%s) is compatible",
|
||||
NS_ConvertUTF16toUTF8(remoteType).get()));
|
||||
return false;
|
||||
}
|
||||
if (NS_WARN_IF(remoteType.IsEmpty())) {
|
||||
LOG(("Process Switch Abort: non-remote target process"));
|
||||
return false;
|
||||
}
|
||||
|
||||
LOG(("Process Switch: Changing Remoteness from '%s' to '%s'",
|
||||
NS_ConvertUTF16toUTF8(currentProcess->GetRemoteType()).get(),
|
||||
NS_ConvertUTF16toUTF8(remoteType).get()));
|
||||
|
||||
// XXX: This is super hacky, and we should be able to do something better.
|
||||
static uint64_t sNextCrossProcessRedirectIdentifier = 0;
|
||||
mCrossProcessRedirectIdentifier = ++sNextCrossProcessRedirectIdentifier;
|
||||
mDoingProcessSwitch = true;
|
||||
|
||||
RefPtr<DocumentLoadListener> self = this;
|
||||
// At this point, we're actually going to perform a process switch, which
|
||||
// involves calling into other logic.
|
||||
if (browsingContext->GetParent()) {
|
||||
LOG(("Process Switch: Calling ChangeFrameRemoteness"));
|
||||
// If we're switching a subframe, ask BrowsingContext to do it for us.
|
||||
MOZ_ASSERT(!isCOOPSwitch);
|
||||
browsingContext
|
||||
->ChangeFrameRemoteness(remoteType, mCrossProcessRedirectIdentifier)
|
||||
->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[self](BrowserParent* aBrowserParent) {
|
||||
MOZ_ASSERT(self->mChannel,
|
||||
"Something went wrong, channel got cancelled");
|
||||
self->TriggerRedirectToRealChannel(
|
||||
Some(aBrowserParent->Manager()->ChildID()));
|
||||
},
|
||||
[self](nsresult aStatusCode) {
|
||||
MOZ_ASSERT(NS_FAILED(aStatusCode), "Status should be error");
|
||||
self->RedirectToRealChannelFinished(aStatusCode);
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
LOG(("Process Switch: Calling nsIBrowser::PerformProcessSwitch"));
|
||||
// We're switching a toplevel BrowsingContext's process. This has to be done
|
||||
// using nsIBrowser.
|
||||
RefPtr<Promise> domPromise;
|
||||
browser->PerformProcessSwitch(remoteType, mCrossProcessRedirectIdentifier,
|
||||
isCOOPSwitch, getter_AddRefs(domPromise));
|
||||
MOZ_DIAGNOSTIC_ASSERT(domPromise,
|
||||
"PerformProcessSwitch didn't return a promise");
|
||||
|
||||
MozPromise<uint64_t, nsresult, true>::FromDomPromise(domPromise)
|
||||
->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[self](uint64_t aCpId) {
|
||||
MOZ_ASSERT(self->mChannel,
|
||||
"Something went wrong, channel got cancelled");
|
||||
self->TriggerRedirectToRealChannel(Some(aCpId));
|
||||
},
|
||||
[self](nsresult aStatusCode) {
|
||||
MOZ_ASSERT(NS_FAILED(aStatusCode), "Status should be error");
|
||||
self->RedirectToRealChannelFinished(aStatusCode);
|
||||
});
|
||||
return true;
|
||||
mRedirectContentProcessIdPromise->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[self, this](uint64_t aCpId) {
|
||||
MOZ_ASSERT(mChannel, "Something went wrong, channel got cancelled");
|
||||
TriggerRedirectToRealChannel(Some(aCpId));
|
||||
},
|
||||
[self](nsresult aStatusCode) {
|
||||
MOZ_ASSERT(NS_FAILED(aStatusCode), "Status should be error");
|
||||
self->RedirectToRealChannelFinished(aStatusCode);
|
||||
});
|
||||
}
|
||||
|
||||
RefPtr<PDocumentChannelParent::RedirectToRealChannelPromise>
|
||||
|
@ -1145,10 +984,18 @@ DocumentLoadListener::OnStartRequest(nsIRequest* aRequest) {
|
|||
httpChannel->SetApplyConversion(false);
|
||||
}
|
||||
|
||||
// Determine if a new process needs to be spawned. If it does, this will
|
||||
// trigger a cross process switch, and we should hold off on redirecting to
|
||||
// the real channel.
|
||||
if (status != NS_BINDING_ABORTED && MaybeTriggerProcessSwitch()) {
|
||||
// notify "channel-on-may-change-process" observers which is typically
|
||||
// SessionStore.jsm. This will determine if a new process needs to be
|
||||
// spawned and if so SwitchProcessTo() will be called which will set a
|
||||
// ContentProcessIdPromise.
|
||||
if (status != NS_BINDING_ABORTED) {
|
||||
nsCOMPtr<nsIObserverService> obsService = services::GetObserverService();
|
||||
obsService->NotifyObservers(ToSupports(this),
|
||||
"channel-on-may-change-process", nullptr);
|
||||
}
|
||||
|
||||
if (mRedirectContentProcessIdPromise) {
|
||||
TriggerCrossProcessSwitch();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1308,8 +1155,10 @@ DocumentLoadListener::AsyncOnChannelRedirect(
|
|||
// include the state of all channels we redirected through.
|
||||
RefPtr<nsHttpChannel> httpChannel = do_QueryObject(aOldChannel);
|
||||
if (httpChannel) {
|
||||
mHasCrossOriginOpenerPolicyMismatch |=
|
||||
httpChannel->HasCrossOriginOpenerPolicyMismatch();
|
||||
bool mismatch = false;
|
||||
MOZ_ALWAYS_SUCCEEDS(
|
||||
httpChannel->HasCrossOriginOpenerPolicyMismatch(&mismatch));
|
||||
mHasCrossOriginOpenerPolicyMismatch |= mismatch;
|
||||
}
|
||||
|
||||
// We don't need to confirm internal redirects or record any
|
||||
|
@ -1394,22 +1243,70 @@ DocumentLoadListener::AsyncOnChannelRedirect(
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// DocumentLoadListener::nsIProcessSwitchRequestor
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP DocumentLoadListener::GetChannel(nsIChannel** aChannel) {
|
||||
MOZ_ASSERT(mChannel);
|
||||
nsCOMPtr<nsIChannel> channel(mChannel);
|
||||
channel.forget(aChannel);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP DocumentLoadListener::SwitchProcessTo(
|
||||
dom::Promise* aContentProcessIdPromise, uint64_t aIdentifier) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
NS_ENSURE_ARG(aContentProcessIdPromise);
|
||||
|
||||
mRedirectContentProcessIdPromise =
|
||||
ContentProcessIdPromise::FromDomPromise(aContentProcessIdPromise);
|
||||
mCrossProcessRedirectIdentifier = aIdentifier;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// This method returns the cached result of running the Cross-Origin-Opener
|
||||
// policy compare algorithm by calling ComputeCrossOriginOpenerPolicyMismatch
|
||||
bool DocumentLoadListener::HasCrossOriginOpenerPolicyMismatch() {
|
||||
NS_IMETHODIMP
|
||||
DocumentLoadListener::HasCrossOriginOpenerPolicyMismatch(bool* aMismatch) {
|
||||
MOZ_ASSERT(aMismatch);
|
||||
|
||||
if (!aMismatch) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
// If we found a COOP mismatch on an earlier channel and then
|
||||
// redirected away from that, we should use that result.
|
||||
if (mHasCrossOriginOpenerPolicyMismatch) {
|
||||
return true;
|
||||
*aMismatch = true;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
RefPtr<nsHttpChannel> httpChannel = do_QueryObject(mChannel);
|
||||
if (!httpChannel) {
|
||||
// Not an nsHttpChannel assume it's okay to switch.
|
||||
return false;
|
||||
*aMismatch = false;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return httpChannel->HasCrossOriginOpenerPolicyMismatch();
|
||||
return httpChannel->HasCrossOriginOpenerPolicyMismatch(aMismatch);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
DocumentLoadListener::GetCachedCrossOriginOpenerPolicy(
|
||||
nsILoadInfo::CrossOriginOpenerPolicy* aPolicy) {
|
||||
MOZ_ASSERT(aPolicy);
|
||||
if (!aPolicy) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
RefPtr<nsHttpChannel> httpChannel = do_QueryObject(mChannel);
|
||||
if (!httpChannel) {
|
||||
*aPolicy = nsILoadInfo::OPENER_POLICY_UNSAFE_NONE;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
return httpChannel->GetCrossOriginOpenerPolicy(aPolicy);
|
||||
}
|
||||
|
||||
} // namespace net
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "nsIObserver.h"
|
||||
#include "nsIParentChannel.h"
|
||||
#include "nsIParentRedirectingChannel.h"
|
||||
#include "nsIProcessSwitchRequestor.h"
|
||||
#include "nsIRedirectResultListener.h"
|
||||
#include "nsIMultiPartChannel.h"
|
||||
|
||||
|
@ -59,6 +60,7 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
public nsIParentChannel,
|
||||
public nsIChannelEventSink,
|
||||
public HttpChannelSecurityWarningReporter,
|
||||
public nsIProcessSwitchRequestor,
|
||||
public nsIMultiPartChannelListener {
|
||||
public:
|
||||
explicit DocumentLoadListener(dom::CanonicalBrowsingContext* aBrowsingContext,
|
||||
|
@ -79,6 +81,7 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
NS_DECL_NSIINTERFACEREQUESTOR
|
||||
NS_DECL_NSIASYNCVERIFYREDIRECTREADYCALLBACK
|
||||
NS_DECL_NSICHANNELEVENTSINK
|
||||
NS_DECL_NSIPROCESSSWITCHREQUESTOR
|
||||
NS_DECL_NSIMULTIPARTCHANNELLISTENER
|
||||
|
||||
// We suspend the underlying channel when replacing ourselves with
|
||||
|
@ -172,10 +175,10 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
// by us, and resumes the underlying source channel.
|
||||
void FinishReplacementChannelSetup(bool aSucceeded);
|
||||
|
||||
// Called from `OnStartRequest` to make the decision about whether or not to
|
||||
// change process. This method will return `nullptr` if the current target
|
||||
// process is appropriate.
|
||||
bool MaybeTriggerProcessSwitch();
|
||||
// Called when we have a cross-process switch promise. Waits on the
|
||||
// promise, and then call TriggerRedirectToRealChannel with the
|
||||
// provided content process id.
|
||||
void TriggerCrossProcessSwitch();
|
||||
|
||||
// A helper for TriggerRedirectToRealChannel that abstracts over
|
||||
// the same-process and cross-process switch cases and returns
|
||||
|
@ -191,8 +194,6 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
dom::CanonicalBrowsingContext* aBrowsingContext,
|
||||
nsDocShellLoadState* aLoadState, uint64_t aOuterWindowId);
|
||||
|
||||
bool HasCrossOriginOpenerPolicyMismatch();
|
||||
|
||||
// This defines a variant that describes all the attribute setters (and their
|
||||
// parameters) from nsIParentChannel
|
||||
//
|
||||
|
@ -345,8 +346,16 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
|
|||
// channel.
|
||||
bool mIsFinished = false;
|
||||
|
||||
// This identifier is set by MaybeTriggerProcessSwitch, and is later
|
||||
// passed to the childChannel in order to identify it in the new process.
|
||||
typedef MozPromise<uint64_t, nsresult, true /* exclusive */>
|
||||
ContentProcessIdPromise;
|
||||
// This promise is set following a on-may-change-process observer
|
||||
// notification when the associated channel is getting relocated to another
|
||||
// process. It will be resolved when that process is set up.
|
||||
RefPtr<ContentProcessIdPromise> mRedirectContentProcessIdPromise;
|
||||
// This identifier is set at the same time as the
|
||||
// mRedirectContentProcessIdPromise.
|
||||
// This identifier is later passed to the childChannel in order to identify it
|
||||
// once the promise is resolved.
|
||||
uint64_t mCrossProcessRedirectIdentifier = 0;
|
||||
};
|
||||
|
||||
|
|
|
@ -6215,6 +6215,7 @@ NS_INTERFACE_MAP_BEGIN(nsHttpChannel)
|
|||
NS_INTERFACE_MAP_ENTRY(nsITimerCallback)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIChannelWithDivertableParentListener)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIRequestTailUnblockCallback)
|
||||
NS_INTERFACE_MAP_ENTRY(nsIProcessSwitchRequestor)
|
||||
NS_INTERFACE_MAP_ENTRY_CONCRETE(nsHttpChannel)
|
||||
NS_INTERFACE_MAP_END_INHERITING(HttpBaseChannel)
|
||||
|
||||
|
@ -7394,6 +7395,59 @@ nsHttpChannel::GetRequestMethod(nsACString& aMethod) {
|
|||
return HttpBaseChannel::GetRequestMethod(aMethod);
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
// nsHttpChannel::nsIProcessSwitchRequestor
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
NS_IMETHODIMP nsHttpChannel::GetChannel(nsIChannel** aChannel) {
|
||||
*aChannel = do_AddRef(this).take();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP nsHttpChannel::SwitchProcessTo(
|
||||
dom::Promise* aContentProcessIdPromise, uint64_t aIdentifier) {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
NS_ENSURE_ARG(aContentProcessIdPromise);
|
||||
|
||||
LOG(("nsHttpChannel::SwitchProcessTo [this=%p]", this));
|
||||
LogCallingScriptLocation(this);
|
||||
|
||||
nsCOMPtr<nsIParentChannel> parentChannel;
|
||||
NS_QueryNotificationCallbacks(this, parentChannel);
|
||||
RefPtr<DocumentLoadListener> documentChannelParent =
|
||||
do_QueryObject(parentChannel);
|
||||
// This is a temporary change as the DocumentChannelParent currently must go
|
||||
// through the nsHttpChannel to perform a process switch via SessionStore.
|
||||
if (!documentChannelParent) {
|
||||
// We cannot do this after OnStartRequest of the listener has been called.
|
||||
NS_ENSURE_FALSE(mOnStartRequestCalled, NS_ERROR_NOT_AVAILABLE);
|
||||
}
|
||||
|
||||
mRedirectContentProcessIdPromise =
|
||||
ContentProcessIdPromise::FromDomPromise(aContentProcessIdPromise);
|
||||
mCrossProcessRedirectIdentifier = aIdentifier;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// This method returns the cached result of running the Cross-Origin-Opener
|
||||
// policy compare algorithm by calling ComputeCrossOriginOpenerPolicyMismatch
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::HasCrossOriginOpenerPolicyMismatch(bool* aMismatch) {
|
||||
MOZ_ASSERT(aMismatch);
|
||||
if (!aMismatch) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
*aMismatch = mHasCrossOriginOpenerPolicyMismatch;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsHttpChannel::GetCachedCrossOriginOpenerPolicy(
|
||||
nsILoadInfo::CrossOriginOpenerPolicy* aPolicy) {
|
||||
return HttpBaseChannel::GetCrossOriginOpenerPolicy(aPolicy);
|
||||
}
|
||||
|
||||
// See https://gist.github.com/annevk/6f2dd8c79c77123f39797f6bdac43f3e
|
||||
// This method runs steps 1-4 of the algorithm to compare
|
||||
// cross-origin-opener policies
|
||||
|
|
|
@ -32,6 +32,7 @@
|
|||
#include "mozilla/Atomics.h"
|
||||
#include "mozilla/extensions/PStreamFilterParent.h"
|
||||
#include "mozilla/Mutex.h"
|
||||
#include "nsIProcessSwitchRequestor.h"
|
||||
|
||||
class nsDNSPrefetch;
|
||||
class nsICancelable;
|
||||
|
@ -78,7 +79,8 @@ class nsHttpChannel final : public HttpBaseChannel,
|
|||
public nsIChannelWithDivertableParentListener,
|
||||
public nsIRaceCacheWithNetwork,
|
||||
public nsIRequestTailUnblockCallback,
|
||||
public nsITimerCallback {
|
||||
public nsITimerCallback,
|
||||
public nsIProcessSwitchRequestor {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
NS_DECL_NSIREQUESTOBSERVER
|
||||
|
@ -100,6 +102,7 @@ class nsHttpChannel final : public HttpBaseChannel,
|
|||
NS_DECL_NSIRACECACHEWITHNETWORK
|
||||
NS_DECL_NSITIMERCALLBACK
|
||||
NS_DECL_NSIREQUESTTAILUNBLOCKCALLBACK
|
||||
NS_DECL_NSIPROCESSSWITCHREQUESTOR
|
||||
|
||||
// nsIHttpAuthenticableChannel. We can't use
|
||||
// NS_DECL_NSIHTTPAUTHENTICABLECHANNEL because it duplicates cancel() and
|
||||
|
@ -274,6 +277,16 @@ class nsHttpChannel final : public HttpBaseChannel,
|
|||
}
|
||||
TransactionObserver* GetTransactionObserver() { return mTransactionObserver; }
|
||||
|
||||
typedef MozPromise<uint64_t, nsresult, true /* exclusive */>
|
||||
ContentProcessIdPromise;
|
||||
already_AddRefed<ContentProcessIdPromise>
|
||||
TakeRedirectContentProcessIdPromise() {
|
||||
return mRedirectContentProcessIdPromise.forget();
|
||||
}
|
||||
uint64_t CrossProcessRedirectIdentifier() {
|
||||
return mCrossProcessRedirectIdentifier;
|
||||
}
|
||||
|
||||
CacheDisposition mCacheDisposition;
|
||||
|
||||
protected:
|
||||
|
@ -482,11 +495,6 @@ class nsHttpChannel final : public HttpBaseChannel,
|
|||
nsresult ProcessCrossOriginResourcePolicyHeader();
|
||||
|
||||
nsresult ComputeCrossOriginOpenerPolicyMismatch();
|
||||
// This method returns the cached result of running the Cross-Origin-Opener
|
||||
// policy compare algorithm by calling ComputeCrossOriginOpenerPolicyMismatch
|
||||
bool HasCrossOriginOpenerPolicyMismatch() {
|
||||
return mHasCrossOriginOpenerPolicyMismatch;
|
||||
}
|
||||
|
||||
/**
|
||||
* A function to process a single security header (STS or PKP), assumes
|
||||
|
@ -574,6 +582,12 @@ class nsHttpChannel final : public HttpBaseChannel,
|
|||
nsCOMPtr<nsIChannel> mRedirectChannel;
|
||||
nsCOMPtr<nsIChannel> mPreflightChannel;
|
||||
|
||||
// The associated childChannel is getting relocated to another process.
|
||||
// This promise will be resolved when that process is set up.
|
||||
RefPtr<ContentProcessIdPromise> mRedirectContentProcessIdPromise;
|
||||
// This identifier is passed to the childChannel in order to identify it.
|
||||
uint64_t mCrossProcessRedirectIdentifier = 0;
|
||||
|
||||
// nsChannelClassifier checks this channel's URI against
|
||||
// the URI classifier service.
|
||||
// nsChannelClassifier will be invoked twice in InitLocalBlockList() and
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "nsStandardURL.h"
|
||||
#include "LoadContextInfo.h"
|
||||
#include "nsCategoryManagerUtils.h"
|
||||
#include "nsIProcessSwitchRequestor.h"
|
||||
#include "nsSocketProviderService.h"
|
||||
#include "nsISocketProvider.h"
|
||||
#include "nsPrintfCString.h"
|
||||
|
|
|
@ -35,6 +35,7 @@ class nsIHttpUpgradeListener;
|
|||
class nsIPrefBranch;
|
||||
class nsICancelable;
|
||||
class nsICookieService;
|
||||
class nsIProcessSwitchRequestor;
|
||||
class nsIIOService;
|
||||
class nsIRequestContextService;
|
||||
class nsISiteSecurityService;
|
||||
|
|
|
@ -2034,41 +2034,6 @@
|
|||
}
|
||||
return origins;
|
||||
}
|
||||
|
||||
get canPerformProcessSwitch() {
|
||||
return this.getTabBrowser() != null;
|
||||
}
|
||||
|
||||
performProcessSwitch(
|
||||
remoteType,
|
||||
redirectLoadSwitchId,
|
||||
replaceBrowsingContext
|
||||
) {
|
||||
return this.getTabBrowser().performProcessSwitch(
|
||||
this,
|
||||
remoteType,
|
||||
redirectLoadSwitchId,
|
||||
replaceBrowsingContext
|
||||
);
|
||||
}
|
||||
|
||||
getRemoteTypeForPrincipal(
|
||||
principal,
|
||||
remoteTabs,
|
||||
remoteSubframes,
|
||||
preferredRemoteType,
|
||||
currentPrincipal,
|
||||
isSubframe
|
||||
) {
|
||||
return E10SUtils.getRemoteTypeForPrincipal(
|
||||
principal,
|
||||
remoteTabs,
|
||||
remoteSubframes,
|
||||
preferredRemoteType,
|
||||
currentPrincipal,
|
||||
isSubframe
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
MozXULElement.implementCustomInterface(MozBrowser, [Ci.nsIBrowser]);
|
||||
|
|
Загрузка…
Ссылка в новой задаче