Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(93)

Side by Side Diff: chrome/browser/sync_file_system/drive_backend/remote_sync_delegate.cc

Issue 23787003: [SyncFS] Move SyncFS V1 files from drive_backend to drive_backend_v1 (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: move back metadata_db_migration_util* Created 7 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
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.
4
5 #include "chrome/browser/sync_file_system/drive_backend/remote_sync_delegate.h"
6
7 #include "base/file_util.h"
8 #include "chrome/browser/sync_file_system/drive_backend/remote_sync_operation_re solver.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"
12 #include "content/public/browser/browser_thread.h"
13
14 using fileapi::FileSystemURL;
15
16 namespace {
17
18 void EmptyStatusCallback(sync_file_system::SyncStatusCode status) {}
19
20 } // namespace
21
22 namespace sync_file_system {
23 namespace drive_backend {
24
25 RemoteSyncDelegate::RemoteSyncDelegate(
26 DriveFileSyncService* sync_service,
27 const RemoteChange& remote_change)
28 : sync_service_(sync_service),
29 remote_change_(remote_change),
30 sync_action_(SYNC_ACTION_NONE),
31 metadata_updated_(false),
32 clear_local_changes_(true) {
33 }
34
35 RemoteSyncDelegate::~RemoteSyncDelegate() {}
36
37 void RemoteSyncDelegate::Run(const SyncStatusCallback& callback) {
38 util::Log(logging::LOG_VERBOSE, FROM_HERE,
39 "ProcessRemoteChange for %s change:%s",
40 url().DebugString().c_str(),
41 remote_file_change().DebugString().c_str());
42
43 remote_change_processor()->PrepareForProcessRemoteChange(
44 url(),
45 base::Bind(&RemoteSyncDelegate::DidPrepareForProcessRemoteChange,
46 AsWeakPtr(), callback));
47 }
48
49 void RemoteSyncDelegate::DidPrepareForProcessRemoteChange(
50 const SyncStatusCallback& callback,
51 SyncStatusCode status,
52 const SyncFileMetadata& metadata,
53 const FileChangeList& local_changes) {
54 if (status != SYNC_STATUS_OK) {
55 AbortSync(callback, status);
56 return;
57 }
58
59 local_metadata_ = metadata;
60 status = metadata_store()->ReadEntry(url(), &drive_metadata_);
61 DCHECK(status == SYNC_STATUS_OK || status == SYNC_DATABASE_ERROR_NOT_FOUND);
62
63 bool missing_db_entry = (status != SYNC_STATUS_OK);
64 if (missing_db_entry) {
65 drive_metadata_.set_resource_id(remote_change_.resource_id);
66 drive_metadata_.set_md5_checksum(std::string());
67 drive_metadata_.set_conflicted(false);
68 drive_metadata_.set_to_be_fetched(false);
69 }
70 bool missing_local_file = (metadata.file_type == SYNC_FILE_TYPE_UNKNOWN);
71
72 if (drive_metadata_.resource_id().empty()) {
73 // This (missing_db_entry is false but resource_id is empty) could
74 // happen when the remote file gets deleted (this clears resource_id
75 // in drive_metadata) but then a file is added with the same name.
76 drive_metadata_.set_resource_id(remote_change_.resource_id);
77 }
78
79 SyncOperationType operation =
80 RemoteSyncOperationResolver::Resolve(remote_file_change(),
81 local_changes,
82 local_metadata_.file_type,
83 drive_metadata_.conflicted());
84
85 util::Log(logging::LOG_VERBOSE, FROM_HERE,
86 "ProcessRemoteChange for %s %s%sremote_change: %s ==> %s",
87 url().DebugString().c_str(),
88 drive_metadata_.conflicted() ? " (conflicted)" : " ",
89 missing_local_file ? " (missing local file)" : " ",
90 remote_file_change().DebugString().c_str(),
91 SyncOperationTypeToString(operation));
92 DCHECK_NE(SYNC_OPERATION_FAIL, operation);
93
94 switch (operation) {
95 case SYNC_OPERATION_ADD_FILE:
96 case SYNC_OPERATION_ADD_DIRECTORY:
97 sync_action_ = SYNC_ACTION_ADDED;
98 break;
99 case SYNC_OPERATION_UPDATE_FILE:
100 sync_action_ = SYNC_ACTION_UPDATED;
101 break;
102 case SYNC_OPERATION_DELETE:
103 sync_action_ = SYNC_ACTION_DELETED;
104 break;
105 case SYNC_OPERATION_NONE:
106 case SYNC_OPERATION_DELETE_METADATA:
107 sync_action_ = SYNC_ACTION_NONE;
108 break;
109 default:
110 break;
111 }
112
113 switch (operation) {
114 case SYNC_OPERATION_ADD_FILE:
115 case SYNC_OPERATION_UPDATE_FILE:
116 DownloadFile(callback);
117 return;
118 case SYNC_OPERATION_ADD_DIRECTORY:
119 case SYNC_OPERATION_DELETE:
120 ApplyRemoteChange(callback);
121 return;
122 case SYNC_OPERATION_NONE:
123 CompleteSync(callback, SYNC_STATUS_OK);
124 return;
125 case SYNC_OPERATION_CONFLICT:
126 HandleConflict(callback, remote_file_change().file_type());
127 return;
128 case SYNC_OPERATION_RESOLVE_TO_LOCAL:
129 ResolveToLocal(callback);
130 return;
131 case SYNC_OPERATION_RESOLVE_TO_REMOTE:
132 ResolveToRemote(callback);
133 return;
134 case SYNC_OPERATION_DELETE_METADATA:
135 if (missing_db_entry)
136 CompleteSync(callback, SYNC_STATUS_OK);
137 else
138 DeleteMetadata(callback);
139 return;
140 case SYNC_OPERATION_FAIL:
141 AbortSync(callback, SYNC_STATUS_FAILED);
142 return;
143 }
144 NOTREACHED();
145 AbortSync(callback, SYNC_STATUS_FAILED);
146 }
147
148 void RemoteSyncDelegate::ApplyRemoteChange(const SyncStatusCallback& callback) {
149 remote_change_processor()->ApplyRemoteChange(
150 remote_file_change(), temporary_file_.path(), url(),
151 base::Bind(&RemoteSyncDelegate::DidApplyRemoteChange, AsWeakPtr(),
152 callback));
153 }
154
155 void RemoteSyncDelegate::DidApplyRemoteChange(
156 const SyncStatusCallback& callback,
157 SyncStatusCode status) {
158 if (status != SYNC_STATUS_OK) {
159 AbortSync(callback, status);
160 return;
161 }
162
163 if (remote_file_change().IsDelete()) {
164 DeleteMetadata(callback);
165 return;
166 }
167
168 drive_metadata_.set_resource_id(remote_change_.resource_id);
169 drive_metadata_.set_conflicted(false);
170 if (remote_file_change().IsFile()) {
171 drive_metadata_.set_type(DriveMetadata::RESOURCE_TYPE_FILE);
172 } else {
173 DCHECK(IsSyncFSDirectoryOperationEnabled());
174 drive_metadata_.set_type(DriveMetadata::RESOURCE_TYPE_FOLDER);
175 }
176
177 metadata_store()->UpdateEntry(
178 url(), drive_metadata_,
179 base::Bind(&RemoteSyncDelegate::CompleteSync,
180 AsWeakPtr(), callback));
181 }
182
183 void RemoteSyncDelegate::DeleteMetadata(const SyncStatusCallback& callback) {
184 metadata_store()->DeleteEntry(
185 url(),
186 base::Bind(&RemoteSyncDelegate::CompleteSync, AsWeakPtr(), callback));
187 }
188
189 void RemoteSyncDelegate::DownloadFile(const SyncStatusCallback& callback) {
190 // We should not use the md5 in metadata for FETCH type to avoid the download
191 // finishes due to NOT_MODIFIED.
192 std::string md5_checksum;
193 if (!drive_metadata_.to_be_fetched())
194 md5_checksum = drive_metadata_.md5_checksum();
195
196 api_util()->DownloadFile(
197 remote_change_.resource_id,
198 md5_checksum,
199 base::Bind(&RemoteSyncDelegate::DidDownloadFile,
200 AsWeakPtr(),
201 callback));
202 }
203
204 void RemoteSyncDelegate::DidDownloadFile(
205 const SyncStatusCallback& callback,
206 google_apis::GDataErrorCode error,
207 const std::string& md5_checksum,
208 int64 file_size,
209 const base::Time& updated_time,
210 scoped_ptr<webkit_blob::ScopedFile> downloaded_file) {
211 if (error == google_apis::HTTP_NOT_MODIFIED) {
212 sync_action_ = SYNC_ACTION_NONE;
213 DidApplyRemoteChange(callback, SYNC_STATUS_OK);
214 return;
215 }
216
217 SyncStatusCode status = GDataErrorCodeToSyncStatusCodeWrapper(error);
218 if (status != SYNC_STATUS_OK) {
219 AbortSync(callback, status);
220 return;
221 }
222
223 temporary_file_ = downloaded_file->Pass();
224 drive_metadata_.set_md5_checksum(md5_checksum);
225 remote_change_processor()->ApplyRemoteChange(
226 remote_file_change(), temporary_file_.path(), url(),
227 base::Bind(&RemoteSyncDelegate::DidApplyRemoteChange,
228 AsWeakPtr(), callback));
229 }
230
231 void RemoteSyncDelegate::HandleConflict(
232 const SyncStatusCallback& callback,
233 SyncFileType remote_file_type) {
234 ConflictResolution resolution = conflict_resolution_resolver()->Resolve(
235 local_metadata_.file_type,
236 local_metadata_.last_modified,
237 remote_file_type,
238 remote_change_.updated_time);
239
240 switch (resolution) {
241 case CONFLICT_RESOLUTION_LOCAL_WIN:
242 HandleLocalWin(callback);
243 return;
244 case CONFLICT_RESOLUTION_REMOTE_WIN:
245 HandleRemoteWin(callback, remote_file_type);
246 return;
247 case CONFLICT_RESOLUTION_MARK_CONFLICT:
248 HandleManualResolutionCase(callback);
249 return;
250 case CONFLICT_RESOLUTION_UNKNOWN:
251 // Get remote file time and call this method again.
252 api_util()->GetResourceEntry(
253 remote_change_.resource_id,
254 base::Bind(
255 &RemoteSyncDelegate::DidGetEntryForConflictResolution,
256 AsWeakPtr(), callback));
257 return;
258 }
259 NOTREACHED();
260 AbortSync(callback, SYNC_STATUS_FAILED);
261 }
262
263 void RemoteSyncDelegate::HandleLocalWin(
264 const SyncStatusCallback& callback) {
265 util::Log(logging::LOG_VERBOSE, FROM_HERE,
266 "Resolving conflict for remote sync: %s: LOCAL WIN",
267 url().DebugString().c_str());
268 ResolveToLocal(callback);
269 }
270
271 void RemoteSyncDelegate::HandleRemoteWin(
272 const SyncStatusCallback& callback,
273 SyncFileType remote_file_type) {
274 // Make sure we reset the conflict flag and start over the remote sync
275 // with empty local changes.
276 util::Log(logging::LOG_VERBOSE, FROM_HERE,
277 "Resolving conflict for remote sync: %s: REMOTE WIN",
278 url().DebugString().c_str());
279
280 drive_metadata_.set_conflicted(false);
281 drive_metadata_.set_to_be_fetched(false);
282 drive_metadata_.set_type(
283 DriveFileSyncService::SyncFileTypeToDriveMetadataResourceType(
284 remote_file_type));
285 metadata_store()->UpdateEntry(
286 url(), drive_metadata_,
287 base::Bind(&RemoteSyncDelegate::StartOver, AsWeakPtr(), callback));
288 }
289
290 void RemoteSyncDelegate::HandleManualResolutionCase(
291 const SyncStatusCallback& callback) {
292 sync_action_ = SYNC_ACTION_NONE;
293 sync_service_->MarkConflict(
294 url(), &drive_metadata_,
295 base::Bind(&RemoteSyncDelegate::CompleteSync, AsWeakPtr(), callback));
296 }
297
298 void RemoteSyncDelegate::DidGetEntryForConflictResolution(
299 const SyncStatusCallback& callback,
300 google_apis::GDataErrorCode error,
301 scoped_ptr<google_apis::ResourceEntry> entry) {
302 SyncStatusCode status = GDataErrorCodeToSyncStatusCodeWrapper(error);
303 if (status != SYNC_STATUS_OK || entry->updated_time().is_null()) {
304 HandleLocalWin(callback);
305 return;
306 }
307
308 SyncFileType file_type = SYNC_FILE_TYPE_UNKNOWN;
309 if (entry->is_file())
310 file_type = SYNC_FILE_TYPE_FILE;
311 if (entry->is_folder())
312 file_type = SYNC_FILE_TYPE_DIRECTORY;
313
314 remote_change_.updated_time = entry->updated_time();
315 HandleConflict(callback, file_type);
316 }
317
318 void RemoteSyncDelegate::ResolveToLocal(
319 const SyncStatusCallback& callback) {
320 sync_action_ = SYNC_ACTION_NONE;
321 clear_local_changes_ = false;
322
323 // Re-add a fake local change to resolve it later in next LocalSync.
324 remote_change_processor()->RecordFakeLocalChange(
325 url(),
326 FileChange(FileChange::FILE_CHANGE_ADD_OR_UPDATE,
327 local_metadata_.file_type),
328 base::Bind(&RemoteSyncDelegate::DidResolveToLocal,
329 AsWeakPtr(), callback));
330 }
331
332 void RemoteSyncDelegate::DidResolveToLocal(
333 const SyncStatusCallback& callback,
334 SyncStatusCode status) {
335 if (status != SYNC_STATUS_OK) {
336 DCHECK_NE(SYNC_STATUS_HAS_CONFLICT, status);
337 AbortSync(callback, status);
338 return;
339 }
340
341 if (remote_file_change().IsDelete()) {
342 metadata_store()->DeleteEntry(
343 url(),
344 base::Bind(&RemoteSyncDelegate::CompleteSync,
345 AsWeakPtr(), callback));
346 } else {
347 DCHECK(!remote_change_.resource_id.empty());
348 drive_metadata_.set_resource_id(remote_change_.resource_id);
349 drive_metadata_.set_conflicted(false);
350 drive_metadata_.set_to_be_fetched(false);
351 drive_metadata_.set_md5_checksum(std::string());
352 metadata_store()->UpdateEntry(
353 url(), drive_metadata_,
354 base::Bind(&RemoteSyncDelegate::CompleteSync,
355 AsWeakPtr(), callback));
356 }
357 }
358
359 void RemoteSyncDelegate::ResolveToRemote(
360 const SyncStatusCallback& callback) {
361 drive_metadata_.set_conflicted(false);
362 drive_metadata_.set_to_be_fetched(true);
363 metadata_store()->UpdateEntry(
364 url(), drive_metadata_,
365 base::Bind(&RemoteSyncDelegate::DidResolveToRemote,
366 AsWeakPtr(), callback));
367 }
368
369 void RemoteSyncDelegate::DidResolveToRemote(
370 const SyncStatusCallback& callback,
371 SyncStatusCode status) {
372 if (status != SYNC_STATUS_OK) {
373 AbortSync(callback, status);
374 return;
375 }
376
377 sync_action_ = SYNC_ACTION_ADDED;
378 if (remote_file_change().file_type() == SYNC_FILE_TYPE_FILE) {
379 DownloadFile(callback);
380 return;
381 }
382
383 // ApplyRemoteChange should replace any existing local file or
384 // directory with remote_change_.
385 ApplyRemoteChange(callback);
386 }
387
388 void RemoteSyncDelegate::StartOver(
389 const SyncStatusCallback& callback,
390 SyncStatusCode status) {
391 DidPrepareForProcessRemoteChange(
392 callback, status, local_metadata_, FileChangeList());
393 }
394
395 void RemoteSyncDelegate::CompleteSync(
396 const SyncStatusCallback& callback,
397 SyncStatusCode status) {
398 if (status != SYNC_STATUS_OK) {
399 AbortSync(callback, status);
400 return;
401 }
402
403 sync_service_->RemoveRemoteChange(url());
404
405 if (drive_metadata_.to_be_fetched()) {
406 // Clear |to_be_fetched| flag since we completed fetching the remote change
407 // and applying it to the local file.
408 DCHECK(!drive_metadata_.conflicted());
409 drive_metadata_.set_conflicted(false);
410 drive_metadata_.set_to_be_fetched(false);
411 metadata_store()->UpdateEntry(url(), drive_metadata_,
412 base::Bind(&EmptyStatusCallback));
413 }
414
415 if (remote_change_.changestamp > 0) {
416 DCHECK(metadata_store()->IsIncrementalSyncOrigin(url().origin()));
417 metadata_store()->SetLargestChangeStamp(
418 remote_change_.changestamp,
419 base::Bind(&RemoteSyncDelegate::DidFinish, AsWeakPtr(), callback));
420 return;
421 }
422
423 if (drive_metadata_.conflicted())
424 status = SYNC_STATUS_HAS_CONFLICT;
425
426 DidFinish(callback, status);
427 }
428
429 void RemoteSyncDelegate::AbortSync(
430 const SyncStatusCallback& callback,
431 SyncStatusCode status) {
432 DidFinish(callback, status);
433 }
434
435 void RemoteSyncDelegate::DidFinish(
436 const SyncStatusCallback& callback,
437 SyncStatusCode status) {
438 // Clear the local changes. If the operation was resolve-to-local, we should
439 // not clear them here since we added the fake local change to sync with the
440 // remote file.
441 if (clear_local_changes_) {
442 clear_local_changes_ = false;
443 remote_change_processor()->ClearLocalChanges(
444 url(), base::Bind(&RemoteSyncDelegate::DidFinish,
445 AsWeakPtr(), callback, status));
446 return;
447 }
448
449 if (status == SYNC_STATUS_OK && sync_action_ != SYNC_ACTION_NONE) {
450 sync_service_->NotifyObserversFileStatusChanged(
451 url(),
452 SYNC_FILE_STATUS_SYNCED,
453 sync_action_,
454 SYNC_DIRECTION_REMOTE_TO_LOCAL);
455 }
456
457 callback.Run(status);
458 }
459
460 SyncStatusCode RemoteSyncDelegate::GDataErrorCodeToSyncStatusCodeWrapper(
461 google_apis::GDataErrorCode error) {
462 return sync_service_->GDataErrorCodeToSyncStatusCodeWrapper(error);
463 }
464
465 DriveMetadataStore* RemoteSyncDelegate::metadata_store() {
466 return sync_service_->metadata_store_.get();
467 }
468
469 APIUtilInterface* RemoteSyncDelegate::api_util() {
470 return sync_service_->api_util_.get();
471 }
472
473 RemoteChangeHandler* RemoteSyncDelegate::remote_change_handler() {
474 return &sync_service_->remote_change_handler_;
475 }
476
477 RemoteChangeProcessor* RemoteSyncDelegate::remote_change_processor() {
478 return sync_service_->remote_change_processor_;
479 }
480
481 ConflictResolutionResolver* RemoteSyncDelegate::conflict_resolution_resolver() {
482 return &sync_service_->conflict_resolution_resolver_;
483 }
484
485 } // namespace drive_backend
486 } // namespace sync_file_system
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698