void DataConsumerTee::create(ExecutionContext* executionContext, PassOwnPtr<FetchDataConsumerHandle> src, OwnPtr<FetchDataConsumerHandle>* dest1, OwnPtr<FetchDataConsumerHandle>* dest2) { RefPtr<BlobDataHandle> blobDataHandle = src->obtainReader(nullptr)->drainAsBlobDataHandle(FetchDataConsumerHandle::Reader::AllowBlobWithInvalidSize); if (blobDataHandle) { *dest1 = FetchBlobDataConsumerHandle::create(executionContext, blobDataHandle); *dest2 = FetchBlobDataConsumerHandle::create(executionContext, blobDataHandle); return; } OwnPtr<WebDataConsumerHandle> webDest1, webDest2; DataConsumerTee::create(executionContext, static_cast<PassOwnPtr<WebDataConsumerHandle>>(std::move(src)), &webDest1, &webDest2); *dest1 = createFetchDataConsumerHandleFromWebHandle(std::move(webDest1)); *dest2 = createFetchDataConsumerHandleFromWebHandle(std::move(webDest2)); return; }
PassOwnPtr<FetchDataConsumerHandle> BodyStreamBuffer::lock(ExecutionContext* executionContext) { ASSERT(!isLocked()); ++m_lockLevel; m_reader = nullptr; OwnPtr<FetchDataConsumerHandle> handle = m_handle.release(); if (ReadableStream::Closed == m_stream->stateInternal()) return createFetchDataConsumerHandleFromWebHandle(createDoneDataConsumerHandle()); if (ReadableStream::Errored == m_stream->stateInternal()) return createFetchDataConsumerHandleFromWebHandle(createUnexpectedErrorDataConsumerHandle()); TrackExceptionState exceptionState; m_streamReader = m_stream->getBytesReader(executionContext, exceptionState); return handle.release(); }
FetchResponseData* FetchResponseData::clone(ExecutionContext* executionContext) { FetchResponseData* newResponse = create(); newResponse->m_type = m_type; if (m_terminationReason) { newResponse->m_terminationReason = adoptPtr(new TerminationReason); *newResponse->m_terminationReason = *m_terminationReason; } newResponse->m_url = m_url; newResponse->m_status = m_status; newResponse->m_statusMessage = m_statusMessage; newResponse->m_headerList = m_headerList->clone(); newResponse->m_mimeType = m_mimeType; switch (m_type) { case BasicType: case CORSType: ASSERT(m_internalResponse); ASSERT(m_buffer == m_internalResponse->m_buffer); ASSERT(m_internalResponse->m_type == DefaultType); newResponse->m_internalResponse = m_internalResponse->clone(executionContext); m_buffer = m_internalResponse->m_buffer; newResponse->m_buffer = newResponse->m_internalResponse->m_buffer; break; case DefaultType: { ASSERT(!m_internalResponse); if (m_buffer) { OwnPtr<WebDataConsumerHandle> handle1, handle2; DataConsumerTee::create(executionContext, m_buffer->releaseHandle(executionContext), &handle1, &handle2); m_buffer = new BodyStreamBuffer(createFetchDataConsumerHandleFromWebHandle(handle1.release())); newResponse->m_buffer = new BodyStreamBuffer(createFetchDataConsumerHandleFromWebHandle(handle2.release())); } break; } case ErrorType: ASSERT(!m_internalResponse); ASSERT(!m_buffer); break; case OpaqueType: case OpaqueRedirectType: ASSERT(m_internalResponse); ASSERT(!m_buffer); ASSERT(m_internalResponse->m_type == DefaultType); newResponse->m_internalResponse = m_internalResponse->clone(executionContext); break; } return newResponse; }
std::unique_ptr<FetchDataConsumerHandle> FetchBlobDataConsumerHandle::create(ExecutionContext* executionContext, PassRefPtr<BlobDataHandle> blobDataHandle) { if (!blobDataHandle) return createFetchDataConsumerHandleFromWebHandle(createDoneDataConsumerHandle()); return wrapUnique(new FetchBlobDataConsumerHandle(executionContext, blobDataHandle, new DefaultLoaderFactory)); }
PassOwnPtr<FetchDataConsumerHandle> FetchBlobDataConsumerHandle::create(ExecutionContext* executionContext, PassRefPtr<BlobDataHandle> blobDataHandle, LoaderFactory* loaderFactory) { if (!blobDataHandle) return createFetchDataConsumerHandleFromWebHandle(createDoneDataConsumerHandle()); return adoptPtr(new FetchBlobDataConsumerHandle(executionContext, blobDataHandle, loaderFactory)); }
Response* Response::create(ScriptState* scriptState, ScriptValue bodyValue, const Dictionary& init, ExceptionState& exceptionState) { v8::Local<v8::Value> body = bodyValue.v8Value(); ScriptValue reader; v8::Isolate* isolate = scriptState->isolate(); ExecutionContext* executionContext = scriptState->executionContext(); OwnPtr<FetchDataConsumerHandle> bodyHandle; String contentType; if (bodyValue.isUndefined() || bodyValue.isNull()) { // Note: The IDL processor cannot handle this situation. See // https://crbug.com/335871. } else if (V8Blob::hasInstance(body, isolate)) { Blob* blob = V8Blob::toImpl(body.As<v8::Object>()); bodyHandle = FetchBlobDataConsumerHandle::create(executionContext, blob->blobDataHandle()); contentType = blob->type(); } else if (V8ArrayBuffer::hasInstance(body, isolate)) { bodyHandle = FetchFormDataConsumerHandle::create(V8ArrayBuffer::toImpl(body.As<v8::Object>())); } else if (V8ArrayBufferView::hasInstance(body, isolate)) { bodyHandle = FetchFormDataConsumerHandle::create(V8ArrayBufferView::toImpl(body.As<v8::Object>())); } else if (V8FormData::hasInstance(body, isolate)) { RefPtr<EncodedFormData> formData = V8FormData::toImpl(body.As<v8::Object>())->encodeMultiPartFormData(); // Here we handle formData->boundary() as a C-style string. See // FormDataEncoder::generateUniqueBoundaryString. contentType = AtomicString("multipart/form-data; boundary=", AtomicString::ConstructFromLiteral) + formData->boundary().data(); bodyHandle = FetchFormDataConsumerHandle::create(executionContext, formData.release()); } else if (RuntimeEnabledFeatures::responseConstructedWithReadableStreamEnabled() && ReadableStreamOperations::isReadableStream(scriptState, bodyValue)) { bodyHandle = ReadableStreamDataConsumerHandle::create(scriptState, bodyValue); reader = ReadableStreamOperations::getReader(scriptState, bodyValue, exceptionState); if (exceptionState.hadException()) { reader = ScriptValue(); bodyHandle = createFetchDataConsumerHandleFromWebHandle(createUnexpectedErrorDataConsumerHandle()); exceptionState.clearException(); } else { bodyHandle = ReadableStreamDataConsumerHandle::create(scriptState, reader); } } else { String string = toUSVString(isolate, body, exceptionState); if (exceptionState.hadException()) return nullptr; bodyHandle = FetchFormDataConsumerHandle::create(string); contentType = "text/plain;charset=UTF-8"; } // TODO(yhirano): Add the URLSearchParams case. Response* response = create(executionContext, bodyHandle.release(), contentType, ResponseInit(init, exceptionState), exceptionState); if (!exceptionState.hadException() && !reader.isEmpty()) { // Add a hidden reference so that the weak persistent in the // ReadableStreamDataConsumerHandle will be valid as long as the // Response is valid. v8::Local<v8::Value> wrapper = toV8(response, scriptState); if (wrapper.IsEmpty()) { exceptionState.throwTypeError("Cannot create a Response wrapper"); return nullptr; } ASSERT(wrapper->IsObject()); V8HiddenValue::setHiddenValue(scriptState, wrapper.As<v8::Object>(), V8HiddenValue::readableStreamReaderInResponse(scriptState->isolate()), reader.v8Value()); } return response; }
FetchRequestData* FetchRequestData::pass(ScriptState* scriptState) { FetchRequestData* request = FetchRequestData::cloneExceptBody(); if (m_buffer) { request->m_buffer = m_buffer; m_buffer = new BodyStreamBuffer(scriptState, createFetchDataConsumerHandleFromWebHandle(createDoneDataConsumerHandle())); m_buffer->closeAndLockAndDisturb(); } return request; }
FetchRequestData* FetchRequestData::pass(ExecutionContext* executionContext) { FetchRequestData* request = FetchRequestData::cloneExceptBody(); if (m_buffer) { request->m_buffer = m_buffer; m_buffer = new BodyStreamBuffer(createFetchDataConsumerHandleFromWebHandle(createDoneDataConsumerHandle())); m_buffer->stream()->setIsDisturbed(); } return request; }
void FetchManager::Loader::didReceiveResponse(unsigned long, const ResourceResponse& response, PassOwnPtr<WebDataConsumerHandle> handle) { ASSERT(handle); m_responseHttpStatusCode = response.httpStatusCode(); // Recompute the tainting if the request was redirected to a different // origin. if (!SecurityOrigin::create(response.url())->isSameSchemeHostPort(m_request->origin().get())) { switch (m_request->mode()) { case WebURLRequest::FetchRequestModeSameOrigin: ASSERT_NOT_REACHED(); break; case WebURLRequest::FetchRequestModeNoCORS: m_request->setResponseTainting(FetchRequestData::OpaqueTainting); break; case WebURLRequest::FetchRequestModeCORS: case WebURLRequest::FetchRequestModeCORSWithForcedPreflight: m_request->setResponseTainting(FetchRequestData::CORSTainting); break; } } FetchResponseData* responseData = FetchResponseData::createWithBuffer(BodyStreamBuffer::create(createFetchDataConsumerHandleFromWebHandle(handle))); responseData->setStatus(response.httpStatusCode()); responseData->setStatusMessage(response.httpStatusText()); for (auto& it : response.httpHeaderFields()) responseData->headerList()->append(it.key, it.value); responseData->setURL(response.url()); responseData->setMIMEType(response.mimeType()); FetchResponseData* taintedResponse = responseData; switch (m_request->tainting()) { case FetchRequestData::BasicTainting: taintedResponse = responseData->createBasicFilteredResponse(); break; case FetchRequestData::CORSTainting: taintedResponse = responseData->createCORSFilteredResponse(); break; case FetchRequestData::OpaqueTainting: taintedResponse = responseData->createOpaqueFilteredResponse(); break; } Response* r = Response::create(m_resolver->executionContext(), taintedResponse); r->headers()->setGuard(Headers::ImmutableGuard); m_resolver->resolve(r); m_resolver.clear(); }