Commit 67332adc authored by Min Qin's avatar Min Qin Committed by Commit Bot

Solve an issue that OnDownloadCreated may not be called in LoadHistoryDownloads

When in-progress DB is enabled, DownloadHistory will wait for in-progress
DB to load first before loading its own downloads.
If a download item exists in both DB, then onDownloadCreated() will be called
before DownloadHistory load the same item.
As a result, when LoadHistoryDownloads() is called, the OnDownloadCreated()
reentrance call will not happen for that download.
This causes the DownloadHistoryData::PERSISTED to not get set.
And later on when the download is deleted, it will be skipped by DownloadHistory, thus showing inconsistent result.

This CL fixes the problem by explicitly adding the
DownloadHistoryData::PERSISTED after each item is loaded in
LoadHistoryDownload() call.

BUG=842245

Change-Id: Id15762e46992644e11d6c9bfd46ead39bb64b13b
Reviewed-on: https://chromium-review.googlesource.com/1145865Reviewed-by: default avatarXing Liu <xingliu@chromium.org>
Commit-Queue: Min Qin <qinmin@chromium.org>
Cr-Commit-Position: refs/heads/master@{#577984}
parent 4a4957da
...@@ -13,15 +13,16 @@ ...@@ -13,15 +13,16 @@
// When the DownloadManager and its delegate (ChromeDownloadManagerDelegate) are // When the DownloadManager and its delegate (ChromeDownloadManagerDelegate) are
// initialized, DownloadHistory is created and queries the HistoryService. When // initialized, DownloadHistory is created and queries the HistoryService. When
// the HistoryService calls back from QueryDownloads() to QueryCallback(), // the HistoryService calls back from QueryDownloads() to QueryCallback(),
// DownloadHistory uses DownloadManager::CreateDownloadItem() to inform // DownloadHistory will then wait for DownloadManager to call
// DownloadManager of these persisted DownloadItems. CreateDownloadItem() // LoadHistoryDownloads(), and uses DownloadManager::CreateDownloadItem() to
// inform DownloadManager of these persisted DownloadItems. CreateDownloadItem()
// internally calls OnDownloadCreated(), which normally adds items to the // internally calls OnDownloadCreated(), which normally adds items to the
// database, so QueryCallback() uses |loading_id_| to disable adding these items // database, so LoadHistoryDownloads() uses |loading_id_| to disable adding
// to the database. If a download is removed via OnDownloadRemoved() while the // these items to the database. If a download is removed via
// item is still being added to the database, DownloadHistory uses // OnDownloadRemoved() while the item is still being added to the database,
// |removed_while_adding_| to remember to remove the item when its ItemAdded() // DownloadHistory uses |removed_while_adding_| to remember to remove the item
// callback is called. All callbacks are bound with a weak pointer to // when its ItemAdded() callback is called. All callbacks are bound with a weak
// DownloadHistory to prevent use-after-free bugs. // pointer to DownloadHistory to prevent use-after-free bugs.
// ChromeDownloadManagerDelegate owns DownloadHistory, and deletes it in // ChromeDownloadManagerDelegate owns DownloadHistory, and deletes it in
// Shutdown(), which is called by DownloadManagerImpl::Shutdown() after all // Shutdown(), which is called by DownloadManagerImpl::Shutdown() after all
// DownloadItems are destroyed. // DownloadItems are destroyed.
...@@ -335,6 +336,7 @@ void DownloadHistory::LoadHistoryDownloads(std::unique_ptr<InfoVector> infos) { ...@@ -335,6 +336,7 @@ void DownloadHistory::LoadHistoryDownloads(std::unique_ptr<InfoVector> infos) {
history::ToContentDownloadInterruptReason(it->interrupt_reason), history::ToContentDownloadInterruptReason(it->interrupt_reason),
it->opened, it->last_access_time, it->transient, it->opened, it->last_access_time, it->transient,
history::ToContentReceivedSlices(it->download_slice_info)); history::ToContentReceivedSlices(it->download_slice_info));
CreateDownloadHistoryData(item, true);
#if BUILDFLAG(ENABLE_EXTENSIONS) #if BUILDFLAG(ENABLE_EXTENSIONS)
if (!it->by_ext_id.empty() && !it->by_ext_name.empty()) { if (!it->by_ext_id.empty() && !it->by_ext_name.empty()) {
new extensions::DownloadedByExtension( new extensions::DownloadedByExtension(
...@@ -440,19 +442,8 @@ void DownloadHistory::ItemAdded(uint32_t download_id, bool success) { ...@@ -440,19 +442,8 @@ void DownloadHistory::ItemAdded(uint32_t download_id, bool success) {
void DownloadHistory::OnDownloadCreated(content::DownloadManager* manager, void DownloadHistory::OnDownloadCreated(content::DownloadManager* manager,
download::DownloadItem* item) { download::DownloadItem* item) {
DCHECK_CURRENTLY_ON(content::BrowserThread::UI); DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
if (item->GetId() != loading_id_)
// All downloads should pass through OnDownloadCreated exactly once. CreateDownloadHistoryData(item, false);
CHECK(!DownloadHistoryData::Get(item));
DownloadHistoryData* data = new DownloadHistoryData(item);
if (item->GetId() == loading_id_) {
data->SetState(DownloadHistoryData::PERSISTED);
data->set_was_restored_from_history(true);
loading_id_ = download::DownloadItem::kInvalidId;
}
if (item->GetState() == download::DownloadItem::IN_PROGRESS) {
data->set_info(GetDownloadRow(item));
}
MaybeAddToHistory(item);
} }
void DownloadHistory::OnDownloadUpdated(content::DownloadManager* manager, void DownloadHistory::OnDownloadUpdated(content::DownloadManager* manager,
...@@ -539,3 +530,19 @@ void DownloadHistory::RemoveDownloadsBatch() { ...@@ -539,3 +530,19 @@ void DownloadHistory::RemoveDownloadsBatch() {
for (Observer& observer : observers_) for (Observer& observer : observers_)
observer.OnDownloadsRemoved(remove_ids); observer.OnDownloadsRemoved(remove_ids);
} }
void DownloadHistory::CreateDownloadHistoryData(
download::DownloadItem* item,
bool was_restored_from_history) {
CHECK(!DownloadHistoryData::Get(item));
DownloadHistoryData* data = new DownloadHistoryData(item);
if (was_restored_from_history) {
DCHECK(item->GetId() == loading_id_);
loading_id_ = download::DownloadItem::kInvalidId;
data->SetState(DownloadHistoryData::PERSISTED);
data->set_was_restored_from_history(true);
}
if (item->GetState() == download::DownloadItem::IN_PROGRESS)
data->set_info(GetDownloadRow(item));
MaybeAddToHistory(item);
}
...@@ -135,6 +135,10 @@ class DownloadHistory : public download::AllDownloadItemNotifier::Observer { ...@@ -135,6 +135,10 @@ class DownloadHistory : public download::AllDownloadItemNotifier::Observer {
// Removes all |removing_ids_| from |history_|. // Removes all |removing_ids_| from |history_|.
void RemoveDownloadsBatch(); void RemoveDownloadsBatch();
// Creates DownloadHistoryData and attach it to the |item|.
void CreateDownloadHistoryData(download::DownloadItem* item,
bool was_restored_from_history);
download::AllDownloadItemNotifier notifier_; download::AllDownloadItemNotifier notifier_;
std::unique_ptr<HistoryAdapter> history_; std::unique_ptr<HistoryAdapter> history_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment