Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2451)

Unified Diff: chrome/browser/performance_monitor/performance_monitor.cc

Issue 10703078: Add Unclean Exit Watching to CPM (Closed) Base URL: http://git.chromium.org/chromium/src.git@dc_crash_event_watching
Patch Set: Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/performance_monitor/performance_monitor.cc
diff --git a/chrome/browser/performance_monitor/performance_monitor.cc b/chrome/browser/performance_monitor/performance_monitor.cc
index 833fcd4f475f263fb3141a759cb579d690b411c3..85a91e51110739b5d9a31b626095f2a69541571e 100644
--- a/chrome/browser/performance_monitor/performance_monitor.cc
+++ b/chrome/browser/performance_monitor/performance_monitor.cc
@@ -4,15 +4,23 @@
#include "chrome/browser/performance_monitor/performance_monitor.h"
+#include <set>
+
#include "base/bind.h"
#include "base/logging.h"
#include "base/process_util.h"
+#include "base/string_number_conversions.h"
#include "base/threading/worker_pool.h"
#include "base/time.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/performance_monitor/constants.h"
#include "chrome/browser/performance_monitor/database.h"
#include "chrome/browser/performance_monitor/performance_monitor_util.h"
+#include "chrome/browser/profiles/profile.h"
+#include "chrome/browser/profiles/profile_manager.h"
+#include "chrome/browser/ui/browser.h"
+#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/extensions/crx_installer.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_version_info.h"
@@ -25,6 +33,24 @@
using extensions::Extension;
+namespace {
+
+bool TimeToString(base::Time time, std::string* output) {
Yoyo Zhou 2012/07/10 02:35:06 It doesn't make sense that conversion in this dire
Devlin 2012/07/10 17:18:32 Done.
+ int64 time_int64 = time.ToInternalValue();
+ *output = base::Int64ToString(time_int64);
+ return !output->empty();
+}
+
+bool StringToTime(std::string time, base::Time* output) {
+ int64 time_int64 = 0;
+ if (!base::StringToInt64(time, &time_int64))
+ return false;
+ *output = base::Time::FromInternalValue(time_int64);
+ return true;
+}
+
+} // namespace
+
namespace performance_monitor {
PerformanceMonitor::PerformanceMonitor() : database_(NULL) {
@@ -34,6 +60,8 @@ PerformanceMonitor::~PerformanceMonitor() {
}
void PerformanceMonitor::Start() {
+ std::string time;
+ CHECK(TimeToString(base::Time::Now(), &time));
content::BrowserThread::PostBlockingPoolTaskAndReply(
FROM_HERE,
base::Bind(&PerformanceMonitor::InitOnBackgroundThread,
@@ -60,7 +88,11 @@ bool PerformanceMonitor::SetDatabasePath(const FilePath& path) {
void PerformanceMonitor::FinishInit() {
CHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
RegisterForNotifications();
+ CheckForUncleanExit();
CheckForVersionUpdate();
+
+ timer_.Start(FROM_HERE, base::TimeDelta::FromMinutes(2),
+ this, &PerformanceMonitor::DoTimedCollections);
}
void PerformanceMonitor::RegisterForNotifications() {
@@ -79,6 +111,10 @@ void PerformanceMonitor::RegisterForNotifications() {
content::NotificationService::AllSources());
registrar_.Add(this, content::NOTIFICATION_WEB_CONTENTS_DISCONNECTED,
content::NotificationService::AllSources());
+
+ // Profiles (for unclean exit)
+ registrar_.Add(this, chrome::NOTIFICATION_PROFILE_ADDED,
+ content::NotificationService::AllSources());
}
// Static
@@ -153,6 +189,86 @@ void PerformanceMonitor::CheckForVersionUpdateHelper(
}
}
+// The reason we need this as well as a notification check is because the first
+// profiles can be loaded prior to the initialization of PerformanceMonitor. In
+// this case, we find if they exited uncleanly here.
Yoyo Zhou 2012/07/10 02:35:06 This comment is written backwards. I'd say "At ini
Devlin 2012/07/10 17:18:32 Done.
+void PerformanceMonitor::CheckForUncleanExit() {
Yoyo Zhou 2012/07/10 02:35:06 CheckForUncleanExits
Devlin 2012/07/10 17:18:32 Done.
+ std::vector<Profile*> profiles =
+ g_browser_process->profile_manager()->GetLoadedProfiles();
+
+ for (std::vector<Profile*>::const_iterator iter = profiles.begin();
+ iter != profiles.end(); ++iter) {
+ if (!(*iter)->DidLastSessionExitCleanly()) {
+ content::BrowserThread::PostBlockingPoolSequencedTask(
+ Database::kDatabaseSequenceToken,
+ FROM_HERE,
+ base::Bind(&PerformanceMonitor::AddUncleanExitEvent,
+ base::Unretained(this),
+ (*iter)->GetDebugName()));
+ }
+ }
+}
+
+void PerformanceMonitor::AddUncleanExitEvent(std::string profile_name) {
+ std::string database_key = kStateProfile + profile_name;
+ std::string last_active_string = database_->GetStateValue(database_key);
+
+ // Check if there was no previous time; this should only happen if the profile
+ // was last used prior to PerformanceMonitor's integration. Do nothing in this
+ // case, since the event was prior to the beginning of our recording.
+ if (last_active_string.empty())
+ return;
+
+ base::Time last_active_time;
+ CHECK(StringToTime(last_active_string, &last_active_time));
+
+ // We should never find a case where the last active time for the profile is
+ // after the current time. DCHECK (instead of CHECK) because of the chance
+ // that someone has backdated the system time, so that Chrome won't crash in
Yoyo Zhou 2012/07/10 02:35:06 This seems like a case that could actually happen,
Devlin 2012/07/10 17:18:32 Yeah, I wasn't sure about this one...it won't brea
+ // a release build.
+ DCHECK(last_active_time < base::Time::Now());
+
+ scoped_ptr<Event> event =
+ util::CreateUncleanExitEvent(last_active_time, profile_name);
+
+ database_->AddEvent(*event.get());
+}
+
+void PerformanceMonitor::UpdateLiveProfiles() {
+ std::string time;
+ CHECK(TimeToString(base::Time::Now(), &time));
+ scoped_ptr<std::set<std::string> > active_profiles(
+ new std::set<std::string>());
+
+ for (BrowserList::const_iterator iter = BrowserList::begin();
+ iter != BrowserList::end(); ++iter) {
+ active_profiles->insert((*iter)->profile()->GetDebugName());
+ }
+
+ content::BrowserThread::PostBlockingPoolSequencedTask(
+ Database::kDatabaseSequenceToken,
+ FROM_HERE,
+ base::Bind(&PerformanceMonitor::UpdateLiveProfilesHelper,
+ base::Unretained(this),
+ base::Passed(active_profiles.Pass()),
+ time));
+}
+
+void PerformanceMonitor::UpdateLiveProfilesHelper(
+ scoped_ptr<std::set<std::string> > active_profiles,
+ std::string time) {
+ CHECK(!content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ for (std::set<std::string>::const_iterator iter = active_profiles->begin();
+ iter != active_profiles->end(); ++iter) {
+ database_->AddStateValue(kStateProfile + *iter, time);
+ }
+}
+
+void PerformanceMonitor::DoTimedCollections() {
+ UpdateLiveProfiles();
+}
+
void PerformanceMonitor::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
@@ -239,6 +355,18 @@ void PerformanceMonitor::Observe(int type,
contents->GetURL().spec()));
break;
}
+ case chrome::NOTIFICATION_PROFILE_ADDED: {
+ Profile* profile = content::Source<Profile>(source).ptr();
+ if (!profile->DidLastSessionExitCleanly()) {
+ content::BrowserThread::PostBlockingPoolSequencedTask(
+ Database::kDatabaseSequenceToken,
+ FROM_HERE,
+ base::Bind(&PerformanceMonitor::AddUncleanExitEvent,
+ base::Unretained(this),
+ profile->GetDebugName()));
+ }
+ break;
+ }
default: {
NOTREACHED();
break;

Powered by Google App Engine
This is Rietveld 408576698