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