Home | History | Annotate | Download | only in view_manager
      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/view_manager/connection_manager.h"
      6 
      7 #include "base/logging.h"
      8 #include "mojo/public/cpp/application/application_connection.h"
      9 #include "mojo/public/interfaces/application/service_provider.mojom.h"
     10 #include "mojo/services/public/cpp/input_events/input_events_type_converters.h"
     11 #include "mojo/services/view_manager/view_manager_service_impl.h"
     12 
     13 namespace mojo {
     14 namespace service {
     15 
     16 ConnectionManager::ScopedChange::ScopedChange(
     17     ViewManagerServiceImpl* connection,
     18     ConnectionManager* connection_manager,
     19     bool is_delete_view)
     20     : connection_manager_(connection_manager),
     21       connection_id_(connection->id()),
     22       is_delete_view_(is_delete_view) {
     23   connection_manager_->PrepareForChange(this);
     24 }
     25 
     26 ConnectionManager::ScopedChange::~ScopedChange() {
     27   connection_manager_->FinishChange();
     28 }
     29 
     30 ConnectionManager::ConnectionManager(
     31     ApplicationConnection* app_connection,
     32     const Callback<void()>& native_viewport_closed_callback)
     33     : app_connection_(app_connection),
     34       next_connection_id_(1),
     35       display_manager_(app_connection,
     36                        this,
     37                        native_viewport_closed_callback),
     38       root_(new ServerView(this, RootViewId())),
     39       current_change_(NULL) {
     40   root_->SetBounds(gfx::Rect(800, 600));
     41 }
     42 
     43 ConnectionManager::~ConnectionManager() {
     44   while (!connections_created_by_connect_.empty())
     45     delete *(connections_created_by_connect_.begin());
     46   // All the connections should have been destroyed.
     47   DCHECK(connection_map_.empty());
     48   root_.reset();
     49 }
     50 
     51 ConnectionSpecificId ConnectionManager::GetAndAdvanceNextConnectionId() {
     52   const ConnectionSpecificId id = next_connection_id_++;
     53   DCHECK_LT(id, next_connection_id_);
     54   return id;
     55 }
     56 
     57 void ConnectionManager::AddConnection(ViewManagerServiceImpl* connection) {
     58   DCHECK_EQ(0u, connection_map_.count(connection->id()));
     59   connection_map_[connection->id()] = connection;
     60 }
     61 
     62 void ConnectionManager::RemoveConnection(ViewManagerServiceImpl* connection) {
     63   connection_map_.erase(connection->id());
     64   connections_created_by_connect_.erase(connection);
     65 
     66   // Notify remaining connections so that they can cleanup.
     67   for (ConnectionMap::const_iterator i = connection_map_.begin();
     68        i != connection_map_.end();
     69        ++i) {
     70     i->second->OnViewManagerServiceImplDestroyed(connection->id());
     71   }
     72 }
     73 
     74 void ConnectionManager::EmbedRoot(
     75     const std::string& url,
     76     InterfaceRequest<ServiceProvider> service_provider) {
     77   if (connection_map_.empty()) {
     78     EmbedImpl(kInvalidConnectionId,
     79               String::From(url),
     80               RootViewId(),
     81               service_provider.Pass());
     82     return;
     83   }
     84   ViewManagerServiceImpl* connection = GetConnection(kWindowManagerConnection);
     85   connection->client()->Embed(url, service_provider.Pass());
     86 }
     87 
     88 void ConnectionManager::Embed(
     89     ConnectionSpecificId creator_id,
     90     const String& url,
     91     Id transport_view_id,
     92     InterfaceRequest<ServiceProvider> service_provider) {
     93   EmbedImpl(creator_id,
     94             url,
     95             ViewIdFromTransportId(transport_view_id),
     96             service_provider.Pass())->set_delete_on_connection_error();
     97 }
     98 
     99 ViewManagerServiceImpl* ConnectionManager::GetConnection(
    100     ConnectionSpecificId connection_id) {
    101   ConnectionMap::iterator i = connection_map_.find(connection_id);
    102   return i == connection_map_.end() ? NULL : i->second;
    103 }
    104 
    105 ServerView* ConnectionManager::GetView(const ViewId& id) {
    106   if (id == root_->id())
    107     return root_.get();
    108   ConnectionMap::iterator i = connection_map_.find(id.connection_id);
    109   return i == connection_map_.end() ? NULL : i->second->GetView(id);
    110 }
    111 
    112 void ConnectionManager::OnConnectionMessagedClient(ConnectionSpecificId id) {
    113   if (current_change_)
    114     current_change_->MarkConnectionAsMessaged(id);
    115 }
    116 
    117 bool ConnectionManager::DidConnectionMessageClient(
    118     ConnectionSpecificId id) const {
    119   return current_change_ && current_change_->DidMessageConnection(id);
    120 }
    121 
    122 const ViewManagerServiceImpl* ConnectionManager::GetConnectionWithRoot(
    123     const ViewId& id) const {
    124   for (ConnectionMap::const_iterator i = connection_map_.begin();
    125        i != connection_map_.end();
    126        ++i) {
    127     if (i->second->HasRoot(id))
    128       return i->second;
    129   }
    130   return NULL;
    131 }
    132 
    133 void ConnectionManager::DispatchViewInputEventToWindowManager(EventPtr event) {
    134   // Input events are forwarded to the WindowManager. The WindowManager
    135   // eventually calls back to us with DispatchOnViewInputEvent().
    136   ViewManagerServiceImpl* connection = GetConnection(kWindowManagerConnection);
    137   if (!connection)
    138     return;
    139   connection->client()->DispatchOnViewInputEvent(event.Pass());
    140 }
    141 
    142 void ConnectionManager::ProcessViewBoundsChanged(const ServerView* view,
    143                                                  const gfx::Rect& old_bounds,
    144                                                  const gfx::Rect& new_bounds) {
    145   for (ConnectionMap::iterator i = connection_map_.begin();
    146        i != connection_map_.end();
    147        ++i) {
    148     i->second->ProcessViewBoundsChanged(
    149         view, old_bounds, new_bounds, IsChangeSource(i->first));
    150   }
    151 }
    152 
    153 void ConnectionManager::ProcessWillChangeViewHierarchy(
    154     const ServerView* view,
    155     const ServerView* new_parent,
    156     const ServerView* old_parent) {
    157   for (ConnectionMap::iterator i = connection_map_.begin();
    158        i != connection_map_.end();
    159        ++i) {
    160     i->second->ProcessWillChangeViewHierarchy(
    161         view, new_parent, old_parent, IsChangeSource(i->first));
    162   }
    163 }
    164 
    165 void ConnectionManager::ProcessViewHierarchyChanged(
    166     const ServerView* view,
    167     const ServerView* new_parent,
    168     const ServerView* old_parent) {
    169   for (ConnectionMap::iterator i = connection_map_.begin();
    170        i != connection_map_.end();
    171        ++i) {
    172     i->second->ProcessViewHierarchyChanged(
    173         view, new_parent, old_parent, IsChangeSource(i->first));
    174   }
    175 }
    176 
    177 void ConnectionManager::ProcessViewReorder(const ServerView* view,
    178                                            const ServerView* relative_view,
    179                                            const OrderDirection direction) {
    180   for (ConnectionMap::iterator i = connection_map_.begin();
    181        i != connection_map_.end();
    182        ++i) {
    183     i->second->ProcessViewReorder(
    184         view, relative_view, direction, IsChangeSource(i->first));
    185   }
    186 }
    187 
    188 void ConnectionManager::ProcessViewDeleted(const ViewId& view) {
    189   for (ConnectionMap::iterator i = connection_map_.begin();
    190        i != connection_map_.end();
    191        ++i) {
    192     i->second->ProcessViewDeleted(view, IsChangeSource(i->first));
    193   }
    194 }
    195 
    196 void ConnectionManager::PrepareForChange(ScopedChange* change) {
    197   // Should only ever have one change in flight.
    198   CHECK(!current_change_);
    199   current_change_ = change;
    200 }
    201 
    202 void ConnectionManager::FinishChange() {
    203   // PrepareForChange/FinishChange should be balanced.
    204   CHECK(current_change_);
    205   current_change_ = NULL;
    206 }
    207 
    208 ViewManagerServiceImpl* ConnectionManager::EmbedImpl(
    209     const ConnectionSpecificId creator_id,
    210     const String& url,
    211     const ViewId& root_id,
    212     InterfaceRequest<ServiceProvider> service_provider) {
    213   MessagePipe pipe;
    214 
    215   ServiceProvider* view_manager_service_provider =
    216       app_connection_->ConnectToApplication(url)->GetServiceProvider();
    217   view_manager_service_provider->ConnectToService(
    218       ViewManagerServiceImpl::Client::Name_, pipe.handle1.Pass());
    219 
    220   std::string creator_url;
    221   ConnectionMap::const_iterator it = connection_map_.find(creator_id);
    222   if (it != connection_map_.end())
    223     creator_url = it->second->url();
    224 
    225   ViewManagerServiceImpl* connection =
    226       new ViewManagerServiceImpl(this,
    227                                  creator_id,
    228                                  creator_url,
    229                                  url.To<std::string>(),
    230                                  root_id,
    231                                  service_provider.Pass());
    232   WeakBindToPipe(connection, pipe.handle0.Pass());
    233   connections_created_by_connect_.insert(connection);
    234   OnConnectionMessagedClient(connection->id());
    235   return connection;
    236 }
    237 
    238 void ConnectionManager::OnViewDestroyed(const ServerView* view) {
    239   ProcessViewDeleted(view->id());
    240 }
    241 
    242 void ConnectionManager::OnWillChangeViewHierarchy(
    243     const ServerView* view,
    244     const ServerView* new_parent,
    245     const ServerView* old_parent) {
    246   if (!display_manager_.in_setup())
    247     ProcessWillChangeViewHierarchy(view, new_parent, old_parent);
    248 }
    249 
    250 void ConnectionManager::OnViewHierarchyChanged(const ServerView* view,
    251                                                const ServerView* new_parent,
    252                                                const ServerView* old_parent) {
    253   if (!display_manager_.in_setup())
    254     ProcessViewHierarchyChanged(view, new_parent, old_parent);
    255   // TODO(beng): optimize.
    256   if (old_parent) {
    257     display_manager_.SchedulePaint(old_parent,
    258                                    gfx::Rect(old_parent->bounds().size()));
    259   }
    260   if (new_parent) {
    261     display_manager_.SchedulePaint(new_parent,
    262                                    gfx::Rect(new_parent->bounds().size()));
    263   }
    264 }
    265 
    266 void ConnectionManager::OnViewBoundsChanged(const ServerView* view,
    267                                             const gfx::Rect& old_bounds,
    268                                             const gfx::Rect& new_bounds) {
    269   ProcessViewBoundsChanged(view, old_bounds, new_bounds);
    270   if (!view->parent())
    271     return;
    272 
    273   // TODO(sky): optimize this.
    274   display_manager_.SchedulePaint(view->parent(), old_bounds);
    275   display_manager_.SchedulePaint(view->parent(), new_bounds);
    276 }
    277 
    278 void ConnectionManager::OnViewSurfaceIdChanged(const ServerView* view) {
    279   display_manager_.SchedulePaint(view, gfx::Rect(view->bounds().size()));
    280 }
    281 
    282 void ConnectionManager::OnWillChangeViewVisibility(const ServerView* view) {
    283   for (ConnectionMap::iterator i = connection_map_.begin();
    284        i != connection_map_.end();
    285        ++i) {
    286     i->second->ProcessWillChangeViewVisibility(view, IsChangeSource(i->first));
    287   }
    288 }
    289 
    290 }  // namespace service
    291 }  // namespace mojo
    292