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 // DownloadHistory manages persisting DownloadItems to the history service by | 5 // DownloadHistory manages persisting DownloadItems to the history service by |
6 // observing a single DownloadManager and all its DownloadItems using an | 6 // observing a single DownloadManager and all its DownloadItems using an |
7 // AllDownloadItemNotifier. | 7 // AllDownloadItemNotifier. |
8 // | 8 // |
9 // DownloadHistory decides whether and when to add items to, remove items from, | 9 // DownloadHistory decides whether and when to add items to, remove items from, |
10 // and update items in the database. DownloadHistory uses DownloadHistoryData to | 10 // and update items in the database. DownloadHistory uses DownloadHistoryData to |
(...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 return data && (data->state() == DownloadHistoryData::PERSISTED); | 205 return data && (data->state() == DownloadHistoryData::PERSISTED); |
206 } | 206 } |
207 | 207 |
208 DownloadHistory::DownloadHistory(content::DownloadManager* manager, | 208 DownloadHistory::DownloadHistory(content::DownloadManager* manager, |
209 scoped_ptr<HistoryAdapter> history) | 209 scoped_ptr<HistoryAdapter> history) |
210 : notifier_(manager, this), | 210 : notifier_(manager, this), |
211 history_(history.Pass()), | 211 history_(history.Pass()), |
212 loading_id_(content::DownloadItem::kInvalidId), | 212 loading_id_(content::DownloadItem::kInvalidId), |
213 history_size_(0), | 213 history_size_(0), |
214 weak_ptr_factory_(this) { | 214 weak_ptr_factory_(this) { |
215 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 215 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
216 content::DownloadManager::DownloadVector items; | 216 content::DownloadManager::DownloadVector items; |
217 notifier_.GetManager()->GetAllDownloads(&items); | 217 notifier_.GetManager()->GetAllDownloads(&items); |
218 for (content::DownloadManager::DownloadVector::const_iterator | 218 for (content::DownloadManager::DownloadVector::const_iterator |
219 it = items.begin(); it != items.end(); ++it) { | 219 it = items.begin(); it != items.end(); ++it) { |
220 OnDownloadCreated(notifier_.GetManager(), *it); | 220 OnDownloadCreated(notifier_.GetManager(), *it); |
221 } | 221 } |
222 history_->QueryDownloads(base::Bind( | 222 history_->QueryDownloads(base::Bind( |
223 &DownloadHistory::QueryCallback, weak_ptr_factory_.GetWeakPtr())); | 223 &DownloadHistory::QueryCallback, weak_ptr_factory_.GetWeakPtr())); |
224 } | 224 } |
225 | 225 |
226 DownloadHistory::~DownloadHistory() { | 226 DownloadHistory::~DownloadHistory() { |
227 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 227 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
228 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadHistoryDestroyed()); | 228 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadHistoryDestroyed()); |
229 observers_.Clear(); | 229 observers_.Clear(); |
230 } | 230 } |
231 | 231 |
232 void DownloadHistory::AddObserver(DownloadHistory::Observer* observer) { | 232 void DownloadHistory::AddObserver(DownloadHistory::Observer* observer) { |
233 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 233 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
234 observers_.AddObserver(observer); | 234 observers_.AddObserver(observer); |
235 } | 235 } |
236 | 236 |
237 void DownloadHistory::RemoveObserver(DownloadHistory::Observer* observer) { | 237 void DownloadHistory::RemoveObserver(DownloadHistory::Observer* observer) { |
238 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 238 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
239 observers_.RemoveObserver(observer); | 239 observers_.RemoveObserver(observer); |
240 } | 240 } |
241 | 241 |
242 bool DownloadHistory::WasRestoredFromHistory( | 242 bool DownloadHistory::WasRestoredFromHistory( |
243 const content::DownloadItem* download) const { | 243 const content::DownloadItem* download) const { |
244 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 244 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
245 const DownloadHistoryData* data = DownloadHistoryData::Get(download); | 245 const DownloadHistoryData* data = DownloadHistoryData::Get(download); |
246 | 246 |
247 // The OnDownloadCreated handler sets the was_restored_from_history flag when | 247 // The OnDownloadCreated handler sets the was_restored_from_history flag when |
248 // resetting the loading_id_. So one of the two conditions below will hold for | 248 // resetting the loading_id_. So one of the two conditions below will hold for |
249 // a download restored from history even if the caller of this method is | 249 // a download restored from history even if the caller of this method is |
250 // racing with our OnDownloadCreated handler. | 250 // racing with our OnDownloadCreated handler. |
251 return (data && data->was_restored_from_history()) || | 251 return (data && data->was_restored_from_history()) || |
252 download->GetId() == loading_id_; | 252 download->GetId() == loading_id_; |
253 } | 253 } |
254 | 254 |
255 void DownloadHistory::QueryCallback(scoped_ptr<InfoVector> infos) { | 255 void DownloadHistory::QueryCallback(scoped_ptr<InfoVector> infos) { |
256 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 256 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
257 // ManagerGoingDown() may have happened before the history loaded. | 257 // ManagerGoingDown() may have happened before the history loaded. |
258 if (!notifier_.GetManager()) | 258 if (!notifier_.GetManager()) |
259 return; | 259 return; |
260 for (InfoVector::const_iterator it = infos->begin(); | 260 for (InfoVector::const_iterator it = infos->begin(); |
261 it != infos->end(); ++it) { | 261 it != infos->end(); ++it) { |
262 loading_id_ = history::ToContentDownloadId(it->id); | 262 loading_id_ = history::ToContentDownloadId(it->id); |
263 content::DownloadItem* item = notifier_.GetManager()->CreateDownloadItem( | 263 content::DownloadItem* item = notifier_.GetManager()->CreateDownloadItem( |
264 loading_id_, | 264 loading_id_, |
265 it->current_path, | 265 it->current_path, |
266 it->target_path, | 266 it->target_path, |
(...skipping 19 matching lines...) Expand all Loading... |
286 } | 286 } |
287 #endif | 287 #endif |
288 DCHECK_EQ(DownloadHistoryData::PERSISTED, | 288 DCHECK_EQ(DownloadHistoryData::PERSISTED, |
289 DownloadHistoryData::Get(item)->state()); | 289 DownloadHistoryData::Get(item)->state()); |
290 ++history_size_; | 290 ++history_size_; |
291 } | 291 } |
292 notifier_.GetManager()->CheckForHistoryFilesRemoval(); | 292 notifier_.GetManager()->CheckForHistoryFilesRemoval(); |
293 } | 293 } |
294 | 294 |
295 void DownloadHistory::MaybeAddToHistory(content::DownloadItem* item) { | 295 void DownloadHistory::MaybeAddToHistory(content::DownloadItem* item) { |
296 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 296 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
297 | 297 |
298 uint32 download_id = item->GetId(); | 298 uint32 download_id = item->GetId(); |
299 DownloadHistoryData* data = DownloadHistoryData::Get(item); | 299 DownloadHistoryData* data = DownloadHistoryData::Get(item); |
300 bool removing = removing_ids_.find(download_id) != removing_ids_.end(); | 300 bool removing = removing_ids_.find(download_id) != removing_ids_.end(); |
301 | 301 |
302 // TODO(benjhayden): Remove IsTemporary(). | 302 // TODO(benjhayden): Remove IsTemporary(). |
303 if (download_crx_util::IsExtensionDownload(*item) || | 303 if (download_crx_util::IsExtensionDownload(*item) || |
304 item->IsTemporary() || | 304 item->IsTemporary() || |
305 (data->state() != DownloadHistoryData::NOT_PERSISTED) || | 305 (data->state() != DownloadHistoryData::NOT_PERSISTED) || |
306 removing) | 306 removing) |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
364 | 364 |
365 // In case the item changed or became temporary while it was being added. | 365 // In case the item changed or became temporary while it was being added. |
366 // Don't just update all of the item's observers because we're the only | 366 // Don't just update all of the item's observers because we're the only |
367 // observer that can also see data->state(), which is the only thing that | 367 // observer that can also see data->state(), which is the only thing that |
368 // ItemAdded() changed. | 368 // ItemAdded() changed. |
369 OnDownloadUpdated(notifier_.GetManager(), item); | 369 OnDownloadUpdated(notifier_.GetManager(), item); |
370 } | 370 } |
371 | 371 |
372 void DownloadHistory::OnDownloadCreated( | 372 void DownloadHistory::OnDownloadCreated( |
373 content::DownloadManager* manager, content::DownloadItem* item) { | 373 content::DownloadManager* manager, content::DownloadItem* item) { |
374 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 374 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
375 | 375 |
376 // All downloads should pass through OnDownloadCreated exactly once. | 376 // All downloads should pass through OnDownloadCreated exactly once. |
377 CHECK(!DownloadHistoryData::Get(item)); | 377 CHECK(!DownloadHistoryData::Get(item)); |
378 DownloadHistoryData* data = new DownloadHistoryData(item); | 378 DownloadHistoryData* data = new DownloadHistoryData(item); |
379 if (item->GetId() == loading_id_) { | 379 if (item->GetId() == loading_id_) { |
380 data->SetState(DownloadHistoryData::PERSISTED); | 380 data->SetState(DownloadHistoryData::PERSISTED); |
381 data->set_was_restored_from_history(true); | 381 data->set_was_restored_from_history(true); |
382 loading_id_ = content::DownloadItem::kInvalidId; | 382 loading_id_ = content::DownloadItem::kInvalidId; |
383 } | 383 } |
384 if (item->GetState() == content::DownloadItem::IN_PROGRESS) { | 384 if (item->GetState() == content::DownloadItem::IN_PROGRESS) { |
385 data->set_info(GetDownloadRow(item)); | 385 data->set_info(GetDownloadRow(item)); |
386 } | 386 } |
387 MaybeAddToHistory(item); | 387 MaybeAddToHistory(item); |
388 } | 388 } |
389 | 389 |
390 void DownloadHistory::OnDownloadUpdated( | 390 void DownloadHistory::OnDownloadUpdated( |
391 content::DownloadManager* manager, content::DownloadItem* item) { | 391 content::DownloadManager* manager, content::DownloadItem* item) { |
392 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 392 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
393 | 393 |
394 DownloadHistoryData* data = DownloadHistoryData::Get(item); | 394 DownloadHistoryData* data = DownloadHistoryData::Get(item); |
395 if (data->state() == DownloadHistoryData::NOT_PERSISTED) { | 395 if (data->state() == DownloadHistoryData::NOT_PERSISTED) { |
396 MaybeAddToHistory(item); | 396 MaybeAddToHistory(item); |
397 return; | 397 return; |
398 } | 398 } |
399 if (item->IsTemporary()) { | 399 if (item->IsTemporary()) { |
400 OnDownloadRemoved(notifier_.GetManager(), item); | 400 OnDownloadRemoved(notifier_.GetManager(), item); |
401 return; | 401 return; |
402 } | 402 } |
(...skipping 14 matching lines...) Expand all Loading... |
417 } | 417 } |
418 } | 418 } |
419 | 419 |
420 void DownloadHistory::OnDownloadOpened( | 420 void DownloadHistory::OnDownloadOpened( |
421 content::DownloadManager* manager, content::DownloadItem* item) { | 421 content::DownloadManager* manager, content::DownloadItem* item) { |
422 OnDownloadUpdated(manager, item); | 422 OnDownloadUpdated(manager, item); |
423 } | 423 } |
424 | 424 |
425 void DownloadHistory::OnDownloadRemoved( | 425 void DownloadHistory::OnDownloadRemoved( |
426 content::DownloadManager* manager, content::DownloadItem* item) { | 426 content::DownloadManager* manager, content::DownloadItem* item) { |
427 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 427 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
428 | 428 |
429 DownloadHistoryData* data = DownloadHistoryData::Get(item); | 429 DownloadHistoryData* data = DownloadHistoryData::Get(item); |
430 if (data->state() != DownloadHistoryData::PERSISTED) { | 430 if (data->state() != DownloadHistoryData::PERSISTED) { |
431 if (data->state() == DownloadHistoryData::PERSISTING) { | 431 if (data->state() == DownloadHistoryData::PERSISTING) { |
432 // ScheduleRemoveDownload will be called when history_ calls ItemAdded(). | 432 // ScheduleRemoveDownload will be called when history_ calls ItemAdded(). |
433 removed_while_adding_.insert(item->GetId()); | 433 removed_while_adding_.insert(item->GetId()); |
434 } | 434 } |
435 return; | 435 return; |
436 } | 436 } |
437 ScheduleRemoveDownload(item->GetId()); | 437 ScheduleRemoveDownload(item->GetId()); |
438 // This is important: another OnDownloadRemoved() handler could do something | 438 // This is important: another OnDownloadRemoved() handler could do something |
439 // that synchronously fires an OnDownloadUpdated(). | 439 // that synchronously fires an OnDownloadUpdated(). |
440 data->SetState(DownloadHistoryData::NOT_PERSISTED); | 440 data->SetState(DownloadHistoryData::NOT_PERSISTED); |
441 // ItemAdded increments history_size_ only if the item wasn't | 441 // ItemAdded increments history_size_ only if the item wasn't |
442 // removed_while_adding_, so the next line does not belong in | 442 // removed_while_adding_, so the next line does not belong in |
443 // ScheduleRemoveDownload(). | 443 // ScheduleRemoveDownload(). |
444 --history_size_; | 444 --history_size_; |
445 } | 445 } |
446 | 446 |
447 void DownloadHistory::ScheduleRemoveDownload(uint32 download_id) { | 447 void DownloadHistory::ScheduleRemoveDownload(uint32 download_id) { |
448 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 448 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
449 | 449 |
450 // For database efficiency, batch removals together if they happen all at | 450 // For database efficiency, batch removals together if they happen all at |
451 // once. | 451 // once. |
452 if (removing_ids_.empty()) { | 452 if (removing_ids_.empty()) { |
453 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, | 453 content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE, |
454 base::Bind(&DownloadHistory::RemoveDownloadsBatch, | 454 base::Bind(&DownloadHistory::RemoveDownloadsBatch, |
455 weak_ptr_factory_.GetWeakPtr())); | 455 weak_ptr_factory_.GetWeakPtr())); |
456 } | 456 } |
457 removing_ids_.insert(download_id); | 457 removing_ids_.insert(download_id); |
458 } | 458 } |
459 | 459 |
460 void DownloadHistory::RemoveDownloadsBatch() { | 460 void DownloadHistory::RemoveDownloadsBatch() { |
461 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); | 461 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
462 IdSet remove_ids; | 462 IdSet remove_ids; |
463 removing_ids_.swap(remove_ids); | 463 removing_ids_.swap(remove_ids); |
464 history_->RemoveDownloads(remove_ids); | 464 history_->RemoveDownloads(remove_ids); |
465 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadsRemoved(remove_ids)); | 465 FOR_EACH_OBSERVER(Observer, observers_, OnDownloadsRemoved(remove_ids)); |
466 } | 466 } |
OLD | NEW |