summaryrefslogtreecommitdiffstats
path: root/chrome/browser/performance_monitor
diff options
context:
space:
mode:
authorrdevlin.cronin@chromium.org <rdevlin.cronin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-02 21:15:08 +0000
committerrdevlin.cronin@chromium.org <rdevlin.cronin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-08-02 21:15:08 +0000
commit3848a179e08a40ce123bdb52531995e5d99f16b5 (patch)
treed7ac313871b3fda929564eaa7279456a1c087bd6 /chrome/browser/performance_monitor
parentbd7a29ff3a5c5c4e7342ab50edbd72925c772a66 (diff)
downloadchromium_src-3848a179e08a40ce123bdb52531995e5d99f16b5.zip
chromium_src-3848a179e08a40ce123bdb52531995e5d99f16b5.tar.gz
chromium_src-3848a179e08a40ce123bdb52531995e5d99f16b5.tar.bz2
CPM: revised unclean exit watching, revised renderer crash test
Fixed unclean exit watching to work on CrOS Added a cleaner waiting structure to renderer crash to see if it clears up the CrOS ASAN error. BUG=137726, 130212 Review URL: https://chromiumcodereview.appspot.com/10815079 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@149697 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/performance_monitor')
-rw-r--r--chrome/browser/performance_monitor/constants.cc32
-rw-r--r--chrome/browser/performance_monitor/constants.h18
-rw-r--r--chrome/browser/performance_monitor/event.h2
-rw-r--r--chrome/browser/performance_monitor/events.json7
-rw-r--r--chrome/browser/performance_monitor/performance_monitor.cc132
-rw-r--r--chrome/browser/performance_monitor/performance_monitor.h28
-rw-r--r--chrome/browser/performance_monitor/performance_monitor_browsertest.cc133
-rw-r--r--chrome/browser/performance_monitor/performance_monitor_util.cc10
-rw-r--r--chrome/browser/performance_monitor/performance_monitor_util.h3
9 files changed, 336 insertions, 29 deletions
diff --git a/chrome/browser/performance_monitor/constants.cc b/chrome/browser/performance_monitor/constants.cc
index 298b9bc..0b91160 100644
--- a/chrome/browser/performance_monitor/constants.cc
+++ b/chrome/browser/performance_monitor/constants.cc
@@ -6,22 +6,44 @@
namespace performance_monitor {
-// The key to insert/retrieve information about the chrome version from the
-// database.
-const char kStateChromeVersion[] = "chrome_version";
-const char kMetricNotFoundError[] = "Mertic details not found.";
+// TODO(chebert): i18n on all constants.
+
+// The error message displayed when a metric's details are not found.
+const char kMetricNotFoundError[] = "Metric details not found.";
+
+// Any metric that is not associated with a specific activity will use this as
+// its activity.
const char kProcessChromeAggregate[] = "chrome_aggregate";
+// The interval at which PerformanceMonitor performs its timed collections.
+const int kGatherIntervalInMinutes = 2;
+
+// Tokens to retrieve state values from the database.
+
+// Stores information about the previous chrome version.
+const char kStateChromeVersion[] = "chrome_version";
+// The prefix to the state of a profile's name, to prevent any possible naming
+// collisions in the database.
+const char kStateProfilePrefix[] = "profile";
+
+// Metric details follow.
+// All metric details have the following constants:
+// - Name
+// - Description
+// - Units
+// - TickSize (the smallest possible maximum which will be viewed in the ui.)
+
+// CPU Usage
const char kMetricCPUUsageName[] = "CPU Usage";
const char kMetricCPUUsageDescription[] = "The CPU usage measured in percent.";
const char kMetricCPUUsageUnits[] = "percent";
const double kMetricCPUUsageTickSize = 100.0;
+// Private Memory Usage
const char kMetricPrivateMemoryUsageName[] = "Private Memory Usage";
const char kMetricPrivateMemoryUsageDescription[] =
"The private memory usage measured in bytes.";
const char kMetricPrivateMemoryUsageUnits[] = "percent";
const double kMetricPrivateMemoryUsageTickSize = 10000000.0;
-
} // namespace performance_monitor
diff --git a/chrome/browser/performance_monitor/constants.h b/chrome/browser/performance_monitor/constants.h
index a3455b0..a536e51 100644
--- a/chrome/browser/performance_monitor/constants.h
+++ b/chrome/browser/performance_monitor/constants.h
@@ -7,26 +7,28 @@
namespace performance_monitor {
-// TODO(chebert): i18n on all constants.
-extern const char kMetricNotFoundError[];
+// Constants which are used by the PerformanceMonitor and its related classes.
+// The constants should be documented alongside the definition of their values
+// in the .cc file.
-// Any metric that is not associated with a specific activity will use this as
-// its activity.
+extern const char kMetricNotFoundError[];
extern const char kProcessChromeAggregate[];
+extern const int kGatherIntervalInMinutes;
+
+// State tokens
+extern const char kStateChromeVersion[];
+extern const char kStateProfilePrefix[];
-// Metrics keys for statistics gathering.
+// Metric details
extern const char kMetricCPUUsageName[];
extern const char kMetricCPUUsageDescription[];
extern const char kMetricCPUUsageUnits[];
extern const double kMetricCPUUsageTickSize;
-
extern const char kMetricPrivateMemoryUsageName[];
extern const char kMetricPrivateMemoryUsageDescription[];
extern const char kMetricPrivateMemoryUsageUnits[];
extern const double kMetricPrivateMemoryUsageTickSize;
-extern const char kStateChromeVersion[];
-
} // namespace performance_monitor
#endif // CHROME_BROWSER_PERFORMANCE_MONITOR_CONSTANTS_H_
diff --git a/chrome/browser/performance_monitor/event.h b/chrome/browser/performance_monitor/event.h
index 4452d25..64afb14 100644
--- a/chrome/browser/performance_monitor/event.h
+++ b/chrome/browser/performance_monitor/event.h
@@ -26,7 +26,7 @@ enum EventType {
EVENT_RENDERER_FREEZE,
EVENT_RENDERER_CRASH,
EVENT_KILLED_BY_OS_CRASH,
- EVENT_UNCLEAN_SHUTDOWN,
+ EVENT_UNCLEAN_EXIT,
EVENT_NUMBER_OF_EVENTS
};
diff --git a/chrome/browser/performance_monitor/events.json b/chrome/browser/performance_monitor/events.json
index d82593c..2ee1c61 100644
--- a/chrome/browser/performance_monitor/events.json
+++ b/chrome/browser/performance_monitor/events.json
@@ -113,12 +113,13 @@
}
},
{
- "id": "UncleanShutdown",
+ "id": "UncleanExit",
"type": "object",
- "description": "The event to represent an unclean shutdown.",
+ "description": "The event to represent an unclean exit.",
"properties": {
"eventType": {"type": "integer", "description": "The type of the event."},
- "time": {"type": "number", "description": "The time at which the event was recorded."}
+ "time": {"type": "number", "description": "The time at which the event was recorded."},
+ "profileName": {"type": "string", "description": "The name of the profile which shutdown uncleanly."}
}
}
]
diff --git a/chrome/browser/performance_monitor/performance_monitor.cc b/chrome/browser/performance_monitor/performance_monitor.cc
index 445d113..c23d68c 100644
--- a/chrome/browser/performance_monitor/performance_monitor.cc
+++ b/chrome/browser/performance_monitor/performance_monitor.cc
@@ -4,16 +4,24 @@
#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/extensions/crx_installer.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/extensions/crx_installer.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/common/chrome_notification_types.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/extensions/extension.h"
@@ -27,6 +35,23 @@
using content::BrowserThread;
using extensions::Extension;
+namespace {
+
+std::string TimeToString(base::Time time) {
+ int64 time_int64 = time.ToInternalValue();
+ return base::Int64ToString(time_int64);
+}
+
+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) {
@@ -60,19 +85,25 @@ void PerformanceMonitor::Start() {
}
void PerformanceMonitor::InitOnBackgroundThread() {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
+ CHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
database_ = Database::Create(database_path_);
}
void PerformanceMonitor::FinishInit() {
- DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
RegisterForNotifications();
+ CheckForUncleanExits();
BrowserThread::PostBlockingPoolSequencedTask(
Database::kDatabaseSequenceToken,
FROM_HERE,
base::Bind(&PerformanceMonitor::CheckForVersionUpdateOnBackgroundThread,
base::Unretained(this)));
+ timer_.Start(FROM_HERE,
+ base::TimeDelta::FromMinutes(kGatherIntervalInMinutes),
+ this,
+ &PerformanceMonitor::DoTimedCollections);
+
// Post a task to the background thread to a function which does nothing.
// This will force any tasks the database is performing to finish prior to
// the reply being sent, since they use the same thread.
@@ -105,10 +136,54 @@ void PerformanceMonitor::RegisterForNotifications() {
content::NotificationService::AllSources());
registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
content::NotificationService::AllSources());
+
+ // Profiles (for unclean exit)
+ registrar_.Add(this, chrome::NOTIFICATION_PROFILE_ADDED,
+ content::NotificationService::AllSources());
+}
+
+// We check if profiles exited cleanly initialization time in case they were
+// loaded prior to PerformanceMonitor's initialization. Later profiles will be
+// checked through the PROFILE_ADDED notification.
+void PerformanceMonitor::CheckForUncleanExits() {
+ 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()) {
+ BrowserThread::PostBlockingPoolSequencedTask(
+ Database::kDatabaseSequenceToken,
+ FROM_HERE,
+ base::Bind(&PerformanceMonitor::AddUncleanExitEventOnBackgroundThread,
+ base::Unretained(this),
+ (*iter)->GetDebugName()));
+ }
+ }
+}
+
+void PerformanceMonitor::AddUncleanExitEventOnBackgroundThread(
+ const std::string& profile_name) {
+ std::string database_key = kStateProfilePrefix + 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));
+
+ scoped_ptr<Event> event =
+ util::CreateUncleanExitEvent(last_active_time, profile_name);
+
+ database_->AddEvent(*event.get());
}
void PerformanceMonitor::CheckForVersionUpdateOnBackgroundThread() {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
+ CHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
chrome::VersionInfo version;
DCHECK(version.is_valid());
@@ -150,7 +225,7 @@ void PerformanceMonitor::AddEventOnBackgroundThread(scoped_ptr<Event> event) {
void PerformanceMonitor::GetStateValueOnBackgroundThread(
const std::string& key,
const StateValueCallback& callback) {
- DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
+ CHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
std::string state_value = database_->GetStateValue(key);
BrowserThread::PostTask(BrowserThread::UI,
@@ -165,6 +240,40 @@ void PerformanceMonitor::NotifyInitialized() {
content::NotificationService::NoDetails());
}
+void PerformanceMonitor::UpdateLiveProfiles() {
+ std::string time = TimeToString(base::Time::Now());
+ 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());
+ }
+
+ 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(!BrowserThread::CurrentlyOn(BrowserThread::UI));
+
+ for (std::set<std::string>::const_iterator iter = active_profiles->begin();
+ iter != active_profiles->end(); ++iter) {
+ database_->AddStateValue(kStateProfilePrefix + *iter, time);
+ }
+}
+
+void PerformanceMonitor::DoTimedCollections() {
+ UpdateLiveProfiles();
+}
+
void PerformanceMonitor::Observe(int type,
const content::NotificationSource& source,
const content::NotificationDetails& details) {
@@ -260,6 +369,19 @@ void PerformanceMonitor::Observe(int type,
type));
break;
}
+ case chrome::NOTIFICATION_PROFILE_ADDED: {
+ Profile* profile = content::Source<Profile>(source).ptr();
+ if (!profile->DidLastSessionExitCleanly()) {
+ BrowserThread::PostBlockingPoolSequencedTask(
+ Database::kDatabaseSequenceToken,
+ FROM_HERE,
+ base::Bind(
+ &PerformanceMonitor::AddUncleanExitEventOnBackgroundThread,
+ base::Unretained(this),
+ profile->GetDebugName()));
+ }
+ break;
+ }
default: {
NOTREACHED();
break;
diff --git a/chrome/browser/performance_monitor/performance_monitor.h b/chrome/browser/performance_monitor/performance_monitor.h
index e4fa0a5..c74ee7a 100644
--- a/chrome/browser/performance_monitor/performance_monitor.h
+++ b/chrome/browser/performance_monitor/performance_monitor.h
@@ -5,10 +5,13 @@
#ifndef CHROME_BROWSER_PERFORMANCE_MONITOR_PERFORMANCE_MONITOR_H_
#define CHROME_BROWSER_PERFORMANCE_MONITOR_PERFORMANCE_MONITOR_H_
+#include <string>
+
#include "base/callback.h"
#include "base/file_path.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h"
+#include "base/timer.h"
#include "chrome/browser/performance_monitor/database.h"
#include "chrome/browser/performance_monitor/event.h"
#include "content/public/browser/notification_details.h"
@@ -51,6 +54,10 @@ class PerformanceMonitor : public content::NotificationObserver {
private:
friend struct DefaultSingletonTraits<PerformanceMonitor>;
FRIEND_TEST_ALL_PREFIXES(PerformanceMonitorBrowserTest, NewVersionEvent);
+ FRIEND_TEST_ALL_PREFIXES(PerformanceMonitorUncleanExitBrowserTest,
+ OneProfileUncleanExit);
+ FRIEND_TEST_ALL_PREFIXES(PerformanceMonitorUncleanExitBrowserTest,
+ TwoProfileUncleanExit);
PerformanceMonitor();
virtual ~PerformanceMonitor();
@@ -64,6 +71,15 @@ class PerformanceMonitor : public content::NotificationObserver {
// Register for the appropriate notifications as a NotificationObserver.
void RegisterForNotifications();
+ // Checks for whether the previous profiles closed uncleanly; this method
+ // should only be called once per run in order to avoid duplication of events
+ // (exceptions made for testing purposes where we construct the environment).
+ void CheckForUncleanExits();
+
+ // Find the last active time for the profile and insert the event into the
+ // database.
+ void AddUncleanExitEventOnBackgroundThread(const std::string& profile_name);
+
// Check the previous Chrome version from the Database and determine if
// it has been updated. If it has, insert an event in the database.
void CheckForVersionUpdateOnBackgroundThread();
@@ -82,12 +98,24 @@ class PerformanceMonitor : public content::NotificationObserver {
// Notify any listeners that PerformanceMonitor has finished the initializing.
void NotifyInitialized();
+ // Update the database record of the last time the active profiles were
+ // running; this is used in determining when an unclean exit occurred.
+ void UpdateLiveProfiles();
+ void UpdateLiveProfilesHelper(
+ scoped_ptr<std::set<std::string> > active_profiles, std::string time);
+
+ // Perform any collections that are done on a timed basis.
+ void DoTimedCollections();
+
// The location at which the database files are stored; if empty, the database
// will default to '<user_data_dir>/performance_monitor_dbs'.
FilePath database_path_;
scoped_ptr<Database> database_;
+ // The timer to signal PerformanceMonitor to perform its timed collections.
+ base::RepeatingTimer<PerformanceMonitor> timer_;
+
content::NotificationRegistrar registrar_;
DISALLOW_COPY_AND_ASSIGN(PerformanceMonitor);
diff --git a/chrome/browser/performance_monitor/performance_monitor_browsertest.cc b/chrome/browser/performance_monitor/performance_monitor_browsertest.cc
index bc71be8..9bc3965 100644
--- a/chrome/browser/performance_monitor/performance_monitor_browsertest.cc
+++ b/chrome/browser/performance_monitor/performance_monitor_browsertest.cc
@@ -4,10 +4,13 @@
#include "chrome/test/base/in_process_browser_test.h"
+#include "base/command_line.h"
#include "base/file_path.h"
#include "base/logging.h"
#include "base/path_service.h"
+#include "base/string_number_conversions.h"
#include "base/threading/sequenced_worker_pool.h"
+#include "chrome/browser/browser_process.h"
#include "chrome/browser/performance_monitor/constants.h"
#include "chrome/browser/performance_monitor/database.h"
#include "chrome/browser/performance_monitor/performance_monitor.h"
@@ -15,10 +18,13 @@
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/unpacked_installer.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_tabstrip.h"
+#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_notification_types.h"
#include "chrome/common/chrome_paths.h"
+#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h"
#include "chrome/common/extensions/extension.h"
#include "chrome/common/url_constants.h"
@@ -26,6 +32,7 @@
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
#include "content/public/test/browser_test_utils.h"
+#include "content/public/test/test_utils.h"
using extensions::Extension;
using performance_monitor::Event;
@@ -197,6 +204,65 @@ class PerformanceMonitorBrowserTest : public ExtensionBrowserTest {
PerformanceMonitor* performance_monitor_;
};
+class PerformanceMonitorUncleanExitBrowserTest
+ : public PerformanceMonitorBrowserTest {
+ public:
+ virtual bool SetUpUserDataDirectory() OVERRIDE {
+ FilePath user_data_directory;
+ PathService::Get(chrome::DIR_USER_DATA, &user_data_directory);
+
+ // On CrOS, if we are "logged in" with the --login-profile switch,
+ // the default profile will be different. We check if we are logged in, and,
+ // if we are, we use that profile name instead. (Note: trybots will
+ // typically be logged in with 'user'.)
+#if defined(OS_CHROMEOS)
+ const CommandLine command_line = *CommandLine::ForCurrentProcess();
+ if (command_line.HasSwitch(switches::kLoginProfile)) {
+ first_profile_name_ =
+ command_line.GetSwitchValueASCII(switches::kLoginProfile);
+ } else {
+ first_profile_name_ = chrome::kInitialProfile;
+ }
+#else
+ first_profile_name_ = chrome::kInitialProfile;
+#endif
+
+ FilePath first_profile =
+ user_data_directory.AppendASCII(first_profile_name_);
+ CHECK(file_util::CreateDirectory(first_profile));
+
+ FilePath stock_prefs_file;
+ PathService::Get(chrome::DIR_TEST_DATA, &stock_prefs_file);
+ stock_prefs_file = stock_prefs_file.AppendASCII("performance_monitor")
+ .AppendASCII("unclean_exit_prefs");
+ CHECK(file_util::PathExists(stock_prefs_file));
+
+ FilePath first_profile_prefs_file =
+ first_profile.Append(chrome::kPreferencesFilename);
+ CHECK(file_util::CopyFile(stock_prefs_file, first_profile_prefs_file));
+ CHECK(file_util::PathExists(first_profile_prefs_file));
+
+ second_profile_name_ =
+ std::string(chrome::kMultiProfileDirPrefix)
+ .append(base::IntToString(1));
+
+ FilePath second_profile =
+ user_data_directory.AppendASCII(second_profile_name_);
+ CHECK(file_util::CreateDirectory(second_profile));
+
+ FilePath second_profile_prefs_file =
+ second_profile.Append(chrome::kPreferencesFilename);
+ CHECK(file_util::CopyFile(stock_prefs_file, second_profile_prefs_file));
+ CHECK(file_util::PathExists(second_profile_prefs_file));
+
+ return true;
+ }
+
+ protected:
+ std::string first_profile_name_;
+ std::string second_profile_name_;
+};
+
// Test that PerformanceMonitor will correctly record an extension installation
// event.
IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, InstallExtensionEvent) {
@@ -411,14 +477,77 @@ IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, KilledByOSEvent) {
}
#endif // !defined(OS_WIN)
-IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest,
- DISABLED_RendererCrashEvent) {
+IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, RendererCrashEvent) {
+ content::WindowedNotificationObserver windowed_observer(
+ content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
+ content::NotificationService::AllSources());
+
ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUICrashURL));
+ windowed_observer.Wait();
+
std::vector<linked_ptr<Event> > events = GetEvents();
ASSERT_EQ(1u, events.size());
CheckEventType(EVENT_RENDERER_CRASH, events[0]);
}
+IN_PROC_BROWSER_TEST_F(PerformanceMonitorUncleanExitBrowserTest,
+ OneProfileUncleanExit) {
+ // Initialize the database value (if there's no value in the database, it
+ // can't determine the last active time of the profile, and doesn't insert
+ // the event).
+ const std::string time = "12985807272597591";
+ AddStateValue(kStateProfilePrefix + first_profile_name_, time);
+
+ performance_monitor()->CheckForUncleanExits();
+ content::RunAllPendingInMessageLoop();
+
+ std::vector<linked_ptr<Event> > events = GetEvents();
+
+ const size_t kNumEvents = 1;
+ ASSERT_EQ(kNumEvents, events.size());
+
+ CheckEventType(EVENT_UNCLEAN_EXIT, events[0]);
+
+ std::string event_profile;
+ ASSERT_TRUE(events[0]->data()->GetString("profileName", &event_profile));
+ ASSERT_EQ(first_profile_name_, event_profile);
+}
+
+IN_PROC_BROWSER_TEST_F(PerformanceMonitorUncleanExitBrowserTest,
+ TwoProfileUncleanExit) {
+ FilePath second_profile_path;
+ PathService::Get(chrome::DIR_USER_DATA, &second_profile_path);
+ second_profile_path = second_profile_path.AppendASCII(second_profile_name_);
+
+ const std::string time1 = "12985807272597591";
+ const std::string time2 = "12985807272599918";
+
+ // Initialize the database.
+ AddStateValue(kStateProfilePrefix + first_profile_name_, time1);
+ AddStateValue(kStateProfilePrefix + second_profile_name_, time2);
+
+ performance_monitor()->CheckForUncleanExits();
+ content::RunAllPendingInMessageLoop();
+
+ // Load the second profile, which has also exited uncleanly.
+ g_browser_process->profile_manager()->GetProfile(second_profile_path);
+ content::RunAllPendingInMessageLoop();
+
+ std::vector<linked_ptr<Event> > events = GetEvents();
+
+ const size_t kNumEvents = 2;
+ ASSERT_EQ(kNumEvents, events.size());
+ CheckEventType(EVENT_UNCLEAN_EXIT, events[0]);
+ CheckEventType(EVENT_UNCLEAN_EXIT, events[1]);
+
+ std::string event_profile;
+ ASSERT_TRUE(events[0]->data()->GetString("profileName", &event_profile));
+ ASSERT_EQ(first_profile_name_, event_profile);
+
+ ASSERT_TRUE(events[1]->data()->GetString("profileName", &event_profile));
+ ASSERT_EQ(second_profile_name_, event_profile);
+}
+
} // namespace performance_monitor
diff --git a/chrome/browser/performance_monitor/performance_monitor_util.cc b/chrome/browser/performance_monitor/performance_monitor_util.cc
index 58c3c77..48baa76 100644
--- a/chrome/browser/performance_monitor/performance_monitor_util.cc
+++ b/chrome/browser/performance_monitor/performance_monitor_util.cc
@@ -194,13 +194,15 @@ scoped_ptr<Event> CreateCrashEvent(const base::Time& time,
return scoped_ptr<Event>(new Event(type, time, value.Pass()));
}
-scoped_ptr<Event> CreateUncleanShutdownEvent(const base::Time& time) {
- events::UncleanShutdown event;
- event.event_type = EVENT_UNCLEAN_SHUTDOWN;
+scoped_ptr<Event> CreateUncleanExitEvent(const base::Time& time,
+ const std::string& profile_name) {
+ events::UncleanExit event;
+ event.event_type = EVENT_UNCLEAN_EXIT;
event.time = static_cast<double>(time.ToInternalValue());
+ event.profile_name = profile_name;
scoped_ptr<base::DictionaryValue> value = event.ToValue();
return scoped_ptr<Event>(new Event(
- EVENT_UNCLEAN_SHUTDOWN, time, value.Pass()));
+ EVENT_UNCLEAN_EXIT, time, value.Pass()));
}
scoped_ptr<Event> CreateChromeUpdateEvent(const base::Time& time,
diff --git a/chrome/browser/performance_monitor/performance_monitor_util.h b/chrome/browser/performance_monitor/performance_monitor_util.h
index 55c52cd..dbe4381 100644
--- a/chrome/browser/performance_monitor/performance_monitor_util.h
+++ b/chrome/browser/performance_monitor/performance_monitor_util.h
@@ -92,7 +92,8 @@ scoped_ptr<Event> CreateCrashEvent(
const base::Time& time,
const EventType& type);
-scoped_ptr<Event> CreateUncleanShutdownEvent(const base::Time& time);
+scoped_ptr<Event> CreateUncleanExitEvent(const base::Time& time,
+ const std::string& profile_name);
scoped_ptr<Event> CreateChromeUpdateEvent(
const base::Time& time,