Return Windows error code when create-process fails.
[chromium-blink-merge.git] / chrome / renderer / chrome_render_process_observer.cc
blob407b6474338be94fb9d249b1a846630cd7f4742b
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/path_service.h"
20 #include "base/single_thread_task_runner.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/thread_task_runner_handle.h"
23 #include "base/threading/platform_thread.h"
24 #include "chrome/common/child_process_logging.h"
25 #include "chrome/common/chrome_paths.h"
26 #include "chrome/common/chrome_switches.h"
27 #include "chrome/common/net/net_resource_provider.h"
28 #include "chrome/common/render_messages.h"
29 #include "chrome/common/resource_usage_reporter.mojom.h"
30 #include "chrome/common/resource_usage_reporter_type_converters.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 ResourceUsageReporterImpl(
121 base::WeakPtr<ChromeRenderProcessObserver> observer,
122 mojo::InterfaceRequest<ResourceUsageReporter> req)
123 : binding_(this, req.Pass()), observer_(observer), weak_factory_(this) {}
124 ~ResourceUsageReporterImpl() override {}
126 private:
127 static void CollectOnWorkerThread(
128 const scoped_refptr<base::TaskRunner>& master,
129 base::WeakPtr<ResourceUsageReporterImpl> impl) {
130 size_t total_bytes = 0;
131 size_t used_bytes = 0;
132 v8::Isolate* isolate = v8::Isolate::GetCurrent();
133 if (isolate) {
134 v8::HeapStatistics heap_stats;
135 isolate->GetHeapStatistics(&heap_stats);
136 total_bytes = heap_stats.total_heap_size();
137 used_bytes = heap_stats.used_heap_size();
139 master->PostTask(FROM_HERE,
140 base::Bind(&ResourceUsageReporterImpl::ReceiveStats, impl,
141 total_bytes, used_bytes));
144 void ReceiveStats(size_t total_bytes, size_t used_bytes) {
145 usage_data_->v8_bytes_allocated += total_bytes;
146 usage_data_->v8_bytes_used += used_bytes;
147 workers_to_go_--;
148 if (!workers_to_go_)
149 SendResults();
152 void SendResults() {
153 if (!callback_.is_null())
154 callback_.Run(usage_data_.Pass());
155 callback_.reset();
156 weak_factory_.InvalidateWeakPtrs();
157 workers_to_go_ = 0;
160 void GetUsageData(
161 const mojo::Callback<void(ResourceUsageDataPtr)>& callback) override {
162 DCHECK(callback_.is_null());
163 weak_factory_.InvalidateWeakPtrs();
164 usage_data_ = ResourceUsageData::New();
165 usage_data_->reports_v8_stats = true;
166 callback_ = callback;
168 // Since it is not safe to call any Blink or V8 functions until Blink has
169 // been initialized (which also initializes V8), early out and send 0 back
170 // for all resources.
171 if (!observer_ || !observer_->webkit_initialized()) {
172 SendResults();
173 return;
176 WebCache::ResourceTypeStats stats;
177 WebCache::getResourceTypeStats(&stats);
178 usage_data_->web_cache_stats = ResourceTypeStats::From(stats);
180 v8::Isolate* isolate = v8::Isolate::GetCurrent();
181 if (isolate) {
182 v8::HeapStatistics heap_stats;
183 isolate->GetHeapStatistics(&heap_stats);
184 usage_data_->v8_bytes_allocated = heap_stats.total_heap_size();
185 usage_data_->v8_bytes_used = heap_stats.used_heap_size();
187 base::Closure collect = base::Bind(
188 &ResourceUsageReporterImpl::CollectOnWorkerThread,
189 base::ThreadTaskRunnerHandle::Get(), weak_factory_.GetWeakPtr());
190 workers_to_go_ = RenderThread::Get()->PostTaskToAllWebWorkers(collect);
191 if (workers_to_go_) {
192 // The guard task to send out partial stats
193 // in case some workers are not responsive.
194 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
195 FROM_HERE, base::Bind(&ResourceUsageReporterImpl::SendResults,
196 weak_factory_.GetWeakPtr()),
197 base::TimeDelta::FromMilliseconds(kWaitForWorkersStatsTimeoutMS));
198 } else {
199 // No worker threads so just send out the main thread data right away.
200 SendResults();
204 ResourceUsageDataPtr usage_data_;
205 mojo::Callback<void(ResourceUsageDataPtr)> callback_;
206 int workers_to_go_;
207 mojo::StrongBinding<ResourceUsageReporter> binding_;
208 base::WeakPtr<ChromeRenderProcessObserver> observer_;
210 base::WeakPtrFactory<ResourceUsageReporterImpl> weak_factory_;
213 void CreateResourceUsageReporter(
214 base::WeakPtr<ChromeRenderProcessObserver> observer,
215 mojo::InterfaceRequest<ResourceUsageReporter> request) {
216 new ResourceUsageReporterImpl(observer, request.Pass());
219 } // namespace
221 bool ChromeRenderProcessObserver::is_incognito_process_ = false;
223 ChromeRenderProcessObserver::ChromeRenderProcessObserver()
224 : webkit_initialized_(false), weak_factory_(this) {
225 const base::CommandLine& command_line =
226 *base::CommandLine::ForCurrentProcess();
228 #if defined(ENABLE_AUTOFILL_DIALOG)
229 WebRuntimeFeatures::enableRequestAutocomplete(true);
230 #endif
232 if (command_line.HasSwitch(switches::kDisableJavaScriptHarmonyShipping)) {
233 std::string flag("--noharmony-shipping");
234 v8::V8::SetFlagsFromString(flag.c_str(), static_cast<int>(flag.size()));
237 if (command_line.HasSwitch(switches::kJavaScriptHarmony)) {
238 std::string flag("--harmony");
239 v8::V8::SetFlagsFromString(flag.c_str(), static_cast<int>(flag.size()));
242 RenderThread* thread = RenderThread::Get();
243 resource_delegate_.reset(new RendererResourceDelegate());
244 thread->SetResourceDispatcherDelegate(resource_delegate_.get());
246 content::ServiceRegistry* service_registry = thread->GetServiceRegistry();
247 if (service_registry) {
248 service_registry->AddService<ResourceUsageReporter>(
249 base::Bind(CreateResourceUsageReporter, weak_factory_.GetWeakPtr()));
252 // Configure modules that need access to resources.
253 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider);
255 #if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(USE_OPENSSL)
256 // On platforms where we use system NSS shared libraries,
257 // initialize NSS now because it won't be able to load the .so's
258 // after we engage the sandbox.
259 if (!command_line.HasSwitch(switches::kSingleProcess))
260 crypto::InitNSSSafely();
261 #endif
262 // Setup initial set of crash dump data for Field Trials in this renderer.
263 chrome_variations::SetChildProcessLoggingVariationList();
264 // Listen for field trial activations to report them to the browser.
265 base::FieldTrialList::AddObserver(this);
268 ChromeRenderProcessObserver::~ChromeRenderProcessObserver() {
271 bool ChromeRenderProcessObserver::OnControlMessageReceived(
272 const IPC::Message& message) {
273 bool handled = true;
274 IPC_BEGIN_MESSAGE_MAP(ChromeRenderProcessObserver, message)
275 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsIncognitoProcess,
276 OnSetIsIncognitoProcess)
277 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetFieldTrialGroup, OnSetFieldTrialGroup)
278 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetContentSettingRules,
279 OnSetContentSettingRules)
280 IPC_MESSAGE_UNHANDLED(handled = false)
281 IPC_END_MESSAGE_MAP()
282 return handled;
285 void ChromeRenderProcessObserver::WebKitInitialized() {
286 webkit_initialized_ = true;
287 // chrome-native: is a scheme used for placeholder navigations that allow
288 // UIs to be drawn with platform native widgets instead of HTML. These pages
289 // should not be accessible, and should also be treated as empty documents
290 // that can commit synchronously. No code should be runnable in these pages,
291 // so it should not need to access anything nor should it allow javascript
292 // URLs since it should never be visible to the user.
293 WebString native_scheme(base::ASCIIToUTF16(chrome::kChromeNativeScheme));
294 WebSecurityPolicy::registerURLSchemeAsDisplayIsolated(native_scheme);
295 WebSecurityPolicy::registerURLSchemeAsEmptyDocument(native_scheme);
296 WebSecurityPolicy::registerURLSchemeAsNoAccess(native_scheme);
297 WebSecurityPolicy::registerURLSchemeAsNotAllowingJavascriptURLs(
298 native_scheme);
301 void ChromeRenderProcessObserver::OnRenderProcessShutdown() {
302 webkit_initialized_ = false;
305 void ChromeRenderProcessObserver::OnSetIsIncognitoProcess(
306 bool is_incognito_process) {
307 is_incognito_process_ = is_incognito_process;
310 void ChromeRenderProcessObserver::OnSetContentSettingRules(
311 const RendererContentSettingRules& rules) {
312 content_setting_rules_ = rules;
315 void ChromeRenderProcessObserver::OnSetFieldTrialGroup(
316 const std::string& field_trial_name,
317 const std::string& group_name) {
318 base::FieldTrial* trial =
319 base::FieldTrialList::CreateFieldTrial(field_trial_name, group_name);
320 // TODO(mef): Remove this check after the investigation of 359406 is complete.
321 CHECK(trial) << field_trial_name << ":" << group_name;
322 // Ensure the trial is marked as "used" by calling group() on it if it is
323 // marked as activated.
324 trial->group();
325 chrome_variations::SetChildProcessLoggingVariationList();
328 const RendererContentSettingRules*
329 ChromeRenderProcessObserver::content_setting_rules() const {
330 return &content_setting_rules_;
333 void ChromeRenderProcessObserver::OnFieldTrialGroupFinalized(
334 const std::string& trial_name,
335 const std::string& group_name) {
336 content::RenderThread::Get()->Send(
337 new ChromeViewHostMsg_FieldTrialActivated(trial_name));