Fetch.cpp 27 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006
  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. #include "Fetch.h"
  6. #include "FetchConsumer.h"
  7. #include "nsIDocument.h"
  8. #include "nsIGlobalObject.h"
  9. #include "nsIStreamLoader.h"
  10. #include "nsIThreadRetargetableRequest.h"
  11. #include "nsIUnicodeDecoder.h"
  12. #include "nsIUnicodeEncoder.h"
  13. #include "nsCharSeparatedTokenizer.h"
  14. #include "nsDOMString.h"
  15. #include "nsNetUtil.h"
  16. #include "nsReadableUtils.h"
  17. #include "nsStreamUtils.h"
  18. #include "nsStringStream.h"
  19. #include "nsProxyRelease.h"
  20. #include "mozilla/ErrorResult.h"
  21. #include "mozilla/dom/BodyUtil.h"
  22. #include "mozilla/dom/EncodingUtils.h"
  23. #include "mozilla/dom/Exceptions.h"
  24. #include "mozilla/dom/FetchDriver.h"
  25. #include "mozilla/dom/File.h"
  26. #include "mozilla/dom/FormData.h"
  27. #include "mozilla/dom/Headers.h"
  28. #include "mozilla/dom/MutableBlobStreamListener.h"
  29. #include "mozilla/dom/Promise.h"
  30. #include "mozilla/dom/PromiseWorkerProxy.h"
  31. #include "mozilla/dom/Request.h"
  32. #include "mozilla/dom/Response.h"
  33. #include "mozilla/dom/ScriptSettings.h"
  34. #include "mozilla/dom/URLSearchParams.h"
  35. #include "mozilla/dom/workers/ServiceWorkerManager.h"
  36. #include "FetchObserver.h"
  37. #include "InternalRequest.h"
  38. #include "InternalResponse.h"
  39. #include "WorkerPrivate.h"
  40. #include "WorkerRunnable.h"
  41. #include "WorkerScope.h"
  42. #include "Workers.h"
  43. namespace mozilla {
  44. namespace dom {
  45. using namespace workers;
  46. // This class helps the proxying of AbortSignal changes cross threads.
  47. class AbortSignalProxy final : public AbortSignal::Follower
  48. {
  49. // This is created and released on the main-thread.
  50. RefPtr<AbortSignal> mSignalMainThread;
  51. // This value is used only for the creation of AbortSignal on the
  52. // main-thread. They are not updated.
  53. const bool mAborted;
  54. // This runnable propagates changes from the AbortSignal on workers to the
  55. // AbortSignal on main-thread.
  56. class AbortSignalProxyRunnable final : public Runnable
  57. {
  58. RefPtr<AbortSignalProxy> mProxy;
  59. public:
  60. explicit AbortSignalProxyRunnable(AbortSignalProxy* aProxy)
  61. : mProxy(aProxy)
  62. {}
  63. NS_IMETHOD
  64. Run() override
  65. {
  66. MOZ_ASSERT(NS_IsMainThread());
  67. AbortSignal* signal = mProxy->GetOrCreateSignalForMainThread();
  68. signal->Abort();
  69. return NS_OK;
  70. }
  71. };
  72. public:
  73. NS_INLINE_DECL_THREADSAFE_REFCOUNTING(AbortSignalProxy)
  74. explicit AbortSignalProxy(AbortSignal* aSignal)
  75. : mAborted(aSignal->Aborted())
  76. {
  77. Follow(aSignal);
  78. }
  79. void
  80. Aborted() override
  81. {
  82. RefPtr<AbortSignalProxyRunnable> runnable =
  83. new AbortSignalProxyRunnable(this);
  84. NS_DispatchToMainThread(runnable);
  85. }
  86. AbortSignal*
  87. GetOrCreateSignalForMainThread()
  88. {
  89. MOZ_ASSERT(NS_IsMainThread());
  90. if (!mSignalMainThread) {
  91. mSignalMainThread = new AbortSignal(mAborted);
  92. }
  93. return mSignalMainThread;
  94. }
  95. AbortSignal*
  96. GetSignalForTargetThread()
  97. {
  98. return mFollowingSignal;
  99. }
  100. void
  101. Shutdown()
  102. {
  103. Unfollow();
  104. }
  105. private:
  106. ~AbortSignalProxy()
  107. {
  108. NS_ReleaseOnMainThread(mSignalMainThread.forget());
  109. }
  110. };
  111. class WorkerFetchResolver final : public FetchDriverObserver
  112. {
  113. friend class MainThreadFetchRunnable;
  114. friend class WorkerDataAvailableRunnable;
  115. friend class WorkerFetchResponseEndBase;
  116. friend class WorkerFetchResponseEndRunnable;
  117. friend class WorkerFetchResponseRunnable;
  118. RefPtr<PromiseWorkerProxy> mPromiseProxy;
  119. RefPtr<AbortSignalProxy> mSignalProxy;
  120. RefPtr<FetchObserver> mFetchObserver;
  121. public:
  122. // Returns null if worker is shutting down.
  123. static already_AddRefed<WorkerFetchResolver>
  124. Create(workers::WorkerPrivate* aWorkerPrivate, Promise* aPromise,
  125. AbortSignal* aSignal, FetchObserver* aObserver)
  126. {
  127. MOZ_ASSERT(aWorkerPrivate);
  128. aWorkerPrivate->AssertIsOnWorkerThread();
  129. RefPtr<PromiseWorkerProxy> proxy =
  130. PromiseWorkerProxy::Create(aWorkerPrivate, aPromise);
  131. if (!proxy) {
  132. return nullptr;
  133. }
  134. RefPtr<AbortSignalProxy> signalProxy;
  135. if (aSignal) {
  136. signalProxy = new AbortSignalProxy(aSignal);
  137. }
  138. RefPtr<WorkerFetchResolver> r =
  139. new WorkerFetchResolver(proxy, signalProxy, aObserver);
  140. return r.forget();
  141. }
  142. AbortSignal*
  143. GetAbortSignalForMainThread()
  144. {
  145. MOZ_ASSERT(NS_IsMainThread());
  146. if (!mSignalProxy) {
  147. return nullptr;
  148. }
  149. return mSignalProxy->GetOrCreateSignalForMainThread();
  150. }
  151. AbortSignal*
  152. GetAbortSignalForTargetThread()
  153. {
  154. mPromiseProxy->GetWorkerPrivate()->AssertIsOnWorkerThread();
  155. if (!mSignalProxy) {
  156. return nullptr;
  157. }
  158. return mSignalProxy->GetSignalForTargetThread();
  159. }
  160. void
  161. OnResponseAvailableInternal(InternalResponse* aResponse) override;
  162. void
  163. OnResponseEnd(FetchDriverObserver::EndReason eReason) override;
  164. void
  165. OnDataAvailable() override;
  166. private:
  167. WorkerFetchResolver(PromiseWorkerProxy* aProxy,
  168. AbortSignalProxy* aSignalProxy,
  169. FetchObserver* aObserver)
  170. : mPromiseProxy(aProxy)
  171. , mSignalProxy(aSignalProxy)
  172. , mFetchObserver(aObserver)
  173. {
  174. MOZ_ASSERT(!NS_IsMainThread());
  175. MOZ_ASSERT(mPromiseProxy);
  176. }
  177. ~WorkerFetchResolver()
  178. {}
  179. virtual void
  180. FlushConsoleReport() override;
  181. };
  182. class MainThreadFetchResolver final : public FetchDriverObserver
  183. {
  184. RefPtr<Promise> mPromise;
  185. RefPtr<Response> mResponse;
  186. RefPtr<FetchObserver> mFetchObserver;
  187. RefPtr<AbortSignal> mSignal;
  188. nsCOMPtr<nsIDocument> mDocument;
  189. NS_DECL_OWNINGTHREAD
  190. public:
  191. MainThreadFetchResolver(Promise* aPromise, FetchObserver* aObserver, AbortSignal* aSignal)
  192. : mPromise(aPromise)
  193. , mFetchObserver(aObserver)
  194. , mSignal(aSignal)
  195. {}
  196. void
  197. OnResponseAvailableInternal(InternalResponse* aResponse) override;
  198. void SetDocument(nsIDocument* aDocument)
  199. {
  200. mDocument = aDocument;
  201. }
  202. void OnResponseEnd(FetchDriverObserver::EndReason aReason) override
  203. {
  204. if (aReason == eAborted) {
  205. mPromise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
  206. }
  207. mFetchObserver = nullptr;
  208. FlushConsoleReport();
  209. }
  210. void
  211. OnDataAvailable() override;
  212. private:
  213. ~MainThreadFetchResolver();
  214. void FlushConsoleReport() override
  215. {
  216. mReporter->FlushConsoleReports(mDocument);
  217. }
  218. };
  219. class MainThreadFetchRunnable : public Runnable
  220. {
  221. RefPtr<WorkerFetchResolver> mResolver;
  222. RefPtr<InternalRequest> mRequest;
  223. public:
  224. MainThreadFetchRunnable(WorkerFetchResolver* aResolver,
  225. InternalRequest* aRequest)
  226. : mResolver(aResolver)
  227. , mRequest(aRequest)
  228. {
  229. MOZ_ASSERT(mResolver);
  230. }
  231. NS_IMETHOD
  232. Run() override
  233. {
  234. AssertIsOnMainThread();
  235. RefPtr<FetchDriver> fetch;
  236. RefPtr<PromiseWorkerProxy> proxy = mResolver->mPromiseProxy;
  237. {
  238. // Acquire the proxy mutex while getting data from the WorkerPrivate...
  239. MutexAutoLock lock(proxy->Lock());
  240. if (proxy->CleanedUp()) {
  241. NS_WARNING("Aborting Fetch because worker already shut down");
  242. return NS_OK;
  243. }
  244. nsCOMPtr<nsIPrincipal> principal = proxy->GetWorkerPrivate()->GetPrincipal();
  245. MOZ_ASSERT(principal);
  246. nsCOMPtr<nsILoadGroup> loadGroup = proxy->GetWorkerPrivate()->GetLoadGroup();
  247. MOZ_ASSERT(loadGroup);
  248. fetch = new FetchDriver(mRequest, principal, loadGroup);
  249. nsAutoCString spec;
  250. if (proxy->GetWorkerPrivate()->GetBaseURI()) {
  251. proxy->GetWorkerPrivate()->GetBaseURI()->GetAsciiSpec(spec);
  252. }
  253. fetch->SetWorkerScript(spec);
  254. }
  255. RefPtr<AbortSignal> signal = mResolver->GetAbortSignalForMainThread();
  256. // ...but release it before calling Fetch, because mResolver's callback can
  257. // be called synchronously and they want the mutex, too.
  258. return fetch->Fetch(signal, mResolver);
  259. }
  260. };
  261. already_AddRefed<Promise>
  262. FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput,
  263. const RequestInit& aInit, ErrorResult& aRv)
  264. {
  265. RefPtr<Promise> p = Promise::Create(aGlobal, aRv);
  266. if (NS_WARN_IF(aRv.Failed())) {
  267. return nullptr;
  268. }
  269. // Double check that we have chrome privileges if the Request's content
  270. // policy type has been overridden. Note, we must do this before
  271. // entering the global below. Otherwise the IsCallerChrome() will
  272. // always fail.
  273. MOZ_ASSERT_IF(aInput.IsRequest() &&
  274. aInput.GetAsRequest().IsContentPolicyTypeOverridden(),
  275. nsContentUtils::IsCallerChrome());
  276. AutoJSAPI jsapi;
  277. if (!jsapi.Init(aGlobal)) {
  278. aRv.Throw(NS_ERROR_NOT_AVAILABLE);
  279. return nullptr;
  280. }
  281. JSContext* cx = jsapi.cx();
  282. JS::Rooted<JSObject*> jsGlobal(cx, aGlobal->GetGlobalJSObject());
  283. GlobalObject global(cx, jsGlobal);
  284. RefPtr<Request> request = Request::Constructor(global, aInput, aInit, aRv);
  285. if (NS_WARN_IF(aRv.Failed())) {
  286. return nullptr;
  287. }
  288. RefPtr<InternalRequest> r = request->GetInternalRequest();
  289. RefPtr<AbortSignal> signal = request->GetSignal();
  290. if (signal && signal->Aborted()) {
  291. // An already aborted signal should reject immediately.
  292. aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
  293. return nullptr;
  294. }
  295. RefPtr<FetchObserver> observer;
  296. if (aInit.mObserve.WasPassed()) {
  297. observer = new FetchObserver(aGlobal, signal);
  298. aInit.mObserve.Value().HandleEvent(*observer);
  299. }
  300. if (NS_IsMainThread()) {
  301. nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal);
  302. nsCOMPtr<nsIDocument> doc;
  303. nsCOMPtr<nsILoadGroup> loadGroup;
  304. nsIPrincipal* principal;
  305. if (window) {
  306. doc = window->GetExtantDoc();
  307. if (!doc) {
  308. aRv.Throw(NS_ERROR_FAILURE);
  309. return nullptr;
  310. }
  311. principal = doc->NodePrincipal();
  312. loadGroup = doc->GetDocumentLoadGroup();
  313. } else {
  314. principal = aGlobal->PrincipalOrNull();
  315. if (NS_WARN_IF(!principal)) {
  316. aRv.Throw(NS_ERROR_FAILURE);
  317. return nullptr;
  318. }
  319. nsresult rv = NS_NewLoadGroup(getter_AddRefs(loadGroup), principal);
  320. if (NS_WARN_IF(NS_FAILED(rv))) {
  321. aRv.Throw(rv);
  322. return nullptr;
  323. }
  324. }
  325. RefPtr<MainThreadFetchResolver> resolver =
  326. new MainThreadFetchResolver(p, observer, signal);
  327. RefPtr<FetchDriver> fetch = new FetchDriver(r, principal, loadGroup);
  328. fetch->SetDocument(doc);
  329. resolver->SetDocument(doc);
  330. aRv = fetch->Fetch(signal, resolver);
  331. if (NS_WARN_IF(aRv.Failed())) {
  332. return nullptr;
  333. }
  334. } else {
  335. WorkerPrivate* worker = GetCurrentThreadWorkerPrivate();
  336. MOZ_ASSERT(worker);
  337. if (worker->IsServiceWorker()) {
  338. r->SetSkipServiceWorker();
  339. }
  340. RefPtr<WorkerFetchResolver> resolver =
  341. WorkerFetchResolver::Create(worker, p, signal, observer);
  342. if (!resolver) {
  343. NS_WARNING("Could not add WorkerFetchResolver workerHolder to worker");
  344. aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
  345. return nullptr;
  346. }
  347. RefPtr<MainThreadFetchRunnable> run = new MainThreadFetchRunnable(resolver, r);
  348. MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(run));
  349. }
  350. return p.forget();
  351. }
  352. void
  353. MainThreadFetchResolver::OnResponseAvailableInternal(InternalResponse* aResponse)
  354. {
  355. NS_ASSERT_OWNINGTHREAD(MainThreadFetchResolver);
  356. AssertIsOnMainThread();
  357. if (aResponse->Type() != ResponseType::Error) {
  358. if (mFetchObserver) {
  359. mFetchObserver->SetState(FetchState::Complete);
  360. }
  361. nsCOMPtr<nsIGlobalObject> go = mPromise->GetParentObject();
  362. mResponse = new Response(go, aResponse, mSignal);
  363. mPromise->MaybeResolve(mResponse);
  364. } else {
  365. if (mFetchObserver) {
  366. mFetchObserver->SetState(FetchState::Errored);
  367. }
  368. ErrorResult result;
  369. result.ThrowTypeError<MSG_FETCH_FAILED>();
  370. mPromise->MaybeReject(result);
  371. }
  372. }
  373. void
  374. MainThreadFetchResolver::OnDataAvailable()
  375. {
  376. NS_ASSERT_OWNINGTHREAD(MainThreadFetchResolver);
  377. AssertIsOnMainThread();
  378. if (!mFetchObserver) {
  379. return;
  380. }
  381. if (mFetchObserver->State() == FetchState::Requesting) {
  382. mFetchObserver->SetState(FetchState::Responding);
  383. }
  384. }
  385. MainThreadFetchResolver::~MainThreadFetchResolver()
  386. {
  387. NS_ASSERT_OWNINGTHREAD(MainThreadFetchResolver);
  388. }
  389. class WorkerFetchResponseRunnable final : public MainThreadWorkerRunnable
  390. {
  391. RefPtr<WorkerFetchResolver> mResolver;
  392. // Passed from main thread to worker thread after being initialized.
  393. RefPtr<InternalResponse> mInternalResponse;
  394. public:
  395. WorkerFetchResponseRunnable(WorkerPrivate* aWorkerPrivate,
  396. WorkerFetchResolver* aResolver,
  397. InternalResponse* aResponse)
  398. : MainThreadWorkerRunnable(aWorkerPrivate)
  399. , mResolver(aResolver)
  400. , mInternalResponse(aResponse)
  401. {
  402. MOZ_ASSERT(mResolver);
  403. }
  404. bool
  405. WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
  406. {
  407. MOZ_ASSERT(aWorkerPrivate);
  408. aWorkerPrivate->AssertIsOnWorkerThread();
  409. RefPtr<Promise> promise = mResolver->mPromiseProxy->WorkerPromise();
  410. if (mInternalResponse->Type() != ResponseType::Error) {
  411. if (mResolver->mFetchObserver) {
  412. mResolver->mFetchObserver->SetState(FetchState::Complete);
  413. }
  414. RefPtr<nsIGlobalObject> global = aWorkerPrivate->GlobalScope();
  415. RefPtr<Response> response = new Response(global, mInternalResponse, mResolver->GetAbortSignalForTargetThread());
  416. promise->MaybeResolve(response);
  417. } else {
  418. if (mResolver->mFetchObserver) {
  419. mResolver->mFetchObserver->SetState(FetchState::Errored);
  420. }
  421. ErrorResult result;
  422. result.ThrowTypeError<MSG_FETCH_FAILED>();
  423. promise->MaybeReject(result);
  424. }
  425. return true;
  426. }
  427. };
  428. class WorkerDataAvailableRunnable final : public MainThreadWorkerRunnable
  429. {
  430. RefPtr<WorkerFetchResolver> mResolver;
  431. public:
  432. WorkerDataAvailableRunnable(WorkerPrivate* aWorkerPrivate,
  433. WorkerFetchResolver* aResolver)
  434. : MainThreadWorkerRunnable(aWorkerPrivate)
  435. , mResolver(aResolver)
  436. {
  437. }
  438. bool
  439. WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
  440. {
  441. MOZ_ASSERT(aWorkerPrivate);
  442. aWorkerPrivate->AssertIsOnWorkerThread();
  443. if (mResolver->mFetchObserver &&
  444. mResolver->mFetchObserver->State() == FetchState::Requesting) {
  445. mResolver->mFetchObserver->SetState(FetchState::Responding);
  446. }
  447. return true;
  448. }
  449. };
  450. class WorkerFetchResponseEndBase
  451. {
  452. protected:
  453. RefPtr<WorkerFetchResolver> mResolver;
  454. public:
  455. explicit WorkerFetchResponseEndBase(WorkerFetchResolver* aResolver)
  456. : mResolver(aResolver)
  457. {
  458. MOZ_ASSERT(aResolver);
  459. }
  460. void
  461. WorkerRunInternal(WorkerPrivate* aWorkerPrivate)
  462. {
  463. MOZ_ASSERT(aWorkerPrivate);
  464. aWorkerPrivate->AssertIsOnWorkerThread();
  465. mResolver->mPromiseProxy->CleanUp();
  466. mResolver->mFetchObserver = nullptr;
  467. if (mResolver->mSignalProxy) {
  468. mResolver->mSignalProxy->Shutdown();
  469. mResolver->mSignalProxy = nullptr;
  470. }
  471. }
  472. };
  473. class WorkerFetchResponseEndRunnable final : public MainThreadWorkerRunnable
  474. , public WorkerFetchResponseEndBase
  475. {
  476. FetchDriverObserver::EndReason mReason;
  477. public:
  478. WorkerFetchResponseEndRunnable(WorkerPrivate* aWorkerPrivate,
  479. WorkerFetchResolver* aResolver,
  480. FetchDriverObserver::EndReason aReason)
  481. : MainThreadWorkerRunnable(aWorkerPrivate)
  482. , WorkerFetchResponseEndBase(aResolver)
  483. , mReason(aReason)
  484. {
  485. }
  486. bool
  487. WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
  488. {
  489. if (mReason == FetchDriverObserver::eAborted) {
  490. RefPtr<Promise> promise = mResolver->mPromiseProxy->WorkerPromise();
  491. promise->MaybeReject(NS_ERROR_DOM_ABORT_ERR);
  492. }
  493. WorkerRunInternal(aWorkerPrivate);
  494. return true;
  495. }
  496. nsresult
  497. Cancel() override
  498. {
  499. // Execute Run anyway to make sure we cleanup our promise proxy to avoid
  500. // leaking the worker thread
  501. Run();
  502. return WorkerRunnable::Cancel();
  503. }
  504. };
  505. class WorkerFetchResponseEndControlRunnable final : public MainThreadWorkerControlRunnable
  506. , public WorkerFetchResponseEndBase
  507. {
  508. public:
  509. WorkerFetchResponseEndControlRunnable(WorkerPrivate* aWorkerPrivate,
  510. WorkerFetchResolver* aResolver)
  511. : MainThreadWorkerControlRunnable(aWorkerPrivate)
  512. , WorkerFetchResponseEndBase(aResolver)
  513. {
  514. }
  515. bool
  516. WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
  517. {
  518. WorkerRunInternal(aWorkerPrivate);
  519. return true;
  520. }
  521. // Control runnable cancel already calls Run().
  522. };
  523. void
  524. WorkerFetchResolver::OnResponseAvailableInternal(InternalResponse* aResponse)
  525. {
  526. AssertIsOnMainThread();
  527. MutexAutoLock lock(mPromiseProxy->Lock());
  528. if (mPromiseProxy->CleanedUp()) {
  529. return;
  530. }
  531. RefPtr<WorkerFetchResponseRunnable> r =
  532. new WorkerFetchResponseRunnable(mPromiseProxy->GetWorkerPrivate(), this,
  533. aResponse);
  534. if (!r->Dispatch()) {
  535. NS_WARNING("Could not dispatch fetch response");
  536. }
  537. }
  538. void
  539. WorkerFetchResolver::OnDataAvailable()
  540. {
  541. AssertIsOnMainThread();
  542. MutexAutoLock lock(mPromiseProxy->Lock());
  543. if (mPromiseProxy->CleanedUp()) {
  544. return;
  545. }
  546. RefPtr<WorkerDataAvailableRunnable> r =
  547. new WorkerDataAvailableRunnable(mPromiseProxy->GetWorkerPrivate(), this);
  548. Unused << r->Dispatch();
  549. }
  550. void
  551. WorkerFetchResolver::OnResponseEnd(FetchDriverObserver::EndReason aReason)
  552. {
  553. AssertIsOnMainThread();
  554. MutexAutoLock lock(mPromiseProxy->Lock());
  555. if (mPromiseProxy->CleanedUp()) {
  556. return;
  557. }
  558. FlushConsoleReport();
  559. RefPtr<WorkerFetchResponseEndRunnable> r =
  560. new WorkerFetchResponseEndRunnable(mPromiseProxy->GetWorkerPrivate(),
  561. this, aReason);
  562. if (!r->Dispatch()) {
  563. RefPtr<WorkerFetchResponseEndControlRunnable> cr =
  564. new WorkerFetchResponseEndControlRunnable(mPromiseProxy->GetWorkerPrivate(),
  565. this);
  566. // This can fail if the worker thread is canceled or killed causing
  567. // the PromiseWorkerProxy to give up its WorkerHolder immediately,
  568. // allowing the worker thread to become Dead.
  569. if (!cr->Dispatch()) {
  570. NS_WARNING("Failed to dispatch WorkerFetchResponseEndControlRunnable");
  571. }
  572. }
  573. }
  574. void
  575. WorkerFetchResolver::FlushConsoleReport()
  576. {
  577. AssertIsOnMainThread();
  578. MOZ_ASSERT(mPromiseProxy);
  579. if(!mReporter) {
  580. return;
  581. }
  582. workers::WorkerPrivate* worker = mPromiseProxy->GetWorkerPrivate();
  583. if (!worker) {
  584. mReporter->FlushConsoleReports((nsIDocument*)nullptr);
  585. return;
  586. }
  587. if (worker->IsServiceWorker()) {
  588. // Flush to service worker
  589. RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
  590. if (!swm) {
  591. mReporter->FlushConsoleReports((nsIDocument*)nullptr);
  592. return;
  593. }
  594. swm->FlushReportsToAllClients(worker->WorkerName(), mReporter);
  595. return;
  596. }
  597. if (worker->IsSharedWorker()) {
  598. // Flush to shared worker
  599. worker->FlushReportsToSharedWorkers(mReporter);
  600. return;
  601. }
  602. // Flush to dedicated worker
  603. mReporter->FlushConsoleReports(worker->GetDocument());
  604. }
  605. namespace {
  606. nsresult
  607. ExtractFromArrayBuffer(const ArrayBuffer& aBuffer,
  608. nsIInputStream** aStream,
  609. uint64_t& aContentLength)
  610. {
  611. aBuffer.ComputeLengthAndData();
  612. aContentLength = aBuffer.Length();
  613. //XXXnsm reinterpret_cast<> is used in DOMParser, should be ok.
  614. return NS_NewByteInputStream(aStream,
  615. reinterpret_cast<char*>(aBuffer.Data()),
  616. aBuffer.Length(), NS_ASSIGNMENT_COPY);
  617. }
  618. nsresult
  619. ExtractFromArrayBufferView(const ArrayBufferView& aBuffer,
  620. nsIInputStream** aStream,
  621. uint64_t& aContentLength)
  622. {
  623. aBuffer.ComputeLengthAndData();
  624. aContentLength = aBuffer.Length();
  625. //XXXnsm reinterpret_cast<> is used in DOMParser, should be ok.
  626. return NS_NewByteInputStream(aStream,
  627. reinterpret_cast<char*>(aBuffer.Data()),
  628. aBuffer.Length(), NS_ASSIGNMENT_COPY);
  629. }
  630. nsresult
  631. ExtractFromBlob(const Blob& aBlob,
  632. nsIInputStream** aStream,
  633. nsCString& aContentType,
  634. uint64_t& aContentLength)
  635. {
  636. RefPtr<BlobImpl> impl = aBlob.Impl();
  637. ErrorResult rv;
  638. aContentLength = impl->GetSize(rv);
  639. if (NS_WARN_IF(rv.Failed())) {
  640. return rv.StealNSResult();
  641. }
  642. impl->GetInternalStream(aStream, rv);
  643. if (NS_WARN_IF(rv.Failed())) {
  644. return rv.StealNSResult();
  645. }
  646. nsAutoString type;
  647. impl->GetType(type);
  648. aContentType = NS_ConvertUTF16toUTF8(type);
  649. return NS_OK;
  650. }
  651. nsresult
  652. ExtractFromFormData(FormData& aFormData,
  653. nsIInputStream** aStream,
  654. nsCString& aContentType,
  655. uint64_t& aContentLength)
  656. {
  657. nsAutoCString unusedCharset;
  658. return aFormData.GetSendInfo(aStream, &aContentLength,
  659. aContentType, unusedCharset);
  660. }
  661. nsresult
  662. ExtractFromUSVString(const nsString& aStr,
  663. nsIInputStream** aStream,
  664. nsCString& aContentType,
  665. uint64_t& aContentLength)
  666. {
  667. nsCOMPtr<nsIUnicodeEncoder> encoder = EncodingUtils::EncoderForEncoding("UTF-8");
  668. if (!encoder) {
  669. return NS_ERROR_OUT_OF_MEMORY;
  670. }
  671. int32_t destBufferLen;
  672. nsresult rv = encoder->GetMaxLength(aStr.get(), aStr.Length(), &destBufferLen);
  673. if (NS_WARN_IF(NS_FAILED(rv))) {
  674. return rv;
  675. }
  676. nsCString encoded;
  677. if (!encoded.SetCapacity(destBufferLen, fallible)) {
  678. return NS_ERROR_OUT_OF_MEMORY;
  679. }
  680. char* destBuffer = encoded.BeginWriting();
  681. int32_t srcLen = (int32_t) aStr.Length();
  682. int32_t outLen = destBufferLen;
  683. rv = encoder->Convert(aStr.get(), &srcLen, destBuffer, &outLen);
  684. if (NS_WARN_IF(NS_FAILED(rv))) {
  685. return rv;
  686. }
  687. MOZ_ASSERT(outLen <= destBufferLen);
  688. encoded.SetLength(outLen);
  689. aContentType = NS_LITERAL_CSTRING("text/plain;charset=UTF-8");
  690. aContentLength = outLen;
  691. return NS_NewCStringInputStream(aStream, encoded);
  692. }
  693. nsresult
  694. ExtractFromURLSearchParams(const URLSearchParams& aParams,
  695. nsIInputStream** aStream,
  696. nsCString& aContentType,
  697. uint64_t& aContentLength)
  698. {
  699. nsAutoString serialized;
  700. aParams.Stringify(serialized);
  701. aContentType = NS_LITERAL_CSTRING("application/x-www-form-urlencoded;charset=UTF-8");
  702. aContentLength = serialized.Length();
  703. return NS_NewCStringInputStream(aStream, NS_ConvertUTF16toUTF8(serialized));
  704. }
  705. } // namespace
  706. nsresult
  707. ExtractByteStreamFromBody(const OwningArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams& aBodyInit,
  708. nsIInputStream** aStream,
  709. nsCString& aContentType,
  710. uint64_t& aContentLength)
  711. {
  712. MOZ_ASSERT(aStream);
  713. if (aBodyInit.IsArrayBuffer()) {
  714. const ArrayBuffer& buf = aBodyInit.GetAsArrayBuffer();
  715. return ExtractFromArrayBuffer(buf, aStream, aContentLength);
  716. }
  717. if (aBodyInit.IsArrayBufferView()) {
  718. const ArrayBufferView& buf = aBodyInit.GetAsArrayBufferView();
  719. return ExtractFromArrayBufferView(buf, aStream, aContentLength);
  720. }
  721. if (aBodyInit.IsBlob()) {
  722. const Blob& blob = aBodyInit.GetAsBlob();
  723. return ExtractFromBlob(blob, aStream, aContentType, aContentLength);
  724. }
  725. if (aBodyInit.IsFormData()) {
  726. FormData& form = aBodyInit.GetAsFormData();
  727. return ExtractFromFormData(form, aStream, aContentType, aContentLength);
  728. }
  729. if (aBodyInit.IsUSVString()) {
  730. nsAutoString str;
  731. str.Assign(aBodyInit.GetAsUSVString());
  732. return ExtractFromUSVString(str, aStream, aContentType, aContentLength);
  733. }
  734. if (aBodyInit.IsURLSearchParams()) {
  735. URLSearchParams& params = aBodyInit.GetAsURLSearchParams();
  736. return ExtractFromURLSearchParams(params, aStream, aContentType, aContentLength);
  737. }
  738. NS_NOTREACHED("Should never reach here");
  739. return NS_ERROR_FAILURE;
  740. }
  741. nsresult
  742. ExtractByteStreamFromBody(const ArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams& aBodyInit,
  743. nsIInputStream** aStream,
  744. nsCString& aContentType,
  745. uint64_t& aContentLength)
  746. {
  747. MOZ_ASSERT(aStream);
  748. MOZ_ASSERT(!*aStream);
  749. if (aBodyInit.IsArrayBuffer()) {
  750. const ArrayBuffer& buf = aBodyInit.GetAsArrayBuffer();
  751. return ExtractFromArrayBuffer(buf, aStream, aContentLength);
  752. }
  753. if (aBodyInit.IsArrayBufferView()) {
  754. const ArrayBufferView& buf = aBodyInit.GetAsArrayBufferView();
  755. return ExtractFromArrayBufferView(buf, aStream, aContentLength);
  756. }
  757. if (aBodyInit.IsBlob()) {
  758. const Blob& blob = aBodyInit.GetAsBlob();
  759. return ExtractFromBlob(blob, aStream, aContentType, aContentLength);
  760. }
  761. if (aBodyInit.IsFormData()) {
  762. FormData& form = aBodyInit.GetAsFormData();
  763. return ExtractFromFormData(form, aStream, aContentType, aContentLength);
  764. }
  765. if (aBodyInit.IsUSVString()) {
  766. nsAutoString str;
  767. str.Assign(aBodyInit.GetAsUSVString());
  768. return ExtractFromUSVString(str, aStream, aContentType, aContentLength);
  769. }
  770. if (aBodyInit.IsURLSearchParams()) {
  771. URLSearchParams& params = aBodyInit.GetAsURLSearchParams();
  772. return ExtractFromURLSearchParams(params, aStream, aContentType, aContentLength);
  773. }
  774. NS_NOTREACHED("Should never reach here");
  775. return NS_ERROR_FAILURE;
  776. }
  777. template <class Derived>
  778. FetchBody<Derived>::FetchBody()
  779. : mWorkerPrivate(nullptr)
  780. , mBodyUsed(false)
  781. {
  782. if (!NS_IsMainThread()) {
  783. mWorkerPrivate = GetCurrentThreadWorkerPrivate();
  784. MOZ_ASSERT(mWorkerPrivate);
  785. }
  786. }
  787. template
  788. FetchBody<Request>::FetchBody();
  789. template
  790. FetchBody<Response>::FetchBody();
  791. template <class Derived>
  792. FetchBody<Derived>::~FetchBody()
  793. {
  794. }
  795. template <class Derived>
  796. already_AddRefed<Promise>
  797. FetchBody<Derived>::ConsumeBody(FetchConsumeType aType, ErrorResult& aRv)
  798. {
  799. RefPtr<AbortSignal> signal = DerivedClass()->GetSignal();
  800. if (signal && signal->Aborted()) {
  801. aRv.Throw(NS_ERROR_DOM_ABORT_ERR);
  802. return nullptr;
  803. }
  804. if (BodyUsed()) {
  805. aRv.ThrowTypeError<MSG_FETCH_BODY_CONSUMED_ERROR>();
  806. return nullptr;
  807. }
  808. SetBodyUsed();
  809. RefPtr<Promise> promise =
  810. FetchBodyConsumer<Derived>::Create(DerivedClass()->GetParentObject(),
  811. this, signal, aType, aRv);
  812. if (NS_WARN_IF(aRv.Failed())) {
  813. return nullptr;
  814. }
  815. return promise.forget();
  816. }
  817. template
  818. already_AddRefed<Promise>
  819. FetchBody<Request>::ConsumeBody(FetchConsumeType aType, ErrorResult& aRv);
  820. template
  821. already_AddRefed<Promise>
  822. FetchBody<Response>::ConsumeBody(FetchConsumeType aType, ErrorResult& aRv);
  823. template <class Derived>
  824. void
  825. FetchBody<Derived>::SetMimeType()
  826. {
  827. // Extract mime type.
  828. ErrorResult result;
  829. nsCString contentTypeValues;
  830. MOZ_ASSERT(DerivedClass()->GetInternalHeaders());
  831. DerivedClass()->GetInternalHeaders()->Get(NS_LITERAL_CSTRING("Content-Type"),
  832. contentTypeValues, result);
  833. MOZ_ALWAYS_TRUE(!result.Failed());
  834. // HTTP ABNF states Content-Type may have only one value.
  835. // This is from the "parse a header value" of the fetch spec.
  836. if (!contentTypeValues.IsVoid() && contentTypeValues.Find(",") == -1) {
  837. mMimeType = contentTypeValues;
  838. ToLowerCase(mMimeType);
  839. }
  840. }
  841. template
  842. void
  843. FetchBody<Request>::SetMimeType();
  844. template
  845. void
  846. FetchBody<Response>::SetMimeType();
  847. } // namespace dom
  848. } // namespace mozilla