/*
 * Copyright (C) 2017 Apple Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE 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 APPLE INC. OR 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.
 */

#include "config.h"
#include "FetchEvent.h"

#include "JSDOMPromise.h"
#include "JSFetchResponse.h"
#include "Logging.h"
#include <wtf/IsoMallocInlines.h>

#if ENABLE(SERVICE_WORKER)

namespace WebCore {

WTF_MAKE_ISO_ALLOCATED_IMPL(FetchEvent);

Ref<FetchEvent> FetchEvent::createForTesting(ScriptExecutionContext& context)
{
    FetchEvent::Init init;
    init.request = FetchRequest::create(context, { }, FetchHeaders::create(FetchHeaders::Guard::Immutable, { }), { }, { }, { });
    return FetchEvent::create("fetch", WTFMove(init), Event::IsTrusted::Yes);
}

FetchEvent::FetchEvent(const AtomString& type, Init&& initializer, IsTrusted isTrusted)
    : ExtendableEvent(type, initializer, isTrusted)
    , m_request(initializer.request.releaseNonNull())
    , m_clientId(WTFMove(initializer.clientId))
    , m_reservedClientId(WTFMove(initializer.reservedClientId))
    , m_targetClientId(WTFMove(initializer.targetClientId))
{
}

FetchEvent::~FetchEvent()
{
    if (auto callback = WTFMove(m_onResponse)) {
        RELEASE_LOG_ERROR_IF(m_respondWithEntered, ServiceWorker, "Fetch event is destroyed without a response, respondWithEntered=%d, waitToRespond=%d, respondWithError=%d, respondPromise=%d", m_respondWithEntered, m_waitToRespond, m_respondWithError, !!m_respondPromise);
        callback(makeUnexpected(std::optional<ResourceError> { }));
    }
}

ResourceError FetchEvent::createResponseError(const URL& url, const String& errorMessage, ResourceError::IsSanitized isSanitized)
{
    return ResourceError { errorDomainWebKitServiceWorker, 0, url, makeString("FetchEvent.respondWith received an error: ", errorMessage), ResourceError::Type::General, isSanitized };

}

ExceptionOr<void> FetchEvent::respondWith(Ref<DOMPromise>&& promise)
{
    if (!isBeingDispatched())
        return Exception { InvalidStateError, "Event is not being dispatched"_s };

    if (m_respondWithEntered)
        return Exception { InvalidStateError, "Event respondWith flag is set"_s };

    m_respondPromise = WTFMove(promise);
    addExtendLifetimePromise(*m_respondPromise);

    auto isRegistered = m_respondPromise->whenSettled([this, protectedThis = Ref { *this }] {
        promiseIsSettled();
    });

    stopPropagation();
    stopImmediatePropagation();

    m_respondWithEntered = true;
    m_waitToRespond = true;

    if (isRegistered == DOMPromise::IsCallbackRegistered::No)
        respondWithError(createResponseError(m_request->url(), "FetchEvent unable to handle respondWith promise."_s, ResourceError::IsSanitized::Yes));

    return { };
}

void FetchEvent::onResponse(ResponseCallback&& callback)
{
    ASSERT(!m_onResponse);
    m_onResponse = WTFMove(callback);
}

void FetchEvent::respondWithError(ResourceError&& error)
{
    m_respondWithError = true;
    processResponse(makeUnexpected(WTFMove(error)));
}

void FetchEvent::processResponse(Expected<Ref<FetchResponse>, std::optional<ResourceError>>&& result)
{
    m_respondPromise = nullptr;
    m_waitToRespond = false;
    if (auto callback = WTFMove(m_onResponse))
        callback(WTFMove(result));
}

void FetchEvent::promiseIsSettled()
{
    if (m_respondPromise->status() == DOMPromise::Status::Rejected) {
        auto reason = m_respondPromise->result().toWTFString(m_respondPromise->globalObject());
        respondWithError(createResponseError(m_request->url(), reason, ResourceError::IsSanitized::Yes));
        return;
    }

    ASSERT(m_respondPromise->status() == DOMPromise::Status::Fulfilled);
    auto response = JSFetchResponse::toWrapped(m_respondPromise->globalObject()->vm(), m_respondPromise->result());
    if (!response) {
        respondWithError(createResponseError(m_request->url(), "Returned response is null."_s, ResourceError::IsSanitized::Yes));
        return;
    }

    if (response->isDisturbedOrLocked()) {
        respondWithError(createResponseError(m_request->url(), "Response is disturbed or locked."_s, ResourceError::IsSanitized::Yes));
        return;
    }

    processResponse(Ref { *response });
}

} // namespace WebCore

#endif // ENABLE(SERVICE_WORKER)
