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 |