/*
 * Copyright (C) 2014-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 "ContentExtensionsBackend.h"

#if ENABLE(CONTENT_EXTENSIONS)

#include "Chrome.h"
#include "ChromeClient.h"
#include "CompiledContentExtension.h"
#include "ContentExtension.h"
#include "ContentExtensionsDebugging.h"
#include "ContentRuleListResults.h"
#include "DFABytecodeInterpreter.h"
#include "Document.h"
#include "DocumentLoader.h"
#include "ExtensionStyleSheets.h"
#include "Frame.h"
#include "FrameLoaderClient.h"
#include "Page.h"
#include "ResourceLoadInfo.h"
#include "ScriptController.h"
#include "ScriptSourceCode.h"
#include "Settings.h"
#include <wtf/URL.h>
#include "UserContentController.h"
#include <wtf/NeverDestroyed.h>
#include <wtf/text/CString.h>

namespace WebCore::ContentExtensions {

#if USE(APPLE_INTERNAL_SDK)
#import <WebKitAdditions/ContentRuleListAdditions.mm>
#else
static void makeSecureIfNecessary(ContentRuleListResults& results, const URL& url, const URL& redirectFrom = { })
{
    if (redirectFrom.host() == url.host() && redirectFrom.protocolIs("https"))
        return;

    if (!url.protocolIs("http"))
        return;
    if (url.host() == "www.opengl.org"
        || url.host() == "webkit.org"
        || url.host() == "download")
        results.summary.madeHTTPS = true;
}
#endif

bool ContentExtensionsBackend::shouldBeMadeSecure(const URL& url)
{
    ContentRuleListResults results;
    makeSecureIfNecessary(results, url);
    return results.summary.madeHTTPS;
}

void ContentExtensionsBackend::addContentExtension(const String& identifier, Ref<CompiledContentExtension> compiledContentExtension, URL&& extensionBaseURL, ContentExtension::ShouldCompileCSS shouldCompileCSS)
{
    ASSERT(!identifier.isEmpty());
    if (identifier.isEmpty())
        return;
    
    auto contentExtension = ContentExtension::create(identifier, WTFMove(compiledContentExtension), WTFMove(extensionBaseURL), shouldCompileCSS);
    m_contentExtensions.set(identifier, WTFMove(contentExtension));
}

void ContentExtensionsBackend::removeContentExtension(const String& identifier)
{
    m_contentExtensions.remove(identifier);
}

void ContentExtensionsBackend::removeAllContentExtensions()
{
    m_contentExtensions.clear();
}

auto ContentExtensionsBackend::actionsFromContentRuleList(const ContentExtension& contentExtension, const String& urlString, const ResourceLoadInfo& resourceLoadInfo, ResourceFlags flags) const -> ActionsFromContentRuleList
{
    ActionsFromContentRuleList actionsStruct;
    actionsStruct.contentRuleListIdentifier = contentExtension.identifier();

    const auto& compiledExtension = contentExtension.compiledExtension();

    DFABytecodeInterpreter interpreter(compiledExtension.urlFiltersBytecode());
    auto actionLocations = interpreter.interpret(urlString, flags);
    auto& topURLActions = contentExtension.topURLActions(resourceLoadInfo.mainDocumentURL);
    auto& frameURLActions = contentExtension.frameURLActions(resourceLoadInfo.frameURL);

    actionLocations.removeIf([&](uint64_t actionAndFlags) {
        ResourceFlags flags = actionAndFlags >> 32;
        auto actionCondition = static_cast<ActionCondition>(flags & ActionConditionMask);
        switch (actionCondition) {
        case ActionCondition::None:
            return false;
        case ActionCondition::IfTopURL:
            return !topURLActions.contains(actionAndFlags);
        case ActionCondition::UnlessTopURL:
            return topURLActions.contains(actionAndFlags);
        case ActionCondition::IfFrameURL:
            return !frameURLActions.contains(actionAndFlags);
        }
        ASSERT_NOT_REACHED();
        return false;
    });

    auto serializedActions = compiledExtension.serializedActions();

    const auto& universalActions = contentExtension.universalActions();
    if (auto totalActionCount = actionLocations.size() + universalActions.size()) {
        Vector<uint32_t> vector;
        vector.reserveInitialCapacity(totalActionCount);
        for (uint64_t actionLocation : actionLocations)
            vector.uncheckedAppend(static_cast<uint32_t>(actionLocation));
        for (uint64_t actionLocation : universalActions)
            vector.uncheckedAppend(static_cast<uint32_t>(actionLocation));
        std::sort(vector.begin(), vector.end());

        // Add actions in reverse order to properly deal with IgnorePreviousRules.
        for (auto i = vector.size(); i; i--) {
            auto action = DeserializedAction::deserialize(serializedActions, vector[i - 1]);
            if (std::holds_alternative<IgnorePreviousRulesAction>(action.data())) {
                actionsStruct.sawIgnorePreviousRules = true;
                break;
            }
            actionsStruct.actions.append(WTFMove(action));
        }
    }
    return actionsStruct;
}

auto ContentExtensionsBackend::actionsForResourceLoad(const ResourceLoadInfo& resourceLoadInfo) const -> Vector<ActionsFromContentRuleList>
{
#if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
    MonotonicTime addedTimeStart = MonotonicTime::now();
#endif
    if (m_contentExtensions.isEmpty()
        || !resourceLoadInfo.resourceURL.isValid()
        || resourceLoadInfo.resourceURL.protocolIsData())
        return { };

    const String& urlString = resourceLoadInfo.resourceURL.string();
    ASSERT_WITH_MESSAGE(urlString.isAllASCII(), "A decoded URL should only contain ASCII characters. The matching algorithm assumes the input is ASCII.");

    Vector<ActionsFromContentRuleList> actionsVector;
    actionsVector.reserveInitialCapacity(m_contentExtensions.size());
    ASSERT(!(resourceLoadInfo.getResourceFlags() & ActionConditionMask));
    const ResourceFlags flags = resourceLoadInfo.getResourceFlags() | ActionConditionMask;
    for (auto& contentExtension : m_contentExtensions.values())
        actionsVector.uncheckedAppend(actionsFromContentRuleList(contentExtension.get(), urlString, resourceLoadInfo, flags));
#if CONTENT_EXTENSIONS_PERFORMANCE_REPORTING
    MonotonicTime addedTimeEnd = MonotonicTime::now();
    dataLogF("Time added: %f microseconds %s \n", (addedTimeEnd - addedTimeStart).microseconds(), resourceLoadInfo.resourceURL.string().utf8().data());
#endif
    return actionsVector;
}

void ContentExtensionsBackend::forEach(const Function<void(const String&, ContentExtension&)>& apply)
{
    for (auto& pair : m_contentExtensions)
        apply(pair.key, pair.value);
}

StyleSheetContents* ContentExtensionsBackend::globalDisplayNoneStyleSheet(const String& identifier) const
{
    const auto& contentExtension = m_contentExtensions.get(identifier);
    return contentExtension ? contentExtension->globalDisplayNoneStyleSheet() : nullptr;
}

ContentRuleListResults ContentExtensionsBackend::processContentRuleListsForLoad(Page& page, const URL& url, OptionSet<ResourceType> resourceType, DocumentLoader& initiatingDocumentLoader, const URL& redirectFrom)
{
    Document* currentDocument = nullptr;
    URL mainDocumentURL;
    URL frameURL;
    bool mainFrameContext = false;

    if (auto* frame = initiatingDocumentLoader.frame()) {
        mainFrameContext = frame->isMainFrame();
        currentDocument = frame->document();

        if (initiatingDocumentLoader.isLoadingMainResource()
            && frame->isMainFrame()
            && resourceType == ResourceType::Document)
            mainDocumentURL = url;
        else if (auto* mainDocument = frame->mainFrame().document())
            mainDocumentURL = mainDocument->url();
    }
    if (currentDocument)
        frameURL = currentDocument->url();
    else
        frameURL = url;

    ResourceLoadInfo resourceLoadInfo { url, mainDocumentURL, frameURL, resourceType, mainFrameContext };
    auto actions = actionsForResourceLoad(resourceLoadInfo);

    ContentRuleListResults results;
    if (page.httpsUpgradeEnabled())
        makeSecureIfNecessary(results, url, redirectFrom);
    results.results.reserveInitialCapacity(actions.size());
    for (const auto& actionsFromContentRuleList : actions) {
        const String& contentRuleListIdentifier = actionsFromContentRuleList.contentRuleListIdentifier;
        ContentRuleListResults::Result result;
        for (const auto& action : actionsFromContentRuleList.actions) {
            std::visit(WTF::makeVisitor([&](const BlockLoadAction&) {
                results.summary.blockedLoad = true;
                result.blockedLoad = true;
            }, [&](const BlockCookiesAction&) {
                results.summary.blockedCookies = true;
                result.blockedCookies = true;
            }, [&](const CSSDisplayNoneSelectorAction& actionData) {
                if (resourceType == ResourceType::Document)
                    initiatingDocumentLoader.addPendingContentExtensionDisplayNoneSelector(contentRuleListIdentifier, actionData.string, action.actionID());
                else if (currentDocument)
                    currentDocument->extensionStyleSheets().addDisplayNoneSelector(contentRuleListIdentifier, actionData.string, action.actionID());
            }, [&](const NotifyAction& actionData) {
                results.summary.hasNotifications = true;
                result.notifications.append(actionData.string);
            }, [&](const MakeHTTPSAction&) {
                if ((url.protocolIs("http") || url.protocolIs("ws"))
                    && (!url.port() || WTF::isDefaultPortForProtocol(url.port().value(), url.protocol()))) {
                    results.summary.madeHTTPS = true;
                    result.madeHTTPS = true;
                }
            }, [&](const IgnorePreviousRulesAction&) {
                RELEASE_ASSERT_NOT_REACHED();
            }, [&] (const ModifyHeadersAction& action) {
                if (initiatingDocumentLoader.allowsActiveContentRuleListActionsForURL(contentRuleListIdentifier, url)) {
                    result.modifiedHeaders = true;
                    results.summary.modifyHeadersActions.append(action);
                }
            }, [&] (const RedirectAction& redirectAction) {
                if (initiatingDocumentLoader.allowsActiveContentRuleListActionsForURL(contentRuleListIdentifier, url)) {
                    result.redirected = true;
                    results.summary.redirectActions.append({ redirectAction, m_contentExtensions.get(contentRuleListIdentifier)->extensionBaseURL() });
                }
            }), action.data());
        }

        if (!actionsFromContentRuleList.sawIgnorePreviousRules) {
            if (auto* styleSheetContents = globalDisplayNoneStyleSheet(contentRuleListIdentifier)) {
                if (resourceType == ResourceType::Document)
                    initiatingDocumentLoader.addPendingContentExtensionSheet(contentRuleListIdentifier, *styleSheetContents);
                else if (currentDocument)
                    currentDocument->extensionStyleSheets().maybeAddContentExtensionSheet(contentRuleListIdentifier, *styleSheetContents);
            }
        }

        results.results.uncheckedAppend({ contentRuleListIdentifier, WTFMove(result) });
    }

    if (currentDocument) {
        if (results.summary.madeHTTPS) {
            ASSERT(url.protocolIs("http") || url.protocolIs("ws"));
            String newProtocol = url.protocolIs("http") ? "https"_s : "wss"_s;
            currentDocument->addConsoleMessage(MessageSource::ContentBlocker, MessageLevel::Info, makeString("Promoted URL from ", url.string(), " to ", newProtocol));
        }
        if (results.summary.blockedLoad) {
            currentDocument->addConsoleMessage(MessageSource::ContentBlocker, MessageLevel::Info, makeString("Content blocker prevented frame displaying ", mainDocumentURL.string(), " from loading a resource from ", url.string()));
        
            // Quirk for content-blocker interference with Google's anti-flicker optimization (rdar://problem/45968770).
            // https://developers.google.com/optimize/
            if (currentDocument->settings().googleAntiFlickerOptimizationQuirkEnabled()
                && ((equalLettersIgnoringASCIICase(url.host(), "www.google-analytics.com") && equalLettersIgnoringASCIICase(url.path(), "/analytics.js"))
                    || (equalLettersIgnoringASCIICase(url.host(), "www.googletagmanager.com") && equalLettersIgnoringASCIICase(url.path(), "/gtm.js")))) {
                if (auto* frame = currentDocument->frame())
                    frame->script().evaluateIgnoringException(ScriptSourceCode { "try { window.dataLayer.hide.end(); console.log('Called window.dataLayer.hide.end() in frame ' + document.URL + ' because the content blocker blocked the load of the https://www.google-analytics.com/analytics.js script'); } catch (e) { }"_s });
            }
        }
    }

    return results;
}

ContentRuleListResults ContentExtensionsBackend::processContentRuleListsForPingLoad(const URL& url, const URL& mainDocumentURL, const URL& frameURL)
{
    ResourceLoadInfo resourceLoadInfo { url, mainDocumentURL, frameURL, ResourceType::Ping };
    auto actions = actionsForResourceLoad(resourceLoadInfo);

    ContentRuleListResults results;
    makeSecureIfNecessary(results, url);
    for (const auto& actionsFromContentRuleList : actions) {
        for (const auto& action : actionsFromContentRuleList.actions) {
            std::visit(WTF::makeVisitor([&](const BlockLoadAction&) {
                results.summary.blockedLoad = true;
            }, [&](const BlockCookiesAction&) {
                results.summary.blockedCookies = true;
            }, [&](const CSSDisplayNoneSelectorAction&) {
            }, [&](const NotifyAction&) {
                // We currently have not implemented notifications from the NetworkProcess to the UIProcess.
            }, [&](const MakeHTTPSAction&) {
                if ((url.protocolIs("http") || url.protocolIs("ws")) && (!url.port() || WTF::isDefaultPortForProtocol(url.port().value(), url.protocol())))
                    results.summary.madeHTTPS = true;
            }, [&](const IgnorePreviousRulesAction&) {
                RELEASE_ASSERT_NOT_REACHED();
            }, [&] (const ModifyHeadersAction&) {
                // We currently have not implemented active actions from the network process (CORS preflight).
            }, [&] (const RedirectAction&) {
                // We currently have not implemented active actions from the network process (CORS preflight).
            }), action.data());
        }
    }

    return results;
}

const String& ContentExtensionsBackend::displayNoneCSSRule()
{
    static NeverDestroyed<const String> rule(MAKE_STATIC_STRING_IMPL("display:none !important;"));
    return rule;
}

void applyResultsToRequest(ContentRuleListResults&& results, Page* page, ResourceRequest& request)
{
    if (results.summary.blockedCookies)
        request.setAllowCookies(false);

    if (results.summary.madeHTTPS) {
        const URL& originalURL = request.url();
        ASSERT(originalURL.protocolIs("http"));
        ASSERT(!originalURL.port() || WTF::isDefaultPortForProtocol(originalURL.port().value(), originalURL.protocol()));

        URL newURL = originalURL;
        newURL.setProtocol("https");
        if (originalURL.port())
            newURL.setPort(WTF::defaultPortForProtocol("https").value());
        request.setURL(newURL);
    }

    for (auto& action : results.summary.modifyHeadersActions)
        action.applyToRequest(request);

    for (auto& pair : results.summary.redirectActions)
        pair.first.applyToRequest(request, pair.second);

    if (page && results.shouldNotifyApplication()) {
        results.results.removeAllMatching([](const auto& pair) {
            return !pair.second.shouldNotifyApplication();
        });
        page->chrome().client().contentRuleListNotification(request.url(), results);
    }
}
    
} // namespace WebCore::ContentExtensions

#endif // ENABLE(CONTENT_EXTENSIONS)
