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/view_manager/view_manager_service_impl.h" | 5 #include "mojo/services/view_manager/view_manager_service_impl.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "mojo/services/public/cpp/geometry/geometry_type_converters.h" | 8 #include "mojo/services/public/cpp/geometry/geometry_type_converters.h" |
9 #include "mojo/services/public/cpp/input_events/input_events_type_converters.h" | 9 #include "mojo/services/public/cpp/input_events/input_events_type_converters.h" |
10 #include "mojo/services/view_manager/node.h" | 10 #include "mojo/services/view_manager/node.h" |
11 #include "mojo/services/view_manager/root_node_manager.h" | 11 #include "mojo/services/view_manager/root_node_manager.h" |
12 #include "mojo/services/view_manager/view.h" | 12 #include "mojo/services/view_manager/view.h" |
13 #include "third_party/skia/include/core/SkBitmap.h" | 13 #include "third_party/skia/include/core/SkBitmap.h" |
14 #include "ui/aura/window.h" | 14 #include "ui/aura/window.h" |
15 #include "ui/gfx/codec/png_codec.h" | 15 #include "ui/gfx/codec/png_codec.h" |
16 | 16 |
17 namespace mojo { | 17 namespace mojo { |
18 namespace view_manager { | 18 namespace view_manager { |
19 namespace service { | 19 namespace service { |
20 namespace { | |
21 | |
22 // Places |node| in |nodes| and recurses through the children. | |
23 void GetDescendants(const Node* node, std::vector<const Node*>* nodes) { | |
24 if (!node) | |
25 return; | |
26 | |
27 nodes->push_back(node); | |
28 | |
29 std::vector<const Node*> children(node->GetChildren()); | |
30 for (size_t i = 0 ; i < children.size(); ++i) | |
31 GetDescendants(children[i], nodes); | |
32 } | |
33 | |
34 } // namespace | |
35 | 20 |
36 ViewManagerServiceImpl::ViewManagerServiceImpl( | 21 ViewManagerServiceImpl::ViewManagerServiceImpl( |
37 RootNodeManager* root_node_manager, | 22 RootNodeManager* root_node_manager, |
38 ConnectionSpecificId creator_id, | 23 ConnectionSpecificId creator_id, |
39 const std::string& creator_url, | 24 const std::string& creator_url, |
40 const std::string& url, | 25 const std::string& url, |
41 const NodeId& root_id) | 26 const NodeId& root_id) |
42 : root_node_manager_(root_node_manager), | 27 : root_node_manager_(root_node_manager), |
43 id_(root_node_manager_->GetAndAdvanceNextConnectionId()), | 28 id_(root_node_manager_->GetAndAdvanceNextConnectionId()), |
44 url_(url), | 29 url_(url), |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 } | 219 } |
235 | 220 |
236 bool ViewManagerServiceImpl::CanRemoveNodeFromParent(const Node* node) const { | 221 bool ViewManagerServiceImpl::CanRemoveNodeFromParent(const Node* node) const { |
237 if (!node) | 222 if (!node) |
238 return false; | 223 return false; |
239 | 224 |
240 const Node* parent = node->GetParent(); | 225 const Node* parent = node->GetParent(); |
241 if (!parent) | 226 if (!parent) |
242 return false; | 227 return false; |
243 | 228 |
244 // Always allow the remove if there are no roots. Otherwise the remove is | 229 if (roots_.empty()) |
245 // allowed if the parent is a descendant of the roots, or the node and its | 230 return true; // Root can do anything. |
246 // parent were created by this connection. We explicitly disallow removal of | 231 |
247 // the node from its parent if the parent isn't visible to this connection | 232 if (node->id().connection_id != id_) |
248 // (not in roots). | 233 return false; // Can only unparent nodes we created. |
249 return (roots_.empty() || | 234 |
250 (IsNodeDescendantOfRoots(parent) || | 235 if (roots_.count(NodeIdToTransportId(parent->id())) > 0) |
251 (node->id().connection_id == id_ && | 236 return true; // We can always remove from one of our roots. |
252 parent->id().connection_id == id_))); | 237 |
| 238 // Don't allow removing from nodes from other connections that aren't in our |
| 239 // root list. |
| 240 if (parent->id().connection_id != id_) |
| 241 return false; |
| 242 |
| 243 // Allow the remove as long as we haven't embedded another node at |parent|. |
| 244 ViewManagerServiceImpl* connection = |
| 245 root_node_manager_->GetConnectionWithRoot(parent->id()); |
| 246 return !connection || connection == this; |
253 } | 247 } |
254 | 248 |
255 bool ViewManagerServiceImpl::CanAddNode(const Node* parent, | 249 bool ViewManagerServiceImpl::CanAddNode(const Node* parent, |
256 const Node* child) const { | 250 const Node* child) const { |
257 if (!parent || !child) | 251 if (!parent || !child) |
258 return false; // Both nodes must be valid. | 252 return false; // Both nodes must be valid. |
259 | 253 |
260 if (child->GetParent() == parent || child->Contains(parent)) | 254 if (child->GetParent() == parent || child->Contains(parent)) |
261 return false; // Would result in an invalid hierarchy. | 255 return false; // Would result in an invalid hierarchy. |
262 | 256 |
263 if (roots_.empty()) | 257 if (roots_.empty()) |
264 return true; // No restriction if there are no roots. | 258 return true; // No restriction if there are no roots. |
265 | 259 |
| 260 if (child->id().connection_id != id_) |
| 261 return false; // Can't move children from different connections. |
| 262 |
266 if (!IsNodeDescendantOfRoots(parent) && parent->id().connection_id != id_) | 263 if (!IsNodeDescendantOfRoots(parent) && parent->id().connection_id != id_) |
267 return false; // |parent| is not visible to this connection. | 264 return false; // |parent| is not visible to this connection. |
268 | 265 |
269 // Allow the add if the child is already a descendant of the roots or was | 266 // Only allow the add if we haven't given one of the ancestors of |parent| to |
270 // created by this connection. | 267 // another node. That is, Embed() hasn't been invoked with one of our nodes. |
271 return (IsNodeDescendantOfRoots(child) || child->id().connection_id == id_); | 268 return !IsNodeEmbeddedInAnotherConnection(parent); |
272 } | 269 } |
273 | 270 |
274 bool ViewManagerServiceImpl::CanReorderNode(const Node* node, | 271 bool ViewManagerServiceImpl::CanReorderNode(const Node* node, |
275 const Node* relative_node, | 272 const Node* relative_node, |
276 OrderDirection direction) const { | 273 OrderDirection direction) const { |
277 if (!node || !relative_node) | 274 if (!node || !relative_node) |
278 return false; | 275 return false; |
279 | 276 |
280 if (node->id().connection_id != id_) | 277 if (node->id().connection_id != id_) |
281 return false; | 278 return false; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
317 const View* view = GetView(view_id); | 314 const View* view = GetView(view_id); |
318 return (view && view_id.connection_id == id_) || view_id == ViewId(); | 315 return (view && view_id.connection_id == id_) || view_id == ViewId(); |
319 } | 316 } |
320 | 317 |
321 bool ViewManagerServiceImpl::CanSetFocus(const Node* node) const { | 318 bool ViewManagerServiceImpl::CanSetFocus(const Node* node) const { |
322 // TODO(beng): security. | 319 // TODO(beng): security. |
323 return true; | 320 return true; |
324 } | 321 } |
325 | 322 |
326 bool ViewManagerServiceImpl::CanGetNodeTree(const Node* node) const { | 323 bool ViewManagerServiceImpl::CanGetNodeTree(const Node* node) const { |
327 return node && | 324 if (!node) |
328 (IsNodeDescendantOfRoots(node) || node->id().connection_id == id_); | 325 return false; |
| 326 |
| 327 if (roots_.empty()) |
| 328 return true; |
| 329 |
| 330 if (node->id().connection_id == id_) |
| 331 return true; |
| 332 |
| 333 return roots_.count(NodeIdToTransportId(node->id())) > 0; |
329 } | 334 } |
330 | 335 |
331 bool ViewManagerServiceImpl::CanEmbed(Id transport_node_id) const { | 336 bool ViewManagerServiceImpl::CanEmbed(Id transport_node_id) const { |
332 const Node* node = GetNode(NodeIdFromTransportId(transport_node_id)); | 337 const Node* node = GetNode(NodeIdFromTransportId(transport_node_id)); |
333 return node && node->id().connection_id == id_; | 338 return node && node->id().connection_id == id_; |
334 } | 339 } |
335 | 340 |
336 bool ViewManagerServiceImpl::CanSetNodeVisibility(const Node* node, | 341 bool ViewManagerServiceImpl::CanSetNodeVisibility(const Node* node, |
337 bool visibile) const { | 342 bool visibile) const { |
338 return node && | 343 return node && |
339 (node->id().connection_id == id_ || | 344 (node->id().connection_id == id_ || |
340 roots_.find(NodeIdToTransportId(node->id())) != roots_.end()) && | 345 roots_.find(NodeIdToTransportId(node->id())) != roots_.end()) && |
341 node->IsVisible() != visibile; | 346 node->IsVisible() != visibile; |
342 } | 347 } |
343 | 348 |
| 349 bool ViewManagerServiceImpl::CanDescendIntoNodeForNodeTree( |
| 350 const Node* node) const { |
| 351 if (roots_.empty()) |
| 352 return true; |
| 353 |
| 354 ViewManagerServiceImpl* connection = |
| 355 root_node_manager_->GetConnectionWithRoot(node->id()); |
| 356 return !connection || connection == this; |
| 357 } |
| 358 |
344 bool ViewManagerServiceImpl::DeleteNodeImpl(ViewManagerServiceImpl* source, | 359 bool ViewManagerServiceImpl::DeleteNodeImpl(ViewManagerServiceImpl* source, |
345 const NodeId& node_id) { | 360 const NodeId& node_id) { |
346 DCHECK_EQ(node_id.connection_id, id_); | 361 DCHECK_EQ(node_id.connection_id, id_); |
347 Node* node = GetNode(node_id); | 362 Node* node = GetNode(node_id); |
348 if (!node) | 363 if (!node) |
349 return false; | 364 return false; |
350 RootNodeManager::ScopedChange change(source, root_node_manager_, true); | 365 RootNodeManager::ScopedChange change(source, root_node_manager_, true); |
351 delete node; | 366 delete node; |
352 return true; | 367 return true; |
353 } | 368 } |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
397 if (local_nodes) | 412 if (local_nodes) |
398 local_nodes->push_back(GetNode(node->id())); | 413 local_nodes->push_back(GetNode(node->id())); |
399 return; | 414 return; |
400 } | 415 } |
401 known_nodes_.erase(NodeIdToTransportId(node->id())); | 416 known_nodes_.erase(NodeIdToTransportId(node->id())); |
402 std::vector<const Node*> children = node->GetChildren(); | 417 std::vector<const Node*> children = node->GetChildren(); |
403 for (size_t i = 0; i < children.size(); ++i) | 418 for (size_t i = 0; i < children.size(); ++i) |
404 RemoveFromKnown(children[i], local_nodes); | 419 RemoveFromKnown(children[i], local_nodes); |
405 } | 420 } |
406 | 421 |
| 422 bool ViewManagerServiceImpl::IsNodeEmbeddedInAnotherConnection( |
| 423 const Node* node) const { |
| 424 while (node) { |
| 425 const ViewManagerServiceImpl* connection = |
| 426 root_node_manager_->GetConnectionWithRoot(node->id()); |
| 427 if (connection) |
| 428 return connection != this; |
| 429 node = node->GetParent(); |
| 430 } |
| 431 return false; |
| 432 } |
| 433 |
407 void ViewManagerServiceImpl::AddRoot(const NodeId& node_id) { | 434 void ViewManagerServiceImpl::AddRoot(const NodeId& node_id) { |
408 const Id transport_node_id(NodeIdToTransportId(node_id)); | 435 const Id transport_node_id(NodeIdToTransportId(node_id)); |
409 CHECK(roots_.count(transport_node_id) == 0); | 436 CHECK(roots_.count(transport_node_id) == 0); |
410 | 437 |
411 std::vector<const Node*> to_send; | 438 std::vector<const Node*> to_send; |
412 CHECK_EQ(creator_id_, node_id.connection_id); | 439 CHECK_EQ(creator_id_, node_id.connection_id); |
413 roots_.insert(transport_node_id); | 440 roots_.insert(transport_node_id); |
414 Node* node = GetNode(node_id); | 441 Node* node = GetNode(node_id); |
415 CHECK(node); | 442 CHECK(node); |
416 if (known_nodes_.count(transport_node_id) == 0) { | 443 if (known_nodes_.count(transport_node_id) == 0) { |
(...skipping 24 matching lines...) Expand all Loading... |
441 root_node_manager_->OnConnectionMessagedClient(id_); | 468 root_node_manager_->OnConnectionMessagedClient(id_); |
442 | 469 |
443 // This connection no longer knows about the node. Unparent any nodes that | 470 // This connection no longer knows about the node. Unparent any nodes that |
444 // were parented to nodes in the root. | 471 // were parented to nodes in the root. |
445 std::vector<Node*> local_nodes; | 472 std::vector<Node*> local_nodes; |
446 RemoveFromKnown(GetNode(node_id), &local_nodes); | 473 RemoveFromKnown(GetNode(node_id), &local_nodes); |
447 for (size_t i = 0; i < local_nodes.size(); ++i) | 474 for (size_t i = 0; i < local_nodes.size(); ++i) |
448 local_nodes[i]->GetParent()->Remove(local_nodes[i]); | 475 local_nodes[i]->GetParent()->Remove(local_nodes[i]); |
449 } | 476 } |
450 | 477 |
| 478 void ViewManagerServiceImpl::RemoveChildrenAsPartOfEmbed( |
| 479 const NodeId& node_id) { |
| 480 // Let the root do what it wants. |
| 481 if (roots_.empty()) |
| 482 return; |
| 483 |
| 484 Node* node = GetNode(node_id); |
| 485 CHECK(node); |
| 486 CHECK(node->id().connection_id == node_id.connection_id); |
| 487 std::vector<Node*> children = node->GetChildren(); |
| 488 for (size_t i = 0; i < children.size(); ++i) |
| 489 node->Remove(children[i]); |
| 490 } |
| 491 |
451 bool ViewManagerServiceImpl::IsNodeDescendantOfRoots(const Node* node) const { | 492 bool ViewManagerServiceImpl::IsNodeDescendantOfRoots(const Node* node) const { |
452 if (roots_.empty()) | 493 if (roots_.empty()) |
453 return true; | 494 return true; |
454 if (!node) | 495 if (!node) |
455 return false; | 496 return false; |
456 const Id invalid_node_id = | 497 const Id invalid_node_id = NodeIdToTransportId(InvalidNodeId()); |
457 NodeIdToTransportId(InvalidNodeId()); | |
458 for (NodeIdSet::const_iterator i = roots_.begin(); i != roots_.end(); ++i) { | 498 for (NodeIdSet::const_iterator i = roots_.begin(); i != roots_.end(); ++i) { |
459 if (*i == invalid_node_id) | 499 if (*i == invalid_node_id) |
460 continue; | 500 continue; |
461 const Node* root = GetNode(NodeIdFromTransportId(*i)); | 501 const Node* root = GetNode(NodeIdFromTransportId(*i)); |
462 DCHECK(root); | 502 DCHECK(root); |
463 if (root->Contains(node)) | 503 if (root->Contains(node)) |
464 return true; | 504 return true; |
465 } | 505 } |
466 return false; | 506 return false; |
467 } | 507 } |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
526 inode->parent_id = NodeIdToTransportId(parent ? parent->id() : NodeId()); | 566 inode->parent_id = NodeIdToTransportId(parent ? parent->id() : NodeId()); |
527 inode->node_id = NodeIdToTransportId(node->id()); | 567 inode->node_id = NodeIdToTransportId(node->id()); |
528 inode->view_id = | 568 inode->view_id = |
529 ViewIdToTransportId(node->view() ? node->view()->id() : ViewId()); | 569 ViewIdToTransportId(node->view() ? node->view()->id() : ViewId()); |
530 inode->bounds = Rect::From(node->bounds()); | 570 inode->bounds = Rect::From(node->bounds()); |
531 array[i] = inode.Pass(); | 571 array[i] = inode.Pass(); |
532 } | 572 } |
533 return array.Pass(); | 573 return array.Pass(); |
534 } | 574 } |
535 | 575 |
| 576 void ViewManagerServiceImpl::GetNodeTreeImpl( |
| 577 const Node* node, |
| 578 std::vector<const Node*>* nodes) const { |
| 579 DCHECK(node); |
| 580 |
| 581 if (!CanGetNodeTree(node)) |
| 582 return; |
| 583 |
| 584 nodes->push_back(node); |
| 585 |
| 586 if (!CanDescendIntoNodeForNodeTree(node)) |
| 587 return; |
| 588 |
| 589 std::vector<const Node*> children(node->GetChildren()); |
| 590 for (size_t i = 0 ; i < children.size(); ++i) |
| 591 GetNodeTreeImpl(children[i], nodes); |
| 592 } |
| 593 |
536 void ViewManagerServiceImpl::CreateNode( | 594 void ViewManagerServiceImpl::CreateNode( |
537 Id transport_node_id, | 595 Id transport_node_id, |
538 const Callback<void(ErrorCode)>& callback) { | 596 const Callback<void(ErrorCode)>& callback) { |
539 const NodeId node_id(NodeIdFromTransportId(transport_node_id)); | 597 const NodeId node_id(NodeIdFromTransportId(transport_node_id)); |
540 ErrorCode error_code = ERROR_CODE_NONE; | 598 ErrorCode error_code = ERROR_CODE_NONE; |
541 if (node_id.connection_id != id_) { | 599 if (node_id.connection_id != id_) { |
542 error_code = ERROR_CODE_ILLEGAL_ARGUMENT; | 600 error_code = ERROR_CODE_ILLEGAL_ARGUMENT; |
543 } else if (node_map_.find(node_id.node_id) != node_map_.end()) { | 601 } else if (node_map_.find(node_id.node_id) != node_map_.end()) { |
544 error_code = ERROR_CODE_VALUE_IN_USE; | 602 error_code = ERROR_CODE_VALUE_IN_USE; |
545 } else { | 603 } else { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
605 } | 663 } |
606 callback.Run(success); | 664 callback.Run(success); |
607 } | 665 } |
608 | 666 |
609 void ViewManagerServiceImpl::GetNodeTree( | 667 void ViewManagerServiceImpl::GetNodeTree( |
610 Id node_id, | 668 Id node_id, |
611 const Callback<void(Array<NodeDataPtr>)>& callback) { | 669 const Callback<void(Array<NodeDataPtr>)>& callback) { |
612 Node* node = GetNode(NodeIdFromTransportId(node_id)); | 670 Node* node = GetNode(NodeIdFromTransportId(node_id)); |
613 std::vector<const Node*> nodes; | 671 std::vector<const Node*> nodes; |
614 if (CanGetNodeTree(node)) { | 672 if (CanGetNodeTree(node)) { |
615 GetDescendants(node, &nodes); | 673 GetNodeTreeImpl(node, &nodes); |
| 674 #if !defined(NDEBUG) |
616 for (size_t i = 0; i < nodes.size(); ++i) | 675 for (size_t i = 0; i < nodes.size(); ++i) |
617 known_nodes_.insert(NodeIdToTransportId(nodes[i]->id())); | 676 DCHECK_GT(known_nodes_.count(NodeIdToTransportId(nodes[i]->id())), 0u); |
| 677 #endif |
618 } | 678 } |
619 callback.Run(NodesToNodeDatas(nodes)); | 679 callback.Run(NodesToNodeDatas(nodes)); |
620 } | 680 } |
621 | 681 |
622 void ViewManagerServiceImpl::CreateView( | 682 void ViewManagerServiceImpl::CreateView( |
623 Id transport_view_id, | 683 Id transport_view_id, |
624 const Callback<void(bool)>& callback) { | 684 const Callback<void(bool)>& callback) { |
625 const ViewId view_id(ViewIdFromTransportId(transport_view_id)); | 685 const ViewId view_id(ViewIdFromTransportId(transport_view_id)); |
626 if (view_id.connection_id != id_ || view_map_.count(view_id.view_id)) { | 686 if (view_id.connection_id != id_ || view_map_.count(view_id.view_id)) { |
627 callback.Run(false); | 687 callback.Run(false); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
736 // Only allow a node to be the root for one connection. | 796 // Only allow a node to be the root for one connection. |
737 const NodeId node_id(NodeIdFromTransportId(transport_node_id)); | 797 const NodeId node_id(NodeIdFromTransportId(transport_node_id)); |
738 ViewManagerServiceImpl* connection_by_url = | 798 ViewManagerServiceImpl* connection_by_url = |
739 root_node_manager_->GetConnectionByCreator(id_, url.To<std::string>()); | 799 root_node_manager_->GetConnectionByCreator(id_, url.To<std::string>()); |
740 ViewManagerServiceImpl* connection_with_node_as_root = | 800 ViewManagerServiceImpl* connection_with_node_as_root = |
741 root_node_manager_->GetConnectionWithRoot(node_id); | 801 root_node_manager_->GetConnectionWithRoot(node_id); |
742 if ((connection_by_url != connection_with_node_as_root || | 802 if ((connection_by_url != connection_with_node_as_root || |
743 (!connection_by_url && !connection_with_node_as_root)) && | 803 (!connection_by_url && !connection_with_node_as_root)) && |
744 (!connection_by_url || !connection_by_url->HasRoot(node_id))) { | 804 (!connection_by_url || !connection_by_url->HasRoot(node_id))) { |
745 RootNodeManager::ScopedChange change(this, root_node_manager_, true); | 805 RootNodeManager::ScopedChange change(this, root_node_manager_, true); |
| 806 RemoveChildrenAsPartOfEmbed(node_id); |
746 // Never message the originating connection. | 807 // Never message the originating connection. |
747 root_node_manager_->OnConnectionMessagedClient(id_); | 808 root_node_manager_->OnConnectionMessagedClient(id_); |
748 if (connection_with_node_as_root) | 809 if (connection_with_node_as_root) |
749 connection_with_node_as_root->RemoveRoot(node_id); | 810 connection_with_node_as_root->RemoveRoot(node_id); |
750 if (connection_by_url) | 811 if (connection_by_url) |
751 connection_by_url->AddRoot(node_id); | 812 connection_by_url->AddRoot(node_id); |
752 else | 813 else |
753 root_node_manager_->Embed(id_, url, transport_node_id); | 814 root_node_manager_->Embed(id_, url, transport_node_id); |
754 } else { | 815 } else { |
755 success = false; | 816 success = false; |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
789 | 850 |
790 client()->OnViewManagerConnectionEstablished( | 851 client()->OnViewManagerConnectionEstablished( |
791 id_, | 852 id_, |
792 creator_url_, | 853 creator_url_, |
793 NodesToNodeDatas(to_send)); | 854 NodesToNodeDatas(to_send)); |
794 } | 855 } |
795 | 856 |
796 } // namespace service | 857 } // namespace service |
797 } // namespace view_manager | 858 } // namespace view_manager |
798 } // namespace mojo | 859 } // namespace mojo |
OLD | NEW |