change_list_loader.h revision 8bcbed890bc3ce4d7a057a8f32cab53fa534672e
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.
4
5#ifndef CHROME_BROWSER_CHROMEOS_DRIVE_CHANGE_LIST_LOADER_H_
6#define CHROME_BROWSER_CHROMEOS_DRIVE_CHANGE_LIST_LOADER_H_
7
8#include <map>
9#include <set>
10#include <string>
11#include <vector>
12
13#include "base/callback.h"
14#include "base/memory/ref_counted.h"
15#include "base/memory/scoped_ptr.h"
16#include "base/memory/scoped_vector.h"
17#include "base/observer_list.h"
18#include "base/time/time.h"
19#include "chrome/browser/chromeos/drive/file_errors.h"
20#include "chrome/browser/google_apis/gdata_errorcode.h"
21
22class GURL;
23
24namespace base {
25class SequencedTaskRunner;
26}  // namespace base
27
28namespace google_apis {
29class AboutResource;
30class ResourceList;
31}  // namespace google_apis
32
33namespace drive {
34
35class DriveServiceInterface;
36class JobScheduler;
37class ResourceEntry;
38
39namespace internal {
40
41class ChangeList;
42class ChangeListLoaderObserver;
43class ChangeListProcessor;
44class DirectoryFetchInfo;
45class ResourceMetadata;
46
47// Callback run as a response to SearchFromServer.
48typedef base::Callback<void(ScopedVector<ChangeList> change_lists,
49                            FileError error)> LoadChangeListCallback;
50
51// ChangeListLoader is used to load the change list, the full resource list,
52// and directory contents, from WAPI (codename for Documents List API)
53// or Google Drive API.  The class also updates the resource metadata with
54// the change list loaded from the server.
55//
56// Note that the difference between "resource list" and "change list" is
57// subtle hence the two words are often used interchangeably. To be precise,
58// "resource list" refers to metadata from the server when fetching the full
59// resource metadata, or fetching directory contents, whereas "change list"
60// refers to metadata from the server when fetching changes (delta).
61class ChangeListLoader {
62 public:
63  // Resource feed fetcher from the server.
64  class FeedFetcher;
65
66  ChangeListLoader(base::SequencedTaskRunner* blocking_task_runner,
67                   ResourceMetadata* resource_metadata,
68                   JobScheduler* scheduler,
69                   DriveServiceInterface* drive_service);
70  ~ChangeListLoader();
71
72  // Indicates whether there is a request for full resource list or change
73  // list fetching is in flight (i.e. directory contents fetching does not
74  // count).
75  bool IsRefreshing() const;
76
77  // Adds and removes the observer.
78  void AddObserver(ChangeListLoaderObserver* observer);
79  void RemoveObserver(ChangeListLoaderObserver* observer);
80
81  // Checks for updates on the server. Does nothing if the change list is now
82  // being loaded or refreshed. |callback| must not be null.
83  // Note: |callback| will be called if the check for updates actually
84  // runs, i.e. it may NOT be called if the checking is ignored.
85  void CheckForUpdates(const FileOperationCallback& callback);
86
87  // Starts the change list loading first from the cache. If loading from the
88  // cache is successful, runs |callback| immediately and starts checking
89  // server for updates in background. If loading from the cache is
90  // unsuccessful, starts loading from the server, and runs |callback| to tell
91  // the result to the caller when it is finished.
92  //
93  // If |directory_fetch_info| is not empty, the directory will be fetched
94  // first from the server, so the UI can show the directory contents
95  // instantly before the entire change list loading is complete.
96  //
97  // |callback| must not be null.
98  void LoadIfNeeded(const DirectoryFetchInfo& directory_fetch_info,
99                    const FileOperationCallback& callback);
100
101 private:
102  // Starts the resource metadata loading and calls |callback| when it's
103  // done. |directory_fetch_info| is used for fast fetch. If there is already
104  // a loading job in-flight for |directory_fetch_info|, just append the
105  // |callback| to the callback queue of the already running job.
106  void Load(const DirectoryFetchInfo& directory_fetch_info,
107            const FileOperationCallback& callback);
108
109  // Part of Load(). DoInitialLoad() is called if it is the first time to Load.
110  // Otherwise DoUpdateLoad() is used. The difference of two cases are:
111  // - When we could load from cache, DoInitialLoad runs callback immediately
112  //   and further operations (check changestamp and load from server if needed)
113  //   in background.
114  // - Even when |directory_fetch_info| is set, DoInitialLoad runs change list
115  //   loading after directory loading is finished.
116  void DoInitialLoad(const DirectoryFetchInfo& directory_fetch_info,
117                     int64 local_changestamp);
118  void DoUpdateLoad(const DirectoryFetchInfo& directory_fetch_info,
119                    int64 local_changestamp);
120
121  // Part of Load().
122  // This function should be called when the change list load is complete.
123  // Flushes the callbacks for change list loading and all directory loading.
124  void OnChangeListLoadComplete(FileError error);
125
126  // Part of Load().
127  // This function should be called when the directory load is complete.
128  // Flushes the callbacks waiting for the directory to be loaded.
129  void OnDirectoryLoadComplete(const DirectoryFetchInfo& directory_fetch_info,
130                               FileError error);
131
132  // ================= Implementation for change list loading =================
133
134  // Initiates the change list loading from the server when |local_changestamp|
135  // is older than the server changestamp. If |directory_fetch_info| is set,
136  // do directory loading before change list loading.
137  void LoadFromServerIfNeeded(const DirectoryFetchInfo& directory_fetch_info,
138                              int64 local_changestamp);
139
140  // Part of LoadFromServerIfNeeded().
141  // Called after GetAboutResource() for getting remote changestamp is complete.
142  void LoadFromServerIfNeededAfterGetAbout(
143      const DirectoryFetchInfo& directory_fetch_info,
144      int64 local_changestamp,
145      google_apis::GDataErrorCode status,
146      scoped_ptr<google_apis::AboutResource> about_resource);
147
148  // Part of LoadFromServerIfNeeded().
149  // When LoadFromServerIfNeeded is called with |directory_fetch_info| for a
150  // specific directory, it tries to load the directory before loading the
151  // content of full filesystem. This method is called after directory loading
152  // is finished, and proceeds to the normal pass: LoadChangeListServer.
153  void LoadFromServerIfNeededAfterLoadDirectory(
154      const DirectoryFetchInfo& directory_fetch_info,
155      scoped_ptr<google_apis::AboutResource> about_resource,
156      int64 start_changestamp,
157      FileError error);
158
159  // Part of LoadFromServerIfNeeded().
160  // Starts loading the change list since |start_changestamp|, or the full
161  // resource list if |start_changestamp| is zero. For full update, the
162  // largest_change_id and root_folder_id from |about_resource| will be used.
163  void LoadChangeListFromServer(
164      scoped_ptr<google_apis::AboutResource> about_resource,
165      int64 start_changestamp);
166
167  // Part of LoadChangeListFromServer().
168  // Called when the entire change list is loaded.
169  void LoadChangeListFromServerAfterLoadChangeList(
170      scoped_ptr<google_apis::AboutResource> about_resource,
171      bool is_delta_update,
172      FileError error,
173      ScopedVector<ChangeList> change_lists);
174
175  // Part of LoadChangeListFromServer().
176  // Called when the resource metadata is updated.
177  void LoadChangeListFromServerAfterUpdate();
178
179  // ================= Implementation for directory loading =================
180
181  // Compares the directory's changestamp and |last_known_remote_changestamp_|.
182  // Starts DoLoadDirectoryFromServer() if the local data is old and runs
183  // |callback| when finished. If it is up to date, calls back immediately.
184  void CheckChangestampAndLoadDirectoryIfNeeded(
185      const DirectoryFetchInfo& directory_fetch_info,
186      int64 local_changestamp,
187      const FileOperationCallback& callback);
188
189  // Loads the directory contents from server, and updates the local metadata.
190  // Runs |callback| when it is finished.
191  void DoLoadDirectoryFromServer(const DirectoryFetchInfo& directory_fetch_info,
192                                 const FileOperationCallback& callback);
193
194  // Part of DoLoadDirectoryFromServer() for the grand root ("/drive").
195  void DoLoadGrandRootDirectoryFromServerAfterGetResourceEntryByPath(
196      const DirectoryFetchInfo& directory_fetch_info,
197      const FileOperationCallback& callback,
198      FileError error,
199      scoped_ptr<ResourceEntry> entry);
200
201  // Part of DoLoadDirectoryFromServer() for the grand root ("/drive").
202  void DoLoadGrandRootDirectoryFromServerAfterGetAboutResource(
203      const DirectoryFetchInfo& directory_fetch_info,
204      const FileOperationCallback& callback,
205      google_apis::GDataErrorCode status,
206      scoped_ptr<google_apis::AboutResource> about_resource);
207
208  // Part of DoLoadDirectoryFromServer() for the grand root ("/drive").
209  void DoLoadDirectoryFromServerAfterAddMyDrive(
210      const DirectoryFetchInfo& directory_fetch_info,
211      const FileOperationCallback& callback,
212      std::string* local_id,
213      FileError error);
214
215  // Part of DoLoadDirectoryFromServer() for a normal directory.
216  void DoLoadDirectoryFromServerAfterLoad(
217      const DirectoryFetchInfo& directory_fetch_info,
218      const FileOperationCallback& callback,
219      FeedFetcher* fetcher,
220      FileError error,
221      ScopedVector<ChangeList> change_lists);
222
223  // Part of DoLoadDirectoryFromServer().
224  void DoLoadDirectoryFromServerAfterRefresh(
225      const DirectoryFetchInfo& directory_fetch_info,
226      const FileOperationCallback& callback,
227      const base::FilePath* directory_path,
228      FileError error);
229
230  // ================= Implementation for other stuff =================
231
232  // Updates from the whole change list collected in |change_lists|.
233  // Record file statistics as UMA histograms.
234  //
235  // See comments at ChangeListProcessor::Apply() for
236  // |about_resource| and |is_delta_update|.
237  // |callback| must not be null.
238  void UpdateFromChangeList(
239      scoped_ptr<google_apis::AboutResource> about_resource,
240      ScopedVector<ChangeList> change_lists,
241      bool is_delta_update,
242      const base::Closure& callback);
243
244  // Part of UpdateFromChangeList().
245  // Called when ChangeListProcessor::Apply() is complete.
246  // Notifies directory changes per the result of the change list processing.
247  void UpdateFromChangeListAfterApply(
248      ChangeListProcessor* change_list_processor,
249      bool should_notify,
250      base::Time start_time,
251      const base::Closure& callback,
252      FileError error);
253
254  scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
255  ResourceMetadata* resource_metadata_;  // Not owned.
256  JobScheduler* scheduler_;  // Not owned.
257  DriveServiceInterface* drive_service_;  // Not owned.
258  ObserverList<ChangeListLoaderObserver> observers_;
259  typedef std::map<std::string, std::vector<FileOperationCallback> >
260      LoadCallbackMap;
261  LoadCallbackMap pending_load_callback_;
262  FileOperationCallback pending_update_check_callback_;
263
264  // Running feed fetcher.
265  scoped_ptr<FeedFetcher> change_feed_fetcher_;
266
267  // Set of the running feed fetcher for the fast fetch.
268  std::set<FeedFetcher*> fast_fetch_feed_fetcher_set_;
269
270  // The last known remote changestamp. Used to check if a directory
271  // changestamp is up-to-date for fast fetch.
272  int64 last_known_remote_changestamp_;
273
274  // The cache of the root_folder_id.
275  std::string root_folder_id_;
276
277  // True if the full resource list is loaded (i.e. the resource metadata is
278  // stored locally).
279  bool loaded_;
280
281  // Note: This should remain the last member so it'll be destroyed and
282  // invalidate its weak pointers before any other members are destroyed.
283  base::WeakPtrFactory<ChangeListLoader> weak_ptr_factory_;
284  DISALLOW_COPY_AND_ASSIGN(ChangeListLoader);
285};
286
287}  // namespace internal
288}  // namespace drive
289
290#endif  // CHROME_BROWSER_CHROMEOS_DRIVE_CHANGE_LIST_LOADER_H_
291