OLD | NEW |
| (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 "view_manager/public/cpp/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 "view_manager/public/cpp/lib/view_private.h" | |
16 #include "view_manager/public/cpp/util.h" | |
17 #include "view_manager/public/cpp/view_manager_delegate.h" | |
18 #include "view_manager/public/cpp/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.LocalSetViewportMetrics(ViewportMetrics(), | |
40 *view_data->viewport_metrics); | |
41 private_view.set_properties( | |
42 view_data->properties.To<std::map<std::string, std::vector<uint8_t>>>()); | |
43 client->AddView(view); | |
44 private_view.LocalSetBounds(Rect(), *view_data->bounds); | |
45 if (parent) | |
46 ViewPrivate(parent).LocalAddChild(view); | |
47 return view; | |
48 } | |
49 | |
50 View* BuildViewTree(ViewManagerClientImpl* client, | |
51 const Array<ViewDataPtr>& views, | |
52 View* initial_parent) { | |
53 std::vector<View*> parents; | |
54 View* root = NULL; | |
55 View* last_view = NULL; | |
56 if (initial_parent) | |
57 parents.push_back(initial_parent); | |
58 for (size_t i = 0; i < views.size(); ++i) { | |
59 if (last_view && views[i]->parent_id == last_view->id()) { | |
60 parents.push_back(last_view); | |
61 } else if (!parents.empty()) { | |
62 while (parents.back()->id() != views[i]->parent_id) | |
63 parents.pop_back(); | |
64 } | |
65 View* view = AddViewToViewManager( | |
66 client, !parents.empty() ? parents.back() : NULL, views[i]); | |
67 if (!last_view) | |
68 root = view; | |
69 last_view = view; | |
70 } | |
71 return root; | |
72 } | |
73 | |
74 // Responsible for removing a root from the ViewManager when that view is | |
75 // destroyed. | |
76 class RootObserver : public ViewObserver { | |
77 public: | |
78 explicit RootObserver(View* root) : root_(root) {} | |
79 ~RootObserver() override {} | |
80 | |
81 private: | |
82 // Overridden from ViewObserver: | |
83 void OnViewDestroyed(View* view) override { | |
84 DCHECK_EQ(view, root_); | |
85 static_cast<ViewManagerClientImpl*>(root_->view_manager()) | |
86 ->RootDestroyed(root_); | |
87 view->RemoveObserver(this); | |
88 delete this; | |
89 } | |
90 | |
91 View* root_; | |
92 | |
93 DISALLOW_COPY_AND_ASSIGN(RootObserver); | |
94 }; | |
95 | |
96 ViewManagerClientImpl::ViewManagerClientImpl(ViewManagerDelegate* delegate, | |
97 Shell* shell, | |
98 ScopedMessagePipeHandle handle, | |
99 bool delete_on_error) | |
100 : connected_(false), | |
101 connection_id_(0), | |
102 next_id_(1), | |
103 delegate_(delegate), | |
104 root_(nullptr), | |
105 capture_view_(nullptr), | |
106 focused_view_(nullptr), | |
107 activated_view_(nullptr), | |
108 binding_(this, handle.Pass()), | |
109 service_(binding_.client()), | |
110 delete_on_error_(delete_on_error) { | |
111 } | |
112 | |
113 ViewManagerClientImpl::~ViewManagerClientImpl() { | |
114 std::vector<View*> non_owned; | |
115 while (!views_.empty()) { | |
116 IdToViewMap::iterator it = views_.begin(); | |
117 if (OwnsView(it->second->id())) { | |
118 it->second->Destroy(); | |
119 } else { | |
120 non_owned.push_back(it->second); | |
121 views_.erase(it); | |
122 } | |
123 } | |
124 // Delete the non-owned views last. In the typical case these are roots. The | |
125 // exception is the window manager, which may know aboutother random views | |
126 // that it doesn't own. | |
127 // NOTE: we manually delete as we're a friend. | |
128 for (size_t i = 0; i < non_owned.size(); ++i) | |
129 delete non_owned[i]; | |
130 | |
131 delegate_->OnViewManagerDisconnected(this); | |
132 } | |
133 | |
134 void ViewManagerClientImpl::DestroyView(Id view_id) { | |
135 DCHECK(connected_); | |
136 service_->DeleteView(view_id, ActionCompletedCallback()); | |
137 } | |
138 | |
139 void ViewManagerClientImpl::AddChild(Id child_id, Id parent_id) { | |
140 DCHECK(connected_); | |
141 service_->AddView(parent_id, child_id, ActionCompletedCallback()); | |
142 } | |
143 | |
144 void ViewManagerClientImpl::RemoveChild(Id child_id, Id parent_id) { | |
145 DCHECK(connected_); | |
146 service_->RemoveViewFromParent(child_id, ActionCompletedCallback()); | |
147 } | |
148 | |
149 void ViewManagerClientImpl::Reorder( | |
150 Id view_id, | |
151 Id relative_view_id, | |
152 OrderDirection direction) { | |
153 DCHECK(connected_); | |
154 service_->ReorderView(view_id, relative_view_id, direction, | |
155 ActionCompletedCallback()); | |
156 } | |
157 | |
158 bool ViewManagerClientImpl::OwnsView(Id id) const { | |
159 return HiWord(id) == connection_id_; | |
160 } | |
161 | |
162 void ViewManagerClientImpl::SetBounds(Id view_id, const Rect& bounds) { | |
163 DCHECK(connected_); | |
164 service_->SetViewBounds(view_id, bounds.Clone(), ActionCompletedCallback()); | |
165 } | |
166 | |
167 void ViewManagerClientImpl::SetSurfaceId(Id view_id, SurfaceIdPtr surface_id) { | |
168 DCHECK(connected_); | |
169 if (surface_id.is_null()) | |
170 return; | |
171 service_->SetViewSurfaceId( | |
172 view_id, surface_id.Pass(), ActionCompletedCallback()); | |
173 } | |
174 | |
175 void ViewManagerClientImpl::SetFocus(Id view_id) { | |
176 // In order for us to get here we had to have exposed a view, which implies we | |
177 // got a connection. | |
178 DCHECK(window_manager_.get()); | |
179 window_manager_->FocusWindow(view_id, ActionCompletedCallback()); | |
180 } | |
181 | |
182 void ViewManagerClientImpl::SetVisible(Id view_id, bool visible) { | |
183 DCHECK(connected_); | |
184 service_->SetViewVisibility(view_id, visible, ActionCompletedCallback()); | |
185 } | |
186 | |
187 void ViewManagerClientImpl::SetProperty( | |
188 Id view_id, | |
189 const std::string& name, | |
190 const std::vector<uint8_t>& data) { | |
191 DCHECK(connected_); | |
192 service_->SetViewProperty(view_id, | |
193 String(name), | |
194 Array<uint8_t>::From(data), | |
195 ActionCompletedCallback()); | |
196 } | |
197 | |
198 void ViewManagerClientImpl::Embed(const String& url, Id view_id) { | |
199 Embed(url, view_id, nullptr, nullptr); | |
200 } | |
201 | |
202 void ViewManagerClientImpl::Embed(const String& url, | |
203 Id view_id, | |
204 InterfaceRequest<ServiceProvider> services, | |
205 ServiceProviderPtr exposed_services) { | |
206 DCHECK(connected_); | |
207 service_->Embed(url, view_id, services.Pass(), exposed_services.Pass(), | |
208 ActionCompletedCallback()); | |
209 } | |
210 | |
211 void ViewManagerClientImpl::AddView(View* view) { | |
212 DCHECK(views_.find(view->id()) == views_.end()); | |
213 views_[view->id()] = view; | |
214 } | |
215 | |
216 void ViewManagerClientImpl::RemoveView(Id view_id) { | |
217 IdToViewMap::iterator it = views_.find(view_id); | |
218 if (it != views_.end()) | |
219 views_.erase(it); | |
220 } | |
221 | |
222 //////////////////////////////////////////////////////////////////////////////// | |
223 // ViewManagerClientImpl, ViewManager implementation: | |
224 | |
225 Id ViewManagerClientImpl::CreateViewOnServer() { | |
226 DCHECK(connected_); | |
227 const Id view_id = MakeTransportId(connection_id_, ++next_id_); | |
228 service_->CreateView(view_id, ActionCompletedCallbackWithErrorCode()); | |
229 return view_id; | |
230 } | |
231 | |
232 const std::string& ViewManagerClientImpl::GetEmbedderURL() const { | |
233 return creator_url_; | |
234 } | |
235 | |
236 View* ViewManagerClientImpl::GetRoot() { | |
237 return root_; | |
238 } | |
239 | |
240 View* ViewManagerClientImpl::GetViewById(Id id) { | |
241 IdToViewMap::const_iterator it = views_.find(id); | |
242 return it != views_.end() ? it->second : NULL; | |
243 } | |
244 | |
245 View* ViewManagerClientImpl::GetFocusedView() { | |
246 return focused_view_; | |
247 } | |
248 | |
249 View* ViewManagerClientImpl::CreateView() { | |
250 View* view = new View(this, CreateViewOnServer()); | |
251 AddView(view); | |
252 return view; | |
253 } | |
254 | |
255 //////////////////////////////////////////////////////////////////////////////// | |
256 // ViewManagerClientImpl, ViewManagerClient implementation: | |
257 | |
258 void ViewManagerClientImpl::OnEmbed( | |
259 ConnectionSpecificId connection_id, | |
260 const String& creator_url, | |
261 ViewDataPtr root_data, | |
262 InterfaceRequest<ServiceProvider> services, | |
263 ServiceProviderPtr exposed_services, | |
264 ScopedMessagePipeHandle window_manager_pipe) { | |
265 DCHECK(!connected_); | |
266 connected_ = true; | |
267 connection_id_ = connection_id; | |
268 creator_url_ = String::From(creator_url); | |
269 | |
270 DCHECK(!root_); | |
271 root_ = AddViewToViewManager(this, nullptr, root_data); | |
272 root_->AddObserver(new RootObserver(root_)); | |
273 | |
274 window_manager_.Bind(window_manager_pipe.Pass()); | |
275 window_manager_.set_client(this); | |
276 // base::Unretained() is safe here as |window_manager_| is bound to our | |
277 // lifetime. | |
278 window_manager_->GetFocusedAndActiveViews( | |
279 base::Bind(&ViewManagerClientImpl::OnGotFocusedAndActiveViews, | |
280 base::Unretained(this))); | |
281 | |
282 delegate_->OnEmbed(root_, services.Pass(), exposed_services.Pass()); | |
283 } | |
284 | |
285 void ViewManagerClientImpl::OnEmbeddedAppDisconnected(Id view_id) { | |
286 View* view = GetViewById(view_id); | |
287 if (view) { | |
288 FOR_EACH_OBSERVER(ViewObserver, *ViewPrivate(view).observers(), | |
289 OnViewEmbeddedAppDisconnected(view)); | |
290 } | |
291 } | |
292 | |
293 void ViewManagerClientImpl::OnViewBoundsChanged(Id view_id, | |
294 RectPtr old_bounds, | |
295 RectPtr new_bounds) { | |
296 View* view = GetViewById(view_id); | |
297 ViewPrivate(view).LocalSetBounds(*old_bounds, *new_bounds); | |
298 } | |
299 | |
300 namespace { | |
301 | |
302 void SetViewportMetricsOnDecendants(View* root, | |
303 const ViewportMetrics& old_metrics, | |
304 const ViewportMetrics& new_metrics) { | |
305 ViewPrivate(root).LocalSetViewportMetrics(old_metrics, new_metrics); | |
306 const View::Children& children = root->children(); | |
307 for (size_t i = 0; i < children.size(); ++i) | |
308 SetViewportMetricsOnDecendants(children[i], old_metrics, new_metrics); | |
309 } | |
310 } | |
311 | |
312 void ViewManagerClientImpl::OnViewViewportMetricsChanged( | |
313 ViewportMetricsPtr old_metrics, | |
314 ViewportMetricsPtr new_metrics) { | |
315 View* view = GetRoot(); | |
316 if (view) | |
317 SetViewportMetricsOnDecendants(view, *old_metrics, *new_metrics); | |
318 } | |
319 | |
320 void ViewManagerClientImpl::OnViewHierarchyChanged( | |
321 Id view_id, | |
322 Id new_parent_id, | |
323 Id old_parent_id, | |
324 mojo::Array<ViewDataPtr> views) { | |
325 View* initial_parent = views.size() ? | |
326 GetViewById(views[0]->parent_id) : NULL; | |
327 | |
328 BuildViewTree(this, views, initial_parent); | |
329 | |
330 View* new_parent = GetViewById(new_parent_id); | |
331 View* old_parent = GetViewById(old_parent_id); | |
332 View* view = GetViewById(view_id); | |
333 if (new_parent) | |
334 ViewPrivate(new_parent).LocalAddChild(view); | |
335 else | |
336 ViewPrivate(old_parent).LocalRemoveChild(view); | |
337 } | |
338 | |
339 void ViewManagerClientImpl::OnViewReordered(Id view_id, | |
340 Id relative_view_id, | |
341 OrderDirection direction) { | |
342 View* view = GetViewById(view_id); | |
343 View* relative_view = GetViewById(relative_view_id); | |
344 if (view && relative_view) | |
345 ViewPrivate(view).LocalReorder(relative_view, direction); | |
346 } | |
347 | |
348 void ViewManagerClientImpl::OnViewDeleted(Id view_id) { | |
349 View* view = GetViewById(view_id); | |
350 if (view) | |
351 ViewPrivate(view).LocalDestroy(); | |
352 } | |
353 | |
354 void ViewManagerClientImpl::OnViewVisibilityChanged(Id view_id, bool visible) { | |
355 // TODO(sky): there is a race condition here. If this client and another | |
356 // client change the visibility at the same time the wrong value may be set. | |
357 // Deal with this some how. | |
358 View* view = GetViewById(view_id); | |
359 if (view) | |
360 view->SetVisible(visible); | |
361 } | |
362 | |
363 void ViewManagerClientImpl::OnViewDrawnStateChanged(Id view_id, bool drawn) { | |
364 View* view = GetViewById(view_id); | |
365 if (view) | |
366 ViewPrivate(view).LocalSetDrawn(drawn); | |
367 } | |
368 | |
369 void ViewManagerClientImpl::OnViewSharedPropertyChanged( | |
370 Id view_id, | |
371 const String& name, | |
372 Array<uint8_t> new_data) { | |
373 View* view = GetViewById(view_id); | |
374 if (view) { | |
375 std::vector<uint8_t> data; | |
376 std::vector<uint8_t>* data_ptr = NULL; | |
377 if (!new_data.is_null()) { | |
378 data = new_data.To<std::vector<uint8_t>>(); | |
379 data_ptr = &data; | |
380 } | |
381 | |
382 view->SetSharedProperty(name, data_ptr); | |
383 } | |
384 } | |
385 | |
386 void ViewManagerClientImpl::OnViewInputEvent( | |
387 Id view_id, | |
388 EventPtr event, | |
389 const Callback<void()>& ack_callback) { | |
390 View* view = GetViewById(view_id); | |
391 if (view) { | |
392 FOR_EACH_OBSERVER(ViewObserver, | |
393 *ViewPrivate(view).observers(), | |
394 OnViewInputEvent(view, event)); | |
395 } | |
396 ack_callback.Run(); | |
397 } | |
398 | |
399 //////////////////////////////////////////////////////////////////////////////// | |
400 // ViewManagerClientImpl, WindowManagerClient implementation: | |
401 | |
402 void ViewManagerClientImpl::OnCaptureChanged(Id old_capture_view_id, | |
403 Id new_capture_view_id) { | |
404 View* gained_capture = GetViewById(new_capture_view_id); | |
405 View* lost_capture = GetViewById(old_capture_view_id); | |
406 if (lost_capture) { | |
407 FOR_EACH_OBSERVER(ViewObserver, | |
408 *ViewPrivate(lost_capture).observers(), | |
409 OnViewFocusChanged(gained_capture, lost_capture)); | |
410 } | |
411 capture_view_ = gained_capture; | |
412 if (gained_capture) { | |
413 FOR_EACH_OBSERVER(ViewObserver, | |
414 *ViewPrivate(gained_capture).observers(), | |
415 OnViewFocusChanged(gained_capture, lost_capture)); | |
416 } | |
417 } | |
418 | |
419 void ViewManagerClientImpl::OnFocusChanged(Id old_focused_view_id, | |
420 Id new_focused_view_id) { | |
421 View* focused = GetViewById(new_focused_view_id); | |
422 View* blurred = GetViewById(old_focused_view_id); | |
423 if (blurred) { | |
424 FOR_EACH_OBSERVER(ViewObserver, | |
425 *ViewPrivate(blurred).observers(), | |
426 OnViewFocusChanged(focused, blurred)); | |
427 } | |
428 focused_view_ = focused; | |
429 if (focused) { | |
430 FOR_EACH_OBSERVER(ViewObserver, | |
431 *ViewPrivate(focused).observers(), | |
432 OnViewFocusChanged(focused, blurred)); | |
433 } | |
434 } | |
435 | |
436 void ViewManagerClientImpl::OnActiveWindowChanged(Id old_active_view_id, | |
437 Id new_active_view_id) { | |
438 View* activated = GetViewById(new_active_view_id); | |
439 View* deactivated = GetViewById(old_active_view_id); | |
440 if (deactivated) { | |
441 FOR_EACH_OBSERVER(ViewObserver, | |
442 *ViewPrivate(deactivated).observers(), | |
443 OnViewActivationChanged(activated, deactivated)); | |
444 } | |
445 activated_view_ = activated; | |
446 if (activated) { | |
447 FOR_EACH_OBSERVER(ViewObserver, | |
448 *ViewPrivate(activated).observers(), | |
449 OnViewActivationChanged(activated, deactivated)); | |
450 } | |
451 } | |
452 | |
453 //////////////////////////////////////////////////////////////////////////////// | |
454 // OnConnectionError, private: | |
455 void ViewManagerClientImpl::OnConnectionError() { | |
456 if (delete_on_error_) | |
457 delete this; | |
458 } | |
459 | |
460 //////////////////////////////////////////////////////////////////////////////// | |
461 // ViewManagerClientImpl, private: | |
462 | |
463 void ViewManagerClientImpl::RootDestroyed(View* root) { | |
464 DCHECK_EQ(root, root_); | |
465 root_ = nullptr; | |
466 } | |
467 | |
468 void ViewManagerClientImpl::OnActionCompleted(bool success) { | |
469 if (!change_acked_callback_.is_null()) | |
470 change_acked_callback_.Run(); | |
471 } | |
472 | |
473 void ViewManagerClientImpl::OnActionCompletedWithErrorCode(ErrorCode code) { | |
474 OnActionCompleted(code == ERROR_CODE_NONE); | |
475 } | |
476 | |
477 base::Callback<void(bool)> ViewManagerClientImpl::ActionCompletedCallback() { | |
478 return base::Bind(&ViewManagerClientImpl::OnActionCompleted, | |
479 base::Unretained(this)); | |
480 } | |
481 | |
482 base::Callback<void(ErrorCode)> | |
483 ViewManagerClientImpl::ActionCompletedCallbackWithErrorCode() { | |
484 return base::Bind(&ViewManagerClientImpl::OnActionCompletedWithErrorCode, | |
485 base::Unretained(this)); | |
486 } | |
487 | |
488 void ViewManagerClientImpl::OnGotFocusedAndActiveViews(uint32 focused_view_id, | |
489 uint32 active_view_id) { | |
490 if (GetViewById(focused_view_id) != focused_view_) | |
491 OnFocusChanged(focused_view_ ? focused_view_->id() : 0, focused_view_id); | |
492 if (GetViewById(active_view_id) != activated_view_) { | |
493 OnActiveWindowChanged(activated_view_ ? activated_view_->id() : 0, | |
494 active_view_id); | |
495 } | |
496 } | |
497 | |
498 } // namespace mojo | |
OLD | NEW |