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.
5 #ifndef CHROME_BROWSER_CHROMEOS_DRIVE_CHANGE_LIST_LOADER_H_
6 #define CHROME_BROWSER_CHROMEOS_DRIVE_CHANGE_LIST_LOADER_H_
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"
25 class SequencedTaskRunner;
28 namespace google_apis {
31 } // namespace google_apis
35 class DriveServiceInterface;
42 class ChangeListLoaderObserver;
43 class ChangeListProcessor;
44 class DirectoryFetchInfo;
45 class ResourceMetadata;
47 // Callback run as a response to SearchFromServer.
48 typedef base::Callback<void(ScopedVector<ChangeList> change_lists,
49 FileError error)> LoadChangeListCallback;
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.
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).
61 class ChangeListLoader {
63 // Resource feed fetcher from the server.
66 ChangeListLoader(base::SequencedTaskRunner* blocking_task_runner,
67 ResourceMetadata* resource_metadata,
68 JobScheduler* scheduler,
69 DriveServiceInterface* drive_service);
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
75 bool IsRefreshing() const;
77 // Adds and removes the observer.
78 void AddObserver(ChangeListLoaderObserver* observer);
79 void RemoveObserver(ChangeListLoaderObserver* observer);
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);
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.
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.
97 // |callback| must not be null.
98 void LoadIfNeeded(const DirectoryFetchInfo& directory_fetch_info,
99 const FileOperationCallback& callback);
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);
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)
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);
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);
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,
132 // ================= Implementation for change list loading =================
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);
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);
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,
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);
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,
173 ScopedVector<ChangeList> change_lists);
175 // Part of LoadChangeListFromServer().
176 // Called when the resource metadata is updated.
177 void LoadChangeListFromServerAfterUpdate();
179 // ================= Implementation for directory loading =================
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);
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);
194 // Part of DoLoadDirectoryFromServer() for the grand root ("/drive").
195 void DoLoadGrandRootDirectoryFromServerAfterGetResourceEntryByPath(
196 const DirectoryFetchInfo& directory_fetch_info,
197 const FileOperationCallback& callback,
199 scoped_ptr<ResourceEntry> entry);
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);
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,
215 // Part of DoLoadDirectoryFromServer() for a normal directory.
216 void DoLoadDirectoryFromServerAfterLoad(
217 const DirectoryFetchInfo& directory_fetch_info,
218 const FileOperationCallback& callback,
219 FeedFetcher* fetcher,
221 ScopedVector<ChangeList> change_lists);
223 // Part of DoLoadDirectoryFromServer().
224 void DoLoadDirectoryFromServerAfterRefresh(
225 const DirectoryFetchInfo& directory_fetch_info,
226 const FileOperationCallback& callback,
227 const base::FilePath* directory_path,
230 // ================= Implementation for other stuff =================
232 // Updates from the whole change list collected in |change_lists|.
233 // Record file statistics as UMA histograms.
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);
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,
250 base::Time start_time,
251 const base::Closure& callback,
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> >
261 LoadCallbackMap pending_load_callback_;
262 FileOperationCallback pending_update_check_callback_;
264 // Running feed fetcher.
265 scoped_ptr<FeedFetcher> change_feed_fetcher_;
267 // Set of the running feed fetcher for the fast fetch.
268 std::set<FeedFetcher*> fast_fetch_feed_fetcher_set_;
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_;
274 // The cache of the root_folder_id.
275 std::string root_folder_id_;
277 // True if the full resource list is loaded (i.e. the resource metadata is
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);
287 } // namespace internal
290 #endif // CHROME_BROWSER_CHROMEOS_DRIVE_CHANGE_LIST_LOADER_H_