• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/connection_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 
13 namespace mojo {
14 namespace service {
15 
ScopedChange(ViewManagerServiceImpl * connection,ConnectionManager * connection_manager,bool is_delete_view)16 ConnectionManager::ScopedChange::ScopedChange(
17     ViewManagerServiceImpl* connection,
18     ConnectionManager* connection_manager,
19     bool is_delete_view)
20     : connection_manager_(connection_manager),
21       connection_id_(connection->id()),
22       is_delete_view_(is_delete_view) {
23   connection_manager_->PrepareForChange(this);
24 }
25 
~ScopedChange()26 ConnectionManager::ScopedChange::~ScopedChange() {
27   connection_manager_->FinishChange();
28 }
29 
ConnectionManager(ApplicationConnection * app_connection,const Callback<void ()> & native_viewport_closed_callback)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,
36                        this,
37                        native_viewport_closed_callback),
38       root_(new ServerView(this, RootViewId())),
39       current_change_(NULL) {
40   root_->SetBounds(gfx::Rect(800, 600));
41 }
42 
~ConnectionManager()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());
48   root_.reset();
49 }
50 
GetAndAdvanceNextConnectionId()51 ConnectionSpecificId ConnectionManager::GetAndAdvanceNextConnectionId() {
52   const ConnectionSpecificId id = next_connection_id_++;
53   DCHECK_LT(id, next_connection_id_);
54   return id;
55 }
56 
AddConnection(ViewManagerServiceImpl * connection)57 void ConnectionManager::AddConnection(ViewManagerServiceImpl* connection) {
58   DCHECK_EQ(0u, connection_map_.count(connection->id()));
59   connection_map_[connection->id()] = connection;
60 }
61 
RemoveConnection(ViewManagerServiceImpl * connection)62 void ConnectionManager::RemoveConnection(ViewManagerServiceImpl* connection) {
63   connection_map_.erase(connection->id());
64   connections_created_by_connect_.erase(connection);
65 
66   // Notify remaining connections so that they can cleanup.
67   for (ConnectionMap::const_iterator i = connection_map_.begin();
68        i != connection_map_.end();
69        ++i) {
70     i->second->OnViewManagerServiceImplDestroyed(connection->id());
71   }
72 }
73 
EmbedRoot(const std::string & url,InterfaceRequest<ServiceProvider> service_provider)74 void ConnectionManager::EmbedRoot(
75     const std::string& url,
76     InterfaceRequest<ServiceProvider> service_provider) {
77   if (connection_map_.empty()) {
78     EmbedImpl(kInvalidConnectionId,
79               String::From(url),
80               RootViewId(),
81               service_provider.Pass());
82     return;
83   }
84   ViewManagerServiceImpl* connection = GetConnection(kWindowManagerConnection);
85   connection->client()->Embed(url, service_provider.Pass());
86 }
87 
Embed(ConnectionSpecificId creator_id,const String & url,Id transport_view_id,InterfaceRequest<ServiceProvider> service_provider)88 void ConnectionManager::Embed(
89     ConnectionSpecificId creator_id,
90     const String& url,
91     Id transport_view_id,
92     InterfaceRequest<ServiceProvider> service_provider) {
93   EmbedImpl(creator_id,
94             url,
95             ViewIdFromTransportId(transport_view_id),
96             service_provider.Pass())->set_delete_on_connection_error();
97 }
98 
GetConnection(ConnectionSpecificId connection_id)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;
103 }
104 
GetView(const ViewId & id)105 ServerView* ConnectionManager::GetView(const ViewId& id) {
106   if (id == root_->id())
107     return root_.get();
108   ConnectionMap::iterator i = connection_map_.find(id.connection_id);
109   return i == connection_map_.end() ? NULL : i->second->GetView(id);
110 }
111 
OnConnectionMessagedClient(ConnectionSpecificId id)112 void ConnectionManager::OnConnectionMessagedClient(ConnectionSpecificId id) {
113   if (current_change_)
114     current_change_->MarkConnectionAsMessaged(id);
115 }
116 
DidConnectionMessageClient(ConnectionSpecificId id) const117 bool ConnectionManager::DidConnectionMessageClient(
118     ConnectionSpecificId id) const {
119   return current_change_ && current_change_->DidMessageConnection(id);
120 }
121 
GetConnectionWithRoot(const ViewId & id) const122 const ViewManagerServiceImpl* ConnectionManager::GetConnectionWithRoot(
123     const ViewId& id) const {
124   for (ConnectionMap::const_iterator i = connection_map_.begin();
125        i != connection_map_.end();
126        ++i) {
127     if (i->second->HasRoot(id))
128       return i->second;
129   }
130   return NULL;
131 }
132 
DispatchViewInputEventToWindowManager(EventPtr event)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);
137   if (!connection)
138     return;
139   connection->client()->DispatchOnViewInputEvent(event.Pass());
140 }
141 
ProcessViewBoundsChanged(const ServerView * view,const gfx::Rect & old_bounds,const gfx::Rect & new_bounds)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();
147        ++i) {
148     i->second->ProcessViewBoundsChanged(
149         view, old_bounds, new_bounds, IsChangeSource(i->first));
150   }
151 }
152 
ProcessWillChangeViewHierarchy(const ServerView * view,const ServerView * new_parent,const ServerView * old_parent)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();
159        ++i) {
160     i->second->ProcessWillChangeViewHierarchy(
161         view, new_parent, old_parent, IsChangeSource(i->first));
162   }
163 }
164 
ProcessViewHierarchyChanged(const ServerView * view,const ServerView * new_parent,const ServerView * old_parent)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();
171        ++i) {
172     i->second->ProcessViewHierarchyChanged(
173         view, new_parent, old_parent, IsChangeSource(i->first));
174   }
175 }
176 
ProcessViewReorder(const ServerView * view,const ServerView * relative_view,const OrderDirection direction)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();
182        ++i) {
183     i->second->ProcessViewReorder(
184         view, relative_view, direction, IsChangeSource(i->first));
185   }
186 }
187 
ProcessViewDeleted(const ViewId & view)188 void ConnectionManager::ProcessViewDeleted(const ViewId& view) {
189   for (ConnectionMap::iterator i = connection_map_.begin();
190        i != connection_map_.end();
191        ++i) {
192     i->second->ProcessViewDeleted(view, IsChangeSource(i->first));
193   }
194 }
195 
PrepareForChange(ScopedChange * change)196 void ConnectionManager::PrepareForChange(ScopedChange* change) {
197   // Should only ever have one change in flight.
198   CHECK(!current_change_);
199   current_change_ = change;
200 }
201 
FinishChange()202 void ConnectionManager::FinishChange() {
203   // PrepareForChange/FinishChange should be balanced.
204   CHECK(current_change_);
205   current_change_ = NULL;
206 }
207 
EmbedImpl(const ConnectionSpecificId creator_id,const String & url,const ViewId & root_id,InterfaceRequest<ServiceProvider> service_provider)208 ViewManagerServiceImpl* ConnectionManager::EmbedImpl(
209     const ConnectionSpecificId creator_id,
210     const String& url,
211     const ViewId& root_id,
212     InterfaceRequest<ServiceProvider> service_provider) {
213   MessagePipe pipe;
214 
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());
219 
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();
224 
225   ViewManagerServiceImpl* connection =
226       new ViewManagerServiceImpl(this,
227                                  creator_id,
228                                  creator_url,
229                                  url.To<std::string>(),
230                                  root_id,
231                                  service_provider.Pass());
232   WeakBindToPipe(connection, pipe.handle0.Pass());
233   connections_created_by_connect_.insert(connection);
234   OnConnectionMessagedClient(connection->id());
235   return connection;
236 }
237 
OnViewDestroyed(const ServerView * view)238 void ConnectionManager::OnViewDestroyed(const ServerView* view) {
239   ProcessViewDeleted(view->id());
240 }
241 
OnWillChangeViewHierarchy(const ServerView * view,const ServerView * new_parent,const ServerView * old_parent)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);
248 }
249 
OnViewHierarchyChanged(const ServerView * view,const ServerView * new_parent,const ServerView * 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.
256   if (old_parent) {
257     display_manager_.SchedulePaint(old_parent,
258                                    gfx::Rect(old_parent->bounds().size()));
259   }
260   if (new_parent) {
261     display_manager_.SchedulePaint(new_parent,
262                                    gfx::Rect(new_parent->bounds().size()));
263   }
264 }
265 
OnViewBoundsChanged(const ServerView * view,const gfx::Rect & old_bounds,const gfx::Rect & new_bounds)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);
270   if (!view->parent())
271     return;
272 
273   // TODO(sky): optimize this.
274   display_manager_.SchedulePaint(view->parent(), old_bounds);
275   display_manager_.SchedulePaint(view->parent(), new_bounds);
276 }
277 
OnViewSurfaceIdChanged(const ServerView * view)278 void ConnectionManager::OnViewSurfaceIdChanged(const ServerView* view) {
279   display_manager_.SchedulePaint(view, gfx::Rect(view->bounds().size()));
280 }
281 
OnWillChangeViewVisibility(const ServerView * view)282 void ConnectionManager::OnWillChangeViewVisibility(const ServerView* view) {
283   for (ConnectionMap::iterator i = connection_map_.begin();
284        i != connection_map_.end();
285        ++i) {
286     i->second->ProcessWillChangeViewVisibility(view, IsChangeSource(i->first));
287   }
288 }
289 
290 }  // namespace service
291 }  // namespace mojo
292