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_JOB_SCHEDULER_H_
6 #define CHROME_BROWSER_CHROMEOS_DRIVE_JOB_SCHEDULER_H_
10 #include "base/id_map.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/observer_list.h"
13 #include "chrome/browser/chromeos/drive/job_list.h"
14 #include "chrome/browser/chromeos/drive/job_queue.h"
15 #include "chrome/browser/drive/drive_service_interface.h"
16 #include "chrome/browser/drive/drive_uploader.h"
17 #include "net/base/network_change_notifier.h"
22 class SeqencedTaskRunner;
29 // Priority of a job. Higher values are lower priority.
33 // Indicates the number of values of this enum.
37 struct ClientContext {
38 explicit ClientContext(ContextType in_type) : type(in_type) {}
42 // The JobScheduler is responsible for queuing and scheduling drive jobs.
43 // Because jobs are executed concurrently by priority and retried for network
44 // failures, there is no guarantee of orderings.
46 // Jobs are grouped into two priority levels:
47 // - USER_INITIATED jobs are those occur as a result of direct user actions.
48 // - BACKGROUND jobs runs in response to state changes, server actions, etc.
49 // USER_INITIATED jobs must be handled immediately, thus have higher priority.
50 // BACKGROUND jobs run only after all USER_INITIATED jobs have run.
52 // Orthogonally, jobs are grouped into two types:
53 // - "File jobs" transfer the contents of files.
54 // - "Metadata jobs" operates on file metadata or the directory structure.
55 // On WiFi or Ethernet connections, all types of jobs just run.
56 // On mobile connections (2G/3G/4G), we don't want large background traffic.
57 // USER_INITIATED jobs or metadata jobs will run. BACKGROUND file jobs wait
58 // in the queue until the network type changes.
59 // On offline case, no jobs run. USER_INITIATED jobs fail immediately.
60 // BACKGROUND jobs stay in the queue and wait for network connection.
62 : public net::NetworkChangeNotifier::ConnectionTypeObserver,
63 public JobListInterface {
65 JobScheduler(PrefService* pref_service,
67 DriveServiceInterface* drive_service,
68 base::SequencedTaskRunner* blocking_task_runner);
69 virtual ~JobScheduler();
71 // JobListInterface overrides.
72 virtual std::vector<JobInfo> GetJobInfoList() OVERRIDE;
73 virtual void AddObserver(JobListObserver* observer) OVERRIDE;
74 virtual void RemoveObserver(JobListObserver* observer) OVERRIDE;
75 virtual void CancelJob(JobID job_id) OVERRIDE;
76 virtual void CancelAllJobs() OVERRIDE;
78 // Adds a GetAppList operation to the queue.
79 // |callback| must not be null.
80 void GetAppList(const google_apis::AppListCallback& callback);
82 // Adds a GetAboutResource operation to the queue.
83 // |callback| must not be null.
84 void GetAboutResource(const google_apis::AboutResourceCallback& callback);
86 // Adds a GetAllResourceList operation to the queue.
87 // |callback| must not be null.
88 void GetAllResourceList(const google_apis::GetResourceListCallback& callback);
90 // Adds a GetResourceListInDirectory operation to the queue.
91 // |callback| must not be null.
92 void GetResourceListInDirectory(
93 const std::string& directory_resource_id,
94 const google_apis::GetResourceListCallback& callback);
96 // Adds a Search operation to the queue.
97 // |callback| must not be null.
98 void Search(const std::string& search_query,
99 const google_apis::GetResourceListCallback& callback);
101 // Adds a GetChangeList operation to the queue.
102 // |callback| must not be null.
103 void GetChangeList(int64 start_changestamp,
104 const google_apis::GetResourceListCallback& callback);
106 // Adds GetRemainingChangeList operation to the queue.
107 // |callback| must not be null.
108 void GetRemainingChangeList(
109 const GURL& next_link,
110 const google_apis::GetResourceListCallback& callback);
112 // Adds GetRemainingFileList operation to the queue.
113 // |callback| must not be null.
114 void GetRemainingFileList(
115 const GURL& next_link,
116 const google_apis::GetResourceListCallback& callback);
118 // Adds a GetResourceEntry operation to the queue.
119 void GetResourceEntry(const std::string& resource_id,
120 const ClientContext& context,
121 const google_apis::GetResourceEntryCallback& callback);
123 // Adds a GetShareUrl operation to the queue.
124 void GetShareUrl(const std::string& resource_id,
125 const GURL& embed_origin,
126 const ClientContext& context,
127 const google_apis::GetShareUrlCallback& callback);
129 // Adds a TrashResource operation to the queue.
130 void TrashResource(const std::string& resource_id,
131 const ClientContext& context,
132 const google_apis::EntryActionCallback& callback);
134 // Adds a CopyResource operation to the queue.
136 const std::string& resource_id,
137 const std::string& parent_resource_id,
138 const std::string& new_title,
139 const base::Time& last_modified,
140 const google_apis::GetResourceEntryCallback& callback);
142 // Adds a UpdateResource operation to the queue.
144 const std::string& resource_id,
145 const std::string& parent_resource_id,
146 const std::string& new_title,
147 const base::Time& last_modified,
148 const base::Time& last_viewed_by_me,
149 const ClientContext& context,
150 const google_apis::GetResourceEntryCallback& callback);
152 // Adds a RenameResource operation to the queue.
153 void RenameResource(const std::string& resource_id,
154 const std::string& new_title,
155 const google_apis::EntryActionCallback& callback);
157 // Adds a AddResourceToDirectory operation to the queue.
158 void AddResourceToDirectory(const std::string& parent_resource_id,
159 const std::string& resource_id,
160 const google_apis::EntryActionCallback& callback);
162 // Adds a RemoveResourceFromDirectory operation to the queue.
163 void RemoveResourceFromDirectory(
164 const std::string& parent_resource_id,
165 const std::string& resource_id,
166 const ClientContext& context,
167 const google_apis::EntryActionCallback& callback);
169 // Adds a AddNewDirectory operation to the queue.
170 void AddNewDirectory(
171 const std::string& parent_resource_id,
172 const std::string& directory_title,
173 const DriveServiceInterface::AddNewDirectoryOptions& options,
174 const ClientContext& context,
175 const google_apis::GetResourceEntryCallback& callback);
177 // Adds a DownloadFile operation to the queue.
178 // The first two arguments |virtual_path| and |expected_file_size| are used
179 // only for filling JobInfo for the operation so that observers can get the
180 // detail. The actual operation never refers these values.
182 const base::FilePath& virtual_path,
183 int64 expected_file_size,
184 const base::FilePath& local_cache_path,
185 const std::string& resource_id,
186 const ClientContext& context,
187 const google_apis::DownloadActionCallback& download_action_callback,
188 const google_apis::GetContentCallback& get_content_callback);
190 // Adds an UploadNewFile operation to the queue.
191 void UploadNewFile(const std::string& parent_resource_id,
192 const base::FilePath& drive_file_path,
193 const base::FilePath& local_file_path,
194 const std::string& title,
195 const std::string& content_type,
196 const DriveUploader::UploadNewFileOptions& options,
197 const ClientContext& context,
198 const google_apis::GetResourceEntryCallback& callback);
200 // Adds an UploadExistingFile operation to the queue.
201 void UploadExistingFile(
202 const std::string& resource_id,
203 const base::FilePath& drive_file_path,
204 const base::FilePath& local_file_path,
205 const std::string& content_type,
206 const DriveUploader::UploadExistingFileOptions& options,
207 const ClientContext& context,
208 const google_apis::GetResourceEntryCallback& callback);
210 // Adds AddPermission operation to the queue. |callback| must not be null.
211 void AddPermission(const std::string& resource_id,
212 const std::string& email,
213 google_apis::drive::PermissionRole role,
214 const google_apis::EntryActionCallback& callback);
217 friend class JobSchedulerTest;
225 static const int kMaxJobCount[NUM_QUEUES];
227 // Represents a single entry in the job map.
229 explicit JobEntry(JobType type);
232 // General user-visible information on the job.
235 // Context of the job.
236 ClientContext context;
238 // The number of times the jobs is retried due to server errors.
241 // The callback to start the job. Called each time it is retry.
242 base::Callback<google_apis::CancelCallback()> task;
244 // The callback to cancel the running job. It is returned from task.Run().
245 google_apis::CancelCallback cancel_callback;
247 // The callback to notify an error to the client of JobScheduler.
248 // This is used to notify cancel of a job that is not running yet.
249 base::Callback<void(google_apis::GDataErrorCode)> abort_callback;
252 // Parameters for DriveUploader::ResumeUploadFile.
253 struct ResumeUploadParams;
255 // Creates a new job and add it to the job map.
256 JobEntry* CreateNewJob(JobType type);
258 // Adds the specified job to the queue and starts the job loop for the queue
260 void StartJob(JobEntry* job);
262 // Adds the specified job to the queue.
263 void QueueJob(JobID job_id);
265 // Determines the next job that should run, and starts it.
266 void DoJobLoop(QueueType queue_type);
268 // Returns the lowest acceptable priority level of the operations that is
269 // currently allowed to start for the |queue_type|.
270 int GetCurrentAcceptedPriority(QueueType queue_type);
272 // Updates |wait_until_| to throttle requests.
275 // Retries the job if needed and returns false. Otherwise returns true.
276 bool OnJobDone(JobID job_id, google_apis::GDataErrorCode error);
278 // Callback for job finishing with a GetResourceListCallback.
279 void OnGetResourceListJobDone(
281 const google_apis::GetResourceListCallback& callback,
282 google_apis::GDataErrorCode error,
283 scoped_ptr<google_apis::ResourceList> resource_list);
285 // Callback for job finishing with a GetResourceEntryCallback.
286 void OnGetResourceEntryJobDone(
288 const google_apis::GetResourceEntryCallback& callback,
289 google_apis::GDataErrorCode error,
290 scoped_ptr<google_apis::ResourceEntry> entry);
292 // Callback for job finishing with a AboutResourceCallback.
293 void OnGetAboutResourceJobDone(
295 const google_apis::AboutResourceCallback& callback,
296 google_apis::GDataErrorCode error,
297 scoped_ptr<google_apis::AboutResource> about_resource);
299 // Callback for job finishing with a GetShareUrlCallback.
300 void OnGetShareUrlJobDone(
302 const google_apis::GetShareUrlCallback& callback,
303 google_apis::GDataErrorCode error,
304 const GURL& share_url);
306 // Callback for job finishing with a AppListCallback.
307 void OnGetAppListJobDone(
309 const google_apis::AppListCallback& callback,
310 google_apis::GDataErrorCode error,
311 scoped_ptr<google_apis::AppList> app_list);
313 // Callback for job finishing with a EntryActionCallback.
314 void OnEntryActionJobDone(JobID job_id,
315 const google_apis::EntryActionCallback& callback,
316 google_apis::GDataErrorCode error);
318 // Callback for job finishing with a DownloadActionCallback.
319 void OnDownloadActionJobDone(
321 const google_apis::DownloadActionCallback& callback,
322 google_apis::GDataErrorCode error,
323 const base::FilePath& temp_file);
325 // Callback for job finishing with a UploadCompletionCallback.
326 void OnUploadCompletionJobDone(
328 const ResumeUploadParams& resume_params,
329 const google_apis::GetResourceEntryCallback& callback,
330 google_apis::GDataErrorCode error,
331 const GURL& upload_location,
332 scoped_ptr<google_apis::ResourceEntry> resource_entry);
334 // Callback for DriveUploader::ResumeUploadFile().
335 void OnResumeUploadFileDone(
337 const base::Callback<google_apis::CancelCallback()>& original_task,
338 const google_apis::GetResourceEntryCallback& callback,
339 google_apis::GDataErrorCode error,
340 const GURL& upload_location,
341 scoped_ptr<google_apis::ResourceEntry> resource_entry);
343 // Updates the progress status of the specified job.
344 void UpdateProgress(JobID job_id, int64 progress, int64 total);
346 // net::NetworkChangeNotifier::ConnectionTypeObserver override.
347 virtual void OnConnectionTypeChanged(
348 net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
350 // Get the type of queue the specified job should be put in.
351 QueueType GetJobQueueType(JobType type);
353 // For testing only. Disables throttling so that testing is faster.
354 void SetDisableThrottling(bool disable) { disable_throttling_ = disable; }
356 // Aborts a job which is not in STATE_RUNNING.
357 void AbortNotRunningJob(JobEntry* job, google_apis::GDataErrorCode error);
359 // Notifies updates to observers.
360 void NotifyJobAdded(const JobInfo& job_info);
361 void NotifyJobDone(const JobInfo& job_info,
362 google_apis::GDataErrorCode error);
363 void NotifyJobUpdated(const JobInfo& job_info);
365 // Gets information of the queue of the given type as string.
366 std::string GetQueueInfo(QueueType type) const;
368 // Returns a string representation of QueueType.
369 static std::string QueueTypeToString(QueueType type);
371 // The number of times operations have failed in a row, capped at
372 // kMaxThrottleCount. This is used to calculate the delay before running the
376 // Jobs should not start running until this time. Used for throttling.
377 base::Time wait_until_;
379 // Disables throttling for testing.
380 bool disable_throttling_;
382 // The queues of jobs.
383 scoped_ptr<JobQueue> queue_[NUM_QUEUES];
385 // The list of queued job info indexed by job IDs.
386 typedef IDMap<JobEntry, IDMapOwnPointer> JobIDMap;
389 // The list of observers for the scheduler.
390 ObserverList<JobListObserver> observer_list_;
392 EventLogger* logger_;
393 DriveServiceInterface* drive_service_;
394 scoped_ptr<DriveUploaderInterface> uploader_;
396 PrefService* pref_service_;
398 // Note: This should remain the last member so it'll be destroyed and
399 // invalidate its weak pointers before any other members are destroyed.
400 base::WeakPtrFactory<JobScheduler> weak_ptr_factory_;
401 DISALLOW_COPY_AND_ASSIGN(JobScheduler);
406 #endif // CHROME_BROWSER_CHROMEOS_DRIVE_JOB_SCHEDULER_H_