Fetch.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
  2. /* This Source Code Form is subject to the terms of the Mozilla Public
  3. * License, v. 2.0. If a copy of the MPL was not distributed with this
  4. * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  5. #ifndef mozilla_dom_Fetch_h
  6. #define mozilla_dom_Fetch_h
  7. #include "nsAutoPtr.h"
  8. #include "nsIStreamLoader.h"
  9. #include "nsCOMPtr.h"
  10. #include "nsError.h"
  11. #include "nsProxyRelease.h"
  12. #include "nsString.h"
  13. #include "mozilla/DebugOnly.h"
  14. #include "mozilla/ErrorResult.h"
  15. #include "mozilla/dom/Promise.h"
  16. #include "mozilla/dom/RequestBinding.h"
  17. class nsIGlobalObject;
  18. namespace mozilla {
  19. namespace dom {
  20. class ArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams;
  21. class BlobImpl;
  22. class InternalRequest;
  23. class OwningArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams;
  24. class RequestOrUSVString;
  25. namespace workers {
  26. class WorkerPrivate;
  27. } // namespace workers
  28. already_AddRefed<Promise>
  29. FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput,
  30. const RequestInit& aInit, ErrorResult& aRv);
  31. nsresult
  32. UpdateRequestReferrer(nsIGlobalObject* aGlobal, InternalRequest* aRequest);
  33. /*
  34. * Creates an nsIInputStream based on the fetch specifications 'extract a byte
  35. * stream algorithm' - http://fetch.spec.whatwg.org/#concept-bodyinit-extract.
  36. * Stores content type in out param aContentType.
  37. */
  38. nsresult
  39. ExtractByteStreamFromBody(const OwningArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams& aBodyInit,
  40. nsIInputStream** aStream,
  41. nsCString& aContentType,
  42. uint64_t& aContentLength);
  43. /*
  44. * Non-owning version.
  45. */
  46. nsresult
  47. ExtractByteStreamFromBody(const ArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams& aBodyInit,
  48. nsIInputStream** aStream,
  49. nsCString& aContentType,
  50. uint64_t& aContentLength);
  51. template <class Derived> class FetchBodyConsumer;
  52. enum FetchConsumeType
  53. {
  54. CONSUME_ARRAYBUFFER,
  55. CONSUME_BLOB,
  56. CONSUME_FORMDATA,
  57. CONSUME_JSON,
  58. CONSUME_TEXT,
  59. };
  60. /*
  61. * FetchBody's body consumption uses nsIInputStreamPump to read from the
  62. * underlying stream to a block of memory, which is then adopted by
  63. * ContinueConsumeBody() and converted to the right type based on the JS
  64. * function called.
  65. *
  66. * Use of the nsIInputStreamPump complicates things on the worker thread.
  67. * The solution used here is similar to WebSockets.
  68. * The difference is that we are only interested in completion and not data
  69. * events, and nsIInputStreamPump can only deliver completion on the main thread.
  70. *
  71. * Before starting the pump on the main thread, we addref the FetchBody to keep
  72. * it alive. Then we add a feature, to track the status of the worker.
  73. *
  74. * ContinueConsumeBody() is the function that cleans things up in both success
  75. * and error conditions and so all callers call it with the appropriate status.
  76. *
  77. * Once the read is initiated on the main thread there are two possibilities.
  78. *
  79. * 1) Pump finishes before worker has finished Running.
  80. * In this case we adopt the data and dispatch a runnable to the worker,
  81. * which derefs FetchBody and removes the feature and resolves the Promise.
  82. *
  83. * 2) Pump still working while worker has stopped Running.
  84. * The feature is Notify()ed and ContinueConsumeBody() is called with
  85. * NS_BINDING_ABORTED. We first Cancel() the pump using a sync runnable to
  86. * ensure that mFetchBody remains alive (since mConsumeBodyPump is strongly
  87. * held by it) until pump->Cancel() is called. OnStreamComplete() will not
  88. * do anything if the error code is NS_BINDING_ABORTED, so we don't have to
  89. * worry about keeping anything alive.
  90. *
  91. * The pump is always released on the main thread.
  92. */
  93. template <class Derived>
  94. class FetchBody
  95. {
  96. public:
  97. friend class FetchBodyConsumer<Derived>;
  98. NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0;
  99. NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0;
  100. bool
  101. BodyUsed() const { return mBodyUsed; }
  102. already_AddRefed<Promise>
  103. ArrayBuffer(ErrorResult& aRv)
  104. {
  105. return ConsumeBody(CONSUME_ARRAYBUFFER, aRv);
  106. }
  107. already_AddRefed<Promise>
  108. Blob(ErrorResult& aRv)
  109. {
  110. return ConsumeBody(CONSUME_BLOB, aRv);
  111. }
  112. already_AddRefed<Promise>
  113. FormData(ErrorResult& aRv)
  114. {
  115. return ConsumeBody(CONSUME_FORMDATA, aRv);
  116. }
  117. already_AddRefed<Promise>
  118. Json(ErrorResult& aRv)
  119. {
  120. return ConsumeBody(CONSUME_JSON, aRv);
  121. }
  122. already_AddRefed<Promise>
  123. Text(ErrorResult& aRv)
  124. {
  125. return ConsumeBody(CONSUME_TEXT, aRv);
  126. }
  127. // Utility public methods accessed by various runnables.
  128. void
  129. SetBodyUsed()
  130. {
  131. mBodyUsed = true;
  132. }
  133. const nsCString&
  134. MimeType() const
  135. {
  136. return mMimeType;
  137. }
  138. virtual AbortSignal*
  139. GetSignal() const = 0;
  140. protected:
  141. FetchBody();
  142. // Always set whenever the FetchBody is created on the worker thread.
  143. workers::WorkerPrivate* mWorkerPrivate;
  144. virtual ~FetchBody();
  145. void
  146. SetMimeType();
  147. private:
  148. Derived*
  149. DerivedClass() const
  150. {
  151. return static_cast<Derived*>(const_cast<FetchBody*>(this));
  152. }
  153. already_AddRefed<Promise>
  154. ConsumeBody(FetchConsumeType aType, ErrorResult& aRv);
  155. bool
  156. IsOnTargetThread()
  157. {
  158. return NS_IsMainThread() == !mWorkerPrivate;
  159. }
  160. void
  161. AssertIsOnTargetThread()
  162. {
  163. MOZ_ASSERT(IsOnTargetThread());
  164. }
  165. // Only ever set once, always on target thread.
  166. bool mBodyUsed;
  167. nsCString mMimeType;
  168. };
  169. } // namespace dom
  170. } // namespace mozilla
  171. #endif // mozilla_dom_Fetch_h