| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/chromeos/drive/drive_scheduler.h" | 5 #include "chrome/browser/chromeos/drive/drive_scheduler.h" |
| 6 | 6 |
| 7 #include <math.h> | 7 #include <math.h> |
| 8 | 8 |
| 9 #include "base/message_loop.h" | 9 #include "base/message_loop.h" |
| 10 #include "base/prefs/pref_service.h" | 10 #include "base/prefs/pref_service.h" |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 48 const DriveScheduler::QueueEntry* left, | 48 const DriveScheduler::QueueEntry* left, |
| 49 const DriveScheduler::QueueEntry* right) { | 49 const DriveScheduler::QueueEntry* right) { |
| 50 return (right->context.type == BACKGROUND && | 50 return (right->context.type == BACKGROUND && |
| 51 left->context.type != BACKGROUND); | 51 left->context.type != BACKGROUND); |
| 52 } | 52 } |
| 53 | 53 |
| 54 DriveScheduler::DriveScheduler( | 54 DriveScheduler::DriveScheduler( |
| 55 Profile* profile, | 55 Profile* profile, |
| 56 google_apis::DriveServiceInterface* drive_service, | 56 google_apis::DriveServiceInterface* drive_service, |
| 57 google_apis::DriveUploaderInterface* uploader) | 57 google_apis::DriveUploaderInterface* uploader) |
| 58 : job_loop_is_running_(false), | 58 : next_job_id_(0), |
| 59 next_job_id_(0), | |
| 60 throttle_count_(0), | 59 throttle_count_(0), |
| 61 disable_throttling_(false), | 60 disable_throttling_(false), |
| 62 drive_service_(drive_service), | 61 drive_service_(drive_service), |
| 63 uploader_(uploader), | 62 uploader_(uploader), |
| 64 profile_(profile), | 63 profile_(profile), |
| 65 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), | 64 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)), |
| 66 initialized_(false) { | 65 initialized_(false) { |
| 67 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 66 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 67 for (int i = 0; i < NUM_QUEUES; ++i) { |
| 68 job_loop_is_running_[i] = false; |
| 69 } |
| 68 } | 70 } |
| 69 | 71 |
| 70 DriveScheduler::~DriveScheduler() { | 72 DriveScheduler::~DriveScheduler() { |
| 71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 73 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 72 DCHECK(initialized_); | 74 DCHECK(initialized_); |
| 73 STLDeleteElements(&queue_); | 75 for (int i = 0; i < NUM_QUEUES; ++i) { |
| 76 STLDeleteElements(&queue_[i]); |
| 77 } |
| 74 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this); | 78 net::NetworkChangeNotifier::RemoveConnectionTypeObserver(this); |
| 75 } | 79 } |
| 76 | 80 |
| 77 void DriveScheduler::Initialize() { | 81 void DriveScheduler::Initialize() { |
| 78 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 82 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 79 | 83 |
| 80 // Initialize() may be called more than once for the lifetime when the | 84 // Initialize() may be called more than once for the lifetime when the |
| 81 // file system is remounted. | 85 // file system is remounted. |
| 82 if (initialized_) | 86 if (initialized_) |
| 83 return; | 87 return; |
| 84 | 88 |
| 85 net::NetworkChangeNotifier::AddConnectionTypeObserver(this); | 89 net::NetworkChangeNotifier::AddConnectionTypeObserver(this); |
| 86 initialized_ = true; | 90 initialized_ = true; |
| 87 } | 91 } |
| 88 | 92 |
| 89 void DriveScheduler::GetAccountMetadata( | 93 void DriveScheduler::GetAccountMetadata( |
| 90 const google_apis::GetAccountMetadataCallback& callback) { | 94 const google_apis::GetAccountMetadataCallback& callback) { |
| 91 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 95 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 92 DCHECK(!callback.is_null()); | 96 DCHECK(!callback.is_null()); |
| 93 | 97 |
| 94 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_GET_ACCOUNT_METADATA)); | 98 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_GET_ACCOUNT_METADATA)); |
| 95 new_job->get_account_metadata_callback = callback; | 99 new_job->get_account_metadata_callback = callback; |
| 96 | 100 |
| 97 QueueJob(new_job.Pass()); | 101 QueueJob(new_job.Pass()); |
| 98 | 102 |
| 99 StartJobLoop(); | 103 StartJobLoop(GetJobQueueType(TYPE_GET_ACCOUNT_METADATA)); |
| 100 } | 104 } |
| 101 | 105 |
| 102 void DriveScheduler::GetAppList( | 106 void DriveScheduler::GetAppList( |
| 103 const google_apis::GetAppListCallback& callback) { | 107 const google_apis::GetAppListCallback& callback) { |
| 104 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 105 DCHECK(!callback.is_null()); | 109 DCHECK(!callback.is_null()); |
| 106 | 110 |
| 107 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_GET_APP_LIST)); | 111 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_GET_APP_LIST)); |
| 108 new_job->get_app_list_callback = callback; | 112 new_job->get_app_list_callback = callback; |
| 109 | 113 |
| 110 QueueJob(new_job.Pass()); | 114 QueueJob(new_job.Pass()); |
| 111 | 115 |
| 112 StartJobLoop(); | 116 StartJobLoop(GetJobQueueType(TYPE_GET_APP_LIST)); |
| 113 } | 117 } |
| 114 | 118 |
| 115 void DriveScheduler::GetResourceList( | 119 void DriveScheduler::GetResourceList( |
| 116 const GURL& feed_url, | 120 const GURL& feed_url, |
| 117 int64 start_changestamp, | 121 int64 start_changestamp, |
| 118 const std::string& search_query, | 122 const std::string& search_query, |
| 119 bool shared_with_me, | 123 bool shared_with_me, |
| 120 const std::string& directory_resource_id, | 124 const std::string& directory_resource_id, |
| 121 const google_apis::GetResourceListCallback& callback) { | 125 const google_apis::GetResourceListCallback& callback) { |
| 122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 123 DCHECK(!callback.is_null()); | 127 DCHECK(!callback.is_null()); |
| 124 | 128 |
| 125 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_GET_RESOURCE_LIST)); | 129 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_GET_RESOURCE_LIST)); |
| 126 new_job->feed_url = feed_url; | 130 new_job->feed_url = feed_url; |
| 127 new_job->start_changestamp = start_changestamp; | 131 new_job->start_changestamp = start_changestamp; |
| 128 new_job->search_query = search_query; | 132 new_job->search_query = search_query; |
| 129 new_job->shared_with_me = shared_with_me; | 133 new_job->shared_with_me = shared_with_me; |
| 130 new_job->directory_resource_id = directory_resource_id; | 134 new_job->directory_resource_id = directory_resource_id; |
| 131 new_job->get_resource_list_callback = callback; | 135 new_job->get_resource_list_callback = callback; |
| 132 | 136 |
| 133 QueueJob(new_job.Pass()); | 137 QueueJob(new_job.Pass()); |
| 134 | 138 |
| 135 StartJobLoop(); | 139 StartJobLoop(GetJobQueueType(TYPE_GET_RESOURCE_LIST)); |
| 136 } | 140 } |
| 137 | 141 |
| 138 void DriveScheduler::GetResourceEntry( | 142 void DriveScheduler::GetResourceEntry( |
| 139 const std::string& resource_id, | 143 const std::string& resource_id, |
| 140 const DriveClientContext& context, | 144 const DriveClientContext& context, |
| 141 const google_apis::GetResourceEntryCallback& callback) { | 145 const google_apis::GetResourceEntryCallback& callback) { |
| 142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 143 DCHECK(!callback.is_null()); | 147 DCHECK(!callback.is_null()); |
| 144 | 148 |
| 145 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_GET_RESOURCE_ENTRY)); | 149 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_GET_RESOURCE_ENTRY)); |
| 146 new_job->resource_id = resource_id; | 150 new_job->resource_id = resource_id; |
| 147 new_job->context = context; | 151 new_job->context = context; |
| 148 new_job->get_resource_entry_callback = callback; | 152 new_job->get_resource_entry_callback = callback; |
| 149 | 153 |
| 150 QueueJob(new_job.Pass()); | 154 QueueJob(new_job.Pass()); |
| 151 | 155 |
| 152 StartJobLoop(); | 156 StartJobLoop(GetJobQueueType(TYPE_GET_RESOURCE_ENTRY)); |
| 153 } | 157 } |
| 154 | 158 |
| 155 void DriveScheduler::DeleteResource( | 159 void DriveScheduler::DeleteResource( |
| 156 const std::string& resource_id, | 160 const std::string& resource_id, |
| 157 const google_apis::EntryActionCallback& callback) { | 161 const google_apis::EntryActionCallback& callback) { |
| 158 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 159 DCHECK(!callback.is_null()); | 163 DCHECK(!callback.is_null()); |
| 160 | 164 |
| 161 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_DELETE_RESOURCE)); | 165 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_DELETE_RESOURCE)); |
| 162 new_job->resource_id = resource_id; | 166 new_job->resource_id = resource_id; |
| 163 new_job->entry_action_callback = callback; | 167 new_job->entry_action_callback = callback; |
| 164 | 168 |
| 165 QueueJob(new_job.Pass()); | 169 QueueJob(new_job.Pass()); |
| 166 | 170 |
| 167 StartJobLoop(); | 171 StartJobLoop(GetJobQueueType(TYPE_DELETE_RESOURCE)); |
| 168 } | 172 } |
| 169 | 173 |
| 170 | 174 |
| 171 void DriveScheduler::CopyHostedDocument( | 175 void DriveScheduler::CopyHostedDocument( |
| 172 const std::string& resource_id, | 176 const std::string& resource_id, |
| 173 const std::string& new_name, | 177 const std::string& new_name, |
| 174 const google_apis::GetResourceEntryCallback& callback) { | 178 const google_apis::GetResourceEntryCallback& callback) { |
| 175 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 179 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 176 DCHECK(!callback.is_null()); | 180 DCHECK(!callback.is_null()); |
| 177 | 181 |
| 178 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_COPY_HOSTED_DOCUMENT)); | 182 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_COPY_HOSTED_DOCUMENT)); |
| 179 new_job->resource_id = resource_id; | 183 new_job->resource_id = resource_id; |
| 180 new_job->new_name = new_name; | 184 new_job->new_name = new_name; |
| 181 new_job->get_resource_entry_callback = callback; | 185 new_job->get_resource_entry_callback = callback; |
| 182 | 186 |
| 183 QueueJob(new_job.Pass()); | 187 QueueJob(new_job.Pass()); |
| 184 | 188 |
| 185 StartJobLoop(); | 189 StartJobLoop(GetJobQueueType(TYPE_COPY_HOSTED_DOCUMENT)); |
| 186 } | 190 } |
| 187 | 191 |
| 188 void DriveScheduler::RenameResource( | 192 void DriveScheduler::RenameResource( |
| 189 const std::string& resource_id, | 193 const std::string& resource_id, |
| 190 const std::string& new_name, | 194 const std::string& new_name, |
| 191 const google_apis::EntryActionCallback& callback) { | 195 const google_apis::EntryActionCallback& callback) { |
| 192 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 196 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 193 DCHECK(!callback.is_null()); | 197 DCHECK(!callback.is_null()); |
| 194 | 198 |
| 195 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_RENAME_RESOURCE)); | 199 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_RENAME_RESOURCE)); |
| 196 new_job->resource_id = resource_id; | 200 new_job->resource_id = resource_id; |
| 197 new_job->new_name = new_name; | 201 new_job->new_name = new_name; |
| 198 new_job->entry_action_callback = callback; | 202 new_job->entry_action_callback = callback; |
| 199 | 203 |
| 200 QueueJob(new_job.Pass()); | 204 QueueJob(new_job.Pass()); |
| 201 | 205 |
| 202 StartJobLoop(); | 206 StartJobLoop(GetJobQueueType(TYPE_RENAME_RESOURCE)); |
| 203 } | 207 } |
| 204 | 208 |
| 205 void DriveScheduler::AddResourceToDirectory( | 209 void DriveScheduler::AddResourceToDirectory( |
| 206 const std::string& parent_resource_id, | 210 const std::string& parent_resource_id, |
| 207 const std::string& resource_id, | 211 const std::string& resource_id, |
| 208 const google_apis::EntryActionCallback& callback) { | 212 const google_apis::EntryActionCallback& callback) { |
| 209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 210 DCHECK(!callback.is_null()); | 214 DCHECK(!callback.is_null()); |
| 211 | 215 |
| 212 scoped_ptr<QueueEntry> new_job( | 216 scoped_ptr<QueueEntry> new_job( |
| 213 new QueueEntry(TYPE_ADD_RESOURCE_TO_DIRECTORY)); | 217 new QueueEntry(TYPE_ADD_RESOURCE_TO_DIRECTORY)); |
| 214 new_job->parent_resource_id = parent_resource_id; | 218 new_job->parent_resource_id = parent_resource_id; |
| 215 new_job->resource_id = resource_id; | 219 new_job->resource_id = resource_id; |
| 216 new_job->entry_action_callback = callback; | 220 new_job->entry_action_callback = callback; |
| 217 | 221 |
| 218 QueueJob(new_job.Pass()); | 222 QueueJob(new_job.Pass()); |
| 219 | 223 |
| 220 StartJobLoop(); | 224 StartJobLoop(GetJobQueueType(TYPE_ADD_RESOURCE_TO_DIRECTORY)); |
| 221 } | 225 } |
| 222 | 226 |
| 223 void DriveScheduler::RemoveResourceFromDirectory( | 227 void DriveScheduler::RemoveResourceFromDirectory( |
| 224 const std::string& parent_resource_id, | 228 const std::string& parent_resource_id, |
| 225 const std::string& resource_id, | 229 const std::string& resource_id, |
| 226 const google_apis::EntryActionCallback& callback) { | 230 const google_apis::EntryActionCallback& callback) { |
| 227 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 231 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 228 | 232 |
| 229 scoped_ptr<QueueEntry> new_job( | 233 scoped_ptr<QueueEntry> new_job( |
| 230 new QueueEntry(TYPE_REMOVE_RESOURCE_FROM_DIRECTORY)); | 234 new QueueEntry(TYPE_REMOVE_RESOURCE_FROM_DIRECTORY)); |
| 231 new_job->parent_resource_id = parent_resource_id; | 235 new_job->parent_resource_id = parent_resource_id; |
| 232 new_job->resource_id = resource_id; | 236 new_job->resource_id = resource_id; |
| 233 new_job->entry_action_callback = callback; | 237 new_job->entry_action_callback = callback; |
| 234 | 238 |
| 235 QueueJob(new_job.Pass()); | 239 QueueJob(new_job.Pass()); |
| 236 | 240 |
| 237 StartJobLoop(); | 241 StartJobLoop(GetJobQueueType(TYPE_REMOVE_RESOURCE_FROM_DIRECTORY)); |
| 238 } | 242 } |
| 239 | 243 |
| 240 void DriveScheduler::AddNewDirectory( | 244 void DriveScheduler::AddNewDirectory( |
| 241 const std::string& parent_resource_id, | 245 const std::string& parent_resource_id, |
| 242 const std::string& directory_name, | 246 const std::string& directory_name, |
| 243 const google_apis::GetResourceEntryCallback& callback) { | 247 const google_apis::GetResourceEntryCallback& callback) { |
| 244 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 248 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 245 | 249 |
| 246 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_ADD_NEW_DIRECTORY)); | 250 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_ADD_NEW_DIRECTORY)); |
| 247 new_job->parent_resource_id = parent_resource_id; | 251 new_job->parent_resource_id = parent_resource_id; |
| 248 new_job->directory_name = directory_name; | 252 new_job->directory_name = directory_name; |
| 249 new_job->get_resource_entry_callback = callback; | 253 new_job->get_resource_entry_callback = callback; |
| 250 | 254 |
| 251 QueueJob(new_job.Pass()); | 255 QueueJob(new_job.Pass()); |
| 252 | 256 |
| 253 StartJobLoop(); | 257 StartJobLoop(GetJobQueueType(TYPE_ADD_NEW_DIRECTORY)); |
| 254 } | 258 } |
| 255 | 259 |
| 256 void DriveScheduler::DownloadFile( | 260 void DriveScheduler::DownloadFile( |
| 257 const base::FilePath& virtual_path, | 261 const base::FilePath& virtual_path, |
| 258 const base::FilePath& local_cache_path, | 262 const base::FilePath& local_cache_path, |
| 259 const GURL& download_url, | 263 const GURL& download_url, |
| 260 const DriveClientContext& context, | 264 const DriveClientContext& context, |
| 261 const google_apis::DownloadActionCallback& download_action_callback, | 265 const google_apis::DownloadActionCallback& download_action_callback, |
| 262 const google_apis::GetContentCallback& get_content_callback) { | 266 const google_apis::GetContentCallback& get_content_callback) { |
| 263 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 267 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 264 | 268 |
| 265 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_DOWNLOAD_FILE)); | 269 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_DOWNLOAD_FILE)); |
| 266 new_job->virtual_path = virtual_path; | 270 new_job->virtual_path = virtual_path; |
| 267 new_job->local_cache_path = local_cache_path; | 271 new_job->local_cache_path = local_cache_path; |
| 268 new_job->download_url = download_url; | 272 new_job->download_url = download_url; |
| 269 new_job->context = context; | 273 new_job->context = context; |
| 270 new_job->download_action_callback = download_action_callback; | 274 new_job->download_action_callback = download_action_callback; |
| 271 new_job->get_content_callback = get_content_callback; | 275 new_job->get_content_callback = get_content_callback; |
| 272 | 276 |
| 273 QueueJob(new_job.Pass()); | 277 QueueJob(new_job.Pass()); |
| 274 | 278 |
| 275 StartJobLoop(); | 279 StartJobLoop(GetJobQueueType(TYPE_DOWNLOAD_FILE)); |
| 276 } | 280 } |
| 277 | 281 |
| 278 void DriveScheduler::UploadExistingFile( | 282 void DriveScheduler::UploadExistingFile( |
| 279 const GURL& upload_location, | 283 const GURL& upload_location, |
| 280 const base::FilePath& drive_file_path, | 284 const base::FilePath& drive_file_path, |
| 281 const base::FilePath& local_file_path, | 285 const base::FilePath& local_file_path, |
| 282 const std::string& content_type, | 286 const std::string& content_type, |
| 283 const std::string& etag, | 287 const std::string& etag, |
| 284 const DriveClientContext& context, | 288 const DriveClientContext& context, |
| 285 const google_apis::UploadCompletionCallback& upload_completion_callback) { | 289 const google_apis::UploadCompletionCallback& upload_completion_callback) { |
| 286 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 290 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 287 | 291 |
| 288 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_UPLOAD_EXISTING_FILE)); | 292 scoped_ptr<QueueEntry> new_job(new QueueEntry(TYPE_UPLOAD_EXISTING_FILE)); |
| 289 new_job->upload_location = upload_location; | 293 new_job->upload_location = upload_location; |
| 290 new_job->drive_file_path = drive_file_path; | 294 new_job->drive_file_path = drive_file_path; |
| 291 new_job->local_file_path = local_file_path; | 295 new_job->local_file_path = local_file_path; |
| 292 new_job->content_type = content_type; | 296 new_job->content_type = content_type; |
| 293 new_job->etag = etag; | 297 new_job->etag = etag; |
| 294 new_job->upload_completion_callback = upload_completion_callback; | 298 new_job->upload_completion_callback = upload_completion_callback; |
| 295 new_job->context = context; | 299 new_job->context = context; |
| 296 | 300 |
| 297 QueueJob(new_job.Pass()); | 301 QueueJob(new_job.Pass()); |
| 298 | 302 |
| 299 StartJobLoop(); | 303 StartJobLoop(GetJobQueueType(TYPE_UPLOAD_EXISTING_FILE)); |
| 300 } | 304 } |
| 301 | 305 |
| 302 void DriveScheduler::QueueJob(scoped_ptr<QueueEntry> job) { | 306 void DriveScheduler::QueueJob(scoped_ptr<QueueEntry> job) { |
| 303 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 307 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 304 | 308 |
| 305 queue_.push_back(job.release()); | 309 QueueType queue_type = GetJobQueueType(job->job_info.job_type); |
| 306 queue_.sort(&QueueEntry::Compare); | 310 std::list<QueueEntry*>& queue = queue_[queue_type]; |
| 311 |
| 312 queue.push_back(job.release()); |
| 313 queue.sort(&QueueEntry::Compare); |
| 307 } | 314 } |
| 308 | 315 |
| 309 void DriveScheduler::StartJobLoop() { | 316 void DriveScheduler::StartJobLoop(QueueType queue_type) { |
| 310 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 317 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 311 | 318 |
| 312 if (!job_loop_is_running_) | 319 if (!job_loop_is_running_[queue_type]) |
| 313 DoJobLoop(); | 320 DoJobLoop(queue_type); |
| 314 } | 321 } |
| 315 | 322 |
| 316 void DriveScheduler::DoJobLoop() { | 323 void DriveScheduler::DoJobLoop(QueueType queue_type) { |
| 317 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 324 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 318 | 325 |
| 319 if (queue_.empty() || ShouldStopJobLoop()) { | 326 if (queue_[queue_type].empty()) { |
| 320 // Note that |queue_| is not cleared so the sync loop can resume. | 327 // Note that |queue_| is not cleared so the sync loop can resume. |
| 321 job_loop_is_running_ = false; | 328 job_loop_is_running_[queue_type] = false; |
| 322 return; | 329 return; |
| 323 } | 330 } |
| 324 job_loop_is_running_ = true; | 331 |
| 332 // Check if we should defer based on the first item in the queue |
| 333 if (ShouldStopJobLoop(queue_type, queue_[queue_type].front()->context)) { |
| 334 job_loop_is_running_[queue_type] = false; |
| 335 return; |
| 336 } |
| 337 |
| 338 job_loop_is_running_[queue_type] = true; |
| 325 | 339 |
| 326 // Should copy before calling queue_.pop_front(). | 340 // Should copy before calling queue_.pop_front(). |
| 327 scoped_ptr<QueueEntry> queue_entry(queue_.front()); | 341 scoped_ptr<QueueEntry> queue_entry(queue_[queue_type].front()); |
| 328 queue_.pop_front(); | 342 queue_[queue_type].pop_front(); |
| 329 | 343 |
| 330 JobInfo& job_info = queue_entry->job_info; | 344 JobInfo& job_info = queue_entry->job_info; |
| 331 job_info.state = STATE_RUNNING; | 345 job_info.state = STATE_RUNNING; |
| 332 | 346 |
| 333 // The some arguments are evaluated after bind, so we copy the pointer to the | 347 // The some arguments are evaluated after bind, so we copy the pointer to the |
| 334 // QueueEntry | 348 // QueueEntry |
| 335 QueueEntry* entry = queue_entry.get(); | 349 QueueEntry* entry = queue_entry.get(); |
| 336 | 350 |
| 337 switch (job_info.job_type) { | 351 switch (job_info.job_type) { |
| 338 case TYPE_GET_ACCOUNT_METADATA: { | 352 case TYPE_GET_ACCOUNT_METADATA: { |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 457 weak_ptr_factory_.GetWeakPtr(), | 471 weak_ptr_factory_.GetWeakPtr(), |
| 458 base::Passed(&queue_entry))); | 472 base::Passed(&queue_entry))); |
| 459 } | 473 } |
| 460 break; | 474 break; |
| 461 | 475 |
| 462 // There is no default case so that there will be a compiler error if a type | 476 // There is no default case so that there will be a compiler error if a type |
| 463 // is added but unhandled. | 477 // is added but unhandled. |
| 464 } | 478 } |
| 465 } | 479 } |
| 466 | 480 |
| 467 bool DriveScheduler::ShouldStopJobLoop() { | 481 bool DriveScheduler::ShouldStopJobLoop(QueueType queue_type, |
| 482 const DriveClientContext& context) { |
| 468 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 483 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 469 | 484 |
| 470 // Should stop if the gdata feature was disabled while running the fetch | 485 // Should stop if the gdata feature was disabled while running the fetch |
| 471 // loop. | 486 // loop. |
| 472 if (profile_->GetPrefs()->GetBoolean(prefs::kDisableDrive)) | 487 if (profile_->GetPrefs()->GetBoolean(prefs::kDisableDrive)) |
| 473 return true; | 488 return true; |
| 474 | 489 |
| 475 // Should stop if the network is not online. | 490 // Should stop if the network is not online. |
| 476 if (net::NetworkChangeNotifier::IsOffline()) | 491 if (net::NetworkChangeNotifier::IsOffline()) |
| 477 return true; | 492 return true; |
| 478 | 493 |
| 479 // TODO(zork): This is a temporary fix for crbug.com/172270. It should be | 494 if (queue_type == FILE_QUEUE && context.type == BACKGROUND) { |
| 480 // re-enabled once it's merged. | 495 // Should stop if the current connection is on cellular network, and |
| 481 // | 496 // fetching is disabled over cellular. |
| 482 // Should stop if the current connection is on cellular network, and | 497 if (profile_->GetPrefs()->GetBoolean(prefs::kDisableDriveOverCellular) && |
| 483 // fetching is disabled over cellular. | 498 net::NetworkChangeNotifier::IsConnectionCellular( |
| 484 // if (profile_->GetPrefs()->GetBoolean(prefs::kDisableDriveOverCellular) && | 499 net::NetworkChangeNotifier::GetConnectionType())) |
| 485 // net::NetworkChangeNotifier::IsConnectionCellular( | 500 return true; |
| 486 // net::NetworkChangeNotifier::GetConnectionType())) | 501 } |
| 487 // return true; | |
| 488 | 502 |
| 489 return false; | 503 return false; |
| 490 } | 504 } |
| 491 | 505 |
| 492 void DriveScheduler::ThrottleAndContinueJobLoop() { | 506 void DriveScheduler::ThrottleAndContinueJobLoop(QueueType queue_type) { |
| 493 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 507 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 494 | 508 |
| 495 if (throttle_count_ < kMaxThrottleCount) | 509 if (throttle_count_ < kMaxThrottleCount) |
| 496 throttle_count_++; | 510 throttle_count_++; |
| 497 | 511 |
| 498 base::TimeDelta delay; | 512 base::TimeDelta delay; |
| 499 if (disable_throttling_) { | 513 if (disable_throttling_) { |
| 500 delay = base::TimeDelta::FromSeconds(0); | 514 delay = base::TimeDelta::FromSeconds(0); |
| 501 } else { | 515 } else { |
| 502 delay = | 516 delay = |
| 503 base::TimeDelta::FromSeconds(pow(2, throttle_count_ - 1)) + | 517 base::TimeDelta::FromSeconds(pow(2, throttle_count_ - 1)) + |
| 504 base::TimeDelta::FromMilliseconds(base::RandInt(0, 1000)); | 518 base::TimeDelta::FromMilliseconds(base::RandInt(0, 1000)); |
| 505 } | 519 } |
| 506 VLOG(1) << "Throttling for " << delay.InMillisecondsF(); | 520 VLOG(1) << "Throttling for " << delay.InMillisecondsF(); |
| 507 | 521 |
| 508 const bool posted = base::MessageLoopProxy::current()->PostDelayedTask( | 522 const bool posted = base::MessageLoopProxy::current()->PostDelayedTask( |
| 509 FROM_HERE, | 523 FROM_HERE, |
| 510 base::Bind(&DriveScheduler::DoJobLoop, | 524 base::Bind(&DriveScheduler::DoJobLoop, |
| 511 weak_ptr_factory_.GetWeakPtr()), | 525 weak_ptr_factory_.GetWeakPtr(), |
| 526 queue_type), |
| 512 delay); | 527 delay); |
| 513 DCHECK(posted); | 528 DCHECK(posted); |
| 514 } | 529 } |
| 515 | 530 |
| 516 void DriveScheduler::ResetThrottleAndContinueJobLoop() { | 531 void DriveScheduler::ResetThrottleAndContinueJobLoop(QueueType queue_type) { |
| 517 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 532 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 518 | 533 |
| 519 // Post a task to continue the job loop. This allows us to finish handling | 534 // Post a task to continue the job loop. This allows us to finish handling |
| 520 // the current job before starting the next one. | 535 // the current job before starting the next one. |
| 521 throttle_count_ = 0; | 536 throttle_count_ = 0; |
| 522 base::MessageLoopProxy::current()->PostTask(FROM_HERE, | 537 base::MessageLoopProxy::current()->PostTask(FROM_HERE, |
| 523 base::Bind(&DriveScheduler::DoJobLoop, | 538 base::Bind(&DriveScheduler::DoJobLoop, |
| 524 weak_ptr_factory_.GetWeakPtr())); | 539 weak_ptr_factory_.GetWeakPtr(), |
| 540 queue_type)); |
| 525 } | 541 } |
| 526 | 542 |
| 527 scoped_ptr<DriveScheduler::QueueEntry> DriveScheduler::OnJobDone( | 543 scoped_ptr<DriveScheduler::QueueEntry> DriveScheduler::OnJobDone( |
| 528 scoped_ptr<DriveScheduler::QueueEntry> queue_entry, | 544 scoped_ptr<DriveScheduler::QueueEntry> queue_entry, |
| 529 DriveFileError error) { | 545 DriveFileError error) { |
| 530 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 546 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 531 | 547 |
| 548 QueueType queue_type = GetJobQueueType(queue_entry->job_info.job_type); |
| 549 |
| 532 // Retry, depending on the error. | 550 // Retry, depending on the error. |
| 533 if (error == DRIVE_FILE_ERROR_THROTTLED) { | 551 if (error == DRIVE_FILE_ERROR_THROTTLED) { |
| 534 queue_entry->job_info.state = STATE_RETRY; | 552 queue_entry->job_info.state = STATE_RETRY; |
| 535 | 553 |
| 536 // Requeue the job. | 554 // Requeue the job. |
| 537 QueueJob(queue_entry.Pass()); | 555 QueueJob(queue_entry.Pass()); |
| 538 | 556 |
| 539 ThrottleAndContinueJobLoop(); | 557 ThrottleAndContinueJobLoop(queue_type); |
| 540 | 558 |
| 541 return scoped_ptr<DriveScheduler::QueueEntry>(); | 559 return scoped_ptr<DriveScheduler::QueueEntry>(); |
| 542 } else { | 560 } else { |
| 543 ResetThrottleAndContinueJobLoop(); | 561 ResetThrottleAndContinueJobLoop(queue_type); |
| 544 | 562 |
| 545 // Send the entry back. | 563 // Send the entry back. |
| 546 return queue_entry.Pass(); | 564 return queue_entry.Pass(); |
| 547 } | 565 } |
| 548 } | 566 } |
| 549 | 567 |
| 550 void DriveScheduler::OnGetResourceListJobDone( | 568 void DriveScheduler::OnGetResourceListJobDone( |
| 551 scoped_ptr<DriveScheduler::QueueEntry> queue_entry, | 569 scoped_ptr<DriveScheduler::QueueEntry> queue_entry, |
| 552 google_apis::GDataErrorCode error, | 570 google_apis::GDataErrorCode error, |
| 553 scoped_ptr<google_apis::ResourceList> resource_list) { | 571 scoped_ptr<google_apis::ResourceList> resource_list) { |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 673 error, drive_path, file_path, resource_entry.Pass()); | 691 error, drive_path, file_path, resource_entry.Pass()); |
| 674 } | 692 } |
| 675 | 693 |
| 676 void DriveScheduler::OnConnectionTypeChanged( | 694 void DriveScheduler::OnConnectionTypeChanged( |
| 677 net::NetworkChangeNotifier::ConnectionType type) { | 695 net::NetworkChangeNotifier::ConnectionType type) { |
| 678 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 696 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 679 | 697 |
| 680 // Resume the job loop if the network is back online. Note that we don't | 698 // Resume the job loop if the network is back online. Note that we don't |
| 681 // need to check the type of the network as it will be checked in | 699 // need to check the type of the network as it will be checked in |
| 682 // ShouldStopJobLoop() as soon as the loop is resumed. | 700 // ShouldStopJobLoop() as soon as the loop is resumed. |
| 683 if (!net::NetworkChangeNotifier::IsOffline()) | 701 if (!net::NetworkChangeNotifier::IsOffline()) { |
| 684 StartJobLoop(); | 702 for (int i = METADATA_QUEUE; i < NUM_QUEUES; ++i) { |
| 703 StartJobLoop(static_cast<QueueType>(i)); |
| 704 } |
| 705 } |
| 706 } |
| 707 |
| 708 DriveScheduler::QueueType DriveScheduler::GetJobQueueType(JobType type) { |
| 709 switch (type) { |
| 710 case TYPE_GET_ACCOUNT_METADATA: |
| 711 case TYPE_GET_APP_LIST: |
| 712 case TYPE_GET_RESOURCE_LIST: |
| 713 case TYPE_GET_RESOURCE_ENTRY: |
| 714 case TYPE_DELETE_RESOURCE: |
| 715 case TYPE_COPY_HOSTED_DOCUMENT: |
| 716 case TYPE_RENAME_RESOURCE: |
| 717 case TYPE_ADD_RESOURCE_TO_DIRECTORY: |
| 718 case TYPE_REMOVE_RESOURCE_FROM_DIRECTORY: |
| 719 case TYPE_ADD_NEW_DIRECTORY: |
| 720 return METADATA_QUEUE; |
| 721 |
| 722 case TYPE_DOWNLOAD_FILE: |
| 723 case TYPE_UPLOAD_EXISTING_FILE: |
| 724 return FILE_QUEUE; |
| 725 } |
| 726 NOTREACHED(); |
| 727 return FILE_QUEUE; |
| 685 } | 728 } |
| 686 | 729 |
| 687 } // namespace drive | 730 } // namespace drive |
| OLD | NEW |