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 = 1000; |
| 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 |