tools/gn: fix escaping of backslashes
[chromium-blink-merge.git] / chrome / renderer / chrome_render_process_observer.cc
blobc1c97c6dc8eb5abc7fe8112c89a8d1e509daf1e8
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(ENABLE_EXTENSIONS)
47 #include "chrome/renderer/extensions/extension_localization_peer.h"
48 #endif
50 using blink::WebCache;
51 using blink::WebRuntimeFeatures;
52 using blink::WebSecurityPolicy;
53 using blink::WebString;
54 using content::RenderThread;
56 namespace {
58 const int kCacheStatsDelayMS = 2000;
60 class RendererResourceDelegate : public content::ResourceDispatcherDelegate {
61 public:
62 RendererResourceDelegate()
63 : weak_factory_(this) {
66 content::RequestPeer* OnRequestComplete(content::RequestPeer* current_peer,
67 content::ResourceType resource_type,
68 int error_code) override {
69 // Update the browser about our cache.
70 // Rate limit informing the host of our cache stats.
71 if (!weak_factory_.HasWeakPtrs()) {
72 base::MessageLoop::current()->PostDelayedTask(
73 FROM_HERE,
74 base::Bind(&RendererResourceDelegate::InformHostOfCacheStats,
75 weak_factory_.GetWeakPtr()),
76 base::TimeDelta::FromMilliseconds(kCacheStatsDelayMS));
79 if (error_code == net::ERR_ABORTED) {
80 return NULL;
83 // Resource canceled with a specific error are filtered.
84 return SecurityFilterPeer::CreateSecurityFilterPeerForDeniedRequest(
85 resource_type, current_peer, error_code);
88 content::RequestPeer* OnReceivedResponse(content::RequestPeer* current_peer,
89 const std::string& mime_type,
90 const GURL& url) override {
91 #if defined(ENABLE_EXTENSIONS)
92 return ExtensionLocalizationPeer::CreateExtensionLocalizationPeer(
93 current_peer, RenderThread::Get(), mime_type, url);
94 #else
95 return NULL;
96 #endif
99 private:
100 void InformHostOfCacheStats() {
101 WebCache::UsageStats stats;
102 WebCache::getUsageStats(&stats);
103 RenderThread::Get()->Send(new ChromeViewHostMsg_UpdatedCacheStats(stats));
106 base::WeakPtrFactory<RendererResourceDelegate> weak_factory_;
108 DISALLOW_COPY_AND_ASSIGN(RendererResourceDelegate);
111 static const int kWaitForWorkersStatsTimeoutMS = 20;
113 class HeapStatisticsCollector {
114 public:
115 HeapStatisticsCollector() : round_id_(0) {}
117 void InitiateCollection();
118 static HeapStatisticsCollector* Instance();
120 private:
121 void CollectOnWorkerThread(scoped_refptr<base::TaskRunner> master,
122 int round_id);
123 void ReceiveStats(int round_id, size_t total_size, size_t used_size);
124 void SendStatsToBrowser(int round_id);
126 size_t total_bytes_;
127 size_t used_bytes_;
128 int workers_to_go_;
129 int round_id_;
132 HeapStatisticsCollector* HeapStatisticsCollector::Instance() {
133 CR_DEFINE_STATIC_LOCAL(HeapStatisticsCollector, instance, ());
134 return &instance;
137 void HeapStatisticsCollector::InitiateCollection() {
138 v8::HeapStatistics heap_stats;
139 v8::Isolate::GetCurrent()->GetHeapStatistics(&heap_stats);
140 total_bytes_ = heap_stats.total_heap_size();
141 used_bytes_ = heap_stats.used_heap_size();
142 base::Closure collect = base::Bind(
143 &HeapStatisticsCollector::CollectOnWorkerThread,
144 base::Unretained(this),
145 base::MessageLoopProxy::current(),
146 round_id_);
147 workers_to_go_ = RenderThread::Get()->PostTaskToAllWebWorkers(collect);
148 if (workers_to_go_) {
149 // The guard task to send out partial stats
150 // in case some workers are not responsive.
151 base::MessageLoopProxy::current()->PostDelayedTask(
152 FROM_HERE,
153 base::Bind(&HeapStatisticsCollector::SendStatsToBrowser,
154 base::Unretained(this),
155 round_id_),
156 base::TimeDelta::FromMilliseconds(kWaitForWorkersStatsTimeoutMS));
157 } else {
158 // No worker threads so just send out the main thread data right away.
159 SendStatsToBrowser(round_id_);
163 void HeapStatisticsCollector::CollectOnWorkerThread(
164 scoped_refptr<base::TaskRunner> master,
165 int round_id) {
167 size_t total_bytes = 0;
168 size_t used_bytes = 0;
169 v8::Isolate* isolate = v8::Isolate::GetCurrent();
170 if (isolate) {
171 v8::HeapStatistics heap_stats;
172 isolate->GetHeapStatistics(&heap_stats);
173 total_bytes = heap_stats.total_heap_size();
174 used_bytes = heap_stats.used_heap_size();
176 master->PostTask(
177 FROM_HERE,
178 base::Bind(&HeapStatisticsCollector::ReceiveStats,
179 base::Unretained(this),
180 round_id,
181 total_bytes,
182 used_bytes));
185 void HeapStatisticsCollector::ReceiveStats(int round_id,
186 size_t total_bytes,
187 size_t used_bytes) {
188 if (round_id != round_id_)
189 return;
190 total_bytes_ += total_bytes;
191 used_bytes_ += used_bytes;
192 if (!--workers_to_go_)
193 SendStatsToBrowser(round_id);
196 void HeapStatisticsCollector::SendStatsToBrowser(int round_id) {
197 if (round_id != round_id_)
198 return;
199 // TODO(alph): Do caching heap stats and use the cache if we haven't got
200 // reply from a worker.
201 // Currently a busy worker stats are not counted.
202 RenderThread::Get()->Send(new ChromeViewHostMsg_V8HeapStats(
203 total_bytes_, used_bytes_));
204 ++round_id_;
207 } // namespace
209 bool ChromeRenderProcessObserver::is_incognito_process_ = false;
211 ChromeRenderProcessObserver::ChromeRenderProcessObserver(
212 ChromeContentRendererClient* client)
213 : client_(client),
214 webkit_initialized_(false) {
215 const base::CommandLine& command_line =
216 *base::CommandLine::ForCurrentProcess();
218 #if defined(ENABLE_AUTOFILL_DIALOG)
219 WebRuntimeFeatures::enableRequestAutocomplete(true);
220 #endif
222 if (command_line.HasSwitch(switches::kDisableJavaScriptHarmonyShipping)) {
223 std::string flag("--noharmony-shipping");
224 v8::V8::SetFlagsFromString(flag.c_str(), static_cast<int>(flag.size()));
227 if (command_line.HasSwitch(switches::kJavaScriptHarmony)) {
228 std::string flag("--harmony");
229 v8::V8::SetFlagsFromString(flag.c_str(), static_cast<int>(flag.size()));
232 RenderThread* thread = RenderThread::Get();
233 resource_delegate_.reset(new RendererResourceDelegate());
234 thread->SetResourceDispatcherDelegate(resource_delegate_.get());
236 // Configure modules that need access to resources.
237 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider);
239 #if defined(OS_POSIX) && !defined(OS_MACOSX) && defined(USE_NSS)
240 // On platforms where we use system NSS shared libraries,
241 // initialize NSS now because it won't be able to load the .so's
242 // after we engage the sandbox.
243 if (!command_line.HasSwitch(switches::kSingleProcess))
244 crypto::InitNSSSafely();
245 #elif defined(OS_WIN)
246 // crypt32.dll is used to decode X509 certificates for Chromoting.
247 // Only load this library when the feature is enabled.
248 base::LoadNativeLibrary(base::FilePath(L"crypt32.dll"), NULL);
249 #endif
250 // Setup initial set of crash dump data for Field Trials in this renderer.
251 chrome_variations::SetChildProcessLoggingVariationList();
252 // Listen for field trial activations to report them to the browser.
253 base::FieldTrialList::AddObserver(this);
256 ChromeRenderProcessObserver::~ChromeRenderProcessObserver() {
259 bool ChromeRenderProcessObserver::OnControlMessageReceived(
260 const IPC::Message& message) {
261 bool handled = true;
262 IPC_BEGIN_MESSAGE_MAP(ChromeRenderProcessObserver, message)
263 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsIncognitoProcess,
264 OnSetIsIncognitoProcess)
265 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetFieldTrialGroup, OnSetFieldTrialGroup)
266 IPC_MESSAGE_HANDLER(ChromeViewMsg_GetV8HeapStats, OnGetV8HeapStats)
267 IPC_MESSAGE_HANDLER(ChromeViewMsg_GetCacheResourceStats,
268 OnGetCacheResourceStats)
269 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetContentSettingRules,
270 OnSetContentSettingRules)
271 IPC_MESSAGE_UNHANDLED(handled = false)
272 IPC_END_MESSAGE_MAP()
273 return handled;
276 void ChromeRenderProcessObserver::WebKitInitialized() {
277 webkit_initialized_ = true;
278 // chrome-native: is a scheme used for placeholder navigations that allow
279 // UIs to be drawn with platform native widgets instead of HTML. These pages
280 // should not be accessible, and should also be treated as empty documents
281 // that can commit synchronously. No code should be runnable in these pages,
282 // so it should not need to access anything nor should it allow javascript
283 // URLs since it should never be visible to the user.
284 WebString native_scheme(base::ASCIIToUTF16(chrome::kChromeNativeScheme));
285 WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(native_scheme);
286 WebSecurityPolicy::registerURLSchemeAsEmptyDocument(native_scheme);
287 WebSecurityPolicy::registerURLSchemeAsNoAccess(native_scheme);
288 WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs(
289 native_scheme);
292 void ChromeRenderProcessObserver::OnRenderProcessShutdown() {
293 webkit_initialized_ = false;
296 void ChromeRenderProcessObserver::OnSetIsIncognitoProcess(
297 bool is_incognito_process) {
298 is_incognito_process_ = is_incognito_process;
301 void ChromeRenderProcessObserver::OnSetContentSettingRules(
302 const RendererContentSettingRules& rules) {
303 content_setting_rules_ = rules;
306 void ChromeRenderProcessObserver::OnGetCacheResourceStats() {
307 WebCache::ResourceTypeStats stats;
308 if (webkit_initialized_)
309 WebCache::getResourceTypeStats(&stats);
310 RenderThread::Get()->Send(new ChromeViewHostMsg_ResourceTypeStats(stats));
313 void ChromeRenderProcessObserver::OnSetFieldTrialGroup(
314 const std::string& field_trial_name,
315 const std::string& group_name) {
316 base::FieldTrial* trial =
317 base::FieldTrialList::CreateFieldTrial(field_trial_name, group_name);
318 // TODO(mef): Remove this check after the investigation of 359406 is complete.
319 CHECK(trial) << field_trial_name << ":" << group_name;
320 // Ensure the trial is marked as "used" by calling group() on it if it is
321 // marked as activated.
322 trial->group();
323 chrome_variations::SetChildProcessLoggingVariationList();
326 void ChromeRenderProcessObserver::OnGetV8HeapStats() {
327 HeapStatisticsCollector::Instance()->InitiateCollection();
330 const RendererContentSettingRules*
331 ChromeRenderProcessObserver::content_setting_rules() const {
332 return &content_setting_rules_;
335 void ChromeRenderProcessObserver::OnFieldTrialGroupFinalized(
336 const std::string& trial_name,
337 const std::string& group_name) {
338 content::RenderThread::Get()->Send(
339 new ChromeViewHostMsg_FieldTrialActivated(trial_name));