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 |