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
ScopedChange(ViewManagerServiceImpl * connection,RootNodeManager * root,RootNodeManager::ChangeType change_type,bool is_delete_node)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
~ScopedChange()30 RootNodeManager::ScopedChange::~ScopedChange() {
31 root_->FinishChange();
32 }
33
Context()34 RootNodeManager::Context::Context() {
35 // Pass in false as native viewport creates the PlatformEventSource.
36 aura::Env::CreateInstance(false);
37 }
38
~Context()39 RootNodeManager::Context::~Context() {
40 aura::Env::DeleteInstance();
41 }
42
RootNodeManager(ServiceProvider * service_provider,RootViewManagerDelegate * view_manager_delegate)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
~RootNodeManager()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
GetAndAdvanceNextConnectionId()60 ConnectionSpecificId RootNodeManager::GetAndAdvanceNextConnectionId() {
61 const ConnectionSpecificId id = next_connection_id_++;
62 DCHECK_LT(id, next_connection_id_);
63 return id;
64 }
65
AddConnection(ViewManagerServiceImpl * connection)66 void RootNodeManager::AddConnection(ViewManagerServiceImpl* connection) {
67 DCHECK_EQ(0u, connection_map_.count(connection->id()));
68 connection_map_[connection->id()] = connection;
69 }
70
RemoveConnection(ViewManagerServiceImpl * connection)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
EmbedRoot(const std::string & url)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
Embed(ConnectionSpecificId creator_id,const String & url,const Array<Id> & node_ids)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
GetConnection(ConnectionSpecificId connection_id)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
GetNode(const NodeId & id)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
GetView(const ViewId & id)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
OnConnectionMessagedClient(ConnectionSpecificId id)113 void RootNodeManager::OnConnectionMessagedClient(ConnectionSpecificId id) {
114 if (current_change_)
115 current_change_->MarkConnectionAsMessaged(id);
116 }
117
DidConnectionMessageClient(ConnectionSpecificId id) const118 bool RootNodeManager::DidConnectionMessageClient(
119 ConnectionSpecificId id) const {
120 return current_change_ && current_change_->DidMessageConnection(id);
121 }
122
GetConnectionByCreator(ConnectionSpecificId creator_id,const std::string & url) const123 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
DispatchViewInputEventToWindowManager(const View * view,const ui::Event * event)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
ProcessNodeBoundsChanged(const Node * node,const gfx::Rect & old_bounds,const gfx::Rect & new_bounds)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
ProcessNodeHierarchyChanged(const Node * node,const Node * new_parent,const Node * old_parent)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
ProcessNodeReorder(const Node * node,const Node * relative_node,const OrderDirection direction)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
ProcessNodeViewReplaced(const Node * node,const View * new_view,const View * old_view)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
ProcessNodeDeleted(const NodeId & node)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
ProcessViewDeleted(const ViewId & view)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
PrepareForChange(ScopedChange * change)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
FinishChange()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
EmbedImpl(const ConnectionSpecificId creator_id,const String & url,const Array<Id> & node_ids)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
OnNodeHierarchyChanged(const Node * node,const Node * new_parent,const Node * old_parent)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
OnNodeViewReplaced(const Node * node,const View * new_view,const View * old_view)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
OnViewInputEvent(const View * view,const ui::Event * event)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