1// Copyright 2014 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "chrome/browser/ui/app_list/app_list_service_views.h" 6 7#include "base/path_service.h" 8#include "base/run_loop.h" 9#include "chrome/browser/extensions/extension_browsertest.h" 10#include "chrome/browser/lifetime/application_lifetime.h" 11#include "chrome/browser/ui/app_list/app_list_controller_delegate.h" 12#include "chrome/browser/ui/app_list/test/chrome_app_list_test_support.h" 13#include "chrome/browser/ui/browser.h" 14#include "chrome/browser/ui/browser_commands.h" 15#include "chrome/common/chrome_paths.h" 16#include "chrome/test/base/in_process_browser_test.h" 17#include "content/public/browser/notification_service.h" 18#include "content/public/test/test_utils.h" 19#include "ui/app_list/app_list_switches.h" 20#include "ui/app_list/views/app_list_view.h" 21#include "ui/events/test/event_generator.h" 22#include "ui/views/widget/widget.h" 23 24#if defined(OS_CHROMEOS) 25#include "ash/shell.h" 26#include "ash/test/app_list_controller_test_api.h" 27#endif 28 29namespace { 30 31app_list::AppListView* GetAppListView(AppListService* service) { 32#if defined(OS_CHROMEOS) 33 return ash::test::AppListControllerTestApi(ash::Shell::GetInstance()).view(); 34#else 35 return static_cast<AppListServiceViews*>(service)->shower().app_list(); 36#endif 37} 38 39} // namespace 40 41namespace test { 42 43// Allow access to private variables of the AppListView for testing. 44class AppListViewTestApi { 45 public: 46 explicit AppListViewTestApi(app_list::AppListView* view) : view_(view) {} 47 virtual ~AppListViewTestApi() {} 48 49 bool is_overlay_visible() { 50 DCHECK(view_->overlay_view_); 51 return view_->overlay_view_->visible(); 52 } 53 54 private: 55 app_list::AppListView* view_; 56 57 DISALLOW_COPY_AND_ASSIGN(AppListViewTestApi); 58}; 59 60} // namespace test 61 62// Browser Test for AppListService on Views platforms. 63typedef InProcessBrowserTest AppListServiceViewsBrowserTest; 64 65// Test closing the native app list window as if via a request from the OS. 66IN_PROC_BROWSER_TEST_F(AppListServiceViewsBrowserTest, NativeClose) { 67 AppListService* service = test::GetAppListService(); 68 EXPECT_FALSE(service->GetAppListWindow()); 69 70 // Since the profile is loaded, this will create a view immediately. This is 71 // important, because anything asynchronous would need an interactive_uitest 72 // due to the possibility of the app list being dismissed, and 73 // AppListService::GetAppListWindow returning NULL. 74 service->ShowForProfile(browser()->profile()); 75 gfx::NativeWindow window = service->GetAppListWindow(); 76 EXPECT_TRUE(window); 77 78 views::Widget* widget = views::Widget::GetWidgetForNativeWindow(window); 79 EXPECT_TRUE(widget); 80 widget->Close(); 81 82 // Close is asynchronous (dismiss is not) so sink the message queue. 83 base::RunLoop().RunUntilIdle(); 84 EXPECT_FALSE(service->GetAppListWindow()); 85 86 // Show again to get some code coverage for possibly stale pointers. 87 service->ShowForProfile(browser()->profile()); 88 EXPECT_TRUE(service->GetAppListWindow()); 89 service->DismissAppList(); // Note: in Ash, this will invalidate the window. 90 91 // Note: no need to sink message queue. 92 EXPECT_FALSE(service->GetAppListWindow()); 93} 94 95// Dismiss the app list via an accelerator when it is the only thing keeping 96// Chrome alive and expect everything to clean up properly. This is a regression 97// test for http://crbug.com/395937. 98IN_PROC_BROWSER_TEST_F(AppListServiceViewsBrowserTest, AcceleratorClose) { 99 AppListService* service = test::GetAppListService(); 100 service->ShowForProfile(browser()->profile()); 101 EXPECT_TRUE(service->GetAppListWindow()); 102 103 content::WindowedNotificationObserver close_observer( 104 chrome::NOTIFICATION_BROWSER_CLOSED, content::Source<Browser>(browser())); 105 chrome::CloseWindow(browser()); 106 close_observer.Wait(); 107 108 ui::test::EventGenerator generator(service->GetAppListWindow()); 109 generator.PressKey(ui::VKEY_ESCAPE, 0); 110 111#if !defined(OS_CHROMEOS) 112 EXPECT_TRUE(chrome::WillKeepAlive()); 113#endif 114 115 base::RunLoop().RunUntilIdle(); 116 117#if !defined(OS_CHROMEOS) 118 EXPECT_FALSE(chrome::WillKeepAlive()); 119#endif 120 EXPECT_FALSE(service->GetAppListWindow()); 121} 122 123// Browser Test for AppListController that ensures the App Info dialog opens 124// correctly. 125typedef ExtensionBrowserTest AppListControllerAppInfoDialogBrowserTest; 126 127// Test the DoShowAppInfoFlow function of the controller delegate. 128// flaky: http://crbug.com/378251 129IN_PROC_BROWSER_TEST_F(AppListControllerAppInfoDialogBrowserTest, 130 DISABLED_DoShowAppInfoFlow) { 131 // Install an extension to open the dialog for. 132 base::FilePath test_extension_path; 133 ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &test_extension_path)); 134 test_extension_path = test_extension_path.AppendASCII("extensions") 135 .AppendASCII("platform_apps") 136 .AppendASCII("minimal"); 137 const extensions::Extension* extension = InstallExtension( 138 test_extension_path, 1 /* expected_change: new install */); 139 ASSERT_TRUE(extension); 140 141 // Open the app list window. 142 AppListService* service = test::GetAppListService(); 143 EXPECT_FALSE(service->GetAppListWindow()); 144 145 service->ShowForProfile(browser()->profile()); 146 app_list::AppListView* app_list_view = GetAppListView(service); 147 ASSERT_TRUE(app_list_view); 148 gfx::NativeView native_view = app_list_view->GetWidget()->GetNativeView(); 149 ASSERT_TRUE(native_view); 150 151 test::AppListViewTestApi test_api(app_list_view); 152 153 // Open the app info dialog. 154 views::Widget::Widgets owned_widgets; 155 views::Widget::GetAllOwnedWidgets(native_view, &owned_widgets); 156 EXPECT_EQ(0U, owned_widgets.size()); 157 EXPECT_FALSE(test_api.is_overlay_visible()); 158 159 AppListControllerDelegate* controller = service->GetControllerDelegate(); 160 ASSERT_TRUE(controller); 161 EXPECT_TRUE(controller->GetAppListWindow()); 162 controller->DoShowAppInfoFlow(browser()->profile(), extension->id()); 163 164 owned_widgets.clear(); 165 views::Widget::GetAllOwnedWidgets(native_view, &owned_widgets); 166 EXPECT_EQ(1U, owned_widgets.size()); 167 EXPECT_TRUE(test_api.is_overlay_visible()); 168 169 // Close the app info dialog. 170 views::Widget* app_info_dialog = *owned_widgets.begin(); 171 app_info_dialog->CloseNow(); 172 173 owned_widgets.clear(); 174 views::Widget::GetAllOwnedWidgets(native_view, &owned_widgets); 175 EXPECT_EQ(0U, owned_widgets.size()); 176 EXPECT_FALSE(test_api.is_overlay_visible()); 177} 178