blob: 1b7f16cfa3787f55406d13b10fe275d86123a371 [file] [log] [blame]
/*
* 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 "ResourceResponse.h"
#include <runtime/TypedArrays.h>
namespace JSC {
class ExecState;
class JSValue;
};
namespace WebCore {
class FetchRequest;
class ReadableStreamSource;
class FetchResponse final : public FetchBodyOwner {
public:
using Type = ResourceResponse::Type;
struct Init {
unsigned short status { 200 };
String statusText { ASCIILiteral("OK") };
std::optional<FetchHeaders::Init> headers;
};
static Ref<FetchResponse> create(ScriptExecutionContext& context) { return adoptRef(*new FetchResponse(context, std::nullopt, FetchHeaders::create(FetchHeaders::Guard::Response), ResourceResponse())); }
static Ref<FetchResponse> error(ScriptExecutionContext&);
static ExceptionOr<Ref<FetchResponse>> redirect(ScriptExecutionContext&, const String& url, int status);
static Ref<FetchResponse> create(ScriptExecutionContext& context, std::optional<FetchBody>&& body, Ref<FetchHeaders>&& headers, ResourceResponse&& response) { return adoptRef(*new FetchResponse(context, WTFMove(body), WTFMove(headers), WTFMove(response))); }
using NotificationCallback = WTF::Function<void(ExceptionOr<FetchResponse&>&&)>;
static void fetch(ScriptExecutionContext&, FetchRequest&, NotificationCallback&&);
void consume(unsigned, Ref<DeferredPromise>&&);
#if ENABLE(STREAMS_API)
void startConsumingStream(unsigned);
void consumeChunk(Ref<JSC::Uint8Array>&&);
void finishConsumingStream(Ref<DeferredPromise>&&);
#endif
ExceptionOr<void> setStatus(int status, const String& statusText);
void initializeWith(FetchBody::Init&&);
void setBodyAsReadableStream();
Type type() const { return m_response.type(); }
const String& url() const;
bool redirected() const { return m_response.isRedirected(); }
int status() const { return m_response.httpStatusCode(); }
bool ok() const { return m_response.isSuccessful(); }
const String& statusText() const { return m_response.httpStatusText(); }
const FetchHeaders& headers() const { return m_headers; }
FetchHeaders& headers() { return m_headers; }
Ref<FetchResponse> cloneForJS();
#if ENABLE(STREAMS_API)
ReadableStreamSource* createReadableStreamSource();
void consumeBodyAsStream();
void feedStream();
void cancel();
#endif
using ResponseData = Variant<std::nullptr_t, Ref<FormData>, Ref<SharedBuffer>>;
ResponseData consumeBody();
void setBodyData(ResponseData&&);
bool isLoading() const { return !!m_bodyLoader; }
using ConsumeDataCallback = WTF::Function<void(ExceptionOr<RefPtr<SharedBuffer>>&&)>;
void consumeBodyWhenLoaded(ConsumeDataCallback&&);
const ResourceResponse& resourceResponse() const { return m_response; }
// FIXME: Remove this method and use FetchBodyOwner one once we have full support in DOM ReadableStream.
bool hasReadableStreamBody() const final { return m_isReadableStream; }
private:
FetchResponse(ScriptExecutionContext&, std::optional<FetchBody>&&, Ref<FetchHeaders>&&, ResourceResponse&&);
void stop() final;
const char* activeDOMObjectName() const final;
bool canSuspendForDocumentSuspension() const final;
#if ENABLE(STREAMS_API)
void closeStream();
#endif
class BodyLoader final : public FetchLoaderClient {
public:
BodyLoader(FetchResponse&, NotificationCallback&&);
~BodyLoader();
bool start(ScriptExecutionContext&, const FetchRequest&);
void stop();
void setConsumeDataCallback(ConsumeDataCallback&& consumeDataCallback) { m_consumeDataCallback = WTFMove(consumeDataCallback); }
#if ENABLE(STREAMS_API)
RefPtr<SharedBuffer> startStreaming();
#endif
private:
// FetchLoaderClient API
void didSucceed() final;
void didFail(const ResourceError&) final;
void didReceiveResponse(const ResourceResponse&) final;
void didReceiveData(const char*, size_t) final;
FetchResponse& m_response;
NotificationCallback m_responseCallback;
ConsumeDataCallback m_consumeDataCallback;
std::unique_ptr<FetchLoader> m_loader;
};
ResourceResponse m_response;
std::optional<BodyLoader> m_bodyLoader;
mutable String m_responseURL;
bool m_shouldExposeBody { true };
// FIXME: Remove that flag once we have full support in DOM ReadableStream.
bool m_isReadableStream { false };
FetchBodyConsumer m_consumer { FetchBodyConsumer::Type::ArrayBuffer };
};
} // namespace WebCore