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 #ifndef MOJO_SERVICES_VIEW_MANAGER_ROOT_NODE_MANAGER_H_ 6 #define MOJO_SERVICES_VIEW_MANAGER_ROOT_NODE_MANAGER_H_ 7 8 #include <map> 9 #include <set> 10 11 #include "base/basictypes.h" 12 #include "mojo/public/cpp/bindings/array.h" 13 #include "mojo/services/view_manager/ids.h" 14 #include "mojo/services/view_manager/node.h" 15 #include "mojo/services/view_manager/node_delegate.h" 16 #include "mojo/services/view_manager/root_view_manager.h" 17 #include "mojo/services/view_manager/view_manager_export.h" 18 19 namespace ui { 20 class Event; 21 } 22 23 namespace mojo { 24 25 class ServiceProvider; 26 27 namespace view_manager { 28 namespace service { 29 30 class RootViewManagerDelegate; 31 class View; 32 class ViewManagerServiceImpl; 33 34 // RootNodeManager is responsible for managing the set of 35 // ViewManagerServiceImpls as well as providing the root of the node hierarchy. 36 class MOJO_VIEW_MANAGER_EXPORT RootNodeManager : public NodeDelegate { 37 public: 38 // Used to indicate if the server id should be incremented after notifiying 39 // clients of the change. 40 enum ChangeType { 41 CHANGE_TYPE_ADVANCE_SERVER_CHANGE_ID, 42 CHANGE_TYPE_DONT_ADVANCE_SERVER_CHANGE_ID, 43 }; 44 45 // Create when a ViewManagerServiceImpl is about to make a change. Ensures 46 // clients are notified of the correct change id. 47 class ScopedChange { 48 public: 49 ScopedChange(ViewManagerServiceImpl* connection, 50 RootNodeManager* root, 51 RootNodeManager::ChangeType change_type, 52 bool is_delete_node); 53 ~ScopedChange(); 54 connection_id()55 ConnectionSpecificId connection_id() const { return connection_id_; } change_type()56 ChangeType change_type() const { return change_type_; } is_delete_node()57 bool is_delete_node() const { return is_delete_node_; } 58 59 // Marks the connection with the specified id as having seen a message. MarkConnectionAsMessaged(ConnectionSpecificId connection_id)60 void MarkConnectionAsMessaged(ConnectionSpecificId connection_id) { 61 message_ids_.insert(connection_id); 62 } 63 64 // Returns true if MarkConnectionAsMessaged(connection_id) was invoked. DidMessageConnection(ConnectionSpecificId connection_id)65 bool DidMessageConnection(ConnectionSpecificId connection_id) const { 66 return message_ids_.count(connection_id) > 0; 67 } 68 69 private: 70 RootNodeManager* root_; 71 const ConnectionSpecificId connection_id_; 72 const ChangeType change_type_; 73 const bool is_delete_node_; 74 75 // See description of MarkConnectionAsMessaged/DidMessageConnection. 76 std::set<ConnectionSpecificId> message_ids_; 77 78 DISALLOW_COPY_AND_ASSIGN(ScopedChange); 79 }; 80 81 RootNodeManager(ServiceProvider* service_provider, 82 RootViewManagerDelegate* view_manager_delegate); 83 virtual ~RootNodeManager(); 84 85 // Returns the id for the next ViewManagerServiceImpl. 86 ConnectionSpecificId GetAndAdvanceNextConnectionId(); 87 next_server_change_id()88 Id next_server_change_id() const { 89 return next_server_change_id_; 90 } 91 92 void AddConnection(ViewManagerServiceImpl* connection); 93 void RemoveConnection(ViewManagerServiceImpl* connection); 94 95 // Establishes the initial client. Similar to Connect(), but the resulting 96 // client is allowed to do anything. 97 void EmbedRoot(const std::string& url); 98 99 // See description of ViewManagerService::Embed() for details. This assumes 100 // |node_ids| has been validated. 101 void Embed(ConnectionSpecificId creator_id, 102 const String& url, 103 const Array<Id>& node_ids); 104 105 // Returns the connection by id. 106 ViewManagerServiceImpl* GetConnection(ConnectionSpecificId connection_id); 107 108 // Returns the Node identified by |id|. 109 Node* GetNode(const NodeId& id); 110 111 // Returns the View identified by |id|. 112 View* GetView(const ViewId& id); 113 root()114 Node* root() { return &root_; } 115 IsProcessingChange()116 bool IsProcessingChange() const { return current_change_ != NULL; } 117 is_processing_delete_node()118 bool is_processing_delete_node() const { 119 return current_change_ && current_change_->is_delete_node(); } 120 121 // Invoked when a connection messages a client about the change. This is used 122 // to avoid sending ServerChangeIdAdvanced() unnecessarily. 123 void OnConnectionMessagedClient(ConnectionSpecificId id); 124 125 // Returns true if OnConnectionMessagedClient() was invoked for id. 126 bool DidConnectionMessageClient(ConnectionSpecificId id) const; 127 128 ViewManagerServiceImpl* GetConnectionByCreator( 129 ConnectionSpecificId creator_id, 130 const std::string& url) const; 131 132 void DispatchViewInputEventToWindowManager(const View* view, 133 const ui::Event* event); 134 135 // These functions trivially delegate to all ViewManagerServiceImpls, which in 136 // term notify their clients. 137 void ProcessNodeBoundsChanged(const Node* node, 138 const gfx::Rect& old_bounds, 139 const gfx::Rect& new_bounds); 140 void ProcessNodeHierarchyChanged(const Node* node, 141 const Node* new_parent, 142 const Node* old_parent); 143 void ProcessNodeReorder(const Node* node, 144 const Node* relative_node, 145 const OrderDirection direction); 146 void ProcessNodeViewReplaced(const Node* node, 147 const View* new_view_id, 148 const View* old_view_id); 149 void ProcessNodeDeleted(const NodeId& node); 150 void ProcessViewDeleted(const ViewId& view); 151 152 private: 153 // Used to setup any static state needed by RootNodeManager. 154 struct Context { 155 Context(); 156 ~Context(); 157 }; 158 159 typedef std::map<ConnectionSpecificId, ViewManagerServiceImpl*> ConnectionMap; 160 161 // Invoked when a connection is about to make a change. Subsequently followed 162 // by FinishChange() once the change is done. 163 // 164 // Changes should never nest, meaning each PrepareForChange() must be 165 // balanced with a call to FinishChange() with no PrepareForChange() 166 // in between. 167 void PrepareForChange(ScopedChange* change); 168 169 // Balances a call to PrepareForChange(). 170 void FinishChange(); 171 172 // Returns true if the specified connection originated the current change. IsChangeSource(ConnectionSpecificId connection_id)173 bool IsChangeSource(ConnectionSpecificId connection_id) const { 174 return current_change_ && current_change_->connection_id() == connection_id; 175 } 176 177 // Implementation of the two embed variants. 178 ViewManagerServiceImpl* EmbedImpl(ConnectionSpecificId creator_id, 179 const String& url, 180 const Array<Id>& node_ids); 181 182 // Overridden from NodeDelegate: 183 virtual void OnNodeHierarchyChanged(const Node* node, 184 const Node* new_parent, 185 const Node* old_parent) OVERRIDE; 186 virtual void OnNodeViewReplaced(const Node* node, 187 const View* new_view, 188 const View* old_view) OVERRIDE; 189 virtual void OnViewInputEvent(const View* view, 190 const ui::Event* event) OVERRIDE; 191 192 Context context_; 193 194 ServiceProvider* service_provider_; 195 196 // ID to use for next ViewManagerServiceImpl. 197 ConnectionSpecificId next_connection_id_; 198 199 Id next_server_change_id_; 200 201 // Set of ViewManagerServiceImpls. 202 ConnectionMap connection_map_; 203 204 RootViewManager root_view_manager_; 205 206 // Root node. 207 Node root_; 208 209 // Set of ViewManagerServiceImpls created by way of Connect(). These have to 210 // be explicitly destroyed. 211 std::set<ViewManagerServiceImpl*> connections_created_by_connect_; 212 213 // If non-null we're processing a change. The ScopedChange is not owned by us 214 // (it's created on the stack by ViewManagerServiceImpl). 215 ScopedChange* current_change_; 216 217 DISALLOW_COPY_AND_ASSIGN(RootNodeManager); 218 }; 219 220 } // namespace service 221 } // namespace view_manager 222 } // namespace mojo 223 224 #endif // MOJO_SERVICES_VIEW_MANAGER_ROOT_NODE_MANAGER_H_ 225