| 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 |