#include "chrome/common/chrome_content_client.h"
#include <stdint.h>
#include <memory>
#include <string>
#include <string_view>
#include <utility>
#include "base/check.h"
#include "base/containers/flat_set.h"
#include "base/functional/bind.h"
#include "base/json/json_reader.h"
#include "base/no_destructor.h"
#include "base/path_service.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/task/sequenced_task_runner.h"
#include "build/branding_buildflags.h"
#include "build/build_config.h"
#include "chrome/common/channel_info.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/crash_keys.h"
#include "chrome/common/media/cdm_registration.h"
#include "chrome/common/url_constants.h"
#include "chrome/grit/common_resources.h"
#include "chrome/grit/generated_resources.h"
#include "components/crash/core/common/crash_key.h"
#include "components/dom_distiller/core/url_constants.h"
#include "components/embedder_support/origin_trials/origin_trial_policy_impl.h"
#include "components/heap_profiling/in_process/child_process_snapshot_controller.h"
#include "components/heap_profiling/in_process/heap_profiler_controller.h"
#include "components/heap_profiling/in_process/mojom/snapshot_controller.mojom.h"
#include "components/services/heap_profiling/public/cpp/profiling_client.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/common/buildflags.h"
#include "content/public/common/cdm_info.h"
#include "content/public/common/content_constants.h"
#include "content/public/common/content_switches.h"
#include "content/public/common/url_constants.h"
#include "extensions/buildflags/buildflags.h"
#include "gpu/config/gpu_info.h"
#include "gpu/config/gpu_util.h"
#include "media/media_buildflags.h"
#include "mojo/public/cpp/bindings/binder_map.h"
#include "mojo/public/cpp/bindings/pending_receiver.h"
#include "net/http/http_util.h"
#include "pdf/buildflags.h"
#include "third_party/widevine/cdm/buildflags.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/resource/resource_scale_factor.h"
#include "url/url_constants.h"
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
BUILDFLAG(IS_CHROMEOS)
#include "components/webapps/isolated_web_apps/scheme.h"
#endif
#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS)
#include <fcntl.h>
#include "sandbox/linux/services/credentials.h"
#endif
#if BUILDFLAG(IS_WIN)
#include "base/win/windows_version.h"
#endif
#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
#include "extensions/common/constants.h"
#endif
#if BUILDFLAG(ENABLE_PLUGINS)
#include "content/public/common/webplugininfo.h"
#endif
#if BUILDFLAG(ENABLE_PDF)
#include "components/pdf/common/constants.h"
#include "components/pdf/common/pdf_util.h"
#endif
#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
#include "chrome/common/media/cdm_host_file_path.h"
#endif
#endif
#if BUILDFLAG(IS_ANDROID)
#include "chrome/common/media/chrome_media_drm_bridge_client.h"
#endif
#if BUILDFLAG(IS_ARKWEB) && BUILDFLAG(ARKWEB_ENABLE_CDM)
#include "chrome/common/media/chrome_media_drm_bridge_client_ohos.h"
#endif
namespace {
}
ChromeContentClient::ChromeContentClient() = default;
ChromeContentClient::~ChromeContentClient() = default;
void ChromeContentClient::SetActiveURL(const GURL& url,
std::string top_origin) {
static crash_reporter::CrashKeyString<1024> active_url("url-chunk");
active_url.Set(url.possibly_invalid_spec());
static crash_reporter::CrashKeyString<128> top_origin_key("top-origin");
top_origin_key.Set(top_origin);
}
void ChromeContentClient::SetGpuInfo(const gpu::GPUInfo& gpu_info) {
gpu::SetKeysForCrashLogging(gpu_info);
}
void ChromeContentClient::AddPlugins(
std::vector<content::WebPluginInfo>* plugins) {
#if BUILDFLAG(ENABLE_PDF)
#if BUILDFLAG(GOOGLE_CHROME_BRANDING)
static constexpr char16_t kPDFPluginName[] = u"Chrome PDF Plugin";
#else
static constexpr char16_t kPDFPluginName[] = u"Chromium PDF Plugin";
#endif
static constexpr char16_t kPDFPluginDescription[] = u"Built-in PDF viewer";
static constexpr char kPDFPluginExtension[] = "pdf";
static constexpr char kPDFPluginExtensionDescription[] =
"Portable Document Format";
content::WebPluginInfo pdf_info;
pdf_info.name = kPDFPluginName;
pdf_info.path = base::FilePath(ChromeContentClient::kPDFInternalPluginPath);
pdf_info.desc = kPDFPluginDescription;
content::WebPluginMimeType pdf_mime_type(pdf::kInternalPluginMimeType,
kPDFPluginExtension,
kPDFPluginExtensionDescription);
pdf_info.mime_types.push_back(pdf_mime_type);
pdf_info.type = content::WebPluginInfo::PLUGIN_TYPE_BROWSER_INTERNAL_PLUGIN;
plugins->push_back(pdf_info);
#endif
}
void ChromeContentClient::AddContentDecryptionModules(
std::vector<content::CdmInfo>* cdms,
std::vector<media::CdmHostFilePath>* cdm_host_file_paths) {
if (cdms)
RegisterCdmInfo(cdms);
#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
#if BUILDFLAG(ENABLE_CDM_HOST_VERIFICATION)
if (cdm_host_file_paths)
AddCdmHostFilePaths(cdm_host_file_paths);
#endif
#endif
}
static const char* const kChromeStandardURLSchemes[] = {
#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
extensions::kExtensionScheme,
#if BUILDFLAG(ARKWEB_ARKWEB_EXTENSIONS)
extensions::kArkwebExtensionScheme,
#endif
#endif
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
BUILDFLAG(IS_CHROMEOS)
webapps::kIsolatedAppScheme,
#endif
chrome::kChromeNativeScheme, chrome::kChromeSearchScheme,
dom_distiller::kDomDistillerScheme,
#if BUILDFLAG(IS_ANDROID)
content::kAndroidAppScheme,
#endif
};
void ChromeContentClient::AddAdditionalSchemes(Schemes* schemes) {
for (auto* standard_scheme : kChromeStandardURLSchemes)
schemes->standard_schemes.push_back(standard_scheme);
#if BUILDFLAG(IS_ANDROID)
schemes->referrer_schemes.push_back(content::kAndroidAppScheme);
#endif
#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
schemes->extension_schemes.push_back(extensions::kExtensionScheme);
#if BUILDFLAG(ARKWEB_ARKWEB_EXTENSIONS)
schemes->extension_schemes.push_back(extensions::kArkwebExtensionScheme);
#endif
#endif
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
BUILDFLAG(IS_CHROMEOS)
schemes->isolated_app_schemes.push_back(webapps::kIsolatedAppScheme);
#endif
#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
schemes->savable_schemes.push_back(extensions::kExtensionScheme);
#if BUILDFLAG(ARKWEB_ARKWEB_EXTENSIONS)
schemes->savable_schemes.push_back(extensions::kArkwebExtensionScheme);
#endif
#endif
schemes->savable_schemes.push_back(chrome::kChromeSearchScheme);
schemes->savable_schemes.push_back(dom_distiller::kDomDistillerScheme);
schemes->secure_schemes.push_back(chrome::kChromeSearchScheme);
#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
schemes->secure_schemes.push_back(extensions::kExtensionScheme);
#if BUILDFLAG(ARKWEB_ARKWEB_EXTENSIONS)
schemes->secure_schemes.push_back(extensions::kArkwebExtensionScheme);
#endif
#endif
schemes->empty_document_schemes.push_back(chrome::kChromeNativeScheme);
schemes->no_access_schemes.push_back(chrome::kChromeNativeScheme);
schemes->secure_schemes.push_back(chrome::kChromeNativeScheme);
#if BUILDFLAG(ENABLE_EXTENSIONS_CORE)
schemes->service_worker_schemes.push_back(extensions::kExtensionScheme);
schemes->service_worker_schemes.push_back(url::kFileScheme);
schemes->cors_enabled_schemes.push_back(extensions::kExtensionScheme);
schemes->csp_bypassing_schemes.push_back(extensions::kExtensionScheme);
#if BUILDFLAG(ARKWEB_ARKWEB_EXTENSIONS)
schemes->service_worker_schemes.push_back(extensions::kArkwebExtensionScheme);
schemes->cors_enabled_schemes.push_back(extensions::kArkwebExtensionScheme);
schemes->csp_bypassing_schemes.push_back(extensions::kArkwebExtensionScheme);
#endif
#endif
#if BUILDFLAG(IS_CHROMEOS)
schemes->predefined_handler_schemes.emplace_back(
url::kMailToScheme, chrome::kChromeOSDefaultMailtoHandler);
schemes->predefined_handler_schemes.emplace_back(
url::kWebcalScheme, chrome::kChromeOSDefaultWebcalHandler);
#endif
#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_MAC) || BUILDFLAG(IS_LINUX) || \
BUILDFLAG(IS_CHROMEOS)
schemes->secure_schemes.push_back(webapps::kIsolatedAppScheme);
schemes->cors_enabled_schemes.push_back(webapps::kIsolatedAppScheme);
schemes->service_worker_schemes.push_back(webapps::kIsolatedAppScheme);
url::AddWebStorageScheme(webapps::kIsolatedAppScheme);
#endif
#if BUILDFLAG(IS_CHROMEOS)
schemes->local_schemes.push_back(content::kExternalFileScheme);
#endif
#if BUILDFLAG(IS_ANDROID)
schemes->local_schemes.push_back(url::kContentScheme);
#endif
}
std::u16string ChromeContentClient::GetLocalizedString(int message_id) {
return l10n_util::GetStringUTF16(message_id);
}
std::u16string ChromeContentClient::GetLocalizedString(
int message_id,
const std::u16string& replacement) {
return l10n_util::GetStringFUTF16(message_id, replacement);
}
bool ChromeContentClient::HasDataResource(int resource_id) const {
return ui::ResourceBundle::GetSharedInstance().HasDataResource(resource_id);
}
std::string_view ChromeContentClient::GetDataResource(
int resource_id,
ui::ResourceScaleFactor scale_factor) {
return ui::ResourceBundle::GetSharedInstance().GetRawDataResourceForScale(
resource_id, scale_factor);
}
base::RefCountedMemory* ChromeContentClient::GetDataResourceBytes(
int resource_id) {
return ui::ResourceBundle::GetSharedInstance().LoadDataResourceBytes(
resource_id);
}
std::string ChromeContentClient::GetDataResourceString(int resource_id) {
return ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(
resource_id);
}
gfx::Image& ChromeContentClient::GetNativeImageNamed(int resource_id) {
return ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(
resource_id);
}
std::string ChromeContentClient::GetProcessTypeNameInEnglish(int type) {
NOTREACHED() << "Unknown child process type!";
}
blink::OriginTrialPolicy* ChromeContentClient::GetOriginTrialPolicy() {
base::AutoLock auto_lock(origin_trial_policy_lock_);
if (!origin_trial_policy_)
origin_trial_policy_ =
std::make_unique<embedder_support::OriginTrialPolicyImpl>();
return origin_trial_policy_.get();
}
#if BUILDFLAG(IS_ANDROID)
media::MediaDrmBridgeClient* ChromeContentClient::GetMediaDrmBridgeClient() {
return new ChromeMediaDrmBridgeClient();
}
#endif
#if BUILDFLAG(IS_ARKWEB) && BUILDFLAG(ARKWEB_ENABLE_CDM)
media::OHOSMediaDrmBridgeClient* ChromeContentClient::GetMediaDrmBridgeClient() {
return new ChromeMediaDrmBridgeClientOHOS();
}
#endif
void ChromeContentClient::ExposeInterfacesToBrowser(
scoped_refptr<base::SequencedTaskRunner> io_task_runner,
mojo::BinderMap* binders) {
binders
->Add<heap_profiling::mojom::ProfilingClient>(
[](mojo::PendingReceiver<heap_profiling::mojom::ProfilingClient>
receiver) {
static base::NoDestructor<heap_profiling::ProfilingClient>
profiling_client;
profiling_client->BindToInterface(std::move(receiver));
},
io_task_runner);
const auto* heap_profiler_controller =
heap_profiling::HeapProfilerController::GetInstance();
if (heap_profiler_controller && heap_profiler_controller->IsEnabled()) {
binders->Add<heap_profiling::mojom::SnapshotController>(
&heap_profiling::ChildProcessSnapshotController::
CreateSelfOwnedReceiver,
base::SequencedTaskRunner::GetCurrentDefault());
}
}
bool ChromeContentClient::IsFilePickerAllowedForCrossOriginSubframe(
const url::Origin& origin) {
#if BUILDFLAG(ENABLE_PDF)
return IsPdfExtensionOrigin(origin);
#else
return false;
#endif
}