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