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 "mojo/services/view_manager/connection_manager.h"
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"
16 ConnectionManager::ScopedChange::ScopedChange(
17 ViewManagerServiceImpl* connection,
18 ConnectionManager* connection_manager,
20 : connection_manager_(connection_manager),
21 connection_id_(connection->id()),
22 is_delete_view_(is_delete_view) {
23 connection_manager_->PrepareForChange(this);
26 ConnectionManager::ScopedChange::~ScopedChange() {
27 connection_manager_->FinishChange();
30 ConnectionManager::ConnectionManager(
31 ApplicationConnection* app_connection,
32 const Callback<void()>& native_viewport_closed_callback)
33 : app_connection_(app_connection),
34 next_connection_id_(1),
35 display_manager_(app_connection,
37 native_viewport_closed_callback),
38 root_(new ServerView(this, RootViewId())),
39 current_change_(NULL) {
40 root_->SetBounds(gfx::Rect(800, 600));
43 ConnectionManager::~ConnectionManager() {
44 while (!connections_created_by_connect_.empty())
45 delete *(connections_created_by_connect_.begin());
46 // All the connections should have been destroyed.
47 DCHECK(connection_map_.empty());
51 ConnectionSpecificId ConnectionManager::GetAndAdvanceNextConnectionId() {
52 const ConnectionSpecificId id = next_connection_id_++;
53 DCHECK_LT(id, next_connection_id_);
57 void ConnectionManager::AddConnection(ViewManagerServiceImpl* connection) {
58 DCHECK_EQ(0u, connection_map_.count(connection->id()));
59 connection_map_[connection->id()] = connection;
62 void ConnectionManager::RemoveConnection(ViewManagerServiceImpl* connection) {
63 connection_map_.erase(connection->id());
64 connections_created_by_connect_.erase(connection);
66 // Notify remaining connections so that they can cleanup.
67 for (ConnectionMap::const_iterator i = connection_map_.begin();
68 i != connection_map_.end();
70 i->second->OnViewManagerServiceImplDestroyed(connection->id());
74 void ConnectionManager::EmbedRoot(
75 const std::string& url,
76 InterfaceRequest<ServiceProvider> service_provider) {
77 if (connection_map_.empty()) {
78 EmbedImpl(kInvalidConnectionId,
81 service_provider.Pass());
84 ViewManagerServiceImpl* connection = GetConnection(kWindowManagerConnection);
85 connection->client()->Embed(url, service_provider.Pass());
88 void ConnectionManager::Embed(
89 ConnectionSpecificId creator_id,
92 InterfaceRequest<ServiceProvider> service_provider) {
95 ViewIdFromTransportId(transport_view_id),
96 service_provider.Pass())->set_delete_on_connection_error();
99 ViewManagerServiceImpl* ConnectionManager::GetConnection(
100 ConnectionSpecificId connection_id) {
101 ConnectionMap::iterator i = connection_map_.find(connection_id);
102 return i == connection_map_.end() ? NULL : i->second;
105 ServerView* ConnectionManager::GetView(const ViewId& id) {
106 if (id == root_->id())
108 ConnectionMap::iterator i = connection_map_.find(id.connection_id);
109 return i == connection_map_.end() ? NULL : i->second->GetView(id);
112 void ConnectionManager::OnConnectionMessagedClient(ConnectionSpecificId id) {
114 current_change_->MarkConnectionAsMessaged(id);
117 bool ConnectionManager::DidConnectionMessageClient(
118 ConnectionSpecificId id) const {
119 return current_change_ && current_change_->DidMessageConnection(id);
122 const ViewManagerServiceImpl* ConnectionManager::GetConnectionWithRoot(
123 const ViewId& id) const {
124 for (ConnectionMap::const_iterator i = connection_map_.begin();
125 i != connection_map_.end();
127 if (i->second->HasRoot(id))
133 void ConnectionManager::DispatchViewInputEventToWindowManager(EventPtr event) {
134 // Input events are forwarded to the WindowManager. The WindowManager
135 // eventually calls back to us with DispatchOnViewInputEvent().
136 ViewManagerServiceImpl* connection = GetConnection(kWindowManagerConnection);
139 connection->client()->DispatchOnViewInputEvent(event.Pass());
142 void ConnectionManager::ProcessViewBoundsChanged(const ServerView* view,
143 const gfx::Rect& old_bounds,
144 const gfx::Rect& new_bounds) {
145 for (ConnectionMap::iterator i = connection_map_.begin();
146 i != connection_map_.end();
148 i->second->ProcessViewBoundsChanged(
149 view, old_bounds, new_bounds, IsChangeSource(i->first));
153 void ConnectionManager::ProcessWillChangeViewHierarchy(
154 const ServerView* view,
155 const ServerView* new_parent,
156 const ServerView* old_parent) {
157 for (ConnectionMap::iterator i = connection_map_.begin();
158 i != connection_map_.end();
160 i->second->ProcessWillChangeViewHierarchy(
161 view, new_parent, old_parent, IsChangeSource(i->first));
165 void ConnectionManager::ProcessViewHierarchyChanged(
166 const ServerView* view,
167 const ServerView* new_parent,
168 const ServerView* old_parent) {
169 for (ConnectionMap::iterator i = connection_map_.begin();
170 i != connection_map_.end();
172 i->second->ProcessViewHierarchyChanged(
173 view, new_parent, old_parent, IsChangeSource(i->first));
177 void ConnectionManager::ProcessViewReorder(const ServerView* view,
178 const ServerView* relative_view,
179 const OrderDirection direction) {
180 for (ConnectionMap::iterator i = connection_map_.begin();
181 i != connection_map_.end();
183 i->second->ProcessViewReorder(
184 view, relative_view, direction, IsChangeSource(i->first));
188 void ConnectionManager::ProcessViewDeleted(const ViewId& view) {
189 for (ConnectionMap::iterator i = connection_map_.begin();
190 i != connection_map_.end();
192 i->second->ProcessViewDeleted(view, IsChangeSource(i->first));
196 void ConnectionManager::PrepareForChange(ScopedChange* change) {
197 // Should only ever have one change in flight.
198 CHECK(!current_change_);
199 current_change_ = change;
202 void ConnectionManager::FinishChange() {
203 // PrepareForChange/FinishChange should be balanced.
204 CHECK(current_change_);
205 current_change_ = NULL;
208 ViewManagerServiceImpl* ConnectionManager::EmbedImpl(
209 const ConnectionSpecificId creator_id,
211 const ViewId& root_id,
212 InterfaceRequest<ServiceProvider> service_provider) {
215 ServiceProvider* view_manager_service_provider =
216 app_connection_->ConnectToApplication(url)->GetServiceProvider();
217 view_manager_service_provider->ConnectToService(
218 ViewManagerServiceImpl::Client::Name_, pipe.handle1.Pass());
220 std::string creator_url;
221 ConnectionMap::const_iterator it = connection_map_.find(creator_id);
222 if (it != connection_map_.end())
223 creator_url = it->second->url();
225 ViewManagerServiceImpl* connection =
226 new ViewManagerServiceImpl(this,
229 url.To<std::string>(),
231 service_provider.Pass());
232 WeakBindToPipe(connection, pipe.handle0.Pass());
233 connections_created_by_connect_.insert(connection);
234 OnConnectionMessagedClient(connection->id());
238 void ConnectionManager::OnViewDestroyed(const ServerView* view) {
239 ProcessViewDeleted(view->id());
242 void ConnectionManager::OnWillChangeViewHierarchy(
243 const ServerView* view,
244 const ServerView* new_parent,
245 const ServerView* old_parent) {
246 if (!display_manager_.in_setup())
247 ProcessWillChangeViewHierarchy(view, new_parent, old_parent);
250 void ConnectionManager::OnViewHierarchyChanged(const ServerView* view,
251 const ServerView* new_parent,
252 const ServerView* old_parent) {
253 if (!display_manager_.in_setup())
254 ProcessViewHierarchyChanged(view, new_parent, old_parent);
255 // TODO(beng): optimize.
257 display_manager_.SchedulePaint(old_parent,
258 gfx::Rect(old_parent->bounds().size()));
261 display_manager_.SchedulePaint(new_parent,
262 gfx::Rect(new_parent->bounds().size()));
266 void ConnectionManager::OnViewBoundsChanged(const ServerView* view,
267 const gfx::Rect& old_bounds,
268 const gfx::Rect& new_bounds) {
269 ProcessViewBoundsChanged(view, old_bounds, new_bounds);
273 // TODO(sky): optimize this.
274 display_manager_.SchedulePaint(view->parent(), old_bounds);
275 display_manager_.SchedulePaint(view->parent(), new_bounds);
278 void ConnectionManager::OnViewSurfaceIdChanged(const ServerView* view) {
279 display_manager_.SchedulePaint(view, gfx::Rect(view->bounds().size()));
282 void ConnectionManager::OnWillChangeViewVisibility(const ServerView* view) {
283 for (ConnectionMap::iterator i = connection_map_.begin();
284 i != connection_map_.end();
286 i->second->ProcessWillChangeViewVisibility(view, IsChangeSource(i->first));
290 } // namespace service