gecko-dev/netwerk/protocol/http/HttpBackgroundChannelParent...

466 строки
12 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et tw=80 : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// HttpLog.h should generally be included first
#include "HttpLog.h"
#include "HttpBackgroundChannelParent.h"
#include "HttpChannelParent.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/IntegerPrintfMacros.h"
#include "mozilla/Unused.h"
#include "nsIBackgroundChannelRegistrar.h"
#include "nsNetCID.h"
#include "nsQueryObject.h"
#include "nsThreadUtils.h"
using mozilla::dom::ContentParent;
using mozilla::ipc::AssertIsInMainProcess;
using mozilla::ipc::AssertIsOnBackgroundThread;
using mozilla::ipc::BackgroundParent;
using mozilla::ipc::IPCResult;
using mozilla::ipc::IsOnBackgroundThread;
namespace mozilla {
namespace net {
/*
* Helper class for continuing the AsyncOpen procedure on main thread.
*/
class ContinueAsyncOpenRunnable final : public Runnable
{
public:
ContinueAsyncOpenRunnable(HttpBackgroundChannelParent* aActor,
const uint64_t& aChannelId)
: Runnable("net::ContinueAsyncOpenRunnable")
, mActor(aActor)
, mChannelId(aChannelId)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
MOZ_ASSERT(mActor);
}
NS_IMETHOD Run() override
{
LOG(("HttpBackgroundChannelParent::ContinueAsyncOpen [this=%p channelId=%"
PRIu64 "]\n", mActor.get(), mChannelId));
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIBackgroundChannelRegistrar> registrar =
do_GetService(NS_BACKGROUNDCHANNELREGISTRAR_CONTRACTID);
MOZ_ASSERT(registrar);
registrar->LinkBackgroundChannel(mChannelId, mActor);
return NS_OK;
}
private:
RefPtr<HttpBackgroundChannelParent> mActor;
const uint64_t mChannelId;
};
HttpBackgroundChannelParent::HttpBackgroundChannelParent()
: mIPCOpened(true)
, mBgThreadMutex("HttpBackgroundChannelParent::BgThreadMutex")
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
{
MutexAutoLock lock(mBgThreadMutex);
mBackgroundThread = NS_GetCurrentThread();
}
}
HttpBackgroundChannelParent::~HttpBackgroundChannelParent()
{
MOZ_ASSERT(NS_IsMainThread() || IsOnBackgroundThread());
MOZ_ASSERT(!mIPCOpened);
}
nsresult
HttpBackgroundChannelParent::Init(const uint64_t& aChannelId)
{
LOG(("HttpBackgroundChannelParent::Init [this=%p channelId=%" PRIu64 "]\n",
this, aChannelId));
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
RefPtr<ContinueAsyncOpenRunnable> runnable =
new ContinueAsyncOpenRunnable(this, aChannelId);
return NS_DispatchToMainThread(runnable);
}
void
HttpBackgroundChannelParent::LinkToChannel(HttpChannelParent* aChannelParent)
{
LOG(("HttpBackgroundChannelParent::LinkToChannel [this=%p channel=%p]\n",
this, aChannelParent));
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
if (!mIPCOpened) {
return;
}
mChannelParent = aChannelParent;
}
void
HttpBackgroundChannelParent::OnChannelClosed()
{
LOG(("HttpBackgroundChannelParent::OnChannelClosed [this=%p]\n", this));
AssertIsInMainProcess();
MOZ_ASSERT(NS_IsMainThread());
if (!mIPCOpened) {
return;
}
nsresult rv;
{
MutexAutoLock lock(mBgThreadMutex);
RefPtr<HttpBackgroundChannelParent> self = this;
rv = mBackgroundThread->Dispatch(
NS_NewRunnableFunction(
"net::HttpBackgroundChannelParent::OnChannelClosed",
[self]() {
LOG(("HttpBackgroundChannelParent::DeleteRunnable [this=%p]\n",
self.get()));
AssertIsOnBackgroundThread();
if (!self->mIPCOpened.compareExchange(true, false)) {
return;
}
Unused << self->Send__delete__(self);
}),
NS_DISPATCH_NORMAL);
}
Unused << NS_WARN_IF(NS_FAILED(rv));
}
bool
HttpBackgroundChannelParent::OnStartRequestSent()
{
LOG(("HttpBackgroundChannelParent::OnStartRequestSent [this=%p]\n", this));
AssertIsInMainProcess();
if (NS_WARN_IF(!mIPCOpened)) {
return false;
}
if (!IsOnBackgroundThread()) {
MutexAutoLock lock(mBgThreadMutex);
nsresult rv = mBackgroundThread->Dispatch(
NewRunnableMethod("net::HttpBackgroundChannelParent::OnStartRequestSent",
this,
&HttpBackgroundChannelParent::OnStartRequestSent),
NS_DISPATCH_NORMAL);
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
return NS_SUCCEEDED(rv);
}
return SendOnStartRequestSent();
}
bool
HttpBackgroundChannelParent::OnTransportAndData(
const nsresult& aChannelStatus,
const nsresult& aTransportStatus,
const uint64_t& aOffset,
const uint32_t& aCount,
const nsCString& aData)
{
LOG(("HttpBackgroundChannelParent::OnTransportAndData [this=%p]\n", this));
AssertIsInMainProcess();
if (NS_WARN_IF(!mIPCOpened)) {
return false;
}
if (!IsOnBackgroundThread()) {
MutexAutoLock lock(mBgThreadMutex);
nsresult rv = mBackgroundThread->Dispatch(
NewRunnableMethod<const nsresult,
const nsresult,
const uint64_t,
const uint32_t,
const nsCString>(
"net::HttpBackgroundChannelParent::OnTransportAndData",
this,
&HttpBackgroundChannelParent::OnTransportAndData,
aChannelStatus,
aTransportStatus,
aOffset,
aCount,
aData),
NS_DISPATCH_NORMAL);
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
return NS_SUCCEEDED(rv);
}
return SendOnTransportAndData(aChannelStatus, aTransportStatus,
aOffset, aCount, aData);
}
bool
HttpBackgroundChannelParent::OnStopRequest(const nsresult& aChannelStatus,
const ResourceTimingStruct& aTiming)
{
LOG(("HttpBackgroundChannelParent::OnStopRequest [this=%p "
"status=%" PRIx32 "]\n", this, static_cast<uint32_t>(aChannelStatus)));
AssertIsInMainProcess();
if (NS_WARN_IF(!mIPCOpened)) {
return false;
}
if (!IsOnBackgroundThread()) {
MutexAutoLock lock(mBgThreadMutex);
nsresult rv = mBackgroundThread->Dispatch(
NewRunnableMethod<const nsresult, const ResourceTimingStruct>(
"net::HttpBackgroundChannelParent::OnStopRequest",
this,
&HttpBackgroundChannelParent::OnStopRequest,
aChannelStatus,
aTiming),
NS_DISPATCH_NORMAL);
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
return NS_SUCCEEDED(rv);
}
return SendOnStopRequest(aChannelStatus, aTiming);
}
bool
HttpBackgroundChannelParent::OnProgress(const int64_t& aProgress,
const int64_t& aProgressMax)
{
LOG(("HttpBackgroundChannelParent::OnProgress [this=%p progress=%" PRId64
" max=%" PRId64 "]\n", this, aProgress, aProgressMax));
AssertIsInMainProcess();
if (NS_WARN_IF(!mIPCOpened)) {
return false;
}
if (!IsOnBackgroundThread()) {
MutexAutoLock lock(mBgThreadMutex);
nsresult rv = mBackgroundThread->Dispatch(
NewRunnableMethod<const int64_t, const int64_t>(
"net::HttpBackgroundChannelParent::OnProgress",
this,
&HttpBackgroundChannelParent::OnProgress,
aProgress,
aProgressMax),
NS_DISPATCH_NORMAL);
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
return NS_SUCCEEDED(rv);
}
return SendOnProgress(aProgress, aProgressMax);
}
bool
HttpBackgroundChannelParent::OnStatus(const nsresult& aStatus)
{
LOG(("HttpBackgroundChannelParent::OnStatus [this=%p stauts=%" PRIx32
"]\n", this, static_cast<uint32_t>(aStatus)));
AssertIsInMainProcess();
if (NS_WARN_IF(!mIPCOpened)) {
return false;
}
if (!IsOnBackgroundThread()) {
MutexAutoLock lock(mBgThreadMutex);
nsresult rv = mBackgroundThread->Dispatch(
NewRunnableMethod<const nsresult>(
"net::HttpBackgroundChannelParent::OnStatus",
this,
&HttpBackgroundChannelParent::OnStatus,
aStatus),
NS_DISPATCH_NORMAL);
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
return NS_SUCCEEDED(rv);
}
return SendOnStatus(aStatus);
}
bool
HttpBackgroundChannelParent::OnDiversion()
{
LOG(("HttpBackgroundChannelParent::OnDiversion [this=%p]\n", this));
AssertIsInMainProcess();
if (NS_WARN_IF(!mIPCOpened)) {
return false;
}
if (!IsOnBackgroundThread()) {
MutexAutoLock lock(mBgThreadMutex);
nsresult rv = mBackgroundThread->Dispatch(
NewRunnableMethod("net::HttpBackgroundChannelParent::OnDiversion",
this,
&HttpBackgroundChannelParent::OnDiversion),
NS_DISPATCH_NORMAL);
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
return NS_SUCCEEDED(rv);
}
if (!SendFlushedForDiversion()) {
return false;
}
// The listener chain should now be setup; tell HttpChannelChild to divert
// the OnDataAvailables and OnStopRequest to associated HttpChannelParent.
if (!SendDivertMessages()) {
return false;
}
return true;
}
bool
HttpBackgroundChannelParent::OnNotifyTrackingProtectionDisabled()
{
LOG(("HttpBackgroundChannelParent::OnNotifyTrackingProtectionDisabled [this=%p]\n", this));
AssertIsInMainProcess();
if (NS_WARN_IF(!mIPCOpened)) {
return false;
}
if (!IsOnBackgroundThread()) {
MutexAutoLock lock(mBgThreadMutex);
nsresult rv = mBackgroundThread->Dispatch(
NewRunnableMethod(
"net::HttpBackgroundChannelParent::OnNotifyTrackingProtectionDisabled",
this,
&HttpBackgroundChannelParent::OnNotifyTrackingProtectionDisabled),
NS_DISPATCH_NORMAL);
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
return NS_SUCCEEDED(rv);
}
return SendNotifyTrackingProtectionDisabled();
}
bool
HttpBackgroundChannelParent::OnNotifyTrackingResource()
{
LOG(("HttpBackgroundChannelParent::OnNotifyTrackingResource [this=%p]\n", this));
AssertIsInMainProcess();
if (NS_WARN_IF(!mIPCOpened)) {
return false;
}
if (!IsOnBackgroundThread()) {
MutexAutoLock lock(mBgThreadMutex);
nsresult rv = mBackgroundThread->Dispatch(
NewRunnableMethod(
"net::HttpBackgroundChannelParent::OnNotifyTrackingResource",
this,
&HttpBackgroundChannelParent::OnNotifyTrackingResource),
NS_DISPATCH_NORMAL);
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
return NS_SUCCEEDED(rv);
}
return SendNotifyTrackingResource();
}
bool
HttpBackgroundChannelParent::OnSetClassifierMatchedInfo(
const nsACString& aList,
const nsACString& aProvider,
const nsACString& aPrefix)
{
LOG(("HttpBackgroundChannelParent::OnSetClassifierMatchedInfo [this=%p]\n", this));
AssertIsInMainProcess();
if (NS_WARN_IF(!mIPCOpened)) {
return false;
}
if (!IsOnBackgroundThread()) {
MutexAutoLock lock(mBgThreadMutex);
nsresult rv = mBackgroundThread->Dispatch(
NewRunnableMethod<const nsCString, const nsCString, const nsCString>(
"net::HttpBackgroundChannelParent::OnSetClassifierMatchedInfo",
this,
&HttpBackgroundChannelParent::OnSetClassifierMatchedInfo,
aList,
aProvider,
aPrefix),
NS_DISPATCH_NORMAL);
MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
return NS_SUCCEEDED(rv);
}
ClassifierInfo info;
info.list() = aList;
info.prefix() = aPrefix;
info.provider() = aProvider;
return SendSetClassifierMatchedInfo(info);
}
void
HttpBackgroundChannelParent::ActorDestroy(ActorDestroyReason aWhy)
{
LOG(("HttpBackgroundChannelParent::ActorDestroy [this=%p]\n", this));
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
mIPCOpened = false;
RefPtr<HttpBackgroundChannelParent> self = this;
DebugOnly<nsresult> rv = NS_DispatchToMainThread(NS_NewRunnableFunction(
"net::HttpBackgroundChannelParent::ActorDestroy", [self]() {
MOZ_ASSERT(NS_IsMainThread());
RefPtr<HttpChannelParent> channelParent =
self->mChannelParent.forget();
if (channelParent) {
channelParent->OnBackgroundParentDestroyed();
}
}));
MOZ_ASSERT(NS_SUCCEEDED(rv));
}
} // namespace net
} // namespace mozilla