// 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_features.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 "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(/*kFailed=*/true, base::Value::List(),
                            ToString(*bad_message_code), nullptr);
    return;
  }

  // TODO(crbug.com/40056469): Validate (or remove) `params.source_url`.
  DispatchWithCallbackInternal(
      std::move(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::ResponseType::kSucceeded,
                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(/*kFailed=*/true, 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(/*kFailed=*/true, 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(/*kFailed=*/true, base::Value::List(), "No SW",
                            nullptr);
    return;
  }

  DispatchWithCallbackInternal(
      std::move(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::ResponseType::kSucceeded,
                std::move(results), error, std::move(response_data));
          },
          std::move(callback)));
}

void ExtensionFunctionDispatcher::DispatchWithCallbackInternal(
    mojom::RequestParamsPtr 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::ResponseType::kFailed,
                            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::ResponseType::kFailed,
                            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::ResponseType::kFailed,
                              kInvalidWebUiUntrustedContext);
      return;
    }
  }

  const bool is_worker_request = IsRequestFromServiceWorker(*params);

  base::ListValue arguments;
  if (base::FeatureList::IsEnabled(
          extensions_features::kAvoidCloneArgsOnExtensionFunctionDispatch)) {
    arguments = std::move(params->arguments);
  } else {
    arguments = params->arguments.Clone();
  }

  scoped_refptr<ExtensionFunction> function = CreateExtensionFunction(
      *params, std::move(arguments), 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_);

  // TODO(crbug.com/424432184): When the
  // `kAvoidCloneArgsOnExtensionFunctionDispatch` feature is cleaned up, this
  // lambda can be removed and references to it can be replaced with
  // `function->GetOriginalArgs()`.
  auto original_args = [&]() -> const base::ListValue& {
    if (base::FeatureList::IsEnabled(
            extensions_features::kAvoidCloneArgsOnExtensionFunctionDispatch)) {
      return function->GetOriginalArgs();
    }
    return params->arguments;
  };

  ExtensionSystem* extension_system = ExtensionSystem::Get(browser_context_);
  QuotaService* quota = extension_system->quota_service();
  std::string violation_error = quota->Assess(
      extension->id(), function.get(), original_args(), 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 (is_worker_request) {
    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());
  }

  function->set_did_initialize();

  if (violation_error.empty()) {
    // See crbug.com/39178.
    ExtensionsBrowserClient::Get()->PermitExternalProtocolHandler();
    NotifyApiFunctionCalled(extension->id(), params->name, original_args(),
                            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 (is_worker_request) {
      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()) {
    if (extension_function.did_initialize()) {
      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_without_args,
    base::ListValue arguments,
    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_without_args.name);
  if (!function) {
    LOG(ERROR) << "Unknown Extension API - " << params_without_args.name;
    ResponseCallbackOnError(std::move(callback),
                            ExtensionFunction::ResponseType::kFailed,
                            kCreationFailed);
    return nullptr;
  }

  function->SetArgs(std::move(arguments));

  // 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_without_args.source_url);
  } else {
    DCHECK(render_frame_host_url);
    function->set_source_url(*render_frame_host_url);
  }

  function->set_has_callback(params_without_args.has_callback);
  function->set_user_gesture(params_without_args.user_gesture);
  function->set_extension(extension);
  if (params_without_args.js_callstack.has_value()) {
    function->set_js_callstack(*params_without_args.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_without_args.worker_thread_id;
    worker_id.version_id = params_without_args.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_without_args.name;
    function->RespondWithError(kCreationFailed);
    return nullptr;
  }

  return function;
}
}  // namespace extensions
