Bug 1647557 - Add preffed-off code for controlling document loads directly from CanonicalBrowsingContext. r=nika,jya,necko-reviewers,dragana

Differential Revision: https://phabricator.services.mozilla.com/D70629
This commit is contained in:
Matt Woodrow 2020-06-30 01:19:15 +00:00
Родитель 751fe6358b
Коммит 7d65de1298
7 изменённых файлов: 287 добавлений и 64 удалений

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

@ -1584,11 +1584,15 @@ nsresult BrowsingContext::LoadURI(nsDocShellLoadState* aLoadState,
return NS_ERROR_UNEXPECTED;
}
if (Canonical()->LoadInParent(aLoadState, aSetNavigating)) {
return NS_OK;
}
if (ContentParent* cp = Canonical()->GetContentParent()) {
// Attempt to initiate this load immediately in the parent, if it succeeds
// it'll return a unique identifier so that we can find it later.
uint64_t loadIdentifier = 0;
if (Canonical()->AttemptLoadURIInParent(aLoadState)) {
if (Canonical()->AttemptSpeculativeLoadInParent(aLoadState)) {
MOZ_DIAGNOSTIC_ASSERT(GetCurrentLoadIdentifier().isSome());
loadIdentifier = GetCurrentLoadIdentifier().value();
aLoadState->SetChannelInitialized(true);

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

@ -942,16 +942,8 @@ MediaController* CanonicalBrowsingContext::GetMediaController() {
return mTabMediaController;
}
bool CanonicalBrowsingContext::AttemptLoadURIInParent(
nsDocShellLoadState* aLoadState) {
// We currently only support starting loads directly from the
// CanonicalBrowsingContext for top-level BCs.
if (!IsTopContent() || !GetContentParent() ||
!StaticPrefs::browser_tabs_documentchannel() ||
!StaticPrefs::browser_tabs_documentchannel_parent_initiated()) {
return false;
}
bool CanonicalBrowsingContext::SupportsLoadingInParent(
nsDocShellLoadState* aLoadState, uint64_t* aOuterWindowId) {
// We currently don't support initiating loads in the parent when they are
// watched by devtools. This is because devtools tracks loads using content
// process notifications, which happens after the load is initiated in this
@ -969,7 +961,6 @@ bool CanonicalBrowsingContext::AttemptLoadURIInParent(
return false;
}
uint64_t outerWindowId = 0;
if (WindowGlobalParent* global = GetCurrentWindowGlobal()) {
nsCOMPtr<nsIURI> currentURI = global->GetDocumentURI();
if (currentURI) {
@ -990,20 +981,72 @@ bool CanonicalBrowsingContext::AttemptLoadURIInParent(
return false;
}
outerWindowId = global->OuterWindowId();
*aOuterWindowId = global->OuterWindowId();
}
return true;
}
bool CanonicalBrowsingContext::LoadInParent(nsDocShellLoadState* aLoadState,
bool aSetNavigating) {
// We currently only support starting loads directly from the
// CanonicalBrowsingContext for top-level BCs.
// We currently only support starting loads directly from the
// CanonicalBrowsingContext for top-level BCs.
if (!IsTopContent() || !GetContentParent() ||
!StaticPrefs::browser_tabs_documentchannel() ||
!StaticPrefs::browser_tabs_documentchannel_parent_controlled()) {
return false;
}
uint64_t outerWindowId = 0;
if (!SupportsLoadingInParent(aLoadState, &outerWindowId)) {
return false;
}
// Note: If successful, this will recurse into StartDocumentLoad and
// set mCurrentLoad to the DocumentLoadListener instance created.
// Ideally in the future we will only start loads from here, and we can
// just set this directly instead.
return net::DocumentLoadListener::LoadInParent(this, aLoadState,
outerWindowId, aSetNavigating);
}
bool CanonicalBrowsingContext::AttemptSpeculativeLoadInParent(
nsDocShellLoadState* aLoadState) {
// We currently only support starting loads directly from the
// CanonicalBrowsingContext for top-level BCs.
// We currently only support starting loads directly from the
// CanonicalBrowsingContext for top-level BCs.
if (!IsTopContent() || !GetContentParent() ||
!StaticPrefs::browser_tabs_documentchannel() ||
!StaticPrefs::browser_tabs_documentchannel_parent_initiated() ||
StaticPrefs::browser_tabs_documentchannel_parent_controlled()) {
return false;
}
uint64_t outerWindowId = 0;
if (!SupportsLoadingInParent(aLoadState, &outerWindowId)) {
return false;
}
// If we successfully open the DocumentChannel, then it'll register
// itself using aLoadIdentifier and be kept alive until it completes
// loading.
return net::DocumentLoadListener::OpenFromParent(this, aLoadState,
return net::DocumentLoadListener::SpeculativeLoadInParent(this, aLoadState,
outerWindowId);
}
void CanonicalBrowsingContext::StartDocumentLoad(
bool CanonicalBrowsingContext::StartDocumentLoad(
net::DocumentLoadListener* aLoad) {
// If we're controlling loads from the parent, then starting a new load means
// that we need to cancel any existing ones.
if (StaticPrefs::browser_tabs_documentchannel_parent_controlled() &&
mCurrentLoad) {
mCurrentLoad->Cancel(NS_BINDING_ABORTED);
}
mCurrentLoad = aLoad;
SetCurrentLoadIdentifier(Some(aLoad->GetLoadIdentifier()));
return true;
}
void CanonicalBrowsingContext::EndDocumentLoad(bool aForProcessSwitch) {

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

@ -161,7 +161,17 @@ class CanonicalBrowsingContext final : public BrowsingContext {
// if the top-level browsing context has been discarded.
MediaController* GetMediaController();
bool AttemptLoadURIInParent(nsDocShellLoadState* aLoadState);
// Attempts to start loading the given load state in this BrowsingContext,
// without requiring any communication from a docshell. This will handle
// computing the right process to load in, and organising handoff to
// the right docshell when we get a response.
bool LoadInParent(nsDocShellLoadState* aLoadState, bool aSetNavigating);
// Attempts to start loading the given load state in this BrowsingContext,
// in parallel with a DocumentChannelChild being created in the docshell.
// Requires the DocumentChannel to connect with this load for it to
// complete successfully.
bool AttemptSpeculativeLoadInParent(nsDocShellLoadState* aLoadState);
// Get or create a secure browser UI for this BrowsingContext
nsISecureBrowserUI* GetSecureBrowserUI();
@ -230,13 +240,17 @@ class CanonicalBrowsingContext final : public BrowsingContext {
friend class net::DocumentLoadListener;
// Called when a DocumentLoadListener is created to start a load for
// this browsing context.
void StartDocumentLoad(net::DocumentLoadListener* aLoad);
// this browsing context. Returns false if a higher priority load is
// already in-progress and the new one has been rejected.
bool StartDocumentLoad(net::DocumentLoadListener* aLoad);
// Called once DocumentLoadListener completes handling a load, and it
// is either complete, or handed off to the final channel to deliver
// data to the destination docshell.
void EndDocumentLoad(bool aForProcessSwitch);
bool SupportsLoadingInParent(nsDocShellLoadState* aLoadState,
uint64_t* aOuterWindowId);
// XXX(farre): Store a ContentParent pointer here rather than mProcessId?
// Indicates which process owns the docshell.
uint64_t mProcessId;

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

@ -1068,13 +1068,21 @@
value: true
mirror: always
# If set, use DocumentChannel to directly initiate loads from
# parent-process BrowsingContexts
# If set, use DocumentChannel to initiate loads from
# parent-process BrowsingContexts in parallel with the content
# process.
- name: browser.tabs.documentchannel.parent-initiated
type: bool
value: true
mirror: always
# If set, use DocumentChannel to directly initiate loads entirely
# from parent-process BrowsingContexts
- name: browser.tabs.documentchannel.parent-controlled
type: bool
value: false
mirror: always
- name: browser.tabs.remote.desktopbehavior
type: bool
value: false

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

@ -29,6 +29,7 @@
#include "nsDocShell.h"
#include "nsDocShellLoadState.h"
#include "nsDocShellLoadTypes.h"
#include "nsDOMNavigationTiming.h"
#include "nsExternalHelperAppService.h"
#include "nsHttpChannel.h"
#include "nsIBrowser.h"
@ -358,7 +359,7 @@ already_AddRefed<LoadInfo> DocumentLoadListener::CreateLoadInfo(
return loadInfo.forget();
}
CanonicalBrowsingContext* DocumentLoadListener::GetBrowsingContext() {
CanonicalBrowsingContext* DocumentLoadListener::GetBrowsingContext() const {
if (!mParentChannelListener) {
return nullptr;
}
@ -397,6 +398,8 @@ auto DocumentLoadListener::Open(
browsingContext, aLoadState, loadInfo, mParentChannelListener,
nullptr, attrs, loadFlags, aCacheKey, *aRv,
getter_AddRefs(mChannel))) {
LOG(("DocumentLoadListener::Open failed to create channel [this=%p]",
this));
mParentChannelListener = nullptr;
return nullptr;
}
@ -457,6 +460,15 @@ auto DocumentLoadListener::Open(
// across any serviceworker related data between channels as needed.
AddClientChannelHelperInParent(mChannel, std::move(aInfo));
if (!browsingContext->StartDocumentLoad(this)) {
LOG(("DocumentLoadListener::Open failed StartDocumentLoad [this=%p]",
this));
*aRv = NS_BINDING_ABORTED;
mParentChannelListener = nullptr;
mChannel = nullptr;
return nullptr;
}
// Recalculate the openFlags, matching the logic in use in Content process.
// NOTE: The only case not handled here to mirror Content process is
// redirecting to re-use the channel.
@ -511,6 +523,10 @@ auto DocumentLoadListener::Open(
{
*aRv = mChannel->AsyncOpen(openInfo);
if (NS_FAILED(*aRv)) {
LOG(("DocumentLoadListener::Open failed AsyncOpen [this=%p rv=%" PRIx32
"]",
this, static_cast<uint32_t>(*aRv)));
browsingContext->EndDocumentLoad(false);
mParentChannelListener = nullptr;
return nullptr;
}
@ -530,8 +546,6 @@ auto DocumentLoadListener::Open(
browsingContext->CreateSessionHistoryEntryForLoad(aLoadState, mChannel);
}
browsingContext->StartDocumentLoad(this);
*aRv = NS_OK;
mOpenPromise = new OpenPromise::Private(__func__);
// We make the promise use direct task dispatch in order to reduce the number
@ -540,18 +554,16 @@ auto DocumentLoadListener::Open(
return mOpenPromise;
}
/* static */
bool DocumentLoadListener::OpenFromParent(
dom::CanonicalBrowsingContext* aBrowsingContext,
nsDocShellLoadState* aLoadState, uint64_t aOuterWindowId) {
LOG(("DocumentLoadListener::OpenFromParent"));
auto DocumentLoadListener::OpenInParent(nsDocShellLoadState* aLoadState,
uint64_t aOuterWindowId,
bool aSupportsRedirectToRealChannel)
-> RefPtr<OpenPromise> {
// We currently only support passing nullptr for aLoadInfo for
// top level browsing contexts.
if (!aBrowsingContext->IsTopContent() ||
!aBrowsingContext->GetContentParent()) {
LOG(("DocumentLoadListener::OpenFromParent failed because of subdoc"));
return false;
if (!GetBrowsingContext()->IsTopContent() ||
!GetBrowsingContext()->GetContentParent()) {
LOG(("DocumentLoadListener::OpenInParent failed because of subdoc"));
return nullptr;
}
if (nsCOMPtr<nsIContentSecurityPolicy> csp = aLoadState->Csp()) {
@ -563,7 +575,7 @@ bool DocumentLoadListener::OpenFromParent(
false, /* aEnforceWhitelist */
&allowsNavigateTo);
if (NS_FAILED(rv) || !allowsNavigateTo) {
return false;
return nullptr;
}
}
@ -576,9 +588,9 @@ bool DocumentLoadListener::OpenFromParent(
loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_CACHE ||
loadType == LOAD_RELOAD_CHARSET_CHANGE_BYPASS_PROXY_AND_CACHE) {
LOG(
("DocumentLoadListener::OpenFromParent failed because of history "
("DocumentLoadListener::OpenInParent failed because of history "
"load"));
return false;
return nullptr;
}
// Clone because this mutates the load flags in the load state, which
@ -588,7 +600,7 @@ bool DocumentLoadListener::OpenFromParent(
RefPtr<nsDOMNavigationTiming> timing = new nsDOMNavigationTiming(nullptr);
timing->NotifyNavigationStart(
aBrowsingContext->GetIsActive()
GetBrowsingContext()->GetIsActive()
? nsDOMNavigationTiming::DocShellState::eActive
: nsDOMNavigationTiming::DocShellState::eInactive);
@ -604,22 +616,110 @@ bool DocumentLoadListener::OpenFromParent(
// not supporting yet.
Maybe<dom::ClientInfo> initialClientInfo;
mSupportsRedirectToRealChannel = aSupportsRedirectToRealChannel;
nsresult rv;
return Open(loadState, cacheKey, channelId, TimeStamp::Now(), timing,
std::move(initialClientInfo), aOuterWindowId, false, Nothing(),
Nothing(), GetBrowsingContext()->GetContentParent()->OtherPid(),
&rv);
}
static void FireStateChange(DocumentLoadListener* aLoad, uint32_t aStateFlags,
nsresult aStatus) {
nsCOMPtr<nsIChannel> request = aLoad->GetChannel();
nsCOMPtr<nsIWebProgress> webProgress =
new RemoteWebProgress(aLoad->GetLoadType(), true, true);
RefPtr<CanonicalBrowsingContext> ctx = aLoad->GetBrowsingContext();
NS_DispatchToMainThread(
NS_NewRunnableFunction("DocumentLoadListener::FireStateChange", [=]() {
if (ctx && ctx->GetWebProgress()) {
ctx->GetWebProgress()->OnStateChange(webProgress, request,
aStateFlags, aStatus);
}
}));
}
static void SetNavigating(CanonicalBrowsingContext* aBrowsingContext,
bool aNavigating) {
nsCOMPtr<nsIBrowser> browser;
if (RefPtr<Element> currentElement = aBrowsingContext->GetEmbedderElement()) {
browser = currentElement->AsBrowser();
}
if (!browser) {
return;
}
NS_DispatchToMainThread(NS_NewRunnableFunction(
"DocumentLoadListener::SetNavigating",
[browser, aNavigating]() { browser->SetIsNavigating(aNavigating); }));
}
/* static */ bool DocumentLoadListener::LoadInParent(
CanonicalBrowsingContext* aBrowsingContext, nsDocShellLoadState* aLoadState,
uint64_t aOuterWindowId, bool aSetNavigating) {
SetNavigating(aBrowsingContext, aSetNavigating);
RefPtr<DocumentLoadListener> load =
new DocumentLoadListener(aBrowsingContext);
RefPtr<DocumentLoadListener::OpenPromise> promise = load->OpenInParent(
aLoadState, aOuterWindowId, /* aSupportsRedirectToRealChannel */ false);
if (!promise) {
SetNavigating(aBrowsingContext, false);
return false;
}
// We passed false for aSupportsRedirectToRealChannel, so we should always
// take the process switching path, and reject this promise.
promise->Then(
GetCurrentSerialEventTarget(), __func__,
[load](DocumentLoadListener::OpenPromise::ResolveOrRejectValue&& aValue) {
MOZ_ASSERT(aValue.IsReject());
DocumentLoadListener::OpenPromiseFailedType& rejectValue =
aValue.RejectValue();
if (!rejectValue.mSwitchedProcess) {
// If we're not switching the load to a new process, then it is
// finished (and failed), and we should fire a state change to notify
// observers. Normally the docshell would fire this, and it would get
// filtered out by BrowserParent if needed.
FireStateChange(load,
nsIWebProgressListener::STATE_STOP |
nsIWebProgressListener::STATE_IS_WINDOW |
nsIWebProgressListener::STATE_IS_NETWORK,
rejectValue.mStatus);
}
});
FireStateChange(load,
nsIWebProgressListener::STATE_START |
nsIWebProgressListener::STATE_IS_DOCUMENT |
nsIWebProgressListener::STATE_IS_REQUEST |
nsIWebProgressListener::STATE_IS_WINDOW |
nsIWebProgressListener::STATE_IS_NETWORK,
NS_OK);
SetNavigating(aBrowsingContext, false);
return true;
}
/* static */
bool DocumentLoadListener::SpeculativeLoadInParent(
dom::CanonicalBrowsingContext* aBrowsingContext,
nsDocShellLoadState* aLoadState, uint64_t aOuterWindowId) {
LOG(("DocumentLoadListener::OpenFromParent"));
RefPtr<DocumentLoadListener> listener =
new DocumentLoadListener(aBrowsingContext);
nsresult rv;
auto promise = listener->Open(
loadState, cacheKey, channelId, TimeStamp::Now(), timing,
std::move(initialClientInfo), aOuterWindowId, false, Nothing(), Nothing(),
aBrowsingContext->GetContentParent()->OtherPid(), &rv);
auto promise = listener->OpenInParent(aLoadState, aOuterWindowId, true);
if (promise) {
MOZ_ASSERT(NS_SUCCEEDED(rv));
// Create an entry in the redirect channel registrar to
// allocate an identifier for this load.
nsCOMPtr<nsIRedirectChannelRegistrar> registrar =
RedirectChannelRegistrar::GetOrCreate();
uint64_t loadIdentifier = aLoadState->GetLoadIdentifier();
rv = registrar->RegisterChannel(nullptr, loadIdentifier);
nsresult rv = registrar->RegisterChannel(nullptr, loadIdentifier);
MOZ_ASSERT(NS_SUCCEEDED(rv));
// Register listener (as an nsIParentChannel) under our new identifier.
rv = registrar->LinkChannels(loadIdentifier, listener, nullptr);
@ -712,14 +812,15 @@ void DocumentLoadListener::Cancel(const nsresult& aStatusCode) {
}
void DocumentLoadListener::DisconnectListeners(nsresult aStatus,
nsresult aLoadGroupStatus) {
nsresult aLoadGroupStatus,
bool aSwitchedProcess) {
LOG(
("DocumentLoadListener DisconnectListener [this=%p, "
"aStatus=%" PRIx32 " aLoadGroupStatus=%" PRIx32 " ]",
this, static_cast<uint32_t>(aStatus),
static_cast<uint32_t>(aLoadGroupStatus)));
RejectOpenPromise(aStatus, aLoadGroupStatus, __func__);
RejectOpenPromise(aStatus, aLoadGroupStatus, aSwitchedProcess, __func__);
Disconnect();
@ -786,7 +887,8 @@ void DocumentLoadListener::FinishReplacementChannelSetup(nsresult aResult) {
});
if (mDoingProcessSwitch) {
DisconnectListeners(NS_BINDING_ABORTED, NS_BINDING_ABORTED);
DisconnectListeners(NS_BINDING_ABORTED, NS_BINDING_ABORTED,
NS_SUCCEEDED(aResult));
}
nsCOMPtr<nsIRedirectChannelRegistrar> registrar =
@ -1642,6 +1744,11 @@ DocumentLoadListener::OnStartRequest(nsIRequest* aRequest) {
// might cancel the channel.
nsContentSecurityUtils::PerformCSPFrameAncestorAndXFOCheck(mChannel);
if (!GetBrowsingContext() || GetBrowsingContext()->IsDiscarded()) {
DisconnectListeners(NS_ERROR_UNEXPECTED, NS_ERROR_UNEXPECTED);
return NS_ERROR_UNEXPECTED;
}
// Generally we want to switch to a real channel even if the request failed,
// since the listener might want to access protocol-specific data (like http
// response headers) in its error handling.
@ -1681,7 +1788,34 @@ DocumentLoadListener::OnStartRequest(nsIRequest* aRequest) {
bool willBeRemote = false;
if (!DocShellWillDisplayContent(status) ||
!MaybeTriggerProcessSwitch(&willBeRemote)) {
TriggerRedirectToRealChannel();
if (!mSupportsRedirectToRealChannel) {
// 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(GetBrowsingContext()->GetCurrentWindowGlobal());
RefPtr<BrowserParent> browserParent =
GetBrowsingContext()->GetCurrentWindowGlobal()->GetBrowserParent();
// This load has already started, so we want to suspend the start progress
// events from the docshell from reaching the parent.
browserParent->SuspendProgressEventsUntilAfterNextLoadStarts();
// Notify the docshell that it should load using the newly connected
// channel
browserParent->ResumeLoad(mLoadIdentifier);
// Use the current process ID to run the 'process switch' path and connect
// the channel into the current process.
TriggerRedirectToRealChannel(
Some(GetBrowsingContext()->OwnerProcessId()));
} else {
TriggerRedirectToRealChannel(Nothing());
}
// If we're not switching, then check if we're currently remote.
if (GetBrowsingContext() && GetBrowsingContext()->GetContentParent()) {
@ -1870,7 +2004,7 @@ NS_IMETHODIMP
DocumentLoadListener::AsyncOnChannelRedirect(
nsIChannel* aOldChannel, nsIChannel* aNewChannel, uint32_t aFlags,
nsIAsyncVerifyRedirectCallback* aCallback) {
LOG(("DocumentLoadListener AsyncOnChannelRedirect [this=%p, aFlags=%" PRIx32
LOG(("DocumentLoadListener::AsyncOnChannelRedirect [this=%p flags=%" PRIu32
"]",
this, aFlags));
// We generally don't want to notify the content process about redirects,

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

@ -9,6 +9,7 @@
#include "mozilla/MozPromise.h"
#include "mozilla/Variant.h"
#include "mozilla/ipc/ProtocolUtils.h"
#include "mozilla/dom/SessionHistoryEntry.h"
#include "mozilla/net/NeckoCommon.h"
#include "mozilla/net/NeckoParent.h"
@ -107,6 +108,9 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
struct OpenPromiseFailedType {
nsresult mStatus;
nsresult mLoadGroupStatus;
// This is set to true if we're rejecting the promise because we
// switched to load away to a new process.
bool mSwitchedProcess = false;
};
typedef MozPromise<OpenPromiseSucceededType, OpenPromiseFailedType,
@ -130,14 +134,22 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
Maybe<bool> aUriModified, Maybe<bool> aIsXFOError,
base::ProcessId aPid, nsresult* aRv);
// Creates a DocumentLoadListener directly in the parent process without
// an associated DocumentChannel.
// Creates a DocumentLoadListener entirely in the parent process and opens it,
// and never needs a DocumentChannel to connect to an existing docshell.
// Once we get a response it takes the 'process switch' path to find the right
// process and docshell, and delivers the response there directly.
static bool LoadInParent(dom::CanonicalBrowsingContext* aBrowsingContext,
nsDocShellLoadState* aLoadState,
uint64_t aOuterWindowId, bool aSetNavigating);
// Creates a DocumentLoadListener directly in the parent process and opens it,
// without needing an existing DocumentChannel.
// If successful it registers a unique identifier (return in aOutIdent) to
// keep it alive until a future DocumentChannel can attach to it, or we fail
// and clean up.
static bool OpenFromParent(dom::CanonicalBrowsingContext* aBrowsingContext,
nsDocShellLoadState* aLoadState,
uint64_t aOuterWindowId);
static bool SpeculativeLoadInParent(
dom::CanonicalBrowsingContext* aBrowsingContext,
nsDocShellLoadState* aLoadState, uint64_t aOuterWindowId);
// Ensures that a load identifier allocated by OpenFromParent has
// been deregistered if it hasn't already been claimed.
@ -225,14 +237,22 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
dom::ContentParent* aParent) const;
uint64_t GetLoadIdentifier() const { return mLoadIdentifier; }
dom::CanonicalBrowsingContext* GetBrowsingContext() const;
uint32_t GetLoadType() const { return mLoadStateLoadType; }
protected:
virtual ~DocumentLoadListener();
private:
RefPtr<OpenPromise> OpenInParent(nsDocShellLoadState* aLoadState,
uint64_t aOuterWindowId,
bool aSupportsRedirectToRealChannel);
friend class ParentProcessDocumentOpenInfo;
// Will reject the promise to notify the DLL consumer that we are done.
void DisconnectListeners(nsresult aStatus, nsresult aLoadGroupStatus);
void DisconnectListeners(nsresult aStatus, nsresult aLoadGroupStatus,
bool aSwitchedProcess = false);
// Called when we were created without a document channel, and creation has
// failed, and won't ever be attached.
@ -241,8 +261,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<uint64_t>& aDestinationProcess = Nothing());
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
@ -281,8 +300,6 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
dom::CanonicalBrowsingContext* aBrowsingContext,
nsDocShellLoadState* aLoadState, uint64_t aOuterWindowId);
dom::CanonicalBrowsingContext* GetBrowsingContext();
void AddURIVisit(nsIChannel* aChannel, uint32_t aLoadFlags);
bool HasCrossOriginOpenerPolicyMismatch() const;
void ApplyPendingFunctions(nsIParentChannel* aChannel) const;
@ -456,16 +473,19 @@ class DocumentLoadListener : public nsIInterfaceRequestor,
Maybe<nsCString> mOriginalUriString;
bool mSupportsRedirectToRealChannel = true;
// 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,
const char* aLocation) {
bool aSwitchedProcess, const char* aLocation) {
// It is possible for mOpenPromise to not be set if AsyncOpen failed and
// the DocumentChannel got canceled.
if (!mOpenPromiseResolved && mOpenPromise) {
mOpenPromise->Reject(OpenPromiseFailedType({aStatus, aLoadGroupStatus}),
mOpenPromise->Reject(
OpenPromiseFailedType({aStatus, aLoadGroupStatus, aSwitchedProcess}),
aLocation);
mOpenPromiseResolved = true;
}

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

@ -64,7 +64,7 @@ class ParentChannelListener final : public nsIInterfaceRequestor,
// Called to set a new listener which replaces the old one after a redirect.
void SetListenerAfterRedirect(nsIStreamListener* aListener);
dom::CanonicalBrowsingContext* GetBrowsingContext() {
dom::CanonicalBrowsingContext* GetBrowsingContext() const {
return mBrowsingContext;
}