| Index: mojo/services/view_manager/view_manager_connection.cc
|
| diff --git a/mojo/services/view_manager/view_manager_connection.cc b/mojo/services/view_manager/view_manager_connection.cc
|
| index 6caf9a1f253241c97e8dbeaf36496d5f9bbbc837..bb9c4de559a8af5cae48339f55076c12ba11f481 100644
|
| --- a/mojo/services/view_manager/view_manager_connection.cc
|
| +++ b/mojo/services/view_manager/view_manager_connection.cc
|
| @@ -47,12 +47,26 @@ ViewManagerConnection::~ViewManagerConnection() {
|
| // We're about to destroy all our nodes. Detach any views from them.
|
| for (NodeMap::iterator i = node_map_.begin(); i != node_map_.end(); ++i) {
|
| if (i->second->view()) {
|
| - bool result = SetViewImpl(i->second->id(), ViewId());
|
| + bool result = SetViewImpl(i->second, ViewId());
|
| DCHECK(result);
|
| }
|
| }
|
|
|
| - STLDeleteContainerPairSecondPointers(node_map_.begin(), node_map_.end());
|
| + if (!node_map_.empty()) {
|
| + RootNodeManager::ScopedChange change(
|
| + this, root_node_manager_,
|
| + RootNodeManager::CHANGE_TYPE_ADVANCE_SERVER_CHANGE_ID, true);
|
| + while (!node_map_.empty()) {
|
| + Node* node = node_map_.begin()->second;
|
| + Node* parent = node->GetParent();
|
| + const NodeId node_id(node->id());
|
| + if (parent)
|
| + parent->Remove(node);
|
| + root_node_manager_->ProcessNodeDeleted(node_id);
|
| + node_map_.erase(NodeIdToTransportId(node_id));
|
| + }
|
| + }
|
| +
|
| root_node_manager_->RemoveConnection(this);
|
| }
|
|
|
| @@ -77,7 +91,7 @@ const Node* ViewManagerConnection::GetNode(const NodeId& id) const {
|
| return root_node_manager_->GetNode(id);
|
| }
|
|
|
| -View* ViewManagerConnection::GetView(const ViewId& id) {
|
| +const View* ViewManagerConnection::GetView(const ViewId& id) const {
|
| if (id_ == id.connection_id) {
|
| ViewMap::const_iterator i = view_map_.find(id.view_id);
|
| return i == view_map_.end() ? NULL : i->second;
|
| @@ -149,6 +163,10 @@ void ViewManagerConnection::ProcessNodeDeleted(
|
| TransportChangeId server_change_id,
|
| bool originated_change) {
|
| const bool in_known = known_nodes_.erase(NodeIdToTransportId(node)) > 0;
|
| + const bool in_roots = roots_.erase(NodeIdToTransportId(node)) > 0;
|
| +
|
| + if (in_roots && roots_.empty())
|
| + roots_.insert(NodeIdToTransportId(InvalidNodeId()));
|
|
|
| if (originated_change)
|
| return;
|
| @@ -168,6 +186,44 @@ void ViewManagerConnection::ProcessViewDeleted(const ViewId& view,
|
| client()->OnViewDeleted(ViewIdToTransportId(view));
|
| }
|
|
|
| +bool ViewManagerConnection::CanRemoveNodeFromParent(const Node* node) const {
|
| + if (!node)
|
| + return false;
|
| +
|
| + const Node* parent = node->GetParent();
|
| + if (!parent)
|
| + return false;
|
| +
|
| + // Always allow the remove if there are no roots. Otherwise the remove is
|
| + // allowed if the parent is a descendant of the roots, or the node and its
|
| + // parent were created by this connection. We explicitly disallow removal of
|
| + // the node from its parent if the parent isn't visible to this connection
|
| + // (not in roots).
|
| + return (roots_.empty() ||
|
| + (IsNodeDescendantOfRoots(parent) ||
|
| + (node->id().connection_id == id_ &&
|
| + parent->id().connection_id == id_)));
|
| +}
|
| +
|
| +bool ViewManagerConnection::CanAddNode(const Node* parent,
|
| + const Node* child) const {
|
| + if (!parent || !child)
|
| + return false; // Both nodes must be valid.
|
| +
|
| + if (child->GetParent() == parent || child->Contains(parent))
|
| + return false; // Would result in an invalid hierarchy.
|
| +
|
| + if (roots_.empty())
|
| + return true; // No restriction if there are no roots.
|
| +
|
| + if (!IsNodeDescendantOfRoots(parent) && parent->id().connection_id != id_)
|
| + return false; // |parent| is not visible to this connection.
|
| +
|
| + // Allow the add if the child is already a descendant of the roots or was
|
| + // created by this connection.
|
| + return (IsNodeDescendantOfRoots(child) || child->id().connection_id == id_);
|
| +}
|
| +
|
| bool ViewManagerConnection::CanDeleteNode(const NodeId& node_id) const {
|
| return node_id.connection_id == id_;
|
| }
|
| @@ -176,6 +232,20 @@ bool ViewManagerConnection::CanDeleteView(const ViewId& view_id) const {
|
| return view_id.connection_id == id_;
|
| }
|
|
|
| +bool ViewManagerConnection::CanSetView(const Node* node,
|
| + const ViewId& view_id) const {
|
| + if (!node || !IsNodeDescendantOfRoots(node))
|
| + return false;
|
| +
|
| + const View* view = GetView(view_id);
|
| + return (view && view_id.connection_id == id_) || view_id == ViewId();
|
| +}
|
| +
|
| +bool ViewManagerConnection::CanGetNodeTree(const Node* node) const {
|
| + return node &&
|
| + (IsNodeDescendantOfRoots(node) || node->id().connection_id == id_);
|
| +}
|
| +
|
| bool ViewManagerConnection::DeleteNodeImpl(ViewManagerConnection* source,
|
| const NodeId& node_id) {
|
| DCHECK_EQ(node_id.connection_id, id_);
|
| @@ -218,14 +288,9 @@ bool ViewManagerConnection::DeleteViewImpl(ViewManagerConnection* source,
|
| return true;
|
| }
|
|
|
| -bool ViewManagerConnection::SetViewImpl(const NodeId& node_id,
|
| - const ViewId& view_id) {
|
| - Node* node = GetNode(node_id);
|
| - if (!node)
|
| - return false;
|
| +bool ViewManagerConnection::SetViewImpl(Node* node, const ViewId& view_id) {
|
| + DCHECK(node); // CanSetView() should have verified node exists.
|
| View* view = GetView(view_id);
|
| - if (!view && view_id != ViewId())
|
| - return false;
|
| RootNodeManager::ScopedChange change(
|
| this, root_node_manager_,
|
| RootNodeManager::CHANGE_TYPE_DONT_ADVANCE_SERVER_CHANGE_ID, false);
|
| @@ -260,7 +325,11 @@ bool ViewManagerConnection::IsNodeDescendantOfRoots(const Node* node) const {
|
| return true;
|
| if (!node)
|
| return false;
|
| + const TransportNodeId invalid_node_id =
|
| + NodeIdToTransportId(InvalidNodeId());
|
| for (NodeIdSet::const_iterator i = roots_.begin(); i != roots_.end(); ++i) {
|
| + if (*i == invalid_node_id)
|
| + continue;
|
| const Node* root = GetNode(NodeIdFromTransportId(*i));
|
| DCHECK(root);
|
| if (root->Contains(node))
|
| @@ -407,8 +476,7 @@ void ViewManagerConnection::AddNode(
|
| if (server_change_id == root_node_manager_->next_server_change_id()) {
|
| Node* parent = GetNode(NodeIdFromTransportId(parent_id));
|
| Node* child = GetNode(NodeIdFromTransportId(child_id));
|
| - if (parent && child && child->GetParent() != parent &&
|
| - !child->window()->Contains(parent->window())) {
|
| + if (CanAddNode(parent, child)) {
|
| success = true;
|
| RootNodeManager::ScopedChange change(
|
| this, root_node_manager_,
|
| @@ -426,7 +494,7 @@ void ViewManagerConnection::RemoveNodeFromParent(
|
| bool success = false;
|
| if (server_change_id == root_node_manager_->next_server_change_id()) {
|
| Node* node = GetNode(NodeIdFromTransportId(node_id));
|
| - if (node && node->GetParent()) {
|
| + if (CanRemoveNodeFromParent(node)) {
|
| success = true;
|
| RootNodeManager::ScopedChange change(
|
| this, root_node_manager_,
|
| @@ -443,9 +511,11 @@ void ViewManagerConnection::GetNodeTree(
|
| AllocationScope allocation_scope;
|
| Node* node = GetNode(NodeIdFromTransportId(node_id));
|
| std::vector<const Node*> nodes;
|
| - GetDescendants(node, &nodes);
|
| - for (size_t i = 0; i < nodes.size(); ++i)
|
| - known_nodes_.insert(NodeIdToTransportId(nodes[i]->id()));
|
| + if (CanGetNodeTree(node)) {
|
| + GetDescendants(node, &nodes);
|
| + for (size_t i = 0; i < nodes.size(); ++i)
|
| + known_nodes_.insert(NodeIdToTransportId(nodes[i]->id()));
|
| + }
|
| callback.Run(NodesToINodes(nodes));
|
| }
|
|
|
| @@ -478,8 +548,9 @@ void ViewManagerConnection::SetView(
|
| TransportNodeId transport_node_id,
|
| TransportViewId transport_view_id,
|
| const Callback<void(bool)>& callback) {
|
| - const NodeId node_id(NodeIdFromTransportId(transport_node_id));
|
| - callback.Run(SetViewImpl(node_id, ViewIdFromTransportId(transport_view_id)));
|
| + Node* node = GetNode(NodeIdFromTransportId(transport_node_id));
|
| + const ViewId view_id(ViewIdFromTransportId(transport_view_id));
|
| + callback.Run(CanSetView(node, view_id) && SetViewImpl(node, view_id));
|
| }
|
|
|
| void ViewManagerConnection::SetViewContents(
|
|
|