diff options
-rw-r--r-- | chrome/browser/download/download_manager.cc | 21 | ||||
-rw-r--r-- | chrome/browser/download/download_manager.h | 5 | ||||
-rw-r--r-- | chrome/browser/history/download_database.cc | 10 | ||||
-rw-r--r-- | chrome/browser/history/download_database.h | 6 | ||||
-rw-r--r-- | chrome/browser/history/history.cc | 7 | ||||
-rw-r--r-- | chrome/browser/history/history.h | 4 | ||||
-rw-r--r-- | chrome/browser/history/history_backend.cc | 9 | ||||
-rw-r--r-- | chrome/browser/history/history_backend.h | 1 | ||||
-rw-r--r-- | chrome/browser/history/history_unittest.cc | 16 |
9 files changed, 79 insertions, 0 deletions
diff --git a/chrome/browser/download/download_manager.cc b/chrome/browser/download/download_manager.cc index 5b804d7..6d79b58 100644 --- a/chrome/browser/download/download_manager.cc +++ b/chrome/browser/download/download_manager.cc @@ -537,6 +537,10 @@ bool DownloadManager::Init(Profile* profile) { // information about new downloads while in that mode. QueryHistoryForDownloads(); + // Cleans up entries only when called for the first time. Subsequent calls are + // a no op. + CleanUpInProgressHistoryEntries(); + ResourceDispatcherHost* rdh = g_browser_process->resource_dispatcher_host(); if (!rdh) { NOTREACHED(); @@ -588,6 +592,18 @@ void DownloadManager::QueryHistoryForDownloads() { } } +void DownloadManager::CleanUpInProgressHistoryEntries() { + static bool already_cleaned_up = false; + + if (!already_cleaned_up) { + HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); + if (hs) { + hs->CleanUpInProgressEntries(); + already_cleaned_up = true; + } + } +} + // We have received a message from DownloadFileManager about a new download. We // create a download item and store it in our download map, and inform the // history system of a new download. Since this method can be called while the @@ -1221,6 +1237,11 @@ int DownloadManager::RemoveDownloads(const base::Time remove_begin) { } int DownloadManager::RemoveAllDownloads() { + if (this != profile_->GetOriginalProfile()->GetDownloadManager()) { + // This is an incognito downloader. Clear All should clear main download + // manager as well. + profile_->GetOriginalProfile()->GetDownloadManager()->RemoveAllDownloads(); + } // The null times make the date range unbounded. return RemoveDownloadsBetween(base::Time(), base::Time()); } diff --git a/chrome/browser/download/download_manager.h b/chrome/browser/download/download_manager.h index c77d480..0707711 100644 --- a/chrome/browser/download/download_manager.h +++ b/chrome/browser/download/download_manager.h @@ -395,6 +395,11 @@ class DownloadManager : public base::RefCountedThreadSafe<DownloadManager>, // Schedule a query of the history service to retrieve all downloads. void QueryHistoryForDownloads(); + // Cleans up IN_PROGRESS history entries as these entries are corrupt because + // of the sudden exit. Changes them to CANCELED. Executed only when called + // first time, subsequent calls a no op. + void CleanUpInProgressHistoryEntries(); + // Notifications sent from the download thread to the UI thread void StartDownload(DownloadCreateInfo* info); void UpdateDownload(int32 download_id, int64 size); diff --git a/chrome/browser/history/download_database.cc b/chrome/browser/history/download_database.cc index 8bf4a95..ea0649d 100644 --- a/chrome/browser/history/download_database.cc +++ b/chrome/browser/history/download_database.cc @@ -135,6 +135,16 @@ bool DownloadDatabase::UpdateDownloadPath(const std::wstring& path, return statement.Run(); } +bool DownloadDatabase::CleanUpInProgressEntries() { + sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, + "UPDATE downloads SET state=? WHERE state=?")); + if (!statement) + return false; + statement.BindInt(0, DownloadItem::CANCELLED); + statement.BindInt(1, DownloadItem::IN_PROGRESS); + return statement.Run(); +} + int64 DownloadDatabase::CreateDownload(const DownloadCreateInfo& info) { sql::Statement statement(GetDB().GetCachedStatement(SQL_FROM_HERE, "INSERT INTO downloads " diff --git a/chrome/browser/history/download_database.h b/chrome/browser/history/download_database.h index 1efb6d4..8ba2e7a 100644 --- a/chrome/browser/history/download_database.h +++ b/chrome/browser/history/download_database.h @@ -31,6 +31,12 @@ class DownloadDatabase { // Update the path of one download. Returns true if successful. bool UpdateDownloadPath(const std::wstring& path, DownloadID db_handle); + // Fixes state of the download entries. Sometimes entries with IN_PROGRESS + // state are not updated during browser shutdown (particularly when crashing). + // On the next start such entries are considered canceled. This functions + // fixes such entries. + bool CleanUpInProgressEntries(); + // Create a new database entry for one download and return its primary db id. int64 CreateDownload(const DownloadCreateInfo& info); diff --git a/chrome/browser/history/history.cc b/chrome/browser/history/history.cc index fe85e5f..0e685748 100644 --- a/chrome/browser/history/history.cc +++ b/chrome/browser/history/history.cc @@ -488,6 +488,13 @@ HistoryService::Handle HistoryService::QueryDownloads( new history::DownloadQueryRequest(callback)); } +// Changes all IN_PROGRESS in the database entries to CANCELED. +// IN_PROGRESS entries are the corrupted entries, not updated by next function +// because of the crash or some other extremal exit. +void HistoryService::CleanUpInProgressEntries() { + ScheduleAndForget(PRIORITY_NORMAL, &HistoryBackend::CleanUpInProgressEntries); +} + // Handle updates for a particular download. This is a 'fire and forget' // operation, so we don't need to be called back. void HistoryService::UpdateDownload(int64 received_bytes, diff --git a/chrome/browser/history/history.h b/chrome/browser/history/history.h index 2326f8b..3507817 100644 --- a/chrome/browser/history/history.h +++ b/chrome/browser/history/history.h @@ -406,6 +406,10 @@ class HistoryService : public CancelableRequestProvider, Handle QueryDownloads(CancelableRequestConsumerBase* consumer, DownloadQueryCallback* callback); + // Begins a request to clean up entries that has been corrupted (because of + // the crash, for example). + void CleanUpInProgressEntries(); + // Called to update the history service about the current state of a download. // This is a 'fire and forget' query, so just pass the relevant state info to // the database with no need for a callback. diff --git a/chrome/browser/history/history_backend.cc b/chrome/browser/history/history_backend.cc index 4be006a..caaec96 100644 --- a/chrome/browser/history/history_backend.cc +++ b/chrome/browser/history/history_backend.cc @@ -1040,6 +1040,15 @@ void HistoryBackend::QueryDownloads( request->ForwardResult(DownloadQueryRequest::TupleType(&request->value)); } +// Clean up entries that has been corrupted (because of the crash, for example). +void HistoryBackend::CleanUpInProgressEntries() { + if (db_.get()) { + // If some "in progress" entries were not updated when Chrome exited, they + // need to be cleaned up. + db_->CleanUpInProgressEntries(); + } +} + // Update a particular download entry. void HistoryBackend::UpdateDownload(int64 received_bytes, int32 state, diff --git a/chrome/browser/history/history_backend.h b/chrome/browser/history/history_backend.h index 7289b5a..4b37f29 100644 --- a/chrome/browser/history/history_backend.h +++ b/chrome/browser/history/history_backend.h @@ -201,6 +201,7 @@ class HistoryBackend : public base::RefCountedThreadSafe<HistoryBackend>, // Downloads ----------------------------------------------------------------- void QueryDownloads(scoped_refptr<DownloadQueryRequest> request); + void CleanUpInProgressEntries(); void UpdateDownload(int64 received_bytes, int32 state, int64 db_handle); void UpdateDownloadPath(const std::wstring& path, int64 db_handle); void CreateDownload(scoped_refptr<DownloadCreateRequest> request, diff --git a/chrome/browser/history/history_unittest.cc b/chrome/browser/history/history_unittest.cc index 00e9154..c0b65b3 100644 --- a/chrome/browser/history/history_unittest.cc +++ b/chrome/browser/history/history_unittest.cc @@ -382,6 +382,22 @@ TEST_F(HistoryTest, ClearBrowsingData_Downloads) { db_->RemoveDownloadsBetween(Time(), Time()); db_->QueryDownloads(&downloads); EXPECT_EQ(0U, downloads.size()); + + // Check removal of downloads stuck in IN_PROGRESS state. + EXPECT_NE(0, AddDownload(DownloadItem::COMPLETE, month_ago)); + EXPECT_NE(0, AddDownload(DownloadItem::IN_PROGRESS, month_ago)); + db_->QueryDownloads(&downloads); + EXPECT_EQ(2U, downloads.size()); + db_->RemoveDownloadsBetween(Time(), Time()); + db_->QueryDownloads(&downloads); + // IN_PROGRESS download should remain. It it indicated as "Canceled" + EXPECT_EQ(1U, downloads.size()); + db_->CleanUpInProgressEntries(); + db_->QueryDownloads(&downloads); + EXPECT_EQ(1U, downloads.size()); + db_->RemoveDownloadsBetween(Time(), Time()); + db_->QueryDownloads(&downloads); + EXPECT_EQ(0U, downloads.size()); } TEST_F(HistoryTest, AddPage) { |