| Index: mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc
|
| diff --git a/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc b/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5fe22b4cb9583454cb77dc23e3863b2632c26fcf
|
| --- /dev/null
|
| +++ b/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc
|
| @@ -0,0 +1,261 @@
|
| +// Copyright 2014 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.h"
|
| +
|
| +#include "base/bind.h"
|
| +#include "base/message_loop/message_loop.h"
|
| +#include "mojo/public/cpp/bindings/allocation_scope.h"
|
| +#include "mojo/public/interfaces/shell/shell.mojom.h"
|
| +#include "mojo/services/public/cpp/view_manager/lib/view_manager_private.h"
|
| +
|
| +namespace mojo {
|
| +namespace services {
|
| +namespace view_manager {
|
| +
|
| +class ViewManagerTransaction {
|
| + public:
|
| + virtual ~ViewManagerTransaction() {}
|
| +
|
| + void Commit() {
|
| + DCHECK(!committed_);
|
| + DoCommit();
|
| + committed_ = true;
|
| + }
|
| +
|
| + bool committed() const { return committed_; }
|
| + uint32_t change_id() const { return change_id_; }
|
| +
|
| + // General callback to be used for commits to the service.
|
| + void OnActionCompleted(bool success) {
|
| + DCHECK(success);
|
| + DoActionCompleted(success);
|
| + synchronizer_->RemoveFromPendingQueue(this);
|
| + }
|
| +
|
| + protected:
|
| + enum TransactionType {
|
| + // Node creation.
|
| + TYPE_CREATE_VIEW_TREE_NODE,
|
| + // Modifications to the hierarchy (addition of or removal of nodes from a
|
| + // parent.)
|
| + TYPE_HIERARCHY
|
| + };
|
| +
|
| + ViewManagerTransaction(TransactionType transaction_type,
|
| + ViewManagerSynchronizer* synchronizer)
|
| + : transaction_type_(transaction_type),
|
| + change_id_(synchronizer->GetNextChangeId()),
|
| + committed_(false),
|
| + synchronizer_(synchronizer) {
|
| + }
|
| +
|
| + // Overridden to perform transaction-specific commit actions.
|
| + virtual void DoCommit() = 0;
|
| +
|
| + // Overridden to perform transaction-specific cleanup on commit ack from the
|
| + // service.
|
| + virtual void DoActionCompleted(bool success) = 0;
|
| +
|
| + IViewManager* service() { return synchronizer_->service_.get(); }
|
| +
|
| + uint32_t MakeTransportId(uint16_t id) {
|
| + return (synchronizer_->connection_id_ << 16) | id;
|
| + }
|
| +
|
| + private:
|
| + const TransactionType transaction_type_;
|
| + const uint32_t change_id_;
|
| + bool committed_;
|
| + ViewManagerSynchronizer* synchronizer_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ViewManagerTransaction);
|
| +};
|
| +
|
| +class CreateViewTreeNodeTransaction
|
| + : public ViewManagerTransaction {
|
| + public:
|
| + CreateViewTreeNodeTransaction(uint16_t node_id,
|
| + ViewManagerSynchronizer* synchronizer)
|
| + : ViewManagerTransaction(TYPE_CREATE_VIEW_TREE_NODE, synchronizer),
|
| + node_id_(node_id) {}
|
| + virtual ~CreateViewTreeNodeTransaction() {}
|
| +
|
| + private:
|
| + // Overridden from ViewManagerTransaction:
|
| + virtual void DoCommit() OVERRIDE {
|
| + service()->CreateNode(
|
| + node_id_,
|
| + base::Bind(&ViewManagerTransaction::OnActionCompleted,
|
| + base::Unretained(this)));
|
| + }
|
| +
|
| + virtual void DoActionCompleted(bool success) OVERRIDE {
|
| + // TODO(beng): Failure means we tried to create with an extant id for this
|
| + // connection. Figure out what to do.
|
| + }
|
| +
|
| + const uint16_t node_id_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(CreateViewTreeNodeTransaction);
|
| +};
|
| +
|
| +class HierarchyTransaction : public ViewManagerTransaction {
|
| + public:
|
| + enum HierarchyChangeType {
|
| + TYPE_ADD,
|
| + TYPE_REMOVE
|
| + };
|
| + HierarchyTransaction(HierarchyChangeType hierarchy_change_type,
|
| + uint16_t child_id,
|
| + uint16_t parent_id,
|
| + ViewManagerSynchronizer* synchronizer)
|
| + : ViewManagerTransaction(TYPE_HIERARCHY, synchronizer),
|
| + hierarchy_change_type_(hierarchy_change_type),
|
| + child_id_(child_id),
|
| + parent_id_(parent_id) {}
|
| + virtual ~HierarchyTransaction() {}
|
| +
|
| + private:
|
| + // Overridden from ViewManagerTransaction:
|
| + virtual void DoCommit() OVERRIDE {
|
| + switch (hierarchy_change_type_) {
|
| + case TYPE_ADD:
|
| + service()->AddNode(
|
| + MakeTransportId(parent_id_),
|
| + MakeTransportId(child_id_),
|
| + change_id(),
|
| + base::Bind(&ViewManagerTransaction::OnActionCompleted,
|
| + base::Unretained(this)));
|
| + break;
|
| + case TYPE_REMOVE:
|
| + service()->RemoveNodeFromParent(
|
| + MakeTransportId(child_id_),
|
| + change_id(),
|
| + base::Bind(&ViewManagerTransaction::OnActionCompleted,
|
| + base::Unretained(this)));
|
| + break;
|
| + }
|
| + }
|
| +
|
| + virtual void DoActionCompleted(bool success) OVERRIDE {
|
| + // TODO(beng): Failure means either one of the nodes specified didn't exist,
|
| + // or we passed the same node id for both params. Roll back?
|
| + }
|
| +
|
| + const HierarchyChangeType hierarchy_change_type_;
|
| + const uint16_t child_id_;
|
| + const uint16_t parent_id_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(HierarchyTransaction);
|
| +};
|
| +
|
| +ViewManagerSynchronizer::ViewManagerSynchronizer(ViewManager* view_manager)
|
| + : view_manager_(view_manager),
|
| + connected_(false),
|
| + connection_id_(0),
|
| + next_id_(0),
|
| + next_change_id_(0) {
|
| + InterfacePipe<services::view_manager::IViewManager, AnyInterface>
|
| + view_manager_pipe;
|
| + AllocationScope scope;
|
| + ViewManagerPrivate(view_manager_).shell()->Connect(
|
| + "mojo:mojo_view_manager", view_manager_pipe.handle_to_peer.Pass());
|
| + service_.reset(view_manager_pipe.handle_to_self.Pass(), this);
|
| +}
|
| +
|
| +ViewManagerSynchronizer::~ViewManagerSynchronizer() {
|
| +}
|
| +
|
| +uint16_t ViewManagerSynchronizer::CreateViewTreeNode() {
|
| + uint16_t id = next_id_++;
|
| + pending_transactions_.push_back(new CreateViewTreeNodeTransaction(id, this));
|
| + ScheduleSync();
|
| + return id;
|
| +}
|
| +
|
| +void ViewManagerSynchronizer::AddChild(uint16_t child_id, uint16_t parent_id) {
|
| + pending_transactions_.push_back(
|
| + new HierarchyTransaction(HierarchyTransaction::TYPE_ADD,
|
| + child_id,
|
| + parent_id,
|
| + this));
|
| + ScheduleSync();
|
| +}
|
| +
|
| +void ViewManagerSynchronizer::RemoveChild(uint16_t child_id,
|
| + uint16_t parent_id) {
|
| + pending_transactions_.push_back(
|
| + new HierarchyTransaction(HierarchyTransaction::TYPE_REMOVE,
|
| + child_id,
|
| + parent_id,
|
| + this));
|
| + ScheduleSync();
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// ViewManagerSynchronizer, IViewManagerClient implementation:
|
| +
|
| +void ViewManagerSynchronizer::OnConnectionEstablished(uint16 connection_id) {
|
| + connected_ = true;
|
| + connection_id_ = connection_id;
|
| + ScheduleSync();
|
| +}
|
| +
|
| +void ViewManagerSynchronizer::OnNodeHierarchyChanged(uint32_t node,
|
| + uint32_t new_parent,
|
| + uint32_t old_parent,
|
| + uint32_t change_id) {
|
| + if (change_id == 0) {
|
| + // TODO(beng): Apply changes from another client.
|
| + }
|
| +}
|
| +
|
| +void ViewManagerSynchronizer::OnNodeViewReplaced(uint32_t node,
|
| + uint32_t new_view_id,
|
| + uint32_t old_view_id,
|
| + uint32_t change_id) {
|
| + // ..
|
| +}
|
| +
|
| +////////////////////////////////////////////////////////////////////////////////
|
| +// ViewManagerSynchronizer, private:
|
| +
|
| +void ViewManagerSynchronizer::ScheduleSync() {
|
| + base::MessageLoop::current()->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&ViewManagerSynchronizer::DoSync, base::Unretained(this)));
|
| +}
|
| +
|
| +void ViewManagerSynchronizer::DoSync() {
|
| + // The service connection may not be set up yet. OnConnectionEstablished()
|
| + // will schedule another sync when it is.
|
| + if (!connected_)
|
| + return;
|
| +
|
| + Transactions::const_iterator it = pending_transactions_.begin();
|
| + for (; it != pending_transactions_.end(); ++it) {
|
| + if (!(*it)->committed())
|
| + (*it)->Commit();
|
| + }
|
| +}
|
| +
|
| +uint32_t ViewManagerSynchronizer::GetNextChangeId() {
|
| + // TODO(beng): deal with change id collisions? Important in the "never ack'ed
|
| + // change" case mentioned in OnNodeHierarchyChanged().
|
| + // "0" is a special value passed to other connected clients, so we can't use
|
| + // it.
|
| + next_change_id_ = std::max(1u, next_change_id_ + 1);
|
| + return next_change_id_;
|
| +}
|
| +
|
| +void ViewManagerSynchronizer::RemoveFromPendingQueue(
|
| + ViewManagerTransaction* transaction) {
|
| + DCHECK_EQ(transaction, pending_transactions_.front());
|
| + pending_transactions_.erase(pending_transactions_.begin());
|
| +}
|
| +
|
| +} // namespace view_manager
|
| +} // namespace services
|
| +} // namespace mojo
|
|
|