Home | History | Annotate | Download | only in lib
      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 
     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.
     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 
     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:
     80   explicit RootObserver(View* root) : root_(root) {}
     81   virtual ~RootObserver() {}
     82 
     83  private:
     84   // Overridden from ViewObserver:
     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 
     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 
    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 
    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 
    148 void ViewManagerClientImpl::DestroyView(Id view_id) {
    149   DCHECK(connected_);
    150   service_->DeleteView(view_id, ActionCompletedCallback());
    151 }
    152 
    153 void ViewManagerClientImpl::AddChild(Id child_id, Id parent_id) {
    154   DCHECK(connected_);
    155   service_->AddView(parent_id, child_id, ActionCompletedCallback());
    156 }
    157 
    158 void ViewManagerClientImpl::RemoveChild(Id child_id, Id parent_id) {
    159   DCHECK(connected_);
    160   service_->RemoveViewFromParent(child_id, ActionCompletedCallback());
    161 }
    162 
    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 
    172 bool ViewManagerClientImpl::OwnsView(Id id) const {
    173   return HiWord(id) == connection_id_;
    174 }
    175 
    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 
    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 
    190 void ViewManagerClientImpl::SetFocus(Id view_id) {
    191   window_manager_->FocusWindow(view_id, ActionCompletedCallback());
    192 }
    193 
    194 void ViewManagerClientImpl::SetVisible(Id view_id, bool visible) {
    195   DCHECK(connected_);
    196   service_->SetViewVisibility(view_id, visible, 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, service_provider.Pass(),
    211                   ActionCompletedCallback());
    212 }
    213 
    214 void ViewManagerClientImpl::AddView(View* view) {
    215   DCHECK(views_.find(view->id()) == views_.end());
    216   views_[view->id()] = view;
    217 }
    218 
    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 
    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 
    235 void ViewManagerClientImpl::DispatchEvent(View* target, EventPtr event) {
    236   CHECK(window_manager_delegate_);
    237   service_->DispatchOnViewInputEvent(target->id(), event.Pass());
    238 }
    239 
    240 const std::string& ViewManagerClientImpl::GetEmbedderURL() const {
    241   return creator_url_;
    242 }
    243 
    244 const std::vector<View*>& ViewManagerClientImpl::GetRoots() const {
    245   return roots_;
    246 }
    247 
    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 
    256 void ViewManagerClientImpl::OnConnectionEstablished() {
    257   service_ = client();
    258 }
    259 
    260 ////////////////////////////////////////////////////////////////////////////////
    261 // ViewManagerClientImpl, ViewManagerClient implementation:
    262 
    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 
    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 
    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 
    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 
    328 void ViewManagerClientImpl::OnViewDeleted(Id view_id) {
    329   View* view = GetViewById(view_id);
    330   if (view)
    331     ViewPrivate(view).LocalDestroy();
    332 }
    333 
    334 void ViewManagerClientImpl::OnViewVisibilityChanged(Id view_id, bool visible) {
    335   // TODO(sky): implement me.
    336   NOTIMPLEMENTED();
    337 }
    338 
    339 void ViewManagerClientImpl::OnViewDrawnStateChanged(Id view_id, bool drawn) {
    340   // TODO(sky): implement me.
    341   NOTIMPLEMENTED();
    342 }
    343 
    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 
    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 
    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 
    372 void ViewManagerClientImpl::OnWindowManagerReady() {}
    373 
    374 void ViewManagerClientImpl::OnCaptureChanged(Id old_capture_view_id,
    375                                              Id new_capture_view_id) {}
    376 
    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 
    393 void ViewManagerClientImpl::OnActiveWindowChanged(Id old_focused_window,
    394                                                   Id new_focused_window) {}
    395 
    396 ////////////////////////////////////////////////////////////////////////////////
    397 // ViewManagerClientImpl, private:
    398 
    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 
    406 void ViewManagerClientImpl::OnActionCompleted(bool success) {
    407   if (!change_acked_callback_.is_null())
    408     change_acked_callback_.Run();
    409 }
    410 
    411 void ViewManagerClientImpl::OnActionCompletedWithErrorCode(ErrorCode code) {
    412   OnActionCompleted(code == ERROR_CODE_NONE);
    413 }
    414 
    415 base::Callback<void(bool)> ViewManagerClientImpl::ActionCompletedCallback() {
    416   return base::Bind(&ViewManagerClientImpl::OnActionCompleted,
    417                     base::Unretained(this));
    418 }
    419 
    420 base::Callback<void(ErrorCode)>
    421     ViewManagerClientImpl::ActionCompletedCallbackWithErrorCode() {
    422   return base::Bind(&ViewManagerClientImpl::OnActionCompletedWithErrorCode,
    423                     base::Unretained(this));
    424 }
    425 
    426 }  // namespace mojo
    427