• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #include "mojo/services/view_manager/view_manager_service_impl.h"
6 
7 #include "base/bind.h"
8 #include "base/stl_util.h"
9 #include "mojo/services/public/cpp/geometry/geometry_type_converters.h"
10 #include "mojo/services/public/cpp/input_events/input_events_type_converters.h"
11 #include "mojo/services/view_manager/node.h"
12 #include "mojo/services/view_manager/root_node_manager.h"
13 #include "mojo/services/view_manager/view.h"
14 #include "third_party/skia/include/core/SkBitmap.h"
15 #include "ui/aura/window.h"
16 #include "ui/gfx/codec/png_codec.h"
17 
18 namespace mojo {
19 namespace view_manager {
20 namespace service {
21 namespace {
22 
23 // Places |node| in |nodes| and recurses through the children.
GetDescendants(const Node * node,std::vector<const Node * > * nodes)24 void GetDescendants(const Node* node, std::vector<const Node*>* nodes) {
25   if (!node)
26     return;
27 
28   nodes->push_back(node);
29 
30   std::vector<const Node*> children(node->GetChildren());
31   for (size_t i = 0 ; i < children.size(); ++i)
32     GetDescendants(children[i], nodes);
33 }
34 
35 }  // namespace
36 
ViewManagerServiceImpl(RootNodeManager * root_node_manager,ConnectionSpecificId creator_id,const std::string & creator_url,const std::string & url)37 ViewManagerServiceImpl::ViewManagerServiceImpl(
38     RootNodeManager* root_node_manager,
39     ConnectionSpecificId creator_id,
40     const std::string& creator_url,
41     const std::string& url)
42     : root_node_manager_(root_node_manager),
43       id_(root_node_manager_->GetAndAdvanceNextConnectionId()),
44       url_(url),
45       creator_id_(creator_id),
46       creator_url_(creator_url),
47       delete_on_connection_error_(false) {
48 }
49 
~ViewManagerServiceImpl()50 ViewManagerServiceImpl::~ViewManagerServiceImpl() {
51   // Delete any views we own.
52   while (!view_map_.empty()) {
53     bool result = DeleteViewImpl(this, view_map_.begin()->second->id());
54     DCHECK(result);
55   }
56 
57   // We're about to destroy all our nodes. Detach any views from them.
58   for (NodeMap::iterator i = node_map_.begin(); i != node_map_.end(); ++i) {
59     if (i->second->view()) {
60       bool result = SetViewImpl(i->second, ViewId());
61       DCHECK(result);
62     }
63   }
64 
65   if (!node_map_.empty()) {
66     RootNodeManager::ScopedChange change(
67         this, root_node_manager_,
68         RootNodeManager::CHANGE_TYPE_ADVANCE_SERVER_CHANGE_ID, true);
69     while (!node_map_.empty()) {
70       scoped_ptr<Node> node(node_map_.begin()->second);
71       Node* parent = node->GetParent();
72       const NodeId node_id(node->id());
73       if (parent)
74         parent->Remove(node.get());
75       root_node_manager_->ProcessNodeDeleted(node_id);
76       node_map_.erase(NodeIdToTransportId(node_id));
77     }
78   }
79 
80   root_node_manager_->RemoveConnection(this);
81 }
82 
GetNode(const NodeId & id) const83 const Node* ViewManagerServiceImpl::GetNode(const NodeId& id) const {
84   if (id_ == id.connection_id) {
85     NodeMap::const_iterator i = node_map_.find(id.node_id);
86     return i == node_map_.end() ? NULL : i->second;
87   }
88   return root_node_manager_->GetNode(id);
89 }
90 
GetView(const ViewId & id) const91 const View* ViewManagerServiceImpl::GetView(const ViewId& id) const {
92   if (id_ == id.connection_id) {
93     ViewMap::const_iterator i = view_map_.find(id.view_id);
94     return i == view_map_.end() ? NULL : i->second;
95   }
96   return root_node_manager_->GetView(id);
97 }
98 
SetRoots(const Array<Id> & node_ids)99 void ViewManagerServiceImpl::SetRoots(const Array<Id>& node_ids) {
100   DCHECK(roots_.empty());
101   NodeIdSet roots;
102   for (size_t i = 0; i < node_ids.size(); ++i) {
103     DCHECK(GetNode(NodeIdFromTransportId(node_ids[i])));
104     roots.insert(node_ids[i]);
105   }
106   roots_.swap(roots);
107 }
108 
OnViewManagerServiceImplDestroyed(ConnectionSpecificId id)109 void ViewManagerServiceImpl::OnViewManagerServiceImplDestroyed(
110     ConnectionSpecificId id) {
111   if (creator_id_ == id)
112     creator_id_ = kRootConnection;
113 }
114 
ProcessNodeBoundsChanged(const Node * node,const gfx::Rect & old_bounds,const gfx::Rect & new_bounds,bool originated_change)115 void ViewManagerServiceImpl::ProcessNodeBoundsChanged(
116     const Node* node,
117     const gfx::Rect& old_bounds,
118     const gfx::Rect& new_bounds,
119     bool originated_change) {
120   if (originated_change)
121     return;
122   Id node_id = NodeIdToTransportId(node->id());
123   if (known_nodes_.count(node_id) > 0) {
124     client()->OnNodeBoundsChanged(node_id,
125                                   Rect::From(old_bounds),
126                                   Rect::From(new_bounds));
127   }
128 }
129 
ProcessNodeHierarchyChanged(const Node * node,const Node * new_parent,const Node * old_parent,Id server_change_id,bool originated_change)130 void ViewManagerServiceImpl::ProcessNodeHierarchyChanged(
131     const Node* node,
132     const Node* new_parent,
133     const Node* old_parent,
134     Id server_change_id,
135     bool originated_change) {
136   if (known_nodes_.count(NodeIdToTransportId(node->id())) > 0) {
137     if (originated_change)
138       return;
139     if (node->id().connection_id != id_ && !IsNodeDescendantOfRoots(node)) {
140       // Node was a descendant of roots and is no longer, treat it as though the
141       // node was deleted.
142       RemoveFromKnown(node);
143       client()->OnNodeDeleted(NodeIdToTransportId(node->id()),
144                               server_change_id);
145       root_node_manager_->OnConnectionMessagedClient(id_);
146       return;
147     }
148   }
149 
150   if (originated_change || root_node_manager_->is_processing_delete_node())
151     return;
152   std::vector<const Node*> to_send;
153   if (!ShouldNotifyOnHierarchyChange(node, &new_parent, &old_parent,
154                                      &to_send)) {
155     if (root_node_manager_->IsProcessingChange()) {
156       client()->OnServerChangeIdAdvanced(
157           root_node_manager_->next_server_change_id() + 1);
158     }
159     return;
160   }
161   const NodeId new_parent_id(new_parent ? new_parent->id() : NodeId());
162   const NodeId old_parent_id(old_parent ? old_parent->id() : NodeId());
163   DCHECK((node->id().connection_id == id_) ||
164          (roots_.count(NodeIdToTransportId(node->id())) > 0) ||
165          (new_parent && IsNodeDescendantOfRoots(new_parent)) ||
166          (old_parent && IsNodeDescendantOfRoots(old_parent)));
167   client()->OnNodeHierarchyChanged(NodeIdToTransportId(node->id()),
168                                    NodeIdToTransportId(new_parent_id),
169                                    NodeIdToTransportId(old_parent_id),
170                                    server_change_id,
171                                    NodesToNodeDatas(to_send));
172 }
173 
ProcessNodeReorder(const Node * node,const Node * relative_node,OrderDirection direction,Id server_change_id,bool originated_change)174 void ViewManagerServiceImpl::ProcessNodeReorder(const Node* node,
175                                                 const Node* relative_node,
176                                                 OrderDirection direction,
177                                                 Id server_change_id,
178                                                 bool originated_change) {
179   if (originated_change ||
180       !known_nodes_.count(NodeIdToTransportId(node->id())) ||
181       !known_nodes_.count(NodeIdToTransportId(relative_node->id()))) {
182     return;
183   }
184 
185   client()->OnNodeReordered(NodeIdToTransportId(node->id()),
186                             NodeIdToTransportId(relative_node->id()),
187                             direction,
188                             server_change_id);
189 }
190 
ProcessNodeViewReplaced(const Node * node,const View * new_view,const View * old_view,bool originated_change)191 void ViewManagerServiceImpl::ProcessNodeViewReplaced(
192     const Node* node,
193     const View* new_view,
194     const View* old_view,
195     bool originated_change) {
196   if (originated_change || !known_nodes_.count(NodeIdToTransportId(node->id())))
197     return;
198   const Id new_view_id = new_view ?
199       ViewIdToTransportId(new_view->id()) : 0;
200   const Id old_view_id = old_view ?
201       ViewIdToTransportId(old_view->id()) : 0;
202   client()->OnNodeViewReplaced(NodeIdToTransportId(node->id()),
203                                new_view_id, old_view_id);
204 }
205 
ProcessNodeDeleted(const NodeId & node,Id server_change_id,bool originated_change)206 void ViewManagerServiceImpl::ProcessNodeDeleted(const NodeId& node,
207                                                 Id server_change_id,
208                                                 bool originated_change) {
209   const bool in_known = known_nodes_.erase(NodeIdToTransportId(node)) > 0;
210   const bool in_roots = roots_.erase(NodeIdToTransportId(node)) > 0;
211 
212   if (in_roots && roots_.empty())
213     roots_.insert(NodeIdToTransportId(InvalidNodeId()));
214 
215   if (originated_change)
216     return;
217 
218   if (in_known) {
219     client()->OnNodeDeleted(NodeIdToTransportId(node), server_change_id);
220     root_node_manager_->OnConnectionMessagedClient(id_);
221   } else if (root_node_manager_->IsProcessingChange() &&
222              !root_node_manager_->DidConnectionMessageClient(id_)) {
223     client()->OnServerChangeIdAdvanced(
224         root_node_manager_->next_server_change_id() + 1);
225     root_node_manager_->OnConnectionMessagedClient(id_);
226   }
227 }
228 
ProcessViewDeleted(const ViewId & view,bool originated_change)229 void ViewManagerServiceImpl::ProcessViewDeleted(const ViewId& view,
230                                                 bool originated_change) {
231   if (originated_change)
232     return;
233   client()->OnViewDeleted(ViewIdToTransportId(view));
234 }
235 
OnConnectionError()236 void ViewManagerServiceImpl::OnConnectionError() {
237   if (delete_on_connection_error_)
238     delete this;
239 }
240 
CanRemoveNodeFromParent(const Node * node) const241 bool ViewManagerServiceImpl::CanRemoveNodeFromParent(const Node* node) const {
242   if (!node)
243     return false;
244 
245   const Node* parent = node->GetParent();
246   if (!parent)
247     return false;
248 
249   // Always allow the remove if there are no roots. Otherwise the remove is
250   // allowed if the parent is a descendant of the roots, or the node and its
251   // parent were created by this connection. We explicitly disallow removal of
252   // the node from its parent if the parent isn't visible to this connection
253   // (not in roots).
254   return (roots_.empty() ||
255           (IsNodeDescendantOfRoots(parent) ||
256            (node->id().connection_id == id_ &&
257             parent->id().connection_id == id_)));
258 }
259 
CanAddNode(const Node * parent,const Node * child) const260 bool ViewManagerServiceImpl::CanAddNode(const Node* parent,
261                                         const Node* child) const {
262   if (!parent || !child)
263     return false;  // Both nodes must be valid.
264 
265   if (child->GetParent() == parent || child->Contains(parent))
266     return false;  // Would result in an invalid hierarchy.
267 
268   if (roots_.empty())
269     return true;  // No restriction if there are no roots.
270 
271   if (!IsNodeDescendantOfRoots(parent) && parent->id().connection_id != id_)
272     return false;  // |parent| is not visible to this connection.
273 
274   // Allow the add if the child is already a descendant of the roots or was
275   // created by this connection.
276   return (IsNodeDescendantOfRoots(child) || child->id().connection_id == id_);
277 }
278 
CanReorderNode(const Node * node,const Node * relative_node,OrderDirection direction) const279 bool ViewManagerServiceImpl::CanReorderNode(const Node* node,
280                                             const Node* relative_node,
281                                             OrderDirection direction) const {
282   if (!node || !relative_node)
283     return false;
284 
285   if (node->id().connection_id != id_)
286     return false;
287 
288   const Node* parent = node->GetParent();
289   if (!parent || parent != relative_node->GetParent())
290     return false;
291 
292   if (known_nodes_.count(NodeIdToTransportId(parent->id())) == 0)
293     return false;
294 
295   std::vector<const Node*> children = parent->GetChildren();
296   const size_t child_i =
297       std::find(children.begin(), children.end(), node) - children.begin();
298   const size_t target_i =
299       std::find(children.begin(), children.end(), relative_node) -
300       children.begin();
301   if ((direction == ORDER_ABOVE && child_i == target_i + 1) ||
302       (direction == ORDER_BELOW && child_i + 1 == target_i)) {
303     return false;
304   }
305 
306   return true;
307 }
308 
CanDeleteNode(const NodeId & node_id) const309 bool ViewManagerServiceImpl::CanDeleteNode(const NodeId& node_id) const {
310   return node_id.connection_id == id_;
311 }
312 
CanDeleteView(const ViewId & view_id) const313 bool ViewManagerServiceImpl::CanDeleteView(const ViewId& view_id) const {
314   return view_id.connection_id == id_;
315 }
316 
CanSetView(const Node * node,const ViewId & view_id) const317 bool ViewManagerServiceImpl::CanSetView(const Node* node,
318                                         const ViewId& view_id) const {
319   if (!node || !IsNodeDescendantOfRoots(node))
320     return false;
321 
322   const View* view = GetView(view_id);
323   return (view && view_id.connection_id == id_) || view_id == ViewId();
324 }
325 
CanSetFocus(const Node * node) const326 bool ViewManagerServiceImpl::CanSetFocus(const Node* node) const {
327   // TODO(beng): security.
328   return true;
329 }
330 
CanGetNodeTree(const Node * node) const331 bool ViewManagerServiceImpl::CanGetNodeTree(const Node* node) const {
332   return node &&
333       (IsNodeDescendantOfRoots(node) || node->id().connection_id == id_);
334 }
335 
CanEmbed(const mojo::Array<uint32_t> & node_ids) const336 bool ViewManagerServiceImpl::CanEmbed(
337     const mojo::Array<uint32_t>& node_ids) const {
338   for (size_t i = 0; i < node_ids.size(); ++i) {
339     const Node* node = GetNode(NodeIdFromTransportId(node_ids[i]));
340     if (!node || node->id().connection_id != id_)
341       return false;
342   }
343   return node_ids.size() > 0;
344 }
345 
DeleteNodeImpl(ViewManagerServiceImpl * source,const NodeId & node_id)346 bool ViewManagerServiceImpl::DeleteNodeImpl(ViewManagerServiceImpl* source,
347                                             const NodeId& node_id) {
348   DCHECK_EQ(node_id.connection_id, id_);
349   Node* node = GetNode(node_id);
350   if (!node)
351     return false;
352   RootNodeManager::ScopedChange change(
353       source, root_node_manager_,
354       RootNodeManager::CHANGE_TYPE_ADVANCE_SERVER_CHANGE_ID, true);
355   if (node->GetParent())
356     node->GetParent()->Remove(node);
357   std::vector<Node*> children(node->GetChildren());
358   for (size_t i = 0; i < children.size(); ++i)
359     node->Remove(children[i]);
360   DCHECK(node->GetChildren().empty());
361   node_map_.erase(node_id.node_id);
362   delete node;
363   node = NULL;
364   root_node_manager_->ProcessNodeDeleted(node_id);
365   return true;
366 }
367 
DeleteViewImpl(ViewManagerServiceImpl * source,const ViewId & view_id)368 bool ViewManagerServiceImpl::DeleteViewImpl(ViewManagerServiceImpl* source,
369                                             const ViewId& view_id) {
370   DCHECK_EQ(view_id.connection_id, id_);
371   View* view = GetView(view_id);
372   if (!view)
373     return false;
374   RootNodeManager::ScopedChange change(
375       source, root_node_manager_,
376       RootNodeManager::CHANGE_TYPE_DONT_ADVANCE_SERVER_CHANGE_ID, false);
377   if (view->node())
378     view->node()->SetView(NULL);
379   view_map_.erase(view_id.view_id);
380   // Make a copy of |view_id| as once we delete view |view_id| may no longer be
381   // valid.
382   const ViewId view_id_copy(view_id);
383   delete view;
384   root_node_manager_->ProcessViewDeleted(view_id_copy);
385   return true;
386 }
387 
SetViewImpl(Node * node,const ViewId & view_id)388 bool ViewManagerServiceImpl::SetViewImpl(Node* node, const ViewId& view_id) {
389   DCHECK(node);  // CanSetView() should have verified node exists.
390   View* view = GetView(view_id);
391   RootNodeManager::ScopedChange change(
392       this, root_node_manager_,
393       RootNodeManager::CHANGE_TYPE_DONT_ADVANCE_SERVER_CHANGE_ID, false);
394   node->SetView(view);
395 
396   // TODO(sky): this is temporary, need a real focus API.
397   if (view && root_node_manager_->root()->Contains(node))
398     node->window()->Focus();
399 
400   return true;
401 }
402 
GetUnknownNodesFrom(const Node * node,std::vector<const Node * > * nodes)403 void ViewManagerServiceImpl::GetUnknownNodesFrom(
404     const Node* node,
405     std::vector<const Node*>* nodes) {
406   const Id transport_id = NodeIdToTransportId(node->id());
407   if (known_nodes_.count(transport_id) == 1)
408     return;
409   nodes->push_back(node);
410   known_nodes_.insert(transport_id);
411   std::vector<const Node*> children(node->GetChildren());
412   for (size_t i = 0 ; i < children.size(); ++i)
413     GetUnknownNodesFrom(children[i], nodes);
414 }
415 
RemoveFromKnown(const Node * node)416 void ViewManagerServiceImpl::RemoveFromKnown(const Node* node) {
417   if (node->id().connection_id == id_)
418     return;
419   known_nodes_.erase(NodeIdToTransportId(node->id()));
420   std::vector<const Node*> children = node->GetChildren();
421   for (size_t i = 0; i < children.size(); ++i)
422     RemoveFromKnown(children[i]);
423 }
424 
AddRoots(const std::vector<Id> & node_ids)425 bool ViewManagerServiceImpl::AddRoots(
426     const std::vector<Id>& node_ids) {
427   std::vector<const Node*> to_send;
428   bool did_add_root = false;
429   for (size_t i = 0; i < node_ids.size(); ++i) {
430     CHECK_EQ(creator_id_, NodeIdFromTransportId(node_ids[i]).connection_id);
431     if (roots_.count(node_ids[i]) > 0)
432       continue;
433 
434     did_add_root = true;
435     roots_.insert(node_ids[i]);
436     Node* node = GetNode(NodeIdFromTransportId(node_ids[i]));
437     DCHECK(node);
438     if (known_nodes_.count(node_ids[i]) == 0) {
439       GetUnknownNodesFrom(node, &to_send);
440     } else {
441       // Even though the connection knows about the new root we need to tell it
442       // |node| is now a root.
443       to_send.push_back(node);
444     }
445   }
446 
447   if (!did_add_root)
448     return false;
449 
450   client()->OnRootsAdded(NodesToNodeDatas(to_send));
451   return true;
452 }
453 
IsNodeDescendantOfRoots(const Node * node) const454 bool ViewManagerServiceImpl::IsNodeDescendantOfRoots(const Node* node) const {
455   if (roots_.empty())
456     return true;
457   if (!node)
458     return false;
459   const Id invalid_node_id =
460       NodeIdToTransportId(InvalidNodeId());
461   for (NodeIdSet::const_iterator i = roots_.begin(); i != roots_.end(); ++i) {
462     if (*i == invalid_node_id)
463       continue;
464     const Node* root = GetNode(NodeIdFromTransportId(*i));
465     DCHECK(root);
466     if (root->Contains(node))
467       return true;
468   }
469   return false;
470 }
471 
ShouldNotifyOnHierarchyChange(const Node * node,const Node ** new_parent,const Node ** old_parent,std::vector<const Node * > * to_send)472 bool ViewManagerServiceImpl::ShouldNotifyOnHierarchyChange(
473     const Node* node,
474     const Node** new_parent,
475     const Node** old_parent,
476     std::vector<const Node*>* to_send) {
477   // If the node is not in |roots_| or was never known to this connection then
478   // don't notify the client about it.
479   if (node->id().connection_id != id_ &&
480       known_nodes_.count(NodeIdToTransportId(node->id())) == 0 &&
481       !IsNodeDescendantOfRoots(node)) {
482     return false;
483   }
484   if (!IsNodeDescendantOfRoots(*new_parent))
485     *new_parent = NULL;
486   if (!IsNodeDescendantOfRoots(*old_parent))
487     *old_parent = NULL;
488 
489   if (*new_parent) {
490     // On getting a new parent we may need to communicate new nodes to the
491     // client. We do that in the following cases:
492     // . New parent is a descendant of the roots. In this case the client
493     //   already knows all ancestors, so we only have to communicate descendants
494     //   of node the client doesn't know about.
495     // . If the client knew about the parent, we have to do the same.
496     // . If the client knows about the node and is added to a tree the client
497     //   doesn't know about we have to communicate from the root down (the
498     //   client is learning about a new root).
499     if (root_node_manager_->root()->Contains(*new_parent) ||
500         known_nodes_.count(NodeIdToTransportId((*new_parent)->id()))) {
501       GetUnknownNodesFrom(node, to_send);
502       return true;
503     }
504     // If parent wasn't known we have to communicate from the root down.
505     if (known_nodes_.count(NodeIdToTransportId(node->id()))) {
506       // No need to check against |roots_| as client should always know it's
507       // |roots_|.
508       GetUnknownNodesFrom((*new_parent)->GetRoot(), to_send);
509       return true;
510     }
511   }
512   // Otherwise only communicate the change if the node was known. We shouldn't
513   // need to communicate any nodes on a remove.
514   return known_nodes_.count(NodeIdToTransportId(node->id())) > 0;
515 }
516 
NodesToNodeDatas(const std::vector<const Node * > & nodes)517 Array<NodeDataPtr> ViewManagerServiceImpl::NodesToNodeDatas(
518     const std::vector<const Node*>& nodes) {
519   Array<NodeDataPtr> array(nodes.size());
520   for (size_t i = 0; i < nodes.size(); ++i) {
521     const Node* node = nodes[i];
522     DCHECK(known_nodes_.count(NodeIdToTransportId(node->id())) > 0);
523     const Node* parent = node->GetParent();
524     // If the parent isn't known, it means the parent is not visible to us (not
525     // in roots), and should not be sent over.
526     if (parent && known_nodes_.count(NodeIdToTransportId(parent->id())) == 0)
527       parent = NULL;
528     NodeDataPtr inode(NodeData::New());
529     inode->parent_id = NodeIdToTransportId(parent ? parent->id() : NodeId());
530     inode->node_id = NodeIdToTransportId(node->id());
531     inode->view_id =
532         ViewIdToTransportId(node->view() ? node->view()->id() : ViewId());
533     inode->bounds = Rect::From(node->bounds());
534     array[i] = inode.Pass();
535   }
536   return array.Pass();
537 }
538 
CreateNode(Id transport_node_id,const Callback<void (bool)> & callback)539 void ViewManagerServiceImpl::CreateNode(
540     Id transport_node_id,
541     const Callback<void(bool)>& callback) {
542   const NodeId node_id(NodeIdFromTransportId(transport_node_id));
543   if (node_id.connection_id != id_ ||
544       node_map_.find(node_id.node_id) != node_map_.end()) {
545     callback.Run(false);
546     return;
547   }
548   node_map_[node_id.node_id] = new Node(this, node_id);
549   known_nodes_.insert(transport_node_id);
550   callback.Run(true);
551 }
552 
DeleteNode(Id transport_node_id,Id server_change_id,const Callback<void (bool)> & callback)553 void ViewManagerServiceImpl::DeleteNode(
554     Id transport_node_id,
555     Id server_change_id,
556     const Callback<void(bool)>& callback) {
557   const NodeId node_id(NodeIdFromTransportId(transport_node_id));
558   bool success = false;
559   if (server_change_id == root_node_manager_->next_server_change_id() &&
560       CanDeleteNode(node_id)) {
561     ViewManagerServiceImpl* connection = root_node_manager_->GetConnection(
562         node_id.connection_id);
563     success = connection && connection->DeleteNodeImpl(this, node_id);
564   }
565   callback.Run(success);
566 }
567 
AddNode(Id parent_id,Id child_id,Id server_change_id,const Callback<void (bool)> & callback)568 void ViewManagerServiceImpl::AddNode(
569     Id parent_id,
570     Id child_id,
571     Id server_change_id,
572     const Callback<void(bool)>& callback) {
573   bool success = false;
574   if (server_change_id == root_node_manager_->next_server_change_id()) {
575     Node* parent = GetNode(NodeIdFromTransportId(parent_id));
576     Node* child = GetNode(NodeIdFromTransportId(child_id));
577     if (CanAddNode(parent, child)) {
578       success = true;
579       RootNodeManager::ScopedChange change(
580           this, root_node_manager_,
581           RootNodeManager::CHANGE_TYPE_ADVANCE_SERVER_CHANGE_ID, false);
582       parent->Add(child);
583     }
584   }
585   callback.Run(success);
586 }
587 
RemoveNodeFromParent(Id node_id,Id server_change_id,const Callback<void (bool)> & callback)588 void ViewManagerServiceImpl::RemoveNodeFromParent(
589     Id node_id,
590     Id server_change_id,
591     const Callback<void(bool)>& callback) {
592   bool success = false;
593   if (server_change_id == root_node_manager_->next_server_change_id()) {
594     Node* node = GetNode(NodeIdFromTransportId(node_id));
595     if (CanRemoveNodeFromParent(node)) {
596       success = true;
597       RootNodeManager::ScopedChange change(
598           this, root_node_manager_,
599           RootNodeManager::CHANGE_TYPE_ADVANCE_SERVER_CHANGE_ID, false);
600       node->GetParent()->Remove(node);
601     }
602   }
603   callback.Run(success);
604 }
605 
ReorderNode(Id node_id,Id relative_node_id,OrderDirection direction,Id server_change_id,const Callback<void (bool)> & callback)606 void ViewManagerServiceImpl::ReorderNode(Id node_id,
607                                          Id relative_node_id,
608                                          OrderDirection direction,
609                                          Id server_change_id,
610                                          const Callback<void(bool)>& callback) {
611   bool success = false;
612   if (server_change_id == root_node_manager_->next_server_change_id()) {
613     Node* node = GetNode(NodeIdFromTransportId(node_id));
614     Node* relative_node = GetNode(NodeIdFromTransportId(relative_node_id));
615     if (CanReorderNode(node, relative_node, direction)) {
616       success = true;
617       RootNodeManager::ScopedChange change(
618           this, root_node_manager_,
619           RootNodeManager::CHANGE_TYPE_ADVANCE_SERVER_CHANGE_ID, false);
620       node->GetParent()->Reorder(node, relative_node, direction);
621       root_node_manager_->ProcessNodeReorder(node, relative_node, direction);
622     }
623   }
624   callback.Run(success);
625 }
626 
GetNodeTree(Id node_id,const Callback<void (Array<NodeDataPtr>)> & callback)627 void ViewManagerServiceImpl::GetNodeTree(
628     Id node_id,
629     const Callback<void(Array<NodeDataPtr>)>& callback) {
630   Node* node = GetNode(NodeIdFromTransportId(node_id));
631   std::vector<const Node*> nodes;
632   if (CanGetNodeTree(node)) {
633     GetDescendants(node, &nodes);
634     for (size_t i = 0; i < nodes.size(); ++i)
635       known_nodes_.insert(NodeIdToTransportId(nodes[i]->id()));
636   }
637   callback.Run(NodesToNodeDatas(nodes));
638 }
639 
CreateView(Id transport_view_id,const Callback<void (bool)> & callback)640 void ViewManagerServiceImpl::CreateView(
641     Id transport_view_id,
642     const Callback<void(bool)>& callback) {
643   const ViewId view_id(ViewIdFromTransportId(transport_view_id));
644   if (view_id.connection_id != id_ || view_map_.count(view_id.view_id)) {
645     callback.Run(false);
646     return;
647   }
648   view_map_[view_id.view_id] = new View(view_id);
649   callback.Run(true);
650 }
651 
DeleteView(Id transport_view_id,const Callback<void (bool)> & callback)652 void ViewManagerServiceImpl::DeleteView(
653     Id transport_view_id,
654     const Callback<void(bool)>& callback) {
655   const ViewId view_id(ViewIdFromTransportId(transport_view_id));
656   bool did_delete = CanDeleteView(view_id);
657   if (did_delete) {
658     ViewManagerServiceImpl* connection = root_node_manager_->GetConnection(
659         view_id.connection_id);
660     did_delete = (connection && connection->DeleteViewImpl(this, view_id));
661   }
662   callback.Run(did_delete);
663 }
664 
SetView(Id transport_node_id,Id transport_view_id,const Callback<void (bool)> & callback)665 void ViewManagerServiceImpl::SetView(Id transport_node_id,
666                                      Id transport_view_id,
667                                      const Callback<void(bool)>& callback) {
668   Node* node = GetNode(NodeIdFromTransportId(transport_node_id));
669   const ViewId view_id(ViewIdFromTransportId(transport_view_id));
670   callback.Run(CanSetView(node, view_id) && SetViewImpl(node, view_id));
671 }
672 
SetViewContents(Id view_id,ScopedSharedBufferHandle buffer,uint32_t buffer_size,const Callback<void (bool)> & callback)673 void ViewManagerServiceImpl::SetViewContents(
674     Id view_id,
675     ScopedSharedBufferHandle buffer,
676     uint32_t buffer_size,
677     const Callback<void(bool)>& callback) {
678   View* view = GetView(ViewIdFromTransportId(view_id));
679   if (!view) {
680     callback.Run(false);
681     return;
682   }
683   void* handle_data;
684   if (MapBuffer(buffer.get(), 0, buffer_size, &handle_data,
685                 MOJO_MAP_BUFFER_FLAG_NONE) != MOJO_RESULT_OK) {
686     callback.Run(false);
687     return;
688   }
689   SkBitmap bitmap;
690   gfx::PNGCodec::Decode(static_cast<const unsigned char*>(handle_data),
691                         buffer_size, &bitmap);
692   view->SetBitmap(bitmap);
693   UnmapBuffer(handle_data);
694   callback.Run(true);
695 }
696 
SetFocus(Id node_id,const Callback<void (bool)> & callback)697 void ViewManagerServiceImpl::SetFocus(Id node_id,
698                                       const Callback<void(bool)> & callback) {
699   bool success = false;
700   Node* node = GetNode(NodeIdFromTransportId(node_id));
701   if (CanSetFocus(node)) {
702     success = true;
703     node->window()->Focus();
704   }
705   callback.Run(success);
706 }
707 
SetNodeBounds(Id node_id,RectPtr bounds,const Callback<void (bool)> & callback)708 void ViewManagerServiceImpl::SetNodeBounds(
709     Id node_id,
710     RectPtr bounds,
711     const Callback<void(bool)>& callback) {
712   if (NodeIdFromTransportId(node_id).connection_id != id_) {
713     callback.Run(false);
714     return;
715   }
716 
717   Node* node = GetNode(NodeIdFromTransportId(node_id));
718   if (!node) {
719     callback.Run(false);
720     return;
721   }
722 
723   RootNodeManager::ScopedChange change(
724       this, root_node_manager_,
725       RootNodeManager::CHANGE_TYPE_DONT_ADVANCE_SERVER_CHANGE_ID, false);
726   gfx::Rect old_bounds = node->window()->bounds();
727   node->window()->SetBounds(bounds.To<gfx::Rect>());
728   root_node_manager_->ProcessNodeBoundsChanged(
729       node, old_bounds, bounds.To<gfx::Rect>());
730   callback.Run(true);
731 }
732 
Embed(const String & url,Array<uint32_t> node_ids,const Callback<void (bool)> & callback)733 void ViewManagerServiceImpl::Embed(const String& url,
734                                    Array<uint32_t> node_ids,
735                                    const Callback<void(bool)>& callback) {
736   bool success = CanEmbed(node_ids);
737   if (success) {
738     // We may already have this connection, if so reuse it.
739     ViewManagerServiceImpl* existing_connection =
740         root_node_manager_->GetConnectionByCreator(id_, url.To<std::string>());
741     if (existing_connection)
742       success = existing_connection->AddRoots(node_ids.storage());
743     else
744       root_node_manager_->Embed(id_, url, node_ids);
745   }
746   callback.Run(success);
747 }
748 
DispatchOnViewInputEvent(Id transport_view_id,EventPtr event)749 void ViewManagerServiceImpl::DispatchOnViewInputEvent(Id transport_view_id,
750                                                       EventPtr event) {
751   // We only allow the WM to dispatch events. At some point this function will
752   // move to a separate interface and the check can go away.
753   if (id_ != kWindowManagerConnection)
754     return;
755 
756   const ViewId view_id(ViewIdFromTransportId(transport_view_id));
757   ViewManagerServiceImpl* connection = root_node_manager_->GetConnection(
758       view_id.connection_id);
759   if (connection)
760     connection->client()->OnViewInputEvent(
761         transport_view_id,
762         event.Pass(),
763         base::Bind(&base::DoNothing));
764 }
765 
OnNodeHierarchyChanged(const Node * node,const Node * new_parent,const Node * old_parent)766 void ViewManagerServiceImpl::OnNodeHierarchyChanged(const Node* node,
767                                                     const Node* new_parent,
768                                                     const Node* old_parent) {
769   root_node_manager_->ProcessNodeHierarchyChanged(node, new_parent, old_parent);
770 }
771 
OnNodeViewReplaced(const Node * node,const View * new_view,const View * old_view)772 void ViewManagerServiceImpl::OnNodeViewReplaced(const Node* node,
773                                                 const View* new_view,
774                                                 const View* old_view) {
775   root_node_manager_->ProcessNodeViewReplaced(node, new_view, old_view);
776 }
777 
OnViewInputEvent(const View * view,const ui::Event * event)778 void ViewManagerServiceImpl::OnViewInputEvent(const View* view,
779                                               const ui::Event* event) {
780   root_node_manager_->DispatchViewInputEventToWindowManager(view, event);
781 }
782 
OnConnectionEstablished()783 void ViewManagerServiceImpl::OnConnectionEstablished() {
784   root_node_manager_->AddConnection(this);
785 
786   std::vector<const Node*> to_send;
787   if (roots_.empty()) {
788     GetUnknownNodesFrom(root_node_manager_->root(), &to_send);
789   } else {
790     for (NodeIdSet::const_iterator i = roots_.begin(); i != roots_.end(); ++i)
791       GetUnknownNodesFrom(GetNode(NodeIdFromTransportId(*i)), &to_send);
792   }
793 
794   client()->OnViewManagerConnectionEstablished(
795       id_,
796       creator_url_,
797       root_node_manager_->next_server_change_id(),
798       NodesToNodeDatas(to_send));
799 }
800 
801 }  // namespace service
802 }  // namespace view_manager
803 }  // namespace mojo
804