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

#include "chrome/browser/extensions/api/scripting/scripting_api.h"

#include "base/check.h"
#include "base/containers/contains.h"
#include "base/json/json_writer.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/types/optional_util.h"
#include "chrome/common/extensions/api/scripting.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_entry.h"
#include "extensions/browser/extension_api_frame_id_map.h"
#include "extensions/browser/extension_file_task_runner.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_system.h"
#include "extensions/browser/extension_user_script_loader.h"
#include "extensions/browser/extension_util.h"
#include "extensions/browser/load_and_localize_file.h"
#include "extensions/browser/script_executor.h"
#include "extensions/browser/scripting_constants.h"
#include "extensions/browser/scripting_utils.h"
#include "extensions/browser/user_script_manager.h"
#include "extensions/common/api/extension_types.h"
#include "extensions/common/api/scripts_internal.h"
#include "extensions/common/api/scripts_internal/script_serialization.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/extension.h"
#include "extensions/common/manifest_constants.h"
#include "extensions/common/mojom/css_origin.mojom-shared.h"
#include "extensions/common/mojom/execution_world.mojom-shared.h"
#include "extensions/common/mojom/host_id.mojom.h"
#include "extensions/common/mojom/match_origin_as_fallback.mojom-shared.h"
#include "extensions/common/mojom/run_location.mojom-shared.h"
#include "extensions/common/permissions/permissions_data.h"
#include "extensions/common/user_script.h"
#include "extensions/common/utils/content_script_utils.h"
#include "extensions/common/utils/extension_types_utils.h"

namespace extensions {

namespace {

constexpr char kEmptyMatchesError[] =
    "Script with ID '*' must specify 'matches'.";
constexpr char kExactlyOneOfCssAndFilesError[] =
    "Exactly one of 'css' and 'files' must be specified.";

// Note: CSS always injects as soon as possible, so we default to
// document_start. Because of tab loading, there's no guarantee this will
// *actually* inject before page load, but it will at least inject "soon".
constexpr mojom::RunLocation kCSSRunLocation =
    mojom::RunLocation::kDocumentStart;

// Converts the given `style_origin` to a CSSOrigin.
mojom::CSSOrigin ConvertStyleOriginToCSSOrigin(
    api::scripting::StyleOrigin style_origin) {
  mojom::CSSOrigin css_origin = mojom::CSSOrigin::kAuthor;
  switch (style_origin) {
    case api::scripting::StyleOrigin::kNone:
    case api::scripting::StyleOrigin::kAuthor:
      css_origin = mojom::CSSOrigin::kAuthor;
      break;
    case api::scripting::StyleOrigin::kUser:
      css_origin = mojom::CSSOrigin::kUser;
      break;
  }

  return css_origin;
}

mojom::ExecutionWorld ConvertExecutionWorld(
    api::scripting::ExecutionWorld world) {
  mojom::ExecutionWorld execution_world = mojom::ExecutionWorld::kIsolated;
  switch (world) {
    case api::scripting::ExecutionWorld::kNone:
    case api::scripting::ExecutionWorld::kIsolated:
      break;  // Default to mojom::ExecutionWorld::kIsolated.
    case api::scripting::ExecutionWorld::kMain:
      execution_world = mojom::ExecutionWorld::kMain;
  }

  return execution_world;
}

scripting::InjectionTarget ConvertToInternalInjectionTarget(
    api::scripting::InjectionTarget injection_target) {
  scripting::InjectionTarget internal_injection_target;
  internal_injection_target.all_frames = injection_target.all_frames;
  internal_injection_target.document_ids =
      std::move(injection_target.document_ids);
  internal_injection_target.frame_ids = std::move(injection_target.frame_ids);
  internal_injection_target.tab_id = std::move(injection_target.tab_id);
  return internal_injection_target;
}

std::string InjectionKeyForCode(const mojom::HostID& host_id,
                                const std::string& code) {
  return ScriptExecutor::GenerateInjectionKey(host_id, /*script_url=*/GURL(),
                                              code);
}

std::string InjectionKeyForFile(const mojom::HostID& host_id,
                                const GURL& resource_url) {
  return ScriptExecutor::GenerateInjectionKey(host_id, resource_url,
                                              /*code=*/std::string());
}

std::vector<mojom::JSSourcePtr> FileSourcesToJSSources(
    const Extension& extension,
    std::vector<scripting::InjectedFileSource> file_sources) {
  std::vector<mojom::JSSourcePtr> js_sources;
  js_sources.reserve(file_sources.size());
  for (auto& file_source : file_sources) {
    js_sources.push_back(mojom::JSSource::New(
        std::move(*file_source.data),
        extension.ResolveExtensionURL(file_source.file_name)));
  }

  return js_sources;
}

std::vector<mojom::CSSSourcePtr> FileSourcesToCSSSources(
    const Extension& extension,
    std::vector<scripting::InjectedFileSource> file_sources) {
  mojom::HostID host_id(mojom::HostID::HostType::kExtensions, extension.id());

  std::vector<mojom::CSSSourcePtr> css_sources;
  css_sources.reserve(file_sources.size());
  for (auto& file_source : file_sources) {
    css_sources.push_back(mojom::CSSSource::New(
        std::move(*file_source.data),
        InjectionKeyForFile(
            host_id, extension.ResolveExtensionURL(file_source.file_name))));
  }

  return css_sources;
}

api::scripts_internal::SerializedUserScript
ConvertRegisteredContentScriptToSerializedUserScript(
    api::scripting::RegisteredContentScript content_script) {
  auto convert_execution_world = [](api::scripting::ExecutionWorld world) {
    switch (world) {
      case api::scripting::ExecutionWorld::kNone:
      case api::scripting::ExecutionWorld::kIsolated:
        return api::extension_types::ExecutionWorld::kIsolated;
      case api::scripting::ExecutionWorld::kMain:
        return api::extension_types::ExecutionWorld::kMain;
    }
  };

  api::scripts_internal::SerializedUserScript serialized_script;
  serialized_script.source =
      api::scripts_internal::Source::kDynamicContentScript;

  // Note: IDs have already been prefixed appropriately.
  serialized_script.id = std::move(content_script.id);
  // Note: `matches` are guaranteed to be non-null.
  serialized_script.matches = std::move(*content_script.matches);
  serialized_script.exclude_matches = std::move(content_script.exclude_matches);
  if (content_script.css) {
    serialized_script.css = script_serialization::GetSourcesFromFileNames(
        std::move(*content_script.css));
  }
  if (content_script.js) {
    serialized_script.js = script_serialization::GetSourcesFromFileNames(
        std::move(*content_script.js));
  }
  serialized_script.all_frames = content_script.all_frames;
  serialized_script.match_origin_as_fallback =
      content_script.match_origin_as_fallback;
  serialized_script.run_at = content_script.run_at;
  serialized_script.world = convert_execution_world(content_script.world);

  return serialized_script;
}

std::unique_ptr<UserScript> ParseUserScript(
    content::BrowserContext* browser_context,
    const Extension& extension,
    bool allowed_in_incognito,
    api::scripting::RegisteredContentScript content_script,
    std::u16string* error) {
  api::scripts_internal::SerializedUserScript serialized_script =
      ConvertRegisteredContentScriptToSerializedUserScript(
          std::move(content_script));

  std::unique_ptr<UserScript> user_script =
      script_serialization::ParseSerializedUserScript(
          serialized_script, extension, allowed_in_incognito, error);
  if (!user_script) {
    return nullptr;  // Parsing failed.
  }

  return user_script;
}

// Converts a UserScript object to a api::scripting::RegisteredContentScript
// object, used for getRegisteredContentScripts.
api::scripting::RegisteredContentScript CreateRegisteredContentScriptInfo(
    const UserScript& script) {
  CHECK_EQ(UserScript::Source::kDynamicContentScript, script.GetSource());

  // To convert a `UserScript`, we first go through our script_internal
  // serialization; this allows us to do simple conversions and avoid any
  // complex logic.
  api::scripts_internal::SerializedUserScript serialized_script =
      script_serialization::SerializeUserScript(script);

  auto convert_serialized_script_sources =
      [](std::vector<api::scripts_internal::ScriptSource> sources) {
        std::vector<std::string> converted;
        converted.reserve(sources.size());
        for (auto& source : sources) {
          CHECK(source.file)
              << "Content scripts don't allow arbtirary code strings";
          converted.push_back(std::move(*source.file));
        }
        return converted;
      };

  auto convert_execution_world =
      [](api::extension_types::ExecutionWorld world) {
        switch (world) {
          case api::extension_types::ExecutionWorld::kNone:
            NOTREACHED()
                << "Execution world should always be present in serialization.";
          case api::extension_types::ExecutionWorld::kIsolated:
            return api::scripting::ExecutionWorld::kIsolated;
          case api::extension_types::ExecutionWorld::kUserScript:
            NOTREACHED() << "ISOLATED worlds are not supported in this API.";
          case api::extension_types::ExecutionWorld::kMain:
            return api::scripting::ExecutionWorld::kMain;
        }
      };

  api::scripting::RegisteredContentScript content_script;
  content_script.id = std::move(serialized_script.id);
  content_script.matches = std::move(serialized_script.matches);
  content_script.exclude_matches = std::move(serialized_script.exclude_matches);
  if (serialized_script.css) {
    content_script.css =
        convert_serialized_script_sources(std::move(*serialized_script.css));
  }
  if (serialized_script.js) {
    content_script.js =
        convert_serialized_script_sources(std::move(*serialized_script.js));
  }
  content_script.all_frames = serialized_script.all_frames;
  content_script.match_origin_as_fallback =
      serialized_script.match_origin_as_fallback;
  content_script.run_at = serialized_script.run_at;
  content_script.world = convert_execution_world(serialized_script.world);

  return content_script;
}

}  // namespace

ScriptingExecuteScriptFunction::ScriptingExecuteScriptFunction() = default;
ScriptingExecuteScriptFunction::~ScriptingExecuteScriptFunction() = default;

ExtensionFunction::ResponseAction ScriptingExecuteScriptFunction::Run() {
  std::optional<api::scripting::ExecuteScript::Params> params =
      api::scripting::ExecuteScript::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);
  injection_ = std::move(params->injection);

  // Silently alias `function` to `func` for backwards compatibility.
  // TODO(devlin): Remove this in M95.
  if (injection_.function) {
    if (injection_.func) {
      return RespondNow(
          Error("Both 'func' and 'function' were specified. "
                "Only 'func' should be used."));
    }
    injection_.func = std::move(injection_.function);
  }

  if ((injection_.files && injection_.func) ||
      (!injection_.files && !injection_.func)) {
    return RespondNow(
        Error("Exactly one of 'func' and 'files' must be specified"));
  }

  if (injection_.files) {
    if (injection_.args)
      return RespondNow(Error("'args' may not be used with file injections."));

    // JS files don't require localization.
    constexpr bool kRequiresLocalization = false;
    std::string error;
    if (!CheckAndLoadFiles(
            std::move(*injection_.files),
            script_parsing::ContentScriptType::kJs, *extension(),
            kRequiresLocalization,
            base::BindOnce(&ScriptingExecuteScriptFunction::DidLoadResources,
                           this),
            &error)) {
      return RespondNow(Error(std::move(error)));
    }
    return RespondLater();
  }

  DCHECK(injection_.func);

  // TODO(devlin): This (wrapping a function to create an IIFE) is pretty hacky,
  // and along with the JSON-serialization of the arguments to curry in.
  // Add support to the ScriptExecutor to better support this case.
  std::string args_expression;
  if (injection_.args) {
    std::vector<std::string> string_args;
    string_args.reserve(injection_.args->size());
    for (const auto& arg : *injection_.args) {
      std::string json;
      if (!base::JSONWriter::Write(arg, &json))
        return RespondNow(Error("Unserializable argument passed."));
      string_args.push_back(std::move(json));
    }
    args_expression = base::JoinString(string_args, ",");
  }

  std::string code_to_execute = base::StringPrintf(
      "(%s)(%s)", injection_.func->c_str(), args_expression.c_str());

  std::vector<mojom::JSSourcePtr> sources;
  sources.push_back(mojom::JSSource::New(std::move(code_to_execute), GURL()));

  std::string error;
  if (!Execute(std::move(sources), &error))
    return RespondNow(Error(std::move(error)));

  return RespondLater();
}

void ScriptingExecuteScriptFunction::DidLoadResources(
    std::vector<scripting::InjectedFileSource> file_sources,
    std::optional<std::string> load_error) {
  if (load_error) {
    Respond(Error(std::move(*load_error)));
    return;
  }

  DCHECK(!file_sources.empty());

  std::string error;
  if (!Execute(FileSourcesToJSSources(*extension(), std::move(file_sources)),
               &error)) {
    Respond(Error(std::move(error)));
  }
}

bool ScriptingExecuteScriptFunction::Execute(
    std::vector<mojom::JSSourcePtr> sources,
    std::string* error) {
  scripting::InjectionTarget internal_injection_target =
      ConvertToInternalInjectionTarget(std::move(injection_.target));
  ScriptExecutor* script_executor = nullptr;
  ScriptExecutor::FrameScope frame_scope = ScriptExecutor::SPECIFIED_FRAMES;
  std::set<int> frame_ids;
  if (!scripting::CanAccessTarget(
          *extension()->permissions_data(), internal_injection_target,
          browser_context(), include_incognito_information(), &script_executor,
          &frame_scope, &frame_ids, error)) {
    return false;
  }

  mojom::ExecutionWorld execution_world =
      ConvertExecutionWorld(injection_.world);
  // scripting.executeScript() doesn't support selecting execution world id.
  std::optional<std::string> execution_world_id = std::nullopt;
  bool inject_immediately = injection_.inject_immediately.value_or(false);

  scripting::ExecuteScript(
      extension()->id(), std::move(sources), execution_world,
      execution_world_id, script_executor, frame_scope, frame_ids,
      inject_immediately, user_gesture(),
      base::BindOnce(&ScriptingExecuteScriptFunction::OnScriptExecuted, this));

  return true;
}

void ScriptingExecuteScriptFunction::OnScriptExecuted(
    std::vector<ScriptExecutor::FrameResult> frame_results) {
  // If only a single frame was included and the injection failed, respond with
  // an error.
  if (frame_results.size() == 1 && !frame_results[0].error.empty()) {
    Respond(Error(std::move(frame_results[0].error)));
    return;
  }

  // Otherwise, respond successfully. We currently just skip over individual
  // frames that failed. In the future, we can bubble up these error messages
  // to the extension.
  std::vector<api::scripting::InjectionResult> injection_results;
  for (auto& result : frame_results) {
    if (!result.error.empty())
      continue;
    api::scripting::InjectionResult injection_result;
    injection_result.result = std::move(result.value);
    injection_result.frame_id = result.frame_id;
    if (result.document_id)
      injection_result.document_id = result.document_id.ToString();

    // Put the top frame first; otherwise, any order.
    if (result.frame_id == ExtensionApiFrameIdMap::kTopFrameId) {
      injection_results.insert(injection_results.begin(),
                               std::move(injection_result));
    } else {
      injection_results.push_back(std::move(injection_result));
    }
  }

  Respond(ArgumentList(
      api::scripting::ExecuteScript::Results::Create(injection_results)));
}

ScriptingInsertCSSFunction::ScriptingInsertCSSFunction() = default;
ScriptingInsertCSSFunction::~ScriptingInsertCSSFunction() = default;

ExtensionFunction::ResponseAction ScriptingInsertCSSFunction::Run() {
  std::optional<api::scripting::InsertCSS::Params> params =
      api::scripting::InsertCSS::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  injection_ = std::move(params->injection);

  if ((injection_.files && injection_.css) ||
      (!injection_.files && !injection_.css)) {
    return RespondNow(Error(kExactlyOneOfCssAndFilesError));
  }

  if (injection_.files) {
    // CSS files require localization.
    constexpr bool kRequiresLocalization = true;
    std::string error;
    if (!CheckAndLoadFiles(
            std::move(*injection_.files),
            script_parsing::ContentScriptType::kCss, *extension(),
            kRequiresLocalization,
            base::BindOnce(&ScriptingInsertCSSFunction::DidLoadResources, this),
            &error)) {
      return RespondNow(Error(std::move(error)));
    }
    return RespondLater();
  }

  DCHECK(injection_.css);

  mojom::HostID host_id(mojom::HostID::HostType::kExtensions,
                        extension()->id());

  std::vector<mojom::CSSSourcePtr> sources;
  sources.push_back(
      mojom::CSSSource::New(std::move(*injection_.css),
                            InjectionKeyForCode(host_id, *injection_.css)));

  std::string error;
  if (!Execute(std::move(sources), &error)) {
    return RespondNow(Error(std::move(error)));
  }

  return RespondLater();
}

void ScriptingInsertCSSFunction::DidLoadResources(
    std::vector<scripting::InjectedFileSource> file_sources,
    std::optional<std::string> load_error) {
  if (load_error) {
    Respond(Error(std::move(*load_error)));
    return;
  }

  DCHECK(!file_sources.empty());
  std::vector<mojom::CSSSourcePtr> sources =
      FileSourcesToCSSSources(*extension(), std::move(file_sources));

  std::string error;
  if (!Execute(std::move(sources), &error))
    Respond(Error(std::move(error)));
}

bool ScriptingInsertCSSFunction::Execute(
    std::vector<mojom::CSSSourcePtr> sources,
    std::string* error) {
  scripting::InjectionTarget internal_injection_target =
      ConvertToInternalInjectionTarget(std::move(injection_.target));
  ScriptExecutor* script_executor = nullptr;
  ScriptExecutor::FrameScope frame_scope = ScriptExecutor::SPECIFIED_FRAMES;
  std::set<int> frame_ids;
  if (!scripting::CanAccessTarget(
          *extension()->permissions_data(), internal_injection_target,
          browser_context(), include_incognito_information(), &script_executor,
          &frame_scope, &frame_ids, error)) {
    return false;
  }
  DCHECK(script_executor);

  script_executor->ExecuteScript(
      mojom::HostID(mojom::HostID::HostType::kExtensions, extension()->id()),
      mojom::CodeInjection::NewCss(mojom::CSSInjection::New(
          std::move(sources), ConvertStyleOriginToCSSOrigin(injection_.origin),
          mojom::CSSInjection::Operation::kAdd)),
      frame_scope, frame_ids, mojom::MatchOriginAsFallbackBehavior::kAlways,
      kCSSRunLocation, ScriptExecutor::DEFAULT_PROCESS,
      /* webview_src */ GURL(),
      base::BindOnce(&ScriptingInsertCSSFunction::OnCSSInserted, this));

  return true;
}

void ScriptingInsertCSSFunction::OnCSSInserted(
    std::vector<ScriptExecutor::FrameResult> results) {
  // If only a single frame was included and the injection failed, respond with
  // an error.
  if (results.size() == 1 && !results[0].error.empty()) {
    Respond(Error(std::move(results[0].error)));
    return;
  }

  Respond(NoArguments());
}

ScriptingRemoveCSSFunction::ScriptingRemoveCSSFunction() = default;
ScriptingRemoveCSSFunction::~ScriptingRemoveCSSFunction() = default;

ExtensionFunction::ResponseAction ScriptingRemoveCSSFunction::Run() {
  std::optional<api::scripting::RemoveCSS::Params> params =
      api::scripting::RemoveCSS::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  api::scripting::CSSInjection& injection = params->injection;

  if ((injection.files && injection.css) ||
      (!injection.files && !injection.css)) {
    return RespondNow(Error(kExactlyOneOfCssAndFilesError));
  }

  scripting::InjectionTarget internal_injection_target =
      ConvertToInternalInjectionTarget(std::move(injection.target));
  ScriptExecutor* script_executor = nullptr;
  ScriptExecutor::FrameScope frame_scope = ScriptExecutor::SPECIFIED_FRAMES;
  std::set<int> frame_ids;
  std::string error;
  if (!scripting::CanAccessTarget(
          *extension()->permissions_data(), internal_injection_target,
          browser_context(), include_incognito_information(), &script_executor,
          &frame_scope, &frame_ids, &error)) {
    return RespondNow(Error(std::move(error)));
  }
  DCHECK(script_executor);

  mojom::HostID host_id(mojom::HostID::HostType::kExtensions,
                        extension()->id());
  std::vector<mojom::CSSSourcePtr> sources;

  if (injection.files) {
    std::vector<ExtensionResource> resources;
    if (!scripting::GetFileResources(*injection.files,
                                     script_parsing::ContentScriptType::kCss,
                                     *extension(), &resources, &error)) {
      return RespondNow(Error(std::move(error)));
    }

    // Note: Since we're just removing the CSS, we don't actually need to load
    // the file here. It's okay for `code` to be empty in this case.
    const std::string empty_code;
    sources.reserve(injection.files->size());

    for (const auto& file : *injection.files) {
      sources.push_back(mojom::CSSSource::New(
          empty_code, InjectionKeyForFile(
                          host_id, extension()->ResolveExtensionURL(file))));
    }
  } else {
    DCHECK(injection.css);
    sources.push_back(
        mojom::CSSSource::New(std::move(*injection.css),
                              InjectionKeyForCode(host_id, *injection.css)));
  }

  script_executor->ExecuteScript(
      std::move(host_id),
      mojom::CodeInjection::NewCss(mojom::CSSInjection::New(
          std::move(sources), ConvertStyleOriginToCSSOrigin(injection.origin),
          mojom::CSSInjection::Operation::kRemove)),
      frame_scope, frame_ids, mojom::MatchOriginAsFallbackBehavior::kAlways,
      kCSSRunLocation, ScriptExecutor::DEFAULT_PROCESS,
      /* webview_src */ GURL(),
      base::BindOnce(&ScriptingRemoveCSSFunction::OnCSSRemoved, this));

  return RespondLater();
}

void ScriptingRemoveCSSFunction::OnCSSRemoved(
    std::vector<ScriptExecutor::FrameResult> results) {
  // If only a single frame was included and the injection failed, respond with
  // an error.
  if (results.size() == 1 && !results[0].error.empty()) {
    Respond(Error(std::move(results[0].error)));
    return;
  }

  Respond(NoArguments());
}

ScriptingRegisterContentScriptsFunction::
    ScriptingRegisterContentScriptsFunction() = default;
ScriptingRegisterContentScriptsFunction::
    ~ScriptingRegisterContentScriptsFunction() = default;

ExtensionFunction::ResponseAction
ScriptingRegisterContentScriptsFunction::Run() {
  std::optional<api::scripting::RegisterContentScripts::Params> params =
      api::scripting::RegisterContentScripts::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  std::vector<api::scripting::RegisteredContentScript>& scripts =
      params->scripts;
  ExtensionUserScriptLoader* loader =
      ExtensionSystem::Get(browser_context())
          ->user_script_manager()
          ->GetUserScriptLoaderForExtension(extension()->id());

  // Create script ids for dynamic content scripts.
  std::string error;
  std::set<std::string> existing_script_ids =
      loader->GetDynamicScriptIDs(UserScript::Source::kDynamicContentScript);
  std::set<std::string> new_script_ids = scripting::CreateDynamicScriptIds(
      scripts, UserScript::Source::kDynamicContentScript, existing_script_ids,
      &error);

  if (!error.empty()) {
    CHECK(new_script_ids.empty());
    return RespondNow(Error(std::move(error)));
  }

  // Parse content scripts.
  std::u16string parse_error;
  UserScriptList parsed_scripts;
  std::set<std::string> persistent_script_ids;

  bool allowed_in_incognito = scripting::ScriptsShouldBeAllowedInIncognito(
      extension()->id(), browser_context());

  parsed_scripts.reserve(scripts.size());
  for (auto& script : scripts) {
    if (!script.matches) {
      return RespondNow(Error(ErrorUtils::FormatErrorMessage(
          kEmptyMatchesError, UserScript::TrimPrefixFromScriptID(script.id))));
    }

    // Scripts will persist across sessions by default.
    bool persist_across_sessions =
        script.persist_across_sessions.value_or(true);

    std::unique_ptr<UserScript> user_script =
        ParseUserScript(browser_context(), *extension(), allowed_in_incognito,
                        std::move(script), &parse_error);
    if (!user_script) {
      return RespondNow(Error(base::UTF16ToASCII(parse_error)));
    }

    if (persist_across_sessions) {
      persistent_script_ids.insert(user_script->id());
    }
    parsed_scripts.push_back(std::move(user_script));
  }
  // The contents of `scripts` have all been std::move()'d.
  scripts.clear();

  // Add new script IDs now in case another call with the same script IDs is
  // made immediately following this one.
  loader->AddPendingDynamicScriptIDs(std::move(new_script_ids));

  GetExtensionFileTaskRunner()->PostTaskAndReplyWithResult(
      FROM_HERE,
      base::BindOnce(&scripting::ValidateParsedScriptsOnFileThread,
                     script_parsing::GetSymlinkPolicy(extension()),
                     std::move(parsed_scripts)),
      base::BindOnce(&ScriptingRegisterContentScriptsFunction::
                         OnContentScriptFilesValidated,
                     this, std::move(persistent_script_ids)));

  // Balanced in `OnContentScriptFilesValidated()` or
  // `OnContentScriptsRegistered()`.
  AddRef();
  return RespondLater();
}

void ScriptingRegisterContentScriptsFunction::OnContentScriptFilesValidated(
    std::set<std::string> persistent_script_ids,
    scripting::ValidateScriptsResult result) {
  // We cannot proceed if the `browser_context` is not valid as the
  // `ExtensionSystem` will not exist.
  if (!browser_context()) {
    Release();  // Matches the `AddRef()` in `Run()`.
    return;
  }

  // We cannot proceed if the extension is uninstalled or unloaded in the middle
  // of validating its script files.
  ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
  if (!extension() ||
      !registry->enabled_extensions().Contains(extension_id())) {
    // Note: a Respond() is not needed if the system is shutting down or if the
    // extension is no longer enabled.
    Release();  // Matches the `AddRef()` in `Run()`.
    return;
  }

  auto error = std::move(result.second);
  auto scripts = std::move(result.first);
  ExtensionUserScriptLoader* loader =
      ExtensionSystem::Get(browser_context())
          ->user_script_manager()
          ->GetUserScriptLoaderForExtension(extension()->id());

  if (error.has_value()) {
    std::set<std::string> ids_to_remove;
    for (const auto& script : scripts) {
      ids_to_remove.insert(script->id());
    }

    loader->RemovePendingDynamicScriptIDs(std::move(ids_to_remove));
    Respond(Error(std::move(*error)));
    Release();  // Matches the `AddRef()` in `Run()`.
    return;
  }

  loader->AddDynamicScripts(
      std::move(scripts), std::move(persistent_script_ids),
      base::BindOnce(
          &ScriptingRegisterContentScriptsFunction::OnContentScriptsRegistered,
          this));
}

void ScriptingRegisterContentScriptsFunction::OnContentScriptsRegistered(
    const std::optional<std::string>& error) {
  if (error.has_value())
    Respond(Error(std::move(*error)));
  else
    Respond(NoArguments());
  Release();  // Matches the `AddRef()` in `Run()`.
}

ScriptingGetRegisteredContentScriptsFunction::
    ScriptingGetRegisteredContentScriptsFunction() = default;
ScriptingGetRegisteredContentScriptsFunction::
    ~ScriptingGetRegisteredContentScriptsFunction() = default;

ExtensionFunction::ResponseAction
ScriptingGetRegisteredContentScriptsFunction::Run() {
  std::optional<api::scripting::GetRegisteredContentScripts::Params> params =
      api::scripting::GetRegisteredContentScripts::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  const std::optional<api::scripting::ContentScriptFilter>& filter =
      params->filter;
  std::set<std::string> id_filter;
  if (filter && filter->ids) {
    for (const std::string& id : *(filter->ids)) {
      id_filter.insert(scripting::AddPrefixToDynamicScriptId(
          id, UserScript::Source::kDynamicContentScript));
    }
  }

  ExtensionUserScriptLoader* loader =
      ExtensionSystem::Get(browser_context())
          ->user_script_manager()
          ->GetUserScriptLoaderForExtension(extension()->id());
  const UserScriptList& dynamic_scripts = loader->GetLoadedDynamicScripts();

  std::vector<api::scripting::RegisteredContentScript> script_infos;
  std::set<std::string> persistent_script_ids =
      loader->GetPersistentDynamicScriptIDs();
  for (const std::unique_ptr<UserScript>& script : dynamic_scripts) {
    if (script->GetSource() != UserScript::Source::kDynamicContentScript) {
      continue;
    }

    if (!id_filter.empty() && !base::Contains(id_filter, script->id())) {
      continue;
    }

    auto registered_script = CreateRegisteredContentScriptInfo(*script);
    registered_script.persist_across_sessions =
        base::Contains(persistent_script_ids, script->id());

    // Remove the internally used prefix from the `script`'s ID before
    // returning.
    registered_script.id = script->GetIDWithoutPrefix();
    script_infos.push_back(std::move(registered_script));
  }

  return RespondNow(
      ArgumentList(api::scripting::GetRegisteredContentScripts::Results::Create(
          script_infos)));
}

ScriptingUnregisterContentScriptsFunction::
    ScriptingUnregisterContentScriptsFunction() = default;
ScriptingUnregisterContentScriptsFunction::
    ~ScriptingUnregisterContentScriptsFunction() = default;

ExtensionFunction::ResponseAction
ScriptingUnregisterContentScriptsFunction::Run() {
  auto params =
      api::scripting::UnregisterContentScripts::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  std::optional<api::scripting::ContentScriptFilter>& filter = params->filter;
  std::optional<std::vector<std::string>> ids = std::nullopt;
  // TODO(crbug.com/40216362): `ids` should have an empty list when filter ids
  // is empty, instead of a nullopt. Otherwise, we are incorrectly removing all
  // content scripts when ids is empty.
  if (filter && filter->ids && !filter->ids->empty()) {
    ids = std::move(filter->ids);
  }

  std::string error;
  bool removal_triggered = scripting::RemoveScripts(
      ids, UserScript::Source::kDynamicContentScript, browser_context(),
      extension()->id(),
      base::BindOnce(&ScriptingUnregisterContentScriptsFunction::
                         OnContentScriptsUnregistered,
                     this),
      &error);

  if (!removal_triggered) {
    CHECK(!error.empty());
    return RespondNow(Error(std::move(error)));
  }

  return RespondLater();
}

void ScriptingUnregisterContentScriptsFunction::OnContentScriptsUnregistered(
    const std::optional<std::string>& error) {
  if (error.has_value())
    Respond(Error(std::move(*error)));
  else
    Respond(NoArguments());
}

ScriptingUpdateContentScriptsFunction::ScriptingUpdateContentScriptsFunction() =
    default;
ScriptingUpdateContentScriptsFunction::
    ~ScriptingUpdateContentScriptsFunction() = default;

ExtensionFunction::ResponseAction ScriptingUpdateContentScriptsFunction::Run() {
  std::optional<api::scripting::UpdateContentScripts::Params> params =
      api::scripting::UpdateContentScripts::Params::Create(args());
  EXTENSION_FUNCTION_VALIDATE(params);

  std::vector<api::scripting::RegisteredContentScript>& scripts_to_update =
      params->scripts;
  std::string error;

  // Add the prefix for dynamic content scripts onto the IDs of all
  // `scripts_to_update` before continuing.
  std::set<std::string> ids_to_update = scripting::CreateDynamicScriptIds(
      scripts_to_update, UserScript::Source::kDynamicContentScript,
      std::set<std::string>(), &error);

  if (!error.empty()) {
    CHECK(ids_to_update.empty());
    return RespondNow(Error(std::move(error)));
  }

  ExtensionUserScriptLoader* loader =
      ExtensionSystem::Get(browser_context())
          ->user_script_manager()
          ->GetUserScriptLoaderForExtension(extension()->id());

  std::set<std::string> updated_script_ids_to_persist;
  UserScriptList parsed_scripts = scripting::UpdateScripts(
      scripts_to_update, UserScript::Source::kDynamicContentScript, *loader,
      base::BindRepeating(&CreateRegisteredContentScriptInfo),
      base::BindRepeating(&ScriptingUpdateContentScriptsFunction::ApplyUpdate,
                          this, &updated_script_ids_to_persist),
      &error);

  if (!error.empty()) {
    CHECK(parsed_scripts.empty());
    return RespondNow(Error(std::move(error)));
  }

  // Add new script IDs now in case another call with the same script IDs is
  // made immediately following this one.
  loader->AddPendingDynamicScriptIDs(std::move(ids_to_update));

  GetExtensionFileTaskRunner()->PostTaskAndReplyWithResult(
      FROM_HERE,
      base::BindOnce(&scripting::ValidateParsedScriptsOnFileThread,
                     script_parsing::GetSymlinkPolicy(extension()),
                     std::move(parsed_scripts)),
      base::BindOnce(
          &ScriptingUpdateContentScriptsFunction::OnContentScriptFilesValidated,
          this, std::move(updated_script_ids_to_persist)));

  // Balanced in `OnContentScriptFilesValidated()` or
  // `OnContentScriptsRegistered()`.
  AddRef();
  return RespondLater();
}

std::unique_ptr<UserScript> ScriptingUpdateContentScriptsFunction::ApplyUpdate(
    std::set<std::string>* script_ids_to_persist,
    api::scripting::RegisteredContentScript& new_script,
    api::scripting::RegisteredContentScript& original_script,
    std::u16string* parse_error) {
  if (new_script.matches) {
    original_script.matches = std::move(new_script.matches);
  }

  if (new_script.exclude_matches) {
    original_script.exclude_matches = std::move(new_script.exclude_matches);
  }

  if (new_script.js) {
    original_script.js = std::move(new_script.js);
  }

  if (new_script.css) {
    original_script.css = std::move(new_script.css);
  }

  if (new_script.all_frames) {
    *original_script.all_frames = *new_script.all_frames;
  }

  if (new_script.match_origin_as_fallback) {
    *original_script.match_origin_as_fallback =
        *new_script.match_origin_as_fallback;
  }

  if (new_script.run_at != api::extension_types::RunAt::kNone) {
    original_script.run_at = new_script.run_at;
  }

  // Note: for the update application, we disregard allowed_in_incognito.
  // We'll set it on the resulting scripts.
  constexpr bool kAllowedInIncognito = false;

  // Parse content script.
  std::unique_ptr<UserScript> parsed_script =
      ParseUserScript(browser_context(), *extension(), kAllowedInIncognito,
                      std::move(original_script), parse_error);
  if (!parsed_script) {
    return nullptr;
  }

  // Persist the updated script if the flag is specified as true, or if the
  // original script is persisted and the flag is not specified.
  if (new_script.persist_across_sessions.value_or(false) ||
      (!new_script.persist_across_sessions &&
       base::Contains(*script_ids_to_persist, new_script.id))) {
    script_ids_to_persist->insert(new_script.id);
  }

  return parsed_script;
}

void ScriptingUpdateContentScriptsFunction::OnContentScriptFilesValidated(
    std::set<std::string> persistent_script_ids,
    scripting::ValidateScriptsResult result) {
  // We cannot proceed if the `browser_context` is not valid as the
  // `ExtensionSystem` will not exist.
  if (!browser_context()) {
    Release();  // Matches the `AddRef()` in `Run()`.
    return;
  }

  // We cannot proceed if the extension is uninstalled or unloaded in the middle
  // of validating its script files.
  ExtensionRegistry* registry = ExtensionRegistry::Get(browser_context());
  if (!extension() ||
      !registry->enabled_extensions().Contains(extension_id())) {
    // Note: a Respond() is not needed if the system is shutting down or if the
    // extension is no longer enabled.
    Release();  // Matches the `AddRef()` in `Run()`.
    return;
  }

  auto error = std::move(result.second);
  auto scripts = std::move(result.first);
  ExtensionUserScriptLoader* loader =
      ExtensionSystem::Get(browser_context())
          ->user_script_manager()
          ->GetUserScriptLoaderForExtension(extension()->id());

  bool allowed_in_incognito = scripting::ScriptsShouldBeAllowedInIncognito(
      extension()->id(), browser_context());

  std::set<std::string> script_ids;
  for (const auto& script : scripts) {
    script_ids.insert(script->id());

    script->set_incognito_enabled(allowed_in_incognito);
  }

  if (error.has_value()) {
    loader->RemovePendingDynamicScriptIDs(script_ids);
    Respond(Error(std::move(*error)));
    Release();  // Matches the `AddRef()` in `Run()`.
    return;
  }

  loader->UpdateDynamicScripts(
      std::move(scripts), std::move(script_ids),
      std::move(persistent_script_ids),
      base::BindOnce(
          &ScriptingUpdateContentScriptsFunction::OnContentScriptsUpdated,
          this));
}

void ScriptingUpdateContentScriptsFunction::OnContentScriptsUpdated(
    const std::optional<std::string>& error) {
  if (error.has_value())
    Respond(Error(std::move(*error)));
  else
    Respond(NoArguments());
  Release();  // Matches the `AddRef()` in `Run()`.
}

}  // namespace extensions
