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