/*
 * Copyright (C) 2019-2020 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 "DocumentStorageAccess.h"

#if ENABLE(INTELLIGENT_TRACKING_PREVENTION)

#include "Chrome.h"
#include "ChromeClient.h"
#include "Document.h"
#include "EventLoop.h"
#include "Frame.h"
#include "FrameLoader.h"
#include "FrameLoaderClient.h"
#include "JSDOMPromiseDeferred.h"
#include "NetworkStorageSession.h"
#include "Page.h"
#include "Quirks.h"
#include "RegistrableDomain.h"
#include "SecurityOrigin.h"
#include "Settings.h"
#include "UserGestureIndicator.h"

namespace WebCore {

DocumentStorageAccess::DocumentStorageAccess(Document& document)
    : m_document(document)
{
}

DocumentStorageAccess::~DocumentStorageAccess() = default;

DocumentStorageAccess* DocumentStorageAccess::from(Document& document)
{
    auto* supplement = static_cast<DocumentStorageAccess*>(Supplement<Document>::from(&document, supplementName()));
    if (!supplement) {
        auto newSupplement = makeUnique<DocumentStorageAccess>(document);
        supplement = newSupplement.get();
        provideTo(&document, supplementName(), WTFMove(newSupplement));
    }
    return supplement;
}

const char* DocumentStorageAccess::supplementName()
{
    return "DocumentStorageAccess";
}

void DocumentStorageAccess::hasStorageAccess(Document& document, Ref<DeferredPromise>&& promise)
{
    DocumentStorageAccess::from(document)->hasStorageAccess(WTFMove(promise));
}

std::optional<bool> DocumentStorageAccess::hasStorageAccessQuickCheck()
{
    ASSERT(m_document.settings().storageAccessAPIEnabled());

    auto* frame = m_document.frame();
    if (frame && hasFrameSpecificStorageAccess())
        return true;

    auto& securityOrigin = m_document.securityOrigin();
    if (!frame || securityOrigin.isUnique())
        return false;

    if (frame->isMainFrame())
        return true;

    if (securityOrigin.equal(&m_document.topOrigin()))
        return true;

    auto* page = frame->page();
    if (!page)
        return false;

    return std::nullopt;
}

void DocumentStorageAccess::hasStorageAccess(Ref<DeferredPromise>&& promise)
{
    ASSERT(m_document.settings().storageAccessAPIEnabled());

    auto quickCheckResult = hasStorageAccessQuickCheck();
    if (quickCheckResult) {
        promise->resolve<IDLBoolean>(*quickCheckResult);
        return;
    }

    // The existence of a frame and page has been checked in requestStorageAccessQuickCheck().
    auto* frame = m_document.frame();
    if (!frame) {
        ASSERT_NOT_REACHED();
        promise->resolve<IDLBoolean>(false);
        return;
    }
    auto* page = frame->page();
    if (!page) {
        ASSERT_NOT_REACHED();
        promise->resolve<IDLBoolean>(false);
        return;
    }

    page->chrome().client().hasStorageAccess(RegistrableDomain::uncheckedCreateFromHost(m_document.securityOrigin().host()), RegistrableDomain::uncheckedCreateFromHost(m_document.topOrigin().host()), *frame, [weakThis = WeakPtr { *this }, promise = WTFMove(promise)] (bool hasAccess) {
        if (!weakThis)
            return;

        promise->resolve<IDLBoolean>(hasAccess);
    });
}

bool DocumentStorageAccess::hasStorageAccessForDocumentQuirk(Document& document)
{
    auto quickCheckResult = DocumentStorageAccess::from(document)->hasStorageAccessQuickCheck();
    if (quickCheckResult)
        return *quickCheckResult;
    return false;
}

void DocumentStorageAccess::requestStorageAccess(Document& document, Ref<DeferredPromise>&& promise)
{
    DocumentStorageAccess::from(document)->requestStorageAccess(WTFMove(promise));
}

std::optional<StorageAccessQuickResult> DocumentStorageAccess::requestStorageAccessQuickCheck()
{
    ASSERT(m_document.settings().storageAccessAPIEnabled());

    auto* frame = m_document.frame();
    if (frame && hasFrameSpecificStorageAccess())
        return StorageAccessQuickResult::Grant;

    auto& securityOrigin = m_document.securityOrigin();
    if (!frame || securityOrigin.isUnique() || !isAllowedToRequestStorageAccess())
        return StorageAccessQuickResult::Reject;

    if (frame->isMainFrame())
        return StorageAccessQuickResult::Grant;

    if (securityOrigin.equal(&m_document.topOrigin()))
        return StorageAccessQuickResult::Grant;

    // If there is a sandbox, it has to allow the storage access API to be called.
    if (m_document.sandboxFlags() != SandboxNone && m_document.isSandboxed(SandboxStorageAccessByUserActivation))
        return StorageAccessQuickResult::Reject;

    if (!UserGestureIndicator::processingUserGesture())
        return StorageAccessQuickResult::Reject;

    return std::nullopt;
}

void DocumentStorageAccess::requestStorageAccess(Ref<DeferredPromise>&& promise)
{
    ASSERT(m_document.settings().storageAccessAPIEnabled());

    auto quickCheckResult = requestStorageAccessQuickCheck();
    if (quickCheckResult) {
        *quickCheckResult == StorageAccessQuickResult::Grant ? promise->resolve() : promise->reject();
        return;
    }

    // The existence of a frame and page has been checked in requestStorageAccessQuickCheck().
    auto* frame = m_document.frame();
    if (!frame) {
        ASSERT_NOT_REACHED();
        promise->reject();
        return;
    }
    auto* page = frame->page();
    if (!page) {
        ASSERT_NOT_REACHED();
        promise->reject();
        return;
    }

    if (!page->settings().storageAccessAPIPerPageScopeEnabled())
        m_storageAccessScope = StorageAccessScope::PerFrame;

    page->chrome().client().requestStorageAccess(RegistrableDomain::uncheckedCreateFromHost(m_document.securityOrigin().host()), RegistrableDomain::uncheckedCreateFromHost(m_document.topOrigin().host()), *frame, m_storageAccessScope, [this, weakThis = WeakPtr { *this }, promise = WTFMove(promise)] (RequestStorageAccessResult result) mutable {
        if (!weakThis)
            return;

        // Consume the user gesture only if the user explicitly denied access.
        bool shouldPreserveUserGesture = result.wasGranted == StorageAccessWasGranted::Yes || result.promptWasShown == StorageAccessPromptWasShown::No;

        if (shouldPreserveUserGesture) {
            m_document.eventLoop().queueMicrotask([this, weakThis] {
                if (weakThis)
                    enableTemporaryTimeUserGesture();
            });
        }

        if (result.wasGranted == StorageAccessWasGranted::Yes)
            promise->resolve();
        else {
            if (result.promptWasShown == StorageAccessPromptWasShown::Yes)
                setWasExplicitlyDeniedFrameSpecificStorageAccess();
            promise->reject();
        }

        if (shouldPreserveUserGesture) {
            m_document.eventLoop().queueMicrotask([this, weakThis] {
                if (weakThis)
                    consumeTemporaryTimeUserGesture();
            });
        }
    });
}

void DocumentStorageAccess::requestStorageAccessForDocumentQuirk(Document& document, CompletionHandler<void(StorageAccessWasGranted)>&& completionHandler)
{
    DocumentStorageAccess::from(document)->requestStorageAccessForDocumentQuirk(WTFMove(completionHandler));
}

void DocumentStorageAccess::requestStorageAccessForDocumentQuirk(CompletionHandler<void(StorageAccessWasGranted)>&& completionHandler)
{
    auto quickCheckResult = requestStorageAccessQuickCheck();
    if (quickCheckResult) {
        *quickCheckResult == StorageAccessQuickResult::Grant ? completionHandler(StorageAccessWasGranted::Yes) : completionHandler(StorageAccessWasGranted::No);
        return;
    }
    requestStorageAccessQuirk(RegistrableDomain::uncheckedCreateFromHost(m_document.securityOrigin().host()), WTFMove(completionHandler));
}

void DocumentStorageAccess::requestStorageAccessForNonDocumentQuirk(Document& hostingDocument, RegistrableDomain&& requestingDomain, CompletionHandler<void(StorageAccessWasGranted)>&& completionHandler)
{
    DocumentStorageAccess::from(hostingDocument)->requestStorageAccessForNonDocumentQuirk(WTFMove(requestingDomain), WTFMove(completionHandler));
}

void DocumentStorageAccess::requestStorageAccessForNonDocumentQuirk(RegistrableDomain&& requestingDomain, CompletionHandler<void(StorageAccessWasGranted)>&& completionHandler)
{
    if (!m_document.frame() || !m_document.frame()->page() || !isAllowedToRequestStorageAccess()) {
        completionHandler(StorageAccessWasGranted::No);
        return;
    }
    requestStorageAccessQuirk(WTFMove(requestingDomain), WTFMove(completionHandler));
}

void DocumentStorageAccess::requestStorageAccessQuirk(RegistrableDomain&& requestingDomain, CompletionHandler<void(StorageAccessWasGranted)>&& completionHandler)
{
    ASSERT(m_document.settings().storageAccessAPIEnabled());
    RELEASE_ASSERT(m_document.frame() && m_document.frame()->page());

    auto topFrameDomain = RegistrableDomain(m_document.topDocument().url());

    m_document.frame()->page()->chrome().client().requestStorageAccess(WTFMove(requestingDomain), WTFMove(topFrameDomain), *m_document.frame(), m_storageAccessScope, [this, weakThis = WeakPtr { *this }, completionHandler = WTFMove(completionHandler)] (RequestStorageAccessResult result) mutable {
        if (!weakThis)
            return;

        // Consume the user gesture only if the user explicitly denied access.
        bool shouldPreserveUserGesture = result.wasGranted == StorageAccessWasGranted::Yes || result.promptWasShown == StorageAccessPromptWasShown::No;

        if (shouldPreserveUserGesture) {
            m_document.eventLoop().queueMicrotask([this, weakThis] {
                if (weakThis)
                    enableTemporaryTimeUserGesture();
            });
        }

        if (result.wasGranted == StorageAccessWasGranted::Yes)
            completionHandler(StorageAccessWasGranted::Yes);
        else {
            if (result.promptWasShown == StorageAccessPromptWasShown::Yes)
                setWasExplicitlyDeniedFrameSpecificStorageAccess();
            completionHandler(StorageAccessWasGranted::No);
        }

        if (shouldPreserveUserGesture) {
            m_document.eventLoop().queueMicrotask([this, weakThis] {
                if (weakThis)
                    consumeTemporaryTimeUserGesture();
            });
        }
    });
}

void DocumentStorageAccess::enableTemporaryTimeUserGesture()
{
    m_temporaryUserGesture = makeUnique<UserGestureIndicator>(ProcessingUserGesture, &m_document);
}

void DocumentStorageAccess::consumeTemporaryTimeUserGesture()
{
    m_temporaryUserGesture = nullptr;
}

bool DocumentStorageAccess::hasFrameSpecificStorageAccess() const
{
    auto* frame = m_document.frame();
    return frame && frame->loader().client().hasFrameSpecificStorageAccess();
}

} // namespace WebCore

#endif // ENABLE(INTELLIGENT_TRACKING_PREVENTION)
