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/root_node_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"
12 #include "ui/aura/env.h"
17 RootNodeManager::ScopedChange::ScopedChange(
18 ViewManagerServiceImpl
* connection
,
19 RootNodeManager
* root
,
22 connection_id_(connection
->id()),
23 is_delete_node_(is_delete_node
) {
24 root_
->PrepareForChange(this);
27 RootNodeManager::ScopedChange::~ScopedChange() {
28 root_
->FinishChange();
31 RootNodeManager::Context::Context() {
32 // Pass in false as native viewport creates the PlatformEventSource.
33 aura::Env::CreateInstance(false);
36 RootNodeManager::Context::~Context() {
37 aura::Env::DeleteInstance();
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
,
48 view_manager_delegate
,
49 native_viewport_closed_callback
),
50 root_(new Node(this, RootNodeId())),
51 current_change_(NULL
) {
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());
62 ConnectionSpecificId
RootNodeManager::GetAndAdvanceNextConnectionId() {
63 const ConnectionSpecificId id
= next_connection_id_
++;
64 DCHECK_LT(id
, next_connection_id_
);
68 void RootNodeManager::AddConnection(ViewManagerServiceImpl
* connection
) {
69 DCHECK_EQ(0u, connection_map_
.count(connection
->id()));
70 connection_map_
[connection
->id()] = connection
;
73 void RootNodeManager::RemoveConnection(ViewManagerServiceImpl
* connection
) {
74 connection_map_
.erase(connection
->id());
75 connections_created_by_connect_
.erase(connection
);
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());
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());
92 ViewManagerServiceImpl
* connection
= GetConnection(kWindowManagerConnection
);
93 connection
->client()->Embed(url
, service_provider
.Pass());
96 void RootNodeManager::Embed(
97 ConnectionSpecificId creator_id
,
100 InterfaceRequest
<ServiceProvider
> service_provider
) {
101 EmbedImpl(creator_id
,
103 NodeIdFromTransportId(transport_node_id
),
104 service_provider
.Pass())->set_delete_on_connection_error();
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
;
113 Node
* RootNodeManager::GetNode(const NodeId
& id
) {
114 if (id
== root_
->id())
116 ConnectionMap::iterator i
= connection_map_
.find(id
.connection_id
);
117 return i
== connection_map_
.end() ? NULL
: i
->second
->GetNode(id
);
120 void RootNodeManager::OnConnectionMessagedClient(ConnectionSpecificId id
) {
122 current_change_
->MarkConnectionAsMessaged(id
);
125 bool RootNodeManager::DidConnectionMessageClient(
126 ConnectionSpecificId id
) const {
127 return current_change_
&& current_change_
->DidMessageConnection(id
);
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
)
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
))
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
);
157 connection
->client()->DispatchOnViewInputEvent(event
.Pass());
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
));
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
));
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
));
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
));
197 void RootNodeManager::PrepareForChange(ScopedChange
* change
) {
198 // Should only ever have one change in flight.
199 CHECK(!current_change_
);
200 current_change_
= change
;
203 void RootNodeManager::FinishChange() {
204 // PrepareForChange/FinishChange should be balanced.
205 CHECK(current_change_
);
206 current_change_
= NULL
;
209 ViewManagerServiceImpl
* RootNodeManager::EmbedImpl(
210 const ConnectionSpecificId creator_id
,
212 const NodeId
& root_id
,
213 InterfaceRequest
<ServiceProvider
> service_provider
) {
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());
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();
227 ViewManagerServiceImpl
* connection
=
228 new ViewManagerServiceImpl(this,
231 url
.To
<std::string
>(),
233 service_provider
.Pass());
234 WeakBindToPipe(connection
, pipe
.handle0
.Pass());
235 connections_created_by_connect_
.insert(connection
);
236 OnConnectionMessagedClient(connection
->id());
240 void RootNodeManager::OnNodeDestroyed(const Node
* node
) {
241 ProcessNodeDeleted(node
->id());
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
);
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
);
257 } // namespace service