Line data Source code
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/CacheStreamControlChild.h"
8 :
9 : #include "mozilla/Unused.h"
10 : #include "mozilla/dom/cache/ActorUtils.h"
11 : #include "mozilla/dom/cache/CacheTypes.h"
12 : #include "mozilla/dom/cache/ReadStream.h"
13 : #include "mozilla/ipc/FileDescriptorSetChild.h"
14 : #include "mozilla/ipc/PBackgroundChild.h"
15 : #include "mozilla/ipc/PFileDescriptorSetChild.h"
16 : #include "nsISupportsImpl.h"
17 :
18 : namespace mozilla {
19 : namespace dom {
20 : namespace cache {
21 :
22 : using mozilla::dom::OptionalFileDescriptorSet;
23 : using mozilla::ipc::AutoIPCStream;
24 : using mozilla::ipc::FileDescriptor;
25 : using mozilla::ipc::FileDescriptorSetChild;
26 : using mozilla::ipc::PFileDescriptorSetChild;
27 :
28 : // declared in ActorUtils.h
29 : PCacheStreamControlChild*
30 0 : AllocPCacheStreamControlChild()
31 : {
32 0 : return new CacheStreamControlChild();
33 : }
34 :
35 : // declared in ActorUtils.h
36 : void
37 0 : DeallocPCacheStreamControlChild(PCacheStreamControlChild* aActor)
38 : {
39 0 : delete aActor;
40 0 : }
41 :
42 0 : CacheStreamControlChild::CacheStreamControlChild()
43 : : mDestroyStarted(false)
44 0 : , mDestroyDelayed(false)
45 : {
46 0 : MOZ_COUNT_CTOR(cache::CacheStreamControlChild);
47 0 : }
48 :
49 0 : CacheStreamControlChild::~CacheStreamControlChild()
50 : {
51 0 : NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
52 0 : MOZ_COUNT_DTOR(cache::CacheStreamControlChild);
53 0 : }
54 :
55 : void
56 0 : CacheStreamControlChild::StartDestroy()
57 : {
58 0 : NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
59 : // This can get called twice under some circumstances. For example, if the
60 : // actor is added to a CacheWorkerHolder that has already been notified and
61 : // the Cache actor has no mListener.
62 0 : if (mDestroyStarted) {
63 0 : return;
64 : }
65 0 : mDestroyStarted = true;
66 :
67 : // If any of the streams have started to be read, then wait for them to close
68 : // naturally.
69 0 : if (HasEverBeenRead()) {
70 : // Note that we are delaying so that we can re-check for active streams
71 : // in NoteClosedAfterForget().
72 0 : mDestroyDelayed = true;
73 0 : return;
74 : }
75 :
76 : // Otherwise, if the streams have not been touched then just pre-emptively
77 : // close them now. This handles the case where someone retrieves a Response
78 : // from the Cache, but never accesses the body. We should not keep the
79 : // Worker alive until that Response is GC'd just because of its ignored
80 : // body stream.
81 :
82 : // Begin shutting down all streams. This is the same as if the parent had
83 : // asked us to shutdown. So simulate the CloseAll IPC message.
84 0 : RecvCloseAll();
85 : }
86 :
87 : void
88 0 : CacheStreamControlChild::SerializeControl(CacheReadStream* aReadStreamOut)
89 : {
90 0 : NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
91 0 : MOZ_DIAGNOSTIC_ASSERT(aReadStreamOut);
92 0 : aReadStreamOut->controlParent() = nullptr;
93 0 : aReadStreamOut->controlChild() = this;
94 0 : }
95 :
96 : void
97 0 : CacheStreamControlChild::SerializeStream(CacheReadStream* aReadStreamOut,
98 : nsIInputStream* aStream,
99 : nsTArray<UniquePtr<AutoIPCStream>>& aStreamCleanupList)
100 : {
101 0 : NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
102 0 : MOZ_DIAGNOSTIC_ASSERT(aReadStreamOut);
103 0 : MOZ_DIAGNOSTIC_ASSERT(aStream);
104 0 : UniquePtr<AutoIPCStream> autoStream(new AutoIPCStream(aReadStreamOut->stream()));
105 0 : autoStream->Serialize(aStream, Manager());
106 0 : aStreamCleanupList.AppendElement(Move(autoStream));
107 0 : }
108 :
109 : void
110 0 : CacheStreamControlChild::NoteClosedAfterForget(const nsID& aId)
111 : {
112 0 : NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
113 0 : Unused << SendNoteClosed(aId);
114 :
115 : // A stream has closed. If we delayed StartDestry() due to this stream
116 : // being read, then we should check to see if any of the remaining streams
117 : // are active. If none of our other streams have been read, then we can
118 : // proceed with the shutdown now.
119 0 : if (mDestroyDelayed && !HasEverBeenRead()) {
120 0 : mDestroyDelayed = false;
121 0 : RecvCloseAll();
122 : }
123 0 : }
124 :
125 : #ifdef DEBUG
126 : void
127 0 : CacheStreamControlChild::AssertOwningThread()
128 : {
129 0 : NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
130 0 : }
131 : #endif
132 :
133 : void
134 0 : CacheStreamControlChild::ActorDestroy(ActorDestroyReason aReason)
135 : {
136 0 : NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
137 0 : CloseAllReadStreamsWithoutReporting();
138 0 : RemoveWorkerHolder();
139 0 : }
140 :
141 : mozilla::ipc::IPCResult
142 0 : CacheStreamControlChild::RecvClose(const nsID& aId)
143 : {
144 0 : NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
145 0 : CloseReadStreams(aId);
146 0 : return IPC_OK();
147 : }
148 :
149 : mozilla::ipc::IPCResult
150 0 : CacheStreamControlChild::RecvCloseAll()
151 : {
152 0 : NS_ASSERT_OWNINGTHREAD(CacheStreamControlChild);
153 0 : CloseAllReadStreams();
154 0 : return IPC_OK();
155 : }
156 :
157 : } // namespace cache
158 : } // namespace dom
159 : } // namespace mozilla
|