Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / mojo / services / view_manager / view_manager_service_impl.cc
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 "mojo/services/public/cpp/geometry/geometry_type_converters.h"
9 #include "mojo/services/public/cpp/input_events/input_events_type_converters.h"
10 #include "mojo/services/view_manager/default_access_policy.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/window_manager_access_policy.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 service {
20
21 ViewManagerServiceImpl::ViewManagerServiceImpl(
22     RootNodeManager* root_node_manager,
23     ConnectionSpecificId creator_id,
24     const std::string& creator_url,
25     const std::string& url,
26     const NodeId& root_id,
27     InterfaceRequest<ServiceProvider> service_provider)
28     : root_node_manager_(root_node_manager),
29       id_(root_node_manager_->GetAndAdvanceNextConnectionId()),
30       url_(url),
31       creator_id_(creator_id),
32       creator_url_(creator_url),
33       delete_on_connection_error_(false),
34       service_provider_(service_provider.Pass()) {
35   CHECK(GetNode(root_id));
36   roots_.insert(NodeIdToTransportId(root_id));
37   if (root_id == RootNodeId())
38     access_policy_.reset(new WindowManagerAccessPolicy(id_, this));
39   else
40     access_policy_.reset(new DefaultAccessPolicy(id_, this));
41 }
42
43 ViewManagerServiceImpl::~ViewManagerServiceImpl() {
44   // Delete any nodes we created.
45   if (!node_map_.empty()) {
46     RootNodeManager::ScopedChange change(this, root_node_manager_, true);
47     while (!node_map_.empty())
48       delete node_map_.begin()->second;
49   }
50
51   root_node_manager_->RemoveConnection(this);
52 }
53
54 const Node* ViewManagerServiceImpl::GetNode(const NodeId& id) const {
55   if (id_ == id.connection_id) {
56     NodeMap::const_iterator i = node_map_.find(id.node_id);
57     return i == node_map_.end() ? NULL : i->second;
58   }
59   return root_node_manager_->GetNode(id);
60 }
61
62 bool ViewManagerServiceImpl::HasRoot(const NodeId& id) const {
63   return roots_.find(NodeIdToTransportId(id)) != roots_.end();
64 }
65
66 void ViewManagerServiceImpl::OnViewManagerServiceImplDestroyed(
67     ConnectionSpecificId id) {
68   if (creator_id_ == id)
69     creator_id_ = kInvalidConnectionId;
70 }
71
72 void ViewManagerServiceImpl::ProcessNodeBoundsChanged(
73     const Node* node,
74     const gfx::Rect& old_bounds,
75     const gfx::Rect& new_bounds,
76     bool originated_change) {
77   if (originated_change || !IsNodeKnown(node))
78     return;
79   client()->OnViewBoundsChanged(NodeIdToTransportId(node->id()),
80                                 Rect::From(old_bounds),
81                                 Rect::From(new_bounds));
82 }
83
84 void ViewManagerServiceImpl::ProcessNodeHierarchyChanged(
85     const Node* node,
86     const Node* new_parent,
87     const Node* old_parent,
88     bool originated_change) {
89   if (originated_change && !IsNodeKnown(node) && new_parent &&
90       IsNodeKnown(new_parent)) {
91     std::vector<const Node*> unused;
92     GetUnknownNodesFrom(node, &unused);
93   }
94   if (originated_change || root_node_manager_->is_processing_delete_node() ||
95       root_node_manager_->DidConnectionMessageClient(id_)) {
96     return;
97   }
98
99   if (!access_policy_->ShouldNotifyOnHierarchyChange(
100           node, &new_parent, &old_parent)) {
101     return;
102   }
103   // Inform the client of any new nodes and update the set of nodes we know
104   // about.
105   std::vector<const Node*> to_send;
106   if (!IsNodeKnown(node))
107     GetUnknownNodesFrom(node, &to_send);
108   const NodeId new_parent_id(new_parent ? new_parent->id() : NodeId());
109   const NodeId old_parent_id(old_parent ? old_parent->id() : NodeId());
110   client()->OnViewHierarchyChanged(NodeIdToTransportId(node->id()),
111                                    NodeIdToTransportId(new_parent_id),
112                                    NodeIdToTransportId(old_parent_id),
113                                    NodesToViewDatas(to_send));
114   root_node_manager_->OnConnectionMessagedClient(id_);
115 }
116
117 void ViewManagerServiceImpl::ProcessNodeReorder(const Node* node,
118                                                 const Node* relative_node,
119                                                 OrderDirection direction,
120                                                 bool originated_change) {
121   if (originated_change || !IsNodeKnown(node) || !IsNodeKnown(relative_node))
122     return;
123
124   client()->OnViewReordered(NodeIdToTransportId(node->id()),
125                             NodeIdToTransportId(relative_node->id()),
126                             direction);
127 }
128
129 void ViewManagerServiceImpl::ProcessNodeDeleted(const NodeId& node,
130                                                 bool originated_change) {
131   node_map_.erase(node.node_id);
132
133   const bool in_known = known_nodes_.erase(NodeIdToTransportId(node)) > 0;
134   roots_.erase(NodeIdToTransportId(node));
135
136   if (originated_change)
137     return;
138
139   if (in_known) {
140     client()->OnViewDeleted(NodeIdToTransportId(node));
141     root_node_manager_->OnConnectionMessagedClient(id_);
142   }
143 }
144
145 void ViewManagerServiceImpl::OnConnectionError() {
146   if (delete_on_connection_error_)
147     delete this;
148 }
149
150 bool ViewManagerServiceImpl::IsNodeKnown(const Node* node) const {
151   return known_nodes_.count(NodeIdToTransportId(node->id())) > 0;
152 }
153
154 bool ViewManagerServiceImpl::CanReorderNode(const Node* node,
155                                             const Node* relative_node,
156                                             OrderDirection direction) const {
157   if (!node || !relative_node)
158     return false;
159
160   const Node* parent = node->GetParent();
161   if (!parent || parent != relative_node->GetParent())
162     return false;
163
164   if (!access_policy_->CanReorderNode(node, relative_node, direction))
165     return false;
166
167   std::vector<const Node*> children = parent->GetChildren();
168   const size_t child_i =
169       std::find(children.begin(), children.end(), node) - children.begin();
170   const size_t target_i =
171       std::find(children.begin(), children.end(), relative_node) -
172       children.begin();
173   if ((direction == ORDER_DIRECTION_ABOVE && child_i == target_i + 1) ||
174       (direction == ORDER_DIRECTION_BELOW && child_i + 1 == target_i)) {
175     return false;
176   }
177
178   return true;
179 }
180
181 bool ViewManagerServiceImpl::DeleteNodeImpl(ViewManagerServiceImpl* source,
182                                             Node* node) {
183   DCHECK(node);
184   DCHECK_EQ(node->id().connection_id, id_);
185   RootNodeManager::ScopedChange change(source, root_node_manager_, true);
186   delete node;
187   return true;
188 }
189
190 void ViewManagerServiceImpl::GetUnknownNodesFrom(
191     const Node* node,
192     std::vector<const Node*>* nodes) {
193   if (IsNodeKnown(node) || !access_policy_->CanGetNodeTree(node))
194     return;
195   nodes->push_back(node);
196   known_nodes_.insert(NodeIdToTransportId(node->id()));
197   if (!access_policy_->CanDescendIntoNodeForNodeTree(node))
198     return;
199   std::vector<const Node*> children(node->GetChildren());
200   for (size_t i = 0 ; i < children.size(); ++i)
201     GetUnknownNodesFrom(children[i], nodes);
202 }
203
204 void ViewManagerServiceImpl::RemoveFromKnown(const Node* node,
205                                              std::vector<Node*>* local_nodes) {
206   if (node->id().connection_id == id_) {
207     if (local_nodes)
208       local_nodes->push_back(GetNode(node->id()));
209     return;
210   }
211   known_nodes_.erase(NodeIdToTransportId(node->id()));
212   std::vector<const Node*> children = node->GetChildren();
213   for (size_t i = 0; i < children.size(); ++i)
214     RemoveFromKnown(children[i], local_nodes);
215 }
216
217 void ViewManagerServiceImpl::AddRoot(
218     const NodeId& node_id,
219     InterfaceRequest<ServiceProvider> service_provider) {
220   const Id transport_node_id(NodeIdToTransportId(node_id));
221   CHECK(roots_.count(transport_node_id) == 0);
222
223   CHECK_EQ(creator_id_, node_id.connection_id);
224   roots_.insert(transport_node_id);
225   const Node* node = GetNode(node_id);
226   CHECK(node);
227   std::vector<const Node*> to_send;
228   if (!IsNodeKnown(node)) {
229     GetUnknownNodesFrom(node, &to_send);
230   } else {
231     // Even though the connection knows about the new root we need to tell it
232     // |node| is now a root.
233     to_send.push_back(node);
234   }
235
236   client()->OnEmbed(id_, creator_url_, NodeToViewData(to_send.front()),
237                     service_provider.Pass());
238   root_node_manager_->OnConnectionMessagedClient(id_);
239 }
240
241 void ViewManagerServiceImpl::RemoveRoot(const NodeId& node_id) {
242   const Id transport_node_id(NodeIdToTransportId(node_id));
243   CHECK(roots_.count(transport_node_id) > 0);
244
245   roots_.erase(transport_node_id);
246
247   // No need to do anything if we created the node.
248   if (node_id.connection_id == id_)
249     return;
250
251   client()->OnViewDeleted(transport_node_id);
252   root_node_manager_->OnConnectionMessagedClient(id_);
253
254   // This connection no longer knows about the node. Unparent any nodes that
255   // were parented to nodes in the root.
256   std::vector<Node*> local_nodes;
257   RemoveFromKnown(GetNode(node_id), &local_nodes);
258   for (size_t i = 0; i < local_nodes.size(); ++i)
259     local_nodes[i]->GetParent()->Remove(local_nodes[i]);
260 }
261
262 void ViewManagerServiceImpl::RemoveChildrenAsPartOfEmbed(
263     const NodeId& node_id) {
264   Node* node = GetNode(node_id);
265   CHECK(node);
266   CHECK(node->id().connection_id == node_id.connection_id);
267   std::vector<Node*> children = node->GetChildren();
268   for (size_t i = 0; i < children.size(); ++i)
269     node->Remove(children[i]);
270 }
271
272 Array<ViewDataPtr> ViewManagerServiceImpl::NodesToViewDatas(
273     const std::vector<const Node*>& nodes) {
274   Array<ViewDataPtr> array(nodes.size());
275   for (size_t i = 0; i < nodes.size(); ++i)
276     array[i] = NodeToViewData(nodes[i]).Pass();
277   return array.Pass();
278 }
279
280 ViewDataPtr ViewManagerServiceImpl::NodeToViewData(const Node* node) {
281   DCHECK(IsNodeKnown(node));
282   const Node* parent = node->GetParent();
283   // If the parent isn't known, it means the parent is not visible to us (not
284   // in roots), and should not be sent over.
285   if (parent && !IsNodeKnown(parent))
286     parent = NULL;
287   ViewDataPtr view_data(ViewData::New());
288   view_data->parent_id = NodeIdToTransportId(parent ? parent->id() : NodeId());
289   view_data->view_id = NodeIdToTransportId(node->id());
290   view_data->bounds = Rect::From(node->bounds());
291   return view_data.Pass();
292 }
293
294 void ViewManagerServiceImpl::GetNodeTreeImpl(
295     const Node* node,
296     std::vector<const Node*>* nodes) const {
297   DCHECK(node);
298
299   if (!access_policy_->CanGetNodeTree(node))
300     return;
301
302   nodes->push_back(node);
303
304   if (!access_policy_->CanDescendIntoNodeForNodeTree(node))
305     return;
306
307   std::vector<const Node*> children(node->GetChildren());
308   for (size_t i = 0 ; i < children.size(); ++i)
309     GetNodeTreeImpl(children[i], nodes);
310 }
311
312 void ViewManagerServiceImpl::CreateView(
313     Id transport_view_id,
314     const Callback<void(ErrorCode)>& callback) {
315   const NodeId node_id(NodeIdFromTransportId(transport_view_id));
316   ErrorCode error_code = ERROR_CODE_NONE;
317   if (node_id.connection_id != id_) {
318     error_code = ERROR_CODE_ILLEGAL_ARGUMENT;
319   } else if (node_map_.find(node_id.node_id) != node_map_.end()) {
320     error_code = ERROR_CODE_VALUE_IN_USE;
321   } else {
322     node_map_[node_id.node_id] = new Node(root_node_manager_, node_id);
323     known_nodes_.insert(transport_view_id);
324   }
325   callback.Run(error_code);
326 }
327
328 void ViewManagerServiceImpl::DeleteView(
329     Id transport_view_id,
330     const Callback<void(bool)>& callback) {
331   Node* node = GetNode(NodeIdFromTransportId(transport_view_id));
332   bool success = false;
333   if (node && access_policy_->CanDeleteNode(node)) {
334     ViewManagerServiceImpl* connection = root_node_manager_->GetConnection(
335         node->id().connection_id);
336     success = connection && connection->DeleteNodeImpl(this, node);
337   }
338   callback.Run(success);
339 }
340
341 void ViewManagerServiceImpl::AddView(
342     Id parent_id,
343     Id child_id,
344     const Callback<void(bool)>& callback) {
345   bool success = false;
346   Node* parent = GetNode(NodeIdFromTransportId(parent_id));
347   Node* child = GetNode(NodeIdFromTransportId(child_id));
348   if (parent && child && child->GetParent() != parent &&
349       !child->Contains(parent) && access_policy_->CanAddNode(parent, child)) {
350     success = true;
351     RootNodeManager::ScopedChange change(this, root_node_manager_, false);
352     parent->Add(child);
353   }
354   callback.Run(success);
355 }
356
357 void ViewManagerServiceImpl::RemoveViewFromParent(
358     Id view_id,
359     const Callback<void(bool)>& callback) {
360   bool success = false;
361   Node* node = GetNode(NodeIdFromTransportId(view_id));
362   if (node && node->GetParent() &&
363       access_policy_->CanRemoveNodeFromParent(node)) {
364     success = true;
365     RootNodeManager::ScopedChange change(this, root_node_manager_, false);
366     node->GetParent()->Remove(node);
367   }
368   callback.Run(success);
369 }
370
371 void ViewManagerServiceImpl::ReorderView(Id view_id,
372                                          Id relative_view_id,
373                                          OrderDirection direction,
374                                          const Callback<void(bool)>& callback) {
375   bool success = false;
376   Node* node = GetNode(NodeIdFromTransportId(view_id));
377   Node* relative_node = GetNode(NodeIdFromTransportId(relative_view_id));
378   if (CanReorderNode(node, relative_node, direction)) {
379     success = true;
380     RootNodeManager::ScopedChange change(this, root_node_manager_, false);
381     node->GetParent()->Reorder(node, relative_node, direction);
382     root_node_manager_->ProcessNodeReorder(node, relative_node, direction);
383   }
384   callback.Run(success);
385 }
386
387 void ViewManagerServiceImpl::GetViewTree(
388     Id view_id,
389     const Callback<void(Array<ViewDataPtr>)>& callback) {
390   Node* node = GetNode(NodeIdFromTransportId(view_id));
391   std::vector<const Node*> nodes;
392   if (node) {
393     GetNodeTreeImpl(node, &nodes);
394     // TODO(sky): this should map in nodes that weren't none.
395   }
396   callback.Run(NodesToViewDatas(nodes));
397 }
398
399 void ViewManagerServiceImpl::SetViewContents(
400     Id view_id,
401     ScopedSharedBufferHandle buffer,
402     uint32_t buffer_size,
403     const Callback<void(bool)>& callback) {
404   // TODO(sky): add coverage of not being able to set for random node.
405   Node* node = GetNode(NodeIdFromTransportId(view_id));
406   if (!node || !access_policy_->CanSetNodeContents(node)) {
407     callback.Run(false);
408     return;
409   }
410   void* handle_data;
411   if (MapBuffer(buffer.get(), 0, buffer_size, &handle_data,
412                 MOJO_MAP_BUFFER_FLAG_NONE) != MOJO_RESULT_OK) {
413     callback.Run(false);
414     return;
415   }
416   SkBitmap bitmap;
417   gfx::PNGCodec::Decode(static_cast<const unsigned char*>(handle_data),
418                         buffer_size, &bitmap);
419   node->SetBitmap(bitmap);
420   UnmapBuffer(handle_data);
421   callback.Run(true);
422 }
423
424 void ViewManagerServiceImpl::SetViewBounds(
425     Id view_id,
426     RectPtr bounds,
427     const Callback<void(bool)>& callback) {
428   Node* node = GetNode(NodeIdFromTransportId(view_id));
429   const bool success = node && access_policy_->CanSetNodeBounds(node);
430   if (success) {
431     RootNodeManager::ScopedChange change(this, root_node_manager_, false);
432     gfx::Rect old_bounds = node->window()->bounds();
433     node->window()->SetBounds(bounds.To<gfx::Rect>());
434   }
435   callback.Run(success);
436 }
437
438 void ViewManagerServiceImpl::SetViewVisibility(
439     Id transport_view_id,
440     bool visible,
441     const Callback<void(bool)>& callback) {
442   Node* node = GetNode(NodeIdFromTransportId(transport_view_id));
443   const bool success = node && node->IsVisible() != visible &&
444       access_policy_->CanChangeNodeVisibility(node);
445   if (success) {
446     DCHECK(node);
447     node->SetVisible(visible);
448   }
449   // TODO(sky): need to notify of visibility changes.
450   callback.Run(success);
451 }
452
453 void ViewManagerServiceImpl::Embed(
454     const String& url,
455     Id transport_view_id,
456     ServiceProviderPtr service_provider,
457     const Callback<void(bool)>& callback) {
458   InterfaceRequest<ServiceProvider> spir;
459   spir.Bind(service_provider.PassMessagePipe());
460
461   if (NodeIdFromTransportId(transport_view_id) == InvalidNodeId()) {
462     root_node_manager_->EmbedRoot(url, spir.Pass());
463     callback.Run(true);
464     return;
465   }
466   const Node* node = GetNode(NodeIdFromTransportId(transport_view_id));
467   bool success = node && access_policy_->CanEmbed(node);
468   if (success) {
469     // Only allow a node to be the root for one connection.
470     const NodeId node_id(NodeIdFromTransportId(transport_view_id));
471     ViewManagerServiceImpl* connection_by_url =
472         root_node_manager_->GetConnectionByCreator(id_, url.To<std::string>());
473     ViewManagerServiceImpl* connection_with_node_as_root =
474         root_node_manager_->GetConnectionWithRoot(node_id);
475     if ((connection_by_url != connection_with_node_as_root ||
476          (!connection_by_url && !connection_with_node_as_root)) &&
477         (!connection_by_url || !connection_by_url->HasRoot(node_id))) {
478       RootNodeManager::ScopedChange change(this, root_node_manager_, true);
479       RemoveChildrenAsPartOfEmbed(node_id);
480       // Never message the originating connection.
481       root_node_manager_->OnConnectionMessagedClient(id_);
482       if (connection_with_node_as_root)
483         connection_with_node_as_root->RemoveRoot(node_id);
484       if (connection_by_url) {
485         connection_by_url->AddRoot(node_id, spir.Pass());
486       } else {
487         root_node_manager_->Embed(id_, url, transport_view_id, spir.Pass());
488       }
489     } else {
490       success = false;
491     }
492   }
493   callback.Run(success);
494 }
495
496 void ViewManagerServiceImpl::DispatchOnViewInputEvent(Id transport_view_id,
497                                                       EventPtr event) {
498   // We only allow the WM to dispatch events. At some point this function will
499   // move to a separate interface and the check can go away.
500   if (id_ != kWindowManagerConnection)
501     return;
502
503   const NodeId node_id(NodeIdFromTransportId(transport_view_id));
504
505   // If another app is embedded at this node, we forward the input event to the
506   // embedded app, rather than the app that created the node.
507   ViewManagerServiceImpl* connection =
508       root_node_manager_->GetConnectionWithRoot(node_id);
509   if (!connection)
510       connection = root_node_manager_->GetConnection(node_id.connection_id);
511   if (connection) {
512     connection->client()->OnViewInputEvent(
513         transport_view_id,
514         event.Pass(),
515         base::Bind(&base::DoNothing));
516   }
517 }
518
519 void ViewManagerServiceImpl::OnConnectionEstablished() {
520   root_node_manager_->AddConnection(this);
521
522   std::vector<const Node*> to_send;
523   for (NodeIdSet::const_iterator i = roots_.begin(); i != roots_.end(); ++i)
524     GetUnknownNodesFrom(GetNode(NodeIdFromTransportId(*i)), &to_send);
525
526   client()->OnEmbed(id_, creator_url_, NodeToViewData(to_send.front()),
527                     service_provider_.Pass());
528 }
529
530 const base::hash_set<Id>&
531 ViewManagerServiceImpl::GetRootsForAccessPolicy() const {
532   return roots_;
533 }
534
535 bool ViewManagerServiceImpl::IsNodeKnownForAccessPolicy(
536     const Node* node) const {
537   return IsNodeKnown(node);
538 }
539
540 bool ViewManagerServiceImpl::IsNodeRootOfAnotherConnectionForAccessPolicy(
541     const Node* node) const {
542   ViewManagerServiceImpl* connection =
543       root_node_manager_->GetConnectionWithRoot(node->id());
544   return connection && connection != this;
545 }
546
547 }  // namespace service
548 }  // namespace mojo