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
parent bd7a29ff
...@@ -6,22 +6,44 @@ ...@@ -6,22 +6,44 @@
namespace performance_monitor { namespace performance_monitor {
// The key to insert/retrieve information about the chrome version from the // TODO(chebert): i18n on all constants.
// database.
const char kStateChromeVersion[] = "chrome_version"; // The error message displayed when a metric's details are not found.
const char kMetricNotFoundError[] = "Mertic details 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"; 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 kMetricCPUUsageName[] = "CPU Usage";
const char kMetricCPUUsageDescription[] = "The CPU usage measured in percent."; const char kMetricCPUUsageDescription[] = "The CPU usage measured in percent.";
const char kMetricCPUUsageUnits[] = "percent"; const char kMetricCPUUsageUnits[] = "percent";
const double kMetricCPUUsageTickSize = 100.0; const double kMetricCPUUsageTickSize = 100.0;
// Private Memory Usage
const char kMetricPrivateMemoryUsageName[] = "Private Memory Usage"; const char kMetricPrivateMemoryUsageName[] = "Private Memory Usage";
const char kMetricPrivateMemoryUsageDescription[] = const char kMetricPrivateMemoryUsageDescription[] =
"The private memory usage measured in bytes."; "The private memory usage measured in bytes.";
const char kMetricPrivateMemoryUsageUnits[] = "percent"; const char kMetricPrivateMemoryUsageUnits[] = "percent";
const double kMetricPrivateMemoryUsageTickSize = 10000000.0; const double kMetricPrivateMemoryUsageTickSize = 10000000.0;
} // namespace performance_monitor } // namespace performance_monitor
...@@ -7,26 +7,28 @@ ...@@ -7,26 +7,28 @@
namespace performance_monitor { namespace performance_monitor {
// TODO(chebert): i18n on all constants. // Constants which are used by the PerformanceMonitor and its related classes.
extern const char kMetricNotFoundError[]; // 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 extern const char kMetricNotFoundError[];
// its activity.
extern const char kProcessChromeAggregate[]; 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 kMetricCPUUsageName[];
extern const char kMetricCPUUsageDescription[]; extern const char kMetricCPUUsageDescription[];
extern const char kMetricCPUUsageUnits[]; extern const char kMetricCPUUsageUnits[];
extern const double kMetricCPUUsageTickSize; extern const double kMetricCPUUsageTickSize;
extern const char kMetricPrivateMemoryUsageName[]; extern const char kMetricPrivateMemoryUsageName[];
extern const char kMetricPrivateMemoryUsageDescription[]; extern const char kMetricPrivateMemoryUsageDescription[];
extern const char kMetricPrivateMemoryUsageUnits[]; extern const char kMetricPrivateMemoryUsageUnits[];
extern const double kMetricPrivateMemoryUsageTickSize; extern const double kMetricPrivateMemoryUsageTickSize;
extern const char kStateChromeVersion[];
} // namespace performance_monitor } // namespace performance_monitor
#endif // CHROME_BROWSER_PERFORMANCE_MONITOR_CONSTANTS_H_ #endif // CHROME_BROWSER_PERFORMANCE_MONITOR_CONSTANTS_H_
...@@ -26,7 +26,7 @@ enum EventType { ...@@ -26,7 +26,7 @@ enum EventType {
EVENT_RENDERER_FREEZE, EVENT_RENDERER_FREEZE,
EVENT_RENDERER_CRASH, EVENT_RENDERER_CRASH,
EVENT_KILLED_BY_OS_CRASH, EVENT_KILLED_BY_OS_CRASH,
EVENT_UNCLEAN_SHUTDOWN, EVENT_UNCLEAN_EXIT,
EVENT_NUMBER_OF_EVENTS EVENT_NUMBER_OF_EVENTS
}; };
......
...@@ -113,12 +113,13 @@ ...@@ -113,12 +113,13 @@
} }
}, },
{ {
"id": "UncleanShutdown", "id": "UncleanExit",
"type": "object", "type": "object",
"description": "The event to represent an unclean shutdown.", "description": "The event to represent an unclean exit.",
"properties": { "properties": {
"eventType": {"type": "integer", "description": "The type of the event."}, "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."}
} }
} }
] ]
......
...@@ -4,16 +4,24 @@ ...@@ -4,16 +4,24 @@
#include "chrome/browser/performance_monitor/performance_monitor.h" #include "chrome/browser/performance_monitor/performance_monitor.h"
#include <set>
#include "base/bind.h" #include "base/bind.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/process_util.h" #include "base/process_util.h"
#include "base/string_number_conversions.h"
#include "base/threading/worker_pool.h" #include "base/threading/worker_pool.h"
#include "base/time.h" #include "base/time.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/browser_shutdown.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/constants.h"
#include "chrome/browser/performance_monitor/database.h" #include "chrome/browser/performance_monitor/database.h"
#include "chrome/browser/performance_monitor/performance_monitor_util.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_notification_types.h"
#include "chrome/common/chrome_version_info.h" #include "chrome/common/chrome_version_info.h"
#include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension.h"
...@@ -27,6 +35,23 @@ ...@@ -27,6 +35,23 @@
using content::BrowserThread; using content::BrowserThread;
using extensions::Extension; 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 { namespace performance_monitor {
PerformanceMonitor::PerformanceMonitor() : database_(NULL) { PerformanceMonitor::PerformanceMonitor() : database_(NULL) {
...@@ -60,19 +85,25 @@ void PerformanceMonitor::Start() { ...@@ -60,19 +85,25 @@ void PerformanceMonitor::Start() {
} }
void PerformanceMonitor::InitOnBackgroundThread() { void PerformanceMonitor::InitOnBackgroundThread() {
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); CHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
database_ = Database::Create(database_path_); database_ = Database::Create(database_path_);
} }
void PerformanceMonitor::FinishInit() { void PerformanceMonitor::FinishInit() {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
RegisterForNotifications(); RegisterForNotifications();
CheckForUncleanExits();
BrowserThread::PostBlockingPoolSequencedTask( BrowserThread::PostBlockingPoolSequencedTask(
Database::kDatabaseSequenceToken, Database::kDatabaseSequenceToken,
FROM_HERE, FROM_HERE,
base::Bind(&PerformanceMonitor::CheckForVersionUpdateOnBackgroundThread, base::Bind(&PerformanceMonitor::CheckForVersionUpdateOnBackgroundThread,
base::Unretained(this))); 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. // 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 // This will force any tasks the database is performing to finish prior to
// the reply being sent, since they use the same thread. // the reply being sent, since they use the same thread.
...@@ -105,10 +136,54 @@ void PerformanceMonitor::RegisterForNotifications() { ...@@ -105,10 +136,54 @@ void PerformanceMonitor::RegisterForNotifications() {
content::NotificationService::AllSources()); content::NotificationService::AllSources());
registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED, registrar_.Add(this, content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
content::NotificationService::AllSources()); 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() { void PerformanceMonitor::CheckForVersionUpdateOnBackgroundThread() {
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); CHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
chrome::VersionInfo version; chrome::VersionInfo version;
DCHECK(version.is_valid()); DCHECK(version.is_valid());
...@@ -150,7 +225,7 @@ void PerformanceMonitor::AddEventOnBackgroundThread(scoped_ptr<Event> event) { ...@@ -150,7 +225,7 @@ void PerformanceMonitor::AddEventOnBackgroundThread(scoped_ptr<Event> event) {
void PerformanceMonitor::GetStateValueOnBackgroundThread( void PerformanceMonitor::GetStateValueOnBackgroundThread(
const std::string& key, const std::string& key,
const StateValueCallback& callback) { const StateValueCallback& callback) {
DCHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI)); CHECK(!BrowserThread::CurrentlyOn(BrowserThread::UI));
std::string state_value = database_->GetStateValue(key); std::string state_value = database_->GetStateValue(key);
BrowserThread::PostTask(BrowserThread::UI, BrowserThread::PostTask(BrowserThread::UI,
...@@ -165,6 +240,40 @@ void PerformanceMonitor::NotifyInitialized() { ...@@ -165,6 +240,40 @@ void PerformanceMonitor::NotifyInitialized() {
content::NotificationService::NoDetails()); 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, void PerformanceMonitor::Observe(int type,
const content::NotificationSource& source, const content::NotificationSource& source,
const content::NotificationDetails& details) { const content::NotificationDetails& details) {
...@@ -260,6 +369,19 @@ void PerformanceMonitor::Observe(int type, ...@@ -260,6 +369,19 @@ void PerformanceMonitor::Observe(int type,
type)); type));
break; 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: { default: {
NOTREACHED(); NOTREACHED();
break; break;
......
...@@ -5,10 +5,13 @@ ...@@ -5,10 +5,13 @@
#ifndef CHROME_BROWSER_PERFORMANCE_MONITOR_PERFORMANCE_MONITOR_H_ #ifndef CHROME_BROWSER_PERFORMANCE_MONITOR_PERFORMANCE_MONITOR_H_
#define CHROME_BROWSER_PERFORMANCE_MONITOR_PERFORMANCE_MONITOR_H_ #define CHROME_BROWSER_PERFORMANCE_MONITOR_PERFORMANCE_MONITOR_H_
#include <string>
#include "base/callback.h" #include "base/callback.h"
#include "base/file_path.h" #include "base/file_path.h"
#include "base/memory/scoped_ptr.h" #include "base/memory/scoped_ptr.h"
#include "base/memory/singleton.h" #include "base/memory/singleton.h"
#include "base/timer.h"
#include "chrome/browser/performance_monitor/database.h" #include "chrome/browser/performance_monitor/database.h"
#include "chrome/browser/performance_monitor/event.h" #include "chrome/browser/performance_monitor/event.h"
#include "content/public/browser/notification_details.h" #include "content/public/browser/notification_details.h"
...@@ -51,6 +54,10 @@ class PerformanceMonitor : public content::NotificationObserver { ...@@ -51,6 +54,10 @@ class PerformanceMonitor : public content::NotificationObserver {
private: private:
friend struct DefaultSingletonTraits<PerformanceMonitor>; friend struct DefaultSingletonTraits<PerformanceMonitor>;
FRIEND_TEST_ALL_PREFIXES(PerformanceMonitorBrowserTest, NewVersionEvent); FRIEND_TEST_ALL_PREFIXES(PerformanceMonitorBrowserTest, NewVersionEvent);
FRIEND_TEST_ALL_PREFIXES(PerformanceMonitorUncleanExitBrowserTest,
OneProfileUncleanExit);
FRIEND_TEST_ALL_PREFIXES(PerformanceMonitorUncleanExitBrowserTest,
TwoProfileUncleanExit);
PerformanceMonitor(); PerformanceMonitor();
virtual ~PerformanceMonitor(); virtual ~PerformanceMonitor();
...@@ -64,6 +71,15 @@ class PerformanceMonitor : public content::NotificationObserver { ...@@ -64,6 +71,15 @@ class PerformanceMonitor : public content::NotificationObserver {
// Register for the appropriate notifications as a NotificationObserver. // Register for the appropriate notifications as a NotificationObserver.
void RegisterForNotifications(); 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 // Check the previous Chrome version from the Database and determine if
// it has been updated. If it has, insert an event in the database. // it has been updated. If it has, insert an event in the database.
void CheckForVersionUpdateOnBackgroundThread(); void CheckForVersionUpdateOnBackgroundThread();
...@@ -82,12 +98,24 @@ class PerformanceMonitor : public content::NotificationObserver { ...@@ -82,12 +98,24 @@ class PerformanceMonitor : public content::NotificationObserver {
// Notify any listeners that PerformanceMonitor has finished the initializing. // Notify any listeners that PerformanceMonitor has finished the initializing.
void NotifyInitialized(); 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 // The location at which the database files are stored; if empty, the database
// will default to '<user_data_dir>/performance_monitor_dbs'. // will default to '<user_data_dir>/performance_monitor_dbs'.
FilePath database_path_; FilePath database_path_;
scoped_ptr<Database> database_; scoped_ptr<Database> database_;
// The timer to signal PerformanceMonitor to perform its timed collections.
base::RepeatingTimer<PerformanceMonitor> timer_;
content::NotificationRegistrar registrar_; content::NotificationRegistrar registrar_;
DISALLOW_COPY_AND_ASSIGN(PerformanceMonitor); DISALLOW_COPY_AND_ASSIGN(PerformanceMonitor);
......
...@@ -4,10 +4,13 @@ ...@@ -4,10 +4,13 @@
#include "chrome/test/base/in_process_browser_test.h" #include "chrome/test/base/in_process_browser_test.h"
#include "base/command_line.h"
#include "base/file_path.h" #include "base/file_path.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "base/string_number_conversions.h"
#include "base/threading/sequenced_worker_pool.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/constants.h"
#include "chrome/browser/performance_monitor/database.h" #include "chrome/browser/performance_monitor/database.h"
#include "chrome/browser/performance_monitor/performance_monitor.h" #include "chrome/browser/performance_monitor/performance_monitor.h"
...@@ -15,10 +18,13 @@ ...@@ -15,10 +18,13 @@
#include "chrome/browser/extensions/extension_service.h" #include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/extensions/unpacked_installer.h" #include "chrome/browser/extensions/unpacked_installer.h"
#include "chrome/browser/profiles/profile.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.h"
#include "chrome/browser/ui/browser_tabstrip.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_notification_types.h"
#include "chrome/common/chrome_paths.h" #include "chrome/common/chrome_paths.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/chrome_version_info.h" #include "chrome/common/chrome_version_info.h"
#include "chrome/common/extensions/extension.h" #include "chrome/common/extensions/extension.h"
#include "chrome/common/url_constants.h" #include "chrome/common/url_constants.h"
...@@ -26,6 +32,7 @@ ...@@ -26,6 +32,7 @@
#include "content/public/browser/notification_registrar.h" #include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h" #include "content/public/browser/notification_service.h"
#include "content/public/test/browser_test_utils.h" #include "content/public/test/browser_test_utils.h"
#include "content/public/test/test_utils.h"
using extensions::Extension; using extensions::Extension;
using performance_monitor::Event; using performance_monitor::Event;
...@@ -197,6 +204,65 @@ class PerformanceMonitorBrowserTest : public ExtensionBrowserTest { ...@@ -197,6 +204,65 @@ class PerformanceMonitorBrowserTest : public ExtensionBrowserTest {
PerformanceMonitor* performance_monitor_; 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 // Test that PerformanceMonitor will correctly record an extension installation
// event. // event.
IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, InstallExtensionEvent) { IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, InstallExtensionEvent) {
...@@ -411,14 +477,77 @@ IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, KilledByOSEvent) { ...@@ -411,14 +477,77 @@ IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, KilledByOSEvent) {
} }
#endif // !defined(OS_WIN) #endif // !defined(OS_WIN)
IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, RendererCrashEvent) {
DISABLED_RendererCrashEvent) { content::WindowedNotificationObserver windowed_observer(
content::NOTIFICATION_RENDERER_PROCESS_CLOSED,
content::NotificationService::AllSources());
ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUICrashURL)); ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUICrashURL));
windowed_observer.Wait();
std::vector<linked_ptr<Event> > events = GetEvents(); std::vector<linked_ptr<Event> > events = GetEvents();
ASSERT_EQ(1u, events.size()); ASSERT_EQ(1u, events.size());
CheckEventType(EVENT_RENDERER_CRASH, events[0]); 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 } // namespace performance_monitor
...@@ -194,13 +194,15 @@ scoped_ptr<Event> CreateCrashEvent(const base::Time& time, ...@@ -194,13 +194,15 @@ scoped_ptr<Event> CreateCrashEvent(const base::Time& time,
return scoped_ptr<Event>(new Event(type, time, value.Pass())); return scoped_ptr<Event>(new Event(type, time, value.Pass()));
} }
scoped_ptr<Event> CreateUncleanShutdownEvent(const base::Time& time) { scoped_ptr<Event> CreateUncleanExitEvent(const base::Time& time,
events::UncleanShutdown event; const std::string& profile_name) {
event.event_type = EVENT_UNCLEAN_SHUTDOWN; events::UncleanExit event;
event.event_type = EVENT_UNCLEAN_EXIT;
event.time = static_cast<double>(time.ToInternalValue()); event.time = static_cast<double>(time.ToInternalValue());
event.profile_name = profile_name;
scoped_ptr<base::DictionaryValue> value = event.ToValue(); scoped_ptr<base::DictionaryValue> value = event.ToValue();
return scoped_ptr<Event>(new Event( 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, scoped_ptr<Event> CreateChromeUpdateEvent(const base::Time& time,
......
...@@ -92,7 +92,8 @@ scoped_ptr<Event> CreateCrashEvent( ...@@ -92,7 +92,8 @@ scoped_ptr<Event> CreateCrashEvent(
const base::Time& time, const base::Time& time,
const EventType& type); 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( scoped_ptr<Event> CreateChromeUpdateEvent(
const base::Time& time, const base::Time& time,
......
{
"profile": {
"exited_cleanly": false
}
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment