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 <algorithm>
6 #include <memory>
7 
8 #include "ash/accessibility/accessibility_controller_impl.h"
9 #include "ash/app_list/app_list_controller_impl.h"
10 #include "ash/app_list/app_list_presenter_impl.h"
11 #include "ash/app_list/model/app_list_item.h"
12 #include "ash/app_list/test/app_list_test_helper.h"
13 #include "ash/app_list/test/app_list_test_model.h"
14 #include "ash/app_list/test/app_list_test_view_delegate.h"
15 #include "ash/app_list/test/test_search_result.h"
16 #include "ash/app_list/views/app_list_folder_view.h"
17 #include "ash/app_list/views/app_list_item_view.h"
18 #include "ash/app_list/views/app_list_main_view.h"
19 #include "ash/app_list/views/app_list_view.h"
20 #include "ash/app_list/views/apps_container_view.h"
21 #include "ash/app_list/views/apps_grid_view.h"
22 #include "ash/app_list/views/contents_view.h"
23 #include "ash/app_list/views/expand_arrow_view.h"
24 #include "ash/app_list/views/privacy_container_view.h"
25 #include "ash/app_list/views/search_box_view.h"
26 #include "ash/app_list/views/search_result_actions_view.h"
27 #include "ash/app_list/views/search_result_base_view.h"
28 #include "ash/app_list/views/search_result_list_view.h"
29 #include "ash/app_list/views/search_result_page_anchored_dialog.h"
30 #include "ash/app_list/views/search_result_page_view.h"
31 #include "ash/app_list/views/test/apps_grid_view_test_api.h"
32 #include "ash/home_screen/home_screen_controller.h"
33 #include "ash/keyboard/keyboard_controller_impl.h"
34 #include "ash/keyboard/ui/keyboard_ui_controller.h"
35 #include "ash/keyboard/ui/test/keyboard_test_util.h"
36 #include "ash/public/cpp/app_list/app_list_color_provider.h"
37 #include "ash/public/cpp/app_list/app_list_config.h"
38 #include "ash/public/cpp/app_list/app_list_features.h"
39 #include "ash/public/cpp/app_list/app_list_switches.h"
40 #include "ash/public/cpp/app_list/app_list_types.h"
41 #include "ash/public/cpp/ash_features.h"
42 #include "ash/public/cpp/ash_switches.h"
43 #include "ash/public/cpp/keyboard/keyboard_switches.h"
44 #include "ash/public/cpp/shelf_config.h"
45 #include "ash/public/cpp/shelf_item_delegate.h"
46 #include "ash/public/cpp/shelf_model.h"
47 #include "ash/public/cpp/shelf_types.h"
48 #include "ash/public/cpp/shell_window_ids.h"
49 #include "ash/public/cpp/test/shell_test_api.h"
50 #include "ash/root_window_controller.h"
51 #include "ash/shelf/home_button.h"
52 #include "ash/shelf/scrollable_shelf_view.h"
53 #include "ash/shelf/shelf.h"
54 #include "ash/shelf/shelf_app_button.h"
55 #include "ash/shelf/shelf_layout_manager.h"
56 #include "ash/shelf/shelf_navigation_widget.h"
57 #include "ash/shelf/shelf_test_util.h"
58 #include "ash/shelf/shelf_view.h"
59 #include "ash/shelf/shelf_view_test_api.h"
60 #include "ash/shell.h"
61 #include "ash/system/unified/unified_system_tray.h"
62 #include "ash/test/ash_test_base.h"
63 #include "ash/wallpaper/wallpaper_controller_test_api.h"
64 #include "ash/wm/mru_window_tracker.h"
65 #include "ash/wm/overview/overview_controller.h"
66 #include "ash/wm/splitview/split_view_controller.h"
67 #include "ash/wm/tablet_mode/tablet_mode_controller.h"
68 #include "ash/wm/window_state.h"
69 #include "ash/wm/window_util.h"
70 #include "ash/wm/workspace_controller_test_api.h"
71 #include "base/callback_helpers.h"
72 #include "base/command_line.h"
73 #include "base/macros.h"
74 #include "base/run_loop.h"
75 #include "base/test/metrics/histogram_tester.h"
76 #include "base/test/scoped_feature_list.h"
77 #include "ui/aura/client/aura_constants.h"
78 #include "ui/aura/test/test_windows.h"
79 #include "ui/aura/window.h"
80 #include "ui/base/ui_base_types.h"
81 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
82 #include "ui/display/display.h"
83 #include "ui/display/manager/display_manager.h"
84 #include "ui/display/screen.h"
85 #include "ui/display/test/display_manager_test_api.h"
86 #include "ui/events/test/event_generator.h"
87 #include "ui/views/controls/textfield/textfield.h"
88 #include "ui/views/test/widget_test.h"
89 #include "ui/wm/core/window_util.h"
90 
91 namespace ash {
92 namespace {
93 
94 constexpr int kAppListBezelMargin = 50;
95 
GetPrimaryDisplayId()96 int64_t GetPrimaryDisplayId() {
97   return display::Screen::GetScreen()->GetPrimaryDisplay().id();
98 }
99 
SetShelfAlignment(ShelfAlignment alignment)100 void SetShelfAlignment(ShelfAlignment alignment) {
101   AshTestBase::GetPrimaryShelf()->SetAlignment(alignment);
102 }
103 
EnableTabletMode(bool enable)104 void EnableTabletMode(bool enable) {
105   // Avoid |TabletModeController::OnGetSwitchStates| from disabling tablet mode
106   // again at the end of |TabletModeController::TabletModeController|.
107   base::RunLoop().RunUntilIdle();
108 
109   Shell::Get()->tablet_mode_controller()->SetEnabledForTest(enable);
110 
111   // The app list will be shown automatically when tablet mode is enabled (Home
112   // launcher flag is enabled). Wait here for the animation complete.
113   base::RunLoop().RunUntilIdle();
114 }
115 
116 // Generates a fling.
FlingUpOrDown(ui::test::EventGenerator * generator,AppListView * view,bool up)117 void FlingUpOrDown(ui::test::EventGenerator* generator,
118                    AppListView* view,
119                    bool up) {
120   int offset = up ? -100 : 100;
121   gfx::Point start_point = view->GetBoundsInScreen().origin();
122   gfx::Point target_point = start_point;
123   target_point.Offset(0, offset);
124 
125   generator->GestureScrollSequence(start_point, target_point,
126                                    base::TimeDelta::FromMilliseconds(10), 2);
127 }
128 
CreateOmniboxSuggestionResult(const std::string & result_id)129 std::unique_ptr<TestSearchResult> CreateOmniboxSuggestionResult(
130     const std::string& result_id) {
131   auto suggestion_result = std::make_unique<TestSearchResult>();
132   suggestion_result->set_result_id(result_id);
133   suggestion_result->set_is_omnibox_search(true);
134   suggestion_result->set_display_type(ash::SearchResultDisplayType::kList);
135   SearchResultActions actions;
136   actions.push_back(SearchResultAction(gfx::ImageSkia(),
137                                        base::ASCIIToUTF16("Remove"),
138                                        true /*visible_on_hover*/));
139   suggestion_result->SetActions(actions);
140 
141   return suggestion_result;
142 }
143 
144 }  // namespace
145 
146 class AppListPresenterDelegateTest : public AshTestBase,
147                                      public testing::WithParamInterface<bool> {
148  public:
149   AppListPresenterDelegateTest() = default;
150   AppListPresenterDelegateTest(const AppListPresenterDelegateTest&) = delete;
151   AppListPresenterDelegateTest& operator=(const AppListPresenterDelegateTest&) =
152       delete;
153   ~AppListPresenterDelegateTest() override = default;
154 
155   // testing::Test:
SetUp()156   void SetUp() override {
157     AppListView::SetShortAnimationForTesting(true);
158     AshTestBase::SetUp();
159 
160     // Make the display big enough to hold the app list.
161     UpdateDisplay("1024x768");
162   }
163 
164   // testing::Test:
TearDown()165   void TearDown() override {
166     AshTestBase::TearDown();
167     AppListView::SetShortAnimationForTesting(false);
168   }
169 
SetAppListStateAndWait(AppListViewState new_state)170   void SetAppListStateAndWait(AppListViewState new_state) {
171     GetAppListView()->SetState(new_state);
172     GetAppListTestHelper()->WaitUntilIdle();
173     GetAppListTestHelper()->CheckState(new_state);
174   }
175 
176   // Whether to run the test with mouse or gesture events.
TestMouseEventParam()177   bool TestMouseEventParam() { return GetParam(); }
178 
GetPointOutsideSearchbox()179   gfx::Point GetPointOutsideSearchbox() {
180     // Ensures that the point satisfies the following conditions:
181     // (1) The point is within AppListView.
182     // (2) The point is outside of the search box.
183     // (3) The touch event on the point should not be consumed by the handler
184     // for back gesture.
185     return GetAppListView()
186         ->search_box_view()
187         ->GetBoundsInScreen()
188         .bottom_right();
189   }
190 
GetPointInsideSearchbox()191   gfx::Point GetPointInsideSearchbox() {
192     return GetAppListView()
193         ->search_box_view()
194         ->GetBoundsInScreen()
195         .CenterPoint();
196   }
197 
GetAppListView()198   AppListView* GetAppListView() {
199     return GetAppListTestHelper()->GetAppListView();
200   }
201 
search_result_page()202   SearchResultPageView* search_result_page() {
203     return GetAppListView()
204         ->app_list_main_view()
205         ->contents_view()
206         ->search_results_page_view();
207   }
208 
ShowZeroStateSearchInHalfState()209   void ShowZeroStateSearchInHalfState() {
210     GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
211     GetEventGenerator()->GestureTapAt(GetPointInsideSearchbox());
212     GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
213   }
214 
GetSearchResultListViewItemAt(int index)215   SearchResultBaseView* GetSearchResultListViewItemAt(int index) {
216     return GetAppListView()
217         ->app_list_main_view()
218         ->contents_view()
219         ->search_result_list_view_for_test()
220         ->GetResultViewAt(index);
221   }
222 
ClickMouseAt(const gfx::Point & point)223   void ClickMouseAt(const gfx::Point& point) {
224     ui::test::EventGenerator* generator = GetEventGenerator();
225     generator->MoveMouseTo(point);
226     generator->PressLeftButton();
227     generator->ReleaseLeftButton();
228   }
229 
LongPressAt(const gfx::Point & point)230   void LongPressAt(const gfx::Point& point) {
231     ui::TouchEvent long_press(ui::ET_GESTURE_LONG_PRESS, point,
232                               base::TimeTicks::Now(),
233                               ui::PointerDetails(ui::EventPointerType::kTouch));
234     GetEventGenerator()->Dispatch(&long_press);
235   }
236 
GetSearchResultPageAnchoredDialog()237   views::DialogDelegate* GetSearchResultPageAnchoredDialog() {
238     return search_result_page()
239         ->anchored_dialog_for_test()
240         ->widget()
241         ->widget_delegate()
242         ->AsDialogDelegate();
243   }
244 
245   // Verifies the current search result page anchored dialog bounds.
246   // The dialog is expected to be positioned horizontally centered within the
247   // search box bounds.
SanityCheckSearchResultsAnchoredDialogBounds(const views::Widget * dialog)248   void SanityCheckSearchResultsAnchoredDialogBounds(
249       const views::Widget* dialog) {
250     auto horizontal_center_offset = [](const gfx::Rect& inner,
251                                        const gfx::Rect& outer) -> int {
252       return outer.CenterPoint().x() - inner.CenterPoint().x();
253     };
254 
255     const gfx::Rect dialog_bounds = dialog->GetWindowBoundsInScreen();
256     const gfx::Rect search_box_bounds = GetAppListView()
257                                             ->search_box_view()
258                                             ->GetWidget()
259                                             ->GetWindowBoundsInScreen();
260     // The dialog should be horizontally centered within the search box.
261     EXPECT_EQ(0, horizontal_center_offset(dialog_bounds, search_box_bounds));
262     // Verify the confirmation dialog is positioned with the top within search
263     // box bounds.
264     EXPECT_GT(dialog_bounds.y(), search_box_bounds.y());
265     EXPECT_LT(dialog_bounds.y(), search_box_bounds.bottom());
266   }
267 
268   // Returns the |dialog| vertical offset from the top of the search box bounds.
GetSearchResultsAnchoredDialogTopOffset(const views::Widget * dialog)269   int GetSearchResultsAnchoredDialogTopOffset(const views::Widget* dialog) {
270     const gfx::Rect dialog_bounds = dialog->GetWindowBoundsInScreen();
271     const gfx::Rect search_box_bounds = GetAppListView()
272                                             ->search_box_view()
273                                             ->GetWidget()
274                                             ->GetWindowBoundsInScreen();
275     return dialog_bounds.y() - search_box_bounds.y();
276   }
277 };
278 
279 // Used to test app_list behavior with a populated apps_grid
280 class PopulatedAppListTest : public AshTestBase,
281                              public testing::WithParamInterface<bool> {
282  public:
283   PopulatedAppListTest() = default;
284   ~PopulatedAppListTest() override = default;
285 
SetUp()286   void SetUp() override {
287     AppListConfigProvider::Get().ResetForTesting();
288     AshTestBase::SetUp();
289 
290     // Make the display big enough to hold the app list.
291     UpdateDisplay("1024x768");
292 
293     app_list_test_delegate_ = std::make_unique<test::AppListTestViewDelegate>();
294     app_list_test_model_ = app_list_test_delegate_->GetTestModel();
295   }
296 
TearDown()297   void TearDown() override {
298     AshTestBase::TearDown();
299     AppListView::SetShortAnimationForTesting(false);
300   }
301 
302  protected:
CreateAndOpenAppList()303   void CreateAndOpenAppList() {
304     app_list_view_ = new AppListView(app_list_test_delegate_.get());
305     app_list_view_->InitView(GetContext());
306     app_list_view_->Show(false /*is_side_shelf*/);
307   }
308 
ShowAppListInAppsFullScreen()309   void ShowAppListInAppsFullScreen() {
310     // Press the ExpandArrowView and check that the AppListView is in
311     // fullscreen.
312     gfx::Point click_point = app_list_view_->app_list_main_view()
313                                  ->contents_view()
314                                  ->expand_arrow_view()
315                                  ->GetBoundsInScreen()
316                                  .CenterPoint();
317     GetEventGenerator()->GestureTapAt(click_point);
318     EXPECT_EQ(AppListViewState::kFullscreenAllApps,
319               app_list_view_->app_list_state());
320   }
321 
InitializeAppsGrid()322   void InitializeAppsGrid() {
323     if (!app_list_view_)
324       CreateAndOpenAppList();
325     apps_grid_view_ = app_list_view_->app_list_main_view()
326                           ->contents_view()
327                           ->apps_container_view()
328                           ->apps_grid_view();
329     apps_grid_test_api_ =
330         std::make_unique<test::AppsGridViewTestApi>(apps_grid_view_);
331   }
332 
GetItemRectOnCurrentPageAt(int row,int col) const333   gfx::Rect GetItemRectOnCurrentPageAt(int row, int col) const {
334     DCHECK_GT(app_list_test_model_->top_level_item_list()->item_count(), 0u);
335     return apps_grid_test_api_->GetItemTileRectOnCurrentPageAt(row, col);
336   }
337 
AppListIsInFolderView() const338   bool AppListIsInFolderView() const {
339     return app_list_view_->app_list_main_view()
340         ->contents_view()
341         ->apps_container_view()
342         ->IsInFolderView();
343   }
344 
folder_view()345   AppListFolderView* folder_view() {
346     return app_list_view_->app_list_main_view()
347         ->contents_view()
348         ->apps_container_view()
349         ->app_list_folder_view();
350   }
351 
352   test::AppListTestModel* app_list_test_model_ = nullptr;
353   std::unique_ptr<test::AppsGridViewTestApi> apps_grid_test_api_;
354   std::unique_ptr<test::AppListTestViewDelegate> app_list_test_delegate_;
355   AppListView* app_list_view_ = nullptr;    // Owned by native widget.
356   AppsGridView* apps_grid_view_ = nullptr;  // Owned by |app_list_view_|.
357 };
358 
359 // Subclass of PopuplatedAppListTest which enables the animation and the virtual
360 // keyboard.
361 class PopulatedAppListWithVKEnabledTest : public PopulatedAppListTest {
362  public:
363   PopulatedAppListWithVKEnabledTest() = default;
364   ~PopulatedAppListWithVKEnabledTest() override = default;
365 
SetUp()366   void SetUp() override {
367     AppListView::SetShortAnimationForTesting(true);
368     base::CommandLine::ForCurrentProcess()->AppendSwitch(
369         keyboard::switches::kEnableVirtualKeyboard);
370     PopulatedAppListTest::SetUp();
371   }
372 };
373 
374 // Instantiate the Boolean which is used to toggle mouse and touch events in
375 // the parameterized tests.
376 INSTANTIATE_TEST_SUITE_P(All, AppListPresenterDelegateTest, testing::Bool());
377 
378 // Verifies that context menu click should not activate the search box
379 // (see https://crbug.com/941428).
TEST_F(AppListPresenterDelegateTest,RightClickSearchBoxInPeeking)380 TEST_F(AppListPresenterDelegateTest, RightClickSearchBoxInPeeking) {
381   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
382   AppListView* app_list_view = GetAppListView();
383   gfx::Rect app_list_bounds = app_list_view->GetBoundsInScreen();
384   ASSERT_EQ(AppListViewState::kPeeking, app_list_view->app_list_state());
385 
386   // Right click the search box and checks the following things:
387   // (1) AppListView's bounds in screen does not change.
388   // (2) AppListView is still in Peeking state.
389   ui::test::EventGenerator* generator = GetEventGenerator();
390   generator->MoveMouseTo(GetPointInsideSearchbox());
391   generator->PressRightButton();
392   EXPECT_EQ(app_list_bounds, app_list_view->GetBoundsInScreen());
393   EXPECT_EQ(AppListViewState::kPeeking, app_list_view->app_list_state());
394 }
395 
TEST_F(AppListPresenterDelegateTest,ReshownAppListResetsSearchBoxActivation)396 TEST_F(AppListPresenterDelegateTest, ReshownAppListResetsSearchBoxActivation) {
397   // Activate the search box.
398   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
399   GetEventGenerator()->GestureTapAt(GetPointInsideSearchbox());
400 
401   // Dismiss and re-show the AppList.
402   GetAppListTestHelper()->Dismiss();
403   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
404 
405   // Test that the search box is no longer active.
406   EXPECT_FALSE(GetAppListTestHelper()
407                    ->GetAppListView()
408                    ->search_box_view()
409                    ->is_search_box_active());
410 }
411 
412 // Tests that the SearchBox activation is reset after the AppList is hidden with
413 // no animation from FULLSCREEN_SEARCH.
TEST_F(AppListPresenterDelegateTest,SideShelfAppListResetsSearchBoxActivationOnClose)414 TEST_F(AppListPresenterDelegateTest,
415        SideShelfAppListResetsSearchBoxActivationOnClose) {
416   // Set the shelf to one side, then show the AppList and activate the
417   // searchbox.
418   SetShelfAlignment(ShelfAlignment::kRight);
419   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
420   GetEventGenerator()->GestureTapAt(GetPointInsideSearchbox());
421   ASSERT_TRUE(GetAppListTestHelper()
422                   ->GetAppListView()
423                   ->search_box_view()
424                   ->is_search_box_active());
425 
426   // Dismiss the AppList using the controller, this is the same way we dismiss
427   // the AppList when a SearchResult is launched, and skips the
428   // FULLSCREEN_SEARCH -> FULLSCREEN_ALL_APPS transition.
429   Shell::Get()->app_list_controller()->DismissAppList();
430 
431   // Test that the search box is not active.
432   EXPECT_FALSE(GetAppListTestHelper()
433                    ->GetAppListView()
434                    ->search_box_view()
435                    ->is_search_box_active());
436 }
437 
438 // Verifies that tapping on the search box in tablet mode with animation and
439 // zero state enabled should not bring Chrome crash (https://crbug.com/958267).
TEST_F(AppListPresenterDelegateTest,ClickSearchBoxInTabletMode)440 TEST_F(AppListPresenterDelegateTest, ClickSearchBoxInTabletMode) {
441   EnableTabletMode(true);
442   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
443   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
444 
445   // Necessary for AppListView::StateAnimationMetricsReporter::Report being
446   // called when animation ends.
447   ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
448       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
449   AppListView::SetShortAnimationForTesting(false);
450 
451   ui::test::EventGenerator* generator = GetEventGenerator();
452 
453   // Gesture tap on the search box.
454   generator->GestureTapAt(GetPointInsideSearchbox());
455 
456   // Wait until animation finishes. Verifies AppListView's state.
457   base::RunLoop().RunUntilIdle();
458   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
459 
460   // Gesture tap on the area out of search box.
461   generator->GestureTapAt(GetPointOutsideSearchbox());
462 
463   // Wait until animation finishes. Verifies AppListView's state.
464   base::RunLoop().RunUntilIdle();
465   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
466 }
467 
TEST_F(AppListPresenterDelegateTest,RemoveSuggestionShowsConfirmDialog)468 TEST_F(AppListPresenterDelegateTest, RemoveSuggestionShowsConfirmDialog) {
469   ShowZeroStateSearchInHalfState();
470 
471   // Mark the privacy notices as dismissed so that they do not interfere with
472   // the layout.
473   Shell::Get()->app_list_controller()->MarkAssistantPrivacyInfoDismissed();
474   Shell::Get()->app_list_controller()->MarkSuggestedContentInfoDismissed();
475   GetAppListView()
476       ->app_list_main_view()
477       ->contents_view()
478       ->privacy_container_view()
479       ->Update();
480 
481   // Add a zero state suggestion results - the result that will be tested is in
482   // the second place.
483   Shell::Get()->app_list_controller()->GetSearchModel()->results()->Add(
484       CreateOmniboxSuggestionResult("Another suggestion"));
485   const std::string kTestResultId = "Test suggestion";
486   Shell::Get()->app_list_controller()->GetSearchModel()->results()->Add(
487       CreateOmniboxSuggestionResult(kTestResultId));
488   // The result list is updated asynchronously.
489   GetAppListTestHelper()->WaitUntilIdle();
490 
491   SearchResultBaseView* result_view = GetSearchResultListViewItemAt(1);
492   ASSERT_TRUE(result_view);
493   ASSERT_TRUE(result_view->result());
494   ASSERT_EQ(kTestResultId, result_view->result()->id());
495 
496   // Make sure the search results page is laid out after adding result action
497   // buttons.
498   GetAppListView()->GetWidget()->LayoutRootViewIfNecessary();
499 
500   ASSERT_TRUE(result_view->actions_view());
501   EXPECT_EQ(1u, result_view->actions_view()->children().size());
502   views::View* const action_view = result_view->actions_view()->children()[0];
503 
504   // The remove action button is visible on hover only.
505   EXPECT_FALSE(action_view->GetVisible());
506 
507   ui::test::EventGenerator* generator = GetEventGenerator();
508   generator->MoveMouseTo(result_view->GetBoundsInScreen().CenterPoint());
509   EXPECT_TRUE(action_view->GetVisible());
510 
511   // Ensure layout after the action view visibility has been updated.
512   GetAppListView()->GetWidget()->LayoutRootViewIfNecessary();
513 
514   // Click the remove action button, this should surface a confirmation dialog.
515   ClickMouseAt(action_view->GetBoundsInScreen().CenterPoint());
516 
517   EXPECT_TRUE(GetAppListTestHelper()
518                   ->app_list_client()
519                   ->GetAndClearInvokedResultActions()
520                   .empty());
521   ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
522 
523   // Cancel the dialog - the app list should remain in the search result page,
524   // the suggestion removal dialog should be hidden, and no result action should
525   // be invoked.
526   GetSearchResultPageAnchoredDialog()->CancelDialog();
527 
528   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
529   EXPECT_FALSE(search_result_page()->anchored_dialog_for_test());
530   EXPECT_TRUE(GetAppListTestHelper()
531                   ->app_list_client()
532                   ->GetAndClearInvokedResultActions()
533                   .empty());
534 
535   // Click remove suggestion action button again.
536   ClickMouseAt(action_view->GetBoundsInScreen().CenterPoint());
537 
538   // Expect the removal confirmation dialog - this time, accept it.
539   ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
540   GetSearchResultPageAnchoredDialog()->AcceptDialog();
541 
542   // The app list should remain showing search results, the dialog should be
543   // closed, and result removal action should be invoked.
544   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
545   EXPECT_FALSE(search_result_page()->anchored_dialog_for_test());
546 
547   std::vector<TestAppListClient::SearchResultActionId> expected_actions = {
548       {kTestResultId, OmniBoxZeroStateAction::kRemoveSuggestion}};
549   std::vector<TestAppListClient::SearchResultActionId> invoked_actions =
550       GetAppListTestHelper()
551           ->app_list_client()
552           ->GetAndClearInvokedResultActions();
553   EXPECT_EQ(expected_actions, invoked_actions);
554 }
555 
TEST_F(AppListPresenterDelegateTest,RemoveSuggestionUsingLongTap)556 TEST_F(AppListPresenterDelegateTest, RemoveSuggestionUsingLongTap) {
557   ShowZeroStateSearchInHalfState();
558 
559   // Add a zero state suggestion results - the result that will be tested is in
560   // the second place.
561   Shell::Get()->app_list_controller()->GetSearchModel()->results()->Add(
562       CreateOmniboxSuggestionResult("Another suggestion"));
563   const std::string kTestResultId = "Test suggestion";
564   Shell::Get()->app_list_controller()->GetSearchModel()->results()->Add(
565       CreateOmniboxSuggestionResult(kTestResultId));
566   GetAppListTestHelper()->WaitUntilIdle();
567 
568   SearchResultBaseView* result_view = GetSearchResultListViewItemAt(1);
569   ASSERT_TRUE(result_view);
570   ASSERT_TRUE(result_view->result());
571   ASSERT_EQ(kTestResultId, result_view->result()->id());
572 
573   // Make sure the search results page is laid out after adding result action
574   // buttons.
575   GetAppListView()->GetWidget()->LayoutRootViewIfNecessary();
576 
577   // Long tap on the search result. This should show the removal confirmation
578   // dialog.
579   LongPressAt(result_view->GetBoundsInScreen().CenterPoint());
580 
581   EXPECT_TRUE(result_view->selected());
582   EXPECT_TRUE(GetAppListTestHelper()
583                   ->app_list_client()
584                   ->GetAndClearInvokedResultActions()
585                   .empty());
586   ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
587 
588   // Cancel the dialog - the app list should remain in the search result page,
589   // the suggestion removal dialog should be hidden, and no result action should
590   // be invoked.
591   GetSearchResultPageAnchoredDialog()->CancelDialog();
592 
593   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
594   EXPECT_FALSE(search_result_page()->anchored_dialog_for_test());
595   EXPECT_TRUE(GetAppListTestHelper()
596                   ->app_list_client()
597                   ->GetAndClearInvokedResultActions()
598                   .empty());
599   EXPECT_FALSE(result_view->selected());
600 
601   // Long tap on the result again.
602   LongPressAt(result_view->GetBoundsInScreen().CenterPoint());
603 
604   // Expect the removal confirmation dialog - this time, accept it.
605   ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
606   GetSearchResultPageAnchoredDialog()->AcceptDialog();
607 
608   // The app list should remain showing search results, the dialog should be
609   // closed, and result removal action should be invoked.
610   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
611   EXPECT_FALSE(search_result_page()->anchored_dialog_for_test());
612   EXPECT_FALSE(result_view->selected());
613 
614   std::vector<TestAppListClient::SearchResultActionId> expected_actions = {
615       {kTestResultId, OmniBoxZeroStateAction::kRemoveSuggestion}};
616 
617   std::vector<TestAppListClient::SearchResultActionId> invoked_actions =
618       GetAppListTestHelper()
619           ->app_list_client()
620           ->GetAndClearInvokedResultActions();
621   EXPECT_EQ(expected_actions, invoked_actions);
622 }
623 
TEST_F(AppListPresenterDelegateTest,RemoveSuggestionDialogAnimatesWithAppListView)624 TEST_F(AppListPresenterDelegateTest,
625        RemoveSuggestionDialogAnimatesWithAppListView) {
626   ShowZeroStateSearchInHalfState();
627 
628   // Add a zero state suggestion result.
629   const std::string kTestResultId = "Test suggestion";
630   Shell::Get()->app_list_controller()->GetSearchModel()->results()->Add(
631       CreateOmniboxSuggestionResult(kTestResultId));
632   GetAppListTestHelper()->WaitUntilIdle();
633 
634   SearchResultBaseView* result_view = GetSearchResultListViewItemAt(0);
635   ASSERT_TRUE(result_view);
636   ASSERT_TRUE(result_view->result());
637   ASSERT_EQ(kTestResultId, result_view->result()->id());
638 
639   // Show remove suggestion dialog.
640   LongPressAt(result_view->GetBoundsInScreen().CenterPoint());
641   ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
642 
643   views::Widget* const confirmation_dialog =
644       search_result_page()->anchored_dialog_for_test()->widget();
645   ASSERT_TRUE(confirmation_dialog);
646 
647   SanityCheckSearchResultsAnchoredDialogBounds(confirmation_dialog);
648   const gfx::Rect initial_dialog_bounds =
649       confirmation_dialog->GetWindowBoundsInScreen();
650 
651   ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
652       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
653   AppListView::SetShortAnimationForTesting(false);
654 
655   // Transition to fullscreen search state.
656   GetAppListView()->SetState(AppListViewState::kFullscreenSearch);
657   ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
658 
659   EXPECT_NE(confirmation_dialog->GetLayer()->transform(), gfx::Transform());
660   EXPECT_EQ(confirmation_dialog->GetLayer()->GetTargetTransform(),
661             gfx::Transform());
662 
663   // Verify that the dialog position in screen does not change when the
664   // animation starts.
665   gfx::RectF current_bounds(confirmation_dialog->GetWindowBoundsInScreen());
666   confirmation_dialog->GetLayer()->transform().TransformRect(&current_bounds);
667   EXPECT_EQ(gfx::RectF(initial_dialog_bounds), current_bounds);
668 }
669 
TEST_F(AppListPresenterDelegateTest,RemoveSuggestionDialogBoundsUpdateWithAppListState)670 TEST_F(AppListPresenterDelegateTest,
671        RemoveSuggestionDialogBoundsUpdateWithAppListState) {
672   ShowZeroStateSearchInHalfState();
673 
674   // Add a zero state suggestion result.
675   const std::string kTestResultId = "Test suggestion";
676   Shell::Get()->app_list_controller()->GetSearchModel()->results()->Add(
677       CreateOmniboxSuggestionResult(kTestResultId));
678   GetAppListTestHelper()->WaitUntilIdle();
679 
680   SearchResultBaseView* result_view = GetSearchResultListViewItemAt(0);
681   ASSERT_TRUE(result_view);
682   ASSERT_TRUE(result_view->result());
683   ASSERT_EQ(kTestResultId, result_view->result()->id());
684 
685   // Show the remove suggestion dialog.
686   LongPressAt(result_view->GetBoundsInScreen().CenterPoint());
687   ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
688 
689   views::Widget* const confirmation_dialog =
690       search_result_page()->anchored_dialog_for_test()->widget();
691   ASSERT_TRUE(confirmation_dialog);
692 
693   SCOPED_TRACE("Initial confirmation dialog bounds");
694   SanityCheckSearchResultsAnchoredDialogBounds(confirmation_dialog);
695   const int dialog_margin =
696       GetSearchResultsAnchoredDialogTopOffset(confirmation_dialog);
697 
698   // Transition to fullscreen search state.
699   GetAppListView()->SetState(AppListViewState::kFullscreenSearch);
700   ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
701 
702   // Verify that the confirmation dialog followed the search box widget.
703   SCOPED_TRACE("Confirmation dialog bounds after transition");
704   SanityCheckSearchResultsAnchoredDialogBounds(confirmation_dialog);
705   EXPECT_EQ(dialog_margin,
706             GetSearchResultsAnchoredDialogTopOffset(confirmation_dialog));
707 }
708 
TEST_F(AppListPresenterDelegateTest,TransitionToAppsContainerClosesRemoveSuggestionDialog)709 TEST_F(AppListPresenterDelegateTest,
710        TransitionToAppsContainerClosesRemoveSuggestionDialog) {
711   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
712   GetAppListView()->SetState(AppListViewState::kFullscreenAllApps);
713   ui::test::EventGenerator* generator = GetEventGenerator();
714   generator->GestureTapAt(GetPointInsideSearchbox());
715   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
716 
717   // Add a zero state suggestion result.
718   const std::string kTestResultId = "Test suggestion";
719   Shell::Get()->app_list_controller()->GetSearchModel()->results()->Add(
720       CreateOmniboxSuggestionResult(kTestResultId));
721   GetAppListTestHelper()->WaitUntilIdle();
722 
723   SearchResultBaseView* result_view = GetSearchResultListViewItemAt(0);
724   ASSERT_TRUE(result_view);
725   ASSERT_TRUE(result_view->result());
726   ASSERT_EQ(kTestResultId, result_view->result()->id());
727 
728   // Show remove suggestion dialog.
729   ui::TouchEvent long_press(
730       ui::ET_GESTURE_LONG_PRESS, result_view->GetBoundsInScreen().CenterPoint(),
731       base::TimeTicks::Now(), ui::PointerDetails(ui::EventPointerType::kTouch));
732   GetEventGenerator()->Dispatch(&long_press);
733   ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
734 
735   views::Widget* const confirmation_dialog =
736       search_result_page()->anchored_dialog_for_test()->widget();
737   ASSERT_TRUE(confirmation_dialog);
738 
739   SanityCheckSearchResultsAnchoredDialogBounds(confirmation_dialog);
740 
741   // Verify that transition to apps page hides the removal confirmation dialog.
742   views::test::WidgetClosingObserver widget_close_waiter(confirmation_dialog);
743   GetAppListView()->SetState(AppListViewState::kFullscreenAllApps);
744 
745   widget_close_waiter.Wait();
746 }
747 
TEST_F(AppListPresenterDelegateTest,RemoveSuggestionDialogBoundsUpdateWhenVKHidden)748 TEST_F(AppListPresenterDelegateTest,
749        RemoveSuggestionDialogBoundsUpdateWhenVKHidden) {
750   // Enable virtual keyboard for this test.
751   KeyboardController* const keyboard_controller =
752       Shell::Get()->keyboard_controller();
753   keyboard_controller->SetEnableFlag(
754       keyboard::KeyboardEnableFlag::kCommandLineEnabled);
755 
756   ShowZeroStateSearchInHalfState();
757 
758   // Add a zero state suggestion result.
759   const std::string kTestResultId = "Test suggestion";
760   Shell::Get()->app_list_controller()->GetSearchModel()->results()->Add(
761       CreateOmniboxSuggestionResult(kTestResultId));
762   GetAppListTestHelper()->WaitUntilIdle();
763 
764   SearchResultBaseView* result_view = GetSearchResultListViewItemAt(0);
765   ASSERT_TRUE(result_view);
766   ASSERT_TRUE(result_view->result());
767   ASSERT_EQ(kTestResultId, result_view->result()->id());
768 
769   auto* const keyboard_ui_controller = keyboard::KeyboardUIController::Get();
770   keyboard_ui_controller->ShowKeyboard(false /* locked */);
771   ASSERT_TRUE(keyboard::WaitUntilShown());
772 
773   // Show remove suggestion dialog.
774   LongPressAt(result_view->GetBoundsInScreen().CenterPoint());
775   ASSERT_TRUE(search_result_page()->anchored_dialog_for_test());
776 
777   // The search box should have lost the focus, which should have hidden the
778   // keyboard.
779   EXPECT_FALSE(keyboard_ui_controller->IsKeyboardVisible());
780 
781   // Sanity check the confirmation dialog bounds (hiding the keyboard might have
782   // changed the position of the search box - the confirmation dialog should
783   // have followed it).
784   views::Widget* const confirmation_dialog =
785       search_result_page()->anchored_dialog_for_test()->widget();
786   SanityCheckSearchResultsAnchoredDialogBounds(confirmation_dialog);
787 
788   views::test::WidgetClosingObserver widget_close_waiter(confirmation_dialog);
789 
790   // Go to peeking state, and verify the keyboard is not reshown.
791   GetAppListView()->SetState(AppListViewState::kPeeking);
792   GetAppListTestHelper()->WaitUntilIdle();
793   // Exiting the search results page should close the dialog.
794   widget_close_waiter.Wait();
795   EXPECT_FALSE(keyboard_controller->IsKeyboardVisible());
796 
797   GetAppListTestHelper()->DismissAndRunLoop();
798   GetAppListTestHelper()->CheckVisibility(false);
799   EXPECT_FALSE(keyboard_controller->IsKeyboardVisible());
800 }
801 
802 // Verifies that the downward mouse drag on AppsGridView's first page should
803 // be handled by AppList.
TEST_F(PopulatedAppListTest,MouseDragAppsGridViewHandledByAppList)804 TEST_F(PopulatedAppListTest, MouseDragAppsGridViewHandledByAppList) {
805   InitializeAppsGrid();
806   app_list_test_model_->PopulateApps(2);
807   ShowAppListInAppsFullScreen();
808 
809   // Calculate the drag start/end points.
810   gfx::Point drag_start_point = apps_grid_view_->GetBoundsInScreen().origin();
811   gfx::Point target_point = GetPrimaryDisplay().bounds().bottom_left();
812   target_point.set_x(drag_start_point.x());
813 
814   // Drag AppsGridView downward by mouse. Check the following things:
815   // (1) Mouse events are processed by AppsGridView, including mouse press,
816   // mouse drag and mouse release.
817   // (2) AppList is closed after mouse drag.
818   ui::test::EventGenerator* event_generator = GetEventGenerator();
819   event_generator->MoveMouseTo(drag_start_point);
820   event_generator->DragMouseTo(target_point);
821   event_generator->ReleaseLeftButton();
822 
823   base::RunLoop().RunUntilIdle();
824   GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
825 }
826 
827 // Verifies that the upward mouse drag on AppsGridView's first page should
828 // be handled by PaginationController.
TEST_F(PopulatedAppListTest,MouseDragAppsGridViewHandledByPaginationController)829 TEST_F(PopulatedAppListTest,
830        MouseDragAppsGridViewHandledByPaginationController) {
831   InitializeAppsGrid();
832   app_list_test_model_->PopulateApps(apps_grid_test_api_->TilesPerPage(0) + 1);
833   EXPECT_EQ(2, apps_grid_view_->pagination_model()->total_pages());
834   ShowAppListInAppsFullScreen();
835 
836   // Calculate the drag start/end points. |drag_start_point| is between the
837   // first and the second AppListItem. Because in this test case, we want
838   // AppsGridView to receive mouse events instead of AppListItemView.
839   gfx::Point right_side =
840       apps_grid_view_->GetItemViewAt(0)->GetBoundsInScreen().right_center();
841   gfx::Point left_side =
842       apps_grid_view_->GetItemViewAt(1)->GetBoundsInScreen().left_center();
843   ASSERT_EQ(left_side.y(), right_side.y());
844   gfx::Point drag_start_point((right_side.x() + left_side.x()) / 2,
845                               right_side.y());
846   gfx::Point target_point = GetPrimaryDisplay().bounds().top_right();
847   target_point.set_x(drag_start_point.x());
848 
849   // Drag AppsGridView downward by mouse. Checks that PaginationController
850   // records the mouse drag.
851   base::HistogramTester histogram_tester;
852   ui::test::EventGenerator* event_generator = GetEventGenerator();
853   event_generator->MoveMouseTo(drag_start_point);
854   event_generator->DragMouseTo(target_point);
855   event_generator->ReleaseLeftButton();
856   histogram_tester.ExpectUniqueSample(
857       kAppListPageSwitcherSourceHistogramInClamshell,
858       AppListPageSwitcherSource::kMouseDrag, 1);
859 }
860 
861 // Tests that mouse app list item drag is cancelled when mouse capture is lost
862 // (e.g. on screen rotation).
TEST_F(PopulatedAppListTest,CancelItemDragOnMouseCaptureLoss)863 TEST_F(PopulatedAppListTest, CancelItemDragOnMouseCaptureLoss) {
864   InitializeAppsGrid();
865   app_list_test_model_->PopulateApps(apps_grid_test_api_->TilesPerPage(0) + 1);
866   ShowAppListInAppsFullScreen();
867 
868   AppListItemView* const dragged_view = apps_grid_view_->GetItemViewAt(0);
869 
870   // Start dragging the first item - move it in between items 1 and 2.
871   ui::test::EventGenerator* event_generator = GetEventGenerator();
872   event_generator->MoveMouseTo(dragged_view->GetBoundsInScreen().CenterPoint());
873   event_generator->PressLeftButton();
874   dragged_view->FireMouseDragTimerForTest();
875   event_generator->MoveMouseTo(
876       apps_grid_view_->GetItemViewAt(2)->GetBoundsInScreen().left_center());
877   EXPECT_TRUE(apps_grid_view_->dragging());
878 
879   display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
880   display_manager()->SetDisplayRotation(
881       display.id(), display::Display::ROTATE_270,
882       display::Display::RotationSource::ACTIVE);
883   // AppListView is usually notified of display bounds changes by
884   // AppListPresenterDelegate, though the test delegate implementation does not
885   // track display metrics changes, so OnParentWindowBoundsChanged() has to be
886   // explicitly called here.
887   app_list_view_->OnParentWindowBoundsChanged();
888 
889   // Verify that mouse drag has been canceled due to mouse capture loss.
890   EXPECT_FALSE(apps_grid_view_->dragging());
891   EXPECT_EQ("Item 0", apps_grid_view_->GetItemViewAt(0)->item()->id());
892   EXPECT_EQ("Item 1", apps_grid_view_->GetItemViewAt(1)->item()->id());
893   EXPECT_EQ("Item 2", apps_grid_view_->GetItemViewAt(2)->item()->id());
894 }
895 
896 // Tests that apps grid item layers are not destroyed immediately after item
897 // drag ends.
TEST_F(PopulatedAppListTest,ItemLayersNotDestroyedDuringBoundsAnimationAfterDrag)898 TEST_F(PopulatedAppListTest,
899        ItemLayersNotDestroyedDuringBoundsAnimationAfterDrag) {
900   InitializeAppsGrid();
901   const int kItemCount = 5;
902   app_list_test_model_->PopulateApps(kItemCount);
903   ShowAppListInAppsFullScreen();
904 
905   ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
906       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
907   AppListView::SetShortAnimationForTesting(false);
908 
909   AppListItemView* const dragged_view = apps_grid_view_->GetItemViewAt(0);
910 
911   // Drag the first item between items 1 and 2.
912   ui::test::EventGenerator* event_generator = GetEventGenerator();
913   event_generator->MoveMouseTo(dragged_view->GetBoundsInScreen().CenterPoint());
914   event_generator->PressLeftButton();
915   dragged_view->FireMouseDragTimerForTest();
916   event_generator->MoveMouseTo(
917       apps_grid_view_->GetItemViewAt(2)->GetBoundsInScreen().left_center());
918 
919   // Items should have layers during app list item drag.
920   for (int i = 0; i < kItemCount; ++i) {
921     views::View* item_view = apps_grid_view_->view_model()->view_at(i);
922     EXPECT_TRUE(item_view->layer()) << "at " << i;
923   }
924 
925   EXPECT_TRUE(apps_grid_view_->dragging());
926   event_generator->ReleaseLeftButton();
927 
928   // After the drag is released, the item bounds should animate to their final
929   // bounds.
930   EXPECT_TRUE(apps_grid_view_->bounds_animator_for_testing()->IsAnimating());
931   for (int i = 0; i < kItemCount; ++i) {
932     views::View* item_view = apps_grid_view_->view_model()->view_at(i);
933     EXPECT_TRUE(item_view->layer()) << "at " << i;
934   }
935 
936   // Layers should be destroyed once the bounds animation completes.
937   apps_grid_view_->bounds_animator_for_testing()->Cancel();
938   for (int i = 0; i < kItemCount; ++i) {
939     views::View* item_view = apps_grid_view_->view_model()->view_at(i);
940     EXPECT_FALSE(item_view->layer()) << "at " << i;
941   }
942 }
943 
944 // Tests that apps grid item drag operation can continue normally after display
945 // rotation (and app list config change).
TEST_F(PopulatedAppListTest,ScreenRotationDuringAppsGridItemDrag)946 TEST_F(PopulatedAppListTest, ScreenRotationDuringAppsGridItemDrag) {
947   // Set the display dimensions so rotation also changes the app list config.
948   UpdateDisplay("1200x600");
949 
950   InitializeAppsGrid();
951   app_list_test_model_->PopulateApps(apps_grid_test_api_->TilesPerPage(0) + 1);
952   ShowAppListInAppsFullScreen();
953 
954   AppListItemView* const dragged_view = apps_grid_view_->GetItemViewAt(0);
955 
956   // Start dragging the first item.
957   ui::test::EventGenerator* event_generator = GetEventGenerator();
958   event_generator->MoveTouch(dragged_view->GetBoundsInScreen().CenterPoint());
959   event_generator->PressTouch();
960   ASSERT_TRUE(dragged_view->FireTouchDragTimerForTest());
961 
962   event_generator->MoveTouch(
963       apps_grid_view_->GetItemViewAt(2)->GetBoundsInScreen().CenterPoint());
964 
965   display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
966   display_manager()->SetDisplayRotation(
967       display.id(), display::Display::ROTATE_270,
968       display::Display::RotationSource::ACTIVE);
969   // AppListView is usually notified of display bounds changes by
970   // AppListPresenterDelegate, though the test delegate implementation does not
971   // track display metrics changes, so OnParentWindowBoundsChanged() has to be
972   // explicitly called here.
973   app_list_view_->OnParentWindowBoundsChanged();
974 
975   // End drag at the in between items 1 and 2 - note that these have been
976   // translated one slot left to fill in space left by the dragged view, so the
977   // expected drop slot is actually slot 1.
978   event_generator->MoveTouch(
979       apps_grid_view_->GetItemViewAt(2)->GetBoundsInScreen().left_center());
980   event_generator->ReleaseTouch();
981 
982   EXPECT_EQ("Item 1", apps_grid_view_->GetItemViewAt(0)->item()->id());
983   EXPECT_EQ("Item 0", apps_grid_view_->GetItemViewAt(1)->item()->id());
984 }
985 
986 // Tests screen rotation during apps grid item drag where the drag item ends up
987 // in page-scroll area. Tests that the apps grid page scrolls without a crash,
988 // and that releasing drag does not change the item position in the model.
TEST_F(PopulatedAppListTest,ScreenRotationDuringAppsGridItemDragWithPageScroll)989 TEST_F(PopulatedAppListTest,
990        ScreenRotationDuringAppsGridItemDragWithPageScroll) {
991   // Set the display dimensions so rotation also changes the app list config.
992   UpdateDisplay("1200x600");
993 
994   InitializeAppsGrid();
995   app_list_test_model_->PopulateApps(apps_grid_test_api_->TilesPerPage(0) + 1);
996   ShowAppListInAppsFullScreen();
997 
998   AppListItemView* const dragged_view = apps_grid_view_->GetItemViewAt(0);
999 
1000   // Start dragging the first item.
1001   ui::test::EventGenerator* event_generator = GetEventGenerator();
1002   event_generator->MoveTouch(dragged_view->GetBoundsInScreen().CenterPoint());
1003   event_generator->PressTouch();
1004   ASSERT_TRUE(dragged_view->FireTouchDragTimerForTest());
1005 
1006   // Move the item close to screen edge, so it ends up in area that triggers
1007   // page scroll after rotation.
1008   event_generator->MoveTouch(app_list_view_->GetBoundsInScreen().left_center() +
1009                              gfx::Vector2d(100, 0));
1010 
1011   display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
1012   display_manager()->SetDisplayRotation(
1013       display.id(), display::Display::ROTATE_90,
1014       display::Display::RotationSource::ACTIVE);
1015   // AppListView is usually notified of display bounds changes by
1016   // AppListPresenterDelegate, though the test delegate implementation does not
1017   // track display metrics changes, so OnParentWindowBoundsChanged() has to be
1018   // explicitly called here.
1019   app_list_view_->OnParentWindowBoundsChanged();
1020 
1021   event_generator->MoveTouchBy(0, 10);
1022   EXPECT_TRUE(apps_grid_view_->FirePageFlipTimerForTest());
1023   event_generator->ReleaseTouch();
1024 
1025   // The model state should not have been changed.
1026   EXPECT_EQ("Item 0", apps_grid_view_->GetItemViewAt(0)->item()->id());
1027   EXPECT_EQ("Item 1", apps_grid_view_->GetItemViewAt(1)->item()->id());
1028   EXPECT_EQ("Item 2", apps_grid_view_->GetItemViewAt(2)->item()->id());
1029 }
1030 
1031 // Tests screen rotation while app list folder item is in progress, and the item
1032 // remains in the folder bounds during the drag.
TEST_F(PopulatedAppListTest,ScreenRotationDuringFolderItemDrag)1033 TEST_F(PopulatedAppListTest, ScreenRotationDuringFolderItemDrag) {
1034   // Set the display dimensions so rotation also changes the app list config.
1035   UpdateDisplay("1200x600");
1036 
1037   InitializeAppsGrid();
1038   app_list_test_model_->PopulateApps(2);
1039   AppListFolderItem* folder =
1040       app_list_test_model_->CreateAndPopulateFolderWithApps(3);
1041   app_list_test_model_->PopulateApps(10);
1042   ShowAppListInAppsFullScreen();
1043 
1044   // Tap the folder item to show it.
1045   ui::test::EventGenerator* event_generator = GetEventGenerator();
1046   event_generator->GestureTapAt(
1047       apps_grid_view_->GetItemViewAt(2)->GetBoundsInScreen().CenterPoint());
1048   ASSERT_TRUE(AppListIsInFolderView());
1049 
1050   // Start dragging the first item in the active folder.
1051   AppListItemView* const dragged_view =
1052       folder_view()->items_grid_view()->GetItemViewAt(0);
1053   event_generator->MoveTouch(dragged_view->GetBoundsInScreen().CenterPoint());
1054   event_generator->PressTouch();
1055   ASSERT_TRUE(dragged_view->FireTouchDragTimerForTest());
1056 
1057   // Drag the item within the folder bounds.
1058   event_generator->MoveTouch(
1059       apps_grid_view_->GetItemViewAt(2)->GetBoundsInScreen().CenterPoint());
1060 
1061   display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
1062   display_manager()->SetDisplayRotation(
1063       display.id(), display::Display::ROTATE_270,
1064       display::Display::RotationSource::ACTIVE);
1065   // AppListView is usually notified of display bounds changes by
1066   // AppListPresenterDelegate, though the test delegate implementation does not
1067   // track display metrics changes, so OnParentWindowBoundsChanged() has to be
1068   // explicitly called here.
1069   app_list_view_->OnParentWindowBoundsChanged();
1070 
1071   // The current behavior on app list bounds change is to close the active
1072   // folder, canceling the drag.
1073   EXPECT_FALSE(AppListIsInFolderView());
1074   EXPECT_FALSE(apps_grid_view_->dragging());
1075   EXPECT_FALSE(folder_view()->items_grid_view()->dragging());
1076 
1077   EXPECT_EQ("Item 0", apps_grid_view_->GetItemViewAt(0)->item()->id());
1078   EXPECT_EQ("Item 1", apps_grid_view_->GetItemViewAt(1)->item()->id());
1079   EXPECT_EQ(folder->id(), apps_grid_view_->GetItemViewAt(2)->item()->id());
1080   EXPECT_EQ(dragged_view, folder_view()->items_grid_view()->GetItemViewAt(0));
1081   EXPECT_EQ("Item 3", apps_grid_view_->GetItemViewAt(3)->item()->id());
1082 }
1083 
1084 // Tests that app list folder item reparenting drag (where a folder item is
1085 // dragged outside the folder bounds, and dropped within the apps grid) can
1086 // continue normally after screen rotation.
TEST_F(PopulatedAppListTest,ScreenRotationDuringAppsGridItemReparentDrag)1087 TEST_F(PopulatedAppListTest, ScreenRotationDuringAppsGridItemReparentDrag) {
1088   UpdateDisplay("1200x600");
1089 
1090   InitializeAppsGrid();
1091   app_list_test_model_->PopulateApps(2);
1092   AppListFolderItem* folder =
1093       app_list_test_model_->CreateAndPopulateFolderWithApps(3);
1094   app_list_test_model_->PopulateApps(10);
1095   ShowAppListInAppsFullScreen();
1096 
1097   // Tap the folder item to show it.
1098   ui::test::EventGenerator* event_generator = GetEventGenerator();
1099   event_generator->GestureTapAt(
1100       apps_grid_view_->GetItemViewAt(2)->GetBoundsInScreen().CenterPoint());
1101   ASSERT_TRUE(AppListIsInFolderView());
1102 
1103   // Start dragging the first item in the active folder.
1104   AppListItemView* dragged_view =
1105       folder_view()->items_grid_view()->GetItemViewAt(0);
1106   event_generator->MoveTouch(dragged_view->GetBoundsInScreen().CenterPoint());
1107   event_generator->PressTouch();
1108   ASSERT_TRUE(dragged_view->FireTouchDragTimerForTest());
1109 
1110   // Drag the item outside the folder bounds.
1111   event_generator->MoveTouch(
1112       apps_grid_view_->GetItemViewAt(1)->GetBoundsInScreen().CenterPoint());
1113   event_generator->MoveTouchBy(2, 2);
1114 
1115   // Fire reparenting timer.
1116   EXPECT_TRUE(
1117       folder_view()->items_grid_view()->FireFolderItemReparentTimerForTest());
1118   EXPECT_FALSE(AppListIsInFolderView());
1119 
1120   display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
1121   display_manager()->SetDisplayRotation(
1122       display.id(), display::Display::ROTATE_270,
1123       display::Display::RotationSource::ACTIVE);
1124   // AppListView is usually notified of display bounds changes by
1125   // AppListPresenterDelegate, though the test delegate implementation does not
1126   // track display metrics changes, so OnParentWindowBoundsChanged() has to be
1127   // explicitly called here.
1128   app_list_view_->OnParentWindowBoundsChanged();
1129 
1130   // End drag at the in between items 1 and 2.
1131   event_generator->MoveTouch(
1132       apps_grid_view_->GetItemViewAt(1)->GetBoundsInScreen().right_center());
1133   event_generator->ReleaseTouch();
1134 
1135   // Verify the new item location within the apps grid.
1136   EXPECT_EQ("Item 0", apps_grid_view_->GetItemViewAt(0)->item()->id());
1137   EXPECT_EQ("Item 1", apps_grid_view_->GetItemViewAt(1)->item()->id());
1138   EXPECT_EQ(dragged_view->item()->id(),
1139             apps_grid_view_->GetItemViewAt(2)->item()->id());
1140   EXPECT_EQ(folder->id(), apps_grid_view_->GetItemViewAt(3)->item()->id());
1141 }
1142 
1143 // Tests that app list folder item reparenting drag to another folder.
TEST_F(PopulatedAppListTest,AppsGridItemReparentToFolderDrag)1144 TEST_F(PopulatedAppListTest, AppsGridItemReparentToFolderDrag) {
1145   UpdateDisplay("1200x600");
1146 
1147   InitializeAppsGrid();
1148   app_list_test_model_->PopulateApps(2);
1149   AppListFolderItem* folder =
1150       app_list_test_model_->CreateAndPopulateFolderWithApps(3);
1151   app_list_test_model_->PopulateApps(10);
1152   ShowAppListInAppsFullScreen();
1153 
1154   // Tap the folder item to show it.
1155   ui::test::EventGenerator* event_generator = GetEventGenerator();
1156   event_generator->GestureTapAt(
1157       apps_grid_view_->GetItemViewAt(2)->GetBoundsInScreen().CenterPoint());
1158   ASSERT_TRUE(AppListIsInFolderView());
1159 
1160   // Start dragging the first item in the active folder.
1161   AppListItemView* dragged_view =
1162       folder_view()->items_grid_view()->GetItemViewAt(0);
1163   event_generator->MoveTouch(dragged_view->GetBoundsInScreen().CenterPoint());
1164   event_generator->PressTouch();
1165   ASSERT_TRUE(dragged_view->FireTouchDragTimerForTest());
1166 
1167   // Drag the item outside the folder bounds.
1168   event_generator->MoveTouch(
1169       apps_grid_view_->GetItemViewAt(0)->GetBoundsInScreen().CenterPoint());
1170   event_generator->MoveTouchBy(2, 2);
1171 
1172   EXPECT_TRUE(
1173       folder_view()->items_grid_view()->FireFolderItemReparentTimerForTest());
1174   EXPECT_FALSE(AppListIsInFolderView());
1175 
1176   // Move the pointer over the item 3, and drop the dragged item.
1177   gfx::Point target =
1178       apps_grid_view_->GetItemViewAt(3)->GetBoundsInScreen().CenterPoint();
1179   event_generator->MoveTouch(target);
1180   EXPECT_TRUE(apps_grid_view_->FireFolderDroppingTimerForTest());
1181   event_generator->ReleaseTouch();
1182 
1183   // Verify the new item location within the apps grid.
1184   EXPECT_EQ("Item 0", apps_grid_view_->GetItemViewAt(0)->item()->id());
1185   EXPECT_EQ("Item 1", apps_grid_view_->GetItemViewAt(1)->item()->id());
1186   EXPECT_EQ(folder->id(), apps_grid_view_->GetItemViewAt(2)->item()->id());
1187 
1188   EXPECT_TRUE(apps_grid_view_->GetItemViewAt(3)->item()->is_folder());
1189   EXPECT_EQ(dragged_view->item()->folder_id(),
1190             apps_grid_view_->GetItemViewAt(3)->item()->id());
1191 }
1192 
1193 // Tests that an item can be removed just after creating a folder that contains
1194 // that item. See https://crbug.com/1083942
TEST_F(PopulatedAppListTest,RemoveFolderItemAfterFolderCreation)1195 TEST_F(PopulatedAppListTest, RemoveFolderItemAfterFolderCreation) {
1196   InitializeAppsGrid();
1197   const int kItemCount = 5;
1198   app_list_test_model_->PopulateApps(kItemCount);
1199   ShowAppListInAppsFullScreen();
1200 
1201   // Dragging the item with index 4.
1202   AppListItemView* const dragged_view = apps_grid_view_->GetItemViewAt(4);
1203   AppListItem* const dragged_item = dragged_view->item();
1204 
1205   // Drag the item on top of the item with index 3.
1206   ui::test::EventGenerator* event_generator = GetEventGenerator();
1207   event_generator->MoveMouseTo(dragged_view->GetBoundsInScreen().CenterPoint());
1208   event_generator->PressLeftButton();
1209   dragged_view->FireMouseDragTimerForTest();
1210   event_generator->MoveMouseTo(
1211       apps_grid_view_->GetItemViewAt(3)->GetBoundsInScreen().CenterPoint());
1212   EXPECT_TRUE(apps_grid_view_->FireFolderDroppingTimerForTest());
1213   event_generator->ReleaseLeftButton();
1214   EXPECT_FALSE(apps_grid_view_->dragging());
1215 
1216   EXPECT_TRUE(apps_grid_view_->GetItemViewAt(3)->item()->is_folder());
1217   EXPECT_EQ(dragged_item->folder_id(),
1218             apps_grid_view_->GetItemViewAt(3)->item()->id());
1219 
1220   // Verify that item layers have been destroyed after the drag operation ended.
1221   apps_grid_test_api_->WaitForItemMoveAnimationDone();
1222 
1223   for (int i = 0; i < apps_grid_view_->view_model()->view_size(); ++i) {
1224     views::View* item_view = apps_grid_view_->view_model()->view_at(i);
1225     EXPECT_FALSE(item_view->layer()) << "at " << i;
1226   }
1227 
1228   // Open the newly created folder.
1229   event_generator->MoveMouseTo(
1230       apps_grid_view_->GetItemViewAt(3)->GetBoundsInScreen().CenterPoint());
1231   event_generator->ClickLeftButton();
1232   event_generator->ReleaseLeftButton();
1233 
1234   // Verify that item views have no layers after the folder has been opened.
1235   apps_grid_test_api_->WaitForItemMoveAnimationDone();
1236   EXPECT_TRUE(AppListIsInFolderView());
1237 
1238   for (int i = 0; i < apps_grid_view_->view_model()->view_size(); ++i) {
1239     views::View* item_view = apps_grid_view_->view_model()->view_at(i);
1240     EXPECT_FALSE(item_view->layer()) << "at " << i;
1241   }
1242 
1243   // Verify that a pending layout, if any, does not cause a crash.
1244   apps_grid_view_->InvalidateLayout();
1245   apps_grid_view_->GetWidget()->LayoutRootViewIfNecessary();
1246 
1247   // Remove the original drag view item.
1248   app_list_test_model_->DeleteUninstalledItem(dragged_item->id());
1249   apps_grid_test_api_->WaitForItemMoveAnimationDone();
1250 
1251   EXPECT_FALSE(AppListIsInFolderView());
1252   EXPECT_FALSE(apps_grid_view_->GetItemViewAt(3)->item()->is_folder());
1253 
1254   // Verify that a pending layout, if any, does not cause a crash.
1255   apps_grid_view_->InvalidateLayout();
1256   apps_grid_view_->GetWidget()->LayoutRootViewIfNecessary();
1257 }
1258 
TEST_F(PopulatedAppListWithVKEnabledTest,TappingAppsGridClosesVirtualKeyboard)1259 TEST_F(PopulatedAppListWithVKEnabledTest,
1260        TappingAppsGridClosesVirtualKeyboard) {
1261   InitializeAppsGrid();
1262   app_list_test_model_->PopulateApps(2);
1263   gfx::Point between_apps = GetItemRectOnCurrentPageAt(0, 0).right_center();
1264   gfx::Point empty_space = GetItemRectOnCurrentPageAt(0, 2).CenterPoint();
1265 
1266   ui::GestureEvent tap_between(between_apps.x(), between_apps.y(), 0,
1267                                base::TimeTicks(),
1268                                ui::GestureEventDetails(ui::ET_GESTURE_TAP));
1269   ui::GestureEvent tap_outside(empty_space.x(), empty_space.y(), 0,
1270                                base::TimeTicks(),
1271                                ui::GestureEventDetails(ui::ET_GESTURE_TAP));
1272 
1273   // Manually show the virtual keyboard.
1274   auto* const keyboard_controller = keyboard::KeyboardUIController::Get();
1275   keyboard_controller->ShowKeyboard(true /* locked */);
1276   ASSERT_TRUE(keyboard::WaitUntilShown());
1277 
1278   // Touch the apps_grid outside of any apps
1279   apps_grid_view_->OnGestureEvent(&tap_outside);
1280   // Expect that the event is ignored here and allowed to propogate to app_list
1281   EXPECT_FALSE(tap_outside.handled());
1282   // Hit the app_list with the same event
1283   app_list_view_->OnGestureEvent(&tap_outside);
1284   // Expect that the event is handled and the keyboard is closed.
1285   EXPECT_TRUE(tap_outside.handled());
1286   EXPECT_FALSE(keyboard_controller->IsKeyboardVisible());
1287 
1288   // Reshow the VKeyboard
1289   keyboard_controller->ShowKeyboard(true);
1290   ASSERT_TRUE(keyboard::WaitUntilShown());
1291 
1292   // Touch the apps_grid between two apps
1293   apps_grid_view_->OnGestureEvent(&tap_between);
1294   // Expect the event to be handled in the grid, and the keyboard to be closed.
1295   EXPECT_TRUE(tap_between.handled());
1296   EXPECT_FALSE(keyboard_controller->IsKeyboardVisible());
1297 }
1298 
1299 // Tests that a folder item that is dragged to the page flip area and released
1300 // will discard empty pages in the apps grid. If an empty page is not discarded,
1301 // the apps grid crashes (See http://crbug.com/1100011).
TEST_F(PopulatedAppListTest,FolderItemDroppedRemovesBlankPage)1302 TEST_F(PopulatedAppListTest, FolderItemDroppedRemovesBlankPage) {
1303   InitializeAppsGrid();
1304   app_list_test_model_->CreateAndPopulateFolderWithApps(3);
1305   app_list_test_model_->PopulateApps(2);
1306   ShowAppListInAppsFullScreen();
1307   ASSERT_EQ(1, apps_grid_view_->pagination_model()->total_pages());
1308 
1309   // Tap the folder item to show its contents.
1310   ui::test::EventGenerator* event_generator = GetEventGenerator();
1311   event_generator->GestureTapAt(
1312       apps_grid_view_->GetItemViewAt(0)->GetBoundsInScreen().CenterPoint());
1313   ASSERT_TRUE(AppListIsInFolderView());
1314 
1315   // Start dragging the first item in the active folder.
1316   AppListItemView* dragged_view =
1317       folder_view()->items_grid_view()->GetItemViewAt(0);
1318   event_generator->MoveTouch(dragged_view->GetBoundsInScreen().CenterPoint());
1319   event_generator->PressTouch();
1320   ASSERT_TRUE(dragged_view->FireTouchDragTimerForTest());
1321 
1322   // Move the pointer over the page flip area in the apps grid. We first fire
1323   // the folder item reparent timer. The folder view should be hidden.
1324   const gfx::Rect apps_grid_bounds = apps_grid_view_->GetBoundsInScreen();
1325   const gfx::Point page_flip_bottom_center =
1326       gfx::Point(apps_grid_bounds.width() / 2, apps_grid_bounds.bottom() + 1);
1327   event_generator->MoveTouch(page_flip_bottom_center);
1328   event_generator->MoveTouchBy(0, 5);
1329   EXPECT_TRUE(
1330       folder_view()->items_grid_view()->FireFolderItemReparentTimerForTest());
1331   EXPECT_FALSE(AppListIsInFolderView());
1332 
1333   // Move again to trigger the page flip timer, fire it and finish the page flip
1334   // animation. There should be 2 pages.
1335   event_generator->MoveTouchBy(0, -10);
1336   EXPECT_TRUE(apps_grid_view_->FirePageFlipTimerForTest());
1337   apps_grid_view_->pagination_model()->FinishAnimation();
1338   EXPECT_EQ(2, apps_grid_view_->pagination_model()->total_pages());
1339 
1340   // Release the dragged app. The dragged app should be still in the folder. The
1341   // newly blank page should be discarded and there should be no crash.
1342   event_generator->ReleaseTouch();
1343   EXPECT_EQ(1, apps_grid_view_->pagination_model()->total_pages());
1344   EXPECT_EQ(dragged_view, folder_view()->items_grid_view()->GetItemViewAt(0));
1345 }
1346 
1347 // Tests that app list hides when focus moves to a normal window.
TEST_F(AppListPresenterDelegateTest,HideOnFocusOut)1348 TEST_F(AppListPresenterDelegateTest, HideOnFocusOut) {
1349   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1350   GetAppListTestHelper()->CheckVisibility(true);
1351 
1352   std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
1353   wm::ActivateWindow(window.get());
1354   GetAppListTestHelper()->WaitUntilIdle();
1355   GetAppListTestHelper()->CheckVisibility(false);
1356 }
1357 
1358 // Tests that app list remains visible when focus is moved to a different
1359 // window in kShellWindowId_AppListContainer.
TEST_F(AppListPresenterDelegateTest,RemainVisibleWhenFocusingToApplistContainer)1360 TEST_F(AppListPresenterDelegateTest,
1361        RemainVisibleWhenFocusingToApplistContainer) {
1362   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1363   GetAppListTestHelper()->CheckVisibility(true);
1364 
1365   aura::Window* applist_container = Shell::GetContainer(
1366       Shell::GetPrimaryRootWindow(), kShellWindowId_AppListContainer);
1367   std::unique_ptr<aura::Window> window(
1368       aura::test::CreateTestWindowWithId(0, applist_container));
1369   wm::ActivateWindow(window.get());
1370   GetAppListTestHelper()->WaitUntilIdle();
1371 
1372   GetAppListTestHelper()->CheckVisibility(true);
1373 }
1374 
1375 // Tests opening the app list on a secondary display, then deleting the display.
TEST_F(AppListPresenterDelegateTest,NonPrimaryDisplay)1376 TEST_F(AppListPresenterDelegateTest, NonPrimaryDisplay) {
1377   // Set up a screen with two displays (horizontally adjacent).
1378   UpdateDisplay("1024x768,1024x768");
1379 
1380   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1381   ASSERT_EQ(2u, root_windows.size());
1382   ASSERT_EQ("1024,0 1024x768", root_windows[1]->GetBoundsInScreen().ToString());
1383 
1384   GetAppListTestHelper()->ShowAndRunLoop(GetSecondaryDisplay().id());
1385   GetAppListTestHelper()->CheckVisibility(true);
1386 
1387   // Remove the secondary display. Shouldn't crash (http://crbug.com/368990).
1388   UpdateDisplay("1024x768");
1389 
1390   // Updating the displays should close the app list.
1391   GetAppListTestHelper()->WaitUntilIdle();
1392   GetAppListTestHelper()->CheckVisibility(false);
1393 }
1394 
1395 // Tests updating display should not close the app list.
TEST_F(AppListPresenterDelegateTest,UpdateDisplayNotCloseAppList)1396 TEST_F(AppListPresenterDelegateTest, UpdateDisplayNotCloseAppList) {
1397   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1398   GetAppListTestHelper()->CheckVisibility(true);
1399 
1400   // Change display bounds.
1401   UpdateDisplay("1024x768");
1402 
1403   // Updating the display should not close the app list.
1404   GetAppListTestHelper()->WaitUntilIdle();
1405   GetAppListTestHelper()->CheckVisibility(true);
1406 }
1407 
1408 // Tests the app list window's bounds under multi-displays environment.
TEST_F(AppListPresenterDelegateTest,AppListWindowBounds)1409 TEST_F(AppListPresenterDelegateTest, AppListWindowBounds) {
1410   // Set up a screen with two displays (horizontally adjacent).
1411   UpdateDisplay("1024x768,1024x768");
1412   const gfx::Size display_size(1024, 768);
1413 
1414   aura::Window::Windows root_windows = Shell::GetAllRootWindows();
1415   ASSERT_EQ(2u, root_windows.size());
1416 
1417   // Test the app list window's bounds on primary display.
1418   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1419   GetAppListTestHelper()->CheckVisibility(true);
1420   const gfx::Rect primary_display_rect(
1421       gfx::Point(0, display_size.height() -
1422                         AppListConfig::instance().peeking_app_list_height()),
1423       display_size);
1424   EXPECT_EQ(
1425       primary_display_rect,
1426       GetAppListView()->GetWidget()->GetNativeView()->GetBoundsInScreen());
1427 
1428   // Close the app list on primary display.
1429   GetAppListTestHelper()->DismissAndRunLoop();
1430   GetAppListTestHelper()->CheckVisibility(false);
1431 
1432   // Test the app list window's bounds on secondary display.
1433   GetAppListTestHelper()->ShowAndRunLoop(GetSecondaryDisplay().id());
1434   GetAppListTestHelper()->CheckVisibility(true);
1435   const gfx::Rect secondary_display_rect(
1436       gfx::Point(display_size.width(),
1437                  display_size.height() -
1438                      AppListConfig::instance().peeking_app_list_height()),
1439       display_size);
1440   EXPECT_EQ(
1441       secondary_display_rect,
1442       GetAppListView()->GetWidget()->GetNativeView()->GetBoundsInScreen());
1443 }
1444 
1445 // Tests that the app list window's bounds and the search box bounds are updated
1446 // when the display bounds change.
TEST_F(AppListPresenterDelegateTest,AppListBoundsChangeForDisplayChange)1447 TEST_F(AppListPresenterDelegateTest, AppListBoundsChangeForDisplayChange) {
1448   UpdateDisplay("1024x768");
1449   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1450   GetAppListTestHelper()->CheckVisibility(true);
1451 
1452   const gfx::Rect app_list_bounds =
1453       GetAppListView()->GetWidget()->GetWindowBoundsInScreen();
1454   const gfx::Rect search_box_bounds = GetAppListView()
1455                                           ->search_box_view()
1456                                           ->GetWidget()
1457                                           ->GetWindowBoundsInScreen();
1458 
1459   UpdateDisplay("800x600");
1460   GetAppListTestHelper()->WaitUntilIdle();
1461   GetAppListTestHelper()->CheckVisibility(true);
1462   const gfx::Rect app_list_bounds2 =
1463       GetAppListView()->GetWidget()->GetWindowBoundsInScreen();
1464   const gfx::Rect search_box_bounds2 = GetAppListView()
1465                                            ->search_box_view()
1466                                            ->GetWidget()
1467                                            ->GetWindowBoundsInScreen();
1468   EXPECT_GT(app_list_bounds.size().GetArea(),
1469             app_list_bounds2.size().GetArea());
1470   EXPECT_NE(search_box_bounds, search_box_bounds2);
1471   EXPECT_EQ(400, search_box_bounds2.CenterPoint().x());
1472 }
1473 
1474 // Tests that the app list window's bounds and the search box bounds in the half
1475 // state are updated when the display bounds change.
TEST_F(AppListPresenterDelegateTest,AppListBoundsChangeForDisplayChangeSearch)1476 TEST_F(AppListPresenterDelegateTest,
1477        AppListBoundsChangeForDisplayChangeSearch) {
1478   UpdateDisplay("1024x768");
1479   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1480   GetAppListTestHelper()->CheckVisibility(true);
1481   SetAppListStateAndWait(AppListViewState::kHalf);
1482 
1483   const gfx::Rect app_list_bounds =
1484       GetAppListView()->GetWidget()->GetWindowBoundsInScreen();
1485   const gfx::Rect search_box_bounds = GetAppListView()
1486                                           ->search_box_view()
1487                                           ->GetWidget()
1488                                           ->GetWindowBoundsInScreen();
1489 
1490   UpdateDisplay("800x600");
1491   GetAppListTestHelper()->WaitUntilIdle();
1492   GetAppListTestHelper()->CheckVisibility(true);
1493   const gfx::Rect app_list_bounds2 =
1494       GetAppListView()->GetWidget()->GetWindowBoundsInScreen();
1495   const gfx::Rect search_box_bounds2 = GetAppListView()
1496                                            ->search_box_view()
1497                                            ->GetWidget()
1498                                            ->GetWindowBoundsInScreen();
1499   EXPECT_GT(app_list_bounds.size().GetArea(),
1500             app_list_bounds2.size().GetArea());
1501   EXPECT_NE(search_box_bounds, search_box_bounds2);
1502   EXPECT_EQ(400, search_box_bounds2.CenterPoint().x());
1503 }
1504 
1505 // Tests that the app list window's bounds and the search box bounds in the
1506 // fullscreen state are updated when the display bounds change.
TEST_F(AppListPresenterDelegateTest,AppListBoundsChangeForDisplayChangeFullscreen)1507 TEST_F(AppListPresenterDelegateTest,
1508        AppListBoundsChangeForDisplayChangeFullscreen) {
1509   UpdateDisplay("1024x768");
1510   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1511   GetAppListTestHelper()->CheckVisibility(true);
1512   SetAppListStateAndWait(AppListViewState::kFullscreenAllApps);
1513 
1514   const gfx::Rect app_list_bounds =
1515       GetAppListView()->GetWidget()->GetWindowBoundsInScreen();
1516   const gfx::Rect search_box_bounds = GetAppListView()
1517                                           ->search_box_view()
1518                                           ->GetWidget()
1519                                           ->GetWindowBoundsInScreen();
1520 
1521   UpdateDisplay("800x600");
1522   GetAppListTestHelper()->WaitUntilIdle();
1523   GetAppListTestHelper()->CheckVisibility(true);
1524   const gfx::Rect app_list_bounds2 =
1525       GetAppListView()->GetWidget()->GetWindowBoundsInScreen();
1526   const gfx::Rect search_box_bounds2 = GetAppListView()
1527                                            ->search_box_view()
1528                                            ->GetWidget()
1529                                            ->GetWindowBoundsInScreen();
1530   EXPECT_GT(app_list_bounds.size().GetArea(),
1531             app_list_bounds2.size().GetArea());
1532   EXPECT_NE(search_box_bounds, search_box_bounds2);
1533   EXPECT_EQ(400, search_box_bounds2.CenterPoint().x());
1534 }
1535 
1536 // Tests that the app list window's bounds and the search box bounds in the
1537 // fullscreen search state are updated when the display bounds change.
TEST_F(AppListPresenterDelegateTest,AppListBoundsChangeForDisplayChangeFullscreenSearch)1538 TEST_F(AppListPresenterDelegateTest,
1539        AppListBoundsChangeForDisplayChangeFullscreenSearch) {
1540   UpdateDisplay("1024x768");
1541   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1542   GetAppListTestHelper()->CheckVisibility(true);
1543   SetAppListStateAndWait(AppListViewState::kFullscreenAllApps);
1544   SetAppListStateAndWait(AppListViewState::kFullscreenSearch);
1545 
1546   const gfx::Rect app_list_bounds =
1547       GetAppListView()->GetWidget()->GetWindowBoundsInScreen();
1548   const gfx::Rect search_box_bounds = GetAppListView()
1549                                           ->search_box_view()
1550                                           ->GetWidget()
1551                                           ->GetWindowBoundsInScreen();
1552 
1553   UpdateDisplay("800x600");
1554   GetAppListTestHelper()->WaitUntilIdle();
1555   GetAppListTestHelper()->CheckVisibility(true);
1556   const gfx::Rect app_list_bounds2 =
1557       GetAppListView()->GetWidget()->GetWindowBoundsInScreen();
1558   const gfx::Rect search_box_bounds2 = GetAppListView()
1559                                            ->search_box_view()
1560                                            ->GetWidget()
1561                                            ->GetWindowBoundsInScreen();
1562   EXPECT_GT(app_list_bounds.size().GetArea(),
1563             app_list_bounds2.size().GetArea());
1564   EXPECT_NE(search_box_bounds, search_box_bounds2);
1565   EXPECT_EQ(400, search_box_bounds2.CenterPoint().x());
1566 }
1567 
1568 // Tests that the app list is not draggable in side shelf alignment.
TEST_F(AppListPresenterDelegateTest,SideShelfAlignmentDragDisabled)1569 TEST_F(AppListPresenterDelegateTest, SideShelfAlignmentDragDisabled) {
1570   SetShelfAlignment(ShelfAlignment::kRight);
1571   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1572   const AppListView* app_list = GetAppListView();
1573   EXPECT_TRUE(app_list->is_fullscreen());
1574   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1575 
1576   // Drag the widget across the screen over an arbitrary 100Ms, this would
1577   // normally result in the app list transitioning to PEEKING but will now
1578   // result in no state change.
1579   ui::test::EventGenerator* generator = GetEventGenerator();
1580   generator->GestureScrollSequence(GetPointOutsideSearchbox(),
1581                                    gfx::Point(10, 900),
1582                                    base::TimeDelta::FromMilliseconds(100), 10);
1583   GetAppListTestHelper()->WaitUntilIdle();
1584   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1585 
1586   // Tap the app list body. This should still close the app list.
1587   generator->GestureTapAt(GetPointOutsideSearchbox());
1588   GetAppListTestHelper()->WaitUntilIdle();
1589   GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
1590   GetAppListTestHelper()->CheckVisibility(false);
1591 }
1592 
1593 // Tests that the app list initializes in fullscreen with side shelf alignment
1594 // and that the state transitions via text input act properly.
TEST_F(AppListPresenterDelegateTest,SideShelfAlignmentTextStateTransitions)1595 TEST_F(AppListPresenterDelegateTest, SideShelfAlignmentTextStateTransitions) {
1596   SetShelfAlignment(ShelfAlignment::kLeft);
1597 
1598   // Open the app list with side shelf alignment, then check that it is in
1599   // fullscreen mode.
1600   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1601   AppListView* app_list = GetAppListView();
1602   EXPECT_TRUE(app_list->is_fullscreen());
1603   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1604 
1605   // Enter text in the searchbox, the app list should transition to fullscreen
1606   // search.
1607   ui::test::EventGenerator* generator = GetEventGenerator();
1608   generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
1609   GetAppListTestHelper()->WaitUntilIdle();
1610   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
1611 
1612   // Pressing escape should transition the app list should to fullscreen all
1613   // apps state.
1614   generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
1615   GetAppListTestHelper()->WaitUntilIdle();
1616   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1617 }
1618 
1619 // Tests that the app list initializes in peeking with bottom shelf alignment
1620 // and that the state transitions via text input act properly.
TEST_F(AppListPresenterDelegateTest,BottomShelfAlignmentTextStateTransitions)1621 TEST_F(AppListPresenterDelegateTest, BottomShelfAlignmentTextStateTransitions) {
1622   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1623   AppListView* app_list = GetAppListView();
1624   EXPECT_FALSE(app_list->is_fullscreen());
1625   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
1626 
1627   // Enter text in the searchbox, this should transition the app list to half
1628   // state.
1629   ui::test::EventGenerator* generator = GetEventGenerator();
1630   generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
1631   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
1632 
1633   // Empty the searchbox - app list should remain in half state (and show zero
1634   // state results).
1635   generator->PressKey(ui::KeyboardCode::VKEY_BACK, 0);
1636   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
1637 
1638   // ESC should transition app list to the peeking state.
1639   generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
1640   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
1641 }
1642 
1643 // Tests that the app list initializes in fullscreen with tablet mode active
1644 // and that the state transitions via text input act properly.
TEST_F(AppListPresenterDelegateTest,TabletModeTextStateTransitions)1645 TEST_F(AppListPresenterDelegateTest, TabletModeTextStateTransitions) {
1646   EnableTabletMode(true);
1647   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1648   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1649 
1650   // Enter text in the searchbox, the app list should transition to fullscreen
1651   // search.
1652   ui::test::EventGenerator* generator = GetEventGenerator();
1653   generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
1654   GetAppListTestHelper()->WaitUntilIdle();
1655   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
1656 
1657   // Pressing the escape key should transition the app list to the fullscreen
1658   // all apps state.
1659   generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
1660   GetAppListTestHelper()->WaitUntilIdle();
1661   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1662 }
1663 
1664 // Tests that the app list closes when tablet mode deactivates.
TEST_F(AppListPresenterDelegateTest,AppListClosesWhenLeavingTabletMode)1665 TEST_F(AppListPresenterDelegateTest, AppListClosesWhenLeavingTabletMode) {
1666   EnableTabletMode(true);
1667   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1668   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1669 
1670   EnableTabletMode(false);
1671   GetAppListTestHelper()->WaitUntilIdle();
1672   GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
1673 
1674   EnableTabletMode(true);
1675   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1676   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1677 
1678   // Enter text in the searchbox, the app list should transition to fullscreen
1679   // search.
1680   ui::test::EventGenerator* generator = GetEventGenerator();
1681   generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
1682   GetAppListTestHelper()->WaitUntilIdle();
1683   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
1684 
1685   EnableTabletMode(false);
1686   GetAppListTestHelper()->WaitUntilIdle();
1687   GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
1688 }
1689 
1690 // Tests that the app list state responds correctly to tablet mode being
1691 // enabled while the app list is being shown with half launcher.
TEST_F(AppListPresenterDelegateTest,HalfToFullscreenWhenTabletModeIsActive)1692 TEST_F(AppListPresenterDelegateTest, HalfToFullscreenWhenTabletModeIsActive) {
1693   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1694   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
1695 
1696   // Enter text in the search box to transition to half app list.
1697   ui::test::EventGenerator* generator = GetEventGenerator();
1698   generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
1699   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
1700 
1701   // Enable tablet mode and force the app list to transition to the fullscreen
1702   // equivalent of the current state.
1703   EnableTabletMode(true);
1704   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
1705   generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
1706   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1707 }
1708 
1709 // Tests that the app list view handles drag properly in laptop mode.
TEST_F(AppListPresenterDelegateTest,AppListViewDragHandler)1710 TEST_F(AppListPresenterDelegateTest, AppListViewDragHandler) {
1711   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1712   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
1713 
1714   ui::test::EventGenerator* generator = GetEventGenerator();
1715   // Execute a slow short upwards drag this should fail to transition the app
1716   // list.
1717   int top_of_app_list =
1718       GetAppListView()->GetWidget()->GetWindowBoundsInScreen().y();
1719   generator->GestureScrollSequence(gfx::Point(0, top_of_app_list + 20),
1720                                    gfx::Point(0, top_of_app_list - 20),
1721                                    base::TimeDelta::FromMilliseconds(500), 50);
1722   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
1723 
1724   // Execute a long upwards drag, this should transition the app list.
1725   generator->GestureScrollSequence(gfx::Point(10, top_of_app_list + 20),
1726                                    gfx::Point(10, 10),
1727                                    base::TimeDelta::FromMilliseconds(100), 10);
1728   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1729 
1730   // Execute a short downward drag, this should fail to transition the app list.
1731   gfx::Point start(10, 10);
1732   gfx::Point end(10, 100);
1733   generator->GestureScrollSequence(
1734       start, end,
1735       generator->CalculateScrollDurationForFlingVelocity(start, end, 1, 100),
1736       100);
1737   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1738 
1739   // Execute a long and slow downward drag to switch to peeking.
1740   start = gfx::Point(10, 200);
1741   end = gfx::Point(10, 650);
1742   generator->GestureScrollSequence(
1743       start, end,
1744       generator->CalculateScrollDurationForFlingVelocity(start, end, 1, 100),
1745       100);
1746   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
1747 
1748   // Transition to fullscreen.
1749   generator->GestureScrollSequence(gfx::Point(10, top_of_app_list + 20),
1750                                    gfx::Point(10, 10),
1751                                    base::TimeDelta::FromMilliseconds(100), 10);
1752   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
1753 
1754   // Enter text to transition to |FULLSCREEN_SEARCH|.
1755   generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
1756   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
1757 
1758   // Execute a short downward drag, this should fail to close the app list.
1759   start = gfx::Point(10, 10);
1760   end = gfx::Point(10, 100);
1761   generator->GestureScrollSequence(
1762       start, end,
1763       generator->CalculateScrollDurationForFlingVelocity(start, end, 1, 100),
1764       100);
1765   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
1766 
1767   // Execute a long downward drag, this should close the app list.
1768   generator->GestureScrollSequence(gfx::Point(10, 10), gfx::Point(10, 900),
1769                                    base::TimeDelta::FromMilliseconds(100), 10);
1770   GetAppListTestHelper()->WaitUntilIdle();
1771   GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
1772   GetAppListTestHelper()->CheckVisibility(false);
1773 }
1774 
1775 // Tests that the bottom shelf background is hidden when the app list is shown
1776 // in laptop mode.
TEST_F(AppListPresenterDelegateTest,ShelfBackgroundIsHiddenWhenAppListIsShown)1777 TEST_F(AppListPresenterDelegateTest,
1778        ShelfBackgroundIsHiddenWhenAppListIsShown) {
1779   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1780   ShelfLayoutManager* shelf_layout_manager =
1781       Shelf::ForWindow(Shell::GetRootWindowForDisplayId(GetPrimaryDisplayId()))
1782           ->shelf_layout_manager();
1783   EXPECT_EQ(ShelfBackgroundType::kAppList,
1784             shelf_layout_manager->GetShelfBackgroundType());
1785 }
1786 
1787 // Tests the shelf background type is as expected when a window is created after
1788 // going to tablet mode.
TEST_F(AppListPresenterDelegateTest,ShelfBackgroundWithHomeLauncher)1789 TEST_F(AppListPresenterDelegateTest, ShelfBackgroundWithHomeLauncher) {
1790   // Enter tablet mode to display the home launcher.
1791   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1792   EnableTabletMode(true);
1793   ShelfLayoutManager* shelf_layout_manager =
1794       Shelf::ForWindow(Shell::GetRootWindowForDisplayId(GetPrimaryDisplayId()))
1795           ->shelf_layout_manager();
1796   EXPECT_EQ(ShelfBackgroundType::kHomeLauncher,
1797             shelf_layout_manager->GetShelfBackgroundType());
1798 
1799   // Add a window. It should be in-app because it is in tablet mode.
1800   auto window = CreateTestWindow();
1801   wm::ActivateWindow(window.get());
1802   EXPECT_EQ(ShelfBackgroundType::kInApp,
1803             shelf_layout_manager->GetShelfBackgroundType());
1804 }
1805 
1806 // Tests that app list understands shelf rounded corners state while animating
1807 // out and in, and that it keeps getting notified of shelf state changes if
1808 // close animation is interrupted by another show request.
TEST_F(AppListPresenterDelegateTest,AppListShownWhileClosing)1809 TEST_F(AppListPresenterDelegateTest, AppListShownWhileClosing) {
1810   auto window = CreateTestWindow();
1811   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
1812 
1813   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1814   GetAppListTestHelper()->CheckVisibility(true);
1815 
1816   ShelfLayoutManager* shelf_layout_manager =
1817       Shelf::ForWindow(Shell::GetRootWindowForDisplayId(GetPrimaryDisplayId()))
1818           ->shelf_layout_manager();
1819 
1820   EXPECT_FALSE(GetAppListView()->shelf_has_rounded_corners());
1821   EXPECT_EQ(ShelfBackgroundType::kMaximizedWithAppList,
1822             shelf_layout_manager->GetShelfBackgroundType());
1823 
1824   // Enable animation to account for delay between app list starting to close
1825   // and reporting visibility change (which happens when close animation
1826   // finishes).
1827   ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
1828       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
1829   AppListView::SetShortAnimationForTesting(false);
1830 
1831   // Dismiss and immediately show the app list (before close animation is done).
1832   GetAppListTestHelper()->Dismiss();
1833 
1834   EXPECT_FALSE(GetAppListView()->shelf_has_rounded_corners());
1835   EXPECT_EQ(ShelfBackgroundType::kMaximizedWithAppList,
1836             shelf_layout_manager->GetShelfBackgroundType());
1837 
1838   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1839 
1840   // Finish app list animations.
1841   if (GetAppListView()->GetWidget()->GetLayer()->GetAnimator()->is_animating())
1842     GetAppListView()->GetWidget()->GetLayer()->GetAnimator()->StopAnimating();
1843 
1844   EXPECT_FALSE(GetAppListView()->shelf_has_rounded_corners());
1845   EXPECT_EQ(ShelfBackgroundType::kMaximizedWithAppList,
1846             shelf_layout_manager->GetShelfBackgroundType());
1847 
1848   // Verify that the app list still picks up shelf changes.
1849   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
1850   EXPECT_TRUE(GetAppListView()->shelf_has_rounded_corners());
1851   EXPECT_EQ(ShelfBackgroundType::kAppList,
1852             shelf_layout_manager->GetShelfBackgroundType());
1853 }
1854 
1855 // Tests how shelf state is updated as app list state changes with a maximized
1856 // window open. It verifies that the app list knows that the maximized shelf had
1857 // no rounded corners.
TEST_F(AppListPresenterDelegateTest,AppListWithMaximizedShelf)1858 TEST_F(AppListPresenterDelegateTest, AppListWithMaximizedShelf) {
1859   auto window = CreateTestWindow();
1860   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
1861 
1862   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1863   GetAppListTestHelper()->CheckVisibility(true);
1864 
1865   ShelfLayoutManager* shelf_layout_manager =
1866       Shelf::ForWindow(Shell::GetRootWindowForDisplayId(GetPrimaryDisplayId()))
1867           ->shelf_layout_manager();
1868 
1869   EXPECT_FALSE(GetAppListView()->shelf_has_rounded_corners());
1870   EXPECT_EQ(ShelfBackgroundType::kMaximizedWithAppList,
1871             shelf_layout_manager->GetShelfBackgroundType());
1872 
1873   // Enable animation to account for delay between app list starting to close
1874   // and reporting visibility change (which happens when close animation
1875   // finishes).
1876   ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
1877       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
1878   AppListView::SetShortAnimationForTesting(false);
1879 
1880   // Start closing the app list view.
1881   GetAppListTestHelper()->Dismiss();
1882 
1883   EXPECT_FALSE(GetAppListView()->shelf_has_rounded_corners());
1884   EXPECT_EQ(ShelfBackgroundType::kMaximizedWithAppList,
1885             shelf_layout_manager->GetShelfBackgroundType());
1886 
1887   // Minimize the window, and verify that the shelf state changed from a
1888   // maximized state, and that |shelf_has_rounded_corners()| value was updated.
1889   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
1890 
1891   EXPECT_TRUE(GetAppListView()->shelf_has_rounded_corners());
1892   EXPECT_EQ(ShelfBackgroundType::kAppList,
1893             shelf_layout_manager->GetShelfBackgroundType());
1894 
1895   // Stop app list hide animation.
1896   ASSERT_TRUE(
1897       GetAppListView()->GetWidget()->GetLayer()->GetAnimator()->is_animating());
1898   GetAppListView()->GetWidget()->GetLayer()->GetAnimator()->StopAnimating();
1899 
1900   EXPECT_EQ(ShelfBackgroundType::kDefaultBg,
1901             shelf_layout_manager->GetShelfBackgroundType());
1902 }
1903 
1904 // Verifies the shelf background state changes when a window is maximized while
1905 // app list is shown. Verifies that AppList::shelf_has_rounded_corners() is
1906 // updated.
TEST_F(AppListPresenterDelegateTest,WindowMaximizedWithAppListShown)1907 TEST_F(AppListPresenterDelegateTest, WindowMaximizedWithAppListShown) {
1908   auto window = CreateTestWindow();
1909 
1910   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1911   GetAppListTestHelper()->CheckVisibility(true);
1912 
1913   ShelfLayoutManager* shelf_layout_manager =
1914       Shelf::ForWindow(Shell::GetRootWindowForDisplayId(GetPrimaryDisplayId()))
1915           ->shelf_layout_manager();
1916 
1917   EXPECT_TRUE(GetAppListView()->shelf_has_rounded_corners());
1918   EXPECT_EQ(ShelfBackgroundType::kAppList,
1919             shelf_layout_manager->GetShelfBackgroundType());
1920 
1921   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
1922 
1923   EXPECT_FALSE(GetAppListView()->shelf_has_rounded_corners());
1924   EXPECT_EQ(ShelfBackgroundType::kMaximizedWithAppList,
1925             shelf_layout_manager->GetShelfBackgroundType());
1926 
1927   GetAppListTestHelper()->Dismiss();
1928 
1929   EXPECT_EQ(ShelfBackgroundType::kMaximized,
1930             shelf_layout_manager->GetShelfBackgroundType());
1931 }
1932 
1933 // Tests that the bottom shelf is auto hidden when a window is fullscreened in
1934 // tablet mode (home launcher is shown behind).
TEST_F(AppListPresenterDelegateTest,ShelfAutoHiddenWhenFullscreen)1935 TEST_F(AppListPresenterDelegateTest, ShelfAutoHiddenWhenFullscreen) {
1936   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1937   EnableTabletMode(true);
1938   Shelf* shelf =
1939       Shelf::ForWindow(Shell::GetRootWindowForDisplayId(GetPrimaryDisplayId()));
1940   EXPECT_EQ(ShelfVisibilityState::SHELF_VISIBLE, shelf->GetVisibilityState());
1941 
1942   // Create and fullscreen a window. The shelf should be auto hidden.
1943   auto window = CreateTestWindow();
1944   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_FULLSCREEN);
1945   EXPECT_EQ(ShelfVisibilityState::SHELF_AUTO_HIDE, shelf->GetVisibilityState());
1946   EXPECT_EQ(ShelfAutoHideState::SHELF_AUTO_HIDE_HIDDEN,
1947             shelf->GetAutoHideState());
1948 }
1949 
1950 // Tests that the peeking app list closes if the user taps or clicks outside
1951 // its bounds.
TEST_P(AppListPresenterDelegateTest,TapAndClickOutsideClosesPeekingAppList)1952 TEST_P(AppListPresenterDelegateTest, TapAndClickOutsideClosesPeekingAppList) {
1953   const bool test_mouse_event = TestMouseEventParam();
1954   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1955   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
1956   ui::test::EventGenerator* generator = GetEventGenerator();
1957 
1958   // Tapping outside the bounds closes the app list.
1959   const gfx::Rect peeking_bounds = GetAppListView()->GetBoundsInScreen();
1960   gfx::Point tap_point = peeking_bounds.origin();
1961   tap_point.Offset(10, -10);
1962   ASSERT_FALSE(peeking_bounds.Contains(tap_point));
1963 
1964   if (test_mouse_event) {
1965     generator->MoveMouseTo(tap_point);
1966     generator->ClickLeftButton();
1967     generator->ReleaseLeftButton();
1968   } else {
1969     generator->GestureTapAt(tap_point);
1970   }
1971   GetAppListTestHelper()->WaitUntilIdle();
1972   GetAppListTestHelper()->CheckVisibility(false);
1973 }
1974 
TEST_P(AppListPresenterDelegateTest,LongPressOutsideCloseAppList)1975 TEST_P(AppListPresenterDelegateTest, LongPressOutsideCloseAppList) {
1976   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1977   GetAppListTestHelper()->CheckVisibility(true);
1978 
1979   // |outside_point| is outside the bounds of app list.
1980   gfx::Point outside_point = GetAppListView()->bounds().origin();
1981   outside_point.Offset(0, -10);
1982 
1983   // Dispatch LONG_PRESS to AppListPresenterDelegate.
1984   ui::TouchEvent long_press(ui::ET_GESTURE_LONG_PRESS, outside_point,
1985                             base::TimeTicks::Now(),
1986                             ui::PointerDetails(ui::EventPointerType::kTouch));
1987   GetEventGenerator()->Dispatch(&long_press);
1988   GetAppListTestHelper()->WaitUntilIdle();
1989   GetAppListTestHelper()->CheckVisibility(false);
1990 }
1991 
TEST_P(AppListPresenterDelegateTest,TwoFingerTapOutsideCloseAppList)1992 TEST_P(AppListPresenterDelegateTest, TwoFingerTapOutsideCloseAppList) {
1993   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
1994   GetAppListTestHelper()->CheckVisibility(true);
1995 
1996   // |outside_point| is outside the bounds of app list.
1997   gfx::Point outside_point = GetAppListView()->bounds().origin();
1998   outside_point.Offset(0, -10);
1999 
2000   // Dispatch TWO_FINGER_TAP to AppListPresenterDelegate.
2001   ui::TouchEvent two_finger_tap(
2002       ui::ET_GESTURE_TWO_FINGER_TAP, outside_point, base::TimeTicks::Now(),
2003       ui::PointerDetails(ui::EventPointerType::kTouch));
2004   GetEventGenerator()->Dispatch(&two_finger_tap);
2005   GetAppListTestHelper()->WaitUntilIdle();
2006   GetAppListTestHelper()->CheckVisibility(false);
2007 }
2008 
2009 // Tests that a keypress activates the searchbox and that clearing the
2010 // searchbox, the searchbox remains active.
TEST_F(AppListPresenterDelegateTest,KeyPressEnablesSearchBox)2011 TEST_F(AppListPresenterDelegateTest, KeyPressEnablesSearchBox) {
2012   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2013   ui::test::EventGenerator* generator = GetEventGenerator();
2014   SearchBoxView* search_box_view = GetAppListView()->search_box_view();
2015   EXPECT_FALSE(search_box_view->is_search_box_active());
2016 
2017   // Press any key, the search box should be active.
2018   generator->PressKey(ui::VKEY_0, 0);
2019   EXPECT_TRUE(search_box_view->is_search_box_active());
2020 
2021   // Delete the text, the search box should be inactive.
2022   search_box_view->ClearSearch();
2023   EXPECT_TRUE(search_box_view->is_search_box_active());
2024 }
2025 
2026 // Tests that a tap/click on the AppListView from half launcher returns the
2027 // AppListView to Peeking, and that a tap/click on the AppListView from
2028 // Peeking closes the app list.
TEST_P(AppListPresenterDelegateTest,StateTransitionsByTapAndClickingAppListBodyFromHalf)2029 TEST_P(AppListPresenterDelegateTest,
2030        StateTransitionsByTapAndClickingAppListBodyFromHalf) {
2031   const bool test_mouse_event = TestMouseEventParam();
2032   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2033   AppListView* app_list_view = GetAppListView();
2034   SearchBoxView* search_box_view = app_list_view->search_box_view();
2035   ui::test::EventGenerator* generator = GetEventGenerator();
2036   GetAppListTestHelper()->WaitUntilIdle();
2037   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2038 
2039   // Press a key, the AppListView should transition to half.
2040   generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
2041   GetAppListTestHelper()->WaitUntilIdle();
2042   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2043   EXPECT_TRUE(search_box_view->is_search_box_active());
2044 
2045   // Tap outside the search box, the AppListView should transition to Peeking
2046   // and the search box should be inactive.
2047   if (test_mouse_event) {
2048     generator->MoveMouseTo(GetPointOutsideSearchbox());
2049     generator->ClickLeftButton();
2050     generator->ReleaseLeftButton();
2051   } else {
2052     generator->GestureTapDownAndUp(GetPointOutsideSearchbox());
2053   }
2054   GetAppListTestHelper()->WaitUntilIdle();
2055   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2056   EXPECT_FALSE(search_box_view->is_search_box_active());
2057 
2058   // Tap outside the search box again, the AppListView should hide.
2059   if (test_mouse_event) {
2060     generator->MoveMouseTo(GetPointOutsideSearchbox());
2061     generator->ClickLeftButton();
2062     generator->ReleaseLeftButton();
2063   } else {
2064     generator->GestureTapDownAndUp(GetPointOutsideSearchbox());
2065   }
2066   GetAppListTestHelper()->WaitUntilIdle();
2067   GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2068   GetAppListTestHelper()->CheckVisibility(false);
2069 }
2070 
2071 // Tests that a tap/click on the AppListView from Fullscreen search returns
2072 // the AppListView to fullscreen all apps, and that a tap/click on the
2073 // AppListView from fullscreen all apps closes the app list.
TEST_P(AppListPresenterDelegateTest,StateTransitionsByTappingAppListBodyFromFullscreen)2074 TEST_P(AppListPresenterDelegateTest,
2075        StateTransitionsByTappingAppListBodyFromFullscreen) {
2076   const bool test_mouse_event = TestMouseEventParam();
2077   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2078   AppListView* app_list_view = GetAppListView();
2079   SearchBoxView* search_box_view = app_list_view->search_box_view();
2080   ui::test::EventGenerator* generator = GetEventGenerator();
2081 
2082   // Execute a long upwards drag, this should transition the app list to
2083   // fullscreen.
2084   const int top_of_app_list =
2085       app_list_view->GetWidget()->GetWindowBoundsInScreen().y();
2086   generator->GestureScrollSequence(gfx::Point(10, top_of_app_list + 20),
2087                                    gfx::Point(10, 10),
2088                                    base::TimeDelta::FromMilliseconds(100), 10);
2089   GetAppListTestHelper()->WaitUntilIdle();
2090   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
2091 
2092   // Press a key, this should activate the searchbox and transition to
2093   // fullscreen search.
2094   generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
2095   GetAppListTestHelper()->WaitUntilIdle();
2096   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
2097   EXPECT_TRUE(search_box_view->is_search_box_active());
2098 
2099   // Tap outside the searchbox, this should deactivate the searchbox and the
2100   // applistview should return to fullscreen all apps.
2101   if (test_mouse_event) {
2102     generator->MoveMouseTo(GetPointOutsideSearchbox());
2103     generator->ClickLeftButton();
2104   } else {
2105     generator->GestureTapDownAndUp(GetPointOutsideSearchbox());
2106   }
2107   GetAppListTestHelper()->WaitUntilIdle();
2108   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
2109   EXPECT_FALSE(search_box_view->is_search_box_active());
2110 
2111   // Tap outside the searchbox again, this should close the applistview.
2112   if (test_mouse_event) {
2113     generator->MoveMouseTo(GetPointOutsideSearchbox());
2114     generator->ClickLeftButton();
2115   } else {
2116     generator->GestureTapDownAndUp(GetPointOutsideSearchbox());
2117   }
2118   GetAppListTestHelper()->WaitUntilIdle();
2119   GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2120   GetAppListTestHelper()->CheckVisibility(false);
2121 }
2122 
2123 // Tests that the searchbox activates when it is tapped and that the widget is
2124 // closed after tapping outside the searchbox.
TEST_P(AppListPresenterDelegateTest,TapAndClickEnablesSearchBox)2125 TEST_P(AppListPresenterDelegateTest, TapAndClickEnablesSearchBox) {
2126   const bool test_mouse_event = TestMouseEventParam();
2127   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2128   SearchBoxView* search_box_view = GetAppListView()->search_box_view();
2129 
2130   // Tap/Click the search box, it should activate.
2131   ui::test::EventGenerator* generator = GetEventGenerator();
2132   if (test_mouse_event) {
2133     generator->MoveMouseTo(GetPointInsideSearchbox());
2134     generator->PressLeftButton();
2135     generator->ReleaseLeftButton();
2136   } else {
2137     generator->GestureTapAt(GetPointInsideSearchbox());
2138   }
2139 
2140   EXPECT_TRUE(search_box_view->is_search_box_active());
2141 
2142   // Tap on the body of the app list, the search box should deactivate.
2143   if (test_mouse_event) {
2144     generator->MoveMouseTo(GetPointOutsideSearchbox());
2145     generator->PressLeftButton();
2146     generator->ReleaseLeftButton();
2147   } else {
2148     generator->GestureTapAt(GetPointOutsideSearchbox());
2149   }
2150   GetAppListTestHelper()->WaitUntilIdle();
2151   EXPECT_FALSE(search_box_view->is_search_box_active());
2152   GetAppListTestHelper()->CheckVisibility(true);
2153 
2154   // Tap on the body of the app list again, the app list should hide.
2155   if (test_mouse_event) {
2156     generator->PressLeftButton();
2157     generator->ReleaseLeftButton();
2158   } else {
2159     generator->GestureTapAt(GetPointOutsideSearchbox());
2160   }
2161   GetAppListTestHelper()->WaitUntilIdle();
2162   GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2163   GetAppListTestHelper()->CheckVisibility(false);
2164 }
2165 
2166 // Tests that the shelf background displays/hides with bottom shelf
2167 // alignment.
TEST_F(AppListPresenterDelegateTest,ShelfBackgroundRespondsToAppListBeingShown)2168 TEST_F(AppListPresenterDelegateTest,
2169        ShelfBackgroundRespondsToAppListBeingShown) {
2170   GetPrimaryShelf()->SetAlignment(ShelfAlignment::kBottom);
2171 
2172   // Show the app list, the shelf background should be transparent.
2173   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2174   ShelfLayoutManager* shelf_layout_manager =
2175       GetPrimaryShelf()->shelf_layout_manager();
2176   EXPECT_EQ(ShelfBackgroundType::kAppList,
2177             shelf_layout_manager->GetShelfBackgroundType());
2178   GetAppListTestHelper()->DismissAndRunLoop();
2179 
2180   // Set the alignment to the side and show the app list. The background
2181   // should show.
2182   GetPrimaryShelf()->SetAlignment(ShelfAlignment::kLeft);
2183   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2184   EXPECT_FALSE(GetPrimaryShelf()->IsHorizontalAlignment());
2185   EXPECT_EQ(
2186       ShelfBackgroundType::kAppList,
2187       GetPrimaryShelf()->shelf_layout_manager()->GetShelfBackgroundType());
2188 }
2189 
2190 // Tests that the half app list closes itself if the user taps outside its
2191 // bounds.
TEST_P(AppListPresenterDelegateTest,TapAndClickOutsideClosesHalfAppList)2192 TEST_P(AppListPresenterDelegateTest, TapAndClickOutsideClosesHalfAppList) {
2193   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2194   ui::test::EventGenerator* generator = GetEventGenerator();
2195 
2196   // Transition to half app list by entering text.
2197   generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
2198   GetAppListTestHelper()->WaitUntilIdle();
2199   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2200 
2201   // A point outside the bounds of launcher.
2202   gfx::Point to_point(
2203       0, GetAppListView()->GetWidget()->GetWindowBoundsInScreen().y() - 1);
2204 
2205   // Clicking/tapping outside the bounds closes the app list.
2206   if (TestMouseEventParam()) {
2207     generator->MoveMouseTo(to_point);
2208     generator->ClickLeftButton();
2209   } else {
2210     generator->GestureTapAt(to_point);
2211   }
2212   GetAppListTestHelper()->WaitUntilIdle();
2213   GetAppListTestHelper()->CheckVisibility(false);
2214 }
2215 
2216 // Tests that the search box is set active with a whitespace query.
TEST_F(AppListPresenterDelegateTest,WhitespaceQuery)2217 TEST_F(AppListPresenterDelegateTest, WhitespaceQuery) {
2218   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2219   AppListView* view = GetAppListView();
2220   ui::test::EventGenerator* generator = GetEventGenerator();
2221   EXPECT_FALSE(view->search_box_view()->is_search_box_active());
2222   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2223 
2224   // Enter a whitespace query, the searchbox should activate (in zero state).
2225   generator->PressKey(ui::VKEY_SPACE, 0);
2226   EXPECT_TRUE(view->search_box_view()->is_search_box_active());
2227   EXPECT_TRUE(view->search_box_view()->IsSearchBoxTrimmedQueryEmpty());
2228   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2229 
2230   generator->PressKey(ui::VKEY_A, 0);
2231   EXPECT_TRUE(view->search_box_view()->is_search_box_active());
2232   EXPECT_FALSE(view->search_box_view()->IsSearchBoxTrimmedQueryEmpty());
2233   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2234 
2235   // Delete the non-whitespace character, the Searchbox should not deactivate.
2236   generator->PressKey(ui::VKEY_BACK, 0);
2237   EXPECT_TRUE(view->search_box_view()->is_search_box_active());
2238   EXPECT_TRUE(view->search_box_view()->IsSearchBoxTrimmedQueryEmpty());
2239   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2240 
2241   // Delete the whitespace, the search box remains active, in zero state.
2242   generator->PressKey(ui::VKEY_BACK, 0);
2243   EXPECT_TRUE(view->search_box_view()->is_search_box_active());
2244   EXPECT_TRUE(view->search_box_view()->IsSearchBoxTrimmedQueryEmpty());
2245   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2246 }
2247 
2248 // Tests that an unhandled two finger tap/right click does not close the app
2249 // list, and an unhandled one finger tap/left click closes the app list in
2250 // Peeking mode.
TEST_P(AppListPresenterDelegateTest,UnhandledEventOnPeeking)2251 TEST_P(AppListPresenterDelegateTest, UnhandledEventOnPeeking) {
2252   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2253   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2254 
2255   // Two finger tap or right click in the empty space below the searchbox. The
2256   // app list should not close.
2257   gfx::Point empty_space =
2258       GetAppListView()->search_box_view()->GetBoundsInScreen().bottom_left();
2259   empty_space.Offset(0, 10);
2260   ui::test::EventGenerator* generator = GetEventGenerator();
2261   if (TestMouseEventParam()) {
2262     generator->MoveMouseTo(empty_space);
2263     generator->PressRightButton();
2264     generator->ReleaseRightButton();
2265   } else {
2266     ui::GestureEvent two_finger_tap(
2267         empty_space.x(), empty_space.y(), 0, base::TimeTicks(),
2268         ui::GestureEventDetails(ui::ET_GESTURE_TWO_FINGER_TAP));
2269     generator->Dispatch(&two_finger_tap);
2270   }
2271   GetAppListTestHelper()->WaitUntilIdle();
2272   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2273   GetAppListTestHelper()->CheckVisibility(true);
2274 
2275   // One finger tap or left click in the empty space below the searchbox. The
2276   // app list should close.
2277   if (TestMouseEventParam()) {
2278     generator->MoveMouseTo(empty_space);
2279     generator->ClickLeftButton();
2280   } else {
2281     generator->GestureTapAt(empty_space);
2282   }
2283   GetAppListTestHelper()->WaitUntilIdle();
2284   GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2285   GetAppListTestHelper()->CheckVisibility(false);
2286 }
2287 
2288 // Tests that a drag to the bezel from Fullscreen/Peeking will close the app
2289 // list.
TEST_P(AppListPresenterDelegateTest,DragToBezelClosesAppListFromFullscreenAndPeeking)2290 TEST_P(AppListPresenterDelegateTest,
2291        DragToBezelClosesAppListFromFullscreenAndPeeking) {
2292   const bool test_fullscreen = GetParam();
2293   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2294   AppListView* view = GetAppListView();
2295   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2296 
2297   if (test_fullscreen) {
2298     FlingUpOrDown(GetEventGenerator(), view, true /* up */);
2299     GetAppListTestHelper()->WaitUntilIdle();
2300     GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
2301   }
2302 
2303   // Drag the app list to 50 DIPs from the bottom bezel.
2304   ui::test::EventGenerator* generator = GetEventGenerator();
2305   const int bezel_y = display::Screen::GetScreen()
2306                           ->GetDisplayNearestView(view->parent_window())
2307                           .bounds()
2308                           .bottom();
2309   generator->GestureScrollSequence(
2310       gfx::Point(0, bezel_y - (kAppListBezelMargin + 100)),
2311       gfx::Point(0, bezel_y - (kAppListBezelMargin)),
2312       base::TimeDelta::FromMilliseconds(1500), 100);
2313 
2314   GetAppListTestHelper()->WaitUntilIdle();
2315   GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2316   GetAppListTestHelper()->CheckVisibility(false);
2317 }
2318 
2319 // Tests that a drag to the bezel from Fullscreen/Peeking will close the app
2320 // list even on external display with non zero y origin.
TEST_P(AppListPresenterDelegateTest,DragToBezelClosesAppListFromFullscreenAndPeekingOnExternal)2321 TEST_P(AppListPresenterDelegateTest,
2322        DragToBezelClosesAppListFromFullscreenAndPeekingOnExternal) {
2323   UpdateDisplay("800x600,1000x768");
2324 
2325   const bool test_fullscreen = GetParam();
2326   GetAppListTestHelper()->ShowAndRunLoop(GetSecondaryDisplay().id());
2327   AppListView* view = GetAppListView();
2328   {
2329     SCOPED_TRACE("Peeking");
2330     GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2331   }
2332   EXPECT_EQ(Shell::GetAllRootWindows()[1],
2333             view->GetWidget()->GetNativeWindow()->GetRootWindow());
2334 
2335   if (test_fullscreen) {
2336     FlingUpOrDown(GetEventGenerator(), view, true /* up */);
2337     GetAppListTestHelper()->WaitUntilIdle();
2338     SCOPED_TRACE("FullscreenAllApps");
2339     GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
2340   }
2341 
2342   // Drag the app list to 50 DIPs from the bottom bezel.
2343   display::Display display =
2344       display::Screen::GetScreen()->GetDisplayNearestView(
2345           view->GetWidget()->GetNativeWindow());
2346   const int bezel_y = display.bounds().bottom();
2347   const int drag_x = display.bounds().x() + 10;
2348   GetEventGenerator()->GestureScrollSequence(
2349       gfx::Point(drag_x, bezel_y - (kAppListBezelMargin + 100)),
2350       gfx::Point(drag_x, bezel_y - (kAppListBezelMargin)),
2351       base::TimeDelta::FromMilliseconds(1500), 100);
2352 
2353   GetAppListTestHelper()->WaitUntilIdle();
2354   SCOPED_TRACE("Closed");
2355   GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2356   GetAppListTestHelper()->CheckVisibility(false);
2357 }
2358 
2359 // Tests that the app list window's bounds height (from the shelf) in kPeeking
2360 // state is the same whether the app list is shown on the primary display
2361 // or the secondary display fir different display placements.
TEST_F(AppListPresenterDelegateTest,AppListPeekingStateHeightOnMultiDisplay)2362 TEST_F(AppListPresenterDelegateTest, AppListPeekingStateHeightOnMultiDisplay) {
2363   UpdateDisplay("800x1000, 800x600");
2364 
2365   const std::vector<display::DisplayPlacement::Position> placements = {
2366       display::DisplayPlacement::LEFT, display::DisplayPlacement::RIGHT,
2367       display::DisplayPlacement::BOTTOM, display::DisplayPlacement::TOP};
2368   for (const display::DisplayPlacement::Position placement : placements) {
2369     SCOPED_TRACE(testing::Message() << "Testing placement " << placement);
2370 
2371     GetAppListTestHelper()->CheckVisibility(false);
2372     Shell::Get()->display_manager()->SetLayoutForCurrentDisplays(
2373         display::test::CreateDisplayLayout(display_manager(), placement, 0));
2374 
2375     GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2376     GetAppListTestHelper()->CheckVisibility(true);
2377     SetAppListStateAndWait(AppListViewState::kPeeking);
2378 
2379     views::Widget* app_list_widget = GetAppListView()->GetWidget();
2380     EXPECT_EQ(Shell::GetAllRootWindows()[0],
2381               app_list_widget->GetNativeWindow()->GetRootWindow());
2382     const display::Display primary_display =
2383         display::Screen::GetScreen()->GetDisplayNearestView(
2384             app_list_widget->GetNativeWindow());
2385     const int primary_display_height =
2386         app_list_widget->GetWindowBoundsInScreen().y() -
2387         primary_display.bounds().bottom();
2388 
2389     GetAppListTestHelper()->Dismiss();
2390     GetAppListTestHelper()->CheckVisibility(false);
2391     const int primary_display_closed_height =
2392         app_list_widget->GetWindowBoundsInScreen().y() -
2393         primary_display.bounds().bottom();
2394 
2395     GetAppListTestHelper()->ShowAndRunLoop(GetSecondaryDisplay().id());
2396     GetAppListTestHelper()->CheckVisibility(true);
2397     SetAppListStateAndWait(AppListViewState::kPeeking);
2398 
2399     app_list_widget = GetAppListView()->GetWidget();
2400     EXPECT_EQ(Shell::GetAllRootWindows()[1],
2401               app_list_widget->GetNativeWindow()->GetRootWindow());
2402     const display::Display secondary_display =
2403         display::Screen::GetScreen()->GetDisplayNearestView(
2404             app_list_widget->GetNativeWindow());
2405     const int secondary_display_height =
2406         app_list_widget->GetWindowBoundsInScreen().y() -
2407         secondary_display.bounds().bottom();
2408 
2409     EXPECT_EQ(secondary_display_height, primary_display_height);
2410 
2411     GetAppListTestHelper()->Dismiss();
2412     GetAppListTestHelper()->CheckVisibility(false);
2413 
2414     const int secondary_display_closed_height =
2415         app_list_widget->GetWindowBoundsInScreen().y() -
2416         secondary_display.bounds().bottom();
2417     EXPECT_EQ(secondary_display_closed_height, primary_display_closed_height);
2418   }
2419 }
2420 
2421 // Tests that the app list window's bounds height (from the shelf) in kHalf
2422 // state is the same whether the app list is shown on the primary display
2423 // or the secondary display fir different display placements.
TEST_F(AppListPresenterDelegateTest,AppListHalfStateHeightOnMultiDisplay)2424 TEST_F(AppListPresenterDelegateTest, AppListHalfStateHeightOnMultiDisplay) {
2425   UpdateDisplay("800x1000, 800x600");
2426 
2427   const std::vector<display::DisplayPlacement::Position> placements = {
2428       display::DisplayPlacement::LEFT, display::DisplayPlacement::RIGHT,
2429       display::DisplayPlacement::BOTTOM, display::DisplayPlacement::TOP};
2430   for (const display::DisplayPlacement::Position placement : placements) {
2431     SCOPED_TRACE(testing::Message() << "Testing placement " << placement);
2432 
2433     GetAppListTestHelper()->CheckVisibility(false);
2434     Shell::Get()->display_manager()->SetLayoutForCurrentDisplays(
2435         display::test::CreateDisplayLayout(display_manager(), placement, 0));
2436 
2437     GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2438     GetAppListTestHelper()->CheckVisibility(true);
2439     SetAppListStateAndWait(AppListViewState::kHalf);
2440 
2441     views::Widget* app_list_widget = GetAppListView()->GetWidget();
2442     EXPECT_EQ(Shell::GetAllRootWindows()[0],
2443               app_list_widget->GetNativeWindow()->GetRootWindow());
2444     const display::Display primary_display =
2445         display::Screen::GetScreen()->GetDisplayNearestView(
2446             app_list_widget->GetNativeWindow());
2447     const int primary_display_height =
2448         app_list_widget->GetWindowBoundsInScreen().y() -
2449         primary_display.bounds().bottom();
2450 
2451     GetAppListTestHelper()->Dismiss();
2452     GetAppListTestHelper()->CheckVisibility(false);
2453     const int primary_display_closed_height =
2454         app_list_widget->GetWindowBoundsInScreen().y() -
2455         primary_display.bounds().bottom();
2456 
2457     GetAppListTestHelper()->ShowAndRunLoop(GetSecondaryDisplay().id());
2458     GetAppListTestHelper()->CheckVisibility(true);
2459     SetAppListStateAndWait(AppListViewState::kHalf);
2460 
2461     app_list_widget = GetAppListView()->GetWidget();
2462     EXPECT_EQ(Shell::GetAllRootWindows()[1],
2463               app_list_widget->GetNativeWindow()->GetRootWindow());
2464     const display::Display secondary_display =
2465         display::Screen::GetScreen()->GetDisplayNearestView(
2466             app_list_widget->GetNativeWindow());
2467     const int secondary_display_height =
2468         app_list_widget->GetWindowBoundsInScreen().y() -
2469         secondary_display.bounds().bottom();
2470 
2471     EXPECT_EQ(secondary_display_height, primary_display_height);
2472 
2473     GetAppListTestHelper()->Dismiss();
2474     GetAppListTestHelper()->CheckVisibility(false);
2475 
2476     const int secondary_display_closed_height =
2477         app_list_widget->GetWindowBoundsInScreen().y() -
2478         secondary_display.bounds().bottom();
2479     EXPECT_EQ(secondary_display_closed_height, primary_display_closed_height);
2480   }
2481 }
2482 
2483 // Tests that a fling from Fullscreen/Peeking closes the app list.
TEST_P(AppListPresenterDelegateTest,FlingDownClosesAppListFromFullscreenAndPeeking)2484 TEST_P(AppListPresenterDelegateTest,
2485        FlingDownClosesAppListFromFullscreenAndPeeking) {
2486   const bool test_fullscreen = GetParam();
2487   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2488   AppListView* view = GetAppListView();
2489   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2490 
2491   if (test_fullscreen) {
2492     FlingUpOrDown(GetEventGenerator(), view, true /* up */);
2493     GetAppListTestHelper()->WaitUntilIdle();
2494     GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
2495   }
2496 
2497   // Fling down, the app list should close.
2498   FlingUpOrDown(GetEventGenerator(), view, false /* down */);
2499   GetAppListTestHelper()->WaitUntilIdle();
2500   GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2501   GetAppListTestHelper()->CheckVisibility(false);
2502 }
2503 
2504 // Tests that drag using a mouse does not always close the app list if the app
2505 // list was previously closed using a fling gesture.
TEST_P(AppListPresenterDelegateTest,MouseDragAfterDownwardFliing)2506 TEST_P(AppListPresenterDelegateTest, MouseDragAfterDownwardFliing) {
2507   const bool test_fullscreen = GetParam();
2508   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2509 
2510   AppListView* view = GetAppListView();
2511   const gfx::Point expand_arrow_point = view->app_list_main_view()
2512                                             ->contents_view()
2513                                             ->expand_arrow_view()
2514                                             ->GetBoundsInScreen()
2515                                             .CenterPoint();
2516 
2517   if (test_fullscreen)
2518     GetEventGenerator()->GestureTapAt(expand_arrow_point);
2519   GetAppListTestHelper()->CheckState(test_fullscreen
2520                                          ? AppListViewState::kFullscreenAllApps
2521                                          : AppListViewState::kPeeking);
2522 
2523   // Fling down, the app list should close.
2524   FlingUpOrDown(GetEventGenerator(), view, false /* down */);
2525   GetAppListTestHelper()->WaitUntilIdle();
2526   GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2527 
2528   // Show the app list again, and perform mouse drag that ends up at the same
2529   // position.
2530   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2531   if (test_fullscreen)
2532     GetEventGenerator()->GestureTapAt(expand_arrow_point);
2533   GetAppListTestHelper()->CheckState(test_fullscreen
2534                                          ? AppListViewState::kFullscreenAllApps
2535                                          : AppListViewState::kPeeking);
2536 
2537   GetEventGenerator()->MoveMouseTo(GetPointOutsideSearchbox());
2538   GetEventGenerator()->PressLeftButton();
2539   GetEventGenerator()->MoveMouseBy(0, -10);
2540   GetEventGenerator()->MoveMouseBy(0, 10);
2541   GetEventGenerator()->ReleaseLeftButton();
2542 
2543   // Verify the app list state has not changed.
2544   GetAppListTestHelper()->CheckState(test_fullscreen
2545                                          ? AppListViewState::kFullscreenAllApps
2546                                          : AppListViewState::kPeeking);
2547 }
2548 
TEST_F(AppListPresenterDelegateTest,MouseWheelFromAppListPresenterImplTransitionsAppListState)2549 TEST_F(AppListPresenterDelegateTest,
2550        MouseWheelFromAppListPresenterImplTransitionsAppListState) {
2551   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2552   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2553 
2554   GetAppListView()->HandleScroll(gfx::Vector2d(0, -30), ui::ET_MOUSEWHEEL);
2555 
2556   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
2557 }
2558 
TEST_P(AppListPresenterDelegateTest,LongUpwardDragInFullscreenShouldNotClose)2559 TEST_P(AppListPresenterDelegateTest, LongUpwardDragInFullscreenShouldNotClose) {
2560   const bool test_fullscreen_search = GetParam();
2561   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2562   AppListView* view = GetAppListView();
2563   FlingUpOrDown(GetEventGenerator(), view, true);
2564   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
2565 
2566   if (test_fullscreen_search) {
2567     // Enter a character into the searchbox to transition to FULLSCREEN_SEARCH.
2568     GetEventGenerator()->PressKey(ui::VKEY_0, 0);
2569     GetAppListTestHelper()->WaitUntilIdle();
2570     GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
2571   }
2572 
2573   // Drag from the center of the applist to the top of the screen very slowly.
2574   // This should not trigger a state transition.
2575   gfx::Point drag_start = view->GetBoundsInScreen().CenterPoint();
2576   drag_start.set_x(15);
2577   gfx::Point drag_end = view->GetBoundsInScreen().top_right();
2578   drag_end.set_x(15);
2579   GetEventGenerator()->GestureScrollSequence(
2580       drag_start, drag_end,
2581       GetEventGenerator()->CalculateScrollDurationForFlingVelocity(
2582           drag_start, drag_end, 1, 1000),
2583       1000);
2584   GetAppListTestHelper()->WaitUntilIdle();
2585   if (test_fullscreen_search)
2586     GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
2587   else
2588     GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
2589 }
2590 
2591 // Tests closing the app list during drag, and verifies the bounds get properly
2592 // updated when the app list is shown again..
TEST_P(AppListPresenterDelegateTest,CloseAppListDuringDrag)2593 TEST_P(AppListPresenterDelegateTest, CloseAppListDuringDrag) {
2594   const bool test_mouse_event = TestMouseEventParam();
2595   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2596   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2597   const gfx::Point drag_start = GetAppListView()->GetBoundsInScreen().origin();
2598 
2599   // Start drag and press escape to close the app list view.
2600   ui::test::EventGenerator* generator = GetEventGenerator();
2601   if (test_mouse_event) {
2602     generator->MoveMouseTo(drag_start);
2603     generator->PressLeftButton();
2604     generator->MoveMouseBy(0, -10);
2605   } else {
2606     generator->MoveTouch(drag_start);
2607     generator->PressTouch();
2608     generator->MoveTouch(drag_start + gfx::Vector2d(0, -10));
2609   }
2610 
2611   EXPECT_TRUE(GetAppListView()->is_in_drag());
2612   generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
2613   GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2614   EXPECT_FALSE(GetAppListView()->is_in_drag());
2615 
2616   // Show the app list and verify the app list returns to peeking position.
2617   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2618   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2619   EXPECT_EQ(drag_start, GetAppListView()->GetBoundsInScreen().origin());
2620 }
2621 
2622 // Tests closing the app list during drag, and verifies that drag updates are
2623 // ignored while the app list is closing.
TEST_P(AppListPresenterDelegateTest,DragUpdateWhileAppListClosing)2624 TEST_P(AppListPresenterDelegateTest, DragUpdateWhileAppListClosing) {
2625   const bool test_mouse_event = TestMouseEventParam();
2626   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2627   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2628   const gfx::Point drag_start = GetAppListView()->GetBoundsInScreen().origin();
2629 
2630   // Set up non zero animation duration to ensure app list is not closed
2631   // immediately.
2632   ui::ScopedAnimationDurationScaleMode non_zero_duration_mode(
2633       ui::ScopedAnimationDurationScaleMode::NON_ZERO_DURATION);
2634   AppListView::SetShortAnimationForTesting(false);
2635 
2636   // Start drag and press escape to close the app list view.
2637   ui::test::EventGenerator* generator = GetEventGenerator();
2638   if (test_mouse_event) {
2639     generator->MoveMouseTo(drag_start);
2640     generator->PressLeftButton();
2641     generator->MoveMouseBy(0, -10);
2642   } else {
2643     generator->MoveTouch(drag_start);
2644     generator->PressTouch();
2645     generator->MoveTouch(drag_start + gfx::Vector2d(0, -10));
2646   }
2647   EXPECT_TRUE(GetAppListView()->is_in_drag());
2648 
2649   generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
2650 
2651   // Update the drag before running the loop that waits for the close animation
2652   // to finish,
2653   if (test_mouse_event) {
2654     generator->MoveMouseBy(0, -10);
2655   } else {
2656     generator->MoveTouch(drag_start + gfx::Vector2d(0, -20));
2657   }
2658 
2659   base::RunLoop().RunUntilIdle();
2660   GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2661   EXPECT_FALSE(GetAppListView()->is_in_drag());
2662 
2663   // Show the app list and verify the app list returns to peeking position.
2664   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2665   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2666   EXPECT_EQ(drag_start, GetAppListView()->GetBoundsInScreen().origin());
2667 }
2668 
2669 // Tests that a drag can not make the app list smaller than the shelf height.
TEST_F(AppListPresenterDelegateTest,LauncherCannotGetSmallerThanShelf)2670 TEST_F(AppListPresenterDelegateTest, LauncherCannotGetSmallerThanShelf) {
2671   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2672   AppListView* view = GetAppListView();
2673 
2674   // Try to place the app list 1 px below the shelf, it should stay at shelf
2675   // height.
2676   int target_y = GetPrimaryShelf()
2677                      ->GetShelfViewForTesting()
2678                      ->GetBoundsInScreen()
2679                      .top_right()
2680                      .y();
2681   const int expected_app_list_y = target_y;
2682   target_y += 1;
2683   view->UpdateYPositionAndOpacity(target_y, 1);
2684 
2685   EXPECT_EQ(expected_app_list_y, view->GetBoundsInScreen().top_right().y());
2686 }
2687 
2688 // Tests that the AppListView is on screen on a small display.
TEST_F(AppListPresenterDelegateTest,SearchBoxShownOnSmallDisplay)2689 TEST_F(AppListPresenterDelegateTest, SearchBoxShownOnSmallDisplay) {
2690   // Update the display to a small scale factor.
2691   UpdateDisplay("600x400");
2692   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2693 
2694   // Animate to Half.
2695   ui::test::EventGenerator* generator = GetEventGenerator();
2696   generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
2697   AppListView* view = GetAppListView();
2698   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2699   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2700   EXPECT_LE(0, view->GetWidget()->GetNativeView()->bounds().y());
2701 
2702   // Animate to peeking.
2703   generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
2704   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2705   EXPECT_LE(0, view->GetWidget()->GetNativeView()->bounds().y());
2706 
2707   // Animate back to Half.
2708   generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
2709   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2710   EXPECT_LE(0, view->GetWidget()->GetNativeView()->bounds().y());
2711 }
2712 
2713 // Tests that the AppListView is on screen on a small work area.
TEST_F(AppListPresenterDelegateTest,SearchBoxShownOnSmallWorkArea)2714 TEST_F(AppListPresenterDelegateTest, SearchBoxShownOnSmallWorkArea) {
2715   // Update the work area to a small size.
2716   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2717   ASSERT_TRUE(display_manager()->UpdateWorkAreaOfDisplay(
2718       GetPrimaryDisplayId(), gfx::Insets(400, 0, 0, 0)));
2719 
2720   // Animate to Half.
2721   ui::test::EventGenerator* generator = GetEventGenerator();
2722   generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
2723   AppListView* view = GetAppListView();
2724   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2725   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2726   EXPECT_LE(GetPrimaryDisplay().work_area().y(),
2727             view->GetWidget()->GetNativeView()->bounds().y());
2728 
2729   // Animate to peeking.
2730   generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
2731   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2732   EXPECT_LE(GetPrimaryDisplay().work_area().y(),
2733             view->GetWidget()->GetNativeView()->bounds().y());
2734 
2735   // Animate back to Half.
2736   generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
2737   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
2738   EXPECT_LE(GetPrimaryDisplay().work_area().y(),
2739             view->GetWidget()->GetNativeView()->bounds().y());
2740 }
2741 
2742 // Tests that no crash occurs after an attempt to show app list in an invalid
2743 // display.
TEST_F(AppListPresenterDelegateTest,ShowInInvalidDisplay)2744 TEST_F(AppListPresenterDelegateTest, ShowInInvalidDisplay) {
2745   GetAppListTestHelper()->ShowAndRunLoop(display::kInvalidDisplayId);
2746   GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
2747 }
2748 
2749 // Tests that tap the auto-hide shelf with app list opened should dismiss the
2750 // app list but keep shelf visible.
TEST_F(AppListPresenterDelegateTest,TapAutoHideShelfWithAppListOpened)2751 TEST_F(AppListPresenterDelegateTest, TapAutoHideShelfWithAppListOpened) {
2752   Shelf* shelf = GetPrimaryShelf();
2753   shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
2754 
2755   // Create a normal unmaximized window; the shelf should be hidden.
2756   std::unique_ptr<views::Widget> window = CreateTestWidget();
2757   window->SetBounds(gfx::Rect(0, 0, 100, 100));
2758   GetAppListTestHelper()->CheckVisibility(false);
2759   EXPECT_EQ(SHELF_AUTO_HIDE, shelf->GetVisibilityState());
2760   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
2761 
2762   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2763   GetAppListTestHelper()->CheckVisibility(true);
2764   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
2765 
2766   // Tap the system tray should open system tray bubble and keep shelf visible.
2767   ui::test::EventGenerator* generator = GetEventGenerator();
2768   generator->GestureTapAt(
2769       GetPrimaryUnifiedSystemTray()->GetBoundsInScreen().CenterPoint());
2770   EXPECT_TRUE(GetPrimaryUnifiedSystemTray()->IsBubbleShown());
2771   GetAppListTestHelper()->CheckVisibility(false);
2772   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
2773 
2774   // Tap to dismiss the app list and the auto-hide shelf.
2775   generator->GestureTapAt(gfx::Point(0, 0));
2776   EXPECT_FALSE(GetPrimaryUnifiedSystemTray()->IsBubbleShown());
2777   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
2778   GetAppListTestHelper()->CheckVisibility(false);
2779 
2780   // Show the AppList again.
2781   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2782   GetAppListTestHelper()->CheckVisibility(true);
2783   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
2784 
2785   // Make sure the shelf has at least one item.
2786   ShelfItem item =
2787       ShelfTestUtil::AddAppShortcut(base::NumberToString(1), TYPE_PINNED_APP);
2788 
2789   // Wait for shelf view's bounds animation to end. Otherwise the scrollable
2790   // shelf's bounds are not updated yet.
2791   ShelfView* const shelf_view = shelf->GetShelfViewForTesting();
2792   ShelfViewTestAPI shelf_view_test_api(shelf_view);
2793   shelf_view_test_api.RunMessageLoopUntilAnimationsDone();
2794 
2795   // Test that tapping the auto-hidden shelf dismisses the app list when tapping
2796   // part of the shelf that does not contain the apps.
2797   generator->GestureTapAt(shelf_view->GetBoundsInScreen().left_center() +
2798                           gfx::Vector2d(10, 0));
2799   GetAppListTestHelper()->CheckVisibility(false);
2800   EXPECT_EQ(SHELF_AUTO_HIDE_HIDDEN, shelf->GetAutoHideState());
2801 
2802   // Show the AppList again.
2803   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2804   GetAppListTestHelper()->CheckVisibility(true);
2805   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
2806 
2807   // App list should remain visible when tapping on a shelf app button.
2808   ASSERT_TRUE(shelf_view_test_api.GetButton(0));
2809   generator->GestureTapAt(
2810       shelf_view_test_api.GetButton(0)->GetBoundsInScreen().CenterPoint());
2811   GetAppListTestHelper()->CheckVisibility(true);
2812   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
2813 }
2814 
TEST_F(AppListPresenterDelegateTest,ClickingShelfArrowDoesNotHideAppList)2815 TEST_F(AppListPresenterDelegateTest, ClickingShelfArrowDoesNotHideAppList) {
2816   // Add enough shelf items for the shelf to enter overflow.
2817   Shelf* const shelf = GetPrimaryShelf();
2818   ScrollableShelfView* const scrollable_shelf_view =
2819       shelf->hotseat_widget()->scrollable_shelf_view();
2820   ShelfView* const shelf_view = shelf->GetShelfViewForTesting();
2821   int index = 0;
2822   while (scrollable_shelf_view->layout_strategy_for_test() ==
2823          ScrollableShelfView::kNotShowArrowButtons) {
2824     ShelfItem item = ShelfTestUtil::AddAppShortcut(
2825         base::NumberToString(index++), TYPE_PINNED_APP);
2826   }
2827 
2828   ShelfViewTestAPI shelf_view_test_api(shelf_view);
2829   shelf_view_test_api.RunMessageLoopUntilAnimationsDone();
2830 
2831   shelf->SetAutoHideBehavior(ShelfAutoHideBehavior::kAlways);
2832 
2833   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2834   GetAppListTestHelper()->CheckVisibility(true);
2835   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
2836 
2837   // Click right scrollable shelf arrow - verify the the app list remains
2838   // visible.
2839   const views::View* right_arrow = scrollable_shelf_view->right_arrow();
2840   ASSERT_TRUE(right_arrow->GetVisible());
2841   GetEventGenerator()->MoveMouseTo(
2842       right_arrow->GetBoundsInScreen().CenterPoint());
2843   GetEventGenerator()->ClickLeftButton();
2844 
2845   GetAppListTestHelper()->CheckVisibility(true);
2846   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
2847 
2848   // Click left button - verify the app list stays visible.
2849   const views::View* left_arrow = scrollable_shelf_view->left_arrow();
2850   ASSERT_TRUE(left_arrow->GetVisible());
2851   GetEventGenerator()->MoveMouseTo(
2852       left_arrow->GetBoundsInScreen().CenterPoint());
2853   GetEventGenerator()->ClickLeftButton();
2854 
2855   GetAppListTestHelper()->CheckVisibility(true);
2856   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
2857 
2858   // Click right of the right arrow - verify the app list gets dismissed.
2859   ASSERT_TRUE(right_arrow->GetVisible());
2860   GetEventGenerator()->MoveMouseTo(
2861       right_arrow->GetBoundsInScreen().right_center() + gfx::Vector2d(10, 0));
2862   GetEventGenerator()->ClickLeftButton();
2863 
2864   GetAppListTestHelper()->CheckVisibility(false);
2865   EXPECT_EQ(SHELF_AUTO_HIDE_SHOWN, shelf->GetAutoHideState());
2866 }
2867 
2868 // Verifies that in clamshell mode, AppList has the expected state based on the
2869 // drag distance after dragging from Peeking state.
TEST_F(AppListPresenterDelegateTest,DragAppListViewFromPeeking)2870 TEST_F(AppListPresenterDelegateTest, DragAppListViewFromPeeking) {
2871   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2872   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2873 
2874   // Calculate |threshold| in the same way with AppListView::EndDrag.
2875   const int threshold = AppListConfig::instance().peeking_app_list_height() /
2876                         kAppListThresholdDenominator;
2877 
2878   // Drag AppListView downward by |threshold| then release the gesture.
2879   // Check the final state should be Peeking.
2880   ui::test::EventGenerator* generator = GetEventGenerator();
2881   AppListView* view = GetAppListView();
2882   const int drag_to_peeking_distance = threshold;
2883   gfx::Point drag_start = view->GetBoundsInScreen().top_center();
2884   gfx::Point drag_end(drag_start.x(),
2885                       drag_start.y() + drag_to_peeking_distance);
2886   generator->GestureScrollSequence(
2887       drag_start, drag_end,
2888       generator->CalculateScrollDurationForFlingVelocity(drag_start, drag_end,
2889                                                          2, 1000),
2890       1000);
2891   GetAppListTestHelper()->WaitUntilIdle();
2892   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2893 
2894   // Drag AppListView upward by bigger distance then release the gesture.
2895   // Check the final state should be kFullscreenAllApps.
2896   const int drag_to_fullscreen_distance = threshold + 1;
2897   drag_start = view->GetBoundsInScreen().top_center();
2898   drag_end =
2899       gfx::Point(drag_start.x(), drag_start.y() - drag_to_fullscreen_distance);
2900 
2901   generator->GestureScrollSequence(
2902       drag_start, drag_end,
2903       generator->CalculateScrollDurationForFlingVelocity(drag_start, drag_end,
2904                                                          2, 1000),
2905       1000);
2906   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
2907 }
2908 
2909 // Tests that the app list background corner radius remains constant during app
2910 // list drag if the shelf is not in maximized state.
TEST_F(AppListPresenterDelegateTest,BackgroundCornerRadiusDuringDrag)2911 TEST_F(AppListPresenterDelegateTest, BackgroundCornerRadiusDuringDrag) {
2912   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2913   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2914 
2915   const gfx::Point shelf_top = GetPrimaryShelf()
2916                                    ->GetShelfViewForTesting()
2917                                    ->GetBoundsInScreen()
2918                                    .top_center();
2919   const int background_radius = ShelfConfig::Get()->shelf_size() / 2;
2920 
2921   AppListView* view = GetAppListView();
2922   const views::View* const background_shield =
2923       view->GetAppListBackgroundShieldForTest();
2924   ui::test::EventGenerator* generator = GetEventGenerator();
2925 
2926   // Start drag at the peeking height, and move to different
2927   // positions relative to the shelf top.
2928   // Verify that the app list background shield never changes.
2929   const gfx::Point peeking_top = view->GetBoundsInScreen().top_center();
2930   generator->MoveTouch(peeking_top);
2931   generator->PressTouch();
2932   EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2933             background_shield->layer()->rounded_corner_radii());
2934 
2935   // Move above the shelf, with an offset less than the background radius.
2936   generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius / 5));
2937   EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2938             background_shield->layer()->rounded_corner_radii());
2939 
2940   // Move to the top of the shelf.
2941   generator->MoveTouch(shelf_top);
2942   EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2943             background_shield->layer()->rounded_corner_radii());
2944 
2945   // Move to half rounded background radius height.
2946   generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius / 2));
2947   EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2948             background_shield->layer()->rounded_corner_radii());
2949 
2950   // Move to the height just under the background radius.
2951   generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius - 1));
2952   EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2953             background_shield->layer()->rounded_corner_radii());
2954 
2955   // Move to the height that equals the background radius.
2956   generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius));
2957   EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2958             background_shield->layer()->rounded_corner_radii());
2959 
2960   // Move to the height just over the background radius.
2961   generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius + 1));
2962   EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2963             background_shield->layer()->rounded_corner_radii());
2964   generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius + 5));
2965   EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2966             background_shield->layer()->rounded_corner_radii());
2967 
2968   // Move above the peeking height.
2969   generator->MoveTouch(gfx::Point(peeking_top.x(), peeking_top.y() + 5));
2970   EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2971             background_shield->layer()->rounded_corner_radii());
2972 
2973   // Move back to peeking height, and end drag.
2974   generator->MoveTouch(peeking_top);
2975   generator->ReleaseTouch();
2976   GetAppListTestHelper()->WaitUntilIdle();
2977   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2978 
2979   EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
2980             background_shield->layer()->rounded_corner_radii());
2981 }
2982 
2983 // Tests how app list background rounded corners are changed during a drag while
2984 // the shelf is in a maximized state (i.e. while a maximized window is shown).
TEST_F(AppListPresenterDelegateTest,BackgroundCornerRadiusDuringDragWithMaximizedShelf)2985 TEST_F(AppListPresenterDelegateTest,
2986        BackgroundCornerRadiusDuringDragWithMaximizedShelf) {
2987   auto window = CreateTestWindow();
2988   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MAXIMIZED);
2989 
2990   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
2991   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
2992 
2993   const gfx::Point shelf_top = GetPrimaryShelf()
2994                                    ->GetShelfViewForTesting()
2995                                    ->GetBoundsInScreen()
2996                                    .top_center();
2997   const int background_radius = ShelfConfig::Get()->shelf_size() / 2;
2998 
2999   AppListView* view = GetAppListView();
3000   const views::View* const background_shield =
3001       view->GetAppListBackgroundShieldForTest();
3002   ui::test::EventGenerator* generator = GetEventGenerator();
3003 
3004   // Start drag at the peeking app list top.
3005   const gfx::Point peeking_top = view->GetBoundsInScreen().top_center();
3006   generator->MoveTouch(peeking_top);
3007   generator->PressTouch();
3008 
3009   EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
3010             background_shield->layer()->rounded_corner_radii());
3011 
3012   // Move above the shelf, with an offset less than the background radius.
3013   // Verify that current background corner radius matches the offset from the
3014   // shelf.
3015   generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius / 5));
3016   EXPECT_EQ(
3017       gfx::RoundedCornersF(background_radius / 5, background_radius / 5, 0, 0),
3018       background_shield->layer()->rounded_corner_radii());
3019 
3020   // Move to the shelf top - background should have no rounded corners.
3021   generator->MoveTouch(shelf_top);
3022   EXPECT_EQ(gfx::RoundedCornersF(),
3023             background_shield->layer()->rounded_corner_radii());
3024 
3025   // Move to half background radius height - the background corner radius should
3026   // match the offset from the shelf.
3027   generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius / 2));
3028   EXPECT_EQ(
3029       gfx::RoundedCornersF(background_radius / 2, background_radius / 2, 0, 0),
3030       background_shield->layer()->rounded_corner_radii());
3031 
3032   // Move to the height just under the background radius - the current
3033   // background corners should be equal to the offset from the shelf.
3034   generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius - 1));
3035   EXPECT_EQ(
3036       gfx::RoundedCornersF(background_radius - 1, background_radius - 1, 0, 0),
3037       background_shield->layer()->rounded_corner_radii());
3038 
3039   // Move to the height that equals the background radius - the current
3040   // background corners should be equal to the offset from the shelf.
3041   generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius));
3042   EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
3043             background_shield->layer()->rounded_corner_radii());
3044 
3045   // Move to the height just over the background radius - the background corner
3046   // radius value should stay at the |background_radius| value.
3047   generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius + 1));
3048   EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
3049             background_shield->layer()->rounded_corner_radii());
3050   generator->MoveTouch(shelf_top - gfx::Vector2d(0, background_radius + 5));
3051   EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
3052             background_shield->layer()->rounded_corner_radii());
3053 
3054   // Move above the peeking height - the background radius should remain the
3055   // same.
3056   generator->MoveTouch(gfx::Point(peeking_top.x(), peeking_top.y() + 5));
3057   EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
3058             background_shield->layer()->rounded_corner_radii());
3059 
3060   // Move back to peeking height, and end drag.
3061   generator->MoveTouch(peeking_top);
3062   generator->ReleaseTouch();
3063   GetAppListTestHelper()->WaitUntilIdle();
3064   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3065 
3066   EXPECT_EQ(gfx::RoundedCornersF(background_radius, background_radius, 0, 0),
3067             background_shield->layer()->rounded_corner_radii());
3068 }
3069 
3070 // Tests how app list is laid out during different state transitions and app
3071 // list drag.
3072 class AppListPresenterDelegateLayoutTest : public AppListPresenterDelegateTest {
3073  public:
AppListPresenterDelegateLayoutTest()3074   AppListPresenterDelegateLayoutTest() {
3075     scoped_feature_list_.InitAndEnableFeature(features::kEnableBackgroundBlur);
3076   }
3077   ~AppListPresenterDelegateLayoutTest() override = default;
3078 
SetUp()3079   void SetUp() override {
3080     AppListPresenterDelegateTest::SetUp();
3081 
3082     UpdateDisplay("1080x900");
3083     GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3084   }
3085 
ExpectedSuggestionChipContainerTop(const gfx::Rect & search_box_bounds)3086   int ExpectedSuggestionChipContainerTop(const gfx::Rect& search_box_bounds) {
3087     return search_box_bounds.bottom() + 16 /*suggesion chip top margin*/;
3088   }
3089 
3090   // Calculates expected apps grid position based on display height and the
3091   // search box in-screen bounds.
3092   // NOTE: This assumes that the display size is such that the preferred apps
3093   // grid size is within min and max apps grid height (in which case the margin
3094   // when scalable app list is not enabled is 1 / 16 of the available height).
ExpectedAppsGridTop(const AppListConfig & config,int display_height,const gfx::Rect & search_box_bounds)3095   int ExpectedAppsGridTop(const AppListConfig& config,
3096                           int display_height,
3097                           const gfx::Rect& search_box_bounds) {
3098     return ExpectedSuggestionChipContainerTop(search_box_bounds) +
3099            32 /*suggestion chip container height*/ +
3100            config.grid_fadeout_zone_height() -
3101            config.grid_fadeout_mask_height();
3102   }
3103 
3104   // Calculates expected apps grid position on the search results page based on
3105   // the display height and the search box in-screen bounds.
ExpectedAppsGridTopForSearchResults(const AppListConfig & config,int display_height,const gfx::Rect & search_box_bounds)3106   int ExpectedAppsGridTopForSearchResults(const AppListConfig& config,
3107                                           int display_height,
3108                                           const gfx::Rect& search_box_bounds) {
3109     const int top =
3110         ExpectedAppsGridTop(config, display_height, search_box_bounds);
3111     // In the search results page, the apps grid is shown 24 dip below where
3112     // they'd be shown in the apps page. The |top| was calculated relative to
3113     // search box bounds in the search results page, so it has to be further
3114     // offset by the difference between search box bottom bounds in the apps and
3115     // search results page.
3116     const int search_box_diff =
3117         contents_view()->GetSearchBoxBounds(AppListState::kStateApps).bottom() -
3118         contents_view()
3119             ->GetSearchBoxBounds(AppListState::kStateSearchResults)
3120             .bottom();
3121     return top + search_box_diff +
3122            24 /*apps grid offset in fullscreen search state*/;
3123   }
3124 
contents_view()3125   ContentsView* contents_view() {
3126     return GetAppListView()->app_list_main_view()->contents_view();
3127   }
3128 
apps_grid_view()3129   AppsGridView* apps_grid_view() {
3130     return GetAppListView()
3131         ->app_list_main_view()
3132         ->contents_view()
3133         ->apps_container_view()
3134         ->apps_grid_view();
3135   }
3136 
3137  private:
3138   base::test::ScopedFeatureList scoped_feature_list_;
3139 };
3140 
3141 // Tests that the app list contents top margin is gradually updated during drag
3142 // between peeking and fullscreen view state while showing apps page.
TEST_F(AppListPresenterDelegateLayoutTest,AppsPagePositionDuringDrag)3143 TEST_F(AppListPresenterDelegateLayoutTest, AppsPagePositionDuringDrag) {
3144   const AppListConfig& config = GetAppListView()->GetAppListConfig();
3145   const int shelf_height = ShelfConfig::Get()->shelf_size();
3146   const int fullscreen_y = 0;
3147   const int closed_y = 900 - shelf_height;
3148   const int fullscreen_search_box_padding = (900 - shelf_height) / 16;
3149 
3150   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3151   const gfx::Point peeking_top =
3152       GetAppListView()->GetBoundsInScreen().top_center();
3153 
3154   // Drag AppListView upwards half way to the top of the screen, and check the
3155   // search box padding has been updated to a value half-way between peeking and
3156   // fullscreen values.
3157   ui::test::EventGenerator* generator = GetEventGenerator();
3158   generator->MoveTouch(peeking_top);
3159   generator->PressTouch();
3160   generator->MoveTouch(
3161       gfx::Point(peeking_top.x(), (peeking_top.y() + fullscreen_y) / 2));
3162   GetAppListTestHelper()->WaitUntilIdle();
3163 
3164   gfx::Rect search_box_bounds =
3165       GetAppListView()->search_box_view()->GetBoundsInScreen();
3166   search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3167 
3168   float progress = GetAppListView()->GetAppListTransitionProgress(
3169       AppListView::kProgressFlagNone);
3170   EXPECT_LE(std::abs(progress - 1.5f), 0.01f);
3171 
3172   EXPECT_EQ((peeking_top.y() + fullscreen_y) / 2 +
3173                 gfx::Tween::IntValueBetween(
3174                     progress - 1, config.search_box_peeking_top_padding(),
3175                     fullscreen_search_box_padding),
3176             search_box_bounds.y());
3177 
3178   EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds),
3179             apps_grid_view()->GetBoundsInScreen().y());
3180   EXPECT_TRUE(apps_grid_view()->GetVisible());
3181   // In apps state, search results page should be hidden behind the search
3182   // box.
3183   EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen());
3184 
3185   // Move to the fullscreen position, and verify the search box padding is
3186   // equal to the expected fullscreen value.
3187   generator->MoveTouch(gfx::Point(peeking_top.x(), fullscreen_y));
3188   GetAppListTestHelper()->WaitUntilIdle();
3189 
3190   EXPECT_EQ(2.0f, GetAppListView()->GetAppListTransitionProgress(
3191                       AppListView::kProgressFlagNone));
3192 
3193   search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3194   search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3195 
3196   EXPECT_EQ(fullscreen_search_box_padding, search_box_bounds.y());
3197   EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds),
3198             apps_grid_view()->GetBoundsInScreen().y());
3199   EXPECT_TRUE(apps_grid_view()->GetVisible());
3200   EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen());
3201 
3202   // Move half way between peeking and closed state - the search box padding
3203   // should be half distance between closed and peeking padding.
3204   generator->MoveTouch(
3205       gfx::Point(peeking_top.x(), (peeking_top.y() + closed_y) / 2));
3206   GetAppListTestHelper()->WaitUntilIdle();
3207 
3208   search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3209   search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3210 
3211   progress = GetAppListView()->GetAppListTransitionProgress(
3212       AppListView::kProgressFlagNone);
3213   EXPECT_LE(std::abs(progress - 0.5f), 0.01f);
3214 
3215   EXPECT_EQ((peeking_top.y() + closed_y) / 2 +
3216                 gfx::Tween::IntValueBetween(
3217                     progress, config.search_box_peeking_top_padding(),
3218                     config.search_box_closed_top_padding()),
3219             search_box_bounds.y());
3220   EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds),
3221             apps_grid_view()->GetBoundsInScreen().y());
3222   EXPECT_TRUE(apps_grid_view()->GetVisible());
3223   EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen());
3224 
3225   // Move to the closed state height, and verify the search box padding matches
3226   // the state.
3227   generator->MoveTouch(gfx::Point(peeking_top.x(), closed_y));
3228   GetAppListTestHelper()->WaitUntilIdle();
3229   EXPECT_EQ(0.0f, GetAppListView()->GetAppListTransitionProgress(
3230                       AppListView::kProgressFlagNone));
3231 
3232   search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3233   search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3234 
3235   EXPECT_EQ(closed_y + config.search_box_closed_top_padding(),
3236             search_box_bounds.y());
3237   EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds),
3238             apps_grid_view()->GetBoundsInScreen().y());
3239   EXPECT_TRUE(apps_grid_view()->GetVisible());
3240   EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen());
3241 }
3242 
3243 // Tests that the app list contents top margin is gradually updated during drag
3244 // between half and fullscreen state while showing search results.
TEST_F(AppListPresenterDelegateLayoutTest,SearchResultsPagePositionDuringDrag)3245 TEST_F(AppListPresenterDelegateLayoutTest,
3246        SearchResultsPagePositionDuringDrag) {
3247   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3248 
3249   // Enter text in the search box to transition to half app list.
3250   ui::test::EventGenerator* generator = GetEventGenerator();
3251   generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
3252   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
3253 
3254   const AppListConfig& config = GetAppListView()->GetAppListConfig();
3255   const int shelf_height = ShelfConfig::Get()->shelf_size();
3256   const int search_results_height = 440;
3257   const int fullscreen_y = 0;
3258   const int closed_y = 900 - shelf_height;
3259   const int fullscreen_search_box_padding = (900 - shelf_height) / 16;
3260 
3261   const gfx::Point half_top =
3262       GetAppListView()->GetBoundsInScreen().top_center();
3263 
3264   // Drag AppListView upwards half way to the top of the screen, and check the
3265   // search box padding has been updated to a value half-way between peeking and
3266   // fullscreen values.
3267   generator->MoveTouch(half_top);
3268   generator->PressTouch();
3269   generator->MoveTouch(
3270       gfx::Point(half_top.x(), (half_top.y() + fullscreen_y) / 2));
3271   GetAppListTestHelper()->WaitUntilIdle();
3272 
3273   gfx::Rect search_box_bounds =
3274       GetAppListView()->search_box_view()->GetBoundsInScreen();
3275   search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3276 
3277   float progress = GetAppListView()->GetAppListTransitionProgress(
3278       AppListView::kProgressFlagSearchResults);
3279   EXPECT_LE(std::abs(progress - 1.5f), 0.01f);
3280 
3281   EXPECT_EQ((half_top.y() + fullscreen_y) / 2 +
3282                 gfx::Tween::IntValueBetween(
3283                     progress - 1, config.search_box_fullscreen_top_padding(),
3284                     fullscreen_search_box_padding),
3285             search_box_bounds.y());
3286   EXPECT_EQ(search_box_bounds.y(),
3287             search_result_page()->GetBoundsInScreen().y());
3288   EXPECT_EQ(search_results_height,
3289             search_result_page()->GetBoundsInScreen().height());
3290   EXPECT_EQ(ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds),
3291             apps_grid_view()->GetBoundsInScreen().y());
3292   EXPECT_TRUE(apps_grid_view()->GetVisible());
3293 
3294   // Move to the fullscreen position, and verify the search box padding is
3295   // equal to the expected fullscreen value.
3296   generator->MoveTouch(gfx::Point(half_top.x(), fullscreen_y));
3297   GetAppListTestHelper()->WaitUntilIdle();
3298   EXPECT_EQ(2.0f, GetAppListView()->GetAppListTransitionProgress(
3299                       AppListView::kProgressFlagSearchResults));
3300 
3301   search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3302   search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3303 
3304   EXPECT_EQ(fullscreen_search_box_padding, search_box_bounds.y());
3305   EXPECT_EQ(search_box_bounds.y(),
3306             search_result_page()->GetBoundsInScreen().y());
3307   EXPECT_EQ(search_results_height,
3308             search_result_page()->GetBoundsInScreen().height());
3309   EXPECT_EQ(ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds),
3310             apps_grid_view()->GetBoundsInScreen().y());
3311   EXPECT_TRUE(apps_grid_view()->GetVisible());
3312 
3313   // Move half way between peeking and closed state - the search box padding
3314   // should be half distance between closed and peeking padding.
3315   generator->MoveTouch(gfx::Point(half_top.x(), (half_top.y() + closed_y) / 2));
3316   GetAppListTestHelper()->WaitUntilIdle();
3317 
3318   progress = GetAppListView()->GetAppListTransitionProgress(
3319       AppListView::kProgressFlagSearchResults);
3320   EXPECT_LE(std::abs(progress - 0.5f), 0.01f);
3321 
3322   search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3323   search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3324 
3325   EXPECT_EQ((half_top.y() + closed_y) / 2 +
3326                 gfx::Tween::IntValueBetween(
3327                     progress, config.search_box_fullscreen_top_padding(),
3328                     config.search_box_closed_top_padding()),
3329             search_box_bounds.y());
3330   EXPECT_EQ(search_box_bounds.y(),
3331             search_result_page()->GetBoundsInScreen().y());
3332   EXPECT_EQ(search_results_height,
3333             search_result_page()->GetBoundsInScreen().height());
3334   EXPECT_EQ(ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds),
3335             apps_grid_view()->GetBoundsInScreen().y());
3336   EXPECT_TRUE(apps_grid_view()->GetVisible());
3337 
3338   // Move to the closed state height, and verify the search box padding matches
3339   // the state.
3340   generator->MoveTouch(gfx::Point(half_top.x(), closed_y));
3341   GetAppListTestHelper()->WaitUntilIdle();
3342   EXPECT_EQ(0.0f, GetAppListView()->GetAppListTransitionProgress(
3343                       AppListView::kProgressFlagSearchResults));
3344 
3345   search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3346   search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3347 
3348   EXPECT_EQ(closed_y + config.search_box_closed_top_padding(),
3349             search_box_bounds.y());
3350   EXPECT_EQ(search_box_bounds.y(),
3351             search_result_page()->GetBoundsInScreen().y());
3352   EXPECT_EQ(search_results_height,
3353             search_result_page()->GetBoundsInScreen().height());
3354   EXPECT_EQ(ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds),
3355             apps_grid_view()->GetBoundsInScreen().y());
3356   EXPECT_TRUE(apps_grid_view()->GetVisible());
3357 }
3358 
3359 // Tests changing the active app list page while drag is in progress.
TEST_F(AppListPresenterDelegateLayoutTest,SwitchPageDuringDrag)3360 TEST_F(AppListPresenterDelegateLayoutTest, SwitchPageDuringDrag) {
3361   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3362   const gfx::Point peeking_top =
3363       GetAppListView()->GetBoundsInScreen().top_center();
3364 
3365   // Enter text in the search box to transition to half app list.
3366   ui::test::EventGenerator* generator = GetEventGenerator();
3367   generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
3368   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
3369 
3370   const gfx::Point half_top =
3371       GetAppListView()->GetBoundsInScreen().top_center();
3372 
3373   const AppListConfig& config = GetAppListView()->GetAppListConfig();
3374   const int shelf_height = ShelfConfig::Get()->shelf_size();
3375   const int search_results_height = 440;
3376   const int fullscreen_y = 0;
3377   const int fullscreen_search_box_padding = (900 - shelf_height) / 16;
3378 
3379   // Drag AppListView upwards half way to the top of the screen, and check the
3380   // search box padding has been updated to a value half-way between peeking and
3381   // fullscreen values.
3382   generator->MoveTouch(half_top);
3383   generator->PressTouch();
3384   generator->MoveTouch(
3385       gfx::Point(half_top.x(), (half_top.y() + fullscreen_y) / 2));
3386   GetAppListTestHelper()->WaitUntilIdle();
3387 
3388   gfx::Rect search_box_bounds =
3389       GetAppListView()->search_box_view()->GetBoundsInScreen();
3390   search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3391 
3392   float progress = GetAppListView()->GetAppListTransitionProgress(
3393       AppListView::kProgressFlagSearchResults);
3394   EXPECT_LE(std::abs(progress - 1.5f), 0.01f);
3395   EXPECT_EQ((half_top.y() + fullscreen_y) / 2 +
3396                 gfx::Tween::IntValueBetween(
3397                     progress - 1, config.search_box_fullscreen_top_padding(),
3398                     fullscreen_search_box_padding),
3399             search_box_bounds.y());
3400   EXPECT_EQ(search_box_bounds.y(),
3401             search_result_page()->GetBoundsInScreen().y());
3402   EXPECT_EQ(search_results_height,
3403             search_result_page()->GetBoundsInScreen().height());
3404   EXPECT_EQ(ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds),
3405             apps_grid_view()->GetBoundsInScreen().y());
3406   EXPECT_TRUE(apps_grid_view()->GetVisible());
3407 
3408   const gfx::Rect apps_grid_bounds_in_results_page =
3409       apps_grid_view()->GetBoundsInScreen();
3410   const gfx::Rect app_list_bounds = GetAppListView()->GetBoundsInScreen();
3411 
3412   // Press ESC key - this should move the UI back to the app list.
3413   generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
3414   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3415 
3416   // The app list position should remain the same.
3417   EXPECT_EQ(app_list_bounds, GetAppListView()->GetBoundsInScreen());
3418 
3419   // The search box should be moved so drag progress for peeking state matches
3420   // the current height.
3421   float new_progress = (0.5 * half_top.y()) / peeking_top.y();
3422   int expected_search_box_top =
3423       new_progress * peeking_top.y() +
3424       (1 - new_progress) * fullscreen_search_box_padding +
3425       new_progress * config.search_box_peeking_top_padding();
3426 
3427   search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3428   search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3429 
3430   EXPECT_EQ(expected_search_box_top, search_box_bounds.y());
3431   EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds),
3432             apps_grid_view()->GetBoundsInScreen().y());
3433   EXPECT_TRUE(apps_grid_view()->GetVisible());
3434   EXPECT_EQ(apps_grid_bounds_in_results_page.y() - 24,
3435             apps_grid_view()->GetBoundsInScreen().y());
3436   EXPECT_EQ(apps_grid_bounds_in_results_page.size(),
3437             apps_grid_view()->GetBoundsInScreen().size());
3438   EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen());
3439 
3440   // Enter text in the search box to transition back to search results page.
3441   generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
3442   GetAppListTestHelper()->CheckState(AppListViewState::kHalf);
3443 
3444   search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3445   search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3446 
3447   progress = GetAppListView()->GetAppListTransitionProgress(
3448       AppListView::kProgressFlagSearchResults);
3449   EXPECT_LE(std::abs(progress - 1.5f), 0.01f);
3450   EXPECT_EQ((half_top.y() + fullscreen_y) / 2 +
3451                 gfx::Tween::IntValueBetween(
3452                     progress - 1, config.search_box_fullscreen_top_padding(),
3453                     fullscreen_search_box_padding),
3454             search_box_bounds.y());
3455   EXPECT_EQ(search_box_bounds.y(),
3456             search_result_page()->GetBoundsInScreen().y());
3457   EXPECT_EQ(search_results_height,
3458             search_result_page()->GetBoundsInScreen().height());
3459   EXPECT_EQ(ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds),
3460             apps_grid_view()->GetBoundsInScreen().y());
3461   EXPECT_TRUE(apps_grid_view()->GetVisible());
3462 }
3463 
3464 // Tests changing the active app list page in fullscreen state.
TEST_F(AppListPresenterDelegateLayoutTest,SwitchPageInFullscreen)3465 TEST_F(AppListPresenterDelegateLayoutTest, SwitchPageInFullscreen) {
3466   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3467   FlingUpOrDown(GetEventGenerator(), GetAppListView(), true);
3468   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
3469 
3470   const AppListConfig& config = GetAppListView()->GetAppListConfig();
3471   const int shelf_height = ShelfConfig::Get()->shelf_size();
3472   const int search_results_height = 440;
3473   const int fullscreen_y = 0;
3474   const int fullscreen_search_box_padding = (900 - shelf_height) / 16;
3475 
3476   gfx::Rect search_box_bounds =
3477       GetAppListView()->search_box_view()->GetBoundsInScreen();
3478   search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3479 
3480   EXPECT_EQ(fullscreen_y + fullscreen_search_box_padding,
3481             search_box_bounds.y());
3482   EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds),
3483             apps_grid_view()->GetBoundsInScreen().y());
3484   EXPECT_TRUE(apps_grid_view()->GetVisible());
3485   EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen());
3486 
3487   const gfx::Rect app_list_bounds = GetAppListView()->GetBoundsInScreen();
3488 
3489   // Enter text in the search box to transition to half app list.
3490   ui::test::EventGenerator* generator = GetEventGenerator();
3491   generator->PressKey(ui::KeyboardCode::VKEY_0, 0);
3492   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
3493 
3494   search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3495   search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3496 
3497   EXPECT_EQ(app_list_bounds, GetAppListView()->GetBoundsInScreen());
3498   EXPECT_EQ(fullscreen_y + fullscreen_search_box_padding,
3499             search_box_bounds.y());
3500   EXPECT_EQ(search_box_bounds.y(),
3501             search_result_page()->GetBoundsInScreen().y());
3502   EXPECT_EQ(search_results_height,
3503             search_result_page()->GetBoundsInScreen().height());
3504   EXPECT_EQ(ExpectedAppsGridTopForSearchResults(config, 900, search_box_bounds),
3505             apps_grid_view()->GetBoundsInScreen().y());
3506   EXPECT_TRUE(apps_grid_view()->GetVisible());
3507   const gfx::Rect apps_grid_bounds_in_results_page =
3508       apps_grid_view()->GetBoundsInScreen();
3509 
3510   // Press ESC key - this should move the UI back to the app list.
3511   generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
3512   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
3513 
3514   search_box_bounds = GetAppListView()->search_box_view()->GetBoundsInScreen();
3515   search_box_bounds.Inset(GetAppListView()->search_box_view()->GetInsets());
3516 
3517   EXPECT_EQ(app_list_bounds, GetAppListView()->GetBoundsInScreen());
3518   EXPECT_EQ(fullscreen_y + fullscreen_search_box_padding,
3519             search_box_bounds.y());
3520   EXPECT_EQ(ExpectedAppsGridTop(config, 900, search_box_bounds),
3521             apps_grid_view()->GetBoundsInScreen().y());
3522   EXPECT_TRUE(apps_grid_view()->GetVisible());
3523   EXPECT_EQ(apps_grid_bounds_in_results_page.y() - 24,
3524             apps_grid_view()->GetBoundsInScreen().y());
3525   EXPECT_EQ(apps_grid_bounds_in_results_page.size(),
3526             apps_grid_view()->GetBoundsInScreen().size());
3527   EXPECT_EQ(search_box_bounds, search_result_page()->GetBoundsInScreen());
3528 }
3529 
3530 // Test a variety of behaviors for home launcher (app list in tablet mode).
3531 class AppListPresenterDelegateHomeLauncherTest
3532     : public AppListPresenterDelegateTest {
3533  public:
AppListPresenterDelegateHomeLauncherTest()3534   AppListPresenterDelegateHomeLauncherTest() {
3535     scoped_feature_list_.InitWithFeatures({features::kEnableBackgroundBlur},
3536                                           {});
3537   }
3538   AppListPresenterDelegateHomeLauncherTest(
3539       const AppListPresenterDelegateHomeLauncherTest&) = delete;
3540   AppListPresenterDelegateHomeLauncherTest& operator=(
3541       const AppListPresenterDelegateHomeLauncherTest&) = delete;
3542   ~AppListPresenterDelegateHomeLauncherTest() override = default;
3543 
3544   // testing::Test:
SetUp()3545   void SetUp() override {
3546     AppListPresenterDelegateTest::SetUp();
3547     GetAppListTestHelper()->WaitUntilIdle();
3548   }
3549 
TapHomeButton(int64_t display_id)3550   void TapHomeButton(int64_t display_id) {
3551     HomeButton* const home_button =
3552         Shell::GetRootWindowControllerWithDisplayId(display_id)
3553             ->shelf()
3554             ->navigation_widget()
3555             ->GetHomeButton();
3556     gfx::Point tap_point = home_button->GetBoundsInScreen().CenterPoint();
3557     GetEventGenerator()->GestureTapDownAndUp(tap_point);
3558     GetAppListTestHelper()->WaitUntilIdle();
3559   }
3560 
3561   // Ensures transition to home screen in tablet mode (where home button is not
3562   // always shown).
GoHome()3563   void GoHome() {
3564     const int64_t primary_display_id = GetPrimaryDisplay().id();
3565     // If home button is not expected to be shown, use
3566     // HomeScreenController::GoHome() directly, otherwise tap on the primary
3567     // screen home button.
3568     if (!Shell::Get()->shelf_config()->shelf_controls_shown()) {
3569       Shell::Get()->home_screen_controller()->GoHome(primary_display_id);
3570       return;
3571     }
3572     TapHomeButton(primary_display_id);
3573   }
3574 
split_view_controller()3575   SplitViewController* split_view_controller() {
3576     return SplitViewController::Get(Shell::GetPrimaryRootWindow());
3577   }
3578 
3579  private:
3580   base::test::ScopedFeatureList scoped_feature_list_;
3581 };
3582 
3583 // Verifies that mouse dragging AppListView is enabled.
TEST_P(AppListPresenterDelegateHomeLauncherTest,MouseDragAppList)3584 TEST_P(AppListPresenterDelegateHomeLauncherTest, MouseDragAppList) {
3585   std::unique_ptr<AppListItem> item(new AppListItem("fake id"));
3586   Shell::Get()->app_list_controller()->GetModel()->AddItem(std::move(item));
3587 
3588   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3589   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3590 
3591   // Drag AppListView upward by mouse. Before moving the mouse, AppsGridView
3592   // should be invisible.
3593   const gfx::Point start_point = GetAppListView()->GetBoundsInScreen().origin();
3594   ui::test::EventGenerator* generator = GetEventGenerator();
3595   generator->MoveMouseTo(start_point);
3596   generator->PressLeftButton();
3597   AppsGridView* apps_grid_view = GetAppListView()
3598                                      ->app_list_main_view()
3599                                      ->contents_view()
3600                                      ->apps_container_view()
3601                                      ->apps_grid_view();
3602   EXPECT_FALSE(apps_grid_view->GetVisible());
3603 
3604   // Verifies that the AppListView state after mouse drag should be
3605   // FullscreenAllApps.
3606   generator->MoveMouseBy(0, -start_point.y());
3607   generator->ReleaseLeftButton();
3608   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
3609   EXPECT_TRUE(apps_grid_view->GetVisible());
3610 }
3611 
3612 // Verifies that mouse dragging AppListView creates layers, causes to change the
3613 // opacity, and destroys the layers when done.
TEST_P(AppListPresenterDelegateHomeLauncherTest,MouseDragAppListItemOpacity)3614 TEST_P(AppListPresenterDelegateHomeLauncherTest, MouseDragAppListItemOpacity) {
3615   const int items_in_page = AppListConfig::instance().preferred_cols() *
3616                             AppListConfig::instance().preferred_rows();
3617   for (int i = 0; i < items_in_page; ++i) {
3618     std::unique_ptr<AppListItem> item(
3619         new AppListItem(base::StringPrintf("fake id %d", i)));
3620     Shell::Get()->app_list_controller()->GetModel()->AddItem(std::move(item));
3621   }
3622 
3623   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3624   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3625 
3626   // Drag AppListView by mouse. Before moving the mouse, each AppListItem
3627   // doesn't have its own layer.
3628   const gfx::Point start_point = GetAppListView()->GetBoundsInScreen().origin();
3629   ui::test::EventGenerator* generator = GetEventGenerator();
3630   generator->MoveMouseTo(start_point);
3631   generator->PressLeftButton();
3632   AppsGridView* apps_grid_view = GetAppListView()
3633                                      ->app_list_main_view()
3634                                      ->contents_view()
3635                                      ->apps_container_view()
3636                                      ->apps_grid_view();
3637   // No items have layer.
3638   for (int i = 0; i < items_in_page; ++i) {
3639     views::View* item_view = apps_grid_view->view_model()->view_at(i);
3640     EXPECT_FALSE(item_view->layer()) << "at " << i;
3641   }
3642 
3643   // Drags the mouse a bit above (twice as shelf's height). This should show the
3644   // item vaguely.
3645   const int shelf_height =
3646       GetPrimaryShelf()->GetShelfViewForTesting()->height();
3647   generator->MoveMouseBy(0, -shelf_height * 2);
3648   // All of the item should have the layer at this point.
3649   for (int i = 0; i < items_in_page; ++i) {
3650     views::View* item_view = apps_grid_view->view_model()->view_at(i);
3651     EXPECT_TRUE(item_view->layer()) << "at " << i;
3652     EXPECT_LE(0.f, item_view->layer()->opacity()) << "at " << i;
3653     EXPECT_GE(1.f, item_view->layer()->opacity()) << "at " << i;
3654   }
3655 
3656   // Moves the mouse to the top edge of the screen; now all app-list items are
3657   // fully visible, but stays to keep layer. The opacity should be almost 1.0.
3658   generator->MoveMouseTo(start_point.x(), 0);
3659   for (int i = 0; i < items_in_page; ++i) {
3660     views::View* item_view = apps_grid_view->view_model()->view_at(i);
3661     EXPECT_TRUE(item_view->layer()) << "at " << i;
3662     EXPECT_LE(0.f, item_view->layer()->opacity()) << "at " << i;
3663     EXPECT_GE(1.f, item_view->layer()->opacity()) << "at " << i;
3664   }
3665 
3666   // Finishes the drag. It should destruct the layer.
3667   generator->ReleaseLeftButton();
3668   for (int i = 0; i < items_in_page; ++i) {
3669     views::View* item_view = apps_grid_view->view_model()->view_at(i);
3670     EXPECT_FALSE(item_view->layer()) << "at " << i;
3671   }
3672 }
3673 
3674 // Tests that ending of the mouse dragging of app-list destroys the layers for
3675 // the items which are in the second page. See https://crbug.com/990529.
TEST_P(AppListPresenterDelegateHomeLauncherTest,LayerOnSecondPage)3676 TEST_P(AppListPresenterDelegateHomeLauncherTest, LayerOnSecondPage) {
3677   const int items_in_page = AppListConfig::instance().preferred_cols() *
3678                             AppListConfig::instance().preferred_rows();
3679   AppListModel* model = Shell::Get()->app_list_controller()->GetModel();
3680   for (int i = 0; i < items_in_page; ++i) {
3681     std::unique_ptr<AppListItem> item(
3682         new AppListItem(base::StringPrintf("fake id %02d", i)));
3683     model->AddItem(std::move(item));
3684   }
3685 
3686   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3687   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3688 
3689   const gfx::Point start_point = GetAppListView()->GetBoundsInScreen().origin();
3690   ui::test::EventGenerator* generator = GetEventGenerator();
3691   generator->MoveMouseTo(start_point);
3692   generator->PressLeftButton();
3693   AppsGridView* apps_grid_view = GetAppListView()
3694                                      ->app_list_main_view()
3695                                      ->contents_view()
3696                                      ->apps_container_view()
3697                                      ->apps_grid_view();
3698 
3699   // Drags the mouse a bit above (twice as shelf's height). This should show the
3700   // item vaguely.
3701   const int shelf_height =
3702       GetPrimaryShelf()->GetShelfViewForTesting()->height();
3703   generator->MoveMouseBy(0, -shelf_height * 2);
3704   // All of the item should have the layer at this point.
3705   for (int i = 0; i < items_in_page; ++i) {
3706     views::View* item_view = apps_grid_view->view_model()->view_at(i);
3707     EXPECT_TRUE(item_view->layer()) << "at " << i;
3708     EXPECT_LE(0.f, item_view->layer()->opacity()) << "at " << i;
3709     EXPECT_GE(1.f, item_view->layer()->opacity()) << "at " << i;
3710   }
3711 
3712   // Add items at the front of the items.
3713   const int additional_items = 10;
3714   syncer::StringOrdinal prev_position =
3715       model->top_level_item_list()->item_at(0)->position();
3716   for (int i = 0; i < additional_items; ++i) {
3717     std::unique_ptr<AppListItem> item(
3718         new AppListItem(base::StringPrintf("fake id %02d", i + items_in_page)));
3719     // Update the position so that the item is added at the front of the list.
3720     auto metadata = item->CloneMetadata();
3721     metadata->position = prev_position.CreateBefore();
3722     prev_position = metadata->position;
3723     item->SetMetadata(std::move(metadata));
3724     model->AddItem(std::move(item));
3725   }
3726 
3727   generator->MoveMouseBy(0, -1);
3728 
3729   // At this point, some items move out from the first page.
3730   EXPECT_LT(1, apps_grid_view->pagination_model()->total_pages());
3731 
3732   // The items on the first page should have layers.
3733   for (int i = 0; i < items_in_page; ++i) {
3734     views::View* item_view = apps_grid_view->view_model()->view_at(i);
3735     EXPECT_TRUE(item_view->layer()) << "at " << i;
3736     EXPECT_LE(0.f, item_view->layer()->opacity()) << "at " << i;
3737     EXPECT_GE(1.f, item_view->layer()->opacity()) << "at " << i;
3738   }
3739 
3740   // Drag to the top of the screen and finish the drag. It should destroy all
3741   // of the layers, including items on the second page.
3742   generator->MoveMouseTo(start_point.x(), 0);
3743   generator->ReleaseLeftButton();
3744   for (int i = 0; i < apps_grid_view->view_model()->view_size(); ++i) {
3745     views::View* item_view = apps_grid_view->view_model()->view_at(i);
3746     EXPECT_FALSE(item_view->layer()) << "at " << i;
3747   }
3748 }
3749 
3750 // Tests that the app list is shown automatically when the tablet mode is on.
3751 // The app list is dismissed when the tablet mode is off.
TEST_P(AppListPresenterDelegateHomeLauncherTest,ShowAppListForTabletMode)3752 TEST_P(AppListPresenterDelegateHomeLauncherTest, ShowAppListForTabletMode) {
3753   GetAppListTestHelper()->CheckVisibility(false);
3754 
3755   // Turns on tablet mode.
3756   EnableTabletMode(true);
3757   GetAppListTestHelper()->CheckVisibility(true);
3758 
3759   // Turns off tablet mode.
3760   EnableTabletMode(false);
3761   GetAppListTestHelper()->CheckVisibility(false);
3762 }
3763 
3764 // Tests that the app list window's parent is changed after entering tablet
3765 // mode.
TEST_P(AppListPresenterDelegateHomeLauncherTest,ParentWindowContainer)3766 TEST_P(AppListPresenterDelegateHomeLauncherTest, ParentWindowContainer) {
3767   // Show app list in non-tablet mode. The window container should be
3768   // kShellWindowId_AppListContainer.
3769   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3770   aura::Window* window = GetAppListView()->GetWidget()->GetNativeWindow();
3771   aura::Window* root_window = window->GetRootWindow();
3772   EXPECT_TRUE(root_window->GetChildById(kShellWindowId_AppListContainer)
3773                   ->Contains(window));
3774 
3775   // Turn on tablet mode. The window container should be
3776   // kShellWindowId_HomeScreenContainer.
3777   EnableTabletMode(true);
3778   EXPECT_TRUE(root_window->GetChildById(kShellWindowId_HomeScreenContainer)
3779                   ->Contains(window));
3780 }
3781 
3782 // Tests that the background opacity change for app list.
TEST_P(AppListPresenterDelegateHomeLauncherTest,BackgroundOpacity)3783 TEST_P(AppListPresenterDelegateHomeLauncherTest, BackgroundOpacity) {
3784   // Show app list in non-tablet mode. The background sheild opacity should be
3785   // 70%.
3786   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3787 
3788   // The opacity should be set on the color, not the layer. Setting opacity on
3789   // the layer will change the opacity of the blur effect, which is not desired.
3790   const U8CPU clamshell_background_opacity = static_cast<U8CPU>(255 * 0.8);
3791   EXPECT_EQ(
3792       SkColorSetA(AppListColorProvider::Get()->GetAppListBackgroundColor(),
3793                   clamshell_background_opacity),
3794       GetAppListView()->GetAppListBackgroundShieldColorForTest());
3795   EXPECT_EQ(1, GetAppListView()
3796                    ->GetAppListBackgroundShieldForTest()
3797                    ->layer()
3798                    ->opacity());
3799 
3800   // Turn on tablet mode. The background shield should be transparent.
3801   EnableTabletMode(true);
3802 
3803   const U8CPU tablet_background_opacity = static_cast<U8CPU>(0);
3804   EXPECT_EQ(
3805       SkColorSetA(AppListColorProvider::Get()->GetAppListBackgroundColor(),
3806                   tablet_background_opacity),
3807       GetAppListView()->GetAppListBackgroundShieldColorForTest());
3808   EXPECT_EQ(1, GetAppListView()
3809                    ->GetAppListBackgroundShieldForTest()
3810                    ->layer()
3811                    ->opacity());
3812 }
3813 
3814 // Tests that the background blur which is present in clamshell mode does not
3815 // show in tablet mode.
TEST_P(AppListPresenterDelegateHomeLauncherTest,BackgroundBlur)3816 TEST_P(AppListPresenterDelegateHomeLauncherTest, BackgroundBlur) {
3817   // Show app list in non-tablet mode. The background blur should be enabled.
3818   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3819   EXPECT_GT(GetAppListView()
3820                 ->GetAppListBackgroundShieldForTest()
3821                 ->layer()
3822                 ->background_blur(),
3823             0.0f);
3824 
3825   // Turn on tablet mode. The background blur should be disabled.
3826   EnableTabletMode(true);
3827   EXPECT_EQ(0.0f, GetAppListView()
3828                       ->GetAppListBackgroundShieldForTest()
3829                       ->layer()
3830                       ->background_blur());
3831 }
3832 
3833 // Tests that tapping or clicking on background cannot dismiss the app list.
TEST_P(AppListPresenterDelegateHomeLauncherTest,TapOrClickToDismiss)3834 TEST_P(AppListPresenterDelegateHomeLauncherTest, TapOrClickToDismiss) {
3835   // Show app list in non-tablet mode. Click outside search box.
3836   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3837   GetAppListTestHelper()->CheckVisibility(true);
3838   ui::test::EventGenerator* generator = GetEventGenerator();
3839   generator->MoveMouseTo(GetPointOutsideSearchbox());
3840   generator->ClickLeftButton();
3841   GetAppListTestHelper()->WaitUntilIdle();
3842   GetAppListTestHelper()->CheckVisibility(false);
3843 
3844   // Show app list in non-tablet mode. Tap outside search box.
3845   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3846   GetAppListTestHelper()->CheckVisibility(true);
3847   generator->GestureTapDownAndUp(GetPointOutsideSearchbox());
3848   GetAppListTestHelper()->WaitUntilIdle();
3849   GetAppListTestHelper()->CheckVisibility(false);
3850 
3851   // Show app list in tablet mode. Click outside search box.
3852   EnableTabletMode(true);
3853   GetAppListTestHelper()->CheckVisibility(true);
3854   generator->MoveMouseTo(GetPointOutsideSearchbox());
3855   generator->PressLeftButton();
3856   GetAppListTestHelper()->WaitUntilIdle();
3857   GetAppListTestHelper()->CheckVisibility(true);
3858 
3859   // Tap outside search box.
3860   generator->GestureTapDownAndUp(GetPointOutsideSearchbox());
3861   GetAppListTestHelper()->WaitUntilIdle();
3862   GetAppListTestHelper()->CheckVisibility(true);
3863 }
3864 
3865 // Tests that accelerator Escape, Broswer back and Search key cannot dismiss the
3866 // appt list.
TEST_P(AppListPresenterDelegateHomeLauncherTest,PressAcceleratorToDismiss)3867 TEST_P(AppListPresenterDelegateHomeLauncherTest, PressAcceleratorToDismiss) {
3868   // Show app list in non-tablet mode. Press Escape key.
3869   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3870   GetAppListTestHelper()->CheckVisibility(true);
3871   ui::test::EventGenerator* generator = GetEventGenerator();
3872   generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
3873   GetAppListTestHelper()->WaitUntilIdle();
3874   GetAppListTestHelper()->CheckVisibility(false);
3875 
3876   // Show app list in non-tablet mode. Press Browser back key.
3877   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3878   GetAppListTestHelper()->CheckVisibility(true);
3879   generator->PressKey(ui::KeyboardCode::VKEY_BROWSER_BACK, 0);
3880   GetAppListTestHelper()->WaitUntilIdle();
3881   GetAppListTestHelper()->CheckVisibility(false);
3882 
3883   // Show app list in non-tablet mode. Press search key.
3884   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3885   GetAppListTestHelper()->CheckVisibility(true);
3886   generator->PressKey(ui::KeyboardCode::VKEY_BROWSER_SEARCH, 0);
3887   GetAppListTestHelper()->WaitUntilIdle();
3888   GetAppListTestHelper()->CheckVisibility(false);
3889 
3890   // Show app list in tablet mode. Press Escape key.
3891   EnableTabletMode(true);
3892   GetAppListTestHelper()->CheckVisibility(true);
3893   generator->PressKey(ui::KeyboardCode::VKEY_ESCAPE, 0);
3894   GetAppListTestHelper()->WaitUntilIdle();
3895   GetAppListTestHelper()->CheckVisibility(true);
3896 
3897   // Press Browser back key.
3898   generator->PressKey(ui::KeyboardCode::VKEY_BROWSER_BACK, 0);
3899   GetAppListTestHelper()->WaitUntilIdle();
3900   GetAppListTestHelper()->CheckVisibility(true);
3901 
3902   // Press search key.
3903   generator->PressKey(ui::KeyboardCode::VKEY_BROWSER_SEARCH, 0);
3904   GetAppListTestHelper()->WaitUntilIdle();
3905   GetAppListTestHelper()->CheckVisibility(true);
3906 }
3907 
3908 // Tests that moving focus outside app list window can dismiss it.
TEST_P(AppListPresenterDelegateHomeLauncherTest,FocusOutToDismiss)3909 TEST_P(AppListPresenterDelegateHomeLauncherTest, FocusOutToDismiss) {
3910   // Show app list in non-tablet mode. Move focus to another window.
3911   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3912   GetAppListTestHelper()->CheckVisibility(true);
3913   std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
3914   wm::ActivateWindow(window.get());
3915   GetAppListTestHelper()->WaitUntilIdle();
3916   GetAppListTestHelper()->CheckVisibility(false);
3917 
3918   // Go to tablet mode with a focused window, the AppList should not be visible.
3919   EnableTabletMode(true);
3920   GetAppListTestHelper()->WaitUntilIdle();
3921   GetAppListTestHelper()->CheckVisibility(false);
3922 
3923   // Refocusing the already focused window should change nothing.
3924   wm::ActivateWindow(window.get());
3925 
3926   GetAppListTestHelper()->WaitUntilIdle();
3927   GetAppListTestHelper()->CheckVisibility(false);
3928 
3929   // Minimizing the focused window with no remaining windows should result in a
3930   // shown applist.
3931   window->SetProperty(aura::client::kShowStateKey, ui::SHOW_STATE_MINIMIZED);
3932 
3933   GetAppListTestHelper()->WaitUntilIdle();
3934   GetAppListTestHelper()->CheckVisibility(true);
3935 }
3936 
3937 // Tests that the gesture-scroll cannot dismiss the app list.
TEST_P(AppListPresenterDelegateHomeLauncherTest,GestureScrollToDismiss)3938 TEST_P(AppListPresenterDelegateHomeLauncherTest, GestureScrollToDismiss) {
3939   // Show app list in non-tablet mode. Fling down.
3940   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3941   GetAppListTestHelper()->CheckVisibility(true);
3942   FlingUpOrDown(GetEventGenerator(), GetAppListView(), false /* up */);
3943   GetAppListTestHelper()->WaitUntilIdle();
3944   GetAppListTestHelper()->CheckVisibility(false);
3945 
3946   // Show app list in tablet mode. Fling down.
3947   EnableTabletMode(true);
3948   GetAppListTestHelper()->CheckVisibility(true);
3949   FlingUpOrDown(GetEventGenerator(), GetAppListView(), false /* up */);
3950   GetAppListTestHelper()->WaitUntilIdle();
3951   GetAppListTestHelper()->CheckVisibility(true);
3952 }
3953 
3954 // Tests that the mouse-scroll cannot dismiss the app list.
TEST_P(AppListPresenterDelegateHomeLauncherTest,MouseScrollDoesntDismissPeekingLauncher)3955 TEST_P(AppListPresenterDelegateHomeLauncherTest,
3956        MouseScrollDoesntDismissPeekingLauncher) {
3957   // Show app list in non-tablet mode. Mouse-scroll up.
3958   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3959   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3960   GetAppListTestHelper()->CheckVisibility(true);
3961   ui::test::EventGenerator* generator = GetEventGenerator();
3962   generator->MoveMouseTo(GetPointOutsideSearchbox());
3963 
3964   // Scroll up to get fullscreen.
3965   generator->MoveMouseWheel(0, 1);
3966   GetAppListTestHelper()->WaitUntilIdle();
3967   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
3968   GetAppListTestHelper()->CheckVisibility(true);
3969 
3970   // Reset and show app list in non-tablet mode. Mouse-scroll down.
3971   GetAppListTestHelper()->DismissAndRunLoop();
3972   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3973   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3974   GetAppListTestHelper()->CheckVisibility(true);
3975 
3976   // Scroll down to get fullscreen.
3977   generator->MoveMouseWheel(0, -1);
3978   GetAppListTestHelper()->WaitUntilIdle();
3979   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
3980   GetAppListTestHelper()->CheckVisibility(true);
3981 }
3982 
3983 // Tests that mouse-scroll up at fullscreen will dismiss app list.
TEST_P(AppListPresenterDelegateHomeLauncherTest,MouseScrollToDismissFromFullscreen)3984 TEST_P(AppListPresenterDelegateHomeLauncherTest,
3985        MouseScrollToDismissFromFullscreen) {
3986   // Show app list in non-tablet mode. Mouse-scroll down.
3987   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
3988   GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
3989   ui::test::EventGenerator* generator = GetEventGenerator();
3990   generator->MoveMouseTo(GetPointOutsideSearchbox());
3991 
3992   // Scroll up with mouse wheel to fullscreen.
3993   generator->MoveMouseWheel(0, 1);
3994   GetAppListTestHelper()->WaitUntilIdle();
3995   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
3996   GetAppListTestHelper()->CheckVisibility(true);
3997   generator->MoveMouseTo(GetPointOutsideSearchbox());
3998 
3999   // Scroll up with mouse wheel to close app list.
4000   generator->MoveMouseWheel(0, 1);
4001   GetAppListTestHelper()->WaitUntilIdle();
4002   GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
4003   GetAppListTestHelper()->CheckVisibility(false);
4004 }
4005 
4006 // Test that the AppListView opacity is reset after it is hidden during the
4007 // overview mode animation.
TEST_P(AppListPresenterDelegateHomeLauncherTest,LauncherShowsAfterOverviewMode)4008 TEST_P(AppListPresenterDelegateHomeLauncherTest,
4009        LauncherShowsAfterOverviewMode) {
4010   // Show the AppList in clamshell mode.
4011   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
4012   GetAppListTestHelper()->CheckVisibility(true);
4013 
4014   // Enable overview mode.
4015   OverviewController* overview_controller = Shell::Get()->overview_controller();
4016   overview_controller->StartOverview();
4017 
4018   // Test that the AppListView is transparent.
4019   EXPECT_EQ(0.0f, GetAppListView()->GetWidget()->GetLayer()->opacity());
4020 
4021   // Disable overview mode.
4022   overview_controller->EndOverview();
4023 
4024   // Show the launcher, test that the opacity is restored.
4025   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
4026   GetAppListTestHelper()->CheckVisibility(true);
4027 
4028   EXPECT_EQ(1.0f, GetAppListView()->GetWidget()->GetLayer()->opacity());
4029   EXPECT_TRUE(GetAppListView()->GetWidget()->IsVisible());
4030 }
4031 
4032 // Tests that tapping home button while home screen is visible and showing
4033 // search results moves the home screen to apps container page.
TEST_P(AppListPresenterDelegateHomeLauncherTest,HomeButtonDismissesSearchResults)4034 TEST_P(AppListPresenterDelegateHomeLauncherTest,
4035        HomeButtonDismissesSearchResults) {
4036   // Show app list in tablet mode.
4037   EnableTabletMode(true);
4038   GetAppListTestHelper()->CheckVisibility(true);
4039   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
4040 
4041   // Enable accessibility feature that forces home button to be shown even with
4042   // kHideShelfControlsInTabletMode enabled.
4043   // TODO(https://crbug.com/1050544) Use the a11y feature specific to showing
4044   // navigation buttons in tablet mode once it lands.
4045   Shell::Get()->accessibility_controller()->autoclick().SetEnabled(true);
4046 
4047   // Enter text in the searchbox, the app list should transition to fullscreen
4048   // search.
4049   ui::test::EventGenerator* generator = GetEventGenerator();
4050   generator->PressKey(ui::KeyboardCode::VKEY_0, ui::EF_NONE);
4051   GetAppListTestHelper()->WaitUntilIdle();
4052   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
4053 
4054   // Tap home button - verify that home goes back to showing the apps page.
4055   TapHomeButton(GetPrimaryDisplay().id());
4056 
4057   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
4058 }
4059 
4060 // Tests the app list opacity in overview mode.
TEST_P(AppListPresenterDelegateHomeLauncherTest,OpacityInOverviewMode)4061 TEST_P(AppListPresenterDelegateHomeLauncherTest, OpacityInOverviewMode) {
4062   // Show app list in tablet mode.
4063   EnableTabletMode(true);
4064   GetAppListTestHelper()->CheckVisibility(true);
4065 
4066   // Enable overview mode.
4067   OverviewController* overview_controller = Shell::Get()->overview_controller();
4068   overview_controller->StartOverview();
4069   EXPECT_TRUE(overview_controller->InOverviewSession());
4070   ui::Layer* layer = GetAppListView()->GetWidget()->GetNativeWindow()->layer();
4071   EXPECT_EQ(0.0f, layer->opacity());
4072 
4073   // Disable overview mode.
4074   overview_controller->EndOverview();
4075   EXPECT_FALSE(overview_controller->InOverviewSession());
4076   EXPECT_EQ(1.0f, layer->opacity());
4077 }
4078 
4079 // Tests the app list visibility during wallpaper preview.
TEST_P(AppListPresenterDelegateHomeLauncherTest,VisibilityDuringWallpaperPreview)4080 TEST_P(AppListPresenterDelegateHomeLauncherTest,
4081        VisibilityDuringWallpaperPreview) {
4082   WallpaperControllerTestApi wallpaper_test_api(
4083       Shell::Get()->wallpaper_controller());
4084 
4085   // The app list is hidden in the beginning.
4086   GetAppListTestHelper()->CheckVisibility(false);
4087   // Open wallpaper picker and start preview. Verify the app list remains
4088   // hidden.
4089   wallpaper_test_api.StartWallpaperPreview();
4090   GetAppListTestHelper()->CheckVisibility(false);
4091   // Enable tablet mode. Verify the app list is still hidden because wallpaper
4092   // preview is active.
4093   EnableTabletMode(true);
4094   GetAppListTestHelper()->CheckVisibility(false);
4095   // End preview by confirming the wallpaper. Verify the app list is shown.
4096   wallpaper_test_api.EndWallpaperPreview(true /*confirm_preview_wallpaper=*/);
4097   GetAppListTestHelper()->CheckVisibility(true);
4098 
4099   // Start preview again. Verify the app list is hidden.
4100   wallpaper_test_api.StartWallpaperPreview();
4101   GetAppListTestHelper()->CheckVisibility(false);
4102   // End preview by canceling the wallpaper. Verify the app list is shown.
4103   wallpaper_test_api.EndWallpaperPreview(false /*confirm_preview_wallpaper=*/);
4104   GetAppListTestHelper()->CheckVisibility(true);
4105 
4106   // Start preview again and enable overview mode during the wallpaper preview.
4107   // Verify the app list is hidden.
4108   wallpaper_test_api.StartWallpaperPreview();
4109   EXPECT_FALSE(GetAppListView()->GetWidget()->IsVisible());
4110   OverviewController* overview_controller = Shell::Get()->overview_controller();
4111   overview_controller->StartOverview();
4112   EXPECT_TRUE(overview_controller->InOverviewSession());
4113   GetAppListTestHelper()->CheckVisibility(false);
4114   // Disable overview mode. Verify the app list is still hidden because
4115   // wallpaper preview is still active.
4116   overview_controller->EndOverview();
4117   EXPECT_FALSE(overview_controller->InOverviewSession());
4118   GetAppListTestHelper()->CheckVisibility(false);
4119   // End preview by confirming the wallpaper. Verify the app list is shown.
4120   wallpaper_test_api.EndWallpaperPreview(true /*confirm_preview_wallpaper=*/);
4121   GetAppListTestHelper()->CheckVisibility(true);
4122 }
4123 
4124 // Tests that going home will minimize all windows.
TEST_P(AppListPresenterDelegateHomeLauncherTest,GoingHomeMinimizesAllWindows)4125 TEST_P(AppListPresenterDelegateHomeLauncherTest, GoingHomeMinimizesAllWindows) {
4126   // Show app list in tablet mode. Maximize all windows.
4127   EnableTabletMode(true);
4128   GetAppListTestHelper()->CheckVisibility(true);
4129   std::unique_ptr<aura::Window> window1(CreateTestWindowInShellWithId(0)),
4130       window2(CreateTestWindowInShellWithId(1)),
4131       window3(CreateTestWindowInShellWithId(2));
4132   WindowState *state1 = WindowState::Get(window1.get()),
4133               *state2 = WindowState::Get(window2.get()),
4134               *state3 = WindowState::Get(window3.get());
4135   state1->Maximize();
4136   state2->Maximize();
4137   state3->Maximize();
4138   EXPECT_TRUE(state1->IsMaximized());
4139   EXPECT_TRUE(state2->IsMaximized());
4140   EXPECT_TRUE(state3->IsMaximized());
4141 
4142   // The windows need to be activated for the mru window tracker.
4143   wm::ActivateWindow(window1.get());
4144   wm::ActivateWindow(window2.get());
4145   wm::ActivateWindow(window3.get());
4146   auto ordering =
4147       Shell::Get()->mru_window_tracker()->BuildWindowForCycleList(kActiveDesk);
4148 
4149   GoHome();
4150   EXPECT_TRUE(state1->IsMinimized());
4151   EXPECT_TRUE(state2->IsMinimized());
4152   EXPECT_TRUE(state3->IsMinimized());
4153   GetAppListTestHelper()->CheckVisibility(true);
4154 
4155   // Tests that the window ordering remains the same as before we minimize.
4156   auto new_order =
4157       Shell::Get()->mru_window_tracker()->BuildWindowForCycleList(kActiveDesk);
4158   EXPECT_TRUE(std::equal(ordering.begin(), ordering.end(), new_order.begin()));
4159 }
4160 
4161 // Tests that going home will end split view mode.
TEST_P(AppListPresenterDelegateHomeLauncherTest,GoingHomeEndsSplitViewMode)4162 TEST_P(AppListPresenterDelegateHomeLauncherTest, GoingHomeEndsSplitViewMode) {
4163   // Show app list in tablet mode. Enter split view mode.
4164   EnableTabletMode(true);
4165   GetAppListTestHelper()->CheckVisibility(true);
4166   std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
4167   split_view_controller()->SnapWindow(window.get(), SplitViewController::LEFT);
4168   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
4169 
4170   GoHome();
4171   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
4172   GetAppListTestHelper()->CheckVisibility(true);
4173 }
4174 
4175 // Tests that going home will end overview mode.
TEST_P(AppListPresenterDelegateHomeLauncherTest,GoingHomeEndOverviewMode)4176 TEST_P(AppListPresenterDelegateHomeLauncherTest, GoingHomeEndOverviewMode) {
4177   // Show app list in tablet mode. Enter overview mode.
4178   EnableTabletMode(true);
4179   GetAppListTestHelper()->CheckVisibility(true);
4180   std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
4181   OverviewController* overview_controller = Shell::Get()->overview_controller();
4182   overview_controller->StartOverview();
4183   EXPECT_TRUE(overview_controller->InOverviewSession());
4184 
4185   GoHome();
4186   EXPECT_FALSE(overview_controller->InOverviewSession());
4187   GetAppListTestHelper()->CheckVisibility(true);
4188 }
4189 
4190 // Tests that going home will end overview and split view mode if both are
4191 // active (e.g. one side of the split view contains overview).
TEST_P(AppListPresenterDelegateHomeLauncherTest,GoingHomeEndsSplitViewModeWithOverview)4192 TEST_P(AppListPresenterDelegateHomeLauncherTest,
4193        GoingHomeEndsSplitViewModeWithOverview) {
4194   // Show app list in tablet mode. Enter split view mode.
4195   EnableTabletMode(true);
4196   GetAppListTestHelper()->CheckVisibility(true);
4197 
4198   std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
4199   std::unique_ptr<aura::Window> dummy_window(CreateTestWindowInShellWithId(1));
4200 
4201   OverviewController* overview_controller = Shell::Get()->overview_controller();
4202   overview_controller->StartOverview();
4203   EXPECT_TRUE(overview_controller->InOverviewSession());
4204 
4205   split_view_controller()->SnapWindow(window.get(), SplitViewController::LEFT);
4206   EXPECT_TRUE(split_view_controller()->InSplitViewMode());
4207   EXPECT_TRUE(overview_controller->InOverviewSession());
4208 
4209   GoHome();
4210   EXPECT_FALSE(split_view_controller()->InSplitViewMode());
4211   EXPECT_FALSE(overview_controller->InOverviewSession());
4212 
4213   GetAppListTestHelper()->CheckVisibility(true);
4214 }
4215 
4216 // Tests that the context menu is triggered in the same way as if we are on
4217 // the wallpaper.
TEST_P(AppListPresenterDelegateHomeLauncherTest,WallpaperContextMenu)4218 TEST_P(AppListPresenterDelegateHomeLauncherTest, WallpaperContextMenu) {
4219   // Show app list in tablet mode.
4220   EnableTabletMode(true);
4221   GetAppListTestHelper()->CheckVisibility(true);
4222 
4223   // Long press on the app list to open the context menu.
4224   // TODO(ginko) look into a way to populate an apps grid, then get a point
4225   // between these apps so that clicks/taps between apps can be tested
4226   const gfx::Point onscreen_point(GetPointOutsideSearchbox());
4227   ui::test::EventGenerator* generator = GetEventGenerator();
4228   ui::GestureEvent long_press(
4229       onscreen_point.x(), onscreen_point.y(), 0, base::TimeTicks(),
4230       ui::GestureEventDetails(ui::ET_GESTURE_LONG_PRESS));
4231   generator->Dispatch(&long_press);
4232   GetAppListTestHelper()->WaitUntilIdle();
4233   const aura::Window* root = window_util::GetRootWindowAt(onscreen_point);
4234   const RootWindowController* root_window_controller =
4235       RootWindowController::ForWindow(root);
4236   EXPECT_TRUE(root_window_controller->IsContextMenuShown());
4237 
4238   // Tap down to close the context menu.
4239   ui::GestureEvent tap_down(onscreen_point.x(), onscreen_point.y(), 0,
4240                             base::TimeTicks(),
4241                             ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN));
4242   generator->Dispatch(&tap_down);
4243   GetAppListTestHelper()->WaitUntilIdle();
4244   EXPECT_FALSE(root_window_controller->IsContextMenuShown());
4245 
4246   // Right click to open the context menu.
4247   generator->MoveMouseTo(onscreen_point);
4248   generator->ClickRightButton();
4249   GetAppListTestHelper()->WaitUntilIdle();
4250   EXPECT_TRUE(root_window_controller->IsContextMenuShown());
4251 
4252   // Left click to close the context menu.
4253   generator->MoveMouseTo(onscreen_point);
4254   generator->ClickLeftButton();
4255   GetAppListTestHelper()->WaitUntilIdle();
4256   EXPECT_FALSE(root_window_controller->IsContextMenuShown());
4257 }
4258 
4259 // Tests app list visibility when switching to tablet mode during dragging from
4260 // shelf.
TEST_P(AppListPresenterDelegateHomeLauncherTest,SwitchToTabletModeDuringDraggingFromShelf)4261 TEST_P(AppListPresenterDelegateHomeLauncherTest,
4262        SwitchToTabletModeDuringDraggingFromShelf) {
4263   UpdateDisplay("1080x900");
4264   GetAppListTestHelper()->CheckVisibility(false);
4265 
4266   // Drag from the shelf to show the app list.
4267   ui::test::EventGenerator* generator = GetEventGenerator();
4268   const int x = 540;
4269   const int closed_y = 890;
4270   const int fullscreen_y = 0;
4271   generator->MoveTouch(gfx::Point(x, closed_y));
4272   generator->PressTouch();
4273   generator->MoveTouch(gfx::Point(x, fullscreen_y));
4274   generator->ReleaseTouch();
4275   GetAppListTestHelper()->CheckVisibility(true);
4276 
4277   // Drag to shelf to close app list.
4278   generator->MoveTouch(gfx::Point(x, fullscreen_y));
4279   generator->PressTouch();
4280   generator->MoveTouch(gfx::Point(x, closed_y));
4281   generator->ReleaseTouch();
4282   GetAppListTestHelper()->WaitUntilIdle();
4283   GetAppListTestHelper()->CheckVisibility(false);
4284 
4285   // Drag from the shelf to show the app list.
4286   generator->MoveTouch(gfx::Point(x, closed_y));
4287   generator->PressTouch();
4288   generator->MoveTouch(gfx::Point(x, fullscreen_y));
4289   GetAppListTestHelper()->CheckVisibility(true);
4290 
4291   // Switch to tablet mode.
4292   EnableTabletMode(true);
4293   GetAppListTestHelper()->CheckVisibility(true);
4294 
4295   // Drag to shelf to try to close app list.
4296   generator->MoveTouch(gfx::Point(x, closed_y));
4297   generator->ReleaseTouch();
4298   GetAppListTestHelper()->WaitUntilIdle();
4299   GetAppListTestHelper()->CheckVisibility(true);
4300 }
4301 
4302 // Tests app list visibility when switching to tablet mode during dragging to
4303 // close app list.
TEST_P(AppListPresenterDelegateHomeLauncherTest,SwitchToTabletModeDuringDraggingToClose)4304 TEST_P(AppListPresenterDelegateHomeLauncherTest,
4305        SwitchToTabletModeDuringDraggingToClose) {
4306   UpdateDisplay("1080x900");
4307 
4308   // Open app list.
4309   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
4310   GetAppListTestHelper()->CheckVisibility(true);
4311 
4312   // Drag to shelf to close app list.
4313   ui::test::EventGenerator* generator = GetEventGenerator();
4314   const int x = 540;
4315   const int peeking_height =
4316       900 - AppListConfig::instance().peeking_app_list_height();
4317   const int closed_y = 890;
4318   generator->MoveTouch(gfx::Point(x, peeking_height));
4319   generator->PressTouch();
4320   generator->MoveTouch(gfx::Point(x, closed_y));
4321   generator->ReleaseTouch();
4322   GetAppListTestHelper()->WaitUntilIdle();
4323   GetAppListTestHelper()->CheckVisibility(false);
4324 
4325   // Open app list.
4326   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
4327   GetAppListTestHelper()->CheckVisibility(true);
4328 
4329   // Drag to shelf to close app list, meanwhile switch to tablet mode.
4330   generator->MoveTouch(gfx::Point(x, peeking_height));
4331   generator->PressTouch();
4332   generator->MoveTouch(gfx::Point(x, peeking_height + 10));
4333   EnableTabletMode(true);
4334   generator->MoveTouch(gfx::Point(x, closed_y));
4335   generator->ReleaseTouch();
4336   GetAppListTestHelper()->WaitUntilIdle();
4337   GetAppListTestHelper()->CheckVisibility(true);
4338 }
4339 
4340 // Test backdrop exists for active non-fullscreen window in tablet mode.
TEST_P(AppListPresenterDelegateHomeLauncherTest,BackdropTest)4341 TEST_P(AppListPresenterDelegateHomeLauncherTest, BackdropTest) {
4342   WorkspaceControllerTestApi test_helper(ShellTestApi().workspace_controller());
4343   EnableTabletMode(true);
4344   GetAppListTestHelper()->CheckVisibility(true);
4345   EXPECT_FALSE(test_helper.GetBackdropWindow());
4346 
4347   std::unique_ptr<aura::Window> non_fullscreen_window(
4348       CreateTestWindow(gfx::Rect(0, 0, 100, 100)));
4349   non_fullscreen_window->Show();
4350   GetAppListTestHelper()->CheckVisibility(false);
4351   EXPECT_TRUE(test_helper.GetBackdropWindow());
4352 }
4353 
4354 // Tests that app list is not active when switching to tablet mode if an active
4355 // window exists.
TEST_P(AppListPresenterDelegateHomeLauncherTest,NotActivateAppListWindowWhenActiveWindowExists)4356 TEST_P(AppListPresenterDelegateHomeLauncherTest,
4357        NotActivateAppListWindowWhenActiveWindowExists) {
4358   // No window is active.
4359   EXPECT_EQ(nullptr, window_util::GetActiveWindow());
4360 
4361   // Show app list in tablet mode. It should become active.
4362   EnableTabletMode(true);
4363   GetAppListTestHelper()->CheckVisibility(true);
4364   EXPECT_EQ(GetAppListView()->GetWidget()->GetNativeWindow(),
4365             window_util::GetActiveWindow());
4366 
4367   // End tablet mode.
4368   EnableTabletMode(false);
4369   GetAppListTestHelper()->CheckVisibility(false);
4370   EXPECT_EQ(nullptr, window_util::GetActiveWindow());
4371 
4372   // Activate a window.
4373   std::unique_ptr<aura::Window> window(CreateTestWindowInShellWithId(0));
4374   WindowState::Get(window.get())->Activate();
4375   EXPECT_EQ(window.get(), window_util::GetActiveWindow());
4376 
4377   // Show app list in tablet mode. It should not be active.
4378   EnableTabletMode(true);
4379   GetAppListTestHelper()->CheckVisibility(false);
4380   EXPECT_EQ(window.get(), window_util::GetActiveWindow());
4381 }
4382 
4383 // Tests that involve the virtual keyboard.
4384 class AppListPresenterDelegateVirtualKeyboardTest
4385     : public AppListPresenterDelegateTest {
4386  public:
4387   AppListPresenterDelegateVirtualKeyboardTest() = default;
4388   ~AppListPresenterDelegateVirtualKeyboardTest() override = default;
4389 
4390   // AppListPresenterDelegateTest:
SetUp()4391   void SetUp() override {
4392     base::CommandLine::ForCurrentProcess()->AppendSwitch(
4393         keyboard::switches::kEnableVirtualKeyboard);
4394     AppListPresenterDelegateTest::SetUp();
4395   }
4396 
4397   // Performs mouse click or tap gesture on the provided point, depending on
4398   // whether the test is parameterized to use mouse clicks or tap gestures.
ClickOrTap(const gfx::Point & point)4399   void ClickOrTap(const gfx::Point& point) {
4400     if (GetParam())
4401       ClickMouseAt(point);
4402     else
4403       GetEventGenerator()->GestureTapAt(point);
4404   }
4405 };
4406 
4407 // Instantiate the Boolean which is used to toggle mouse and touch events in
4408 // the parameterized tests.
4409 INSTANTIATE_TEST_SUITE_P(All,
4410                          AppListPresenterDelegateVirtualKeyboardTest,
4411                          testing::Bool());
4412 
4413 // Tests that tapping or clicking the body of the applist with an active virtual
4414 // keyboard when there exists text in the searchbox results in the virtual
4415 // keyboard closing with no side effects.
TEST_P(AppListPresenterDelegateVirtualKeyboardTest,TapAppListWithVirtualKeyboardDismissesVirtualKeyboardWithSearchText)4416 TEST_P(AppListPresenterDelegateVirtualKeyboardTest,
4417        TapAppListWithVirtualKeyboardDismissesVirtualKeyboardWithSearchText) {
4418   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
4419   EnableTabletMode(true);
4420 
4421   // Tap to activate the searchbox.
4422   ClickOrTap(GetPointInsideSearchbox());
4423 
4424   // Enter some text in the searchbox, the applist should transition to
4425   // fullscreen search.
4426   GetEventGenerator()->PressKey(ui::KeyboardCode::VKEY_0, 0);
4427   GetAppListTestHelper()->WaitUntilIdle();
4428   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
4429 
4430   // Manually show the virtual keyboard.
4431   auto* const keyboard_controller = keyboard::KeyboardUIController::Get();
4432   keyboard_controller->ShowKeyboard(true);
4433   ASSERT_TRUE(keyboard::WaitUntilShown());
4434 
4435   // Tap or click outside the searchbox, the virtual keyboard should hide.
4436   ClickOrTap(GetPointOutsideSearchbox());
4437   EXPECT_FALSE(keyboard_controller->IsKeyboardVisible());
4438 
4439   // The searchbox should still be active and the AppListView should still be in
4440   // FULLSCREEN_SEARCH.
4441   GetAppListTestHelper()->WaitUntilIdle();
4442   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
4443   EXPECT_TRUE(GetAppListView()->search_box_view()->is_search_box_active());
4444 
4445   // Tap or click the body of the AppList again, the searchbox should deactivate
4446   // and the applist should be in FULLSCREEN_ALL_APPS.
4447   ClickOrTap(GetPointOutsideSearchbox());
4448   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
4449   EXPECT_FALSE(GetAppListView()->search_box_view()->is_search_box_active());
4450 }
4451 
4452 // Tests that tapping or clicking the body of the applist with an active virtual
4453 // keyboard when there is no text in the searchbox results in both the virtual
4454 // keyboard and searchbox closing with no side effects.
TEST_P(AppListPresenterDelegateVirtualKeyboardTest,TapAppListWithVirtualKeyboardDismissesVirtualKeyboardWithoutSearchText)4455 TEST_P(AppListPresenterDelegateVirtualKeyboardTest,
4456        TapAppListWithVirtualKeyboardDismissesVirtualKeyboardWithoutSearchText) {
4457   GetAppListTestHelper()->ShowAndRunLoop(GetPrimaryDisplayId());
4458   EnableTabletMode(true);
4459 
4460   // Tap to activate the searchbox.
4461   ClickOrTap(GetPointInsideSearchbox());
4462   GetAppListTestHelper()->WaitUntilIdle();
4463   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenSearch);
4464 
4465   // Manually show the virtual keyboard.
4466   auto* const keyboard_controller = keyboard::KeyboardUIController::Get();
4467   keyboard_controller->ShowKeyboard(true);
4468   ASSERT_TRUE(keyboard::WaitUntilShown());
4469 
4470   // Tap or click outside the searchbox, the virtual keyboard should hide and
4471   // the searchbox should be inactive when there is no text in the searchbox.
4472   ClickOrTap(GetPointOutsideSearchbox());
4473   GetAppListTestHelper()->WaitUntilIdle();
4474   GetAppListTestHelper()->CheckState(AppListViewState::kFullscreenAllApps);
4475   EXPECT_FALSE(keyboard_controller->IsKeyboardVisible());
4476   EXPECT_FALSE(GetAppListView()->search_box_view()->is_search_box_active());
4477 }
4478 
TEST_P(AppListPresenterDelegateHomeLauncherTest,TapHomeButtonOnExternalDisplay)4479 TEST_P(AppListPresenterDelegateHomeLauncherTest,
4480        TapHomeButtonOnExternalDisplay) {
4481   UpdateDisplay("800x600,1000x768");
4482 
4483   TapHomeButton(GetSecondaryDisplay().id());
4484   {
4485     SCOPED_TRACE("1st tap");
4486     GetAppListTestHelper()->CheckVisibility(true);
4487     GetAppListTestHelper()->CheckState(AppListViewState::kPeeking);
4488   }
4489 
4490   TapHomeButton(GetSecondaryDisplay().id());
4491   {
4492     SCOPED_TRACE("2nd tap");
4493     GetAppListTestHelper()->CheckVisibility(false);
4494     GetAppListTestHelper()->CheckState(AppListViewState::kClosed);
4495   }
4496 }
4497 
4498 }  // namespace ash
4499