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/launcher_application_menu_item_model.h"
28 #include "chrome/browser/ui/ash/launcher/launcher_item_controller.h"
29 #include "chrome/browser/ui/ash/launcher/shell_window_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/base/models/menu_model.h"
48 #if defined(OS_CHROMEOS)
49 #include "apps/app_window_contents.h"
50 #include "apps/app_window_registry.h"
51 #include "apps/ui/native_app_window.h"
52 #include "ash/test/test_session_state_delegate.h"
53 #include "ash/test/test_shell_delegate.h"
54 #include "chrome/browser/chromeos/login/fake_user_manager.h"
55 #include "chrome/browser/ui/apps/chrome_shell_window_delegate.h"
56 #include "chrome/browser/ui/ash/launcher/browser_status_monitor.h"
57 #include "chrome/browser/ui/ash/launcher/shell_window_launcher_controller.h"
58 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
59 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
60 #include "chrome/common/chrome_constants.h"
61 #include "chrome/common/chrome_switches.h"
62 #include "chrome/test/base/testing_browser_process.h"
63 #include "chrome/test/base/testing_profile_manager.h"
64 #include "content/public/browser/web_contents_observer.h"
65 #include "content/public/test/test_utils.h"
66 #include "ui/aura/window.h"
67 #include "ui/views/test/test_views_delegate.h"
70 using base::ASCIIToUTF16
;
71 using extensions::Extension
;
72 using extensions::Manifest
;
73 using extensions::UnloadedExtensionInfo
;
76 const char* offline_gmail_url
= "https://mail.google.com/mail/mu/u";
77 const char* gmail_url
= "https://mail.google.com/mail/u";
78 const char* kGmailLaunchURL
= "https://mail.google.com/mail/ca";
80 // As defined in /chromeos/dbus/cryptohome_client.cc.
81 const char kUserIdHashSuffix
[] = "-hash";
83 // An extension prefix.
84 const char kCrxAppPrefix
[] = "_crx_";
86 // ShelfModelObserver implementation that tracks what messages are invoked.
87 class TestShelfModelObserver
: public ash::ShelfModelObserver
{
89 TestShelfModelObserver()
95 virtual ~TestShelfModelObserver() {
98 // Overridden from ash::ShelfModelObserver:
99 virtual void ShelfItemAdded(int index
) OVERRIDE
{
104 virtual void ShelfItemRemoved(int index
, ash::ShelfID id
) OVERRIDE
{
109 virtual void ShelfItemChanged(int index
,
110 const ash::ShelfItem
& old_item
) OVERRIDE
{
115 virtual void ShelfItemMoved(int start_index
, int target_index
) OVERRIDE
{
116 last_index_
= target_index
;
119 virtual void ShelfStatusChanged() OVERRIDE
{
122 void clear_counts() {
129 int added() const { return added_
; }
130 int removed() const { return removed_
; }
131 int changed() const { return changed_
; }
132 int last_index() const { return last_index_
; }
140 DISALLOW_COPY_AND_ASSIGN(TestShelfModelObserver
);
143 // Test implementation of AppIconLoader.
144 class TestAppIconLoaderImpl
: public extensions::AppIconLoader
{
146 TestAppIconLoaderImpl() : fetch_count_(0) {
149 virtual ~TestAppIconLoaderImpl() {
152 // AppIconLoader implementation:
153 virtual void FetchImage(const std::string
& id
) OVERRIDE
{
157 virtual void ClearImage(const std::string
& id
) OVERRIDE
{
160 virtual void UpdateImage(const std::string
& id
) OVERRIDE
{
163 int fetch_count() const { return fetch_count_
; }
168 DISALLOW_COPY_AND_ASSIGN(TestAppIconLoaderImpl
);
171 // Test implementation of AppTabHelper.
172 class TestAppTabHelperImpl
: public ChromeLauncherController::AppTabHelper
{
174 TestAppTabHelperImpl() {}
175 virtual ~TestAppTabHelperImpl() {}
177 // Sets the id for the specified tab. The id is removed if Remove() is
179 void SetAppID(content::WebContents
* tab
, const std::string
& id
) {
180 tab_id_map_
[tab
] = id
;
183 // Returns true if there is an id registered for |tab|.
184 bool HasAppID(content::WebContents
* tab
) const {
185 return tab_id_map_
.find(tab
) != tab_id_map_
.end();
188 // AppTabHelper implementation:
189 virtual std::string
GetAppID(content::WebContents
* tab
) OVERRIDE
{
190 return tab_id_map_
.find(tab
) != tab_id_map_
.end() ? tab_id_map_
[tab
] :
194 virtual bool IsValidIDForCurrentUser(const std::string
& id
) OVERRIDE
{
195 for (TabToStringMap::const_iterator i
= tab_id_map_
.begin();
196 i
!= tab_id_map_
.end(); ++i
) {
203 virtual void SetCurrentUser(Profile
* profile
) OVERRIDE
{
204 // We can ignore this for now.
208 typedef std::map
<content::WebContents
*, std::string
> TabToStringMap
;
210 TabToStringMap tab_id_map_
;
212 DISALLOW_COPY_AND_ASSIGN(TestAppTabHelperImpl
);
215 // Test implementation of a V2 app launcher item controller.
216 class TestV2AppLauncherItemController
: public LauncherItemController
{
218 TestV2AppLauncherItemController(const std::string
& app_id
,
219 ChromeLauncherController
* controller
)
220 : LauncherItemController(LauncherItemController::TYPE_APP
,
225 virtual ~TestV2AppLauncherItemController() {}
227 // Override for LauncherItemController:
228 virtual bool IsOpen() const OVERRIDE
{ return true; }
229 virtual bool IsVisible() const OVERRIDE
{ return true; }
230 virtual void Launch(ash::LaunchSource source
, int event_flags
) OVERRIDE
{}
231 virtual bool Activate(ash::LaunchSource source
) OVERRIDE
{ return false; }
232 virtual void Close() OVERRIDE
{}
233 virtual bool ItemSelected(const ui::Event
& event
) OVERRIDE
{ return false; }
234 virtual base::string16
GetTitle() OVERRIDE
{ return base::string16(); }
235 virtual ChromeLauncherAppMenuItems
GetApplicationList(
236 int event_flags
) OVERRIDE
{
237 ChromeLauncherAppMenuItems items
;
239 new ChromeLauncherAppMenuItem(base::string16(), NULL
, false));
241 new ChromeLauncherAppMenuItem(base::string16(), NULL
, false));
244 virtual ui::MenuModel
* CreateContextMenu(aura::Window
* root_window
) OVERRIDE
{
247 virtual ash::ShelfMenuModel
* CreateApplicationMenu(int event_flags
) OVERRIDE
{
250 virtual bool IsDraggable() OVERRIDE
{ return false; }
251 virtual bool ShouldShowTooltip() OVERRIDE
{ return false; }
254 DISALLOW_COPY_AND_ASSIGN(TestV2AppLauncherItemController
);
259 class ChromeLauncherControllerTest
: public BrowserWithTestWindowTest
{
261 ChromeLauncherControllerTest()
262 : BrowserWithTestWindowTest(
263 Browser::TYPE_TABBED
,
264 chrome::HOST_DESKTOP_TYPE_ASH
,
266 test_controller_(NULL
),
267 extension_service_(NULL
) {
270 virtual ~ChromeLauncherControllerTest() {
273 virtual void SetUp() OVERRIDE
{
274 BrowserWithTestWindowTest::SetUp();
276 model_
.reset(new ash::ShelfModel
);
277 model_observer_
.reset(new TestShelfModelObserver
);
278 model_
->AddObserver(model_observer_
.get());
280 if (ash::Shell::HasInstance()) {
281 item_delegate_manager_
=
282 ash::Shell::GetInstance()->shelf_item_delegate_manager();
284 item_delegate_manager_
=
285 new ash::ShelfItemDelegateManager(model_
.get());
288 base::DictionaryValue manifest
;
289 manifest
.SetString(extensions::manifest_keys::kName
,
290 "launcher controller test extension");
291 manifest
.SetString(extensions::manifest_keys::kVersion
, "1");
292 manifest
.SetString(extensions::manifest_keys::kDescription
,
293 "for testing pinned apps");
295 extensions::TestExtensionSystem
* extension_system(
296 static_cast<extensions::TestExtensionSystem
*>(
297 extensions::ExtensionSystem::Get(profile())));
298 extension_service_
= extension_system
->CreateExtensionService(
299 CommandLine::ForCurrentProcess(), base::FilePath(), false);
302 extension1_
= Extension::Create(base::FilePath(), Manifest::UNPACKED
,
305 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
307 extension2_
= Extension::Create(base::FilePath(), Manifest::UNPACKED
,
310 "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb",
312 // Fake gmail extension.
313 base::DictionaryValue manifest_gmail
;
314 manifest_gmail
.SetString(extensions::manifest_keys::kName
,
315 "Gmail launcher controller test extension");
316 manifest_gmail
.SetString(extensions::manifest_keys::kVersion
, "1");
317 manifest_gmail
.SetString(extensions::manifest_keys::kDescription
,
318 "for testing pinned Gmail");
319 manifest_gmail
.SetString(extensions::manifest_keys::kLaunchWebURL
,
321 base::ListValue
* list
= new base::ListValue();
322 list
->Append(base::Value::CreateStringValue("*://mail.google.com/mail/ca"));
323 manifest_gmail
.Set(extensions::manifest_keys::kWebURLs
, list
);
325 extension3_
= Extension::Create(base::FilePath(), Manifest::UNPACKED
,
328 extension_misc::kGmailAppId
,
331 // Fake search extension.
332 extension4_
= Extension::Create(base::FilePath(), Manifest::UNPACKED
,
335 extension_misc::kGoogleSearchAppId
,
337 extension5_
= Extension::Create(base::FilePath(), Manifest::UNPACKED
,
340 "cccccccccccccccccccccccccccccccc",
342 extension6_
= Extension::Create(base::FilePath(), Manifest::UNPACKED
,
345 "dddddddddddddddddddddddddddddddd",
347 extension7_
= Extension::Create(base::FilePath(), Manifest::UNPACKED
,
350 "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee",
352 extension8_
= Extension::Create(base::FilePath(), Manifest::UNPACKED
,
355 "ffffffffffffffffffffffffffffffff",
359 // Creates a running V2 app (not pinned) of type |app_id|.
360 virtual void CreateRunningV2App(const std::string
& app_id
) {
361 DCHECK(!test_controller_
);
363 launcher_controller_
->CreateAppShortcutLauncherItemWithType(
365 model_
->item_count(),
366 ash::TYPE_PLATFORM_APP
);
368 // Change the created launcher controller into a V2 app controller.
369 test_controller_
= new TestV2AppLauncherItemController(app_id
,
370 launcher_controller_
.get());
371 launcher_controller_
->SetItemController(id
, test_controller_
);
374 // Sets the stage for a multi user test.
375 virtual void SetUpMultiUserScenario(base::ListValue
* user_a
,
376 base::ListValue
* user_b
) {
377 InitLauncherController();
378 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
380 // Set an empty pinned pref to begin with.
381 base::ListValue no_user
;
382 SetShelfChromeIconIndex(0);
383 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
385 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
387 // Assume all applications have been added already.
388 extension_service_
->AddExtension(extension1_
.get());
389 extension_service_
->AddExtension(extension2_
.get());
390 extension_service_
->AddExtension(extension3_
.get());
391 extension_service_
->AddExtension(extension4_
.get());
392 extension_service_
->AddExtension(extension5_
.get());
393 extension_service_
->AddExtension(extension6_
.get());
394 extension_service_
->AddExtension(extension7_
.get());
395 extension_service_
->AddExtension(extension8_
.get());
396 // There should be nothing in the list by now.
397 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
399 // Set user a preferences.
400 InsertPrefValue(user_a
, 0, extension1_
->id());
401 InsertPrefValue(user_a
, 1, extension2_
->id());
402 InsertPrefValue(user_a
, 2, extension3_
->id());
403 InsertPrefValue(user_a
, 3, extension4_
->id());
404 InsertPrefValue(user_a
, 4, extension5_
->id());
405 InsertPrefValue(user_a
, 5, extension6_
->id());
407 // Set user b preferences.
408 InsertPrefValue(user_b
, 0, extension7_
->id());
409 InsertPrefValue(user_b
, 1, extension8_
->id());
412 virtual void TearDown() OVERRIDE
{
413 if (!ash::Shell::HasInstance())
414 delete item_delegate_manager_
;
415 model_
->RemoveObserver(model_observer_
.get());
416 model_observer_
.reset();
417 launcher_controller_
.reset();
420 BrowserWithTestWindowTest::TearDown();
423 void AddAppListLauncherItem() {
424 ash::ShelfItem app_list
;
425 app_list
.type
= ash::TYPE_APP_LIST
;
426 model_
->Add(app_list
);
429 void InitLauncherController() {
430 AddAppListLauncherItem();
431 launcher_controller_
.reset(
432 new ChromeLauncherController(profile(), model_
.get()));
433 if (!ash::Shell::HasInstance())
434 SetShelfItemDelegateManager(item_delegate_manager_
);
435 launcher_controller_
->Init();
438 void InitLauncherControllerWithBrowser() {
439 chrome::NewTab(browser());
440 BrowserList::SetLastActive(browser());
441 InitLauncherController();
444 void SetAppIconLoader(extensions::AppIconLoader
* loader
) {
445 launcher_controller_
->SetAppIconLoaderForTest(loader
);
448 void SetAppTabHelper(ChromeLauncherController::AppTabHelper
* helper
) {
449 launcher_controller_
->SetAppTabHelperForTest(helper
);
452 void SetShelfItemDelegateManager(ash::ShelfItemDelegateManager
* manager
) {
453 launcher_controller_
->SetShelfItemDelegateManagerForTest(manager
);
456 void InsertPrefValue(base::ListValue
* pref_value
,
458 const std::string
& extension_id
) {
459 base::DictionaryValue
* entry
= new base::DictionaryValue();
460 entry
->SetString(ash::kPinnedAppsPrefAppIDPath
, extension_id
);
461 pref_value
->Insert(index
, entry
);
464 // Gets the currently configured app launchers from the controller.
465 void GetAppLaunchers(ChromeLauncherController
* controller
,
466 std::vector
<std::string
>* launchers
) {
468 for (ash::ShelfItems::const_iterator
iter(model_
->items().begin());
469 iter
!= model_
->items().end(); ++iter
) {
470 ChromeLauncherController::IDToItemControllerMap::const_iterator
471 entry(controller
->id_to_item_controller_map_
.find(iter
->id
));
472 if (iter
->type
== ash::TYPE_APP_SHORTCUT
&&
473 entry
!= controller
->id_to_item_controller_map_
.end()) {
474 launchers
->push_back(entry
->second
->app_id());
479 // Get the setup of the currently shown launcher items in one string.
480 // Each pinned element will start with a big letter, each running but not
481 // pinned V1 app will start with a small letter and each running but not
482 // pinned V2 app will start with a '*' + small letter.
483 std::string
GetPinnedAppStatus() {
485 for (int i
= 0; i
< model_
->item_count(); i
++) {
488 switch (model_
->items()[i
].type
) {
489 case ash::TYPE_PLATFORM_APP
:
492 case ash::TYPE_WINDOWED_APP
: {
493 const std::string
& app
=
494 launcher_controller_
->GetAppIDForShelfID(model_
->items()[i
].id
);
495 if (app
== extension1_
->id()) {
498 launcher_controller_
->IsAppPinned(extension1_
->id()));
499 } else if (app
== extension2_
->id()) {
502 launcher_controller_
->IsAppPinned(extension2_
->id()));
503 } else if (app
== extension3_
->id()) {
506 launcher_controller_
->IsAppPinned(extension3_
->id()));
507 } else if (app
== extension4_
->id()) {
510 launcher_controller_
->IsAppPinned(extension4_
->id()));
511 } else if (app
== extension5_
->id()) {
514 launcher_controller_
->IsAppPinned(extension5_
->id()));
515 } else if (app
== extension6_
->id()) {
518 launcher_controller_
->IsAppPinned(extension6_
->id()));
519 } else if (app
== extension7_
->id()) {
522 launcher_controller_
->IsAppPinned(extension7_
->id()));
523 } else if (app
== extension8_
->id()) {
526 launcher_controller_
->IsAppPinned(extension8_
->id()));
532 case ash::TYPE_APP_SHORTCUT
: {
533 const std::string
& app
=
534 launcher_controller_
->GetAppIDForShelfID(model_
->items()[i
].id
);
535 if (app
== extension1_
->id()) {
537 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
538 } else if (app
== extension2_
->id()) {
540 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension2_
->id()));
541 } else if (app
== extension3_
->id()) {
543 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension3_
->id()));
544 } else if (app
== extension4_
->id()) {
546 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension4_
->id()));
547 } else if (app
== extension5_
->id()) {
549 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension5_
->id()));
550 } else if (app
== extension6_
->id()) {
552 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension6_
->id()));
553 } else if (app
== extension7_
->id()) {
555 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension7_
->id()));
556 } else if (app
== extension8_
->id()) {
558 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension8_
->id()));
564 case ash::TYPE_BROWSER_SHORTCUT
:
567 case ash::TYPE_APP_LIST
:
578 // Set the index at which the chrome icon should be.
579 void SetShelfChromeIconIndex(int index
) {
580 profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex
,
584 // Remember the order of unpinned but running applications for the current
586 void RememberUnpinnedRunningApplicationOrder() {
587 launcher_controller_
->RememberUnpinnedRunningApplicationOrder();
590 // Restore the order of running but unpinned applications for a given user.
591 void RestoreUnpinnedRunningApplicationOrder(const std::string
& user_id
) {
592 launcher_controller_
->RestoreUnpinnedRunningApplicationOrder(user_id
);
595 // Needed for extension service & friends to work.
596 scoped_refptr
<Extension
> extension1_
;
597 scoped_refptr
<Extension
> extension2_
;
598 scoped_refptr
<Extension
> extension3_
;
599 scoped_refptr
<Extension
> extension4_
;
600 scoped_refptr
<Extension
> extension5_
;
601 scoped_refptr
<Extension
> extension6_
;
602 scoped_refptr
<Extension
> extension7_
;
603 scoped_refptr
<Extension
> extension8_
;
604 scoped_ptr
<ChromeLauncherController
> launcher_controller_
;
605 scoped_ptr
<TestShelfModelObserver
> model_observer_
;
606 scoped_ptr
<ash::ShelfModel
> model_
;
608 // |item_delegate_manager_| owns |test_controller_|.
609 LauncherItemController
* test_controller_
;
611 ExtensionService
* extension_service_
;
613 ash::ShelfItemDelegateManager
* item_delegate_manager_
;
616 DISALLOW_COPY_AND_ASSIGN(ChromeLauncherControllerTest
);
619 // The testing framework to test the legacy shelf layout.
620 class LegacyShelfLayoutChromeLauncherControllerTest
621 : public ChromeLauncherControllerTest
{
623 LegacyShelfLayoutChromeLauncherControllerTest() {
626 virtual ~LegacyShelfLayoutChromeLauncherControllerTest() {
629 // Overwrite the Setup function to use the legacy shelf layout option.
630 virtual void SetUp() OVERRIDE
{
631 CommandLine::ForCurrentProcess()->AppendSwitch(
632 ash::switches::kAshDisableAlternateShelfLayout
);
633 ChromeLauncherControllerTest::SetUp();
637 DISALLOW_COPY_AND_ASSIGN(LegacyShelfLayoutChromeLauncherControllerTest
);
640 #if defined(OS_CHROMEOS)
641 // A browser window proxy which is able to associate an aura native window with
643 class TestBrowserWindowAura
: public TestBrowserWindow
{
645 // |native_window| will still be owned by the caller after the constructor
647 explicit TestBrowserWindowAura(aura::Window
* native_window
)
648 : native_window_(native_window
) {
650 virtual ~TestBrowserWindowAura() {}
652 virtual gfx::NativeWindow
GetNativeWindow() OVERRIDE
{
653 return native_window_
.get();
656 Browser
* browser() { return browser_
.get(); }
658 void CreateBrowser(const Browser::CreateParams
& params
) {
659 Browser::CreateParams create_params
= params
;
660 create_params
.window
= this;
661 browser_
.reset(new Browser(create_params
));
665 scoped_ptr
<Browser
> browser_
;
666 scoped_ptr
<aura::Window
> native_window_
;
668 DISALLOW_COPY_AND_ASSIGN(TestBrowserWindowAura
);
671 // Creates a test browser window which has a native window.
672 scoped_ptr
<TestBrowserWindowAura
> CreateTestBrowserWindow(
673 const Browser::CreateParams
& params
) {
675 aura::Window
* window
= new aura::Window(NULL
);
677 window
->SetType(ui::wm::WINDOW_TYPE_NORMAL
);
678 window
->Init(aura::WINDOW_LAYER_TEXTURED
);
681 scoped_ptr
<TestBrowserWindowAura
> browser_window(
682 new TestBrowserWindowAura(window
));
683 browser_window
->CreateBrowser(params
);
684 return browser_window
.Pass();
687 // A views delegate which allows creating app windows.
688 class TestViewsDelegateForAppTest
: public views::TestViewsDelegate
{
690 TestViewsDelegateForAppTest() {}
691 virtual ~TestViewsDelegateForAppTest() {}
693 // views::TestViewsDelegate overrides.
694 virtual void OnBeforeWidgetInit(
695 views::Widget::InitParams
* params
,
696 views::internal::NativeWidgetDelegate
* delegate
) OVERRIDE
{
697 if (!params
->parent
&& !params
->context
) {
698 // If the window has neither a parent nor a context we add the root window
700 params
->parent
= ash::Shell::GetInstance()->GetPrimaryRootWindow();
705 DISALLOW_COPY_AND_ASSIGN(TestViewsDelegateForAppTest
);
708 // Watches WebContents and blocks until it is destroyed. This is needed for
709 // the destruction of a V2 application.
710 class WebContentsDestroyedWatcher
: public content::WebContentsObserver
{
712 explicit WebContentsDestroyedWatcher(content::WebContents
* web_contents
)
713 : content::WebContentsObserver(web_contents
),
714 message_loop_runner_(new content::MessageLoopRunner
) {
715 EXPECT_TRUE(web_contents
!= NULL
);
717 virtual ~WebContentsDestroyedWatcher() {}
719 // Waits until the WebContents is destroyed.
721 message_loop_runner_
->Run();
725 // Overridden WebContentsObserver methods.
726 virtual void WebContentsDestroyed(
727 content::WebContents
* web_contents
) OVERRIDE
{
728 message_loop_runner_
->Quit();
731 scoped_refptr
<content::MessageLoopRunner
> message_loop_runner_
;
733 DISALLOW_COPY_AND_ASSIGN(WebContentsDestroyedWatcher
);
736 // A V1 windowed application.
737 class V1App
: public TestBrowserWindow
{
739 V1App(Profile
* profile
, const std::string
& app_name
) {
741 native_window_
.reset(new aura::Window(NULL
));
742 native_window_
->set_id(0);
743 native_window_
->SetType(ui::wm::WINDOW_TYPE_POPUP
);
744 native_window_
->Init(aura::WINDOW_LAYER_TEXTURED
);
745 native_window_
->Show();
747 Browser::CreateParams params
= Browser::CreateParams::CreateForApp(
749 kCrxAppPrefix
+ app_name
,
752 chrome::HOST_DESKTOP_TYPE_ASH
);
753 params
.window
= this;
754 browser_
.reset(new Browser(params
));
755 chrome::AddTabAt(browser_
.get(), GURL(), 0, true);
759 // close all tabs. Note that we do not need to destroy the browser itself.
760 browser_
->tab_strip_model()->CloseAllTabs();
763 Browser
* browser() { return browser_
.get(); }
765 // TestBrowserWindow override:
766 virtual gfx::NativeWindow
GetNativeWindow() OVERRIDE
{
767 return native_window_
.get();
771 // The associated browser with this app.
772 scoped_ptr
<Browser
> browser_
;
774 // The native window we use.
775 scoped_ptr
<aura::Window
> native_window_
;
777 DISALLOW_COPY_AND_ASSIGN(V1App
);
780 // A V2 application which gets created with an |extension| and for a |profile|.
781 // Upon destruction it will properly close the application.
784 V2App(Profile
* profile
, const extensions::Extension
* extension
) {
785 window_
= new apps::AppWindow(
786 profile
, new ChromeShellWindowDelegate(), extension
);
787 apps::AppWindow::CreateParams params
= apps::AppWindow::CreateParams();
789 GURL(std::string()), new apps::AppWindowContentsImpl(window_
), params
);
793 WebContentsDestroyedWatcher
destroyed_watcher(window_
->web_contents());
794 window_
->GetBaseWindow()->Close();
795 destroyed_watcher
.Wait();
799 // The app window which represents the application. Note that the window
800 // deletes itself asynchronously after window_->GetBaseWindow()->Close() gets
802 apps::AppWindow
* window_
;
804 DISALLOW_COPY_AND_ASSIGN(V2App
);
807 // The testing framework to test multi profile scenarios.
808 class MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
809 : public ChromeLauncherControllerTest
{
811 MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest() {
814 virtual ~MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest() {
817 // Overwrite the Setup function to enable multi profile and needed objects.
818 virtual void SetUp() OVERRIDE
{
819 profile_manager_
.reset(
820 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
822 ASSERT_TRUE(profile_manager_
->SetUp());
824 // AvatarMenu and multiple profiles works after user logged in.
825 profile_manager_
->SetLoggedIn(true);
827 // Enabling multi profile requires several flags to be set.
828 CommandLine::ForCurrentProcess()->AppendSwitch(switches::kMultiProfiles
);
830 // Initialize the UserManager singleton to a fresh FakeUserManager instance.
831 user_manager_enabler_
.reset(
832 new chromeos::ScopedUserManagerEnabler(new chromeos::FakeUserManager
));
834 // Initialize the rest.
835 ChromeLauncherControllerTest::SetUp();
837 // Get some base objects.
838 session_delegate_
= static_cast<ash::test::TestSessionStateDelegate
*>(
839 ash::Shell::GetInstance()->session_state_delegate());
840 session_delegate_
->set_logged_in_users(2);
841 shell_delegate_
= static_cast<ash::test::TestShellDelegate
*>(
842 ash::Shell::GetInstance()->delegate());
843 shell_delegate_
->set_multi_profiles_enabled(true);
846 virtual void TearDown() {
847 ChromeLauncherControllerTest::TearDown();
848 user_manager_enabler_
.reset();
849 for (ProfileToNameMap::iterator it
= created_profiles_
.begin();
850 it
!= created_profiles_
.end(); ++it
)
851 profile_manager_
->DeleteTestingProfile(it
->second
);
853 // A Task is leaked if we don't destroy everything, then run the message
855 base::MessageLoop::current()->PostTask(FROM_HERE
,
856 base::MessageLoop::QuitClosure());
857 base::MessageLoop::current()->Run();
860 // Creates a profile for a given |user_name|. Note that this class will keep
861 // the ownership of the created object.
862 TestingProfile
* CreateMultiUserProfile(const std::string
& user_name
) {
863 std::string email_string
= user_name
+ "@example.com";
865 // Add a user to the fake user manager.
866 GetFakeUserManager()->AddUser(email_string
);
868 GetFakeUserManager()->UserLoggedIn(
870 email_string
+ kUserIdHashSuffix
,
873 std::string profile_name
=
874 chrome::kProfileDirPrefix
+ email_string
+ kUserIdHashSuffix
;
875 TestingProfile
* profile
= profile_manager()->CreateTestingProfile(
877 scoped_ptr
<PrefServiceSyncable
>(),
878 ASCIIToUTF16(email_string
), 0, std::string(),
879 TestingProfile::TestingFactories());
880 profile
->set_profile_name(email_string
);
881 EXPECT_TRUE(profile
);
882 // Remember the profile name so that we can destroy it upon destruction.
883 created_profiles_
[profile
] = profile_name
;
887 // Switch to another user.
888 void SwitchActiveUser(const std::string
& name
) {
889 session_delegate()->SwitchActiveUser(name
);
890 GetFakeUserManager()->SwitchActiveUser(name
);
891 launcher_controller_
->browser_status_monitor_for_test()->
892 ActiveUserChanged(name
);
893 launcher_controller_
->shell_window_controller_for_test()->
894 ActiveUserChanged(name
);
897 // Creates a browser with a |profile| and load a tab with a |title| and |url|.
898 Browser
* CreateBrowserAndTabWithProfile(Profile
* profile
,
899 const std::string
& title
,
900 const std::string
& url
) {
901 Browser::CreateParams
params(profile
, chrome::HOST_DESKTOP_TYPE_ASH
);
902 Browser
* browser
= chrome::CreateBrowserWithTestWindowForParams(¶ms
);
903 chrome::NewTab(browser
);
905 BrowserList::SetLastActive(browser
);
906 NavigateAndCommitActiveTabWithTitle(
907 browser
, GURL(url
), ASCIIToUTF16(title
));
911 // Creates a running V1 application.
912 // Note that with the use of the app_tab_helper as done below, this is only
913 // usable with a single v1 application.
914 V1App
* CreateRunningV1App(Profile
* profile
,
915 const std::string
& app_name
,
916 const std::string
& url
) {
917 V1App
* v1_app
= new V1App(profile
, app_name
);
918 // Create a new app tab helper and assign it to the launcher so that this
919 // app gets properly detected.
920 // TODO(skuhne): Create a more intelligent app tab helper which is able to
921 // detect all running apps properly.
922 TestAppTabHelperImpl
* app_tab_helper
= new TestAppTabHelperImpl
;
923 app_tab_helper
->SetAppID(
924 v1_app
->browser()->tab_strip_model()->GetWebContentsAt(0),
926 SetAppTabHelper(app_tab_helper
);
928 NavigateAndCommitActiveTabWithTitle(
929 v1_app
->browser(), GURL(url
), ASCIIToUTF16(""));
933 ash::test::TestSessionStateDelegate
*
934 session_delegate() { return session_delegate_
; }
935 ash::test::TestShellDelegate
* shell_delegate() { return shell_delegate_
; }
937 // Override BrowserWithTestWindowTest:
938 virtual TestingProfile
* CreateProfile() OVERRIDE
{
939 return CreateMultiUserProfile("user1");
941 virtual void DestroyProfile(TestingProfile
* profile
) OVERRIDE
{
942 // Delete the profile through our profile manager.
943 ProfileToNameMap::iterator it
= created_profiles_
.find(profile
);
944 DCHECK(it
!= created_profiles_
.end());
945 profile_manager_
->DeleteTestingProfile(it
->second
);
946 created_profiles_
.erase(it
);
949 virtual views::ViewsDelegate
* CreateViewsDelegate() OVERRIDE
{
950 return new TestViewsDelegateForAppTest
;
954 typedef std::map
<Profile
*, std::string
> ProfileToNameMap
;
955 TestingProfileManager
* profile_manager() { return profile_manager_
.get(); }
957 chromeos::FakeUserManager
* GetFakeUserManager() {
958 return static_cast<chromeos::FakeUserManager
*>(
959 chromeos::UserManager::Get());
962 scoped_ptr
<TestingProfileManager
> profile_manager_
;
963 scoped_ptr
<chromeos::ScopedUserManagerEnabler
> user_manager_enabler_
;
965 ash::test::TestSessionStateDelegate
* session_delegate_
;
966 ash::test::TestShellDelegate
* shell_delegate_
;
968 ProfileToNameMap created_profiles_
;
970 DISALLOW_COPY_AND_ASSIGN(
971 MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
);
973 #endif // defined(OS_CHROMEOS)
975 TEST_F(LegacyShelfLayoutChromeLauncherControllerTest
, DefaultApps
) {
976 InitLauncherController();
977 // Model should only contain the browser shortcut and app list items.
978 EXPECT_EQ(2, model_
->item_count());
979 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
980 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
981 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
983 // Installing |extension3_| should add it to the launcher - behind the
985 extension_service_
->AddExtension(extension3_
.get());
986 EXPECT_EQ("Chrome, App3, AppList", GetPinnedAppStatus());
987 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
988 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
991 // Check that the restauration of launcher items is happening in the same order
992 // as the user has pinned them (on another system) when they are synced reverse
994 TEST_F(LegacyShelfLayoutChromeLauncherControllerTest
,
995 RestoreDefaultAppsReverseOrder
) {
996 InitLauncherController();
998 base::ListValue policy_value
;
999 InsertPrefValue(&policy_value
, 0, extension1_
->id());
1000 InsertPrefValue(&policy_value
, 1, extension2_
->id());
1001 InsertPrefValue(&policy_value
, 2, extension3_
->id());
1002 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1003 policy_value
.DeepCopy());
1004 EXPECT_EQ(0, profile()->GetPrefs()->GetInteger(prefs::kShelfChromeIconIndex
));
1005 // Model should only contain the browser shortcut and app list items.
1006 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1007 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1008 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1009 EXPECT_EQ("Chrome, AppList", GetPinnedAppStatus());
1011 // Installing |extension3_| should add it to the shelf - behind the
1013 ash::ShelfItem item
;
1014 extension_service_
->AddExtension(extension3_
.get());
1015 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1016 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1017 EXPECT_EQ("Chrome, App3, AppList", GetPinnedAppStatus());
1019 // Installing |extension2_| should add it to the launcher - behind the
1020 // chrome icon, but in first location.
1021 extension_service_
->AddExtension(extension2_
.get());
1022 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1023 EXPECT_EQ("Chrome, App2, App3, AppList", GetPinnedAppStatus());
1025 // Installing |extension1_| should add it to the launcher - behind the
1026 // chrome icon, but in first location.
1027 extension_service_
->AddExtension(extension1_
.get());
1028 EXPECT_EQ("Chrome, App1, App2, App3, AppList", GetPinnedAppStatus());
1031 // Check that the restauration of launcher items is happening in the same order
1032 // as the user has pinned them (on another system) when they are synced random
1034 TEST_F(LegacyShelfLayoutChromeLauncherControllerTest
,
1035 RestoreDefaultAppsRandomOrder
) {
1036 InitLauncherController();
1038 base::ListValue policy_value
;
1039 InsertPrefValue(&policy_value
, 0, extension1_
->id());
1040 InsertPrefValue(&policy_value
, 1, extension2_
->id());
1041 InsertPrefValue(&policy_value
, 2, extension3_
->id());
1042 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1043 policy_value
.DeepCopy());
1044 EXPECT_EQ(0, profile()->GetPrefs()->GetInteger(prefs::kShelfChromeIconIndex
));
1045 // Model should only contain the browser shortcut and app list items.
1046 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1047 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1048 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1049 EXPECT_EQ("Chrome, AppList", GetPinnedAppStatus());
1051 // Installing |extension2_| should add it to the launcher - behind the
1053 extension_service_
->AddExtension(extension2_
.get());
1054 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1055 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1056 EXPECT_EQ("Chrome, App2, AppList", GetPinnedAppStatus());
1058 // Installing |extension1_| should add it to the launcher - behind the
1059 // chrome icon, but in first location.
1060 extension_service_
->AddExtension(extension1_
.get());
1061 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1062 EXPECT_EQ("Chrome, App1, App2, AppList", GetPinnedAppStatus());
1064 // Installing |extension3_| should add it to the launcher - behind the
1065 // chrome icon, but in first location.
1066 extension_service_
->AddExtension(extension3_
.get());
1067 EXPECT_EQ("Chrome, App1, App2, App3, AppList", GetPinnedAppStatus());
1070 // Check that the restauration of launcher items is happening in the same order
1071 // as the user has pinned / moved them (on another system) when they are synced
1072 // random order - including the chrome icon.
1073 TEST_F(LegacyShelfLayoutChromeLauncherControllerTest
,
1074 RestoreDefaultAppsRandomOrderChromeMoved
) {
1075 InitLauncherController();
1077 base::ListValue policy_value
;
1078 InsertPrefValue(&policy_value
, 0, extension1_
->id());
1079 InsertPrefValue(&policy_value
, 1, extension2_
->id());
1080 InsertPrefValue(&policy_value
, 2, extension3_
->id());
1081 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1082 policy_value
.DeepCopy());
1083 profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex
,
1085 // Model should only contain the browser shortcut and app list items.
1086 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1087 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1088 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1089 EXPECT_EQ("Chrome, AppList", GetPinnedAppStatus());
1091 // Installing |extension2_| should add it to the shelf - behind the
1093 ash::ShelfItem item
;
1094 extension_service_
->AddExtension(extension2_
.get());
1095 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1096 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1097 EXPECT_EQ("Chrome, App2, AppList", GetPinnedAppStatus());
1099 // Installing |extension1_| should add it to the launcher - behind the
1100 // chrome icon, but in first location.
1101 extension_service_
->AddExtension(extension1_
.get());
1102 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1103 EXPECT_EQ("App1, Chrome, App2, AppList", GetPinnedAppStatus());
1105 // Installing |extension3_| should add it to the launcher - behind the
1106 // chrome icon, but in first location.
1107 extension_service_
->AddExtension(extension3_
.get());
1108 EXPECT_EQ("App1, Chrome, App2, App3, AppList", GetPinnedAppStatus());
1111 // Check that syncing to a different state does the correct thing.
1112 TEST_F(LegacyShelfLayoutChromeLauncherControllerTest
,
1113 RestoreDefaultAppsResyncOrder
) {
1114 InitLauncherController();
1115 base::ListValue policy_value
;
1116 InsertPrefValue(&policy_value
, 0, extension1_
->id());
1117 InsertPrefValue(&policy_value
, 1, extension2_
->id());
1118 InsertPrefValue(&policy_value
, 2, extension3_
->id());
1119 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1120 policy_value
.DeepCopy());
1121 EXPECT_EQ(0, profile()->GetPrefs()->GetInteger(prefs::kShelfChromeIconIndex
));
1122 extension_service_
->AddExtension(extension2_
.get());
1123 extension_service_
->AddExtension(extension1_
.get());
1124 extension_service_
->AddExtension(extension3_
.get());
1125 EXPECT_EQ("Chrome, App1, App2, App3, AppList", GetPinnedAppStatus());
1127 // Change the order with increasing chrome position and decreasing position.
1128 base::ListValue policy_value1
;
1129 InsertPrefValue(&policy_value1
, 0, extension3_
->id());
1130 InsertPrefValue(&policy_value1
, 1, extension1_
->id());
1131 InsertPrefValue(&policy_value1
, 2, extension2_
->id());
1132 profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex
,
1134 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1135 policy_value1
.DeepCopy());
1136 EXPECT_EQ("App3, App1, Chrome, App2, AppList", GetPinnedAppStatus());
1137 base::ListValue policy_value2
;
1138 InsertPrefValue(&policy_value2
, 0, extension2_
->id());
1139 InsertPrefValue(&policy_value2
, 1, extension3_
->id());
1140 InsertPrefValue(&policy_value2
, 2, extension1_
->id());
1141 profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex
,
1143 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1144 policy_value2
.DeepCopy());
1145 EXPECT_EQ("App2, Chrome, App3, App1, AppList", GetPinnedAppStatus());
1148 TEST_F(ChromeLauncherControllerTest
, DefaultApps
) {
1149 InitLauncherController();
1150 // Model should only contain the browser shortcut and app list items.
1151 EXPECT_EQ(2, model_
->item_count());
1152 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1153 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1154 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1156 // Installing |extension3_| should add it to the launcher - behind the
1158 extension_service_
->AddExtension(extension3_
.get());
1159 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
1160 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1161 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1164 // Check that changing from the alternate shelf layout to the old shelflayout
1165 // and back does keep the app launcher at location #0.
1166 TEST_F(ChromeLauncherControllerTest
,
1167 SwitchingFromAlternateShelfLayoutToLegacyAndBack
) {
1168 InitLauncherController();
1170 // We simulate this problem by intentionally placing the app list item in
1171 // the middle of several apps which caused a crash (see crbug.com/329597).
1172 const char kAppShelfIdPlaceholder
[] = "AppShelfIDPlaceholder--------";
1174 base::ListValue policy_value
;
1175 InsertPrefValue(&policy_value
, 0, extension1_
->id());
1176 InsertPrefValue(&policy_value
, 1, kAppShelfIdPlaceholder
);
1177 InsertPrefValue(&policy_value
, 2, extension2_
->id());
1178 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1179 policy_value
.DeepCopy());
1180 EXPECT_EQ(0, profile()->GetPrefs()->GetInteger(prefs::kShelfChromeIconIndex
));
1181 // Model should only contain the browser shortcut and app list items.
1182 extension_service_
->AddExtension(extension1_
.get());
1183 extension_service_
->AddExtension(extension2_
.get());
1184 EXPECT_EQ("AppList, Chrome, App1, App2", GetPinnedAppStatus());
1187 // Check that the restauration of launcher items is happening in the same order
1188 // as the user has pinned them (on another system) when they are synced reverse
1190 TEST_F(ChromeLauncherControllerTest
, RestoreDefaultAppsReverseOrder
) {
1191 InitLauncherController();
1193 base::ListValue policy_value
;
1194 InsertPrefValue(&policy_value
, 0, extension1_
->id());
1195 InsertPrefValue(&policy_value
, 1, extension2_
->id());
1196 InsertPrefValue(&policy_value
, 2, extension3_
->id());
1197 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1198 policy_value
.DeepCopy());
1199 SetShelfChromeIconIndex(0);
1200 // Model should only contain the browser shortcut and app list items.
1201 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1202 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1203 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1204 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
1206 // Installing |extension3_| should add it to the shelf - behind the
1208 ash::ShelfItem item
;
1209 extension_service_
->AddExtension(extension3_
.get());
1210 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1211 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1212 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
1214 // Installing |extension2_| should add it to the launcher - behind the
1215 // chrome icon, but in first location.
1216 extension_service_
->AddExtension(extension2_
.get());
1217 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1218 EXPECT_EQ("AppList, Chrome, App2, App3", GetPinnedAppStatus());
1220 // Installing |extension1_| should add it to the launcher - behind the
1221 // chrome icon, but in first location.
1222 extension_service_
->AddExtension(extension1_
.get());
1223 EXPECT_EQ("AppList, Chrome, App1, App2, App3", GetPinnedAppStatus());
1226 // Check that the restauration of launcher items is happening in the same order
1227 // as the user has pinned them (on another system) when they are synced random
1229 TEST_F(ChromeLauncherControllerTest
, RestoreDefaultAppsRandomOrder
) {
1230 InitLauncherController();
1232 base::ListValue policy_value
;
1233 InsertPrefValue(&policy_value
, 0, extension1_
->id());
1234 InsertPrefValue(&policy_value
, 1, extension2_
->id());
1235 InsertPrefValue(&policy_value
, 2, extension3_
->id());
1236 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1237 policy_value
.DeepCopy());
1238 SetShelfChromeIconIndex(0);
1239 // Model should only contain the browser shortcut and app list items.
1240 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1241 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1242 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1243 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
1245 // Installing |extension2_| should add it to the launcher - behind the
1247 extension_service_
->AddExtension(extension2_
.get());
1248 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1249 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1250 EXPECT_EQ("AppList, Chrome, App2", GetPinnedAppStatus());
1252 // Installing |extension1_| should add it to the launcher - behind the
1253 // chrome icon, but in first location.
1254 extension_service_
->AddExtension(extension1_
.get());
1255 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1256 EXPECT_EQ("AppList, Chrome, App1, App2", GetPinnedAppStatus());
1258 // Installing |extension3_| should add it to the launcher - behind the
1259 // chrome icon, but in first location.
1260 extension_service_
->AddExtension(extension3_
.get());
1261 EXPECT_EQ("AppList, Chrome, App1, App2, App3", GetPinnedAppStatus());
1264 // Check that the restauration of launcher items is happening in the same order
1265 // as the user has pinned / moved them (on another system) when they are synced
1266 // random order - including the chrome icon.
1267 TEST_F(ChromeLauncherControllerTest
, RestoreDefaultAppsRandomOrderChromeMoved
) {
1268 InitLauncherController();
1270 base::ListValue policy_value
;
1271 InsertPrefValue(&policy_value
, 0, extension1_
->id());
1272 InsertPrefValue(&policy_value
, 1, extension2_
->id());
1273 InsertPrefValue(&policy_value
, 2, extension3_
->id());
1274 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1275 policy_value
.DeepCopy());
1276 SetShelfChromeIconIndex(1);
1277 // Model should only contain the browser shortcut and app list items.
1278 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1279 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1280 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1281 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
1283 // Installing |extension2_| should add it to the shelf - behind the
1285 ash::ShelfItem item
;
1286 extension_service_
->AddExtension(extension2_
.get());
1287 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1288 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1289 EXPECT_EQ("AppList, Chrome, App2", GetPinnedAppStatus());
1291 // Installing |extension1_| should add it to the launcher - behind the
1292 // chrome icon, but in first location.
1293 extension_service_
->AddExtension(extension1_
.get());
1294 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1295 EXPECT_EQ("AppList, App1, Chrome, App2", GetPinnedAppStatus());
1297 // Installing |extension3_| should add it to the launcher - behind the
1298 // chrome icon, but in first location.
1299 extension_service_
->AddExtension(extension3_
.get());
1300 EXPECT_EQ("AppList, App1, Chrome, App2, App3", GetPinnedAppStatus());
1303 // Check that syncing to a different state does the correct thing.
1304 TEST_F(ChromeLauncherControllerTest
, RestoreDefaultAppsResyncOrder
) {
1305 InitLauncherController();
1306 base::ListValue policy_value
;
1307 InsertPrefValue(&policy_value
, 0, extension1_
->id());
1308 InsertPrefValue(&policy_value
, 1, extension2_
->id());
1309 InsertPrefValue(&policy_value
, 2, extension3_
->id());
1310 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1311 policy_value
.DeepCopy());
1312 // The shelf layout has always one static item at the beginning (App List).
1313 SetShelfChromeIconIndex(0);
1314 extension_service_
->AddExtension(extension2_
.get());
1315 EXPECT_EQ("AppList, Chrome, App2", GetPinnedAppStatus());
1316 extension_service_
->AddExtension(extension1_
.get());
1317 EXPECT_EQ("AppList, Chrome, App1, App2", GetPinnedAppStatus());
1318 extension_service_
->AddExtension(extension3_
.get());
1319 EXPECT_EQ("AppList, Chrome, App1, App2, App3", GetPinnedAppStatus());
1321 // Change the order with increasing chrome position and decreasing position.
1322 base::ListValue policy_value1
;
1323 InsertPrefValue(&policy_value1
, 0, extension3_
->id());
1324 InsertPrefValue(&policy_value1
, 1, extension1_
->id());
1325 InsertPrefValue(&policy_value1
, 2, extension2_
->id());
1326 SetShelfChromeIconIndex(3);
1327 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1328 policy_value1
.DeepCopy());
1329 EXPECT_EQ("AppList, App3, App1, App2, Chrome", GetPinnedAppStatus());
1330 base::ListValue policy_value2
;
1331 InsertPrefValue(&policy_value2
, 0, extension2_
->id());
1332 InsertPrefValue(&policy_value2
, 1, extension3_
->id());
1333 InsertPrefValue(&policy_value2
, 2, extension1_
->id());
1334 SetShelfChromeIconIndex(2);
1335 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1336 policy_value2
.DeepCopy());
1337 EXPECT_EQ("AppList, App2, App3, Chrome, App1", GetPinnedAppStatus());
1339 // Check that the chrome icon can also be at the first possible location.
1340 SetShelfChromeIconIndex(0);
1341 base::ListValue policy_value3
;
1342 InsertPrefValue(&policy_value3
, 0, extension3_
->id());
1343 InsertPrefValue(&policy_value3
, 1, extension2_
->id());
1344 InsertPrefValue(&policy_value3
, 2, extension1_
->id());
1345 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1346 policy_value3
.DeepCopy());
1347 EXPECT_EQ("AppList, Chrome, App3, App2, App1", GetPinnedAppStatus());
1349 // Check that unloading of extensions works as expected.
1350 extension_service_
->UnloadExtension(extension1_
->id(),
1351 UnloadedExtensionInfo::REASON_UNINSTALL
);
1352 EXPECT_EQ("AppList, Chrome, App3, App2", GetPinnedAppStatus());
1354 extension_service_
->UnloadExtension(extension2_
->id(),
1355 UnloadedExtensionInfo::REASON_UNINSTALL
);
1356 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
1358 // Check that an update of an extension does not crash the system.
1359 extension_service_
->UnloadExtension(extension3_
->id(),
1360 UnloadedExtensionInfo::REASON_UPDATE
);
1361 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
1364 // Check that simple locking of an application will 'create' a launcher item.
1365 TEST_F(ChromeLauncherControllerTest
, CheckLockApps
) {
1366 InitLauncherController();
1367 // Model should only contain the browser shortcut and app list items.
1368 EXPECT_EQ(2, model_
->item_count());
1369 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1371 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1372 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1374 launcher_controller_
->IsWindowedAppInLauncher(extension2_
->id()));
1376 launcher_controller_
->LockV1AppWithID(extension1_
->id());
1378 EXPECT_EQ(3, model_
->item_count());
1379 EXPECT_EQ(ash::TYPE_WINDOWED_APP
, model_
->items()[2].type
);
1380 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1381 EXPECT_TRUE(launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1382 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1384 launcher_controller_
->IsWindowedAppInLauncher(extension2_
->id()));
1386 launcher_controller_
->UnlockV1AppWithID(extension1_
->id());
1388 EXPECT_EQ(2, model_
->item_count());
1389 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1391 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1392 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1394 launcher_controller_
->IsWindowedAppInLauncher(extension2_
->id()));
1397 // Check that multiple locks of an application will be properly handled.
1398 TEST_F(ChromeLauncherControllerTest
, CheckMultiLockApps
) {
1399 InitLauncherController();
1400 // Model should only contain the browser shortcut and app list items.
1401 EXPECT_EQ(2, model_
->item_count());
1402 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1404 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1406 for (int i
= 0; i
< 2; i
++) {
1407 launcher_controller_
->LockV1AppWithID(extension1_
->id());
1409 EXPECT_EQ(3, model_
->item_count());
1410 EXPECT_EQ(ash::TYPE_WINDOWED_APP
, model_
->items()[2].type
);
1411 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1412 EXPECT_TRUE(launcher_controller_
->IsWindowedAppInLauncher(
1413 extension1_
->id()));
1416 launcher_controller_
->UnlockV1AppWithID(extension1_
->id());
1418 EXPECT_EQ(3, model_
->item_count());
1419 EXPECT_EQ(ash::TYPE_WINDOWED_APP
, model_
->items()[2].type
);
1420 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1421 EXPECT_TRUE(launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1423 launcher_controller_
->UnlockV1AppWithID(extension1_
->id());
1425 EXPECT_EQ(2, model_
->item_count());
1426 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1428 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1429 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1431 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1434 // Check that already pinned items are not effected by locks.
1435 TEST_F(ChromeLauncherControllerTest
, CheckAlreadyPinnedLockApps
) {
1436 InitLauncherController();
1437 // Model should only contain the browser shortcut and app list items.
1438 EXPECT_EQ(2, model_
->item_count());
1439 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1441 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1443 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1444 launcher_controller_
->PinAppWithID(extension1_
->id());
1445 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1447 EXPECT_EQ(3, model_
->item_count());
1448 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
1449 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1451 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1453 launcher_controller_
->LockV1AppWithID(extension1_
->id());
1455 EXPECT_EQ(3, model_
->item_count());
1456 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
1457 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1459 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1461 launcher_controller_
->UnlockV1AppWithID(extension1_
->id());
1463 EXPECT_EQ(3, model_
->item_count());
1464 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
1465 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1467 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1469 launcher_controller_
->UnpinAppWithID(extension1_
->id());
1471 EXPECT_EQ(2, model_
->item_count());
1474 // Check that already pinned items which get locked stay after unpinning.
1475 TEST_F(ChromeLauncherControllerTest
, CheckPinnedAppsStayAfterUnlock
) {
1476 InitLauncherController();
1477 // Model should only contain the browser shortcut and app list items.
1478 EXPECT_EQ(2, model_
->item_count());
1479 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1481 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1483 launcher_controller_
->PinAppWithID(extension1_
->id());
1485 EXPECT_EQ(3, model_
->item_count());
1486 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
1487 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1489 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1491 launcher_controller_
->LockV1AppWithID(extension1_
->id());
1493 EXPECT_EQ(3, model_
->item_count());
1494 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
1495 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1497 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1499 launcher_controller_
->UnpinAppWithID(extension1_
->id());
1501 EXPECT_EQ(3, model_
->item_count());
1502 EXPECT_EQ(ash::TYPE_WINDOWED_APP
, model_
->items()[2].type
);
1503 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1504 EXPECT_TRUE(launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1506 launcher_controller_
->UnlockV1AppWithID(extension1_
->id());
1508 EXPECT_EQ(2, model_
->item_count());
1511 #if defined(OS_CHROMEOS)
1512 // Check that running applications wich are not pinned get properly restored
1513 // upon user change.
1514 TEST_F(ChromeLauncherControllerTest
, CheckRunningAppOrder
) {
1515 InitLauncherController();
1516 // Model should only contain the browser shortcut and app list items.
1517 EXPECT_EQ(2, model_
->item_count());
1519 // Add a few running applications.
1520 launcher_controller_
->LockV1AppWithID(extension1_
->id());
1521 launcher_controller_
->LockV1AppWithID(extension2_
->id());
1522 launcher_controller_
->LockV1AppWithID(extension3_
->id());
1523 EXPECT_EQ(5, model_
->item_count());
1524 // Note that this not only checks the order of applications but also the
1526 EXPECT_EQ("AppList, Chrome, app1, app2, app3", GetPinnedAppStatus());
1528 // Remember the current order of applications for the current user.
1529 const std::string
& current_user_id
=
1530 multi_user_util::GetUserIDFromProfile(profile());
1531 RememberUnpinnedRunningApplicationOrder();
1533 // Switch some items and check that restoring a user which was not yet
1534 // remembered changes nothing.
1536 EXPECT_EQ("AppList, Chrome, app2, app1, app3", GetPinnedAppStatus());
1537 RestoreUnpinnedRunningApplicationOrder("second-fake-user@fake.com");
1538 EXPECT_EQ("AppList, Chrome, app2, app1, app3", GetPinnedAppStatus());
1540 // Restoring the stored user should however do the right thing.
1541 RestoreUnpinnedRunningApplicationOrder(current_user_id
);
1542 EXPECT_EQ("AppList, Chrome, app1, app2, app3", GetPinnedAppStatus());
1544 // Switch again some items and even delete one - making sure that the missing
1545 // item gets properly handled.
1547 launcher_controller_
->UnlockV1AppWithID(extension1_
->id());
1548 EXPECT_EQ("AppList, Chrome, app3, app2", GetPinnedAppStatus());
1549 RestoreUnpinnedRunningApplicationOrder(current_user_id
);
1550 EXPECT_EQ("AppList, Chrome, app2, app3", GetPinnedAppStatus());
1552 // Check that removing more items does not crash and changes nothing.
1553 launcher_controller_
->UnlockV1AppWithID(extension2_
->id());
1554 RestoreUnpinnedRunningApplicationOrder(current_user_id
);
1555 EXPECT_EQ("AppList, Chrome, app3", GetPinnedAppStatus());
1556 launcher_controller_
->UnlockV1AppWithID(extension3_
->id());
1557 RestoreUnpinnedRunningApplicationOrder(current_user_id
);
1558 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
1561 // Check that with multi profile V1 apps are properly added / removed from the
1563 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
,
1564 V1AppUpdateOnUserSwitch
) {
1565 // Create a browser item in the LauncherController.
1566 InitLauncherController();
1567 EXPECT_EQ(2, model_
->item_count());
1569 // Create a "windowed gmail app".
1570 scoped_ptr
<V1App
> v1_app(CreateRunningV1App(
1571 profile(), extension_misc::kGmailAppId
, gmail_url
));
1572 EXPECT_EQ(3, model_
->item_count());
1574 // After switching to a second user the item should be gone.
1575 std::string user2
= "user2";
1576 TestingProfile
* profile2
= CreateMultiUserProfile(user2
);
1577 SwitchActiveUser(profile2
->GetProfileName());
1578 EXPECT_EQ(2, model_
->item_count());
1580 // After switching back the item should be back.
1581 SwitchActiveUser(profile()->GetProfileName());
1582 EXPECT_EQ(3, model_
->item_count());
1583 // Note we destroy now the gmail app with the closure end.
1585 EXPECT_EQ(2, model_
->item_count());
1588 // Check edge cases with multi profile V1 apps in the shelf.
1589 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
,
1590 V1AppUpdateOnUserSwitchEdgecases
) {
1591 // Create a browser item in the LauncherController.
1592 InitLauncherController();
1594 // First test: Create an app when the user is not active.
1595 std::string user2
= "user2";
1596 TestingProfile
* profile2
= CreateMultiUserProfile(user2
);
1598 // Create a "windowed gmail app".
1599 scoped_ptr
<V1App
> v1_app(CreateRunningV1App(
1600 profile2
, extension_misc::kGmailAppId
, gmail_url
));
1601 EXPECT_EQ(2, model_
->item_count());
1603 // However - switching to the user should show it.
1604 SwitchActiveUser(profile2
->GetProfileName());
1605 EXPECT_EQ(3, model_
->item_count());
1607 // Second test: Remove the app when the user is not active and see that it
1609 SwitchActiveUser(profile()->GetProfileName());
1610 EXPECT_EQ(2, model_
->item_count());
1611 // Note: the closure ends and the browser will go away.
1613 EXPECT_EQ(2, model_
->item_count());
1614 SwitchActiveUser(profile2
->GetProfileName());
1615 EXPECT_EQ(2, model_
->item_count());
1616 SwitchActiveUser(profile()->GetProfileName());
1617 EXPECT_EQ(2, model_
->item_count());
1620 // Check edge case where a visiting V1 app gets closed (crbug.com/321374).
1621 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
,
1622 V1CloseOnVisitingDesktop
) {
1623 // Create a browser item in the LauncherController.
1624 InitLauncherController();
1626 chrome::MultiUserWindowManager
* manager
=
1627 chrome::MultiUserWindowManager::GetInstance();
1629 // First create an app when the user is active.
1630 std::string user2
= "user2";
1631 TestingProfile
* profile2
= CreateMultiUserProfile(user2
);
1633 // Create a "windowed gmail app".
1634 scoped_ptr
<V1App
> v1_app(CreateRunningV1App(
1636 extension_misc::kGmailAppId
,
1638 EXPECT_EQ(3, model_
->item_count());
1640 // Transfer the app to the other screen and switch users.
1641 manager
->ShowWindowForUser(v1_app
->browser()->window()->GetNativeWindow(),
1643 EXPECT_EQ(3, model_
->item_count());
1644 SwitchActiveUser(profile2
->GetProfileName());
1645 EXPECT_EQ(2, model_
->item_count());
1647 // After the app was destroyed, switch back. (which caused already a crash).
1648 SwitchActiveUser(profile()->GetProfileName());
1650 // Create the same app again - which was also causing the crash.
1651 EXPECT_EQ(2, model_
->item_count());
1653 // Create a "windowed gmail app".
1654 scoped_ptr
<V1App
> v1_app(CreateRunningV1App(
1656 extension_misc::kGmailAppId
,
1658 EXPECT_EQ(3, model_
->item_count());
1660 SwitchActiveUser(profile2
->GetProfileName());
1661 EXPECT_EQ(2, model_
->item_count());
1664 // Check edge cases with multi profile V1 apps in the shelf.
1665 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
,
1666 V1AppUpdateOnUserSwitchEdgecases2
) {
1667 // Create a browser item in the LauncherController.
1668 InitLauncherController();
1669 TestAppTabHelperImpl
* app_tab_helper
= new TestAppTabHelperImpl
;
1670 SetAppTabHelper(app_tab_helper
);
1672 // First test: Create an app when the user is not active.
1673 std::string user2
= "user2";
1674 TestingProfile
* profile2
= CreateMultiUserProfile(user2
);
1675 SwitchActiveUser(profile2
->GetProfileName());
1677 // Create a "windowed gmail app".
1678 scoped_ptr
<V1App
> v1_app(CreateRunningV1App(
1679 profile(), extension_misc::kGmailAppId
, gmail_url
));
1680 EXPECT_EQ(2, model_
->item_count());
1682 // However - switching to the user should show it.
1683 SwitchActiveUser(profile()->GetProfileName());
1684 EXPECT_EQ(3, model_
->item_count());
1686 // Second test: Remove the app when the user is not active and see that it
1688 SwitchActiveUser(profile2
->GetProfileName());
1689 EXPECT_EQ(2, model_
->item_count());
1692 EXPECT_EQ(2, model_
->item_count());
1693 SwitchActiveUser(profile()->GetProfileName());
1694 EXPECT_EQ(2, model_
->item_count());
1695 SwitchActiveUser(profile2
->GetProfileName());
1696 EXPECT_EQ(2, model_
->item_count());
1699 // Check that activating an item which is on another user's desktop, will bring
1701 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
,
1702 TestLauncherActivationPullsBackWindow
) {
1703 // Create a browser item in the LauncherController.
1704 InitLauncherController();
1705 chrome::MultiUserWindowManager
* manager
=
1706 chrome::MultiUserWindowManager::GetInstance();
1708 // Add two users to the window manager.
1709 std::string user2
= "user2";
1710 TestingProfile
* profile2
= CreateMultiUserProfile(user2
);
1711 manager
->AddUser(profile());
1712 manager
->AddUser(profile2
);
1713 const std::string
& current_user
=
1714 multi_user_util::GetUserIDFromProfile(profile());
1716 // Create a browser window with a native window for the current user.
1717 scoped_ptr
<BrowserWindow
> browser_window(CreateTestBrowserWindow(
1718 Browser::CreateParams(profile(), chrome::HOST_DESKTOP_TYPE_ASH
)));
1719 aura::Window
* window
= browser_window
->GetNativeWindow();
1720 manager
->SetWindowOwner(window
, current_user
);
1722 // Check that an activation of the window on its owner's desktop does not
1723 // change the visibility to another user.
1724 launcher_controller_
->ActivateWindowOrMinimizeIfActive(browser_window
.get(),
1726 EXPECT_TRUE(manager
->IsWindowOnDesktopOfUser(window
, current_user
));
1728 // Transfer the window to another user's desktop and check that activating it
1729 // does pull it back to that user.
1730 manager
->ShowWindowForUser(window
, user2
);
1731 EXPECT_FALSE(manager
->IsWindowOnDesktopOfUser(window
, current_user
));
1732 launcher_controller_
->ActivateWindowOrMinimizeIfActive(browser_window
.get(),
1734 EXPECT_TRUE(manager
->IsWindowOnDesktopOfUser(window
, current_user
));
1738 // Check that lock -> pin -> unlock -> unpin does properly transition.
1739 TEST_F(ChromeLauncherControllerTest
, CheckLockPinUnlockUnpin
) {
1740 InitLauncherController();
1741 // Model should only contain the browser shortcut and app list items.
1742 EXPECT_EQ(2, model_
->item_count());
1743 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1745 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1747 launcher_controller_
->LockV1AppWithID(extension1_
->id());
1749 EXPECT_EQ(3, model_
->item_count());
1750 EXPECT_EQ(ash::TYPE_WINDOWED_APP
, model_
->items()[2].type
);
1751 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1752 EXPECT_TRUE(launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1754 launcher_controller_
->PinAppWithID(extension1_
->id());
1756 EXPECT_EQ(3, model_
->item_count());
1757 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
1758 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1760 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1762 launcher_controller_
->UnlockV1AppWithID(extension1_
->id());
1764 EXPECT_EQ(3, model_
->item_count());
1765 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
1766 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1768 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1770 launcher_controller_
->UnpinAppWithID(extension1_
->id());
1772 EXPECT_EQ(2, model_
->item_count());
1775 // Check that a locked (windowed V1 application) will be properly converted
1776 // between locked and pinned when the order gets changed through a profile /
1778 TEST_F(ChromeLauncherControllerTest
, RestoreDefaultAndLockedAppsResyncOrder
) {
1779 InitLauncherController();
1780 base::ListValue policy_value0
;
1781 InsertPrefValue(&policy_value0
, 0, extension1_
->id());
1782 InsertPrefValue(&policy_value0
, 1, extension3_
->id());
1783 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1784 policy_value0
.DeepCopy());
1785 // The shelf layout has always one static item at the beginning (App List).
1786 SetShelfChromeIconIndex(0);
1787 extension_service_
->AddExtension(extension1_
.get());
1788 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1789 extension_service_
->AddExtension(extension2_
.get());
1790 // No new app icon will be generated.
1791 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1792 // Add the app as locked app which will add it (un-pinned).
1793 launcher_controller_
->LockV1AppWithID(extension2_
->id());
1794 EXPECT_EQ("AppList, Chrome, App1, app2", GetPinnedAppStatus());
1795 extension_service_
->AddExtension(extension3_
.get());
1796 EXPECT_EQ("AppList, Chrome, App1, App3, app2", GetPinnedAppStatus());
1798 // Now request to pin all items which should convert the locked item into a
1800 base::ListValue policy_value1
;
1801 InsertPrefValue(&policy_value1
, 0, extension3_
->id());
1802 InsertPrefValue(&policy_value1
, 1, extension2_
->id());
1803 InsertPrefValue(&policy_value1
, 2, extension1_
->id());
1804 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1805 policy_value1
.DeepCopy());
1806 EXPECT_EQ("AppList, Chrome, App3, App2, App1", GetPinnedAppStatus());
1808 // Going back to a status where there is no requirement for app 2 to be pinned
1809 // should convert it back to locked but not pinned and state. The position
1810 // is determined by the |ShelfModel|'s weight system and since running
1811 // applications are not allowed to be mixed with shortcuts, it should show up
1812 // at the end of the list.
1813 base::ListValue policy_value2
;
1814 InsertPrefValue(&policy_value2
, 0, extension3_
->id());
1815 InsertPrefValue(&policy_value2
, 1, extension1_
->id());
1816 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1817 policy_value2
.DeepCopy());
1818 EXPECT_EQ("AppList, Chrome, App3, App1, app2", GetPinnedAppStatus());
1820 // Removing an item should simply close it and everything should shift.
1821 base::ListValue policy_value3
;
1822 InsertPrefValue(&policy_value3
, 0, extension3_
->id());
1823 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1824 policy_value3
.DeepCopy());
1825 EXPECT_EQ("AppList, Chrome, App3, app2", GetPinnedAppStatus());
1828 // Check that a running and not pinned V2 application will be properly converted
1829 // between locked and pinned when the order gets changed through a profile /
1831 TEST_F(ChromeLauncherControllerTest
,
1832 RestoreDefaultAndRunningV2AppsResyncOrder
) {
1833 InitLauncherController();
1834 base::ListValue policy_value0
;
1835 InsertPrefValue(&policy_value0
, 0, extension1_
->id());
1836 InsertPrefValue(&policy_value0
, 1, extension3_
->id());
1837 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1838 policy_value0
.DeepCopy());
1839 // The shelf layout has always one static item at the beginning (app List).
1840 SetShelfChromeIconIndex(0);
1841 extension_service_
->AddExtension(extension1_
.get());
1842 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1843 extension_service_
->AddExtension(extension2_
.get());
1844 // No new app icon will be generated.
1845 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1846 // Add the app as an unpinned but running V2 app.
1847 CreateRunningV2App(extension2_
->id());
1848 EXPECT_EQ("AppList, Chrome, App1, *app2", GetPinnedAppStatus());
1849 extension_service_
->AddExtension(extension3_
.get());
1850 EXPECT_EQ("AppList, Chrome, App1, App3, *app2", GetPinnedAppStatus());
1852 // Now request to pin all items which should convert the locked item into a
1854 base::ListValue policy_value1
;
1855 InsertPrefValue(&policy_value1
, 0, extension3_
->id());
1856 InsertPrefValue(&policy_value1
, 1, extension2_
->id());
1857 InsertPrefValue(&policy_value1
, 2, extension1_
->id());
1858 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1859 policy_value1
.DeepCopy());
1860 EXPECT_EQ("AppList, Chrome, App3, App2, App1", GetPinnedAppStatus());
1862 // Going back to a status where there is no requirement for app 2 to be pinned
1863 // should convert it back to running V2 app. Since the position is determined
1864 // by the |ShelfModel|'s weight system, it will be after last pinned item.
1865 base::ListValue policy_value2
;
1866 InsertPrefValue(&policy_value2
, 0, extension3_
->id());
1867 InsertPrefValue(&policy_value2
, 1, extension1_
->id());
1868 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1869 policy_value2
.DeepCopy());
1870 EXPECT_EQ("AppList, Chrome, App3, App1, *app2", GetPinnedAppStatus());
1872 // Removing an item should simply close it and everything should shift.
1873 base::ListValue policy_value3
;
1874 InsertPrefValue(&policy_value3
, 0, extension3_
->id());
1875 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1876 policy_value3
.DeepCopy());
1877 EXPECT_EQ("AppList, Chrome, App3, *app2", GetPinnedAppStatus());
1880 // Each user has a different set of applications pinned. Check that when
1881 // switching between the two users, the state gets properly set.
1882 TEST_F(ChromeLauncherControllerTest
, UserSwitchIconRestore
) {
1883 base::ListValue user_a
;
1884 base::ListValue user_b
;
1885 SetUpMultiUserScenario(&user_a
, &user_b
);
1887 SetShelfChromeIconIndex(6);
1888 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1890 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1891 GetPinnedAppStatus());
1894 SetShelfChromeIconIndex(4);
1895 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1898 EXPECT_EQ("AppList, App7, App8, Chrome", GetPinnedAppStatus());
1900 // Switch back to 1.
1901 SetShelfChromeIconIndex(8);
1902 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1904 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1905 GetPinnedAppStatus());
1907 // Switch back to 2.
1908 SetShelfChromeIconIndex(4);
1909 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1911 EXPECT_EQ("AppList, App7, App8, Chrome", GetPinnedAppStatus());
1914 // Each user has a different set of applications pinned, and one user has an
1915 // application running. Check that when switching between the two users, the
1916 // state gets properly set.
1917 TEST_F(ChromeLauncherControllerTest
, UserSwitchIconRestoreWithRunningV2App
) {
1918 base::ListValue user_a
;
1919 base::ListValue user_b
;
1920 SetUpMultiUserScenario(&user_a
, &user_b
);
1922 // Run App1 and assume that it is a V2 app.
1923 CreateRunningV2App(extension1_
->id());
1926 SetShelfChromeIconIndex(6);
1927 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1929 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1930 GetPinnedAppStatus());
1933 SetShelfChromeIconIndex(4);
1934 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1937 EXPECT_EQ("AppList, App7, App8, Chrome, *app1", GetPinnedAppStatus());
1939 // Switch back to 1.
1940 SetShelfChromeIconIndex(8);
1941 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1943 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1944 GetPinnedAppStatus());
1946 // Switch back to 2.
1947 SetShelfChromeIconIndex(4);
1948 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1950 EXPECT_EQ("AppList, App7, App8, Chrome, *app1", GetPinnedAppStatus());
1953 // Each user has a different set of applications pinned, and one user has an
1954 // application running. The chrome icon is not the last item in the list.
1955 // Check that when switching between the two users, the state gets properly set.
1956 // There was once a bug associated with this.
1957 TEST_F(ChromeLauncherControllerTest
,
1958 UserSwitchIconRestoreWithRunningV2AppChromeInMiddle
) {
1959 base::ListValue user_a
;
1960 base::ListValue user_b
;
1961 SetUpMultiUserScenario(&user_a
, &user_b
);
1963 // Run App1 and assume that it is a V2 app.
1964 CreateRunningV2App(extension1_
->id());
1967 SetShelfChromeIconIndex(5);
1968 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1970 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, Chrome, App6",
1971 GetPinnedAppStatus());
1974 SetShelfChromeIconIndex(4);
1975 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1978 EXPECT_EQ("AppList, App7, App8, Chrome, *app1", GetPinnedAppStatus());
1980 // Switch back to 1.
1981 SetShelfChromeIconIndex(5);
1982 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1984 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, Chrome, App6",
1985 GetPinnedAppStatus());
1988 TEST_F(ChromeLauncherControllerTest
, Policy
) {
1989 extension_service_
->AddExtension(extension1_
.get());
1990 extension_service_
->AddExtension(extension3_
.get());
1992 base::ListValue policy_value
;
1993 InsertPrefValue(&policy_value
, 0, extension1_
->id());
1994 InsertPrefValue(&policy_value
, 1, extension2_
->id());
1995 profile()->GetTestingPrefService()->SetManagedPref(prefs::kPinnedLauncherApps
,
1996 policy_value
.DeepCopy());
1998 // Only |extension1_| should get pinned. |extension2_| is specified but not
1999 // installed, and |extension3_| is part of the default set, but that shouldn't
2000 // take effect when the policy override is in place.
2001 InitLauncherController();
2002 EXPECT_EQ(3, model_
->item_count());
2003 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
2004 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
2005 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
2006 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2008 // Installing |extension2_| should add it to the launcher.
2009 extension_service_
->AddExtension(extension2_
.get());
2010 EXPECT_EQ(4, model_
->item_count());
2011 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
2012 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[3].type
);
2013 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
2014 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension2_
->id()));
2015 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2017 // Removing |extension1_| from the policy should be reflected in the launcher.
2018 policy_value
.Remove(0, NULL
);
2019 profile()->GetTestingPrefService()->SetManagedPref(prefs::kPinnedLauncherApps
,
2020 policy_value
.DeepCopy());
2021 EXPECT_EQ(3, model_
->item_count());
2022 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
2023 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
2024 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension2_
->id()));
2025 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2028 TEST_F(ChromeLauncherControllerTest
, UnpinWithUninstall
) {
2029 extension_service_
->AddExtension(extension3_
.get());
2030 extension_service_
->AddExtension(extension4_
.get());
2032 InitLauncherController();
2034 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2035 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension4_
->id()));
2037 extension_service_
->UnloadExtension(extension3_
->id(),
2038 UnloadedExtensionInfo::REASON_UNINSTALL
);
2040 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2041 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension4_
->id()));
2044 TEST_F(ChromeLauncherControllerTest
, PrefUpdates
) {
2045 extension_service_
->AddExtension(extension2_
.get());
2046 extension_service_
->AddExtension(extension3_
.get());
2047 extension_service_
->AddExtension(extension4_
.get());
2049 InitLauncherController();
2051 std::vector
<std::string
> expected_launchers
;
2052 std::vector
<std::string
> actual_launchers
;
2053 base::ListValue pref_value
;
2054 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
2055 pref_value
.DeepCopy());
2056 GetAppLaunchers(launcher_controller_
.get(), &actual_launchers
);
2057 EXPECT_EQ(expected_launchers
, actual_launchers
);
2059 // Unavailable extensions don't create launcher items.
2060 InsertPrefValue(&pref_value
, 0, extension1_
->id());
2061 InsertPrefValue(&pref_value
, 1, extension2_
->id());
2062 InsertPrefValue(&pref_value
, 2, extension4_
->id());
2063 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
2064 pref_value
.DeepCopy());
2065 expected_launchers
.push_back(extension2_
->id());
2066 expected_launchers
.push_back(extension4_
->id());
2067 GetAppLaunchers(launcher_controller_
.get(), &actual_launchers
);
2068 EXPECT_EQ(expected_launchers
, actual_launchers
);
2070 // Redundant pref entries show up only once.
2071 InsertPrefValue(&pref_value
, 2, extension3_
->id());
2072 InsertPrefValue(&pref_value
, 2, extension3_
->id());
2073 InsertPrefValue(&pref_value
, 5, extension3_
->id());
2074 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
2075 pref_value
.DeepCopy());
2076 expected_launchers
.insert(expected_launchers
.begin() + 1, extension3_
->id());
2077 GetAppLaunchers(launcher_controller_
.get(), &actual_launchers
);
2078 EXPECT_EQ(expected_launchers
, actual_launchers
);
2080 // Order changes are reflected correctly.
2082 InsertPrefValue(&pref_value
, 0, extension4_
->id());
2083 InsertPrefValue(&pref_value
, 1, extension3_
->id());
2084 InsertPrefValue(&pref_value
, 2, extension2_
->id());
2085 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
2086 pref_value
.DeepCopy());
2087 std::reverse(expected_launchers
.begin(), expected_launchers
.end());
2088 GetAppLaunchers(launcher_controller_
.get(), &actual_launchers
);
2089 EXPECT_EQ(expected_launchers
, actual_launchers
);
2093 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
2094 pref_value
.DeepCopy());
2095 expected_launchers
.clear();
2096 GetAppLaunchers(launcher_controller_
.get(), &actual_launchers
);
2097 EXPECT_EQ(expected_launchers
, actual_launchers
);
2100 TEST_F(ChromeLauncherControllerTest
, PendingInsertionOrder
) {
2101 extension_service_
->AddExtension(extension1_
.get());
2102 extension_service_
->AddExtension(extension3_
.get());
2104 InitLauncherController();
2106 base::ListValue pref_value
;
2107 InsertPrefValue(&pref_value
, 0, extension1_
->id());
2108 InsertPrefValue(&pref_value
, 1, extension2_
->id());
2109 InsertPrefValue(&pref_value
, 2, extension3_
->id());
2110 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
2111 pref_value
.DeepCopy());
2113 std::vector
<std::string
> expected_launchers
;
2114 expected_launchers
.push_back(extension1_
->id());
2115 expected_launchers
.push_back(extension3_
->id());
2116 std::vector
<std::string
> actual_launchers
;
2118 GetAppLaunchers(launcher_controller_
.get(), &actual_launchers
);
2119 EXPECT_EQ(expected_launchers
, actual_launchers
);
2121 // Install |extension2| and verify it shows up between the other two.
2122 extension_service_
->AddExtension(extension2_
.get());
2123 expected_launchers
.insert(expected_launchers
.begin() + 1, extension2_
->id());
2124 GetAppLaunchers(launcher_controller_
.get(), &actual_launchers
);
2125 EXPECT_EQ(expected_launchers
, actual_launchers
);
2128 // Checks the created menus and menu lists for correctness. It uses the given
2129 // |controller| to create the objects for the given |item| and checks the
2130 // found item count against the |expected_items|. The |title| list contains the
2131 // menu titles in the order of their appearance in the menu (not including the
2132 // application name).
2133 bool CheckMenuCreation(ChromeLauncherController
* controller
,
2134 const ash::ShelfItem
& item
,
2135 size_t expected_items
,
2136 base::string16 title
[],
2138 ChromeLauncherAppMenuItems items
= controller
->GetApplicationList(item
, 0);
2139 // A new behavior has been added: Only show menus if there is at least one
2141 if (expected_items
< 1 && is_browser
) {
2142 EXPECT_EQ(0u, items
.size());
2143 return items
.size() == 0;
2145 // There should be one item in there: The title.
2146 EXPECT_EQ(expected_items
+ 1, items
.size());
2147 EXPECT_FALSE(items
[0]->IsEnabled());
2148 for (size_t i
= 0; i
< expected_items
; i
++) {
2149 EXPECT_EQ(title
[i
], items
[1 + i
]->title());
2150 // Check that the first real item has a leading separator.
2152 EXPECT_TRUE(items
[i
]->HasLeadingSeparator());
2154 EXPECT_FALSE(items
[i
]->HasLeadingSeparator());
2157 scoped_ptr
<ash::ShelfMenuModel
> menu(new LauncherApplicationMenuItemModel(
2158 controller
->GetApplicationList(item
, 0)));
2159 // The first element in the menu is a spacing separator. On some systems
2160 // (e.g. Windows) such things do not exist. As such we check the existence
2161 // and adjust dynamically.
2162 int first_item
= menu
->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR
? 1 : 0;
2163 int expected_menu_items
= first_item
+
2164 (expected_items
? (expected_items
+ 3) : 2);
2165 EXPECT_EQ(expected_menu_items
, menu
->GetItemCount());
2166 EXPECT_FALSE(menu
->IsEnabledAt(first_item
));
2167 if (expected_items
) {
2168 EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR
,
2169 menu
->GetTypeAt(first_item
+ 1));
2171 return items
.size() == expected_items
+ 1;
2174 // Check that browsers get reflected correctly in the launcher menu.
2175 TEST_F(ChromeLauncherControllerTest
, BrowserMenuGeneration
) {
2176 EXPECT_EQ(1U, chrome::GetTotalBrowserCount());
2177 chrome::NewTab(browser());
2179 InitLauncherController();
2181 // Check that the browser list is empty at this time.
2182 ash::ShelfItem item_browser
;
2183 item_browser
.type
= ash::TYPE_BROWSER_SHORTCUT
;
2185 launcher_controller_
->GetShelfIDForAppID(extension_misc::kChromeAppId
);
2186 EXPECT_TRUE(CheckMenuCreation(
2187 launcher_controller_
.get(), item_browser
, 0, NULL
, true));
2189 // Now make the created browser() visible by adding it to the active browser
2191 BrowserList::SetLastActive(browser());
2192 base::string16 title1
= ASCIIToUTF16("Test1");
2193 NavigateAndCommitActiveTabWithTitle(browser(), GURL("http://test1"), title1
);
2194 base::string16 one_menu_item
[] = { title1
};
2196 EXPECT_TRUE(CheckMenuCreation(
2197 launcher_controller_
.get(), item_browser
, 1, one_menu_item
, true));
2199 // Create one more browser/window and check that one more was added.
2200 Browser::CreateParams
ash_params(profile(), chrome::HOST_DESKTOP_TYPE_ASH
);
2201 scoped_ptr
<Browser
> browser2(
2202 chrome::CreateBrowserWithTestWindowForParams(&ash_params
));
2203 chrome::NewTab(browser2
.get());
2204 BrowserList::SetLastActive(browser2
.get());
2205 base::string16 title2
= ASCIIToUTF16("Test2");
2206 NavigateAndCommitActiveTabWithTitle(browser2
.get(), GURL("http://test2"),
2209 // Check that the list contains now two entries - make furthermore sure that
2210 // the active item is the first entry.
2211 base::string16 two_menu_items
[] = {title1
, title2
};
2212 EXPECT_TRUE(CheckMenuCreation(
2213 launcher_controller_
.get(), item_browser
, 2, two_menu_items
, true));
2215 // Apparently we have to close all tabs we have.
2216 chrome::CloseTab(browser2
.get());
2219 #if defined(OS_CHROMEOS)
2220 // Check the multi profile case where only user related browsers should show
2222 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
,
2223 BrowserMenuGenerationTwoUsers
) {
2224 // Create a browser item in the LauncherController.
2225 InitLauncherController();
2227 ash::ShelfItem item_browser
;
2228 item_browser
.type
= ash::TYPE_BROWSER_SHORTCUT
;
2230 launcher_controller_
->GetShelfIDForAppID(extension_misc::kChromeAppId
);
2232 // Check that the menu is empty.
2233 chrome::NewTab(browser());
2234 EXPECT_TRUE(CheckMenuCreation(
2235 launcher_controller_
.get(), item_browser
, 0, NULL
, true));
2237 // Show the created |browser()| by adding it to the active browser list.
2238 BrowserList::SetLastActive(browser());
2239 base::string16 title1
= ASCIIToUTF16("Test1");
2240 NavigateAndCommitActiveTabWithTitle(browser(), GURL("http://test1"), title1
);
2241 base::string16 one_menu_item1
[] = { title1
};
2242 EXPECT_TRUE(CheckMenuCreation(
2243 launcher_controller_
.get(), item_browser
, 1, one_menu_item1
, true));
2245 // Create a browser for another user and check that it is not included in the
2246 // users running browser list.
2247 std::string user2
= "user2";
2248 TestingProfile
* profile2
= CreateMultiUserProfile(user2
);
2249 scoped_ptr
<Browser
> browser2(
2250 CreateBrowserAndTabWithProfile(profile2
, user2
, "http://test2"));
2251 base::string16 one_menu_item2
[] = { ASCIIToUTF16(user2
) };
2252 EXPECT_TRUE(CheckMenuCreation(
2253 launcher_controller_
.get(), item_browser
, 1, one_menu_item1
, true));
2255 // Switch to the other user and make sure that only that browser window gets
2257 SwitchActiveUser(profile2
->GetProfileName());
2258 EXPECT_TRUE(CheckMenuCreation(
2259 launcher_controller_
.get(), item_browser
, 1, one_menu_item2
, true));
2261 // Transferred browsers of other users should not show up in the list.
2262 chrome::MultiUserWindowManager::GetInstance()->ShowWindowForUser(
2263 browser()->window()->GetNativeWindow(),
2265 EXPECT_TRUE(CheckMenuCreation(
2266 launcher_controller_
.get(), item_browser
, 1, one_menu_item2
, true));
2268 chrome::CloseTab(browser2
.get());
2270 #endif // defined(OS_CHROMEOS)
2272 // Check that V1 apps are correctly reflected in the launcher menu using the
2274 // Note that the extension matching logic is tested by the extension system
2275 // and does not need a separate test here.
2276 TEST_F(ChromeLauncherControllerTest
, V1AppMenuGeneration
) {
2277 EXPECT_EQ(1U, chrome::GetTotalBrowserCount());
2278 EXPECT_EQ(0, browser()->tab_strip_model()->count());
2280 InitLauncherControllerWithBrowser();
2282 // Model should only contain the browser shortcut and app list items.
2283 EXPECT_EQ(2, model_
->item_count());
2284 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2286 // Installing |extension3_| adds it to the launcher.
2287 ash::ShelfID gmail_id
= model_
->next_id();
2288 extension_service_
->AddExtension(extension3_
.get());
2289 EXPECT_EQ(3, model_
->item_count());
2290 int gmail_index
= model_
->ItemIndexByID(gmail_id
);
2291 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[gmail_index
].type
);
2292 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2293 launcher_controller_
->SetRefocusURLPatternForTest(gmail_id
, GURL(gmail_url
));
2295 // Check the menu content.
2296 ash::ShelfItem item_browser
;
2297 item_browser
.type
= ash::TYPE_BROWSER_SHORTCUT
;
2299 launcher_controller_
->GetShelfIDForAppID(extension_misc::kChromeAppId
);
2301 ash::ShelfItem item_gmail
;
2302 item_gmail
.type
= ash::TYPE_APP_SHORTCUT
;
2303 item_gmail
.id
= gmail_id
;
2304 EXPECT_TRUE(CheckMenuCreation(
2305 launcher_controller_
.get(), item_gmail
, 0, NULL
, false));
2307 // Set the gmail URL to a new tab.
2308 base::string16 title1
= ASCIIToUTF16("Test1");
2309 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url
), title1
);
2311 base::string16 one_menu_item
[] = { title1
};
2312 EXPECT_TRUE(CheckMenuCreation(
2313 launcher_controller_
.get(), item_gmail
, 1, one_menu_item
, false));
2315 // Create one empty tab.
2316 chrome::NewTab(browser());
2317 base::string16 title2
= ASCIIToUTF16("Test2");
2318 NavigateAndCommitActiveTabWithTitle(
2320 GURL("https://bla"),
2323 // and another one with another gmail instance.
2324 chrome::NewTab(browser());
2325 base::string16 title3
= ASCIIToUTF16("Test3");
2326 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url
), title3
);
2327 base::string16 two_menu_items
[] = {title1
, title3
};
2328 EXPECT_TRUE(CheckMenuCreation(
2329 launcher_controller_
.get(), item_gmail
, 2, two_menu_items
, false));
2331 // Even though the item is in the V1 app list, it should also be in the
2333 base::string16 browser_menu_item
[] = {title3
};
2334 EXPECT_TRUE(CheckMenuCreation(
2335 launcher_controller_
.get(), item_browser
, 1, browser_menu_item
, false));
2337 // Test that closing of (all) the item(s) does work (and all menus get
2338 // updated properly).
2339 launcher_controller_
->Close(item_gmail
.id
);
2341 EXPECT_TRUE(CheckMenuCreation(
2342 launcher_controller_
.get(), item_gmail
, 0, NULL
, false));
2343 base::string16 browser_menu_item2
[] = { title2
};
2344 EXPECT_TRUE(CheckMenuCreation(
2345 launcher_controller_
.get(), item_browser
, 1, browser_menu_item2
, false));
2348 #if defined(OS_CHROMEOS)
2349 // Check the multi profile case where only user related apps should show up.
2350 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
,
2351 V1AppMenuGenerationTwoUsers
) {
2352 // Create a browser item in the LauncherController.
2353 InitLauncherController();
2354 chrome::NewTab(browser());
2356 // Installing |extension3_| adds it to the launcher.
2357 ash::ShelfID gmail_id
= model_
->next_id();
2358 extension_service_
->AddExtension(extension3_
.get());
2359 EXPECT_EQ(3, model_
->item_count());
2360 int gmail_index
= model_
->ItemIndexByID(gmail_id
);
2361 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[gmail_index
].type
);
2362 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2363 launcher_controller_
->SetRefocusURLPatternForTest(gmail_id
, GURL(gmail_url
));
2365 // Check the menu content.
2366 ash::ShelfItem item_browser
;
2367 item_browser
.type
= ash::TYPE_BROWSER_SHORTCUT
;
2369 launcher_controller_
->GetShelfIDForAppID(extension_misc::kChromeAppId
);
2371 ash::ShelfItem item_gmail
;
2372 item_gmail
.type
= ash::TYPE_APP_SHORTCUT
;
2373 item_gmail
.id
= gmail_id
;
2374 EXPECT_TRUE(CheckMenuCreation(
2375 launcher_controller_
.get(), item_gmail
, 0, NULL
, false));
2377 // Set the gmail URL to a new tab.
2378 base::string16 title1
= ASCIIToUTF16("Test1");
2379 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url
), title1
);
2381 base::string16 one_menu_item
[] = { title1
};
2382 EXPECT_TRUE(CheckMenuCreation(
2383 launcher_controller_
.get(), item_gmail
, 1, one_menu_item
, false));
2385 // Create a second profile and switch to that user.
2386 std::string user2
= "user2";
2387 TestingProfile
* profile2
= CreateMultiUserProfile(user2
);
2388 SwitchActiveUser(profile2
->GetProfileName());
2390 // No item should have content yet.
2391 EXPECT_TRUE(CheckMenuCreation(
2392 launcher_controller_
.get(), item_browser
, 0, NULL
, true));
2393 EXPECT_TRUE(CheckMenuCreation(
2394 launcher_controller_
.get(), item_gmail
, 0, NULL
, false));
2396 // Transfer the browser of the first user - it should still not show up.
2397 chrome::MultiUserWindowManager::GetInstance()->ShowWindowForUser(
2398 browser()->window()->GetNativeWindow(),
2401 EXPECT_TRUE(CheckMenuCreation(
2402 launcher_controller_
.get(), item_browser
, 0, NULL
, true));
2403 EXPECT_TRUE(CheckMenuCreation(
2404 launcher_controller_
.get(), item_gmail
, 0, NULL
, false));
2407 // Check that V2 applications are creating items properly in the launcher when
2408 // instantiated by the current user.
2409 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
,
2410 V2AppHandlingTwoUsers
) {
2411 InitLauncherController();
2412 // Create a profile for our second user (will be destroyed by the framework).
2413 TestingProfile
* profile2
= CreateMultiUserProfile("user2");
2414 // Check that there is a browser and a app launcher.
2415 EXPECT_EQ(2, model_
->item_count());
2418 V2App
v2_app(profile(), extension1_
);
2419 EXPECT_EQ(3, model_
->item_count());
2421 // After switching users the item should go away.
2422 SwitchActiveUser(profile2
->GetProfileName());
2423 EXPECT_EQ(2, model_
->item_count());
2425 // And it should come back when switching back.
2426 SwitchActiveUser(profile()->GetProfileName());
2427 EXPECT_EQ(3, model_
->item_count());
2430 // Check that V2 applications are creating items properly in edge cases:
2431 // a background user creates a V2 app, gets active and inactive again and then
2433 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
,
2434 V2AppHandlingTwoUsersEdgeCases
) {
2435 InitLauncherController();
2436 // Create a profile for our second user (will be destroyed by the framework).
2437 TestingProfile
* profile2
= CreateMultiUserProfile("user2");
2438 // Check that there is a browser and a app launcher.
2439 EXPECT_EQ(2, model_
->item_count());
2441 // Switch to an inactive user.
2442 SwitchActiveUser(profile2
->GetProfileName());
2443 EXPECT_EQ(2, model_
->item_count());
2445 // Add the v2 app to the inactive user and check that no item was added to
2448 V2App
v2_app(profile(), extension1_
);
2449 EXPECT_EQ(2, model_
->item_count());
2451 // Switch to the primary user and check that the item is shown.
2452 SwitchActiveUser(profile()->GetProfileName());
2453 EXPECT_EQ(3, model_
->item_count());
2455 // Switch to the second user and check that the item goes away - even if the
2456 // item gets closed.
2457 SwitchActiveUser(profile2
->GetProfileName());
2458 EXPECT_EQ(2, model_
->item_count());
2461 // After the application was killed there should be still 2 items.
2462 EXPECT_EQ(2, model_
->item_count());
2464 // Switching then back to the default user should not show the additional item
2466 SwitchActiveUser(profile()->GetProfileName());
2467 EXPECT_EQ(2, model_
->item_count());
2469 #endif // defined(OS_CHROMEOS)
2471 // Checks that the generated menu list properly activates items.
2472 TEST_F(ChromeLauncherControllerTest
, V1AppMenuExecution
) {
2473 InitLauncherControllerWithBrowser();
2475 // Add |extension3_| to the launcher and add two items.
2476 GURL gmail
= GURL("https://mail.google.com/mail/u");
2477 ash::ShelfID gmail_id
= model_
->next_id();
2478 extension_service_
->AddExtension(extension3_
.get());
2479 launcher_controller_
->SetRefocusURLPatternForTest(gmail_id
, GURL(gmail_url
));
2480 base::string16 title1
= ASCIIToUTF16("Test1");
2481 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url
), title1
);
2482 chrome::NewTab(browser());
2483 base::string16 title2
= ASCIIToUTF16("Test2");
2484 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url
), title2
);
2486 // Check that the menu is properly set.
2487 ash::ShelfItem item_gmail
;
2488 item_gmail
.type
= ash::TYPE_APP_SHORTCUT
;
2489 item_gmail
.id
= gmail_id
;
2490 base::string16 two_menu_items
[] = {title1
, title2
};
2491 EXPECT_TRUE(CheckMenuCreation(
2492 launcher_controller_
.get(), item_gmail
, 2, two_menu_items
, false));
2493 EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
2494 // Execute the second item in the list (which shouldn't do anything since that
2495 // item is per definition already the active tab).
2497 scoped_ptr
<ash::ShelfMenuModel
> menu(new LauncherApplicationMenuItemModel(
2498 launcher_controller_
->GetApplicationList(item_gmail
, 0)));
2499 // The first element in the menu is a spacing separator. On some systems
2500 // (e.g. Windows) such things do not exist. As such we check the existence
2501 // and adjust dynamically.
2503 (menu
->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR
) ? 1 : 0;
2504 menu
->ActivatedAt(first_item
+ 3);
2506 EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
2508 // Execute the first item.
2510 scoped_ptr
<ash::ShelfMenuModel
> menu(new LauncherApplicationMenuItemModel(
2511 launcher_controller_
->GetApplicationList(item_gmail
, 0)));
2513 (menu
->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR
) ? 1 : 0;
2514 menu
->ActivatedAt(first_item
+ 2);
2516 // Now the active tab should be the second item.
2517 EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
2520 // Checks that the generated menu list properly deletes items.
2521 TEST_F(ChromeLauncherControllerTest
, V1AppMenuDeletionExecution
) {
2522 InitLauncherControllerWithBrowser();
2524 // Add |extension3_| to the launcher and add two items.
2525 GURL gmail
= GURL("https://mail.google.com/mail/u");
2526 ash::ShelfID gmail_id
= model_
->next_id();
2527 extension_service_
->AddExtension(extension3_
.get());
2528 launcher_controller_
->SetRefocusURLPatternForTest(gmail_id
, GURL(gmail_url
));
2529 base::string16 title1
= ASCIIToUTF16("Test1");
2530 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url
), title1
);
2531 chrome::NewTab(browser());
2532 base::string16 title2
= ASCIIToUTF16("Test2");
2533 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url
), title2
);
2535 // Check that the menu is properly set.
2536 ash::ShelfItem item_gmail
;
2537 item_gmail
.type
= ash::TYPE_APP_SHORTCUT
;
2538 item_gmail
.id
= gmail_id
;
2539 base::string16 two_menu_items
[] = {title1
, title2
};
2540 EXPECT_TRUE(CheckMenuCreation(
2541 launcher_controller_
.get(), item_gmail
, 2, two_menu_items
, false));
2543 int tabs
= browser()->tab_strip_model()->count();
2544 // Activate the proper tab through the menu item.
2546 ChromeLauncherAppMenuItems items
=
2547 launcher_controller_
->GetApplicationList(item_gmail
, 0);
2548 items
[1]->Execute(0);
2549 EXPECT_EQ(tabs
, browser()->tab_strip_model()->count());
2552 // Delete one tab through the menu item.
2554 ChromeLauncherAppMenuItems items
=
2555 launcher_controller_
->GetApplicationList(item_gmail
, 0);
2556 items
[1]->Execute(ui::EF_SHIFT_DOWN
);
2557 EXPECT_EQ(--tabs
, browser()->tab_strip_model()->count());
2561 // Tests that panels create launcher items correctly
2562 TEST_F(ChromeLauncherControllerTest
, AppPanels
) {
2563 InitLauncherControllerWithBrowser();
2564 // App list and Browser shortcut ShelfItems are added.
2565 EXPECT_EQ(2, model_observer_
->added());
2567 TestAppIconLoaderImpl
* app_icon_loader
= new TestAppIconLoaderImpl();
2568 SetAppIconLoader(app_icon_loader
);
2570 // Test adding an app panel
2571 std::string app_id
= extension1_
->id();
2572 ShellWindowLauncherItemController
* app_panel_controller
=
2573 new ShellWindowLauncherItemController(
2574 LauncherItemController::TYPE_APP_PANEL
,
2577 launcher_controller_
.get());
2578 ash::ShelfID shelf_id1
= launcher_controller_
->CreateAppLauncherItem(
2579 app_panel_controller
, app_id
, ash::STATUS_RUNNING
);
2580 int panel_index
= model_observer_
->last_index();
2581 EXPECT_EQ(3, model_observer_
->added());
2582 EXPECT_EQ(0, model_observer_
->changed());
2583 EXPECT_EQ(1, app_icon_loader
->fetch_count());
2584 model_observer_
->clear_counts();
2586 // App panels should have a separate identifier than the app id
2587 EXPECT_EQ(0, launcher_controller_
->GetShelfIDForAppID(app_id
));
2589 // Setting the app image image should not change the panel if it set its icon
2590 app_panel_controller
->set_image_set_by_controller(true);
2591 gfx::ImageSkia image
;
2592 launcher_controller_
->SetAppImage(app_id
, image
);
2593 EXPECT_EQ(0, model_observer_
->changed());
2594 model_observer_
->clear_counts();
2596 // Add a second app panel and verify that it get the same index as the first
2597 // one had, being added to the left of the existing panel.
2598 ShellWindowLauncherItemController
* app_panel_controller2
=
2599 new ShellWindowLauncherItemController(
2600 LauncherItemController::TYPE_APP_PANEL
,
2603 launcher_controller_
.get());
2605 ash::ShelfID shelf_id2
= launcher_controller_
->CreateAppLauncherItem(
2606 app_panel_controller2
, app_id
, ash::STATUS_RUNNING
);
2607 EXPECT_EQ(panel_index
, model_observer_
->last_index());
2608 EXPECT_EQ(1, model_observer_
->added());
2609 model_observer_
->clear_counts();
2611 launcher_controller_
->CloseLauncherItem(shelf_id2
);
2612 launcher_controller_
->CloseLauncherItem(shelf_id1
);
2613 EXPECT_EQ(2, model_observer_
->removed());
2616 // Tests that the Gmail extension matches more then the app itself claims with
2617 // the manifest file.
2618 TEST_F(ChromeLauncherControllerTest
, GmailMatching
) {
2619 InitLauncherControllerWithBrowser();
2621 // Create a Gmail browser tab.
2622 chrome::NewTab(browser());
2623 base::string16 title
= ASCIIToUTF16("Test");
2624 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url
), title
);
2625 content::WebContents
* content
=
2626 browser()->tab_strip_model()->GetActiveWebContents();
2628 // Check that the launcher controller does not recognize the running app.
2629 EXPECT_FALSE(launcher_controller_
->ContentCanBeHandledByGmailApp(content
));
2631 // Installing |extension3_| adds it to the launcher.
2632 ash::ShelfID gmail_id
= model_
->next_id();
2633 extension_service_
->AddExtension(extension3_
.get());
2634 EXPECT_EQ(3, model_
->item_count());
2635 int gmail_index
= model_
->ItemIndexByID(gmail_id
);
2636 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[gmail_index
].type
);
2637 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2639 // Check that it is now handled.
2640 EXPECT_TRUE(launcher_controller_
->ContentCanBeHandledByGmailApp(content
));
2642 // Check also that the app has detected that properly.
2643 ash::ShelfItem item_gmail
;
2644 item_gmail
.type
= ash::TYPE_APP_SHORTCUT
;
2645 item_gmail
.id
= gmail_id
;
2646 EXPECT_EQ(2U, launcher_controller_
->GetApplicationList(item_gmail
, 0).size());
2649 // Tests that the Gmail extension does not match the offline verison.
2650 TEST_F(ChromeLauncherControllerTest
, GmailOfflineMatching
) {
2651 InitLauncherControllerWithBrowser();
2653 // Create a Gmail browser tab.
2654 chrome::NewTab(browser());
2655 base::string16 title
= ASCIIToUTF16("Test");
2656 NavigateAndCommitActiveTabWithTitle(browser(),
2657 GURL(offline_gmail_url
),
2659 content::WebContents
* content
=
2660 browser()->tab_strip_model()->GetActiveWebContents();
2662 // Installing |extension3_| adds it to the launcher.
2663 ash::ShelfID gmail_id
= model_
->next_id();
2664 extension_service_
->AddExtension(extension3_
.get());
2665 EXPECT_EQ(3, model_
->item_count());
2666 int gmail_index
= model_
->ItemIndexByID(gmail_id
);
2667 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[gmail_index
].type
);
2668 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2670 // The content should not be able to be handled by the app.
2671 EXPECT_FALSE(launcher_controller_
->ContentCanBeHandledByGmailApp(content
));
2674 // Verify that the launcher item positions are persisted and restored.
2675 TEST_F(ChromeLauncherControllerTest
, PersistLauncherItemPositions
) {
2676 InitLauncherController();
2678 TestAppTabHelperImpl
* app_tab_helper
= new TestAppTabHelperImpl
;
2679 SetAppTabHelper(app_tab_helper
);
2681 EXPECT_EQ(ash::TYPE_APP_LIST
, model_
->items()[0].type
);
2682 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT
, model_
->items()[1].type
);
2684 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2685 EXPECT_EQ(0, tab_strip_model
->count());
2686 chrome::NewTab(browser());
2687 chrome::NewTab(browser());
2688 EXPECT_EQ(2, tab_strip_model
->count());
2689 app_tab_helper
->SetAppID(tab_strip_model
->GetWebContentsAt(0), "1");
2690 app_tab_helper
->SetAppID(tab_strip_model
->GetWebContentsAt(1), "2");
2692 EXPECT_FALSE(launcher_controller_
->IsAppPinned("1"));
2693 launcher_controller_
->PinAppWithID("1");
2694 EXPECT_TRUE(launcher_controller_
->IsAppPinned("1"));
2695 launcher_controller_
->PinAppWithID("2");
2697 EXPECT_EQ(ash::TYPE_APP_LIST
, model_
->items()[0].type
);
2698 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT
, model_
->items()[1].type
);
2699 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
2700 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[3].type
);
2702 // Move browser shortcut item from index 1 to index 3.
2704 EXPECT_EQ(ash::TYPE_APP_LIST
, model_
->items()[0].type
);
2705 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[1].type
);
2706 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
2707 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT
, model_
->items()[3].type
);
2709 launcher_controller_
.reset();
2710 if (!ash::Shell::HasInstance()) {
2711 delete item_delegate_manager_
;
2713 // Clear already registered ShelfItemDelegate.
2714 ash::test::ShelfItemDelegateManagerTestAPI
test(item_delegate_manager_
);
2715 test
.RemoveAllShelfItemDelegateForTest();
2717 model_
.reset(new ash::ShelfModel
);
2719 AddAppListLauncherItem();
2720 launcher_controller_
.reset(
2721 ChromeLauncherController::CreateInstance(profile(), model_
.get()));
2722 app_tab_helper
= new TestAppTabHelperImpl
;
2723 app_tab_helper
->SetAppID(tab_strip_model
->GetWebContentsAt(0), "1");
2724 app_tab_helper
->SetAppID(tab_strip_model
->GetWebContentsAt(1), "2");
2725 SetAppTabHelper(app_tab_helper
);
2726 if (!ash::Shell::HasInstance()) {
2727 item_delegate_manager_
= new ash::ShelfItemDelegateManager(model_
.get());
2728 SetShelfItemDelegateManager(item_delegate_manager_
);
2730 launcher_controller_
->Init();
2732 // Check ShelfItems are restored after resetting ChromeLauncherController.
2733 EXPECT_EQ(ash::TYPE_APP_LIST
, model_
->items()[0].type
);
2734 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[1].type
);
2735 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
2736 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT
, model_
->items()[3].type
);
2739 // Verifies pinned apps are persisted and restored.
2740 TEST_F(ChromeLauncherControllerTest
, PersistPinned
) {
2741 InitLauncherControllerWithBrowser();
2742 size_t initial_size
= model_
->items().size();
2744 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2745 EXPECT_EQ(1, tab_strip_model
->count());
2747 TestAppTabHelperImpl
* app_tab_helper
= new TestAppTabHelperImpl
;
2748 app_tab_helper
->SetAppID(tab_strip_model
->GetWebContentsAt(0), "1");
2749 SetAppTabHelper(app_tab_helper
);
2751 TestAppIconLoaderImpl
* app_icon_loader
= new TestAppIconLoaderImpl
;
2752 SetAppIconLoader(app_icon_loader
);
2753 EXPECT_EQ(0, app_icon_loader
->fetch_count());
2755 launcher_controller_
->PinAppWithID("1");
2756 ash::ShelfID id
= launcher_controller_
->GetShelfIDForAppID("1");
2757 int app_index
= model_
->ItemIndexByID(id
);
2758 EXPECT_EQ(1, app_icon_loader
->fetch_count());
2759 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[app_index
].type
);
2760 EXPECT_TRUE(launcher_controller_
->IsAppPinned("1"));
2761 EXPECT_FALSE(launcher_controller_
->IsAppPinned("0"));
2762 EXPECT_EQ(initial_size
+ 1, model_
->items().size());
2764 launcher_controller_
.reset();
2765 if (!ash::Shell::HasInstance()) {
2766 delete item_delegate_manager_
;
2768 // Clear already registered ShelfItemDelegate.
2769 ash::test::ShelfItemDelegateManagerTestAPI
test(item_delegate_manager_
);
2770 test
.RemoveAllShelfItemDelegateForTest();
2772 model_
.reset(new ash::ShelfModel
);
2774 AddAppListLauncherItem();
2775 launcher_controller_
.reset(
2776 ChromeLauncherController::CreateInstance(profile(), model_
.get()));
2777 app_tab_helper
= new TestAppTabHelperImpl
;
2778 app_tab_helper
->SetAppID(tab_strip_model
->GetWebContentsAt(0), "1");
2779 SetAppTabHelper(app_tab_helper
);
2780 app_icon_loader
= new TestAppIconLoaderImpl
;
2781 SetAppIconLoader(app_icon_loader
);
2782 if (!ash::Shell::HasInstance()) {
2783 item_delegate_manager_
= new ash::ShelfItemDelegateManager(model_
.get());
2784 SetShelfItemDelegateManager(item_delegate_manager_
);
2786 launcher_controller_
->Init();
2788 EXPECT_EQ(1, app_icon_loader
->fetch_count());
2789 ASSERT_EQ(initial_size
+ 1, model_
->items().size());
2790 EXPECT_TRUE(launcher_controller_
->IsAppPinned("1"));
2791 EXPECT_FALSE(launcher_controller_
->IsAppPinned("0"));
2792 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[app_index
].type
);
2794 launcher_controller_
->UnpinAppWithID("1");
2795 ASSERT_EQ(initial_size
, model_
->items().size());