Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(281)

Side by Side Diff: chrome/browser/extensions/extension_toolbar_model_unittest.cc

Issue 1241063003: Support Component Actions in the toolbar. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Changes per isherman@'s comments. Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
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.
4
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/browser/ui/extensions/extension_toolbar_icon_surfacing_bubble_d elegate.h"
23 #include "chrome/common/extensions/api/extension_action/action_info.h"
24 #include "components/crx_file/id_util.h"
25 #include "content/public/test/test_renderer_host.h"
26 #include "content/public/test/web_contents_tester.h"
27 #include "extensions/browser/extension_prefs.h"
28 #include "extensions/browser/extension_registry.h"
29 #include "extensions/browser/extension_system.h"
30 #include "extensions/browser/pref_names.h"
31 #include "extensions/browser/test_extension_registry_observer.h"
32 #include "extensions/common/extension.h"
33 #include "extensions/common/extension_builder.h"
34 #include "extensions/common/feature_switch.h"
35 #include "extensions/common/value_builder.h"
36
37 #if defined(USE_AURA)
38 #include "ui/aura/env.h"
39 #endif
40
41 namespace extensions {
42
43 namespace {
44
45 // A simple observer that tracks the number of times certain events occur.
46 class ExtensionToolbarModelTestObserver
47 : public ExtensionToolbarModel::Observer {
48 public:
49 explicit ExtensionToolbarModelTestObserver(ExtensionToolbarModel* model);
50 ~ExtensionToolbarModelTestObserver() override;
51
52 size_t inserted_count() const { return inserted_count_; }
53 size_t removed_count() const { return removed_count_; }
54 size_t moved_count() const { return moved_count_; }
55 int highlight_mode_count() const { return highlight_mode_count_; }
56 size_t initialized_count() const { return initialized_count_; }
57
58 private:
59 // ExtensionToolbarModel::Observer:
60 void OnToolbarExtensionAdded(const Extension* extension, int index) override {
61 ++inserted_count_;
62 }
63
64 void OnToolbarExtensionRemoved(const Extension* extension) override {
65 ++removed_count_;
66 }
67
68 void OnToolbarExtensionMoved(const Extension* extension, int index) override {
69 ++moved_count_;
70 }
71
72 void OnToolbarExtensionUpdated(const Extension* extension) override {}
73
74 bool ShowExtensionActionPopup(const Extension* extension,
75 bool grant_active_tab) override {
76 return false;
77 }
78
79 void OnToolbarVisibleCountChanged() override {}
80
81 void OnToolbarHighlightModeChanged(bool is_highlighting) override {
82 // Add one if highlighting, subtract one if not.
83 highlight_mode_count_ += is_highlighting ? 1 : -1;
84 }
85
86 void OnToolbarModelInitialized() override { ++initialized_count_; }
87
88 Browser* GetBrowser() override { return NULL; }
89
90 ExtensionToolbarModel* model_;
91
92 size_t inserted_count_;
93 size_t removed_count_;
94 size_t moved_count_;
95 // Int because it could become negative (if something goes wrong).
96 int highlight_mode_count_;
97 size_t initialized_count_;
98 };
99
100 ExtensionToolbarModelTestObserver::ExtensionToolbarModelTestObserver(
101 ExtensionToolbarModel* model) : model_(model),
102 inserted_count_(0),
103 removed_count_(0),
104 moved_count_(0),
105 highlight_mode_count_(0),
106 initialized_count_(0) {
107 model_->AddObserver(this);
108 }
109
110 ExtensionToolbarModelTestObserver::~ExtensionToolbarModelTestObserver() {
111 model_->RemoveObserver(this);
112 }
113
114 } // namespace
115
116 class ExtensionToolbarModelUnitTest : public ExtensionServiceTestBase {
117 protected:
118 // Initialize the ExtensionService, ExtensionToolbarModel, and
119 // ExtensionSystem.
120 void Init();
121
122 void TearDown() override;
123
124 // Adds or removes the given |extension| and verify success.
125 testing::AssertionResult AddExtension(
126 const scoped_refptr<const Extension>& extension) WARN_UNUSED_RESULT;
127 testing::AssertionResult RemoveExtension(
128 const scoped_refptr<const Extension>& extension) WARN_UNUSED_RESULT;
129
130 // Adds three extensions, all with browser actions.
131 testing::AssertionResult AddBrowserActionExtensions() WARN_UNUSED_RESULT;
132
133 // Adds three extensions, one each for browser action, page action, and no
134 // action, and are added in that order.
135 testing::AssertionResult AddActionExtensions() WARN_UNUSED_RESULT;
136
137 // Returns the extension at the given index in the toolbar model, or NULL
138 // if one does not exist.
139 // If |model| is specified, it is used. Otherwise, this defaults to
140 // |toolbar_model_|.
141 const Extension* GetExtensionAtIndex(
142 size_t index, const ExtensionToolbarModel* model) const;
143 const Extension* GetExtensionAtIndex(size_t index) const;
144
145 ExtensionToolbarModel* toolbar_model() { return toolbar_model_; }
146
147 const ExtensionToolbarModelTestObserver* observer() const {
148 return model_observer_.get();
149 }
150 size_t num_toolbar_items() const {
151 return toolbar_model_->toolbar_items().size();
152 }
153 const Extension* browser_action_a() const { return browser_action_a_.get(); }
154 const Extension* browser_action_b() const { return browser_action_b_.get(); }
155 const Extension* browser_action_c() const { return browser_action_c_.get(); }
156 const Extension* browser_action() const {
157 return browser_action_extension_.get();
158 }
159 const Extension* page_action() const { return page_action_extension_.get(); }
160 const Extension* no_action() const { return no_action_extension_.get(); }
161
162 private:
163 // Verifies that all extensions in |extensions| are added successfully.
164 testing::AssertionResult AddAndVerifyExtensions(
165 const ExtensionList& extensions);
166
167 // The toolbar model associated with the testing profile.
168 ExtensionToolbarModel* toolbar_model_;
169
170 // The test observer to track events. Must come after toolbar_model_ so that
171 // it is destroyed and removes itself as an observer first.
172 scoped_ptr<ExtensionToolbarModelTestObserver> model_observer_;
173
174 // Sample extensions with only browser actions.
175 scoped_refptr<const Extension> browser_action_a_;
176 scoped_refptr<const Extension> browser_action_b_;
177 scoped_refptr<const Extension> browser_action_c_;
178
179 // Sample extensions with different kinds of actions.
180 scoped_refptr<const Extension> browser_action_extension_;
181 scoped_refptr<const Extension> page_action_extension_;
182 scoped_refptr<const Extension> no_action_extension_;
183 };
184
185 void ExtensionToolbarModelUnitTest::Init() {
186 InitializeEmptyExtensionService();
187 toolbar_model_ =
188 extension_action_test_util::CreateToolbarModelForProfile(profile());
189 model_observer_.reset(new ExtensionToolbarModelTestObserver(toolbar_model_));
190 }
191
192 void ExtensionToolbarModelUnitTest::TearDown() {
193 model_observer_.reset();
194 ExtensionServiceTestBase::TearDown();
195 }
196
197 testing::AssertionResult ExtensionToolbarModelUnitTest::AddExtension(
198 const scoped_refptr<const Extension>& extension) {
199 if (registry()->enabled_extensions().GetByID(extension->id())) {
200 return testing::AssertionFailure() << "Extension " << extension->name() <<
201 " already installed!";
202 }
203 service()->AddExtension(extension.get());
204 if (!registry()->enabled_extensions().GetByID(extension->id())) {
205 return testing::AssertionFailure() << "Failed to install extension: " <<
206 extension->name();
207 }
208 return testing::AssertionSuccess();
209 }
210
211 testing::AssertionResult ExtensionToolbarModelUnitTest::RemoveExtension(
212 const scoped_refptr<const Extension>& extension) {
213 if (!registry()->enabled_extensions().GetByID(extension->id())) {
214 return testing::AssertionFailure() << "Extension " << extension->name() <<
215 " not installed!";
216 }
217 service()->UnloadExtension(extension->id(),
218 UnloadedExtensionInfo::REASON_DISABLE);
219 if (registry()->enabled_extensions().GetByID(extension->id())) {
220 return testing::AssertionFailure() << "Failed to unload extension: " <<
221 extension->name();
222 }
223 return testing::AssertionSuccess();
224 }
225
226 testing::AssertionResult ExtensionToolbarModelUnitTest::AddActionExtensions() {
227 browser_action_extension_ = extension_action_test_util::CreateActionExtension(
228 "browser_action", extension_action_test_util::BROWSER_ACTION);
229 page_action_extension_ = extension_action_test_util::CreateActionExtension(
230 "page_action", extension_action_test_util::PAGE_ACTION);
231 no_action_extension_ = extension_action_test_util::CreateActionExtension(
232 "no_action", extension_action_test_util::NO_ACTION);
233
234 ExtensionList extensions;
235 extensions.push_back(browser_action_extension_);
236 extensions.push_back(page_action_extension_);
237 extensions.push_back(no_action_extension_);
238
239 return AddAndVerifyExtensions(extensions);
240 }
241
242 testing::AssertionResult
243 ExtensionToolbarModelUnitTest::AddBrowserActionExtensions() {
244 browser_action_a_ = extension_action_test_util::CreateActionExtension(
245 "browser_actionA", extension_action_test_util::BROWSER_ACTION);
246 browser_action_b_ = extension_action_test_util::CreateActionExtension(
247 "browser_actionB", extension_action_test_util::BROWSER_ACTION);
248 browser_action_c_ = extension_action_test_util::CreateActionExtension(
249 "browser_actionC", extension_action_test_util::BROWSER_ACTION);
250
251 ExtensionList extensions;
252 extensions.push_back(browser_action_a_);
253 extensions.push_back(browser_action_b_);
254 extensions.push_back(browser_action_c_);
255
256 return AddAndVerifyExtensions(extensions);
257 }
258
259 const Extension* ExtensionToolbarModelUnitTest::GetExtensionAtIndex(
260 size_t index, const ExtensionToolbarModel* model) const {
261 return index < model->toolbar_items().size()
262 ? model->toolbar_items()[index].get()
263 : NULL;
264 }
265
266 const Extension* ExtensionToolbarModelUnitTest::GetExtensionAtIndex(
267 size_t index) const {
268 return GetExtensionAtIndex(index, toolbar_model_);
269 }
270
271 testing::AssertionResult ExtensionToolbarModelUnitTest::AddAndVerifyExtensions(
272 const ExtensionList& extensions) {
273 for (ExtensionList::const_iterator iter = extensions.begin();
274 iter != extensions.end(); ++iter) {
275 if (!AddExtension(*iter)) {
276 return testing::AssertionFailure() << "Failed to install extension: " <<
277 (*iter)->name();
278 }
279 }
280 return testing::AssertionSuccess();
281 }
282
283 // A basic test for extensions with browser actions showing up in the toolbar.
284 TEST_F(ExtensionToolbarModelUnitTest, BasicExtensionToolbarModelTest) {
285 Init();
286
287 // Load an extension with no browser action.
288 scoped_refptr<const Extension> extension1 =
289 extension_action_test_util::CreateActionExtension(
290 "no_action", extension_action_test_util::NO_ACTION);
291 ASSERT_TRUE(AddExtension(extension1));
292
293 // This extension should not be in the model (has no browser action).
294 EXPECT_EQ(0u, observer()->inserted_count());
295 EXPECT_EQ(0u, num_toolbar_items());
296 EXPECT_EQ(NULL, GetExtensionAtIndex(0u));
297
298 // Load an extension with a browser action.
299 scoped_refptr<const Extension> extension2 =
300 extension_action_test_util::CreateActionExtension(
301 "browser_action", extension_action_test_util::BROWSER_ACTION);
302 ASSERT_TRUE(AddExtension(extension2));
303
304 // We should now find our extension in the model.
305 EXPECT_EQ(1u, observer()->inserted_count());
306 EXPECT_EQ(1u, num_toolbar_items());
307 EXPECT_EQ(extension2.get(), GetExtensionAtIndex(0u));
308
309 // Should be a no-op, but still fires the events.
310 toolbar_model()->MoveExtensionIcon(extension2->id(), 0);
311 EXPECT_EQ(1u, observer()->moved_count());
312 EXPECT_EQ(1u, num_toolbar_items());
313 EXPECT_EQ(extension2.get(), GetExtensionAtIndex(0u));
314
315 // Remove the extension and verify.
316 ASSERT_TRUE(RemoveExtension(extension2));
317 EXPECT_EQ(1u, observer()->removed_count());
318 EXPECT_EQ(0u, num_toolbar_items());
319 EXPECT_EQ(NULL, GetExtensionAtIndex(0u));
320 }
321
322 // Test various different reorderings, removals, and reinsertions.
323 TEST_F(ExtensionToolbarModelUnitTest, ExtensionToolbarReorderAndReinsert) {
324 Init();
325
326 // Add the three browser action extensions.
327 ASSERT_TRUE(AddBrowserActionExtensions());
328
329 // Verify the three extensions are in the model in the proper order.
330 EXPECT_EQ(3u, num_toolbar_items());
331 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
332 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
333 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
334
335 // Order is now A, B, C. Let's put C first.
336 toolbar_model()->MoveExtensionIcon(browser_action_c()->id(), 0);
337 EXPECT_EQ(1u, observer()->moved_count());
338 EXPECT_EQ(3u, num_toolbar_items());
339 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
340 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(1u));
341 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(2u));
342
343 // Order is now C, A, B. Let's put A last.
344 toolbar_model()->MoveExtensionIcon(browser_action_a()->id(), 2);
345 EXPECT_EQ(2u, observer()->moved_count());
346 EXPECT_EQ(3u, num_toolbar_items());
347 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
348 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
349 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(2u));
350
351 // Order is now C, B, A. Let's remove B.
352 ASSERT_TRUE(RemoveExtension(browser_action_b()));
353 EXPECT_EQ(1u, observer()->removed_count());
354 EXPECT_EQ(2u, num_toolbar_items());
355 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
356 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(1u));
357
358 // Load extension B again.
359 ASSERT_TRUE(AddExtension(browser_action_b()));
360
361 // Extension B loaded again.
362 EXPECT_EQ(4u, observer()->inserted_count());
363 EXPECT_EQ(3u, num_toolbar_items());
364 // Make sure it gets its old spot in the list.
365 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
366
367 // Unload B again.
368 ASSERT_TRUE(RemoveExtension(browser_action_b()));
369 EXPECT_EQ(2u, observer()->removed_count());
370 EXPECT_EQ(2u, num_toolbar_items());
371
372 // Order is now C, A. Flip it.
373 toolbar_model()->MoveExtensionIcon(browser_action_a()->id(), 0);
374 EXPECT_EQ(3u, observer()->moved_count());
375 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
376 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
377
378 // Move A to the location it already occupies.
379 toolbar_model()->MoveExtensionIcon(browser_action_a()->id(), 0);
380 EXPECT_EQ(4u, observer()->moved_count());
381 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
382 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
383
384 // Order is now A, C. Remove C.
385 ASSERT_TRUE(RemoveExtension(browser_action_c()));
386 EXPECT_EQ(3u, observer()->removed_count());
387 EXPECT_EQ(1u, num_toolbar_items());
388 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
389
390 // Load extension C again.
391 ASSERT_TRUE(AddExtension(browser_action_c()));
392
393 // Extension C loaded again.
394 EXPECT_EQ(5u, observer()->inserted_count());
395 EXPECT_EQ(2u, num_toolbar_items());
396 // Make sure it gets its old spot in the list (at the very end).
397 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
398 }
399
400 // Test that order persists after unloading and disabling, but not across
401 // uninstallation.
402 TEST_F(ExtensionToolbarModelUnitTest,
403 ExtensionToolbarUnloadDisableAndUninstall) {
404 Init();
405
406 // Add the three browser action extensions.
407 ASSERT_TRUE(AddBrowserActionExtensions());
408
409 // Verify the three extensions are in the model in the proper order: A, B, C.
410 EXPECT_EQ(3u, num_toolbar_items());
411 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
412 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
413 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
414
415 // Unload B, then C, then A, and then reload C, then A, then B.
416 ASSERT_TRUE(RemoveExtension(browser_action_b()));
417 ASSERT_TRUE(RemoveExtension(browser_action_c()));
418 ASSERT_TRUE(RemoveExtension(browser_action_a()));
419 EXPECT_EQ(0u, num_toolbar_items()); // Sanity check: all gone?
420 ASSERT_TRUE(AddExtension(browser_action_c()));
421 ASSERT_TRUE(AddExtension(browser_action_a()));
422 ASSERT_TRUE(AddExtension(browser_action_b()));
423 EXPECT_EQ(3u, num_toolbar_items()); // Sanity check: all back?
424 EXPECT_EQ(0u, observer()->moved_count());
425
426 // Even though we unloaded and reloaded in a different order, the original
427 // order (A, B, C) should be preserved.
428 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
429 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
430 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
431
432 // Disabling extensions should also preserve order.
433 service()->DisableExtension(browser_action_b()->id(),
434 Extension::DISABLE_USER_ACTION);
435 service()->DisableExtension(browser_action_c()->id(),
436 Extension::DISABLE_USER_ACTION);
437 service()->DisableExtension(browser_action_a()->id(),
438 Extension::DISABLE_USER_ACTION);
439 service()->EnableExtension(browser_action_c()->id());
440 service()->EnableExtension(browser_action_a()->id());
441 service()->EnableExtension(browser_action_b()->id());
442
443 // Make sure we still get the original A, B, C order.
444 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
445 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
446 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
447
448 // Move browser_action_b() to be first.
449 toolbar_model()->MoveExtensionIcon(browser_action_b()->id(), 0);
450 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(0u));
451
452 // Uninstall Extension B.
453 service()->UninstallExtension(browser_action_b()->id(),
454 UNINSTALL_REASON_FOR_TESTING,
455 base::Bind(&base::DoNothing),
456 NULL); // Ignore error.
457 // List contains only A and C now. Validate that.
458 EXPECT_EQ(2u, num_toolbar_items());
459 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
460 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
461
462 ASSERT_TRUE(AddExtension(browser_action_b()));
463
464 // Make sure Extension B is _not_ first (its old position should have been
465 // forgotten at uninstall time). Order should be A, C, B.
466 EXPECT_EQ(3u, num_toolbar_items());
467 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
468 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
469 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(2u));
470 }
471
472 TEST_F(ExtensionToolbarModelUnitTest, ReorderOnPrefChange) {
473 Init();
474
475 // Add the three browser action extensions.
476 ASSERT_TRUE(AddBrowserActionExtensions());
477 EXPECT_EQ(3u, num_toolbar_items());
478
479 // Change the value of the toolbar preference.
480 ExtensionIdList new_order;
481 new_order.push_back(browser_action_c()->id());
482 new_order.push_back(browser_action_b()->id());
483 ExtensionPrefs::Get(profile())->SetToolbarOrder(new_order);
484
485 // Verify order is changed.
486 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
487 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
488 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(2u));
489 }
490
491 // Test that new extensions are always visible on installation and inserted at
492 // the "end" of the visible section.
493 TEST_F(ExtensionToolbarModelUnitTest, NewToolbarExtensionsAreVisible) {
494 Init();
495
496 // Three extensions with actions.
497 scoped_refptr<const Extension> extension_a =
498 extension_action_test_util::CreateActionExtension(
499 "a", extension_action_test_util::BROWSER_ACTION);
500 scoped_refptr<const Extension> extension_b =
501 extension_action_test_util::CreateActionExtension(
502 "b", extension_action_test_util::BROWSER_ACTION);
503 scoped_refptr<const Extension> extension_c =
504 extension_action_test_util::CreateActionExtension(
505 "c", extension_action_test_util::BROWSER_ACTION);
506 scoped_refptr<const Extension> extension_d =
507 extension_action_test_util::CreateActionExtension(
508 "d", extension_action_test_util::BROWSER_ACTION);
509
510 // We should start off without any extensions.
511 EXPECT_EQ(0u, num_toolbar_items());
512 EXPECT_EQ(0u, toolbar_model()->visible_icon_count());
513
514 // Add one extension. It should be visible.
515 service()->AddExtension(extension_a.get());
516 EXPECT_EQ(1u, num_toolbar_items());
517 EXPECT_EQ(1u, toolbar_model()->visible_icon_count());
518 EXPECT_EQ(extension_a.get(), GetExtensionAtIndex(0u));
519
520 // Hide all extensions.
521 toolbar_model()->SetVisibleIconCount(0);
522 EXPECT_EQ(0u, toolbar_model()->visible_icon_count());
523
524 // Add a new extension - it should be visible, so it should be in the first
525 // index. The other extension should remain hidden.
526 service()->AddExtension(extension_b.get());
527 EXPECT_EQ(2u, num_toolbar_items());
528 EXPECT_EQ(1u, toolbar_model()->visible_icon_count());
529 EXPECT_EQ(extension_b.get(), GetExtensionAtIndex(0u));
530 EXPECT_EQ(extension_a.get(), GetExtensionAtIndex(1u));
531
532 // Show all extensions.
533 toolbar_model()->SetVisibleIconCount(2);
534 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
535 EXPECT_TRUE(toolbar_model()->all_icons_visible());
536
537 // Add the third extension. Since all extensions are visible, it should go in
538 // the last index.
539 service()->AddExtension(extension_c.get());
540 EXPECT_EQ(3u, num_toolbar_items());
541 EXPECT_EQ(3u, toolbar_model()->visible_icon_count());
542 EXPECT_TRUE(toolbar_model()->all_icons_visible());
543 EXPECT_EQ(extension_b.get(), GetExtensionAtIndex(0u));
544 EXPECT_EQ(extension_a.get(), GetExtensionAtIndex(1u));
545 EXPECT_EQ(extension_c.get(), GetExtensionAtIndex(2u));
546
547 // Hide one extension (two remaining visible).
548 toolbar_model()->SetVisibleIconCount(2);
549 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
550
551 // Add a fourth extension. It should go at the end of the visible section and
552 // be visible, so it increases visible count by 1, and goes into the third
553 // index. The hidden extension should remain hidden.
554 service()->AddExtension(extension_d.get());
555 EXPECT_EQ(4u, num_toolbar_items());
556 EXPECT_EQ(3u, toolbar_model()->visible_icon_count());
557 EXPECT_EQ(extension_b.get(), GetExtensionAtIndex(0u));
558 EXPECT_EQ(extension_a.get(), GetExtensionAtIndex(1u));
559 EXPECT_EQ(extension_d.get(), GetExtensionAtIndex(2u));
560 EXPECT_EQ(extension_c.get(), GetExtensionAtIndex(3u));
561 }
562
563 TEST_F(ExtensionToolbarModelUnitTest, ExtensionToolbarHighlightMode) {
564 Init();
565
566 EXPECT_FALSE(toolbar_model()->HighlightExtensions(
567 ExtensionIdList(), ExtensionToolbarModel::HIGHLIGHT_WARNING));
568 EXPECT_EQ(0, observer()->highlight_mode_count());
569
570 // Add the three browser action extensions.
571 ASSERT_TRUE(AddBrowserActionExtensions());
572 EXPECT_EQ(3u, num_toolbar_items());
573
574 // Start with a visible count of 2 (non-zero, and not all).
575 toolbar_model()->SetVisibleIconCount(2u);
576
577 // Highlight one extension.
578 ExtensionIdList extension_ids;
579 extension_ids.push_back(browser_action_b()->id());
580 toolbar_model()->HighlightExtensions(
581 extension_ids, ExtensionToolbarModel::HIGHLIGHT_WARNING);
582 EXPECT_EQ(1, observer()->highlight_mode_count());
583 EXPECT_TRUE(toolbar_model()->is_highlighting());
584
585 EXPECT_EQ(1u, num_toolbar_items());
586 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(0u));
587 EXPECT_EQ(1u, toolbar_model()->visible_icon_count());
588
589 // Stop highlighting.
590 toolbar_model()->StopHighlighting();
591 EXPECT_EQ(0, observer()->highlight_mode_count());
592 EXPECT_FALSE(toolbar_model()->is_highlighting());
593
594 // Verify that the extensions are back to normal.
595 EXPECT_EQ(3u, num_toolbar_items());
596 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
597 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
598 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
599 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
600
601 // Call stop highlighting a second time (shouldn't be notified).
602 toolbar_model()->StopHighlighting();
603 EXPECT_EQ(0, observer()->highlight_mode_count());
604 EXPECT_FALSE(toolbar_model()->is_highlighting());
605
606 // Highlight all extensions.
607 extension_ids.clear();
608 extension_ids.push_back(browser_action_a()->id());
609 extension_ids.push_back(browser_action_b()->id());
610 extension_ids.push_back(browser_action_c()->id());
611 toolbar_model()->HighlightExtensions(
612 extension_ids, ExtensionToolbarModel::HIGHLIGHT_WARNING);
613 EXPECT_EQ(1, observer()->highlight_mode_count());
614 EXPECT_EQ(3u, num_toolbar_items());
615 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
616 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
617 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
618 EXPECT_EQ(3u, toolbar_model()->visible_icon_count());
619 // Even though the visible count is 3, we shouldn't adjust the stored
620 // preference.
621 EXPECT_EQ(2, profile()->GetPrefs()->GetInteger(pref_names::kToolbarSize));
622
623 // Highlight only extension b (shrink the highlight list).
624 extension_ids.clear();
625 extension_ids.push_back(browser_action_b()->id());
626 toolbar_model()->HighlightExtensions(
627 extension_ids, ExtensionToolbarModel::HIGHLIGHT_WARNING);
628 EXPECT_EQ(2, observer()->highlight_mode_count());
629 EXPECT_EQ(1u, num_toolbar_items());
630 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(0u));
631
632 // Highlight extensions a and b (grow the highlight list).
633 extension_ids.clear();
634 extension_ids.push_back(browser_action_a()->id());
635 extension_ids.push_back(browser_action_b()->id());
636 toolbar_model()->HighlightExtensions(
637 extension_ids, ExtensionToolbarModel::HIGHLIGHT_WARNING);
638 EXPECT_EQ(3, observer()->highlight_mode_count());
639 EXPECT_EQ(2u, num_toolbar_items());
640 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
641 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
642
643 // Highlight no extensions (empty the highlight list).
644 extension_ids.clear();
645 toolbar_model()->HighlightExtensions(
646 extension_ids, ExtensionToolbarModel::HIGHLIGHT_WARNING);
647 EXPECT_EQ(2, observer()->highlight_mode_count());
648 EXPECT_FALSE(toolbar_model()->is_highlighting());
649 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
650 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
651 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
652
653 // Our toolbar size should be back to normal.
654 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
655 EXPECT_EQ(2, profile()->GetPrefs()->GetInteger(pref_names::kToolbarSize));
656 }
657
658 TEST_F(ExtensionToolbarModelUnitTest, ExtensionToolbarHighlightModeRemove) {
659 Init();
660
661 // Add the three browser action extensions.
662 ASSERT_TRUE(AddBrowserActionExtensions());
663 EXPECT_EQ(3u, num_toolbar_items());
664
665 // Highlight two of the extensions.
666 ExtensionIdList extension_ids;
667 extension_ids.push_back(browser_action_a()->id());
668 extension_ids.push_back(browser_action_b()->id());
669 toolbar_model()->HighlightExtensions(
670 extension_ids, ExtensionToolbarModel::HIGHLIGHT_WARNING);
671 EXPECT_TRUE(toolbar_model()->is_highlighting());
672 EXPECT_EQ(1, observer()->highlight_mode_count());
673 EXPECT_EQ(2u, num_toolbar_items());
674
675 // Disable one of them - only one should remain highlighted.
676 service()->DisableExtension(browser_action_a()->id(),
677 Extension::DISABLE_USER_ACTION);
678 EXPECT_TRUE(toolbar_model()->is_highlighting());
679 EXPECT_EQ(1u, num_toolbar_items());
680 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(0u));
681
682 // Uninstall the remaining highlighted extension. This should result in
683 // highlight mode exiting.
684 service()->UninstallExtension(browser_action_b()->id(),
685 UNINSTALL_REASON_FOR_TESTING,
686 base::Bind(&base::DoNothing),
687 NULL); // Ignore error.
688 EXPECT_FALSE(toolbar_model()->is_highlighting());
689 EXPECT_EQ(0, observer()->highlight_mode_count());
690 EXPECT_EQ(1u, num_toolbar_items());
691 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
692
693 // Test that removing an unhighlighted extension still works.
694 // Reinstall extension b, and then highlight extension c.
695 ASSERT_TRUE(AddExtension(browser_action_b()));
696 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
697 extension_ids.clear();
698 extension_ids.push_back(browser_action_c()->id());
699 toolbar_model()->HighlightExtensions(
700 extension_ids, ExtensionToolbarModel::HIGHLIGHT_WARNING);
701 EXPECT_EQ(1, observer()->highlight_mode_count());
702 EXPECT_TRUE(toolbar_model()->is_highlighting());
703 EXPECT_EQ(1u, num_toolbar_items());
704 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
705
706 // Uninstalling b should not have visible impact.
707 service()->UninstallExtension(browser_action_b()->id(),
708 UNINSTALL_REASON_FOR_TESTING,
709 base::Bind(&base::DoNothing),
710 NULL); // Ignore error.
711 EXPECT_TRUE(toolbar_model()->is_highlighting());
712 EXPECT_EQ(1, observer()->highlight_mode_count());
713 EXPECT_EQ(1u, num_toolbar_items());
714 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
715
716 // When we stop, only extension c should remain.
717 toolbar_model()->StopHighlighting();
718 EXPECT_FALSE(toolbar_model()->is_highlighting());
719 EXPECT_EQ(0, observer()->highlight_mode_count());
720 EXPECT_EQ(1u, num_toolbar_items());
721 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u));
722 }
723
724 TEST_F(ExtensionToolbarModelUnitTest, ExtensionToolbarHighlightModeAdd) {
725 Init();
726
727 // Add the three browser action extensions.
728 ASSERT_TRUE(AddBrowserActionExtensions());
729 EXPECT_EQ(3u, num_toolbar_items());
730
731 // Remove one (down to two).
732 ASSERT_TRUE(RemoveExtension(browser_action_c()));
733
734 // Highlight one of the two extensions.
735 ExtensionIdList extension_ids;
736 extension_ids.push_back(browser_action_a()->id());
737 toolbar_model()->HighlightExtensions(
738 extension_ids, ExtensionToolbarModel::HIGHLIGHT_WARNING);
739 EXPECT_TRUE(toolbar_model()->is_highlighting());
740 EXPECT_EQ(1u, num_toolbar_items());
741 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
742
743 // Adding a new extension should have no visible effect.
744 ASSERT_TRUE(AddExtension(browser_action_c()));
745 EXPECT_TRUE(toolbar_model()->is_highlighting());
746 EXPECT_EQ(1u, num_toolbar_items());
747 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
748
749 // When we stop highlighting, we should see the new extension show up.
750 toolbar_model()->StopHighlighting();
751 EXPECT_FALSE(toolbar_model()->is_highlighting());
752 EXPECT_EQ(3u, num_toolbar_items());
753 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
754 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
755 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
756 }
757
758 // Test that the extension toolbar maintains the proper size, even after a pref
759 // change.
760 TEST_F(ExtensionToolbarModelUnitTest, ExtensionToolbarSizeAfterPrefChange) {
761 Init();
762
763 // Add the three browser action extensions.
764 ASSERT_TRUE(AddBrowserActionExtensions());
765 EXPECT_EQ(3u, num_toolbar_items());
766
767 // Should be at max size.
768 EXPECT_TRUE(toolbar_model()->all_icons_visible());
769 EXPECT_EQ(num_toolbar_items(), toolbar_model()->visible_icon_count());
770 toolbar_model()->OnExtensionToolbarPrefChange();
771 // Should still be at max size.
772 EXPECT_TRUE(toolbar_model()->all_icons_visible());
773 EXPECT_EQ(num_toolbar_items(), toolbar_model()->visible_icon_count());
774 }
775
776 // Test that, in the absence of the extension-action-redesign switch, the
777 // model only contains extensions with browser actions.
778 TEST_F(ExtensionToolbarModelUnitTest, TestToolbarExtensionTypesNoSwitch) {
779 Init();
780 ASSERT_TRUE(AddActionExtensions());
781
782 EXPECT_EQ(1u, num_toolbar_items());
783 EXPECT_EQ(browser_action(), GetExtensionAtIndex(0u));
784 }
785
786 // Test that, with the extension-action-redesign switch, the model contains
787 // all types of extensions, except those which should not be displayed on the
788 // toolbar (like component extensions).
789 TEST_F(ExtensionToolbarModelUnitTest, TestToolbarExtensionTypesSwitch) {
790 FeatureSwitch::ScopedOverride enable_redesign(
791 FeatureSwitch::extension_action_redesign(), true);
792 Init();
793 ASSERT_TRUE(AddActionExtensions());
794
795 // With the switch on, extensions with page actions and no action should also
796 // be displayed in the toolbar.
797 EXPECT_EQ(3u, num_toolbar_items());
798 EXPECT_EQ(browser_action(), GetExtensionAtIndex(0u));
799 EXPECT_EQ(page_action(), GetExtensionAtIndex(1u));
800 EXPECT_EQ(no_action(), GetExtensionAtIndex(2u));
801 }
802
803 // Test that hiding actions on the toolbar results in their removal from the
804 // model when the redesign switch is not enabled.
805 TEST_F(ExtensionToolbarModelUnitTest,
806 ExtensionToolbarActionsVisibilityNoSwitch) {
807 Init();
808
809 ExtensionActionAPI* action_api = ExtensionActionAPI::Get(profile());
810
811 ASSERT_TRUE(AddBrowserActionExtensions());
812 // Sanity check: Order should start as 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));
817
818 // By default, all actions should be visible.
819 EXPECT_TRUE(action_api->GetBrowserActionVisibility(browser_action_a()->id()));
820 EXPECT_TRUE(action_api->GetBrowserActionVisibility(browser_action_b()->id()));
821 EXPECT_TRUE(action_api->GetBrowserActionVisibility(browser_action_c()->id()));
822
823 // Hiding an action should result in its removal from the toolbar.
824 action_api->SetBrowserActionVisibility(browser_action_b()->id(), false);
825 EXPECT_FALSE(action_api->GetBrowserActionVisibility(
826 browser_action_b()->id()));
827 // Thus, there should now only be two items on the toolbar - A and C.
828 EXPECT_EQ(2u, num_toolbar_items());
829 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
830 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
831
832 // Resetting the visibility to 'true' should result in the extension being
833 // added back at its original position.
834 action_api->SetBrowserActionVisibility(browser_action_b()->id(), true);
835 EXPECT_TRUE(action_api->GetBrowserActionVisibility(browser_action_b()->id()));
836 // So the toolbar order should be A B C.
837 EXPECT_EQ(3u, num_toolbar_items());
838 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
839 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u));
840 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2u));
841 }
842
843 TEST_F(ExtensionToolbarModelUnitTest, ExtensionToolbarIncognitoModeTest) {
844 Init();
845 ASSERT_TRUE(AddBrowserActionExtensions());
846
847 // Give two extensions incognito access.
848 // Note: We use ExtensionPrefs::SetIsIncognitoEnabled instead of
849 // util::SetIsIncognitoEnabled because the latter tries to reload the
850 // extension, which requries a filepath associated with the extension (and,
851 // for this test, reloading the extension is irrelevant to us).
852 ExtensionPrefs* extension_prefs = ExtensionPrefs::Get(profile());
853 extension_prefs->SetIsIncognitoEnabled(browser_action_b()->id(), true);
854 extension_prefs->SetIsIncognitoEnabled(browser_action_c()->id(), true);
855
856 util::SetIsIncognitoEnabled(browser_action_b()->id(), profile(), true);
857 util::SetIsIncognitoEnabled(browser_action_c()->id(), profile(), true);
858
859 // Move C to the second index.
860 toolbar_model()->MoveExtensionIcon(browser_action_c()->id(), 1u);
861 // Set visible count to 2 so that c is overflowed. State is A C [B].
862 toolbar_model()->SetVisibleIconCount(2);
863 EXPECT_EQ(1u, observer()->moved_count());
864
865 // Get an incognito profile and toolbar.
866 ExtensionToolbarModel* incognito_model =
867 extension_action_test_util::CreateToolbarModelForProfile(
868 profile()->GetOffTheRecordProfile());
869
870 ExtensionToolbarModelTestObserver incognito_observer(incognito_model);
871 EXPECT_EQ(0u, incognito_observer.moved_count());
872
873 // We should have two items, C and B, and the order should be preserved from
874 // the original model.
875 EXPECT_EQ(2u, incognito_model->toolbar_items().size());
876 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(0u, incognito_model));
877 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1u, incognito_model));
878
879 // Extensions in the overflow menu in the regular toolbar should remain in
880 // overflow in the incognito toolbar. So, we should have C [B].
881 EXPECT_EQ(1u, incognito_model->visible_icon_count());
882 // The regular model should still have two icons visible.
883 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
884
885 // Changing the incognito model size should not affect the regular model.
886 incognito_model->SetVisibleIconCount(0);
887 EXPECT_EQ(0u, incognito_model->visible_icon_count());
888 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
889
890 // Expanding the incognito model to 2 should register as "all icons"
891 // since it is all of the incognito-enabled extensions.
892 incognito_model->SetVisibleIconCount(2u);
893 EXPECT_EQ(2u, incognito_model->visible_icon_count());
894 EXPECT_TRUE(incognito_model->all_icons_visible());
895
896 // Moving icons in the incognito toolbar should not affect the regular
897 // toolbar. Incognito currently has C B...
898 incognito_model->MoveExtensionIcon(browser_action_b()->id(), 0u);
899 // So now it should be B C...
900 EXPECT_EQ(1u, incognito_observer.moved_count());
901 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(0u, incognito_model));
902 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u, incognito_model));
903 // ... and the regular toolbar should be unaffected.
904 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0u));
905 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1u));
906 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(2u));
907
908 // Similarly, the observer for the regular model should not have received
909 // any updates.
910 EXPECT_EQ(1u, observer()->moved_count());
911
912 // And performing moves on the regular model should have no effect on the
913 // incognito model or its observers.
914 toolbar_model()->MoveExtensionIcon(browser_action_c()->id(), 2u);
915 EXPECT_EQ(2u, observer()->moved_count());
916 EXPECT_EQ(1u, incognito_observer.moved_count());
917 }
918
919 // Test that enabling extensions incognito with an active incognito profile
920 // works.
921 TEST_F(ExtensionToolbarModelUnitTest,
922 ExtensionToolbarIncognitoEnableExtension) {
923 Init();
924
925 const char* kManifest =
926 "{"
927 " \"name\": \"%s\","
928 " \"version\": \"1.0\","
929 " \"manifest_version\": 2,"
930 " \"browser_action\": {}"
931 "}";
932
933 // For this test, we need to have "real" extension files, because we need to
934 // be able to reload them during the incognito process. Since the toolbar
935 // needs to be notified of the reload, we need it this time (as opposed to
936 // above, where we simply set the prefs before the incognito bar was
937 // created.
938 TestExtensionDir dir1;
939 dir1.WriteManifest(base::StringPrintf(kManifest, "incognito1"));
940 TestExtensionDir dir2;
941 dir2.WriteManifest(base::StringPrintf(kManifest, "incognito2"));
942
943 TestExtensionDir* dirs[] = { &dir1, &dir2 };
944 const Extension* extensions[] = { nullptr, nullptr };
945 for (size_t i = 0; i < arraysize(dirs); ++i) {
946 // The extension id will be calculated from the file path; we need this to
947 // wait for the extension to load.
948 base::FilePath path_for_id =
949 base::MakeAbsoluteFilePath(dirs[i]->unpacked_path());
950 std::string id = crx_file::id_util::GenerateIdForPath(path_for_id);
951 TestExtensionRegistryObserver observer(registry(), id);
952 UnpackedInstaller::Create(service())->Load(dirs[i]->unpacked_path());
953 observer.WaitForExtensionLoaded();
954 extensions[i] = registry()->enabled_extensions().GetByID(id);
955 ASSERT_TRUE(extensions[i]);
956 }
957
958 // For readability, alias to A and B. Since we'll be reloading these
959 // extensions, we also can't rely on pointers.
960 std::string extension_a = extensions[0]->id();
961 std::string extension_b = extensions[1]->id();
962
963 // The first model should have both extensions visible.
964 EXPECT_EQ(2u, toolbar_model()->toolbar_items().size());
965 EXPECT_EQ(extension_a, GetExtensionAtIndex(0)->id());
966 EXPECT_EQ(extension_b, GetExtensionAtIndex(1)->id());
967
968 // Set the model to only show one extension, so the order is A [B].
969 toolbar_model()->SetVisibleIconCount(1u);
970
971 // Get an incognito profile and toolbar.
972 ExtensionToolbarModel* incognito_model =
973 extension_action_test_util::CreateToolbarModelForProfile(
974 profile()->GetOffTheRecordProfile());
975 ExtensionToolbarModelTestObserver incognito_observer(incognito_model);
976
977 // Right now, no extensions are enabled in incognito mode.
978 EXPECT_EQ(0u, incognito_model->toolbar_items().size());
979
980 // Set extension b (which is overflowed) to be enabled in incognito. This
981 // results in b reloading, so wait for it.
982 {
983 TestExtensionRegistryObserver observer(registry(), extension_b);
984 util::SetIsIncognitoEnabled(extension_b, profile(), true);
985 observer.WaitForExtensionLoaded();
986 }
987
988 // Now, we should have one icon in the incognito bar. But, since B is
989 // overflowed in the main bar, it shouldn't be visible.
990 EXPECT_EQ(1u, incognito_model->toolbar_items().size());
991 EXPECT_EQ(extension_b, GetExtensionAtIndex(0u, incognito_model)->id());
992 EXPECT_EQ(0u, incognito_model->visible_icon_count());
993
994 // Also enable extension a for incognito (again, wait for the reload).
995 {
996 TestExtensionRegistryObserver observer(registry(), extension_a);
997 util::SetIsIncognitoEnabled(extension_a, profile(), true);
998 observer.WaitForExtensionLoaded();
999 }
1000
1001 // Now, both extensions should be enabled in incognito mode. In addition, the
1002 // incognito toolbar should have expanded to show extension a (since it isn't
1003 // overflowed in the main bar).
1004 EXPECT_EQ(2u, incognito_model->toolbar_items().size());
1005 EXPECT_EQ(extension_a, GetExtensionAtIndex(0u, incognito_model)->id());
1006 EXPECT_EQ(extension_b, GetExtensionAtIndex(1u, incognito_model)->id());
1007 EXPECT_EQ(1u, incognito_model->visible_icon_count());
1008 }
1009
1010 // Test that hiding actions on the toolbar results in sending them to the
1011 // overflow menu when the redesign switch is enabled.
1012 TEST_F(ExtensionToolbarModelUnitTest,
1013 ExtensionToolbarActionsVisibilityWithSwitch) {
1014 FeatureSwitch::ScopedOverride enable_redesign(
1015 FeatureSwitch::extension_action_redesign(), true);
1016 Init();
1017
1018 // We choose to use all types of extensions here, since the misnamed
1019 // BrowserActionVisibility is now for toolbar visibility.
1020 ASSERT_TRUE(AddActionExtensions());
1021
1022 // For readability, alias extensions A B C.
1023 const Extension* extension_a = browser_action();
1024 const Extension* extension_b = page_action();
1025 const Extension* extension_c = no_action();
1026
1027 // Sanity check: Order should start as A B C, with all three visible.
1028 EXPECT_EQ(3u, num_toolbar_items());
1029 EXPECT_TRUE(toolbar_model()->all_icons_visible());
1030 EXPECT_EQ(extension_a, GetExtensionAtIndex(0u));
1031 EXPECT_EQ(extension_b, GetExtensionAtIndex(1u));
1032 EXPECT_EQ(extension_c, GetExtensionAtIndex(2u));
1033
1034 ExtensionActionAPI* action_api = ExtensionActionAPI::Get(profile());
1035
1036 // By default, all actions should be visible.
1037 EXPECT_TRUE(action_api->GetBrowserActionVisibility(extension_a->id()));
1038 EXPECT_TRUE(action_api->GetBrowserActionVisibility(extension_c->id()));
1039 EXPECT_TRUE(action_api->GetBrowserActionVisibility(extension_b->id()));
1040
1041 // Hiding an action should result in it being sent to the overflow menu.
1042 action_api->SetBrowserActionVisibility(extension_b->id(), false);
1043
1044 // Thus, the order should be A C B, with B in the overflow.
1045 EXPECT_EQ(3u, num_toolbar_items());
1046 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
1047 EXPECT_EQ(extension_a, GetExtensionAtIndex(0u));
1048 EXPECT_EQ(extension_c, GetExtensionAtIndex(1u));
1049 EXPECT_EQ(extension_b, GetExtensionAtIndex(2u));
1050
1051 // Hiding an extension's action should result in it being sent to the overflow
1052 // as well, but as the _first_ extension in the overflow.
1053 action_api->SetBrowserActionVisibility(extension_a->id(), false);
1054 // Thus, the order should be C A B, with A and B in the overflow.
1055 EXPECT_EQ(3u, num_toolbar_items());
1056 EXPECT_EQ(1u, toolbar_model()->visible_icon_count());
1057 EXPECT_EQ(extension_c, GetExtensionAtIndex(0u));
1058 EXPECT_EQ(extension_a, GetExtensionAtIndex(1u));
1059 EXPECT_EQ(extension_b, GetExtensionAtIndex(2u));
1060
1061 // Resetting A's visibility to true should send it back to the visible icons
1062 // (and should grow visible icons by 1), but it should be added to the end of
1063 // the visible icon list (not to its original position).
1064 action_api->SetBrowserActionVisibility(extension_a->id(), true);
1065 // So order is C A B, with only B in the overflow.
1066 EXPECT_EQ(3u, num_toolbar_items());
1067 EXPECT_EQ(2u, toolbar_model()->visible_icon_count());
1068 EXPECT_EQ(extension_c, GetExtensionAtIndex(0u));
1069 EXPECT_EQ(extension_a, GetExtensionAtIndex(1u));
1070 EXPECT_EQ(extension_b, GetExtensionAtIndex(2u));
1071
1072 // Resetting B to be visible should make the order C A B, with no overflow.
1073 action_api->SetBrowserActionVisibility(extension_b->id(), true);
1074 EXPECT_EQ(3u, num_toolbar_items());
1075 EXPECT_TRUE(toolbar_model()->all_icons_visible());
1076 EXPECT_EQ(extension_c, GetExtensionAtIndex(0u));
1077 EXPECT_EQ(extension_a, GetExtensionAtIndex(1u));
1078 EXPECT_EQ(extension_b, GetExtensionAtIndex(2u));
1079 }
1080
1081 // Test that observers receive no Added notifications until after the
1082 // ExtensionSystem has initialized.
1083 TEST_F(ExtensionToolbarModelUnitTest, ModelWaitsForExtensionSystemReady) {
1084 InitializeEmptyExtensionService();
1085 ExtensionToolbarModel* toolbar_model =
1086 extension_action_test_util::
1087 CreateToolbarModelForProfileWithoutWaitingForReady(profile());
1088 ExtensionToolbarModelTestObserver model_observer(toolbar_model);
1089 EXPECT_TRUE(AddBrowserActionExtensions());
1090
1091 // Since the model hasn't been initialized (the ExtensionSystem::ready task
1092 // hasn't been run), there should be no insertion notifications.
1093 EXPECT_EQ(0u, model_observer.inserted_count());
1094 EXPECT_EQ(0u, model_observer.initialized_count());
1095 EXPECT_FALSE(toolbar_model->extensions_initialized());
1096
1097 // Run the ready task.
1098 static_cast<TestExtensionSystem*>(ExtensionSystem::Get(profile()))->
1099 SetReady();
1100 // Run tasks posted to TestExtensionSystem.
1101 base::RunLoop().RunUntilIdle();
1102
1103 // We should still have no insertions, but should have an initialized count.
1104 EXPECT_TRUE(toolbar_model->extensions_initialized());
1105 EXPECT_EQ(0u, model_observer.inserted_count());
1106 EXPECT_EQ(1u, model_observer.initialized_count());
1107 }
1108
1109 // Check that the toolbar model correctly clears and reorders when it detects
1110 // a preference change.
1111 TEST_F(ExtensionToolbarModelUnitTest, ToolbarModelPrefChange) {
1112 Init();
1113
1114 ASSERT_TRUE(AddBrowserActionExtensions());
1115
1116 // We should start in the basic A B C order.
1117 ASSERT_TRUE(browser_action_a());
1118 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0));
1119 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1));
1120 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2));
1121 // Record the difference between the inserted and removed counts. The actual
1122 // value of the counts is not important, but we need to be sure that if we
1123 // call to remove any, we also add them back.
1124 size_t inserted_and_removed_difference =
1125 observer()->inserted_count() - observer()->removed_count();
1126
1127 // Assign a new order, B C A, and write it in the prefs.
1128 ExtensionIdList new_order;
1129 new_order.push_back(browser_action_b()->id());
1130 new_order.push_back(browser_action_c()->id());
1131 new_order.push_back(browser_action_a()->id());
1132 ExtensionPrefs::Get(profile())->SetToolbarOrder(new_order);
1133
1134 // Ensure everything has time to run.
1135 base::RunLoop().RunUntilIdle();
1136
1137 // The new order should be reflected in the model.
1138 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(0));
1139 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(1));
1140 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(2));
1141 EXPECT_EQ(inserted_and_removed_difference,
1142 observer()->inserted_count() - observer()->removed_count());
1143 }
1144
1145 TEST_F(ExtensionToolbarModelUnitTest, ComponentExtesionsAddedToEnd) {
1146 Init();
1147
1148 ASSERT_TRUE(AddBrowserActionExtensions());
1149
1150 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(0));
1151 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(1));
1152 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(2));
1153
1154 const char kName[] = "component";
1155 DictionaryBuilder manifest;
1156 manifest.Set("name", kName)
1157 .Set("description", "An extension")
1158 .Set("manifest_version", 2)
1159 .Set("version", "1.0.0")
1160 .Set("browser_action", DictionaryBuilder().Pass());
1161 scoped_refptr<const Extension> component_extension =
1162 ExtensionBuilder().SetManifest(manifest.Pass())
1163 .SetID(crx_file::id_util::GenerateId(kName))
1164 .SetLocation(Manifest::COMPONENT)
1165 .Build();
1166 service()->AddExtension(component_extension.get());
1167
1168 EXPECT_EQ(component_extension.get(), GetExtensionAtIndex(0));
1169 EXPECT_EQ(browser_action_a(), GetExtensionAtIndex(1));
1170 EXPECT_EQ(browser_action_b(), GetExtensionAtIndex(2));
1171 EXPECT_EQ(browser_action_c(), GetExtensionAtIndex(3));
1172 }
1173
1174 TEST_F(ExtensionToolbarModelUnitTest,
1175 ToolbarModelHighlightsForToolbarRedesign) {
1176 FeatureSwitch::ScopedOverride enable_redesign(
1177 FeatureSwitch::extension_action_redesign(), true);
1178 InitializeEmptyExtensionService();
1179 EXPECT_TRUE(AddActionExtensions());
1180 ExtensionToolbarModel* toolbar_model =
1181 extension_action_test_util::CreateToolbarModelForProfile(profile());
1182 EXPECT_TRUE(toolbar_model);
1183 base::RunLoop().RunUntilIdle();
1184
1185 EXPECT_TRUE(ExtensionToolbarIconSurfacingBubbleDelegate::ShouldShowForProfile(
1186 profile()));
1187 EXPECT_TRUE(toolbar_model->is_highlighting());
1188 EXPECT_EQ(ExtensionToolbarModel::HIGHLIGHT_INFO,
1189 toolbar_model->highlight_type());
1190 EXPECT_EQ(3u, toolbar_model->visible_icon_count());
1191 EXPECT_EQ(3u, toolbar_model->toolbar_items().size());
1192
1193 scoped_ptr<ToolbarActionsBarBubbleDelegate> bubble(
1194 new ExtensionToolbarIconSurfacingBubbleDelegate(profile()));
1195 bubble->OnBubbleClosed(ToolbarActionsBarBubbleDelegate::CLOSE_DISMISS);
1196
1197 EXPECT_FALSE(toolbar_model->is_highlighting());
1198 EXPECT_EQ(ExtensionToolbarModel::HIGHLIGHT_NONE,
1199 toolbar_model->highlight_type());
1200 }
1201
1202 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698