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 14namespace mojo { 15namespace view_manager { 16namespace service { 17 18RootNodeManager::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 30RootNodeManager::ScopedChange::~ScopedChange() { 31 root_->FinishChange(); 32} 33 34RootNodeManager::Context::Context() { 35 // Pass in false as native viewport creates the PlatformEventSource. 36 aura::Env::CreateInstance(false); 37} 38 39RootNodeManager::Context::~Context() { 40 aura::Env::DeleteInstance(); 41} 42 43RootNodeManager::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 53RootNodeManager::~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 60ConnectionSpecificId RootNodeManager::GetAndAdvanceNextConnectionId() { 61 const ConnectionSpecificId id = next_connection_id_++; 62 DCHECK_LT(id, next_connection_id_); 63 return id; 64} 65 66void RootNodeManager::AddConnection(ViewManagerServiceImpl* connection) { 67 DCHECK_EQ(0u, connection_map_.count(connection->id())); 68 connection_map_[connection->id()] = connection; 69} 70 71void 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 82void 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 88void 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 95ViewManagerServiceImpl* 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 101Node* 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 108View* 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 113void RootNodeManager::OnConnectionMessagedClient(ConnectionSpecificId id) { 114 if (current_change_) 115 current_change_->MarkConnectionAsMessaged(id); 116} 117 118bool RootNodeManager::DidConnectionMessageClient( 119 ConnectionSpecificId id) const { 120 return current_change_ && current_change_->DidMessageConnection(id); 121} 122 123ViewManagerServiceImpl* 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 134void 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 147void 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 157void 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 168void 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 179void 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 189void 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 197void 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 204void RootNodeManager::PrepareForChange(ScopedChange* change) { 205 // Should only ever have one change in flight. 206 CHECK(!current_change_); 207 current_change_ = change; 208} 209 210void 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 218ViewManagerServiceImpl* 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 245void 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 252void RootNodeManager::OnNodeViewReplaced(const Node* node, 253 const View* new_view, 254 const View* old_view) { 255 ProcessNodeViewReplaced(node, new_view, old_view); 256} 257 258void 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