OLD | NEW |
---|---|
(Empty) | |
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/public/cpp/view_manager/lib/view_manager_synchronizer.h" | |
6 | |
7 #include "base/bind.h" | |
8 #include "base/message_loop/message_loop.h" | |
9 #include "mojo/public/cpp/bindings/allocation_scope.h" | |
10 #include "mojo/public/interfaces/shell/shell.mojom.h" | |
11 #include "mojo/services/public/cpp/view_manager/lib/view_manager_private.h" | |
12 | |
13 namespace mojo { | |
14 namespace services { | |
15 namespace view_manager { | |
16 | |
17 class ViewManagerTransaction { | |
18 public: | |
19 virtual ~ViewManagerTransaction() {} | |
20 | |
21 void Commit() { | |
22 DCHECK(!committed_); | |
23 DoCommit(); | |
24 committed_ = true; | |
25 } | |
26 | |
27 bool committed() const { return committed_; } | |
28 uint32_t change_id() const { return change_id_; } | |
29 | |
30 // General callback to be used for commits to the service. | |
31 void OnActionCompleted(bool success) { | |
32 DCHECK(success); | |
33 DoActionCompleted(success); | |
34 synchronizer_->RemoveFromPendingQueue(this); | |
35 } | |
36 | |
37 protected: | |
38 enum TransactionType { | |
39 // Node creation. | |
40 TYPE_CREATE_VIEW_TREE_NODE, | |
41 // Modifications to the hierarchy (addition of or removal of nodes from a | |
42 // parent.) | |
43 TYPE_HIERARCHY | |
44 }; | |
45 | |
46 ViewManagerTransaction(TransactionType transaction_type, | |
47 ViewManagerSynchronizer* synchronizer) | |
48 : transaction_type_(transaction_type), | |
49 change_id_(synchronizer->GetNextChangeId()), | |
50 committed_(false), | |
51 synchronizer_(synchronizer) { | |
52 } | |
53 | |
54 // Overridden to perform transaction-specific commit actions. | |
55 virtual void DoCommit() = 0; | |
56 | |
57 // Overridden to perform transaction-specific cleanup on commit ack from the | |
58 // service. | |
59 virtual void DoActionCompleted(bool success) = 0; | |
60 | |
61 IViewManager* service() { return synchronizer_->service_.get(); } | |
62 | |
63 uint32_t MakeTransportId(uint16_t id) { | |
64 return (synchronizer_->connection_id_ << 16) | id; | |
65 } | |
66 | |
67 private: | |
68 const int transaction_type_; | |
sky
2014/04/29 04:14:06
int->TransactionType
| |
69 const uint32_t change_id_; | |
70 bool committed_; | |
71 ViewManagerSynchronizer* synchronizer_; | |
72 | |
73 DISALLOW_COPY_AND_ASSIGN(ViewManagerTransaction); | |
74 }; | |
75 | |
76 class CreateViewTreeNodeTransaction | |
77 : public ViewManagerTransaction { | |
78 public: | |
79 CreateViewTreeNodeTransaction(int node_id, | |
80 ViewManagerSynchronizer* synchronizer) | |
81 : ViewManagerTransaction(TYPE_CREATE_VIEW_TREE_NODE, synchronizer), | |
82 node_id_(node_id) {} | |
83 virtual ~CreateViewTreeNodeTransaction() {} | |
84 | |
85 private: | |
86 // Overridden from ViewManagerTransaction: | |
87 virtual void DoCommit() OVERRIDE { | |
88 service()->CreateNode( | |
89 node_id_, | |
90 base::Bind(&ViewManagerTransaction::OnActionCompleted, | |
91 base::Unretained(this))); | |
92 } | |
93 | |
94 void DoActionCompleted(bool success) { | |
95 // TODO(beng): Failure means we tried to create with an extant id for this | |
96 // connection. Figure out what to do. | |
97 } | |
98 | |
99 const uint16_t node_id_; | |
100 | |
101 DISALLOW_COPY_AND_ASSIGN(CreateViewTreeNodeTransaction); | |
102 }; | |
103 | |
104 class HierarchyTransaction : public ViewManagerTransaction { | |
105 public: | |
106 enum HierarchyChangeType { | |
107 TYPE_ADD, | |
108 TYPE_REMOVE | |
109 }; | |
110 HierarchyTransaction(HierarchyChangeType hierarchy_change_type, | |
111 int child_id, | |
sky
2014/04/29 04:14:06
uint16_t for child_id and parent_id, including mem
| |
112 int parent_id, | |
113 ViewManagerSynchronizer* synchronizer) | |
114 : ViewManagerTransaction(TYPE_HIERARCHY, synchronizer), | |
115 hierarchy_change_type_(hierarchy_change_type), | |
116 child_id_(child_id), | |
117 parent_id_(parent_id) {} | |
118 virtual ~HierarchyTransaction() {} | |
119 | |
120 private: | |
121 // Overridden from ViewManagerTransaction: | |
122 virtual void DoCommit() OVERRIDE { | |
123 switch (hierarchy_change_type_) { | |
124 case TYPE_ADD: | |
sky
2014/04/29 04:14:06
nit: spacing off, indent case statements 2 more.
| |
125 service()->AddNode(MakeTransportId(parent_id_), | |
126 MakeTransportId(child_id_), | |
127 change_id(), | |
128 base::Bind(&ViewManagerTransaction::OnActionCompleted, | |
129 base::Unretained(this))); | |
130 break; | |
131 case TYPE_REMOVE: | |
132 service()->RemoveNodeFromParent( | |
133 MakeTransportId(child_id_), | |
134 change_id(), | |
135 base::Bind(&ViewManagerTransaction::OnActionCompleted, | |
136 base::Unretained(this))); | |
137 break; | |
138 } | |
139 } | |
140 | |
141 void DoActionCompleted(bool success) { | |
142 // TODO(beng): Failure means either one of the nodes specified didn't exist, | |
143 // or we passed the same node id for both params. Roll back? | |
144 } | |
145 | |
146 const HierarchyChangeType hierarchy_change_type_; | |
147 const int child_id_; | |
148 const int parent_id_; | |
149 | |
150 DISALLOW_COPY_AND_ASSIGN(HierarchyTransaction); | |
151 }; | |
152 | |
153 ViewManagerSynchronizer::ViewManagerSynchronizer(ViewManager* view_manager) | |
154 : view_manager_(view_manager), | |
155 connected_(false), | |
156 connection_id_(0), | |
157 next_id_(0), | |
158 next_change_id_(0) { | |
159 InterfacePipe<services::view_manager::IViewManager, AnyInterface> | |
160 view_manager_pipe; | |
161 AllocationScope scope; | |
162 ViewManagerPrivate(view_manager_).shell()->Connect( | |
163 "mojo:mojo_view_manager", view_manager_pipe.handle_to_peer.Pass()); | |
164 service_.reset(view_manager_pipe.handle_to_self.Pass(), this); | |
165 } | |
166 | |
167 ViewManagerSynchronizer::~ViewManagerSynchronizer() { | |
168 } | |
169 | |
170 int ViewManagerSynchronizer::CreateViewTreeNode() { | |
171 int id = next_id_++; | |
sky
2014/04/29 04:14:06
uint32_t
| |
172 pending_transactions_.push_back(new CreateViewTreeNodeTransaction(id, this)); | |
173 ScheduleSync(); | |
174 return id; | |
175 } | |
176 | |
177 void ViewManagerSynchronizer::AddChild(int child_id, int parent_id) { | |
178 pending_transactions_.push_back( | |
179 new HierarchyTransaction(HierarchyTransaction::TYPE_ADD, | |
180 child_id, | |
181 parent_id, | |
182 this)); | |
183 ScheduleSync(); | |
184 } | |
185 | |
186 void ViewManagerSynchronizer::RemoveChild(int child_id, int parent_id) { | |
187 pending_transactions_.push_back( | |
188 new HierarchyTransaction(HierarchyTransaction::TYPE_REMOVE, | |
189 child_id, | |
190 parent_id, | |
191 this)); | |
192 ScheduleSync(); | |
193 } | |
194 | |
195 //////////////////////////////////////////////////////////////////////////////// | |
196 // ViewManagerSynchronizer, IViewManagerClient implementation: | |
197 | |
198 void ViewManagerSynchronizer::OnConnectionEstablished(uint16 connection_id) { | |
199 connected_ = true; | |
200 connection_id_ = connection_id; | |
201 ScheduleSync(); | |
202 } | |
203 | |
204 void ViewManagerSynchronizer::OnNodeHierarchyChanged(uint32_t node, | |
205 uint32_t new_parent, | |
206 uint32_t old_parent, | |
207 int32_t change_id) { | |
208 if (change_id == 0) { | |
209 // TODO(beng): Apply changes from another client. | |
210 } | |
211 } | |
212 | |
213 void ViewManagerSynchronizer::OnNodeViewReplaced(uint32_t node, | |
214 uint32_t new_view_id, | |
215 uint32_t old_view_id, | |
216 int32_t change_id) { | |
217 // .. | |
218 } | |
219 | |
220 //////////////////////////////////////////////////////////////////////////////// | |
221 // ViewManagerSynchronizer, private: | |
222 | |
223 void ViewManagerSynchronizer::ScheduleSync() { | |
224 base::MessageLoop::current()->PostTask( | |
225 FROM_HERE, | |
226 base::Bind(&ViewManagerSynchronizer::DoSync, base::Unretained(this))); | |
227 } | |
228 | |
229 void ViewManagerSynchronizer::DoSync() { | |
230 // The service connection may not be set up yet. OnConnectionEstablished() | |
231 // will schedule another sync when it is. | |
232 if (!connected_) | |
233 return; | |
234 | |
235 Transactions::const_iterator it = pending_transactions_.begin(); | |
236 for (; it != pending_transactions_.end(); ++it) { | |
237 if (!(*it)->committed()) | |
238 (*it)->Commit(); | |
239 } | |
240 } | |
241 | |
242 int ViewManagerSynchronizer::GetNextChangeId() { | |
243 // TODO(beng): deal with change id collisions? Important in the "never ack'ed | |
244 // change" case mentioned in OnNodeHierarchyChanged(). | |
245 // "0" is a special value passed to other connected clients, so we can't use | |
246 // it. | |
247 next_change_id_ = std::max(1u, ++next_change_id_); | |
248 return next_change_id_; | |
249 } | |
250 | |
251 void ViewManagerSynchronizer::RemoveFromPendingQueue( | |
252 ViewManagerTransaction* transaction) { | |
253 DCHECK_EQ(transaction, pending_transactions_.front()); | |
254 pending_transactions_.erase(pending_transactions_.begin()); | |
255 } | |
256 | |
257 } // namespace view_manager | |
258 } // namespace services | |
259 } // namespace mojo | |
OLD | NEW |