Chromium Code Reviews| 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/gdata/gdata_operation_registry.h" | 5 #include "chrome/browser/chromeos/gdata/gdata_operation_registry.h" |
| 6 | 6 |
| 7 #include "base/string_number_conversions.h" | 7 #include "base/string_number_conversions.h" |
| 8 #include "content/public/browser/browser_thread.h" | 8 #include "content/public/browser/browser_thread.h" |
| 9 | 9 |
| 10 using content::BrowserThread; | 10 using content::BrowserThread; |
| 11 | 11 |
| 12 namespace { | |
| 13 | |
| 14 const int64 kNotificationFrequencyInMilliseconds = 150; | |
|
zel
2012/07/31 15:24:50
even this looks too frequent to me. let's bring it
kinaba
2012/08/01 02:28:56
OK, now it's 1000ms.
| |
| 15 | |
| 16 } // namespace | |
| 17 | |
| 12 namespace gdata { | 18 namespace gdata { |
| 13 | 19 |
| 14 // static | 20 // static |
| 15 std::string GDataOperationRegistry::OperationTypeToString(OperationType type) { | 21 std::string GDataOperationRegistry::OperationTypeToString(OperationType type) { |
| 16 switch (type) { | 22 switch (type) { |
| 17 case OPERATION_UPLOAD: return "upload"; | 23 case OPERATION_UPLOAD: return "upload"; |
| 18 case OPERATION_DOWNLOAD: return "download"; | 24 case OPERATION_DOWNLOAD: return "download"; |
| 19 case OPERATION_OTHER: return "other"; | 25 case OPERATION_OTHER: return "other"; |
| 20 } | 26 } |
| 21 NOTREACHED(); | 27 NOTREACHED(); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 130 progress_status_.transfer_state = OPERATION_IN_PROGRESS; | 136 progress_status_.transfer_state = OPERATION_IN_PROGRESS; |
| 131 registry_->OnOperationResume(this, &progress_status_); | 137 registry_->OnOperationResume(this, &progress_status_); |
| 132 } | 138 } |
| 133 } | 139 } |
| 134 | 140 |
| 135 void GDataOperationRegistry::Operation::NotifyAuthFailed() { | 141 void GDataOperationRegistry::Operation::NotifyAuthFailed() { |
| 136 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 137 registry_->OnOperationAuthFailed(); | 143 registry_->OnOperationAuthFailed(); |
| 138 } | 144 } |
| 139 | 145 |
| 140 GDataOperationRegistry::GDataOperationRegistry() { | 146 GDataOperationRegistry::GDataOperationRegistry() |
| 147 : do_notification_frequency_control_(true) { | |
| 141 in_flight_operations_.set_check_on_null_data(true); | 148 in_flight_operations_.set_check_on_null_data(true); |
| 142 } | 149 } |
| 143 | 150 |
| 144 GDataOperationRegistry::~GDataOperationRegistry() { | 151 GDataOperationRegistry::~GDataOperationRegistry() { |
| 145 DCHECK(in_flight_operations_.IsEmpty()); | 152 DCHECK(in_flight_operations_.IsEmpty()); |
| 146 } | 153 } |
| 147 | 154 |
| 148 void GDataOperationRegistry::AddObserver(Observer* observer) { | 155 void GDataOperationRegistry::AddObserver(Observer* observer) { |
| 149 observer_list_.AddObserver(observer); | 156 observer_list_.AddObserver(observer); |
| 150 } | 157 } |
| 151 | 158 |
| 152 void GDataOperationRegistry::RemoveObserver(Observer* observer) { | 159 void GDataOperationRegistry::RemoveObserver(Observer* observer) { |
| 153 observer_list_.RemoveObserver(observer); | 160 observer_list_.RemoveObserver(observer); |
| 154 } | 161 } |
| 155 | 162 |
| 163 void GDataOperationRegistry::DisableNotificationFrequencyControlForTest() { | |
| 164 do_notification_frequency_control_ = false; | |
| 165 } | |
| 166 | |
| 156 void GDataOperationRegistry::CancelAll() { | 167 void GDataOperationRegistry::CancelAll() { |
| 157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 168 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 158 | 169 |
| 159 for (OperationIDMap::iterator iter(&in_flight_operations_); | 170 for (OperationIDMap::iterator iter(&in_flight_operations_); |
| 160 !iter.IsAtEnd(); | 171 !iter.IsAtEnd(); |
| 161 iter.Advance()) { | 172 iter.Advance()) { |
| 162 Operation* operation = iter.GetCurrentValue(); | 173 Operation* operation = iter.GetCurrentValue(); |
| 163 operation->Cancel(); | 174 operation->Cancel(); |
| 164 // Cancel() may immediately trigger OnOperationFinish and remove the | 175 // Cancel() may immediately trigger OnOperationFinish and remove the |
| 165 // operation from the map, but IDMap is designed to be safe on such remove | 176 // operation from the map, but IDMap is designed to be safe on such remove |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 182 return false; | 193 return false; |
| 183 } | 194 } |
| 184 | 195 |
| 185 void GDataOperationRegistry::OnOperationStart( | 196 void GDataOperationRegistry::OnOperationStart( |
| 186 GDataOperationRegistry::Operation* operation, | 197 GDataOperationRegistry::Operation* operation, |
| 187 OperationID* id) { | 198 OperationID* id) { |
| 188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 199 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 189 | 200 |
| 190 *id = in_flight_operations_.Add(operation); | 201 *id = in_flight_operations_.Add(operation); |
| 191 DVLOG(1) << "GDataOperation[" << *id << "] started."; | 202 DVLOG(1) << "GDataOperation[" << *id << "] started."; |
| 192 if (IsFileTransferOperation(operation)) { | 203 if (IsFileTransferOperation(operation)) |
| 193 FOR_EACH_OBSERVER(Observer, observer_list_, | 204 NotifyStatusToObservers(); |
| 194 OnProgressUpdate(GetProgressStatusList())); | |
| 195 } | |
| 196 } | 205 } |
| 197 | 206 |
| 198 void GDataOperationRegistry::OnOperationProgress(OperationID id) { | 207 void GDataOperationRegistry::OnOperationProgress(OperationID id) { |
| 199 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 200 | 209 |
| 201 Operation* operation = in_flight_operations_.Lookup(id); | 210 Operation* operation = in_flight_operations_.Lookup(id); |
| 202 DCHECK(operation); | 211 DCHECK(operation); |
| 203 | 212 |
| 204 DVLOG(1) << "GDataOperation[" << id << "] " | 213 DVLOG(1) << "GDataOperation[" << id << "] " |
| 205 << operation->progress_status().DebugString(); | 214 << operation->progress_status().DebugString(); |
| 206 if (IsFileTransferOperation(operation)) { | 215 if (IsFileTransferOperation(operation)) |
| 207 FOR_EACH_OBSERVER(Observer, observer_list_, | 216 NotifyStatusToObservers(); |
| 208 OnProgressUpdate(GetProgressStatusList())); | |
| 209 } | |
| 210 } | 217 } |
| 211 | 218 |
| 212 void GDataOperationRegistry::OnOperationFinish(OperationID id) { | 219 void GDataOperationRegistry::OnOperationFinish(OperationID id) { |
| 213 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 220 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 214 | 221 |
| 215 Operation* operation = in_flight_operations_.Lookup(id); | 222 Operation* operation = in_flight_operations_.Lookup(id); |
| 216 DCHECK(operation); | 223 DCHECK(operation); |
| 217 | 224 |
| 218 DVLOG(1) << "GDataOperation[" << id << "] finished."; | 225 DVLOG(1) << "GDataOperation[" << id << "] finished."; |
| 219 if (IsFileTransferOperation(operation)) { | 226 if (IsFileTransferOperation(operation)) |
| 220 FOR_EACH_OBSERVER(Observer, observer_list_, | 227 NotifyStatusToObservers(); |
| 221 OnProgressUpdate(GetProgressStatusList())); | |
| 222 } | |
| 223 in_flight_operations_.Remove(id); | 228 in_flight_operations_.Remove(id); |
| 224 } | 229 } |
| 225 | 230 |
| 226 void GDataOperationRegistry::OnOperationResume( | 231 void GDataOperationRegistry::OnOperationResume( |
| 227 GDataOperationRegistry::Operation* operation, | 232 GDataOperationRegistry::Operation* operation, |
| 228 GDataOperationRegistry::ProgressStatus* new_status) { | 233 GDataOperationRegistry::ProgressStatus* new_status) { |
| 229 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 234 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 230 | 235 |
| 231 // Find the corresponding suspended task. | 236 // Find the corresponding suspended task. |
| 232 Operation* suspended = NULL; | 237 Operation* suspended = NULL; |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 249 | 254 |
| 250 new_status->progress_current = old_status.progress_current; | 255 new_status->progress_current = old_status.progress_current; |
| 251 new_status->progress_total = old_status.progress_total; | 256 new_status->progress_total = old_status.progress_total; |
| 252 new_status->start_time = old_status.start_time; | 257 new_status->start_time = old_status.start_time; |
| 253 | 258 |
| 254 // Remove the old one and initiate the new operation. | 259 // Remove the old one and initiate the new operation. |
| 255 in_flight_operations_.Remove(old_id); | 260 in_flight_operations_.Remove(old_id); |
| 256 new_status->operation_id = in_flight_operations_.Add(operation); | 261 new_status->operation_id = in_flight_operations_.Add(operation); |
| 257 DVLOG(1) << "GDataOperation[" << old_id << " -> " << | 262 DVLOG(1) << "GDataOperation[" << old_id << " -> " << |
| 258 new_status->operation_id << "] resumed."; | 263 new_status->operation_id << "] resumed."; |
| 259 if (IsFileTransferOperation(operation)) { | 264 if (IsFileTransferOperation(operation)) |
| 260 FOR_EACH_OBSERVER(Observer, observer_list_, | 265 NotifyStatusToObservers(); |
| 261 OnProgressUpdate(GetProgressStatusList())); | |
| 262 } | |
| 263 } | 266 } |
| 264 | 267 |
| 265 void GDataOperationRegistry::OnOperationSuspend(OperationID id) { | 268 void GDataOperationRegistry::OnOperationSuspend(OperationID id) { |
| 266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 269 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 267 | 270 |
| 268 Operation* operation = in_flight_operations_.Lookup(id); | 271 Operation* operation = in_flight_operations_.Lookup(id); |
| 269 DCHECK(operation); | 272 DCHECK(operation); |
| 270 | 273 |
| 271 DVLOG(1) << "GDataOperation[" << id << "] suspended."; | 274 DVLOG(1) << "GDataOperation[" << id << "] suspended."; |
| 272 if (IsFileTransferOperation(operation)) { | 275 if (IsFileTransferOperation(operation)) |
| 273 FOR_EACH_OBSERVER(Observer, observer_list_, | 276 NotifyStatusToObservers(); |
| 274 OnProgressUpdate(GetProgressStatusList())); | |
| 275 } | |
| 276 } | 277 } |
| 277 | 278 |
| 278 void GDataOperationRegistry::OnOperationAuthFailed() { | 279 void GDataOperationRegistry::OnOperationAuthFailed() { |
| 279 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 280 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 280 | 281 |
| 281 DVLOG(1) << "GDataOperation authentication failed."; | 282 DVLOG(1) << "GDataOperation authentication failed."; |
| 282 FOR_EACH_OBSERVER(Observer, observer_list_, OnAuthenticationFailed()); | 283 FOR_EACH_OBSERVER(Observer, observer_list_, OnAuthenticationFailed()); |
| 283 } | 284 } |
| 284 | 285 |
| 285 bool GDataOperationRegistry::IsFileTransferOperation( | 286 bool GDataOperationRegistry::IsFileTransferOperation( |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 296 for (OperationIDMap::const_iterator iter(&in_flight_operations_); | 297 for (OperationIDMap::const_iterator iter(&in_flight_operations_); |
| 297 !iter.IsAtEnd(); | 298 !iter.IsAtEnd(); |
| 298 iter.Advance()) { | 299 iter.Advance()) { |
| 299 const Operation* operation = iter.GetCurrentValue(); | 300 const Operation* operation = iter.GetCurrentValue(); |
| 300 if (IsFileTransferOperation(operation)) | 301 if (IsFileTransferOperation(operation)) |
| 301 status_list.push_back(operation->progress_status()); | 302 status_list.push_back(operation->progress_status()); |
| 302 } | 303 } |
| 303 return status_list; | 304 return status_list; |
| 304 } | 305 } |
| 305 | 306 |
| 307 bool GDataOperationRegistry::ShouldNotifyStatusNow( | |
| 308 const ProgressStatusList& list) { | |
| 309 if (!do_notification_frequency_control_) | |
| 310 return true; | |
| 311 | |
| 312 base::Time now = base::Time::Now(); | |
| 313 | |
| 314 // If it is a first event, or some time abnormality is detected, we should | |
| 315 // not skip this notification. | |
| 316 if (last_notification_.is_null() || now < last_notification_) { | |
| 317 last_notification_ = now; | |
| 318 return true; | |
| 319 } | |
| 320 | |
| 321 // If sufficiently long time has elapsed since the previous event, we should | |
| 322 // not skip this notification. | |
| 323 if ((now - last_notification_).InMilliseconds() >= | |
| 324 kNotificationFrequencyInMilliseconds) { | |
| 325 last_notification_ = now; | |
| 326 return true; | |
| 327 } | |
| 328 | |
| 329 // If important events (OPERATION_STARTED, COMPLETED, or FAILED) are there, | |
| 330 // we should not skip this notification. | |
| 331 for (size_t i = 0; i < list.size(); ++i) { | |
| 332 if (list[i].transfer_state != OPERATION_IN_PROGRESS) { | |
| 333 last_notification_ = now; | |
| 334 return true; | |
| 335 } | |
| 336 } | |
| 337 | |
| 338 // Otherwise we can skip it. | |
| 339 return false; | |
| 340 } | |
| 341 | |
| 342 void GDataOperationRegistry::NotifyStatusToObservers() { | |
| 343 ProgressStatusList list(GetProgressStatusList()); | |
| 344 if (ShouldNotifyStatusNow(list)) | |
| 345 FOR_EACH_OBSERVER(Observer, observer_list_, OnProgressUpdate(list)); | |
| 346 } | |
| 347 | |
| 306 } // namespace gdata | 348 } // namespace gdata |
| OLD | NEW |