Cast: Stop logging kVideoFrameSentToEncoder and rename a couple events.
[chromium-blink-merge.git] / chrome / browser / sync_file_system / drive_backend_v1 / remote_sync_delegate.cc
blob896fa373724651c14f75c7af22f0bb588d3c5787
1 // Copyright 2013 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 "chrome/browser/sync_file_system/drive_backend_v1/remote_sync_delegate.h"
7 #include "base/file_util.h"
8 #include "chrome/browser/sync_file_system/drive_backend_v1/remote_sync_operation_resolver.h"
9 #include "chrome/browser/sync_file_system/logger.h"
10 #include "chrome/browser/sync_file_system/remote_change_processor.h"
11 #include "chrome/browser/sync_file_system/syncable_file_system_util.h"
13 using fileapi::FileSystemURL;
15 namespace {
17 void EmptyStatusCallback(sync_file_system::SyncStatusCode status) {}
19 } // namespace
21 namespace sync_file_system {
22 namespace drive_backend {
24 RemoteSyncDelegate::RemoteSyncDelegate(
25 DriveFileSyncService* sync_service,
26 const RemoteChange& remote_change)
27 : sync_service_(sync_service),
28 remote_change_(remote_change),
29 sync_action_(SYNC_ACTION_NONE),
30 metadata_updated_(false),
31 clear_local_changes_(true) {
34 RemoteSyncDelegate::~RemoteSyncDelegate() {}
36 void RemoteSyncDelegate::Run(const SyncStatusCallback& callback) {
37 util::Log(logging::LOG_VERBOSE, FROM_HERE,
38 "ProcessRemoteChange for %s change:%s",
39 url().DebugString().c_str(),
40 remote_file_change().DebugString().c_str());
42 remote_change_processor()->PrepareForProcessRemoteChange(
43 url(),
44 base::Bind(&RemoteSyncDelegate::DidPrepareForProcessRemoteChange,
45 AsWeakPtr(), callback));
48 void RemoteSyncDelegate::DidPrepareForProcessRemoteChange(
49 const SyncStatusCallback& callback,
50 SyncStatusCode status,
51 const SyncFileMetadata& metadata,
52 const FileChangeList& local_changes) {
53 if (status != SYNC_STATUS_OK) {
54 AbortSync(callback, status);
55 return;
58 local_metadata_ = metadata;
59 status = metadata_store()->ReadEntry(url(), &drive_metadata_);
60 DCHECK(status == SYNC_STATUS_OK || status == SYNC_DATABASE_ERROR_NOT_FOUND);
62 bool missing_db_entry = (status != SYNC_STATUS_OK);
63 if (missing_db_entry) {
64 drive_metadata_.set_resource_id(remote_change_.resource_id);
65 drive_metadata_.set_md5_checksum(std::string());
66 drive_metadata_.set_conflicted(false);
67 drive_metadata_.set_to_be_fetched(false);
69 bool missing_local_file = (metadata.file_type == SYNC_FILE_TYPE_UNKNOWN);
71 if (drive_metadata_.resource_id().empty()) {
72 // This (missing_db_entry is false but resource_id is empty) could
73 // happen when the remote file gets deleted (this clears resource_id
74 // in drive_metadata) but then a file is added with the same name.
75 drive_metadata_.set_resource_id(remote_change_.resource_id);
78 SyncOperationType operation =
79 RemoteSyncOperationResolver::Resolve(remote_file_change(),
80 local_changes,
81 local_metadata_.file_type,
82 drive_metadata_.conflicted());
84 util::Log(logging::LOG_VERBOSE, FROM_HERE,
85 "ProcessRemoteChange for %s %s%sremote_change: %s ==> %s",
86 url().DebugString().c_str(),
87 drive_metadata_.conflicted() ? " (conflicted)" : " ",
88 missing_local_file ? " (missing local file)" : " ",
89 remote_file_change().DebugString().c_str(),
90 SyncOperationTypeToString(operation));
91 DCHECK_NE(SYNC_OPERATION_FAIL, operation);
93 switch (operation) {
94 case SYNC_OPERATION_ADD_FILE:
95 case SYNC_OPERATION_ADD_DIRECTORY:
96 sync_action_ = SYNC_ACTION_ADDED;
97 break;
98 case SYNC_OPERATION_UPDATE_FILE:
99 sync_action_ = SYNC_ACTION_UPDATED;
100 break;
101 case SYNC_OPERATION_DELETE:
102 sync_action_ = SYNC_ACTION_DELETED;
103 break;
104 case SYNC_OPERATION_NONE:
105 case SYNC_OPERATION_DELETE_METADATA:
106 sync_action_ = SYNC_ACTION_NONE;
107 break;
108 default:
109 break;
112 switch (operation) {
113 case SYNC_OPERATION_ADD_FILE:
114 case SYNC_OPERATION_UPDATE_FILE:
115 DownloadFile(callback);
116 return;
117 case SYNC_OPERATION_ADD_DIRECTORY:
118 case SYNC_OPERATION_DELETE:
119 ApplyRemoteChange(callback);
120 return;
121 case SYNC_OPERATION_NONE:
122 CompleteSync(callback, SYNC_STATUS_OK);
123 return;
124 case SYNC_OPERATION_CONFLICT:
125 HandleConflict(callback, remote_file_change().file_type());
126 return;
127 case SYNC_OPERATION_RESOLVE_TO_LOCAL:
128 ResolveToLocal(callback);
129 return;
130 case SYNC_OPERATION_RESOLVE_TO_REMOTE:
131 ResolveToRemote(callback);
132 return;
133 case SYNC_OPERATION_DELETE_METADATA:
134 if (missing_db_entry)
135 CompleteSync(callback, SYNC_STATUS_OK);
136 else
137 DeleteMetadata(callback);
138 return;
139 case SYNC_OPERATION_FAIL:
140 AbortSync(callback, SYNC_STATUS_FAILED);
141 return;
143 NOTREACHED();
144 AbortSync(callback, SYNC_STATUS_FAILED);
147 void RemoteSyncDelegate::ApplyRemoteChange(const SyncStatusCallback& callback) {
148 remote_change_processor()->ApplyRemoteChange(
149 remote_file_change(), temporary_file_.path(), url(),
150 base::Bind(&RemoteSyncDelegate::DidApplyRemoteChange, AsWeakPtr(),
151 callback));
154 void RemoteSyncDelegate::DidApplyRemoteChange(
155 const SyncStatusCallback& callback,
156 SyncStatusCode status) {
157 if (status != SYNC_STATUS_OK) {
158 AbortSync(callback, status);
159 return;
162 if (remote_file_change().IsDelete()) {
163 DeleteMetadata(callback);
164 return;
167 drive_metadata_.set_resource_id(remote_change_.resource_id);
168 drive_metadata_.set_conflicted(false);
169 if (remote_file_change().IsFile()) {
170 drive_metadata_.set_type(DriveMetadata::RESOURCE_TYPE_FILE);
171 } else {
172 DCHECK(IsSyncFSDirectoryOperationEnabled());
173 drive_metadata_.set_type(DriveMetadata::RESOURCE_TYPE_FOLDER);
176 metadata_store()->UpdateEntry(
177 url(), drive_metadata_,
178 base::Bind(&RemoteSyncDelegate::CompleteSync,
179 AsWeakPtr(), callback));
182 void RemoteSyncDelegate::DeleteMetadata(const SyncStatusCallback& callback) {
183 metadata_store()->DeleteEntry(
184 url(),
185 base::Bind(&RemoteSyncDelegate::CompleteSync, AsWeakPtr(), callback));
188 void RemoteSyncDelegate::DownloadFile(const SyncStatusCallback& callback) {
189 // We should not use the md5 in metadata for FETCH type to avoid the download
190 // finishes due to NOT_MODIFIED.
191 std::string md5_checksum;
192 if (!drive_metadata_.to_be_fetched())
193 md5_checksum = drive_metadata_.md5_checksum();
195 api_util()->DownloadFile(
196 remote_change_.resource_id,
197 md5_checksum,
198 base::Bind(&RemoteSyncDelegate::DidDownloadFile,
199 AsWeakPtr(),
200 callback));
203 void RemoteSyncDelegate::DidDownloadFile(
204 const SyncStatusCallback& callback,
205 google_apis::GDataErrorCode error,
206 const std::string& md5_checksum,
207 int64 file_size,
208 const base::Time& updated_time,
209 webkit_blob::ScopedFile downloaded_file) {
210 if (error == google_apis::HTTP_NOT_MODIFIED) {
211 sync_action_ = SYNC_ACTION_NONE;
212 DidApplyRemoteChange(callback, SYNC_STATUS_OK);
213 return;
216 // File may be deleted. If this was for new file it's ok, if this was
217 // for existing file we'll process the delete change later.
218 if (error == google_apis::HTTP_NOT_FOUND) {
219 sync_action_ = SYNC_ACTION_NONE;
220 DidApplyRemoteChange(callback, SYNC_STATUS_OK);
221 return;
224 SyncStatusCode status = GDataErrorCodeToSyncStatusCodeWrapper(error);
225 if (status != SYNC_STATUS_OK) {
226 AbortSync(callback, status);
227 return;
230 temporary_file_ = downloaded_file.Pass();
231 drive_metadata_.set_md5_checksum(md5_checksum);
232 remote_change_processor()->ApplyRemoteChange(
233 remote_file_change(), temporary_file_.path(), url(),
234 base::Bind(&RemoteSyncDelegate::DidApplyRemoteChange,
235 AsWeakPtr(), callback));
238 void RemoteSyncDelegate::HandleConflict(
239 const SyncStatusCallback& callback,
240 SyncFileType remote_file_type) {
241 ConflictResolution resolution = conflict_resolution_resolver()->Resolve(
242 local_metadata_.file_type,
243 local_metadata_.last_modified,
244 remote_file_type,
245 remote_change_.updated_time);
247 switch (resolution) {
248 case CONFLICT_RESOLUTION_LOCAL_WIN:
249 HandleLocalWin(callback);
250 return;
251 case CONFLICT_RESOLUTION_REMOTE_WIN:
252 HandleRemoteWin(callback, remote_file_type);
253 return;
254 case CONFLICT_RESOLUTION_MARK_CONFLICT:
255 HandleManualResolutionCase(callback);
256 return;
257 case CONFLICT_RESOLUTION_UNKNOWN:
258 // Get remote file time and call this method again.
259 api_util()->GetResourceEntry(
260 remote_change_.resource_id,
261 base::Bind(
262 &RemoteSyncDelegate::DidGetEntryForConflictResolution,
263 AsWeakPtr(), callback));
264 return;
266 NOTREACHED();
267 AbortSync(callback, SYNC_STATUS_FAILED);
270 void RemoteSyncDelegate::HandleLocalWin(
271 const SyncStatusCallback& callback) {
272 util::Log(logging::LOG_VERBOSE, FROM_HERE,
273 "Resolving conflict for remote sync: %s: LOCAL WIN",
274 url().DebugString().c_str());
275 ResolveToLocal(callback);
278 void RemoteSyncDelegate::HandleRemoteWin(
279 const SyncStatusCallback& callback,
280 SyncFileType remote_file_type) {
281 // Make sure we reset the conflict flag and start over the remote sync
282 // with empty local changes.
283 util::Log(logging::LOG_VERBOSE, FROM_HERE,
284 "Resolving conflict for remote sync: %s: REMOTE WIN",
285 url().DebugString().c_str());
287 drive_metadata_.set_conflicted(false);
288 drive_metadata_.set_to_be_fetched(false);
289 drive_metadata_.set_type(
290 DriveFileSyncService::SyncFileTypeToDriveMetadataResourceType(
291 remote_file_type));
292 metadata_store()->UpdateEntry(
293 url(), drive_metadata_,
294 base::Bind(&RemoteSyncDelegate::StartOver, AsWeakPtr(), callback));
297 void RemoteSyncDelegate::HandleManualResolutionCase(
298 const SyncStatusCallback& callback) {
299 sync_action_ = SYNC_ACTION_NONE;
300 sync_service_->MarkConflict(
301 url(), &drive_metadata_,
302 base::Bind(&RemoteSyncDelegate::CompleteSync, AsWeakPtr(), callback));
305 void RemoteSyncDelegate::DidGetEntryForConflictResolution(
306 const SyncStatusCallback& callback,
307 google_apis::GDataErrorCode error,
308 scoped_ptr<google_apis::ResourceEntry> entry) {
309 SyncStatusCode status = GDataErrorCodeToSyncStatusCodeWrapper(error);
310 if (status != SYNC_STATUS_OK || entry->updated_time().is_null()) {
311 HandleLocalWin(callback);
312 return;
315 SyncFileType file_type = SYNC_FILE_TYPE_UNKNOWN;
316 if (entry->is_file())
317 file_type = SYNC_FILE_TYPE_FILE;
318 if (entry->is_folder())
319 file_type = SYNC_FILE_TYPE_DIRECTORY;
321 remote_change_.updated_time = entry->updated_time();
322 HandleConflict(callback, file_type);
325 void RemoteSyncDelegate::ResolveToLocal(
326 const SyncStatusCallback& callback) {
327 sync_action_ = SYNC_ACTION_NONE;
328 clear_local_changes_ = false;
330 // Re-add a fake local change to resolve it later in next LocalSync.
331 remote_change_processor()->RecordFakeLocalChange(
332 url(),
333 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
334 local_metadata_.file_type),
335 base::Bind(&RemoteSyncDelegate::DidResolveToLocal,
336 AsWeakPtr(), callback));
339 void RemoteSyncDelegate::DidResolveToLocal(
340 const SyncStatusCallback& callback,
341 SyncStatusCode status) {
342 if (status != SYNC_STATUS_OK) {
343 DCHECK_NE(SYNC_STATUS_HAS_CONFLICT, status);
344 AbortSync(callback, status);
345 return;
348 if (remote_file_change().IsDelete()) {
349 metadata_store()->DeleteEntry(
350 url(),
351 base::Bind(&RemoteSyncDelegate::CompleteSync,
352 AsWeakPtr(), callback));
353 } else {
354 DCHECK(!remote_change_.resource_id.empty());
355 drive_metadata_.set_resource_id(remote_change_.resource_id);
356 drive_metadata_.set_conflicted(false);
357 drive_metadata_.set_to_be_fetched(false);
358 drive_metadata_.set_md5_checksum(std::string());
359 metadata_store()->UpdateEntry(
360 url(), drive_metadata_,
361 base::Bind(&RemoteSyncDelegate::CompleteSync,
362 AsWeakPtr(), callback));
366 void RemoteSyncDelegate::ResolveToRemote(
367 const SyncStatusCallback& callback) {
368 drive_metadata_.set_conflicted(false);
369 drive_metadata_.set_to_be_fetched(true);
370 metadata_store()->UpdateEntry(
371 url(), drive_metadata_,
372 base::Bind(&RemoteSyncDelegate::DidResolveToRemote,
373 AsWeakPtr(), callback));
376 void RemoteSyncDelegate::DidResolveToRemote(
377 const SyncStatusCallback& callback,
378 SyncStatusCode status) {
379 if (status != SYNC_STATUS_OK) {
380 AbortSync(callback, status);
381 return;
384 sync_action_ = SYNC_ACTION_ADDED;
385 if (remote_file_change().file_type() == SYNC_FILE_TYPE_FILE) {
386 DownloadFile(callback);
387 return;
390 // ApplyRemoteChange should replace any existing local file or
391 // directory with remote_change_.
392 ApplyRemoteChange(callback);
395 void RemoteSyncDelegate::StartOver(
396 const SyncStatusCallback& callback,
397 SyncStatusCode status) {
398 DidPrepareForProcessRemoteChange(
399 callback, status, local_metadata_, FileChangeList());
402 void RemoteSyncDelegate::CompleteSync(
403 const SyncStatusCallback& callback,
404 SyncStatusCode status) {
405 if (status != SYNC_STATUS_OK) {
406 AbortSync(callback, status);
407 return;
410 sync_service_->RemoveRemoteChange(url());
412 if (drive_metadata_.to_be_fetched()) {
413 // Clear |to_be_fetched| flag since we completed fetching the remote change
414 // and applying it to the local file.
415 DCHECK(!drive_metadata_.conflicted());
416 drive_metadata_.set_conflicted(false);
417 drive_metadata_.set_to_be_fetched(false);
418 metadata_store()->UpdateEntry(url(), drive_metadata_,
419 base::Bind(&EmptyStatusCallback));
422 if (remote_change_.changestamp > 0) {
423 DCHECK(metadata_store()->IsIncrementalSyncOrigin(url().origin()));
424 metadata_store()->SetLargestChangeStamp(
425 remote_change_.changestamp,
426 base::Bind(&RemoteSyncDelegate::DidFinish, AsWeakPtr(), callback));
427 return;
430 if (drive_metadata_.conflicted())
431 status = SYNC_STATUS_HAS_CONFLICT;
433 DidFinish(callback, status);
436 void RemoteSyncDelegate::AbortSync(
437 const SyncStatusCallback& callback,
438 SyncStatusCode status) {
439 clear_local_changes_ = false;
440 DidFinish(callback, status);
443 void RemoteSyncDelegate::DidFinish(
444 const SyncStatusCallback& callback,
445 SyncStatusCode status) {
446 remote_change_processor()->FinalizeRemoteSync(
447 url(), clear_local_changes_,
448 base::Bind(&RemoteSyncDelegate::DispatchCallbackAfterDidFinish,
449 AsWeakPtr(), callback, status));
452 void RemoteSyncDelegate::DispatchCallbackAfterDidFinish(
453 const SyncStatusCallback& callback,
454 SyncStatusCode status) {
455 if (status == SYNC_STATUS_OK && sync_action_ != SYNC_ACTION_NONE) {
456 sync_service_->NotifyObserversFileStatusChanged(
457 url(),
458 SYNC_FILE_STATUS_SYNCED,
459 sync_action_,
460 SYNC_DIRECTION_REMOTE_TO_LOCAL);
463 callback.Run(status);
466 SyncStatusCode RemoteSyncDelegate::GDataErrorCodeToSyncStatusCodeWrapper(
467 google_apis::GDataErrorCode error) {
468 return sync_service_->GDataErrorCodeToSyncStatusCodeWrapper(error);
471 DriveMetadataStore* RemoteSyncDelegate::metadata_store() {
472 return sync_service_->metadata_store_.get();
475 APIUtilInterface* RemoteSyncDelegate::api_util() {
476 return sync_service_->api_util_.get();
479 RemoteChangeHandler* RemoteSyncDelegate::remote_change_handler() {
480 return &sync_service_->remote_change_handler_;
483 RemoteChangeProcessor* RemoteSyncDelegate::remote_change_processor() {
484 return sync_service_->remote_change_processor_;
487 ConflictResolutionResolver* RemoteSyncDelegate::conflict_resolution_resolver() {
488 return &sync_service_->conflict_resolution_resolver_;
491 } // namespace drive_backend
492 } // namespace sync_file_system