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