| 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 f4384b86cb8bcfe1b8e0908c1dff13583fb56673..6caf9a1f253241c97e8dbeaf36496d5f9bbbc837 100644
|
| --- a/mojo/services/view_manager/view_manager_connection.cc
|
| +++ b/mojo/services/view_manager/view_manager_connection.cc
|
| @@ -8,7 +8,6 @@
|
| #include "mojo/public/cpp/bindings/allocation_scope.h"
|
| #include "mojo/services/view_manager/node.h"
|
| #include "mojo/services/view_manager/root_node_manager.h"
|
| -#include "mojo/services/view_manager/type_converters.h"
|
| #include "mojo/services/view_manager/view.h"
|
| #include "third_party/skia/include/core/SkBitmap.h"
|
| #include "ui/aura/window.h"
|
| @@ -67,7 +66,7 @@ void ViewManagerConnection::OnConnectionEstablished() {
|
| client()->OnConnectionEstablished(
|
| id_,
|
| root_node_manager_->next_server_change_id(),
|
| - Array<INode>::From(to_send));
|
| + NodesToINodes(to_send));
|
| }
|
|
|
| const Node* ViewManagerConnection::GetNode(const NodeId& id) const {
|
| @@ -92,10 +91,24 @@ void ViewManagerConnection::ProcessNodeHierarchyChanged(
|
| const Node* old_parent,
|
| TransportChangeId server_change_id,
|
| bool originated_change) {
|
| + if (known_nodes_.count(NodeIdToTransportId(node->id())) > 0) {
|
| + if (originated_change)
|
| + return;
|
| + if (node->id().connection_id != id_ && !IsNodeDescendantOfRoots(node)) {
|
| + // Node was a descendant of roots and is no longer, treat it as though the
|
| + // node was deleted.
|
| + RemoveFromKnown(node);
|
| + client()->OnNodeDeleted(NodeIdToTransportId(node->id()),
|
| + server_change_id);
|
| + return;
|
| + }
|
| + }
|
| +
|
| if (originated_change || root_node_manager_->is_processing_delete_node())
|
| return;
|
| std::vector<const Node*> to_send;
|
| - if (!ShouldNotifyOnHierarchyChange(node, new_parent, old_parent, &to_send)) {
|
| + if (!ShouldNotifyOnHierarchyChange(node, &new_parent, &old_parent,
|
| + &to_send)) {
|
| if (root_node_manager_->IsProcessingChange()) {
|
| client()->OnServerChangeIdAdvanced(
|
| root_node_manager_->next_server_change_id() + 1);
|
| @@ -105,11 +118,15 @@ void ViewManagerConnection::ProcessNodeHierarchyChanged(
|
| AllocationScope allocation_scope;
|
| const NodeId new_parent_id(new_parent ? new_parent->id() : NodeId());
|
| const NodeId old_parent_id(old_parent ? old_parent->id() : NodeId());
|
| + DCHECK((node->id().connection_id == id_) ||
|
| + (roots_.count(NodeIdToTransportId(node->id())) > 0) ||
|
| + (new_parent && IsNodeDescendantOfRoots(new_parent)) ||
|
| + (old_parent && IsNodeDescendantOfRoots(old_parent)));
|
| client()->OnNodeHierarchyChanged(NodeIdToTransportId(node->id()),
|
| NodeIdToTransportId(new_parent_id),
|
| NodeIdToTransportId(old_parent_id),
|
| server_change_id,
|
| - Array<INode>::From(to_send));
|
| + NodesToINodes(to_send));
|
| }
|
|
|
| void ViewManagerConnection::ProcessNodeViewReplaced(
|
| @@ -117,16 +134,14 @@ void ViewManagerConnection::ProcessNodeViewReplaced(
|
| const View* new_view,
|
| const View* old_view,
|
| bool originated_change) {
|
| - if (originated_change)
|
| + if (originated_change || !known_nodes_.count(NodeIdToTransportId(node->id())))
|
| return;
|
| - if (known_nodes_.count(NodeIdToTransportId(node->id())) > 0) {
|
| - const TransportViewId new_view_id = new_view ?
|
| - ViewIdToTransportId(new_view->id()) : 0;
|
| - const TransportViewId old_view_id = old_view ?
|
| - ViewIdToTransportId(old_view->id()) : 0;
|
| - client()->OnNodeViewReplaced(NodeIdToTransportId(node->id()),
|
| - new_view_id, old_view_id);
|
| - }
|
| + const TransportViewId new_view_id = new_view ?
|
| + ViewIdToTransportId(new_view->id()) : 0;
|
| + const TransportViewId old_view_id = old_view ?
|
| + ViewIdToTransportId(old_view->id()) : 0;
|
| + client()->OnNodeViewReplaced(NodeIdToTransportId(node->id()),
|
| + new_view_id, old_view_id);
|
| }
|
|
|
| void ViewManagerConnection::ProcessNodeDeleted(
|
| @@ -231,29 +246,66 @@ void ViewManagerConnection::GetUnknownNodesFrom(
|
| GetUnknownNodesFrom(children[i], nodes);
|
| }
|
|
|
| +void ViewManagerConnection::RemoveFromKnown(const Node* node) {
|
| + if (node->id().connection_id == id_)
|
| + return;
|
| + known_nodes_.erase(NodeIdToTransportId(node->id()));
|
| + std::vector<const Node*> children = node->GetChildren();
|
| + for (size_t i = 0; i < children.size(); ++i)
|
| + RemoveFromKnown(children[i]);
|
| +}
|
| +
|
| +bool ViewManagerConnection::IsNodeDescendantOfRoots(const Node* node) const {
|
| + if (roots_.empty())
|
| + return true;
|
| + if (!node)
|
| + return false;
|
| + for (NodeIdSet::const_iterator i = roots_.begin(); i != roots_.end(); ++i) {
|
| + const Node* root = GetNode(NodeIdFromTransportId(*i));
|
| + DCHECK(root);
|
| + if (root->Contains(node))
|
| + return true;
|
| + }
|
| + return false;
|
| +}
|
| +
|
| bool ViewManagerConnection::ShouldNotifyOnHierarchyChange(
|
| const Node* node,
|
| - const Node* new_parent,
|
| - const Node* old_parent,
|
| + const Node** new_parent,
|
| + const Node** old_parent,
|
| std::vector<const Node*>* to_send) {
|
| - if (new_parent) {
|
| + // If the node is not in |roots_| or was never known to this connection then
|
| + // don't notify the client about it.
|
| + if (node->id().connection_id != id_ &&
|
| + known_nodes_.count(NodeIdToTransportId(node->id())) == 0 &&
|
| + !IsNodeDescendantOfRoots(node)) {
|
| + return false;
|
| + }
|
| + if (!IsNodeDescendantOfRoots(*new_parent))
|
| + *new_parent = NULL;
|
| + if (!IsNodeDescendantOfRoots(*old_parent))
|
| + *old_parent = NULL;
|
| +
|
| + if (*new_parent) {
|
| // On getting a new parent we may need to communicate new nodes to the
|
| // client. We do that in the following cases:
|
| - // . New parent is a descendant of the root. In this case the client already
|
| - // knows all ancestors, so we only have to communicate descendants of node
|
| - // the client doesn't know about.
|
| + // . New parent is a descendant of the roots. In this case the client
|
| + // already knows all ancestors, so we only have to communicate descendants
|
| + // of node the client doesn't know about.
|
| // . If the client knew about the parent, we have to do the same.
|
| // . If the client knows about the node and is added to a tree the client
|
| // doesn't know about we have to communicate from the root down (the
|
| // client is learning about a new root).
|
| - if (root_node_manager_->root()->Contains(new_parent) ||
|
| - known_nodes_.count(NodeIdToTransportId(new_parent->id()))) {
|
| + if (root_node_manager_->root()->Contains(*new_parent) ||
|
| + known_nodes_.count(NodeIdToTransportId((*new_parent)->id()))) {
|
| GetUnknownNodesFrom(node, to_send);
|
| return true;
|
| }
|
| // If parent wasn't known we have to communicate from the root down.
|
| if (known_nodes_.count(NodeIdToTransportId(node->id()))) {
|
| - GetUnknownNodesFrom(new_parent->GetRoot(), to_send);
|
| + // No need to check against |roots_| as client should always know it's
|
| + // |roots_|.
|
| + GetUnknownNodesFrom((*new_parent)->GetRoot(), to_send);
|
| return true;
|
| }
|
| }
|
| @@ -262,6 +314,62 @@ bool ViewManagerConnection::ShouldNotifyOnHierarchyChange(
|
| return known_nodes_.count(NodeIdToTransportId(node->id())) > 0;
|
| }
|
|
|
| +bool ViewManagerConnection::ProcessSetRoots(
|
| + TransportConnectionId source_connection_id,
|
| + const Array<TransportNodeId>& transport_node_ids) {
|
| + // TODO(sky): these DCHECKs can go away once this is part of a real API. Also
|
| + // make sure that when roots are set nodes are communicate to client. Code in
|
| + // ProcessNodeHierarchyChanged() is depending on this.
|
| + DCHECK(node_map_.empty());
|
| + DCHECK(view_map_.empty());
|
| +
|
| + NodeIdSet roots;
|
| + for (size_t i = 0; i < transport_node_ids.size(); ++i) {
|
| + const Node* node = GetNode(NodeIdFromTransportId(transport_node_ids[i]));
|
| + // Only allow setting roots that are owned by the source connection.
|
| + if (!node || node->id().connection_id != source_connection_id)
|
| + return false;
|
| + roots.insert(transport_node_ids[i]);
|
| + }
|
| + roots_.swap(roots);
|
| +
|
| + // TODO(sky): remove |known_nodes_.clear()| temporary while this is done here
|
| + // instead of at creation time.
|
| + known_nodes_.clear();
|
| + std::vector<const Node*> to_send;
|
| + for (NodeIdSet::const_iterator i = roots_.begin(); i != roots_.end(); ++i)
|
| + GetUnknownNodesFrom(GetNode(NodeIdFromTransportId(*i)), &to_send);
|
| + AllocationScope allocation_scope;
|
| + client()->OnConnectionEstablished(
|
| + id_,
|
| + root_node_manager_->next_server_change_id(),
|
| + NodesToINodes(to_send));
|
| +
|
| + return true;
|
| +}
|
| +
|
| +Array<INode> ViewManagerConnection::NodesToINodes(
|
| + const std::vector<const Node*>& nodes) {
|
| + Array<INode>::Builder array_builder(nodes.size());
|
| + for (size_t i = 0; i < nodes.size(); ++i) {
|
| + INode::Builder node_builder;
|
| + const Node* node = nodes[i];
|
| + DCHECK(known_nodes_.count(NodeIdToTransportId(node->id())) > 0);
|
| + const Node* parent = node->GetParent();
|
| + // If the parent isn't known, it means the parent is not visible to us (not
|
| + // in roots), and should not be sent over.
|
| + if (parent && known_nodes_.count(NodeIdToTransportId(parent->id())) == 0)
|
| + parent = NULL;
|
| + node_builder.set_parent_id(NodeIdToTransportId(
|
| + parent ? parent->id() : NodeId()));
|
| + node_builder.set_node_id(NodeIdToTransportId(node->id()));
|
| + node_builder.set_view_id(ViewIdToTransportId(
|
| + node->view() ? node->view()->id() : ViewId()));
|
| + array_builder[i] = node_builder.Finish();
|
| + }
|
| + return array_builder.Finish();
|
| +}
|
| +
|
| void ViewManagerConnection::CreateNode(
|
| TransportNodeId transport_node_id,
|
| const Callback<void(bool)>& callback) {
|
| @@ -338,7 +446,7 @@ void ViewManagerConnection::GetNodeTree(
|
| GetDescendants(node, &nodes);
|
| for (size_t i = 0; i < nodes.size(); ++i)
|
| known_nodes_.insert(NodeIdToTransportId(nodes[i]->id()));
|
| - callback.Run(Array<INode>::From(nodes));
|
| + callback.Run(NodesToINodes(nodes));
|
| }
|
|
|
| void ViewManagerConnection::CreateView(
|
| @@ -393,6 +501,16 @@ void ViewManagerConnection::SetViewContents(
|
| UnmapBuffer(handle_data);
|
| }
|
|
|
| +void ViewManagerConnection::SetRoots(
|
| + TransportConnectionId connection_id,
|
| + const Array<TransportNodeId>& transport_node_ids,
|
| + const Callback<void(bool)>& callback) {
|
| + ViewManagerConnection* connection =
|
| + root_node_manager_->GetConnection(connection_id);
|
| + callback.Run(connection &&
|
| + connection->ProcessSetRoots(id_, transport_node_ids));
|
| +}
|
| +
|
| void ViewManagerConnection::OnNodeHierarchyChanged(const Node* node,
|
| const Node* new_parent,
|
| const Node* old_parent) {
|
|
|