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