1 // Copyright (c) 2011 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.
5 #include "chrome/browser/extensions/extension_browsertest.h"
6 #include "chrome/browser/extensions/extension_toolbar_model.h"
7 #include "chrome/browser/profiles/profile.h"
8 #include "chrome/browser/ui/browser.h"
9 #include "chrome/test/base/in_process_browser_test.h"
11 using extensions::Extension
;
13 // An InProcessBrowserTest for testing the ExtensionToolbarModel.
14 // TODO(erikkay) It's unfortunate that this needs to be an in-proc browser test.
15 // It would be nice to refactor things so that ExtensionService could run
16 // without so much of the browser in place.
17 class ExtensionToolbarModelTest
: public ExtensionBrowserTest
,
18 public ExtensionToolbarModel::Observer
{
20 virtual void SetUp() {
25 ExtensionBrowserTest::SetUp();
28 virtual void SetUpOnMainThread() OVERRIDE
{
29 model_
= ExtensionToolbarModel::Get(browser()->profile());
30 model_
->AddObserver(this);
33 virtual void CleanUpOnMainThread() OVERRIDE
{
34 model_
->RemoveObserver(this);
37 virtual void BrowserActionAdded(const Extension
* extension
,
42 virtual void BrowserActionRemoved(const Extension
* extension
) OVERRIDE
{
46 virtual void BrowserActionMoved(const Extension
* extension
,
51 const Extension
* ExtensionAt(int index
) {
52 const extensions::ExtensionList
& toolbar_items
= model_
->toolbar_items();
53 for (extensions::ExtensionList::const_iterator i
= toolbar_items
.begin();
54 i
< toolbar_items
.end(); ++i
) {
62 ExtensionToolbarModel
* model_
;
69 IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest
, Basic
) {
70 // Load an extension with no browser action.
71 ASSERT_TRUE(LoadExtension(test_data_dir_
.AppendASCII("api_test")
72 .AppendASCII("browser_action")
73 .AppendASCII("none")));
75 // This extension should not be in the model (has no browser action).
76 EXPECT_EQ(0, inserted_count_
);
77 EXPECT_EQ(0u, model_
->toolbar_items().size());
78 ASSERT_EQ(NULL
, ExtensionAt(0));
80 // Load an extension with a browser action.
81 ASSERT_TRUE(LoadExtension(test_data_dir_
.AppendASCII("api_test")
82 .AppendASCII("browser_action")
83 .AppendASCII("basics")));
85 // We should now find our extension in the model.
86 EXPECT_EQ(1, inserted_count_
);
87 EXPECT_EQ(1u, model_
->toolbar_items().size());
88 const Extension
* extension
= ExtensionAt(0);
89 ASSERT_TRUE(NULL
!= extension
);
90 EXPECT_STREQ("A browser action with no icon that makes the page red",
91 extension
->name().c_str());
93 // Should be a no-op, but still fires the events.
94 model_
->MoveBrowserAction(extension
, 0);
95 EXPECT_EQ(1, moved_count_
);
96 EXPECT_EQ(1u, model_
->toolbar_items().size());
97 const Extension
* extension2
= ExtensionAt(0);
98 EXPECT_EQ(extension
, extension2
);
100 UnloadExtension(extension
->id());
101 EXPECT_EQ(1, removed_count_
);
102 EXPECT_EQ(0u, model_
->toolbar_items().size());
103 EXPECT_EQ(NULL
, ExtensionAt(0));
106 #if defined(OS_MACOSX)
107 // Flaky on Mac 10.8 Blink canary bots: http://crbug.com/166580
108 #define MAYBE_ReorderAndReinsert DISABLED_ReorderAndReinsert
110 #define MAYBE_ReorderAndReinsert ReorderAndReinsert
112 IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest
, MAYBE_ReorderAndReinsert
) {
113 // Load an extension with a browser action.
114 base::FilePath
extension_a_path(test_data_dir_
.AppendASCII("api_test")
115 .AppendASCII("browser_action")
116 .AppendASCII("basics"));
117 ASSERT_TRUE(LoadExtension(extension_a_path
));
119 // First extension loaded.
120 EXPECT_EQ(1, inserted_count_
);
121 EXPECT_EQ(1u, model_
->toolbar_items().size());
122 const Extension
* extensionA
= ExtensionAt(0);
123 ASSERT_TRUE(NULL
!= extensionA
);
124 EXPECT_STREQ("A browser action with no icon that makes the page red",
125 extensionA
->name().c_str());
127 // Load another extension with a browser action.
128 base::FilePath
extension_b_path(test_data_dir_
.AppendASCII("api_test")
129 .AppendASCII("browser_action")
130 .AppendASCII("popup"));
131 ASSERT_TRUE(LoadExtension(extension_b_path
));
133 // Second extension loaded.
134 EXPECT_EQ(2, inserted_count_
);
135 EXPECT_EQ(2u, model_
->toolbar_items().size());
136 const Extension
* extensionB
= ExtensionAt(1);
137 ASSERT_TRUE(NULL
!= extensionB
);
138 EXPECT_STREQ("Popup tester", extensionB
->name().c_str());
140 // Load yet another extension with a browser action.
141 base::FilePath
extension_c_path(test_data_dir_
.AppendASCII("api_test")
142 .AppendASCII("browser_action")
143 .AppendASCII("remove_popup"));
144 ASSERT_TRUE(LoadExtension(extension_c_path
));
146 // Third extension loaded.
147 EXPECT_EQ(3, inserted_count_
);
148 EXPECT_EQ(3u, model_
->toolbar_items().size());
149 const Extension
* extensionC
= ExtensionAt(2);
150 ASSERT_TRUE(NULL
!= extensionC
);
151 EXPECT_STREQ("A page action which removes a popup.",
152 extensionC
->name().c_str());
154 // Order is now A, B, C. Let's put C first.
155 model_
->MoveBrowserAction(extensionC
, 0);
156 EXPECT_EQ(1, moved_count_
);
157 EXPECT_EQ(3u, model_
->toolbar_items().size());
158 EXPECT_EQ(extensionC
, ExtensionAt(0));
159 EXPECT_EQ(extensionA
, ExtensionAt(1));
160 EXPECT_EQ(extensionB
, ExtensionAt(2));
161 EXPECT_EQ(NULL
, ExtensionAt(3));
163 // Order is now C, A, B. Let's put A last.
164 model_
->MoveBrowserAction(extensionA
, 2);
165 EXPECT_EQ(2, moved_count_
);
166 EXPECT_EQ(3u, model_
->toolbar_items().size());
167 EXPECT_EQ(extensionC
, ExtensionAt(0));
168 EXPECT_EQ(extensionB
, ExtensionAt(1));
169 EXPECT_EQ(extensionA
, ExtensionAt(2));
170 EXPECT_EQ(NULL
, ExtensionAt(3));
172 // Order is now C, B, A. Let's remove B.
173 std::string idB
= extensionB
->id();
174 UnloadExtension(idB
);
175 EXPECT_EQ(1, removed_count_
);
176 EXPECT_EQ(2u, model_
->toolbar_items().size());
177 EXPECT_EQ(extensionC
, ExtensionAt(0));
178 EXPECT_EQ(extensionA
, ExtensionAt(1));
179 EXPECT_EQ(NULL
, ExtensionAt(2));
181 // Load extension B again.
182 ASSERT_TRUE(LoadExtension(extension_b_path
));
184 // Extension B loaded again.
185 EXPECT_EQ(4, inserted_count_
);
186 EXPECT_EQ(3u, model_
->toolbar_items().size());
187 // Make sure it gets its old spot in the list. We should get the same
188 // extension again, otherwise the order has changed.
189 ASSERT_STREQ(idB
.c_str(), ExtensionAt(1)->id().c_str());
192 UnloadExtension(idB
);
193 EXPECT_EQ(2, removed_count_
);
194 EXPECT_EQ(2u, model_
->toolbar_items().size());
195 EXPECT_EQ(extensionC
, ExtensionAt(0));
196 EXPECT_EQ(extensionA
, ExtensionAt(1));
197 EXPECT_EQ(NULL
, ExtensionAt(2));
199 // Order is now C, A. Flip it.
200 model_
->MoveBrowserAction(extensionA
, 0);
201 EXPECT_EQ(3, moved_count_
);
202 EXPECT_EQ(2u, model_
->toolbar_items().size());
203 EXPECT_EQ(extensionA
, ExtensionAt(0));
204 EXPECT_EQ(extensionC
, ExtensionAt(1));
205 EXPECT_EQ(NULL
, ExtensionAt(2));
207 // Move A to the location it already occupies.
208 model_
->MoveBrowserAction(extensionA
, 0);
209 EXPECT_EQ(4, moved_count_
);
210 EXPECT_EQ(2u, model_
->toolbar_items().size());
211 EXPECT_EQ(extensionA
, ExtensionAt(0));
212 EXPECT_EQ(extensionC
, ExtensionAt(1));
213 EXPECT_EQ(NULL
, ExtensionAt(2));
215 // Order is now A, C. Remove C.
216 std::string idC
= extensionC
->id();
217 UnloadExtension(idC
);
218 EXPECT_EQ(3, removed_count_
);
219 EXPECT_EQ(1u, model_
->toolbar_items().size());
220 EXPECT_EQ(extensionA
, ExtensionAt(0));
221 EXPECT_EQ(NULL
, ExtensionAt(1));
223 // Load extension C again.
224 ASSERT_TRUE(LoadExtension(extension_c_path
));
226 // Extension C loaded again.
227 EXPECT_EQ(5, inserted_count_
);
228 EXPECT_EQ(2u, model_
->toolbar_items().size());
229 // Make sure it gets its old spot in the list (at the very end).
230 ASSERT_STREQ(idC
.c_str(), ExtensionAt(1)->id().c_str());
233 IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest
, UnloadAndDisableMultiple
) {
234 // Load three extensions with browser action.
235 base::FilePath
extension_a_path(test_data_dir_
.AppendASCII("api_test")
236 .AppendASCII("browser_action")
237 .AppendASCII("basics"));
238 ASSERT_TRUE(LoadExtension(extension_a_path
));
239 base::FilePath
extension_b_path(test_data_dir_
.AppendASCII("api_test")
240 .AppendASCII("browser_action")
241 .AppendASCII("popup"));
242 ASSERT_TRUE(LoadExtension(extension_b_path
));
243 base::FilePath
extension_c_path(test_data_dir_
.AppendASCII("api_test")
244 .AppendASCII("browser_action")
245 .AppendASCII("remove_popup"));
246 ASSERT_TRUE(LoadExtension(extension_c_path
));
248 // Verify we got the three we asked for and that they are ordered as: A, B, C.
249 const Extension
* extensionA
= ExtensionAt(0);
250 const Extension
* extensionB
= ExtensionAt(1);
251 const Extension
* extensionC
= ExtensionAt(2);
252 std::string idA
= extensionA
->id();
253 std::string idB
= extensionB
->id();
254 std::string idC
= extensionC
->id();
255 EXPECT_STREQ("A browser action with no icon that makes the page red",
256 extensionA
->name().c_str());
257 EXPECT_STREQ("Popup tester", extensionB
->name().c_str());
258 EXPECT_STREQ("A page action which removes a popup.",
259 extensionC
->name().c_str());
261 // Unload B, then C, then A.
262 UnloadExtension(idB
);
263 UnloadExtension(idC
);
264 UnloadExtension(idA
);
266 // Load C, then A, then B.
267 ASSERT_TRUE(LoadExtension(extension_c_path
));
268 ASSERT_TRUE(LoadExtension(extension_a_path
));
269 ASSERT_TRUE(LoadExtension(extension_b_path
));
270 EXPECT_EQ(0, moved_count_
);
272 extensionA
= ExtensionAt(0);
273 extensionB
= ExtensionAt(1);
274 extensionC
= ExtensionAt(2);
276 // Make sure we get the order we started with (A, B, C).
277 EXPECT_STREQ(idA
.c_str(), extensionA
->id().c_str());
278 EXPECT_STREQ(idB
.c_str(), extensionB
->id().c_str());
279 EXPECT_STREQ(idC
.c_str(), extensionC
->id().c_str());
281 // Put C in the middle and A to the end.
282 model_
->MoveBrowserAction(extensionC
, 1);
283 model_
->MoveBrowserAction(extensionA
, 2);
285 // Make sure we get this order (C, B, A).
286 EXPECT_STREQ(idC
.c_str(), ExtensionAt(0)->id().c_str());
287 EXPECT_STREQ(idB
.c_str(), ExtensionAt(1)->id().c_str());
288 EXPECT_STREQ(idA
.c_str(), ExtensionAt(2)->id().c_str());
290 // Disable B, then C, then A.
291 DisableExtension(idB
);
292 DisableExtension(idC
);
293 DisableExtension(idA
);
295 // Enable C, then A, then B.
296 EnableExtension(idA
);
297 EnableExtension(idB
);
298 EnableExtension(idC
);
300 // Make sure we get the order we started with.
301 EXPECT_STREQ(idC
.c_str(), ExtensionAt(0)->id().c_str());
302 EXPECT_STREQ(idB
.c_str(), ExtensionAt(1)->id().c_str());
303 EXPECT_STREQ(idA
.c_str(), ExtensionAt(2)->id().c_str());
306 IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest
, Uninstall
) {
307 // Load two extensions with browser action.
308 base::FilePath
extension_a_path(test_data_dir_
.AppendASCII("api_test")
309 .AppendASCII("browser_action")
310 .AppendASCII("basics"));
311 ASSERT_TRUE(LoadExtension(extension_a_path
));
312 base::FilePath
extension_b_path(test_data_dir_
.AppendASCII("api_test")
313 .AppendASCII("browser_action")
314 .AppendASCII("popup"));
315 ASSERT_TRUE(LoadExtension(extension_b_path
));
317 // Verify we got what we came for.
318 const Extension
* extensionA
= ExtensionAt(0);
319 const Extension
* extensionB
= ExtensionAt(1);
320 std::string idA
= extensionA
->id();
321 std::string idB
= extensionB
->id();
322 EXPECT_STREQ("A browser action with no icon that makes the page red",
323 extensionA
->name().c_str());
324 EXPECT_STREQ("Popup tester", extensionB
->name().c_str());
326 // Order is now A, B. Make B first.
327 model_
->MoveBrowserAction(extensionB
, 0);
329 // Order is now B, A. Uninstall Extension B.
330 UninstallExtension(idB
);
332 // List contains only A now. Validate that.
333 EXPECT_STREQ(idA
.c_str(), ExtensionAt(0)->id().c_str());
334 EXPECT_EQ(1u, model_
->toolbar_items().size());
336 // Load Extension B again.
337 ASSERT_TRUE(LoadExtension(extension_b_path
));
338 EXPECT_EQ(2u, model_
->toolbar_items().size());
340 // Make sure Extension B is _not_ first (should have been forgotten at
342 EXPECT_STREQ(idA
.c_str(), ExtensionAt(0)->id().c_str());
343 EXPECT_STREQ(idB
.c_str(), ExtensionAt(1)->id().c_str());
346 IN_PROC_BROWSER_TEST_F(ExtensionToolbarModelTest
, ReorderOnPrefChange
) {
347 // Load three extensions with browser action.
348 base::FilePath
extension_a_path(test_data_dir_
.AppendASCII("api_test")
349 .AppendASCII("browser_action")
350 .AppendASCII("basics"));
351 ASSERT_TRUE(LoadExtension(extension_a_path
));
352 base::FilePath
extension_b_path(test_data_dir_
.AppendASCII("api_test")
353 .AppendASCII("browser_action")
354 .AppendASCII("popup"));
355 ASSERT_TRUE(LoadExtension(extension_b_path
));
356 base::FilePath
extension_c_path(test_data_dir_
.AppendASCII("api_test")
357 .AppendASCII("browser_action")
358 .AppendASCII("remove_popup"));
359 ASSERT_TRUE(LoadExtension(extension_c_path
));
360 std::string id_a
= ExtensionAt(0)->id();
361 std::string id_b
= ExtensionAt(1)->id();
362 std::string id_c
= ExtensionAt(2)->id();
364 // Change value of toolbar preference.
365 extensions::ExtensionIdList new_order
;
366 new_order
.push_back(id_c
);
367 new_order
.push_back(id_b
);
368 extensions::ExtensionPrefs::Get(browser()->profile())->SetToolbarOrder(
371 // Verify order is changed.
372 EXPECT_EQ(id_c
, ExtensionAt(0)->id());
373 EXPECT_EQ(id_b
, ExtensionAt(1)->id());
374 EXPECT_EQ(id_a
, ExtensionAt(2)->id());