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/browser/performance_monitor/performance_monitor.h" | 5 #include "chrome/browser/performance_monitor/performance_monitor.h" |
6 | 6 |
| 7 #include <set> |
| 8 |
7 #include "base/bind.h" | 9 #include "base/bind.h" |
8 #include "base/logging.h" | 10 #include "base/logging.h" |
9 #include "base/process_util.h" | 11 #include "base/process_util.h" |
| 12 #include "base/string_number_conversions.h" |
10 #include "base/threading/worker_pool.h" | 13 #include "base/threading/worker_pool.h" |
11 #include "base/time.h" | 14 #include "base/time.h" |
| 15 #include "chrome/browser/browser_process.h" |
12 #include "chrome/browser/browser_shutdown.h" | 16 #include "chrome/browser/browser_shutdown.h" |
13 #include "chrome/browser/performance_monitor/constants.h" | 17 #include "chrome/browser/performance_monitor/constants.h" |
14 #include "chrome/browser/performance_monitor/database.h" | 18 #include "chrome/browser/performance_monitor/database.h" |
15 #include "chrome/browser/performance_monitor/performance_monitor_util.h" | 19 #include "chrome/browser/performance_monitor/performance_monitor_util.h" |
| 20 #include "chrome/browser/profiles/profile.h" |
| 21 #include "chrome/browser/profiles/profile_manager.h" |
| 22 #include "chrome/browser/ui/browser.h" |
| 23 #include "chrome/browser/ui/browser_list.h" |
16 #include "chrome/browser/extensions/crx_installer.h" | 24 #include "chrome/browser/extensions/crx_installer.h" |
17 #include "chrome/common/chrome_notification_types.h" | 25 #include "chrome/common/chrome_notification_types.h" |
18 #include "chrome/common/chrome_version_info.h" | 26 #include "chrome/common/chrome_version_info.h" |
19 #include "chrome/common/extensions/extension.h" | 27 #include "chrome/common/extensions/extension.h" |
20 #include "chrome/common/extensions/extension_constants.h" | 28 #include "chrome/common/extensions/extension_constants.h" |
21 #include "content/public/browser/browser_thread.h" | 29 #include "content/public/browser/browser_thread.h" |
22 #include "content/public/browser/notification_service.h" | 30 #include "content/public/browser/notification_service.h" |
23 #include "content/public/browser/notification_types.h" | 31 #include "content/public/browser/notification_types.h" |
24 #include "content/public/browser/web_contents.h" | 32 #include "content/public/browser/web_contents.h" |
25 | 33 |
26 using extensions::Extension; | 34 using extensions::Extension; |
27 | 35 |
| 36 namespace { |
| 37 |
| 38 std::string TimeToString(base::Time time) { |
| 39 int64 time_int64 = time.ToInternalValue(); |
| 40 return base::Int64ToString(time_int64); |
| 41 } |
| 42 |
| 43 bool StringToTime(std::string time, base::Time* output) { |
| 44 int64 time_int64 = 0; |
| 45 if (!base::StringToInt64(time, &time_int64)) |
| 46 return false; |
| 47 *output = base::Time::FromInternalValue(time_int64); |
| 48 return true; |
| 49 } |
| 50 |
| 51 } // namespace |
| 52 |
28 namespace performance_monitor { | 53 namespace performance_monitor { |
29 | 54 |
30 PerformanceMonitor::PerformanceMonitor() : database_(NULL) { | 55 PerformanceMonitor::PerformanceMonitor() : database_(NULL) { |
31 } | 56 } |
32 | 57 |
33 PerformanceMonitor::~PerformanceMonitor() { | 58 PerformanceMonitor::~PerformanceMonitor() { |
34 } | 59 } |
35 | 60 |
36 void PerformanceMonitor::Start() { | 61 void PerformanceMonitor::Start() { |
| 62 std::string time = TimeToString(base::Time::Now()); |
37 content::BrowserThread::PostBlockingPoolTaskAndReply( | 63 content::BrowserThread::PostBlockingPoolTaskAndReply( |
38 FROM_HERE, | 64 FROM_HERE, |
39 base::Bind(&PerformanceMonitor::InitOnBackgroundThread, | 65 base::Bind(&PerformanceMonitor::InitOnBackgroundThread, |
40 base::Unretained(this)), | 66 base::Unretained(this)), |
41 base::Bind(&PerformanceMonitor::FinishInit, | 67 base::Bind(&PerformanceMonitor::FinishInit, |
42 base::Unretained(this))); | 68 base::Unretained(this))); |
43 } | 69 } |
44 | 70 |
45 void PerformanceMonitor::InitOnBackgroundThread() { | 71 void PerformanceMonitor::InitOnBackgroundThread() { |
46 DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 72 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
47 database_ = Database::Create(database_path_); | 73 database_ = Database::Create(database_path_); |
48 } | 74 } |
49 | 75 |
50 bool PerformanceMonitor::SetDatabasePath(const FilePath& path) { | 76 bool PerformanceMonitor::SetDatabasePath(const FilePath& path) { |
51 if (!database_.get()) { | 77 if (!database_.get()) { |
52 database_path_ = path; | 78 database_path_ = path; |
53 return true; | 79 return true; |
54 } | 80 } |
55 | 81 |
56 // PerformanceMonitor already initialized with another path. | 82 // PerformanceMonitor already initialized with another path. |
57 return false; | 83 return false; |
58 } | 84 } |
59 | 85 |
60 void PerformanceMonitor::FinishInit() { | 86 void PerformanceMonitor::FinishInit() { |
61 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 87 CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
62 RegisterForNotifications(); | 88 RegisterForNotifications(); |
| 89 CheckForUncleanExits(); |
63 CheckForVersionUpdate(); | 90 CheckForVersionUpdate(); |
| 91 |
| 92 timer_.Start(FROM_HERE, base::TimeDelta::FromMinutes(2), |
| 93 this, &PerformanceMonitor::DoTimedCollections); |
64 } | 94 } |
65 | 95 |
66 void PerformanceMonitor::RegisterForNotifications() { | 96 void PerformanceMonitor::RegisterForNotifications() { |
67 // Extensions | 97 // Extensions |
68 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, | 98 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_INSTALLED, |
69 content::NotificationService::AllSources()); | 99 content::NotificationService::AllSources()); |
70 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_ENABLED, | 100 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_ENABLED, |
71 content::NotificationService::AllSources()); | 101 content::NotificationService::AllSources()); |
72 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, | 102 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
73 content::NotificationService::AllSources()); | 103 content::NotificationService::AllSources()); |
74 registrar_.Add(this, chrome::NOTIFICATION_CRX_INSTALLER_DONE, | 104 registrar_.Add(this, chrome::NOTIFICATION_CRX_INSTALLER_DONE, |
75 content::NotificationService::AllSources()); | 105 content::NotificationService::AllSources()); |
76 | 106 |
77 // Crashes | 107 // Crashes |
78 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_HANG, | 108 registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_HANG, |
79 content::NotificationService::AllSources()); | 109 content::NotificationService::AllSources()); |
80 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, | 110 registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED, |
81 content::NotificationService::AllSources()); | 111 content::NotificationService::AllSources()); |
| 112 |
| 113 // Profiles (for unclean exit) |
| 114 registrar_.Add(this, chrome::NOTIFICATION_PROFILE_ADDED, |
| 115 content::NotificationService::AllSources()); |
82 } | 116 } |
83 | 117 |
84 // Static | 118 // Static |
85 PerformanceMonitor* PerformanceMonitor::GetInstance() { | 119 PerformanceMonitor* PerformanceMonitor::GetInstance() { |
86 return Singleton<PerformanceMonitor>::get(); | 120 return Singleton<PerformanceMonitor>::get(); |
87 } | 121 } |
88 | 122 |
89 void PerformanceMonitor::AddEvent(scoped_ptr<Event> event) { | 123 void PerformanceMonitor::AddEvent(scoped_ptr<Event> event) { |
90 content::BrowserThread::PostBlockingPoolSequencedTask( | 124 content::BrowserThread::PostBlockingPoolSequencedTask( |
91 Database::kDatabaseSequenceToken, | 125 Database::kDatabaseSequenceToken, |
92 FROM_HERE, | 126 FROM_HERE, |
93 base::Bind(&PerformanceMonitor::AddEventOnBackgroundThread, | 127 base::Bind(&PerformanceMonitor::AddEventOnBackgroundThread, |
94 base::Unretained(this), | 128 base::Unretained(this), |
95 base::Passed(event.Pass()))); | 129 base::Passed(event.Pass()))); |
96 } | 130 } |
97 | 131 |
98 void PerformanceMonitor::AddEventOnBackgroundThread(scoped_ptr<Event> event) { | 132 void PerformanceMonitor::AddEventOnBackgroundThread(scoped_ptr<Event> event) { |
99 database_->AddEvent(*event.get()); | 133 database_->AddEvent(*event.get()); |
100 } | 134 } |
101 | 135 |
102 void PerformanceMonitor::GetStateValueOnBackgroundThread( | 136 void PerformanceMonitor::GetStateValueOnBackgroundThread( |
103 const std::string& key, | 137 const std::string& key, |
104 const StateValueCallback& callback) { | 138 const StateValueCallback& callback) { |
105 DCHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 139 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
106 std::string state_value = database_->GetStateValue(key); | 140 std::string state_value = database_->GetStateValue(key); |
107 | 141 |
108 callback.Run(state_value); | 142 callback.Run(state_value); |
109 } | 143 } |
110 | 144 |
111 void PerformanceMonitor::CheckForVersionUpdate() { | 145 void PerformanceMonitor::CheckForVersionUpdate() { |
112 StateValueCallback callback = | 146 StateValueCallback callback = |
113 base::Bind(&PerformanceMonitor::CheckForVersionUpdateHelper, | 147 base::Bind(&PerformanceMonitor::CheckForVersionUpdateHelper, |
114 base::Unretained(this)); | 148 base::Unretained(this)); |
115 | 149 |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 current_version)); | 181 current_version)); |
148 if (!previous_version.empty()) { | 182 if (!previous_version.empty()) { |
149 AddEvent(util::CreateChromeUpdateEvent( | 183 AddEvent(util::CreateChromeUpdateEvent( |
150 base::Time::Now(), | 184 base::Time::Now(), |
151 previous_version, | 185 previous_version, |
152 current_version)); | 186 current_version)); |
153 } | 187 } |
154 } | 188 } |
155 } | 189 } |
156 | 190 |
| 191 // We check if profiles exited cleanly initialization time in case they were |
| 192 // loaded prior to PerformanceMonitor's initialization. Later profiles will be |
| 193 // checked through the PROFILE_ADDED notification. |
| 194 void PerformanceMonitor::CheckForUncleanExits() { |
| 195 std::vector<Profile*> profiles = |
| 196 g_browser_process->profile_manager()->GetLoadedProfiles(); |
| 197 |
| 198 for (std::vector<Profile*>::const_iterator iter = profiles.begin(); |
| 199 iter != profiles.end(); ++iter) { |
| 200 if (!(*iter)->DidLastSessionExitCleanly()) { |
| 201 content::BrowserThread::PostBlockingPoolSequencedTask( |
| 202 Database::kDatabaseSequenceToken, |
| 203 FROM_HERE, |
| 204 base::Bind(&PerformanceMonitor::AddUncleanExitEvent, |
| 205 base::Unretained(this), |
| 206 (*iter)->GetDebugName())); |
| 207 } |
| 208 } |
| 209 } |
| 210 |
| 211 void PerformanceMonitor::AddUncleanExitEvent(std::string profile_name) { |
| 212 std::string database_key = kStateProfilePrefix + profile_name; |
| 213 std::string last_active_string = database_->GetStateValue(database_key); |
| 214 |
| 215 // Check if there was no previous time; this should only happen if the profile |
| 216 // was last used prior to PerformanceMonitor's integration. Do nothing in this |
| 217 // case, since the event was prior to the beginning of our recording. |
| 218 if (last_active_string.empty()) |
| 219 return; |
| 220 |
| 221 base::Time last_active_time; |
| 222 CHECK(StringToTime(last_active_string, &last_active_time)); |
| 223 |
| 224 scoped_ptr<Event> event = |
| 225 util::CreateUncleanExitEvent(last_active_time, profile_name); |
| 226 |
| 227 database_->AddEvent(*event.get()); |
| 228 } |
| 229 |
| 230 void PerformanceMonitor::UpdateLiveProfiles() { |
| 231 std::string time = TimeToString(base::Time::Now()); |
| 232 scoped_ptr<std::set<std::string> > active_profiles( |
| 233 new std::set<std::string>()); |
| 234 |
| 235 for (BrowserList::const_iterator iter = BrowserList::begin(); |
| 236 iter != BrowserList::end(); ++iter) { |
| 237 active_profiles->insert((*iter)->profile()->GetDebugName()); |
| 238 } |
| 239 |
| 240 content::BrowserThread::PostBlockingPoolSequencedTask( |
| 241 Database::kDatabaseSequenceToken, |
| 242 FROM_HERE, |
| 243 base::Bind(&PerformanceMonitor::UpdateLiveProfilesHelper, |
| 244 base::Unretained(this), |
| 245 base::Passed(active_profiles.Pass()), |
| 246 time)); |
| 247 } |
| 248 |
| 249 void PerformanceMonitor::UpdateLiveProfilesHelper( |
| 250 scoped_ptr<std::set<std::string> > active_profiles, |
| 251 std::string time) { |
| 252 CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); |
| 253 |
| 254 for (std::set<std::string>::const_iterator iter = active_profiles->begin(); |
| 255 iter != active_profiles->end(); ++iter) { |
| 256 database_->AddStateValue(kStateProfilePrefix + *iter, time); |
| 257 } |
| 258 } |
| 259 |
| 260 void PerformanceMonitor::DoTimedCollections() { |
| 261 UpdateLiveProfiles(); |
| 262 } |
| 263 |
157 void PerformanceMonitor::Observe(int type, | 264 void PerformanceMonitor::Observe(int type, |
158 const content::NotificationSource& source, | 265 const content::NotificationSource& source, |
159 const content::NotificationDetails& details) { | 266 const content::NotificationDetails& details) { |
160 switch (type) { | 267 switch (type) { |
161 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { | 268 case chrome::NOTIFICATION_EXTENSION_INSTALLED: { |
162 const Extension* extension = content::Details<Extension>(details).ptr(); | 269 const Extension* extension = content::Details<Extension>(details).ptr(); |
163 AddEvent(util::CreateExtensionInstallEvent(base::Time::Now(), | 270 AddEvent(util::CreateExtensionInstallEvent(base::Time::Now(), |
164 extension->id(), | 271 extension->id(), |
165 extension->name(), | 272 extension->name(), |
166 extension->url().spec(), | 273 extension->url().spec(), |
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
233 // Determine the type of crash. | 340 // Determine the type of crash. |
234 EventType type = | 341 EventType type = |
235 status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ? | 342 status == base::TERMINATION_STATUS_PROCESS_WAS_KILLED ? |
236 EVENT_KILLED_BY_OS_CRASH : EVENT_RENDERER_CRASH; | 343 EVENT_KILLED_BY_OS_CRASH : EVENT_RENDERER_CRASH; |
237 | 344 |
238 AddEvent(util::CreateCrashEvent(base::Time::Now(), | 345 AddEvent(util::CreateCrashEvent(base::Time::Now(), |
239 type, | 346 type, |
240 contents->GetURL().spec())); | 347 contents->GetURL().spec())); |
241 break; | 348 break; |
242 } | 349 } |
| 350 case chrome::NOTIFICATION_PROFILE_ADDED: { |
| 351 Profile* profile = content::Source<Profile>(source).ptr(); |
| 352 if (!profile->DidLastSessionExitCleanly()) { |
| 353 content::BrowserThread::PostBlockingPoolSequencedTask( |
| 354 Database::kDatabaseSequenceToken, |
| 355 FROM_HERE, |
| 356 base::Bind(&PerformanceMonitor::AddUncleanExitEvent, |
| 357 base::Unretained(this), |
| 358 profile->GetDebugName())); |
| 359 } |
| 360 break; |
| 361 } |
243 default: { | 362 default: { |
244 NOTREACHED(); | 363 NOTREACHED(); |
245 break; | 364 break; |
246 } | 365 } |
247 } | 366 } |
248 } | 367 } |
249 | 368 |
250 } // namespace performance_monitor | 369 } // namespace performance_monitor |
OLD | NEW |