| OLD | NEW |
| (Empty) |
| 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 #include "sync/engine/syncer.h" | |
| 6 | |
| 7 #include <memory> | |
| 8 | |
| 9 #include "base/auto_reset.h" | |
| 10 #include "base/location.h" | |
| 11 #include "base/logging.h" | |
| 12 #include "base/message_loop/message_loop.h" | |
| 13 #include "base/time/time.h" | |
| 14 #include "base/trace_event/trace_event.h" | |
| 15 #include "build/build_config.h" | |
| 16 #include "sync/engine/apply_control_data_updates.h" | |
| 17 #include "sync/engine/clear_server_data.h" | |
| 18 #include "sync/engine/commit.h" | |
| 19 #include "sync/engine/commit_processor.h" | |
| 20 #include "sync/engine/conflict_resolver.h" | |
| 21 #include "sync/engine/get_updates_delegate.h" | |
| 22 #include "sync/engine/get_updates_processor.h" | |
| 23 #include "sync/engine/net/server_connection_manager.h" | |
| 24 #include "sync/engine/syncer_types.h" | |
| 25 #include "sync/internal_api/public/base/cancelation_signal.h" | |
| 26 #include "sync/internal_api/public/base/unique_position.h" | |
| 27 #include "sync/internal_api/public/util/syncer_error.h" | |
| 28 #include "sync/sessions/nudge_tracker.h" | |
| 29 #include "sync/syncable/directory.h" | |
| 30 #include "sync/syncable/mutable_entry.h" | |
| 31 #include "sync/syncable/syncable-inl.h" | |
| 32 | |
| 33 using base::Time; | |
| 34 using base::TimeDelta; | |
| 35 using sync_pb::ClientCommand; | |
| 36 | |
| 37 namespace syncer { | |
| 38 | |
| 39 // TODO(akalin): We may want to propagate this switch up | |
| 40 // eventually. | |
| 41 #if defined(OS_ANDROID) || defined(OS_IOS) | |
| 42 static const bool kCreateMobileBookmarksFolder = true; | |
| 43 #else | |
| 44 static const bool kCreateMobileBookmarksFolder = false; | |
| 45 #endif | |
| 46 | |
| 47 using sessions::StatusController; | |
| 48 using sessions::SyncSession; | |
| 49 using sessions::NudgeTracker; | |
| 50 | |
| 51 Syncer::Syncer(syncer::CancelationSignal* cancelation_signal) | |
| 52 : cancelation_signal_(cancelation_signal), | |
| 53 is_syncing_(false) { | |
| 54 } | |
| 55 | |
| 56 Syncer::~Syncer() {} | |
| 57 | |
| 58 bool Syncer::ExitRequested() { | |
| 59 return cancelation_signal_->IsSignalled(); | |
| 60 } | |
| 61 | |
| 62 bool Syncer::IsSyncing() const { | |
| 63 return is_syncing_; | |
| 64 } | |
| 65 | |
| 66 bool Syncer::NormalSyncShare(ModelTypeSet request_types, | |
| 67 NudgeTracker* nudge_tracker, | |
| 68 SyncSession* session) { | |
| 69 base::AutoReset<bool> is_syncing(&is_syncing_, true); | |
| 70 HandleCycleBegin(session); | |
| 71 if (nudge_tracker->IsGetUpdatesRequired() || | |
| 72 session->context()->ShouldFetchUpdatesBeforeCommit()) { | |
| 73 VLOG(1) << "Downloading types " << ModelTypeSetToString(request_types); | |
| 74 NormalGetUpdatesDelegate normal_delegate(*nudge_tracker); | |
| 75 GetUpdatesProcessor get_updates_processor( | |
| 76 session->context()->model_type_registry()->update_handler_map(), | |
| 77 normal_delegate); | |
| 78 if (!DownloadAndApplyUpdates( | |
| 79 &request_types, | |
| 80 session, | |
| 81 &get_updates_processor, | |
| 82 kCreateMobileBookmarksFolder)) { | |
| 83 return HandleCycleEnd(session, nudge_tracker->GetLegacySource()); | |
| 84 } | |
| 85 } | |
| 86 | |
| 87 VLOG(1) << "Committing from types " << ModelTypeSetToString(request_types); | |
| 88 CommitProcessor commit_processor( | |
| 89 session->context()->model_type_registry()->commit_contributor_map()); | |
| 90 SyncerError commit_result = BuildAndPostCommits(request_types, nudge_tracker, | |
| 91 session, &commit_processor); | |
| 92 session->mutable_status_controller()->set_commit_result(commit_result); | |
| 93 | |
| 94 return HandleCycleEnd(session, nudge_tracker->GetLegacySource()); | |
| 95 } | |
| 96 | |
| 97 bool Syncer::ConfigureSyncShare( | |
| 98 ModelTypeSet request_types, | |
| 99 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source, | |
| 100 SyncSession* session) { | |
| 101 base::AutoReset<bool> is_syncing(&is_syncing_, true); | |
| 102 VLOG(1) << "Configuring types " << ModelTypeSetToString(request_types); | |
| 103 HandleCycleBegin(session); | |
| 104 ConfigureGetUpdatesDelegate configure_delegate(source); | |
| 105 GetUpdatesProcessor get_updates_processor( | |
| 106 session->context()->model_type_registry()->update_handler_map(), | |
| 107 configure_delegate); | |
| 108 DownloadAndApplyUpdates( | |
| 109 &request_types, | |
| 110 session, | |
| 111 &get_updates_processor, | |
| 112 kCreateMobileBookmarksFolder); | |
| 113 return HandleCycleEnd(session, source); | |
| 114 } | |
| 115 | |
| 116 bool Syncer::PollSyncShare(ModelTypeSet request_types, | |
| 117 SyncSession* session) { | |
| 118 base::AutoReset<bool> is_syncing(&is_syncing_, true); | |
| 119 VLOG(1) << "Polling types " << ModelTypeSetToString(request_types); | |
| 120 HandleCycleBegin(session); | |
| 121 PollGetUpdatesDelegate poll_delegate; | |
| 122 GetUpdatesProcessor get_updates_processor( | |
| 123 session->context()->model_type_registry()->update_handler_map(), | |
| 124 poll_delegate); | |
| 125 DownloadAndApplyUpdates( | |
| 126 &request_types, | |
| 127 session, | |
| 128 &get_updates_processor, | |
| 129 kCreateMobileBookmarksFolder); | |
| 130 return HandleCycleEnd(session, sync_pb::GetUpdatesCallerInfo::PERIODIC); | |
| 131 } | |
| 132 | |
| 133 bool Syncer::DownloadAndApplyUpdates( | |
| 134 ModelTypeSet* request_types, | |
| 135 SyncSession* session, | |
| 136 GetUpdatesProcessor* get_updates_processor, | |
| 137 bool create_mobile_bookmarks_folder) { | |
| 138 SyncerError download_result = UNSET; | |
| 139 do { | |
| 140 download_result = get_updates_processor->DownloadUpdates( | |
| 141 request_types, | |
| 142 session, | |
| 143 create_mobile_bookmarks_folder); | |
| 144 } while (download_result == SERVER_MORE_TO_DOWNLOAD); | |
| 145 | |
| 146 // Exit without applying if we're shutting down or an error was detected. | |
| 147 if (download_result != SYNCER_OK) | |
| 148 return false; | |
| 149 if (ExitRequested()) | |
| 150 return false; | |
| 151 | |
| 152 { | |
| 153 TRACE_EVENT0("sync", "ApplyUpdates"); | |
| 154 | |
| 155 // Control type updates always get applied first. | |
| 156 ApplyControlDataUpdates(session->context()->directory()); | |
| 157 | |
| 158 // Apply upates to the other types. May or may not involve cross-thread | |
| 159 // traffic, depending on the underlying update handlers and the GU type's | |
| 160 // delegate. | |
| 161 get_updates_processor->ApplyUpdates(*request_types, | |
| 162 session->mutable_status_controller()); | |
| 163 | |
| 164 session->context()->set_hierarchy_conflict_detected( | |
| 165 session->status_controller().num_hierarchy_conflicts() > 0); | |
| 166 session->SendEventNotification(SyncCycleEvent::STATUS_CHANGED); | |
| 167 } | |
| 168 | |
| 169 if (ExitRequested()) | |
| 170 return false; | |
| 171 return true; | |
| 172 } | |
| 173 | |
| 174 SyncerError Syncer::BuildAndPostCommits(ModelTypeSet requested_types, | |
| 175 sessions::NudgeTracker* nudge_tracker, | |
| 176 sessions::SyncSession* session, | |
| 177 CommitProcessor* commit_processor) { | |
| 178 // The ExitRequested() check is unnecessary, since we should start getting | |
| 179 // errors from the ServerConnectionManager if an exist has been requested. | |
| 180 // However, it doesn't hurt to check it anyway. | |
| 181 while (!ExitRequested()) { | |
| 182 std::unique_ptr<Commit> commit( | |
| 183 Commit::Init(requested_types, session->context()->GetEnabledTypes(), | |
| 184 session->context()->max_commit_batch_size(), | |
| 185 session->context()->account_name(), | |
| 186 session->context()->directory()->cache_guid(), | |
| 187 session->context()->cookie_jar_mismatch(), | |
| 188 session->context()->cookie_jar_empty(), commit_processor, | |
| 189 session->context()->extensions_activity())); | |
| 190 if (!commit) { | |
| 191 break; | |
| 192 } | |
| 193 | |
| 194 SyncerError error = commit->PostAndProcessResponse( | |
| 195 nudge_tracker, session, session->mutable_status_controller(), | |
| 196 session->context()->extensions_activity()); | |
| 197 commit->CleanUp(); | |
| 198 if (error != SYNCER_OK) { | |
| 199 return error; | |
| 200 } | |
| 201 } | |
| 202 | |
| 203 return SYNCER_OK; | |
| 204 } | |
| 205 | |
| 206 void Syncer::HandleCycleBegin(SyncSession* session) { | |
| 207 session->mutable_status_controller()->UpdateStartTime(); | |
| 208 session->SendEventNotification(SyncCycleEvent::SYNC_CYCLE_BEGIN); | |
| 209 } | |
| 210 | |
| 211 bool Syncer::HandleCycleEnd( | |
| 212 SyncSession* session, | |
| 213 sync_pb::GetUpdatesCallerInfo::GetUpdatesSource source) { | |
| 214 if (!ExitRequested()) { | |
| 215 session->SendSyncCycleEndEventNotification(source); | |
| 216 | |
| 217 bool success = !sessions::HasSyncerError( | |
| 218 session->status_controller().model_neutral_state()); | |
| 219 if (success && source == sync_pb::GetUpdatesCallerInfo::PERIODIC) | |
| 220 session->mutable_status_controller()->UpdatePollTime(); | |
| 221 return success; | |
| 222 } else { | |
| 223 return false; | |
| 224 } | |
| 225 } | |
| 226 | |
| 227 bool Syncer::PostClearServerData(SyncSession* session) { | |
| 228 DCHECK(session); | |
| 229 ClearServerData clear_server_data(session->context()->account_name()); | |
| 230 const SyncerError post_result = clear_server_data.SendRequest(session); | |
| 231 return post_result == SYNCER_OK; | |
| 232 } | |
| 233 | |
| 234 } // namespace syncer | |
| OLD | NEW |