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.
5 #include "mojo/services/view_manager/view_manager_service_impl.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"
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()),
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));
40 access_policy_.reset(new DefaultAccessPolicy(id_, this));
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;
51 root_node_manager_->RemoveConnection(this);
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;
59 return root_node_manager_->GetNode(id);
62 bool ViewManagerServiceImpl::HasRoot(const NodeId& id) const {
63 return roots_.find(NodeIdToTransportId(id)) != roots_.end();
66 void ViewManagerServiceImpl::OnViewManagerServiceImplDestroyed(
67 ConnectionSpecificId id) {
68 if (creator_id_ == id)
69 creator_id_ = kInvalidConnectionId;
72 void ViewManagerServiceImpl::ProcessNodeBoundsChanged(
74 const gfx::Rect& old_bounds,
75 const gfx::Rect& new_bounds,
76 bool originated_change) {
77 if (originated_change || !IsNodeKnown(node))
79 client()->OnViewBoundsChanged(NodeIdToTransportId(node->id()),
80 Rect::From(old_bounds),
81 Rect::From(new_bounds));
84 void ViewManagerServiceImpl::ProcessNodeHierarchyChanged(
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);
94 if (originated_change || root_node_manager_->is_processing_delete_node() ||
95 root_node_manager_->DidConnectionMessageClient(id_)) {
99 if (!access_policy_->ShouldNotifyOnHierarchyChange(
100 node, &new_parent, &old_parent)) {
103 // Inform the client of any new nodes and update the set of nodes we know
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_);
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))
124 client()->OnViewReordered(NodeIdToTransportId(node->id()),
125 NodeIdToTransportId(relative_node->id()),
129 void ViewManagerServiceImpl::ProcessNodeDeleted(const NodeId& node,
130 bool originated_change) {
131 node_map_.erase(node.node_id);
133 const bool in_known = known_nodes_.erase(NodeIdToTransportId(node)) > 0;
134 roots_.erase(NodeIdToTransportId(node));
136 if (originated_change)
140 client()->OnViewDeleted(NodeIdToTransportId(node));
141 root_node_manager_->OnConnectionMessagedClient(id_);
145 void ViewManagerServiceImpl::OnConnectionError() {
146 if (delete_on_connection_error_)
150 bool ViewManagerServiceImpl::IsNodeKnown(const Node* node) const {
151 return known_nodes_.count(NodeIdToTransportId(node->id())) > 0;
154 bool ViewManagerServiceImpl::CanReorderNode(const Node* node,
155 const Node* relative_node,
156 OrderDirection direction) const {
157 if (!node || !relative_node)
160 const Node* parent = node->GetParent();
161 if (!parent || parent != relative_node->GetParent())
164 if (!access_policy_->CanReorderNode(node, relative_node, direction))
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) -
173 if ((direction == ORDER_DIRECTION_ABOVE && child_i == target_i + 1) ||
174 (direction == ORDER_DIRECTION_BELOW && child_i + 1 == target_i)) {
181 bool ViewManagerServiceImpl::DeleteNodeImpl(ViewManagerServiceImpl* source,
184 DCHECK_EQ(node->id().connection_id, id_);
185 RootNodeManager::ScopedChange change(source, root_node_manager_, true);
190 void ViewManagerServiceImpl::GetUnknownNodesFrom(
192 std::vector<const Node*>* nodes) {
193 if (IsNodeKnown(node) || !access_policy_->CanGetNodeTree(node))
195 nodes->push_back(node);
196 known_nodes_.insert(NodeIdToTransportId(node->id()));
197 if (!access_policy_->CanDescendIntoNodeForNodeTree(node))
199 std::vector<const Node*> children(node->GetChildren());
200 for (size_t i = 0 ; i < children.size(); ++i)
201 GetUnknownNodesFrom(children[i], nodes);
204 void ViewManagerServiceImpl::RemoveFromKnown(const Node* node,
205 std::vector<Node*>* local_nodes) {
206 if (node->id().connection_id == id_) {
208 local_nodes->push_back(GetNode(node->id()));
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);
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);
223 CHECK_EQ(creator_id_, node_id.connection_id);
224 roots_.insert(transport_node_id);
225 const Node* node = GetNode(node_id);
227 std::vector<const Node*> to_send;
228 if (!IsNodeKnown(node)) {
229 GetUnknownNodesFrom(node, &to_send);
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);
236 client()->OnEmbed(id_, creator_url_, NodeToViewData(to_send.front()),
237 service_provider.Pass());
238 root_node_manager_->OnConnectionMessagedClient(id_);
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);
245 roots_.erase(transport_node_id);
247 // No need to do anything if we created the node.
248 if (node_id.connection_id == id_)
251 client()->OnViewDeleted(transport_node_id);
252 root_node_manager_->OnConnectionMessagedClient(id_);
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]);
262 void ViewManagerServiceImpl::RemoveChildrenAsPartOfEmbed(
263 const NodeId& node_id) {
264 Node* node = GetNode(node_id);
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]);
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();
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))
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();
294 void ViewManagerServiceImpl::GetNodeTreeImpl(
296 std::vector<const Node*>* nodes) const {
299 if (!access_policy_->CanGetNodeTree(node))
302 nodes->push_back(node);
304 if (!access_policy_->CanDescendIntoNodeForNodeTree(node))
307 std::vector<const Node*> children(node->GetChildren());
308 for (size_t i = 0 ; i < children.size(); ++i)
309 GetNodeTreeImpl(children[i], nodes);
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;
322 node_map_[node_id.node_id] = new Node(root_node_manager_, node_id);
323 known_nodes_.insert(transport_view_id);
325 callback.Run(error_code);
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);
338 callback.Run(success);
341 void ViewManagerServiceImpl::AddView(
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)) {
351 RootNodeManager::ScopedChange change(this, root_node_manager_, false);
354 callback.Run(success);
357 void ViewManagerServiceImpl::RemoveViewFromParent(
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)) {
365 RootNodeManager::ScopedChange change(this, root_node_manager_, false);
366 node->GetParent()->Remove(node);
368 callback.Run(success);
371 void ViewManagerServiceImpl::ReorderView(Id 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)) {
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);
384 callback.Run(success);
387 void ViewManagerServiceImpl::GetViewTree(
389 const Callback<void(Array<ViewDataPtr>)>& callback) {
390 Node* node = GetNode(NodeIdFromTransportId(view_id));
391 std::vector<const Node*> nodes;
393 GetNodeTreeImpl(node, &nodes);
394 // TODO(sky): this should map in nodes that weren't none.
396 callback.Run(NodesToViewDatas(nodes));
399 void ViewManagerServiceImpl::SetViewContents(
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)) {
411 if (MapBuffer(buffer.get(), 0, buffer_size, &handle_data,
412 MOJO_MAP_BUFFER_FLAG_NONE) != MOJO_RESULT_OK) {
417 gfx::PNGCodec::Decode(static_cast<const unsigned char*>(handle_data),
418 buffer_size, &bitmap);
419 node->SetBitmap(bitmap);
420 UnmapBuffer(handle_data);
424 void ViewManagerServiceImpl::SetViewBounds(
427 const Callback<void(bool)>& callback) {
428 Node* node = GetNode(NodeIdFromTransportId(view_id));
429 const bool success = node && access_policy_->CanSetNodeBounds(node);
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>());
435 callback.Run(success);
438 void ViewManagerServiceImpl::SetViewVisibility(
439 Id transport_view_id,
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);
447 node->SetVisible(visible);
449 // TODO(sky): need to notify of visibility changes.
450 callback.Run(success);
453 void ViewManagerServiceImpl::Embed(
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());
461 if (NodeIdFromTransportId(transport_view_id) == InvalidNodeId()) {
462 root_node_manager_->EmbedRoot(url, spir.Pass());
466 const Node* node = GetNode(NodeIdFromTransportId(transport_view_id));
467 bool success = node && access_policy_->CanEmbed(node);
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());
487 root_node_manager_->Embed(id_, url, transport_view_id, spir.Pass());
493 callback.Run(success);
496 void ViewManagerServiceImpl::DispatchOnViewInputEvent(Id transport_view_id,
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)
503 const NodeId node_id(NodeIdFromTransportId(transport_view_id));
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);
510 connection = root_node_manager_->GetConnection(node_id.connection_id);
512 connection->client()->OnViewInputEvent(
515 base::Bind(&base::DoNothing));
519 void ViewManagerServiceImpl::OnConnectionEstablished() {
520 root_node_manager_->AddConnection(this);
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);
526 client()->OnEmbed(id_, creator_url_, NodeToViewData(to_send.front()),
527 service_provider_.Pass());
530 const base::hash_set<Id>&
531 ViewManagerServiceImpl::GetRootsForAccessPolicy() const {
535 bool ViewManagerServiceImpl::IsNodeKnownForAccessPolicy(
536 const Node* node) const {
537 return IsNodeKnown(node);
540 bool ViewManagerServiceImpl::IsNodeRootOfAnotherConnectionForAccessPolicy(
541 const Node* node) const {
542 ViewManagerServiceImpl* connection =
543 root_node_manager_->GetConnectionWithRoot(node->id());
544 return connection && connection != this;
547 } // namespace service