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

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

Issue 2052013002: Adding ChromeLauncherController interface. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@chrome_launcher_smaller_api
Patch Set: Rebase Created 4 years, 6 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 2013 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.h"
6
7 #include <stddef.h>
8
9 #include <algorithm>
10 #include <memory>
11 #include <set>
12 #include <string>
13 #include <utility>
14 #include <vector>
15
16 #include "ash/ash_switches.h"
17 #include "ash/common/shelf/shelf_item_delegate_manager.h"
18 #include "ash/common/shelf/shelf_model.h"
19 #include "ash/common/shelf/shelf_model_observer.h"
20 #include "ash/shell.h"
21 #include "ash/test/shelf_item_delegate_manager_test_api.h"
22 #include "ash/test/test_session_state_delegate.h"
23 #include "ash/test/test_shell_delegate.h"
24 #include "base/command_line.h"
25 #include "base/compiler_specific.h"
26 #include "base/files/file_path.h"
27 #include "base/location.h"
28 #include "base/macros.h"
29 #include "base/memory/ptr_util.h"
30 #include "base/message_loop/message_loop.h"
31 #include "base/single_thread_task_runner.h"
32 #include "base/strings/utf_string_conversions.h"
33 #include "base/threading/thread_task_runner_handle.h"
34 #include "base/values.h"
35 #include "build/build_config.h"
36 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
37 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
38 #include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h"
39 #include "chrome/browser/extensions/extension_service.h"
40 #include "chrome/browser/extensions/test_extension_system.h"
41 #include "chrome/browser/lifetime/scoped_keep_alive.h"
42 #include "chrome/browser/ui/app_list/arc/arc_app_list_prefs.h"
43 #include "chrome/browser/ui/app_list/arc/arc_app_test.h"
44 #include "chrome/browser/ui/app_list/arc/arc_app_utils.h"
45 #include "chrome/browser/ui/apps/chrome_app_delegate.h"
46 #include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
47 #include "chrome/browser/ui/ash/launcher/app_window_launcher_controller.h"
48 #include "chrome/browser/ui/ash/launcher/browser_status_monitor.h"
49 #include "chrome/browser/ui/ash/launcher/extension_app_window_launcher_item_cont roller.h"
50 #include "chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h"
51 #include "chrome/browser/ui/ash/launcher/launcher_controller_helper.h"
52 #include "chrome/browser/ui/ash/launcher/launcher_item_controller.h"
53 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
54 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
55 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h"
56 #include "chrome/browser/ui/browser.h"
57 #include "chrome/browser/ui/browser_commands.h"
58 #include "chrome/browser/ui/browser_finder.h"
59 #include "chrome/browser/ui/browser_list.h"
60 #include "chrome/browser/ui/browser_tabstrip.h"
61 #include "chrome/browser/ui/tabs/tab_strip_model.h"
62 #include "chrome/common/chrome_constants.h"
63 #include "chrome/common/chrome_switches.h"
64 #include "chrome/common/extensions/extension_constants.h"
65 #include "chrome/common/pref_names.h"
66 #include "chrome/test/base/browser_with_test_window_test.h"
67 #include "chrome/test/base/test_browser_window_aura.h"
68 #include "chrome/test/base/testing_browser_process.h"
69 #include "chrome/test/base/testing_profile.h"
70 #include "chrome/test/base/testing_profile_manager.h"
71 #include "chromeos/chromeos_switches.h"
72 #include "components/arc/common/app.mojom.h"
73 #include "components/arc/test/fake_app_instance.h"
74 #include "components/arc/test/fake_arc_bridge_service.h"
75 #include "components/exo/shell_surface.h"
76 #include "components/signin/core/account_id/account_id.h"
77 #include "components/syncable_prefs/testing_pref_service_syncable.h"
78 #include "components/user_manager/fake_user_manager.h"
79 #include "content/public/browser/web_contents.h"
80 #include "content/public/browser/web_contents_observer.h"
81 #include "content/public/test/test_utils.h"
82 #include "content/public/test/web_contents_tester.h"
83 #include "extensions/browser/app_window/app_window_contents.h"
84 #include "extensions/browser/app_window/app_window_registry.h"
85 #include "extensions/browser/app_window/native_app_window.h"
86 #include "extensions/common/extension.h"
87 #include "extensions/common/manifest_constants.h"
88 #include "testing/gtest/include/gtest/gtest.h"
89 #include "ui/aura/client/window_tree_client.h"
90 #include "ui/aura/window.h"
91 #include "ui/base/models/menu_model.h"
92 #include "ui/views/widget/widget.h"
93
94 using base::ASCIIToUTF16;
95 using extensions::Extension;
96 using extensions::Manifest;
97 using extensions::UnloadedExtensionInfo;
98
99 namespace {
100 const char* offline_gmail_url = "https://mail.google.com/mail/mu/u";
101 const char* gmail_url = "https://mail.google.com/mail/u";
102 const char* kGmailLaunchURL = "https://mail.google.com/mail/ca";
103
104 // An extension prefix.
105 const char kCrxAppPrefix[] = "_crx_";
106
107 // ShelfModelObserver implementation that tracks what messages are invoked.
108 class TestShelfModelObserver : public ash::ShelfModelObserver {
109 public:
110 TestShelfModelObserver()
111 : added_(0),
112 removed_(0),
113 changed_(0) {
114 }
115
116 ~TestShelfModelObserver() override {}
117
118 // Overridden from ash::ShelfModelObserver:
119 void ShelfItemAdded(int index) override {
120 ++added_;
121 last_index_ = index;
122 }
123
124 void ShelfItemRemoved(int index, ash::ShelfID id) override {
125 ++removed_;
126 last_index_ = index;
127 }
128
129 void ShelfItemChanged(int index, const ash::ShelfItem& old_item) override {
130 ++changed_;
131 last_index_ = index;
132 }
133
134 void ShelfItemMoved(int start_index, int target_index) override {
135 last_index_ = target_index;
136 }
137
138 void clear_counts() {
139 added_ = 0;
140 removed_ = 0;
141 changed_ = 0;
142 last_index_ = 0;
143 }
144
145 int added() const { return added_; }
146 int removed() const { return removed_; }
147 int changed() const { return changed_; }
148 int last_index() const { return last_index_; }
149
150 private:
151 int added_;
152 int removed_;
153 int changed_;
154 int last_index_;
155
156 DISALLOW_COPY_AND_ASSIGN(TestShelfModelObserver);
157 };
158
159 // Test implementation of AppIconLoader.
160 class TestAppIconLoaderImpl : public AppIconLoader {
161 public:
162 TestAppIconLoaderImpl() = default;
163 ~TestAppIconLoaderImpl() override = default;
164
165 void AddSupportedApp(const std::string& id) { supported_apps_.insert(id); }
166
167 // AppIconLoader implementation:
168 bool CanLoadImageForApp(const std::string& id) override {
169 return supported_apps_.find(id) != supported_apps_.end();
170 }
171
172 void FetchImage(const std::string& id) override { ++fetch_count_; }
173
174 void ClearImage(const std::string& id) override { ++clear_count_; }
175
176 void UpdateImage(const std::string& id) override {}
177
178 int fetch_count() const { return fetch_count_; }
179 int clear_count() const { return clear_count_; }
180
181 private:
182 int fetch_count_ = 0;
183 int clear_count_ = 0;
184 std::set<std::string> supported_apps_;
185
186 DISALLOW_COPY_AND_ASSIGN(TestAppIconLoaderImpl);
187 };
188
189 // Test implementation of LauncherControllerHelper.
190 class TestLauncherControllerHelper : public LauncherControllerHelper {
191 public:
192 TestLauncherControllerHelper() : LauncherControllerHelper(nullptr) {}
193 ~TestLauncherControllerHelper() override {}
194
195 // Sets the id for the specified tab.
196 void SetAppID(content::WebContents* tab, const std::string& id) {
197 tab_id_map_[tab] = id;
198 }
199
200 // Returns true if there is an id registered for |tab|.
201 bool HasAppID(content::WebContents* tab) const {
202 return tab_id_map_.find(tab) != tab_id_map_.end();
203 }
204
205 // LauncherControllerHelper:
206 std::string GetAppID(content::WebContents* tab) override {
207 return tab_id_map_.find(tab) != tab_id_map_.end() ? tab_id_map_[tab] :
208 std::string();
209 }
210
211 bool IsValidIDForCurrentUser(const std::string& id) const override {
212 for (TabToStringMap::const_iterator i = tab_id_map_.begin();
213 i != tab_id_map_.end(); ++i) {
214 if (i->second == id)
215 return true;
216 }
217 return false;
218 }
219
220 void SetCurrentUser(Profile* profile) override {
221 // We can ignore this for now.
222 }
223
224 ArcAppListPrefs* GetArcAppListPrefs() const override { return nullptr; }
225
226 private:
227 typedef std::map<content::WebContents*, std::string> TabToStringMap;
228
229 TabToStringMap tab_id_map_;
230
231 DISALLOW_COPY_AND_ASSIGN(TestLauncherControllerHelper);
232 };
233
234 // Test implementation of a V2 app launcher item controller.
235 class TestV2AppLauncherItemController : public LauncherItemController {
236 public:
237 TestV2AppLauncherItemController(const std::string& app_id,
238 ChromeLauncherController* controller)
239 : LauncherItemController(LauncherItemController::TYPE_APP,
240 app_id,
241 controller) {
242 }
243
244 ~TestV2AppLauncherItemController() override {}
245
246 // Override for LauncherItemController:
247 bool IsOpen() const override { return true; }
248 bool IsVisible() const override { return true; }
249 void Launch(ash::LaunchSource source, int event_flags) override {}
250 ash::ShelfItemDelegate::PerformedAction Activate(
251 ash::LaunchSource source) override {
252 return kExistingWindowActivated;
253 }
254 void Close() override {}
255 ash::ShelfItemDelegate::PerformedAction ItemSelected(
256 const ui::Event& event) override {
257 return kExistingWindowActivated;
258 }
259 base::string16 GetTitle() override { return base::string16(); }
260 ChromeLauncherAppMenuItems GetApplicationList(int event_flags) override {
261 ChromeLauncherAppMenuItems items;
262 items.push_back(
263 new ChromeLauncherAppMenuItem(base::string16(), NULL, false));
264 items.push_back(
265 new ChromeLauncherAppMenuItem(base::string16(), NULL, false));
266 return items;
267 }
268 ash::ShelfMenuModel* CreateApplicationMenu(int event_flags) override {
269 return NULL;
270 }
271 bool IsDraggable() override { return false; }
272 bool CanPin() const override {
273 return launcher_controller()->GetPinnable(app_id()) ==
274 AppListControllerDelegate::PIN_EDITABLE;
275 }
276 bool ShouldShowTooltip() override { return false; }
277
278 private:
279 DISALLOW_COPY_AND_ASSIGN(TestV2AppLauncherItemController);
280 };
281
282 } // namespace
283
284 class ChromeLauncherControllerTest : public BrowserWithTestWindowTest {
285 protected:
286 ChromeLauncherControllerTest()
287 : BrowserWithTestWindowTest(Browser::TYPE_TABBED, false),
288 test_controller_(NULL),
289 extension_service_(NULL) {}
290
291 ~ChromeLauncherControllerTest() override {}
292
293 void SetUp() override {
294 BrowserWithTestWindowTest::SetUp();
295
296 model_.reset(new ash::ShelfModel);
297 model_observer_.reset(new TestShelfModelObserver);
298 model_->AddObserver(model_observer_.get());
299
300 if (ash::Shell::HasInstance()) {
301 item_delegate_manager_ =
302 ash::Shell::GetInstance()->shelf_item_delegate_manager();
303 } else {
304 item_delegate_manager_ =
305 new ash::ShelfItemDelegateManager(model_.get());
306 }
307
308 base::DictionaryValue manifest;
309 manifest.SetString(extensions::manifest_keys::kName,
310 "launcher controller test extension");
311 manifest.SetString(extensions::manifest_keys::kVersion, "1");
312 manifest.SetString(extensions::manifest_keys::kDescription,
313 "for testing pinned apps");
314
315 extensions::TestExtensionSystem* extension_system(
316 static_cast<extensions::TestExtensionSystem*>(
317 extensions::ExtensionSystem::Get(profile())));
318 extension_service_ = extension_system->CreateExtensionService(
319 base::CommandLine::ForCurrentProcess(), base::FilePath(), false);
320
321 std::string error;
322 extension1_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
323 manifest,
324 Extension::NO_FLAGS,
325 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
326 &error);
327 extension2_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
328 manifest,
329 Extension::NO_FLAGS,
330 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
331 &error);
332 // Fake gmail extension.
333 base::DictionaryValue manifest_gmail;
334 manifest_gmail.SetString(extensions::manifest_keys::kName,
335 "Gmail launcher controller test extension");
336 manifest_gmail.SetString(extensions::manifest_keys::kVersion, "1");
337 manifest_gmail.SetString(extensions::manifest_keys::kDescription,
338 "for testing pinned Gmail");
339 manifest_gmail.SetString(extensions::manifest_keys::kLaunchWebURL,
340 kGmailLaunchURL);
341 base::ListValue* list = new base::ListValue();
342 list->Append(new base::StringValue("*://mail.google.com/mail/ca"));
343 manifest_gmail.Set(extensions::manifest_keys::kWebURLs, list);
344
345 extension3_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
346 manifest_gmail,
347 Extension::NO_FLAGS,
348 extension_misc::kGmailAppId,
349 &error);
350
351 // Fake google docs extension.
352 extension4_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
353 manifest,
354 Extension::NO_FLAGS,
355 extension_misc::kGoogleDocAppId,
356 &error);
357 extension5_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
358 manifest,
359 Extension::NO_FLAGS,
360 "cccccccccccccccccccccccccccccccc",
361 &error);
362 extension6_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
363 manifest,
364 Extension::NO_FLAGS,
365 "dddddddddddddddddddddddddddddddd",
366 &error);
367 extension7_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
368 manifest,
369 Extension::NO_FLAGS,
370 "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
371 &error);
372 extension8_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
373 manifest,
374 Extension::NO_FLAGS,
375 "ffffffffffffffffffffffffffffffff",
376 &error);
377 }
378
379 // Creates a running V2 app (not pinned) of type |app_id|.
380 virtual void CreateRunningV2App(const std::string& app_id) {
381 DCHECK(!test_controller_);
382 ash::ShelfID id =
383 launcher_controller_->CreateAppShortcutLauncherItemWithType(
384 app_id,
385 model_->item_count(),
386 ash::TYPE_PLATFORM_APP);
387 DCHECK(id);
388 // Change the created launcher controller into a V2 app controller.
389 test_controller_ = new TestV2AppLauncherItemController(app_id,
390 launcher_controller_.get());
391 launcher_controller_->SetItemController(id, test_controller_);
392 }
393
394 // Sets the stage for a multi user test.
395 virtual void SetUpMultiUserScenario(base::ListValue* user_a,
396 base::ListValue* user_b) {
397 InitLauncherController();
398 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
399
400 // Set an empty pinned pref to begin with.
401 base::ListValue no_user;
402 SetShelfChromeIconIndex(0);
403 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
404 no_user.DeepCopy());
405 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
406
407 // Assume all applications have been added already.
408 extension_service_->AddExtension(extension1_.get());
409 extension_service_->AddExtension(extension2_.get());
410 extension_service_->AddExtension(extension3_.get());
411 extension_service_->AddExtension(extension4_.get());
412 extension_service_->AddExtension(extension5_.get());
413 extension_service_->AddExtension(extension6_.get());
414 extension_service_->AddExtension(extension7_.get());
415 extension_service_->AddExtension(extension8_.get());
416 // There should be nothing in the list by now.
417 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
418
419 // Set user a preferences.
420 InsertPrefValue(user_a, 0, extension1_->id());
421 InsertPrefValue(user_a, 1, extension2_->id());
422 InsertPrefValue(user_a, 2, extension3_->id());
423 InsertPrefValue(user_a, 3, extension4_->id());
424 InsertPrefValue(user_a, 4, extension5_->id());
425 InsertPrefValue(user_a, 5, extension6_->id());
426
427 // Set user b preferences.
428 InsertPrefValue(user_b, 0, extension7_->id());
429 InsertPrefValue(user_b, 1, extension8_->id());
430 }
431
432 void TearDown() override {
433 arc_test_.TearDown();
434 launcher_controller_->SetShelfItemDelegateManagerForTest(nullptr);
435 model_->RemoveObserver(model_observer_.get());
436 model_observer_.reset();
437 launcher_controller_.reset();
438
439 // item_delegate_manager_ must be deleted after launch_controller_,
440 // because launch_controller_ has a map of pointers to the data
441 // hold by item_delegate_manager_.
442 if (!ash::Shell::HasInstance())
443 delete item_delegate_manager_;
444
445 model_.reset();
446
447 BrowserWithTestWindowTest::TearDown();
448 }
449
450 BrowserWindow* CreateBrowserWindow() override {
451 return CreateTestBrowserWindowAura();
452 }
453
454 std::unique_ptr<Browser> CreateBrowserWithTestWindowForProfile(
455 Profile* profile) {
456 TestBrowserWindow* browser_window = CreateTestBrowserWindowAura();
457 new TestBrowserWindowOwner(browser_window);
458 return base::WrapUnique(
459 CreateBrowser(profile, Browser::TYPE_TABBED, false, browser_window));
460 }
461
462 void AddAppListLauncherItem() {
463 ash::ShelfItem app_list;
464 app_list.type = ash::TYPE_APP_LIST;
465 model_->Add(app_list);
466 }
467
468 void InitLauncherController() {
469 AddAppListLauncherItem();
470 launcher_controller_.reset(
471 new ChromeLauncherController(profile(), model_.get()));
472 if (!ash::Shell::HasInstance())
473 SetShelfItemDelegateManager(item_delegate_manager_);
474 launcher_controller_->Init();
475 }
476
477 void InitLauncherControllerWithBrowser() {
478 InitLauncherController();
479 chrome::NewTab(browser());
480 browser()->window()->Show();
481 }
482
483 void SetAppIconLoader(std::unique_ptr<AppIconLoader> loader) {
484 std::vector<std::unique_ptr<AppIconLoader>> loaders;
485 loaders.push_back(std::move(loader));
486 launcher_controller_->SetAppIconLoadersForTest(loaders);
487 }
488
489 void SetAppIconLoaders(std::unique_ptr<AppIconLoader> loader1,
490 std::unique_ptr<AppIconLoader> loader2) {
491 std::vector<std::unique_ptr<AppIconLoader>> loaders;
492 loaders.push_back(std::move(loader1));
493 loaders.push_back(std::move(loader2));
494 launcher_controller_->SetAppIconLoadersForTest(loaders);
495 }
496
497 void SetLauncherControllerHelper(LauncherControllerHelper* helper) {
498 launcher_controller_->SetLauncherControllerHelperForTest(helper);
499 }
500
501 void SetShelfItemDelegateManager(ash::ShelfItemDelegateManager* manager) {
502 launcher_controller_->SetShelfItemDelegateManagerForTest(manager);
503 }
504
505 void InsertPrefValue(base::ListValue* pref_value,
506 int index,
507 const std::string& extension_id) {
508 base::DictionaryValue* entry = new base::DictionaryValue();
509 entry->SetString(ash::kPinnedAppsPrefAppIDPath, extension_id);
510 pref_value->Insert(index, entry);
511 }
512
513 // Gets the currently configured app launchers from the controller.
514 void GetAppLaunchers(ChromeLauncherController* controller,
515 std::vector<std::string>* launchers) {
516 launchers->clear();
517 for (ash::ShelfItems::const_iterator iter(model_->items().begin());
518 iter != model_->items().end(); ++iter) {
519 ChromeLauncherController::IDToItemControllerMap::const_iterator
520 entry(controller->id_to_item_controller_map_.find(iter->id));
521 if (iter->type == ash::TYPE_APP_SHORTCUT &&
522 entry != controller->id_to_item_controller_map_.end()) {
523 launchers->push_back(entry->second->app_id());
524 }
525 }
526 }
527
528 // Get the setup of the currently shown launcher items in one string.
529 // Each pinned element will start with a big letter, each running but not
530 // pinned V1 app will start with a small letter and each running but not
531 // pinned V2 app will start with a '*' + small letter.
532 std::string GetPinnedAppStatus() {
533 std::string result;
534 for (int i = 0; i < model_->item_count(); i++) {
535 if (!result.empty())
536 result.append(", ");
537 switch (model_->items()[i].type) {
538 case ash::TYPE_PLATFORM_APP:
539 result += "*";
540 // FALLTHROUGH
541 case ash::TYPE_WINDOWED_APP: {
542 const std::string& app =
543 launcher_controller_->GetAppIDForShelfID(model_->items()[i].id);
544 if (app == extension1_->id()) {
545 result += "app1";
546 EXPECT_FALSE(
547 launcher_controller_->IsAppPinned(extension1_->id()));
548 } else if (app == extension2_->id()) {
549 result += "app2";
550 EXPECT_FALSE(
551 launcher_controller_->IsAppPinned(extension2_->id()));
552 } else if (app == extension3_->id()) {
553 result += "app3";
554 EXPECT_FALSE(
555 launcher_controller_->IsAppPinned(extension3_->id()));
556 } else if (app == extension4_->id()) {
557 result += "app4";
558 EXPECT_FALSE(
559 launcher_controller_->IsAppPinned(extension4_->id()));
560 } else if (app == extension5_->id()) {
561 result += "app5";
562 EXPECT_FALSE(
563 launcher_controller_->IsAppPinned(extension5_->id()));
564 } else if (app == extension6_->id()) {
565 result += "app6";
566 EXPECT_FALSE(
567 launcher_controller_->IsAppPinned(extension6_->id()));
568 } else if (app == extension7_->id()) {
569 result += "app7";
570 EXPECT_FALSE(
571 launcher_controller_->IsAppPinned(extension7_->id()));
572 } else if (app == extension8_->id()) {
573 result += "app8";
574 EXPECT_FALSE(
575 launcher_controller_->IsAppPinned(extension8_->id()));
576 } else {
577 result += "unknown";
578 }
579 break;
580 }
581 case ash::TYPE_APP_SHORTCUT: {
582 const std::string& app =
583 launcher_controller_->GetAppIDForShelfID(model_->items()[i].id);
584 if (app == extension1_->id()) {
585 result += "App1";
586 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
587 } else if (app == extension2_->id()) {
588 result += "App2";
589 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension2_->id()));
590 } else if (app == extension3_->id()) {
591 result += "App3";
592 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
593 } else if (app == extension4_->id()) {
594 result += "App4";
595 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension4_->id()));
596 } else if (app == extension5_->id()) {
597 result += "App5";
598 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension5_->id()));
599 } else if (app == extension6_->id()) {
600 result += "App6";
601 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension6_->id()));
602 } else if (app == extension7_->id()) {
603 result += "App7";
604 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension7_->id()));
605 } else if (app == extension8_->id()) {
606 result += "App8";
607 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension8_->id()));
608 } else if (app == ArcAppTest::GetAppId(arc_test_.fake_apps()[0])) {
609 result += arc_test_.fake_apps()[0].name;
610 } else {
611 result += "unknown";
612 }
613 break;
614 }
615 case ash::TYPE_BROWSER_SHORTCUT:
616 result += "Chrome";
617 break;
618 case ash::TYPE_APP_LIST:
619 result += "AppList";
620 break;
621 default:
622 result += "Unknown";
623 break;
624 }
625 }
626 return result;
627 }
628
629 // Set the index at which the chrome icon should be.
630 void SetShelfChromeIconIndex(int index) {
631 profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex,
632 index);
633 }
634
635 // Remember the order of unpinned but running applications for the current
636 // user.
637 void RememberUnpinnedRunningApplicationOrder() {
638 launcher_controller_->RememberUnpinnedRunningApplicationOrder();
639 }
640
641 // Restore the order of running but unpinned applications for a given user.
642 void RestoreUnpinnedRunningApplicationOrder(const AccountId& account_id) {
643 launcher_controller_->RestoreUnpinnedRunningApplicationOrder(
644 account_id.GetUserEmail());
645 }
646
647 void SendListOfArcApps() {
648 arc_test_.app_instance()->RefreshAppList();
649 arc_test_.app_instance()->SendRefreshAppList(arc_test_.fake_apps());
650 }
651
652 void UninstallArcApps() {
653 arc_test_.app_instance()->RefreshAppList();
654 arc_test_.app_instance()->SendRefreshAppList(
655 std::vector<arc::mojom::AppInfo>());
656 }
657
658 void EnableArc(bool enable) {
659 enable ? arc_test_.arc_auth_service()->EnableArc()
660 : arc_test_.arc_auth_service()->DisableArc();
661 base::RunLoop().RunUntilIdle();
662 }
663
664 // Creates app window and set optional Arc application id.
665 views::Widget* CreateAppWindow(std::string* window_app_id) {
666 views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW);
667 params.bounds = gfx::Rect(5, 5, 20, 20);
668 views::Widget* widget = new views::Widget();
669 widget->Init(params);
670 widget->Show();
671 widget->Activate();
672 if (window_app_id) {
673 exo::ShellSurface::SetApplicationId(widget->GetNativeWindow(),
674 window_app_id);
675 }
676 return widget;
677 }
678
679 // Needed for extension service & friends to work.
680 scoped_refptr<Extension> extension1_;
681 scoped_refptr<Extension> extension2_;
682 scoped_refptr<Extension> extension3_;
683 scoped_refptr<Extension> extension4_;
684 scoped_refptr<Extension> extension5_;
685 scoped_refptr<Extension> extension6_;
686 scoped_refptr<Extension> extension7_;
687 scoped_refptr<Extension> extension8_;
688
689 ArcAppTest arc_test_;
690 std::unique_ptr<ChromeLauncherController> launcher_controller_;
691 std::unique_ptr<TestShelfModelObserver> model_observer_;
692 std::unique_ptr<ash::ShelfModel> model_;
693
694 // |item_delegate_manager_| owns |test_controller_|.
695 LauncherItemController* test_controller_;
696
697 ExtensionService* extension_service_;
698
699 ash::ShelfItemDelegateManager* item_delegate_manager_;
700
701 private:
702 TestBrowserWindow* CreateTestBrowserWindowAura() {
703 std::unique_ptr<aura::Window> window(new aura::Window(nullptr));
704 window->set_id(0);
705 window->SetType(ui::wm::WINDOW_TYPE_NORMAL);
706 window->Init(ui::LAYER_TEXTURED);
707 aura::client::ParentWindowWithContext(window.get(), GetContext(),
708 gfx::Rect(200, 200));
709
710 return new TestBrowserWindowAura(std::move(window));
711 }
712
713 DISALLOW_COPY_AND_ASSIGN(ChromeLauncherControllerTest);
714 };
715
716 // Watches WebContents and blocks until it is destroyed. This is needed for
717 // the destruction of a V2 application.
718 class WebContentsDestroyedWatcher : public content::WebContentsObserver {
719 public:
720 explicit WebContentsDestroyedWatcher(content::WebContents* web_contents)
721 : content::WebContentsObserver(web_contents),
722 message_loop_runner_(new content::MessageLoopRunner) {
723 EXPECT_TRUE(web_contents != NULL);
724 }
725 ~WebContentsDestroyedWatcher() override {}
726
727 // Waits until the WebContents is destroyed.
728 void Wait() {
729 message_loop_runner_->Run();
730 }
731
732 private:
733 // Overridden WebContentsObserver methods.
734 void WebContentsDestroyed() override { message_loop_runner_->Quit(); }
735
736 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
737
738 DISALLOW_COPY_AND_ASSIGN(WebContentsDestroyedWatcher);
739 };
740
741 // A V1 windowed application.
742 class V1App : public TestBrowserWindow {
743 public:
744 V1App(Profile* profile, const std::string& app_name) {
745 // Create a window.
746 native_window_.reset(new aura::Window(NULL));
747 native_window_->set_id(0);
748 native_window_->SetType(ui::wm::WINDOW_TYPE_POPUP);
749 native_window_->Init(ui::LAYER_TEXTURED);
750 native_window_->Show();
751 aura::client::ParentWindowWithContext(native_window_.get(),
752 ash::Shell::GetPrimaryRootWindow(),
753 gfx::Rect(10, 10, 20, 30));
754 Browser::CreateParams params = Browser::CreateParams::CreateForApp(
755 kCrxAppPrefix + app_name, true /* trusted_source */, gfx::Rect(),
756 profile);
757 params.window = this;
758 browser_.reset(new Browser(params));
759 chrome::AddTabAt(browser_.get(), GURL(), 0, true);
760 }
761
762 ~V1App() override {
763 // close all tabs. Note that we do not need to destroy the browser itself.
764 browser_->tab_strip_model()->CloseAllTabs();
765 }
766
767 Browser* browser() { return browser_.get(); }
768
769 // TestBrowserWindow override:
770 gfx::NativeWindow GetNativeWindow() const override {
771 return native_window_.get();
772 }
773
774 private:
775 // The associated browser with this app.
776 std::unique_ptr<Browser> browser_;
777
778 // The native window we use.
779 std::unique_ptr<aura::Window> native_window_;
780
781 DISALLOW_COPY_AND_ASSIGN(V1App);
782 };
783
784 // A V2 application which gets created with an |extension| and for a |profile|.
785 // Upon destruction it will properly close the application.
786 class V2App {
787 public:
788 V2App(Profile* profile, const extensions::Extension* extension)
789 : creator_web_contents_(
790 content::WebContentsTester::CreateTestWebContents(profile,
791 nullptr)) {
792 window_ = new extensions::AppWindow(profile, new ChromeAppDelegate(true),
793 extension);
794 extensions::AppWindow::CreateParams params =
795 extensions::AppWindow::CreateParams();
796 // Note: normally, the creator RFH is the background page of the
797 // app/extension
798 // calling chrome.app.window.create. For unit testing purposes, just passing
799 // in a random RenderFrameHost is Good Enoughâ„¢.
800 window_->Init(GURL(std::string()),
801 new extensions::AppWindowContentsImpl(window_),
802 creator_web_contents_->GetMainFrame(), params);
803 }
804
805 virtual ~V2App() {
806 WebContentsDestroyedWatcher destroyed_watcher(window_->web_contents());
807 window_->GetBaseWindow()->Close();
808 destroyed_watcher.Wait();
809 }
810
811 extensions::AppWindow* window() { return window_; }
812
813 private:
814 std::unique_ptr<content::WebContents> creator_web_contents_;
815
816 // The app window which represents the application. Note that the window
817 // deletes itself asynchronously after window_->GetBaseWindow()->Close() gets
818 // called.
819 extensions::AppWindow* window_;
820
821 DISALLOW_COPY_AND_ASSIGN(V2App);
822 };
823
824 // The testing framework to test multi profile scenarios.
825 class MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
826 : public ChromeLauncherControllerTest {
827 protected:
828 MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest() {
829 }
830
831 ~MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest() override {}
832
833 // Overwrite the Setup function to enable multi profile and needed objects.
834 void SetUp() override {
835 profile_manager_.reset(
836 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
837
838 ASSERT_TRUE(profile_manager_->SetUp());
839
840 // AvatarMenu and multiple profiles works after user logged in.
841 profile_manager_->SetLoggedIn(true);
842
843 // Initialize the UserManager singleton to a fresh FakeUserManager instance.
844 user_manager_enabler_.reset(new chromeos::ScopedUserManagerEnabler(
845 new chromeos::FakeChromeUserManager));
846
847 // Initialize the WallpaperManager singleton.
848 chromeos::WallpaperManager::Initialize();
849
850 // Initialize the rest.
851 ChromeLauncherControllerTest::SetUp();
852
853 // Get some base objects.
854 session_delegate()->set_logged_in_users(2);
855 shell_delegate_ = static_cast<ash::test::TestShellDelegate*>(
856 ash::Shell::GetInstance()->delegate());
857 shell_delegate_->set_multi_profiles_enabled(true);
858 }
859
860 void TearDown() override {
861 ChromeLauncherControllerTest::TearDown();
862 user_manager_enabler_.reset();
863 for (ProfileToNameMap::iterator it = created_profiles_.begin();
864 it != created_profiles_.end(); ++it)
865 profile_manager_->DeleteTestingProfile(it->second);
866 chromeos::WallpaperManager::Shutdown();
867
868 // A Task is leaked if we don't destroy everything, then run the message
869 // loop.
870 base::ThreadTaskRunnerHandle::Get()->PostTask(
871 FROM_HERE, base::MessageLoop::QuitWhenIdleClosure());
872 base::MessageLoop::current()->Run();
873 }
874
875 // Creates a profile for a given |user_name|. Note that this class will keep
876 // the ownership of the created object.
877 TestingProfile* CreateMultiUserProfile(const std::string& user_name) {
878 const std::string email_string = user_name + "@example.com";
879 const AccountId account_id(AccountId::FromUserEmail(email_string));
880 static_cast<ash::test::TestSessionStateDelegate*>(
881 ash::Shell::GetInstance()->session_state_delegate())
882 ->AddUser(account_id);
883 // Add a user to the fake user manager.
884 session_delegate()->AddUser(account_id);
885 GetFakeUserManager()->AddUser(account_id);
886
887 GetFakeUserManager()->LoginUser(account_id);
888
889 TestingProfile* profile =
890 profile_manager()->CreateTestingProfile(account_id.GetUserEmail());
891 EXPECT_TRUE(profile);
892
893 // Remember the profile name so that we can destroy it upon destruction.
894 created_profiles_[profile] = account_id.GetUserEmail();
895 if (chrome::MultiUserWindowManager::GetInstance())
896 chrome::MultiUserWindowManager::GetInstance()->AddUser(profile);
897 if (launcher_controller_)
898 launcher_controller_->AdditionalUserAddedToSession(profile);
899 return profile;
900 }
901
902 // Switch to another user.
903 void SwitchActiveUser(const AccountId& account_id) {
904 session_delegate()->SwitchActiveUser(account_id);
905 GetFakeUserManager()->SwitchActiveUser(account_id);
906 chrome::MultiUserWindowManagerChromeOS* manager =
907 static_cast<chrome::MultiUserWindowManagerChromeOS*>(
908 chrome::MultiUserWindowManager::GetInstance());
909 manager->SetAnimationSpeedForTest(
910 chrome::MultiUserWindowManagerChromeOS::ANIMATION_SPEED_DISABLED);
911 manager->ActiveUserChanged(account_id);
912 launcher_controller_->browser_status_monitor_for_test()->ActiveUserChanged(
913 account_id.GetUserEmail());
914 launcher_controller_->app_window_controller_for_test()->ActiveUserChanged(
915 account_id.GetUserEmail());
916 }
917
918 // Creates a browser with a |profile| and load a tab with a |title| and |url|.
919 std::unique_ptr<Browser> CreateBrowserAndTabWithProfile(
920 Profile* profile,
921 const std::string& title,
922 const std::string& url) {
923 std::unique_ptr<Browser> browser(
924 CreateBrowserWithTestWindowForProfile(profile));
925 chrome::NewTab(browser.get());
926
927 browser->window()->Show();
928 NavigateAndCommitActiveTabWithTitle(browser.get(), GURL(url),
929 ASCIIToUTF16(title));
930 return browser;
931 }
932
933 // Creates a running V1 application.
934 // Note that with the use of the launcher_controller_helper as done below,
935 // this is only usable with a single v1 application.
936 V1App* CreateRunningV1App(Profile* profile,
937 const std::string& app_name,
938 const std::string& url) {
939 V1App* v1_app = new V1App(profile, app_name);
940 // Create a new launcher controller helper and assign it to the launcher so
941 // that this app gets properly detected.
942 // TODO(skuhne): Create a more intelligent launcher contrller helper that is
943 // able to detect all running apps properly.
944 TestLauncherControllerHelper* helper = new TestLauncherControllerHelper;
945 helper->SetAppID(v1_app->browser()->tab_strip_model()->GetWebContentsAt(0),
946 app_name);
947 SetLauncherControllerHelper(helper);
948
949 NavigateAndCommitActiveTabWithTitle(
950 v1_app->browser(), GURL(url), ASCIIToUTF16(""));
951 return v1_app;
952 }
953
954 ash::test::TestSessionStateDelegate* session_delegate() {
955 return static_cast<ash::test::TestSessionStateDelegate*>(
956 ash::Shell::GetInstance()->session_state_delegate());
957 }
958 ash::test::TestShellDelegate* shell_delegate() { return shell_delegate_; }
959
960 // Override BrowserWithTestWindowTest:
961 TestingProfile* CreateProfile() override {
962 return CreateMultiUserProfile("user1");
963 }
964 void DestroyProfile(TestingProfile* profile) override {
965 // Delete the profile through our profile manager.
966 ProfileToNameMap::iterator it = created_profiles_.find(profile);
967 DCHECK(it != created_profiles_.end());
968 profile_manager_->DeleteTestingProfile(it->second);
969 created_profiles_.erase(it);
970 }
971
972 private:
973 typedef std::map<Profile*, std::string> ProfileToNameMap;
974 TestingProfileManager* profile_manager() { return profile_manager_.get(); }
975
976 chromeos::FakeChromeUserManager* GetFakeUserManager() {
977 return static_cast<chromeos::FakeChromeUserManager*>(
978 user_manager::UserManager::Get());
979 }
980
981 std::unique_ptr<TestingProfileManager> profile_manager_;
982 std::unique_ptr<chromeos::ScopedUserManagerEnabler> user_manager_enabler_;
983
984 ash::test::TestShellDelegate* shell_delegate_;
985
986 ProfileToNameMap created_profiles_;
987
988 DISALLOW_COPY_AND_ASSIGN(
989 MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest);
990 };
991
992 TEST_F(ChromeLauncherControllerTest, DefaultApps) {
993 InitLauncherController();
994 // Model should only contain the browser shortcut and app list items.
995 EXPECT_EQ(2, model_->item_count());
996 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
997 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
998 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
999
1000 // Installing |extension3_| should add it to the launcher - behind the
1001 // chrome icon.
1002 extension_service_->AddExtension(extension3_.get());
1003 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
1004 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1005 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1006 }
1007
1008 /*
1009 * Test ChromeLauncherController correctly merges policy pinned apps
1010 * and user pinned apps
1011 */
1012 TEST_F(ChromeLauncherControllerTest, MergePolicyAndUserPrefPinnedApps) {
1013 InitLauncherController();
1014
1015 base::ListValue user_pref_value;
1016 extension_service_->AddExtension(extension1_.get());
1017 extension_service_->AddExtension(extension3_.get());
1018 extension_service_->AddExtension(extension4_.get());
1019 extension_service_->AddExtension(extension5_.get());
1020 // extension 1, 3 are pinned by user
1021 InsertPrefValue(&user_pref_value, 0, extension1_->id());
1022 InsertPrefValue(&user_pref_value, 1, extension3_->id());
1023 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1024 user_pref_value.DeepCopy());
1025
1026 base::ListValue policy_value;
1027 // extension 2 4 are pinned by policy
1028 InsertPrefValue(&policy_value, 0, extension2_->id());
1029 InsertPrefValue(&policy_value, 1, extension4_->id());
1030 profile()->GetTestingPrefService()->SetManagedPref(
1031 prefs::kPolicyPinnedLauncherApps, policy_value.DeepCopy());
1032
1033 SetShelfChromeIconIndex(1);
1034
1035 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1036 // 2 is not pinned as it's not installed
1037 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1038 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
1039 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension4_->id()));
1040 // install extension 2 and check
1041 extension_service_->AddExtension(extension2_.get());
1042 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension2_->id()));
1043
1044 // Check user can manually pin or unpin these apps
1045 EXPECT_EQ(AppListControllerDelegate::PIN_EDITABLE,
1046 launcher_controller_->GetPinnable(extension1_->id()));
1047 EXPECT_EQ(AppListControllerDelegate::PIN_FIXED,
1048 launcher_controller_->GetPinnable(extension2_->id()));
1049 EXPECT_EQ(AppListControllerDelegate::PIN_EDITABLE,
1050 launcher_controller_->GetPinnable(extension3_->id()));
1051 EXPECT_EQ(AppListControllerDelegate::PIN_FIXED,
1052 launcher_controller_->GetPinnable(extension4_->id()));
1053
1054 // Check the order of shelf pinned apps
1055 EXPECT_EQ("AppList, App2, App4, App1, Chrome, App3", GetPinnedAppStatus());
1056 }
1057
1058 // Check that the restauration of launcher items is happening in the same order
1059 // as the user has pinned them (on another system) when they are synced reverse
1060 // order.
1061 TEST_F(ChromeLauncherControllerTest, RestoreDefaultAppsReverseOrder) {
1062 InitLauncherController();
1063
1064 base::ListValue policy_value;
1065 InsertPrefValue(&policy_value, 0, extension1_->id());
1066 InsertPrefValue(&policy_value, 1, extension2_->id());
1067 InsertPrefValue(&policy_value, 2, extension3_->id());
1068 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1069 policy_value.DeepCopy());
1070 SetShelfChromeIconIndex(0);
1071 // Model should only contain the browser shortcut and app list items.
1072 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1073 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1074 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1075 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
1076
1077 // Installing |extension3_| should add it to the shelf - behind the
1078 // chrome icon.
1079 ash::ShelfItem item;
1080 extension_service_->AddExtension(extension3_.get());
1081 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1082 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1083 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
1084
1085 // Installing |extension2_| should add it to the launcher - behind the
1086 // chrome icon, but in first location.
1087 extension_service_->AddExtension(extension2_.get());
1088 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1089 EXPECT_EQ("AppList, Chrome, App2, App3", GetPinnedAppStatus());
1090
1091 // Installing |extension1_| should add it to the launcher - behind the
1092 // chrome icon, but in first location.
1093 extension_service_->AddExtension(extension1_.get());
1094 EXPECT_EQ("AppList, Chrome, App1, App2, App3", GetPinnedAppStatus());
1095 }
1096
1097 // Check that the restauration of launcher items is happening in the same order
1098 // as the user has pinned them (on another system) when they are synced random
1099 // order.
1100 TEST_F(ChromeLauncherControllerTest, RestoreDefaultAppsRandomOrder) {
1101 InitLauncherController();
1102
1103 base::ListValue policy_value;
1104 InsertPrefValue(&policy_value, 0, extension1_->id());
1105 InsertPrefValue(&policy_value, 1, extension2_->id());
1106 InsertPrefValue(&policy_value, 2, extension3_->id());
1107
1108 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1109 policy_value.DeepCopy());
1110 SetShelfChromeIconIndex(0);
1111 // Model should only contain the browser shortcut and app list items.
1112 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1113 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1114 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1115 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
1116
1117 // Installing |extension2_| should add it to the launcher - behind the
1118 // chrome icon.
1119 extension_service_->AddExtension(extension2_.get());
1120 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1121 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1122 EXPECT_EQ("AppList, Chrome, App2", GetPinnedAppStatus());
1123
1124 // Installing |extension1_| should add it to the launcher - behind the
1125 // chrome icon, but in first location.
1126 extension_service_->AddExtension(extension1_.get());
1127 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1128 EXPECT_EQ("AppList, Chrome, App1, App2", GetPinnedAppStatus());
1129
1130 // Installing |extension3_| should add it to the launcher - behind the
1131 // chrome icon, but in first location.
1132 extension_service_->AddExtension(extension3_.get());
1133 EXPECT_EQ("AppList, Chrome, App1, App2, App3", GetPinnedAppStatus());
1134 }
1135
1136 // Check that the restauration of launcher items is happening in the same order
1137 // as the user has pinned / moved them (on another system) when they are synced
1138 // random order - including the chrome icon.
1139 TEST_F(ChromeLauncherControllerTest, RestoreDefaultAppsRandomOrderChromeMoved) {
1140 InitLauncherController();
1141
1142 base::ListValue policy_value;
1143 InsertPrefValue(&policy_value, 0, extension1_->id());
1144 InsertPrefValue(&policy_value, 1, extension2_->id());
1145 InsertPrefValue(&policy_value, 2, extension3_->id());
1146 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1147 policy_value.DeepCopy());
1148 SetShelfChromeIconIndex(1);
1149 // Model should only contain the browser shortcut and app list items.
1150 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1151 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1152 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1153 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
1154
1155 // Installing |extension2_| should add it to the shelf - behind the
1156 // chrome icon.
1157 ash::ShelfItem item;
1158 extension_service_->AddExtension(extension2_.get());
1159 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1160 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1161 EXPECT_EQ("AppList, Chrome, App2", GetPinnedAppStatus());
1162
1163 // Installing |extension1_| should add it to the launcher - behind the
1164 // chrome icon, but in first location.
1165 extension_service_->AddExtension(extension1_.get());
1166 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1167 EXPECT_EQ("AppList, App1, Chrome, App2", GetPinnedAppStatus());
1168
1169 // Installing |extension3_| should add it to the launcher - behind the
1170 // chrome icon, but in first location.
1171 extension_service_->AddExtension(extension3_.get());
1172 EXPECT_EQ("AppList, App1, Chrome, App2, App3", GetPinnedAppStatus());
1173 }
1174
1175 // Check that syncing to a different state does the correct thing.
1176 TEST_F(ChromeLauncherControllerTest, RestoreDefaultAppsResyncOrder) {
1177 InitLauncherController();
1178 base::ListValue policy_value;
1179 InsertPrefValue(&policy_value, 0, extension1_->id());
1180 InsertPrefValue(&policy_value, 1, extension2_->id());
1181 InsertPrefValue(&policy_value, 2, extension3_->id());
1182 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1183 policy_value.DeepCopy());
1184 // The shelf layout has always one static item at the beginning (App List).
1185 SetShelfChromeIconIndex(0);
1186 extension_service_->AddExtension(extension2_.get());
1187 EXPECT_EQ("AppList, Chrome, App2", GetPinnedAppStatus());
1188 extension_service_->AddExtension(extension1_.get());
1189 EXPECT_EQ("AppList, Chrome, App1, App2", GetPinnedAppStatus());
1190 extension_service_->AddExtension(extension3_.get());
1191 EXPECT_EQ("AppList, Chrome, App1, App2, App3", GetPinnedAppStatus());
1192
1193 // Change the order with increasing chrome position and decreasing position.
1194 base::ListValue policy_value1;
1195 InsertPrefValue(&policy_value1, 0, extension3_->id());
1196 InsertPrefValue(&policy_value1, 1, extension1_->id());
1197 InsertPrefValue(&policy_value1, 2, extension2_->id());
1198 SetShelfChromeIconIndex(3);
1199 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1200 policy_value1.DeepCopy());
1201 EXPECT_EQ("AppList, App3, App1, App2, Chrome", GetPinnedAppStatus());
1202 base::ListValue policy_value2;
1203 InsertPrefValue(&policy_value2, 0, extension2_->id());
1204 InsertPrefValue(&policy_value2, 1, extension3_->id());
1205 InsertPrefValue(&policy_value2, 2, extension1_->id());
1206 SetShelfChromeIconIndex(2);
1207 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1208 policy_value2.DeepCopy());
1209 EXPECT_EQ("AppList, App2, App3, Chrome, App1", GetPinnedAppStatus());
1210
1211 // Check that the chrome icon can also be at the first possible location.
1212 SetShelfChromeIconIndex(0);
1213 base::ListValue policy_value3;
1214 InsertPrefValue(&policy_value3, 0, extension3_->id());
1215 InsertPrefValue(&policy_value3, 1, extension2_->id());
1216 InsertPrefValue(&policy_value3, 2, extension1_->id());
1217 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1218 policy_value3.DeepCopy());
1219 EXPECT_EQ("AppList, Chrome, App3, App2, App1", GetPinnedAppStatus());
1220
1221 // Check that unloading of extensions works as expected.
1222 extension_service_->UnloadExtension(extension1_->id(),
1223 UnloadedExtensionInfo::REASON_UNINSTALL);
1224 EXPECT_EQ("AppList, Chrome, App3, App2", GetPinnedAppStatus());
1225
1226 extension_service_->UnloadExtension(extension2_->id(),
1227 UnloadedExtensionInfo::REASON_UNINSTALL);
1228 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
1229
1230 // Check that an update of an extension does not crash the system.
1231 extension_service_->UnloadExtension(extension3_->id(),
1232 UnloadedExtensionInfo::REASON_UPDATE);
1233 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
1234 }
1235
1236 // Check that simple locking of an application will 'create' a launcher item.
1237 TEST_F(ChromeLauncherControllerTest, CheckLockApps) {
1238 InitLauncherController();
1239 // Model should only contain the browser shortcut and app list items.
1240 EXPECT_EQ(2, model_->item_count());
1241 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1242 EXPECT_FALSE(
1243 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1244 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1245 EXPECT_FALSE(
1246 launcher_controller_->IsWindowedAppInLauncher(extension2_->id()));
1247
1248 launcher_controller_->LockV1AppWithID(extension1_->id());
1249
1250 EXPECT_EQ(3, model_->item_count());
1251 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type);
1252 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1253 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1254 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1255 EXPECT_FALSE(
1256 launcher_controller_->IsWindowedAppInLauncher(extension2_->id()));
1257
1258 launcher_controller_->UnlockV1AppWithID(extension1_->id());
1259
1260 EXPECT_EQ(2, model_->item_count());
1261 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1262 EXPECT_FALSE(
1263 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1264 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1265 EXPECT_FALSE(
1266 launcher_controller_->IsWindowedAppInLauncher(extension2_->id()));
1267 }
1268
1269 // Check that multiple locks of an application will be properly handled.
1270 TEST_F(ChromeLauncherControllerTest, CheckMultiLockApps) {
1271 InitLauncherController();
1272 // Model should only contain the browser shortcut and app list items.
1273 EXPECT_EQ(2, model_->item_count());
1274 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1275 EXPECT_FALSE(
1276 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1277
1278 for (int i = 0; i < 2; i++) {
1279 launcher_controller_->LockV1AppWithID(extension1_->id());
1280
1281 EXPECT_EQ(3, model_->item_count());
1282 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type);
1283 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1284 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(
1285 extension1_->id()));
1286 }
1287
1288 launcher_controller_->UnlockV1AppWithID(extension1_->id());
1289
1290 EXPECT_EQ(3, model_->item_count());
1291 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type);
1292 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1293 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1294
1295 launcher_controller_->UnlockV1AppWithID(extension1_->id());
1296
1297 EXPECT_EQ(2, model_->item_count());
1298 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1299 EXPECT_FALSE(
1300 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1301 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1302 EXPECT_FALSE(
1303 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1304 }
1305
1306 // Check that already pinned items are not effected by locks.
1307 TEST_F(ChromeLauncherControllerTest, CheckAlreadyPinnedLockApps) {
1308 InitLauncherController();
1309 // Model should only contain the browser shortcut and app list items.
1310 EXPECT_EQ(2, model_->item_count());
1311 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1312 EXPECT_FALSE(
1313 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1314
1315 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1316 launcher_controller_->PinAppWithID(extension1_->id());
1317 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1318
1319 EXPECT_EQ(3, model_->item_count());
1320 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1321 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1322 EXPECT_FALSE(
1323 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1324
1325 launcher_controller_->LockV1AppWithID(extension1_->id());
1326
1327 EXPECT_EQ(3, model_->item_count());
1328 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1329 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1330 EXPECT_FALSE(
1331 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1332
1333 launcher_controller_->UnlockV1AppWithID(extension1_->id());
1334
1335 EXPECT_EQ(3, model_->item_count());
1336 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1337 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1338 EXPECT_FALSE(
1339 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1340
1341 launcher_controller_->UnpinAppWithID(extension1_->id());
1342
1343 EXPECT_EQ(2, model_->item_count());
1344 }
1345
1346 // Check that already pinned items which get locked stay after unpinning.
1347 TEST_F(ChromeLauncherControllerTest, CheckPinnedAppsStayAfterUnlock) {
1348 InitLauncherController();
1349 // Model should only contain the browser shortcut and app list items.
1350 EXPECT_EQ(2, model_->item_count());
1351 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1352 EXPECT_FALSE(
1353 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1354
1355 launcher_controller_->PinAppWithID(extension1_->id());
1356
1357 EXPECT_EQ(3, model_->item_count());
1358 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1359 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1360 EXPECT_FALSE(
1361 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1362
1363 launcher_controller_->LockV1AppWithID(extension1_->id());
1364
1365 EXPECT_EQ(3, model_->item_count());
1366 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1367 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1368 EXPECT_FALSE(
1369 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1370
1371 launcher_controller_->UnpinAppWithID(extension1_->id());
1372
1373 EXPECT_EQ(3, model_->item_count());
1374 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type);
1375 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1376 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1377
1378 launcher_controller_->UnlockV1AppWithID(extension1_->id());
1379
1380 EXPECT_EQ(2, model_->item_count());
1381 }
1382
1383 // Check that running applications wich are not pinned get properly restored
1384 // upon user change.
1385 TEST_F(ChromeLauncherControllerTest, CheckRunningAppOrder) {
1386 InitLauncherController();
1387 // Model should only contain the browser shortcut and app list items.
1388 EXPECT_EQ(2, model_->item_count());
1389
1390 // Add a few running applications.
1391 launcher_controller_->LockV1AppWithID(extension1_->id());
1392 launcher_controller_->LockV1AppWithID(extension2_->id());
1393 launcher_controller_->LockV1AppWithID(extension3_->id());
1394 EXPECT_EQ(5, model_->item_count());
1395 // Note that this not only checks the order of applications but also the
1396 // running type.
1397 EXPECT_EQ("AppList, Chrome, app1, app2, app3", GetPinnedAppStatus());
1398
1399 // Remember the current order of applications for the current user.
1400 const AccountId& current_account_id =
1401 multi_user_util::GetAccountIdFromProfile(profile());
1402 RememberUnpinnedRunningApplicationOrder();
1403
1404 // Switch some items and check that restoring a user which was not yet
1405 // remembered changes nothing.
1406 model_->Move(2, 3);
1407 EXPECT_EQ("AppList, Chrome, app2, app1, app3", GetPinnedAppStatus());
1408 const AccountId second_fake_account_id(
1409 AccountId::FromUserEmail("second-fake-user@fake.com"));
1410 RestoreUnpinnedRunningApplicationOrder(second_fake_account_id);
1411 EXPECT_EQ("AppList, Chrome, app2, app1, app3", GetPinnedAppStatus());
1412
1413 // Restoring the stored user should however do the right thing.
1414 RestoreUnpinnedRunningApplicationOrder(current_account_id);
1415 EXPECT_EQ("AppList, Chrome, app1, app2, app3", GetPinnedAppStatus());
1416
1417 // Switch again some items and even delete one - making sure that the missing
1418 // item gets properly handled.
1419 model_->Move(3, 4);
1420 launcher_controller_->UnlockV1AppWithID(extension1_->id());
1421 EXPECT_EQ("AppList, Chrome, app3, app2", GetPinnedAppStatus());
1422 RestoreUnpinnedRunningApplicationOrder(current_account_id);
1423 EXPECT_EQ("AppList, Chrome, app2, app3", GetPinnedAppStatus());
1424
1425 // Check that removing more items does not crash and changes nothing.
1426 launcher_controller_->UnlockV1AppWithID(extension2_->id());
1427 RestoreUnpinnedRunningApplicationOrder(current_account_id);
1428 EXPECT_EQ("AppList, Chrome, app3", GetPinnedAppStatus());
1429 launcher_controller_->UnlockV1AppWithID(extension3_->id());
1430 RestoreUnpinnedRunningApplicationOrder(current_account_id);
1431 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
1432 }
1433
1434 TEST_F(ChromeLauncherControllerTest, ArcDeferredLaunch) {
1435 arc_test_.SetUp(profile());
1436
1437 launcher_controller_.reset(
1438 ChromeLauncherController::CreateInstance(profile(), model_.get()));
1439 launcher_controller_->Init();
1440
1441 const arc::mojom::AppInfo& app1 = arc_test_.fake_apps()[0];
1442 const arc::mojom::AppInfo& app2 = arc_test_.fake_apps()[1];
1443 const arc::mojom::AppInfo& app3 = arc_test_.fake_apps()[2];
1444 const std::string arc_app_id1 = ArcAppTest::GetAppId(app1);
1445 const std::string arc_app_id2 = ArcAppTest::GetAppId(app2);
1446 const std::string arc_app_id3 = ArcAppTest::GetAppId(app3);
1447
1448 SendListOfArcApps();
1449
1450 arc_test_.bridge_service()->SetStopped();
1451
1452 EXPECT_EQ(0, launcher_controller_->GetShelfIDForAppID(arc_app_id1));
1453 EXPECT_EQ(0, launcher_controller_->GetShelfIDForAppID(arc_app_id2));
1454 EXPECT_EQ(0, launcher_controller_->GetShelfIDForAppID(arc_app_id3));
1455
1456 arc::LaunchApp(profile(), arc_app_id1);
1457 arc::LaunchApp(profile(), arc_app_id1);
1458 arc::LaunchApp(profile(), arc_app_id2);
1459 arc::LaunchApp(profile(), arc_app_id3);
1460 arc::LaunchApp(profile(), arc_app_id3);
1461
1462 const ash::ShelfID shelf_id_app_1 =
1463 launcher_controller_->GetShelfIDForAppID(arc_app_id1);
1464 const ash::ShelfID shelf_id_app_2 =
1465 launcher_controller_->GetShelfIDForAppID(arc_app_id2);
1466 const ash::ShelfID shelf_id_app_3 =
1467 launcher_controller_->GetShelfIDForAppID(arc_app_id3);
1468 EXPECT_NE(0, shelf_id_app_1);
1469 EXPECT_NE(0, shelf_id_app_2);
1470 EXPECT_NE(0, shelf_id_app_3);
1471
1472 // We activated arc_app_id1 twice but expect one close for item controller
1473 // stops launching request.
1474 LauncherItemController* item_controller =
1475 launcher_controller_->GetLauncherItemController(shelf_id_app_1);
1476 ASSERT_NE(nullptr, item_controller);
1477 item_controller->Close();
1478 base::RunLoop().RunUntilIdle();
1479
1480 EXPECT_EQ(0, launcher_controller_->GetShelfIDForAppID(arc_app_id1));
1481 EXPECT_EQ(shelf_id_app_2,
1482 launcher_controller_->GetShelfIDForAppID(arc_app_id2));
1483 EXPECT_EQ(shelf_id_app_3,
1484 launcher_controller_->GetShelfIDForAppID(arc_app_id3));
1485
1486 arc_test_.bridge_service()->SetReady();
1487 SendListOfArcApps();
1488
1489 base::RunLoop().RunUntilIdle();
1490
1491 EXPECT_EQ(0, launcher_controller_->GetShelfIDForAppID(arc_app_id1));
1492 EXPECT_EQ(0, launcher_controller_->GetShelfIDForAppID(arc_app_id2));
1493 EXPECT_EQ(0, launcher_controller_->GetShelfIDForAppID(arc_app_id3));
1494
1495 ASSERT_EQ(2U, arc_test_.app_instance()->launch_requests().size());
1496
1497 const arc::FakeAppInstance::Request* request1 =
1498 arc_test_.app_instance()->launch_requests()[0];
1499 const arc::FakeAppInstance::Request* request2 =
1500 arc_test_.app_instance()->launch_requests()[1];
1501
1502 EXPECT_TRUE((request1->IsForApp(app2) && request2->IsForApp(app3)) ||
1503 (request1->IsForApp(app3) && request2->IsForApp(app2)));
1504 }
1505
1506 TEST_F(ChromeLauncherControllerTest, ArcRunningApp) {
1507 arc_test_.SetUp(profile());
1508 InitLauncherController();
1509
1510 const std::string arc_app_id = ArcAppTest::GetAppId(arc_test_.fake_apps()[0]);
1511 SendListOfArcApps();
1512 EXPECT_EQ(0, launcher_controller_->GetShelfIDForAppID(arc_app_id));
1513
1514 // Normal flow, create/destroy tasks.
1515 arc_test_.app_instance()->SendTaskCreated(1, arc_test_.fake_apps()[0]);
1516 EXPECT_NE(0, launcher_controller_->GetShelfIDForAppID(arc_app_id));
1517 arc_test_.app_instance()->SendTaskCreated(2, arc_test_.fake_apps()[0]);
1518 EXPECT_NE(0, launcher_controller_->GetShelfIDForAppID(arc_app_id));
1519 arc_test_.app_instance()->SendTaskDestroyed(1);
1520 EXPECT_NE(0, launcher_controller_->GetShelfIDForAppID(arc_app_id));
1521 arc_test_.app_instance()->SendTaskDestroyed(2);
1522 EXPECT_EQ(0, launcher_controller_->GetShelfIDForAppID(arc_app_id));
1523
1524 // Stopping bridge removes apps.
1525 arc_test_.app_instance()->SendTaskCreated(3, arc_test_.fake_apps()[0]);
1526 EXPECT_NE(0, launcher_controller_->GetShelfIDForAppID(arc_app_id));
1527 arc_test_.bridge_service()->SetStopped();
1528 base::RunLoop().RunUntilIdle();
1529 EXPECT_EQ(0, launcher_controller_->GetShelfIDForAppID(arc_app_id));
1530 }
1531
1532 // Validate that Arc app is pinned correctly and pin is removed automatically
1533 // once app is uninstalled.
1534 TEST_F(ChromeLauncherControllerTest, ArcAppPin) {
1535 arc_test_.SetUp(profile());
1536 InitLauncherController();
1537
1538 const std::string arc_app_id = ArcAppTest::GetAppId(arc_test_.fake_apps()[0]);
1539
1540 SendListOfArcApps();
1541 extension_service_->AddExtension(extension1_.get());
1542 extension_service_->AddExtension(extension2_.get());
1543
1544 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1545 EXPECT_FALSE(launcher_controller_->IsAppPinned(arc_app_id));
1546 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1547
1548 launcher_controller_->PinAppWithID(extension1_->id());
1549 launcher_controller_->PinAppWithID(arc_app_id);
1550 launcher_controller_->PinAppWithID(extension2_->id());
1551
1552 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1553 EXPECT_TRUE(launcher_controller_->IsAppPinned(arc_app_id));
1554 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension2_->id()));
1555
1556 EXPECT_EQ("AppList, Chrome, App1, Fake App 0, App2", GetPinnedAppStatus());
1557 UninstallArcApps();
1558 EXPECT_EQ("AppList, Chrome, App1, App2", GetPinnedAppStatus());
1559 SendListOfArcApps();
1560 EXPECT_EQ("AppList, Chrome, App1, App2", GetPinnedAppStatus());
1561
1562 // Disable/Enable Arc should persist pin state.
1563 launcher_controller_->PinAppWithID(arc_app_id);
1564 EXPECT_EQ("AppList, Chrome, App1, App2, Fake App 0", GetPinnedAppStatus());
1565 arc::ArcAuthService::Get()->Shutdown();
1566 EXPECT_EQ("AppList, Chrome, App1, App2, Fake App 0", GetPinnedAppStatus());
1567 arc::ArcAuthService::Get()->OnPrimaryUserProfilePrepared(profile());
1568 EXPECT_EQ("AppList, Chrome, App1, App2, Fake App 0", GetPinnedAppStatus());
1569
1570 // Opt-Out/Opt-In remove item from the shelf.
1571 EnableArc(false);
1572 EXPECT_EQ("AppList, Chrome, App1, App2", GetPinnedAppStatus());
1573 EnableArc(true);
1574 EXPECT_EQ("AppList, Chrome, App1, App2", GetPinnedAppStatus());
1575 SendListOfArcApps();
1576 EXPECT_EQ("AppList, Chrome, App1, App2", GetPinnedAppStatus());
1577 }
1578
1579 // Check that with multi profile V1 apps are properly added / removed from the
1580 // shelf.
1581 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
1582 V1AppUpdateOnUserSwitch) {
1583 // Create a browser item in the LauncherController.
1584 InitLauncherController();
1585 EXPECT_EQ(2, model_->item_count());
1586 {
1587 // Create a "windowed gmail app".
1588 std::unique_ptr<V1App> v1_app(
1589 CreateRunningV1App(profile(), extension_misc::kGmailAppId, gmail_url));
1590 EXPECT_EQ(3, model_->item_count());
1591
1592 // After switching to a second user the item should be gone.
1593 std::string user2 = "user2";
1594 TestingProfile* profile2 = CreateMultiUserProfile(user2);
1595 const AccountId account_id2(
1596 multi_user_util::GetAccountIdFromProfile(profile2));
1597 const AccountId account_id(
1598 multi_user_util::GetAccountIdFromProfile(profile()));
1599 SwitchActiveUser(account_id2);
1600 EXPECT_EQ(2, model_->item_count());
1601
1602 // After switching back the item should be back.
1603 SwitchActiveUser(account_id);
1604 EXPECT_EQ(3, model_->item_count());
1605 // Note we destroy now the gmail app with the closure end.
1606 }
1607 EXPECT_EQ(2, model_->item_count());
1608 }
1609
1610 // Check edge cases with multi profile V1 apps in the shelf.
1611 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
1612 V1AppUpdateOnUserSwitchEdgecases) {
1613 // Create a browser item in the LauncherController.
1614 InitLauncherController();
1615
1616 // First test: Create an app when the user is not active.
1617 std::string user2 = "user2";
1618 TestingProfile* profile2 = CreateMultiUserProfile(user2);
1619 const AccountId account_id2(
1620 multi_user_util::GetAccountIdFromProfile(profile2));
1621 const AccountId account_id(
1622 multi_user_util::GetAccountIdFromProfile(profile()));
1623 {
1624 // Create a "windowed gmail app".
1625 std::unique_ptr<V1App> v1_app(
1626 CreateRunningV1App(profile2, extension_misc::kGmailAppId, gmail_url));
1627 EXPECT_EQ(2, model_->item_count());
1628
1629 // However - switching to the user should show it.
1630 SwitchActiveUser(account_id2);
1631 EXPECT_EQ(3, model_->item_count());
1632
1633 // Second test: Remove the app when the user is not active and see that it
1634 // works.
1635 SwitchActiveUser(account_id);
1636 EXPECT_EQ(2, model_->item_count());
1637 // Note: the closure ends and the browser will go away.
1638 }
1639 EXPECT_EQ(2, model_->item_count());
1640 SwitchActiveUser(account_id2);
1641 EXPECT_EQ(2, model_->item_count());
1642 SwitchActiveUser(account_id);
1643 EXPECT_EQ(2, model_->item_count());
1644 }
1645
1646 // Check edge case where a visiting V1 app gets closed (crbug.com/321374).
1647 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
1648 V1CloseOnVisitingDesktop) {
1649 // Create a browser item in the LauncherController.
1650 InitLauncherController();
1651
1652 chrome::MultiUserWindowManager* manager =
1653 chrome::MultiUserWindowManager::GetInstance();
1654
1655 // First create an app when the user is active.
1656 std::string user2 = "user2";
1657 TestingProfile* profile2 = CreateMultiUserProfile(user2);
1658 const AccountId account_id(
1659 multi_user_util::GetAccountIdFromProfile(profile()));
1660 const AccountId account_id2(
1661 multi_user_util::GetAccountIdFromProfile(profile2));
1662 {
1663 // Create a "windowed gmail app".
1664 std::unique_ptr<V1App> v1_app(CreateRunningV1App(
1665 profile(), extension_misc::kGmailAppId, kGmailLaunchURL));
1666 EXPECT_EQ(3, model_->item_count());
1667
1668 // Transfer the app to the other screen and switch users.
1669 manager->ShowWindowForUser(v1_app->browser()->window()->GetNativeWindow(),
1670 account_id2);
1671 EXPECT_EQ(3, model_->item_count());
1672 SwitchActiveUser(account_id2);
1673 EXPECT_EQ(2, model_->item_count());
1674 }
1675 // After the app was destroyed, switch back. (which caused already a crash).
1676 SwitchActiveUser(account_id);
1677
1678 // Create the same app again - which was also causing the crash.
1679 EXPECT_EQ(2, model_->item_count());
1680 {
1681 // Create a "windowed gmail app".
1682 std::unique_ptr<V1App> v1_app(CreateRunningV1App(
1683 profile(), extension_misc::kGmailAppId, kGmailLaunchURL));
1684 EXPECT_EQ(3, model_->item_count());
1685 }
1686 SwitchActiveUser(account_id2);
1687 EXPECT_EQ(2, model_->item_count());
1688 }
1689
1690 // Check edge cases with multi profile V1 apps in the shelf.
1691 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
1692 V1AppUpdateOnUserSwitchEdgecases2) {
1693 // Create a browser item in the LauncherController.
1694 InitLauncherController();
1695 SetLauncherControllerHelper(new TestLauncherControllerHelper);
1696
1697 // First test: Create an app when the user is not active.
1698 std::string user2 = "user2";
1699 TestingProfile* profile2 = CreateMultiUserProfile(user2);
1700 const AccountId account_id(
1701 multi_user_util::GetAccountIdFromProfile(profile()));
1702 const AccountId account_id2(
1703 multi_user_util::GetAccountIdFromProfile(profile2));
1704 SwitchActiveUser(account_id2);
1705 {
1706 // Create a "windowed gmail app".
1707 std::unique_ptr<V1App> v1_app(
1708 CreateRunningV1App(profile(), extension_misc::kGmailAppId, gmail_url));
1709 EXPECT_EQ(2, model_->item_count());
1710
1711 // However - switching to the user should show it.
1712 SwitchActiveUser(account_id);
1713 EXPECT_EQ(3, model_->item_count());
1714
1715 // Second test: Remove the app when the user is not active and see that it
1716 // works.
1717 SwitchActiveUser(account_id2);
1718 EXPECT_EQ(2, model_->item_count());
1719 v1_app.reset();
1720 }
1721 EXPECT_EQ(2, model_->item_count());
1722 SwitchActiveUser(account_id);
1723 EXPECT_EQ(2, model_->item_count());
1724 SwitchActiveUser(account_id2);
1725 EXPECT_EQ(2, model_->item_count());
1726 }
1727
1728 // Check that activating an item which is on another user's desktop, will bring
1729 // it back.
1730 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
1731 TestLauncherActivationPullsBackWindow) {
1732 // Create a browser item in the LauncherController.
1733 InitLauncherController();
1734 chrome::MultiUserWindowManager* manager =
1735 chrome::MultiUserWindowManager::GetInstance();
1736
1737 // Create a second test profile. The first is the one in profile() created in
1738 // BrowserWithTestWindowTest::SetUp().
1739 // No need to add the profiles to the MultiUserWindowManager here.
1740 // CreateMultiUserProfile() already does that.
1741 TestingProfile* profile2 = CreateMultiUserProfile("user2");
1742 const AccountId current_user =
1743 multi_user_util::GetAccountIdFromProfile(profile());
1744
1745 // Create a browser window with a native window for the current user.
1746 Browser::CreateParams params(profile());
1747 std::unique_ptr<Browser> browser(
1748 chrome::CreateBrowserWithAuraTestWindowForParams(nullptr, &params));
1749 BrowserWindow* browser_window = browser->window();
1750 aura::Window* window = browser_window->GetNativeWindow();
1751 manager->SetWindowOwner(window, current_user);
1752
1753 // Check that an activation of the window on its owner's desktop does not
1754 // change the visibility to another user.
1755 launcher_controller_->ActivateWindowOrMinimizeIfActive(browser_window, false);
1756 EXPECT_TRUE(manager->IsWindowOnDesktopOfUser(window, current_user));
1757
1758 // Transfer the window to another user's desktop and check that activating it
1759 // does pull it back to that user.
1760 manager->ShowWindowForUser(
1761 window, multi_user_util::GetAccountIdFromProfile(profile2));
1762 EXPECT_FALSE(manager->IsWindowOnDesktopOfUser(window, current_user));
1763 launcher_controller_->ActivateWindowOrMinimizeIfActive(browser_window, false);
1764 EXPECT_TRUE(manager->IsWindowOnDesktopOfUser(window, current_user));
1765 }
1766
1767 // Check that lock -> pin -> unlock -> unpin does properly transition.
1768 TEST_F(ChromeLauncherControllerTest, CheckLockPinUnlockUnpin) {
1769 InitLauncherController();
1770 // Model should only contain the browser shortcut and app list items.
1771 EXPECT_EQ(2, model_->item_count());
1772 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1773 EXPECT_FALSE(
1774 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1775
1776 launcher_controller_->LockV1AppWithID(extension1_->id());
1777
1778 EXPECT_EQ(3, model_->item_count());
1779 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type);
1780 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1781 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1782
1783 launcher_controller_->PinAppWithID(extension1_->id());
1784
1785 EXPECT_EQ(3, model_->item_count());
1786 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1787 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1788 EXPECT_FALSE(
1789 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1790
1791 launcher_controller_->UnlockV1AppWithID(extension1_->id());
1792
1793 EXPECT_EQ(3, model_->item_count());
1794 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1795 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1796 EXPECT_FALSE(
1797 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1798
1799 launcher_controller_->UnpinAppWithID(extension1_->id());
1800
1801 EXPECT_EQ(2, model_->item_count());
1802 }
1803
1804 // Check that a locked (windowed V1 application) will be properly converted
1805 // between locked and pinned when the order gets changed through a profile /
1806 // policy change.
1807 TEST_F(ChromeLauncherControllerTest, RestoreDefaultAndLockedAppsResyncOrder) {
1808 InitLauncherController();
1809 base::ListValue policy_value0;
1810 InsertPrefValue(&policy_value0, 0, extension1_->id());
1811 InsertPrefValue(&policy_value0, 1, extension3_->id());
1812 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1813 policy_value0.DeepCopy());
1814 // The shelf layout has always one static item at the beginning (App List).
1815 SetShelfChromeIconIndex(0);
1816 extension_service_->AddExtension(extension1_.get());
1817 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1818 extension_service_->AddExtension(extension2_.get());
1819 // No new app icon will be generated.
1820 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1821 // Add the app as locked app which will add it (un-pinned).
1822 launcher_controller_->LockV1AppWithID(extension2_->id());
1823 EXPECT_EQ("AppList, Chrome, App1, app2", GetPinnedAppStatus());
1824 extension_service_->AddExtension(extension3_.get());
1825 EXPECT_EQ("AppList, Chrome, App1, App3, app2", GetPinnedAppStatus());
1826
1827 // Now request to pin all items which should convert the locked item into a
1828 // pinned item.
1829 base::ListValue policy_value1;
1830 InsertPrefValue(&policy_value1, 0, extension3_->id());
1831 InsertPrefValue(&policy_value1, 1, extension2_->id());
1832 InsertPrefValue(&policy_value1, 2, extension1_->id());
1833 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1834 policy_value1.DeepCopy());
1835 EXPECT_EQ("AppList, Chrome, App3, App2, App1", GetPinnedAppStatus());
1836
1837 // Going back to a status where there is no requirement for app 2 to be pinned
1838 // should convert it back to locked but not pinned and state. The position
1839 // is determined by the |ShelfModel|'s weight system and since running
1840 // applications are not allowed to be mixed with shortcuts, it should show up
1841 // at the end of the list.
1842 base::ListValue policy_value2;
1843 InsertPrefValue(&policy_value2, 0, extension3_->id());
1844 InsertPrefValue(&policy_value2, 1, extension1_->id());
1845 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1846 policy_value2.DeepCopy());
1847 EXPECT_EQ("AppList, Chrome, App3, App1, app2", GetPinnedAppStatus());
1848
1849 // Removing an item should simply close it and everything should shift.
1850 base::ListValue policy_value3;
1851 InsertPrefValue(&policy_value3, 0, extension3_->id());
1852 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1853 policy_value3.DeepCopy());
1854 EXPECT_EQ("AppList, Chrome, App3, app2", GetPinnedAppStatus());
1855 }
1856
1857 // Check that a running and not pinned V2 application will be properly converted
1858 // between locked and pinned when the order gets changed through a profile /
1859 // policy change.
1860 TEST_F(ChromeLauncherControllerTest,
1861 RestoreDefaultAndRunningV2AppsResyncOrder) {
1862 InitLauncherController();
1863 base::ListValue policy_value0;
1864 InsertPrefValue(&policy_value0, 0, extension1_->id());
1865 InsertPrefValue(&policy_value0, 1, extension3_->id());
1866 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1867 policy_value0.DeepCopy());
1868 // The shelf layout has always one static item at the beginning (app List).
1869 SetShelfChromeIconIndex(0);
1870 extension_service_->AddExtension(extension1_.get());
1871 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1872 extension_service_->AddExtension(extension2_.get());
1873 // No new app icon will be generated.
1874 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1875 // Add the app as an unpinned but running V2 app.
1876 CreateRunningV2App(extension2_->id());
1877 EXPECT_EQ("AppList, Chrome, App1, *app2", GetPinnedAppStatus());
1878 extension_service_->AddExtension(extension3_.get());
1879 EXPECT_EQ("AppList, Chrome, App1, App3, *app2", GetPinnedAppStatus());
1880
1881 // Now request to pin all items which should convert the locked item into a
1882 // pinned item.
1883 base::ListValue policy_value1;
1884 InsertPrefValue(&policy_value1, 0, extension3_->id());
1885 InsertPrefValue(&policy_value1, 1, extension2_->id());
1886 InsertPrefValue(&policy_value1, 2, extension1_->id());
1887 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1888 policy_value1.DeepCopy());
1889 EXPECT_EQ("AppList, Chrome, App3, App2, App1", GetPinnedAppStatus());
1890
1891 // Going back to a status where there is no requirement for app 2 to be pinned
1892 // should convert it back to running V2 app. Since the position is determined
1893 // by the |ShelfModel|'s weight system, it will be after last pinned item.
1894 base::ListValue policy_value2;
1895 InsertPrefValue(&policy_value2, 0, extension3_->id());
1896 InsertPrefValue(&policy_value2, 1, extension1_->id());
1897 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1898 policy_value2.DeepCopy());
1899 EXPECT_EQ("AppList, Chrome, App3, App1, *app2", GetPinnedAppStatus());
1900
1901 // Removing an item should simply close it and everything should shift.
1902 base::ListValue policy_value3;
1903 InsertPrefValue(&policy_value3, 0, extension3_->id());
1904 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1905 policy_value3.DeepCopy());
1906 EXPECT_EQ("AppList, Chrome, App3, *app2", GetPinnedAppStatus());
1907 }
1908
1909 // Each user has a different set of applications pinned. Check that when
1910 // switching between the two users, the state gets properly set.
1911 TEST_F(ChromeLauncherControllerTest, UserSwitchIconRestore) {
1912 base::ListValue user_a;
1913 base::ListValue user_b;
1914 SetUpMultiUserScenario(&user_a, &user_b);
1915 // Show user 1.
1916 SetShelfChromeIconIndex(6);
1917 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1918 user_a.DeepCopy());
1919 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1920 GetPinnedAppStatus());
1921
1922 // Show user 2.
1923 SetShelfChromeIconIndex(4);
1924 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1925 user_b.DeepCopy());
1926
1927 EXPECT_EQ("AppList, App7, App8, Chrome", GetPinnedAppStatus());
1928
1929 // Switch back to 1.
1930 SetShelfChromeIconIndex(8);
1931 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1932 user_a.DeepCopy());
1933 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1934 GetPinnedAppStatus());
1935
1936 // Switch back to 2.
1937 SetShelfChromeIconIndex(4);
1938 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1939 user_b.DeepCopy());
1940 EXPECT_EQ("AppList, App7, App8, Chrome", GetPinnedAppStatus());
1941 }
1942
1943 // Each user has a different set of applications pinned, and one user has an
1944 // application running. Check that when switching between the two users, the
1945 // state gets properly set.
1946 TEST_F(ChromeLauncherControllerTest, UserSwitchIconRestoreWithRunningV2App) {
1947 base::ListValue user_a;
1948 base::ListValue user_b;
1949 SetUpMultiUserScenario(&user_a, &user_b);
1950
1951 // Run App1 and assume that it is a V2 app.
1952 CreateRunningV2App(extension1_->id());
1953
1954 // Show user 1.
1955 SetShelfChromeIconIndex(6);
1956 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1957 user_a.DeepCopy());
1958 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1959 GetPinnedAppStatus());
1960
1961 // Show user 2.
1962 SetShelfChromeIconIndex(4);
1963 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1964 user_b.DeepCopy());
1965
1966 EXPECT_EQ("AppList, App7, App8, Chrome, *app1", GetPinnedAppStatus());
1967
1968 // Switch back to 1.
1969 SetShelfChromeIconIndex(8);
1970 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1971 user_a.DeepCopy());
1972 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1973 GetPinnedAppStatus());
1974
1975 // Switch back to 2.
1976 SetShelfChromeIconIndex(4);
1977 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1978 user_b.DeepCopy());
1979 EXPECT_EQ("AppList, App7, App8, Chrome, *app1", GetPinnedAppStatus());
1980 }
1981
1982 // Each user has a different set of applications pinned, and one user has an
1983 // application running. The chrome icon is not the last item in the list.
1984 // Check that when switching between the two users, the state gets properly set.
1985 // There was once a bug associated with this.
1986 TEST_F(ChromeLauncherControllerTest,
1987 UserSwitchIconRestoreWithRunningV2AppChromeInMiddle) {
1988 base::ListValue user_a;
1989 base::ListValue user_b;
1990 SetUpMultiUserScenario(&user_a, &user_b);
1991
1992 // Run App1 and assume that it is a V2 app.
1993 CreateRunningV2App(extension1_->id());
1994
1995 // Show user 1.
1996 SetShelfChromeIconIndex(5);
1997 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1998 user_a.DeepCopy());
1999 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, Chrome, App6",
2000 GetPinnedAppStatus());
2001
2002 // Show user 2.
2003 SetShelfChromeIconIndex(4);
2004 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
2005 user_b.DeepCopy());
2006
2007 EXPECT_EQ("AppList, App7, App8, Chrome, *app1", GetPinnedAppStatus());
2008
2009 // Switch back to 1.
2010 SetShelfChromeIconIndex(5);
2011 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
2012 user_a.DeepCopy());
2013 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, Chrome, App6",
2014 GetPinnedAppStatus());
2015 }
2016
2017 TEST_F(ChromeLauncherControllerTest, Policy) {
2018 extension_service_->AddExtension(extension1_.get());
2019 extension_service_->AddExtension(extension3_.get());
2020
2021 base::ListValue policy_value;
2022 InsertPrefValue(&policy_value, 0, extension1_->id());
2023 InsertPrefValue(&policy_value, 1, extension2_->id());
2024 profile()->GetTestingPrefService()->SetManagedPref(prefs::kPinnedLauncherApps,
2025 policy_value.DeepCopy());
2026
2027 // Only |extension1_| should get pinned. |extension2_| is specified but not
2028 // installed, and |extension3_| is part of the default set, but that shouldn't
2029 // take effect when the policy override is in place.
2030 InitLauncherController();
2031 EXPECT_EQ(3, model_->item_count());
2032 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
2033 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
2034 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
2035 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
2036
2037 // Installing |extension2_| should add it to the launcher.
2038 extension_service_->AddExtension(extension2_.get());
2039 EXPECT_EQ(4, model_->item_count());
2040 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
2041 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[3].type);
2042 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
2043 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension2_->id()));
2044 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
2045
2046 // Removing |extension1_| from the policy should be reflected in the launcher.
2047 policy_value.Remove(0, NULL);
2048 profile()->GetTestingPrefService()->SetManagedPref(prefs::kPinnedLauncherApps,
2049 policy_value.DeepCopy());
2050 EXPECT_EQ(3, model_->item_count());
2051 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
2052 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
2053 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension2_->id()));
2054 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
2055 }
2056
2057 TEST_F(ChromeLauncherControllerTest, UnpinWithUninstall) {
2058 extension_service_->AddExtension(extension3_.get());
2059 extension_service_->AddExtension(extension4_.get());
2060
2061 InitLauncherController();
2062
2063 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
2064 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension4_->id()));
2065
2066 extension_service_->UnloadExtension(extension3_->id(),
2067 UnloadedExtensionInfo::REASON_UNINSTALL);
2068
2069 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
2070 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension4_->id()));
2071 }
2072
2073 TEST_F(ChromeLauncherControllerTest, PrefUpdates) {
2074 extension_service_->AddExtension(extension2_.get());
2075 extension_service_->AddExtension(extension3_.get());
2076 extension_service_->AddExtension(extension4_.get());
2077
2078 InitLauncherController();
2079
2080 std::vector<std::string> expected_launchers;
2081 std::vector<std::string> actual_launchers;
2082 base::ListValue pref_value;
2083 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
2084 pref_value.DeepCopy());
2085 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
2086 EXPECT_EQ(expected_launchers, actual_launchers);
2087
2088 // Unavailable extensions don't create launcher items.
2089 InsertPrefValue(&pref_value, 0, extension1_->id());
2090 InsertPrefValue(&pref_value, 1, extension2_->id());
2091 InsertPrefValue(&pref_value, 2, extension4_->id());
2092 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
2093 pref_value.DeepCopy());
2094 expected_launchers.push_back(extension2_->id());
2095 expected_launchers.push_back(extension4_->id());
2096 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
2097 EXPECT_EQ(expected_launchers, actual_launchers);
2098
2099 // Redundant pref entries show up only once.
2100 InsertPrefValue(&pref_value, 2, extension3_->id());
2101 InsertPrefValue(&pref_value, 2, extension3_->id());
2102 InsertPrefValue(&pref_value, 5, extension3_->id());
2103 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
2104 pref_value.DeepCopy());
2105 expected_launchers.insert(expected_launchers.begin() + 1, extension3_->id());
2106 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
2107 EXPECT_EQ(expected_launchers, actual_launchers);
2108
2109 // Order changes are reflected correctly.
2110 pref_value.Clear();
2111 InsertPrefValue(&pref_value, 0, extension4_->id());
2112 InsertPrefValue(&pref_value, 1, extension3_->id());
2113 InsertPrefValue(&pref_value, 2, extension2_->id());
2114 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
2115 pref_value.DeepCopy());
2116 std::reverse(expected_launchers.begin(), expected_launchers.end());
2117 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
2118 EXPECT_EQ(expected_launchers, actual_launchers);
2119
2120 // Clearing works.
2121 pref_value.Clear();
2122 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
2123 pref_value.DeepCopy());
2124 expected_launchers.clear();
2125 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
2126 EXPECT_EQ(expected_launchers, actual_launchers);
2127 }
2128
2129 TEST_F(ChromeLauncherControllerTest, PendingInsertionOrder) {
2130 extension_service_->AddExtension(extension1_.get());
2131 extension_service_->AddExtension(extension3_.get());
2132
2133 InitLauncherController();
2134
2135 base::ListValue pref_value;
2136 InsertPrefValue(&pref_value, 0, extension1_->id());
2137 InsertPrefValue(&pref_value, 1, extension2_->id());
2138 InsertPrefValue(&pref_value, 2, extension3_->id());
2139 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
2140 pref_value.DeepCopy());
2141
2142 std::vector<std::string> expected_launchers;
2143 expected_launchers.push_back(extension1_->id());
2144 expected_launchers.push_back(extension3_->id());
2145 std::vector<std::string> actual_launchers;
2146
2147 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
2148 EXPECT_EQ(expected_launchers, actual_launchers);
2149
2150 // Install |extension2| and verify it shows up between the other two.
2151 extension_service_->AddExtension(extension2_.get());
2152 expected_launchers.insert(expected_launchers.begin() + 1, extension2_->id());
2153 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
2154 EXPECT_EQ(expected_launchers, actual_launchers);
2155 }
2156
2157 // Checks the created menus and menu lists for correctness. It uses the given
2158 // |controller| to create the objects for the given |item| and checks the
2159 // found item count against the |expected_items|. The |title| list contains the
2160 // menu titles in the order of their appearance in the menu (not including the
2161 // application name).
2162 bool CheckMenuCreation(ChromeLauncherController* controller,
2163 const ash::ShelfItem& item,
2164 size_t expected_items,
2165 base::string16 title[],
2166 bool is_browser) {
2167 ChromeLauncherAppMenuItems items = controller->GetApplicationList(item, 0);
2168 // A new behavior has been added: Only show menus if there is at least one
2169 // item available.
2170 if (expected_items < 1 && is_browser) {
2171 EXPECT_EQ(0u, items.size());
2172 return items.size() == 0;
2173 }
2174 // There should be one item in there: The title.
2175 EXPECT_EQ(expected_items + 1, items.size());
2176 EXPECT_FALSE(items[0]->IsEnabled());
2177 for (size_t i = 0; i < expected_items; i++) {
2178 EXPECT_EQ(title[i], items[1 + i]->title());
2179 // Check that the first real item has a leading separator.
2180 if (i == 1)
2181 EXPECT_TRUE(items[i]->HasLeadingSeparator());
2182 else
2183 EXPECT_FALSE(items[i]->HasLeadingSeparator());
2184 }
2185
2186 std::unique_ptr<ash::ShelfMenuModel> menu(
2187 new LauncherApplicationMenuItemModel(
2188 controller->GetApplicationList(item, 0)));
2189 // The first element in the menu is a spacing separator. On some systems
2190 // (e.g. Windows) such things do not exist. As such we check the existence
2191 // and adjust dynamically.
2192 int first_item = menu->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR ? 1 : 0;
2193 int expected_menu_items = first_item +
2194 (expected_items ? (expected_items + 3) : 2);
2195 EXPECT_EQ(expected_menu_items, menu->GetItemCount());
2196 EXPECT_FALSE(menu->IsEnabledAt(first_item));
2197 if (expected_items) {
2198 EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR,
2199 menu->GetTypeAt(first_item + 1));
2200 }
2201 return items.size() == expected_items + 1;
2202 }
2203
2204 // Check that browsers get reflected correctly in the launcher menu.
2205 TEST_F(ChromeLauncherControllerTest, BrowserMenuGeneration) {
2206 EXPECT_EQ(1U, chrome::GetTotalBrowserCount());
2207 chrome::NewTab(browser());
2208
2209 InitLauncherController();
2210
2211 // Check that the browser list is empty at this time.
2212 ash::ShelfItem item_browser;
2213 item_browser.type = ash::TYPE_BROWSER_SHORTCUT;
2214 item_browser.id =
2215 launcher_controller_->GetShelfIDForAppID(extension_misc::kChromeAppId);
2216 EXPECT_TRUE(CheckMenuCreation(
2217 launcher_controller_.get(), item_browser, 0, NULL, true));
2218
2219 // Now make the created browser() visible by showing its browser window.
2220 browser()->window()->Show();
2221 base::string16 title1 = ASCIIToUTF16("Test1");
2222 NavigateAndCommitActiveTabWithTitle(browser(), GURL("http://test1"), title1);
2223 base::string16 one_menu_item[] = { title1 };
2224
2225 EXPECT_TRUE(CheckMenuCreation(
2226 launcher_controller_.get(), item_browser, 1, one_menu_item, true));
2227
2228 // Create one more browser/window and check that one more was added.
2229 std::unique_ptr<Browser> browser2(
2230 CreateBrowserWithTestWindowForProfile(profile()));
2231 chrome::NewTab(browser2.get());
2232 browser2->window()->Show();
2233 base::string16 title2 = ASCIIToUTF16("Test2");
2234 NavigateAndCommitActiveTabWithTitle(browser2.get(), GURL("http://test2"),
2235 title2);
2236
2237 // Check that the list contains now two entries - make furthermore sure that
2238 // the active item is the first entry.
2239 base::string16 two_menu_items[] = {title1, title2};
2240 EXPECT_TRUE(CheckMenuCreation(
2241 launcher_controller_.get(), item_browser, 2, two_menu_items, true));
2242
2243 // Apparently we have to close all tabs we have.
2244 chrome::CloseTab(browser2.get());
2245 }
2246
2247 // Check the multi profile case where only user related browsers should show
2248 // up.
2249 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
2250 BrowserMenuGenerationTwoUsers) {
2251 // Create a browser item in the LauncherController.
2252 InitLauncherController();
2253
2254 ash::ShelfItem item_browser;
2255 item_browser.type = ash::TYPE_BROWSER_SHORTCUT;
2256 item_browser.id =
2257 launcher_controller_->GetShelfIDForAppID(extension_misc::kChromeAppId);
2258
2259 // Check that the menu is empty.
2260 chrome::NewTab(browser());
2261 EXPECT_TRUE(CheckMenuCreation(
2262 launcher_controller_.get(), item_browser, 0, NULL, true));
2263
2264 // Show the created |browser()| by showing its window.
2265 browser()->window()->Show();
2266 base::string16 title1 = ASCIIToUTF16("Test1");
2267 NavigateAndCommitActiveTabWithTitle(browser(), GURL("http://test1"), title1);
2268 base::string16 one_menu_item1[] = { title1 };
2269 EXPECT_TRUE(CheckMenuCreation(
2270 launcher_controller_.get(), item_browser, 1, one_menu_item1, true));
2271
2272 // Create a browser for another user and check that it is not included in the
2273 // users running browser list.
2274 std::string user2 = "user2";
2275 TestingProfile* profile2 = CreateMultiUserProfile(user2);
2276 const AccountId account_id2(
2277 multi_user_util::GetAccountIdFromProfile(profile2));
2278 std::unique_ptr<Browser> browser2(
2279 CreateBrowserAndTabWithProfile(profile2, user2, "http://test2"));
2280 base::string16 one_menu_item2[] = { ASCIIToUTF16(user2) };
2281 EXPECT_TRUE(CheckMenuCreation(
2282 launcher_controller_.get(), item_browser, 1, one_menu_item1, true));
2283
2284 // Switch to the other user and make sure that only that browser window gets
2285 // shown.
2286 SwitchActiveUser(account_id2);
2287 EXPECT_TRUE(CheckMenuCreation(
2288 launcher_controller_.get(), item_browser, 1, one_menu_item2, true));
2289
2290 // Transferred browsers of other users should not show up in the list.
2291 chrome::MultiUserWindowManager::GetInstance()->ShowWindowForUser(
2292 browser()->window()->GetNativeWindow(), account_id2);
2293 EXPECT_TRUE(CheckMenuCreation(
2294 launcher_controller_.get(), item_browser, 1, one_menu_item2, true));
2295
2296 chrome::CloseTab(browser2.get());
2297 }
2298
2299 // Check that V1 apps are correctly reflected in the launcher menu using the
2300 // refocus logic.
2301 // Note that the extension matching logic is tested by the extension system
2302 // and does not need a separate test here.
2303 TEST_F(ChromeLauncherControllerTest, V1AppMenuGeneration) {
2304 EXPECT_EQ(1U, chrome::GetTotalBrowserCount());
2305 EXPECT_EQ(0, browser()->tab_strip_model()->count());
2306
2307 InitLauncherControllerWithBrowser();
2308
2309 // Model should only contain the browser shortcut and app list items.
2310 EXPECT_EQ(2, model_->item_count());
2311 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
2312
2313 // Installing |extension3_| adds it to the launcher.
2314 ash::ShelfID gmail_id = model_->next_id();
2315 extension_service_->AddExtension(extension3_.get());
2316 EXPECT_EQ(3, model_->item_count());
2317 int gmail_index = model_->ItemIndexByID(gmail_id);
2318 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[gmail_index].type);
2319 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
2320 launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(gmail_url));
2321
2322 // Check the menu content.
2323 ash::ShelfItem item_browser;
2324 item_browser.type = ash::TYPE_BROWSER_SHORTCUT;
2325 item_browser.id =
2326 launcher_controller_->GetShelfIDForAppID(extension_misc::kChromeAppId);
2327
2328 ash::ShelfItem item_gmail;
2329 item_gmail.type = ash::TYPE_APP_SHORTCUT;
2330 item_gmail.id = gmail_id;
2331 EXPECT_TRUE(CheckMenuCreation(
2332 launcher_controller_.get(), item_gmail, 0, NULL, false));
2333
2334 // Set the gmail URL to a new tab.
2335 base::string16 title1 = ASCIIToUTF16("Test1");
2336 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title1);
2337
2338 base::string16 one_menu_item[] = { title1 };
2339 EXPECT_TRUE(CheckMenuCreation(
2340 launcher_controller_.get(), item_gmail, 1, one_menu_item, false));
2341
2342 // Create one empty tab.
2343 chrome::NewTab(browser());
2344 base::string16 title2 = ASCIIToUTF16("Test2");
2345 NavigateAndCommitActiveTabWithTitle(
2346 browser(),
2347 GURL("https://bla"),
2348 title2);
2349
2350 // and another one with another gmail instance.
2351 chrome::NewTab(browser());
2352 base::string16 title3 = ASCIIToUTF16("Test3");
2353 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title3);
2354 base::string16 two_menu_items[] = {title1, title3};
2355 EXPECT_TRUE(CheckMenuCreation(
2356 launcher_controller_.get(), item_gmail, 2, two_menu_items, false));
2357
2358 // Even though the item is in the V1 app list, it should also be in the
2359 // browser list.
2360 base::string16 browser_menu_item[] = {title3};
2361 EXPECT_TRUE(CheckMenuCreation(
2362 launcher_controller_.get(), item_browser, 1, browser_menu_item, false));
2363
2364 // Test that closing of (all) the item(s) does work (and all menus get
2365 // updated properly).
2366 launcher_controller_->Close(item_gmail.id);
2367
2368 EXPECT_TRUE(CheckMenuCreation(
2369 launcher_controller_.get(), item_gmail, 0, NULL, false));
2370 base::string16 browser_menu_item2[] = { title2 };
2371 EXPECT_TRUE(CheckMenuCreation(
2372 launcher_controller_.get(), item_browser, 1, browser_menu_item2, false));
2373 }
2374
2375 // Check the multi profile case where only user related apps should show up.
2376 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
2377 V1AppMenuGenerationTwoUsers) {
2378 // Create a browser item in the LauncherController.
2379 InitLauncherController();
2380 chrome::NewTab(browser());
2381
2382 // Installing |extension3_| adds it to the launcher.
2383 ash::ShelfID gmail_id = model_->next_id();
2384 extension_service_->AddExtension(extension3_.get());
2385 EXPECT_EQ(3, model_->item_count());
2386 int gmail_index = model_->ItemIndexByID(gmail_id);
2387 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[gmail_index].type);
2388 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
2389 launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(gmail_url));
2390
2391 // Check the menu content.
2392 ash::ShelfItem item_browser;
2393 item_browser.type = ash::TYPE_BROWSER_SHORTCUT;
2394 item_browser.id =
2395 launcher_controller_->GetShelfIDForAppID(extension_misc::kChromeAppId);
2396
2397 ash::ShelfItem item_gmail;
2398 item_gmail.type = ash::TYPE_APP_SHORTCUT;
2399 item_gmail.id = gmail_id;
2400 EXPECT_TRUE(CheckMenuCreation(
2401 launcher_controller_.get(), item_gmail, 0, NULL, false));
2402
2403 // Set the gmail URL to a new tab.
2404 base::string16 title1 = ASCIIToUTF16("Test1");
2405 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title1);
2406
2407 base::string16 one_menu_item[] = { title1 };
2408 EXPECT_TRUE(CheckMenuCreation(
2409 launcher_controller_.get(), item_gmail, 1, one_menu_item, false));
2410
2411 // Create a second profile and switch to that user.
2412 std::string user2 = "user2";
2413 TestingProfile* profile2 = CreateMultiUserProfile(user2);
2414 const AccountId account_id2(
2415 multi_user_util::GetAccountIdFromProfile(profile2));
2416 SwitchActiveUser(account_id2);
2417
2418 // No item should have content yet.
2419 EXPECT_TRUE(CheckMenuCreation(
2420 launcher_controller_.get(), item_browser, 0, NULL, true));
2421 EXPECT_TRUE(CheckMenuCreation(
2422 launcher_controller_.get(), item_gmail, 0, NULL, false));
2423
2424 // Transfer the browser of the first user - it should still not show up.
2425 chrome::MultiUserWindowManager::GetInstance()->ShowWindowForUser(
2426 browser()->window()->GetNativeWindow(), account_id2);
2427
2428 EXPECT_TRUE(CheckMenuCreation(
2429 launcher_controller_.get(), item_browser, 0, NULL, true));
2430 EXPECT_TRUE(CheckMenuCreation(
2431 launcher_controller_.get(), item_gmail, 0, NULL, false));
2432 }
2433
2434 // Check that V2 applications are creating items properly in the launcher when
2435 // instantiated by the current user.
2436 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
2437 V2AppHandlingTwoUsers) {
2438 InitLauncherController();
2439 // Create a profile for our second user (will be destroyed by the framework).
2440 TestingProfile* profile2 = CreateMultiUserProfile("user2");
2441 const AccountId account_id(
2442 multi_user_util::GetAccountIdFromProfile(profile()));
2443 const AccountId account_id2(
2444 multi_user_util::GetAccountIdFromProfile(profile2));
2445 // Check that there is a browser and a app launcher.
2446 EXPECT_EQ(2, model_->item_count());
2447
2448 // Add a v2 app.
2449 V2App v2_app(profile(), extension1_.get());
2450 EXPECT_EQ(3, model_->item_count());
2451
2452 // After switching users the item should go away.
2453 SwitchActiveUser(account_id2);
2454 EXPECT_EQ(2, model_->item_count());
2455
2456 // And it should come back when switching back.
2457 SwitchActiveUser(account_id);
2458 EXPECT_EQ(3, model_->item_count());
2459 }
2460
2461 // Check that V2 applications are creating items properly in edge cases:
2462 // a background user creates a V2 app, gets active and inactive again and then
2463 // deletes the app.
2464 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
2465 V2AppHandlingTwoUsersEdgeCases) {
2466 InitLauncherController();
2467 // Create a profile for our second user (will be destroyed by the framework).
2468 TestingProfile* profile2 = CreateMultiUserProfile("user2");
2469 const AccountId account_id(
2470 multi_user_util::GetAccountIdFromProfile(profile()));
2471 const AccountId account_id2(
2472 multi_user_util::GetAccountIdFromProfile(profile2));
2473 // Check that there is a browser and a app launcher.
2474 EXPECT_EQ(2, model_->item_count());
2475
2476 // Switch to an inactive user.
2477 SwitchActiveUser(account_id2);
2478 EXPECT_EQ(2, model_->item_count());
2479
2480 // Add the v2 app to the inactive user and check that no item was added to
2481 // the launcher.
2482 {
2483 V2App v2_app(profile(), extension1_.get());
2484 EXPECT_EQ(2, model_->item_count());
2485
2486 // Switch to the primary user and check that the item is shown.
2487 SwitchActiveUser(account_id);
2488 EXPECT_EQ(3, model_->item_count());
2489
2490 // Switch to the second user and check that the item goes away - even if the
2491 // item gets closed.
2492 SwitchActiveUser(account_id2);
2493 EXPECT_EQ(2, model_->item_count());
2494 }
2495
2496 // After the application was killed there should be still 2 items.
2497 EXPECT_EQ(2, model_->item_count());
2498
2499 // Switching then back to the default user should not show the additional item
2500 // anymore.
2501 SwitchActiveUser(account_id);
2502 EXPECT_EQ(2, model_->item_count());
2503 }
2504
2505 // Check that V2 applications will be made visible on the target desktop if
2506 // another window of the same type got previously teleported there.
2507 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
2508 V2AppFollowsTeleportedWindow) {
2509 InitLauncherController();
2510 chrome::MultiUserWindowManager* manager =
2511 chrome::MultiUserWindowManager::GetInstance();
2512
2513 // Create and add three users / profiles, and go to #1's desktop.
2514 TestingProfile* profile1 = CreateMultiUserProfile("user-1");
2515 TestingProfile* profile2 = CreateMultiUserProfile("user-2");
2516 TestingProfile* profile3 = CreateMultiUserProfile("user-3");
2517 const AccountId account_id1(
2518 multi_user_util::GetAccountIdFromProfile(profile1));
2519 const AccountId account_id2(
2520 multi_user_util::GetAccountIdFromProfile(profile2));
2521 const AccountId account_id3(
2522 multi_user_util::GetAccountIdFromProfile(profile3));
2523 SwitchActiveUser(account_id1);
2524
2525 // A v2 app for user #1 should be shown first and get hidden when switching to
2526 // desktop #2.
2527 V2App v2_app_1(profile1, extension1_.get());
2528 EXPECT_TRUE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2529 SwitchActiveUser(account_id2);
2530 EXPECT_FALSE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2531
2532 // Add a v2 app for user #1 while on desktop #2 should not be shown.
2533 V2App v2_app_2(profile1, extension1_.get());
2534 EXPECT_FALSE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2535 EXPECT_FALSE(v2_app_2.window()->GetNativeWindow()->IsVisible());
2536
2537 // Teleport the app from user #1 to the desktop #2 should show it.
2538 manager->ShowWindowForUser(v2_app_1.window()->GetNativeWindow(), account_id2);
2539 EXPECT_TRUE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2540 EXPECT_FALSE(v2_app_2.window()->GetNativeWindow()->IsVisible());
2541
2542 // Creating a new application for user #1 on desktop #2 should teleport it
2543 // there automatically.
2544 V2App v2_app_3(profile1, extension1_.get());
2545 EXPECT_TRUE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2546 EXPECT_FALSE(v2_app_2.window()->GetNativeWindow()->IsVisible());
2547 EXPECT_TRUE(v2_app_3.window()->GetNativeWindow()->IsVisible());
2548
2549 // Switching back to desktop#1 and creating an app for user #1 should move
2550 // the app on desktop #1.
2551 SwitchActiveUser(account_id1);
2552 V2App v2_app_4(profile1, extension1_.get());
2553 EXPECT_FALSE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2554 EXPECT_TRUE(v2_app_2.window()->GetNativeWindow()->IsVisible());
2555 EXPECT_FALSE(v2_app_3.window()->GetNativeWindow()->IsVisible());
2556 EXPECT_TRUE(v2_app_4.window()->GetNativeWindow()->IsVisible());
2557
2558 // Switching to desktop #3 and create an app for user #1 there should land on
2559 // his own desktop (#1).
2560 SwitchActiveUser(account_id3);
2561 V2App v2_app_5(profile1, extension1_.get());
2562 EXPECT_FALSE(v2_app_5.window()->GetNativeWindow()->IsVisible());
2563 SwitchActiveUser(account_id1);
2564 EXPECT_TRUE(v2_app_5.window()->GetNativeWindow()->IsVisible());
2565
2566 // Switching to desktop #2, hiding the app window and creating an app should
2567 // teleport there automatically.
2568 SwitchActiveUser(account_id2);
2569 v2_app_1.window()->Hide();
2570 V2App v2_app_6(profile1, extension1_.get());
2571 EXPECT_FALSE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2572 EXPECT_FALSE(v2_app_2.window()->GetNativeWindow()->IsVisible());
2573 EXPECT_TRUE(v2_app_6.window()->GetNativeWindow()->IsVisible());
2574 }
2575
2576 // Check that V2 applications hide correctly on the shelf when the app window
2577 // is hidden.
2578 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
2579 V2AppHiddenWindows) {
2580 InitLauncherController();
2581
2582 TestingProfile* profile2 = CreateMultiUserProfile("user-2");
2583 const AccountId account_id(
2584 multi_user_util::GetAccountIdFromProfile(profile()));
2585 const AccountId account_id2(
2586 multi_user_util::GetAccountIdFromProfile(profile2));
2587 SwitchActiveUser(account_id);
2588 EXPECT_EQ(2, model_->item_count());
2589
2590 V2App v2_app_1(profile(), extension1_.get());
2591 EXPECT_EQ(3, model_->item_count());
2592 {
2593 // Hide and show the app.
2594 v2_app_1.window()->Hide();
2595 EXPECT_EQ(2, model_->item_count());
2596
2597 v2_app_1.window()->Show(extensions::AppWindow::SHOW_ACTIVE);
2598 EXPECT_EQ(3, model_->item_count());
2599 }
2600 {
2601 // Switch user, hide and show the app and switch back.
2602 SwitchActiveUser(account_id2);
2603 EXPECT_EQ(2, model_->item_count());
2604
2605 v2_app_1.window()->Hide();
2606 EXPECT_EQ(2, model_->item_count());
2607
2608 v2_app_1.window()->Show(extensions::AppWindow::SHOW_ACTIVE);
2609 EXPECT_EQ(2, model_->item_count());
2610
2611 SwitchActiveUser(account_id);
2612 EXPECT_EQ(3, model_->item_count());
2613 }
2614 {
2615 // Switch user, hide the app, switch back and then show it again.
2616 SwitchActiveUser(account_id2);
2617 EXPECT_EQ(2, model_->item_count());
2618
2619 v2_app_1.window()->Hide();
2620 EXPECT_EQ(2, model_->item_count());
2621
2622 SwitchActiveUser(account_id);
2623 EXPECT_EQ(2, model_->item_count());
2624
2625 v2_app_1.window()->Show(extensions::AppWindow::SHOW_ACTIVE);
2626 EXPECT_EQ(3, model_->item_count());
2627 }
2628 {
2629 // Create a second app, hide and show it and then hide both apps.
2630 V2App v2_app_2(profile(), extension1_.get());
2631 EXPECT_EQ(3, model_->item_count());
2632
2633 v2_app_2.window()->Hide();
2634 EXPECT_EQ(3, model_->item_count());
2635
2636 v2_app_2.window()->Show(extensions::AppWindow::SHOW_ACTIVE);
2637 EXPECT_EQ(3, model_->item_count());
2638
2639 v2_app_1.window()->Hide();
2640 v2_app_2.window()->Hide();
2641 EXPECT_EQ(2, model_->item_count());
2642 }
2643 }
2644
2645 // Checks that the generated menu list properly activates items.
2646 TEST_F(ChromeLauncherControllerTest, V1AppMenuExecution) {
2647 InitLauncherControllerWithBrowser();
2648
2649 // Add |extension3_| to the launcher and add two items.
2650 GURL gmail = GURL("https://mail.google.com/mail/u");
2651 ash::ShelfID gmail_id = model_->next_id();
2652 extension_service_->AddExtension(extension3_.get());
2653 launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(gmail_url));
2654 base::string16 title1 = ASCIIToUTF16("Test1");
2655 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title1);
2656 chrome::NewTab(browser());
2657 base::string16 title2 = ASCIIToUTF16("Test2");
2658 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title2);
2659
2660 // Check that the menu is properly set.
2661 ash::ShelfItem item_gmail;
2662 item_gmail.type = ash::TYPE_APP_SHORTCUT;
2663 item_gmail.id = gmail_id;
2664 base::string16 two_menu_items[] = {title1, title2};
2665 EXPECT_TRUE(CheckMenuCreation(
2666 launcher_controller_.get(), item_gmail, 2, two_menu_items, false));
2667 EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
2668 // Execute the second item in the list (which shouldn't do anything since that
2669 // item is per definition already the active tab).
2670 {
2671 std::unique_ptr<ash::ShelfMenuModel> menu(
2672 new LauncherApplicationMenuItemModel(
2673 launcher_controller_->GetApplicationList(item_gmail, 0)));
2674 // The first element in the menu is a spacing separator. On some systems
2675 // (e.g. Windows) such things do not exist. As such we check the existence
2676 // and adjust dynamically.
2677 int first_item =
2678 (menu->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR) ? 1 : 0;
2679 menu->ActivatedAt(first_item + 3);
2680 }
2681 EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
2682
2683 // Execute the first item.
2684 {
2685 std::unique_ptr<ash::ShelfMenuModel> menu(
2686 new LauncherApplicationMenuItemModel(
2687 launcher_controller_->GetApplicationList(item_gmail, 0)));
2688 int first_item =
2689 (menu->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR) ? 1 : 0;
2690 menu->ActivatedAt(first_item + 2);
2691 }
2692 // Now the active tab should be the second item.
2693 EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
2694 }
2695
2696 // Checks that the generated menu list properly deletes items.
2697 TEST_F(ChromeLauncherControllerTest, V1AppMenuDeletionExecution) {
2698 InitLauncherControllerWithBrowser();
2699
2700 // Add |extension3_| to the launcher and add two items.
2701 GURL gmail = GURL("https://mail.google.com/mail/u");
2702 ash::ShelfID gmail_id = model_->next_id();
2703 extension_service_->AddExtension(extension3_.get());
2704 launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(gmail_url));
2705 base::string16 title1 = ASCIIToUTF16("Test1");
2706 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title1);
2707 chrome::NewTab(browser());
2708 base::string16 title2 = ASCIIToUTF16("Test2");
2709 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title2);
2710
2711 // Check that the menu is properly set.
2712 ash::ShelfItem item_gmail;
2713 item_gmail.type = ash::TYPE_APP_SHORTCUT;
2714 item_gmail.id = gmail_id;
2715 base::string16 two_menu_items[] = {title1, title2};
2716 EXPECT_TRUE(CheckMenuCreation(
2717 launcher_controller_.get(), item_gmail, 2, two_menu_items, false));
2718
2719 int tabs = browser()->tab_strip_model()->count();
2720 // Activate the proper tab through the menu item.
2721 {
2722 ChromeLauncherAppMenuItems items =
2723 launcher_controller_->GetApplicationList(item_gmail, 0);
2724 items[1]->Execute(0);
2725 EXPECT_EQ(tabs, browser()->tab_strip_model()->count());
2726 }
2727
2728 // Delete one tab through the menu item.
2729 {
2730 ChromeLauncherAppMenuItems items =
2731 launcher_controller_->GetApplicationList(item_gmail, 0);
2732 items[1]->Execute(ui::EF_SHIFT_DOWN);
2733 EXPECT_EQ(--tabs, browser()->tab_strip_model()->count());
2734 }
2735 }
2736
2737 // Tests that panels create launcher items correctly
2738 TEST_F(ChromeLauncherControllerTest, AppPanels) {
2739 InitLauncherControllerWithBrowser();
2740 // App list and Browser shortcut ShelfItems are added.
2741 EXPECT_EQ(2, model_observer_->added());
2742 EXPECT_EQ(1, model_observer_->changed());
2743
2744 const std::string app_id = extension1_->id();
2745 // app_icon_loader is owned by ChromeLauncherController.
2746 TestAppIconLoaderImpl* app_icon_loader = new TestAppIconLoaderImpl();
2747 app_icon_loader->AddSupportedApp(app_id);
2748 SetAppIconLoader(std::unique_ptr<AppIconLoader>(app_icon_loader));
2749
2750 // Test adding an app panel
2751 AppWindowLauncherItemController* app_panel_controller =
2752 new ExtensionAppWindowLauncherItemController(
2753 LauncherItemController::TYPE_APP_PANEL, "id", app_id,
2754 launcher_controller_.get());
2755 ash::ShelfID shelf_id1 = launcher_controller_->CreateAppLauncherItem(
2756 app_panel_controller, app_id, ash::STATUS_RUNNING);
2757 int panel_index = model_observer_->last_index();
2758 EXPECT_EQ(3, model_observer_->added());
2759 EXPECT_EQ(1, model_observer_->changed());
2760 EXPECT_EQ(1, app_icon_loader->fetch_count());
2761 model_observer_->clear_counts();
2762
2763 // App panels should have a separate identifier than the app id
2764 EXPECT_EQ(0, launcher_controller_->GetShelfIDForAppID(app_id));
2765
2766 // Setting the app image image should not change the panel if it set its icon
2767 app_panel_controller->set_image_set_by_controller(true);
2768 gfx::ImageSkia image;
2769 launcher_controller_->OnAppImageUpdated(app_id, image);
2770 EXPECT_EQ(0, model_observer_->changed());
2771 model_observer_->clear_counts();
2772
2773 // Add a second app panel and verify that it get the same index as the first
2774 // one had, being added to the left of the existing panel.
2775 AppWindowLauncherItemController* app_panel_controller2 =
2776 new ExtensionAppWindowLauncherItemController(
2777 LauncherItemController::TYPE_APP_PANEL, "id", app_id,
2778 launcher_controller_.get());
2779
2780 ash::ShelfID shelf_id2 = launcher_controller_->CreateAppLauncherItem(
2781 app_panel_controller2, app_id, ash::STATUS_RUNNING);
2782 EXPECT_EQ(panel_index, model_observer_->last_index());
2783 EXPECT_EQ(1, model_observer_->added());
2784 model_observer_->clear_counts();
2785
2786 launcher_controller_->CloseLauncherItem(shelf_id2);
2787 launcher_controller_->CloseLauncherItem(shelf_id1);
2788 EXPECT_EQ(2, model_observer_->removed());
2789 }
2790
2791 // Tests that the Gmail extension matches more then the app itself claims with
2792 // the manifest file.
2793 TEST_F(ChromeLauncherControllerTest, GmailMatching) {
2794 InitLauncherControllerWithBrowser();
2795
2796 // Create a Gmail browser tab.
2797 chrome::NewTab(browser());
2798 base::string16 title = ASCIIToUTF16("Test");
2799 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title);
2800 content::WebContents* content =
2801 browser()->tab_strip_model()->GetActiveWebContents();
2802
2803 // Check that the launcher controller does not recognize the running app.
2804 EXPECT_FALSE(launcher_controller_->ContentCanBeHandledByGmailApp(content));
2805
2806 // Installing |extension3_| adds it to the launcher.
2807 ash::ShelfID gmail_id = model_->next_id();
2808 extension_service_->AddExtension(extension3_.get());
2809 EXPECT_EQ(3, model_->item_count());
2810 int gmail_index = model_->ItemIndexByID(gmail_id);
2811 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[gmail_index].type);
2812 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
2813
2814 // Check that it is now handled.
2815 EXPECT_TRUE(launcher_controller_->ContentCanBeHandledByGmailApp(content));
2816
2817 // Check also that the app has detected that properly.
2818 ash::ShelfItem item_gmail;
2819 item_gmail.type = ash::TYPE_APP_SHORTCUT;
2820 item_gmail.id = gmail_id;
2821 EXPECT_EQ(2U, launcher_controller_->GetApplicationList(item_gmail, 0).size());
2822 }
2823
2824 // Tests that the Gmail extension does not match the offline verison.
2825 TEST_F(ChromeLauncherControllerTest, GmailOfflineMatching) {
2826 InitLauncherControllerWithBrowser();
2827
2828 // Create a Gmail browser tab.
2829 chrome::NewTab(browser());
2830 base::string16 title = ASCIIToUTF16("Test");
2831 NavigateAndCommitActiveTabWithTitle(browser(),
2832 GURL(offline_gmail_url),
2833 title);
2834 content::WebContents* content =
2835 browser()->tab_strip_model()->GetActiveWebContents();
2836
2837 // Installing |extension3_| adds it to the launcher.
2838 ash::ShelfID gmail_id = model_->next_id();
2839 extension_service_->AddExtension(extension3_.get());
2840 EXPECT_EQ(3, model_->item_count());
2841 int gmail_index = model_->ItemIndexByID(gmail_id);
2842 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[gmail_index].type);
2843 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
2844
2845 // The content should not be able to be handled by the app.
2846 EXPECT_FALSE(launcher_controller_->ContentCanBeHandledByGmailApp(content));
2847 }
2848
2849 // Verify that the launcher item positions are persisted and restored.
2850 TEST_F(ChromeLauncherControllerTest, PersistLauncherItemPositions) {
2851 InitLauncherController();
2852
2853 TestLauncherControllerHelper* helper = new TestLauncherControllerHelper;
2854 SetLauncherControllerHelper(helper);
2855
2856 EXPECT_EQ(ash::TYPE_APP_LIST, model_->items()[0].type);
2857 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT, model_->items()[1].type);
2858
2859 TabStripModel* tab_strip_model = browser()->tab_strip_model();
2860 EXPECT_EQ(0, tab_strip_model->count());
2861 chrome::NewTab(browser());
2862 chrome::NewTab(browser());
2863 EXPECT_EQ(2, tab_strip_model->count());
2864 helper->SetAppID(tab_strip_model->GetWebContentsAt(0), "1");
2865 helper->SetAppID(tab_strip_model->GetWebContentsAt(1), "2");
2866
2867 EXPECT_FALSE(launcher_controller_->IsAppPinned("1"));
2868 launcher_controller_->PinAppWithID("1");
2869 EXPECT_TRUE(launcher_controller_->IsAppPinned("1"));
2870 launcher_controller_->PinAppWithID("2");
2871
2872 EXPECT_EQ(ash::TYPE_APP_LIST, model_->items()[0].type);
2873 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT, model_->items()[1].type);
2874 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
2875 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[3].type);
2876
2877 // Move browser shortcut item from index 1 to index 3.
2878 model_->Move(1, 3);
2879 EXPECT_EQ(ash::TYPE_APP_LIST, model_->items()[0].type);
2880 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[1].type);
2881 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
2882 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT, model_->items()[3].type);
2883
2884 SetShelfItemDelegateManager(nullptr);
2885 launcher_controller_.reset();
2886 if (!ash::Shell::HasInstance()) {
2887 delete item_delegate_manager_;
2888 } else {
2889 // Clear already registered ShelfItemDelegate.
2890 ash::test::ShelfItemDelegateManagerTestAPI test(item_delegate_manager_);
2891 test.RemoveAllShelfItemDelegateForTest();
2892 }
2893 model_.reset(new ash::ShelfModel);
2894
2895 AddAppListLauncherItem();
2896 launcher_controller_.reset(
2897 ChromeLauncherController::CreateInstance(profile(), model_.get()));
2898 helper = new TestLauncherControllerHelper;
2899 helper->SetAppID(tab_strip_model->GetWebContentsAt(0), "1");
2900 helper->SetAppID(tab_strip_model->GetWebContentsAt(1), "2");
2901 SetLauncherControllerHelper(helper);
2902 if (!ash::Shell::HasInstance()) {
2903 item_delegate_manager_ = new ash::ShelfItemDelegateManager(model_.get());
2904 SetShelfItemDelegateManager(item_delegate_manager_);
2905 }
2906 launcher_controller_->Init();
2907
2908 // Check ShelfItems are restored after resetting ChromeLauncherController.
2909 EXPECT_EQ(ash::TYPE_APP_LIST, model_->items()[0].type);
2910 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[1].type);
2911 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
2912 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT, model_->items()[3].type);
2913 }
2914
2915 // Verifies pinned apps are persisted and restored.
2916 TEST_F(ChromeLauncherControllerTest, PersistPinned) {
2917 InitLauncherControllerWithBrowser();
2918 size_t initial_size = model_->items().size();
2919
2920 TabStripModel* tab_strip_model = browser()->tab_strip_model();
2921 EXPECT_EQ(1, tab_strip_model->count());
2922
2923 TestLauncherControllerHelper* helper = new TestLauncherControllerHelper;
2924 helper->SetAppID(tab_strip_model->GetWebContentsAt(0), "1");
2925 SetLauncherControllerHelper(helper);
2926
2927 // app_icon_loader is owned by ChromeLauncherController.
2928 TestAppIconLoaderImpl* app_icon_loader = new TestAppIconLoaderImpl;
2929 app_icon_loader->AddSupportedApp("1");
2930 SetAppIconLoader(std::unique_ptr<AppIconLoader>(app_icon_loader));
2931 EXPECT_EQ(0, app_icon_loader->fetch_count());
2932
2933 launcher_controller_->PinAppWithID("1");
2934 ash::ShelfID id = launcher_controller_->GetShelfIDForAppID("1");
2935 int app_index = model_->ItemIndexByID(id);
2936 EXPECT_EQ(1, app_icon_loader->fetch_count());
2937 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[app_index].type);
2938 EXPECT_TRUE(launcher_controller_->IsAppPinned("1"));
2939 EXPECT_FALSE(launcher_controller_->IsAppPinned("0"));
2940 EXPECT_EQ(initial_size + 1, model_->items().size());
2941
2942 SetShelfItemDelegateManager(nullptr);
2943 launcher_controller_.reset();
2944 if (!ash::Shell::HasInstance()) {
2945 delete item_delegate_manager_;
2946 } else {
2947 // Clear already registered ShelfItemDelegate.
2948 ash::test::ShelfItemDelegateManagerTestAPI test(item_delegate_manager_);
2949 test.RemoveAllShelfItemDelegateForTest();
2950 }
2951 model_.reset(new ash::ShelfModel);
2952
2953 AddAppListLauncherItem();
2954 launcher_controller_.reset(
2955 ChromeLauncherController::CreateInstance(profile(), model_.get()));
2956 helper = new TestLauncherControllerHelper;
2957 helper->SetAppID(tab_strip_model->GetWebContentsAt(0), "1");
2958 SetLauncherControllerHelper(helper);
2959 // app_icon_loader is owned by ChromeLauncherController.
2960 app_icon_loader = new TestAppIconLoaderImpl;
2961 app_icon_loader->AddSupportedApp("1");
2962 SetAppIconLoader(std::unique_ptr<AppIconLoader>(app_icon_loader));
2963 if (!ash::Shell::HasInstance()) {
2964 item_delegate_manager_ = new ash::ShelfItemDelegateManager(model_.get());
2965 SetShelfItemDelegateManager(item_delegate_manager_);
2966 }
2967 launcher_controller_->Init();
2968
2969 EXPECT_EQ(1, app_icon_loader->fetch_count());
2970 ASSERT_EQ(initial_size + 1, model_->items().size());
2971 EXPECT_TRUE(launcher_controller_->IsAppPinned("1"));
2972 EXPECT_FALSE(launcher_controller_->IsAppPinned("0"));
2973 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[app_index].type);
2974
2975 launcher_controller_->UnpinAppWithID("1");
2976 ASSERT_EQ(initial_size, model_->items().size());
2977 }
2978
2979 TEST_F(ChromeLauncherControllerTest, MultipleAppIconLoaders) {
2980 InitLauncherControllerWithBrowser();
2981
2982 const std::string app_id1 = extension1_->id();
2983 const std::string app_id2 = extension2_->id();
2984 const std::string app_id3 = extension3_->id();
2985 // app_icon_loader1 and app_icon_loader2 are owned by
2986 // ChromeLauncherController.
2987 TestAppIconLoaderImpl* app_icon_loader1 = new TestAppIconLoaderImpl();
2988 TestAppIconLoaderImpl* app_icon_loader2 = new TestAppIconLoaderImpl();
2989 app_icon_loader1->AddSupportedApp(app_id1);
2990 app_icon_loader2->AddSupportedApp(app_id2);
2991 SetAppIconLoaders(std::unique_ptr<AppIconLoader>(app_icon_loader1),
2992 std::unique_ptr<AppIconLoader>(app_icon_loader2));
2993
2994 AppWindowLauncherItemController* app_panel_controller3 =
2995 new ExtensionAppWindowLauncherItemController(
2996 LauncherItemController::TYPE_APP_PANEL, "id", app_id3,
2997 launcher_controller_.get());
2998 const ash::ShelfID shelfId3 = launcher_controller_->CreateAppLauncherItem(
2999 app_panel_controller3, app_id3, ash::STATUS_RUNNING);
3000 EXPECT_EQ(0, app_icon_loader1->fetch_count());
3001 EXPECT_EQ(0, app_icon_loader1->clear_count());
3002 EXPECT_EQ(0, app_icon_loader2->fetch_count());
3003 EXPECT_EQ(0, app_icon_loader2->clear_count());
3004
3005 AppWindowLauncherItemController* app_panel_controller2 =
3006 new ExtensionAppWindowLauncherItemController(
3007 LauncherItemController::TYPE_APP_PANEL, "id", app_id2,
3008 launcher_controller_.get());
3009 const ash::ShelfID shelfId2 = launcher_controller_->CreateAppLauncherItem(
3010 app_panel_controller2, app_id2, ash::STATUS_RUNNING);
3011 EXPECT_EQ(0, app_icon_loader1->fetch_count());
3012 EXPECT_EQ(0, app_icon_loader1->clear_count());
3013 EXPECT_EQ(1, app_icon_loader2->fetch_count());
3014 EXPECT_EQ(0, app_icon_loader2->clear_count());
3015
3016 // Test adding an app panel
3017 AppWindowLauncherItemController* app_panel_controller1 =
3018 new ExtensionAppWindowLauncherItemController(
3019 LauncherItemController::TYPE_APP_PANEL, "id", app_id1,
3020 launcher_controller_.get());
3021
3022 const ash::ShelfID shelfId1 = launcher_controller_->CreateAppLauncherItem(
3023 app_panel_controller1, app_id1, ash::STATUS_RUNNING);
3024 EXPECT_EQ(1, app_icon_loader1->fetch_count());
3025 EXPECT_EQ(0, app_icon_loader1->clear_count());
3026 EXPECT_EQ(1, app_icon_loader2->fetch_count());
3027 EXPECT_EQ(0, app_icon_loader2->clear_count());
3028
3029 launcher_controller_->CloseLauncherItem(shelfId1);
3030 EXPECT_EQ(1, app_icon_loader1->fetch_count());
3031 EXPECT_EQ(1, app_icon_loader1->clear_count());
3032 EXPECT_EQ(1, app_icon_loader2->fetch_count());
3033 EXPECT_EQ(0, app_icon_loader2->clear_count());
3034
3035 launcher_controller_->CloseLauncherItem(shelfId2);
3036 EXPECT_EQ(1, app_icon_loader1->fetch_count());
3037 EXPECT_EQ(1, app_icon_loader1->clear_count());
3038 EXPECT_EQ(1, app_icon_loader2->fetch_count());
3039 EXPECT_EQ(1, app_icon_loader2->clear_count());
3040
3041 launcher_controller_->CloseLauncherItem(shelfId3);
3042 EXPECT_EQ(1, app_icon_loader1->fetch_count());
3043 EXPECT_EQ(1, app_icon_loader1->clear_count());
3044 EXPECT_EQ(1, app_icon_loader2->fetch_count());
3045 EXPECT_EQ(1, app_icon_loader2->clear_count());
3046 }
3047
3048 TEST_F(ChromeLauncherControllerTest, ArcAppPinPolicy) {
3049 arc_test_.SetUp(profile());
3050 InitLauncherControllerWithBrowser();
3051
3052 arc::mojom::AppInfo appinfo;
3053 appinfo.name = "Some App";
3054 appinfo.activity = "SomeActivity";
3055 appinfo.package_name = "com.example.app";
3056
3057 ArcAppListPrefs* const prefs = arc_test_.arc_app_list_prefs();
3058 ASSERT_TRUE(prefs);
3059
3060 // Adding app to the prefs, and check that the app is accessible by id.
3061 prefs->AddApp(appinfo);
3062 const std::string app_id =
3063 ArcAppListPrefs::GetAppId(appinfo.package_name, appinfo.activity);
3064 EXPECT_TRUE(prefs->GetApp(app_id));
3065
3066 // Set policy, that makes pins ARC app. Unlike native extension, for ARC app
3067 // package_name (not hash) specified as id. In this test we check that
3068 // by hash we can determine that appropriate package was set by policy.
3069 base::ListValue policy_value;
3070 InsertPrefValue(&policy_value, 0, appinfo.package_name);
3071 profile()->GetTestingPrefService()->SetManagedPref(
3072 prefs::kPolicyPinnedLauncherApps, policy_value.DeepCopy());
3073
3074 EXPECT_TRUE(launcher_controller_->IsAppPinned(app_id));
3075 EXPECT_EQ(AppListControllerDelegate::PIN_FIXED,
3076 launcher_controller_->GetPinnable(app_id));
3077 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698