Skip to content

Instantly share code, notes, and snippets.

@valenting
Last active January 13, 2019 14:53
Show Gist options
  • Save valenting/026dbfe1e3bbb2509a29155b4c0acb5e to your computer and use it in GitHub Desktop.
Save valenting/026dbfe1e3bbb2509a29155b4c0acb5e to your computer and use it in GitHub Desktop.
diff --git a/netwerk/protocol/http/HttpChannelParent.cpp b/netwerk/protocol/http/HttpChannelParent.cpp
--- a/netwerk/protocol/http/HttpChannelParent.cpp
+++ b/netwerk/protocol/http/HttpChannelParent.cpp
@@ -1311,20 +1311,24 @@ static void GetTimingAttributes(HttpBase
NS_IMETHODIMP
HttpChannelParent::OnStartRequest(nsIRequest* aRequest, nsISupports* aContext) {
nsresult rv;
LOG(("HttpChannelParent::OnStartRequest [this=%p, aRequest=%p]\n", this,
aRequest));
MOZ_ASSERT(NS_IsMainThread());
-
MOZ_RELEASE_ASSERT(!mDivertingFromChild,
"Cannot call OnStartRequest if diverting is set!");
+ if (mDoingCrossProcessRedirect) {
+ LOG(("Child was cancelled for cross-process redirect. Bail."));
+ return NS_OK;
+ }
+
RefPtr<HttpBaseChannel> chan = do_QueryObject(aRequest);
if (!chan) {
LOG((" aRequest is not HttpBaseChannel"));
NS_ERROR(
"Expecting only HttpBaseChannel as aRequest in "
"HttpChannelParent::OnStartRequest");
return NS_ERROR_UNEXPECTED;
}
@@ -1478,16 +1482,21 @@ HttpChannelParent::OnStartRequest(nsIReq
NS_IMETHODIMP
HttpChannelParent::OnStopRequest(nsIRequest* aRequest, nsISupports* aContext,
nsresult aStatusCode) {
LOG(("HttpChannelParent::OnStopRequest: [this=%p aRequest=%p status=%" PRIx32
"]\n",
this, aRequest, static_cast<uint32_t>(aStatusCode)));
MOZ_ASSERT(NS_IsMainThread());
+ if (mDoingCrossProcessRedirect) {
+ LOG(("Child was cancelled for cross-process redirect. Bail."));
+ return NS_OK;
+ }
+
MOZ_RELEASE_ASSERT(!mDivertingFromChild,
"Cannot call OnStopRequest if diverting is set!");
ResourceTimingStruct timing;
GetTimingAttributes(mChannel, timing);
RefPtr<nsHttpChannel> httpChannelImpl = do_QueryObject(mChannel);
if (httpChannelImpl) {
httpChannelImpl->SetWarningReporter(nullptr);
@@ -1589,17 +1598,17 @@ HttpChannelParent::OnDataAvailable(nsIRe
if (NS_FAILED(rv)) {
return rv;
}
// Either IPC channel is closed or background channel
// is ready to send OnTransportAndData.
MOZ_ASSERT(mIPCClosed || mBgParent);
- if (mIPCClosed || !mBgParent ||
+ if (mIPCClosed || !mBgParent || mDoingCrossProcessRedirect ||
!mBgParent->OnTransportAndData(channelStatus, transportStatus, aOffset,
toRead, data)) {
return NS_ERROR_UNEXPECTED;
}
aOffset += toRead;
aCount -= toRead;
toRead = std::min<uint32_t>(aCount, kCopyChunkSize);
@@ -1971,27 +1980,31 @@ HttpChannelParent::StartRedirect(uint32_
// Result is handled in RecvRedirect2Verify above
mRedirectChannel = newChannel;
mRedirectCallback = callback;
return NS_OK;
}
+void HttpChannelParent::CancelChildCrossProcessRedirect() {
+ MOZ_ASSERT(!mDoingCrossProcessRedirect, "Already redirected");
+ mDoingCrossProcessRedirect = true;
+ if (!mIPCClosed) {
+ Unused << SendCancelRedirected();
+ }
+}
+
NS_IMETHODIMP
HttpChannelParent::CompleteRedirect(bool succeeded) {
LOG(("HttpChannelParent::CompleteRedirect [this=%p succeeded=%d]\n", this,
succeeded));
- // The channel was redirected to another process, and the channel parent
- // is about to be deleted. We send a CancelRedirected message in order to
- // inform the listener that this child is going away.
- if (mDoingCrossProcessRedirect && !mIPCClosed) {
- MOZ_ASSERT(!mRedirectChannel);
- Unused << SendCancelRedirected();
+ if (mDoingCrossProcessRedirect) {
+ LOG(("Child was cancelled for cross-process redirect. Bail."));
return NS_OK;
}
// If this was an internal redirect for a service worker interception then
// we will not have a redirecting channel here. Hide this redirect from
// the child.
if (!mRedirectChannel) {
return NS_OK;
diff --git a/netwerk/protocol/http/HttpChannelParent.h b/netwerk/protocol/http/HttpChannelParent.h
--- a/netwerk/protocol/http/HttpChannelParent.h
+++ b/netwerk/protocol/http/HttpChannelParent.h
@@ -118,17 +118,21 @@ class HttpChannelParent final : public n
// Callback while background channel is ready.
void OnBackgroundParentReady(HttpBackgroundChannelParent* aBgParent);
// Callback while background channel is destroyed.
void OnBackgroundParentDestroyed();
base::ProcessId OtherPid() const override;
- void SetCrossProcessRedirect() { mDoingCrossProcessRedirect = true; }
+ // Calling this method will cancel the HttpChannelChild because the consumer
+ // needs to be relocated to another process.
+ // Any OnStart/Stop/DataAvailable calls that follow will not be sent to the
+ // child channel.
+ void CancelChildCrossProcessRedirect();
protected:
// used to connect redirected-to channel in parent with just created
// ChildChannel. Used during redirects.
MOZ_MUST_USE bool ConnectChannel(const uint32_t& channelId,
const bool& shouldIntercept);
MOZ_MUST_USE bool DoAsyncOpen(
@@ -329,16 +333,19 @@ class HttpChannelParent final : public n
uint8_t mSuspendAfterSynthesizeResponse : 1;
// Set if this channel will synthesize its response.
uint8_t mWillSynthesizeResponse : 1;
// Set if we get the result of and cache |mNeedFlowControl|
uint8_t mCacheNeedFlowControlInitialized : 1;
uint8_t mNeedFlowControl : 1;
uint8_t mSuspendedForFlowControl : 1;
+
+ // The child channel was cancelled, as the consumer was relocated to another
+ // process.
uint8_t mDoingCrossProcessRedirect : 1;
// Number of events to wait before actually invoking AsyncOpen on the main
// channel. For each asynchronous step required before InvokeAsyncOpen, should
// increase 1 to mAsyncOpenBarrier and invoke TryInvokeAsyncOpen after
// finished. This attribute is main thread only.
uint8_t mAsyncOpenBarrier = 0;
};
diff --git a/netwerk/protocol/http/HttpChannelParentListener.cpp b/netwerk/protocol/http/HttpChannelParentListener.cpp
--- a/netwerk/protocol/http/HttpChannelParentListener.cpp
+++ b/netwerk/protocol/http/HttpChannelParentListener.cpp
@@ -152,17 +152,17 @@ HttpChannelParentListener::GetInterface(
//-----------------------------------------------------------------------------
// HttpChannelParentListener::nsIChannelEventSink
//-----------------------------------------------------------------------------
nsresult HttpChannelParentListener::TriggerCrossProcessRedirect(
nsIChannel* aChannel, nsILoadInfo* aLoadInfo, uint64_t aIdentifier) {
RefPtr<HttpChannelParent> channelParent = do_QueryObject(mNextListener);
MOZ_ASSERT(channelParent);
- channelParent->SetCrossProcessRedirect();
+ channelParent->CancelChildCrossProcessRedirect();
nsCOMPtr<nsIChannel> channel = aChannel;
RefPtr<nsHttpChannel> httpChannel = do_QueryObject(channel);
RefPtr<nsHttpChannel::TabPromise> p = httpChannel->TakeRedirectTabPromise();
nsCOMPtr<nsILoadInfo> loadInfo = aLoadInfo;
RefPtr<HttpChannelParentListener> self = this;
p->Then(
@@ -193,21 +193,16 @@ nsresult HttpChannelParentListener::Trig
channel->GetOriginalURI(getter_AddRefs(originalURI));
uint64_t channelId;
MOZ_ALWAYS_SUCCEEDS(httpChannel->GetChannelId(&channelId));
dom::TabParent* tabParent = dom::TabParent::GetFrom(tp);
ContentParent* cp = tabParent->Manager()->AsContentParent();
- RefPtr<HttpChannelParent> channelParent =
- do_QueryObject(self->mNextListener);
- MOZ_ASSERT(channelParent);
- channelParent->SetCrossProcessRedirect();
-
auto result = cp->SendCrossProcessRedirect(
self->mRedirectChannelId, uri, newLoadFlags, loadInfoArgs,
channelId, originalURI, aIdentifier);
MOZ_ASSERT(result, "SendCrossProcessRedirect failed");
return result ? NS_OK : NS_ERROR_UNEXPECTED;
},
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment