| // Copyright 2013 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "chrome/browser/ui/ash/launcher/chrome_launcher_controller.h" |
| |
| #include <algorithm> |
| #include <string> |
| #include <vector> |
| |
| #include "ash/ash_switches.h" |
| #include "ash/shelf/shelf_item_delegate_manager.h" |
| #include "ash/shelf/shelf_model.h" |
| #include "ash/shelf/shelf_model_observer.h" |
| #include "ash/shell.h" |
| #include "ash/test/shelf_item_delegate_manager_test_api.h" |
| #include "base/command_line.h" |
| #include "base/compiler_specific.h" |
| #include "base/files/file_path.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/values.h" |
| #include "chrome/browser/extensions/extension_service.h" |
| #include "chrome/browser/extensions/test_extension_system.h" |
| #include "chrome/browser/ui/ash/chrome_launcher_prefs.h" |
| #include "chrome/browser/ui/ash/launcher/launcher_application_menu_item_model.h" |
| #include "chrome/browser/ui/ash/launcher/launcher_item_controller.h" |
| #include "chrome/browser/ui/ash/launcher/shell_window_launcher_item_controller.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_commands.h" |
| #include "chrome/browser/ui/browser_finder.h" |
| #include "chrome/browser/ui/browser_list.h" |
| #include "chrome/browser/ui/browser_tabstrip.h" |
| #include "chrome/browser/ui/host_desktop.h" |
| #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| #include "chrome/common/extensions/extension_constants.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/test/base/browser_with_test_window_test.h" |
| #include "chrome/test/base/testing_pref_service_syncable.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/test/test_browser_thread.h" |
| #include "extensions/common/extension.h" |
| #include "extensions/common/manifest_constants.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "ui/base/models/menu_model.h" |
| |
| #if defined(OS_CHROMEOS) |
| #include "apps/app_window_contents.h" |
| #include "apps/shell_window_registry.h" |
| #include "apps/ui/native_app_window.h" |
| #include "ash/test/test_session_state_delegate.h" |
| #include "ash/test/test_shell_delegate.h" |
| #include "base/metrics/field_trial.h" |
| #include "chrome/browser/chromeos/login/fake_user_manager.h" |
| #include "chrome/browser/ui/apps/chrome_shell_window_delegate.h" |
| #include "chrome/browser/ui/ash/launcher/browser_status_monitor.h" |
| #include "chrome/browser/ui/ash/launcher/shell_window_launcher_controller.h" |
| #include "chrome/browser/ui/ash/multi_user/multi_user_util.h" |
| #include "chrome/browser/ui/ash/multi_user/multi_user_window_manager.h" |
| #include "chrome/common/chrome_constants.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/test/base/testing_browser_process.h" |
| #include "chrome/test/base/testing_profile_manager.h" |
| #include "components/variations/entropy_provider.h" |
| #include "content/public/browser/web_contents_observer.h" |
| #include "content/public/test/test_utils.h" |
| #include "ui/aura/window.h" |
| #include "ui/views/test/test_views_delegate.h" |
| #endif |
| |
| using extensions::Extension; |
| using extensions::Manifest; |
| using extensions::UnloadedExtensionInfo; |
| |
| namespace { |
| const char* offline_gmail_url = "https://mail.google.com/mail/mu/u"; |
| const char* gmail_url = "https://mail.google.com/mail/u"; |
| const char* kGmailLaunchURL = "https://mail.google.com/mail/ca"; |
| |
| // As defined in /chromeos/dbus/cryptohome_client.cc. |
| const char kUserIdHashSuffix[] = "-hash"; |
| |
| // An extension prefix. |
| const char kCrxAppPrefix[] = "_crx_"; |
| |
| // ShelfModelObserver implementation that tracks what messages are invoked. |
| class TestShelfModelObserver : public ash::ShelfModelObserver { |
| public: |
| TestShelfModelObserver() |
| : added_(0), |
| removed_(0), |
| changed_(0) { |
| } |
| |
| virtual ~TestShelfModelObserver() { |
| } |
| |
| // Overridden from ash::ShelfModelObserver: |
| virtual void ShelfItemAdded(int index) OVERRIDE { |
| ++added_; |
| last_index_ = index; |
| } |
| |
| virtual void ShelfItemRemoved(int index, ash::LauncherID id) OVERRIDE { |
| ++removed_; |
| last_index_ = index; |
| } |
| |
| virtual void ShelfItemChanged(int index, |
| const ash::LauncherItem& old_item) OVERRIDE { |
| ++changed_; |
| last_index_ = index; |
| } |
| |
| virtual void ShelfItemMoved(int start_index, int target_index) OVERRIDE { |
| last_index_ = target_index; |
| } |
| |
| virtual void ShelfStatusChanged() OVERRIDE { |
| } |
| |
| void clear_counts() { |
| added_ = 0; |
| removed_ = 0; |
| changed_ = 0; |
| last_index_ = 0; |
| } |
| |
| int added() const { return added_; } |
| int removed() const { return removed_; } |
| int changed() const { return changed_; } |
| int last_index() const { return last_index_; } |
| |
| private: |
| int added_; |
| int removed_; |
| int changed_; |
| int last_index_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestShelfModelObserver); |
| }; |
| |
| // Test implementation of AppIconLoader. |
| class TestAppIconLoaderImpl : public extensions::AppIconLoader { |
| public: |
| TestAppIconLoaderImpl() : fetch_count_(0) { |
| } |
| |
| virtual ~TestAppIconLoaderImpl() { |
| } |
| |
| // AppIconLoader implementation: |
| virtual void FetchImage(const std::string& id) OVERRIDE { |
| ++fetch_count_; |
| } |
| |
| virtual void ClearImage(const std::string& id) OVERRIDE { |
| } |
| |
| virtual void UpdateImage(const std::string& id) OVERRIDE { |
| } |
| |
| int fetch_count() const { return fetch_count_; } |
| |
| private: |
| int fetch_count_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestAppIconLoaderImpl); |
| }; |
| |
| // Test implementation of AppTabHelper. |
| class TestAppTabHelperImpl : public ChromeLauncherController::AppTabHelper { |
| public: |
| TestAppTabHelperImpl() {} |
| virtual ~TestAppTabHelperImpl() {} |
| |
| // Sets the id for the specified tab. The id is removed if Remove() is |
| // invoked. |
| void SetAppID(content::WebContents* tab, const std::string& id) { |
| tab_id_map_[tab] = id; |
| } |
| |
| // Returns true if there is an id registered for |tab|. |
| bool HasAppID(content::WebContents* tab) const { |
| return tab_id_map_.find(tab) != tab_id_map_.end(); |
| } |
| |
| // AppTabHelper implementation: |
| virtual std::string GetAppID(content::WebContents* tab) OVERRIDE { |
| return tab_id_map_.find(tab) != tab_id_map_.end() ? tab_id_map_[tab] : |
| std::string(); |
| } |
| |
| virtual bool IsValidIDForCurrentUser(const std::string& id) OVERRIDE { |
| for (TabToStringMap::const_iterator i = tab_id_map_.begin(); |
| i != tab_id_map_.end(); ++i) { |
| if (i->second == id) |
| return true; |
| } |
| return false; |
| } |
| |
| virtual void SetCurrentUser(Profile* profile) OVERRIDE { |
| // We can ignore this for now. |
| } |
| |
| private: |
| typedef std::map<content::WebContents*, std::string> TabToStringMap; |
| |
| TabToStringMap tab_id_map_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestAppTabHelperImpl); |
| }; |
| |
| // Test implementation of a V2 app launcher item controller. |
| class TestV2AppLauncherItemController : public LauncherItemController { |
| public: |
| TestV2AppLauncherItemController(const std::string& app_id, |
| ChromeLauncherController* controller) |
| : LauncherItemController(LauncherItemController::TYPE_APP, |
| app_id, |
| controller) { |
| } |
| |
| virtual ~TestV2AppLauncherItemController() {} |
| |
| // Override for LauncherItemController: |
| virtual bool IsOpen() const OVERRIDE { return true; } |
| virtual bool IsVisible() const OVERRIDE { return true; } |
| virtual void Launch(ash::LaunchSource source, int event_flags) OVERRIDE {} |
| virtual bool Activate(ash::LaunchSource source) OVERRIDE { return false; } |
| virtual void Close() OVERRIDE {} |
| virtual bool ItemSelected(const ui::Event& event) OVERRIDE { return false; } |
| virtual base::string16 GetTitle() OVERRIDE { return base::string16(); } |
| virtual ChromeLauncherAppMenuItems GetApplicationList( |
| int event_flags) OVERRIDE { |
| ChromeLauncherAppMenuItems items; |
| items.push_back( |
| new ChromeLauncherAppMenuItem(base::string16(), NULL, false)); |
| items.push_back( |
| new ChromeLauncherAppMenuItem(base::string16(), NULL, false)); |
| return items.Pass(); |
| } |
| virtual ui::MenuModel* CreateContextMenu(aura::Window* root_window) OVERRIDE { |
| return NULL; |
| } |
| virtual ash::ShelfMenuModel* CreateApplicationMenu(int event_flags) OVERRIDE { |
| return NULL; |
| } |
| virtual bool IsDraggable() OVERRIDE { return false; } |
| virtual bool ShouldShowTooltip() OVERRIDE { return false; } |
| |
| private: |
| |
| DISALLOW_COPY_AND_ASSIGN(TestV2AppLauncherItemController); |
| }; |
| |
| } // namespace |
| |
| class ChromeLauncherControllerTest : public BrowserWithTestWindowTest { |
| protected: |
| ChromeLauncherControllerTest() : test_controller_(NULL), |
| extension_service_(NULL) { |
| SetHostDesktopType(chrome::HOST_DESKTOP_TYPE_ASH); |
| } |
| |
| virtual ~ChromeLauncherControllerTest() { |
| } |
| |
| virtual void SetUp() OVERRIDE { |
| BrowserWithTestWindowTest::SetUp(); |
| |
| model_.reset(new ash::ShelfModel); |
| model_observer_.reset(new TestShelfModelObserver); |
| model_->AddObserver(model_observer_.get()); |
| |
| if (ash::Shell::HasInstance()) { |
| item_delegate_manager_ = |
| ash::Shell::GetInstance()->shelf_item_delegate_manager(); |
| } else { |
| item_delegate_manager_ = |
| new ash::ShelfItemDelegateManager(model_.get()); |
| } |
| |
| DictionaryValue manifest; |
| manifest.SetString(extensions::manifest_keys::kName, |
| "launcher controller test extension"); |
| manifest.SetString(extensions::manifest_keys::kVersion, "1"); |
| manifest.SetString(extensions::manifest_keys::kDescription, |
| "for testing pinned apps"); |
| |
| extensions::TestExtensionSystem* extension_system( |
| static_cast<extensions::TestExtensionSystem*>( |
| extensions::ExtensionSystem::Get(profile()))); |
| extension_service_ = extension_system->CreateExtensionService( |
| CommandLine::ForCurrentProcess(), base::FilePath(), false); |
| |
| std::string error; |
| extension1_ = Extension::Create(base::FilePath(), Manifest::UNPACKED, |
| manifest, |
| Extension::NO_FLAGS, |
| "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", |
| &error); |
| extension2_ = Extension::Create(base::FilePath(), Manifest::UNPACKED, |
| manifest, |
| Extension::NO_FLAGS, |
| "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", |
| &error); |
| // Fake gmail extension. |
| DictionaryValue manifest_gmail; |
| manifest_gmail.SetString(extensions::manifest_keys::kName, |
| "Gmail launcher controller test extension"); |
| manifest_gmail.SetString(extensions::manifest_keys::kVersion, "1"); |
| manifest_gmail.SetString(extensions::manifest_keys::kDescription, |
| "for testing pinned Gmail"); |
| manifest_gmail.SetString(extensions::manifest_keys::kLaunchWebURL, |
| kGmailLaunchURL); |
| ListValue* list = new ListValue(); |
| list->Append(Value::CreateStringValue("*://mail.google.com/mail/ca")); |
| manifest_gmail.Set(extensions::manifest_keys::kWebURLs, list); |
| |
| extension3_ = Extension::Create(base::FilePath(), Manifest::UNPACKED, |
| manifest_gmail, |
| Extension::NO_FLAGS, |
| extension_misc::kGmailAppId, |
| &error); |
| |
| // Fake search extension. |
| extension4_ = Extension::Create(base::FilePath(), Manifest::UNPACKED, |
| manifest, |
| Extension::NO_FLAGS, |
| extension_misc::kGoogleSearchAppId, |
| &error); |
| extension5_ = Extension::Create(base::FilePath(), Manifest::UNPACKED, |
| manifest, |
| Extension::NO_FLAGS, |
| "cccccccccccccccccccccccccccccccc", |
| &error); |
| extension6_ = Extension::Create(base::FilePath(), Manifest::UNPACKED, |
| manifest, |
| Extension::NO_FLAGS, |
| "dddddddddddddddddddddddddddddddd", |
| &error); |
| extension7_ = Extension::Create(base::FilePath(), Manifest::UNPACKED, |
| manifest, |
| Extension::NO_FLAGS, |
| "eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee", |
| &error); |
| extension8_ = Extension::Create(base::FilePath(), Manifest::UNPACKED, |
| manifest, |
| Extension::NO_FLAGS, |
| "ffffffffffffffffffffffffffffffff", |
| &error); |
| } |
| |
| // Creates a running V2 app (not pinned) of type |app_id|. |
| virtual void CreateRunningV2App(const std::string& app_id) { |
| DCHECK(!test_controller_); |
| ash::LauncherID id = |
| launcher_controller_->CreateAppShortcutLauncherItemWithType( |
| app_id, |
| model_->item_count(), |
| ash::TYPE_PLATFORM_APP); |
| DCHECK(id); |
| // Change the created launcher controller into a V2 app controller. |
| test_controller_ = new TestV2AppLauncherItemController(app_id, |
| launcher_controller_.get()); |
| launcher_controller_->SetItemController(id, test_controller_); |
| } |
| |
| // Sets the stage for a multi user test. |
| virtual void SetUpMultiUserScenario(base::ListValue* user_a, |
| base::ListValue* user_b) { |
| InitLauncherController(); |
| EXPECT_EQ("AppList, Chrome, ", GetPinnedAppStatus()); |
| |
| // Set an empty pinned pref to begin with. |
| base::ListValue no_user; |
| SetShelfChromeIconIndex(0); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| no_user.DeepCopy()); |
| EXPECT_EQ("AppList, Chrome, ", GetPinnedAppStatus()); |
| |
| // Assume all applications have been added already. |
| extension_service_->AddExtension(extension1_.get()); |
| extension_service_->AddExtension(extension2_.get()); |
| extension_service_->AddExtension(extension3_.get()); |
| extension_service_->AddExtension(extension4_.get()); |
| extension_service_->AddExtension(extension5_.get()); |
| extension_service_->AddExtension(extension6_.get()); |
| extension_service_->AddExtension(extension7_.get()); |
| extension_service_->AddExtension(extension8_.get()); |
| // There should be nothing in the list by now. |
| EXPECT_EQ("AppList, Chrome, ", GetPinnedAppStatus()); |
| |
| // Set user a preferences. |
| InsertPrefValue(user_a, 0, extension1_->id()); |
| InsertPrefValue(user_a, 1, extension2_->id()); |
| InsertPrefValue(user_a, 2, extension3_->id()); |
| InsertPrefValue(user_a, 3, extension4_->id()); |
| InsertPrefValue(user_a, 4, extension5_->id()); |
| InsertPrefValue(user_a, 5, extension6_->id()); |
| |
| // Set user b preferences. |
| InsertPrefValue(user_b, 0, extension7_->id()); |
| InsertPrefValue(user_b, 1, extension8_->id()); |
| } |
| |
| virtual void TearDown() OVERRIDE { |
| if (!ash::Shell::HasInstance()) |
| delete item_delegate_manager_; |
| model_->RemoveObserver(model_observer_.get()); |
| model_observer_.reset(); |
| launcher_controller_.reset(); |
| model_.reset(); |
| |
| BrowserWithTestWindowTest::TearDown(); |
| } |
| |
| void AddAppListLauncherItem() { |
| ash::LauncherItem app_list; |
| app_list.type = ash::TYPE_APP_LIST; |
| model_->Add(app_list); |
| } |
| |
| void InitLauncherController() { |
| AddAppListLauncherItem(); |
| launcher_controller_.reset( |
| new ChromeLauncherController(profile(), model_.get())); |
| if (!ash::Shell::HasInstance()) |
| SetShelfItemDelegateManager(item_delegate_manager_); |
| launcher_controller_->Init(); |
| } |
| |
| void InitLauncherControllerWithBrowser() { |
| chrome::NewTab(browser()); |
| BrowserList::SetLastActive(browser()); |
| InitLauncherController(); |
| } |
| |
| void SetAppIconLoader(extensions::AppIconLoader* loader) { |
| launcher_controller_->SetAppIconLoaderForTest(loader); |
| } |
| |
| void SetAppTabHelper(ChromeLauncherController::AppTabHelper* helper) { |
| launcher_controller_->SetAppTabHelperForTest(helper); |
| } |
| |
| void SetShelfItemDelegateManager(ash::ShelfItemDelegateManager* manager) { |
| launcher_controller_->SetShelfItemDelegateManagerForTest(manager); |
| } |
| |
| void InsertPrefValue(base::ListValue* pref_value, |
| int index, |
| const std::string& extension_id) { |
| base::DictionaryValue* entry = new DictionaryValue(); |
| entry->SetString(ash::kPinnedAppsPrefAppIDPath, extension_id); |
| pref_value->Insert(index, entry); |
| } |
| |
| // Gets the currently configured app launchers from the controller. |
| void GetAppLaunchers(ChromeLauncherController* controller, |
| std::vector<std::string>* launchers) { |
| launchers->clear(); |
| for (ash::LauncherItems::const_iterator iter(model_->items().begin()); |
| iter != model_->items().end(); ++iter) { |
| ChromeLauncherController::IDToItemControllerMap::const_iterator |
| entry(controller->id_to_item_controller_map_.find(iter->id)); |
| if (iter->type == ash::TYPE_APP_SHORTCUT && |
| entry != controller->id_to_item_controller_map_.end()) { |
| launchers->push_back(entry->second->app_id()); |
| } |
| } |
| } |
| |
| // Get the setup of the currently shown launcher items in one string. |
| // Each pinned element will start with a big letter, each running but not |
| // pinned V1 app will start with a small letter and each running but not |
| // pinned V2 app will start with a '*' + small letter. |
| std::string GetPinnedAppStatus() { |
| std::string result; |
| for (int i = 0; i < model_->item_count(); i++) { |
| switch (model_->items()[i].type) { |
| case ash::TYPE_PLATFORM_APP: |
| result+= "*"; |
| // FALLTHROUGH |
| case ash::TYPE_WINDOWED_APP: { |
| const std::string& app = |
| launcher_controller_->GetAppIDForLauncherID( |
| model_->items()[i].id); |
| if (app == extension1_->id()) { |
| result += "app1, "; |
| EXPECT_FALSE( |
| launcher_controller_->IsAppPinned(extension1_->id())); |
| } else if (app == extension2_->id()) { |
| result += "app2, "; |
| EXPECT_FALSE( |
| launcher_controller_->IsAppPinned(extension2_->id())); |
| } else if (app == extension3_->id()) { |
| result += "app3, "; |
| EXPECT_FALSE( |
| launcher_controller_->IsAppPinned(extension3_->id())); |
| } else if (app == extension4_->id()) { |
| result += "app4, "; |
| EXPECT_FALSE( |
| launcher_controller_->IsAppPinned(extension4_->id())); |
| } else if (app == extension5_->id()) { |
| result += "app5, "; |
| EXPECT_FALSE( |
| launcher_controller_->IsAppPinned(extension5_->id())); |
| } else if (app == extension6_->id()) { |
| result += "app6, "; |
| EXPECT_FALSE( |
| launcher_controller_->IsAppPinned(extension6_->id())); |
| } else if (app == extension7_->id()) { |
| result += "app7, "; |
| EXPECT_FALSE( |
| launcher_controller_->IsAppPinned(extension7_->id())); |
| } else if (app == extension8_->id()) { |
| result += "app8, "; |
| EXPECT_FALSE( |
| launcher_controller_->IsAppPinned(extension8_->id())); |
| } else { |
| result += "unknown, "; |
| } |
| break; |
| } |
| case ash::TYPE_APP_SHORTCUT: { |
| const std::string& app = |
| launcher_controller_->GetAppIDForLauncherID( |
| model_->items()[i].id); |
| if (app == extension1_->id()) { |
| result += "App1, "; |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id())); |
| } else if (app == extension2_->id()) { |
| result += "App2, "; |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension2_->id())); |
| } else if (app == extension3_->id()) { |
| result += "App3, "; |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id())); |
| } else if (app == extension4_->id()) { |
| result += "App4, "; |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension4_->id())); |
| } else if (app == extension5_->id()) { |
| result += "App5, "; |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension5_->id())); |
| } else if (app == extension6_->id()) { |
| result += "App6, "; |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension6_->id())); |
| } else if (app == extension7_->id()) { |
| result += "App7, "; |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension7_->id())); |
| } else if (app == extension8_->id()) { |
| result += "App8, "; |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension8_->id())); |
| } else { |
| result += "unknown, "; |
| } |
| break; |
| } |
| case ash::TYPE_BROWSER_SHORTCUT: |
| result += "Chrome, "; |
| break; |
| case ash::TYPE_APP_LIST: |
| result += "AppList, "; |
| break; |
| default: |
| result += "Unknown"; |
| break; |
| } |
| } |
| return result; |
| } |
| |
| // Set the index at which the chrome icon should be. |
| void SetShelfChromeIconIndex(int index) { |
| profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex, |
| index); |
| } |
| |
| // Needed for extension service & friends to work. |
| scoped_refptr<Extension> extension1_; |
| scoped_refptr<Extension> extension2_; |
| scoped_refptr<Extension> extension3_; |
| scoped_refptr<Extension> extension4_; |
| scoped_refptr<Extension> extension5_; |
| scoped_refptr<Extension> extension6_; |
| scoped_refptr<Extension> extension7_; |
| scoped_refptr<Extension> extension8_; |
| scoped_ptr<ChromeLauncherController> launcher_controller_; |
| scoped_ptr<TestShelfModelObserver> model_observer_; |
| scoped_ptr<ash::ShelfModel> model_; |
| |
| // |item_delegate_manager_| owns |test_controller_|. |
| LauncherItemController* test_controller_; |
| |
| ExtensionService* extension_service_; |
| |
| ash::ShelfItemDelegateManager* item_delegate_manager_; |
| |
| DISALLOW_COPY_AND_ASSIGN(ChromeLauncherControllerTest); |
| }; |
| |
| // The testing framework to test the legacy shelf layout. |
| class LegacyShelfLayoutChromeLauncherControllerTest |
| : public ChromeLauncherControllerTest { |
| protected: |
| LegacyShelfLayoutChromeLauncherControllerTest() { |
| } |
| |
| virtual ~LegacyShelfLayoutChromeLauncherControllerTest() { |
| } |
| |
| // Overwrite the Setup function to use the legacy shelf layout option. |
| virtual void SetUp() OVERRIDE { |
| CommandLine::ForCurrentProcess()->AppendSwitch( |
| ash::switches::kAshDisableAlternateShelfLayout); |
| ChromeLauncherControllerTest::SetUp(); |
| } |
| |
| private: |
| |
| DISALLOW_COPY_AND_ASSIGN(LegacyShelfLayoutChromeLauncherControllerTest); |
| }; |
| |
| #if defined(OS_CHROMEOS) |
| // A browser window proxy which is able to associate an aura native window with |
| // it. |
| class TestBrowserWindowAura : public TestBrowserWindow { |
| public: |
| // |native_window| will still be owned by the caller after the constructor |
| // was called. |
| explicit TestBrowserWindowAura(aura::Window* native_window) |
| : native_window_(native_window) { |
| } |
| virtual ~TestBrowserWindowAura() {} |
| |
| virtual gfx::NativeWindow GetNativeWindow() OVERRIDE { |
| return native_window_.get(); |
| } |
| |
| Browser* browser() { return browser_.get(); } |
| |
| void CreateBrowser(const Browser::CreateParams& params) { |
| Browser::CreateParams create_params = params; |
| create_params.window = this; |
| browser_.reset(new Browser(create_params)); |
| } |
| |
| private: |
| scoped_ptr<Browser> browser_; |
| scoped_ptr<aura::Window> native_window_; |
| |
| DISALLOW_COPY_AND_ASSIGN(TestBrowserWindowAura); |
| }; |
| |
| // Creates a test browser window which has a native window. |
| scoped_ptr<TestBrowserWindowAura> CreateTestBrowserWindow( |
| const Browser::CreateParams& params) { |
| // Create a window. |
| aura::Window* window = new aura::Window(NULL); |
| window->set_id(0); |
| window->SetType(aura::client::WINDOW_TYPE_NORMAL); |
| window->Init(ui::LAYER_TEXTURED); |
| window->Show(); |
| |
| scoped_ptr<TestBrowserWindowAura> browser_window( |
| new TestBrowserWindowAura(window)); |
| browser_window->CreateBrowser(params); |
| return browser_window.Pass(); |
| } |
| |
| // A views delegate which allows creating shell windows. |
| class TestViewsDelegateForAppTest : public views::TestViewsDelegate { |
| public: |
| TestViewsDelegateForAppTest() {} |
| virtual ~TestViewsDelegateForAppTest() {} |
| |
| // views::TestViewsDelegate overrides. |
| virtual void OnBeforeWidgetInit( |
| views::Widget::InitParams* params, |
| views::internal::NativeWidgetDelegate* delegate) OVERRIDE { |
| if (!params->parent && !params->context) { |
| // If the window has neither a parent nor a context we add the root window |
| // as parent. |
| params->parent = ash::Shell::GetInstance()->GetPrimaryRootWindow(); |
| } |
| } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(TestViewsDelegateForAppTest); |
| }; |
| |
| // Watches WebContents and blocks until it is destroyed. This is needed for |
| // the destruction of a V2 application. |
| class WebContentsDestroyedWatcher : public content::WebContentsObserver { |
| public: |
| explicit WebContentsDestroyedWatcher(content::WebContents* web_contents) |
| : content::WebContentsObserver(web_contents), |
| message_loop_runner_(new content::MessageLoopRunner) { |
| EXPECT_TRUE(web_contents != NULL); |
| } |
| virtual ~WebContentsDestroyedWatcher() {} |
| |
| // Waits until the WebContents is destroyed. |
| void Wait() { |
| message_loop_runner_->Run(); |
| } |
| |
| private: |
| // Overridden WebContentsObserver methods. |
| virtual void WebContentsDestroyed( |
| content::WebContents* web_contents) OVERRIDE { |
| message_loop_runner_->Quit(); |
| } |
| |
| scoped_refptr<content::MessageLoopRunner> message_loop_runner_; |
| |
| DISALLOW_COPY_AND_ASSIGN(WebContentsDestroyedWatcher); |
| }; |
| |
| // A V1 windowed application. |
| class V1App : public TestBrowserWindow { |
| public: |
| V1App(Profile* profile, const std::string& app_name) { |
| // Create a window. |
| native_window_.reset(new aura::Window(NULL)); |
| native_window_->set_id(0); |
| native_window_->SetType(aura::client::WINDOW_TYPE_POPUP); |
| native_window_->Init(ui::LAYER_TEXTURED); |
| native_window_->Show(); |
| |
| Browser::CreateParams params = Browser::CreateParams::CreateForApp( |
| Browser::TYPE_POPUP, |
| kCrxAppPrefix + app_name, |
| gfx::Rect(), |
| profile, |
| chrome::HOST_DESKTOP_TYPE_ASH); |
| params.window = this; |
| browser_.reset(new Browser(params)); |
| chrome::AddTabAt(browser_.get(), GURL(), 0, true); |
| } |
| |
| virtual ~V1App() { |
| // close all tabs. Note that we do not need to destroy the browser itself. |
| browser_->tab_strip_model()->CloseAllTabs(); |
| } |
| |
| Browser* browser() { return browser_.get(); } |
| |
| // TestBrowserWindow override: |
| virtual gfx::NativeWindow GetNativeWindow() OVERRIDE { |
| return native_window_.get(); |
| } |
| |
| private: |
| // The associated browser with this app. |
| scoped_ptr<Browser> browser_; |
| |
| // The native window we use. |
| scoped_ptr<aura::Window> native_window_; |
| |
| DISALLOW_COPY_AND_ASSIGN(V1App); |
| }; |
| |
| // A V2 application which gets created with an |extension| and for a |profile|. |
| // Upon destruction it will properly close the application. |
| class V2App { |
| public: |
| V2App(Profile* profile, const extensions::Extension* extension) { |
| window_ = new apps::ShellWindow(profile, |
| new ChromeShellWindowDelegate(), |
| extension); |
| apps::ShellWindow::CreateParams params = apps::ShellWindow::CreateParams(); |
| window_->Init(GURL(std::string()), |
| new apps::AppWindowContents(window_), |
| params); |
| } |
| |
| virtual ~V2App() { |
| WebContentsDestroyedWatcher destroyed_watcher(window_->web_contents()); |
| window_->GetBaseWindow()->Close(); |
| destroyed_watcher.Wait(); |
| } |
| |
| private: |
| // The shell window which represents the application. Note that the window |
| // deletes itself asynchronously after window_->GetBaseWindow()->Close() gets |
| // called. |
| apps::ShellWindow* window_; |
| |
| DISALLOW_COPY_AND_ASSIGN(V2App); |
| }; |
| |
| // The testing framework to test multi profile scenarios. |
| class MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest |
| : public ChromeLauncherControllerTest { |
| protected: |
| MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest() { |
| } |
| |
| virtual ~MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest() { |
| } |
| |
| // Overwrite the Setup function to enable multi profile and needed objects. |
| virtual void SetUp() OVERRIDE { |
| profile_manager_.reset( |
| new TestingProfileManager(TestingBrowserProcess::GetGlobal())); |
| |
| ASSERT_TRUE(profile_manager_->SetUp()); |
| |
| // AvatarMenu and multiple profiles works after user logged in. |
| profile_manager_->SetLoggedIn(true); |
| |
| // Enabling multi profile requires several flags to be set. |
| CommandLine::ForCurrentProcess()->AppendSwitch(switches::kMultiProfiles); |
| field_trial_list_.reset(new base::FieldTrialList( |
| new metrics::SHA1EntropyProvider("42"))); |
| base::FieldTrialList::CreateTrialsFromString( |
| "ChromeOSUseMultiProfiles/Enable/", |
| base::FieldTrialList::ACTIVATE_TRIALS); |
| |
| // Initialize the UserManager singleton to a fresh FakeUserManager instance. |
| user_manager_enabler_.reset( |
| new chromeos::ScopedUserManagerEnabler(new chromeos::FakeUserManager)); |
| |
| // Initialize the rest. |
| ChromeLauncherControllerTest::SetUp(); |
| |
| // Get some base objects. |
| session_delegate_ = static_cast<ash::test::TestSessionStateDelegate*>( |
| ash::Shell::GetInstance()->session_state_delegate()); |
| session_delegate_->set_logged_in_users(2); |
| shell_delegate_ = static_cast<ash::test::TestShellDelegate*>( |
| ash::Shell::GetInstance()->delegate()); |
| shell_delegate_->set_multi_profiles_enabled(true); |
| } |
| |
| virtual void TearDown() { |
| ChromeLauncherControllerTest::TearDown(); |
| user_manager_enabler_.reset(); |
| field_trial_list_.reset(); |
| for (ProfileToNameMap::iterator it = created_profiles_.begin(); |
| it != created_profiles_.end(); ++it) |
| profile_manager_->DeleteTestingProfile(it->second); |
| |
| // A Task is leaked if we don't destroy everything, then run the message |
| // loop. |
| base::MessageLoop::current()->PostTask(FROM_HERE, |
| base::MessageLoop::QuitClosure()); |
| base::MessageLoop::current()->Run(); |
| } |
| |
| // Creates a profile for a given |user_name|. Note that this class will keep |
| // the ownership of the created object. |
| TestingProfile* CreateMultiUserProfile(const std::string& user_name) { |
| std::string email_string = user_name + "@example.com"; |
| |
| // Add a user to the fake user manager. |
| GetFakeUserManager()->AddUser(email_string); |
| |
| GetFakeUserManager()->UserLoggedIn( |
| email_string, |
| email_string + kUserIdHashSuffix, |
| false); |
| |
| std::string profile_name = |
| chrome::kProfileDirPrefix + email_string + kUserIdHashSuffix; |
| TestingProfile* profile = profile_manager()->CreateTestingProfile( |
| profile_name, |
| scoped_ptr<PrefServiceSyncable>(), |
| ASCIIToUTF16(email_string), 0, std::string(), |
| TestingProfile::TestingFactories()); |
| profile->set_profile_name(email_string); |
| EXPECT_TRUE(profile); |
| // Remember the profile name so that we can destroy it upon destruction. |
| created_profiles_[profile] = profile_name; |
| return profile; |
| } |
| |
| // Switch to another user. |
| void SwitchActiveUser(const std::string& name) { |
| session_delegate()->SwitchActiveUser(name); |
| GetFakeUserManager()->SwitchActiveUser(name); |
| launcher_controller_->browser_status_monitor_for_test()-> |
| ActiveUserChanged(name); |
| launcher_controller_->shell_window_controller_for_test()-> |
| ActiveUserChanged(name); |
| } |
| |
| // Creates a browser with a |profile| and load a tab with a |title| and |url|. |
| Browser* CreateBrowserAndTabWithProfile(Profile* profile, |
| const std::string& title, |
| const std::string& url) { |
| Browser::CreateParams params(profile, chrome::HOST_DESKTOP_TYPE_ASH); |
| Browser* browser = chrome::CreateBrowserWithTestWindowForParams(¶ms); |
| chrome::NewTab(browser); |
| |
| BrowserList::SetLastActive(browser); |
| NavigateAndCommitActiveTabWithTitle( |
| browser, GURL(url), ASCIIToUTF16(title)); |
| return browser; |
| } |
| |
| // Creates a running V1 application. |
| // Note that with the use of the app_tab_helper as done below, this is only |
| // usable with a single v1 application. |
| V1App* CreateRunningV1App(Profile* profile, |
| const std::string& app_name, |
| const std::string& url) { |
| V1App* v1_app = new V1App(profile, app_name); |
| // Create a new app tab helper and assign it to the launcher so that this |
| // app gets properly detected. |
| // TODO(skuhne): Create a more intelligent app tab helper which is able to |
| // detect all running apps properly. |
| TestAppTabHelperImpl* app_tab_helper = new TestAppTabHelperImpl; |
| app_tab_helper->SetAppID( |
| v1_app->browser()->tab_strip_model()->GetWebContentsAt(0), |
| app_name); |
| SetAppTabHelper(app_tab_helper); |
| |
| NavigateAndCommitActiveTabWithTitle( |
| v1_app->browser(), GURL(url), ASCIIToUTF16("")); |
| return v1_app; |
| } |
| |
| ash::test::TestSessionStateDelegate* |
| session_delegate() { return session_delegate_; } |
| ash::test::TestShellDelegate* shell_delegate() { return shell_delegate_; } |
| |
| // Override BrowserWithTestWindowTest: |
| virtual TestingProfile* CreateProfile() OVERRIDE { |
| return CreateMultiUserProfile("user1"); |
| } |
| virtual void DestroyProfile(TestingProfile* profile) OVERRIDE { |
| // Delete the profile through our profile manager. |
| ProfileToNameMap::iterator it = created_profiles_.find(profile); |
| DCHECK(it != created_profiles_.end()); |
| profile_manager_->DeleteTestingProfile(it->second); |
| created_profiles_.erase(it); |
| } |
| |
| private: |
| typedef std::map<Profile*, std::string> ProfileToNameMap; |
| TestingProfileManager* profile_manager() { return profile_manager_.get(); } |
| |
| chromeos::FakeUserManager* GetFakeUserManager() { |
| return static_cast<chromeos::FakeUserManager*>( |
| chromeos::UserManager::Get()); |
| } |
| |
| scoped_ptr<TestingProfileManager> profile_manager_; |
| scoped_ptr<chromeos::ScopedUserManagerEnabler> user_manager_enabler_; |
| scoped_ptr<base::FieldTrialList> field_trial_list_; |
| |
| ash::test::TestSessionStateDelegate* session_delegate_; |
| ash::test::TestShellDelegate* shell_delegate_; |
| |
| ProfileToNameMap created_profiles_; |
| |
| DISALLOW_COPY_AND_ASSIGN( |
| MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest); |
| }; |
| #endif // defined(OS_CHROMEOS) |
| |
| TEST_F(LegacyShelfLayoutChromeLauncherControllerTest, DefaultApps) { |
| InitLauncherController(); |
| // Model should only contain the browser shortcut and app list items. |
| EXPECT_EQ(2, model_->item_count()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| |
| // Installing |extension3_| should add it to the launcher - behind the |
| // chrome icon. |
| extension_service_->AddExtension(extension3_.get()); |
| EXPECT_EQ("Chrome, App3, AppList, ", GetPinnedAppStatus()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id())); |
| } |
| |
| // Check that the restauration of launcher items is happening in the same order |
| // as the user has pinned them (on another system) when they are synced reverse |
| // order. |
| TEST_F(LegacyShelfLayoutChromeLauncherControllerTest, |
| RestoreDefaultAppsReverseOrder) { |
| InitLauncherController(); |
| |
| base::ListValue policy_value; |
| InsertPrefValue(&policy_value, 0, extension1_->id()); |
| InsertPrefValue(&policy_value, 1, extension2_->id()); |
| InsertPrefValue(&policy_value, 2, extension3_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value.DeepCopy()); |
| EXPECT_EQ(0, profile()->GetPrefs()->GetInteger(prefs::kShelfChromeIconIndex)); |
| // Model should only contain the browser shortcut and app list items. |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| EXPECT_EQ("Chrome, AppList, ", GetPinnedAppStatus()); |
| |
| // Installing |extension3_| should add it to the launcher - behind the |
| // chrome icon. |
| ash::LauncherItem item; |
| extension_service_->AddExtension(extension3_.get()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id())); |
| EXPECT_EQ("Chrome, App3, AppList, ", GetPinnedAppStatus()); |
| |
| // Installing |extension2_| should add it to the launcher - behind the |
| // chrome icon, but in first location. |
| extension_service_->AddExtension(extension2_.get()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_EQ("Chrome, App2, App3, AppList, ", GetPinnedAppStatus()); |
| |
| // Installing |extension1_| should add it to the launcher - behind the |
| // chrome icon, but in first location. |
| extension_service_->AddExtension(extension1_.get()); |
| EXPECT_EQ("Chrome, App1, App2, App3, AppList, ", GetPinnedAppStatus()); |
| } |
| |
| // Check that the restauration of launcher items is happening in the same order |
| // as the user has pinned them (on another system) when they are synced random |
| // order. |
| TEST_F(LegacyShelfLayoutChromeLauncherControllerTest, |
| RestoreDefaultAppsRandomOrder) { |
| InitLauncherController(); |
| |
| base::ListValue policy_value; |
| InsertPrefValue(&policy_value, 0, extension1_->id()); |
| InsertPrefValue(&policy_value, 1, extension2_->id()); |
| InsertPrefValue(&policy_value, 2, extension3_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value.DeepCopy()); |
| EXPECT_EQ(0, profile()->GetPrefs()->GetInteger(prefs::kShelfChromeIconIndex)); |
| // Model should only contain the browser shortcut and app list items. |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| EXPECT_EQ("Chrome, AppList, ", GetPinnedAppStatus()); |
| |
| // Installing |extension2_| should add it to the launcher - behind the |
| // chrome icon. |
| extension_service_->AddExtension(extension2_.get()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| EXPECT_EQ("Chrome, App2, AppList, ", GetPinnedAppStatus()); |
| |
| // Installing |extension1_| should add it to the launcher - behind the |
| // chrome icon, but in first location. |
| extension_service_->AddExtension(extension1_.get()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| EXPECT_EQ("Chrome, App1, App2, AppList, ", GetPinnedAppStatus()); |
| |
| // Installing |extension3_| should add it to the launcher - behind the |
| // chrome icon, but in first location. |
| extension_service_->AddExtension(extension3_.get()); |
| EXPECT_EQ("Chrome, App1, App2, App3, AppList, ", GetPinnedAppStatus()); |
| } |
| |
| // Check that the restauration of launcher items is happening in the same order |
| // as the user has pinned / moved them (on another system) when they are synced |
| // random order - including the chrome icon. |
| TEST_F(LegacyShelfLayoutChromeLauncherControllerTest, |
| RestoreDefaultAppsRandomOrderChromeMoved) { |
| InitLauncherController(); |
| |
| base::ListValue policy_value; |
| InsertPrefValue(&policy_value, 0, extension1_->id()); |
| InsertPrefValue(&policy_value, 1, extension2_->id()); |
| InsertPrefValue(&policy_value, 2, extension3_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value.DeepCopy()); |
| profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex, |
| 1); |
| // Model should only contain the browser shortcut and app list items. |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| EXPECT_EQ("Chrome, AppList, ", GetPinnedAppStatus()); |
| |
| // Installing |extension2_| should add it to the launcher - behind the |
| // chrome icon. |
| ash::LauncherItem item; |
| extension_service_->AddExtension(extension2_.get()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| EXPECT_EQ("Chrome, App2, AppList, ", GetPinnedAppStatus()); |
| |
| // Installing |extension1_| should add it to the launcher - behind the |
| // chrome icon, but in first location. |
| extension_service_->AddExtension(extension1_.get()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| EXPECT_EQ("App1, Chrome, App2, AppList, ", GetPinnedAppStatus()); |
| |
| // Installing |extension3_| should add it to the launcher - behind the |
| // chrome icon, but in first location. |
| extension_service_->AddExtension(extension3_.get()); |
| EXPECT_EQ("App1, Chrome, App2, App3, AppList, ", GetPinnedAppStatus()); |
| } |
| |
| // Check that syncing to a different state does the correct thing. |
| TEST_F(LegacyShelfLayoutChromeLauncherControllerTest, |
| RestoreDefaultAppsResyncOrder) { |
| InitLauncherController(); |
| base::ListValue policy_value; |
| InsertPrefValue(&policy_value, 0, extension1_->id()); |
| InsertPrefValue(&policy_value, 1, extension2_->id()); |
| InsertPrefValue(&policy_value, 2, extension3_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value.DeepCopy()); |
| EXPECT_EQ(0, profile()->GetPrefs()->GetInteger(prefs::kShelfChromeIconIndex)); |
| extension_service_->AddExtension(extension2_.get()); |
| extension_service_->AddExtension(extension1_.get()); |
| extension_service_->AddExtension(extension3_.get()); |
| EXPECT_EQ("Chrome, App1, App2, App3, AppList, ", GetPinnedAppStatus()); |
| |
| // Change the order with increasing chrome position and decreasing position. |
| base::ListValue policy_value1; |
| InsertPrefValue(&policy_value1, 0, extension3_->id()); |
| InsertPrefValue(&policy_value1, 1, extension1_->id()); |
| InsertPrefValue(&policy_value1, 2, extension2_->id()); |
| profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex, |
| 2); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value1.DeepCopy()); |
| EXPECT_EQ("App3, App1, Chrome, App2, AppList, ", GetPinnedAppStatus()); |
| base::ListValue policy_value2; |
| InsertPrefValue(&policy_value2, 0, extension2_->id()); |
| InsertPrefValue(&policy_value2, 1, extension3_->id()); |
| InsertPrefValue(&policy_value2, 2, extension1_->id()); |
| profile()->GetTestingPrefService()->SetInteger(prefs::kShelfChromeIconIndex, |
| 1); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value2.DeepCopy()); |
| EXPECT_EQ("App2, Chrome, App3, App1, AppList, ", GetPinnedAppStatus()); |
| } |
| |
| TEST_F(ChromeLauncherControllerTest, DefaultApps) { |
| InitLauncherController(); |
| // Model should only contain the browser shortcut and app list items. |
| EXPECT_EQ(2, model_->item_count()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| |
| // Installing |extension3_| should add it to the launcher - behind the |
| // chrome icon. |
| extension_service_->AddExtension(extension3_.get()); |
| EXPECT_EQ("AppList, Chrome, App3, ", GetPinnedAppStatus()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id())); |
| } |
| |
| // Check that the restauration of launcher items is happening in the same order |
| // as the user has pinned them (on another system) when they are synced reverse |
| // order. |
| TEST_F(ChromeLauncherControllerTest, RestoreDefaultAppsReverseOrder) { |
| InitLauncherController(); |
| |
| base::ListValue policy_value; |
| InsertPrefValue(&policy_value, 0, extension1_->id()); |
| InsertPrefValue(&policy_value, 1, extension2_->id()); |
| InsertPrefValue(&policy_value, 2, extension3_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value.DeepCopy()); |
| SetShelfChromeIconIndex(0); |
| // Model should only contain the browser shortcut and app list items. |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| EXPECT_EQ("AppList, Chrome, ", GetPinnedAppStatus()); |
| |
| // Installing |extension3_| should add it to the launcher - behind the |
| // chrome icon. |
| ash::LauncherItem item; |
| extension_service_->AddExtension(extension3_.get()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id())); |
| EXPECT_EQ("AppList, Chrome, App3, ", GetPinnedAppStatus()); |
| |
| // Installing |extension2_| should add it to the launcher - behind the |
| // chrome icon, but in first location. |
| extension_service_->AddExtension(extension2_.get()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_EQ("AppList, Chrome, App2, App3, ", GetPinnedAppStatus()); |
| |
| // Installing |extension1_| should add it to the launcher - behind the |
| // chrome icon, but in first location. |
| extension_service_->AddExtension(extension1_.get()); |
| EXPECT_EQ("AppList, Chrome, App1, App2, App3, ", GetPinnedAppStatus()); |
| } |
| |
| // Check that the restauration of launcher items is happening in the same order |
| // as the user has pinned them (on another system) when they are synced random |
| // order. |
| TEST_F(ChromeLauncherControllerTest, RestoreDefaultAppsRandomOrder) { |
| InitLauncherController(); |
| |
| base::ListValue policy_value; |
| InsertPrefValue(&policy_value, 0, extension1_->id()); |
| InsertPrefValue(&policy_value, 1, extension2_->id()); |
| InsertPrefValue(&policy_value, 2, extension3_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value.DeepCopy()); |
| SetShelfChromeIconIndex(0); |
| // Model should only contain the browser shortcut and app list items. |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| EXPECT_EQ("AppList, Chrome, ", GetPinnedAppStatus()); |
| |
| // Installing |extension2_| should add it to the launcher - behind the |
| // chrome icon. |
| extension_service_->AddExtension(extension2_.get()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| EXPECT_EQ("AppList, Chrome, App2, ", GetPinnedAppStatus()); |
| |
| // Installing |extension1_| should add it to the launcher - behind the |
| // chrome icon, but in first location. |
| extension_service_->AddExtension(extension1_.get()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| EXPECT_EQ("AppList, Chrome, App1, App2, ", GetPinnedAppStatus()); |
| |
| // Installing |extension3_| should add it to the launcher - behind the |
| // chrome icon, but in first location. |
| extension_service_->AddExtension(extension3_.get()); |
| EXPECT_EQ("AppList, Chrome, App1, App2, App3, ", GetPinnedAppStatus()); |
| } |
| |
| // Check that the restauration of launcher items is happening in the same order |
| // as the user has pinned / moved them (on another system) when they are synced |
| // random order - including the chrome icon. |
| TEST_F(ChromeLauncherControllerTest, RestoreDefaultAppsRandomOrderChromeMoved) { |
| InitLauncherController(); |
| |
| base::ListValue policy_value; |
| InsertPrefValue(&policy_value, 0, extension1_->id()); |
| InsertPrefValue(&policy_value, 1, extension2_->id()); |
| InsertPrefValue(&policy_value, 2, extension3_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value.DeepCopy()); |
| SetShelfChromeIconIndex(1); |
| // Model should only contain the browser shortcut and app list items. |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| EXPECT_EQ("AppList, Chrome, ", GetPinnedAppStatus()); |
| |
| // Installing |extension2_| should add it to the launcher - behind the |
| // chrome icon. |
| ash::LauncherItem item; |
| extension_service_->AddExtension(extension2_.get()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| EXPECT_EQ("AppList, Chrome, App2, ", GetPinnedAppStatus()); |
| |
| // Installing |extension1_| should add it to the launcher - behind the |
| // chrome icon, but in first location. |
| extension_service_->AddExtension(extension1_.get()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| EXPECT_EQ("AppList, App1, Chrome, App2, ", GetPinnedAppStatus()); |
| |
| // Installing |extension3_| should add it to the launcher - behind the |
| // chrome icon, but in first location. |
| extension_service_->AddExtension(extension3_.get()); |
| EXPECT_EQ("AppList, App1, Chrome, App2, App3, ", GetPinnedAppStatus()); |
| } |
| |
| // Check that syncing to a different state does the correct thing. |
| TEST_F(ChromeLauncherControllerTest, RestoreDefaultAppsResyncOrder) { |
| InitLauncherController(); |
| base::ListValue policy_value; |
| InsertPrefValue(&policy_value, 0, extension1_->id()); |
| InsertPrefValue(&policy_value, 1, extension2_->id()); |
| InsertPrefValue(&policy_value, 2, extension3_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value.DeepCopy()); |
| // The shelf layout has always one static item at the beginning (App List). |
| SetShelfChromeIconIndex(0); |
| extension_service_->AddExtension(extension2_.get()); |
| EXPECT_EQ("AppList, Chrome, App2, ", GetPinnedAppStatus()); |
| extension_service_->AddExtension(extension1_.get()); |
| EXPECT_EQ("AppList, Chrome, App1, App2, ", GetPinnedAppStatus()); |
| extension_service_->AddExtension(extension3_.get()); |
| EXPECT_EQ("AppList, Chrome, App1, App2, App3, ", GetPinnedAppStatus()); |
| |
| // Change the order with increasing chrome position and decreasing position. |
| base::ListValue policy_value1; |
| InsertPrefValue(&policy_value1, 0, extension3_->id()); |
| InsertPrefValue(&policy_value1, 1, extension1_->id()); |
| InsertPrefValue(&policy_value1, 2, extension2_->id()); |
| SetShelfChromeIconIndex(3); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value1.DeepCopy()); |
| EXPECT_EQ("AppList, App3, App1, App2, Chrome, ", GetPinnedAppStatus()); |
| base::ListValue policy_value2; |
| InsertPrefValue(&policy_value2, 0, extension2_->id()); |
| InsertPrefValue(&policy_value2, 1, extension3_->id()); |
| InsertPrefValue(&policy_value2, 2, extension1_->id()); |
| SetShelfChromeIconIndex(2); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value2.DeepCopy()); |
| EXPECT_EQ("AppList, App2, App3, Chrome, App1, ", GetPinnedAppStatus()); |
| |
| // Check that the chrome icon can also be at the first possible location. |
| SetShelfChromeIconIndex(0); |
| base::ListValue policy_value3; |
| InsertPrefValue(&policy_value3, 0, extension3_->id()); |
| InsertPrefValue(&policy_value3, 1, extension2_->id()); |
| InsertPrefValue(&policy_value3, 2, extension1_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value3.DeepCopy()); |
| EXPECT_EQ("AppList, Chrome, App3, App2, App1, ", GetPinnedAppStatus()); |
| |
| // Check that unloading of extensions works as expected. |
| extension_service_->UnloadExtension(extension1_->id(), |
| UnloadedExtensionInfo::REASON_UNINSTALL); |
| EXPECT_EQ("AppList, Chrome, App3, App2, ", GetPinnedAppStatus()); |
| |
| extension_service_->UnloadExtension(extension2_->id(), |
| UnloadedExtensionInfo::REASON_UNINSTALL); |
| EXPECT_EQ("AppList, Chrome, App3, ", GetPinnedAppStatus()); |
| |
| // Check that an update of an extension does not crash the system. |
| extension_service_->UnloadExtension(extension3_->id(), |
| UnloadedExtensionInfo::REASON_UPDATE); |
| EXPECT_EQ("AppList, Chrome, App3, ", GetPinnedAppStatus()); |
| } |
| |
| // Check that simple locking of an application will 'create' a launcher item. |
| TEST_F(ChromeLauncherControllerTest, CheckLockApps) { |
| InitLauncherController(); |
| // Model should only contain the browser shortcut and app list items. |
| EXPECT_EQ(2, model_->item_count()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE( |
| launcher_controller_->IsWindowedAppInLauncher(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id())); |
| EXPECT_FALSE( |
| launcher_controller_->IsWindowedAppInLauncher(extension2_->id())); |
| |
| launcher_controller_->LockV1AppWithID(extension1_->id()); |
| |
| EXPECT_EQ(3, model_->item_count()); |
| EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id())); |
| EXPECT_FALSE( |
| launcher_controller_->IsWindowedAppInLauncher(extension2_->id())); |
| |
| launcher_controller_->UnlockV1AppWithID(extension1_->id()); |
| |
| EXPECT_EQ(2, model_->item_count()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE( |
| launcher_controller_->IsWindowedAppInLauncher(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id())); |
| EXPECT_FALSE( |
| launcher_controller_->IsWindowedAppInLauncher(extension2_->id())); |
| } |
| |
| // Check that multiple locks of an application will be properly handled. |
| TEST_F(ChromeLauncherControllerTest, CheckMultiLockApps) { |
| InitLauncherController(); |
| // Model should only contain the browser shortcut and app list items. |
| EXPECT_EQ(2, model_->item_count()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE( |
| launcher_controller_->IsWindowedAppInLauncher(extension1_->id())); |
| |
| for (int i = 0; i < 2; i++) { |
| launcher_controller_->LockV1AppWithID(extension1_->id()); |
| |
| EXPECT_EQ(3, model_->item_count()); |
| EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher( |
| extension1_->id())); |
| } |
| |
| launcher_controller_->UnlockV1AppWithID(extension1_->id()); |
| |
| EXPECT_EQ(3, model_->item_count()); |
| EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id())); |
| |
| launcher_controller_->UnlockV1AppWithID(extension1_->id()); |
| |
| EXPECT_EQ(2, model_->item_count()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE( |
| launcher_controller_->IsWindowedAppInLauncher(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id())); |
| EXPECT_FALSE( |
| launcher_controller_->IsWindowedAppInLauncher(extension1_->id())); |
| } |
| |
| // Check that already pinned items are not effected by locks. |
| TEST_F(ChromeLauncherControllerTest, CheckAlreadyPinnedLockApps) { |
| InitLauncherController(); |
| // Model should only contain the browser shortcut and app list items. |
| EXPECT_EQ(2, model_->item_count()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE( |
| launcher_controller_->IsWindowedAppInLauncher(extension1_->id())); |
| |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| launcher_controller_->PinAppWithID(extension1_->id()); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id())); |
| |
| EXPECT_EQ(3, model_->item_count()); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE( |
| launcher_controller_->IsWindowedAppInLauncher(extension1_->id())); |
| |
| launcher_controller_->LockV1AppWithID(extension1_->id()); |
| |
| EXPECT_EQ(3, model_->item_count()); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE( |
| launcher_controller_->IsWindowedAppInLauncher(extension1_->id())); |
| |
| launcher_controller_->UnlockV1AppWithID(extension1_->id()); |
| |
| EXPECT_EQ(3, model_->item_count()); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE( |
| launcher_controller_->IsWindowedAppInLauncher(extension1_->id())); |
| |
| launcher_controller_->UnpinAppWithID(extension1_->id()); |
| |
| EXPECT_EQ(2, model_->item_count()); |
| } |
| |
| // Check that already pinned items which get locked stay after unpinning. |
| TEST_F(ChromeLauncherControllerTest, CheckPinnedAppsStayAfterUnlock) { |
| InitLauncherController(); |
| // Model should only contain the browser shortcut and app list items. |
| EXPECT_EQ(2, model_->item_count()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE( |
| launcher_controller_->IsWindowedAppInLauncher(extension1_->id())); |
| |
| launcher_controller_->PinAppWithID(extension1_->id()); |
| |
| EXPECT_EQ(3, model_->item_count()); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE( |
| launcher_controller_->IsWindowedAppInLauncher(extension1_->id())); |
| |
| launcher_controller_->LockV1AppWithID(extension1_->id()); |
| |
| EXPECT_EQ(3, model_->item_count()); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE( |
| launcher_controller_->IsWindowedAppInLauncher(extension1_->id())); |
| |
| launcher_controller_->UnpinAppWithID(extension1_->id()); |
| |
| EXPECT_EQ(3, model_->item_count()); |
| EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id())); |
| |
| launcher_controller_->UnlockV1AppWithID(extension1_->id()); |
| |
| EXPECT_EQ(2, model_->item_count()); |
| } |
| |
| #if defined(OS_CHROMEOS) |
| // Check that with multi profile V1 apps are properly added / removed from the |
| // shelf. |
| TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest, |
| V1AppUpdateOnUserSwitch) { |
| // Create a browser item in the LauncherController. |
| InitLauncherController(); |
| EXPECT_EQ(2, model_->item_count()); |
| { |
| // Create a "windowed gmail app". |
| scoped_ptr<V1App> v1_app(CreateRunningV1App( |
| profile(), extension_misc::kGmailAppId, gmail_url)); |
| EXPECT_EQ(3, model_->item_count()); |
| |
| // After switching to a second user the item should be gone. |
| std::string user2 = "user2"; |
| TestingProfile* profile2 = CreateMultiUserProfile(user2); |
| SwitchActiveUser(profile2->GetProfileName()); |
| EXPECT_EQ(2, model_->item_count()); |
| |
| // After switching back the item should be back. |
| SwitchActiveUser(profile()->GetProfileName()); |
| EXPECT_EQ(3, model_->item_count()); |
| // Note we destroy now the gmail app with the closure end. |
| } |
| EXPECT_EQ(2, model_->item_count()); |
| } |
| |
| // Check edge cases with multi profile V1 apps in the shelf. |
| TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest, |
| V1AppUpdateOnUserSwitchEdgecases) { |
| // Create a browser item in the LauncherController. |
| InitLauncherController(); |
| |
| // First test: Create an app when the user is not active. |
| std::string user2 = "user2"; |
| TestingProfile* profile2 = CreateMultiUserProfile(user2); |
| { |
| // Create a "windowed gmail app". |
| scoped_ptr<V1App> v1_app(CreateRunningV1App( |
| profile2, extension_misc::kGmailAppId, gmail_url)); |
| EXPECT_EQ(2, model_->item_count()); |
| |
| // However - switching to the user should show it. |
| SwitchActiveUser(profile2->GetProfileName()); |
| EXPECT_EQ(3, model_->item_count()); |
| |
| // Second test: Remove the app when the user is not active and see that it |
| // works. |
| SwitchActiveUser(profile()->GetProfileName()); |
| EXPECT_EQ(2, model_->item_count()); |
| // Note: the closure ends and the browser will go away. |
| } |
| EXPECT_EQ(2, model_->item_count()); |
| SwitchActiveUser(profile2->GetProfileName()); |
| EXPECT_EQ(2, model_->item_count()); |
| SwitchActiveUser(profile()->GetProfileName()); |
| EXPECT_EQ(2, model_->item_count()); |
| } |
| |
| // Check edge case where a visiting V1 app gets closed (crbug.com/321374). |
| TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest, |
| V1CloseOnVisitingDesktop) { |
| // Create a browser item in the LauncherController. |
| InitLauncherController(); |
| |
| chrome::MultiUserWindowManager* manager = |
| chrome::MultiUserWindowManager::GetInstance(); |
| |
| // First create an app when the user is active. |
| std::string user2 = "user2"; |
| TestingProfile* profile2 = CreateMultiUserProfile(user2); |
| { |
| // Create a "windowed gmail app". |
| scoped_ptr<V1App> v1_app(CreateRunningV1App( |
| profile(), |
| extension_misc::kGmailAppId, |
| kGmailLaunchURL)); |
| EXPECT_EQ(3, model_->item_count()); |
| |
| // Transfer the app to the other screen and switch users. |
| manager->ShowWindowForUser(v1_app->browser()->window()->GetNativeWindow(), |
| user2); |
| EXPECT_EQ(3, model_->item_count()); |
| SwitchActiveUser(profile2->GetProfileName()); |
| EXPECT_EQ(2, model_->item_count()); |
| } |
| // After the app was destroyed, switch back. (which caused already a crash). |
| SwitchActiveUser(profile()->GetProfileName()); |
| |
| // Create the same app again - which was also causing the crash. |
| EXPECT_EQ(2, model_->item_count()); |
| { |
| // Create a "windowed gmail app". |
| scoped_ptr<V1App> v1_app(CreateRunningV1App( |
| profile(), |
| extension_misc::kGmailAppId, |
| kGmailLaunchURL)); |
| EXPECT_EQ(3, model_->item_count()); |
| } |
| SwitchActiveUser(profile2->GetProfileName()); |
| EXPECT_EQ(2, model_->item_count()); |
| } |
| |
| // Check edge cases with multi profile V1 apps in the shelf. |
| TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest, |
| V1AppUpdateOnUserSwitchEdgecases2) { |
| // Create a browser item in the LauncherController. |
| InitLauncherController(); |
| TestAppTabHelperImpl* app_tab_helper = new TestAppTabHelperImpl; |
| SetAppTabHelper(app_tab_helper); |
| |
| // First test: Create an app when the user is not active. |
| std::string user2 = "user2"; |
| TestingProfile* profile2 = CreateMultiUserProfile(user2); |
| SwitchActiveUser(profile2->GetProfileName()); |
| { |
| // Create a "windowed gmail app". |
| scoped_ptr<V1App> v1_app(CreateRunningV1App( |
| profile(), extension_misc::kGmailAppId, gmail_url)); |
| EXPECT_EQ(2, model_->item_count()); |
| |
| // However - switching to the user should show it. |
| SwitchActiveUser(profile()->GetProfileName()); |
| EXPECT_EQ(3, model_->item_count()); |
| |
| // Second test: Remove the app when the user is not active and see that it |
| // works. |
| SwitchActiveUser(profile2->GetProfileName()); |
| EXPECT_EQ(2, model_->item_count()); |
| v1_app.reset(); |
| } |
| EXPECT_EQ(2, model_->item_count()); |
| SwitchActiveUser(profile()->GetProfileName()); |
| EXPECT_EQ(2, model_->item_count()); |
| SwitchActiveUser(profile2->GetProfileName()); |
| EXPECT_EQ(2, model_->item_count()); |
| } |
| |
| // Check that activating an item which is on another user's desktop, will bring |
| // it back. |
| TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest, |
| TestLauncherActivationPullsBackWindow) { |
| // Create a browser item in the LauncherController. |
| InitLauncherController(); |
| chrome::MultiUserWindowManager* manager = |
| chrome::MultiUserWindowManager::GetInstance(); |
| |
| // Add two users to the window manager. |
| std::string user2 = "user2"; |
| TestingProfile* profile2 = CreateMultiUserProfile(user2); |
| manager->AddUser(profile()); |
| manager->AddUser(profile2); |
| const std::string& current_user = |
| multi_user_util::GetUserIDFromProfile(profile()); |
| |
| // Create a browser window with a native window for the current user. |
| scoped_ptr<BrowserWindow> browser_window(CreateTestBrowserWindow( |
| Browser::CreateParams(profile(), chrome::HOST_DESKTOP_TYPE_ASH))); |
| aura::Window* window = browser_window->GetNativeWindow(); |
| manager->SetWindowOwner(window, current_user); |
| |
| // Check that an activation of the window on its owner's desktop does not |
| // change the visibility to another user. |
| launcher_controller_->ActivateWindowOrMinimizeIfActive(browser_window.get(), |
| false); |
| EXPECT_TRUE(manager->IsWindowOnDesktopOfUser(window, current_user)); |
| |
| // Transfer the window to another user's desktop and check that activating it |
| // does pull it back to that user. |
| manager->ShowWindowForUser(window, user2); |
| EXPECT_FALSE(manager->IsWindowOnDesktopOfUser(window, current_user)); |
| launcher_controller_->ActivateWindowOrMinimizeIfActive(browser_window.get(), |
| false); |
| EXPECT_TRUE(manager->IsWindowOnDesktopOfUser(window, current_user)); |
| } |
| #endif |
| |
| // Check that lock -> pin -> unlock -> unpin does properly transition. |
| TEST_F(ChromeLauncherControllerTest, CheckLockPinUnlockUnpin) { |
| InitLauncherController(); |
| // Model should only contain the browser shortcut and app list items. |
| EXPECT_EQ(2, model_->item_count()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE( |
| launcher_controller_->IsWindowedAppInLauncher(extension1_->id())); |
| |
| launcher_controller_->LockV1AppWithID(extension1_->id()); |
| |
| EXPECT_EQ(3, model_->item_count()); |
| EXPECT_EQ(ash::TYPE_WINDOWED_APP, model_->items()[2].type); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_TRUE(launcher_controller_->IsWindowedAppInLauncher(extension1_->id())); |
| |
| launcher_controller_->PinAppWithID(extension1_->id()); |
| |
| EXPECT_EQ(3, model_->item_count()); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE( |
| launcher_controller_->IsWindowedAppInLauncher(extension1_->id())); |
| |
| launcher_controller_->UnlockV1AppWithID(extension1_->id()); |
| |
| EXPECT_EQ(3, model_->item_count()); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE( |
| launcher_controller_->IsWindowedAppInLauncher(extension1_->id())); |
| |
| launcher_controller_->UnpinAppWithID(extension1_->id()); |
| |
| EXPECT_EQ(2, model_->item_count()); |
| } |
| |
| // Check that a locked (windowed V1 application) will be properly converted |
| // between locked and pinned when the order gets changed through a profile / |
| // policy change. |
| TEST_F(ChromeLauncherControllerTest, RestoreDefaultAndLockedAppsResyncOrder) { |
| InitLauncherController(); |
| base::ListValue policy_value0; |
| InsertPrefValue(&policy_value0, 0, extension1_->id()); |
| InsertPrefValue(&policy_value0, 1, extension3_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value0.DeepCopy()); |
| // The shelf layout has always one static item at the beginning (App List). |
| SetShelfChromeIconIndex(0); |
| extension_service_->AddExtension(extension1_.get()); |
| EXPECT_EQ("AppList, Chrome, App1, ", GetPinnedAppStatus()); |
| extension_service_->AddExtension(extension2_.get()); |
| // No new app icon will be generated. |
| EXPECT_EQ("AppList, Chrome, App1, ", GetPinnedAppStatus()); |
| // Add the app as locked app which will add it (un-pinned). |
| launcher_controller_->LockV1AppWithID(extension2_->id()); |
| EXPECT_EQ("AppList, Chrome, App1, app2, ", GetPinnedAppStatus()); |
| extension_service_->AddExtension(extension3_.get()); |
| EXPECT_EQ("AppList, Chrome, App1, App3, app2, ", GetPinnedAppStatus()); |
| |
| // Now request to pin all items which should convert the locked item into a |
| // pinned item. |
| base::ListValue policy_value1; |
| InsertPrefValue(&policy_value1, 0, extension3_->id()); |
| InsertPrefValue(&policy_value1, 1, extension2_->id()); |
| InsertPrefValue(&policy_value1, 2, extension1_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value1.DeepCopy()); |
| EXPECT_EQ("AppList, Chrome, App3, App2, App1, ", GetPinnedAppStatus()); |
| |
| // Going back to a status where there is no requirement for app 2 to be pinned |
| // should convert it back to locked but not pinned and state. The position |
| // is determined by the |ShelfModel|'s weight system. Since at the moment |
| // the weight of a running app has the same as a shortcut, it will remain |
| // where it is. Surely note ideal, but since the sync process can shift around |
| // locations - as well as many other edge cases - this gets nearly impossible |
| // to get right. |
| // TODO(skuhne): Filed crbug.com/293761 to track of this. |
| base::ListValue policy_value2; |
| InsertPrefValue(&policy_value2, 0, extension3_->id()); |
| InsertPrefValue(&policy_value2, 1, extension1_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value2.DeepCopy()); |
| EXPECT_EQ("AppList, Chrome, App3, app2, App1, ", GetPinnedAppStatus()); |
| |
| // Removing an item should simply close it and everything should shift. |
| base::ListValue policy_value3; |
| InsertPrefValue(&policy_value3, 0, extension3_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value3.DeepCopy()); |
| EXPECT_EQ("AppList, Chrome, App3, app2, ", GetPinnedAppStatus()); |
| } |
| |
| // Check that a running and not pinned V2 application will be properly converted |
| // between locked and pinned when the order gets changed through a profile / |
| // policy change. |
| TEST_F(ChromeLauncherControllerTest, |
| RestoreDefaultAndRunningV2AppsResyncOrder) { |
| InitLauncherController(); |
| base::ListValue policy_value0; |
| InsertPrefValue(&policy_value0, 0, extension1_->id()); |
| InsertPrefValue(&policy_value0, 1, extension3_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value0.DeepCopy()); |
| // The shelf layout has always one static item at the beginning (app List). |
| SetShelfChromeIconIndex(0); |
| extension_service_->AddExtension(extension1_.get()); |
| EXPECT_EQ("AppList, Chrome, App1, ", GetPinnedAppStatus()); |
| extension_service_->AddExtension(extension2_.get()); |
| // No new app icon will be generated. |
| EXPECT_EQ("AppList, Chrome, App1, ", GetPinnedAppStatus()); |
| // Add the app as an unpinned but running V2 app. |
| CreateRunningV2App(extension2_->id()); |
| EXPECT_EQ("AppList, Chrome, App1, *app2, ", GetPinnedAppStatus()); |
| extension_service_->AddExtension(extension3_.get()); |
| EXPECT_EQ("AppList, Chrome, App1, App3, *app2, ", GetPinnedAppStatus()); |
| |
| // Now request to pin all items which should convert the locked item into a |
| // pinned item. |
| base::ListValue policy_value1; |
| InsertPrefValue(&policy_value1, 0, extension3_->id()); |
| InsertPrefValue(&policy_value1, 1, extension2_->id()); |
| InsertPrefValue(&policy_value1, 2, extension1_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value1.DeepCopy()); |
| EXPECT_EQ("AppList, Chrome, App3, App2, App1, ", GetPinnedAppStatus()); |
| |
| // Going back to a status where there is no requirement for app 2 to be pinned |
| // should convert it back to running V2 app. Since the position is determined |
| // by the |ShelfModel|'s weight system, it will be after last pinned item. |
| base::ListValue policy_value2; |
| InsertPrefValue(&policy_value2, 0, extension3_->id()); |
| InsertPrefValue(&policy_value2, 1, extension1_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value2.DeepCopy()); |
| EXPECT_EQ("AppList, Chrome, App3, App1, *app2, ", GetPinnedAppStatus()); |
| |
| // Removing an item should simply close it and everything should shift. |
| base::ListValue policy_value3; |
| InsertPrefValue(&policy_value3, 0, extension3_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| policy_value3.DeepCopy()); |
| EXPECT_EQ("AppList, Chrome, App3, *app2, ", GetPinnedAppStatus()); |
| } |
| |
| // Each user has a different set of applications pinned. Check that when |
| // switching between the two users, the state gets properly set. |
| TEST_F(ChromeLauncherControllerTest, UserSwitchIconRestore) { |
| base::ListValue user_a; |
| base::ListValue user_b; |
| SetUpMultiUserScenario(&user_a, &user_b); |
| // Show user 1. |
| SetShelfChromeIconIndex(6); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| user_a.DeepCopy()); |
| EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome, ", |
| GetPinnedAppStatus()); |
| |
| // Show user 2. |
| SetShelfChromeIconIndex(4); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| user_b.DeepCopy()); |
| |
| EXPECT_EQ("AppList, App7, App8, Chrome, ", GetPinnedAppStatus()); |
| |
| // Switch back to 1. |
| SetShelfChromeIconIndex(8); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| user_a.DeepCopy()); |
| EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome, ", |
| GetPinnedAppStatus()); |
| |
| // Switch back to 2. |
| SetShelfChromeIconIndex(4); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| user_b.DeepCopy()); |
| EXPECT_EQ("AppList, App7, App8, Chrome, ", GetPinnedAppStatus()); |
| } |
| |
| // Each user has a different set of applications pinned, and one user has an |
| // application running. Check that when switching between the two users, the |
| // state gets properly set. |
| TEST_F(ChromeLauncherControllerTest, UserSwitchIconRestoreWithRunningV2App) { |
| base::ListValue user_a; |
| base::ListValue user_b; |
| SetUpMultiUserScenario(&user_a, &user_b); |
| |
| // Run App1 and assume that it is a V2 app. |
| CreateRunningV2App(extension1_->id()); |
| |
| // Show user 1. |
| SetShelfChromeIconIndex(6); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| user_a.DeepCopy()); |
| EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome, ", |
| GetPinnedAppStatus()); |
| |
| // Show user 2. |
| SetShelfChromeIconIndex(4); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| user_b.DeepCopy()); |
| |
| EXPECT_EQ("AppList, App7, App8, Chrome, *app1, ", GetPinnedAppStatus()); |
| |
| // Switch back to 1. |
| SetShelfChromeIconIndex(8); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| user_a.DeepCopy()); |
| EXPECT_EQ("AppList, App1, App2, App3, App4, App5, App6, Chrome, ", |
| GetPinnedAppStatus()); |
| |
| // Switch back to 2. |
| SetShelfChromeIconIndex(4); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| user_b.DeepCopy()); |
| EXPECT_EQ("AppList, App7, App8, Chrome, *app1, ", GetPinnedAppStatus()); |
| } |
| |
| // Each user has a different set of applications pinned, and one user has an |
| // application running. The chrome icon is not the last item in the list. |
| // Check that when switching between the two users, the state gets properly set. |
| // There was once a bug associated with this. |
| TEST_F(ChromeLauncherControllerTest, |
| UserSwitchIconRestoreWithRunningV2AppChromeInMiddle) { |
| base::ListValue user_a; |
| base::ListValue user_b; |
| SetUpMultiUserScenario(&user_a, &user_b); |
| |
| // Run App1 and assume that it is a V2 app. |
| CreateRunningV2App(extension1_->id()); |
| |
| // Show user 1. |
| SetShelfChromeIconIndex(5); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| user_a.DeepCopy()); |
| EXPECT_EQ("AppList, App1, App2, App3, App4, App5, Chrome, App6, ", |
| GetPinnedAppStatus()); |
| |
| // Show user 2. |
| SetShelfChromeIconIndex(4); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| user_b.DeepCopy()); |
| |
| EXPECT_EQ("AppList, App7, App8, Chrome, *app1, ", GetPinnedAppStatus()); |
| |
| // Switch back to 1. |
| SetShelfChromeIconIndex(5); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| user_a.DeepCopy()); |
| EXPECT_EQ("AppList, App1, App2, App3, App4, App5, Chrome, App6, ", |
| GetPinnedAppStatus()); |
| } |
| |
| TEST_F(ChromeLauncherControllerTest, Policy) { |
| extension_service_->AddExtension(extension1_.get()); |
| extension_service_->AddExtension(extension3_.get()); |
| |
| base::ListValue policy_value; |
| InsertPrefValue(&policy_value, 0, extension1_->id()); |
| InsertPrefValue(&policy_value, 1, extension2_->id()); |
| profile()->GetTestingPrefService()->SetManagedPref(prefs::kPinnedLauncherApps, |
| policy_value.DeepCopy()); |
| |
| // Only |extension1_| should get pinned. |extension2_| is specified but not |
| // installed, and |extension3_| is part of the default set, but that shouldn't |
| // take effect when the policy override is in place. |
| InitLauncherController(); |
| EXPECT_EQ(3, model_->item_count()); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension2_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| |
| // Installing |extension2_| should add it to the launcher. |
| extension_service_->AddExtension(extension2_.get()); |
| EXPECT_EQ(4, model_->item_count()); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[3].type); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension2_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| |
| // Removing |extension1_| from the policy should be reflected in the launcher. |
| policy_value.Remove(0, NULL); |
| profile()->GetTestingPrefService()->SetManagedPref(prefs::kPinnedLauncherApps, |
| policy_value.DeepCopy()); |
| EXPECT_EQ(3, model_->item_count()); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension1_->id())); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension2_->id())); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| } |
| |
| TEST_F(ChromeLauncherControllerTest, UnpinWithUninstall) { |
| extension_service_->AddExtension(extension3_.get()); |
| extension_service_->AddExtension(extension4_.get()); |
| |
| InitLauncherController(); |
| |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id())); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension4_->id())); |
| |
| extension_service_->UnloadExtension(extension3_->id(), |
| UnloadedExtensionInfo::REASON_UNINSTALL); |
| |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension4_->id())); |
| } |
| |
| TEST_F(ChromeLauncherControllerTest, PrefUpdates) { |
| extension_service_->AddExtension(extension2_.get()); |
| extension_service_->AddExtension(extension3_.get()); |
| extension_service_->AddExtension(extension4_.get()); |
| |
| InitLauncherController(); |
| |
| std::vector<std::string> expected_launchers; |
| std::vector<std::string> actual_launchers; |
| base::ListValue pref_value; |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| pref_value.DeepCopy()); |
| GetAppLaunchers(launcher_controller_.get(), &actual_launchers); |
| EXPECT_EQ(expected_launchers, actual_launchers); |
| |
| // Unavailable extensions don't create launcher items. |
| InsertPrefValue(&pref_value, 0, extension1_->id()); |
| InsertPrefValue(&pref_value, 1, extension2_->id()); |
| InsertPrefValue(&pref_value, 2, extension4_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| pref_value.DeepCopy()); |
| expected_launchers.push_back(extension2_->id()); |
| expected_launchers.push_back(extension4_->id()); |
| GetAppLaunchers(launcher_controller_.get(), &actual_launchers); |
| EXPECT_EQ(expected_launchers, actual_launchers); |
| |
| // Redundant pref entries show up only once. |
| InsertPrefValue(&pref_value, 2, extension3_->id()); |
| InsertPrefValue(&pref_value, 2, extension3_->id()); |
| InsertPrefValue(&pref_value, 5, extension3_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| pref_value.DeepCopy()); |
| expected_launchers.insert(expected_launchers.begin() + 1, extension3_->id()); |
| GetAppLaunchers(launcher_controller_.get(), &actual_launchers); |
| EXPECT_EQ(expected_launchers, actual_launchers); |
| |
| // Order changes are reflected correctly. |
| pref_value.Clear(); |
| InsertPrefValue(&pref_value, 0, extension4_->id()); |
| InsertPrefValue(&pref_value, 1, extension3_->id()); |
| InsertPrefValue(&pref_value, 2, extension2_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| pref_value.DeepCopy()); |
| std::reverse(expected_launchers.begin(), expected_launchers.end()); |
| GetAppLaunchers(launcher_controller_.get(), &actual_launchers); |
| EXPECT_EQ(expected_launchers, actual_launchers); |
| |
| // Clearing works. |
| pref_value.Clear(); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| pref_value.DeepCopy()); |
| expected_launchers.clear(); |
| GetAppLaunchers(launcher_controller_.get(), &actual_launchers); |
| EXPECT_EQ(expected_launchers, actual_launchers); |
| } |
| |
| TEST_F(ChromeLauncherControllerTest, PendingInsertionOrder) { |
| extension_service_->AddExtension(extension1_.get()); |
| extension_service_->AddExtension(extension3_.get()); |
| |
| InitLauncherController(); |
| |
| base::ListValue pref_value; |
| InsertPrefValue(&pref_value, 0, extension1_->id()); |
| InsertPrefValue(&pref_value, 1, extension2_->id()); |
| InsertPrefValue(&pref_value, 2, extension3_->id()); |
| profile()->GetTestingPrefService()->SetUserPref(prefs::kPinnedLauncherApps, |
| pref_value.DeepCopy()); |
| |
| std::vector<std::string> expected_launchers; |
| expected_launchers.push_back(extension1_->id()); |
| expected_launchers.push_back(extension3_->id()); |
| std::vector<std::string> actual_launchers; |
| |
| GetAppLaunchers(launcher_controller_.get(), &actual_launchers); |
| EXPECT_EQ(expected_launchers, actual_launchers); |
| |
| // Install |extension2| and verify it shows up between the other two. |
| extension_service_->AddExtension(extension2_.get()); |
| expected_launchers.insert(expected_launchers.begin() + 1, extension2_->id()); |
| GetAppLaunchers(launcher_controller_.get(), &actual_launchers); |
| EXPECT_EQ(expected_launchers, actual_launchers); |
| } |
| |
| // Checks the created menus and menu lists for correctness. It uses the given |
| // |controller| to create the objects for the given |item| and checks the |
| // found item count against the |expected_items|. The |title| list contains the |
| // menu titles in the order of their appearance in the menu (not including the |
| // application name). |
| bool CheckMenuCreation(ChromeLauncherController* controller, |
| const ash::LauncherItem& item, |
| size_t expected_items, |
| base::string16 title[], |
| bool is_browser) { |
| ChromeLauncherAppMenuItems items = controller->GetApplicationList(item, 0); |
| // A new behavior has been added: Only show menus if there is at least one |
| // item available. |
| if (expected_items < 1 && is_browser) { |
| EXPECT_EQ(0u, items.size()); |
| return items.size() == 0; |
| } |
| // There should be one item in there: The title. |
| EXPECT_EQ(expected_items + 1, items.size()); |
| EXPECT_FALSE(items[0]->IsEnabled()); |
| for (size_t i = 0; i < expected_items; i++) { |
| EXPECT_EQ(title[i], items[1 + i]->title()); |
| // Check that the first real item has a leading separator. |
| if (i == 1) |
| EXPECT_TRUE(items[i]->HasLeadingSeparator()); |
| else |
| EXPECT_FALSE(items[i]->HasLeadingSeparator()); |
| } |
| |
| scoped_ptr<ash::ShelfMenuModel> menu(new LauncherApplicationMenuItemModel( |
| controller->GetApplicationList(item, 0))); |
| // The first element in the menu is a spacing separator. On some systems |
| // (e.g. Windows) such things do not exist. As such we check the existence |
| // and adjust dynamically. |
| int first_item = menu->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR ? 1 : 0; |
| int expected_menu_items = first_item + |
| (expected_items ? (expected_items + 3) : 2); |
| EXPECT_EQ(expected_menu_items, menu->GetItemCount()); |
| EXPECT_FALSE(menu->IsEnabledAt(first_item)); |
| if (expected_items) { |
| EXPECT_EQ(ui::MenuModel::TYPE_SEPARATOR, |
| menu->GetTypeAt(first_item + 1)); |
| } |
| return items.size() == expected_items + 1; |
| } |
| |
| // Check that browsers get reflected correctly in the launcher menu. |
| TEST_F(ChromeLauncherControllerTest, BrowserMenuGeneration) { |
| EXPECT_EQ(1U, chrome::GetTotalBrowserCount()); |
| chrome::NewTab(browser()); |
| |
| InitLauncherController(); |
| |
| // Check that the browser list is empty at this time. |
| ash::LauncherItem item_browser; |
| item_browser.type = ash::TYPE_BROWSER_SHORTCUT; |
| item_browser.id = |
| launcher_controller_->GetLauncherIDForAppID(extension_misc::kChromeAppId); |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_browser, 0, NULL, true)); |
| |
| // Now make the created browser() visible by adding it to the active browser |
| // list. |
| BrowserList::SetLastActive(browser()); |
| base::string16 title1 = ASCIIToUTF16("Test1"); |
| NavigateAndCommitActiveTabWithTitle(browser(), GURL("http://test1"), title1); |
| base::string16 one_menu_item[] = { title1 }; |
| |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_browser, 1, one_menu_item, true)); |
| |
| // Create one more browser/window and check that one more was added. |
| Browser::CreateParams ash_params(profile(), chrome::HOST_DESKTOP_TYPE_ASH); |
| scoped_ptr<Browser> browser2( |
| chrome::CreateBrowserWithTestWindowForParams(&ash_params)); |
| chrome::NewTab(browser2.get()); |
| BrowserList::SetLastActive(browser2.get()); |
| base::string16 title2 = ASCIIToUTF16("Test2"); |
| NavigateAndCommitActiveTabWithTitle(browser2.get(), GURL("http://test2"), |
| title2); |
| |
| // Check that the list contains now two entries - make furthermore sure that |
| // the active item is the first entry. |
| base::string16 two_menu_items[] = {title1, title2}; |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_browser, 2, two_menu_items, true)); |
| |
| // Apparently we have to close all tabs we have. |
| chrome::CloseTab(browser2.get()); |
| } |
| |
| #if defined(OS_CHROMEOS) |
| // Check the multi profile case where only user related browsers should show |
| // up. |
| TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest, |
| BrowserMenuGenerationTwoUsers) { |
| // Create a browser item in the LauncherController. |
| InitLauncherController(); |
| |
| ash::LauncherItem item_browser; |
| item_browser.type = ash::TYPE_BROWSER_SHORTCUT; |
| item_browser.id = |
| launcher_controller_->GetLauncherIDForAppID(extension_misc::kChromeAppId); |
| |
| // Check that the menu is empty. |
| chrome::NewTab(browser()); |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_browser, 0, NULL, true)); |
| |
| // Show the created |browser()| by adding it to the active browser list. |
| BrowserList::SetLastActive(browser()); |
| base::string16 title1 = ASCIIToUTF16("Test1"); |
| NavigateAndCommitActiveTabWithTitle(browser(), GURL("http://test1"), title1); |
| base::string16 one_menu_item1[] = { title1 }; |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_browser, 1, one_menu_item1, true)); |
| |
| // Create a browser for another user and check that it is not included in the |
| // users running browser list. |
| std::string user2 = "user2"; |
| TestingProfile* profile2 = CreateMultiUserProfile(user2); |
| scoped_ptr<Browser> browser2( |
| CreateBrowserAndTabWithProfile(profile2, user2, "http://test2")); |
| base::string16 one_menu_item2[] = { ASCIIToUTF16(user2) }; |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_browser, 1, one_menu_item1, true)); |
| |
| // Switch to the other user and make sure that only that browser window gets |
| // shown. |
| SwitchActiveUser(profile2->GetProfileName()); |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_browser, 1, one_menu_item2, true)); |
| |
| // Transferred browsers of other users should not show up in the list. |
| chrome::MultiUserWindowManager::GetInstance()->ShowWindowForUser( |
| browser()->window()->GetNativeWindow(), |
| user2); |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_browser, 1, one_menu_item2, true)); |
| |
| chrome::CloseTab(browser2.get()); |
| } |
| #endif // defined(OS_CHROMEOS) |
| |
| // Check that V1 apps are correctly reflected in the launcher menu using the |
| // refocus logic. |
| // Note that the extension matching logic is tested by the extension system |
| // and does not need a separate test here. |
| TEST_F(ChromeLauncherControllerTest, V1AppMenuGeneration) { |
| EXPECT_EQ(1U, chrome::GetTotalBrowserCount()); |
| EXPECT_EQ(0, browser()->tab_strip_model()->count()); |
| |
| InitLauncherControllerWithBrowser(); |
| |
| // Model should only contain the browser shortcut and app list items. |
| EXPECT_EQ(2, model_->item_count()); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned(extension3_->id())); |
| |
| // Installing |extension3_| adds it to the launcher. |
| ash::LauncherID gmail_id = model_->next_id(); |
| extension_service_->AddExtension(extension3_.get()); |
| EXPECT_EQ(3, model_->item_count()); |
| int gmail_index = model_->ItemIndexByID(gmail_id); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[gmail_index].type); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id())); |
| launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(gmail_url)); |
| |
| // Check the menu content. |
| ash::LauncherItem item_browser; |
| item_browser.type = ash::TYPE_BROWSER_SHORTCUT; |
| item_browser.id = |
| launcher_controller_->GetLauncherIDForAppID(extension_misc::kChromeAppId); |
| |
| ash::LauncherItem item_gmail; |
| item_gmail.type = ash::TYPE_APP_SHORTCUT; |
| item_gmail.id = gmail_id; |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_gmail, 0, NULL, false)); |
| |
| // Set the gmail URL to a new tab. |
| base::string16 title1 = ASCIIToUTF16("Test1"); |
| NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title1); |
| |
| base::string16 one_menu_item[] = { title1 }; |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_gmail, 1, one_menu_item, false)); |
| |
| // Create one empty tab. |
| chrome::NewTab(browser()); |
| base::string16 title2 = ASCIIToUTF16("Test2"); |
| NavigateAndCommitActiveTabWithTitle( |
| browser(), |
| GURL("https://bla"), |
| title2); |
| |
| // and another one with another gmail instance. |
| chrome::NewTab(browser()); |
| base::string16 title3 = ASCIIToUTF16("Test3"); |
| NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title3); |
| base::string16 two_menu_items[] = {title1, title3}; |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_gmail, 2, two_menu_items, false)); |
| |
| // Even though the item is in the V1 app list, it should also be in the |
| // browser list. |
| base::string16 browser_menu_item[] = {title3}; |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_browser, 1, browser_menu_item, false)); |
| |
| // Test that closing of (all) the item(s) does work (and all menus get |
| // updated properly). |
| launcher_controller_->Close(item_gmail.id); |
| |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_gmail, 0, NULL, false)); |
| base::string16 browser_menu_item2[] = { title2 }; |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_browser, 1, browser_menu_item2, false)); |
| } |
| |
| #if defined(OS_CHROMEOS) |
| // Check the multi profile case where only user related apps should show up. |
| TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest, |
| V1AppMenuGenerationTwoUsers) { |
| // Create a browser item in the LauncherController. |
| InitLauncherController(); |
| chrome::NewTab(browser()); |
| |
| // Installing |extension3_| adds it to the launcher. |
| ash::LauncherID gmail_id = model_->next_id(); |
| extension_service_->AddExtension(extension3_.get()); |
| EXPECT_EQ(3, model_->item_count()); |
| int gmail_index = model_->ItemIndexByID(gmail_id); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[gmail_index].type); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id())); |
| launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(gmail_url)); |
| |
| // Check the menu content. |
| ash::LauncherItem item_browser; |
| item_browser.type = ash::TYPE_BROWSER_SHORTCUT; |
| item_browser.id = |
| launcher_controller_->GetLauncherIDForAppID(extension_misc::kChromeAppId); |
| |
| ash::LauncherItem item_gmail; |
| item_gmail.type = ash::TYPE_APP_SHORTCUT; |
| item_gmail.id = gmail_id; |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_gmail, 0, NULL, false)); |
| |
| // Set the gmail URL to a new tab. |
| base::string16 title1 = ASCIIToUTF16("Test1"); |
| NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title1); |
| |
| base::string16 one_menu_item[] = { title1 }; |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_gmail, 1, one_menu_item, false)); |
| |
| // Create a second profile and switch to that user. |
| std::string user2 = "user2"; |
| TestingProfile* profile2 = CreateMultiUserProfile(user2); |
| SwitchActiveUser(profile2->GetProfileName()); |
| |
| // No item should have content yet. |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_browser, 0, NULL, true)); |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_gmail, 0, NULL, false)); |
| |
| // Transfer the browser of the first user - it should still not show up. |
| chrome::MultiUserWindowManager::GetInstance()->ShowWindowForUser( |
| browser()->window()->GetNativeWindow(), |
| user2); |
| |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_browser, 0, NULL, true)); |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_gmail, 0, NULL, false)); |
| } |
| |
| // Check that V2 applications are creating items properly in the launcher when |
| // instantiated by the current user. |
| TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest, |
| V2AppHandlingTwoUsers) { |
| InitLauncherController(); |
| // We need to create a dummy views delegate to be able to create a V2 app. |
| scoped_ptr<TestViewsDelegateForAppTest> views_delegate( |
| new TestViewsDelegateForAppTest()); |
| // Create a profile for our second user (will be destroyed by the framework). |
| TestingProfile* profile2 = CreateMultiUserProfile("user2"); |
| // Check that there is a browser and a app launcher. |
| EXPECT_EQ(2, model_->item_count()); |
| |
| // Add a v2 app. |
| V2App v2_app(profile(), extension1_); |
| EXPECT_EQ(3, model_->item_count()); |
| |
| // After switching users the item should go away. |
| SwitchActiveUser(profile2->GetProfileName()); |
| EXPECT_EQ(2, model_->item_count()); |
| |
| // And it should come back when switching back. |
| SwitchActiveUser(profile()->GetProfileName()); |
| EXPECT_EQ(3, model_->item_count()); |
| } |
| |
| // Check that V2 applications are creating items properly in edge cases: |
| // a background user creates a V2 app, gets active and inactive again and then |
| // deletes the app. |
| TEST_F(MultiProfileMultiBrowserShelfLayoutChromeLauncherControllerTest, |
| V2AppHandlingTwoUsersEdgeCases) { |
| InitLauncherController(); |
| // We need to create a dummy views delegate to be able to create a V2 app. |
| scoped_ptr<TestViewsDelegateForAppTest> views_delegate( |
| new TestViewsDelegateForAppTest()); |
| // Create a profile for our second user (will be destroyed by the framework). |
| TestingProfile* profile2 = CreateMultiUserProfile("user2"); |
| // Check that there is a browser and a app launcher. |
| EXPECT_EQ(2, model_->item_count()); |
| |
| // Switch to an inactive user. |
| SwitchActiveUser(profile2->GetProfileName()); |
| EXPECT_EQ(2, model_->item_count()); |
| |
| // Add the v2 app to the inactive user and check that no item was added to |
| // the launcher. |
| { |
| V2App v2_app(profile(), extension1_); |
| EXPECT_EQ(2, model_->item_count()); |
| |
| // Switch to the primary user and check that the item is shown. |
| SwitchActiveUser(profile()->GetProfileName()); |
| EXPECT_EQ(3, model_->item_count()); |
| |
| // Switch to the second user and check that the item goes away - even if the |
| // item gets closed. |
| SwitchActiveUser(profile2->GetProfileName()); |
| EXPECT_EQ(2, model_->item_count()); |
| } |
| |
| // After the application was killed there should be still 2 items. |
| EXPECT_EQ(2, model_->item_count()); |
| |
| // Switching then back to the default user should not show the additional item |
| // anymore. |
| SwitchActiveUser(profile()->GetProfileName()); |
| EXPECT_EQ(2, model_->item_count()); |
| } |
| #endif // defined(OS_CHROMEOS) |
| |
| // Checks that the generated menu list properly activates items. |
| TEST_F(ChromeLauncherControllerTest, V1AppMenuExecution) { |
| InitLauncherControllerWithBrowser(); |
| |
| // Add |extension3_| to the launcher and add two items. |
| GURL gmail = GURL("https://mail.google.com/mail/u"); |
| ash::LauncherID gmail_id = model_->next_id(); |
| extension_service_->AddExtension(extension3_.get()); |
| launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(gmail_url)); |
| base::string16 title1 = ASCIIToUTF16("Test1"); |
| NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title1); |
| chrome::NewTab(browser()); |
| base::string16 title2 = ASCIIToUTF16("Test2"); |
| NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title2); |
| |
| // Check that the menu is properly set. |
| ash::LauncherItem item_gmail; |
| item_gmail.type = ash::TYPE_APP_SHORTCUT; |
| item_gmail.id = gmail_id; |
| base::string16 two_menu_items[] = {title1, title2}; |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_gmail, 2, two_menu_items, false)); |
| EXPECT_EQ(1, browser()->tab_strip_model()->active_index()); |
| // Execute the second item in the list (which shouldn't do anything since that |
| // item is per definition already the active tab). |
| { |
| scoped_ptr<ash::ShelfMenuModel> menu(new LauncherApplicationMenuItemModel( |
| launcher_controller_->GetApplicationList(item_gmail, 0))); |
| // The first element in the menu is a spacing separator. On some systems |
| // (e.g. Windows) such things do not exist. As such we check the existence |
| // and adjust dynamically. |
| int first_item = |
| (menu->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR) ? 1 : 0; |
| menu->ActivatedAt(first_item + 3); |
| } |
| EXPECT_EQ(1, browser()->tab_strip_model()->active_index()); |
| |
| // Execute the first item. |
| { |
| scoped_ptr<ash::ShelfMenuModel> menu(new LauncherApplicationMenuItemModel( |
| launcher_controller_->GetApplicationList(item_gmail, 0))); |
| int first_item = |
| (menu->GetTypeAt(0) == ui::MenuModel::TYPE_SEPARATOR) ? 1 : 0; |
| menu->ActivatedAt(first_item + 2); |
| } |
| // Now the active tab should be the second item. |
| EXPECT_EQ(0, browser()->tab_strip_model()->active_index()); |
| } |
| |
| // Checks that the generated menu list properly deletes items. |
| TEST_F(ChromeLauncherControllerTest, V1AppMenuDeletionExecution) { |
| InitLauncherControllerWithBrowser(); |
| |
| // Add |extension3_| to the launcher and add two items. |
| GURL gmail = GURL("https://mail.google.com/mail/u"); |
| ash::LauncherID gmail_id = model_->next_id(); |
| extension_service_->AddExtension(extension3_.get()); |
| launcher_controller_->SetRefocusURLPatternForTest(gmail_id, GURL(gmail_url)); |
| base::string16 title1 = ASCIIToUTF16("Test1"); |
| NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title1); |
| chrome::NewTab(browser()); |
| base::string16 title2 = ASCIIToUTF16("Test2"); |
| NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title2); |
| |
| // Check that the menu is properly set. |
| ash::LauncherItem item_gmail; |
| item_gmail.type = ash::TYPE_APP_SHORTCUT; |
| item_gmail.id = gmail_id; |
| base::string16 two_menu_items[] = {title1, title2}; |
| EXPECT_TRUE(CheckMenuCreation( |
| launcher_controller_.get(), item_gmail, 2, two_menu_items, false)); |
| |
| int tabs = browser()->tab_strip_model()->count(); |
| // Activate the proper tab through the menu item. |
| { |
| ChromeLauncherAppMenuItems items = |
| launcher_controller_->GetApplicationList(item_gmail, 0); |
| items[1]->Execute(0); |
| EXPECT_EQ(tabs, browser()->tab_strip_model()->count()); |
| } |
| |
| // Delete one tab through the menu item. |
| { |
| ChromeLauncherAppMenuItems items = |
| launcher_controller_->GetApplicationList(item_gmail, 0); |
| items[1]->Execute(ui::EF_SHIFT_DOWN); |
| EXPECT_EQ(--tabs, browser()->tab_strip_model()->count()); |
| } |
| } |
| |
| // Tests that panels create launcher items correctly |
| TEST_F(ChromeLauncherControllerTest, AppPanels) { |
| InitLauncherControllerWithBrowser(); |
| // App list and Browser shortcut LauncherItems are added. |
| EXPECT_EQ(2, model_observer_->added()); |
| |
| TestAppIconLoaderImpl* app_icon_loader = new TestAppIconLoaderImpl(); |
| SetAppIconLoader(app_icon_loader); |
| |
| // Test adding an app panel |
| std::string app_id = extension1_->id(); |
| ShellWindowLauncherItemController* app_panel_controller = |
| new ShellWindowLauncherItemController( |
| LauncherItemController::TYPE_APP_PANEL, |
| "id", |
| app_id, |
| launcher_controller_.get()); |
| ash::LauncherID launcher_id1 = launcher_controller_->CreateAppLauncherItem( |
| app_panel_controller, app_id, ash::STATUS_RUNNING); |
| int panel_index = model_observer_->last_index(); |
| EXPECT_EQ(3, model_observer_->added()); |
| EXPECT_EQ(0, model_observer_->changed()); |
| EXPECT_EQ(1, app_icon_loader->fetch_count()); |
| model_observer_->clear_counts(); |
| |
| // App panels should have a separate identifier than the app id |
| EXPECT_EQ(0, launcher_controller_->GetLauncherIDForAppID(app_id)); |
| |
| // Setting the app image image should not change the panel if it set its icon |
| app_panel_controller->set_image_set_by_controller(true); |
| gfx::ImageSkia image; |
| launcher_controller_->SetAppImage(app_id, image); |
| EXPECT_EQ(0, model_observer_->changed()); |
| model_observer_->clear_counts(); |
| |
| // Add a second app panel and verify that it get the same index as the first |
| // one had, being added to the left of the existing panel. |
| ShellWindowLauncherItemController* app_panel_controller2 = |
| new ShellWindowLauncherItemController( |
| LauncherItemController::TYPE_APP_PANEL, |
| "id", |
| app_id, |
| launcher_controller_.get()); |
| |
| ash::LauncherID launcher_id2 = launcher_controller_->CreateAppLauncherItem( |
| app_panel_controller2, app_id, ash::STATUS_RUNNING); |
| EXPECT_EQ(panel_index, model_observer_->last_index()); |
| EXPECT_EQ(1, model_observer_->added()); |
| model_observer_->clear_counts(); |
| |
| launcher_controller_->CloseLauncherItem(launcher_id2); |
| launcher_controller_->CloseLauncherItem(launcher_id1); |
| EXPECT_EQ(2, model_observer_->removed()); |
| } |
| |
| // Tests that the Gmail extension matches more then the app itself claims with |
| // the manifest file. |
| TEST_F(ChromeLauncherControllerTest, GmailMatching) { |
| InitLauncherControllerWithBrowser(); |
| |
| // Create a Gmail browser tab. |
| chrome::NewTab(browser()); |
| base::string16 title = ASCIIToUTF16("Test"); |
| NavigateAndCommitActiveTabWithTitle(browser(), GURL(gmail_url), title); |
| content::WebContents* content = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| |
| // Check that the launcher controller does not recognize the running app. |
| EXPECT_FALSE(launcher_controller_->ContentCanBeHandledByGmailApp(content)); |
| |
| // Installing |extension3_| adds it to the launcher. |
| ash::LauncherID gmail_id = model_->next_id(); |
| extension_service_->AddExtension(extension3_.get()); |
| EXPECT_EQ(3, model_->item_count()); |
| int gmail_index = model_->ItemIndexByID(gmail_id); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[gmail_index].type); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id())); |
| |
| // Check that it is now handled. |
| EXPECT_TRUE(launcher_controller_->ContentCanBeHandledByGmailApp(content)); |
| |
| // Check also that the app has detected that properly. |
| ash::LauncherItem item_gmail; |
| item_gmail.type = ash::TYPE_APP_SHORTCUT; |
| item_gmail.id = gmail_id; |
| EXPECT_EQ(2U, launcher_controller_->GetApplicationList(item_gmail, 0).size()); |
| } |
| |
| // Tests that the Gmail extension does not match the offline verison. |
| TEST_F(ChromeLauncherControllerTest, GmailOfflineMatching) { |
| InitLauncherControllerWithBrowser(); |
| |
| // Create a Gmail browser tab. |
| chrome::NewTab(browser()); |
| base::string16 title = ASCIIToUTF16("Test"); |
| NavigateAndCommitActiveTabWithTitle(browser(), |
| GURL(offline_gmail_url), |
| title); |
| content::WebContents* content = |
| browser()->tab_strip_model()->GetActiveWebContents(); |
| |
| // Installing |extension3_| adds it to the launcher. |
| ash::LauncherID gmail_id = model_->next_id(); |
| extension_service_->AddExtension(extension3_.get()); |
| EXPECT_EQ(3, model_->item_count()); |
| int gmail_index = model_->ItemIndexByID(gmail_id); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[gmail_index].type); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned(extension3_->id())); |
| |
| // The content should not be able to be handled by the app. |
| EXPECT_FALSE(launcher_controller_->ContentCanBeHandledByGmailApp(content)); |
| } |
| |
| // Verify that the launcher item positions are persisted and restored. |
| TEST_F(ChromeLauncherControllerTest, PersistLauncherItemPositions) { |
| InitLauncherController(); |
| |
| TestAppTabHelperImpl* app_tab_helper = new TestAppTabHelperImpl; |
| SetAppTabHelper(app_tab_helper); |
| |
| EXPECT_EQ(ash::TYPE_APP_LIST, model_->items()[0].type); |
| EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT, model_->items()[1].type); |
| |
| TabStripModel* tab_strip_model = browser()->tab_strip_model(); |
| EXPECT_EQ(0, tab_strip_model->count()); |
| chrome::NewTab(browser()); |
| chrome::NewTab(browser()); |
| EXPECT_EQ(2, tab_strip_model->count()); |
| app_tab_helper->SetAppID(tab_strip_model->GetWebContentsAt(0), "1"); |
| app_tab_helper->SetAppID(tab_strip_model->GetWebContentsAt(1), "2"); |
| |
| EXPECT_FALSE(launcher_controller_->IsAppPinned("1")); |
| launcher_controller_->PinAppWithID("1"); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned("1")); |
| launcher_controller_->PinAppWithID("2"); |
| |
| EXPECT_EQ(ash::TYPE_APP_LIST, model_->items()[0].type); |
| EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT, model_->items()[1].type); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[3].type); |
| |
| // Move browser shortcut item from index 1 to index 3. |
| model_->Move(1, 3); |
| EXPECT_EQ(ash::TYPE_APP_LIST, model_->items()[0].type); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[1].type); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type); |
| EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT, model_->items()[3].type); |
| |
| launcher_controller_.reset(); |
| if (!ash::Shell::HasInstance()) { |
| delete item_delegate_manager_; |
| } else { |
| // Clear already registered ShelfItemDelegate. |
| ash::test::ShelfItemDelegateManagerTestAPI test(item_delegate_manager_); |
| test.RemoveAllShelfItemDelegateForTest(); |
| } |
| model_.reset(new ash::ShelfModel); |
| |
| AddAppListLauncherItem(); |
| launcher_controller_.reset( |
| ChromeLauncherController::CreateInstance(profile(), model_.get())); |
| app_tab_helper = new TestAppTabHelperImpl; |
| app_tab_helper->SetAppID(tab_strip_model->GetWebContentsAt(0), "1"); |
| app_tab_helper->SetAppID(tab_strip_model->GetWebContentsAt(1), "2"); |
| SetAppTabHelper(app_tab_helper); |
| if (!ash::Shell::HasInstance()) { |
| item_delegate_manager_ = new ash::ShelfItemDelegateManager(model_.get()); |
| SetShelfItemDelegateManager(item_delegate_manager_); |
| } |
| launcher_controller_->Init(); |
| |
| // Check LauncherItems are restored after resetting ChromeLauncherController. |
| EXPECT_EQ(ash::TYPE_APP_LIST, model_->items()[0].type); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[1].type); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[2].type); |
| EXPECT_EQ(ash::TYPE_BROWSER_SHORTCUT, model_->items()[3].type); |
| } |
| |
| // Verifies pinned apps are persisted and restored. |
| TEST_F(ChromeLauncherControllerTest, PersistPinned) { |
| InitLauncherControllerWithBrowser(); |
| size_t initial_size = model_->items().size(); |
| |
| TabStripModel* tab_strip_model = browser()->tab_strip_model(); |
| EXPECT_EQ(1, tab_strip_model->count()); |
| |
| TestAppTabHelperImpl* app_tab_helper = new TestAppTabHelperImpl; |
| app_tab_helper->SetAppID(tab_strip_model->GetWebContentsAt(0), "1"); |
| SetAppTabHelper(app_tab_helper); |
| |
| TestAppIconLoaderImpl* app_icon_loader = new TestAppIconLoaderImpl; |
| SetAppIconLoader(app_icon_loader); |
| EXPECT_EQ(0, app_icon_loader->fetch_count()); |
| |
| launcher_controller_->PinAppWithID("1"); |
| ash::LauncherID id = launcher_controller_->GetLauncherIDForAppID("1"); |
| int app_index = model_->ItemIndexByID(id); |
| EXPECT_EQ(1, app_icon_loader->fetch_count()); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[app_index].type); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned("1")); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned("0")); |
| EXPECT_EQ(initial_size + 1, model_->items().size()); |
| |
| launcher_controller_.reset(); |
| if (!ash::Shell::HasInstance()) { |
| delete item_delegate_manager_; |
| } else { |
| // Clear already registered ShelfItemDelegate. |
| ash::test::ShelfItemDelegateManagerTestAPI test(item_delegate_manager_); |
| test.RemoveAllShelfItemDelegateForTest(); |
| } |
| model_.reset(new ash::ShelfModel); |
| |
| AddAppListLauncherItem(); |
| launcher_controller_.reset( |
| ChromeLauncherController::CreateInstance(profile(), model_.get())); |
| app_tab_helper = new TestAppTabHelperImpl; |
| app_tab_helper->SetAppID(tab_strip_model->GetWebContentsAt(0), "1"); |
| SetAppTabHelper(app_tab_helper); |
| app_icon_loader = new TestAppIconLoaderImpl; |
| SetAppIconLoader(app_icon_loader); |
| if (!ash::Shell::HasInstance()) { |
| item_delegate_manager_ = new ash::ShelfItemDelegateManager(model_.get()); |
| SetShelfItemDelegateManager(item_delegate_manager_); |
| } |
| launcher_controller_->Init(); |
| |
| EXPECT_EQ(1, app_icon_loader->fetch_count()); |
| ASSERT_EQ(initial_size + 1, model_->items().size()); |
| EXPECT_TRUE(launcher_controller_->IsAppPinned("1")); |
| EXPECT_FALSE(launcher_controller_->IsAppPinned("0")); |
| EXPECT_EQ(ash::TYPE_APP_SHORTCUT, model_->items()[app_index].type); |
| |
| launcher_controller_->UnpinAppWithID("1"); |
| ASSERT_EQ(initial_size, model_->items().size()); |
| } |