| 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 thread->GetServiceRegistry()->AddService<ResourceUsageReporter>( |
| 227 base::Bind(CreateResourceUsageReporter)); |
| 228 |
| 234 // Configure modules that need access to resources. | 229 // Configure modules that need access to resources. |
| 235 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider); | 230 net::NetModule::SetResourceProvider(chrome_common_net::NetResourceProvider); |
| 236 | 231 |
| 237 #if defined(OS_POSIX) && !defined(OS_MACOSX) && defined(USE_NSS_CERTS) | 232 #if defined(OS_POSIX) && !defined(OS_MACOSX) && defined(USE_NSS_CERTS) |
| 238 // On platforms where we use system NSS shared libraries, | 233 // On platforms where we use system NSS shared libraries, |
| 239 // initialize NSS now because it won't be able to load the .so's | 234 // initialize NSS now because it won't be able to load the .so's |
| 240 // after we engage the sandbox. | 235 // after we engage the sandbox. |
| 241 if (!command_line.HasSwitch(switches::kSingleProcess)) | 236 if (!command_line.HasSwitch(switches::kSingleProcess)) |
| 242 crypto::InitNSSSafely(); | 237 crypto::InitNSSSafely(); |
| 243 #elif defined(OS_WIN) | 238 #elif defined(OS_WIN) |
| (...skipping 10 matching lines...) Expand all Loading... |
| 254 ChromeRenderProcessObserver::~ChromeRenderProcessObserver() { | 249 ChromeRenderProcessObserver::~ChromeRenderProcessObserver() { |
| 255 } | 250 } |
| 256 | 251 |
| 257 bool ChromeRenderProcessObserver::OnControlMessageReceived( | 252 bool ChromeRenderProcessObserver::OnControlMessageReceived( |
| 258 const IPC::Message& message) { | 253 const IPC::Message& message) { |
| 259 bool handled = true; | 254 bool handled = true; |
| 260 IPC_BEGIN_MESSAGE_MAP(ChromeRenderProcessObserver, message) | 255 IPC_BEGIN_MESSAGE_MAP(ChromeRenderProcessObserver, message) |
| 261 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsIncognitoProcess, | 256 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetIsIncognitoProcess, |
| 262 OnSetIsIncognitoProcess) | 257 OnSetIsIncognitoProcess) |
| 263 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetFieldTrialGroup, OnSetFieldTrialGroup) | 258 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetFieldTrialGroup, OnSetFieldTrialGroup) |
| 264 IPC_MESSAGE_HANDLER(ChromeViewMsg_GetV8HeapStats, OnGetV8HeapStats) | |
| 265 IPC_MESSAGE_HANDLER(ChromeViewMsg_GetCacheResourceStats, | 259 IPC_MESSAGE_HANDLER(ChromeViewMsg_GetCacheResourceStats, |
| 266 OnGetCacheResourceStats) | 260 OnGetCacheResourceStats) |
| 267 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetContentSettingRules, | 261 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetContentSettingRules, |
| 268 OnSetContentSettingRules) | 262 OnSetContentSettingRules) |
| 269 IPC_MESSAGE_UNHANDLED(handled = false) | 263 IPC_MESSAGE_UNHANDLED(handled = false) |
| 270 IPC_END_MESSAGE_MAP() | 264 IPC_END_MESSAGE_MAP() |
| 271 return handled; | 265 return handled; |
| 272 } | 266 } |
| 273 | 267 |
| 274 void ChromeRenderProcessObserver::WebKitInitialized() { | 268 void ChromeRenderProcessObserver::WebKitInitialized() { |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 314 base::FieldTrial* trial = | 308 base::FieldTrial* trial = |
| 315 base::FieldTrialList::CreateFieldTrial(field_trial_name, group_name); | 309 base::FieldTrialList::CreateFieldTrial(field_trial_name, group_name); |
| 316 // TODO(mef): Remove this check after the investigation of 359406 is complete. | 310 // TODO(mef): Remove this check after the investigation of 359406 is complete. |
| 317 CHECK(trial) << field_trial_name << ":" << group_name; | 311 CHECK(trial) << field_trial_name << ":" << group_name; |
| 318 // Ensure the trial is marked as "used" by calling group() on it if it is | 312 // Ensure the trial is marked as "used" by calling group() on it if it is |
| 319 // marked as activated. | 313 // marked as activated. |
| 320 trial->group(); | 314 trial->group(); |
| 321 chrome_variations::SetChildProcessLoggingVariationList(); | 315 chrome_variations::SetChildProcessLoggingVariationList(); |
| 322 } | 316 } |
| 323 | 317 |
| 324 void ChromeRenderProcessObserver::OnGetV8HeapStats() { | |
| 325 HeapStatisticsCollector::Instance()->InitiateCollection(); | |
| 326 } | |
| 327 | |
| 328 const RendererContentSettingRules* | 318 const RendererContentSettingRules* |
| 329 ChromeRenderProcessObserver::content_setting_rules() const { | 319 ChromeRenderProcessObserver::content_setting_rules() const { |
| 330 return &content_setting_rules_; | 320 return &content_setting_rules_; |
| 331 } | 321 } |
| 332 | 322 |
| 333 void ChromeRenderProcessObserver::OnFieldTrialGroupFinalized( | 323 void ChromeRenderProcessObserver::OnFieldTrialGroupFinalized( |
| 334 const std::string& trial_name, | 324 const std::string& trial_name, |
| 335 const std::string& group_name) { | 325 const std::string& group_name) { |
| 336 content::RenderThread::Get()->Send( | 326 content::RenderThread::Get()->Send( |
| 337 new ChromeViewHostMsg_FieldTrialActivated(trial_name)); | 327 new ChromeViewHostMsg_FieldTrialActivated(trial_name)); |
| 338 } | 328 } |
| OLD | NEW |