Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(366)

Side by Side Diff: mojo/services/view_manager/view_manager_service_impl.cc

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

Powered by Google App Engine
This is Rietveld 408576698