/* * Copyright (C) 2016 Canon Inc. * * Redistribution and use in source and binary forms, with or without * modification, are permitted, provided that the following conditions * are required to be met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Canon Inc. nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY CANON INC. AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL CANON INC. AND ITS CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "FetchBodyOwner.h" #include "FetchHeaders.h" #include "ReadableStreamSink.h" #include "ResourceResponse.h" #include #include #include namespace JSC { class CallFrame; class JSValue; }; namespace WebCore { class AbortSignal; class FetchRequest; class ReadableStreamSource; class FetchResponse final : public FetchBodyOwner { public: using Type = ResourceResponse::Type; struct Init { unsigned short status { 200 }; String statusText; std::optional headers; }; WEBCORE_EXPORT static Ref create(ScriptExecutionContext&, std::optional&&, FetchHeaders::Guard, ResourceResponse&&); static ExceptionOr> create(ScriptExecutionContext&, std::optional&&, Init&&); static Ref error(ScriptExecutionContext&); static ExceptionOr> redirect(ScriptExecutionContext&, const String& url, int status); using NotificationCallback = WTF::Function&&)>; static void fetch(ScriptExecutionContext&, FetchRequest&, NotificationCallback&&); void startConsumingStream(unsigned); void consumeChunk(Ref&&); void finishConsumingStream(Ref&&); Type type() const { return filteredResponse().type(); } const String& url() const; bool redirected() const { return filteredResponse().isRedirected(); } int status() const { return filteredResponse().httpStatusCode(); } bool ok() const { return filteredResponse().isSuccessful(); } const String& statusText() const { return filteredResponse().httpStatusText(); } const FetchHeaders& headers() const { return m_headers; } FetchHeaders& headers() { return m_headers; } ExceptionOr> clone(ScriptExecutionContext&); void consumeBodyAsStream() final; void feedStream() final; void cancel() final; using ResponseData = Variant, Ref>; ResponseData consumeBody(); void setBodyData(ResponseData&&, uint64_t bodySizeWithPadding); bool isLoading() const { return !!m_bodyLoader; } bool isBodyReceivedByChunk() const { return isLoading() || hasReadableStreamBody(); } bool isBlobBody() const { return !isBodyNull() && body().isBlob(); } bool isBlobFormData() const { return !isBodyNull() && body().isFormData(); } using ConsumeDataByChunkCallback = Function*>&&)>; void consumeBodyReceivedByChunk(ConsumeDataByChunkCallback&&); WEBCORE_EXPORT ResourceResponse resourceResponse() const; ResourceResponse::Tainting tainting() const { return m_internalResponse.tainting(); } uint64_t bodySizeWithPadding() const { return m_bodySizeWithPadding; } void setBodySizeWithPadding(uint64_t size) { m_bodySizeWithPadding = size; } uint64_t opaqueLoadIdentifier() const { return m_opaqueLoadIdentifier; } void initializeOpaqueLoadIdentifierForTesting() { m_opaqueLoadIdentifier = 1; } const HTTPHeaderMap& internalResponseHeaders() const { return m_internalResponse.httpHeaderFields(); } bool isCORSSameOrigin() const; bool hasWasmMIMEType() const; private: FetchResponse(ScriptExecutionContext&, std::optional&&, Ref&&, ResourceResponse&&); void stop() final; const char* activeDOMObjectName() const final; const ResourceResponse& filteredResponse() const; void closeStream(); void addAbortSteps(Ref&&); class BodyLoader final : public FetchLoaderClient { WTF_MAKE_FAST_ALLOCATED; public: BodyLoader(FetchResponse&, NotificationCallback&&); ~BodyLoader(); bool start(ScriptExecutionContext&, const FetchRequest&); void stop(); void consumeDataByChunk(ConsumeDataByChunkCallback&&); RefPtr startStreaming(); NotificationCallback takeNotificationCallback() { return WTFMove(m_responseCallback); } ConsumeDataByChunkCallback takeConsumeDataCallback() { return WTFMove(m_consumeDataCallback); } private: // FetchLoaderClient API void didSucceed() final; void didFail(const ResourceError&) final; void didReceiveResponse(const ResourceResponse&) final; void didReceiveData(const uint8_t*, size_t) final; FetchResponse& m_response; NotificationCallback m_responseCallback; ConsumeDataByChunkCallback m_consumeDataCallback; std::unique_ptr m_loader; Ref> m_pendingActivity; FetchOptions::Credentials m_credentials; }; mutable std::optional m_filteredResponse; ResourceResponse m_internalResponse; std::unique_ptr m_bodyLoader; mutable String m_responseURL; // Opaque responses will padd their body size when used with Cache API. uint64_t m_bodySizeWithPadding { 0 }; uint64_t m_opaqueLoadIdentifier { 0 }; RefPtr m_abortSignal; }; } // namespace WebCore