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 "components/view_manager/view_manager_service_impl.h"
8 #include "base/stl_util.h"
9 #include "components/view_manager/connection_manager.h"
10 #include "components/view_manager/default_access_policy.h"
11 #include "components/view_manager/display_manager.h"
12 #include "components/view_manager/server_view.h"
13 #include "components/view_manager/window_manager_access_policy.h"
14 #include "mojo/converters/geometry/geometry_type_converters.h"
15 #include "mojo/converters/input_events/input_events_type_converters.h"
16 #include "mojo/converters/surfaces/surfaces_type_converters.h"
21 using mojo::InterfaceRequest
;
22 using mojo::OrderDirection
;
24 using mojo::ServiceProvider
;
25 using mojo::ServiceProviderPtr
;
27 using mojo::ViewDataPtr
;
29 namespace view_manager
{
31 ViewManagerServiceImpl::ViewManagerServiceImpl(
32 ConnectionManager
* connection_manager
,
33 mojo::ConnectionSpecificId creator_id
,
34 const std::string
& creator_url
,
35 const std::string
& url
,
36 const ViewId
& root_id
)
37 : connection_manager_(connection_manager
),
38 id_(connection_manager_
->GetAndAdvanceNextConnectionId()),
40 creator_id_(creator_id
),
41 creator_url_(creator_url
),
43 CHECK(GetView(root_id
));
44 root_
.reset(new ViewId(root_id
));
45 if (root_id
== RootViewId())
46 access_policy_
.reset(new WindowManagerAccessPolicy(id_
, this));
48 access_policy_
.reset(new DefaultAccessPolicy(id_
, this));
51 ViewManagerServiceImpl::~ViewManagerServiceImpl() {
55 void ViewManagerServiceImpl::Init(mojo::ViewManagerClient
* client
,
56 mojo::ViewManagerServicePtr service_ptr
,
57 InterfaceRequest
<ServiceProvider
> services
,
58 ServiceProviderPtr exposed_services
) {
61 std::vector
<const ServerView
*> to_send
;
63 GetUnknownViewsFrom(GetView(*root_
), &to_send
);
65 const ServerView
* focused_view
= connection_manager_
->GetFocusedView();
67 focused_view
= access_policy_
->GetViewForFocusChange(focused_view
);
68 const mojo::Id
focused_view_transport_id(
69 ViewIdToTransportId(focused_view
? focused_view
->id() : ViewId()));
71 client
->OnEmbed(id_
, creator_url_
, ViewToViewData(to_send
.front()),
72 service_ptr
.Pass(), services
.Pass(), exposed_services
.Pass(),
73 focused_view_transport_id
);
76 const ServerView
* ViewManagerServiceImpl::GetView(const ViewId
& id
) const {
77 if (id_
== id
.connection_id
) {
78 ViewMap::const_iterator i
= view_map_
.find(id
.view_id
);
79 return i
== view_map_
.end() ? NULL
: i
->second
;
81 return connection_manager_
->GetView(id
);
84 bool ViewManagerServiceImpl::IsRoot(const ViewId
& id
) const {
85 return root_
.get() && *root_
== id
;
88 void ViewManagerServiceImpl::OnWillDestroyViewManagerServiceImpl(
89 ViewManagerServiceImpl
* connection
) {
90 if (creator_id_
== connection
->id())
91 creator_id_
= kInvalidConnectionId
;
92 if (connection
->root_
&& connection
->root_
->connection_id
== id_
&&
93 view_map_
.count(connection
->root_
->view_id
) > 0) {
94 client()->OnEmbeddedAppDisconnected(
95 ViewIdToTransportId(*connection
->root_
));
97 if (root_
.get() && root_
->connection_id
== connection
->id())
101 mojo::ErrorCode
ViewManagerServiceImpl::CreateView(const ViewId
& view_id
) {
102 if (view_id
.connection_id
!= id_
)
103 return mojo::ERROR_CODE_ILLEGAL_ARGUMENT
;
104 if (view_map_
.find(view_id
.view_id
) != view_map_
.end())
105 return mojo::ERROR_CODE_VALUE_IN_USE
;
106 view_map_
[view_id
.view_id
] = connection_manager_
->CreateServerView(view_id
);
107 known_views_
.insert(ViewIdToTransportId(view_id
));
108 return mojo::ERROR_CODE_NONE
;
111 bool ViewManagerServiceImpl::AddView(const ViewId
& parent_id
,
112 const ViewId
& child_id
) {
113 ServerView
* parent
= GetView(parent_id
);
114 ServerView
* child
= GetView(child_id
);
115 if (parent
&& child
&& child
->parent() != parent
&&
116 !child
->Contains(parent
) && access_policy_
->CanAddView(parent
, child
)) {
117 ConnectionManager::ScopedChange
change(this, connection_manager_
, false);
124 std::vector
<const ServerView
*> ViewManagerServiceImpl::GetViewTree(
125 const ViewId
& view_id
) const {
126 const ServerView
* view
= GetView(view_id
);
127 std::vector
<const ServerView
*> views
;
129 GetViewTreeImpl(view
, &views
);
133 bool ViewManagerServiceImpl::SetViewVisibility(const ViewId
& view_id
,
135 ServerView
* view
= GetView(view_id
);
136 if (!view
|| view
->visible() == visible
||
137 !access_policy_
->CanChangeViewVisibility(view
)) {
140 ConnectionManager::ScopedChange
change(this, connection_manager_
, false);
141 view
->SetVisible(visible
);
145 bool ViewManagerServiceImpl::EmbedUrl(
146 const std::string
& url
,
147 const ViewId
& view_id
,
148 InterfaceRequest
<ServiceProvider
> services
,
149 ServiceProviderPtr exposed_services
) {
150 if (!PrepareForEmbed(view_id
))
152 connection_manager_
->EmbedAtView(id_
, url
, view_id
, services
.Pass(),
153 exposed_services
.Pass());
157 bool ViewManagerServiceImpl::Embed(const ViewId
& view_id
,
158 mojo::ViewManagerClientPtr client
) {
159 if (!client
.get() || !PrepareForEmbed(view_id
))
161 connection_manager_
->EmbedAtView(id_
, view_id
, client
.Pass());
165 void ViewManagerServiceImpl::ProcessViewBoundsChanged(
166 const ServerView
* view
,
167 const gfx::Rect
& old_bounds
,
168 const gfx::Rect
& new_bounds
,
169 bool originated_change
) {
170 if (originated_change
|| !IsViewKnown(view
))
172 client()->OnViewBoundsChanged(ViewIdToTransportId(view
->id()),
173 Rect::From(old_bounds
),
174 Rect::From(new_bounds
));
177 void ViewManagerServiceImpl::ProcessViewportMetricsChanged(
178 const mojo::ViewportMetrics
& old_metrics
,
179 const mojo::ViewportMetrics
& new_metrics
,
180 bool originated_change
) {
181 client()->OnViewViewportMetricsChanged(old_metrics
.Clone(),
182 new_metrics
.Clone());
185 void ViewManagerServiceImpl::ProcessWillChangeViewHierarchy(
186 const ServerView
* view
,
187 const ServerView
* new_parent
,
188 const ServerView
* old_parent
,
189 bool originated_change
) {
190 if (originated_change
)
193 const bool old_drawn
= view
->IsDrawn(connection_manager_
->root());
194 const bool new_drawn
= view
->visible() && new_parent
&&
195 new_parent
->IsDrawn(connection_manager_
->root());
196 if (old_drawn
== new_drawn
)
199 NotifyDrawnStateChanged(view
, new_drawn
);
202 void ViewManagerServiceImpl::ProcessViewPropertyChanged(
203 const ServerView
* view
,
204 const std::string
& name
,
205 const std::vector
<uint8_t>* new_data
,
206 bool originated_change
) {
207 if (originated_change
)
212 data
= Array
<uint8_t>::From(*new_data
);
214 client()->OnViewSharedPropertyChanged(ViewIdToTransportId(view
->id()),
215 String(name
), data
.Pass());
218 void ViewManagerServiceImpl::ProcessViewHierarchyChanged(
219 const ServerView
* view
,
220 const ServerView
* new_parent
,
221 const ServerView
* old_parent
,
222 bool originated_change
) {
223 if (originated_change
&& !IsViewKnown(view
) && new_parent
&&
224 IsViewKnown(new_parent
)) {
225 std::vector
<const ServerView
*> unused
;
226 GetUnknownViewsFrom(view
, &unused
);
228 if (originated_change
|| connection_manager_
->is_processing_delete_view() ||
229 connection_manager_
->DidConnectionMessageClient(id_
)) {
233 if (!access_policy_
->ShouldNotifyOnHierarchyChange(
234 view
, &new_parent
, &old_parent
)) {
237 // Inform the client of any new views and update the set of views we know
239 std::vector
<const ServerView
*> to_send
;
240 if (!IsViewKnown(view
))
241 GetUnknownViewsFrom(view
, &to_send
);
242 const ViewId
new_parent_id(new_parent
? new_parent
->id() : ViewId());
243 const ViewId
old_parent_id(old_parent
? old_parent
->id() : ViewId());
244 client()->OnViewHierarchyChanged(ViewIdToTransportId(view
->id()),
245 ViewIdToTransportId(new_parent_id
),
246 ViewIdToTransportId(old_parent_id
),
247 ViewsToViewDatas(to_send
));
248 connection_manager_
->OnConnectionMessagedClient(id_
);
251 void ViewManagerServiceImpl::ProcessViewReorder(const ServerView
* view
,
252 const ServerView
* relative_view
,
253 OrderDirection direction
,
254 bool originated_change
) {
255 if (originated_change
|| !IsViewKnown(view
) || !IsViewKnown(relative_view
))
258 client()->OnViewReordered(ViewIdToTransportId(view
->id()),
259 ViewIdToTransportId(relative_view
->id()),
263 void ViewManagerServiceImpl::ProcessViewDeleted(const ViewId
& view
,
264 bool originated_change
) {
265 if (view
.connection_id
== id_
)
266 view_map_
.erase(view
.view_id
);
268 const bool in_known
= known_views_
.erase(ViewIdToTransportId(view
)) > 0;
273 if (originated_change
)
277 client()->OnViewDeleted(ViewIdToTransportId(view
));
278 connection_manager_
->OnConnectionMessagedClient(id_
);
282 void ViewManagerServiceImpl::ProcessWillChangeViewVisibility(
283 const ServerView
* view
,
284 bool originated_change
) {
285 if (originated_change
)
288 if (IsViewKnown(view
)) {
289 client()->OnViewVisibilityChanged(ViewIdToTransportId(view
->id()),
294 bool view_target_drawn_state
;
295 if (view
->visible()) {
296 // View is being hidden, won't be drawn.
297 view_target_drawn_state
= false;
299 // View is being shown. View will be drawn if its parent is drawn.
300 view_target_drawn_state
=
301 view
->parent() && view
->parent()->IsDrawn(connection_manager_
->root());
304 NotifyDrawnStateChanged(view
, view_target_drawn_state
);
307 void ViewManagerServiceImpl::ProcessFocusChanged(
308 const ServerView
* old_focused_view
,
309 const ServerView
* new_focused_view
) {
310 const ServerView
* view
=
311 new_focused_view
? access_policy_
->GetViewForFocusChange(new_focused_view
)
313 client()->OnViewFocused(view
? ViewIdToTransportId(view
->id())
314 : ViewIdToTransportId(ViewId()));
317 bool ViewManagerServiceImpl::IsViewKnown(const ServerView
* view
) const {
318 return known_views_
.count(ViewIdToTransportId(view
->id())) > 0;
321 bool ViewManagerServiceImpl::CanReorderView(const ServerView
* view
,
322 const ServerView
* relative_view
,
323 OrderDirection direction
) const {
324 if (!view
|| !relative_view
)
327 if (!view
->parent() || view
->parent() != relative_view
->parent())
330 if (!access_policy_
->CanReorderView(view
, relative_view
, direction
))
333 std::vector
<const ServerView
*> children
= view
->parent()->GetChildren();
334 const size_t child_i
=
335 std::find(children
.begin(), children
.end(), view
) - children
.begin();
336 const size_t target_i
=
337 std::find(children
.begin(), children
.end(), relative_view
) -
339 if ((direction
== mojo::ORDER_DIRECTION_ABOVE
&& child_i
== target_i
+ 1) ||
340 (direction
== mojo::ORDER_DIRECTION_BELOW
&& child_i
+ 1 == target_i
)) {
347 bool ViewManagerServiceImpl::DeleteViewImpl(ViewManagerServiceImpl
* source
,
350 DCHECK_EQ(view
->id().connection_id
, id_
);
351 ConnectionManager::ScopedChange
change(source
, connection_manager_
, true);
356 void ViewManagerServiceImpl::GetUnknownViewsFrom(
357 const ServerView
* view
,
358 std::vector
<const ServerView
*>* views
) {
359 if (IsViewKnown(view
) || !access_policy_
->CanGetViewTree(view
))
361 views
->push_back(view
);
362 known_views_
.insert(ViewIdToTransportId(view
->id()));
363 if (!access_policy_
->CanDescendIntoViewForViewTree(view
))
365 std::vector
<const ServerView
*> children(view
->GetChildren());
366 for (size_t i
= 0 ; i
< children
.size(); ++i
)
367 GetUnknownViewsFrom(children
[i
], views
);
370 void ViewManagerServiceImpl::RemoveFromKnown(
371 const ServerView
* view
,
372 std::vector
<ServerView
*>* local_views
) {
373 if (view
->id().connection_id
== id_
) {
375 local_views
->push_back(GetView(view
->id()));
378 known_views_
.erase(ViewIdToTransportId(view
->id()));
379 std::vector
<const ServerView
*> children
= view
->GetChildren();
380 for (size_t i
= 0; i
< children
.size(); ++i
)
381 RemoveFromKnown(children
[i
], local_views
);
384 void ViewManagerServiceImpl::RemoveRoot() {
386 const ViewId
root_id(*root_
);
388 // No need to do anything if we created the view.
389 if (root_id
.connection_id
== id_
)
392 client()->OnViewDeleted(ViewIdToTransportId(root_id
));
393 connection_manager_
->OnConnectionMessagedClient(id_
);
395 // This connection no longer knows about the view. Unparent any views that
396 // were parented to views in the root.
397 std::vector
<ServerView
*> local_views
;
398 RemoveFromKnown(GetView(root_id
), &local_views
);
399 for (size_t i
= 0; i
< local_views
.size(); ++i
)
400 local_views
[i
]->parent()->Remove(local_views
[i
]);
403 void ViewManagerServiceImpl::RemoveChildrenAsPartOfEmbed(
404 const ViewId
& view_id
) {
405 ServerView
* view
= GetView(view_id
);
407 CHECK(view
->id().connection_id
== view_id
.connection_id
);
408 std::vector
<ServerView
*> children
= view
->GetChildren();
409 for (size_t i
= 0; i
< children
.size(); ++i
)
410 view
->Remove(children
[i
]);
413 Array
<ViewDataPtr
> ViewManagerServiceImpl::ViewsToViewDatas(
414 const std::vector
<const ServerView
*>& views
) {
415 Array
<ViewDataPtr
> array(views
.size());
416 for (size_t i
= 0; i
< views
.size(); ++i
)
417 array
[i
] = ViewToViewData(views
[i
]).Pass();
421 ViewDataPtr
ViewManagerServiceImpl::ViewToViewData(const ServerView
* view
) {
422 DCHECK(IsViewKnown(view
));
423 const ServerView
* parent
= view
->parent();
424 // If the parent isn't known, it means the parent is not visible to us (not
425 // in roots), and should not be sent over.
426 if (parent
&& !IsViewKnown(parent
))
428 ViewDataPtr
view_data(mojo::ViewData::New());
429 view_data
->parent_id
= ViewIdToTransportId(parent
? parent
->id() : ViewId());
430 view_data
->view_id
= ViewIdToTransportId(view
->id());
431 view_data
->bounds
= Rect::From(view
->bounds());
432 view_data
->properties
=
433 mojo::Map
<String
, Array
<uint8_t>>::From(view
->properties());
434 view_data
->visible
= view
->visible();
435 view_data
->drawn
= view
->IsDrawn(connection_manager_
->root());
436 view_data
->viewport_metrics
=
437 connection_manager_
->display_manager()->GetViewportMetrics().Clone();
438 return view_data
.Pass();
441 void ViewManagerServiceImpl::GetViewTreeImpl(
442 const ServerView
* view
,
443 std::vector
<const ServerView
*>* views
) const {
446 if (!access_policy_
->CanGetViewTree(view
))
449 views
->push_back(view
);
451 if (!access_policy_
->CanDescendIntoViewForViewTree(view
))
454 std::vector
<const ServerView
*> children(view
->GetChildren());
455 for (size_t i
= 0 ; i
< children
.size(); ++i
)
456 GetViewTreeImpl(children
[i
], views
);
459 void ViewManagerServiceImpl::NotifyDrawnStateChanged(const ServerView
* view
,
460 bool new_drawn_value
) {
461 // Even though we don't know about view, it may be an ancestor of our root, in
462 // which case the change may effect our roots drawn state.
466 const ServerView
* root
= GetView(*root_
);
468 if (view
->Contains(root
) &&
469 (new_drawn_value
!= root
->IsDrawn(connection_manager_
->root()))) {
470 client()->OnViewDrawnStateChanged(ViewIdToTransportId(root
->id()),
475 void ViewManagerServiceImpl::DestroyViews() {
476 if (!view_map_
.empty()) {
477 ConnectionManager::ScopedChange
change(this, connection_manager_
, true);
478 // If we get here from the destructor we're not going to get
479 // ProcessViewDeleted(). Copy the map and delete from the copy so that we
480 // don't have to worry about whether |view_map_| changes or not.
481 ViewMap view_map_copy
;
482 view_map_
.swap(view_map_copy
);
483 STLDeleteValues(&view_map_copy
);
487 bool ViewManagerServiceImpl::PrepareForEmbed(const ViewId
& view_id
) {
488 const ServerView
* view
= GetView(view_id
);
489 if (!view
|| !access_policy_
->CanEmbed(view
))
492 // Only allow a node to be the root for one connection.
493 ViewManagerServiceImpl
* existing_owner
=
494 connection_manager_
->GetConnectionWithRoot(view_id
);
496 ConnectionManager::ScopedChange
change(this, connection_manager_
, true);
497 RemoveChildrenAsPartOfEmbed(view_id
);
498 if (existing_owner
) {
499 // Never message the originating connection.
500 connection_manager_
->OnConnectionMessagedClient(id_
);
501 existing_owner
->RemoveRoot();
506 void ViewManagerServiceImpl::CreateView(
507 Id transport_view_id
,
508 const Callback
<void(mojo::ErrorCode
)>& callback
) {
509 callback
.Run(CreateView(ViewIdFromTransportId(transport_view_id
)));
512 void ViewManagerServiceImpl::DeleteView(
513 Id transport_view_id
,
514 const Callback
<void(bool)>& callback
) {
515 ServerView
* view
= GetView(ViewIdFromTransportId(transport_view_id
));
516 bool success
= false;
517 if (view
&& access_policy_
->CanDeleteView(view
)) {
518 ViewManagerServiceImpl
* connection
=
519 connection_manager_
->GetConnection(view
->id().connection_id
);
520 success
= connection
&& connection
->DeleteViewImpl(this, view
);
522 callback
.Run(success
);
525 void ViewManagerServiceImpl::AddView(
528 const Callback
<void(bool)>& callback
) {
529 callback
.Run(AddView(ViewIdFromTransportId(parent_id
),
530 ViewIdFromTransportId(child_id
)));
533 void ViewManagerServiceImpl::RemoveViewFromParent(
535 const Callback
<void(bool)>& callback
) {
536 bool success
= false;
537 ServerView
* view
= GetView(ViewIdFromTransportId(view_id
));
538 if (view
&& view
->parent() && access_policy_
->CanRemoveViewFromParent(view
)) {
540 ConnectionManager::ScopedChange
change(this, connection_manager_
, false);
541 view
->parent()->Remove(view
);
543 callback
.Run(success
);
546 void ViewManagerServiceImpl::ReorderView(Id view_id
,
548 OrderDirection direction
,
549 const Callback
<void(bool)>& callback
) {
550 bool success
= false;
551 ServerView
* view
= GetView(ViewIdFromTransportId(view_id
));
552 ServerView
* relative_view
= GetView(ViewIdFromTransportId(relative_view_id
));
553 if (CanReorderView(view
, relative_view
, direction
)) {
555 ConnectionManager::ScopedChange
change(this, connection_manager_
, false);
556 view
->parent()->Reorder(view
, relative_view
, direction
);
557 connection_manager_
->ProcessViewReorder(view
, relative_view
, direction
);
559 callback
.Run(success
);
562 void ViewManagerServiceImpl::GetViewTree(
564 const Callback
<void(Array
<ViewDataPtr
>)>& callback
) {
565 std::vector
<const ServerView
*> views(
566 GetViewTree(ViewIdFromTransportId(view_id
)));
567 callback
.Run(ViewsToViewDatas(views
));
570 void ViewManagerServiceImpl::SetViewSurfaceId(
572 mojo::SurfaceIdPtr surface_id
,
573 const Callback
<void(bool)>& callback
) {
574 // TODO(sky): add coverage of not being able to set for random node.
575 ServerView
* view
= GetView(ViewIdFromTransportId(view_id
));
576 if (!view
|| !access_policy_
->CanSetViewSurfaceId(view
)) {
580 view
->SetSurfaceId(surface_id
.To
<cc::SurfaceId
>());
584 void ViewManagerServiceImpl::SetViewBounds(
586 mojo::RectPtr bounds
,
587 const Callback
<void(bool)>& callback
) {
588 ServerView
* view
= GetView(ViewIdFromTransportId(view_id
));
589 const bool success
= view
&& access_policy_
->CanSetViewBounds(view
);
591 ConnectionManager::ScopedChange
change(this, connection_manager_
, false);
592 view
->SetBounds(bounds
.To
<gfx::Rect
>());
594 callback
.Run(success
);
597 void ViewManagerServiceImpl::SetViewVisibility(
598 Id transport_view_id
,
600 const Callback
<void(bool)>& callback
) {
602 SetViewVisibility(ViewIdFromTransportId(transport_view_id
), visible
));
605 void ViewManagerServiceImpl::SetViewProperty(
607 const mojo::String
& name
,
608 mojo::Array
<uint8_t> value
,
609 const mojo::Callback
<void(bool)>& callback
) {
610 ServerView
* view
= GetView(ViewIdFromTransportId(view_id
));
611 const bool success
= view
&& access_policy_
->CanSetViewProperties(view
);
613 ConnectionManager::ScopedChange
change(this, connection_manager_
, false);
615 if (value
.is_null()) {
616 view
->SetProperty(name
, nullptr);
618 std::vector
<uint8_t> data
= value
.To
<std::vector
<uint8_t>>();
619 view
->SetProperty(name
, &data
);
622 callback
.Run(success
);
625 void ViewManagerServiceImpl::EmbedUrl(
627 Id transport_view_id
,
628 InterfaceRequest
<ServiceProvider
> services
,
629 ServiceProviderPtr exposed_services
,
630 const Callback
<void(bool)>& callback
) {
631 callback
.Run(EmbedUrl(url
.To
<std::string
>(),
632 ViewIdFromTransportId(transport_view_id
),
633 services
.Pass(), exposed_services
.Pass()));
636 void ViewManagerServiceImpl::Embed(mojo::Id transport_view_id
,
637 mojo::ViewManagerClientPtr client
,
638 const mojo::Callback
<void(bool)>& callback
) {
639 callback
.Run(Embed(ViewIdFromTransportId(transport_view_id
), client
.Pass()));
642 void ViewManagerServiceImpl::SetFocus(uint32_t view_id
,
643 const SetFocusCallback
& callback
) {
644 ServerView
* view
= GetView(ViewIdFromTransportId(view_id
));
645 bool success
= view
&& view
->IsDrawn(connection_manager_
->root()) &&
646 access_policy_
->CanSetFocus(view
);
648 ConnectionManager::ScopedChange
change(this, connection_manager_
, false);
649 connection_manager_
->SetFocusedView(view
);
651 callback
.Run(success
);
654 bool ViewManagerServiceImpl::IsRootForAccessPolicy(const ViewId
& id
) const {
658 bool ViewManagerServiceImpl::IsViewKnownForAccessPolicy(
659 const ServerView
* view
) const {
660 return IsViewKnown(view
);
663 bool ViewManagerServiceImpl::IsViewRootOfAnotherConnectionForAccessPolicy(
664 const ServerView
* view
) const {
665 ViewManagerServiceImpl
* connection
=
666 connection_manager_
->GetConnectionWithRoot(view
->id());
667 return connection
&& connection
!= this;
670 } // namespace view_manager