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/root_node_manager.h"
      6 
      7 #include "base/logging.h"
      8 #include "mojo/public/interfaces/service_provider/service_provider.mojom.h"
      9 #include "mojo/services/public/cpp/input_events/input_events_type_converters.h"
     10 #include "mojo/services/view_manager/view.h"
     11 #include "mojo/services/view_manager/view_manager_service_impl.h"
     12 #include "ui/aura/env.h"
     13 
     14 namespace mojo {
     15 namespace view_manager {
     16 namespace service {
     17 
     18 RootNodeManager::ScopedChange::ScopedChange(
     19     ViewManagerServiceImpl* connection,
     20     RootNodeManager* root,
     21     RootNodeManager::ChangeType change_type,
     22     bool is_delete_node)
     23     : root_(root),
     24       connection_id_(connection->id()),
     25       change_type_(change_type),
     26       is_delete_node_(is_delete_node) {
     27   root_->PrepareForChange(this);
     28 }
     29 
     30 RootNodeManager::ScopedChange::~ScopedChange() {
     31   root_->FinishChange();
     32 }
     33 
     34 RootNodeManager::Context::Context() {
     35   // Pass in false as native viewport creates the PlatformEventSource.
     36   aura::Env::CreateInstance(false);
     37 }
     38 
     39 RootNodeManager::Context::~Context() {
     40   aura::Env::DeleteInstance();
     41 }
     42 
     43 RootNodeManager::RootNodeManager(ServiceProvider* service_provider,
     44                                  RootViewManagerDelegate* view_manager_delegate)
     45     : service_provider_(service_provider),
     46       next_connection_id_(1),
     47       next_server_change_id_(1),
     48       root_view_manager_(service_provider, this, view_manager_delegate),
     49       root_(this, RootNodeId()),
     50       current_change_(NULL) {
     51 }
     52 
     53 RootNodeManager::~RootNodeManager() {
     54   while (!connections_created_by_connect_.empty())
     55     delete *(connections_created_by_connect_.begin());
     56   // All the connections should have been destroyed.
     57   DCHECK(connection_map_.empty());
     58 }
     59 
     60 ConnectionSpecificId RootNodeManager::GetAndAdvanceNextConnectionId() {
     61   const ConnectionSpecificId id = next_connection_id_++;
     62   DCHECK_LT(id, next_connection_id_);
     63   return id;
     64 }
     65 
     66 void RootNodeManager::AddConnection(ViewManagerServiceImpl* connection) {
     67   DCHECK_EQ(0u, connection_map_.count(connection->id()));
     68   connection_map_[connection->id()] = connection;
     69 }
     70 
     71 void RootNodeManager::RemoveConnection(ViewManagerServiceImpl* connection) {
     72   connection_map_.erase(connection->id());
     73   connections_created_by_connect_.erase(connection);
     74 
     75   // Notify remaining connections so that they can cleanup.
     76   for (ConnectionMap::const_iterator i = connection_map_.begin();
     77        i != connection_map_.end(); ++i) {
     78     i->second->OnViewManagerServiceImplDestroyed(connection->id());
     79   }
     80 }
     81 
     82 void RootNodeManager::EmbedRoot(const std::string& url) {
     83   CHECK(connection_map_.empty());
     84   Array<Id> roots(0);
     85   EmbedImpl(kRootConnection, String::From(url), roots);
     86 }
     87 
     88 void RootNodeManager::Embed(ConnectionSpecificId creator_id,
     89                             const String& url,
     90                             const Array<Id>& node_ids) {
     91   CHECK_GT(node_ids.size(), 0u);
     92   EmbedImpl(creator_id, url, node_ids)->set_delete_on_connection_error();
     93 }
     94 
     95 ViewManagerServiceImpl* RootNodeManager::GetConnection(
     96     ConnectionSpecificId connection_id) {
     97   ConnectionMap::iterator i = connection_map_.find(connection_id);
     98   return i == connection_map_.end() ? NULL : i->second;
     99 }
    100 
    101 Node* RootNodeManager::GetNode(const NodeId& id) {
    102   if (id == root_.id())
    103     return &root_;
    104   ConnectionMap::iterator i = connection_map_.find(id.connection_id);
    105   return i == connection_map_.end() ? NULL : i->second->GetNode(id);
    106 }
    107 
    108 View* RootNodeManager::GetView(const ViewId& id) {
    109   ConnectionMap::iterator i = connection_map_.find(id.connection_id);
    110   return i == connection_map_.end() ? NULL : i->second->GetView(id);
    111 }
    112 
    113 void RootNodeManager::OnConnectionMessagedClient(ConnectionSpecificId id) {
    114   if (current_change_)
    115     current_change_->MarkConnectionAsMessaged(id);
    116 }
    117 
    118 bool RootNodeManager::DidConnectionMessageClient(
    119     ConnectionSpecificId id) const {
    120   return current_change_ && current_change_->DidMessageConnection(id);
    121 }
    122 
    123 ViewManagerServiceImpl* RootNodeManager::GetConnectionByCreator(
    124     ConnectionSpecificId creator_id,
    125     const std::string& url) const {
    126   for (ConnectionMap::const_iterator i = connection_map_.begin();
    127        i != connection_map_.end(); ++i) {
    128     if (i->second->creator_id() == creator_id && i->second->url() == url)
    129       return i->second;
    130   }
    131   return NULL;
    132 }
    133 
    134 void RootNodeManager::DispatchViewInputEventToWindowManager(
    135     const View* view,
    136     const ui::Event* event) {
    137   // Input events are forwarded to the WindowManager. The WindowManager
    138   // eventually calls back to us with DispatchOnViewInputEvent().
    139   ViewManagerServiceImpl* connection = GetConnection(kWindowManagerConnection);
    140   if (!connection)
    141     return;
    142   connection->client()->DispatchOnViewInputEvent(
    143       ViewIdToTransportId(view->id()),
    144       TypeConverter<EventPtr, ui::Event>::ConvertFrom(*event));
    145 }
    146 
    147 void RootNodeManager::ProcessNodeBoundsChanged(const Node* node,
    148                                                const gfx::Rect& old_bounds,
    149                                                const gfx::Rect& new_bounds) {
    150   for (ConnectionMap::iterator i = connection_map_.begin();
    151        i != connection_map_.end(); ++i) {
    152     i->second->ProcessNodeBoundsChanged(node, old_bounds, new_bounds,
    153                                         IsChangeSource(i->first));
    154   }
    155 }
    156 
    157 void RootNodeManager::ProcessNodeHierarchyChanged(const Node* node,
    158                                                   const Node* new_parent,
    159                                                   const Node* old_parent) {
    160   for (ConnectionMap::iterator i = connection_map_.begin();
    161        i != connection_map_.end(); ++i) {
    162     i->second->ProcessNodeHierarchyChanged(
    163         node, new_parent, old_parent, next_server_change_id_,
    164         IsChangeSource(i->first));
    165   }
    166 }
    167 
    168 void RootNodeManager::ProcessNodeReorder(const Node* node,
    169                                          const Node* relative_node,
    170                                          const OrderDirection direction) {
    171   for (ConnectionMap::iterator i = connection_map_.begin();
    172        i != connection_map_.end(); ++i) {
    173     i->second->ProcessNodeReorder(
    174         node, relative_node, direction, next_server_change_id_,
    175         IsChangeSource(i->first));
    176   }
    177 }
    178 
    179 void RootNodeManager::ProcessNodeViewReplaced(const Node* node,
    180                                               const View* new_view,
    181                                               const View* old_view) {
    182   for (ConnectionMap::iterator i = connection_map_.begin();
    183        i != connection_map_.end(); ++i) {
    184     i->second->ProcessNodeViewReplaced(node, new_view, old_view,
    185                                        IsChangeSource(i->first));
    186   }
    187 }
    188 
    189 void RootNodeManager::ProcessNodeDeleted(const NodeId& node) {
    190   for (ConnectionMap::iterator i = connection_map_.begin();
    191        i != connection_map_.end(); ++i) {
    192     i->second->ProcessNodeDeleted(node, next_server_change_id_,
    193                                  IsChangeSource(i->first));
    194   }
    195 }
    196 
    197 void RootNodeManager::ProcessViewDeleted(const ViewId& view) {
    198   for (ConnectionMap::iterator i = connection_map_.begin();
    199        i != connection_map_.end(); ++i) {
    200     i->second->ProcessViewDeleted(view, IsChangeSource(i->first));
    201   }
    202 }
    203 
    204 void RootNodeManager::PrepareForChange(ScopedChange* change) {
    205   // Should only ever have one change in flight.
    206   CHECK(!current_change_);
    207   current_change_ = change;
    208 }
    209 
    210 void RootNodeManager::FinishChange() {
    211   // PrepareForChange/FinishChange should be balanced.
    212   CHECK(current_change_);
    213   if (current_change_->change_type() == CHANGE_TYPE_ADVANCE_SERVER_CHANGE_ID)
    214     next_server_change_id_++;
    215   current_change_ = NULL;
    216 }
    217 
    218 ViewManagerServiceImpl* RootNodeManager::EmbedImpl(
    219     const ConnectionSpecificId creator_id,
    220     const String& url,
    221     const Array<Id>& node_ids) {
    222   MessagePipe pipe;
    223   service_provider_->ConnectToService(
    224       url,
    225       ViewManagerServiceImpl::Client::Name_,
    226       pipe.handle1.Pass(),
    227       String());
    228 
    229   std::string creator_url;
    230   ConnectionMap::const_iterator it = connection_map_.find(creator_id);
    231   if (it != connection_map_.end())
    232     creator_url = it->second->url();
    233 
    234   ViewManagerServiceImpl* connection =
    235       new ViewManagerServiceImpl(this,
    236                                 creator_id,
    237                                 creator_url,
    238                                 url.To<std::string>());
    239   connection->SetRoots(node_ids);
    240   BindToPipe(connection, pipe.handle0.Pass());
    241   connections_created_by_connect_.insert(connection);
    242   return connection;
    243 }
    244 
    245 void RootNodeManager::OnNodeHierarchyChanged(const Node* node,
    246                                              const Node* new_parent,
    247                                              const Node* old_parent) {
    248   if (!root_view_manager_.in_setup())
    249     ProcessNodeHierarchyChanged(node, new_parent, old_parent);
    250 }
    251 
    252 void RootNodeManager::OnNodeViewReplaced(const Node* node,
    253                                          const View* new_view,
    254                                          const View* old_view) {
    255   ProcessNodeViewReplaced(node, new_view, old_view);
    256 }
    257 
    258 void RootNodeManager::OnViewInputEvent(const View* view,
    259                                        const ui::Event* event) {
    260   DispatchViewInputEventToWindowManager(view, event);
    261 }
    262 
    263 }  // namespace service
    264 }  // namespace view_manager
    265 }  // namespace mojo
    266