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