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

#include "extensions/browser/extension_function_dispatcher.h"

#include <algorithm>
#include <optional>
#include <utility>

#include "base/debug/crash_logging.h"
#include "base/functional/bind.h"
#include "base/json/json_string_value_serializer.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_refptr.h"
#include "base/metrics/histogram_functions.h"
#include "base/metrics/histogram_macros.h"
#include "base/process/process.h"
#include "base/scoped_observation.h"
#include "base/trace_event/typed_macros.h"
#include "base/tracing/protos/chrome_track_event.pbzero.h"
#include "base/values.h"
#include "build/build_config.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/render_process_host_observer.h"
#include "content/public/browser/service_worker_context.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_observer.h"
#include "content/public/common/result_codes.h"
#include "content/public/common/url_constants.h"
#include "extensions/browser/api_activity_monitor.h"
#include "extensions/browser/bad_message.h"
#include "extensions/browser/extension_function_registry.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/extension_util.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/process_manager.h"
#include "extensions/browser/process_map.h"
#include "extensions/browser/quota_service.h"
#include "extensions/browser/script_injection_tracker.h"
#include "extensions/browser/service_worker/service_worker_keepalive.h"
#include "extensions/common/constants.h"
#include "extensions/common/extension_api.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/extension_urls.h"
#include "extensions/common/mojom/context_type.mojom.h"
#include "extensions/common/trace_util.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_message_macros.h"
#include "mojo/public/cpp/bindings/message.h"

using content::BrowserThread;
using perfetto::protos::pbzero::ChromeTrackEvent;

namespace extensions {
namespace {

// Notifies the ApiActivityMonitor that an extension API function has been
// called. May be called from any thread.
void NotifyApiFunctionCalled(const ExtensionId& extension_id,
                             const std::string& api_name,
                             const base::Value::List& args,
                             content::BrowserContext* browser_context) {
  activity_monitor::OnApiFunctionCalled(browser_context, extension_id, api_name,
                                        args);
}

bool IsRequestFromServiceWorker(const mojom::RequestParams& request_params) {
  return request_params.service_worker_version_id !=
         blink::mojom::kInvalidServiceWorkerVersionId;
}

// Calls ResponseCallback with an empty result.
void ResponseCallbackOnError(ExtensionFunction::ResponseCallback callback,
                             ExtensionFunction::ResponseType type,
                             const std::string& error) {
  std::move(callback).Run(type, base::Value::List(), error, nullptr);
}

std::optional<bad_message::BadMessageReason> ValidateRequest(
    const mojom::RequestParams& params,
    content::RenderFrameHost* render_frame_host,
    content::RenderProcessHost& render_process_host) {
  if ((render_frame_host && IsRequestFromServiceWorker(params)) ||
      (!render_frame_host && !IsRequestFromServiceWorker(params))) {
    return bad_message::EFD_BAD_MESSAGE;
  }

  if (!util::CanRendererActOnBehalfOfExtension(
          params.extension_id, render_frame_host, render_process_host,
          /*include_user_scripts=*/true)) {
    return bad_message::EFD_INVALID_EXTENSION_ID_FOR_PROCESS;
  }

  // TODO(crbug.com/40055124): Validate `params.user_gesture`.

  return std::nullopt;
}

const char* ToString(bad_message::BadMessageReason bad_message_code) {
  switch (bad_message_code) {
    case bad_message::BadMessageReason::EFD_BAD_MESSAGE:
      return "LocalFrameHost::Request got a bad message.";
    case bad_message::BadMessageReason::EFD_INVALID_EXTENSION_ID_FOR_PROCESS:
      return "LocalFrameHost::Request: renderer never hosted such extension";
    default:
      NOTREACHED();
  }
}

// Helper for logging crash keys related to a the IPC payload from
// mojom::RequestParams.
class ScopedRequestParamsCrashKeys {
 public:
  explicit ScopedRequestParamsCrashKeys(const mojom::RequestParams& params)
      : name_(GetNameCrashKey(), params.name),
        extension_id_(GetExtensionIdCrashKey(), params.extension_id) {}

  ~ScopedRequestParamsCrashKeys() = default;

  // No copy constructor and no copy assignment operator.
  ScopedRequestParamsCrashKeys(const ScopedRequestParamsCrashKeys&) = delete;
  ScopedRequestParamsCrashKeys& operator=(const ScopedRequestParamsCrashKeys&) =
      delete;

 private:
  static base::debug::CrashKeyString* GetNameCrashKey() {
    static auto* crash_key = base::debug::AllocateCrashKeyString(
        "RequestParams-name", base::debug::CrashKeySize::Size256);
    return crash_key;
  }

  static base::debug::CrashKeyString* GetExtensionIdCrashKey() {
    static auto* crash_key = base::debug::AllocateCrashKeyString(
        "RequestParams-extension_id", base::debug::CrashKeySize::Size64);
    return crash_key;
  }

  base::debug::ScopedCrashKeyString name_;
  base::debug::ScopedCrashKeyString extension_id_;
};

}  // namespace

WindowController*
ExtensionFunctionDispatcher::Delegate::GetExtensionWindowController() const {
  return nullptr;
}

content::WebContents*
ExtensionFunctionDispatcher::Delegate::GetAssociatedWebContents() const {
  return nullptr;
}

content::WebContents*
ExtensionFunctionDispatcher::Delegate::GetVisibleWebContents() const {
  return GetAssociatedWebContents();
}

ExtensionFunctionDispatcher::ExtensionFunctionDispatcher(
    content::BrowserContext* browser_context)
    : browser_context_(browser_context), delegate_(nullptr) {}

ExtensionFunctionDispatcher::~ExtensionFunctionDispatcher() {
}

void ExtensionFunctionDispatcher::Dispatch(
    mojom::RequestParamsPtr params,
    content::RenderFrameHost& frame,
    mojom::LocalFrameHost::RequestCallback callback) {
  content::RenderProcessHost& process = *frame.GetProcess();
  TRACE_EVENT("extensions", "ExtensionFunctionDispatcher::Dispatch",
              ChromeTrackEvent::kRenderProcessHost, process,
              ChromeTrackEvent::kChromeExtensionId,
              ExtensionIdForTracing(params->extension_id));

  ScopedRequestParamsCrashKeys request_params_crash_keys(*params);
  SCOPED_CRASH_KEY_STRING256(
      "extensions", "frame.GetSiteInstance()",
      frame.GetSiteInstance()->GetSiteURL().possibly_invalid_spec());

  if (auto bad_message_code = ValidateRequest(*params, &frame, process)) {
    // Kill the renderer if it's an invalid request.
    debug::ScopedScriptInjectionTrackerFailureCrashKeys tracker_keys(
        frame, params->extension_id);
    bad_message::ReceivedBadMessage(&process, *bad_message_code);
    std::move(callback).Run(ExtensionFunction::FAILED, base::Value::List(),
                            ToString(*bad_message_code), nullptr);
    return;
  }

  // TODO(crbug.com/40056469): Validate (or remove) `params.source_url`.
  DispatchWithCallbackInternal(
      *params, &frame, *frame.GetProcess(),
      base::BindOnce(
          [](mojom::LocalFrameHost::RequestCallback callback,
             ExtensionFunction::ResponseType type, base::Value::List results,
             const std::string& error,
             mojom::ExtraResponseDataPtr response_data) {
            std::move(callback).Run(type == ExtensionFunction::SUCCEEDED,
                                    std::move(results), error,
                                    std::move(response_data));
          },
          std::move(callback)));
}

void ExtensionFunctionDispatcher::DispatchForServiceWorker(
    mojom::RequestParamsPtr params,
    int render_process_id,
    mojom::ServiceWorkerHost::RequestWorkerCallback callback) {
  ScopedRequestParamsCrashKeys request_params_crash_keys(*params);

  // The IPC might race with RenderProcessHost destruction.  This may only
  // happen in scenarios that are already inherently racey, so dropping the IPC
  // is okay and won't lead to any additional risk of data loss.  Continuing is
  // impossible, because WorkerResponseCallbackWrapper requires render process
  // host to be around.
  content::RenderProcessHost* rph =
      content::RenderProcessHost::FromID(render_process_id);
  if (!rph) {
    std::move(callback).Run(ExtensionFunction::FAILED, base::Value::List(),
                            "No RPH", nullptr);
    return;
  }

  TRACE_EVENT("extensions",
              "ExtensionFunctionDispatcher::DispatchForServiceWorker",
              ChromeTrackEvent::kRenderProcessHost, *rph,
              ChromeTrackEvent::kChromeExtensionId,
              ExtensionIdForTracing(params->extension_id));
  if (auto bad_message_code = ValidateRequest(*params, nullptr, *rph)) {
    // Kill the renderer if it's an invalid request.
    bad_message::ReceivedBadMessage(render_process_id, *bad_message_code);
    std::move(callback).Run(ExtensionFunction::FAILED, base::Value::List(),
                            ToString(*bad_message_code), nullptr);
    return;
  }

  WorkerId worker_id{params->extension_id, render_process_id,
                     params->service_worker_version_id,
                     params->worker_thread_id};
  // Ignore if the worker has already stopped.
  if (!ProcessManager::Get(browser_context_)->HasServiceWorker(worker_id)) {
    std::move(callback).Run(ExtensionFunction::FAILED, base::Value::List(),
                            "No SW", nullptr);
    return;
  }

  DispatchWithCallbackInternal(
      *params, nullptr, *rph,
      base::BindOnce(
          [](mojom::ServiceWorkerHost::RequestWorkerCallback callback,
             ExtensionFunction::ResponseType type, base::Value::List results,
             const std::string& error,
             mojom::ExtraResponseDataPtr response_data) {
            std::move(callback).Run(type == ExtensionFunction::SUCCEEDED,
                                    std::move(results), error,
                                    std::move(response_data));
          },
          std::move(callback)));
}

void ExtensionFunctionDispatcher::DispatchWithCallbackInternal(
    const mojom::RequestParams& params,
    content::RenderFrameHost* render_frame_host,
    content::RenderProcessHost& render_process_host,
    ExtensionFunction::ResponseCallback callback) {
  ProcessMap* process_map = ProcessMap::Get(browser_context_);
  if (!process_map) {
    constexpr char kProcessNotFound[] =
        "The process for the extension is not found.";
    ResponseCallbackOnError(std::move(callback), ExtensionFunction::FAILED,
                            kProcessNotFound);
    return;
  }

  const int render_process_id = render_process_host.GetDeprecatedID();

  const GURL* render_frame_host_url = nullptr;
  if (render_frame_host) {
    render_frame_host_url = &render_frame_host->GetLastCommittedURL();
    DCHECK_EQ(render_process_id,
              render_frame_host->GetProcess()->GetDeprecatedID());
  }

  ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context_);
  const Extension* extension =
      registry->enabled_extensions().GetByID(params.extension_id);
  // Check if the call is from a hosted app. Hosted apps can only make call from
  // render frames, so we can use `render_frame_host_url`.
  // TODO(devlin): Isn't `params.extension_id` still populated for hosted app
  // calls?
  if (!extension && render_frame_host_url) {
    extension = registry->enabled_extensions().GetHostedAppByURL(
        *render_frame_host_url);
  }

  if (!process_map->CanProcessHostContextType(extension, render_process_host,
                                              params.context_type)) {
    // TODO(crbug.com/40055126): Ideally, we'd be able to mark some
    // of these as bad messages. We can't do that in all cases because there
    // are times some of these might legitimately fail (for instance, during
    // extension unload), but there are others that should never, ever happen
    // (privileged extension contexts in web processes).
    static constexpr char kInvalidContextType[] =
        "Invalid context type provided.";
    ResponseCallbackOnError(std::move(callback), ExtensionFunction::FAILED,
                            kInvalidContextType);
    return;
  }

  if (params.context_type == mojom::ContextType::kUntrustedWebUi) {
    // TODO(crbug.com/40265193): We should, at minimum, be using an
    // origin here. It'd be even better if we could have a more robust way of
    // checking that a process can host untrusted webui.
    if (extension || !render_frame_host_url ||
        !render_frame_host_url->SchemeIs(content::kChromeUIUntrustedScheme)) {
      constexpr char kInvalidWebUiUntrustedContext[] =
          "Context indicated it was untrusted webui, but is invalid.";
      ResponseCallbackOnError(std::move(callback), ExtensionFunction::FAILED,
                              kInvalidWebUiUntrustedContext);
      return;
    }
  }

  const bool is_worker_request = IsRequestFromServiceWorker(params);

  scoped_refptr<ExtensionFunction> function = CreateExtensionFunction(
      params, extension, render_process_id, is_worker_request,
      render_frame_host_url, params.context_type,
      ExtensionAPI::GetSharedInstance(), std::move(callback),
      render_frame_host);
  if (!function.get()) {
    return;
  }

  if (extension &&
      ExtensionsBrowserClient::Get()->CanExtensionCrossIncognito(
          extension, browser_context_)) {
    function->set_include_incognito_information(true);
  }

  if (!extension) {
    if (function->source_context_type() == mojom::ContextType::kWebUi) {
      base::UmaHistogramSparse("Extensions.Functions.WebUICalls",
                               function->histogram_value());
    } else if (function->source_context_type() ==
               mojom::ContextType::kUntrustedWebUi) {
      base::UmaHistogramSparse("Extensions.Functions.WebUIUntrustedCalls",
                               function->histogram_value());
    } else if (function->source_context_type() ==
               mojom::ContextType::kWebPage) {
      base::UmaHistogramSparse("Extensions.Functions.NonExtensionWebPageCalls",
                               function->histogram_value());
    }

    // Skip the quota, event page, activity logging stuff if there
    // isn't an extension, e.g. if the function call was from WebUI.
    function->RunWithValidation().Execute();
    return;
  }

  // Fetch the ProcessManager before |this| is possibly invalidated.
  ProcessManager* process_manager = ProcessManager::Get(browser_context_);

  ExtensionSystem* extension_system = ExtensionSystem::Get(browser_context_);
  QuotaService* quota = extension_system->quota_service();
  std::string violation_error =
      quota->Assess(extension->id(), function.get(), params.arguments,
                    base::TimeTicks::Now());

  function->set_request_uuid(base::Uuid::GenerateRandomV4());

  // Increment the keepalive to ensure the extension doesn't shut down while
  // it's executing an API function. This is balanced in
  // `OnExtensionFunctionCompleted()`.
  if (IsRequestFromServiceWorker(params)) {
    CHECK(function->worker_id());
    content::ServiceWorkerExternalRequestTimeoutType timeout_type =
        function->ShouldKeepWorkerAliveIndefinitely()
            ? content::ServiceWorkerExternalRequestTimeoutType::kDoesNotTimeout
            : content::ServiceWorkerExternalRequestTimeoutType::kDefault;
    function->set_service_worker_keepalive(
        std::make_unique<ServiceWorkerKeepalive>(
            browser_context_, *function->worker_id(), timeout_type,
            Activity::API_FUNCTION, function->name()));
  } else {
    process_manager->IncrementLazyKeepaliveCount(
        function->extension(), Activity::API_FUNCTION, function->name());
  }

  if (violation_error.empty()) {
    // See crbug.com/39178.
    ExtensionsBrowserClient::Get()->PermitExternalProtocolHandler();
    NotifyApiFunctionCalled(extension->id(), params.name, params.arguments,
                            browser_context_);

    // Since sandboxed frames listed in the manifest don't get access to the
    // extension APIs, this will only be true in an extension frame in an iframe
    // with the sandbox attribute specified, or served with a CSP header.
    bool is_sandboxed =
        render_frame_host && render_frame_host->IsSandboxed(
                                 network::mojom::WebSandboxFlags::kOrigin);
    // Note: Deliberately don't include external component extensions here -
    // this lets us differentiate between "built-in" extension calls and
    // external extension calls
    if (extension->location() == mojom::ManifestLocation::kComponent) {
      base::UmaHistogramSparse("Extensions.Functions.ComponentExtensionCalls",
                               function->histogram_value());
      if (is_sandboxed) {
        base::UmaHistogramBoolean(
            "Extensions.Functions.DidSandboxedComponentExtensionAPICall", true);
      }
    } else {
      base::UmaHistogramSparse("Extensions.Functions.ExtensionCalls",
                               function->histogram_value());
      if (is_sandboxed) {
        base::UmaHistogramBoolean(
            "Extensions.Functions.DidSandboxedExtensionAPICall", true);
      }
    }

    if (IsRequestFromServiceWorker(params)) {
      base::UmaHistogramSparse(
          "Extensions.Functions.ExtensionServiceWorkerCalls",
          function->histogram_value());
    }

    if (extension->manifest_version() == 3) {
      base::UmaHistogramSparse("Extensions.Functions.ExtensionMV3Calls",
                               function->histogram_value());
    }

    base::ElapsedTimer timer;
    function->RunWithValidation().Execute();
    // TODO(devlin): Once we have a baseline metric for how long functions take,
    // we can create a handful of buckets and record the function name so that
    // we can find what the fastest/slowest are.
    // Note: Many functions execute finish asynchronously, so this time is not
    // always a representation of total time taken. See also
    // Extensions.Functions.TotalExecutionTime.
    UMA_HISTOGRAM_TIMES("Extensions.Functions.SynchronousExecutionTime",
                        timer.Elapsed());
  } else {
    function->OnQuotaExceeded(violation_error);
  }

  // Note: do not access |this| after this point. We may have been deleted
  // if `function->RunWithValidation()` resulted in closing the execution
  // context for this function.
}

void ExtensionFunctionDispatcher::OnExtensionFunctionCompleted(
    ExtensionFunction& extension_function) {
  if (!extension_function.extension()) {
    // The function had no associated extension; nothing to clean up.
    return;
  }

  if (!extension_function.browser_context()) {
    // The ExtensionFunction's browser context is null'ed out when the browser
    // context is being shut down. If this happens, there's nothing to clean up.
    return;
  }

  if (!ExtensionRegistry::Get(browser_context_)
           ->enabled_extensions()
           .GetByID(extension_function.extension()->id())) {
    // The extension may have been unloaded (the ExtensionFunction holds a
    // reference to it, so it's still safe to access). If so, there's nothing to
    // // clean up.
    return;
  }

  ProcessManager* process_manager = ProcessManager::Get(browser_context_);
  if (extension_function.is_from_service_worker()) {
    CHECK(extension_function.request_uuid().is_valid());
    CHECK(extension_function.worker_id());

    extension_function.ResetServiceWorkerKeepalive();
  } else {
    process_manager->DecrementLazyKeepaliveCount(extension_function.extension(),
                                                 Activity::API_FUNCTION,
                                                 extension_function.name());
  }
}

WindowController*
ExtensionFunctionDispatcher::GetExtensionWindowController() const {
  return delegate_ ? delegate_->GetExtensionWindowController() : nullptr;
}

content::WebContents*
ExtensionFunctionDispatcher::GetAssociatedWebContents() const {
  return delegate_ ? delegate_->GetAssociatedWebContents() : nullptr;
}

content::WebContents*
ExtensionFunctionDispatcher::GetVisibleWebContents() const {
  return delegate_ ? delegate_->GetVisibleWebContents() : nullptr;
}

void ExtensionFunctionDispatcher::AddResponseTarget(ExtensionFunction* func) {
  response_targets_.insert(func);
}

void ExtensionFunctionDispatcher::ProcessResponseAck(
    const base::Uuid& request_uuid) {
  auto iter = std::ranges::find_if(
      response_targets_, [request_uuid](ExtensionFunction* function) {
        return function->request_uuid() == request_uuid;
      });
  if (iter == response_targets_.end()) {
    return;
  }
  // Calling this may cause the instance to delete itself, so no
  // referencing it after this!
  (*iter)->OnResponseAck();
  response_targets_.erase(iter);
}

scoped_refptr<ExtensionFunction>
ExtensionFunctionDispatcher::CreateExtensionFunction(
    const mojom::RequestParams& params,
    const Extension* extension,
    int requesting_process_id,
    bool is_worker_request,
    const GURL* render_frame_host_url,
    mojom::ContextType context_type,
    ExtensionAPI* api,
    ExtensionFunction::ResponseCallback callback,
    content::RenderFrameHost* render_frame_host) {
  constexpr char kCreationFailed[] = "Access to extension API denied.";

  scoped_refptr<ExtensionFunction> function =
      ExtensionFunctionRegistry::GetInstance().NewFunction(params.name);
  if (!function) {
    LOG(ERROR) << "Unknown Extension API - " << params.name;
    ResponseCallbackOnError(std::move(callback), ExtensionFunction::FAILED,
                            kCreationFailed);
    return nullptr;
  }

  function->SetArgs(params.arguments.Clone());

  // Determine the source URL. When possible, prefer fetching this value from
  // the RenderFrameHost, but fallback to the value in the `params` object if
  // necessary.
  // We can't use the frame URL in the case of a worker-based request (where
  // there is no frame).
  if (is_worker_request) {
    // TODO(crbug.com/40056469): Validate this URL further. Or, better,
    // remove it from `mojom::RequestParams`.
    function->set_source_url(params.source_url);
  } else {
    DCHECK(render_frame_host_url);
    function->set_source_url(*render_frame_host_url);
  }

  function->set_has_callback(params.has_callback);
  function->set_user_gesture(params.user_gesture);
  function->set_extension(extension);
  if (params.js_callstack.has_value()) {
    function->set_js_callstack(*params.js_callstack);
  }
  function->set_response_callback(std::move(callback));
  function->set_source_context_type(context_type);
  function->set_source_process_id(requesting_process_id);
  if (is_worker_request) {
    CHECK(extension);
    WorkerId worker_id;
    worker_id.thread_id = params.worker_thread_id;
    worker_id.version_id = params.service_worker_version_id;
    worker_id.render_process_id = requesting_process_id;
    worker_id.extension_id = extension->id();
    function->set_worker_id(std::move(worker_id));
  } else {
    function->SetRenderFrameHost(render_frame_host);
  }

  // Note: `SetDispatcher()` also initializes the `browser_context_` member
  // for `ExtensionFunction`, which is necessary for properly performing
  // permission checks.
  function->SetDispatcher(weak_ptr_factory_.GetWeakPtr());

  if (!function->HasPermission()) {
    LOG(ERROR) << "Permission denied for " << params.name;
    function->RespondWithError(kCreationFailed);
    return nullptr;
  }

  return function;
}
}  // namespace extensions
