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 "content/public/test/test_browser_thread.h"
44 #include "extensions/common/extension.h"
45 #include "extensions/common/manifest_constants.h"
46 #include "testing/gtest/include/gtest/gtest.h"
47 #include "ui/base/models/menu_model.h"
49 #if defined(OS_CHROMEOS)
50 #include "apps/app_window_contents.h"
51 #include "apps/shell_window_registry.h"
52 #include "apps/ui/native_app_window.h"
53 #include "ash/test/test_session_state_delegate.h"
54 #include "ash/test/test_shell_delegate.h"
55 #include "base/metrics/field_trial.h"
56 #include "chrome/browser/chromeos/login/fake_user_manager.h"
57 #include "chrome/browser/ui/apps/chrome_shell_window_delegate.h"
58 #include "chrome/browser/ui/ash/launcher/browser_status_monitor.h"
59 #include "chrome/browser/ui/ash/launcher/shell_window_launcher_controller.h"
60 #include "chrome/browser/ui/ash/multi_user/multi_user_util.h"
61 #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h"
62 #include "chrome/common/chrome_constants.h"
63 #include "chrome/common/chrome_switches.h"
64 #include "chrome/test/base/testing_browser_process.h"
65 #include "chrome/test/base/testing_profile_manager.h"
66 #include "components/variations/entropy_provider.h"
67 #include "content/public/browser/web_contents_observer.h"
68 #include "content/public/test/test_utils.h"
69 #include "ui/aura/window.h"
70 #include "ui/views/test/test_views_delegate.h"
73 using base::ASCIIToUTF16
;
74 using extensions::Extension
;
75 using extensions::Manifest
;
76 using extensions::UnloadedExtensionInfo
;
79 const char* offline_gmail_url
= "https://mail.google.com/mail/mu/u";
80 const char* gmail_url
= "https://mail.google.com/mail/u";
81 const char* kGmailLaunchURL
= "https://mail.google.com/mail/ca";
83 // As defined in /chromeos/dbus/cryptohome_client.cc.
84 const char kUserIdHashSuffix
[] = "-hash";
86 // An extension prefix.
87 const char kCrxAppPrefix
[] = "_crx_";
89 // ShelfModelObserver implementation that tracks what messages are invoked.
90 class TestShelfModelObserver
: public ash::ShelfModelObserver
{
92 TestShelfModelObserver()
98 virtual ~TestShelfModelObserver() {
101 // Overridden from ash::ShelfModelObserver:
102 virtual void ShelfItemAdded(int index
) OVERRIDE
{
107 virtual void ShelfItemRemoved(int index
, ash::LauncherID id
) OVERRIDE
{
112 virtual void ShelfItemChanged(int index
,
113 const ash::LauncherItem
& old_item
) OVERRIDE
{
118 virtual void ShelfItemMoved(int start_index
, int target_index
) OVERRIDE
{
119 last_index_
= target_index
;
122 virtual void ShelfStatusChanged() OVERRIDE
{
125 void clear_counts() {
132 int added() const { return added_
; }
133 int removed() const { return removed_
; }
134 int changed() const { return changed_
; }
135 int last_index() const { return last_index_
; }
143 DISALLOW_COPY_AND_ASSIGN(TestShelfModelObserver
);
146 // Test implementation of AppIconLoader.
147 class TestAppIconLoaderImpl
: public extensions::AppIconLoader
{
149 TestAppIconLoaderImpl() : fetch_count_(0) {
152 virtual ~TestAppIconLoaderImpl() {
155 // AppIconLoader implementation:
156 virtual void FetchImage(const std::string
& id
) OVERRIDE
{
160 virtual void ClearImage(const std::string
& id
) OVERRIDE
{
163 virtual void UpdateImage(const std::string
& id
) OVERRIDE
{
166 int fetch_count() const { return fetch_count_
; }
171 DISALLOW_COPY_AND_ASSIGN(TestAppIconLoaderImpl
);
174 // Test implementation of AppTabHelper.
175 class TestAppTabHelperImpl
: public ChromeLauncherController::AppTabHelper
{
177 TestAppTabHelperImpl() {}
178 virtual ~TestAppTabHelperImpl() {}
180 // Sets the id for the specified tab. The id is removed if Remove() is
182 void SetAppID(content::WebContents
* tab
, const std::string
& id
) {
183 tab_id_map_
[tab
] = id
;
186 // Returns true if there is an id registered for |tab|.
187 bool HasAppID(content::WebContents
* tab
) const {
188 return tab_id_map_
.find(tab
) != tab_id_map_
.end();
191 // AppTabHelper implementation:
192 virtual std::string
GetAppID(content::WebContents
* tab
) OVERRIDE
{
193 return tab_id_map_
.find(tab
) != tab_id_map_
.end() ? tab_id_map_
[tab
] :
197 virtual bool IsValidIDForCurrentUser(const std::string
& id
) OVERRIDE
{
198 for (TabToStringMap::const_iterator i
= tab_id_map_
.begin();
199 i
!= tab_id_map_
.end(); ++i
) {
206 virtual void SetCurrentUser(Profile
* profile
) OVERRIDE
{
207 // We can ignore this for now.
211 typedef std::map
<content::WebContents
*, std::string
> TabToStringMap
;
213 TabToStringMap tab_id_map_
;
215 DISALLOW_COPY_AND_ASSIGN(TestAppTabHelperImpl
);
218 // Test implementation of a V2 app launcher item controller.
219 class TestV2AppLauncherItemController
: public LauncherItemController
{
221 TestV2AppLauncherItemController(const std::string
& app_id
,
222 ChromeLauncherController
* controller
)
223 : LauncherItemController(LauncherItemController::TYPE_APP
,
228 virtual ~TestV2AppLauncherItemController() {}
230 // Override for LauncherItemController:
231 virtual bool IsOpen() const OVERRIDE
{ return true; }
232 virtual bool IsVisible() const OVERRIDE
{ return true; }
233 virtual void Launch(ash::LaunchSource source
, int event_flags
) OVERRIDE
{}
234 virtual bool Activate(ash::LaunchSource source
) OVERRIDE
{ return false; }
235 virtual void Close() OVERRIDE
{}
236 virtual bool ItemSelected(const ui::Event
& event
) OVERRIDE
{ return false; }
237 virtual base::string16
GetTitle() OVERRIDE
{ return base::string16(); }
238 virtual ChromeLauncherAppMenuItems
GetApplicationList(
239 int event_flags
) OVERRIDE
{
240 ChromeLauncherAppMenuItems items
;
242 new ChromeLauncherAppMenuItem(base::string16(), NULL
, false));
244 new ChromeLauncherAppMenuItem(base::string16(), NULL
, false));
247 virtual ui::MenuModel
* CreateContextMenu(aura::Window
* root_window
) OVERRIDE
{
250 virtual ash::ShelfMenuModel
* CreateApplicationMenu(int event_flags
) OVERRIDE
{
253 virtual bool IsDraggable() OVERRIDE
{ return false; }
254 virtual bool ShouldShowTooltip() OVERRIDE
{ return false; }
258 DISALLOW_COPY_AND_ASSIGN(TestV2AppLauncherItemController
);
263 class ChromeLauncherControllerTest
: public BrowserWithTestWindowTest
{
265 ChromeLauncherControllerTest() : test_controller_(NULL
),
266 extension_service_(NULL
) {
267 SetHostDesktopType(chrome::HOST_DESKTOP_TYPE_ASH
);
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::LauncherItem 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::LauncherItems::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_
->GetAppIDForLauncherID(
495 model_
->items()[i
].id
);
496 if (app
== extension1_
->id()) {
499 launcher_controller_
->IsAppPinned(extension1_
->id()));
500 } else if (app
== extension2_
->id()) {
503 launcher_controller_
->IsAppPinned(extension2_
->id()));
504 } else if (app
== extension3_
->id()) {
507 launcher_controller_
->IsAppPinned(extension3_
->id()));
508 } else if (app
== extension4_
->id()) {
511 launcher_controller_
->IsAppPinned(extension4_
->id()));
512 } else if (app
== extension5_
->id()) {
515 launcher_controller_
->IsAppPinned(extension5_
->id()));
516 } else if (app
== extension6_
->id()) {
519 launcher_controller_
->IsAppPinned(extension6_
->id()));
520 } else if (app
== extension7_
->id()) {
523 launcher_controller_
->IsAppPinned(extension7_
->id()));
524 } else if (app
== extension8_
->id()) {
527 launcher_controller_
->IsAppPinned(extension8_
->id()));
533 case ash::TYPE_APP_SHORTCUT
: {
534 const std::string
& app
=
535 launcher_controller_
->GetAppIDForLauncherID(
536 model_
->items()[i
].id
);
537 if (app
== extension1_
->id()) {
539 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
540 } else if (app
== extension2_
->id()) {
542 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension2_
->id()));
543 } else if (app
== extension3_
->id()) {
545 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension3_
->id()));
546 } else if (app
== extension4_
->id()) {
548 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension4_
->id()));
549 } else if (app
== extension5_
->id()) {
551 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension5_
->id()));
552 } else if (app
== extension6_
->id()) {
554 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension6_
->id()));
555 } else if (app
== extension7_
->id()) {
557 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension7_
->id()));
558 } else if (app
== extension8_
->id()) {
560 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension8_
->id()));
566 case ash::TYPE_BROWSER_SHORTCUT
:
569 case ash::TYPE_APP_LIST
:
580 // Set the index at which the chrome icon should be.
581 void SetShelfChromeIconIndex(int index
) {
582 profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex
,
586 // Remember the order of unpinned but running applications for the current
588 void RememberUnpinnedRunningApplicationOrder() {
589 launcher_controller_
->RememberUnpinnedRunningApplicationOrder();
592 // Restore the order of running but unpinned applications for a given user.
593 void RestoreUnpinnedRunningApplicationOrder(const std::string
& user_id
) {
594 launcher_controller_
->RestoreUnpinnedRunningApplicationOrder(user_id
);
597 // Needed for extension service & friends to work.
598 scoped_refptr
<Extension
> extension1_
;
599 scoped_refptr
<Extension
> extension2_
;
600 scoped_refptr
<Extension
> extension3_
;
601 scoped_refptr
<Extension
> extension4_
;
602 scoped_refptr
<Extension
> extension5_
;
603 scoped_refptr
<Extension
> extension6_
;
604 scoped_refptr
<Extension
> extension7_
;
605 scoped_refptr
<Extension
> extension8_
;
606 scoped_ptr
<ChromeLauncherController
> launcher_controller_
;
607 scoped_ptr
<TestShelfModelObserver
> model_observer_
;
608 scoped_ptr
<ash::ShelfModel
> model_
;
610 // |item_delegate_manager_| owns |test_controller_|.
611 LauncherItemController
* test_controller_
;
613 ExtensionService
* extension_service_
;
615 ash::ShelfItemDelegateManager
* item_delegate_manager_
;
617 DISALLOW_COPY_AND_ASSIGN(ChromeLauncherControllerTest
);
620 // The testing framework to test the legacy shelf layout.
621 class LegacyShelfLayoutChromeLauncherControllerTest
622 : public ChromeLauncherControllerTest
{
624 LegacyShelfLayoutChromeLauncherControllerTest() {
627 virtual ~LegacyShelfLayoutChromeLauncherControllerTest() {
630 // Overwrite the Setup function to use the legacy shelf layout option.
631 virtual void SetUp() OVERRIDE
{
632 CommandLine::ForCurrentProcess()->AppendSwitch(
633 ash::switches::kAshDisableAlternateShelfLayout
);
634 ChromeLauncherControllerTest::SetUp();
639 DISALLOW_COPY_AND_ASSIGN(LegacyShelfLayoutChromeLauncherControllerTest
);
642 #if defined(OS_CHROMEOS)
643 // A browser window proxy which is able to associate an aura native window with
645 class TestBrowserWindowAura
: public TestBrowserWindow
{
647 // |native_window| will still be owned by the caller after the constructor
649 explicit TestBrowserWindowAura(aura::Window
* native_window
)
650 : native_window_(native_window
) {
652 virtual ~TestBrowserWindowAura() {}
654 virtual gfx::NativeWindow
GetNativeWindow() OVERRIDE
{
655 return native_window_
.get();
658 Browser
* browser() { return browser_
.get(); }
660 void CreateBrowser(const Browser::CreateParams
& params
) {
661 Browser::CreateParams create_params
= params
;
662 create_params
.window
= this;
663 browser_
.reset(new Browser(create_params
));
667 scoped_ptr
<Browser
> browser_
;
668 scoped_ptr
<aura::Window
> native_window_
;
670 DISALLOW_COPY_AND_ASSIGN(TestBrowserWindowAura
);
673 // Creates a test browser window which has a native window.
674 scoped_ptr
<TestBrowserWindowAura
> CreateTestBrowserWindow(
675 const Browser::CreateParams
& params
) {
677 aura::Window
* window
= new aura::Window(NULL
);
679 window
->SetType(ui::wm::WINDOW_TYPE_NORMAL
);
680 window
->Init(aura::WINDOW_LAYER_TEXTURED
);
683 scoped_ptr
<TestBrowserWindowAura
> browser_window(
684 new TestBrowserWindowAura(window
));
685 browser_window
->CreateBrowser(params
);
686 return browser_window
.Pass();
689 // A views delegate which allows creating shell windows.
690 class TestViewsDelegateForAppTest
: public views::TestViewsDelegate
{
692 TestViewsDelegateForAppTest() {}
693 virtual ~TestViewsDelegateForAppTest() {}
695 // views::TestViewsDelegate overrides.
696 virtual void OnBeforeWidgetInit(
697 views::Widget::InitParams
* params
,
698 views::internal::NativeWidgetDelegate
* delegate
) OVERRIDE
{
699 if (!params
->parent
&& !params
->context
) {
700 // If the window has neither a parent nor a context we add the root window
702 params
->parent
= ash::Shell::GetInstance()->GetPrimaryRootWindow();
707 DISALLOW_COPY_AND_ASSIGN(TestViewsDelegateForAppTest
);
710 // Watches WebContents and blocks until it is destroyed. This is needed for
711 // the destruction of a V2 application.
712 class WebContentsDestroyedWatcher
: public content::WebContentsObserver
{
714 explicit WebContentsDestroyedWatcher(content::WebContents
* web_contents
)
715 : content::WebContentsObserver(web_contents
),
716 message_loop_runner_(new content::MessageLoopRunner
) {
717 EXPECT_TRUE(web_contents
!= NULL
);
719 virtual ~WebContentsDestroyedWatcher() {}
721 // Waits until the WebContents is destroyed.
723 message_loop_runner_
->Run();
727 // Overridden WebContentsObserver methods.
728 virtual void WebContentsDestroyed(
729 content::WebContents
* web_contents
) OVERRIDE
{
730 message_loop_runner_
->Quit();
733 scoped_refptr
<content::MessageLoopRunner
> message_loop_runner_
;
735 DISALLOW_COPY_AND_ASSIGN(WebContentsDestroyedWatcher
);
738 // A V1 windowed application.
739 class V1App
: public TestBrowserWindow
{
741 V1App(Profile
* profile
, const std::string
& app_name
) {
743 native_window_
.reset(new aura::Window(NULL
));
744 native_window_
->set_id(0);
745 native_window_
->SetType(ui::wm::WINDOW_TYPE_POPUP
);
746 native_window_
->Init(aura::WINDOW_LAYER_TEXTURED
);
747 native_window_
->Show();
749 Browser::CreateParams params
= Browser::CreateParams::CreateForApp(
751 kCrxAppPrefix
+ app_name
,
754 chrome::HOST_DESKTOP_TYPE_ASH
);
755 params
.window
= this;
756 browser_
.reset(new Browser(params
));
757 chrome::AddTabAt(browser_
.get(), GURL(), 0, true);
761 // close all tabs. Note that we do not need to destroy the browser itself.
762 browser_
->tab_strip_model()->CloseAllTabs();
765 Browser
* browser() { return browser_
.get(); }
767 // TestBrowserWindow override:
768 virtual gfx::NativeWindow
GetNativeWindow() OVERRIDE
{
769 return native_window_
.get();
773 // The associated browser with this app.
774 scoped_ptr
<Browser
> browser_
;
776 // The native window we use.
777 scoped_ptr
<aura::Window
> native_window_
;
779 DISALLOW_COPY_AND_ASSIGN(V1App
);
782 // A V2 application which gets created with an |extension| and for a |profile|.
783 // Upon destruction it will properly close the application.
786 V2App(Profile
* profile
, const extensions::Extension
* extension
) {
787 window_
= new apps::ShellWindow(profile
,
788 new ChromeShellWindowDelegate(),
790 apps::ShellWindow::CreateParams params
= apps::ShellWindow::CreateParams();
791 window_
->Init(GURL(std::string()),
792 new apps::AppWindowContents(window_
),
797 WebContentsDestroyedWatcher
destroyed_watcher(window_
->web_contents());
798 window_
->GetBaseWindow()->Close();
799 destroyed_watcher
.Wait();
803 // The shell window which represents the application. Note that the window
804 // deletes itself asynchronously after window_->GetBaseWindow()->Close() gets
806 apps::ShellWindow
* window_
;
808 DISALLOW_COPY_AND_ASSIGN(V2App
);
811 // The testing framework to test multi profile scenarios.
812 class MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
813 : public ChromeLauncherControllerTest
{
815 MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest() {
818 virtual ~MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest() {
821 // Overwrite the Setup function to enable multi profile and needed objects.
822 virtual void SetUp() OVERRIDE
{
823 profile_manager_
.reset(
824 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
826 ASSERT_TRUE(profile_manager_
->SetUp());
828 // AvatarMenu and multiple profiles works after user logged in.
829 profile_manager_
->SetLoggedIn(true);
831 // Enabling multi profile requires several flags to be set.
832 CommandLine::ForCurrentProcess()->AppendSwitch(switches::kMultiProfiles
);
833 field_trial_list_
.reset(new base::FieldTrialList(
834 new metrics::SHA1EntropyProvider("42")));
835 base::FieldTrialList::CreateTrialsFromString(
836 "ChromeOSUseMultiProfiles/Enable/",
837 base::FieldTrialList::ACTIVATE_TRIALS
);
839 // Initialize the UserManager singleton to a fresh FakeUserManager instance.
840 user_manager_enabler_
.reset(
841 new chromeos::ScopedUserManagerEnabler(new chromeos::FakeUserManager
));
843 // Initialize the rest.
844 ChromeLauncherControllerTest::SetUp();
846 // Get some base objects.
847 session_delegate_
= static_cast<ash::test::TestSessionStateDelegate
*>(
848 ash::Shell::GetInstance()->session_state_delegate());
849 session_delegate_
->set_logged_in_users(2);
850 shell_delegate_
= static_cast<ash::test::TestShellDelegate
*>(
851 ash::Shell::GetInstance()->delegate());
852 shell_delegate_
->set_multi_profiles_enabled(true);
855 virtual void TearDown() {
856 ChromeLauncherControllerTest::TearDown();
857 user_manager_enabler_
.reset();
858 field_trial_list_
.reset();
859 for (ProfileToNameMap::iterator it
= created_profiles_
.begin();
860 it
!= created_profiles_
.end(); ++it
)
861 profile_manager_
->DeleteTestingProfile(it
->second
);
863 // A Task is leaked if we don't destroy everything, then run the message
865 base::MessageLoop::current()->PostTask(FROM_HERE
,
866 base::MessageLoop::QuitClosure());
867 base::MessageLoop::current()->Run();
870 // Creates a profile for a given |user_name|. Note that this class will keep
871 // the ownership of the created object.
872 TestingProfile
* CreateMultiUserProfile(const std::string
& user_name
) {
873 std::string email_string
= user_name
+ "@example.com";
875 // Add a user to the fake user manager.
876 GetFakeUserManager()->AddUser(email_string
);
878 GetFakeUserManager()->UserLoggedIn(
880 email_string
+ kUserIdHashSuffix
,
883 std::string profile_name
=
884 chrome::kProfileDirPrefix
+ email_string
+ kUserIdHashSuffix
;
885 TestingProfile
* profile
= profile_manager()->CreateTestingProfile(
887 scoped_ptr
<PrefServiceSyncable
>(),
888 ASCIIToUTF16(email_string
), 0, std::string(),
889 TestingProfile::TestingFactories());
890 profile
->set_profile_name(email_string
);
891 EXPECT_TRUE(profile
);
892 // Remember the profile name so that we can destroy it upon destruction.
893 created_profiles_
[profile
] = profile_name
;
897 // Switch to another user.
898 void SwitchActiveUser(const std::string
& name
) {
899 session_delegate()->SwitchActiveUser(name
);
900 GetFakeUserManager()->SwitchActiveUser(name
);
901 launcher_controller_
->browser_status_monitor_for_test()->
902 ActiveUserChanged(name
);
903 launcher_controller_
->shell_window_controller_for_test()->
904 ActiveUserChanged(name
);
907 // Creates a browser with a |profile| and load a tab with a |title| and |url|.
908 Browser
* CreateBrowserAndTabWithProfile(Profile
* profile
,
909 const std::string
& title
,
910 const std::string
& url
) {
911 Browser::CreateParams
params(profile
, chrome::HOST_DESKTOP_TYPE_ASH
);
912 Browser
* browser
= chrome::CreateBrowserWithTestWindowForParams(¶ms
);
913 chrome::NewTab(browser
);
915 BrowserList::SetLastActive(browser
);
916 NavigateAndCommitActiveTabWithTitle(
917 browser
, GURL(url
), ASCIIToUTF16(title
));
921 // Creates a running V1 application.
922 // Note that with the use of the app_tab_helper as done below, this is only
923 // usable with a single v1 application.
924 V1App
* CreateRunningV1App(Profile
* profile
,
925 const std::string
& app_name
,
926 const std::string
& url
) {
927 V1App
* v1_app
= new V1App(profile
, app_name
);
928 // Create a new app tab helper and assign it to the launcher so that this
929 // app gets properly detected.
930 // TODO(skuhne): Create a more intelligent app tab helper which is able to
931 // detect all running apps properly.
932 TestAppTabHelperImpl
* app_tab_helper
= new TestAppTabHelperImpl
;
933 app_tab_helper
->SetAppID(
934 v1_app
->browser()->tab_strip_model()->GetWebContentsAt(0),
936 SetAppTabHelper(app_tab_helper
);
938 NavigateAndCommitActiveTabWithTitle(
939 v1_app
->browser(), GURL(url
), ASCIIToUTF16(""));
943 ash::test::TestSessionStateDelegate
*
944 session_delegate() { return session_delegate_
; }
945 ash::test::TestShellDelegate
* shell_delegate() { return shell_delegate_
; }
947 // Override BrowserWithTestWindowTest:
948 virtual TestingProfile
* CreateProfile() OVERRIDE
{
949 return CreateMultiUserProfile("user1");
951 virtual void DestroyProfile(TestingProfile
* profile
) OVERRIDE
{
952 // Delete the profile through our profile manager.
953 ProfileToNameMap::iterator it
= created_profiles_
.find(profile
);
954 DCHECK(it
!= created_profiles_
.end());
955 profile_manager_
->DeleteTestingProfile(it
->second
);
956 created_profiles_
.erase(it
);
959 virtual views::ViewsDelegate
* CreateViewsDelegate() OVERRIDE
{
960 return new TestViewsDelegateForAppTest
;
964 typedef std::map
<Profile
*, std::string
> ProfileToNameMap
;
965 TestingProfileManager
* profile_manager() { return profile_manager_
.get(); }
967 chromeos::FakeUserManager
* GetFakeUserManager() {
968 return static_cast<chromeos::FakeUserManager
*>(
969 chromeos::UserManager::Get());
972 scoped_ptr
<TestingProfileManager
> profile_manager_
;
973 scoped_ptr
<chromeos::ScopedUserManagerEnabler
> user_manager_enabler_
;
974 scoped_ptr
<base::FieldTrialList
> field_trial_list_
;
976 ash::test::TestSessionStateDelegate
* session_delegate_
;
977 ash::test::TestShellDelegate
* shell_delegate_
;
979 ProfileToNameMap created_profiles_
;
981 DISALLOW_COPY_AND_ASSIGN(
982 MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
);
984 #endif // defined(OS_CHROMEOS)
986 TEST_F(LegacyShelfLayoutChromeLauncherControllerTest
, DefaultApps
) {
987 InitLauncherController();
988 // Model should only contain the browser shortcut and app list items.
989 EXPECT_EQ(2, model_
->item_count());
990 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
991 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
992 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
994 // Installing |extension3_| should add it to the launcher - behind the
996 extension_service_
->AddExtension(extension3_
.get());
997 EXPECT_EQ("Chrome, App3, AppList", GetPinnedAppStatus());
998 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
999 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1002 // Check that the restauration of launcher items is happening in the same order
1003 // as the user has pinned them (on another system) when they are synced reverse
1005 TEST_F(LegacyShelfLayoutChromeLauncherControllerTest
,
1006 RestoreDefaultAppsReverseOrder
) {
1007 InitLauncherController();
1009 base::ListValue policy_value
;
1010 InsertPrefValue(&policy_value
, 0, extension1_
->id());
1011 InsertPrefValue(&policy_value
, 1, extension2_
->id());
1012 InsertPrefValue(&policy_value
, 2, extension3_
->id());
1013 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1014 policy_value
.DeepCopy());
1015 EXPECT_EQ(0, profile()->GetPrefs()->GetInteger(prefs::kShelfChromeIconIndex
));
1016 // Model should only contain the browser shortcut and app list items.
1017 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1018 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1019 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1020 EXPECT_EQ("Chrome, AppList", GetPinnedAppStatus());
1022 // Installing |extension3_| should add it to the launcher - behind the
1024 ash::LauncherItem item
;
1025 extension_service_
->AddExtension(extension3_
.get());
1026 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1027 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1028 EXPECT_EQ("Chrome, App3, AppList", GetPinnedAppStatus());
1030 // Installing |extension2_| should add it to the launcher - behind the
1031 // chrome icon, but in first location.
1032 extension_service_
->AddExtension(extension2_
.get());
1033 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1034 EXPECT_EQ("Chrome, App2, App3, AppList", GetPinnedAppStatus());
1036 // Installing |extension1_| should add it to the launcher - behind the
1037 // chrome icon, but in first location.
1038 extension_service_
->AddExtension(extension1_
.get());
1039 EXPECT_EQ("Chrome, App1, App2, App3, AppList", GetPinnedAppStatus());
1042 // Check that the restauration of launcher items is happening in the same order
1043 // as the user has pinned them (on another system) when they are synced random
1045 TEST_F(LegacyShelfLayoutChromeLauncherControllerTest
,
1046 RestoreDefaultAppsRandomOrder
) {
1047 InitLauncherController();
1049 base::ListValue policy_value
;
1050 InsertPrefValue(&policy_value
, 0, extension1_
->id());
1051 InsertPrefValue(&policy_value
, 1, extension2_
->id());
1052 InsertPrefValue(&policy_value
, 2, extension3_
->id());
1053 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1054 policy_value
.DeepCopy());
1055 EXPECT_EQ(0, profile()->GetPrefs()->GetInteger(prefs::kShelfChromeIconIndex
));
1056 // Model should only contain the browser shortcut and app list items.
1057 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1058 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1059 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1060 EXPECT_EQ("Chrome, AppList", GetPinnedAppStatus());
1062 // Installing |extension2_| should add it to the launcher - behind the
1064 extension_service_
->AddExtension(extension2_
.get());
1065 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1066 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1067 EXPECT_EQ("Chrome, App2, AppList", GetPinnedAppStatus());
1069 // Installing |extension1_| should add it to the launcher - behind the
1070 // chrome icon, but in first location.
1071 extension_service_
->AddExtension(extension1_
.get());
1072 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1073 EXPECT_EQ("Chrome, App1, App2, AppList", GetPinnedAppStatus());
1075 // Installing |extension3_| should add it to the launcher - behind the
1076 // chrome icon, but in first location.
1077 extension_service_
->AddExtension(extension3_
.get());
1078 EXPECT_EQ("Chrome, App1, App2, App3, AppList", GetPinnedAppStatus());
1081 // Check that the restauration of launcher items is happening in the same order
1082 // as the user has pinned / moved them (on another system) when they are synced
1083 // random order - including the chrome icon.
1084 TEST_F(LegacyShelfLayoutChromeLauncherControllerTest
,
1085 RestoreDefaultAppsRandomOrderChromeMoved
) {
1086 InitLauncherController();
1088 base::ListValue policy_value
;
1089 InsertPrefValue(&policy_value
, 0, extension1_
->id());
1090 InsertPrefValue(&policy_value
, 1, extension2_
->id());
1091 InsertPrefValue(&policy_value
, 2, extension3_
->id());
1092 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1093 policy_value
.DeepCopy());
1094 profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex
,
1096 // Model should only contain the browser shortcut and app list items.
1097 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1098 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1099 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1100 EXPECT_EQ("Chrome, AppList", GetPinnedAppStatus());
1102 // Installing |extension2_| should add it to the launcher - behind the
1104 ash::LauncherItem item
;
1105 extension_service_
->AddExtension(extension2_
.get());
1106 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1107 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1108 EXPECT_EQ("Chrome, App2, AppList", GetPinnedAppStatus());
1110 // Installing |extension1_| should add it to the launcher - behind the
1111 // chrome icon, but in first location.
1112 extension_service_
->AddExtension(extension1_
.get());
1113 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1114 EXPECT_EQ("App1, Chrome, App2, AppList", GetPinnedAppStatus());
1116 // Installing |extension3_| should add it to the launcher - behind the
1117 // chrome icon, but in first location.
1118 extension_service_
->AddExtension(extension3_
.get());
1119 EXPECT_EQ("App1, Chrome, App2, App3, AppList", GetPinnedAppStatus());
1122 // Check that syncing to a different state does the correct thing.
1123 TEST_F(LegacyShelfLayoutChromeLauncherControllerTest
,
1124 RestoreDefaultAppsResyncOrder
) {
1125 InitLauncherController();
1126 base::ListValue policy_value
;
1127 InsertPrefValue(&policy_value
, 0, extension1_
->id());
1128 InsertPrefValue(&policy_value
, 1, extension2_
->id());
1129 InsertPrefValue(&policy_value
, 2, extension3_
->id());
1130 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1131 policy_value
.DeepCopy());
1132 EXPECT_EQ(0, profile()->GetPrefs()->GetInteger(prefs::kShelfChromeIconIndex
));
1133 extension_service_
->AddExtension(extension2_
.get());
1134 extension_service_
->AddExtension(extension1_
.get());
1135 extension_service_
->AddExtension(extension3_
.get());
1136 EXPECT_EQ("Chrome, App1, App2, App3, AppList", GetPinnedAppStatus());
1138 // Change the order with increasing chrome position and decreasing position.
1139 base::ListValue policy_value1
;
1140 InsertPrefValue(&policy_value1
, 0, extension3_
->id());
1141 InsertPrefValue(&policy_value1
, 1, extension1_
->id());
1142 InsertPrefValue(&policy_value1
, 2, extension2_
->id());
1143 profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex
,
1145 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1146 policy_value1
.DeepCopy());
1147 EXPECT_EQ("App3, App1, Chrome, App2, AppList", GetPinnedAppStatus());
1148 base::ListValue policy_value2
;
1149 InsertPrefValue(&policy_value2
, 0, extension2_
->id());
1150 InsertPrefValue(&policy_value2
, 1, extension3_
->id());
1151 InsertPrefValue(&policy_value2
, 2, extension1_
->id());
1152 profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex
,
1154 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1155 policy_value2
.DeepCopy());
1156 EXPECT_EQ("App2, Chrome, App3, App1, AppList", GetPinnedAppStatus());
1159 TEST_F(ChromeLauncherControllerTest
, DefaultApps
) {
1160 InitLauncherController();
1161 // Model should only contain the browser shortcut and app list items.
1162 EXPECT_EQ(2, model_
->item_count());
1163 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1164 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1165 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1167 // Installing |extension3_| should add it to the launcher - behind the
1169 extension_service_
->AddExtension(extension3_
.get());
1170 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
1171 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1172 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1175 // Check that changing from the alternate shelf layout to the old shelflayout
1176 // and back does keep the app launcher at location #0.
1177 TEST_F(ChromeLauncherControllerTest
,
1178 SwitchingFromAlternateShelfLayoutToLegacyAndBack
) {
1179 InitLauncherController();
1181 // We simulate this problem by intentionally placing the app list item in
1182 // the middle of several apps which caused a crash (see crbug.com/329597).
1183 const char kAppLauncherIdPlaceholder
[] = "AppLauncherIDPlaceholder--------";
1185 base::ListValue policy_value
;
1186 InsertPrefValue(&policy_value
, 0, extension1_
->id());
1187 InsertPrefValue(&policy_value
, 1, kAppLauncherIdPlaceholder
);
1188 InsertPrefValue(&policy_value
, 2, extension2_
->id());
1189 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1190 policy_value
.DeepCopy());
1191 EXPECT_EQ(0, profile()->GetPrefs()->GetInteger(prefs::kShelfChromeIconIndex
));
1192 // Model should only contain the browser shortcut and app list items.
1193 extension_service_
->AddExtension(extension1_
.get());
1194 extension_service_
->AddExtension(extension2_
.get());
1195 EXPECT_EQ("AppList, Chrome, App1, App2", GetPinnedAppStatus());
1198 // Check that the restauration of launcher items is happening in the same order
1199 // as the user has pinned them (on another system) when they are synced reverse
1201 TEST_F(ChromeLauncherControllerTest
, RestoreDefaultAppsReverseOrder
) {
1202 InitLauncherController();
1204 base::ListValue policy_value
;
1205 InsertPrefValue(&policy_value
, 0, extension1_
->id());
1206 InsertPrefValue(&policy_value
, 1, extension2_
->id());
1207 InsertPrefValue(&policy_value
, 2, extension3_
->id());
1208 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1209 policy_value
.DeepCopy());
1210 SetShelfChromeIconIndex(0);
1211 // Model should only contain the browser shortcut and app list items.
1212 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1213 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1214 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1215 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
1217 // Installing |extension3_| should add it to the launcher - behind the
1219 ash::LauncherItem item
;
1220 extension_service_
->AddExtension(extension3_
.get());
1221 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1222 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1223 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
1225 // Installing |extension2_| should add it to the launcher - behind the
1226 // chrome icon, but in first location.
1227 extension_service_
->AddExtension(extension2_
.get());
1228 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1229 EXPECT_EQ("AppList, Chrome, App2, App3", GetPinnedAppStatus());
1231 // Installing |extension1_| should add it to the launcher - behind the
1232 // chrome icon, but in first location.
1233 extension_service_
->AddExtension(extension1_
.get());
1234 EXPECT_EQ("AppList, Chrome, App1, App2, App3", GetPinnedAppStatus());
1237 // Check that the restauration of launcher items is happening in the same order
1238 // as the user has pinned them (on another system) when they are synced random
1240 TEST_F(ChromeLauncherControllerTest
, RestoreDefaultAppsRandomOrder
) {
1241 InitLauncherController();
1243 base::ListValue policy_value
;
1244 InsertPrefValue(&policy_value
, 0, extension1_
->id());
1245 InsertPrefValue(&policy_value
, 1, extension2_
->id());
1246 InsertPrefValue(&policy_value
, 2, extension3_
->id());
1247 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1248 policy_value
.DeepCopy());
1249 SetShelfChromeIconIndex(0);
1250 // Model should only contain the browser shortcut and app list items.
1251 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1252 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1253 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1254 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
1256 // Installing |extension2_| should add it to the launcher - behind the
1258 extension_service_
->AddExtension(extension2_
.get());
1259 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1260 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1261 EXPECT_EQ("AppList, Chrome, App2", GetPinnedAppStatus());
1263 // Installing |extension1_| should add it to the launcher - behind the
1264 // chrome icon, but in first location.
1265 extension_service_
->AddExtension(extension1_
.get());
1266 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1267 EXPECT_EQ("AppList, Chrome, App1, App2", GetPinnedAppStatus());
1269 // Installing |extension3_| should add it to the launcher - behind the
1270 // chrome icon, but in first location.
1271 extension_service_
->AddExtension(extension3_
.get());
1272 EXPECT_EQ("AppList, Chrome, App1, App2, App3", GetPinnedAppStatus());
1275 // Check that the restauration of launcher items is happening in the same order
1276 // as the user has pinned / moved them (on another system) when they are synced
1277 // random order - including the chrome icon.
1278 TEST_F(ChromeLauncherControllerTest
, RestoreDefaultAppsRandomOrderChromeMoved
) {
1279 InitLauncherController();
1281 base::ListValue policy_value
;
1282 InsertPrefValue(&policy_value
, 0, extension1_
->id());
1283 InsertPrefValue(&policy_value
, 1, extension2_
->id());
1284 InsertPrefValue(&policy_value
, 2, extension3_
->id());
1285 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1286 policy_value
.DeepCopy());
1287 SetShelfChromeIconIndex(1);
1288 // Model should only contain the browser shortcut and app list items.
1289 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1290 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1291 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1292 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
1294 // Installing |extension2_| should add it to the launcher - behind the
1296 ash::LauncherItem item
;
1297 extension_service_
->AddExtension(extension2_
.get());
1298 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1299 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1300 EXPECT_EQ("AppList, Chrome, App2", GetPinnedAppStatus());
1302 // Installing |extension1_| should add it to the launcher - behind the
1303 // chrome icon, but in first location.
1304 extension_service_
->AddExtension(extension1_
.get());
1305 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
1306 EXPECT_EQ("AppList, App1, Chrome, App2", GetPinnedAppStatus());
1308 // Installing |extension3_| should add it to the launcher - behind the
1309 // chrome icon, but in first location.
1310 extension_service_
->AddExtension(extension3_
.get());
1311 EXPECT_EQ("AppList, App1, Chrome, App2, App3", GetPinnedAppStatus());
1314 // Check that syncing to a different state does the correct thing.
1315 TEST_F(ChromeLauncherControllerTest
, RestoreDefaultAppsResyncOrder
) {
1316 InitLauncherController();
1317 base::ListValue policy_value
;
1318 InsertPrefValue(&policy_value
, 0, extension1_
->id());
1319 InsertPrefValue(&policy_value
, 1, extension2_
->id());
1320 InsertPrefValue(&policy_value
, 2, extension3_
->id());
1321 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1322 policy_value
.DeepCopy());
1323 // The shelf layout has always one static item at the beginning (App List).
1324 SetShelfChromeIconIndex(0);
1325 extension_service_
->AddExtension(extension2_
.get());
1326 EXPECT_EQ("AppList, Chrome, App2", GetPinnedAppStatus());
1327 extension_service_
->AddExtension(extension1_
.get());
1328 EXPECT_EQ("AppList, Chrome, App1, App2", GetPinnedAppStatus());
1329 extension_service_
->AddExtension(extension3_
.get());
1330 EXPECT_EQ("AppList, Chrome, App1, App2, App3", GetPinnedAppStatus());
1332 // Change the order with increasing chrome position and decreasing position.
1333 base::ListValue policy_value1
;
1334 InsertPrefValue(&policy_value1
, 0, extension3_
->id());
1335 InsertPrefValue(&policy_value1
, 1, extension1_
->id());
1336 InsertPrefValue(&policy_value1
, 2, extension2_
->id());
1337 SetShelfChromeIconIndex(3);
1338 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1339 policy_value1
.DeepCopy());
1340 EXPECT_EQ("AppList, App3, App1, App2, Chrome", GetPinnedAppStatus());
1341 base::ListValue policy_value2
;
1342 InsertPrefValue(&policy_value2
, 0, extension2_
->id());
1343 InsertPrefValue(&policy_value2
, 1, extension3_
->id());
1344 InsertPrefValue(&policy_value2
, 2, extension1_
->id());
1345 SetShelfChromeIconIndex(2);
1346 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1347 policy_value2
.DeepCopy());
1348 EXPECT_EQ("AppList, App2, App3, Chrome, App1", GetPinnedAppStatus());
1350 // Check that the chrome icon can also be at the first possible location.
1351 SetShelfChromeIconIndex(0);
1352 base::ListValue policy_value3
;
1353 InsertPrefValue(&policy_value3
, 0, extension3_
->id());
1354 InsertPrefValue(&policy_value3
, 1, extension2_
->id());
1355 InsertPrefValue(&policy_value3
, 2, extension1_
->id());
1356 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1357 policy_value3
.DeepCopy());
1358 EXPECT_EQ("AppList, Chrome, App3, App2, App1", GetPinnedAppStatus());
1360 // Check that unloading of extensions works as expected.
1361 extension_service_
->UnloadExtension(extension1_
->id(),
1362 UnloadedExtensionInfo::REASON_UNINSTALL
);
1363 EXPECT_EQ("AppList, Chrome, App3, App2", GetPinnedAppStatus());
1365 extension_service_
->UnloadExtension(extension2_
->id(),
1366 UnloadedExtensionInfo::REASON_UNINSTALL
);
1367 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
1369 // Check that an update of an extension does not crash the system.
1370 extension_service_
->UnloadExtension(extension3_
->id(),
1371 UnloadedExtensionInfo::REASON_UPDATE
);
1372 EXPECT_EQ("AppList, Chrome, App3", GetPinnedAppStatus());
1375 // Check that simple locking of an application will 'create' a launcher item.
1376 TEST_F(ChromeLauncherControllerTest
, CheckLockApps
) {
1377 InitLauncherController();
1378 // Model should only contain the browser shortcut and app list items.
1379 EXPECT_EQ(2, model_
->item_count());
1380 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1382 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1383 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1385 launcher_controller_
->IsWindowedAppInLauncher(extension2_
->id()));
1387 launcher_controller_
->LockV1AppWithID(extension1_
->id());
1389 EXPECT_EQ(3, model_
->item_count());
1390 EXPECT_EQ(ash::TYPE_WINDOWED_APP
, model_
->items()[2].type
);
1391 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1392 EXPECT_TRUE(launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1393 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1395 launcher_controller_
->IsWindowedAppInLauncher(extension2_
->id()));
1397 launcher_controller_
->UnlockV1AppWithID(extension1_
->id());
1399 EXPECT_EQ(2, model_
->item_count());
1400 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1402 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1403 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1405 launcher_controller_
->IsWindowedAppInLauncher(extension2_
->id()));
1408 // Check that multiple locks of an application will be properly handled.
1409 TEST_F(ChromeLauncherControllerTest
, CheckMultiLockApps
) {
1410 InitLauncherController();
1411 // Model should only contain the browser shortcut and app list items.
1412 EXPECT_EQ(2, model_
->item_count());
1413 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1415 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1417 for (int i
= 0; i
< 2; i
++) {
1418 launcher_controller_
->LockV1AppWithID(extension1_
->id());
1420 EXPECT_EQ(3, model_
->item_count());
1421 EXPECT_EQ(ash::TYPE_WINDOWED_APP
, model_
->items()[2].type
);
1422 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1423 EXPECT_TRUE(launcher_controller_
->IsWindowedAppInLauncher(
1424 extension1_
->id()));
1427 launcher_controller_
->UnlockV1AppWithID(extension1_
->id());
1429 EXPECT_EQ(3, model_
->item_count());
1430 EXPECT_EQ(ash::TYPE_WINDOWED_APP
, model_
->items()[2].type
);
1431 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1432 EXPECT_TRUE(launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1434 launcher_controller_
->UnlockV1AppWithID(extension1_
->id());
1436 EXPECT_EQ(2, model_
->item_count());
1437 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1439 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1440 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
1442 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1445 // Check that already pinned items are not effected by locks.
1446 TEST_F(ChromeLauncherControllerTest
, CheckAlreadyPinnedLockApps
) {
1447 InitLauncherController();
1448 // Model should only contain the browser shortcut and app list items.
1449 EXPECT_EQ(2, model_
->item_count());
1450 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1452 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1454 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1455 launcher_controller_
->PinAppWithID(extension1_
->id());
1456 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1458 EXPECT_EQ(3, model_
->item_count());
1459 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
1460 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1462 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1464 launcher_controller_
->LockV1AppWithID(extension1_
->id());
1466 EXPECT_EQ(3, model_
->item_count());
1467 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
1468 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1470 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1472 launcher_controller_
->UnlockV1AppWithID(extension1_
->id());
1474 EXPECT_EQ(3, model_
->item_count());
1475 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
1476 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1478 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1480 launcher_controller_
->UnpinAppWithID(extension1_
->id());
1482 EXPECT_EQ(2, model_
->item_count());
1485 // Check that already pinned items which get locked stay after unpinning.
1486 TEST_F(ChromeLauncherControllerTest
, CheckPinnedAppsStayAfterUnlock
) {
1487 InitLauncherController();
1488 // Model should only contain the browser shortcut and app list items.
1489 EXPECT_EQ(2, model_
->item_count());
1490 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1492 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1494 launcher_controller_
->PinAppWithID(extension1_
->id());
1496 EXPECT_EQ(3, model_
->item_count());
1497 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
1498 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1500 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1502 launcher_controller_
->LockV1AppWithID(extension1_
->id());
1504 EXPECT_EQ(3, model_
->item_count());
1505 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
1506 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1508 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1510 launcher_controller_
->UnpinAppWithID(extension1_
->id());
1512 EXPECT_EQ(3, model_
->item_count());
1513 EXPECT_EQ(ash::TYPE_WINDOWED_APP
, model_
->items()[2].type
);
1514 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1515 EXPECT_TRUE(launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1517 launcher_controller_
->UnlockV1AppWithID(extension1_
->id());
1519 EXPECT_EQ(2, model_
->item_count());
1522 #if defined(OS_CHROMEOS)
1523 // Check that running applications wich are not pinned get properly restored
1524 // upon user change.
1525 TEST_F(ChromeLauncherControllerTest
, CheckRunningAppOrder
) {
1526 InitLauncherController();
1527 // Model should only contain the browser shortcut and app list items.
1528 EXPECT_EQ(2, model_
->item_count());
1530 // Add a few running applications.
1531 launcher_controller_
->LockV1AppWithID(extension1_
->id());
1532 launcher_controller_
->LockV1AppWithID(extension2_
->id());
1533 launcher_controller_
->LockV1AppWithID(extension3_
->id());
1534 EXPECT_EQ(5, model_
->item_count());
1535 // Note that this not only checks the order of applications but also the
1537 EXPECT_EQ("AppList, Chrome, app1, app2, app3", GetPinnedAppStatus());
1539 // Remember the current order of applications for the current user.
1540 const std::string
& current_user_id
=
1541 multi_user_util::GetUserIDFromProfile(profile());
1542 RememberUnpinnedRunningApplicationOrder();
1544 // Switch some items and check that restoring a user which was not yet
1545 // remembered changes nothing.
1547 EXPECT_EQ("AppList, Chrome, app2, app1, app3", GetPinnedAppStatus());
1548 RestoreUnpinnedRunningApplicationOrder("second-fake-user@fake.com");
1549 EXPECT_EQ("AppList, Chrome, app2, app1, app3", GetPinnedAppStatus());
1551 // Restoring the stored user should however do the right thing.
1552 RestoreUnpinnedRunningApplicationOrder(current_user_id
);
1553 EXPECT_EQ("AppList, Chrome, app1, app2, app3", GetPinnedAppStatus());
1555 // Switch again some items and even delete one - making sure that the missing
1556 // item gets properly handled.
1558 launcher_controller_
->UnlockV1AppWithID(extension1_
->id());
1559 EXPECT_EQ("AppList, Chrome, app3, app2", GetPinnedAppStatus());
1560 RestoreUnpinnedRunningApplicationOrder(current_user_id
);
1561 EXPECT_EQ("AppList, Chrome, app2, app3", GetPinnedAppStatus());
1563 // Check that removing more items does not crash and changes nothing.
1564 launcher_controller_
->UnlockV1AppWithID(extension2_
->id());
1565 RestoreUnpinnedRunningApplicationOrder(current_user_id
);
1566 EXPECT_EQ("AppList, Chrome, app3", GetPinnedAppStatus());
1567 launcher_controller_
->UnlockV1AppWithID(extension3_
->id());
1568 RestoreUnpinnedRunningApplicationOrder(current_user_id
);
1569 EXPECT_EQ("AppList, Chrome", GetPinnedAppStatus());
1572 // Check that with multi profile V1 apps are properly added / removed from the
1574 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
,
1575 V1AppUpdateOnUserSwitch
) {
1576 // Create a browser item in the LauncherController.
1577 InitLauncherController();
1578 EXPECT_EQ(2, model_
->item_count());
1580 // Create a "windowed gmail app".
1581 scoped_ptr
<V1App
> v1_app(CreateRunningV1App(
1582 profile(), extension_misc::kGmailAppId
, gmail_url
));
1583 EXPECT_EQ(3, model_
->item_count());
1585 // After switching to a second user the item should be gone.
1586 std::string user2
= "user2";
1587 TestingProfile
* profile2
= CreateMultiUserProfile(user2
);
1588 SwitchActiveUser(profile2
->GetProfileName());
1589 EXPECT_EQ(2, model_
->item_count());
1591 // After switching back the item should be back.
1592 SwitchActiveUser(profile()->GetProfileName());
1593 EXPECT_EQ(3, model_
->item_count());
1594 // Note we destroy now the gmail app with the closure end.
1596 EXPECT_EQ(2, model_
->item_count());
1599 // Check edge cases with multi profile V1 apps in the shelf.
1600 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
,
1601 V1AppUpdateOnUserSwitchEdgecases
) {
1602 // Create a browser item in the LauncherController.
1603 InitLauncherController();
1605 // First test: Create an app when the user is not active.
1606 std::string user2
= "user2";
1607 TestingProfile
* profile2
= CreateMultiUserProfile(user2
);
1609 // Create a "windowed gmail app".
1610 scoped_ptr
<V1App
> v1_app(CreateRunningV1App(
1611 profile2
, extension_misc::kGmailAppId
, gmail_url
));
1612 EXPECT_EQ(2, model_
->item_count());
1614 // However - switching to the user should show it.
1615 SwitchActiveUser(profile2
->GetProfileName());
1616 EXPECT_EQ(3, model_
->item_count());
1618 // Second test: Remove the app when the user is not active and see that it
1620 SwitchActiveUser(profile()->GetProfileName());
1621 EXPECT_EQ(2, model_
->item_count());
1622 // Note: the closure ends and the browser will go away.
1624 EXPECT_EQ(2, model_
->item_count());
1625 SwitchActiveUser(profile2
->GetProfileName());
1626 EXPECT_EQ(2, model_
->item_count());
1627 SwitchActiveUser(profile()->GetProfileName());
1628 EXPECT_EQ(2, model_
->item_count());
1631 // Check edge case where a visiting V1 app gets closed (crbug.com/321374).
1632 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
,
1633 V1CloseOnVisitingDesktop
) {
1634 // Create a browser item in the LauncherController.
1635 InitLauncherController();
1637 chrome::MultiUserWindowManager
* manager
=
1638 chrome::MultiUserWindowManager::GetInstance();
1640 // First create an app when the user is active.
1641 std::string user2
= "user2";
1642 TestingProfile
* profile2
= CreateMultiUserProfile(user2
);
1644 // Create a "windowed gmail app".
1645 scoped_ptr
<V1App
> v1_app(CreateRunningV1App(
1647 extension_misc::kGmailAppId
,
1649 EXPECT_EQ(3, model_
->item_count());
1651 // Transfer the app to the other screen and switch users.
1652 manager
->ShowWindowForUser(v1_app
->browser()->window()->GetNativeWindow(),
1654 EXPECT_EQ(3, model_
->item_count());
1655 SwitchActiveUser(profile2
->GetProfileName());
1656 EXPECT_EQ(2, model_
->item_count());
1658 // After the app was destroyed, switch back. (which caused already a crash).
1659 SwitchActiveUser(profile()->GetProfileName());
1661 // Create the same app again - which was also causing the crash.
1662 EXPECT_EQ(2, model_
->item_count());
1664 // Create a "windowed gmail app".
1665 scoped_ptr
<V1App
> v1_app(CreateRunningV1App(
1667 extension_misc::kGmailAppId
,
1669 EXPECT_EQ(3, model_
->item_count());
1671 SwitchActiveUser(profile2
->GetProfileName());
1672 EXPECT_EQ(2, model_
->item_count());
1675 // Check edge cases with multi profile V1 apps in the shelf.
1676 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
,
1677 V1AppUpdateOnUserSwitchEdgecases2
) {
1678 // Create a browser item in the LauncherController.
1679 InitLauncherController();
1680 TestAppTabHelperImpl
* app_tab_helper
= new TestAppTabHelperImpl
;
1681 SetAppTabHelper(app_tab_helper
);
1683 // First test: Create an app when the user is not active.
1684 std::string user2
= "user2";
1685 TestingProfile
* profile2
= CreateMultiUserProfile(user2
);
1686 SwitchActiveUser(profile2
->GetProfileName());
1688 // Create a "windowed gmail app".
1689 scoped_ptr
<V1App
> v1_app(CreateRunningV1App(
1690 profile(), extension_misc::kGmailAppId
, gmail_url
));
1691 EXPECT_EQ(2, model_
->item_count());
1693 // However - switching to the user should show it.
1694 SwitchActiveUser(profile()->GetProfileName());
1695 EXPECT_EQ(3, model_
->item_count());
1697 // Second test: Remove the app when the user is not active and see that it
1699 SwitchActiveUser(profile2
->GetProfileName());
1700 EXPECT_EQ(2, model_
->item_count());
1703 EXPECT_EQ(2, model_
->item_count());
1704 SwitchActiveUser(profile()->GetProfileName());
1705 EXPECT_EQ(2, model_
->item_count());
1706 SwitchActiveUser(profile2
->GetProfileName());
1707 EXPECT_EQ(2, model_
->item_count());
1710 // Check that activating an item which is on another user's desktop, will bring
1712 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
,
1713 TestLauncherActivationPullsBackWindow
) {
1714 // Create a browser item in the LauncherController.
1715 InitLauncherController();
1716 chrome::MultiUserWindowManager
* manager
=
1717 chrome::MultiUserWindowManager::GetInstance();
1719 // Add two users to the window manager.
1720 std::string user2
= "user2";
1721 TestingProfile
* profile2
= CreateMultiUserProfile(user2
);
1722 manager
->AddUser(profile());
1723 manager
->AddUser(profile2
);
1724 const std::string
& current_user
=
1725 multi_user_util::GetUserIDFromProfile(profile());
1727 // Create a browser window with a native window for the current user.
1728 scoped_ptr
<BrowserWindow
> browser_window(CreateTestBrowserWindow(
1729 Browser::CreateParams(profile(), chrome::HOST_DESKTOP_TYPE_ASH
)));
1730 aura::Window
* window
= browser_window
->GetNativeWindow();
1731 manager
->SetWindowOwner(window
, current_user
);
1733 // Check that an activation of the window on its owner's desktop does not
1734 // change the visibility to another user.
1735 launcher_controller_
->ActivateWindowOrMinimizeIfActive(browser_window
.get(),
1737 EXPECT_TRUE(manager
->IsWindowOnDesktopOfUser(window
, current_user
));
1739 // Transfer the window to another user's desktop and check that activating it
1740 // does pull it back to that user.
1741 manager
->ShowWindowForUser(window
, user2
);
1742 EXPECT_FALSE(manager
->IsWindowOnDesktopOfUser(window
, current_user
));
1743 launcher_controller_
->ActivateWindowOrMinimizeIfActive(browser_window
.get(),
1745 EXPECT_TRUE(manager
->IsWindowOnDesktopOfUser(window
, current_user
));
1749 // Check that lock -> pin -> unlock -> unpin does properly transition.
1750 TEST_F(ChromeLauncherControllerTest
, CheckLockPinUnlockUnpin
) {
1751 InitLauncherController();
1752 // Model should only contain the browser shortcut and app list items.
1753 EXPECT_EQ(2, model_
->item_count());
1754 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1756 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1758 launcher_controller_
->LockV1AppWithID(extension1_
->id());
1760 EXPECT_EQ(3, model_
->item_count());
1761 EXPECT_EQ(ash::TYPE_WINDOWED_APP
, model_
->items()[2].type
);
1762 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1763 EXPECT_TRUE(launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1765 launcher_controller_
->PinAppWithID(extension1_
->id());
1767 EXPECT_EQ(3, model_
->item_count());
1768 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
1769 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1771 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1773 launcher_controller_
->UnlockV1AppWithID(extension1_
->id());
1775 EXPECT_EQ(3, model_
->item_count());
1776 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
1777 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
1779 launcher_controller_
->IsWindowedAppInLauncher(extension1_
->id()));
1781 launcher_controller_
->UnpinAppWithID(extension1_
->id());
1783 EXPECT_EQ(2, model_
->item_count());
1786 // Check that a locked (windowed V1 application) will be properly converted
1787 // between locked and pinned when the order gets changed through a profile /
1789 TEST_F(ChromeLauncherControllerTest
, RestoreDefaultAndLockedAppsResyncOrder
) {
1790 InitLauncherController();
1791 base::ListValue policy_value0
;
1792 InsertPrefValue(&policy_value0
, 0, extension1_
->id());
1793 InsertPrefValue(&policy_value0
, 1, extension3_
->id());
1794 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1795 policy_value0
.DeepCopy());
1796 // The shelf layout has always one static item at the beginning (App List).
1797 SetShelfChromeIconIndex(0);
1798 extension_service_
->AddExtension(extension1_
.get());
1799 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1800 extension_service_
->AddExtension(extension2_
.get());
1801 // No new app icon will be generated.
1802 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1803 // Add the app as locked app which will add it (un-pinned).
1804 launcher_controller_
->LockV1AppWithID(extension2_
->id());
1805 EXPECT_EQ("AppList, Chrome, App1, app2", GetPinnedAppStatus());
1806 extension_service_
->AddExtension(extension3_
.get());
1807 EXPECT_EQ("AppList, Chrome, App1, App3, app2", GetPinnedAppStatus());
1809 // Now request to pin all items which should convert the locked item into a
1811 base::ListValue policy_value1
;
1812 InsertPrefValue(&policy_value1
, 0, extension3_
->id());
1813 InsertPrefValue(&policy_value1
, 1, extension2_
->id());
1814 InsertPrefValue(&policy_value1
, 2, extension1_
->id());
1815 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1816 policy_value1
.DeepCopy());
1817 EXPECT_EQ("AppList, Chrome, App3, App2, App1", GetPinnedAppStatus());
1819 // Going back to a status where there is no requirement for app 2 to be pinned
1820 // should convert it back to locked but not pinned and state. The position
1821 // is determined by the |ShelfModel|'s weight system and since running
1822 // applications are not allowed to be mixed with shortcuts, it should show up
1823 // at the end of the list.
1824 base::ListValue policy_value2
;
1825 InsertPrefValue(&policy_value2
, 0, extension3_
->id());
1826 InsertPrefValue(&policy_value2
, 1, extension1_
->id());
1827 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1828 policy_value2
.DeepCopy());
1829 EXPECT_EQ("AppList, Chrome, App3, App1, app2", GetPinnedAppStatus());
1831 // Removing an item should simply close it and everything should shift.
1832 base::ListValue policy_value3
;
1833 InsertPrefValue(&policy_value3
, 0, extension3_
->id());
1834 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1835 policy_value3
.DeepCopy());
1836 EXPECT_EQ("AppList, Chrome, App3, app2", GetPinnedAppStatus());
1839 // Check that a running and not pinned V2 application will be properly converted
1840 // between locked and pinned when the order gets changed through a profile /
1842 TEST_F(ChromeLauncherControllerTest
,
1843 RestoreDefaultAndRunningV2AppsResyncOrder
) {
1844 InitLauncherController();
1845 base::ListValue policy_value0
;
1846 InsertPrefValue(&policy_value0
, 0, extension1_
->id());
1847 InsertPrefValue(&policy_value0
, 1, extension3_
->id());
1848 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1849 policy_value0
.DeepCopy());
1850 // The shelf layout has always one static item at the beginning (app List).
1851 SetShelfChromeIconIndex(0);
1852 extension_service_
->AddExtension(extension1_
.get());
1853 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1854 extension_service_
->AddExtension(extension2_
.get());
1855 // No new app icon will be generated.
1856 EXPECT_EQ("AppList, Chrome, App1", GetPinnedAppStatus());
1857 // Add the app as an unpinned but running V2 app.
1858 CreateRunningV2App(extension2_
->id());
1859 EXPECT_EQ("AppList, Chrome, App1, *app2", GetPinnedAppStatus());
1860 extension_service_
->AddExtension(extension3_
.get());
1861 EXPECT_EQ("AppList, Chrome, App1, App3, *app2", GetPinnedAppStatus());
1863 // Now request to pin all items which should convert the locked item into a
1865 base::ListValue policy_value1
;
1866 InsertPrefValue(&policy_value1
, 0, extension3_
->id());
1867 InsertPrefValue(&policy_value1
, 1, extension2_
->id());
1868 InsertPrefValue(&policy_value1
, 2, extension1_
->id());
1869 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1870 policy_value1
.DeepCopy());
1871 EXPECT_EQ("AppList, Chrome, App3, App2, App1", GetPinnedAppStatus());
1873 // Going back to a status where there is no requirement for app 2 to be pinned
1874 // should convert it back to running V2 app. Since the position is determined
1875 // by the |ShelfModel|'s weight system, it will be after last pinned item.
1876 base::ListValue policy_value2
;
1877 InsertPrefValue(&policy_value2
, 0, extension3_
->id());
1878 InsertPrefValue(&policy_value2
, 1, extension1_
->id());
1879 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1880 policy_value2
.DeepCopy());
1881 EXPECT_EQ("AppList, Chrome, App3, App1, *app2", GetPinnedAppStatus());
1883 // Removing an item should simply close it and everything should shift.
1884 base::ListValue policy_value3
;
1885 InsertPrefValue(&policy_value3
, 0, extension3_
->id());
1886 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1887 policy_value3
.DeepCopy());
1888 EXPECT_EQ("AppList, Chrome, App3, *app2", GetPinnedAppStatus());
1891 // Each user has a different set of applications pinned. Check that when
1892 // switching between the two users, the state gets properly set.
1893 TEST_F(ChromeLauncherControllerTest
, UserSwitchIconRestore
) {
1894 base::ListValue user_a
;
1895 base::ListValue user_b
;
1896 SetUpMultiUserScenario(&user_a
, &user_b
);
1898 SetShelfChromeIconIndex(6);
1899 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1901 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1902 GetPinnedAppStatus());
1905 SetShelfChromeIconIndex(4);
1906 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1909 EXPECT_EQ("AppList, App7, App8, Chrome", GetPinnedAppStatus());
1911 // Switch back to 1.
1912 SetShelfChromeIconIndex(8);
1913 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1915 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1916 GetPinnedAppStatus());
1918 // Switch back to 2.
1919 SetShelfChromeIconIndex(4);
1920 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1922 EXPECT_EQ("AppList, App7, App8, Chrome", GetPinnedAppStatus());
1925 // Each user has a different set of applications pinned, and one user has an
1926 // application running. Check that when switching between the two users, the
1927 // state gets properly set.
1928 TEST_F(ChromeLauncherControllerTest
, UserSwitchIconRestoreWithRunningV2App
) {
1929 base::ListValue user_a
;
1930 base::ListValue user_b
;
1931 SetUpMultiUserScenario(&user_a
, &user_b
);
1933 // Run App1 and assume that it is a V2 app.
1934 CreateRunningV2App(extension1_
->id());
1937 SetShelfChromeIconIndex(6);
1938 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1940 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1941 GetPinnedAppStatus());
1944 SetShelfChromeIconIndex(4);
1945 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1948 EXPECT_EQ("AppList, App7, App8, Chrome, *app1", GetPinnedAppStatus());
1950 // Switch back to 1.
1951 SetShelfChromeIconIndex(8);
1952 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1954 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome",
1955 GetPinnedAppStatus());
1957 // Switch back to 2.
1958 SetShelfChromeIconIndex(4);
1959 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1961 EXPECT_EQ("AppList, App7, App8, Chrome, *app1", GetPinnedAppStatus());
1964 // Each user has a different set of applications pinned, and one user has an
1965 // application running. The chrome icon is not the last item in the list.
1966 // Check that when switching between the two users, the state gets properly set.
1967 // There was once a bug associated with this.
1968 TEST_F(ChromeLauncherControllerTest
,
1969 UserSwitchIconRestoreWithRunningV2AppChromeInMiddle
) {
1970 base::ListValue user_a
;
1971 base::ListValue user_b
;
1972 SetUpMultiUserScenario(&user_a
, &user_b
);
1974 // Run App1 and assume that it is a V2 app.
1975 CreateRunningV2App(extension1_
->id());
1978 SetShelfChromeIconIndex(5);
1979 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1981 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, Chrome, App6",
1982 GetPinnedAppStatus());
1985 SetShelfChromeIconIndex(4);
1986 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1989 EXPECT_EQ("AppList, App7, App8, Chrome, *app1", GetPinnedAppStatus());
1991 // Switch back to 1.
1992 SetShelfChromeIconIndex(5);
1993 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
1995 EXPECT_EQ("AppList, App1, App2, App3, App4, App5, Chrome, App6",
1996 GetPinnedAppStatus());
1999 TEST_F(ChromeLauncherControllerTest
, Policy
) {
2000 extension_service_
->AddExtension(extension1_
.get());
2001 extension_service_
->AddExtension(extension3_
.get());
2003 base::ListValue policy_value
;
2004 InsertPrefValue(&policy_value
, 0, extension1_
->id());
2005 InsertPrefValue(&policy_value
, 1, extension2_
->id());
2006 profile()->GetTestingPrefService()->SetManagedPref(prefs::kPinnedLauncherApps
,
2007 policy_value
.DeepCopy());
2009 // Only |extension1_| should get pinned. |extension2_| is specified but not
2010 // installed, and |extension3_| is part of the default set, but that shouldn't
2011 // take effect when the policy override is in place.
2012 InitLauncherController();
2013 EXPECT_EQ(3, model_
->item_count());
2014 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
2015 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
2016 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension2_
->id()));
2017 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2019 // Installing |extension2_| should add it to the launcher.
2020 extension_service_
->AddExtension(extension2_
.get());
2021 EXPECT_EQ(4, model_
->item_count());
2022 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
2023 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[3].type
);
2024 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension1_
->id()));
2025 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension2_
->id()));
2026 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2028 // Removing |extension1_| from the policy should be reflected in the launcher.
2029 policy_value
.Remove(0, NULL
);
2030 profile()->GetTestingPrefService()->SetManagedPref(prefs::kPinnedLauncherApps
,
2031 policy_value
.DeepCopy());
2032 EXPECT_EQ(3, model_
->item_count());
2033 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
2034 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension1_
->id()));
2035 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension2_
->id()));
2036 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2039 TEST_F(ChromeLauncherControllerTest
, UnpinWithUninstall
) {
2040 extension_service_
->AddExtension(extension3_
.get());
2041 extension_service_
->AddExtension(extension4_
.get());
2043 InitLauncherController();
2045 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2046 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension4_
->id()));
2048 extension_service_
->UnloadExtension(extension3_
->id(),
2049 UnloadedExtensionInfo::REASON_UNINSTALL
);
2051 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2052 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension4_
->id()));
2055 TEST_F(ChromeLauncherControllerTest
, PrefUpdates
) {
2056 extension_service_
->AddExtension(extension2_
.get());
2057 extension_service_
->AddExtension(extension3_
.get());
2058 extension_service_
->AddExtension(extension4_
.get());
2060 InitLauncherController();
2062 std::vector
<std::string
> expected_launchers
;
2063 std::vector
<std::string
> actual_launchers
;
2064 base::ListValue pref_value
;
2065 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
2066 pref_value
.DeepCopy());
2067 GetAppLaunchers(launcher_controller_
.get(), &actual_launchers
);
2068 EXPECT_EQ(expected_launchers
, actual_launchers
);
2070 // Unavailable extensions don't create launcher items.
2071 InsertPrefValue(&pref_value
, 0, extension1_
->id());
2072 InsertPrefValue(&pref_value
, 1, extension2_
->id());
2073 InsertPrefValue(&pref_value
, 2, extension4_
->id());
2074 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
2075 pref_value
.DeepCopy());
2076 expected_launchers
.push_back(extension2_
->id());
2077 expected_launchers
.push_back(extension4_
->id());
2078 GetAppLaunchers(launcher_controller_
.get(), &actual_launchers
);
2079 EXPECT_EQ(expected_launchers
, actual_launchers
);
2081 // Redundant pref entries show up only once.
2082 InsertPrefValue(&pref_value
, 2, extension3_
->id());
2083 InsertPrefValue(&pref_value
, 2, extension3_
->id());
2084 InsertPrefValue(&pref_value
, 5, extension3_
->id());
2085 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
2086 pref_value
.DeepCopy());
2087 expected_launchers
.insert(expected_launchers
.begin() + 1, extension3_
->id());
2088 GetAppLaunchers(launcher_controller_
.get(), &actual_launchers
);
2089 EXPECT_EQ(expected_launchers
, actual_launchers
);
2091 // Order changes are reflected correctly.
2093 InsertPrefValue(&pref_value
, 0, extension4_
->id());
2094 InsertPrefValue(&pref_value
, 1, extension3_
->id());
2095 InsertPrefValue(&pref_value
, 2, extension2_
->id());
2096 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
2097 pref_value
.DeepCopy());
2098 std::reverse(expected_launchers
.begin(), expected_launchers
.end());
2099 GetAppLaunchers(launcher_controller_
.get(), &actual_launchers
);
2100 EXPECT_EQ(expected_launchers
, actual_launchers
);
2104 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
2105 pref_value
.DeepCopy());
2106 expected_launchers
.clear();
2107 GetAppLaunchers(launcher_controller_
.get(), &actual_launchers
);
2108 EXPECT_EQ(expected_launchers
, actual_launchers
);
2111 TEST_F(ChromeLauncherControllerTest
, PendingInsertionOrder
) {
2112 extension_service_
->AddExtension(extension1_
.get());
2113 extension_service_
->AddExtension(extension3_
.get());
2115 InitLauncherController();
2117 base::ListValue pref_value
;
2118 InsertPrefValue(&pref_value
, 0, extension1_
->id());
2119 InsertPrefValue(&pref_value
, 1, extension2_
->id());
2120 InsertPrefValue(&pref_value
, 2, extension3_
->id());
2121 profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps
,
2122 pref_value
.DeepCopy());
2124 std::vector
<std::string
> expected_launchers
;
2125 expected_launchers
.push_back(extension1_
->id());
2126 expected_launchers
.push_back(extension3_
->id());
2127 std::vector
<std::string
> actual_launchers
;
2129 GetAppLaunchers(launcher_controller_
.get(), &actual_launchers
);
2130 EXPECT_EQ(expected_launchers
, actual_launchers
);
2132 // Install |extension2| and verify it shows up between the other two.
2133 extension_service_
->AddExtension(extension2_
.get());
2134 expected_launchers
.insert(expected_launchers
.begin() + 1, extension2_
->id());
2135 GetAppLaunchers(launcher_controller_
.get(), &actual_launchers
);
2136 EXPECT_EQ(expected_launchers
, actual_launchers
);
2139 // Checks the created menus and menu lists for correctness. It uses the given
2140 // |controller| to create the objects for the given |item| and checks the
2141 // found item count against the |expected_items|. The |title| list contains the
2142 // menu titles in the order of their appearance in the menu (not including the
2143 // application name).
2144 bool CheckMenuCreation(ChromeLauncherController
* controller
,
2145 const ash::LauncherItem
& item
,
2146 size_t expected_items
,
2147 base::string16 title
[],
2149 ChromeLauncherAppMenuItems items
= controller
->GetApplicationList(item
, 0);
2150 // A new behavior has been added: Only show menus if there is at least one
2152 if (expected_items
< 1 && is_browser
) {
2153 EXPECT_EQ(0u, items
.size());
2154 return items
.size() == 0;
2156 // There should be one item in there: The title.
2157 EXPECT_EQ(expected_items
+ 1, items
.size());
2158 EXPECT_FALSE(items
[0]->IsEnabled());
2159 for (size_t i
= 0; i
< expected_items
; i
++) {
2160 EXPECT_EQ(title
[i
], items
[1 + i
]->title());
2161 // Check that the first real item has a leading separator.
2163 EXPECT_TRUE(items
[i
]->HasLeadingSeparator());
2165 EXPECT_FALSE(items
[i
]->HasLeadingSeparator());
2168 scoped_ptr
<ash::ShelfMenuModel
> menu(new LauncherApplicationMenuItemModel(
2169 controller
->GetApplicationList(item
, 0)));
2170 // The first element in the menu is a spacing separator. On some systems
2171 // (e.g. Windows) such things do not exist. As such we check the existence
2172 // and adjust dynamically.
2173 int first_item
= menu
->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR
? 1 : 0;
2174 int expected_menu_items
= first_item
+
2175 (expected_items
? (expected_items
+ 3) : 2);
2176 EXPECT_EQ(expected_menu_items
, menu
->GetItemCount());
2177 EXPECT_FALSE(menu
->IsEnabledAt(first_item
));
2178 if (expected_items
) {
2179 EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR
,
2180 menu
->GetTypeAt(first_item
+ 1));
2182 return items
.size() == expected_items
+ 1;
2185 // Check that browsers get reflected correctly in the launcher menu.
2186 TEST_F(ChromeLauncherControllerTest
, BrowserMenuGeneration
) {
2187 EXPECT_EQ(1U, chrome::GetTotalBrowserCount());
2188 chrome::NewTab(browser());
2190 InitLauncherController();
2192 // Check that the browser list is empty at this time.
2193 ash::LauncherItem item_browser
;
2194 item_browser
.type
= ash::TYPE_BROWSER_SHORTCUT
;
2196 launcher_controller_
->GetLauncherIDForAppID(extension_misc::kChromeAppId
);
2197 EXPECT_TRUE(CheckMenuCreation(
2198 launcher_controller_
.get(), item_browser
, 0, NULL
, true));
2200 // Now make the created browser() visible by adding it to the active browser
2202 BrowserList::SetLastActive(browser());
2203 base::string16 title1
= ASCIIToUTF16("Test1");
2204 NavigateAndCommitActiveTabWithTitle(browser(), GURL("http://test1"), title1
);
2205 base::string16 one_menu_item
[] = { title1
};
2207 EXPECT_TRUE(CheckMenuCreation(
2208 launcher_controller_
.get(), item_browser
, 1, one_menu_item
, true));
2210 // Create one more browser/window and check that one more was added.
2211 Browser::CreateParams
ash_params(profile(), chrome::HOST_DESKTOP_TYPE_ASH
);
2212 scoped_ptr
<Browser
> browser2(
2213 chrome::CreateBrowserWithTestWindowForParams(&ash_params
));
2214 chrome::NewTab(browser2
.get());
2215 BrowserList::SetLastActive(browser2
.get());
2216 base::string16 title2
= ASCIIToUTF16("Test2");
2217 NavigateAndCommitActiveTabWithTitle(browser2
.get(), GURL("http://test2"),
2220 // Check that the list contains now two entries - make furthermore sure that
2221 // the active item is the first entry.
2222 base::string16 two_menu_items
[] = {title1
, title2
};
2223 EXPECT_TRUE(CheckMenuCreation(
2224 launcher_controller_
.get(), item_browser
, 2, two_menu_items
, true));
2226 // Apparently we have to close all tabs we have.
2227 chrome::CloseTab(browser2
.get());
2230 #if defined(OS_CHROMEOS)
2231 // Check the multi profile case where only user related browsers should show
2233 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
,
2234 BrowserMenuGenerationTwoUsers
) {
2235 // Create a browser item in the LauncherController.
2236 InitLauncherController();
2238 ash::LauncherItem item_browser
;
2239 item_browser
.type
= ash::TYPE_BROWSER_SHORTCUT
;
2241 launcher_controller_
->GetLauncherIDForAppID(extension_misc::kChromeAppId
);
2243 // Check that the menu is empty.
2244 chrome::NewTab(browser());
2245 EXPECT_TRUE(CheckMenuCreation(
2246 launcher_controller_
.get(), item_browser
, 0, NULL
, true));
2248 // Show the created |browser()| by adding it to the active browser list.
2249 BrowserList::SetLastActive(browser());
2250 base::string16 title1
= ASCIIToUTF16("Test1");
2251 NavigateAndCommitActiveTabWithTitle(browser(), GURL("http://test1"), title1
);
2252 base::string16 one_menu_item1
[] = { title1
};
2253 EXPECT_TRUE(CheckMenuCreation(
2254 launcher_controller_
.get(), item_browser
, 1, one_menu_item1
, true));
2256 // Create a browser for another user and check that it is not included in the
2257 // users running browser list.
2258 std::string user2
= "user2";
2259 TestingProfile
* profile2
= CreateMultiUserProfile(user2
);
2260 scoped_ptr
<Browser
> browser2(
2261 CreateBrowserAndTabWithProfile(profile2
, user2
, "http://test2"));
2262 base::string16 one_menu_item2
[] = { ASCIIToUTF16(user2
) };
2263 EXPECT_TRUE(CheckMenuCreation(
2264 launcher_controller_
.get(), item_browser
, 1, one_menu_item1
, true));
2266 // Switch to the other user and make sure that only that browser window gets
2268 SwitchActiveUser(profile2
->GetProfileName());
2269 EXPECT_TRUE(CheckMenuCreation(
2270 launcher_controller_
.get(), item_browser
, 1, one_menu_item2
, true));
2272 // Transferred browsers of other users should not show up in the list.
2273 chrome::MultiUserWindowManager::GetInstance()->ShowWindowForUser(
2274 browser()->window()->GetNativeWindow(),
2276 EXPECT_TRUE(CheckMenuCreation(
2277 launcher_controller_
.get(), item_browser
, 1, one_menu_item2
, true));
2279 chrome::CloseTab(browser2
.get());
2281 #endif // defined(OS_CHROMEOS)
2283 // Check that V1 apps are correctly reflected in the launcher menu using the
2285 // Note that the extension matching logic is tested by the extension system
2286 // and does not need a separate test here.
2287 TEST_F(ChromeLauncherControllerTest
, V1AppMenuGeneration
) {
2288 EXPECT_EQ(1U, chrome::GetTotalBrowserCount());
2289 EXPECT_EQ(0, browser()->tab_strip_model()->count());
2291 InitLauncherControllerWithBrowser();
2293 // Model should only contain the browser shortcut and app list items.
2294 EXPECT_EQ(2, model_
->item_count());
2295 EXPECT_FALSE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2297 // Installing |extension3_| adds it to the launcher.
2298 ash::LauncherID gmail_id
= model_
->next_id();
2299 extension_service_
->AddExtension(extension3_
.get());
2300 EXPECT_EQ(3, model_
->item_count());
2301 int gmail_index
= model_
->ItemIndexByID(gmail_id
);
2302 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[gmail_index
].type
);
2303 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2304 launcher_controller_
->SetRefocusURLPatternForTest(gmail_id
, GURL(gmail_url
));
2306 // Check the menu content.
2307 ash::LauncherItem item_browser
;
2308 item_browser
.type
= ash::TYPE_BROWSER_SHORTCUT
;
2310 launcher_controller_
->GetLauncherIDForAppID(extension_misc::kChromeAppId
);
2312 ash::LauncherItem item_gmail
;
2313 item_gmail
.type
= ash::TYPE_APP_SHORTCUT
;
2314 item_gmail
.id
= gmail_id
;
2315 EXPECT_TRUE(CheckMenuCreation(
2316 launcher_controller_
.get(), item_gmail
, 0, NULL
, false));
2318 // Set the gmail URL to a new tab.
2319 base::string16 title1
= ASCIIToUTF16("Test1");
2320 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url
), title1
);
2322 base::string16 one_menu_item
[] = { title1
};
2323 EXPECT_TRUE(CheckMenuCreation(
2324 launcher_controller_
.get(), item_gmail
, 1, one_menu_item
, false));
2326 // Create one empty tab.
2327 chrome::NewTab(browser());
2328 base::string16 title2
= ASCIIToUTF16("Test2");
2329 NavigateAndCommitActiveTabWithTitle(
2331 GURL("https://bla"),
2334 // and another one with another gmail instance.
2335 chrome::NewTab(browser());
2336 base::string16 title3
= ASCIIToUTF16("Test3");
2337 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url
), title3
);
2338 base::string16 two_menu_items
[] = {title1
, title3
};
2339 EXPECT_TRUE(CheckMenuCreation(
2340 launcher_controller_
.get(), item_gmail
, 2, two_menu_items
, false));
2342 // Even though the item is in the V1 app list, it should also be in the
2344 base::string16 browser_menu_item
[] = {title3
};
2345 EXPECT_TRUE(CheckMenuCreation(
2346 launcher_controller_
.get(), item_browser
, 1, browser_menu_item
, false));
2348 // Test that closing of (all) the item(s) does work (and all menus get
2349 // updated properly).
2350 launcher_controller_
->Close(item_gmail
.id
);
2352 EXPECT_TRUE(CheckMenuCreation(
2353 launcher_controller_
.get(), item_gmail
, 0, NULL
, false));
2354 base::string16 browser_menu_item2
[] = { title2
};
2355 EXPECT_TRUE(CheckMenuCreation(
2356 launcher_controller_
.get(), item_browser
, 1, browser_menu_item2
, false));
2359 #if defined(OS_CHROMEOS)
2360 // Check the multi profile case where only user related apps should show up.
2361 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
,
2362 V1AppMenuGenerationTwoUsers
) {
2363 // Create a browser item in the LauncherController.
2364 InitLauncherController();
2365 chrome::NewTab(browser());
2367 // Installing |extension3_| adds it to the launcher.
2368 ash::LauncherID gmail_id
= model_
->next_id();
2369 extension_service_
->AddExtension(extension3_
.get());
2370 EXPECT_EQ(3, model_
->item_count());
2371 int gmail_index
= model_
->ItemIndexByID(gmail_id
);
2372 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[gmail_index
].type
);
2373 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2374 launcher_controller_
->SetRefocusURLPatternForTest(gmail_id
, GURL(gmail_url
));
2376 // Check the menu content.
2377 ash::LauncherItem item_browser
;
2378 item_browser
.type
= ash::TYPE_BROWSER_SHORTCUT
;
2380 launcher_controller_
->GetLauncherIDForAppID(extension_misc::kChromeAppId
);
2382 ash::LauncherItem item_gmail
;
2383 item_gmail
.type
= ash::TYPE_APP_SHORTCUT
;
2384 item_gmail
.id
= gmail_id
;
2385 EXPECT_TRUE(CheckMenuCreation(
2386 launcher_controller_
.get(), item_gmail
, 0, NULL
, false));
2388 // Set the gmail URL to a new tab.
2389 base::string16 title1
= ASCIIToUTF16("Test1");
2390 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url
), title1
);
2392 base::string16 one_menu_item
[] = { title1
};
2393 EXPECT_TRUE(CheckMenuCreation(
2394 launcher_controller_
.get(), item_gmail
, 1, one_menu_item
, false));
2396 // Create a second profile and switch to that user.
2397 std::string user2
= "user2";
2398 TestingProfile
* profile2
= CreateMultiUserProfile(user2
);
2399 SwitchActiveUser(profile2
->GetProfileName());
2401 // No item should have content yet.
2402 EXPECT_TRUE(CheckMenuCreation(
2403 launcher_controller_
.get(), item_browser
, 0, NULL
, true));
2404 EXPECT_TRUE(CheckMenuCreation(
2405 launcher_controller_
.get(), item_gmail
, 0, NULL
, false));
2407 // Transfer the browser of the first user - it should still not show up.
2408 chrome::MultiUserWindowManager::GetInstance()->ShowWindowForUser(
2409 browser()->window()->GetNativeWindow(),
2412 EXPECT_TRUE(CheckMenuCreation(
2413 launcher_controller_
.get(), item_browser
, 0, NULL
, true));
2414 EXPECT_TRUE(CheckMenuCreation(
2415 launcher_controller_
.get(), item_gmail
, 0, NULL
, false));
2418 // Check that V2 applications are creating items properly in the launcher when
2419 // instantiated by the current user.
2420 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
,
2421 V2AppHandlingTwoUsers
) {
2422 InitLauncherController();
2423 // Create a profile for our second user (will be destroyed by the framework).
2424 TestingProfile
* profile2
= CreateMultiUserProfile("user2");
2425 // Check that there is a browser and a app launcher.
2426 EXPECT_EQ(2, model_
->item_count());
2429 V2App
v2_app(profile(), extension1_
);
2430 EXPECT_EQ(3, model_
->item_count());
2432 // After switching users the item should go away.
2433 SwitchActiveUser(profile2
->GetProfileName());
2434 EXPECT_EQ(2, model_
->item_count());
2436 // And it should come back when switching back.
2437 SwitchActiveUser(profile()->GetProfileName());
2438 EXPECT_EQ(3, model_
->item_count());
2441 // Check that V2 applications are creating items properly in edge cases:
2442 // a background user creates a V2 app, gets active and inactive again and then
2444 TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest
,
2445 V2AppHandlingTwoUsersEdgeCases
) {
2446 InitLauncherController();
2447 // Create a profile for our second user (will be destroyed by the framework).
2448 TestingProfile
* profile2
= CreateMultiUserProfile("user2");
2449 // Check that there is a browser and a app launcher.
2450 EXPECT_EQ(2, model_
->item_count());
2452 // Switch to an inactive user.
2453 SwitchActiveUser(profile2
->GetProfileName());
2454 EXPECT_EQ(2, model_
->item_count());
2456 // Add the v2 app to the inactive user and check that no item was added to
2459 V2App
v2_app(profile(), extension1_
);
2460 EXPECT_EQ(2, model_
->item_count());
2462 // Switch to the primary user and check that the item is shown.
2463 SwitchActiveUser(profile()->GetProfileName());
2464 EXPECT_EQ(3, model_
->item_count());
2466 // Switch to the second user and check that the item goes away - even if the
2467 // item gets closed.
2468 SwitchActiveUser(profile2
->GetProfileName());
2469 EXPECT_EQ(2, model_
->item_count());
2472 // After the application was killed there should be still 2 items.
2473 EXPECT_EQ(2, model_
->item_count());
2475 // Switching then back to the default user should not show the additional item
2477 SwitchActiveUser(profile()->GetProfileName());
2478 EXPECT_EQ(2, model_
->item_count());
2480 #endif // defined(OS_CHROMEOS)
2482 // Checks that the generated menu list properly activates items.
2483 TEST_F(ChromeLauncherControllerTest
, V1AppMenuExecution
) {
2484 InitLauncherControllerWithBrowser();
2486 // Add |extension3_| to the launcher and add two items.
2487 GURL gmail
= GURL("https://mail.google.com/mail/u");
2488 ash::LauncherID gmail_id
= model_
->next_id();
2489 extension_service_
->AddExtension(extension3_
.get());
2490 launcher_controller_
->SetRefocusURLPatternForTest(gmail_id
, GURL(gmail_url
));
2491 base::string16 title1
= ASCIIToUTF16("Test1");
2492 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url
), title1
);
2493 chrome::NewTab(browser());
2494 base::string16 title2
= ASCIIToUTF16("Test2");
2495 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url
), title2
);
2497 // Check that the menu is properly set.
2498 ash::LauncherItem item_gmail
;
2499 item_gmail
.type
= ash::TYPE_APP_SHORTCUT
;
2500 item_gmail
.id
= gmail_id
;
2501 base::string16 two_menu_items
[] = {title1
, title2
};
2502 EXPECT_TRUE(CheckMenuCreation(
2503 launcher_controller_
.get(), item_gmail
, 2, two_menu_items
, false));
2504 EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
2505 // Execute the second item in the list (which shouldn't do anything since that
2506 // item is per definition already the active tab).
2508 scoped_ptr
<ash::ShelfMenuModel
> menu(new LauncherApplicationMenuItemModel(
2509 launcher_controller_
->GetApplicationList(item_gmail
, 0)));
2510 // The first element in the menu is a spacing separator. On some systems
2511 // (e.g. Windows) such things do not exist. As such we check the existence
2512 // and adjust dynamically.
2514 (menu
->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR
) ? 1 : 0;
2515 menu
->ActivatedAt(first_item
+ 3);
2517 EXPECT_EQ(1, browser()->tab_strip_model()->active_index());
2519 // Execute the first item.
2521 scoped_ptr
<ash::ShelfMenuModel
> menu(new LauncherApplicationMenuItemModel(
2522 launcher_controller_
->GetApplicationList(item_gmail
, 0)));
2524 (menu
->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR
) ? 1 : 0;
2525 menu
->ActivatedAt(first_item
+ 2);
2527 // Now the active tab should be the second item.
2528 EXPECT_EQ(0, browser()->tab_strip_model()->active_index());
2531 // Checks that the generated menu list properly deletes items.
2532 TEST_F(ChromeLauncherControllerTest
, V1AppMenuDeletionExecution
) {
2533 InitLauncherControllerWithBrowser();
2535 // Add |extension3_| to the launcher and add two items.
2536 GURL gmail
= GURL("https://mail.google.com/mail/u");
2537 ash::LauncherID gmail_id
= model_
->next_id();
2538 extension_service_
->AddExtension(extension3_
.get());
2539 launcher_controller_
->SetRefocusURLPatternForTest(gmail_id
, GURL(gmail_url
));
2540 base::string16 title1
= ASCIIToUTF16("Test1");
2541 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url
), title1
);
2542 chrome::NewTab(browser());
2543 base::string16 title2
= ASCIIToUTF16("Test2");
2544 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url
), title2
);
2546 // Check that the menu is properly set.
2547 ash::LauncherItem item_gmail
;
2548 item_gmail
.type
= ash::TYPE_APP_SHORTCUT
;
2549 item_gmail
.id
= gmail_id
;
2550 base::string16 two_menu_items
[] = {title1
, title2
};
2551 EXPECT_TRUE(CheckMenuCreation(
2552 launcher_controller_
.get(), item_gmail
, 2, two_menu_items
, false));
2554 int tabs
= browser()->tab_strip_model()->count();
2555 // Activate the proper tab through the menu item.
2557 ChromeLauncherAppMenuItems items
=
2558 launcher_controller_
->GetApplicationList(item_gmail
, 0);
2559 items
[1]->Execute(0);
2560 EXPECT_EQ(tabs
, browser()->tab_strip_model()->count());
2563 // Delete one tab through the menu item.
2565 ChromeLauncherAppMenuItems items
=
2566 launcher_controller_
->GetApplicationList(item_gmail
, 0);
2567 items
[1]->Execute(ui::EF_SHIFT_DOWN
);
2568 EXPECT_EQ(--tabs
, browser()->tab_strip_model()->count());
2572 // Tests that panels create launcher items correctly
2573 TEST_F(ChromeLauncherControllerTest
, AppPanels
) {
2574 InitLauncherControllerWithBrowser();
2575 // App list and Browser shortcut LauncherItems are added.
2576 EXPECT_EQ(2, model_observer_
->added());
2578 TestAppIconLoaderImpl
* app_icon_loader
= new TestAppIconLoaderImpl();
2579 SetAppIconLoader(app_icon_loader
);
2581 // Test adding an app panel
2582 std::string app_id
= extension1_
->id();
2583 ShellWindowLauncherItemController
* app_panel_controller
=
2584 new ShellWindowLauncherItemController(
2585 LauncherItemController::TYPE_APP_PANEL
,
2588 launcher_controller_
.get());
2589 ash::LauncherID launcher_id1
= launcher_controller_
->CreateAppLauncherItem(
2590 app_panel_controller
, app_id
, ash::STATUS_RUNNING
);
2591 int panel_index
= model_observer_
->last_index();
2592 EXPECT_EQ(3, model_observer_
->added());
2593 EXPECT_EQ(0, model_observer_
->changed());
2594 EXPECT_EQ(1, app_icon_loader
->fetch_count());
2595 model_observer_
->clear_counts();
2597 // App panels should have a separate identifier than the app id
2598 EXPECT_EQ(0, launcher_controller_
->GetLauncherIDForAppID(app_id
));
2600 // Setting the app image image should not change the panel if it set its icon
2601 app_panel_controller
->set_image_set_by_controller(true);
2602 gfx::ImageSkia image
;
2603 launcher_controller_
->SetAppImage(app_id
, image
);
2604 EXPECT_EQ(0, model_observer_
->changed());
2605 model_observer_
->clear_counts();
2607 // Add a second app panel and verify that it get the same index as the first
2608 // one had, being added to the left of the existing panel.
2609 ShellWindowLauncherItemController
* app_panel_controller2
=
2610 new ShellWindowLauncherItemController(
2611 LauncherItemController::TYPE_APP_PANEL
,
2614 launcher_controller_
.get());
2616 ash::LauncherID launcher_id2
= launcher_controller_
->CreateAppLauncherItem(
2617 app_panel_controller2
, app_id
, ash::STATUS_RUNNING
);
2618 EXPECT_EQ(panel_index
, model_observer_
->last_index());
2619 EXPECT_EQ(1, model_observer_
->added());
2620 model_observer_
->clear_counts();
2622 launcher_controller_
->CloseLauncherItem(launcher_id2
);
2623 launcher_controller_
->CloseLauncherItem(launcher_id1
);
2624 EXPECT_EQ(2, model_observer_
->removed());
2627 // Tests that the Gmail extension matches more then the app itself claims with
2628 // the manifest file.
2629 TEST_F(ChromeLauncherControllerTest
, GmailMatching
) {
2630 InitLauncherControllerWithBrowser();
2632 // Create a Gmail browser tab.
2633 chrome::NewTab(browser());
2634 base::string16 title
= ASCIIToUTF16("Test");
2635 NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url
), title
);
2636 content::WebContents
* content
=
2637 browser()->tab_strip_model()->GetActiveWebContents();
2639 // Check that the launcher controller does not recognize the running app.
2640 EXPECT_FALSE(launcher_controller_
->ContentCanBeHandledByGmailApp(content
));
2642 // Installing |extension3_| adds it to the launcher.
2643 ash::LauncherID gmail_id
= model_
->next_id();
2644 extension_service_
->AddExtension(extension3_
.get());
2645 EXPECT_EQ(3, model_
->item_count());
2646 int gmail_index
= model_
->ItemIndexByID(gmail_id
);
2647 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[gmail_index
].type
);
2648 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2650 // Check that it is now handled.
2651 EXPECT_TRUE(launcher_controller_
->ContentCanBeHandledByGmailApp(content
));
2653 // Check also that the app has detected that properly.
2654 ash::LauncherItem item_gmail
;
2655 item_gmail
.type
= ash::TYPE_APP_SHORTCUT
;
2656 item_gmail
.id
= gmail_id
;
2657 EXPECT_EQ(2U, launcher_controller_
->GetApplicationList(item_gmail
, 0).size());
2660 // Tests that the Gmail extension does not match the offline verison.
2661 TEST_F(ChromeLauncherControllerTest
, GmailOfflineMatching
) {
2662 InitLauncherControllerWithBrowser();
2664 // Create a Gmail browser tab.
2665 chrome::NewTab(browser());
2666 base::string16 title
= ASCIIToUTF16("Test");
2667 NavigateAndCommitActiveTabWithTitle(browser(),
2668 GURL(offline_gmail_url
),
2670 content::WebContents
* content
=
2671 browser()->tab_strip_model()->GetActiveWebContents();
2673 // Installing |extension3_| adds it to the launcher.
2674 ash::LauncherID gmail_id
= model_
->next_id();
2675 extension_service_
->AddExtension(extension3_
.get());
2676 EXPECT_EQ(3, model_
->item_count());
2677 int gmail_index
= model_
->ItemIndexByID(gmail_id
);
2678 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[gmail_index
].type
);
2679 EXPECT_TRUE(launcher_controller_
->IsAppPinned(extension3_
->id()));
2681 // The content should not be able to be handled by the app.
2682 EXPECT_FALSE(launcher_controller_
->ContentCanBeHandledByGmailApp(content
));
2685 // Verify that the launcher item positions are persisted and restored.
2686 TEST_F(ChromeLauncherControllerTest
, PersistLauncherItemPositions
) {
2687 InitLauncherController();
2689 TestAppTabHelperImpl
* app_tab_helper
= new TestAppTabHelperImpl
;
2690 SetAppTabHelper(app_tab_helper
);
2692 EXPECT_EQ(ash::TYPE_APP_LIST
, model_
->items()[0].type
);
2693 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT
, model_
->items()[1].type
);
2695 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2696 EXPECT_EQ(0, tab_strip_model
->count());
2697 chrome::NewTab(browser());
2698 chrome::NewTab(browser());
2699 EXPECT_EQ(2, tab_strip_model
->count());
2700 app_tab_helper
->SetAppID(tab_strip_model
->GetWebContentsAt(0), "1");
2701 app_tab_helper
->SetAppID(tab_strip_model
->GetWebContentsAt(1), "2");
2703 EXPECT_FALSE(launcher_controller_
->IsAppPinned("1"));
2704 launcher_controller_
->PinAppWithID("1");
2705 EXPECT_TRUE(launcher_controller_
->IsAppPinned("1"));
2706 launcher_controller_
->PinAppWithID("2");
2708 EXPECT_EQ(ash::TYPE_APP_LIST
, model_
->items()[0].type
);
2709 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT
, model_
->items()[1].type
);
2710 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
2711 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[3].type
);
2713 // Move browser shortcut item from index 1 to index 3.
2715 EXPECT_EQ(ash::TYPE_APP_LIST
, model_
->items()[0].type
);
2716 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[1].type
);
2717 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
2718 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT
, model_
->items()[3].type
);
2720 launcher_controller_
.reset();
2721 if (!ash::Shell::HasInstance()) {
2722 delete item_delegate_manager_
;
2724 // Clear already registered ShelfItemDelegate.
2725 ash::test::ShelfItemDelegateManagerTestAPI
test(item_delegate_manager_
);
2726 test
.RemoveAllShelfItemDelegateForTest();
2728 model_
.reset(new ash::ShelfModel
);
2730 AddAppListLauncherItem();
2731 launcher_controller_
.reset(
2732 ChromeLauncherController::CreateInstance(profile(), model_
.get()));
2733 app_tab_helper
= new TestAppTabHelperImpl
;
2734 app_tab_helper
->SetAppID(tab_strip_model
->GetWebContentsAt(0), "1");
2735 app_tab_helper
->SetAppID(tab_strip_model
->GetWebContentsAt(1), "2");
2736 SetAppTabHelper(app_tab_helper
);
2737 if (!ash::Shell::HasInstance()) {
2738 item_delegate_manager_
= new ash::ShelfItemDelegateManager(model_
.get());
2739 SetShelfItemDelegateManager(item_delegate_manager_
);
2741 launcher_controller_
->Init();
2743 // Check LauncherItems are restored after resetting ChromeLauncherController.
2744 EXPECT_EQ(ash::TYPE_APP_LIST
, model_
->items()[0].type
);
2745 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[1].type
);
2746 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[2].type
);
2747 EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT
, model_
->items()[3].type
);
2750 // Verifies pinned apps are persisted and restored.
2751 TEST_F(ChromeLauncherControllerTest
, PersistPinned
) {
2752 InitLauncherControllerWithBrowser();
2753 size_t initial_size
= model_
->items().size();
2755 TabStripModel
* tab_strip_model
= browser()->tab_strip_model();
2756 EXPECT_EQ(1, tab_strip_model
->count());
2758 TestAppTabHelperImpl
* app_tab_helper
= new TestAppTabHelperImpl
;
2759 app_tab_helper
->SetAppID(tab_strip_model
->GetWebContentsAt(0), "1");
2760 SetAppTabHelper(app_tab_helper
);
2762 TestAppIconLoaderImpl
* app_icon_loader
= new TestAppIconLoaderImpl
;
2763 SetAppIconLoader(app_icon_loader
);
2764 EXPECT_EQ(0, app_icon_loader
->fetch_count());
2766 launcher_controller_
->PinAppWithID("1");
2767 ash::LauncherID id
= launcher_controller_
->GetLauncherIDForAppID("1");
2768 int app_index
= model_
->ItemIndexByID(id
);
2769 EXPECT_EQ(1, app_icon_loader
->fetch_count());
2770 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[app_index
].type
);
2771 EXPECT_TRUE(launcher_controller_
->IsAppPinned("1"));
2772 EXPECT_FALSE(launcher_controller_
->IsAppPinned("0"));
2773 EXPECT_EQ(initial_size
+ 1, model_
->items().size());
2775 launcher_controller_
.reset();
2776 if (!ash::Shell::HasInstance()) {
2777 delete item_delegate_manager_
;
2779 // Clear already registered ShelfItemDelegate.
2780 ash::test::ShelfItemDelegateManagerTestAPI
test(item_delegate_manager_
);
2781 test
.RemoveAllShelfItemDelegateForTest();
2783 model_
.reset(new ash::ShelfModel
);
2785 AddAppListLauncherItem();
2786 launcher_controller_
.reset(
2787 ChromeLauncherController::CreateInstance(profile(), model_
.get()));
2788 app_tab_helper
= new TestAppTabHelperImpl
;
2789 app_tab_helper
->SetAppID(tab_strip_model
->GetWebContentsAt(0), "1");
2790 SetAppTabHelper(app_tab_helper
);
2791 app_icon_loader
= new TestAppIconLoaderImpl
;
2792 SetAppIconLoader(app_icon_loader
);
2793 if (!ash::Shell::HasInstance()) {
2794 item_delegate_manager_
= new ash::ShelfItemDelegateManager(model_
.get());
2795 SetShelfItemDelegateManager(item_delegate_manager_
);
2797 launcher_controller_
->Init();
2799 EXPECT_EQ(1, app_icon_loader
->fetch_count());
2800 ASSERT_EQ(initial_size
+ 1, model_
->items().size());
2801 EXPECT_TRUE(launcher_controller_
->IsAppPinned("1"));
2802 EXPECT_FALSE(launcher_controller_
->IsAppPinned("0"));
2803 EXPECT_EQ(ash::TYPE_APP_SHORTCUT
, model_
->items()[app_index
].type
);
2805 launcher_controller_
->UnpinAppWithID("1");
2806 ASSERT_EQ(initial_size
, model_
->items().size());