Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / mojo / services / view_manager / connection_manager.cc
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
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
26 ConnectionManager::ScopedChange::~ScopedChange() {
27   connection_manager_->FinishChange();
28 }
29
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
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
51 ConnectionSpecificId ConnectionManager::GetAndAdvanceNextConnectionId() {
52   const ConnectionSpecificId id = next_connection_id_++;
53   DCHECK_LT(id, next_connection_id_);
54   return id;
55 }
56
57 void ConnectionManager::AddConnection(ViewManagerServiceImpl* connection) {
58   DCHECK_EQ(0u, connection_map_.count(connection->id()));
59   connection_map_[connection->id()] = connection;
60 }
61
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
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
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
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
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
112 void ConnectionManager::OnConnectionMessagedClient(ConnectionSpecificId id) {
113   if (current_change_)
114     current_change_->MarkConnectionAsMessaged(id);
115 }
116
117 bool ConnectionManager::DidConnectionMessageClient(
118     ConnectionSpecificId id) const {
119   return current_change_ && current_change_->DidMessageConnection(id);
120 }
121
122 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
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
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
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
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
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
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
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
202 void ConnectionManager::FinishChange() {
203   // PrepareForChange/FinishChange should be balanced.
204   CHECK(current_change_);
205   current_change_ = NULL;
206 }
207
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
238 void ConnectionManager::OnViewDestroyed(const ServerView* view) {
239   ProcessViewDeleted(view->id());
240 }
241
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
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
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
278 void ConnectionManager::OnViewSurfaceIdChanged(const ServerView* view) {
279   display_manager_.SchedulePaint(view, gfx::Rect(view->bounds().size()));
280 }
281
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