Files
palemoon27/dom/fetch/Request.cpp
T
roytam1 52a27516d8 import changes from `dev' branch of rmottola/Arctic-Fox:
- Bug 1261720 (part 1) - Separate js::ClassExtension from js::Class. r=jorendorff,bz. (6368952442)
- Bug 1261720 (part 2) - Move ClassExtension::isWrappedNative into js::Class::flags. r=jorendorff. (554fe695c2)
- Bug 1261723 (part 1) - Rename js::Class::ops as oOps. r=efaust. (e9dace574c)
- Bug 1261723 (part 2) - Separate class ops from js::Class. code=njn,h4writer. r=efaust,bz. (54bc06aec6)
- Bug 1263865 - Check the return value of GetSelfHostedFunction in ArraySpeciesCreate. r=efaust (cc6e1c0e50)
- Bug 1248948 - Don't pass non-SavedFrame objects to SavedFrame JSAPI functions; r=tromey r=evilpie (8c753c3c89)
- Bug 1260475 - Add an option to disable GC slices triggered by painting. r=terrence a=kwierso (df86be5e34)
- Bug 1263803 - Change AllocateArrayBuffer to receive byteLength instead of nelements. r=lth (751e333ff0)
- Bug 1264941 - Use byteLength of source typedArray in CloneArrayBuffer. r=lth (0095fce3aa)
- Bug 1263879 - Check the return value of AtomizeString in str_replace_string_raw. r=h4writer (31e1470bc3)
- Bug 1258453 - Compact arenas containing strings r=terrence (f6b4029d79)
- Bug 1258095 - patch 1/3 - OSFileSystem should have the root == the directory root, r=smaug (8cf74899f4)
- Bug 1258095 - patch 2/3 - Implement Directory::GetPath() correctly, r=smaug (776f503c98)
- Bug 1258095 - patch 3/3 - Directory tasks should use FallibleArray, r=smaug (b4888c92b9)
- Bug 1258221 - patch 1 - File::CreateFromFile only for main-thread, r=smaug (c106b37cb4)
- Bug 1258056 - Propagate the window opener full page zoom across the IPC layer; r=smaug (511386589f)
- Bug 1248772 - Trigger a OS window focus in ServiceWorkerClients::OpenWindow. r=ehsan (feb322b9f0)
- Bug 1259707 - Fix confusion between desktop and CSS pixels when session-restore is constraining window to the available screen space. r=emk (def9cc918b)
- Bug 1250266 - Always send a TTL in the Push mochitests. r=benbangert (43c7bde7b8)
- Bug 1244816 - Create PushService mock for mochitests backed by a mock web socket. r=kitcambridge (92270cbae5)
- Bug 1257395: Update comments for GCHashTable and GCPolicy. DONTBUILD r=terrence (fee0311ea0)
- Bug 1263772 - Use WeakCache wrapper to sweep BaseShape table; r=jonco (a0e015667c)
- Bug 1263777 - Use WeakCache to sweep the InitialShapeTable; r=jonco (84d1591585)
- Bug 1132502 (part 1) - Abort if compartmentStats is null during memory reporting. r=jandem. (bd144192b1)
- Bug 1132502 (part 2) - Don't call AddClassInfo() for BaseShapes. r=jandem. (10881fe48c)
- Bug 1259490 - Update the DtoA cache after compacting GC; r=jandem (6e3139501c)
- Bug 1257903 - Fix spurious GC hazard on a CLOSED TREE r=me (ce2935d8b2)
- Bug 1259042 - Re-introduce a version of ZoneCellIter for use under GC r=terrence (d1e4ca6e30)
- Bug 1259180 - Compact arenas containing scripts r=terrence (365d22ab00)
- Bug 1258407 - Limit GC heap growth parameters r=sfink (1c9ffb0e3f)
- Bug 1263966 - Compact arenas containing lazy scripts r=terrence (e22c571c37)
- Bug 1266107 - Update type descriptors first when compacting r=terrence (4c2ca98bb3)
- Bug 1266105 - Only purge runtime tables once per slice when compacting r=terrence (74e2977241)
- Bug 1263769 - Sweep WeakCaches in parallel; r=sfink (54b077b37b)
- Bug 1266107 - Track all existing typed object descriptor objects r=terrence (bc60425bf6)
- Bug 1260198 - Clear per-zone string cache after compacting r=terrence (c3002b8021)
- Bug 1259306 - Trace ShapeTables r=terrence (15abb48a33)
- Bug 1262203 - Skip shape table tracing where possible r=terrence (8a1ec15053)
- Bug 1164432 - Update test_try_registering_offline_disabled.html to use mock push server. r=kitcambridge (6d52de1a17)
- Bug 1263857 - Initialize the slots of the match result object before creating properties in generateRegExpMatcherStub. r=h4writer (802af47b3a)
- Bug 1263549 - Fix inlined RegExpPrototypeOptimizable and RegExpInstanceOptimizable. r=h4writer (5565bca590)
- Bug 1264998 - CodeGeneratorShared::assignBailoutId: Properly handle allocation errors. r=h4writer (258cbfc0b6)
- Bug 1257408 - Fix VS2015 C4312 warnings in js/src. r=nbp (d52a4d1fe7)
- Bug 1220466 - Don't build event region display items for pseudo stacking contexts, unless they are also an AGR. r=mstange (9f9a2c7eba)
- Bug 1220466 - Avoid doing unnecessary layer building work for inactive layers. r=mstange (372097e6df)
- Bug 1239151. Increase skia font cache size to 10mb on non-android platforms. r=lsalzman (8a2029da40)
- Bug 1255068 - Do not allow empty transaction transform changes if the scroll position has changed since the last paint. r=kats, r=mattwoodrow (f4a42e10c8)
- Bug 1255068 - Add a check for null scrollid. r=kats (3ddbb78fd3)
- Bug 1258910 - IonMonkey: MIPS: Implement float-point conditional move instructions. r=huangwenjun06 (b53499103b)
- Bug 1258910 - OdinMonkey: MIPS64: Implement AsmSelectI64. r=bbouvier (a36cfffa1d)
- Bug 1258910 - OdinMonkey: MIPS: Implement AsmSelect. r=bbouvier (e458724bc1)
- Bug 1254500 - IonMonkey: MIPS: Implement ma_ctz. r=arai (c8bfd7a6c9)
- Bug 1254500 - IonMonkey: MIPS: Implement CodeGeneratorMIPSShared::visitCtzI. r=arai (b65dad7d1b)
- Bug 1254500 - IonMonkey: MIPS: Implement CodeGeneratorMIPSShared::visitPopcntI. r=arai (58c00b603e)
- Bug 1258105 - Port object length stubs to CacheIR. r=efaust (ed0ec07678)
- Bug 1258301 - Use TraceNullableEdge for CacheIR pointers. r=jonco (3342ef24b4)
- Bug 1258327 - Part 1: Move ToAddress from CodeGeneratorMIPSShared to CodeGeneratorShared. r=hev (59e7494f02)
- Bug 1258327 - Part 2: Remove Operand variant from bailoutCmp32. r=nbp (c4609af383)
- Bug 1258327 - Part 3: Remove Operand variant from branch32 except x86-shared. r=nbp (dca4bc7577)
- Bug 1258327 - Part 4: Remove ToOperand call from arm CodeGenerator. r=jandem (395d7a004f)
- Bug 1258327 - Part 5: Remove dummy ToOperand definition from arm64 CodeGenerator. r=jandem (bc447cb6aa)
- Bug 1258327 - Part 6: Remove ToOperand call from mips-shared and mips64 CodeGenerator. r=hev (d01b028148)
- Bug 1258327 - Part 7: Move ToOperand from CodeGeneratorShared to CodeGeneratorX86Shared. r=nbp (71449d7c62)
- Bug 1248412 - Prevent immediate bailout from innermost for-of loops. r=h4writer (616897a580)
- Bug 1261326 - Fix a bogus assert. r=bhackett (ff715a7954)
- Bug 1260371 - Rearrange RelocationOverlay so that magic field does not overlay inline string chars r=terrence (f88fbb8927)
- Bug 1262203 - Do GC relocation writes in order; r=sfink (b82a25dd15)
- Bug 1247909 - Move MFunctionEnvironment after the entry resume points operands. r=h4writer (29d8d1c2df)
- Bug 1259925 - Port ModuleNamespace getprop stub to CacheIR. r=efaust (b31980bdc3)
- Bug 1264561 - Fix ClassOps::call and ClassOps::construct address calculation in visitIsCallable and visitIsConstructor. r=efaust (172037857b)
- Bug 1264823 - Add pre-barrier to the elements of mapIterationResultPair. r=jandem (b2e451c371)
- Bug 1263609: SharedStubs - Allow JSOP_POW in ion codegen ON CLOSED TREE, r=bbouvier (16bb4ca9af)
- Bug 1265159 - IonMonkey: Throw error when popping from an empty array in MArrayPopShift, r=jandem (e3a1b08614)
- Bug 1259392 - nail down isLockFree(4) for good. r=jolesen (72fa558eec)
- Bug 1244252 - Don't check object group generation when generating code to create unboxed objects off thread, r=terrence. (4191175759)
- Bug 1254578 - Fix OOM case when rematerializing frames. (r=jandem) (a213756a2b)
- Bug 1263139 - Apply ToString to non-standard flags argument of String.prototype.{match,search,replace}. r=till (91c8f6f592)
- Bug 1257810 - ReleaseAcquire should be adequate for a counter; r=sfink (e394a21b3d)
- Bug 1251833 - Part 4: Remove some unneeded qualification from GCRuntime and friends. r=terrence (e77de1a3ac)
- Bug 1260371 - Forward another pointer during TypedObject tracing to fix bustage r=me (24636e9463)
- Bug 1266107 - Simplify typed object tracing now type descriptors are traced first r=terrence (6872be4bfa)
- Bug 1260998 - Add support for HOST_CPPFLAGS for consistency. r=nalexander (9fe0ddee7e)
- Bug 1105556 - Don't call CheckLoadURIWithPrincipal() in DoCheckLoadURIChecks() for TYPE_DOCUMENT loads where we don't have a loadingPrincipal. Ensure SEC_COOKIES_SAME_ORIGIN isn't set for TYPE_DOCUMENT loads in CheckChannel(). r=ckerschb, sicking (fbebbf1017)
- Bug 1195172 - Use channel->ascynOpen2 layout/style/FontFaceSet.cpp (r=bz,cam) (3e943da95c)
- Bug 1250986 - Make Request.referrer a USVString; r=bzbarsky (6987ab9838)
- Bug 1250987 - Make RequestInit.body nullable; r=bzbarsky (2496ebea1f)
- Bug 1251448 - Add support for RequestInit.referrer; r=jdm (dcf1a668f8)
- Bug 1250985 - Part 1: Add a way to identify whether a WebIDL dictionary has any members present; r=bzbarsky (7ddd6e8043)
- Bug 1250985 - Part 2: Prevent copy constructing a Request object with navigate mode if a RequestInit member is present; r=bzbarsky (24c8c1ca56)
- Bug 1184550 - Move the check for bodyUsed before the check for a null body so subsequent fetches with the same Request fail. r=bkelly (60837c04eb)
- Bug 1251872 - Part 1: Implement Request.referrerPolicy; r=jdm (bd024c0614)
- bug 1252687 - make Migration's ctor constexpr r=bz (793d608bcd)
- Bug 1251872 - Part 2: Store the Request referrerPolicy in the DOM Cache; r=bkelly (e1511c07a6)
- Bug 1251229 P2 Add wpt test verifying FetchEvent.request.url does not include fragments. r=ehsan (1d74e2491e)
- Bug 1251229 P1 Strip fragment from request URL when creating FetchEvent. r=ehsan (5faddecc78)
- Bug 1120715 - Part 4: Add tests for Request.cache; r=bkelly (81537bd125)
- Bug 1237455 P1 Make file_CrossSiteXHR_server.sjs check headers on redirects. r=ehsan (597fdf223d)
- Bug 1237455 P2 Test headers on redirects in fetch mochitests. r=ehsan (2a19ac6a44)
- Bug 1237455 P3 Add a version of test_fetch_cors that reroutes through an empty service worker. r=ehsan (0550d5e115)
- Bug 1205288 - implement and test fetch spec changes for blob scheme with non-GET method. r=bkelly (bb519b1c71)
- Bug 1237455 P4 Create helper method to set fetch request headers. r=ehsan (20266aa708)
- Bug 1237455 P5 Set headers on fetch() redirects. r=ehsan (95dcfe7f71)
- Bug 1120715 - Part 5: Treat a default cache mode Request with a revalidation header as no-store; r=bkelly (4182fded21)
- fix! (c3097a682a)
- Bug 1204520 - Remove unused return value from FetchDriver::FailWithNetworkError. r=jdm (ddd84df514)
- Bug 1253054 - Stop warning if request has already failed. r=bkelly (52eb17afd2)
- Bug 1176824 - Intermittent browser_test_web_manifest.js. r=ckerschb (b8c1fc5757)
- Bug 1242051 - Add inter-directory test support file dependencies to ini manifests. r=gps (5d06d6b00c)
- Bug 1250048 - CSP manifest-src doesn't override default-src. r=ckerschb,bkelly,ehsan (3d77b91226)
- Bug 1262624 Move service worker wpt tests out of mozilla dir so they will be upstreamed. r=jgraham (cf1f010cd2)
- Bug 1263469 P1 Set FetchEvent.request.cache value correctly for non-fetch channels. r=mayhemer (0fac232769)
- Bug 1263469 P2 Validate FetchEvent.request.cache in refresh mochitest. r=ehsan (de0db7da84)
- Bug 1263469 P3 Test FetchEvent.request.cache value on reload in wpt test. r=ehsan (8b4fc58d08)
- Bug 1263469 P4 Update test_eventsource_intercept.html to validate FetchEvent.request.cache. r=ehsan (81843666c0)
- Bug 1263469 P5 Add a wpt test case for EventSource. r=ehsan (a32cbbaf80)
- Bug 1265941 - Rename the ReferrerPolicy "origin-only" enum value to "origin"; r=jdm (1b1dfcebbc)
2024-04-16 14:48:59 +08:00

597 lines
17 KiB
C++

/* -*- 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/. */
#include "Request.h"
#include "nsIURI.h"
#include "nsPIDOMWindow.h"
#include "mozilla/ErrorResult.h"
#include "mozilla/dom/Headers.h"
#include "mozilla/dom/Fetch.h"
#include "mozilla/dom/FetchUtil.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/dom/URL.h"
#include "mozilla/dom/WorkerPrivate.h"
#include "mozilla/dom/workers/bindings/URL.h"
#include "mozilla/unused.h"
#include "WorkerPrivate.h"
namespace mozilla {
namespace dom {
NS_IMPL_CYCLE_COLLECTING_ADDREF(Request)
NS_IMPL_CYCLE_COLLECTING_RELEASE(Request)
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Request, mOwner, mHeaders)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Request)
NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
NS_INTERFACE_MAP_ENTRY(nsISupports)
NS_INTERFACE_MAP_END
Request::Request(nsIGlobalObject* aOwner, InternalRequest* aRequest)
: FetchBody<Request>()
, mOwner(aOwner)
, mRequest(aRequest)
{
SetMimeType();
}
Request::~Request()
{
}
// static
bool
Request::RequestContextEnabled(JSContext* aCx, JSObject* aObj)
{
if (NS_IsMainThread()) {
return Preferences::GetBool("dom.requestcontext.enabled", false);
}
using namespace workers;
// Otherwise, check the pref via the WorkerPrivate
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
if (!workerPrivate) {
return false;
}
return workerPrivate->RequestContextEnabled();
}
// static
bool
Request::RequestCacheEnabled(JSContext* aCx, JSObject* aObj)
{
if (NS_IsMainThread()) {
return Preferences::GetBool("dom.requestcache.enabled", false);
}
using namespace workers;
// Otherwise, check the pref via the WorkerPrivate
WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
if (!workerPrivate) {
return false;
}
return workerPrivate->RequestCacheEnabled();
}
already_AddRefed<InternalRequest>
Request::GetInternalRequest()
{
RefPtr<InternalRequest> r = mRequest;
return r.forget();
}
namespace {
already_AddRefed<nsIURI>
ParseURLFromDocument(nsIDocument* aDocument, const nsAString& aInput,
ErrorResult& aRv)
{
MOZ_ASSERT(aDocument);
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIURI> baseURI = aDocument->GetBaseURI();
nsCOMPtr<nsIURI> resolvedURI;
aRv = NS_NewURI(getter_AddRefs(resolvedURI), aInput, nullptr, baseURI);
if (NS_WARN_IF(aRv.Failed())) {
aRv.ThrowTypeError<MSG_INVALID_URL>(aInput);
}
return resolvedURI.forget();
}
void
GetRequestURLFromDocument(nsIDocument* aDocument, const nsAString& aInput,
nsAString& aRequestURL, ErrorResult& aRv)
{
nsCOMPtr<nsIURI> resolvedURI = ParseURLFromDocument(aDocument, aInput, aRv);
if (aRv.Failed()) {
return;
}
// This fails with URIs with weird protocols, even when they are valid,
// so we ignore the failure
nsAutoCString credentials;
Unused << resolvedURI->GetUserPass(credentials);
if (!credentials.IsEmpty()) {
aRv.ThrowTypeError<MSG_URL_HAS_CREDENTIALS>(aInput);
return;
}
nsCOMPtr<nsIURI> resolvedURIClone;
// We use CloneIgnoringRef to strip away the fragment even if the original URI
// is immutable.
aRv = resolvedURI->CloneIgnoringRef(getter_AddRefs(resolvedURIClone));
if (NS_WARN_IF(aRv.Failed())) {
return;
}
nsAutoCString spec;
aRv = resolvedURIClone->GetSpec(spec);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
CopyUTF8toUTF16(spec, aRequestURL);
}
already_AddRefed<nsIURI>
ParseURLFromChrome(const nsAString& aInput, ErrorResult& aRv)
{
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIURI> uri;
aRv = NS_NewURI(getter_AddRefs(uri), aInput, nullptr, nullptr);
if (NS_WARN_IF(aRv.Failed())) {
aRv.ThrowTypeError<MSG_INVALID_URL>(aInput);
}
return uri.forget();
}
void
GetRequestURLFromChrome(const nsAString& aInput, nsAString& aRequestURL,
ErrorResult& aRv)
{
nsCOMPtr<nsIURI> uri = ParseURLFromChrome(aInput, aRv);
if (aRv.Failed()) {
return;
}
// This fails with URIs with weird protocols, even when they are valid,
// so we ignore the failure
nsAutoCString credentials;
Unused << uri->GetUserPass(credentials);
if (!credentials.IsEmpty()) {
aRv.ThrowTypeError<MSG_URL_HAS_CREDENTIALS>(aInput);
return;
}
nsCOMPtr<nsIURI> uriClone;
// We use CloneIgnoringRef to strip away the fragment even if the original URI
// is immutable.
aRv = uri->CloneIgnoringRef(getter_AddRefs(uriClone));
if (NS_WARN_IF(aRv.Failed())) {
return;
}
nsAutoCString spec;
aRv = uriClone->GetSpec(spec);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
CopyUTF8toUTF16(spec, aRequestURL);
}
already_AddRefed<workers::URL>
ParseURLFromWorker(const GlobalObject& aGlobal, const nsAString& aInput,
ErrorResult& aRv)
{
workers::WorkerPrivate* worker = workers::GetCurrentThreadWorkerPrivate();
MOZ_ASSERT(worker);
worker->AssertIsOnWorkerThread();
NS_ConvertUTF8toUTF16 baseURL(worker->GetLocationInfo().mHref);
RefPtr<workers::URL> url =
workers::URL::Constructor(aGlobal, aInput, baseURL, aRv);
if (NS_WARN_IF(aRv.Failed())) {
aRv.ThrowTypeError<MSG_INVALID_URL>(aInput);
}
return url.forget();
}
void
GetRequestURLFromWorker(const GlobalObject& aGlobal, const nsAString& aInput,
nsAString& aRequestURL, ErrorResult& aRv)
{
RefPtr<workers::URL> url = ParseURLFromWorker(aGlobal, aInput, aRv);
if (aRv.Failed()) {
return;
}
nsString username;
url->GetUsername(username, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
nsString password;
url->GetPassword(password, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
if (!username.IsEmpty() || !password.IsEmpty()) {
aRv.ThrowTypeError<MSG_URL_HAS_CREDENTIALS>(aInput);
return;
}
url->SetHash(EmptyString(), aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
url->Stringify(aRequestURL, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return;
}
}
class ReferrerSameOriginChecker final : public workers::WorkerMainThreadRunnable
{
public:
ReferrerSameOriginChecker(workers::WorkerPrivate* aWorkerPrivate,
const nsAString& aReferrerURL,
nsresult& aResult)
: workers::WorkerMainThreadRunnable(aWorkerPrivate),
mReferrerURL(aReferrerURL),
mResult(aResult)
{
mWorkerPrivate->AssertIsOnWorkerThread();
}
bool
MainThreadRun() override
{
nsCOMPtr<nsIURI> uri;
if (NS_SUCCEEDED(NS_NewURI(getter_AddRefs(uri), mReferrerURL))) {
nsCOMPtr<nsIPrincipal> principal = mWorkerPrivate->GetPrincipal();
if (principal) {
mResult = principal->CheckMayLoad(uri, /* report */ false,
/* allowIfInheritsPrincipal */ false);
}
}
return true;
}
private:
const nsString mReferrerURL;
nsresult& mResult;
};
} // namespace
/*static*/ already_AddRefed<Request>
Request::Constructor(const GlobalObject& aGlobal,
const RequestOrUSVString& aInput,
const RequestInit& aInit, ErrorResult& aRv)
{
nsCOMPtr<nsIInputStream> temporaryBody;
RefPtr<InternalRequest> request;
nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
if (aInput.IsRequest()) {
RefPtr<Request> inputReq = &aInput.GetAsRequest();
nsCOMPtr<nsIInputStream> body;
inputReq->GetBody(getter_AddRefs(body));
if (inputReq->BodyUsed()) {
aRv.ThrowTypeError<MSG_FETCH_BODY_CONSUMED_ERROR>();
return nullptr;
}
if (body) {
temporaryBody = body;
}
request = inputReq->GetInternalRequest();
} else {
request = new InternalRequest();
}
request = request->GetRequestConstructorCopy(global, aRv);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
RequestMode fallbackMode = RequestMode::EndGuard_;
RequestCredentials fallbackCredentials = RequestCredentials::EndGuard_;
RequestCache fallbackCache = RequestCache::EndGuard_;
if (aInput.IsUSVString()) {
nsAutoString input;
input.Assign(aInput.GetAsUSVString());
nsAutoString requestURL;
if (NS_IsMainThread()) {
nsIDocument* doc = GetEntryDocument();
if (doc) {
GetRequestURLFromDocument(doc, input, requestURL, aRv);
} else {
// If we don't have a document, we must assume that this is a full URL.
GetRequestURLFromChrome(input, requestURL, aRv);
}
} else {
GetRequestURLFromWorker(aGlobal, input, requestURL, aRv);
}
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
request->SetURL(NS_ConvertUTF16toUTF8(requestURL));
fallbackMode = RequestMode::Cors;
fallbackCredentials = RequestCredentials::Omit;
fallbackCache = RequestCache::Default;
}
RequestMode mode = aInit.mMode.WasPassed() ? aInit.mMode.Value() : fallbackMode;
RequestCredentials credentials =
aInit.mCredentials.WasPassed() ? aInit.mCredentials.Value()
: fallbackCredentials;
if (mode == RequestMode::Navigate ||
(aInit.IsAnyMemberPresent() && request->Mode() == RequestMode::Navigate)) {
aRv.ThrowTypeError<MSG_INVALID_REQUEST_MODE>(NS_LITERAL_STRING("navigate"));
return nullptr;
}
if (aInit.IsAnyMemberPresent()) {
request->SetReferrer(NS_LITERAL_STRING(kFETCH_CLIENT_REFERRER_STR));
request->SetReferrerPolicy(ReferrerPolicy::_empty);
}
if (aInit.mReferrer.WasPassed()) {
const nsString& referrer = aInit.mReferrer.Value();
if (referrer.IsEmpty()) {
request->SetReferrer(NS_LITERAL_STRING(""));
} else {
nsAutoString referrerURL;
if (NS_IsMainThread()) {
nsIDocument* doc = GetEntryDocument();
nsCOMPtr<nsIURI> uri;
if (doc) {
uri = ParseURLFromDocument(doc, referrer, aRv);
} else {
// If we don't have a document, we must assume that this is a full URL.
uri = ParseURLFromChrome(referrer, aRv);
}
if (NS_WARN_IF(aRv.Failed())) {
aRv.ThrowTypeError<MSG_INVALID_REFERRER_URL>(referrer);
return nullptr;
}
nsAutoCString spec;
uri->GetSpec(spec);
CopyUTF8toUTF16(spec, referrerURL);
if (!referrerURL.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR)) {
nsCOMPtr<nsIPrincipal> principal = global->PrincipalOrNull();
if (principal) {
nsresult rv = principal->CheckMayLoad(uri, /* report */ false,
/* allowIfInheritsPrincipal */ false);
if (NS_FAILED(rv)) {
aRv.ThrowTypeError<MSG_INVALID_REFERRER_URL>(referrer);
return nullptr;
}
}
}
} else {
RefPtr<workers::URL> url = ParseURLFromWorker(aGlobal, referrer, aRv);
if (NS_WARN_IF(aRv.Failed())) {
aRv.ThrowTypeError<MSG_INVALID_REFERRER_URL>(referrer);
return nullptr;
}
url->Stringify(referrerURL, aRv);
if (NS_WARN_IF(aRv.Failed())) {
aRv.ThrowTypeError<MSG_INVALID_REFERRER_URL>(referrer);
return nullptr;
}
if (!referrerURL.EqualsLiteral(kFETCH_CLIENT_REFERRER_STR)) {
workers::WorkerPrivate* worker = workers::GetCurrentThreadWorkerPrivate();
nsresult rv = NS_OK;
// ReferrerSameOriginChecker uses a sync loop to get the main thread
// to perform the same-origin check. Overall, on Workers this method
// can create 3 sync loops (two for constructing URLs and one here) so
// in the future we may want to optimize it all by off-loading all of
// this work in a single sync loop.
RefPtr<ReferrerSameOriginChecker> checker =
new ReferrerSameOriginChecker(worker, referrerURL, rv);
checker->Dispatch(aRv);
if (aRv.Failed() || NS_FAILED(rv)) {
aRv.ThrowTypeError<MSG_INVALID_REFERRER_URL>(referrer);
return nullptr;
}
}
}
request->SetReferrer(referrerURL);
}
}
if (aInit.mReferrerPolicy.WasPassed()) {
request->SetReferrerPolicy(aInit.mReferrerPolicy.Value());
}
if (mode != RequestMode::EndGuard_) {
request->ClearCreatedByFetchEvent();
request->SetMode(mode);
}
if (credentials != RequestCredentials::EndGuard_) {
request->ClearCreatedByFetchEvent();
request->SetCredentialsMode(credentials);
}
RequestCache cache = aInit.mCache.WasPassed() ?
aInit.mCache.Value() : fallbackCache;
if (cache != RequestCache::EndGuard_) {
request->ClearCreatedByFetchEvent();
request->SetCacheMode(cache);
}
if (aInit.mRedirect.WasPassed()) {
request->SetRedirectMode(aInit.mRedirect.Value());
}
// Request constructor step 14.
if (aInit.mMethod.WasPassed()) {
nsAutoCString method(aInit.mMethod.Value());
// Step 14.1. Disallow forbidden methods, and anything that is not a HTTP
// token, since HTTP states that Method may be any of the defined values or
// a token (extension method).
nsAutoCString outMethod;
nsresult rv = FetchUtil::GetValidRequestMethod(method, outMethod);
if (NS_FAILED(rv)) {
NS_ConvertUTF8toUTF16 label(method);
aRv.ThrowTypeError<MSG_INVALID_REQUEST_METHOD>(label);
return nullptr;
}
// Step 14.2
request->ClearCreatedByFetchEvent();
request->SetMethod(outMethod);
}
RefPtr<InternalHeaders> requestHeaders = request->Headers();
RefPtr<InternalHeaders> headers;
if (aInit.mHeaders.WasPassed()) {
RefPtr<Headers> h = Headers::Constructor(aGlobal, aInit.mHeaders.Value(), aRv);
if (aRv.Failed()) {
return nullptr;
}
request->ClearCreatedByFetchEvent();
headers = h->GetInternalHeaders();
} else {
headers = new InternalHeaders(*requestHeaders);
}
requestHeaders->Clear();
// From "Let r be a new Request object associated with request and a new
// Headers object whose guard is "request"."
requestHeaders->SetGuard(HeadersGuardEnum::Request, aRv);
MOZ_ASSERT(!aRv.Failed());
if (request->Mode() == RequestMode::No_cors) {
if (!request->HasSimpleMethod()) {
nsAutoCString method;
request->GetMethod(method);
NS_ConvertUTF8toUTF16 label(method);
aRv.ThrowTypeError<MSG_INVALID_REQUEST_METHOD>(label);
return nullptr;
}
requestHeaders->SetGuard(HeadersGuardEnum::Request_no_cors, aRv);
if (aRv.Failed()) {
return nullptr;
}
}
requestHeaders->Fill(*headers, aRv);
if (aRv.Failed()) {
return nullptr;
}
if ((aInit.mBody.WasPassed() && !aInit.mBody.Value().IsNull()) ||
temporaryBody) {
// HEAD and GET are not allowed to have a body.
nsAutoCString method;
request->GetMethod(method);
// method is guaranteed to be uppercase due to step 14.2 above.
if (method.EqualsLiteral("HEAD") || method.EqualsLiteral("GET")) {
aRv.ThrowTypeError<MSG_NO_BODY_ALLOWED_FOR_GET_AND_HEAD>();
return nullptr;
}
}
if (aInit.mBody.WasPassed()) {
const Nullable<OwningArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams>& bodyInitNullable =
aInit.mBody.Value();
if (!bodyInitNullable.IsNull()) {
const OwningArrayBufferOrArrayBufferViewOrBlobOrFormDataOrUSVStringOrURLSearchParams& bodyInit =
bodyInitNullable.Value();
nsCOMPtr<nsIInputStream> stream;
nsAutoCString contentType;
aRv = ExtractByteStreamFromBody(bodyInit,
getter_AddRefs(stream), contentType);
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
temporaryBody = stream;
if (!contentType.IsVoid() &&
!requestHeaders->Has(NS_LITERAL_CSTRING("Content-Type"), aRv)) {
requestHeaders->Append(NS_LITERAL_CSTRING("Content-Type"),
contentType, aRv);
}
if (NS_WARN_IF(aRv.Failed())) {
return nullptr;
}
request->ClearCreatedByFetchEvent();
request->SetBody(temporaryBody);
}
}
RefPtr<Request> domRequest = new Request(global, request);
domRequest->SetMimeType();
if (aInput.IsRequest()) {
RefPtr<Request> inputReq = &aInput.GetAsRequest();
nsCOMPtr<nsIInputStream> body;
inputReq->GetBody(getter_AddRefs(body));
if (body) {
inputReq->SetBody(nullptr);
inputReq->SetBodyUsed();
}
}
return domRequest.forget();
}
already_AddRefed<Request>
Request::Clone(ErrorResult& aRv) const
{
if (BodyUsed()) {
aRv.ThrowTypeError<MSG_FETCH_BODY_CONSUMED_ERROR>();
return nullptr;
}
RefPtr<InternalRequest> ir = mRequest->Clone();
if (!ir) {
aRv.Throw(NS_ERROR_FAILURE);
return nullptr;
}
RefPtr<Request> request = new Request(mOwner, ir);
return request.forget();
}
Headers*
Request::Headers_()
{
if (!mHeaders) {
mHeaders = new Headers(mOwner, mRequest->Headers());
}
return mHeaders;
}
} // namespace dom
} // namespace mozilla