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