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.
5 #include "chromecast/renderer/cast_content_renderer_client.h"
7 #include <sys/sysinfo.h>
9 #include "base/command_line.h"
10 #include "base/location.h"
11 #include "base/memory/memory_pressure_listener.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/thread_task_runner_handle.h"
14 #include "chromecast/base/chromecast_switches.h"
15 #include "chromecast/crash/cast_crash_keys.h"
16 #include "chromecast/media/base/media_caps.h"
17 #include "chromecast/renderer/cast_media_load_deferrer.h"
18 #include "chromecast/renderer/cast_render_process_observer.h"
19 #include "chromecast/renderer/key_systems_cast.h"
20 #include "chromecast/renderer/media/chromecast_media_renderer_factory.h"
21 #include "components/network_hints/renderer/prescient_networking_dispatcher.h"
22 #include "content/public/common/content_switches.h"
23 #include "content/public/renderer/render_frame.h"
24 #include "content/public/renderer/render_view.h"
25 #include "content/public/renderer/render_view_observer.h"
26 #include "crypto/nss_util.h"
27 #include "third_party/WebKit/public/platform/WebColor.h"
28 #include "third_party/WebKit/public/web/WebSettings.h"
29 #include "third_party/WebKit/public/web/WebView.h"
31 namespace chromecast
{
36 #if defined(ARCH_CPU_ARM_FAMILY) && !defined(OS_ANDROID)
37 // This memory threshold is set for Chromecast. See the UMA histogram
38 // Platform.MeminfoMemFree when tuning.
39 // TODO(gunsch): These should be platform/product-dependent. Look into a way
40 // to move these to platform-specific repositories.
41 const int kCriticalMinFreeMemMB
= 24;
42 const int kPollingIntervalMS
= 5000;
44 void PlatformPollFreemem(void) {
47 if (sysinfo(&sys
) == -1) {
48 LOG(ERROR
) << "platform_poll_freemem(): sysinfo failed";
50 int free_mem_mb
= static_cast<int64_t>(sys
.freeram
) *
51 sys
.mem_unit
/ (1024 * 1024);
53 if (free_mem_mb
<= kCriticalMinFreeMemMB
) {
54 // Memory is getting really low, we need to do whatever we can to
55 // prevent deadlocks and interfering with other processes.
56 base::MemoryPressureListener::NotifyMemoryPressure(
57 base::MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL
);
62 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
63 FROM_HERE
, base::Bind(&PlatformPollFreemem
),
64 base::TimeDelta::FromMilliseconds(kPollingIntervalMS
));
68 // Default background color to set for WebViews. WebColor is in ARGB format
69 // though the comment of WebColor says it is in RGBA.
70 const blink::WebColor kColorBlack
= 0xFF000000;
72 class CastRenderViewObserver
: content::RenderViewObserver
{
74 CastRenderViewObserver(CastContentRendererClient
* client
,
75 content::RenderView
* render_view
);
76 ~CastRenderViewObserver() override
{}
78 void DidClearWindowObject(blink::WebLocalFrame
* frame
) override
;
81 CastContentRendererClient
* const client_
;
83 DISALLOW_COPY_AND_ASSIGN(CastRenderViewObserver
);
86 CastRenderViewObserver::CastRenderViewObserver(
87 CastContentRendererClient
* client
,
88 content::RenderView
* render_view
)
89 : content::RenderViewObserver(render_view
),
93 void CastRenderViewObserver::DidClearWindowObject(blink::WebLocalFrame
* frame
) {
94 client_
->AddRendererNativeBindings(frame
);
99 CastContentRendererClient::CastContentRendererClient()
100 : allow_hidden_media_playback_(
101 base::CommandLine::ForCurrentProcess()->HasSwitch(
102 switches::kAllowHiddenMediaPlayback
)) {
105 CastContentRendererClient::~CastContentRendererClient() {
108 void CastContentRendererClient::AddRendererNativeBindings(
109 blink::WebLocalFrame
* frame
) {
112 void CastContentRendererClient::RenderThreadStarted() {
113 base::CommandLine
* command_line
= base::CommandLine::ForCurrentProcess();
114 #if !defined(USE_OPENSSL)
115 // Note: Copied from chrome_render_process_observer.cc to fix b/8676652.
117 // On platforms where the system NSS shared libraries are used,
118 // initialize NSS now because it won't be able to load the .so's
119 // after entering the sandbox.
120 if (!command_line
->HasSwitch(switches::kSingleProcess
))
121 crypto::InitNSSSafely();
124 #if defined(ARCH_CPU_ARM_FAMILY) && !defined(OS_ANDROID)
125 PlatformPollFreemem();
128 // Set the initial known codecs mask.
129 if (command_line
->HasSwitch(switches::kHdmiSinkSupportedCodecs
)) {
130 int hdmi_codecs_mask
;
131 if (base::StringToInt(command_line
->GetSwitchValueASCII(
132 switches::kHdmiSinkSupportedCodecs
),
133 &hdmi_codecs_mask
)) {
134 ::media::SetHdmiSinkCodecs(hdmi_codecs_mask
);
138 cast_observer_
.reset(new CastRenderProcessObserver());
140 prescient_networking_dispatcher_
.reset(
141 new network_hints::PrescientNetworkingDispatcher());
143 std::string last_launched_app
=
144 command_line
->GetSwitchValueNative(switches::kLastLaunchedApp
);
145 if (!last_launched_app
.empty())
146 base::debug::SetCrashKeyValue(crash_keys::kLastApp
, last_launched_app
);
148 std::string previous_app
=
149 command_line
->GetSwitchValueNative(switches::kPreviousApp
);
150 if (!previous_app
.empty())
151 base::debug::SetCrashKeyValue(crash_keys::kPreviousApp
, previous_app
);
154 void CastContentRendererClient::RenderViewCreated(
155 content::RenderView
* render_view
) {
156 blink::WebView
* webview
= render_view
->GetWebView();
158 webview
->setBaseBackgroundColor(kColorBlack
);
160 // The following settings express consistent behaviors across Cast
161 // embedders, though Android has enabled by default for mobile browsers.
162 webview
->settings()->setShrinksViewportContentToFit(false);
163 webview
->settings()->setMediaControlsOverlayPlayButtonEnabled(false);
165 // Scale 1 ensures window.innerHeight/Width match application resolution.
166 // PageScaleOverride is the 'user agent' value which overrides page
167 // settings (from meta viewport tag) - thus preventing inconsistency
168 // between Android and non-Android cast_shell.
169 webview
->setDefaultPageScaleLimits(1.f
, 1.f
);
170 webview
->setInitialPageScaleOverride(1.f
);
172 // Disable application cache as Chromecast doesn't support off-line
173 // application running.
174 webview
->settings()->setOfflineWebApplicationCacheEnabled(false);
177 // Note: RenderView will own the lifetime of its observer.
178 new CastRenderViewObserver(this, render_view
);
181 void CastContentRendererClient::AddKeySystems(
182 std::vector
< ::media::KeySystemInfo
>* key_systems
) {
183 AddChromecastKeySystems(key_systems
);
186 #if !defined(OS_ANDROID)
187 scoped_ptr
<::media::RendererFactory
>
188 CastContentRendererClient::CreateMediaRendererFactory(
189 ::content::RenderFrame
* render_frame
,
190 const scoped_refptr
<::media::GpuVideoAcceleratorFactories
>& gpu_factories
,
191 const scoped_refptr
<::media::MediaLog
>& media_log
) {
192 const base::CommandLine
* cmd_line
= base::CommandLine::ForCurrentProcess();
193 if (!cmd_line
->HasSwitch(switches::kEnableCmaMediaPipeline
))
196 return scoped_ptr
<::media::RendererFactory
>(
197 new chromecast::media::ChromecastMediaRendererFactory(
198 gpu_factories
, media_log
, render_frame
->GetRoutingID()));
202 blink::WebPrescientNetworking
*
203 CastContentRendererClient::GetPrescientNetworking() {
204 return prescient_networking_dispatcher_
.get();
207 void CastContentRendererClient::DeferMediaLoad(
208 content::RenderFrame
* render_frame
,
209 bool render_frame_has_played_media_before
,
210 const base::Closure
& closure
) {
211 if (!render_frame
->IsHidden() || allow_hidden_media_playback_
) {
216 // Lifetime is tied to |render_frame| via content::RenderFrameObserver.
217 new CastMediaLoadDeferrer(render_frame
, closure
);
221 } // namespace chromecast