Home | History | Annotate | Download | only in performance_monitor
      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
      3 // found in the LICENSE file.
      4 
      5 #include "base/command_line.h"
      6 #include "base/files/file_path.h"
      7 #include "base/logging.h"
      8 #include "base/path_service.h"
      9 #include "base/strings/string_number_conversions.h"
     10 #include "base/threading/sequenced_worker_pool.h"
     11 #include "chrome/browser/browser_process.h"
     12 #include "chrome/browser/chrome_notification_types.h"
     13 #include "chrome/browser/extensions/extension_browsertest.h"
     14 #include "chrome/browser/extensions/extension_service.h"
     15 #include "chrome/browser/performance_monitor/constants.h"
     16 #include "chrome/browser/performance_monitor/database.h"
     17 #include "chrome/browser/performance_monitor/metric.h"
     18 #include "chrome/browser/performance_monitor/performance_monitor.h"
     19 #include "chrome/browser/prefs/session_startup_pref.h"
     20 #include "chrome/browser/profiles/profile.h"
     21 #include "chrome/browser/profiles/profile_manager.h"
     22 #include "chrome/browser/sessions/session_service.h"
     23 #include "chrome/browser/sessions/session_service_factory.h"
     24 #include "chrome/browser/sessions/session_service_test_helper.h"
     25 #include "chrome/browser/ui/browser.h"
     26 #include "chrome/browser/ui/browser_commands.h"
     27 #include "chrome/browser/ui/browser_navigator.h"
     28 #include "chrome/browser/ui/browser_window.h"
     29 #include "chrome/browser/ui/host_desktop.h"
     30 #include "chrome/browser/ui/tabs/tab_strip_model.h"
     31 #include "chrome/common/chrome_constants.h"
     32 #include "chrome/common/chrome_paths.h"
     33 #include "chrome/common/chrome_switches.h"
     34 #include "chrome/common/chrome_version_info.h"
     35 #include "chrome/common/url_constants.h"
     36 #include "chrome/test/base/ui_test_utils.h"
     37 #include "content/public/browser/notification_registrar.h"
     38 #include "content/public/browser/notification_service.h"
     39 #include "content/public/common/page_transition_types.h"
     40 #include "content/public/test/browser_test_utils.h"
     41 #include "content/public/test/test_navigation_observer.h"
     42 #include "content/public/test/test_utils.h"
     43 #include "extensions/common/extension.h"
     44 
     45 #if defined(OS_CHROMEOS)
     46 #include "chrome/browser/chromeos/login/users/user_manager.h"
     47 #include "chrome/browser/chromeos/profiles/profile_helper.h"
     48 #include "chromeos/chromeos_switches.h"
     49 #endif
     50 
     51 #if defined(OS_MACOSX)
     52 #include "base/mac/scoped_nsautorelease_pool.h"
     53 #endif
     54 
     55 using extensions::Extension;
     56 
     57 namespace performance_monitor {
     58 
     59 namespace {
     60 
     61 const base::TimeDelta kMaxStartupTime = base::TimeDelta::FromMinutes(3);
     62 
     63 #if defined(OS_CHROMEOS)
     64 // User account email and directory hash for secondary account for multi-profile
     65 // sensitive test cases.
     66 const char kSecondProfileAccount[] = "profile2 (at) test.com";
     67 const char kSecondProfileHash[] = "profile2";
     68 #endif
     69 
     70 // Helper struct to store the information of an extension; this is needed if the
     71 // pointer to the extension ever becomes invalid (e.g., if we uninstall the
     72 // extension).
     73 struct ExtensionBasicInfo {
     74   // Empty constructor for stl-container-happiness.
     75   ExtensionBasicInfo() {
     76   }
     77   explicit ExtensionBasicInfo(const Extension* extension)
     78       : description(extension->description()),
     79         id(extension->id()),
     80         name(extension->name()),
     81         url(extension->url().spec()),
     82         version(extension->VersionString()),
     83         location(extension->location()) {
     84   }
     85 
     86   std::string description;
     87   std::string id;
     88   std::string name;
     89   std::string url;
     90   std::string version;
     91   extensions::Manifest::Location location;
     92 };
     93 
     94 // Compare the fields of |extension| to those in |value|; this is a check to
     95 // make sure the extension data was recorded properly in the event.
     96 void ValidateExtensionInfo(const ExtensionBasicInfo extension,
     97                            const base::DictionaryValue* value) {
     98   std::string extension_description;
     99   std::string extension_id;
    100   std::string extension_name;
    101   std::string extension_url;
    102   std::string extension_version;
    103   int extension_location;
    104 
    105   ASSERT_TRUE(value->GetString("extensionDescription",
    106                                &extension_description));
    107   ASSERT_EQ(extension.description, extension_description);
    108   ASSERT_TRUE(value->GetString("extensionId", &extension_id));
    109   ASSERT_EQ(extension.id, extension_id);
    110   ASSERT_TRUE(value->GetString("extensionName", &extension_name));
    111   ASSERT_EQ(extension.name, extension_name);
    112   ASSERT_TRUE(value->GetString("extensionUrl", &extension_url));
    113   ASSERT_EQ(extension.url, extension_url);
    114   ASSERT_TRUE(value->GetString("extensionVersion", &extension_version));
    115   ASSERT_EQ(extension.version, extension_version);
    116   ASSERT_TRUE(value->GetInteger("extensionLocation", &extension_location));
    117   ASSERT_EQ(extension.location, extension_location);
    118 }
    119 
    120 // Verify that a particular event has the proper type.
    121 void CheckEventType(int expected_event_type, const linked_ptr<Event>& event) {
    122   int event_type = -1;
    123   ASSERT_TRUE(event->data()->GetInteger("eventType", &event_type));
    124   ASSERT_EQ(expected_event_type, event_type);
    125   ASSERT_EQ(expected_event_type, event->type());
    126 }
    127 
    128 // Verify that we received the proper number of events, checking the type of
    129 // each one.
    130 void CheckEventTypes(const std::vector<int>& expected_event_types,
    131                      const Database::EventVector& events) {
    132   ASSERT_EQ(expected_event_types.size(), events.size());
    133 
    134   for (size_t i = 0; i < expected_event_types.size(); ++i)
    135     CheckEventType(expected_event_types[i], events[i]);
    136 }
    137 
    138 // Check that we received the proper number of events, that each event is of the
    139 // proper type, and that each event recorded the proper information about the
    140 // extension.
    141 void CheckExtensionEvents(
    142     const std::vector<int>& expected_event_types,
    143     const Database::EventVector& events,
    144     const std::vector<ExtensionBasicInfo>& extension_infos) {
    145   CheckEventTypes(expected_event_types, events);
    146 
    147   for (size_t i = 0; i < expected_event_types.size(); ++i) {
    148     ValidateExtensionInfo(extension_infos[i], events[i]->data());
    149     int event_type;
    150     ASSERT_TRUE(events[i]->data()->GetInteger("eventType", &event_type));
    151     ASSERT_EQ(expected_event_types[i], event_type);
    152   }
    153 }
    154 
    155 }  // namespace
    156 
    157 class PerformanceMonitorBrowserTest : public ExtensionBrowserTest {
    158  public:
    159   virtual void SetUpOnMainThread() OVERRIDE {
    160     CHECK(db_dir_.CreateUniqueTempDir());
    161     performance_monitor_ = PerformanceMonitor::GetInstance();
    162     performance_monitor_->SetDatabasePath(db_dir_.path());
    163 
    164     // PerformanceMonitor's initialization process involves a significant
    165     // amount of thread-hopping between the UI thread and the background thread.
    166     // If we begin the tests prior to full initialization, we cannot predict
    167     // the behavior or mock synchronicity as we must. Wait for initialization
    168     // to complete fully before proceeding with the test.
    169     content::WindowedNotificationObserver windowed_observer(
    170         chrome::NOTIFICATION_PERFORMANCE_MONITOR_INITIALIZED,
    171         content::NotificationService::AllSources());
    172 
    173     // We stop the timer in charge of doing timed collections so that we can
    174     // enforce when, and how many times, we do these collections.
    175     performance_monitor_->disable_timer_autostart_for_testing_ = true;
    176     // Force metrics to be stored, regardless of switches used.
    177     performance_monitor_->database_logging_enabled_ = true;
    178     performance_monitor_->Initialize();
    179 
    180     windowed_observer.Wait();
    181   }
    182 
    183   // A handle for gathering statistics from the database, which must be done on
    184   // the background thread. Since we are testing, we can mock synchronicity with
    185   // FlushForTesting().
    186   void GatherStatistics() {
    187     performance_monitor_->next_collection_time_ = base::Time::Now();
    188     performance_monitor_->GatherMetricsMapOnUIThread();
    189 
    190     RunAllPendingInMessageLoop(content::BrowserThread::IO);
    191     content::BrowserThread::GetBlockingPool()->FlushForTesting();
    192   }
    193 
    194   void GetEventsOnBackgroundThread(Database::EventVector* events) {
    195     // base::Time is potentially flaky in that there is no guarantee that it
    196     // won't actually decrease between successive calls. If we call GetEvents
    197     // and the Database uses base::Time::Now() and gets a lesser time, then it
    198     // will return 0 events. Thus, we use a time that is guaranteed to be in the
    199     // future (for at least the next couple hundred thousand years).
    200     *events = performance_monitor_->database()->GetEvents(
    201         base::Time(), base::Time::FromInternalValue(kint64max));
    202   }
    203 
    204   // A handle for getting the events from the database, which must be done on
    205   // the background thread. Since we are testing, we can mock synchronicity
    206   // with FlushForTesting().
    207   Database::EventVector GetEvents() {
    208     // Ensure that any event insertions happen prior to getting events in order
    209     // to avoid race conditions.
    210     content::BrowserThread::GetBlockingPool()->FlushForTesting();
    211     content::RunAllPendingInMessageLoop();
    212 
    213     Database::EventVector events;
    214     content::BrowserThread::PostBlockingPoolSequencedTask(
    215         Database::kDatabaseSequenceToken,
    216         FROM_HERE,
    217         base::Bind(&PerformanceMonitorBrowserTest::GetEventsOnBackgroundThread,
    218                    base::Unretained(this),
    219                    &events));
    220 
    221     content::BrowserThread::GetBlockingPool()->FlushForTesting();
    222     return events;
    223   }
    224 
    225   void GetStatsOnBackgroundThread(Database::MetricVector* metrics,
    226                                   MetricType type) {
    227     *metrics = *performance_monitor_->database()->GetStatsForActivityAndMetric(
    228         type, base::Time(), base::Time::FromInternalValue(kint64max));
    229   }
    230 
    231   // A handle for getting statistics from the database (see previous comments on
    232   // GetEvents() and GetEventsOnBackgroundThread).
    233   Database::MetricVector GetStats(MetricType type) {
    234     content::BrowserThread::GetBlockingPool()->FlushForTesting();
    235     content::RunAllPendingInMessageLoop();
    236 
    237     Database::MetricVector metrics;
    238     content::BrowserThread::PostBlockingPoolSequencedTask(
    239         Database::kDatabaseSequenceToken,
    240         FROM_HERE,
    241         base::Bind(&PerformanceMonitorBrowserTest::GetStatsOnBackgroundThread,
    242                    base::Unretained(this),
    243                    &metrics,
    244                    type));
    245 
    246     content::BrowserThread::GetBlockingPool()->FlushForTesting();
    247     return metrics;
    248   }
    249 
    250   // A handle for inserting a state value into the database, which must be done
    251   // on the background thread. This is useful for mocking up a scenario in which
    252   // the database has prior data stored. We mock synchronicity with
    253   // FlushForTesting().
    254   void AddStateValue(const std::string& key, const std::string& value) {
    255     content::BrowserThread::PostBlockingPoolSequencedTask(
    256         Database::kDatabaseSequenceToken,
    257         FROM_HERE,
    258         base::Bind(base::IgnoreResult(&Database::AddStateValue),
    259                    base::Unretained(performance_monitor()->database()),
    260                    key,
    261                    value));
    262 
    263     content::BrowserThread::GetBlockingPool()->FlushForTesting();
    264   }
    265 
    266   // A handle for PerformanceMonitor::CheckForVersionUpdateOnBackgroundThread();
    267   // we mock synchronicity with FlushForTesting().
    268   void CheckForVersionUpdate() {
    269     content::BrowserThread::PostBlockingPoolSequencedTask(
    270         Database::kDatabaseSequenceToken,
    271         FROM_HERE,
    272         base::Bind(&PerformanceMonitor::CheckForVersionUpdateOnBackgroundThread,
    273                    base::Unretained(performance_monitor())));
    274 
    275     content::BrowserThread::GetBlockingPool()->FlushForTesting();
    276   }
    277 
    278   PerformanceMonitor* performance_monitor() const {
    279     return performance_monitor_;
    280   }
    281 
    282  protected:
    283   base::ScopedTempDir db_dir_;
    284   PerformanceMonitor* performance_monitor_;
    285 };
    286 
    287 class PerformanceMonitorUncleanExitBrowserTest
    288     : public PerformanceMonitorBrowserTest,
    289       public testing::WithParamInterface<bool> {
    290  public:
    291   virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
    292     PerformanceMonitorBrowserTest::SetUpCommandLine(command_line);
    293 #if defined(OS_CHROMEOS)
    294     command_line->AppendSwitch(
    295         chromeos::switches::kIgnoreUserProfileMappingForTests);
    296 #endif
    297   }
    298 
    299   virtual bool SetUpUserDataDirectory() OVERRIDE {
    300     base::FilePath user_data_directory;
    301     PathService::Get(chrome::DIR_USER_DATA, &user_data_directory);
    302 
    303     // On CrOS, if we are "logged in" with the --login-profile switch,
    304     // the default profile will be different. We check if we are logged in, and,
    305     // if we are, we use that profile name instead. (Note: trybots will
    306     // typically be logged in with 'user'.)
    307 #if defined(OS_CHROMEOS)
    308     const CommandLine command_line = *CommandLine::ForCurrentProcess();
    309     if (command_line.HasSwitch(chromeos::switches::kLoginProfile)) {
    310       first_profile_name_ =
    311           command_line.GetSwitchValueASCII(chromeos::switches::kLoginProfile);
    312     } else {
    313       first_profile_name_ = chrome::kInitialProfile;
    314     }
    315 #else
    316     first_profile_name_ = chrome::kInitialProfile;
    317 #endif
    318 
    319     base::FilePath first_profile =
    320         user_data_directory.AppendASCII(first_profile_name_);
    321     CHECK(base::CreateDirectory(first_profile));
    322 
    323     base::FilePath stock_prefs_file;
    324     PathService::Get(chrome::DIR_TEST_DATA, &stock_prefs_file);
    325     stock_prefs_file = stock_prefs_file.AppendASCII("performance_monitor")
    326                                        .AppendASCII("unclean_exit_prefs");
    327     CHECK(base::PathExists(stock_prefs_file));
    328 
    329     base::FilePath first_profile_prefs_file =
    330         first_profile.Append(chrome::kPreferencesFilename);
    331     CHECK(base::CopyFile(stock_prefs_file, first_profile_prefs_file));
    332     CHECK(base::PathExists(first_profile_prefs_file));
    333 
    334     second_profile_name_ =
    335         std::string(chrome::kMultiProfileDirPrefix)
    336         .append(base::IntToString(1));
    337 #if defined(OS_CHROMEOS)
    338     if (GetParam()) {
    339       second_profile_name_ = chromeos::ProfileHelper::GetUserProfileDir(
    340           kSecondProfileHash).BaseName().value();
    341     }
    342 #endif
    343 
    344     base::FilePath second_profile =
    345         user_data_directory.AppendASCII(second_profile_name_);
    346     CHECK(base::CreateDirectory(second_profile));
    347 
    348     base::FilePath second_profile_prefs_file =
    349         second_profile.Append(chrome::kPreferencesFilename);
    350     CHECK(base::CopyFile(stock_prefs_file, second_profile_prefs_file));
    351     CHECK(base::PathExists(second_profile_prefs_file));
    352 
    353     return true;
    354   }
    355 
    356 #if defined(OS_CHROMEOS)
    357   virtual void AddSecondUserAccount() {
    358     // Add second user account for multi-profile test.
    359     if (GetParam()) {
    360       chromeos::UserManager::Get()->UserLoggedIn(kSecondProfileAccount,
    361                                                  kSecondProfileHash,
    362                                                  false);
    363     }
    364   }
    365 #endif
    366 
    367  protected:
    368   std::string first_profile_name_;
    369   std::string second_profile_name_;
    370 };
    371 
    372 class PerformanceMonitorSessionRestoreBrowserTest
    373     : public PerformanceMonitorBrowserTest {
    374  public:
    375   virtual void SetUpOnMainThread() OVERRIDE {
    376     SessionStartupPref pref(SessionStartupPref::LAST);
    377     SessionStartupPref::SetStartupPref(browser()->profile(), pref);
    378 #if defined(OS_CHROMEOS) || defined (OS_MACOSX)
    379     // Undo the effect of kBrowserAliveWithNoWindows in defaults.cc so that we
    380     // can get these test to work without quitting.
    381     SessionServiceTestHelper helper(
    382         SessionServiceFactory::GetForProfile(browser()->profile()));
    383     helper.SetForceBrowserNotAliveWithNoWindows(true);
    384     helper.ReleaseService();
    385 #endif
    386 
    387     PerformanceMonitorBrowserTest::SetUpOnMainThread();
    388   }
    389 
    390   Browser* QuitBrowserAndRestore(Browser* browser, int expected_tab_count) {
    391     Profile* profile = browser->profile();
    392 
    393     // Close the browser.
    394     g_browser_process->AddRefModule();
    395     content::WindowedNotificationObserver observer(
    396         chrome::NOTIFICATION_BROWSER_CLOSED,
    397         content::NotificationService::AllSources());
    398     browser->window()->Close();
    399 #if defined(OS_MACOSX)
    400     // BrowserWindowController depends on the auto release pool being recycled
    401     // in the message loop to delete itself, which frees the Browser object
    402     // which fires this event.
    403     AutoreleasePool()->Recycle();
    404 #endif
    405     observer.Wait();
    406 
    407     // Create a new window, which should trigger session restore.
    408     content::TestNavigationObserver restore_observer(NULL, expected_tab_count);
    409     restore_observer.StartWatchingNewWebContents();
    410     ui_test_utils::BrowserAddedObserver window_observer;
    411     chrome::NewEmptyWindow(profile, chrome::GetActiveDesktop());
    412     Browser* new_browser = window_observer.WaitForSingleNewBrowser();
    413     restore_observer.Wait();
    414     g_browser_process->ReleaseModule();
    415 
    416     return new_browser;
    417   }
    418 };
    419 
    420 // Test that PerformanceMonitor will correctly record an extension installation
    421 // event.
    422 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, InstallExtensionEvent) {
    423   base::FilePath extension_path;
    424   PathService::Get(chrome::DIR_TEST_DATA, &extension_path);
    425   extension_path = extension_path.AppendASCII("performance_monitor")
    426                                  .AppendASCII("extensions")
    427                                  .AppendASCII("simple_extension_v1");
    428   const Extension* extension = LoadExtension(extension_path);
    429 
    430   std::vector<ExtensionBasicInfo> extension_infos;
    431   extension_infos.push_back(ExtensionBasicInfo(extension));
    432 
    433   std::vector<int> expected_event_types;
    434   expected_event_types.push_back(EVENT_EXTENSION_INSTALL);
    435 
    436   Database::EventVector events = GetEvents();
    437   CheckExtensionEvents(expected_event_types, events, extension_infos);
    438 }
    439 
    440 // Test that PerformanceMonitor will correctly record events as an extension is
    441 // disabled and enabled.
    442 // Test is falky, see http://crbug.com/157980
    443 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest,
    444                        DISABLED_DisableAndEnableExtensionEvent) {
    445   const int kNumEvents = 3;
    446 
    447   base::FilePath extension_path;
    448   PathService::Get(chrome::DIR_TEST_DATA, &extension_path);
    449   extension_path = extension_path.AppendASCII("performance_monitor")
    450                                  .AppendASCII("extensions")
    451                                  .AppendASCII("simple_extension_v1");
    452   const Extension* extension = LoadExtension(extension_path);
    453 
    454   DisableExtension(extension->id());
    455   EnableExtension(extension->id());
    456 
    457   std::vector<ExtensionBasicInfo> extension_infos;
    458   // There will be three events in all, each pertaining to the same extension:
    459   //   Extension Install
    460   //   Extension Disable
    461   //   Extension Enable
    462   for (int i = 0; i < kNumEvents; ++i)
    463     extension_infos.push_back(ExtensionBasicInfo(extension));
    464 
    465   std::vector<int> expected_event_types;
    466   expected_event_types.push_back(EVENT_EXTENSION_INSTALL);
    467   expected_event_types.push_back(EVENT_EXTENSION_DISABLE);
    468   expected_event_types.push_back(EVENT_EXTENSION_ENABLE);
    469 
    470   Database::EventVector events = GetEvents();
    471   CheckExtensionEvents(expected_event_types, events, extension_infos);
    472 }
    473 
    474 // Test that PerformanceMonitor correctly records an extension update event.
    475 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, UpdateExtensionEvent) {
    476   base::ScopedTempDir temp_dir;
    477   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
    478 
    479   base::FilePath test_data_dir;
    480   PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
    481   test_data_dir = test_data_dir.AppendASCII("performance_monitor")
    482                                .AppendASCII("extensions");
    483 
    484   // We need two versions of the same extension.
    485   base::FilePath pem_path = test_data_dir.AppendASCII("simple_extension.pem");
    486   base::FilePath path_v1_ = PackExtensionWithOptions(
    487       test_data_dir.AppendASCII("simple_extension_v1"),
    488       temp_dir.path().AppendASCII("simple_extension1.crx"),
    489       pem_path,
    490       base::FilePath());
    491   base::FilePath path_v2_ = PackExtensionWithOptions(
    492       test_data_dir.AppendASCII("simple_extension_v2"),
    493       temp_dir.path().AppendASCII("simple_extension2.crx"),
    494       pem_path,
    495       base::FilePath());
    496 
    497   const extensions::Extension* extension = InstallExtension(path_v1_, 1);
    498 
    499   std::vector<ExtensionBasicInfo> extension_infos;
    500   extension_infos.push_back(ExtensionBasicInfo(extension));
    501 
    502   ExtensionService* extension_service =
    503       browser()->profile()->GetExtensionService();
    504 
    505   extensions::CrxInstaller* crx_installer = NULL;
    506 
    507   // Create an observer to wait for the update to finish.
    508   content::WindowedNotificationObserver windowed_observer(
    509       chrome::NOTIFICATION_CRX_INSTALLER_DONE,
    510       content::Source<extensions::CrxInstaller>(crx_installer));
    511   ASSERT_TRUE(extension_service->
    512       UpdateExtension(extension->id(), path_v2_, true, &crx_installer));
    513   windowed_observer.Wait();
    514 
    515   extension = extension_service->GetExtensionById(
    516       extension_infos[0].id, false); // don't include disabled extensions.
    517 
    518   // The total series of events for this process will be:
    519   //   Extension Install - install version 1
    520   //   Extension Install - install version 2
    521   //   Extension Update  - signal the udate to version 2
    522   // We push back the corresponding ExtensionBasicInfos.
    523   extension_infos.push_back(ExtensionBasicInfo(extension));
    524   extension_infos.push_back(extension_infos[1]);
    525 
    526   std::vector<int> expected_event_types;
    527   expected_event_types.push_back(EVENT_EXTENSION_INSTALL);
    528   expected_event_types.push_back(EVENT_EXTENSION_INSTALL);
    529   expected_event_types.push_back(EVENT_EXTENSION_UPDATE);
    530 
    531   Database::EventVector events = GetEvents();
    532 
    533   CheckExtensionEvents(expected_event_types, events, extension_infos);
    534 }
    535 
    536 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, UninstallExtensionEvent) {
    537   const int kNumEvents = 2;
    538   base::FilePath extension_path;
    539   PathService::Get(chrome::DIR_TEST_DATA, &extension_path);
    540   extension_path = extension_path.AppendASCII("performance_monitor")
    541                                  .AppendASCII("extensions")
    542                                  .AppendASCII("simple_extension_v1");
    543   const Extension* extension = LoadExtension(extension_path);
    544 
    545   std::vector<ExtensionBasicInfo> extension_infos;
    546   // There will be two events, both pertaining to the same extension:
    547   //   Extension Install
    548   //   Extension Uninstall
    549   for (int i = 0; i < kNumEvents; ++i)
    550     extension_infos.push_back(ExtensionBasicInfo(extension));
    551 
    552   UninstallExtension(extension->id());
    553 
    554   std::vector<int> expected_event_types;
    555   expected_event_types.push_back(EVENT_EXTENSION_INSTALL);
    556   expected_event_types.push_back(EVENT_EXTENSION_UNINSTALL);
    557 
    558   Database::EventVector events = GetEvents();
    559 
    560   CheckExtensionEvents(expected_event_types, events, extension_infos);
    561 }
    562 
    563 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, NewVersionEvent) {
    564   const char kOldVersion[] = "0.0";
    565 
    566   // The version in the database right now will be the current version of chrome
    567   // (gathered at initialization of PerformanceMonitor). Replace this with an
    568   // older version so an event is generated.
    569   AddStateValue(kStateChromeVersion, kOldVersion);
    570 
    571   CheckForVersionUpdate();
    572 
    573   chrome::VersionInfo version;
    574   ASSERT_TRUE(version.is_valid());
    575   std::string version_string = version.Version();
    576 
    577   Database::EventVector events = GetEvents();
    578   ASSERT_EQ(1u, events.size());
    579   ASSERT_EQ(EVENT_CHROME_UPDATE, events[0]->type());
    580 
    581   const base::DictionaryValue* value;
    582   ASSERT_TRUE(events[0]->data()->GetAsDictionary(&value));
    583 
    584   std::string previous_version;
    585   std::string current_version;
    586 
    587   ASSERT_TRUE(value->GetString("previousVersion", &previous_version));
    588   ASSERT_EQ(kOldVersion, previous_version);
    589   ASSERT_TRUE(value->GetString("currentVersion", &current_version));
    590   ASSERT_EQ(version_string, current_version);
    591 }
    592 
    593 // crbug.com/160502
    594 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest,
    595                        DISABLED_GatherStatistics) {
    596   GatherStatistics();
    597 
    598   // No stats should be recorded for this CPUUsage because this was the first
    599   // call to GatherStatistics.
    600   Database::MetricVector stats = GetStats(METRIC_CPU_USAGE);
    601   ASSERT_EQ(0u, stats.size());
    602 
    603   stats = GetStats(METRIC_PRIVATE_MEMORY_USAGE);
    604   ASSERT_EQ(1u, stats.size());
    605   EXPECT_GT(stats[0].value, 0);
    606 
    607   stats = GetStats(METRIC_SHARED_MEMORY_USAGE);
    608   ASSERT_EQ(1u, stats.size());
    609   EXPECT_GT(stats[0].value, 0);
    610 
    611   // Open new tabs to incur CPU usage.
    612   for (int i = 0; i < 10; ++i) {
    613     chrome::NavigateParams params(
    614         browser(), ui_test_utils::GetTestUrl(
    615                        base::FilePath(base::FilePath::kCurrentDirectory),
    616                        base::FilePath(FILE_PATH_LITERAL("title1.html"))),
    617         content::PAGE_TRANSITION_LINK);
    618     params.disposition = NEW_BACKGROUND_TAB;
    619     ui_test_utils::NavigateToURL(&params);
    620   }
    621   GatherStatistics();
    622 
    623   // One CPUUsage stat should exist now.
    624   stats = GetStats(METRIC_CPU_USAGE);
    625   ASSERT_EQ(1u, stats.size());
    626   EXPECT_GT(stats[0].value, 0);
    627 
    628   stats = GetStats(METRIC_PRIVATE_MEMORY_USAGE);
    629   ASSERT_EQ(2u, stats.size());
    630   EXPECT_GT(stats[1].value, 0);
    631 
    632   stats = GetStats(METRIC_SHARED_MEMORY_USAGE);
    633   ASSERT_EQ(2u, stats.size());
    634   EXPECT_GT(stats[1].value, 0);
    635 }
    636 
    637 // Disabled on other platforms because of flakiness: http://crbug.com/159172.
    638 #if !defined(OS_WIN)
    639 // Disabled on Windows due to a bug where Windows will return a normal exit
    640 // code in the testing environment, even if the process died (this is not the
    641 // case when hand-testing). This code can be traced to MSDN functions in
    642 // base::GetTerminationStatus(), so there's not much we can do.
    643 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest,
    644                        DISABLED_RendererKilledEvent) {
    645   content::CrashTab(browser()->tab_strip_model()->GetActiveWebContents());
    646 
    647   Database::EventVector events = GetEvents();
    648 
    649   ASSERT_EQ(1u, events.size());
    650   CheckEventType(EVENT_RENDERER_KILLED, events[0]);
    651 
    652   // Check the url - since we never went anywhere, this should be about:blank.
    653   std::string url;
    654   ASSERT_TRUE(events[0]->data()->GetString("url", &url));
    655   ASSERT_EQ("about:blank", url);
    656 }
    657 #endif  // !defined(OS_WIN)
    658 
    659 // TODO(jam): http://crbug.com/350550
    660 #if !(defined(OS_CHROMEOS) && defined(ADDRESS_SANITIZER))
    661 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, RendererCrashEvent) {
    662   content::RenderProcessHostWatcher observer(
    663       browser()->tab_strip_model()->GetActiveWebContents(),
    664       content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
    665 
    666   ui_test_utils::NavigateToURL(browser(), GURL(content::kChromeUICrashURL));
    667 
    668   observer.Wait();
    669 
    670   Database::EventVector events = GetEvents();
    671   ASSERT_EQ(1u, events.size());
    672 
    673   CheckEventType(EVENT_RENDERER_CRASH, events[0]);
    674 
    675   std::string url;
    676   ASSERT_TRUE(events[0]->data()->GetString("url", &url));
    677   ASSERT_EQ("chrome://crash/", url);
    678 }
    679 #endif
    680 
    681 IN_PROC_BROWSER_TEST_P(PerformanceMonitorUncleanExitBrowserTest,
    682                        OneProfileUncleanExit) {
    683   // Initialize the database value (if there's no value in the database, it
    684   // can't determine the last active time of the profile, and doesn't insert
    685   // the event).
    686   const std::string time = "12985807272597591";
    687   AddStateValue(kStateProfilePrefix + first_profile_name_, time);
    688 
    689   performance_monitor()->CheckForUncleanExits();
    690   content::RunAllPendingInMessageLoop();
    691 
    692   Database::EventVector events = GetEvents();
    693 
    694   const size_t kNumEvents = 1;
    695   ASSERT_EQ(kNumEvents, events.size());
    696 
    697   CheckEventType(EVENT_UNCLEAN_EXIT, events[0]);
    698 
    699   std::string event_profile;
    700   ASSERT_TRUE(events[0]->data()->GetString("profileName", &event_profile));
    701   ASSERT_EQ(first_profile_name_, event_profile);
    702 }
    703 
    704 IN_PROC_BROWSER_TEST_P(PerformanceMonitorUncleanExitBrowserTest,
    705                        TwoProfileUncleanExit) {
    706 #if defined(OS_CHROMEOS)
    707   AddSecondUserAccount();
    708 #endif
    709 
    710   base::FilePath second_profile_path;
    711   PathService::Get(chrome::DIR_USER_DATA, &second_profile_path);
    712   second_profile_path = second_profile_path.AppendASCII(second_profile_name_);
    713 
    714   const std::string time1 = "12985807272597591";
    715   const std::string time2 = "12985807272599918";
    716 
    717   // Initialize the database.
    718   AddStateValue(kStateProfilePrefix + first_profile_name_, time1);
    719   AddStateValue(kStateProfilePrefix + second_profile_name_, time2);
    720 
    721   performance_monitor()->CheckForUncleanExits();
    722   content::RunAllPendingInMessageLoop();
    723 
    724   // Load the second profile, which has also exited uncleanly. Note that since
    725   // the second profile is new, component extensions will be installed as part
    726   // of the browser startup for that profile, generating extra events.
    727   g_browser_process->profile_manager()->GetProfile(second_profile_path);
    728   content::RunAllPendingInMessageLoop();
    729 
    730   Database::EventVector events = GetEvents();
    731 
    732   const size_t kNumUncleanExitEvents = 2;
    733   size_t num_unclean_exit_events = 0;
    734   for (size_t i = 0; i < events.size(); ++i) {
    735     int event_type = -1;
    736     if (events[i]->data()->GetInteger("eventType", &event_type) &&
    737         event_type == EVENT_EXTENSION_INSTALL) {
    738       continue;
    739     }
    740     CheckEventType(EVENT_UNCLEAN_EXIT, events[i]);
    741     ++num_unclean_exit_events;
    742   }
    743   ASSERT_EQ(kNumUncleanExitEvents, num_unclean_exit_events);
    744 
    745   std::string event_profile;
    746   ASSERT_TRUE(events[0]->data()->GetString("profileName", &event_profile));
    747   ASSERT_EQ(first_profile_name_, event_profile);
    748 
    749   ASSERT_TRUE(events[1]->data()->GetString("profileName", &event_profile));
    750   ASSERT_EQ(second_profile_name_, event_profile);
    751 }
    752 
    753 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, StartupTime) {
    754   Database::MetricVector metrics = GetStats(METRIC_TEST_STARTUP_TIME);
    755 
    756   ASSERT_EQ(1u, metrics.size());
    757   ASSERT_LT(metrics[0].value, kMaxStartupTime.ToInternalValue());
    758 }
    759 
    760 IN_PROC_BROWSER_TEST_F(PerformanceMonitorSessionRestoreBrowserTest,
    761                        StartupWithSessionRestore) {
    762   ui_test_utils::NavigateToURL(
    763       browser(), ui_test_utils::GetTestUrl(
    764                      base::FilePath(base::FilePath::kCurrentDirectory),
    765                      base::FilePath(FILE_PATH_LITERAL("title1.html"))));
    766 
    767   QuitBrowserAndRestore(browser(), 1);
    768 
    769   Database::MetricVector metrics = GetStats(METRIC_TEST_STARTUP_TIME);
    770   ASSERT_EQ(1u, metrics.size());
    771   ASSERT_LT(metrics[0].value, kMaxStartupTime.ToInternalValue());
    772 
    773   metrics = GetStats(METRIC_SESSION_RESTORE_TIME);
    774   ASSERT_EQ(1u, metrics.size());
    775   ASSERT_LT(metrics[0].value, kMaxStartupTime.ToInternalValue());
    776 }
    777 
    778 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, PageLoadTime) {
    779   const base::TimeDelta kMaxLoadTime = base::TimeDelta::FromSeconds(30);
    780 
    781   ui_test_utils::NavigateToURL(
    782       browser(), ui_test_utils::GetTestUrl(
    783                      base::FilePath(base::FilePath::kCurrentDirectory),
    784                      base::FilePath(FILE_PATH_LITERAL("title1.html"))));
    785 
    786   ui_test_utils::NavigateToURL(
    787       browser(), ui_test_utils::GetTestUrl(
    788                      base::FilePath(base::FilePath::kCurrentDirectory),
    789                      base::FilePath(FILE_PATH_LITERAL("title1.html"))));
    790 
    791   Database::MetricVector metrics = GetStats(METRIC_PAGE_LOAD_TIME);
    792 
    793   ASSERT_EQ(2u, metrics.size());
    794   ASSERT_LT(metrics[0].value, kMaxLoadTime.ToInternalValue());
    795   ASSERT_LT(metrics[1].value, kMaxLoadTime.ToInternalValue());
    796 }
    797 
    798 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, NetworkBytesRead) {
    799   base::FilePath test_dir;
    800   PathService::Get(chrome::DIR_TEST_DATA, &test_dir);
    801 
    802   int64 page1_size = 0;
    803   ASSERT_TRUE(base::GetFileSize(test_dir.AppendASCII("title1.html"),
    804                                 &page1_size));
    805 
    806   int64 page2_size = 0;
    807   ASSERT_TRUE(base::GetFileSize(test_dir.AppendASCII("title2.html"),
    808                                 &page2_size));
    809 
    810   ASSERT_TRUE(test_server()->Start());
    811 
    812   ui_test_utils::NavigateToURL(
    813       browser(),
    814       test_server()->GetURL(std::string("files/").append("title1.html")));
    815 
    816   GatherStatistics();
    817 
    818   Database::MetricVector metrics = GetStats(METRIC_NETWORK_BYTES_READ);
    819   ASSERT_EQ(1u, metrics.size());
    820   // Since these pages are read over the "network" (actually the test_server),
    821   // some extraneous information is carried along, and the best check we can do
    822   // is for greater than or equal to.
    823   EXPECT_GE(metrics[0].value, page1_size);
    824 
    825   ui_test_utils::NavigateToURL(
    826       browser(),
    827       test_server()->GetURL(std::string("files/").append("title2.html")));
    828 
    829   GatherStatistics();
    830 
    831   metrics = GetStats(METRIC_NETWORK_BYTES_READ);
    832   ASSERT_EQ(2u, metrics.size());
    833   EXPECT_GE(metrics[1].value, page1_size + page2_size);
    834 }
    835 
    836 INSTANTIATE_TEST_CASE_P(PerformanceMonitorUncleanExitBrowserTestInstantiation,
    837                         PerformanceMonitorUncleanExitBrowserTest,
    838                         testing::Bool());
    839 
    840 }  // namespace performance_monitor
    841