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/auto_reset.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "mojo/public/cpp/application/application.h" | 10 #include "mojo/public/cpp/application/application.h" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
43 QuitRunLoop(); | 43 QuitRunLoop(); |
44 } | 44 } |
45 | 45 |
46 void WaitForAllChangesToBeAcked(ViewManager* manager) { | 46 void WaitForAllChangesToBeAcked(ViewManager* manager) { |
47 ViewManagerPrivate(manager).synchronizer()->set_changes_acked_callback( | 47 ViewManagerPrivate(manager).synchronizer()->set_changes_acked_callback( |
48 base::Bind(&QuitRunLoopOnChangesAcked)); | 48 base::Bind(&QuitRunLoopOnChangesAcked)); |
49 DoRunLoop(); | 49 DoRunLoop(); |
50 ViewManagerPrivate(manager).synchronizer()->ClearChangesAckedCallback(); | 50 ViewManagerPrivate(manager).synchronizer()->ClearChangesAckedCallback(); |
51 } | 51 } |
52 | 52 |
53 // Used with IViewManager::Connect(). Creates a TestViewManagerClientConnection, | |
54 // which creates and owns the ViewManagerProxy. | |
55 class ConnectServiceLoader : public ServiceLoader { | 53 class ConnectServiceLoader : public ServiceLoader { |
56 public: | 54 public: |
57 explicit ConnectServiceLoader(base::Callback<void(ViewManager*)> callback) | 55 explicit ConnectServiceLoader(base::Callback<void(ViewManager*)> callback) |
58 : callback_(callback) {} | 56 : callback_(callback) {} |
59 virtual ~ConnectServiceLoader() {} | 57 virtual ~ConnectServiceLoader() {} |
60 | 58 |
61 // ServiceLoader: | 59 private: |
| 60 // Overridden from ServiceLoader: |
62 virtual void LoadService(ServiceManager* manager, | 61 virtual void LoadService(ServiceManager* manager, |
63 const GURL& url, | 62 const GURL& url, |
64 ScopedMessagePipeHandle shell_handle) OVERRIDE { | 63 ScopedMessagePipeHandle shell_handle) OVERRIDE { |
65 scoped_ptr<Application> app(new Application(shell_handle.Pass())); | 64 scoped_ptr<Application> app(new Application(shell_handle.Pass())); |
66 ViewManager::Create(app.get(), callback_); | 65 ViewManager::Create(app.get(), callback_); |
67 apps_.push_back(app.release()); | 66 apps_.push_back(app.release()); |
68 } | 67 } |
69 virtual void OnServiceError(ServiceManager* manager, | 68 virtual void OnServiceError(ServiceManager* manager, |
70 const GURL& url) OVERRIDE { | 69 const GURL& url) OVERRIDE { |
71 } | 70 } |
72 | 71 |
73 private: | |
74 ScopedVector<Application> apps_; | 72 ScopedVector<Application> apps_; |
75 base::Callback<void(ViewManager*)> callback_; | 73 base::Callback<void(ViewManager*)> callback_; |
76 | 74 |
77 DISALLOW_COPY_AND_ASSIGN(ConnectServiceLoader); | 75 DISALLOW_COPY_AND_ASSIGN(ConnectServiceLoader); |
78 }; | 76 }; |
79 | 77 |
80 class ActiveViewChangedObserver : public ViewTreeNodeObserver { | 78 class ActiveViewChangedObserver : public ViewTreeNodeObserver { |
81 public: | 79 public: |
82 explicit ActiveViewChangedObserver(ViewTreeNode* node) | 80 explicit ActiveViewChangedObserver(ViewTreeNode* node) |
83 : node_(node) {} | 81 : node_(node) {} |
(...skipping 231 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
315 void DestroyViewManager1() {} | 313 void DestroyViewManager1() {} |
316 ViewManager* view_manager_1() { return NULL; } | 314 ViewManager* view_manager_1() { return NULL; } |
317 ViewManager* view_manager_2() { return NULL; } | 315 ViewManager* view_manager_2() { return NULL; } |
318 | 316 |
319 ViewManager* GetLoadedViewManager() { | 317 ViewManager* GetLoadedViewManager() { |
320 ViewManager* view_manager = loaded_view_manager_; | 318 ViewManager* view_manager = loaded_view_manager_; |
321 loaded_view_manager_ = NULL; | 319 loaded_view_manager_ = NULL; |
322 return view_manager; | 320 return view_manager; |
323 } | 321 } |
324 | 322 |
| 323 void UnloadApplication(const GURL& url) { |
| 324 test_helper_.SetLoaderForURL(scoped_ptr<ServiceLoader>(), url); |
| 325 } |
| 326 |
325 private: | 327 private: |
326 // Overridden from testing::Test: | 328 // Overridden from testing::Test: |
327 virtual void SetUp() OVERRIDE { | 329 virtual void SetUp() OVERRIDE { |
328 test_helper_.Init(); | 330 test_helper_.Init(); |
329 test_helper_.SetLoaderForURL( | 331 test_helper_.SetLoaderForURL( |
330 scoped_ptr<ServiceLoader>(new ConnectServiceLoader( | 332 scoped_ptr<ServiceLoader>(new ConnectServiceLoader( |
331 base::Bind(&ViewManagerTest::OnViewManagerLoaded, | 333 base::Bind(&ViewManagerTest::OnViewManagerLoaded, |
332 base::Unretained(this)))), | 334 base::Unretained(this)))), |
333 GURL(kTestServiceURL)); | 335 GURL(kTestServiceURL)); |
334 test_helper_.SetLoaderForURL( | 336 test_helper_.SetLoaderForURL( |
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
469 nested->Destroy(); | 471 nested->Destroy(); |
470 | 472 |
471 std::set<TransportNodeId> nodes; | 473 std::set<TransportNodeId> nodes; |
472 nodes.insert(id); | 474 nodes.insert(id); |
473 WaitForDestruction(embedded, &nodes, NULL); | 475 WaitForDestruction(embedded, &nodes, NULL); |
474 | 476 |
475 EXPECT_TRUE(embedded->tree()->children().empty()); | 477 EXPECT_TRUE(embedded->tree()->children().empty()); |
476 EXPECT_EQ(NULL, embedded->GetNodeById(id)); | 478 EXPECT_EQ(NULL, embedded->GetNodeById(id)); |
477 } | 479 } |
478 | 480 |
479 // TODO(beng): provide a way to terminate an application. | 481 TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNode) { |
480 TEST_F(ViewManagerTest, DISABLED_ViewManagerDestroyed_CleanupNode) { | 482 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
481 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 483 window_manager()->tree()->AddChild(node); |
482 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); | 484 ViewManager* embedded = Embed(window_manager(), node); |
483 | 485 |
484 TransportNodeId id = node1->id(); | 486 TransportNodeId node_id = node->id(); |
485 DestroyViewManager1(); | 487 |
| 488 UnloadApplication(GURL(kTestServiceURL)); |
| 489 |
486 std::set<TransportNodeId> nodes; | 490 std::set<TransportNodeId> nodes; |
487 nodes.insert(id); | 491 nodes.insert(node_id); |
488 WaitForDestruction(view_manager_2(), &nodes, NULL); | 492 WaitForDestruction(embedded, &nodes, NULL); |
489 | 493 |
490 // tree() should still be valid, since it's owned by neither connection. | 494 EXPECT_EQ(NULL, embedded->tree()); |
491 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); | |
492 } | 495 } |
493 | 496 |
494 TEST_F(ViewManagerTest, SetActiveView) { | 497 TEST_F(ViewManagerTest, SetActiveView) { |
495 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); | 498 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
496 window_manager()->tree()->AddChild(node); | 499 window_manager()->tree()->AddChild(node); |
497 ViewManager* embedded = Embed(window_manager(), node); | 500 ViewManager* embedded = Embed(window_manager(), node); |
498 | 501 |
499 View* view = View::Create(window_manager()); | 502 View* view = View::Create(window_manager()); |
500 node->SetActiveView(view); | 503 node->SetActiveView(view); |
501 | 504 |
(...skipping 21 matching lines...) Expand all Loading... |
523 | 526 |
524 std::set<TransportViewId> views; | 527 std::set<TransportViewId> views; |
525 views.insert(view_id); | 528 views.insert(view_id); |
526 WaitForDestruction(embedded, NULL, &views); | 529 WaitForDestruction(embedded, NULL, &views); |
527 EXPECT_EQ(NULL, node_in_embedded->active_view()); | 530 EXPECT_EQ(NULL, node_in_embedded->active_view()); |
528 EXPECT_EQ(NULL, embedded->GetViewById(view_id)); | 531 EXPECT_EQ(NULL, embedded->GetViewById(view_id)); |
529 } | 532 } |
530 | 533 |
531 // Destroying the connection that created a node and view should result in that | 534 // Destroying the connection that created a node and view should result in that |
532 // node and view disappearing from all connections that see them. | 535 // node and view disappearing from all connections that see them. |
533 TEST_F(ViewManagerTest, DISABLED_ViewManagerDestroyed_CleanupNodeAndView) { | 536 TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNodeAndView) { |
534 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 537 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
535 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); | 538 window_manager()->tree()->AddChild(node); |
| 539 View* view = View::Create(window_manager()); |
| 540 node->SetActiveView(view); |
| 541 ViewManager* embedded = Embed(window_manager(), node); |
536 | 542 |
537 View* view1 = View::Create(view_manager_1()); | 543 TransportNodeId node_id = node->id(); |
538 node1->SetActiveView(view1); | 544 TransportViewId view_id = view->id(); |
539 | 545 |
540 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id()); | 546 UnloadApplication(GURL(kTestServiceURL)); |
541 WaitForActiveViewToChange(node1_2); | |
542 | 547 |
543 TransportNodeId node1_id = node1->id(); | 548 std::set<TransportNodeId> observed_nodes; |
544 TransportViewId view1_id = view1->id(); | 549 observed_nodes.insert(node_id); |
| 550 std::set<TransportViewId> observed_views; |
| 551 observed_views.insert(view_id); |
| 552 WaitForDestruction(embedded, &observed_nodes, &observed_views); |
545 | 553 |
546 DestroyViewManager1(); | 554 EXPECT_EQ(NULL, embedded->tree()); |
547 std::set<TransportNodeId> observed_nodes; | 555 EXPECT_EQ(NULL, embedded->GetNodeById(node_id)); |
548 observed_nodes.insert(node1_id); | 556 EXPECT_EQ(NULL, embedded->GetViewById(view_id)); |
549 std::set<TransportViewId> observed_views; | |
550 observed_views.insert(view1_id); | |
551 WaitForDestruction(view_manager_2(), &observed_nodes, &observed_views); | |
552 | |
553 // tree() should still be valid, since it's owned by neither connection. | |
554 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); | |
555 EXPECT_EQ(NULL, view_manager_2()->GetNodeById(node1_id)); | |
556 EXPECT_EQ(NULL, view_manager_2()->GetViewById(view1_id)); | |
557 } | 557 } |
558 | 558 |
559 // This test validates the following scenario: | 559 // This test validates the following scenario: |
560 // - a node originating from one connection | 560 // - a node originating from one connection |
561 // - a view originating from a second connection | 561 // - a view originating from a second connection |
562 // + the connection originating the node is destroyed | 562 // + the connection originating the node is destroyed |
563 // -> the view should still exist (since the second connection is live) but | 563 // -> the view should still exist (since the second connection is live) but |
564 // should be disconnected from any nodes. | 564 // should be disconnected from any nodes. |
565 TEST_F(ViewManagerTest, | 565 TEST_F(ViewManagerTest, |
566 DISABLED_ViewManagerDestroyed_CleanupNodeAndViewFromDifferentConnections) { | 566 ViewManagerDestroyed_CleanupNodeAndViewFromDifferentConnections) { |
567 ViewTreeNode* node1 = CreateNodeInParent(view_manager_1()->tree()); | 567 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
568 WaitForTreeSizeToMatch(view_manager_2()->tree(), 2); | 568 window_manager()->tree()->AddChild(node); |
| 569 ViewManager* embedded = Embed(window_manager(), node); |
| 570 View* view_in_embedded = View::Create(embedded); |
| 571 ViewTreeNode* node_in_embedded = embedded->GetNodeById(node->id()); |
| 572 node_in_embedded->SetActiveView(view_in_embedded); |
569 | 573 |
570 View* view1_2 = View::Create(view_manager_2()); | 574 WaitForActiveViewToChange(node); |
571 ViewTreeNode* node1_2 = view_manager_2()->tree()->GetChildById(node1->id()); | |
572 node1_2->SetActiveView(view1_2); | |
573 WaitForActiveViewToChange(node1); | |
574 | 575 |
575 TransportNodeId node1_id = node1->id(); | 576 TransportNodeId node_id = node->id(); |
576 TransportViewId view1_2_id = view1_2->id(); | 577 TransportViewId view_id = view_in_embedded->id(); |
577 | 578 |
578 DestroyViewManager1(); | 579 UnloadApplication(GURL(kTestServiceURL)); |
579 std::set<TransportNodeId> nodes; | 580 std::set<TransportNodeId> nodes; |
580 nodes.insert(node1_id); | 581 nodes.insert(node_id); |
581 WaitForDestruction(view_manager_2(), &nodes, NULL); | 582 WaitForDestruction(embedded, &nodes, NULL); |
582 | 583 |
583 // tree() should still be valid, since it's owned by neither connection. | 584 EXPECT_EQ(NULL, embedded->tree()); |
584 EXPECT_TRUE(view_manager_2()->tree()->children().empty()); | 585 // node was owned by the window manager, so it should be gone. |
585 // node1 was owned by the first connection, so it should be gone. | 586 EXPECT_EQ(NULL, embedded->GetNodeById(node_id)); |
586 EXPECT_EQ(NULL, view_manager_2()->GetNodeById(node1_id)); | 587 // view_in_embedded was owned by the embedded app, so it should still exist, |
587 // view1_2 was owned by the second connection, so it should still exist, but | 588 // but disconnected from the node tree. |
588 // disconnected from the node tree. | 589 EXPECT_EQ(view_in_embedded, embedded->GetViewById(view_id)); |
589 View* another_view1_2 = view_manager_2()->GetViewById(view1_2_id); | 590 EXPECT_EQ(NULL, view_in_embedded->node()); |
590 EXPECT_EQ(view1_2, another_view1_2); | |
591 EXPECT_EQ(NULL, view1_2->node()); | |
592 } | 591 } |
593 | 592 |
594 // This test verifies that it is not possible to set the active view to a view | 593 // This test verifies that it is not possible to set the active view to a view |
595 // defined in a different connection. | 594 // defined in a different connection. |
596 // TODO(beng): write these tests for ViewTreeNode::AddChild(), RemoveChild() and | 595 // TODO(beng): write these tests for ViewTreeNode::AddChild(), RemoveChild() and |
597 // Contains(). | 596 // Contains(). |
598 TEST_F(ViewManagerTest, SetActiveViewAcrossConnection) { | 597 TEST_F(ViewManagerTest, SetActiveViewAcrossConnection) { |
599 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); | 598 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
600 window_manager()->tree()->AddChild(node); | 599 window_manager()->tree()->AddChild(node); |
601 ViewManager* embedded = Embed(window_manager(), node); | 600 ViewManager* embedded = Embed(window_manager(), node); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
679 // Node should not have been destroyed. | 678 // Node should not have been destroyed. |
680 EXPECT_TRUE(tracker2.is_valid()); | 679 EXPECT_TRUE(tracker2.is_valid()); |
681 | 680 |
682 NodeTracker tracker1(node); | 681 NodeTracker tracker1(node); |
683 node->Destroy(); | 682 node->Destroy(); |
684 EXPECT_FALSE(tracker1.is_valid()); | 683 EXPECT_FALSE(tracker1.is_valid()); |
685 } | 684 } |
686 | 685 |
687 } // namespace view_manager | 686 } // namespace view_manager |
688 } // namespace mojo | 687 } // namespace mojo |
OLD | NEW |