app_list_service_interactive_uitest.cc revision 5f1c94371a64b3196d4be9466099bb892df9b88e
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() {
39    ProfileManager* profile_manager = g_browser_process->profile_manager();
40    base::FilePath temp_profile_dir =
41        profile_manager->user_data_dir().AppendASCII("Profile 1");
42    profile_manager->CreateProfileAsync(
43        temp_profile_dir,
44        base::Bind(&AppListServiceInteractiveTest::OnProfileCreated,
45                   this),
46        base::string16(), base::string16(), std::string());
47    content::RunMessageLoop();  // Will stop in OnProfileCreated().
48  }
49
50  void OnProfileCreated(Profile* profile, Profile::CreateStatus status) {
51    if (status == Profile::CREATE_STATUS_INITIALIZED) {
52      profile2_ = profile;
53      base::MessageLoop::current()->Quit();
54    }
55  }
56
57 protected:
58  Profile* profile2_;
59
60 private:
61  DISALLOW_COPY_AND_ASSIGN(AppListServiceInteractiveTest);
62};
63
64// ChromeOS does not support ShowForProfile(), or profile switching within the
65// app list. Profile switching on CrOS goes through a different code path.
66#if defined(OS_CHROMEOS)
67#define MAYBE_ShowAndDismiss DISABLED_ShowAndDismiss
68#define MAYBE_SwitchAppListProfiles DISABLED_SwitchAppListProfiles
69#define MAYBE_SwitchAppListProfilesDuringSearch \
70    DISABLED_SwitchAppListProfilesDuringSearch
71#define MAYBE_ShowAppListNonDefaultProfile \
72    DISABLED_ShowAppListNonDefaultProfile
73#else
74#define MAYBE_ShowAndDismiss ShowAndDismiss
75#define MAYBE_SwitchAppListProfiles SwitchAppListProfiles
76#define MAYBE_SwitchAppListProfilesDuringSearch \
77    SwitchAppListProfilesDuringSearch
78#define MAYBE_ShowAppListNonDefaultProfile ShowAppListNonDefaultProfile
79#endif
80
81// Show the app list, then dismiss it.
82IN_PROC_BROWSER_TEST_F(AppListServiceInteractiveTest, MAYBE_ShowAndDismiss) {
83  AppListService* service = test::GetAppListService();
84  ASSERT_FALSE(service->IsAppListVisible());
85  service->ShowForProfile(browser()->profile());
86  ASSERT_TRUE(service->IsAppListVisible());
87  service->DismissAppList();
88  ASSERT_FALSE(service->IsAppListVisible());
89}
90
91// Switch profiles on the app list while it is showing.
92IN_PROC_BROWSER_TEST_F(AppListServiceInteractiveTest,
93                       MAYBE_SwitchAppListProfiles) {
94  InitSecondProfile();
95
96  AppListService* service = test::GetAppListService();
97  ASSERT_TRUE(service);
98
99  AppListControllerDelegate* controller(service->GetControllerDelegate());
100  ASSERT_TRUE(controller);
101
102  // Open the app list with the browser's profile.
103  ASSERT_FALSE(service->IsAppListVisible());
104  controller->ShowForProfileByPath(browser()->profile()->GetPath());
105  app_list::AppListModel* model = test::GetAppListModel(service);
106  ASSERT_TRUE(model);
107
108  base::RunLoop().RunUntilIdle();
109
110  ASSERT_TRUE(service->IsAppListVisible());
111  ASSERT_EQ(browser()->profile(), service->GetCurrentAppListProfile());
112
113  // Open the app list with the second profile.
114  controller->ShowForProfileByPath(profile2_->GetPath());
115  model = test::GetAppListModel(service);
116  ASSERT_TRUE(model);
117  base::RunLoop().RunUntilIdle();
118
119  ASSERT_TRUE(service->IsAppListVisible());
120  ASSERT_EQ(profile2_, service->GetCurrentAppListProfile());
121
122  controller->DismissView();
123}
124
125// Test switching app list profiles while search results are visibile.
126IN_PROC_BROWSER_TEST_F(AppListServiceInteractiveTest,
127                       MAYBE_SwitchAppListProfilesDuringSearch) {
128  InitSecondProfile();
129
130  AppListService* service = test::GetAppListService();
131  ASSERT_TRUE(service);
132
133  AppListControllerDelegate* controller(service->GetControllerDelegate());
134  ASSERT_TRUE(controller);
135
136  // Set a search with original profile.
137  controller->ShowForProfileByPath(browser()->profile()->GetPath());
138  app_list::AppListModel* model = test::GetAppListModel(service);
139  ASSERT_TRUE(model);
140
141  model->search_box()->SetText(base::ASCIIToUTF16("minimal"));
142  base::RunLoop().RunUntilIdle();
143
144  // Switch to the second profile.
145  controller->ShowForProfileByPath(profile2_->GetPath());
146  model = test::GetAppListModel(service);
147  ASSERT_TRUE(model);
148  base::RunLoop().RunUntilIdle();
149
150  // Ensure the search box is empty.
151  ASSERT_TRUE(model->search_box()->text().empty());
152  ASSERT_EQ(profile2_, service->GetCurrentAppListProfile());
153
154  controller->DismissView();
155  ASSERT_FALSE(service->IsAppListVisible());
156}
157
158// Interactive UI test that adds the --show-app-list command line switch.
159class ShowAppListInteractiveTest : public InProcessBrowserTest {
160 public:
161  ShowAppListInteractiveTest() {}
162
163  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
164    command_line->AppendSwitch(switches::kShowAppList);
165  }
166
167 private:
168  DISALLOW_COPY_AND_ASSIGN(ShowAppListInteractiveTest);
169};
170
171// Test showing the app list using the command line switch.
172#if defined(OS_CHROMEOS)
173// http://crbug.com/396499
174#define MAYBE_ShowAppListFlag DISABLED_ShowAppListFlag
175#else
176#define MAYBE_ShowAppListFlag ShowAppListFlag
177#endif
178IN_PROC_BROWSER_TEST_F(ShowAppListInteractiveTest, MAYBE_ShowAppListFlag) {
179  AppListService* service = test::GetAppListService();
180  // The app list should already be shown because we passed
181  // switches::kShowAppList.
182  EXPECT_TRUE(service->IsAppListVisible());
183
184  // Create a browser to prevent shutdown when we dismiss the app list.  We
185  // need to do this because switches::kShowAppList suppresses the creation of
186  // any browsers.
187  Profile* profile = service->GetCurrentAppListProfile();
188  CreateBrowser(profile);
189
190  service->DismissAppList();
191  EXPECT_FALSE(service->IsAppListVisible());
192
193  // With Chrome still running, test receiving a second --show-app-list request
194  // via the process singleton. ChromeOS has no process singleton so exclude it.
195#if !defined(OS_CHROMEOS)
196  CommandLine command_line(CommandLine::NO_PROGRAM);
197  command_line.AppendSwitch(switches::kShowAppList);
198  StartupBrowserCreator::ProcessCommandLineAlreadyRunning(
199      command_line, base::FilePath(), profile->GetPath());
200
201  EXPECT_TRUE(service->IsAppListVisible());
202  service->DismissAppList();
203  EXPECT_FALSE(service->IsAppListVisible());
204#endif
205}
206
207// Interactive UI test that creates a non-default profile and configures it for
208// the --show-app-list flag.
209class ShowAppListNonDefaultInteractiveTest : public ShowAppListInteractiveTest {
210 public:
211  ShowAppListNonDefaultInteractiveTest()
212      : second_profile_name_(FILE_PATH_LITERAL("Profile 1")) {
213  }
214
215  virtual bool SetUpUserDataDirectory() OVERRIDE {
216    // Create a temp dir for "Profile 1" and seed the user data dir with a Local
217    // State file configuring the app list to use it.
218    base::FilePath user_data_dir;
219    CHECK(PathService::Get(chrome::DIR_USER_DATA, &user_data_dir));
220    base::FilePath profile_path = user_data_dir.Append(second_profile_name_);
221    CHECK(second_profile_temp_dir_.Set(profile_path));
222
223    base::FilePath local_pref_path =
224        user_data_dir.Append(chrome::kLocalStateFilename);
225    base::DictionaryValue dict;
226    dict.SetString(prefs::kAppListProfile,
227                   second_profile_name_.MaybeAsASCII());
228    CHECK(JSONFileValueSerializer(local_pref_path).Serialize(dict));
229
230    return InProcessBrowserTest::SetUpUserDataDirectory();
231  }
232
233 protected:
234  const base::FilePath second_profile_name_;
235  base::ScopedTempDir second_profile_temp_dir_;
236
237 private:
238  DISALLOW_COPY_AND_ASSIGN(ShowAppListNonDefaultInteractiveTest);
239};
240
241// Test showing the app list for a profile that doesn't match the browser
242// profile.
243IN_PROC_BROWSER_TEST_F(ShowAppListNonDefaultInteractiveTest,
244                       MAYBE_ShowAppListNonDefaultProfile) {
245  AppListService* service = test::GetAppListService();
246  EXPECT_TRUE(service->IsAppListVisible());
247  EXPECT_EQ(second_profile_name_.value(),
248            service->GetCurrentAppListProfile()->GetPath().BaseName().value());
249
250  // Check that the default profile hasn't been loaded.
251  ProfileManager* profile_manager = g_browser_process->profile_manager();
252  EXPECT_EQ(1u, profile_manager->GetNumberOfProfiles());
253
254  // Create a browser for the Default profile. This stops MaybeTeminate being
255  // called when the app list window is dismissed. Use the last used browser
256  // profile to verify that it is different and causes ProfileManager to load a
257  // new profile.
258  CreateBrowser(profile_manager->GetLastUsedProfile());
259  EXPECT_EQ(2u, profile_manager->GetNumberOfProfiles());
260
261  service->DismissAppList();
262}
263