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