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

Side by Side Diff: chrome/browser/ui/toolbar/toolbar_actions_model_unittest.cc

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

Powered by Google App Engine
This is Rietveld 408576698