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/renderer/cast_content_renderer_client.h"
6
7 #include <utility>
8
9 #include "base/command_line.h"
10 #include "base/optional.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "chromecast/base/bitstream_audio_codecs.h"
13 #include "chromecast/base/cast_features.h"
14 #include "chromecast/base/chromecast_switches.h"
15 #include "chromecast/crash/app_state_tracker.h"
16 #include "chromecast/media/base/media_codec_support.h"
17 #include "chromecast/media/base/supported_codec_profile_levels_memo.h"
18 #include "chromecast/public/media/media_capabilities_shlib.h"
19 #include "chromecast/renderer/cast_url_loader_throttle_provider.h"
20 #include "chromecast/renderer/cast_websocket_handshake_throttle_provider.h"
21 #include "chromecast/renderer/identification_settings_manager.h"
22 #include "chromecast/renderer/js_channel_bindings.h"
23 #include "chromecast/renderer/media/key_systems_cast.h"
24 #include "chromecast/renderer/media/media_caps_observer_impl.h"
25 #include "components/media_control/renderer/media_playback_options.h"
26 #include "components/network_hints/renderer/web_prescient_networking_impl.h"
27 #include "components/on_load_script_injector/renderer/on_load_script_injector.h"
28 #include "content/public/common/content_switches.h"
29 #include "content/public/renderer/render_frame.h"
30 #include "content/public/renderer/render_thread.h"
31 #include "content/public/renderer/render_view.h"
32 #include "media/base/audio_parameters.h"
33 #include "media/base/media.h"
34 #include "media/remoting/receiver_controller.h"
35 #include "media/remoting/remoting_constants.h"
36 #include "media/remoting/stream_provider.h"
37 #include "mojo/public/cpp/bindings/pending_remote.h"
38 #include "mojo/public/cpp/bindings/remote.h"
39 #include "services/network/public/cpp/is_potentially_trustworthy.h"
40 #include "third_party/blink/public/common/browser_interface_broker_proxy.h"
41 #include "third_party/blink/public/platform/web_runtime_features.h"
42 #include "third_party/blink/public/web/web_frame_widget.h"
43 #include "third_party/blink/public/web/web_security_policy.h"
44 #include "third_party/blink/public/web/web_settings.h"
45 #include "third_party/blink/public/web/web_view.h"
46
47 #if defined(OS_ANDROID)
48 #include "chromecast/media/audio/cast_audio_device_factory.h"
49 #include "media/base/android/media_codec_util.h"
50 #else
51 #include "chromecast/renderer/memory_pressure_observer_impl.h"
52 #endif // OS_ANDROID
53
54 #if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
55 #include "chromecast/common/cast_extensions_client.h"
56 #include "chromecast/renderer/cast_extensions_renderer_client.h"
57 #include "content/public/common/content_constants.h"
58 #include "extensions/common/common_manifest_handlers.h" // nogncheck
59 #include "extensions/common/extension_urls.h" // nogncheck
60 #include "extensions/renderer/dispatcher.h" // nogncheck
61 #include "extensions/renderer/extension_frame_helper.h" // nogncheck
62 #include "extensions/renderer/guest_view/extensions_guest_view_container_dispatcher.h" // nogncheck
63 #endif
64
65 namespace chromecast {
66 namespace shell {
67 namespace {
IsSupportedBitstreamAudioCodecHelper(::media::AudioCodec codec,int mask)68 bool IsSupportedBitstreamAudioCodecHelper(::media::AudioCodec codec, int mask) {
69 return (codec == ::media::kCodecAC3 && (kBitstreamAudioCodecAc3 & mask)) ||
70 (codec == ::media::kCodecEAC3 && (kBitstreamAudioCodecEac3 & mask)) ||
71 (codec == ::media::kCodecMpegHAudio &&
72 (kBitstreamAudioCodecMpegHAudio & mask));
73 }
74 } // namespace
75
76 #if defined(OS_ANDROID)
77 // Audio renderer algorithm maximum capacity.
78 constexpr base::TimeDelta kAudioRendererMaxCapacity =
79 base::TimeDelta::FromSeconds(10);
80 // Audio renderer algorithm starting capacity. Configure large enough to
81 // prevent underrun.
82 constexpr base::TimeDelta kAudioRendererStartingCapacity =
83 base::TimeDelta::FromMilliseconds(5000);
84 constexpr base::TimeDelta kAudioRendererStartingCapacityEncrypted =
85 base::TimeDelta::FromMilliseconds(5500);
86 #endif // defined(OS_ANDROID)
87
CastContentRendererClient()88 CastContentRendererClient::CastContentRendererClient()
89 : supported_profiles_(
90 std::make_unique<media::SupportedCodecProfileLevelsMemo>()),
91 activity_url_filter_manager_(
92 std::make_unique<CastActivityUrlFilterManager>()) {
93 #if defined(OS_ANDROID)
94 DCHECK(::media::MediaCodecUtil::IsMediaCodecAvailable())
95 << "MediaCodec is not available!";
96 // Platform decoder support must be enabled before we set the
97 // IsCodecSupportedCB because the latter instantiates the lazy MimeUtil
98 // instance, which caches the platform decoder supported state when it is
99 // constructed.
100 ::media::EnablePlatformDecoderSupport();
101
102 // Registers a custom content::AudioDeviceFactory
103 cast_audio_device_factory_ =
104 std::make_unique<media::CastAudioDeviceFactory>();
105 #endif // OS_ANDROID
106 }
107
108 CastContentRendererClient::~CastContentRendererClient() = default;
109
RenderThreadStarted()110 void CastContentRendererClient::RenderThreadStarted() {
111 // Register as observer for media capabilities
112 content::RenderThread* thread = content::RenderThread::Get();
113 mojo::Remote<media::mojom::MediaCaps> media_caps;
114 thread->BindHostReceiver(media_caps.BindNewPipeAndPassReceiver());
115 mojo::PendingRemote<media::mojom::MediaCapsObserver> proxy;
116 media_caps_observer_.reset(
117 new media::MediaCapsObserverImpl(&proxy, supported_profiles_.get()));
118 media_caps->AddObserver(std::move(proxy));
119
120 #if !defined(OS_ANDROID)
121 // Register to observe memory pressure changes
122 mojo::Remote<chromecast::mojom::MemoryPressureController>
123 memory_pressure_controller;
124 thread->BindHostReceiver(
125 memory_pressure_controller.BindNewPipeAndPassReceiver());
126 mojo::PendingRemote<chromecast::mojom::MemoryPressureObserver>
127 memory_pressure_proxy;
128 memory_pressure_observer_.reset(
129 new MemoryPressureObserverImpl(&memory_pressure_proxy));
130 memory_pressure_controller->AddObserver(std::move(memory_pressure_proxy));
131 #endif
132
133 base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
134
135 std::string last_launched_app =
136 command_line->GetSwitchValueNative(switches::kLastLaunchedApp);
137 if (!last_launched_app.empty())
138 AppStateTracker::SetLastLaunchedApp(last_launched_app);
139
140 std::string previous_app =
141 command_line->GetSwitchValueNative(switches::kPreviousApp);
142 if (!previous_app.empty())
143 AppStateTracker::SetPreviousApp(previous_app);
144
145 #if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
146 extensions_client_ = std::make_unique<extensions::CastExtensionsClient>();
147 extensions::ExtensionsClient::Set(extensions_client_.get());
148
149 extensions_renderer_client_ =
150 std::make_unique<extensions::CastExtensionsRendererClient>();
151 extensions::ExtensionsRendererClient::Set(extensions_renderer_client_.get());
152
153 thread->AddObserver(extensions_renderer_client_->GetDispatcher());
154
155 guest_view_container_dispatcher_ =
156 std::make_unique<extensions::ExtensionsGuestViewContainerDispatcher>();
157 thread->AddObserver(guest_view_container_dispatcher_.get());
158 #endif
159
160 for (auto& origin_or_hostname_pattern :
161 network::SecureOriginAllowlist::GetInstance().GetCurrentAllowlist()) {
162 blink::WebSecurityPolicy::AddOriginToTrustworthySafelist(
163 blink::WebString::FromUTF8(origin_or_hostname_pattern));
164 }
165 }
166
RenderViewCreated(content::RenderView * render_view)167 void CastContentRendererClient::RenderViewCreated(
168 content::RenderView* render_view) {
169 blink::WebView* webview = render_view->GetWebView();
170 webview->SetBaseBackgroundColor(chromecast::GetSwitchValueColor(
171 switches::kCastAppBackgroundColor, SK_ColorBLACK));
172 // Disable application cache as Chromecast doesn't support off-line
173 // application running.
174 webview->GetSettings()->SetOfflineWebApplicationCacheEnabled(false);
175 }
176
RenderFrameCreated(content::RenderFrame * render_frame)177 void CastContentRendererClient::RenderFrameCreated(
178 content::RenderFrame* render_frame) {
179 DCHECK(render_frame);
180
181 // Lifetime is tied to |render_frame| via content::RenderFrameObserver.
182 new media_control::MediaPlaybackOptions(render_frame);
183
184 // Add script injection support to the RenderFrame, used by Cast platform
185 // APIs. The injector's lifetime is bound to the RenderFrame's lifetime.
186 new on_load_script_injector::OnLoadScriptInjector(render_frame);
187
188 if (!app_media_capabilities_observer_receiver_.is_bound()) {
189 mojo::Remote<mojom::ApplicationMediaCapabilities> app_media_capabilities;
190 render_frame->GetBrowserInterfaceBroker()->GetInterface(
191 app_media_capabilities.BindNewPipeAndPassReceiver());
192 app_media_capabilities->AddObserver(
193 app_media_capabilities_observer_receiver_.BindNewPipeAndPassRemote());
194 }
195
196 #if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
197 extensions::Dispatcher* dispatcher =
198 extensions_renderer_client_->GetDispatcher();
199 // ExtensionFrameHelper destroys itself when the RenderFrame is destroyed.
200 new extensions::ExtensionFrameHelper(render_frame, dispatcher);
201
202 dispatcher->OnRenderFrameCreated(render_frame);
203 #endif
204
205 #if (defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_BSD)) && defined(USE_OZONE)
206 // JsChannelBindings destroys itself when the RenderFrame is destroyed.
207 JsChannelBindings::Create(render_frame);
208 #endif
209
210 activity_url_filter_manager_->OnRenderFrameCreated(render_frame);
211
212 // |base::Unretained| is safe here since the callback is triggered before the
213 // destruction of IdentificationSettingsManager by which point
214 // CastContentRendererClient should be alive.
215 settings_managers_.emplace(
216 render_frame->GetRoutingID(),
217 std::make_unique<IdentificationSettingsManager>(
218 render_frame,
219 base::BindOnce(&CastContentRendererClient::OnRenderFrameRemoved,
220 base::Unretained(this),
221 render_frame->GetRoutingID())));
222 }
223
RunScriptsAtDocumentStart(content::RenderFrame * render_frame)224 void CastContentRendererClient::RunScriptsAtDocumentStart(
225 content::RenderFrame* render_frame) {
226 #if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
227 extensions_renderer_client_->GetDispatcher()->RunScriptsAtDocumentStart(
228 render_frame);
229 #endif
230 }
231
RunScriptsAtDocumentEnd(content::RenderFrame * render_frame)232 void CastContentRendererClient::RunScriptsAtDocumentEnd(
233 content::RenderFrame* render_frame) {
234 #if BUILDFLAG(ENABLE_CHROMECAST_EXTENSIONS)
235 extensions_renderer_client_->GetDispatcher()->RunScriptsAtDocumentEnd(
236 render_frame);
237 #endif
238 }
239
AddSupportedKeySystems(std::vector<std::unique_ptr<::media::KeySystemProperties>> * key_systems_properties)240 void CastContentRendererClient::AddSupportedKeySystems(
241 std::vector<std::unique_ptr<::media::KeySystemProperties>>*
242 key_systems_properties) {
243 media::AddChromecastKeySystems(key_systems_properties,
244 false /* enable_persistent_license_support */,
245 false /* force_software_crypto */);
246 }
247
IsSupportedAudioType(const::media::AudioType & type)248 bool CastContentRendererClient::IsSupportedAudioType(
249 const ::media::AudioType& type) {
250 #if defined(OS_ANDROID)
251 if (type.spatial_rendering)
252 return false;
253
254 // No ATV device we know of has (E)AC3 decoder, so it relies on the audio sink
255 // device.
256 if (type.codec == ::media::kCodecEAC3) {
257 return kBitstreamAudioCodecEac3 &
258 supported_bitstream_audio_codecs_info_.codecs;
259 }
260 if (type.codec == ::media::kCodecAC3) {
261 return kBitstreamAudioCodecAc3 &
262 supported_bitstream_audio_codecs_info_.codecs;
263 }
264 if (type.codec == ::media::kCodecMpegHAudio) {
265 return kBitstreamAudioCodecMpegHAudio &
266 supported_bitstream_audio_codecs_info_.codecs;
267 }
268
269 return ::media::IsDefaultSupportedAudioType(type);
270 #else
271 if (type.profile == ::media::AudioCodecProfile::kXHE_AAC)
272 return false;
273
274 // If the HDMI sink supports bitstreaming the codec, then the vendor backend
275 // does not need to support it.
276 if (CheckSupportedBitstreamAudioCodec(type.codec, type.spatial_rendering))
277 return true;
278
279 media::AudioCodec codec = media::ToCastAudioCodec(type.codec);
280 // Cast platform implements software decoding of Opus and FLAC, so only PCM
281 // support is necessary in order to support Opus and FLAC.
282 if (codec == media::kCodecOpus || codec == media::kCodecFLAC)
283 codec = media::kCodecPCM;
284
285 media::AudioConfig cast_audio_config;
286 cast_audio_config.codec = codec;
287 return media::MediaCapabilitiesShlib::IsSupportedAudioConfig(
288 cast_audio_config);
289 #endif
290 }
291
IsSupportedVideoType(const::media::VideoType & type)292 bool CastContentRendererClient::IsSupportedVideoType(
293 const ::media::VideoType& type) {
294 // TODO(servolk): make use of eotf.
295
296 // TODO(1066567): Check attached screen for support of type.hdr_metadata_type.
297 if (type.hdr_metadata_type != ::gfx::HdrMetadataType::kNone) {
298 NOTIMPLEMENTED() << "HdrMetadataType support signaling not implemented.";
299 return false;
300 }
301
302 #if defined(OS_ANDROID)
303 return supported_profiles_->IsSupportedVideoConfig(
304 media::ToCastVideoCodec(type.codec, type.profile),
305 media::ToCastVideoProfile(type.profile), type.level);
306 #else
307 return media::MediaCapabilitiesShlib::IsSupportedVideoConfig(
308 media::ToCastVideoCodec(type.codec, type.profile),
309 media::ToCastVideoProfile(type.profile), type.level);
310 #endif
311 }
312
IsSupportedBitstreamAudioCodec(::media::AudioCodec codec)313 bool CastContentRendererClient::IsSupportedBitstreamAudioCodec(
314 ::media::AudioCodec codec) {
315 return IsSupportedBitstreamAudioCodecHelper(
316 codec, supported_bitstream_audio_codecs_info_.codecs);
317 }
318
CheckSupportedBitstreamAudioCodec(::media::AudioCodec codec,bool check_spatial_rendering)319 bool CastContentRendererClient::CheckSupportedBitstreamAudioCodec(
320 ::media::AudioCodec codec,
321 bool check_spatial_rendering) {
322 if (!IsSupportedBitstreamAudioCodec(codec))
323 return false;
324
325 if (!check_spatial_rendering)
326 return true;
327
328 return IsSupportedBitstreamAudioCodecHelper(
329 codec, supported_bitstream_audio_codecs_info_.spatial_rendering);
330 }
331
332 std::unique_ptr<blink::WebPrescientNetworking>
CreatePrescientNetworking(content::RenderFrame * render_frame)333 CastContentRendererClient::CreatePrescientNetworking(
334 content::RenderFrame* render_frame) {
335 return std::make_unique<network_hints::WebPrescientNetworkingImpl>(
336 render_frame);
337 }
338
DeferMediaLoad(content::RenderFrame * render_frame,bool render_frame_has_played_media_before,base::OnceClosure closure)339 bool CastContentRendererClient::DeferMediaLoad(
340 content::RenderFrame* render_frame,
341 bool render_frame_has_played_media_before,
342 base::OnceClosure closure) {
343 return RunWhenInForeground(render_frame, std::move(closure));
344 }
345
346 std::unique_ptr<::media::Demuxer>
OverrideDemuxerForUrl(content::RenderFrame * render_frame,const GURL & url,scoped_refptr<base::SingleThreadTaskRunner> task_runner)347 CastContentRendererClient::OverrideDemuxerForUrl(
348 content::RenderFrame* render_frame,
349 const GURL& url,
350 scoped_refptr<base::SingleThreadTaskRunner> task_runner) {
351 if (render_frame->GetRenderFrameMediaPlaybackOptions()
352 .is_remoting_renderer_enabled() &&
353 url.SchemeIs(::media::remoting::kRemotingScheme)) {
354 return std::make_unique<::media::remoting::StreamProvider>(
355 ::media::remoting::ReceiverController::GetInstance(), task_runner);
356 }
357 return nullptr;
358 }
359
RunWhenInForeground(content::RenderFrame * render_frame,base::OnceClosure closure)360 bool CastContentRendererClient::RunWhenInForeground(
361 content::RenderFrame* render_frame,
362 base::OnceClosure closure) {
363 auto* playback_options =
364 media_control::MediaPlaybackOptions::Get(render_frame);
365 DCHECK(playback_options);
366 return playback_options->RunWhenInForeground(std::move(closure));
367 }
368
IsIdleMediaSuspendEnabled()369 bool CastContentRendererClient::IsIdleMediaSuspendEnabled() {
370 return false;
371 }
372
373 void CastContentRendererClient::
SetRuntimeFeaturesDefaultsBeforeBlinkInitialization()374 SetRuntimeFeaturesDefaultsBeforeBlinkInitialization() {
375 // Allow HtmlMediaElement.volume to be greater than 1, for normalization.
376 blink::WebRuntimeFeatures::EnableFeatureFromString(
377 "MediaElementVolumeGreaterThanOne", true);
378 // Settings for ATV (Android defaults are not what we want).
379 blink::WebRuntimeFeatures::EnableMediaControlsOverlayPlayButton(false);
380 }
381
OnSupportedBitstreamAudioCodecsChanged(const BitstreamAudioCodecsInfo & info)382 void CastContentRendererClient::OnSupportedBitstreamAudioCodecsChanged(
383 const BitstreamAudioCodecsInfo& info) {
384 supported_bitstream_audio_codecs_info_ = info;
385 }
386
387 std::unique_ptr<content::WebSocketHandshakeThrottleProvider>
CreateWebSocketHandshakeThrottleProvider()388 CastContentRendererClient::CreateWebSocketHandshakeThrottleProvider() {
389 return std::make_unique<CastWebSocketHandshakeThrottleProvider>(
390 activity_url_filter_manager_.get());
391 }
392
393 std::unique_ptr<content::URLLoaderThrottleProvider>
CreateURLLoaderThrottleProvider(content::URLLoaderThrottleProviderType type)394 CastContentRendererClient::CreateURLLoaderThrottleProvider(
395 content::URLLoaderThrottleProviderType type) {
396 return std::make_unique<CastURLLoaderThrottleProvider>(
397 type, activity_url_filter_manager(), this);
398 }
399
400 base::Optional<::media::AudioRendererAlgorithmParameters>
GetAudioRendererAlgorithmParameters(::media::AudioParameters audio_parameters)401 CastContentRendererClient::GetAudioRendererAlgorithmParameters(
402 ::media::AudioParameters audio_parameters) {
403 #if defined(OS_ANDROID)
404 ::media::AudioRendererAlgorithmParameters parameters;
405 parameters.max_capacity = kAudioRendererMaxCapacity;
406 parameters.starting_capacity = kAudioRendererStartingCapacity;
407 parameters.starting_capacity_for_encrypted =
408 kAudioRendererStartingCapacityEncrypted;
409 return base::Optional<::media::AudioRendererAlgorithmParameters>(parameters);
410 #else
411 return base::nullopt;
412 #endif
413 }
414
415 IdentificationSettingsManager*
GetSettingsManagerFromRenderFrameID(int render_frame_id)416 CastContentRendererClient::GetSettingsManagerFromRenderFrameID(
417 int render_frame_id) {
418 const auto& it = settings_managers_.find(render_frame_id);
419 if (it == settings_managers_.end()) {
420 return nullptr;
421 }
422 return it->second.get();
423 }
424
OnRenderFrameRemoved(int render_frame_id)425 void CastContentRendererClient::OnRenderFrameRemoved(int render_frame_id) {
426 size_t result = settings_managers_.erase(render_frame_id);
427 if (result != 1U) {
428 LOG(WARNING)
429 << "Can't find the identification settings manager for render frame: "
430 << render_frame_id;
431 }
432 }
433
434 } // namespace shell
435 } // namespace chromecast
436