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