| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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 "mojo/services/public/cpp/view_manager/view_manager.h" | 5 #include "mojo/services/public/cpp/view_manager/view_manager.h" |
| 6 | 6 |
| 7 #include "base/auto_reset.h" |
| 7 #include "base/bind.h" | 8 #include "base/bind.h" |
| 8 #include "base/logging.h" | 9 #include "base/logging.h" |
| 9 #include "mojo/public/cpp/application/application.h" | 10 #include "mojo/public/cpp/application/application.h" |
| 10 #include "mojo/service_manager/service_manager.h" | 11 #include "mojo/service_manager/service_manager.h" |
| 11 #include "mojo/services/public/cpp/view_manager/lib/view_manager_private.h" | 12 #include "mojo/services/public/cpp/view_manager/lib/view_manager_private.h" |
| 12 #include "mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.h" | 13 #include "mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.h" |
| 13 #include "mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h" | 14 #include "mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h" |
| 14 #include "mojo/services/public/cpp/view_manager/util.h" | 15 #include "mojo/services/public/cpp/view_manager/util.h" |
| 15 #include "mojo/services/public/cpp/view_manager/view.h" | 16 #include "mojo/services/public/cpp/view_manager/view.h" |
| 16 #include "mojo/services/public/cpp/view_manager/view_observer.h" | 17 #include "mojo/services/public/cpp/view_manager/view_observer.h" |
| 17 #include "mojo/services/public/cpp/view_manager/view_tree_node_observer.h" | 18 #include "mojo/services/public/cpp/view_manager/view_tree_node_observer.h" |
| 18 #include "mojo/shell/shell_test_helper.h" | 19 #include "mojo/shell/shell_test_helper.h" |
| 19 #include "testing/gtest/include/gtest/gtest.h" | 20 #include "testing/gtest/include/gtest/gtest.h" |
| 20 | 21 |
| 21 namespace mojo { | 22 namespace mojo { |
| 22 namespace view_manager { | 23 namespace view_manager { |
| 23 namespace { | 24 namespace { |
| 24 | 25 |
| 25 const char kTestServiceURL[] = "mojo:test_url"; | 26 const char kTestServiceURL[] = "mojo:test_url"; |
| 27 const char kTestServiceURL2[] = "mojo:test_url2"; |
| 26 | 28 |
| 27 base::RunLoop* current_run_loop = NULL; | 29 base::RunLoop* current_run_loop = NULL; |
| 28 | 30 |
| 29 void DoRunLoop() { | 31 void DoRunLoop() { |
| 30 base::RunLoop run_loop; | 32 base::RunLoop run_loop; |
| 31 current_run_loop = &run_loop; | 33 current_run_loop = &run_loop; |
| 32 current_run_loop->Run(); | 34 current_run_loop->Run(); |
| 33 current_run_loop = NULL; | 35 current_run_loop = NULL; |
| 34 } | 36 } |
| 35 | 37 |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 tree_size_(tree_size) {} | 145 tree_size_(tree_size) {} |
| 144 virtual ~TreeSizeMatchesObserver() {} | 146 virtual ~TreeSizeMatchesObserver() {} |
| 145 | 147 |
| 146 bool IsTreeCorrectSize() { | 148 bool IsTreeCorrectSize() { |
| 147 return CountNodes(tree_) == tree_size_; | 149 return CountNodes(tree_) == tree_size_; |
| 148 } | 150 } |
| 149 | 151 |
| 150 private: | 152 private: |
| 151 // Overridden from ViewTreeNodeObserver: | 153 // Overridden from ViewTreeNodeObserver: |
| 152 virtual void OnTreeChange(const TreeChangeParams& params) OVERRIDE { | 154 virtual void OnTreeChange(const TreeChangeParams& params) OVERRIDE { |
| 153 if (params.phase != ViewTreeNodeObserver::DISPOSITION_CHANGED) | |
| 154 return; | |
| 155 if (IsTreeCorrectSize()) | 155 if (IsTreeCorrectSize()) |
| 156 QuitRunLoop(); | 156 QuitRunLoop(); |
| 157 } | 157 } |
| 158 | 158 |
| 159 size_t CountNodes(const ViewTreeNode* node) const { | 159 size_t CountNodes(const ViewTreeNode* node) const { |
| 160 size_t count = 1; | 160 size_t count = 1; |
| 161 ViewTreeNode::Children::const_iterator it = node->children().begin(); | 161 ViewTreeNode::Children::const_iterator it = node->children().begin(); |
| 162 for (; it != node->children().end(); ++it) | 162 for (; it != node->children().end(); ++it) |
| 163 count += CountNodes(*it); | 163 count += CountNodes(*it); |
| 164 return count; | 164 return count; |
| 165 } | 165 } |
| 166 | 166 |
| 167 ViewTreeNode* tree_; | 167 ViewTreeNode* tree_; |
| 168 size_t tree_size_; | 168 size_t tree_size_; |
| 169 |
| 169 DISALLOW_COPY_AND_ASSIGN(TreeSizeMatchesObserver); | 170 DISALLOW_COPY_AND_ASSIGN(TreeSizeMatchesObserver); |
| 170 }; | 171 }; |
| 171 | 172 |
| 172 void WaitForTreeSizeToMatch(ViewTreeNode* node, size_t tree_size) { | 173 void WaitForTreeSizeToMatch(ViewTreeNode* node, size_t tree_size) { |
| 173 TreeSizeMatchesObserver observer(node, tree_size); | 174 TreeSizeMatchesObserver observer(node, tree_size); |
| 174 if (observer.IsTreeCorrectSize()) | 175 if (observer.IsTreeCorrectSize()) |
| 175 return; | 176 return; |
| 176 node->AddObserver(&observer); | 177 node->AddObserver(&observer); |
| 177 DoRunLoop(); | 178 DoRunLoop(); |
| 178 node->RemoveObserver(&observer); | 179 node->RemoveObserver(&observer); |
| (...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 279 | 280 |
| 280 } // namespace | 281 } // namespace |
| 281 | 282 |
| 282 // ViewManager ----------------------------------------------------------------- | 283 // ViewManager ----------------------------------------------------------------- |
| 283 | 284 |
| 284 // These tests model synchronization of two peer connections to the view manager | 285 // These tests model synchronization of two peer connections to the view manager |
| 285 // service, that are given access to some root node. | 286 // service, that are given access to some root node. |
| 286 | 287 |
| 287 class ViewManagerTest : public testing::Test { | 288 class ViewManagerTest : public testing::Test { |
| 288 public: | 289 public: |
| 289 ViewManagerTest() : commit_count_(0) {} | 290 ViewManagerTest() |
| 291 : connect_loop_(NULL), |
| 292 loaded_view_manager_(NULL), |
| 293 window_manager_(NULL), |
| 294 commit_count_(0) {} |
| 290 | 295 |
| 291 protected: | 296 protected: |
| 292 ViewManager* view_manager_1() { return view_manager_1_; } | 297 ViewManager* window_manager() { return window_manager_; } |
| 293 ViewManager* view_manager_2() { return view_manager_2_; } | |
| 294 | 298 |
| 295 ViewTreeNode* CreateNodeInParent(ViewTreeNode* parent) { | 299 ViewTreeNode* CreateNodeInParent(ViewTreeNode* parent) { |
| 296 ViewManager* parent_manager = ViewTreeNodePrivate(parent).view_manager(); | 300 ViewManager* parent_manager = ViewTreeNodePrivate(parent).view_manager(); |
| 297 ViewTreeNode* node = ViewTreeNode::Create(parent_manager); | 301 ViewTreeNode* node = ViewTreeNode::Create(parent_manager); |
| 298 parent->AddChild(node); | 302 parent->AddChild(node); |
| 299 return node; | 303 return node; |
| 300 } | 304 } |
| 301 | 305 |
| 302 void DestroyViewManager1() { | 306 // Embeds another version of the test app @ node. |
| 303 // view_manager_1_.reset(); | 307 ViewManager* Embed(ViewManager* view_manager, ViewTreeNode* node) { |
| 308 DCHECK_EQ(view_manager, ViewTreeNodePrivate(node).view_manager()); |
| 309 view_manager->Embed(kTestServiceURL2, node); |
| 310 RunRunLoop(); |
| 311 return GetLoadedViewManager(); |
| 312 } |
| 313 |
| 314 // TODO(beng): remove these methods once all the tests are migrated. |
| 315 void DestroyViewManager1() {} |
| 316 ViewManager* view_manager_1() { return NULL; } |
| 317 ViewManager* view_manager_2() { return NULL; } |
| 318 |
| 319 ViewManager* GetLoadedViewManager() { |
| 320 ViewManager* view_manager = loaded_view_manager_; |
| 321 loaded_view_manager_ = NULL; |
| 322 return view_manager; |
| 304 } | 323 } |
| 305 | 324 |
| 306 private: | 325 private: |
| 307 // Overridden from testing::Test: | 326 // Overridden from testing::Test: |
| 308 virtual void SetUp() OVERRIDE { | 327 virtual void SetUp() OVERRIDE { |
| 309 test_helper_.Init(); | 328 test_helper_.Init(); |
| 310 ConnectServiceLoader* loader = | 329 test_helper_.SetLoaderForURL( |
| 311 new ConnectServiceLoader( | 330 scoped_ptr<ServiceLoader>(new ConnectServiceLoader( |
| 312 base::Bind(&ViewManagerTest::OnViewManagerLoaded, | 331 base::Bind(&ViewManagerTest::OnViewManagerLoaded, |
| 313 base::Unretained(this))); | 332 base::Unretained(this)))), |
| 333 GURL(kTestServiceURL)); |
| 314 test_helper_.SetLoaderForURL( | 334 test_helper_.SetLoaderForURL( |
| 315 scoped_ptr<ServiceLoader>(loader), | 335 scoped_ptr<ServiceLoader>(new ConnectServiceLoader( |
| 316 GURL(kTestServiceURL)); | 336 base::Bind(&ViewManagerTest::OnViewManagerLoaded, |
| 337 base::Unretained(this)))), |
| 338 GURL(kTestServiceURL2)); |
| 317 | 339 |
| 318 ConnectToService(test_helper_.service_provider(), | 340 ConnectToService(test_helper_.service_provider(), |
| 319 "mojo:mojo_view_manager", | 341 "mojo:mojo_view_manager", |
| 320 &view_manager_init_); | 342 &view_manager_init_); |
| 321 ASSERT_TRUE(ViewManagerInitConnect(view_manager_init_.get(), | 343 ASSERT_TRUE(ViewManagerInitConnect(view_manager_init_.get(), |
| 322 kTestServiceURL)); | 344 kTestServiceURL)); |
| 323 } | 345 } |
| 324 | 346 |
| 325 void ViewManagerInitConnectCallback(bool* result_cache, | 347 void ViewManagerInitConnectCallback(bool* result_cache, |
| 326 bool result) { | 348 bool result) { |
| 327 *result_cache = result; | 349 *result_cache = result; |
| 328 } | 350 } |
| 329 | 351 |
| 330 bool ViewManagerInitConnect(IViewManagerInit* view_manager_init, | 352 bool ViewManagerInitConnect(IViewManagerInit* view_manager_init, |
| 331 const std::string& url) { | 353 const std::string& url) { |
| 332 bool result = false; | 354 bool result = false; |
| 333 view_manager_init->Connect( | 355 view_manager_init->Connect( |
| 334 url, | 356 url, |
| 335 base::Bind(&ViewManagerTest::ViewManagerInitConnectCallback, | 357 base::Bind(&ViewManagerTest::ViewManagerInitConnectCallback, |
| 336 base::Unretained(this), &result)); | 358 base::Unretained(this), &result)); |
| 337 init_loop_.Run(); | 359 RunRunLoop(); |
| 360 window_manager_ = GetLoadedViewManager(); |
| 338 return result; | 361 return result; |
| 339 } | 362 } |
| 340 | 363 |
| 341 void OnViewManagerLoaded(ViewManager* view_manager) { | 364 void OnViewManagerLoaded(ViewManager* view_manager) { |
| 342 init_loop_.Quit(); | 365 loaded_view_manager_ = view_manager; |
| 366 connect_loop_->Quit(); |
| 367 } |
| 368 |
| 369 void RunRunLoop() { |
| 370 base::RunLoop run_loop; |
| 371 connect_loop_ = &run_loop; |
| 372 connect_loop_->Run(); |
| 373 connect_loop_ = NULL; |
| 343 } | 374 } |
| 344 | 375 |
| 345 base::MessageLoop loop_; | 376 base::MessageLoop loop_; |
| 346 base::RunLoop init_loop_; | 377 base::RunLoop* connect_loop_; |
| 347 shell::ShellTestHelper test_helper_; | 378 shell::ShellTestHelper test_helper_; |
| 348 IViewManagerInitPtr view_manager_init_; | 379 IViewManagerInitPtr view_manager_init_; |
| 349 ViewManager* view_manager_1_; | 380 // Used to receive the most recent view manager loaded by an embed action. |
| 350 ViewManager* view_manager_2_; | 381 ViewManager* loaded_view_manager_; |
| 382 // The View Manager connection held by the window manager (app running at the |
| 383 // root node). |
| 384 ViewManager* window_manager_; |
| 351 int commit_count_; | 385 int commit_count_; |
| 352 | 386 |
| 353 DISALLOW_COPY_AND_ASSIGN(ViewManagerTest); | 387 DISALLOW_COPY_AND_ASSIGN(ViewManagerTest); |
| 354 }; | 388 }; |
| 355 | 389 |
| 356 // Base class for helpers that quit the current runloop after a specific tree | 390 TEST_F(ViewManagerTest, SetUp) {} |
| 357 // change is observed by a view manager. | |
| 358 class TreeObserverBase : public ViewTreeNodeObserver { | |
| 359 public: | |
| 360 explicit TreeObserverBase(ViewManager* view_manager) | |
| 361 : view_manager_(view_manager) { | |
| 362 view_manager_->tree()->AddObserver(this); | |
| 363 } | |
| 364 virtual ~TreeObserverBase() { | |
| 365 view_manager_->tree()->RemoveObserver(this); | |
| 366 } | |
| 367 | 391 |
| 368 protected: | 392 TEST_F(ViewManagerTest, Embed) { |
| 369 virtual bool ShouldQuitRunLoop(const TreeChangeParams& params) = 0; | 393 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
| 370 | 394 window_manager()->tree()->AddChild(node); |
| 371 ViewManager* view_manager() { return view_manager_; } | 395 ViewManager* embedded = Embed(window_manager(), node); |
| 372 | 396 EXPECT_TRUE(NULL != embedded); |
| 373 private: | |
| 374 // Overridden from ViewTreeNodeObserver: | |
| 375 virtual void OnTreeChange(const TreeChangeParams& params) OVERRIDE { | |
| 376 if (ShouldQuitRunLoop(params)) | |
| 377 QuitRunLoop(); | |
| 378 } | |
| 379 | |
| 380 ViewManager* view_manager_; | |
| 381 DISALLOW_COPY_AND_ASSIGN(TreeObserverBase); | |
| 382 }; | |
| 383 | |
| 384 class HierarchyChanged_NodeCreatedObserver : public TreeObserverBase { | |
| 385 public: | |
| 386 explicit HierarchyChanged_NodeCreatedObserver(ViewManager* view_manager) | |
| 387 : TreeObserverBase(view_manager) {} | |
| 388 virtual ~HierarchyChanged_NodeCreatedObserver() {} | |
| 389 | |
| 390 private: | |
| 391 // Overridden from TreeObserverBase: | |
| 392 virtual bool ShouldQuitRunLoop(const TreeChangeParams& params) OVERRIDE { | |
| 393 if (params.phase != ViewTreeNodeObserver::DISPOSITION_CHANGED) | |
| 394 return false; | |
| 395 return params.receiver == view_manager()->tree() && | |
| 396 !params.old_parent && | |
| 397 params.new_parent == view_manager()->tree(); | |
| 398 } | |
| 399 | |
| 400 DISALLOW_COPY_AND_ASSIGN(HierarchyChanged_NodeCreatedObserver); | |
| 401 }; | |
| 402 | |
| 403 // TODO(beng): reenable these once converted to new way of connecting. | |
| 404 | |
| 405 TEST_F(ViewManagerTest, SetUp) { | |
| 406 } | 397 } |
| 407 | 398 |
| 408 TEST_F(ViewManagerTest, DISABLED_HierarchyChanged_NodeCreated) { | 399 // When Window Manager embeds A @ N, then creates N2 and parents to N, N becomes |
| 409 HierarchyChanged_NodeCreatedObserver observer(view_manager_2()); | 400 // visible to A. |
| 410 ViewTreeNode* node1 = ViewTreeNode::Create(view_manager_1()); | 401 // TODO(beng): verify whether or not this is a policy we like. |
| 411 view_manager_1()->tree()->AddChild(node1); | 402 TEST_F(ViewManagerTest, HierarchyChanged_NodeAdded) { |
| 412 DoRunLoop(); | 403 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
| 413 | 404 window_manager()->tree()->AddChild(node); |
| 414 EXPECT_EQ(view_manager_2()->tree()->children().front()->id(), node1->id()); | 405 ViewManager* embedded = Embed(window_manager(), node); |
| 406 ViewTreeNode* nested = ViewTreeNode::Create(window_manager()); |
| 407 node->AddChild(nested); |
| 408 WaitForTreeSizeToMatch(embedded->tree(), 2); |
| 409 EXPECT_EQ(embedded->tree()->children().front()->id(), nested->id()); |
| 415 } | 410 } |
| 416 | 411 |
| 417 // Quits the current runloop when the root is notified about a node moved from | 412 // Window manager has two nodes, N1 & N2. Embeds A at N1. Creates node N21, |
| 418 // |old_parent_id| to |new_parent_id|. | 413 // a child of N2. Reparents N2 to N1. N1 should become visible to A. |
| 419 class HierarchyChanged_NodeMovedObserver : public TreeObserverBase { | 414 // TODO(beng): verify whether or not this is a policy we like. |
| 420 public: | 415 TEST_F(ViewManagerTest, HierarchyChanged_NodeMoved) { |
| 421 HierarchyChanged_NodeMovedObserver(ViewManager* view_manager, | 416 ViewTreeNode* node1 = ViewTreeNode::Create(window_manager()); |
| 422 TransportNodeId old_parent_id, | 417 window_manager()->tree()->AddChild(node1); |
| 423 TransportNodeId new_parent_id) | 418 ViewManager* embedded = Embed(window_manager(), node1); |
| 424 : TreeObserverBase(view_manager), | 419 WaitForTreeSizeToMatch(embedded->tree(), 1); |
| 425 old_parent_id_(old_parent_id), | |
| 426 new_parent_id_(new_parent_id) {} | |
| 427 virtual ~HierarchyChanged_NodeMovedObserver() {} | |
| 428 | 420 |
| 429 private: | 421 ViewTreeNode* node2 = ViewTreeNode::Create(window_manager()); |
| 430 // Overridden from TreeObserverBase: | 422 window_manager()->tree()->AddChild(node2); |
| 431 virtual bool ShouldQuitRunLoop(const TreeChangeParams& params) OVERRIDE { | 423 WaitForTreeSizeToMatch(embedded->tree(), 1); |
| 432 if (params.phase != ViewTreeNodeObserver::DISPOSITION_CHANGED) | 424 EXPECT_TRUE(embedded->tree()->children().empty()); |
| 433 return false; | |
| 434 return params.receiver == view_manager()->tree() && | |
| 435 params.old_parent->id() == old_parent_id_&& | |
| 436 params.new_parent->id() == new_parent_id_; | |
| 437 } | |
| 438 | 425 |
| 439 TransportNodeId old_parent_id_; | 426 ViewTreeNode* node21 = ViewTreeNode::Create(window_manager()); |
| 440 TransportNodeId new_parent_id_; | 427 node2->AddChild(node21); |
| 428 WaitForTreeSizeToMatch(embedded->tree(), 1); |
| 429 EXPECT_TRUE(embedded->tree()->children().empty()); |
| 441 | 430 |
| 442 DISALLOW_COPY_AND_ASSIGN(HierarchyChanged_NodeMovedObserver); | 431 // Makes node21 visible to |embedded|. |
| 443 }; | |
| 444 | |
| 445 TEST_F(ViewManagerTest, DISABLED_HierarchyChanged_NodeMoved) { | |
| 446 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | |
| 447 ViewTreeNode* node2 = CreateNodeInParent(view_manager_1()->tree()); | |
| 448 ViewTreeNode* node21 = CreateNodeInParent(node2); | |
| 449 WaitForTreeSizeToMatch(view_manager_2()->tree(), 4); | |
| 450 | |
| 451 HierarchyChanged_NodeMovedObserver observer(view_manager_2(), | |
| 452 node2->id(), | |
| 453 node1->id()); | |
| 454 | |
| 455 node1->AddChild(node21); | 432 node1->AddChild(node21); |
| 456 DoRunLoop(); | 433 WaitForTreeSizeToMatch(embedded->tree(), 2); |
| 457 | 434 EXPECT_FALSE(embedded->tree()->children().empty()); |
| 458 ViewTreeNode* tree2 = view_manager_2()->tree(); | 435 EXPECT_EQ(embedded->tree()->children().front()->id(), node21->id()); |
| 459 | |
| 460 EXPECT_EQ(tree2->children().size(), 2u); | |
| 461 ViewTreeNode* tree2_node1 = tree2->GetChildById(node1->id()); | |
| 462 EXPECT_EQ(tree2_node1->children().size(), 1u); | |
| 463 ViewTreeNode* tree2_node2 = tree2->GetChildById(node2->id()); | |
| 464 EXPECT_TRUE(tree2_node2->children().empty()); | |
| 465 ViewTreeNode* tree2_node21 = tree2->GetChildById(node21->id()); | |
| 466 EXPECT_EQ(tree2_node21->parent(), tree2_node1); | |
| 467 } | 436 } |
| 468 | 437 |
| 469 class HierarchyChanged_NodeRemovedObserver : public TreeObserverBase { | 438 // Window manager has two nodes, N1 and N11. Embeds A at N1. Removes N11 from |
| 470 public: | 439 // N1. N11 should disappear from A. |
| 471 HierarchyChanged_NodeRemovedObserver(ViewManager* view_manager) | 440 // TODO(beng): verify whether or not this is a policy we like. |
| 472 : TreeObserverBase(view_manager) {} | 441 TEST_F(ViewManagerTest, HierarchyChanged_NodeRemoved) { |
| 473 virtual ~HierarchyChanged_NodeRemovedObserver() {} | 442 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
| 443 window_manager()->tree()->AddChild(node); |
| 444 ViewTreeNode* nested = ViewTreeNode::Create(window_manager()); |
| 445 node->AddChild(nested); |
| 474 | 446 |
| 475 private: | 447 ViewManager* embedded = Embed(window_manager(), node); |
| 476 // Overridden from TreeObserverBase: | 448 EXPECT_EQ(embedded->tree()->children().front()->id(), nested->id()); |
| 477 virtual bool ShouldQuitRunLoop(const TreeChangeParams& params) OVERRIDE { | |
| 478 if (params.phase != ViewTreeNodeObserver::DISPOSITION_CHANGING) | |
| 479 return false; | |
| 480 return params.receiver == view_manager()->tree() && | |
| 481 params.old_parent->id() == params.receiver->id() && | |
| 482 params.new_parent == 0; | |
| 483 } | |
| 484 | 449 |
| 485 DISALLOW_COPY_AND_ASSIGN(HierarchyChanged_NodeRemovedObserver); | 450 node->RemoveChild(nested); |
| 486 }; | 451 WaitForTreeSizeToMatch(embedded->tree(), 1); |
| 487 | 452 EXPECT_TRUE(embedded->tree()->children().empty()); |
| 488 TEST_F(ViewManagerTest, DISABLED_HierarchyChanged_NodeRemoved) { | |
| 489 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | |
| 490 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); | |
| 491 | |
| 492 HierarchyChanged_NodeRemovedObserver observer(view_manager_2()); | |
| 493 | |
| 494 view_manager_1()->tree()->RemoveChild(node1); | |
| 495 DoRunLoop(); | |
| 496 | |
| 497 ViewTreeNode* tree2 = view_manager_2()->tree(); | |
| 498 | |
| 499 EXPECT_TRUE(tree2->children().empty()); | |
| 500 } | 453 } |
| 501 | 454 |
| 502 TEST_F(ViewManagerTest, DISABLED_NodeDestroyed) { | 455 // Window manager has two nodes, N1 and N11. Embeds A at N1. Destroys N11. |
| 503 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 456 // N11 should disappear from A. |
| 504 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); | 457 // TODO(beng): verify whether or not this is a policy we like. |
| 458 TEST_F(ViewManagerTest, NodeDestroyed) { |
| 459 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
| 460 window_manager()->tree()->AddChild(node); |
| 461 ViewTreeNode* nested = ViewTreeNode::Create(window_manager()); |
| 462 node->AddChild(nested); |
| 505 | 463 |
| 506 // |node1| will be deleted after calling Destroy() below. | 464 ViewManager* embedded = Embed(window_manager(), node); |
| 507 TransportNodeId id = node1->id(); | 465 EXPECT_EQ(embedded->tree()->children().front()->id(), nested->id()); |
| 508 node1->Destroy(); | 466 |
| 467 // |nested| will be deleted after calling Destroy() below. |
| 468 TransportNodeId id = nested->id(); |
| 469 nested->Destroy(); |
| 509 | 470 |
| 510 std::set<TransportNodeId> nodes; | 471 std::set<TransportNodeId> nodes; |
| 511 nodes.insert(id); | 472 nodes.insert(id); |
| 512 WaitForDestruction(view_manager_2(), &nodes, NULL); | 473 WaitForDestruction(embedded, &nodes, NULL); |
| 513 | 474 |
| 514 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); | 475 EXPECT_TRUE(embedded->tree()->children().empty()); |
| 515 EXPECT_EQ(NULL, view_manager_2()->GetNodeById(id)); | 476 EXPECT_EQ(NULL, embedded->GetNodeById(id)); |
| 516 } | 477 } |
| 517 | 478 |
| 479 // TODO(beng): provide a way to terminate an application. |
| 518 TEST_F(ViewManagerTest, DISABLED_ViewManagerDestroyed_CleanupNode) { | 480 TEST_F(ViewManagerTest, DISABLED_ViewManagerDestroyed_CleanupNode) { |
| 519 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 481 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); |
| 520 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); | 482 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); |
| 521 | 483 |
| 522 TransportNodeId id = node1->id(); | 484 TransportNodeId id = node1->id(); |
| 523 DestroyViewManager1(); | 485 DestroyViewManager1(); |
| 524 std::set<TransportNodeId> nodes; | 486 std::set<TransportNodeId> nodes; |
| 525 nodes.insert(id); | 487 nodes.insert(id); |
| 526 WaitForDestruction(view_manager_2(), &nodes, NULL); | 488 WaitForDestruction(view_manager_2(), &nodes, NULL); |
| 527 | 489 |
| 528 // tree() should still be valid, since it's owned by neither connection. | 490 // tree() should still be valid, since it's owned by neither connection. |
| 529 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); | 491 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); |
| 530 } | 492 } |
| 531 | 493 |
| 532 TEST_F(ViewManagerTest, DISABLED_SetActiveView) { | 494 TEST_F(ViewManagerTest, SetActiveView) { |
| 533 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 495 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
| 534 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); | 496 window_manager()->tree()->AddChild(node); |
| 497 ViewManager* embedded = Embed(window_manager(), node); |
| 535 | 498 |
| 536 View* view1 = View::Create(view_manager_1()); | 499 View* view = View::Create(window_manager()); |
| 537 node1->SetActiveView(view1); | 500 node->SetActiveView(view); |
| 538 | 501 |
| 539 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id()); | 502 ViewTreeNode* node_in_embedded = embedded->GetNodeById(node->id()); |
| 540 WaitForActiveViewToChange(node1_2); | 503 WaitForActiveViewToChange(node_in_embedded); |
| 541 | 504 |
| 542 EXPECT_EQ(node1_2->active_view()->id(), view1->id()); | 505 EXPECT_EQ(node_in_embedded->active_view()->id(), view->id()); |
| 543 } | 506 } |
| 544 | 507 |
| 545 TEST_F(ViewManagerTest, DISABLED_DestroyView) { | 508 TEST_F(ViewManagerTest, DestroyView) { |
| 546 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 509 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
| 547 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); | 510 window_manager()->tree()->AddChild(node); |
| 511 ViewManager* embedded = Embed(window_manager(), node); |
| 548 | 512 |
| 549 View* view1 = View::Create(view_manager_1()); | 513 View* view = View::Create(window_manager()); |
| 550 node1->SetActiveView(view1); | 514 node->SetActiveView(view); |
| 551 | 515 |
| 552 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id()); | 516 ViewTreeNode* node_in_embedded = embedded->GetNodeById(node->id()); |
| 553 WaitForActiveViewToChange(node1_2); | 517 WaitForActiveViewToChange(node_in_embedded); |
| 554 | 518 |
| 555 TransportViewId view1_id = view1->id(); | 519 EXPECT_EQ(node_in_embedded->active_view()->id(), view->id()); |
| 556 view1->Destroy(); | 520 |
| 521 TransportViewId view_id = view->id(); |
| 522 view->Destroy(); |
| 557 | 523 |
| 558 std::set<TransportViewId> views; | 524 std::set<TransportViewId> views; |
| 559 views.insert(view1_id); | 525 views.insert(view_id); |
| 560 WaitForDestruction(view_manager_2(), NULL, &views); | 526 WaitForDestruction(embedded, NULL, &views); |
| 561 EXPECT_EQ(NULL, node1_2->active_view()); | 527 EXPECT_EQ(NULL, node_in_embedded->active_view()); |
| 562 EXPECT_EQ(NULL, view_manager_2()->GetViewById(view1_id)); | 528 EXPECT_EQ(NULL, embedded->GetViewById(view_id)); |
| 563 } | 529 } |
| 564 | 530 |
| 565 // Destroying the connection that created a node and view should result in that | 531 // Destroying the connection that created a node and view should result in that |
| 566 // node and view disappearing from all connections that see them. | 532 // node and view disappearing from all connections that see them. |
| 567 TEST_F(ViewManagerTest, DISABLED_ViewManagerDestroyed_CleanupNodeAndView) { | 533 TEST_F(ViewManagerTest, DISABLED_ViewManagerDestroyed_CleanupNodeAndView) { |
| 568 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 534 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); |
| 569 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); | 535 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); |
| 570 | 536 |
| 571 View* view1 = View::Create(view_manager_1()); | 537 View* view1 = View::Create(view_manager_1()); |
| 572 node1->SetActiveView(view1); | 538 node1->SetActiveView(view1); |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 622 // disconnected from the node tree. | 588 // disconnected from the node tree. |
| 623 View* another_view1_2 = view_manager_2()->GetViewById(view1_2_id); | 589 View* another_view1_2 = view_manager_2()->GetViewById(view1_2_id); |
| 624 EXPECT_EQ(view1_2, another_view1_2); | 590 EXPECT_EQ(view1_2, another_view1_2); |
| 625 EXPECT_EQ(NULL, view1_2->node()); | 591 EXPECT_EQ(NULL, view1_2->node()); |
| 626 } | 592 } |
| 627 | 593 |
| 628 // This test verifies that it is not possible to set the active view to a view | 594 // This test verifies that it is not possible to set the active view to a view |
| 629 // defined in a different connection. | 595 // defined in a different connection. |
| 630 // TODO(beng): write these tests for ViewTreeNode::AddChild(), RemoveChild() and | 596 // TODO(beng): write these tests for ViewTreeNode::AddChild(), RemoveChild() and |
| 631 // Contains(). | 597 // Contains(). |
| 632 TEST_F(ViewManagerTest, DISABLED_SetActiveViewAcrossConnection) { | 598 TEST_F(ViewManagerTest, SetActiveViewAcrossConnection) { |
| 633 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 599 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
| 634 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); | 600 window_manager()->tree()->AddChild(node); |
| 601 ViewManager* embedded = Embed(window_manager(), node); |
| 635 | 602 |
| 636 View* view1_2 = View::Create(view_manager_2()); | 603 View* view_in_embedded = View::Create(embedded); |
| 637 EXPECT_DEATH(node1->SetActiveView(view1_2), ""); | 604 EXPECT_DEATH(node->SetActiveView(view_in_embedded), ""); |
| 638 } | 605 } |
| 639 | 606 |
| 640 // This test verifies that a node hierarchy constructed in one connection | 607 // This test verifies that a node hierarchy constructed in one connection |
| 641 // becomes entirely visible to the second connection when the hierarchy is | 608 // becomes entirely visible to the second connection when the hierarchy is |
| 642 // attached. | 609 // attached. |
| 643 TEST_F(ViewManagerTest, DISABLED_MapSubtreeOnAttach) { | 610 TEST_F(ViewManagerTest, MapSubtreeOnAttach) { |
| 644 ViewTreeNode* node1 = ViewTreeNode::Create(view_manager_1()); | 611 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
| 645 ViewTreeNode* node11 = CreateNodeInParent(node1); | 612 window_manager()->tree()->AddChild(node); |
| 646 View* view11 = View::Create(view_manager_1()); | 613 ViewManager* embedded = Embed(window_manager(), node); |
| 647 node11->SetActiveView(view11); | |
| 648 gfx::Rect node11_bounds(800, 600); | |
| 649 node11->SetBounds(node11_bounds); | |
| 650 WaitForAllChangesToBeAcked(view_manager_1()); | |
| 651 | 614 |
| 652 // Now attach this node tree to the root & wait for it to show up in the | 615 // Create a subtree private to the window manager and make some changes to it. |
| 653 // second connection. | 616 ViewTreeNode* child1 = ViewTreeNode::Create(window_manager()); |
| 654 view_manager_1()->tree()->AddChild(node1); | 617 ViewTreeNode* child11 = ViewTreeNode::Create(window_manager()); |
| 655 WaitForTreeSizeToMatch(view_manager_2()->tree(), 3); | 618 child1->AddChild(child11); |
| 619 gfx::Rect child11_bounds(800, 600); |
| 620 child11->SetBounds(child11_bounds); |
| 621 View* view11 = View::Create(window_manager()); |
| 622 child11->SetActiveView(view11); |
| 623 WaitForAllChangesToBeAcked(window_manager()); |
| 656 | 624 |
| 657 ViewTreeNode* node11_2 = view_manager_2()->GetNodeById(node11->id()); | 625 // When added to the shared node, the entire hierarchy and all property |
| 658 View* view11_2 = view_manager_2()->GetViewById(view11->id()); | 626 // changes should become visible to the embedded app. |
| 659 EXPECT_TRUE(node11_2 != NULL); | 627 node->AddChild(child1); |
| 660 EXPECT_EQ(view11_2, node11_2->active_view()); | 628 WaitForTreeSizeToMatch(embedded->tree(), 3); |
| 661 EXPECT_EQ(node11_bounds, node11_2->bounds()); | 629 |
| 630 ViewTreeNode* child11_in_embedded = embedded->GetNodeById(child11->id()); |
| 631 View* view11_in_embedded = embedded->GetViewById(view11->id()); |
| 632 EXPECT_TRUE(child11_in_embedded != NULL); |
| 633 EXPECT_EQ(view11_in_embedded, child11_in_embedded->active_view()); |
| 634 EXPECT_EQ(child11_bounds, child11_in_embedded->bounds()); |
| 662 } | 635 } |
| 663 | 636 |
| 664 // Verifies that bounds changes applied to a node hierarchy in one connection | 637 // Verifies that bounds changes applied to a node hierarchy in one connection |
| 665 // are reflected to another. | 638 // are reflected to another. |
| 666 TEST_F(ViewManagerTest, DISABLED_SetBounds) { | 639 TEST_F(ViewManagerTest, SetBounds) { |
| 667 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 640 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
| 668 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); | 641 window_manager()->tree()->AddChild(node); |
| 642 ViewManager* embedded = Embed(window_manager(), node); |
| 669 | 643 |
| 670 ViewTreeNode* node1_2 = view_manager_2()->GetNodeById(node1->id()); | 644 ViewTreeNode* node_in_embedded = embedded->GetNodeById(node->id()); |
| 671 EXPECT_EQ(node1->bounds(), node1_2->bounds()); | 645 EXPECT_EQ(node->bounds(), node_in_embedded->bounds()); |
| 672 | 646 |
| 673 node1->SetBounds(gfx::Rect(0, 0, 100, 100)); | 647 node->SetBounds(gfx::Rect(100, 100)); |
| 674 WaitForBoundsToChange(node1_2); | 648 EXPECT_NE(node->bounds(), node_in_embedded->bounds()); |
| 675 EXPECT_EQ(node1->bounds(), node1_2->bounds()); | 649 WaitForBoundsToChange(node_in_embedded); |
| 650 EXPECT_EQ(node->bounds(), node_in_embedded->bounds()); |
| 676 } | 651 } |
| 677 | 652 |
| 678 // Verifies that bounds changes applied to a node owned by a different | 653 // Verifies that bounds changes applied to a node owned by a different |
| 679 // connection are refused. | 654 // connection are refused. |
| 680 TEST_F(ViewManagerTest, DISABLED_SetBoundsSecurity) { | 655 TEST_F(ViewManagerTest, SetBoundsSecurity) { |
| 681 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 656 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
| 682 node1->SetBounds(gfx::Rect(800, 600)); | 657 window_manager()->tree()->AddChild(node); |
| 683 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); | 658 ViewManager* embedded = Embed(window_manager(), node); |
| 684 | 659 |
| 685 ViewTreeNode* node1_2 = view_manager_2()->GetNodeById(node1->id()); | 660 ViewTreeNode* node_in_embedded = embedded->GetNodeById(node->id()); |
| 686 node1_2->SetBounds(gfx::Rect(1024, 768)); | 661 node->SetBounds(gfx::Rect(800, 600)); |
| 662 WaitForBoundsToChange(node_in_embedded); |
| 663 |
| 664 node_in_embedded->SetBounds(gfx::Rect(1024, 768)); |
| 687 // Bounds change should have been rejected. | 665 // Bounds change should have been rejected. |
| 688 EXPECT_EQ(node1->bounds(), node1_2->bounds()); | 666 EXPECT_EQ(node->bounds(), node_in_embedded->bounds()); |
| 689 } | 667 } |
| 690 | 668 |
| 691 // Verifies that a node can only be destroyed by the connection that created it. | 669 // Verifies that a node can only be destroyed by the connection that created it. |
| 692 TEST_F(ViewManagerTest, DISABLED_DestroySecurity) { | 670 TEST_F(ViewManagerTest, DestroySecurity) { |
| 693 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 671 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
| 694 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); | 672 window_manager()->tree()->AddChild(node); |
| 673 ViewManager* embedded = Embed(window_manager(), node); |
| 695 | 674 |
| 696 ViewTreeNode* node1_2 = view_manager_2()->GetNodeById(node1->id()); | 675 ViewTreeNode* node_in_embedded = embedded->GetNodeById(node->id()); |
| 697 NodeTracker tracker2(node1_2); | 676 |
| 698 node1_2->Destroy(); | 677 NodeTracker tracker2(node_in_embedded); |
| 678 node_in_embedded->Destroy(); |
| 699 // Node should not have been destroyed. | 679 // Node should not have been destroyed. |
| 700 EXPECT_TRUE(tracker2.is_valid()); | 680 EXPECT_TRUE(tracker2.is_valid()); |
| 701 | 681 |
| 702 NodeTracker tracker1(node1); | 682 NodeTracker tracker1(node); |
| 703 node1->Destroy(); | 683 node->Destroy(); |
| 704 EXPECT_FALSE(tracker1.is_valid()); | 684 EXPECT_FALSE(tracker1.is_valid()); |
| 705 } | 685 } |
| 706 | 686 |
| 707 } // namespace view_manager | 687 } // namespace view_manager |
| 708 } // namespace mojo | 688 } // namespace mojo |
| OLD | NEW |