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 = -1; |
| 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 // Create an observer to wait for the update to finish. |
| 233 ui_test_utils::WindowedNotificationObserver windowed_observer( |
| 234 chrome::NOTIFICATION_CRX_INSTALLER_DONE, |
| 235 content::Source<CrxInstaller>(crx_installer)); |
| 236 ASSERT_TRUE(extension_service-> |
| 237 UpdateExtension(extension->id(), path_v2_, GURL(), &crx_installer)); |
| 238 windowed_observer.Wait(); |
| 239 |
| 240 extension = extension_service->GetExtensionById( |
| 241 extension_infos[0].id, false); // don't include disabled extensions. |
| 242 |
| 243 // The total series of events for this process will be: |
| 244 // Extension Install - install version 1 |
| 245 // Extension Install - install version 2 |
| 246 // Extension Unload - disable version 1 |
| 247 // Extension Update - signal the udate to version 2 |
| 248 // We push back the corresponding ExtensionBasicInfos. |
| 249 extension_infos.push_back(ExtensionBasicInfo(extension)); |
| 250 extension_infos.push_back(extension_infos[0]); |
| 251 extension_infos.push_back(extension_infos[1]); |
| 252 |
| 253 std::vector<int> expected_event_types; |
| 254 expected_event_types.push_back(EVENT_EXTENSION_INSTALL); |
| 255 expected_event_types.push_back(EVENT_EXTENSION_INSTALL); |
| 256 expected_event_types.push_back(EVENT_EXTENSION_UNLOAD); |
| 257 expected_event_types.push_back(EVENT_EXTENSION_UPDATE); |
| 258 |
| 259 std::vector<linked_ptr<Event> > events = GetEvents(); |
| 260 |
| 261 CheckExtensionEvents(expected_event_types, extension_infos, events); |
| 262 |
| 263 // There will be an additional field: The unload reason. |
| 264 int unload_reason = -1; |
| 265 ASSERT_TRUE(events[2]->data()->GetInteger("unload_reason", &unload_reason)); |
| 266 ASSERT_EQ(extension_misc::UNLOAD_REASON_UPDATE, unload_reason); |
| 267 } |
| 268 |
| 269 } // namespace performance_monitor |
OLD | NEW |