1 // Copyright 2014 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 
5 #include "chromecast/browser/cast_content_browser_client.h"
6 
7 #include <stddef.h>
8 
9 #include <utility>
10 
11 #include "base/base_switches.h"
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/feature_list.h"
15 #include "base/files/scoped_file.h"
16 #include "base/i18n/rtl.h"
17 #include "base/message_loop/message_pump_type.h"
18 #include "base/path_service.h"
19 #include "base/stl_util.h"
20 #include "base/strings/string_number_conversions.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/task/post_task.h"
23 #include "base/threading/thread_task_runner_handle.h"
24 #include "base/unguessable_token.h"
25 #include "build/build_config.h"
26 #include "chromecast/base/cast_constants.h"
27 #include "chromecast/base/cast_features.h"
28 #include "chromecast/base/cast_paths.h"
29 #include "chromecast/base/chromecast_switches.h"
30 #include "chromecast/base/pref_names.h"
31 #include "chromecast/browser/application_media_info_manager.h"
32 #include "chromecast/browser/browser_buildflags.h"
33 #include "chromecast/browser/cast_browser_context.h"
34 #include "chromecast/browser/cast_browser_main_parts.h"
35 #include "chromecast/browser/cast_browser_process.h"
36 #include "chromecast/browser/cast_feature_list_creator.h"
37 #include "chromecast/browser/cast_http_user_agent_settings.h"
38 #include "chromecast/browser/cast_navigation_ui_data.h"
39 #include "chromecast/browser/cast_network_contexts.h"
40 #include "chromecast/browser/cast_overlay_manifests.h"
41 #include "chromecast/browser/cast_quota_permission_context.h"
42 #include "chromecast/browser/cast_session_id_map.h"
43 #include "chromecast/browser/cast_web_contents.h"
44 #include "chromecast/browser/cast_web_preferences.h"
45 #include "chromecast/browser/default_navigation_throttle.h"
46 #include "chromecast/browser/devtools/cast_devtools_manager_delegate.h"
47 #include "chromecast/browser/general_audience_browsing_navigation_throttle.h"
48 #include "chromecast/browser/general_audience_browsing_service.h"
49 #include "chromecast/browser/media/media_caps_impl.h"
50 #include "chromecast/browser/service/cast_service_simple.h"
51 #include "chromecast/browser/service_connector.h"
52 #include "chromecast/common/cast_content_client.h"
53 #include "chromecast/common/global_descriptors.h"
54 #include "chromecast/media/audio/cast_audio_manager.h"
55 #include "chromecast/media/base/media_resource_tracker.h"
56 #include "chromecast/media/cdm/cast_cdm_factory.h"
57 #include "chromecast/media/cdm/cast_cdm_origin_provider.h"
58 #include "chromecast/media/cma/backend/cma_backend_factory_impl.h"
59 #include "chromecast/media/cma/backend/media_pipeline_backend_manager.h"
60 #include "chromecast/media/service/cast_renderer.h"
61 #include "chromecast/media/service/mojom/video_geometry_setter.mojom.h"
62 #include "chromecast/public/media/media_pipeline_backend.h"
63 #include "components/prefs/pref_service.h"
64 #include "content/public/browser/browser_task_traits.h"
65 #include "content/public/browser/browser_thread.h"
66 #include "content/public/browser/certificate_request_result_type.h"
67 #include "content/public/browser/client_certificate_delegate.h"
68 #include "content/public/browser/navigation_handle.h"
69 #include "content/public/browser/navigation_ui_data.h"
70 #include "content/public/browser/render_frame_host.h"
71 #include "content/public/browser/render_process_host.h"
72 #include "content/public/browser/site_instance.h"
73 #include "content/public/browser/storage_partition.h"
74 #include "content/public/browser/system_connector.h"
75 #include "content/public/browser/web_contents.h"
76 #include "content/public/browser/web_ui_url_loader_factory.h"
77 #include "content/public/common/content_descriptors.h"
78 #include "content/public/common/content_features.h"
79 #include "content/public/common/content_switches.h"
80 #include "content/public/common/service_names.mojom.h"
81 #include "content/public/common/url_constants.h"
82 #include "media/audio/audio_thread_impl.h"
83 #include "media/base/media_switches.h"
84 #include "media/mojo/services/mojo_renderer_service.h"
85 #include "mojo/public/cpp/bindings/pending_receiver.h"
86 #include "net/ssl/ssl_cert_request_info.h"
87 #include "net/url_request/url_request_context_getter.h"
88 #include "services/metrics/public/cpp/ukm_source_id.h"
89 #include "services/network/public/cpp/network_switches.h"
90 #include "third_party/blink/public/common/features.h"
91 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
92 #include "ui/display/display.h"
93 #include "ui/display/screen.h"
94 #include "ui/gl/gl_switches.h"
95 
96 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
97 #include "components/crash/content/browser/crash_handler_host_linux.h"
98 #endif  // defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_ANDROID)
99 
100 #if defined(OS_LINUX) || defined(OS_CHROMEOS)
101 #include "components/crash/core/app/breakpad_linux.h"
102 #endif  // defined(OS_LINUX) || defined(OS_CHROMEOS)
103 
104 #if defined(OS_ANDROID)
105 #include "chromecast/media/audio/cast_audio_manager_android.h"  // nogncheck
106 #include "components/cdm/browser/cdm_message_filter_android.h"
107 #include "components/crash/core/app/crashpad.h"
108 #include "media/audio/android/audio_manager_android.h"
109 #else
110 #include "chromecast/browser/memory_pressure_controller_impl.h"
111 #endif  // defined(OS_ANDROID)
112 
113 #if defined(USE_ALSA)
114 #include "chromecast/media/audio/cast_audio_manager_alsa.h"  // nogncheck
115 #endif  // defined(USE_ALSA)
116 
117 #if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
118 #include "chromecast/browser/cast_extension_message_filter.h"      // nogncheck
119 #include "chromecast/browser/cast_extension_url_loader_factory.h"  // nogncheck
120 #include "extensions/browser/extension_message_filter.h"           // nogncheck
121 #include "extensions/browser/extension_protocols.h"                // nogncheck
122 #include "extensions/browser/extension_registry.h"                 // nogncheck
123 #include "extensions/browser/guest_view/extensions_guest_view_message_filter.h"  // nogncheck
124 #include "extensions/browser/guest_view/web_view/web_view_guest.h"  // nogncheck
125 #include "extensions/browser/process_map.h"                         // nogncheck
126 #include "extensions/common/constants.h"                            // nogncheck
127 #endif
128 
129 #if BUILDFLAG(ENABLE_EXTERNAL_MOJO_SERVICES)
130 #include "chromecast/external_mojo/broker_service/broker_service.h"  // nogncheck
131 #endif
132 
133 #if (defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_BSD)) && defined(USE_OZONE)
134 #include "chromecast/browser/webview/webview_controller.h"
135 #endif  // (defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_BSD)) && defined(USE_OZONE)
136 
137 #if BUILDFLAG(ENABLE_CAST_RENDERER)
138 #include "base/sequenced_task_runner.h"
139 #include "chromecast/media/service/video_geometry_setter_service.h"
140 #endif  // BUILDFLAG(ENABLE_CAST_RENDERER)
141 
142 #if !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
143 #include "device/bluetooth/cast/bluetooth_adapter_cast.h"
144 #endif
145 
146 namespace chromecast {
147 namespace shell {
148 
CastContentBrowserClient(CastFeatureListCreator * cast_feature_list_creator)149 CastContentBrowserClient::CastContentBrowserClient(
150     CastFeatureListCreator* cast_feature_list_creator)
151     :
152 #if BUILDFLAG(ENABLE_CAST_RENDERER)
153       video_geometry_setter_service_(
154           std::unique_ptr<media::VideoGeometrySetterService,
155                           base::OnTaskRunnerDeleter>(
156               nullptr,
157               base::OnTaskRunnerDeleter(nullptr))),
158 #endif  // BUILDFLAG(ENABLE_CAST_RENDERER)
159       cast_browser_main_parts_(nullptr),
160       cast_network_contexts_(
161           std::make_unique<CastNetworkContexts>(GetCorsExemptHeadersList())),
162       cast_feature_list_creator_(cast_feature_list_creator) {
163   cast_feature_list_creator_->SetExtraEnableFeatures({
164     ::media::kInternalMediaSession, features::kNetworkServiceInProcess,
165         // TODO(b/161486194): Can be removed when it's enabled by default in
166         // Chrome.
167         features::kWebAssemblySimd,
168 #if defined(OS_ANDROID) && BUILDFLAG(ENABLE_VIDEO_CAPTURE_SERVICE)
169         features::kMojoVideoCapture,
170 #endif
171   });
172 
173   cast_feature_list_creator_->SetExtraDisableFeatures({
174       // TODO(juke): Reenable this after solving casting issue on LAN.
175       blink::features::kMixedContentAutoupgrade,
176 #if defined(OS_ANDROID)
177       ::media::kAudioFocusLossSuspendMediaSession,
178       ::media::kRequestSystemAudioFocus,
179 #endif
180   });
181 }
182 
~CastContentBrowserClient()183 CastContentBrowserClient::~CastContentBrowserClient() {
184   DCHECK(!media_resource_tracker_)
185       << "ResetMediaResourceTracker was not called";
186   cast_network_contexts_.reset();
187 }
188 
189 std::unique_ptr<ServiceConnector>
CreateServiceConnector()190 CastContentBrowserClient::CreateServiceConnector() {
191   return std::make_unique<ServiceConnector>();
192 }
193 
CreateCastService(content::BrowserContext * browser_context,CastSystemMemoryPressureEvaluatorAdjuster * cast_system_memory_pressure_evaluator_adjuster,PrefService * pref_service,media::VideoPlaneController * video_plane_controller,CastWindowManager * window_manager)194 std::unique_ptr<CastService> CastContentBrowserClient::CreateCastService(
195     content::BrowserContext* browser_context,
196     CastSystemMemoryPressureEvaluatorAdjuster*
197         cast_system_memory_pressure_evaluator_adjuster,
198     PrefService* pref_service,
199     media::VideoPlaneController* video_plane_controller,
200     CastWindowManager* window_manager) {
201   return std::make_unique<CastServiceSimple>(browser_context, window_manager);
202 }
203 
GetVideoModeSwitcher()204 media::VideoModeSwitcher* CastContentBrowserClient::GetVideoModeSwitcher() {
205   return nullptr;
206 }
207 
InitializeURLLoaderThrottleDelegate()208 void CastContentBrowserClient::InitializeURLLoaderThrottleDelegate() {}
209 
210 scoped_refptr<base::SingleThreadTaskRunner>
GetMediaTaskRunner()211 CastContentBrowserClient::GetMediaTaskRunner() {
212   if (!media_thread_) {
213     media_thread_.reset(new base::Thread("CastMediaThread"));
214     base::Thread::Options options;
215     // We need the media thread to be IO-capable to use the mixer service.
216     options.message_pump_type = base::MessagePumpType::IO;
217     options.priority = base::ThreadPriority::REALTIME_AUDIO;
218     CHECK(media_thread_->StartWithOptions(options));
219     // Start the media_resource_tracker as soon as the media thread is created.
220     // There are services that run on the media thread that depend on it,
221     // and we want to initialize it with the correct task runner before any
222     // tasks that might use it are posted to the media thread.
223     media_resource_tracker_ = new media::MediaResourceTracker(
224         base::ThreadTaskRunnerHandle::Get(), media_thread_->task_runner());
225   }
226   return media_thread_->task_runner();
227 }
228 
229 media::VideoResolutionPolicy*
GetVideoResolutionPolicy()230 CastContentBrowserClient::GetVideoResolutionPolicy() {
231   return nullptr;
232 }
233 
GetCmaBackendFactory()234 media::CmaBackendFactory* CastContentBrowserClient::GetCmaBackendFactory() {
235   DCHECK(GetMediaTaskRunner()->BelongsToCurrentThread());
236   if (!cma_backend_factory_) {
237     cma_backend_factory_ = std::make_unique<media::CmaBackendFactoryImpl>(
238         media_pipeline_backend_manager());
239   }
240   return cma_backend_factory_.get();
241 }
242 
243 media::MediaResourceTracker*
media_resource_tracker()244 CastContentBrowserClient::media_resource_tracker() {
245   DCHECK(media_thread_);
246   return media_resource_tracker_;
247 }
248 
ResetMediaResourceTracker()249 void CastContentBrowserClient::ResetMediaResourceTracker() {
250   media_resource_tracker_->FinalizeAndDestroy();
251   media_resource_tracker_ = nullptr;
252 }
253 
254 media::MediaPipelineBackendManager*
media_pipeline_backend_manager()255 CastContentBrowserClient::media_pipeline_backend_manager() {
256   DCHECK(cast_browser_main_parts_);
257   return cast_browser_main_parts_->media_pipeline_backend_manager();
258 }
259 
260 std::unique_ptr<::media::AudioManager>
CreateAudioManager(::media::AudioLogFactory * audio_log_factory)261 CastContentBrowserClient::CreateAudioManager(
262     ::media::AudioLogFactory* audio_log_factory) {
263   // Create the audio thread and initialize the CastSessionIdMap. We need to
264   // initialize the CastSessionIdMap as soon as possible, so that the task
265   // runner gets set before any calls to it.
266   auto audio_thread = std::make_unique<::media::AudioThreadImpl>();
267   shell::CastSessionIdMap::GetInstance(audio_thread->GetTaskRunner());
268 
269 #if defined(USE_ALSA)
270   return std::make_unique<media::CastAudioManagerAlsa>(
271       std::move(audio_thread), audio_log_factory,
272       base::BindRepeating(&CastContentBrowserClient::GetCmaBackendFactory,
273                           base::Unretained(this)),
274       base::BindRepeating(&shell::CastSessionIdMap::GetSessionId),
275       base::CreateSingleThreadTaskRunner({content::BrowserThread::UI}),
276       GetMediaTaskRunner(),
277       ServiceConnector::MakeRemote(kBrowserProcessClientId),
278       BUILDFLAG(ENABLE_CAST_AUDIO_MANAGER_MIXER));
279 #elif defined(OS_ANDROID)
280   if (base::FeatureList::IsEnabled(kEnableChromeAudioManagerAndroid)) {
281     LOG(INFO) << "Use AudioManagerAndroid instead of CastAudioManagerAndroid.";
282     return std::make_unique<::media::AudioManagerAndroid>(
283         std::move(audio_thread), audio_log_factory);
284   }
285 
286   return std::make_unique<media::CastAudioManagerAndroid>(
287       std::move(audio_thread), audio_log_factory,
288       base::BindRepeating(&CastContentBrowserClient::GetCmaBackendFactory,
289                           base::Unretained(this)),
290       base::BindRepeating(&shell::CastSessionIdMap::GetSessionId),
291       GetMediaTaskRunner(),
292       ServiceConnector::MakeRemote(kBrowserProcessClientId));
293 #else
294   return std::make_unique<media::CastAudioManager>(
295       std::move(audio_thread), audio_log_factory,
296       base::BindRepeating(&CastContentBrowserClient::GetCmaBackendFactory,
297                           base::Unretained(this)),
298       base::BindRepeating(&shell::CastSessionIdMap::GetSessionId),
299       base::CreateSingleThreadTaskRunner({content::BrowserThread::UI}),
300       GetMediaTaskRunner(),
301       ServiceConnector::MakeRemote(kBrowserProcessClientId),
302       BUILDFLAG(ENABLE_CAST_AUDIO_MANAGER_MIXER));
303 #endif
304 }
305 
OverridesAudioManager()306 bool CastContentBrowserClient::OverridesAudioManager() {
307   return true;
308 }
309 
CreateCdmFactory(::media::mojom::FrameInterfaceFactory * frame_interfaces)310 std::unique_ptr<::media::CdmFactory> CastContentBrowserClient::CreateCdmFactory(
311     ::media::mojom::FrameInterfaceFactory* frame_interfaces) {
312   url::Origin cdm_origin;
313   if (!CastCdmOriginProvider::GetCdmOrigin(frame_interfaces, &cdm_origin))
314     return nullptr;
315 
316   return std::make_unique<media::CastCdmFactory>(
317       GetMediaTaskRunner(), cdm_origin, media_resource_tracker());
318 }
319 
media_caps()320 media::MediaCapsImpl* CastContentBrowserClient::media_caps() {
321   DCHECK(cast_browser_main_parts_);
322   return cast_browser_main_parts_->media_caps();
323 }
324 
325 #if !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
326 scoped_refptr<device::BluetoothAdapterCast>
CreateBluetoothAdapter()327 CastContentBrowserClient::CreateBluetoothAdapter() {
328   NOTREACHED() << "Bluetooth Adapter is not supported!";
329   return nullptr;
330 }
331 #endif  // !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
332 
SetMetricsClientId(const std::string & client_id)333 void CastContentBrowserClient::SetMetricsClientId(
334     const std::string& client_id) {}
335 
RegisterMetricsProviders(::metrics::MetricsService * metrics_service)336 void CastContentBrowserClient::RegisterMetricsProviders(
337     ::metrics::MetricsService* metrics_service) {}
338 
EnableRemoteDebuggingImmediately()339 bool CastContentBrowserClient::EnableRemoteDebuggingImmediately() {
340   return true;
341 }
342 
GetStartupServices()343 std::vector<std::string> CastContentBrowserClient::GetStartupServices() {
344   return {
345 #if BUILDFLAG(ENABLE_EXTERNAL_MOJO_SERVICES)
346     external_mojo::BrokerService::kServiceName
347 #endif
348   };
349 }
350 
351 std::unique_ptr<content::BrowserMainParts>
CreateBrowserMainParts(const content::MainFunctionParams & parameters)352 CastContentBrowserClient::CreateBrowserMainParts(
353     const content::MainFunctionParams& parameters) {
354   DCHECK(!cast_browser_main_parts_);
355 
356   auto main_parts = CastBrowserMainParts::Create(parameters, this);
357 
358   cast_browser_main_parts_ = main_parts.get();
359   CastBrowserProcess::GetInstance()->SetCastContentBrowserClient(this);
360 
361   return main_parts;
362 }
363 
RenderProcessWillLaunch(content::RenderProcessHost * host)364 void CastContentBrowserClient::RenderProcessWillLaunch(
365     content::RenderProcessHost* host) {
366 #if defined(OS_ANDROID)
367   // Cast on Android always allows persisting data.
368   //
369   // Cast on Android build always uses kForceVideoOverlays command line switch
370   // such that secure codecs can always be rendered.
371   //
372   // TODO(yucliu): On Clank, secure codecs support is tied to AndroidOverlay.
373   // Remove kForceVideoOverlays and swtich to the Clank model for secure codecs
374   // support.
375   host->AddFilter(new cdm::CdmMessageFilterAndroid(true, true));
376 #endif  // defined(OS_ANDROID)
377 
378 #if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
379   int render_process_id = host->GetID();
380   content::BrowserContext* browser_context =
381       cast_browser_main_parts_->browser_context();
382   host->AddFilter(new extensions::ExtensionMessageFilter(render_process_id,
383                                                          browser_context));
384   host->AddFilter(new extensions::ExtensionsGuestViewMessageFilter(
385       render_process_id, browser_context));
386   host->AddFilter(
387       new CastExtensionMessageFilter(render_process_id, browser_context));
388 #endif
389 }
390 
IsHandledURL(const GURL & url)391 bool CastContentBrowserClient::IsHandledURL(const GURL& url) {
392   if (!url.is_valid())
393     return false;
394 
395   static const char* const kProtocolList[] = {
396       content::kChromeUIScheme, content::kChromeDevToolsScheme,
397       kChromeResourceScheme,    url::kBlobScheme,
398       url::kDataScheme,         url::kFileSystemScheme,
399   };
400 
401   const std::string& scheme = url.scheme();
402   for (size_t i = 0; i < base::size(kProtocolList); ++i) {
403     if (scheme == kProtocolList[i])
404       return true;
405   }
406 
407   if (scheme == url::kFileScheme) {
408     return base::CommandLine::ForCurrentProcess()->HasSwitch(
409         switches::kEnableLocalFileAccesses);
410   }
411 
412   return false;
413 }
414 
SiteInstanceGotProcess(content::SiteInstance * site_instance)415 void CastContentBrowserClient::SiteInstanceGotProcess(
416     content::SiteInstance* site_instance) {
417 #if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
418   // If this isn't an extension renderer there's nothing to do.
419   extensions::ExtensionRegistry* registry =
420       extensions::ExtensionRegistry::Get(site_instance->GetBrowserContext());
421   const extensions::Extension* extension =
422       registry->enabled_extensions().GetExtensionOrAppByURL(
423           site_instance->GetSiteURL());
424   if (!extension)
425     return;
426   extensions::ProcessMap::Get(cast_browser_main_parts_->browser_context())
427       ->Insert(extension->id(), site_instance->GetProcess()->GetID(),
428                site_instance->GetId());
429 #endif
430 }
431 
AppendExtraCommandLineSwitches(base::CommandLine * command_line,int child_process_id)432 void CastContentBrowserClient::AppendExtraCommandLineSwitches(
433     base::CommandLine* command_line,
434     int child_process_id) {
435   std::string process_type =
436       command_line->GetSwitchValueNative(switches::kProcessType);
437   base::CommandLine* browser_command_line =
438       base::CommandLine::ForCurrentProcess();
439 
440 #if !defined(OS_FUCHSIA)
441 #if defined(OS_ANDROID)
442   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
443           switches::kEnableCrashReporter)) {
444     command_line->AppendSwitch(switches::kEnableCrashReporter);
445   }
446 #else
447   // IsCrashReporterEnabled() is set when InitCrashReporter() is called, and
448   // controlled by GetBreakpadClient()->EnableBreakpadForProcess(), therefore
449   // it's ok to add switch to every process here.
450   if (breakpad::IsCrashReporterEnabled()) {
451     command_line->AppendSwitch(switches::kEnableCrashReporter);
452   }
453 #endif  // defined(OS_ANDROID)
454 #endif  // !defined(OS_FUCHSIA)
455 
456   // Command-line for different processes.
457   if (process_type == switches::kRendererProcess) {
458     // Any browser command-line switches that should be propagated to
459     // the renderer go here.
460     static const char* const kForwardSwitches[] = {
461         switches::kCastAppBackgroundColor,
462         switches::kForceMediaResolutionHeight,
463         switches::kForceMediaResolutionWidth,
464         network::switches::kUnsafelyTreatInsecureOriginAsSecure};
465     command_line->CopySwitchesFrom(*browser_command_line, kForwardSwitches,
466                                    base::size(kForwardSwitches));
467   } else if (process_type == switches::kUtilityProcess) {
468     if (browser_command_line->HasSwitch(switches::kAudioOutputChannels)) {
469       command_line->AppendSwitchASCII(switches::kAudioOutputChannels,
470                                       browser_command_line->GetSwitchValueASCII(
471                                           switches::kAudioOutputChannels));
472     }
473   } else if (process_type == switches::kGpuProcess) {
474 #if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_BSD)
475     // Necessary for accelerated 2d canvas.  By default on Linux, Chromium
476     // assumes GLES2 contexts can be lost to a power-save mode, which breaks GPU
477     // canvas apps.
478     command_line->AppendSwitch(switches::kGpuNoContextLost);
479 #endif
480 
481 #if defined(USE_AURA)
482     static const char* const kForwardSwitches[] = {
483         switches::kCastInitialScreenHeight,
484         switches::kCastInitialScreenWidth,
485         switches::kVSyncInterval,
486     };
487     command_line->CopySwitchesFrom(*browser_command_line, kForwardSwitches,
488                                    base::size(kForwardSwitches));
489 
490     auto display = display::Screen::GetScreen()->GetPrimaryDisplay();
491     gfx::Size res = display.GetSizeInPixel();
492     if (display.rotation() == display::Display::ROTATE_90 ||
493         display.rotation() == display::Display::ROTATE_270) {
494       res = gfx::Size(res.height(), res.width());
495     }
496 
497     if (!command_line->HasSwitch(switches::kCastInitialScreenWidth)) {
498       command_line->AppendSwitchASCII(switches::kCastInitialScreenWidth,
499                                       base::NumberToString(res.width()));
500     }
501     if (!command_line->HasSwitch(switches::kCastInitialScreenHeight)) {
502       command_line->AppendSwitchASCII(switches::kCastInitialScreenHeight,
503                                       base::NumberToString(res.height()));
504     }
505 
506     if (chromecast::IsFeatureEnabled(kSingleBuffer)) {
507       command_line->AppendSwitchASCII(switches::kGraphicsBufferCount, "1");
508     } else if (chromecast::IsFeatureEnabled(chromecast::kTripleBuffer720)) {
509       command_line->AppendSwitchASCII(switches::kGraphicsBufferCount, "3");
510     }
511 #endif  // defined(USE_AURA)
512   }
513 }
514 
GetAcceptLangs(content::BrowserContext * context)515 std::string CastContentBrowserClient::GetAcceptLangs(
516     content::BrowserContext* context) {
517   return CastHttpUserAgentSettings::AcceptLanguage();
518 }
519 
520 network::mojom::NetworkContext*
GetSystemNetworkContext()521 CastContentBrowserClient::GetSystemNetworkContext() {
522   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
523   return cast_network_contexts_->GetSystemContext();
524 }
525 
OverrideWebkitPrefs(content::RenderViewHost * render_view_host,blink::web_pref::WebPreferences * prefs)526 void CastContentBrowserClient::OverrideWebkitPrefs(
527     content::RenderViewHost* render_view_host,
528     blink::web_pref::WebPreferences* prefs) {
529   prefs->allow_scripts_to_close_windows = true;
530   // TODO(halliwell): http://crbug.com/391089. This pref defaults to to true
531   // because some content providers such as YouTube use plain http requests
532   // to retrieve media data chunks while running in a https page. This pref
533   // should be disabled once all the content providers are no longer doing that.
534   prefs->allow_running_insecure_content = true;
535 
536   // Enable 5% margins for WebVTT cues to keep within title-safe area
537   prefs->text_track_margin_percentage = 5;
538 
539   prefs->hide_scrollbars = true;
540 
541   // Disable images rendering in Cast for Audio configuration
542 #if BUILDFLAG(IS_CAST_AUDIO_ONLY)
543   prefs->images_enabled = false;
544 #endif
545 
546 #if defined(OS_ANDROID)
547   // Enable the television style for viewport so that all cast apps have a
548   // 1280px wide layout viewport by default.
549   DCHECK(prefs->viewport_enabled);
550   DCHECK(prefs->viewport_meta_enabled);
551   prefs->viewport_style = blink::mojom::ViewportStyle::kTelevision;
552 #endif  // defined(OS_ANDROID)
553 
554   // Disable WebSQL databases by default.
555   prefs->databases_enabled = false;
556   content::WebContents* web_contents =
557       content::WebContents::FromRenderViewHost(render_view_host);
558   if (web_contents) {
559     chromecast::CastWebContents* cast_web_contents =
560         chromecast::CastWebContents::FromWebContents(web_contents);
561     if (cast_web_contents && cast_web_contents->is_websql_enabled()) {
562       prefs->databases_enabled = true;
563     }
564   }
565 
566   prefs->preferred_color_scheme =
567       static_cast<blink::mojom::PreferredColorScheme>(
568           CastBrowserProcess::GetInstance()->pref_service()->GetInteger(
569               prefs::kWebColorScheme));
570 
571   // After all other default settings are set, check and see if there are any
572   // specific overrides for the WebContents.
573   CastWebPreferences* web_preferences =
574       static_cast<CastWebPreferences*>(web_contents->GetUserData(
575           CastWebPreferences::kCastWebPreferencesDataKey));
576   if (web_preferences)
577     web_preferences->Update(prefs);
578 }
579 
GetApplicationLocale()580 std::string CastContentBrowserClient::GetApplicationLocale() {
581   const std::string locale(base::i18n::GetConfiguredLocale());
582   return locale.empty() ? "en-US" : locale;
583 }
584 
585 scoped_refptr<content::QuotaPermissionContext>
CreateQuotaPermissionContext()586 CastContentBrowserClient::CreateQuotaPermissionContext() {
587   return new CastQuotaPermissionContext();
588 }
589 
AllowCertificateError(content::WebContents * web_contents,int cert_error,const net::SSLInfo & ssl_info,const GURL & request_url,bool is_main_frame_request,bool strict_enforcement,base::OnceCallback<void (content::CertificateRequestResultType)> callback)590 void CastContentBrowserClient::AllowCertificateError(
591     content::WebContents* web_contents,
592     int cert_error,
593     const net::SSLInfo& ssl_info,
594     const GURL& request_url,
595     bool is_main_frame_request,
596     bool strict_enforcement,
597     base::OnceCallback<void(content::CertificateRequestResultType)> callback) {
598   // Allow developers to override certificate errors.
599   // Otherwise, any fatal certificate errors will cause an abort.
600   if (callback) {
601     std::move(callback).Run(content::CERTIFICATE_REQUEST_RESULT_TYPE_CANCEL);
602   }
603   return;
604 }
605 
SelectClientCertificate(content::WebContents * web_contents,net::SSLCertRequestInfo * cert_request_info,net::ClientCertIdentityList client_certs,std::unique_ptr<content::ClientCertificateDelegate> delegate)606 base::OnceClosure CastContentBrowserClient::SelectClientCertificate(
607     content::WebContents* web_contents,
608     net::SSLCertRequestInfo* cert_request_info,
609     net::ClientCertIdentityList client_certs,
610     std::unique_ptr<content::ClientCertificateDelegate> delegate) {
611   GURL requesting_url("https://" + cert_request_info->host_and_port.ToString());
612 
613   if (!requesting_url.is_valid()) {
614     LOG(ERROR) << "Invalid URL string: "
615                << requesting_url.possibly_invalid_spec();
616     delegate->ContinueWithCertificate(nullptr, nullptr);
617     return base::OnceClosure();
618   }
619 
620   // In our case there are no relevant certs in |client_certs|. The cert
621   // we need to return (if permitted) is the Cast device cert, which we can
622   // access directly through the ClientAuthSigner instance. However, we need to
623   // be on the IO thread to determine whether the app is whitelisted to return
624   // it.
625   // Subsequently, the callback must then itself be performed back here
626   // on the UI thread.
627   //
628   // TODO(davidben): Stop using child ID to identify an app.
629   std::string session_id =
630       CastNavigationUIData::GetSessionIdForWebContents(web_contents);
631   DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
632   base::PostTask(
633       FROM_HERE, {content::BrowserThread::IO},
634       base::BindOnce(
635           &CastContentBrowserClient::SelectClientCertificateOnIOThread,
636           base::Unretained(this), requesting_url, session_id,
637           web_contents->GetMainFrame()->GetProcess()->GetID(),
638           web_contents->GetMainFrame()->GetRoutingID(),
639           base::SequencedTaskRunnerHandle::Get(),
640           base::BindOnce(
641               &content::ClientCertificateDelegate::ContinueWithCertificate,
642               base::Owned(delegate.release()))));
643   return base::OnceClosure();
644 }
645 
IsWhitelisted(const GURL &,const std::string &,int,int,bool)646 bool CastContentBrowserClient::IsWhitelisted(
647     const GURL& /* gurl */,
648     const std::string& /* session_id */,
649     int /* render_process_id */,
650     int /* render_frame_id */,
651     bool /* for_device_auth */) {
652   return false;
653 }
654 
SelectClientCertificateOnIOThread(GURL requesting_url,const std::string & session_id,int render_process_id,int render_frame_id,scoped_refptr<base::SequencedTaskRunner> original_runner,base::OnceCallback<void (scoped_refptr<net::X509Certificate>,scoped_refptr<net::SSLPrivateKey>)> continue_callback)655 void CastContentBrowserClient::SelectClientCertificateOnIOThread(
656     GURL requesting_url,
657     const std::string& session_id,
658     int render_process_id,
659     int render_frame_id,
660     scoped_refptr<base::SequencedTaskRunner> original_runner,
661     base::OnceCallback<void(scoped_refptr<net::X509Certificate>,
662                             scoped_refptr<net::SSLPrivateKey>)>
663         continue_callback) {
664   DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
665   if (IsWhitelisted(requesting_url, session_id, render_process_id,
666                     render_frame_id, false)) {
667     original_runner->PostTask(
668         FROM_HERE, base::BindOnce(std::move(continue_callback), DeviceCert(),
669                                   DeviceKey()));
670     return;
671   } else {
672     LOG(ERROR) << "Invalid host for client certificate request: "
673                << requesting_url.host()
674                << " with render_process_id: " << render_process_id
675                << " and render_frame_id: " << render_frame_id;
676   }
677   original_runner->PostTask(
678       FROM_HERE,
679       base::BindOnce(std::move(continue_callback), nullptr, nullptr));
680 }
681 
CanCreateWindow(content::RenderFrameHost * opener,const GURL & opener_url,const GURL & opener_top_level_frame_url,const url::Origin & source_origin,content::mojom::WindowContainerType container_type,const GURL & target_url,const content::Referrer & referrer,const std::string & frame_name,WindowOpenDisposition disposition,const blink::mojom::WindowFeatures & features,bool user_gesture,bool opener_suppressed,bool * no_javascript_access)682 bool CastContentBrowserClient::CanCreateWindow(
683     content::RenderFrameHost* opener,
684     const GURL& opener_url,
685     const GURL& opener_top_level_frame_url,
686     const url::Origin& source_origin,
687     content::mojom::WindowContainerType container_type,
688     const GURL& target_url,
689     const content::Referrer& referrer,
690     const std::string& frame_name,
691     WindowOpenDisposition disposition,
692     const blink::mojom::WindowFeatures& features,
693     bool user_gesture,
694     bool opener_suppressed,
695     bool* no_javascript_access) {
696   *no_javascript_access = true;
697   return false;
698 }
699 
GetApplicationMediaInfo(std::string * application_session_id,bool * mixer_audio_enabled,content::RenderFrameHost * render_frame_host)700 void CastContentBrowserClient::GetApplicationMediaInfo(
701     std::string* application_session_id,
702     bool* mixer_audio_enabled,
703     content::RenderFrameHost* render_frame_host) {
704   content::WebContents* web_contents =
705       content::WebContents::FromRenderFrameHost(render_frame_host);
706   if (web_contents) {
707     *application_session_id =
708         CastNavigationUIData::GetSessionIdForWebContents(web_contents);
709     chromecast::CastWebContents* cast_web_contents =
710         chromecast::CastWebContents::FromWebContents(web_contents);
711     *mixer_audio_enabled =
712         (cast_web_contents && cast_web_contents->is_mixer_audio_enabled());
713   }
714 }
715 
716 base::Optional<service_manager::Manifest>
GetServiceManifestOverlay(base::StringPiece service_name)717 CastContentBrowserClient::GetServiceManifestOverlay(
718     base::StringPiece service_name) {
719   if (service_name == content::mojom::kBrowserServiceName)
720     return GetCastContentBrowserOverlayManifest();
721 
722   return base::nullopt;
723 }
724 
725 std::vector<service_manager::Manifest>
GetExtraServiceManifests()726 CastContentBrowserClient::GetExtraServiceManifests() {
727   // NOTE: This could be simplified and the list of manifests could be inlined.
728   // Not done yet since it would require touching downstream cast code.
729   return GetCastContentPackagedServicesOverlayManifest().packaged_services;
730 }
731 
GetAdditionalMappedFilesForChildProcess(const base::CommandLine & command_line,int child_process_id,content::PosixFileDescriptorInfo * mappings)732 void CastContentBrowserClient::GetAdditionalMappedFilesForChildProcess(
733     const base::CommandLine& command_line,
734     int child_process_id,
735     content::PosixFileDescriptorInfo* mappings) {
736 #if defined(OS_ANDROID)
737   mappings->ShareWithRegion(
738       kAndroidPakDescriptor,
739       base::GlobalDescriptors::GetInstance()->Get(kAndroidPakDescriptor),
740       base::GlobalDescriptors::GetInstance()->GetRegion(kAndroidPakDescriptor));
741 #endif  // defined(OS_ANDROID)
742 #if !defined(OS_FUCHSIA)
743   // TODO(crbug.com/753619): Enable crash reporting on Fuchsia.
744   int crash_signal_fd = GetCrashSignalFD(command_line);
745   if (crash_signal_fd >= 0) {
746     mappings->Share(kCrashDumpSignal, crash_signal_fd);
747   }
748 #endif  // !defined(OS_FUCHSIA)
749 }
750 
GetAdditionalWebUISchemes(std::vector<std::string> * additional_schemes)751 void CastContentBrowserClient::GetAdditionalWebUISchemes(
752     std::vector<std::string>* additional_schemes) {
753   additional_schemes->push_back(kChromeResourceScheme);
754 }
755 
756 content::DevToolsManagerDelegate*
GetDevToolsManagerDelegate()757 CastContentBrowserClient::GetDevToolsManagerDelegate() {
758   return new CastDevToolsManagerDelegate();
759 }
760 
761 std::unique_ptr<content::NavigationUIData>
GetNavigationUIData(content::NavigationHandle * navigation_handle)762 CastContentBrowserClient::GetNavigationUIData(
763     content::NavigationHandle* navigation_handle) {
764   DCHECK(navigation_handle);
765 
766   content::WebContents* web_contents = navigation_handle->GetWebContents();
767   DCHECK(web_contents);
768 
769   std::string session_id =
770       CastNavigationUIData::GetSessionIdForWebContents(web_contents);
771   return std::make_unique<CastNavigationUIData>(session_id);
772 }
773 
ShouldEnableStrictSiteIsolation()774 bool CastContentBrowserClient::ShouldEnableStrictSiteIsolation() {
775   return false;
776 }
777 
DeviceCert()778 scoped_refptr<net::X509Certificate> CastContentBrowserClient::DeviceCert() {
779   return nullptr;
780 }
781 
DeviceKey()782 scoped_refptr<net::SSLPrivateKey> CastContentBrowserClient::DeviceKey() {
783   return nullptr;
784 }
785 
786 #if defined(OS_ANDROID)
GetCrashSignalFD(const base::CommandLine & command_line)787 int CastContentBrowserClient::GetCrashSignalFD(
788     const base::CommandLine& command_line) {
789   return crashpad::CrashHandlerHost::Get()->GetDeathSignalSocket();
790 }
791 #elif !defined(OS_FUCHSIA)
GetCrashSignalFD(const base::CommandLine & command_line)792 int CastContentBrowserClient::GetCrashSignalFD(
793     const base::CommandLine& command_line) {
794   std::string process_type =
795       command_line.GetSwitchValueASCII(switches::kProcessType);
796 
797   if (process_type == switches::kRendererProcess ||
798       process_type == switches::kGpuProcess ||
799       process_type == switches::kUtilityProcess) {
800     breakpad::CrashHandlerHostLinux* crash_handler =
801         crash_handlers_[process_type];
802     if (!crash_handler) {
803       crash_handler = CreateCrashHandlerHost(process_type);
804       crash_handlers_[process_type] = crash_handler;
805     }
806     return crash_handler->GetDeathSignalSocket();
807   }
808 
809   return -1;
810 }
811 
812 breakpad::CrashHandlerHostLinux*
CreateCrashHandlerHost(const std::string & process_type)813 CastContentBrowserClient::CreateCrashHandlerHost(
814     const std::string& process_type) {
815   // Let cast shell dump to /tmp. Internal minidump generator code can move it
816   // to /data/minidumps later, since /data/minidumps is file lock-controlled.
817   base::FilePath dumps_path;
818   base::PathService::Get(base::DIR_TEMP, &dumps_path);
819 
820   // Alway set "upload" to false to use our own uploader.
821   breakpad::CrashHandlerHostLinux* crash_handler =
822       new breakpad::CrashHandlerHostLinux(process_type, dumps_path,
823                                           false /* upload */);
824   // StartUploaderThread() even though upload is diferred.
825   // Breakpad-related memory is freed in the uploader thread.
826   crash_handler->StartUploaderThread();
827   return crash_handler;
828 }
829 #endif  // defined(OS_ANDROID)
830 
831 std::vector<std::unique_ptr<content::NavigationThrottle>>
CreateThrottlesForNavigation(content::NavigationHandle * handle)832 CastContentBrowserClient::CreateThrottlesForNavigation(
833     content::NavigationHandle* handle) {
834   std::vector<std::unique_ptr<content::NavigationThrottle>> throttles;
835 #if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
836   // If this isn't an extension renderer there's nothing to do.
837   content::SiteInstance* site_instance = handle->GetStartingSiteInstance();
838   if (site_instance) {
839     extensions::ExtensionRegistry* registry =
840         extensions::ExtensionRegistry::Get(site_instance->GetBrowserContext());
841     const extensions::Extension* extension =
842         registry->enabled_extensions().GetExtensionOrAppByURL(
843             site_instance->GetSiteURL());
844     if (extension) {
845       throttles.push_back(std::make_unique<DefaultNavigationThrottle>(
846           handle, content::NavigationThrottle::CANCEL_AND_IGNORE));
847     }
848   }
849 #endif
850 
851   if (chromecast::IsFeatureEnabled(kEnableGeneralAudienceBrowsing)) {
852     throttles.push_back(
853         std::make_unique<GeneralAudienceBrowsingNavigationThrottle>(
854             handle, general_audience_browsing_service_.get()));
855   }
856 
857 #if (defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_BSD)) && defined(USE_OZONE)
858   auto webview_throttle = WebviewController::MaybeGetNavigationThrottle(handle);
859   if (webview_throttle) {
860     throttles.push_back(std::move(webview_throttle));
861   }
862 #endif  // (defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_BSD)) && defined(USE_OZONE)
863 
864   return throttles;
865 }
866 
RegisterNonNetworkNavigationURLLoaderFactories(int frame_tree_node_id,ukm::SourceIdObj ukm_source_id,NonNetworkURLLoaderFactoryMap * factories)867 void CastContentBrowserClient::RegisterNonNetworkNavigationURLLoaderFactories(
868     int frame_tree_node_id,
869     ukm::SourceIdObj ukm_source_id,
870     NonNetworkURLLoaderFactoryMap* factories) {
871 #if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
872   content::WebContents* web_contents =
873       content::WebContents::FromFrameTreeNodeId(frame_tree_node_id);
874   auto* browser_context = web_contents->GetBrowserContext();
875   auto extension_factory =
876       extensions::CreateExtensionNavigationURLLoaderFactory(
877           browser_context, ukm_source_id,
878           !!extensions::WebViewGuest::FromWebContents(web_contents));
879   factories->emplace(extensions::kExtensionScheme,
880                      CastExtensionURLLoaderFactory::Create(
881                          browser_context, std::move(extension_factory)));
882 #endif
883 }
884 
RegisterNonNetworkSubresourceURLLoaderFactories(int render_process_id,int render_frame_id,NonNetworkURLLoaderFactoryMap * factories)885 void CastContentBrowserClient::RegisterNonNetworkSubresourceURLLoaderFactories(
886     int render_process_id,
887     int render_frame_id,
888     NonNetworkURLLoaderFactoryMap* factories) {
889   if (render_frame_id == MSG_ROUTING_NONE) {
890     LOG(ERROR) << "Service worker not supported.";
891     return;
892   }
893   content::RenderFrameHost* frame_host =
894       content::RenderFrameHost::FromID(render_process_id, render_frame_id);
895 
896 #if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
897   auto* browser_context = frame_host->GetProcess()->GetBrowserContext();
898   auto extension_factory = extensions::CreateExtensionURLLoaderFactory(
899       render_process_id, render_frame_id);
900   factories->emplace(extensions::kExtensionScheme,
901                      CastExtensionURLLoaderFactory::Create(
902                          browser_context, std::move(extension_factory)));
903 #endif
904 
905   factories->emplace(
906       kChromeResourceScheme,
907       content::CreateWebUIURLLoaderFactory(
908           frame_host, kChromeResourceScheme,
909           /*allowed_webui_hosts=*/base::flat_set<std::string>()));
910 }
911 
OnNetworkServiceCreated(network::mojom::NetworkService * network_service)912 void CastContentBrowserClient::OnNetworkServiceCreated(
913     network::mojom::NetworkService* network_service) {
914   // Need to set up global NetworkService state before anything else uses it.
915   cast_network_contexts_->OnNetworkServiceCreated(network_service);
916 }
917 
ConfigureNetworkContextParams(content::BrowserContext * context,bool in_memory,const base::FilePath & relative_partition_path,network::mojom::NetworkContextParams * network_context_params,network::mojom::CertVerifierCreationParams * cert_verifier_creation_params)918 void CastContentBrowserClient::ConfigureNetworkContextParams(
919     content::BrowserContext* context,
920     bool in_memory,
921     const base::FilePath& relative_partition_path,
922     network::mojom::NetworkContextParams* network_context_params,
923     network::mojom::CertVerifierCreationParams* cert_verifier_creation_params) {
924   return cast_network_contexts_->ConfigureNetworkContextParams(
925       context, in_memory, relative_partition_path, network_context_params,
926       cert_verifier_creation_params);
927 }
928 
DoesSiteRequireDedicatedProcess(content::BrowserContext * browser_context,const GURL & effective_site_url)929 bool CastContentBrowserClient::DoesSiteRequireDedicatedProcess(
930     content::BrowserContext* browser_context,
931     const GURL& effective_site_url) {
932   // Always isolate extensions. This prevents site isolation from messing up
933   // URLs.
934 #if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
935   return effective_site_url.SchemeIs(extensions::kExtensionScheme);
936 #else
937   return false;
938 #endif
939 }
940 
GetUserAgent()941 std::string CastContentBrowserClient::GetUserAgent() {
942   return chromecast::shell::GetUserAgent();
943 }
944 
CreateGeneralAudienceBrowsingService()945 void CastContentBrowserClient::CreateGeneralAudienceBrowsingService() {
946   DCHECK(!general_audience_browsing_service_);
947   general_audience_browsing_service_ =
948       std::make_unique<GeneralAudienceBrowsingService>(
949           cast_network_contexts_->GetSystemSharedURLLoaderFactory());
950 }
951 
BindMediaRenderer(mojo::PendingReceiver<::media::mojom::Renderer> receiver)952 void CastContentBrowserClient::BindMediaRenderer(
953     mojo::PendingReceiver<::media::mojom::Renderer> receiver) {
954   auto media_task_runner = GetMediaTaskRunner();
955   if (!media_task_runner->BelongsToCurrentThread()) {
956     media_task_runner->PostTask(
957         FROM_HERE, base::BindOnce(&CastContentBrowserClient::BindMediaRenderer,
958                                   base::Unretained(this), std::move(receiver)));
959     return;
960   }
961 
962   ::media::MojoRendererService::Create(
963       nullptr /* mojo_cdm_service_context */,
964       std::make_unique<media::CastRenderer>(
965           GetCmaBackendFactory(), std::move(media_task_runner),
966           GetVideoModeSwitcher(), GetVideoResolutionPolicy(),
967           base::UnguessableToken::Create(), nullptr /* frame_interfaces */),
968       std::move(receiver));
969 }
970 
971 }  // namespace shell
972 }  // namespace chromecast
973