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 |
index 5fe22b4cb9583454cb77dc23e3863b2632c26fcf..609a90e2f9100d9d811f954e1f83cccbd4dffd30 100644 |
--- a/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc |
+++ b/mojo/services/public/cpp/view_manager/lib/view_manager_synchronizer.cc |
@@ -8,12 +8,17 @@ |
#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_observer.h" |
#include "mojo/services/public/cpp/view_manager/lib/view_manager_private.h" |
+#include "mojo/services/public/cpp/view_manager/lib/view_tree_node_private.h" |
+#include "mojo/services/public/cpp/view_manager/util.h" |
namespace mojo { |
namespace services { |
namespace view_manager { |
+const TransportNodeId kRootNodeId = 1; |
+ |
class ViewManagerTransaction { |
public: |
virtual ~ViewManagerTransaction() {} |
@@ -21,6 +26,7 @@ class ViewManagerTransaction { |
void Commit() { |
DCHECK(!committed_); |
DoCommit(); |
+ synchronizer_->NotifyCommit(); |
committed_ = true; |
} |
@@ -31,13 +37,15 @@ class ViewManagerTransaction { |
void OnActionCompleted(bool success) { |
DCHECK(success); |
DoActionCompleted(success); |
+ synchronizer_->NotifyCommitResponse(success); |
synchronizer_->RemoveFromPendingQueue(this); |
} |
protected: |
enum TransactionType { |
- // Node creation. |
+ // Node creation and destruction. |
TYPE_CREATE_VIEW_TREE_NODE, |
+ TYPE_DESTROY_VIEW_TREE_NODE, |
// Modifications to the hierarchy (addition of or removal of nodes from a |
// parent.) |
TYPE_HIERARCHY |
@@ -60,8 +68,10 @@ class ViewManagerTransaction { |
IViewManager* service() { return synchronizer_->service_.get(); } |
- uint32_t MakeTransportId(uint16_t id) { |
- return (synchronizer_->connection_id_ << 16) | id; |
+ TransportNodeId MakeTransportId(uint32_t id) { |
+ if (id == kRootNodeId || HiWord(id) != 0) |
+ return id; |
+ return (synchronizer_->connection_id_ << 16) | LoWord(id); |
} |
private: |
@@ -73,8 +83,7 @@ class ViewManagerTransaction { |
DISALLOW_COPY_AND_ASSIGN(ViewManagerTransaction); |
}; |
-class CreateViewTreeNodeTransaction |
- : public ViewManagerTransaction { |
+class CreateViewTreeNodeTransaction : public ViewManagerTransaction { |
public: |
CreateViewTreeNodeTransaction(uint16_t node_id, |
ViewManagerSynchronizer* synchronizer) |
@@ -90,7 +99,6 @@ class CreateViewTreeNodeTransaction |
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. |
@@ -101,6 +109,31 @@ class CreateViewTreeNodeTransaction |
DISALLOW_COPY_AND_ASSIGN(CreateViewTreeNodeTransaction); |
}; |
+class DestroyViewTreeNodeTransaction : public ViewManagerTransaction { |
+ public: |
+ DestroyViewTreeNodeTransaction(TransportNodeId node_id, |
+ ViewManagerSynchronizer* synchronizer) |
+ : ViewManagerTransaction(TYPE_DESTROY_VIEW_TREE_NODE, synchronizer), |
+ node_id_(node_id) {} |
+ virtual ~DestroyViewTreeNodeTransaction() {} |
+ |
+ private: |
+ // Overridden from ViewManagerTransaction: |
+ virtual void DoCommit() OVERRIDE { |
+ service()->DeleteNode( |
+ node_id_, |
+ change_id(), |
+ base::Bind(&ViewManagerTransaction::OnActionCompleted, |
+ base::Unretained(this))); |
+ } |
+ virtual void DoActionCompleted(bool success) OVERRIDE { |
+ // TODO(beng): recovery? |
+ } |
+ |
+ TransportNodeId node_id_; |
+ DISALLOW_COPY_AND_ASSIGN(DestroyViewTreeNodeTransaction); |
+}; |
+ |
class HierarchyTransaction : public ViewManagerTransaction { |
public: |
enum HierarchyChangeType { |
@@ -108,8 +141,8 @@ class HierarchyTransaction : public ViewManagerTransaction { |
TYPE_REMOVE |
}; |
HierarchyTransaction(HierarchyChangeType hierarchy_change_type, |
- uint16_t child_id, |
- uint16_t parent_id, |
+ TransportNodeId child_id, |
+ TransportNodeId parent_id, |
ViewManagerSynchronizer* synchronizer) |
: ViewManagerTransaction(TYPE_HIERARCHY, synchronizer), |
hierarchy_change_type_(hierarchy_change_type), |
@@ -145,8 +178,8 @@ class HierarchyTransaction : public ViewManagerTransaction { |
} |
const HierarchyChangeType hierarchy_change_type_; |
- const uint16_t child_id_; |
- const uint16_t parent_id_; |
+ const TransportNodeId child_id_; |
+ const TransportNodeId parent_id_; |
DISALLOW_COPY_AND_ASSIGN(HierarchyTransaction); |
}; |
@@ -155,7 +188,7 @@ ViewManagerSynchronizer::ViewManagerSynchronizer(ViewManager* view_manager) |
: view_manager_(view_manager), |
connected_(false), |
connection_id_(0), |
- next_id_(0), |
+ next_id_(1), |
next_change_id_(0) { |
InterfacePipe<services::view_manager::IViewManager, AnyInterface> |
view_manager_pipe; |
@@ -169,13 +202,20 @@ ViewManagerSynchronizer::~ViewManagerSynchronizer() { |
} |
uint16_t ViewManagerSynchronizer::CreateViewTreeNode() { |
- uint16_t id = next_id_++; |
+ 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) { |
+void ViewManagerSynchronizer::DestroyViewTreeNode(TransportNodeId node_id) { |
+ pending_transactions_.push_back( |
+ new DestroyViewTreeNodeTransaction(node_id, this)); |
+ ScheduleSync(); |
+} |
+ |
+void ViewManagerSynchronizer::AddChild(TransportNodeId child_id, |
+ TransportNodeId parent_id) { |
pending_transactions_.push_back( |
new HierarchyTransaction(HierarchyTransaction::TYPE_ADD, |
child_id, |
@@ -184,8 +224,8 @@ void ViewManagerSynchronizer::AddChild(uint16_t child_id, uint16_t parent_id) { |
ScheduleSync(); |
} |
-void ViewManagerSynchronizer::RemoveChild(uint16_t child_id, |
- uint16_t parent_id) { |
+void ViewManagerSynchronizer::RemoveChild(TransportNodeId child_id, |
+ TransportNodeId parent_id) { |
pending_transactions_.push_back( |
new HierarchyTransaction(HierarchyTransaction::TYPE_REMOVE, |
child_id, |
@@ -194,6 +234,15 @@ void ViewManagerSynchronizer::RemoveChild(uint16_t child_id, |
ScheduleSync(); |
} |
+void ViewManagerSynchronizer::BuildNodeTree( |
+ const Callback<void()>& callback) { |
+ service_->GetNodeTree( |
+ 1, |
+ base::Bind(&ViewManagerSynchronizer::OnTreeReceived, |
+ base::Unretained(this), |
+ callback)); |
+} |
+ |
//////////////////////////////////////////////////////////////////////////////// |
// ViewManagerSynchronizer, IViewManagerClient implementation: |
@@ -201,6 +250,9 @@ void ViewManagerSynchronizer::OnConnectionEstablished(uint16 connection_id) { |
connected_ = true; |
connection_id_ = connection_id; |
ScheduleSync(); |
+ FOR_EACH_OBSERVER(ViewManagerObserver, |
+ *ViewManagerPrivate(view_manager_).observers(), |
+ OnViewManagerConnected(view_manager_)); |
} |
void ViewManagerSynchronizer::OnNodeHierarchyChanged(uint32_t node, |
@@ -250,12 +302,53 @@ uint32_t ViewManagerSynchronizer::GetNextChangeId() { |
return next_change_id_; |
} |
+void ViewManagerSynchronizer::NotifyCommit() { |
+ FOR_EACH_OBSERVER(ViewManagerObserver, |
+ *ViewManagerPrivate(view_manager_).observers(), |
+ OnCommit(view_manager_)); |
+} |
+ |
+void ViewManagerSynchronizer::NotifyCommitResponse(bool success) { |
+ FOR_EACH_OBSERVER(ViewManagerObserver, |
+ *ViewManagerPrivate(view_manager_).observers(), |
+ OnCommitResponse(view_manager_, success)); |
+} |
+ |
void ViewManagerSynchronizer::RemoveFromPendingQueue( |
ViewManagerTransaction* transaction) { |
DCHECK_EQ(transaction, pending_transactions_.front()); |
pending_transactions_.erase(pending_transactions_.begin()); |
} |
+void ViewManagerSynchronizer::OnTreeReceived( |
+ const Callback<void()>& callback, |
+ const Array<INode>& nodes) { |
+ std::vector<ViewTreeNode*> parents; |
+ ViewTreeNode* root = NULL; |
+ ViewTreeNode* last_node = NULL; |
+ for (size_t i = 0; i < nodes.size(); ++i) { |
+ if (last_node && nodes[i].parent_id() == last_node->id()) { |
+ parents.push_back(last_node); |
+ } else if (!parents.empty()) { |
+ while (parents.back()->id() != nodes[i].parent_id()) |
+ parents.pop_back(); |
+ } |
+ // We don't use the ctor that takes a ViewManager here, since it will call |
+ // back to the service and attempt to create a new node. |
+ ViewTreeNode* node = new ViewTreeNode; |
+ ViewTreeNodePrivate private_node(node); |
+ private_node.set_view_manager(view_manager_); |
+ private_node.set_id(nodes[i].node_id()); |
+ if (!parents.empty()) |
+ ViewTreeNodePrivate(parents.back()).LocalAddChild(node); |
+ if (!last_node) |
+ root = node; |
+ last_node = node; |
+ } |
+ ViewManagerPrivate(view_manager_).set_tree(root); |
+ callback.Run(); |
+} |
+ |
} // namespace view_manager |
} // namespace services |
} // namespace mojo |