Bumping manifests a=b2g-bump
[gecko.git] / dom / fetch / Request.cpp
blob0653f35d7854dc08aabaad64936517366f459521
1 /* -*- Mode: C++; tab-width: 2; 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/. */
6 #include "Request.h"
8 #include "nsIURI.h"
9 #include "nsPIDOMWindow.h"
11 #include "mozilla/ErrorResult.h"
12 #include "mozilla/dom/Headers.h"
13 #include "mozilla/dom/Fetch.h"
14 #include "mozilla/dom/Promise.h"
15 #include "mozilla/dom/URL.h"
16 #include "mozilla/dom/workers/bindings/URL.h"
18 #include "WorkerPrivate.h"
20 namespace mozilla {
21 namespace dom {
23 NS_IMPL_CYCLE_COLLECTING_ADDREF(Request)
24 NS_IMPL_CYCLE_COLLECTING_RELEASE(Request)
25 NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(Request, mOwner, mHeaders)
27 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(Request)
28 NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
29 NS_INTERFACE_MAP_ENTRY(nsISupports)
30 NS_INTERFACE_MAP_END
32 Request::Request(nsIGlobalObject* aOwner, InternalRequest* aRequest)
33 : FetchBody<Request>()
34 , mOwner(aOwner)
35 , mRequest(aRequest)
39 Request::~Request()
43 already_AddRefed<InternalRequest>
44 Request::GetInternalRequest()
46 nsRefPtr<InternalRequest> r = mRequest;
47 return r.forget();
50 /*static*/ already_AddRefed<Request>
51 Request::Constructor(const GlobalObject& aGlobal,
52 const RequestOrUSVString& aInput,
53 const RequestInit& aInit, ErrorResult& aRv)
55 nsRefPtr<InternalRequest> request;
57 nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(aGlobal.GetAsSupports());
59 if (aInput.IsRequest()) {
60 nsRefPtr<Request> inputReq = &aInput.GetAsRequest();
61 if (inputReq->BodyUsed()) {
62 aRv.ThrowTypeError(MSG_REQUEST_BODY_CONSUMED_ERROR);
63 return nullptr;
66 inputReq->SetBodyUsed();
67 request = inputReq->GetInternalRequest();
68 } else {
69 request = new InternalRequest();
72 request = request->GetRequestConstructorCopy(global, aRv);
73 if (NS_WARN_IF(aRv.Failed())) {
74 return nullptr;
77 RequestMode fallbackMode = RequestMode::EndGuard_;
78 RequestCredentials fallbackCredentials = RequestCredentials::EndGuard_;
79 if (aInput.IsUSVString()) {
80 nsString input;
81 input.Assign(aInput.GetAsUSVString());
83 nsString requestURL;
84 if (NS_IsMainThread()) {
85 nsCOMPtr<nsPIDOMWindow> window = do_QueryInterface(global);
86 MOZ_ASSERT(window);
87 nsCOMPtr<nsIURI> docURI = window->GetDocumentURI();
88 nsCString spec;
89 aRv = docURI->GetSpec(spec);
90 if (NS_WARN_IF(aRv.Failed())) {
91 return nullptr;
94 nsRefPtr<mozilla::dom::URL> url =
95 dom::URL::Constructor(aGlobal, input, NS_ConvertUTF8toUTF16(spec), aRv);
96 if (aRv.Failed()) {
97 return nullptr;
100 url->Stringify(requestURL, aRv);
101 if (aRv.Failed()) {
102 return nullptr;
104 } else {
105 workers::WorkerPrivate* worker = workers::GetCurrentThreadWorkerPrivate();
106 MOZ_ASSERT(worker);
107 worker->AssertIsOnWorkerThread();
109 nsString baseURL = NS_ConvertUTF8toUTF16(worker->GetLocationInfo().mHref);
110 nsRefPtr<workers::URL> url =
111 workers::URL::Constructor(aGlobal, input, baseURL, aRv);
112 if (aRv.Failed()) {
113 return nullptr;
116 url->Stringify(requestURL, aRv);
117 if (aRv.Failed()) {
118 return nullptr;
121 request->SetURL(NS_ConvertUTF16toUTF8(requestURL));
122 fallbackMode = RequestMode::Cors;
123 fallbackCredentials = RequestCredentials::Omit;
126 RequestMode mode = aInit.mMode.WasPassed() ? aInit.mMode.Value() : fallbackMode;
127 RequestCredentials credentials =
128 aInit.mCredentials.WasPassed() ? aInit.mCredentials.Value()
129 : fallbackCredentials;
131 if (mode != RequestMode::EndGuard_) {
132 request->SetMode(mode);
135 if (credentials != RequestCredentials::EndGuard_) {
136 request->SetCredentialsMode(credentials);
139 if (aInit.mMethod.WasPassed()) {
140 nsCString method = aInit.mMethod.Value();
141 ToLowerCase(method);
143 if (!method.EqualsASCII("options") &&
144 !method.EqualsASCII("get") &&
145 !method.EqualsASCII("head") &&
146 !method.EqualsASCII("post") &&
147 !method.EqualsASCII("put") &&
148 !method.EqualsASCII("delete")) {
149 NS_ConvertUTF8toUTF16 label(method);
150 aRv.ThrowTypeError(MSG_INVALID_REQUEST_METHOD, &label);
151 return nullptr;
154 ToUpperCase(method);
155 request->SetMethod(method);
158 nsRefPtr<InternalHeaders> requestHeaders = request->Headers();
160 nsRefPtr<InternalHeaders> headers;
161 if (aInit.mHeaders.WasPassed()) {
162 nsRefPtr<Headers> h = Headers::Constructor(aGlobal, aInit.mHeaders.Value(), aRv);
163 if (aRv.Failed()) {
164 return nullptr;
166 headers = h->GetInternalHeaders();
167 } else {
168 headers = new InternalHeaders(*requestHeaders);
171 requestHeaders->Clear();
173 if (request->Mode() == RequestMode::No_cors) {
174 if (!request->HasSimpleMethod()) {
175 nsAutoCString method;
176 request->GetMethod(method);
177 NS_ConvertUTF8toUTF16 label(method);
178 aRv.ThrowTypeError(MSG_INVALID_REQUEST_METHOD, &label);
179 return nullptr;
182 requestHeaders->SetGuard(HeadersGuardEnum::Request_no_cors, aRv);
183 if (aRv.Failed()) {
184 return nullptr;
188 requestHeaders->Fill(*headers, aRv);
189 if (aRv.Failed()) {
190 return nullptr;
193 if (aInit.mBody.WasPassed()) {
194 const OwningArrayBufferOrArrayBufferViewOrBlobOrUSVStringOrURLSearchParams& bodyInit = aInit.mBody.Value();
195 nsCOMPtr<nsIInputStream> stream;
196 nsCString contentType;
197 aRv = ExtractByteStreamFromBody(bodyInit,
198 getter_AddRefs(stream), contentType);
199 if (NS_WARN_IF(aRv.Failed())) {
200 return nullptr;
202 request->SetBody(stream);
204 if (!contentType.IsVoid() &&
205 !requestHeaders->Has(NS_LITERAL_CSTRING("Content-Type"), aRv)) {
206 requestHeaders->Append(NS_LITERAL_CSTRING("Content-Type"),
207 contentType, aRv);
210 if (aRv.Failed()) {
211 return nullptr;
215 nsRefPtr<Request> domRequest = new Request(global, request);
216 domRequest->SetMimeType(aRv);
217 return domRequest.forget();
220 already_AddRefed<Request>
221 Request::Clone() const
223 // FIXME(nsm): Bug 1073231. This is incorrect, but the clone method isn't
224 // well defined yet.
225 nsRefPtr<Request> request = new Request(mOwner,
226 new InternalRequest(*mRequest));
227 return request.forget();
230 Headers*
231 Request::Headers_()
233 if (!mHeaders) {
234 mHeaders = new Headers(mOwner, mRequest->Headers());
237 return mHeaders;
240 } // namespace dom
241 } // namespace mozilla