• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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