/****************************************************************************
**
** Copyright (C) 2017 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$
**
****************************************************************************/

// based on content/shell/browser/shell_devtools_frontend.cc:
// 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 file.

#include "devtools_frontend_qt.h"

#include "profile_adapter.h"
#include "profile_qt.h"
#include "web_contents_adapter.h"

#include "base/base64.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/json/string_escape.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/post_task.h"
#include "base/values.h"
#include "chrome/common/url_constants.h"
#include "components/prefs/in_memory_pref_store.h"
#include "components/prefs/json_pref_store.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/file_url_loader.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_handle.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/shared_cors_origin_access_list.h"
#include "content/public/browser/storage_partition.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/content_client.h"
#include "content/public/common/url_constants.h"
#include "content/public/common/url_utils.h"
#include "ipc/ipc_channel.h"
#include "net/http/http_response_headers.h"
#include "net/traffic_annotation/network_traffic_annotation.h"
#include "services/network/public/cpp/simple_url_loader.h"
#include "services/network/public/cpp/simple_url_loader_stream_consumer.h"

using namespace QtWebEngineCore;

namespace {

std::unique_ptr<base::DictionaryValue> BuildObjectForResponse(const net::HttpResponseHeaders *rh)
{
    auto response = std::make_unique<base::DictionaryValue>();
    response->SetInteger("statusCode", rh ? rh->response_code() : 200);

    auto headers = std::make_unique<base::DictionaryValue>();
    size_t iterator = 0;
    std::string name;
    std::string value;
    // TODO(caseq): this probably needs to handle duplicate header names
    // correctly by folding them.
    while (rh && rh->EnumerateHeaderLines(&iterator, &name, &value))
        headers->SetString(name, value);

    response->Set("headers", std::move(headers));
    return response;
}

static std::string GetFrontendURL()
{
    return "devtools://devtools/bundled/devtools_app.html";
}

}  // namespace

namespace QtWebEngineCore {

class DevToolsFrontendQt::NetworkResourceLoader
        : public network::SimpleURLLoaderStreamConsumer {
public:
    NetworkResourceLoader(int stream_id,
                          int request_id,
                          DevToolsFrontendQt *bindings,
                          std::unique_ptr<network::SimpleURLLoader> loader,
                          network::mojom::URLLoaderFactory *url_loader_factory)
        : stream_id_(stream_id),
          request_id_(request_id),
          bindings_(bindings),
          loader_(std::move(loader))
    {
        loader_->SetOnResponseStartedCallback(base::BindOnce(
                                                  &NetworkResourceLoader::OnResponseStarted, base::Unretained(this)));
        loader_->DownloadAsStream(url_loader_factory, this);
    }

private:
    void OnResponseStarted(const GURL &final_url,
                           const network::mojom::URLResponseHead &response_head)
    {
        response_headers_ = response_head.headers;
    }

    void OnDataReceived(base::StringPiece chunk, base::OnceClosure resume) override
    {
        base::Value chunkValue;

        bool encoded = !base::IsStringUTF8(chunk);
        if (encoded) {
            std::string encoded_string;
            base::Base64Encode(chunk, &encoded_string);
            chunkValue = base::Value(std::move(encoded_string));
        } else {
            chunkValue = base::Value(chunk);
        }
        base::Value id(stream_id_);
        base::Value encodedValue(encoded);

        bindings_->CallClientFunction("DevToolsAPI.streamWrite", &id, &chunkValue, &encodedValue);
        std::move(resume).Run();
    }

    void OnComplete(bool success) override
    {
        Q_UNUSED(success);
        auto response = BuildObjectForResponse(response_headers_.get());
        bindings_->SendMessageAck(request_id_, response.get());
        bindings_->m_loaders.erase(bindings_->m_loaders.find(this));
    }

    void OnRetry(base::OnceClosure start_retry) override { NOTREACHED(); }

    const int stream_id_;
    const int request_id_;
    DevToolsFrontendQt *const bindings_;
    std::unique_ptr<network::SimpleURLLoader> loader_;
    scoped_refptr<net::HttpResponseHeaders> response_headers_;

    DISALLOW_COPY_AND_ASSIGN(NetworkResourceLoader);
};

// This constant should be in sync with
// the constant at devtools_ui_bindings.cc.
const size_t kMaxMessageChunkSize = IPC::Channel::kMaximumMessageSize / 4;

// static
DevToolsFrontendQt *DevToolsFrontendQt::Show(QSharedPointer<WebContentsAdapter> frontendAdapter, content::WebContents *inspectedContents)
{
    DCHECK(frontendAdapter);
    DCHECK(inspectedContents);

    if (!frontendAdapter->isInitialized()) {
        scoped_refptr<content::SiteInstance> site =
            content::SiteInstance::CreateForURL(frontendAdapter->profile(), GURL(GetFrontendURL()));
        frontendAdapter->initialize(site.get());
    }

    frontendAdapter->setInspector(true);

    content::WebContents *contents = frontendAdapter->webContents();
    if (contents == inspectedContents) {
        LOG(WARNING) << "You can not inspect yourself";
        return nullptr;
    }

    DevToolsFrontendQt *devtoolsFrontend = new DevToolsFrontendQt(frontendAdapter, inspectedContents);

    if (contents->GetURL() == GURL(GetFrontendURL())) {
        contents->GetController().Reload(content::ReloadType::ORIGINAL_REQUEST_URL, false);
    }  else {
        content::NavigationController::LoadURLParams loadParams((GURL(GetFrontendURL())));
        loadParams.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_AUTO_TOPLEVEL | ui::PAGE_TRANSITION_FROM_API);
        contents->GetController().LoadURLWithParams(loadParams);
    }

    return devtoolsFrontend;
}

DevToolsFrontendQt::DevToolsFrontendQt(QSharedPointer<WebContentsAdapter> webContentsAdapter,
                                       content::WebContents *inspectedContents)
    : content::WebContentsObserver(webContentsAdapter->webContents())
    , m_webContentsAdapter(webContentsAdapter)
    , m_inspectedContents(inspectedContents)
    , m_inspect_element_at_x(-1)
    , m_inspect_element_at_y(-1)
    , m_prefStore(nullptr)
    , m_weakFactory(this)
{
    // We use a separate prefstore than one in ProfileQt, because that one is in-memory only, and this
    // needs to be stored or it will show introduction text on every load.
    if (webContentsAdapter->profileAdapter()->isOffTheRecord())
        m_prefStore = scoped_refptr<PersistentPrefStore>(new InMemoryPrefStore());
    else
        CreateJsonPreferences(false);

    m_frontendDelegate = static_cast<WebContentsDelegateQt *>(webContentsAdapter->webContents()->GetDelegate());
}


DevToolsFrontendQt::~DevToolsFrontendQt()
{
    if (QSharedPointer<WebContentsAdapter> p = m_webContentsAdapter)
        p->setInspector(false);
}

void DevToolsFrontendQt::Activate()
{
    m_frontendDelegate->ActivateContents(web_contents());
}

void DevToolsFrontendQt::Focus()
{
    web_contents()->Focus();
}

void DevToolsFrontendQt::InspectElementAt(int x, int y)
{
    if (m_agentHost)
        m_agentHost->InspectElement(m_inspectedContents->GetFocusedFrame(), x, y);
    else {
        m_inspect_element_at_x = x;
        m_inspect_element_at_y = y;
    }
}

void DevToolsFrontendQt::Close()
{
    // Don't close the webContents, it might be reused, but pretend it was
    WebContentsDestroyed();
}

void DevToolsFrontendQt::DisconnectFromTarget()
{
    if (!m_agentHost)
        return;
    m_agentHost->DetachClient(this);
    m_agentHost = nullptr;
}

void DevToolsFrontendQt::ReadyToCommitNavigation(content::NavigationHandle *navigationHandle)
{
    // ShellDevToolsFrontend does this in RenderViewCreated,
    // but that doesn't work for us for some reason.
    content::RenderFrameHost *frame = navigationHandle->GetRenderFrameHost();
    if (navigationHandle->IsInMainFrame()) {
        // If the frontend for some reason goes to some place other than devtools, stop the bindings
        if (navigationHandle->GetURL() != GetFrontendURL())
            m_frontendHost.reset(nullptr);
        else
            m_frontendHost = content::DevToolsFrontendHost::Create(
                        frame,
                        base::Bind(&DevToolsFrontendQt::HandleMessageFromDevToolsFrontend,
                                   base::Unretained(this)));
    }
}

void DevToolsFrontendQt::DocumentAvailableInMainFrame()
{
    if (!m_inspectedContents)
        return;
    // Don't call AttachClient multiple times for the same DevToolsAgentHost.
    // Otherwise it will call AgentHostClosed which closes the DevTools window.
    // This may happen in cases where the DevTools content fails to load.
    scoped_refptr<content::DevToolsAgentHost> agent_host =
            content::DevToolsAgentHost::GetOrCreateFor(m_inspectedContents);
    if (agent_host != m_agentHost) {
        if (m_agentHost)
            m_agentHost->DetachClient(this);
        m_agentHost = agent_host;
        m_agentHost->AttachClient(this);
        if (m_inspect_element_at_x != -1) {
            m_agentHost->InspectElement(m_inspectedContents->GetFocusedFrame(), m_inspect_element_at_x, m_inspect_element_at_y);
            m_inspect_element_at_x = -1;
            m_inspect_element_at_y = -1;
        }
    }
}

void DevToolsFrontendQt::WebContentsDestroyed()
{
    if (m_inspectedContents)
        static_cast<WebContentsDelegateQt *>(m_inspectedContents->GetDelegate())->webContentsAdapter()->devToolsFrontendDestroyed(this);

    if (m_agentHost) {
        m_agentHost->DetachClient(this);
        m_agentHost = nullptr;
    }
    delete this;
}

void DevToolsFrontendQt::SetPreference(const std::string &name, const std::string &value)
{
    DCHECK(m_prefStore);
    m_prefStore->SetValue(name, base::WrapUnique(new base::Value(value)), 0);
}

void DevToolsFrontendQt::RemovePreference(const std::string &name)
{
    DCHECK(m_prefStore);
    m_prefStore->RemoveValue(name, 0);
}

void DevToolsFrontendQt::ClearPreferences()
{
    ProfileQt *profile = static_cast<ProfileQt *>(web_contents()->GetBrowserContext());
    if (profile->IsOffTheRecord() || profile->profileAdapter()->storageName().isEmpty())
        m_prefStore = scoped_refptr<PersistentPrefStore>(new InMemoryPrefStore());
    else
        CreateJsonPreferences(true);
}

void DevToolsFrontendQt::CreateJsonPreferences(bool clear)
{
    content::BrowserContext *browserContext = web_contents()->GetBrowserContext();
    DCHECK(!browserContext->IsOffTheRecord());
    JsonPrefStore *jsonPrefStore = new JsonPrefStore(
                browserContext->GetPath().Append(FILE_PATH_LITERAL("devtoolsprefs.json")));
    // We effectively clear the preferences by not calling ReadPrefs
    if (!clear)
        jsonPrefStore->ReadPrefs();

    m_prefStore = scoped_refptr<PersistentPrefStore>(jsonPrefStore);
}

void DevToolsFrontendQt::HandleMessageFromDevToolsFrontend(const std::string &message)
{
    if (!m_agentHost)
        return;
    std::string method;
    base::ListValue *params = nullptr;
    base::DictionaryValue *dict = nullptr;
    std::unique_ptr<base::Value> parsed_message = base::JSONReader::ReadDeprecated(message);
    if (!parsed_message || !parsed_message->GetAsDictionary(&dict) || !dict->GetString("method", &method))
        return;
    int request_id = 0;
    dict->GetInteger("id", &request_id);
    dict->GetList("params", &params);

    if (method == "dispatchProtocolMessage" && params && params->GetSize() == 1) {
        std::string protocol_message;
        if (!params->GetString(0, &protocol_message))
            return;
        m_agentHost->DispatchProtocolMessage(this, protocol_message);
    } else if (method == "loadCompleted") {
        web_contents()->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16("DevToolsAPI.setUseSoftMenu(true);"),
                                                          base::NullCallback());
    } else if (method == "loadNetworkResource" && params->GetSize() == 3) {
        // TODO(pfeldman): handle some of the embedder messages in content.
        std::string url;
        std::string headers;
        int stream_id;
        if (!params->GetString(0, &url) || !params->GetString(1, &headers) || !params->GetInteger(2, &stream_id))
            return;

        GURL gurl(url);
        if (!gurl.is_valid()) {
            base::DictionaryValue response;
            response.SetInteger("statusCode", 404);
            SendMessageAck(request_id, &response);
            return;
        }

        net::NetworkTrafficAnnotationTag traffic_annotation =
            net::DefineNetworkTrafficAnnotation(
                "devtools_handle_front_end_messages", R"(
                semantics {
                  sender: "Developer Tools"
                  description:
                    "When user opens Developer Tools, the browser may fetch "
                    "additional resources from the network to enrich the debugging "
                    "experience (e.g. source map resources)."
                  trigger: "User opens Developer Tools to debug a web page."
                  data: "Any resources requested by Developer Tools."
                  destination: OTHER
                }
                policy {
                  cookies_allowed: YES
                  cookies_store: "user"
                  setting:
                    "It's not possible to disable this feature from settings."
                  chrome_policy {
                    DeveloperToolsAvailability {
                      policy_options {mode: MANDATORY}
                      DeveloperToolsAvailability: 2
                    }
                  }
                })");
        auto resource_request = std::make_unique<network::ResourceRequest>();
        resource_request->url = gurl;
        // TODO(caseq): this preserves behavior of URLFetcher-based implementation.
        // We really need to pass proper first party origin from the front-end.
        resource_request->site_for_cookies = gurl;
        resource_request->headers.AddHeadersFromString(headers);

        std::unique_ptr<network::mojom::URLLoaderFactory> file_url_loader_factory;
        scoped_refptr<network::SharedURLLoaderFactory> network_url_loader_factory;
        network::mojom::URLLoaderFactory *url_loader_factory;
        if (gurl.SchemeIsFile()) {
            file_url_loader_factory = content::CreateFileURLLoaderFactory(base::FilePath(), nullptr);
            url_loader_factory = file_url_loader_factory.get();
        } else if (content::HasWebUIScheme(gurl)) {
            base::DictionaryValue response;
            response.SetInteger("statusCode", 403);
            SendMessageAck(request_id, &response);
            return;
        } else {
            auto *partition = content::BrowserContext::GetStoragePartitionForSite(
                                  web_contents()->GetBrowserContext(), gurl);
            network_url_loader_factory = partition->GetURLLoaderFactoryForBrowserProcess();
            url_loader_factory = network_url_loader_factory.get();
        }
        auto simple_url_loader = network::SimpleURLLoader::Create(
                    std::move(resource_request), traffic_annotation);
        auto resource_loader = std::make_unique<NetworkResourceLoader>(
                    stream_id, request_id, this, std::move(simple_url_loader),
                    url_loader_factory);
        m_loaders.insert(std::move(resource_loader));
        return;
    } else if (method == "getPreferences") {
        m_preferences = std::move(*m_prefStore->GetValues());
        SendMessageAck(request_id, &m_preferences);
        return;
    } else if (method == "setPreference") {
        std::string name;
        std::string value;
        if (!params->GetString(0, &name) || !params->GetString(1, &value))
            return;
        SetPreference(name, value);
    } else if (method == "removePreference") {
        std::string name;
        if (!params->GetString(0, &name))
            return;
        RemovePreference(name);
    } else if (method == "clearPreferences") {
        ClearPreferences();
    } else if (method == "requestFileSystems") {
        web_contents()->GetMainFrame()->ExecuteJavaScript(base::ASCIIToUTF16("DevToolsAPI.fileSystemsLoaded([]);"),
                                                          base::NullCallback());
    } else if (method == "reattach") {
        m_agentHost->DetachClient(this);
        m_agentHost->AttachClient(this);
    } else if (method == "openInNewTab") {
        std::string urlString;
        if (!params->GetString(0, &urlString))
            return;
        GURL url(urlString);
        if (!url.is_valid())
            return;
        content::OpenURLParams openParams(GURL(url),
                                          content::Referrer(),
                                          WindowOpenDisposition::NEW_FOREGROUND_TAB,
                                          ui::PAGE_TRANSITION_LINK,
                                          false);
        // OpenURL will (via WebContentsDelegateQt::OpenURLFromTab) call
        // application code, which may decide to close this devtools view (see
        // quicknanobrowser for example).
        //
        // Chromium always calls SendMessageAck through a callback bound to a
        // WeakPtr, we do the same here, except without the callback.
        base::WeakPtr<DevToolsFrontendQt> weakThis = m_weakFactory.GetWeakPtr();
        web_contents()->OpenURL(openParams);
        if (!weakThis)
            return;
    } else if (method == "bringToFront") {
        Activate();
    } else {
        VLOG(1) << "Unimplemented devtools method: " << message;
        return;
    }

    if (request_id)
        SendMessageAck(request_id, nullptr);
}

void DevToolsFrontendQt::DispatchProtocolMessage(content::DevToolsAgentHost *agentHost, const std::string &message)
{
    Q_UNUSED(agentHost);
    if (message.length() < kMaxMessageChunkSize) {
        std::string param;
        base::EscapeJSONString(message, true, &param);
        std::string code = "DevToolsAPI.dispatchMessage(" + param + ");";
        base::string16 javascript = base::UTF8ToUTF16(code);
        web_contents()->GetMainFrame()->ExecuteJavaScript(javascript, base::NullCallback());
        return;
    }

    size_t total_size = message.length();
    for (size_t pos = 0; pos < message.length(); pos += kMaxMessageChunkSize) {
        std::string param;
        base::EscapeJSONString(message.substr(pos, kMaxMessageChunkSize), true, &param);
        std::string code = "DevToolsAPI.dispatchMessageChunk(" + param + ","
                         + std::to_string(pos ? 0 : total_size) + ");";
        base::string16 javascript = base::UTF8ToUTF16(code);
        web_contents()->GetMainFrame()->ExecuteJavaScript(javascript, base::NullCallback());
    }
}

void DevToolsFrontendQt::CallClientFunction(const std::string &function_name,
                                            const base::Value *arg1,
                                            const base::Value *arg2,
                                            const base::Value *arg3)
{
    std::string javascript = function_name + "(";
    if (arg1) {
        std::string json;
        base::JSONWriter::Write(*arg1, &json);
        javascript.append(json);
        if (arg2) {
            base::JSONWriter::Write(*arg2, &json);
            javascript.append(", ").append(json);
            if (arg3) {
                base::JSONWriter::Write(*arg3, &json);
                javascript.append(", ").append(json);
            }
        }
    }
    javascript.append(");");
    web_contents()->GetMainFrame()->ExecuteJavaScript(base::UTF8ToUTF16(javascript), base::NullCallback());
}

void DevToolsFrontendQt::SendMessageAck(int request_id, const base::Value *arg)
{
    base::Value id_value(request_id);
    CallClientFunction("DevToolsAPI.embedderMessageAck", &id_value, arg, nullptr);
}

void DevToolsFrontendQt::AgentHostClosed(content::DevToolsAgentHost *agentHost)
{
    DCHECK(agentHost == m_agentHost.get());
    m_agentHost = nullptr;
    m_inspectedContents = nullptr;
    Close();
}

} // namespace QtWebEngineCore
