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/file_system_interface.h"
14 #include "chrome/browser/chromeos/drive/job_list.h"
15 #include "chrome/browser/chromeos/drive/job_queue.h"
16 #include "chrome/browser/drive/drive_service_interface.h"
17 #include "chrome/browser/drive/drive_uploader.h"
18 #include "net/base/network_change_notifier.h"
23 class SeqencedTaskRunner;
30 // The JobScheduler is responsible for queuing and scheduling drive jobs.
31 // Because jobs are executed concurrently by priority and retried for network
32 // failures, there is no guarantee of orderings.
34 // Jobs are grouped into two priority levels:
35 // - USER_INITIATED jobs are those occur as a result of direct user actions.
36 // - BACKGROUND jobs runs in response to state changes, server actions, etc.
37 // USER_INITIATED jobs must be handled immediately, thus have higher priority.
38 // BACKGROUND jobs run only after all USER_INITIATED jobs have run.
40 // Orthogonally, jobs are grouped into two types:
41 // - "File jobs" transfer the contents of files.
42 // - "Metadata jobs" operates on file metadata or the directory structure.
43 // On WiFi or Ethernet connections, all types of jobs just run.
44 // On mobile connections (2G/3G/4G), we don't want large background traffic.
45 // USER_INITIATED jobs or metadata jobs will run. BACKGROUND file jobs wait
46 // in the queue until the network type changes.
47 // On offline case, no jobs run. USER_INITIATED jobs fail immediately.
48 // BACKGROUND jobs stay in the queue and wait for network connection.
50 : public net::NetworkChangeNotifier::ConnectionTypeObserver,
51 public JobListInterface {
53 JobScheduler(PrefService* pref_service,
55 DriveServiceInterface* drive_service,
56 base::SequencedTaskRunner* blocking_task_runner);
57 virtual ~JobScheduler();
59 // JobListInterface overrides.
60 virtual std::vector<JobInfo> GetJobInfoList() OVERRIDE;
61 virtual void AddObserver(JobListObserver* observer) OVERRIDE;
62 virtual void RemoveObserver(JobListObserver* observer) OVERRIDE;
63 virtual void CancelJob(JobID job_id) OVERRIDE;
64 virtual void CancelAllJobs() OVERRIDE;
66 // Adds a GetAppList operation to the queue.
67 // |callback| must not be null.
68 void GetAppList(const google_apis::AppListCallback& callback);
70 // Adds a GetAboutResource operation to the queue.
71 // |callback| must not be null.
72 void GetAboutResource(const google_apis::AboutResourceCallback& callback);
74 // Adds a GetAllResourceList operation to the queue.
75 // |callback| must not be null.
76 void GetAllResourceList(const google_apis::GetResourceListCallback& callback);
78 // Adds a GetResourceListInDirectory operation to the queue.
79 // |callback| must not be null.
80 void GetResourceListInDirectory(
81 const std::string& directory_resource_id,
82 const google_apis::GetResourceListCallback& callback);
84 // Adds a Search operation to the queue.
85 // |callback| must not be null.
86 void Search(const std::string& search_query,
87 const google_apis::GetResourceListCallback& callback);
89 // Adds a GetChangeList operation to the queue.
90 // |callback| must not be null.
91 void GetChangeList(int64 start_changestamp,
92 const google_apis::GetResourceListCallback& callback);
94 // Adds GetRemainingChangeList operation to the queue.
95 // |callback| must not be null.
96 void GetRemainingChangeList(
97 const GURL& next_link,
98 const google_apis::GetResourceListCallback& callback);
100 // Adds GetRemainingFileList operation to the queue.
101 // |callback| must not be null.
102 void GetRemainingFileList(
103 const GURL& next_link,
104 const google_apis::GetResourceListCallback& callback);
106 // Adds a GetResourceEntry operation to the queue.
107 void GetResourceEntry(const std::string& resource_id,
108 const ClientContext& context,
109 const google_apis::GetResourceEntryCallback& callback);
111 // Adds a GetShareUrl operation to the queue.
112 void GetShareUrl(const std::string& resource_id,
113 const GURL& embed_origin,
114 const ClientContext& context,
115 const google_apis::GetShareUrlCallback& callback);
117 // Adds a TrashResource operation to the queue.
118 void TrashResource(const std::string& resource_id,
119 const ClientContext& context,
120 const google_apis::EntryActionCallback& callback);
122 // Adds a CopyResource operation to the queue.
124 const std::string& resource_id,
125 const std::string& parent_resource_id,
126 const std::string& new_title,
127 const base::Time& last_modified,
128 const google_apis::GetResourceEntryCallback& callback);
130 // Adds a UpdateResource operation to the queue.
132 const std::string& resource_id,
133 const std::string& parent_resource_id,
134 const std::string& new_title,
135 const base::Time& last_modified,
136 const base::Time& last_viewed_by_me,
137 const ClientContext& context,
138 const google_apis::GetResourceEntryCallback& callback);
140 // Adds a RenameResource operation to the queue.
141 void RenameResource(const std::string& resource_id,
142 const std::string& new_title,
143 const google_apis::EntryActionCallback& callback);
145 // Adds a AddResourceToDirectory operation to the queue.
146 void AddResourceToDirectory(const std::string& parent_resource_id,
147 const std::string& resource_id,
148 const google_apis::EntryActionCallback& callback);
150 // Adds a RemoveResourceFromDirectory operation to the queue.
151 void RemoveResourceFromDirectory(
152 const std::string& parent_resource_id,
153 const std::string& resource_id,
154 const ClientContext& context,
155 const google_apis::EntryActionCallback& callback);
157 // Adds a AddNewDirectory operation to the queue.
158 void AddNewDirectory(
159 const std::string& parent_resource_id,
160 const std::string& directory_title,
161 const DriveServiceInterface::AddNewDirectoryOptions& options,
162 const ClientContext& context,
163 const google_apis::GetResourceEntryCallback& callback);
165 // Adds a DownloadFile operation to the queue.
166 // The first two arguments |virtual_path| and |expected_file_size| are used
167 // only for filling JobInfo for the operation so that observers can get the
168 // detail. The actual operation never refers these values.
170 const base::FilePath& virtual_path,
171 int64 expected_file_size,
172 const base::FilePath& local_cache_path,
173 const std::string& resource_id,
174 const ClientContext& context,
175 const google_apis::DownloadActionCallback& download_action_callback,
176 const google_apis::GetContentCallback& get_content_callback);
178 // Adds an UploadNewFile operation to the queue.
179 void UploadNewFile(const std::string& parent_resource_id,
180 const base::FilePath& drive_file_path,
181 const base::FilePath& local_file_path,
182 const std::string& title,
183 const std::string& content_type,
184 const DriveUploader::UploadNewFileOptions& options,
185 const ClientContext& context,
186 const google_apis::GetResourceEntryCallback& callback);
188 // Adds an UploadExistingFile operation to the queue.
189 void UploadExistingFile(
190 const std::string& resource_id,
191 const base::FilePath& drive_file_path,
192 const base::FilePath& local_file_path,
193 const std::string& content_type,
194 const DriveUploader::UploadExistingFileOptions& options,
195 const ClientContext& context,
196 const google_apis::GetResourceEntryCallback& callback);
198 // Adds a GetResourceListInDirectoryByWapi operation to the queue.
199 // |callback| must not be null.
200 void GetResourceListInDirectoryByWapi(
201 const std::string& directory_resource_id,
202 const google_apis::GetResourceListCallback& callback);
204 // Adds GetRemainingResourceList operation to the queue.
205 // |callback| must not be null.
206 void GetRemainingResourceList(
207 const GURL& next_link,
208 const google_apis::GetResourceListCallback& callback);
211 friend class JobSchedulerTest;
219 static const int kMaxJobCount[NUM_QUEUES];
221 // Represents a single entry in the job map.
223 explicit JobEntry(JobType type);
226 // General user-visible information on the job.
229 // Context of the job.
230 ClientContext context;
232 // The number of times the jobs is retried due to server errors.
235 // The callback to start the job. Called each time it is retry.
236 base::Callback<google_apis::CancelCallback()> task;
238 // The callback to cancel the running job. It is returned from task.Run().
239 google_apis::CancelCallback cancel_callback;
241 // The callback to notify an error to the client of JobScheduler.
242 // This is used to notify cancel of a job that is not running yet.
243 base::Callback<void(google_apis::GDataErrorCode)> abort_callback;
246 // Parameters for DriveUploader::ResumeUploadFile.
247 struct ResumeUploadParams;
249 // Creates a new job and add it to the job map.
250 JobEntry* CreateNewJob(JobType type);
252 // Adds the specified job to the queue and starts the job loop for the queue
254 void StartJob(JobEntry* job);
256 // Adds the specified job to the queue.
257 void QueueJob(JobID job_id);
259 // Determines the next job that should run, and starts it.
260 void DoJobLoop(QueueType queue_type);
262 // Returns the lowest acceptable priority level of the operations that is
263 // currently allowed to start for the |queue_type|.
264 int GetCurrentAcceptedPriority(QueueType queue_type);
266 // Updates |wait_until_| to throttle requests.
269 // Retries the job if needed and returns false. Otherwise returns true.
270 bool OnJobDone(JobID job_id, google_apis::GDataErrorCode error);
272 // Callback for job finishing with a GetResourceListCallback.
273 void OnGetResourceListJobDone(
275 const google_apis::GetResourceListCallback& callback,
276 google_apis::GDataErrorCode error,
277 scoped_ptr<google_apis::ResourceList> resource_list);
279 // Callback for job finishing with a GetResourceEntryCallback.
280 void OnGetResourceEntryJobDone(
282 const google_apis::GetResourceEntryCallback& callback,
283 google_apis::GDataErrorCode error,
284 scoped_ptr<google_apis::ResourceEntry> entry);
286 // Callback for job finishing with a AboutResourceCallback.
287 void OnGetAboutResourceJobDone(
289 const google_apis::AboutResourceCallback& callback,
290 google_apis::GDataErrorCode error,
291 scoped_ptr<google_apis::AboutResource> about_resource);
293 // Callback for job finishing with a GetShareUrlCallback.
294 void OnGetShareUrlJobDone(
296 const google_apis::GetShareUrlCallback& callback,
297 google_apis::GDataErrorCode error,
298 const GURL& share_url);
300 // Callback for job finishing with a AppListCallback.
301 void OnGetAppListJobDone(
303 const google_apis::AppListCallback& callback,
304 google_apis::GDataErrorCode error,
305 scoped_ptr<google_apis::AppList> app_list);
307 // Callback for job finishing with a EntryActionCallback.
308 void OnEntryActionJobDone(JobID job_id,
309 const google_apis::EntryActionCallback& callback,
310 google_apis::GDataErrorCode error);
312 // Callback for job finishing with a DownloadActionCallback.
313 void OnDownloadActionJobDone(
315 const google_apis::DownloadActionCallback& callback,
316 google_apis::GDataErrorCode error,
317 const base::FilePath& temp_file);
319 // Callback for job finishing with a UploadCompletionCallback.
320 void OnUploadCompletionJobDone(
322 const ResumeUploadParams& resume_params,
323 const google_apis::GetResourceEntryCallback& callback,
324 google_apis::GDataErrorCode error,
325 const GURL& upload_location,
326 scoped_ptr<google_apis::ResourceEntry> resource_entry);
328 // Callback for DriveUploader::ResumeUploadFile().
329 void OnResumeUploadFileDone(
331 const base::Callback<google_apis::CancelCallback()>& original_task,
332 const google_apis::GetResourceEntryCallback& callback,
333 google_apis::GDataErrorCode error,
334 const GURL& upload_location,
335 scoped_ptr<google_apis::ResourceEntry> resource_entry);
337 // Updates the progress status of the specified job.
338 void UpdateProgress(JobID job_id, int64 progress, int64 total);
340 // net::NetworkChangeNotifier::ConnectionTypeObserver override.
341 virtual void OnConnectionTypeChanged(
342 net::NetworkChangeNotifier::ConnectionType type) OVERRIDE;
344 // Get the type of queue the specified job should be put in.
345 QueueType GetJobQueueType(JobType type);
347 // For testing only. Disables throttling so that testing is faster.
348 void SetDisableThrottling(bool disable) { disable_throttling_ = disable; }
350 // Aborts a job which is not in STATE_RUNNING.
351 void AbortNotRunningJob(JobEntry* job, google_apis::GDataErrorCode error);
353 // Notifies updates to observers.
354 void NotifyJobAdded(const JobInfo& job_info);
355 void NotifyJobDone(const JobInfo& job_info,
356 google_apis::GDataErrorCode error);
357 void NotifyJobUpdated(const JobInfo& job_info);
359 // Gets information of the queue of the given type as string.
360 std::string GetQueueInfo(QueueType type) const;
362 // Returns a string representation of QueueType.
363 static std::string QueueTypeToString(QueueType type);
365 // The number of times operations have failed in a row, capped at
366 // kMaxThrottleCount. This is used to calculate the delay before running the
370 // Jobs should not start running until this time. Used for throttling.
371 base::Time wait_until_;
373 // Disables throttling for testing.
374 bool disable_throttling_;
376 // The queues of jobs.
377 scoped_ptr<JobQueue> queue_[NUM_QUEUES];
379 // The list of queued job info indexed by job IDs.
380 typedef IDMap<JobEntry, IDMapOwnPointer> JobIDMap;
383 // The list of observers for the scheduler.
384 ObserverList<JobListObserver> observer_list_;
386 EventLogger* logger_;
387 DriveServiceInterface* drive_service_;
388 scoped_ptr<DriveUploaderInterface> uploader_;
390 PrefService* pref_service_;
392 // Note: This should remain the last member so it'll be destroyed and
393 // invalidate its weak pointers before any other members are destroyed.
394 base::WeakPtrFactory<JobScheduler> weak_ptr_factory_;
395 DISALLOW_COPY_AND_ASSIGN(JobScheduler);
400 #endif // CHROME_BROWSER_CHROMEOS_DRIVE_JOB_SCHEDULER_H_