| Index: chrome/browser/ui/webui/downloads_dom_handler.cc
|
| diff --git a/chrome/browser/ui/webui/downloads_dom_handler.cc b/chrome/browser/ui/webui/downloads_dom_handler.cc
|
| index 60bdcf5797957bec8748b5c567d281f29b36c8dd..76acbccb5a7854c704d640309e7de7148411221d 100644
|
| --- a/chrome/browser/ui/webui/downloads_dom_handler.cc
|
| +++ b/chrome/browser/ui/webui/downloads_dom_handler.cc
|
| @@ -12,6 +12,7 @@
|
| #include "base/bind_helpers.h"
|
| #include "base/i18n/rtl.h"
|
| #include "base/i18n/time_formatting.h"
|
| +#include "base/logging.h"
|
| #include "base/memory/singleton.h"
|
| #include "base/metrics/field_trial.h"
|
| #include "base/metrics/histogram.h"
|
| @@ -199,7 +200,7 @@ base::DictionaryValue* CreateDownloadItemValue(
|
| download_model.GetTabProgressStatusText());
|
|
|
| file_value->SetInteger("percent",
|
| - static_cast<int>(download_item->PercentComplete()));
|
| + std::max(0, static_cast<int>(download_item->PercentComplete())));
|
| file_value->SetInteger("received",
|
| static_cast<int>(download_item->GetReceivedBytes()));
|
| break;
|
| @@ -324,33 +325,50 @@ void DownloadsDOMHandler::OnDownloadCreated(
|
| content::DownloadManager* manager, content::DownloadItem* download_item) {
|
| if (IsDownloadDisplayable(*download_item))
|
| ScheduleSendCurrentDownloads();
|
| + else
|
| + new_downloads_.insert(download_item->GetId());
|
| }
|
|
|
| void DownloadsDOMHandler::OnDownloadUpdated(
|
| content::DownloadManager* manager,
|
| content::DownloadItem* download_item) {
|
| - if (IsDownloadDisplayable(*download_item)) {
|
| - if (search_terms_ && !search_terms_->empty()) {
|
| - // Don't CallDownloadUpdated() if download_item doesn't match
|
| - // search_terms_.
|
| - // TODO(benjhayden): Consider splitting MatchesQuery() out to a function.
|
| - content::DownloadManager::DownloadVector all_items, filtered_items;
|
| - all_items.push_back(download_item);
|
| - DownloadQuery query;
|
| - query.AddFilter(DownloadQuery::FILTER_QUERY, *search_terms_.get());
|
| - query.Search(all_items.begin(), all_items.end(), &filtered_items);
|
| - if (filtered_items.empty())
|
| - return;
|
| + bool showing_new_item = false;
|
| +
|
| + if (new_downloads_.count(download_item->GetId())) {
|
| + // A new download (that the page doesn't know about yet) has been updated.
|
| + if (!IsDownloadDisplayable(*download_item)) {
|
| + // Item isn't ready to be displayed yet. Wait until it is.
|
| + return;
|
| }
|
| - base::ListValue results_value;
|
| - results_value.Append(CreateDownloadItemValue(
|
| - download_item,
|
| - (original_notifier_.get() &&
|
| - (manager == main_notifier_.GetManager()))));
|
| - CallDownloadUpdated(results_value);
|
| - } else {
|
| +
|
| + new_downloads_.erase(download_item->GetId());
|
| + showing_new_item = true;
|
| + }
|
| +
|
| + if (showing_new_item || DownloadItemModel(download_item).IsBeingRevived() ||
|
| + !IsDownloadDisplayable(*download_item)) {
|
| + // A download will be shown or hidden by this update. Resend the list.
|
| ScheduleSendCurrentDownloads();
|
| + return;
|
| }
|
| +
|
| + if (search_terms_ && !search_terms_->empty()) {
|
| + // Don't CallUpdateItem() if download_item doesn't match
|
| + // search_terms_.
|
| + // TODO(benjhayden): Consider splitting MatchesQuery() out to a function.
|
| + content::DownloadManager::DownloadVector all_items, filtered_items;
|
| + all_items.push_back(download_item);
|
| + DownloadQuery query;
|
| + query.AddFilter(DownloadQuery::FILTER_QUERY, *search_terms_);
|
| + query.Search(all_items.begin(), all_items.end(), &filtered_items);
|
| + if (filtered_items.empty())
|
| + return;
|
| + }
|
| +
|
| + scoped_ptr<base::DictionaryValue> item(CreateDownloadItemValue(
|
| + download_item,
|
| + original_notifier_ && manager == main_notifier_.GetManager()));
|
| + CallUpdateItem(*item);
|
| }
|
|
|
| void DownloadsDOMHandler::OnDownloadRemoved(
|
| @@ -374,7 +392,7 @@ void DownloadsDOMHandler::OnDownloadRemoved(
|
|
|
| void DownloadsDOMHandler::HandleGetDownloads(const base::ListValue* args) {
|
| CountDownloadsDOMEvents(DOWNLOADS_DOM_EVENT_GET_DOWNLOADS);
|
| - search_terms_.reset((args && !args->empty()) ? args->DeepCopy() : NULL);
|
| + search_terms_.reset(args && !args->empty() ? args->DeepCopy() : NULL);
|
| SendCurrentDownloads();
|
| }
|
|
|
| @@ -471,8 +489,14 @@ void DownloadsDOMHandler::HandleUndo(const base::ListValue* args) {
|
| content::DownloadItem* download = GetDownloadById(id);
|
| if (!download)
|
| continue;
|
| - DownloadItemModel(download).SetShouldShowInShelf(true);
|
| +
|
| + DownloadItemModel model(download);
|
| + model.SetShouldShowInShelf(true);
|
| + model.SetIsBeingRevived(true);
|
| +
|
| download->UpdateObservers();
|
| +
|
| + model.SetIsBeingRevived(false);
|
| }
|
| }
|
|
|
| @@ -484,8 +508,10 @@ void DownloadsDOMHandler::HandleCancel(const base::ListValue* args) {
|
| }
|
|
|
| void DownloadsDOMHandler::HandleClearAll(const base::ListValue* args) {
|
| - if (!IsDeletingHistoryAllowed())
|
| + if (!IsDeletingHistoryAllowed()) {
|
| + // This should only be reached during tests.
|
| return;
|
| + }
|
|
|
| CountDownloadsDOMEvents(DOWNLOADS_DOM_EVENT_CLEAR_ALL);
|
|
|
| @@ -500,6 +526,7 @@ void DownloadsDOMHandler::HandleClearAll(const base::ListValue* args) {
|
| void DownloadsDOMHandler::RemoveDownloads(
|
| const std::vector<content::DownloadItem*>& to_remove) {
|
| std::set<uint32> ids;
|
| +
|
| for (auto* download : to_remove) {
|
| DownloadItemModel item_model(download);
|
| if (!item_model.ShouldShowInShelf() ||
|
| @@ -511,6 +538,7 @@ void DownloadsDOMHandler::RemoveDownloads(
|
| ids.insert(download->GetId());
|
| download->UpdateObservers();
|
| }
|
| +
|
| if (!ids.empty())
|
| removals_.push_back(ids);
|
| }
|
| @@ -535,7 +563,9 @@ void DownloadsDOMHandler::ScheduleSendCurrentDownloads() {
|
| // in a single UI message loop iteration when the user Clears All downloads.
|
| if (update_scheduled_)
|
| return;
|
| +
|
| update_scheduled_ = true;
|
| +
|
| BrowserThread::PostTask(
|
| BrowserThread::UI, FROM_HERE,
|
| base::Bind(&DownloadsDOMHandler::SendCurrentDownloads,
|
| @@ -561,34 +591,33 @@ void DownloadsDOMHandler::FinalizeRemovals() {
|
|
|
| void DownloadsDOMHandler::SendCurrentDownloads() {
|
| update_scheduled_ = false;
|
| +
|
| content::DownloadManager::DownloadVector all_items, filtered_items;
|
| if (main_notifier_.GetManager()) {
|
| main_notifier_.GetManager()->GetAllDownloads(&all_items);
|
| main_notifier_.GetManager()->CheckForHistoryFilesRemoval();
|
| }
|
| - if (original_notifier_.get() && original_notifier_->GetManager()) {
|
| + if (original_notifier_ && original_notifier_->GetManager()) {
|
| original_notifier_->GetManager()->GetAllDownloads(&all_items);
|
| original_notifier_->GetManager()->CheckForHistoryFilesRemoval();
|
| }
|
| +
|
| DownloadQuery query;
|
| - if (search_terms_ && !search_terms_->empty()) {
|
| - query.AddFilter(DownloadQuery::FILTER_QUERY, *search_terms_.get());
|
| - }
|
| + if (search_terms_ && !search_terms_->empty())
|
| + query.AddFilter(DownloadQuery::FILTER_QUERY, *search_terms_);
|
| query.AddFilter(base::Bind(&IsDownloadDisplayable));
|
| query.AddSorter(DownloadQuery::SORT_START_TIME, DownloadQuery::DESCENDING);
|
| query.Limit(kMaxDownloads);
|
| query.Search(all_items.begin(), all_items.end(), &filtered_items);
|
| +
|
| base::ListValue results_value;
|
| - for (content::DownloadManager::DownloadVector::iterator
|
| - iter = filtered_items.begin(); iter != filtered_items.end(); ++iter) {
|
| + for (auto* item : filtered_items) {
|
| results_value.Append(CreateDownloadItemValue(
|
| - *iter,
|
| - (original_notifier_.get() &&
|
| - main_notifier_.GetManager() &&
|
| - (main_notifier_.GetManager()->GetDownload((*iter)->GetId()) ==
|
| - *iter))));
|
| + item,
|
| + original_notifier_ && main_notifier_.GetManager() &&
|
| + main_notifier_.GetManager()->GetDownload(item->GetId()) == item));
|
| }
|
| - CallDownloadsList(results_value);
|
| + CallUpdateAll(results_value);
|
| }
|
|
|
| void DownloadsDOMHandler::ShowDangerPrompt(
|
| @@ -620,9 +649,9 @@ void DownloadsDOMHandler::DangerPromptDone(
|
|
|
| bool DownloadsDOMHandler::IsDeletingHistoryAllowed() {
|
| content::DownloadManager* manager = main_notifier_.GetManager();
|
| - return (manager &&
|
| - Profile::FromBrowserContext(manager->GetBrowserContext())->
|
| - GetPrefs()->GetBoolean(prefs::kAllowDeletingBrowserHistory));
|
| + return manager &&
|
| + Profile::FromBrowserContext(manager->GetBrowserContext())->
|
| + GetPrefs()->GetBoolean(prefs::kAllowDeletingBrowserHistory);
|
| }
|
|
|
| content::DownloadItem* DownloadsDOMHandler::GetDownloadByValue(
|
| @@ -646,7 +675,7 @@ content::DownloadItem* DownloadsDOMHandler::GetDownloadById(uint32 id) {
|
| content::DownloadItem* item = NULL;
|
| if (GetMainNotifierManager())
|
| item = GetMainNotifierManager()->GetDownload(id);
|
| - if (!item && original_notifier_.get() && original_notifier_->GetManager())
|
| + if (!item && original_notifier_ && original_notifier_->GetManager())
|
| item = original_notifier_->GetManager()->GetDownload(id);
|
| return item;
|
| }
|
| @@ -655,11 +684,10 @@ content::WebContents* DownloadsDOMHandler::GetWebUIWebContents() {
|
| return web_ui()->GetWebContents();
|
| }
|
|
|
| -void DownloadsDOMHandler::CallDownloadsList(const base::ListValue& downloads) {
|
| - web_ui()->CallJavascriptFunction("downloadsList", downloads);
|
| +void DownloadsDOMHandler::CallUpdateAll(const base::ListValue& list) {
|
| + web_ui()->CallJavascriptFunction("downloads.Manager.updateAll", list);
|
| }
|
|
|
| -void DownloadsDOMHandler::CallDownloadUpdated(
|
| - const base::ListValue& download_item) {
|
| - web_ui()->CallJavascriptFunction("downloadUpdated", download_item);
|
| +void DownloadsDOMHandler::CallUpdateItem(const base::DictionaryValue& item) {
|
| + web_ui()->CallJavascriptFunction("downloads.Manager.updateItem", item);
|
| }
|
|
|