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", ¤t_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(¶ms); 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