Switch global error menu icon to vectorized MD asset
[chromium-blink-merge.git] / chrome / browser / apps / custom_launcher_page_browsertest_views.cc
blobeb8aea103b038419bd586748c047d9248ab5cd47
1 // Copyright 2014 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.
5 #include <string>
7 #include "ash/shell.h"
8 #include "base/command_line.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/apps/app_browsertest_util.h"
11 #include "chrome/browser/ui/app_list/app_list_service.h"
12 #include "chrome/browser/ui/app_list/app_list_service_views.h"
13 #include "chrome/browser/ui/app_list/app_list_shower_views.h"
14 #include "content/public/browser/render_frame_host.h"
15 #include "content/public/browser/web_contents.h"
16 #include "extensions/common/extension.h"
17 #include "extensions/common/switches.h"
18 #include "extensions/test/extension_test_message_listener.h"
19 #include "ui/app_list/app_list_switches.h"
20 #include "ui/app_list/views/app_list_main_view.h"
21 #include "ui/app_list/views/app_list_view.h"
22 #include "ui/app_list/views/contents_view.h"
23 #include "ui/app_list/views/custom_launcher_page_view.h"
24 #include "ui/app_list/views/search_box_view.h"
25 #include "ui/events/test/event_generator.h"
26 #include "ui/views/controls/textfield/textfield.h"
27 #include "ui/views/controls/webview/webview.h"
28 #include "ui/views/focus/focus_manager.h"
30 namespace {
32 // The path of the test application within the "platform_apps" directory.
33 const char kCustomLauncherPagePath[] = "custom_launcher_page";
35 // The app ID of the test application.
36 const char kCustomLauncherPageID[] = "lmadimbbgapmngbiclpjjngmdickadpl";
38 } // namespace
40 // Browser tests for custom launcher pages, platform apps that run as a page in
41 // the app launcher. Within this test class, LoadAndLaunchPlatformApp runs the
42 // app inside the launcher, not as a standalone background page.
43 // the app launcher.
44 class CustomLauncherPageBrowserTest
45 : public extensions::PlatformAppBrowserTest {
46 public:
47 CustomLauncherPageBrowserTest() {}
49 void SetUpCommandLine(base::CommandLine* command_line) override {
50 PlatformAppBrowserTest::SetUpCommandLine(command_line);
52 // Custom launcher pages only work in the experimental app list.
53 command_line->AppendSwitch(app_list::switches::kEnableExperimentalAppList);
55 // Ensure the app list does not close during the test.
56 command_line->AppendSwitch(
57 app_list::switches::kDisableAppListDismissOnBlur);
59 // The test app must be whitelisted to use launcher_page.
60 command_line->AppendSwitchASCII(
61 extensions::switches::kWhitelistedExtensionID, kCustomLauncherPageID);
64 // Open the launcher. Ignores the Extension argument (this will simply
65 // activate any loaded launcher pages).
66 void LaunchPlatformApp(const extensions::Extension* /*unused*/) override {
67 AppListService* service =
68 AppListService::Get(chrome::HOST_DESKTOP_TYPE_NATIVE);
69 DCHECK(service);
70 service->ShowForProfile(browser()->profile());
73 app_list::AppListView* GetAppListView() {
74 app_list::AppListView* app_list_view = nullptr;
75 #if defined(OS_CHROMEOS)
76 ash::Shell* shell = ash::Shell::GetInstance();
77 app_list_view = shell->GetAppListView();
78 EXPECT_TRUE(shell->GetAppListTargetVisibility());
79 #else
80 AppListServiceViews* service = static_cast<AppListServiceViews*>(
81 AppListService::Get(chrome::HOST_DESKTOP_TYPE_NATIVE));
82 // The app list should have loaded instantly since the profile is already
83 // loaded.
84 EXPECT_TRUE(service->IsAppListVisible());
85 app_list_view = service->shower().app_list();
86 #endif
87 return app_list_view;
90 // Set the active page on the app list, according to |state|. Does not wait
91 // for any animation or custom page to complete.
92 void SetActiveStateAndVerify(app_list::AppListModel::State state) {
93 app_list::ContentsView* contents_view =
94 GetAppListView()->app_list_main_view()->contents_view();
95 contents_view->SetActiveState(state);
96 EXPECT_TRUE(contents_view->IsStateActive(state));
99 void SetCustomLauncherPageEnabled(bool enabled) {
100 const base::string16 kLauncherPageDisableScript =
101 base::ASCIIToUTF16("disableCustomLauncherPage();");
102 const base::string16 kLauncherPageEnableScript =
103 base::ASCIIToUTF16("enableCustomLauncherPage();");
105 app_list::ContentsView* contents_view =
106 GetAppListView()->app_list_main_view()->contents_view();
107 views::WebView* custom_page_view = static_cast<views::WebView*>(
108 contents_view->custom_page_view()->custom_launcher_page_contents());
109 content::RenderFrameHost* custom_page_frame =
110 custom_page_view->GetWebContents()->GetMainFrame();
112 const char* test_message =
113 enabled ? "launcherPageEnabled" : "launcherPageDisabled";
115 ExtensionTestMessageListener listener(test_message, false);
116 custom_page_frame->ExecuteJavaScriptForTests(
117 enabled ? kLauncherPageEnableScript : kLauncherPageDisableScript);
118 listener.WaitUntilSatisfied();
121 private:
122 DISALLOW_COPY_AND_ASSIGN(CustomLauncherPageBrowserTest);
125 IN_PROC_BROWSER_TEST_F(CustomLauncherPageBrowserTest,
126 OpenLauncherAndSwitchToCustomPage) {
127 LoadAndLaunchPlatformApp(kCustomLauncherPagePath, "Launched");
128 app_list::AppListView* app_list_view = GetAppListView();
129 app_list::ContentsView* contents_view =
130 app_list_view->app_list_main_view()->contents_view();
132 ASSERT_TRUE(
133 contents_view->IsStateActive(app_list::AppListModel::STATE_START));
136 ExtensionTestMessageListener listener("onPageProgressAt1", false);
137 contents_view->SetActiveState(
138 app_list::AppListModel::STATE_CUSTOM_LAUNCHER_PAGE);
140 listener.WaitUntilSatisfied();
143 ExtensionTestMessageListener listener("onPageProgressAt0", false);
144 contents_view->SetActiveState(app_list::AppListModel::STATE_START);
146 listener.WaitUntilSatisfied();
150 // Test that the app list will switch to the custom launcher page by sending a
151 // click inside the clickzone, or a mouse scroll event.
152 IN_PROC_BROWSER_TEST_F(CustomLauncherPageBrowserTest,
153 EventsActivateSwitchToCustomPage) {
154 LoadAndLaunchPlatformApp(kCustomLauncherPagePath, "Launched");
155 // Use an event generator to ensure targeting is correct.
156 app_list::AppListView* app_list_view = GetAppListView();
157 app_list::ContentsView* contents_view =
158 app_list_view->app_list_main_view()->contents_view();
159 gfx::NativeWindow window = app_list_view->GetWidget()->GetNativeWindow();
160 ui::test::EventGenerator event_generator(window->GetRootWindow(), window);
161 EXPECT_TRUE(
162 contents_view->IsStateActive(app_list::AppListModel::STATE_START));
164 // Find the clickzone.
165 gfx::Rect bounds =
166 contents_view->custom_page_view()->GetCollapsedLauncherPageBounds();
167 bounds.Intersect(contents_view->bounds());
168 gfx::Point point_in_clickzone = bounds.CenterPoint();
169 views::View::ConvertPointToWidget(contents_view, &point_in_clickzone);
171 // First try clicking 10px above the clickzone.
172 gfx::Point point_above_clickzone = point_in_clickzone;
173 point_above_clickzone.set_y(bounds.y() - 10);
174 views::View::ConvertPointToWidget(contents_view, &point_above_clickzone);
176 event_generator.MoveMouseRelativeTo(window, point_above_clickzone);
177 event_generator.ClickLeftButton();
179 // Should stay on the start page.
180 EXPECT_TRUE(
181 contents_view->IsStateActive(app_list::AppListModel::STATE_START));
183 // Now click in the clickzone.
184 event_generator.MoveMouseRelativeTo(window, point_in_clickzone);
185 // First, try disabling the custom page view. Click should do nothing.
186 SetCustomLauncherPageEnabled(false);
187 event_generator.ClickLeftButton();
188 EXPECT_TRUE(
189 contents_view->IsStateActive(app_list::AppListModel::STATE_START));
190 // Click again with it enabled. The active state should update immediately.
191 SetCustomLauncherPageEnabled(true);
192 event_generator.ClickLeftButton();
193 EXPECT_TRUE(contents_view->IsStateActive(
194 app_list::AppListModel::STATE_CUSTOM_LAUNCHER_PAGE));
196 // Back to the start page. And send a mouse wheel event.
197 SetActiveStateAndVerify(app_list::AppListModel::STATE_START);
198 // Generate wheel events above the clickzone.
199 event_generator.MoveMouseRelativeTo(window, point_above_clickzone);
200 // Scrolling left, right or up should do nothing.
201 event_generator.MoveMouseWheel(-5, 0);
202 event_generator.MoveMouseWheel(5, 0);
203 event_generator.MoveMouseWheel(0, 5);
204 EXPECT_TRUE(
205 contents_view->IsStateActive(app_list::AppListModel::STATE_START));
206 // Scroll down to open launcher page.
207 event_generator.MoveMouseWheel(0, -5);
208 EXPECT_TRUE(contents_view->IsStateActive(
209 app_list::AppListModel::STATE_CUSTOM_LAUNCHER_PAGE));
211 // Constants for gesture/trackpad events.
212 const base::TimeDelta step_delay = base::TimeDelta::FromMilliseconds(300);
213 const int num_steps = 5;
214 const int num_fingers = 2;
216 #if defined(OS_CHROMEOS)
217 // Gesture events need to be in host coordinates. On Desktop platforms, the
218 // Widget is the host, so nothing needs to be done. On ChromeOS, the points
219 // need to be put into screen coordinates. This works because the root window
220 // assumes it fills the screen.
221 point_in_clickzone = bounds.CenterPoint();
222 point_above_clickzone.SetPoint(point_in_clickzone.x(), bounds.y() - 10);
223 views::View::ConvertPointToScreen(contents_view, &point_above_clickzone);
224 views::View::ConvertPointToScreen(contents_view, &point_in_clickzone);
225 #endif
227 // Back to the start page. And send a scroll gesture.
228 SetActiveStateAndVerify(app_list::AppListModel::STATE_START);
229 // Going down should do nothing.
230 event_generator.GestureScrollSequence(
231 point_above_clickzone, point_in_clickzone, step_delay, num_steps);
232 EXPECT_TRUE(
233 contents_view->IsStateActive(app_list::AppListModel::STATE_START));
234 // Now go up - should change state.
235 event_generator.GestureScrollSequence(
236 point_in_clickzone, point_above_clickzone, step_delay, num_steps);
237 EXPECT_TRUE(contents_view->IsStateActive(
238 app_list::AppListModel::STATE_CUSTOM_LAUNCHER_PAGE));
240 // Back to the start page. And send a trackpad scroll event.
241 SetActiveStateAndVerify(app_list::AppListModel::STATE_START);
242 // Going down left, right or up should do nothing.
243 event_generator.ScrollSequence(point_in_clickzone, step_delay, -5, 0,
244 num_steps, num_fingers);
245 event_generator.ScrollSequence(point_in_clickzone, step_delay, 5, 0,
246 num_steps, num_fingers);
247 event_generator.ScrollSequence(point_in_clickzone, step_delay, 0, 5,
248 num_steps, num_fingers);
249 EXPECT_TRUE(
250 contents_view->IsStateActive(app_list::AppListModel::STATE_START));
251 // Scroll up to open launcher page.
252 event_generator.ScrollSequence(point_in_clickzone, step_delay, 0, -5,
253 num_steps, num_fingers);
254 EXPECT_TRUE(contents_view->IsStateActive(
255 app_list::AppListModel::STATE_CUSTOM_LAUNCHER_PAGE));
257 // Back to the start page. And send a tap gesture.
258 SetActiveStateAndVerify(app_list::AppListModel::STATE_START);
259 // Tapping outside the clickzone should do nothing.
260 event_generator.GestureTapAt(point_above_clickzone);
261 EXPECT_TRUE(
262 contents_view->IsStateActive(app_list::AppListModel::STATE_START));
263 // Now tap in the clickzone.
264 event_generator.GestureTapAt(point_in_clickzone);
265 EXPECT_TRUE(contents_view->IsStateActive(
266 app_list::AppListModel::STATE_CUSTOM_LAUNCHER_PAGE));
269 IN_PROC_BROWSER_TEST_F(CustomLauncherPageBrowserTest, LauncherPageSubpages) {
270 LoadAndLaunchPlatformApp(kCustomLauncherPagePath, "Launched");
272 app_list::AppListView* app_list_view = GetAppListView();
273 app_list::AppListModel* model = app_list_view->app_list_main_view()->model();
274 app_list::ContentsView* contents_view =
275 app_list_view->app_list_main_view()->contents_view();
277 ASSERT_TRUE(
278 contents_view->IsStateActive(app_list::AppListModel::STATE_START));
281 ExtensionTestMessageListener listener("onPageProgressAt1", false);
282 contents_view->SetActiveState(
283 app_list::AppListModel::STATE_CUSTOM_LAUNCHER_PAGE);
284 listener.WaitUntilSatisfied();
285 EXPECT_TRUE(contents_view->IsStateActive(
286 app_list::AppListModel::STATE_CUSTOM_LAUNCHER_PAGE));
287 // The app pushes 2 subpages when the launcher page is shown.
288 EXPECT_EQ(2, model->custom_launcher_page_subpage_depth());
291 // Pop the subpages.
293 ExtensionTestMessageListener listener("onPopSubpage", false);
294 EXPECT_TRUE(contents_view->Back());
295 listener.WaitUntilSatisfied();
296 EXPECT_TRUE(contents_view->IsStateActive(
297 app_list::AppListModel::STATE_CUSTOM_LAUNCHER_PAGE));
298 EXPECT_EQ(1, model->custom_launcher_page_subpage_depth());
301 ExtensionTestMessageListener listener("onPopSubpage", false);
302 EXPECT_TRUE(contents_view->Back());
303 listener.WaitUntilSatisfied();
304 EXPECT_TRUE(contents_view->IsStateActive(
305 app_list::AppListModel::STATE_CUSTOM_LAUNCHER_PAGE));
306 EXPECT_EQ(0, model->custom_launcher_page_subpage_depth());
309 // Once all subpages are popped, the start page should show.
310 EXPECT_TRUE(contents_view->Back());
312 // Immediately finish the animation.
313 contents_view->Layout();
314 EXPECT_TRUE(
315 contents_view->IsStateActive(app_list::AppListModel::STATE_START));
318 IN_PROC_BROWSER_TEST_F(CustomLauncherPageBrowserTest, LauncherPageShowAndHide) {
319 const base::string16 kLauncherPageShowScript =
320 base::ASCIIToUTF16("chrome.launcherPage.show();");
321 const base::string16 kLauncherPageHideScript =
322 base::ASCIIToUTF16("hideCustomLauncherPage()");
324 LoadAndLaunchPlatformApp(kCustomLauncherPagePath, "Launched");
325 app_list::AppListView* app_list_view = GetAppListView();
326 app_list::ContentsView* contents_view =
327 app_list_view->app_list_main_view()->contents_view();
329 views::WebView* custom_page_view = static_cast<views::WebView*>(
330 contents_view->custom_page_view()->custom_launcher_page_contents());
332 content::RenderFrameHost* custom_page_frame =
333 custom_page_view->GetWebContents()->GetMainFrame();
335 ASSERT_TRUE(
336 contents_view->IsStateActive(app_list::AppListModel::STATE_START));
338 // Ensure launcherPage.show() will switch the page to the custom launcher page
339 // if the app launcher is already showing.
341 ExtensionTestMessageListener listener("onPageProgressAt1", false);
342 custom_page_frame->ExecuteJavaScriptForTests(kLauncherPageShowScript);
344 listener.WaitUntilSatisfied();
345 EXPECT_TRUE(contents_view->IsStateActive(
346 app_list::AppListModel::STATE_CUSTOM_LAUNCHER_PAGE));
349 // Ensure launcherPage.show() will show the app list if it's hidden.
351 // Close the app list immediately.
352 app_list_view->Close();
353 app_list_view->GetWidget()->Close();
355 ExtensionTestMessageListener listener("onPageProgressAt1", false);
356 custom_page_frame->ExecuteJavaScriptForTests(kLauncherPageShowScript);
358 listener.WaitUntilSatisfied();
360 // The app list view will have changed on ChromeOS.
361 app_list_view = GetAppListView();
362 contents_view = app_list_view->app_list_main_view()->contents_view();
363 EXPECT_TRUE(contents_view->IsStateActive(
364 app_list::AppListModel::STATE_CUSTOM_LAUNCHER_PAGE));
367 // Ensure launcherPage.hide() hides the launcher page when it's showing.
369 ExtensionTestMessageListener listener("onPageProgressAt0", false);
370 custom_page_frame->ExecuteJavaScriptForTests(kLauncherPageHideScript);
372 listener.WaitUntilSatisfied();
374 EXPECT_TRUE(
375 contents_view->IsStateActive(app_list::AppListModel::STATE_START));
378 // Nothing should happen if hide() is called from the apps page.
380 contents_view->SetActiveState(app_list::AppListModel::STATE_APPS, false);
382 ExtensionTestMessageListener listener("launcherPageHidden", false);
383 custom_page_frame->ExecuteJavaScriptForTests(kLauncherPageHideScript);
384 listener.WaitUntilSatisfied();
386 EXPECT_TRUE(
387 contents_view->IsStateActive(app_list::AppListModel::STATE_APPS));
391 IN_PROC_BROWSER_TEST_F(CustomLauncherPageBrowserTest, LauncherPageSetEnabled) {
392 LoadAndLaunchPlatformApp(kCustomLauncherPagePath, "Launched");
393 app_list::AppListView* app_list_view = GetAppListView();
394 app_list::AppListModel* model = app_list_view->app_list_main_view()->model();
395 app_list::ContentsView* contents_view =
396 app_list_view->app_list_main_view()->contents_view();
398 views::View* custom_page_view = contents_view->custom_page_view();
399 ASSERT_TRUE(
400 contents_view->IsStateActive(app_list::AppListModel::STATE_START));
402 EXPECT_TRUE(model->custom_launcher_page_enabled());
403 EXPECT_TRUE(custom_page_view->visible());
405 SetCustomLauncherPageEnabled(false);
406 EXPECT_FALSE(model->custom_launcher_page_enabled());
407 EXPECT_FALSE(custom_page_view->visible());
409 SetCustomLauncherPageEnabled(true);
410 EXPECT_TRUE(model->custom_launcher_page_enabled());
411 EXPECT_TRUE(custom_page_view->visible());
414 // Currently this is flaky.
415 // Disabled test http://crbug.com/463456
416 IN_PROC_BROWSER_TEST_F(CustomLauncherPageBrowserTest,
417 LauncherPageFocusTraversal) {
418 LoadAndLaunchPlatformApp(kCustomLauncherPagePath, "Launched");
419 app_list::AppListView* app_list_view = GetAppListView();
420 app_list::ContentsView* contents_view =
421 app_list_view->app_list_main_view()->contents_view();
422 app_list::SearchBoxView* search_box_view =
423 app_list_view->app_list_main_view()->search_box_view();
425 ASSERT_TRUE(
426 contents_view->IsStateActive(app_list::AppListModel::STATE_START));
429 ExtensionTestMessageListener listener("onPageProgressAt1", false);
430 contents_view->SetActiveState(
431 app_list::AppListModel::STATE_CUSTOM_LAUNCHER_PAGE);
432 listener.WaitUntilSatisfied();
435 // Expect that the search box and webview are the only two focusable views.
436 views::View* search_box_textfield = search_box_view->search_box();
437 views::WebView* custom_page_webview = static_cast<views::WebView*>(
438 contents_view->custom_page_view()->custom_launcher_page_contents());
439 EXPECT_EQ(custom_page_webview,
440 app_list_view->GetFocusManager()->GetNextFocusableView(
441 search_box_textfield, search_box_textfield->GetWidget(), false,
442 false));
443 EXPECT_EQ(
444 search_box_textfield,
445 app_list_view->GetFocusManager()->GetNextFocusableView(
446 custom_page_webview, custom_page_webview->GetWidget(), false, false));
448 // And in reverse.
449 EXPECT_EQ(
450 search_box_textfield,
451 app_list_view->GetFocusManager()->GetNextFocusableView(
452 custom_page_webview, custom_page_webview->GetWidget(), true, false));
453 EXPECT_EQ(custom_page_webview,
454 app_list_view->GetFocusManager()->GetNextFocusableView(
455 search_box_textfield, search_box_textfield->GetWidget(), true,
456 false));