Roll ANGLE e754fb8..6ffeb74
[chromium-blink-merge.git] / chrome / renderer / chrome_render_process_observer.cc
blob2d2edce587d6ec735821d8dc3216c7a60dccdc72
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/location.h"
15 #include "base/memory/weak_ptr.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/single_thread_task_runner.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "base/thread_task_runner_handle.h"
24 #include "base/threading/platform_thread.h"
25 #include "chrome/common/child_process_logging.h"
26 #include "chrome/common/chrome_paths.h"
27 #include "chrome/common/chrome_switches.h"
28 #include "chrome/common/net/net_resource_provider.h"
29 #include "chrome/common/render_messages.h"
30 #include "chrome/common/resource_usage_reporter.mojom.h"
31 #include "chrome/common/url_constants.h"
32 #include "chrome/common/variations/variations_util.h"
33 #include "chrome/renderer/content_settings_observer.h"
34 #include "chrome/renderer/security_filter_peer.h"
35 #include "content/public/child/resource_dispatcher_delegate.h"
36 #include "content/public/common/service_registry.h"
37 #include "content/public/renderer/render_thread.h"
38 #include "content/public/renderer/render_view.h"
39 #include "content/public/renderer/render_view_visitor.h"
40 #include "crypto/nss_util.h"
41 #include "net/base/net_errors.h"
42 #include "net/base/net_module.h"
43 #include "third_party/WebKit/public/web/WebCache.h"
44 #include "third_party/WebKit/public/web/WebDocument.h"
45 #include "third_party/WebKit/public/web/WebFrame.h"
46 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h"
47 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
48 #include "third_party/WebKit/public/web/WebView.h"
49 #include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h"
51 #if defined(ENABLE_EXTENSIONS)
52 #include "chrome/renderer/extensions/extension_localization_peer.h"
53 #endif
55 using blink::WebCache;
56 using blink::WebRuntimeFeatures;
57 using blink::WebSecurityPolicy;
58 using blink::WebString;
59 using content::RenderThread;
61 namespace {
63 const int kCacheStatsDelayMS = 2000;
65 class RendererResourceDelegate : public content::ResourceDispatcherDelegate {
66 public:
67 RendererResourceDelegate()
68 : weak_factory_(this) {
71 content::RequestPeer* OnRequestComplete(content::RequestPeer* current_peer,
72 content::ResourceType resource_type,
73 int error_code) override {
74 // Update the browser about our cache.
75 // Rate limit informing the host of our cache stats.
76 if (!weak_factory_.HasWeakPtrs()) {
77 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
78 FROM_HERE,
79 base::Bind(&RendererResourceDelegate::InformHostOfCacheStats,
80 weak_factory_.GetWeakPtr()),
81 base::TimeDelta::FromMilliseconds(kCacheStatsDelayMS));
84 if (error_code == net::ERR_ABORTED) {
85 return NULL;
88 // Resource canceled with a specific error are filtered.
89 return SecurityFilterPeer::CreateSecurityFilterPeerForDeniedRequest(
90 resource_type, current_peer, error_code);
93 content::RequestPeer* OnReceivedResponse(content::RequestPeer* current_peer,
94 const std::string& mime_type,
95 const GURL& url) override {
96 #if defined(ENABLE_EXTENSIONS)
97 return ExtensionLocalizationPeer::CreateExtensionLocalizationPeer(
98 current_peer, RenderThread::Get(), mime_type, url);
99 #else
100 return NULL;
101 #endif
104 private:
105 void InformHostOfCacheStats() {
106 WebCache::UsageStats stats;
107 WebCache::getUsageStats(&stats);
108 RenderThread::Get()->Send(new ChromeViewHostMsg_UpdatedCacheStats(stats));
111 base::WeakPtrFactory<RendererResourceDelegate> weak_factory_;
113 DISALLOW_COPY_AND_ASSIGN(RendererResourceDelegate);
116 static const int kWaitForWorkersStatsTimeoutMS = 20;
118 class ResourceUsageReporterImpl : public ResourceUsageReporter {
119 public:
120 explicit ResourceUsageReporterImpl(
121 mojo::InterfaceRequest<ResourceUsageReporter> req)
122 : binding_(this, req.Pass()), weak_factory_(this) {}
123 ~ResourceUsageReporterImpl() override {}
125 private:
126 static void CollectOnWorkerThread(
127 const scoped_refptr<base::TaskRunner>& master,
128 base::WeakPtr<ResourceUsageReporterImpl> impl) {
129 size_t total_bytes = 0;
130 size_t used_bytes = 0;
131 v8::Isolate* isolate = v8::Isolate::GetCurrent();
132 if (isolate) {
133 v8::HeapStatistics heap_stats;
134 isolate->GetHeapStatistics(&heap_stats);
135 total_bytes = heap_stats.total_heap_size();
136 used_bytes = heap_stats.used_heap_size();
138 master->PostTask(FROM_HERE,
139 base::Bind(&ResourceUsageReporterImpl::ReceiveStats, impl,
140 total_bytes, used_bytes));
143 void ReceiveStats(size_t total_bytes, size_t used_bytes) {
144 usage_data_->v8_bytes_allocated += total_bytes;
145 usage_data_->v8_bytes_used += used_bytes;
146 workers_to_go_--;
147 if (!workers_to_go_)
148 SendResults();
151 void SendResults() {
152 if (!callback_.is_null())
153 callback_.Run(usage_data_.Pass());
154 callback_.reset();
155 weak_factory_.InvalidateWeakPtrs();
156 workers_to_go_ = 0;
159 void GetUsageData(
160 const mojo::Callback<void(ResourceUsageDataPtr)>& callback) override {
161 DCHECK(callback_.is_null());
162 weak_factory_.InvalidateWeakPtrs();
163 usage_data_ = ResourceUsageData::New();
164 usage_data_->reports_v8_stats = true;
165 callback_ = callback;
167 v8::HeapStatistics heap_stats;
168 v8::Isolate::GetCurrent()->GetHeapStatistics(&heap_stats);
169 usage_data_->v8_bytes_allocated = heap_stats.total_heap_size();
170 usage_data_->v8_bytes_used = heap_stats.used_heap_size();
171 base::Closure collect = base::Bind(
172 &ResourceUsageReporterImpl::CollectOnWorkerThread,
173 base::ThreadTaskRunnerHandle::Get(), weak_factory_.GetWeakPtr());
174 workers_to_go_ = RenderThread::Get()->PostTaskToAllWebWorkers(collect);
175 if (workers_to_go_) {
176 // The guard task to send out partial stats
177 // in case some workers are not responsive.
178 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
179 FROM_HERE, base::Bind(&ResourceUsageReporterImpl::SendResults,
180 weak_factory_.GetWeakPtr()),
181 base::TimeDelta::FromMilliseconds(kWaitForWorkersStatsTimeoutMS));
182 } else {
183 // No worker threads so just send out the main thread data right away.
184 SendResults();
188 ResourceUsageDataPtr usage_data_;
189 mojo::Callback<void(ResourceUsageDataPtr)> callback_;
190 int workers_to_go_;
191 mojo::StrongBinding<ResourceUsageReporter> binding_;
193 base::WeakPtrFactory<ResourceUsageReporterImpl> weak_factory_;
196 void CreateResourceUsageReporter(
197 mojo::InterfaceRequest<ResourceUsageReporter> request) {
198 new ResourceUsageReporterImpl(request.Pass());
201 } // namespace
203 bool ChromeRenderProcessObserver::is_incognito_process_ = false;
205 ChromeRenderProcessObserver::ChromeRenderProcessObserver()
206 : webkit_initialized_(false) {
207 const base::CommandLine& command_line =
208 *base::CommandLine::ForCurrentProcess();
210 #if defined(ENABLE_AUTOFILL_DIALOG)
211 WebRuntimeFeatures::enableRequestAutocomplete(true);
212 #endif
214 if (command_line.HasSwitch(switches::kDisableJavaScriptHarmonyShipping)) {
215 std::string flag("--noharmony-shipping");
216 v8::V8::SetFlagsFromString(flag.c_str(), static_cast<int>(flag.size()));
219 if (command_line.HasSwitch(switches::kJavaScriptHarmony)) {
220 std::string flag("--harmony");
221 v8::V8::SetFlagsFromString(flag.c_str(), static_cast<int>(flag.size()));
224 RenderThread* thread = RenderThread::Get();
225 resource_delegate_.reset(new RendererResourceDelegate());
226 thread->SetResourceDispatcherDelegate(resource_delegate_.get());
228 content::ServiceRegistry* service_registry = thread->GetServiceRegistry();
229 if (service_registry) {
230 service_registry->AddService<ResourceUsageReporter>(
231 base::Bind(CreateResourceUsageReporter));
234 // Configure modules that need access to resources.
235 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider);
237 #if defined(OS_POSIX) && !defined(OS_MACOSX) && defined(USE_NSS_CERTS)
238 // On platforms where we use system NSS shared libraries,
239 // initialize NSS now because it won't be able to load the .so's
240 // after we engage the sandbox.
241 if (!command_line.HasSwitch(switches::kSingleProcess))
242 crypto::InitNSSSafely();
243 #elif defined(OS_WIN)
244 // crypt32.dll is used to decode X509 certificates for Chromoting.
245 // Only load this library when the feature is enabled.
246 base::LoadNativeLibrary(base::FilePath(L"crypt32.dll"), NULL);
247 #endif
248 // Setup initial set of crash dump data for Field Trials in this renderer.
249 chrome_variations::SetChildProcessLoggingVariationList();
250 // Listen for field trial activations to report them to the browser.
251 base::FieldTrialList::AddObserver(this);
254 ChromeRenderProcessObserver::~ChromeRenderProcessObserver() {
257 bool ChromeRenderProcessObserver::OnControlMessageReceived(
258 const IPC::Message& message) {
259 bool handled = true;
260 IPC_BEGIN_MESSAGE_MAP(ChromeRenderProcessObserver, message)
261 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsIncognitoProcess,
262 OnSetIsIncognitoProcess)
263 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetFieldTrialGroup, OnSetFieldTrialGroup)
264 IPC_MESSAGE_HANDLER(ChromeViewMsg_GetCacheResourceStats,
265 OnGetCacheResourceStats)
266 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetContentSettingRules,
267 OnSetContentSettingRules)
268 IPC_MESSAGE_UNHANDLED(handled = false)
269 IPC_END_MESSAGE_MAP()
270 return handled;
273 void ChromeRenderProcessObserver::WebKitInitialized() {
274 webkit_initialized_ = true;
275 // chrome-native: is a scheme used for placeholder navigations that allow
276 // UIs to be drawn with platform native widgets instead of HTML. These pages
277 // should not be accessible, and should also be treated as empty documents
278 // that can commit synchronously. No code should be runnable in these pages,
279 // so it should not need to access anything nor should it allow javascript
280 // URLs since it should never be visible to the user.
281 WebString native_scheme(base::ASCIIToUTF16(chrome::kChromeNativeScheme));
282 WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(native_scheme);
283 WebSecurityPolicy::registerURLSchemeAsEmptyDocument(native_scheme);
284 WebSecurityPolicy::registerURLSchemeAsNoAccess(native_scheme);
285 WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs(
286 native_scheme);
289 void ChromeRenderProcessObserver::OnRenderProcessShutdown() {
290 webkit_initialized_ = false;
293 void ChromeRenderProcessObserver::OnSetIsIncognitoProcess(
294 bool is_incognito_process) {
295 is_incognito_process_ = is_incognito_process;
298 void ChromeRenderProcessObserver::OnSetContentSettingRules(
299 const RendererContentSettingRules& rules) {
300 content_setting_rules_ = rules;
303 void ChromeRenderProcessObserver::OnGetCacheResourceStats() {
304 WebCache::ResourceTypeStats stats;
305 if (webkit_initialized_)
306 WebCache::getResourceTypeStats(&stats);
307 RenderThread::Get()->Send(new ChromeViewHostMsg_ResourceTypeStats(stats));
310 void ChromeRenderProcessObserver::OnSetFieldTrialGroup(
311 const std::string& field_trial_name,
312 const std::string& group_name) {
313 base::FieldTrial* trial =
314 base::FieldTrialList::CreateFieldTrial(field_trial_name, group_name);
315 // TODO(mef): Remove this check after the investigation of 359406 is complete.
316 CHECK(trial) << field_trial_name << ":" << group_name;
317 // Ensure the trial is marked as "used" by calling group() on it if it is
318 // marked as activated.
319 trial->group();
320 chrome_variations::SetChildProcessLoggingVariationList();
323 const RendererContentSettingRules*
324 ChromeRenderProcessObserver::content_setting_rules() const {
325 return &content_setting_rules_;
328 void ChromeRenderProcessObserver::OnFieldTrialGroupFinalized(
329 const std::string& trial_name,
330 const std::string& group_name) {
331 content::RenderThread::Get()->Send(
332 new ChromeViewHostMsg_FieldTrialActivated(trial_name));