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 |