Delete chrome.mediaGalleriesPrivate because the functionality unique to it has since...
[chromium-blink-merge.git] / chrome / renderer / chrome_render_process_observer.cc
blob9367b98d2318f32f4367e403054aefe549379c54
1 // Copyright (c) 2012 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 "chrome/renderer/chrome_render_process_observer.h"
7 #include <limits>
8 #include <vector>
10 #include "base/allocator/allocator_extension.h"
11 #include "base/bind.h"
12 #include "base/command_line.h"
13 #include "base/files/file_util.h"
14 #include "base/memory/weak_ptr.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/metrics/field_trial.h"
17 #include "base/metrics/histogram.h"
18 #include "base/metrics/statistics_recorder.h"
19 #include "base/native_library.h"
20 #include "base/path_service.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/threading/platform_thread.h"
23 #include "chrome/common/child_process_logging.h"
24 #include "chrome/common/chrome_paths.h"
25 #include "chrome/common/chrome_switches.h"
26 #include "chrome/common/net/net_resource_provider.h"
27 #include "chrome/common/render_messages.h"
28 #include "chrome/common/url_constants.h"
29 #include "chrome/common/variations/variations_util.h"
30 #include "chrome/renderer/content_settings_observer.h"
31 #include "chrome/renderer/security_filter_peer.h"
32 #include "content/public/child/resource_dispatcher_delegate.h"
33 #include "content/public/renderer/render_thread.h"
34 #include "content/public/renderer/render_view.h"
35 #include "content/public/renderer/render_view_visitor.h"
36 #include "crypto/nss_util.h"
37 #include "net/base/net_errors.h"
38 #include "net/base/net_module.h"
39 #include "third_party/WebKit/public/web/WebCache.h"
40 #include "third_party/WebKit/public/web/WebDocument.h"
41 #include "third_party/WebKit/public/web/WebFrame.h"
42 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
43 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
44 #include "third_party/WebKit/public/web/WebView.h"
46 #if defined(OS_WIN)
47 #include "base/win/iat_patch_function.h"
48 #endif
50 #if defined(ENABLE_EXTENSIONS)
51 #include "chrome/renderer/extensions/extension_localization_peer.h"
52 #endif
54 using blink::WebCache;
55 using blink::WebRuntimeFeatures;
56 using blink::WebSecurityPolicy;
57 using blink::WebString;
58 using content::RenderThread;
60 namespace {
62 const int kCacheStatsDelayMS = 2000;
64 class RendererResourceDelegate : public content::ResourceDispatcherDelegate {
65 public:
66 RendererResourceDelegate()
67 : weak_factory_(this) {
70 content::RequestPeer* OnRequestComplete(content::RequestPeer* current_peer,
71 content::ResourceType resource_type,
72 int error_code) override {
73 // Update the browser about our cache.
74 // Rate limit informing the host of our cache stats.
75 if (!weak_factory_.HasWeakPtrs()) {
76 base::MessageLoop::current()->PostDelayedTask(
77 FROM_HERE,
78 base::Bind(&RendererResourceDelegate::InformHostOfCacheStats,
79 weak_factory_.GetWeakPtr()),
80 base::TimeDelta::FromMilliseconds(kCacheStatsDelayMS));
83 if (error_code == net::ERR_ABORTED) {
84 return NULL;
87 // Resource canceled with a specific error are filtered.
88 return SecurityFilterPeer::CreateSecurityFilterPeerForDeniedRequest(
89 resource_type, current_peer, error_code);
92 content::RequestPeer* OnReceivedResponse(content::RequestPeer* current_peer,
93 const std::string& mime_type,
94 const GURL& url) override {
95 #if defined(ENABLE_EXTENSIONS)
96 return ExtensionLocalizationPeer::CreateExtensionLocalizationPeer(
97 current_peer, RenderThread::Get(), mime_type, url);
98 #else
99 return NULL;
100 #endif
103 private:
104 void InformHostOfCacheStats() {
105 WebCache::UsageStats stats;
106 WebCache::getUsageStats(&stats);
107 RenderThread::Get()->Send(new ChromeViewHostMsg_UpdatedCacheStats(stats));
110 base::WeakPtrFactory<RendererResourceDelegate> weak_factory_;
112 DISALLOW_COPY_AND_ASSIGN(RendererResourceDelegate);
115 #if defined(OS_WIN)
116 static base::win::IATPatchFunction g_iat_patch_createdca;
117 HDC WINAPI CreateDCAPatch(LPCSTR driver_name,
118 LPCSTR device_name,
119 LPCSTR output,
120 const void* init_data) {
121 DCHECK(std::string("DISPLAY") == std::string(driver_name));
122 DCHECK(!device_name);
123 DCHECK(!output);
124 DCHECK(!init_data);
126 // CreateDC fails behind the sandbox, but not CreateCompatibleDC.
127 return CreateCompatibleDC(NULL);
130 static base::win::IATPatchFunction g_iat_patch_get_font_data;
131 DWORD WINAPI GetFontDataPatch(HDC hdc,
132 DWORD table,
133 DWORD offset,
134 LPVOID buffer,
135 DWORD length) {
136 int rv = GetFontData(hdc, table, offset, buffer, length);
137 if (rv == GDI_ERROR && hdc) {
138 HFONT font = static_cast<HFONT>(GetCurrentObject(hdc, OBJ_FONT));
140 LOGFONT logfont;
141 if (GetObject(font, sizeof(LOGFONT), &logfont)) {
142 std::vector<char> font_data;
143 RenderThread::Get()->PreCacheFont(logfont);
144 rv = GetFontData(hdc, table, offset, buffer, length);
145 RenderThread::Get()->ReleaseCachedFonts();
148 return rv;
150 #endif // OS_WIN
152 static const int kWaitForWorkersStatsTimeoutMS = 20;
154 class HeapStatisticsCollector {
155 public:
156 HeapStatisticsCollector() : round_id_(0) {}
158 void InitiateCollection();
159 static HeapStatisticsCollector* Instance();
161 private:
162 void CollectOnWorkerThread(scoped_refptr<base::TaskRunner> master,
163 int round_id);
164 void ReceiveStats(int round_id, size_t total_size, size_t used_size);
165 void SendStatsToBrowser(int round_id);
167 size_t total_bytes_;
168 size_t used_bytes_;
169 int workers_to_go_;
170 int round_id_;
173 HeapStatisticsCollector* HeapStatisticsCollector::Instance() {
174 CR_DEFINE_STATIC_LOCAL(HeapStatisticsCollector, instance, ());
175 return &instance;
178 void HeapStatisticsCollector::InitiateCollection() {
179 v8::HeapStatistics heap_stats;
180 v8::Isolate::GetCurrent()->GetHeapStatistics(&heap_stats);
181 total_bytes_ = heap_stats.total_heap_size();
182 used_bytes_ = heap_stats.used_heap_size();
183 base::Closure collect = base::Bind(
184 &HeapStatisticsCollector::CollectOnWorkerThread,
185 base::Unretained(this),
186 base::MessageLoopProxy::current(),
187 round_id_);
188 workers_to_go_ = RenderThread::Get()->PostTaskToAllWebWorkers(collect);
189 if (workers_to_go_) {
190 // The guard task to send out partial stats
191 // in case some workers are not responsive.
192 base::MessageLoopProxy::current()->PostDelayedTask(
193 FROM_HERE,
194 base::Bind(&HeapStatisticsCollector::SendStatsToBrowser,
195 base::Unretained(this),
196 round_id_),
197 base::TimeDelta::FromMilliseconds(kWaitForWorkersStatsTimeoutMS));
198 } else {
199 // No worker threads so just send out the main thread data right away.
200 SendStatsToBrowser(round_id_);
204 void HeapStatisticsCollector::CollectOnWorkerThread(
205 scoped_refptr<base::TaskRunner> master,
206 int round_id) {
208 size_t total_bytes = 0;
209 size_t used_bytes = 0;
210 v8::Isolate* isolate = v8::Isolate::GetCurrent();
211 if (isolate) {
212 v8::HeapStatistics heap_stats;
213 isolate->GetHeapStatistics(&heap_stats);
214 total_bytes = heap_stats.total_heap_size();
215 used_bytes = heap_stats.used_heap_size();
217 master->PostTask(
218 FROM_HERE,
219 base::Bind(&HeapStatisticsCollector::ReceiveStats,
220 base::Unretained(this),
221 round_id,
222 total_bytes,
223 used_bytes));
226 void HeapStatisticsCollector::ReceiveStats(int round_id,
227 size_t total_bytes,
228 size_t used_bytes) {
229 if (round_id != round_id_)
230 return;
231 total_bytes_ += total_bytes;
232 used_bytes_ += used_bytes;
233 if (!--workers_to_go_)
234 SendStatsToBrowser(round_id);
237 void HeapStatisticsCollector::SendStatsToBrowser(int round_id) {
238 if (round_id != round_id_)
239 return;
240 // TODO(alph): Do caching heap stats and use the cache if we haven't got
241 // reply from a worker.
242 // Currently a busy worker stats are not counted.
243 RenderThread::Get()->Send(new ChromeViewHostMsg_V8HeapStats(
244 total_bytes_, used_bytes_));
245 ++round_id_;
248 } // namespace
250 bool ChromeRenderProcessObserver::is_incognito_process_ = false;
252 ChromeRenderProcessObserver::ChromeRenderProcessObserver(
253 ChromeContentRendererClient* client)
254 : client_(client),
255 webkit_initialized_(false) {
256 const base::CommandLine& command_line =
257 *base::CommandLine::ForCurrentProcess();
259 #if defined(ENABLE_AUTOFILL_DIALOG)
260 WebRuntimeFeatures::enableRequestAutocomplete(true);
261 #endif
263 if (command_line.HasSwitch(switches::kEnableShowModalDialog))
264 WebRuntimeFeatures::enableShowModalDialog(true);
266 if (command_line.HasSwitch(switches::kDisableJavaScriptHarmonyShipping)) {
267 std::string flag("--noharmony-shipping");
268 v8::V8::SetFlagsFromString(flag.c_str(), static_cast<int>(flag.size()));
271 if (command_line.HasSwitch(switches::kJavaScriptHarmony)) {
272 std::string flag("--harmony");
273 v8::V8::SetFlagsFromString(flag.c_str(), static_cast<int>(flag.size()));
276 RenderThread* thread = RenderThread::Get();
277 resource_delegate_.reset(new RendererResourceDelegate());
278 thread->SetResourceDispatcherDelegate(resource_delegate_.get());
280 // Configure modules that need access to resources.
281 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider);
283 #if defined(OS_WIN)
284 // TODO(scottmg): http://crbug.com/448473. This code should be removed once
285 // PDF is always OOP and/or PDF is made to use Skia instead of GDI directly.
286 if (!command_line.HasSwitch(switches::kEnableOutOfProcessPdf)) {
287 // Need to patch a few functions for font loading to work correctly.
288 base::FilePath pdf;
289 if (PathService::Get(chrome::FILE_PDF_PLUGIN, &pdf) &&
290 base::PathExists(pdf)) {
291 g_iat_patch_createdca.Patch(pdf.value().c_str(), "gdi32.dll", "CreateDCA",
292 CreateDCAPatch);
293 g_iat_patch_get_font_data.Patch(pdf.value().c_str(), "gdi32.dll",
294 "GetFontData", GetFontDataPatch);
297 #endif
299 #if defined(OS_POSIX) && !defined(OS_MACOSX) && defined(USE_NSS)
300 // On platforms where we use system NSS shared libraries,
301 // initialize NSS now because it won't be able to load the .so's
302 // after we engage the sandbox.
303 if (!command_line.HasSwitch(switches::kSingleProcess))
304 crypto::InitNSSSafely();
305 #elif defined(OS_WIN)
306 // crypt32.dll is used to decode X509 certificates for Chromoting.
307 // Only load this library when the feature is enabled.
308 base::LoadNativeLibrary(base::FilePath(L"crypt32.dll"), NULL);
309 #endif
310 // Setup initial set of crash dump data for Field Trials in this renderer.
311 chrome_variations::SetChildProcessLoggingVariationList();
312 // Listen for field trial activations to report them to the browser.
313 base::FieldTrialList::AddObserver(this);
316 ChromeRenderProcessObserver::~ChromeRenderProcessObserver() {
319 bool ChromeRenderProcessObserver::OnControlMessageReceived(
320 const IPC::Message& message) {
321 bool handled = true;
322 IPC_BEGIN_MESSAGE_MAP(ChromeRenderProcessObserver, message)
323 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsIncognitoProcess,
324 OnSetIsIncognitoProcess)
325 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetFieldTrialGroup, OnSetFieldTrialGroup)
326 IPC_MESSAGE_HANDLER(ChromeViewMsg_GetV8HeapStats, OnGetV8HeapStats)
327 IPC_MESSAGE_HANDLER(ChromeViewMsg_GetCacheResourceStats,
328 OnGetCacheResourceStats)
329 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetContentSettingRules,
330 OnSetContentSettingRules)
331 IPC_MESSAGE_UNHANDLED(handled = false)
332 IPC_END_MESSAGE_MAP()
333 return handled;
336 void ChromeRenderProcessObserver::WebKitInitialized() {
337 webkit_initialized_ = true;
338 // chrome-native: is a scheme used for placeholder navigations that allow
339 // UIs to be drawn with platform native widgets instead of HTML. These pages
340 // should not be accessible, and should also be treated as empty documents
341 // that can commit synchronously. No code should be runnable in these pages,
342 // so it should not need to access anything nor should it allow javascript
343 // URLs since it should never be visible to the user.
344 WebString native_scheme(base::ASCIIToUTF16(chrome::kChromeNativeScheme));
345 WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(native_scheme);
346 WebSecurityPolicy::registerURLSchemeAsEmptyDocument(native_scheme);
347 WebSecurityPolicy::registerURLSchemeAsNoAccess(native_scheme);
348 WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs(
349 native_scheme);
352 void ChromeRenderProcessObserver::OnRenderProcessShutdown() {
353 webkit_initialized_ = false;
356 void ChromeRenderProcessObserver::OnSetIsIncognitoProcess(
357 bool is_incognito_process) {
358 is_incognito_process_ = is_incognito_process;
361 void ChromeRenderProcessObserver::OnSetContentSettingRules(
362 const RendererContentSettingRules& rules) {
363 content_setting_rules_ = rules;
366 void ChromeRenderProcessObserver::OnGetCacheResourceStats() {
367 WebCache::ResourceTypeStats stats;
368 if (webkit_initialized_)
369 WebCache::getResourceTypeStats(&stats);
370 RenderThread::Get()->Send(new ChromeViewHostMsg_ResourceTypeStats(stats));
373 void ChromeRenderProcessObserver::OnSetFieldTrialGroup(
374 const std::string& field_trial_name,
375 const std::string& group_name) {
376 base::FieldTrial* trial =
377 base::FieldTrialList::CreateFieldTrial(field_trial_name, group_name);
378 // TODO(mef): Remove this check after the investigation of 359406 is complete.
379 CHECK(trial) << field_trial_name << ":" << group_name;
380 // Ensure the trial is marked as "used" by calling group() on it if it is
381 // marked as activated.
382 trial->group();
383 chrome_variations::SetChildProcessLoggingVariationList();
386 void ChromeRenderProcessObserver::OnGetV8HeapStats() {
387 HeapStatisticsCollector::Instance()->InitiateCollection();
390 const RendererContentSettingRules*
391 ChromeRenderProcessObserver::content_setting_rules() const {
392 return &content_setting_rules_;
395 void ChromeRenderProcessObserver::OnFieldTrialGroupFinalized(
396 const std::string& trial_name,
397 const std::string& group_name) {
398 content::RenderThread::Get()->Send(
399 new ChromeViewHostMsg_FieldTrialActivated(trial_name));