Home | History | Annotate | Download | only in widget
      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 <algorithm>
      6 #include <set>
      7 
      8 #include "base/basictypes.h"
      9 #include "base/bind.h"
     10 #include "base/memory/scoped_ptr.h"
     11 #include "base/message_loop/message_loop.h"
     12 #include "base/run_loop.h"
     13 #include "base/strings/utf_string_conversions.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 #include "ui/aura/test/event_generator.h"
     16 #include "ui/aura/window.h"
     17 #include "ui/base/hit_test.h"
     18 #include "ui/compositor/scoped_animation_duration_scale_mode.h"
     19 #include "ui/compositor/scoped_layer_animation_settings.h"
     20 #include "ui/events/event_processor.h"
     21 #include "ui/events/event_utils.h"
     22 #include "ui/gfx/native_widget_types.h"
     23 #include "ui/gfx/point.h"
     24 #include "ui/views/bubble/bubble_delegate.h"
     25 #include "ui/views/controls/textfield/textfield.h"
     26 #include "ui/views/test/test_views_delegate.h"
     27 #include "ui/views/test/widget_test.h"
     28 #include "ui/views/views_delegate.h"
     29 #include "ui/views/widget/native_widget_delegate.h"
     30 #include "ui/views/widget/root_view.h"
     31 #include "ui/views/widget/widget_deletion_observer.h"
     32 #include "ui/views/window/dialog_delegate.h"
     33 #include "ui/views/window/native_frame_view.h"
     34 
     35 #if defined(OS_WIN)
     36 #include "ui/views/win/hwnd_util.h"
     37 #endif
     38 
     39 namespace views {
     40 namespace test {
     41 
     42 // A view that keeps track of the events it receives, but consumes no events.
     43 class EventCountView : public View {
     44  public:
     45   EventCountView() {}
     46   virtual ~EventCountView() {}
     47 
     48   int GetEventCount(ui::EventType type) {
     49     return event_count_[type];
     50   }
     51 
     52   void ResetCounts() {
     53     event_count_.clear();
     54   }
     55 
     56  protected:
     57   // Overridden from ui::EventHandler:
     58   virtual void OnKeyEvent(ui::KeyEvent* event) OVERRIDE {
     59     RecordEvent(*event);
     60   }
     61   virtual void OnMouseEvent(ui::MouseEvent* event) OVERRIDE {
     62     RecordEvent(*event);
     63   }
     64   virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE {
     65     RecordEvent(*event);
     66   }
     67   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
     68     RecordEvent(*event);
     69   }
     70 
     71  private:
     72   void RecordEvent(const ui::Event& event) {
     73     ++event_count_[event.type()];
     74   }
     75 
     76   std::map<ui::EventType, int> event_count_;
     77 
     78   DISALLOW_COPY_AND_ASSIGN(EventCountView);
     79 };
     80 
     81 // A view that keeps track of the events it receives, and consumes all scroll
     82 // gesture events and ui::ET_SCROLL events.
     83 class ScrollableEventCountView : public EventCountView {
     84  public:
     85   ScrollableEventCountView() {}
     86   virtual ~ScrollableEventCountView() {}
     87 
     88  private:
     89   // Overridden from ui::EventHandler:
     90   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
     91     EventCountView::OnGestureEvent(event);
     92     switch (event->type()) {
     93       case ui::ET_GESTURE_SCROLL_BEGIN:
     94       case ui::ET_GESTURE_SCROLL_UPDATE:
     95       case ui::ET_GESTURE_SCROLL_END:
     96       case ui::ET_SCROLL_FLING_START:
     97         event->SetHandled();
     98         break;
     99       default:
    100         break;
    101     }
    102   }
    103 
    104   virtual void OnScrollEvent(ui::ScrollEvent* event) OVERRIDE {
    105     EventCountView::OnScrollEvent(event);
    106     if (event->type() == ui::ET_SCROLL)
    107       event->SetHandled();
    108   }
    109 
    110   DISALLOW_COPY_AND_ASSIGN(ScrollableEventCountView);
    111 };
    112 
    113 // A view that implements GetMinimumSize.
    114 class MinimumSizeFrameView : public NativeFrameView {
    115  public:
    116   explicit MinimumSizeFrameView(Widget* frame): NativeFrameView(frame) {}
    117   virtual ~MinimumSizeFrameView() {}
    118 
    119  private:
    120   // Overridden from View:
    121   virtual gfx::Size GetMinimumSize() const OVERRIDE {
    122     return gfx::Size(300, 400);
    123   }
    124 
    125   DISALLOW_COPY_AND_ASSIGN(MinimumSizeFrameView);
    126 };
    127 
    128 // An event handler that simply keeps a count of the different types of events
    129 // it receives.
    130 class EventCountHandler : public ui::EventHandler {
    131  public:
    132   EventCountHandler() {}
    133   virtual ~EventCountHandler() {}
    134 
    135   int GetEventCount(ui::EventType type) {
    136     return event_count_[type];
    137   }
    138 
    139   void ResetCounts() {
    140     event_count_.clear();
    141   }
    142 
    143  protected:
    144   // Overridden from ui::EventHandler:
    145   virtual void OnEvent(ui::Event* event) OVERRIDE {
    146     RecordEvent(*event);
    147     ui::EventHandler::OnEvent(event);
    148   }
    149 
    150  private:
    151   void RecordEvent(const ui::Event& event) {
    152     ++event_count_[event.type()];
    153   }
    154 
    155   std::map<ui::EventType, int> event_count_;
    156 
    157   DISALLOW_COPY_AND_ASSIGN(EventCountHandler);
    158 };
    159 
    160 // Class that closes the widget (which ends up deleting it immediately) when the
    161 // appropriate event is received.
    162 class CloseWidgetView : public View {
    163  public:
    164   explicit CloseWidgetView(ui::EventType event_type)
    165       : event_type_(event_type) {
    166   }
    167 
    168   // ui::EventHandler override:
    169   virtual void OnEvent(ui::Event* event) OVERRIDE {
    170     if (event->type() == event_type_) {
    171       // Go through NativeWidgetPrivate to simulate what happens if the OS
    172       // deletes the NativeWindow out from under us.
    173       GetWidget()->native_widget_private()->CloseNow();
    174     } else {
    175       View::OnEvent(event);
    176       if (!event->IsTouchEvent())
    177         event->SetHandled();
    178     }
    179   }
    180 
    181  private:
    182   const ui::EventType event_type_;
    183 
    184   DISALLOW_COPY_AND_ASSIGN(CloseWidgetView);
    185 };
    186 
    187 ui::WindowShowState GetWidgetShowState(const Widget* widget) {
    188   // Use IsMaximized/IsMinimized/IsFullScreen instead of GetWindowPlacement
    189   // because the former is implemented on all platforms but the latter is not.
    190   return widget->IsFullscreen() ? ui::SHOW_STATE_FULLSCREEN :
    191       widget->IsMaximized() ? ui::SHOW_STATE_MAXIMIZED :
    192       widget->IsMinimized() ? ui::SHOW_STATE_MINIMIZED :
    193       widget->IsActive() ? ui::SHOW_STATE_NORMAL :
    194                            ui::SHOW_STATE_INACTIVE;
    195 }
    196 
    197 TEST_F(WidgetTest, WidgetInitParams) {
    198   // Widgets are not transparent by default.
    199   Widget::InitParams init1;
    200   EXPECT_EQ(Widget::InitParams::INFER_OPACITY, init1.opacity);
    201 }
    202 
    203 ////////////////////////////////////////////////////////////////////////////////
    204 // Widget::GetTopLevelWidget tests.
    205 
    206 TEST_F(WidgetTest, GetTopLevelWidget_Native) {
    207   // Create a hierarchy of native widgets.
    208   Widget* toplevel = CreateTopLevelPlatformWidget();
    209   gfx::NativeView parent = toplevel->GetNativeView();
    210   Widget* child = CreateChildPlatformWidget(parent);
    211 
    212   EXPECT_EQ(toplevel, toplevel->GetTopLevelWidget());
    213   EXPECT_EQ(toplevel, child->GetTopLevelWidget());
    214 
    215   toplevel->CloseNow();
    216   // |child| should be automatically destroyed with |toplevel|.
    217 }
    218 
    219 // Test if a focus manager and an inputmethod work without CHECK failure
    220 // when window activation changes.
    221 TEST_F(WidgetTest, ChangeActivation) {
    222   Widget* top1 = CreateTopLevelPlatformWidget();
    223   // CreateInputMethod before activated
    224   top1->GetInputMethod();
    225   top1->Show();
    226   RunPendingMessages();
    227 
    228   Widget* top2 = CreateTopLevelPlatformWidget();
    229   top2->Show();
    230   RunPendingMessages();
    231 
    232   top1->Activate();
    233   RunPendingMessages();
    234 
    235   // Create InputMethod after deactivated.
    236   top2->GetInputMethod();
    237   top2->Activate();
    238   RunPendingMessages();
    239 
    240   top1->Activate();
    241   RunPendingMessages();
    242 
    243   top1->CloseNow();
    244   top2->CloseNow();
    245 }
    246 
    247 // Tests visibility of child widgets.
    248 TEST_F(WidgetTest, Visibility) {
    249   Widget* toplevel = CreateTopLevelPlatformWidget();
    250   gfx::NativeView parent = toplevel->GetNativeView();
    251   Widget* child = CreateChildPlatformWidget(parent);
    252 
    253   EXPECT_FALSE(toplevel->IsVisible());
    254   EXPECT_FALSE(child->IsVisible());
    255 
    256   child->Show();
    257 
    258   EXPECT_FALSE(toplevel->IsVisible());
    259   EXPECT_FALSE(child->IsVisible());
    260 
    261   toplevel->Show();
    262 
    263   EXPECT_TRUE(toplevel->IsVisible());
    264   EXPECT_TRUE(child->IsVisible());
    265 
    266   toplevel->CloseNow();
    267   // |child| should be automatically destroyed with |toplevel|.
    268 }
    269 
    270 ////////////////////////////////////////////////////////////////////////////////
    271 // Widget ownership tests.
    272 //
    273 // Tests various permutations of Widget ownership specified in the
    274 // InitParams::Ownership param.
    275 
    276 // A WidgetTest that supplies a toplevel widget for NativeWidget to parent to.
    277 class WidgetOwnershipTest : public WidgetTest {
    278  public:
    279   WidgetOwnershipTest() {}
    280   virtual ~WidgetOwnershipTest() {}
    281 
    282   virtual void SetUp() {
    283     WidgetTest::SetUp();
    284     desktop_widget_ = CreateTopLevelPlatformWidget();
    285   }
    286 
    287   virtual void TearDown() {
    288     desktop_widget_->CloseNow();
    289     WidgetTest::TearDown();
    290   }
    291 
    292  private:
    293   Widget* desktop_widget_;
    294 
    295   DISALLOW_COPY_AND_ASSIGN(WidgetOwnershipTest);
    296 };
    297 
    298 // A bag of state to monitor destructions.
    299 struct OwnershipTestState {
    300   OwnershipTestState() : widget_deleted(false), native_widget_deleted(false) {}
    301 
    302   bool widget_deleted;
    303   bool native_widget_deleted;
    304 };
    305 
    306 // A platform NativeWidget subclass that updates a bag of state when it is
    307 // destroyed.
    308 class OwnershipTestNativeWidget : public PlatformNativeWidget {
    309  public:
    310   OwnershipTestNativeWidget(internal::NativeWidgetDelegate* delegate,
    311                             OwnershipTestState* state)
    312       : PlatformNativeWidget(delegate),
    313         state_(state) {
    314   }
    315   virtual ~OwnershipTestNativeWidget() {
    316     state_->native_widget_deleted = true;
    317   }
    318 
    319  private:
    320   OwnershipTestState* state_;
    321 
    322   DISALLOW_COPY_AND_ASSIGN(OwnershipTestNativeWidget);
    323 };
    324 
    325 // A views NativeWidget subclass that updates a bag of state when it is
    326 // destroyed.
    327 class OwnershipTestNativeWidgetAura : public NativeWidgetCapture {
    328  public:
    329   OwnershipTestNativeWidgetAura(internal::NativeWidgetDelegate* delegate,
    330                                 OwnershipTestState* state)
    331       : NativeWidgetCapture(delegate),
    332         state_(state) {
    333   }
    334   virtual ~OwnershipTestNativeWidgetAura() {
    335     state_->native_widget_deleted = true;
    336   }
    337 
    338  private:
    339   OwnershipTestState* state_;
    340 
    341   DISALLOW_COPY_AND_ASSIGN(OwnershipTestNativeWidgetAura);
    342 };
    343 
    344 // A Widget subclass that updates a bag of state when it is destroyed.
    345 class OwnershipTestWidget : public Widget {
    346  public:
    347   explicit OwnershipTestWidget(OwnershipTestState* state) : state_(state) {}
    348   virtual ~OwnershipTestWidget() {
    349     state_->widget_deleted = true;
    350   }
    351 
    352  private:
    353   OwnershipTestState* state_;
    354 
    355   DISALLOW_COPY_AND_ASSIGN(OwnershipTestWidget);
    356 };
    357 
    358 // Widget owns its NativeWidget, part 1: NativeWidget is a platform-native
    359 // widget.
    360 TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsPlatformNativeWidget) {
    361   OwnershipTestState state;
    362 
    363   scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
    364   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
    365   params.native_widget =
    366       new OwnershipTestNativeWidgetAura(widget.get(), &state);
    367   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    368   widget->Init(params);
    369 
    370   // Now delete the Widget, which should delete the NativeWidget.
    371   widget.reset();
    372 
    373   EXPECT_TRUE(state.widget_deleted);
    374   EXPECT_TRUE(state.native_widget_deleted);
    375 
    376   // TODO(beng): write test for this ownership scenario and the NativeWidget
    377   //             being deleted out from under the Widget.
    378 }
    379 
    380 // Widget owns its NativeWidget, part 2: NativeWidget is a NativeWidget.
    381 TEST_F(WidgetOwnershipTest, Ownership_WidgetOwnsViewsNativeWidget) {
    382   OwnershipTestState state;
    383 
    384   scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
    385   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
    386   params.native_widget =
    387       new OwnershipTestNativeWidgetAura(widget.get(), &state);
    388   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    389   widget->Init(params);
    390 
    391   // Now delete the Widget, which should delete the NativeWidget.
    392   widget.reset();
    393 
    394   EXPECT_TRUE(state.widget_deleted);
    395   EXPECT_TRUE(state.native_widget_deleted);
    396 
    397   // TODO(beng): write test for this ownership scenario and the NativeWidget
    398   //             being deleted out from under the Widget.
    399 }
    400 
    401 // Widget owns its NativeWidget, part 3: NativeWidget is a NativeWidget,
    402 // destroy the parent view.
    403 TEST_F(WidgetOwnershipTest,
    404        Ownership_WidgetOwnsViewsNativeWidget_DestroyParentView) {
    405   OwnershipTestState state;
    406 
    407   Widget* toplevel = CreateTopLevelPlatformWidget();
    408 
    409   scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
    410   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
    411   params.native_widget =
    412       new OwnershipTestNativeWidgetAura(widget.get(), &state);
    413   params.parent = toplevel->GetNativeView();
    414   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    415   widget->Init(params);
    416 
    417   // Now close the toplevel, which deletes the view hierarchy.
    418   toplevel->CloseNow();
    419 
    420   RunPendingMessages();
    421 
    422   // This shouldn't delete the widget because it shouldn't be deleted
    423   // from the native side.
    424   EXPECT_FALSE(state.widget_deleted);
    425   EXPECT_FALSE(state.native_widget_deleted);
    426 
    427   // Now delete it explicitly.
    428   widget.reset();
    429 
    430   EXPECT_TRUE(state.widget_deleted);
    431   EXPECT_TRUE(state.native_widget_deleted);
    432 }
    433 
    434 // NativeWidget owns its Widget, part 1: NativeWidget is a platform-native
    435 // widget.
    436 TEST_F(WidgetOwnershipTest, Ownership_PlatformNativeWidgetOwnsWidget) {
    437   OwnershipTestState state;
    438 
    439   Widget* widget = new OwnershipTestWidget(&state);
    440   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
    441   params.native_widget =
    442       new OwnershipTestNativeWidgetAura(widget, &state);
    443   widget->Init(params);
    444 
    445   // Now destroy the native widget.
    446   widget->CloseNow();
    447 
    448   EXPECT_TRUE(state.widget_deleted);
    449   EXPECT_TRUE(state.native_widget_deleted);
    450 }
    451 
    452 // NativeWidget owns its Widget, part 2: NativeWidget is a NativeWidget.
    453 TEST_F(WidgetOwnershipTest, Ownership_ViewsNativeWidgetOwnsWidget) {
    454   OwnershipTestState state;
    455 
    456   Widget* toplevel = CreateTopLevelPlatformWidget();
    457 
    458   Widget* widget = new OwnershipTestWidget(&state);
    459   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
    460   params.native_widget =
    461       new OwnershipTestNativeWidgetAura(widget, &state);
    462   params.parent = toplevel->GetNativeView();
    463   widget->Init(params);
    464 
    465   // Now destroy the native widget. This is achieved by closing the toplevel.
    466   toplevel->CloseNow();
    467 
    468   // The NativeWidget won't be deleted until after a return to the message loop
    469   // so we have to run pending messages before testing the destruction status.
    470   RunPendingMessages();
    471 
    472   EXPECT_TRUE(state.widget_deleted);
    473   EXPECT_TRUE(state.native_widget_deleted);
    474 }
    475 
    476 // NativeWidget owns its Widget, part 3: NativeWidget is a platform-native
    477 // widget, destroyed out from under it by the OS.
    478 TEST_F(WidgetOwnershipTest,
    479        Ownership_PlatformNativeWidgetOwnsWidget_NativeDestroy) {
    480   OwnershipTestState state;
    481 
    482   Widget* widget = new OwnershipTestWidget(&state);
    483   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
    484   params.native_widget =
    485       new OwnershipTestNativeWidgetAura(widget, &state);
    486   widget->Init(params);
    487 
    488   // Now simulate a destroy of the platform native widget from the OS:
    489   SimulateNativeDestroy(widget);
    490 
    491   EXPECT_TRUE(state.widget_deleted);
    492   EXPECT_TRUE(state.native_widget_deleted);
    493 }
    494 
    495 // NativeWidget owns its Widget, part 4: NativeWidget is a NativeWidget,
    496 // destroyed by the view hierarchy that contains it.
    497 TEST_F(WidgetOwnershipTest,
    498        Ownership_ViewsNativeWidgetOwnsWidget_NativeDestroy) {
    499   OwnershipTestState state;
    500 
    501   Widget* toplevel = CreateTopLevelPlatformWidget();
    502 
    503   Widget* widget = new OwnershipTestWidget(&state);
    504   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
    505   params.native_widget =
    506       new OwnershipTestNativeWidgetAura(widget, &state);
    507   params.parent = toplevel->GetNativeView();
    508   widget->Init(params);
    509 
    510   // Destroy the widget (achieved by closing the toplevel).
    511   toplevel->CloseNow();
    512 
    513   // The NativeWidget won't be deleted until after a return to the message loop
    514   // so we have to run pending messages before testing the destruction status.
    515   RunPendingMessages();
    516 
    517   EXPECT_TRUE(state.widget_deleted);
    518   EXPECT_TRUE(state.native_widget_deleted);
    519 }
    520 
    521 // NativeWidget owns its Widget, part 5: NativeWidget is a NativeWidget,
    522 // we close it directly.
    523 TEST_F(WidgetOwnershipTest,
    524        Ownership_ViewsNativeWidgetOwnsWidget_Close) {
    525   OwnershipTestState state;
    526 
    527   Widget* toplevel = CreateTopLevelPlatformWidget();
    528 
    529   Widget* widget = new OwnershipTestWidget(&state);
    530   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
    531   params.native_widget =
    532       new OwnershipTestNativeWidgetAura(widget, &state);
    533   params.parent = toplevel->GetNativeView();
    534   widget->Init(params);
    535 
    536   // Destroy the widget.
    537   widget->Close();
    538   toplevel->CloseNow();
    539 
    540   // The NativeWidget won't be deleted until after a return to the message loop
    541   // so we have to run pending messages before testing the destruction status.
    542   RunPendingMessages();
    543 
    544   EXPECT_TRUE(state.widget_deleted);
    545   EXPECT_TRUE(state.native_widget_deleted);
    546 }
    547 
    548 // Widget owns its NativeWidget and has a WidgetDelegateView as its contents.
    549 TEST_F(WidgetOwnershipTest,
    550        Ownership_WidgetOwnsNativeWidgetWithWithWidgetDelegateView) {
    551   OwnershipTestState state;
    552 
    553   WidgetDelegateView* delegate_view = new WidgetDelegateView;
    554 
    555   scoped_ptr<Widget> widget(new OwnershipTestWidget(&state));
    556   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
    557   params.native_widget =
    558       new OwnershipTestNativeWidgetAura(widget.get(), &state);
    559   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    560   params.delegate = delegate_view;
    561   widget->Init(params);
    562   widget->SetContentsView(delegate_view);
    563 
    564   // Now delete the Widget. There should be no crash or use-after-free.
    565   widget.reset();
    566 
    567   EXPECT_TRUE(state.widget_deleted);
    568   EXPECT_TRUE(state.native_widget_deleted);
    569 }
    570 
    571 ////////////////////////////////////////////////////////////////////////////////
    572 // Test to verify using various Widget methods doesn't crash when the underlying
    573 // NativeView is destroyed.
    574 //
    575 class WidgetWithDestroyedNativeViewTest : public ViewsTestBase {
    576  public:
    577   WidgetWithDestroyedNativeViewTest() {}
    578   virtual ~WidgetWithDestroyedNativeViewTest() {}
    579 
    580   void InvokeWidgetMethods(Widget* widget) {
    581     widget->GetNativeView();
    582     widget->GetNativeWindow();
    583     ui::Accelerator accelerator;
    584     widget->GetAccelerator(0, &accelerator);
    585     widget->GetTopLevelWidget();
    586     widget->GetWindowBoundsInScreen();
    587     widget->GetClientAreaBoundsInScreen();
    588     widget->SetBounds(gfx::Rect(0, 0, 100, 80));
    589     widget->SetSize(gfx::Size(10, 11));
    590     widget->SetBoundsConstrained(gfx::Rect(0, 0, 120, 140));
    591     widget->SetVisibilityChangedAnimationsEnabled(false);
    592     widget->StackAtTop();
    593     widget->IsClosed();
    594     widget->Close();
    595     widget->Hide();
    596     widget->Activate();
    597     widget->Deactivate();
    598     widget->IsActive();
    599     widget->DisableInactiveRendering();
    600     widget->SetAlwaysOnTop(true);
    601     widget->IsAlwaysOnTop();
    602     widget->Maximize();
    603     widget->Minimize();
    604     widget->Restore();
    605     widget->IsMaximized();
    606     widget->IsFullscreen();
    607     widget->SetOpacity(0);
    608     widget->SetUseDragFrame(true);
    609     widget->FlashFrame(true);
    610     widget->IsVisible();
    611     widget->GetThemeProvider();
    612     widget->GetNativeTheme();
    613     widget->GetFocusManager();
    614     widget->GetInputMethod();
    615     widget->SchedulePaintInRect(gfx::Rect(0, 0, 1, 2));
    616     widget->IsMouseEventsEnabled();
    617     widget->SetNativeWindowProperty("xx", widget);
    618     widget->GetNativeWindowProperty("xx");
    619     widget->GetFocusTraversable();
    620     widget->GetLayer();
    621     widget->ReorderNativeViews();
    622     widget->SetCapture(widget->GetRootView());
    623     widget->ReleaseCapture();
    624     widget->HasCapture();
    625     widget->GetWorkAreaBoundsInScreen();
    626     widget->IsTranslucentWindowOpacitySupported();
    627   }
    628 
    629  private:
    630   DISALLOW_COPY_AND_ASSIGN(WidgetWithDestroyedNativeViewTest);
    631 };
    632 
    633 TEST_F(WidgetWithDestroyedNativeViewTest, Test) {
    634   {
    635     Widget widget;
    636     Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
    637     params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    638     widget.Init(params);
    639     widget.Show();
    640 
    641     widget.native_widget_private()->CloseNow();
    642     InvokeWidgetMethods(&widget);
    643   }
    644 #if !defined(OS_CHROMEOS)
    645   {
    646     Widget widget;
    647     Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
    648     params.native_widget = new PlatformDesktopNativeWidget(&widget);
    649     params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    650     widget.Init(params);
    651     widget.Show();
    652 
    653     widget.native_widget_private()->CloseNow();
    654     InvokeWidgetMethods(&widget);
    655   }
    656 #endif
    657 }
    658 
    659 ////////////////////////////////////////////////////////////////////////////////
    660 // Widget observer tests.
    661 //
    662 
    663 class WidgetObserverTest : public WidgetTest, public WidgetObserver {
    664  public:
    665   WidgetObserverTest()
    666       : active_(NULL),
    667         widget_closed_(NULL),
    668         widget_activated_(NULL),
    669         widget_shown_(NULL),
    670         widget_hidden_(NULL),
    671         widget_bounds_changed_(NULL) {
    672   }
    673 
    674   virtual ~WidgetObserverTest() {}
    675 
    676   // Overridden from WidgetObserver:
    677   virtual void OnWidgetDestroying(Widget* widget) OVERRIDE {
    678     if (active_ == widget)
    679       active_ = NULL;
    680     widget_closed_ = widget;
    681   }
    682 
    683   virtual void OnWidgetActivationChanged(Widget* widget,
    684                                          bool active) OVERRIDE {
    685     if (active) {
    686       if (widget_activated_)
    687         widget_activated_->Deactivate();
    688       widget_activated_ = widget;
    689       active_ = widget;
    690     } else {
    691       if (widget_activated_ == widget)
    692         widget_activated_ = NULL;
    693       widget_deactivated_ = widget;
    694     }
    695   }
    696 
    697   virtual void OnWidgetVisibilityChanged(Widget* widget,
    698                                          bool visible) OVERRIDE {
    699     if (visible)
    700       widget_shown_ = widget;
    701     else
    702       widget_hidden_ = widget;
    703   }
    704 
    705   virtual void OnWidgetBoundsChanged(Widget* widget,
    706                                      const gfx::Rect& new_bounds) OVERRIDE {
    707     widget_bounds_changed_ = widget;
    708   }
    709 
    710   void reset() {
    711     active_ = NULL;
    712     widget_closed_ = NULL;
    713     widget_activated_ = NULL;
    714     widget_deactivated_ = NULL;
    715     widget_shown_ = NULL;
    716     widget_hidden_ = NULL;
    717     widget_bounds_changed_ = NULL;
    718   }
    719 
    720   Widget* NewWidget() {
    721     Widget* widget = CreateTopLevelNativeWidget();
    722     widget->AddObserver(this);
    723     return widget;
    724   }
    725 
    726   const Widget* active() const { return active_; }
    727   const Widget* widget_closed() const { return widget_closed_; }
    728   const Widget* widget_activated() const { return widget_activated_; }
    729   const Widget* widget_deactivated() const { return widget_deactivated_; }
    730   const Widget* widget_shown() const { return widget_shown_; }
    731   const Widget* widget_hidden() const { return widget_hidden_; }
    732   const Widget* widget_bounds_changed() const { return widget_bounds_changed_; }
    733 
    734  private:
    735   Widget* active_;
    736 
    737   Widget* widget_closed_;
    738   Widget* widget_activated_;
    739   Widget* widget_deactivated_;
    740   Widget* widget_shown_;
    741   Widget* widget_hidden_;
    742   Widget* widget_bounds_changed_;
    743 };
    744 
    745 TEST_F(WidgetObserverTest, DISABLED_ActivationChange) {
    746   Widget* toplevel = CreateTopLevelPlatformWidget();
    747 
    748   Widget* toplevel1 = NewWidget();
    749   Widget* toplevel2 = NewWidget();
    750 
    751   toplevel1->Show();
    752   toplevel2->Show();
    753 
    754   reset();
    755 
    756   toplevel1->Activate();
    757 
    758   RunPendingMessages();
    759   EXPECT_EQ(toplevel1, widget_activated());
    760 
    761   toplevel2->Activate();
    762   RunPendingMessages();
    763   EXPECT_EQ(toplevel1, widget_deactivated());
    764   EXPECT_EQ(toplevel2, widget_activated());
    765   EXPECT_EQ(toplevel2, active());
    766 
    767   toplevel->CloseNow();
    768 }
    769 
    770 TEST_F(WidgetObserverTest, DISABLED_VisibilityChange) {
    771   Widget* toplevel = CreateTopLevelPlatformWidget();
    772 
    773   Widget* child1 = NewWidget();
    774   Widget* child2 = NewWidget();
    775 
    776   toplevel->Show();
    777   child1->Show();
    778   child2->Show();
    779 
    780   reset();
    781 
    782   child1->Hide();
    783   EXPECT_EQ(child1, widget_hidden());
    784 
    785   child2->Hide();
    786   EXPECT_EQ(child2, widget_hidden());
    787 
    788   child1->Show();
    789   EXPECT_EQ(child1, widget_shown());
    790 
    791   child2->Show();
    792   EXPECT_EQ(child2, widget_shown());
    793 
    794   toplevel->CloseNow();
    795 }
    796 
    797 TEST_F(WidgetObserverTest, DestroyBubble) {
    798   Widget* anchor = CreateTopLevelPlatformWidget();
    799   anchor->Show();
    800 
    801   BubbleDelegateView* bubble_delegate =
    802       new BubbleDelegateView(anchor->client_view(), BubbleBorder::NONE);
    803   Widget* bubble_widget(BubbleDelegateView::CreateBubble(bubble_delegate));
    804   bubble_widget->Show();
    805   bubble_widget->CloseNow();
    806 
    807   anchor->Hide();
    808   anchor->CloseNow();
    809 }
    810 
    811 TEST_F(WidgetObserverTest, WidgetBoundsChanged) {
    812   Widget* child1 = NewWidget();
    813   Widget* child2 = NewWidget();
    814 
    815   child1->OnNativeWidgetMove();
    816   EXPECT_EQ(child1, widget_bounds_changed());
    817 
    818   child2->OnNativeWidgetMove();
    819   EXPECT_EQ(child2, widget_bounds_changed());
    820 
    821   child1->OnNativeWidgetSizeChanged(gfx::Size());
    822   EXPECT_EQ(child1, widget_bounds_changed());
    823 
    824   child2->OnNativeWidgetSizeChanged(gfx::Size());
    825   EXPECT_EQ(child2, widget_bounds_changed());
    826 }
    827 
    828 #if defined(false)
    829 // Aura needs shell to maximize/fullscreen window.
    830 // NativeWidgetGtk doesn't implement GetRestoredBounds.
    831 TEST_F(WidgetTest, GetRestoredBounds) {
    832   Widget* toplevel = CreateTopLevelPlatformWidget();
    833   EXPECT_EQ(toplevel->GetWindowBoundsInScreen().ToString(),
    834             toplevel->GetRestoredBounds().ToString());
    835   toplevel->Show();
    836   toplevel->Maximize();
    837   RunPendingMessages();
    838   EXPECT_NE(toplevel->GetWindowBoundsInScreen().ToString(),
    839             toplevel->GetRestoredBounds().ToString());
    840   EXPECT_GT(toplevel->GetRestoredBounds().width(), 0);
    841   EXPECT_GT(toplevel->GetRestoredBounds().height(), 0);
    842 
    843   toplevel->Restore();
    844   RunPendingMessages();
    845   EXPECT_EQ(toplevel->GetWindowBoundsInScreen().ToString(),
    846             toplevel->GetRestoredBounds().ToString());
    847 
    848   toplevel->SetFullscreen(true);
    849   RunPendingMessages();
    850   EXPECT_NE(toplevel->GetWindowBoundsInScreen().ToString(),
    851             toplevel->GetRestoredBounds().ToString());
    852   EXPECT_GT(toplevel->GetRestoredBounds().width(), 0);
    853   EXPECT_GT(toplevel->GetRestoredBounds().height(), 0);
    854 }
    855 #endif
    856 
    857 // Test that window state is not changed after getting out of full screen.
    858 TEST_F(WidgetTest, ExitFullscreenRestoreState) {
    859   Widget* toplevel = CreateTopLevelPlatformWidget();
    860 
    861   toplevel->Show();
    862   RunPendingMessages();
    863 
    864   // This should be a normal state window.
    865   EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetWidgetShowState(toplevel));
    866 
    867   toplevel->SetFullscreen(true);
    868   EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel));
    869   toplevel->SetFullscreen(false);
    870   EXPECT_NE(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel));
    871 
    872   // And it should still be in normal state after getting out of full screen.
    873   EXPECT_EQ(ui::SHOW_STATE_NORMAL, GetWidgetShowState(toplevel));
    874 
    875   // Now, make it maximized.
    876   toplevel->Maximize();
    877   EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, GetWidgetShowState(toplevel));
    878 
    879   toplevel->SetFullscreen(true);
    880   EXPECT_EQ(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel));
    881   toplevel->SetFullscreen(false);
    882   EXPECT_NE(ui::SHOW_STATE_FULLSCREEN, GetWidgetShowState(toplevel));
    883 
    884   // And it stays maximized after getting out of full screen.
    885   EXPECT_EQ(ui::SHOW_STATE_MAXIMIZED, GetWidgetShowState(toplevel));
    886 
    887   // Clean up.
    888   toplevel->Close();
    889   RunPendingMessages();
    890 }
    891 
    892 // The key-event propagation from Widget happens differently on aura and
    893 // non-aura systems because of the difference in IME. So this test works only on
    894 // aura.
    895 TEST_F(WidgetTest, KeyboardInputEvent) {
    896   Widget* toplevel = CreateTopLevelPlatformWidget();
    897   View* container = toplevel->client_view();
    898 
    899   Textfield* textfield = new Textfield();
    900   textfield->SetText(base::ASCIIToUTF16("some text"));
    901   container->AddChildView(textfield);
    902   toplevel->Show();
    903   textfield->RequestFocus();
    904 
    905   // The press gets handled. The release doesn't have an effect.
    906   ui::KeyEvent backspace_p(ui::ET_KEY_PRESSED, ui::VKEY_DELETE, 0, false);
    907   toplevel->OnKeyEvent(&backspace_p);
    908   EXPECT_TRUE(backspace_p.stopped_propagation());
    909   ui::KeyEvent backspace_r(ui::ET_KEY_RELEASED, ui::VKEY_DELETE, 0, false);
    910   toplevel->OnKeyEvent(&backspace_r);
    911   EXPECT_FALSE(backspace_r.handled());
    912 
    913   toplevel->Close();
    914 }
    915 
    916 // Verifies bubbles result in a focus lost when shown.
    917 // TODO(msw): this tests relies on focus, it needs to be in
    918 // interactive_ui_tests.
    919 TEST_F(WidgetTest, DISABLED_FocusChangesOnBubble) {
    920   // Create a widget, show and activate it and focus the contents view.
    921   View* contents_view = new View;
    922   contents_view->SetFocusable(true);
    923   Widget widget;
    924   Widget::InitParams init_params =
    925       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
    926   init_params.bounds = gfx::Rect(0, 0, 200, 200);
    927   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    928 #if !defined(OS_CHROMEOS)
    929   init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
    930 #endif
    931   widget.Init(init_params);
    932   widget.SetContentsView(contents_view);
    933   widget.Show();
    934   widget.Activate();
    935   contents_view->RequestFocus();
    936   EXPECT_TRUE(contents_view->HasFocus());
    937 
    938   // Show a bubble.
    939   BubbleDelegateView* bubble_delegate_view =
    940       new BubbleDelegateView(contents_view, BubbleBorder::TOP_LEFT);
    941   bubble_delegate_view->SetFocusable(true);
    942   BubbleDelegateView::CreateBubble(bubble_delegate_view)->Show();
    943   bubble_delegate_view->RequestFocus();
    944 
    945   // |contents_view_| should no longer have focus.
    946   EXPECT_FALSE(contents_view->HasFocus());
    947   EXPECT_TRUE(bubble_delegate_view->HasFocus());
    948 
    949   bubble_delegate_view->GetWidget()->CloseNow();
    950 
    951   // Closing the bubble should result in focus going back to the contents view.
    952   EXPECT_TRUE(contents_view->HasFocus());
    953 }
    954 
    955 class TestBubbleDelegateView : public BubbleDelegateView {
    956  public:
    957   TestBubbleDelegateView(View* anchor)
    958       : BubbleDelegateView(anchor, BubbleBorder::NONE),
    959         reset_controls_called_(false) {}
    960   virtual ~TestBubbleDelegateView() {}
    961 
    962   virtual bool ShouldShowCloseButton() const OVERRIDE {
    963     reset_controls_called_ = true;
    964     return true;
    965   }
    966 
    967   mutable bool reset_controls_called_;
    968 };
    969 
    970 TEST_F(WidgetTest, BubbleControlsResetOnInit) {
    971   Widget* anchor = CreateTopLevelPlatformWidget();
    972   anchor->Show();
    973 
    974   TestBubbleDelegateView* bubble_delegate =
    975       new TestBubbleDelegateView(anchor->client_view());
    976   Widget* bubble_widget(BubbleDelegateView::CreateBubble(bubble_delegate));
    977   EXPECT_TRUE(bubble_delegate->reset_controls_called_);
    978   bubble_widget->Show();
    979   bubble_widget->CloseNow();
    980 
    981   anchor->Hide();
    982   anchor->CloseNow();
    983 }
    984 
    985 // Desktop native widget Aura tests are for non Chrome OS platforms.
    986 #if !defined(OS_CHROMEOS)
    987 // Test to ensure that after minimize, view width is set to zero.
    988 TEST_F(WidgetTest, TestViewWidthAfterMinimizingWidget) {
    989   // Create a widget.
    990   Widget widget;
    991   Widget::InitParams init_params =
    992       CreateParams(Widget::InitParams::TYPE_WINDOW);
    993   init_params.show_state = ui::SHOW_STATE_NORMAL;
    994   gfx::Rect initial_bounds(0, 0, 300, 400);
    995   init_params.bounds = initial_bounds;
    996   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
    997   init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
    998   widget.Init(init_params);
    999   NonClientView* non_client_view = widget.non_client_view();
   1000   NonClientFrameView* frame_view = new MinimumSizeFrameView(&widget);
   1001   non_client_view->SetFrameView(frame_view);
   1002   widget.Show();
   1003   widget.Minimize();
   1004   EXPECT_EQ(0, frame_view->width());
   1005 }
   1006 
   1007 // This class validates whether paints are received for a visible Widget.
   1008 // To achieve this it overrides the Show and Close methods on the Widget class
   1009 // and sets state whether subsequent paints are expected.
   1010 class DesktopAuraTestValidPaintWidget : public views::Widget {
   1011  public:
   1012   DesktopAuraTestValidPaintWidget()
   1013     : expect_paint_(true),
   1014       received_paint_while_hidden_(false) {
   1015   }
   1016 
   1017   virtual ~DesktopAuraTestValidPaintWidget() {
   1018   }
   1019 
   1020   virtual void Show() OVERRIDE {
   1021     expect_paint_ = true;
   1022     views::Widget::Show();
   1023   }
   1024 
   1025   virtual void Close() OVERRIDE {
   1026     expect_paint_ = false;
   1027     views::Widget::Close();
   1028   }
   1029 
   1030   void Hide() {
   1031     expect_paint_ = false;
   1032     views::Widget::Hide();
   1033   }
   1034 
   1035   virtual void OnNativeWidgetPaint(gfx::Canvas* canvas) OVERRIDE {
   1036     EXPECT_TRUE(expect_paint_);
   1037     if (!expect_paint_)
   1038       received_paint_while_hidden_ = true;
   1039     views::Widget::OnNativeWidgetPaint(canvas);
   1040   }
   1041 
   1042   bool received_paint_while_hidden() const {
   1043     return received_paint_while_hidden_;
   1044   }
   1045 
   1046  private:
   1047   bool expect_paint_;
   1048   bool received_paint_while_hidden_;
   1049 };
   1050 
   1051 TEST_F(WidgetTest, DesktopNativeWidgetNoPaintAfterCloseTest) {
   1052   View* contents_view = new View;
   1053   contents_view->SetFocusable(true);
   1054   DesktopAuraTestValidPaintWidget widget;
   1055   Widget::InitParams init_params =
   1056       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
   1057   init_params.bounds = gfx::Rect(0, 0, 200, 200);
   1058   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   1059   init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
   1060   widget.Init(init_params);
   1061   widget.SetContentsView(contents_view);
   1062   widget.Show();
   1063   widget.Activate();
   1064   RunPendingMessages();
   1065   widget.SchedulePaintInRect(init_params.bounds);
   1066   widget.Close();
   1067   RunPendingMessages();
   1068   EXPECT_FALSE(widget.received_paint_while_hidden());
   1069 }
   1070 
   1071 TEST_F(WidgetTest, DesktopNativeWidgetNoPaintAfterHideTest) {
   1072   View* contents_view = new View;
   1073   contents_view->SetFocusable(true);
   1074   DesktopAuraTestValidPaintWidget widget;
   1075   Widget::InitParams init_params =
   1076       CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
   1077   init_params.bounds = gfx::Rect(0, 0, 200, 200);
   1078   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   1079   init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
   1080   widget.Init(init_params);
   1081   widget.SetContentsView(contents_view);
   1082   widget.Show();
   1083   widget.Activate();
   1084   RunPendingMessages();
   1085   widget.SchedulePaintInRect(init_params.bounds);
   1086   widget.Hide();
   1087   RunPendingMessages();
   1088   EXPECT_FALSE(widget.received_paint_while_hidden());
   1089   widget.Close();
   1090 }
   1091 
   1092 // Test to ensure that the aura Window's visiblity state is set to visible if
   1093 // the underlying widget is hidden and then shown.
   1094 TEST_F(WidgetTest, TestWindowVisibilityAfterHide) {
   1095   // Create a widget.
   1096   Widget widget;
   1097   Widget::InitParams init_params =
   1098       CreateParams(Widget::InitParams::TYPE_WINDOW);
   1099   init_params.show_state = ui::SHOW_STATE_NORMAL;
   1100   gfx::Rect initial_bounds(0, 0, 300, 400);
   1101   init_params.bounds = initial_bounds;
   1102   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   1103   init_params.native_widget = new PlatformDesktopNativeWidget(&widget);
   1104   widget.Init(init_params);
   1105   NonClientView* non_client_view = widget.non_client_view();
   1106   NonClientFrameView* frame_view = new MinimumSizeFrameView(&widget);
   1107   non_client_view->SetFrameView(frame_view);
   1108 
   1109   widget.Hide();
   1110   EXPECT_FALSE(IsNativeWindowVisible(widget.GetNativeWindow()));
   1111   widget.Show();
   1112   EXPECT_TRUE(IsNativeWindowVisible(widget.GetNativeWindow()));
   1113 }
   1114 
   1115 // The following code verifies we can correctly destroy a Widget from a mouse
   1116 // enter/exit. We could test move/drag/enter/exit but in general we don't run
   1117 // nested message loops from such events, nor has the code ever really dealt
   1118 // with this situation.
   1119 
   1120 // Generates two moves (first generates enter, second real move), a press, drag
   1121 // and release stopping at |last_event_type|.
   1122 void GenerateMouseEvents(Widget* widget, ui::EventType last_event_type) {
   1123   const gfx::Rect screen_bounds(widget->GetWindowBoundsInScreen());
   1124   ui::MouseEvent move_event(ui::ET_MOUSE_MOVED, screen_bounds.CenterPoint(),
   1125                             screen_bounds.CenterPoint(), 0, 0);
   1126   ui::EventProcessor* dispatcher = WidgetTest::GetEventProcessor(widget);
   1127   ui::EventDispatchDetails details = dispatcher->OnEventFromSource(&move_event);
   1128   if (last_event_type == ui::ET_MOUSE_ENTERED || details.dispatcher_destroyed)
   1129     return;
   1130   details = dispatcher->OnEventFromSource(&move_event);
   1131   if (last_event_type == ui::ET_MOUSE_MOVED || details.dispatcher_destroyed)
   1132     return;
   1133 
   1134   ui::MouseEvent press_event(ui::ET_MOUSE_PRESSED, screen_bounds.CenterPoint(),
   1135                              screen_bounds.CenterPoint(), 0, 0);
   1136   details = dispatcher->OnEventFromSource(&press_event);
   1137   if (last_event_type == ui::ET_MOUSE_PRESSED || details.dispatcher_destroyed)
   1138     return;
   1139 
   1140   gfx::Point end_point(screen_bounds.CenterPoint());
   1141   end_point.Offset(1, 1);
   1142   ui::MouseEvent drag_event(ui::ET_MOUSE_DRAGGED, end_point, end_point, 0, 0);
   1143   details = dispatcher->OnEventFromSource(&drag_event);
   1144   if (last_event_type == ui::ET_MOUSE_DRAGGED || details.dispatcher_destroyed)
   1145     return;
   1146 
   1147   ui::MouseEvent release_event(ui::ET_MOUSE_RELEASED, end_point, end_point, 0,
   1148                                0);
   1149   details = dispatcher->OnEventFromSource(&release_event);
   1150   if (details.dispatcher_destroyed)
   1151     return;
   1152 }
   1153 
   1154 // Creates a widget and invokes GenerateMouseEvents() with |last_event_type|.
   1155 void RunCloseWidgetDuringDispatchTest(WidgetTest* test,
   1156                                       ui::EventType last_event_type) {
   1157   // |widget| is deleted by CloseWidgetView.
   1158   Widget* widget = new Widget;
   1159   Widget::InitParams params =
   1160       test->CreateParams(Widget::InitParams::TYPE_POPUP);
   1161   params.native_widget = new PlatformDesktopNativeWidget(widget);
   1162   params.bounds = gfx::Rect(0, 0, 50, 100);
   1163   widget->Init(params);
   1164   widget->SetContentsView(new CloseWidgetView(last_event_type));
   1165   widget->Show();
   1166   GenerateMouseEvents(widget, last_event_type);
   1167 }
   1168 
   1169 // Verifies deleting the widget from a mouse pressed event doesn't crash.
   1170 TEST_F(WidgetTest, CloseWidgetDuringMousePress) {
   1171   RunCloseWidgetDuringDispatchTest(this, ui::ET_MOUSE_PRESSED);
   1172 }
   1173 
   1174 // Verifies deleting the widget from a mouse released event doesn't crash.
   1175 TEST_F(WidgetTest, CloseWidgetDuringMouseReleased) {
   1176   RunCloseWidgetDuringDispatchTest(this, ui::ET_MOUSE_RELEASED);
   1177 }
   1178 
   1179 #endif  // !defined(OS_CHROMEOS)
   1180 
   1181 // Tests that wheel events generated from scroll events are targetted to the
   1182 // views under the cursor when the focused view does not processed them.
   1183 TEST_F(WidgetTest, WheelEventsFromScrollEventTarget) {
   1184   EventCountView* cursor_view = new EventCountView;
   1185   cursor_view->SetBounds(60, 0, 50, 40);
   1186 
   1187   Widget* widget = CreateTopLevelPlatformWidget();
   1188   widget->GetRootView()->AddChildView(cursor_view);
   1189 
   1190   // Generate a scroll event on the cursor view.
   1191   ui::ScrollEvent scroll(ui::ET_SCROLL,
   1192                          gfx::Point(65, 5),
   1193                          ui::EventTimeForNow(),
   1194                          0,
   1195                          0, 20,
   1196                          0, 20,
   1197                          2);
   1198   widget->OnScrollEvent(&scroll);
   1199 
   1200   EXPECT_EQ(1, cursor_view->GetEventCount(ui::ET_SCROLL));
   1201   EXPECT_EQ(1, cursor_view->GetEventCount(ui::ET_MOUSEWHEEL));
   1202 
   1203   cursor_view->ResetCounts();
   1204 
   1205   ui::ScrollEvent scroll2(ui::ET_SCROLL,
   1206                           gfx::Point(5, 5),
   1207                           ui::EventTimeForNow(),
   1208                           0,
   1209                           0, 20,
   1210                           0, 20,
   1211                           2);
   1212   widget->OnScrollEvent(&scroll2);
   1213 
   1214   EXPECT_EQ(0, cursor_view->GetEventCount(ui::ET_SCROLL));
   1215   EXPECT_EQ(0, cursor_view->GetEventCount(ui::ET_MOUSEWHEEL));
   1216 
   1217   widget->CloseNow();
   1218 }
   1219 
   1220 // Tests that if a scroll-begin gesture is not handled, then subsequent scroll
   1221 // events are not dispatched to any view.
   1222 TEST_F(WidgetTest, GestureScrollEventDispatching) {
   1223   EventCountView* noscroll_view = new EventCountView;
   1224   EventCountView* scroll_view = new ScrollableEventCountView;
   1225 
   1226   noscroll_view->SetBounds(0, 0, 50, 40);
   1227   scroll_view->SetBounds(60, 0, 40, 40);
   1228 
   1229   Widget* widget = CreateTopLevelPlatformWidget();
   1230   widget->GetRootView()->AddChildView(noscroll_view);
   1231   widget->GetRootView()->AddChildView(scroll_view);
   1232 
   1233   {
   1234     ui::GestureEvent begin(ui::ET_GESTURE_SCROLL_BEGIN,
   1235         5, 5, 0, base::TimeDelta(),
   1236         ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, 0, 0),
   1237         1);
   1238     widget->OnGestureEvent(&begin);
   1239     ui::GestureEvent update(ui::ET_GESTURE_SCROLL_UPDATE,
   1240         25, 15, 0, base::TimeDelta(),
   1241         ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, 20, 10),
   1242         1);
   1243     widget->OnGestureEvent(&update);
   1244     ui::GestureEvent end(ui::ET_GESTURE_SCROLL_END,
   1245         25, 15, 0, base::TimeDelta(),
   1246         ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END, 0, 0),
   1247         1);
   1248     widget->OnGestureEvent(&end);
   1249 
   1250     EXPECT_EQ(1, noscroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN));
   1251     EXPECT_EQ(0, noscroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
   1252     EXPECT_EQ(0, noscroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_END));
   1253   }
   1254 
   1255   {
   1256     ui::GestureEvent begin(ui::ET_GESTURE_SCROLL_BEGIN,
   1257         65, 5, 0, base::TimeDelta(),
   1258         ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_BEGIN, 0, 0),
   1259         1);
   1260     widget->OnGestureEvent(&begin);
   1261     ui::GestureEvent update(ui::ET_GESTURE_SCROLL_UPDATE,
   1262         85, 15, 0, base::TimeDelta(),
   1263         ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, 20, 10),
   1264         1);
   1265     widget->OnGestureEvent(&update);
   1266     ui::GestureEvent end(ui::ET_GESTURE_SCROLL_END,
   1267         85, 15, 0, base::TimeDelta(),
   1268         ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_END, 0, 0),
   1269         1);
   1270     widget->OnGestureEvent(&end);
   1271 
   1272     EXPECT_EQ(1, scroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_BEGIN));
   1273     EXPECT_EQ(1, scroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_UPDATE));
   1274     EXPECT_EQ(1, scroll_view->GetEventCount(ui::ET_GESTURE_SCROLL_END));
   1275   }
   1276 
   1277   widget->CloseNow();
   1278 }
   1279 
   1280 // Tests that event-handlers installed on the RootView get triggered correctly.
   1281 // TODO(tdanderson): Clean up this test as part of crbug.com/355680.
   1282 TEST_F(WidgetTest, EventHandlersOnRootView) {
   1283   Widget* widget = CreateTopLevelNativeWidget();
   1284   View* root_view = widget->GetRootView();
   1285 
   1286   scoped_ptr<EventCountView> view(new EventCountView());
   1287   view->set_owned_by_client();
   1288   view->SetBounds(0, 0, 20, 20);
   1289   root_view->AddChildView(view.get());
   1290 
   1291   EventCountHandler h1;
   1292   root_view->AddPreTargetHandler(&h1);
   1293 
   1294   EventCountHandler h2;
   1295   root_view->AddPostTargetHandler(&h2);
   1296 
   1297   widget->SetBounds(gfx::Rect(0, 0, 100, 100));
   1298   widget->Show();
   1299 
   1300   ui::GestureEvent begin(ui::ET_GESTURE_BEGIN,
   1301       5, 5, 0, ui::EventTimeForNow(),
   1302       ui::GestureEventDetails(ui::ET_GESTURE_BEGIN, 0, 0), 1);
   1303   ui::GestureEvent end(ui::ET_GESTURE_END,
   1304       5, 5, 0, ui::EventTimeForNow(),
   1305       ui::GestureEventDetails(ui::ET_GESTURE_END, 0, 0), 1);
   1306   widget->OnGestureEvent(&begin);
   1307   EXPECT_EQ(1, h1.GetEventCount(ui::ET_GESTURE_BEGIN));
   1308   EXPECT_EQ(1, view->GetEventCount(ui::ET_GESTURE_BEGIN));
   1309   EXPECT_EQ(1, h2.GetEventCount(ui::ET_GESTURE_BEGIN));
   1310 
   1311   widget->OnGestureEvent(&end);
   1312   EXPECT_EQ(1, h1.GetEventCount(ui::ET_GESTURE_END));
   1313   EXPECT_EQ(1, view->GetEventCount(ui::ET_GESTURE_END));
   1314   EXPECT_EQ(1, h2.GetEventCount(ui::ET_GESTURE_END));
   1315 
   1316   ui::ScrollEvent scroll(ui::ET_SCROLL,
   1317                          gfx::Point(5, 5),
   1318                          ui::EventTimeForNow(),
   1319                          0,
   1320                          0, 20,
   1321                          0, 20,
   1322                          2);
   1323   widget->OnScrollEvent(&scroll);
   1324   EXPECT_EQ(2, h1.GetEventCount(ui::ET_SCROLL));
   1325   EXPECT_EQ(1, view->GetEventCount(ui::ET_SCROLL));
   1326   EXPECT_EQ(2, h2.GetEventCount(ui::ET_SCROLL));
   1327 
   1328   // Unhandled scroll events are turned into wheel events and re-dispatched.
   1329   EXPECT_EQ(1, h1.GetEventCount(ui::ET_MOUSEWHEEL));
   1330   EXPECT_EQ(1, view->GetEventCount(ui::ET_MOUSEWHEEL));
   1331   EXPECT_EQ(1, h2.GetEventCount(ui::ET_MOUSEWHEEL));
   1332 
   1333   h1.ResetCounts();
   1334   view->ResetCounts();
   1335   h2.ResetCounts();
   1336 
   1337   ui::ScrollEvent fling(ui::ET_SCROLL_FLING_START,
   1338                         gfx::Point(5, 5),
   1339                         ui::EventTimeForNow(),
   1340                         0,
   1341                         0, 20,
   1342                         0, 20,
   1343                         2);
   1344   widget->OnScrollEvent(&fling);
   1345   EXPECT_EQ(2, h1.GetEventCount(ui::ET_SCROLL_FLING_START));
   1346   EXPECT_EQ(1, view->GetEventCount(ui::ET_SCROLL_FLING_START));
   1347   EXPECT_EQ(2, h2.GetEventCount(ui::ET_SCROLL_FLING_START));
   1348 
   1349   // Unhandled scroll events which are not of type ui::ET_SCROLL should not
   1350   // be turned into wheel events and re-dispatched.
   1351   EXPECT_EQ(0, h1.GetEventCount(ui::ET_MOUSEWHEEL));
   1352   EXPECT_EQ(0, view->GetEventCount(ui::ET_MOUSEWHEEL));
   1353   EXPECT_EQ(0, h2.GetEventCount(ui::ET_MOUSEWHEEL));
   1354 
   1355   h1.ResetCounts();
   1356   view->ResetCounts();
   1357   h2.ResetCounts();
   1358 
   1359   // Replace the child of |root_view| with a ScrollableEventCountView so that
   1360   // ui::ET_SCROLL events are marked as handled at the target phase.
   1361   root_view->RemoveChildView(view.get());
   1362   ScrollableEventCountView* scroll_view = new ScrollableEventCountView;
   1363   scroll_view->SetBounds(0, 0, 20, 20);
   1364   root_view->AddChildView(scroll_view);
   1365 
   1366   ui::ScrollEvent consumed_scroll(ui::ET_SCROLL,
   1367                                   gfx::Point(5, 5),
   1368                                   ui::EventTimeForNow(),
   1369                                   0,
   1370                                   0, 20,
   1371                                   0, 20,
   1372                                   2);
   1373   widget->OnScrollEvent(&consumed_scroll);
   1374 
   1375   // The event is handled at the target phase and should not reach the
   1376   // post-target handler.
   1377   EXPECT_EQ(1, h1.GetEventCount(ui::ET_SCROLL));
   1378   EXPECT_EQ(1, scroll_view->GetEventCount(ui::ET_SCROLL));
   1379   EXPECT_EQ(0, h2.GetEventCount(ui::ET_SCROLL));
   1380 
   1381   // Handled scroll events are not turned into wheel events and re-dispatched.
   1382   EXPECT_EQ(0, h1.GetEventCount(ui::ET_MOUSEWHEEL));
   1383   EXPECT_EQ(0, scroll_view->GetEventCount(ui::ET_MOUSEWHEEL));
   1384   EXPECT_EQ(0, h2.GetEventCount(ui::ET_MOUSEWHEEL));
   1385 
   1386   widget->CloseNow();
   1387 }
   1388 
   1389 TEST_F(WidgetTest, SynthesizeMouseMoveEvent) {
   1390   Widget* widget = CreateTopLevelNativeWidget();
   1391   View* root_view = widget->GetRootView();
   1392 
   1393   EventCountView* v1 = new EventCountView();
   1394   v1->SetBounds(0, 0, 10, 10);
   1395   root_view->AddChildView(v1);
   1396   EventCountView* v2 = new EventCountView();
   1397   v2->SetBounds(0, 10, 10, 10);
   1398   root_view->AddChildView(v2);
   1399 
   1400   gfx::Point cursor_location(5, 5);
   1401   ui::MouseEvent move(ui::ET_MOUSE_MOVED, cursor_location, cursor_location,
   1402                       ui::EF_NONE, ui::EF_NONE);
   1403   widget->OnMouseEvent(&move);
   1404 
   1405   EXPECT_EQ(1, v1->GetEventCount(ui::ET_MOUSE_ENTERED));
   1406   EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_ENTERED));
   1407 
   1408   delete v1;
   1409   v2->SetBounds(0, 0, 10, 10);
   1410   EXPECT_EQ(0, v2->GetEventCount(ui::ET_MOUSE_ENTERED));
   1411 
   1412   widget->SynthesizeMouseMoveEvent();
   1413   EXPECT_EQ(1, v2->GetEventCount(ui::ET_MOUSE_ENTERED));
   1414 }
   1415 
   1416 // Used by SingleWindowClosing to count number of times WindowClosing() has
   1417 // been invoked.
   1418 class ClosingDelegate : public WidgetDelegate {
   1419  public:
   1420   ClosingDelegate() : count_(0), widget_(NULL) {}
   1421 
   1422   int count() const { return count_; }
   1423 
   1424   void set_widget(views::Widget* widget) { widget_ = widget; }
   1425 
   1426   // WidgetDelegate overrides:
   1427   virtual Widget* GetWidget() OVERRIDE { return widget_; }
   1428   virtual const Widget* GetWidget() const OVERRIDE { return widget_; }
   1429   virtual void WindowClosing() OVERRIDE {
   1430     count_++;
   1431   }
   1432 
   1433  private:
   1434   int count_;
   1435   views::Widget* widget_;
   1436 
   1437   DISALLOW_COPY_AND_ASSIGN(ClosingDelegate);
   1438 };
   1439 
   1440 // Verifies WindowClosing() is invoked correctly on the delegate when a Widget
   1441 // is closed.
   1442 TEST_F(WidgetTest, SingleWindowClosing) {
   1443   scoped_ptr<ClosingDelegate> delegate(new ClosingDelegate());
   1444   Widget* widget = new Widget();  // Destroyed by CloseNow() below.
   1445   Widget::InitParams init_params =
   1446       CreateParams(Widget::InitParams::TYPE_WINDOW);
   1447   init_params.bounds = gfx::Rect(0, 0, 200, 200);
   1448   init_params.delegate = delegate.get();
   1449 #if !defined(OS_CHROMEOS)
   1450   init_params.native_widget = new PlatformDesktopNativeWidget(widget);
   1451 #endif
   1452   widget->Init(init_params);
   1453   EXPECT_EQ(0, delegate->count());
   1454   widget->CloseNow();
   1455   EXPECT_EQ(1, delegate->count());
   1456 }
   1457 
   1458 class WidgetWindowTitleTest : public WidgetTest {
   1459  protected:
   1460   void RunTest(bool desktop_native_widget) {
   1461     Widget* widget = new Widget();  // Destroyed by CloseNow() below.
   1462     Widget::InitParams init_params =
   1463         CreateParams(Widget::InitParams::TYPE_WINDOW);
   1464     widget->Init(init_params);
   1465 
   1466 #if !defined(OS_CHROMEOS)
   1467     if (desktop_native_widget)
   1468       init_params.native_widget = new PlatformDesktopNativeWidget(widget);
   1469 #else
   1470     DCHECK(!desktop_native_widget)
   1471         << "DesktopNativeWidget does not exist on non-Aura or on ChromeOS.";
   1472 #endif
   1473 
   1474     internal::NativeWidgetPrivate* native_widget =
   1475         widget->native_widget_private();
   1476 
   1477     base::string16 empty;
   1478     base::string16 s1(base::UTF8ToUTF16("Title1"));
   1479     base::string16 s2(base::UTF8ToUTF16("Title2"));
   1480     base::string16 s3(base::UTF8ToUTF16("TitleLong"));
   1481 
   1482     // The widget starts with no title, setting empty should not change
   1483     // anything.
   1484     EXPECT_FALSE(native_widget->SetWindowTitle(empty));
   1485     // Setting the title to something non-empty should cause a change.
   1486     EXPECT_TRUE(native_widget->SetWindowTitle(s1));
   1487     // Setting the title to something else with the same length should cause a
   1488     // change.
   1489     EXPECT_TRUE(native_widget->SetWindowTitle(s2));
   1490     // Setting the title to something else with a different length should cause
   1491     // a change.
   1492     EXPECT_TRUE(native_widget->SetWindowTitle(s3));
   1493     // Setting the title to the same thing twice should not cause a change.
   1494     EXPECT_FALSE(native_widget->SetWindowTitle(s3));
   1495 
   1496     widget->CloseNow();
   1497   }
   1498 };
   1499 
   1500 TEST_F(WidgetWindowTitleTest, SetWindowTitleChanged_NativeWidget) {
   1501   // Use the default NativeWidget.
   1502   bool desktop_native_widget = false;
   1503   RunTest(desktop_native_widget);
   1504 }
   1505 
   1506 // DesktopNativeWidget does not exist on non-Aura or on ChromeOS.
   1507 #if !defined(OS_CHROMEOS)
   1508 TEST_F(WidgetWindowTitleTest, SetWindowTitleChanged_DesktopNativeWidget) {
   1509   // Override to use a DesktopNativeWidget.
   1510   bool desktop_native_widget = true;
   1511   RunTest(desktop_native_widget);
   1512 }
   1513 #endif  // !OS_CHROMEOS
   1514 
   1515 TEST_F(WidgetTest, WidgetDeleted_InOnMousePressed) {
   1516   Widget* widget = new Widget;
   1517   Widget::InitParams params =
   1518       CreateParams(views::Widget::InitParams::TYPE_POPUP);
   1519   widget->Init(params);
   1520 
   1521   widget->SetContentsView(new CloseWidgetView(ui::ET_MOUSE_PRESSED));
   1522 
   1523   widget->SetSize(gfx::Size(100, 100));
   1524   widget->Show();
   1525 
   1526   aura::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
   1527 
   1528   WidgetDeletionObserver deletion_observer(widget);
   1529   generator.ClickLeftButton();
   1530   EXPECT_FALSE(deletion_observer.IsWidgetAlive());
   1531 
   1532   // Yay we did not crash!
   1533 }
   1534 
   1535 TEST_F(WidgetTest, WidgetDeleted_InDispatchGestureEvent) {
   1536   Widget* widget = new Widget;
   1537   Widget::InitParams params =
   1538       CreateParams(views::Widget::InitParams::TYPE_POPUP);
   1539   widget->Init(params);
   1540 
   1541   widget->SetContentsView(new CloseWidgetView(ui::ET_GESTURE_TAP_DOWN));
   1542 
   1543   widget->SetSize(gfx::Size(100, 100));
   1544   widget->Show();
   1545 
   1546   aura::test::EventGenerator generator(GetContext());
   1547 
   1548   WidgetDeletionObserver deletion_observer(widget);
   1549   generator.GestureTapAt(widget->GetWindowBoundsInScreen().CenterPoint());
   1550   EXPECT_FALSE(deletion_observer.IsWidgetAlive());
   1551 
   1552   // Yay we did not crash!
   1553 }
   1554 
   1555 // See description of RunGetNativeThemeFromDestructor() for details.
   1556 class GetNativeThemeFromDestructorView : public WidgetDelegateView {
   1557  public:
   1558   GetNativeThemeFromDestructorView() {}
   1559   virtual ~GetNativeThemeFromDestructorView() {
   1560     VerifyNativeTheme();
   1561   }
   1562 
   1563   virtual View* GetContentsView() OVERRIDE {
   1564     return this;
   1565   }
   1566 
   1567  private:
   1568   void VerifyNativeTheme() {
   1569     ASSERT_TRUE(GetNativeTheme() != NULL);
   1570   }
   1571 
   1572   DISALLOW_COPY_AND_ASSIGN(GetNativeThemeFromDestructorView);
   1573 };
   1574 
   1575 // Verifies GetNativeTheme() from the destructor of a WidgetDelegateView doesn't
   1576 // crash. |is_first_run| is true if this is the first call. A return value of
   1577 // true indicates this should be run again with a value of false.
   1578 // First run uses DesktopNativeWidgetAura (if possible). Second run doesn't.
   1579 bool RunGetNativeThemeFromDestructor(const Widget::InitParams& in_params,
   1580                                      bool is_first_run) {
   1581   bool needs_second_run = false;
   1582   // Destroyed by CloseNow() below.
   1583   Widget* widget = new Widget;
   1584   Widget::InitParams params(in_params);
   1585   // Deletes itself when the Widget is destroyed.
   1586   params.delegate = new GetNativeThemeFromDestructorView;
   1587 #if !defined(OS_CHROMEOS)
   1588   if (is_first_run) {
   1589     params.native_widget = new PlatformDesktopNativeWidget(widget);
   1590     needs_second_run = true;
   1591   }
   1592 #endif
   1593   widget->Init(params);
   1594   widget->CloseNow();
   1595   return needs_second_run;
   1596 }
   1597 
   1598 // See description of RunGetNativeThemeFromDestructor() for details.
   1599 TEST_F(WidgetTest, GetNativeThemeFromDestructor) {
   1600   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
   1601   if (RunGetNativeThemeFromDestructor(params, true))
   1602     RunGetNativeThemeFromDestructor(params, false);
   1603 }
   1604 
   1605 // Used by HideCloseDestroy. Allows setting a boolean when the widget is
   1606 // destroyed.
   1607 class CloseDestroysWidget : public Widget {
   1608  public:
   1609   explicit CloseDestroysWidget(bool* destroyed)
   1610       : destroyed_(destroyed) {
   1611   }
   1612 
   1613   virtual ~CloseDestroysWidget() {
   1614     if (destroyed_) {
   1615       *destroyed_ = true;
   1616       base::MessageLoop::current()->QuitNow();
   1617     }
   1618   }
   1619 
   1620   void Detach() { destroyed_ = NULL; }
   1621 
   1622  private:
   1623   // If non-null set to true from destructor.
   1624   bool* destroyed_;
   1625 
   1626   DISALLOW_COPY_AND_ASSIGN(CloseDestroysWidget);
   1627 };
   1628 
   1629 // Verifies Close() results in destroying.
   1630 TEST_F(WidgetTest, CloseDestroys) {
   1631   bool destroyed = false;
   1632   CloseDestroysWidget* widget = new CloseDestroysWidget(&destroyed);
   1633   Widget::InitParams params =
   1634       CreateParams(views::Widget::InitParams::TYPE_MENU);
   1635   params.opacity = Widget::InitParams::OPAQUE_WINDOW;
   1636 #if !defined(OS_CHROMEOS)
   1637   params.native_widget = new PlatformDesktopNativeWidget(widget);
   1638 #endif
   1639   widget->Init(params);
   1640   widget->Show();
   1641   widget->Hide();
   1642   widget->Close();
   1643   // Run the message loop as Close() asynchronously deletes.
   1644   RunPendingMessages();
   1645   EXPECT_TRUE(destroyed);
   1646   // Close() should destroy the widget. If not we'll cleanup to avoid leaks.
   1647   if (!destroyed) {
   1648     widget->Detach();
   1649     widget->CloseNow();
   1650   }
   1651 }
   1652 
   1653 // Tests that killing a widget while animating it does not crash.
   1654 TEST_F(WidgetTest, CloseWidgetWhileAnimating) {
   1655   scoped_ptr<Widget> widget(new Widget);
   1656   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
   1657   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   1658   widget->Init(params);
   1659 
   1660   // Normal animations for tests have ZERO_DURATION, make sure we are actually
   1661   // animating the movement.
   1662   ui::ScopedAnimationDurationScaleMode animation_scale_mode(
   1663       ui::ScopedAnimationDurationScaleMode::NORMAL_DURATION);
   1664   ui::ScopedLayerAnimationSettings animation_settings(
   1665       widget->GetLayer()->GetAnimator());
   1666   widget->Show();
   1667   // Animate the bounds change.
   1668   widget->SetBounds(gfx::Rect(0, 0, 200, 200));
   1669 }
   1670 
   1671 // A view that consumes mouse-pressed event and gesture-tap-down events.
   1672 class RootViewTestView : public View {
   1673  public:
   1674   RootViewTestView(): View() {}
   1675 
   1676  private:
   1677   virtual bool OnMousePressed(const ui::MouseEvent& event) OVERRIDE {
   1678     return true;
   1679   }
   1680 
   1681   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
   1682     if (event->type() == ui::ET_GESTURE_TAP_DOWN)
   1683       event->SetHandled();
   1684   }
   1685 };
   1686 
   1687 // Checks if RootView::*_handler_ fields are unset when widget is hidden.
   1688 // Fails on chromium.webkit Windows bot, see crbug.com/264872.
   1689 #if defined(OS_WIN)
   1690 #define MAYBE_DisableTestRootViewHandlersWhenHidden\
   1691     DISABLED_TestRootViewHandlersWhenHidden
   1692 #else
   1693 #define MAYBE_DisableTestRootViewHandlersWhenHidden\
   1694     TestRootViewHandlersWhenHidden
   1695 #endif
   1696 TEST_F(WidgetTest, MAYBE_DisableTestRootViewHandlersWhenHidden) {
   1697   Widget* widget = CreateTopLevelNativeWidget();
   1698   widget->SetBounds(gfx::Rect(0, 0, 300, 300));
   1699   View* view = new RootViewTestView();
   1700   view->SetBounds(0, 0, 300, 300);
   1701   internal::RootView* root_view =
   1702       static_cast<internal::RootView*>(widget->GetRootView());
   1703   root_view->AddChildView(view);
   1704 
   1705   // Check RootView::mouse_pressed_handler_.
   1706   widget->Show();
   1707   EXPECT_EQ(NULL, GetMousePressedHandler(root_view));
   1708   gfx::Point click_location(45, 15);
   1709   ui::MouseEvent press(ui::ET_MOUSE_PRESSED, click_location, click_location,
   1710                        ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON);
   1711   widget->OnMouseEvent(&press);
   1712   EXPECT_EQ(view, GetMousePressedHandler(root_view));
   1713   widget->Hide();
   1714   EXPECT_EQ(NULL, GetMousePressedHandler(root_view));
   1715 
   1716   // Check RootView::mouse_move_handler_.
   1717   widget->Show();
   1718   EXPECT_EQ(NULL, GetMouseMoveHandler(root_view));
   1719   gfx::Point move_location(45, 15);
   1720   ui::MouseEvent move(ui::ET_MOUSE_MOVED, move_location, move_location, 0, 0);
   1721   widget->OnMouseEvent(&move);
   1722   EXPECT_EQ(view, GetMouseMoveHandler(root_view));
   1723   widget->Hide();
   1724   EXPECT_EQ(NULL, GetMouseMoveHandler(root_view));
   1725 
   1726   // Check RootView::gesture_handler_.
   1727   widget->Show();
   1728   EXPECT_EQ(NULL, GetGestureHandler(root_view));
   1729   ui::GestureEvent tap_down(
   1730       ui::ET_GESTURE_TAP_DOWN,
   1731       15,
   1732       15,
   1733       0,
   1734       base::TimeDelta(),
   1735       ui::GestureEventDetails(ui::ET_GESTURE_TAP_DOWN, 0, 0),
   1736       1);
   1737   widget->OnGestureEvent(&tap_down);
   1738   EXPECT_EQ(view, GetGestureHandler(root_view));
   1739   widget->Hide();
   1740   EXPECT_EQ(NULL, GetGestureHandler(root_view));
   1741 
   1742   widget->Close();
   1743 }
   1744 
   1745 class GestureEndConsumerView : public View {
   1746  private:
   1747   virtual void OnGestureEvent(ui::GestureEvent* event) OVERRIDE {
   1748     if (event->type() == ui::ET_GESTURE_END)
   1749       event->SetHandled();
   1750   }
   1751 };
   1752 
   1753 TEST_F(WidgetTest, GestureHandlerNotSetOnGestureEnd) {
   1754   Widget* widget = CreateTopLevelNativeWidget();
   1755   widget->SetBounds(gfx::Rect(0, 0, 300, 300));
   1756   View* view = new GestureEndConsumerView();
   1757   view->SetBounds(0, 0, 300, 300);
   1758   internal::RootView* root_view =
   1759       static_cast<internal::RootView*>(widget->GetRootView());
   1760   root_view->AddChildView(view);
   1761 
   1762   widget->Show();
   1763   EXPECT_EQ(NULL, GetGestureHandler(root_view));
   1764   ui::GestureEvent end(ui::ET_GESTURE_END, 15, 15, 0, base::TimeDelta(),
   1765                        ui::GestureEventDetails(ui::ET_GESTURE_END, 0, 0), 1);
   1766   widget->OnGestureEvent(&end);
   1767   EXPECT_EQ(NULL, GetGestureHandler(root_view));
   1768 
   1769   widget->Close();
   1770 }
   1771 
   1772 // Test the result of Widget::GetAllChildWidgets().
   1773 TEST_F(WidgetTest, GetAllChildWidgets) {
   1774   // Create the following widget hierarchy:
   1775   //
   1776   // toplevel
   1777   // +-- w1
   1778   //     +-- w11
   1779   // +-- w2
   1780   //     +-- w21
   1781   //     +-- w22
   1782   Widget* toplevel = CreateTopLevelPlatformWidget();
   1783   Widget* w1 = CreateChildPlatformWidget(toplevel->GetNativeView());
   1784   Widget* w11 = CreateChildPlatformWidget(w1->GetNativeView());
   1785   Widget* w2 = CreateChildPlatformWidget(toplevel->GetNativeView());
   1786   Widget* w21 = CreateChildPlatformWidget(w2->GetNativeView());
   1787   Widget* w22 = CreateChildPlatformWidget(w2->GetNativeView());
   1788 
   1789   std::set<Widget*> expected;
   1790   expected.insert(toplevel);
   1791   expected.insert(w1);
   1792   expected.insert(w11);
   1793   expected.insert(w2);
   1794   expected.insert(w21);
   1795   expected.insert(w22);
   1796 
   1797   std::set<Widget*> widgets;
   1798   Widget::GetAllChildWidgets(toplevel->GetNativeView(), &widgets);
   1799 
   1800   EXPECT_EQ(expected.size(), widgets.size());
   1801   EXPECT_TRUE(std::equal(expected.begin(), expected.end(), widgets.begin()));
   1802 }
   1803 
   1804 // Used by DestroyChildWidgetsInOrder. On destruction adds the supplied name to
   1805 // a vector.
   1806 class DestroyedTrackingView : public View {
   1807  public:
   1808   DestroyedTrackingView(const std::string& name,
   1809                         std::vector<std::string>* add_to)
   1810       : name_(name),
   1811         add_to_(add_to) {
   1812   }
   1813 
   1814   virtual ~DestroyedTrackingView() {
   1815     add_to_->push_back(name_);
   1816   }
   1817 
   1818  private:
   1819   const std::string name_;
   1820   std::vector<std::string>* add_to_;
   1821 
   1822   DISALLOW_COPY_AND_ASSIGN(DestroyedTrackingView);
   1823 };
   1824 
   1825 class WidgetChildDestructionTest : public WidgetTest {
   1826  public:
   1827   WidgetChildDestructionTest() {}
   1828 
   1829   // Creates a top level and a child, destroys the child and verifies the views
   1830   // of the child are destroyed before the views of the parent.
   1831   void RunDestroyChildWidgetsTest(bool top_level_has_desktop_native_widget_aura,
   1832                                   bool child_has_desktop_native_widget_aura) {
   1833     // When a View is destroyed its name is added here.
   1834     std::vector<std::string> destroyed;
   1835 
   1836     Widget* top_level = new Widget;
   1837     Widget::InitParams params =
   1838         CreateParams(views::Widget::InitParams::TYPE_WINDOW);
   1839 #if !defined(OS_CHROMEOS)
   1840     if (top_level_has_desktop_native_widget_aura)
   1841       params.native_widget = new PlatformDesktopNativeWidget(top_level);
   1842 #endif
   1843     top_level->Init(params);
   1844     top_level->GetRootView()->AddChildView(
   1845         new DestroyedTrackingView("parent", &destroyed));
   1846     top_level->Show();
   1847 
   1848     Widget* child = new Widget;
   1849     Widget::InitParams child_params =
   1850         CreateParams(views::Widget::InitParams::TYPE_POPUP);
   1851     child_params.parent = top_level->GetNativeView();
   1852 #if !defined(OS_CHROMEOS)
   1853     if (child_has_desktop_native_widget_aura)
   1854       child_params.native_widget = new PlatformDesktopNativeWidget(child);
   1855 #endif
   1856     child->Init(child_params);
   1857     child->GetRootView()->AddChildView(
   1858         new DestroyedTrackingView("child", &destroyed));
   1859     child->Show();
   1860 
   1861     // Should trigger destruction of the child too.
   1862     top_level->native_widget_private()->CloseNow();
   1863 
   1864     // Child should be destroyed first.
   1865     ASSERT_EQ(2u, destroyed.size());
   1866     EXPECT_EQ("child", destroyed[0]);
   1867     EXPECT_EQ("parent", destroyed[1]);
   1868   }
   1869 
   1870  private:
   1871   DISALLOW_COPY_AND_ASSIGN(WidgetChildDestructionTest);
   1872 };
   1873 
   1874 #if !defined(OS_CHROMEOS)
   1875 // See description of RunDestroyChildWidgetsTest(). Parent uses
   1876 // DesktopNativeWidgetAura.
   1877 TEST_F(WidgetChildDestructionTest,
   1878        DestroyChildWidgetsInOrderWithDesktopNativeWidget) {
   1879   RunDestroyChildWidgetsTest(true, false);
   1880 }
   1881 
   1882 // See description of RunDestroyChildWidgetsTest(). Both parent and child use
   1883 // DesktopNativeWidgetAura.
   1884 TEST_F(WidgetChildDestructionTest,
   1885        DestroyChildWidgetsInOrderWithDesktopNativeWidgetForBoth) {
   1886   RunDestroyChildWidgetsTest(true, true);
   1887 }
   1888 #endif  // !defined(OS_CHROMEOS)
   1889 
   1890 // See description of RunDestroyChildWidgetsTest().
   1891 TEST_F(WidgetChildDestructionTest, DestroyChildWidgetsInOrder) {
   1892   RunDestroyChildWidgetsTest(false, false);
   1893 }
   1894 
   1895 #if !defined(OS_CHROMEOS)
   1896 // Provides functionality to create a window modal dialog.
   1897 class ModalDialogDelegate : public DialogDelegateView {
   1898  public:
   1899   ModalDialogDelegate() {}
   1900   virtual ~ModalDialogDelegate() {}
   1901 
   1902   // WidgetDelegate overrides.
   1903   virtual ui::ModalType GetModalType() const OVERRIDE {
   1904     return ui::MODAL_TYPE_WINDOW;
   1905   }
   1906 
   1907  private:
   1908   DISALLOW_COPY_AND_ASSIGN(ModalDialogDelegate);
   1909 };
   1910 
   1911 // This test verifies that whether mouse events when a modal dialog is
   1912 // displayed are eaten or recieved by the dialog.
   1913 TEST_F(WidgetTest, WindowMouseModalityTest) {
   1914   // Create a top level widget.
   1915   Widget top_level_widget;
   1916   Widget::InitParams init_params =
   1917       CreateParams(Widget::InitParams::TYPE_WINDOW);
   1918   init_params.show_state = ui::SHOW_STATE_NORMAL;
   1919   gfx::Rect initial_bounds(0, 0, 500, 500);
   1920   init_params.bounds = initial_bounds;
   1921   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   1922   init_params.native_widget =
   1923       new PlatformDesktopNativeWidget(&top_level_widget);
   1924   top_level_widget.Init(init_params);
   1925   top_level_widget.Show();
   1926   EXPECT_TRUE(top_level_widget.IsVisible());
   1927 
   1928   // Create a view and validate that a mouse moves makes it to the view.
   1929   EventCountView* widget_view = new EventCountView();
   1930   widget_view->SetBounds(0, 0, 10, 10);
   1931   top_level_widget.GetRootView()->AddChildView(widget_view);
   1932 
   1933   gfx::Point cursor_location_main(5, 5);
   1934   ui::MouseEvent move_main(ui::ET_MOUSE_MOVED,
   1935                            cursor_location_main,
   1936                            cursor_location_main,
   1937                            ui::EF_NONE,
   1938                            ui::EF_NONE);
   1939   ui::EventDispatchDetails details =
   1940       GetEventProcessor(&top_level_widget)->OnEventFromSource(&move_main);
   1941   ASSERT_FALSE(details.dispatcher_destroyed);
   1942 
   1943   EXPECT_EQ(1, widget_view->GetEventCount(ui::ET_MOUSE_ENTERED));
   1944   widget_view->ResetCounts();
   1945 
   1946   // Create a modal dialog and validate that a mouse down message makes it to
   1947   // the main view within the dialog.
   1948 
   1949   // This instance will be destroyed when the dialog is destroyed.
   1950   ModalDialogDelegate* dialog_delegate = new ModalDialogDelegate;
   1951 
   1952   Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget(
   1953       dialog_delegate, NULL, top_level_widget.GetNativeView());
   1954   modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200));
   1955   EventCountView* dialog_widget_view = new EventCountView();
   1956   dialog_widget_view->SetBounds(0, 0, 50, 50);
   1957   modal_dialog_widget->GetRootView()->AddChildView(dialog_widget_view);
   1958   modal_dialog_widget->Show();
   1959   EXPECT_TRUE(modal_dialog_widget->IsVisible());
   1960 
   1961   gfx::Point cursor_location_dialog(100, 100);
   1962   ui::MouseEvent mouse_down_dialog(ui::ET_MOUSE_PRESSED,
   1963                                    cursor_location_dialog,
   1964                                    cursor_location_dialog,
   1965                                    ui::EF_NONE,
   1966                                    ui::EF_NONE);
   1967   details = GetEventProcessor(&top_level_widget)->OnEventFromSource(
   1968       &mouse_down_dialog);
   1969   ASSERT_FALSE(details.dispatcher_destroyed);
   1970   EXPECT_EQ(1, dialog_widget_view->GetEventCount(ui::ET_MOUSE_PRESSED));
   1971 
   1972   // Send a mouse move message to the main window. It should not be received by
   1973   // the main window as the modal dialog is still active.
   1974   gfx::Point cursor_location_main2(6, 6);
   1975   ui::MouseEvent mouse_down_main(ui::ET_MOUSE_MOVED,
   1976                                  cursor_location_main2,
   1977                                  cursor_location_main2,
   1978                                  ui::EF_NONE,
   1979                                  ui::EF_NONE);
   1980   details = GetEventProcessor(&top_level_widget)->OnEventFromSource(
   1981       &mouse_down_main);
   1982   ASSERT_FALSE(details.dispatcher_destroyed);
   1983   EXPECT_EQ(0, widget_view->GetEventCount(ui::ET_MOUSE_MOVED));
   1984 
   1985   modal_dialog_widget->CloseNow();
   1986   top_level_widget.CloseNow();
   1987 }
   1988 
   1989 // Verifies nativeview visbility matches that of Widget visibility when
   1990 // SetFullscreen is invoked.
   1991 TEST_F(WidgetTest, FullscreenStatePropagated) {
   1992   Widget::InitParams init_params =
   1993       CreateParams(Widget::InitParams::TYPE_WINDOW);
   1994   init_params.show_state = ui::SHOW_STATE_NORMAL;
   1995   init_params.bounds = gfx::Rect(0, 0, 500, 500);
   1996   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   1997 
   1998   {
   1999     Widget top_level_widget;
   2000     top_level_widget.Init(init_params);
   2001     top_level_widget.SetFullscreen(true);
   2002     EXPECT_EQ(top_level_widget.IsVisible(),
   2003               IsNativeWindowVisible(top_level_widget.GetNativeWindow()));
   2004     top_level_widget.CloseNow();
   2005   }
   2006 
   2007 #if !defined(OS_CHROMEOS)
   2008   {
   2009     Widget top_level_widget;
   2010     init_params.native_widget =
   2011         new PlatformDesktopNativeWidget(&top_level_widget);
   2012     top_level_widget.Init(init_params);
   2013     top_level_widget.SetFullscreen(true);
   2014     EXPECT_EQ(top_level_widget.IsVisible(),
   2015               IsNativeWindowVisible(top_level_widget.GetNativeWindow()));
   2016     top_level_widget.CloseNow();
   2017   }
   2018 #endif
   2019 }
   2020 
   2021 #if defined(OS_WIN)
   2022 
   2023 // Provides functionality to test widget activation via an activation flag
   2024 // which can be set by an accessor.
   2025 class ModalWindowTestWidgetDelegate : public WidgetDelegate {
   2026  public:
   2027   ModalWindowTestWidgetDelegate()
   2028       : widget_(NULL),
   2029         can_activate_(true) {}
   2030 
   2031   virtual ~ModalWindowTestWidgetDelegate() {}
   2032 
   2033   // Overridden from WidgetDelegate:
   2034   virtual void DeleteDelegate() OVERRIDE {
   2035     delete this;
   2036   }
   2037   virtual Widget* GetWidget() OVERRIDE {
   2038     return widget_;
   2039   }
   2040   virtual const Widget* GetWidget() const OVERRIDE {
   2041     return widget_;
   2042   }
   2043   virtual bool CanActivate() const OVERRIDE {
   2044     return can_activate_;
   2045   }
   2046   virtual bool ShouldAdvanceFocusToTopLevelWidget() const OVERRIDE {
   2047     return true;
   2048   }
   2049 
   2050   void set_can_activate(bool can_activate) {
   2051     can_activate_ = can_activate;
   2052   }
   2053 
   2054   void set_widget(Widget* widget) {
   2055     widget_ = widget;
   2056   }
   2057 
   2058  private:
   2059   Widget* widget_;
   2060   bool can_activate_;
   2061 
   2062   DISALLOW_COPY_AND_ASSIGN(ModalWindowTestWidgetDelegate);
   2063 };
   2064 
   2065 // Tests whether we can activate the top level widget when a modal dialog is
   2066 // active.
   2067 TEST_F(WidgetTest, WindowModalityActivationTest) {
   2068   // Destroyed when the top level widget created below is destroyed.
   2069   ModalWindowTestWidgetDelegate* widget_delegate =
   2070       new ModalWindowTestWidgetDelegate;
   2071   // Create a top level widget.
   2072   Widget top_level_widget;
   2073   Widget::InitParams init_params =
   2074       CreateParams(Widget::InitParams::TYPE_WINDOW);
   2075   init_params.show_state = ui::SHOW_STATE_NORMAL;
   2076   gfx::Rect initial_bounds(0, 0, 500, 500);
   2077   init_params.bounds = initial_bounds;
   2078   init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   2079   init_params.native_widget = new DesktopNativeWidgetAura(&top_level_widget);
   2080   init_params.delegate = widget_delegate;
   2081   top_level_widget.Init(init_params);
   2082   widget_delegate->set_widget(&top_level_widget);
   2083   top_level_widget.Show();
   2084   EXPECT_TRUE(top_level_widget.IsVisible());
   2085 
   2086   HWND win32_window = views::HWNDForWidget(&top_level_widget);
   2087   EXPECT_TRUE(::IsWindow(win32_window));
   2088 
   2089   // This instance will be destroyed when the dialog is destroyed.
   2090   ModalDialogDelegate* dialog_delegate = new ModalDialogDelegate;
   2091 
   2092   // We should be able to activate the window even if the WidgetDelegate
   2093   // says no, when a modal dialog is active.
   2094   widget_delegate->set_can_activate(false);
   2095 
   2096   Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget(
   2097       dialog_delegate, NULL, top_level_widget.GetNativeWindow());
   2098   modal_dialog_widget->SetBounds(gfx::Rect(100, 100, 200, 200));
   2099   modal_dialog_widget->Show();
   2100   EXPECT_TRUE(modal_dialog_widget->IsVisible());
   2101 
   2102   LRESULT activate_result = ::SendMessage(
   2103       win32_window,
   2104       WM_MOUSEACTIVATE,
   2105       reinterpret_cast<WPARAM>(win32_window),
   2106       MAKELPARAM(WM_LBUTTONDOWN, HTCLIENT));
   2107   EXPECT_EQ(activate_result, MA_ACTIVATE);
   2108 
   2109   modal_dialog_widget->CloseNow();
   2110   top_level_widget.CloseNow();
   2111 }
   2112 #endif  // defined(OS_WIN)
   2113 #endif  // !defined(OS_CHROMEOS)
   2114 
   2115 TEST_F(WidgetTest, ShowCreatesActiveWindow) {
   2116   Widget* widget = CreateTopLevelPlatformWidget();
   2117 
   2118   widget->Show();
   2119   EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
   2120 
   2121   widget->CloseNow();
   2122 }
   2123 
   2124 TEST_F(WidgetTest, ShowInactive) {
   2125   Widget* widget = CreateTopLevelPlatformWidget();
   2126 
   2127   widget->ShowInactive();
   2128   EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_INACTIVE);
   2129 
   2130   widget->CloseNow();
   2131 }
   2132 
   2133 TEST_F(WidgetTest, ShowInactiveAfterShow) {
   2134   Widget* widget = CreateTopLevelPlatformWidget();
   2135 
   2136   widget->Show();
   2137   widget->ShowInactive();
   2138   EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
   2139 
   2140   widget->CloseNow();
   2141 }
   2142 
   2143 TEST_F(WidgetTest, ShowAfterShowInactive) {
   2144   Widget* widget = CreateTopLevelPlatformWidget();
   2145 
   2146   widget->ShowInactive();
   2147   widget->Show();
   2148   EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
   2149 
   2150   widget->CloseNow();
   2151 }
   2152 
   2153 #if !defined(OS_CHROMEOS)
   2154 TEST_F(WidgetTest, InactiveWidgetDoesNotGrabActivation) {
   2155   Widget* widget = CreateTopLevelPlatformWidget();
   2156   widget->Show();
   2157   EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
   2158 
   2159   Widget widget2;
   2160   Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
   2161   params.native_widget = new PlatformDesktopNativeWidget(&widget2);
   2162   params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   2163   widget2.Init(params);
   2164   widget2.Show();
   2165 
   2166   EXPECT_EQ(GetWidgetShowState(&widget2), ui::SHOW_STATE_INACTIVE);
   2167   EXPECT_EQ(GetWidgetShowState(widget), ui::SHOW_STATE_NORMAL);
   2168 
   2169   widget->CloseNow();
   2170   widget2.CloseNow();
   2171 }
   2172 #endif  // !defined(OS_CHROMEOS)
   2173 
   2174 namespace {
   2175 
   2176 class FullscreenAwareFrame : public views::NonClientFrameView {
   2177  public:
   2178   explicit FullscreenAwareFrame(views::Widget* widget)
   2179       : widget_(widget), fullscreen_layout_called_(false) {}
   2180   virtual ~FullscreenAwareFrame() {}
   2181 
   2182   // views::NonClientFrameView overrides:
   2183   virtual gfx::Rect GetBoundsForClientView() const OVERRIDE {
   2184     return gfx::Rect();
   2185   }
   2186   virtual gfx::Rect GetWindowBoundsForClientBounds(
   2187       const gfx::Rect& client_bounds) const OVERRIDE {
   2188     return gfx::Rect();
   2189   }
   2190   virtual int NonClientHitTest(const gfx::Point& point) OVERRIDE {
   2191     return HTNOWHERE;
   2192   }
   2193   virtual void GetWindowMask(const gfx::Size& size,
   2194                              gfx::Path* window_mask) OVERRIDE {}
   2195   virtual void ResetWindowControls() OVERRIDE {}
   2196   virtual void UpdateWindowIcon() OVERRIDE {}
   2197   virtual void UpdateWindowTitle() OVERRIDE {}
   2198 
   2199   // views::View overrides:
   2200   virtual void Layout() OVERRIDE {
   2201     if (widget_->IsFullscreen())
   2202       fullscreen_layout_called_ = true;
   2203   }
   2204 
   2205   bool fullscreen_layout_called() const { return fullscreen_layout_called_; }
   2206 
   2207  private:
   2208   views::Widget* widget_;
   2209   bool fullscreen_layout_called_;
   2210 
   2211   DISALLOW_COPY_AND_ASSIGN(FullscreenAwareFrame);
   2212 };
   2213 
   2214 }  // namespace
   2215 
   2216 // Tests that frame Layout is called when a widget goes fullscreen without
   2217 // changing its size or title.
   2218 TEST_F(WidgetTest, FullscreenFrameLayout) {
   2219   Widget* widget = CreateTopLevelPlatformWidget();
   2220   FullscreenAwareFrame* frame = new FullscreenAwareFrame(widget);
   2221   widget->non_client_view()->SetFrameView(frame);  // Owns |frame|.
   2222 
   2223   widget->Maximize();
   2224   RunPendingMessages();
   2225 
   2226   EXPECT_FALSE(frame->fullscreen_layout_called());
   2227   widget->SetFullscreen(true);
   2228   widget->Show();
   2229   RunPendingMessages();
   2230   EXPECT_TRUE(frame->fullscreen_layout_called());
   2231 
   2232   widget->CloseNow();
   2233 }
   2234 
   2235 #if !defined(OS_CHROMEOS)
   2236 namespace {
   2237 
   2238 // Trivial WidgetObserverTest that invokes Widget::IsActive() from
   2239 // OnWindowDestroying.
   2240 class IsActiveFromDestroyObserver : public WidgetObserver {
   2241  public:
   2242   IsActiveFromDestroyObserver() {}
   2243   virtual ~IsActiveFromDestroyObserver() {}
   2244   virtual void OnWidgetDestroying(Widget* widget) OVERRIDE {
   2245     widget->IsActive();
   2246   }
   2247 
   2248  private:
   2249   DISALLOW_COPY_AND_ASSIGN(IsActiveFromDestroyObserver);
   2250 };
   2251 
   2252 }  // namespace
   2253 
   2254 // Verifies Widget::IsActive() invoked from
   2255 // WidgetObserver::OnWidgetDestroying() in a child widget doesn't crash.
   2256 TEST_F(WidgetTest, IsActiveFromDestroy) {
   2257   // Create two widgets, one a child of the other.
   2258   IsActiveFromDestroyObserver observer;
   2259   Widget parent_widget;
   2260   Widget::InitParams parent_params =
   2261       CreateParams(Widget::InitParams::TYPE_POPUP);
   2262   parent_params.native_widget = new PlatformDesktopNativeWidget(&parent_widget);
   2263   parent_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   2264   parent_widget.Init(parent_params);
   2265   parent_widget.Show();
   2266 
   2267   Widget child_widget;
   2268   Widget::InitParams child_params =
   2269       CreateParams(Widget::InitParams::TYPE_POPUP);
   2270   child_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
   2271   child_params.context = parent_widget.GetNativeView();
   2272   child_widget.Init(child_params);
   2273   child_widget.AddObserver(&observer);
   2274   child_widget.Show();
   2275 
   2276   parent_widget.CloseNow();
   2277 }
   2278 #endif  // !defined(OS_CHROMEOS)
   2279 
   2280 }  // namespace test
   2281 }  // namespace views
   2282