/****************************************************************************
**
** 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_delegate_qt.h"

#include "profile_adapter.h"
#include "color_chooser_controller.h"
#include "color_chooser_qt.h"
#include "favicon_manager.h"
#include "file_picker_controller.h"
#include "media_capture_devices_dispatcher.h"
#include "profile_qt.h"
#include "qwebengineregisterprotocolhandlerrequest.h"
#include "register_protocol_handler_request_controller_impl.h"
#include "render_widget_host_view_qt.h"
#include "type_conversion.h"
#include "visited_links_manager_qt.h"
#include "web_contents_adapter_client.h"
#include "web_contents_adapter.h"
#include "web_contents_view_qt.h"
#include "web_engine_context.h"
#include "web_engine_settings.h"

#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
#include "components/web_cache/browser/web_cache_manager.h"
#include "content/browser/frame_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/file_select_listener.h"
#include "content/public/browser/invalidate_type.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/favicon_url.h"
#include "content/public/common/frame_navigate_params.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/web_preferences.h"
#include "net/base/data_url.h"
#include "net/base/url_util.h"

#include <QDesktopServices>
#include <QTimer>
#include <QWindow>

namespace QtWebEngineCore {

static WebContentsAdapterClient::JavaScriptConsoleMessageLevel mapToJavascriptConsoleMessageLevel(blink::mojom::ConsoleMessageLevel log_level)
{
    switch (log_level) {
    case blink::mojom::ConsoleMessageLevel::kVerbose:
    case blink::mojom::ConsoleMessageLevel::kInfo:
        return WebContentsAdapterClient::Info;
    case blink::mojom::ConsoleMessageLevel::kWarning:
        return WebContentsAdapterClient::Warning;
    case blink::mojom::ConsoleMessageLevel::kError:
        return WebContentsAdapterClient::Error;
    }
}

WebContentsDelegateQt::WebContentsDelegateQt(content::WebContents *webContents, WebContentsAdapterClient *adapterClient)
    : m_viewClient(adapterClient)
    , m_faviconManager(new FaviconManager(webContents, adapterClient))
    , m_findTextHelper(new FindTextHelper(webContents, adapterClient))
    , m_lastLoadProgress(-1)
    , m_loadingState(determineLoadingState(webContents))
    , m_didStartLoadingSeen(m_loadingState == LoadingState::Loading)
    , m_frameFocusedObserver(adapterClient)
{
    webContents->SetDelegate(this);
    Observe(webContents);
}

WebContentsDelegateQt::~WebContentsDelegateQt()
{
    // The destruction of this object should take place before
    // WebContents destruction since WebContentsAdapterClient
    // might be already deleted.
}

content::WebContents *WebContentsDelegateQt::OpenURLFromTab(content::WebContents *source, const content::OpenURLParams &params)
{
    content::WebContents *target = source;
    content::SiteInstance *target_site_instance = params.source_site_instance.get();
    content::Referrer referrer = params.referrer;
    if (params.disposition != WindowOpenDisposition::CURRENT_TAB) {
        QSharedPointer<WebContentsAdapter> targetAdapter = createWindow(0, params.disposition, gfx::Rect(), params.user_gesture);
        if (targetAdapter) {
            if (targetAdapter->profile() != source->GetBrowserContext()) {
                target_site_instance = nullptr;
                referrer = content::Referrer();
            }
            if (!targetAdapter->isInitialized())
                targetAdapter->initialize(target_site_instance);
            target = targetAdapter->webContents();
        }
    }
    Q_ASSERT(target);

    content::NavigationController::LoadURLParams load_url_params(params.url);
    load_url_params.initiator_origin = params.initiator_origin;
    load_url_params.source_site_instance = target_site_instance;
    load_url_params.referrer = referrer;
    load_url_params.frame_tree_node_id = params.frame_tree_node_id;
    load_url_params.redirect_chain = params.redirect_chain;
    load_url_params.transition_type = params.transition;
    load_url_params.extra_headers = params.extra_headers;
    load_url_params.should_replace_current_entry = params.should_replace_current_entry;
    load_url_params.is_renderer_initiated = params.is_renderer_initiated;
    load_url_params.started_from_context_menu = params.started_from_context_menu;
    load_url_params.has_user_gesture = params.user_gesture;
    load_url_params.blob_url_loader_factory = params.blob_url_loader_factory;
    load_url_params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE;
    load_url_params.href_translate = params.href_translate;
    load_url_params.reload_type = params.reload_type;
    if (params.post_data) {
        load_url_params.load_type = content::NavigationController::LOAD_TYPE_HTTP_POST;
        load_url_params.post_data = params.post_data;
    }

    target->GetController().LoadURLWithParams(load_url_params);
    return target;
}

static bool shouldUseActualURL(content::NavigationEntry *entry)
{
    Q_ASSERT(entry);

    // Show actual URL for data URLs only
    if (!entry->GetURL().SchemeIs(url::kDataScheme))
        return false;

    // Do not show data URL of interstitial and error pages
    if (entry->GetPageType() != content::PAGE_TYPE_NORMAL)
        return false;

    // Show invalid data URL
    std::string mime_type, charset, data;
    if (!net::DataURL::Parse(entry->GetURL(), &mime_type, &charset, &data))
        return false;

    // Do not show empty data URL
    return !data.empty();
}

void WebContentsDelegateQt::NavigationStateChanged(content::WebContents* source, content::InvalidateTypes changed_flags)
{
    if (changed_flags & content::INVALIDATE_TYPE_URL && !m_pendingUrlUpdate) {
        m_pendingUrlUpdate = true;
        base::WeakPtr<WebContentsDelegateQt> delegate = AsWeakPtr();
        QTimer::singleShot(0, [delegate, this](){ if (delegate) m_viewClient->urlChanged();});
    }

    if (changed_flags & content::INVALIDATE_TYPE_TITLE) {
        QString newTitle = toQt(source->GetTitle());
        if (m_title != newTitle) {
            m_title = newTitle;
            QTimer::singleShot(0, [delegate = AsWeakPtr(), title = newTitle] () {
                if (delegate)
                    delegate->adapterClient()->titleChanged(title);
            });
        }
    }

    // Make sure to only emit the signal when loading isn't in progress, because it causes multiple
    // false signals to be emitted.
    if ((changed_flags & content::INVALIDATE_TYPE_AUDIO) && !(changed_flags & content::INVALIDATE_TYPE_LOAD)) {
        m_viewClient->recentlyAudibleChanged(source->IsCurrentlyAudible());
    }
}

QUrl WebContentsDelegateQt::url(content::WebContents* source) const {

    content::NavigationEntry *entry = source->GetController().GetVisibleEntry();
    QUrl newUrl;
    if (entry) {
        GURL url = entry->GetURL();
        // Strip user name, password and reference section from view-source URLs
        if (source->GetVisibleURL().SchemeIs(content::kViewSourceScheme) &&
            (url.has_password() || url.has_username() || url.has_ref())) {
            GURL strippedUrl = net::SimplifyUrlForRequest(url);
            newUrl = QUrl(QString("%1:%2").arg(content::kViewSourceScheme, QString::fromStdString(strippedUrl.spec())));
        }
        // If there is a visible entry there are special cases when we dont wan't to use the actual URL
        if (newUrl.isEmpty())
            newUrl = shouldUseActualURL(entry) ? toQt(url) : toQt(entry->GetVirtualURL());
    }
    m_pendingUrlUpdate = false;
    return newUrl;
}
void WebContentsDelegateQt::AddNewContents(content::WebContents* source, std::unique_ptr<content::WebContents> new_contents, WindowOpenDisposition disposition, const gfx::Rect& initial_pos, bool user_gesture, bool* was_blocked)
{
    Q_UNUSED(source)
    QSharedPointer<WebContentsAdapter> newAdapter = createWindow(std::move(new_contents), disposition, initial_pos, user_gesture);
    // Chromium can forget to pass user-agent override settings to new windows (see QTBUG-61774 and QTBUG-76249),
    // so set it here. Note the actual value doesn't really matter here. Only the second value does, but we try
    // to give the correct user-agent anyway.
    if (newAdapter)
        newAdapter->webContents()->SetUserAgentOverride(newAdapter->profileAdapter()->httpUserAgent().toStdString(), true);
    if (newAdapter && !newAdapter->isInitialized())
        newAdapter->loadDefault();
    if (was_blocked)
        *was_blocked = !newAdapter;
}

void WebContentsDelegateQt::CloseContents(content::WebContents *source)
{
    GetJavaScriptDialogManager(source)->CancelDialogs(source, /* whatever?: */false);
    // Must be the last call because close() might trigger the destruction of this object.
    m_viewClient->close();
}

void WebContentsDelegateQt::LoadProgressChanged(double progress)
{
    if (!m_loadingErrorFrameList.isEmpty())
        return;
    if (m_lastLoadProgress < 0) // suppress signals that aren't between loadStarted and loadFinished
        return;
    m_lastLoadProgress = qMax(m_lastLoadProgress, qRound(progress * 100)); // ensure monotonicity
    m_lastLoadProgress = qMin(m_lastLoadProgress, 100);
    m_viewClient->loadProgressChanged(m_lastLoadProgress);
}

bool WebContentsDelegateQt::HandleKeyboardEvent(content::WebContents *, const content::NativeWebKeyboardEvent &event)
{
    Q_ASSERT(!event.skip_in_browser);
    if (event.os_event)
        m_viewClient->unhandledKeyEvent(reinterpret_cast<QKeyEvent *>(event.os_event));
    // FIXME: ?
    return true;
}

void WebContentsDelegateQt::RenderFrameCreated(content::RenderFrameHost *render_frame_host)
{
    content::FrameTreeNode *node = static_cast<content::RenderFrameHostImpl *>(render_frame_host)->frame_tree_node();
    m_frameFocusedObserver.addNode(node);
}

void WebContentsDelegateQt::RenderFrameDeleted(content::RenderFrameHost *render_frame_host)
{
    m_loadingErrorFrameList.removeOne(render_frame_host->GetRoutingID());
}

void WebContentsDelegateQt::RenderProcessGone(base::TerminationStatus status)
{
    // RenderProcessHost::FastShutdownIfPossible results in TERMINATION_STATUS_STILL_RUNNING
    if (status != base::TERMINATION_STATUS_STILL_RUNNING) {
        m_viewClient->renderProcessTerminated(
                m_viewClient->renderProcessExitStatus(status),
                web_contents()->GetCrashedErrorCode());
    }

    // Based one TabLoadTracker::RenderProcessGone

    if (status == base::TERMINATION_STATUS_NORMAL_TERMINATION
        || status == base::TERMINATION_STATUS_STILL_RUNNING) {
        return;
    }

    setLoadingState(LoadingState::Unloaded);
}

void WebContentsDelegateQt::RenderFrameHostChanged(content::RenderFrameHost *old_host, content::RenderFrameHost *new_host)
{
    if (old_host) {
        content::FrameTreeNode *old_node = static_cast<content::RenderFrameHostImpl *>(old_host)->frame_tree_node();
        m_frameFocusedObserver.removeNode(old_node);
    }

    if (new_host) {
        content::FrameTreeNode *new_node = static_cast<content::RenderFrameHostImpl *>(new_host)->frame_tree_node();
        m_frameFocusedObserver.addNode(new_node);

        // Is this a main frame?
        if (new_host->GetFrameOwnerElementType() == blink::FrameOwnerElementType::kNone) {
            content::RenderProcessHost *renderProcessHost = new_host->GetProcess();
            const base::Process &process = renderProcessHost->GetProcess();
            if (process.IsValid())
                m_viewClient->renderProcessPidChanged(process.Pid());
        }
    }
}

void WebContentsDelegateQt::RenderViewHostChanged(content::RenderViewHost *, content::RenderViewHost *newHost)
{
    if (newHost && newHost->GetWidget() && newHost->GetWidget()->GetView()) {
        auto rwhv = static_cast<RenderWidgetHostViewQt *>(newHost->GetWidget()->GetView());
        m_viewClient->widgetChanged(rwhv->delegate());
    }
}

void WebContentsDelegateQt::EmitLoadStarted(const QUrl &url, bool isErrorPage)
{
    if (m_lastLoadProgress >= 0 && m_lastLoadProgress < 100) // already running
        return;
    m_viewClient->loadStarted(url, isErrorPage);
    m_viewClient->updateNavigationActions();
    m_viewClient->loadProgressChanged(0);
    m_lastLoadProgress = 0;
}

void WebContentsDelegateQt::DidStartNavigation(content::NavigationHandle *navigation_handle)
{
    if (!navigation_handle->IsInMainFrame())
        return;

    // Error-pages are not reported as separate started navigations.
    Q_ASSERT(!navigation_handle->IsErrorPage());

    m_loadingErrorFrameList.clear();
    m_faviconManager->resetCandidates();
    EmitLoadStarted(toQt(navigation_handle->GetURL()));
}

void WebContentsDelegateQt::EmitLoadFinished(bool success, const QUrl &url, bool isErrorPage, int errorCode, const QString &errorDescription)
{
    if (m_lastLoadProgress < 0) // not currently running
        return;
    m_lastLoadProgress = -1;
    m_viewClient->loadProgressChanged(100);
    m_viewClient->loadFinished(success, url, isErrorPage, errorCode, errorDescription);
    m_viewClient->updateNavigationActions();
}

void WebContentsDelegateQt::EmitLoadCommitted()
{
    m_findTextHelper->handleLoadCommitted();
    m_viewClient->loadCommitted();
    m_viewClient->updateNavigationActions();
}

void WebContentsDelegateQt::DidFinishNavigation(content::NavigationHandle *navigation_handle)
{
    if (!navigation_handle->IsInMainFrame())
        return;

    if (navigation_handle->HasCommitted() && !navigation_handle->IsErrorPage()) {
        ProfileAdapter *profileAdapter = m_viewClient->profileAdapter();
        // VisistedLinksMaster asserts !IsOffTheRecord().
        if (navigation_handle->ShouldUpdateHistory() && profileAdapter->trackVisitedLinks()) {
            for (const GURL &url : navigation_handle->GetRedirectChain())
                profileAdapter->visitedLinksManager()->addUrl(url);
        }

        EmitLoadCommitted();
    }
    // Success is reported by DidFinishLoad, but DidFailLoad is now dead code and needs to be handled below
    if (navigation_handle->GetNetErrorCode() == net::OK)
        return;

    // WebContentsObserver::DidFailLoad is not called any longer so we have to report the failure here.
    const net::Error error_code = navigation_handle->GetNetErrorCode();
    const std::string error_description = net::ErrorToString(error_code);
    didFailLoad(toQt(navigation_handle->GetURL()), error_code, toQt(error_description));

    // The load will succede as an error-page load later, and we reported the original error above
    if (navigation_handle->IsErrorPage()) {
        // Now report we are starting to load an error-page.
        m_loadingErrorFrameList.append(navigation_handle->GetRenderFrameHost()->GetRoutingID());
        m_faviconManager->resetCandidates();
        EmitLoadStarted(toQt(GURL(content::kUnreachableWebDataURL)), true);

        // If it is already committed we will not see another DidFinishNavigation call or a DidFinishLoad call.
        if (navigation_handle->HasCommitted())
            EmitLoadCommitted();
    }
}

void WebContentsDelegateQt::DidStartLoading()
{
    // Based on TabLoadTracker::DidStartLoading

    if (!web_contents()->IsLoadingToDifferentDocument())
        return;
    if (m_loadingState == LoadingState::Loading) {
        DCHECK(m_didStartLoadingSeen);
        return;
    }
    m_didStartLoadingSeen = true;
}

void WebContentsDelegateQt::DidReceiveResponse()
{
    // Based on TabLoadTracker::DidReceiveResponse

    if (m_loadingState == LoadingState::Loading) {
        DCHECK(m_didStartLoadingSeen);
        return;
    }

    // A transition to loading requires both DidStartLoading (navigation
    // committed) and DidReceiveResponse (data has been transmitted over the
    // network) events to occur. This is because NavigationThrottles can block
    // actual network requests, but not the rest of the state machinery.
    if (m_didStartLoadingSeen)
        setLoadingState(LoadingState::Loading);
}

void WebContentsDelegateQt::DidStopLoading()
{
    // Based on TabLoadTracker::DidStopLoading

    // NOTE: PageAlmostIdle feature not implemented

    if (m_loadingState == LoadingState::Loading)
        setLoadingState(LoadingState::Loaded);
}

void WebContentsDelegateQt::didFailLoad(const QUrl &url, int errorCode, const QString &errorDescription)
{
    m_viewClient->iconChanged(QUrl());
    EmitLoadFinished(false /* success */ , url, false /* isErrorPage */, errorCode, errorDescription);
}

void WebContentsDelegateQt::DidFailLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code, const base::string16& error_description)
{
    if (m_loadingState == LoadingState::Loading)
        setLoadingState(LoadingState::Loaded);

    if (render_frame_host != web_contents()->GetMainFrame())
        return;

    if (validated_url.spec() == content::kUnreachableWebDataURL) {
        // error-pages should only ever fail due to abort:
        Q_ASSERT(error_code == -3 /* ERR_ABORTED */);
        m_loadingErrorFrameList.removeOne(render_frame_host->GetRoutingID());
        m_viewClient->iconChanged(QUrl());

        EmitLoadFinished(false /* success */, toQt(validated_url), true /* isErrorPage */);
        return;
    }

    didFailLoad(toQt(validated_url), error_code, toQt(error_description));
}

void WebContentsDelegateQt::DidFinishLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url)
{
    Q_ASSERT(validated_url.is_valid());
    if (validated_url.spec() == content::kUnreachableWebDataURL) {
        m_loadingErrorFrameList.removeOne(render_frame_host->GetRoutingID());

        // Trigger LoadFinished signal for main frame's error page only.
        if (!render_frame_host->GetParent()) {
            m_viewClient->iconChanged(QUrl());
            EmitLoadFinished(true /* success */, toQt(validated_url), true /* isErrorPage */);
        }

        return;
    }

    if (render_frame_host->GetParent()) {
        m_viewClient->updateNavigationActions();
        return;
    }

    if (!m_faviconManager->hasCandidate())
        m_viewClient->iconChanged(QUrl());

    content::NavigationEntry *entry = web_contents()->GetController().GetActiveEntry();
    int http_statuscode = 0;
    if (entry)
       http_statuscode = entry->GetHttpStatusCode();
    EmitLoadFinished(true /* success */ , toQt(validated_url), false /* isErrorPage */, http_statuscode);
}

void WebContentsDelegateQt::DidUpdateFaviconURL(const std::vector<content::FaviconURL> &candidates)
{
    QList<FaviconInfo> faviconCandidates;
    faviconCandidates.reserve(static_cast<int>(candidates.size()));
    for (const content::FaviconURL &candidate : candidates) {
        // Store invalid candidates too for later debugging via API
        faviconCandidates.append(toFaviconInfo(candidate));
    }

    // Favicon URL can be changed from JavaScript too. Thus we need to reset
    // the current candidate icon list to not handle previous icon as a candidate.
    m_faviconManager->resetCandidates();
    m_faviconManager->update(faviconCandidates);
}

void WebContentsDelegateQt::WebContentsCreated(content::WebContents * /*source_contents*/,
                                               int /*opener_render_process_id*/, int /*opener_render_frame_id*/,
                                               const std::string &/*frame_name*/,
                                               const GURL &target_url, content::WebContents *newContents)
{
    m_initialTargetUrl = toQt(target_url);
    if (auto *view = static_cast<content::WebContentsImpl *>(newContents)->GetView())
        static_cast<WebContentsViewQt *>(view)->setFactoryClient(m_viewClient);
}

content::ColorChooser *WebContentsDelegateQt::OpenColorChooser(content::WebContents *source, SkColor color, const std::vector<blink::mojom::ColorSuggestionPtr> &suggestion)
{
    Q_UNUSED(suggestion);
    ColorChooserQt *colorChooser = new ColorChooserQt(source, toQt(color));
    m_viewClient->showColorDialog(colorChooser->controller());

    return colorChooser;
}
content::JavaScriptDialogManager *WebContentsDelegateQt::GetJavaScriptDialogManager(content::WebContents *)
{
    return JavaScriptDialogManagerQt::GetInstance();
}

void WebContentsDelegateQt::EnterFullscreenModeForTab(content::WebContents *web_contents, const GURL& origin, const blink::mojom::FullscreenOptions &)
{
    Q_UNUSED(web_contents);
    if (!m_viewClient->isFullScreenMode())
        m_viewClient->requestFullScreenMode(toQt(origin), true);
}

void WebContentsDelegateQt::ExitFullscreenModeForTab(content::WebContents *web_contents)
{
    if (m_viewClient->isFullScreenMode())
        m_viewClient->requestFullScreenMode(toQt(web_contents->GetLastCommittedURL().GetOrigin()), false);
}

bool WebContentsDelegateQt::IsFullscreenForTabOrPending(const content::WebContents* web_contents)
{
    Q_UNUSED(web_contents);
    return m_viewClient->isFullScreenMode();
}

ASSERT_ENUMS_MATCH(FilePickerController::Open, blink::mojom::FileChooserParams::Mode::kOpen)
ASSERT_ENUMS_MATCH(FilePickerController::OpenMultiple, blink::mojom::FileChooserParams::Mode::kOpenMultiple)
ASSERT_ENUMS_MATCH(FilePickerController::UploadFolder, blink::mojom::FileChooserParams::Mode::kUploadFolder)
ASSERT_ENUMS_MATCH(FilePickerController::Save, blink::mojom::FileChooserParams::Mode::kSave)

void WebContentsDelegateQt::RunFileChooser(content::RenderFrameHost * /*frameHost*/,
                                           std::unique_ptr<content::FileSelectListener> listener,
                                           const blink::mojom::FileChooserParams& params)
{
    QStringList acceptedMimeTypes;
    acceptedMimeTypes.reserve(params.accept_types.size());
    for (std::vector<base::string16>::const_iterator it = params.accept_types.begin(); it < params.accept_types.end(); ++it)
        acceptedMimeTypes.append(toQt(*it));

    m_filePickerController.reset(new FilePickerController(static_cast<FilePickerController::FileChooserMode>(params.mode),
                                                          std::move(listener), toQt(params.default_file_name.value()), acceptedMimeTypes));

    // Defer the call to not block base::MessageLoop::RunTask with modal dialogs.
    QTimer::singleShot(0, [this] () {
        m_viewClient->runFileChooser(m_filePickerController);
    });
}

bool WebContentsDelegateQt::DidAddMessageToConsole(content::WebContents *source, blink::mojom::ConsoleMessageLevel log_level,
                                                   const base::string16 &message, int32_t line_no, const base::string16 &source_id)
{
    Q_UNUSED(source)
    m_viewClient->javaScriptConsoleMessage(mapToJavascriptConsoleMessageLevel(log_level), toQt(message), static_cast<int>(line_no), toQt(source_id));
    return false;
}

void WebContentsDelegateQt::FindReply(content::WebContents *source, int request_id, int number_of_matches, const gfx::Rect& selection_rect, int active_match_ordinal, bool final_update)
{
    m_findTextHelper->handleFindReply(source, request_id, number_of_matches, selection_rect, active_match_ordinal, final_update);
}

void WebContentsDelegateQt::RequestMediaAccessPermission(content::WebContents *web_contents, const content::MediaStreamRequest &request,  content::MediaResponseCallback callback)
{
    MediaCaptureDevicesDispatcher::GetInstance()->processMediaAccessRequest(m_viewClient, web_contents, request, std::move(callback));
}

void WebContentsDelegateQt::SetContentsBounds(content::WebContents *source, const gfx::Rect &bounds)
{
    if (!source->HasOpener()) // is popup
        return;

    QRect frameGeometry(toQt(bounds));
    QRect geometry;
    if (RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt*>(web_contents()->GetRenderWidgetHostView())) {
        if (rwhv->delegate() && rwhv->delegate()->window())
            geometry = frameGeometry.marginsRemoved(rwhv->delegate()->window()->frameMargins());
    }
    m_viewClient->requestGeometryChange(geometry, frameGeometry);
}

void WebContentsDelegateQt::UpdateTargetURL(content::WebContents* source, const GURL& url)
{
    Q_UNUSED(source)
    m_viewClient->didUpdateTargetURL(toQt(url));
}

void WebContentsDelegateQt::OnVisibilityChanged(content::Visibility visibility)
{
    if (visibility != content::Visibility::HIDDEN)
        web_cache::WebCacheManager::GetInstance()->ObserveActivity(web_contents()->GetMainFrame()->GetProcess()->GetID());
}

void WebContentsDelegateQt::DidFirstVisuallyNonEmptyPaint()
{
    RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt*>(web_contents()->GetRenderWidgetHostView());
    if (!rwhv)
        return;

    rwhv->OnDidFirstVisuallyNonEmptyPaint();
}

void WebContentsDelegateQt::ActivateContents(content::WebContents* contents)
{
    WebEngineSettings *settings = m_viewClient->webEngineSettings();
    if (settings->testAttribute(settings->Attribute::AllowWindowActivationFromJavaScript))
        contents->Focus();
}

void WebContentsDelegateQt::RequestToLockMouse(content::WebContents *web_contents, bool user_gesture, bool last_unlocked_by_target)
{
    Q_UNUSED(user_gesture);

    if (last_unlocked_by_target)
        web_contents->GotResponseToLockMouseRequest(true);
    else
        m_viewClient->runMouseLockPermissionRequest(toQt(web_contents->GetLastCommittedURL().GetOrigin()));
}

void WebContentsDelegateQt::overrideWebPreferences(content::WebContents *webContents, content::WebPreferences *webPreferences)
{
    m_viewClient->webEngineSettings()->overrideWebPreferences(webContents, webPreferences);
}

QSharedPointer<WebContentsAdapter>
WebContentsDelegateQt::createWindow(std::unique_ptr<content::WebContents> new_contents,
                                    WindowOpenDisposition disposition, const gfx::Rect &initial_pos,
                                    bool user_gesture)
{
    QSharedPointer<WebContentsAdapter> newAdapter = QSharedPointer<WebContentsAdapter>::create(std::move(new_contents));

    return m_viewClient->adoptNewWindow(
            std::move(newAdapter),
            static_cast<WebContentsAdapterClient::WindowOpenDisposition>(disposition), user_gesture,
            toQt(initial_pos), m_initialTargetUrl);
}

void WebContentsDelegateQt::allowCertificateError(const QSharedPointer<CertificateErrorController> &errorController)
{
    m_viewClient->allowCertificateError(errorController);
}

void WebContentsDelegateQt::selectClientCert(const QSharedPointer<ClientCertSelectController> &selectController)
{
    m_viewClient->selectClientCert(selectController);
}

void WebContentsDelegateQt::requestFeaturePermission(ProfileAdapter::PermissionType feature, const QUrl &requestingOrigin)
{
    m_viewClient->runFeaturePermissionRequest(feature, requestingOrigin);
}

extern WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::PageTransition transition);

void WebContentsDelegateQt::launchExternalURL(const QUrl &url, ui::PageTransition page_transition, bool is_main_frame, bool has_user_gesture)
{
    WebEngineSettings *settings = m_viewClient->webEngineSettings();
    bool navigationAllowedByPolicy = false;
    bool navigationRequestAccepted = true;

    switch (settings->unknownUrlSchemePolicy()) {
    case WebEngineSettings::DisallowUnknownUrlSchemes:
        break;
    case WebEngineSettings::AllowUnknownUrlSchemesFromUserInteraction:
        navigationAllowedByPolicy = has_user_gesture;
        break;
    case WebEngineSettings::AllowAllUnknownUrlSchemes:
        navigationAllowedByPolicy = true;
        break;
    default:
        Q_UNREACHABLE();
    }

    if (navigationAllowedByPolicy) {
        int navigationRequestAction = WebContentsAdapterClient::AcceptRequest;
        m_viewClient->navigationRequested(pageTransitionToNavigationType(page_transition), url, navigationRequestAction, is_main_frame);
        navigationRequestAccepted = navigationRequestAction == WebContentsAdapterClient::AcceptRequest;
#ifndef QT_NO_DESKTOPSERVICES
        if (navigationRequestAccepted)
            QDesktopServices::openUrl(url);
#endif
    }

    if (!navigationAllowedByPolicy || !navigationRequestAccepted) {
        QString errorDescription;
        if (!navigationAllowedByPolicy)
            errorDescription = QStringLiteral("Launching external protocol forbidden by WebEngineSettings::UnknownUrlSchemePolicy");
        else
            errorDescription = QStringLiteral("Launching external protocol suppressed by WebContentsAdapterClient::navigationRequested");
        didFailLoad(url, net::Error::ERR_ABORTED, errorDescription);
    }
}

void WebContentsDelegateQt::BeforeUnloadFired(content::WebContents *tab, bool proceed, bool *proceed_to_fire_unload)
{
    Q_UNUSED(tab);
    Q_ASSERT(proceed_to_fire_unload);
    *proceed_to_fire_unload = proceed;
    if (!proceed)
        m_viewClient->windowCloseRejected();
}

void WebContentsDelegateQt::BeforeUnloadFired(bool proceed, const base::TimeTicks &proceed_time)
{
    Q_UNUSED(proceed);
    Q_UNUSED(proceed_time);
}

bool WebContentsDelegateQt::CheckMediaAccessPermission(content::RenderFrameHost *, const GURL& security_origin, blink::mojom::MediaStreamType type)
{
    switch (type) {
    case blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE:
        return m_viewClient->profileAdapter()->checkPermission(toQt(security_origin), ProfileAdapter::AudioCapturePermission);
    case blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE:
        return m_viewClient->profileAdapter()->checkPermission(toQt(security_origin), ProfileAdapter::VideoCapturePermission);
    default:
        LOG(INFO) << "WebContentsDelegateQt::CheckMediaAccessPermission: "
                  << "Unsupported media stream type checked" << type;
        return false;
    }
}

void WebContentsDelegateQt::RegisterProtocolHandler(content::WebContents *webContents, const std::string &protocol, const GURL &url, bool)
{
    content::BrowserContext *context = webContents->GetBrowserContext();
    if (context->IsOffTheRecord())
        return;

    ProtocolHandler handler =
        ProtocolHandler::CreateProtocolHandler(protocol, url);

    ProtocolHandlerRegistry *registry =
        ProtocolHandlerRegistryFactory::GetForBrowserContext(context);
    if (registry->SilentlyHandleRegisterHandlerRequest(handler))
        return;

    QWebEngineRegisterProtocolHandlerRequest request(
        QSharedPointer<RegisterProtocolHandlerRequestControllerImpl>::create(webContents, handler));
    m_viewClient->runRegisterProtocolHandlerRequest(std::move(request));
}

void WebContentsDelegateQt::UnregisterProtocolHandler(content::WebContents *webContents, const std::string &protocol, const GURL &url, bool)
{
    content::BrowserContext* context = webContents->GetBrowserContext();
    if (context->IsOffTheRecord())
        return;

    ProtocolHandler handler =
        ProtocolHandler::CreateProtocolHandler(protocol, url);

    ProtocolHandlerRegistry* registry =
        ProtocolHandlerRegistryFactory::GetForBrowserContext(context);
    registry->RemoveHandler(handler);
}

bool WebContentsDelegateQt::TakeFocus(content::WebContents *source, bool reverse)
{
    Q_UNUSED(source);
    return m_viewClient->passOnFocus(reverse);
}

void WebContentsDelegateQt::ContentsZoomChange(bool zoom_in)
{
    WebContentsAdapter *adapter = webContentsAdapter();
    if (zoom_in)
        adapter->setZoomFactor(adapter->currentZoomFactor() + 0.1f);
    else
        adapter->setZoomFactor(adapter->currentZoomFactor() - 0.1f);
}

bool WebContentsDelegateQt::ShouldNavigateOnBackForwardMouseButtons()
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
    return false;
#else
    return true;
#endif
}

FaviconManager *WebContentsDelegateQt::faviconManager()
{
    return m_faviconManager.data();
}

FindTextHelper *WebContentsDelegateQt::findTextHelper()
{
    return m_findTextHelper.data();
}

WebEngineSettings *WebContentsDelegateQt::webEngineSettings() const {
    return m_viewClient->webEngineSettings();
}

WebContentsAdapter *WebContentsDelegateQt::webContentsAdapter() const
{
    return m_viewClient->webContentsAdapter();
}

void WebContentsDelegateQt::copyStateFrom(WebContentsDelegateQt *source)
{
    m_title = source->m_title;
    NavigationStateChanged(web_contents(), content::INVALIDATE_TYPE_URL);
    m_faviconManager->copyStateFrom(source->m_faviconManager.data());
}

WebContentsDelegateQt::LoadingState WebContentsDelegateQt::determineLoadingState(content::WebContents *contents)
{
    // Based on TabLoadTracker::DetermineLoadingState

    if (contents->IsLoadingToDifferentDocument() && !contents->IsWaitingForResponse())
        return LoadingState::Loading;

    content::NavigationController &controller = contents->GetController();
    if (controller.GetLastCommittedEntry() != nullptr && !controller.IsInitialNavigation() && !controller.NeedsReload())
        return LoadingState::Loaded;

    return LoadingState::Unloaded;
}

void WebContentsDelegateQt::setLoadingState(LoadingState state)
{
    if (m_loadingState == state)
        return;

    m_loadingState = state;

    webContentsAdapter()->updateRecommendedState();
}

int &WebContentsDelegateQt::streamCount(blink::mojom::MediaStreamType type)
{
    // Based on MediaStreamCaptureIndicator::WebContentsDeviceUsage::GetStreamCount
    switch (type) {
    case blink::mojom::MediaStreamType::DEVICE_AUDIO_CAPTURE:
        return m_audioStreamCount;

    case blink::mojom::MediaStreamType::DEVICE_VIDEO_CAPTURE:
        return m_videoStreamCount;

    case blink::mojom::MediaStreamType::GUM_TAB_AUDIO_CAPTURE:
    case blink::mojom::MediaStreamType::GUM_TAB_VIDEO_CAPTURE:
        return m_mirroringStreamCount;

    case blink::mojom::MediaStreamType::GUM_DESKTOP_VIDEO_CAPTURE:
    case blink::mojom::MediaStreamType::GUM_DESKTOP_AUDIO_CAPTURE:
    case blink::mojom::MediaStreamType::DISPLAY_VIDEO_CAPTURE:
    case blink::mojom::MediaStreamType::DISPLAY_AUDIO_CAPTURE:
        return m_desktopStreamCount;

    case blink::mojom::MediaStreamType::NO_SERVICE:
    case blink::mojom::MediaStreamType::NUM_MEDIA_TYPES:
        NOTREACHED();
        return m_videoStreamCount;
    }
    NOTREACHED();
    return m_videoStreamCount;
}

void WebContentsDelegateQt::addDevices(const blink::MediaStreamDevices &devices)
{
    for (const auto &device : devices)
        ++streamCount(device.type);

    webContentsAdapter()->updateRecommendedState();
}

void WebContentsDelegateQt::removeDevices(const blink::MediaStreamDevices &devices)
{
    for (const auto &device : devices)
        ++streamCount(device.type);

    webContentsAdapter()->updateRecommendedState();
}

FrameFocusedObserver::FrameFocusedObserver(WebContentsAdapterClient *adapterClient)
    : m_viewClient(adapterClient)
{}

void FrameFocusedObserver::addNode(content::FrameTreeNode *node)
{
   if (m_observedNodes.contains(node))
       return;

   node->AddObserver(this);
   m_observedNodes.append(node);
}

void FrameFocusedObserver::removeNode(content::FrameTreeNode *node)
{
    node->RemoveObserver(this);
    m_observedNodes.removeOne(node);
}

void FrameFocusedObserver::OnFrameTreeNodeFocused(content::FrameTreeNode *node)
{
    Q_UNUSED(node);
    m_viewClient->updateEditActions();
}

void FrameFocusedObserver::OnFrameTreeNodeDestroyed(content::FrameTreeNode *node)
{
    m_observedNodes.removeOne(node);
    m_viewClient->updateEditActions();
}

FrameFocusedObserver::~FrameFocusedObserver()
{
    for (content::FrameTreeNode *node : m_observedNodes)
        node->RemoveObserver(this);
}

} // namespace QtWebEngineCore
