app_list_controller_browsertest.cc revision f2477e01787aa58f445919b809d89e252beef54f
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 "base/command_line.h" 6#include "base/file_util.h" 7#include "base/memory/scoped_ptr.h" 8#include "base/message_loop/message_loop.h" 9#include "base/path_service.h" 10#include "base/prefs/pref_service.h" 11#include "base/strings/utf_string_conversions.h" 12#include "chrome/browser/browser_process.h" 13#include "chrome/browser/extensions/extension_browsertest.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/app_list_service.h" 18#include "chrome/browser/ui/app_list/app_list_syncable_service.h" 19#include "chrome/browser/ui/app_list/app_list_syncable_service_factory.h" 20#include "chrome/browser/ui/browser.h" 21#include "chrome/browser/ui/browser_finder.h" 22#include "chrome/browser/ui/host_desktop.h" 23#include "chrome/common/chrome_paths.h" 24#include "chrome/common/chrome_switches.h" 25#include "chrome/common/pref_names.h" 26#include "chrome/test/base/in_process_browser_test.h" 27#include "chrome/test/base/ui_test_utils.h" 28#include "ui/app_list/app_list_model.h" 29#include "ui/app_list/search_box_model.h" 30#include "ui/app_list/search_result.h" 31#include "ui/app_list/search_result_observer.h" 32#include "ui/base/models/list_model_observer.h" 33 34namespace { 35 36app_list::AppListModel* GetAppListModel(AppListService* service) { 37 return app_list::AppListSyncableServiceFactory::GetForProfile( 38 service->GetCurrentAppListProfile())->model(); 39} 40 41AppListService* GetAppListService() { 42 // TODO(tapted): Consider testing ash explicitly on the win-ash trybot. 43 return AppListService::Get(chrome::GetActiveDesktop()); 44} 45 46} // namespace 47 48// Browser Test for AppListController that runs on all platforms supporting 49// app_list. 50class AppListControllerBrowserTest : public InProcessBrowserTest { 51 public: 52 AppListControllerBrowserTest() 53 : profile2_(NULL) {} 54 55 void InitSecondProfile() { 56 ProfileManager* profile_manager = g_browser_process->profile_manager(); 57 base::FilePath temp_profile_dir = 58 profile_manager->user_data_dir().AppendASCII("Profile 1"); 59 profile_manager->CreateProfileAsync( 60 temp_profile_dir, 61 base::Bind(&AppListControllerBrowserTest::OnProfileCreated, 62 this), 63 string16(), string16(), std::string()); 64 content::RunMessageLoop(); // Will stop in OnProfileCreated(). 65 } 66 67 void OnProfileCreated(Profile* profile, Profile::CreateStatus status) { 68 if (status == Profile::CREATE_STATUS_INITIALIZED) { 69 profile2_ = profile; 70 base::MessageLoop::current()->Quit(); 71 } 72 } 73 74 protected: 75 Profile* profile2_; 76 77 private: 78 DISALLOW_COPY_AND_ASSIGN(AppListControllerBrowserTest); 79}; 80 81// TODO(mgiuca): Enable on Linux when supported. 82#if defined(OS_LINUX) && !defined(OS_CHROMEOS) 83#define MAYBE_CreateNewWindow DISABLED_CreateNewWindow 84#else 85#define MAYBE_CreateNewWindow CreateNewWindow 86#endif 87 88// Test the CreateNewWindow function of the controller delegate. 89IN_PROC_BROWSER_TEST_F(AppListControllerBrowserTest, MAYBE_CreateNewWindow) { 90 const chrome::HostDesktopType desktop = chrome::GetActiveDesktop(); 91 AppListService* service = GetAppListService(); 92 AppListControllerDelegate* controller(service->GetControllerDelegate()); 93 ASSERT_TRUE(controller); 94 95 EXPECT_EQ(1U, chrome::GetBrowserCount(browser()->profile(), desktop)); 96 EXPECT_EQ(0U, chrome::GetBrowserCount( 97 browser()->profile()->GetOffTheRecordProfile(), desktop)); 98 99 controller->CreateNewWindow(browser()->profile(), false); 100 EXPECT_EQ(2U, chrome::GetBrowserCount(browser()->profile(), desktop)); 101 102 controller->CreateNewWindow(browser()->profile(), true); 103 EXPECT_EQ(1U, chrome::GetBrowserCount( 104 browser()->profile()->GetOffTheRecordProfile(), desktop)); 105} 106 107// TODO(mgiuca): Enable on Linux/ChromeOS when supported. 108#if defined(OS_LINUX) 109#define MAYBE_ShowAndDismiss DISABLED_ShowAndDismiss 110#define MAYBE_SwitchAppListProfiles DISABLED_SwitchAppListProfiles 111#define MAYBE_SwitchAppListProfilesDuringSearch \ 112 DISABLED_SwitchAppListProfilesDuringSearch 113#else 114#define MAYBE_ShowAndDismiss ShowAndDismiss 115#define MAYBE_SwitchAppListProfiles SwitchAppListProfiles 116#define MAYBE_SwitchAppListProfilesDuringSearch \ 117 SwitchAppListProfilesDuringSearch 118#endif 119 120// Show the app list, then dismiss it. 121IN_PROC_BROWSER_TEST_F(AppListControllerBrowserTest, MAYBE_ShowAndDismiss) { 122 AppListService* service = GetAppListService(); 123 ASSERT_FALSE(service->IsAppListVisible()); 124 service->ShowForProfile(browser()->profile()); 125 ASSERT_TRUE(service->IsAppListVisible()); 126 service->DismissAppList(); 127 ASSERT_FALSE(service->IsAppListVisible()); 128} 129 130IN_PROC_BROWSER_TEST_F(AppListControllerBrowserTest, 131 MAYBE_SwitchAppListProfiles) { 132 InitSecondProfile(); 133 134 AppListService* service = GetAppListService(); 135 ASSERT_TRUE(service); 136 137 AppListControllerDelegate* controller(service->GetControllerDelegate()); 138 ASSERT_TRUE(controller); 139 140 // Open the app list with the browser's profile. 141 ASSERT_FALSE(service->IsAppListVisible()); 142 controller->ShowForProfileByPath(browser()->profile()->GetPath()); 143 app_list::AppListModel* model = GetAppListModel(service); 144 ASSERT_TRUE(model); 145 model->SetSignedIn(true); 146 base::RunLoop().RunUntilIdle(); 147 148 ASSERT_TRUE(service->IsAppListVisible()); 149 ASSERT_EQ(browser()->profile(), service->GetCurrentAppListProfile()); 150 151 // Open the app list with the second profile. 152 controller->ShowForProfileByPath(profile2_->GetPath()); 153 model = GetAppListModel(service); 154 ASSERT_TRUE(model); 155 model->SetSignedIn(true); 156 base::RunLoop().RunUntilIdle(); 157 158 ASSERT_TRUE(service->IsAppListVisible()); 159 ASSERT_EQ(profile2_, service->GetCurrentAppListProfile()); 160 161 controller->DismissView(); 162} 163 164IN_PROC_BROWSER_TEST_F(AppListControllerBrowserTest, 165 MAYBE_SwitchAppListProfilesDuringSearch) { 166 InitSecondProfile(); 167 168 AppListService* service = GetAppListService(); 169 ASSERT_TRUE(service); 170 171 AppListControllerDelegate* controller(service->GetControllerDelegate()); 172 ASSERT_TRUE(controller); 173 174 // Set a search with original profile. 175 controller->ShowForProfileByPath(browser()->profile()->GetPath()); 176 app_list::AppListModel* model = GetAppListModel(service); 177 ASSERT_TRUE(model); 178 model->SetSignedIn(true); 179 model->search_box()->SetText(ASCIIToUTF16("minimal")); 180 base::RunLoop().RunUntilIdle(); 181 182 // Switch to the second profile. 183 controller->ShowForProfileByPath(profile2_->GetPath()); 184 model = GetAppListModel(service); 185 ASSERT_TRUE(model); 186 model->SetSignedIn(true); 187 base::RunLoop().RunUntilIdle(); 188 189 // Ensure the search box is empty. 190 ASSERT_TRUE(model->search_box()->text().empty()); 191 ASSERT_EQ(profile2_, service->GetCurrentAppListProfile()); 192 193 controller->DismissView(); 194 ASSERT_FALSE(service->IsAppListVisible()); 195} 196 197class ShowAppListBrowserTest : public InProcessBrowserTest { 198 public: 199 ShowAppListBrowserTest() {} 200 201 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 202 command_line->AppendSwitch(switches::kShowAppList); 203 } 204 205 private: 206 DISALLOW_COPY_AND_ASSIGN(ShowAppListBrowserTest); 207}; 208 209// See http://crbug.com/315677 210#if defined(OS_WIN) 211#define MAYBE_ShowAppListFlag DISABLED_ShowAppListFlag 212#else 213#define MAYBE_ShowAppListFlag ShowAppListFlag 214#endif 215 216IN_PROC_BROWSER_TEST_F(ShowAppListBrowserTest, MAYBE_ShowAppListFlag) { 217 AppListService* service = GetAppListService(); 218 // The app list should already be shown because we passed 219 // switches::kShowAppList. 220 ASSERT_TRUE(service->IsAppListVisible()); 221 222 // Create a browser to prevent shutdown when we dismiss the app list. We 223 // need to do this because switches::kShowAppList suppresses the creation of 224 // any browsers. 225 CreateBrowser(service->GetCurrentAppListProfile()); 226 service->DismissAppList(); 227} 228 229// Browser Test for AppListController that observes search result changes. 230class AppListControllerSearchResultsBrowserTest 231 : public ExtensionBrowserTest, 232 public app_list::SearchResultObserver, 233 public ui::ListModelObserver { 234 public: 235 AppListControllerSearchResultsBrowserTest() 236 : observed_result_(NULL), 237 item_uninstall_count_(0), 238 observed_results_list_(NULL) {} 239 240 void WatchResultsLookingForItem( 241 app_list::AppListModel::SearchResults* search_results, 242 const std::string& extension_name) { 243 EXPECT_FALSE(observed_results_list_); 244 observed_results_list_ = search_results; 245 observed_results_list_->AddObserver(this); 246 item_to_observe_ = ASCIIToUTF16(extension_name); 247 } 248 249 void StopWatchingResults() { 250 EXPECT_TRUE(observed_results_list_); 251 observed_results_list_->RemoveObserver(this); 252 } 253 254 protected: 255 void AttemptToLocateItem() { 256 if (observed_result_) { 257 observed_result_->RemoveObserver(this); 258 observed_result_ = NULL; 259 } 260 261 for (size_t i = 0; i < observed_results_list_->item_count(); ++i) { 262 if (observed_results_list_->GetItemAt(i)->title() != item_to_observe_) 263 continue; 264 265 // Ensure there is at most one. 266 EXPECT_FALSE(observed_result_); 267 observed_result_ = observed_results_list_->GetItemAt(i); 268 } 269 270 if (observed_result_) 271 observed_result_->AddObserver(this); 272 } 273 274 // Overridden from SearchResultObserver: 275 virtual void OnIconChanged() OVERRIDE {} 276 virtual void OnActionsChanged() OVERRIDE {} 277 virtual void OnIsInstallingChanged() OVERRIDE {} 278 virtual void OnPercentDownloadedChanged() OVERRIDE {} 279 virtual void OnItemInstalled() OVERRIDE {} 280 virtual void OnItemUninstalled() OVERRIDE { 281 ++item_uninstall_count_; 282 EXPECT_TRUE(observed_result_); 283 } 284 285 // Overridden from ui::ListModelObserver: 286 virtual void ListItemsAdded(size_t start, size_t count) OVERRIDE { 287 AttemptToLocateItem(); 288 } 289 virtual void ListItemsRemoved(size_t start, size_t count) OVERRIDE { 290 AttemptToLocateItem(); 291 } 292 virtual void ListItemMoved(size_t index, size_t target_index) OVERRIDE {} 293 virtual void ListItemsChanged(size_t start, size_t count) OVERRIDE {} 294 295 app_list::SearchResult* observed_result_; 296 int item_uninstall_count_; 297 298 private: 299 base::string16 item_to_observe_; 300 app_list::AppListModel::SearchResults* observed_results_list_; 301 302 DISALLOW_COPY_AND_ASSIGN(AppListControllerSearchResultsBrowserTest); 303}; 304 305// TODO(mgiuca): Enable on Linux when supported. 306#if defined(OS_LINUX) && !defined(OS_CHROMEOS) 307#define MAYBE_UninstallSearchResult DISABLED_UninstallSearchResult 308#else 309#define MAYBE_UninstallSearchResult UninstallSearchResult 310#endif 311 312// Test showing search results, and uninstalling one of them while displayed. 313IN_PROC_BROWSER_TEST_F(AppListControllerSearchResultsBrowserTest, 314 UninstallSearchResult) { 315 base::FilePath test_extension_path; 316 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_extension_path)); 317 test_extension_path = test_extension_path.AppendASCII("extensions") 318 .AppendASCII("platform_apps") 319 .AppendASCII("minimal"); 320 const extensions::Extension* extension = 321 InstallExtension(test_extension_path, 322 1 /* expected_change: new install */); 323 ASSERT_TRUE(extension); 324 325 AppListService* service = GetAppListService(); 326 ASSERT_TRUE(service); 327 service->ShowForProfile(browser()->profile()); 328 329 app_list::AppListModel* model = GetAppListModel(service); 330 ASSERT_TRUE(model); 331 model->SetSignedIn(true); 332 WatchResultsLookingForItem(model->results(), extension->name()); 333 334 // Ensure a search finds the extension. 335 EXPECT_FALSE(observed_result_); 336 model->search_box()->SetText(ASCIIToUTF16("minimal")); 337 EXPECT_TRUE(observed_result_); 338 339 // Ensure the UI is updated. This is via PostTask in views. 340 base::RunLoop().RunUntilIdle(); 341 342 // Now uninstall and ensure this browser test observes it. 343 EXPECT_EQ(0, item_uninstall_count_); 344 UninstallExtension(extension->id()); 345 EXPECT_EQ(1, item_uninstall_count_); 346 347 // Results should not be immediately refreshed. When they are, the item should 348 // be removed from the model. 349 EXPECT_TRUE(observed_result_); 350 base::RunLoop().RunUntilIdle(); 351 EXPECT_FALSE(observed_result_); 352 StopWatchingResults(); 353 service->DismissAppList(); 354} 355