Bug 1338493 - Part 2, move HttpBackgroundChannelChild to socket transport thread. r=mayhemer

Move HttpBackgroundChannelChild from main thread to socket transport thread.
Allow HttpChannelChild.mBgChild to be used on both main thread and STS thread under mutex protection.

MozReview-Commit-ID: 9WAXmJLr8HT

--HG--
extra : rebase_source : 774c71cec9d36412e2101719f5ca930a214f6472
This commit is contained in:
Shih-Chiang Chien 2017-06-28 22:04:17 +08:00
Родитель 69d4008264
Коммит 0f8c26e1d3
6 изменённых файлов: 235 добавлений и 103 удалений

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

@ -11,12 +11,12 @@
#include "HttpBackgroundChannelChild.h"
#include "HttpChannelChild.h"
#include "MainThreadUtils.h"
#include "mozilla/ipc/BackgroundChild.h"
#include "mozilla/ipc/PBackgroundChild.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Unused.h"
#include "nsIIPCBackgroundChildCreateCallback.h"
#include "nsSocketTransportService2.h"
using mozilla::ipc::BackgroundChild;
using mozilla::ipc::IPCResult;
@ -35,6 +35,7 @@ public:
explicit BackgroundChannelCreateCallback(HttpBackgroundChannelChild* aBgChild)
: mBgChild(aBgChild)
{
MOZ_ASSERT(OnSocketThread());
MOZ_ASSERT(aBgChild);
}
@ -50,7 +51,7 @@ NS_IMPL_ISUPPORTS(BackgroundChannelCreateCallback,
void
BackgroundChannelCreateCallback::ActorCreated(PBackgroundChild* aActor)
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
MOZ_ASSERT(aActor);
MOZ_ASSERT(mBgChild);
@ -70,12 +71,14 @@ BackgroundChannelCreateCallback::ActorCreated(PBackgroundChild* aActor)
// hold extra reference for IPDL
RefPtr<HttpBackgroundChannelChild> child = mBgChild;
Unused << child.forget().take();
mBgChild->mChannelChild->OnBackgroundChildReady(mBgChild);
}
void
BackgroundChannelCreateCallback::ActorFailed()
{
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
MOZ_ASSERT(mBgChild);
mBgChild->OnBackgroundChannelCreationFailed();
@ -95,7 +98,7 @@ HttpBackgroundChannelChild::Init(HttpChannelChild* aChannelChild)
{
LOG(("HttpBackgroundChannelChild::Init [this=%p httpChannel=%p channelId=%"
PRIu64 "]\n", this, aChannelChild, aChannelChild->ChannelId()));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
NS_ENSURE_ARG(aChannelChild);
mChannelChild = aChannelChild;
@ -112,7 +115,7 @@ void
HttpBackgroundChannelChild::OnChannelClosed()
{
LOG(("HttpBackgroundChannelChild::OnChannelClosed [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
// HttpChannelChild is not going to handle any incoming message.
mChannelChild = nullptr;
@ -122,7 +125,7 @@ void
HttpBackgroundChannelChild::OnStartRequestReceived()
{
LOG(("HttpBackgroundChannelChild::OnStartRequestReceived [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
MOZ_ASSERT(mChannelChild);
MOZ_ASSERT(!mStartReceived); // Should only be called once.
@ -146,11 +149,11 @@ HttpBackgroundChannelChild::OnBackgroundChannelCreationFailed()
{
LOG(("HttpBackgroundChannelChild::OnBackgroundChannelCreationFailed"
" [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
if (mChannelChild) {
RefPtr<HttpChannelChild> channelChild = mChannelChild.forget();
channelChild->FailedAsyncOpen(NS_ERROR_UNEXPECTED);
channelChild->OnBackgroundChildDestroyed(this);
}
}
@ -158,7 +161,7 @@ bool
HttpBackgroundChannelChild::CreateBackgroundChannel()
{
LOG(("HttpBackgroundChannelChild::CreateBackgroundChannel [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
RefPtr<BackgroundChannelCreateCallback> callback =
new BackgroundChannelCreateCallback(this);
@ -169,6 +172,7 @@ HttpBackgroundChannelChild::CreateBackgroundChannel()
bool
HttpBackgroundChannelChild::IsWaitingOnStartRequest()
{
MOZ_ASSERT(OnSocketThread());
// Need to wait for OnStartRequest if it is sent by
// parent process but not received by content process.
return (mStartSent && !mStartReceived);
@ -179,7 +183,7 @@ IPCResult
HttpBackgroundChannelChild::RecvOnStartRequestSent()
{
LOG(("HttpBackgroundChannelChild::RecvOnStartRequestSent [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
MOZ_ASSERT(!mStartSent); // Should only receive this message once.
mStartSent = true;
@ -195,7 +199,7 @@ HttpBackgroundChannelChild::RecvOnTransportAndData(
const nsCString& aData)
{
LOG(("HttpBackgroundChannelChild::RecvOnTransportAndData [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
if (NS_WARN_IF(!mChannelChild)) {
return IPC_OK();
@ -210,7 +214,7 @@ HttpBackgroundChannelChild::RecvOnTransportAndData(
const uint64_t,
const uint32_t,
const nsCString>(
"net::HttpBackgroundChannelChild::RecvOnTransportAndData",
"HttpBackgroundChannelChild::RecvOnTransportAndData",
this,
&HttpBackgroundChannelChild::RecvOnTransportAndData,
aChannelStatus,
@ -237,7 +241,7 @@ HttpBackgroundChannelChild::RecvOnStopRequest(
const ResourceTimingStruct& aTiming)
{
LOG(("HttpBackgroundChannelChild::RecvOnStopRequest [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
if (NS_WARN_IF(!mChannelChild)) {
return IPC_OK();
@ -249,7 +253,7 @@ HttpBackgroundChannelChild::RecvOnStopRequest(
mQueuedRunnables.AppendElement(
NewRunnableMethod<const nsresult, const ResourceTimingStruct>(
"net::HttpBackgroundChannelChild::RecvOnStopRequest",
"HttpBackgroundChannelChild::RecvOnStopRequest",
this,
&HttpBackgroundChannelChild::RecvOnStopRequest,
aChannelStatus,
@ -269,7 +273,7 @@ HttpBackgroundChannelChild::RecvOnProgress(const int64_t& aProgress,
{
LOG(("HttpBackgroundChannelChild::RecvOnProgress [this=%p progress=%"
PRId64 " max=%" PRId64 "]\n", this, aProgress, aProgressMax));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
if (NS_WARN_IF(!mChannelChild)) {
return IPC_OK();
@ -281,7 +285,7 @@ HttpBackgroundChannelChild::RecvOnProgress(const int64_t& aProgress,
mQueuedRunnables.AppendElement(
NewRunnableMethod<const int64_t, const int64_t>(
"net::HttpBackgroundChannelChild::RecvOnProgress",
"HttpBackgroundChannelChild::RecvOnProgress",
this,
&HttpBackgroundChannelChild::RecvOnProgress,
aProgress,
@ -300,7 +304,7 @@ HttpBackgroundChannelChild::RecvOnStatus(const nsresult& aStatus)
{
LOG(("HttpBackgroundChannelChild::RecvOnStatus [this=%p status=%"
PRIx32 "]\n", this, static_cast<uint32_t>(aStatus)));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
if (NS_WARN_IF(!mChannelChild)) {
return IPC_OK();
@ -311,7 +315,7 @@ HttpBackgroundChannelChild::RecvOnStatus(const nsresult& aStatus)
static_cast<uint32_t>(aStatus)));
mQueuedRunnables.AppendElement(NewRunnableMethod<const nsresult>(
"net::HttpBackgroundChannelChild::RecvOnStatus",
"HttpBackgroundChannelChild::RecvOnStatus",
this,
&HttpBackgroundChannelChild::RecvOnStatus,
aStatus));
@ -328,7 +332,7 @@ IPCResult
HttpBackgroundChannelChild::RecvFlushedForDiversion()
{
LOG(("HttpBackgroundChannelChild::RecvFlushedForDiversion [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
if (NS_WARN_IF(!mChannelChild)) {
return IPC_OK();
@ -338,7 +342,7 @@ HttpBackgroundChannelChild::RecvFlushedForDiversion()
LOG((" > pending until OnStartRequest\n"));
mQueuedRunnables.AppendElement(NewRunnableMethod(
"net::HttpBackgroundChannelChild::RecvFlushedForDiversion",
"HttpBackgroundChannelChild::RecvFlushedForDiversion",
this,
&HttpBackgroundChannelChild::RecvFlushedForDiversion));
@ -354,7 +358,7 @@ IPCResult
HttpBackgroundChannelChild::RecvDivertMessages()
{
LOG(("HttpBackgroundChannelChild::RecvDivertMessages [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
if (NS_WARN_IF(!mChannelChild)) {
return IPC_OK();
@ -364,7 +368,7 @@ HttpBackgroundChannelChild::RecvDivertMessages()
LOG((" > pending until OnStartRequest\n"));
mQueuedRunnables.AppendElement(
NewRunnableMethod("net::HttpBackgroundChannelChild::RecvDivertMessages",
NewRunnableMethod("HttpBackgroundChannelChild::RecvDivertMessages",
this,
&HttpBackgroundChannelChild::RecvDivertMessages));
@ -380,7 +384,7 @@ IPCResult
HttpBackgroundChannelChild::RecvNotifyTrackingProtectionDisabled()
{
LOG(("HttpBackgroundChannelChild::RecvNotifyTrackingProtectionDisabled [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
if (NS_WARN_IF(!mChannelChild)) {
return IPC_OK();
@ -397,7 +401,7 @@ IPCResult
HttpBackgroundChannelChild::RecvNotifyTrackingResource()
{
LOG(("HttpBackgroundChannelChild::RecvNotifyTrackingResource [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
if (NS_WARN_IF(!mChannelChild)) {
return IPC_OK();
@ -414,7 +418,7 @@ IPCResult
HttpBackgroundChannelChild::RecvSetClassifierMatchedInfo(const ClassifierInfo& info)
{
LOG(("HttpBackgroundChannelChild::RecvSetClassifierMatchedInfo [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
if (NS_WARN_IF(!mChannelChild)) {
return IPC_OK();
@ -431,7 +435,22 @@ void
HttpBackgroundChannelChild::ActorDestroy(ActorDestroyReason aWhy)
{
LOG(("HttpBackgroundChannelChild::ActorDestroy[this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
if (!OnSocketThread()) {
// PBackgroundChild might be destroyed during shutdown and
// ActorDestroy will be called on main thread directly.
// Simply disconnect with HttpChannelChild to release memory.
mChannelChild = nullptr;
RefPtr<HttpBackgroundChannelChild> self = this;
mQueuedRunnables.AppendElement(NS_NewRunnableFunction(
"HttpBackgroundChannelChild::ActorDestroyNonSTSThread", [self]() {
MOZ_ASSERT(NS_IsMainThread());
self->mChannelChild = nullptr;
}));
return;
}
MOZ_ASSERT(OnSocketThread());
// Ensure all IPC messages received before ActorDestroy can be
// handled correctly. If there is any pending IPC message, destroyed
@ -440,12 +459,12 @@ HttpBackgroundChannelChild::ActorDestroy(ActorDestroyReason aWhy)
LOG((" > pending until queued messages are flushed\n"));
RefPtr<HttpBackgroundChannelChild> self = this;
mQueuedRunnables.AppendElement(NS_NewRunnableFunction(
"net::HttpBackgroundChannelChild::ActorDestroy", [self]() {
"HttpBackgroundChannelChild::ActorDestroy", [self]() {
MOZ_ASSERT(NS_IsMainThread());
RefPtr<HttpChannelChild> channelChild = self->mChannelChild.forget();
if (channelChild) {
channelChild->OnBackgroundChildDestroyed();
channelChild->OnBackgroundChildDestroyed(self);
}
}));
return;
@ -454,7 +473,7 @@ HttpBackgroundChannelChild::ActorDestroy(ActorDestroyReason aWhy)
if (mChannelChild) {
RefPtr<HttpChannelChild> channelChild = mChannelChild.forget();
channelChild->OnBackgroundChildDestroyed();
channelChild->OnBackgroundChildDestroyed(this);
}
}

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

@ -95,13 +95,16 @@ private:
RefPtr<HttpChannelChild> mChannelChild;
// True if OnStartRequest is received by HttpChannelChild.
// Should only access on STS thread.
bool mStartReceived = false;
// True if OnStartRequest is sent by HttpChannelParent.
// Should only access on STS thread.
bool mStartSent = false;
// Store pending messages that require to be handled after OnStartRequest.
// Should be flushed after OnStartRequest is received and handled.
// Should only access on STS thread.
nsTArray<nsCOMPtr<nsIRunnable>> mQueuedRunnables;
};

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

@ -499,7 +499,7 @@ protected:
nsCString mEntityID;
uint64_t mStartPos;
nsresult mStatus;
Atomic<nsresult, ReleaseAcquire> mStatus;
uint32_t mLoadFlags;
uint32_t mCaps;
uint32_t mClassOfService;

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

@ -50,6 +50,7 @@
#include "nsIDOMWindowUtils.h"
#include "nsIEventTarget.h"
#include "nsRedirectHistoryEntry.h"
#include "nsSocketTransportService2.h"
#include "nsStreamUtils.h"
#include "nsThreadUtils.h"
@ -177,6 +178,7 @@ HttpChannelChild::HttpChannelChild()
, mPostRedirectChannelShouldUpgrade(false)
, mShouldParentIntercept(false)
, mSuspendParentAfterSynthesizeResponse(false)
, mBgChildMutex("HttpChannelChild::BgChildMutex")
, mEventTargetMutex("HttpChannelChild::EventTargetMutex")
{
LOG(("Creating HttpChannelChild @%p\n", this));
@ -295,19 +297,46 @@ HttpChannelChild::OnBackgroundChildReady(HttpBackgroundChannelChild* aBgChild)
{
LOG(("HttpChannelChild::OnBackgroundChildReady [this=%p, bgChild=%p]\n",
this, aBgChild));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(mBgChild);
MOZ_ASSERT(OnSocketThread());
MOZ_ASSERT(mBgChild == aBgChild);
{
MutexAutoLock lock(mBgChildMutex);
// mBgChild might be removed or replaced while the original background
// channel is inited on STS thread.
if (mBgChild != aBgChild) {
return;
}
MOZ_ASSERT(mBgInitFailCallback);
mBgInitFailCallback = nullptr;
}
}
void
HttpChannelChild::OnBackgroundChildDestroyed()
HttpChannelChild::OnBackgroundChildDestroyed(HttpBackgroundChannelChild* aBgChild)
{
LOG(("HttpChannelChild::OnBackgroundChildDestroyed [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
mBgChild = nullptr;
nsCOMPtr<nsIRunnable> callback;
{
MutexAutoLock lock(mBgChildMutex);
// mBgChild might be removed or replaced while the original background
// channel is destroyed on STS thread.
if (aBgChild != mBgChild) {
return;
}
mBgChild = nullptr;
callback = mBgInitFailCallback.forget();
}
if (callback) {
nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget();
neckoTarget->Dispatch(callback, NS_DISPATCH_NORMAL);
}
}
class AssociateApplicationCacheEvent : public NeckoTargetChannelEvent<HttpChannelChild>
@ -459,9 +488,23 @@ HttpChannelChild::RecvOnStartRequest(const nsresult& channelStatus,
selfAddr, peerAddr, cacheKey,
altDataType, altDataLen));
MOZ_ASSERT(mBgChild);
if (mBgChild) {
mBgChild->OnStartRequestReceived();
{
// Child's mEventQ is to control the execution order of the IPC messages
// from both main thread IPDL and PBackground IPDL.
// To guarantee the ordering, PBackground IPC messages that are sent after
// OnStartRequest will be throttled until OnStartRequest hits the Child's
// mEventQ.
MutexAutoLock lock(mBgChildMutex);
if (mBgChild) {
MOZ_RELEASE_ASSERT(gSocketTransportService);
DebugOnly<nsresult> rv =
gSocketTransportService->Dispatch(
NewRunnableMethod(
"HttpBackgroundChannelChild::OnStartRequestReceived",
mBgChild, &HttpBackgroundChannelChild::OnStartRequestReceived),
NS_DISPATCH_NORMAL);
}
}
return IPC_OK();
@ -697,7 +740,7 @@ HttpChannelChild::ProcessOnTransportAndData(const nsresult& aChannelStatus,
const nsCString& aData)
{
LOG(("HttpChannelChild::ProcessOnTransportAndData [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
"Should not be receiving any more callbacks from parent!");
mEventQ->RunOrEnqueue(new TransportAndDataEvent(this, aChannelStatus,
@ -756,6 +799,7 @@ HttpChannelChild::OnTransportAndData(const nsresult& channelStatus,
// For diversion to parent, just SendDivertOnDataAvailable.
if (mDivertingToParent) {
MOZ_ASSERT(NS_IsMainThread());
MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
"Should not be processing any more callbacks from parent!");
@ -769,6 +813,7 @@ HttpChannelChild::OnTransportAndData(const nsresult& channelStatus,
if (mUnknownDecoderInvolved) {
LOG(("UnknownDecoder is involved queue OnDataAvailable call. [this=%p]",
this));
MOZ_ASSERT(NS_IsMainThread());
mUnknownDecoderEventQ.AppendElement(
MakeUnique<MaybeDivertOnDataHttpEvent>(this, data, offset, count));
}
@ -923,7 +968,7 @@ HttpChannelChild::ProcessOnStopRequest(const nsresult& aChannelStatus,
const ResourceTimingStruct& aTiming)
{
LOG(("HttpChannelChild::ProcessOnStopRequest [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
MOZ_RELEASE_ASSERT(!mFlushedForDiversion,
"Should not be receiving any more callbacks from parent!");
@ -953,7 +998,8 @@ void
HttpChannelChild::MaybeDivertOnStop(const nsresult& aChannelStatus)
{
LOG(("HttpChannelChild::MaybeDivertOnStop [this=%p, "
"mDivertingToParent=%d status=%" PRIx32 "]", this, mDivertingToParent,
"mDivertingToParent=%d status=%" PRIx32 "]", this,
static_cast<bool>(mDivertingToParent),
static_cast<uint32_t>(aChannelStatus)));
if (mDivertingToParent) {
SendDivertOnStopRequest(aChannelStatus);
@ -976,35 +1022,10 @@ HttpChannelChild::OnStopRequest(const nsresult& channelStatus,
return;
}
// In thread retargeting is enabled, there might be Runnable for
// DoOnStatus/DoOnProgress sit in the main thread event target. We need to
// ensure OnStopRequest is fired after that by postponing the
// ChannelEventQueue processing to the end of main thread event target.
// This workaround can be removed after bug 1338493 is complete.
if (mODATarget) {
{
MutexAutoLock lock(mEventTargetMutex);
mODATarget = nullptr;
}
mEventQ->Suspend();
UniquePtr<ChannelEvent> stopEvent =
MakeUnique<StopRequestEvent>(this, channelStatus, timing);
mEventQ->PrependEvent(stopEvent);
nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget();
MOZ_ASSERT(neckoTarget);
DebugOnly<nsresult> rv = neckoTarget->Dispatch(
NewRunnableMethod(
"net::ChannelEventQueue::Resume", mEventQ, &ChannelEventQueue::Resume),
NS_DISPATCH_NORMAL);
MOZ_ASSERT(NS_SUCCEEDED(rv));
return;
}
if (mUnknownDecoderInvolved) {
LOG(("UnknownDecoder is involved queue OnStopRequest call. [this=%p]",
this));
MOZ_ASSERT(NS_IsMainThread());
mUnknownDecoderEventQ.AppendElement(
MakeUnique<MaybeDivertOnStopHttpEvent>(this, channelStatus));
}
@ -1160,7 +1181,7 @@ HttpChannelChild::ProcessOnProgress(const int64_t& aProgress,
const int64_t& aProgressMax)
{
LOG(("HttpChannelChild::ProcessOnProgress [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
mEventQ->RunOrEnqueue(new ProgressEvent(this, aProgress, aProgressMax));
}
@ -1208,7 +1229,7 @@ void
HttpChannelChild::ProcessOnStatus(const nsresult& aStatus)
{
LOG(("HttpChannelChild::ProcessOnStatus [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
mEventQ->RunOrEnqueue(new StatusEvent(this, aStatus));
}
@ -1299,21 +1320,26 @@ HttpChannelChild::FailedAsyncOpen(const nsresult& status)
void
HttpChannelChild::CleanupBackgroundChannel()
{
MutexAutoLock lock(mBgChildMutex);
LOG(("HttpChannelChild::CleanupBackgroundChannel [this=%p bgChild=%p]\n",
this, mBgChild.get()));
mBgInitFailCallback = nullptr;
if (!mBgChild) {
return;
}
RefPtr<HttpBackgroundChannelChild> bgChild = mBgChild.forget();
if (!NS_IsMainThread()) {
SystemGroup::Dispatch(
"HttpChannelChild::CleanupBackgroundChannel",
TaskCategory::Other,
NewRunnableMethod("net::HttpBackgroundChannelChild::OnChannelClosed",
bgChild,
&HttpBackgroundChannelChild::OnChannelClosed));
MOZ_RELEASE_ASSERT(gSocketTransportService);
if (!OnSocketThread()) {
gSocketTransportService->Dispatch(
NewRunnableMethod(
"HttpBackgroundChannelChild::OnChannelClosed",
bgChild, &HttpBackgroundChannelChild::OnChannelClosed),
NS_DISPATCH_NORMAL);
} else {
bgChild->OnChannelClosed();
}
@ -1685,7 +1711,7 @@ void
HttpChannelChild::ProcessFlushedForDiversion()
{
LOG(("HttpChannelChild::ProcessFlushedForDiversion [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
MOZ_RELEASE_ASSERT(mDivertingToParent);
mEventQ->RunOrEnqueue(new HttpFlushedForDiversionEvent(this), true);
@ -1695,18 +1721,31 @@ void
HttpChannelChild::ProcessNotifyTrackingProtectionDisabled()
{
LOG(("HttpChannelChild::ProcessNotifyTrackingProtectionDisabled [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
nsChannelClassifier::NotifyTrackingProtectionDisabled(this);
RefPtr<HttpChannelChild> self = this;
nsCOMPtr<nsIEventTarget> mainTarget = GetMainThreadEventTarget();
mainTarget->Dispatch(
NS_NewRunnableFunction(
"nsChannelClassifier::NotifyTrackingProtectionDisabled",
[self]() {
nsChannelClassifier::NotifyTrackingProtectionDisabled(self);
}),
NS_DISPATCH_NORMAL);
}
void
HttpChannelChild::ProcessNotifyTrackingResource()
{
LOG(("HttpChannelChild::ProcessNotifyTrackingResource [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
SetIsTrackingResource();
nsCOMPtr<nsIEventTarget> mainTarget = GetMainThreadEventTarget();
mainTarget->Dispatch(
NewRunnableMethod(
"HttpChannelChild::SetIsTrackingResource",
this, &HttpChannelChild::SetIsTrackingResource),
NS_DISPATCH_NORMAL);
}
void
@ -1729,22 +1768,36 @@ HttpChannelChild::ProcessSetClassifierMatchedInfo(const nsCString& aList,
const nsCString& aPrefix)
{
LOG(("HttpChannelChild::ProcessSetClassifierMatchedInfo [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
SetMatchedInfo(aList, aProvider, aPrefix);
nsCOMPtr<nsIEventTarget> mainTarget = GetMainThreadEventTarget();
mainTarget->Dispatch(
NewRunnableMethod<const nsCString, const nsCString, const nsCString>
("HttpChannelChild::SetMatchedInfo",
this, &HttpChannelChild::SetMatchedInfo,
aList, aProvider, aPrefix),
NS_DISPATCH_NORMAL);
}
void
HttpChannelChild::ProcessDivertMessages()
{
LOG(("HttpChannelChild::ProcessDivertMessages [this=%p]\n", this));
MOZ_ASSERT(NS_IsMainThread());
MOZ_ASSERT(OnSocketThread());
MOZ_RELEASE_ASSERT(mDivertingToParent);
MOZ_RELEASE_ASSERT(mSuspendCount > 0);
// DivertTo() has been called on parent, so we can now start sending queued
// IPDL messages back to parent listener.
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(Resume()));
nsCOMPtr<nsIEventTarget> neckoTarget = GetNeckoTarget();
MOZ_ASSERT(neckoTarget);
nsresult rv =
neckoTarget->Dispatch(
NewRunnableMethod(
"HttpChannelChild::Resume",
this, &HttpChannelChild::Resume),
NS_DISPATCH_NORMAL);
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
}
// Returns true if has actually completed the redirect and cleaned up the
@ -1866,12 +1919,29 @@ HttpChannelChild::ConnectParent(uint32_t registrarId)
}
{
MutexAutoLock lock(mBgChildMutex);
MOZ_ASSERT(!mBgChild);
MOZ_ASSERT(!mBgInitFailCallback);
mBgInitFailCallback = NewRunnableMethod<nsresult>(
"HttpChannelChild::OnRedirectVerifyCallback",
this, &HttpChannelChild::OnRedirectVerifyCallback,
NS_ERROR_FAILURE);
RefPtr<HttpBackgroundChannelChild> bgChild =
new HttpBackgroundChannelChild();
nsresult rv = bgChild->Init(this);
MOZ_RELEASE_ASSERT(gSocketTransportService);
RefPtr<HttpChannelChild> self = this;
nsresult rv =
gSocketTransportService->Dispatch(
NewRunnableMethod<RefPtr<HttpChannelChild>>(
"HttpBackgroundChannelChild::Init",
bgChild, &HttpBackgroundChannelChild::Init, Move(self)),
NS_DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -2102,7 +2172,8 @@ NS_IMETHODIMP
HttpChannelChild::Suspend()
{
LOG(("HttpChannelChild::Suspend [this=%p, mSuspendCount=%" PRIu32 ", "
"mDivertingToParent=%d]\n", this, mSuspendCount+1, mDivertingToParent));
"mDivertingToParent=%d]\n", this, mSuspendCount + 1,
static_cast<bool>(mDivertingToParent)));
NS_ENSURE_TRUE(RemoteChannelExists() || mInterceptListener,
NS_ERROR_NOT_AVAILABLE);
@ -2127,7 +2198,8 @@ NS_IMETHODIMP
HttpChannelChild::Resume()
{
LOG(("HttpChannelChild::Resume [this=%p, mSuspendCount=%" PRIu32 ", "
"mDivertingToParent=%d]\n", this, mSuspendCount-1, mDivertingToParent));
"mDivertingToParent=%d]\n", this, mSuspendCount - 1,
static_cast<bool>(mDivertingToParent)));
NS_ENSURE_TRUE(RemoteChannelExists() || mInterceptListener,
NS_ERROR_NOT_AVAILABLE);
NS_ENSURE_TRUE(mSuspendCount > 0, NS_ERROR_UNEXPECTED);
@ -2511,18 +2583,41 @@ HttpChannelChild::ContinueAsyncOpen()
}
{
MutexAutoLock lock(mBgChildMutex);
MOZ_RELEASE_ASSERT(gSocketTransportService);
// Service worker might use the same HttpChannelChild to do async open
// twice. Need to disconnect with previous background channel before
// creating the new one.
// creating the new one, to prevent receiving further notification
// from it.
if (mBgChild) {
RefPtr<HttpBackgroundChannelChild> prevBgChild = mBgChild.forget();
prevBgChild->OnChannelClosed();
gSocketTransportService->Dispatch(
NewRunnableMethod(
"HttpBackgroundChannelChild::OnChannelClosed",
prevBgChild, &HttpBackgroundChannelChild::OnChannelClosed),
NS_DISPATCH_NORMAL);
}
MOZ_ASSERT(!mBgInitFailCallback);
mBgInitFailCallback = NewRunnableMethod<nsresult>(
"HttpChannelChild::FailedAsyncOpen",
this, &HttpChannelChild::FailedAsyncOpen,
NS_ERROR_FAILURE);
RefPtr<HttpBackgroundChannelChild> bgChild =
new HttpBackgroundChannelChild();
rv = bgChild->Init(this);
RefPtr<HttpChannelChild> self = this;
nsresult rv =
gSocketTransportService->Dispatch(
NewRunnableMethod<RefPtr<HttpChannelChild>>(
"HttpBackgroundChannelChild::Init",
bgChild, &HttpBackgroundChannelChild::Init, self),
NS_DISPATCH_NORMAL);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -3115,6 +3210,8 @@ HttpChannelChild::UnknownDecoderInvolvedKeepData()
{
LOG(("HttpChannelChild::UnknownDecoderInvolvedKeepData [this=%p]",
this));
MOZ_ASSERT(NS_IsMainThread());
mUnknownDecoderInvolved = true;
return NS_OK;
}
@ -3123,7 +3220,10 @@ NS_IMETHODIMP
HttpChannelChild::UnknownDecoderInvolvedOnStartRequestCalled()
{
LOG(("HttpChannelChild::UnknownDecoderInvolvedOnStartRequestCalled "
"[this=%p, mDivertingToParent=%d]", this, mDivertingToParent));
"[this=%p, mDivertingToParent=%d]", this,
static_cast<bool>(mDivertingToParent)));
MOZ_ASSERT(NS_IsMainThread());
mUnknownDecoderInvolved = false;
nsresult rv = NS_OK;

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

@ -120,7 +120,7 @@ public:
// Callback while background channel is ready.
void OnBackgroundChildReady(HttpBackgroundChannelChild* aBgChild);
// Callback while background channel is destroyed.
void OnBackgroundChildDestroyed();
void OnBackgroundChildDestroyed(HttpBackgroundChannelChild* aBgChild);
protected:
mozilla::ipc::IPCResult RecvOnStartRequest(const nsresult& channelStatus,
@ -294,13 +294,13 @@ private:
// this queue keeps OnDataAvailable data until OnStartRequest is finally
// called.
nsTArray<UniquePtr<ChannelEvent>> mUnknownDecoderEventQ;
bool mUnknownDecoderInvolved;
Atomic<bool, ReleaseAcquire> mUnknownDecoderInvolved;
// Once set, OnData and possibly OnStop will be diverted to the parent.
bool mDivertingToParent;
Atomic<bool, ReleaseAcquire> mDivertingToParent;
// Once set, no OnStart/OnData/OnStop callbacks should be received from the
// parent channel, nor dequeued from the ChannelEventQueue.
bool mFlushedForDiversion;
Atomic<bool, ReleaseAcquire> mFlushedForDiversion;
// Set if SendSuspend is called. Determines if SendResume is needed when
// diverting callbacks to parent.
bool mSuspendSent;
@ -332,8 +332,15 @@ private:
// is synthesized.
bool mSuspendParentAfterSynthesizeResponse;
// Used to ensure atomicity of mBgChild and mBgInitFailCallback
Mutex mBgChildMutex;
// Associated HTTP background channel
RefPtr<HttpBackgroundChannelChild> mBgChild;
// Error handling procedure if failed to establish PBackground IPC
nsCOMPtr<nsIRunnable> mBgInitFailCallback;
// Remove the association with background channel after OnStopRequest
// or AsyncAbort.
void CleanupBackgroundChannel();

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

@ -4412,7 +4412,7 @@ nsHttpChannel::OnCacheEntryAvailableInternal(nsICacheEntry *entry,
if (mCanceled) {
LOG(("channel was canceled [this=%p status=%" PRIx32 "]\n",
this, static_cast<uint32_t>(mStatus)));
this, static_cast<uint32_t>(static_cast<nsresult>(mStatus))));
return mStatus;
}
@ -5047,7 +5047,7 @@ nsHttpChannel::CloseCacheEntry(bool doomOnFailure)
return;
LOG(("nsHttpChannel::CloseCacheEntry [this=%p] mStatus=%" PRIx32 " mCacheEntryIsWriteOnly=%x",
this, static_cast<uint32_t>(mStatus), mCacheEntryIsWriteOnly));
this, static_cast<uint32_t>(static_cast<nsresult>(mStatus)), mCacheEntryIsWriteOnly));
// If we have begun to create or replace a cache entry, and that cache
// entry is not complete and not resumable, then it needs to be doomed.
@ -6743,7 +6743,8 @@ nsHttpChannel::OnProxyAvailable(nsICancelable *request, nsIChannel *channel,
{
LOG(("nsHttpChannel::OnProxyAvailable [this=%p pi=%p status=%" PRIx32
" mStatus=%" PRIx32 "]\n",
this, pi, static_cast<uint32_t>(status), static_cast<uint32_t>(mStatus)));
this, pi, static_cast<uint32_t>(status),
static_cast<uint32_t>(static_cast<nsresult>(mStatus))));
mProxyRequest = nullptr;
nsresult rv;
@ -6967,11 +6968,13 @@ nsHttpChannel::OnStartRequest(nsIRequest *request, nsISupports *ctxt)
if (!(mCanceled || NS_FAILED(mStatus)) && !WRONG_RACING_RESPONSE_SOURCE(request)) {
// capture the request's status, so our consumers will know ASAP of any
// connection failures, etc - bug 93581
request->GetStatus(&mStatus);
nsresult status;
request->GetStatus(&status);
mStatus = status;
}
LOG(("nsHttpChannel::OnStartRequest [this=%p request=%p status=%" PRIx32 "]\n",
this, request, static_cast<uint32_t>(mStatus)));
this, request, static_cast<uint32_t>(static_cast<nsresult>(mStatus))));
if (mRaceCacheWithNetwork) {
LOG((" racingNetAndCache - mFirstResponseSource:%d fromCache:%d fromNet:%d\n",