Elim cr-checkbox
[chromium-blink-merge.git] / chrome / browser / ui / ash / launcher / chrome_launcher_controller_unittest.cc
blobe10c9529c892ccb14df294e9848f83d62100a350
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.
5 #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h"
7 #include <algorithm>
8 #include <string>
9 #include <vector>
11 #include "ash/ash_switches.h"
12 #include "ash/shelf/shelf_item_delegate_manager.h"
13 #include "ash/shelf/shelf_model.h"
14 #include "ash/shelf/shelf_model_observer.h"
15 #include "ash/shell.h"
16 #include "ash/test/shelf_item_delegate_manager_test_api.h"
17 #include "base/command_line.h"
18 #include "base/compiler_specific.h"
19 #include "base/files/file_path.h"
20 #include "base/memory/scoped_ptr.h"
21 #include "base/message_loop/message_loop.h"
22 #include "base/strings/utf_string_conversions.h"
23 #include "base/values.h"
24 #include "chrome/browser/extensions/extension_service.h"
25 #include "chrome/browser/extensions/test_extension_system.h"
26 #include "chrome/browser/ui/ash/chrome_launcher_prefs.h"
27 #include "chrome/browser/ui/ash/launcher/app_window_launcher_item_controller.h"
28 #include "chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h"
29 #include "chrome/browser/ui/ash/launcher/launcher_item_controller.h"
30 #include "chrome/browser/ui/browser.h"
31 #include "chrome/browser/ui/browser_commands.h"
32 #include "chrome/browser/ui/browser_finder.h"
33 #include "chrome/browser/ui/browser_list.h"
34 #include "chrome/browser/ui/browser_tabstrip.h"
35 #include "chrome/browser/ui/host_desktop.h"
36 #include "chrome/browser/ui/tabs/tab_strip_model.h"
37 #include "chrome/common/extensions/extension_constants.h"
38 #include "chrome/common/pref_names.h"
39 #include "chrome/test/base/browser_with_test_window_test.h"
40 #include "chrome/test/base/testing_profile.h"
41 #include "components/syncable_prefs/testing_pref_service_syncable.h"
42 #include "content/public/browser/web_contents.h"
43 #include "extensions/common/extension.h"
44 #include "extensions/common/manifest_constants.h"
45 #include "testing/gtest/include/gtest/gtest.h"
46 #include "ui/aura/client/window_tree_client.h"
47 #include "ui/base/models/menu_model.h"
49 #if defined(OS_CHROMEOS)
50 #include "ash/test/test_session_state_delegate.h"
51 #include "ash/test/test_shell_delegate.h"
52 #include "chrome/browser/apps/scoped_keep_alive.h"
53 #include "chrome/browser/chromeos/login/users/fake_chrome_user_manager.h"
54 #include "chrome/browser/chromeos/login/users/scoped_user_manager_enabler.h"
55 #include "chrome/browser/chromeos/login/users/wallpaper/wallpaper_manager.h"
56 #include "chrome/browser/ui/apps/chrome_app_delegate.h"
57 #include "chrome/browser/ui/ash/launcher/app_window_launcher_controller.h"
58 #include "chrome/browser/ui/ash/launcher/browser_status_monitor.h"
59 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
60 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
61 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager_chromeos.h"
62 #include "chrome/common/chrome_constants.h"
63 #include "chrome/common/chrome_switches.h"
64 #include "chrome/test/base/testing_browser_process.h"
65 #include "chrome/test/base/testing_profile_manager.h"
66 #include "components/user_manager/fake_user_manager.h"
67 #include "content/public/browser/web_contents_observer.h"
68 #include "content/public/test/test_utils.h"
69 #include "extensions/browser/app_window/app_window_contents.h"
70 #include "extensions/browser/app_window/app_window_registry.h"
71 #include "extensions/browser/app_window/native_app_window.h"
72 #include "ui/aura/window.h"
73 #endif
75 #if defined(USE_AURA)
76 #include "chrome/test/base/test_browser_window_aura.h"
77 #endif // defined(USE_AURA)
79 using base::ASCIIToUTF16;
80 using extensions::Extension;
81 using extensions::Manifest;
82 using extensions::UnloadedExtensionInfo;
84 namespace {
85 const char* offline_gmail_url = "https://mail.google.com/mail/mu/u";
86 const char* gmail_url = "https://mail.google.com/mail/u";
87 const char* kGmailLaunchURL = "https://mail.google.com/mail/ca";
89 #if defined(OS_CHROMEOS)
90 // An extension prefix.
91 const char kCrxAppPrefix[] = "_crx_";
92 #endif
94 // ShelfModelObserver implementation that tracks what messages are invoked.
95 class TestShelfModelObserver : public ash::ShelfModelObserver {
96 public:
97 TestShelfModelObserver()
98 : added_(0),
99 removed_(0),
100 changed_(0) {
103 ~TestShelfModelObserver() override {}
105 // Overridden from ash::ShelfModelObserver:
106 void ShelfItemAdded(int index) override {
107 ++added_;
108 last_index_ = index;
111 void ShelfItemRemoved(int index, ash::ShelfID id) override {
112 ++removed_;
113 last_index_ = index;
116 void ShelfItemChanged(int index, const ash::ShelfItem& old_item) override {
117 ++changed_;
118 last_index_ = index;
121 void ShelfItemMoved(int start_index, int target_index) override {
122 last_index_ = target_index;
125 void ShelfStatusChanged() override {}
127 void clear_counts() {
128 added_ = 0;
129 removed_ = 0;
130 changed_ = 0;
131 last_index_ = 0;
134 int added() const { return added_; }
135 int removed() const { return removed_; }
136 int changed() const { return changed_; }
137 int last_index() const { return last_index_; }
139 private:
140 int added_;
141 int removed_;
142 int changed_;
143 int last_index_;
145 DISALLOW_COPY_AND_ASSIGN(TestShelfModelObserver);
148 // Test implementation of AppIconLoader.
149 class TestAppIconLoaderImpl : public extensions::AppIconLoader {
150 public:
151 TestAppIconLoaderImpl() : fetch_count_(0) {
154 ~TestAppIconLoaderImpl() override {}
156 // AppIconLoader implementation:
157 void FetchImage(const std::string& id) override { ++fetch_count_; }
159 void ClearImage(const std::string& id) override {}
161 void UpdateImage(const std::string& id) override {}
163 int fetch_count() const { return fetch_count_; }
165 private:
166 int fetch_count_;
168 DISALLOW_COPY_AND_ASSIGN(TestAppIconLoaderImpl);
171 // Test implementation of AppTabHelper.
172 class TestAppTabHelperImpl : public ChromeLauncherController::AppTabHelper {
173 public:
174 TestAppTabHelperImpl() {}
175 ~TestAppTabHelperImpl() override {}
177 // Sets the id for the specified tab. The id is removed if Remove() is
178 // invoked.
179 void SetAppID(content::WebContents* tab, const std::string& id) {
180 tab_id_map_[tab] = id;
183 // Returns true if there is an id registered for |tab|.
184 bool HasAppID(content::WebContents* tab) const {
185 return tab_id_map_.find(tab) != tab_id_map_.end();
188 // AppTabHelper implementation:
189 std::string GetAppID(content::WebContents* tab) override {
190 return tab_id_map_.find(tab) != tab_id_map_.end() ? tab_id_map_[tab] :
191 std::string();
194 bool IsValidIDForCurrentUser(const std::string& id) override {
195 for (TabToStringMap::const_iterator i = tab_id_map_.begin();
196 i != tab_id_map_.end(); ++i) {
197 if (i->second == id)
198 return true;
200 return false;
203 void SetCurrentUser(Profile* profile) override {
204 // We can ignore this for now.
207 private:
208 typedef std::map<content::WebContents*, std::string> TabToStringMap;
210 TabToStringMap tab_id_map_;
212 DISALLOW_COPY_AND_ASSIGN(TestAppTabHelperImpl);
215 // Test implementation of a V2 app launcher item controller.
216 class TestV2AppLauncherItemController : public LauncherItemController {
217 public:
218 TestV2AppLauncherItemController(const std::string& app_id,
219 ChromeLauncherController* controller)
220 : LauncherItemController(LauncherItemController::TYPE_APP,
221 app_id,
222 controller) {
225 ~TestV2AppLauncherItemController() override {}
227 // Override for LauncherItemController:
228 bool IsOpen() const override { return true; }
229 bool IsVisible() const override { return true; }
230 void Launch(ash::LaunchSource source, int event_flags) override {}
231 ash::ShelfItemDelegate::PerformedAction Activate(
232 ash::LaunchSource source) override {
233 return kExistingWindowActivated;
235 void Close() override {}
236 ash::ShelfItemDelegate::PerformedAction ItemSelected(
237 const ui::Event& event) override {
238 return kExistingWindowActivated;
240 base::string16 GetTitle() override { return base::string16(); }
241 ChromeLauncherAppMenuItems GetApplicationList(int event_flags) override {
242 ChromeLauncherAppMenuItems items;
243 items.push_back(
244 new ChromeLauncherAppMenuItem(base::string16(), NULL, false));
245 items.push_back(
246 new ChromeLauncherAppMenuItem(base::string16(), NULL, false));
247 return items.Pass();
249 ui::MenuModel* CreateContextMenu(aura::Window* root_window) override {
250 return NULL;
252 ash::ShelfMenuModel* CreateApplicationMenu(int event_flags) override {
253 return NULL;
255 bool IsDraggable() override { return false; }
256 bool ShouldShowTooltip() override { return false; }
258 private:
259 DISALLOW_COPY_AND_ASSIGN(TestV2AppLauncherItemController);
262 } // namespace
264 class ChromeLauncherControllerTest : public BrowserWithTestWindowTest {
265 protected:
266 ChromeLauncherControllerTest()
267 : BrowserWithTestWindowTest(
268 Browser::TYPE_TABBED,
269 chrome::HOST_DESKTOP_TYPE_ASH,
270 false),
271 test_controller_(NULL),
272 extension_service_(NULL) {
275 ~ChromeLauncherControllerTest() override {}
277 void SetUp() override {
278 BrowserWithTestWindowTest::SetUp();
280 model_.reset(new ash::ShelfModel);
281 model_observer_.reset(new TestShelfModelObserver);
282 model_->AddObserver(model_observer_.get());
284 if (ash::Shell::HasInstance()) {
285 item_delegate_manager_ =
286 ash::Shell::GetInstance()->shelf_item_delegate_manager();
287 } else {
288 item_delegate_manager_ =
289 new ash::ShelfItemDelegateManager(model_.get());
292 base::DictionaryValue manifest;
293 manifest.SetString(extensions::manifest_keys::kName,
294 "launcher controller test extension");
295 manifest.SetString(extensions::manifest_keys::kVersion, "1");
296 manifest.SetString(extensions::manifest_keys::kDescription,
297 "for testing pinned apps");
299 extensions::TestExtensionSystem* extension_system(
300 static_cast<extensions::TestExtensionSystem*>(
301 extensions::ExtensionSystem::Get(profile())));
302 extension_service_ = extension_system->CreateExtensionService(
303 base::CommandLine::ForCurrentProcess(), base::FilePath(), false);
305 std::string error;
306 extension1_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
307 manifest,
308 Extension::NO_FLAGS,
309 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
310 &error);
311 extension2_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
312 manifest,
313 Extension::NO_FLAGS,
314 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
315 &error);
316 // Fake gmail extension.
317 base::DictionaryValue manifest_gmail;
318 manifest_gmail.SetString(extensions::manifest_keys::kName,
319 "Gmail launcher controller test extension");
320 manifest_gmail.SetString(extensions::manifest_keys::kVersion, "1");
321 manifest_gmail.SetString(extensions::manifest_keys::kDescription,
322 "for testing pinned Gmail");
323 manifest_gmail.SetString(extensions::manifest_keys::kLaunchWebURL,
324 kGmailLaunchURL);
325 base::ListValue* list = new base::ListValue();
326 list->Append(new base::StringValue("*://mail.google.com/mail/ca"));
327 manifest_gmail.Set(extensions::manifest_keys::kWebURLs, list);
329 extension3_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
330 manifest_gmail,
331 Extension::NO_FLAGS,
332 extension_misc::kGmailAppId,
333 &error);
335 // Fake search extension.
336 extension4_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
337 manifest,
338 Extension::NO_FLAGS,
339 extension_misc::kGoogleSearchAppId,
340 &error);
341 extension5_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
342 manifest,
343 Extension::NO_FLAGS,
344 "cccccccccccccccccccccccccccccccc",
345 &error);
346 extension6_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
347 manifest,
348 Extension::NO_FLAGS,
349 "dddddddddddddddddddddddddddddddd",
350 &error);
351 extension7_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
352 manifest,
353 Extension::NO_FLAGS,
354 "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
355 &error);
356 extension8_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
357 manifest,
358 Extension::NO_FLAGS,
359 "ffffffffffffffffffffffffffffffff",
360 &error);
363 // Creates a running V2 app (not pinned) of type |app_id|.
364 virtual void CreateRunningV2App(const std::string& app_id) {
365 DCHECK(!test_controller_);
366 ash::ShelfID id =
367 launcher_controller_->CreateAppShortcutLauncherItemWithType(
368 app_id,
369 model_->item_count(),
370 ash::TYPE_PLATFORM_APP);
371 DCHECK(id);
372 // Change the created launcher controller into a V2 app controller.
373 test_controller_ = new TestV2AppLauncherItemController(app_id,
374 launcher_controller_.get());
375 launcher_controller_->SetItemController(id, test_controller_);
378 // Sets the stage for a multi user test.
379 virtual void SetUpMultiUserScenario(base::ListValue* user_a,
380 base::ListValue* user_b) {
381 InitLauncherController();
382 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
384 // Set an empty pinned pref to begin with.
385 base::ListValue no_user;
386 SetShelfChromeIconIndex(0);
387 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
388 no_user.DeepCopy());
389 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
391 // Assume all applications have been added already.
392 extension_service_->AddExtension(extension1_.get());
393 extension_service_->AddExtension(extension2_.get());
394 extension_service_->AddExtension(extension3_.get());
395 extension_service_->AddExtension(extension4_.get());
396 extension_service_->AddExtension(extension5_.get());
397 extension_service_->AddExtension(extension6_.get());
398 extension_service_->AddExtension(extension7_.get());
399 extension_service_->AddExtension(extension8_.get());
400 // There should be nothing in the list by now.
401 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
403 // Set user a preferences.
404 InsertPrefValue(user_a, 0, extension1_->id());
405 InsertPrefValue(user_a, 1, extension2_->id());
406 InsertPrefValue(user_a, 2, extension3_->id());
407 InsertPrefValue(user_a, 3, extension4_->id());
408 InsertPrefValue(user_a, 4, extension5_->id());
409 InsertPrefValue(user_a, 5, extension6_->id());
411 // Set user b preferences.
412 InsertPrefValue(user_b, 0, extension7_->id());
413 InsertPrefValue(user_b, 1, extension8_->id());
416 void TearDown() override {
417 launcher_controller_->SetShelfItemDelegateManagerForTest(nullptr);
418 model_->RemoveObserver(model_observer_.get());
419 model_observer_.reset();
420 launcher_controller_.reset();
422 // item_delegate_manager_ must be deleted after launch_controller_,
423 // because launch_controller_ has a map of pointers to the data
424 // hold by item_delegate_manager_.
425 if (!ash::Shell::HasInstance())
426 delete item_delegate_manager_;
428 model_.reset();
430 BrowserWithTestWindowTest::TearDown();
433 BrowserWindow* CreateBrowserWindow() override {
434 return CreateTestBrowserWindowAura();
437 scoped_ptr<Browser> CreateBrowserWithTestWindowForProfile(Profile* profile) {
438 TestBrowserWindow* browser_widnow = CreateTestBrowserWindowAura();
439 new TestBrowserWindowOwner(browser_widnow);
440 return make_scoped_ptr(CreateBrowser(profile, Browser::TYPE_TABBED, false,
441 chrome::HOST_DESKTOP_TYPE_ASH,
442 browser_widnow));
445 void AddAppListLauncherItem() {
446 ash::ShelfItem app_list;
447 app_list.type = ash::TYPE_APP_LIST;
448 model_->Add(app_list);
451 void InitLauncherController() {
452 AddAppListLauncherItem();
453 launcher_controller_.reset(
454 new ChromeLauncherController(profile(), model_.get()));
455 if (!ash::Shell::HasInstance())
456 SetShelfItemDelegateManager(item_delegate_manager_);
457 launcher_controller_->Init();
460 void InitLauncherControllerWithBrowser() {
461 InitLauncherController();
462 chrome::NewTab(browser());
463 browser()->window()->Show();
466 void SetAppIconLoader(extensions::AppIconLoader* loader) {
467 launcher_controller_->SetAppIconLoaderForTest(loader);
470 void SetAppTabHelper(ChromeLauncherController::AppTabHelper* helper) {
471 launcher_controller_->SetAppTabHelperForTest(helper);
474 void SetShelfItemDelegateManager(ash::ShelfItemDelegateManager* manager) {
475 launcher_controller_->SetShelfItemDelegateManagerForTest(manager);
478 void InsertPrefValue(base::ListValue* pref_value,
479 int index,
480 const std::string& extension_id) {
481 base::DictionaryValue* entry = new base::DictionaryValue();
482 entry->SetString(ash::kPinnedAppsPrefAppIDPath, extension_id);
483 pref_value->Insert(index, entry);
486 // Gets the currently configured app launchers from the controller.
487 void GetAppLaunchers(ChromeLauncherController* controller,
488 std::vector<std::string>* launchers) {
489 launchers->clear();
490 for (ash::ShelfItems::const_iterator iter(model_->items().begin());
491 iter != model_->items().end(); ++iter) {
492 ChromeLauncherController::IDToItemControllerMap::const_iterator
493 entry(controller->id_to_item_controller_map_.find(iter->id));
494 if (iter->type == ash::TYPE_APP_SHORTCUT &&
495 entry != controller->id_to_item_controller_map_.end()) {
496 launchers->push_back(entry->second->app_id());
501 // Get the setup of the currently shown launcher items in one string.
502 // Each pinned element will start with a big letter, each running but not
503 // pinned V1 app will start with a small letter and each running but not
504 // pinned V2 app will start with a '*' + small letter.
505 std::string GetPinnedAppStatus() {
506 std::string result;
507 for (int i = 0; i < model_->item_count(); i++) {
508 if (!result.empty())
509 result.append(", ");
510 switch (model_->items()[i].type) {
511 case ash::TYPE_PLATFORM_APP:
512 result+= "*";
513 // FALLTHROUGH
514 case ash::TYPE_WINDOWED_APP: {
515 const std::string& app =
516 launcher_controller_->GetAppIDForShelfID(model_->items()[i].id);
517 if (app == extension1_->id()) {
518 result += "app1";
519 EXPECT_FALSE(
520 launcher_controller_->IsAppPinned(extension1_->id()));
521 } else if (app == extension2_->id()) {
522 result += "app2";
523 EXPECT_FALSE(
524 launcher_controller_->IsAppPinned(extension2_->id()));
525 } else if (app == extension3_->id()) {
526 result += "app3";
527 EXPECT_FALSE(
528 launcher_controller_->IsAppPinned(extension3_->id()));
529 } else if (app == extension4_->id()) {
530 result += "app4";
531 EXPECT_FALSE(
532 launcher_controller_->IsAppPinned(extension4_->id()));
533 } else if (app == extension5_->id()) {
534 result += "app5";
535 EXPECT_FALSE(
536 launcher_controller_->IsAppPinned(extension5_->id()));
537 } else if (app == extension6_->id()) {
538 result += "app6";
539 EXPECT_FALSE(
540 launcher_controller_->IsAppPinned(extension6_->id()));
541 } else if (app == extension7_->id()) {
542 result += "app7";
543 EXPECT_FALSE(
544 launcher_controller_->IsAppPinned(extension7_->id()));
545 } else if (app == extension8_->id()) {
546 result += "app8";
547 EXPECT_FALSE(
548 launcher_controller_->IsAppPinned(extension8_->id()));
549 } else {
550 result += "unknown";
552 break;
554 case ash::TYPE_APP_SHORTCUT: {
555 const std::string& app =
556 launcher_controller_->GetAppIDForShelfID(model_->items()[i].id);
557 if (app == extension1_->id()) {
558 result += "App1";
559 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
560 } else if (app == extension2_->id()) {
561 result += "App2";
562 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension2_->id()));
563 } else if (app == extension3_->id()) {
564 result += "App3";
565 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
566 } else if (app == extension4_->id()) {
567 result += "App4";
568 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension4_->id()));
569 } else if (app == extension5_->id()) {
570 result += "App5";
571 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension5_->id()));
572 } else if (app == extension6_->id()) {
573 result += "App6";
574 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension6_->id()));
575 } else if (app == extension7_->id()) {
576 result += "App7";
577 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension7_->id()));
578 } else if (app == extension8_->id()) {
579 result += "App8";
580 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension8_->id()));
581 } else {
582 result += "unknown";
584 break;
586 case ash::TYPE_BROWSER_SHORTCUT:
587 result += "Chrome";
588 break;
589 case ash::TYPE_APP_LIST:
590 result += "AppList";
591 break;
592 default:
593 result += "Unknown";
594 break;
597 return result;
600 // Set the index at which the chrome icon should be.
601 void SetShelfChromeIconIndex(int index) {
602 profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex,
603 index);
606 // Remember the order of unpinned but running applications for the current
607 // user.
608 void RememberUnpinnedRunningApplicationOrder() {
609 launcher_controller_->RememberUnpinnedRunningApplicationOrder();
612 // Restore the order of running but unpinned applications for a given user.
613 void RestoreUnpinnedRunningApplicationOrder(const std::string& user_id) {
614 launcher_controller_->RestoreUnpinnedRunningApplicationOrder(user_id);
617 // Needed for extension service & friends to work.
618 scoped_refptr<Extension> extension1_;
619 scoped_refptr<Extension> extension2_;
620 scoped_refptr<Extension> extension3_;
621 scoped_refptr<Extension> extension4_;
622 scoped_refptr<Extension> extension5_;
623 scoped_refptr<Extension> extension6_;
624 scoped_refptr<Extension> extension7_;
625 scoped_refptr<Extension> extension8_;
626 scoped_ptr<ChromeLauncherController> launcher_controller_;
627 scoped_ptr<TestShelfModelObserver> model_observer_;
628 scoped_ptr<ash::ShelfModel> model_;
630 // |item_delegate_manager_| owns |test_controller_|.
631 LauncherItemController* test_controller_;
633 ExtensionService* extension_service_;
635 ash::ShelfItemDelegateManager* item_delegate_manager_;
637 private:
638 TestBrowserWindow* CreateTestBrowserWindowAura() {
639 scoped_ptr<aura::Window> window(new aura::Window(nullptr));
640 window->set_id(0);
641 window->SetType(ui::wm::WINDOW_TYPE_NORMAL);
642 window->Init(ui::LAYER_TEXTURED);
643 aura::client::ParentWindowWithContext(window.get(), GetContext(),
644 gfx::Rect(200, 200));
646 return new TestBrowserWindowAura(window.Pass());
649 DISALLOW_COPY_AND_ASSIGN(ChromeLauncherControllerTest);
652 #if defined(OS_CHROMEOS)
654 // Watches WebContents and blocks until it is destroyed. This is needed for
655 // the destruction of a V2 application.
656 class WebContentsDestroyedWatcher : public content::WebContentsObserver {
657 public:
658 explicit WebContentsDestroyedWatcher(content::WebContents* web_contents)
659 : content::WebContentsObserver(web_contents),
660 message_loop_runner_(new content::MessageLoopRunner) {
661 EXPECT_TRUE(web_contents != NULL);
663 ~WebContentsDestroyedWatcher() override {}
665 // Waits until the WebContents is destroyed.
666 void Wait() {
667 message_loop_runner_->Run();
670 private:
671 // Overridden WebContentsObserver methods.
672 void WebContentsDestroyed() override { message_loop_runner_->Quit(); }
674 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
676 DISALLOW_COPY_AND_ASSIGN(WebContentsDestroyedWatcher);
679 // A V1 windowed application.
680 class V1App : public TestBrowserWindow {
681 public:
682 V1App(Profile* profile, const std::string& app_name) {
683 // Create a window.
684 native_window_.reset(new aura::Window(NULL));
685 native_window_->set_id(0);
686 native_window_->SetType(ui::wm::WINDOW_TYPE_POPUP);
687 native_window_->Init(ui::LAYER_TEXTURED);
688 native_window_->Show();
689 aura::client::ParentWindowWithContext(native_window_.get(),
690 ash::Shell::GetPrimaryRootWindow(),
691 gfx::Rect(10, 10, 20, 30));
692 Browser::CreateParams params =
693 Browser::CreateParams::CreateForApp(kCrxAppPrefix + app_name,
694 true /* trusted_source */,
695 gfx::Rect(),
696 profile,
697 chrome::HOST_DESKTOP_TYPE_ASH);
698 params.window = this;
699 browser_.reset(new Browser(params));
700 chrome::AddTabAt(browser_.get(), GURL(), 0, true);
703 ~V1App() override {
704 // close all tabs. Note that we do not need to destroy the browser itself.
705 browser_->tab_strip_model()->CloseAllTabs();
708 Browser* browser() { return browser_.get(); }
710 // TestBrowserWindow override:
711 gfx::NativeWindow GetNativeWindow() const override {
712 return native_window_.get();
715 private:
716 // The associated browser with this app.
717 scoped_ptr<Browser> browser_;
719 // The native window we use.
720 scoped_ptr<aura::Window> native_window_;
722 DISALLOW_COPY_AND_ASSIGN(V1App);
725 // A V2 application which gets created with an |extension| and for a |profile|.
726 // Upon destruction it will properly close the application.
727 class V2App {
728 public:
729 V2App(Profile* profile, const extensions::Extension* extension) {
730 window_ = new extensions::AppWindow(
731 profile,
732 new ChromeAppDelegate(make_scoped_ptr(new ScopedKeepAlive)),
733 extension);
734 extensions::AppWindow::CreateParams params =
735 extensions::AppWindow::CreateParams();
736 window_->Init(GURL(std::string()),
737 new extensions::AppWindowContentsImpl(window_), params);
740 virtual ~V2App() {
741 WebContentsDestroyedWatcher destroyed_watcher(window_->web_contents());
742 window_->GetBaseWindow()->Close();
743 destroyed_watcher.Wait();
746 extensions::AppWindow* window() { return window_; }
748 private:
749 // The app window which represents the application. Note that the window
750 // deletes itself asynchronously after window_->GetBaseWindow()->Close() gets
751 // called.
752 extensions::AppWindow* window_;
754 DISALLOW_COPY_AND_ASSIGN(V2App);
757 // The testing framework to test multi profile scenarios.
758 class MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
759 : public ChromeLauncherControllerTest {
760 protected:
761 MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest() {
764 ~MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest() override {}
766 // Overwrite the Setup function to enable multi profile and needed objects.
767 void SetUp() override {
768 profile_manager_.reset(
769 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
771 ASSERT_TRUE(profile_manager_->SetUp());
773 // AvatarMenu and multiple profiles works after user logged in.
774 profile_manager_->SetLoggedIn(true);
776 // Initialize the UserManager singleton to a fresh FakeUserManager instance.
777 user_manager_enabler_.reset(new chromeos::ScopedUserManagerEnabler(
778 new chromeos::FakeChromeUserManager));
780 // Initialize the WallpaperManager singleton.
781 chromeos::WallpaperManager::Initialize();
783 // Initialize the rest.
784 ChromeLauncherControllerTest::SetUp();
786 // Get some base objects.
787 session_delegate()->set_logged_in_users(2);
788 shell_delegate_ = static_cast<ash::test::TestShellDelegate*>(
789 ash::Shell::GetInstance()->delegate());
790 shell_delegate_->set_multi_profiles_enabled(true);
793 void TearDown() override {
794 ChromeLauncherControllerTest::TearDown();
795 user_manager_enabler_.reset();
796 for (ProfileToNameMap::iterator it = created_profiles_.begin();
797 it != created_profiles_.end(); ++it)
798 profile_manager_->DeleteTestingProfile(it->second);
799 chromeos::WallpaperManager::Shutdown();
801 // A Task is leaked if we don't destroy everything, then run the message
802 // loop.
803 base::MessageLoop::current()->PostTask(FROM_HERE,
804 base::MessageLoop::QuitClosure());
805 base::MessageLoop::current()->Run();
808 // Creates a profile for a given |user_name|. Note that this class will keep
809 // the ownership of the created object.
810 TestingProfile* CreateMultiUserProfile(const std::string& user_name) {
811 std::string email_string = user_name + "@example.com";
812 static_cast<ash::test::TestSessionStateDelegate*>(
813 ash::Shell::GetInstance()->session_state_delegate())
814 ->AddUser(email_string);
815 // Add a user to the fake user manager.
816 session_delegate()->AddUser(email_string);
817 GetFakeUserManager()->AddUser(email_string);
819 GetFakeUserManager()->LoginUser(email_string);
821 TestingProfile* profile =
822 profile_manager()->CreateTestingProfile(email_string);
823 EXPECT_TRUE(profile);
825 // Remember the profile name so that we can destroy it upon destruction.
826 created_profiles_[profile] = email_string;
827 if (chrome::MultiUserWindowManager::GetInstance())
828 chrome::MultiUserWindowManager::GetInstance()->AddUser(profile);
829 if (launcher_controller_)
830 launcher_controller_->AdditionalUserAddedToSession(profile);
831 return profile;
834 // Switch to another user.
835 void SwitchActiveUser(const std::string& name) {
836 session_delegate()->SwitchActiveUser(name);
837 GetFakeUserManager()->SwitchActiveUser(name);
838 chrome::MultiUserWindowManagerChromeOS* manager =
839 static_cast<chrome::MultiUserWindowManagerChromeOS*>(
840 chrome::MultiUserWindowManager::GetInstance());
841 manager->SetAnimationSpeedForTest(
842 chrome::MultiUserWindowManagerChromeOS::ANIMATION_SPEED_DISABLED);
843 manager->ActiveUserChanged(name);
844 launcher_controller_->browser_status_monitor_for_test()->
845 ActiveUserChanged(name);
846 launcher_controller_->app_window_controller_for_test()->
847 ActiveUserChanged(name);
850 // Creates a browser with a |profile| and load a tab with a |title| and |url|.
851 scoped_ptr<Browser> CreateBrowserAndTabWithProfile(Profile* profile,
852 const std::string& title,
853 const std::string& url) {
854 scoped_ptr<Browser> browser(CreateBrowserWithTestWindowForProfile(profile));
855 chrome::NewTab(browser.get());
857 browser->window()->Show();
858 NavigateAndCommitActiveTabWithTitle(browser.get(), GURL(url),
859 ASCIIToUTF16(title));
860 return browser.Pass();
863 // Creates a running V1 application.
864 // Note that with the use of the app_tab_helper as done below, this is only
865 // usable with a single v1 application.
866 V1App* CreateRunningV1App(Profile* profile,
867 const std::string& app_name,
868 const std::string& url) {
869 V1App* v1_app = new V1App(profile, app_name);
870 // Create a new app tab helper and assign it to the launcher so that this
871 // app gets properly detected.
872 // TODO(skuhne): Create a more intelligent app tab helper which is able to
873 // detect all running apps properly.
874 TestAppTabHelperImpl* app_tab_helper = new TestAppTabHelperImpl;
875 app_tab_helper->SetAppID(
876 v1_app->browser()->tab_strip_model()->GetWebContentsAt(0),
877 app_name);
878 SetAppTabHelper(app_tab_helper);
880 NavigateAndCommitActiveTabWithTitle(
881 v1_app->browser(), GURL(url), ASCIIToUTF16(""));
882 return v1_app;
885 ash::test::TestSessionStateDelegate* session_delegate() {
886 return static_cast<ash::test::TestSessionStateDelegate*>(
887 ash::Shell::GetInstance()->session_state_delegate());
889 ash::test::TestShellDelegate* shell_delegate() { return shell_delegate_; }
891 // Override BrowserWithTestWindowTest:
892 TestingProfile* CreateProfile() override {
893 return CreateMultiUserProfile("user1");
895 void DestroyProfile(TestingProfile* profile) override {
896 // Delete the profile through our profile manager.
897 ProfileToNameMap::iterator it = created_profiles_.find(profile);
898 DCHECK(it != created_profiles_.end());
899 profile_manager_->DeleteTestingProfile(it->second);
900 created_profiles_.erase(it);
903 private:
904 typedef std::map<Profile*, std::string> ProfileToNameMap;
905 TestingProfileManager* profile_manager() { return profile_manager_.get(); }
907 chromeos::FakeChromeUserManager* GetFakeUserManager() {
908 return static_cast<chromeos::FakeChromeUserManager*>(
909 user_manager::UserManager::Get());
912 scoped_ptr<TestingProfileManager> profile_manager_;
913 scoped_ptr<chromeos::ScopedUserManagerEnabler> user_manager_enabler_;
915 ash::test::TestShellDelegate* shell_delegate_;
917 ProfileToNameMap created_profiles_;
919 DISALLOW_COPY_AND_ASSIGN(
920 MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest);
922 #endif // defined(OS_CHROMEOS)
925 TEST_F(ChromeLauncherControllerTest, DefaultApps) {
926 InitLauncherController();
927 // Model should only contain the browser shortcut and app list items.
928 EXPECT_EQ(2, model_->item_count());
929 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
930 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
931 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
933 // Installing |extension3_| should add it to the launcher - behind the
934 // chrome icon.
935 extension_service_->AddExtension(extension3_.get());
936 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
937 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
938 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
941 // Check that the restauration of launcher items is happening in the same order
942 // as the user has pinned them (on another system) when they are synced reverse
943 // order.
944 TEST_F(ChromeLauncherControllerTest, RestoreDefaultAppsReverseOrder) {
945 InitLauncherController();
947 base::ListValue policy_value;
948 InsertPrefValue(&policy_value, 0, extension1_->id());
949 InsertPrefValue(&policy_value, 1, extension2_->id());
950 InsertPrefValue(&policy_value, 2, extension3_->id());
951 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
952 policy_value.DeepCopy());
953 SetShelfChromeIconIndex(0);
954 // Model should only contain the browser shortcut and app list items.
955 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
956 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
957 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
958 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
960 // Installing |extension3_| should add it to the shelf - behind the
961 // chrome icon.
962 ash::ShelfItem item;
963 extension_service_->AddExtension(extension3_.get());
964 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
965 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
966 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
968 // Installing |extension2_| should add it to the launcher - behind the
969 // chrome icon, but in first location.
970 extension_service_->AddExtension(extension2_.get());
971 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
972 EXPECT_EQ("AppList, Chrome, App2, App3", GetPinnedAppStatus());
974 // Installing |extension1_| should add it to the launcher - behind the
975 // chrome icon, but in first location.
976 extension_service_->AddExtension(extension1_.get());
977 EXPECT_EQ("AppList, Chrome, App1, App2, App3", GetPinnedAppStatus());
980 // Check that the restauration of launcher items is happening in the same order
981 // as the user has pinned them (on another system) when they are synced random
982 // order.
983 TEST_F(ChromeLauncherControllerTest, RestoreDefaultAppsRandomOrder) {
984 InitLauncherController();
986 base::ListValue policy_value;
987 InsertPrefValue(&policy_value, 0, extension1_->id());
988 InsertPrefValue(&policy_value, 1, extension2_->id());
989 InsertPrefValue(&policy_value, 2, extension3_->id());
990 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
991 policy_value.DeepCopy());
992 SetShelfChromeIconIndex(0);
993 // Model should only contain the browser shortcut and app list items.
994 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
995 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
996 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
997 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
999 // Installing |extension2_| should add it to the launcher - behind the
1000 // chrome icon.
1001 extension_service_->AddExtension(extension2_.get());
1002 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1003 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1004 EXPECT_EQ("AppList, Chrome, App2", GetPinnedAppStatus());
1006 // Installing |extension1_| should add it to the launcher - behind the
1007 // chrome icon, but in first location.
1008 extension_service_->AddExtension(extension1_.get());
1009 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1010 EXPECT_EQ("AppList, Chrome, App1, App2", GetPinnedAppStatus());
1012 // Installing |extension3_| should add it to the launcher - behind the
1013 // chrome icon, but in first location.
1014 extension_service_->AddExtension(extension3_.get());
1015 EXPECT_EQ("AppList, Chrome, App1, App2, App3", GetPinnedAppStatus());
1018 // Check that the restauration of launcher items is happening in the same order
1019 // as the user has pinned / moved them (on another system) when they are synced
1020 // random order - including the chrome icon.
1021 TEST_F(ChromeLauncherControllerTest, RestoreDefaultAppsRandomOrderChromeMoved) {
1022 InitLauncherController();
1024 base::ListValue policy_value;
1025 InsertPrefValue(&policy_value, 0, extension1_->id());
1026 InsertPrefValue(&policy_value, 1, extension2_->id());
1027 InsertPrefValue(&policy_value, 2, extension3_->id());
1028 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1029 policy_value.DeepCopy());
1030 SetShelfChromeIconIndex(1);
1031 // Model should only contain the browser shortcut and app list items.
1032 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1033 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1034 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1035 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
1037 // Installing |extension2_| should add it to the shelf - behind the
1038 // chrome icon.
1039 ash::ShelfItem item;
1040 extension_service_->AddExtension(extension2_.get());
1041 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1042 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1043 EXPECT_EQ("AppList, Chrome, App2", GetPinnedAppStatus());
1045 // Installing |extension1_| should add it to the launcher - behind the
1046 // chrome icon, but in first location.
1047 extension_service_->AddExtension(extension1_.get());
1048 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1049 EXPECT_EQ("AppList, App1, Chrome, App2", GetPinnedAppStatus());
1051 // Installing |extension3_| should add it to the launcher - behind the
1052 // chrome icon, but in first location.
1053 extension_service_->AddExtension(extension3_.get());
1054 EXPECT_EQ("AppList, App1, Chrome, App2, App3", GetPinnedAppStatus());
1057 // Check that syncing to a different state does the correct thing.
1058 TEST_F(ChromeLauncherControllerTest, RestoreDefaultAppsResyncOrder) {
1059 InitLauncherController();
1060 base::ListValue policy_value;
1061 InsertPrefValue(&policy_value, 0, extension1_->id());
1062 InsertPrefValue(&policy_value, 1, extension2_->id());
1063 InsertPrefValue(&policy_value, 2, extension3_->id());
1064 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1065 policy_value.DeepCopy());
1066 // The shelf layout has always one static item at the beginning (App List).
1067 SetShelfChromeIconIndex(0);
1068 extension_service_->AddExtension(extension2_.get());
1069 EXPECT_EQ("AppList, Chrome, App2", GetPinnedAppStatus());
1070 extension_service_->AddExtension(extension1_.get());
1071 EXPECT_EQ("AppList, Chrome, App1, App2", GetPinnedAppStatus());
1072 extension_service_->AddExtension(extension3_.get());
1073 EXPECT_EQ("AppList, Chrome, App1, App2, App3", GetPinnedAppStatus());
1075 // Change the order with increasing chrome position and decreasing position.
1076 base::ListValue policy_value1;
1077 InsertPrefValue(&policy_value1, 0, extension3_->id());
1078 InsertPrefValue(&policy_value1, 1, extension1_->id());
1079 InsertPrefValue(&policy_value1, 2, extension2_->id());
1080 SetShelfChromeIconIndex(3);
1081 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1082 policy_value1.DeepCopy());
1083 EXPECT_EQ("AppList, App3, App1, App2, Chrome", GetPinnedAppStatus());
1084 base::ListValue policy_value2;
1085 InsertPrefValue(&policy_value2, 0, extension2_->id());
1086 InsertPrefValue(&policy_value2, 1, extension3_->id());
1087 InsertPrefValue(&policy_value2, 2, extension1_->id());
1088 SetShelfChromeIconIndex(2);
1089 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1090 policy_value2.DeepCopy());
1091 EXPECT_EQ("AppList, App2, App3, Chrome, App1", GetPinnedAppStatus());
1093 // Check that the chrome icon can also be at the first possible location.
1094 SetShelfChromeIconIndex(0);
1095 base::ListValue policy_value3;
1096 InsertPrefValue(&policy_value3, 0, extension3_->id());
1097 InsertPrefValue(&policy_value3, 1, extension2_->id());
1098 InsertPrefValue(&policy_value3, 2, extension1_->id());
1099 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1100 policy_value3.DeepCopy());
1101 EXPECT_EQ("AppList, Chrome, App3, App2, App1", GetPinnedAppStatus());
1103 // Check that unloading of extensions works as expected.
1104 extension_service_->UnloadExtension(extension1_->id(),
1105 UnloadedExtensionInfo::REASON_UNINSTALL);
1106 EXPECT_EQ("AppList, Chrome, App3, App2", GetPinnedAppStatus());
1108 extension_service_->UnloadExtension(extension2_->id(),
1109 UnloadedExtensionInfo::REASON_UNINSTALL);
1110 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
1112 // Check that an update of an extension does not crash the system.
1113 extension_service_->UnloadExtension(extension3_->id(),
1114 UnloadedExtensionInfo::REASON_UPDATE);
1115 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
1118 // Check that simple locking of an application will 'create' a launcher item.
1119 TEST_F(ChromeLauncherControllerTest, CheckLockApps) {
1120 InitLauncherController();
1121 // Model should only contain the browser shortcut and app list items.
1122 EXPECT_EQ(2, model_->item_count());
1123 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1124 EXPECT_FALSE(
1125 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1126 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1127 EXPECT_FALSE(
1128 launcher_controller_->IsWindowedAppInLauncher(extension2_->id()));
1130 launcher_controller_->LockV1AppWithID(extension1_->id());
1132 EXPECT_EQ(3, model_->item_count());
1133 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type);
1134 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1135 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1136 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1137 EXPECT_FALSE(
1138 launcher_controller_->IsWindowedAppInLauncher(extension2_->id()));
1140 launcher_controller_->UnlockV1AppWithID(extension1_->id());
1142 EXPECT_EQ(2, model_->item_count());
1143 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1144 EXPECT_FALSE(
1145 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1146 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1147 EXPECT_FALSE(
1148 launcher_controller_->IsWindowedAppInLauncher(extension2_->id()));
1151 // Check that multiple locks of an application will be properly handled.
1152 TEST_F(ChromeLauncherControllerTest, CheckMultiLockApps) {
1153 InitLauncherController();
1154 // Model should only contain the browser shortcut and app list items.
1155 EXPECT_EQ(2, model_->item_count());
1156 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1157 EXPECT_FALSE(
1158 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1160 for (int i = 0; i < 2; i++) {
1161 launcher_controller_->LockV1AppWithID(extension1_->id());
1163 EXPECT_EQ(3, model_->item_count());
1164 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type);
1165 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1166 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(
1167 extension1_->id()));
1170 launcher_controller_->UnlockV1AppWithID(extension1_->id());
1172 EXPECT_EQ(3, model_->item_count());
1173 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type);
1174 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1175 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1177 launcher_controller_->UnlockV1AppWithID(extension1_->id());
1179 EXPECT_EQ(2, model_->item_count());
1180 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1181 EXPECT_FALSE(
1182 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1183 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1184 EXPECT_FALSE(
1185 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1188 // Check that already pinned items are not effected by locks.
1189 TEST_F(ChromeLauncherControllerTest, CheckAlreadyPinnedLockApps) {
1190 InitLauncherController();
1191 // Model should only contain the browser shortcut and app list items.
1192 EXPECT_EQ(2, model_->item_count());
1193 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1194 EXPECT_FALSE(
1195 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1197 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1198 launcher_controller_->PinAppWithID(extension1_->id());
1199 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1201 EXPECT_EQ(3, model_->item_count());
1202 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1203 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1204 EXPECT_FALSE(
1205 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1207 launcher_controller_->LockV1AppWithID(extension1_->id());
1209 EXPECT_EQ(3, model_->item_count());
1210 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1211 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1212 EXPECT_FALSE(
1213 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1215 launcher_controller_->UnlockV1AppWithID(extension1_->id());
1217 EXPECT_EQ(3, model_->item_count());
1218 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1219 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1220 EXPECT_FALSE(
1221 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1223 launcher_controller_->UnpinAppWithID(extension1_->id());
1225 EXPECT_EQ(2, model_->item_count());
1228 // Check that already pinned items which get locked stay after unpinning.
1229 TEST_F(ChromeLauncherControllerTest, CheckPinnedAppsStayAfterUnlock) {
1230 InitLauncherController();
1231 // Model should only contain the browser shortcut and app list items.
1232 EXPECT_EQ(2, model_->item_count());
1233 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1234 EXPECT_FALSE(
1235 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1237 launcher_controller_->PinAppWithID(extension1_->id());
1239 EXPECT_EQ(3, model_->item_count());
1240 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1241 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1242 EXPECT_FALSE(
1243 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1245 launcher_controller_->LockV1AppWithID(extension1_->id());
1247 EXPECT_EQ(3, model_->item_count());
1248 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1249 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1250 EXPECT_FALSE(
1251 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1253 launcher_controller_->UnpinAppWithID(extension1_->id());
1255 EXPECT_EQ(3, model_->item_count());
1256 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type);
1257 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1258 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1260 launcher_controller_->UnlockV1AppWithID(extension1_->id());
1262 EXPECT_EQ(2, model_->item_count());
1265 #if defined(OS_CHROMEOS)
1266 // Check that running applications wich are not pinned get properly restored
1267 // upon user change.
1268 TEST_F(ChromeLauncherControllerTest, CheckRunningAppOrder) {
1269 InitLauncherController();
1270 // Model should only contain the browser shortcut and app list items.
1271 EXPECT_EQ(2, model_->item_count());
1273 // Add a few running applications.
1274 launcher_controller_->LockV1AppWithID(extension1_->id());
1275 launcher_controller_->LockV1AppWithID(extension2_->id());
1276 launcher_controller_->LockV1AppWithID(extension3_->id());
1277 EXPECT_EQ(5, model_->item_count());
1278 // Note that this not only checks the order of applications but also the
1279 // running type.
1280 EXPECT_EQ("AppList, Chrome, app1, app2, app3", GetPinnedAppStatus());
1282 // Remember the current order of applications for the current user.
1283 const std::string& current_user_id =
1284 multi_user_util::GetUserIDFromProfile(profile());
1285 RememberUnpinnedRunningApplicationOrder();
1287 // Switch some items and check that restoring a user which was not yet
1288 // remembered changes nothing.
1289 model_->Move(2, 3);
1290 EXPECT_EQ("AppList, Chrome, app2, app1, app3", GetPinnedAppStatus());
1291 RestoreUnpinnedRunningApplicationOrder("second-fake-user@fake.com");
1292 EXPECT_EQ("AppList, Chrome, app2, app1, app3", GetPinnedAppStatus());
1294 // Restoring the stored user should however do the right thing.
1295 RestoreUnpinnedRunningApplicationOrder(current_user_id);
1296 EXPECT_EQ("AppList, Chrome, app1, app2, app3", GetPinnedAppStatus());
1298 // Switch again some items and even delete one - making sure that the missing
1299 // item gets properly handled.
1300 model_->Move(3, 4);
1301 launcher_controller_->UnlockV1AppWithID(extension1_->id());
1302 EXPECT_EQ("AppList, Chrome, app3, app2", GetPinnedAppStatus());
1303 RestoreUnpinnedRunningApplicationOrder(current_user_id);
1304 EXPECT_EQ("AppList, Chrome, app2, app3", GetPinnedAppStatus());
1306 // Check that removing more items does not crash and changes nothing.
1307 launcher_controller_->UnlockV1AppWithID(extension2_->id());
1308 RestoreUnpinnedRunningApplicationOrder(current_user_id);
1309 EXPECT_EQ("AppList, Chrome, app3", GetPinnedAppStatus());
1310 launcher_controller_->UnlockV1AppWithID(extension3_->id());
1311 RestoreUnpinnedRunningApplicationOrder(current_user_id);
1312 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
1315 // Check that with multi profile V1 apps are properly added / removed from the
1316 // shelf.
1317 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
1318 V1AppUpdateOnUserSwitch) {
1319 // Create a browser item in the LauncherController.
1320 InitLauncherController();
1321 EXPECT_EQ(2, model_->item_count());
1323 // Create a "windowed gmail app".
1324 scoped_ptr<V1App> v1_app(CreateRunningV1App(
1325 profile(), extension_misc::kGmailAppId, gmail_url));
1326 EXPECT_EQ(3, model_->item_count());
1328 // After switching to a second user the item should be gone.
1329 std::string user2 = "user2";
1330 TestingProfile* profile2 = CreateMultiUserProfile(user2);
1331 SwitchActiveUser(profile2->GetProfileUserName());
1332 EXPECT_EQ(2, model_->item_count());
1334 // After switching back the item should be back.
1335 SwitchActiveUser(profile()->GetProfileUserName());
1336 EXPECT_EQ(3, model_->item_count());
1337 // Note we destroy now the gmail app with the closure end.
1339 EXPECT_EQ(2, model_->item_count());
1342 // Check edge cases with multi profile V1 apps in the shelf.
1343 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
1344 V1AppUpdateOnUserSwitchEdgecases) {
1345 // Create a browser item in the LauncherController.
1346 InitLauncherController();
1348 // First test: Create an app when the user is not active.
1349 std::string user2 = "user2";
1350 TestingProfile* profile2 = CreateMultiUserProfile(user2);
1352 // Create a "windowed gmail app".
1353 scoped_ptr<V1App> v1_app(CreateRunningV1App(
1354 profile2, extension_misc::kGmailAppId, gmail_url));
1355 EXPECT_EQ(2, model_->item_count());
1357 // However - switching to the user should show it.
1358 SwitchActiveUser(profile2->GetProfileUserName());
1359 EXPECT_EQ(3, model_->item_count());
1361 // Second test: Remove the app when the user is not active and see that it
1362 // works.
1363 SwitchActiveUser(profile()->GetProfileUserName());
1364 EXPECT_EQ(2, model_->item_count());
1365 // Note: the closure ends and the browser will go away.
1367 EXPECT_EQ(2, model_->item_count());
1368 SwitchActiveUser(profile2->GetProfileUserName());
1369 EXPECT_EQ(2, model_->item_count());
1370 SwitchActiveUser(profile()->GetProfileUserName());
1371 EXPECT_EQ(2, model_->item_count());
1374 // Check edge case where a visiting V1 app gets closed (crbug.com/321374).
1375 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
1376 V1CloseOnVisitingDesktop) {
1377 // Create a browser item in the LauncherController.
1378 InitLauncherController();
1380 chrome::MultiUserWindowManager* manager =
1381 chrome::MultiUserWindowManager::GetInstance();
1383 // First create an app when the user is active.
1384 std::string user2 = "user2";
1385 TestingProfile* profile2 = CreateMultiUserProfile(user2);
1387 // Create a "windowed gmail app".
1388 scoped_ptr<V1App> v1_app(CreateRunningV1App(
1389 profile(),
1390 extension_misc::kGmailAppId,
1391 kGmailLaunchURL));
1392 EXPECT_EQ(3, model_->item_count());
1394 // Transfer the app to the other screen and switch users.
1395 manager->ShowWindowForUser(v1_app->browser()->window()->GetNativeWindow(),
1396 user2);
1397 EXPECT_EQ(3, model_->item_count());
1398 SwitchActiveUser(profile2->GetProfileUserName());
1399 EXPECT_EQ(2, model_->item_count());
1401 // After the app was destroyed, switch back. (which caused already a crash).
1402 SwitchActiveUser(profile()->GetProfileUserName());
1404 // Create the same app again - which was also causing the crash.
1405 EXPECT_EQ(2, model_->item_count());
1407 // Create a "windowed gmail app".
1408 scoped_ptr<V1App> v1_app(CreateRunningV1App(
1409 profile(),
1410 extension_misc::kGmailAppId,
1411 kGmailLaunchURL));
1412 EXPECT_EQ(3, model_->item_count());
1414 SwitchActiveUser(profile2->GetProfileUserName());
1415 EXPECT_EQ(2, model_->item_count());
1418 // Check edge cases with multi profile V1 apps in the shelf.
1419 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
1420 V1AppUpdateOnUserSwitchEdgecases2) {
1421 // Create a browser item in the LauncherController.
1422 InitLauncherController();
1423 TestAppTabHelperImpl* app_tab_helper = new TestAppTabHelperImpl;
1424 SetAppTabHelper(app_tab_helper);
1426 // First test: Create an app when the user is not active.
1427 std::string user2 = "user2";
1428 TestingProfile* profile2 = CreateMultiUserProfile(user2);
1429 SwitchActiveUser(profile2->GetProfileUserName());
1431 // Create a "windowed gmail app".
1432 scoped_ptr<V1App> v1_app(CreateRunningV1App(
1433 profile(), extension_misc::kGmailAppId, gmail_url));
1434 EXPECT_EQ(2, model_->item_count());
1436 // However - switching to the user should show it.
1437 SwitchActiveUser(profile()->GetProfileUserName());
1438 EXPECT_EQ(3, model_->item_count());
1440 // Second test: Remove the app when the user is not active and see that it
1441 // works.
1442 SwitchActiveUser(profile2->GetProfileUserName());
1443 EXPECT_EQ(2, model_->item_count());
1444 v1_app.reset();
1446 EXPECT_EQ(2, model_->item_count());
1447 SwitchActiveUser(profile()->GetProfileUserName());
1448 EXPECT_EQ(2, model_->item_count());
1449 SwitchActiveUser(profile2->GetProfileUserName());
1450 EXPECT_EQ(2, model_->item_count());
1453 // Check that activating an item which is on another user's desktop, will bring
1454 // it back.
1455 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
1456 TestLauncherActivationPullsBackWindow) {
1457 // Create a browser item in the LauncherController.
1458 InitLauncherController();
1459 chrome::MultiUserWindowManager* manager =
1460 chrome::MultiUserWindowManager::GetInstance();
1462 // Create a second test profile. The first is the one in profile() created in
1463 // BrowserWithTestWindowTest::SetUp().
1464 // No need to add the profiles to the MultiUserWindowManager here.
1465 // CreateMultiUserProfile() already does that.
1466 TestingProfile* profile2 = CreateMultiUserProfile("user2");
1467 const std::string& current_user =
1468 multi_user_util::GetUserIDFromProfile(profile());
1470 // Create a browser window with a native window for the current user.
1471 Browser::CreateParams params(profile(), chrome::HOST_DESKTOP_TYPE_ASH);
1472 scoped_ptr<Browser> browser(
1473 chrome::CreateBrowserWithAuraTestWindowForParams(nullptr, &params));
1474 BrowserWindow* browser_window = browser->window();
1475 aura::Window* window = browser_window->GetNativeWindow();
1476 manager->SetWindowOwner(window, current_user);
1478 // Check that an activation of the window on its owner's desktop does not
1479 // change the visibility to another user.
1480 launcher_controller_->ActivateWindowOrMinimizeIfActive(browser_window, false);
1481 EXPECT_TRUE(manager->IsWindowOnDesktopOfUser(window, current_user));
1483 // Transfer the window to another user's desktop and check that activating it
1484 // does pull it back to that user.
1485 manager->ShowWindowForUser(window,
1486 multi_user_util::GetUserIDFromProfile(profile2));
1487 EXPECT_FALSE(manager->IsWindowOnDesktopOfUser(window, current_user));
1488 launcher_controller_->ActivateWindowOrMinimizeIfActive(browser_window, false);
1489 EXPECT_TRUE(manager->IsWindowOnDesktopOfUser(window, current_user));
1491 #endif
1493 // Check that lock -> pin -> unlock -> unpin does properly transition.
1494 TEST_F(ChromeLauncherControllerTest, CheckLockPinUnlockUnpin) {
1495 InitLauncherController();
1496 // Model should only contain the browser shortcut and app list items.
1497 EXPECT_EQ(2, model_->item_count());
1498 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1499 EXPECT_FALSE(
1500 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1502 launcher_controller_->LockV1AppWithID(extension1_->id());
1504 EXPECT_EQ(3, model_->item_count());
1505 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type);
1506 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1507 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1509 launcher_controller_->PinAppWithID(extension1_->id());
1511 EXPECT_EQ(3, model_->item_count());
1512 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1513 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1514 EXPECT_FALSE(
1515 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1517 launcher_controller_->UnlockV1AppWithID(extension1_->id());
1519 EXPECT_EQ(3, model_->item_count());
1520 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1521 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1522 EXPECT_FALSE(
1523 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1525 launcher_controller_->UnpinAppWithID(extension1_->id());
1527 EXPECT_EQ(2, model_->item_count());
1530 // Check that a locked (windowed V1 application) will be properly converted
1531 // between locked and pinned when the order gets changed through a profile /
1532 // policy change.
1533 TEST_F(ChromeLauncherControllerTest, RestoreDefaultAndLockedAppsResyncOrder) {
1534 InitLauncherController();
1535 base::ListValue policy_value0;
1536 InsertPrefValue(&policy_value0, 0, extension1_->id());
1537 InsertPrefValue(&policy_value0, 1, extension3_->id());
1538 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1539 policy_value0.DeepCopy());
1540 // The shelf layout has always one static item at the beginning (App List).
1541 SetShelfChromeIconIndex(0);
1542 extension_service_->AddExtension(extension1_.get());
1543 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1544 extension_service_->AddExtension(extension2_.get());
1545 // No new app icon will be generated.
1546 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1547 // Add the app as locked app which will add it (un-pinned).
1548 launcher_controller_->LockV1AppWithID(extension2_->id());
1549 EXPECT_EQ("AppList, Chrome, App1, app2", GetPinnedAppStatus());
1550 extension_service_->AddExtension(extension3_.get());
1551 EXPECT_EQ("AppList, Chrome, App1, App3, app2", GetPinnedAppStatus());
1553 // Now request to pin all items which should convert the locked item into a
1554 // pinned item.
1555 base::ListValue policy_value1;
1556 InsertPrefValue(&policy_value1, 0, extension3_->id());
1557 InsertPrefValue(&policy_value1, 1, extension2_->id());
1558 InsertPrefValue(&policy_value1, 2, extension1_->id());
1559 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1560 policy_value1.DeepCopy());
1561 EXPECT_EQ("AppList, Chrome, App3, App2, App1", GetPinnedAppStatus());
1563 // Going back to a status where there is no requirement for app 2 to be pinned
1564 // should convert it back to locked but not pinned and state. The position
1565 // is determined by the |ShelfModel|'s weight system and since running
1566 // applications are not allowed to be mixed with shortcuts, it should show up
1567 // at the end of the list.
1568 base::ListValue policy_value2;
1569 InsertPrefValue(&policy_value2, 0, extension3_->id());
1570 InsertPrefValue(&policy_value2, 1, extension1_->id());
1571 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1572 policy_value2.DeepCopy());
1573 EXPECT_EQ("AppList, Chrome, App3, App1, app2", GetPinnedAppStatus());
1575 // Removing an item should simply close it and everything should shift.
1576 base::ListValue policy_value3;
1577 InsertPrefValue(&policy_value3, 0, extension3_->id());
1578 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1579 policy_value3.DeepCopy());
1580 EXPECT_EQ("AppList, Chrome, App3, app2", GetPinnedAppStatus());
1583 // Check that a running and not pinned V2 application will be properly converted
1584 // between locked and pinned when the order gets changed through a profile /
1585 // policy change.
1586 TEST_F(ChromeLauncherControllerTest,
1587 RestoreDefaultAndRunningV2AppsResyncOrder) {
1588 InitLauncherController();
1589 base::ListValue policy_value0;
1590 InsertPrefValue(&policy_value0, 0, extension1_->id());
1591 InsertPrefValue(&policy_value0, 1, extension3_->id());
1592 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1593 policy_value0.DeepCopy());
1594 // The shelf layout has always one static item at the beginning (app List).
1595 SetShelfChromeIconIndex(0);
1596 extension_service_->AddExtension(extension1_.get());
1597 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1598 extension_service_->AddExtension(extension2_.get());
1599 // No new app icon will be generated.
1600 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1601 // Add the app as an unpinned but running V2 app.
1602 CreateRunningV2App(extension2_->id());
1603 EXPECT_EQ("AppList, Chrome, App1, *app2", GetPinnedAppStatus());
1604 extension_service_->AddExtension(extension3_.get());
1605 EXPECT_EQ("AppList, Chrome, App1, App3, *app2", GetPinnedAppStatus());
1607 // Now request to pin all items which should convert the locked item into a
1608 // pinned item.
1609 base::ListValue policy_value1;
1610 InsertPrefValue(&policy_value1, 0, extension3_->id());
1611 InsertPrefValue(&policy_value1, 1, extension2_->id());
1612 InsertPrefValue(&policy_value1, 2, extension1_->id());
1613 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1614 policy_value1.DeepCopy());
1615 EXPECT_EQ("AppList, Chrome, App3, App2, App1", GetPinnedAppStatus());
1617 // Going back to a status where there is no requirement for app 2 to be pinned
1618 // should convert it back to running V2 app. Since the position is determined
1619 // by the |ShelfModel|'s weight system, it will be after last pinned item.
1620 base::ListValue policy_value2;
1621 InsertPrefValue(&policy_value2, 0, extension3_->id());
1622 InsertPrefValue(&policy_value2, 1, extension1_->id());
1623 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1624 policy_value2.DeepCopy());
1625 EXPECT_EQ("AppList, Chrome, App3, App1, *app2", GetPinnedAppStatus());
1627 // Removing an item should simply close it and everything should shift.
1628 base::ListValue policy_value3;
1629 InsertPrefValue(&policy_value3, 0, extension3_->id());
1630 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1631 policy_value3.DeepCopy());
1632 EXPECT_EQ("AppList, Chrome, App3, *app2", GetPinnedAppStatus());
1635 // Each user has a different set of applications pinned. Check that when
1636 // switching between the two users, the state gets properly set.
1637 TEST_F(ChromeLauncherControllerTest, UserSwitchIconRestore) {
1638 base::ListValue user_a;
1639 base::ListValue user_b;
1640 SetUpMultiUserScenario(&user_a, &user_b);
1641 // Show user 1.
1642 SetShelfChromeIconIndex(6);
1643 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1644 user_a.DeepCopy());
1645 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1646 GetPinnedAppStatus());
1648 // Show user 2.
1649 SetShelfChromeIconIndex(4);
1650 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1651 user_b.DeepCopy());
1653 EXPECT_EQ("AppList, App7, App8, Chrome", GetPinnedAppStatus());
1655 // Switch back to 1.
1656 SetShelfChromeIconIndex(8);
1657 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1658 user_a.DeepCopy());
1659 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1660 GetPinnedAppStatus());
1662 // Switch back to 2.
1663 SetShelfChromeIconIndex(4);
1664 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1665 user_b.DeepCopy());
1666 EXPECT_EQ("AppList, App7, App8, Chrome", GetPinnedAppStatus());
1669 // Each user has a different set of applications pinned, and one user has an
1670 // application running. Check that when switching between the two users, the
1671 // state gets properly set.
1672 TEST_F(ChromeLauncherControllerTest, UserSwitchIconRestoreWithRunningV2App) {
1673 base::ListValue user_a;
1674 base::ListValue user_b;
1675 SetUpMultiUserScenario(&user_a, &user_b);
1677 // Run App1 and assume that it is a V2 app.
1678 CreateRunningV2App(extension1_->id());
1680 // Show user 1.
1681 SetShelfChromeIconIndex(6);
1682 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1683 user_a.DeepCopy());
1684 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1685 GetPinnedAppStatus());
1687 // Show user 2.
1688 SetShelfChromeIconIndex(4);
1689 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1690 user_b.DeepCopy());
1692 EXPECT_EQ("AppList, App7, App8, Chrome, *app1", GetPinnedAppStatus());
1694 // Switch back to 1.
1695 SetShelfChromeIconIndex(8);
1696 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1697 user_a.DeepCopy());
1698 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1699 GetPinnedAppStatus());
1701 // Switch back to 2.
1702 SetShelfChromeIconIndex(4);
1703 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1704 user_b.DeepCopy());
1705 EXPECT_EQ("AppList, App7, App8, Chrome, *app1", GetPinnedAppStatus());
1708 // Each user has a different set of applications pinned, and one user has an
1709 // application running. The chrome icon is not the last item in the list.
1710 // Check that when switching between the two users, the state gets properly set.
1711 // There was once a bug associated with this.
1712 TEST_F(ChromeLauncherControllerTest,
1713 UserSwitchIconRestoreWithRunningV2AppChromeInMiddle) {
1714 base::ListValue user_a;
1715 base::ListValue user_b;
1716 SetUpMultiUserScenario(&user_a, &user_b);
1718 // Run App1 and assume that it is a V2 app.
1719 CreateRunningV2App(extension1_->id());
1721 // Show user 1.
1722 SetShelfChromeIconIndex(5);
1723 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1724 user_a.DeepCopy());
1725 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, Chrome, App6",
1726 GetPinnedAppStatus());
1728 // Show user 2.
1729 SetShelfChromeIconIndex(4);
1730 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1731 user_b.DeepCopy());
1733 EXPECT_EQ("AppList, App7, App8, Chrome, *app1", GetPinnedAppStatus());
1735 // Switch back to 1.
1736 SetShelfChromeIconIndex(5);
1737 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1738 user_a.DeepCopy());
1739 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, Chrome, App6",
1740 GetPinnedAppStatus());
1743 TEST_F(ChromeLauncherControllerTest, Policy) {
1744 extension_service_->AddExtension(extension1_.get());
1745 extension_service_->AddExtension(extension3_.get());
1747 base::ListValue policy_value;
1748 InsertPrefValue(&policy_value, 0, extension1_->id());
1749 InsertPrefValue(&policy_value, 1, extension2_->id());
1750 profile()->GetTestingPrefService()->SetManagedPref(prefs::kPinnedLauncherApps,
1751 policy_value.DeepCopy());
1753 // Only |extension1_| should get pinned. |extension2_| is specified but not
1754 // installed, and |extension3_| is part of the default set, but that shouldn't
1755 // take effect when the policy override is in place.
1756 InitLauncherController();
1757 EXPECT_EQ(3, model_->item_count());
1758 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1759 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1760 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1761 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1763 // Installing |extension2_| should add it to the launcher.
1764 extension_service_->AddExtension(extension2_.get());
1765 EXPECT_EQ(4, model_->item_count());
1766 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1767 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[3].type);
1768 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1769 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension2_->id()));
1770 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1772 // Removing |extension1_| from the policy should be reflected in the launcher.
1773 policy_value.Remove(0, NULL);
1774 profile()->GetTestingPrefService()->SetManagedPref(prefs::kPinnedLauncherApps,
1775 policy_value.DeepCopy());
1776 EXPECT_EQ(3, model_->item_count());
1777 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1778 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1779 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension2_->id()));
1780 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1783 TEST_F(ChromeLauncherControllerTest, UnpinWithUninstall) {
1784 extension_service_->AddExtension(extension3_.get());
1785 extension_service_->AddExtension(extension4_.get());
1787 InitLauncherController();
1789 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
1790 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension4_->id()));
1792 extension_service_->UnloadExtension(extension3_->id(),
1793 UnloadedExtensionInfo::REASON_UNINSTALL);
1795 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1796 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension4_->id()));
1799 TEST_F(ChromeLauncherControllerTest, PrefUpdates) {
1800 extension_service_->AddExtension(extension2_.get());
1801 extension_service_->AddExtension(extension3_.get());
1802 extension_service_->AddExtension(extension4_.get());
1804 InitLauncherController();
1806 std::vector<std::string> expected_launchers;
1807 std::vector<std::string> actual_launchers;
1808 base::ListValue pref_value;
1809 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1810 pref_value.DeepCopy());
1811 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
1812 EXPECT_EQ(expected_launchers, actual_launchers);
1814 // Unavailable extensions don't create launcher items.
1815 InsertPrefValue(&pref_value, 0, extension1_->id());
1816 InsertPrefValue(&pref_value, 1, extension2_->id());
1817 InsertPrefValue(&pref_value, 2, extension4_->id());
1818 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1819 pref_value.DeepCopy());
1820 expected_launchers.push_back(extension2_->id());
1821 expected_launchers.push_back(extension4_->id());
1822 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
1823 EXPECT_EQ(expected_launchers, actual_launchers);
1825 // Redundant pref entries show up only once.
1826 InsertPrefValue(&pref_value, 2, extension3_->id());
1827 InsertPrefValue(&pref_value, 2, extension3_->id());
1828 InsertPrefValue(&pref_value, 5, extension3_->id());
1829 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1830 pref_value.DeepCopy());
1831 expected_launchers.insert(expected_launchers.begin() + 1, extension3_->id());
1832 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
1833 EXPECT_EQ(expected_launchers, actual_launchers);
1835 // Order changes are reflected correctly.
1836 pref_value.Clear();
1837 InsertPrefValue(&pref_value, 0, extension4_->id());
1838 InsertPrefValue(&pref_value, 1, extension3_->id());
1839 InsertPrefValue(&pref_value, 2, extension2_->id());
1840 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1841 pref_value.DeepCopy());
1842 std::reverse(expected_launchers.begin(), expected_launchers.end());
1843 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
1844 EXPECT_EQ(expected_launchers, actual_launchers);
1846 // Clearing works.
1847 pref_value.Clear();
1848 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1849 pref_value.DeepCopy());
1850 expected_launchers.clear();
1851 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
1852 EXPECT_EQ(expected_launchers, actual_launchers);
1855 TEST_F(ChromeLauncherControllerTest, PendingInsertionOrder) {
1856 extension_service_->AddExtension(extension1_.get());
1857 extension_service_->AddExtension(extension3_.get());
1859 InitLauncherController();
1861 base::ListValue pref_value;
1862 InsertPrefValue(&pref_value, 0, extension1_->id());
1863 InsertPrefValue(&pref_value, 1, extension2_->id());
1864 InsertPrefValue(&pref_value, 2, extension3_->id());
1865 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1866 pref_value.DeepCopy());
1868 std::vector<std::string> expected_launchers;
1869 expected_launchers.push_back(extension1_->id());
1870 expected_launchers.push_back(extension3_->id());
1871 std::vector<std::string> actual_launchers;
1873 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
1874 EXPECT_EQ(expected_launchers, actual_launchers);
1876 // Install |extension2| and verify it shows up between the other two.
1877 extension_service_->AddExtension(extension2_.get());
1878 expected_launchers.insert(expected_launchers.begin() + 1, extension2_->id());
1879 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
1880 EXPECT_EQ(expected_launchers, actual_launchers);
1883 // Checks the created menus and menu lists for correctness. It uses the given
1884 // |controller| to create the objects for the given |item| and checks the
1885 // found item count against the |expected_items|. The |title| list contains the
1886 // menu titles in the order of their appearance in the menu (not including the
1887 // application name).
1888 bool CheckMenuCreation(ChromeLauncherController* controller,
1889 const ash::ShelfItem& item,
1890 size_t expected_items,
1891 base::string16 title[],
1892 bool is_browser) {
1893 ChromeLauncherAppMenuItems items = controller->GetApplicationList(item, 0);
1894 // A new behavior has been added: Only show menus if there is at least one
1895 // item available.
1896 if (expected_items < 1 && is_browser) {
1897 EXPECT_EQ(0u, items.size());
1898 return items.size() == 0;
1900 // There should be one item in there: The title.
1901 EXPECT_EQ(expected_items + 1, items.size());
1902 EXPECT_FALSE(items[0]->IsEnabled());
1903 for (size_t i = 0; i < expected_items; i++) {
1904 EXPECT_EQ(title[i], items[1 + i]->title());
1905 // Check that the first real item has a leading separator.
1906 if (i == 1)
1907 EXPECT_TRUE(items[i]->HasLeadingSeparator());
1908 else
1909 EXPECT_FALSE(items[i]->HasLeadingSeparator());
1912 scoped_ptr<ash::ShelfMenuModel> menu(new LauncherApplicationMenuItemModel(
1913 controller->GetApplicationList(item, 0)));
1914 // The first element in the menu is a spacing separator. On some systems
1915 // (e.g. Windows) such things do not exist. As such we check the existence
1916 // and adjust dynamically.
1917 int first_item = menu->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR ? 1 : 0;
1918 int expected_menu_items = first_item +
1919 (expected_items ? (expected_items + 3) : 2);
1920 EXPECT_EQ(expected_menu_items, menu->GetItemCount());
1921 EXPECT_FALSE(menu->IsEnabledAt(first_item));
1922 if (expected_items) {
1923 EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR,
1924 menu->GetTypeAt(first_item + 1));
1926 return items.size() == expected_items + 1;
1929 // Check that browsers get reflected correctly in the launcher menu.
1930 TEST_F(ChromeLauncherControllerTest, BrowserMenuGeneration) {
1931 EXPECT_EQ(1U, chrome::GetTotalBrowserCount());
1932 chrome::NewTab(browser());
1934 InitLauncherController();
1936 // Check that the browser list is empty at this time.
1937 ash::ShelfItem item_browser;
1938 item_browser.type = ash::TYPE_BROWSER_SHORTCUT;
1939 item_browser.id =
1940 launcher_controller_->GetShelfIDForAppID(extension_misc::kChromeAppId);
1941 EXPECT_TRUE(CheckMenuCreation(
1942 launcher_controller_.get(), item_browser, 0, NULL, true));
1944 // Now make the created browser() visible by showing its browser window.
1945 browser()->window()->Show();
1946 base::string16 title1 = ASCIIToUTF16("Test1");
1947 NavigateAndCommitActiveTabWithTitle(browser(), GURL("http://test1"), title1);
1948 base::string16 one_menu_item[] = { title1 };
1950 EXPECT_TRUE(CheckMenuCreation(
1951 launcher_controller_.get(), item_browser, 1, one_menu_item, true));
1953 // Create one more browser/window and check that one more was added.
1954 scoped_ptr<Browser> browser2(
1955 CreateBrowserWithTestWindowForProfile(profile()));
1956 chrome::NewTab(browser2.get());
1957 browser2->window()->Show();
1958 base::string16 title2 = ASCIIToUTF16("Test2");
1959 NavigateAndCommitActiveTabWithTitle(browser2.get(), GURL("http://test2"),
1960 title2);
1962 // Check that the list contains now two entries - make furthermore sure that
1963 // the active item is the first entry.
1964 base::string16 two_menu_items[] = {title1, title2};
1965 EXPECT_TRUE(CheckMenuCreation(
1966 launcher_controller_.get(), item_browser, 2, two_menu_items, true));
1968 // Apparently we have to close all tabs we have.
1969 chrome::CloseTab(browser2.get());
1972 #if defined(OS_CHROMEOS)
1973 // Check the multi profile case where only user related browsers should show
1974 // up.
1975 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
1976 BrowserMenuGenerationTwoUsers) {
1977 // Create a browser item in the LauncherController.
1978 InitLauncherController();
1980 ash::ShelfItem item_browser;
1981 item_browser.type = ash::TYPE_BROWSER_SHORTCUT;
1982 item_browser.id =
1983 launcher_controller_->GetShelfIDForAppID(extension_misc::kChromeAppId);
1985 // Check that the menu is empty.
1986 chrome::NewTab(browser());
1987 EXPECT_TRUE(CheckMenuCreation(
1988 launcher_controller_.get(), item_browser, 0, NULL, true));
1990 // Show the created |browser()| by showing its window.
1991 browser()->window()->Show();
1992 base::string16 title1 = ASCIIToUTF16("Test1");
1993 NavigateAndCommitActiveTabWithTitle(browser(), GURL("http://test1"), title1);
1994 base::string16 one_menu_item1[] = { title1 };
1995 EXPECT_TRUE(CheckMenuCreation(
1996 launcher_controller_.get(), item_browser, 1, one_menu_item1, true));
1998 // Create a browser for another user and check that it is not included in the
1999 // users running browser list.
2000 std::string user2 = "user2";
2001 TestingProfile* profile2 = CreateMultiUserProfile(user2);
2002 scoped_ptr<Browser> browser2(
2003 CreateBrowserAndTabWithProfile(profile2, user2, "http://test2"));
2004 base::string16 one_menu_item2[] = { ASCIIToUTF16(user2) };
2005 EXPECT_TRUE(CheckMenuCreation(
2006 launcher_controller_.get(), item_browser, 1, one_menu_item1, true));
2008 // Switch to the other user and make sure that only that browser window gets
2009 // shown.
2010 SwitchActiveUser(profile2->GetProfileUserName());
2011 EXPECT_TRUE(CheckMenuCreation(
2012 launcher_controller_.get(), item_browser, 1, one_menu_item2, true));
2014 // Transferred browsers of other users should not show up in the list.
2015 chrome::MultiUserWindowManager::GetInstance()->ShowWindowForUser(
2016 browser()->window()->GetNativeWindow(),
2017 user2);
2018 EXPECT_TRUE(CheckMenuCreation(
2019 launcher_controller_.get(), item_browser, 1, one_menu_item2, true));
2021 chrome::CloseTab(browser2.get());
2023 #endif // defined(OS_CHROMEOS)
2025 // Check that V1 apps are correctly reflected in the launcher menu using the
2026 // refocus logic.
2027 // Note that the extension matching logic is tested by the extension system
2028 // and does not need a separate test here.
2029 TEST_F(ChromeLauncherControllerTest, V1AppMenuGeneration) {
2030 EXPECT_EQ(1U, chrome::GetTotalBrowserCount());
2031 EXPECT_EQ(0, browser()->tab_strip_model()->count());
2033 InitLauncherControllerWithBrowser();
2035 // Model should only contain the browser shortcut and app list items.
2036 EXPECT_EQ(2, model_->item_count());
2037 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
2039 // Installing |extension3_| adds it to the launcher.
2040 ash::ShelfID gmail_id = model_->next_id();
2041 extension_service_->AddExtension(extension3_.get());
2042 EXPECT_EQ(3, model_->item_count());
2043 int gmail_index = model_->ItemIndexByID(gmail_id);
2044 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[gmail_index].type);
2045 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
2046 launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(gmail_url));
2048 // Check the menu content.
2049 ash::ShelfItem item_browser;
2050 item_browser.type = ash::TYPE_BROWSER_SHORTCUT;
2051 item_browser.id =
2052 launcher_controller_->GetShelfIDForAppID(extension_misc::kChromeAppId);
2054 ash::ShelfItem item_gmail;
2055 item_gmail.type = ash::TYPE_APP_SHORTCUT;
2056 item_gmail.id = gmail_id;
2057 EXPECT_TRUE(CheckMenuCreation(
2058 launcher_controller_.get(), item_gmail, 0, NULL, false));
2060 // Set the gmail URL to a new tab.
2061 base::string16 title1 = ASCIIToUTF16("Test1");
2062 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title1);
2064 base::string16 one_menu_item[] = { title1 };
2065 EXPECT_TRUE(CheckMenuCreation(
2066 launcher_controller_.get(), item_gmail, 1, one_menu_item, false));
2068 // Create one empty tab.
2069 chrome::NewTab(browser());
2070 base::string16 title2 = ASCIIToUTF16("Test2");
2071 NavigateAndCommitActiveTabWithTitle(
2072 browser(),
2073 GURL("https://bla"),
2074 title2);
2076 // and another one with another gmail instance.
2077 chrome::NewTab(browser());
2078 base::string16 title3 = ASCIIToUTF16("Test3");
2079 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title3);
2080 base::string16 two_menu_items[] = {title1, title3};
2081 EXPECT_TRUE(CheckMenuCreation(
2082 launcher_controller_.get(), item_gmail, 2, two_menu_items, false));
2084 // Even though the item is in the V1 app list, it should also be in the
2085 // browser list.
2086 base::string16 browser_menu_item[] = {title3};
2087 EXPECT_TRUE(CheckMenuCreation(
2088 launcher_controller_.get(), item_browser, 1, browser_menu_item, false));
2090 // Test that closing of (all) the item(s) does work (and all menus get
2091 // updated properly).
2092 launcher_controller_->Close(item_gmail.id);
2094 EXPECT_TRUE(CheckMenuCreation(
2095 launcher_controller_.get(), item_gmail, 0, NULL, false));
2096 base::string16 browser_menu_item2[] = { title2 };
2097 EXPECT_TRUE(CheckMenuCreation(
2098 launcher_controller_.get(), item_browser, 1, browser_menu_item2, false));
2101 #if defined(OS_CHROMEOS)
2102 // Check the multi profile case where only user related apps should show up.
2103 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
2104 V1AppMenuGenerationTwoUsers) {
2105 // Create a browser item in the LauncherController.
2106 InitLauncherController();
2107 chrome::NewTab(browser());
2109 // Installing |extension3_| adds it to the launcher.
2110 ash::ShelfID gmail_id = model_->next_id();
2111 extension_service_->AddExtension(extension3_.get());
2112 EXPECT_EQ(3, model_->item_count());
2113 int gmail_index = model_->ItemIndexByID(gmail_id);
2114 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[gmail_index].type);
2115 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
2116 launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(gmail_url));
2118 // Check the menu content.
2119 ash::ShelfItem item_browser;
2120 item_browser.type = ash::TYPE_BROWSER_SHORTCUT;
2121 item_browser.id =
2122 launcher_controller_->GetShelfIDForAppID(extension_misc::kChromeAppId);
2124 ash::ShelfItem item_gmail;
2125 item_gmail.type = ash::TYPE_APP_SHORTCUT;
2126 item_gmail.id = gmail_id;
2127 EXPECT_TRUE(CheckMenuCreation(
2128 launcher_controller_.get(), item_gmail, 0, NULL, false));
2130 // Set the gmail URL to a new tab.
2131 base::string16 title1 = ASCIIToUTF16("Test1");
2132 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title1);
2134 base::string16 one_menu_item[] = { title1 };
2135 EXPECT_TRUE(CheckMenuCreation(
2136 launcher_controller_.get(), item_gmail, 1, one_menu_item, false));
2138 // Create a second profile and switch to that user.
2139 std::string user2 = "user2";
2140 TestingProfile* profile2 = CreateMultiUserProfile(user2);
2141 SwitchActiveUser(profile2->GetProfileUserName());
2143 // No item should have content yet.
2144 EXPECT_TRUE(CheckMenuCreation(
2145 launcher_controller_.get(), item_browser, 0, NULL, true));
2146 EXPECT_TRUE(CheckMenuCreation(
2147 launcher_controller_.get(), item_gmail, 0, NULL, false));
2149 // Transfer the browser of the first user - it should still not show up.
2150 chrome::MultiUserWindowManager::GetInstance()->ShowWindowForUser(
2151 browser()->window()->GetNativeWindow(),
2152 user2);
2154 EXPECT_TRUE(CheckMenuCreation(
2155 launcher_controller_.get(), item_browser, 0, NULL, true));
2156 EXPECT_TRUE(CheckMenuCreation(
2157 launcher_controller_.get(), item_gmail, 0, NULL, false));
2160 // Check that V2 applications are creating items properly in the launcher when
2161 // instantiated by the current user.
2162 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
2163 V2AppHandlingTwoUsers) {
2164 InitLauncherController();
2165 // Create a profile for our second user (will be destroyed by the framework).
2166 TestingProfile* profile2 = CreateMultiUserProfile("user2");
2167 // Check that there is a browser and a app launcher.
2168 EXPECT_EQ(2, model_->item_count());
2170 // Add a v2 app.
2171 V2App v2_app(profile(), extension1_.get());
2172 EXPECT_EQ(3, model_->item_count());
2174 // After switching users the item should go away.
2175 SwitchActiveUser(profile2->GetProfileUserName());
2176 EXPECT_EQ(2, model_->item_count());
2178 // And it should come back when switching back.
2179 SwitchActiveUser(profile()->GetProfileUserName());
2180 EXPECT_EQ(3, model_->item_count());
2183 // Check that V2 applications are creating items properly in edge cases:
2184 // a background user creates a V2 app, gets active and inactive again and then
2185 // deletes the app.
2186 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
2187 V2AppHandlingTwoUsersEdgeCases) {
2188 InitLauncherController();
2189 // Create a profile for our second user (will be destroyed by the framework).
2190 TestingProfile* profile2 = CreateMultiUserProfile("user2");
2191 // Check that there is a browser and a app launcher.
2192 EXPECT_EQ(2, model_->item_count());
2194 // Switch to an inactive user.
2195 SwitchActiveUser(profile2->GetProfileUserName());
2196 EXPECT_EQ(2, model_->item_count());
2198 // Add the v2 app to the inactive user and check that no item was added to
2199 // the launcher.
2201 V2App v2_app(profile(), extension1_.get());
2202 EXPECT_EQ(2, model_->item_count());
2204 // Switch to the primary user and check that the item is shown.
2205 SwitchActiveUser(profile()->GetProfileUserName());
2206 EXPECT_EQ(3, model_->item_count());
2208 // Switch to the second user and check that the item goes away - even if the
2209 // item gets closed.
2210 SwitchActiveUser(profile2->GetProfileUserName());
2211 EXPECT_EQ(2, model_->item_count());
2214 // After the application was killed there should be still 2 items.
2215 EXPECT_EQ(2, model_->item_count());
2217 // Switching then back to the default user should not show the additional item
2218 // anymore.
2219 SwitchActiveUser(profile()->GetProfileUserName());
2220 EXPECT_EQ(2, model_->item_count());
2223 // Check that V2 applications will be made visible on the target desktop if
2224 // another window of the same type got previously teleported there.
2225 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
2226 V2AppFollowsTeleportedWindow) {
2227 InitLauncherController();
2228 chrome::MultiUserWindowManager* manager =
2229 chrome::MultiUserWindowManager::GetInstance();
2231 // Create and add three users / profiles, and go to #1's desktop.
2232 TestingProfile* profile1 = CreateMultiUserProfile("user-1");
2233 TestingProfile* profile2 = CreateMultiUserProfile("user-2");
2234 TestingProfile* profile3 = CreateMultiUserProfile("user-3");
2235 SwitchActiveUser(profile1->GetProfileUserName());
2237 // A v2 app for user #1 should be shown first and get hidden when switching to
2238 // desktop #2.
2239 V2App v2_app_1(profile1, extension1_.get());
2240 EXPECT_TRUE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2241 SwitchActiveUser(profile2->GetProfileUserName());
2242 EXPECT_FALSE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2244 // Add a v2 app for user #1 while on desktop #2 should not be shown.
2245 V2App v2_app_2(profile1, extension1_.get());
2246 EXPECT_FALSE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2247 EXPECT_FALSE(v2_app_2.window()->GetNativeWindow()->IsVisible());
2249 // Teleport the app from user #1 to the desktop #2 should show it.
2250 manager->ShowWindowForUser(v2_app_1.window()->GetNativeWindow(),
2251 profile2->GetProfileUserName());
2252 EXPECT_TRUE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2253 EXPECT_FALSE(v2_app_2.window()->GetNativeWindow()->IsVisible());
2255 // Creating a new application for user #1 on desktop #2 should teleport it
2256 // there automatically.
2257 V2App v2_app_3(profile1, extension1_.get());
2258 EXPECT_TRUE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2259 EXPECT_FALSE(v2_app_2.window()->GetNativeWindow()->IsVisible());
2260 EXPECT_TRUE(v2_app_3.window()->GetNativeWindow()->IsVisible());
2262 // Switching back to desktop#1 and creating an app for user #1 should move
2263 // the app on desktop #1.
2264 SwitchActiveUser(profile1->GetProfileUserName());
2265 V2App v2_app_4(profile1, extension1_.get());
2266 EXPECT_FALSE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2267 EXPECT_TRUE(v2_app_2.window()->GetNativeWindow()->IsVisible());
2268 EXPECT_FALSE(v2_app_3.window()->GetNativeWindow()->IsVisible());
2269 EXPECT_TRUE(v2_app_4.window()->GetNativeWindow()->IsVisible());
2271 // Switching to desktop #3 and create an app for user #1 there should land on
2272 // his own desktop (#1).
2273 SwitchActiveUser(profile3->GetProfileUserName());
2274 V2App v2_app_5(profile1, extension1_.get());
2275 EXPECT_FALSE(v2_app_5.window()->GetNativeWindow()->IsVisible());
2276 SwitchActiveUser(profile1->GetProfileUserName());
2277 EXPECT_TRUE(v2_app_5.window()->GetNativeWindow()->IsVisible());
2279 // Switching to desktop #2, hiding the app window and creating an app should
2280 // teleport there automatically.
2281 SwitchActiveUser(profile2->GetProfileUserName());
2282 v2_app_1.window()->Hide();
2283 V2App v2_app_6(profile1, extension1_.get());
2284 EXPECT_FALSE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2285 EXPECT_FALSE(v2_app_2.window()->GetNativeWindow()->IsVisible());
2286 EXPECT_TRUE(v2_app_6.window()->GetNativeWindow()->IsVisible());
2289 // Check that V2 applications hide correctly on the shelf when the app window
2290 // is hidden.
2291 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
2292 V2AppHiddenWindows) {
2293 InitLauncherController();
2295 TestingProfile* profile2 = CreateMultiUserProfile("user-2");
2296 SwitchActiveUser(profile()->GetProfileUserName());
2297 EXPECT_EQ(2, model_->item_count());
2299 V2App v2_app_1(profile(), extension1_.get());
2300 EXPECT_EQ(3, model_->item_count());
2302 // Hide and show the app.
2303 v2_app_1.window()->Hide();
2304 EXPECT_EQ(2, model_->item_count());
2306 v2_app_1.window()->Show(extensions::AppWindow::SHOW_ACTIVE);
2307 EXPECT_EQ(3, model_->item_count());
2310 // Switch user, hide and show the app and switch back.
2311 SwitchActiveUser(profile2->GetProfileUserName());
2312 EXPECT_EQ(2, model_->item_count());
2314 v2_app_1.window()->Hide();
2315 EXPECT_EQ(2, model_->item_count());
2317 v2_app_1.window()->Show(extensions::AppWindow::SHOW_ACTIVE);
2318 EXPECT_EQ(2, model_->item_count());
2320 SwitchActiveUser(profile()->GetProfileUserName());
2321 EXPECT_EQ(3, model_->item_count());
2324 // Switch user, hide the app, switch back and then show it again.
2325 SwitchActiveUser(profile2->GetProfileUserName());
2326 EXPECT_EQ(2, model_->item_count());
2328 v2_app_1.window()->Hide();
2329 EXPECT_EQ(2, model_->item_count());
2331 SwitchActiveUser(profile()->GetProfileUserName());
2332 EXPECT_EQ(2, model_->item_count());
2334 v2_app_1.window()->Show(extensions::AppWindow::SHOW_ACTIVE);
2335 EXPECT_EQ(3, model_->item_count());
2338 // Create a second app, hide and show it and then hide both apps.
2339 V2App v2_app_2(profile(), extension1_.get());
2340 EXPECT_EQ(3, model_->item_count());
2342 v2_app_2.window()->Hide();
2343 EXPECT_EQ(3, model_->item_count());
2345 v2_app_2.window()->Show(extensions::AppWindow::SHOW_ACTIVE);
2346 EXPECT_EQ(3, model_->item_count());
2348 v2_app_1.window()->Hide();
2349 v2_app_2.window()->Hide();
2350 EXPECT_EQ(2, model_->item_count());
2353 #endif // defined(OS_CHROMEOS)
2355 // Checks that the generated menu list properly activates items.
2356 TEST_F(ChromeLauncherControllerTest, V1AppMenuExecution) {
2357 InitLauncherControllerWithBrowser();
2359 // Add |extension3_| to the launcher and add two items.
2360 GURL gmail = GURL("https://mail.google.com/mail/u");
2361 ash::ShelfID gmail_id = model_->next_id();
2362 extension_service_->AddExtension(extension3_.get());
2363 launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(gmail_url));
2364 base::string16 title1 = ASCIIToUTF16("Test1");
2365 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title1);
2366 chrome::NewTab(browser());
2367 base::string16 title2 = ASCIIToUTF16("Test2");
2368 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title2);
2370 // Check that the menu is properly set.
2371 ash::ShelfItem item_gmail;
2372 item_gmail.type = ash::TYPE_APP_SHORTCUT;
2373 item_gmail.id = gmail_id;
2374 base::string16 two_menu_items[] = {title1, title2};
2375 EXPECT_TRUE(CheckMenuCreation(
2376 launcher_controller_.get(), item_gmail, 2, two_menu_items, false));
2377 EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
2378 // Execute the second item in the list (which shouldn't do anything since that
2379 // item is per definition already the active tab).
2381 scoped_ptr<ash::ShelfMenuModel> menu(new LauncherApplicationMenuItemModel(
2382 launcher_controller_->GetApplicationList(item_gmail, 0)));
2383 // The first element in the menu is a spacing separator. On some systems
2384 // (e.g. Windows) such things do not exist. As such we check the existence
2385 // and adjust dynamically.
2386 int first_item =
2387 (menu->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR) ? 1 : 0;
2388 menu->ActivatedAt(first_item + 3);
2390 EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
2392 // Execute the first item.
2394 scoped_ptr<ash::ShelfMenuModel> menu(new LauncherApplicationMenuItemModel(
2395 launcher_controller_->GetApplicationList(item_gmail, 0)));
2396 int first_item =
2397 (menu->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR) ? 1 : 0;
2398 menu->ActivatedAt(first_item + 2);
2400 // Now the active tab should be the second item.
2401 EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
2404 // Checks that the generated menu list properly deletes items.
2405 TEST_F(ChromeLauncherControllerTest, V1AppMenuDeletionExecution) {
2406 InitLauncherControllerWithBrowser();
2408 // Add |extension3_| to the launcher and add two items.
2409 GURL gmail = GURL("https://mail.google.com/mail/u");
2410 ash::ShelfID gmail_id = model_->next_id();
2411 extension_service_->AddExtension(extension3_.get());
2412 launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(gmail_url));
2413 base::string16 title1 = ASCIIToUTF16("Test1");
2414 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title1);
2415 chrome::NewTab(browser());
2416 base::string16 title2 = ASCIIToUTF16("Test2");
2417 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title2);
2419 // Check that the menu is properly set.
2420 ash::ShelfItem item_gmail;
2421 item_gmail.type = ash::TYPE_APP_SHORTCUT;
2422 item_gmail.id = gmail_id;
2423 base::string16 two_menu_items[] = {title1, title2};
2424 EXPECT_TRUE(CheckMenuCreation(
2425 launcher_controller_.get(), item_gmail, 2, two_menu_items, false));
2427 int tabs = browser()->tab_strip_model()->count();
2428 // Activate the proper tab through the menu item.
2430 ChromeLauncherAppMenuItems items =
2431 launcher_controller_->GetApplicationList(item_gmail, 0);
2432 items[1]->Execute(0);
2433 EXPECT_EQ(tabs, browser()->tab_strip_model()->count());
2436 // Delete one tab through the menu item.
2438 ChromeLauncherAppMenuItems items =
2439 launcher_controller_->GetApplicationList(item_gmail, 0);
2440 items[1]->Execute(ui::EF_SHIFT_DOWN);
2441 EXPECT_EQ(--tabs, browser()->tab_strip_model()->count());
2445 // Tests that panels create launcher items correctly
2446 TEST_F(ChromeLauncherControllerTest, AppPanels) {
2447 InitLauncherControllerWithBrowser();
2448 // App list and Browser shortcut ShelfItems are added.
2449 EXPECT_EQ(2, model_observer_->added());
2451 TestAppIconLoaderImpl* app_icon_loader = new TestAppIconLoaderImpl();
2452 SetAppIconLoader(app_icon_loader);
2454 // Test adding an app panel
2455 std::string app_id = extension1_->id();
2456 AppWindowLauncherItemController* app_panel_controller =
2457 new AppWindowLauncherItemController(
2458 LauncherItemController::TYPE_APP_PANEL,
2459 "id",
2460 app_id,
2461 launcher_controller_.get());
2462 ash::ShelfID shelf_id1 = launcher_controller_->CreateAppLauncherItem(
2463 app_panel_controller, app_id, ash::STATUS_RUNNING);
2464 int panel_index = model_observer_->last_index();
2465 EXPECT_EQ(3, model_observer_->added());
2466 EXPECT_EQ(0, model_observer_->changed());
2467 EXPECT_EQ(1, app_icon_loader->fetch_count());
2468 model_observer_->clear_counts();
2470 // App panels should have a separate identifier than the app id
2471 EXPECT_EQ(0, launcher_controller_->GetShelfIDForAppID(app_id));
2473 // Setting the app image image should not change the panel if it set its icon
2474 app_panel_controller->set_image_set_by_controller(true);
2475 gfx::ImageSkia image;
2476 launcher_controller_->SetAppImage(app_id, image);
2477 EXPECT_EQ(0, model_observer_->changed());
2478 model_observer_->clear_counts();
2480 // Add a second app panel and verify that it get the same index as the first
2481 // one had, being added to the left of the existing panel.
2482 AppWindowLauncherItemController* app_panel_controller2 =
2483 new AppWindowLauncherItemController(
2484 LauncherItemController::TYPE_APP_PANEL,
2485 "id",
2486 app_id,
2487 launcher_controller_.get());
2489 ash::ShelfID shelf_id2 = launcher_controller_->CreateAppLauncherItem(
2490 app_panel_controller2, app_id, ash::STATUS_RUNNING);
2491 EXPECT_EQ(panel_index, model_observer_->last_index());
2492 EXPECT_EQ(1, model_observer_->added());
2493 model_observer_->clear_counts();
2495 launcher_controller_->CloseLauncherItem(shelf_id2);
2496 launcher_controller_->CloseLauncherItem(shelf_id1);
2497 EXPECT_EQ(2, model_observer_->removed());
2500 // Tests that the Gmail extension matches more then the app itself claims with
2501 // the manifest file.
2502 TEST_F(ChromeLauncherControllerTest, GmailMatching) {
2503 InitLauncherControllerWithBrowser();
2505 // Create a Gmail browser tab.
2506 chrome::NewTab(browser());
2507 base::string16 title = ASCIIToUTF16("Test");
2508 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title);
2509 content::WebContents* content =
2510 browser()->tab_strip_model()->GetActiveWebContents();
2512 // Check that the launcher controller does not recognize the running app.
2513 EXPECT_FALSE(launcher_controller_->ContentCanBeHandledByGmailApp(content));
2515 // Installing |extension3_| adds it to the launcher.
2516 ash::ShelfID gmail_id = model_->next_id();
2517 extension_service_->AddExtension(extension3_.get());
2518 EXPECT_EQ(3, model_->item_count());
2519 int gmail_index = model_->ItemIndexByID(gmail_id);
2520 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[gmail_index].type);
2521 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
2523 // Check that it is now handled.
2524 EXPECT_TRUE(launcher_controller_->ContentCanBeHandledByGmailApp(content));
2526 // Check also that the app has detected that properly.
2527 ash::ShelfItem item_gmail;
2528 item_gmail.type = ash::TYPE_APP_SHORTCUT;
2529 item_gmail.id = gmail_id;
2530 EXPECT_EQ(2U, launcher_controller_->GetApplicationList(item_gmail, 0).size());
2533 // Tests that the Gmail extension does not match the offline verison.
2534 TEST_F(ChromeLauncherControllerTest, GmailOfflineMatching) {
2535 InitLauncherControllerWithBrowser();
2537 // Create a Gmail browser tab.
2538 chrome::NewTab(browser());
2539 base::string16 title = ASCIIToUTF16("Test");
2540 NavigateAndCommitActiveTabWithTitle(browser(),
2541 GURL(offline_gmail_url),
2542 title);
2543 content::WebContents* content =
2544 browser()->tab_strip_model()->GetActiveWebContents();
2546 // Installing |extension3_| adds it to the launcher.
2547 ash::ShelfID gmail_id = model_->next_id();
2548 extension_service_->AddExtension(extension3_.get());
2549 EXPECT_EQ(3, model_->item_count());
2550 int gmail_index = model_->ItemIndexByID(gmail_id);
2551 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[gmail_index].type);
2552 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
2554 // The content should not be able to be handled by the app.
2555 EXPECT_FALSE(launcher_controller_->ContentCanBeHandledByGmailApp(content));
2558 // Verify that the launcher item positions are persisted and restored.
2559 TEST_F(ChromeLauncherControllerTest, PersistLauncherItemPositions) {
2560 InitLauncherController();
2562 TestAppTabHelperImpl* app_tab_helper = new TestAppTabHelperImpl;
2563 SetAppTabHelper(app_tab_helper);
2565 EXPECT_EQ(ash::TYPE_APP_LIST, model_->items()[0].type);
2566 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT, model_->items()[1].type);
2568 TabStripModel* tab_strip_model = browser()->tab_strip_model();
2569 EXPECT_EQ(0, tab_strip_model->count());
2570 chrome::NewTab(browser());
2571 chrome::NewTab(browser());
2572 EXPECT_EQ(2, tab_strip_model->count());
2573 app_tab_helper->SetAppID(tab_strip_model->GetWebContentsAt(0), "1");
2574 app_tab_helper->SetAppID(tab_strip_model->GetWebContentsAt(1), "2");
2576 EXPECT_FALSE(launcher_controller_->IsAppPinned("1"));
2577 launcher_controller_->PinAppWithID("1");
2578 EXPECT_TRUE(launcher_controller_->IsAppPinned("1"));
2579 launcher_controller_->PinAppWithID("2");
2581 EXPECT_EQ(ash::TYPE_APP_LIST, model_->items()[0].type);
2582 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT, model_->items()[1].type);
2583 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
2584 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[3].type);
2586 // Move browser shortcut item from index 1 to index 3.
2587 model_->Move(1, 3);
2588 EXPECT_EQ(ash::TYPE_APP_LIST, model_->items()[0].type);
2589 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[1].type);
2590 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
2591 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT, model_->items()[3].type);
2593 SetShelfItemDelegateManager(nullptr);
2594 launcher_controller_.reset();
2595 if (!ash::Shell::HasInstance()) {
2596 delete item_delegate_manager_;
2597 } else {
2598 // Clear already registered ShelfItemDelegate.
2599 ash::test::ShelfItemDelegateManagerTestAPI test(item_delegate_manager_);
2600 test.RemoveAllShelfItemDelegateForTest();
2602 model_.reset(new ash::ShelfModel);
2604 AddAppListLauncherItem();
2605 launcher_controller_.reset(
2606 ChromeLauncherController::CreateInstance(profile(), model_.get()));
2607 app_tab_helper = new TestAppTabHelperImpl;
2608 app_tab_helper->SetAppID(tab_strip_model->GetWebContentsAt(0), "1");
2609 app_tab_helper->SetAppID(tab_strip_model->GetWebContentsAt(1), "2");
2610 SetAppTabHelper(app_tab_helper);
2611 if (!ash::Shell::HasInstance()) {
2612 item_delegate_manager_ = new ash::ShelfItemDelegateManager(model_.get());
2613 SetShelfItemDelegateManager(item_delegate_manager_);
2615 launcher_controller_->Init();
2617 // Check ShelfItems are restored after resetting ChromeLauncherController.
2618 EXPECT_EQ(ash::TYPE_APP_LIST, model_->items()[0].type);
2619 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[1].type);
2620 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
2621 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT, model_->items()[3].type);
2624 // Verifies pinned apps are persisted and restored.
2625 TEST_F(ChromeLauncherControllerTest, PersistPinned) {
2626 InitLauncherControllerWithBrowser();
2627 size_t initial_size = model_->items().size();
2629 TabStripModel* tab_strip_model = browser()->tab_strip_model();
2630 EXPECT_EQ(1, tab_strip_model->count());
2632 TestAppTabHelperImpl* app_tab_helper = new TestAppTabHelperImpl;
2633 app_tab_helper->SetAppID(tab_strip_model->GetWebContentsAt(0), "1");
2634 SetAppTabHelper(app_tab_helper);
2636 TestAppIconLoaderImpl* app_icon_loader = new TestAppIconLoaderImpl;
2637 SetAppIconLoader(app_icon_loader);
2638 EXPECT_EQ(0, app_icon_loader->fetch_count());
2640 launcher_controller_->PinAppWithID("1");
2641 ash::ShelfID id = launcher_controller_->GetShelfIDForAppID("1");
2642 int app_index = model_->ItemIndexByID(id);
2643 EXPECT_EQ(1, app_icon_loader->fetch_count());
2644 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[app_index].type);
2645 EXPECT_TRUE(launcher_controller_->IsAppPinned("1"));
2646 EXPECT_FALSE(launcher_controller_->IsAppPinned("0"));
2647 EXPECT_EQ(initial_size + 1, model_->items().size());
2649 SetShelfItemDelegateManager(nullptr);
2650 launcher_controller_.reset();
2651 if (!ash::Shell::HasInstance()) {
2652 delete item_delegate_manager_;
2653 } else {
2654 // Clear already registered ShelfItemDelegate.
2655 ash::test::ShelfItemDelegateManagerTestAPI test(item_delegate_manager_);
2656 test.RemoveAllShelfItemDelegateForTest();
2658 model_.reset(new ash::ShelfModel);
2660 AddAppListLauncherItem();
2661 launcher_controller_.reset(
2662 ChromeLauncherController::CreateInstance(profile(), model_.get()));
2663 app_tab_helper = new TestAppTabHelperImpl;
2664 app_tab_helper->SetAppID(tab_strip_model->GetWebContentsAt(0), "1");
2665 SetAppTabHelper(app_tab_helper);
2666 app_icon_loader = new TestAppIconLoaderImpl;
2667 SetAppIconLoader(app_icon_loader);
2668 if (!ash::Shell::HasInstance()) {
2669 item_delegate_manager_ = new ash::ShelfItemDelegateManager(model_.get());
2670 SetShelfItemDelegateManager(item_delegate_manager_);
2672 launcher_controller_->Init();
2674 EXPECT_EQ(1, app_icon_loader->fetch_count());
2675 ASSERT_EQ(initial_size + 1, model_->items().size());
2676 EXPECT_TRUE(launcher_controller_->IsAppPinned("1"));
2677 EXPECT_FALSE(launcher_controller_->IsAppPinned("0"));
2678 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[app_index].type);
2680 launcher_controller_->UnpinAppWithID("1");
2681 ASSERT_EQ(initial_size, model_->items().size());