| OLD | NEW | 
|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be | 
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. | 
| 4 | 4 | 
| 5 #include "components/sync/driver/model_association_manager.h" | 5 #include "components/sync/driver/model_association_manager.h" | 
| 6 | 6 | 
| 7 #include <stddef.h> | 7 #include <stddef.h> | 
| 8 #include <stdint.h> | 8 #include <stdint.h> | 
| 9 | 9 | 
| 10 #include <algorithm> | 10 #include <algorithm> | 
| 11 #include <functional> | 11 #include <functional> | 
| 12 | 12 | 
| 13 #include "base/logging.h" | 13 #include "base/logging.h" | 
| 14 #include "base/message_loop/message_loop.h" | 14 #include "base/message_loop/message_loop.h" | 
| 15 #include "base/metrics/histogram_macros.h" | 15 #include "base/metrics/histogram_macros.h" | 
| 16 #include "base/trace_event/trace_event.h" | 16 #include "base/trace_event/trace_event.h" | 
| 17 #include "components/sync/api/sync_merge_result.h" | 17 #include "components/sync/api/sync_merge_result.h" | 
| 18 #include "components/sync/base/model_type.h" | 18 #include "components/sync/base/model_type.h" | 
| 19 | 19 | 
| 20 using syncer::ModelTypeSet; | 20 namespace syncer { | 
| 21 |  | 
| 22 namespace sync_driver { |  | 
| 23 | 21 | 
| 24 namespace { | 22 namespace { | 
| 25 | 23 | 
| 26 static const syncer::ModelType kStartOrder[] = { | 24 static const ModelType kStartOrder[] = { | 
| 27     syncer::NIGORI,       //  Listed for completeness. | 25     NIGORI,       //  Listed for completeness. | 
| 28     syncer::DEVICE_INFO,  //  Listed for completeness. | 26     DEVICE_INFO,  //  Listed for completeness. | 
| 29     syncer::EXPERIMENTS,  //  Listed for completeness. | 27     EXPERIMENTS,  //  Listed for completeness. | 
| 30     syncer::PROXY_TABS,   //  Listed for completeness. | 28     PROXY_TABS,   //  Listed for completeness. | 
| 31 | 29 | 
| 32     // Kick off the association of the non-UI types first so they can associate | 30     // Kick off the association of the non-UI types first so they can associate | 
| 33     // in parallel with the UI types. | 31     // in parallel with the UI types. | 
| 34     syncer::PASSWORDS, syncer::AUTOFILL, syncer::AUTOFILL_PROFILE, | 32     PASSWORDS, AUTOFILL, AUTOFILL_PROFILE, AUTOFILL_WALLET_DATA, | 
| 35     syncer::AUTOFILL_WALLET_DATA, syncer::AUTOFILL_WALLET_METADATA, | 33     AUTOFILL_WALLET_METADATA, EXTENSION_SETTINGS, APP_SETTINGS, TYPED_URLS, | 
| 36     syncer::EXTENSION_SETTINGS, syncer::APP_SETTINGS, syncer::TYPED_URLS, | 34     HISTORY_DELETE_DIRECTIVES, SYNCED_NOTIFICATIONS, | 
| 37     syncer::HISTORY_DELETE_DIRECTIVES, syncer::SYNCED_NOTIFICATIONS, | 35     SYNCED_NOTIFICATION_APP_INFO, | 
| 38     syncer::SYNCED_NOTIFICATION_APP_INFO, |  | 
| 39 | 36 | 
| 40     // UI thread data types. | 37     // UI thread data types. | 
| 41     syncer::BOOKMARKS, | 38     BOOKMARKS, | 
| 42     syncer::SUPERVISED_USERS,  //  Syncing supervised users on initial login | 39     SUPERVISED_USERS,  //  Syncing supervised users on initial login | 
| 43                                //  might block creating a new supervised user, | 40                        //  might block creating a new supervised user, | 
| 44                                //  so we want to do it early. | 41                        //  so we want to do it early. | 
| 45     syncer::PREFERENCES, syncer::PRIORITY_PREFERENCES, syncer::EXTENSIONS, | 42     PREFERENCES, PRIORITY_PREFERENCES, EXTENSIONS, APPS, APP_LIST, ARC_PACKAGE, | 
| 46     syncer::APPS, syncer::APP_LIST, syncer::ARC_PACKAGE, syncer::READING_LIST, | 43     READING_LIST, THEMES, SEARCH_ENGINES, SESSIONS, APP_NOTIFICATIONS, | 
| 47     syncer::THEMES, syncer::SEARCH_ENGINES, syncer::SESSIONS, | 44     DICTIONARY, FAVICON_IMAGES, FAVICON_TRACKING, PRINTERS, | 
| 48     syncer::APP_NOTIFICATIONS, syncer::DICTIONARY, syncer::FAVICON_IMAGES, | 45     SUPERVISED_USER_SETTINGS, SUPERVISED_USER_SHARED_SETTINGS, | 
| 49     syncer::FAVICON_TRACKING, syncer::PRINTERS, | 46     SUPERVISED_USER_WHITELISTS, ARTICLES, WIFI_CREDENTIALS, | 
| 50     syncer::SUPERVISED_USER_SETTINGS, syncer::SUPERVISED_USER_SHARED_SETTINGS, |  | 
| 51     syncer::SUPERVISED_USER_WHITELISTS, syncer::ARTICLES, |  | 
| 52     syncer::WIFI_CREDENTIALS, |  | 
| 53 }; | 47 }; | 
| 54 | 48 | 
| 55 static_assert(arraysize(kStartOrder) == | 49 static_assert(arraysize(kStartOrder) == | 
| 56                   syncer::MODEL_TYPE_COUNT - syncer::FIRST_REAL_MODEL_TYPE, | 50                   MODEL_TYPE_COUNT - FIRST_REAL_MODEL_TYPE, | 
| 57               "kStartOrder must have MODEL_TYPE_COUNT - " | 51               "kStartOrder must have MODEL_TYPE_COUNT - " | 
| 58               "FIRST_REAL_MODEL_TYPE elements"); | 52               "FIRST_REAL_MODEL_TYPE elements"); | 
| 59 | 53 | 
| 60 // The amount of time we wait for association to finish. If some types haven't | 54 // The amount of time we wait for association to finish. If some types haven't | 
| 61 // finished association by the time, DataTypeManager is notified of the | 55 // finished association by the time, DataTypeManager is notified of the | 
| 62 // unfinished types. | 56 // unfinished types. | 
| 63 const int64_t kAssociationTimeOutInSeconds = 600; | 57 const int64_t kAssociationTimeOutInSeconds = 600; | 
| 64 | 58 | 
| 65 syncer::DataTypeAssociationStats BuildAssociationStatsFromMergeResults( | 59 DataTypeAssociationStats BuildAssociationStatsFromMergeResults( | 
| 66     const syncer::SyncMergeResult& local_merge_result, | 60     const SyncMergeResult& local_merge_result, | 
| 67     const syncer::SyncMergeResult& syncer_merge_result, | 61     const SyncMergeResult& syncer_merge_result, | 
| 68     const base::TimeDelta& association_wait_time, | 62     const base::TimeDelta& association_wait_time, | 
| 69     const base::TimeDelta& association_time) { | 63     const base::TimeDelta& association_time) { | 
| 70   DCHECK_EQ(local_merge_result.model_type(), syncer_merge_result.model_type()); | 64   DCHECK_EQ(local_merge_result.model_type(), syncer_merge_result.model_type()); | 
| 71   syncer::DataTypeAssociationStats stats; | 65   DataTypeAssociationStats stats; | 
| 72   stats.had_error = | 66   stats.had_error = | 
| 73       local_merge_result.error().IsSet() || syncer_merge_result.error().IsSet(); | 67       local_merge_result.error().IsSet() || syncer_merge_result.error().IsSet(); | 
| 74   stats.num_local_items_before_association = | 68   stats.num_local_items_before_association = | 
| 75       local_merge_result.num_items_before_association(); | 69       local_merge_result.num_items_before_association(); | 
| 76   stats.num_sync_items_before_association = | 70   stats.num_sync_items_before_association = | 
| 77       syncer_merge_result.num_items_before_association(); | 71       syncer_merge_result.num_items_before_association(); | 
| 78   stats.num_local_items_after_association = | 72   stats.num_local_items_after_association = | 
| 79       local_merge_result.num_items_after_association(); | 73       local_merge_result.num_items_after_association(); | 
| 80   stats.num_sync_items_after_association = | 74   stats.num_sync_items_after_association = | 
| 81       syncer_merge_result.num_items_after_association(); | 75       syncer_merge_result.num_items_after_association(); | 
| (...skipping 25 matching lines...) Expand all  Loading... | 
| 107       weak_ptr_factory_(this) { | 101       weak_ptr_factory_(this) { | 
| 108   // Ensure all data type controllers are stopped. | 102   // Ensure all data type controllers are stopped. | 
| 109   for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); | 103   for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); | 
| 110        it != controllers_->end(); ++it) { | 104        it != controllers_->end(); ++it) { | 
| 111     DCHECK_EQ(DataTypeController::NOT_RUNNING, (*it).second->state()); | 105     DCHECK_EQ(DataTypeController::NOT_RUNNING, (*it).second->state()); | 
| 112   } | 106   } | 
| 113 } | 107 } | 
| 114 | 108 | 
| 115 ModelAssociationManager::~ModelAssociationManager() {} | 109 ModelAssociationManager::~ModelAssociationManager() {} | 
| 116 | 110 | 
| 117 void ModelAssociationManager::Initialize(syncer::ModelTypeSet desired_types) { | 111 void ModelAssociationManager::Initialize(ModelTypeSet desired_types) { | 
| 118   // state_ can be INITIALIZED if types are reconfigured when | 112   // state_ can be INITIALIZED if types are reconfigured when | 
| 119   // data is being downloaded, so StartAssociationAsync() is never called for | 113   // data is being downloaded, so StartAssociationAsync() is never called for | 
| 120   // the first configuration. | 114   // the first configuration. | 
| 121   DCHECK_NE(ASSOCIATING, state_); | 115   DCHECK_NE(ASSOCIATING, state_); | 
| 122 | 116 | 
| 123   // Only keep types that have controllers. | 117   // Only keep types that have controllers. | 
| 124   desired_types_.Clear(); | 118   desired_types_.Clear(); | 
| 125   for (syncer::ModelTypeSet::Iterator it = desired_types.First(); it.Good(); | 119   for (ModelTypeSet::Iterator it = desired_types.First(); it.Good(); it.Inc()) { | 
| 126        it.Inc()) { |  | 
| 127     if (controllers_->find(it.Get()) != controllers_->end()) | 120     if (controllers_->find(it.Get()) != controllers_->end()) | 
| 128       desired_types_.Put(it.Get()); | 121       desired_types_.Put(it.Get()); | 
| 129   } | 122   } | 
| 130 | 123 | 
| 131   DVLOG(1) << "ModelAssociationManager: Initializing for " | 124   DVLOG(1) << "ModelAssociationManager: Initializing for " | 
| 132            << syncer::ModelTypeSetToString(desired_types_); | 125            << ModelTypeSetToString(desired_types_); | 
| 133 | 126 | 
| 134   state_ = INITIALIZED; | 127   state_ = INITIALIZED; | 
| 135   notified_about_ready_for_configure_ = false; | 128   notified_about_ready_for_configure_ = false; | 
| 136 | 129 | 
| 137   StopDisabledTypes(); | 130   StopDisabledTypes(); | 
| 138   LoadEnabledTypes(); | 131   LoadEnabledTypes(); | 
| 139 } | 132 } | 
| 140 | 133 | 
| 141 void ModelAssociationManager::StopDatatype(const syncer::SyncError& error, | 134 void ModelAssociationManager::StopDatatype(const SyncError& error, | 
| 142                                            DataTypeController* dtc) { | 135                                            DataTypeController* dtc) { | 
| 143   loaded_types_.Remove(dtc->type()); | 136   loaded_types_.Remove(dtc->type()); | 
| 144   associated_types_.Remove(dtc->type()); | 137   associated_types_.Remove(dtc->type()); | 
| 145   associating_types_.Remove(dtc->type()); | 138   associating_types_.Remove(dtc->type()); | 
| 146 | 139 | 
| 147   if (error.IsSet() || dtc->state() != DataTypeController::NOT_RUNNING) { | 140   if (error.IsSet() || dtc->state() != DataTypeController::NOT_RUNNING) { | 
| 148     // If an error was set, the delegate must be informed of the error. | 141     // If an error was set, the delegate must be informed of the error. | 
| 149     delegate_->OnSingleDataTypeWillStop(dtc->type(), error); | 142     delegate_->OnSingleDataTypeWillStop(dtc->type(), error); | 
| 150     dtc->Stop(); | 143     dtc->Stop(); | 
| 151   } | 144   } | 
| 152 } | 145 } | 
| 153 | 146 | 
| 154 void ModelAssociationManager::StopDisabledTypes() { | 147 void ModelAssociationManager::StopDisabledTypes() { | 
| 155   DVLOG(1) << "ModelAssociationManager: Stopping disabled types."; | 148   DVLOG(1) << "ModelAssociationManager: Stopping disabled types."; | 
| 156   for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); | 149   for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); | 
| 157        it != controllers_->end(); ++it) { | 150        it != controllers_->end(); ++it) { | 
| 158     DataTypeController* dtc = (*it).second.get(); | 151     DataTypeController* dtc = (*it).second.get(); | 
| 159     if (dtc->state() != DataTypeController::NOT_RUNNING && | 152     if (dtc->state() != DataTypeController::NOT_RUNNING && | 
| 160         !desired_types_.Has(dtc->type())) { | 153         !desired_types_.Has(dtc->type())) { | 
| 161       DVLOG(1) << "ModelAssociationManager: stop " << dtc->name(); | 154       DVLOG(1) << "ModelAssociationManager: stop " << dtc->name(); | 
| 162       StopDatatype(syncer::SyncError(), dtc); | 155       StopDatatype(SyncError(), dtc); | 
| 163     } | 156     } | 
| 164   } | 157   } | 
| 165 } | 158 } | 
| 166 | 159 | 
| 167 void ModelAssociationManager::LoadEnabledTypes() { | 160 void ModelAssociationManager::LoadEnabledTypes() { | 
| 168   // Load in kStartOrder. | 161   // Load in kStartOrder. | 
| 169   for (size_t i = 0; i < arraysize(kStartOrder); i++) { | 162   for (size_t i = 0; i < arraysize(kStartOrder); i++) { | 
| 170     syncer::ModelType type = kStartOrder[i]; | 163     ModelType type = kStartOrder[i]; | 
| 171     if (!desired_types_.Has(type)) | 164     if (!desired_types_.Has(type)) | 
| 172       continue; | 165       continue; | 
| 173 | 166 | 
| 174     DCHECK(controllers_->find(type) != controllers_->end()); | 167     DCHECK(controllers_->find(type) != controllers_->end()); | 
| 175     DataTypeController* dtc = controllers_->find(type)->second.get(); | 168     DataTypeController* dtc = controllers_->find(type)->second.get(); | 
| 176     if (dtc->state() == DataTypeController::NOT_RUNNING) { | 169     if (dtc->state() == DataTypeController::NOT_RUNNING) { | 
| 177       DCHECK(!loaded_types_.Has(dtc->type())); | 170       DCHECK(!loaded_types_.Has(dtc->type())); | 
| 178       DCHECK(!associated_types_.Has(dtc->type())); | 171       DCHECK(!associated_types_.Has(dtc->type())); | 
| 179       dtc->LoadModels(base::Bind(&ModelAssociationManager::ModelLoadCallback, | 172       dtc->LoadModels(base::Bind(&ModelAssociationManager::ModelLoadCallback, | 
| 180                                  weak_ptr_factory_.GetWeakPtr())); | 173                                  weak_ptr_factory_.GetWeakPtr())); | 
| 181     } | 174     } | 
| 182   } | 175   } | 
| 183   NotifyDelegateIfReadyForConfigure(); | 176   NotifyDelegateIfReadyForConfigure(); | 
| 184 } | 177 } | 
| 185 | 178 | 
| 186 void ModelAssociationManager::StartAssociationAsync( | 179 void ModelAssociationManager::StartAssociationAsync( | 
| 187     const syncer::ModelTypeSet& types_to_associate) { | 180     const ModelTypeSet& types_to_associate) { | 
| 188   DCHECK_EQ(INITIALIZED, state_); | 181   DCHECK_EQ(INITIALIZED, state_); | 
| 189   DVLOG(1) << "Starting association for " | 182   DVLOG(1) << "Starting association for " | 
| 190            << syncer::ModelTypeSetToString(types_to_associate); | 183            << ModelTypeSetToString(types_to_associate); | 
| 191   state_ = ASSOCIATING; | 184   state_ = ASSOCIATING; | 
| 192 | 185 | 
| 193   association_start_time_ = base::TimeTicks::Now(); | 186   association_start_time_ = base::TimeTicks::Now(); | 
| 194 | 187 | 
| 195   requested_types_ = types_to_associate; | 188   requested_types_ = types_to_associate; | 
| 196 | 189 | 
| 197   associating_types_ = types_to_associate; | 190   associating_types_ = types_to_associate; | 
| 198   associating_types_.RetainAll(desired_types_); | 191   associating_types_.RetainAll(desired_types_); | 
| 199   associating_types_.RemoveAll(associated_types_); | 192   associating_types_.RemoveAll(associated_types_); | 
| 200 | 193 | 
| 201   // Assume success. | 194   // Assume success. | 
| 202   configure_status_ = DataTypeManager::OK; | 195   configure_status_ = DataTypeManager::OK; | 
| 203 | 196 | 
| 204   // Done if no types to associate. | 197   // Done if no types to associate. | 
| 205   if (associating_types_.Empty()) { | 198   if (associating_types_.Empty()) { | 
| 206     ModelAssociationDone(INITIALIZED); | 199     ModelAssociationDone(INITIALIZED); | 
| 207     return; | 200     return; | 
| 208   } | 201   } | 
| 209 | 202 | 
| 210   timer_.Start(FROM_HERE, | 203   timer_.Start(FROM_HERE, | 
| 211                base::TimeDelta::FromSeconds(kAssociationTimeOutInSeconds), | 204                base::TimeDelta::FromSeconds(kAssociationTimeOutInSeconds), | 
| 212                base::Bind(&ModelAssociationManager::ModelAssociationDone, | 205                base::Bind(&ModelAssociationManager::ModelAssociationDone, | 
| 213                           weak_ptr_factory_.GetWeakPtr(), INITIALIZED)); | 206                           weak_ptr_factory_.GetWeakPtr(), INITIALIZED)); | 
| 214 | 207 | 
| 215   // Start association of types that are loaded in specified order. | 208   // Start association of types that are loaded in specified order. | 
| 216   for (size_t i = 0; i < arraysize(kStartOrder); i++) { | 209   for (size_t i = 0; i < arraysize(kStartOrder); i++) { | 
| 217     syncer::ModelType type = kStartOrder[i]; | 210     ModelType type = kStartOrder[i]; | 
| 218     if (!associating_types_.Has(type) || !loaded_types_.Has(type)) | 211     if (!associating_types_.Has(type) || !loaded_types_.Has(type)) | 
| 219       continue; | 212       continue; | 
| 220 | 213 | 
| 221     DataTypeController* dtc = controllers_->find(type)->second.get(); | 214     DataTypeController* dtc = controllers_->find(type)->second.get(); | 
| 222     DCHECK(DataTypeController::MODEL_LOADED == dtc->state() || | 215     DCHECK(DataTypeController::MODEL_LOADED == dtc->state() || | 
| 223            DataTypeController::ASSOCIATING == dtc->state()); | 216            DataTypeController::ASSOCIATING == dtc->state()); | 
| 224     if (dtc->state() == DataTypeController::MODEL_LOADED) { | 217     if (dtc->state() == DataTypeController::MODEL_LOADED) { | 
| 225       TRACE_EVENT_ASYNC_BEGIN1("sync", "ModelAssociation", dtc, "DataType", | 218       TRACE_EVENT_ASYNC_BEGIN1("sync", "ModelAssociation", dtc, "DataType", | 
| 226                                ModelTypeToString(type)); | 219                                ModelTypeToString(type)); | 
| 227 | 220 | 
| 228       dtc->StartAssociating(base::Bind( | 221       dtc->StartAssociating(base::Bind( | 
| 229           &ModelAssociationManager::TypeStartCallback, | 222           &ModelAssociationManager::TypeStartCallback, | 
| 230           weak_ptr_factory_.GetWeakPtr(), type, base::TimeTicks::Now())); | 223           weak_ptr_factory_.GetWeakPtr(), type, base::TimeTicks::Now())); | 
| 231     } | 224     } | 
| 232   } | 225   } | 
| 233 } | 226 } | 
| 234 | 227 | 
| 235 void ModelAssociationManager::Stop() { | 228 void ModelAssociationManager::Stop() { | 
| 236   // Ignore callbacks from controllers. | 229   // Ignore callbacks from controllers. | 
| 237   weak_ptr_factory_.InvalidateWeakPtrs(); | 230   weak_ptr_factory_.InvalidateWeakPtrs(); | 
| 238 | 231 | 
| 239   // Stop started data types. | 232   // Stop started data types. | 
| 240   for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); | 233   for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); | 
| 241        it != controllers_->end(); ++it) { | 234        it != controllers_->end(); ++it) { | 
| 242     DataTypeController* dtc = (*it).second.get(); | 235     DataTypeController* dtc = (*it).second.get(); | 
| 243     if (dtc->state() != DataTypeController::NOT_RUNNING) { | 236     if (dtc->state() != DataTypeController::NOT_RUNNING) { | 
| 244       StopDatatype(syncer::SyncError(), dtc); | 237       StopDatatype(SyncError(), dtc); | 
| 245       DVLOG(1) << "ModelAssociationManager: Stopped " << dtc->name(); | 238       DVLOG(1) << "ModelAssociationManager: Stopped " << dtc->name(); | 
| 246     } | 239     } | 
| 247   } | 240   } | 
| 248 | 241 | 
| 249   desired_types_.Clear(); | 242   desired_types_.Clear(); | 
| 250   loaded_types_.Clear(); | 243   loaded_types_.Clear(); | 
| 251   associated_types_.Clear(); | 244   associated_types_.Clear(); | 
| 252 | 245 | 
| 253   if (state_ == ASSOCIATING) { | 246   if (state_ == ASSOCIATING) { | 
| 254     if (configure_status_ == DataTypeManager::OK) | 247     if (configure_status_ == DataTypeManager::OK) | 
| 255       configure_status_ = DataTypeManager::ABORTED; | 248       configure_status_ = DataTypeManager::ABORTED; | 
| 256     DVLOG(1) << "ModelAssociationManager: Calling OnModelAssociationDone"; | 249     DVLOG(1) << "ModelAssociationManager: Calling OnModelAssociationDone"; | 
| 257     ModelAssociationDone(IDLE); | 250     ModelAssociationDone(IDLE); | 
| 258   } else { | 251   } else { | 
| 259     DCHECK(associating_types_.Empty()); | 252     DCHECK(associating_types_.Empty()); | 
| 260     DCHECK(requested_types_.Empty()); | 253     DCHECK(requested_types_.Empty()); | 
| 261     state_ = IDLE; | 254     state_ = IDLE; | 
| 262   } | 255   } | 
| 263 } | 256 } | 
| 264 | 257 | 
| 265 void ModelAssociationManager::ModelLoadCallback( | 258 void ModelAssociationManager::ModelLoadCallback(ModelType type, | 
| 266     syncer::ModelType type, | 259                                                 const SyncError& error) { | 
| 267     const syncer::SyncError& error) { |  | 
| 268   DVLOG(1) << "ModelAssociationManager: ModelLoadCallback for " | 260   DVLOG(1) << "ModelAssociationManager: ModelLoadCallback for " | 
| 269            << syncer::ModelTypeToString(type); | 261            << ModelTypeToString(type); | 
| 270 | 262 | 
| 271   if (error.IsSet()) { | 263   if (error.IsSet()) { | 
| 272     syncer::SyncMergeResult local_merge_result(type); | 264     SyncMergeResult local_merge_result(type); | 
| 273     local_merge_result.set_error(error); | 265     local_merge_result.set_error(error); | 
| 274     TypeStartCallback(type, base::TimeTicks::Now(), | 266     TypeStartCallback(type, base::TimeTicks::Now(), | 
| 275                       DataTypeController::ASSOCIATION_FAILED, | 267                       DataTypeController::ASSOCIATION_FAILED, | 
| 276                       local_merge_result, syncer::SyncMergeResult(type)); | 268                       local_merge_result, SyncMergeResult(type)); | 
| 277     return; | 269     return; | 
| 278   } | 270   } | 
| 279 | 271 | 
| 280   // This happens when slow loading type is disabled by new configuration. | 272   // This happens when slow loading type is disabled by new configuration. | 
| 281   if (!desired_types_.Has(type)) | 273   if (!desired_types_.Has(type)) | 
| 282     return; | 274     return; | 
| 283 | 275 | 
| 284   DCHECK(!loaded_types_.Has(type)); | 276   DCHECK(!loaded_types_.Has(type)); | 
| 285   loaded_types_.Put(type); | 277   loaded_types_.Put(type); | 
| 286   NotifyDelegateIfReadyForConfigure(); | 278   NotifyDelegateIfReadyForConfigure(); | 
| 287   if (associating_types_.Has(type)) { | 279   if (associating_types_.Has(type)) { | 
| 288     DataTypeController* dtc = controllers_->find(type)->second.get(); | 280     DataTypeController* dtc = controllers_->find(type)->second.get(); | 
| 289     // If initial sync was done for this datatype then | 281     // If initial sync was done for this datatype then | 
| 290     // NotifyDelegateIfReadyForConfigure possibly already triggered model | 282     // NotifyDelegateIfReadyForConfigure possibly already triggered model | 
| 291     // association and StartAssociating was already called for this type. To | 283     // association and StartAssociating was already called for this type. To | 
| 292     // ensure StartAssociating is called only once only make a call if state is | 284     // ensure StartAssociating is called only once only make a call if state is | 
| 293     // MODEL_LOADED. | 285     // MODEL_LOADED. | 
| 294     // TODO(pavely): Add test for this scenario in DataTypeManagerImpl | 286     // TODO(pavely): Add test for this scenario in DataTypeManagerImpl | 
| 295     // unittests. | 287     // unittests. | 
| 296     if (dtc->state() == DataTypeController::MODEL_LOADED) { | 288     if (dtc->state() == DataTypeController::MODEL_LOADED) { | 
| 297       dtc->StartAssociating(base::Bind( | 289       dtc->StartAssociating(base::Bind( | 
| 298           &ModelAssociationManager::TypeStartCallback, | 290           &ModelAssociationManager::TypeStartCallback, | 
| 299           weak_ptr_factory_.GetWeakPtr(), type, base::TimeTicks::Now())); | 291           weak_ptr_factory_.GetWeakPtr(), type, base::TimeTicks::Now())); | 
| 300     } | 292     } | 
| 301   } | 293   } | 
| 302 } | 294 } | 
| 303 | 295 | 
| 304 void ModelAssociationManager::TypeStartCallback( | 296 void ModelAssociationManager::TypeStartCallback( | 
| 305     syncer::ModelType type, | 297     ModelType type, | 
| 306     base::TimeTicks type_start_time, | 298     base::TimeTicks type_start_time, | 
| 307     DataTypeController::ConfigureResult start_result, | 299     DataTypeController::ConfigureResult start_result, | 
| 308     const syncer::SyncMergeResult& local_merge_result, | 300     const SyncMergeResult& local_merge_result, | 
| 309     const syncer::SyncMergeResult& syncer_merge_result) { | 301     const SyncMergeResult& syncer_merge_result) { | 
| 310   if (desired_types_.Has(type) && | 302   if (desired_types_.Has(type) && | 
| 311       !DataTypeController::IsSuccessfulResult(start_result)) { | 303       !DataTypeController::IsSuccessfulResult(start_result)) { | 
| 312     DVLOG(1) << "ModelAssociationManager: Type encountered an error."; | 304     DVLOG(1) << "ModelAssociationManager: Type encountered an error."; | 
| 313     desired_types_.Remove(type); | 305     desired_types_.Remove(type); | 
| 314     DataTypeController* dtc = controllers_->find(type)->second.get(); | 306     DataTypeController* dtc = controllers_->find(type)->second.get(); | 
| 315     StopDatatype(local_merge_result.error(), dtc); | 307     StopDatatype(local_merge_result.error(), dtc); | 
| 316     NotifyDelegateIfReadyForConfigure(); | 308     NotifyDelegateIfReadyForConfigure(); | 
| 317 | 309 | 
| 318     // Update configuration result. | 310     // Update configuration result. | 
| 319     if (start_result == DataTypeController::UNRECOVERABLE_ERROR) | 311     if (start_result == DataTypeController::UNRECOVERABLE_ERROR) | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 336 | 328 | 
| 337   if (state_ != ASSOCIATING) | 329   if (state_ != ASSOCIATING) | 
| 338     return; | 330     return; | 
| 339 | 331 | 
| 340   TRACE_EVENT_ASYNC_END1("sync", "ModelAssociation", | 332   TRACE_EVENT_ASYNC_END1("sync", "ModelAssociation", | 
| 341                          controllers_->find(type)->second.get(), "DataType", | 333                          controllers_->find(type)->second.get(), "DataType", | 
| 342                          ModelTypeToString(type)); | 334                          ModelTypeToString(type)); | 
| 343 | 335 | 
| 344   // Track the merge results if we succeeded or an association failure | 336   // Track the merge results if we succeeded or an association failure | 
| 345   // occurred. | 337   // occurred. | 
| 346   if (syncer::ProtocolTypes().Has(type)) { | 338   if (ProtocolTypes().Has(type)) { | 
| 347     base::TimeDelta association_wait_time = | 339     base::TimeDelta association_wait_time = | 
| 348         std::max(base::TimeDelta(), type_start_time - association_start_time_); | 340         std::max(base::TimeDelta(), type_start_time - association_start_time_); | 
| 349     base::TimeDelta association_time = base::TimeTicks::Now() - type_start_time; | 341     base::TimeDelta association_time = base::TimeTicks::Now() - type_start_time; | 
| 350     syncer::DataTypeAssociationStats stats = | 342     DataTypeAssociationStats stats = BuildAssociationStatsFromMergeResults( | 
| 351         BuildAssociationStatsFromMergeResults( | 343         local_merge_result, syncer_merge_result, association_wait_time, | 
| 352             local_merge_result, syncer_merge_result, association_wait_time, | 344         association_time); | 
| 353             association_time); |  | 
| 354     delegate_->OnSingleDataTypeAssociationDone(type, stats); | 345     delegate_->OnSingleDataTypeAssociationDone(type, stats); | 
| 355   } | 346   } | 
| 356 | 347 | 
| 357   associating_types_.Remove(type); | 348   associating_types_.Remove(type); | 
| 358 | 349 | 
| 359   if (associating_types_.Empty()) | 350   if (associating_types_.Empty()) | 
| 360     ModelAssociationDone(INITIALIZED); | 351     ModelAssociationDone(INITIALIZED); | 
| 361 } | 352 } | 
| 362 | 353 | 
| 363 void ModelAssociationManager::ModelAssociationDone(State new_state) { | 354 void ModelAssociationManager::ModelAssociationDone(State new_state) { | 
| 364   DCHECK_NE(IDLE, state_); | 355   DCHECK_NE(IDLE, state_); | 
| 365 | 356 | 
| 366   if (state_ == INITIALIZED) { | 357   if (state_ == INITIALIZED) { | 
| 367     // No associations are currently happening. Just reset the state. | 358     // No associations are currently happening. Just reset the state. | 
| 368     state_ = new_state; | 359     state_ = new_state; | 
| 369     return; | 360     return; | 
| 370   } | 361   } | 
| 371 | 362 | 
| 372   DVLOG(1) << "Model association complete for " | 363   DVLOG(1) << "Model association complete for " | 
| 373            << syncer::ModelTypeSetToString(requested_types_); | 364            << ModelTypeSetToString(requested_types_); | 
| 374 | 365 | 
| 375   timer_.Stop(); | 366   timer_.Stop(); | 
| 376 | 367 | 
| 377   // Treat any unfinished types as having errors. | 368   // Treat any unfinished types as having errors. | 
| 378   desired_types_.RemoveAll(associating_types_); | 369   desired_types_.RemoveAll(associating_types_); | 
| 379   for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); | 370   for (DataTypeController::TypeMap::const_iterator it = controllers_->begin(); | 
| 380        it != controllers_->end(); ++it) { | 371        it != controllers_->end(); ++it) { | 
| 381     DataTypeController* dtc = (*it).second.get(); | 372     DataTypeController* dtc = (*it).second.get(); | 
| 382     if (associating_types_.Has(dtc->type()) && | 373     if (associating_types_.Has(dtc->type()) && | 
| 383         dtc->state() != DataTypeController::NOT_RUNNING) { | 374         dtc->state() != DataTypeController::NOT_RUNNING) { | 
| 384       UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureFailed", | 375       UMA_HISTOGRAM_ENUMERATION("Sync.ConfigureFailed", | 
| 385                                 ModelTypeToHistogramInt(dtc->type()), | 376                                 ModelTypeToHistogramInt(dtc->type()), | 
| 386                                 syncer::MODEL_TYPE_COUNT); | 377                                 MODEL_TYPE_COUNT); | 
| 387       StopDatatype( | 378       StopDatatype(SyncError(FROM_HERE, SyncError::DATATYPE_ERROR, | 
| 388           syncer::SyncError(FROM_HERE, syncer::SyncError::DATATYPE_ERROR, | 379                              "Association timed out.", dtc->type()), | 
| 389                             "Association timed out.", dtc->type()), | 380                    dtc); | 
| 390           dtc); |  | 
| 391     } | 381     } | 
| 392   } | 382   } | 
| 393 | 383 | 
| 394   DataTypeManager::ConfigureResult result(configure_status_, requested_types_); | 384   DataTypeManager::ConfigureResult result(configure_status_, requested_types_); | 
| 395 | 385 | 
| 396   // Need to reset state before invoking delegate in order to avoid re-entrancy | 386   // Need to reset state before invoking delegate in order to avoid re-entrancy | 
| 397   // issues (delegate may trigger a reconfiguration). | 387   // issues (delegate may trigger a reconfiguration). | 
| 398   associating_types_.Clear(); | 388   associating_types_.Clear(); | 
| 399   requested_types_.Clear(); | 389   requested_types_.Clear(); | 
| 400   state_ = new_state; | 390   state_ = new_state; | 
| 401 | 391 | 
| 402   delegate_->OnModelAssociationDone(result); | 392   delegate_->OnModelAssociationDone(result); | 
| 403 } | 393 } | 
| 404 | 394 | 
| 405 base::OneShotTimer* ModelAssociationManager::GetTimerForTesting() { | 395 base::OneShotTimer* ModelAssociationManager::GetTimerForTesting() { | 
| 406   return &timer_; | 396   return &timer_; | 
| 407 } | 397 } | 
| 408 | 398 | 
| 409 void ModelAssociationManager::NotifyDelegateIfReadyForConfigure() { | 399 void ModelAssociationManager::NotifyDelegateIfReadyForConfigure() { | 
| 410   if (notified_about_ready_for_configure_) | 400   if (notified_about_ready_for_configure_) | 
| 411     return; | 401     return; | 
| 412   for (const auto& type_dtc_pair : *controllers_) { | 402   for (const auto& type_dtc_pair : *controllers_) { | 
| 413     syncer::ModelType type = type_dtc_pair.first; | 403     ModelType type = type_dtc_pair.first; | 
| 414     if (!desired_types_.Has(type)) | 404     if (!desired_types_.Has(type)) | 
| 415       continue; | 405       continue; | 
| 416     DataTypeController* dtc = type_dtc_pair.second.get(); | 406     DataTypeController* dtc = type_dtc_pair.second.get(); | 
| 417     if (dtc->ShouldLoadModelBeforeConfigure() && !loaded_types_.Has(type)) { | 407     if (dtc->ShouldLoadModelBeforeConfigure() && !loaded_types_.Has(type)) { | 
| 418       // At least one type is not ready. | 408       // At least one type is not ready. | 
| 419       return; | 409       return; | 
| 420     } | 410     } | 
| 421   } | 411   } | 
| 422 | 412 | 
| 423   notified_about_ready_for_configure_ = true; | 413   notified_about_ready_for_configure_ = true; | 
| 424   delegate_->OnAllDataTypesReadyForConfigure(); | 414   delegate_->OnAllDataTypesReadyForConfigure(); | 
| 425 } | 415 } | 
| 426 | 416 | 
| 427 }  // namespace sync_driver | 417 }  // namespace syncer | 
| OLD | NEW | 
|---|