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 <string> 9#include <vector> 10 11#include "base/callback.h" 12#include "base/memory/ref_counted.h" 13#include "base/memory/scoped_ptr.h" 14#include "base/memory/scoped_vector.h" 15#include "base/observer_list.h" 16#include "chrome/browser/chromeos/drive/file_errors.h" 17#include "google_apis/drive/drive_common_callbacks.h" 18#include "google_apis/drive/gdata_errorcode.h" 19 20class GURL; 21 22namespace base { 23class ScopedClosureRunner; 24class SequencedTaskRunner; 25class Time; 26} // namespace base 27 28namespace google_apis { 29class AboutResource; 30class ResourceList; 31} // namespace google_apis 32 33namespace drive { 34 35class EventLogger; 36class JobScheduler; 37class ResourceEntry; 38 39namespace internal { 40 41class ChangeList; 42class ChangeListLoaderObserver; 43class ChangeListProcessor; 44class DirectoryLoader; 45class ResourceMetadata; 46 47// Delays execution of tasks as long as more than one lock is alive. 48// Used to ensure that ChangeListLoader does not cause race condition by adding 49// new entries created by sync tasks before they do. 50// All code which may add entries found on the server to the local metadata 51// should use this class. 52class LoaderController { 53 public: 54 LoaderController(); 55 ~LoaderController(); 56 57 // Increments the lock count and returns an object which decrements the count 58 // on its destruction. 59 // While the lock count is positive, tasks will be pending. 60 scoped_ptr<base::ScopedClosureRunner> GetLock(); 61 62 // Runs the task if the lock count is 0, otherwise it will be pending. 63 void ScheduleRun(const base::Closure& task); 64 65 private: 66 // Decrements the lock count. 67 void Unlock(); 68 69 int lock_count_; 70 std::vector<base::Closure> pending_tasks_; 71 72 base::WeakPtrFactory<LoaderController> weak_ptr_factory_; 73 DISALLOW_COPY_AND_ASSIGN(LoaderController); 74}; 75 76// This class is responsible to load AboutResource from the server and cache it. 77class AboutResourceLoader { 78 public: 79 explicit AboutResourceLoader(JobScheduler* scheduler); 80 ~AboutResourceLoader(); 81 82 // Returns the cached about resource. 83 // NULL is returned if the cache is not available. 84 const google_apis::AboutResource* cached_about_resource() const { 85 return cached_about_resource_.get(); 86 } 87 88 // Gets the 'latest' about resource and asynchronously runs |callback|. I.e., 89 // 1) If the last call to UpdateAboutResource call is in-flight, wait for it. 90 // 2) Otherwise, if the resource is cached, just returns the cached value. 91 // 3) If neither of the above hold, queries the API server by calling 92 // |UpdateAboutResource|. 93 void GetAboutResource(const google_apis::AboutResourceCallback& callback); 94 95 // Gets the about resource from the server, and caches it if successful. This 96 // function calls JobScheduler::GetAboutResource internally. The cache will be 97 // used in |GetAboutResource|. 98 void UpdateAboutResource(const google_apis::AboutResourceCallback& callback); 99 100 private: 101 // Part of UpdateAboutResource(). 102 // This function should be called when the latest about resource is being 103 // fetched from the server. The retrieved about resource is cloned, and one is 104 // cached and the other is passed to callbacks associated with |task_id|. 105 void UpdateAboutResourceAfterGetAbout( 106 int task_id, 107 google_apis::GDataErrorCode status, 108 scoped_ptr<google_apis::AboutResource> about_resource); 109 110 JobScheduler* scheduler_; 111 scoped_ptr<google_apis::AboutResource> cached_about_resource_; 112 113 // Identifier to denote the latest UpdateAboutResource call. 114 int current_update_task_id_; 115 // Mapping from each UpdateAboutResource task ID to the corresponding 116 // callbacks. Note that there will be multiple callbacks for a single task 117 // when GetAboutResource is called before the task completes. 118 std::map<int, std::vector<google_apis::AboutResourceCallback> > 119 pending_callbacks_; 120 121 base::WeakPtrFactory<AboutResourceLoader> weak_ptr_factory_; 122 DISALLOW_COPY_AND_ASSIGN(AboutResourceLoader); 123}; 124 125// ChangeListLoader is used to load the change list, the full resource list, 126// and directory contents, from Google Drive API. The class also updates the 127// resource metadata with the change list loaded from the server. 128// 129// Note that the difference between "resource list" and "change list" is 130// subtle hence the two words are often used interchangeably. To be precise, 131// "resource list" refers to metadata from the server when fetching the full 132// resource metadata, or fetching directory contents, whereas "change list" 133// refers to metadata from the server when fetching changes (delta). 134class ChangeListLoader { 135 public: 136 // Resource feed fetcher from the server. 137 class FeedFetcher; 138 139 ChangeListLoader(EventLogger* logger, 140 base::SequencedTaskRunner* blocking_task_runner, 141 ResourceMetadata* resource_metadata, 142 JobScheduler* scheduler, 143 AboutResourceLoader* about_resource_loader, 144 LoaderController* apply_task_controller); 145 ~ChangeListLoader(); 146 147 // Indicates whether there is a request for full resource list or change 148 // list fetching is in flight (i.e. directory contents fetching does not 149 // count). 150 bool IsRefreshing() const; 151 152 // Adds and removes the observer. 153 void AddObserver(ChangeListLoaderObserver* observer); 154 void RemoveObserver(ChangeListLoaderObserver* observer); 155 156 // Checks for updates on the server. Does nothing if the change list is now 157 // being loaded or refreshed. |callback| must not be null. 158 // Note: |callback| will be called if the check for updates actually 159 // runs, i.e. it may NOT be called if the checking is ignored. 160 void CheckForUpdates(const FileOperationCallback& callback); 161 162 // Starts the change list loading if needed. If the locally stored metadata is 163 // available, runs |callback| immediately and starts checking server for 164 // updates in background. If the locally stored metadata is not available, 165 // starts loading from the server, and runs |callback| to tell the result to 166 // the caller when it is finished. 167 // 168 // |callback| must not be null. 169 void LoadIfNeeded(const FileOperationCallback& callback); 170 171 private: 172 // Starts the resource metadata loading and calls |callback| when it's done. 173 void Load(const FileOperationCallback& callback); 174 void LoadAfterGetLargestChangestamp(bool is_initial_load, 175 const int64* local_changestamp, 176 FileError error); 177 void LoadAfterGetAboutResource( 178 int64 local_changestamp, 179 google_apis::GDataErrorCode status, 180 scoped_ptr<google_apis::AboutResource> about_resource); 181 182 // Part of Load(). 183 // This function should be called when the change list load is complete. 184 // Flushes the callbacks for change list loading and all directory loading. 185 void OnChangeListLoadComplete(FileError error); 186 187 // Called when the loading about_resource_loader_->UpdateAboutResource is 188 // completed. 189 void OnAboutResourceUpdated(google_apis::GDataErrorCode error, 190 scoped_ptr<google_apis::AboutResource> resource); 191 192 // ================= Implementation for change list loading ================= 193 194 // Part of LoadFromServerIfNeeded(). 195 // Starts loading the change list since |start_changestamp|, or the full 196 // resource list if |start_changestamp| is zero. 197 void LoadChangeListFromServer(int64 start_changestamp); 198 199 // Part of LoadChangeListFromServer(). 200 // Called when the entire change list is loaded. 201 void LoadChangeListFromServerAfterLoadChangeList( 202 scoped_ptr<google_apis::AboutResource> about_resource, 203 bool is_delta_update, 204 FileError error, 205 ScopedVector<ChangeList> change_lists); 206 207 // Part of LoadChangeListFromServer(). 208 // Called when the resource metadata is updated. 209 void LoadChangeListFromServerAfterUpdate( 210 ChangeListProcessor* change_list_processor, 211 bool should_notify_changed_directories, 212 const base::Time& start_time, 213 FileError error); 214 215 EventLogger* logger_; // Not owned. 216 scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_; 217 ResourceMetadata* resource_metadata_; // Not owned. 218 JobScheduler* scheduler_; // Not owned. 219 AboutResourceLoader* about_resource_loader_; // Not owned. 220 LoaderController* loader_controller_; // Not owned. 221 ObserverList<ChangeListLoaderObserver> observers_; 222 std::vector<FileOperationCallback> pending_load_callback_; 223 FileOperationCallback pending_update_check_callback_; 224 225 // Running feed fetcher. 226 scoped_ptr<FeedFetcher> change_feed_fetcher_; 227 228 // True if the full resource list is loaded (i.e. the resource metadata is 229 // stored locally). 230 bool loaded_; 231 232 // Note: This should remain the last member so it'll be destroyed and 233 // invalidate its weak pointers before any other members are destroyed. 234 base::WeakPtrFactory<ChangeListLoader> weak_ptr_factory_; 235 DISALLOW_COPY_AND_ASSIGN(ChangeListLoader); 236}; 237 238} // namespace internal 239} // namespace drive 240 241#endif // CHROME_BROWSER_CHROMEOS_DRIVE_CHANGE_LIST_LOADER_H_ 242