• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
20 class GURL;
21 
22 namespace base {
23 class ScopedClosureRunner;
24 class SequencedTaskRunner;
25 class Time;
26 }  // namespace base
27 
28 namespace google_apis {
29 class AboutResource;
30 class ResourceList;
31 }  // namespace google_apis
32 
33 namespace drive {
34 
35 class EventLogger;
36 class JobScheduler;
37 class ResourceEntry;
38 
39 namespace internal {
40 
41 class ChangeList;
42 class ChangeListLoaderObserver;
43 class ChangeListProcessor;
44 class DirectoryLoader;
45 class 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.
52 class 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.
77 class 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.
cached_about_resource()84   const google_apis::AboutResource* cached_about_resource() const {
85     return cached_about_resource_.get();
86   }
87 
88   // Gets the about resource from the cache or the server. If the cache is
89   // availlavle, just runs |callback| with the cached about resource. If not,
90   // calls |UpdateAboutResource| passing |callback|.
91   void GetAboutResource(const google_apis::AboutResourceCallback& callback);
92 
93   // Gets the about resource from the server, and caches it if successful. This
94   // function calls JobScheduler::GetAboutResource internally. The cache will be
95   // used in |GetAboutResource|.
96   void UpdateAboutResource(
97       const google_apis::AboutResourceCallback& callback);
98 
99  private:
100   // Part of UpdateAboutResource().
101   // This function should be called when the latest about resource is being
102   // fetched from the server. The retrieved about resoure is cloned, and one is
103   // cached and the other is passed to |callback|.
104   void UpdateAboutResourceAfterGetAbout(
105       const google_apis::AboutResourceCallback& callback,
106       google_apis::GDataErrorCode status,
107       scoped_ptr<google_apis::AboutResource> about_resource);
108 
109   JobScheduler* scheduler_;
110   scoped_ptr<google_apis::AboutResource> cached_about_resource_;
111   base::WeakPtrFactory<AboutResourceLoader> weak_ptr_factory_;
112   DISALLOW_COPY_AND_ASSIGN(AboutResourceLoader);
113 };
114 
115 // ChangeListLoader is used to load the change list, the full resource list,
116 // and directory contents, from WAPI (codename for Documents List API)
117 // or Google Drive API.  The class also updates the resource metadata with
118 // the change list loaded from the server.
119 //
120 // Note that the difference between "resource list" and "change list" is
121 // subtle hence the two words are often used interchangeably. To be precise,
122 // "resource list" refers to metadata from the server when fetching the full
123 // resource metadata, or fetching directory contents, whereas "change list"
124 // refers to metadata from the server when fetching changes (delta).
125 class ChangeListLoader {
126  public:
127   // Resource feed fetcher from the server.
128   class FeedFetcher;
129 
130   ChangeListLoader(EventLogger* logger,
131                    base::SequencedTaskRunner* blocking_task_runner,
132                    ResourceMetadata* resource_metadata,
133                    JobScheduler* scheduler,
134                    AboutResourceLoader* about_resource_loader,
135                    LoaderController* apply_task_controller);
136   ~ChangeListLoader();
137 
138   // Indicates whether there is a request for full resource list or change
139   // list fetching is in flight (i.e. directory contents fetching does not
140   // count).
141   bool IsRefreshing() const;
142 
143   // Adds and removes the observer.
144   void AddObserver(ChangeListLoaderObserver* observer);
145   void RemoveObserver(ChangeListLoaderObserver* observer);
146 
147   // Checks for updates on the server. Does nothing if the change list is now
148   // being loaded or refreshed. |callback| must not be null.
149   // Note: |callback| will be called if the check for updates actually
150   // runs, i.e. it may NOT be called if the checking is ignored.
151   void CheckForUpdates(const FileOperationCallback& callback);
152 
153   // Starts the change list loading if needed. If the locally stored metadata is
154   // available, runs |callback| immediately and starts checking server for
155   // updates in background. If the locally stored metadata is not available,
156   // starts loading from the server, and runs |callback| to tell the result to
157   // the caller when it is finished.
158   //
159   // |callback| must not be null.
160   void LoadIfNeeded(const FileOperationCallback& callback);
161 
162  private:
163   // Starts the resource metadata loading and calls |callback| when it's done.
164   void Load(const FileOperationCallback& callback);
165   void LoadAfterGetLargestChangestamp(bool is_initial_load,
166                                       const int64* local_changestamp,
167                                       FileError error);
168   void LoadAfterGetAboutResource(
169       int64 local_changestamp,
170       google_apis::GDataErrorCode status,
171       scoped_ptr<google_apis::AboutResource> about_resource);
172 
173   // Part of Load().
174   // This function should be called when the change list load is complete.
175   // Flushes the callbacks for change list loading and all directory loading.
176   void OnChangeListLoadComplete(FileError error);
177 
178   // ================= Implementation for change list loading =================
179 
180   // Part of LoadFromServerIfNeeded().
181   // Starts loading the change list since |start_changestamp|, or the full
182   // resource list if |start_changestamp| is zero.
183   void LoadChangeListFromServer(int64 start_changestamp);
184 
185   // Part of LoadChangeListFromServer().
186   // Called when the entire change list is loaded.
187   void LoadChangeListFromServerAfterLoadChangeList(
188       scoped_ptr<google_apis::AboutResource> about_resource,
189       bool is_delta_update,
190       FileError error,
191       ScopedVector<ChangeList> change_lists);
192 
193   // Part of LoadChangeListFromServer().
194   // Called when the resource metadata is updated.
195   void LoadChangeListFromServerAfterUpdate(
196       ChangeListProcessor* change_list_processor,
197       bool should_notify_changed_directories,
198       const base::Time& start_time,
199       FileError error);
200 
201   EventLogger* logger_;  // Not owned.
202   scoped_refptr<base::SequencedTaskRunner> blocking_task_runner_;
203   ResourceMetadata* resource_metadata_;  // Not owned.
204   JobScheduler* scheduler_;  // Not owned.
205   AboutResourceLoader* about_resource_loader_;  // Not owned.
206   LoaderController* loader_controller_;  // Not owned.
207   ObserverList<ChangeListLoaderObserver> observers_;
208   std::vector<FileOperationCallback> pending_load_callback_;
209   FileOperationCallback pending_update_check_callback_;
210 
211   // Running feed fetcher.
212   scoped_ptr<FeedFetcher> change_feed_fetcher_;
213 
214   // True if the full resource list is loaded (i.e. the resource metadata is
215   // stored locally).
216   bool loaded_;
217 
218   // Note: This should remain the last member so it'll be destroyed and
219   // invalidate its weak pointers before any other members are destroyed.
220   base::WeakPtrFactory<ChangeListLoader> weak_ptr_factory_;
221   DISALLOW_COPY_AND_ASSIGN(ChangeListLoader);
222 };
223 
224 }  // namespace internal
225 }  // namespace drive
226 
227 #endif  // CHROME_BROWSER_CHROMEOS_DRIVE_CHANGE_LIST_LOADER_H_
228