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