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