[SyncFS] Build indexes from FileTracker entries on disk.
[chromium-blink-merge.git] / ui / views / controls / native / native_view_host_unittest.cc
blob400f6db3c19fccaef736c881003f457653ece26b
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.
5 #include "ui/views/controls/native/native_view_host.h"
7 #include "base/basictypes.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "ui/aura/window.h"
10 #include "ui/views/test/views_test_base.h"
11 #include "ui/views/widget/widget.h"
13 namespace views {
15 class NativeViewHostTest : public ViewsTestBase {
16 public:
17 NativeViewHostTest() {
20 virtual void SetUp() OVERRIDE {
21 ViewsTestBase::SetUp();
23 // Create the top level widget.
24 toplevel_.reset(new Widget);
25 Widget::InitParams toplevel_params =
26 CreateParams(Widget::InitParams::TYPE_WINDOW);
27 toplevel_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
28 toplevel_->Init(toplevel_params);
31 // Create a child widget whose native parent is |native_parent_view|, uses
32 // |contents_view|, and is attached to |host| which is added as a child to
33 // |parent_view|.
34 Widget* CreateChildForHost(gfx::NativeView native_parent_view,
35 View* parent_view,
36 View* contents_view,
37 NativeViewHost* host) {
38 Widget* child = new Widget;
39 Widget::InitParams child_params(Widget::InitParams::TYPE_CONTROL);
40 child_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
41 child_params.parent = native_parent_view;
42 child->Init(child_params);
43 child->SetContentsView(contents_view);
45 // Owned by |parent_view|.
46 parent_view->AddChildView(host);
47 host->Attach(child->GetNativeView());
49 return child;
52 Widget* toplevel() {
53 return toplevel_.get();
56 private:
57 scoped_ptr<Widget> toplevel_;
59 DISALLOW_COPY_AND_ASSIGN(NativeViewHostTest);
62 namespace {
64 // View implementation used by NativeViewHierarchyChanged to count number of
65 // times NativeViewHierarchyChanged() is invoked.
66 class NativeViewHierarchyChangedTestView : public View {
67 public:
68 NativeViewHierarchyChangedTestView() : notification_count_(0) {
71 void ResetCount() {
72 notification_count_ = 0;
75 int notification_count() const { return notification_count_; }
77 // Overriden from View:
78 virtual void NativeViewHierarchyChanged() OVERRIDE {
79 ++notification_count_;
80 View::NativeViewHierarchyChanged();
83 private:
84 int notification_count_;
86 DISALLOW_COPY_AND_ASSIGN(NativeViewHierarchyChangedTestView);
89 aura::Window* GetNativeParent(aura::Window* window) {
90 return window->parent();
93 class ViewHierarchyChangedTestHost : public NativeViewHost {
94 public:
95 ViewHierarchyChangedTestHost()
96 : num_parent_changes_(0) {
99 void ResetParentChanges() {
100 num_parent_changes_ = 0;
103 int num_parent_changes() const {
104 return num_parent_changes_;
107 // Overriden from NativeViewHost:
108 virtual void ViewHierarchyChanged(
109 const ViewHierarchyChangedDetails& details) OVERRIDE {
110 gfx::NativeView parent_before = native_view() ?
111 GetNativeParent(native_view()) : NULL;
112 NativeViewHost::ViewHierarchyChanged(details);
113 gfx::NativeView parent_after = native_view() ?
114 GetNativeParent(native_view()) : NULL;
115 if (parent_before != parent_after)
116 ++num_parent_changes_;
119 private:
120 int num_parent_changes_;
122 DISALLOW_COPY_AND_ASSIGN(ViewHierarchyChangedTestHost);
125 } // namespace
127 // Verifies NativeViewHierarchyChanged is sent.
128 TEST_F(NativeViewHostTest, NativeViewHierarchyChanged) {
129 // Create a child widget.
130 NativeViewHierarchyChangedTestView* test_view =
131 new NativeViewHierarchyChangedTestView;
132 NativeViewHost* host = new NativeViewHost;
133 scoped_ptr<Widget> child(CreateChildForHost(toplevel()->GetNativeView(),
134 toplevel()->GetRootView(),
135 test_view,
136 host));
137 #if defined(USE_AURA)
138 // One notification is generated from inserting the native view into the
139 // clipping window.
140 EXPECT_EQ(1, test_view->notification_count());
141 #else
142 EXPECT_EQ(0, test_view->notification_count());
143 #endif
144 test_view->ResetCount();
146 // Detaching should send a NativeViewHierarchyChanged() notification and
147 // change the parent.
148 host->Detach();
149 #if defined(USE_AURA)
150 // Two notifications are generated from removing the native view from the
151 // clipping window and then reparenting it to the root window.
152 EXPECT_EQ(2, test_view->notification_count());
153 #else
154 EXPECT_EQ(1, test_view->notification_count());
155 #endif
156 EXPECT_NE(toplevel()->GetNativeView(),
157 GetNativeParent(child->GetNativeView()));
158 test_view->ResetCount();
160 // Attaching should send a NativeViewHierarchyChanged() notification and
161 // reset the parent.
162 host->Attach(child->GetNativeView());
163 EXPECT_EQ(1, test_view->notification_count());
164 #if defined(USE_AURA)
165 // There is a clipping window inserted above the native view that needs to be
166 // accounted for when looking at the relationship between the native views.
167 EXPECT_EQ(toplevel()->GetNativeView(),
168 GetNativeParent(GetNativeParent(child->GetNativeView())));
169 #else
170 EXPECT_EQ(toplevel()->GetNativeView(),
171 GetNativeParent(child->GetNativeView()));
172 #endif
175 // Verifies ViewHierarchyChanged handles NativeViewHost remove, add and move
176 // (reparent) operations with correct parent changes.
177 // This exercises the non-recursive code paths in
178 // View::PropagateRemoveNotifications() and View::PropagateAddNotifications().
179 TEST_F(NativeViewHostTest, ViewHierarchyChangedForHost) {
180 // Original tree:
181 // toplevel
182 // +-- host0 (NativeViewHost)
183 // +-- child0 (Widget, attached to host0)
184 // +-- test_host (ViewHierarchyChangedTestHost)
185 // +-- test_child (Widget, attached to test_host)
186 // +-- host1 (NativeViewHost)
187 // +-- child1 (Widget, attached to host1)
189 // Add two children widgets attached to a NativeViewHost, and a test
190 // grandchild as child widget of host0.
191 NativeViewHost* host0 = new NativeViewHost;
192 scoped_ptr<Widget> child0(CreateChildForHost(toplevel()->GetNativeView(),
193 toplevel()->GetRootView(),
194 new View,
195 host0));
196 NativeViewHost* host1 = new NativeViewHost;
197 scoped_ptr<Widget> child1(CreateChildForHost(toplevel()->GetNativeView(),
198 toplevel()->GetRootView(),
199 new View,
200 host1));
201 ViewHierarchyChangedTestHost* test_host = new ViewHierarchyChangedTestHost;
202 scoped_ptr<Widget> test_child(CreateChildForHost(host0->native_view(),
203 host0,
204 new View,
205 test_host));
207 // Remove test_host from host0, expect 1 parent change.
208 test_host->ResetParentChanges();
209 EXPECT_EQ(0, test_host->num_parent_changes());
210 host0->RemoveChildView(test_host);
211 EXPECT_EQ(1, test_host->num_parent_changes());
213 // Add test_host back to host0, expect 1 parent change.
214 test_host->ResetParentChanges();
215 EXPECT_EQ(0, test_host->num_parent_changes());
216 host0->AddChildView(test_host);
217 EXPECT_EQ(1, test_host->num_parent_changes());
219 // Reparent test_host to host1, expect no parent change because the old and
220 // new parents, host0 and host1, belong to the same toplevel widget.
221 test_host->ResetParentChanges();
222 EXPECT_EQ(0, test_host->num_parent_changes());
223 host1->AddChildView(test_host);
224 EXPECT_EQ(0, test_host->num_parent_changes());
226 // Reparent test_host to contents view of child0, expect 2 parent changes
227 // because the old parent belongs to the toplevel widget whereas the new
228 // parent belongs to the child0.
229 test_host->ResetParentChanges();
230 EXPECT_EQ(0, test_host->num_parent_changes());
231 child0->GetContentsView()->AddChildView(test_host);
232 EXPECT_EQ(2, test_host->num_parent_changes());
235 // Verifies ViewHierarchyChanged handles NativeViewHost's parent remove, add and
236 // move (reparent) operations with correct parent changes.
237 // This exercises the recursive code paths in
238 // View::PropagateRemoveNotifications() and View::PropagateAddNotifications().
239 TEST_F(NativeViewHostTest, ViewHierarchyChangedForHostParent) {
240 // Original tree:
241 // toplevel
242 // +-- view0 (View)
243 // +-- host0 (NativeViewHierarchyChangedTestHost)
244 // +-- child0 (Widget, attached to host0)
245 // +-- view1 (View)
246 // +-- host1 (NativeViewHierarchyChangedTestHost)
247 // +-- child1 (Widget, attached to host1)
249 // Add two children views.
250 View* view0 = new View;
251 toplevel()->GetRootView()->AddChildView(view0);
252 View* view1 = new View;
253 toplevel()->GetRootView()->AddChildView(view1);
255 // To each child view, add a child widget.
256 ViewHierarchyChangedTestHost* host0 = new ViewHierarchyChangedTestHost;
257 scoped_ptr<Widget> child0(CreateChildForHost(toplevel()->GetNativeView(),
258 view0,
259 new View,
260 host0));
261 ViewHierarchyChangedTestHost* host1 = new ViewHierarchyChangedTestHost;
262 scoped_ptr<Widget> child1(CreateChildForHost(toplevel()->GetNativeView(),
263 view1,
264 new View,
265 host1));
267 // Remove view0 from top level, expect 1 parent change.
268 host0->ResetParentChanges();
269 EXPECT_EQ(0, host0->num_parent_changes());
270 toplevel()->GetRootView()->RemoveChildView(view0);
271 EXPECT_EQ(1, host0->num_parent_changes());
273 // Add view0 back to top level, expect 1 parent change.
274 host0->ResetParentChanges();
275 EXPECT_EQ(0, host0->num_parent_changes());
276 toplevel()->GetRootView()->AddChildView(view0);
277 EXPECT_EQ(1, host0->num_parent_changes());
279 // Reparent view0 to view1, expect no parent change because the old and new
280 // parents of both view0 and view1 belong to the same toplevel widget.
281 host0->ResetParentChanges();
282 host1->ResetParentChanges();
283 EXPECT_EQ(0, host0->num_parent_changes());
284 EXPECT_EQ(0, host1->num_parent_changes());
285 view1->AddChildView(view0);
286 EXPECT_EQ(0, host0->num_parent_changes());
287 EXPECT_EQ(0, host1->num_parent_changes());
289 // Restore original view hierarchy by adding back view0 to top level.
290 // Then, reparent view1 to contents view of child0.
291 // Expect 2 parent changes because the old parent belongs to the toplevel
292 // widget whereas the new parent belongs to the 1st child widget.
293 toplevel()->GetRootView()->AddChildView(view0);
294 host0->ResetParentChanges();
295 host1->ResetParentChanges();
296 EXPECT_EQ(0, host0->num_parent_changes());
297 EXPECT_EQ(0, host1->num_parent_changes());
298 child0->GetContentsView()->AddChildView(view1);
299 EXPECT_EQ(0, host0->num_parent_changes());
300 EXPECT_EQ(2, host1->num_parent_changes());
303 } // namespace views