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

#include "content/browser/webui/web_ui_impl.h"

#include <stddef.h>

#include <string>
#include <string_view>
#include <utility>

#include "base/containers/flat_map.h"
#include "base/debug/dump_without_crashing.h"
#include "base/feature_list.h"
#include "base/functional/callback_helpers.h"
#include "base/json/json_writer.h"
#include "base/strings/strcat.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "build/build_config.h"
#include "content/browser/child_process_security_policy_impl.h"
#include "content/browser/renderer_host/dip_util.h"
#include "content/browser/renderer_host/frame_tree.h"
#include "content/browser/renderer_host/navigation_request.h"
#include "content/browser/renderer_host/render_frame_host_impl.h"
#include "content/browser/renderer_host/render_process_host_impl.h"
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/browser/web_contents/web_contents_view.h"
#include "content/browser/webui/url_data_manager_backend.h"
#include "content/browser/webui/web_ui_controller_factory_registry.h"
#include "content/browser/webui/web_ui_data_source_impl.h"
#include "content/browser/webui/web_ui_main_frame_observer.h"
#include "content/common/features.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/browser/web_ui_controller.h"
#include "content/public/browser/web_ui_message_handler.h"
#include "content/public/common/bindings_policy.h"
#include "content/public/common/content_client.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "services/service_manager/public/cpp/interface_provider.h"
#include "third_party/blink/public/mojom/loader/local_resource_loader_config.mojom.h"

namespace content {

namespace {

template <typename Range>
std::u16string GetJavascriptCallImpl(std::string_view function_name,
                                     const Range& args) {
  std::vector<std::u16string> json_args;
  for (const auto& arg : args) {
    json_args.push_back(base::UTF8ToUTF16(*base::WriteJson(arg)));
  }

  std::u16string result(base::ASCIIToUTF16(function_name));
  result.push_back('(');
  result.append(base::JoinString(json_args, u","));
  result.push_back(')');
  result.push_back(';');
  return result;
}

blink::mojom::LocalResourceLoaderConfigPtr CreateLocalResourceLoaderConfig(
    URLDataManagerBackend* data_backend) {
  auto loader_config = blink::mojom::LocalResourceLoaderConfig::New();
  base::flat_map<url::Origin, blink::mojom::LocalResourceSourcePtr>&
      loader_sources = loader_config->sources;
  for (auto const& [source_name, data_source] : data_backend->data_sources()) {
    // For a data source to be useful in the renderer process, it must have a
    // map from path to resource ID. Only WebUIDataSourceImpls have a map from
    // path to resource ID. Most URLDataSources are not WebUIDataSourceImpls,
    // e.g. favicon, image, etc.
    if (!data_source->IsWebUIDataSourceImpl()) {
      continue;
    }
    auto* webui_data_source =
        static_cast<WebUIDataSourceImpl*>(data_source.get());
    url::Origin origin = webui_data_source->GetOrigin();
    // We only support data sources that serve URLs of the form: chrome://*
    if (origin.scheme() != kChromeUIScheme) {
      continue;
    }
    auto loader_source = blink::mojom::LocalResourceSource::New();
    webui_data_source->EnsureLoadTimeDataDefaultsAdded();
    loader_source->headers =
        URLDataManagerBackend::GetHeaders(webui_data_source, GURL("/"), "")
            ->raw_headers();
    loader_source->should_replace_i18n_in_js =
        data_source->source()->ShouldReplaceI18nInJS();
    loader_source->path_to_resource_id_map.insert(
        webui_data_source->path_to_idr_map().begin(),
        webui_data_source->path_to_idr_map().end());
    loader_source->replacement_strings.insert(
        webui_data_source->source()->GetReplacements()->begin(),
        webui_data_source->source()->GetReplacements()->end());
    loader_sources[origin] = std::move(loader_source);
  }
  return loader_config;
}

bool IsForTestMessage(const std::string& message) {
  return base::EndsWith(message, "ForTest") ||
         base::EndsWith(message, "ForTesting");
}

}  // namespace

const WebUI::TypeID WebUI::kNoWebUI = nullptr;

// static
std::u16string WebUI::GetJavascriptCall(
    std::string_view function_name,
    base::span<const base::ValueView> arg_list) {
  return GetJavascriptCallImpl(function_name, arg_list);
}

// static
std::u16string WebUI::GetJavascriptCall(std::string_view function_name,
                                        const base::Value::List& arg_list) {
  return GetJavascriptCallImpl(function_name, arg_list);
}

WebUIImpl::WebUIImpl(WebContents* web_contents)
    : requestable_schemes_({kChromeUIScheme, url::kFileScheme}),
      web_contents_(web_contents),
      web_contents_observer_(
          std::make_unique<WebUIMainFrameObserver>(this, web_contents_)) {
  DCHECK(web_contents_);
}

WebUIImpl::WebUIImpl(NavigationRequest* request)
    : WebUIImpl(
          WebContents::FromFrameTreeNodeId(request->GetFrameTreeNodeId())) {}

WebUIImpl::~WebUIImpl() {
  // Delete the controller first, since it may also be keeping a pointer to some
  // of the handlers and can call them at destruction.
  // Note: Calling this might delete |web_content_| and |frame_host_|. The two
  // pointers are now potentially dangling.
  // See https://crbug.com/1308391
  controller_.reset();

  remote_.reset();
  receiver_.reset();
}

void WebUIImpl::SetProperty(const std::string& name, const std::string& value) {
  DCHECK(remote_);
  remote_->SetProperty(name, value);
}

void WebUIImpl::Send(const std::string& message, base::Value::List args) {
  const GURL& source_url = frame_host_->GetLastCommittedURL();
  if (!ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
          frame_host_->GetProcess()->GetDeprecatedID()) ||
      !WebUIControllerFactoryRegistry::GetInstance()->IsURLAcceptableForWebUI(
          web_contents_->GetBrowserContext(), source_url)) {
    bad_message::ReceivedBadMessage(
        frame_host_->GetProcess(),
        bad_message::WEBUI_SEND_FROM_UNAUTHORIZED_PROCESS);
    return;
  }

  if (base::EndsWith(message, "RequiringGesture",
                     base::CompareCase::SENSITIVE) &&
      !web_contents_->HasRecentInteraction()) {
    LOG(ERROR) << message << " received without recent user interaction";
    return;
  }

  ProcessWebUIMessage(source_url, message, std::move(args));
}

void WebUIImpl::SetRenderFrameHost(RenderFrameHost* render_frame_host) {
  frame_host_ =
      static_cast<RenderFrameHostImpl*>(render_frame_host)->GetWeakPtr();
  // Assert that we can only open WebUI for the active or speculative pages.
  DCHECK(frame_host_->lifecycle_state() ==
             RenderFrameHostImpl::LifecycleStateImpl::kActive ||
         frame_host_->lifecycle_state() ==
             RenderFrameHostImpl::LifecycleStateImpl::kSpeculative);
}

void WebUIImpl::WebUIRenderFrameCreated(RenderFrameHost* render_frame_host) {
  controller_->WebUIRenderFrameCreated(render_frame_host);

#if BUILDFLAG(LOAD_WEBUI_FROM_DISK)
  if (base::CommandLine::ForCurrentProcess()->HasSwitch(
          switches::kLoadWebUIfromDisk)) {
    return;
  }
#endif

  if (base::FeatureList::IsEnabled(features::kWebUIInProcessResourceLoading)) {
    CHECK(frame_host_);
    frame_host_->UpdateLocalResourceLoader(GetLocalResourceLoaderConfig());
  }
}

void WebUIImpl::RenderFrameHostUnloading() {
  DisallowJavascriptOnAllHandlers();
}

void WebUIImpl::RenderFrameDeleted() {
  DisallowJavascriptOnAllHandlers();
}

void WebUIImpl::SetUpMojoConnection() {
  // TODO(nasko): WebUI mojo might be useful to be registered for
  // subframes as well, though at this time there is no such usage but currently
  // this is expected to be called only for outermost main frames.
  if (frame_host_->GetParentOrOuterDocument())
    return;

  frame_host_->GetFrameBindingsControl()->BindWebUI(
      remote_.BindNewEndpointAndPassReceiver(),
      receiver_.BindNewEndpointAndPassRemote());
}

void WebUIImpl::TearDownMojoConnection() {
  // This is expected to be called only for outermost main frames.
  if (frame_host_->GetParentOrOuterDocument())
    return;

  remote_.reset();
  receiver_.reset();
}

WebContents* WebUIImpl::GetWebContents() {
  return web_contents_;
}

float WebUIImpl::GetDeviceScaleFactor() {
  return GetScaleFactorForView(web_contents_->GetRenderWidgetHostView());
}

const std::u16string& WebUIImpl::GetOverriddenTitle() {
  return overridden_title_;
}

void WebUIImpl::OverrideTitle(const std::u16string& title) {
  overridden_title_ = title;
}

BindingsPolicySet WebUIImpl::GetBindings() {
  return bindings_;
}

void WebUIImpl::SetBindings(BindingsPolicySet bindings) {
  bindings_ = bindings;
}

const std::vector<std::string>& WebUIImpl::GetRequestableSchemes() {
  return requestable_schemes_;
}

void WebUIImpl::AddRequestableScheme(const char* scheme) {
  requestable_schemes_.push_back(scheme);
}

WebUIController* WebUIImpl::GetController() {
  return controller_.get();
}

RenderFrameHost* WebUIImpl::GetRenderFrameHost() {
  return frame_host_.get();
}

bool WebUIImpl::HasRenderFrameHost() const {
  return !!frame_host_;
}

void WebUIImpl::SetController(std::unique_ptr<WebUIController> controller) {
  DCHECK(controller);
  controller_ = std::move(controller);
}

bool WebUIImpl::CanCallJavascript() {
  return (ChildProcessSecurityPolicyImpl::GetInstance()->HasWebUIBindings(
              frame_host_->GetProcess()->GetDeprecatedID()) ||
          // It's possible to load about:blank in a Web UI renderer.
          // See http://crbug.com/42547
          frame_host_->GetLastCommittedURL().spec() == url::kAboutBlankURL);
}

void WebUIImpl::CallJavascriptFunctionUnsafe(
    std::string_view function_name,
    base::span<const base::ValueView> args) {
  DCHECK(base::IsStringASCII(function_name));
  ExecuteJavascript(GetJavascriptCall(function_name, args));
}

void WebUIImpl::RegisterMessageCallback(std::string_view message,
                                        MessageCallback callback) {
  message_callbacks_.emplace(message, std::move(callback));
}

void WebUIImpl::ProcessWebUIMessage(const GURL& source_url,
                                    const std::string& message,
                                    base::Value::List args) {
  if (controller_->OverrideHandleWebUIMessage(source_url, message, args))
    return;

  auto callback_pair = message_callbacks_.find(message);
  if (callback_pair != message_callbacks_.end()) {
    // Forward this message and content on.
    callback_pair->second.Run(args);
    return;
  }

  if (!IsForTestMessage(message)) {
    DUMP_WILL_BE_NOTREACHED() << "Unhandled chrome.send(\"" << message << "\", "
                              << args << "); from " << source_url;
  }
}

std::vector<std::unique_ptr<WebUIMessageHandler>>*
WebUIImpl::GetHandlersForTesting() {
  return &handlers_;
}

// WebUIImpl, protected: -------------------------------------------------------

void WebUIImpl::AddMessageHandler(
    std::unique_ptr<WebUIMessageHandler> handler) {
  DCHECK(!handler->web_ui());
  handler->set_web_ui(this);
  handler->RegisterMessages();
  handlers_.push_back(std::move(handler));
}

void WebUIImpl::ExecuteJavascript(const std::u16string& javascript) {
  // Silently ignore the request. Would be nice to clean-up WebUI so we
  // could turn this into a CHECK(). http://crbug.com/516690.
  if (!CanCallJavascript())
    return;

  frame_host_->ExecuteJavaScript(javascript, base::NullCallback());
}

void WebUIImpl::DisallowJavascriptOnAllHandlers() {
  for (const std::unique_ptr<WebUIMessageHandler>& handler : handlers_)
    handler->DisallowJavascript();
}

blink::mojom::LocalResourceLoaderConfigPtr
WebUIImpl::GetLocalResourceLoaderConfig() {
  URLDataManagerBackend* data_backend =
      URLDataManagerBackend::GetForBrowserContext(
          web_contents_->GetBrowserContext());
  return CreateLocalResourceLoaderConfig(data_backend);
}

// static
blink::mojom::LocalResourceLoaderConfigPtr
WebUIImpl::GetLocalResourceLoaderConfigForTesting(
    URLDataManagerBackend* data_backend) {
  return CreateLocalResourceLoaderConfig(data_backend);
}

}  // namespace content
