Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "ui/views/controls/native/native_view_host_aura.h" | 5 #include "ui/views/controls/native/native_view_host_aura.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/memory/scoped_ptr.h" | 8 #include "base/memory/scoped_ptr.h" |
| 9 #include "ui/aura/window.h" | 9 #include "ui/aura/window.h" |
| 10 #include "ui/views/controls/native/native_view_host.h" | 10 #include "ui/views/controls/native/native_view_host.h" |
| 11 #include "ui/views/test/views_test_base.h" | 11 #include "ui/views/test/views_test_base.h" |
| 12 #include "ui/views/view.h" | 12 #include "ui/views/view.h" |
| 13 #include "ui/views/view_constants_aura.h" | 13 #include "ui/views/view_constants_aura.h" |
| 14 #include "ui/views/widget/widget.h" | 14 #include "ui/views/widget/widget.h" |
| 15 | 15 |
| 16 namespace views { | 16 namespace views { |
| 17 | 17 |
| 18 // Testing wrapper of the NativeViewHost | |
| 19 class NativeViewHostTesting : public NativeViewHost { | |
| 20 public: | |
| 21 NativeViewHostTesting() {} | |
| 22 virtual ~NativeViewHostTesting() { | |
| 23 destroyed_count_++; | |
| 24 } | |
| 25 | |
| 26 static void ResetDestroyedCount() { | |
| 27 destroyed_count_ = 0; | |
| 28 } | |
| 29 | |
| 30 static int destroyed_count() { | |
| 31 return destroyed_count_; | |
| 32 } | |
| 33 | |
| 34 private: | |
| 35 static int destroyed_count_; | |
| 36 }; | |
|
sky
2013/10/24 18:16:50
nit: DISALLOW_...
rharrison
2013/10/24 19:28:17
Done.
| |
| 37 int NativeViewHostTesting::destroyed_count_ = 0; | |
| 38 | |
| 39 class AuraWindowDestroyedObserver : public aura::WindowObserver { | |
| 40 public: | |
| 41 AuraWindowDestroyedObserver(aura::Window *window) : | |
| 42 destroyed_count_(0) { | |
| 43 window->AddObserver(this); | |
| 44 } | |
| 45 | |
| 46 virtual ~AuraWindowDestroyedObserver() {} | |
| 47 | |
| 48 int destroyed_count() { return destroyed_count_; } | |
| 49 | |
| 50 // aura::WindowObserver overrides | |
| 51 virtual void OnWindowDestroyed(aura::Window* window) OVERRIDE { | |
| 52 destroyed_count_++; | |
| 53 } | |
| 54 | |
| 55 private: | |
| 56 int destroyed_count_; | |
| 57 }; | |
|
sky
2013/10/24 18:16:50
nit: DISALLOW_...
rharrison
2013/10/24 19:28:17
Done.
| |
| 58 | |
| 18 class NativeViewHostAuraTest : public ViewsTestBase { | 59 class NativeViewHostAuraTest : public ViewsTestBase { |
| 19 public: | 60 public: |
| 20 NativeViewHostAuraTest() { | 61 NativeViewHostAuraTest() { |
| 21 } | 62 } |
| 22 | 63 |
| 23 NativeViewHostAura* native_host() { | 64 NativeViewHostAura* native_host() { |
| 24 return static_cast<NativeViewHostAura*>(host_->native_wrapper_.get()); | 65 return static_cast<NativeViewHostAura*>(host_->native_wrapper_.get()); |
| 25 } | 66 } |
| 26 | 67 |
| 27 NativeViewHost* host() { | 68 NativeViewHost* host() { |
| 28 return host_.get(); | 69 return host_.get(); |
| 29 } | 70 } |
| 30 | 71 |
| 31 Widget* child() { | 72 Widget* child() { |
| 32 return child_.get(); | 73 return child_.get(); |
| 33 } | 74 } |
| 34 | 75 |
| 76 aura::Window* clipping_window() { | |
| 77 return native_host()->clipping_window_; | |
| 78 } | |
| 79 | |
| 80 Widget* toplevel() { | |
| 81 return toplevel_.get(); | |
| 82 } | |
| 83 | |
| 35 void CreateHost() { | 84 void CreateHost() { |
| 36 // Create the top level widget. | 85 // Create the top level widget. |
| 37 toplevel_.reset(new Widget); | 86 toplevel_.reset(new Widget); |
| 38 Widget::InitParams toplevel_params = | 87 Widget::InitParams toplevel_params = |
| 39 CreateParams(Widget::InitParams::TYPE_WINDOW); | 88 CreateParams(Widget::InitParams::TYPE_WINDOW); |
| 40 toplevel_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 89 toplevel_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 41 toplevel_->Init(toplevel_params); | 90 toplevel_->Init(toplevel_params); |
| 42 | 91 |
| 43 // And the child widget. | 92 // And the child widget. |
| 44 View* test_view = new View; | 93 View* test_view = new View; |
| 45 child_.reset(new Widget); | 94 child_.reset(new Widget); |
| 46 Widget::InitParams child_params(Widget::InitParams::TYPE_CONTROL); | 95 Widget::InitParams child_params(Widget::InitParams::TYPE_CONTROL); |
| 47 child_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; | 96 child_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
| 48 child_params.parent = toplevel_->GetNativeView(); | 97 child_params.parent = toplevel_->GetNativeView(); |
| 49 child_->Init(child_params); | 98 child_->Init(child_params); |
| 50 child_->SetContentsView(test_view); | 99 child_->SetContentsView(test_view); |
| 51 | 100 |
| 52 // Owned by |toplevel|. | 101 // Owned by |toplevel|. |
| 53 host_.reset(new NativeViewHost); | 102 host_.reset(new NativeViewHostTesting); |
| 54 toplevel_->GetRootView()->AddChildView(host_.get()); | 103 toplevel_->GetRootView()->AddChildView(host_.get()); |
| 55 host_->Attach(child_->GetNativeView()); | 104 host_->Attach(child_->GetNativeView()); |
| 56 } | 105 } |
| 57 | 106 |
| 58 void DestroyHost() { | 107 void DestroyHost() { |
| 59 host_.reset(); | 108 host_.reset(); |
| 60 } | 109 } |
| 61 | 110 |
| 111 NativeViewHostTesting* ReleaseHost() { | |
| 112 return host_.release(); | |
| 113 } | |
| 114 | |
| 115 void DestroyTopLevel() { | |
| 116 toplevel_.reset(); | |
| 117 } | |
| 118 | |
| 119 gfx::Point CalculateNativeViewOrigin(gfx::Rect input_rect, | |
| 120 gfx::Rect native_rect) { | |
| 121 return native_host()->CalculateNativeViewOrigin(input_rect, native_rect); | |
| 122 } | |
| 123 | |
| 62 private: | 124 private: |
| 63 scoped_ptr<Widget> toplevel_; | 125 scoped_ptr<Widget> toplevel_; |
| 64 scoped_ptr<NativeViewHost> host_; | 126 scoped_ptr<NativeViewHostTesting> host_; |
| 65 scoped_ptr<Widget> child_; | 127 scoped_ptr<Widget> child_; |
| 66 | 128 |
| 67 DISALLOW_COPY_AND_ASSIGN(NativeViewHostAuraTest); | 129 DISALLOW_COPY_AND_ASSIGN(NativeViewHostAuraTest); |
| 68 }; | 130 }; |
| 69 | 131 |
| 70 // Verifies NativeViewHostAura stops observing native view on destruction. | 132 // Verifies NativeViewHostAura stops observing native view on destruction. |
| 71 TEST_F(NativeViewHostAuraTest, StopObservingNativeViewOnDestruct) { | 133 TEST_F(NativeViewHostAuraTest, StopObservingNativeViewOnDestruct) { |
| 72 CreateHost(); | 134 CreateHost(); |
| 73 aura::Window* child_win = child()->GetNativeView(); | 135 aura::Window* child_win = child()->GetNativeView(); |
| 74 NativeViewHostAura* aura_host = native_host(); | 136 NativeViewHostAura* aura_host = native_host(); |
| 75 | 137 |
| 76 EXPECT_TRUE(child_win->HasObserver(aura_host)); | 138 EXPECT_TRUE(child_win->HasObserver(aura_host)); |
| 77 DestroyHost(); | 139 DestroyHost(); |
| 78 EXPECT_FALSE(child_win->HasObserver(aura_host)); | 140 EXPECT_FALSE(child_win->HasObserver(aura_host)); |
| 79 } | 141 } |
| 80 | 142 |
| 81 // Tests that the kHostViewKey is correctly set and cleared. | 143 // Tests that the kHostViewKey is correctly set and cleared. |
| 82 TEST_F(NativeViewHostAuraTest, HostViewPropertyKey) { | 144 TEST_F(NativeViewHostAuraTest, HostViewPropertyKey) { |
| 83 // Create the NativeViewHost and attach a NativeView. | 145 // Create the NativeViewHost and attach a NativeView. |
| 84 CreateHost(); | 146 CreateHost(); |
| 85 aura::Window* child_win = child()->GetNativeView(); | 147 aura::Window* child_win = child()->GetNativeView(); |
| 86 EXPECT_EQ(host(), child_win->GetProperty(views::kHostViewKey)); | 148 EXPECT_EQ(host(), child_win->GetProperty(views::kHostViewKey)); |
| 149 EXPECT_EQ(host(), clipping_window()->GetProperty(views::kHostViewKey)); | |
| 87 | 150 |
| 88 host()->Detach(); | 151 host()->Detach(); |
| 89 EXPECT_FALSE(child_win->GetProperty(views::kHostViewKey)); | 152 EXPECT_FALSE(child_win->GetProperty(views::kHostViewKey)); |
| 90 | 153 |
| 91 host()->Attach(child_win); | 154 host()->Attach(child_win); |
| 92 EXPECT_EQ(host(), child_win->GetProperty(views::kHostViewKey)); | 155 EXPECT_EQ(host(), child_win->GetProperty(views::kHostViewKey)); |
| 156 EXPECT_EQ(host(), clipping_window()->GetProperty(views::kHostViewKey)); | |
| 93 | 157 |
| 94 DestroyHost(); | 158 DestroyHost(); |
| 95 EXPECT_FALSE(child_win->GetProperty(views::kHostViewKey)); | 159 EXPECT_FALSE(child_win->GetProperty(views::kHostViewKey)); |
| 96 } | 160 } |
| 97 | 161 |
| 162 // Tests that the values being calculated by CalculateNativeViewOrigin are | |
| 163 // correct. | |
| 164 TEST_F(NativeViewHostAuraTest, CalculateNewNativeViewOrigin) { | |
| 165 CreateHost(); | |
| 166 | |
| 167 gfx::Rect clip_rect(0, 0, 50, 50); | |
| 168 gfx::Rect contents_rect(50, 50, 100, 100); | |
| 169 | |
| 170 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_NORTHWEST); | |
| 171 EXPECT_EQ(gfx::Point(0, 0).ToString(), | |
| 172 CalculateNativeViewOrigin(clip_rect, contents_rect).ToString()); | |
| 173 | |
| 174 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_NORTH); | |
| 175 EXPECT_EQ(gfx::Point(-25, 0).ToString(), | |
| 176 CalculateNativeViewOrigin(clip_rect, contents_rect).ToString()); | |
| 177 | |
| 178 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_NORTHEAST); | |
| 179 EXPECT_EQ(gfx::Point(-50, 0).ToString(), | |
| 180 CalculateNativeViewOrigin(clip_rect, contents_rect).ToString()); | |
| 181 | |
| 182 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_EAST); | |
| 183 EXPECT_EQ(gfx::Point(-50, -25).ToString(), | |
| 184 CalculateNativeViewOrigin(clip_rect, contents_rect).ToString()); | |
| 185 | |
| 186 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_SOUTHEAST); | |
| 187 EXPECT_EQ(gfx::Point(-50, -50).ToString(), | |
| 188 CalculateNativeViewOrigin(clip_rect, contents_rect).ToString()); | |
| 189 | |
| 190 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_SOUTH); | |
| 191 EXPECT_EQ(gfx::Point(-25, -50).ToString(), | |
| 192 CalculateNativeViewOrigin(clip_rect, contents_rect).ToString()); | |
| 193 | |
| 194 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_SOUTHWEST); | |
| 195 EXPECT_EQ(gfx::Point(0, -50).ToString(), | |
| 196 CalculateNativeViewOrigin(clip_rect, contents_rect).ToString()); | |
| 197 | |
| 198 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_WEST); | |
| 199 EXPECT_EQ(gfx::Point(0, -25).ToString(), | |
| 200 CalculateNativeViewOrigin(clip_rect, contents_rect).ToString()); | |
| 201 | |
| 202 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_CENTER); | |
| 203 EXPECT_EQ(gfx::Point(-25, -25).ToString(), | |
| 204 CalculateNativeViewOrigin(clip_rect, contents_rect).ToString()); | |
| 205 | |
| 206 DestroyHost(); | |
| 207 } | |
| 208 | |
| 209 // Test that the fast resize path places the clipping and content windows were | |
| 210 // they are supposed to be. | |
| 211 TEST_F(NativeViewHostAuraTest, FastResizePath) { | |
| 212 CreateHost(); | |
| 213 host()->set_fast_resize(false); | |
| 214 toplevel()->SetBounds(gfx::Rect(0, 0, 100, 100)); | |
| 215 native_host()->ShowWidget(0, 0, 100, 100); | |
| 216 host()->set_fast_resize(true); | |
| 217 | |
| 218 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_CENTER); | |
| 219 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), | |
| 220 host()->native_view()->layer()->bounds().ToString()); | |
| 221 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), | |
| 222 clipping_window()->layer()->bounds().ToString()); | |
| 223 | |
| 224 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_NORTHWEST); | |
| 225 native_host()->ShowWidget(0, 0, 50, 50); | |
| 226 EXPECT_EQ(gfx::Rect(0, 0, 100, 100).ToString(), | |
| 227 host()->native_view()->layer()->bounds().ToString()); | |
| 228 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), | |
| 229 clipping_window()->layer()->bounds().ToString()); | |
| 230 | |
| 231 host()->set_fast_resize_gravity(NativeViewHost::GRAVITY_SOUTHEAST); | |
| 232 native_host()->ShowWidget(0, 0, 50, 50); | |
| 233 EXPECT_EQ(gfx::Rect(-50, -50, 100, 100).ToString(), | |
| 234 host()->native_view()->layer()->bounds().ToString()); | |
| 235 EXPECT_EQ(gfx::Rect(0, 0, 50, 50).ToString(), | |
| 236 clipping_window()->layer()->bounds().ToString()); | |
| 237 | |
| 238 DestroyHost(); | |
| 239 } | |
| 240 | |
| 241 // Test that destroying the top level widget before destroying the attached | |
| 242 // NativeViewHost works correctly. Specifically the associated NVH should be | |
| 243 // destroyed and there shouldn't be any errors. | |
| 244 TEST_F(NativeViewHostAuraTest, DestroyWidget) { | |
| 245 NativeViewHostTesting::ResetDestroyedCount(); | |
| 246 CreateHost(); | |
| 247 ReleaseHost(); | |
| 248 EXPECT_EQ(0, NativeViewHostTesting::destroyed_count()); | |
| 249 DestroyTopLevel(); | |
| 250 EXPECT_EQ(1, NativeViewHostTesting::destroyed_count()); | |
| 251 } | |
| 252 | |
| 253 // Test that the clipping window and the native view are destroyed when the | |
| 254 // containing widget for the native view is closed. | |
| 255 TEST_F(NativeViewHostAuraTest, ClosingWidgetDoesntLeak) { | |
| 256 CreateHost(); | |
| 257 AuraWindowDestroyedObserver clipping_observer(clipping_window()); | |
| 258 AuraWindowDestroyedObserver native_view_observer(child()->GetNativeView()); | |
| 259 EXPECT_EQ(0, clipping_observer.destroyed_count()); | |
| 260 EXPECT_EQ(0, native_view_observer.destroyed_count()); | |
| 261 child()->CloseNow(); | |
| 262 EXPECT_EQ(1, clipping_observer.destroyed_count()); | |
| 263 EXPECT_EQ(1, native_view_observer.destroyed_count()); | |
| 264 DestroyHost(); | |
| 265 } | |
| 266 | |
| 267 // Test that the none fast resize path is clipped and positioned correctly. | |
| 268 TEST_F(NativeViewHostAuraTest, NonFastResizePath) { | |
| 269 const gfx::Rect base_rect = gfx::Rect(0, 0, 100, 100); | |
| 270 CreateHost(); | |
| 271 toplevel()->SetBounds(base_rect); | |
| 272 native_host()->ShowWidget(base_rect.x(), base_rect.y(), | |
| 273 base_rect.width(), base_rect.height()); | |
| 274 EXPECT_EQ(base_rect.ToString(), | |
| 275 host()->native_view()->bounds().ToString()); | |
| 276 EXPECT_EQ(base_rect.ToString(), | |
| 277 clipping_window()->bounds().ToString()); | |
| 278 | |
| 279 const gfx::Rect kTestCases[] = { | |
| 280 gfx::Rect(-10, -20, 100, 100), | |
| 281 gfx::Rect(0, -20, 100, 100), | |
| 282 gfx::Rect(10, -20, 100, 100), | |
| 283 gfx::Rect(-10, 0, 100, 100), | |
| 284 gfx::Rect(0, 0, 100, 100), | |
| 285 gfx::Rect(10, 0, 100, 100), | |
| 286 gfx::Rect(-10, 20, 100, 100), | |
| 287 gfx::Rect(0, 20, 100, 100), | |
| 288 gfx::Rect(10, 20, 100, 100), | |
| 289 gfx::Rect(0, 0, 200, 300), | |
| 290 gfx::Rect(-50, -100, 200, 300), | |
| 291 }; | |
| 292 | |
| 293 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kTestCases); ++i) { | |
| 294 const gfx::Rect& bounds = kTestCases[i]; | |
| 295 | |
| 296 host()->SetBoundsRect(bounds); | |
| 297 | |
| 298 gfx::Rect clip_rect = gfx::IntersectRects(bounds, base_rect); | |
| 299 EXPECT_EQ(clip_rect.ToString(), clipping_window()->bounds().ToString()); | |
| 300 | |
| 301 gfx::Rect native_view_bounds = bounds; | |
| 302 native_view_bounds.Offset(-clip_rect.x(), -clip_rect.y()); | |
| 303 EXPECT_EQ(native_view_bounds.ToString(), | |
| 304 host()->native_view()->bounds().ToString()); | |
| 305 } | |
| 306 | |
| 307 DestroyHost(); | |
| 308 } | |
| 309 | |
| 98 } // namespace views | 310 } // namespace views |
| OLD | NEW |