Chromium Code Reviews| 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 |