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_BodyConsumer_h
8 #define mozilla_dom_BodyConsumer_h
9 
10 #include "mozilla/dom/AbortSignal.h"
11 #include "mozilla/dom/MutableBlobStorage.h"
12 #include "nsIInputStreamPump.h"
13 #include "nsNetUtil.h"
14 #include "nsIObserver.h"
15 #include "nsWeakReference.h"
16 
17 class nsIThread;
18 
19 namespace mozilla {
20 namespace dom {
21 
22 class Promise;
23 class ThreadSafeWorkerRef;
24 
25 // In order to keep alive the object all the time, we use a ThreadSafeWorkerRef,
26 // if created on workers.
27 class BodyConsumer final : public nsIObserver,
28                            public nsSupportsWeakReference,
29                            public AbortFollower {
30  public:
31   NS_DECL_THREADSAFE_ISUPPORTS
32   NS_DECL_NSIOBSERVER
33 
34   enum ConsumeType {
35     CONSUME_ARRAYBUFFER,
36     CONSUME_BLOB,
37     CONSUME_FORMDATA,
38     CONSUME_JSON,
39     CONSUME_TEXT,
40   };
41 
42   /**
43    * Returns a promise which will be resolved when the body is completely
44    * consumed and converted to the wanted type (See ConsumeType).
45    *
46    * @param aGlobal the global to construct the Promise.
47    * @param aMainThreadEventTarget the main-thread event target. The reading
48    *          needs to start on the main-thread because of nsIInputStreamPump.
49    * @param aBodyStream the stream to read.
50    * @param aSignalImpl an AbortSignal object. Optional.
51    * @param aType the consume type.
52    * @param aBodyBlobURISpec this is used only if the consume type is
53    *          CONSUME_BLOB. Optional.
54    * @param aBodyLocalPath local path in case the blob is created from a local
55    *          file. Used only by CONSUME_BLOB. Optional.
56    * @param aBodyMimeType the mime-type for blob. Used only by CONSUME_BLOB.
57    *          Optional.
58    * @param aBlobStorageType Blobs can be saved in temporary file. This is the
59    *          type of blob storage to use. Used only by CONSUME_BLOB.
60    * @param aRv An ErrorResult.
61    */
62   static already_AddRefed<Promise> Create(
63       nsIGlobalObject* aGlobal, nsIEventTarget* aMainThreadEventTarget,
64       nsIInputStream* aBodyStream, AbortSignalImpl* aSignalImpl,
65       ConsumeType aType, const nsACString& aBodyBlobURISpec,
66       const nsAString& aBodyLocalPath, const nsACString& aBodyMimeType,
67       MutableBlobStorage::MutableBlobStorageType aBlobStorageType,
68       ErrorResult& aRv);
69 
70   void ReleaseObject();
71 
72   void BeginConsumeBodyMainThread(ThreadSafeWorkerRef* aWorkerRef);
73 
74   void OnBlobResult(BlobImpl* aBlobImpl,
75                     ThreadSafeWorkerRef* aWorkerRef = nullptr);
76 
77   void ContinueConsumeBody(nsresult aStatus, uint32_t aLength, uint8_t* aResult,
78                            bool aShuttingDown = false);
79 
80   void ContinueConsumeBlobBody(BlobImpl* aBlobImpl, bool aShuttingDown = false);
81 
82   void DispatchContinueConsumeBlobBody(BlobImpl* aBlobImpl,
83                                        ThreadSafeWorkerRef* aWorkerRef);
84 
85   void ShutDownMainThreadConsuming();
86 
NullifyConsumeBodyPump()87   void NullifyConsumeBodyPump() {
88     mShuttingDown = true;
89     mConsumeBodyPump = nullptr;
90   }
91 
92   // AbortFollower
93   void Abort() override;
94 
95  private:
96   BodyConsumer(nsIEventTarget* aMainThreadEventTarget,
97                nsIGlobalObject* aGlobalObject, nsIInputStream* aBodyStream,
98                Promise* aPromise, ConsumeType aType,
99                const nsACString& aBodyBlobURISpec,
100                const nsAString& aBodyLocalPath, const nsACString& aBodyMimeType,
101                MutableBlobStorage::MutableBlobStorageType aBlobStorageType);
102 
103   ~BodyConsumer();
104 
105   nsresult GetBodyLocalFile(nsIFile** aFile) const;
106 
107   void AssertIsOnTargetThread() const;
108 
109   nsCOMPtr<nsIThread> mTargetThread;
110   nsCOMPtr<nsIEventTarget> mMainThreadEventTarget;
111 
112   // This is nullified when the consuming of the body starts.
113   nsCOMPtr<nsIInputStream> mBodyStream;
114 
115   MutableBlobStorage::MutableBlobStorageType mBlobStorageType;
116   nsCString mBodyMimeType;
117 
118   nsCString mBodyBlobURISpec;
119   nsString mBodyLocalPath;
120 
121   nsCOMPtr<nsIGlobalObject> mGlobal;
122 
123   // Touched on the main-thread only.
124   nsCOMPtr<nsIInputStreamPump> mConsumeBodyPump;
125 
126   // Only ever set once, always on target thread.
127   ConsumeType mConsumeType;
128   RefPtr<Promise> mConsumePromise;
129 
130   // touched only on the target thread.
131   bool mBodyConsumed;
132 
133   // touched only on the main-thread.
134   bool mShuttingDown;
135 };
136 
137 }  // namespace dom
138 }  // namespace mozilla
139 
140 #endif  // mozilla_dom_BodyConsumer_h
141