web_engine_content_browser_client.cc 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. // Copyright 2018 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "fuchsia_web/webengine/browser/web_engine_content_browser_client.h"
  5. #include <string>
  6. #include <utility>
  7. #include "base/callback.h"
  8. #include "base/command_line.h"
  9. #include "base/i18n/rtl.h"
  10. #include "base/strings/string_split.h"
  11. #include "components/embedder_support/user_agent_utils.h"
  12. #include "components/policy/content/safe_sites_navigation_throttle.h"
  13. #include "components/site_isolation/features.h"
  14. #include "components/site_isolation/preloaded_isolated_origins.h"
  15. #include "components/strings/grit/components_locale_settings.h"
  16. #include "components/url_rewrite/common/url_loader_throttle.h"
  17. #include "components/url_rewrite/common/url_request_rewrite_rules.h"
  18. #include "components/version_info/version_info.h"
  19. #include "content/public/browser/client_certificate_delegate.h"
  20. #include "content/public/browser/devtools_manager_delegate.h"
  21. #include "content/public/browser/navigation_handle.h"
  22. #include "content/public/browser/network_service_instance.h"
  23. #include "content/public/common/content_switches.h"
  24. #include "fuchsia_web/common/fuchsia_dir_scheme.h"
  25. #include "fuchsia_web/common/init_logging.h"
  26. #include "fuchsia_web/webengine/browser/frame_impl.h"
  27. #include "fuchsia_web/webengine/browser/navigation_policy_throttle.h"
  28. #include "fuchsia_web/webengine/browser/web_engine_browser_context.h"
  29. #include "fuchsia_web/webengine/browser/web_engine_browser_interface_binders.h"
  30. #include "fuchsia_web/webengine/browser/web_engine_browser_main_parts.h"
  31. #include "fuchsia_web/webengine/browser/web_engine_devtools_controller.h"
  32. #include "fuchsia_web/webengine/common/cors_exempt_headers.h"
  33. #include "fuchsia_web/webengine/common/web_engine_content_client.h"
  34. #include "fuchsia_web/webengine/switches.h"
  35. #include "media/base/media_switches.h"
  36. #include "net/cert/x509_certificate.h"
  37. #include "net/http/http_util.h"
  38. #include "net/ssl/ssl_private_key.h"
  39. #include "services/metrics/public/cpp/ukm_source_id.h"
  40. #include "services/network/public/cpp/network_switches.h"
  41. #include "services/network/public/cpp/resource_request.h"
  42. #include "services/network/public/mojom/network_context.mojom.h"
  43. #include "services/network/public/mojom/network_service.mojom.h"
  44. #include "third_party/blink/public/common/switches.h"
  45. #include "third_party/blink/public/mojom/webpreferences/web_preferences.mojom.h"
  46. #include "ui/base/l10n/l10n_util.h"
  47. namespace {
  48. class DevToolsManagerDelegate final : public content::DevToolsManagerDelegate {
  49. public:
  50. explicit DevToolsManagerDelegate(WebEngineBrowserMainParts* main_parts)
  51. : main_parts_(main_parts) {
  52. DCHECK(main_parts_);
  53. }
  54. ~DevToolsManagerDelegate() override = default;
  55. DevToolsManagerDelegate(const DevToolsManagerDelegate&) = delete;
  56. DevToolsManagerDelegate& operator=(const DevToolsManagerDelegate&) = delete;
  57. // content::DevToolsManagerDelegate implementation.
  58. std::vector<content::BrowserContext*> GetBrowserContexts() override {
  59. return main_parts_->browser_contexts();
  60. }
  61. content::BrowserContext* GetDefaultBrowserContext() override {
  62. std::vector<content::BrowserContext*> contexts = GetBrowserContexts();
  63. return contexts.empty() ? nullptr : contexts.front();
  64. }
  65. content::DevToolsAgentHost::List RemoteDebuggingTargets() override {
  66. return main_parts_->devtools_controller()->RemoteDebuggingTargets();
  67. }
  68. private:
  69. WebEngineBrowserMainParts* const main_parts_;
  70. };
  71. std::vector<std::string> GetCorsExemptHeaders() {
  72. return base::SplitString(
  73. base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(
  74. switches::kCorsExemptHeaders),
  75. ",", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
  76. }
  77. static constexpr char const* kRendererSwitchesToCopy[] = {
  78. blink::switches::kSharedArrayBufferAllowedOrigins,
  79. switches::kCorsExemptHeaders,
  80. switches::kEnableCastStreamingReceiver,
  81. switches::kEnableProtectedVideoBuffers,
  82. switches::kUseOverlaysForVideo,
  83. // TODO(crbug/1013412): Delete these two switches when fixed.
  84. switches::kEnableWidevine,
  85. switches::kPlayreadyKeySystem,
  86. // Pass to the renderer process for consistency with Chrome.
  87. network::switches::kUnsafelyTreatInsecureOriginAsSecure,
  88. };
  89. static constexpr char const*
  90. kUnsafelyTreatInsecureOriginAsSecureSwitchToCopy[] = {
  91. network::switches::kUnsafelyTreatInsecureOriginAsSecure,
  92. };
  93. // These are passed to every child process and should only be used when it is
  94. // not possible to narrow the scope down to a subset of processes.
  95. static constexpr char const* kAllProcessSwitchesToCopy[] = {
  96. // This is used by every child process in WebEngineContentClient.
  97. switches::kEnableContentDirectories,
  98. };
  99. } // namespace
  100. WebEngineContentBrowserClient::WebEngineContentBrowserClient()
  101. : cors_exempt_headers_(GetCorsExemptHeaders()),
  102. allow_insecure_content_(base::CommandLine::ForCurrentProcess()->HasSwitch(
  103. switches::kAllowRunningInsecureContent)) {
  104. // Logging in this class ensures this is logged once per web_instance.
  105. LogComponentStartWithVersion("WebEngine web_instance");
  106. }
  107. WebEngineContentBrowserClient::~WebEngineContentBrowserClient() = default;
  108. std::unique_ptr<content::BrowserMainParts>
  109. WebEngineContentBrowserClient::CreateBrowserMainParts(
  110. bool /* is_integration_test */) {
  111. auto browser_main_parts = std::make_unique<WebEngineBrowserMainParts>(this);
  112. main_parts_ = browser_main_parts.get();
  113. return browser_main_parts;
  114. }
  115. std::unique_ptr<content::DevToolsManagerDelegate>
  116. WebEngineContentBrowserClient::CreateDevToolsManagerDelegate() {
  117. DCHECK(main_parts_);
  118. return std::make_unique<DevToolsManagerDelegate>(main_parts_);
  119. }
  120. std::string WebEngineContentBrowserClient::GetProduct() {
  121. return version_info::GetProductNameAndVersionForUserAgent();
  122. }
  123. std::string WebEngineContentBrowserClient::GetUserAgent() {
  124. std::string user_agent = embedder_support::GetUserAgent();
  125. if (base::CommandLine::ForCurrentProcess()->HasSwitch(
  126. switches::kUserAgentProductAndVersion)) {
  127. user_agent +=
  128. " " + base::CommandLine::ForCurrentProcess()->GetSwitchValueNative(
  129. switches::kUserAgentProductAndVersion);
  130. }
  131. return user_agent;
  132. }
  133. blink::UserAgentMetadata WebEngineContentBrowserClient::GetUserAgentMetadata() {
  134. return embedder_support::GetUserAgentMetadata();
  135. }
  136. void WebEngineContentBrowserClient::OverrideWebkitPrefs(
  137. content::WebContents* web_contents,
  138. blink::web_pref::WebPreferences* web_prefs) {
  139. // Disable WebSQL support since it's being removed from the web platform.
  140. web_prefs->databases_enabled = false;
  141. if (allow_insecure_content_)
  142. web_prefs->allow_running_insecure_content = true;
  143. FrameImpl* frame = FrameImpl::FromWebContents(web_contents);
  144. // This method may be called when a |web_contents| is instantiated but an
  145. // associated frame has not been created.
  146. if (frame != nullptr)
  147. frame->OverrideWebPreferences(web_prefs);
  148. }
  149. void WebEngineContentBrowserClient::RegisterBrowserInterfaceBindersForFrame(
  150. content::RenderFrameHost* render_frame_host,
  151. mojo::BinderMapWithContext<content::RenderFrameHost*>* map) {
  152. PopulateFuchsiaFrameBinders(map);
  153. }
  154. void WebEngineContentBrowserClient::
  155. RegisterNonNetworkNavigationURLLoaderFactories(
  156. int frame_tree_node_id,
  157. ukm::SourceIdObj ukm_source_id,
  158. NonNetworkURLLoaderFactoryMap* factories) {
  159. if (base::CommandLine::ForCurrentProcess()->HasSwitch(
  160. switches::kEnableContentDirectories)) {
  161. factories->emplace(kFuchsiaDirScheme,
  162. ContentDirectoryLoaderFactory::Create());
  163. }
  164. }
  165. void WebEngineContentBrowserClient::
  166. RegisterNonNetworkSubresourceURLLoaderFactories(
  167. int render_process_id,
  168. int render_frame_id,
  169. const absl::optional<url::Origin>& request_initiator_origin,
  170. NonNetworkURLLoaderFactoryMap* factories) {
  171. if (base::CommandLine::ForCurrentProcess()->HasSwitch(
  172. switches::kEnableContentDirectories)) {
  173. factories->emplace(kFuchsiaDirScheme,
  174. ContentDirectoryLoaderFactory::Create());
  175. }
  176. }
  177. bool WebEngineContentBrowserClient::ShouldEnableStrictSiteIsolation() {
  178. constexpr base::Feature kSitePerProcess{"site-per-process",
  179. base::FEATURE_ENABLED_BY_DEFAULT};
  180. static bool enable_strict_isolation =
  181. base::FeatureList::IsEnabled(kSitePerProcess);
  182. return enable_strict_isolation;
  183. }
  184. void WebEngineContentBrowserClient::AppendExtraCommandLineSwitches(
  185. base::CommandLine* command_line,
  186. int child_process_id) {
  187. const base::CommandLine& browser_command_line =
  188. *base::CommandLine::ForCurrentProcess();
  189. command_line->CopySwitchesFrom(browser_command_line,
  190. kAllProcessSwitchesToCopy,
  191. std::size(kAllProcessSwitchesToCopy));
  192. std::string process_type =
  193. command_line->GetSwitchValueASCII(switches::kProcessType);
  194. if (process_type == switches::kRendererProcess) {
  195. command_line->CopySwitchesFrom(browser_command_line,
  196. kRendererSwitchesToCopy,
  197. std::size(kRendererSwitchesToCopy));
  198. } else if (process_type == switches::kUtilityProcess) {
  199. // Although only the Network process needs
  200. // kUnsafelyTreatInsecureOriginAsSecureSwitchToCopy, differentiating utility
  201. // process sub-types is non-trivial. ChromeContentBrowserClient appends this
  202. // switch to all Utility processes so do the same here.
  203. // Do not add other switches here.
  204. command_line->CopySwitchesFrom(
  205. browser_command_line, kUnsafelyTreatInsecureOriginAsSecureSwitchToCopy,
  206. std::size(kUnsafelyTreatInsecureOriginAsSecureSwitchToCopy));
  207. }
  208. }
  209. std::string WebEngineContentBrowserClient::GetApplicationLocale() {
  210. // ICU is configured with the system locale by WebEngineBrowserMainParts.
  211. return base::i18n::GetConfiguredLocale();
  212. }
  213. std::string WebEngineContentBrowserClient::GetAcceptLangs(
  214. content::BrowserContext* context) {
  215. // Returns a comma-separated list of language codes, in preference order.
  216. // This is passed to net::HttpUtil::GenerateAcceptLanguageHeader() to
  217. // generate a legacy "accept-language" header value.
  218. return l10n_util::GetStringUTF8(IDS_ACCEPT_LANGUAGES);
  219. }
  220. base::OnceClosure WebEngineContentBrowserClient::SelectClientCertificate(
  221. content::WebContents* web_contents,
  222. net::SSLCertRequestInfo* cert_request_info,
  223. net::ClientCertIdentityList client_certs,
  224. std::unique_ptr<content::ClientCertificateDelegate> delegate) {
  225. // Continue without a certificate.
  226. delegate->ContinueWithCertificate(nullptr, nullptr);
  227. return base::OnceClosure();
  228. }
  229. std::vector<std::unique_ptr<content::NavigationThrottle>>
  230. WebEngineContentBrowserClient::CreateThrottlesForNavigation(
  231. content::NavigationHandle* navigation_handle) {
  232. std::vector<std::unique_ptr<content::NavigationThrottle>> throttles;
  233. auto* frame_impl =
  234. FrameImpl::FromWebContents(navigation_handle->GetWebContents());
  235. DCHECK(frame_impl);
  236. // Only create throttle if FrameImpl has a NavigationPolicyProvider,
  237. // indicating an interest in navigations.
  238. if (frame_impl->navigation_policy_handler()) {
  239. throttles.push_back(std::make_unique<NavigationPolicyThrottle>(
  240. navigation_handle, frame_impl->navigation_policy_handler()));
  241. }
  242. const absl::optional<std::string>& explicit_sites_filter_error_page =
  243. frame_impl->explicit_sites_filter_error_page();
  244. if (explicit_sites_filter_error_page) {
  245. throttles.push_back(std::make_unique<SafeSitesNavigationThrottle>(
  246. navigation_handle,
  247. navigation_handle->GetWebContents()->GetBrowserContext(),
  248. *explicit_sites_filter_error_page));
  249. }
  250. return throttles;
  251. }
  252. std::vector<std::unique_ptr<blink::URLLoaderThrottle>>
  253. WebEngineContentBrowserClient::CreateURLLoaderThrottles(
  254. const network::ResourceRequest& request,
  255. content::BrowserContext* browser_context,
  256. const base::RepeatingCallback<content::WebContents*()>& wc_getter,
  257. content::NavigationUIData* navigation_ui_data,
  258. int frame_tree_node_id) {
  259. if (frame_tree_node_id == content::RenderFrameHost::kNoFrameTreeNodeId) {
  260. // TODO(crbug.com/976975): Add support for service workers.
  261. return {};
  262. }
  263. std::vector<std::unique_ptr<blink::URLLoaderThrottle>> throttles;
  264. auto* frame_impl = FrameImpl::FromWebContents(wc_getter.Run());
  265. DCHECK(frame_impl);
  266. const auto& rules =
  267. frame_impl->url_request_rewrite_rules_manager()->GetCachedRules();
  268. if (rules) {
  269. throttles.emplace_back(std::make_unique<url_rewrite::URLLoaderThrottle>(
  270. rules, base::BindRepeating(&IsHeaderCorsExempt)));
  271. }
  272. return throttles;
  273. }
  274. void WebEngineContentBrowserClient::ConfigureNetworkContextParams(
  275. content::BrowserContext* context,
  276. bool in_memory,
  277. const base::FilePath& relative_partition_path,
  278. network::mojom::NetworkContextParams* network_context_params,
  279. cert_verifier::mojom::CertVerifierCreationParams*
  280. cert_verifier_creation_params) {
  281. network_context_params->user_agent = GetUserAgent();
  282. network_context_params->accept_language =
  283. net::HttpUtil::GenerateAcceptLanguageHeader(GetAcceptLangs(context));
  284. // Set the list of cors_exempt_headers which may be specified in a URLRequest,
  285. // starting with the headers passed in via
  286. // |CreateContextParams.cors_exempt_headers|.
  287. network_context_params->cors_exempt_header_list = cors_exempt_headers_;
  288. }
  289. std::vector<url::Origin>
  290. WebEngineContentBrowserClient::GetOriginsRequiringDedicatedProcess() {
  291. std::vector<url::Origin> isolated_origin_list;
  292. // Include additional origins preloaded with specific browser configurations,
  293. // if any.
  294. auto built_in_origins =
  295. site_isolation::GetBrowserSpecificBuiltInIsolatedOrigins();
  296. std::move(std::begin(built_in_origins), std::end(built_in_origins),
  297. std::back_inserter(isolated_origin_list));
  298. return isolated_origin_list;
  299. }