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 #ifndef mozilla_dom_ipc_BlobParent_h
8 #define mozilla_dom_ipc_BlobParent_h
9 
10 #include "mozilla/Attributes.h"
11 #include "mozilla/StaticPtr.h"
12 #include "mozilla/dom/PBlobParent.h"
13 #include "nsCOMPtr.h"
14 #include "nsTArray.h"
15 
16 template <class, class> class nsDataHashtable;
17 class nsIDHashKey;
18 class nsIEventTarget;
19 class nsIRemoteBlob;
20 template <class> class nsRevocableEventPtr;
21 class nsString;
22 
23 namespace mozilla {
24 
25 class Mutex;
26 
27 namespace ipc {
28 
29 class PBackgroundParent;
30 
31 } // namespace ipc
32 
33 namespace dom {
34 
35 class ContentParent;
36 class BlobImpl;
37 class nsIContentParent;
38 class PBlobStreamParent;
39 
40 class BlobParent final
41   : public PBlobParent
42 {
43   typedef mozilla::ipc::PBackgroundParent PBackgroundParent;
44 
45   class IDTableEntry;
46   typedef nsDataHashtable<nsIDHashKey, IDTableEntry*> IDTable;
47 
48   class OpenStreamRunnable;
49   friend class OpenStreamRunnable;
50 
51   class RemoteBlobImpl;
52 
53   struct CreateBlobImplMetadata;
54 
55   static StaticAutoPtr<IDTable> sIDTable;
56   static StaticAutoPtr<Mutex> sIDTableMutex;
57 
58   BlobImpl* mBlobImpl;
59   RemoteBlobImpl* mRemoteBlobImpl;
60 
61   // One of these will be null and the other non-null.
62   PBackgroundParent* mBackgroundManager;
63   nsCOMPtr<nsIContentParent> mContentManager;
64 
65   nsCOMPtr<nsIEventTarget> mEventTarget;
66 
67   // nsIInputStreams backed by files must ensure that the files are actually
68   // opened and closed on a background thread before we can send their file
69   // handles across to the child. The child process could crash during this
70   // process so we need to make sure we cancel the intended response in such a
71   // case. We do that by holding an array of nsRevocableEventPtr. If the child
72   // crashes then this actor will be destroyed and the nsRevocableEventPtr
73   // destructor will cancel any stream events that are currently in flight.
74   nsTArray<nsRevocableEventPtr<OpenStreamRunnable>> mOpenStreamRunnables;
75 
76   RefPtr<IDTableEntry> mIDTableEntry;
77 
78   bool mOwnsBlobImpl;
79 
80 public:
81   class FriendKey;
82 
83   static void
84   Startup(const FriendKey& aKey);
85 
86   // These create functions are called on the sending side.
87   static BlobParent*
88   GetOrCreate(nsIContentParent* aManager, BlobImpl* aBlobImpl);
89 
90   static BlobParent*
91   GetOrCreate(PBackgroundParent* aManager, BlobImpl* aBlobImpl);
92 
93   // These create functions are called on the receiving side.
94   static BlobParent*
95   Create(nsIContentParent* aManager,
96          const ParentBlobConstructorParams& aParams);
97 
98   static BlobParent*
99   Create(PBackgroundParent* aManager,
100          const ParentBlobConstructorParams& aParams);
101 
102   static void
Destroy(PBlobParent * aActor)103   Destroy(PBlobParent* aActor)
104   {
105     delete static_cast<BlobParent*>(aActor);
106   }
107 
108   static already_AddRefed<BlobImpl>
109   GetBlobImplForID(const nsID& aID);
110 
111   bool
HasManager()112   HasManager() const
113   {
114     return mBackgroundManager || mContentManager;
115   }
116 
117   PBackgroundParent*
GetBackgroundManager()118   GetBackgroundManager() const
119   {
120     return mBackgroundManager;
121   }
122 
123   nsIContentParent*
GetContentManager()124   GetContentManager() const
125   {
126     return mContentManager;
127   }
128 
129   // Get the BlobImpl associated with this actor.
130   already_AddRefed<BlobImpl>
131   GetBlobImpl();
132 
133   void
134   AssertIsOnOwningThread() const
135 #ifdef DEBUG
136   ;
137 #else
138   { }
139 #endif
140 
141 private:
142   // These constructors are called on the sending side.
143   BlobParent(nsIContentParent* aManager, IDTableEntry* aIDTableEntry);
144 
145   BlobParent(PBackgroundParent* aManager, IDTableEntry* aIDTableEntry);
146 
147   // These constructors are called on the receiving side.
148   BlobParent(nsIContentParent* aManager,
149              BlobImpl* aBlobImpl,
150              IDTableEntry* aIDTableEntry);
151 
152   BlobParent(PBackgroundParent* aManager,
153              BlobImpl* aBlobImpl,
154              IDTableEntry* aIDTableEntry);
155 
156   // Only destroyed by BackgroundParentImpl and ContentParent.
157   ~BlobParent();
158 
159   void
160   CommonInit(IDTableEntry* aIDTableEntry);
161 
162   void
163   CommonInit(BlobImpl* aBlobImpl, IDTableEntry* aIDTableEntry);
164 
165   template <class ParentManagerType>
166   static BlobParent*
167   GetOrCreateFromImpl(ParentManagerType* aManager,
168                       BlobImpl* aBlobImpl);
169 
170   template <class ParentManagerType>
171   static BlobParent*
172   CreateFromParams(ParentManagerType* aManager,
173                    const ParentBlobConstructorParams& aParams);
174 
175   template <class ParentManagerType>
176   static BlobParent*
177   SendSliceConstructor(ParentManagerType* aManager,
178                        const ParentBlobConstructorParams& aParams,
179                        const ChildBlobConstructorParams& aOtherSideParams);
180 
181   static BlobParent*
182   MaybeGetActorFromRemoteBlob(nsIRemoteBlob* aRemoteBlob,
183                               nsIContentParent* aManager);
184 
185   static BlobParent*
186   MaybeGetActorFromRemoteBlob(nsIRemoteBlob* aRemoteBlob,
187                               PBackgroundParent* aManager);
188 
189   void
190   NoteDyingRemoteBlobImpl();
191 
192   void
193   NoteRunnableCompleted(OpenStreamRunnable* aRunnable);
194 
195   nsIEventTarget*
EventTarget()196   EventTarget() const
197   {
198     return mEventTarget;
199   }
200 
201   bool
202   IsOnOwningThread() const;
203 
204   // These methods are only called by the IPDL message machinery.
205   virtual void
206   ActorDestroy(ActorDestroyReason aWhy) override;
207 
208   virtual PBlobStreamParent*
209   AllocPBlobStreamParent(const uint64_t& aStart,
210                          const uint64_t& aLength) override;
211 
212   virtual bool
213   RecvPBlobStreamConstructor(PBlobStreamParent* aActor,
214                              const uint64_t& aStart,
215                              const uint64_t& aLength) override;
216 
217   virtual bool
218   DeallocPBlobStreamParent(PBlobStreamParent* aActor) override;
219 
220   virtual bool
221   RecvResolveMystery(const ResolveMysteryParams& aParams) override;
222 
223   virtual bool
224   RecvBlobStreamSync(const uint64_t& aStart,
225                      const uint64_t& aLength,
226                      InputStreamParams* aParams,
227                      OptionalFileDescriptorSet* aFDs) override;
228 
229   virtual bool
230   RecvWaitForSliceCreation() override;
231 
232   virtual bool
233   RecvGetFileId(int64_t* aFileId) override;
234 
235   virtual bool
236   RecvGetFilePath(nsString* aFilePath) override;
237 };
238 
239 // Only let ContentParent call BlobParent::Startup() and ensure that
240 // ContentParent can't access any other BlobParent internals.
241 class BlobParent::FriendKey final
242 {
243   friend class ContentParent;
244 
245 private:
FriendKey()246   FriendKey()
247   { }
248 
FriendKey(const FriendKey &)249   FriendKey(const FriendKey& /* aOther */)
250   { }
251 
252 public:
~FriendKey()253   ~FriendKey()
254   { }
255 };
256 
257 } // namespace dom
258 } // namespace mozilla
259 
260 #endif // mozilla_dom_ipc_BlobParent_h
261