tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

HttpBackgroundChannelParent.cpp (16944B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set sw=2 ts=8 et tw=80 : */
      3 
      4 /* This Source Code Form is subject to the terms of the Mozilla Public
      5 * License, v. 2.0. If a copy of the MPL was not distributed with this
      6 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      7 
      8 // HttpLog.h should generally be included first
      9 #include "HttpLog.h"
     10 
     11 #include "HttpBackgroundChannelParent.h"
     12 
     13 #include "HttpChannelParent.h"
     14 #include "mozilla/ipc/BackgroundParent.h"
     15 #include "mozilla/IntegerPrintfMacros.h"
     16 #include "mozilla/net/BackgroundChannelRegistrar.h"
     17 #include "mozilla/net/ChannelEventQueue.h"
     18 #include "nsNetCID.h"
     19 #include "nsQueryObject.h"
     20 #include "nsThreadUtils.h"
     21 
     22 using mozilla::dom::ContentParent;
     23 using mozilla::ipc::AssertIsInMainProcess;
     24 using mozilla::ipc::AssertIsOnBackgroundThread;
     25 using mozilla::ipc::BackgroundParent;
     26 using mozilla::ipc::IPCResult;
     27 using mozilla::ipc::IsOnBackgroundThread;
     28 
     29 namespace mozilla {
     30 namespace net {
     31 
     32 /*
     33 * Helper class for continuing the AsyncOpen procedure on main thread.
     34 */
     35 class ContinueAsyncOpenRunnable final : public Runnable {
     36 public:
     37  ContinueAsyncOpenRunnable(HttpBackgroundChannelParent* aActor,
     38                            const uint64_t& aChannelId)
     39      : Runnable("net::ContinueAsyncOpenRunnable"),
     40        mActor(aActor),
     41        mChannelId(aChannelId) {
     42    AssertIsInMainProcess();
     43    AssertIsOnBackgroundThread();
     44    MOZ_ASSERT(mActor);
     45  }
     46 
     47  NS_IMETHOD Run() override {
     48    LOG(
     49        ("HttpBackgroundChannelParent::ContinueAsyncOpen [this=%p "
     50         "channelId=%" PRIu64 "]\n",
     51         mActor.get(), mChannelId));
     52    AssertIsInMainProcess();
     53    MOZ_ASSERT(NS_IsMainThread());
     54 
     55    nsCOMPtr<nsIBackgroundChannelRegistrar> registrar =
     56        BackgroundChannelRegistrar::GetOrCreate();
     57    MOZ_ASSERT(registrar);
     58 
     59    registrar->LinkBackgroundChannel(mChannelId, mActor);
     60    return NS_OK;
     61  }
     62 
     63 private:
     64  RefPtr<HttpBackgroundChannelParent> mActor;
     65  const uint64_t mChannelId;
     66 };
     67 
     68 HttpBackgroundChannelParent::HttpBackgroundChannelParent()
     69    : mIPCOpened(true),
     70      mBgThreadMutex("HttpBackgroundChannelParent::BgThreadMutex") {
     71  AssertIsInMainProcess();
     72  AssertIsOnBackgroundThread();
     73 
     74  {
     75    MutexAutoLock lock(mBgThreadMutex);
     76    mBackgroundThread = NS_GetCurrentThread();
     77  }
     78 }
     79 
     80 HttpBackgroundChannelParent::~HttpBackgroundChannelParent() {
     81  MOZ_ASSERT(NS_IsMainThread() || IsOnBackgroundThread());
     82  MOZ_ASSERT(!mIPCOpened);
     83 }
     84 
     85 nsresult HttpBackgroundChannelParent::Init(const uint64_t& aChannelId) {
     86  LOG(("HttpBackgroundChannelParent::Init [this=%p channelId=%" PRIu64 "]\n",
     87       this, aChannelId));
     88  AssertIsInMainProcess();
     89  AssertIsOnBackgroundThread();
     90 
     91  RefPtr<ContinueAsyncOpenRunnable> runnable =
     92      new ContinueAsyncOpenRunnable(this, aChannelId);
     93 
     94  return NS_DispatchToMainThread(runnable);
     95 }
     96 
     97 void HttpBackgroundChannelParent::LinkToChannel(
     98    HttpChannelParent* aChannelParent) {
     99  LOG(("HttpBackgroundChannelParent::LinkToChannel [this=%p channel=%p]\n",
    100       this, aChannelParent));
    101  AssertIsInMainProcess();
    102  MOZ_ASSERT(NS_IsMainThread());
    103 
    104  if (!mIPCOpened) {
    105    return;
    106  }
    107 
    108  mChannelParent = aChannelParent;
    109 }
    110 
    111 void HttpBackgroundChannelParent::OnChannelClosed() {
    112  LOG(("HttpBackgroundChannelParent::OnChannelClosed [this=%p]\n", this));
    113  AssertIsInMainProcess();
    114  MOZ_ASSERT(NS_IsMainThread());
    115 
    116  if (!mIPCOpened) {
    117    return;
    118  }
    119 
    120  nsresult rv;
    121 
    122  {
    123    MutexAutoLock lock(mBgThreadMutex);
    124    RefPtr<HttpBackgroundChannelParent> self = this;
    125    rv = mBackgroundThread->Dispatch(
    126        NS_NewRunnableFunction(
    127            "net::HttpBackgroundChannelParent::OnChannelClosed",
    128            [self]() {
    129              LOG(("HttpBackgroundChannelParent::DeleteRunnable [this=%p]\n",
    130                   self.get()));
    131              AssertIsOnBackgroundThread();
    132 
    133              if (!self->mIPCOpened.compareExchange(true, false)) {
    134                return;
    135              }
    136 
    137              (void)self->Send__delete__(self);
    138            }),
    139        NS_DISPATCH_NORMAL);
    140  }
    141 
    142  (void)NS_WARN_IF(NS_FAILED(rv));
    143 }
    144 
    145 bool HttpBackgroundChannelParent::OnStartRequest(
    146    nsHttpResponseHead&& aResponseHead, const bool& aUseResponseHead,
    147    const nsHttpHeaderArray& aRequestHeaders,
    148    const HttpChannelOnStartRequestArgs& aArgs,
    149    const nsCOMPtr<nsICacheEntry>& aAltDataSource,
    150    TimeStamp aOnStartRequestStart) {
    151  LOG(("HttpBackgroundChannelParent::OnStartRequest [this=%p]\n", this));
    152  AssertIsInMainProcess();
    153 
    154  if (NS_WARN_IF(!mIPCOpened)) {
    155    return false;
    156  }
    157 
    158  if (!IsOnBackgroundThread()) {
    159    MutexAutoLock lock(mBgThreadMutex);
    160    nsresult rv = mBackgroundThread->Dispatch(
    161        NewRunnableMethod<nsHttpResponseHead&&, const bool,
    162                          const nsHttpHeaderArray,
    163                          const HttpChannelOnStartRequestArgs,
    164                          const nsCOMPtr<nsICacheEntry>, TimeStamp>(
    165            "net::HttpBackgroundChannelParent::OnStartRequest", this,
    166            &HttpBackgroundChannelParent::OnStartRequest,
    167            std::move(aResponseHead), aUseResponseHead, aRequestHeaders, aArgs,
    168            aAltDataSource, aOnStartRequestStart),
    169        NS_DISPATCH_NORMAL);
    170 
    171    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
    172 
    173    return NS_SUCCEEDED(rv);
    174  }
    175 
    176  HttpChannelAltDataStream altData;
    177  if (aAltDataSource) {
    178    nsAutoCString altDataType;
    179    (void)aAltDataSource->GetAltDataType(altDataType);
    180 
    181    if (!altDataType.IsEmpty()) {
    182      nsCOMPtr<nsIInputStream> inputStream;
    183      nsresult rv = aAltDataSource->OpenAlternativeInputStream(
    184          altDataType, getter_AddRefs(inputStream));
    185      if (NS_SUCCEEDED(rv)) {
    186        (void)mozilla::ipc::SerializeIPCStream(inputStream.forget(),
    187                                               altData.altDataInputStream(),
    188                                               /* aAllowLazy */ true);
    189      }
    190    }
    191  }
    192 
    193  return SendOnStartRequest(std::move(aResponseHead), aUseResponseHead,
    194                            aRequestHeaders, aArgs, altData,
    195                            aOnStartRequestStart);
    196 }
    197 
    198 bool HttpBackgroundChannelParent::OnTransportAndData(
    199    const nsresult& aChannelStatus, const nsresult& aTransportStatus,
    200    const uint64_t& aOffset, const uint32_t& aCount, const nsCString& aData,
    201    TimeStamp aOnDataAvailableStart) {
    202  LOG(("HttpBackgroundChannelParent::OnTransportAndData [this=%p]\n", this));
    203  AssertIsInMainProcess();
    204 
    205  if (NS_WARN_IF(!mIPCOpened)) {
    206    return false;
    207  }
    208 
    209  if (!IsOnBackgroundThread()) {
    210    MutexAutoLock lock(mBgThreadMutex);
    211    nsresult rv = mBackgroundThread->Dispatch(
    212        NewRunnableMethod<const nsresult, const nsresult, const uint64_t,
    213                          const uint32_t, const nsCString, TimeStamp>(
    214            "net::HttpBackgroundChannelParent::OnTransportAndData", this,
    215            &HttpBackgroundChannelParent::OnTransportAndData, aChannelStatus,
    216            aTransportStatus, aOffset, aCount, aData, aOnDataAvailableStart),
    217        NS_DISPATCH_NORMAL);
    218 
    219    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
    220 
    221    return NS_SUCCEEDED(rv);
    222  }
    223 
    224  nsHttp::SendFunc<nsDependentCSubstring> sendFunc =
    225      [self = UnsafePtr<HttpBackgroundChannelParent>(this), aChannelStatus,
    226       aTransportStatus,
    227       aOnDataAvailableStart](const nsDependentCSubstring& aData,
    228                              uint64_t aOffset, uint32_t aCount) {
    229        return self->SendOnTransportAndData(aChannelStatus, aTransportStatus,
    230                                            aOffset, aCount, aData, false,
    231                                            aOnDataAvailableStart);
    232      };
    233 
    234  return nsHttp::SendDataInChunks(aData, aOffset, aCount, sendFunc);
    235 }
    236 
    237 bool HttpBackgroundChannelParent::OnStopRequest(
    238    const nsresult& aChannelStatus, const ResourceTimingStructArgs& aTiming,
    239    const nsHttpHeaderArray& aResponseTrailers,
    240    const nsTArray<ConsoleReportCollected>& aConsoleReports,
    241    TimeStamp aOnStopRequestStart) {
    242  LOG(
    243      ("HttpBackgroundChannelParent::OnStopRequest [this=%p "
    244       "status=%" PRIx32 "]\n",
    245       this, static_cast<uint32_t>(aChannelStatus)));
    246  AssertIsInMainProcess();
    247 
    248  if (NS_WARN_IF(!mIPCOpened)) {
    249    return false;
    250  }
    251 
    252  if (!IsOnBackgroundThread()) {
    253    MutexAutoLock lock(mBgThreadMutex);
    254    nsresult rv = mBackgroundThread->Dispatch(
    255        NewRunnableMethod<const nsresult, const ResourceTimingStructArgs,
    256                          const nsHttpHeaderArray,
    257                          const CopyableTArray<ConsoleReportCollected>,
    258                          TimeStamp>(
    259            "net::HttpBackgroundChannelParent::OnStopRequest", this,
    260            &HttpBackgroundChannelParent::OnStopRequest, aChannelStatus,
    261            aTiming, aResponseTrailers, aConsoleReports, aOnStopRequestStart),
    262        NS_DISPATCH_NORMAL);
    263 
    264    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
    265 
    266    return NS_SUCCEEDED(rv);
    267  }
    268 
    269  // See the child code for why we do this.
    270  TimeStamp lastActTabOpt = nsHttp::GetLastActiveTabLoadOptimizationHit();
    271 
    272  return SendOnStopRequest(aChannelStatus, aTiming, lastActTabOpt,
    273                           aResponseTrailers, aConsoleReports, false,
    274                           aOnStopRequestStart);
    275 }
    276 
    277 bool HttpBackgroundChannelParent::OnConsoleReport(
    278    const nsTArray<ConsoleReportCollected>& aConsoleReports) {
    279  LOG(("HttpBackgroundChannelParent::OnConsoleReport [this=%p]", this));
    280  AssertIsInMainProcess();
    281 
    282  if (NS_WARN_IF(!mIPCOpened)) {
    283    return false;
    284  }
    285 
    286  if (!IsOnBackgroundThread()) {
    287    MutexAutoLock lock(mBgThreadMutex);
    288    nsresult rv = mBackgroundThread->Dispatch(
    289        NewRunnableMethod<const CopyableTArray<ConsoleReportCollected>>(
    290            "net::HttpBackgroundChannelParent::OnConsoleReport", this,
    291            &HttpBackgroundChannelParent::OnConsoleReport, aConsoleReports),
    292        NS_DISPATCH_NORMAL);
    293 
    294    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
    295 
    296    return NS_SUCCEEDED(rv);
    297  }
    298 
    299  return SendOnConsoleReport(aConsoleReports);
    300 }
    301 
    302 bool HttpBackgroundChannelParent::OnAfterLastPart(const nsresult aStatus) {
    303  LOG(("HttpBackgroundChannelParent::OnAfterLastPart [this=%p]\n", this));
    304  AssertIsInMainProcess();
    305 
    306  if (NS_WARN_IF(!mIPCOpened)) {
    307    return false;
    308  }
    309 
    310  if (!IsOnBackgroundThread()) {
    311    MutexAutoLock lock(mBgThreadMutex);
    312    nsresult rv = mBackgroundThread->Dispatch(
    313        NewRunnableMethod<const nsresult>(
    314            "net::HttpBackgroundChannelParent::OnAfterLastPart", this,
    315            &HttpBackgroundChannelParent::OnAfterLastPart, aStatus),
    316        NS_DISPATCH_NORMAL);
    317 
    318    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
    319 
    320    return NS_SUCCEEDED(rv);
    321  }
    322 
    323  return SendOnAfterLastPart(aStatus);
    324 }
    325 
    326 bool HttpBackgroundChannelParent::OnProgress(const int64_t aProgress,
    327                                             const int64_t aProgressMax) {
    328  LOG(("HttpBackgroundChannelParent::OnProgress [this=%p]\n", this));
    329  AssertIsInMainProcess();
    330 
    331  if (NS_WARN_IF(!mIPCOpened)) {
    332    return false;
    333  }
    334 
    335  if (!IsOnBackgroundThread()) {
    336    MutexAutoLock lock(mBgThreadMutex);
    337    nsresult rv = mBackgroundThread->Dispatch(
    338        NewRunnableMethod<const int64_t, const int64_t>(
    339            "net::HttpBackgroundChannelParent::OnProgress", this,
    340            &HttpBackgroundChannelParent::OnProgress, aProgress, aProgressMax),
    341        NS_DISPATCH_NORMAL);
    342 
    343    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
    344 
    345    return NS_SUCCEEDED(rv);
    346  }
    347 
    348  return SendOnProgress(aProgress, aProgressMax);
    349 }
    350 
    351 bool HttpBackgroundChannelParent::OnStatus(const nsresult aStatus) {
    352  LOG(("HttpBackgroundChannelParent::OnStatus [this=%p]\n", this));
    353  AssertIsInMainProcess();
    354 
    355  if (NS_WARN_IF(!mIPCOpened)) {
    356    return false;
    357  }
    358 
    359  if (!IsOnBackgroundThread()) {
    360    MutexAutoLock lock(mBgThreadMutex);
    361    nsresult rv = mBackgroundThread->Dispatch(
    362        NewRunnableMethod<const nsresult>(
    363            "net::HttpBackgroundChannelParent::OnStatus", this,
    364            &HttpBackgroundChannelParent::OnStatus, aStatus),
    365        NS_DISPATCH_NORMAL);
    366 
    367    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
    368 
    369    return NS_SUCCEEDED(rv);
    370  }
    371 
    372  return SendOnStatus(aStatus);
    373 }
    374 
    375 bool HttpBackgroundChannelParent::OnNotifyClassificationFlags(
    376    uint32_t aClassificationFlags, bool aIsThirdParty) {
    377  LOG(
    378      ("HttpBackgroundChannelParent::OnNotifyClassificationFlags "
    379       "classificationFlags=%" PRIu32 ", thirdparty=%d [this=%p]\n",
    380       aClassificationFlags, static_cast<int>(aIsThirdParty), this));
    381  AssertIsInMainProcess();
    382 
    383  if (NS_WARN_IF(!mIPCOpened)) {
    384    return false;
    385  }
    386 
    387  if (!IsOnBackgroundThread()) {
    388    MutexAutoLock lock(mBgThreadMutex);
    389    nsresult rv = mBackgroundThread->Dispatch(
    390        NewRunnableMethod<uint32_t, bool>(
    391            "net::HttpBackgroundChannelParent::OnNotifyClassificationFlags",
    392            this, &HttpBackgroundChannelParent::OnNotifyClassificationFlags,
    393            aClassificationFlags, aIsThirdParty),
    394        NS_DISPATCH_NORMAL);
    395 
    396    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
    397 
    398    return NS_SUCCEEDED(rv);
    399  }
    400 
    401  return SendNotifyClassificationFlags(aClassificationFlags, aIsThirdParty);
    402 }
    403 
    404 bool HttpBackgroundChannelParent::OnSetClassifierMatchedInfo(
    405    const nsACString& aList, const nsACString& aProvider,
    406    const nsACString& aFullHash) {
    407  LOG(("HttpBackgroundChannelParent::OnSetClassifierMatchedInfo [this=%p]\n",
    408       this));
    409  AssertIsInMainProcess();
    410 
    411  if (NS_WARN_IF(!mIPCOpened)) {
    412    return false;
    413  }
    414 
    415  if (!IsOnBackgroundThread()) {
    416    MutexAutoLock lock(mBgThreadMutex);
    417    nsresult rv = mBackgroundThread->Dispatch(
    418        NewRunnableMethod<const nsCString, const nsCString, const nsCString>(
    419            "net::HttpBackgroundChannelParent::OnSetClassifierMatchedInfo",
    420            this, &HttpBackgroundChannelParent::OnSetClassifierMatchedInfo,
    421            aList, aProvider, aFullHash),
    422        NS_DISPATCH_NORMAL);
    423 
    424    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
    425 
    426    return NS_SUCCEEDED(rv);
    427  }
    428 
    429  ClassifierInfo info;
    430  info.list() = aList;
    431  info.fullhash() = aFullHash;
    432  info.provider() = aProvider;
    433 
    434  return SendSetClassifierMatchedInfo(info);
    435 }
    436 
    437 bool HttpBackgroundChannelParent::OnSetClassifierMatchedTrackingInfo(
    438    const nsACString& aLists, const nsACString& aFullHashes) {
    439  LOG(
    440      ("HttpBackgroundChannelParent::OnSetClassifierMatchedTrackingInfo "
    441       "[this=%p]\n",
    442       this));
    443  AssertIsInMainProcess();
    444 
    445  if (NS_WARN_IF(!mIPCOpened)) {
    446    return false;
    447  }
    448 
    449  if (!IsOnBackgroundThread()) {
    450    MutexAutoLock lock(mBgThreadMutex);
    451    nsresult rv = mBackgroundThread->Dispatch(
    452        NewRunnableMethod<const nsCString, const nsCString>(
    453            "net::HttpBackgroundChannelParent::"
    454            "OnSetClassifierMatchedTrackingInfo",
    455            this,
    456            &HttpBackgroundChannelParent::OnSetClassifierMatchedTrackingInfo,
    457            aLists, aFullHashes),
    458        NS_DISPATCH_NORMAL);
    459 
    460    MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv));
    461 
    462    return NS_SUCCEEDED(rv);
    463  }
    464 
    465  ClassifierInfo info;
    466  info.list() = aLists;
    467  info.fullhash() = aFullHashes;
    468 
    469  return SendSetClassifierMatchedTrackingInfo(info);
    470 }
    471 
    472 nsISerialEventTarget* HttpBackgroundChannelParent::GetBackgroundTarget() {
    473  MOZ_ASSERT(mBackgroundThread);
    474  return mBackgroundThread.get();
    475 }
    476 
    477 auto HttpBackgroundChannelParent::AttachStreamFilter(
    478    Endpoint<extensions::PStreamFilterParent>&& aParentEndpoint,
    479    Endpoint<extensions::PStreamFilterChild>&& aChildEndpoint)
    480    -> RefPtr<ChildEndpointPromise> {
    481  LOG(("HttpBackgroundChannelParent::AttachStreamFilter [this=%p]\n", this));
    482  MOZ_ASSERT(IsOnBackgroundThread());
    483 
    484  if (NS_WARN_IF(!mIPCOpened) ||
    485      !SendAttachStreamFilter(std::move(aParentEndpoint))) {
    486    return ChildEndpointPromise::CreateAndReject(false, __func__);
    487  }
    488 
    489  return ChildEndpointPromise::CreateAndResolve(std::move(aChildEndpoint),
    490                                                __func__);
    491 }
    492 
    493 auto HttpBackgroundChannelParent::DetachStreamFilters()
    494    -> RefPtr<GenericPromise> {
    495  LOG(("HttpBackgroundChannelParent::DetachStreamFilters [this=%p]\n", this));
    496  if (NS_WARN_IF(!mIPCOpened) || !SendDetachStreamFilters()) {
    497    return GenericPromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
    498  }
    499 
    500  return GenericPromise::CreateAndResolve(true, __func__);
    501 }
    502 
    503 void HttpBackgroundChannelParent::ActorDestroy(ActorDestroyReason aWhy) {
    504  LOG(("HttpBackgroundChannelParent::ActorDestroy [this=%p]\n", this));
    505  AssertIsInMainProcess();
    506  AssertIsOnBackgroundThread();
    507 
    508  mIPCOpened = false;
    509 
    510  RefPtr<HttpBackgroundChannelParent> self = this;
    511  DebugOnly<nsresult> rv = NS_DispatchToMainThread(NS_NewRunnableFunction(
    512      "net::HttpBackgroundChannelParent::ActorDestroy", [self]() {
    513        MOZ_ASSERT(NS_IsMainThread());
    514 
    515        RefPtr<HttpChannelParent> channelParent =
    516            std::move(self->mChannelParent);
    517 
    518        if (channelParent) {
    519          channelParent->OnBackgroundParentDestroyed();
    520        }
    521      }));
    522  MOZ_ASSERT(NS_SUCCEEDED(rv));
    523 }
    524 
    525 }  // namespace net
    526 }  // namespace mozilla