OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |