Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 1 // Copyright 2015 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/ui/webui/md_downloads/downloads_list_tracker.h" | 5 #include "chrome/browser/ui/webui/md_downloads/downloads_list_tracker.h" |
| 6 | 6 |
| 7 #include <iterator> | 7 #include <iterator> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/bind_helpers.h" | 10 #include "base/bind_helpers.h" |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 31 #include "ui/base/l10n/time_format.h" | 31 #include "ui/base/l10n/time_format.h" |
| 32 | 32 |
| 33 using content::BrowserContext; | 33 using content::BrowserContext; |
| 34 using content::DownloadItem; | 34 using content::DownloadItem; |
| 35 using content::DownloadManager; | 35 using content::DownloadManager; |
| 36 | 36 |
| 37 using DownloadVector = DownloadManager::DownloadVector; | 37 using DownloadVector = DownloadManager::DownloadVector; |
| 38 | 38 |
| 39 namespace { | 39 namespace { |
| 40 | 40 |
| 41 const size_t kChunkSize = 20u; | |
| 42 | |
| 41 // Returns a string constant to be used as the |danger_type| value in | 43 // Returns a string constant to be used as the |danger_type| value in |
| 42 // CreateDownloadItemValue(). Only return strings for DANGEROUS_FILE, | 44 // CreateDownloadItemValue(). Only return strings for DANGEROUS_FILE, |
| 43 // DANGEROUS_URL, DANGEROUS_CONTENT, and UNCOMMON_CONTENT because the | 45 // DANGEROUS_URL, DANGEROUS_CONTENT, and UNCOMMON_CONTENT because the |
| 44 // |danger_type| value is only defined if the value of |state| is |DANGEROUS|. | 46 // |danger_type| value is only defined if the value of |state| is |DANGEROUS|. |
| 45 const char* GetDangerTypeString(content::DownloadDangerType danger_type) { | 47 const char* GetDangerTypeString(content::DownloadDangerType danger_type) { |
| 46 switch (danger_type) { | 48 switch (danger_type) { |
| 47 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: | 49 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE: |
| 48 return "DANGEROUS_FILE"; | 50 return "DANGEROUS_FILE"; |
| 49 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: | 51 case content::DOWNLOAD_DANGER_TYPE_DANGEROUS_URL: |
| 50 return "DANGEROUS_URL"; | 52 return "DANGEROUS_URL"; |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 85 content::WebUI* web_ui) | 87 content::WebUI* web_ui) |
| 86 : main_notifier_(download_manager, this), | 88 : main_notifier_(download_manager, this), |
| 87 web_ui_(web_ui), | 89 web_ui_(web_ui), |
| 88 should_show_(base::Bind(&DownloadsListTracker::ShouldShow, | 90 should_show_(base::Bind(&DownloadsListTracker::ShouldShow, |
| 89 base::Unretained(this))) { | 91 base::Unretained(this))) { |
| 90 Init(); | 92 Init(); |
| 91 } | 93 } |
| 92 | 94 |
| 93 DownloadsListTracker::~DownloadsListTracker() {} | 95 DownloadsListTracker::~DownloadsListTracker() {} |
| 94 | 96 |
| 95 void DownloadsListTracker::CallClearAll() { | |
| 96 if (sending_updates_) | |
| 97 web_ui_->CallJavascriptFunction("downloads.Manager.clearAll"); | |
| 98 } | |
| 99 | |
| 100 bool DownloadsListTracker::SetSearchTerms(const base::ListValue& search_terms) { | 97 bool DownloadsListTracker::SetSearchTerms(const base::ListValue& search_terms) { |
| 101 std::vector<base::string16> new_terms; | 98 std::vector<base::string16> new_terms; |
| 102 new_terms.resize(search_terms.GetSize()); | 99 new_terms.resize(search_terms.GetSize()); |
| 103 | 100 |
| 104 for (size_t i = 0; i < search_terms.GetSize(); ++i) | 101 for (size_t i = 0; i < search_terms.GetSize(); ++i) |
| 105 search_terms.GetString(i, &new_terms[i]); | 102 search_terms.GetString(i, &new_terms[i]); |
| 106 | 103 |
| 107 if (new_terms == search_terms_) | 104 if (new_terms == search_terms_) |
| 108 return false; | 105 return false; |
| 109 | 106 |
| 110 search_terms_.swap(new_terms); | 107 search_terms_.swap(new_terms); |
| 111 RebuildSortedSet(); | 108 RebuildSortedItems(); |
| 112 return true; | 109 return true; |
| 113 } | 110 } |
| 114 | 111 |
| 115 void DownloadsListTracker::Start() { | 112 void DownloadsListTracker::StartAndSendChunk() { |
| 116 sending_updates_ = true; | 113 sending_updates_ = true; |
| 117 | 114 |
| 118 // TODO(dbeam): paging and limiting logic. | 115 CHECK_LE(sent_to_page_, sorted_items_.size()); |
| 116 | |
| 117 SortedSet::iterator it = sorted_items_.begin(); | |
| 118 std::advance(it, sent_to_page_); | |
| 119 | 119 |
| 120 base::ListValue list; | 120 base::ListValue list; |
| 121 for (auto* item : sorted_visible_items_) | 121 while (it != sorted_items_.end() && list.GetSize() < kChunkSize) { |
| 122 list.Append(CreateDownloadItemValue(item).Pass()); | 122 list.Append(CreateDownloadItemValue(*it).Pass()); |
| 123 ++it; | |
| 124 } | |
| 123 | 125 |
| 124 web_ui_->CallJavascriptFunction("downloads.Manager.insertItems", | 126 web_ui_->CallJavascriptFunction( |
| 125 base::FundamentalValue(0), list); | 127 "downloads.Manager.insertItems", |
| 128 base::FundamentalValue(static_cast<int>(sent_to_page_)), | |
| 129 list); | |
| 130 | |
| 131 sent_to_page_ += list.GetSize(); | |
| 126 } | 132 } |
| 127 | 133 |
| 128 void DownloadsListTracker::Stop() { | 134 void DownloadsListTracker::Reset() { |
| 135 if (sending_updates_) | |
| 136 web_ui_->CallJavascriptFunction("downloads.Manager.clearAll"); | |
| 137 | |
| 129 sending_updates_ = false; | 138 sending_updates_ = false; |
| 139 sent_to_page_ = 0u; | |
| 130 } | 140 } |
| 131 | 141 |
| 132 DownloadManager* DownloadsListTracker::GetMainNotifierManager() const { | 142 DownloadManager* DownloadsListTracker::GetMainNotifierManager() const { |
| 133 return main_notifier_.GetManager(); | 143 return main_notifier_.GetManager(); |
| 134 } | 144 } |
| 135 | 145 |
| 136 DownloadManager* DownloadsListTracker::GetOriginalNotifierManager() const { | 146 DownloadManager* DownloadsListTracker::GetOriginalNotifierManager() const { |
| 137 return original_notifier_ ? original_notifier_->GetManager() : nullptr; | 147 return original_notifier_ ? original_notifier_->GetManager() : nullptr; |
| 138 } | 148 } |
| 139 | 149 |
| 140 void DownloadsListTracker::OnDownloadCreated(DownloadManager* manager, | 150 void DownloadsListTracker::OnDownloadCreated(DownloadManager* manager, |
| 141 DownloadItem* download_item) { | 151 DownloadItem* download_item) { |
| 152 DCHECK_EQ(0u, sorted_items_.count(download_item)); | |
| 142 if (should_show_.Run(*download_item)) | 153 if (should_show_.Run(*download_item)) |
| 143 CallInsertItem(sorted_visible_items_.insert(download_item).first); | 154 InsertItem(sorted_items_.insert(download_item).first); |
| 144 } | 155 } |
| 145 | 156 |
| 146 void DownloadsListTracker::OnDownloadUpdated(DownloadManager* manager, | 157 void DownloadsListTracker::OnDownloadUpdated(DownloadManager* manager, |
| 147 DownloadItem* download_item) { | 158 DownloadItem* download_item) { |
| 148 auto current_position = sorted_visible_items_.find(download_item); | 159 auto current_position = sorted_items_.find(download_item); |
| 149 bool is_showing = current_position != sorted_visible_items_.end(); | 160 bool is_showing = current_position != sorted_items_.end(); |
| 150 bool should_show = should_show_.Run(*download_item); | 161 bool should_show = should_show_.Run(*download_item); |
| 151 | 162 |
| 152 if (!is_showing && should_show) | 163 if (!is_showing && should_show) |
| 153 CallInsertItem(sorted_visible_items_.insert(download_item).first); | 164 InsertItem(sorted_items_.insert(download_item).first); |
| 154 else if (is_showing && !should_show) | 165 else if (is_showing && !should_show) |
| 155 RemoveItem(current_position); | 166 RemoveItem(current_position); |
| 156 else if (is_showing) | 167 else if (is_showing) |
| 157 CallUpdateItem(current_position); | 168 UpdateItem(current_position); |
| 158 } | 169 } |
| 159 | 170 |
| 160 void DownloadsListTracker::OnDownloadRemoved(DownloadManager* manager, | 171 void DownloadsListTracker::OnDownloadRemoved(DownloadManager* manager, |
| 161 DownloadItem* download_item) { | 172 DownloadItem* download_item) { |
| 162 auto current_position = sorted_visible_items_.find(download_item); | 173 auto current_position = sorted_items_.find(download_item); |
| 163 if (current_position != sorted_visible_items_.end()) | 174 if (current_position != sorted_items_.end()) |
| 164 RemoveItem(current_position); | 175 RemoveItem(current_position); |
| 165 } | 176 } |
| 166 | 177 |
| 167 DownloadsListTracker::DownloadsListTracker( | 178 DownloadsListTracker::DownloadsListTracker( |
| 168 DownloadManager* download_manager, | 179 DownloadManager* download_manager, |
| 169 content::WebUI* web_ui, | 180 content::WebUI* web_ui, |
| 170 base::Callback<bool(const DownloadItem&)> should_show) | 181 base::Callback<bool(const DownloadItem&)> should_show) |
| 171 : main_notifier_(download_manager, this), | 182 : main_notifier_(download_manager, this), |
| 172 web_ui_(web_ui), | 183 web_ui_(web_ui), |
| 173 should_show_(should_show) { | 184 should_show_(should_show) { |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 302 file_value->SetInteger("percent", percent); | 313 file_value->SetInteger("percent", percent); |
| 303 file_value->SetString("progress_status_text", progress_status_text); | 314 file_value->SetString("progress_status_text", progress_status_text); |
| 304 file_value->SetBoolean("retry", retry); | 315 file_value->SetBoolean("retry", retry); |
| 305 file_value->SetString("state", state); | 316 file_value->SetString("state", state); |
| 306 | 317 |
| 307 return file_value.Pass(); | 318 return file_value.Pass(); |
| 308 } | 319 } |
| 309 | 320 |
| 310 const DownloadItem* DownloadsListTracker::GetItemForTesting(size_t index) | 321 const DownloadItem* DownloadsListTracker::GetItemForTesting(size_t index) |
| 311 const { | 322 const { |
| 312 if (index >= sorted_visible_items_.size()) | 323 if (index >= sorted_items_.size()) |
| 313 return nullptr; | 324 return nullptr; |
| 314 | 325 |
| 315 SortedSet::iterator it = sorted_visible_items_.begin(); | 326 SortedSet::iterator it = sorted_items_.begin(); |
| 316 std::advance(it, index); | 327 std::advance(it, index); |
| 317 return *it; | 328 return *it; |
| 318 } | 329 } |
| 319 | 330 |
| 320 bool DownloadsListTracker::ShouldShow(const DownloadItem& item) const { | 331 bool DownloadsListTracker::ShouldShow(const DownloadItem& item) const { |
| 321 return !download_crx_util::IsExtensionDownload(item) && | 332 return !download_crx_util::IsExtensionDownload(item) && |
| 322 !item.IsTemporary() && | 333 !item.IsTemporary() && |
| 323 !item.GetFileNameToReportUser().empty() && | 334 !item.GetFileNameToReportUser().empty() && |
| 324 !item.GetTargetFilePath().empty() && | 335 !item.GetTargetFilePath().empty() && |
| 325 DownloadItemModel(const_cast<DownloadItem*>(&item)).ShouldShowInShelf() && | 336 DownloadItemModel(const_cast<DownloadItem*>(&item)).ShouldShowInShelf() && |
| 326 DownloadQuery::MatchesQuery(search_terms_, item); | 337 DownloadQuery::MatchesQuery(search_terms_, item); |
| 327 } | 338 } |
| 328 | 339 |
| 329 bool DownloadsListTracker::StartTimeComparator::operator() ( | 340 bool DownloadsListTracker::StartTimeComparator::operator() ( |
| 330 const content::DownloadItem* a, const content::DownloadItem* b) const { | 341 const content::DownloadItem* a, const content::DownloadItem* b) const { |
| 331 return a->GetStartTime() > b->GetStartTime(); | 342 return a->GetStartTime() > b->GetStartTime(); |
| 332 } | 343 } |
| 333 | 344 |
| 334 void DownloadsListTracker::Init() { | 345 void DownloadsListTracker::Init() { |
| 335 Profile* profile = Profile::FromBrowserContext( | 346 Profile* profile = Profile::FromBrowserContext( |
| 336 GetMainNotifierManager()->GetBrowserContext()); | 347 GetMainNotifierManager()->GetBrowserContext()); |
| 337 if (profile->IsOffTheRecord()) { | 348 if (profile->IsOffTheRecord()) { |
| 338 original_notifier_.reset(new AllDownloadItemNotifier( | 349 original_notifier_.reset(new AllDownloadItemNotifier( |
| 339 BrowserContext::GetDownloadManager(profile->GetOriginalProfile()), | 350 BrowserContext::GetDownloadManager(profile->GetOriginalProfile()), |
| 340 this)); | 351 this)); |
| 341 } | 352 } |
| 342 | 353 |
| 343 RebuildSortedSet(); | 354 RebuildSortedItems(); |
| 344 } | 355 } |
| 345 | 356 |
| 346 void DownloadsListTracker::RebuildSortedSet() { | 357 void DownloadsListTracker::RebuildSortedItems() { |
| 347 DownloadVector all_items, visible_items; | 358 DownloadVector all_items, visible_items; |
| 348 | 359 |
| 349 GetMainNotifierManager()->GetAllDownloads(&all_items); | 360 GetMainNotifierManager()->GetAllDownloads(&all_items); |
| 350 | 361 |
| 351 if (GetOriginalNotifierManager()) | 362 if (GetOriginalNotifierManager()) |
| 352 GetOriginalNotifierManager()->GetAllDownloads(&all_items); | 363 GetOriginalNotifierManager()->GetAllDownloads(&all_items); |
| 353 | 364 |
| 354 DownloadQuery query; | 365 DownloadQuery query; |
| 355 query.AddFilter(should_show_); | 366 query.AddFilter(should_show_); |
| 356 query.Search(all_items.begin(), all_items.end(), &visible_items); | 367 query.Search(all_items.begin(), all_items.end(), &visible_items); |
| 357 | 368 |
| 358 SortedSet sorted_visible_items(visible_items.begin(), visible_items.end()); | 369 SortedSet sorted_items(visible_items.begin(), visible_items.end()); |
| 359 sorted_visible_items_.swap(sorted_visible_items); | 370 sorted_items_.swap(sorted_items); |
| 360 } | 371 } |
| 361 | 372 |
| 362 void DownloadsListTracker::CallInsertItem(const SortedSet::iterator& insert) { | 373 void DownloadsListTracker::InsertItem(const SortedSet::iterator& insert) { |
| 363 if (!sending_updates_) | 374 if (!sending_updates_) |
| 364 return; | 375 return; |
| 365 | 376 |
| 377 size_t index = GetIndex(insert); | |
| 378 if (index > kChunkSize && index >= sent_to_page_) | |
|
asanka
2015/12/04 21:03:56
What's the point of the (index > kChunkSize)? Don'
Dan Beam
2015/12/04 22:52:35
when the first download ever is created, sent_to_p
Dan Beam
2015/12/05 00:31:43
and if you were wondering how we avoid pathologica
asanka
2015/12/07 20:31:50
Ok. My misunderstanding was that I thought this co
Dan Beam
2015/12/09 06:55:21
the only way users currently know if there are mor
| |
| 379 return; | |
| 380 | |
| 366 base::ListValue list; | 381 base::ListValue list; |
| 367 list.Append(CreateDownloadItemValue(*insert).Pass()); | 382 list.Append(CreateDownloadItemValue(*insert).Pass()); |
| 368 | 383 |
| 369 web_ui_->CallJavascriptFunction("downloads.Manager.insertItems", | 384 web_ui_->CallJavascriptFunction( |
| 370 base::FundamentalValue(GetIndex(insert)), | 385 "downloads.Manager.insertItems", |
| 371 list); | 386 base::FundamentalValue(static_cast<int>(index)), |
| 387 list); | |
| 388 | |
| 389 sent_to_page_++; | |
| 372 } | 390 } |
| 373 | 391 |
| 374 void DownloadsListTracker::CallUpdateItem(const SortedSet::iterator& update) { | 392 void DownloadsListTracker::UpdateItem(const SortedSet::iterator& update) { |
| 375 if (!sending_updates_) | 393 if (!sending_updates_ || GetIndex(update) >= sent_to_page_) |
| 376 return; | 394 return; |
| 377 | 395 |
| 378 web_ui_->CallJavascriptFunction("downloads.Manager.updateItem", | 396 web_ui_->CallJavascriptFunction( |
| 379 base::FundamentalValue(GetIndex(update)), | 397 "downloads.Manager.updateItem", |
| 380 *CreateDownloadItemValue(*update)); | 398 base::FundamentalValue(static_cast<int>(GetIndex(update))), |
| 399 *CreateDownloadItemValue(*update)); | |
| 381 } | 400 } |
| 382 | 401 |
| 383 int DownloadsListTracker::GetIndex(const SortedSet::iterator& position) const { | 402 size_t DownloadsListTracker::GetIndex(const SortedSet::iterator& item) const { |
| 384 // TODO(dbeam): this could be log(N) if |position| was random access. | 403 // TODO(dbeam): this could be log(N) if |item| was random access. |
| 385 return std::distance(sorted_visible_items_.begin(), position); | 404 return std::distance(sorted_items_.begin(), item); |
| 386 } | 405 } |
| 387 | 406 |
| 388 void DownloadsListTracker::RemoveItem(const SortedSet::iterator& remove) { | 407 void DownloadsListTracker::RemoveItem(const SortedSet::iterator& remove) { |
| 389 if (sending_updates_) { | 408 if (sending_updates_) { |
| 390 web_ui_->CallJavascriptFunction("downloads.Manager.removeItem", | 409 size_t index = GetIndex(remove); |
| 391 base::FundamentalValue(GetIndex(remove))); | 410 if (index < sent_to_page_) { |
| 411 web_ui_->CallJavascriptFunction( | |
| 412 "downloads.Manager.removeItem", | |
| 413 base::FundamentalValue(static_cast<int>(index))); | |
| 414 sent_to_page_--; | |
| 415 } | |
| 392 } | 416 } |
| 393 sorted_visible_items_.erase(remove); | 417 sorted_items_.erase(remove); |
| 394 } | 418 } |
| OLD | NEW |