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