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/feature_switch.h"
34 #include "ui/aura/env.h"
37 namespace extensions
{
41 // A simple observer that tracks the number of times certain events occur.
42 class ExtensionToolbarModelTestObserver
43 : public ExtensionToolbarModel::Observer
{
45 explicit ExtensionToolbarModelTestObserver(ExtensionToolbarModel
* model
);
46 ~ExtensionToolbarModelTestObserver() override
;
48 size_t inserted_count() const { return inserted_count_
; }
49 size_t removed_count() const { return removed_count_
; }
50 size_t moved_count() const { return moved_count_
; }
51 int highlight_mode_count() const { return highlight_mode_count_
; }
52 size_t initialized_count() const { return initialized_count_
; }
55 // ExtensionToolbarModel::Observer:
56 void ToolbarExtensionAdded(const Extension
* extension
, int index
) override
{
60 void ToolbarExtensionRemoved(const Extension
* extension
) override
{
64 void ToolbarExtensionMoved(const Extension
* extension
, int index
) override
{
68 void ToolbarExtensionUpdated(const Extension
* extension
) override
{}
70 bool ShowExtensionActionPopup(const Extension
* extension
,
71 bool grant_active_tab
) override
{
75 void ToolbarVisibleCountChanged() override
{}
77 void ToolbarHighlightModeChanged(bool is_highlighting
) override
{
78 // Add one if highlighting, subtract one if not.
79 highlight_mode_count_
+= is_highlighting
? 1 : -1;
82 void OnToolbarModelInitialized() override
{ ++initialized_count_
; }
84 Browser
* GetBrowser() override
{ return NULL
; }
86 ExtensionToolbarModel
* model_
;
88 size_t inserted_count_
;
89 size_t removed_count_
;
91 // Int because it could become negative (if something goes wrong).
92 int highlight_mode_count_
;
93 size_t initialized_count_
;
96 ExtensionToolbarModelTestObserver::ExtensionToolbarModelTestObserver(
97 ExtensionToolbarModel
* model
) : model_(model
),
101 highlight_mode_count_(0),
102 initialized_count_(0) {
103 model_
->AddObserver(this);
106 ExtensionToolbarModelTestObserver::~ExtensionToolbarModelTestObserver() {
107 model_
->RemoveObserver(this);
112 class ExtensionToolbarModelUnitTest
: public ExtensionServiceTestBase
{
114 // Initialize the ExtensionService, ExtensionToolbarModel, and
118 void TearDown() override
;
120 // Adds or removes the given |extension| and verify success.
121 testing::AssertionResult
AddExtension(
122 const scoped_refptr
<const Extension
>& extension
) WARN_UNUSED_RESULT
;
123 testing::AssertionResult
RemoveExtension(
124 const scoped_refptr
<const Extension
>& extension
) WARN_UNUSED_RESULT
;
126 // Adds three extensions, all with browser actions.
127 testing::AssertionResult
AddBrowserActionExtensions() WARN_UNUSED_RESULT
;
129 // Adds three extensions, one each for browser action, page action, and no
130 // action, and are added in that order.
131 testing::AssertionResult
AddActionExtensions() WARN_UNUSED_RESULT
;
133 // Returns the extension at the given index in the toolbar model, or NULL
134 // if one does not exist.
135 // If |model| is specified, it is used. Otherwise, this defaults to
137 const Extension
* GetExtensionAtIndex(
138 size_t index
, const ExtensionToolbarModel
* model
) const;
139 const Extension
* GetExtensionAtIndex(size_t index
) const;
141 ExtensionToolbarModel
* toolbar_model() { return toolbar_model_
; }
143 const ExtensionToolbarModelTestObserver
* observer() const {
144 return model_observer_
.get();
146 size_t num_toolbar_items() const {
147 return toolbar_model_
->toolbar_items().size();
149 const Extension
* browser_action_a() const { return browser_action_a_
.get(); }
150 const Extension
* browser_action_b() const { return browser_action_b_
.get(); }
151 const Extension
* browser_action_c() const { return browser_action_c_
.get(); }
152 const Extension
* browser_action() const {
153 return browser_action_extension_
.get();
155 const Extension
* page_action() const { return page_action_extension_
.get(); }
156 const Extension
* no_action() const { return no_action_extension_
.get(); }
159 // Verifies that all extensions in |extensions| are added successfully.
160 testing::AssertionResult
AddAndVerifyExtensions(
161 const ExtensionList
& extensions
);
163 // The toolbar model associated with the testing profile.
164 ExtensionToolbarModel
* toolbar_model_
;
166 // The test observer to track events. Must come after toolbar_model_ so that
167 // it is destroyed and removes itself as an observer first.
168 scoped_ptr
<ExtensionToolbarModelTestObserver
> model_observer_
;
170 // Sample extensions with only browser actions.
171 scoped_refptr
<const Extension
> browser_action_a_
;
172 scoped_refptr
<const Extension
> browser_action_b_
;
173 scoped_refptr
<const Extension
> browser_action_c_
;
175 // Sample extensions with different kinds of actions.
176 scoped_refptr
<const Extension
> browser_action_extension_
;
177 scoped_refptr
<const Extension
> page_action_extension_
;
178 scoped_refptr
<const Extension
> no_action_extension_
;
181 void ExtensionToolbarModelUnitTest::Init() {
182 InitializeEmptyExtensionService();
184 extension_action_test_util::CreateToolbarModelForProfile(profile());
185 model_observer_
.reset(new ExtensionToolbarModelTestObserver(toolbar_model_
));
188 void ExtensionToolbarModelUnitTest::TearDown() {
189 model_observer_
.reset();
190 ExtensionServiceTestBase::TearDown();
193 testing::AssertionResult
ExtensionToolbarModelUnitTest::AddExtension(
194 const scoped_refptr
<const Extension
>& extension
) {
195 if (registry()->enabled_extensions().GetByID(extension
->id())) {
196 return testing::AssertionFailure() << "Extension " << extension
->name() <<
197 " already installed!";
199 service()->AddExtension(extension
.get());
200 if (!registry()->enabled_extensions().GetByID(extension
->id())) {
201 return testing::AssertionFailure() << "Failed to install extension: " <<
204 return testing::AssertionSuccess();
207 testing::AssertionResult
ExtensionToolbarModelUnitTest::RemoveExtension(
208 const scoped_refptr
<const Extension
>& extension
) {
209 if (!registry()->enabled_extensions().GetByID(extension
->id())) {
210 return testing::AssertionFailure() << "Extension " << extension
->name() <<
213 service()->UnloadExtension(extension
->id(),
214 UnloadedExtensionInfo::REASON_DISABLE
);
215 if (registry()->enabled_extensions().GetByID(extension
->id())) {
216 return testing::AssertionFailure() << "Failed to unload extension: " <<
219 return testing::AssertionSuccess();
222 testing::AssertionResult
ExtensionToolbarModelUnitTest::AddActionExtensions() {
223 browser_action_extension_
= extension_action_test_util::CreateActionExtension(
224 "browser_action", extension_action_test_util::BROWSER_ACTION
);
225 page_action_extension_
= extension_action_test_util::CreateActionExtension(
226 "page_action", extension_action_test_util::PAGE_ACTION
);
227 no_action_extension_
= extension_action_test_util::CreateActionExtension(
228 "no_action", extension_action_test_util::NO_ACTION
);
230 ExtensionList extensions
;
231 extensions
.push_back(browser_action_extension_
);
232 extensions
.push_back(page_action_extension_
);
233 extensions
.push_back(no_action_extension_
);
235 return AddAndVerifyExtensions(extensions
);
238 testing::AssertionResult
239 ExtensionToolbarModelUnitTest::AddBrowserActionExtensions() {
240 browser_action_a_
= extension_action_test_util::CreateActionExtension(
241 "browser_actionA", extension_action_test_util::BROWSER_ACTION
);
242 browser_action_b_
= extension_action_test_util::CreateActionExtension(
243 "browser_actionB", extension_action_test_util::BROWSER_ACTION
);
244 browser_action_c_
= extension_action_test_util::CreateActionExtension(
245 "browser_actionC", extension_action_test_util::BROWSER_ACTION
);
247 ExtensionList extensions
;
248 extensions
.push_back(browser_action_a_
);
249 extensions
.push_back(browser_action_b_
);
250 extensions
.push_back(browser_action_c_
);
252 return AddAndVerifyExtensions(extensions
);
255 const Extension
* ExtensionToolbarModelUnitTest::GetExtensionAtIndex(
256 size_t index
, const ExtensionToolbarModel
* model
) const {
257 return index
< model
->toolbar_items().size()
258 ? model
->toolbar_items()[index
].get()
262 const Extension
* ExtensionToolbarModelUnitTest::GetExtensionAtIndex(
263 size_t index
) const {
264 return GetExtensionAtIndex(index
, toolbar_model_
);
267 testing::AssertionResult
ExtensionToolbarModelUnitTest::AddAndVerifyExtensions(
268 const ExtensionList
& extensions
) {
269 for (ExtensionList::const_iterator iter
= extensions
.begin();
270 iter
!= extensions
.end(); ++iter
) {
271 if (!AddExtension(*iter
)) {
272 return testing::AssertionFailure() << "Failed to install extension: " <<
276 return testing::AssertionSuccess();
279 // A basic test for extensions with browser actions showing up in the toolbar.
280 TEST_F(ExtensionToolbarModelUnitTest
, BasicExtensionToolbarModelTest
) {
283 // Load an extension with no browser action.
284 scoped_refptr
<const Extension
> extension1
=
285 extension_action_test_util::CreateActionExtension(
286 "no_action", extension_action_test_util::NO_ACTION
);
287 ASSERT_TRUE(AddExtension(extension1
));
289 // This extension should not be in the model (has no browser action).
290 EXPECT_EQ(0u, observer()->inserted_count());
291 EXPECT_EQ(0u, num_toolbar_items());
292 EXPECT_EQ(NULL
, GetExtensionAtIndex(0u));
294 // Load an extension with a browser action.
295 scoped_refptr
<const Extension
> extension2
=
296 extension_action_test_util::CreateActionExtension(
297 "browser_action", extension_action_test_util::BROWSER_ACTION
);
298 ASSERT_TRUE(AddExtension(extension2
));
300 // We should now find our extension in the model.
301 EXPECT_EQ(1u, observer()->inserted_count());
302 EXPECT_EQ(1u, num_toolbar_items());
303 EXPECT_EQ(extension2
.get(), GetExtensionAtIndex(0u));
305 // Should be a no-op, but still fires the events.
306 toolbar_model()->MoveExtensionIcon(extension2
->id(), 0);
307 EXPECT_EQ(1u, observer()->moved_count());
308 EXPECT_EQ(1u, num_toolbar_items());
309 EXPECT_EQ(extension2
.get(), GetExtensionAtIndex(0u));
311 // Remove the extension and verify.
312 ASSERT_TRUE(RemoveExtension(extension2
));
313 EXPECT_EQ(1u, observer()->removed_count());
314 EXPECT_EQ(0u, num_toolbar_items());
315 EXPECT_EQ(NULL
, GetExtensionAtIndex(0u));
318 // Test various different reorderings, removals, and reinsertions.
319 TEST_F(ExtensionToolbarModelUnitTest
, ExtensionToolbarReorderAndReinsert
) {
322 // Add the three browser action extensions.
323 ASSERT_TRUE(AddBrowserActionExtensions());
325 // Verify the three extensions are in the model in the proper order.
326 EXPECT_EQ(3u, num_toolbar_items());
327 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
328 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
329 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
331 // Order is now A, B, C. Let's put C first.
332 toolbar_model()->MoveExtensionIcon(browser_action_c()->id(), 0);
333 EXPECT_EQ(1u, observer()->moved_count());
334 EXPECT_EQ(3u, num_toolbar_items());
335 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
336 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(1u));
337 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(2u));
339 // Order is now C, A, B. Let's put A last.
340 toolbar_model()->MoveExtensionIcon(browser_action_a()->id(), 2);
341 EXPECT_EQ(2u, observer()->moved_count());
342 EXPECT_EQ(3u, num_toolbar_items());
343 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
344 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
345 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(2u));
347 // Order is now C, B, A. Let's remove B.
348 ASSERT_TRUE(RemoveExtension(browser_action_b()));
349 EXPECT_EQ(1u, observer()->removed_count());
350 EXPECT_EQ(2u, num_toolbar_items());
351 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
352 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(1u));
354 // Load extension B again.
355 ASSERT_TRUE(AddExtension(browser_action_b()));
357 // Extension B loaded again.
358 EXPECT_EQ(4u, observer()->inserted_count());
359 EXPECT_EQ(3u, num_toolbar_items());
360 // Make sure it gets its old spot in the list.
361 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
364 ASSERT_TRUE(RemoveExtension(browser_action_b()));
365 EXPECT_EQ(2u, observer()->removed_count());
366 EXPECT_EQ(2u, num_toolbar_items());
368 // Order is now C, A. Flip it.
369 toolbar_model()->MoveExtensionIcon(browser_action_a()->id(), 0);
370 EXPECT_EQ(3u, observer()->moved_count());
371 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
372 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
374 // Move A to the location it already occupies.
375 toolbar_model()->MoveExtensionIcon(browser_action_a()->id(), 0);
376 EXPECT_EQ(4u, observer()->moved_count());
377 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
378 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
380 // Order is now A, C. Remove C.
381 ASSERT_TRUE(RemoveExtension(browser_action_c()));
382 EXPECT_EQ(3u, observer()->removed_count());
383 EXPECT_EQ(1u, num_toolbar_items());
384 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
386 // Load extension C again.
387 ASSERT_TRUE(AddExtension(browser_action_c()));
389 // Extension C loaded again.
390 EXPECT_EQ(5u, observer()->inserted_count());
391 EXPECT_EQ(2u, num_toolbar_items());
392 // Make sure it gets its old spot in the list (at the very end).
393 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
396 // Test that order persists after unloading and disabling, but not across
398 TEST_F(ExtensionToolbarModelUnitTest
,
399 ExtensionToolbarUnloadDisableAndUninstall
) {
402 // Add the three browser action extensions.
403 ASSERT_TRUE(AddBrowserActionExtensions());
405 // Verify the three extensions are in the model in the proper order: A, B, C.
406 EXPECT_EQ(3u, num_toolbar_items());
407 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
408 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
409 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
411 // Unload B, then C, then A, and then reload C, then A, then B.
412 ASSERT_TRUE(RemoveExtension(browser_action_b()));
413 ASSERT_TRUE(RemoveExtension(browser_action_c()));
414 ASSERT_TRUE(RemoveExtension(browser_action_a()));
415 EXPECT_EQ(0u, num_toolbar_items()); // Sanity check: all gone?
416 ASSERT_TRUE(AddExtension(browser_action_c()));
417 ASSERT_TRUE(AddExtension(browser_action_a()));
418 ASSERT_TRUE(AddExtension(browser_action_b()));
419 EXPECT_EQ(3u, num_toolbar_items()); // Sanity check: all back?
420 EXPECT_EQ(0u, observer()->moved_count());
422 // Even though we unloaded and reloaded in a different order, the original
423 // order (A, B, C) should be preserved.
424 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
425 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
426 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
428 // Disabling extensions should also preserve order.
429 service()->DisableExtension(browser_action_b()->id(),
430 Extension::DISABLE_USER_ACTION
);
431 service()->DisableExtension(browser_action_c()->id(),
432 Extension::DISABLE_USER_ACTION
);
433 service()->DisableExtension(browser_action_a()->id(),
434 Extension::DISABLE_USER_ACTION
);
435 service()->EnableExtension(browser_action_c()->id());
436 service()->EnableExtension(browser_action_a()->id());
437 service()->EnableExtension(browser_action_b()->id());
439 // Make sure we still get the original A, B, C order.
440 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
441 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
442 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
444 // Move browser_action_b() to be first.
445 toolbar_model()->MoveExtensionIcon(browser_action_b()->id(), 0);
446 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(0u));
448 // Uninstall Extension B.
449 service()->UninstallExtension(browser_action_b()->id(),
450 UNINSTALL_REASON_FOR_TESTING
,
451 base::Bind(&base::DoNothing
),
452 NULL
); // Ignore error.
453 // List contains only A and C now. Validate that.
454 EXPECT_EQ(2u, num_toolbar_items());
455 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
456 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
458 ASSERT_TRUE(AddExtension(browser_action_b()));
460 // Make sure Extension B is _not_ first (its old position should have been
461 // forgotten at uninstall time). Order should be A, C, B.
462 EXPECT_EQ(3u, num_toolbar_items());
463 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
464 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
465 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(2u));
468 TEST_F(ExtensionToolbarModelUnitTest
, ReorderOnPrefChange
) {
471 // Add the three browser action extensions.
472 ASSERT_TRUE(AddBrowserActionExtensions());
473 EXPECT_EQ(3u, num_toolbar_items());
475 // Change the value of the toolbar preference.
476 ExtensionIdList new_order
;
477 new_order
.push_back(browser_action_c()->id());
478 new_order
.push_back(browser_action_b()->id());
479 ExtensionPrefs::Get(profile())->SetToolbarOrder(new_order
);
481 // Verify order is changed.
482 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
483 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
484 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(2u));
487 // Test that new extensions are always visible on installation and inserted at
488 // the "end" of the visible section.
489 TEST_F(ExtensionToolbarModelUnitTest
, NewToolbarExtensionsAreVisible
) {
492 // Three extensions with actions.
493 scoped_refptr
<const Extension
> extension_a
=
494 extension_action_test_util::CreateActionExtension(
495 "a", extension_action_test_util::BROWSER_ACTION
);
496 scoped_refptr
<const Extension
> extension_b
=
497 extension_action_test_util::CreateActionExtension(
498 "b", extension_action_test_util::BROWSER_ACTION
);
499 scoped_refptr
<const Extension
> extension_c
=
500 extension_action_test_util::CreateActionExtension(
501 "c", extension_action_test_util::BROWSER_ACTION
);
502 scoped_refptr
<const Extension
> extension_d
=
503 extension_action_test_util::CreateActionExtension(
504 "d", extension_action_test_util::BROWSER_ACTION
);
506 // We should start off without any extensions.
507 EXPECT_EQ(0u, num_toolbar_items());
508 EXPECT_EQ(0u, toolbar_model()->visible_icon_count());
510 // Add one extension. It should be visible.
511 service()->AddExtension(extension_a
.get());
512 EXPECT_EQ(1u, num_toolbar_items());
513 EXPECT_EQ(1u, toolbar_model()->visible_icon_count());
514 EXPECT_EQ(extension_a
.get(), GetExtensionAtIndex(0u));
516 // Hide all extensions.
517 toolbar_model()->SetVisibleIconCount(0);
518 EXPECT_EQ(0u, toolbar_model()->visible_icon_count());
520 // Add a new extension - it should be visible, so it should be in the first
521 // index. The other extension should remain hidden.
522 service()->AddExtension(extension_b
.get());
523 EXPECT_EQ(2u, num_toolbar_items());
524 EXPECT_EQ(1u, toolbar_model()->visible_icon_count());
525 EXPECT_EQ(extension_b
.get(), GetExtensionAtIndex(0u));
526 EXPECT_EQ(extension_a
.get(), GetExtensionAtIndex(1u));
528 // Show all extensions.
529 toolbar_model()->SetVisibleIconCount(2);
530 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
531 EXPECT_TRUE(toolbar_model()->all_icons_visible());
533 // Add the third extension. Since all extensions are visible, it should go in
535 service()->AddExtension(extension_c
.get());
536 EXPECT_EQ(3u, num_toolbar_items());
537 EXPECT_EQ(3u, toolbar_model()->visible_icon_count());
538 EXPECT_TRUE(toolbar_model()->all_icons_visible());
539 EXPECT_EQ(extension_b
.get(), GetExtensionAtIndex(0u));
540 EXPECT_EQ(extension_a
.get(), GetExtensionAtIndex(1u));
541 EXPECT_EQ(extension_c
.get(), GetExtensionAtIndex(2u));
543 // Hide one extension (two remaining visible).
544 toolbar_model()->SetVisibleIconCount(2);
545 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
547 // Add a fourth extension. It should go at the end of the visible section and
548 // be visible, so it increases visible count by 1, and goes into the third
549 // index. The hidden extension should remain hidden.
550 service()->AddExtension(extension_d
.get());
551 EXPECT_EQ(4u, num_toolbar_items());
552 EXPECT_EQ(3u, toolbar_model()->visible_icon_count());
553 EXPECT_EQ(extension_b
.get(), GetExtensionAtIndex(0u));
554 EXPECT_EQ(extension_a
.get(), GetExtensionAtIndex(1u));
555 EXPECT_EQ(extension_d
.get(), GetExtensionAtIndex(2u));
556 EXPECT_EQ(extension_c
.get(), GetExtensionAtIndex(3u));
559 TEST_F(ExtensionToolbarModelUnitTest
, ExtensionToolbarHighlightMode
) {
562 EXPECT_FALSE(toolbar_model()->HighlightExtensions(ExtensionIdList()));
563 EXPECT_EQ(0, observer()->highlight_mode_count());
565 // Add the three browser action extensions.
566 ASSERT_TRUE(AddBrowserActionExtensions());
567 EXPECT_EQ(3u, num_toolbar_items());
569 // Highlight one extension.
570 ExtensionIdList extension_ids
;
571 extension_ids
.push_back(browser_action_b()->id());
572 toolbar_model()->HighlightExtensions(extension_ids
);
573 EXPECT_EQ(1, observer()->highlight_mode_count());
574 EXPECT_TRUE(toolbar_model()->is_highlighting());
576 EXPECT_EQ(1u, num_toolbar_items());
577 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(0u));
579 // Stop highlighting.
580 toolbar_model()->StopHighlighting();
581 EXPECT_EQ(0, observer()->highlight_mode_count());
582 EXPECT_FALSE(toolbar_model()->is_highlighting());
584 // Verify that the extensions are back to normal.
585 EXPECT_EQ(3u, num_toolbar_items());
586 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
587 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
588 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
590 // Call stop highlighting a second time (shouldn't be notified).
591 toolbar_model()->StopHighlighting();
592 EXPECT_EQ(0, observer()->highlight_mode_count());
593 EXPECT_FALSE(toolbar_model()->is_highlighting());
595 // Highlight all extensions.
596 extension_ids
.clear();
597 extension_ids
.push_back(browser_action_a()->id());
598 extension_ids
.push_back(browser_action_b()->id());
599 extension_ids
.push_back(browser_action_c()->id());
600 toolbar_model()->HighlightExtensions(extension_ids
);
601 EXPECT_EQ(1, observer()->highlight_mode_count());
602 EXPECT_EQ(3u, num_toolbar_items());
603 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
604 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
605 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
607 // Highlight only extension b (shrink the highlight list).
608 extension_ids
.clear();
609 extension_ids
.push_back(browser_action_b()->id());
610 toolbar_model()->HighlightExtensions(extension_ids
);
611 EXPECT_EQ(2, observer()->highlight_mode_count());
612 EXPECT_EQ(1u, num_toolbar_items());
613 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(0u));
615 // Highlight extensions a and b (grow the highlight list).
616 extension_ids
.clear();
617 extension_ids
.push_back(browser_action_a()->id());
618 extension_ids
.push_back(browser_action_b()->id());
619 toolbar_model()->HighlightExtensions(extension_ids
);
620 EXPECT_EQ(3, observer()->highlight_mode_count());
621 EXPECT_EQ(2u, num_toolbar_items());
622 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
623 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
625 // Highlight no extensions (empty the highlight list).
626 extension_ids
.clear();
627 toolbar_model()->HighlightExtensions(extension_ids
);
628 EXPECT_EQ(2, observer()->highlight_mode_count());
629 EXPECT_FALSE(toolbar_model()->is_highlighting());
630 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
631 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
632 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
635 TEST_F(ExtensionToolbarModelUnitTest
, ExtensionToolbarHighlightModeRemove
) {
638 // Add the three browser action extensions.
639 ASSERT_TRUE(AddBrowserActionExtensions());
640 EXPECT_EQ(3u, num_toolbar_items());
642 // Highlight two of the extensions.
643 ExtensionIdList extension_ids
;
644 extension_ids
.push_back(browser_action_a()->id());
645 extension_ids
.push_back(browser_action_b()->id());
646 toolbar_model()->HighlightExtensions(extension_ids
);
647 EXPECT_TRUE(toolbar_model()->is_highlighting());
648 EXPECT_EQ(1, observer()->highlight_mode_count());
649 EXPECT_EQ(2u, num_toolbar_items());
651 // Disable one of them - only one should remain highlighted.
652 service()->DisableExtension(browser_action_a()->id(),
653 Extension::DISABLE_USER_ACTION
);
654 EXPECT_TRUE(toolbar_model()->is_highlighting());
655 EXPECT_EQ(1u, num_toolbar_items());
656 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(0u));
658 // Uninstall the remaining highlighted extension. This should result in
659 // highlight mode exiting.
660 service()->UninstallExtension(browser_action_b()->id(),
661 UNINSTALL_REASON_FOR_TESTING
,
662 base::Bind(&base::DoNothing
),
663 NULL
); // Ignore error.
664 EXPECT_FALSE(toolbar_model()->is_highlighting());
665 EXPECT_EQ(0, observer()->highlight_mode_count());
666 EXPECT_EQ(1u, num_toolbar_items());
667 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
669 // Test that removing an unhighlighted extension still works.
670 // Reinstall extension b, and then highlight extension c.
671 ASSERT_TRUE(AddExtension(browser_action_b()));
672 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
673 extension_ids
.clear();
674 extension_ids
.push_back(browser_action_c()->id());
675 toolbar_model()->HighlightExtensions(extension_ids
);
676 EXPECT_EQ(1, observer()->highlight_mode_count());
677 EXPECT_TRUE(toolbar_model()->is_highlighting());
678 EXPECT_EQ(1u, num_toolbar_items());
679 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
681 // Uninstalling b should not have visible impact.
682 service()->UninstallExtension(browser_action_b()->id(),
683 UNINSTALL_REASON_FOR_TESTING
,
684 base::Bind(&base::DoNothing
),
685 NULL
); // Ignore error.
686 EXPECT_TRUE(toolbar_model()->is_highlighting());
687 EXPECT_EQ(1, observer()->highlight_mode_count());
688 EXPECT_EQ(1u, num_toolbar_items());
689 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
691 // When we stop, only extension c should remain.
692 toolbar_model()->StopHighlighting();
693 EXPECT_FALSE(toolbar_model()->is_highlighting());
694 EXPECT_EQ(0, observer()->highlight_mode_count());
695 EXPECT_EQ(1u, num_toolbar_items());
696 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
699 TEST_F(ExtensionToolbarModelUnitTest
, ExtensionToolbarHighlightModeAdd
) {
702 // Add the three browser action extensions.
703 ASSERT_TRUE(AddBrowserActionExtensions());
704 EXPECT_EQ(3u, num_toolbar_items());
706 // Remove one (down to two).
707 ASSERT_TRUE(RemoveExtension(browser_action_c()));
709 // Highlight one of the two extensions.
710 ExtensionIdList extension_ids
;
711 extension_ids
.push_back(browser_action_a()->id());
712 toolbar_model()->HighlightExtensions(extension_ids
);
713 EXPECT_TRUE(toolbar_model()->is_highlighting());
714 EXPECT_EQ(1u, num_toolbar_items());
715 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
717 // Adding a new extension should have no visible effect.
718 ASSERT_TRUE(AddExtension(browser_action_c()));
719 EXPECT_TRUE(toolbar_model()->is_highlighting());
720 EXPECT_EQ(1u, num_toolbar_items());
721 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
723 // When we stop highlighting, we should see the new extension show up.
724 toolbar_model()->StopHighlighting();
725 EXPECT_FALSE(toolbar_model()->is_highlighting());
726 EXPECT_EQ(3u, num_toolbar_items());
727 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
728 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
729 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
732 // Test that the extension toolbar maintains the proper size, even after a pref
734 TEST_F(ExtensionToolbarModelUnitTest
, ExtensionToolbarSizeAfterPrefChange
) {
737 // Add the three browser action extensions.
738 ASSERT_TRUE(AddBrowserActionExtensions());
739 EXPECT_EQ(3u, num_toolbar_items());
741 // Should be at max size.
742 EXPECT_TRUE(toolbar_model()->all_icons_visible());
743 EXPECT_EQ(num_toolbar_items(), toolbar_model()->visible_icon_count());
744 toolbar_model()->OnExtensionToolbarPrefChange();
745 // Should still be at max size.
746 EXPECT_TRUE(toolbar_model()->all_icons_visible());
747 EXPECT_EQ(num_toolbar_items(), toolbar_model()->visible_icon_count());
750 // Test that, in the absence of the extension-action-redesign switch, the
751 // model only contains extensions with browser actions.
752 TEST_F(ExtensionToolbarModelUnitTest
, TestToolbarExtensionTypesNoSwitch
) {
754 ASSERT_TRUE(AddActionExtensions());
756 EXPECT_EQ(1u, num_toolbar_items());
757 EXPECT_EQ(browser_action(), GetExtensionAtIndex(0u));
760 // Test that, with the extension-action-redesign switch, the model contains
761 // all types of extensions, except those which should not be displayed on the
762 // toolbar (like component extensions).
763 TEST_F(ExtensionToolbarModelUnitTest
, TestToolbarExtensionTypesSwitch
) {
764 FeatureSwitch::ScopedOverride
enable_redesign(
765 FeatureSwitch::extension_action_redesign(), true);
767 ASSERT_TRUE(AddActionExtensions());
769 // With the switch on, extensions with page actions and no action should also
770 // be displayed in the toolbar.
771 EXPECT_EQ(3u, num_toolbar_items());
772 EXPECT_EQ(browser_action(), GetExtensionAtIndex(0u));
773 EXPECT_EQ(page_action(), GetExtensionAtIndex(1u));
774 EXPECT_EQ(no_action(), GetExtensionAtIndex(2u));
777 // Test that hiding actions on the toolbar results in their removal from the
778 // model when the redesign switch is not enabled.
779 TEST_F(ExtensionToolbarModelUnitTest
,
780 ExtensionToolbarActionsVisibilityNoSwitch
) {
783 ASSERT_TRUE(AddBrowserActionExtensions());
784 // Sanity check: Order should start as A B C.
785 EXPECT_EQ(3u, num_toolbar_items());
786 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
787 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
788 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
790 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(profile());
792 // By default, all actions should be visible.
793 EXPECT_TRUE(ExtensionActionAPI::GetBrowserActionVisibility(
794 prefs
, browser_action_a()->id()));
795 EXPECT_TRUE(ExtensionActionAPI::GetBrowserActionVisibility(
796 prefs
, browser_action_b()->id()));
797 EXPECT_TRUE(ExtensionActionAPI::GetBrowserActionVisibility(
798 prefs
, browser_action_c()->id()));
800 // Hiding an action should result in its removal from the toolbar.
801 ExtensionActionAPI::SetBrowserActionVisibility(
802 prefs
, browser_action_b()->id(), false);
803 EXPECT_FALSE(ExtensionActionAPI::GetBrowserActionVisibility(
804 prefs
, browser_action_b()->id()));
805 // Thus, there should now only be two items on the toolbar - A and C.
806 EXPECT_EQ(2u, num_toolbar_items());
807 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
808 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
810 // Resetting the visibility to 'true' should result in the extension being
811 // added back at its original position.
812 ExtensionActionAPI::SetBrowserActionVisibility(
813 prefs
, browser_action_b()->id(), true);
814 EXPECT_TRUE(ExtensionActionAPI::GetBrowserActionVisibility(
815 prefs
, browser_action_b()->id()));
816 // So the toolbar order should be A B C.
817 EXPECT_EQ(3u, num_toolbar_items());
818 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
819 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
820 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
823 TEST_F(ExtensionToolbarModelUnitTest
, ExtensionToolbarIncognitoModeTest
) {
825 ASSERT_TRUE(AddBrowserActionExtensions());
827 // Give two extensions incognito access.
828 // Note: We use ExtensionPrefs::SetIsIncognitoEnabled instead of
829 // util::SetIsIncognitoEnabled because the latter tries to reload the
830 // extension, which requries a filepath associated with the extension (and,
831 // for this test, reloading the extension is irrelevant to us).
832 ExtensionPrefs
* extension_prefs
= ExtensionPrefs::Get(profile());
833 extension_prefs
->SetIsIncognitoEnabled(browser_action_b()->id(), true);
834 extension_prefs
->SetIsIncognitoEnabled(browser_action_c()->id(), true);
836 util::SetIsIncognitoEnabled(browser_action_b()->id(), profile(), true);
837 util::SetIsIncognitoEnabled(browser_action_c()->id(), profile(), true);
839 // Move C to the second index.
840 toolbar_model()->MoveExtensionIcon(browser_action_c()->id(), 1u);
841 // Set visible count to 2 so that c is overflowed. State is A C [B].
842 toolbar_model()->SetVisibleIconCount(2);
843 EXPECT_EQ(1u, observer()->moved_count());
845 // Get an incognito profile and toolbar.
846 ExtensionToolbarModel
* incognito_model
=
847 extension_action_test_util::CreateToolbarModelForProfile(
848 profile()->GetOffTheRecordProfile());
850 ExtensionToolbarModelTestObserver
incognito_observer(incognito_model
);
851 EXPECT_EQ(0u, incognito_observer
.moved_count());
853 // We should have two items, C and B, and the order should be preserved from
854 // the original model.
855 EXPECT_EQ(2u, incognito_model
->toolbar_items().size());
856 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u, incognito_model
));
857 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u, incognito_model
));
859 // Extensions in the overflow menu in the regular toolbar should remain in
860 // overflow in the incognito toolbar. So, we should have C [B].
861 EXPECT_EQ(1u, incognito_model
->visible_icon_count());
862 // The regular model should still have two icons visible.
863 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
865 // Changing the incognito model size should not affect the regular model.
866 incognito_model
->SetVisibleIconCount(0);
867 EXPECT_EQ(0u, incognito_model
->visible_icon_count());
868 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
870 // Expanding the incognito model to 2 should register as "all icons"
871 // since it is all of the incognito-enabled extensions.
872 incognito_model
->SetVisibleIconCount(2u);
873 EXPECT_EQ(2u, incognito_model
->visible_icon_count());
874 EXPECT_TRUE(incognito_model
->all_icons_visible());
876 // Moving icons in the incognito toolbar should not affect the regular
877 // toolbar. Incognito currently has C B...
878 incognito_model
->MoveExtensionIcon(browser_action_b()->id(), 0u);
879 // So now it should be B C...
880 EXPECT_EQ(1u, incognito_observer
.moved_count());
881 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(0u, incognito_model
));
882 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u, incognito_model
));
883 // ... and the regular toolbar should be unaffected.
884 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
885 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
886 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(2u));
888 // Similarly, the observer for the regular model should not have received
890 EXPECT_EQ(1u, observer()->moved_count());
892 // And performing moves on the regular model should have no effect on the
893 // incognito model or its observers.
894 toolbar_model()->MoveExtensionIcon(browser_action_c()->id(), 2u);
895 EXPECT_EQ(2u, observer()->moved_count());
896 EXPECT_EQ(1u, incognito_observer
.moved_count());
899 // Test that enabling extensions incognito with an active incognito profile
901 TEST_F(ExtensionToolbarModelUnitTest
,
902 ExtensionToolbarIncognitoEnableExtension
) {
905 const char* kManifest
=
908 " \"version\": \"1.0\","
909 " \"manifest_version\": 2,"
910 " \"browser_action\": {}"
913 // For this test, we need to have "real" extension files, because we need to
914 // be able to reload them during the incognito process. Since the toolbar
915 // needs to be notified of the reload, we need it this time (as opposed to
916 // above, where we simply set the prefs before the incognito bar was
918 TestExtensionDir dir1
;
919 dir1
.WriteManifest(base::StringPrintf(kManifest
, "incognito1"));
920 TestExtensionDir dir2
;
921 dir2
.WriteManifest(base::StringPrintf(kManifest
, "incognito2"));
923 TestExtensionDir
* dirs
[] = { &dir1
, &dir2
};
924 const Extension
* extensions
[] = { nullptr, nullptr };
925 for (size_t i
= 0; i
< arraysize(dirs
); ++i
) {
926 // The extension id will be calculated from the file path; we need this to
927 // wait for the extension to load.
928 base::FilePath path_for_id
=
929 base::MakeAbsoluteFilePath(dirs
[i
]->unpacked_path());
930 std::string id
= crx_file::id_util::GenerateIdForPath(path_for_id
);
931 TestExtensionRegistryObserver
observer(registry(), id
);
932 UnpackedInstaller::Create(service())->Load(dirs
[i
]->unpacked_path());
933 observer
.WaitForExtensionLoaded();
934 extensions
[i
] = registry()->enabled_extensions().GetByID(id
);
935 ASSERT_TRUE(extensions
[i
]);
938 // For readability, alias to A and B. Since we'll be reloading these
939 // extensions, we also can't rely on pointers.
940 std::string extension_a
= extensions
[0]->id();
941 std::string extension_b
= extensions
[1]->id();
943 // The first model should have both extensions visible.
944 EXPECT_EQ(2u, toolbar_model()->toolbar_items().size());
945 EXPECT_EQ(extension_a
, GetExtensionAtIndex(0)->id());
946 EXPECT_EQ(extension_b
, GetExtensionAtIndex(1)->id());
948 // Set the model to only show one extension, so the order is A [B].
949 toolbar_model()->SetVisibleIconCount(1u);
951 // Get an incognito profile and toolbar.
952 ExtensionToolbarModel
* incognito_model
=
953 extension_action_test_util::CreateToolbarModelForProfile(
954 profile()->GetOffTheRecordProfile());
955 ExtensionToolbarModelTestObserver
incognito_observer(incognito_model
);
957 // Right now, no extensions are enabled in incognito mode.
958 EXPECT_EQ(0u, incognito_model
->toolbar_items().size());
960 // Set extension b (which is overflowed) to be enabled in incognito. This
961 // results in b reloading, so wait for it.
963 TestExtensionRegistryObserver
observer(registry(), extension_b
);
964 util::SetIsIncognitoEnabled(extension_b
, profile(), true);
965 observer
.WaitForExtensionLoaded();
968 // Now, we should have one icon in the incognito bar. But, since B is
969 // overflowed in the main bar, it shouldn't be visible.
970 EXPECT_EQ(1u, incognito_model
->toolbar_items().size());
971 EXPECT_EQ(extension_b
, GetExtensionAtIndex(0u, incognito_model
)->id());
972 EXPECT_EQ(0u, incognito_model
->visible_icon_count());
974 // Also enable extension a for incognito (again, wait for the reload).
976 TestExtensionRegistryObserver
observer(registry(), extension_a
);
977 util::SetIsIncognitoEnabled(extension_a
, profile(), true);
978 observer
.WaitForExtensionLoaded();
981 // Now, both extensions should be enabled in incognito mode. In addition, the
982 // incognito toolbar should have expanded to show extension a (since it isn't
983 // overflowed in the main bar).
984 EXPECT_EQ(2u, incognito_model
->toolbar_items().size());
985 EXPECT_EQ(extension_a
, GetExtensionAtIndex(0u, incognito_model
)->id());
986 EXPECT_EQ(extension_b
, GetExtensionAtIndex(1u, incognito_model
)->id());
987 EXPECT_EQ(1u, incognito_model
->visible_icon_count());
990 // Test that hiding actions on the toolbar results in sending them to the
991 // overflow menu when the redesign switch is enabled.
992 TEST_F(ExtensionToolbarModelUnitTest
,
993 ExtensionToolbarActionsVisibilityWithSwitch
) {
994 FeatureSwitch::ScopedOverride
enable_redesign(
995 FeatureSwitch::extension_action_redesign(), true);
998 // We choose to use all types of extensions here, since the misnamed
999 // BrowserActionVisibility is now for toolbar visibility.
1000 ASSERT_TRUE(AddActionExtensions());
1002 // For readability, alias extensions A B C.
1003 const Extension
* extension_a
= browser_action();
1004 const Extension
* extension_b
= page_action();
1005 const Extension
* extension_c
= no_action();
1007 // Sanity check: Order should start as A B C, with all three visible.
1008 EXPECT_EQ(3u, num_toolbar_items());
1009 EXPECT_TRUE(toolbar_model()->all_icons_visible());
1010 EXPECT_EQ(extension_a
, GetExtensionAtIndex(0u));
1011 EXPECT_EQ(extension_b
, GetExtensionAtIndex(1u));
1012 EXPECT_EQ(extension_c
, GetExtensionAtIndex(2u));
1014 ExtensionPrefs
* prefs
= ExtensionPrefs::Get(profile());
1016 // By default, all actions should be visible.
1017 EXPECT_TRUE(ExtensionActionAPI::GetBrowserActionVisibility(
1018 prefs
, extension_a
->id()));
1019 EXPECT_TRUE(ExtensionActionAPI::GetBrowserActionVisibility(
1020 prefs
, extension_c
->id()));
1021 EXPECT_TRUE(ExtensionActionAPI::GetBrowserActionVisibility(
1022 prefs
, extension_b
->id()));
1024 // Hiding an action should result in it being sent to the overflow menu.
1025 ExtensionActionAPI::SetBrowserActionVisibility(
1026 prefs
, extension_b
->id(), false);
1028 // Thus, the order should be A C B, with B in the overflow.
1029 EXPECT_EQ(3u, num_toolbar_items());
1030 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
1031 EXPECT_EQ(extension_a
, GetExtensionAtIndex(0u));
1032 EXPECT_EQ(extension_c
, GetExtensionAtIndex(1u));
1033 EXPECT_EQ(extension_b
, GetExtensionAtIndex(2u));
1035 // Hiding an extension's action should result in it being sent to the overflow
1036 // as well, but as the _first_ extension in the overflow.
1037 ExtensionActionAPI::SetBrowserActionVisibility(
1038 prefs
, extension_a
->id(), false);
1039 // Thus, the order should be C A B, with A and B in the overflow.
1040 EXPECT_EQ(3u, num_toolbar_items());
1041 EXPECT_EQ(1u, toolbar_model()->visible_icon_count());
1042 EXPECT_EQ(extension_c
, GetExtensionAtIndex(0u));
1043 EXPECT_EQ(extension_a
, GetExtensionAtIndex(1u));
1044 EXPECT_EQ(extension_b
, GetExtensionAtIndex(2u));
1046 // Resetting A's visibility to true should send it back to the visible icons
1047 // (and should grow visible icons by 1), but it should be added to the end of
1048 // the visible icon list (not to its original position).
1049 ExtensionActionAPI::SetBrowserActionVisibility(
1050 prefs
, extension_a
->id(), true);
1051 // So order is C A B, with only B in the overflow.
1052 EXPECT_EQ(3u, num_toolbar_items());
1053 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
1054 EXPECT_EQ(extension_c
, GetExtensionAtIndex(0u));
1055 EXPECT_EQ(extension_a
, GetExtensionAtIndex(1u));
1056 EXPECT_EQ(extension_b
, GetExtensionAtIndex(2u));
1058 // Resetting B to be visible should make the order C A B, with no overflow.
1059 ExtensionActionAPI::SetBrowserActionVisibility(
1060 prefs
, extension_b
->id(), true);
1061 EXPECT_EQ(3u, num_toolbar_items());
1062 EXPECT_TRUE(toolbar_model()->all_icons_visible());
1063 EXPECT_EQ(extension_c
, GetExtensionAtIndex(0u));
1064 EXPECT_EQ(extension_a
, GetExtensionAtIndex(1u));
1065 EXPECT_EQ(extension_b
, GetExtensionAtIndex(2u));
1068 // Test that observers receive no Added notifications until after the
1069 // ExtensionSystem has initialized.
1070 TEST_F(ExtensionToolbarModelUnitTest
, ModelWaitsForExtensionSystemReady
) {
1071 InitializeEmptyExtensionService();
1072 ExtensionToolbarModel
* toolbar_model
=
1073 extension_action_test_util::
1074 CreateToolbarModelForProfileWithoutWaitingForReady(profile());
1075 ExtensionToolbarModelTestObserver
model_observer(toolbar_model
);
1076 EXPECT_TRUE(AddBrowserActionExtensions());
1078 // Since the model hasn't been initialized (the ExtensionSystem::ready task
1079 // hasn't been run), there should be no insertion notifications.
1080 EXPECT_EQ(0u, model_observer
.inserted_count());
1081 EXPECT_EQ(0u, model_observer
.initialized_count());
1082 EXPECT_FALSE(toolbar_model
->extensions_initialized());
1084 // Run the ready task.
1085 static_cast<TestExtensionSystem
*>(ExtensionSystem::Get(profile()))->
1087 // Run tasks posted to TestExtensionSystem.
1088 base::RunLoop().RunUntilIdle();
1090 // We should still have no insertions, but should have an initialized count.
1091 EXPECT_TRUE(toolbar_model
->extensions_initialized());
1092 EXPECT_EQ(0u, model_observer
.inserted_count());
1093 EXPECT_EQ(1u, model_observer
.initialized_count());
1096 // Check that the toolbar model correctly clears and reorders when it detects
1097 // a preference change.
1098 TEST_F(ExtensionToolbarModelUnitTest
, ToolbarModelPrefChange
) {
1101 ASSERT_TRUE(AddBrowserActionExtensions());
1103 // We should start in the basic A B C order.
1104 ASSERT_TRUE(browser_action_a());
1105 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0));
1106 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1));
1107 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2));
1108 // Record the difference between the inserted and removed counts. The actual
1109 // value of the counts is not important, but we need to be sure that if we
1110 // call to remove any, we also add them back.
1111 size_t inserted_and_removed_difference
=
1112 observer()->inserted_count() - observer()->removed_count();
1114 // Assign a new order, B C A, and write it in the prefs.
1115 ExtensionIdList new_order
;
1116 new_order
.push_back(browser_action_b()->id());
1117 new_order
.push_back(browser_action_c()->id());
1118 new_order
.push_back(browser_action_a()->id());
1119 ExtensionPrefs::Get(profile())->SetToolbarOrder(new_order
);
1121 // Ensure everything has time to run.
1122 base::RunLoop().RunUntilIdle();
1124 // The new order should be reflected in the model.
1125 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(0));
1126 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1));
1127 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(2));
1128 EXPECT_EQ(inserted_and_removed_difference
,
1129 observer()->inserted_count() - observer()->removed_count());
1132 } // namespace extensions