tor-browser

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

CacheStreamControlParent.cpp (5509B)


      1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
      2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
      3 /* This Source Code Form is subject to the terms of the Mozilla Public
      4 * License, v. 2.0. If a copy of the MPL was not distributed with this
      5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      6 
      7 #include "mozilla/dom/cache/CacheStreamControlParent.h"
      8 
      9 #include "mozilla/dom/cache/CacheTypes.h"
     10 #include "mozilla/dom/cache/ReadStream.h"
     11 #include "mozilla/dom/cache/StreamList.h"
     12 #include "mozilla/ipc/IPCStreamUtils.h"
     13 #include "mozilla/ipc/PBackgroundParent.h"
     14 #include "nsISupportsImpl.h"
     15 #include "nsTArray.h"
     16 
     17 namespace mozilla::dom::cache {
     18 
     19 using mozilla::ipc::FileDescriptor;
     20 
     21 // declared in ActorUtils.h
     22 void DeallocPCacheStreamControlParent(PCacheStreamControlParent* aActor) {
     23  delete aActor;
     24 }
     25 
     26 CacheStreamControlParent::CacheStreamControlParent() {
     27  MOZ_COUNT_CTOR(cache::CacheStreamControlParent);
     28 }
     29 
     30 CacheStreamControlParent::~CacheStreamControlParent() {
     31  NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
     32  MOZ_DIAGNOSTIC_ASSERT(!mStreamList);
     33  MOZ_COUNT_DTOR(cache::CacheStreamControlParent);
     34 }
     35 
     36 void CacheStreamControlParent::SerializeControl(
     37    CacheReadStream* aReadStreamOut) {
     38  NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
     39  MOZ_DIAGNOSTIC_ASSERT(aReadStreamOut);
     40  aReadStreamOut->control() = this;
     41 }
     42 
     43 void CacheStreamControlParent::SerializeStream(CacheReadStream* aReadStreamOut,
     44                                               nsIInputStream* aStream) {
     45  NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
     46  MOZ_DIAGNOSTIC_ASSERT(aReadStreamOut);
     47 
     48  DebugOnly<bool> ok = mozilla::ipc::SerializeIPCStream(
     49      do_AddRef(aStream), aReadStreamOut->stream(), /* aAllowLazy */ false);
     50  MOZ_ASSERT(ok);
     51 }
     52 
     53 void CacheStreamControlParent::OpenStream(const nsID& aId,
     54                                          InputStreamResolver&& aResolver) {
     55  NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
     56  MOZ_DIAGNOSTIC_ASSERT(aResolver);
     57 
     58  if (!mStreamList || !mStreamList->ShouldOpenStreamFor(aId)) {
     59    aResolver(nullptr);
     60    return;
     61  }
     62 
     63  // Make sure to add ourself as a Listener even thought we are using
     64  // a separate resolver function to signal the completion of the
     65  // operation.  The Manager uses the existence of the Listener to ensure
     66  // that its safe to complete the operation.
     67  mStreamList->GetManager().ExecuteOpenStream(this, std::move(aResolver), aId);
     68 }
     69 
     70 void CacheStreamControlParent::NoteClosedAfterForget(const nsID& aId) {
     71  NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
     72  RecvNoteClosed(aId);
     73 }
     74 
     75 #ifdef DEBUG
     76 void CacheStreamControlParent::AssertOwningThread() {
     77  NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
     78 }
     79 #endif
     80 
     81 void CacheStreamControlParent::LostIPCCleanup(
     82    SafeRefPtr<StreamList> aStreamList) {
     83  NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
     84  CloseAllReadStreamsWithoutReporting();
     85  // If the initial SendPStreamControlConstructor() fails we will
     86  // be called before mStreamList is set.
     87  if (!aStreamList) {
     88    return;
     89  }
     90  aStreamList->GetManager().RemoveListener(this);
     91 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
     92  aStreamList->GetManager().RecordHaveDeletedCSCP(Id());
     93 #endif
     94  aStreamList->RemoveStreamControl(this);
     95  aStreamList->NoteClosedAll();
     96  mStreamList = nullptr;
     97 }
     98 
     99 void CacheStreamControlParent::ActorDestroy(ActorDestroyReason aReason) {
    100  LostIPCCleanup(std::move(mStreamList));
    101 }
    102 
    103 void CacheStreamControlParent::AssertWillDelete() {
    104 #ifdef MOZ_DIAGNOSTIC_ASSERT_ENABLED
    105  // If we cannot send, Send__delete__ will not do any cleanup.
    106  // But if we are still unfreed, that might be wrong.
    107  if (mStreamList && !CanSend()) {
    108    MOZ_ASSERT(false, "Attempt to delete blocking CSCP that cannot send.");
    109    mStreamList->GetManager().RecordMayNotDeleteCSCP(Id());
    110  }
    111 #endif
    112 }
    113 
    114 mozilla::ipc::IPCResult CacheStreamControlParent::RecvOpenStream(
    115    const nsID& aStreamId, OpenStreamResolver&& aResolver) {
    116  NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
    117 
    118  OpenStream(aStreamId, [aResolver, self = RefPtr{this}](
    119                            nsCOMPtr<nsIInputStream>&& aStream) {
    120    Maybe<IPCStream> stream;
    121    if (self->CanSend() &&
    122        mozilla::ipc::SerializeIPCStream(aStream.forget(), stream,
    123                                         /* aAllowLazy */ false)) {
    124      aResolver(stream);
    125    } else {
    126      aResolver(Nothing());
    127    }
    128  });
    129 
    130  return IPC_OK();
    131 }
    132 
    133 mozilla::ipc::IPCResult CacheStreamControlParent::RecvNoteClosed(
    134    const nsID& aId) {
    135  NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
    136  MOZ_DIAGNOSTIC_ASSERT(mStreamList);
    137  mStreamList->NoteClosed(aId);
    138  return IPC_OK();
    139 }
    140 
    141 void CacheStreamControlParent::SetStreamList(
    142    SafeRefPtr<StreamList> aStreamList) {
    143  NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
    144  MOZ_DIAGNOSTIC_ASSERT(!mStreamList);
    145  mStreamList = std::move(aStreamList);
    146 }
    147 
    148 void CacheStreamControlParent::CloseAll() {
    149  NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
    150 
    151  QM_WARNONLY_TRY(OkIf(SendCloseAll()));
    152 
    153  // Attention: NotifyCloseAll potentially destroys our this synchronously!
    154  NotifyCloseAll();
    155 }
    156 
    157 void CacheStreamControlParent::Shutdown() {
    158  NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
    159 
    160  AssertWillDelete();
    161  // If child process is gone, warn and allow actor to clean up normally
    162  QM_WARNONLY_TRY(OkIf(Send__delete__(this)));
    163 }
    164 
    165 void CacheStreamControlParent::NotifyCloseAll() {
    166  NS_ASSERT_OWNINGTHREAD(CacheStreamControlParent);
    167  CloseAllReadStreams();
    168 }
    169 
    170 }  // namespace mozilla::dom::cache