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 "mojo/services/public/cpp/view_manager/lib/view_manager_client_impl.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"
22 Id MakeTransportId(ConnectionSpecificId connection_id,
23 ConnectionSpecificId local_id) {
24 return (connection_id << 16) | local_id;
27 // Helper called to construct a local view object from transport data.
28 View* AddViewToViewManager(ViewManagerClientImpl* client,
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);
44 ViewPrivate(parent).LocalAddChild(view);
48 View* BuildViewTree(ViewManagerClientImpl* client,
49 const Array<ViewDataPtr>& views,
50 View* initial_parent) {
51 std::vector<View*> parents;
53 View* last_view = NULL;
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)
63 View* view = AddViewToViewManager(
64 client, !parents.empty() ? parents.back() : NULL, views[i]);
72 // Responsible for removing a root from the ViewManager when that view is
74 class RootObserver : public ViewObserver {
76 explicit RootObserver(View* root) : root_(root) {}
77 ~RootObserver() override {}
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);
91 DISALLOW_COPY_AND_ASSIGN(RootObserver);
94 ViewManagerClientImpl::ViewManagerClientImpl(ViewManagerDelegate* delegate,
96 : connected_(false), connection_id_(0), next_id_(1), delegate_(delegate) {
99 ViewManagerClientImpl::~ViewManagerClientImpl() {
100 std::vector<View*> non_owned;
101 while (!views_.empty()) {
102 IdToViewMap::iterator it = views_.begin();
103 if (OwnsView(it->second->id())) {
104 it->second->Destroy();
106 non_owned.push_back(it->second);
110 // Delete the non-owned views last. In the typical case these are roots. The
111 // exception is the window manager, which may know aboutother random views
112 // that it doesn't own.
113 // NOTE: we manually delete as we're a friend.
114 for (size_t i = 0; i < non_owned.size(); ++i)
117 delegate_->OnViewManagerDisconnected(this);
120 Id ViewManagerClientImpl::CreateView() {
122 const Id view_id = MakeTransportId(connection_id_, ++next_id_);
123 service_->CreateView(view_id, ActionCompletedCallbackWithErrorCode());
127 void ViewManagerClientImpl::DestroyView(Id view_id) {
129 service_->DeleteView(view_id, ActionCompletedCallback());
132 void ViewManagerClientImpl::AddChild(Id child_id, Id parent_id) {
134 service_->AddView(parent_id, child_id, ActionCompletedCallback());
137 void ViewManagerClientImpl::RemoveChild(Id child_id, Id parent_id) {
139 service_->RemoveViewFromParent(child_id, ActionCompletedCallback());
142 void ViewManagerClientImpl::Reorder(
145 OrderDirection direction) {
147 service_->ReorderView(view_id, relative_view_id, direction,
148 ActionCompletedCallback());
151 bool ViewManagerClientImpl::OwnsView(Id id) const {
152 return HiWord(id) == connection_id_;
155 void ViewManagerClientImpl::SetBounds(Id view_id, const Rect& bounds) {
157 service_->SetViewBounds(view_id, bounds.Clone(), ActionCompletedCallback());
160 void ViewManagerClientImpl::SetSurfaceId(Id view_id, SurfaceIdPtr surface_id) {
162 if (surface_id.is_null())
164 service_->SetViewSurfaceId(
165 view_id, surface_id.Pass(), ActionCompletedCallback());
168 void ViewManagerClientImpl::SetFocus(Id view_id) {
169 // In order for us to get here we had to have exposed a view, which implies we
171 DCHECK(window_manager_.get());
172 window_manager_->FocusWindow(view_id, ActionCompletedCallback());
175 void ViewManagerClientImpl::SetVisible(Id view_id, bool visible) {
177 service_->SetViewVisibility(view_id, visible, ActionCompletedCallback());
180 void ViewManagerClientImpl::SetProperty(
182 const std::string& name,
183 const std::vector<uint8_t>& data) {
185 service_->SetViewProperty(view_id,
187 Array<uint8_t>::From(data),
188 ActionCompletedCallback());
191 void ViewManagerClientImpl::Embed(const String& url, Id view_id) {
192 ServiceProviderPtr sp;
193 BindToProxy(new ServiceProviderImpl, &sp);
194 Embed(url, view_id, sp.Pass());
197 void ViewManagerClientImpl::Embed(
200 ServiceProviderPtr service_provider) {
202 service_->Embed(url, view_id, service_provider.Pass(),
203 ActionCompletedCallback());
206 void ViewManagerClientImpl::AddView(View* view) {
207 DCHECK(views_.find(view->id()) == views_.end());
208 views_[view->id()] = view;
211 void ViewManagerClientImpl::RemoveView(Id view_id) {
212 IdToViewMap::iterator it = views_.find(view_id);
213 if (it != views_.end())
217 ////////////////////////////////////////////////////////////////////////////////
218 // ViewManagerClientImpl, ViewManager implementation:
220 const std::string& ViewManagerClientImpl::GetEmbedderURL() const {
224 const std::vector<View*>& ViewManagerClientImpl::GetRoots() const {
228 View* ViewManagerClientImpl::GetViewById(Id id) {
229 IdToViewMap::const_iterator it = views_.find(id);
230 return it != views_.end() ? it->second : NULL;
233 ////////////////////////////////////////////////////////////////////////////////
234 // ViewManagerClientImpl, InterfaceImpl overrides:
236 void ViewManagerClientImpl::OnConnectionEstablished() {
240 ////////////////////////////////////////////////////////////////////////////////
241 // ViewManagerClientImpl, ViewManagerClient implementation:
243 void ViewManagerClientImpl::OnEmbed(
244 ConnectionSpecificId connection_id,
245 const String& creator_url,
246 ViewDataPtr root_data,
247 InterfaceRequest<ServiceProvider> parent_services,
248 ScopedMessagePipeHandle window_manager_pipe) {
251 connection_id_ = connection_id;
252 creator_url_ = String::From(creator_url);
254 DCHECK_EQ(connection_id_, connection_id);
255 DCHECK_EQ(creator_url_, creator_url);
258 // A new root must not already exist as a root or be contained by an existing
259 // hierarchy visible to this view manager.
260 View* root = AddViewToViewManager(this, NULL, root_data);
261 roots_.push_back(root);
262 root->AddObserver(new RootObserver(root));
264 ServiceProviderImpl* exported_services = nullptr;
265 scoped_ptr<ServiceProvider> remote;
267 if (parent_services.is_pending()) {
268 // BindToRequest() binds the lifetime of |exported_services| to the pipe.
269 exported_services = new ServiceProviderImpl;
270 BindToRequest(exported_services, &parent_services);
271 remote.reset(exported_services->CreateRemoteServiceProvider());
273 window_manager_.Bind(window_manager_pipe.Pass());
274 window_manager_.set_client(this);
275 delegate_->OnEmbed(this, root, exported_services, remote.Pass());
278 void ViewManagerClientImpl::OnEmbeddedAppDisconnected(Id view_id) {
279 View* view = GetViewById(view_id);
281 FOR_EACH_OBSERVER(ViewObserver, *ViewPrivate(view).observers(),
282 OnViewEmbeddedAppDisconnected(view));
286 void ViewManagerClientImpl::OnViewBoundsChanged(Id view_id,
288 RectPtr new_bounds) {
289 View* view = GetViewById(view_id);
290 ViewPrivate(view).LocalSetBounds(*old_bounds, *new_bounds);
293 void ViewManagerClientImpl::OnViewHierarchyChanged(
297 mojo::Array<ViewDataPtr> views) {
298 View* initial_parent = views.size() ?
299 GetViewById(views[0]->parent_id) : NULL;
301 BuildViewTree(this, views, initial_parent);
303 View* new_parent = GetViewById(new_parent_id);
304 View* old_parent = GetViewById(old_parent_id);
305 View* view = GetViewById(view_id);
307 ViewPrivate(new_parent).LocalAddChild(view);
309 ViewPrivate(old_parent).LocalRemoveChild(view);
312 void ViewManagerClientImpl::OnViewReordered(Id view_id,
314 OrderDirection direction) {
315 View* view = GetViewById(view_id);
316 View* relative_view = GetViewById(relative_view_id);
317 if (view && relative_view)
318 ViewPrivate(view).LocalReorder(relative_view, direction);
321 void ViewManagerClientImpl::OnViewDeleted(Id view_id) {
322 View* view = GetViewById(view_id);
324 ViewPrivate(view).LocalDestroy();
327 void ViewManagerClientImpl::OnViewVisibilityChanged(Id view_id, bool visible) {
328 // TODO(sky): there is a race condition here. If this client and another
329 // client change the visibility at the same time the wrong value may be set.
330 // Deal with this some how.
331 View* view = GetViewById(view_id);
333 view->SetVisible(visible);
336 void ViewManagerClientImpl::OnViewDrawnStateChanged(Id view_id, bool drawn) {
337 View* view = GetViewById(view_id);
339 ViewPrivate(view).LocalSetDrawn(drawn);
342 void ViewManagerClientImpl::OnViewPropertyChanged(
345 Array<uint8_t> new_data) {
346 View* view = GetViewById(view_id);
348 std::vector<uint8_t> data;
349 std::vector<uint8_t>* data_ptr = NULL;
350 if (!new_data.is_null()) {
351 data = new_data.To<std::vector<uint8_t>>();
355 view->SetProperty(name, data_ptr);
359 void ViewManagerClientImpl::OnViewInputEvent(
362 const Callback<void()>& ack_callback) {
363 View* view = GetViewById(view_id);
365 FOR_EACH_OBSERVER(ViewObserver,
366 *ViewPrivate(view).observers(),
367 OnViewInputEvent(view, event));
372 ////////////////////////////////////////////////////////////////////////////////
373 // ViewManagerClientImpl, WindowManagerClient implementation:
375 void ViewManagerClientImpl::OnCaptureChanged(Id old_capture_view_id,
376 Id new_capture_view_id) {}
378 void ViewManagerClientImpl::OnFocusChanged(Id old_focused_view_id,
379 Id new_focused_view_id) {
380 View* focused = GetViewById(new_focused_view_id);
381 View* blurred = GetViewById(old_focused_view_id);
383 FOR_EACH_OBSERVER(ViewObserver,
384 *ViewPrivate(blurred).observers(),
385 OnViewFocusChanged(focused, blurred));
388 FOR_EACH_OBSERVER(ViewObserver,
389 *ViewPrivate(focused).observers(),
390 OnViewFocusChanged(focused, blurred));
394 void ViewManagerClientImpl::OnActiveWindowChanged(Id old_focused_window,
395 Id new_focused_window) {}
397 ////////////////////////////////////////////////////////////////////////////////
398 // ViewManagerClientImpl, private:
400 void ViewManagerClientImpl::RemoveRoot(View* root) {
401 std::vector<View*>::iterator it =
402 std::find(roots_.begin(), roots_.end(), root);
403 if (it != roots_.end())
407 void ViewManagerClientImpl::OnActionCompleted(bool success) {
408 if (!change_acked_callback_.is_null())
409 change_acked_callback_.Run();
412 void ViewManagerClientImpl::OnActionCompletedWithErrorCode(ErrorCode code) {
413 OnActionCompleted(code == ERROR_CODE_NONE);
416 base::Callback<void(bool)> ViewManagerClientImpl::ActionCompletedCallback() {
417 return base::Bind(&ViewManagerClientImpl::OnActionCompleted,
418 base::Unretained(this));
421 base::Callback<void(ErrorCode)>
422 ViewManagerClientImpl::ActionCompletedCallbackWithErrorCode() {
423 return base::Bind(&ViewManagerClientImpl::OnActionCompletedWithErrorCode,
424 base::Unretained(this));