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); |
} |