Bug 1575744 - P5. Implement process switch from DocumentChannelParent. r=mayhemer

Differential Revision: https://phabricator.services.mozilla.com/D46020

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jean-Yves Avenard 2019-09-20 04:09:47 +00:00
Родитель 912b0df630
Коммит abec029eac
2 изменённых файлов: 75 добавлений и 28 удалений

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

@ -8,6 +8,7 @@
#include "DocumentChannelParent.h"
#include "mozilla/DebugOnly.h"
#include "mozilla/LoadInfo.h"
#include "mozilla/MozPromiseInlines.h" // For MozPromise::FromDomPromise
#include "mozilla/dom/BrowserParent.h"
#include "mozilla/dom/ClientChannelHelper.h"
#include "mozilla/dom/ContentParent.h"
@ -40,6 +41,7 @@ NS_INTERFACE_MAP_BEGIN(DocumentChannelParent)
NS_INTERFACE_MAP_ENTRY(nsIAsyncVerifyRedirectReadyCallback)
NS_INTERFACE_MAP_ENTRY(nsICrossProcessSwitchChannel)
NS_INTERFACE_MAP_ENTRY(nsIChannelEventSink)
NS_INTERFACE_MAP_ENTRY(nsIProcessSwitchRequestor)
NS_INTERFACE_MAP_ENTRY_CONCRETE(DocumentChannelParent)
NS_INTERFACE_MAP_END
@ -369,26 +371,22 @@ DocumentChannelParent::FinishCrossProcessSwitch(
nsresult DocumentChannelParent::TriggerCrossProcessSwitch(
nsIHttpChannel* aChannel, uint64_t aIdentifier) {
RefPtr<nsHttpChannel> httpChannel = do_QueryObject(aChannel);
MOZ_DIAGNOSTIC_ASSERT(httpChannel,
"Must be called with nsHttpChannel object");
RefPtr<ContentProcessIdPromise> p =
httpChannel->TakeRedirectContentProcessIdPromise();
TriggerCrossProcessSwitch(p.forget(), aIdentifier, httpChannel);
MOZ_ASSERT_UNREACHABLE(
"We can no longer be called from nsHttpChannel, this interface will be "
"removed in a follow-up patch");
return NS_OK;
}
void DocumentChannelParent::TriggerCrossProcessSwitch(
already_AddRefed<ContentProcessIdPromise> aPromise, uint64_t aIdentifier,
nsHttpChannel* aChannel) {
void DocumentChannelParent::TriggerCrossProcessSwitch() {
MOZ_ASSERT(mRedirectContentProcessIdPromise);
CancelChildForProcessSwitch();
RefPtr<DocumentChannelParent> self = this;
RefPtr<nsHttpChannel> channel = aChannel;
RefPtr<ContentProcessIdPromise> p = aPromise;
p->Then(
mRedirectContentProcessIdPromise->Then(
GetMainThreadSerialEventTarget(), __func__,
[self, aIdentifier, channel](uint64_t aCpId) {
self->TriggerRedirectToRealChannel(channel, Some(aCpId), aIdentifier);
[self, this](uint64_t aCpId) {
MOZ_ASSERT(mChannel, "Something went wrong, channel got cancelled");
TriggerRedirectToRealChannel(mChannel, Some(aCpId),
mCrossProcessRedirectIdentifier);
},
[self](nsresult aStatusCode) {
MOZ_ASSERT(NS_FAILED(aStatusCode), "Status should be error");
@ -606,14 +604,11 @@ DocumentChannelParent::OnStartRequest(nsIRequest* aRequest) {
// notify "http-on-may-change-process" observers which is typically
// SessionStore.jsm. This will determine if a new process needs to be
// spawned and if so channel->SwitchProcessTo() will be called which will
// set a ContentProcessIdPromise.
gHttpHandler->OnMayChangeProcess(channel);
RefPtr<ContentProcessIdPromise> promise =
channel->TakeRedirectContentProcessIdPromise();
if (promise) {
TriggerCrossProcessSwitch(
promise.forget(), channel->CrossProcessRedirectIdentifier(), channel);
// spawned and if so SwitchProcessTo() will be called which will set a
// ContentProcessIdPromise.
gHttpHandler->OnMayChangeProcess(this);
if (mRedirectContentProcessIdPromise) {
TriggerCrossProcessSwitch();
return NS_OK;
}
}
@ -839,5 +834,47 @@ DocumentChannelParent::AsyncOnChannelRedirect(
return NS_OK;
}
//-----------------------------------------------------------------------------
// DocumentChannelParent::nsIProcessSwitchRequestor
//-----------------------------------------------------------------------------
NS_IMETHODIMP DocumentChannelParent::GetChannel(nsIChannel** aChannel) {
MOZ_ASSERT(mChannel);
nsCOMPtr<nsIChannel> channel(mChannel);
channel.forget(aChannel);
return NS_OK;
}
NS_IMETHODIMP DocumentChannelParent::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
NS_IMETHODIMP
DocumentChannelParent::HasCrossOriginOpenerPolicyMismatch(bool* aMismatch) {
MOZ_ASSERT(aMismatch);
if (!aMismatch) {
return NS_ERROR_INVALID_ARG;
}
nsCOMPtr<nsHttpChannel> channel = do_QueryInterface(mChannel);
if (!channel) {
// Not an nsHttpChannel assume it's okay to switch.
*aMismatch = false;
return NS_OK;
}
return channel->HasCrossOriginOpenerPolicyMismatch(aMismatch);
}
} // namespace net
} // namespace mozilla

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

@ -38,7 +38,8 @@ class DocumentChannelParent : public nsIInterfaceRequestor,
public nsIParentChannel,
public nsIChannelEventSink,
public nsICrossProcessSwitchChannel,
public HttpChannelSecurityWarningReporter {
public HttpChannelSecurityWarningReporter,
public nsIProcessSwitchRequestor {
public:
explicit DocumentChannelParent(const dom::PBrowserOrId& iframeEmbedding,
nsILoadContext* aLoadContext,
@ -54,6 +55,7 @@ class DocumentChannelParent : public nsIInterfaceRequestor,
NS_DECL_NSIASYNCVERIFYREDIRECTREADYCALLBACK
NS_DECL_NSICHANNELEVENTSINK
NS_DECL_NSICROSSPROCESSSWITCHCHANNEL
NS_DECL_NSIPROCESSSWITCHREQUESTOR
NS_DECLARE_STATIC_IID_ACCESSOR(DOCUMENT_CHANNEL_PARENT_IID)
@ -111,11 +113,7 @@ class DocumentChannelParent : public nsIInterfaceRequestor,
void FinishReplacementChannelSetup(bool aSucceeded);
typedef MozPromise<uint64_t, nsresult, true /* exclusive */>
ContentProcessIdPromise;
void TriggerCrossProcessSwitch(
already_AddRefed<ContentProcessIdPromise> aPromise, uint64_t aIdentifier,
nsHttpChannel* aChannel);
void TriggerCrossProcessSwitch();
// This defines a variant that describes all the attribute setters (and their
// parameters) from nsIParentChannel
@ -216,6 +214,18 @@ class DocumentChannelParent : public nsIInterfaceRequestor,
// helper from being installed, but we need to restore the value
// later.
bool mOldApplyConversion = false;
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;
};
NS_DEFINE_STATIC_IID_ACCESSOR(DocumentChannelParent,