| // 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 COMPONENTS_DRIVE_CHROMEOS_CHANGE_LIST_LOADER_H_ |
| #define COMPONENTS_DRIVE_CHROMEOS_CHANGE_LIST_LOADER_H_ |
| |
| #include <stdint.h> |
| |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "base/callback.h" |
| #include "base/macros.h" |
| #include "base/memory/ref_counted.h" |
| #include "base/observer_list.h" |
| #include "base/threading/thread_checker.h" |
| #include "components/drive/file_errors.h" |
| #include "google_apis/drive/drive_api_error_codes.h" |
| #include "google_apis/drive/drive_common_callbacks.h" |
| |
| namespace base { |
| class AtomicFlag; |
| class SequencedTaskRunner; |
| class Time; |
| } // namespace base |
| |
| namespace google_apis { |
| class StartPageToken; |
| } // namespace google_apis |
| |
| namespace drive { |
| |
| class EventLogger; |
| class JobScheduler; |
| |
| namespace internal { |
| |
| class RootFolderIdLoader; |
| class ChangeList; |
| class ChangeListLoaderObserver; |
| class ChangeListProcessor; |
| class LoaderController; |
| class ResourceMetadata; |
| class StartPageTokenLoader; |
| |
| // ChangeListLoader is used to load the change list, the full resource list, |
| // and directory contents, from 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(EventLogger* logger, |
| base::SequencedTaskRunner* blocking_task_runner, |
| ResourceMetadata* resource_metadata, |
| JobScheduler* scheduler, |
| RootFolderIdLoader* root_folder_id_loader, |
| StartPageTokenLoader* start_page_token_loader, |
| LoaderController* apply_task_controller, |
| const std::string& team_drive_id, |
| const base::FilePath& root_entry_path); |
| ~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 if needed. If the locally stored metadata is |
| // available, runs |callback| immediately and starts checking server for |
| // updates in background. If the locally stored metadata is not available, |
| // starts loading from the server, and runs |callback| to tell the result to |
| // the caller when it is finished. |
| // |
| // |callback| must not be null. |
| void LoadIfNeeded(const FileOperationCallback& callback); |
| |
| private: |
| // Starts the resource metadata loading and calls |callback| when it's done. |
| void Load(const FileOperationCallback& callback); |
| void LoadAfterGetLocalStartPageToken( |
| bool is_initial_load, |
| const std::string* local_start_page_token, |
| FileError error); |
| void LoadAfterGetRootFolderId(const std::string& local_start_page_token, |
| FileError error, |
| base::Optional<std::string> root_folder_id); |
| |
| void LoadAfterGetStartPageToken( |
| const std::string& local_start_page_token, |
| const std::string& root_folder_id, |
| google_apis::DriveApiErrorCode status, |
| std::unique_ptr<google_apis::StartPageToken> start_page_token); |
| |
| // 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); |
| |
| // Called when loading the start page token is completed. |
| void OnStartPageTokenLoaderUpdated( |
| google_apis::DriveApiErrorCode error, |
| std::unique_ptr<google_apis::StartPageToken> start_page_token); |
| |
| // ================= Implementation for change list loading ================= |
| |
| // Part of LoadFromServerIfNeeded(). |
| // Starts loading the change list since |local_start_page_token|, or the full |
| // resource list if |local_start_page_token| is empty. If there's no changes |
| // since then, and there are no new team drives changes to apply from |
| // team_drives_change_lists, finishes early. |
| // TODO(sashab): Currently, team_drives_change_lists always contains all of |
| // the team drives. Update this so team_drives_change_lists is only filled |
| // when the TD flag is newly turned on or local data cleared. crbug.com/829154 |
| void LoadChangeListFromServer(const std::string& remote_start_page_token, |
| const std::string& local_start_page_token, |
| const std::string& root_resource_id); |
| |
| // Part of LoadChangeListFromServer(). |
| // Called when the entire change list is loaded. |
| void LoadChangeListFromServerAfterLoadChangeList( |
| const std::string& start_page_token, |
| const std::string& root_resource_id, |
| bool is_delta_update, |
| FileError error, |
| std::vector<std::unique_ptr<ChangeList>> change_lists); |
| |
| // Part of LoadChangeListFromServer(). |
| // Called when the resource metadata is updated. |
| void LoadChangeListFromServerAfterUpdate( |
| ChangeListProcessor* change_list_processor, |
| bool should_notify_changed_directories, |
| base::Time start_time, |
| FileError error); |
| |
| EventLogger* logger_; // Not owned. |
| scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; |
| std::unique_ptr<base::AtomicFlag> in_shutdown_; |
| ResourceMetadata* resource_metadata_; // Not owned. |
| JobScheduler* scheduler_; // Not owned. |
| RootFolderIdLoader* root_folder_id_loader_; // Not owned. |
| StartPageTokenLoader* start_page_token_loader_; // Not owned. |
| LoaderController* loader_controller_; // Not owned. |
| base::ObserverList<ChangeListLoaderObserver>::Unchecked observers_; |
| std::vector<FileOperationCallback> pending_load_callback_; |
| FileOperationCallback pending_update_check_callback_; |
| |
| // Running feed fetcher. |
| // TODO(slangley): Do not make this stateful by changing the feed_fetcher |
| // to be base::Owned by the callback. |
| std::unique_ptr<FeedFetcher> change_feed_fetcher_; |
| |
| // True if the full resource list is loaded (i.e. the resource metadata is |
| // stored locally). |
| bool loaded_; |
| |
| // The team drive id for the changes being loaded by this change list loader. |
| const std::string team_drive_id_; |
| |
| // The formatted team drive id message used for logging. |
| const std::string team_drive_msg_; |
| |
| // The root entry path for changes being loaded by this change list loader. |
| // Can be a team drive root entry or for the users default corpus will be the |
| // drive root entry. |
| const base::FilePath root_entry_path_; |
| |
| THREAD_CHECKER(thread_checker_); |
| |
| // 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_{this}; |
| DISALLOW_COPY_AND_ASSIGN(ChangeListLoader); |
| }; |
| |
| } // namespace internal |
| } // namespace drive |
| |
| #endif // COMPONENTS_DRIVE_CHROMEOS_CHANGE_LIST_LOADER_H_ |