diff options
Diffstat (limited to 'dom/fetch/Fetch.h')
-rw-r--r-- | dom/fetch/Fetch.h | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/dom/fetch/Fetch.h b/dom/fetch/Fetch.h new file mode 100644 index 0000000000..fc50d3fda0 --- /dev/null +++ b/dom/fetch/Fetch.h @@ -0,0 +1,205 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_Fetch_h +#define mozilla_dom_Fetch_h + +#include "nsAutoPtr.h" +#include "nsIStreamLoader.h" + +#include "nsCOMPtr.h" +#include "nsError.h" +#include "nsProxyRelease.h" +#include "nsString.h" + +#include "mozilla/DebugOnly.h" +#include "mozilla/ErrorResult.h" +#include "mozilla/dom/Promise.h" +#include "mozilla/dom/RequestBinding.h" + +class nsIGlobalObject; + +namespace mozilla { +namespace dom { + +class ArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams; +class BlobImpl; +class InternalRequest; +class OwningArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams; +class RequestOrUSVString; + +namespace workers { +class WorkerPrivate; +} // namespace workers + +already_AddRefed<Promise> +FetchRequest(nsIGlobalObject* aGlobal, const RequestOrUSVString& aInput, + const RequestInit& aInit, ErrorResult& aRv); + +nsresult +UpdateRequestReferrer(nsIGlobalObject* aGlobal, InternalRequest* aRequest); + +/* + * Creates an nsIInputStream based on the fetch specifications 'extract a byte + * stream algorithm' - http://fetch.spec.whatwg.org/#concept-bodyinit-extract. + * Stores content type in out param aContentType. + */ +nsresult +ExtractByteStreamFromBody(const OwningArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams& aBodyInit, + nsIInputStream** aStream, + nsCString& aContentType, + uint64_t& aContentLength); + +/* + * Non-owning version. + */ +nsresult +ExtractByteStreamFromBody(const ArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams& aBodyInit, + nsIInputStream** aStream, + nsCString& aContentType, + uint64_t& aContentLength); + +template <class Derived> class FetchBodyConsumer; + +enum FetchConsumeType +{ + CONSUME_ARRAYBUFFER, + CONSUME_BLOB, + CONSUME_FORMDATA, + CONSUME_JSON, + CONSUME_TEXT, +}; + +/* + * FetchBody's body consumption uses nsIInputStreamPump to read from the + * underlying stream to a block of memory, which is then adopted by + * ContinueConsumeBody() and converted to the right type based on the JS + * function called. + * + * Use of the nsIInputStreamPump complicates things on the worker thread. + * The solution used here is similar to WebSockets. + * The difference is that we are only interested in completion and not data + * events, and nsIInputStreamPump can only deliver completion on the main thread. + * + * Before starting the pump on the main thread, we addref the FetchBody to keep + * it alive. Then we add a feature, to track the status of the worker. + * + * ContinueConsumeBody() is the function that cleans things up in both success + * and error conditions and so all callers call it with the appropriate status. + * + * Once the read is initiated on the main thread there are two possibilities. + * + * 1) Pump finishes before worker has finished Running. + * In this case we adopt the data and dispatch a runnable to the worker, + * which derefs FetchBody and removes the feature and resolves the Promise. + * + * 2) Pump still working while worker has stopped Running. + * The feature is Notify()ed and ContinueConsumeBody() is called with + * NS_BINDING_ABORTED. We first Cancel() the pump using a sync runnable to + * ensure that mFetchBody remains alive (since mConsumeBodyPump is strongly + * held by it) until pump->Cancel() is called. OnStreamComplete() will not + * do anything if the error code is NS_BINDING_ABORTED, so we don't have to + * worry about keeping anything alive. + * + * The pump is always released on the main thread. + */ +template <class Derived> +class FetchBody +{ +public: + friend class FetchBodyConsumer<Derived>; + + NS_IMETHOD_(MozExternalRefCountType) AddRef(void) = 0; + NS_IMETHOD_(MozExternalRefCountType) Release(void) = 0; + + bool + BodyUsed() const { return mBodyUsed; } + + already_AddRefed<Promise> + ArrayBuffer(ErrorResult& aRv) + { + return ConsumeBody(CONSUME_ARRAYBUFFER, aRv); + } + + already_AddRefed<Promise> + Blob(ErrorResult& aRv) + { + return ConsumeBody(CONSUME_BLOB, aRv); + } + + already_AddRefed<Promise> + FormData(ErrorResult& aRv) + { + return ConsumeBody(CONSUME_FORMDATA, aRv); + } + + already_AddRefed<Promise> + Json(ErrorResult& aRv) + { + return ConsumeBody(CONSUME_JSON, aRv); + } + + already_AddRefed<Promise> + Text(ErrorResult& aRv) + { + return ConsumeBody(CONSUME_TEXT, aRv); + } + + // Utility public methods accessed by various runnables. + + void + SetBodyUsed() + { + mBodyUsed = true; + } + + const nsCString& + MimeType() const + { + return mMimeType; + } + +protected: + FetchBody(); + + // Always set whenever the FetchBody is created on the worker thread. + workers::WorkerPrivate* mWorkerPrivate; + + virtual ~FetchBody(); + + void + SetMimeType(); +private: + Derived* + DerivedClass() const + { + return static_cast<Derived*>(const_cast<FetchBody*>(this)); + } + + already_AddRefed<Promise> + ConsumeBody(FetchConsumeType aType, ErrorResult& aRv); + + bool + IsOnTargetThread() + { + return NS_IsMainThread() == !mWorkerPrivate; + } + + void + AssertIsOnTargetThread() + { + MOZ_ASSERT(IsOnTargetThread()); + } + + // Only ever set once, always on target thread. + bool mBodyUsed; + nsCString mMimeType; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_Fetch_h |