Drive: Add BatchableRequest subclass.
[chromium-blink-merge.git] / ui / views / controls / native / native_view_host_mac_unittest.mm
blob3e84416f3507914493978e8ed2697a68a61aed35
1 // Copyright 2014 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.
5 #include "ui/views/controls/native/native_view_host_mac.h"
7 #import <Cocoa/Cocoa.h>
9 #import "base/mac/scoped_nsautorelease_pool.h"
10 #import "base/mac/scoped_nsobject.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "ui/views/controls/native/native_view_host.h"
13 #include "ui/views/controls/native/native_view_host_test_base.h"
14 #include "ui/views/view.h"
15 #include "ui/views/widget/widget.h"
17 namespace views {
19 class NativeViewHostMacTest : public test::NativeViewHostTestBase {
20  public:
21   NativeViewHostMacTest() {}
23   // testing::Test:
24   void TearDown() override {
25     // On Aura, the compositor is destroyed when the WindowTreeHost provided by
26     // AuraTestHelper is destroyed. On Mac, the Widget is the host, so it must
27     // be closed before the ContextFactory is torn down by ViewsTestBase.
28     DestroyTopLevel();
29     NativeViewHostTestBase::TearDown();
30   }
32   NativeViewHostMac* native_host() {
33     return static_cast<NativeViewHostMac*>(GetNativeWrapper());
34   }
36   void CreateHost() {
37     CreateTopLevel();
38     CreateTestingHost();
39     native_view_.reset([[NSView alloc] initWithFrame:NSZeroRect]);
41     // Verify the expectation that the NativeViewHostWrapper is only created
42     // after the NativeViewHost is added to a widget.
43     EXPECT_FALSE(native_host());
44     toplevel()->GetRootView()->AddChildView(host());
45     EXPECT_TRUE(native_host());
47     host()->Attach(native_view_);
48   }
50  protected:
51   base::scoped_nsobject<NSView> native_view_;
53  private:
54   DISALLOW_COPY_AND_ASSIGN(NativeViewHostMacTest);
57 // Test destroying the top level widget before destroying the NativeViewHost.
58 // On Mac, also ensure that the native view is removed from its superview when
59 // the Widget containing its host is destroyed.
60 TEST_F(NativeViewHostMacTest, DestroyWidget) {
61   ResetHostDestroyedCount();
62   CreateHost();
63   ReleaseHost();
64   EXPECT_EQ(0, host_destroyed_count());
65   EXPECT_TRUE([native_view_ superview]);
66   DestroyTopLevel();
67   EXPECT_FALSE([native_view_ superview]);
68   EXPECT_EQ(1, host_destroyed_count());
71 // Ensure the native view receives the correct bounds when it is attached. On
72 // Mac, the bounds of the native view is relative to the NSWindow it is in, not
73 // the screen, and the coordinates have to be flipped.
74 TEST_F(NativeViewHostMacTest, Attach) {
75   CreateHost();
76   EXPECT_TRUE([native_view_ superview]);
77   EXPECT_TRUE([native_view_ window]);
79   host()->Detach();
81   [native_view_ setFrame:NSZeroRect];
82   toplevel()->SetBounds(gfx::Rect(64, 48, 100, 200));
83   host()->SetBounds(10, 10, 80, 60);
85   EXPECT_FALSE([native_view_ superview]);
86   EXPECT_FALSE([native_view_ window]);
87   EXPECT_TRUE(NSEqualRects(NSZeroRect, [native_view_ frame]));
89   host()->Attach(native_view_);
90   EXPECT_TRUE([native_view_ superview]);
91   EXPECT_TRUE([native_view_ window]);
93   // Expect the top-left to be 10 pixels below the titlebar.
94   int bottom = toplevel()->GetClientAreaBoundsInScreen().height() - 10 - 60;
95   EXPECT_TRUE(NSEqualRects(NSMakeRect(10, bottom, 80, 60),
96                            [native_view_ frame]));
98   DestroyHost();
101 // Ensure the native view is hidden along with its host, and when detaching, or
102 // when attaching to a host that is already hidden.
103 TEST_F(NativeViewHostMacTest, NativeViewHidden) {
104   CreateHost();
105   toplevel()->SetBounds(gfx::Rect(0, 0, 100, 100));
106   host()->SetBounds(10, 10, 80, 60);
108   EXPECT_FALSE([native_view_ isHidden]);
109   host()->SetVisible(false);
110   EXPECT_TRUE([native_view_ isHidden]);
111   host()->SetVisible(true);
112   EXPECT_FALSE([native_view_ isHidden]);
114   host()->Detach();
115   EXPECT_TRUE([native_view_ isHidden]);  // Hidden when detached.
116   [native_view_ setHidden:NO];
118   host()->SetVisible(false);
119   EXPECT_FALSE([native_view_ isHidden]);  // Stays visible.
120   host()->Attach(native_view_);
121   EXPECT_TRUE([native_view_ isHidden]);  // Hidden when attached.
123   host()->Detach();
124   [native_view_ setHidden:YES];
125   host()->SetVisible(true);
126   EXPECT_TRUE([native_view_ isHidden]);  // Stays hidden.
127   host()->Attach(native_view_);
128   EXPECT_FALSE([native_view_ isHidden]);  // Made visible when attached.
130   EXPECT_TRUE([native_view_ superview]);
131   toplevel()->GetRootView()->RemoveChildView(host());
132   EXPECT_TRUE([native_view_ isHidden]);  // Hidden when removed from Widget.
133   EXPECT_FALSE([native_view_ superview]);
135   toplevel()->GetRootView()->AddChildView(host());
136   EXPECT_FALSE([native_view_ isHidden]);  // And visible when added.
137   EXPECT_TRUE([native_view_ superview]);
139   DestroyHost();
142 // Check that we can destroy cleanly even if the native view has already been
143 // released.
144 TEST_F(NativeViewHostMacTest, NativeViewReleased) {
145   {
146     base::mac::ScopedNSAutoreleasePool pool;
147     CreateHost();
148     // In practice the native view is a WebContentsViewCocoa which is retained
149     // by its superview (a TabContentsContainerView) and by WebContentsViewMac.
150     // It's possible for both of them to be destroyed without calling
151     // NativeHostView::Detach().
152     [native_view_ removeFromSuperview];
153     native_view_.reset();
154   }
156   // During teardown, NativeViewDetaching() is called in RemovedFromWidget().
157   // Just trigger it with Detach().
158   host()->Detach();
160   DestroyHost();
163 }  // namespace views