| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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/panels/base_panel_browser_test.h" | |
| 6 | |
| 7 #include <string.h> | |
| 8 | |
| 9 #include "base/bind.h" | |
| 10 #include "base/command_line.h" | |
| 11 #include "base/macros.h" | |
| 12 #include "base/memory/weak_ptr.h" | |
| 13 #include "base/message_loop/message_loop.h" | |
| 14 #include "base/strings/string_number_conversions.h" | |
| 15 #include "build/build_config.h" | |
| 16 #include "chrome/browser/chrome_notification_types.h" | |
| 17 #include "chrome/browser/extensions/extension_service.h" | |
| 18 #include "chrome/browser/profiles/profile.h" | |
| 19 #include "chrome/browser/ui/browser.h" | |
| 20 #include "chrome/browser/ui/browser_window.h" | |
| 21 #include "chrome/browser/ui/panels/detached_panel_collection.h" | |
| 22 #include "chrome/browser/ui/panels/native_panel.h" | |
| 23 #include "chrome/browser/ui/panels/panel_collection.h" | |
| 24 #include "chrome/browser/ui/panels/panel_mouse_watcher.h" | |
| 25 #include "chrome/browser/ui/panels/stacked_panel_collection.h" | |
| 26 #include "chrome/browser/ui/panels/test_panel_active_state_observer.h" | |
| 27 #include "chrome/browser/ui/panels/test_panel_mouse_watcher.h" | |
| 28 #include "chrome/common/chrome_paths.h" | |
| 29 #include "chrome/common/chrome_switches.h" | |
| 30 #include "chrome/test/base/interactive_test_utils.h" | |
| 31 #include "chrome/test/base/ui_test_utils.h" | |
| 32 #include "components/sync/api/string_ordinal.h" | |
| 33 #include "content/public/browser/notification_service.h" | |
| 34 #include "content/public/common/url_constants.h" | |
| 35 #include "content/public/test/web_contents_tester.h" | |
| 36 #include "extensions/browser/extension_prefs.h" | |
| 37 #include "extensions/browser/extension_system.h" | |
| 38 #include "extensions/browser/install_flag.h" | |
| 39 #include "extensions/common/manifest_constants.h" | |
| 40 | |
| 41 #if defined(OS_LINUX) | |
| 42 #include "ui/base/x/x11_util.h" | |
| 43 #endif | |
| 44 | |
| 45 #if defined(OS_MACOSX) | |
| 46 #include "base/mac/scoped_nsautorelease_pool.h" | |
| 47 #include "chrome/browser/ui/cocoa/run_loop_testing.h" | |
| 48 #endif | |
| 49 | |
| 50 using content::WebContentsTester; | |
| 51 using extensions::Extension; | |
| 52 | |
| 53 namespace { | |
| 54 | |
| 55 const gfx::Rect kTestingPrimaryDisplayArea = gfx::Rect(0, 0, 800, 600); | |
| 56 const gfx::Rect kTestingPrimaryWorkArea = gfx::Rect(0, 0, 800, 580); | |
| 57 | |
| 58 struct MockDesktopBar { | |
| 59 bool auto_hiding_enabled; | |
| 60 DisplaySettingsProvider::DesktopBarVisibility visibility; | |
| 61 int thickness; | |
| 62 }; | |
| 63 | |
| 64 class MockDisplaySettingsProviderImpl : | |
| 65 public BasePanelBrowserTest::MockDisplaySettingsProvider { | |
| 66 public: | |
| 67 MockDisplaySettingsProviderImpl(); | |
| 68 ~MockDisplaySettingsProviderImpl() override {} | |
| 69 | |
| 70 // Overridden from DisplaySettingsProvider: | |
| 71 gfx::Rect GetPrimaryDisplayArea() const override; | |
| 72 gfx::Rect GetPrimaryWorkArea() const override; | |
| 73 gfx::Rect GetDisplayAreaMatching(const gfx::Rect& bounds) const override; | |
| 74 gfx::Rect GetWorkAreaMatching(const gfx::Rect& bounds) const override; | |
| 75 bool IsAutoHidingDesktopBarEnabled(DesktopBarAlignment alignment) override; | |
| 76 int GetDesktopBarThickness(DesktopBarAlignment alignment) const override; | |
| 77 DesktopBarVisibility GetDesktopBarVisibility( | |
| 78 DesktopBarAlignment alignment) const override; | |
| 79 bool IsFullScreen() override; | |
| 80 | |
| 81 // Overridden from MockDisplaySettingsProvider: | |
| 82 void SetPrimaryDisplay(const gfx::Rect& display_area, | |
| 83 const gfx::Rect& work_area) override; | |
| 84 void SetSecondaryDisplay(const gfx::Rect& display_area, | |
| 85 const gfx::Rect& work_area) override; | |
| 86 void EnableAutoHidingDesktopBar(DesktopBarAlignment alignment, | |
| 87 bool enabled, | |
| 88 int thickness) override; | |
| 89 void SetDesktopBarVisibility(DesktopBarAlignment alignment, | |
| 90 DesktopBarVisibility visibility) override; | |
| 91 void SetDesktopBarThickness(DesktopBarAlignment alignment, | |
| 92 int thickness) override; | |
| 93 void EnableFullScreenMode(bool enabled) override; | |
| 94 | |
| 95 private: | |
| 96 gfx::Rect primary_display_area_; | |
| 97 gfx::Rect primary_work_area_; | |
| 98 gfx::Rect secondary_display_area_; | |
| 99 gfx::Rect secondary_work_area_; | |
| 100 MockDesktopBar mock_desktop_bars[3]; | |
| 101 bool full_screen_enabled_; | |
| 102 | |
| 103 DISALLOW_COPY_AND_ASSIGN(MockDisplaySettingsProviderImpl); | |
| 104 }; | |
| 105 | |
| 106 | |
| 107 MockDisplaySettingsProviderImpl::MockDisplaySettingsProviderImpl() | |
| 108 : full_screen_enabled_(false) { | |
| 109 memset(mock_desktop_bars, 0, sizeof(mock_desktop_bars)); | |
| 110 } | |
| 111 | |
| 112 gfx::Rect MockDisplaySettingsProviderImpl::GetPrimaryDisplayArea() const { | |
| 113 return primary_display_area_; | |
| 114 } | |
| 115 | |
| 116 gfx::Rect MockDisplaySettingsProviderImpl::GetPrimaryWorkArea() const { | |
| 117 return primary_work_area_; | |
| 118 } | |
| 119 | |
| 120 gfx::Rect MockDisplaySettingsProviderImpl::GetDisplayAreaMatching( | |
| 121 const gfx::Rect& bounds) const { | |
| 122 if (secondary_display_area_.IsEmpty()) | |
| 123 return primary_display_area_; | |
| 124 | |
| 125 gfx::Rect primary_intersection = | |
| 126 gfx::IntersectRects(bounds, primary_display_area_); | |
| 127 int primary_intersection_size = | |
| 128 primary_intersection.width() * primary_intersection.height(); | |
| 129 | |
| 130 gfx::Rect secondary_intersection = | |
| 131 gfx::IntersectRects(bounds, secondary_display_area_); | |
| 132 int secondary_intersection_size = | |
| 133 secondary_intersection.width() * secondary_intersection.height(); | |
| 134 | |
| 135 return primary_intersection_size >= secondary_intersection_size ? | |
| 136 primary_display_area_ : secondary_display_area_; | |
| 137 } | |
| 138 | |
| 139 gfx::Rect MockDisplaySettingsProviderImpl::GetWorkAreaMatching( | |
| 140 const gfx::Rect& bounds) const { | |
| 141 if (secondary_work_area_.IsEmpty()) | |
| 142 return primary_work_area_; | |
| 143 | |
| 144 gfx::Rect primary_intersection = | |
| 145 gfx::IntersectRects(bounds, primary_work_area_); | |
| 146 int primary_intersection_size = | |
| 147 primary_intersection.width() * primary_intersection.height(); | |
| 148 | |
| 149 gfx::Rect secondary_intersection = | |
| 150 gfx::IntersectRects(bounds, secondary_work_area_); | |
| 151 int secondary_intersection_size = | |
| 152 secondary_intersection.width() * secondary_intersection.height(); | |
| 153 | |
| 154 return primary_intersection_size >= secondary_intersection_size ? | |
| 155 primary_work_area_ : secondary_work_area_; | |
| 156 } | |
| 157 | |
| 158 bool MockDisplaySettingsProviderImpl::IsAutoHidingDesktopBarEnabled( | |
| 159 DesktopBarAlignment alignment) { | |
| 160 return mock_desktop_bars[static_cast<int>(alignment)].auto_hiding_enabled; | |
| 161 } | |
| 162 | |
| 163 int MockDisplaySettingsProviderImpl::GetDesktopBarThickness( | |
| 164 DesktopBarAlignment alignment) const { | |
| 165 return mock_desktop_bars[static_cast<int>(alignment)].thickness; | |
| 166 } | |
| 167 | |
| 168 DisplaySettingsProvider::DesktopBarVisibility | |
| 169 MockDisplaySettingsProviderImpl::GetDesktopBarVisibility( | |
| 170 DesktopBarAlignment alignment) const { | |
| 171 return mock_desktop_bars[static_cast<int>(alignment)].visibility; | |
| 172 } | |
| 173 | |
| 174 bool MockDisplaySettingsProviderImpl::IsFullScreen() { | |
| 175 return full_screen_enabled_; | |
| 176 } | |
| 177 | |
| 178 void MockDisplaySettingsProviderImpl::EnableAutoHidingDesktopBar( | |
| 179 DesktopBarAlignment alignment, bool enabled, int thickness) { | |
| 180 MockDesktopBar* bar = &(mock_desktop_bars[static_cast<int>(alignment)]); | |
| 181 bar->auto_hiding_enabled = enabled; | |
| 182 bar->thickness = thickness; | |
| 183 } | |
| 184 | |
| 185 void MockDisplaySettingsProviderImpl::SetPrimaryDisplay( | |
| 186 const gfx::Rect& display_area, const gfx::Rect& work_area) { | |
| 187 DCHECK(display_area.Contains(work_area)); | |
| 188 primary_display_area_ = display_area; | |
| 189 primary_work_area_ = work_area; | |
| 190 OnDisplaySettingsChanged(); | |
| 191 } | |
| 192 | |
| 193 void MockDisplaySettingsProviderImpl::SetSecondaryDisplay( | |
| 194 const gfx::Rect& display_area, const gfx::Rect& work_area) { | |
| 195 DCHECK(display_area.Contains(work_area)); | |
| 196 secondary_display_area_ = display_area; | |
| 197 secondary_work_area_ = work_area; | |
| 198 OnDisplaySettingsChanged(); | |
| 199 } | |
| 200 | |
| 201 void MockDisplaySettingsProviderImpl::SetDesktopBarVisibility( | |
| 202 DesktopBarAlignment alignment, DesktopBarVisibility visibility) { | |
| 203 MockDesktopBar* bar = &(mock_desktop_bars[static_cast<int>(alignment)]); | |
| 204 if (!bar->auto_hiding_enabled) | |
| 205 return; | |
| 206 if (visibility == bar->visibility) | |
| 207 return; | |
| 208 bar->visibility = visibility; | |
| 209 FOR_EACH_OBSERVER( | |
| 210 DesktopBarObserver, | |
| 211 desktop_bar_observers(), | |
| 212 OnAutoHidingDesktopBarVisibilityChanged(alignment, visibility)); | |
| 213 } | |
| 214 | |
| 215 void MockDisplaySettingsProviderImpl::SetDesktopBarThickness( | |
| 216 DesktopBarAlignment alignment, int thickness) { | |
| 217 MockDesktopBar* bar = &(mock_desktop_bars[static_cast<int>(alignment)]); | |
| 218 if (!bar->auto_hiding_enabled) | |
| 219 return; | |
| 220 if (thickness == bar->thickness) | |
| 221 return; | |
| 222 bar->thickness = thickness; | |
| 223 FOR_EACH_OBSERVER( | |
| 224 DesktopBarObserver, | |
| 225 desktop_bar_observers(), | |
| 226 OnAutoHidingDesktopBarThicknessChanged(alignment, thickness)); | |
| 227 } | |
| 228 | |
| 229 void MockDisplaySettingsProviderImpl::EnableFullScreenMode(bool enabled) { | |
| 230 full_screen_enabled_ = enabled; | |
| 231 CheckFullScreenMode(PERFORM_FULLSCREEN_CHECK); | |
| 232 } | |
| 233 | |
| 234 } // namespace | |
| 235 | |
| 236 const base::FilePath::CharType* BasePanelBrowserTest::kTestDir = | |
| 237 FILE_PATH_LITERAL("panels"); | |
| 238 | |
| 239 BasePanelBrowserTest::BasePanelBrowserTest() | |
| 240 : InProcessBrowserTest(), | |
| 241 mock_display_settings_enabled_(true) { | |
| 242 } | |
| 243 | |
| 244 BasePanelBrowserTest::~BasePanelBrowserTest() { | |
| 245 } | |
| 246 | |
| 247 void BasePanelBrowserTest::SetUpCommandLine(base::CommandLine* command_line) { | |
| 248 command_line->AppendSwitch(switches::kEnablePanels); | |
| 249 } | |
| 250 | |
| 251 void BasePanelBrowserTest::SetUpOnMainThread() { | |
| 252 InProcessBrowserTest::SetUpOnMainThread(); | |
| 253 | |
| 254 // Setup the work area and desktop bar so that we have consistent testing | |
| 255 // environment for all panel related tests. | |
| 256 if (mock_display_settings_enabled_) { | |
| 257 mock_display_settings_provider_ = new MockDisplaySettingsProviderImpl(); | |
| 258 mock_display_settings_provider_->SetPrimaryDisplay( | |
| 259 kTestingPrimaryDisplayArea, kTestingPrimaryWorkArea); | |
| 260 PanelManager::SetDisplaySettingsProviderForTesting( | |
| 261 mock_display_settings_provider_); | |
| 262 } | |
| 263 | |
| 264 PanelManager* panel_manager = PanelManager::GetInstance(); | |
| 265 panel_manager->enable_auto_sizing(false); | |
| 266 | |
| 267 PanelManager::shorten_time_intervals_for_testing(); | |
| 268 | |
| 269 // Simulate the mouse movement so that tests are not affected by actual mouse | |
| 270 // events. | |
| 271 PanelMouseWatcher* mouse_watcher = new TestPanelMouseWatcher(); | |
| 272 panel_manager->SetMouseWatcherForTesting(mouse_watcher); | |
| 273 | |
| 274 // This is needed so the subsequently created panels can be activated. | |
| 275 // On a Mac, it transforms background-only test process into foreground one. | |
| 276 ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser())); | |
| 277 } | |
| 278 | |
| 279 void BasePanelBrowserTest::WaitForPanelActiveState( | |
| 280 Panel* panel, ActiveState expected_state) { | |
| 281 DCHECK(expected_state == SHOW_AS_ACTIVE || | |
| 282 expected_state == SHOW_AS_INACTIVE); | |
| 283 | |
| 284 #if defined(OS_MACOSX) | |
| 285 std::unique_ptr<NativePanelTesting> panel_testing( | |
| 286 CreateNativePanelTesting(panel)); | |
| 287 ASSERT_TRUE(panel_testing->EnsureApplicationRunOnForeground()) << | |
| 288 "Failed to bring application to foreground. Bail out."; | |
| 289 #endif | |
| 290 | |
| 291 PanelActiveStateObserver signal(panel, expected_state == SHOW_AS_ACTIVE); | |
| 292 signal.Wait(); | |
| 293 } | |
| 294 | |
| 295 void BasePanelBrowserTest::WaitForBoundsAnimationFinished(Panel* panel) { | |
| 296 std::unique_ptr<NativePanelTesting> panel_testing( | |
| 297 CreateNativePanelTesting(panel)); | |
| 298 // Sometimes there are several animations in sequence due to content | |
| 299 // auto resizing. Wait for all animations to finish. | |
| 300 while (panel_testing->IsAnimatingBounds()) { | |
| 301 content::WindowedNotificationObserver signal( | |
| 302 chrome::NOTIFICATION_PANEL_BOUNDS_ANIMATIONS_FINISHED, | |
| 303 content::Source<Panel>(panel)); | |
| 304 if (!panel_testing->IsAnimatingBounds()) | |
| 305 return; | |
| 306 signal.Wait(); | |
| 307 } | |
| 308 } | |
| 309 | |
| 310 BasePanelBrowserTest::CreatePanelParams::CreatePanelParams( | |
| 311 const std::string& name, | |
| 312 const gfx::Rect& bounds, | |
| 313 ActiveState show_flag) | |
| 314 : name(name), | |
| 315 bounds(bounds), | |
| 316 show_flag(show_flag), | |
| 317 wait_for_fully_created(true), | |
| 318 expected_active_state(show_flag), | |
| 319 create_mode(PanelManager::CREATE_AS_DOCKED), | |
| 320 profile(NULL) { | |
| 321 } | |
| 322 | |
| 323 Panel* BasePanelBrowserTest::CreatePanelWithParams( | |
| 324 const CreatePanelParams& params) { | |
| 325 #if defined(OS_MACOSX) | |
| 326 // Opening panels on a Mac causes NSWindowController of the Panel window | |
| 327 // to be autoreleased. We need a pool drained after it's done so the test | |
| 328 // can close correctly. The NSWindowController of the Panel window controls | |
| 329 // lifetime of the Panel object so we want to release it as soon as | |
| 330 // possible. In real Chrome, this is done by message pump. | |
| 331 // On non-Mac platform, this is an empty class. | |
| 332 base::mac::ScopedNSAutoreleasePool autorelease_pool; | |
| 333 #endif | |
| 334 | |
| 335 content::WindowedNotificationObserver observer( | |
| 336 content::NOTIFICATION_LOAD_STOP, | |
| 337 content::NotificationService::AllSources()); | |
| 338 | |
| 339 PanelManager* manager = PanelManager::GetInstance(); | |
| 340 Panel* panel = manager->CreatePanel( | |
| 341 params.name, | |
| 342 params.profile ? params.profile : browser()->profile(), | |
| 343 params.url, | |
| 344 nullptr, | |
| 345 params.bounds, | |
| 346 params.create_mode); | |
| 347 | |
| 348 if (!params.url.is_empty()) | |
| 349 observer.Wait(); | |
| 350 | |
| 351 if (!manager->auto_sizing_enabled() || | |
| 352 params.bounds.width() || params.bounds.height()) { | |
| 353 EXPECT_FALSE(panel->auto_resizable()); | |
| 354 } else { | |
| 355 EXPECT_TRUE(panel->auto_resizable()); | |
| 356 } | |
| 357 | |
| 358 if (params.show_flag == SHOW_AS_ACTIVE) { | |
| 359 panel->Show(); | |
| 360 } else { | |
| 361 panel->ShowInactive(); | |
| 362 } | |
| 363 | |
| 364 if (params.wait_for_fully_created) { | |
| 365 base::MessageLoopForUI::current()->RunUntilIdle(); | |
| 366 | |
| 367 #if defined(OS_LINUX) && defined(USE_X11) | |
| 368 // On bots, we might have a simple window manager which always activates new | |
| 369 // windows, and can't always deactivate them. Re-activate the main tabbed | |
| 370 // browser to "deactivate" the newly created panel. | |
| 371 if (params.expected_active_state == SHOW_AS_INACTIVE && | |
| 372 ui::GuessWindowManager() == ui::WM_ICE_WM) { | |
| 373 // Wait for new panel to become active before deactivating to ensure | |
| 374 // the activated notification is consumed before we wait for the panel | |
| 375 // to become inactive. | |
| 376 WaitForPanelActiveState(panel, SHOW_AS_ACTIVE); | |
| 377 browser()->window()->Activate(); | |
| 378 } | |
| 379 #endif | |
| 380 // More waiting, because gaining or losing focus may require inter-process | |
| 381 // asynchronous communication, and it is not enough to just run the local | |
| 382 // message loop to make sure this activity has completed. | |
| 383 WaitForPanelActiveState(panel, params.expected_active_state); | |
| 384 | |
| 385 // Wait for the bounds animations on creation to finish. | |
| 386 WaitForBoundsAnimationFinished(panel); | |
| 387 } | |
| 388 | |
| 389 return panel; | |
| 390 } | |
| 391 | |
| 392 Panel* BasePanelBrowserTest::CreatePanelWithBounds( | |
| 393 const std::string& panel_name, const gfx::Rect& bounds) { | |
| 394 CreatePanelParams params(panel_name, bounds, SHOW_AS_ACTIVE); | |
| 395 return CreatePanelWithParams(params); | |
| 396 } | |
| 397 | |
| 398 Panel* BasePanelBrowserTest::CreatePanel(const std::string& panel_name) { | |
| 399 CreatePanelParams params(panel_name, gfx::Rect(), SHOW_AS_ACTIVE); | |
| 400 return CreatePanelWithParams(params); | |
| 401 } | |
| 402 | |
| 403 Panel* BasePanelBrowserTest::CreateDockedPanel(const std::string& name, | |
| 404 const gfx::Rect& bounds) { | |
| 405 Panel* panel = CreatePanelWithBounds(name, bounds); | |
| 406 EXPECT_EQ(PanelCollection::DOCKED, panel->collection()->type()); | |
| 407 return panel; | |
| 408 } | |
| 409 | |
| 410 Panel* BasePanelBrowserTest::CreateDetachedPanel(const std::string& name, | |
| 411 const gfx::Rect& bounds) { | |
| 412 Panel* panel = CreatePanelWithBounds(name, bounds); | |
| 413 PanelManager* panel_manager = panel->manager(); | |
| 414 panel_manager->MovePanelToCollection(panel, | |
| 415 panel_manager->detached_collection(), | |
| 416 PanelCollection::DEFAULT_POSITION); | |
| 417 EXPECT_EQ(PanelCollection::DETACHED, panel->collection()->type()); | |
| 418 // The panel is first created as docked panel, which ignores the specified | |
| 419 // origin in |bounds|. We need to reposition the panel after it becomes | |
| 420 // detached. | |
| 421 panel->SetPanelBounds(bounds); | |
| 422 WaitForBoundsAnimationFinished(panel); | |
| 423 return panel; | |
| 424 } | |
| 425 | |
| 426 Panel* BasePanelBrowserTest::CreateStackedPanel(const std::string& name, | |
| 427 const gfx::Rect& bounds, | |
| 428 StackedPanelCollection* stack) { | |
| 429 Panel* panel = CreateDetachedPanel(name, bounds); | |
| 430 panel->manager()->MovePanelToCollection( | |
| 431 panel, | |
| 432 stack, | |
| 433 static_cast<PanelCollection::PositioningMask>( | |
| 434 PanelCollection::DEFAULT_POSITION | | |
| 435 PanelCollection::COLLAPSE_TO_FIT)); | |
| 436 EXPECT_EQ(PanelCollection::STACKED, panel->collection()->type()); | |
| 437 WaitForBoundsAnimationFinished(panel); | |
| 438 return panel; | |
| 439 } | |
| 440 | |
| 441 Panel* BasePanelBrowserTest::CreateInactivePanel(const std::string& name) { | |
| 442 // Create an active panel first, instead of inactive panel. This is because | |
| 443 // certain window managers on Linux, like icewm, will always activate the | |
| 444 // new window. | |
| 445 Panel* panel = CreatePanel(name); | |
| 446 | |
| 447 DeactivatePanel(panel); | |
| 448 WaitForPanelActiveState(panel, SHOW_AS_INACTIVE); | |
| 449 | |
| 450 return panel; | |
| 451 } | |
| 452 | |
| 453 Panel* BasePanelBrowserTest::CreateInactiveDockedPanel( | |
| 454 const std::string& name, const gfx::Rect& bounds) { | |
| 455 // Create an active panel first, instead of inactive panel. This is because | |
| 456 // certain window managers on Linux, like icewm, will always activate the | |
| 457 // new window. | |
| 458 Panel* panel = CreateDockedPanel(name, bounds); | |
| 459 | |
| 460 DeactivatePanel(panel); | |
| 461 WaitForPanelActiveState(panel, SHOW_AS_INACTIVE); | |
| 462 | |
| 463 return panel; | |
| 464 } | |
| 465 | |
| 466 Panel* BasePanelBrowserTest::CreateInactiveDetachedPanel( | |
| 467 const std::string& name, const gfx::Rect& bounds) { | |
| 468 // Create an active panel first, instead of inactive panel. This is because | |
| 469 // certain window managers on Linux, like icewm, will always activate the | |
| 470 // new window. | |
| 471 Panel* panel = CreateDetachedPanel(name, bounds); | |
| 472 | |
| 473 DeactivatePanel(panel); | |
| 474 WaitForPanelActiveState(panel, SHOW_AS_INACTIVE); | |
| 475 | |
| 476 return panel; | |
| 477 } | |
| 478 | |
| 479 void BasePanelBrowserTest::ActivatePanel(Panel* panel) { | |
| 480 // For certain window managers on Linux, the window activation/deactivation | |
| 481 // signals might not be sent. To work around this, we explicitly deactivate | |
| 482 // all other panels first. | |
| 483 #if defined(OS_LINUX) | |
| 484 std::vector<Panel*> panels = PanelManager::GetInstance()->panels(); | |
| 485 for (std::vector<Panel*>::const_iterator iter = panels.begin(); | |
| 486 iter != panels.end(); ++iter) { | |
| 487 Panel* current_panel = *iter; | |
| 488 if (panel != current_panel) | |
| 489 current_panel->Deactivate(); | |
| 490 } | |
| 491 #endif | |
| 492 | |
| 493 panel->Activate(); | |
| 494 } | |
| 495 | |
| 496 void BasePanelBrowserTest::DeactivatePanel(Panel* panel) { | |
| 497 #if defined(OS_LINUX) | |
| 498 // For certain window managers on Linux, like icewm, panel activation and | |
| 499 // deactivation notification might not get tiggered when non-panel window is | |
| 500 // activated or deactivated. So we deactivate the panel directly. | |
| 501 panel->Deactivate(); | |
| 502 #else | |
| 503 // Make the panel lose focus by activating the browser window. This is | |
| 504 // because: | |
| 505 // 1) On Windows, deactivating the panel window might cause the application | |
| 506 // to lose the foreground status. When this occurs, trying to activate | |
| 507 // the panel window again will not be allowed by the system. | |
| 508 // 2) On MacOS, deactivating a window is not supported by Cocoa. | |
| 509 browser()->window()->Activate(); | |
| 510 #endif | |
| 511 } | |
| 512 | |
| 513 // static | |
| 514 NativePanelTesting* BasePanelBrowserTest::CreateNativePanelTesting( | |
| 515 Panel* panel) { | |
| 516 return panel->native_panel()->CreateNativePanelTesting(); | |
| 517 } | |
| 518 | |
| 519 scoped_refptr<Extension> BasePanelBrowserTest::CreateExtension( | |
| 520 const base::FilePath::StringType& path, | |
| 521 extensions::Manifest::Location location, | |
| 522 const base::DictionaryValue& extra_value) { | |
| 523 extensions::ExtensionPrefs* extension_prefs = | |
| 524 extensions::ExtensionPrefs::Get(browser()->profile()); | |
| 525 base::FilePath full_path = extension_prefs->install_directory().Append(path); | |
| 526 | |
| 527 std::unique_ptr<base::DictionaryValue> input_value(extra_value.DeepCopy()); | |
| 528 input_value->SetString(extensions::manifest_keys::kVersion, "1.0.0.0"); | |
| 529 input_value->SetString(extensions::manifest_keys::kName, "Sample Extension"); | |
| 530 | |
| 531 std::string error; | |
| 532 scoped_refptr<Extension> extension = Extension::Create( | |
| 533 full_path, location, *input_value, Extension::NO_FLAGS, &error); | |
| 534 EXPECT_TRUE(extension.get()); | |
| 535 EXPECT_STREQ("", error.c_str()); | |
| 536 extensions::ExtensionSystem::Get( | |
| 537 browser()->profile())->extension_service()->OnExtensionInstalled( | |
| 538 extension.get(), | |
| 539 syncer::StringOrdinal(), | |
| 540 extensions::kInstallFlagInstallImmediately); | |
| 541 return extension; | |
| 542 } | |
| 543 | |
| 544 void BasePanelBrowserTest::CloseWindowAndWait(Panel* panel) { | |
| 545 // Closing a panel may involve several async tasks. Need to use | |
| 546 // message pump and wait for the notification. | |
| 547 PanelManager* manager = PanelManager::GetInstance(); | |
| 548 int panel_count = manager->num_panels(); | |
| 549 content::WindowedNotificationObserver signal( | |
| 550 chrome::NOTIFICATION_PANEL_CLOSED, | |
| 551 content::Source<Panel>(panel)); | |
| 552 panel->Close(); | |
| 553 signal.Wait(); | |
| 554 // Now we have one less panel. | |
| 555 EXPECT_EQ(panel_count - 1, manager->num_panels()); | |
| 556 | |
| 557 #if defined(OS_MACOSX) | |
| 558 // Mac window controllers may be autoreleased, and in the non-test | |
| 559 // environment, may actually depend on the autorelease pool being recycled | |
| 560 // with the run loop in order to perform important work. Replicate this in | |
| 561 // the test environment. | |
| 562 AutoreleasePool()->Recycle(); | |
| 563 | |
| 564 // Make sure that everything has a chance to run. | |
| 565 chrome::testing::NSRunLoopRunAllPending(); | |
| 566 #endif // OS_MACOSX | |
| 567 } | |
| 568 | |
| 569 void BasePanelBrowserTest::MoveMouseAndWaitForExpansionStateChange( | |
| 570 Panel* panel, | |
| 571 const gfx::Point& position) { | |
| 572 content::WindowedNotificationObserver signal( | |
| 573 chrome::NOTIFICATION_PANEL_CHANGED_EXPANSION_STATE, | |
| 574 content::Source<Panel>(panel)); | |
| 575 MoveMouse(position); | |
| 576 signal.Wait(); | |
| 577 } | |
| 578 | |
| 579 void BasePanelBrowserTest::MoveMouse(const gfx::Point& position) { | |
| 580 PanelManager::GetInstance()->mouse_watcher()->NotifyMouseMovement(position); | |
| 581 } | |
| 582 | |
| 583 std::string BasePanelBrowserTest::MakePanelName(int index) { | |
| 584 std::string panel_name("Panel"); | |
| 585 return panel_name + base::IntToString(index); | |
| 586 } | |
| 587 | |
| 588 bool BasePanelBrowserTest::WmSupportWindowActivation() { | |
| 589 return true; | |
| 590 } | |
| OLD | NEW |