| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef CHROME_BROWSER_CHROMEOS_DRIVE_CHANGE_LIST_LOADER_H_ |
| #define CHROME_BROWSER_CHROMEOS_DRIVE_CHANGE_LIST_LOADER_H_ |
| |
| #include <map> |
| #include <set> |
| #include <string> |
| #include <vector> |
| |
| #include "base/callback.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/memory/scoped_ptr.h" |
| #include "base/memory/scoped_vector.h" |
| #include "base/observer_list.h" |
| #include "base/time/time.h" |
| #include "chrome/browser/chromeos/drive/file_errors.h" |
| #include "chrome/browser/google_apis/gdata_errorcode.h" |
| |
| class GURL; |
| |
| namespace base { |
| class SequencedTaskRunner; |
| } // namespace base |
| |
| namespace google_apis { |
| class AboutResource; |
| class ResourceList; |
| } // namespace google_apis |
| |
| namespace drive { |
| |
| class DriveServiceInterface; |
| class JobScheduler; |
| class ResourceEntry; |
| |
| namespace internal { |
| |
| class ChangeList; |
| class ChangeListLoaderObserver; |
| class ChangeListProcessor; |
| class DirectoryFetchInfo; |
| class ResourceMetadata; |
| |
| // Callback run as a response to SearchFromServer. |
| typedef base::Callback<void(ScopedVector<ChangeList> change_lists, |
| FileError error)> LoadChangeListCallback; |
| |
| // ChangeListLoader is used to load the change list, the full resource list, |
| // and directory contents, from WAPI (codename for Documents List API) |
| // or Google Drive API. The class also updates the resource metadata with |
| // the change list loaded from the server. |
| // |
| // Note that the difference between "resource list" and "change list" is |
| // subtle hence the two words are often used interchangeably. To be precise, |
| // "resource list" refers to metadata from the server when fetching the full |
| // resource metadata, or fetching directory contents, whereas "change list" |
| // refers to metadata from the server when fetching changes (delta). |
| class ChangeListLoader { |
| public: |
| // Resource feed fetcher from the server. |
| class FeedFetcher; |
| |
| ChangeListLoader(base::SequencedTaskRunner* blocking_task_runner, |
| ResourceMetadata* resource_metadata, |
| JobScheduler* scheduler, |
| DriveServiceInterface* drive_service); |
| ~ChangeListLoader(); |
| |
| // Indicates whether there is a request for full resource list or change |
| // list fetching is in flight (i.e. directory contents fetching does not |
| // count). |
| bool IsRefreshing() const; |
| |
| // Adds and removes the observer. |
| void AddObserver(ChangeListLoaderObserver* observer); |
| void RemoveObserver(ChangeListLoaderObserver* observer); |
| |
| // Checks for updates on the server. Does nothing if the change list is now |
| // being loaded or refreshed. |callback| must not be null. |
| // Note: |callback| will be called if the check for updates actually |
| // runs, i.e. it may NOT be called if the checking is ignored. |
| void CheckForUpdates(const FileOperationCallback& callback); |
| |
| // Starts the change list loading first from the cache. If loading from the |
| // cache is successful, runs |callback| immediately and starts checking |
| // server for updates in background. If loading from the cache is |
| // unsuccessful, starts loading from the server, and runs |callback| to tell |
| // the result to the caller when it is finished. |
| // |
| // If |directory_fetch_info| is not empty, the directory will be fetched |
| // first from the server, so the UI can show the directory contents |
| // instantly before the entire change list loading is complete. |
| // |
| // |callback| must not be null. |
| void LoadIfNeeded(const DirectoryFetchInfo& directory_fetch_info, |
| const FileOperationCallback& callback); |
| |
| // Loads the directory content from the server, without comparing the |
| // changestamps. The purpose of this function is to update thumbnail URLs |
| // in the directory which can stale over time. |
| void LoadDirectoryFromServer(const std::string& directory_resource_id, |
| const FileOperationCallback& callback); |
| |
| private: |
| // Starts the resource metadata loading and calls |callback| when it's |
| // done. |directory_fetch_info| is used for fast fetch. If there is already |
| // a loading job in-flight for |directory_fetch_info|, just append the |
| // |callback| to the callback queue of the already running job. |
| void Load(const DirectoryFetchInfo& directory_fetch_info, |
| const FileOperationCallback& callback); |
| |
| // Part of Load(). DoInitialLoad() is called if it is the first time to Load. |
| // Otherwise DoUpdateLoad() is used. The difference of two cases are: |
| // - When we could load from cache, DoInitialLoad runs callback immediately |
| // and further operations (check changestamp and load from server if needed) |
| // in background. |
| // - Even when |directory_fetch_info| is set, DoInitialLoad runs change list |
| // loading after directory loading is finished. |
| void DoInitialLoad(const DirectoryFetchInfo& directory_fetch_info, |
| int64 local_changestamp); |
| void DoUpdateLoad(const DirectoryFetchInfo& directory_fetch_info, |
| int64 local_changestamp); |
| |
| // Part of Load(). |
| // This function should be called when the change list load is complete. |
| // Flushes the callbacks for change list loading and all directory loading. |
| void OnChangeListLoadComplete(FileError error); |
| |
| // Part of Load(). |
| // This function should be called when the directory load is complete. |
| // Flushes the callbacks waiting for the directory to be loaded. |
| void OnDirectoryLoadComplete(const DirectoryFetchInfo& directory_fetch_info, |
| FileError error); |
| |
| // ================= Implementation for change list loading ================= |
| |
| // Initiates the change list loading from the server when |local_changestamp| |
| // is older than the server changestamp. If |directory_fetch_info| is set, |
| // do directory loading before change list loading. |
| void LoadFromServerIfNeeded(const DirectoryFetchInfo& directory_fetch_info, |
| int64 local_changestamp); |
| |
| // Part of LoadFromServerIfNeeded(). |
| // Called after GetAboutResource() for getting remote changestamp is complete. |
| void LoadFromServerIfNeededAfterGetAbout( |
| const DirectoryFetchInfo& directory_fetch_info, |
| int64 local_changestamp, |
| google_apis::GDataErrorCode status, |
| scoped_ptr<google_apis::AboutResource> about_resource); |
| |
| // Part of LoadFromServerIfNeeded(). |
| // When LoadFromServerIfNeeded is called with |directory_fetch_info| for a |
| // specific directory, it tries to load the directory before loading the |
| // content of full filesystem. This method is called after directory loading |
| // is finished, and proceeds to the normal pass: LoadChangeListServer. |
| void LoadFromServerIfNeededAfterLoadDirectory( |
| const DirectoryFetchInfo& directory_fetch_info, |
| scoped_ptr<google_apis::AboutResource> about_resource, |
| int64 start_changestamp, |
| FileError error); |
| |
| // Part of LoadFromServerIfNeeded(). |
| // Starts loading the change list since |start_changestamp|, or the full |
| // resource list if |start_changestamp| is zero. For full update, the |
| // largest_change_id and root_folder_id from |about_resource| will be used. |
| void LoadChangeListFromServer( |
| scoped_ptr<google_apis::AboutResource> about_resource, |
| int64 start_changestamp); |
| |
| // Part of LoadChangeListFromServer(). |
| // Called when the entire change list is loaded. |
| void LoadChangeListFromServerAfterLoadChangeList( |
| scoped_ptr<google_apis::AboutResource> about_resource, |
| bool is_delta_update, |
| FileError error, |
| ScopedVector<ChangeList> change_lists); |
| |
| // Part of LoadChangeListFromServer(). |
| // Called when the resource metadata is updated. |
| void LoadChangeListFromServerAfterUpdate(); |
| |
| // ================= Implementation for directory loading ================= |
| |
| // Part of LoadDirectoryFromServer(), called after the current remote |
| // changestamp is obtained as |about_resource|. |
| void LoadDirectoryFromServerAfterGetAbout( |
| const std::string& directory_resource_id, |
| const FileOperationCallback& callback, |
| google_apis::GDataErrorCode status, |
| scoped_ptr<google_apis::AboutResource> about_resource); |
| |
| // Compares the directory's changestamp and |last_known_remote_changestamp_|. |
| // Starts DoLoadDirectoryFromServer() if the local data is old and runs |
| // |callback| when finished. If it is up to date, calls back immediately. |
| void CheckChangestampAndLoadDirectoryIfNeeded( |
| const DirectoryFetchInfo& directory_fetch_info, |
| int64 local_changestamp, |
| const FileOperationCallback& callback); |
| |
| // Loads the directory contents from server, and updates the local metadata. |
| // Runs |callback| when it is finished. |
| void DoLoadDirectoryFromServer(const DirectoryFetchInfo& directory_fetch_info, |
| const FileOperationCallback& callback); |
| |
| // Part of DoLoadDirectoryFromServer() for the grand root ("/drive"). |
| void DoLoadGrandRootDirectoryFromServerAfterGetResourceEntryByPath( |
| const DirectoryFetchInfo& directory_fetch_info, |
| const FileOperationCallback& callback, |
| FileError error, |
| scoped_ptr<ResourceEntry> entry); |
| |
| // Part of DoLoadDirectoryFromServer() for the grand root ("/drive"). |
| void DoLoadGrandRootDirectoryFromServerAfterGetAboutResource( |
| const DirectoryFetchInfo& directory_fetch_info, |
| const FileOperationCallback& callback, |
| google_apis::GDataErrorCode status, |
| scoped_ptr<google_apis::AboutResource> about_resource); |
| |
| // Part of DoLoadDirectoryFromServer() for the grand root ("/drive"). |
| void DoLoadDirectoryFromServerAfterAddMyDrive( |
| const DirectoryFetchInfo& directory_fetch_info, |
| const FileOperationCallback& callback, |
| std::string* local_id, |
| FileError error); |
| |
| // Part of DoLoadDirectoryFromServer() for a normal directory. |
| void DoLoadDirectoryFromServerAfterLoad( |
| const DirectoryFetchInfo& directory_fetch_info, |
| const FileOperationCallback& callback, |
| FeedFetcher* fetcher, |
| FileError error, |
| ScopedVector<ChangeList> change_lists); |
| |
| // Part of DoLoadDirectoryFromServer(). |
| void DoLoadDirectoryFromServerAfterRefresh( |
| const DirectoryFetchInfo& directory_fetch_info, |
| const FileOperationCallback& callback, |
| const base::FilePath* directory_path, |
| FileError error); |
| |
| // ================= Implementation for other stuff ================= |
| |
| // Updates from the whole change list collected in |change_lists|. |
| // Record file statistics as UMA histograms. |
| // |
| // See comments at ChangeListProcessor::Apply() for |
| // |about_resource| and |is_delta_update|. |
| // |callback| must not be null. |
| void UpdateFromChangeList( |
| scoped_ptr<google_apis::AboutResource> about_resource, |
| ScopedVector<ChangeList> change_lists, |
| bool is_delta_update, |
| const base::Closure& callback); |
| |
| // Part of UpdateFromChangeList(). |
| // Called when ChangeListProcessor::Apply() is complete. |
| // Notifies directory changes per the result of the change list processing. |
| void UpdateFromChangeListAfterApply( |
| ChangeListProcessor* change_list_processor, |
| bool should_notify, |
| base::Time start_time, |
| const base::Closure& callback); |
| |
| scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; |
| ResourceMetadata* resource_metadata_; // Not owned. |
| JobScheduler* scheduler_; // Not owned. |
| DriveServiceInterface* drive_service_; // Not owned. |
| ObserverList<ChangeListLoaderObserver> observers_; |
| typedef std::map<std::string, std::vector<FileOperationCallback> > |
| LoadCallbackMap; |
| LoadCallbackMap pending_load_callback_; |
| FileOperationCallback pending_update_check_callback_; |
| |
| // Running feed fetcher. |
| scoped_ptr<FeedFetcher> change_feed_fetcher_; |
| |
| // Set of the running feed fetcher for the fast fetch. |
| std::set<FeedFetcher*> fast_fetch_feed_fetcher_set_; |
| |
| // The last known remote changestamp. Used to check if a directory |
| // changestamp is up-to-date for fast fetch. |
| int64 last_known_remote_changestamp_; |
| |
| // The cache of the root_folder_id. |
| std::string root_folder_id_; |
| |
| // True if the full resource list is loaded (i.e. the resource metadata is |
| // stored locally). |
| bool loaded_; |
| |
| // Note: This should remain the last member so it'll be destroyed and |
| // invalidate its weak pointers before any other members are destroyed. |
| base::WeakPtrFactory<ChangeListLoader> weak_ptr_factory_; |
| DISALLOW_COPY_AND_ASSIGN(ChangeListLoader); |
| }; |
| |
| } // namespace internal |
| } // namespace drive |
| |
| #endif // CHROME_BROWSER_CHROMEOS_DRIVE_CHANGE_LIST_LOADER_H_ |