| // Copyright 2014 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "modules/fetch/RequestInit.h" |
| |
| #include "bindings/core/v8/Dictionary.h" |
| #include "bindings/core/v8/V8ArrayBuffer.h" |
| #include "bindings/core/v8/V8ArrayBufferView.h" |
| #include "bindings/core/v8/V8Binding.h" |
| #include "bindings/core/v8/V8Blob.h" |
| #include "bindings/core/v8/V8FormData.h" |
| #include "bindings/core/v8/V8URLSearchParams.h" |
| #include "bindings/modules/v8/V8PasswordCredential.h" |
| #include "core/dom/URLSearchParams.h" |
| #include "core/fileapi/Blob.h" |
| #include "core/html/FormData.h" |
| #include "modules/fetch/FetchBlobDataConsumerHandle.h" |
| #include "modules/fetch/FetchFormDataConsumerHandle.h" |
| #include "modules/fetch/Headers.h" |
| #include "platform/blob/BlobData.h" |
| #include "platform/network/EncodedFormData.h" |
| #include "platform/weborigin/ReferrerPolicy.h" |
| |
| namespace blink { |
| |
| RequestInit::RequestInit(ExecutionContext* context, const Dictionary& options, ExceptionState& exceptionState) |
| : areAnyMembersSet(false) |
| { |
| areAnyMembersSet |= DictionaryHelper::get(options, "method", method); |
| areAnyMembersSet |= DictionaryHelper::get(options, "headers", headers); |
| if (!headers) { |
| Vector<Vector<String>> headersVector; |
| if (DictionaryHelper::get(options, "headers", headersVector, exceptionState)) { |
| headers = Headers::create(headersVector, exceptionState); |
| areAnyMembersSet = true; |
| } else { |
| areAnyMembersSet |= DictionaryHelper::get(options, "headers", headersDictionary); |
| } |
| } |
| areAnyMembersSet |= DictionaryHelper::get(options, "mode", mode); |
| areAnyMembersSet |= DictionaryHelper::get(options, "redirect", redirect); |
| AtomicString referrerString; |
| bool isReferrerStringSet = DictionaryHelper::get(options, "referrer", referrerString); |
| areAnyMembersSet |= isReferrerStringSet; |
| areAnyMembersSet |= DictionaryHelper::get(options, "integrity", integrity); |
| |
| v8::Local<v8::Value> v8Body; |
| bool isBodySet = DictionaryHelper::get(options, "body", v8Body); |
| areAnyMembersSet |= isBodySet; |
| |
| v8::Local<v8::Value> v8Credential; |
| bool isCredentialSet = DictionaryHelper::get(options, "credentials", v8Credential); |
| areAnyMembersSet |= isCredentialSet; |
| |
| if (areAnyMembersSet) { |
| // A part of the Request constructor algorithm is performed here. See |
| // the comments in the Request constructor code for the detail. |
| |
| // We need to use "about:client" instead of |clientReferrerString|, |
| // because "about:client" => |clientReferrerString| conversion is done |
| // in Request::createRequestWithRequestOrString. |
| referrer = Referrer("about:client", ReferrerPolicyDefault); |
| if (isReferrerStringSet) |
| referrer.referrer = referrerString; |
| } |
| |
| v8::Isolate* isolate = toIsolate(context); |
| if (isCredentialSet) { |
| if (V8PasswordCredential::hasInstance(v8Credential, isolate)) { |
| // TODO(mkwst): According to the spec, we'd serialize this once we touch the network. We're |
| // serializing it here, ahead of time, because lifetime issues around ResourceRequest make |
| // it pretty difficult to pass a PasswordCredential around at the platform level, and the |
| // hop between the browser and renderer processes to deal with service workers is equally |
| // painful. There should be no developer-visible difference in behavior with this option, |
| // except that the `Content-Type` header will be set early. That seems reasonable. |
| PasswordCredential* credential = V8PasswordCredential::toImpl(v8::Local<v8::Object>::Cast(v8Credential)); |
| attachedCredential = credential->encodeFormData(contentType); |
| credentials = "password"; |
| } else if (v8Credential->IsString()) { |
| credentials = toUSVString(isolate, v8Credential, exceptionState); |
| } |
| } |
| |
| if (attachedCredential.get() || !isBodySet || v8Body->IsUndefined() || v8Body->IsNull()) |
| return; |
| |
| if (v8Body->IsArrayBuffer()) { |
| body = FetchFormDataConsumerHandle::create(V8ArrayBuffer::toImpl(v8::Local<v8::Object>::Cast(v8Body))); |
| } else if (v8Body->IsArrayBufferView()) { |
| body = FetchFormDataConsumerHandle::create(V8ArrayBufferView::toImpl(v8::Local<v8::Object>::Cast(v8Body))); |
| } else if (V8Blob::hasInstance(v8Body, isolate)) { |
| RefPtr<BlobDataHandle> blobDataHandle = V8Blob::toImpl(v8::Local<v8::Object>::Cast(v8Body))->blobDataHandle(); |
| contentType = blobDataHandle->type(); |
| body = FetchBlobDataConsumerHandle::create(context, blobDataHandle.release()); |
| } else if (V8FormData::hasInstance(v8Body, isolate)) { |
| RefPtr<EncodedFormData> formData = V8FormData::toImpl(v8::Local<v8::Object>::Cast(v8Body))->encodeMultiPartFormData(); |
| // Here we handle formData->boundary() as a C-style string. See |
| // FormDataEncoder::generateUniqueBoundaryString. |
| contentType = AtomicString("multipart/form-data; boundary=") + formData->boundary().data(); |
| body = FetchFormDataConsumerHandle::create(context, formData.release()); |
| } else if (V8URLSearchParams::hasInstance(v8Body, isolate)) { |
| RefPtr<EncodedFormData> formData = V8URLSearchParams::toImpl(v8::Local<v8::Object>::Cast(v8Body))->encodeFormData(); |
| contentType = AtomicString("application/x-www-form-urlencoded;charset=UTF-8"); |
| body = FetchFormDataConsumerHandle::create(context, formData.release()); |
| } else if (v8Body->IsString()) { |
| contentType = "text/plain;charset=UTF-8"; |
| body = FetchFormDataConsumerHandle::create(toUSVString(isolate, v8Body, exceptionState)); |
| } |
| } |
| |
| } // namespace blink |