diff options
author | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-29 22:04:57 +0000 |
---|---|---|
committer | phajdan.jr@chromium.org <phajdan.jr@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-07-29 22:04:57 +0000 |
commit | 82f37b0d8c9b0e8e09c5e4debf98ddcb5bfbce09 (patch) | |
tree | da28f20debb7321045f81bbb54bf5e437071ddb0 /chrome/browser | |
parent | 947b1a563bceae4b78425424f0c0b88fa182ce22 (diff) | |
download | chromium_src-82f37b0d8c9b0e8e09c5e4debf98ddcb5bfbce09.zip chromium_src-82f37b0d8c9b0e8e09c5e4debf98ddcb5bfbce09.tar.gz chromium_src-82f37b0d8c9b0e8e09c5e4debf98ddcb5bfbce09.tar.bz2 |
Download code cleanup patch of death:
Separate all interactions with HistoryService out of DownloadManager
to new class DownloadHistory owned by the DownloadManager.
The goal is to create more smaller classes with clearly defined
responsibilities.
TEST=unit_tests, browser_tests, ui_tests
BUG=48913
Review URL: http://codereview.chromium.org/3071005
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@54205 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser')
-rw-r--r-- | chrome/browser/automation/automation_provider.cc | 18 | ||||
-rw-r--r-- | chrome/browser/automation/automation_provider_observers.h | 26 | ||||
-rw-r--r-- | chrome/browser/dom_ui/downloads_dom_handler.cc | 17 | ||||
-rw-r--r-- | chrome/browser/dom_ui/downloads_dom_handler.h | 3 | ||||
-rw-r--r-- | chrome/browser/dom_ui/filebrowse_ui.cc | 6 | ||||
-rw-r--r-- | chrome/browser/download/download_history.cc | 151 | ||||
-rw-r--r-- | chrome/browser/download/download_history.h | 91 | ||||
-rw-r--r-- | chrome/browser/download/download_item.cc | 5 | ||||
-rw-r--r-- | chrome/browser/download/download_item.h | 1 | ||||
-rw-r--r-- | chrome/browser/download/download_manager.cc | 292 | ||||
-rw-r--r-- | chrome/browser/download/download_manager.h | 81 | ||||
-rw-r--r-- | chrome/browser/download/drag_download_file.cc | 16 | ||||
-rw-r--r-- | chrome/browser/download/drag_download_file.h | 1 |
13 files changed, 339 insertions, 369 deletions
diff --git a/chrome/browser/automation/automation_provider.cc b/chrome/browser/automation/automation_provider.cc index 2e5d0fb..f635916 100644 --- a/chrome/browser/automation/automation_provider.cc +++ b/chrome/browser/automation/automation_provider.cc @@ -2099,8 +2099,6 @@ void AutomationProvider::AddHistoryItem(Browser* browser, void AutomationProvider::GetDownloadsInfo(Browser* browser, DictionaryValue* args, IPC::Message* reply_message) { - AutomationProviderDownloadManagerObserver observer; - std::vector<DownloadItem*> downloads; scoped_ptr<DictionaryValue> return_value(new DictionaryValue); AutomationJSONReply reply(this, reply_message); @@ -2108,11 +2106,9 @@ void AutomationProvider::GetDownloadsInfo(Browser* browser, reply.SendError("no download manager"); return; } - // Use DownloadManager's GetDownloads() method and not GetCurrentDownloads() - // since that would be transient; a download might enter and empty out - // the current download queue too soon to be noticed. - profile_->GetDownloadManager()->GetDownloads(&observer, L""); - downloads = observer.Downloads(); + + std::vector<DownloadItem*> downloads; + profile_->GetDownloadManager()->GetAllDownloads(FilePath(), &downloads); std::map<DownloadItem::DownloadState, std::string> state_to_string; state_to_string[DownloadItem::IN_PROGRESS] = std::string("IN_PROGRESS"); @@ -2160,8 +2156,6 @@ void AutomationProvider::WaitForDownloadsToComplete( Browser* browser, DictionaryValue* args, IPC::Message* reply_message) { - AutomationProviderDownloadManagerObserver observer; - std::vector<DownloadItem*> downloads; AutomationJSONReply reply(this, reply_message); // Look for a quick return. @@ -2169,9 +2163,9 @@ void AutomationProvider::WaitForDownloadsToComplete( reply.SendSuccess(NULL); // No download manager. return; } - profile_->GetDownloadManager()->GetCurrentDownloads(&observer, FilePath()); - downloads = observer.Downloads(); - if (downloads.size() == 0) { + std::vector<DownloadItem*> downloads; + profile_->GetDownloadManager()->GetCurrentDownloads(FilePath(), &downloads); + if (downloads.empty()) { reply.SendSuccess(NULL); return; } diff --git a/chrome/browser/automation/automation_provider_observers.h b/chrome/browser/automation/automation_provider_observers.h index 5d53cd3..f0a264f 100644 --- a/chrome/browser/automation/automation_provider_observers.h +++ b/chrome/browser/automation/automation_provider_observers.h @@ -14,6 +14,7 @@ #include "chrome/browser/browsing_data_remover.h" #include "chrome/browser/download/download_item.h" #include "chrome/browser/download/download_manager.h" +#include "chrome/browser/history/history.h" #include "chrome/browser/importer/importer.h" #include "chrome/browser/importer/importer_data_types.h" #include "chrome/browser/password_manager/password_store.h" @@ -596,27 +597,6 @@ class AutomationProviderBookmarkModelObserver : BookmarkModelObserver { DISALLOW_COPY_AND_ASSIGN(AutomationProviderBookmarkModelObserver); }; -// When asked for pending downloads, the DownloadManager places -// results in a DownloadManager::Observer. -class AutomationProviderDownloadManagerObserver - : public DownloadManager::Observer { - public: - AutomationProviderDownloadManagerObserver() : DownloadManager::Observer() {} - virtual ~AutomationProviderDownloadManagerObserver() {} - virtual void ModelChanged() {} - virtual void SetDownloads(std::vector<DownloadItem*>& downloads) { - downloads_ = downloads; - } - std::vector<DownloadItem*> Downloads() { - return downloads_; - } - private: - std::vector<DownloadItem*> downloads_; - - DISALLOW_COPY_AND_ASSIGN(AutomationProviderDownloadManagerObserver); -}; - - // Allows the automation provider to wait for all downloads to finish. class AutomationProviderDownloadItemObserver : public DownloadItem::Observer { public: @@ -679,8 +659,8 @@ class AutomationProviderImportSettingsObserver }; // Allows automation provider to wait for getting passwords to finish. -class AutomationProviderGetPasswordsObserver : - public PasswordStoreConsumer { +class AutomationProviderGetPasswordsObserver + : public PasswordStoreConsumer { public: AutomationProviderGetPasswordsObserver( AutomationProvider* provider, diff --git a/chrome/browser/dom_ui/downloads_dom_handler.cc b/chrome/browser/dom_ui/downloads_dom_handler.cc index 581ab20..c1ba9d2 100644 --- a/chrome/browser/dom_ui/downloads_dom_handler.cc +++ b/chrome/browser/dom_ui/downloads_dom_handler.cc @@ -9,11 +9,13 @@ #include "base/singleton.h" #include "base/string_piece.h" #include "base/thread.h" +#include "base/utf_string_conversions.h" #include "base/values.h" #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_thread.h" #include "chrome/browser/dom_ui/chrome_url_data_manager.h" #include "chrome/browser/dom_ui/fileicon_source.h" +#include "chrome/browser/download/download_history.h" #include "chrome/browser/download/download_item.h" #include "chrome/browser/download/download_util.h" #include "chrome/browser/metrics/user_metrics.h" @@ -110,15 +112,16 @@ void DownloadsDOMHandler::OnDownloadUpdated(DownloadItem* download) { } // A download has started or been deleted. Query our DownloadManager for the -// current set of downloads, which will call us back in SetDownloads once it -// has retrieved them. +// current set of downloads. void DownloadsDOMHandler::ModelChanged() { ClearDownloadItems(); - download_manager_->GetDownloads(this, search_text_); + download_manager_->download_history()->Search( + WideToUTF16(search_text_), + NewCallback(this, &DownloadsDOMHandler::OnSearchDownloadsComplete)); } -void DownloadsDOMHandler::SetDownloads( - std::vector<DownloadItem*>& downloads) { +void DownloadsDOMHandler::OnSearchDownloadsComplete( + std::vector<DownloadItem*> downloads) { ClearDownloadItems(); // Swap new downloads in. @@ -149,7 +152,9 @@ void DownloadsDOMHandler::HandleGetDownloads(const Value* value) { if (search_text_.compare(new_search) != 0) { search_text_ = new_search; ClearDownloadItems(); - download_manager_->GetDownloads(this, search_text_); + download_manager_->download_history()->Search( + WideToUTF16(search_text_), + NewCallback(this, &DownloadsDOMHandler::OnSearchDownloadsComplete)); } else { SendCurrentDownloads(); } diff --git a/chrome/browser/dom_ui/downloads_dom_handler.h b/chrome/browser/dom_ui/downloads_dom_handler.h index 32ab2bf..06b48d6 100644 --- a/chrome/browser/dom_ui/downloads_dom_handler.h +++ b/chrome/browser/dom_ui/downloads_dom_handler.h @@ -35,7 +35,8 @@ class DownloadsDOMHandler : public DOMMessageHandler, // DownloadManager::Observer interface virtual void ModelChanged(); - virtual void SetDownloads(std::vector<DownloadItem*>& downloads); + + void OnSearchDownloadsComplete(std::vector<DownloadItem*> downloads); // Callback for the "getDownloads" message. void HandleGetDownloads(const Value* value); diff --git a/chrome/browser/dom_ui/filebrowse_ui.cc b/chrome/browser/dom_ui/filebrowse_ui.cc index 7886752..8bab7cd 100644 --- a/chrome/browser/dom_ui/filebrowse_ui.cc +++ b/chrome/browser/dom_ui/filebrowse_ui.cc @@ -126,7 +126,8 @@ class FilebrowseHandler : public net::DirectoryLister::DirectoryListerDelegate, // DownloadManager::Observer interface virtual void ModelChanged(); - virtual void SetDownloads(std::vector<DownloadItem*>& downloads); + + void OnSearchDownloadsComplete(std::vector<DownloadItem*> downloads); // Callback for the "getRoots" message. void HandleGetRoots(const Value* value); @@ -969,7 +970,8 @@ void FilebrowseHandler::ModelChanged() { download_manager_->GetAllDownloads(this, FilePath()); } -void FilebrowseHandler::SetDownloads(std::vector<DownloadItem*>& downloads) { +void FilebrowseHandler::OnSearchDownloadsComplete( + std::vector<DownloadItem*> downloads) { ClearDownloadItems(); std::vector<DownloadItem*> new_downloads; // Scan for any in progress downloads and add ourself to them as an observer. diff --git a/chrome/browser/download/download_history.cc b/chrome/browser/download/download_history.cc new file mode 100644 index 0000000..7c84385 --- /dev/null +++ b/chrome/browser/download/download_history.cc @@ -0,0 +1,151 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "chrome/browser/download/download_history.h" + +#include "base/logging.h" +#include "chrome/browser/history/download_types.h" +#include "chrome/browser/history/history_marshaling.h" +#include "chrome/browser/download/download_item.h" +#include "chrome/browser/profile.h" + +// Our download table ID starts at 1, so we use 0 to represent a download that +// has started, but has not yet had its data persisted in the table. We use fake +// database handles in incognito mode starting at -1 and progressively getting +// more negative. +// static +const int DownloadHistory::kUninitializedHandle = 0; + +DownloadHistory::DownloadHistory(Profile* profile, DownloadItemMapper* mapper) + : profile_(profile), + next_fake_db_handle_(kUninitializedHandle - 1), + download_item_mapper_(mapper) { + DCHECK(profile); + DCHECK(mapper); +} + +void DownloadHistory::Load(HistoryService::DownloadQueryCallback* callback) { + DCHECK(callback); + HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); + if (!hs) { + delete callback; + return; + } + hs->QueryDownloads(&history_consumer_, callback); + + // This is the initial load, so do a cleanup of corrupt in-progress entries. + hs->CleanUpInProgressEntries(); +} + +void DownloadHistory::Search(const string16& query, + DownloadSearchCallback* callback) { + HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); + if (!hs) { + delete callback; + return; + } + + HistoryService::Handle handle = hs->SearchDownloads( + query, + &history_consumer_, + NewCallback(this, &DownloadHistory::OnSearchDownloadsComplete)); + history_consumer_.SetClientData(hs, handle, callback); +} + +void DownloadHistory::AddEntry( + const DownloadCreateInfo& info, + DownloadItem* download_item, + HistoryService::DownloadCreateCallback* callback) { + // Do not store the download in the history database for a few special cases: + // - incognito mode (that is the point of this mode) + // - extensions (users don't think of extension installation as 'downloading') + // - temporary download, like in drag-and-drop + // - history service is not available (e.g. in tests) + // We have to make sure that these handles don't collide with normal db + // handles, so we use a negative value. Eventually, they could overlap, but + // you'd have to do enough downloading that your ISP would likely stab you in + // the neck first. YMMV. + // FIXME(paulg) see bug 958058. EXPLICIT_ACCESS below is wrong. + HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); + if (download_item->is_otr() || download_item->is_extension_install() || + download_item->is_temporary() || !hs) { + callback->RunWithParams( + history::DownloadCreateRequest::TupleType(info, GetNextFakeDbHandle())); + delete callback; + return; + } + + hs->CreateDownload(info, &history_consumer_, callback); +} + +void DownloadHistory::UpdateEntry(DownloadItem* download_item) { + // Don't store info in the database if the download was initiated while in + // incognito mode or if it hasn't been initialized in our database table. + if (download_item->db_handle() <= kUninitializedHandle) + return; + + // FIXME(paulg) see bug 958058. EXPLICIT_ACCESS below is wrong. + HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); + if (!hs) + return; + + hs->UpdateDownload(download_item->received_bytes(), + download_item->state(), + download_item->db_handle()); +} + +void DownloadHistory::UpdateDownloadPath(DownloadItem* download_item, + const FilePath& new_path) { + // No update necessary if the download was initiated while in incognito mode. + if (download_item->db_handle() <= kUninitializedHandle) + return; + + // FIXME(paulg) see bug 958058. EXPLICIT_ACCESS below is wrong. + HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); + if (hs) + hs->UpdateDownloadPath(new_path, download_item->db_handle()); +} + +void DownloadHistory::RemoveEntry(DownloadItem* download_item) { + // No update necessary if the download was initiated while in incognito mode. + if (download_item->db_handle() <= kUninitializedHandle) + return; + + // FIXME(paulg) see bug 958058. EXPLICIT_ACCESS below is wrong. + HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); + if (hs) + hs->RemoveDownload(download_item->db_handle()); +} + +void DownloadHistory::RemoveEntriesBetween(const base::Time remove_begin, + const base::Time remove_end) { + // FIXME(paulg) see bug 958058. EXPLICIT_ACCESS below is wrong. + HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); + if (hs) + hs->RemoveDownloadsBetween(remove_begin, remove_end); +} + +void DownloadHistory::OnSearchDownloadsComplete(HistoryService::Handle handle, + std::vector<int64>* results) { + HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); + DownloadSearchCallback* callback = + history_consumer_.GetClientData(hs, handle); + if (!callback) + return; + + std::vector<DownloadItem*> download_items; + for (std::vector<int64>::iterator i = results->begin(); + i != results->end(); ++i) { + DownloadItem* download_item = + download_item_mapper_->GetDownloadItemFromDbHandle(*i); + if (download_item) + download_items.push_back(download_item); + } + + callback->RunWithParams(MakeTuple(download_items)); +} + +int64 DownloadHistory::GetNextFakeDbHandle() { + return next_fake_db_handle_--; +} diff --git a/chrome/browser/download/download_history.h b/chrome/browser/download/download_history.h new file mode 100644 index 0000000..3fe789e --- /dev/null +++ b/chrome/browser/download/download_history.h @@ -0,0 +1,91 @@ +// Copyright (c) 2010 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef CHROME_BROWSER_DOWNLOAD_DOWNLOAD_HISTORY_H_ +#define CHROME_BROWSER_DOWNLOAD_DOWNLOAD_HISTORY_H_ +#pragma once + +#include <vector> + +#include "base/basictypes.h" +#include "chrome/browser/cancelable_request.h" +#include "chrome/browser/history/history.h" + +class DownloadItem; +class Profile; + +namespace base { +class Time; +} + +// Interacts with the HistoryService on behalf of the download subsystem. +class DownloadHistory { + public: + // Converts history database handles to download items. + class DownloadItemMapper { + public: + virtual ~DownloadItemMapper() {} + + // Returns a DownloadItem* corresponding to |db_handle|, or NULL if no such + // DownloadItem exists. + virtual DownloadItem* GetDownloadItemFromDbHandle(int64 db_handle) = 0; + }; + + // A fake download table ID which represents a download that has started, + // but is not yet in the table. + static const int kUninitializedHandle; + + typedef Callback1<std::vector<DownloadItem*> >::Type DownloadSearchCallback; + + DownloadHistory(Profile* profile, DownloadItemMapper* mapper); + + // Retrieves DownloadCreateInfos saved in the history. + void Load(HistoryService::DownloadQueryCallback* callback); + + // Starts a history search for downloads and invokes |callback| when done. + void Search(const string16& query, + DownloadSearchCallback* callback); + + // Adds a new entry for a download to the history database. + void AddEntry(const DownloadCreateInfo& info, + DownloadItem* download_item, + HistoryService::DownloadCreateCallback* callback); + + // Updates the history entry for |download_item|. + void UpdateEntry(DownloadItem* download_item); + + // Updates the download path for |download_item| to |new_path|. + void UpdateDownloadPath(DownloadItem* download_item, + const FilePath& new_path); + + // Removes |download_item| from the history database. + void RemoveEntry(DownloadItem* download_item); + + // Removes download-related history entries in the given time range. + void RemoveEntriesBetween(const base::Time remove_begin, + const base::Time remove_end); + + // Returns a new unique database handle which will not collide with real ones. + int64 GetNextFakeDbHandle(); + + private: + void OnSearchDownloadsComplete(HistoryService::Handle handle, + std::vector<int64>* results); + + Profile* profile_; + + // In case we don't have a valid db_handle, we use |fake_db_handle_| instead. + // This is useful for incognito mode or when the history database is offline. + // Downloads are expected to have unique handles, so we decrement the next + // fake handle value on every use. + int64 next_fake_db_handle_; + + DownloadItemMapper* download_item_mapper_; + + CancelableRequestConsumerTSimple<DownloadSearchCallback*> history_consumer_; + + DISALLOW_COPY_AND_ASSIGN(DownloadHistory); +}; + +#endif // CHROME_BROWSER_DOWNLOAD_DOWNLOAD_HISTORY_H_ diff --git a/chrome/browser/download/download_item.cc b/chrome/browser/download/download_item.cc index f67b1a1..905d00f 100644 --- a/chrome/browser/download/download_item.cc +++ b/chrome/browser/download/download_item.cc @@ -6,6 +6,7 @@ #include "base/logging.h" #include "base/timer.h" +#include "chrome/browser/download/download_history.h" #include "chrome/browser/download/download_manager.h" #include "chrome/browser/download/download_util.h" #include "chrome/browser/history/download_types.h" @@ -68,7 +69,7 @@ DownloadItem::DownloadItem(DownloadManager* download_manager, start_tick_(base::TimeTicks::Now()), state_(IN_PROGRESS), start_time_(info.start_time), - db_handle_(DownloadManager::kUninitializedHandle), + db_handle_(DownloadHistory::kUninitializedHandle), download_manager_(download_manager), is_paused_(false), open_when_complete_(false), @@ -103,7 +104,7 @@ DownloadItem::DownloadItem(DownloadManager* download_manager, start_tick_(base::TimeTicks::Now()), state_(IN_PROGRESS), start_time_(base::Time::Now()), - db_handle_(DownloadManager::kUninitializedHandle), + db_handle_(DownloadHistory::kUninitializedHandle), download_manager_(download_manager), is_paused_(false), open_when_complete_(false), diff --git a/chrome/browser/download/download_item.h b/chrome/browser/download/download_item.h index 1a9a5ef..110f2fa 100644 --- a/chrome/browser/download/download_item.h +++ b/chrome/browser/download/download_item.h @@ -171,7 +171,6 @@ class DownloadItem { void set_db_handle(int64 handle) { db_handle_ = handle; } int64 db_handle() const { return db_handle_; } bool is_paused() const { return is_paused_; } - void set_is_paused(bool pause) { is_paused_ = pause; } bool open_when_complete() const { return open_when_complete_; } void set_open_when_complete(bool open) { open_when_complete_ = open; } int render_process_id() const { return render_process_id_; } diff --git a/chrome/browser/download/download_manager.cc b/chrome/browser/download/download_manager.cc index b12db28..f2e3a65 100644 --- a/chrome/browser/download/download_manager.cc +++ b/chrome/browser/download/download_manager.cc @@ -19,6 +19,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/chrome_thread.h" #include "chrome/browser/download/download_file_manager.h" +#include "chrome/browser/download/download_history.h" #include "chrome/browser/download/download_item.h" #include "chrome/browser/download/download_util.h" #include "chrome/browser/extensions/crx_installer.h" @@ -66,13 +67,6 @@ void DeleteDownloadedFile(const FilePath& path) { } // namespace -// Our download table ID starts at 1, so we use 0 to represent a download that -// has started, but has not yet had its data persisted in the table. We use fake -// database handles in incognito mode starting at -1 and progressively getting -// more negative. -// static -const int DownloadManager::kUninitializedHandle = 0; - // static void DownloadManager::RegisterUserPrefs(PrefService* prefs) { prefs->RegisterBooleanPref(prefs::kPromptForDownload, false); @@ -109,8 +103,7 @@ void DownloadManager::RegisterUserPrefs(PrefService* prefs) { DownloadManager::DownloadManager() : shutdown_needed_(false), profile_(NULL), - file_manager_(NULL), - fake_db_handle_(kUninitializedHandle - 1) { + file_manager_(NULL) { } DownloadManager::~DownloadManager() { @@ -127,9 +120,6 @@ void DownloadManager::Shutdown() { if (file_manager_) file_manager_->RemoveDownloadManager(this); - // Stop making history service requests - cancelable_consumer_.CancelAllRequests(); - // 'in_progress_' may contain DownloadItems that have not finished the start // complete (from the history service) and thus aren't in downloads_. DownloadMap::iterator it = in_progress_.begin(); @@ -145,8 +135,8 @@ void DownloadManager::Shutdown() { } DCHECK_EQ(DownloadItem::IN_PROGRESS, download->state()); download->Cancel(false); - UpdateHistoryForDownload(download); - if (download->db_handle() == kUninitializedHandle) { + download_history_->UpdateEntry(download); + if (download->db_handle() == DownloadHistory::kUninitializedHandle) { // An invalid handle means that 'download' does not yet exist in // 'downloads_', so we have to delete it here. delete download; @@ -167,7 +157,7 @@ void DownloadManager::Shutdown() { download->Remove(true); // Same as above, delete the download if it is not in 'downloads_' (as the // Remove() call above won't have deleted it). - if (handle == kUninitializedHandle) + if (handle == DownloadHistory::kUninitializedHandle) delete download; } to_remove.clear(); @@ -186,123 +176,38 @@ void DownloadManager::Shutdown() { if (select_file_dialog_.get()) select_file_dialog_->ListenerDestroyed(); - shutdown_needed_ = false; -} - -// Issue a history query for downloads matching 'search_text'. If 'search_text' -// is empty, return all downloads that we know about. -void DownloadManager::GetDownloads(Observer* observer, - const std::wstring& search_text) { - std::vector<DownloadItem*> otr_downloads; - - if (profile_->IsOffTheRecord() && search_text.empty()) { - // List all incognito downloads and add that to the downloads the parent - // profile lists. - otr_downloads.reserve(downloads_.size()); - for (DownloadMap::iterator it = downloads_.begin(); - it != downloads_.end(); ++it) { - DownloadItem* download = it->second; - if (download->is_otr() && !download->is_extension_install() && - !download->is_temporary()) { - otr_downloads.push_back(download); - } - } - } - - profile_->GetOriginalProfile()->GetDownloadManager()-> - DoGetDownloads(observer, search_text, otr_downloads); -} - -void DownloadManager::DoGetDownloads( - Observer* observer, - const std::wstring& search_text, - std::vector<DownloadItem*>& otr_downloads) { - DCHECK(observer); - - // Return a empty list if we've not yet received the set of downloads from the - // history system (we'll update all observers once we get that list in - // OnQueryDownloadEntriesComplete), or if there are no downloads at all. - if (downloads_.empty()) { - observer->SetDownloads(otr_downloads); - return; - } - - std::vector<DownloadItem*> download_copy; - // We already know all the downloads and there is no filter, so just return a - // copy to the observer. - if (search_text.empty()) { - download_copy.reserve(downloads_.size()); - for (DownloadMap::iterator it = downloads_.begin(); - it != downloads_.end(); ++it) { - if (it->second->db_handle() > kUninitializedHandle) - download_copy.push_back(it->second); - } - - // Merge sort based on start time. - std::vector<DownloadItem*> merged_downloads; - std::merge(otr_downloads.begin(), otr_downloads.end(), - download_copy.begin(), download_copy.end(), - std::back_inserter(merged_downloads), - CompareStartTime); + download_history_.reset(); - // We retain ownership of the DownloadItems. - observer->SetDownloads(merged_downloads); - return; - } - - DCHECK(otr_downloads.empty()); - - // Issue a request to the history service for a list of downloads matching - // our search text. - HistoryService* hs = - profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); - if (hs) { - HistoryService::Handle h = - hs->SearchDownloads(WideToUTF16(search_text), - &cancelable_consumer_, - NewCallback(this, - &DownloadManager::OnSearchComplete)); - cancelable_consumer_.SetClientData(hs, h, observer); - } + shutdown_needed_ = false; } -void DownloadManager::GetTemporaryDownloads(Observer* observer, - const FilePath& dir_path) { - DCHECK(observer); - - std::vector<DownloadItem*> download_copy; +void DownloadManager::GetTemporaryDownloads( + const FilePath& dir_path, std::vector<DownloadItem*>* result) { + DCHECK(result); for (DownloadMap::iterator it = downloads_.begin(); it != downloads_.end(); ++it) { if (it->second->is_temporary() && it->second->full_path().DirName() == dir_path) - download_copy.push_back(it->second); + result->push_back(it->second); } - - observer->SetDownloads(download_copy); } -void DownloadManager::GetAllDownloads(Observer* observer, - const FilePath& dir_path) { - DCHECK(observer); - - std::vector<DownloadItem*> download_copy; +void DownloadManager::GetAllDownloads( + const FilePath& dir_path, std::vector<DownloadItem*>* result) { + DCHECK(result); for (DownloadMap::iterator it = downloads_.begin(); it != downloads_.end(); ++it) { if (!it->second->is_temporary() && (dir_path.empty() || it->second->full_path().DirName() == dir_path)) - download_copy.push_back(it->second); + result->push_back(it->second); } - - observer->SetDownloads(download_copy); } -void DownloadManager::GetCurrentDownloads(Observer* observer, - const FilePath& dir_path) { - DCHECK(observer); - - std::vector<DownloadItem*> download_copy; +void DownloadManager::GetCurrentDownloads( + const FilePath& dir_path, std::vector<DownloadItem*>* result) { + DCHECK(result); for (DownloadMap::iterator it = downloads_.begin(); it != downloads_.end(); ++it) { @@ -310,10 +215,8 @@ void DownloadManager::GetCurrentDownloads(Observer* observer, (it->second->state() == DownloadItem::IN_PROGRESS || it->second->safety_state() == DownloadItem::DANGEROUS) && (dir_path.empty() || it->second->full_path().DirName() == dir_path)) - download_copy.push_back(it->second); + result->push_back(it->second); } - - observer->SetDownloads(download_copy); } // Query the history service for information about all persisted downloads. @@ -324,14 +227,9 @@ bool DownloadManager::Init(Profile* profile) { profile_ = profile; request_context_getter_ = profile_->GetRequestContext(); - - // 'incognito mode' will have access to past downloads, but we won't store - // 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(); + download_history_.reset(new DownloadHistory(profile, this)); + download_history_->Load( + NewCallback(this, &DownloadManager::OnQueryDownloadEntriesComplete)); // In test mode, there may be no ResourceDispatcherHost. In this case it's // safe to avoid setting |file_manager_| because we only call a small set of @@ -376,27 +274,6 @@ bool DownloadManager::Init(Profile* profile) { return true; } -void DownloadManager::QueryHistoryForDownloads() { - HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); - if (hs) { - hs->QueryDownloads( - &cancelable_consumer_, - NewCallback(this, &DownloadManager::OnQueryDownloadEntriesComplete)); - } -} - -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 @@ -613,71 +490,18 @@ void DownloadManager::ContinueStartDownload(DownloadCreateInfo* info, download->Rename(target_path); - // Do not store the download in the history database for a few special cases: - // - incognito mode (that is the point of this mode) - // - extensions (users don't think of extension installation as 'downloading') - // - temporary download, like in drag-and-drop - // - history service is not available (e.g. in tests) - // We have to make sure that these handles don't collide with normal db - // handles, so we use a negative value. Eventually, they could overlap, but - // you'd have to do enough downloading that your ISP would likely stab you in - // the neck first. YMMV. - // FIXME(paulg) see bug 958058. EXPLICIT_ACCESS below is wrong. - HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); - if (download->is_otr() || download->is_extension_install() || - download->is_temporary() || !hs) { - OnCreateDownloadEntryComplete(*info, fake_db_handle_.GetNext()); - } else { - // Update the history system with the new download. - hs->CreateDownload( - *info, &cancelable_consumer_, - NewCallback(this, &DownloadManager::OnCreateDownloadEntryComplete)); - } + download_history_->AddEntry(*info, download, + NewCallback(this, &DownloadManager::OnCreateDownloadEntryComplete)); UpdateAppIcon(); } -// Convenience function for updating the history service for a download. -void DownloadManager::UpdateHistoryForDownload(DownloadItem* download) { - DCHECK(download); - - // Don't store info in the database if the download was initiated while in - // incognito mode or if it hasn't been initialized in our database table. - if (download->db_handle() <= kUninitializedHandle) - return; - - // FIXME(paulg) see bug 958058. EXPLICIT_ACCESS below is wrong. - HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); - if (hs) { - hs->UpdateDownload(download->received_bytes(), - download->state(), - download->db_handle()); - } -} - -void DownloadManager::RemoveDownloadFromHistory(DownloadItem* download) { - DCHECK(download); - // FIXME(paulg) see bug 958058. EXPLICIT_ACCESS below is wrong. - HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); - if (download->db_handle() > kUninitializedHandle && hs) - hs->RemoveDownload(download->db_handle()); -} - -void DownloadManager::RemoveDownloadsFromHistoryBetween( - const base::Time remove_begin, - const base::Time remove_end) { - // FIXME(paulg) see bug 958058. EXPLICIT_ACCESS below is wrong. - HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); - if (hs) - hs->RemoveDownloadsBetween(remove_begin, remove_end); -} - void DownloadManager::UpdateDownload(int32 download_id, int64 size) { DownloadMap::iterator it = in_progress_.find(download_id); if (it != in_progress_.end()) { DownloadItem* download = it->second; download->Update(size); - UpdateHistoryForDownload(download); + download_history_->UpdateEntry(download); } UpdateAppIcon(); } @@ -707,9 +531,9 @@ void DownloadManager::DownloadFinished(int32 download_id, int64 size) { // Clean up will happen when the history system create callback runs if we // don't have a valid db_handle yet. - if (download->db_handle() != kUninitializedHandle) { + if (download->db_handle() != DownloadHistory::kUninitializedHandle) { in_progress_.erase(it); - UpdateHistoryForDownload(download); + download_history_->UpdateEntry(download); } UpdateAppIcon(); @@ -861,9 +685,9 @@ void DownloadManager::DownloadCancelled(int32 download_id) { // Clean up will happen when the history system create callback runs if we // don't have a valid db_handle yet. - if (download->db_handle() != kUninitializedHandle) { + if (download->db_handle() != DownloadHistory::kUninitializedHandle) { in_progress_.erase(it); - UpdateHistoryForDownload(download); + download_history_->UpdateEntry(download); } DownloadCancelledInternal(download_id, @@ -956,17 +780,7 @@ void DownloadManager::UpdateAppIcon() { void DownloadManager::RenameDownload(DownloadItem* download, const FilePath& new_path) { download->Rename(new_path); - - // Update the history. - - // No update necessary if the download was initiated while in incognito mode. - if (download->db_handle() <= kUninitializedHandle) - return; - - // FIXME(paulg) see bug 958058. EXPLICIT_ACCESS below is wrong. - HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); - if (hs) - hs->UpdateDownloadPath(new_path, download->db_handle()); + download_history_->UpdateDownloadPath(download, new_path); } void DownloadManager::RemoveDownload(int64 download_handle) { @@ -976,7 +790,7 @@ void DownloadManager::RemoveDownload(int64 download_handle) { // Make history update. DownloadItem* download = it->second; - RemoveDownloadFromHistory(download); + download_history_->RemoveEntry(download); // Remove from our tables and delete. downloads_.erase(it); @@ -992,7 +806,7 @@ void DownloadManager::RemoveDownload(int64 download_handle) { int DownloadManager::RemoveDownloadsBetween(const base::Time remove_begin, const base::Time remove_end) { - RemoveDownloadsFromHistoryBetween(remove_begin, remove_end); + download_history_->RemoveEntriesBetween(remove_begin, remove_end); DownloadMap::iterator it = downloads_.begin(); std::vector<DownloadItem*> pending_deletes; @@ -1412,6 +1226,16 @@ void DownloadManager::SaveAutoOpens() { } } +DownloadItem* DownloadManager::GetDownloadItemFromDbHandle(int64 db_handle) { + for (DownloadMap::iterator it = downloads_.begin(); + it != downloads_.end(); ++it) { + DownloadItem* item = it->second; + if (item->db_handle() == db_handle) + return item; + } + return NULL; +} + void DownloadManager::FileSelected(const FilePath& path, int index, void* params) { DownloadCreateInfo* info = reinterpret_cast<DownloadCreateInfo*>(params); @@ -1505,10 +1329,10 @@ void DownloadManager::OnCreateDownloadEntryComplete(DownloadCreateInfo info, // happen when the history database is offline. We cannot have multiple // DownloadItems with the same invalid db_handle, so we need to assign a // unique |db_handle| here. - if (db_handle == kUninitializedHandle) - db_handle = fake_db_handle_.GetNext(); + if (db_handle == DownloadHistory::kUninitializedHandle) + db_handle = download_history_->GetNextFakeDbHandle(); - DCHECK(download->db_handle() == kUninitializedHandle); + DCHECK(download->db_handle() == DownloadHistory::kUninitializedHandle); download->set_db_handle(db_handle); // Insert into our full map. @@ -1527,33 +1351,13 @@ void DownloadManager::OnCreateDownloadEntryComplete(DownloadCreateInfo info, // observers so that they get more than just the start notification. if (download->state() != DownloadItem::IN_PROGRESS) { in_progress_.erase(it); - UpdateHistoryForDownload(download); + download_history_->UpdateEntry(download); download->UpdateObservers(); } UpdateAppIcon(); } -// Called when the history service has retrieved the list of downloads that -// match the search text. -void DownloadManager::OnSearchComplete(HistoryService::Handle handle, - std::vector<int64>* results) { - HistoryService* hs = profile_->GetHistoryService(Profile::EXPLICIT_ACCESS); - Observer* requestor = cancelable_consumer_.GetClientData(hs, handle); - if (!requestor) - return; - - std::vector<DownloadItem*> searched_downloads; - for (std::vector<int64>::iterator it = results->begin(); - it != results->end(); ++it) { - DownloadMap::iterator dit = downloads_.find(*it); - if (dit != downloads_.end()) - searched_downloads.push_back(dit->second); - } - - requestor->SetDownloads(searched_downloads); -} - void DownloadManager::ShowDownloadInBrowser(const DownloadCreateInfo& info, DownloadItem* download) { // The 'contents' may no longer exist if the user closed the tab before we @@ -1619,10 +1423,6 @@ void DownloadManager::OtherDownloadManagerObserver::ModelChanged() { observing_download_manager_->NotifyModelChanged(); } -void DownloadManager::OtherDownloadManagerObserver::SetDownloads( - std::vector<DownloadItem*>& downloads) { -} - void DownloadManager::OtherDownloadManagerObserver::ManagerGoingDown() { observed_download_manager_ = NULL; } diff --git a/chrome/browser/download/download_manager.h b/chrome/browser/download/download_manager.h index ce7d76c..ce6901a 100644 --- a/chrome/browser/download/download_manager.h +++ b/chrome/browser/download/download_manager.h @@ -37,9 +37,9 @@ #include "base/file_path.h" #include "base/observer_list.h" #include "base/ref_counted.h" +#include "base/scoped_ptr.h" #include "base/time.h" -#include "chrome/browser/cancelable_request.h" -#include "chrome/browser/history/history.h" +#include "chrome/browser/download/download_history.h" #include "chrome/browser/pref_member.h" #include "chrome/browser/shell_dialogs.h" @@ -51,20 +51,18 @@ class Profile; class ResourceDispatcherHost; class URLRequestContextGetter; class TabContents; +struct DownloadCreateInfo; struct DownloadSaveInfo; // Browser's download manager: manages all downloads and destination view. class DownloadManager : public base::RefCountedThreadSafe<DownloadManager>, + public DownloadHistory::DownloadItemMapper, public SelectFileDialog::Listener { // For testing. friend class DownloadManagerTest; friend class MockDownloadManager; public: - // A fake download table ID which representas a download that has started, - // but is not yet in the table. - static const int kUninitializedHandle; - DownloadManager(); static void RegisterUserPrefs(PrefService* prefs); @@ -77,11 +75,6 @@ class DownloadManager : public base::RefCountedThreadSafe<DownloadManager>, // of downloads. virtual void ModelChanged() = 0; - // A callback once the DownloadManager has retrieved the requested set of - // downloads. The DownloadManagerObserver must copy the vector, but does not - // own the individual DownloadItems, when this call is made. - virtual void SetDownloads(std::vector<DownloadItem*>& downloads) = 0; - // Called when the DownloadManager is being destroyed to prevent Observers // from calling back to a stale pointer. virtual void ManagerGoingDown() {} @@ -90,44 +83,23 @@ class DownloadManager : public base::RefCountedThreadSafe<DownloadManager>, virtual ~Observer() {} }; - // Public API - - // If this download manager has an incognito profile, find all incognito - // downloads and pass them along to the parent profile's download manager - // via DoGetDownloads. Otherwise, just call DoGetDownloads(). - void GetDownloads(Observer* observer, - const std::wstring& search_text); - - // Begin a search for all downloads matching 'search_text'. If 'search_text' - // is empty, return all known downloads. The results are returned in the - // 'SetDownloads' observer callback. - void DoGetDownloads(Observer* observer, - const std::wstring& search_text, - std::vector<DownloadItem*>& otr_downloads); - // Return all temporary downloads that reside in the specified directory. - void GetTemporaryDownloads(Observer* observer, - const FilePath& dir_path); + void GetTemporaryDownloads(const FilePath& dir_path, + std::vector<DownloadItem*>* result); // Return all non-temporary downloads in the specified directory that are // are in progress or have finished. - void GetAllDownloads(Observer* observer, const FilePath& dir_path); + void GetAllDownloads(const FilePath& dir_path, + std::vector<DownloadItem*>* result); // Return all non-temporary downloads in the specified directory that are // either in-progress or finished but still waiting for user confirmation. - void GetCurrentDownloads(Observer* observer, const FilePath& dir_path); + void GetCurrentDownloads(const FilePath& dir_path, + std::vector<DownloadItem*>* result); // Returns true if initialized properly. bool Init(Profile* profile); - // 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); @@ -181,8 +153,6 @@ class DownloadManager : public base::RefCountedThreadSafe<DownloadManager>, void OnQueryDownloadEntriesComplete( std::vector<DownloadCreateInfo>* entries); void OnCreateDownloadEntryComplete(DownloadCreateInfo info, int64 db_handle); - void OnSearchComplete(HistoryService::Handle handle, - std::vector<int64>* results); // Display a new download in the appropriate browser UI. void ShowDownloadInBrowser(const DownloadCreateInfo& info, @@ -204,6 +174,8 @@ class DownloadManager : public base::RefCountedThreadSafe<DownloadManager>, FilePath download_path() { return *download_path_; } + DownloadHistory* download_history() { return download_history_.get(); } + // Clears the last download path, used to initialize "save as" dialogs. void ClearLastDownloadPath(); @@ -231,6 +203,9 @@ class DownloadManager : public base::RefCountedThreadSafe<DownloadManager>, // types. bool HasAutoOpenFileTypesRegistered() const; + // Overridden from DownloadHistory::DownloadItemMapper: + virtual DownloadItem* GetDownloadItemFromDbHandle(int64 db_handle); + // Overridden from SelectFileDialog::Listener: virtual void FileSelected(const FilePath& path, int index, void* params); virtual void FileSelectionCanceled(void* params); @@ -255,15 +230,6 @@ class DownloadManager : public base::RefCountedThreadSafe<DownloadManager>, FilePath* generated_name); private: - class FakeDbHandleGenerator { - public: - explicit FakeDbHandleGenerator(int64 start_value) : value_(start_value) {} - - int64 GetNext() { return value_--; } - private: - int64 value_; - }; - // This class is used to let an incognito DownloadManager observe changes to // a normal DownloadManager, to propagate ModelChanged() calls from the parent // DownloadManager to the observers of the incognito DownloadManager. @@ -275,7 +241,6 @@ class DownloadManager : public base::RefCountedThreadSafe<DownloadManager>, // Observer interface. virtual void ModelChanged(); - virtual void SetDownloads(std::vector<DownloadItem*>& downloads); virtual void ManagerGoingDown(); private: @@ -319,13 +284,6 @@ class DownloadManager : public base::RefCountedThreadSafe<DownloadManager>, void ContinueStartDownload(DownloadCreateInfo* info, const FilePath& target_path); - // Update the history service for a particular download. - // Marked virtual for testing. - virtual void UpdateHistoryForDownload(DownloadItem* download); - void RemoveDownloadFromHistory(DownloadItem* download); - void RemoveDownloadsFromHistoryBetween(const base::Time remove_begin, - const base::Time remove_before); - // Create an extension based on the file name and mime type. static void GenerateExtension(const FilePath& file_name, const std::string& mime_type, @@ -425,8 +383,7 @@ class DownloadManager : public base::RefCountedThreadSafe<DownloadManager>, Profile* profile_; scoped_refptr<URLRequestContextGetter> request_context_getter_; - // Used for history service request management. - CancelableRequestConsumerTSimple<Observer*> cancelable_consumer_; + scoped_ptr<DownloadHistory> download_history_; // Non-owning pointer for handling file writing on the download_thread_. DownloadFileManager* file_manager_; @@ -461,12 +418,6 @@ class DownloadManager : public base::RefCountedThreadSafe<DownloadManager>, // saved. scoped_refptr<SelectFileDialog> select_file_dialog_; - // In case we don't have a valid db_handle, we use |fake_db_handle_| instead. - // This is useful for incognito mode or when the history database is offline. - // Downloads are expected to have unique handles, so FakeDbHandleGenerator - // automatically decrement the handle value on every use. - FakeDbHandleGenerator fake_db_handle_; - scoped_ptr<OtherDownloadManagerObserver> other_download_manager_observer_; DISALLOW_COPY_AND_ASSIGN(DownloadManager); diff --git a/chrome/browser/download/drag_download_file.cc b/chrome/browser/download/drag_download_file.cc index 4b2b370..ad99b75 100644 --- a/chrome/browser/download/drag_download_file.cc +++ b/chrome/browser/download/drag_download_file.cc @@ -151,17 +151,13 @@ void DragDownloadFile::DownloadCompleted(bool is_successful) { void DragDownloadFile::ModelChanged() { AssertCurrentlyOnUIThread(); - download_manager_->GetTemporaryDownloads(this, file_path_.DirName()); -} - -void DragDownloadFile::SetDownloads(std::vector<DownloadItem*>& downloads) { - AssertCurrentlyOnUIThread(); - - std::vector<DownloadItem*>::const_iterator it = downloads.begin(); - for (; it != downloads.end(); ++it) { - if (!download_item_observer_added_ && (*it)->url() == url_) { + std::vector<DownloadItem*> downloads; + download_manager_->GetTemporaryDownloads(file_path_.DirName(), &downloads); + for (std::vector<DownloadItem*>::const_iterator i = downloads.begin(); + i != downloads.end(); ++i) { + if (!download_item_observer_added_ && (*i)->url() == url_) { download_item_observer_added_ = true; - (*it)->AddObserver(this); + (*i)->AddObserver(this); } } } diff --git a/chrome/browser/download/drag_download_file.h b/chrome/browser/download/drag_download_file.h index 34fefaa..a6cb190 100644 --- a/chrome/browser/download/drag_download_file.h +++ b/chrome/browser/download/drag_download_file.h @@ -52,7 +52,6 @@ class DragDownloadFile : public DownloadFileProvider, // DownloadManager::Observer methods. // Called on UI thread. virtual void ModelChanged(); - virtual void SetDownloads(std::vector<DownloadItem*>& downloads); // DownloadItem::Observer methods. // Called on UI thread. |