• 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/root_node_manager.h"
6 
7 #include "base/logging.h"
8 #include "mojo/public/interfaces/service_provider/service_provider.mojom.h"
9 #include "mojo/services/public/cpp/input_events/input_events_type_converters.h"
10 #include "mojo/services/view_manager/view.h"
11 #include "mojo/services/view_manager/view_manager_service_impl.h"
12 #include "ui/aura/env.h"
13 
14 namespace mojo {
15 namespace view_manager {
16 namespace service {
17 
ScopedChange(ViewManagerServiceImpl * connection,RootNodeManager * root,RootNodeManager::ChangeType change_type,bool is_delete_node)18 RootNodeManager::ScopedChange::ScopedChange(
19     ViewManagerServiceImpl* connection,
20     RootNodeManager* root,
21     RootNodeManager::ChangeType change_type,
22     bool is_delete_node)
23     : root_(root),
24       connection_id_(connection->id()),
25       change_type_(change_type),
26       is_delete_node_(is_delete_node) {
27   root_->PrepareForChange(this);
28 }
29 
~ScopedChange()30 RootNodeManager::ScopedChange::~ScopedChange() {
31   root_->FinishChange();
32 }
33 
Context()34 RootNodeManager::Context::Context() {
35   // Pass in false as native viewport creates the PlatformEventSource.
36   aura::Env::CreateInstance(false);
37 }
38 
~Context()39 RootNodeManager::Context::~Context() {
40   aura::Env::DeleteInstance();
41 }
42 
RootNodeManager(ServiceProvider * service_provider,RootViewManagerDelegate * view_manager_delegate)43 RootNodeManager::RootNodeManager(ServiceProvider* service_provider,
44                                  RootViewManagerDelegate* view_manager_delegate)
45     : service_provider_(service_provider),
46       next_connection_id_(1),
47       next_server_change_id_(1),
48       root_view_manager_(service_provider, this, view_manager_delegate),
49       root_(this, RootNodeId()),
50       current_change_(NULL) {
51 }
52 
~RootNodeManager()53 RootNodeManager::~RootNodeManager() {
54   while (!connections_created_by_connect_.empty())
55     delete *(connections_created_by_connect_.begin());
56   // All the connections should have been destroyed.
57   DCHECK(connection_map_.empty());
58 }
59 
GetAndAdvanceNextConnectionId()60 ConnectionSpecificId RootNodeManager::GetAndAdvanceNextConnectionId() {
61   const ConnectionSpecificId id = next_connection_id_++;
62   DCHECK_LT(id, next_connection_id_);
63   return id;
64 }
65 
AddConnection(ViewManagerServiceImpl * connection)66 void RootNodeManager::AddConnection(ViewManagerServiceImpl* connection) {
67   DCHECK_EQ(0u, connection_map_.count(connection->id()));
68   connection_map_[connection->id()] = connection;
69 }
70 
RemoveConnection(ViewManagerServiceImpl * connection)71 void RootNodeManager::RemoveConnection(ViewManagerServiceImpl* connection) {
72   connection_map_.erase(connection->id());
73   connections_created_by_connect_.erase(connection);
74 
75   // Notify remaining connections so that they can cleanup.
76   for (ConnectionMap::const_iterator i = connection_map_.begin();
77        i != connection_map_.end(); ++i) {
78     i->second->OnViewManagerServiceImplDestroyed(connection->id());
79   }
80 }
81 
EmbedRoot(const std::string & url)82 void RootNodeManager::EmbedRoot(const std::string& url) {
83   CHECK(connection_map_.empty());
84   Array<Id> roots(0);
85   EmbedImpl(kRootConnection, String::From(url), roots);
86 }
87 
Embed(ConnectionSpecificId creator_id,const String & url,const Array<Id> & node_ids)88 void RootNodeManager::Embed(ConnectionSpecificId creator_id,
89                             const String& url,
90                             const Array<Id>& node_ids) {
91   CHECK_GT(node_ids.size(), 0u);
92   EmbedImpl(creator_id, url, node_ids)->set_delete_on_connection_error();
93 }
94 
GetConnection(ConnectionSpecificId connection_id)95 ViewManagerServiceImpl* RootNodeManager::GetConnection(
96     ConnectionSpecificId connection_id) {
97   ConnectionMap::iterator i = connection_map_.find(connection_id);
98   return i == connection_map_.end() ? NULL : i->second;
99 }
100 
GetNode(const NodeId & id)101 Node* RootNodeManager::GetNode(const NodeId& id) {
102   if (id == root_.id())
103     return &root_;
104   ConnectionMap::iterator i = connection_map_.find(id.connection_id);
105   return i == connection_map_.end() ? NULL : i->second->GetNode(id);
106 }
107 
GetView(const ViewId & id)108 View* RootNodeManager::GetView(const ViewId& id) {
109   ConnectionMap::iterator i = connection_map_.find(id.connection_id);
110   return i == connection_map_.end() ? NULL : i->second->GetView(id);
111 }
112 
OnConnectionMessagedClient(ConnectionSpecificId id)113 void RootNodeManager::OnConnectionMessagedClient(ConnectionSpecificId id) {
114   if (current_change_)
115     current_change_->MarkConnectionAsMessaged(id);
116 }
117 
DidConnectionMessageClient(ConnectionSpecificId id) const118 bool RootNodeManager::DidConnectionMessageClient(
119     ConnectionSpecificId id) const {
120   return current_change_ && current_change_->DidMessageConnection(id);
121 }
122 
GetConnectionByCreator(ConnectionSpecificId creator_id,const std::string & url) const123 ViewManagerServiceImpl* RootNodeManager::GetConnectionByCreator(
124     ConnectionSpecificId creator_id,
125     const std::string& url) const {
126   for (ConnectionMap::const_iterator i = connection_map_.begin();
127        i != connection_map_.end(); ++i) {
128     if (i->second->creator_id() == creator_id && i->second->url() == url)
129       return i->second;
130   }
131   return NULL;
132 }
133 
DispatchViewInputEventToWindowManager(const View * view,const ui::Event * event)134 void RootNodeManager::DispatchViewInputEventToWindowManager(
135     const View* view,
136     const ui::Event* event) {
137   // Input events are forwarded to the WindowManager. The WindowManager
138   // eventually calls back to us with DispatchOnViewInputEvent().
139   ViewManagerServiceImpl* connection = GetConnection(kWindowManagerConnection);
140   if (!connection)
141     return;
142   connection->client()->DispatchOnViewInputEvent(
143       ViewIdToTransportId(view->id()),
144       TypeConverter<EventPtr, ui::Event>::ConvertFrom(*event));
145 }
146 
ProcessNodeBoundsChanged(const Node * node,const gfx::Rect & old_bounds,const gfx::Rect & new_bounds)147 void RootNodeManager::ProcessNodeBoundsChanged(const Node* node,
148                                                const gfx::Rect& old_bounds,
149                                                const gfx::Rect& new_bounds) {
150   for (ConnectionMap::iterator i = connection_map_.begin();
151        i != connection_map_.end(); ++i) {
152     i->second->ProcessNodeBoundsChanged(node, old_bounds, new_bounds,
153                                         IsChangeSource(i->first));
154   }
155 }
156 
ProcessNodeHierarchyChanged(const Node * node,const Node * new_parent,const Node * old_parent)157 void RootNodeManager::ProcessNodeHierarchyChanged(const Node* node,
158                                                   const Node* new_parent,
159                                                   const Node* old_parent) {
160   for (ConnectionMap::iterator i = connection_map_.begin();
161        i != connection_map_.end(); ++i) {
162     i->second->ProcessNodeHierarchyChanged(
163         node, new_parent, old_parent, next_server_change_id_,
164         IsChangeSource(i->first));
165   }
166 }
167 
ProcessNodeReorder(const Node * node,const Node * relative_node,const OrderDirection direction)168 void RootNodeManager::ProcessNodeReorder(const Node* node,
169                                          const Node* relative_node,
170                                          const OrderDirection direction) {
171   for (ConnectionMap::iterator i = connection_map_.begin();
172        i != connection_map_.end(); ++i) {
173     i->second->ProcessNodeReorder(
174         node, relative_node, direction, next_server_change_id_,
175         IsChangeSource(i->first));
176   }
177 }
178 
ProcessNodeViewReplaced(const Node * node,const View * new_view,const View * old_view)179 void RootNodeManager::ProcessNodeViewReplaced(const Node* node,
180                                               const View* new_view,
181                                               const View* old_view) {
182   for (ConnectionMap::iterator i = connection_map_.begin();
183        i != connection_map_.end(); ++i) {
184     i->second->ProcessNodeViewReplaced(node, new_view, old_view,
185                                        IsChangeSource(i->first));
186   }
187 }
188 
ProcessNodeDeleted(const NodeId & node)189 void RootNodeManager::ProcessNodeDeleted(const NodeId& node) {
190   for (ConnectionMap::iterator i = connection_map_.begin();
191        i != connection_map_.end(); ++i) {
192     i->second->ProcessNodeDeleted(node, next_server_change_id_,
193                                  IsChangeSource(i->first));
194   }
195 }
196 
ProcessViewDeleted(const ViewId & view)197 void RootNodeManager::ProcessViewDeleted(const ViewId& view) {
198   for (ConnectionMap::iterator i = connection_map_.begin();
199        i != connection_map_.end(); ++i) {
200     i->second->ProcessViewDeleted(view, IsChangeSource(i->first));
201   }
202 }
203 
PrepareForChange(ScopedChange * change)204 void RootNodeManager::PrepareForChange(ScopedChange* change) {
205   // Should only ever have one change in flight.
206   CHECK(!current_change_);
207   current_change_ = change;
208 }
209 
FinishChange()210 void RootNodeManager::FinishChange() {
211   // PrepareForChange/FinishChange should be balanced.
212   CHECK(current_change_);
213   if (current_change_->change_type() == CHANGE_TYPE_ADVANCE_SERVER_CHANGE_ID)
214     next_server_change_id_++;
215   current_change_ = NULL;
216 }
217 
EmbedImpl(const ConnectionSpecificId creator_id,const String & url,const Array<Id> & node_ids)218 ViewManagerServiceImpl* RootNodeManager::EmbedImpl(
219     const ConnectionSpecificId creator_id,
220     const String& url,
221     const Array<Id>& node_ids) {
222   MessagePipe pipe;
223   service_provider_->ConnectToService(
224       url,
225       ViewManagerServiceImpl::Client::Name_,
226       pipe.handle1.Pass(),
227       String());
228 
229   std::string creator_url;
230   ConnectionMap::const_iterator it = connection_map_.find(creator_id);
231   if (it != connection_map_.end())
232     creator_url = it->second->url();
233 
234   ViewManagerServiceImpl* connection =
235       new ViewManagerServiceImpl(this,
236                                 creator_id,
237                                 creator_url,
238                                 url.To<std::string>());
239   connection->SetRoots(node_ids);
240   BindToPipe(connection, pipe.handle0.Pass());
241   connections_created_by_connect_.insert(connection);
242   return connection;
243 }
244 
OnNodeHierarchyChanged(const Node * node,const Node * new_parent,const Node * old_parent)245 void RootNodeManager::OnNodeHierarchyChanged(const Node* node,
246                                              const Node* new_parent,
247                                              const Node* old_parent) {
248   if (!root_view_manager_.in_setup())
249     ProcessNodeHierarchyChanged(node, new_parent, old_parent);
250 }
251 
OnNodeViewReplaced(const Node * node,const View * new_view,const View * old_view)252 void RootNodeManager::OnNodeViewReplaced(const Node* node,
253                                          const View* new_view,
254                                          const View* old_view) {
255   ProcessNodeViewReplaced(node, new_view, old_view);
256 }
257 
OnViewInputEvent(const View * view,const ui::Event * event)258 void RootNodeManager::OnViewInputEvent(const View* view,
259                                        const ui::Event* event) {
260   DispatchViewInputEventToWindowManager(view, event);
261 }
262 
263 }  // namespace service
264 }  // namespace view_manager
265 }  // namespace mojo
266