Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2010 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 "chrome/test/base/in_process_browser_test.h" | |
| 6 | |
| 7 #include "base/file_path.h" | |
| 8 #include "base/logging.h" | |
| 9 #include "base/path_service.h" | |
| 10 #include "base/threading/sequenced_worker_pool.h" | |
| 11 #include "chrome/browser/performance_monitor/database.h" | |
| 12 #include "chrome/browser/performance_monitor/performance_monitor.h" | |
| 13 #include "chrome/browser/extensions/extension_browsertest.h" | |
| 14 #include "chrome/browser/extensions/extension_service.h" | |
| 15 #include "chrome/browser/extensions/unpacked_installer.h" | |
| 16 #include "chrome/browser/profiles/profile.h" | |
| 17 #include "chrome/browser/ui/browser.h" | |
| 18 #include "chrome/common/chrome_notification_types.h" | |
| 19 #include "chrome/common/chrome_paths.h" | |
| 20 #include "chrome/common/extensions/extension.h" | |
| 21 #include "chrome/test/base/ui_test_utils.h" | |
| 22 #include "content/public/browser/notification_registrar.h" | |
| 23 #include "content/public/browser/notification_service.h" | |
| 24 | |
| 25 using extensions::Extension; | |
| 26 using performance_monitor::Event; | |
| 27 | |
| 28 namespace { | |
| 29 | |
| 30 // Helper struct to store the information of an extension; this is needed if the | |
| 31 // pointer to the extension ever becomes invalid (e.g., if we uninstall the | |
| 32 // extension). | |
| 33 struct ExtensionBasicInfo { | |
| 34 // Empty constructor for stl-container-happiness. | |
| 35 ExtensionBasicInfo() { | |
| 36 } | |
| 37 explicit ExtensionBasicInfo(const Extension* extension) | |
| 38 : description(extension->description()), | |
| 39 id(extension->id()), | |
| 40 name(extension->name()), | |
| 41 url(extension->url().spec()), | |
| 42 version(extension->VersionString()), | |
| 43 location(extension->location()) { | |
| 44 } | |
| 45 | |
| 46 std::string description; | |
| 47 std::string id; | |
| 48 std::string name; | |
| 49 std::string url; | |
| 50 std::string version; | |
| 51 Extension::Location location; | |
| 52 }; | |
| 53 | |
| 54 // Compare the fields of |extension| to those in |value|; this is a check to | |
| 55 // make sure the extension data was recorded properly in the event. | |
| 56 void ValidateExtensionInfo(const ExtensionBasicInfo extension, | |
| 57 const DictionaryValue* value) { | |
| 58 std::string extension_description; | |
| 59 std::string extension_id; | |
| 60 std::string extension_name; | |
| 61 std::string extension_url; | |
| 62 std::string extension_version; | |
| 63 int extension_location; | |
| 64 | |
| 65 ASSERT_TRUE(value->GetString("extension_description", | |
| 66 &extension_description)); | |
| 67 ASSERT_EQ(extension.description, extension_description); | |
| 68 ASSERT_TRUE(value->GetString("extension_id", &extension_id)); | |
| 69 ASSERT_EQ(extension.id, extension_id); | |
| 70 ASSERT_TRUE(value->GetString("extension_name", &extension_name)); | |
| 71 ASSERT_EQ(extension.name, extension_name); | |
| 72 ASSERT_TRUE(value->GetString("extension_url", &extension_url)); | |
| 73 ASSERT_EQ(extension.url, extension_url); | |
| 74 ASSERT_TRUE(value->GetString("extension_version", &extension_version)); | |
| 75 ASSERT_EQ(extension.version, extension_version); | |
| 76 ASSERT_TRUE(value->GetInteger("extension_location", &extension_location)); | |
| 77 ASSERT_EQ(extension.location, extension_location); | |
| 78 } | |
| 79 | |
| 80 // Check that we received the proper number of events, that each event is of the | |
| 81 // proper type, and that each event recorded the proper information about the | |
| 82 // extension. | |
| 83 void CheckExtensionEvents(std::vector<int> expected_event_types, | |
| 84 std::vector<ExtensionBasicInfo> extension_infos, | |
| 85 const std::vector<linked_ptr<Event> >& events) { | |
| 86 ASSERT_EQ(expected_event_types.size(), events.size()); | |
| 87 | |
| 88 for (size_t i = 0; i < expected_event_types.size(); ++i) { | |
| 89 ValidateExtensionInfo(extension_infos[i], events[i]->data()); | |
| 90 int event_type; | |
| 91 ASSERT_TRUE(events[i]->data()->GetInteger("type", &event_type)); | |
| 92 ASSERT_EQ(expected_event_types[i], event_type); | |
| 93 } | |
| 94 } | |
| 95 | |
| 96 } // namespace | |
| 97 | |
| 98 namespace performance_monitor { | |
| 99 | |
| 100 class PerformanceMonitorBrowserTest : public ExtensionBrowserTest { | |
| 101 public: | |
| 102 virtual void SetUpOnMainThread() { | |
| 103 CHECK(db_dir_.CreateUniqueTempDir()); | |
| 104 performance_monitor_ = PerformanceMonitor::GetInstance(); | |
| 105 performance_monitor_->SetDatabasePath(db_dir_.path()); | |
| 106 performance_monitor_->Start(); | |
| 107 | |
| 108 // Wait for DB to finish setting up. | |
| 109 content::BrowserThread::GetBlockingPool()->FlushForTesting(); | |
| 110 } | |
| 111 | |
| 112 void GetEventsOnBackgroundThread(std::vector<linked_ptr<Event> >* events) { | |
| 113 *events = performance_monitor_->database()->GetEvents(); | |
| 114 } | |
| 115 | |
| 116 // A handle for getting the events from the database, which must be done on | |
| 117 // the background thread. Since we are testing, we can mock synchronicity | |
| 118 // with FlushForTesting(). | |
| 119 std::vector<linked_ptr<Event> > GetEvents() { | |
| 120 std::vector<linked_ptr<Event> > events; | |
| 121 content::BrowserThread::PostBlockingPoolSequencedTask( | |
| 122 Database::kDatabaseSequenceToken, | |
| 123 FROM_HERE, | |
| 124 base::Bind(&PerformanceMonitorBrowserTest::GetEventsOnBackgroundThread, | |
| 125 base::Unretained(this), | |
| 126 &events)); | |
| 127 | |
| 128 content::BrowserThread::GetBlockingPool()->FlushForTesting(); | |
| 129 return events; | |
| 130 } | |
| 131 | |
| 132 PerformanceMonitor* performance_monitor() const { | |
| 133 return performance_monitor_; | |
| 134 } | |
| 135 | |
| 136 protected: | |
| 137 ScopedTempDir db_dir_; | |
| 138 PerformanceMonitor* performance_monitor_; | |
| 139 }; | |
| 140 | |
| 141 // Test that PerformanceMonitor will correctly record an extension installation | |
| 142 // event. | |
| 143 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, InstallExtensionEvent) { | |
| 144 FilePath extension_path; | |
| 145 PathService::Get(chrome::DIR_TEST_DATA, &extension_path); | |
| 146 extension_path = extension_path.AppendASCII("performance_monitor") | |
| 147 .AppendASCII("extensions") | |
| 148 .AppendASCII("simple_extension_v1"); | |
| 149 const Extension* extension = LoadExtension(extension_path); | |
| 150 | |
| 151 std::vector<ExtensionBasicInfo> extension_infos; | |
| 152 extension_infos.push_back(ExtensionBasicInfo(extension)); | |
| 153 | |
| 154 std::vector<int> expected_event_types; | |
| 155 expected_event_types.push_back(EVENT_EXTENSION_INSTALL); | |
| 156 | |
| 157 std::vector<linked_ptr<Event> > events = GetEvents(); | |
| 158 CheckExtensionEvents(expected_event_types, extension_infos, events); | |
| 159 } | |
| 160 | |
| 161 // Test that PerformanceMonitor will correctly record events as an extension is | |
| 162 // disabled and enabled. | |
| 163 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, | |
| 164 DisableAndEnableExtensionEvent) { | |
| 165 const int kNumEvents = 3; | |
| 166 | |
| 167 FilePath extension_path; | |
| 168 PathService::Get(chrome::DIR_TEST_DATA, &extension_path); | |
| 169 extension_path = extension_path.AppendASCII("performance_monitor") | |
| 170 .AppendASCII("extensions") | |
| 171 .AppendASCII("simple_extension_v1"); | |
| 172 const Extension* extension = LoadExtension(extension_path); | |
| 173 | |
| 174 DisableExtension(extension->id()); | |
| 175 EnableExtension(extension->id()); | |
| 176 | |
| 177 std::vector<ExtensionBasicInfo> extension_infos; | |
| 178 // There will be three events in all, each pertaining to the same extension: | |
| 179 // Extension Install | |
| 180 // Extension Unload | |
| 181 // Extension Enable | |
| 182 for (int i = 0; i < kNumEvents; ++i) | |
| 183 extension_infos.push_back(ExtensionBasicInfo(extension)); | |
| 184 | |
| 185 std::vector<int> expected_event_types; | |
| 186 expected_event_types.push_back(EVENT_EXTENSION_INSTALL); | |
| 187 expected_event_types.push_back(EVENT_EXTENSION_UNLOAD); | |
| 188 expected_event_types.push_back(EVENT_EXTENSION_ENABLE); | |
| 189 | |
| 190 std::vector<linked_ptr<Event> > events = GetEvents(); | |
| 191 CheckExtensionEvents(expected_event_types, extension_infos, events); | |
| 192 | |
| 193 // There will be an additional field on the unload event: Unload Reason. | |
| 194 int unload_reason = 0; | |
|
Yoyo Zhou
2012/06/27 21:55:51
nit: Maybe -1 is better as a known invalid value (
Devlin
2012/06/27 22:25:35
Done.
| |
| 195 ASSERT_TRUE(events[1]->data()->GetInteger("unload_reason", &unload_reason)); | |
| 196 ASSERT_EQ(extension_misc::UNLOAD_REASON_DISABLE, unload_reason); | |
| 197 } | |
| 198 | |
| 199 // Test that PerformanceMonitor correctly records an extension update event. | |
| 200 IN_PROC_BROWSER_TEST_F(PerformanceMonitorBrowserTest, UpdateExtensionEvent) { | |
| 201 ScopedTempDir temp_dir; | |
| 202 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); | |
| 203 | |
| 204 FilePath test_data_dir; | |
| 205 PathService::Get(chrome::DIR_TEST_DATA, &test_data_dir); | |
| 206 test_data_dir = test_data_dir.AppendASCII("performance_monitor") | |
| 207 .AppendASCII("extensions"); | |
| 208 | |
| 209 // We need two versions of the same extension. | |
| 210 FilePath pem_path = test_data_dir.AppendASCII("simple_extension.pem"); | |
| 211 FilePath path_v1_ = PackExtensionWithOptions( | |
| 212 test_data_dir.AppendASCII("simple_extension_v1"), | |
| 213 temp_dir.path().AppendASCII("simple_extension1.crx"), | |
| 214 pem_path, | |
| 215 FilePath()); | |
| 216 FilePath path_v2_ = PackExtensionWithOptions( | |
| 217 test_data_dir.AppendASCII("simple_extension_v2"), | |
| 218 temp_dir.path().AppendASCII("simple_extension2.crx"), | |
| 219 pem_path, | |
| 220 FilePath()); | |
| 221 | |
| 222 const extensions::Extension* extension = InstallExtension(path_v1_, 1); | |
| 223 | |
| 224 std::vector<ExtensionBasicInfo> extension_infos; | |
| 225 extension_infos.push_back(ExtensionBasicInfo(extension)); | |
| 226 | |
| 227 ExtensionService* extension_service = | |
| 228 browser()->profile()->GetExtensionService(); | |
| 229 | |
| 230 CrxInstaller* crx_installer = NULL; | |
| 231 | |
| 232 // Observe implementation in ExtensionBrowserTest; this will exit the loop | |
|
Yoyo Zhou
2012/06/27 21:55:51
nit: no longer explicitly running a message loop h
Devlin
2012/06/27 22:25:35
Done.
| |
| 233 // upon receipt of the notification. | |
| 234 ui_test_utils::WindowedNotificationObserver windowed_observer( | |
| 235 chrome::NOTIFICATION_CRX_INSTALLER_DONE, | |
| 236 content::Source<CrxInstaller>(crx_installer)); | |
| 237 ASSERT_TRUE(extension_service-> | |
| 238 UpdateExtension(extension->id(), path_v2_, GURL(), &crx_installer)); | |
| 239 windowed_observer.Wait(); | |
| 240 | |
| 241 extension = extension_service->GetExtensionById( | |
| 242 extension_infos[0].id, false); // don't include disabled extensions. | |
| 243 | |
| 244 // The total series of events for this process will be: | |
| 245 // Extension Install - install version 1 | |
| 246 // Extension Install - install version 2 | |
| 247 // Extension Unload - disable version 1 | |
| 248 // Extension Update - signal the udate to version 2 | |
| 249 // We push back the corresponding ExtensionBasicInfos. | |
| 250 extension_infos.push_back(ExtensionBasicInfo(extension)); | |
| 251 extension_infos.push_back(extension_infos[0]); | |
| 252 extension_infos.push_back(extension_infos[1]); | |
| 253 | |
| 254 std::vector<int> expected_event_types; | |
| 255 expected_event_types.push_back(EVENT_EXTENSION_INSTALL); | |
| 256 expected_event_types.push_back(EVENT_EXTENSION_INSTALL); | |
| 257 expected_event_types.push_back(EVENT_EXTENSION_UNLOAD); | |
| 258 expected_event_types.push_back(EVENT_EXTENSION_UPDATE); | |
| 259 | |
| 260 std::vector<linked_ptr<Event> > events = GetEvents(); | |
| 261 | |
| 262 CheckExtensionEvents(expected_event_types, extension_infos, events); | |
| 263 | |
| 264 // There will be an additional field: The unload reason. | |
| 265 int unload_reason = 0; | |
| 266 ASSERT_TRUE(events[2]->data()->GetInteger("unload_reason", &unload_reason)); | |
| 267 ASSERT_EQ(extension_misc::UNLOAD_REASON_UPDATE, unload_reason); | |
| 268 } | |
| 269 | |
| 270 } // namespace performance_monitor | |
| OLD | NEW |