| 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 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 188 node->RemoveObserver(&observer); | 188 node->RemoveObserver(&observer); |
| 189 } | 189 } |
| 190 | 190 |
| 191 | 191 |
| 192 // Utility class that waits for the destruction of some number of nodes and | 192 // Utility class that waits for the destruction of some number of nodes and |
| 193 // views. | 193 // views. |
| 194 class DestructionObserver : public ViewTreeNodeObserver, | 194 class DestructionObserver : public ViewTreeNodeObserver, |
| 195 public ViewObserver { | 195 public ViewObserver { |
| 196 public: | 196 public: |
| 197 // |nodes| or |views| can be NULL. | 197 // |nodes| or |views| can be NULL. |
| 198 DestructionObserver(std::set<TransportNodeId>* nodes, | 198 DestructionObserver(std::set<Id>* nodes, std::set<Id>* views) |
| 199 std::set<TransportViewId>* views) | |
| 200 : nodes_(nodes), | 199 : nodes_(nodes), |
| 201 views_(views) {} | 200 views_(views) {} |
| 202 | 201 |
| 203 private: | 202 private: |
| 204 // Overridden from ViewTreeNodeObserver: | 203 // Overridden from ViewTreeNodeObserver: |
| 205 virtual void OnNodeDestroy( | 204 virtual void OnNodeDestroy( |
| 206 ViewTreeNode* node, | 205 ViewTreeNode* node, |
| 207 ViewTreeNodeObserver::DispositionChangePhase phase) OVERRIDE { | 206 ViewTreeNodeObserver::DispositionChangePhase phase) OVERRIDE { |
| 208 if (phase != ViewTreeNodeObserver::DISPOSITION_CHANGED) | 207 if (phase != ViewTreeNodeObserver::DISPOSITION_CHANGED) |
| 209 return; | 208 return; |
| 210 std::set<TransportNodeId>::const_iterator it = nodes_->find(node->id()); | 209 std::set<Id>::const_iterator it = nodes_->find(node->id()); |
| 211 if (it != nodes_->end()) | 210 if (it != nodes_->end()) |
| 212 nodes_->erase(it); | 211 nodes_->erase(it); |
| 213 if (CanQuit()) | 212 if (CanQuit()) |
| 214 QuitRunLoop(); | 213 QuitRunLoop(); |
| 215 } | 214 } |
| 216 | 215 |
| 217 // Overridden from ViewObserver: | 216 // Overridden from ViewObserver: |
| 218 virtual void OnViewDestroy( | 217 virtual void OnViewDestroy( |
| 219 View* view, | 218 View* view, |
| 220 ViewObserver::DispositionChangePhase phase) OVERRIDE { | 219 ViewObserver::DispositionChangePhase phase) OVERRIDE { |
| 221 if (phase != ViewObserver::DISPOSITION_CHANGED) | 220 if (phase != ViewObserver::DISPOSITION_CHANGED) |
| 222 return; | 221 return; |
| 223 std::set<TransportViewId>::const_iterator it = views_->find(view->id()); | 222 std::set<Id>::const_iterator it = views_->find(view->id()); |
| 224 if (it != views_->end()) | 223 if (it != views_->end()) |
| 225 views_->erase(it); | 224 views_->erase(it); |
| 226 if (CanQuit()) | 225 if (CanQuit()) |
| 227 QuitRunLoop(); | 226 QuitRunLoop(); |
| 228 } | 227 } |
| 229 | 228 |
| 230 bool CanQuit() { | 229 bool CanQuit() { |
| 231 return (!nodes_ || nodes_->empty()) && (!views_ || views_->empty()); | 230 return (!nodes_ || nodes_->empty()) && (!views_ || views_->empty()); |
| 232 } | 231 } |
| 233 | 232 |
| 234 std::set<TransportNodeId>* nodes_; | 233 std::set<Id>* nodes_; |
| 235 std::set<TransportViewId>* views_; | 234 std::set<Id>* views_; |
| 236 | 235 |
| 237 DISALLOW_COPY_AND_ASSIGN(DestructionObserver); | 236 DISALLOW_COPY_AND_ASSIGN(DestructionObserver); |
| 238 }; | 237 }; |
| 239 | 238 |
| 240 void WaitForDestruction(ViewManager* view_manager, | 239 void WaitForDestruction(ViewManager* view_manager, |
| 241 std::set<TransportNodeId>* nodes, | 240 std::set<Id>* nodes, |
| 242 std::set<TransportViewId>* views) { | 241 std::set<Id>* views) { |
| 243 DestructionObserver observer(nodes, views); | 242 DestructionObserver observer(nodes, views); |
| 244 DCHECK(nodes || views); | 243 DCHECK(nodes || views); |
| 245 if (nodes) { | 244 if (nodes) { |
| 246 for (std::set<TransportNodeId>::const_iterator it = nodes->begin(); | 245 for (std::set<Id>::const_iterator it = nodes->begin(); |
| 247 it != nodes->end(); ++it) { | 246 it != nodes->end(); ++it) { |
| 248 view_manager->GetNodeById(*it)->AddObserver(&observer); | 247 view_manager->GetNodeById(*it)->AddObserver(&observer); |
| 249 } | 248 } |
| 250 } | 249 } |
| 251 if (views) { | 250 if (views) { |
| 252 for (std::set<TransportViewId>::const_iterator it = views->begin(); | 251 for (std::set<Id>::const_iterator it = views->begin(); |
| 253 it != views->end(); ++it) { | 252 it != views->end(); ++it) { |
| 254 view_manager->GetViewById(*it)->AddObserver(&observer); | 253 view_manager->GetViewById(*it)->AddObserver(&observer); |
| 255 } | 254 } |
| 256 } | 255 } |
| 257 DoRunLoop(); | 256 DoRunLoop(); |
| 258 } | 257 } |
| 259 | 258 |
| 260 // Tracks a node's destruction. Query is_valid() for current state. | 259 // Tracks a node's destruction. Query is_valid() for current state. |
| 261 class NodeTracker : public ViewTreeNodeObserver { | 260 class NodeTracker : public ViewTreeNodeObserver { |
| 262 public: | 261 public: |
| (...skipping 211 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 474 TEST_F(ViewManagerTest, NodeDestroyed) { | 473 TEST_F(ViewManagerTest, NodeDestroyed) { |
| 475 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); | 474 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
| 476 window_manager()->roots().front()->AddChild(node); | 475 window_manager()->roots().front()->AddChild(node); |
| 477 ViewTreeNode* nested = ViewTreeNode::Create(window_manager()); | 476 ViewTreeNode* nested = ViewTreeNode::Create(window_manager()); |
| 478 node->AddChild(nested); | 477 node->AddChild(nested); |
| 479 | 478 |
| 480 ViewManager* embedded = Embed(window_manager(), node); | 479 ViewManager* embedded = Embed(window_manager(), node); |
| 481 EXPECT_EQ(embedded->roots().front()->children().front()->id(), nested->id()); | 480 EXPECT_EQ(embedded->roots().front()->children().front()->id(), nested->id()); |
| 482 | 481 |
| 483 // |nested| will be deleted after calling Destroy() below. | 482 // |nested| will be deleted after calling Destroy() below. |
| 484 TransportNodeId id = nested->id(); | 483 Id id = nested->id(); |
| 485 nested->Destroy(); | 484 nested->Destroy(); |
| 486 | 485 |
| 487 std::set<TransportNodeId> nodes; | 486 std::set<Id> nodes; |
| 488 nodes.insert(id); | 487 nodes.insert(id); |
| 489 WaitForDestruction(embedded, &nodes, NULL); | 488 WaitForDestruction(embedded, &nodes, NULL); |
| 490 | 489 |
| 491 EXPECT_TRUE(embedded->roots().front()->children().empty()); | 490 EXPECT_TRUE(embedded->roots().front()->children().empty()); |
| 492 EXPECT_EQ(NULL, embedded->GetNodeById(id)); | 491 EXPECT_EQ(NULL, embedded->GetNodeById(id)); |
| 493 } | 492 } |
| 494 | 493 |
| 495 TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNode) { | 494 TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNode) { |
| 496 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); | 495 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
| 497 window_manager()->roots().front()->AddChild(node); | 496 window_manager()->roots().front()->AddChild(node); |
| 498 ViewManager* embedded = Embed(window_manager(), node); | 497 ViewManager* embedded = Embed(window_manager(), node); |
| 499 | 498 |
| 500 TransportNodeId node_id = node->id(); | 499 Id node_id = node->id(); |
| 501 | 500 |
| 502 UnloadApplication(GURL(kWindowManagerURL)); | 501 UnloadApplication(GURL(kWindowManagerURL)); |
| 503 | 502 |
| 504 std::set<TransportNodeId> nodes; | 503 std::set<Id> nodes; |
| 505 nodes.insert(node_id); | 504 nodes.insert(node_id); |
| 506 WaitForDestruction(embedded, &nodes, NULL); | 505 WaitForDestruction(embedded, &nodes, NULL); |
| 507 | 506 |
| 508 EXPECT_TRUE(embedded->roots().empty()); | 507 EXPECT_TRUE(embedded->roots().empty()); |
| 509 } | 508 } |
| 510 | 509 |
| 511 TEST_F(ViewManagerTest, SetActiveView) { | 510 TEST_F(ViewManagerTest, SetActiveView) { |
| 512 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); | 511 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
| 513 window_manager()->roots().front()->AddChild(node); | 512 window_manager()->roots().front()->AddChild(node); |
| 514 ViewManager* embedded = Embed(window_manager(), node); | 513 ViewManager* embedded = Embed(window_manager(), node); |
| (...skipping 13 matching lines...) Expand all Loading... |
| 528 ViewManager* embedded = Embed(window_manager(), node); | 527 ViewManager* embedded = Embed(window_manager(), node); |
| 529 | 528 |
| 530 View* view = View::Create(window_manager()); | 529 View* view = View::Create(window_manager()); |
| 531 node->SetActiveView(view); | 530 node->SetActiveView(view); |
| 532 | 531 |
| 533 ViewTreeNode* node_in_embedded = embedded->GetNodeById(node->id()); | 532 ViewTreeNode* node_in_embedded = embedded->GetNodeById(node->id()); |
| 534 WaitForActiveViewToChange(node_in_embedded); | 533 WaitForActiveViewToChange(node_in_embedded); |
| 535 | 534 |
| 536 EXPECT_EQ(node_in_embedded->active_view()->id(), view->id()); | 535 EXPECT_EQ(node_in_embedded->active_view()->id(), view->id()); |
| 537 | 536 |
| 538 TransportViewId view_id = view->id(); | 537 Id view_id = view->id(); |
| 539 view->Destroy(); | 538 view->Destroy(); |
| 540 | 539 |
| 541 std::set<TransportViewId> views; | 540 std::set<Id> views; |
| 542 views.insert(view_id); | 541 views.insert(view_id); |
| 543 WaitForDestruction(embedded, NULL, &views); | 542 WaitForDestruction(embedded, NULL, &views); |
| 544 EXPECT_EQ(NULL, node_in_embedded->active_view()); | 543 EXPECT_EQ(NULL, node_in_embedded->active_view()); |
| 545 EXPECT_EQ(NULL, embedded->GetViewById(view_id)); | 544 EXPECT_EQ(NULL, embedded->GetViewById(view_id)); |
| 546 } | 545 } |
| 547 | 546 |
| 548 // Destroying the connection that created a node and view should result in that | 547 // Destroying the connection that created a node and view should result in that |
| 549 // node and view disappearing from all connections that see them. | 548 // node and view disappearing from all connections that see them. |
| 550 TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNodeAndView) { | 549 TEST_F(ViewManagerTest, ViewManagerDestroyed_CleanupNodeAndView) { |
| 551 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); | 550 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
| 552 window_manager()->roots().front()->AddChild(node); | 551 window_manager()->roots().front()->AddChild(node); |
| 553 View* view = View::Create(window_manager()); | 552 View* view = View::Create(window_manager()); |
| 554 node->SetActiveView(view); | 553 node->SetActiveView(view); |
| 555 ViewManager* embedded = Embed(window_manager(), node); | 554 ViewManager* embedded = Embed(window_manager(), node); |
| 556 | 555 |
| 557 TransportNodeId node_id = node->id(); | 556 Id node_id = node->id(); |
| 558 TransportViewId view_id = view->id(); | 557 Id view_id = view->id(); |
| 559 | 558 |
| 560 UnloadApplication(GURL(kWindowManagerURL)); | 559 UnloadApplication(GURL(kWindowManagerURL)); |
| 561 | 560 |
| 562 std::set<TransportNodeId> observed_nodes; | 561 std::set<Id> observed_nodes; |
| 563 observed_nodes.insert(node_id); | 562 observed_nodes.insert(node_id); |
| 564 std::set<TransportViewId> observed_views; | 563 std::set<Id> observed_views; |
| 565 observed_views.insert(view_id); | 564 observed_views.insert(view_id); |
| 566 WaitForDestruction(embedded, &observed_nodes, &observed_views); | 565 WaitForDestruction(embedded, &observed_nodes, &observed_views); |
| 567 | 566 |
| 568 EXPECT_TRUE(embedded->roots().empty()); | 567 EXPECT_TRUE(embedded->roots().empty()); |
| 569 EXPECT_EQ(NULL, embedded->GetNodeById(node_id)); | 568 EXPECT_EQ(NULL, embedded->GetNodeById(node_id)); |
| 570 EXPECT_EQ(NULL, embedded->GetViewById(view_id)); | 569 EXPECT_EQ(NULL, embedded->GetViewById(view_id)); |
| 571 } | 570 } |
| 572 | 571 |
| 573 // This test validates the following scenario: | 572 // This test validates the following scenario: |
| 574 // - a node originating from one connection | 573 // - a node originating from one connection |
| 575 // - a view originating from a second connection | 574 // - a view originating from a second connection |
| 576 // + the connection originating the node is destroyed | 575 // + the connection originating the node is destroyed |
| 577 // -> the view should still exist (since the second connection is live) but | 576 // -> the view should still exist (since the second connection is live) but |
| 578 // should be disconnected from any nodes. | 577 // should be disconnected from any nodes. |
| 579 TEST_F(ViewManagerTest, | 578 TEST_F(ViewManagerTest, |
| 580 ViewManagerDestroyed_CleanupNodeAndViewFromDifferentConnections) { | 579 ViewManagerDestroyed_CleanupNodeAndViewFromDifferentConnections) { |
| 581 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); | 580 ViewTreeNode* node = ViewTreeNode::Create(window_manager()); |
| 582 window_manager()->roots().front()->AddChild(node); | 581 window_manager()->roots().front()->AddChild(node); |
| 583 ViewManager* embedded = Embed(window_manager(), node); | 582 ViewManager* embedded = Embed(window_manager(), node); |
| 584 View* view_in_embedded = View::Create(embedded); | 583 View* view_in_embedded = View::Create(embedded); |
| 585 ViewTreeNode* node_in_embedded = embedded->GetNodeById(node->id()); | 584 ViewTreeNode* node_in_embedded = embedded->GetNodeById(node->id()); |
| 586 node_in_embedded->SetActiveView(view_in_embedded); | 585 node_in_embedded->SetActiveView(view_in_embedded); |
| 587 | 586 |
| 588 WaitForActiveViewToChange(node); | 587 WaitForActiveViewToChange(node); |
| 589 | 588 |
| 590 TransportNodeId node_id = node->id(); | 589 Id node_id = node->id(); |
| 591 TransportViewId view_id = view_in_embedded->id(); | 590 Id view_id = view_in_embedded->id(); |
| 592 | 591 |
| 593 UnloadApplication(GURL(kWindowManagerURL)); | 592 UnloadApplication(GURL(kWindowManagerURL)); |
| 594 std::set<TransportNodeId> nodes; | 593 std::set<Id> nodes; |
| 595 nodes.insert(node_id); | 594 nodes.insert(node_id); |
| 596 WaitForDestruction(embedded, &nodes, NULL); | 595 WaitForDestruction(embedded, &nodes, NULL); |
| 597 | 596 |
| 598 EXPECT_TRUE(embedded->roots().empty()); | 597 EXPECT_TRUE(embedded->roots().empty()); |
| 599 // node was owned by the window manager, so it should be gone. | 598 // node was owned by the window manager, so it should be gone. |
| 600 EXPECT_EQ(NULL, embedded->GetNodeById(node_id)); | 599 EXPECT_EQ(NULL, embedded->GetNodeById(node_id)); |
| 601 // view_in_embedded was owned by the embedded app, so it should still exist, | 600 // view_in_embedded was owned by the embedded app, so it should still exist, |
| 602 // but disconnected from the node tree. | 601 // but disconnected from the node tree. |
| 603 EXPECT_EQ(view_in_embedded, embedded->GetViewById(view_id)); | 602 EXPECT_EQ(view_in_embedded, embedded->GetViewById(view_id)); |
| 604 EXPECT_EQ(NULL, view_in_embedded->node()); | 603 EXPECT_EQ(NULL, view_in_embedded->node()); |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 window_manager()->roots().front()->AddChild(node1); | 701 window_manager()->roots().front()->AddChild(node1); |
| 703 ViewTreeNode* node2 = ViewTreeNode::Create(window_manager()); | 702 ViewTreeNode* node2 = ViewTreeNode::Create(window_manager()); |
| 704 window_manager()->roots().front()->AddChild(node2); | 703 window_manager()->roots().front()->AddChild(node2); |
| 705 ViewManager* embedded1 = Embed(window_manager(), node1); | 704 ViewManager* embedded1 = Embed(window_manager(), node1); |
| 706 ViewManager* embedded2 = Embed(window_manager(), node2); | 705 ViewManager* embedded2 = Embed(window_manager(), node2); |
| 707 EXPECT_EQ(embedded1, embedded2); | 706 EXPECT_EQ(embedded1, embedded2); |
| 708 } | 707 } |
| 709 | 708 |
| 710 } // namespace view_manager | 709 } // namespace view_manager |
| 711 } // namespace mojo | 710 } // namespace mojo |
| OLD | NEW |