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