Revert of Add button to add new FSP services to Files app. (patchset #8 id:140001...
[chromium-blink-merge.git] / chrome / browser / ui / ash / launcher / chrome_launcher_controller_unittest.cc
blob871f373e78597ee17b624db33700e0c253d9a538
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_pref_service_syncable.h"
41 #include "chrome/test/base/testing_profile.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 using base::ASCIIToUTF16;
76 using extensions::Extension;
77 using extensions::Manifest;
78 using extensions::UnloadedExtensionInfo;
80 namespace {
81 const char* offline_gmail_url = "https://mail.google.com/mail/mu/u";
82 const char* gmail_url = "https://mail.google.com/mail/u";
83 const char* kGmailLaunchURL = "https://mail.google.com/mail/ca";
85 #if defined(OS_CHROMEOS)
86 // An extension prefix.
87 const char kCrxAppPrefix[] = "_crx_";
88 #endif
90 // ShelfModelObserver implementation that tracks what messages are invoked.
91 class TestShelfModelObserver : public ash::ShelfModelObserver {
92 public:
93 TestShelfModelObserver()
94 : added_(0),
95 removed_(0),
96 changed_(0) {
99 ~TestShelfModelObserver() override {}
101 // Overridden from ash::ShelfModelObserver:
102 void ShelfItemAdded(int index) override {
103 ++added_;
104 last_index_ = index;
107 void ShelfItemRemoved(int index, ash::ShelfID id) override {
108 ++removed_;
109 last_index_ = index;
112 void ShelfItemChanged(int index, const ash::ShelfItem& old_item) override {
113 ++changed_;
114 last_index_ = index;
117 void ShelfItemMoved(int start_index, int target_index) override {
118 last_index_ = target_index;
121 void ShelfStatusChanged() override {}
123 void clear_counts() {
124 added_ = 0;
125 removed_ = 0;
126 changed_ = 0;
127 last_index_ = 0;
130 int added() const { return added_; }
131 int removed() const { return removed_; }
132 int changed() const { return changed_; }
133 int last_index() const { return last_index_; }
135 private:
136 int added_;
137 int removed_;
138 int changed_;
139 int last_index_;
141 DISALLOW_COPY_AND_ASSIGN(TestShelfModelObserver);
144 // Test implementation of AppIconLoader.
145 class TestAppIconLoaderImpl : public extensions::AppIconLoader {
146 public:
147 TestAppIconLoaderImpl() : fetch_count_(0) {
150 ~TestAppIconLoaderImpl() override {}
152 // AppIconLoader implementation:
153 void FetchImage(const std::string& id) override { ++fetch_count_; }
155 void ClearImage(const std::string& id) override {}
157 void UpdateImage(const std::string& id) override {}
159 int fetch_count() const { return fetch_count_; }
161 private:
162 int fetch_count_;
164 DISALLOW_COPY_AND_ASSIGN(TestAppIconLoaderImpl);
167 // Test implementation of AppTabHelper.
168 class TestAppTabHelperImpl : public ChromeLauncherController::AppTabHelper {
169 public:
170 TestAppTabHelperImpl() {}
171 ~TestAppTabHelperImpl() override {}
173 // Sets the id for the specified tab. The id is removed if Remove() is
174 // invoked.
175 void SetAppID(content::WebContents* tab, const std::string& id) {
176 tab_id_map_[tab] = id;
179 // Returns true if there is an id registered for |tab|.
180 bool HasAppID(content::WebContents* tab) const {
181 return tab_id_map_.find(tab) != tab_id_map_.end();
184 // AppTabHelper implementation:
185 std::string GetAppID(content::WebContents* tab) override {
186 return tab_id_map_.find(tab) != tab_id_map_.end() ? tab_id_map_[tab] :
187 std::string();
190 bool IsValidIDForCurrentUser(const std::string& id) override {
191 for (TabToStringMap::const_iterator i = tab_id_map_.begin();
192 i != tab_id_map_.end(); ++i) {
193 if (i->second == id)
194 return true;
196 return false;
199 void SetCurrentUser(Profile* profile) override {
200 // We can ignore this for now.
203 private:
204 typedef std::map<content::WebContents*, std::string> TabToStringMap;
206 TabToStringMap tab_id_map_;
208 DISALLOW_COPY_AND_ASSIGN(TestAppTabHelperImpl);
211 // Test implementation of a V2 app launcher item controller.
212 class TestV2AppLauncherItemController : public LauncherItemController {
213 public:
214 TestV2AppLauncherItemController(const std::string& app_id,
215 ChromeLauncherController* controller)
216 : LauncherItemController(LauncherItemController::TYPE_APP,
217 app_id,
218 controller) {
221 ~TestV2AppLauncherItemController() override {}
223 // Override for LauncherItemController:
224 bool IsOpen() const override { return true; }
225 bool IsVisible() const override { return true; }
226 void Launch(ash::LaunchSource source, int event_flags) override {}
227 bool Activate(ash::LaunchSource source) override { return false; }
228 void Close() override {}
229 bool ItemSelected(const ui::Event& event) override { return false; }
230 base::string16 GetTitle() override { return base::string16(); }
231 ChromeLauncherAppMenuItems GetApplicationList(int event_flags) override {
232 ChromeLauncherAppMenuItems items;
233 items.push_back(
234 new ChromeLauncherAppMenuItem(base::string16(), NULL, false));
235 items.push_back(
236 new ChromeLauncherAppMenuItem(base::string16(), NULL, false));
237 return items.Pass();
239 ui::MenuModel* CreateContextMenu(aura::Window* root_window) override {
240 return NULL;
242 ash::ShelfMenuModel* CreateApplicationMenu(int event_flags) override {
243 return NULL;
245 bool IsDraggable() override { return false; }
246 bool ShouldShowTooltip() override { return false; }
248 private:
249 DISALLOW_COPY_AND_ASSIGN(TestV2AppLauncherItemController);
252 } // namespace
254 class ChromeLauncherControllerTest : public BrowserWithTestWindowTest {
255 protected:
256 ChromeLauncherControllerTest()
257 : BrowserWithTestWindowTest(
258 Browser::TYPE_TABBED,
259 chrome::HOST_DESKTOP_TYPE_ASH,
260 false),
261 test_controller_(NULL),
262 extension_service_(NULL) {
265 ~ChromeLauncherControllerTest() override {}
267 void SetUp() override {
268 BrowserWithTestWindowTest::SetUp();
270 model_.reset(new ash::ShelfModel);
271 model_observer_.reset(new TestShelfModelObserver);
272 model_->AddObserver(model_observer_.get());
274 if (ash::Shell::HasInstance()) {
275 item_delegate_manager_ =
276 ash::Shell::GetInstance()->shelf_item_delegate_manager();
277 } else {
278 item_delegate_manager_ =
279 new ash::ShelfItemDelegateManager(model_.get());
282 base::DictionaryValue manifest;
283 manifest.SetString(extensions::manifest_keys::kName,
284 "launcher controller test extension");
285 manifest.SetString(extensions::manifest_keys::kVersion, "1");
286 manifest.SetString(extensions::manifest_keys::kDescription,
287 "for testing pinned apps");
289 extensions::TestExtensionSystem* extension_system(
290 static_cast<extensions::TestExtensionSystem*>(
291 extensions::ExtensionSystem::Get(profile())));
292 extension_service_ = extension_system->CreateExtensionService(
293 base::CommandLine::ForCurrentProcess(), base::FilePath(), false);
295 std::string error;
296 extension1_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
297 manifest,
298 Extension::NO_FLAGS,
299 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
300 &error);
301 extension2_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
302 manifest,
303 Extension::NO_FLAGS,
304 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
305 &error);
306 // Fake gmail extension.
307 base::DictionaryValue manifest_gmail;
308 manifest_gmail.SetString(extensions::manifest_keys::kName,
309 "Gmail launcher controller test extension");
310 manifest_gmail.SetString(extensions::manifest_keys::kVersion, "1");
311 manifest_gmail.SetString(extensions::manifest_keys::kDescription,
312 "for testing pinned Gmail");
313 manifest_gmail.SetString(extensions::manifest_keys::kLaunchWebURL,
314 kGmailLaunchURL);
315 base::ListValue* list = new base::ListValue();
316 list->Append(new base::StringValue("*://mail.google.com/mail/ca"));
317 manifest_gmail.Set(extensions::manifest_keys::kWebURLs, list);
319 extension3_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
320 manifest_gmail,
321 Extension::NO_FLAGS,
322 extension_misc::kGmailAppId,
323 &error);
325 // Fake search extension.
326 extension4_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
327 manifest,
328 Extension::NO_FLAGS,
329 extension_misc::kGoogleSearchAppId,
330 &error);
331 extension5_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
332 manifest,
333 Extension::NO_FLAGS,
334 "cccccccccccccccccccccccccccccccc",
335 &error);
336 extension6_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
337 manifest,
338 Extension::NO_FLAGS,
339 "dddddddddddddddddddddddddddddddd",
340 &error);
341 extension7_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
342 manifest,
343 Extension::NO_FLAGS,
344 "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
345 &error);
346 extension8_ = Extension::Create(base::FilePath(), Manifest::UNPACKED,
347 manifest,
348 Extension::NO_FLAGS,
349 "ffffffffffffffffffffffffffffffff",
350 &error);
353 // Creates a running V2 app (not pinned) of type |app_id|.
354 virtual void CreateRunningV2App(const std::string& app_id) {
355 DCHECK(!test_controller_);
356 ash::ShelfID id =
357 launcher_controller_->CreateAppShortcutLauncherItemWithType(
358 app_id,
359 model_->item_count(),
360 ash::TYPE_PLATFORM_APP);
361 DCHECK(id);
362 // Change the created launcher controller into a V2 app controller.
363 test_controller_ = new TestV2AppLauncherItemController(app_id,
364 launcher_controller_.get());
365 launcher_controller_->SetItemController(id, test_controller_);
368 // Sets the stage for a multi user test.
369 virtual void SetUpMultiUserScenario(base::ListValue* user_a,
370 base::ListValue* user_b) {
371 InitLauncherController();
372 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
374 // Set an empty pinned pref to begin with.
375 base::ListValue no_user;
376 SetShelfChromeIconIndex(0);
377 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
378 no_user.DeepCopy());
379 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
381 // Assume all applications have been added already.
382 extension_service_->AddExtension(extension1_.get());
383 extension_service_->AddExtension(extension2_.get());
384 extension_service_->AddExtension(extension3_.get());
385 extension_service_->AddExtension(extension4_.get());
386 extension_service_->AddExtension(extension5_.get());
387 extension_service_->AddExtension(extension6_.get());
388 extension_service_->AddExtension(extension7_.get());
389 extension_service_->AddExtension(extension8_.get());
390 // There should be nothing in the list by now.
391 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
393 // Set user a preferences.
394 InsertPrefValue(user_a, 0, extension1_->id());
395 InsertPrefValue(user_a, 1, extension2_->id());
396 InsertPrefValue(user_a, 2, extension3_->id());
397 InsertPrefValue(user_a, 3, extension4_->id());
398 InsertPrefValue(user_a, 4, extension5_->id());
399 InsertPrefValue(user_a, 5, extension6_->id());
401 // Set user b preferences.
402 InsertPrefValue(user_b, 0, extension7_->id());
403 InsertPrefValue(user_b, 1, extension8_->id());
406 void TearDown() override {
407 launcher_controller_->SetShelfItemDelegateManagerForTest(nullptr);
408 if (!ash::Shell::HasInstance())
409 delete item_delegate_manager_;
410 model_->RemoveObserver(model_observer_.get());
411 model_observer_.reset();
412 launcher_controller_.reset();
413 model_.reset();
415 BrowserWithTestWindowTest::TearDown();
418 void AddAppListLauncherItem() {
419 ash::ShelfItem app_list;
420 app_list.type = ash::TYPE_APP_LIST;
421 model_->Add(app_list);
424 void InitLauncherController() {
425 AddAppListLauncherItem();
426 launcher_controller_.reset(
427 new ChromeLauncherController(profile(), model_.get()));
428 if (!ash::Shell::HasInstance())
429 SetShelfItemDelegateManager(item_delegate_manager_);
430 launcher_controller_->Init();
433 void InitLauncherControllerWithBrowser() {
434 InitLauncherController();
435 chrome::NewTab(browser());
436 BrowserList::SetLastActive(browser());
439 void SetAppIconLoader(extensions::AppIconLoader* loader) {
440 launcher_controller_->SetAppIconLoaderForTest(loader);
443 void SetAppTabHelper(ChromeLauncherController::AppTabHelper* helper) {
444 launcher_controller_->SetAppTabHelperForTest(helper);
447 void SetShelfItemDelegateManager(ash::ShelfItemDelegateManager* manager) {
448 launcher_controller_->SetShelfItemDelegateManagerForTest(manager);
451 void InsertPrefValue(base::ListValue* pref_value,
452 int index,
453 const std::string& extension_id) {
454 base::DictionaryValue* entry = new base::DictionaryValue();
455 entry->SetString(ash::kPinnedAppsPrefAppIDPath, extension_id);
456 pref_value->Insert(index, entry);
459 // Gets the currently configured app launchers from the controller.
460 void GetAppLaunchers(ChromeLauncherController* controller,
461 std::vector<std::string>* launchers) {
462 launchers->clear();
463 for (ash::ShelfItems::const_iterator iter(model_->items().begin());
464 iter != model_->items().end(); ++iter) {
465 ChromeLauncherController::IDToItemControllerMap::const_iterator
466 entry(controller->id_to_item_controller_map_.find(iter->id));
467 if (iter->type == ash::TYPE_APP_SHORTCUT &&
468 entry != controller->id_to_item_controller_map_.end()) {
469 launchers->push_back(entry->second->app_id());
474 // Get the setup of the currently shown launcher items in one string.
475 // Each pinned element will start with a big letter, each running but not
476 // pinned V1 app will start with a small letter and each running but not
477 // pinned V2 app will start with a '*' + small letter.
478 std::string GetPinnedAppStatus() {
479 std::string result;
480 for (int i = 0; i < model_->item_count(); i++) {
481 if (!result.empty())
482 result.append(", ");
483 switch (model_->items()[i].type) {
484 case ash::TYPE_PLATFORM_APP:
485 result+= "*";
486 // FALLTHROUGH
487 case ash::TYPE_WINDOWED_APP: {
488 const std::string& app =
489 launcher_controller_->GetAppIDForShelfID(model_->items()[i].id);
490 if (app == extension1_->id()) {
491 result += "app1";
492 EXPECT_FALSE(
493 launcher_controller_->IsAppPinned(extension1_->id()));
494 } else if (app == extension2_->id()) {
495 result += "app2";
496 EXPECT_FALSE(
497 launcher_controller_->IsAppPinned(extension2_->id()));
498 } else if (app == extension3_->id()) {
499 result += "app3";
500 EXPECT_FALSE(
501 launcher_controller_->IsAppPinned(extension3_->id()));
502 } else if (app == extension4_->id()) {
503 result += "app4";
504 EXPECT_FALSE(
505 launcher_controller_->IsAppPinned(extension4_->id()));
506 } else if (app == extension5_->id()) {
507 result += "app5";
508 EXPECT_FALSE(
509 launcher_controller_->IsAppPinned(extension5_->id()));
510 } else if (app == extension6_->id()) {
511 result += "app6";
512 EXPECT_FALSE(
513 launcher_controller_->IsAppPinned(extension6_->id()));
514 } else if (app == extension7_->id()) {
515 result += "app7";
516 EXPECT_FALSE(
517 launcher_controller_->IsAppPinned(extension7_->id()));
518 } else if (app == extension8_->id()) {
519 result += "app8";
520 EXPECT_FALSE(
521 launcher_controller_->IsAppPinned(extension8_->id()));
522 } else {
523 result += "unknown";
525 break;
527 case ash::TYPE_APP_SHORTCUT: {
528 const std::string& app =
529 launcher_controller_->GetAppIDForShelfID(model_->items()[i].id);
530 if (app == extension1_->id()) {
531 result += "App1";
532 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
533 } else if (app == extension2_->id()) {
534 result += "App2";
535 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension2_->id()));
536 } else if (app == extension3_->id()) {
537 result += "App3";
538 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
539 } else if (app == extension4_->id()) {
540 result += "App4";
541 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension4_->id()));
542 } else if (app == extension5_->id()) {
543 result += "App5";
544 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension5_->id()));
545 } else if (app == extension6_->id()) {
546 result += "App6";
547 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension6_->id()));
548 } else if (app == extension7_->id()) {
549 result += "App7";
550 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension7_->id()));
551 } else if (app == extension8_->id()) {
552 result += "App8";
553 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension8_->id()));
554 } else {
555 result += "unknown";
557 break;
559 case ash::TYPE_BROWSER_SHORTCUT:
560 result += "Chrome";
561 break;
562 case ash::TYPE_APP_LIST:
563 result += "AppList";
564 break;
565 default:
566 result += "Unknown";
567 break;
570 return result;
573 // Set the index at which the chrome icon should be.
574 void SetShelfChromeIconIndex(int index) {
575 profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex,
576 index);
579 // Remember the order of unpinned but running applications for the current
580 // user.
581 void RememberUnpinnedRunningApplicationOrder() {
582 launcher_controller_->RememberUnpinnedRunningApplicationOrder();
585 // Restore the order of running but unpinned applications for a given user.
586 void RestoreUnpinnedRunningApplicationOrder(const std::string& user_id) {
587 launcher_controller_->RestoreUnpinnedRunningApplicationOrder(user_id);
590 // Needed for extension service & friends to work.
591 scoped_refptr<Extension> extension1_;
592 scoped_refptr<Extension> extension2_;
593 scoped_refptr<Extension> extension3_;
594 scoped_refptr<Extension> extension4_;
595 scoped_refptr<Extension> extension5_;
596 scoped_refptr<Extension> extension6_;
597 scoped_refptr<Extension> extension7_;
598 scoped_refptr<Extension> extension8_;
599 scoped_ptr<ChromeLauncherController> launcher_controller_;
600 scoped_ptr<TestShelfModelObserver> model_observer_;
601 scoped_ptr<ash::ShelfModel> model_;
603 // |item_delegate_manager_| owns |test_controller_|.
604 LauncherItemController* test_controller_;
606 ExtensionService* extension_service_;
608 ash::ShelfItemDelegateManager* item_delegate_manager_;
610 private:
611 DISALLOW_COPY_AND_ASSIGN(ChromeLauncherControllerTest);
614 #if defined(OS_CHROMEOS)
615 // A browser window proxy which is able to associate an aura native window with
616 // it.
617 class TestBrowserWindowAura : public TestBrowserWindow {
618 public:
619 // |native_window| will still be owned by the caller after the constructor
620 // was called.
621 explicit TestBrowserWindowAura(aura::Window* native_window)
622 : native_window_(native_window) {
624 ~TestBrowserWindowAura() override {}
626 gfx::NativeWindow GetNativeWindow() const override {
627 return native_window_.get();
630 Browser* browser() { return browser_.get(); }
632 void CreateBrowser(const Browser::CreateParams& params) {
633 Browser::CreateParams create_params = params;
634 create_params.window = this;
635 browser_.reset(new Browser(create_params));
638 private:
639 scoped_ptr<Browser> browser_;
640 scoped_ptr<aura::Window> native_window_;
642 DISALLOW_COPY_AND_ASSIGN(TestBrowserWindowAura);
645 // Creates a test browser window which has a native window.
646 scoped_ptr<TestBrowserWindowAura> CreateTestBrowserWindow(
647 const Browser::CreateParams& params) {
648 // Create a window.
649 aura::Window* window = new aura::Window(NULL);
650 window->set_id(0);
651 window->SetType(ui::wm::WINDOW_TYPE_NORMAL);
652 window->Init(aura::WINDOW_LAYER_TEXTURED);
653 window->Show();
655 scoped_ptr<TestBrowserWindowAura> browser_window(
656 new TestBrowserWindowAura(window));
657 browser_window->CreateBrowser(params);
658 return browser_window.Pass();
661 // Watches WebContents and blocks until it is destroyed. This is needed for
662 // the destruction of a V2 application.
663 class WebContentsDestroyedWatcher : public content::WebContentsObserver {
664 public:
665 explicit WebContentsDestroyedWatcher(content::WebContents* web_contents)
666 : content::WebContentsObserver(web_contents),
667 message_loop_runner_(new content::MessageLoopRunner) {
668 EXPECT_TRUE(web_contents != NULL);
670 ~WebContentsDestroyedWatcher() override {}
672 // Waits until the WebContents is destroyed.
673 void Wait() {
674 message_loop_runner_->Run();
677 private:
678 // Overridden WebContentsObserver methods.
679 void WebContentsDestroyed() override { message_loop_runner_->Quit(); }
681 scoped_refptr<content::MessageLoopRunner> message_loop_runner_;
683 DISALLOW_COPY_AND_ASSIGN(WebContentsDestroyedWatcher);
686 // A V1 windowed application.
687 class V1App : public TestBrowserWindow {
688 public:
689 V1App(Profile* profile, const std::string& app_name) {
690 // Create a window.
691 native_window_.reset(new aura::Window(NULL));
692 native_window_->set_id(0);
693 native_window_->SetType(ui::wm::WINDOW_TYPE_POPUP);
694 native_window_->Init(aura::WINDOW_LAYER_TEXTURED);
695 native_window_->Show();
696 aura::client::ParentWindowWithContext(native_window_.get(),
697 ash::Shell::GetPrimaryRootWindow(),
698 gfx::Rect(10, 10, 20, 30));
699 Browser::CreateParams params =
700 Browser::CreateParams::CreateForApp(kCrxAppPrefix + app_name,
701 true /* trusted_source */,
702 gfx::Rect(),
703 profile,
704 chrome::HOST_DESKTOP_TYPE_ASH);
705 params.window = this;
706 browser_.reset(new Browser(params));
707 chrome::AddTabAt(browser_.get(), GURL(), 0, true);
710 ~V1App() override {
711 // close all tabs. Note that we do not need to destroy the browser itself.
712 browser_->tab_strip_model()->CloseAllTabs();
715 Browser* browser() { return browser_.get(); }
717 // TestBrowserWindow override:
718 gfx::NativeWindow GetNativeWindow() const override {
719 return native_window_.get();
722 private:
723 // The associated browser with this app.
724 scoped_ptr<Browser> browser_;
726 // The native window we use.
727 scoped_ptr<aura::Window> native_window_;
729 DISALLOW_COPY_AND_ASSIGN(V1App);
732 // A V2 application which gets created with an |extension| and for a |profile|.
733 // Upon destruction it will properly close the application.
734 class V2App {
735 public:
736 V2App(Profile* profile, const extensions::Extension* extension) {
737 window_ = new extensions::AppWindow(
738 profile,
739 new ChromeAppDelegate(make_scoped_ptr(new ScopedKeepAlive)),
740 extension);
741 extensions::AppWindow::CreateParams params =
742 extensions::AppWindow::CreateParams();
743 window_->Init(GURL(std::string()),
744 new extensions::AppWindowContentsImpl(window_), params);
747 virtual ~V2App() {
748 WebContentsDestroyedWatcher destroyed_watcher(window_->web_contents());
749 window_->GetBaseWindow()->Close();
750 destroyed_watcher.Wait();
753 extensions::AppWindow* window() { return window_; }
755 private:
756 // The app window which represents the application. Note that the window
757 // deletes itself asynchronously after window_->GetBaseWindow()->Close() gets
758 // called.
759 extensions::AppWindow* window_;
761 DISALLOW_COPY_AND_ASSIGN(V2App);
764 // The testing framework to test multi profile scenarios.
765 class MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
766 : public ChromeLauncherControllerTest {
767 protected:
768 MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest() {
771 ~MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest() override {}
773 // Overwrite the Setup function to enable multi profile and needed objects.
774 void SetUp() override {
775 profile_manager_.reset(
776 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
778 ASSERT_TRUE(profile_manager_->SetUp());
780 // AvatarMenu and multiple profiles works after user logged in.
781 profile_manager_->SetLoggedIn(true);
783 // Initialize the UserManager singleton to a fresh FakeUserManager instance.
784 user_manager_enabler_.reset(new chromeos::ScopedUserManagerEnabler(
785 new chromeos::FakeChromeUserManager));
787 // Initialize the WallpaperManager singleton.
788 chromeos::WallpaperManager::Initialize();
790 // Initialize the rest.
791 ChromeLauncherControllerTest::SetUp();
793 // Get some base objects.
794 session_delegate()->set_logged_in_users(2);
795 shell_delegate_ = static_cast<ash::test::TestShellDelegate*>(
796 ash::Shell::GetInstance()->delegate());
797 shell_delegate_->set_multi_profiles_enabled(true);
800 void TearDown() override {
801 ChromeLauncherControllerTest::TearDown();
802 user_manager_enabler_.reset();
803 for (ProfileToNameMap::iterator it = created_profiles_.begin();
804 it != created_profiles_.end(); ++it)
805 profile_manager_->DeleteTestingProfile(it->second);
806 chromeos::WallpaperManager::Shutdown();
808 // A Task is leaked if we don't destroy everything, then run the message
809 // loop.
810 base::MessageLoop::current()->PostTask(FROM_HERE,
811 base::MessageLoop::QuitClosure());
812 base::MessageLoop::current()->Run();
815 // Creates a profile for a given |user_name|. Note that this class will keep
816 // the ownership of the created object.
817 TestingProfile* CreateMultiUserProfile(const std::string& user_name) {
818 std::string email_string = user_name + "@example.com";
819 static_cast<ash::test::TestSessionStateDelegate*>(
820 ash::Shell::GetInstance()->session_state_delegate())
821 ->AddUser(email_string);
822 // Add a user to the fake user manager.
823 session_delegate()->AddUser(email_string);
824 GetFakeUserManager()->AddUser(email_string);
826 GetFakeUserManager()->LoginUser(email_string);
828 TestingProfile* profile =
829 profile_manager()->CreateTestingProfile(email_string);
830 EXPECT_TRUE(profile);
832 // Remember the profile name so that we can destroy it upon destruction.
833 created_profiles_[profile] = email_string;
834 if (chrome::MultiUserWindowManager::GetInstance())
835 chrome::MultiUserWindowManager::GetInstance()->AddUser(profile);
836 if (launcher_controller_)
837 launcher_controller_->AdditionalUserAddedToSession(profile);
838 return profile;
841 // Switch to another user.
842 void SwitchActiveUser(const std::string& name) {
843 session_delegate()->SwitchActiveUser(name);
844 GetFakeUserManager()->SwitchActiveUser(name);
845 chrome::MultiUserWindowManagerChromeOS* manager =
846 static_cast<chrome::MultiUserWindowManagerChromeOS*>(
847 chrome::MultiUserWindowManager::GetInstance());
848 manager->SetAnimationSpeedForTest(
849 chrome::MultiUserWindowManagerChromeOS::ANIMATION_SPEED_DISABLED);
850 manager->ActiveUserChanged(name);
851 launcher_controller_->browser_status_monitor_for_test()->
852 ActiveUserChanged(name);
853 launcher_controller_->app_window_controller_for_test()->
854 ActiveUserChanged(name);
857 // Creates a browser with a |profile| and load a tab with a |title| and |url|.
858 Browser* CreateBrowserAndTabWithProfile(Profile* profile,
859 const std::string& title,
860 const std::string& url) {
861 Browser::CreateParams params(profile, chrome::HOST_DESKTOP_TYPE_ASH);
862 Browser* browser = chrome::CreateBrowserWithTestWindowForParams(&params);
863 chrome::NewTab(browser);
865 BrowserList::SetLastActive(browser);
866 NavigateAndCommitActiveTabWithTitle(
867 browser, GURL(url), ASCIIToUTF16(title));
868 return browser;
871 // Creates a running V1 application.
872 // Note that with the use of the app_tab_helper as done below, this is only
873 // usable with a single v1 application.
874 V1App* CreateRunningV1App(Profile* profile,
875 const std::string& app_name,
876 const std::string& url) {
877 V1App* v1_app = new V1App(profile, app_name);
878 // Create a new app tab helper and assign it to the launcher so that this
879 // app gets properly detected.
880 // TODO(skuhne): Create a more intelligent app tab helper which is able to
881 // detect all running apps properly.
882 TestAppTabHelperImpl* app_tab_helper = new TestAppTabHelperImpl;
883 app_tab_helper->SetAppID(
884 v1_app->browser()->tab_strip_model()->GetWebContentsAt(0),
885 app_name);
886 SetAppTabHelper(app_tab_helper);
888 NavigateAndCommitActiveTabWithTitle(
889 v1_app->browser(), GURL(url), ASCIIToUTF16(""));
890 return v1_app;
893 ash::test::TestSessionStateDelegate* session_delegate() {
894 return static_cast<ash::test::TestSessionStateDelegate*>(
895 ash::Shell::GetInstance()->session_state_delegate());
897 ash::test::TestShellDelegate* shell_delegate() { return shell_delegate_; }
899 // Override BrowserWithTestWindowTest:
900 TestingProfile* CreateProfile() override {
901 return CreateMultiUserProfile("user1");
903 void DestroyProfile(TestingProfile* profile) override {
904 // Delete the profile through our profile manager.
905 ProfileToNameMap::iterator it = created_profiles_.find(profile);
906 DCHECK(it != created_profiles_.end());
907 profile_manager_->DeleteTestingProfile(it->second);
908 created_profiles_.erase(it);
911 private:
912 typedef std::map<Profile*, std::string> ProfileToNameMap;
913 TestingProfileManager* profile_manager() { return profile_manager_.get(); }
915 chromeos::FakeChromeUserManager* GetFakeUserManager() {
916 return static_cast<chromeos::FakeChromeUserManager*>(
917 user_manager::UserManager::Get());
920 scoped_ptr<TestingProfileManager> profile_manager_;
921 scoped_ptr<chromeos::ScopedUserManagerEnabler> user_manager_enabler_;
923 ash::test::TestShellDelegate* shell_delegate_;
925 ProfileToNameMap created_profiles_;
927 DISALLOW_COPY_AND_ASSIGN(
928 MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest);
930 #endif // defined(OS_CHROMEOS)
933 TEST_F(ChromeLauncherControllerTest, DefaultApps) {
934 InitLauncherController();
935 // Model should only contain the browser shortcut and app list items.
936 EXPECT_EQ(2, model_->item_count());
937 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
938 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
939 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
941 // Installing |extension3_| should add it to the launcher - behind the
942 // chrome icon.
943 extension_service_->AddExtension(extension3_.get());
944 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
945 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
946 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
949 // Check that the restauration of launcher items is happening in the same order
950 // as the user has pinned them (on another system) when they are synced reverse
951 // order.
952 TEST_F(ChromeLauncherControllerTest, RestoreDefaultAppsReverseOrder) {
953 InitLauncherController();
955 base::ListValue policy_value;
956 InsertPrefValue(&policy_value, 0, extension1_->id());
957 InsertPrefValue(&policy_value, 1, extension2_->id());
958 InsertPrefValue(&policy_value, 2, extension3_->id());
959 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
960 policy_value.DeepCopy());
961 SetShelfChromeIconIndex(0);
962 // Model should only contain the browser shortcut and app list items.
963 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
964 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
965 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
966 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
968 // Installing |extension3_| should add it to the shelf - behind the
969 // chrome icon.
970 ash::ShelfItem item;
971 extension_service_->AddExtension(extension3_.get());
972 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
973 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
974 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
976 // Installing |extension2_| should add it to the launcher - behind the
977 // chrome icon, but in first location.
978 extension_service_->AddExtension(extension2_.get());
979 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
980 EXPECT_EQ("AppList, Chrome, App2, App3", GetPinnedAppStatus());
982 // Installing |extension1_| should add it to the launcher - behind the
983 // chrome icon, but in first location.
984 extension_service_->AddExtension(extension1_.get());
985 EXPECT_EQ("AppList, Chrome, App1, App2, App3", GetPinnedAppStatus());
988 // Check that the restauration of launcher items is happening in the same order
989 // as the user has pinned them (on another system) when they are synced random
990 // order.
991 TEST_F(ChromeLauncherControllerTest, RestoreDefaultAppsRandomOrder) {
992 InitLauncherController();
994 base::ListValue policy_value;
995 InsertPrefValue(&policy_value, 0, extension1_->id());
996 InsertPrefValue(&policy_value, 1, extension2_->id());
997 InsertPrefValue(&policy_value, 2, extension3_->id());
998 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
999 policy_value.DeepCopy());
1000 SetShelfChromeIconIndex(0);
1001 // Model should only contain the browser shortcut and app list items.
1002 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1003 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1004 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1005 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
1007 // Installing |extension2_| should add it to the launcher - behind the
1008 // chrome icon.
1009 extension_service_->AddExtension(extension2_.get());
1010 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1011 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1012 EXPECT_EQ("AppList, Chrome, App2", GetPinnedAppStatus());
1014 // Installing |extension1_| should add it to the launcher - behind the
1015 // chrome icon, but in first location.
1016 extension_service_->AddExtension(extension1_.get());
1017 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1018 EXPECT_EQ("AppList, Chrome, App1, App2", GetPinnedAppStatus());
1020 // Installing |extension3_| should add it to the launcher - behind the
1021 // chrome icon, but in first location.
1022 extension_service_->AddExtension(extension3_.get());
1023 EXPECT_EQ("AppList, Chrome, App1, App2, App3", GetPinnedAppStatus());
1026 // Check that the restauration of launcher items is happening in the same order
1027 // as the user has pinned / moved them (on another system) when they are synced
1028 // random order - including the chrome icon.
1029 TEST_F(ChromeLauncherControllerTest, RestoreDefaultAppsRandomOrderChromeMoved) {
1030 InitLauncherController();
1032 base::ListValue policy_value;
1033 InsertPrefValue(&policy_value, 0, extension1_->id());
1034 InsertPrefValue(&policy_value, 1, extension2_->id());
1035 InsertPrefValue(&policy_value, 2, extension3_->id());
1036 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1037 policy_value.DeepCopy());
1038 SetShelfChromeIconIndex(1);
1039 // Model should only contain the browser shortcut and app list items.
1040 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1041 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1042 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1043 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
1045 // Installing |extension2_| should add it to the shelf - behind the
1046 // chrome icon.
1047 ash::ShelfItem item;
1048 extension_service_->AddExtension(extension2_.get());
1049 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1050 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1051 EXPECT_EQ("AppList, Chrome, App2", GetPinnedAppStatus());
1053 // Installing |extension1_| should add it to the launcher - behind the
1054 // chrome icon, but in first location.
1055 extension_service_->AddExtension(extension1_.get());
1056 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1057 EXPECT_EQ("AppList, App1, Chrome, App2", GetPinnedAppStatus());
1059 // Installing |extension3_| should add it to the launcher - behind the
1060 // chrome icon, but in first location.
1061 extension_service_->AddExtension(extension3_.get());
1062 EXPECT_EQ("AppList, App1, Chrome, App2, App3", GetPinnedAppStatus());
1065 // Check that syncing to a different state does the correct thing.
1066 TEST_F(ChromeLauncherControllerTest, RestoreDefaultAppsResyncOrder) {
1067 InitLauncherController();
1068 base::ListValue policy_value;
1069 InsertPrefValue(&policy_value, 0, extension1_->id());
1070 InsertPrefValue(&policy_value, 1, extension2_->id());
1071 InsertPrefValue(&policy_value, 2, extension3_->id());
1072 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1073 policy_value.DeepCopy());
1074 // The shelf layout has always one static item at the beginning (App List).
1075 SetShelfChromeIconIndex(0);
1076 extension_service_->AddExtension(extension2_.get());
1077 EXPECT_EQ("AppList, Chrome, App2", GetPinnedAppStatus());
1078 extension_service_->AddExtension(extension1_.get());
1079 EXPECT_EQ("AppList, Chrome, App1, App2", GetPinnedAppStatus());
1080 extension_service_->AddExtension(extension3_.get());
1081 EXPECT_EQ("AppList, Chrome, App1, App2, App3", GetPinnedAppStatus());
1083 // Change the order with increasing chrome position and decreasing position.
1084 base::ListValue policy_value1;
1085 InsertPrefValue(&policy_value1, 0, extension3_->id());
1086 InsertPrefValue(&policy_value1, 1, extension1_->id());
1087 InsertPrefValue(&policy_value1, 2, extension2_->id());
1088 SetShelfChromeIconIndex(3);
1089 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1090 policy_value1.DeepCopy());
1091 EXPECT_EQ("AppList, App3, App1, App2, Chrome", GetPinnedAppStatus());
1092 base::ListValue policy_value2;
1093 InsertPrefValue(&policy_value2, 0, extension2_->id());
1094 InsertPrefValue(&policy_value2, 1, extension3_->id());
1095 InsertPrefValue(&policy_value2, 2, extension1_->id());
1096 SetShelfChromeIconIndex(2);
1097 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1098 policy_value2.DeepCopy());
1099 EXPECT_EQ("AppList, App2, App3, Chrome, App1", GetPinnedAppStatus());
1101 // Check that the chrome icon can also be at the first possible location.
1102 SetShelfChromeIconIndex(0);
1103 base::ListValue policy_value3;
1104 InsertPrefValue(&policy_value3, 0, extension3_->id());
1105 InsertPrefValue(&policy_value3, 1, extension2_->id());
1106 InsertPrefValue(&policy_value3, 2, extension1_->id());
1107 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1108 policy_value3.DeepCopy());
1109 EXPECT_EQ("AppList, Chrome, App3, App2, App1", GetPinnedAppStatus());
1111 // Check that unloading of extensions works as expected.
1112 extension_service_->UnloadExtension(extension1_->id(),
1113 UnloadedExtensionInfo::REASON_UNINSTALL);
1114 EXPECT_EQ("AppList, Chrome, App3, App2", GetPinnedAppStatus());
1116 extension_service_->UnloadExtension(extension2_->id(),
1117 UnloadedExtensionInfo::REASON_UNINSTALL);
1118 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
1120 // Check that an update of an extension does not crash the system.
1121 extension_service_->UnloadExtension(extension3_->id(),
1122 UnloadedExtensionInfo::REASON_UPDATE);
1123 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
1126 // Check that simple locking of an application will 'create' a launcher item.
1127 TEST_F(ChromeLauncherControllerTest, CheckLockApps) {
1128 InitLauncherController();
1129 // Model should only contain the browser shortcut and app list items.
1130 EXPECT_EQ(2, model_->item_count());
1131 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1132 EXPECT_FALSE(
1133 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1134 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1135 EXPECT_FALSE(
1136 launcher_controller_->IsWindowedAppInLauncher(extension2_->id()));
1138 launcher_controller_->LockV1AppWithID(extension1_->id());
1140 EXPECT_EQ(3, model_->item_count());
1141 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type);
1142 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1143 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1144 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1145 EXPECT_FALSE(
1146 launcher_controller_->IsWindowedAppInLauncher(extension2_->id()));
1148 launcher_controller_->UnlockV1AppWithID(extension1_->id());
1150 EXPECT_EQ(2, model_->item_count());
1151 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1152 EXPECT_FALSE(
1153 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1154 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1155 EXPECT_FALSE(
1156 launcher_controller_->IsWindowedAppInLauncher(extension2_->id()));
1159 // Check that multiple locks of an application will be properly handled.
1160 TEST_F(ChromeLauncherControllerTest, CheckMultiLockApps) {
1161 InitLauncherController();
1162 // Model should only contain the browser shortcut and app list items.
1163 EXPECT_EQ(2, model_->item_count());
1164 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1165 EXPECT_FALSE(
1166 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1168 for (int i = 0; i < 2; i++) {
1169 launcher_controller_->LockV1AppWithID(extension1_->id());
1171 EXPECT_EQ(3, model_->item_count());
1172 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type);
1173 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1174 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(
1175 extension1_->id()));
1178 launcher_controller_->UnlockV1AppWithID(extension1_->id());
1180 EXPECT_EQ(3, model_->item_count());
1181 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type);
1182 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1183 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1185 launcher_controller_->UnlockV1AppWithID(extension1_->id());
1187 EXPECT_EQ(2, model_->item_count());
1188 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1189 EXPECT_FALSE(
1190 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1191 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1192 EXPECT_FALSE(
1193 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1196 // Check that already pinned items are not effected by locks.
1197 TEST_F(ChromeLauncherControllerTest, CheckAlreadyPinnedLockApps) {
1198 InitLauncherController();
1199 // Model should only contain the browser shortcut and app list items.
1200 EXPECT_EQ(2, model_->item_count());
1201 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1202 EXPECT_FALSE(
1203 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1205 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1206 launcher_controller_->PinAppWithID(extension1_->id());
1207 EXPECT_TRUE(launcher_controller_->IsAppPinned(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_->LockV1AppWithID(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_->UnlockV1AppWithID(extension1_->id());
1225 EXPECT_EQ(3, model_->item_count());
1226 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1227 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1228 EXPECT_FALSE(
1229 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1231 launcher_controller_->UnpinAppWithID(extension1_->id());
1233 EXPECT_EQ(2, model_->item_count());
1236 // Check that already pinned items which get locked stay after unpinning.
1237 TEST_F(ChromeLauncherControllerTest, CheckPinnedAppsStayAfterUnlock) {
1238 InitLauncherController();
1239 // Model should only contain the browser shortcut and app list items.
1240 EXPECT_EQ(2, model_->item_count());
1241 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1242 EXPECT_FALSE(
1243 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1245 launcher_controller_->PinAppWithID(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_->LockV1AppWithID(extension1_->id());
1255 EXPECT_EQ(3, model_->item_count());
1256 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1257 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1258 EXPECT_FALSE(
1259 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1261 launcher_controller_->UnpinAppWithID(extension1_->id());
1263 EXPECT_EQ(3, model_->item_count());
1264 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type);
1265 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1266 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1268 launcher_controller_->UnlockV1AppWithID(extension1_->id());
1270 EXPECT_EQ(2, model_->item_count());
1273 #if defined(OS_CHROMEOS)
1274 // Check that running applications wich are not pinned get properly restored
1275 // upon user change.
1276 TEST_F(ChromeLauncherControllerTest, CheckRunningAppOrder) {
1277 InitLauncherController();
1278 // Model should only contain the browser shortcut and app list items.
1279 EXPECT_EQ(2, model_->item_count());
1281 // Add a few running applications.
1282 launcher_controller_->LockV1AppWithID(extension1_->id());
1283 launcher_controller_->LockV1AppWithID(extension2_->id());
1284 launcher_controller_->LockV1AppWithID(extension3_->id());
1285 EXPECT_EQ(5, model_->item_count());
1286 // Note that this not only checks the order of applications but also the
1287 // running type.
1288 EXPECT_EQ("AppList, Chrome, app1, app2, app3", GetPinnedAppStatus());
1290 // Remember the current order of applications for the current user.
1291 const std::string& current_user_id =
1292 multi_user_util::GetUserIDFromProfile(profile());
1293 RememberUnpinnedRunningApplicationOrder();
1295 // Switch some items and check that restoring a user which was not yet
1296 // remembered changes nothing.
1297 model_->Move(2, 3);
1298 EXPECT_EQ("AppList, Chrome, app2, app1, app3", GetPinnedAppStatus());
1299 RestoreUnpinnedRunningApplicationOrder("second-fake-user@fake.com");
1300 EXPECT_EQ("AppList, Chrome, app2, app1, app3", GetPinnedAppStatus());
1302 // Restoring the stored user should however do the right thing.
1303 RestoreUnpinnedRunningApplicationOrder(current_user_id);
1304 EXPECT_EQ("AppList, Chrome, app1, app2, app3", GetPinnedAppStatus());
1306 // Switch again some items and even delete one - making sure that the missing
1307 // item gets properly handled.
1308 model_->Move(3, 4);
1309 launcher_controller_->UnlockV1AppWithID(extension1_->id());
1310 EXPECT_EQ("AppList, Chrome, app3, app2", GetPinnedAppStatus());
1311 RestoreUnpinnedRunningApplicationOrder(current_user_id);
1312 EXPECT_EQ("AppList, Chrome, app2, app3", GetPinnedAppStatus());
1314 // Check that removing more items does not crash and changes nothing.
1315 launcher_controller_->UnlockV1AppWithID(extension2_->id());
1316 RestoreUnpinnedRunningApplicationOrder(current_user_id);
1317 EXPECT_EQ("AppList, Chrome, app3", GetPinnedAppStatus());
1318 launcher_controller_->UnlockV1AppWithID(extension3_->id());
1319 RestoreUnpinnedRunningApplicationOrder(current_user_id);
1320 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
1323 // Check that with multi profile V1 apps are properly added / removed from the
1324 // shelf.
1325 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
1326 V1AppUpdateOnUserSwitch) {
1327 // Create a browser item in the LauncherController.
1328 InitLauncherController();
1329 EXPECT_EQ(2, model_->item_count());
1331 // Create a "windowed gmail app".
1332 scoped_ptr<V1App> v1_app(CreateRunningV1App(
1333 profile(), extension_misc::kGmailAppId, gmail_url));
1334 EXPECT_EQ(3, model_->item_count());
1336 // After switching to a second user the item should be gone.
1337 std::string user2 = "user2";
1338 TestingProfile* profile2 = CreateMultiUserProfile(user2);
1339 SwitchActiveUser(profile2->GetProfileUserName());
1340 EXPECT_EQ(2, model_->item_count());
1342 // After switching back the item should be back.
1343 SwitchActiveUser(profile()->GetProfileUserName());
1344 EXPECT_EQ(3, model_->item_count());
1345 // Note we destroy now the gmail app with the closure end.
1347 EXPECT_EQ(2, model_->item_count());
1350 // Check edge cases with multi profile V1 apps in the shelf.
1351 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
1352 V1AppUpdateOnUserSwitchEdgecases) {
1353 // Create a browser item in the LauncherController.
1354 InitLauncherController();
1356 // First test: Create an app when the user is not active.
1357 std::string user2 = "user2";
1358 TestingProfile* profile2 = CreateMultiUserProfile(user2);
1360 // Create a "windowed gmail app".
1361 scoped_ptr<V1App> v1_app(CreateRunningV1App(
1362 profile2, extension_misc::kGmailAppId, gmail_url));
1363 EXPECT_EQ(2, model_->item_count());
1365 // However - switching to the user should show it.
1366 SwitchActiveUser(profile2->GetProfileUserName());
1367 EXPECT_EQ(3, model_->item_count());
1369 // Second test: Remove the app when the user is not active and see that it
1370 // works.
1371 SwitchActiveUser(profile()->GetProfileUserName());
1372 EXPECT_EQ(2, model_->item_count());
1373 // Note: the closure ends and the browser will go away.
1375 EXPECT_EQ(2, model_->item_count());
1376 SwitchActiveUser(profile2->GetProfileUserName());
1377 EXPECT_EQ(2, model_->item_count());
1378 SwitchActiveUser(profile()->GetProfileUserName());
1379 EXPECT_EQ(2, model_->item_count());
1382 // Check edge case where a visiting V1 app gets closed (crbug.com/321374).
1383 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
1384 V1CloseOnVisitingDesktop) {
1385 // Create a browser item in the LauncherController.
1386 InitLauncherController();
1388 chrome::MultiUserWindowManager* manager =
1389 chrome::MultiUserWindowManager::GetInstance();
1391 // First create an app when the user is active.
1392 std::string user2 = "user2";
1393 TestingProfile* profile2 = CreateMultiUserProfile(user2);
1395 // Create a "windowed gmail app".
1396 scoped_ptr<V1App> v1_app(CreateRunningV1App(
1397 profile(),
1398 extension_misc::kGmailAppId,
1399 kGmailLaunchURL));
1400 EXPECT_EQ(3, model_->item_count());
1402 // Transfer the app to the other screen and switch users.
1403 manager->ShowWindowForUser(v1_app->browser()->window()->GetNativeWindow(),
1404 user2);
1405 EXPECT_EQ(3, model_->item_count());
1406 SwitchActiveUser(profile2->GetProfileUserName());
1407 EXPECT_EQ(2, model_->item_count());
1409 // After the app was destroyed, switch back. (which caused already a crash).
1410 SwitchActiveUser(profile()->GetProfileUserName());
1412 // Create the same app again - which was also causing the crash.
1413 EXPECT_EQ(2, model_->item_count());
1415 // Create a "windowed gmail app".
1416 scoped_ptr<V1App> v1_app(CreateRunningV1App(
1417 profile(),
1418 extension_misc::kGmailAppId,
1419 kGmailLaunchURL));
1420 EXPECT_EQ(3, model_->item_count());
1422 SwitchActiveUser(profile2->GetProfileUserName());
1423 EXPECT_EQ(2, model_->item_count());
1426 // Check edge cases with multi profile V1 apps in the shelf.
1427 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
1428 V1AppUpdateOnUserSwitchEdgecases2) {
1429 // Create a browser item in the LauncherController.
1430 InitLauncherController();
1431 TestAppTabHelperImpl* app_tab_helper = new TestAppTabHelperImpl;
1432 SetAppTabHelper(app_tab_helper);
1434 // First test: Create an app when the user is not active.
1435 std::string user2 = "user2";
1436 TestingProfile* profile2 = CreateMultiUserProfile(user2);
1437 SwitchActiveUser(profile2->GetProfileUserName());
1439 // Create a "windowed gmail app".
1440 scoped_ptr<V1App> v1_app(CreateRunningV1App(
1441 profile(), extension_misc::kGmailAppId, gmail_url));
1442 EXPECT_EQ(2, model_->item_count());
1444 // However - switching to the user should show it.
1445 SwitchActiveUser(profile()->GetProfileUserName());
1446 EXPECT_EQ(3, model_->item_count());
1448 // Second test: Remove the app when the user is not active and see that it
1449 // works.
1450 SwitchActiveUser(profile2->GetProfileUserName());
1451 EXPECT_EQ(2, model_->item_count());
1452 v1_app.reset();
1454 EXPECT_EQ(2, model_->item_count());
1455 SwitchActiveUser(profile()->GetProfileUserName());
1456 EXPECT_EQ(2, model_->item_count());
1457 SwitchActiveUser(profile2->GetProfileUserName());
1458 EXPECT_EQ(2, model_->item_count());
1461 // Check that activating an item which is on another user's desktop, will bring
1462 // it back.
1463 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
1464 TestLauncherActivationPullsBackWindow) {
1465 // Create a browser item in the LauncherController.
1466 InitLauncherController();
1467 chrome::MultiUserWindowManager* manager =
1468 chrome::MultiUserWindowManager::GetInstance();
1470 // Add two users to the window manager.
1471 std::string user2 = "user2";
1472 TestingProfile* profile2 = CreateMultiUserProfile(user2);
1473 manager->AddUser(profile());
1474 manager->AddUser(profile2);
1475 const std::string& current_user =
1476 multi_user_util::GetUserIDFromProfile(profile());
1478 // Create a browser window with a native window for the current user.
1479 scoped_ptr<BrowserWindow> browser_window(CreateTestBrowserWindow(
1480 Browser::CreateParams(profile(), chrome::HOST_DESKTOP_TYPE_ASH)));
1481 aura::Window* window = browser_window->GetNativeWindow();
1482 manager->SetWindowOwner(window, current_user);
1484 // Check that an activation of the window on its owner's desktop does not
1485 // change the visibility to another user.
1486 launcher_controller_->ActivateWindowOrMinimizeIfActive(browser_window.get(),
1487 false);
1488 EXPECT_TRUE(manager->IsWindowOnDesktopOfUser(window, current_user));
1490 // Transfer the window to another user's desktop and check that activating it
1491 // does pull it back to that user.
1492 manager->ShowWindowForUser(window,
1493 multi_user_util::GetUserIDFromProfile(profile2));
1494 EXPECT_FALSE(manager->IsWindowOnDesktopOfUser(window, current_user));
1495 launcher_controller_->ActivateWindowOrMinimizeIfActive(browser_window.get(),
1496 false);
1497 EXPECT_TRUE(manager->IsWindowOnDesktopOfUser(window, current_user));
1499 #endif
1501 // Check that lock -> pin -> unlock -> unpin does properly transition.
1502 TEST_F(ChromeLauncherControllerTest, CheckLockPinUnlockUnpin) {
1503 InitLauncherController();
1504 // Model should only contain the browser shortcut and app list items.
1505 EXPECT_EQ(2, model_->item_count());
1506 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1507 EXPECT_FALSE(
1508 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1510 launcher_controller_->LockV1AppWithID(extension1_->id());
1512 EXPECT_EQ(3, model_->item_count());
1513 EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type);
1514 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1515 EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1517 launcher_controller_->PinAppWithID(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_->UnlockV1AppWithID(extension1_->id());
1527 EXPECT_EQ(3, model_->item_count());
1528 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1529 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1530 EXPECT_FALSE(
1531 launcher_controller_->IsWindowedAppInLauncher(extension1_->id()));
1533 launcher_controller_->UnpinAppWithID(extension1_->id());
1535 EXPECT_EQ(2, model_->item_count());
1538 // Check that a locked (windowed V1 application) will be properly converted
1539 // between locked and pinned when the order gets changed through a profile /
1540 // policy change.
1541 TEST_F(ChromeLauncherControllerTest, RestoreDefaultAndLockedAppsResyncOrder) {
1542 InitLauncherController();
1543 base::ListValue policy_value0;
1544 InsertPrefValue(&policy_value0, 0, extension1_->id());
1545 InsertPrefValue(&policy_value0, 1, extension3_->id());
1546 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1547 policy_value0.DeepCopy());
1548 // The shelf layout has always one static item at the beginning (App List).
1549 SetShelfChromeIconIndex(0);
1550 extension_service_->AddExtension(extension1_.get());
1551 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1552 extension_service_->AddExtension(extension2_.get());
1553 // No new app icon will be generated.
1554 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1555 // Add the app as locked app which will add it (un-pinned).
1556 launcher_controller_->LockV1AppWithID(extension2_->id());
1557 EXPECT_EQ("AppList, Chrome, App1, app2", GetPinnedAppStatus());
1558 extension_service_->AddExtension(extension3_.get());
1559 EXPECT_EQ("AppList, Chrome, App1, App3, app2", GetPinnedAppStatus());
1561 // Now request to pin all items which should convert the locked item into a
1562 // pinned item.
1563 base::ListValue policy_value1;
1564 InsertPrefValue(&policy_value1, 0, extension3_->id());
1565 InsertPrefValue(&policy_value1, 1, extension2_->id());
1566 InsertPrefValue(&policy_value1, 2, extension1_->id());
1567 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1568 policy_value1.DeepCopy());
1569 EXPECT_EQ("AppList, Chrome, App3, App2, App1", GetPinnedAppStatus());
1571 // Going back to a status where there is no requirement for app 2 to be pinned
1572 // should convert it back to locked but not pinned and state. The position
1573 // is determined by the |ShelfModel|'s weight system and since running
1574 // applications are not allowed to be mixed with shortcuts, it should show up
1575 // at the end of the list.
1576 base::ListValue policy_value2;
1577 InsertPrefValue(&policy_value2, 0, extension3_->id());
1578 InsertPrefValue(&policy_value2, 1, extension1_->id());
1579 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1580 policy_value2.DeepCopy());
1581 EXPECT_EQ("AppList, Chrome, App3, App1, app2", GetPinnedAppStatus());
1583 // Removing an item should simply close it and everything should shift.
1584 base::ListValue policy_value3;
1585 InsertPrefValue(&policy_value3, 0, extension3_->id());
1586 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1587 policy_value3.DeepCopy());
1588 EXPECT_EQ("AppList, Chrome, App3, app2", GetPinnedAppStatus());
1591 // Check that a running and not pinned V2 application will be properly converted
1592 // between locked and pinned when the order gets changed through a profile /
1593 // policy change.
1594 TEST_F(ChromeLauncherControllerTest,
1595 RestoreDefaultAndRunningV2AppsResyncOrder) {
1596 InitLauncherController();
1597 base::ListValue policy_value0;
1598 InsertPrefValue(&policy_value0, 0, extension1_->id());
1599 InsertPrefValue(&policy_value0, 1, extension3_->id());
1600 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1601 policy_value0.DeepCopy());
1602 // The shelf layout has always one static item at the beginning (app List).
1603 SetShelfChromeIconIndex(0);
1604 extension_service_->AddExtension(extension1_.get());
1605 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1606 extension_service_->AddExtension(extension2_.get());
1607 // No new app icon will be generated.
1608 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1609 // Add the app as an unpinned but running V2 app.
1610 CreateRunningV2App(extension2_->id());
1611 EXPECT_EQ("AppList, Chrome, App1, *app2", GetPinnedAppStatus());
1612 extension_service_->AddExtension(extension3_.get());
1613 EXPECT_EQ("AppList, Chrome, App1, App3, *app2", GetPinnedAppStatus());
1615 // Now request to pin all items which should convert the locked item into a
1616 // pinned item.
1617 base::ListValue policy_value1;
1618 InsertPrefValue(&policy_value1, 0, extension3_->id());
1619 InsertPrefValue(&policy_value1, 1, extension2_->id());
1620 InsertPrefValue(&policy_value1, 2, extension1_->id());
1621 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1622 policy_value1.DeepCopy());
1623 EXPECT_EQ("AppList, Chrome, App3, App2, App1", GetPinnedAppStatus());
1625 // Going back to a status where there is no requirement for app 2 to be pinned
1626 // should convert it back to running V2 app. Since the position is determined
1627 // by the |ShelfModel|'s weight system, it will be after last pinned item.
1628 base::ListValue policy_value2;
1629 InsertPrefValue(&policy_value2, 0, extension3_->id());
1630 InsertPrefValue(&policy_value2, 1, extension1_->id());
1631 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1632 policy_value2.DeepCopy());
1633 EXPECT_EQ("AppList, Chrome, App3, App1, *app2", GetPinnedAppStatus());
1635 // Removing an item should simply close it and everything should shift.
1636 base::ListValue policy_value3;
1637 InsertPrefValue(&policy_value3, 0, extension3_->id());
1638 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1639 policy_value3.DeepCopy());
1640 EXPECT_EQ("AppList, Chrome, App3, *app2", GetPinnedAppStatus());
1643 // Each user has a different set of applications pinned. Check that when
1644 // switching between the two users, the state gets properly set.
1645 TEST_F(ChromeLauncherControllerTest, UserSwitchIconRestore) {
1646 base::ListValue user_a;
1647 base::ListValue user_b;
1648 SetUpMultiUserScenario(&user_a, &user_b);
1649 // Show user 1.
1650 SetShelfChromeIconIndex(6);
1651 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1652 user_a.DeepCopy());
1653 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1654 GetPinnedAppStatus());
1656 // Show user 2.
1657 SetShelfChromeIconIndex(4);
1658 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1659 user_b.DeepCopy());
1661 EXPECT_EQ("AppList, App7, App8, Chrome", GetPinnedAppStatus());
1663 // Switch back to 1.
1664 SetShelfChromeIconIndex(8);
1665 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1666 user_a.DeepCopy());
1667 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1668 GetPinnedAppStatus());
1670 // Switch back to 2.
1671 SetShelfChromeIconIndex(4);
1672 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1673 user_b.DeepCopy());
1674 EXPECT_EQ("AppList, App7, App8, Chrome", GetPinnedAppStatus());
1677 // Each user has a different set of applications pinned, and one user has an
1678 // application running. Check that when switching between the two users, the
1679 // state gets properly set.
1680 TEST_F(ChromeLauncherControllerTest, UserSwitchIconRestoreWithRunningV2App) {
1681 base::ListValue user_a;
1682 base::ListValue user_b;
1683 SetUpMultiUserScenario(&user_a, &user_b);
1685 // Run App1 and assume that it is a V2 app.
1686 CreateRunningV2App(extension1_->id());
1688 // Show user 1.
1689 SetShelfChromeIconIndex(6);
1690 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1691 user_a.DeepCopy());
1692 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1693 GetPinnedAppStatus());
1695 // Show user 2.
1696 SetShelfChromeIconIndex(4);
1697 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1698 user_b.DeepCopy());
1700 EXPECT_EQ("AppList, App7, App8, Chrome, *app1", GetPinnedAppStatus());
1702 // Switch back to 1.
1703 SetShelfChromeIconIndex(8);
1704 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1705 user_a.DeepCopy());
1706 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1707 GetPinnedAppStatus());
1709 // Switch back to 2.
1710 SetShelfChromeIconIndex(4);
1711 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1712 user_b.DeepCopy());
1713 EXPECT_EQ("AppList, App7, App8, Chrome, *app1", GetPinnedAppStatus());
1716 // Each user has a different set of applications pinned, and one user has an
1717 // application running. The chrome icon is not the last item in the list.
1718 // Check that when switching between the two users, the state gets properly set.
1719 // There was once a bug associated with this.
1720 TEST_F(ChromeLauncherControllerTest,
1721 UserSwitchIconRestoreWithRunningV2AppChromeInMiddle) {
1722 base::ListValue user_a;
1723 base::ListValue user_b;
1724 SetUpMultiUserScenario(&user_a, &user_b);
1726 // Run App1 and assume that it is a V2 app.
1727 CreateRunningV2App(extension1_->id());
1729 // Show user 1.
1730 SetShelfChromeIconIndex(5);
1731 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1732 user_a.DeepCopy());
1733 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, Chrome, App6",
1734 GetPinnedAppStatus());
1736 // Show user 2.
1737 SetShelfChromeIconIndex(4);
1738 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1739 user_b.DeepCopy());
1741 EXPECT_EQ("AppList, App7, App8, Chrome, *app1", GetPinnedAppStatus());
1743 // Switch back to 1.
1744 SetShelfChromeIconIndex(5);
1745 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1746 user_a.DeepCopy());
1747 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, Chrome, App6",
1748 GetPinnedAppStatus());
1751 TEST_F(ChromeLauncherControllerTest, Policy) {
1752 extension_service_->AddExtension(extension1_.get());
1753 extension_service_->AddExtension(extension3_.get());
1755 base::ListValue policy_value;
1756 InsertPrefValue(&policy_value, 0, extension1_->id());
1757 InsertPrefValue(&policy_value, 1, extension2_->id());
1758 profile()->GetTestingPrefService()->SetManagedPref(prefs::kPinnedLauncherApps,
1759 policy_value.DeepCopy());
1761 // Only |extension1_| should get pinned. |extension2_| is specified but not
1762 // installed, and |extension3_| is part of the default set, but that shouldn't
1763 // take effect when the policy override is in place.
1764 InitLauncherController();
1765 EXPECT_EQ(3, model_->item_count());
1766 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1767 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1768 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id()));
1769 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1771 // Installing |extension2_| should add it to the launcher.
1772 extension_service_->AddExtension(extension2_.get());
1773 EXPECT_EQ(4, model_->item_count());
1774 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1775 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[3].type);
1776 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id()));
1777 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension2_->id()));
1778 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1780 // Removing |extension1_| from the policy should be reflected in the launcher.
1781 policy_value.Remove(0, NULL);
1782 profile()->GetTestingPrefService()->SetManagedPref(prefs::kPinnedLauncherApps,
1783 policy_value.DeepCopy());
1784 EXPECT_EQ(3, model_->item_count());
1785 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
1786 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id()));
1787 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension2_->id()));
1788 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1791 TEST_F(ChromeLauncherControllerTest, UnpinWithUninstall) {
1792 extension_service_->AddExtension(extension3_.get());
1793 extension_service_->AddExtension(extension4_.get());
1795 InitLauncherController();
1797 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
1798 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension4_->id()));
1800 extension_service_->UnloadExtension(extension3_->id(),
1801 UnloadedExtensionInfo::REASON_UNINSTALL);
1803 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
1804 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension4_->id()));
1807 TEST_F(ChromeLauncherControllerTest, PrefUpdates) {
1808 extension_service_->AddExtension(extension2_.get());
1809 extension_service_->AddExtension(extension3_.get());
1810 extension_service_->AddExtension(extension4_.get());
1812 InitLauncherController();
1814 std::vector<std::string> expected_launchers;
1815 std::vector<std::string> actual_launchers;
1816 base::ListValue pref_value;
1817 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1818 pref_value.DeepCopy());
1819 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
1820 EXPECT_EQ(expected_launchers, actual_launchers);
1822 // Unavailable extensions don't create launcher items.
1823 InsertPrefValue(&pref_value, 0, extension1_->id());
1824 InsertPrefValue(&pref_value, 1, extension2_->id());
1825 InsertPrefValue(&pref_value, 2, extension4_->id());
1826 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1827 pref_value.DeepCopy());
1828 expected_launchers.push_back(extension2_->id());
1829 expected_launchers.push_back(extension4_->id());
1830 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
1831 EXPECT_EQ(expected_launchers, actual_launchers);
1833 // Redundant pref entries show up only once.
1834 InsertPrefValue(&pref_value, 2, extension3_->id());
1835 InsertPrefValue(&pref_value, 2, extension3_->id());
1836 InsertPrefValue(&pref_value, 5, extension3_->id());
1837 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1838 pref_value.DeepCopy());
1839 expected_launchers.insert(expected_launchers.begin() + 1, extension3_->id());
1840 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
1841 EXPECT_EQ(expected_launchers, actual_launchers);
1843 // Order changes are reflected correctly.
1844 pref_value.Clear();
1845 InsertPrefValue(&pref_value, 0, extension4_->id());
1846 InsertPrefValue(&pref_value, 1, extension3_->id());
1847 InsertPrefValue(&pref_value, 2, extension2_->id());
1848 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1849 pref_value.DeepCopy());
1850 std::reverse(expected_launchers.begin(), expected_launchers.end());
1851 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
1852 EXPECT_EQ(expected_launchers, actual_launchers);
1854 // Clearing works.
1855 pref_value.Clear();
1856 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1857 pref_value.DeepCopy());
1858 expected_launchers.clear();
1859 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
1860 EXPECT_EQ(expected_launchers, actual_launchers);
1863 TEST_F(ChromeLauncherControllerTest, PendingInsertionOrder) {
1864 extension_service_->AddExtension(extension1_.get());
1865 extension_service_->AddExtension(extension3_.get());
1867 InitLauncherController();
1869 base::ListValue pref_value;
1870 InsertPrefValue(&pref_value, 0, extension1_->id());
1871 InsertPrefValue(&pref_value, 1, extension2_->id());
1872 InsertPrefValue(&pref_value, 2, extension3_->id());
1873 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps,
1874 pref_value.DeepCopy());
1876 std::vector<std::string> expected_launchers;
1877 expected_launchers.push_back(extension1_->id());
1878 expected_launchers.push_back(extension3_->id());
1879 std::vector<std::string> actual_launchers;
1881 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
1882 EXPECT_EQ(expected_launchers, actual_launchers);
1884 // Install |extension2| and verify it shows up between the other two.
1885 extension_service_->AddExtension(extension2_.get());
1886 expected_launchers.insert(expected_launchers.begin() + 1, extension2_->id());
1887 GetAppLaunchers(launcher_controller_.get(), &actual_launchers);
1888 EXPECT_EQ(expected_launchers, actual_launchers);
1891 // Checks the created menus and menu lists for correctness. It uses the given
1892 // |controller| to create the objects for the given |item| and checks the
1893 // found item count against the |expected_items|. The |title| list contains the
1894 // menu titles in the order of their appearance in the menu (not including the
1895 // application name).
1896 bool CheckMenuCreation(ChromeLauncherController* controller,
1897 const ash::ShelfItem& item,
1898 size_t expected_items,
1899 base::string16 title[],
1900 bool is_browser) {
1901 ChromeLauncherAppMenuItems items = controller->GetApplicationList(item, 0);
1902 // A new behavior has been added: Only show menus if there is at least one
1903 // item available.
1904 if (expected_items < 1 && is_browser) {
1905 EXPECT_EQ(0u, items.size());
1906 return items.size() == 0;
1908 // There should be one item in there: The title.
1909 EXPECT_EQ(expected_items + 1, items.size());
1910 EXPECT_FALSE(items[0]->IsEnabled());
1911 for (size_t i = 0; i < expected_items; i++) {
1912 EXPECT_EQ(title[i], items[1 + i]->title());
1913 // Check that the first real item has a leading separator.
1914 if (i == 1)
1915 EXPECT_TRUE(items[i]->HasLeadingSeparator());
1916 else
1917 EXPECT_FALSE(items[i]->HasLeadingSeparator());
1920 scoped_ptr<ash::ShelfMenuModel> menu(new LauncherApplicationMenuItemModel(
1921 controller->GetApplicationList(item, 0)));
1922 // The first element in the menu is a spacing separator. On some systems
1923 // (e.g. Windows) such things do not exist. As such we check the existence
1924 // and adjust dynamically.
1925 int first_item = menu->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR ? 1 : 0;
1926 int expected_menu_items = first_item +
1927 (expected_items ? (expected_items + 3) : 2);
1928 EXPECT_EQ(expected_menu_items, menu->GetItemCount());
1929 EXPECT_FALSE(menu->IsEnabledAt(first_item));
1930 if (expected_items) {
1931 EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR,
1932 menu->GetTypeAt(first_item + 1));
1934 return items.size() == expected_items + 1;
1937 // Check that browsers get reflected correctly in the launcher menu.
1938 TEST_F(ChromeLauncherControllerTest, BrowserMenuGeneration) {
1939 EXPECT_EQ(1U, chrome::GetTotalBrowserCount());
1940 chrome::NewTab(browser());
1942 InitLauncherController();
1944 // Check that the browser list is empty at this time.
1945 ash::ShelfItem item_browser;
1946 item_browser.type = ash::TYPE_BROWSER_SHORTCUT;
1947 item_browser.id =
1948 launcher_controller_->GetShelfIDForAppID(extension_misc::kChromeAppId);
1949 EXPECT_TRUE(CheckMenuCreation(
1950 launcher_controller_.get(), item_browser, 0, NULL, true));
1952 // Now make the created browser() visible by adding it to the active browser
1953 // list.
1954 BrowserList::SetLastActive(browser());
1955 base::string16 title1 = ASCIIToUTF16("Test1");
1956 NavigateAndCommitActiveTabWithTitle(browser(), GURL("http://test1"), title1);
1957 base::string16 one_menu_item[] = { title1 };
1959 EXPECT_TRUE(CheckMenuCreation(
1960 launcher_controller_.get(), item_browser, 1, one_menu_item, true));
1962 // Create one more browser/window and check that one more was added.
1963 Browser::CreateParams ash_params(profile(), chrome::HOST_DESKTOP_TYPE_ASH);
1964 scoped_ptr<Browser> browser2(
1965 chrome::CreateBrowserWithTestWindowForParams(&ash_params));
1966 chrome::NewTab(browser2.get());
1967 BrowserList::SetLastActive(browser2.get());
1968 base::string16 title2 = ASCIIToUTF16("Test2");
1969 NavigateAndCommitActiveTabWithTitle(browser2.get(), GURL("http://test2"),
1970 title2);
1972 // Check that the list contains now two entries - make furthermore sure that
1973 // the active item is the first entry.
1974 base::string16 two_menu_items[] = {title1, title2};
1975 EXPECT_TRUE(CheckMenuCreation(
1976 launcher_controller_.get(), item_browser, 2, two_menu_items, true));
1978 // Apparently we have to close all tabs we have.
1979 chrome::CloseTab(browser2.get());
1982 #if defined(OS_CHROMEOS)
1983 // Check the multi profile case where only user related browsers should show
1984 // up.
1985 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
1986 BrowserMenuGenerationTwoUsers) {
1987 // Create a browser item in the LauncherController.
1988 InitLauncherController();
1990 ash::ShelfItem item_browser;
1991 item_browser.type = ash::TYPE_BROWSER_SHORTCUT;
1992 item_browser.id =
1993 launcher_controller_->GetShelfIDForAppID(extension_misc::kChromeAppId);
1995 // Check that the menu is empty.
1996 chrome::NewTab(browser());
1997 EXPECT_TRUE(CheckMenuCreation(
1998 launcher_controller_.get(), item_browser, 0, NULL, true));
2000 // Show the created |browser()| by adding it to the active browser list.
2001 BrowserList::SetLastActive(browser());
2002 base::string16 title1 = ASCIIToUTF16("Test1");
2003 NavigateAndCommitActiveTabWithTitle(browser(), GURL("http://test1"), title1);
2004 base::string16 one_menu_item1[] = { title1 };
2005 EXPECT_TRUE(CheckMenuCreation(
2006 launcher_controller_.get(), item_browser, 1, one_menu_item1, true));
2008 // Create a browser for another user and check that it is not included in the
2009 // users running browser list.
2010 std::string user2 = "user2";
2011 TestingProfile* profile2 = CreateMultiUserProfile(user2);
2012 scoped_ptr<Browser> browser2(
2013 CreateBrowserAndTabWithProfile(profile2, user2, "http://test2"));
2014 base::string16 one_menu_item2[] = { ASCIIToUTF16(user2) };
2015 EXPECT_TRUE(CheckMenuCreation(
2016 launcher_controller_.get(), item_browser, 1, one_menu_item1, true));
2018 // Switch to the other user and make sure that only that browser window gets
2019 // shown.
2020 SwitchActiveUser(profile2->GetProfileUserName());
2021 EXPECT_TRUE(CheckMenuCreation(
2022 launcher_controller_.get(), item_browser, 1, one_menu_item2, true));
2024 // Transferred browsers of other users should not show up in the list.
2025 chrome::MultiUserWindowManager::GetInstance()->ShowWindowForUser(
2026 browser()->window()->GetNativeWindow(),
2027 user2);
2028 EXPECT_TRUE(CheckMenuCreation(
2029 launcher_controller_.get(), item_browser, 1, one_menu_item2, true));
2031 chrome::CloseTab(browser2.get());
2033 #endif // defined(OS_CHROMEOS)
2035 // Check that V1 apps are correctly reflected in the launcher menu using the
2036 // refocus logic.
2037 // Note that the extension matching logic is tested by the extension system
2038 // and does not need a separate test here.
2039 TEST_F(ChromeLauncherControllerTest, V1AppMenuGeneration) {
2040 EXPECT_EQ(1U, chrome::GetTotalBrowserCount());
2041 EXPECT_EQ(0, browser()->tab_strip_model()->count());
2043 InitLauncherControllerWithBrowser();
2045 // Model should only contain the browser shortcut and app list items.
2046 EXPECT_EQ(2, model_->item_count());
2047 EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id()));
2049 // Installing |extension3_| adds it to the launcher.
2050 ash::ShelfID gmail_id = model_->next_id();
2051 extension_service_->AddExtension(extension3_.get());
2052 EXPECT_EQ(3, model_->item_count());
2053 int gmail_index = model_->ItemIndexByID(gmail_id);
2054 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[gmail_index].type);
2055 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
2056 launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(gmail_url));
2058 // Check the menu content.
2059 ash::ShelfItem item_browser;
2060 item_browser.type = ash::TYPE_BROWSER_SHORTCUT;
2061 item_browser.id =
2062 launcher_controller_->GetShelfIDForAppID(extension_misc::kChromeAppId);
2064 ash::ShelfItem item_gmail;
2065 item_gmail.type = ash::TYPE_APP_SHORTCUT;
2066 item_gmail.id = gmail_id;
2067 EXPECT_TRUE(CheckMenuCreation(
2068 launcher_controller_.get(), item_gmail, 0, NULL, false));
2070 // Set the gmail URL to a new tab.
2071 base::string16 title1 = ASCIIToUTF16("Test1");
2072 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title1);
2074 base::string16 one_menu_item[] = { title1 };
2075 EXPECT_TRUE(CheckMenuCreation(
2076 launcher_controller_.get(), item_gmail, 1, one_menu_item, false));
2078 // Create one empty tab.
2079 chrome::NewTab(browser());
2080 base::string16 title2 = ASCIIToUTF16("Test2");
2081 NavigateAndCommitActiveTabWithTitle(
2082 browser(),
2083 GURL("https://bla"),
2084 title2);
2086 // and another one with another gmail instance.
2087 chrome::NewTab(browser());
2088 base::string16 title3 = ASCIIToUTF16("Test3");
2089 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title3);
2090 base::string16 two_menu_items[] = {title1, title3};
2091 EXPECT_TRUE(CheckMenuCreation(
2092 launcher_controller_.get(), item_gmail, 2, two_menu_items, false));
2094 // Even though the item is in the V1 app list, it should also be in the
2095 // browser list.
2096 base::string16 browser_menu_item[] = {title3};
2097 EXPECT_TRUE(CheckMenuCreation(
2098 launcher_controller_.get(), item_browser, 1, browser_menu_item, false));
2100 // Test that closing of (all) the item(s) does work (and all menus get
2101 // updated properly).
2102 launcher_controller_->Close(item_gmail.id);
2104 EXPECT_TRUE(CheckMenuCreation(
2105 launcher_controller_.get(), item_gmail, 0, NULL, false));
2106 base::string16 browser_menu_item2[] = { title2 };
2107 EXPECT_TRUE(CheckMenuCreation(
2108 launcher_controller_.get(), item_browser, 1, browser_menu_item2, false));
2111 #if defined(OS_CHROMEOS)
2112 // Check the multi profile case where only user related apps should show up.
2113 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
2114 V1AppMenuGenerationTwoUsers) {
2115 // Create a browser item in the LauncherController.
2116 InitLauncherController();
2117 chrome::NewTab(browser());
2119 // Installing |extension3_| adds it to the launcher.
2120 ash::ShelfID gmail_id = model_->next_id();
2121 extension_service_->AddExtension(extension3_.get());
2122 EXPECT_EQ(3, model_->item_count());
2123 int gmail_index = model_->ItemIndexByID(gmail_id);
2124 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[gmail_index].type);
2125 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
2126 launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(gmail_url));
2128 // Check the menu content.
2129 ash::ShelfItem item_browser;
2130 item_browser.type = ash::TYPE_BROWSER_SHORTCUT;
2131 item_browser.id =
2132 launcher_controller_->GetShelfIDForAppID(extension_misc::kChromeAppId);
2134 ash::ShelfItem item_gmail;
2135 item_gmail.type = ash::TYPE_APP_SHORTCUT;
2136 item_gmail.id = gmail_id;
2137 EXPECT_TRUE(CheckMenuCreation(
2138 launcher_controller_.get(), item_gmail, 0, NULL, false));
2140 // Set the gmail URL to a new tab.
2141 base::string16 title1 = ASCIIToUTF16("Test1");
2142 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title1);
2144 base::string16 one_menu_item[] = { title1 };
2145 EXPECT_TRUE(CheckMenuCreation(
2146 launcher_controller_.get(), item_gmail, 1, one_menu_item, false));
2148 // Create a second profile and switch to that user.
2149 std::string user2 = "user2";
2150 TestingProfile* profile2 = CreateMultiUserProfile(user2);
2151 SwitchActiveUser(profile2->GetProfileUserName());
2153 // No item should have content yet.
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));
2159 // Transfer the browser of the first user - it should still not show up.
2160 chrome::MultiUserWindowManager::GetInstance()->ShowWindowForUser(
2161 browser()->window()->GetNativeWindow(),
2162 user2);
2164 EXPECT_TRUE(CheckMenuCreation(
2165 launcher_controller_.get(), item_browser, 0, NULL, true));
2166 EXPECT_TRUE(CheckMenuCreation(
2167 launcher_controller_.get(), item_gmail, 0, NULL, false));
2170 // Check that V2 applications are creating items properly in the launcher when
2171 // instantiated by the current user.
2172 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
2173 V2AppHandlingTwoUsers) {
2174 InitLauncherController();
2175 // Create a profile for our second user (will be destroyed by the framework).
2176 TestingProfile* profile2 = CreateMultiUserProfile("user2");
2177 // Check that there is a browser and a app launcher.
2178 EXPECT_EQ(2, model_->item_count());
2180 // Add a v2 app.
2181 V2App v2_app(profile(), extension1_.get());
2182 EXPECT_EQ(3, model_->item_count());
2184 // After switching users the item should go away.
2185 SwitchActiveUser(profile2->GetProfileUserName());
2186 EXPECT_EQ(2, model_->item_count());
2188 // And it should come back when switching back.
2189 SwitchActiveUser(profile()->GetProfileUserName());
2190 EXPECT_EQ(3, model_->item_count());
2193 // Check that V2 applications are creating items properly in edge cases:
2194 // a background user creates a V2 app, gets active and inactive again and then
2195 // deletes the app.
2196 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
2197 V2AppHandlingTwoUsersEdgeCases) {
2198 InitLauncherController();
2199 // Create a profile for our second user (will be destroyed by the framework).
2200 TestingProfile* profile2 = CreateMultiUserProfile("user2");
2201 // Check that there is a browser and a app launcher.
2202 EXPECT_EQ(2, model_->item_count());
2204 // Switch to an inactive user.
2205 SwitchActiveUser(profile2->GetProfileUserName());
2206 EXPECT_EQ(2, model_->item_count());
2208 // Add the v2 app to the inactive user and check that no item was added to
2209 // the launcher.
2211 V2App v2_app(profile(), extension1_.get());
2212 EXPECT_EQ(2, model_->item_count());
2214 // Switch to the primary user and check that the item is shown.
2215 SwitchActiveUser(profile()->GetProfileUserName());
2216 EXPECT_EQ(3, model_->item_count());
2218 // Switch to the second user and check that the item goes away - even if the
2219 // item gets closed.
2220 SwitchActiveUser(profile2->GetProfileUserName());
2221 EXPECT_EQ(2, model_->item_count());
2224 // After the application was killed there should be still 2 items.
2225 EXPECT_EQ(2, model_->item_count());
2227 // Switching then back to the default user should not show the additional item
2228 // anymore.
2229 SwitchActiveUser(profile()->GetProfileUserName());
2230 EXPECT_EQ(2, model_->item_count());
2233 // Check that V2 applications will be made visible on the target desktop if
2234 // another window of the same type got previously teleported there.
2235 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
2236 V2AppFollowsTeleportedWindow) {
2237 InitLauncherController();
2238 chrome::MultiUserWindowManager* manager =
2239 chrome::MultiUserWindowManager::GetInstance();
2241 // Create and add three users / profiles, and go to #1's desktop.
2242 TestingProfile* profile1 = CreateMultiUserProfile("user-1");
2243 TestingProfile* profile2 = CreateMultiUserProfile("user-2");
2244 TestingProfile* profile3 = CreateMultiUserProfile("user-3");
2245 SwitchActiveUser(profile1->GetProfileUserName());
2247 // A v2 app for user #1 should be shown first and get hidden when switching to
2248 // desktop #2.
2249 V2App v2_app_1(profile1, extension1_.get());
2250 EXPECT_TRUE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2251 SwitchActiveUser(profile2->GetProfileUserName());
2252 EXPECT_FALSE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2254 // Add a v2 app for user #1 while on desktop #2 should not be shown.
2255 V2App v2_app_2(profile1, extension1_.get());
2256 EXPECT_FALSE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2257 EXPECT_FALSE(v2_app_2.window()->GetNativeWindow()->IsVisible());
2259 // Teleport the app from user #1 to the desktop #2 should show it.
2260 manager->ShowWindowForUser(v2_app_1.window()->GetNativeWindow(),
2261 profile2->GetProfileUserName());
2262 EXPECT_TRUE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2263 EXPECT_FALSE(v2_app_2.window()->GetNativeWindow()->IsVisible());
2265 // Creating a new application for user #1 on desktop #2 should teleport it
2266 // there automatically.
2267 V2App v2_app_3(profile1, extension1_.get());
2268 EXPECT_TRUE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2269 EXPECT_FALSE(v2_app_2.window()->GetNativeWindow()->IsVisible());
2270 EXPECT_TRUE(v2_app_3.window()->GetNativeWindow()->IsVisible());
2272 // Switching back to desktop#1 and creating an app for user #1 should move
2273 // the app on desktop #1.
2274 SwitchActiveUser(profile1->GetProfileUserName());
2275 V2App v2_app_4(profile1, extension1_.get());
2276 EXPECT_FALSE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2277 EXPECT_TRUE(v2_app_2.window()->GetNativeWindow()->IsVisible());
2278 EXPECT_FALSE(v2_app_3.window()->GetNativeWindow()->IsVisible());
2279 EXPECT_TRUE(v2_app_4.window()->GetNativeWindow()->IsVisible());
2281 // Switching to desktop #3 and create an app for user #1 there should land on
2282 // his own desktop (#1).
2283 SwitchActiveUser(profile3->GetProfileUserName());
2284 V2App v2_app_5(profile1, extension1_.get());
2285 EXPECT_FALSE(v2_app_5.window()->GetNativeWindow()->IsVisible());
2286 SwitchActiveUser(profile1->GetProfileUserName());
2287 EXPECT_TRUE(v2_app_5.window()->GetNativeWindow()->IsVisible());
2289 // Switching to desktop #2, hiding the app window and creating an app should
2290 // teleport there automatically.
2291 SwitchActiveUser(profile2->GetProfileUserName());
2292 v2_app_1.window()->Hide();
2293 V2App v2_app_6(profile1, extension1_.get());
2294 EXPECT_FALSE(v2_app_1.window()->GetNativeWindow()->IsVisible());
2295 EXPECT_FALSE(v2_app_2.window()->GetNativeWindow()->IsVisible());
2296 EXPECT_TRUE(v2_app_6.window()->GetNativeWindow()->IsVisible());
2299 // Check that V2 applications hide correctly on the shelf when the app window
2300 // is hidden.
2301 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest,
2302 V2AppHiddenWindows) {
2303 InitLauncherController();
2305 TestingProfile* profile2 = CreateMultiUserProfile("user-2");
2306 SwitchActiveUser(profile()->GetProfileUserName());
2307 EXPECT_EQ(2, model_->item_count());
2309 V2App v2_app_1(profile(), extension1_.get());
2310 EXPECT_EQ(3, model_->item_count());
2312 // Hide and show the app.
2313 v2_app_1.window()->Hide();
2314 EXPECT_EQ(2, model_->item_count());
2316 v2_app_1.window()->Show(extensions::AppWindow::SHOW_ACTIVE);
2317 EXPECT_EQ(3, model_->item_count());
2320 // Switch user, hide and show the app and switch back.
2321 SwitchActiveUser(profile2->GetProfileUserName());
2322 EXPECT_EQ(2, model_->item_count());
2324 v2_app_1.window()->Hide();
2325 EXPECT_EQ(2, model_->item_count());
2327 v2_app_1.window()->Show(extensions::AppWindow::SHOW_ACTIVE);
2328 EXPECT_EQ(2, model_->item_count());
2330 SwitchActiveUser(profile()->GetProfileUserName());
2331 EXPECT_EQ(3, model_->item_count());
2334 // Switch user, hide the app, switch back and then show it again.
2335 SwitchActiveUser(profile2->GetProfileUserName());
2336 EXPECT_EQ(2, model_->item_count());
2338 v2_app_1.window()->Hide();
2339 EXPECT_EQ(2, model_->item_count());
2341 SwitchActiveUser(profile()->GetProfileUserName());
2342 EXPECT_EQ(2, model_->item_count());
2344 v2_app_1.window()->Show(extensions::AppWindow::SHOW_ACTIVE);
2345 EXPECT_EQ(3, model_->item_count());
2348 // Create a second app, hide and show it and then hide both apps.
2349 V2App v2_app_2(profile(), extension1_.get());
2350 EXPECT_EQ(3, model_->item_count());
2352 v2_app_2.window()->Hide();
2353 EXPECT_EQ(3, model_->item_count());
2355 v2_app_2.window()->Show(extensions::AppWindow::SHOW_ACTIVE);
2356 EXPECT_EQ(3, model_->item_count());
2358 v2_app_1.window()->Hide();
2359 v2_app_2.window()->Hide();
2360 EXPECT_EQ(2, model_->item_count());
2363 #endif // defined(OS_CHROMEOS)
2365 // Checks that the generated menu list properly activates items.
2366 TEST_F(ChromeLauncherControllerTest, V1AppMenuExecution) {
2367 InitLauncherControllerWithBrowser();
2369 // Add |extension3_| to the launcher and add two items.
2370 GURL gmail = GURL("https://mail.google.com/mail/u");
2371 ash::ShelfID gmail_id = model_->next_id();
2372 extension_service_->AddExtension(extension3_.get());
2373 launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(gmail_url));
2374 base::string16 title1 = ASCIIToUTF16("Test1");
2375 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title1);
2376 chrome::NewTab(browser());
2377 base::string16 title2 = ASCIIToUTF16("Test2");
2378 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title2);
2380 // Check that the menu is properly set.
2381 ash::ShelfItem item_gmail;
2382 item_gmail.type = ash::TYPE_APP_SHORTCUT;
2383 item_gmail.id = gmail_id;
2384 base::string16 two_menu_items[] = {title1, title2};
2385 EXPECT_TRUE(CheckMenuCreation(
2386 launcher_controller_.get(), item_gmail, 2, two_menu_items, false));
2387 EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
2388 // Execute the second item in the list (which shouldn't do anything since that
2389 // item is per definition already the active tab).
2391 scoped_ptr<ash::ShelfMenuModel> menu(new LauncherApplicationMenuItemModel(
2392 launcher_controller_->GetApplicationList(item_gmail, 0)));
2393 // The first element in the menu is a spacing separator. On some systems
2394 // (e.g. Windows) such things do not exist. As such we check the existence
2395 // and adjust dynamically.
2396 int first_item =
2397 (menu->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR) ? 1 : 0;
2398 menu->ActivatedAt(first_item + 3);
2400 EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
2402 // Execute the first item.
2404 scoped_ptr<ash::ShelfMenuModel> menu(new LauncherApplicationMenuItemModel(
2405 launcher_controller_->GetApplicationList(item_gmail, 0)));
2406 int first_item =
2407 (menu->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR) ? 1 : 0;
2408 menu->ActivatedAt(first_item + 2);
2410 // Now the active tab should be the second item.
2411 EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
2414 // Checks that the generated menu list properly deletes items.
2415 TEST_F(ChromeLauncherControllerTest, V1AppMenuDeletionExecution) {
2416 InitLauncherControllerWithBrowser();
2418 // Add |extension3_| to the launcher and add two items.
2419 GURL gmail = GURL("https://mail.google.com/mail/u");
2420 ash::ShelfID gmail_id = model_->next_id();
2421 extension_service_->AddExtension(extension3_.get());
2422 launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(gmail_url));
2423 base::string16 title1 = ASCIIToUTF16("Test1");
2424 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title1);
2425 chrome::NewTab(browser());
2426 base::string16 title2 = ASCIIToUTF16("Test2");
2427 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title2);
2429 // Check that the menu is properly set.
2430 ash::ShelfItem item_gmail;
2431 item_gmail.type = ash::TYPE_APP_SHORTCUT;
2432 item_gmail.id = gmail_id;
2433 base::string16 two_menu_items[] = {title1, title2};
2434 EXPECT_TRUE(CheckMenuCreation(
2435 launcher_controller_.get(), item_gmail, 2, two_menu_items, false));
2437 int tabs = browser()->tab_strip_model()->count();
2438 // Activate the proper tab through the menu item.
2440 ChromeLauncherAppMenuItems items =
2441 launcher_controller_->GetApplicationList(item_gmail, 0);
2442 items[1]->Execute(0);
2443 EXPECT_EQ(tabs, browser()->tab_strip_model()->count());
2446 // Delete one tab through the menu item.
2448 ChromeLauncherAppMenuItems items =
2449 launcher_controller_->GetApplicationList(item_gmail, 0);
2450 items[1]->Execute(ui::EF_SHIFT_DOWN);
2451 EXPECT_EQ(--tabs, browser()->tab_strip_model()->count());
2455 // Tests that panels create launcher items correctly
2456 TEST_F(ChromeLauncherControllerTest, AppPanels) {
2457 InitLauncherControllerWithBrowser();
2458 // App list and Browser shortcut ShelfItems are added.
2459 EXPECT_EQ(2, model_observer_->added());
2461 TestAppIconLoaderImpl* app_icon_loader = new TestAppIconLoaderImpl();
2462 SetAppIconLoader(app_icon_loader);
2464 // Test adding an app panel
2465 std::string app_id = extension1_->id();
2466 AppWindowLauncherItemController* app_panel_controller =
2467 new AppWindowLauncherItemController(
2468 LauncherItemController::TYPE_APP_PANEL,
2469 "id",
2470 app_id,
2471 launcher_controller_.get());
2472 ash::ShelfID shelf_id1 = launcher_controller_->CreateAppLauncherItem(
2473 app_panel_controller, app_id, ash::STATUS_RUNNING);
2474 int panel_index = model_observer_->last_index();
2475 EXPECT_EQ(3, model_observer_->added());
2476 EXPECT_EQ(0, model_observer_->changed());
2477 EXPECT_EQ(1, app_icon_loader->fetch_count());
2478 model_observer_->clear_counts();
2480 // App panels should have a separate identifier than the app id
2481 EXPECT_EQ(0, launcher_controller_->GetShelfIDForAppID(app_id));
2483 // Setting the app image image should not change the panel if it set its icon
2484 app_panel_controller->set_image_set_by_controller(true);
2485 gfx::ImageSkia image;
2486 launcher_controller_->SetAppImage(app_id, image);
2487 EXPECT_EQ(0, model_observer_->changed());
2488 model_observer_->clear_counts();
2490 // Add a second app panel and verify that it get the same index as the first
2491 // one had, being added to the left of the existing panel.
2492 AppWindowLauncherItemController* app_panel_controller2 =
2493 new AppWindowLauncherItemController(
2494 LauncherItemController::TYPE_APP_PANEL,
2495 "id",
2496 app_id,
2497 launcher_controller_.get());
2499 ash::ShelfID shelf_id2 = launcher_controller_->CreateAppLauncherItem(
2500 app_panel_controller2, app_id, ash::STATUS_RUNNING);
2501 EXPECT_EQ(panel_index, model_observer_->last_index());
2502 EXPECT_EQ(1, model_observer_->added());
2503 model_observer_->clear_counts();
2505 launcher_controller_->CloseLauncherItem(shelf_id2);
2506 launcher_controller_->CloseLauncherItem(shelf_id1);
2507 EXPECT_EQ(2, model_observer_->removed());
2510 // Tests that the Gmail extension matches more then the app itself claims with
2511 // the manifest file.
2512 TEST_F(ChromeLauncherControllerTest, GmailMatching) {
2513 InitLauncherControllerWithBrowser();
2515 // Create a Gmail browser tab.
2516 chrome::NewTab(browser());
2517 base::string16 title = ASCIIToUTF16("Test");
2518 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title);
2519 content::WebContents* content =
2520 browser()->tab_strip_model()->GetActiveWebContents();
2522 // Check that the launcher controller does not recognize the running app.
2523 EXPECT_FALSE(launcher_controller_->ContentCanBeHandledByGmailApp(content));
2525 // Installing |extension3_| adds it to the launcher.
2526 ash::ShelfID gmail_id = model_->next_id();
2527 extension_service_->AddExtension(extension3_.get());
2528 EXPECT_EQ(3, model_->item_count());
2529 int gmail_index = model_->ItemIndexByID(gmail_id);
2530 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[gmail_index].type);
2531 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
2533 // Check that it is now handled.
2534 EXPECT_TRUE(launcher_controller_->ContentCanBeHandledByGmailApp(content));
2536 // Check also that the app has detected that properly.
2537 ash::ShelfItem item_gmail;
2538 item_gmail.type = ash::TYPE_APP_SHORTCUT;
2539 item_gmail.id = gmail_id;
2540 EXPECT_EQ(2U, launcher_controller_->GetApplicationList(item_gmail, 0).size());
2543 // Tests that the Gmail extension does not match the offline verison.
2544 TEST_F(ChromeLauncherControllerTest, GmailOfflineMatching) {
2545 InitLauncherControllerWithBrowser();
2547 // Create a Gmail browser tab.
2548 chrome::NewTab(browser());
2549 base::string16 title = ASCIIToUTF16("Test");
2550 NavigateAndCommitActiveTabWithTitle(browser(),
2551 GURL(offline_gmail_url),
2552 title);
2553 content::WebContents* content =
2554 browser()->tab_strip_model()->GetActiveWebContents();
2556 // Installing |extension3_| adds it to the launcher.
2557 ash::ShelfID gmail_id = model_->next_id();
2558 extension_service_->AddExtension(extension3_.get());
2559 EXPECT_EQ(3, model_->item_count());
2560 int gmail_index = model_->ItemIndexByID(gmail_id);
2561 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[gmail_index].type);
2562 EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id()));
2564 // The content should not be able to be handled by the app.
2565 EXPECT_FALSE(launcher_controller_->ContentCanBeHandledByGmailApp(content));
2568 // Verify that the launcher item positions are persisted and restored.
2569 TEST_F(ChromeLauncherControllerTest, PersistLauncherItemPositions) {
2570 InitLauncherController();
2572 TestAppTabHelperImpl* app_tab_helper = new TestAppTabHelperImpl;
2573 SetAppTabHelper(app_tab_helper);
2575 EXPECT_EQ(ash::TYPE_APP_LIST, model_->items()[0].type);
2576 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT, model_->items()[1].type);
2578 TabStripModel* tab_strip_model = browser()->tab_strip_model();
2579 EXPECT_EQ(0, tab_strip_model->count());
2580 chrome::NewTab(browser());
2581 chrome::NewTab(browser());
2582 EXPECT_EQ(2, tab_strip_model->count());
2583 app_tab_helper->SetAppID(tab_strip_model->GetWebContentsAt(0), "1");
2584 app_tab_helper->SetAppID(tab_strip_model->GetWebContentsAt(1), "2");
2586 EXPECT_FALSE(launcher_controller_->IsAppPinned("1"));
2587 launcher_controller_->PinAppWithID("1");
2588 EXPECT_TRUE(launcher_controller_->IsAppPinned("1"));
2589 launcher_controller_->PinAppWithID("2");
2591 EXPECT_EQ(ash::TYPE_APP_LIST, model_->items()[0].type);
2592 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT, model_->items()[1].type);
2593 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
2594 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[3].type);
2596 // Move browser shortcut item from index 1 to index 3.
2597 model_->Move(1, 3);
2598 EXPECT_EQ(ash::TYPE_APP_LIST, model_->items()[0].type);
2599 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[1].type);
2600 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
2601 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT, model_->items()[3].type);
2603 SetShelfItemDelegateManager(nullptr);
2604 launcher_controller_.reset();
2605 if (!ash::Shell::HasInstance()) {
2606 delete item_delegate_manager_;
2607 } else {
2608 // Clear already registered ShelfItemDelegate.
2609 ash::test::ShelfItemDelegateManagerTestAPI test(item_delegate_manager_);
2610 test.RemoveAllShelfItemDelegateForTest();
2612 model_.reset(new ash::ShelfModel);
2614 AddAppListLauncherItem();
2615 launcher_controller_.reset(
2616 ChromeLauncherController::CreateInstance(profile(), model_.get()));
2617 app_tab_helper = new TestAppTabHelperImpl;
2618 app_tab_helper->SetAppID(tab_strip_model->GetWebContentsAt(0), "1");
2619 app_tab_helper->SetAppID(tab_strip_model->GetWebContentsAt(1), "2");
2620 SetAppTabHelper(app_tab_helper);
2621 if (!ash::Shell::HasInstance()) {
2622 item_delegate_manager_ = new ash::ShelfItemDelegateManager(model_.get());
2623 SetShelfItemDelegateManager(item_delegate_manager_);
2625 launcher_controller_->Init();
2627 // Check ShelfItems are restored after resetting ChromeLauncherController.
2628 EXPECT_EQ(ash::TYPE_APP_LIST, model_->items()[0].type);
2629 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[1].type);
2630 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type);
2631 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT, model_->items()[3].type);
2634 // Verifies pinned apps are persisted and restored.
2635 TEST_F(ChromeLauncherControllerTest, PersistPinned) {
2636 InitLauncherControllerWithBrowser();
2637 size_t initial_size = model_->items().size();
2639 TabStripModel* tab_strip_model = browser()->tab_strip_model();
2640 EXPECT_EQ(1, tab_strip_model->count());
2642 TestAppTabHelperImpl* app_tab_helper = new TestAppTabHelperImpl;
2643 app_tab_helper->SetAppID(tab_strip_model->GetWebContentsAt(0), "1");
2644 SetAppTabHelper(app_tab_helper);
2646 TestAppIconLoaderImpl* app_icon_loader = new TestAppIconLoaderImpl;
2647 SetAppIconLoader(app_icon_loader);
2648 EXPECT_EQ(0, app_icon_loader->fetch_count());
2650 launcher_controller_->PinAppWithID("1");
2651 ash::ShelfID id = launcher_controller_->GetShelfIDForAppID("1");
2652 int app_index = model_->ItemIndexByID(id);
2653 EXPECT_EQ(1, app_icon_loader->fetch_count());
2654 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[app_index].type);
2655 EXPECT_TRUE(launcher_controller_->IsAppPinned("1"));
2656 EXPECT_FALSE(launcher_controller_->IsAppPinned("0"));
2657 EXPECT_EQ(initial_size + 1, model_->items().size());
2659 SetShelfItemDelegateManager(nullptr);
2660 launcher_controller_.reset();
2661 if (!ash::Shell::HasInstance()) {
2662 delete item_delegate_manager_;
2663 } else {
2664 // Clear already registered ShelfItemDelegate.
2665 ash::test::ShelfItemDelegateManagerTestAPI test(item_delegate_manager_);
2666 test.RemoveAllShelfItemDelegateForTest();
2668 model_.reset(new ash::ShelfModel);
2670 AddAppListLauncherItem();
2671 launcher_controller_.reset(
2672 ChromeLauncherController::CreateInstance(profile(), model_.get()));
2673 app_tab_helper = new TestAppTabHelperImpl;
2674 app_tab_helper->SetAppID(tab_strip_model->GetWebContentsAt(0), "1");
2675 SetAppTabHelper(app_tab_helper);
2676 app_icon_loader = new TestAppIconLoaderImpl;
2677 SetAppIconLoader(app_icon_loader);
2678 if (!ash::Shell::HasInstance()) {
2679 item_delegate_manager_ = new ash::ShelfItemDelegateManager(model_.get());
2680 SetShelfItemDelegateManager(item_delegate_manager_);
2682 launcher_controller_->Init();
2684 EXPECT_EQ(1, app_icon_loader->fetch_count());
2685 ASSERT_EQ(initial_size + 1, model_->items().size());
2686 EXPECT_TRUE(launcher_controller_->IsAppPinned("1"));
2687 EXPECT_FALSE(launcher_controller_->IsAppPinned("0"));
2688 EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[app_index].type);
2690 launcher_controller_->UnpinAppWithID("1");
2691 ASSERT_EQ(initial_size, model_->items().size());