Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / mojo / services / view_manager / root_node_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/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     RootViewManagerDelegate* view_manager_delegate,
43     const Callback<void()>& native_viewport_closed_callback)
44     : app_connection_(app_connection),
45       next_connection_id_(1),
46       root_view_manager_(app_connection,
47                          this,
48                          view_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 (!root_view_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 }
256
257 }  // namespace service
258 }  // namespace mojo