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

Side by Side Diff: mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.cc

Issue 790623003: Restructure public side of view_manager service. (Closed) Base URL: https://github.com/domokit/mojo.git@master
Patch Set: BUILD.gn file reorderings 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/public/cpp/view_manager/lib/view_manager_client_impl.h"
6
7 #include "base/bind.h"
8 #include "base/message_loop/message_loop.h"
9 #include "base/stl_util.h"
10 #include "mojo/public/cpp/application/application_impl.h"
11 #include "mojo/public/cpp/application/connect.h"
12 #include "mojo/public/cpp/application/service_provider_impl.h"
13 #include "mojo/public/interfaces/application/service_provider.mojom.h"
14 #include "mojo/public/interfaces/application/shell.mojom.h"
15 #include "mojo/services/public/cpp/view_manager/lib/view_private.h"
16 #include "mojo/services/public/cpp/view_manager/util.h"
17 #include "mojo/services/public/cpp/view_manager/view_manager_delegate.h"
18 #include "mojo/services/public/cpp/view_manager/view_observer.h"
19
20 namespace mojo {
21
22 Id MakeTransportId(ConnectionSpecificId connection_id,
23 ConnectionSpecificId local_id) {
24 return (connection_id << 16) | local_id;
25 }
26
27 // Helper called to construct a local view object from transport data.
28 View* AddViewToViewManager(ViewManagerClientImpl* client,
29 View* parent,
30 const ViewDataPtr& view_data) {
31 // We don't use the ctor that takes a ViewManager here, since it will call
32 // back to the service and attempt to create a new view.
33 View* view = ViewPrivate::LocalCreate();
34 ViewPrivate private_view(view);
35 private_view.set_view_manager(client);
36 private_view.set_id(view_data->view_id);
37 private_view.set_visible(view_data->visible);
38 private_view.set_drawn(view_data->drawn);
39 private_view.set_properties(
40 view_data->properties.To<std::map<std::string, std::vector<uint8_t>>>());
41 client->AddView(view);
42 private_view.LocalSetBounds(Rect(), *view_data->bounds);
43 if (parent)
44 ViewPrivate(parent).LocalAddChild(view);
45 return view;
46 }
47
48 View* BuildViewTree(ViewManagerClientImpl* client,
49 const Array<ViewDataPtr>& views,
50 View* initial_parent) {
51 std::vector<View*> parents;
52 View* root = NULL;
53 View* last_view = NULL;
54 if (initial_parent)
55 parents.push_back(initial_parent);
56 for (size_t i = 0; i < views.size(); ++i) {
57 if (last_view && views[i]->parent_id == last_view->id()) {
58 parents.push_back(last_view);
59 } else if (!parents.empty()) {
60 while (parents.back()->id() != views[i]->parent_id)
61 parents.pop_back();
62 }
63 View* view = AddViewToViewManager(
64 client, !parents.empty() ? parents.back() : NULL, views[i]);
65 if (!last_view)
66 root = view;
67 last_view = view;
68 }
69 return root;
70 }
71
72 // Responsible for removing a root from the ViewManager when that view is
73 // destroyed.
74 class RootObserver : public ViewObserver {
75 public:
76 explicit RootObserver(View* root) : root_(root) {}
77 ~RootObserver() override {}
78
79 private:
80 // Overridden from ViewObserver:
81 void OnViewDestroyed(View* view) override {
82 DCHECK_EQ(view, root_);
83 static_cast<ViewManagerClientImpl*>(
84 ViewPrivate(root_).view_manager())->RemoveRoot(root_);
85 view->RemoveObserver(this);
86 delete this;
87 }
88
89 View* root_;
90
91 DISALLOW_COPY_AND_ASSIGN(RootObserver);
92 };
93
94 ViewManagerClientImpl::ViewManagerClientImpl(ViewManagerDelegate* delegate,
95 Shell* shell,
96 ScopedMessagePipeHandle handle,
97 bool delete_on_error)
98 : connected_(false),
99 connection_id_(0),
100 next_id_(1),
101 delegate_(delegate),
102 binding_(this, handle.Pass()),
103 service_(binding_.client()),
104 delete_on_error_(delete_on_error) {
105 }
106
107 ViewManagerClientImpl::~ViewManagerClientImpl() {
108 std::vector<View*> non_owned;
109 while (!views_.empty()) {
110 IdToViewMap::iterator it = views_.begin();
111 if (OwnsView(it->second->id())) {
112 it->second->Destroy();
113 } else {
114 non_owned.push_back(it->second);
115 views_.erase(it);
116 }
117 }
118 // Delete the non-owned views last. In the typical case these are roots. The
119 // exception is the window manager, which may know aboutother random views
120 // that it doesn't own.
121 // NOTE: we manually delete as we're a friend.
122 for (size_t i = 0; i < non_owned.size(); ++i)
123 delete non_owned[i];
124
125 delegate_->OnViewManagerDisconnected(this);
126 }
127
128 Id ViewManagerClientImpl::CreateView() {
129 DCHECK(connected_);
130 const Id view_id = MakeTransportId(connection_id_, ++next_id_);
131 service_->CreateView(view_id, ActionCompletedCallbackWithErrorCode());
132 return view_id;
133 }
134
135 void ViewManagerClientImpl::DestroyView(Id view_id) {
136 DCHECK(connected_);
137 service_->DeleteView(view_id, ActionCompletedCallback());
138 }
139
140 void ViewManagerClientImpl::AddChild(Id child_id, Id parent_id) {
141 DCHECK(connected_);
142 service_->AddView(parent_id, child_id, ActionCompletedCallback());
143 }
144
145 void ViewManagerClientImpl::RemoveChild(Id child_id, Id parent_id) {
146 DCHECK(connected_);
147 service_->RemoveViewFromParent(child_id, ActionCompletedCallback());
148 }
149
150 void ViewManagerClientImpl::Reorder(
151 Id view_id,
152 Id relative_view_id,
153 OrderDirection direction) {
154 DCHECK(connected_);
155 service_->ReorderView(view_id, relative_view_id, direction,
156 ActionCompletedCallback());
157 }
158
159 bool ViewManagerClientImpl::OwnsView(Id id) const {
160 return HiWord(id) == connection_id_;
161 }
162
163 void ViewManagerClientImpl::SetBounds(Id view_id, const Rect& bounds) {
164 DCHECK(connected_);
165 service_->SetViewBounds(view_id, bounds.Clone(), ActionCompletedCallback());
166 }
167
168 void ViewManagerClientImpl::SetSurfaceId(Id view_id, SurfaceIdPtr surface_id) {
169 DCHECK(connected_);
170 if (surface_id.is_null())
171 return;
172 service_->SetViewSurfaceId(
173 view_id, surface_id.Pass(), ActionCompletedCallback());
174 }
175
176 void ViewManagerClientImpl::SetFocus(Id view_id) {
177 // In order for us to get here we had to have exposed a view, which implies we
178 // got a connection.
179 DCHECK(window_manager_.get());
180 window_manager_->FocusWindow(view_id, ActionCompletedCallback());
181 }
182
183 void ViewManagerClientImpl::SetVisible(Id view_id, bool visible) {
184 DCHECK(connected_);
185 service_->SetViewVisibility(view_id, visible, ActionCompletedCallback());
186 }
187
188 void ViewManagerClientImpl::SetProperty(
189 Id view_id,
190 const std::string& name,
191 const std::vector<uint8_t>& data) {
192 DCHECK(connected_);
193 service_->SetViewProperty(view_id,
194 String(name),
195 Array<uint8_t>::From(data),
196 ActionCompletedCallback());
197 }
198
199 void ViewManagerClientImpl::Embed(const String& url, Id view_id) {
200 ServiceProviderPtr sp;
201 BindToProxy(new ServiceProviderImpl, &sp);
202 Embed(url, view_id, sp.Pass());
203 }
204
205 void ViewManagerClientImpl::Embed(
206 const String& url,
207 Id view_id,
208 ServiceProviderPtr service_provider) {
209 DCHECK(connected_);
210 service_->Embed(url, view_id,
211 MakeRequest<ServiceProvider>(service_provider.PassMessagePipe()),
212 ActionCompletedCallback());
213 }
214
215 void ViewManagerClientImpl::AddView(View* view) {
216 DCHECK(views_.find(view->id()) == views_.end());
217 views_[view->id()] = view;
218 }
219
220 void ViewManagerClientImpl::RemoveView(Id view_id) {
221 IdToViewMap::iterator it = views_.find(view_id);
222 if (it != views_.end())
223 views_.erase(it);
224 }
225
226 ////////////////////////////////////////////////////////////////////////////////
227 // ViewManagerClientImpl, ViewManager implementation:
228
229 const std::string& ViewManagerClientImpl::GetEmbedderURL() const {
230 return creator_url_;
231 }
232
233 const std::vector<View*>& ViewManagerClientImpl::GetRoots() const {
234 return roots_;
235 }
236
237 View* ViewManagerClientImpl::GetViewById(Id id) {
238 IdToViewMap::const_iterator it = views_.find(id);
239 return it != views_.end() ? it->second : NULL;
240 }
241
242 ////////////////////////////////////////////////////////////////////////////////
243 // ViewManagerClientImpl, ViewManagerClient implementation:
244
245 void ViewManagerClientImpl::OnEmbed(
246 ConnectionSpecificId connection_id,
247 const String& creator_url,
248 ViewDataPtr root_data,
249 InterfaceRequest<ServiceProvider> parent_services,
250 ScopedMessagePipeHandle window_manager_pipe) {
251 if (!connected_) {
252 connected_ = true;
253 connection_id_ = connection_id;
254 creator_url_ = String::From(creator_url);
255 } else {
256 DCHECK_EQ(connection_id_, connection_id);
257 DCHECK_EQ(creator_url_, creator_url);
258 }
259
260 // A new root must not already exist as a root or be contained by an existing
261 // hierarchy visible to this view manager.
262 View* root = AddViewToViewManager(this, NULL, root_data);
263 roots_.push_back(root);
264 root->AddObserver(new RootObserver(root));
265
266 ServiceProviderImpl* exported_services = nullptr;
267 scoped_ptr<ServiceProvider> remote;
268
269 if (parent_services.is_pending()) {
270 // BindToRequest() binds the lifetime of |exported_services| to the pipe.
271 exported_services = new ServiceProviderImpl;
272 BindToRequest(exported_services, &parent_services);
273 remote.reset(exported_services->CreateRemoteServiceProvider());
274 }
275 window_manager_.Bind(window_manager_pipe.Pass());
276 window_manager_.set_client(this);
277 delegate_->OnEmbed(this, root, exported_services, remote.Pass());
278 }
279
280 void ViewManagerClientImpl::OnEmbeddedAppDisconnected(Id view_id) {
281 View* view = GetViewById(view_id);
282 if (view) {
283 FOR_EACH_OBSERVER(ViewObserver, *ViewPrivate(view).observers(),
284 OnViewEmbeddedAppDisconnected(view));
285 }
286 }
287
288 void ViewManagerClientImpl::OnViewBoundsChanged(Id view_id,
289 RectPtr old_bounds,
290 RectPtr new_bounds) {
291 View* view = GetViewById(view_id);
292 ViewPrivate(view).LocalSetBounds(*old_bounds, *new_bounds);
293 }
294
295 void ViewManagerClientImpl::OnViewHierarchyChanged(
296 Id view_id,
297 Id new_parent_id,
298 Id old_parent_id,
299 mojo::Array<ViewDataPtr> views) {
300 View* initial_parent = views.size() ?
301 GetViewById(views[0]->parent_id) : NULL;
302
303 BuildViewTree(this, views, initial_parent);
304
305 View* new_parent = GetViewById(new_parent_id);
306 View* old_parent = GetViewById(old_parent_id);
307 View* view = GetViewById(view_id);
308 if (new_parent)
309 ViewPrivate(new_parent).LocalAddChild(view);
310 else
311 ViewPrivate(old_parent).LocalRemoveChild(view);
312 }
313
314 void ViewManagerClientImpl::OnViewReordered(Id view_id,
315 Id relative_view_id,
316 OrderDirection direction) {
317 View* view = GetViewById(view_id);
318 View* relative_view = GetViewById(relative_view_id);
319 if (view && relative_view)
320 ViewPrivate(view).LocalReorder(relative_view, direction);
321 }
322
323 void ViewManagerClientImpl::OnViewDeleted(Id view_id) {
324 View* view = GetViewById(view_id);
325 if (view)
326 ViewPrivate(view).LocalDestroy();
327 }
328
329 void ViewManagerClientImpl::OnViewVisibilityChanged(Id view_id, bool visible) {
330 // TODO(sky): there is a race condition here. If this client and another
331 // client change the visibility at the same time the wrong value may be set.
332 // Deal with this some how.
333 View* view = GetViewById(view_id);
334 if (view)
335 view->SetVisible(visible);
336 }
337
338 void ViewManagerClientImpl::OnViewDrawnStateChanged(Id view_id, bool drawn) {
339 View* view = GetViewById(view_id);
340 if (view)
341 ViewPrivate(view).LocalSetDrawn(drawn);
342 }
343
344 void ViewManagerClientImpl::OnViewSharedPropertyChanged(
345 Id view_id,
346 const String& name,
347 Array<uint8_t> new_data) {
348 View* view = GetViewById(view_id);
349 if (view) {
350 std::vector<uint8_t> data;
351 std::vector<uint8_t>* data_ptr = NULL;
352 if (!new_data.is_null()) {
353 data = new_data.To<std::vector<uint8_t>>();
354 data_ptr = &data;
355 }
356
357 view->SetSharedProperty(name, data_ptr);
358 }
359 }
360
361 void ViewManagerClientImpl::OnViewInputEvent(
362 Id view_id,
363 EventPtr event,
364 const Callback<void()>& ack_callback) {
365 View* view = GetViewById(view_id);
366 if (view) {
367 FOR_EACH_OBSERVER(ViewObserver,
368 *ViewPrivate(view).observers(),
369 OnViewInputEvent(view, event));
370 }
371 ack_callback.Run();
372 }
373
374 ////////////////////////////////////////////////////////////////////////////////
375 // ViewManagerClientImpl, WindowManagerClient implementation:
376
377 void ViewManagerClientImpl::OnCaptureChanged(Id old_capture_view_id,
378 Id new_capture_view_id) {}
379
380 void ViewManagerClientImpl::OnFocusChanged(Id old_focused_view_id,
381 Id new_focused_view_id) {
382 View* focused = GetViewById(new_focused_view_id);
383 View* blurred = GetViewById(old_focused_view_id);
384 if (blurred) {
385 FOR_EACH_OBSERVER(ViewObserver,
386 *ViewPrivate(blurred).observers(),
387 OnViewFocusChanged(focused, blurred));
388 }
389 if (focused) {
390 FOR_EACH_OBSERVER(ViewObserver,
391 *ViewPrivate(focused).observers(),
392 OnViewFocusChanged(focused, blurred));
393 }
394 }
395
396 void ViewManagerClientImpl::OnActiveWindowChanged(Id old_focused_window,
397 Id new_focused_window) {}
398
399 ////////////////////////////////////////////////////////////////////////////////
400 // OnConnectionError, private:
401 void ViewManagerClientImpl::OnConnectionError() {
402 if (delete_on_error_)
403 delete this;
404 }
405
406 ////////////////////////////////////////////////////////////////////////////////
407 // ViewManagerClientImpl, private:
408
409 void ViewManagerClientImpl::RemoveRoot(View* root) {
410 std::vector<View*>::iterator it =
411 std::find(roots_.begin(), roots_.end(), root);
412 if (it != roots_.end())
413 roots_.erase(it);
414 }
415
416 void ViewManagerClientImpl::OnActionCompleted(bool success) {
417 if (!change_acked_callback_.is_null())
418 change_acked_callback_.Run();
419 }
420
421 void ViewManagerClientImpl::OnActionCompletedWithErrorCode(ErrorCode code) {
422 OnActionCompleted(code == ERROR_CODE_NONE);
423 }
424
425 base::Callback<void(bool)> ViewManagerClientImpl::ActionCompletedCallback() {
426 return base::Bind(&ViewManagerClientImpl::OnActionCompleted,
427 base::Unretained(this));
428 }
429
430 base::Callback<void(ErrorCode)>
431 ViewManagerClientImpl::ActionCompletedCallbackWithErrorCode() {
432 return base::Bind(&ViewManagerClientImpl::OnActionCompletedWithErrorCode,
433 base::Unretained(this));
434 }
435
436 } // namespace mojo
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698