// 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/renderer_startup_helper.h"

#include <string>
#include <utility>
#include <vector>

#include "base/containers/adapters.h"
#include "base/containers/contains.h"
#include "base/debug/dump_without_crashing.h"
#include "base/functional/callback_helpers.h"
#include "base/memory/ptr_util.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/string_util.h"
#include "base/task/thread_pool.h"
#include "base/unguessable_token.h"
#include "base/values.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/render_process_host.h"
#include "extensions/browser/bad_message.h"
#include "extensions/browser/extension_function_dispatcher.h"
#include "extensions/browser/extension_prefs.h"
#include "extensions/browser/extension_registry.h"
#include "extensions/browser/extension_util.h"
#include "extensions/browser/extensions_browser_client.h"
#include "extensions/browser/guest_view/web_view/web_view_guest.h"
#include "extensions/browser/guest_view/web_view/web_view_renderer_state.h"
#include "extensions/browser/l10n_file_util.h"
#include "extensions/browser/network_permissions_updater.h"
#include "extensions/browser/process_manager.h"
#include "extensions/browser/process_manager_factory.h"
#include "extensions/browser/service_worker/service_worker_task_queue.h"
#include "extensions/browser/user_script_world_configuration_manager.h"
#include "extensions/common/extension_id.h"
#include "extensions/common/extension_l10n_util.h"
#include "extensions/common/extension_set.h"
#include "extensions/common/extensions_client.h"
#include "extensions/common/features/feature_channel.h"
#include "extensions/common/features/feature_developer_mode_only.h"
#include "extensions/common/features/feature_session_type.h"
#include "extensions/common/manifest_handlers/background_info.h"
#include "extensions/common/manifest_handlers/default_locale_handler.h"
#include "extensions/common/manifest_handlers/shared_module_info.h"
#include "extensions/common/message_bundle.h"
#include "extensions/common/permissions/permissions_data.h"
#include "ipc/ipc_channel_proxy.h"
#include "ui/base/webui/web_ui_util.h"
#include "url/origin.h"

namespace extensions {

namespace {

using ::content::BrowserContext;

// Returns the current activation sequence of |extension| if the extension is
// Service Worker-based, otherwise returns std::nullopt.
std::optional<base::UnguessableToken> GetWorkerActivationToken(
    BrowserContext* browser_context,
    const Extension& extension) {
  if (BackgroundInfo::IsServiceWorkerBased(&extension)) {
    return ServiceWorkerTaskQueue::Get(browser_context)
        ->GetCurrentActivationToken(extension.id());
  }
  return std::nullopt;
}

PermissionSet CreatePermissionSet(const PermissionSet& set) {
  return PermissionSet(set.apis().Clone(), set.manifest_permissions().Clone(),
                       set.explicit_hosts().Clone(),
                       set.scriptable_hosts().Clone());
}

mojom::ExtensionLoadedParamsPtr CreateExtensionLoadedParams(
    const Extension& extension,
    bool include_tab_permissions,
    BrowserContext* browser_context) {
  const PermissionsData* permissions_data = extension.permissions_data();

  base::flat_map<int, PermissionSet> tab_specific_permissions;
  if (include_tab_permissions) {
    for (const auto& pair : permissions_data->tab_specific_permissions()) {
      tab_specific_permissions[pair.first] = CreatePermissionSet(*pair.second);
    }
  }

  return mojom::ExtensionLoadedParams::New(
      extension.manifest()->value()->Clone(), extension.location(),
      extension.path(),
      CreatePermissionSet(permissions_data->active_permissions()),
      CreatePermissionSet(permissions_data->withheld_permissions()),
      std::move(tab_specific_permissions),
      permissions_data->policy_blocked_hosts(),
      permissions_data->policy_allowed_hosts(),
      permissions_data->UsesDefaultPolicyHostRestrictions(), extension.id(),
      GetWorkerActivationToken(browser_context, extension),
      extension.creation_flags(), extension.guid());
}

base::flat_map<std::string, std::string> ToFlatMap(
    const std::map<std::string, std::string>& map) {
  return {map.begin(), map.end()};
}

}  // namespace

RendererStartupHelper::RendererStartupHelper(BrowserContext* browser_context)
    : browser_context_(browser_context) {
  DCHECK(browser_context);
}

RendererStartupHelper::~RendererStartupHelper() {
  for (auto& process_entry : process_mojo_map_)
    process_entry.first->RemoveObserver(this);
}

void RendererStartupHelper::OnRenderProcessHostCreated(
    content::RenderProcessHost* host) {
  InitializeProcess(host);
}

void RendererStartupHelper::RenderProcessExited(
    content::RenderProcessHost* host,
    const content::ChildProcessTerminationInfo& info) {
  UntrackProcess(host);
}

void RendererStartupHelper::RenderProcessHostDestroyed(
    content::RenderProcessHost* host) {
  UntrackProcess(host);
}

void RendererStartupHelper::InitializeProcess(
    content::RenderProcessHost* process) {
  ExtensionsBrowserClient* client = ExtensionsBrowserClient::Get();
  if (!client->IsSameContext(browser_context_, process->GetBrowserContext()))
    return;

  mojom::Renderer* renderer =
      process_mojo_map_.emplace(process, BindNewRendererRemote(process))
          .first->second.get();
  process->AddObserver(this);

  bool activity_logging_enabled =
      client->IsActivityLoggingEnabled(process->GetBrowserContext());
  // We only send the ActivityLoggingEnabled message if it is enabled; otherwise
  // the default (not enabled) is correct.
  if (activity_logging_enabled)
    renderer->SetActivityLoggingEnabled(activity_logging_enabled);

  // extensions need to know the developer mode value for api restrictions.
  renderer->SetDeveloperMode(
      GetCurrentDeveloperMode(util::GetBrowserContextId(browser_context_)));

  // Extensions need to know the channel and the session type for API
  // restrictions. The values are sent to all renderers, as the non-extension
  // renderers may have content scripts.
  bool is_lock_screen_context =
      client->IsLockScreenContext(process->GetBrowserContext());
  renderer->SetSessionInfo(GetCurrentChannel(), GetCurrentFeatureSessionType(),
                           is_lock_screen_context);

  // Platform apps need to know the system font.
  // TODO(dbeam): this is not the system font in all cases.
  renderer->SetSystemFont(webui::GetFontFamily(), webui::GetFontSize());

  // Scripting allowlist. This is modified by tests and must be communicated
  // to renderers.
  renderer->SetScriptingAllowlist(
      ExtensionsClient::Get()->GetScriptingAllowlist());

  // If the new render process is a WebView guest process, propagate the WebView
  // partition ID to it.
  if (WebViewRendererState::GetInstance()->IsGuest(process->GetID())) {
    std::string webview_partition_id = WebViewGuest::GetPartitionID(process);
    renderer->SetWebViewPartitionID(webview_partition_id);
  }

  BrowserContext* renderer_context = process->GetBrowserContext();

  // Load default policy_blocked_hosts and policy_allowed_hosts settings, part
  // of the ExtensionSettings policy.
  int context_id = util::GetBrowserContextId(renderer_context);
  renderer->UpdateDefaultPolicyHostRestrictions(
      PermissionsData::GetDefaultPolicyBlockedHosts(context_id),
      PermissionsData::GetDefaultPolicyAllowedHosts(context_id));

  renderer->UpdateUserHostRestrictions(
      PermissionsData::GetUserBlockedHosts(context_id),
      PermissionsData::GetUserAllowedHosts(context_id));

  // Loaded extensions.
  std::vector<mojom::ExtensionLoadedParamsPtr> loaded_extensions;
  const ExtensionSet& extensions =
      ExtensionRegistry::Get(browser_context_)->enabled_extensions();
  for (const auto& ext : extensions) {
    // OnExtensionLoaded should have already been called for the extension.
    DCHECK(base::Contains(extension_process_map_, ext->id()));
    DCHECK(!base::Contains(extension_process_map_[ext->id()], process));

    if (!util::IsExtensionVisibleToContext(*ext, renderer_context))
      continue;

    // TODO(kalman): Only include tab specific permissions for extension
    // processes, no other process needs it, so it's mildly wasteful.
    // I am not sure this is possible to know this here, at such a low
    // level of the stack. Perhaps site isolation can help.
    loaded_extensions.push_back(CreateExtensionLoadedParams(
        *ext, true /* include tab permissions*/, renderer_context));
    extension_process_map_[ext->id()].insert(process);

    // Each extension needs to know its user script world configurations.
    std::vector<mojom::UserScriptWorldInfoPtr> worlds_info =
        UserScriptWorldConfigurationManager::Get(browser_context_)
            ->GetAllUserScriptWorlds(ext->id());
    renderer->UpdateUserScriptWorlds(std::move(worlds_info));
  }

  // Activate pending extensions.
  renderer->LoadExtensions(std::move(loaded_extensions));
  auto iter = pending_active_extensions_.find(process);
  if (iter != pending_active_extensions_.end()) {
    for (const ExtensionId& id : iter->second) {
      // The extension should be loaded in the process.
      DCHECK(extensions.Contains(id));
      DCHECK(base::Contains(extension_process_map_, id));
      DCHECK(base::Contains(extension_process_map_[id], process));
      renderer->ActivateExtension(id);
    }
  }

  pending_active_extensions_.erase(process);
}

void RendererStartupHelper::UntrackProcess(
    content::RenderProcessHost* process) {
  if (!ExtensionsBrowserClient::Get()->IsSameContext(
          browser_context_, process->GetBrowserContext())) {
    return;
  }

  process->RemoveObserver(this);
  process_mojo_map_.erase(process);
  pending_active_extensions_.erase(process);
  for (auto& extension_process_pair : extension_process_map_)
    extension_process_pair.second.erase(process);
}

void RendererStartupHelper::ActivateExtensionInProcess(
    const Extension& extension,
    content::RenderProcessHost* process) {
  // The extension should have been loaded already. Dump without crashing to
  // debug crbug.com/528026.
  if (!base::Contains(extension_process_map_, extension.id())) {
#if DCHECK_IS_ON()
    NOTREACHED_IN_MIGRATION()
        << "Extension " << extension.id() << " activated before loading";
#else
    base::debug::DumpWithoutCrashing();
    return;
#endif
  }

  if (!util::IsExtensionVisibleToContext(extension,
                                         process->GetBrowserContext()))
    return;

  // Populate NetworkContext's OriginAccessList for this extension.
  //
  // Doing it in ActivateExtensionInProcess rather than in OnExtensionLoaded
  // ensures that we cover both the regular profile and incognito profiles.  See
  // also https://crbug.com/1197798.
  //
  // This is guaranteed to happen before the extension can make any network
  // requests (so there is no race) because ActivateExtensionInProcess will
  // always be called before creating URLLoaderFactory for any extension frames
  // that might be eventually hosted inside the renderer `process` (this
  // Browser-side ordering will be replicated within the NetworkService because
  // `SetCorsOriginAccessListsForOrigin()`, which is used in
  // NetworkPermissionsUpdater, and `CreateURLLoaderFactory()` are 2 methods
  // of the same mojom::NetworkContext interface).
  NetworkPermissionsUpdater::UpdateExtension(
      *process->GetBrowserContext(), extension,
      NetworkPermissionsUpdater::ContextSet::kCurrentContextOnly,
      base::DoNothing());

  auto remote = process_mojo_map_.find(process);
  if (remote != process_mojo_map_.end()) {
    DCHECK(base::Contains(extension_process_map_[extension.id()], process));
    remote->second->ActivateExtension(extension.id());
  } else {
    pending_active_extensions_[process].insert(extension.id());
  }
}

void RendererStartupHelper::OnExtensionLoaded(const Extension& extension) {
  DCHECK(!base::Contains(extension_process_map_, extension.id()));

  // Mark the extension as loaded.
  std::set<raw_ptr<content::RenderProcessHost, SetExperimental>>&
      loaded_process_set = extension_process_map_[extension.id()];

  // util::IsExtensionVisibleToContext() would filter out themes, but we choose
  // to return early for performance reasons.
  if (extension.is_theme())
    return;

  for (auto& process_entry : process_mojo_map_) {
    content::RenderProcessHost* process = process_entry.first;
    if (!util::IsExtensionVisibleToContext(extension,
                                           process->GetBrowserContext()))
      continue;

    // We don't need to include tab permissions here, since the extension
    // was just loaded.
    // Uninitialized renderers will be informed of the extension load during the
    // first batch of messages.
    std::vector<mojom::ExtensionLoadedParamsPtr> params;
    params.emplace_back(CreateExtensionLoadedParams(
        extension, false /* no tab permissions */, browser_context_));

    mojom::Renderer* renderer = GetRenderer(process);
    if (renderer)
      renderer->LoadExtensions(std::move(params));

    loaded_process_set.insert(process);
  }
}

void RendererStartupHelper::OnExtensionUnloaded(const Extension& extension) {
  DCHECK(base::Contains(extension_process_map_, extension.id()));

  const std::set<raw_ptr<content::RenderProcessHost, SetExperimental>>&
      loaded_process_set = extension_process_map_[extension.id()];
  for (content::RenderProcessHost* process : loaded_process_set) {
    mojom::Renderer* renderer = GetRenderer(process);
    if (renderer)
      renderer->UnloadExtension(extension.id());
  }

  // Resets registered origin access lists in the BrowserContext asynchronously.
  NetworkPermissionsUpdater::ResetOriginAccessForExtension(*browser_context_,
                                                           extension);

  for (auto& process_extensions_pair : pending_active_extensions_)
    process_extensions_pair.second.erase(extension.id());

  // Mark the extension as unloaded.
  extension_process_map_.erase(extension.id());
}

void RendererStartupHelper::OnDeveloperModeChanged(bool in_developer_mode) {
  for (auto& process_entry : process_mojo_map_) {
    content::RenderProcessHost* process = process_entry.first;
    mojom::Renderer* renderer = GetRenderer(process);
    if (renderer)
      renderer->SetDeveloperMode(in_developer_mode);
  }
}

void RendererStartupHelper::SetUserScriptWorldProperties(
    const Extension& extension,
    std::optional<std::string> world_id,
    std::optional<std::string> csp,
    bool enable_messaging) {
  mojom::UserScriptWorldInfoPtr info = mojom::UserScriptWorldInfo::New(
      extension.id(), std::move(world_id), std::move(csp), enable_messaging);
  for (auto& process_entry : process_mojo_map_) {
    content::RenderProcessHost* process = process_entry.first;
    mojom::Renderer* renderer = GetRenderer(process);
    if (!renderer) {
      continue;
    }

    if (!util::IsExtensionVisibleToContext(extension,
                                           process->GetBrowserContext())) {
      continue;
    }

    std::vector<mojom::UserScriptWorldInfoPtr> worlds_info;
    worlds_info.push_back(info.Clone());
    renderer->UpdateUserScriptWorlds(std::move(worlds_info));
  }
}

void RendererStartupHelper::ClearUserScriptWorldProperties(
    const Extension& extension,
    const std::optional<std::string>& world_id) {
  for (auto& process_entry : process_mojo_map_) {
    content::RenderProcessHost* process = process_entry.first;
    mojom::Renderer* renderer = GetRenderer(process);
    if (!renderer) {
      continue;
    }

    if (!util::IsExtensionVisibleToContext(extension,
                                           process->GetBrowserContext())) {
      continue;
    }

    renderer->ClearUserScriptWorldConfig(extension.id(), world_id);
  }
}

mojo::PendingAssociatedRemote<mojom::Renderer>
RendererStartupHelper::BindNewRendererRemote(
    content::RenderProcessHost* process) {
  mojo::AssociatedRemote<mojom::Renderer> renderer_interface;
  process->GetChannel()->GetRemoteAssociatedInterface(&renderer_interface);
  return renderer_interface.Unbind();
}

mojom::Renderer* RendererStartupHelper::GetRenderer(
    content::RenderProcessHost* process) {
  auto it = process_mojo_map_.find(process);
  if (it == process_mojo_map_.end())
    return nullptr;
  return it->second.get();
}

BrowserContext* RendererStartupHelper::GetRendererBrowserContext() {
  // `browser_context_` is redirected to remove incognito mode. This method
  // returns the original browser context associated with the renderer.
  auto* host = content::RenderProcessHost::FromID(receivers_.current_context());
  if (!host) {
    return nullptr;
  }

  return host->GetBrowserContext();
}

void RendererStartupHelper::AddAPIActionToActivityLog(
    const ExtensionId& extension_id,
    const std::string& call_name,
    base::Value::List args,
    const std::string& extra) {
  auto* browser_context = GetRendererBrowserContext();
  if (!browser_context) {
    return;
  }

  ExtensionsBrowserClient::Get()->AddAPIActionToActivityLog(
      browser_context, extension_id, call_name, std::move(args), extra);
}

void RendererStartupHelper::AddEventToActivityLog(
    const ExtensionId& extension_id,
    const std::string& call_name,
    base::Value::List args,
    const std::string& extra) {
  auto* browser_context = GetRendererBrowserContext();
  if (!browser_context) {
    return;
  }

  ExtensionsBrowserClient::Get()->AddEventToActivityLog(
      browser_context, extension_id, call_name, std::move(args), extra);
}

void RendererStartupHelper::AddDOMActionToActivityLog(
    const ExtensionId& extension_id,
    const std::string& call_name,
    base::Value::List args,
    const GURL& url,
    const std::u16string& url_title,
    int32_t call_type) {
  auto* browser_context = GetRendererBrowserContext();
  if (!browser_context) {
    return;
  }

  ExtensionsBrowserClient::Get()->AddDOMActionToActivityLog(
      browser_context, extension_id, call_name, std::move(args), url, url_title,
      call_type);
}

// static
void RendererStartupHelper::BindForRenderer(
    int process_id,
    mojo::PendingAssociatedReceiver<mojom::RendererHost> receiver) {
  auto* host = content::RenderProcessHost::FromID(process_id);
  if (!host) {
    return;
  }

  auto* renderer_startup_helper =
      RendererStartupHelperFactory::GetForBrowserContext(
          host->GetBrowserContext());
  renderer_startup_helper->receivers_.Add(renderer_startup_helper,
                                          std::move(receiver), process_id);
}

void RendererStartupHelper::WakeEventPage(const ExtensionId& extension_id,
                                          WakeEventPageCallback callback) {
  auto* browser_context = GetRendererBrowserContext();
  if (!browser_context) {
    std::move(callback).Run(false);
    return;
  }

  const Extension* extension = ExtensionRegistry::Get(browser_context)
                                   ->enabled_extensions()
                                   .GetByID(extension_id);
  if (!extension) {
    // Don't kill the renderer, it might just be some context which hasn't
    // caught up to extension having been uninstalled.
    std::move(callback).Run(false);
    return;
  }

  ProcessManager* process_manager = ProcessManager::Get(browser_context);

  if (BackgroundInfo::HasLazyBackgroundPage(extension)) {
    // Wake the event page if it's asleep, or immediately repond with success
    // if it's already awake.
    if (process_manager->IsEventPageSuspended(extension_id)) {
      process_manager->WakeEventPage(extension_id, std::move(callback));
    } else {
      std::move(callback).Run(true);
    }
    return;
  }

  if (BackgroundInfo::HasPersistentBackgroundPage(extension)) {
    // No point in trying to wake a persistent background page. If it's open,
    // immediately return and call it a success. If it's closed, fail.
    std::move(callback).Run(process_manager->GetBackgroundHostForExtension(
                                extension_id) != nullptr);
    return;
  }

  // The extension has no background page, so there is nothing to wake.
  std::move(callback).Run(false);
}

void RendererStartupHelper::GetMessageBundle(
    const ExtensionId& extension_id,
    GetMessageBundleCallback callback) {
  auto* browser_context = GetRendererBrowserContext();
  if (!browser_context) {
    std::move(callback).Run({});
    return;
  }

  const ExtensionSet& extension_set =
      ExtensionRegistry::Get(browser_context)->enabled_extensions();
  const Extension* extension = extension_set.GetByID(extension_id);

  if (!extension) {  // The extension has gone.
    std::move(callback).Run({});
    return;
  }

  const std::string& default_locale = LocaleInfo::GetDefaultLocale(extension);
  if (default_locale.empty()) {
    // A little optimization: send the answer here to avoid an extra thread hop.
    std::unique_ptr<MessageBundle::SubstitutionMap> dictionary_map(
        l10n_file_util::LoadNonLocalizedMessageBundleSubstitutionMap(
            extension_id));
    std::move(callback).Run(ToFlatMap(*dictionary_map));
    return;
  }

  std::vector<base::FilePath> paths_to_load;
  paths_to_load.push_back(extension->path());

  auto imports = SharedModuleInfo::GetImports(extension);
  // Iterate through the imports in reverse.  This will allow later imported
  // modules to override earlier imported modules, as the list order is
  // maintained from the definition in manifest.json of the imports.
  for (const SharedModuleInfo::ImportInfo& import : base::Reversed(imports)) {
    const Extension* imported_extension =
        extension_set.GetByID(import.extension_id);
    if (!imported_extension) {
      NOTREACHED_IN_MIGRATION()
          << "Missing shared module " << import.extension_id;
      continue;
    }
    paths_to_load.push_back(imported_extension->path());
  }

  // This blocks tab loading. Priority is inherited from the calling context.
  base::ThreadPool::PostTaskAndReplyWithResult(
      FROM_HERE, {base::MayBlock()},
      base::BindOnce(
          [](const std::vector<base::FilePath>& extension_paths,
             const ExtensionId& main_extension_id,
             const std::string& default_locale,
             extension_l10n_util::GzippedMessagesPermission gzip_permission) {
            return base::WrapUnique<MessageBundle::SubstitutionMap>(
                l10n_file_util::LoadMessageBundleSubstitutionMapFromPaths(
                    extension_paths, main_extension_id, default_locale,
                    gzip_permission));
          },
          paths_to_load, extension_id, default_locale,
          extension_l10n_util::GetGzippedMessagesPermissionForExtension(
              extension)),
      base::BindOnce(
          [](GetMessageBundleCallback callback,
             std::unique_ptr<MessageBundle::SubstitutionMap> dictionary_map) {
            std::move(callback).Run(ToFlatMap(*dictionary_map));
          },
          std::move(callback)));
}

//////////////////////////////////////////////////////////////////////////////

// static
RendererStartupHelper* RendererStartupHelperFactory::GetForBrowserContext(
    BrowserContext* context) {
  return static_cast<RendererStartupHelper*>(
      GetInstance()->GetServiceForBrowserContext(context, true));
}

// static
RendererStartupHelperFactory* RendererStartupHelperFactory::GetInstance() {
  return base::Singleton<RendererStartupHelperFactory>::get();
}

RendererStartupHelperFactory::RendererStartupHelperFactory()
    : BrowserContextKeyedServiceFactory(
          "RendererStartupHelper",
          BrowserContextDependencyManager::GetInstance()) {
  DependsOn(ProcessManagerFactory::GetInstance());
}

RendererStartupHelperFactory::~RendererStartupHelperFactory() = default;

std::unique_ptr<KeyedService>
RendererStartupHelperFactory::BuildServiceInstanceForBrowserContext(
    BrowserContext* context) const {
  return std::make_unique<RendererStartupHelper>(context);
}

BrowserContext* RendererStartupHelperFactory::GetBrowserContextToUse(
    BrowserContext* context) const {
  // Redirected in incognito.
  return ExtensionsBrowserClient::Get()->GetContextRedirectedToOriginal(
      context, /*force_guest_profile=*/true);
}

bool RendererStartupHelperFactory::ServiceIsCreatedWithBrowserContext() const {
  return true;
}

}  // namespace extensions
