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