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

Side by Side Diff: chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app_unittest.cc

Issue 22887015: Remove PerBrowser launcher (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix nit Created 7 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 (c) 2012 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 "chrome/browser/ui/ash/launcher/chrome_launcher_controller_per_app.h"
6
7 #include <algorithm>
8 #include <string>
9 #include <vector>
10
11 #include "ash/ash_switches.h"
12 #include "ash/launcher/launcher_model.h"
13 #include "ash/launcher/launcher_model_observer.h"
14 #include "base/command_line.h"
15 #include "base/compiler_specific.h"
16 #include "base/files/file_path.h"
17 #include "base/memory/scoped_ptr.h"
18 #include "base/message_loop/message_loop.h"
19 #include "base/strings/utf_string_conversions.h"
20 #include "base/values.h"
21 #include "chrome/browser/extensions/extension_service.h"
22 #include "chrome/browser/extensions/test_extension_system.h"
23 #include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
24 #include "chrome/browser/ui/ash/launcher/launcher_item_controller.h"
25 #include "chrome/browser/ui/ash/launcher/shell_window_launcher_item_controller.h "
26 #include "chrome/browser/ui/browser.h"
27 #include "chrome/browser/ui/browser_commands.h"
28 #include "chrome/browser/ui/browser_finder.h"
29 #include "chrome/browser/ui/browser_list.h"
30 #include "chrome/browser/ui/host_desktop.h"
31 #include "chrome/browser/ui/tabs/tab_strip_model.h"
32 #include "chrome/common/extensions/extension.h"
33 #include "chrome/common/extensions/extension_constants.h"
34 #include "chrome/common/pref_names.h"
35 #include "chrome/test/base/browser_with_test_window_test.h"
36 #include "chrome/test/base/testing_pref_service_syncable.h"
37 #include "chrome/test/base/testing_profile.h"
38 #include "content/public/test/test_browser_thread.h"
39 #include "extensions/common/manifest_constants.h"
40 #include "testing/gtest/include/gtest/gtest.h"
41 #include "ui/base/models/menu_model.h"
42
43 using extensions::Extension;
44 using extensions::Manifest;
45
46 namespace {
47 const char* offline_gmail_url = "https://mail.google.com/mail/mu/u";
48 const char* gmail_url = "https://mail.google.com/mail/u";
49 }
50
51 namespace {
52
53 // LauncherModelObserver implementation that tracks what messages are invoked.
54 class TestLauncherModelObserver : public ash::LauncherModelObserver {
55 public:
56 TestLauncherModelObserver()
57 : added_(0),
58 removed_(0),
59 changed_(0) {
60 }
61
62 virtual ~TestLauncherModelObserver() {
63 }
64
65 // LauncherModelObserver
66 virtual void LauncherItemAdded(int index) OVERRIDE {
67 ++added_;
68 last_index_ = index;
69 }
70
71 virtual void LauncherItemRemoved(int index, ash::LauncherID id) OVERRIDE {
72 ++removed_;
73 last_index_ = index;
74 }
75
76 virtual void LauncherItemChanged(int index,
77 const ash::LauncherItem& old_item) OVERRIDE {
78 ++changed_;
79 last_index_ = index;
80 }
81
82 virtual void LauncherItemMoved(int start_index, int target_index) OVERRIDE {
83 last_index_ = target_index;
84 }
85
86 virtual void LauncherStatusChanged() OVERRIDE {
87 }
88
89 void clear_counts() {
90 added_ = 0;
91 removed_ = 0;
92 changed_ = 0;
93 last_index_ = 0;
94 }
95
96 int added() const { return added_; }
97 int removed() const { return removed_; }
98 int changed() const { return changed_; }
99 int last_index() const { return last_index_; }
100
101 private:
102 int added_;
103 int removed_;
104 int changed_;
105 int last_index_;
106
107 DISALLOW_COPY_AND_ASSIGN(TestLauncherModelObserver);
108 };
109
110 // Test implementation of AppIconLoader.
111 class TestAppIconLoaderImpl : public extensions::AppIconLoader {
112 public:
113 TestAppIconLoaderImpl() : fetch_count_(0) {
114 }
115
116 virtual ~TestAppIconLoaderImpl() {
117 }
118
119 // AppIconLoader implementation:
120 virtual void FetchImage(const std::string& id) OVERRIDE {
121 ++fetch_count_;
122 }
123
124 virtual void ClearImage(const std::string& id) OVERRIDE {
125 }
126
127 virtual void UpdateImage(const std::string& id) OVERRIDE {
128 }
129
130 int fetch_count() const { return fetch_count_; }
131
132 private:
133 int fetch_count_;
134
135 DISALLOW_COPY_AND_ASSIGN(TestAppIconLoaderImpl);
136 };
137
138 } // namespace
139
140 class ChromeLauncherControllerPerAppTest : public BrowserWithTestWindowTest {
141 protected:
142 ChromeLauncherControllerPerAppTest()
143 : extension_service_(NULL) {
144 SetHostDesktopType(chrome::HOST_DESKTOP_TYPE_ASH);
145 }
146
147 virtual ~ChromeLauncherControllerPerAppTest() {
148 }
149
150 virtual void SetUp() OVERRIDE {
151 BrowserWithTestWindowTest::SetUp();
152
153 model_.reset(new ash::LauncherModel);
154 model_observer_.reset(new TestLauncherModelObserver);
155 model_->AddObserver(model_observer_.get());
156
157 DictionaryValue manifest;
158 manifest.SetString(extensions::manifest_keys::kName,
159 "launcher controller test extension");
160 manifest.SetString(extensions::manifest_keys::kVersion, "1");
161 manifest.SetString(extensions::manifest_keys::kDescription,
162 "for testing pinned apps");
163
164 extensions::TestExtensionSystem* extension_system(
165 static_cast<extensions::TestExtensionSystem*>(
166 extensions::ExtensionSystem::Get(profile())));
167 extension_service_ = extension_system->CreateExtensionService(
168 CommandLine::ForCurrentProcess(), base::FilePath(), false);
169
170 std::string error;
171 extension1_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
172 manifest,
173 Extension::NO_FLAGS,
174 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
175 &error);
176 extension2_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
177 manifest,
178 Extension::NO_FLAGS,
179 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
180 &error);
181 // Fake gmail extension.
182 DictionaryValue manifest_gmail;
183 manifest_gmail.SetString(extensions::manifest_keys::kName,
184 "Gmail launcher controller test extension");
185 manifest_gmail.SetString(extensions::manifest_keys::kVersion, "1");
186 manifest_gmail.SetString(extensions::manifest_keys::kDescription,
187 "for testing pinned Gmail");
188 manifest_gmail.SetString(extensions::manifest_keys::kLaunchWebURL,
189 "https://mail.google.com/mail/ca");
190 ListValue* list = new ListValue();
191 list->Append(Value::CreateStringValue("*://mail.google.com/mail/ca"));
192 manifest_gmail.Set(extensions::manifest_keys::kWebURLs, list);
193
194 extension3_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
195 manifest_gmail,
196 Extension::NO_FLAGS,
197 extension_misc::kGmailAppId,
198 &error);
199
200 // Fake search extension.
201 extension4_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
202 manifest,
203 Extension::NO_FLAGS,
204 extension_misc::kGoogleSearchAppId,
205 &error);
206 }
207
208 virtual void TearDown() OVERRIDE {
209 model_->RemoveObserver(model_observer_.get());
210 model_observer_.reset();
211 launcher_controller_.reset();
212 model_.reset();
213
214 BrowserWithTestWindowTest::TearDown();
215 }
216
217 void InitLauncherController() {
218 launcher_controller_.reset(
219 new ChromeLauncherControllerPerApp(profile(), model_.get()));
220 launcher_controller_->Init();
221 }
222
223 void InitLauncherControllerWithBrowser() {
224 chrome::NewTab(browser());
225 BrowserList::SetLastActive(browser());
226 InitLauncherController();
227 }
228
229 void SetAppIconLoader(extensions::AppIconLoader* loader) {
230 launcher_controller_->SetAppIconLoaderForTest(loader);
231 }
232
233 void InsertPrefValue(base::ListValue* pref_value,
234 int index,
235 const std::string& extension_id) {
236 base::DictionaryValue* entry = new DictionaryValue();
237 entry->SetString(ash::kPinnedAppsPrefAppIDPath, extension_id);
238 pref_value->Insert(index, entry);
239 }
240
241 // Gets the currently configured app launchers from the controller.
242 void GetAppLaunchers(ChromeLauncherControllerPerApp* controller,
243 std::vector<std::string>* launchers) {
244 launchers->clear();
245 for (ash::LauncherItems::const_iterator iter(model_->items().begin());
246 iter != model_->items().end(); ++iter) {
247 ChromeLauncherControllerPerApp::IDToItemControllerMap::const_iterator
248 entry(controller->id_to_item_controller_map_.find(iter->id));
249 if (iter->type == ash::TYPE_APP_SHORTCUT &&
250 entry != controller->id_to_item_controller_map_.end()) {
251 launchers->push_back(entry->second->app_id());
252 }
253 }
254 }
255
256 std::string GetPinnedAppStatus() {
257 std::string result;
258 for (int i = 0; i < model_->item_count(); i++) {
259 switch (model_->items()[i].type) {
260 case ash::TYPE_APP_SHORTCUT: {
261 const std::string& app =
262 launcher_controller_->GetAppIDForLauncherID(
263 model_->items()[i].id);
264 if (app == extension1_->id()) {
265 result += "App1, ";
266 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
267 } else if (app == extension2_->id()) {
268 result += "App2, ";
269 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension2_->id()));
270 } else if (app == extension3_->id()) {
271 result += "App3, ";
272 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
273 } else if (app == extension4_->id()) {
274 result += "App4, ";
275 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension4_->id()));
276 } else {
277 result += "unknown, ";
278 }
279 break;
280 }
281 case ash::TYPE_BROWSER_SHORTCUT:
282 result += "Chrome, ";
283 break;
284 case ash::TYPE_APP_LIST:
285 result += "AppList, ";
286 break;
287 default:
288 result += "Unknown";
289 break;
290 }
291 }
292 return result;
293 }
294
295 // Needed for extension service & friends to work.
296 scoped_refptr<Extension> extension1_;
297 scoped_refptr<Extension> extension2_;
298 scoped_refptr<Extension> extension3_;
299 scoped_refptr<Extension> extension4_;
300 scoped_ptr<ChromeLauncherControllerPerApp> launcher_controller_;
301 scoped_ptr<TestLauncherModelObserver> model_observer_;
302 scoped_ptr<ash::LauncherModel> model_;
303
304 ExtensionService* extension_service_;
305
306 DISALLOW_COPY_AND_ASSIGN(ChromeLauncherControllerPerAppTest);
307 };
308
309 // The testing framework to test the alternate shelf layout.
310 class AlternateLayoutChromeLauncherControllerPerAppTest
311 : public ChromeLauncherControllerPerAppTest {
312 protected:
313 AlternateLayoutChromeLauncherControllerPerAppTest() {
314 }
315
316 virtual ~AlternateLayoutChromeLauncherControllerPerAppTest() {
317 }
318
319 // Overwrite the Setup function to add the Alternate Shelf layout option.
320 virtual void SetUp() OVERRIDE {
321 CommandLine::ForCurrentProcess()->AppendSwitch(
322 ash::switches::kAshUseAlternateShelfLayout);
323 ChromeLauncherControllerPerAppTest::SetUp();
324 }
325
326 // Set the index at which the chrome icon should be.
327 void SetShelfChromeIconIndex(int index) {
328 profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex,
329 index + 1);
330 }
331
332 private:
333
334 DISALLOW_COPY_AND_ASSIGN(AlternateLayoutChromeLauncherControllerPerAppTest);
335 };
336
337
338 TEST_F(ChromeLauncherControllerPerAppTest, DefaultApps) {
339 InitLauncherController();
340 // Model should only contain the browser shortcut and app list items.
341 EXPECT_EQ(2, model_->item_count());
342 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
343 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
344 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
345
346 // Installing |extension3_| should add it to the launcher - behind the
347 // chrome icon.
348 extension_service_->AddExtension(extension3_.get());
349 EXPECT_EQ("Chrome, App3, AppList, ", GetPinnedAppStatus());
350 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
351 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
352 }
353
354 // Check that the restauration of launcher items is happening in the same order
355 // as the user has pinned them (on another system) when they are synced reverse
356 // order.
357 TEST_F(ChromeLauncherControllerPerAppTest, RestoreDefaultAppsReverseOrder) {
358 InitLauncherController();
359
360 base::ListValue policy_value;
361 InsertPrefValue(&policy_value, 0, extension1_->id());
362 InsertPrefValue(&policy_value, 1, extension2_->id());
363 InsertPrefValue(&policy_value, 2, extension3_->id());
364 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
365 policy_value.DeepCopy());
366 EXPECT_EQ(0, profile()->GetPrefs()->GetInteger(prefs::kShelfChromeIconIndex));
367 // Model should only contain the browser shortcut and app list items.
368 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
369 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
370 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
371 EXPECT_EQ("Chrome, AppList, ", GetPinnedAppStatus());
372
373 // Installing |extension3_| should add it to the launcher - behind the
374 // chrome icon.
375 ash::LauncherItem item;
376 extension_service_->AddExtension(extension3_.get());
377 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
378 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
379 EXPECT_EQ("Chrome, App3, AppList, ", GetPinnedAppStatus());
380
381 // Installing |extension2_| should add it to the launcher - behind the
382 // chrome icon, but in first location.
383 extension_service_->AddExtension(extension2_.get());
384 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
385 EXPECT_EQ("Chrome, App2, App3, AppList, ", GetPinnedAppStatus());
386
387 // Installing |extension1_| should add it to the launcher - behind the
388 // chrome icon, but in first location.
389 extension_service_->AddExtension(extension1_.get());
390 EXPECT_EQ("Chrome, App1, App2, App3, AppList, ", GetPinnedAppStatus());
391 }
392
393 // Check that the restauration of launcher items is happening in the same order
394 // as the user has pinned them (on another system) when they are synced random
395 // order.
396 TEST_F(ChromeLauncherControllerPerAppTest, RestoreDefaultAppsRandomOrder) {
397 InitLauncherController();
398
399 base::ListValue policy_value;
400 InsertPrefValue(&policy_value, 0, extension1_->id());
401 InsertPrefValue(&policy_value, 1, extension2_->id());
402 InsertPrefValue(&policy_value, 2, extension3_->id());
403 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
404 policy_value.DeepCopy());
405 EXPECT_EQ(0, profile()->GetPrefs()->GetInteger(prefs::kShelfChromeIconIndex));
406 // Model should only contain the browser shortcut and app list items.
407 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
408 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
409 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
410 EXPECT_EQ("Chrome, AppList, ", GetPinnedAppStatus());
411
412 // Installing |extension2_| should add it to the launcher - behind the
413 // chrome icon.
414 extension_service_->AddExtension(extension2_.get());
415 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
416 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
417 EXPECT_EQ("Chrome, App2, AppList, ", GetPinnedAppStatus());
418
419 // Installing |extension1_| should add it to the launcher - behind the
420 // chrome icon, but in first location.
421 extension_service_->AddExtension(extension1_.get());
422 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
423 EXPECT_EQ("Chrome, App1, App2, AppList, ", GetPinnedAppStatus());
424
425 // Installing |extension3_| should add it to the launcher - behind the
426 // chrome icon, but in first location.
427 extension_service_->AddExtension(extension3_.get());
428 EXPECT_EQ("Chrome, App1, App2, App3, AppList, ", GetPinnedAppStatus());
429 }
430
431 // Check that the restauration of launcher items is happening in the same order
432 // as the user has pinned / moved them (on another system) when they are synced
433 // random order - including the chrome icon.
434 TEST_F(ChromeLauncherControllerPerAppTest,
435 RestoreDefaultAppsRandomOrderChromeMoved) {
436 InitLauncherController();
437
438 base::ListValue policy_value;
439 InsertPrefValue(&policy_value, 0, extension1_->id());
440 InsertPrefValue(&policy_value, 1, extension2_->id());
441 InsertPrefValue(&policy_value, 2, extension3_->id());
442 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
443 policy_value.DeepCopy());
444 profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex,
445 1);
446 // Model should only contain the browser shortcut and app list items.
447 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
448 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
449 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
450 EXPECT_EQ("Chrome, AppList, ", GetPinnedAppStatus());
451
452 // Installing |extension2_| should add it to the launcher - behind the
453 // chrome icon.
454 ash::LauncherItem item;
455 extension_service_->AddExtension(extension2_.get());
456 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
457 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
458 EXPECT_EQ("Chrome, App2, AppList, ", GetPinnedAppStatus());
459
460 // Installing |extension1_| should add it to the launcher - behind the
461 // chrome icon, but in first location.
462 extension_service_->AddExtension(extension1_.get());
463 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
464 EXPECT_EQ("App1, Chrome, App2, AppList, ", GetPinnedAppStatus());
465
466 // Installing |extension3_| should add it to the launcher - behind the
467 // chrome icon, but in first location.
468 extension_service_->AddExtension(extension3_.get());
469 EXPECT_EQ("App1, Chrome, App2, App3, AppList, ", GetPinnedAppStatus());
470 }
471
472 // Check that syncing to a different state does the correct thing.
473 TEST_F(ChromeLauncherControllerPerAppTest, RestoreDefaultAppsResyncOrder) {
474 InitLauncherController();
475 base::ListValue policy_value;
476 InsertPrefValue(&policy_value, 0, extension1_->id());
477 InsertPrefValue(&policy_value, 1, extension2_->id());
478 InsertPrefValue(&policy_value, 2, extension3_->id());
479 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
480 policy_value.DeepCopy());
481 EXPECT_EQ(0, profile()->GetPrefs()->GetInteger(prefs::kShelfChromeIconIndex));
482 extension_service_->AddExtension(extension2_.get());
483 extension_service_->AddExtension(extension1_.get());
484 extension_service_->AddExtension(extension3_.get());
485 EXPECT_EQ("Chrome, App1, App2, App3, AppList, ", GetPinnedAppStatus());
486
487 // Change the order with increasing chrome position and decreasing position.
488 base::ListValue policy_value1;
489 InsertPrefValue(&policy_value1, 0, extension3_->id());
490 InsertPrefValue(&policy_value1, 1, extension1_->id());
491 InsertPrefValue(&policy_value1, 2, extension2_->id());
492 profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex,
493 2);
494 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
495 policy_value1.DeepCopy());
496 EXPECT_EQ("App3, App1, Chrome, App2, AppList, ", GetPinnedAppStatus());
497 base::ListValue policy_value2;
498 InsertPrefValue(&policy_value2, 0, extension2_->id());
499 InsertPrefValue(&policy_value2, 1, extension3_->id());
500 InsertPrefValue(&policy_value2, 2, extension1_->id());
501 profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex,
502 1);
503 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
504 policy_value2.DeepCopy());
505 EXPECT_EQ("App2, Chrome, App3, App1, AppList, ", GetPinnedAppStatus());
506 }
507
508 TEST_F(AlternateLayoutChromeLauncherControllerPerAppTest, DefaultApps) {
509 InitLauncherController();
510 // Model should only contain the browser shortcut and app list items.
511 EXPECT_EQ(2, model_->item_count());
512 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
513 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
514 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
515
516 // Installing |extension3_| should add it to the launcher - behind the
517 // chrome icon.
518 extension_service_->AddExtension(extension3_.get());
519 EXPECT_EQ("AppList, Chrome, App3, ", GetPinnedAppStatus());
520 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
521 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
522 }
523
524 // Check that the restauration of launcher items is happening in the same order
525 // as the user has pinned them (on another system) when they are synced reverse
526 // order.
527 TEST_F(AlternateLayoutChromeLauncherControllerPerAppTest,
528 RestoreDefaultAppsReverseOrder) {
529 InitLauncherController();
530
531 base::ListValue policy_value;
532 InsertPrefValue(&policy_value, 0, extension1_->id());
533 InsertPrefValue(&policy_value, 1, extension2_->id());
534 InsertPrefValue(&policy_value, 2, extension3_->id());
535 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
536 policy_value.DeepCopy());
537 SetShelfChromeIconIndex(0);
538 // Model should only contain the browser shortcut and app list items.
539 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
540 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
541 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
542 EXPECT_EQ("AppList, Chrome, ", GetPinnedAppStatus());
543
544 // Installing |extension3_| should add it to the launcher - behind the
545 // chrome icon.
546 ash::LauncherItem item;
547 extension_service_->AddExtension(extension3_.get());
548 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
549 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
550 EXPECT_EQ("AppList, Chrome, App3, ", GetPinnedAppStatus());
551
552 // Installing |extension2_| should add it to the launcher - behind the
553 // chrome icon, but in first location.
554 extension_service_->AddExtension(extension2_.get());
555 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
556 EXPECT_EQ("AppList, Chrome, App2, App3, ", GetPinnedAppStatus());
557
558 // Installing |extension1_| should add it to the launcher - behind the
559 // chrome icon, but in first location.
560 extension_service_->AddExtension(extension1_.get());
561 EXPECT_EQ("AppList, Chrome, App1, App2, App3, ", GetPinnedAppStatus());
562 }
563
564 // Check that the restauration of launcher items is happening in the same order
565 // as the user has pinned them (on another system) when they are synced random
566 // order.
567 TEST_F(AlternateLayoutChromeLauncherControllerPerAppTest,
568 RestoreDefaultAppsRandomOrder) {
569 InitLauncherController();
570
571 base::ListValue policy_value;
572 InsertPrefValue(&policy_value, 0, extension1_->id());
573 InsertPrefValue(&policy_value, 1, extension2_->id());
574 InsertPrefValue(&policy_value, 2, extension3_->id());
575 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
576 policy_value.DeepCopy());
577 SetShelfChromeIconIndex(0);
578 // Model should only contain the browser shortcut and app list items.
579 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
580 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
581 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
582 EXPECT_EQ("AppList, Chrome, ", GetPinnedAppStatus());
583
584 // Installing |extension2_| should add it to the launcher - behind the
585 // chrome icon.
586 extension_service_->AddExtension(extension2_.get());
587 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
588 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
589 EXPECT_EQ("AppList, Chrome, App2, ", GetPinnedAppStatus());
590
591 // Installing |extension1_| should add it to the launcher - behind the
592 // chrome icon, but in first location.
593 extension_service_->AddExtension(extension1_.get());
594 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
595 EXPECT_EQ("AppList, Chrome, App1, App2, ", GetPinnedAppStatus());
596
597 // Installing |extension3_| should add it to the launcher - behind the
598 // chrome icon, but in first location.
599 extension_service_->AddExtension(extension3_.get());
600 EXPECT_EQ("AppList, Chrome, App1, App2, App3, ", GetPinnedAppStatus());
601 }
602
603 // Check that the restauration of launcher items is happening in the same order
604 // as the user has pinned / moved them (on another system) when they are synced
605 // random order - including the chrome icon - using the alternate shelf layout.
606 TEST_F(AlternateLayoutChromeLauncherControllerPerAppTest,
607 RestoreDefaultAppsRandomOrderChromeMoved) {
608 InitLauncherController();
609
610 base::ListValue policy_value;
611 InsertPrefValue(&policy_value, 0, extension1_->id());
612 InsertPrefValue(&policy_value, 1, extension2_->id());
613 InsertPrefValue(&policy_value, 2, extension3_->id());
614 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
615 policy_value.DeepCopy());
616 SetShelfChromeIconIndex(1);
617 // Model should only contain the browser shortcut and app list items.
618 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
619 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
620 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
621 EXPECT_EQ("AppList, Chrome, ", GetPinnedAppStatus());
622
623 // Installing |extension2_| should add it to the launcher - behind the
624 // chrome icon.
625 ash::LauncherItem item;
626 extension_service_->AddExtension(extension2_.get());
627 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
628 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
629 EXPECT_EQ("AppList, Chrome, App2, ", GetPinnedAppStatus());
630
631 // Installing |extension1_| should add it to the launcher - behind the
632 // chrome icon, but in first location.
633 extension_service_->AddExtension(extension1_.get());
634 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
635 EXPECT_EQ("AppList, App1, Chrome, App2, ", GetPinnedAppStatus());
636
637 // Installing |extension3_| should add it to the launcher - behind the
638 // chrome icon, but in first location.
639 extension_service_->AddExtension(extension3_.get());
640 EXPECT_EQ("AppList, App1, Chrome, App2, App3, ", GetPinnedAppStatus());
641 }
642
643 // Check that syncing to a different state does the correct thing with the
644 // alternate shelf layout.
645 TEST_F(AlternateLayoutChromeLauncherControllerPerAppTest,
646 RestoreDefaultAppsResyncOrder) {
647 InitLauncherController();
648 base::ListValue policy_value;
649 InsertPrefValue(&policy_value, 0, extension1_->id());
650 InsertPrefValue(&policy_value, 1, extension2_->id());
651 InsertPrefValue(&policy_value, 2, extension3_->id());
652 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
653 policy_value.DeepCopy());
654 // The alternate shelf layout has always one static item at the beginning.
655 SetShelfChromeIconIndex(0);
656 extension_service_->AddExtension(extension2_.get());
657 EXPECT_EQ("AppList, Chrome, App2, ", GetPinnedAppStatus());
658 extension_service_->AddExtension(extension1_.get());
659 EXPECT_EQ("AppList, Chrome, App1, App2, ", GetPinnedAppStatus());
660 extension_service_->AddExtension(extension3_.get());
661 EXPECT_EQ("AppList, Chrome, App1, App2, App3, ", GetPinnedAppStatus());
662
663 // Change the order with increasing chrome position and decreasing position.
664 base::ListValue policy_value1;
665 InsertPrefValue(&policy_value1, 0, extension3_->id());
666 InsertPrefValue(&policy_value1, 1, extension1_->id());
667 InsertPrefValue(&policy_value1, 2, extension2_->id());
668 SetShelfChromeIconIndex(3);
669 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
670 policy_value1.DeepCopy());
671 EXPECT_EQ("AppList, App3, App1, App2, Chrome, ", GetPinnedAppStatus());
672 base::ListValue policy_value2;
673 InsertPrefValue(&policy_value2, 0, extension2_->id());
674 InsertPrefValue(&policy_value2, 1, extension3_->id());
675 InsertPrefValue(&policy_value2, 2, extension1_->id());
676 SetShelfChromeIconIndex(2);
677 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
678 policy_value2.DeepCopy());
679 EXPECT_EQ("AppList, App2, App3, Chrome, App1, ", GetPinnedAppStatus());
680
681 // Check that the chrome icon can also be at the first possible location.
682 SetShelfChromeIconIndex(0);
683 base::ListValue policy_value3;
684 InsertPrefValue(&policy_value3, 0, extension3_->id());
685 InsertPrefValue(&policy_value3, 1, extension2_->id());
686 InsertPrefValue(&policy_value3, 2, extension1_->id());
687 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
688 policy_value3.DeepCopy());
689 EXPECT_EQ("AppList, Chrome, App3, App2, App1, ", GetPinnedAppStatus());
690
691 // Check that unloading of extensions works as expected.
692 extension_service_->UnloadExtension(extension1_->id(),
693 extension_misc::UNLOAD_REASON_UNINSTALL);
694 EXPECT_EQ("AppList, Chrome, App3, App2, ", GetPinnedAppStatus());
695
696 extension_service_->UnloadExtension(extension2_->id(),
697 extension_misc::UNLOAD_REASON_UNINSTALL);
698 EXPECT_EQ("AppList, Chrome, App3, ", GetPinnedAppStatus());
699
700 // Check that an update of an extension does not crash the system.
701 extension_service_->UnloadExtension(extension3_->id(),
702 extension_misc::UNLOAD_REASON_UPDATE);
703 EXPECT_EQ("AppList, Chrome, App3, ", GetPinnedAppStatus());
704 }
705
706 // Check that simple locking of an application will 'create' a launcher item.
707 TEST_F(ChromeLauncherControllerPerAppTest, CheckLockApps) {
708 InitLauncherController();
709 // Model should only contain the browser shortcut and app list items.
710 EXPECT_EQ(2, model_->item_count());
711 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
712 EXPECT_FALSE(
713 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
714 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
715 EXPECT_FALSE(
716 launcher_controller_->IsWindowedAppInLauncher(extension2_->id()));
717
718 launcher_controller_->LockV1AppWithID(extension1_->id());
719
720 EXPECT_EQ(3, model_->item_count());
721 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[1].type);
722 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
723 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
724 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
725 EXPECT_FALSE(
726 launcher_controller_->IsWindowedAppInLauncher(extension2_->id()));
727
728 launcher_controller_->UnlockV1AppWithID(extension1_->id());
729
730 EXPECT_EQ(2, model_->item_count());
731 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
732 EXPECT_FALSE(
733 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
734 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
735 EXPECT_FALSE(
736 launcher_controller_->IsWindowedAppInLauncher(extension2_->id()));
737 }
738
739 // Check that multiple locks of an application will be properly handled.
740 TEST_F(ChromeLauncherControllerPerAppTest, CheckMukltiLockApps) {
741 InitLauncherController();
742 // Model should only contain the browser shortcut and app list items.
743 EXPECT_EQ(2, model_->item_count());
744 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
745 EXPECT_FALSE(
746 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
747
748 for (int i = 0; i < 2; i++) {
749 launcher_controller_->LockV1AppWithID(extension1_->id());
750
751 EXPECT_EQ(3, model_->item_count());
752 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[1].type);
753 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
754 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(
755 extension1_->id()));
756 }
757
758 launcher_controller_->UnlockV1AppWithID(extension1_->id());
759
760 EXPECT_EQ(3, model_->item_count());
761 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[1].type);
762 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
763 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
764
765 launcher_controller_->UnlockV1AppWithID(extension1_->id());
766
767 EXPECT_EQ(2, model_->item_count());
768 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
769 EXPECT_FALSE(
770 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
771 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
772 EXPECT_FALSE(
773 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
774 }
775
776 // Check that already pinned items are not effected by locks.
777 TEST_F(ChromeLauncherControllerPerAppTest, CheckAlreadyPinnedLockApps) {
778 InitLauncherController();
779 // Model should only contain the browser shortcut and app list items.
780 EXPECT_EQ(2, model_->item_count());
781 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
782 EXPECT_FALSE(
783 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
784
785 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
786 launcher_controller_->PinAppWithID(extension1_->id());
787 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
788
789 EXPECT_EQ(3, model_->item_count());
790 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[1].type);
791 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
792 EXPECT_FALSE(
793 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
794
795 launcher_controller_->LockV1AppWithID(extension1_->id());
796
797 EXPECT_EQ(3, model_->item_count());
798 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[1].type);
799 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
800 EXPECT_FALSE(
801 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
802
803 launcher_controller_->UnlockV1AppWithID(extension1_->id());
804
805 EXPECT_EQ(3, model_->item_count());
806 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[1].type);
807 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
808 EXPECT_FALSE(
809 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
810
811 launcher_controller_->UnpinAppsWithID(extension1_->id());
812
813 EXPECT_EQ(2, model_->item_count());
814 }
815
816 // Check that already pinned items which get locked stay after unpinning.
817 TEST_F(ChromeLauncherControllerPerAppTest, CheckPinnedAppsStayAfterUnlock) {
818 InitLauncherController();
819 // Model should only contain the browser shortcut and app list items.
820 EXPECT_EQ(2, model_->item_count());
821 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
822 EXPECT_FALSE(
823 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
824
825 launcher_controller_->PinAppWithID(extension1_->id());
826
827 EXPECT_EQ(3, model_->item_count());
828 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[1].type);
829 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
830 EXPECT_FALSE(
831 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
832
833 launcher_controller_->LockV1AppWithID(extension1_->id());
834
835 EXPECT_EQ(3, model_->item_count());
836 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[1].type);
837 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
838 EXPECT_FALSE(
839 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
840
841 launcher_controller_->UnpinAppsWithID(extension1_->id());
842
843 EXPECT_EQ(3, model_->item_count());
844 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[1].type);
845 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
846 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
847
848 launcher_controller_->UnlockV1AppWithID(extension1_->id());
849
850 EXPECT_EQ(2, model_->item_count());
851 }
852
853 // Check that lock -> pin -> unlock -> unpin does properly transition.
854 TEST_F(ChromeLauncherControllerPerAppTest, CheckLockPinUnlockUnpin) {
855 InitLauncherController();
856 // Model should only contain the browser shortcut and app list items.
857 EXPECT_EQ(2, model_->item_count());
858 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
859 EXPECT_FALSE(
860 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
861
862 launcher_controller_->LockV1AppWithID(extension1_->id());
863
864 EXPECT_EQ(3, model_->item_count());
865 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[1].type);
866 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
867 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
868
869 launcher_controller_->PinAppWithID(extension1_->id());
870
871 EXPECT_EQ(3, model_->item_count());
872 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[1].type);
873 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
874 EXPECT_FALSE(
875 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
876
877 launcher_controller_->UnlockV1AppWithID(extension1_->id());
878
879 EXPECT_EQ(3, model_->item_count());
880 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[1].type);
881 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
882 EXPECT_FALSE(
883 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
884
885 launcher_controller_->UnpinAppsWithID(extension1_->id());
886
887 EXPECT_EQ(2, model_->item_count());
888 }
889
890 TEST_F(ChromeLauncherControllerPerAppTest, Policy) {
891 extension_service_->AddExtension(extension1_.get());
892 extension_service_->AddExtension(extension3_.get());
893
894 base::ListValue policy_value;
895 InsertPrefValue(&policy_value, 0, extension1_->id());
896 InsertPrefValue(&policy_value, 1, extension2_->id());
897 profile()->GetTestingPrefService()->SetManagedPref(prefs::kPinnedLauncherApps,
898 policy_value.DeepCopy());
899
900 // Only |extension1_| should get pinned. |extension2_| is specified but not
901 // installed, and |extension3_| is part of the default set, but that shouldn't
902 // take effect when the policy override is in place.
903 InitLauncherController();
904 EXPECT_EQ(3, model_->item_count());
905 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[1].type);
906 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
907 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
908 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
909
910 // Installing |extension2_| should add it to the launcher.
911 extension_service_->AddExtension(extension2_.get());
912 EXPECT_EQ(4, model_->item_count());
913 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[1].type);
914 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
915 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
916 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension2_->id()));
917 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
918
919 // Removing |extension1_| from the policy should be reflected in the launcher.
920 policy_value.Remove(0, NULL);
921 profile()->GetTestingPrefService()->SetManagedPref(prefs::kPinnedLauncherApps,
922 policy_value.DeepCopy());
923 EXPECT_EQ(3, model_->item_count());
924 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[1].type);
925 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
926 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension2_->id()));
927 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
928 }
929
930 TEST_F(ChromeLauncherControllerPerAppTest, UnpinWithUninstall) {
931 extension_service_->AddExtension(extension3_.get());
932 extension_service_->AddExtension(extension4_.get());
933
934 InitLauncherController();
935
936 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
937 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension4_->id()));
938
939 extension_service_->UnloadExtension(extension3_->id(),
940 extension_misc::UNLOAD_REASON_UNINSTALL);
941
942 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
943 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension4_->id()));
944 }
945
946 TEST_F(ChromeLauncherControllerPerAppTest, PrefUpdates) {
947 extension_service_->AddExtension(extension2_.get());
948 extension_service_->AddExtension(extension3_.get());
949 extension_service_->AddExtension(extension4_.get());
950
951 InitLauncherController();
952
953 std::vector<std::string> expected_launchers;
954 std::vector<std::string> actual_launchers;
955 base::ListValue pref_value;
956 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
957 pref_value.DeepCopy());
958 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
959 EXPECT_EQ(expected_launchers, actual_launchers);
960
961 // Unavailable extensions don't create launcher items.
962 InsertPrefValue(&pref_value, 0, extension1_->id());
963 InsertPrefValue(&pref_value, 1, extension2_->id());
964 InsertPrefValue(&pref_value, 2, extension4_->id());
965 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
966 pref_value.DeepCopy());
967 expected_launchers.push_back(extension2_->id());
968 expected_launchers.push_back(extension4_->id());
969 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
970 EXPECT_EQ(expected_launchers, actual_launchers);
971
972 // Redundant pref entries show up only once.
973 InsertPrefValue(&pref_value, 2, extension3_->id());
974 InsertPrefValue(&pref_value, 2, extension3_->id());
975 InsertPrefValue(&pref_value, 5, extension3_->id());
976 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
977 pref_value.DeepCopy());
978 expected_launchers.insert(expected_launchers.begin() + 1, extension3_->id());
979 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
980 EXPECT_EQ(expected_launchers, actual_launchers);
981
982 // Order changes are reflected correctly.
983 pref_value.Clear();
984 InsertPrefValue(&pref_value, 0, extension4_->id());
985 InsertPrefValue(&pref_value, 1, extension3_->id());
986 InsertPrefValue(&pref_value, 2, extension2_->id());
987 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
988 pref_value.DeepCopy());
989 std::reverse(expected_launchers.begin(), expected_launchers.end());
990 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
991 EXPECT_EQ(expected_launchers, actual_launchers);
992
993 // Clearing works.
994 pref_value.Clear();
995 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
996 pref_value.DeepCopy());
997 expected_launchers.clear();
998 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
999 EXPECT_EQ(expected_launchers, actual_launchers);
1000 }
1001
1002 TEST_F(ChromeLauncherControllerPerAppTest, PendingInsertionOrder) {
1003 extension_service_->AddExtension(extension1_.get());
1004 extension_service_->AddExtension(extension3_.get());
1005
1006 InitLauncherController();
1007
1008 base::ListValue pref_value;
1009 InsertPrefValue(&pref_value, 0, extension1_->id());
1010 InsertPrefValue(&pref_value, 1, extension2_->id());
1011 InsertPrefValue(&pref_value, 2, extension3_->id());
1012 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1013 pref_value.DeepCopy());
1014
1015 std::vector<std::string> expected_launchers;
1016 expected_launchers.push_back(extension1_->id());
1017 expected_launchers.push_back(extension3_->id());
1018 std::vector<std::string> actual_launchers;
1019
1020 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
1021 EXPECT_EQ(expected_launchers, actual_launchers);
1022
1023 // Install |extension2| and verify it shows up between the other two.
1024 extension_service_->AddExtension(extension2_.get());
1025 expected_launchers.insert(expected_launchers.begin() + 1, extension2_->id());
1026 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
1027 EXPECT_EQ(expected_launchers, actual_launchers);
1028 }
1029
1030 // Checks the created menus and menu lists for correctness. It uses the given
1031 // |controller| to create the objects for the given |item| and checks the
1032 // found item count against the |expected_items|. The |title| list contains the
1033 // menu titles in the order of their appearance in the menu (not including the
1034 // application name).
1035 bool CheckMenuCreation(ChromeLauncherControllerPerApp* controller,
1036 const ash::LauncherItem& item,
1037 size_t expected_items,
1038 string16 title[],
1039 bool is_browser) {
1040 ChromeLauncherAppMenuItems items = controller->GetApplicationList(item, 0);
1041 // A new behavior has been added: Only show menus if there is at least one
1042 // item available.
1043 if (expected_items < 1 && is_browser) {
1044 EXPECT_EQ(0u, items.size());
1045 return items.size() == 0;
1046 }
1047 // There should be one item in there: The title.
1048 EXPECT_EQ(expected_items + 1, items.size());
1049 EXPECT_FALSE(items[0]->IsEnabled());
1050 for (size_t i = 0; i < expected_items; i++) {
1051 EXPECT_EQ(title[i], items[1 + i]->title());
1052 // Check that the first real item has a leading separator.
1053 if (i == 1)
1054 EXPECT_TRUE(items[i]->HasLeadingSeparator());
1055 else
1056 EXPECT_FALSE(items[i]->HasLeadingSeparator());
1057 }
1058
1059 scoped_ptr<ash::LauncherMenuModel> menu(
1060 controller->CreateApplicationMenu(item, 0));
1061 // The first element in the menu is a spacing separator. On some systems
1062 // (e.g. Windows) such things do not exist. As such we check the existence
1063 // and adjust dynamically.
1064 int first_item = menu->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR ? 1 : 0;
1065 int expected_menu_items = first_item +
1066 (expected_items ? (expected_items + 3) : 2);
1067 EXPECT_EQ(expected_menu_items, menu->GetItemCount());
1068 EXPECT_FALSE(menu->IsEnabledAt(first_item));
1069 if (expected_items) {
1070 EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR,
1071 menu->GetTypeAt(first_item + 1));
1072 }
1073 return items.size() == expected_items + 1;
1074 }
1075
1076 // Check that browsers get reflected correctly in the launcher menu.
1077 TEST_F(ChromeLauncherControllerPerAppTest, BrowserMenuGeneration) {
1078 EXPECT_EQ(1U, chrome::GetTotalBrowserCount());
1079 chrome::NewTab(browser());
1080
1081 InitLauncherController();
1082
1083 // Check that the browser list is empty at this time.
1084 ash::LauncherItem item_browser;
1085 item_browser.type = ash::TYPE_BROWSER_SHORTCUT;
1086 item_browser.id =
1087 launcher_controller_->GetLauncherIDForAppID(extension_misc::kChromeAppId);
1088 EXPECT_TRUE(CheckMenuCreation(
1089 launcher_controller_.get(), item_browser, 0, NULL, true));
1090
1091 // Now make the created browser() visible by adding it to the active browser
1092 // list.
1093 BrowserList::SetLastActive(browser());
1094 string16 title1 = ASCIIToUTF16("Test1");
1095 NavigateAndCommitActiveTabWithTitle(browser(), GURL("http://test1"), title1);
1096 string16 one_menu_item[] = {title1};
1097
1098 EXPECT_TRUE(CheckMenuCreation(
1099 launcher_controller_.get(), item_browser, 1, one_menu_item, true));
1100
1101 // Create one more browser/window and check that one more was added.
1102 Browser::CreateParams ash_params(profile(), chrome::HOST_DESKTOP_TYPE_ASH);
1103 scoped_ptr<Browser> browser2(
1104 chrome::CreateBrowserWithTestWindowForParams(&ash_params));
1105 chrome::NewTab(browser2.get());
1106 BrowserList::SetLastActive(browser2.get());
1107 string16 title2 = ASCIIToUTF16("Test2");
1108 NavigateAndCommitActiveTabWithTitle(browser2.get(), GURL("http://test2"),
1109 title2);
1110
1111 // Check that the list contains now two entries - make furthermore sure that
1112 // the active item is the first entry.
1113 string16 two_menu_items[] = {title1, title2};
1114 EXPECT_TRUE(CheckMenuCreation(
1115 launcher_controller_.get(), item_browser, 2, two_menu_items, true));
1116
1117 // Apparently we have to close all tabs we have.
1118 chrome::CloseTab(browser2.get());
1119 }
1120
1121 // Check that V1 apps are correctly reflected in the launcher menu using the
1122 // refocus logic.
1123 // Note that the extension matching logic is tested by the extension system
1124 // and does not need a separate test here.
1125 TEST_F(ChromeLauncherControllerPerAppTest, V1AppMenuGeneration) {
1126 EXPECT_EQ(1U, chrome::GetTotalBrowserCount());
1127 EXPECT_EQ(0, browser()->tab_strip_model()->count());
1128
1129 InitLauncherControllerWithBrowser();
1130
1131 // Model should only contain the browser shortcut and app list items.
1132 EXPECT_EQ(2, model_->item_count());
1133 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1134
1135 // Installing |extension3_| adds it to the launcher.
1136 ash::LauncherID gmail_id = model_->next_id();
1137 extension_service_->AddExtension(extension3_.get());
1138 EXPECT_EQ(3, model_->item_count());
1139 int gmail_index = model_->ItemIndexByID(gmail_id);
1140 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[gmail_index].type);
1141 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
1142 launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(gmail_url));
1143
1144 // Check the menu content.
1145 ash::LauncherItem item_browser;
1146 item_browser.type = ash::TYPE_BROWSER_SHORTCUT;
1147 item_browser.id =
1148 launcher_controller_->GetLauncherIDForAppID(extension_misc::kChromeAppId);
1149
1150 ash::LauncherItem item_gmail;
1151 item_gmail.type = ash::TYPE_APP_SHORTCUT;
1152 item_gmail.id = gmail_id;
1153 EXPECT_TRUE(CheckMenuCreation(
1154 launcher_controller_.get(), item_gmail, 0, NULL, false));
1155
1156 // Set the gmail URL to a new tab.
1157 string16 title1 = ASCIIToUTF16("Test1");
1158 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title1);
1159
1160 string16 one_menu_item[] = {title1};
1161 EXPECT_TRUE(CheckMenuCreation(
1162 launcher_controller_.get(), item_gmail, 1, one_menu_item, false));
1163
1164 // Create one empty tab.
1165 chrome::NewTab(browser());
1166 string16 title2 = ASCIIToUTF16("Test2");
1167 NavigateAndCommitActiveTabWithTitle(
1168 browser(),
1169 GURL("https://bla"),
1170 title2);
1171
1172 // and another one with another gmail instance.
1173 chrome::NewTab(browser());
1174 string16 title3 = ASCIIToUTF16("Test3");
1175 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title3);
1176 string16 two_menu_items[] = {title1, title3};
1177 EXPECT_TRUE(CheckMenuCreation(
1178 launcher_controller_.get(), item_gmail, 2, two_menu_items, false));
1179
1180 // Even though the item is in the V1 app list, it should also be in the
1181 // browser list.
1182 string16 browser_menu_item[] = {title3};
1183 EXPECT_TRUE(CheckMenuCreation(
1184 launcher_controller_.get(), item_browser, 1, browser_menu_item, false));
1185
1186 // Test that closing of (all) the item(s) does work (and all menus get
1187 // updated properly).
1188 launcher_controller_->Close(item_gmail.id);
1189
1190 EXPECT_TRUE(CheckMenuCreation(
1191 launcher_controller_.get(), item_gmail, 0, NULL, false));
1192 string16 browser_menu_item2[] = {title2};
1193 EXPECT_TRUE(CheckMenuCreation(
1194 launcher_controller_.get(), item_browser, 1, browser_menu_item2, false));
1195 }
1196
1197 // Checks that the generated menu list properly activates items.
1198 TEST_F(ChromeLauncherControllerPerAppTest, V1AppMenuExecution) {
1199 InitLauncherControllerWithBrowser();
1200
1201 // Add |extension3_| to the launcher and add two items.
1202 GURL gmail = GURL("https://mail.google.com/mail/u");
1203 ash::LauncherID gmail_id = model_->next_id();
1204 extension_service_->AddExtension(extension3_.get());
1205 launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(gmail_url));
1206 string16 title1 = ASCIIToUTF16("Test1");
1207 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title1);
1208 chrome::NewTab(browser());
1209 string16 title2 = ASCIIToUTF16("Test2");
1210 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title2);
1211
1212 // Check that the menu is properly set.
1213 ash::LauncherItem item_gmail;
1214 item_gmail.type = ash::TYPE_APP_SHORTCUT;
1215 item_gmail.id = gmail_id;
1216 string16 two_menu_items[] = {title1, title2};
1217 EXPECT_TRUE(CheckMenuCreation(
1218 launcher_controller_.get(), item_gmail, 2, two_menu_items, false));
1219 EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
1220 // Execute the second item in the list (which shouldn't do anything since that
1221 // item is per definition already the active tab).
1222 {
1223 scoped_ptr<ash::LauncherMenuModel> menu(
1224 launcher_controller_->CreateApplicationMenu(item_gmail, 0));
1225 // The first element in the menu is a spacing separator. On some systems
1226 // (e.g. Windows) such things do not exist. As such we check the existence
1227 // and adjust dynamically.
1228 int first_item =
1229 (menu->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR) ? 1 : 0;
1230 menu->ActivatedAt(first_item + 3);
1231 }
1232 EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
1233
1234 // Execute the first item.
1235 {
1236 scoped_ptr<ash::LauncherMenuModel> menu(
1237 launcher_controller_->CreateApplicationMenu(item_gmail, 0));
1238 int first_item =
1239 (menu->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR) ? 1 : 0;
1240 menu->ActivatedAt(first_item + 2);
1241 }
1242 // Now the active tab should be the second item.
1243 EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
1244 }
1245
1246 // Checks that the generated menu list properly deletes items.
1247 TEST_F(ChromeLauncherControllerPerAppTest, V1AppMenuDeletionExecution) {
1248 InitLauncherControllerWithBrowser();
1249
1250 // Add |extension3_| to the launcher and add two items.
1251 GURL gmail = GURL("https://mail.google.com/mail/u");
1252 ash::LauncherID gmail_id = model_->next_id();
1253 extension_service_->AddExtension(extension3_.get());
1254 launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(gmail_url));
1255 string16 title1 = ASCIIToUTF16("Test1");
1256 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title1);
1257 chrome::NewTab(browser());
1258 string16 title2 = ASCIIToUTF16("Test2");
1259 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title2);
1260
1261 // Check that the menu is properly set.
1262 ash::LauncherItem item_gmail;
1263 item_gmail.type = ash::TYPE_APP_SHORTCUT;
1264 item_gmail.id = gmail_id;
1265 string16 two_menu_items[] = {title1, title2};
1266 EXPECT_TRUE(CheckMenuCreation(
1267 launcher_controller_.get(), item_gmail, 2, two_menu_items, false));
1268
1269 int tabs = browser()->tab_strip_model()->count();
1270 // Activate the proper tab through the menu item.
1271 {
1272 ChromeLauncherAppMenuItems items =
1273 launcher_controller_->GetApplicationList(item_gmail, 0);
1274 items[1]->Execute(0);
1275 EXPECT_EQ(tabs, browser()->tab_strip_model()->count());
1276 }
1277
1278 // Delete one tab through the menu item.
1279 {
1280 ChromeLauncherAppMenuItems items =
1281 launcher_controller_->GetApplicationList(item_gmail, 0);
1282 items[1]->Execute(ui::EF_SHIFT_DOWN);
1283 EXPECT_EQ(--tabs, browser()->tab_strip_model()->count());
1284 }
1285 }
1286
1287 // Tests that panels create launcher items correctly
1288 TEST_F(ChromeLauncherControllerPerAppTest, AppPanels) {
1289 InitLauncherControllerWithBrowser();
1290 EXPECT_EQ(1, model_observer_->added());
1291
1292 TestAppIconLoaderImpl* app_icon_loader = new TestAppIconLoaderImpl();
1293 SetAppIconLoader(app_icon_loader);
1294
1295 // Test adding an app panel
1296 std::string app_id = extension1_->id();
1297 ShellWindowLauncherItemController app_panel_controller(
1298 LauncherItemController::TYPE_APP_PANEL, "id", app_id,
1299 launcher_controller_.get());
1300 ash::LauncherID launcher_id1 = launcher_controller_->CreateAppLauncherItem(
1301 &app_panel_controller, app_id, ash::STATUS_RUNNING);
1302 int panel_index = model_observer_->last_index();
1303 EXPECT_EQ(2, model_observer_->added());
1304 EXPECT_EQ(0, model_observer_->changed());
1305 EXPECT_EQ(1, app_icon_loader->fetch_count());
1306 model_observer_->clear_counts();
1307
1308 // App panels should have a separate identifier than the app id
1309 EXPECT_EQ(0, launcher_controller_->GetLauncherIDForAppID(app_id));
1310
1311 // Setting the app image image should not change the panel if it set its icon
1312 app_panel_controller.set_image_set_by_controller(true);
1313 gfx::ImageSkia image;
1314 launcher_controller_->SetAppImage(app_id, image);
1315 EXPECT_EQ(0, model_observer_->changed());
1316 model_observer_->clear_counts();
1317
1318 // Add a second app panel and verify that it get the same index as the first
1319 // one had, being added to the left of the existing panel.
1320 ash::LauncherID launcher_id2 = launcher_controller_->CreateAppLauncherItem(
1321 &app_panel_controller, app_id, ash::STATUS_RUNNING);
1322 EXPECT_EQ(panel_index, model_observer_->last_index());
1323 EXPECT_EQ(1, model_observer_->added());
1324 model_observer_->clear_counts();
1325
1326 launcher_controller_->CloseLauncherItem(launcher_id2);
1327 launcher_controller_->CloseLauncherItem(launcher_id1);
1328 EXPECT_EQ(2, model_observer_->removed());
1329 }
1330
1331 // Tests that the Gmail extension matches more then the app itself claims with
1332 // the manifest file.
1333 TEST_F(ChromeLauncherControllerPerAppTest, GmailMatching) {
1334 InitLauncherControllerWithBrowser();
1335
1336 // Create a Gmail browser tab.
1337 chrome::NewTab(browser());
1338 string16 title = ASCIIToUTF16("Test");
1339 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title);
1340 content::WebContents* content =
1341 browser()->tab_strip_model()->GetActiveWebContents();
1342
1343 // Check that the launcher controller does not recognize the running app.
1344 EXPECT_FALSE(launcher_controller_->ContentCanBeHandledByGmailApp(content));
1345
1346 // Installing |extension3_| adds it to the launcher.
1347 ash::LauncherID gmail_id = model_->next_id();
1348 extension_service_->AddExtension(extension3_.get());
1349 EXPECT_EQ(3, model_->item_count());
1350 int gmail_index = model_->ItemIndexByID(gmail_id);
1351 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[gmail_index].type);
1352 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
1353
1354 // Check that it is now handled.
1355 EXPECT_TRUE(launcher_controller_->ContentCanBeHandledByGmailApp(content));
1356
1357 // Check also that the app has detected that properly.
1358 ash::LauncherItem item_gmail;
1359 item_gmail.type = ash::TYPE_APP_SHORTCUT;
1360 item_gmail.id = gmail_id;
1361 EXPECT_EQ(2U, launcher_controller_->GetApplicationList(item_gmail, 0).size());
1362 }
1363
1364 // Tests that the Gmail extension does not match the offline verison.
1365 TEST_F(ChromeLauncherControllerPerAppTest, GmailOfflineMatching) {
1366 InitLauncherControllerWithBrowser();
1367
1368 // Create a Gmail browser tab.
1369 chrome::NewTab(browser());
1370 string16 title = ASCIIToUTF16("Test");
1371 NavigateAndCommitActiveTabWithTitle(browser(),
1372 GURL(offline_gmail_url),
1373 title);
1374 content::WebContents* content =
1375 browser()->tab_strip_model()->GetActiveWebContents();
1376
1377 // Installing |extension3_| adds it to the launcher.
1378 ash::LauncherID gmail_id = model_->next_id();
1379 extension_service_->AddExtension(extension3_.get());
1380 EXPECT_EQ(3, model_->item_count());
1381 int gmail_index = model_->ItemIndexByID(gmail_id);
1382 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[gmail_index].type);
1383 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
1384
1385 // The content should not be able to be handled by the app.
1386 EXPECT_FALSE(launcher_controller_->ContentCanBeHandledByGmailApp(content));
1387 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698