Revert of Mandoline UI Process: Update namespaces and file names (patchset #9 id...
[chromium-blink-merge.git] / components / mus / connection_manager.cc
blob0bd66023585641f084e55c43b74b054b4075f333
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.
5 #include "components/mus/connection_manager.h"
7 #include "base/logging.h"
8 #include "base/stl_util.h"
9 #include "cc/output/compositor_frame.h"
10 #include "cc/quads/shared_quad_state.h"
11 #include "components/mus/client_connection.h"
12 #include "components/mus/connection_manager_delegate.h"
13 #include "components/mus/server_view.h"
14 #include "components/mus/view_coordinate_conversions.h"
15 #include "components/mus/view_tree_host_connection.h"
16 #include "components/mus/view_tree_impl.h"
17 #include "mojo/application/public/cpp/application_connection.h"
18 #include "mojo/converters/geometry/geometry_type_converters.h"
19 #include "mojo/converters/input_events/input_events_type_converters.h"
20 #include "mojo/converters/surfaces/surfaces_type_converters.h"
21 #include "ui/gfx/geometry/size_conversions.h"
23 using mojo::ConnectionSpecificId;
25 namespace view_manager {
27 ConnectionManager::ScopedChange::ScopedChange(
28 ViewTreeImpl* connection,
29 ConnectionManager* connection_manager,
30 bool is_delete_view)
31 : connection_manager_(connection_manager),
32 connection_id_(connection->id()),
33 is_delete_view_(is_delete_view) {
34 connection_manager_->PrepareForChange(this);
37 ConnectionManager::ScopedChange::~ScopedChange() {
38 connection_manager_->FinishChange();
41 ConnectionManager::ConnectionManager(
42 ConnectionManagerDelegate* delegate,
43 const scoped_refptr<surfaces::SurfacesState>& surfaces_state)
44 : delegate_(delegate),
45 surfaces_state_(surfaces_state),
46 next_connection_id_(1),
47 next_host_id_(0),
48 current_change_(nullptr),
49 in_destructor_(false) {}
51 ConnectionManager::~ConnectionManager() {
52 in_destructor_ = true;
54 // Copy the HostConnectionMap because it will be mutated as the connections
55 // are closed.
56 HostConnectionMap host_connection_map(host_connection_map_);
57 for (auto& pair : host_connection_map)
58 pair.second->CloseConnection();
60 STLDeleteValues(&connection_map_);
61 // All the connections should have been destroyed.
62 DCHECK(host_connection_map_.empty());
63 DCHECK(connection_map_.empty());
66 void ConnectionManager::AddHost(ViewTreeHostConnection* host_connection) {
67 DCHECK_EQ(0u, host_connection_map_.count(host_connection->view_tree_host()));
68 host_connection_map_[host_connection->view_tree_host()] = host_connection;
71 ServerView* ConnectionManager::CreateServerView(const ViewId& id) {
72 ServerView* view = new ServerView(this, id);
73 view->AddObserver(this);
74 return view;
77 ConnectionSpecificId ConnectionManager::GetAndAdvanceNextConnectionId() {
78 const ConnectionSpecificId id = next_connection_id_++;
79 DCHECK_LT(id, next_connection_id_);
80 return id;
83 uint16_t ConnectionManager::GetAndAdvanceNextHostId() {
84 const uint16_t id = next_host_id_++;
85 DCHECK_LT(id, next_host_id_);
86 return id;
89 void ConnectionManager::OnConnectionError(ClientConnection* connection) {
90 // This will be null if the root has been destroyed.
91 const ViewId* view_id = connection->service()->root();
92 ServerView* view =
93 view_id ? GetView(*connection->service()->root()) : nullptr;
94 // If the ViewTree root is a viewport root, then we'll wait until
95 // the root connection goes away to cleanup.
96 if (view && (GetRootView(view) == view))
97 return;
99 scoped_ptr<ClientConnection> connection_owner(connection);
101 connection_map_.erase(connection->service()->id());
103 // Notify remaining connections so that they can cleanup.
104 for (auto& pair : connection_map_) {
105 pair.second->service()->OnWillDestroyViewTreeImpl(connection->service());
109 void ConnectionManager::OnHostConnectionClosed(
110 ViewTreeHostConnection* connection) {
111 auto it = host_connection_map_.find(connection->view_tree_host());
112 DCHECK(it != host_connection_map_.end());
114 // Get the ClientConnection by ViewTreeImpl ID.
115 ConnectionMap::iterator service_connection_it =
116 connection_map_.find(it->first->GetViewTree()->id());
117 DCHECK(service_connection_it != connection_map_.end());
119 // Tear down the associated ViewTree connection.
120 // TODO(fsamuel): I don't think this is quite right, we should tear down all
121 // connections within the root's viewport. We should probably employ an
122 // observer pattern to do this. Each ViewTreeImpl should track its
123 // parent's lifetime.
124 host_connection_map_.erase(it);
125 OnConnectionError(service_connection_it->second);
127 // If we have no more roots left, let the app know so it can terminate.
128 if (!host_connection_map_.size())
129 delegate_->OnNoMoreRootConnections();
132 void ConnectionManager::EmbedAtView(mojo::ConnectionSpecificId creator_id,
133 const ViewId& view_id,
134 uint32_t policy_bitmask,
135 mojo::URLRequestPtr request) {
136 mojo::ViewTreePtr service_ptr;
137 ClientConnection* client_connection =
138 delegate_->CreateClientConnectionForEmbedAtView(
139 this, GetProxy(&service_ptr), creator_id, request.Pass(), view_id,
140 policy_bitmask);
141 AddConnection(client_connection);
142 client_connection->service()->Init(client_connection->client(),
143 service_ptr.Pass());
144 OnConnectionMessagedClient(client_connection->service()->id());
147 ViewTreeImpl* ConnectionManager::EmbedAtView(
148 mojo::ConnectionSpecificId creator_id,
149 const ViewId& view_id,
150 uint32_t policy_bitmask,
151 mojo::ViewTreeClientPtr client) {
152 mojo::ViewTreePtr service_ptr;
153 ClientConnection* client_connection =
154 delegate_->CreateClientConnectionForEmbedAtView(
155 this, GetProxy(&service_ptr), creator_id, view_id, policy_bitmask,
156 client.Pass());
157 AddConnection(client_connection);
158 client_connection->service()->Init(client_connection->client(),
159 service_ptr.Pass());
160 OnConnectionMessagedClient(client_connection->service()->id());
162 return client_connection->service();
165 ViewTreeImpl* ConnectionManager::GetConnection(
166 ConnectionSpecificId connection_id) {
167 ConnectionMap::iterator i = connection_map_.find(connection_id);
168 return i == connection_map_.end() ? nullptr : i->second->service();
171 ServerView* ConnectionManager::GetView(const ViewId& id) {
172 for (auto& pair : host_connection_map_) {
173 if (pair.first->root_view()->id() == id)
174 return pair.first->root_view();
176 ViewTreeImpl* service = GetConnection(id.connection_id);
177 return service ? service->GetView(id) : nullptr;
180 bool ConnectionManager::IsViewAttachedToRoot(const ServerView* view) const {
181 for (auto& pair : host_connection_map_) {
182 if (pair.first->IsViewAttachedToRoot(view))
183 return true;
185 return false;
188 void ConnectionManager::SchedulePaint(const ServerView* view,
189 const gfx::Rect& bounds) {
190 for (auto& pair : host_connection_map_) {
191 if (pair.first->SchedulePaintIfInViewport(view, bounds))
192 return;
196 void ConnectionManager::OnConnectionMessagedClient(ConnectionSpecificId id) {
197 if (current_change_)
198 current_change_->MarkConnectionAsMessaged(id);
201 bool ConnectionManager::DidConnectionMessageClient(
202 ConnectionSpecificId id) const {
203 return current_change_ && current_change_->DidMessageConnection(id);
206 mojo::ViewportMetricsPtr ConnectionManager::GetViewportMetricsForView(
207 const ServerView* view) {
208 ViewTreeHostImpl* host = GetViewTreeHostByView(view);
209 if (host)
210 return host->GetViewportMetrics().Clone();
212 if (!host_connection_map_.empty())
213 return host_connection_map_.begin()->first->GetViewportMetrics().Clone();
215 mojo::ViewportMetricsPtr metrics = mojo::ViewportMetrics::New();
216 metrics->size_in_pixels = mojo::Size::New();
217 return metrics.Pass();
220 const ViewTreeImpl* ConnectionManager::GetConnectionWithRoot(
221 const ViewId& id) const {
222 for (auto& pair : connection_map_) {
223 if (pair.second->service()->IsRoot(id))
224 return pair.second->service();
226 return nullptr;
229 ViewTreeHostImpl* ConnectionManager::GetViewTreeHostByView(
230 const ServerView* view) {
231 return const_cast<ViewTreeHostImpl*>(
232 static_cast<const ConnectionManager*>(this)->GetViewTreeHostByView(view));
235 const ViewTreeHostImpl* ConnectionManager::GetViewTreeHostByView(
236 const ServerView* view) const {
237 while (view && view->parent())
238 view = view->parent();
239 for (auto& pair : host_connection_map_) {
240 if (view == pair.first->root_view())
241 return pair.first;
243 return nullptr;
246 ViewTreeImpl* ConnectionManager::GetEmbedRoot(ViewTreeImpl* service) {
247 while (service) {
248 const ViewId* root_id = service->root();
249 if (!root_id || root_id->connection_id == service->id())
250 return nullptr;
252 ViewTreeImpl* parent_service = GetConnection(root_id->connection_id);
253 service = parent_service;
254 if (service && service->is_embed_root())
255 return service;
257 return nullptr;
260 void ConnectionManager::ProcessViewBoundsChanged(const ServerView* view,
261 const gfx::Rect& old_bounds,
262 const gfx::Rect& new_bounds) {
263 for (auto& pair : connection_map_) {
264 pair.second->service()->ProcessViewBoundsChanged(
265 view, old_bounds, new_bounds, IsChangeSource(pair.first));
269 void ConnectionManager::ProcessWillChangeViewHierarchy(
270 const ServerView* view,
271 const ServerView* new_parent,
272 const ServerView* old_parent) {
273 for (auto& pair : connection_map_) {
274 pair.second->service()->ProcessWillChangeViewHierarchy(
275 view, new_parent, old_parent, IsChangeSource(pair.first));
279 void ConnectionManager::ProcessViewHierarchyChanged(
280 const ServerView* view,
281 const ServerView* new_parent,
282 const ServerView* old_parent) {
283 for (auto& pair : connection_map_) {
284 pair.second->service()->ProcessViewHierarchyChanged(
285 view, new_parent, old_parent, IsChangeSource(pair.first));
289 void ConnectionManager::ProcessViewReorder(
290 const ServerView* view,
291 const ServerView* relative_view,
292 const mojo::OrderDirection direction) {
293 for (auto& pair : connection_map_) {
294 pair.second->service()->ProcessViewReorder(view, relative_view, direction,
295 IsChangeSource(pair.first));
299 void ConnectionManager::ProcessViewDeleted(const ViewId& view) {
300 for (auto& pair : connection_map_) {
301 pair.second->service()->ProcessViewDeleted(view,
302 IsChangeSource(pair.first));
306 void ConnectionManager::ProcessViewportMetricsChanged(
307 const mojo::ViewportMetrics& old_metrics,
308 const mojo::ViewportMetrics& new_metrics) {
309 for (auto& pair : connection_map_) {
310 pair.second->service()->ProcessViewportMetricsChanged(
311 old_metrics, new_metrics, IsChangeSource(pair.first));
315 void ConnectionManager::PrepareForChange(ScopedChange* change) {
316 // Should only ever have one change in flight.
317 CHECK(!current_change_);
318 current_change_ = change;
321 void ConnectionManager::FinishChange() {
322 // PrepareForChange/FinishChange should be balanced.
323 CHECK(current_change_);
324 current_change_ = NULL;
327 void ConnectionManager::AddConnection(ClientConnection* connection) {
328 DCHECK_EQ(0u, connection_map_.count(connection->service()->id()));
329 connection_map_[connection->service()->id()] = connection;
332 scoped_ptr<cc::CompositorFrame>
333 ConnectionManager::UpdateViewTreeFromCompositorFrame(
334 const mojo::CompositorFramePtr& input) {
335 return ConvertToCompositorFrame(input, this);
338 surfaces::SurfacesState* ConnectionManager::GetSurfacesState() {
339 return surfaces_state_.get();
342 void ConnectionManager::OnScheduleViewPaint(const ServerView* view) {
343 if (!in_destructor_)
344 SchedulePaint(view, gfx::Rect(view->bounds().size()));
347 const ServerView* ConnectionManager::GetRootView(const ServerView* view) const {
348 const ViewTreeHostImpl* host = GetViewTreeHostByView(view);
349 return host ? host->root_view() : nullptr;
352 void ConnectionManager::OnViewDestroyed(ServerView* view) {
353 if (!in_destructor_)
354 ProcessViewDeleted(view->id());
357 void ConnectionManager::OnWillChangeViewHierarchy(ServerView* view,
358 ServerView* new_parent,
359 ServerView* old_parent) {
360 if (in_destructor_)
361 return;
363 ProcessWillChangeViewHierarchy(view, new_parent, old_parent);
366 void ConnectionManager::OnViewHierarchyChanged(ServerView* view,
367 ServerView* new_parent,
368 ServerView* old_parent) {
369 if (in_destructor_)
370 return;
372 ProcessViewHierarchyChanged(view, new_parent, old_parent);
374 // TODO(beng): optimize.
375 if (old_parent)
376 SchedulePaint(old_parent, gfx::Rect(old_parent->bounds().size()));
377 if (new_parent)
378 SchedulePaint(new_parent, gfx::Rect(new_parent->bounds().size()));
381 void ConnectionManager::OnViewBoundsChanged(ServerView* view,
382 const gfx::Rect& old_bounds,
383 const gfx::Rect& new_bounds) {
384 if (in_destructor_)
385 return;
387 ProcessViewBoundsChanged(view, old_bounds, new_bounds);
388 if (!view->parent())
389 return;
391 // TODO(sky): optimize this.
392 SchedulePaint(view->parent(), old_bounds);
393 SchedulePaint(view->parent(), new_bounds);
396 void ConnectionManager::OnViewReordered(ServerView* view,
397 ServerView* relative,
398 mojo::OrderDirection direction) {
399 if (!in_destructor_)
400 SchedulePaint(view, gfx::Rect(view->bounds().size()));
403 void ConnectionManager::OnWillChangeViewVisibility(ServerView* view) {
404 if (in_destructor_)
405 return;
407 // Need to repaint if the view was drawn (which means it's in the process of
408 // hiding) or the view is transitioning to drawn.
409 if (view->parent() &&
410 (view->IsDrawn() || (!view->visible() && view->parent()->IsDrawn()))) {
411 SchedulePaint(view->parent(), view->bounds());
414 for (auto& pair : connection_map_) {
415 pair.second->service()->ProcessWillChangeViewVisibility(
416 view, IsChangeSource(pair.first));
420 void ConnectionManager::OnViewSharedPropertyChanged(
421 ServerView* view,
422 const std::string& name,
423 const std::vector<uint8_t>* new_data) {
424 for (auto& pair : connection_map_) {
425 pair.second->service()->ProcessViewPropertyChanged(
426 view, name, new_data, IsChangeSource(pair.first));
430 void ConnectionManager::OnViewTextInputStateChanged(
431 ServerView* view,
432 const ui::TextInputState& state) {
433 ViewTreeHostImpl* host = GetViewTreeHostByView(view);
434 host->UpdateTextInputState(view, state);
437 bool ConnectionManager::ConvertSurfaceDrawQuad(
438 const mojo::QuadPtr& input,
439 const mojo::CompositorFrameMetadataPtr& metadata,
440 cc::SharedQuadState* sqs,
441 cc::RenderPass* render_pass) {
442 unsigned int id = static_cast<unsigned int>(
443 input->surface_quad_state->surface.To<cc::SurfaceId>().id);
444 // TODO(fsamuel): Security checks:
445 // 1. We need to make sure the embedder can only position views it's allowed
446 // to access.
447 // 2. We need to make sure that the embedder cannot place views in areas
448 // outside of its own bounds.
449 ServerView* view = GetView(ViewIdFromTransportId(id));
450 // If a CompositorFrame message arrives late, say during a navigation, then
451 // it may contain view IDs that no longer exist.
452 if (!view)
453 return false;
454 gfx::Rect bounds(input->visible_rect.To<gfx::Rect>());
455 gfx::Point p;
456 sqs->quad_to_target_transform.TransformPoint(&p);
457 bounds.set_origin(p);
458 // TODO(fsamuel): This seems like a crude way to set the size that probably
459 // doesn't work correctly in the general case. We need to get transforms
460 // working correctly in the general case.
461 bounds.set_size(gfx::ToRoundedSize(
462 gfx::ScaleSize(bounds.size(), metadata->device_scale_factor)));
463 view->SetBounds(bounds);
464 return true;
467 } // namespace view_manager