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 "base/bind.h"
6#include "base/prefs/pref_service.h"
7#include "base/strings/utf_string_conversions.h"
8#include "chrome/app/chrome_command_ids.h"
9#include "chrome/browser/chrome_notification_types.h"
10#include "chrome/browser/devtools/devtools_window.h"
11#include "chrome/browser/extensions/extension_apitest.h"
12#include "chrome/browser/net/url_request_mock_util.h"
13#include "chrome/browser/prefs/browser_prefs.h"
14#include "chrome/browser/profiles/profile.h"
15#include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h"
16#include "chrome/browser/ui/app_modal_dialogs/native_app_modal_dialog.h"
17#include "chrome/browser/ui/browser.h"
18#include "chrome/browser/ui/browser_commands.h"
19#include "chrome/browser/ui/browser_finder.h"
20#include "chrome/browser/ui/browser_iterator.h"
21#include "chrome/browser/ui/browser_window.h"
22#include "chrome/browser/ui/panels/base_panel_browser_test.h"
23#include "chrome/browser/ui/panels/docked_panel_collection.h"
24#include "chrome/browser/ui/panels/native_panel.h"
25#include "chrome/browser/ui/panels/panel.h"
26#include "chrome/browser/ui/panels/panel_manager.h"
27#include "chrome/browser/ui/panels/test_panel_active_state_observer.h"
28#include "chrome/browser/web_applications/web_app.h"
29#include "chrome/common/chrome_switches.h"
30#include "chrome/common/pref_names.h"
31#include "chrome/common/url_constants.h"
32#include "chrome/test/base/interactive_test_utils.h"
33#include "chrome/test/base/ui_test_utils.h"
34#include "content/public/browser/native_web_keyboard_event.h"
35#include "content/public/browser/notification_service.h"
36#include "content/public/browser/web_contents.h"
37#include "content/public/common/url_constants.h"
38#include "content/public/test/browser_test_utils.h"
39#include "extensions/browser/extension_registry.h"
40#include "extensions/common/constants.h"
41#include "net/base/net_util.h"
42#include "net/test/url_request/url_request_mock_http_job.h"
43#include "testing/gtest/include/gtest/gtest.h"
44#include "ui/base/hit_test.h"
45#include "ui/events/event_utils.h"
46#include "ui/gfx/screen.h"
47
48using content::WebContents;
49
50class PanelBrowserTest : public BasePanelBrowserTest {
51 public:
52  PanelBrowserTest() : BasePanelBrowserTest() {
53  }
54
55 protected:
56  // Helper function for debugging.
57  void PrintAllPanelBounds() {
58    const std::vector<Panel*>& panels = PanelManager::GetInstance()->panels();
59    DLOG(WARNING) << "PanelBounds:";
60    for (size_t i = 0; i < panels.size(); ++i) {
61      DLOG(WARNING) << "#=" << i
62                    << ", ptr=" << panels[i]
63                    << ", x=" << panels[i]->GetBounds().x()
64                    << ", y=" << panels[i]->GetBounds().y()
65                    << ", width=" << panels[i]->GetBounds().width()
66                    << ", height" << panels[i]->GetBounds().height();
67    }
68  }
69
70  std::vector<gfx::Rect> GetAllPanelBounds() {
71    std::vector<Panel*> panels = PanelManager::GetInstance()->panels();
72    std::vector<gfx::Rect> bounds;
73    for (size_t i = 0; i < panels.size(); i++)
74      bounds.push_back(panels[i]->GetBounds());
75    return bounds;
76  }
77
78  std::vector<gfx::Rect> AddXDeltaToBounds(const std::vector<gfx::Rect>& bounds,
79                                           const std::vector<int>& delta_x) {
80    std::vector<gfx::Rect> new_bounds = bounds;
81    for (size_t i = 0; i < bounds.size(); ++i)
82      new_bounds[i].Offset(delta_x[i], 0);
83    return new_bounds;
84  }
85
86  std::vector<Panel::ExpansionState> GetAllPanelExpansionStates() {
87    std::vector<Panel*> panels = PanelManager::GetInstance()->panels();
88    std::vector<Panel::ExpansionState> expansion_states;
89    for (size_t i = 0; i < panels.size(); i++)
90      expansion_states.push_back(panels[i]->expansion_state());
91    return expansion_states;
92  }
93
94  std::vector<bool> GetAllPanelActiveStates() {
95    std::vector<Panel*> panels = PanelManager::GetInstance()->panels();
96    std::vector<bool> active_states;
97    for (size_t i = 0; i < panels.size(); i++)
98      active_states.push_back(panels[i]->IsActive());
99    return active_states;
100  }
101
102  std::vector<bool> ProduceExpectedActiveStates(
103      int expected_active_panel_index) {
104    std::vector<Panel*> panels = PanelManager::GetInstance()->panels();
105    std::vector<bool> active_states;
106    for (int i = 0; i < static_cast<int>(panels.size()); i++)
107      active_states.push_back(i == expected_active_panel_index);
108    return active_states;
109  }
110
111  void WaitForPanelActiveStates(const std::vector<bool>& old_states,
112                                const std::vector<bool>& new_states) {
113    DCHECK(old_states.size() == new_states.size());
114    std::vector<Panel*> panels = PanelManager::GetInstance()->panels();
115    for (size_t i = 0; i < old_states.size(); i++) {
116      if (old_states[i] != new_states[i]){
117        WaitForPanelActiveState(
118            panels[i], new_states[i] ? SHOW_AS_ACTIVE : SHOW_AS_INACTIVE);
119      }
120    }
121  }
122
123  void TestMinimizeRestore() {
124    // This constant is used to generate a point 'sufficiently higher then
125    // top edge of the panel'. On some platforms (Mac) we extend hover area
126    // a bit above the minimized panel as well, so it takes significant
127    // distance to 'move mouse out' of the hover-sensitive area.
128    const int kFarEnoughFromHoverArea = 153;
129
130    PanelManager* panel_manager = PanelManager::GetInstance();
131    std::vector<Panel*> panels = panel_manager->panels();
132    std::vector<gfx::Rect> test_begin_bounds = GetAllPanelBounds();
133    std::vector<gfx::Rect> expected_bounds = test_begin_bounds;
134    std::vector<Panel::ExpansionState> expected_expansion_states(
135        panels.size(), Panel::EXPANDED);
136    std::vector<NativePanelTesting*> native_panels_testing(panels.size());
137    for (size_t i = 0; i < panels.size(); ++i) {
138      native_panels_testing[i] = CreateNativePanelTesting(panels[i]);
139    }
140
141    // Verify titlebar click does not minimize.
142    for (size_t index = 0; index < panels.size(); ++index) {
143      // Press left mouse button.  Verify nothing changed.
144      native_panels_testing[index]->PressLeftMouseButtonTitlebar(
145          panels[index]->GetBounds().origin());
146      EXPECT_EQ(expected_bounds, GetAllPanelBounds());
147      EXPECT_EQ(expected_expansion_states, GetAllPanelExpansionStates());
148
149      // Release mouse button.  Verify nothing changed.
150      native_panels_testing[index]->ReleaseMouseButtonTitlebar();
151      EXPECT_EQ(expected_bounds, GetAllPanelBounds());
152      EXPECT_EQ(expected_expansion_states, GetAllPanelExpansionStates());
153    }
154
155    // Minimize all panels for next stage in test.
156    for (size_t index = 0; index < panels.size(); ++index) {
157      panels[index]->Minimize();
158      expected_bounds[index].set_height(panel::kMinimizedPanelHeight);
159      expected_bounds[index].set_y(
160          test_begin_bounds[index].y() +
161          test_begin_bounds[index].height() - panel::kMinimizedPanelHeight);
162      expected_expansion_states[index] = Panel::MINIMIZED;
163      EXPECT_EQ(expected_bounds, GetAllPanelBounds());
164      EXPECT_EQ(expected_expansion_states, GetAllPanelExpansionStates());
165    }
166
167    // Setup bounds and expansion states for minimized and titlebar-only
168    // states.
169    std::vector<Panel::ExpansionState> titlebar_exposed_states(
170        panels.size(), Panel::TITLE_ONLY);
171    std::vector<gfx::Rect> minimized_bounds = expected_bounds;
172    std::vector<Panel::ExpansionState> minimized_states(
173        panels.size(), Panel::MINIMIZED);
174    std::vector<gfx::Rect> titlebar_exposed_bounds = test_begin_bounds;
175    for (size_t index = 0; index < panels.size(); ++index) {
176      titlebar_exposed_bounds[index].set_height(
177          panels[index]->native_panel()->TitleOnlyHeight());
178      titlebar_exposed_bounds[index].set_y(
179          test_begin_bounds[index].y() +
180          test_begin_bounds[index].height() -
181          panels[index]->native_panel()->TitleOnlyHeight());
182    }
183
184    // Test hover.  All panels are currently in minimized state.
185    EXPECT_EQ(minimized_states, GetAllPanelExpansionStates());
186    for (size_t index = 0; index < panels.size(); ++index) {
187      // Hover mouse on minimized panel.
188      // Verify titlebar is exposed on all panels.
189      gfx::Point hover_point(panels[index]->GetBounds().origin());
190      MoveMouseAndWaitForExpansionStateChange(panels[index], hover_point);
191      EXPECT_EQ(titlebar_exposed_bounds, GetAllPanelBounds());
192      EXPECT_EQ(titlebar_exposed_states, GetAllPanelExpansionStates());
193
194      // Hover mouse above the panel. Verify all panels are minimized.
195      hover_point.set_y(
196          panels[index]->GetBounds().y() - kFarEnoughFromHoverArea);
197      MoveMouseAndWaitForExpansionStateChange(panels[index], hover_point);
198      EXPECT_EQ(minimized_bounds, GetAllPanelBounds());
199      EXPECT_EQ(minimized_states, GetAllPanelExpansionStates());
200
201      // Hover mouse below minimized panel.
202      // Verify titlebar is exposed on all panels.
203      hover_point.set_y(panels[index]->GetBounds().y() +
204                        panels[index]->GetBounds().height() + 5);
205      MoveMouseAndWaitForExpansionStateChange(panels[index], hover_point);
206      EXPECT_EQ(titlebar_exposed_bounds, GetAllPanelBounds());
207      EXPECT_EQ(titlebar_exposed_states, GetAllPanelExpansionStates());
208
209      // Hover below titlebar exposed panel.  Verify nothing changed.
210      hover_point.set_y(panels[index]->GetBounds().y() +
211                        panels[index]->GetBounds().height() + 6);
212      MoveMouse(hover_point);
213      EXPECT_EQ(titlebar_exposed_bounds, GetAllPanelBounds());
214      EXPECT_EQ(titlebar_exposed_states, GetAllPanelExpansionStates());
215
216      // Hover mouse above panel.  Verify all panels are minimized.
217      hover_point.set_y(
218          panels[index]->GetBounds().y() - kFarEnoughFromHoverArea);
219      MoveMouseAndWaitForExpansionStateChange(panels[index], hover_point);
220      EXPECT_EQ(minimized_bounds, GetAllPanelBounds());
221      EXPECT_EQ(minimized_states, GetAllPanelExpansionStates());
222    }
223
224    // Test restore.  All panels are currently in minimized state.
225    for (size_t index = 0; index < panels.size(); ++index) {
226      // Hover on the last panel.  This is to test the case of clicking on the
227      // panel when it's in titlebar exposed state.
228      if (index == panels.size() - 1)
229        MoveMouse(minimized_bounds[index].origin());
230
231      // Click minimized or title bar exposed panel as the case may be.
232      // Verify panel is restored to its original size.
233      native_panels_testing[index]->PressLeftMouseButtonTitlebar(
234          panels[index]->GetBounds().origin());
235      native_panels_testing[index]->ReleaseMouseButtonTitlebar();
236      expected_bounds[index].set_height(
237          test_begin_bounds[index].height());
238      expected_bounds[index].set_y(test_begin_bounds[index].y());
239      expected_expansion_states[index] = Panel::EXPANDED;
240      EXPECT_EQ(expected_bounds, GetAllPanelBounds());
241      EXPECT_EQ(expected_expansion_states, GetAllPanelExpansionStates());
242
243      // Hover again on the last panel which is now restored, to reset the
244      // titlebar exposed state.
245      if (index == panels.size() - 1)
246        MoveMouse(minimized_bounds[index].origin());
247    }
248
249    // The below could be separate tests, just adding a TODO here for tracking.
250    // TODO(prasadt): Add test for dragging when in titlebar exposed state.
251    // TODO(prasadt): Add test in presence of auto hiding task bar.
252
253    for (size_t i = 0; i < panels.size(); ++i)
254      delete native_panels_testing[i];
255  }
256};
257
258IN_PROC_BROWSER_TEST_F(PanelBrowserTest, CheckDockedPanelProperties) {
259  PanelManager* panel_manager = PanelManager::GetInstance();
260  DockedPanelCollection* docked_collection = panel_manager->docked_collection();
261
262  // Create 3 docked panels that are in expanded, title-only or minimized states
263  // respectively.
264  Panel* panel1 = CreatePanelWithBounds("1", gfx::Rect(0, 0, 100, 100));
265  Panel* panel2 = CreatePanelWithBounds("2", gfx::Rect(0, 0, 100, 100));
266  Panel* panel3 = CreatePanelWithBounds("3", gfx::Rect(0, 0, 100, 100));
267  panel2->SetExpansionState(Panel::TITLE_ONLY);
268  EXPECT_EQ(Panel::TITLE_ONLY, panel2->expansion_state());
269  panel3->SetExpansionState(Panel::MINIMIZED);
270  EXPECT_EQ(Panel::MINIMIZED, panel3->expansion_state());
271  scoped_ptr<NativePanelTesting> panel1_testing(
272      CreateNativePanelTesting(panel1));
273  scoped_ptr<NativePanelTesting> panel2_testing(
274      CreateNativePanelTesting(panel2));
275  scoped_ptr<NativePanelTesting> panel3_testing(
276      CreateNativePanelTesting(panel3));
277
278  // Ensure that the layout message can get a chance to be processed so that
279  // the button visibility can be updated.
280  base::MessageLoop::current()->RunUntilIdle();
281
282  EXPECT_EQ(3, panel_manager->num_panels());
283  EXPECT_TRUE(docked_collection->HasPanel(panel1));
284  EXPECT_TRUE(docked_collection->HasPanel(panel2));
285  EXPECT_TRUE(docked_collection->HasPanel(panel3));
286
287  EXPECT_EQ(Panel::EXPANDED, panel1->expansion_state());
288  EXPECT_EQ(Panel::TITLE_ONLY, panel2->expansion_state());
289  EXPECT_EQ(Panel::MINIMIZED, panel3->expansion_state());
290
291  EXPECT_TRUE(panel1->IsAlwaysOnTop());
292  EXPECT_TRUE(panel2->IsAlwaysOnTop());
293  EXPECT_TRUE(panel3->IsAlwaysOnTop());
294
295  EXPECT_TRUE(panel1_testing->IsButtonVisible(panel::CLOSE_BUTTON));
296  EXPECT_TRUE(panel2_testing->IsButtonVisible(panel::CLOSE_BUTTON));
297  EXPECT_TRUE(panel3_testing->IsButtonVisible(panel::CLOSE_BUTTON));
298
299  EXPECT_TRUE(panel1_testing->IsButtonVisible(panel::MINIMIZE_BUTTON));
300  EXPECT_FALSE(panel2_testing->IsButtonVisible(panel::MINIMIZE_BUTTON));
301  EXPECT_FALSE(panel3_testing->IsButtonVisible(panel::MINIMIZE_BUTTON));
302
303  EXPECT_FALSE(panel1_testing->IsButtonVisible(panel::RESTORE_BUTTON));
304  EXPECT_TRUE(panel2_testing->IsButtonVisible(panel::RESTORE_BUTTON));
305  EXPECT_TRUE(panel3_testing->IsButtonVisible(panel::RESTORE_BUTTON));
306
307  // Expanded panel cannot be resized at the bottom.
308  EXPECT_EQ(panel::RESIZABLE_EXCEPT_BOTTOM, panel1->CanResizeByMouse());
309  EXPECT_EQ(panel::NOT_RESIZABLE, panel2->CanResizeByMouse());
310  EXPECT_EQ(panel::NOT_RESIZABLE, panel3->CanResizeByMouse());
311
312  EXPECT_EQ(panel::TOP_ROUNDED, panel1_testing->GetWindowCornerStyle());
313  EXPECT_EQ(panel::TOP_ROUNDED, panel1_testing->GetWindowCornerStyle());
314  EXPECT_EQ(panel::TOP_ROUNDED, panel3_testing->GetWindowCornerStyle());
315
316  EXPECT_EQ(Panel::USE_PANEL_ATTENTION, panel1->attention_mode());
317  EXPECT_EQ(Panel::USE_PANEL_ATTENTION, panel2->attention_mode());
318  EXPECT_EQ(Panel::USE_PANEL_ATTENTION, panel3->attention_mode());
319
320  panel_manager->CloseAll();
321}
322
323IN_PROC_BROWSER_TEST_F(PanelBrowserTest, CreatePanel) {
324  PanelManager* panel_manager = PanelManager::GetInstance();
325  EXPECT_EQ(0, panel_manager->num_panels()); // No panels initially.
326
327  Panel* panel = CreatePanel("PanelTest");
328  EXPECT_EQ(1, panel_manager->num_panels());
329
330  gfx::Rect bounds = panel->GetBounds();
331  EXPECT_GT(bounds.x(), 0);
332  EXPECT_GT(bounds.y(), 0);
333  EXPECT_GT(bounds.width(), 0);
334  EXPECT_GT(bounds.height(), 0);
335
336  EXPECT_EQ(bounds.right(),
337            panel_manager->docked_collection()->StartingRightPosition());
338
339  CloseWindowAndWait(panel);
340
341  EXPECT_EQ(0, panel_manager->num_panels());
342}
343
344IN_PROC_BROWSER_TEST_F(PanelBrowserTest, CreateBigPanel) {
345  gfx::Rect work_area = PanelManager::GetInstance()->
346      display_settings_provider()->GetPrimaryWorkArea();
347  Panel* panel = CreatePanelWithBounds("BigPanel", work_area);
348  gfx::Rect bounds = panel->GetBounds();
349  EXPECT_EQ(panel->max_size().width(), bounds.width());
350  EXPECT_LT(bounds.width(), work_area.width());
351  EXPECT_EQ(panel->max_size().height(), bounds.height());
352  EXPECT_LT(bounds.height(), work_area.height());
353  panel->Close();
354}
355
356class WaitForStableInitialSize : public TestPanelNotificationObserver {
357 public:
358  explicit WaitForStableInitialSize(Panel* panel)
359      : TestPanelNotificationObserver(
360          chrome::NOTIFICATION_PANEL_COLLECTION_UPDATED,
361          content::NotificationService::AllSources()),
362        panel_(panel) {}
363  virtual ~WaitForStableInitialSize() {}
364
365 protected:
366  virtual bool AtExpectedState() OVERRIDE {
367    return panel_->GetBounds().height() > panel_->TitleOnlyHeight();
368  }
369  Panel* panel_;
370};
371
372class WaitForAutoResizeWider : public TestPanelNotificationObserver {
373 public:
374  explicit WaitForAutoResizeWider(Panel* panel)
375      : TestPanelNotificationObserver(
376          chrome::NOTIFICATION_PANEL_COLLECTION_UPDATED,
377          content::NotificationService::AllSources()),
378        panel_(panel),
379        initial_size_(panel->GetBounds().size()) {}
380  virtual ~WaitForAutoResizeWider() {}
381
382 protected:
383  virtual bool AtExpectedState() OVERRIDE {
384    return panel_->GetBounds().width() > initial_size_.width();
385  }
386  Panel* panel_;
387  gfx::Size initial_size_;
388};
389
390class WaitForAutoResizeNarrower : public TestPanelNotificationObserver {
391 public:
392  explicit WaitForAutoResizeNarrower(Panel* panel)
393      : TestPanelNotificationObserver(
394          chrome::NOTIFICATION_PANEL_COLLECTION_UPDATED,
395          content::NotificationService::AllSources()),
396        panel_(panel),
397        initial_size_(panel->GetBounds().size()) {}
398  virtual ~WaitForAutoResizeNarrower() {}
399
400 protected:
401  virtual bool AtExpectedState() OVERRIDE {
402    return panel_->GetBounds().width() < initial_size_.width();
403  }
404  Panel* panel_;
405  gfx::Size initial_size_;
406};
407
408// crbug.com/160504
409IN_PROC_BROWSER_TEST_F(PanelBrowserTest, DISABLED_AutoResize) {
410  PanelManager* panel_manager = PanelManager::GetInstance();
411  panel_manager->enable_auto_sizing(true);
412  // Bigger space is needed by this test.
413  mock_display_settings_provider()->SetPrimaryDisplay(
414      gfx::Rect(0, 0, 1200, 900), gfx::Rect(0, 0, 1200, 900));
415
416  // Create a test panel with web contents loaded.
417  CreatePanelParams params("PanelTest1", gfx::Rect(), SHOW_AS_ACTIVE);
418  GURL url(ui_test_utils::GetTestUrl(
419      base::FilePath(kTestDir),
420      base::FilePath(FILE_PATH_LITERAL("update-preferred-size.html"))));
421  params.url = url;
422  Panel* panel = CreatePanelWithParams(params);
423
424  // Ensure panel has auto resized to original web content size.
425  // The resize will update the docked panel collection.
426  WaitForStableInitialSize initial_resize(panel);
427  initial_resize.Wait();
428  gfx::Rect initial_bounds = panel->GetBounds();
429
430  // Expand the test page. The resize will update the docked panel collection.
431  WaitForAutoResizeWider enlarge(panel);
432  EXPECT_TRUE(content::ExecuteScript(
433      panel->GetWebContents(), "changeSize(50);"));
434  enlarge.Wait();
435  gfx::Rect bounds_on_grow = panel->GetBounds();
436  EXPECT_GT(bounds_on_grow.width(), initial_bounds.width());
437  EXPECT_EQ(bounds_on_grow.height(), initial_bounds.height());
438
439  // Shrink the test page. The resize will update the docked panel collection.
440  WaitForAutoResizeNarrower shrink(panel);
441  EXPECT_TRUE(content::ExecuteScript(
442      panel->GetWebContents(), "changeSize(-30);"));
443  shrink.Wait();
444  gfx::Rect bounds_on_shrink = panel->GetBounds();
445  EXPECT_LT(bounds_on_shrink.width(), bounds_on_grow.width());
446  EXPECT_GT(bounds_on_shrink.width(), initial_bounds.width());
447  EXPECT_EQ(bounds_on_shrink.height(), initial_bounds.height());
448
449  // Verify resizing turns off auto-resizing and panel no longer auto-resizes.
450  gfx::Rect previous_bounds = panel->GetBounds();
451  // These should be identical because the panel is expanded.
452  EXPECT_EQ(previous_bounds.size(), panel->GetRestoredBounds().size());
453  gfx::Size new_size(previous_bounds.size());
454  new_size.Enlarge(5, 5);
455  gfx::Rect new_bounds(previous_bounds.origin(), new_size);
456  panel->SetBounds(new_bounds);
457  EXPECT_FALSE(panel->auto_resizable());
458  EXPECT_EQ(new_bounds.size(), panel->GetBounds().size());
459  EXPECT_EQ(new_bounds.size(), panel->GetRestoredBounds().size());
460
461  // Turn back on auto-resize and verify that panel auto resizes.
462  content::WindowedNotificationObserver auto_resize_enabled(
463      chrome::NOTIFICATION_PANEL_COLLECTION_UPDATED,
464      content::NotificationService::AllSources());
465  panel->SetAutoResizable(true);
466  auto_resize_enabled.Wait();
467  gfx::Rect bounds_auto_resize_enabled = panel->GetBounds();
468  EXPECT_EQ(bounds_on_shrink.width(), bounds_auto_resize_enabled.width());
469  EXPECT_EQ(bounds_on_shrink.height(), bounds_auto_resize_enabled.height());
470
471  panel->Close();
472}
473
474IN_PROC_BROWSER_TEST_F(PanelBrowserTest, ResizePanel) {
475  PanelManager* panel_manager = PanelManager::GetInstance();
476  panel_manager->enable_auto_sizing(true);
477
478  Panel* panel = CreatePanel("TestPanel");
479  EXPECT_TRUE(panel->auto_resizable());
480  EXPECT_EQ(Panel::EXPANDED, panel->expansion_state());
481
482  // Verify resizing turns off auto-resizing and that it works.
483  gfx::Rect original_bounds = panel->GetBounds();
484  // These should be identical because the panel is expanded.
485  EXPECT_EQ(original_bounds.size(), panel->GetRestoredBounds().size());
486  gfx::Size new_size(original_bounds.size());
487  new_size.Enlarge(5, 5);
488  gfx::Rect new_bounds(original_bounds.origin(), new_size);
489  panel->SetBounds(new_bounds);
490  EXPECT_FALSE(panel->auto_resizable());
491  EXPECT_EQ(new_bounds.size(), panel->GetBounds().size());
492  EXPECT_EQ(new_bounds.size(), panel->GetRestoredBounds().size());
493
494  // Verify current height unaffected when panel is not expanded.
495  panel->SetExpansionState(Panel::MINIMIZED);
496  int original_height = panel->GetBounds().height();
497  new_size.Enlarge(5, 5);
498  new_bounds.set_size(new_size);
499  panel->SetBounds(new_bounds);
500  EXPECT_EQ(new_bounds.size().width(), panel->GetBounds().width());
501  EXPECT_EQ(original_height, panel->GetBounds().height());
502  EXPECT_EQ(new_bounds.size(), panel->GetRestoredBounds().size());
503
504  panel->Close();
505}
506
507IN_PROC_BROWSER_TEST_F(PanelBrowserTest, AnimateBounds) {
508  // Create a detached panel, instead of docked panel because it cannot be
509  // moved to any location.
510  Panel* panel = CreateDetachedPanel("1", gfx::Rect(200, 100, 100, 100));
511  scoped_ptr<NativePanelTesting> panel_testing(
512      CreateNativePanelTesting(panel));
513
514  // Validates that no animation should be triggered when the panel is being
515  // dragged.
516  gfx::Point mouse_location(panel->GetBounds().origin());
517  panel_testing->PressLeftMouseButtonTitlebar(mouse_location);
518  panel_testing->DragTitlebar(mouse_location + gfx::Vector2d(-100, 5));
519  EXPECT_FALSE(panel_testing->IsAnimatingBounds());
520  panel_testing->FinishDragTitlebar();
521
522  // Set bounds with animation.
523  gfx::Rect bounds = gfx::Rect(10, 20, 150, 160);
524  panel->SetPanelBounds(bounds);
525  EXPECT_TRUE(panel_testing->IsAnimatingBounds());
526  WaitForBoundsAnimationFinished(panel);
527  EXPECT_FALSE(panel_testing->IsAnimatingBounds());
528  EXPECT_EQ(bounds, panel->GetBounds());
529
530  // Set bounds without animation.
531  bounds = gfx::Rect(30, 40, 200, 220);
532  panel->SetPanelBoundsInstantly(bounds);
533  EXPECT_FALSE(panel_testing->IsAnimatingBounds());
534  EXPECT_EQ(bounds, panel->GetBounds());
535
536  panel->Close();
537}
538
539IN_PROC_BROWSER_TEST_F(PanelBrowserTest, RestoredBounds) {
540  Panel* panel = CreatePanelWithBounds("PanelTest", gfx::Rect(0, 0, 100, 100));
541  EXPECT_EQ(Panel::EXPANDED, panel->expansion_state());
542  EXPECT_EQ(panel->GetBounds(), panel->GetRestoredBounds());
543
544  panel->SetExpansionState(Panel::MINIMIZED);
545  EXPECT_EQ(Panel::MINIMIZED, panel->expansion_state());
546  gfx::Rect bounds = panel->GetBounds();
547  gfx::Rect restored = panel->GetRestoredBounds();
548  EXPECT_EQ(bounds.x(), restored.x());
549  EXPECT_GT(bounds.y(), restored.y());
550  EXPECT_EQ(bounds.width(), restored.width());
551  EXPECT_LT(bounds.height(), restored.height());
552
553  panel->SetExpansionState(Panel::TITLE_ONLY);
554  EXPECT_EQ(Panel::TITLE_ONLY, panel->expansion_state());
555  bounds = panel->GetBounds();
556  restored = panel->GetRestoredBounds();
557  EXPECT_EQ(bounds.x(), restored.x());
558  EXPECT_GT(bounds.y(), restored.y());
559  EXPECT_EQ(bounds.width(), restored.width());
560  EXPECT_LT(bounds.height(), restored.height());
561
562  panel->SetExpansionState(Panel::MINIMIZED);
563  EXPECT_EQ(Panel::MINIMIZED, panel->expansion_state());
564  bounds = panel->GetBounds();
565  restored = panel->GetRestoredBounds();
566  EXPECT_EQ(bounds.x(), restored.x());
567  EXPECT_GT(bounds.y(), restored.y());
568  EXPECT_EQ(bounds.width(), restored.width());
569  EXPECT_LT(bounds.height(), restored.height());
570
571  panel->SetExpansionState(Panel::EXPANDED);
572  EXPECT_EQ(panel->GetBounds(), panel->GetRestoredBounds());
573
574  // Verify that changing the panel bounds does not affect the restored height.
575  int saved_restored_height = restored.height();
576  panel->SetExpansionState(Panel::MINIMIZED);
577  bounds = gfx::Rect(10, 20, 300, 400);
578  panel->SetPanelBounds(bounds);
579  EXPECT_EQ(saved_restored_height, panel->GetRestoredBounds().height());
580
581  panel->SetExpansionState(Panel::TITLE_ONLY);
582  bounds = gfx::Rect(20, 30, 100, 200);
583  panel->SetPanelBounds(bounds);
584  EXPECT_EQ(saved_restored_height, panel->GetRestoredBounds().height());
585
586  panel->SetExpansionState(Panel::EXPANDED);
587  bounds = gfx::Rect(40, 60, 300, 400);
588  panel->SetPanelBounds(bounds);
589  EXPECT_EQ(saved_restored_height, panel->GetRestoredBounds().height());
590  panel->set_full_size(bounds.size());
591  EXPECT_NE(saved_restored_height, panel->GetRestoredBounds().height());
592
593  panel->Close();
594}
595
596IN_PROC_BROWSER_TEST_F(PanelBrowserTest, MinimizeRestore) {
597  // Test with one panel.
598  CreatePanelWithBounds("PanelTest1", gfx::Rect(0, 0, 100, 100));
599  TestMinimizeRestore();
600
601  PanelManager::GetInstance()->CloseAll();
602}
603
604IN_PROC_BROWSER_TEST_F(PanelBrowserTest, MinimizeRestoreTwoPanels) {
605  // Test with two panels.
606  CreatePanelWithBounds("PanelTest1", gfx::Rect(0, 0, 100, 100));
607  CreatePanelWithBounds("PanelTest2", gfx::Rect(0, 0, 110, 110));
608  TestMinimizeRestore();
609
610  PanelManager::GetInstance()->CloseAll();
611}
612
613IN_PROC_BROWSER_TEST_F(PanelBrowserTest, MinimizeRestoreThreePanels) {
614  // Test with three panels.
615  CreatePanelWithBounds("PanelTest1", gfx::Rect(0, 0, 100, 100));
616  CreatePanelWithBounds("PanelTest2", gfx::Rect(0, 0, 110, 110));
617  CreatePanelWithBounds("PanelTest3", gfx::Rect(0, 0, 120, 120));
618  TestMinimizeRestore();
619
620  PanelManager::GetInstance()->CloseAll();
621}
622
623IN_PROC_BROWSER_TEST_F(PanelBrowserTest, MinimizeRestoreButtonClick) {
624  // Test with three panels.
625  Panel* panel1 = CreatePanel("PanelTest1");
626  Panel* panel2 = CreatePanel("PanelTest2");
627  Panel* panel3 = CreatePanel("PanelTest3");
628  EXPECT_FALSE(panel1->IsMinimized());
629  EXPECT_FALSE(panel2->IsMinimized());
630  EXPECT_FALSE(panel3->IsMinimized());
631
632  // Click restore button on an expanded panel. Expect no change.
633  panel1->OnRestoreButtonClicked(panel::NO_MODIFIER);
634  EXPECT_FALSE(panel1->IsMinimized());
635  EXPECT_FALSE(panel2->IsMinimized());
636  EXPECT_FALSE(panel3->IsMinimized());
637
638  // Click minimize button on an expanded panel. Only that panel will minimize.
639  panel1->OnMinimizeButtonClicked(panel::NO_MODIFIER);
640  EXPECT_TRUE(panel1->IsMinimized());
641  EXPECT_FALSE(panel2->IsMinimized());
642  EXPECT_FALSE(panel3->IsMinimized());
643
644  // Click minimize button on a minimized panel. Expect no change.
645  panel1->OnMinimizeButtonClicked(panel::NO_MODIFIER);
646  EXPECT_TRUE(panel1->IsMinimized());
647  EXPECT_FALSE(panel2->IsMinimized());
648  EXPECT_FALSE(panel3->IsMinimized());
649
650  // Minimize all panels by clicking minimize button on an expanded panel
651  // with the apply-all modifier.
652  panel2->OnMinimizeButtonClicked(panel::APPLY_TO_ALL);
653  EXPECT_TRUE(panel1->IsMinimized());
654  EXPECT_TRUE(panel2->IsMinimized());
655  EXPECT_TRUE(panel3->IsMinimized());
656
657  // Click restore button on a minimized panel. Only that panel will restore.
658  panel2->OnRestoreButtonClicked(panel::NO_MODIFIER);
659  EXPECT_TRUE(panel1->IsMinimized());
660  EXPECT_FALSE(panel2->IsMinimized());
661  EXPECT_TRUE(panel3->IsMinimized());
662
663  // Restore all panels by clicking restore button on a minimized panel.
664  panel3->OnRestoreButtonClicked(panel::APPLY_TO_ALL);
665  EXPECT_FALSE(panel1->IsMinimized());
666  EXPECT_FALSE(panel2->IsMinimized());
667  EXPECT_FALSE(panel3->IsMinimized());
668}
669
670// http://crbug.com/243891 flaky on Linux
671#if defined(OS_LINUX)
672#define MAYBE_RestoreAllWithTitlebarClick DISABLED_RestoreAllWithTitlebarClick
673#else
674#define MAYBE_RestoreAllWithTitlebarClick RestoreAllWithTitlebarClick
675#endif
676IN_PROC_BROWSER_TEST_F(PanelBrowserTest, MAYBE_RestoreAllWithTitlebarClick) {
677  // Test with three panels.
678  Panel* panel1 = CreatePanel("PanelTest1");
679  Panel* panel2 = CreatePanel("PanelTest2");
680  Panel* panel3 = CreatePanel("PanelTest3");
681  EXPECT_FALSE(panel1->IsMinimized());
682  EXPECT_FALSE(panel2->IsMinimized());
683  EXPECT_FALSE(panel3->IsMinimized());
684
685  scoped_ptr<NativePanelTesting> test_panel1(
686      CreateNativePanelTesting(panel1));
687  scoped_ptr<NativePanelTesting> test_panel2(
688      CreateNativePanelTesting(panel2));
689  scoped_ptr<NativePanelTesting> test_panel3(
690      CreateNativePanelTesting(panel3));
691
692  // Click on an expanded panel's titlebar using the apply-all modifier.
693  // Verify expansion state is unchanged.
694  test_panel2->PressLeftMouseButtonTitlebar(panel2->GetBounds().origin(),
695                                            panel::APPLY_TO_ALL);
696  test_panel2->ReleaseMouseButtonTitlebar(panel::APPLY_TO_ALL);
697  EXPECT_FALSE(panel1->IsMinimized());
698  EXPECT_FALSE(panel2->IsMinimized());
699  EXPECT_FALSE(panel3->IsMinimized());
700
701  // Click on a minimized panel's titlebar using the apply-all modifier.
702  panel1->Minimize();
703  panel2->Minimize();
704  panel3->Minimize();
705  EXPECT_TRUE(panel1->IsMinimized());
706  EXPECT_TRUE(panel2->IsMinimized());
707  EXPECT_TRUE(panel3->IsMinimized());
708
709  // Nothing changes until mouse is released.
710  test_panel1->PressLeftMouseButtonTitlebar(panel1->GetBounds().origin(),
711                                            panel::APPLY_TO_ALL);
712  EXPECT_TRUE(panel1->IsMinimized());
713  EXPECT_TRUE(panel2->IsMinimized());
714  EXPECT_TRUE(panel3->IsMinimized());
715  // Verify all panels restored when mouse is released.
716  test_panel1->ReleaseMouseButtonTitlebar(panel::APPLY_TO_ALL);
717  EXPECT_FALSE(panel1->IsMinimized());
718  EXPECT_FALSE(panel2->IsMinimized());
719  EXPECT_FALSE(panel3->IsMinimized());
720
721  // Minimize a single panel. Then click on expanded panel with apply-all
722  // modifier. Verify nothing changes.
723  panel1->Minimize();
724  EXPECT_TRUE(panel1->IsMinimized());
725  EXPECT_FALSE(panel2->IsMinimized());
726  EXPECT_FALSE(panel3->IsMinimized());
727
728  test_panel2->PressLeftMouseButtonTitlebar(panel2->GetBounds().origin(),
729                                            panel::APPLY_TO_ALL);
730  test_panel2->ReleaseMouseButtonTitlebar(panel::APPLY_TO_ALL);
731  EXPECT_TRUE(panel1->IsMinimized());
732  EXPECT_FALSE(panel2->IsMinimized());
733  EXPECT_FALSE(panel3->IsMinimized());
734
735  // Minimize another panel. Then click on a minimized panel with apply-all
736  // modifier to restore all panels.
737  panel2->Minimize();
738  EXPECT_TRUE(panel1->IsMinimized());
739  EXPECT_TRUE(panel2->IsMinimized());
740  EXPECT_FALSE(panel3->IsMinimized());
741
742  test_panel2->PressLeftMouseButtonTitlebar(panel2->GetBounds().origin(),
743                                            panel::APPLY_TO_ALL);
744  test_panel2->ReleaseMouseButtonTitlebar(panel::APPLY_TO_ALL);
745  EXPECT_FALSE(panel1->IsMinimized());
746  EXPECT_FALSE(panel2->IsMinimized());
747  EXPECT_FALSE(panel3->IsMinimized());
748
749  // Click on the single minimized panel. Verify all are restored.
750  panel1->Minimize();
751  EXPECT_TRUE(panel1->IsMinimized());
752  EXPECT_FALSE(panel2->IsMinimized());
753  EXPECT_FALSE(panel3->IsMinimized());
754
755  test_panel1->PressLeftMouseButtonTitlebar(panel1->GetBounds().origin(),
756                                            panel::APPLY_TO_ALL);
757  test_panel1->ReleaseMouseButtonTitlebar(panel::APPLY_TO_ALL);
758  EXPECT_FALSE(panel1->IsMinimized());
759  EXPECT_FALSE(panel2->IsMinimized());
760  EXPECT_FALSE(panel3->IsMinimized());
761
762  // Click on the single expanded panel. Verify nothing changes.
763  panel1->Minimize();
764  panel3->Minimize();
765  EXPECT_TRUE(panel1->IsMinimized());
766  EXPECT_FALSE(panel2->IsMinimized());
767  EXPECT_TRUE(panel3->IsMinimized());
768
769  test_panel2->PressLeftMouseButtonTitlebar(panel2->GetBounds().origin(),
770                                            panel::APPLY_TO_ALL);
771  test_panel2->ReleaseMouseButtonTitlebar(panel::APPLY_TO_ALL);
772  EXPECT_TRUE(panel1->IsMinimized());
773  EXPECT_FALSE(panel2->IsMinimized());
774  EXPECT_TRUE(panel3->IsMinimized());
775
776  // Hover over a minimized panel and click on the titlebar while it is in
777  // title-only mode. Should restore all panels.
778  panel2->Minimize();
779  EXPECT_TRUE(panel1->IsMinimized());
780  EXPECT_TRUE(panel2->IsMinimized());
781  EXPECT_TRUE(panel3->IsMinimized());
782
783  MoveMouseAndWaitForExpansionStateChange(panel2, panel2->GetBounds().origin());
784  EXPECT_EQ(Panel::TITLE_ONLY, panel1->expansion_state());
785  EXPECT_EQ(Panel::TITLE_ONLY, panel2->expansion_state());
786  EXPECT_EQ(Panel::TITLE_ONLY, panel3->expansion_state());
787
788  test_panel3->PressLeftMouseButtonTitlebar(panel3->GetBounds().origin(),
789                                            panel::APPLY_TO_ALL);
790  test_panel3->ReleaseMouseButtonTitlebar(panel::APPLY_TO_ALL);
791  EXPECT_FALSE(panel1->IsMinimized());
792  EXPECT_FALSE(panel2->IsMinimized());
793  EXPECT_FALSE(panel3->IsMinimized());
794
795  // Draw attention to a minimized panel. Click on a minimized panel that is
796  // not drawing attention. Verify restore all applies without affecting
797  // draw attention.
798  panel1->Minimize();
799  panel2->Minimize();
800  panel3->Minimize();
801  EXPECT_TRUE(panel1->IsMinimized());
802  EXPECT_TRUE(panel2->IsMinimized());
803  EXPECT_TRUE(panel3->IsMinimized());
804
805  panel1->FlashFrame(true);
806  EXPECT_TRUE(panel1->IsDrawingAttention());
807
808  test_panel2->PressLeftMouseButtonTitlebar(panel2->GetBounds().origin(),
809                                            panel::APPLY_TO_ALL);
810  test_panel2->ReleaseMouseButtonTitlebar(panel::APPLY_TO_ALL);
811  EXPECT_FALSE(panel1->IsMinimized());
812  EXPECT_FALSE(panel2->IsMinimized());
813  EXPECT_FALSE(panel3->IsMinimized());
814  EXPECT_TRUE(panel1->IsDrawingAttention());
815
816  // Restore all panels by clicking on the minimized panel that is drawing
817  // attention. Verify restore all applies and clears draw attention.
818  panel1->Minimize();
819  panel2->Minimize();
820  panel3->Minimize();
821  EXPECT_TRUE(panel1->IsMinimized());
822  EXPECT_TRUE(panel2->IsMinimized());
823  EXPECT_TRUE(panel3->IsMinimized());
824
825  test_panel1->PressLeftMouseButtonTitlebar(panel1->GetBounds().origin(),
826                                            panel::APPLY_TO_ALL);
827  test_panel1->ReleaseMouseButtonTitlebar(panel::APPLY_TO_ALL);
828  EXPECT_FALSE(panel1->IsMinimized());
829  EXPECT_FALSE(panel2->IsMinimized());
830  EXPECT_FALSE(panel3->IsMinimized());
831  EXPECT_FALSE(panel1->IsDrawingAttention());
832
833  PanelManager::GetInstance()->CloseAll();
834}
835
836IN_PROC_BROWSER_TEST_F(PanelBrowserTest,
837                       MinimizeRestoreOnAutoHidingDesktopBar) {
838  PanelManager* panel_manager = PanelManager::GetInstance();
839  DockedPanelCollection* docked_collection = panel_manager->docked_collection();
840  int expected_bottom_on_expanded = docked_collection->work_area().bottom();
841  int expected_bottom_on_title_only = expected_bottom_on_expanded;
842  int expected_bottom_on_minimized = expected_bottom_on_expanded;
843
844  // Turn on auto-hiding.
845  static const int bottom_bar_thickness = 40;
846  mock_display_settings_provider()->EnableAutoHidingDesktopBar(
847      DisplaySettingsProvider::DESKTOP_BAR_ALIGNED_BOTTOM,
848      true,
849      bottom_bar_thickness);
850  expected_bottom_on_title_only -= bottom_bar_thickness;
851
852  Panel* panel = CreatePanel("1");
853  int initial_height = panel->GetBounds().height();
854
855  EXPECT_EQ(Panel::EXPANDED, panel->expansion_state());
856  EXPECT_EQ(expected_bottom_on_expanded, panel->GetBounds().bottom());
857
858  panel->Minimize();
859  WaitForBoundsAnimationFinished(panel);
860  EXPECT_EQ(Panel::MINIMIZED, panel->expansion_state());
861  EXPECT_EQ(panel::kMinimizedPanelHeight, panel->GetBounds().height());
862  EXPECT_EQ(expected_bottom_on_minimized, panel->GetBounds().bottom());
863
864  panel->SetExpansionState(Panel::TITLE_ONLY);
865  WaitForBoundsAnimationFinished(panel);
866  EXPECT_EQ(Panel::TITLE_ONLY, panel->expansion_state());
867  EXPECT_EQ(panel::kTitlebarHeight, panel->GetBounds().height());
868  EXPECT_EQ(expected_bottom_on_title_only, panel->GetBounds().bottom());
869
870  panel->Restore();
871  WaitForBoundsAnimationFinished(panel);
872  EXPECT_EQ(Panel::EXPANDED, panel->expansion_state());
873  EXPECT_EQ(initial_height, panel->GetBounds().height());
874  EXPECT_EQ(expected_bottom_on_expanded, panel->GetBounds().bottom());
875
876  panel->Close();
877}
878
879IN_PROC_BROWSER_TEST_F(PanelBrowserTest, ChangeAutoHideTaskBarThickness) {
880  PanelManager* manager = PanelManager::GetInstance();
881  DockedPanelCollection* docked_collection = manager->docked_collection();
882  int initial_starting_right_position =
883      docked_collection->StartingRightPosition();
884
885  int bottom_bar_thickness = 20;
886  int right_bar_thickness = 30;
887  mock_display_settings_provider()->EnableAutoHidingDesktopBar(
888      DisplaySettingsProvider::DESKTOP_BAR_ALIGNED_BOTTOM,
889      true,
890      bottom_bar_thickness);
891  mock_display_settings_provider()->EnableAutoHidingDesktopBar(
892      DisplaySettingsProvider::DESKTOP_BAR_ALIGNED_RIGHT,
893      true,
894      right_bar_thickness);
895  EXPECT_EQ(initial_starting_right_position,
896            docked_collection->StartingRightPosition());
897
898  Panel* panel = CreatePanel("PanelTest");
899  panel->SetExpansionState(Panel::TITLE_ONLY);
900  WaitForBoundsAnimationFinished(panel);
901
902  EXPECT_EQ(docked_collection->work_area().bottom() - bottom_bar_thickness,
903            panel->GetBounds().bottom());
904  EXPECT_EQ(docked_collection->StartingRightPosition(),
905            panel->GetBounds().right());
906
907  initial_starting_right_position = docked_collection->StartingRightPosition();
908  int bottom_bar_thickness_delta = 10;
909  bottom_bar_thickness += bottom_bar_thickness_delta;
910  int right_bar_thickness_delta = 15;
911  right_bar_thickness += right_bar_thickness_delta;
912  mock_display_settings_provider()->SetDesktopBarThickness(
913      DisplaySettingsProvider::DESKTOP_BAR_ALIGNED_BOTTOM,
914      bottom_bar_thickness);
915  mock_display_settings_provider()->SetDesktopBarThickness(
916      DisplaySettingsProvider::DESKTOP_BAR_ALIGNED_RIGHT,
917      right_bar_thickness);
918  base::MessageLoopForUI::current()->RunUntilIdle();
919  EXPECT_EQ(initial_starting_right_position,
920            docked_collection->StartingRightPosition());
921  EXPECT_EQ(docked_collection->work_area().bottom() - bottom_bar_thickness,
922            panel->GetBounds().bottom());
923  EXPECT_EQ(docked_collection->StartingRightPosition(),
924            panel->GetBounds().right());
925
926  initial_starting_right_position = docked_collection->StartingRightPosition();
927  bottom_bar_thickness_delta = 20;
928  bottom_bar_thickness -= bottom_bar_thickness_delta;
929  right_bar_thickness_delta = 10;
930  right_bar_thickness -= right_bar_thickness_delta;
931  mock_display_settings_provider()->SetDesktopBarThickness(
932      DisplaySettingsProvider::DESKTOP_BAR_ALIGNED_BOTTOM,
933      bottom_bar_thickness);
934  mock_display_settings_provider()->SetDesktopBarThickness(
935      DisplaySettingsProvider::DESKTOP_BAR_ALIGNED_RIGHT,
936      right_bar_thickness);
937  base::MessageLoopForUI::current()->RunUntilIdle();
938  EXPECT_EQ(docked_collection->StartingRightPosition(),
939            initial_starting_right_position);
940  EXPECT_EQ(docked_collection->work_area().bottom() - bottom_bar_thickness,
941            panel->GetBounds().bottom());
942  EXPECT_EQ(docked_collection->StartingRightPosition(),
943            panel->GetBounds().right());
944
945  panel->Close();
946}
947
948IN_PROC_BROWSER_TEST_F(PanelBrowserTest, ActivatePanelOrTabbedWindow) {
949  if (!WmSupportWindowActivation()) {
950    LOG(WARNING) << "Skipping test due to WM problems.";
951    return;
952  }
953
954  Panel* panel1 = CreatePanel("Panel1");
955  Panel* panel2 = CreatePanel("Panel2");
956
957  // Activate main tabbed window.
958  browser()->window()->Activate();
959  WaitForPanelActiveState(panel2, SHOW_AS_INACTIVE);
960
961  // Activate a panel.
962  panel2->Activate();
963  WaitForPanelActiveState(panel2, SHOW_AS_ACTIVE);
964
965  // Activate the main tabbed window back.
966  browser()->window()->Activate();
967  WaitForPanelActiveState(panel2, SHOW_AS_INACTIVE);
968
969  // Activate another panel.
970  panel1->Activate();
971  WaitForPanelActiveState(panel1, SHOW_AS_ACTIVE);
972  WaitForPanelActiveState(panel2, SHOW_AS_INACTIVE);
973
974  // Switch focus between panels.
975  panel2->Activate();
976  WaitForPanelActiveState(panel2, SHOW_AS_ACTIVE);
977  WaitForPanelActiveState(panel1, SHOW_AS_INACTIVE);
978
979  PanelManager::GetInstance()->CloseAll();
980}
981
982// TODO(jianli): To be enabled for other platforms.
983#if defined(OS_WIN) || defined(OS_LINUX)
984#define MAYBE_ActivateDeactivateBasic ActivateDeactivateBasic
985#else
986#define MAYBE_ActivateDeactivateBasic DISABLED_ActivateDeactivateBasic
987#endif
988IN_PROC_BROWSER_TEST_F(PanelBrowserTest, MAYBE_ActivateDeactivateBasic) {
989  if (!WmSupportWindowActivation()) {
990    LOG(WARNING) << "Skipping test due to WM problems.";
991    return;
992  }
993
994  // Create an active panel.
995  Panel* panel = CreatePanel("PanelTest");
996  scoped_ptr<NativePanelTesting> native_panel_testing(
997      CreateNativePanelTesting(panel));
998
999  WaitForPanelActiveState(panel, SHOW_AS_ACTIVE);  // doublecheck active state
1000  EXPECT_TRUE(native_panel_testing->VerifyActiveState(true));
1001
1002  // Deactivate the panel.
1003  panel->Deactivate();
1004  WaitForPanelActiveState(panel, SHOW_AS_INACTIVE);
1005
1006  // On GTK there is no way to deactivate a window. So the Deactivate() call
1007  // above does not actually deactivate the window, but simply lowers it.
1008#if !defined(OS_LINUX)
1009  EXPECT_TRUE(native_panel_testing->VerifyActiveState(false));
1010#endif
1011
1012  // This test does not reactivate the panel because the panel might not be
1013  // reactivated programmatically once it is deactivated.
1014}
1015
1016IN_PROC_BROWSER_TEST_F(PanelBrowserTest, ActivateDeactivateMultiple) {
1017  if (!WmSupportWindowActivation()) {
1018    LOG(WARNING) << "Skipping test due to WM problems.";
1019    return;
1020  }
1021
1022  BrowserWindow* tabbed_window = browser()->window();
1023
1024  // Create 4 panels in the following screen layout:
1025  //    P3  P2  P1  P0
1026  const int kNumPanels = 4;
1027  for (int i = 0; i < kNumPanels; ++i)
1028    CreatePanelWithBounds(MakePanelName(i), gfx::Rect(0, 0, 100, 100));
1029  const std::vector<Panel*>& panels = PanelManager::GetInstance()->panels();
1030
1031  std::vector<bool> expected_active_states;
1032  std::vector<bool> last_active_states;
1033
1034  // The last created panel, P3, should be active.
1035  expected_active_states = ProduceExpectedActiveStates(3);
1036  EXPECT_EQ(expected_active_states, GetAllPanelActiveStates());
1037  EXPECT_FALSE(tabbed_window->IsActive());
1038
1039  // Activating P1 should cause P3 to lose focus.
1040  panels[1]->Activate();
1041  last_active_states = expected_active_states;
1042  expected_active_states = ProduceExpectedActiveStates(1);
1043  WaitForPanelActiveStates(last_active_states, expected_active_states);
1044  EXPECT_EQ(expected_active_states, GetAllPanelActiveStates());
1045
1046  // Minimizing inactive panel P2 should not affect other panels' active states.
1047  panels[2]->SetExpansionState(Panel::MINIMIZED);
1048  EXPECT_EQ(expected_active_states, GetAllPanelActiveStates());
1049  EXPECT_FALSE(tabbed_window->IsActive());
1050}
1051
1052IN_PROC_BROWSER_TEST_F(PanelBrowserTest, DrawAttentionBasic) {
1053  Panel* panel = CreateInactivePanel("P1");
1054  scoped_ptr<NativePanelTesting> native_panel_testing(
1055      CreateNativePanelTesting(panel));
1056
1057  // Test that the attention is drawn when the expanded panel is not in focus.
1058  EXPECT_EQ(Panel::EXPANDED, panel->expansion_state());
1059  EXPECT_FALSE(panel->IsActive());
1060  EXPECT_FALSE(panel->IsDrawingAttention());
1061  panel->FlashFrame(true);
1062  EXPECT_TRUE(panel->IsDrawingAttention());
1063  EXPECT_TRUE(native_panel_testing->VerifyDrawingAttention());
1064
1065  // Stop drawing attention.
1066  panel->FlashFrame(false);
1067  EXPECT_FALSE(panel->IsDrawingAttention());
1068  EXPECT_FALSE(native_panel_testing->VerifyDrawingAttention());
1069
1070  // Draw attention, then minimize. Titlebar should remain visible.
1071  panel->FlashFrame(true);
1072  EXPECT_TRUE(panel->IsDrawingAttention());
1073
1074  panel->Minimize();
1075  EXPECT_TRUE(panel->IsDrawingAttention());
1076  EXPECT_EQ(Panel::TITLE_ONLY, panel->expansion_state());
1077
1078  // Stop drawing attention. Titlebar should no longer be visible.
1079  panel->FlashFrame(false);
1080  EXPECT_FALSE(panel->IsDrawingAttention());
1081  EXPECT_EQ(Panel::MINIMIZED, panel->expansion_state());
1082
1083  panel->Close();
1084}
1085
1086IN_PROC_BROWSER_TEST_F(PanelBrowserTest, DrawAttentionWhileMinimized) {
1087  Panel* panel1 = CreateInactivePanel("P1");
1088  Panel* panel2 = CreateInactivePanel("P2");
1089
1090  scoped_ptr<NativePanelTesting> native_panel1_testing(
1091      CreateNativePanelTesting(panel1));
1092
1093  // Test that the attention is drawn and the title-bar is brought up when the
1094  // minimized panel is drawing attention.
1095  panel1->Minimize();
1096  EXPECT_EQ(Panel::MINIMIZED, panel1->expansion_state());
1097  panel1->FlashFrame(true);
1098  EXPECT_TRUE(panel1->IsDrawingAttention());
1099  EXPECT_EQ(Panel::TITLE_ONLY, panel1->expansion_state());
1100  EXPECT_TRUE(native_panel1_testing->VerifyDrawingAttention());
1101
1102  // Test that we cannot bring up other minimized panel if the mouse is over
1103  // the panel that draws attension.
1104  panel2->Minimize();
1105  gfx::Point hover_point(panel1->GetBounds().origin());
1106  MoveMouse(hover_point);
1107  EXPECT_EQ(Panel::TITLE_ONLY, panel1->expansion_state());
1108  EXPECT_EQ(Panel::MINIMIZED, panel2->expansion_state());
1109
1110  // Test that we cannot bring down the panel that is drawing the attention.
1111  hover_point.set_y(hover_point.y() - 200);
1112  MoveMouse(hover_point);
1113  EXPECT_EQ(Panel::TITLE_ONLY, panel1->expansion_state());
1114
1115  // Test that the attention is cleared when activated.
1116  panel1->Activate();
1117  WaitForPanelActiveState(panel1, SHOW_AS_ACTIVE);
1118  EXPECT_FALSE(panel1->IsDrawingAttention());
1119  EXPECT_EQ(Panel::EXPANDED, panel1->expansion_state());
1120  EXPECT_FALSE(native_panel1_testing->VerifyDrawingAttention());
1121
1122  PanelManager::GetInstance()->CloseAll();
1123}
1124
1125// Verify that minimized state of a panel is correct after draw attention
1126// is stopped when there are other minimized panels.
1127IN_PROC_BROWSER_TEST_F(PanelBrowserTest, StopDrawingAttentionWhileMinimized) {
1128  Panel* panel1 = CreateInactivePanel("P1");
1129  Panel* panel2 = CreateInactivePanel("P2");
1130
1131  panel1->Minimize();
1132  EXPECT_EQ(Panel::MINIMIZED, panel1->expansion_state());
1133  panel2->Minimize();
1134  EXPECT_EQ(Panel::MINIMIZED, panel2->expansion_state());
1135
1136  // Verify panel returns to minimized state when no longer drawing attention.
1137  panel1->FlashFrame(true);
1138  EXPECT_TRUE(panel1->IsDrawingAttention());
1139  EXPECT_EQ(Panel::TITLE_ONLY, panel1->expansion_state());
1140
1141  panel1->FlashFrame(false);
1142  EXPECT_FALSE(panel1->IsDrawingAttention());
1143  EXPECT_EQ(Panel::MINIMIZED, panel1->expansion_state());
1144
1145  // Hover over other minimized panel to bring up titlebars.
1146  gfx::Point hover_point(panel2->GetBounds().origin());
1147  MoveMouseAndWaitForExpansionStateChange(panel1, hover_point);
1148  EXPECT_EQ(Panel::TITLE_ONLY, panel1->expansion_state());
1149  EXPECT_EQ(Panel::TITLE_ONLY, panel2->expansion_state());
1150
1151  // Verify panel keeps titlebar visible when no longer drawing attention
1152  // if titlebars are up.
1153  panel1->FlashFrame(true);
1154  EXPECT_TRUE(panel1->IsDrawingAttention());
1155  EXPECT_EQ(Panel::TITLE_ONLY, panel1->expansion_state());
1156
1157  panel1->FlashFrame(false);
1158  EXPECT_FALSE(panel1->IsDrawingAttention());
1159  EXPECT_EQ(Panel::TITLE_ONLY, panel1->expansion_state());
1160
1161  // Move mouse away. All panels should return to minimized state.
1162  hover_point.set_y(hover_point.y() - 200);
1163  MoveMouseAndWaitForExpansionStateChange(panel1, hover_point);
1164  EXPECT_EQ(Panel::MINIMIZED, panel1->expansion_state());
1165  EXPECT_EQ(Panel::MINIMIZED, panel2->expansion_state());
1166
1167  // Verify minimized panel that is drawing attention stays in title-only mode
1168  // after attention is cleared if mouse is in the titlebar area.
1169  panel1->FlashFrame(true);
1170  EXPECT_TRUE(panel1->IsDrawingAttention());
1171  EXPECT_EQ(Panel::TITLE_ONLY, panel1->expansion_state());
1172
1173  gfx::Point hover_point_in_panel(panel1->GetBounds().origin());
1174  MoveMouse(hover_point_in_panel);
1175
1176  panel1->FlashFrame(false);
1177  EXPECT_FALSE(panel1->IsDrawingAttention());
1178  EXPECT_EQ(Panel::TITLE_ONLY, panel1->expansion_state());
1179  EXPECT_EQ(Panel::MINIMIZED, panel2->expansion_state());
1180
1181  // Typical user scenario will detect the mouse in the panel
1182  // after attention is cleared, causing titles to pop up, so
1183  // we simulate that here.
1184  MoveMouseAndWaitForExpansionStateChange(panel2, hover_point_in_panel);
1185  EXPECT_EQ(Panel::TITLE_ONLY, panel1->expansion_state());
1186  EXPECT_EQ(Panel::TITLE_ONLY, panel2->expansion_state());
1187
1188  // Move mouse away and panels should go back to fully minimized state.
1189  MoveMouseAndWaitForExpansionStateChange(panel1, hover_point);
1190  EXPECT_EQ(Panel::MINIMIZED, panel1->expansion_state());
1191  EXPECT_EQ(Panel::MINIMIZED, panel2->expansion_state());
1192
1193  PanelManager::GetInstance()->CloseAll();
1194}
1195
1196IN_PROC_BROWSER_TEST_F(PanelBrowserTest, DrawAttentionWhenActive) {
1197  // Create an active panel.
1198  Panel* panel = CreatePanel("P1");
1199  scoped_ptr<NativePanelTesting> native_panel_testing(
1200      CreateNativePanelTesting(panel));
1201
1202  // Test that the attention should not be drawn if the expanded panel is in
1203  // focus.
1204  panel->FlashFrame(true);
1205  EXPECT_FALSE(panel->IsDrawingAttention());
1206  EXPECT_FALSE(native_panel_testing->VerifyDrawingAttention());
1207
1208  panel->Close();
1209}
1210
1211IN_PROC_BROWSER_TEST_F(PanelBrowserTest, DrawAttentionResetOnActivate) {
1212  Panel* panel = CreateInactivePanel("P1");
1213  scoped_ptr<NativePanelTesting> native_panel_testing(
1214      CreateNativePanelTesting(panel));
1215
1216  panel->FlashFrame(true);
1217  EXPECT_TRUE(panel->IsDrawingAttention());
1218  EXPECT_TRUE(native_panel_testing->VerifyDrawingAttention());
1219
1220  // Test that the attention is cleared when panel gets focus.
1221  panel->Activate();
1222  WaitForPanelActiveState(panel, SHOW_AS_ACTIVE);
1223  EXPECT_FALSE(panel->IsDrawingAttention());
1224  EXPECT_FALSE(native_panel_testing->VerifyDrawingAttention());
1225
1226  panel->Close();
1227}
1228
1229IN_PROC_BROWSER_TEST_F(PanelBrowserTest,
1230                       DrawAttentionMinimizedNotResetOnActivate) {
1231  Panel* panel = CreateInactivePanel("P1");
1232
1233  panel->Minimize();
1234  EXPECT_TRUE(panel->IsMinimized());
1235  panel->FlashFrame(true);
1236  EXPECT_TRUE(panel->IsDrawingAttention());
1237
1238  // Simulate panel being activated while minimized. Cannot call
1239  // Activate() as that expands the panel.
1240  panel->OnActiveStateChanged(true);
1241  EXPECT_TRUE(panel->IsDrawingAttention());  // Unchanged.
1242
1243  // Unminimize panel to show that attention would have been cleared
1244  // if panel had not been minimized.
1245  panel->Restore();
1246  EXPECT_FALSE(panel->IsMinimized());
1247  EXPECT_TRUE(panel->IsDrawingAttention());  // Unchanged.
1248
1249  panel->OnActiveStateChanged(true);
1250  EXPECT_FALSE(panel->IsDrawingAttention());  // Attention cleared.
1251
1252  panel->Close();
1253}
1254
1255IN_PROC_BROWSER_TEST_F(PanelBrowserTest, DrawAttentionResetOnClick) {
1256  Panel* panel = CreateInactivePanel("P1");
1257  scoped_ptr<NativePanelTesting> native_panel_testing(
1258      CreateNativePanelTesting(panel));
1259
1260  panel->FlashFrame(true);
1261  EXPECT_TRUE(panel->IsDrawingAttention());
1262  EXPECT_TRUE(native_panel_testing->VerifyDrawingAttention());
1263
1264  // Test that the attention is cleared when panel gets focus.
1265  native_panel_testing->PressLeftMouseButtonTitlebar(
1266      panel->GetBounds().origin());
1267  native_panel_testing->ReleaseMouseButtonTitlebar();
1268
1269  WaitForPanelActiveState(panel, SHOW_AS_ACTIVE);
1270  EXPECT_FALSE(panel->IsDrawingAttention());
1271  EXPECT_FALSE(native_panel_testing->VerifyDrawingAttention());
1272
1273  panel->Close();
1274}
1275
1276// http://crbug.com/175760; several panel tests failing regularly on mac.
1277#if defined(OS_MACOSX)
1278#define MAYBE_MinimizeImmediatelyAfterRestore \
1279  DISABLED_MinimizeImmediatelyAfterRestore
1280#else
1281#define MAYBE_MinimizeImmediatelyAfterRestore MinimizeImmediatelyAfterRestore
1282#endif
1283IN_PROC_BROWSER_TEST_F(PanelBrowserTest,
1284                       MAYBE_MinimizeImmediatelyAfterRestore) {
1285  CreatePanelParams params("Panel Test", gfx::Rect(), SHOW_AS_ACTIVE);
1286  Panel* panel = CreatePanelWithParams(params);
1287  scoped_ptr<NativePanelTesting> native_panel_testing(
1288      CreateNativePanelTesting(panel));
1289
1290  PanelActiveStateObserver signal(panel, false);
1291  panel->Minimize();  // this should deactivate.
1292  signal.Wait();
1293  EXPECT_EQ(Panel::MINIMIZED, panel->expansion_state());
1294
1295  panel->Restore();
1296  EXPECT_EQ(Panel::EXPANDED, panel->expansion_state());
1297
1298  // Verify that minimizing a panel right after expansion works.
1299  panel->Minimize();
1300  EXPECT_EQ(Panel::MINIMIZED, panel->expansion_state());
1301
1302  panel->Close();
1303}
1304
1305IN_PROC_BROWSER_TEST_F(PanelBrowserTest, FocusLostOnMinimize) {
1306  CreatePanelParams params("Initially Active", gfx::Rect(), SHOW_AS_ACTIVE);
1307  Panel* panel = CreatePanelWithParams(params);
1308  EXPECT_EQ(Panel::EXPANDED, panel->expansion_state());
1309
1310  PanelActiveStateObserver signal(panel, false);
1311  panel->Minimize();
1312  signal.Wait();
1313  panel->Close();
1314}
1315
1316IN_PROC_BROWSER_TEST_F(PanelBrowserTest, CreateInactiveSwitchToActive) {
1317  Panel* panel = CreateInactivePanel("1");
1318
1319  panel->Activate();
1320  WaitForPanelActiveState(panel, SHOW_AS_ACTIVE);
1321
1322  panel->Close();
1323}
1324
1325// TODO(dimich): try/enable on other platforms. See bug 103253 for details on
1326// why this is disabled on windows.
1327#if defined(OS_MACOSX)
1328#define MAYBE_MinimizeTwoPanelsWithoutTabbedWindow \
1329    MinimizeTwoPanelsWithoutTabbedWindow
1330#else
1331#define MAYBE_MinimizeTwoPanelsWithoutTabbedWindow \
1332    DISABLED_MinimizeTwoPanelsWithoutTabbedWindow
1333#endif
1334
1335// When there are 2 panels and no chrome window, minimizing one panel does
1336// not expand/focuses another.
1337IN_PROC_BROWSER_TEST_F(PanelBrowserTest,
1338                       MAYBE_MinimizeTwoPanelsWithoutTabbedWindow) {
1339  CreatePanelParams params("Initially Inactive", gfx::Rect(), SHOW_AS_INACTIVE);
1340  Panel* panel1 = CreatePanelWithParams(params);
1341  Panel* panel2 = CreatePanelWithParams(params);
1342
1343  // Close main tabbed window.
1344  content::WindowedNotificationObserver signal(
1345      chrome::NOTIFICATION_BROWSER_CLOSED,
1346      content::Source<Browser>(browser()));
1347  chrome::CloseWindow(browser());
1348  signal.Wait();
1349
1350  EXPECT_EQ(Panel::EXPANDED, panel1->expansion_state());
1351  EXPECT_EQ(Panel::EXPANDED, panel2->expansion_state());
1352  panel1->Activate();
1353  WaitForPanelActiveState(panel1, SHOW_AS_ACTIVE);
1354
1355  panel1->SetExpansionState(Panel::MINIMIZED);
1356  base::MessageLoop::current()->RunUntilIdle();
1357  WaitForPanelActiveState(panel1, SHOW_AS_INACTIVE);
1358  EXPECT_EQ(Panel::MINIMIZED, panel1->expansion_state());
1359
1360  panel2->SetExpansionState(Panel::MINIMIZED);
1361  base::MessageLoop::current()->RunUntilIdle();
1362  WaitForPanelActiveState(panel2, SHOW_AS_INACTIVE);
1363  EXPECT_EQ(Panel::MINIMIZED, panel2->expansion_state());
1364
1365  // Verify that panel1 is still minimized and not active.
1366  WaitForPanelActiveState(panel1, SHOW_AS_INACTIVE);
1367  EXPECT_EQ(Panel::MINIMIZED, panel1->expansion_state());
1368
1369  // Another check for the same.
1370  EXPECT_FALSE(panel1->IsActive());
1371  EXPECT_FALSE(panel2->IsActive());
1372
1373  panel1->Close();
1374  panel2->Close();
1375}
1376
1377IN_PROC_BROWSER_TEST_F(PanelBrowserTest,
1378                       NonExtensionDomainPanelsCloseOnUninstall) {
1379  // Create a test extension.
1380  base::DictionaryValue empty_value;
1381  scoped_refptr<extensions::Extension> extension =
1382      CreateExtension(FILE_PATH_LITERAL("TestExtension"),
1383                      extensions::Manifest::INTERNAL, empty_value);
1384  std::string extension_app_name =
1385      web_app::GenerateApplicationNameFromExtensionId(extension->id());
1386
1387  PanelManager* panel_manager = PanelManager::GetInstance();
1388  EXPECT_EQ(0, panel_manager->num_panels());
1389
1390  // Create a panel with the extension as host.
1391  CreatePanelParams params(extension_app_name, gfx::Rect(), SHOW_AS_ACTIVE);
1392  std::string extension_domain_url(extensions::kExtensionScheme);
1393  extension_domain_url += "://";
1394  extension_domain_url += extension->id();
1395  extension_domain_url += "/hello.html";
1396  params.url = GURL(extension_domain_url);
1397  Panel* panel = CreatePanelWithParams(params);
1398  EXPECT_EQ(1, panel_manager->num_panels());
1399
1400  // Create a panel with a non-extension host.
1401  CreatePanelParams params1(extension_app_name, gfx::Rect(), SHOW_AS_ACTIVE);
1402  params1.url = GURL(url::kAboutBlankURL);
1403  Panel* panel1 = CreatePanelWithParams(params1);
1404  EXPECT_EQ(2, panel_manager->num_panels());
1405
1406  // Create another extension and a panel from that extension.
1407  scoped_refptr<extensions::Extension> extension_other =
1408      CreateExtension(FILE_PATH_LITERAL("TestExtensionOther"),
1409                      extensions::Manifest::INTERNAL, empty_value);
1410  std::string extension_app_name_other =
1411      web_app::GenerateApplicationNameFromExtensionId(extension_other->id());
1412  Panel* panel_other = CreatePanel(extension_app_name_other);
1413
1414  content::WindowedNotificationObserver signal(
1415      chrome::NOTIFICATION_PANEL_CLOSED,
1416      content::Source<Panel>(panel));
1417  content::WindowedNotificationObserver signal1(
1418      chrome::NOTIFICATION_PANEL_CLOSED,
1419      content::Source<Panel>(panel1));
1420
1421  // Send unload notification on the first extension.
1422  extensions::ExtensionRegistry* registry =
1423      extensions::ExtensionRegistry::Get(browser()->profile());
1424  registry->RemoveEnabled(extension->id());
1425  registry->TriggerOnUnloaded(
1426      extension.get(), extensions::UnloadedExtensionInfo::REASON_UNINSTALL);
1427
1428  // Wait for the panels opened by the first extension to close.
1429  signal.Wait();
1430  signal1.Wait();
1431
1432  // Verify that the panel that's left is the panel from the second extension.
1433  EXPECT_EQ(panel_other, panel_manager->panels()[0]);
1434  panel_other->Close();
1435}
1436
1437IN_PROC_BROWSER_TEST_F(PanelBrowserTest, OnBeforeUnloadOnClose) {
1438  PanelManager* panel_manager = PanelManager::GetInstance();
1439  EXPECT_EQ(0, panel_manager->num_panels()); // No panels initially.
1440
1441  const base::string16 title_first_close = base::UTF8ToUTF16("TitleFirstClose");
1442  const base::string16 title_second_close =
1443      base::UTF8ToUTF16("TitleSecondClose");
1444
1445  // Create a test panel with web contents loaded.
1446  CreatePanelParams params("PanelTest1", gfx::Rect(0, 0, 300, 300),
1447                           SHOW_AS_ACTIVE);
1448  params.url = ui_test_utils::GetTestUrl(
1449      base::FilePath(kTestDir),
1450      base::FilePath(FILE_PATH_LITERAL("onbeforeunload.html")));
1451  Panel* panel = CreatePanelWithParams(params);
1452  EXPECT_EQ(1, panel_manager->num_panels());
1453
1454  // Close panel and verify it closes despite having a onbeforeunload handler.
1455  CloseWindowAndWait(panel);
1456  EXPECT_EQ(0, panel_manager->num_panels());
1457}
1458
1459// http://crbug.com/175760; several panel tests failing regularly on mac.
1460#if defined(OS_MACOSX)
1461#define MAYBE_SizeClamping DISABLED_SizeClamping
1462#else
1463#define MAYBE_SizeClamping SizeClamping
1464#endif
1465IN_PROC_BROWSER_TEST_F(PanelBrowserTest, MAYBE_SizeClamping) {
1466  // Using '0' sizes is equivalent of not providing sizes in API and causes
1467  // minimum sizes to be applied to facilitate auto-sizing.
1468  CreatePanelParams params("Panel", gfx::Rect(), SHOW_AS_ACTIVE);
1469  Panel* panel = CreatePanelWithParams(params);
1470  EXPECT_EQ(panel->min_size().width(), panel->GetBounds().width());
1471  EXPECT_EQ(panel->min_size().height(), panel->GetBounds().height());
1472  int reasonable_width = panel->min_size().width() + 10;
1473  int reasonable_height = panel->min_size().height() + 20;
1474
1475  panel->Close();
1476
1477  // Using reasonable actual sizes should avoid clamping.
1478  CreatePanelParams params1("Panel1",
1479                            gfx::Rect(0, 0,
1480                                      reasonable_width, reasonable_height),
1481                            SHOW_AS_ACTIVE);
1482  panel = CreatePanelWithParams(params1);
1483  EXPECT_EQ(reasonable_width, panel->GetBounds().width());
1484  EXPECT_EQ(reasonable_height, panel->GetBounds().height());
1485  panel->Close();
1486
1487  // Using just one size should auto-compute some reasonable other size.
1488  int given_height = 200;
1489  CreatePanelParams params2("Panel2", gfx::Rect(0, 0, 0, given_height),
1490                            SHOW_AS_ACTIVE);
1491  panel = CreatePanelWithParams(params2);
1492  EXPECT_GT(panel->GetBounds().width(), 0);
1493  EXPECT_EQ(given_height, panel->GetBounds().height());
1494  panel->Close();
1495}
1496
1497// http://crbug.com/175760; several panel tests failing regularly on mac.
1498// http://crbug.com/179890; TightAutosizeAroundSingleLine broken on Windows by
1499IN_PROC_BROWSER_TEST_F(PanelBrowserTest,
1500                       DISABLED_TightAutosizeAroundSingleLine) {
1501  PanelManager::GetInstance()->enable_auto_sizing(true);
1502  // Using 0 sizes triggers auto-sizing.
1503  CreatePanelParams params("Panel", gfx::Rect(), SHOW_AS_ACTIVE);
1504  params.url = GURL("data:text/html;charset=utf-8,<!doctype html><body>");
1505  Panel* panel = CreatePanelWithParams(params);
1506
1507  // Ensure panel has auto resized to original web content size.
1508  WaitForStableInitialSize initial_resize(panel);
1509  initial_resize.Wait();
1510
1511  int initial_width = panel->GetBounds().width();
1512  int initial_height = panel->GetBounds().height();
1513
1514  // Inject some HTML content into the panel.
1515  WaitForAutoResizeWider enlarge(panel);
1516  EXPECT_TRUE(content::ExecuteScript(
1517      panel->GetWebContents(),
1518      "document.body.innerHTML ="
1519      "    '<nobr>line of text and a <button>Button</button>';"));
1520  enlarge.Wait();
1521
1522  // The panel should have become larger in both dimensions (the minimums
1523  // has to be set to be smaller then a simple 1-line content, so the autosize
1524  // can work correctly.
1525  EXPECT_GT(panel->GetBounds().width(), initial_width);
1526  EXPECT_GT(panel->GetBounds().height(), initial_height);
1527
1528  panel->Close();
1529}
1530
1531// http://crbug.com/175760; several panel tests failing regularly on mac.
1532#if defined(OS_MACOSX)
1533#define MAYBE_DefaultMaxSizeOnDisplaySettingsChange \
1534        DISABLED_DefaultMaxSizeOnDisplaySettingsChange
1535#else
1536#define MAYBE_DefaultMaxSizeOnDisplaySettingsChange \
1537        DefaultMaxSizeOnDisplaySettingsChange
1538#endif
1539IN_PROC_BROWSER_TEST_F(PanelBrowserTest,
1540                       MAYBE_DefaultMaxSizeOnDisplaySettingsChange) {
1541  Panel* panel = CreatePanelWithBounds("1", gfx::Rect(0, 0, 240, 220));
1542
1543  gfx::Size old_max_size = panel->max_size();
1544  gfx::Size old_full_size = panel->full_size();
1545
1546  // Shrink the work area. Expect max size and full size become smaller.
1547  gfx::Rect smaller_work_area(0, 0, 500, 300);
1548  mock_display_settings_provider()->SetPrimaryDisplay(
1549      smaller_work_area, smaller_work_area);
1550  EXPECT_GT(old_max_size.width(), panel->max_size().width());
1551  EXPECT_GT(old_max_size.height(), panel->max_size().height());
1552  EXPECT_GT(smaller_work_area.width(), panel->max_size().width());
1553  EXPECT_GT(smaller_work_area.height(), panel->max_size().height());
1554  EXPECT_GT(old_full_size.width(), panel->full_size().width());
1555  EXPECT_GT(old_full_size.height(), panel->full_size().height());
1556  EXPECT_GE(panel->max_size().width(), panel->full_size().width());
1557  EXPECT_GE(panel->max_size().height(), panel->full_size().height());
1558
1559  panel->Close();
1560}
1561
1562// http://crbug.com/175760; several panel tests failing regularly on mac.
1563#if defined(OS_MACOSX)
1564#define MAYBE_CustomMaxSizeOnDisplaySettingsChange \
1565        DISABLED_CustomMaxSizeOnDisplaySettingsChange
1566#else
1567#define MAYBE_CustomMaxSizeOnDisplaySettingsChange \
1568        CustomMaxSizeOnDisplaySettingsChange
1569#endif
1570IN_PROC_BROWSER_TEST_F(PanelBrowserTest,
1571                       MAYBE_CustomMaxSizeOnDisplaySettingsChange) {
1572  PanelManager* panel_manager = PanelManager::GetInstance();
1573  Panel* panel = CreatePanelWithBounds("1", gfx::Rect(0, 0, 240, 220));
1574
1575  // Trigger custom max size by user resizing.
1576  gfx::Size bigger_size = gfx::Size(550, 400);
1577  gfx::Point mouse_location = panel->GetBounds().origin();
1578  panel_manager->StartResizingByMouse(panel,
1579                                      mouse_location,
1580                                      HTTOPLEFT);
1581  mouse_location.Offset(panel->GetBounds().width() - bigger_size.width(),
1582                        panel->GetBounds().height() - bigger_size.height());
1583  panel_manager->ResizeByMouse(mouse_location);
1584  panel_manager->EndResizingByMouse(false);
1585
1586  gfx::Size old_max_size = panel->max_size();
1587  EXPECT_EQ(bigger_size, old_max_size);
1588  gfx::Size old_full_size = panel->full_size();
1589  EXPECT_EQ(bigger_size, old_full_size);
1590
1591  // Shrink the work area. Expect max size and full size become smaller.
1592  gfx::Rect smaller_work_area(0, 0, 500, 300);
1593  mock_display_settings_provider()->SetPrimaryDisplay(
1594      smaller_work_area, smaller_work_area);
1595  EXPECT_GT(old_max_size.width(), panel->max_size().width());
1596  EXPECT_GT(old_max_size.height(), panel->max_size().height());
1597  EXPECT_GE(smaller_work_area.width(), panel->max_size().width());
1598  EXPECT_EQ(smaller_work_area.height(), panel->max_size().height());
1599  EXPECT_GT(old_full_size.width(), panel->full_size().width());
1600  EXPECT_GT(old_full_size.height(), panel->full_size().height());
1601  EXPECT_GE(panel->max_size().width(), panel->full_size().width());
1602  EXPECT_GE(panel->max_size().height(), panel->full_size().height());
1603  EXPECT_EQ(smaller_work_area.height(), panel->full_size().height());
1604
1605  panel->Close();
1606}
1607
1608IN_PROC_BROWSER_TEST_F(PanelBrowserTest, DevTools) {
1609  // Create a test panel with web contents loaded.
1610  CreatePanelParams params("1", gfx::Rect(0, 0, 200, 220), SHOW_AS_ACTIVE);
1611  GURL url(ui_test_utils::GetTestUrl(
1612      base::FilePath(kTestDir),
1613      base::FilePath(FILE_PATH_LITERAL("update-preferred-size.html"))));
1614  params.url = url;
1615  Panel* panel = CreatePanelWithParams(params);
1616
1617  // Open devtools.
1618  size_t num_browsers = 1;
1619  EXPECT_EQ(num_browsers, chrome::GetBrowserCount(
1620                              browser()->profile(),
1621                              browser()->host_desktop_type()));
1622  content::WindowedNotificationObserver signal(
1623      chrome::NOTIFICATION_BROWSER_WINDOW_READY,
1624      content::NotificationService::AllSources());
1625  EXPECT_TRUE(panel->ExecuteCommandIfEnabled(IDC_DEV_TOOLS));
1626  signal.Wait();
1627
1628  // Check that the new browser window that opened is dev tools window.
1629  ++num_browsers;
1630  EXPECT_EQ(num_browsers, chrome::GetBrowserCount(
1631                              browser()->profile(),
1632                              browser()->host_desktop_type()));
1633  for (chrome::BrowserIterator iter; !iter.done(); iter.Next()) {
1634    if (*iter == browser())
1635      continue;
1636    ASSERT_TRUE((*iter)->is_devtools());
1637  }
1638
1639  panel->Close();
1640}
1641
1642IN_PROC_BROWSER_TEST_F(PanelBrowserTest, DevToolsConsole) {
1643  // Create a test panel with web contents loaded.
1644  CreatePanelParams params("1", gfx::Rect(0, 0, 200, 220), SHOW_AS_ACTIVE);
1645  GURL url(ui_test_utils::GetTestUrl(
1646      base::FilePath(kTestDir),
1647      base::FilePath(FILE_PATH_LITERAL("update-preferred-size.html"))));
1648  params.url = url;
1649  Panel* panel = CreatePanelWithParams(params);
1650
1651  // Open devtools console.
1652  size_t num_browsers = 1;
1653  EXPECT_EQ(num_browsers, chrome::GetBrowserCount(
1654                              browser()->profile(),
1655                              browser()->host_desktop_type()));
1656  content::WindowedNotificationObserver signal(
1657      chrome::NOTIFICATION_BROWSER_WINDOW_READY,
1658      content::NotificationService::AllSources());
1659  EXPECT_TRUE(panel->ExecuteCommandIfEnabled(IDC_DEV_TOOLS_CONSOLE));
1660  signal.Wait();
1661
1662  // Check that the new browser window that opened is dev tools window.
1663  ++num_browsers;
1664  EXPECT_EQ(num_browsers, chrome::GetBrowserCount(
1665                              browser()->profile(),
1666                              browser()->host_desktop_type()));
1667  for (chrome::BrowserIterator iter; !iter.done(); iter.Next()) {
1668    if (*iter == browser())
1669      continue;
1670    ASSERT_TRUE((*iter)->is_devtools());
1671  }
1672
1673  panel->Close();
1674}
1675
1676#if defined(OS_WIN)
1677#define MAYBE_Accelerator Accelerator
1678#else
1679#define MAYBE_Accelerator DISABLED_Accelerator
1680#endif
1681IN_PROC_BROWSER_TEST_F(PanelBrowserTest, MAYBE_Accelerator) {
1682  PanelManager* panel_manager = PanelManager::GetInstance();
1683
1684  // Create a test panel with web contents loaded.
1685  CreatePanelParams params("1", gfx::Rect(), SHOW_AS_ACTIVE);
1686  GURL url(ui_test_utils::GetTestUrl(
1687      base::FilePath(kTestDir),
1688      base::FilePath(FILE_PATH_LITERAL("update-preferred-size.html"))));
1689  params.url = url;
1690  Panel* panel = CreatePanelWithParams(params);
1691  EXPECT_EQ(1, panel_manager->num_panels());
1692
1693  // Close the panel by acclerator.
1694  content::WindowedNotificationObserver signal(
1695      chrome::NOTIFICATION_PANEL_CLOSED,
1696      content::Source<Panel>(panel));
1697#if defined(USE_AURA)
1698  double now = ui::EventTimeForNow().InSecondsF();
1699  content::NativeWebKeyboardEvent key_event(
1700      ui::ET_KEY_PRESSED,
1701      false,
1702      ui::VKEY_W,
1703      ui::EF_CONTROL_DOWN,
1704      now);
1705#elif defined(OS_WIN)
1706  ::MSG key_msg = { NULL, WM_KEYDOWN, ui::VKEY_W, 0 };
1707  content::NativeWebKeyboardEvent key_event(key_msg);
1708  key_event.modifiers = content::NativeWebKeyboardEvent::ControlKey;
1709#else
1710  content::NativeWebKeyboardEvent key_event;
1711#endif
1712  panel->HandleKeyboardEvent(key_event);
1713  signal.Wait();
1714  EXPECT_EQ(0, panel_manager->num_panels());
1715}
1716
1717IN_PROC_BROWSER_TEST_F(PanelBrowserTest,
1718                       HideDockedPanelCreatedBeforeFullScreenMode) {
1719  // Create a docked panel.
1720  Panel* panel = CreatePanel("PanelTest");
1721  scoped_ptr<NativePanelTesting> panel_testing(CreateNativePanelTesting(panel));
1722
1723  // Panel should be visible at first.
1724  EXPECT_TRUE(panel_testing->IsWindowVisible());
1725
1726  // Panel should become hidden when entering full-screen mode.
1727  mock_display_settings_provider()->EnableFullScreenMode(true);
1728  EXPECT_FALSE(panel_testing->IsWindowVisible());
1729
1730  // Panel should become visible when leaving full-screen mode.
1731  mock_display_settings_provider()->EnableFullScreenMode(false);
1732  EXPECT_TRUE(panel_testing->IsWindowVisible());
1733
1734  PanelManager::GetInstance()->CloseAll();
1735}
1736
1737IN_PROC_BROWSER_TEST_F(PanelBrowserTest,
1738                       HideDockedPanelCreatedOnFullScreenMode) {
1739  // Enable full-screen mode first.
1740  mock_display_settings_provider()->EnableFullScreenMode(true);
1741
1742  // Create a docked panel without waiting for it to be shown since it is not
1743  // supposed to be shown on full-screen mode.
1744  CreatePanelParams params("1", gfx::Rect(0, 0, 250, 200), SHOW_AS_ACTIVE);
1745  params.wait_for_fully_created = false;
1746  Panel* panel = CreatePanelWithParams(params);
1747  scoped_ptr<NativePanelTesting> panel_testing(
1748      CreateNativePanelTesting(panel));
1749
1750  // Panel should not be shown on full-screen mode.
1751  EXPECT_FALSE(panel_testing->IsWindowVisible());
1752
1753  // Panel should become visible when leaving full-screen mode.
1754  mock_display_settings_provider()->EnableFullScreenMode(false);
1755  EXPECT_TRUE(panel_testing->IsWindowVisible());
1756
1757  PanelManager::GetInstance()->CloseAll();
1758}
1759
1760class PanelExtensionApiTest : public ExtensionApiTest {
1761 protected:
1762  virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE {
1763    ExtensionApiTest::SetUpCommandLine(command_line);
1764    command_line->AppendSwitch(switches::kEnablePanels);
1765  }
1766};
1767
1768#if defined(OS_LINUX) || (!defined(OS_WIN) && defined(USE_AURA)) || \
1769    defined(OS_MACOSX)
1770// Focus test fails if there is no window manager on Linux.
1771// Aura panels have different behavior that do not apply to this test.
1772#define MAYBE_FocusChangeEventOnMinimize DISABLED_FocusChangeEventOnMinimize
1773#else
1774#define MAYBE_FocusChangeEventOnMinimize FocusChangeEventOnMinimize
1775#endif
1776IN_PROC_BROWSER_TEST_F(PanelExtensionApiTest,
1777                       MAYBE_FocusChangeEventOnMinimize) {
1778  // This is needed so the subsequently created panels can be activated.
1779  // On a Mac, it transforms background-only test process into foreground one.
1780  ASSERT_TRUE(ui_test_utils::BringBrowserWindowToFront(browser()));
1781  ASSERT_TRUE(RunExtensionTest("panels/focus_change_on_minimize")) << message_;
1782}
1783