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