Upstream version 7.36.149.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/common/extension.h"
44
45 #if defined(OS_CHROMEOS)
46 #include "chrome/browser/chromeos/login/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@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 (GetParam())
294       command_line->AppendSwitch(::switches::kMultiProfiles);
295   }
296
297   virtual bool SetUpUserDataDirectory() OVERRIDE {
298     base::FilePath user_data_directory;
299     PathService::Get(chrome::DIR_USER_DATA, &user_data_directory);
300
301     // On CrOS, if we are "logged in" with the --login-profile switch,
302     // the default profile will be different. We check if we are logged in, and,
303     // if we are, we use that profile name instead. (Note: trybots will
304     // typically be logged in with 'user'.)
305 #if defined(OS_CHROMEOS)
306     const CommandLine command_line = *CommandLine::ForCurrentProcess();
307     if (command_line.HasSwitch(chromeos::switches::kLoginProfile)) {
308       first_profile_name_ =
309           command_line.GetSwitchValueASCII(chromeos::switches::kLoginProfile);
310     } else {
311       first_profile_name_ = chrome::kInitialProfile;
312     }
313 #else
314     first_profile_name_ = chrome::kInitialProfile;
315 #endif
316
317     base::FilePath first_profile =
318         user_data_directory.AppendASCII(first_profile_name_);
319     CHECK(base::CreateDirectory(first_profile));
320
321     base::FilePath stock_prefs_file;
322     PathService::Get(chrome::DIR_TEST_DATA, &stock_prefs_file);
323     stock_prefs_file = stock_prefs_file.AppendASCII("performance_monitor")
324                                        .AppendASCII("unclean_exit_prefs");
325     CHECK(base::PathExists(stock_prefs_file));
326
327     base::FilePath first_profile_prefs_file =
328         first_profile.Append(chrome::kPreferencesFilename);
329     CHECK(base::CopyFile(stock_prefs_file, first_profile_prefs_file));
330     CHECK(base::PathExists(first_profile_prefs_file));
331
332     second_profile_name_ =
333         std::string(chrome::kMultiProfileDirPrefix)
334         .append(base::IntToString(1));
335 #if defined(OS_CHROMEOS)
336     if (GetParam()) {
337       second_profile_name_ = chromeos::ProfileHelper::GetUserProfileDir(
338           kSecondProfileHash).BaseName().value();
339     }
340 #endif
341
342     base::FilePath second_profile =
343         user_data_directory.AppendASCII(second_profile_name_);
344     CHECK(base::CreateDirectory(second_profile));
345
346     base::FilePath second_profile_prefs_file =
347         second_profile.Append(chrome::kPreferencesFilename);
348     CHECK(base::CopyFile(stock_prefs_file, second_profile_prefs_file));
349     CHECK(base::PathExists(second_profile_prefs_file));
350
351     return true;
352   }
353
354 #if defined(OS_CHROMEOS)
355   virtual void AddSecondUserAccount() {
356     // Add second user account for multi-profile test.
357     if (GetParam()) {
358       chromeos::UserManager::Get()->UserLoggedIn(kSecondProfileAccount,
359                                                  kSecondProfileHash,
360                                                  false);
361     }
362   }
363 #endif
364
365  protected:
366   std::string first_profile_name_;
367   std::string second_profile_name_;
368 };
369
370 class PerformanceMonitorSessionRestoreBrowserTest
371     : public PerformanceMonitorBrowserTest {
372  public:
373   virtual void SetUpOnMainThread() OVERRIDE {
374     SessionStartupPref pref(SessionStartupPref::LAST);
375     SessionStartupPref::SetStartupPref(browser()->profile(), pref);
376 #if defined(OS_CHROMEOS) || defined (OS_MACOSX)
377     // Undo the effect of kBrowserAliveWithNoWindows in defaults.cc so that we
378     // can get these test to work without quitting.
379     SessionServiceTestHelper helper(
380         SessionServiceFactory::GetForProfile(browser()->profile()));
381     helper.SetForceBrowserNotAliveWithNoWindows(true);
382     helper.ReleaseService();
383 #endif
384
385     PerformanceMonitorBrowserTest::SetUpOnMainThread();
386   }
387
388   Browser* QuitBrowserAndRestore(Browser* browser, int expected_tab_count) {
389     Profile* profile = browser->profile();
390
391     // Close the browser.
392     g_browser_process->AddRefModule();
393     content::WindowedNotificationObserver observer(
394         chrome::NOTIFICATION_BROWSER_CLOSED,
395         content::NotificationService::AllSources());
396     browser->window()->Close();
397 #if defined(OS_MACOSX)
398     // BrowserWindowController depends on the auto release pool being recycled
399     // in the message loop to delete itself, which frees the Browser object
400     // which fires this event.
401     AutoreleasePool()->Recycle();
402 #endif
403     observer.Wait();
404
405     // Create a new window, which should trigger session restore.
406     content::TestNavigationObserver restore_observer(NULL, expected_tab_count);
407     restore_observer.StartWatchingNewWebContents();
408     ui_test_utils::BrowserAddedObserver window_observer;
409     chrome::NewEmptyWindow(profile, chrome::GetActiveDesktop());
410     Browser* new_browser = window_observer.WaitForSingleNewBrowser();
411     restore_observer.Wait();
412     g_browser_process->ReleaseModule();
413
414     return new_browser;
415   }
416 };
417
418 // Test that PerformanceMonitor will correctly record an extension installation
419 // event.
420 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, InstallExtensionEvent) {
421   base::FilePath extension_path;
422   PathService::Get(chrome::DIR_TEST_DATA, &extension_path);
423   extension_path = extension_path.AppendASCII("performance_monitor")
424                                  .AppendASCII("extensions")
425                                  .AppendASCII("simple_extension_v1");
426   const Extension* extension = LoadExtension(extension_path);
427
428   std::vector<ExtensionBasicInfo> extension_infos;
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
434   Database::EventVector events = GetEvents();
435   CheckExtensionEvents(expected_event_types, events, extension_infos);
436 }
437
438 // Test that PerformanceMonitor will correctly record events as an extension is
439 // disabled and enabled.
440 // Test is falky, see http://crbug.com/157980
441 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest,
442                        DISABLED_DisableAndEnableExtensionEvent) {
443   const int kNumEvents = 3;
444
445   base::FilePath extension_path;
446   PathService::Get(chrome::DIR_TEST_DATA, &extension_path);
447   extension_path = extension_path.AppendASCII("performance_monitor")
448                                  .AppendASCII("extensions")
449                                  .AppendASCII("simple_extension_v1");
450   const Extension* extension = LoadExtension(extension_path);
451
452   DisableExtension(extension->id());
453   EnableExtension(extension->id());
454
455   std::vector<ExtensionBasicInfo> extension_infos;
456   // There will be three events in all, each pertaining to the same extension:
457   //   Extension Install
458   //   Extension Disable
459   //   Extension Enable
460   for (int i = 0; i < kNumEvents; ++i)
461     extension_infos.push_back(ExtensionBasicInfo(extension));
462
463   std::vector<int> expected_event_types;
464   expected_event_types.push_back(EVENT_EXTENSION_INSTALL);
465   expected_event_types.push_back(EVENT_EXTENSION_DISABLE);
466   expected_event_types.push_back(EVENT_EXTENSION_ENABLE);
467
468   Database::EventVector events = GetEvents();
469   CheckExtensionEvents(expected_event_types, events, extension_infos);
470 }
471
472 // Test that PerformanceMonitor correctly records an extension update event.
473 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, UpdateExtensionEvent) {
474   base::ScopedTempDir temp_dir;
475   ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
476
477   base::FilePath test_data_dir;
478   PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir);
479   test_data_dir = test_data_dir.AppendASCII("performance_monitor")
480                                .AppendASCII("extensions");
481
482   // We need two versions of the same extension.
483   base::FilePath pem_path = test_data_dir.AppendASCII("simple_extension.pem");
484   base::FilePath path_v1_ = PackExtensionWithOptions(
485       test_data_dir.AppendASCII("simple_extension_v1"),
486       temp_dir.path().AppendASCII("simple_extension1.crx"),
487       pem_path,
488       base::FilePath());
489   base::FilePath path_v2_ = PackExtensionWithOptions(
490       test_data_dir.AppendASCII("simple_extension_v2"),
491       temp_dir.path().AppendASCII("simple_extension2.crx"),
492       pem_path,
493       base::FilePath());
494
495   const extensions::Extension* extension = InstallExtension(path_v1_, 1);
496
497   std::vector<ExtensionBasicInfo> extension_infos;
498   extension_infos.push_back(ExtensionBasicInfo(extension));
499
500   ExtensionService* extension_service =
501       browser()->profile()->GetExtensionService();
502
503   extensions::CrxInstaller* crx_installer = NULL;
504
505   // Create an observer to wait for the update to finish.
506   content::WindowedNotificationObserver windowed_observer(
507       chrome::NOTIFICATION_CRX_INSTALLER_DONE,
508       content::Source<extensions::CrxInstaller>(crx_installer));
509   ASSERT_TRUE(extension_service->
510       UpdateExtension(extension->id(), path_v2_, true, &crx_installer));
511   windowed_observer.Wait();
512
513   extension = extension_service->GetExtensionById(
514       extension_infos[0].id, false); // don't include disabled extensions.
515
516   // The total series of events for this process will be:
517   //   Extension Install - install version 1
518   //   Extension Install - install version 2
519   //   Extension Update  - signal the udate to version 2
520   // We push back the corresponding ExtensionBasicInfos.
521   extension_infos.push_back(ExtensionBasicInfo(extension));
522   extension_infos.push_back(extension_infos[1]);
523
524   std::vector<int> expected_event_types;
525   expected_event_types.push_back(EVENT_EXTENSION_INSTALL);
526   expected_event_types.push_back(EVENT_EXTENSION_INSTALL);
527   expected_event_types.push_back(EVENT_EXTENSION_UPDATE);
528
529   Database::EventVector events = GetEvents();
530
531   CheckExtensionEvents(expected_event_types, events, extension_infos);
532 }
533
534 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, UninstallExtensionEvent) {
535   const int kNumEvents = 2;
536   base::FilePath extension_path;
537   PathService::Get(chrome::DIR_TEST_DATA, &extension_path);
538   extension_path = extension_path.AppendASCII("performance_monitor")
539                                  .AppendASCII("extensions")
540                                  .AppendASCII("simple_extension_v1");
541   const Extension* extension = LoadExtension(extension_path);
542
543   std::vector<ExtensionBasicInfo> extension_infos;
544   // There will be two events, both pertaining to the same extension:
545   //   Extension Install
546   //   Extension Uninstall
547   for (int i = 0; i < kNumEvents; ++i)
548     extension_infos.push_back(ExtensionBasicInfo(extension));
549
550   UninstallExtension(extension->id());
551
552   std::vector<int> expected_event_types;
553   expected_event_types.push_back(EVENT_EXTENSION_INSTALL);
554   expected_event_types.push_back(EVENT_EXTENSION_UNINSTALL);
555
556   Database::EventVector events = GetEvents();
557
558   CheckExtensionEvents(expected_event_types, events, extension_infos);
559 }
560
561 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, NewVersionEvent) {
562   const char kOldVersion[] = "0.0";
563
564   // The version in the database right now will be the current version of chrome
565   // (gathered at initialization of PerformanceMonitor). Replace this with an
566   // older version so an event is generated.
567   AddStateValue(kStateChromeVersion, kOldVersion);
568
569   CheckForVersionUpdate();
570
571   chrome::VersionInfo version;
572   ASSERT_TRUE(version.is_valid());
573   std::string version_string = version.Version();
574
575   Database::EventVector events = GetEvents();
576   ASSERT_EQ(1u, events.size());
577   ASSERT_EQ(EVENT_CHROME_UPDATE, events[0]->type());
578
579   const base::DictionaryValue* value;
580   ASSERT_TRUE(events[0]->data()->GetAsDictionary(&value));
581
582   std::string previous_version;
583   std::string current_version;
584
585   ASSERT_TRUE(value->GetString("previousVersion", &previous_version));
586   ASSERT_EQ(kOldVersion, previous_version);
587   ASSERT_TRUE(value->GetString("currentVersion", &current_version));
588   ASSERT_EQ(version_string, current_version);
589 }
590
591 // crbug.com/160502
592 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest,
593                        DISABLED_GatherStatistics) {
594   GatherStatistics();
595
596   // No stats should be recorded for this CPUUsage because this was the first
597   // call to GatherStatistics.
598   Database::MetricVector stats = GetStats(METRIC_CPU_USAGE);
599   ASSERT_EQ(0u, stats.size());
600
601   stats = GetStats(METRIC_PRIVATE_MEMORY_USAGE);
602   ASSERT_EQ(1u, stats.size());
603   EXPECT_GT(stats[0].value, 0);
604
605   stats = GetStats(METRIC_SHARED_MEMORY_USAGE);
606   ASSERT_EQ(1u, stats.size());
607   EXPECT_GT(stats[0].value, 0);
608
609   // Open new tabs to incur CPU usage.
610   for (int i = 0; i < 10; ++i) {
611     chrome::NavigateParams params(
612         browser(), ui_test_utils::GetTestUrl(
613                        base::FilePath(base::FilePath::kCurrentDirectory),
614                        base::FilePath(FILE_PATH_LITERAL("title1.html"))),
615         content::PAGE_TRANSITION_LINK);
616     params.disposition = NEW_BACKGROUND_TAB;
617     ui_test_utils::NavigateToURL(&params);
618   }
619   GatherStatistics();
620
621   // One CPUUsage stat should exist now.
622   stats = GetStats(METRIC_CPU_USAGE);
623   ASSERT_EQ(1u, stats.size());
624   EXPECT_GT(stats[0].value, 0);
625
626   stats = GetStats(METRIC_PRIVATE_MEMORY_USAGE);
627   ASSERT_EQ(2u, stats.size());
628   EXPECT_GT(stats[1].value, 0);
629
630   stats = GetStats(METRIC_SHARED_MEMORY_USAGE);
631   ASSERT_EQ(2u, stats.size());
632   EXPECT_GT(stats[1].value, 0);
633 }
634
635 // Disabled on other platforms because of flakiness: http://crbug.com/159172.
636 #if !defined(OS_WIN)
637 // Disabled on Windows due to a bug where Windows will return a normal exit
638 // code in the testing environment, even if the process died (this is not the
639 // case when hand-testing). This code can be traced to MSDN functions in
640 // base::GetTerminationStatus(), so there's not much we can do.
641 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest,
642                        DISABLED_RendererKilledEvent) {
643   content::CrashTab(browser()->tab_strip_model()->GetActiveWebContents());
644
645   Database::EventVector events = GetEvents();
646
647   ASSERT_EQ(1u, events.size());
648   CheckEventType(EVENT_RENDERER_KILLED, events[0]);
649
650   // Check the url - since we never went anywhere, this should be about:blank.
651   std::string url;
652   ASSERT_TRUE(events[0]->data()->GetString("url", &url));
653   ASSERT_EQ("about:blank", url);
654 }
655 #endif  // !defined(OS_WIN)
656
657 // TODO(jam): http://crbug.com/350550
658 #if !(defined(OS_CHROMEOS) && defined(ADDRESS_SANITIZER))
659 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, RendererCrashEvent) {
660   content::RenderProcessHostWatcher observer(
661       browser()->tab_strip_model()->GetActiveWebContents(),
662       content::RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT);
663
664   ui_test_utils::NavigateToURL(browser(), GURL(content::kChromeUICrashURL));
665
666   observer.Wait();
667
668   Database::EventVector events = GetEvents();
669   ASSERT_EQ(1u, events.size());
670
671   CheckEventType(EVENT_RENDERER_CRASH, events[0]);
672
673   std::string url;
674   ASSERT_TRUE(events[0]->data()->GetString("url", &url));
675   ASSERT_EQ("chrome://crash/", url);
676 }
677 #endif
678
679 IN_PROC_BROWSER_TEST_P(PerformanceMonitorUncleanExitBrowserTest,
680                        OneProfileUncleanExit) {
681   // Initialize the database value (if there's no value in the database, it
682   // can't determine the last active time of the profile, and doesn't insert
683   // the event).
684   const std::string time = "12985807272597591";
685   AddStateValue(kStateProfilePrefix + first_profile_name_, time);
686
687   performance_monitor()->CheckForUncleanExits();
688   content::RunAllPendingInMessageLoop();
689
690   Database::EventVector events = GetEvents();
691
692   const size_t kNumEvents = 1;
693   ASSERT_EQ(kNumEvents, events.size());
694
695   CheckEventType(EVENT_UNCLEAN_EXIT, events[0]);
696
697   std::string event_profile;
698   ASSERT_TRUE(events[0]->data()->GetString("profileName", &event_profile));
699   ASSERT_EQ(first_profile_name_, event_profile);
700 }
701
702 IN_PROC_BROWSER_TEST_P(PerformanceMonitorUncleanExitBrowserTest,
703                        TwoProfileUncleanExit) {
704 #if defined(OS_CHROMEOS)
705   AddSecondUserAccount();
706 #endif
707
708   base::FilePath second_profile_path;
709   PathService::Get(chrome::DIR_USER_DATA, &second_profile_path);
710   second_profile_path = second_profile_path.AppendASCII(second_profile_name_);
711
712   const std::string time1 = "12985807272597591";
713   const std::string time2 = "12985807272599918";
714
715   // Initialize the database.
716   AddStateValue(kStateProfilePrefix + first_profile_name_, time1);
717   AddStateValue(kStateProfilePrefix + second_profile_name_, time2);
718
719   performance_monitor()->CheckForUncleanExits();
720   content::RunAllPendingInMessageLoop();
721
722   // Load the second profile, which has also exited uncleanly. Note that since
723   // the second profile is new, component extensions will be installed as part
724   // of the browser startup for that profile, generating extra events.
725   g_browser_process->profile_manager()->GetProfile(second_profile_path);
726   content::RunAllPendingInMessageLoop();
727
728   Database::EventVector events = GetEvents();
729
730   const size_t kNumUncleanExitEvents = 2;
731   size_t num_unclean_exit_events = 0;
732   for (size_t i = 0; i < events.size(); ++i) {
733     int event_type = -1;
734     if (events[i]->data()->GetInteger("eventType", &event_type) &&
735         event_type == EVENT_EXTENSION_INSTALL) {
736       continue;
737     }
738     CheckEventType(EVENT_UNCLEAN_EXIT, events[i]);
739     ++num_unclean_exit_events;
740   }
741   ASSERT_EQ(kNumUncleanExitEvents, num_unclean_exit_events);
742
743   std::string event_profile;
744   ASSERT_TRUE(events[0]->data()->GetString("profileName", &event_profile));
745   ASSERT_EQ(first_profile_name_, event_profile);
746
747   ASSERT_TRUE(events[1]->data()->GetString("profileName", &event_profile));
748   ASSERT_EQ(second_profile_name_, event_profile);
749 }
750
751 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, StartupTime) {
752   Database::MetricVector metrics = GetStats(METRIC_TEST_STARTUP_TIME);
753
754   ASSERT_EQ(1u, metrics.size());
755   ASSERT_LT(metrics[0].value, kMaxStartupTime.ToInternalValue());
756 }
757
758 IN_PROC_BROWSER_TEST_F(PerformanceMonitorSessionRestoreBrowserTest,
759                        StartupWithSessionRestore) {
760   ui_test_utils::NavigateToURL(
761       browser(), ui_test_utils::GetTestUrl(
762                      base::FilePath(base::FilePath::kCurrentDirectory),
763                      base::FilePath(FILE_PATH_LITERAL("title1.html"))));
764
765   QuitBrowserAndRestore(browser(), 1);
766
767   Database::MetricVector metrics = GetStats(METRIC_TEST_STARTUP_TIME);
768   ASSERT_EQ(1u, metrics.size());
769   ASSERT_LT(metrics[0].value, kMaxStartupTime.ToInternalValue());
770
771   metrics = GetStats(METRIC_SESSION_RESTORE_TIME);
772   ASSERT_EQ(1u, metrics.size());
773   ASSERT_LT(metrics[0].value, kMaxStartupTime.ToInternalValue());
774 }
775
776 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, PageLoadTime) {
777   const base::TimeDelta kMaxLoadTime = base::TimeDelta::FromSeconds(30);
778
779   ui_test_utils::NavigateToURL(
780       browser(), ui_test_utils::GetTestUrl(
781                      base::FilePath(base::FilePath::kCurrentDirectory),
782                      base::FilePath(FILE_PATH_LITERAL("title1.html"))));
783
784   ui_test_utils::NavigateToURL(
785       browser(), ui_test_utils::GetTestUrl(
786                      base::FilePath(base::FilePath::kCurrentDirectory),
787                      base::FilePath(FILE_PATH_LITERAL("title1.html"))));
788
789   Database::MetricVector metrics = GetStats(METRIC_PAGE_LOAD_TIME);
790
791   ASSERT_EQ(2u, metrics.size());
792   ASSERT_LT(metrics[0].value, kMaxLoadTime.ToInternalValue());
793   ASSERT_LT(metrics[1].value, kMaxLoadTime.ToInternalValue());
794 }
795
796 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, NetworkBytesRead) {
797   base::FilePath test_dir;
798   PathService::Get(chrome::DIR_TEST_DATA, &test_dir);
799
800   int64 page1_size = 0;
801   ASSERT_TRUE(base::GetFileSize(test_dir.AppendASCII("title1.html"),
802                                 &page1_size));
803
804   int64 page2_size = 0;
805   ASSERT_TRUE(base::GetFileSize(test_dir.AppendASCII("title2.html"),
806                                 &page2_size));
807
808   ASSERT_TRUE(test_server()->Start());
809
810   ui_test_utils::NavigateToURL(
811       browser(),
812       test_server()->GetURL(std::string("files/").append("title1.html")));
813
814   GatherStatistics();
815
816   Database::MetricVector metrics = GetStats(METRIC_NETWORK_BYTES_READ);
817   ASSERT_EQ(1u, metrics.size());
818   // Since these pages are read over the "network" (actually the test_server),
819   // some extraneous information is carried along, and the best check we can do
820   // is for greater than or equal to.
821   EXPECT_GE(metrics[0].value, page1_size);
822
823   ui_test_utils::NavigateToURL(
824       browser(),
825       test_server()->GetURL(std::string("files/").append("title2.html")));
826
827   GatherStatistics();
828
829   metrics = GetStats(METRIC_NETWORK_BYTES_READ);
830   ASSERT_EQ(2u, metrics.size());
831   EXPECT_GE(metrics[1].value, page1_size + page2_size);
832 }
833
834 INSTANTIATE_TEST_CASE_P(PerformanceMonitorUncleanExitBrowserTestInstantiation,
835                         PerformanceMonitorUncleanExitBrowserTest,
836                         testing::Bool());
837
838 }  // namespace performance_monitor