/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 3 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL3 included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 3 requirements
** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 2.0 or (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/

#include "permission_manager_qt.h"

#include "content/browser/renderer_host/render_view_host_delegate.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_type.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"

#include "type_conversion.h"
#include "web_contents_delegate_qt.h"
#include "web_engine_settings.h"

namespace QtWebEngineCore {

static ProfileAdapter::PermissionType toQt(content::PermissionType type)
{
    switch (type) {
    case content::PermissionType::GEOLOCATION:
        return ProfileAdapter::GeolocationPermission;
    case content::PermissionType::AUDIO_CAPTURE:
        return ProfileAdapter::AudioCapturePermission;
    case content::PermissionType::VIDEO_CAPTURE:
        return ProfileAdapter::VideoCapturePermission;
    case content::PermissionType::CLIPBOARD_READ:
        return ProfileAdapter::ClipboardRead;
    case content::PermissionType::CLIPBOARD_WRITE:
        return ProfileAdapter::ClipboardWrite;
    case content::PermissionType::NOTIFICATIONS:
        return ProfileAdapter::NotificationPermission;
    case content::PermissionType::ACCESSIBILITY_EVENTS:
        return ProfileAdapter::UnsupportedPermission;
    case content::PermissionType::FLASH:
    case content::PermissionType::MIDI_SYSEX:
    case content::PermissionType::PROTECTED_MEDIA_IDENTIFIER:
    case content::PermissionType::MIDI:
    case content::PermissionType::DURABLE_STORAGE:
    case content::PermissionType::BACKGROUND_SYNC:
    case content::PermissionType::SENSORS:
    case content::PermissionType::PAYMENT_HANDLER:
    case content::PermissionType::BACKGROUND_FETCH:
    case content::PermissionType::IDLE_DETECTION:
    case content::PermissionType::PERIODIC_BACKGROUND_SYNC:
    case content::PermissionType::WAKE_LOCK_SCREEN:
    case content::PermissionType::WAKE_LOCK_SYSTEM:
    case content::PermissionType::NFC:
    case content::PermissionType::NUM:
        NOTIMPLEMENTED() << "Unsupported permission type: " << static_cast<int>(type);
        break;
    }
    return ProfileAdapter::UnsupportedPermission;
}

static bool canRequestPermissionFor(ProfileAdapter::PermissionType type)
{
    switch (type) {
    case ProfileAdapter::GeolocationPermission:
    case ProfileAdapter::NotificationPermission:
        return true;
    default:
        break;
    }
    return false;
}

static blink::mojom::PermissionStatus toBlink(ProfileAdapter::PermissionState reply)
{
    switch (reply) {
    case ProfileAdapter::AskPermission:
        return blink::mojom::PermissionStatus::ASK;
    case ProfileAdapter::AllowedPermission:
        return blink::mojom::PermissionStatus::GRANTED;
    case ProfileAdapter::DeniedPermission:
        return blink::mojom::PermissionStatus::DENIED;
    }
}

PermissionManagerQt::PermissionManagerQt()
    : m_requestIdCount(0)
    , m_subscriberIdCount(0)
{
}

PermissionManagerQt::~PermissionManagerQt()
{
}

void PermissionManagerQt::permissionRequestReply(const QUrl &url, ProfileAdapter::PermissionType type, ProfileAdapter::PermissionState reply)
{
    // Normalize the QUrl to GURL origin form.
    const GURL gorigin = toGurl(url).GetOrigin();
    const QUrl origin = gorigin.is_empty() ? url : toQt(gorigin);
    if (origin.isEmpty())
        return;
    QPair<QUrl, ProfileAdapter::PermissionType> key(origin, type);
    if (reply == ProfileAdapter::AskPermission)
        m_permissions.remove(key);
    else
        m_permissions[key] = (reply == ProfileAdapter::AllowedPermission);
    blink::mojom::PermissionStatus status = toBlink(reply);
    if (reply != ProfileAdapter::AskPermission) {
        auto it = m_requests.begin();
        while (it != m_requests.end()) {
            if (it->origin == origin && it->type == type) {
                std::move(it->callback).Run(status);
                it = m_requests.erase(it);
            } else
                ++it;
        }
    }
    for (const auto &it: m_subscribers) {
        if (it.second.origin == origin && it.second.type == type)
            it.second.callback.Run(status);
    }

    if (reply == ProfileAdapter::AskPermission)
        return;

    auto it = m_multiRequests.begin();
    while (it != m_multiRequests.end()) {
        if (it->origin == origin) {
            bool answerable = true;
            std::vector<blink::mojom::PermissionStatus> result;
            result.reserve(it->types.size());
            for (content::PermissionType permission : it->types) {
                const ProfileAdapter::PermissionType permissionType = toQt(permission);
                if (permissionType == ProfileAdapter::UnsupportedPermission) {
                    result.push_back(blink::mojom::PermissionStatus::DENIED);
                    continue;
                }

                QPair<QUrl, ProfileAdapter::PermissionType> key(origin, permissionType);
                if (!m_permissions.contains(key)) {
                    answerable = false;
                    break;
                }
                if (m_permissions[key])
                    result.push_back(blink::mojom::PermissionStatus::GRANTED);
                else
                    result.push_back(blink::mojom::PermissionStatus::DENIED);
            }
            if (answerable) {
                std::move(it->callback).Run(result);
                it = m_multiRequests.erase(it);
                continue;
            }
        }
        ++it;
    }
}

bool PermissionManagerQt::checkPermission(const QUrl &origin, ProfileAdapter::PermissionType type)
{
    QPair<QUrl, ProfileAdapter::PermissionType> key(origin, type);
    return m_permissions.contains(key) && m_permissions[key];
}

int PermissionManagerQt::RequestPermission(content::PermissionType permission,
                                            content::RenderFrameHost *frameHost,
                                            const GURL& requesting_origin,
                                            bool /*user_gesture*/,
                                            base::OnceCallback<void(blink::mojom::PermissionStatus)> callback)
{
    if (requesting_origin.is_empty()) {
        std::move(callback).Run(blink::mojom::PermissionStatus::DENIED);
        return content::PermissionController::kNoPendingOperation;
    }

    WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt *>(
        content::WebContents::FromRenderFrameHost(frameHost)->GetDelegate());
    Q_ASSERT(contentsDelegate);

    ProfileAdapter::PermissionType permissionType = toQt(permission);
    if (permissionType == ProfileAdapter::ClipboardRead) {
        WebEngineSettings *settings = contentsDelegate->webEngineSettings();
        if (settings->testAttribute(WebEngineSettings::JavascriptCanAccessClipboard)
            && settings->testAttribute(WebEngineSettings::JavascriptCanPaste))
            std::move(callback).Run(blink::mojom::PermissionStatus::GRANTED);
        else
            std::move(callback).Run(blink::mojom::PermissionStatus::DENIED);
        return content::PermissionController::kNoPendingOperation;
    } else if (!canRequestPermissionFor(permissionType)) {
        std::move(callback).Run(blink::mojom::PermissionStatus::DENIED);
        return content::PermissionController::kNoPendingOperation;
    }

    int request_id = ++m_requestIdCount;
    auto requestOrigin = toQt(requesting_origin);
    m_requests.push_back({ request_id, permissionType, requestOrigin, std::move(callback) });
    contentsDelegate->requestFeaturePermission(permissionType, requestOrigin);
    return request_id;
}

int PermissionManagerQt::RequestPermissions(const std::vector<content::PermissionType>& permissions,
                                            content::RenderFrameHost* frameHost,
                                            const GURL& requesting_origin,
                                            bool /*user_gesture*/,
                                            base::OnceCallback<void(const std::vector<blink::mojom::PermissionStatus>&)> callback)
{
    if (requesting_origin.is_empty()) {
        std::move(callback).Run(std::vector<blink::mojom::PermissionStatus>(permissions.size(), blink::mojom::PermissionStatus::DENIED));
        return content::PermissionController::kNoPendingOperation;
    }

    WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt *>(
        content::WebContents::FromRenderFrameHost(frameHost)->GetDelegate());
    Q_ASSERT(contentsDelegate);

    bool answerable = true;
    std::vector<blink::mojom::PermissionStatus> result;
    result.reserve(permissions.size());
    for (content::PermissionType permission : permissions) {
        const ProfileAdapter::PermissionType permissionType = toQt(permission);
        if (permissionType == ProfileAdapter::UnsupportedPermission)
            result.push_back(blink::mojom::PermissionStatus::DENIED);
        else if (permissionType == ProfileAdapter::ClipboardRead) {
            WebEngineSettings *settings = contentsDelegate->webEngineSettings();
            if (settings->testAttribute(WebEngineSettings::JavascriptCanAccessClipboard)
                && settings->testAttribute(WebEngineSettings::JavascriptCanPaste))
                result.push_back(blink::mojom::PermissionStatus::GRANTED);
            else
                result.push_back(blink::mojom::PermissionStatus::DENIED);
        } else {
            answerable = false;
            break;
        }
    }
    if (answerable) {
        std::move(callback).Run(result);
        return content::PermissionController::kNoPendingOperation;
    }

    int request_id = ++m_requestIdCount;
    auto requestOrigin = toQt(requesting_origin);
    m_multiRequests.push_back({ request_id, permissions, requestOrigin, std::move(callback) });
    for (content::PermissionType permission : permissions) {
        const ProfileAdapter::PermissionType permissionType = toQt(permission);
        if (canRequestPermissionFor(permissionType))
            contentsDelegate->requestFeaturePermission(permissionType, requestOrigin);
    }
    return request_id;
}

blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatus(
    content::PermissionType permission,
    const GURL& requesting_origin,
    const GURL& /*embedding_origin*/)
{
    const ProfileAdapter::PermissionType permissionType = toQt(permission);
    if (permissionType == ProfileAdapter::UnsupportedPermission)
        return blink::mojom::PermissionStatus::DENIED;

    QPair<QUrl, ProfileAdapter::PermissionType> key(toQt(requesting_origin), permissionType);
    if (!m_permissions.contains(key))
        return blink::mojom::PermissionStatus::ASK;
    if (m_permissions[key])
        return blink::mojom::PermissionStatus::GRANTED;
    return blink::mojom::PermissionStatus::DENIED;
}

blink::mojom::PermissionStatus PermissionManagerQt::GetPermissionStatusForFrame(
        content::PermissionType permission,
        content::RenderFrameHost *render_frame_host,
        const GURL &requesting_origin)
{
    if (permission == content::PermissionType::CLIPBOARD_READ ||
            permission == content::PermissionType::CLIPBOARD_WRITE) {
        WebContentsDelegateQt *delegate = static_cast<WebContentsDelegateQt *>(
                content::WebContents::FromRenderFrameHost(render_frame_host)->GetDelegate());
        if (!delegate->webEngineSettings()->testAttribute(WebEngineSettings::JavascriptCanAccessClipboard))
            return blink::mojom::PermissionStatus::DENIED;
        if (permission == content::PermissionType::CLIPBOARD_READ &&
                !delegate->webEngineSettings()->testAttribute(WebEngineSettings::JavascriptCanPaste))
            return blink::mojom::PermissionStatus::DENIED;
        return blink::mojom::PermissionStatus::GRANTED;
    }

    return GetPermissionStatus(
                permission,
                requesting_origin,
                content::WebContents::FromRenderFrameHost(render_frame_host)->GetLastCommittedURL().GetOrigin());
}

void PermissionManagerQt::ResetPermission(
    content::PermissionType permission,
    const GURL& requesting_origin,
    const GURL& /*embedding_origin*/)
{
    const ProfileAdapter::PermissionType permissionType = toQt(permission);
    if (permissionType == ProfileAdapter::UnsupportedPermission)
        return;

    QPair<QUrl, ProfileAdapter::PermissionType> key(toQt(requesting_origin), permissionType);
    m_permissions.remove(key);
}

int PermissionManagerQt::SubscribePermissionStatusChange(
    content::PermissionType permission,
    content::RenderFrameHost * /* render_frame_host */,
    const GURL& requesting_origin,
    base::RepeatingCallback<void(blink::mojom::PermissionStatus)> callback)
{
    int subscriber_id = ++m_subscriberIdCount;
    m_subscribers.insert( { subscriber_id,
                            Subscription { toQt(permission), toQt(requesting_origin), std::move(callback) } });
    return subscriber_id;
}

void PermissionManagerQt::UnsubscribePermissionStatusChange(int subscription_id)
{
    if (!m_subscribers.erase(subscription_id))
        LOG(WARNING) << "PermissionManagerQt::UnsubscribePermissionStatusChange called on unknown subscription id" << subscription_id;
}

} // namespace QtWebEngineCore
