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