1// Copyright 2013 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/app_list/app_list_service.h" 6 7#include "base/command_line.h" 8#include "base/json/json_file_value_serializer.h" 9#include "base/memory/scoped_ptr.h" 10#include "base/message_loop/message_loop.h" 11#include "base/path_service.h" 12#include "base/strings/utf_string_conversions.h" 13#include "chrome/browser/browser_process.h" 14#include "chrome/browser/profiles/profile.h" 15#include "chrome/browser/profiles/profile_manager.h" 16#include "chrome/browser/ui/app_list/app_list_controller_delegate.h" 17#include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h" 18#include "chrome/browser/ui/browser.h" 19#include "chrome/browser/ui/host_desktop.h" 20#include "chrome/browser/ui/startup/startup_browser_creator.h" 21#include "chrome/common/chrome_constants.h" 22#include "chrome/common/chrome_paths.h" 23#include "chrome/common/chrome_switches.h" 24#include "chrome/common/pref_names.h" 25#include "chrome/test/base/in_process_browser_test.h" 26#include "chrome/test/base/ui_test_utils.h" 27#include "ui/app_list/app_list_model.h" 28#include "ui/app_list/search_box_model.h" 29 30// Interactive UI Test for AppListService that runs on all platforms supporting 31// app_list. Interactive because the app list uses focus changes to dismiss 32// itself, which will cause tests that check the visibility to fail flakily. 33class AppListServiceInteractiveTest : public InProcessBrowserTest { 34 public: 35 AppListServiceInteractiveTest() 36 : profile2_(NULL) {} 37 38 void InitSecondProfile() { profile2_ = test::CreateSecondProfileAsync(); } 39 40 protected: 41 Profile* profile2_; 42 43 private: 44 DISALLOW_COPY_AND_ASSIGN(AppListServiceInteractiveTest); 45}; 46 47// ChromeOS does not support ShowForProfile(), or profile switching within the 48// app list. Profile switching on CrOS goes through a different code path. 49#if defined(OS_CHROMEOS) 50#define MAYBE_ShowAndDismiss DISABLED_ShowAndDismiss 51#define MAYBE_SwitchAppListProfiles DISABLED_SwitchAppListProfiles 52#define MAYBE_SwitchAppListProfilesDuringSearch \ 53 DISABLED_SwitchAppListProfilesDuringSearch 54#define MAYBE_ShowAppListNonDefaultProfile \ 55 DISABLED_ShowAppListNonDefaultProfile 56#define MAYBE_DeleteShowingAppList DISABLED_DeleteShowingAppList 57#else 58#define MAYBE_ShowAndDismiss ShowAndDismiss 59#define MAYBE_SwitchAppListProfiles SwitchAppListProfiles 60#define MAYBE_SwitchAppListProfilesDuringSearch \ 61 SwitchAppListProfilesDuringSearch 62#define MAYBE_ShowAppListNonDefaultProfile ShowAppListNonDefaultProfile 63#define MAYBE_DeleteShowingAppList DeleteShowingAppList 64#endif 65 66// Show the app list, then dismiss it. 67IN_PROC_BROWSER_TEST_F(AppListServiceInteractiveTest, MAYBE_ShowAndDismiss) { 68 AppListService* service = test::GetAppListService(); 69 ASSERT_FALSE(service->IsAppListVisible()); 70 service->ShowForProfile(browser()->profile()); 71 ASSERT_TRUE(service->IsAppListVisible()); 72 service->DismissAppList(); 73 ASSERT_FALSE(service->IsAppListVisible()); 74} 75 76// Switch profiles on the app list while it is showing. 77IN_PROC_BROWSER_TEST_F(AppListServiceInteractiveTest, 78 MAYBE_SwitchAppListProfiles) { 79 InitSecondProfile(); 80 81 AppListService* service = test::GetAppListService(); 82 ASSERT_TRUE(service); 83 84 AppListControllerDelegate* controller(service->GetControllerDelegate()); 85 ASSERT_TRUE(controller); 86 87 // Open the app list with the browser's profile. 88 ASSERT_FALSE(service->IsAppListVisible()); 89 controller->ShowForProfileByPath(browser()->profile()->GetPath()); 90 app_list::AppListModel* model = test::GetAppListModel(service); 91 ASSERT_TRUE(model); 92 93 base::RunLoop().RunUntilIdle(); 94 95 ASSERT_TRUE(service->IsAppListVisible()); 96 ASSERT_EQ(browser()->profile(), service->GetCurrentAppListProfile()); 97 98 // Open the app list with the second profile. 99 controller->ShowForProfileByPath(profile2_->GetPath()); 100 model = test::GetAppListModel(service); 101 ASSERT_TRUE(model); 102 base::RunLoop().RunUntilIdle(); 103 104 ASSERT_TRUE(service->IsAppListVisible()); 105 ASSERT_EQ(profile2_, service->GetCurrentAppListProfile()); 106 107 controller->DismissView(); 108} 109 110// Test switching app list profiles while search results are visibile. 111IN_PROC_BROWSER_TEST_F(AppListServiceInteractiveTest, 112 MAYBE_SwitchAppListProfilesDuringSearch) { 113 InitSecondProfile(); 114 115 AppListService* service = test::GetAppListService(); 116 ASSERT_TRUE(service); 117 118 AppListControllerDelegate* controller(service->GetControllerDelegate()); 119 ASSERT_TRUE(controller); 120 121 // Set a search with original profile. 122 controller->ShowForProfileByPath(browser()->profile()->GetPath()); 123 app_list::AppListModel* model = test::GetAppListModel(service); 124 ASSERT_TRUE(model); 125 126 model->search_box()->SetText(base::ASCIIToUTF16("minimal")); 127 base::RunLoop().RunUntilIdle(); 128 129 // Switch to the second profile. 130 controller->ShowForProfileByPath(profile2_->GetPath()); 131 model = test::GetAppListModel(service); 132 ASSERT_TRUE(model); 133 base::RunLoop().RunUntilIdle(); 134 135 // Ensure the search box is empty. 136 ASSERT_TRUE(model->search_box()->text().empty()); 137 ASSERT_EQ(profile2_, service->GetCurrentAppListProfile()); 138 139 controller->DismissView(); 140 ASSERT_FALSE(service->IsAppListVisible()); 141} 142 143// Interactive UI test that adds the --show-app-list command line switch. 144class ShowAppListInteractiveTest : public InProcessBrowserTest { 145 public: 146 ShowAppListInteractiveTest() {} 147 148 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 149 command_line->AppendSwitch(switches::kShowAppList); 150 } 151 152 private: 153 DISALLOW_COPY_AND_ASSIGN(ShowAppListInteractiveTest); 154}; 155 156// Test showing the app list using the command line switch. 157#if defined(OS_CHROMEOS) 158// http://crbug.com/396499 159#define MAYBE_ShowAppListFlag DISABLED_ShowAppListFlag 160#else 161#define MAYBE_ShowAppListFlag ShowAppListFlag 162#endif 163IN_PROC_BROWSER_TEST_F(ShowAppListInteractiveTest, MAYBE_ShowAppListFlag) { 164 AppListService* service = test::GetAppListService(); 165 // The app list should already be shown because we passed 166 // switches::kShowAppList. 167 EXPECT_TRUE(service->IsAppListVisible()); 168 169 // Create a browser to prevent shutdown when we dismiss the app list. We 170 // need to do this because switches::kShowAppList suppresses the creation of 171 // any browsers. 172 Profile* profile = service->GetCurrentAppListProfile(); 173 CreateBrowser(profile); 174 175 service->DismissAppList(); 176 EXPECT_FALSE(service->IsAppListVisible()); 177 178 // With Chrome still running, test receiving a second --show-app-list request 179 // via the process singleton. ChromeOS has no process singleton so exclude it. 180#if !defined(OS_CHROMEOS) 181 CommandLine command_line(CommandLine::NO_PROGRAM); 182 command_line.AppendSwitch(switches::kShowAppList); 183 StartupBrowserCreator::ProcessCommandLineAlreadyRunning( 184 command_line, base::FilePath(), profile->GetPath()); 185 186 EXPECT_TRUE(service->IsAppListVisible()); 187 service->DismissAppList(); 188 EXPECT_FALSE(service->IsAppListVisible()); 189#endif 190} 191 192// Interactive UI test that creates a non-default profile and configures it for 193// the --show-app-list flag. 194class ShowAppListNonDefaultInteractiveTest : public ShowAppListInteractiveTest { 195 public: 196 ShowAppListNonDefaultInteractiveTest() 197 : second_profile_name_(FILE_PATH_LITERAL("Profile 1")) { 198 } 199 200 virtual bool SetUpUserDataDirectory() OVERRIDE { 201 // Create a temp dir for "Profile 1" and seed the user data dir with a Local 202 // State file configuring the app list to use it. 203 base::FilePath user_data_dir; 204 CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)); 205 base::FilePath profile_path = user_data_dir.Append(second_profile_name_); 206 CHECK(second_profile_temp_dir_.Set(profile_path)); 207 208 base::FilePath local_pref_path = 209 user_data_dir.Append(chrome::kLocalStateFilename); 210 base::DictionaryValue dict; 211 dict.SetString(prefs::kAppListProfile, 212 second_profile_name_.MaybeAsASCII()); 213 CHECK(JSONFileValueSerializer(local_pref_path).Serialize(dict)); 214 215 return InProcessBrowserTest::SetUpUserDataDirectory(); 216 } 217 218 protected: 219 const base::FilePath second_profile_name_; 220 base::ScopedTempDir second_profile_temp_dir_; 221 222 private: 223 DISALLOW_COPY_AND_ASSIGN(ShowAppListNonDefaultInteractiveTest); 224}; 225 226// Test showing the app list for a profile that doesn't match the browser 227// profile. 228IN_PROC_BROWSER_TEST_F(ShowAppListNonDefaultInteractiveTest, 229 MAYBE_ShowAppListNonDefaultProfile) { 230 AppListService* service = test::GetAppListService(); 231 EXPECT_TRUE(service->IsAppListVisible()); 232 EXPECT_EQ(second_profile_name_.value(), 233 service->GetCurrentAppListProfile()->GetPath().BaseName().value()); 234 235 // Check that the default profile hasn't been loaded. 236 ProfileManager* profile_manager = g_browser_process->profile_manager(); 237 EXPECT_EQ(1u, profile_manager->GetNumberOfProfiles()); 238 239 // Create a browser for the Default profile. This stops MaybeTeminate being 240 // called when the app list window is dismissed. Use the last used browser 241 // profile to verify that it is different and causes ProfileManager to load a 242 // new profile. 243 CreateBrowser(profile_manager->GetLastUsedProfile()); 244 EXPECT_EQ(2u, profile_manager->GetNumberOfProfiles()); 245 246 service->DismissAppList(); 247} 248 249// Test showing the app list for a profile then deleting that profile while the 250// app list is visible. 251IN_PROC_BROWSER_TEST_F(ShowAppListNonDefaultInteractiveTest, 252 MAYBE_DeleteShowingAppList) { 253 AppListService* service = test::GetAppListService(); 254 EXPECT_TRUE(service->IsAppListVisible()); 255 EXPECT_EQ(second_profile_name_.value(), 256 service->GetCurrentAppListProfile()->GetPath().BaseName().value()); 257 258 ProfileManager* profile_manager = g_browser_process->profile_manager(); 259 260 // Create a browser for the Default profile. 261 CreateBrowser(profile_manager->GetLastUsedProfile()); 262 263 // Delete the profile being used by the app list. 264 profile_manager->ScheduleProfileForDeletion( 265 service->GetCurrentAppListProfile()->GetPath(), 266 ProfileManager::CreateCallback()); 267 268 // App Launcher should get closed immediately and nothing should explode. 269 EXPECT_FALSE(service->IsAppListVisible()); 270} 271