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 |