Bug 1646892 - Allow DocumentChannel process switches into the parent process. r=jya,nika
Differential Revision: https://phabricator.services.mozilla.com/D80327
This commit is contained in:
@@ -79,6 +79,7 @@
|
||||
#include "mozilla/dom/JSWindowActorChild.h"
|
||||
#include "mozilla/ipc/ProtocolUtils.h"
|
||||
#include "mozilla/net/DocumentChannel.h"
|
||||
#include "mozilla/net/ParentChannelWrapper.h"
|
||||
#include "mozilla/net/UrlClassifierFeatureFactory.h"
|
||||
#include "ReferrerInfo.h"
|
||||
|
||||
@@ -206,6 +207,7 @@
|
||||
#include "nsSHEntry.h"
|
||||
#include "nsStructuredCloneContainer.h"
|
||||
#include "nsSubDocumentFrame.h"
|
||||
#include "nsURILoader.h"
|
||||
#include "nsView.h"
|
||||
#include "nsViewManager.h"
|
||||
#include "nsViewSourceHandler.h"
|
||||
@@ -9436,8 +9438,7 @@ nsresult nsDocShell::DoURILoad(nsDocShellLoadState* aLoadState,
|
||||
outRequest.forget(aRequest);
|
||||
}
|
||||
|
||||
return OpenInitializedChannel(channel, uriLoader,
|
||||
nsIURILoader::REDIRECTED_CHANNEL);
|
||||
return OpenRedirectedChannel(aLoadState);
|
||||
}
|
||||
|
||||
// There are two cases we care about:
|
||||
@@ -9723,15 +9724,10 @@ static nsresult AppendSegmentToString(nsIInputStream* aIn, void* aClosure,
|
||||
return openFlags;
|
||||
}
|
||||
|
||||
nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel,
|
||||
nsIURILoader* aURILoader,
|
||||
uint32_t aOpenFlags) {
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
void nsDocShell::UpdateMixedContentChannelForNewLoad(nsIChannel* aChannel) {
|
||||
if (mLoadType == LOAD_NORMAL_ALLOW_MIXED_CONTENT ||
|
||||
mLoadType == LOAD_RELOAD_ALLOW_MIXED_CONTENT) {
|
||||
rv = SetMixedContentChannel(aChannel);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
SetMixedContentChannel(aChannel);
|
||||
} else if (mMixedContentChannel) {
|
||||
/*
|
||||
* If the user "Disables Protection on This Page", we call
|
||||
@@ -9742,11 +9738,20 @@ nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel,
|
||||
* This way, the user does not have to click the disable protection button
|
||||
* over and over for browsing the same site.
|
||||
*/
|
||||
rv = nsContentUtils::CheckSameOrigin(mMixedContentChannel, aChannel);
|
||||
nsresult rv =
|
||||
nsContentUtils::CheckSameOrigin(mMixedContentChannel, aChannel);
|
||||
if (NS_FAILED(rv) || NS_FAILED(SetMixedContentChannel(aChannel))) {
|
||||
SetMixedContentChannel(nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel,
|
||||
nsIURILoader* aURILoader,
|
||||
uint32_t aOpenFlags) {
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
UpdateMixedContentChannelForNewLoad(aChannel);
|
||||
|
||||
// If anything fails here, make sure to clear our initial ClientSource.
|
||||
auto cleanupInitialClient =
|
||||
@@ -9757,21 +9762,6 @@ nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel,
|
||||
|
||||
MaybeCreateInitialClientSource();
|
||||
|
||||
if (aOpenFlags & nsIURILoader::REDIRECTED_CHANNEL) {
|
||||
nsCOMPtr<nsILoadInfo> loadInfo;
|
||||
aChannel->GetLoadInfo(getter_AddRefs(loadInfo));
|
||||
|
||||
LoadInfo* li = static_cast<LoadInfo*>(loadInfo.get());
|
||||
if (loadInfo->GetExternalContentPolicyType() ==
|
||||
nsIContentPolicy::TYPE_DOCUMENT) {
|
||||
li->UpdateBrowsingContextID(mBrowsingContext->Id());
|
||||
} else if (loadInfo->GetExternalContentPolicyType() ==
|
||||
nsIContentPolicy::TYPE_SUBDOCUMENT) {
|
||||
li->UpdateFrameBrowsingContextID(mBrowsingContext->Id());
|
||||
}
|
||||
}
|
||||
// TODO: more attributes need to be updated on the LoadInfo (bug 1561706)
|
||||
|
||||
// Let the client channel helper know if we are using DocumentChannel,
|
||||
// since redirects get handled in the parent process in that case.
|
||||
RefPtr<net::DocumentChannel> docChannel = do_QueryObject(aChannel);
|
||||
@@ -9794,12 +9784,6 @@ nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel,
|
||||
rv = AddClientChannelHelperInChild(
|
||||
aChannel, win->EventTargetFor(TaskCategory::Other));
|
||||
docChannel->SetInitialClientInfo(GetInitialClientInfo());
|
||||
} else if (aOpenFlags & nsIURILoader::REDIRECTED_CHANNEL) {
|
||||
// If we did a process switch, then we should have an existing allocated
|
||||
// ClientInfo, so we just need to allocate a corresponding ClientSource.
|
||||
CreateReservedSourceIfNeeded(aChannel,
|
||||
win->EventTargetFor(TaskCategory::Other));
|
||||
rv = NS_OK;
|
||||
} else {
|
||||
rv = AddClientChannelHelper(aChannel, std::move(noReservedClient),
|
||||
GetInitialClientInfo(),
|
||||
@@ -9821,6 +9805,81 @@ nsresult nsDocShell::OpenInitializedChannel(nsIChannel* aChannel,
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsDocShell::OpenRedirectedChannel(nsDocShellLoadState* aLoadState) {
|
||||
nsCOMPtr<nsIChannel> channel = aLoadState->GetPendingRedirectedChannel();
|
||||
MOZ_ASSERT(channel);
|
||||
|
||||
UpdateMixedContentChannelForNewLoad(channel);
|
||||
|
||||
// If anything fails here, make sure to clear our initial ClientSource.
|
||||
auto cleanupInitialClient =
|
||||
MakeScopeExit([&] { mInitialClientSource.reset(); });
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> win = GetWindow();
|
||||
NS_ENSURE_TRUE(win, NS_ERROR_FAILURE);
|
||||
|
||||
MaybeCreateInitialClientSource();
|
||||
|
||||
nsCOMPtr<nsILoadInfo> loadInfo;
|
||||
channel->GetLoadInfo(getter_AddRefs(loadInfo));
|
||||
|
||||
LoadInfo* li = static_cast<LoadInfo*>(loadInfo.get());
|
||||
if (loadInfo->GetExternalContentPolicyType() ==
|
||||
nsIContentPolicy::TYPE_DOCUMENT) {
|
||||
li->UpdateBrowsingContextID(mBrowsingContext->Id());
|
||||
} else if (loadInfo->GetExternalContentPolicyType() ==
|
||||
nsIContentPolicy::TYPE_SUBDOCUMENT) {
|
||||
li->UpdateFrameBrowsingContextID(mBrowsingContext->Id());
|
||||
}
|
||||
// TODO: more attributes need to be updated on the LoadInfo (bug 1561706)
|
||||
|
||||
// If we did a process switch, then we should have an existing allocated
|
||||
// ClientInfo, so we just need to allocate a corresponding ClientSource.
|
||||
CreateReservedSourceIfNeeded(channel,
|
||||
win->EventTargetFor(TaskCategory::Other));
|
||||
|
||||
RefPtr<nsDocumentOpenInfo> loader =
|
||||
new nsDocumentOpenInfo(this, nsIURILoader::DONT_RETARGET, nullptr);
|
||||
channel->SetLoadGroup(mLoadGroup);
|
||||
|
||||
MOZ_ALWAYS_SUCCEEDS(loader->Prepare());
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
if (XRE_IsParentProcess()) {
|
||||
// If we're in the parent, the we don't have an nsIChildChannel, just
|
||||
// the original channel, which is already open in this process.
|
||||
|
||||
// DocumentLoadListener expects to get an nsIParentChannel, so
|
||||
// we create a wrapper around the channel and nsIStreamListener
|
||||
// that forwards functionality as needed, and then we register
|
||||
// it under the provided identifier.
|
||||
RefPtr<ParentChannelWrapper> wrapper =
|
||||
new ParentChannelWrapper(channel, loader);
|
||||
wrapper->Register(aLoadState->GetPendingRedirectChannelRegistrarId());
|
||||
|
||||
mLoadGroup->AddRequest(channel, nullptr);
|
||||
} else if (nsCOMPtr<nsIChildChannel> childChannel =
|
||||
do_QueryInterface(channel)) {
|
||||
// Our channel was redirected from another process, so doesn't need to
|
||||
// be opened again. However, it does need its listener hooked up
|
||||
// correctly.
|
||||
rv = childChannel->CompleteRedirectSetup(loader);
|
||||
} else {
|
||||
// It's possible for the redirected channel to not implement
|
||||
// nsIChildChannel and be entirely local (like srcdoc). In that case we
|
||||
// can just open the local instance and it will work.
|
||||
rv = channel->AsyncOpen(loader);
|
||||
}
|
||||
if (rv == NS_ERROR_NO_CONTENT) {
|
||||
return NS_OK;
|
||||
}
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// Success. Keep the initial ClientSource if it exists.
|
||||
cleanupInitialClient.release();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult nsDocShell::ScrollToAnchor(bool aCurHasRef, bool aNewHasRef,
|
||||
nsACString& aNewHash, uint32_t aLoadType) {
|
||||
if (!mCurrentURI) {
|
||||
|
||||
Reference in New Issue
Block a user