OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.h" | 5 #include "mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/message_loop/message_loop.h" | 8 #include "base/message_loop/message_loop.h" |
9 #include "mojo/public/cpp/bindings/allocation_scope.h" | 9 #include "mojo/public/cpp/bindings/allocation_scope.h" |
10 #include "mojo/public/interfaces/shell/shell.mojom.h" | 10 #include "mojo/public/interfaces/shell/shell.mojom.h" |
| 11 #include "mojo/services/public/cpp/view_manager/lib/view_manager_observer.h" |
11 #include "mojo/services/public/cpp/view_manager/lib/view_manager_private.h" | 12 #include "mojo/services/public/cpp/view_manager/lib/view_manager_private.h" |
| 13 #include "mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h" |
| 14 #include "mojo/services/public/cpp/view_manager/util.h" |
12 | 15 |
13 namespace mojo { | 16 namespace mojo { |
14 namespace services { | 17 namespace services { |
15 namespace view_manager { | 18 namespace view_manager { |
16 | 19 |
| 20 const TransportNodeId kRootNodeId = 1; |
| 21 |
17 class ViewManagerTransaction { | 22 class ViewManagerTransaction { |
18 public: | 23 public: |
19 virtual ~ViewManagerTransaction() {} | 24 virtual ~ViewManagerTransaction() {} |
20 | 25 |
21 void Commit() { | 26 void Commit() { |
22 DCHECK(!committed_); | 27 DCHECK(!committed_); |
23 DoCommit(); | 28 DoCommit(); |
| 29 synchronizer_->NotifyCommit(); |
24 committed_ = true; | 30 committed_ = true; |
25 } | 31 } |
26 | 32 |
27 bool committed() const { return committed_; } | 33 bool committed() const { return committed_; } |
28 uint32_t change_id() const { return change_id_; } | 34 uint32_t change_id() const { return change_id_; } |
29 | 35 |
30 // General callback to be used for commits to the service. | 36 // General callback to be used for commits to the service. |
31 void OnActionCompleted(bool success) { | 37 void OnActionCompleted(bool success) { |
32 DCHECK(success); | 38 DCHECK(success); |
33 DoActionCompleted(success); | 39 DoActionCompleted(success); |
| 40 synchronizer_->NotifyCommitResponse(success); |
34 synchronizer_->RemoveFromPendingQueue(this); | 41 synchronizer_->RemoveFromPendingQueue(this); |
35 } | 42 } |
36 | 43 |
37 protected: | 44 protected: |
38 enum TransactionType { | 45 enum TransactionType { |
39 // Node creation. | 46 // Node creation and destruction. |
40 TYPE_CREATE_VIEW_TREE_NODE, | 47 TYPE_CREATE_VIEW_TREE_NODE, |
| 48 TYPE_DESTROY_VIEW_TREE_NODE, |
41 // Modifications to the hierarchy (addition of or removal of nodes from a | 49 // Modifications to the hierarchy (addition of or removal of nodes from a |
42 // parent.) | 50 // parent.) |
43 TYPE_HIERARCHY | 51 TYPE_HIERARCHY |
44 }; | 52 }; |
45 | 53 |
46 ViewManagerTransaction(TransactionType transaction_type, | 54 ViewManagerTransaction(TransactionType transaction_type, |
47 ViewManagerSynchronizer* synchronizer) | 55 ViewManagerSynchronizer* synchronizer) |
48 : transaction_type_(transaction_type), | 56 : transaction_type_(transaction_type), |
49 change_id_(synchronizer->GetNextChangeId()), | 57 change_id_(synchronizer->GetNextChangeId()), |
50 committed_(false), | 58 committed_(false), |
51 synchronizer_(synchronizer) { | 59 synchronizer_(synchronizer) { |
52 } | 60 } |
53 | 61 |
54 // Overridden to perform transaction-specific commit actions. | 62 // Overridden to perform transaction-specific commit actions. |
55 virtual void DoCommit() = 0; | 63 virtual void DoCommit() = 0; |
56 | 64 |
57 // Overridden to perform transaction-specific cleanup on commit ack from the | 65 // Overridden to perform transaction-specific cleanup on commit ack from the |
58 // service. | 66 // service. |
59 virtual void DoActionCompleted(bool success) = 0; | 67 virtual void DoActionCompleted(bool success) = 0; |
60 | 68 |
61 IViewManager* service() { return synchronizer_->service_.get(); } | 69 IViewManager* service() { return synchronizer_->service_.get(); } |
62 | 70 |
63 uint32_t MakeTransportId(uint16_t id) { | 71 TransportNodeId MakeTransportId(uint32_t id) { |
64 return (synchronizer_->connection_id_ << 16) | id; | 72 if (id == kRootNodeId || HiWord(id) != 0) |
| 73 return id; |
| 74 return (synchronizer_->connection_id_ << 16) | LoWord(id); |
65 } | 75 } |
66 | 76 |
67 private: | 77 private: |
68 const TransactionType transaction_type_; | 78 const TransactionType transaction_type_; |
69 const uint32_t change_id_; | 79 const uint32_t change_id_; |
70 bool committed_; | 80 bool committed_; |
71 ViewManagerSynchronizer* synchronizer_; | 81 ViewManagerSynchronizer* synchronizer_; |
72 | 82 |
73 DISALLOW_COPY_AND_ASSIGN(ViewManagerTransaction); | 83 DISALLOW_COPY_AND_ASSIGN(ViewManagerTransaction); |
74 }; | 84 }; |
75 | 85 |
76 class CreateViewTreeNodeTransaction | 86 class CreateViewTreeNodeTransaction : public ViewManagerTransaction { |
77 : public ViewManagerTransaction { | |
78 public: | 87 public: |
79 CreateViewTreeNodeTransaction(uint16_t node_id, | 88 CreateViewTreeNodeTransaction(uint16_t node_id, |
80 ViewManagerSynchronizer* synchronizer) | 89 ViewManagerSynchronizer* synchronizer) |
81 : ViewManagerTransaction(TYPE_CREATE_VIEW_TREE_NODE, synchronizer), | 90 : ViewManagerTransaction(TYPE_CREATE_VIEW_TREE_NODE, synchronizer), |
82 node_id_(node_id) {} | 91 node_id_(node_id) {} |
83 virtual ~CreateViewTreeNodeTransaction() {} | 92 virtual ~CreateViewTreeNodeTransaction() {} |
84 | 93 |
85 private: | 94 private: |
86 // Overridden from ViewManagerTransaction: | 95 // Overridden from ViewManagerTransaction: |
87 virtual void DoCommit() OVERRIDE { | 96 virtual void DoCommit() OVERRIDE { |
88 service()->CreateNode( | 97 service()->CreateNode( |
89 node_id_, | 98 node_id_, |
90 base::Bind(&ViewManagerTransaction::OnActionCompleted, | 99 base::Bind(&ViewManagerTransaction::OnActionCompleted, |
91 base::Unretained(this))); | 100 base::Unretained(this))); |
92 } | 101 } |
93 | |
94 virtual void DoActionCompleted(bool success) OVERRIDE { | 102 virtual void DoActionCompleted(bool success) OVERRIDE { |
95 // TODO(beng): Failure means we tried to create with an extant id for this | 103 // TODO(beng): Failure means we tried to create with an extant id for this |
96 // connection. Figure out what to do. | 104 // connection. Figure out what to do. |
97 } | 105 } |
98 | 106 |
99 const uint16_t node_id_; | 107 const uint16_t node_id_; |
100 | 108 |
101 DISALLOW_COPY_AND_ASSIGN(CreateViewTreeNodeTransaction); | 109 DISALLOW_COPY_AND_ASSIGN(CreateViewTreeNodeTransaction); |
102 }; | 110 }; |
103 | 111 |
| 112 class DestroyViewTreeNodeTransaction : public ViewManagerTransaction { |
| 113 public: |
| 114 DestroyViewTreeNodeTransaction(TransportNodeId node_id, |
| 115 ViewManagerSynchronizer* synchronizer) |
| 116 : ViewManagerTransaction(TYPE_DESTROY_VIEW_TREE_NODE, synchronizer), |
| 117 node_id_(node_id) {} |
| 118 virtual ~DestroyViewTreeNodeTransaction() {} |
| 119 |
| 120 private: |
| 121 // Overridden from ViewManagerTransaction: |
| 122 virtual void DoCommit() OVERRIDE { |
| 123 service()->DeleteNode( |
| 124 node_id_, |
| 125 change_id(), |
| 126 base::Bind(&ViewManagerTransaction::OnActionCompleted, |
| 127 base::Unretained(this))); |
| 128 } |
| 129 virtual void DoActionCompleted(bool success) OVERRIDE { |
| 130 // TODO(beng): recovery? |
| 131 } |
| 132 |
| 133 TransportNodeId node_id_; |
| 134 DISALLOW_COPY_AND_ASSIGN(DestroyViewTreeNodeTransaction); |
| 135 }; |
| 136 |
104 class HierarchyTransaction : public ViewManagerTransaction { | 137 class HierarchyTransaction : public ViewManagerTransaction { |
105 public: | 138 public: |
106 enum HierarchyChangeType { | 139 enum HierarchyChangeType { |
107 TYPE_ADD, | 140 TYPE_ADD, |
108 TYPE_REMOVE | 141 TYPE_REMOVE |
109 }; | 142 }; |
110 HierarchyTransaction(HierarchyChangeType hierarchy_change_type, | 143 HierarchyTransaction(HierarchyChangeType hierarchy_change_type, |
111 uint16_t child_id, | 144 TransportNodeId child_id, |
112 uint16_t parent_id, | 145 TransportNodeId parent_id, |
113 ViewManagerSynchronizer* synchronizer) | 146 ViewManagerSynchronizer* synchronizer) |
114 : ViewManagerTransaction(TYPE_HIERARCHY, synchronizer), | 147 : ViewManagerTransaction(TYPE_HIERARCHY, synchronizer), |
115 hierarchy_change_type_(hierarchy_change_type), | 148 hierarchy_change_type_(hierarchy_change_type), |
116 child_id_(child_id), | 149 child_id_(child_id), |
117 parent_id_(parent_id) {} | 150 parent_id_(parent_id) {} |
118 virtual ~HierarchyTransaction() {} | 151 virtual ~HierarchyTransaction() {} |
119 | 152 |
120 private: | 153 private: |
121 // Overridden from ViewManagerTransaction: | 154 // Overridden from ViewManagerTransaction: |
122 virtual void DoCommit() OVERRIDE { | 155 virtual void DoCommit() OVERRIDE { |
(...skipping 15 matching lines...) Expand all Loading... |
138 break; | 171 break; |
139 } | 172 } |
140 } | 173 } |
141 | 174 |
142 virtual void DoActionCompleted(bool success) OVERRIDE { | 175 virtual void DoActionCompleted(bool success) OVERRIDE { |
143 // TODO(beng): Failure means either one of the nodes specified didn't exist, | 176 // TODO(beng): Failure means either one of the nodes specified didn't exist, |
144 // or we passed the same node id for both params. Roll back? | 177 // or we passed the same node id for both params. Roll back? |
145 } | 178 } |
146 | 179 |
147 const HierarchyChangeType hierarchy_change_type_; | 180 const HierarchyChangeType hierarchy_change_type_; |
148 const uint16_t child_id_; | 181 const TransportNodeId child_id_; |
149 const uint16_t parent_id_; | 182 const TransportNodeId parent_id_; |
150 | 183 |
151 DISALLOW_COPY_AND_ASSIGN(HierarchyTransaction); | 184 DISALLOW_COPY_AND_ASSIGN(HierarchyTransaction); |
152 }; | 185 }; |
153 | 186 |
154 ViewManagerSynchronizer::ViewManagerSynchronizer(ViewManager* view_manager) | 187 ViewManagerSynchronizer::ViewManagerSynchronizer(ViewManager* view_manager) |
155 : view_manager_(view_manager), | 188 : view_manager_(view_manager), |
156 connected_(false), | 189 connected_(false), |
157 connection_id_(0), | 190 connection_id_(0), |
158 next_id_(0), | 191 next_id_(1), |
159 next_change_id_(0) { | 192 next_change_id_(0) { |
160 InterfacePipe<services::view_manager::IViewManager, AnyInterface> | 193 InterfacePipe<services::view_manager::IViewManager, AnyInterface> |
161 view_manager_pipe; | 194 view_manager_pipe; |
162 AllocationScope scope; | 195 AllocationScope scope; |
163 ViewManagerPrivate(view_manager_).shell()->Connect( | 196 ViewManagerPrivate(view_manager_).shell()->Connect( |
164 "mojo:mojo_view_manager", view_manager_pipe.handle_to_peer.Pass()); | 197 "mojo:mojo_view_manager", view_manager_pipe.handle_to_peer.Pass()); |
165 service_.reset(view_manager_pipe.handle_to_self.Pass(), this); | 198 service_.reset(view_manager_pipe.handle_to_self.Pass(), this); |
166 } | 199 } |
167 | 200 |
168 ViewManagerSynchronizer::~ViewManagerSynchronizer() { | 201 ViewManagerSynchronizer::~ViewManagerSynchronizer() { |
169 } | 202 } |
170 | 203 |
171 uint16_t ViewManagerSynchronizer::CreateViewTreeNode() { | 204 uint16_t ViewManagerSynchronizer::CreateViewTreeNode() { |
172 uint16_t id = next_id_++; | 205 uint16_t id = ++next_id_; |
173 pending_transactions_.push_back(new CreateViewTreeNodeTransaction(id, this)); | 206 pending_transactions_.push_back(new CreateViewTreeNodeTransaction(id, this)); |
174 ScheduleSync(); | 207 ScheduleSync(); |
175 return id; | 208 return id; |
176 } | 209 } |
177 | 210 |
178 void ViewManagerSynchronizer::AddChild(uint16_t child_id, uint16_t parent_id) { | 211 void ViewManagerSynchronizer::DestroyViewTreeNode(TransportNodeId node_id) { |
| 212 pending_transactions_.push_back( |
| 213 new DestroyViewTreeNodeTransaction(node_id, this)); |
| 214 ScheduleSync(); |
| 215 } |
| 216 |
| 217 void ViewManagerSynchronizer::AddChild(TransportNodeId child_id, |
| 218 TransportNodeId parent_id) { |
179 pending_transactions_.push_back( | 219 pending_transactions_.push_back( |
180 new HierarchyTransaction(HierarchyTransaction::TYPE_ADD, | 220 new HierarchyTransaction(HierarchyTransaction::TYPE_ADD, |
181 child_id, | 221 child_id, |
182 parent_id, | 222 parent_id, |
183 this)); | 223 this)); |
184 ScheduleSync(); | 224 ScheduleSync(); |
185 } | 225 } |
186 | 226 |
187 void ViewManagerSynchronizer::RemoveChild(uint16_t child_id, | 227 void ViewManagerSynchronizer::RemoveChild(TransportNodeId child_id, |
188 uint16_t parent_id) { | 228 TransportNodeId parent_id) { |
189 pending_transactions_.push_back( | 229 pending_transactions_.push_back( |
190 new HierarchyTransaction(HierarchyTransaction::TYPE_REMOVE, | 230 new HierarchyTransaction(HierarchyTransaction::TYPE_REMOVE, |
191 child_id, | 231 child_id, |
192 parent_id, | 232 parent_id, |
193 this)); | 233 this)); |
194 ScheduleSync(); | 234 ScheduleSync(); |
195 } | 235 } |
196 | 236 |
| 237 void ViewManagerSynchronizer::BuildNodeTree( |
| 238 const Callback<void()>& callback) { |
| 239 service_->GetNodeTree( |
| 240 1, |
| 241 base::Bind(&ViewManagerSynchronizer::OnTreeReceived, |
| 242 base::Unretained(this), |
| 243 callback)); |
| 244 } |
| 245 |
197 //////////////////////////////////////////////////////////////////////////////// | 246 //////////////////////////////////////////////////////////////////////////////// |
198 // ViewManagerSynchronizer, IViewManagerClient implementation: | 247 // ViewManagerSynchronizer, IViewManagerClient implementation: |
199 | 248 |
200 void ViewManagerSynchronizer::OnConnectionEstablished(uint16 connection_id) { | 249 void ViewManagerSynchronizer::OnConnectionEstablished(uint16 connection_id) { |
201 connected_ = true; | 250 connected_ = true; |
202 connection_id_ = connection_id; | 251 connection_id_ = connection_id; |
203 ScheduleSync(); | 252 ScheduleSync(); |
| 253 FOR_EACH_OBSERVER(ViewManagerObserver, |
| 254 *ViewManagerPrivate(view_manager_).observers(), |
| 255 OnViewManagerConnected(view_manager_)); |
204 } | 256 } |
205 | 257 |
206 void ViewManagerSynchronizer::OnNodeHierarchyChanged(uint32_t node, | 258 void ViewManagerSynchronizer::OnNodeHierarchyChanged(uint32_t node, |
207 uint32_t new_parent, | 259 uint32_t new_parent, |
208 uint32_t old_parent, | 260 uint32_t old_parent, |
209 uint32_t change_id) { | 261 uint32_t change_id) { |
210 if (change_id == 0) { | 262 if (change_id == 0) { |
211 // TODO(beng): Apply changes from another client. | 263 // TODO(beng): Apply changes from another client. |
212 } | 264 } |
213 } | 265 } |
(...skipping 29 matching lines...) Expand all Loading... |
243 | 295 |
244 uint32_t ViewManagerSynchronizer::GetNextChangeId() { | 296 uint32_t ViewManagerSynchronizer::GetNextChangeId() { |
245 // TODO(beng): deal with change id collisions? Important in the "never ack'ed | 297 // TODO(beng): deal with change id collisions? Important in the "never ack'ed |
246 // change" case mentioned in OnNodeHierarchyChanged(). | 298 // change" case mentioned in OnNodeHierarchyChanged(). |
247 // "0" is a special value passed to other connected clients, so we can't use | 299 // "0" is a special value passed to other connected clients, so we can't use |
248 // it. | 300 // it. |
249 next_change_id_ = std::max(1u, next_change_id_ + 1); | 301 next_change_id_ = std::max(1u, next_change_id_ + 1); |
250 return next_change_id_; | 302 return next_change_id_; |
251 } | 303 } |
252 | 304 |
| 305 void ViewManagerSynchronizer::NotifyCommit() { |
| 306 FOR_EACH_OBSERVER(ViewManagerObserver, |
| 307 *ViewManagerPrivate(view_manager_).observers(), |
| 308 OnCommit(view_manager_)); |
| 309 } |
| 310 |
| 311 void ViewManagerSynchronizer::NotifyCommitResponse(bool success) { |
| 312 FOR_EACH_OBSERVER(ViewManagerObserver, |
| 313 *ViewManagerPrivate(view_manager_).observers(), |
| 314 OnCommitResponse(view_manager_, success)); |
| 315 } |
| 316 |
253 void ViewManagerSynchronizer::RemoveFromPendingQueue( | 317 void ViewManagerSynchronizer::RemoveFromPendingQueue( |
254 ViewManagerTransaction* transaction) { | 318 ViewManagerTransaction* transaction) { |
255 DCHECK_EQ(transaction, pending_transactions_.front()); | 319 DCHECK_EQ(transaction, pending_transactions_.front()); |
256 pending_transactions_.erase(pending_transactions_.begin()); | 320 pending_transactions_.erase(pending_transactions_.begin()); |
257 } | 321 } |
258 | 322 |
| 323 void ViewManagerSynchronizer::OnTreeReceived( |
| 324 const Callback<void()>& callback, |
| 325 const Array<INode>& nodes) { |
| 326 std::vector<ViewTreeNode*> parents; |
| 327 ViewTreeNode* root = NULL; |
| 328 ViewTreeNode* last_node = NULL; |
| 329 for (size_t i = 0; i < nodes.size(); ++i) { |
| 330 if (last_node && nodes[i].parent_id() == last_node->id()) { |
| 331 parents.push_back(last_node); |
| 332 } else if (!parents.empty()) { |
| 333 while (parents.back()->id() != nodes[i].parent_id()) |
| 334 parents.pop_back(); |
| 335 } |
| 336 // We don't use the ctor that takes a ViewManager here, since it will call |
| 337 // back to the service and attempt to create a new node. |
| 338 ViewTreeNode* node = new ViewTreeNode; |
| 339 ViewTreeNodePrivate private_node(node); |
| 340 private_node.set_view_manager(view_manager_); |
| 341 private_node.set_id(nodes[i].node_id()); |
| 342 if (!parents.empty()) |
| 343 ViewTreeNodePrivate(parents.back()).LocalAddChild(node); |
| 344 if (!last_node) |
| 345 root = node; |
| 346 last_node = node; |
| 347 } |
| 348 ViewManagerPrivate(view_manager_).set_tree(root); |
| 349 callback.Run(); |
| 350 } |
| 351 |
259 } // namespace view_manager | 352 } // namespace view_manager |
260 } // namespace services | 353 } // namespace services |
261 } // namespace mojo | 354 } // namespace mojo |
OLD | NEW |