/****************************************************************************
**
** 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$
**
****************************************************************************/

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE.Chromium file.

#include "web_contents_adapter.h"

#include "devtools_frontend_qt.h"
#include "download_manager_delegate_qt.h"
#include "media_capture_devices_dispatcher.h"
#if QT_CONFIG(webengine_printing_and_pdf)
#include "printing/print_view_manager_qt.h"
#endif
#include "profile_adapter_client.h"
#include "profile_adapter.h"
#include "profile_qt.h"
#include "qwebenginecallback_p.h"
#include "renderer_host/render_view_observer_host_qt.h"
#include "render_widget_host_view_qt.h"
#include "type_conversion.h"
#include "web_contents_view_qt.h"
#include "web_engine_context.h"
#include "web_engine_settings.h"

#include "base/command_line.h"
#include "base/run_loop.h"
#include "base/task/post_task.h"
#include "base/task/sequence_manager/sequence_manager_impl.h"
#include "base/task/sequence_manager/thread_controller_with_message_pump_impl.h"
#include "base/values.h"
#include "content/browser/renderer_host/render_view_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/download_manager.h"
#include "content/public/browser/download_request_utils.h"
#include "content/public/browser/host_zoom_map.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/favicon_status.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/drop_data.h"
#include "content/public/common/page_state.h"
#include "content/public/common/page_zoom.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/web_preferences.h"
#include "content/public/common/webrtc_ip_handling_policy.h"
#include "extensions/buildflags/buildflags.h"
#include "third_party/blink/public/web/web_media_player_action.h"
#include "printing/buildflags/buildflags.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/clipboard_constants.h"
#include "ui/base/clipboard/custom_data_helper.h"
#include "ui/gfx/font_render_params.h"

#if QT_CONFIG(webengine_webchannel)
#include "renderer_host/web_channel_ipc_transport_host.h"
#include <QtWebChannel/QWebChannel>
#endif

#if BUILDFLAG(ENABLE_EXTENSIONS)
#include "extensions/extension_web_contents_observer_qt.h"
#endif

#include <QDir>
#include <QGuiApplication>
#include <QPageLayout>
#include <QStringList>
#include <QStyleHints>
#include <QTimer>
#include <QVariant>
#include <QtCore/qelapsedtimer.h>
#include <QtCore/qmimedata.h>
#include <QtCore/qtemporarydir.h>
#include <QtGui/qdrag.h>
#include <QtGui/qpixmap.h>

// Can't include headers as qaccessible.h conflicts with Chromium headers.
namespace content {
extern QAccessibleInterface *toQAccessibleInterface(BrowserAccessibility *acc);
}

namespace QtWebEngineCore {

#define CHECK_INITIALIZED(return_value)         \
    if (!isInitialized())                       \
        return return_value

#define CHECK_VALID_RENDER_WIDGET_HOST_VIEW(render_view_host) \
    if (!render_view_host->IsRenderViewLive() && render_view_host->GetWidget()->GetView()) { \
        LOG(WARNING) << "Ignore navigation due to terminated render process with invalid RenderWidgetHostView."; \
        return; \
    }

static const int kTestWindowWidth = 800;
static const int kTestWindowHeight = 600;
static const int kHistoryStreamVersion = 4;

static QVariant fromJSValue(const base::Value *result)
{
    QVariant ret;
    switch (result->type()) {
    case base::Value::Type::NONE:
        break;
    case base::Value::Type::BOOLEAN:
    {
        bool out;
        if (result->GetAsBoolean(&out))
            ret.setValue(out);
        break;
    }
    case base::Value::Type::INTEGER:
    {
        int out;
        if (result->GetAsInteger(&out))
            ret.setValue(out);
        break;
    }
    case base::Value::Type::DOUBLE:
    {
        double out;
        if (result->GetAsDouble(&out))
            ret.setValue(out);
        break;
    }
    case base::Value::Type::STRING:
    {
        base::string16 out;
        if (result->GetAsString(&out))
            ret.setValue(toQt(out));
        break;
    }
    case base::Value::Type::LIST:
    {
        const base::ListValue *out;
        if (result->GetAsList(&out)) {
            QVariantList list;
            list.reserve(out->GetSize());
            for (size_t i = 0; i < out->GetSize(); ++i) {
                const base::Value *outVal = 0;
                if (out->Get(i, &outVal) && outVal)
                    list.insert(i, fromJSValue(outVal));
            }
            ret.setValue(list);
        }
        break;
    }
    case base::Value::Type::DICTIONARY:
    {
        const base::DictionaryValue *out;
        if (result->GetAsDictionary(&out)) {
            QVariantMap map;
            base::DictionaryValue::Iterator it(*out);
            while (!it.IsAtEnd()) {
                map.insert(toQt(it.key()), fromJSValue(&it.value()));
                it.Advance();
            }
            ret.setValue(map);
        }
        break;
    }
    case base::Value::Type::BINARY:
    {
        QByteArray data(reinterpret_cast<const char *>(result->GetBlob().data()), result->GetBlob().size());
        ret.setValue(data);
        break;
    }
    default:
        Q_UNREACHABLE();
        break;
    }
    return ret;
}

static void callbackOnEvaluateJS(WebContentsAdapterClient *adapterClient, quint64 requestId, base::Value result)
{
    if (requestId)
        adapterClient->didRunJavaScript(requestId, fromJSValue(&result));
}

#if QT_CONFIG(webengine_printing_and_pdf)
static void callbackOnPrintingFinished(WebContentsAdapterClient *adapterClient,
                                       int requestId,
                                       QSharedPointer<QByteArray> result)
{
    if (requestId)
        adapterClient->didPrintPage(requestId, result);
}

static void callbackOnPdfSavingFinished(WebContentsAdapterClient *adapterClient,
                                        const QString& filePath,
                                        bool success)
{
    adapterClient->didPrintPageToPdf(filePath, success);
}
#endif

static std::unique_ptr<content::WebContents> createBlankWebContents(WebContentsAdapterClient *adapterClient, content::BrowserContext *browserContext)
{
    content::WebContents::CreateParams create_params(browserContext, NULL);
    create_params.routing_id = MSG_ROUTING_NONE;
    create_params.initial_size = gfx::Size(kTestWindowWidth, kTestWindowHeight);
    create_params.initially_hidden = true;

    std::unique_ptr<content::WebContents> webContents = content::WebContents::Create(create_params);
    WebContentsViewQt* contentsView = static_cast<WebContentsViewQt*>(static_cast<content::WebContentsImpl*>(webContents.get())->GetView());
    contentsView->setClient(adapterClient);

    return webContents;
}

static void serializeNavigationHistory(content::NavigationController &controller, QDataStream &output)
{
    const int currentIndex = controller.GetCurrentEntryIndex();
    const int count = controller.GetEntryCount();
    const int pendingIndex = controller.GetPendingEntryIndex();

    output << kHistoryStreamVersion;
    output << count;
    output << currentIndex;

    // Logic taken from SerializedNavigationEntry::WriteToPickle.
    for (int i = 0; i < count; ++i) {
        content::NavigationEntry* entry = (i == pendingIndex)
            ? controller.GetPendingEntry()
            : controller.GetEntryAtIndex(i);
        if (entry->GetVirtualURL().is_valid()) {
            if (entry->GetHasPostData())
                entry->GetPageState().RemovePasswordData();
            std::string encodedPageState = entry->GetPageState().ToEncodedData();
            output << toQt(entry->GetVirtualURL());
            output << toQt(entry->GetTitle());
            output << QByteArray(encodedPageState.data(), encodedPageState.size());
            output << static_cast<qint32>(entry->GetTransitionType());
            output << entry->GetHasPostData();
            output << toQt(entry->GetReferrer().url);
            output << static_cast<qint32>(entry->GetReferrer().policy);
            output << toQt(entry->GetOriginalRequestURL());
            output << entry->GetIsOverridingUserAgent();
            output << static_cast<qint64>(entry->GetTimestamp().ToInternalValue());
            output << entry->GetHttpStatusCode();
            // kHistoryStreamVersion >= 4
            content::FaviconStatus &favicon = entry->GetFavicon();
            output << (favicon.valid ? toQt(favicon.url) : QUrl());
        }
    }
}

static void deserializeNavigationHistory(QDataStream &input, int *currentIndex, std::vector<std::unique_ptr<content::NavigationEntry>> *entries, content::BrowserContext *browserContext)
{
    int version;
    input >> version;
    if (version < 3 || version > kHistoryStreamVersion) {
        // We do not try to decode history stream versions before 3.
        // Make sure that our history is cleared and mark the rest of the stream as invalid.
        input.setStatus(QDataStream::ReadCorruptData);
        *currentIndex = -1;
        return;
    }

    int count;
    input >> count >> *currentIndex;

    entries->reserve(count);
    // Logic taken from SerializedNavigationEntry::ReadFromPickle and ToNavigationEntries.
    for (int i = 0; i < count; ++i) {
        QUrl virtualUrl, referrerUrl, originalRequestUrl, iconUrl;
        QString title;
        QByteArray pageState;
        qint32 transitionType, referrerPolicy;
        bool hasPostData, isOverridingUserAgent;
        qint64 timestamp;
        int httpStatusCode;
        input >> virtualUrl;
        input >> title;
        input >> pageState;
        input >> transitionType;
        input >> hasPostData;
        input >> referrerUrl;
        input >> referrerPolicy;
        input >> originalRequestUrl;
        input >> isOverridingUserAgent;
        input >> timestamp;
        input >> httpStatusCode;
        // kHistoryStreamVersion >= 4
        if (version >= 4)
            input >> iconUrl;

        // If we couldn't unpack the entry successfully, abort everything.
        if (input.status() != QDataStream::Ok) {
            *currentIndex = -1;
            auto it = entries->begin();
            auto end = entries->end();
            for (; it != end; ++it)
                it->reset();
            entries->clear();
            return;
        }

        std::unique_ptr<content::NavigationEntry> entry = content::NavigationController::CreateNavigationEntry(
            toGurl(virtualUrl),
            content::Referrer(toGurl(referrerUrl), static_cast<network::mojom::ReferrerPolicy>(referrerPolicy)),
            base::nullopt, // optional initiator_origin
            // Use a transition type of reload so that we don't incorrectly
            // increase the typed count.
            ui::PAGE_TRANSITION_RELOAD,
            false,
            // The extra headers are not sync'ed across sessions.
            std::string(),
            browserContext,
            nullptr);

        entry->SetTitle(toString16(title));
        entry->SetPageState(content::PageState::CreateFromEncodedData(std::string(pageState.data(), pageState.size())));
        entry->SetHasPostData(hasPostData);
        entry->SetOriginalRequestURL(toGurl(originalRequestUrl));
        entry->SetIsOverridingUserAgent(isOverridingUserAgent);
        entry->SetTimestamp(base::Time::FromInternalValue(timestamp));
        entry->SetHttpStatusCode(httpStatusCode);
        if (iconUrl.isValid()) {
            // Note: we don't set .image below as we don't have it and chromium will refetch favicon
            // anyway. However, we set .url and .valid to let QWebEngineHistory items restored from
            // a stream receive valid icon URLs via our getNavigationEntryIconUrl calls.
            content::FaviconStatus &favicon = entry->GetFavicon();
            favicon.url = toGurl(iconUrl);
            favicon.valid = true;
        }
        entries->push_back(std::move(entry));
    }
}

namespace {
static QList<WebContentsAdapter *> recursive_guard_loading_adapters;

class LoadRecursionGuard {
    public:
    static bool isGuarded(WebContentsAdapter *adapter)
    {
        return recursive_guard_loading_adapters.contains(adapter);
    }
    LoadRecursionGuard(WebContentsAdapter *adapter)
        : m_adapter(adapter)
    {
        recursive_guard_loading_adapters.append(adapter);
    }

    ~LoadRecursionGuard() {
        recursive_guard_loading_adapters.removeOne(m_adapter);
    }

    private:
        WebContentsAdapter *m_adapter;
};
} // Anonymous namespace

QSharedPointer<WebContentsAdapter> WebContentsAdapter::createFromSerializedNavigationHistory(QDataStream &input, WebContentsAdapterClient *adapterClient)
{
    int currentIndex;
    std::vector<std::unique_ptr<content::NavigationEntry>> entries;
    deserializeNavigationHistory(input, &currentIndex, &entries, adapterClient->profileAdapter()->profile());

    if (currentIndex == -1)
        return QSharedPointer<WebContentsAdapter>();

    // Unlike WebCore, Chromium only supports Restoring to a new WebContents instance.
    std::unique_ptr<content::WebContents> newWebContents = createBlankWebContents(adapterClient, adapterClient->profileAdapter()->profile());
    content::NavigationController &controller = newWebContents->GetController();
    controller.Restore(currentIndex, content::RestoreType::LAST_SESSION_EXITED_CLEANLY, &entries);

    if (controller.GetActiveEntry()) {
        // Set up the file access rights for the selected navigation entry.
        // TODO(joth): This is duplicated from chrome/.../session_restore.cc and
        // should be shared e.g. in  NavigationController. http://crbug.com/68222
        const int id = newWebContents->GetMainFrame()->GetProcess()->GetID();
        const content::PageState& pageState = controller.GetActiveEntry()->GetPageState();
        const std::vector<base::FilePath>& filePaths = pageState.GetReferencedFiles();
        for (std::vector<base::FilePath>::const_iterator file = filePaths.begin(); file != filePaths.end(); ++file)
            content::ChildProcessSecurityPolicy::GetInstance()->GrantReadFile(id, *file);
    }

    return QSharedPointer<WebContentsAdapter>::create(std::move(newWebContents));
}

WebContentsAdapter::WebContentsAdapter()
  : m_profileAdapter(nullptr)
  , m_webContents(nullptr)
#if QT_CONFIG(webengine_webchannel)
  , m_webChannel(nullptr)
  , m_webChannelWorld(0)
#endif
  , m_adapterClient(nullptr)
  , m_nextRequestId(CallbackDirectory::ReservedCallbackIdsEnd)
  , m_currentDropAction(blink::kWebDragOperationNone)
  , m_devToolsFrontend(nullptr)
{
    // This has to be the first thing we create, and the last we destroy.
    WebEngineContext::current();
}

WebContentsAdapter::WebContentsAdapter(std::unique_ptr<content::WebContents> webContents)
  : m_profileAdapter(nullptr)
  , m_webContents(std::move(webContents))
#if QT_CONFIG(webengine_webchannel)
  , m_webChannel(nullptr)
  , m_webChannelWorld(0)
#endif
  , m_adapterClient(nullptr)
  , m_nextRequestId(CallbackDirectory::ReservedCallbackIdsEnd)
  , m_currentDropAction(blink::kWebDragOperationNone)
  , m_devToolsFrontend(nullptr)
{
    // This has to be the first thing we create, and the last we destroy.
    WebEngineContext::current();
}

WebContentsAdapter::~WebContentsAdapter()
{
    if (m_devToolsFrontend)
        closeDevToolsFrontend();
    Q_ASSERT(!m_devToolsFrontend);
}

void WebContentsAdapter::setClient(WebContentsAdapterClient *adapterClient)
{
    Q_ASSERT(!isInitialized());
    m_adapterClient = adapterClient;
    m_profileAdapter = adapterClient->profileAdapter();
    Q_ASSERT(m_profileAdapter);

    // This might replace any adapter that has been initialized with this WebEngineSettings.
    adapterClient->webEngineSettings()->setWebContentsAdapter(this);
}

bool WebContentsAdapter::isInitialized() const
{
    return (bool)m_webContentsDelegate;
}

void WebContentsAdapter::initialize(content::SiteInstance *site)
{
    Q_ASSERT(m_adapterClient);
    Q_ASSERT(!isInitialized());

    // Create our own if a WebContents wasn't provided at construction.
    if (!m_webContents) {
        content::WebContents::CreateParams create_params(m_profileAdapter->profile(), site);
        create_params.initial_size = gfx::Size(kTestWindowWidth, kTestWindowHeight);
        create_params.initially_hidden = true;
        m_webContents = content::WebContents::Create(create_params);
    }

    initializeRenderPrefs();

    // Create and attach observers to the WebContents.
    m_webContentsDelegate.reset(new WebContentsDelegateQt(m_webContents.get(), m_adapterClient));
    m_renderViewObserverHost.reset(new RenderViewObserverHostQt(m_webContents.get(), m_adapterClient));

    // Let the WebContent's view know about the WebContentsAdapterClient.
    WebContentsViewQt* contentsView = static_cast<WebContentsViewQt*>(static_cast<content::WebContentsImpl*>(m_webContents.get())->GetView());
    contentsView->setClient(m_adapterClient);

    // This should only be necessary after having restored the history to a new WebContentsAdapter.
    m_webContents->GetController().LoadIfNecessary();

#if QT_CONFIG(webengine_printing_and_pdf)
    PrintViewManagerQt::CreateForWebContents(webContents());
#endif
#if BUILDFLAG(ENABLE_EXTENSIONS)
    extensions::ExtensionWebContentsObserverQt::CreateForWebContents(webContents());
#endif

    // Create an instance of WebEngineVisitedLinksManager to catch the first
    // content::NOTIFICATION_RENDERER_PROCESS_CREATED event. This event will
    // force to initialize visited links in VisitedLinkSlave.
    // It must be done before creating a RenderView.
    m_profileAdapter->visitedLinksManager();

    // Create a RenderView with the initial empty document
    content::RenderViewHost *rvh = m_webContents->GetRenderViewHost();
    Q_ASSERT(rvh);
    if (!rvh->IsRenderViewLive())
        static_cast<content::WebContentsImpl*>(m_webContents.get())->CreateRenderViewForRenderManager(rvh, MSG_ROUTING_NONE, MSG_ROUTING_NONE, base::UnguessableToken::Create(), content::FrameReplicationState());

    m_webContentsDelegate->RenderViewHostChanged(nullptr, rvh);

    m_adapterClient->initializationFinished();
}

void WebContentsAdapter::initializeRenderPrefs()
{
    blink::mojom::RendererPreferences *rendererPrefs = m_webContents->GetMutableRendererPrefs();
    rendererPrefs->use_custom_colors = true;
    // Qt returns a flash time (the whole cycle) in ms, chromium expects just the interval in
    // seconds
    const int qtCursorFlashTime = QGuiApplication::styleHints()->cursorFlashTime();
    rendererPrefs->caret_blink_interval =
            base::TimeDelta::FromMillisecondsD(0.5 * static_cast<double>(qtCursorFlashTime));
    rendererPrefs->user_agent_override = m_profileAdapter->httpUserAgent().toStdString();
    rendererPrefs->accept_languages = m_profileAdapter->httpAcceptLanguageWithoutQualities().toStdString();
#if QT_CONFIG(webengine_webrtc)
    base::CommandLine* commandLine = base::CommandLine::ForCurrentProcess();
    if (commandLine->HasSwitch(switches::kForceWebRtcIPHandlingPolicy))
        rendererPrefs->webrtc_ip_handling_policy =
                commandLine->GetSwitchValueASCII(switches::kForceWebRtcIPHandlingPolicy);
    else
        rendererPrefs->webrtc_ip_handling_policy =
                m_adapterClient->webEngineSettings()->testAttribute(WebEngineSettings::WebRTCPublicInterfacesOnly)
                ? content::kWebRTCIPHandlingDefaultPublicInterfaceOnly
                : content::kWebRTCIPHandlingDefault;
#endif
    // Set web-contents font settings to the default font settings as Chromium constantly overrides
    // the global font defaults with the font settings of the latest web-contents created.
    static const gfx::FontRenderParams params = gfx::GetFontRenderParams(gfx::FontRenderParamsQuery(), nullptr);
    rendererPrefs->should_antialias_text = params.antialiasing;
    rendererPrefs->use_subpixel_positioning = params.subpixel_positioning;
    rendererPrefs->hinting = params.hinting;
    rendererPrefs->use_autohinter = params.autohinter;
    rendererPrefs->use_bitmaps = params.use_bitmaps;
    rendererPrefs->subpixel_rendering = params.subpixel_rendering;
    m_webContents->GetRenderViewHost()->SyncRendererPrefs();
}

bool WebContentsAdapter::canGoBack() const
{
    CHECK_INITIALIZED(false);
    return m_webContents->GetController().CanGoBack();
}

bool WebContentsAdapter::canGoForward() const
{
    CHECK_INITIALIZED(false);
    return m_webContents->GetController().CanGoForward();
}

bool WebContentsAdapter::canGoToOffset(int offset) const
{
    CHECK_INITIALIZED(false);
    return m_webContents->GetController().CanGoToOffset(offset);
}

void WebContentsAdapter::stop()
{
    CHECK_INITIALIZED();
    content::NavigationController& controller = m_webContents->GetController();

    int index = controller.GetPendingEntryIndex();
    if (index != -1)
        controller.RemoveEntryAtIndex(index);

    m_webContents->Stop();
    focusIfNecessary();
}

void WebContentsAdapter::reload()
{
    CHECK_INITIALIZED();
    bool wasDiscarded = (m_lifecycleState == LifecycleState::Discarded);
    setLifecycleState(LifecycleState::Active);
    CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost());
    if (!wasDiscarded) // undiscard() already triggers a reload
        m_webContents->GetController().Reload(content::ReloadType::NORMAL, /*checkRepost = */false);
    focusIfNecessary();
}

void WebContentsAdapter::reloadAndBypassCache()
{
    CHECK_INITIALIZED();
    bool wasDiscarded = (m_lifecycleState == LifecycleState::Discarded);
    setLifecycleState(LifecycleState::Active);
    CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost());
    if (!wasDiscarded) // undiscard() already triggers a reload
        m_webContents->GetController().Reload(content::ReloadType::BYPASSING_CACHE, /*checkRepost = */false);
    focusIfNecessary();
}

void WebContentsAdapter::loadDefault()
{
    Q_ASSERT(!isInitialized());
    initialize(nullptr);
}

void WebContentsAdapter::load(const QUrl &url)
{
    QWebEngineHttpRequest request(url);
    load(request);
}

void WebContentsAdapter::load(const QWebEngineHttpRequest &request)
{
    GURL gurl = toGurl(request.url());
    if (!isInitialized()) {
        scoped_refptr<content::SiteInstance> site =
            content::SiteInstance::CreateForURL(m_profileAdapter->profile(), gurl);
        initialize(site.get());
    } else {
        setLifecycleState(LifecycleState::Active);
    }

    CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost());

    // The situation can occur when relying on the editingFinished signal in QML to set the url
    // of the WebView.
    // When enter is pressed, onEditingFinished fires and the url of the webview is set, which
    // calls into this and focuses the webview, taking the focus from the TextField/TextInput,
    // which in turn leads to editingFinished firing again. This scenario would cause a crash
    // down the line when unwinding as the first RenderWidgetHostViewQtDelegateQuick instance is
    // a dangling pointer by that time.

    if (LoadRecursionGuard::isGuarded(this))
        return;
    LoadRecursionGuard guard(this);
    Q_UNUSED(guard);

    // Add URL scheme if missing from view-source URL.
    if (request.url().scheme() == content::kViewSourceScheme) {
        QUrl pageUrl = QUrl(request.url().toString().remove(0,
                                                           strlen(content::kViewSourceScheme) + 1));
        if (pageUrl.scheme().isEmpty()) {
            QUrl extendedUrl = QUrl::fromUserInput(pageUrl.toString());
            extendedUrl = QUrl(QString("%1:%2").arg(content::kViewSourceScheme,
                                                    extendedUrl.toString()));
            gurl = toGurl(extendedUrl);
        }
    }

    content::NavigationController::LoadURLParams params(gurl);
    params.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED
                                                     | ui::PAGE_TRANSITION_FROM_ADDRESS_BAR);
    params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;

    switch (request.method()) {
    case QWebEngineHttpRequest::Get:
        params.load_type = content::NavigationController::LOAD_TYPE_DEFAULT;
        break;

    case QWebEngineHttpRequest::Post:
        params.load_type = content::NavigationController::LOAD_TYPE_HTTP_POST;
        // chromium accepts LOAD_TYPE_HTTP_POST only for the HTTP and HTTPS protocols
        if (!params.url.SchemeIsHTTPOrHTTPS()) {
            m_adapterClient->loadFinished(false, request.url(), false,
                                           net::ERR_DISALLOWED_URL_SCHEME,
                                           QCoreApplication::translate("WebContentsAdapter",
                                           "HTTP-POST data can only be sent over HTTP(S) protocol"));
            return;
        }
        params.post_data = network::ResourceRequestBody::CreateFromBytes(
                    (const char*)request.postData().constData(),
                    request.postData().length());
        break;
    }

    // convert the custom headers into the format that chromium expects
    QVector<QByteArray> headers = request.headers();
    for (QVector<QByteArray>::const_iterator it = headers.cbegin(); it != headers.cend(); ++it) {
        if (params.extra_headers.length() > 0)
            params.extra_headers += '\n';
        params.extra_headers += (*it).toStdString() + ": " + request.header(*it).toStdString();
    }

    bool resizeNeeded = false;
    if (request.url().hasFragment()) {
        if (content::RenderWidgetHostView *rwhv = webContents()->GetRenderWidgetHostView()) {
            const gfx::Size &viewportSize = rwhv->GetVisibleViewportSize();
            resizeNeeded = (viewportSize.width() == 0 || viewportSize.height() == 0);
        }
    }

    auto navigate = [](QWeakPointer<WebContentsAdapter> weakAdapter, const content::NavigationController::LoadURLParams &params) {
        const auto adapter = weakAdapter.toStrongRef();
        if (!adapter)
            return;
        adapter->webContents()->GetController().LoadURLWithParams(params);
        adapter->focusIfNecessary();
    };

    QWeakPointer<WebContentsAdapter> weakThis(sharedFromThis());
    if (resizeNeeded) {
        // Schedule navigation on the event loop.
        base::PostTaskWithTraits(FROM_HERE, {content::BrowserThread::UI},
                                 base::BindOnce(navigate, std::move(weakThis), std::move(params)));
    } else {
        navigate(std::move(weakThis), params);
    }
}

void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl)
{
    if (!isInitialized())
        loadDefault();
    else
        setLifecycleState(LifecycleState::Active);

    CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost());

    QByteArray encodedData = data.toPercentEncoding();
    std::string urlString;
    if (!mimeType.isEmpty())
        urlString = std::string("data:") + mimeType.toStdString() + std::string(",");
    else
        urlString = std::string("data:text/plain;charset=US-ASCII,");
    urlString.append(encodedData.constData(), encodedData.length());

    GURL dataUrlToLoad(urlString);
    if (dataUrlToLoad.spec().size() > url::kMaxURLChars) {
        m_adapterClient->loadFinished(false, baseUrl, false, net::ERR_ABORTED);
        return;
    }
    content::NavigationController::LoadURLParams params((dataUrlToLoad));
    params.load_type = content::NavigationController::LOAD_TYPE_DATA;
    params.base_url_for_data_url = toGurl(baseUrl);
    params.virtual_url_for_data_url = baseUrl.isEmpty() ? GURL(url::kAboutBlankURL) : toGurl(baseUrl);
    params.can_load_local_resources = true;
    params.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_API);
    params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;
    m_webContents->GetController().LoadURLWithParams(params);
    focusIfNecessary();
    m_webContents->CollapseSelection();
}

void WebContentsAdapter::save(const QString &filePath, int savePageFormat)
{
    CHECK_INITIALIZED();
    m_webContentsDelegate->setSavePageInfo(SavePageInfo(filePath, savePageFormat));
    m_webContents->OnSavePage();
}

QUrl WebContentsAdapter::activeUrl() const
{
    CHECK_INITIALIZED(QUrl());
    return m_webContentsDelegate->url(webContents());
}

QUrl WebContentsAdapter::requestedUrl() const
{
    CHECK_INITIALIZED(QUrl());
    content::NavigationEntry* entry = m_webContents->GetController().GetVisibleEntry();
    content::NavigationEntry* pendingEntry = m_webContents->GetController().GetPendingEntry();

    if (entry) {
        if (!entry->GetOriginalRequestURL().is_empty())
            return toQt(entry->GetOriginalRequestURL());

        if (pendingEntry && pendingEntry == entry)
            return toQt(entry->GetURL());
    }
    return QUrl();
}

QUrl WebContentsAdapter::iconUrl() const
{
    CHECK_INITIALIZED(QUrl());
    if (content::NavigationEntry* entry = m_webContents->GetController().GetVisibleEntry()) {
        content::FaviconStatus &favicon = entry->GetFavicon();
        if (favicon.valid)
            return toQt(favicon.url);
    }
    return QUrl();
}

QString WebContentsAdapter::pageTitle() const
{
    CHECK_INITIALIZED(QString());
    return m_webContentsDelegate->title();
}

QString WebContentsAdapter::selectedText() const
{
    CHECK_INITIALIZED(QString());
    if (auto *rwhv = m_webContents->GetRenderWidgetHostView())
        return toQt(rwhv->GetSelectedText());
    return QString();
}

void WebContentsAdapter::undo()
{
    CHECK_INITIALIZED();
    m_webContents->Undo();
}

void WebContentsAdapter::redo()
{
    CHECK_INITIALIZED();
    m_webContents->Redo();
}

void WebContentsAdapter::cut()
{
    CHECK_INITIALIZED();
    m_webContents->Cut();
}

void WebContentsAdapter::copy()
{
    CHECK_INITIALIZED();
    m_webContents->Copy();
}

void WebContentsAdapter::paste()
{
    CHECK_INITIALIZED();
    m_webContents->Paste();
}

void WebContentsAdapter::pasteAndMatchStyle()
{
    CHECK_INITIALIZED();
    m_webContents->PasteAndMatchStyle();
}

void WebContentsAdapter::selectAll()
{
    CHECK_INITIALIZED();
    m_webContents->SelectAll();
}

void WebContentsAdapter::requestClose()
{
    CHECK_INITIALIZED();
    m_webContents->DispatchBeforeUnload(false /* auto_cancel */);
}

void WebContentsAdapter::unselect()
{
    CHECK_INITIALIZED();
    m_webContents->CollapseSelection();
}

void WebContentsAdapter::navigateBack()
{
    CHECK_INITIALIZED();
    CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost());
    if (!m_webContents->GetController().CanGoBack())
        return;
    m_webContents->GetController().GoBack();
    focusIfNecessary();
}

void WebContentsAdapter::navigateForward()
{
    CHECK_INITIALIZED();
    CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost());
    if (!m_webContents->GetController().CanGoForward())
        return;
    m_webContents->GetController().GoForward();
    focusIfNecessary();
}

void WebContentsAdapter::navigateToIndex(int offset)
{
    CHECK_INITIALIZED();
    CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost());
    m_webContents->GetController().GoToIndex(offset);
    focusIfNecessary();
}

void WebContentsAdapter::navigateToOffset(int offset)
{
    CHECK_INITIALIZED();
    CHECK_VALID_RENDER_WIDGET_HOST_VIEW(m_webContents->GetRenderViewHost());
    m_webContents->GetController().GoToOffset(offset);
    focusIfNecessary();
}

int WebContentsAdapter::navigationEntryCount()
{
    CHECK_INITIALIZED(0);
    return m_webContents->GetController().GetEntryCount();
}

int WebContentsAdapter::currentNavigationEntryIndex()
{
    CHECK_INITIALIZED(0);
    return m_webContents->GetController().GetCurrentEntryIndex();
}

QUrl WebContentsAdapter::getNavigationEntryOriginalUrl(int index)
{
    CHECK_INITIALIZED(QUrl());
    content::NavigationEntry *entry = m_webContents->GetController().GetEntryAtIndex(index);
    return entry ? toQt(entry->GetOriginalRequestURL()) : QUrl();
}

QUrl WebContentsAdapter::getNavigationEntryUrl(int index)
{
    CHECK_INITIALIZED(QUrl());
    content::NavigationEntry *entry = m_webContents->GetController().GetEntryAtIndex(index);
    return entry ? toQt(entry->GetURL()) : QUrl();
}

QString WebContentsAdapter::getNavigationEntryTitle(int index)
{
    CHECK_INITIALIZED(QString());
    content::NavigationEntry *entry = m_webContents->GetController().GetEntryAtIndex(index);
    return entry ? toQt(entry->GetTitle()) : QString();
}

QDateTime WebContentsAdapter::getNavigationEntryTimestamp(int index)
{
    CHECK_INITIALIZED(QDateTime());
    content::NavigationEntry *entry = m_webContents->GetController().GetEntryAtIndex(index);
    return entry ? toQt(entry->GetTimestamp()) : QDateTime();
}

QUrl WebContentsAdapter::getNavigationEntryIconUrl(int index)
{
    CHECK_INITIALIZED(QUrl());
    content::NavigationEntry *entry = m_webContents->GetController().GetEntryAtIndex(index);
    if (!entry)
        return QUrl();
    content::FaviconStatus &favicon = entry->GetFavicon();
    return favicon.valid ? toQt(favicon.url) : QUrl();
}

void WebContentsAdapter::clearNavigationHistory()
{
    CHECK_INITIALIZED();
    if (m_webContents->GetController().CanPruneAllButLastCommitted())
        m_webContents->GetController().PruneAllButLastCommitted();
}

void WebContentsAdapter::serializeNavigationHistory(QDataStream &output)
{
    CHECK_INITIALIZED();
    QtWebEngineCore::serializeNavigationHistory(m_webContents->GetController(), output);
}

void WebContentsAdapter::setZoomFactor(qreal factor)
{
    CHECK_INITIALIZED();
    if (factor < content::kMinimumZoomFactor || factor > content::kMaximumZoomFactor)
        return;

    double zoomLevel = content::ZoomFactorToZoomLevel(static_cast<double>(factor));
    content::HostZoomMap *zoomMap = content::HostZoomMap::GetForWebContents(m_webContents.get());

    if (zoomMap) {
        int render_process_id = m_webContents->GetMainFrame()->GetProcess()->GetID();
        int render_view_id = m_webContents->GetRenderViewHost()->GetRoutingID();
        zoomMap->SetTemporaryZoomLevel(render_process_id, render_view_id, zoomLevel);
    }
}

qreal WebContentsAdapter::currentZoomFactor() const
{
    CHECK_INITIALIZED(1);
    return content::ZoomLevelToZoomFactor(content::HostZoomMap::GetZoomLevel(m_webContents.get()));
}

ProfileQt* WebContentsAdapter::profile()
{
    return m_profileAdapter ? m_profileAdapter->profile() : m_webContents ?
                                         static_cast<ProfileQt*>(m_webContents->GetBrowserContext()) : nullptr;
}

ProfileAdapter* WebContentsAdapter::profileAdapter()
{
    return m_profileAdapter ? m_profileAdapter : m_webContents ?
                    static_cast<ProfileQt*>(m_webContents->GetBrowserContext())->profileAdapter() : nullptr;
}

#ifndef QT_NO_ACCESSIBILITY
QAccessibleInterface *WebContentsAdapter::browserAccessible()
{
    CHECK_INITIALIZED(nullptr);
    content::RenderViewHost *rvh = m_webContents->GetRenderViewHost();
    Q_ASSERT(rvh);
    content::BrowserAccessibilityManager *manager = static_cast<content::RenderFrameHostImpl*>(rvh->GetMainFrame())->GetOrCreateBrowserAccessibilityManager();
    if (!manager) // FIXME!
        return nullptr;
    content::BrowserAccessibility *acc = manager->GetRoot();

    return content::toQAccessibleInterface(acc);
}
#endif // QT_NO_ACCESSIBILITY

void WebContentsAdapter::runJavaScript(const QString &javaScript, quint32 worldId)
{
    CHECK_INITIALIZED();
    content::RenderViewHost *rvh = m_webContents->GetRenderViewHost();
    Q_ASSERT(rvh);
//    static_cast<content::RenderFrameHostImpl *>(rvh->GetMainFrame())->NotifyUserActivation();
    if (worldId == 0) {
        rvh->GetMainFrame()->ExecuteJavaScript(toString16(javaScript), base::NullCallback());
        return;
    }

    content::RenderFrameHost::JavaScriptResultCallback callback = base::BindOnce(&callbackOnEvaluateJS, m_adapterClient, CallbackDirectory::NoCallbackId);
    rvh->GetMainFrame()->ExecuteJavaScriptInIsolatedWorld(toString16(javaScript), std::move(callback), worldId);
}

quint64 WebContentsAdapter::runJavaScriptCallbackResult(const QString &javaScript, quint32 worldId)
{
    CHECK_INITIALIZED(0);
    content::RenderViewHost *rvh = m_webContents->GetRenderViewHost();
    Q_ASSERT(rvh);
//    static_cast<content::RenderFrameHostImpl *>(rvh->GetMainFrame())->NotifyUserActivation();
    content::RenderFrameHost::JavaScriptResultCallback callback = base::BindOnce(&callbackOnEvaluateJS, m_adapterClient, m_nextRequestId);
    if (worldId == 0)
        rvh->GetMainFrame()->ExecuteJavaScript(toString16(javaScript), std::move(callback));
    else
        rvh->GetMainFrame()->ExecuteJavaScriptInIsolatedWorld(toString16(javaScript), std::move(callback), worldId);
    return m_nextRequestId++;
}

quint64 WebContentsAdapter::fetchDocumentMarkup()
{
    CHECK_INITIALIZED(0);
    m_renderViewObserverHost->fetchDocumentMarkup(m_nextRequestId);
    return m_nextRequestId++;
}

quint64 WebContentsAdapter::fetchDocumentInnerText()
{
    CHECK_INITIALIZED(0);
    m_renderViewObserverHost->fetchDocumentInnerText(m_nextRequestId);
    return m_nextRequestId++;
}

void WebContentsAdapter::updateWebPreferences(const content::WebPreferences & webPreferences)
{
    CHECK_INITIALIZED();
    m_webContents->GetRenderViewHost()->UpdateWebkitPreferences(webPreferences);

    // In case of updating preferences during navigation, there might be a pending RVH what will
    // be active on successful navigation.
    content::RenderFrameHost *pendingRFH = (static_cast<content::WebContentsImpl*>(m_webContents.get()))->GetPendingMainFrame();
    if (pendingRFH) {
        content::RenderViewHost *pendingRVH = pendingRFH->GetRenderViewHost();
        Q_ASSERT(pendingRVH);
        pendingRVH->UpdateWebkitPreferences(webPreferences);
    }
}

void WebContentsAdapter::download(const QUrl &url, const QString &suggestedFileName,
                                  const QUrl &referrerUrl,
                                  ReferrerPolicy referrerPolicy)
{
    CHECK_INITIALIZED();
    content::BrowserContext *bctx = m_webContents->GetBrowserContext();
    content::DownloadManager *dlm =  content::BrowserContext::GetDownloadManager(bctx);
    DownloadManagerDelegateQt *dlmd = m_profileAdapter->downloadManagerDelegate();

    if (!dlm)
        return;

    dlmd->markNextDownloadAsUserRequested();
    dlm->SetDelegate(dlmd);

    net::NetworkTrafficAnnotationTag traffic_annotation =
        net::DefineNetworkTrafficAnnotation(
            "WebContentsAdapter::download", R"(
            semantics {
              sender: "User"
              description:
                "User requested download"
              trigger: "User."
              data: "Anything."
              destination: OTHER
            }
            policy {
              cookies_allowed: YES
              cookies_store: "user"
              setting:
                "It's possible not to use this feature."
            })");
    GURL gurl = toGurl(url);
    std::unique_ptr<download::DownloadUrlParameters> params(
        content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame(webContents(), gurl, traffic_annotation));

    params->set_suggested_name(toString16(suggestedFileName));

    // referrer logic based on chrome/browser/renderer_context_menu/render_view_context_menu.cc:
    content::Referrer referrer = content::Referrer::SanitizeForRequest(
                gurl,
                content::Referrer(toGurl(referrerUrl).GetAsReferrer(),
                                  static_cast<network::mojom::ReferrerPolicy>(referrerPolicy)));

    params->set_referrer(referrer.url);
    params->set_referrer_policy(content::Referrer::ReferrerPolicyForUrlRequest(referrer.policy));

    dlm->DownloadUrl(std::move(params));
}

bool WebContentsAdapter::isAudioMuted() const
{
    CHECK_INITIALIZED(false);
    return m_webContents->IsAudioMuted();
}

void WebContentsAdapter::setAudioMuted(bool muted)
{
    CHECK_INITIALIZED();
    m_webContents->SetAudioMuted(muted);
}

bool WebContentsAdapter::recentlyAudible() const
{
    CHECK_INITIALIZED(false);
    return m_webContents->IsCurrentlyAudible();
}

void WebContentsAdapter::copyImageAt(const QPoint &location)
{
    CHECK_INITIALIZED();
    m_webContents->GetRenderViewHost()->GetMainFrame()->CopyImageAt(location.x(), location.y());
}

static blink::WebMediaPlayerAction::Type toBlinkMediaPlayerActionType(WebContentsAdapter::MediaPlayerAction action)
{
    switch (action) {
    case WebContentsAdapter::MediaPlayerPlay:
        return blink::WebMediaPlayerAction::Type::kPlay;
    case WebContentsAdapter::MediaPlayerMute:
        return blink::WebMediaPlayerAction::Type::kMute;
    case WebContentsAdapter::MediaPlayerLoop:
        return blink::WebMediaPlayerAction::Type::kLoop;
    case WebContentsAdapter::MediaPlayerControls:
        return blink::WebMediaPlayerAction::Type::kControls;
    case WebContentsAdapter::MediaPlayerNoAction:
        break;
    }
    NOTREACHED();
    return (blink::WebMediaPlayerAction::Type)-1;
}

void WebContentsAdapter::executeMediaPlayerActionAt(const QPoint &location, MediaPlayerAction action, bool enable)
{
    CHECK_INITIALIZED();
    if (action == MediaPlayerNoAction)
        return;
    blink::WebMediaPlayerAction blinkAction(toBlinkMediaPlayerActionType(action), enable);
    m_webContents->GetRenderViewHost()->GetMainFrame()->ExecuteMediaPlayerActionAtLocation(toGfx(location), blinkAction);
}

void WebContentsAdapter::inspectElementAt(const QPoint &location)
{
    Q_ASSERT(isInitialized());
    if (m_devToolsFrontend) {
        m_devToolsFrontend->InspectElementAt(location.x(), location.y());
        return;
    }
    if (content::DevToolsAgentHost::HasFor(m_webContents.get()))
        content::DevToolsAgentHost::GetOrCreateFor(m_webContents.get())->InspectElement(
                    m_webContents->GetFocusedFrame(), location.x(), location.y());
}

bool WebContentsAdapter::hasInspector() const
{
    CHECK_INITIALIZED(false);
    if (m_devToolsFrontend)
        return true;
    if (content::DevToolsAgentHost::HasFor(m_webContents.get()))
        return content::DevToolsAgentHost::GetOrCreateFor(m_webContents.get())->IsAttached();
    return false;
}

bool WebContentsAdapter::isInspector() const
{
    return m_inspector;
}

void WebContentsAdapter::setInspector(bool inspector)
{
    m_inspector = inspector;
    if (inspector)
        setLifecycleState(LifecycleState::Active);
}

void WebContentsAdapter::openDevToolsFrontend(QSharedPointer<WebContentsAdapter> frontendAdapter)
{
    Q_ASSERT(isInitialized());
    if (m_devToolsFrontend && frontendAdapter->webContents() &&
            m_devToolsFrontend->frontendDelegate() == frontendAdapter->webContents()->GetDelegate())
        return;

    if (m_devToolsFrontend) {
        m_devToolsFrontend->DisconnectFromTarget();
        m_devToolsFrontend->Close();
    }

    setLifecycleState(LifecycleState::Active);

    m_devToolsFrontend = DevToolsFrontendQt::Show(frontendAdapter, m_webContents.get());
    updateRecommendedState();
}

void WebContentsAdapter::closeDevToolsFrontend()
{
    if (m_devToolsFrontend) {
        m_devToolsFrontend->DisconnectFromTarget();
        m_devToolsFrontend->Close();
    }
}

void WebContentsAdapter::devToolsFrontendDestroyed(DevToolsFrontendQt *frontend)
{
    Q_ASSERT(frontend == m_devToolsFrontend);
    Q_UNUSED(frontend);
    m_devToolsFrontend = nullptr;
    updateRecommendedState();
}

void WebContentsAdapter::exitFullScreen()
{
    CHECK_INITIALIZED();
    m_webContents->ExitFullscreen(false);
}

void WebContentsAdapter::changedFullScreen()
{
    CHECK_INITIALIZED();
    m_webContents->NotifyFullscreenChanged(false);
}

void WebContentsAdapter::wasShown()
{
    CHECK_INITIALIZED();
    m_webContents->WasShown();
}

void WebContentsAdapter::wasHidden()
{
    CHECK_INITIALIZED();
    m_webContents->WasHidden();
}

void WebContentsAdapter::printToPDF(const QPageLayout &pageLayout, const QString &filePath)
{
#if QT_CONFIG(webengine_printing_and_pdf)
    CHECK_INITIALIZED();
    PrintViewManagerQt::PrintToPDFFileCallback callback = base::Bind(&callbackOnPdfSavingFinished,
                                                                m_adapterClient,
                                                                filePath);
    PrintViewManagerQt::FromWebContents(m_webContents.get())->PrintToPDFFileWithCallback(pageLayout,
                                                                                   true,
                                                                                   filePath,
                                                                                   callback);
#endif // QT_CONFIG(webengine_printing_and_pdf)
}

quint64 WebContentsAdapter::printToPDFCallbackResult(const QPageLayout &pageLayout,
                                                     bool colorMode,
                                                     bool useCustomMargins)
{
#if QT_CONFIG(webengine_printing_and_pdf)
    CHECK_INITIALIZED(0);
    PrintViewManagerQt::PrintToPDFCallback callback = base::Bind(&callbackOnPrintingFinished,
                                                                 m_adapterClient,
                                                                 m_nextRequestId);
    PrintViewManagerQt::FromWebContents(m_webContents.get())->PrintToPDFWithCallback(pageLayout,
                                                                               colorMode,
                                                                               useCustomMargins,
                                                                               callback);
    return m_nextRequestId++;
#else
    Q_UNUSED(pageLayout);
    Q_UNUSED(colorMode);
    return 0;
#endif // QT_CONFIG(webengine_printing_and_pdf)
}

QPointF WebContentsAdapter::lastScrollOffset() const
{
    CHECK_INITIALIZED(QPointF());
    if (RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView()))
        return toQt(rwhv->lastScrollOffset());
    return QPointF();
}

QSizeF WebContentsAdapter::lastContentsSize() const
{
    CHECK_INITIALIZED(QSizeF());
    if (RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView()))
        return toQt(rwhv->lastContentsSize());
    return QSizeF();
}

void WebContentsAdapter::grantMediaAccessPermission(const QUrl &securityOrigin, WebContentsAdapterClient::MediaRequestFlags flags)
{
    CHECK_INITIALIZED();
    // Let the permission manager remember the reply.
    if (flags & WebContentsAdapterClient::MediaAudioCapture)
        m_profileAdapter->permissionRequestReply(securityOrigin, ProfileAdapter::AudioCapturePermission, true);
    if (flags & WebContentsAdapterClient::MediaVideoCapture)
        m_profileAdapter->permissionRequestReply(securityOrigin, ProfileAdapter::VideoCapturePermission, true);
    MediaCaptureDevicesDispatcher::GetInstance()->handleMediaAccessPermissionResponse(m_webContents.get(), securityOrigin, flags);
}

void WebContentsAdapter::runGeolocationRequestCallback(const QUrl &securityOrigin, bool allowed)
{
    CHECK_INITIALIZED();
    m_profileAdapter->permissionRequestReply(securityOrigin, ProfileAdapter::GeolocationPermission, allowed);
}

void WebContentsAdapter::runUserNotificationRequestCallback(const QUrl &securityOrigin, bool allowed)
{
    CHECK_INITIALIZED();
    m_profileAdapter->permissionRequestReply(securityOrigin, ProfileAdapter::NotificationPermission, allowed);
}

void WebContentsAdapter::grantMouseLockPermission(bool granted)
{
    CHECK_INITIALIZED();

    if (granted) {
        if (RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView()))
            rwhv->Focus();
        else
            granted = false;
    }

    m_webContents->GotResponseToLockMouseRequest(granted);
}

void WebContentsAdapter::setBackgroundColor(const QColor &color)
{
    CHECK_INITIALIZED();
    if (content::RenderWidgetHostView *rwhv = m_webContents->GetRenderWidgetHostView())
        rwhv->SetBackgroundColor(toSk(color));
}

content::WebContents *WebContentsAdapter::webContents() const
{
    return m_webContents.get();
}

#if QT_CONFIG(webengine_webchannel)
QWebChannel *WebContentsAdapter::webChannel() const
{
    return m_webChannel;
}

void WebContentsAdapter::setWebChannel(QWebChannel *channel, uint worldId)
{
    CHECK_INITIALIZED();
    if (m_webChannel == channel && m_webChannelWorld == worldId)
        return;

    if (!m_webChannelTransport.get())
        m_webChannelTransport.reset(new WebChannelIPCTransportHost(m_webContents.get(), worldId));
    else {
        if (m_webChannel != channel)
            m_webChannel->disconnectFrom(m_webChannelTransport.get());
        if (m_webChannelWorld != worldId)
            m_webChannelTransport->setWorldId(worldId);
    }

    m_webChannel = channel;
    m_webChannelWorld = worldId;

    if (!channel) {
        m_webChannelTransport.reset();
        return;
    }
    channel->connectTo(m_webChannelTransport.get());
}
#endif

#if QT_CONFIG(draganddrop)
static QMimeData *mimeDataFromDropData(const content::DropData &dropData)
{
    QMimeData *mimeData = new QMimeData();
    if (!dropData.text.is_null())
        mimeData->setText(toQt(dropData.text.string()));
    if (!dropData.html.is_null())
        mimeData->setHtml(toQt(dropData.html.string()));
    if (dropData.url.is_valid())
        mimeData->setUrls(QList<QUrl>() << toQt(dropData.url));
    if (!dropData.custom_data.empty()) {
        base::Pickle pickle;
        ui::WriteCustomDataToPickle(dropData.custom_data, &pickle);
        mimeData->setData(QLatin1String(ui::kMimeTypeWebCustomData), QByteArray((const char*)pickle.data(), pickle.size()));
    }
    return mimeData;
}

static blink::WebDragOperationsMask toWeb(const Qt::DropActions action)
{
    int result = blink::kWebDragOperationNone;
    if (action & Qt::CopyAction)
        result |= blink::kWebDragOperationCopy;
    if (action & Qt::LinkAction)
        result |= blink::kWebDragOperationLink;
    if (action & Qt::MoveAction)
        result |= blink::kWebDragOperationMove;
    return static_cast<blink::WebDragOperationsMask>(result);
}

void WebContentsAdapter::startDragging(QObject *dragSource, const content::DropData &dropData,
                                       Qt::DropActions allowedActions, const QPixmap &pixmap,
                                       const QPoint &offset)
{
    CHECK_INITIALIZED();

    if (m_currentDropData)
        return;

    // Clear certain fields of the drop data to not run into DCHECKs
    // of DropDataToWebDragData in render_view_impl.cc.
    m_currentDropData.reset(new content::DropData(dropData));
    m_currentDropData->download_metadata.clear();
    m_currentDropData->file_contents.clear();
    m_currentDropData->file_contents_content_disposition.clear();

    m_currentDropAction = blink::kWebDragOperationNone;
    QDrag *drag = new QDrag(dragSource);    // will be deleted by Qt's DnD implementation
    bool dValid = true;
    QMetaObject::Connection onDestroyed = QObject::connect(dragSource, &QObject::destroyed, [&dValid](){
        dValid = false;
        QDrag::cancel();
    });

    QMimeData *mimeData = mimeDataFromDropData(*m_currentDropData);
    handleDropDataFileContents(dropData, mimeData);

    drag->setMimeData(mimeData);
    if (!pixmap.isNull()) {
        drag->setPixmap(pixmap);
        drag->setHotSpot(offset);
    }

    {
        base::MessageLoopCurrent::ScopedNestableTaskAllower allow;
        drag->exec(allowedActions);
    }

    QObject::disconnect(onDestroyed);
    if (dValid) {
        if (m_webContents) {
            content::RenderViewHost *rvh = m_webContents->GetRenderViewHost();
            if (rvh) {
                rvh->GetWidget()->DragSourceEndedAt(gfx::PointF(m_lastDragClientPos.x(), m_lastDragClientPos.y()),
                                                    gfx::PointF(m_lastDragScreenPos.x(), m_lastDragScreenPos.y()),
                                                    blink::WebDragOperation(m_currentDropAction));
                rvh->GetWidget()->DragSourceSystemDragEnded();
            }
        }
        m_currentDropData.reset();
    }
}

bool WebContentsAdapter::handleDropDataFileContents(const content::DropData &dropData,
                                                    QMimeData *mimeData)
{
    CHECK_INITIALIZED(false);
    if (dropData.file_contents.empty())
        return false;

    if (!m_dndTmpDir) {
        m_dndTmpDir.reset(new QTemporaryDir);
        if (!m_dndTmpDir->isValid()) {
            m_dndTmpDir.reset();
            return false;
        }
    }

    const auto maybeFilename = dropData.GetSafeFilenameForImageFileContents();
    const QString fileName = maybeFilename ? toQt(maybeFilename->AsUTF16Unsafe()) : QString();
    const QString &filePath = m_dndTmpDir->filePath(fileName);
    QFile file(filePath);
    if (!file.open(QIODevice::WriteOnly)) {
        qWarning("Cannot write temporary file %s.", qUtf8Printable(filePath));
        return false;
    }
    file.write(QByteArray::fromStdString(dropData.file_contents));

    const QUrl &targetUrl = QUrl::fromLocalFile(filePath);
    mimeData->setUrls(QList<QUrl>{targetUrl});
    return true;
}

static void fillDropDataFromMimeData(content::DropData *dropData, const QMimeData *mimeData)
{
    Q_ASSERT(dropData->filenames.empty());
    const QList<QUrl> urls = mimeData->urls();
    for (const QUrl &url : urls) {
        if (url.isLocalFile()) {
            ui::FileInfo uifi;
            uifi.path = toFilePath(url.toLocalFile());
            dropData->filenames.push_back(uifi);
        }
    }
    if (!dropData->filenames.empty())
        return;
    if (mimeData->hasHtml())
        dropData->html = toNullableString16(mimeData->html());
    if (mimeData->hasText())
        dropData->text = toNullableString16(mimeData->text());
    if (mimeData->hasFormat(QLatin1String(ui::kMimeTypeWebCustomData))) {
        QByteArray customData = mimeData->data(QLatin1String(ui::kMimeTypeWebCustomData));
        ui::ReadCustomDataIntoMap(customData.constData(), customData.length(), &dropData->custom_data);
    }
}

Qt::DropAction toQt(blink::WebDragOperation op)
{
    if (op & blink::kWebDragOperationCopy)
        return Qt::CopyAction;
    if (op & blink::kWebDragOperationLink)
        return Qt::LinkAction;
    if (op & blink::kWebDragOperationMove || op & blink::kWebDragOperationDelete)
        return Qt::MoveAction;
    return Qt::IgnoreAction;
}

static int toWeb(Qt::MouseButtons buttons)
{
    int result = 0;
    if (buttons & Qt::LeftButton)
        result |= blink::WebInputEvent::kLeftButtonDown;
    if (buttons & Qt::RightButton)
        result |= blink::WebInputEvent::kRightButtonDown;
    if (buttons & Qt::MiddleButton)
        result |= blink::WebInputEvent::kMiddleButtonDown;
    return result;
}

static int toWeb(Qt::KeyboardModifiers modifiers)
{
    int result = 0;
    if (modifiers & Qt::ShiftModifier)
        result |= blink::WebInputEvent::kShiftKey;
    if (modifiers & Qt::ControlModifier)
        result |= blink::WebInputEvent::kControlKey;
    if (modifiers & Qt::AltModifier)
        result |= blink::WebInputEvent::kAltKey;
    if (modifiers & Qt::MetaModifier)
        result |= blink::WebInputEvent::kMetaKey;
    return result;
}

void WebContentsAdapter::enterDrag(QDragEnterEvent *e, const QPointF &screenPos)
{
    CHECK_INITIALIZED();

    if (!m_currentDropData) {
        // The drag originated outside the WebEngineView.
        m_currentDropData.reset(new content::DropData);
        fillDropDataFromMimeData(m_currentDropData.get(), e->mimeData());
    }

    content::RenderViewHost *rvh = m_webContents->GetRenderViewHost();
    rvh->GetWidget()->FilterDropData(m_currentDropData.get());
    rvh->GetWidget()->DragTargetDragEnter(*m_currentDropData, toGfx(e->posF()), toGfx(screenPos),
                                          toWeb(e->possibleActions()),
                                          toWeb(e->mouseButtons()) | toWeb(e->keyboardModifiers()));
}

Qt::DropAction WebContentsAdapter::updateDragPosition(QDragMoveEvent *e, const QPointF &screenPos)
{
    CHECK_INITIALIZED(Qt::DropAction());
    content::RenderViewHost *rvh = m_webContents->GetRenderViewHost();
    m_lastDragClientPos = e->posF();
    m_lastDragScreenPos = screenPos;
    rvh->GetWidget()->DragTargetDragOver(toGfx(m_lastDragClientPos), toGfx(m_lastDragScreenPos), toWeb(e->possibleActions()),
                                         toWeb(e->mouseButtons()) | toWeb(e->keyboardModifiers()));
    waitForUpdateDragActionCalled();
    return toQt(blink::WebDragOperation(m_currentDropAction));
}

void WebContentsAdapter::waitForUpdateDragActionCalled()
{
    CHECK_INITIALIZED();
    const qint64 timeout = 3000;
    QElapsedTimer t;
    t.start();
    auto seqMan = base::MessageLoopCurrent::GetCurrentSequenceManagerImpl();
    base::MessagePump::Delegate *delegate =
            static_cast<base::sequence_manager::internal::ThreadControllerWithMessagePumpImpl *>(
                seqMan->controller_.get());

    DCHECK(delegate);
    m_updateDragActionCalled = false;
    for (;;) {
        while (delegate->DoWork() && !m_updateDragActionCalled) {}
        if (m_updateDragActionCalled)
            break;
        if (t.hasExpired(timeout)) {
            qWarning("WebContentsAdapter::updateDragAction was not called within %d ms.",
                     static_cast<int>(timeout));
            return;
        }
        base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
    }
}

void WebContentsAdapter::updateDragAction(int action)
{
    CHECK_INITIALIZED();
    m_updateDragActionCalled = true;
    m_currentDropAction = static_cast<blink::WebDragOperation>(action);
}

void WebContentsAdapter::endDragging(QDropEvent *e, const QPointF &screenPos)
{
    CHECK_INITIALIZED();
    content::RenderViewHost *rvh = m_webContents->GetRenderViewHost();
    rvh->GetWidget()->FilterDropData(m_currentDropData.get());
    m_lastDragClientPos = e->posF();
    m_lastDragScreenPos = screenPos;
    rvh->GetWidget()->DragTargetDrop(*m_currentDropData, toGfx(m_lastDragClientPos), toGfx(m_lastDragScreenPos),
                                     toWeb(e->mouseButtons()) | toWeb(e->keyboardModifiers()));

    m_currentDropData.reset();
}

void WebContentsAdapter::leaveDrag()
{
    CHECK_INITIALIZED();
    content::RenderViewHost *rvh = m_webContents->GetRenderViewHost();
    rvh->GetWidget()->DragTargetDragLeave(toGfx(m_lastDragClientPos), toGfx(m_lastDragScreenPos));
    m_currentDropData.reset();
}
#endif // QT_CONFIG(draganddrop)

void WebContentsAdapter::replaceMisspelling(const QString &word)
{
#if QT_CONFIG(webengine_spellchecker)
    CHECK_INITIALIZED();
    m_webContents->ReplaceMisspelling(toString16(word));
#endif
}

void WebContentsAdapter::focusIfNecessary()
{
    CHECK_INITIALIZED();
    const WebEngineSettings *settings = m_adapterClient->webEngineSettings();
    bool focusOnNavigation = settings->testAttribute(WebEngineSettings::FocusOnNavigationEnabled);
    if (focusOnNavigation)
        m_webContents->Focus();
}

bool WebContentsAdapter::hasFocusedFrame() const
{
    CHECK_INITIALIZED(false);
    return m_webContents->GetFocusedFrame() != nullptr;
}

WebContentsAdapterClient::RenderProcessTerminationStatus
WebContentsAdapterClient::renderProcessExitStatus(int terminationStatus) {
    auto status = WebContentsAdapterClient::RenderProcessTerminationStatus(-1);
    switch (terminationStatus) {
    case base::TERMINATION_STATUS_NORMAL_TERMINATION:
        status = WebContentsAdapterClient::NormalTerminationStatus;
        break;
    case base::TERMINATION_STATUS_ABNORMAL_TERMINATION:
        status = WebContentsAdapterClient::AbnormalTerminationStatus;
        break;
    case base::TERMINATION_STATUS_PROCESS_WAS_KILLED:
#if defined(OS_CHROMEOS)
    case base::TERMINATION_STATUS_PROCESS_WAS_KILLED_BY_OOM:
#endif
        status = WebContentsAdapterClient::KilledTerminationStatus;
        break;
    case base::TERMINATION_STATUS_PROCESS_CRASHED:
#if defined(OS_ANDROID)
    case base::TERMINATION_STATUS_OOM_PROTECTED:
#endif
        status = WebContentsAdapterClient::CrashedTerminationStatus;
        break;
    case base::TERMINATION_STATUS_STILL_RUNNING:
    case base::TERMINATION_STATUS_MAX_ENUM:
        Q_UNREACHABLE();
        break;
    }

    return status;
}

FaviconManager *WebContentsAdapter::faviconManager()
{
    CHECK_INITIALIZED(nullptr);
    return m_webContentsDelegate->faviconManager();
}

FindTextHelper *WebContentsAdapter::findTextHelper()
{
    CHECK_INITIALIZED(nullptr);
    return m_webContentsDelegate->findTextHelper();
}

void WebContentsAdapter::viewSource()
{
    CHECK_INITIALIZED();
    m_webContents->GetMainFrame()->ViewSource();
}

bool WebContentsAdapter::canViewSource()
{
    CHECK_INITIALIZED(false);
    return m_webContents->GetController().CanViewSource();
}

WebContentsAdapter::LifecycleState WebContentsAdapter::lifecycleState() const
{
    return m_lifecycleState;
}

void WebContentsAdapter::setLifecycleState(LifecycleState state)
{
    CHECK_INITIALIZED();

    LifecycleState from = m_lifecycleState;
    LifecycleState to = state;

    const auto warn = [from, to](const char *reason) {
        static const char *names[] { "Active", "Frozen", "Discarded" };
        qWarning("setLifecycleState: failed to transition from %s to %s state: %s",
                 names[(int)from], names[(int)to], reason);
    };

    if (from == to)
        return;

    if (from == LifecycleState::Active) {
        if (isVisible()) {
            warn("page is visible");
            return;
        }
        if (hasInspector() || isInspector()) {
            warn("DevTools open");
            return;
        }
    }

    if (from == LifecycleState::Discarded && to != LifecycleState::Active) {
        warn("illegal transition");
        return;
    }

    // Prevent recursion due to initializationFinished() in undiscard().
    m_lifecycleState = to;

    switch (to) {
    case LifecycleState::Active:
        if (from == LifecycleState::Frozen)
            unfreeze();
        else
            undiscard();
        break;
    case LifecycleState::Frozen:
        freeze();
        break;
    case LifecycleState::Discarded:
        discard();
        break;
    }

    m_adapterClient->lifecycleStateChanged(to);
    updateRecommendedState();
}

WebContentsAdapter::LifecycleState WebContentsAdapter::recommendedState() const
{
    return m_recommendedState;
}

WebContentsAdapter::LifecycleState WebContentsAdapter::determineRecommendedState() const
{
    CHECK_INITIALIZED(LifecycleState::Active);

    if (m_lifecycleState == LifecycleState::Discarded)
        return LifecycleState::Discarded;

    if (isVisible())
        return LifecycleState::Active;

    if (m_webContentsDelegate->loadingState() != WebContentsDelegateQt::LoadingState::Loaded)
        return LifecycleState::Active;

    if (recentlyAudible())
        return LifecycleState::Active;

    if (m_webContents->GetSiteInstance()->GetRelatedActiveContentsCount() > 1U)
        return LifecycleState::Active;

    if (hasInspector() || isInspector())
        return LifecycleState::Active;

    if (m_webContentsDelegate->isCapturingAudio() || m_webContentsDelegate->isCapturingVideo()
        || m_webContentsDelegate->isMirroring() || m_webContentsDelegate->isCapturingDesktop())
        return LifecycleState::Active;

    if (m_webContents->IsCrashed())
        return LifecycleState::Active;

    if (m_lifecycleState == LifecycleState::Active)
        return LifecycleState::Frozen;

    // Form input is not saved.
    if (m_webContents->GetPageImportanceSignals().had_form_interaction)
        return LifecycleState::Frozen;

    // Do not discard PDFs as they might contain entry that is not saved and they
    // don't remember their scrolling positions. See crbug.com/547286 and
    // crbug.com/65244.
    if (m_webContents->GetContentsMimeType() == "application/pdf")
        return LifecycleState::Frozen;

    return LifecycleState::Discarded;
}

void WebContentsAdapter::updateRecommendedState()
{
    LifecycleState newState = determineRecommendedState();
    if (m_recommendedState == newState)
        return;

    m_recommendedState = newState;
    m_adapterClient->recommendedStateChanged(newState);
}

bool WebContentsAdapter::isVisible() const
{
    CHECK_INITIALIZED(false);

    // Visibility::OCCLUDED is not used
    return m_webContents->GetVisibility() == content::Visibility::VISIBLE;
}

void WebContentsAdapter::setVisible(bool visible)
{
    CHECK_INITIALIZED();

    if (isVisible() == visible)
        return;

    if (visible) {
        setLifecycleState(LifecycleState::Active);
        wasShown();
    } else {
        Q_ASSERT(m_lifecycleState == LifecycleState::Active);
        wasHidden();
    }

    m_adapterClient->visibleChanged(visible);
    updateRecommendedState();
}

void WebContentsAdapter::freeze()
{
    m_webContents->SetPageFrozen(true);
}

void WebContentsAdapter::unfreeze()
{
    m_webContents->SetPageFrozen(false);
}

void WebContentsAdapter::discard()
{
    // Based on TabLifecycleUnitSource::TabLifecycleUnit::FinishDiscard

    if (m_webContents->IsLoading()) {
        m_webContentsDelegate->didFailLoad(m_webContentsDelegate->url(webContents()), net::Error::ERR_ABORTED,
                                           QStringLiteral("Discarded"));
    }

    content::WebContents::CreateParams createParams(m_profileAdapter->profile());
    createParams.initially_hidden = true;
    createParams.desired_renderer_state = content::WebContents::CreateParams::kNoRendererProcess;
    createParams.last_active_time = m_webContents->GetLastActiveTime();
    std::unique_ptr<content::WebContents> nullContents = content::WebContents::Create(createParams);
    std::unique_ptr<WebContentsDelegateQt> nullDelegate(new WebContentsDelegateQt(nullContents.get(), m_adapterClient));
    nullContents->GetController().CopyStateFrom(&m_webContents->GetController(),
                                                /* needs_reload */ false);
    nullDelegate->copyStateFrom(m_webContentsDelegate.get());
    nullContents->SetWasDiscarded(true);

    // Kill render process if this is the only page it's got.
    content::RenderProcessHost *renderProcessHost = m_webContents->GetMainFrame()->GetProcess();
    renderProcessHost->FastShutdownIfPossible(/* page_count */ 1u,
                                              /* skip_unload_handlers */ false);

#if QT_CONFIG(webengine_webchannel)
    if (m_webChannel)
        m_webChannel->disconnectFrom(m_webChannelTransport.get());
    m_webChannelTransport.reset();
    m_webChannel = nullptr;
    m_webChannelWorld = 0;
#endif
    m_renderViewObserverHost.reset();
    m_webContentsDelegate.reset();
    m_webContents.reset();

    m_webContents = std::move(nullContents);
    initializeRenderPrefs();
    m_webContentsDelegate = std::move(nullDelegate);
    m_renderViewObserverHost.reset(new RenderViewObserverHostQt(m_webContents.get(), m_adapterClient));
    WebContentsViewQt *contentsView =
            static_cast<WebContentsViewQt *>(static_cast<content::WebContentsImpl *>(m_webContents.get())->GetView());
    contentsView->setClient(m_adapterClient);
#if QT_CONFIG(webengine_printing_and_pdf)
    PrintViewManagerQt::CreateForWebContents(webContents());
#endif
#if BUILDFLAG(ENABLE_EXTENSIONS)
    extensions::ExtensionWebContentsObserverQt::CreateForWebContents(webContents());
#endif
}

void WebContentsAdapter::undiscard()
{
    m_webContents->GetController().SetNeedsReload();
    m_webContents->GetController().LoadIfNecessary();
    // Create a RenderView with the initial empty document
    content::RenderViewHost *rvh = m_webContents->GetRenderViewHost();
    Q_ASSERT(rvh);
    if (!rvh->IsRenderViewLive())
        static_cast<content::WebContentsImpl *>(m_webContents.get())
                ->CreateRenderViewForRenderManager(rvh, MSG_ROUTING_NONE, MSG_ROUTING_NONE,
                                                   base::UnguessableToken::Create(),
                                                   content::FrameReplicationState());
    m_webContentsDelegate->RenderViewHostChanged(nullptr, rvh);
    m_adapterClient->initializationFinished();
    m_adapterClient->selectionChanged();
}

ASSERT_ENUMS_MATCH(WebContentsAdapterClient::UnknownDisposition, WindowOpenDisposition::UNKNOWN)
ASSERT_ENUMS_MATCH(WebContentsAdapterClient::CurrentTabDisposition, WindowOpenDisposition::CURRENT_TAB)
ASSERT_ENUMS_MATCH(WebContentsAdapterClient::SingletonTabDisposition, WindowOpenDisposition::SINGLETON_TAB)
ASSERT_ENUMS_MATCH(WebContentsAdapterClient::NewForegroundTabDisposition, WindowOpenDisposition::NEW_FOREGROUND_TAB)
ASSERT_ENUMS_MATCH(WebContentsAdapterClient::NewBackgroundTabDisposition, WindowOpenDisposition::NEW_BACKGROUND_TAB)
ASSERT_ENUMS_MATCH(WebContentsAdapterClient::NewPopupDisposition, WindowOpenDisposition::NEW_POPUP)
ASSERT_ENUMS_MATCH(WebContentsAdapterClient::NewWindowDisposition, WindowOpenDisposition::NEW_WINDOW)
ASSERT_ENUMS_MATCH(WebContentsAdapterClient::SaveToDiskDisposition, WindowOpenDisposition::SAVE_TO_DISK)
ASSERT_ENUMS_MATCH(WebContentsAdapterClient::OffTheRecordDisposition, WindowOpenDisposition::OFF_THE_RECORD)
ASSERT_ENUMS_MATCH(WebContentsAdapterClient::IgnoreActionDisposition, WindowOpenDisposition::IGNORE_ACTION)

ASSERT_ENUMS_MATCH(ReferrerPolicy::Always, network::mojom::ReferrerPolicy::kAlways)
ASSERT_ENUMS_MATCH(ReferrerPolicy::Default, network::mojom::ReferrerPolicy::kDefault)
ASSERT_ENUMS_MATCH(ReferrerPolicy::NoReferrerWhenDowngrade, network::mojom::ReferrerPolicy::kNoReferrerWhenDowngrade)
ASSERT_ENUMS_MATCH(ReferrerPolicy::Never, network::mojom::ReferrerPolicy::kNever)
ASSERT_ENUMS_MATCH(ReferrerPolicy::Origin, network::mojom::ReferrerPolicy::kOrigin)
ASSERT_ENUMS_MATCH(ReferrerPolicy::OriginWhenCrossOrigin, network::mojom::ReferrerPolicy::kOriginWhenCrossOrigin)
ASSERT_ENUMS_MATCH(ReferrerPolicy::NoReferrerWhenDowngradeOriginWhenCrossOrigin, network::mojom::ReferrerPolicy::kNoReferrerWhenDowngradeOriginWhenCrossOrigin)
ASSERT_ENUMS_MATCH(ReferrerPolicy::SameOrigin, network::mojom::ReferrerPolicy::kSameOrigin)
ASSERT_ENUMS_MATCH(ReferrerPolicy::StrictOrigin, network::mojom::ReferrerPolicy::kStrictOrigin)
ASSERT_ENUMS_MATCH(ReferrerPolicy::Last, network::mojom::ReferrerPolicy::kLast)

} // namespace QtWebEngineCore
