1 // Copyright (c) 2012 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 CHROME_BROWSER_SYNC_GLUE_MODEL_ASSOCIATION_MANAGER_H__ 6 #define CHROME_BROWSER_SYNC_GLUE_MODEL_ASSOCIATION_MANAGER_H__ 7 8 #include <map> 9 10 #include "base/memory/weak_ptr.h" 11 #include "base/timer/timer.h" 12 13 #include "chrome/browser/sync/glue/data_type_manager.h" 14 #include "sync/internal_api/public/data_type_association_stats.h" 15 #include "sync/internal_api/public/util/weak_handle.h" 16 17 // |ModelAssociationManager| does the heavy lifting for doing the actual model 18 // association. It instructs DataTypeControllers to load models, start 19 // associating and stopping. Since the operations are async it uses an 20 // interface to inform DataTypeManager the results of the operations. 21 // This class is owned by DataTypeManager. 22 namespace browser_sync { 23 24 class DataTypeController; 25 26 // |ModelAssociationManager| association functions are async. The results of 27 // those operations are passed back via this interface. 28 class ModelAssociationResultProcessor { 29 public: 30 virtual void OnSingleDataTypeAssociationDone( 31 syncer::ModelType type, 32 const syncer::DataTypeAssociationStats& association_stats) = 0; 33 virtual void OnModelAssociationDone( 34 const DataTypeManager::ConfigureResult& result) = 0; 35 virtual ~ModelAssociationResultProcessor() {} 36 37 // Called to let the |ModelAssociationResultProcessor| know that "delayed" 38 // types have finished loading and association should take place. (A delayed 39 // type here is a type that did not finish loading during the previous 40 // configure cycle.) 41 virtual void OnTypesLoaded() = 0; 42 }; 43 44 // The class that is responsible for model association. 45 class ModelAssociationManager { 46 public: 47 ModelAssociationManager(const DataTypeController::TypeMap* controllers, 48 ModelAssociationResultProcessor* processor); 49 virtual ~ModelAssociationManager(); 50 51 // Initializes the state to do the model association in future. This 52 // should be called before communicating with sync server. A subsequent call 53 // of Initialize is only allowed if the ModelAssociationManager has invoked 54 // |OnModelAssociationDone| on the |ModelAssociationResultProcessor|. After 55 // this call, there should be several calls to StartAssociationAsync() 56 // to associate subset of |desired_types|. 57 void Initialize(syncer::ModelTypeSet desired_types); 58 59 // Can be called at any time. Synchronously stops all datatypes. 60 void Stop(); 61 62 // Should only be called after Initialize to start the actual association. 63 // |types_to_associate| should be subset of |desired_types| in Initialize(). 64 // When this is completed, |OnModelAssociationDone| will be invoked. 65 void StartAssociationAsync(const syncer::ModelTypeSet& types_to_associate); 66 67 // It is valid to call this only when we are initialized to configure 68 // but we have not started the configuration.(i.e., |Initialize| has 69 // been called but |StartAssociationAsync| has not yet been called.) 70 // If we have started configuration then the DataTypeManager will wait until 71 // the current configuration is done before processing the reconfigure 72 // request. We goto IDLE state and clear all our internal state. It is 73 // safe to do this as we have not started association on any DTCs. 74 void ResetForReconfiguration(); 75 76 // Should only be called after Initialize. 77 // Stops any disabled types. 78 void StopDisabledTypes(); 79 80 // This is used for TESTING PURPOSE ONLY. The test case can inspect 81 // and modify the timer. 82 // TODO(sync) : This would go away if we made this class be able to do 83 // Dependency injection. crbug.com/129212. 84 base::OneShotTimer<ModelAssociationManager>* GetTimerForTesting(); 85 86 private: 87 enum State { 88 // This is the state after |Initialize| is called. 89 INITIALIZED_TO_CONFIGURE, 90 // Starting a new configuration. 91 CONFIGURING, 92 // A stop command was issued. 93 ABORTED, 94 // No configuration is in progress. 95 IDLE 96 }; 97 98 // Returns true if any requested types currently need to start model 99 // association. If non-null, fills |needs_start| with all such controllers. 100 bool GetControllersNeedingStart( 101 std::vector<DataTypeController*>* needs_start); 102 103 // Callback passed to each data type controller on starting association. This 104 // callback will be invoked when the model association is done. 105 void TypeStartCallback(DataTypeController::StartResult start_result, 106 const syncer::SyncMergeResult& local_merge_result, 107 const syncer::SyncMergeResult& syncer_merge_result); 108 109 // Callback that will be invoked when the models finish loading. This callback 110 // will be passed to |LoadModels| function. 111 void ModelLoadCallback(syncer::ModelType type, syncer::SyncError error); 112 113 // Calls the |LoadModels| method on the next controller waiting to start. 114 void LoadModelForNextType(); 115 116 // Calls |StartAssociating| on the next available controller whose models are 117 // loaded. 118 void StartAssociatingNextType(); 119 120 // When a type fails to load or fails associating this method is invoked to 121 // do the book keeping and do the UMA reporting. 122 void AppendToFailedDatatypesAndLogError( 123 DataTypeController::StartResult result, 124 const syncer::SyncError& error); 125 126 syncer::ModelTypeSet GetTypesWaitingToLoad(); 127 128 State state_; 129 130 // Data types currently being associated. 131 syncer::ModelTypeSet associating_types_; 132 133 // Collects the list of errors resulting from failing to start a type. This 134 // would eventually be sent to the listeners after all the types have 135 // been given a chance to start. 136 std::map<syncer::ModelType, syncer::SyncError> failed_data_types_info_; 137 138 // The set of types that can't configure due to cryptographer errors. 139 syncer::ModelTypeSet needs_crypto_types_; 140 141 // The order in which association of the datatypes should be performed. 142 std::map<syncer::ModelType, int> start_order_; 143 144 // This illustration explains the movement of one DTC through various lists. 145 // Consider a dataype, say, BOOKMARKS which is NOT_RUNNING and will be 146 // configured now. 147 // Initially all lists are empty. BOOKMARKS is in the |controllers_| 148 // map. Here is how the controller moves to various list 149 // (indicated by arrows). The first column is the method that causes the 150 // transition. 151 // Step 1 : |Initialize| - |controllers_| -> |needs_start_| 152 // Step 2 : |LoadModelForNextType| - |needs_start_| -> |pending_model_load_| 153 // Step 3 : |ModelLoadCallback| - |pending_model_load_| -> 154 // |waiting_to_associate_| 155 // Step 4 : |StartAssociatingNextType| - |waiting_to_associate_| -> 156 // |currently_associating_| 157 // Step 5 : |TypeStartCallback| - |currently_associating_| set to NULL. 158 159 // Controllers that need to be started during a config cycle. 160 std::vector<DataTypeController*> needs_start_; 161 162 // Controllers that need to be stopped during a config cycle. 163 std::vector<DataTypeController*> needs_stop_; 164 165 // Controllers whose |LoadModels| function has been invoked and that are 166 // waiting for their models to be loaded. Cotrollers will be moved from 167 // |needs_start_| to this list as their |LoadModels| method is invoked. 168 std::vector<DataTypeController*> pending_model_load_; 169 170 // Controllers whose models are loaded and are ready to do model 171 // association. Controllers will be moved from |pending_model_load_| 172 // list to this list as they finish loading their model. 173 std::vector<DataTypeController*> waiting_to_associate_; 174 175 // Time when StartAssociationAsync() is called to associate for a set of data 176 // types. 177 base::Time association_start_time_; 178 179 // Controller currently doing model association. 180 DataTypeController* currently_associating_; 181 base::Time current_type_association_start_time_; 182 183 // Set of all registered controllers. 184 const DataTypeController::TypeMap* controllers_; 185 186 // The processor in charge of handling model association results. 187 ModelAssociationResultProcessor* result_processor_; 188 189 // Timer to track and limit how long a datatype takes to model associate. 190 base::OneShotTimer<ModelAssociationManager> timer_; 191 192 base::WeakPtrFactory<ModelAssociationManager> weak_ptr_factory_; 193 194 DISALLOW_COPY_AND_ASSIGN(ModelAssociationManager); 195 }; 196 } // namespace browser_sync 197 #endif // CHROME_BROWSER_SYNC_GLUE_MODEL_ASSOCIATION_MANAGER_H__ 198