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