Drive: Add BatchableRequest subclass.
[chromium-blink-merge.git] / ui / views / controls / native / native_view_host_aura_unittest.cc
blob5f03fc86ee3771fc5f7877801296a32f8f2e3c9b
1 // Copyright (c) 2013 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_aura.h"
7 #include "base/basictypes.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "ui/aura/client/aura_constants.h"
10 #include "ui/aura/window.h"
11 #include "ui/base/cursor/cursor.h"
12 #include "ui/events/event_utils.h"
13 #include "ui/views/controls/native/native_view_host.h"
14 #include "ui/views/controls/native/native_view_host_test_base.h"
15 #include "ui/views/view.h"
16 #include "ui/views/view_constants_aura.h"
17 #include "ui/views/widget/widget.h"
19 namespace views {
21 // Observer watching for window visibility and bounds change events. This is
22 // used to verify that the child and clipping window operations are done in the
23 // right order.
24 class NativeViewHostWindowObserver : public aura::WindowObserver {
25 public:
26 enum EventType {
27 EVENT_NONE,
28 EVENT_SHOWN,
29 EVENT_HIDDEN,
30 EVENT_BOUNDS_CHANGED,
33 struct EventDetails {
34 EventType type;
35 aura::Window* window;
36 gfx::Rect bounds;
37 bool operator!=(const EventDetails& rhs) {
38 return type != rhs.type || window != rhs.window || bounds != rhs.bounds;
42 NativeViewHostWindowObserver() {}
43 ~NativeViewHostWindowObserver() override {}
45 const std::vector<EventDetails>& events() const { return events_; }
47 // aura::WindowObserver overrides
48 void OnWindowVisibilityChanged(aura::Window* window, bool visible) override {
49 EventDetails event;
50 event.type = visible ? EVENT_SHOWN : EVENT_HIDDEN;
51 event.window = window;
52 event.bounds = window->GetBoundsInRootWindow();
54 // Dedupe events as a single Hide() call can result in several
55 // notifications.
56 if (events_.size() == 0u || events_.back() != event)
57 events_.push_back(event);
60 void OnWindowBoundsChanged(aura::Window* window,
61 const gfx::Rect& old_bounds,
62 const gfx::Rect& new_bounds) override {
63 EventDetails event;
64 event.type = EVENT_BOUNDS_CHANGED;
65 event.window = window;
66 event.bounds = window->GetBoundsInRootWindow();
67 events_.push_back(event);
70 private:
71 std::vector<EventDetails> events_;
72 gfx::Rect bounds_at_visibility_changed_;
74 DISALLOW_COPY_AND_ASSIGN(NativeViewHostWindowObserver);
77 class NativeViewHostAuraTest : public test::NativeViewHostTestBase {
78 public:
79 NativeViewHostAuraTest() {
82 NativeViewHostAura* native_host() {
83 return static_cast<NativeViewHostAura*>(GetNativeWrapper());
86 Widget* child() {
87 return child_.get();
90 aura::Window* clipping_window() { return &(native_host()->clipping_window_); }
92 void CreateHost() {
93 CreateTopLevel();
94 CreateTestingHost();
95 child_.reset(CreateChildForHost(toplevel()->GetNativeView(),
96 toplevel()->GetRootView(),
97 new View,
98 host()));
101 private:
102 scoped_ptr<Widget> child_;
104 DISALLOW_COPY_AND_ASSIGN(NativeViewHostAuraTest);
107 // Verifies NativeViewHostAura stops observing native view on destruction.
108 TEST_F(NativeViewHostAuraTest, StopObservingNativeViewOnDestruct) {
109 CreateHost();
110 aura::Window* child_win = child()->GetNativeView();
111 NativeViewHostAura* aura_host = native_host();
113 EXPECT_TRUE(child_win->HasObserver(aura_host));
114 DestroyHost();
115 EXPECT_FALSE(child_win->HasObserver(aura_host));
118 // Tests that the kHostViewKey is correctly set and cleared.
119 TEST_F(NativeViewHostAuraTest, HostViewPropertyKey) {
120 // Create the NativeViewHost and attach a NativeView.
121 CreateHost();
122 aura::Window* child_win = child()->GetNativeView();
123 EXPECT_EQ(host(), child_win->GetProperty(views::kHostViewKey));
124 EXPECT_EQ(host()->GetWidget()->GetNativeView(),
125 child_win->GetProperty(aura::client::kHostWindowKey));
126 EXPECT_EQ(host(), clipping_window()->GetProperty(views::kHostViewKey));
128 host()->Detach();
129 EXPECT_FALSE(child_win->GetProperty(views::kHostViewKey));
130 EXPECT_FALSE(child_win->GetProperty(aura::client::kHostWindowKey));
131 EXPECT_TRUE(clipping_window()->GetProperty(views::kHostViewKey));
133 host()->Attach(child_win);
134 EXPECT_EQ(host(), child_win->GetProperty(views::kHostViewKey));
135 EXPECT_EQ(host()->GetWidget()->GetNativeView(),
136 child_win->GetProperty(aura::client::kHostWindowKey));
137 EXPECT_EQ(host(), clipping_window()->GetProperty(views::kHostViewKey));
139 DestroyHost();
140 EXPECT_FALSE(child_win->GetProperty(views::kHostViewKey));
141 EXPECT_FALSE(child_win->GetProperty(aura::client::kHostWindowKey));
144 // Tests that the NativeViewHost reports the cursor set on its native view.
145 TEST_F(NativeViewHostAuraTest, CursorForNativeView) {
146 CreateHost();
148 toplevel()->SetCursor(ui::kCursorHand);
149 child()->SetCursor(ui::kCursorWait);
150 ui::MouseEvent move_event(ui::ET_MOUSE_MOVED, gfx::Point(0, 0),
151 gfx::Point(0, 0), ui::EventTimeForNow(), 0, 0);
153 EXPECT_EQ(ui::kCursorWait, host()->GetCursor(move_event).native_type());
155 DestroyHost();
158 // Test that destroying the top level widget before destroying the attached
159 // NativeViewHost works correctly. Specifically the associated NVH should be
160 // destroyed and there shouldn't be any errors.
161 TEST_F(NativeViewHostAuraTest, DestroyWidget) {
162 ResetHostDestroyedCount();
163 CreateHost();
164 ReleaseHost();
165 EXPECT_EQ(0, host_destroyed_count());
166 DestroyTopLevel();
167 EXPECT_EQ(1, host_destroyed_count());
170 // Test that the fast resize path places the clipping and content windows were
171 // they are supposed to be.
172 TEST_F(NativeViewHostAuraTest, FastResizePath) {
173 CreateHost();
174 toplevel()->SetBounds(gfx::Rect(20, 20, 100, 100));
176 // Without fast resize, the clipping window should size to the native view
177 // with the native view positioned at the origin of the clipping window and
178 // the clipping window positioned where the native view was requested.
179 host()->set_fast_resize(false);
180 native_host()->ShowWidget(5, 10, 100, 100);
181 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
182 host()->native_view()->bounds().ToString());
183 EXPECT_EQ(gfx::Rect(5, 10, 100, 100).ToString(),
184 clipping_window()->bounds().ToString());
186 // With fast resize, the native view should remain the same size but be
187 // clipped the requested size.
188 host()->set_fast_resize(true);
189 native_host()->ShowWidget(10, 25, 50, 50);
190 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
191 host()->native_view()->bounds().ToString());
192 EXPECT_EQ(gfx::Rect(10, 25, 50, 50).ToString(),
193 clipping_window()->bounds().ToString());
195 // Turning off fast resize should make the native view start resizing again.
196 host()->set_fast_resize(false);
197 native_host()->ShowWidget(10, 25, 50, 50);
198 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(),
199 host()->native_view()->bounds().ToString());
200 EXPECT_EQ(gfx::Rect(10, 25, 50, 50).ToString(),
201 clipping_window()->bounds().ToString());
203 DestroyHost();
206 // Test installing and uninstalling a clip.
207 TEST_F(NativeViewHostAuraTest, InstallClip) {
208 CreateHost();
209 toplevel()->SetBounds(gfx::Rect(20, 20, 100, 100));
211 // Without a clip, the clipping window should always be positioned at the
212 // requested coordinates with the native view positioned at the origin of the
213 // clipping window.
214 native_host()->ShowWidget(10, 20, 100, 100);
215 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
216 host()->native_view()->bounds().ToString());
217 EXPECT_EQ(gfx::Rect(10, 20, 100, 100).ToString(),
218 clipping_window()->bounds().ToString());
220 // Clip to the bottom right quarter of the native view.
221 native_host()->InstallClip(60, 70, 50, 50);
222 native_host()->ShowWidget(10, 20, 100, 100);
223 EXPECT_EQ(gfx::Rect(-50, -50, 100, 100).ToString(),
224 host()->native_view()->bounds().ToString());
225 EXPECT_EQ(gfx::Rect(60, 70, 50, 50).ToString(),
226 clipping_window()->bounds().ToString());
228 // Clip to the center of the native view.
229 native_host()->InstallClip(35, 45, 50, 50);
230 native_host()->ShowWidget(10, 20, 100, 100);
231 EXPECT_EQ(gfx::Rect(-25, -25, 100, 100).ToString(),
232 host()->native_view()->bounds().ToString());
233 EXPECT_EQ(gfx::Rect(35, 45, 50, 50).ToString(),
234 clipping_window()->bounds().ToString());
236 // Uninstalling the clip should make the clipping window match the native view
237 // again.
238 native_host()->UninstallClip();
239 native_host()->ShowWidget(10, 20, 100, 100);
240 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(),
241 host()->native_view()->bounds().ToString());
242 EXPECT_EQ(gfx::Rect(10, 20, 100, 100).ToString(),
243 clipping_window()->bounds().ToString());
245 DestroyHost();
248 // Ensure native view is parented to the root window after detaching. This is
249 // a regression test for http://crbug.com/389261.
250 TEST_F(NativeViewHostAuraTest, ParentAfterDetach) {
251 CreateHost();
252 aura::Window* child_win = child()->GetNativeView();
253 aura::Window* root_window = child_win->GetRootWindow();
254 aura::WindowTreeHost* child_win_tree_host = child_win->GetHost();
256 host()->Detach();
257 EXPECT_EQ(root_window, child_win->GetRootWindow());
258 EXPECT_EQ(child_win_tree_host, child_win->GetHost());
260 DestroyHost();
263 // Ensure the clipping window is hidden before setting the native view's bounds.
264 // This is a regression test for http://crbug.com/388699.
265 TEST_F(NativeViewHostAuraTest, RemoveClippingWindowOrder) {
266 CreateHost();
267 toplevel()->SetBounds(gfx::Rect(20, 20, 100, 100));
268 native_host()->ShowWidget(10, 20, 100, 100);
270 NativeViewHostWindowObserver test_observer;
271 clipping_window()->AddObserver(&test_observer);
272 child()->GetNativeView()->AddObserver(&test_observer);
274 host()->Detach();
276 ASSERT_EQ(3u, test_observer.events().size());
277 EXPECT_EQ(NativeViewHostWindowObserver::EVENT_HIDDEN,
278 test_observer.events()[0].type);
279 EXPECT_EQ(clipping_window(), test_observer.events()[0].window);
280 EXPECT_EQ(NativeViewHostWindowObserver::EVENT_BOUNDS_CHANGED,
281 test_observer.events()[1].type);
282 EXPECT_EQ(child()->GetNativeView(), test_observer.events()[1].window);
283 EXPECT_EQ(NativeViewHostWindowObserver::EVENT_HIDDEN,
284 test_observer.events()[2].type);
285 EXPECT_EQ(child()->GetNativeView(), test_observer.events()[2].window);
287 clipping_window()->RemoveObserver(&test_observer);
288 child()->GetNativeView()->RemoveObserver(&test_observer);
290 DestroyHost();
293 // Ensure the native view receives the correct bounds notification when it is
294 // attached. This is a regression test for https://crbug.com/399420.
295 TEST_F(NativeViewHostAuraTest, Attach) {
296 CreateHost();
297 host()->Detach();
299 child()->GetNativeView()->SetBounds(gfx::Rect(0, 0, 0, 0));
300 toplevel()->SetBounds(gfx::Rect(0, 0, 100, 100));
301 host()->SetBounds(10, 10, 80, 80);
303 NativeViewHostWindowObserver test_observer;
304 child()->GetNativeView()->AddObserver(&test_observer);
306 host()->Attach(child()->GetNativeView());
308 ASSERT_EQ(3u, test_observer.events().size());
309 EXPECT_EQ(NativeViewHostWindowObserver::EVENT_BOUNDS_CHANGED,
310 test_observer.events()[0].type);
311 EXPECT_EQ(child()->GetNativeView(), test_observer.events()[0].window);
312 EXPECT_EQ(gfx::Rect(10, 10, 80, 80).ToString(),
313 test_observer.events()[0].bounds.ToString());
314 EXPECT_EQ(NativeViewHostWindowObserver::EVENT_SHOWN,
315 test_observer.events()[1].type);
316 EXPECT_EQ(child()->GetNativeView(), test_observer.events()[1].window);
317 EXPECT_EQ(gfx::Rect(10, 10, 80, 80).ToString(),
318 test_observer.events()[1].bounds.ToString());
319 EXPECT_EQ(NativeViewHostWindowObserver::EVENT_SHOWN,
320 test_observer.events()[2].type);
321 EXPECT_EQ(clipping_window(), test_observer.events()[2].window);
322 EXPECT_EQ(gfx::Rect(10, 10, 80, 80).ToString(),
323 test_observer.events()[2].bounds.ToString());
325 child()->GetNativeView()->RemoveObserver(&test_observer);
326 DestroyHost();
329 // Ensure the clipping window is hidden with the native view. This is a
330 // regression test for https://crbug.com/408877.
331 TEST_F(NativeViewHostAuraTest, SimpleShowAndHide) {
332 CreateHost();
334 toplevel()->SetBounds(gfx::Rect(20, 20, 100, 100));
335 toplevel()->Show();
337 host()->SetBounds(10, 10, 80, 80);
338 EXPECT_TRUE(clipping_window()->IsVisible());
339 EXPECT_TRUE(child()->IsVisible());
341 host()->SetVisible(false);
342 EXPECT_FALSE(clipping_window()->IsVisible());
343 EXPECT_FALSE(child()->IsVisible());
345 DestroyHost();
346 DestroyTopLevel();
349 } // namespace views