remote_to_local_syncer.h revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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#ifndef CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_REMOTE_TO_LOCAL_SYNCER_H_
6#define CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_REMOTE_TO_LOCAL_SYNCER_H_
7
8#include <string>
9#include <vector>
10
11#include "base/memory/scoped_vector.h"
12#include "base/memory/weak_ptr.h"
13#include "chrome/browser/sync_file_system/drive_backend/metadata_database.pb.h"
14#include "chrome/browser/sync_file_system/remote_change_processor.h"
15#include "chrome/browser/sync_file_system/sync_action.h"
16#include "chrome/browser/sync_file_system/sync_callbacks.h"
17#include "chrome/browser/sync_file_system/sync_file_metadata.h"
18#include "chrome/browser/sync_file_system/sync_task.h"
19#include "google_apis/drive/gdata_errorcode.h"
20#include "webkit/browser/fileapi/file_system_url.h"
21
22namespace drive {
23class DriveServiceInterface;
24}
25
26namespace google_apis {
27class FileResource;
28class ResourceEntry;
29class ResourceList;
30}
31
32namespace webkit_blob {
33class ScopedFile;
34}
35
36namespace sync_file_system {
37namespace drive_backend {
38
39class MetadataDatabase;
40class SyncEngineContext;
41
42class RemoteToLocalSyncer : public SyncTask {
43 public:
44  // Conflicting trackers will have low priority for RemoteToLocalSyncer so that
45  // it should be resolved by LocatToRemoteSyncer.
46  explicit RemoteToLocalSyncer(SyncEngineContext* sync_context);
47  virtual ~RemoteToLocalSyncer();
48
49  virtual void Run(const SyncStatusCallback& callback) OVERRIDE;
50
51  const fileapi::FileSystemURL& url() const { return url_; }
52  SyncAction sync_action() const { return sync_action_; }
53
54  bool is_sync_root_deletion() const { return sync_root_deletion_; }
55
56 private:
57  typedef std::vector<std::string> FileIDList;
58
59  // TODO(tzik): Update documentation here.
60  //
61  // Dispatches remote change to handlers or to SyncCompleted() directly.
62  // This function uses information only in MetadataDatabase.
63  //
64  // If the tracker doesn't have remote metadata:
65  //   # The file is listed in a folder right before this operation.
66  //   - Dispatch to HandleMissingRemoteMetadata to fetch remote metadata.
67  // Else, if the tracker is not active or the dominating app-root is disabled:
68  //   # Assume the file has remote metadata.
69  //   - Update the tracker with |missing| flag and empty |md5|.
70  //   Note: MetadataDatabase may activate the tracker if possible.
71  // Else, if the tracker doesn't have synced metadata:
72  //   # Assume the tracker has remote metadata and the tracker is active.
73  //   # The tracker is not yet synced ever.
74  //   - If the file is remotely deleted, do nothing to local file and dispatch
75  //     directly to SyncCompleted().
76  //   - Else, if the file is a regular file, dispatch to HandleNewFile().
77  //   - Else, if the file is a folder, dispatch to HandleFolderUpdate().
78  //   - Else, the file should be an unsupported active file. This should not
79  //     happen.
80  // Else, if the remote metadata is marked as deleted:
81  //   # Most of the remote metadata is missing including title, kind and md5.
82  //   - Dispatch to HandleDeletion().
83  // Else, if the tracker has different titles between its synced metadata and
84  // remote metadata:
85  //   # Assume the tracker is active and has remote metetadata and synced
86  //     metadata.
87  //   # The file is remotely renamed.
88  //   # Maybe, this can be decomposed to delete and update.
89  //   - Dispatch to HandleRemoteRename().
90  // Else, if the tracker's parent is not a parent of the remote metadata:
91  //   # The file has reorganized.
92  //   # Maybe, this can be decomposed to delete and update.
93  //   - Dispatch to HandreReorganize().
94  // Else, if the folder is a regular file and the md5 in remote metadata does
95  // not match the md5 in synced metadata:
96  //   # The file is modified remotely.
97  //   - Dispatch to HandleContentUpdate().
98  // Else, if the tracker is a folder and it has needs_folder_listing flag:
99  //   - Dispatch to HandleFolderContentListing()
100  // Else, there should be no change to sync.
101  //   - Dispatch to HandleOfflineSolvable()
102  void ResolveRemoteChange(const SyncStatusCallback& callback);
103
104  // Handles missing remote metadata case.
105  // Fetches remote metadata and updates MetadataDatabase by that.  The sync
106  // operation itself will be deferred to the next sync round.
107  // Note: if the file is not found, it should be handled as if deleted.
108  void HandleMissingRemoteMetadata(const SyncStatusCallback& callback);
109  void DidGetRemoteMetadata(const SyncStatusCallback& callback,
110                            google_apis::GDataErrorCode error,
111                            scoped_ptr<google_apis::ResourceEntry> entry);
112  void DidUpdateDatabaseForRemoteMetadata(const SyncStatusCallback& callback,
113                                          SyncStatusCode status);
114
115  // This implements the body of the HandleNewFile and HandleContentUpdate.
116  // If the file doesn't have corresponding local file:
117  //   - Dispatch to DownloadFile.
118  // Else, if the local file doesn't have local change:
119  //   - Dispatch to DownloadFile if the local file is a regular file.
120  //   - If the local file is a folder, handle this case as a conflict.  Lower
121  //     the priority of the tracker, and defer further handling to
122  //     local-to-remote change.
123  // Else:
124  //  # The file has local modification.
125  //  - Handle this case as a conflict.  Lower the priority of the tracker, and
126  //    defer further handling to local-to-remote change.
127  void DidPrepareForAddOrUpdateFile(const SyncStatusCallback& callback,
128                                    SyncStatusCode status);
129
130  // Handles remotely added folder.  Needs Prepare() call.
131  // TODO(tzik): Write details and implement this.
132  void HandleFolderUpdate(const SyncStatusCallback& callback);
133  void DidPrepareForFolderUpdate(const SyncStatusCallback& callback,
134                                 SyncStatusCode status);
135
136  void HandleSyncRootDeletion(const SyncStatusCallback& callback);
137
138  // Handles deleted remote file.  Needs Prepare() call.
139  // If the deleted tracker is the sync-root:
140  //  - TODO(tzik): Needs special handling.
141  // Else, if the deleted tracker is a app-root:
142  //  - TODO(tzik): Needs special handling.
143  // Else, if the local file is already deleted:
144  //  - Do nothing anymore to the local, call SyncCompleted().
145  // Else, if the local file is modified:
146  //  - Do nothing to the local file, call SyncCompleted().
147  // Else, if the local file is not modified:
148  //  - Delete local file.
149  //  # Note: if the local file is a folder, delete recursively.
150  void HandleDeletion(const SyncStatusCallback& callback);
151  void DidPrepareForDeletion(const SyncStatusCallback& callback,
152                             SyncStatusCode status);
153
154  // Handles new file.  Needs Prepare() call.
155  void HandleContentUpdate(const SyncStatusCallback& callback);
156
157  void ListFolderContent(const SyncStatusCallback& callback);
158  void DidListFolderContent(
159      const SyncStatusCallback& callback,
160      scoped_ptr<FileIDList> children,
161      google_apis::GDataErrorCode error,
162      scoped_ptr<google_apis::ResourceList> resource_list);
163
164  void SyncCompleted(const SyncStatusCallback& callback, SyncStatusCode status);
165  void FinalizeSync(const SyncStatusCallback& callback, SyncStatusCode status);
166
167
168  void Prepare(const SyncStatusCallback& callback);
169  void DidPrepare(const SyncStatusCallback& callback,
170                  SyncStatusCode status,
171                  const SyncFileMetadata& metadata,
172                  const FileChangeList& changes);
173
174  void DeleteLocalFile(const SyncStatusCallback& callback);
175  void DownloadFile(const SyncStatusCallback& callback);
176  void DidCreateTemporaryFileForDownload(const SyncStatusCallback& callback,
177                                         webkit_blob::ScopedFile file);
178  void DidDownloadFile(const SyncStatusCallback& callback,
179                       webkit_blob::ScopedFile file,
180                       google_apis::GDataErrorCode error,
181                       const base::FilePath&);
182  void DidCalculateMD5ForDownload(const SyncStatusCallback& callback,
183                                  webkit_blob::ScopedFile file,
184                                  const std::string& md5);
185  void DidApplyDownload(const SyncStatusCallback& callback,
186                        webkit_blob::ScopedFile,
187                        SyncStatusCode status);
188
189  void CreateFolder(const SyncStatusCallback& callback);
190
191  drive::DriveServiceInterface* drive_service();
192  MetadataDatabase* metadata_database();
193  RemoteChangeProcessor* remote_change_processor();
194
195  SyncEngineContext* sync_context_;  // Not owned.
196
197  scoped_ptr<FileTracker> dirty_tracker_;
198  scoped_ptr<FileMetadata> remote_metadata_;
199
200  fileapi::FileSystemURL url_;
201  SyncAction sync_action_;
202
203  bool prepared_;
204  bool sync_root_deletion_;
205
206  scoped_ptr<SyncFileMetadata> local_metadata_;
207  scoped_ptr<FileChangeList> local_changes_;
208
209  base::WeakPtrFactory<RemoteToLocalSyncer> weak_ptr_factory_;
210
211  DISALLOW_COPY_AND_ASSIGN(RemoteToLocalSyncer);
212};
213
214}  // namespace drive_backend
215}  // namespace sync_file_system
216
217#endif  // CHROME_BROWSER_SYNC_FILE_SYSTEM_DRIVE_BACKEND_REMOTE_TO_LOCAL_SYNCER_H_
218