Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(87)

Side by Side Diff: chrome/browser/ui/webui/downloads_dom_handler.cc

Issue 722953002: downloads: add the ability to undo download removal. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: dcheck Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/downloads_dom_handler.h" 5 #include "chrome/browser/ui/webui/downloads_dom_handler.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <functional> 8 #include <functional>
9 9
10 #include "base/basictypes.h" 10 #include "base/basictypes.h"
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/bind_helpers.h" 12 #include "base/bind_helpers.h"
13 #include "base/i18n/rtl.h" 13 #include "base/i18n/rtl.h"
14 #include "base/i18n/time_formatting.h" 14 #include "base/i18n/time_formatting.h"
15 #include "base/memory/singleton.h" 15 #include "base/memory/singleton.h"
16 #include "base/metrics/field_trial.h" 16 #include "base/metrics/field_trial.h"
17 #include "base/metrics/histogram.h" 17 #include "base/metrics/histogram.h"
18 #include "base/prefs/pref_service.h" 18 #include "base/prefs/pref_service.h"
19 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/string_piece.h" 20 #include "base/strings/string_piece.h"
20 #include "base/strings/utf_string_conversions.h" 21 #include "base/strings/utf_string_conversions.h"
21 #include "base/threading/thread.h" 22 #include "base/threading/thread.h"
22 #include "base/value_conversions.h" 23 #include "base/value_conversions.h"
23 #include "base/values.h" 24 #include "base/values.h"
24 #include "chrome/browser/browser_process.h" 25 #include "chrome/browser/browser_process.h"
25 #include "chrome/browser/download/download_crx_util.h" 26 #include "chrome/browser/download/download_crx_util.h"
26 #include "chrome/browser/download/download_danger_prompt.h" 27 #include "chrome/browser/download/download_danger_prompt.h"
27 #include "chrome/browser/download/download_history.h" 28 #include "chrome/browser/download/download_history.h"
28 #include "chrome/browser/download/download_item_model.h" 29 #include "chrome/browser/download/download_item_model.h"
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
124 // any keys in file_value. 125 // any keys in file_value.
125 base::DictionaryValue* file_value = new base::DictionaryValue(); 126 base::DictionaryValue* file_value = new base::DictionaryValue();
126 127
127 file_value->SetInteger( 128 file_value->SetInteger(
128 "started", static_cast<int>(download_item->GetStartTime().ToTimeT())); 129 "started", static_cast<int>(download_item->GetStartTime().ToTimeT()));
129 file_value->SetString( 130 file_value->SetString(
130 "since_string", ui::TimeFormat::RelativeDate( 131 "since_string", ui::TimeFormat::RelativeDate(
131 download_item->GetStartTime(), NULL)); 132 download_item->GetStartTime(), NULL));
132 file_value->SetString( 133 file_value->SetString(
133 "date_string", base::TimeFormatShortDate(download_item->GetStartTime())); 134 "date_string", base::TimeFormatShortDate(download_item->GetStartTime()));
134 file_value->SetInteger("id", download_item->GetId()); 135 file_value->SetString("id", base::Uint64ToString(download_item->GetId()));
135 136
136 base::FilePath download_path(download_item->GetTargetFilePath()); 137 base::FilePath download_path(download_item->GetTargetFilePath());
137 file_value->Set("file_path", base::CreateFilePathValue(download_path)); 138 file_value->Set("file_path", base::CreateFilePathValue(download_path));
138 file_value->SetString("file_url", 139 file_value->SetString("file_url",
139 net::FilePathToFileURL(download_path).spec()); 140 net::FilePathToFileURL(download_path).spec());
140 141
141 extensions::DownloadedByExtension* by_ext = 142 extensions::DownloadedByExtension* by_ext =
142 extensions::DownloadedByExtension::Get(download_item); 143 extensions::DownloadedByExtension::Get(download_item);
143 if (by_ext) { 144 if (by_ext) {
144 file_value->SetString("by_ext_id", by_ext->id()); 145 file_value->SetString("by_ext_id", by_ext->id());
145 file_value->SetString("by_ext_name", by_ext->name()); 146 file_value->SetString("by_ext_name", by_ext->name());
146 // Lookup the extension's current name() in case the user changed their 147 // Lookup the extension's current name() in case the user changed their
147 // language. This won't work if the extension was uninstalled, so the name 148 // language. This won't work if the extension was uninstalled, so the name
148 // might be the wrong language. 149 // might be the wrong language.
149 bool include_disabled = true; 150 bool include_disabled = true;
150 const extensions::Extension* extension = extensions::ExtensionSystem::Get( 151 const extensions::Extension* extension = extensions::ExtensionSystem::Get(
151 Profile::FromBrowserContext(download_item->GetBrowserContext()))-> 152 Profile::FromBrowserContext(download_item->GetBrowserContext()))->
152 extension_service()->GetExtensionById(by_ext->id(), include_disabled); 153 extension_service()->GetExtensionById(by_ext->id(), include_disabled);
153 if (extension) 154 if (extension)
154 file_value->SetString("by_ext_name", extension->name()); 155 file_value->SetString("by_ext_name", extension->name());
155 } 156 }
156 157
157 // Keep file names as LTR. 158 // Keep file names as LTR.
158 base::string16 file_name = 159 base::string16 file_name =
159 download_item->GetFileNameToReportUser().LossyDisplayName(); 160 download_item->GetFileNameToReportUser().LossyDisplayName();
160 file_name = base::i18n::GetDisplayStringInLTRDirectionality(file_name); 161 file_name = base::i18n::GetDisplayStringInLTRDirectionality(file_name);
161 file_value->SetString("file_name", file_name); 162 file_value->SetString("file_name", file_name);
162 file_value->SetString("url", download_item->GetURL().spec()); 163 file_value->SetString("url", download_item->GetURL().spec());
163 file_value->SetBoolean("otr", incognito); 164 file_value->SetBoolean("otr", incognito);
164 file_value->SetInteger("total", static_cast<int>( 165 file_value->SetInteger("total", static_cast<int>(
165 download_item->GetTotalBytes())); 166 download_item->GetTotalBytes()));
166 file_value->SetBoolean("file_externally_removed", 167 file_value->SetBoolean("file_externally_removed",
167 download_item->GetFileExternallyRemoved()); 168 download_item->GetFileExternallyRemoved());
168 file_value->SetBoolean("retry", false); // Overridden below if needed. 169 file_value->SetBoolean("retry", false); // Overridden below if needed.
169 file_value->SetBoolean("resume", download_item->CanResume()); 170 file_value->SetBoolean("resume", download_item->CanResume());
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
223 file_value->SetString("state", "CANCELLED"); 224 file_value->SetString("state", "CANCELLED");
224 file_value->SetBoolean("retry", true); 225 file_value->SetBoolean("retry", true);
225 break; 226 break;
226 227
227 case content::DownloadItem::COMPLETE: 228 case content::DownloadItem::COMPLETE:
228 DCHECK(!download_item->IsDangerous()); 229 DCHECK(!download_item->IsDangerous());
229 file_value->SetString("state", "COMPLETE"); 230 file_value->SetString("state", "COMPLETE");
230 break; 231 break;
231 232
232 case content::DownloadItem::MAX_DOWNLOAD_STATE: 233 case content::DownloadItem::MAX_DOWNLOAD_STATE:
233 NOTREACHED() << "state undefined"; 234 NOTREACHED();
234 } 235 }
235 236
236 return file_value; 237 return file_value;
237 } 238 }
238 239
239 // Filters out extension downloads and downloads that don't have a filename yet. 240 // Filters out extension downloads and downloads that don't have a filename yet.
240 bool IsDownloadDisplayable(const content::DownloadItem& item) { 241 bool IsDownloadDisplayable(const content::DownloadItem& item) {
241 return (!download_crx_util::IsExtensionDownload(item) && 242 return (!download_crx_util::IsExtensionDownload(item) &&
242 !item.IsTemporary() && 243 !item.IsTemporary() &&
243 !item.GetFileNameToReportUser().empty() && 244 !item.GetFileNameToReportUser().empty() &&
244 !item.GetTargetFilePath().empty()); 245 !item.GetTargetFilePath().empty());
245 } 246 }
246 247
247 } // namespace 248 } // namespace
248 249
249 DownloadsDOMHandler::DownloadsDOMHandler(content::DownloadManager* dlm) 250 DownloadsDOMHandler::DownloadsDOMHandler(content::DownloadManager* dlm)
250 : main_notifier_(dlm, this), 251 : main_notifier_(dlm, this),
251 update_scheduled_(false), 252 update_scheduled_(false),
253 last_removed_id_(content::DownloadItem::kInvalidId),
252 weak_ptr_factory_(this) { 254 weak_ptr_factory_(this) {
253 // Create our fileicon data source. 255 // Create our fileicon data source.
254 Profile* profile = Profile::FromBrowserContext(dlm->GetBrowserContext()); 256 Profile* profile = Profile::FromBrowserContext(dlm->GetBrowserContext());
255 content::URLDataSource::Add(profile, new FileIconSource()); 257 content::URLDataSource::Add(profile, new FileIconSource());
256 258
257 if (profile->IsOffTheRecord()) { 259 if (profile->IsOffTheRecord()) {
258 original_notifier_.reset(new AllDownloadItemNotifier( 260 original_notifier_.reset(new AllDownloadItemNotifier(
259 BrowserContext::GetDownloadManager(profile->GetOriginalProfile()), 261 BrowserContext::GetDownloadManager(profile->GetOriginalProfile()),
260 this)); 262 this));
261 } 263 }
262 } 264 }
263 265
264 DownloadsDOMHandler::~DownloadsDOMHandler() { 266 DownloadsDOMHandler::~DownloadsDOMHandler() {
267 FinalizeRemoval();
265 } 268 }
266 269
267 // DownloadsDOMHandler, public: ----------------------------------------------- 270 // DownloadsDOMHandler, public: -----------------------------------------------
268 271
269 void DownloadsDOMHandler::OnPageLoaded(const base::ListValue* args) { 272 void DownloadsDOMHandler::OnPageLoaded(const base::ListValue* args) {
270 SendCurrentDownloads(); 273 SendCurrentDownloads();
271 } 274 }
272 275
273 void DownloadsDOMHandler::RegisterMessages() { 276 void DownloadsDOMHandler::RegisterMessages() {
274 web_ui()->RegisterMessageCallback("onPageLoaded", 277 web_ui()->RegisterMessageCallback("onPageLoaded",
(...skipping 28 matching lines...) Expand all
303 weak_ptr_factory_.GetWeakPtr())); 306 weak_ptr_factory_.GetWeakPtr()));
304 web_ui()->RegisterMessageCallback("cancel", 307 web_ui()->RegisterMessageCallback("cancel",
305 base::Bind(&DownloadsDOMHandler::HandleCancel, 308 base::Bind(&DownloadsDOMHandler::HandleCancel,
306 weak_ptr_factory_.GetWeakPtr())); 309 weak_ptr_factory_.GetWeakPtr()));
307 web_ui()->RegisterMessageCallback("clearAll", 310 web_ui()->RegisterMessageCallback("clearAll",
308 base::Bind(&DownloadsDOMHandler::HandleClearAll, 311 base::Bind(&DownloadsDOMHandler::HandleClearAll,
309 weak_ptr_factory_.GetWeakPtr())); 312 weak_ptr_factory_.GetWeakPtr()));
310 web_ui()->RegisterMessageCallback("openDownloadsFolder", 313 web_ui()->RegisterMessageCallback("openDownloadsFolder",
311 base::Bind(&DownloadsDOMHandler::HandleOpenDownloadsFolder, 314 base::Bind(&DownloadsDOMHandler::HandleOpenDownloadsFolder,
312 weak_ptr_factory_.GetWeakPtr())); 315 weak_ptr_factory_.GetWeakPtr()));
316 web_ui()->RegisterMessageCallback("undoRemove",
317 base::Bind(&DownloadsDOMHandler::HandleUndoRemove,
318 weak_ptr_factory_.GetWeakPtr()));
313 } 319 }
314 320
315 void DownloadsDOMHandler::OnDownloadCreated( 321 void DownloadsDOMHandler::OnDownloadCreated(
316 content::DownloadManager* manager, content::DownloadItem* download_item) { 322 content::DownloadManager* manager, content::DownloadItem* download_item) {
317 if (IsDownloadDisplayable(*download_item)) 323 if (IsDownloadDisplayable(*download_item))
318 ScheduleSendCurrentDownloads(); 324 ScheduleSendCurrentDownloads();
319 } 325 }
320 326
321 void DownloadsDOMHandler::OnDownloadUpdated( 327 void DownloadsDOMHandler::OnDownloadUpdated(
322 content::DownloadManager* manager, 328 content::DownloadManager* manager,
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after
431 if (file) 437 if (file)
432 file->Resume(); 438 file->Resume();
433 } 439 }
434 440
435 void DownloadsDOMHandler::HandleRemove(const base::ListValue* args) { 441 void DownloadsDOMHandler::HandleRemove(const base::ListValue* args) {
436 if (!IsDeletingHistoryAllowed()) 442 if (!IsDeletingHistoryAllowed())
437 return; 443 return;
438 444
439 CountDownloadsDOMEvents(DOWNLOADS_DOM_EVENT_REMOVE); 445 CountDownloadsDOMEvents(DOWNLOADS_DOM_EVENT_REMOVE);
440 content::DownloadItem* file = GetDownloadByValue(args); 446 content::DownloadItem* file = GetDownloadByValue(args);
441 if (file) 447 if (file) {
448 FinalizeRemoval();
449 last_removed_id_ = file->GetId();
442 file->Remove(); 450 file->Remove();
451 }
443 } 452 }
444 453
445 void DownloadsDOMHandler::HandleCancel(const base::ListValue* args) { 454 void DownloadsDOMHandler::HandleCancel(const base::ListValue* args) {
446 CountDownloadsDOMEvents(DOWNLOADS_DOM_EVENT_CANCEL); 455 CountDownloadsDOMEvents(DOWNLOADS_DOM_EVENT_CANCEL);
447 content::DownloadItem* file = GetDownloadByValue(args); 456 content::DownloadItem* file = GetDownloadByValue(args);
448 if (file) 457 if (file)
449 file->Cancel(true); 458 file->Cancel(true);
450 } 459 }
451 460
452 void DownloadsDOMHandler::HandleClearAll(const base::ListValue* args) { 461 void DownloadsDOMHandler::HandleClearAll(const base::ListValue* args) {
(...skipping 20 matching lines...) Expand all
473 const base::ListValue* args) { 482 const base::ListValue* args) {
474 CountDownloadsDOMEvents(DOWNLOADS_DOM_EVENT_OPEN_FOLDER); 483 CountDownloadsDOMEvents(DOWNLOADS_DOM_EVENT_OPEN_FOLDER);
475 content::DownloadManager* manager = main_notifier_.GetManager(); 484 content::DownloadManager* manager = main_notifier_.GetManager();
476 if (manager) { 485 if (manager) {
477 platform_util::OpenItem( 486 platform_util::OpenItem(
478 Profile::FromBrowserContext(manager->GetBrowserContext()), 487 Profile::FromBrowserContext(manager->GetBrowserContext()),
479 DownloadPrefs::FromDownloadManager(manager)->DownloadPath()); 488 DownloadPrefs::FromDownloadManager(manager)->DownloadPath());
480 } 489 }
481 } 490 }
482 491
492 void DownloadsDOMHandler::HandleUndoRemove(const base::ListValue* args) {
493 if (last_removed_id_ == content::DownloadItem::kInvalidId)
494 return;
495
496 if (main_notifier_.GetManager())
497 main_notifier_.GetManager()->ReviveDownload(last_removed_id_);
498 if (original_notifier_ && original_notifier_->GetManager())
499 original_notifier_->GetManager()->ReviveDownload(last_removed_id_);
500
501 last_removed_id_ = content::DownloadItem::kInvalidId;
502 }
503
483 // DownloadsDOMHandler, private: ---------------------------------------------- 504 // DownloadsDOMHandler, private: ----------------------------------------------
484 505
485 void DownloadsDOMHandler::ScheduleSendCurrentDownloads() { 506 void DownloadsDOMHandler::ScheduleSendCurrentDownloads() {
486 // Don't call SendCurrentDownloads() every time anything changes. Batch them 507 // Don't call SendCurrentDownloads() every time anything changes. Batch them
487 // together instead. This may handle hundreds of OnDownloadDestroyed() calls 508 // together instead. This may handle hundreds of OnDownloadDestroyed() calls
488 // in a single UI message loop iteration when the user Clears All downloads. 509 // in a single UI message loop iteration when the user Clears All downloads.
489 if (update_scheduled_) 510 if (update_scheduled_)
490 return; 511 return;
491 update_scheduled_ = true; 512 update_scheduled_ = true;
492 BrowserThread::PostTask( 513 BrowserThread::PostTask(
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
554 item->ValidateDangerousDownload(); 575 item->ValidateDangerousDownload();
555 } 576 }
556 577
557 bool DownloadsDOMHandler::IsDeletingHistoryAllowed() { 578 bool DownloadsDOMHandler::IsDeletingHistoryAllowed() {
558 content::DownloadManager* manager = main_notifier_.GetManager(); 579 content::DownloadManager* manager = main_notifier_.GetManager();
559 return (manager && 580 return (manager &&
560 Profile::FromBrowserContext(manager->GetBrowserContext())-> 581 Profile::FromBrowserContext(manager->GetBrowserContext())->
561 GetPrefs()->GetBoolean(prefs::kAllowDeletingBrowserHistory)); 582 GetPrefs()->GetBoolean(prefs::kAllowDeletingBrowserHistory));
562 } 583 }
563 584
585 void DownloadsDOMHandler::FinalizeRemoval() {
586 if (last_removed_id_ == content::DownloadItem::kInvalidId)
587 return;
588
589 if (main_notifier_.GetManager())
590 main_notifier_.GetManager()->FinalizeRemoval(last_removed_id_);
591 if (original_notifier_ && original_notifier_->GetManager())
592 original_notifier_->GetManager()->FinalizeRemoval(last_removed_id_);
593
594 last_removed_id_ = content::DownloadItem::kInvalidId;
595 }
596
564 content::DownloadItem* DownloadsDOMHandler::GetDownloadByValue( 597 content::DownloadItem* DownloadsDOMHandler::GetDownloadByValue(
565 const base::ListValue* args) { 598 const base::ListValue* args) {
566 int download_id = -1; 599 std::string download_id;
567 if (!ExtractIntegerValue(args, &download_id)) 600 if (!args->GetString(0, &download_id)) {
601 NOTREACHED();
568 return NULL; 602 return NULL;
603 }
604
605 uint64 id;
606 if (!base::StringToUint64(download_id, &id)) {
607 NOTREACHED();
608 return NULL;
609 }
610
569 content::DownloadItem* item = NULL; 611 content::DownloadItem* item = NULL;
570 if (main_notifier_.GetManager()) 612 if (main_notifier_.GetManager())
571 item = main_notifier_.GetManager()->GetDownload(download_id); 613 item = main_notifier_.GetManager()->GetDownload(id);
572 if (!item && original_notifier_.get() && original_notifier_->GetManager()) 614 if (!item && original_notifier_.get() && original_notifier_->GetManager())
573 item = original_notifier_->GetManager()->GetDownload(download_id); 615 item = original_notifier_->GetManager()->GetDownload(id);
574 return item; 616 return item;
575 } 617 }
576 618
577 content::WebContents* DownloadsDOMHandler::GetWebUIWebContents() { 619 content::WebContents* DownloadsDOMHandler::GetWebUIWebContents() {
578 return web_ui()->GetWebContents(); 620 return web_ui()->GetWebContents();
579 } 621 }
580 622
581 void DownloadsDOMHandler::CallDownloadsList(const base::ListValue& downloads) { 623 void DownloadsDOMHandler::CallDownloadsList(const base::ListValue& downloads) {
582 web_ui()->CallJavascriptFunction("downloadsList", downloads); 624 web_ui()->CallJavascriptFunction("downloadsList", downloads);
583 } 625 }
584 626
585 void DownloadsDOMHandler::CallDownloadUpdated( 627 void DownloadsDOMHandler::CallDownloadUpdated(
586 const base::ListValue& download_item) { 628 const base::ListValue& download_item) {
587 web_ui()->CallJavascriptFunction("downloadUpdated", download_item); 629 web_ui()->CallJavascriptFunction("downloadUpdated", download_item);
588 } 630 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698