1 // Copyright 2014 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 "base/files/file_util.h"
6 #include "base/macros.h"
7 #include "base/memory/ref_counted.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/stringprintf.h"
10 #include "chrome/browser/extensions/api/extension_action/extension_action_api.h"
11 #include "chrome/browser/extensions/extension_action_manager.h"
12 #include "chrome/browser/extensions/extension_action_test_util.h"
13 #include "chrome/browser/extensions/extension_service.h"
14 #include "chrome/browser/extensions/extension_service_test_base.h"
15 #include "chrome/browser/extensions/extension_toolbar_model.h"
16 #include "chrome/browser/extensions/extension_util.h"
17 #include "chrome/browser/extensions/test_extension_dir.h"
18 #include "chrome/browser/extensions/test_extension_system.h"
19 #include "chrome/browser/extensions/unpacked_installer.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/sessions/session_tab_helper.h"
22 #include "chrome/common/extensions/api/extension_action/action_info.h"
23 #include "components/crx_file/id_util.h"
24 #include "content/public/test/test_renderer_host.h"
25 #include "content/public/test/web_contents_tester.h"
26 #include "extensions/browser/extension_prefs.h"
27 #include "extensions/browser/extension_registry.h"
28 #include "extensions/browser/extension_system.h"
29 #include "extensions/browser/test_extension_registry_observer.h"
30 #include "extensions/common/extension.h"
31 #include "extensions/common/extension_builder.h"
32 #include "extensions/common/feature_switch.h"
33 #include "extensions/common/value_builder.h"
36 #include "ui/aura/env.h"
39 namespace extensions
{
43 // A simple observer that tracks the number of times certain events occur.
44 class ExtensionToolbarModelTestObserver
45 : public ExtensionToolbarModel::Observer
{
47 explicit ExtensionToolbarModelTestObserver(ExtensionToolbarModel
* model
);
48 ~ExtensionToolbarModelTestObserver() override
;
50 size_t inserted_count() const { return inserted_count_
; }
51 size_t removed_count() const { return removed_count_
; }
52 size_t moved_count() const { return moved_count_
; }
53 int highlight_mode_count() const { return highlight_mode_count_
; }
54 size_t initialized_count() const { return initialized_count_
; }
57 // ExtensionToolbarModel::Observer:
58 void OnToolbarExtensionAdded(const Extension
* extension
, int index
) override
{
62 void OnToolbarExtensionRemoved(const Extension
* extension
) override
{
66 void OnToolbarExtensionMoved(const Extension
* extension
, int index
) override
{
70 void OnToolbarExtensionUpdated(const Extension
* extension
) override
{}
72 bool ShowExtensionActionPopup(const Extension
* extension
,
73 bool grant_active_tab
) override
{
77 void OnToolbarVisibleCountChanged() override
{}
79 void OnToolbarHighlightModeChanged(bool is_highlighting
) override
{
80 // Add one if highlighting, subtract one if not.
81 highlight_mode_count_
+= is_highlighting
? 1 : -1;
84 void OnToolbarModelInitialized() override
{ ++initialized_count_
; }
86 Browser
* GetBrowser() override
{ return NULL
; }
88 ExtensionToolbarModel
* model_
;
90 size_t inserted_count_
;
91 size_t removed_count_
;
93 // Int because it could become negative (if something goes wrong).
94 int highlight_mode_count_
;
95 size_t initialized_count_
;
98 ExtensionToolbarModelTestObserver::ExtensionToolbarModelTestObserver(
99 ExtensionToolbarModel
* model
) : model_(model
),
103 highlight_mode_count_(0),
104 initialized_count_(0) {
105 model_
->AddObserver(this);
108 ExtensionToolbarModelTestObserver::~ExtensionToolbarModelTestObserver() {
109 model_
->RemoveObserver(this);
114 class ExtensionToolbarModelUnitTest
: public ExtensionServiceTestBase
{
116 // Initialize the ExtensionService, ExtensionToolbarModel, and
120 void TearDown() override
;
122 // Adds or removes the given |extension| and verify success.
123 testing::AssertionResult
AddExtension(
124 const scoped_refptr
<const Extension
>& extension
) WARN_UNUSED_RESULT
;
125 testing::AssertionResult
RemoveExtension(
126 const scoped_refptr
<const Extension
>& extension
) WARN_UNUSED_RESULT
;
128 // Adds three extensions, all with browser actions.
129 testing::AssertionResult
AddBrowserActionExtensions() WARN_UNUSED_RESULT
;
131 // Adds three extensions, one each for browser action, page action, and no
132 // action, and are added in that order.
133 testing::AssertionResult
AddActionExtensions() WARN_UNUSED_RESULT
;
135 // Returns the extension at the given index in the toolbar model, or NULL
136 // if one does not exist.
137 // If |model| is specified, it is used. Otherwise, this defaults to
139 const Extension
* GetExtensionAtIndex(
140 size_t index
, const ExtensionToolbarModel
* model
) const;
141 const Extension
* GetExtensionAtIndex(size_t index
) const;
143 ExtensionToolbarModel
* toolbar_model() { return toolbar_model_
; }
145 const ExtensionToolbarModelTestObserver
* observer() const {
146 return model_observer_
.get();
148 size_t num_toolbar_items() const {
149 return toolbar_model_
->toolbar_items().size();
151 const Extension
* browser_action_a() const { return browser_action_a_
.get(); }
152 const Extension
* browser_action_b() const { return browser_action_b_
.get(); }
153 const Extension
* browser_action_c() const { return browser_action_c_
.get(); }
154 const Extension
* browser_action() const {
155 return browser_action_extension_
.get();
157 const Extension
* page_action() const { return page_action_extension_
.get(); }
158 const Extension
* no_action() const { return no_action_extension_
.get(); }
161 // Verifies that all extensions in |extensions| are added successfully.
162 testing::AssertionResult
AddAndVerifyExtensions(
163 const ExtensionList
& extensions
);
165 // The toolbar model associated with the testing profile.
166 ExtensionToolbarModel
* toolbar_model_
;
168 // The test observer to track events. Must come after toolbar_model_ so that
169 // it is destroyed and removes itself as an observer first.
170 scoped_ptr
<ExtensionToolbarModelTestObserver
> model_observer_
;
172 // Sample extensions with only browser actions.
173 scoped_refptr
<const Extension
> browser_action_a_
;
174 scoped_refptr
<const Extension
> browser_action_b_
;
175 scoped_refptr
<const Extension
> browser_action_c_
;
177 // Sample extensions with different kinds of actions.
178 scoped_refptr
<const Extension
> browser_action_extension_
;
179 scoped_refptr
<const Extension
> page_action_extension_
;
180 scoped_refptr
<const Extension
> no_action_extension_
;
183 void ExtensionToolbarModelUnitTest::Init() {
184 InitializeEmptyExtensionService();
186 extension_action_test_util::CreateToolbarModelForProfile(profile());
187 model_observer_
.reset(new ExtensionToolbarModelTestObserver(toolbar_model_
));
190 void ExtensionToolbarModelUnitTest::TearDown() {
191 model_observer_
.reset();
192 ExtensionServiceTestBase::TearDown();
195 testing::AssertionResult
ExtensionToolbarModelUnitTest::AddExtension(
196 const scoped_refptr
<const Extension
>& extension
) {
197 if (registry()->enabled_extensions().GetByID(extension
->id())) {
198 return testing::AssertionFailure() << "Extension " << extension
->name() <<
199 " already installed!";
201 service()->AddExtension(extension
.get());
202 if (!registry()->enabled_extensions().GetByID(extension
->id())) {
203 return testing::AssertionFailure() << "Failed to install extension: " <<
206 return testing::AssertionSuccess();
209 testing::AssertionResult
ExtensionToolbarModelUnitTest::RemoveExtension(
210 const scoped_refptr
<const Extension
>& extension
) {
211 if (!registry()->enabled_extensions().GetByID(extension
->id())) {
212 return testing::AssertionFailure() << "Extension " << extension
->name() <<
215 service()->UnloadExtension(extension
->id(),
216 UnloadedExtensionInfo::REASON_DISABLE
);
217 if (registry()->enabled_extensions().GetByID(extension
->id())) {
218 return testing::AssertionFailure() << "Failed to unload extension: " <<
221 return testing::AssertionSuccess();
224 testing::AssertionResult
ExtensionToolbarModelUnitTest::AddActionExtensions() {
225 browser_action_extension_
= extension_action_test_util::CreateActionExtension(
226 "browser_action", extension_action_test_util::BROWSER_ACTION
);
227 page_action_extension_
= extension_action_test_util::CreateActionExtension(
228 "page_action", extension_action_test_util::PAGE_ACTION
);
229 no_action_extension_
= extension_action_test_util::CreateActionExtension(
230 "no_action", extension_action_test_util::NO_ACTION
);
232 ExtensionList extensions
;
233 extensions
.push_back(browser_action_extension_
);
234 extensions
.push_back(page_action_extension_
);
235 extensions
.push_back(no_action_extension_
);
237 return AddAndVerifyExtensions(extensions
);
240 testing::AssertionResult
241 ExtensionToolbarModelUnitTest::AddBrowserActionExtensions() {
242 browser_action_a_
= extension_action_test_util::CreateActionExtension(
243 "browser_actionA", extension_action_test_util::BROWSER_ACTION
);
244 browser_action_b_
= extension_action_test_util::CreateActionExtension(
245 "browser_actionB", extension_action_test_util::BROWSER_ACTION
);
246 browser_action_c_
= extension_action_test_util::CreateActionExtension(
247 "browser_actionC", extension_action_test_util::BROWSER_ACTION
);
249 ExtensionList extensions
;
250 extensions
.push_back(browser_action_a_
);
251 extensions
.push_back(browser_action_b_
);
252 extensions
.push_back(browser_action_c_
);
254 return AddAndVerifyExtensions(extensions
);
257 const Extension
* ExtensionToolbarModelUnitTest::GetExtensionAtIndex(
258 size_t index
, const ExtensionToolbarModel
* model
) const {
259 return index
< model
->toolbar_items().size()
260 ? model
->toolbar_items()[index
].get()
264 const Extension
* ExtensionToolbarModelUnitTest::GetExtensionAtIndex(
265 size_t index
) const {
266 return GetExtensionAtIndex(index
, toolbar_model_
);
269 testing::AssertionResult
ExtensionToolbarModelUnitTest::AddAndVerifyExtensions(
270 const ExtensionList
& extensions
) {
271 for (ExtensionList::const_iterator iter
= extensions
.begin();
272 iter
!= extensions
.end(); ++iter
) {
273 if (!AddExtension(*iter
)) {
274 return testing::AssertionFailure() << "Failed to install extension: " <<
278 return testing::AssertionSuccess();
281 // A basic test for extensions with browser actions showing up in the toolbar.
282 TEST_F(ExtensionToolbarModelUnitTest
, BasicExtensionToolbarModelTest
) {
285 // Load an extension with no browser action.
286 scoped_refptr
<const Extension
> extension1
=
287 extension_action_test_util::CreateActionExtension(
288 "no_action", extension_action_test_util::NO_ACTION
);
289 ASSERT_TRUE(AddExtension(extension1
));
291 // This extension should not be in the model (has no browser action).
292 EXPECT_EQ(0u, observer()->inserted_count());
293 EXPECT_EQ(0u, num_toolbar_items());
294 EXPECT_EQ(NULL
, GetExtensionAtIndex(0u));
296 // Load an extension with a browser action.
297 scoped_refptr
<const Extension
> extension2
=
298 extension_action_test_util::CreateActionExtension(
299 "browser_action", extension_action_test_util::BROWSER_ACTION
);
300 ASSERT_TRUE(AddExtension(extension2
));
302 // We should now find our extension in the model.
303 EXPECT_EQ(1u, observer()->inserted_count());
304 EXPECT_EQ(1u, num_toolbar_items());
305 EXPECT_EQ(extension2
.get(), GetExtensionAtIndex(0u));
307 // Should be a no-op, but still fires the events.
308 toolbar_model()->MoveExtensionIcon(extension2
->id(), 0);
309 EXPECT_EQ(1u, observer()->moved_count());
310 EXPECT_EQ(1u, num_toolbar_items());
311 EXPECT_EQ(extension2
.get(), GetExtensionAtIndex(0u));
313 // Remove the extension and verify.
314 ASSERT_TRUE(RemoveExtension(extension2
));
315 EXPECT_EQ(1u, observer()->removed_count());
316 EXPECT_EQ(0u, num_toolbar_items());
317 EXPECT_EQ(NULL
, GetExtensionAtIndex(0u));
320 // Test various different reorderings, removals, and reinsertions.
321 TEST_F(ExtensionToolbarModelUnitTest
, ExtensionToolbarReorderAndReinsert
) {
324 // Add the three browser action extensions.
325 ASSERT_TRUE(AddBrowserActionExtensions());
327 // Verify the three extensions are in the model in the proper order.
328 EXPECT_EQ(3u, num_toolbar_items());
329 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
330 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
331 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
333 // Order is now A, B, C. Let's put C first.
334 toolbar_model()->MoveExtensionIcon(browser_action_c()->id(), 0);
335 EXPECT_EQ(1u, observer()->moved_count());
336 EXPECT_EQ(3u, num_toolbar_items());
337 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
338 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(1u));
339 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(2u));
341 // Order is now C, A, B. Let's put A last.
342 toolbar_model()->MoveExtensionIcon(browser_action_a()->id(), 2);
343 EXPECT_EQ(2u, observer()->moved_count());
344 EXPECT_EQ(3u, num_toolbar_items());
345 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
346 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
347 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(2u));
349 // Order is now C, B, A. Let's remove B.
350 ASSERT_TRUE(RemoveExtension(browser_action_b()));
351 EXPECT_EQ(1u, observer()->removed_count());
352 EXPECT_EQ(2u, num_toolbar_items());
353 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
354 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(1u));
356 // Load extension B again.
357 ASSERT_TRUE(AddExtension(browser_action_b()));
359 // Extension B loaded again.
360 EXPECT_EQ(4u, observer()->inserted_count());
361 EXPECT_EQ(3u, num_toolbar_items());
362 // Make sure it gets its old spot in the list.
363 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
366 ASSERT_TRUE(RemoveExtension(browser_action_b()));
367 EXPECT_EQ(2u, observer()->removed_count());
368 EXPECT_EQ(2u, num_toolbar_items());
370 // Order is now C, A. Flip it.
371 toolbar_model()->MoveExtensionIcon(browser_action_a()->id(), 0);
372 EXPECT_EQ(3u, observer()->moved_count());
373 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
374 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
376 // Move A to the location it already occupies.
377 toolbar_model()->MoveExtensionIcon(browser_action_a()->id(), 0);
378 EXPECT_EQ(4u, observer()->moved_count());
379 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
380 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
382 // Order is now A, C. Remove C.
383 ASSERT_TRUE(RemoveExtension(browser_action_c()));
384 EXPECT_EQ(3u, observer()->removed_count());
385 EXPECT_EQ(1u, num_toolbar_items());
386 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
388 // Load extension C again.
389 ASSERT_TRUE(AddExtension(browser_action_c()));
391 // Extension C loaded again.
392 EXPECT_EQ(5u, observer()->inserted_count());
393 EXPECT_EQ(2u, num_toolbar_items());
394 // Make sure it gets its old spot in the list (at the very end).
395 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
398 // Test that order persists after unloading and disabling, but not across
400 TEST_F(ExtensionToolbarModelUnitTest
,
401 ExtensionToolbarUnloadDisableAndUninstall
) {
404 // Add the three browser action extensions.
405 ASSERT_TRUE(AddBrowserActionExtensions());
407 // Verify the three extensions are in the model in the proper order: A, B, C.
408 EXPECT_EQ(3u, num_toolbar_items());
409 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
410 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
411 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
413 // Unload B, then C, then A, and then reload C, then A, then B.
414 ASSERT_TRUE(RemoveExtension(browser_action_b()));
415 ASSERT_TRUE(RemoveExtension(browser_action_c()));
416 ASSERT_TRUE(RemoveExtension(browser_action_a()));
417 EXPECT_EQ(0u, num_toolbar_items()); // Sanity check: all gone?
418 ASSERT_TRUE(AddExtension(browser_action_c()));
419 ASSERT_TRUE(AddExtension(browser_action_a()));
420 ASSERT_TRUE(AddExtension(browser_action_b()));
421 EXPECT_EQ(3u, num_toolbar_items()); // Sanity check: all back?
422 EXPECT_EQ(0u, observer()->moved_count());
424 // Even though we unloaded and reloaded in a different order, the original
425 // order (A, B, C) should be preserved.
426 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
427 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
428 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
430 // Disabling extensions should also preserve order.
431 service()->DisableExtension(browser_action_b()->id(),
432 Extension::DISABLE_USER_ACTION
);
433 service()->DisableExtension(browser_action_c()->id(),
434 Extension::DISABLE_USER_ACTION
);
435 service()->DisableExtension(browser_action_a()->id(),
436 Extension::DISABLE_USER_ACTION
);
437 service()->EnableExtension(browser_action_c()->id());
438 service()->EnableExtension(browser_action_a()->id());
439 service()->EnableExtension(browser_action_b()->id());
441 // Make sure we still get the original A, B, C order.
442 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
443 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
444 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
446 // Move browser_action_b() to be first.
447 toolbar_model()->MoveExtensionIcon(browser_action_b()->id(), 0);
448 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(0u));
450 // Uninstall Extension B.
451 service()->UninstallExtension(browser_action_b()->id(),
452 UNINSTALL_REASON_FOR_TESTING
,
453 base::Bind(&base::DoNothing
),
454 NULL
); // Ignore error.
455 // List contains only A and C now. Validate that.
456 EXPECT_EQ(2u, num_toolbar_items());
457 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
458 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
460 ASSERT_TRUE(AddExtension(browser_action_b()));
462 // Make sure Extension B is _not_ first (its old position should have been
463 // forgotten at uninstall time). Order should be A, C, B.
464 EXPECT_EQ(3u, num_toolbar_items());
465 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
466 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
467 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(2u));
470 TEST_F(ExtensionToolbarModelUnitTest
, ReorderOnPrefChange
) {
473 // Add the three browser action extensions.
474 ASSERT_TRUE(AddBrowserActionExtensions());
475 EXPECT_EQ(3u, num_toolbar_items());
477 // Change the value of the toolbar preference.
478 ExtensionIdList new_order
;
479 new_order
.push_back(browser_action_c()->id());
480 new_order
.push_back(browser_action_b()->id());
481 ExtensionPrefs::Get(profile())->SetToolbarOrder(new_order
);
483 // Verify order is changed.
484 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
485 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
486 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(2u));
489 // Test that new extensions are always visible on installation and inserted at
490 // the "end" of the visible section.
491 TEST_F(ExtensionToolbarModelUnitTest
, NewToolbarExtensionsAreVisible
) {
494 // Three extensions with actions.
495 scoped_refptr
<const Extension
> extension_a
=
496 extension_action_test_util::CreateActionExtension(
497 "a", extension_action_test_util::BROWSER_ACTION
);
498 scoped_refptr
<const Extension
> extension_b
=
499 extension_action_test_util::CreateActionExtension(
500 "b", extension_action_test_util::BROWSER_ACTION
);
501 scoped_refptr
<const Extension
> extension_c
=
502 extension_action_test_util::CreateActionExtension(
503 "c", extension_action_test_util::BROWSER_ACTION
);
504 scoped_refptr
<const Extension
> extension_d
=
505 extension_action_test_util::CreateActionExtension(
506 "d", extension_action_test_util::BROWSER_ACTION
);
508 // We should start off without any extensions.
509 EXPECT_EQ(0u, num_toolbar_items());
510 EXPECT_EQ(0u, toolbar_model()->visible_icon_count());
512 // Add one extension. It should be visible.
513 service()->AddExtension(extension_a
.get());
514 EXPECT_EQ(1u, num_toolbar_items());
515 EXPECT_EQ(1u, toolbar_model()->visible_icon_count());
516 EXPECT_EQ(extension_a
.get(), GetExtensionAtIndex(0u));
518 // Hide all extensions.
519 toolbar_model()->SetVisibleIconCount(0);
520 EXPECT_EQ(0u, toolbar_model()->visible_icon_count());
522 // Add a new extension - it should be visible, so it should be in the first
523 // index. The other extension should remain hidden.
524 service()->AddExtension(extension_b
.get());
525 EXPECT_EQ(2u, num_toolbar_items());
526 EXPECT_EQ(1u, toolbar_model()->visible_icon_count());
527 EXPECT_EQ(extension_b
.get(), GetExtensionAtIndex(0u));
528 EXPECT_EQ(extension_a
.get(), GetExtensionAtIndex(1u));
530 // Show all extensions.
531 toolbar_model()->SetVisibleIconCount(2);
532 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
533 EXPECT_TRUE(toolbar_model()->all_icons_visible());
535 // Add the third extension. Since all extensions are visible, it should go in
537 service()->AddExtension(extension_c
.get());
538 EXPECT_EQ(3u, num_toolbar_items());
539 EXPECT_EQ(3u, toolbar_model()->visible_icon_count());
540 EXPECT_TRUE(toolbar_model()->all_icons_visible());
541 EXPECT_EQ(extension_b
.get(), GetExtensionAtIndex(0u));
542 EXPECT_EQ(extension_a
.get(), GetExtensionAtIndex(1u));
543 EXPECT_EQ(extension_c
.get(), GetExtensionAtIndex(2u));
545 // Hide one extension (two remaining visible).
546 toolbar_model()->SetVisibleIconCount(2);
547 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
549 // Add a fourth extension. It should go at the end of the visible section and
550 // be visible, so it increases visible count by 1, and goes into the third
551 // index. The hidden extension should remain hidden.
552 service()->AddExtension(extension_d
.get());
553 EXPECT_EQ(4u, num_toolbar_items());
554 EXPECT_EQ(3u, toolbar_model()->visible_icon_count());
555 EXPECT_EQ(extension_b
.get(), GetExtensionAtIndex(0u));
556 EXPECT_EQ(extension_a
.get(), GetExtensionAtIndex(1u));
557 EXPECT_EQ(extension_d
.get(), GetExtensionAtIndex(2u));
558 EXPECT_EQ(extension_c
.get(), GetExtensionAtIndex(3u));
561 TEST_F(ExtensionToolbarModelUnitTest
, ExtensionToolbarHighlightMode
) {
564 EXPECT_FALSE(toolbar_model()->HighlightExtensions(ExtensionIdList()));
565 EXPECT_EQ(0, observer()->highlight_mode_count());
567 // Add the three browser action extensions.
568 ASSERT_TRUE(AddBrowserActionExtensions());
569 EXPECT_EQ(3u, num_toolbar_items());
571 // Highlight one extension.
572 ExtensionIdList extension_ids
;
573 extension_ids
.push_back(browser_action_b()->id());
574 toolbar_model()->HighlightExtensions(extension_ids
);
575 EXPECT_EQ(1, observer()->highlight_mode_count());
576 EXPECT_TRUE(toolbar_model()->is_highlighting());
578 EXPECT_EQ(1u, num_toolbar_items());
579 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(0u));
581 // Stop highlighting.
582 toolbar_model()->StopHighlighting();
583 EXPECT_EQ(0, observer()->highlight_mode_count());
584 EXPECT_FALSE(toolbar_model()->is_highlighting());
586 // Verify that the extensions are back to normal.
587 EXPECT_EQ(3u, num_toolbar_items());
588 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
589 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
590 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
592 // Call stop highlighting a second time (shouldn't be notified).
593 toolbar_model()->StopHighlighting();
594 EXPECT_EQ(0, observer()->highlight_mode_count());
595 EXPECT_FALSE(toolbar_model()->is_highlighting());
597 // Highlight all extensions.
598 extension_ids
.clear();
599 extension_ids
.push_back(browser_action_a()->id());
600 extension_ids
.push_back(browser_action_b()->id());
601 extension_ids
.push_back(browser_action_c()->id());
602 toolbar_model()->HighlightExtensions(extension_ids
);
603 EXPECT_EQ(1, observer()->highlight_mode_count());
604 EXPECT_EQ(3u, num_toolbar_items());
605 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
606 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
607 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
609 // Highlight only extension b (shrink the highlight list).
610 extension_ids
.clear();
611 extension_ids
.push_back(browser_action_b()->id());
612 toolbar_model()->HighlightExtensions(extension_ids
);
613 EXPECT_EQ(2, observer()->highlight_mode_count());
614 EXPECT_EQ(1u, num_toolbar_items());
615 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(0u));
617 // Highlight extensions a and b (grow the highlight list).
618 extension_ids
.clear();
619 extension_ids
.push_back(browser_action_a()->id());
620 extension_ids
.push_back(browser_action_b()->id());
621 toolbar_model()->HighlightExtensions(extension_ids
);
622 EXPECT_EQ(3, observer()->highlight_mode_count());
623 EXPECT_EQ(2u, num_toolbar_items());
624 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
625 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
627 // Highlight no extensions (empty the highlight list).
628 extension_ids
.clear();
629 toolbar_model()->HighlightExtensions(extension_ids
);
630 EXPECT_EQ(2, observer()->highlight_mode_count());
631 EXPECT_FALSE(toolbar_model()->is_highlighting());
632 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
633 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
634 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
637 TEST_F(ExtensionToolbarModelUnitTest
, ExtensionToolbarHighlightModeRemove
) {
640 // Add the three browser action extensions.
641 ASSERT_TRUE(AddBrowserActionExtensions());
642 EXPECT_EQ(3u, num_toolbar_items());
644 // Highlight two of the extensions.
645 ExtensionIdList extension_ids
;
646 extension_ids
.push_back(browser_action_a()->id());
647 extension_ids
.push_back(browser_action_b()->id());
648 toolbar_model()->HighlightExtensions(extension_ids
);
649 EXPECT_TRUE(toolbar_model()->is_highlighting());
650 EXPECT_EQ(1, observer()->highlight_mode_count());
651 EXPECT_EQ(2u, num_toolbar_items());
653 // Disable one of them - only one should remain highlighted.
654 service()->DisableExtension(browser_action_a()->id(),
655 Extension::DISABLE_USER_ACTION
);
656 EXPECT_TRUE(toolbar_model()->is_highlighting());
657 EXPECT_EQ(1u, num_toolbar_items());
658 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(0u));
660 // Uninstall the remaining highlighted extension. This should result in
661 // highlight mode exiting.
662 service()->UninstallExtension(browser_action_b()->id(),
663 UNINSTALL_REASON_FOR_TESTING
,
664 base::Bind(&base::DoNothing
),
665 NULL
); // Ignore error.
666 EXPECT_FALSE(toolbar_model()->is_highlighting());
667 EXPECT_EQ(0, observer()->highlight_mode_count());
668 EXPECT_EQ(1u, num_toolbar_items());
669 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
671 // Test that removing an unhighlighted extension still works.
672 // Reinstall extension b, and then highlight extension c.
673 ASSERT_TRUE(AddExtension(browser_action_b()));
674 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
675 extension_ids
.clear();
676 extension_ids
.push_back(browser_action_c()->id());
677 toolbar_model()->HighlightExtensions(extension_ids
);
678 EXPECT_EQ(1, observer()->highlight_mode_count());
679 EXPECT_TRUE(toolbar_model()->is_highlighting());
680 EXPECT_EQ(1u, num_toolbar_items());
681 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
683 // Uninstalling b should not have visible impact.
684 service()->UninstallExtension(browser_action_b()->id(),
685 UNINSTALL_REASON_FOR_TESTING
,
686 base::Bind(&base::DoNothing
),
687 NULL
); // Ignore error.
688 EXPECT_TRUE(toolbar_model()->is_highlighting());
689 EXPECT_EQ(1, observer()->highlight_mode_count());
690 EXPECT_EQ(1u, num_toolbar_items());
691 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
693 // When we stop, only extension c should remain.
694 toolbar_model()->StopHighlighting();
695 EXPECT_FALSE(toolbar_model()->is_highlighting());
696 EXPECT_EQ(0, observer()->highlight_mode_count());
697 EXPECT_EQ(1u, num_toolbar_items());
698 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
701 TEST_F(ExtensionToolbarModelUnitTest
, ExtensionToolbarHighlightModeAdd
) {
704 // Add the three browser action extensions.
705 ASSERT_TRUE(AddBrowserActionExtensions());
706 EXPECT_EQ(3u, num_toolbar_items());
708 // Remove one (down to two).
709 ASSERT_TRUE(RemoveExtension(browser_action_c()));
711 // Highlight one of the two extensions.
712 ExtensionIdList extension_ids
;
713 extension_ids
.push_back(browser_action_a()->id());
714 toolbar_model()->HighlightExtensions(extension_ids
);
715 EXPECT_TRUE(toolbar_model()->is_highlighting());
716 EXPECT_EQ(1u, num_toolbar_items());
717 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
719 // Adding a new extension should have no visible effect.
720 ASSERT_TRUE(AddExtension(browser_action_c()));
721 EXPECT_TRUE(toolbar_model()->is_highlighting());
722 EXPECT_EQ(1u, num_toolbar_items());
723 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
725 // When we stop highlighting, we should see the new extension show up.
726 toolbar_model()->StopHighlighting();
727 EXPECT_FALSE(toolbar_model()->is_highlighting());
728 EXPECT_EQ(3u, num_toolbar_items());
729 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
730 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
731 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
734 // Test that the extension toolbar maintains the proper size, even after a pref
736 TEST_F(ExtensionToolbarModelUnitTest
, ExtensionToolbarSizeAfterPrefChange
) {
739 // Add the three browser action extensions.
740 ASSERT_TRUE(AddBrowserActionExtensions());
741 EXPECT_EQ(3u, num_toolbar_items());
743 // Should be at max size.
744 EXPECT_TRUE(toolbar_model()->all_icons_visible());
745 EXPECT_EQ(num_toolbar_items(), toolbar_model()->visible_icon_count());
746 toolbar_model()->OnExtensionToolbarPrefChange();
747 // Should still be at max size.
748 EXPECT_TRUE(toolbar_model()->all_icons_visible());
749 EXPECT_EQ(num_toolbar_items(), toolbar_model()->visible_icon_count());
752 // Test that, in the absence of the extension-action-redesign switch, the
753 // model only contains extensions with browser actions.
754 TEST_F(ExtensionToolbarModelUnitTest
, TestToolbarExtensionTypesNoSwitch
) {
756 ASSERT_TRUE(AddActionExtensions());
758 EXPECT_EQ(1u, num_toolbar_items());
759 EXPECT_EQ(browser_action(), GetExtensionAtIndex(0u));
762 // Test that, with the extension-action-redesign switch, the model contains
763 // all types of extensions, except those which should not be displayed on the
764 // toolbar (like component extensions).
765 TEST_F(ExtensionToolbarModelUnitTest
, TestToolbarExtensionTypesSwitch
) {
766 FeatureSwitch::ScopedOverride
enable_redesign(
767 FeatureSwitch::extension_action_redesign(), true);
769 ASSERT_TRUE(AddActionExtensions());
771 // With the switch on, extensions with page actions and no action should also
772 // be displayed in the toolbar.
773 EXPECT_EQ(3u, num_toolbar_items());
774 EXPECT_EQ(browser_action(), GetExtensionAtIndex(0u));
775 EXPECT_EQ(page_action(), GetExtensionAtIndex(1u));
776 EXPECT_EQ(no_action(), GetExtensionAtIndex(2u));
779 // Test that hiding actions on the toolbar results in their removal from the
780 // model when the redesign switch is not enabled.
781 TEST_F(ExtensionToolbarModelUnitTest
,
782 ExtensionToolbarActionsVisibilityNoSwitch
) {
785 ExtensionActionAPI
* action_api
= ExtensionActionAPI::Get(profile());
787 ASSERT_TRUE(AddBrowserActionExtensions());
788 // Sanity check: Order should start as A B C.
789 EXPECT_EQ(3u, num_toolbar_items());
790 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
791 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
792 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
794 // By default, all actions should be visible.
795 EXPECT_TRUE(action_api
->GetBrowserActionVisibility(browser_action_a()->id()));
796 EXPECT_TRUE(action_api
->GetBrowserActionVisibility(browser_action_b()->id()));
797 EXPECT_TRUE(action_api
->GetBrowserActionVisibility(browser_action_c()->id()));
799 // Hiding an action should result in its removal from the toolbar.
800 action_api
->SetBrowserActionVisibility(browser_action_b()->id(), false);
801 EXPECT_FALSE(action_api
->GetBrowserActionVisibility(
802 browser_action_b()->id()));
803 // Thus, there should now only be two items on the toolbar - A and C.
804 EXPECT_EQ(2u, num_toolbar_items());
805 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
806 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
808 // Resetting the visibility to 'true' should result in the extension being
809 // added back at its original position.
810 action_api
->SetBrowserActionVisibility(browser_action_b()->id(), true);
811 EXPECT_TRUE(action_api
->GetBrowserActionVisibility(browser_action_b()->id()));
812 // So the toolbar order should be A B C.
813 EXPECT_EQ(3u, num_toolbar_items());
814 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
815 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
816 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
819 TEST_F(ExtensionToolbarModelUnitTest
, ExtensionToolbarIncognitoModeTest
) {
821 ASSERT_TRUE(AddBrowserActionExtensions());
823 // Give two extensions incognito access.
824 // Note: We use ExtensionPrefs::SetIsIncognitoEnabled instead of
825 // util::SetIsIncognitoEnabled because the latter tries to reload the
826 // extension, which requries a filepath associated with the extension (and,
827 // for this test, reloading the extension is irrelevant to us).
828 ExtensionPrefs
* extension_prefs
= ExtensionPrefs::Get(profile());
829 extension_prefs
->SetIsIncognitoEnabled(browser_action_b()->id(), true);
830 extension_prefs
->SetIsIncognitoEnabled(browser_action_c()->id(), true);
832 util::SetIsIncognitoEnabled(browser_action_b()->id(), profile(), true);
833 util::SetIsIncognitoEnabled(browser_action_c()->id(), profile(), true);
835 // Move C to the second index.
836 toolbar_model()->MoveExtensionIcon(browser_action_c()->id(), 1u);
837 // Set visible count to 2 so that c is overflowed. State is A C [B].
838 toolbar_model()->SetVisibleIconCount(2);
839 EXPECT_EQ(1u, observer()->moved_count());
841 // Get an incognito profile and toolbar.
842 ExtensionToolbarModel
* incognito_model
=
843 extension_action_test_util::CreateToolbarModelForProfile(
844 profile()->GetOffTheRecordProfile());
846 ExtensionToolbarModelTestObserver
incognito_observer(incognito_model
);
847 EXPECT_EQ(0u, incognito_observer
.moved_count());
849 // We should have two items, C and B, and the order should be preserved from
850 // the original model.
851 EXPECT_EQ(2u, incognito_model
->toolbar_items().size());
852 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u, incognito_model
));
853 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u, incognito_model
));
855 // Extensions in the overflow menu in the regular toolbar should remain in
856 // overflow in the incognito toolbar. So, we should have C [B].
857 EXPECT_EQ(1u, incognito_model
->visible_icon_count());
858 // The regular model should still have two icons visible.
859 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
861 // Changing the incognito model size should not affect the regular model.
862 incognito_model
->SetVisibleIconCount(0);
863 EXPECT_EQ(0u, incognito_model
->visible_icon_count());
864 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
866 // Expanding the incognito model to 2 should register as "all icons"
867 // since it is all of the incognito-enabled extensions.
868 incognito_model
->SetVisibleIconCount(2u);
869 EXPECT_EQ(2u, incognito_model
->visible_icon_count());
870 EXPECT_TRUE(incognito_model
->all_icons_visible());
872 // Moving icons in the incognito toolbar should not affect the regular
873 // toolbar. Incognito currently has C B...
874 incognito_model
->MoveExtensionIcon(browser_action_b()->id(), 0u);
875 // So now it should be B C...
876 EXPECT_EQ(1u, incognito_observer
.moved_count());
877 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(0u, incognito_model
));
878 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u, incognito_model
));
879 // ... and the regular toolbar should be unaffected.
880 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
881 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
882 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(2u));
884 // Similarly, the observer for the regular model should not have received
886 EXPECT_EQ(1u, observer()->moved_count());
888 // And performing moves on the regular model should have no effect on the
889 // incognito model or its observers.
890 toolbar_model()->MoveExtensionIcon(browser_action_c()->id(), 2u);
891 EXPECT_EQ(2u, observer()->moved_count());
892 EXPECT_EQ(1u, incognito_observer
.moved_count());
895 // Test that enabling extensions incognito with an active incognito profile
897 TEST_F(ExtensionToolbarModelUnitTest
,
898 ExtensionToolbarIncognitoEnableExtension
) {
901 const char* kManifest
=
904 " \"version\": \"1.0\","
905 " \"manifest_version\": 2,"
906 " \"browser_action\": {}"
909 // For this test, we need to have "real" extension files, because we need to
910 // be able to reload them during the incognito process. Since the toolbar
911 // needs to be notified of the reload, we need it this time (as opposed to
912 // above, where we simply set the prefs before the incognito bar was
914 TestExtensionDir dir1
;
915 dir1
.WriteManifest(base::StringPrintf(kManifest
, "incognito1"));
916 TestExtensionDir dir2
;
917 dir2
.WriteManifest(base::StringPrintf(kManifest
, "incognito2"));
919 TestExtensionDir
* dirs
[] = { &dir1
, &dir2
};
920 const Extension
* extensions
[] = { nullptr, nullptr };
921 for (size_t i
= 0; i
< arraysize(dirs
); ++i
) {
922 // The extension id will be calculated from the file path; we need this to
923 // wait for the extension to load.
924 base::FilePath path_for_id
=
925 base::MakeAbsoluteFilePath(dirs
[i
]->unpacked_path());
926 std::string id
= crx_file::id_util::GenerateIdForPath(path_for_id
);
927 TestExtensionRegistryObserver
observer(registry(), id
);
928 UnpackedInstaller::Create(service())->Load(dirs
[i
]->unpacked_path());
929 observer
.WaitForExtensionLoaded();
930 extensions
[i
] = registry()->enabled_extensions().GetByID(id
);
931 ASSERT_TRUE(extensions
[i
]);
934 // For readability, alias to A and B. Since we'll be reloading these
935 // extensions, we also can't rely on pointers.
936 std::string extension_a
= extensions
[0]->id();
937 std::string extension_b
= extensions
[1]->id();
939 // The first model should have both extensions visible.
940 EXPECT_EQ(2u, toolbar_model()->toolbar_items().size());
941 EXPECT_EQ(extension_a
, GetExtensionAtIndex(0)->id());
942 EXPECT_EQ(extension_b
, GetExtensionAtIndex(1)->id());
944 // Set the model to only show one extension, so the order is A [B].
945 toolbar_model()->SetVisibleIconCount(1u);
947 // Get an incognito profile and toolbar.
948 ExtensionToolbarModel
* incognito_model
=
949 extension_action_test_util::CreateToolbarModelForProfile(
950 profile()->GetOffTheRecordProfile());
951 ExtensionToolbarModelTestObserver
incognito_observer(incognito_model
);
953 // Right now, no extensions are enabled in incognito mode.
954 EXPECT_EQ(0u, incognito_model
->toolbar_items().size());
956 // Set extension b (which is overflowed) to be enabled in incognito. This
957 // results in b reloading, so wait for it.
959 TestExtensionRegistryObserver
observer(registry(), extension_b
);
960 util::SetIsIncognitoEnabled(extension_b
, profile(), true);
961 observer
.WaitForExtensionLoaded();
964 // Now, we should have one icon in the incognito bar. But, since B is
965 // overflowed in the main bar, it shouldn't be visible.
966 EXPECT_EQ(1u, incognito_model
->toolbar_items().size());
967 EXPECT_EQ(extension_b
, GetExtensionAtIndex(0u, incognito_model
)->id());
968 EXPECT_EQ(0u, incognito_model
->visible_icon_count());
970 // Also enable extension a for incognito (again, wait for the reload).
972 TestExtensionRegistryObserver
observer(registry(), extension_a
);
973 util::SetIsIncognitoEnabled(extension_a
, profile(), true);
974 observer
.WaitForExtensionLoaded();
977 // Now, both extensions should be enabled in incognito mode. In addition, the
978 // incognito toolbar should have expanded to show extension a (since it isn't
979 // overflowed in the main bar).
980 EXPECT_EQ(2u, incognito_model
->toolbar_items().size());
981 EXPECT_EQ(extension_a
, GetExtensionAtIndex(0u, incognito_model
)->id());
982 EXPECT_EQ(extension_b
, GetExtensionAtIndex(1u, incognito_model
)->id());
983 EXPECT_EQ(1u, incognito_model
->visible_icon_count());
986 // Test that hiding actions on the toolbar results in sending them to the
987 // overflow menu when the redesign switch is enabled.
988 TEST_F(ExtensionToolbarModelUnitTest
,
989 ExtensionToolbarActionsVisibilityWithSwitch
) {
990 FeatureSwitch::ScopedOverride
enable_redesign(
991 FeatureSwitch::extension_action_redesign(), true);
994 // We choose to use all types of extensions here, since the misnamed
995 // BrowserActionVisibility is now for toolbar visibility.
996 ASSERT_TRUE(AddActionExtensions());
998 // For readability, alias extensions A B C.
999 const Extension
* extension_a
= browser_action();
1000 const Extension
* extension_b
= page_action();
1001 const Extension
* extension_c
= no_action();
1003 // Sanity check: Order should start as A B C, with all three visible.
1004 EXPECT_EQ(3u, num_toolbar_items());
1005 EXPECT_TRUE(toolbar_model()->all_icons_visible());
1006 EXPECT_EQ(extension_a
, GetExtensionAtIndex(0u));
1007 EXPECT_EQ(extension_b
, GetExtensionAtIndex(1u));
1008 EXPECT_EQ(extension_c
, GetExtensionAtIndex(2u));
1010 ExtensionActionAPI
* action_api
= ExtensionActionAPI::Get(profile());
1012 // By default, all actions should be visible.
1013 EXPECT_TRUE(action_api
->GetBrowserActionVisibility(extension_a
->id()));
1014 EXPECT_TRUE(action_api
->GetBrowserActionVisibility(extension_c
->id()));
1015 EXPECT_TRUE(action_api
->GetBrowserActionVisibility(extension_b
->id()));
1017 // Hiding an action should result in it being sent to the overflow menu.
1018 action_api
->SetBrowserActionVisibility(extension_b
->id(), false);
1020 // Thus, the order should be A C B, with B in the overflow.
1021 EXPECT_EQ(3u, num_toolbar_items());
1022 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
1023 EXPECT_EQ(extension_a
, GetExtensionAtIndex(0u));
1024 EXPECT_EQ(extension_c
, GetExtensionAtIndex(1u));
1025 EXPECT_EQ(extension_b
, GetExtensionAtIndex(2u));
1027 // Hiding an extension's action should result in it being sent to the overflow
1028 // as well, but as the _first_ extension in the overflow.
1029 action_api
->SetBrowserActionVisibility(extension_a
->id(), false);
1030 // Thus, the order should be C A B, with A and B in the overflow.
1031 EXPECT_EQ(3u, num_toolbar_items());
1032 EXPECT_EQ(1u, toolbar_model()->visible_icon_count());
1033 EXPECT_EQ(extension_c
, GetExtensionAtIndex(0u));
1034 EXPECT_EQ(extension_a
, GetExtensionAtIndex(1u));
1035 EXPECT_EQ(extension_b
, GetExtensionAtIndex(2u));
1037 // Resetting A's visibility to true should send it back to the visible icons
1038 // (and should grow visible icons by 1), but it should be added to the end of
1039 // the visible icon list (not to its original position).
1040 action_api
->SetBrowserActionVisibility(extension_a
->id(), true);
1041 // So order is C A B, with only B in the overflow.
1042 EXPECT_EQ(3u, num_toolbar_items());
1043 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
1044 EXPECT_EQ(extension_c
, GetExtensionAtIndex(0u));
1045 EXPECT_EQ(extension_a
, GetExtensionAtIndex(1u));
1046 EXPECT_EQ(extension_b
, GetExtensionAtIndex(2u));
1048 // Resetting B to be visible should make the order C A B, with no overflow.
1049 action_api
->SetBrowserActionVisibility(extension_b
->id(), true);
1050 EXPECT_EQ(3u, num_toolbar_items());
1051 EXPECT_TRUE(toolbar_model()->all_icons_visible());
1052 EXPECT_EQ(extension_c
, GetExtensionAtIndex(0u));
1053 EXPECT_EQ(extension_a
, GetExtensionAtIndex(1u));
1054 EXPECT_EQ(extension_b
, GetExtensionAtIndex(2u));
1057 // Test that observers receive no Added notifications until after the
1058 // ExtensionSystem has initialized.
1059 TEST_F(ExtensionToolbarModelUnitTest
, ModelWaitsForExtensionSystemReady
) {
1060 InitializeEmptyExtensionService();
1061 ExtensionToolbarModel
* toolbar_model
=
1062 extension_action_test_util::
1063 CreateToolbarModelForProfileWithoutWaitingForReady(profile());
1064 ExtensionToolbarModelTestObserver
model_observer(toolbar_model
);
1065 EXPECT_TRUE(AddBrowserActionExtensions());
1067 // Since the model hasn't been initialized (the ExtensionSystem::ready task
1068 // hasn't been run), there should be no insertion notifications.
1069 EXPECT_EQ(0u, model_observer
.inserted_count());
1070 EXPECT_EQ(0u, model_observer
.initialized_count());
1071 EXPECT_FALSE(toolbar_model
->extensions_initialized());
1073 // Run the ready task.
1074 static_cast<TestExtensionSystem
*>(ExtensionSystem::Get(profile()))->
1076 // Run tasks posted to TestExtensionSystem.
1077 base::RunLoop().RunUntilIdle();
1079 // We should still have no insertions, but should have an initialized count.
1080 EXPECT_TRUE(toolbar_model
->extensions_initialized());
1081 EXPECT_EQ(0u, model_observer
.inserted_count());
1082 EXPECT_EQ(1u, model_observer
.initialized_count());
1085 // Check that the toolbar model correctly clears and reorders when it detects
1086 // a preference change.
1087 TEST_F(ExtensionToolbarModelUnitTest
, ToolbarModelPrefChange
) {
1090 ASSERT_TRUE(AddBrowserActionExtensions());
1092 // We should start in the basic A B C order.
1093 ASSERT_TRUE(browser_action_a());
1094 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0));
1095 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1));
1096 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2));
1097 // Record the difference between the inserted and removed counts. The actual
1098 // value of the counts is not important, but we need to be sure that if we
1099 // call to remove any, we also add them back.
1100 size_t inserted_and_removed_difference
=
1101 observer()->inserted_count() - observer()->removed_count();
1103 // Assign a new order, B C A, and write it in the prefs.
1104 ExtensionIdList new_order
;
1105 new_order
.push_back(browser_action_b()->id());
1106 new_order
.push_back(browser_action_c()->id());
1107 new_order
.push_back(browser_action_a()->id());
1108 ExtensionPrefs::Get(profile())->SetToolbarOrder(new_order
);
1110 // Ensure everything has time to run.
1111 base::RunLoop().RunUntilIdle();
1113 // The new order should be reflected in the model.
1114 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(0));
1115 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1));
1116 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(2));
1117 EXPECT_EQ(inserted_and_removed_difference
,
1118 observer()->inserted_count() - observer()->removed_count());
1121 TEST_F(ExtensionToolbarModelUnitTest
, ComponentExtesionsAddedToEnd
) {
1124 ASSERT_TRUE(AddBrowserActionExtensions());
1126 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0));
1127 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1));
1128 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2));
1130 const char kName
[] = "component";
1131 DictionaryBuilder manifest
;
1132 manifest
.Set("name", kName
)
1133 .Set("description", "An extension")
1134 .Set("manifest_version", 2)
1135 .Set("version", "1.0.0")
1136 .Set("browser_action", DictionaryBuilder().Pass());
1137 scoped_refptr
<const Extension
> component_extension
=
1138 ExtensionBuilder().SetManifest(manifest
.Pass())
1139 .SetID(crx_file::id_util::GenerateId(kName
))
1140 .SetLocation(Manifest::COMPONENT
)
1142 service()->AddExtension(component_extension
.get());
1144 EXPECT_EQ(component_extension
.get(), GetExtensionAtIndex(0));
1145 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(1));
1146 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(2));
1147 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(3));
1150 } // namespace extensions