OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/renderer/chrome_render_process_observer.h" | 5 #include "chrome/renderer/chrome_render_process_observer.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 #include <vector> | 8 #include <vector> |
9 | 9 |
10 #include "base/allocator/allocator_extension.h" | 10 #include "base/allocator/allocator_extension.h" |
11 #include "base/bind.h" | 11 #include "base/bind.h" |
12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
13 #include "base/files/file_util.h" | 13 #include "base/files/file_util.h" |
14 #include "base/memory/weak_ptr.h" | 14 #include "base/memory/weak_ptr.h" |
15 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
16 #include "base/metrics/field_trial.h" | 16 #include "base/metrics/field_trial.h" |
17 #include "base/metrics/histogram.h" | 17 #include "base/metrics/histogram.h" |
18 #include "base/metrics/statistics_recorder.h" | 18 #include "base/metrics/statistics_recorder.h" |
19 #include "base/native_library.h" | 19 #include "base/native_library.h" |
20 #include "base/path_service.h" | 20 #include "base/path_service.h" |
21 #include "base/strings/utf_string_conversions.h" | 21 #include "base/strings/utf_string_conversions.h" |
22 #include "base/threading/platform_thread.h" | 22 #include "base/threading/platform_thread.h" |
23 #include "chrome/common/child_process_logging.h" | 23 #include "chrome/common/child_process_logging.h" |
24 #include "chrome/common/chrome_paths.h" | 24 #include "chrome/common/chrome_paths.h" |
25 #include "chrome/common/chrome_switches.h" | 25 #include "chrome/common/chrome_switches.h" |
26 #include "chrome/common/net/net_resource_provider.h" | 26 #include "chrome/common/net/net_resource_provider.h" |
27 #include "chrome/common/render_messages.h" | 27 #include "chrome/common/render_messages.h" |
| 28 #include "chrome/common/resource_usage_reporter.mojom.h" |
28 #include "chrome/common/url_constants.h" | 29 #include "chrome/common/url_constants.h" |
29 #include "chrome/common/variations/variations_util.h" | 30 #include "chrome/common/variations/variations_util.h" |
30 #include "chrome/renderer/content_settings_observer.h" | 31 #include "chrome/renderer/content_settings_observer.h" |
31 #include "chrome/renderer/security_filter_peer.h" | 32 #include "chrome/renderer/security_filter_peer.h" |
32 #include "content/public/child/resource_dispatcher_delegate.h" | 33 #include "content/public/child/resource_dispatcher_delegate.h" |
| 34 #include "content/public/common/service_registry.h" |
33 #include "content/public/renderer/render_thread.h" | 35 #include "content/public/renderer/render_thread.h" |
34 #include "content/public/renderer/render_view.h" | 36 #include "content/public/renderer/render_view.h" |
35 #include "content/public/renderer/render_view_visitor.h" | 37 #include "content/public/renderer/render_view_visitor.h" |
36 #include "crypto/nss_util.h" | 38 #include "crypto/nss_util.h" |
37 #include "net/base/net_errors.h" | 39 #include "net/base/net_errors.h" |
38 #include "net/base/net_module.h" | 40 #include "net/base/net_module.h" |
| 41 #include "third_party/mojo/src/mojo/public/cpp/bindings/strong_binding.h" |
39 #include "third_party/WebKit/public/web/WebCache.h" | 42 #include "third_party/WebKit/public/web/WebCache.h" |
40 #include "third_party/WebKit/public/web/WebDocument.h" | 43 #include "third_party/WebKit/public/web/WebDocument.h" |
41 #include "third_party/WebKit/public/web/WebFrame.h" | 44 #include "third_party/WebKit/public/web/WebFrame.h" |
42 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h" | 45 #include "third_party/WebKit/public/web/WebRuntimeFeatures.h" |
43 #include "third_party/WebKit/public/web/WebSecurityPolicy.h" | 46 #include "third_party/WebKit/public/web/WebSecurityPolicy.h" |
44 #include "third_party/WebKit/public/web/WebView.h" | 47 #include "third_party/WebKit/public/web/WebView.h" |
45 | 48 |
46 #if defined(ENABLE_EXTENSIONS) | 49 #if defined(ENABLE_EXTENSIONS) |
47 #include "chrome/renderer/extensions/extension_localization_peer.h" | 50 #include "chrome/renderer/extensions/extension_localization_peer.h" |
48 #endif | 51 #endif |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
103 RenderThread::Get()->Send(new ChromeViewHostMsg_UpdatedCacheStats(stats)); | 106 RenderThread::Get()->Send(new ChromeViewHostMsg_UpdatedCacheStats(stats)); |
104 } | 107 } |
105 | 108 |
106 base::WeakPtrFactory<RendererResourceDelegate> weak_factory_; | 109 base::WeakPtrFactory<RendererResourceDelegate> weak_factory_; |
107 | 110 |
108 DISALLOW_COPY_AND_ASSIGN(RendererResourceDelegate); | 111 DISALLOW_COPY_AND_ASSIGN(RendererResourceDelegate); |
109 }; | 112 }; |
110 | 113 |
111 static const int kWaitForWorkersStatsTimeoutMS = 20; | 114 static const int kWaitForWorkersStatsTimeoutMS = 20; |
112 | 115 |
113 class HeapStatisticsCollector { | 116 class ResourceUsageReporterImpl : public ResourceUsageReporter { |
114 public: | 117 public: |
115 HeapStatisticsCollector() : round_id_(0) {} | 118 explicit ResourceUsageReporterImpl( |
116 | 119 mojo::InterfaceRequest<ResourceUsageReporter> req) |
117 void InitiateCollection(); | 120 : binding_(this, req.Pass()), weak_factory_(this) {} |
118 static HeapStatisticsCollector* Instance(); | 121 ~ResourceUsageReporterImpl() override {} |
119 | 122 |
120 private: | 123 private: |
121 void CollectOnWorkerThread(scoped_refptr<base::TaskRunner> master, | 124 static void CollectOnWorkerThread( |
122 int round_id); | 125 const scoped_refptr<base::TaskRunner>& master, |
123 void ReceiveStats(int round_id, size_t total_size, size_t used_size); | 126 base::WeakPtr<ResourceUsageReporterImpl> impl) { |
124 void SendStatsToBrowser(int round_id); | 127 size_t total_bytes = 0; |
| 128 size_t used_bytes = 0; |
| 129 v8::Isolate* isolate = v8::Isolate::GetCurrent(); |
| 130 if (isolate) { |
| 131 v8::HeapStatistics heap_stats; |
| 132 isolate->GetHeapStatistics(&heap_stats); |
| 133 total_bytes = heap_stats.total_heap_size(); |
| 134 used_bytes = heap_stats.used_heap_size(); |
| 135 } |
| 136 master->PostTask(FROM_HERE, |
| 137 base::Bind(&ResourceUsageReporterImpl::ReceiveStats, impl, |
| 138 total_bytes, used_bytes)); |
| 139 } |
125 | 140 |
126 size_t total_bytes_; | 141 void ReceiveStats(size_t total_bytes, size_t used_bytes) { |
127 size_t used_bytes_; | 142 usage_data_->v8_bytes_allocated += total_bytes; |
| 143 usage_data_->v8_bytes_used += used_bytes; |
| 144 workers_to_go_--; |
| 145 if (!workers_to_go_) |
| 146 SendResults(); |
| 147 } |
| 148 |
| 149 void SendResults() { |
| 150 if (!callback_.is_null()) |
| 151 callback_.Run(usage_data_.Pass()); |
| 152 callback_.reset(); |
| 153 weak_factory_.InvalidateWeakPtrs(); |
| 154 workers_to_go_ = 0; |
| 155 } |
| 156 |
| 157 void GetUsageData( |
| 158 const mojo::Callback<void(ResourceUsageDataPtr)>& callback) override { |
| 159 DCHECK(callback_.is_null()); |
| 160 weak_factory_.InvalidateWeakPtrs(); |
| 161 usage_data_ = ResourceUsageData::New(); |
| 162 usage_data_->reports_v8_stats = true; |
| 163 callback_ = callback; |
| 164 |
| 165 v8::HeapStatistics heap_stats; |
| 166 v8::Isolate::GetCurrent()->GetHeapStatistics(&heap_stats); |
| 167 usage_data_->v8_bytes_allocated = heap_stats.total_heap_size(); |
| 168 usage_data_->v8_bytes_used = heap_stats.used_heap_size(); |
| 169 base::Closure collect = base::Bind( |
| 170 &ResourceUsageReporterImpl::CollectOnWorkerThread, |
| 171 base::MessageLoopProxy::current(), weak_factory_.GetWeakPtr()); |
| 172 workers_to_go_ = RenderThread::Get()->PostTaskToAllWebWorkers(collect); |
| 173 if (workers_to_go_) { |
| 174 // The guard task to send out partial stats |
| 175 // in case some workers are not responsive. |
| 176 base::MessageLoopProxy::current()->PostDelayedTask( |
| 177 FROM_HERE, base::Bind(&ResourceUsageReporterImpl::SendResults, |
| 178 weak_factory_.GetWeakPtr()), |
| 179 base::TimeDelta::FromMilliseconds(kWaitForWorkersStatsTimeoutMS)); |
| 180 } else { |
| 181 // No worker threads so just send out the main thread data right away. |
| 182 SendResults(); |
| 183 } |
| 184 } |
| 185 |
| 186 ResourceUsageDataPtr usage_data_; |
| 187 mojo::Callback<void(ResourceUsageDataPtr)> callback_; |
128 int workers_to_go_; | 188 int workers_to_go_; |
129 int round_id_; | 189 mojo::StrongBinding<ResourceUsageReporter> binding_; |
| 190 |
| 191 base::WeakPtrFactory<ResourceUsageReporterImpl> weak_factory_; |
130 }; | 192 }; |
131 | 193 |
132 HeapStatisticsCollector* HeapStatisticsCollector::Instance() { | 194 void CreateResourceUsageReporter( |
133 CR_DEFINE_STATIC_LOCAL(HeapStatisticsCollector, instance, ()); | 195 mojo::InterfaceRequest<ResourceUsageReporter> request) { |
134 return &instance; | 196 new ResourceUsageReporterImpl(request.Pass()); |
135 } | |
136 | |
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_); | |
160 } | |
161 } | |
162 | |
163 void HeapStatisticsCollector::CollectOnWorkerThread( | |
164 scoped_refptr<base::TaskRunner> master, | |
165 int round_id) { | |
166 | |
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(); | |
175 } | |
176 master->PostTask( | |
177 FROM_HERE, | |
178 base::Bind(&HeapStatisticsCollector::ReceiveStats, | |
179 base::Unretained(this), | |
180 round_id, | |
181 total_bytes, | |
182 used_bytes)); | |
183 } | |
184 | |
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); | |
194 } | |
195 | |
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_; | |
205 } | 197 } |
206 | 198 |
207 } // namespace | 199 } // namespace |
208 | 200 |
209 bool ChromeRenderProcessObserver::is_incognito_process_ = false; | 201 bool ChromeRenderProcessObserver::is_incognito_process_ = false; |
210 | 202 |
211 ChromeRenderProcessObserver::ChromeRenderProcessObserver() | 203 ChromeRenderProcessObserver::ChromeRenderProcessObserver() |
212 : webkit_initialized_(false) { | 204 : webkit_initialized_(false) { |
213 const base::CommandLine& command_line = | 205 const base::CommandLine& command_line = |
214 *base::CommandLine::ForCurrentProcess(); | 206 *base::CommandLine::ForCurrentProcess(); |
215 | 207 |
216 #if defined(ENABLE_AUTOFILL_DIALOG) | 208 #if defined(ENABLE_AUTOFILL_DIALOG) |
217 WebRuntimeFeatures::enableRequestAutocomplete(true); | 209 WebRuntimeFeatures::enableRequestAutocomplete(true); |
218 #endif | 210 #endif |
219 | 211 |
220 if (command_line.HasSwitch(switches::kDisableJavaScriptHarmonyShipping)) { | 212 if (command_line.HasSwitch(switches::kDisableJavaScriptHarmonyShipping)) { |
221 std::string flag("--noharmony-shipping"); | 213 std::string flag("--noharmony-shipping"); |
222 v8::V8::SetFlagsFromString(flag.c_str(), static_cast<int>(flag.size())); | 214 v8::V8::SetFlagsFromString(flag.c_str(), static_cast<int>(flag.size())); |
223 } | 215 } |
224 | 216 |
225 if (command_line.HasSwitch(switches::kJavaScriptHarmony)) { | 217 if (command_line.HasSwitch(switches::kJavaScriptHarmony)) { |
226 std::string flag("--harmony"); | 218 std::string flag("--harmony"); |
227 v8::V8::SetFlagsFromString(flag.c_str(), static_cast<int>(flag.size())); | 219 v8::V8::SetFlagsFromString(flag.c_str(), static_cast<int>(flag.size())); |
228 } | 220 } |
229 | 221 |
230 RenderThread* thread = RenderThread::Get(); | 222 RenderThread* thread = RenderThread::Get(); |
231 resource_delegate_.reset(new RendererResourceDelegate()); | 223 resource_delegate_.reset(new RendererResourceDelegate()); |
232 thread->SetResourceDispatcherDelegate(resource_delegate_.get()); | 224 thread->SetResourceDispatcherDelegate(resource_delegate_.get()); |
233 | 225 |
| 226 content::ServiceRegistry* service_registry = thread->GetServiceRegistry(); |
| 227 if (service_registry) { |
| 228 service_registry->AddService<ResourceUsageReporter>( |
| 229 base::Bind(CreateResourceUsageReporter)); |
| 230 } |
| 231 |
234 // Configure modules that need access to resources. | 232 // Configure modules that need access to resources. |
235 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider); | 233 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider); |
236 | 234 |
237 #if defined(OS_POSIX) && !defined(OS_MACOSX) && defined(USE_NSS_CERTS) | 235 #if defined(OS_POSIX) && !defined(OS_MACOSX) && defined(USE_NSS_CERTS) |
238 // On platforms where we use system NSS shared libraries, | 236 // On platforms where we use system NSS shared libraries, |
239 // initialize NSS now because it won't be able to load the .so's | 237 // initialize NSS now because it won't be able to load the .so's |
240 // after we engage the sandbox. | 238 // after we engage the sandbox. |
241 if (!command_line.HasSwitch(switches::kSingleProcess)) | 239 if (!command_line.HasSwitch(switches::kSingleProcess)) |
242 crypto::InitNSSSafely(); | 240 crypto::InitNSSSafely(); |
243 #elif defined(OS_WIN) | 241 #elif defined(OS_WIN) |
(...skipping 10 matching lines...) Expand all Loading... |
254 ChromeRenderProcessObserver::~ChromeRenderProcessObserver() { | 252 ChromeRenderProcessObserver::~ChromeRenderProcessObserver() { |
255 } | 253 } |
256 | 254 |
257 bool ChromeRenderProcessObserver::OnControlMessageReceived( | 255 bool ChromeRenderProcessObserver::OnControlMessageReceived( |
258 const IPC::Message& message) { | 256 const IPC::Message& message) { |
259 bool handled = true; | 257 bool handled = true; |
260 IPC_BEGIN_MESSAGE_MAP(ChromeRenderProcessObserver, message) | 258 IPC_BEGIN_MESSAGE_MAP(ChromeRenderProcessObserver, message) |
261 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsIncognitoProcess, | 259 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsIncognitoProcess, |
262 OnSetIsIncognitoProcess) | 260 OnSetIsIncognitoProcess) |
263 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetFieldTrialGroup, OnSetFieldTrialGroup) | 261 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetFieldTrialGroup, OnSetFieldTrialGroup) |
264 IPC_MESSAGE_HANDLER(ChromeViewMsg_GetV8HeapStats, OnGetV8HeapStats) | |
265 IPC_MESSAGE_HANDLER(ChromeViewMsg_GetCacheResourceStats, | 262 IPC_MESSAGE_HANDLER(ChromeViewMsg_GetCacheResourceStats, |
266 OnGetCacheResourceStats) | 263 OnGetCacheResourceStats) |
267 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetContentSettingRules, | 264 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetContentSettingRules, |
268 OnSetContentSettingRules) | 265 OnSetContentSettingRules) |
269 IPC_MESSAGE_UNHANDLED(handled = false) | 266 IPC_MESSAGE_UNHANDLED(handled = false) |
270 IPC_END_MESSAGE_MAP() | 267 IPC_END_MESSAGE_MAP() |
271 return handled; | 268 return handled; |
272 } | 269 } |
273 | 270 |
274 void ChromeRenderProcessObserver::WebKitInitialized() { | 271 void ChromeRenderProcessObserver::WebKitInitialized() { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 base::FieldTrial* trial = | 311 base::FieldTrial* trial = |
315 base::FieldTrialList::CreateFieldTrial(field_trial_name, group_name); | 312 base::FieldTrialList::CreateFieldTrial(field_trial_name, group_name); |
316 // TODO(mef): Remove this check after the investigation of 359406 is complete. | 313 // TODO(mef): Remove this check after the investigation of 359406 is complete. |
317 CHECK(trial) << field_trial_name << ":" << group_name; | 314 CHECK(trial) << field_trial_name << ":" << group_name; |
318 // Ensure the trial is marked as "used" by calling group() on it if it is | 315 // Ensure the trial is marked as "used" by calling group() on it if it is |
319 // marked as activated. | 316 // marked as activated. |
320 trial->group(); | 317 trial->group(); |
321 chrome_variations::SetChildProcessLoggingVariationList(); | 318 chrome_variations::SetChildProcessLoggingVariationList(); |
322 } | 319 } |
323 | 320 |
324 void ChromeRenderProcessObserver::OnGetV8HeapStats() { | |
325 HeapStatisticsCollector::Instance()->InitiateCollection(); | |
326 } | |
327 | |
328 const RendererContentSettingRules* | 321 const RendererContentSettingRules* |
329 ChromeRenderProcessObserver::content_setting_rules() const { | 322 ChromeRenderProcessObserver::content_setting_rules() const { |
330 return &content_setting_rules_; | 323 return &content_setting_rules_; |
331 } | 324 } |
332 | 325 |
333 void ChromeRenderProcessObserver::OnFieldTrialGroupFinalized( | 326 void ChromeRenderProcessObserver::OnFieldTrialGroupFinalized( |
334 const std::string& trial_name, | 327 const std::string& trial_name, |
335 const std::string& group_name) { | 328 const std::string& group_name) { |
336 content::RenderThread::Get()->Send( | 329 content::RenderThread::Get()->Send( |
337 new ChromeViewHostMsg_FieldTrialActivated(trial_name)); | 330 new ChromeViewHostMsg_FieldTrialActivated(trial_name)); |
338 } | 331 } |
OLD | NEW |