| 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/extensions/api/downloads/downloads_api.h" | 5 #include "chrome/browser/extensions/api/downloads/downloads_api.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cctype> | 8 #include <cctype> |
| 9 #include <iterator> | 9 #include <iterator> |
| 10 #include <set> | 10 #include <set> |
| 11 #include <string> | 11 #include <string> |
| 12 | 12 |
| 13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
| 14 #include "base/bind.h" | 14 #include "base/bind.h" |
| 15 #include "base/bind_helpers.h" | 15 #include "base/bind_helpers.h" |
| 16 #include "base/callback.h" | 16 #include "base/callback.h" |
| 17 #include "base/file_path.h" |
| 17 #include "base/json/json_writer.h" | 18 #include "base/json/json_writer.h" |
| 18 #include "base/lazy_instance.h" | 19 #include "base/lazy_instance.h" |
| 19 #include "base/logging.h" | 20 #include "base/logging.h" |
| 20 #include "base/metrics/histogram.h" | 21 #include "base/metrics/histogram.h" |
| 21 #include "base/stl_util.h" | 22 #include "base/stl_util.h" |
| 22 #include "base/string16.h" | 23 #include "base/string16.h" |
| 23 #include "base/string_split.h" | 24 #include "base/string_split.h" |
| 24 #include "base/string_util.h" | 25 #include "base/string_util.h" |
| 25 #include "base/stringprintf.h" | 26 #include "base/stringprintf.h" |
| 26 #include "base/values.h" | 27 #include "base/values.h" |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 | 173 |
| 173 DownloadItem::DownloadState StateEnumFromString(const std::string& state) { | 174 DownloadItem::DownloadState StateEnumFromString(const std::string& state) { |
| 174 for (size_t i = 0; i < arraysize(kStateStrings); ++i) { | 175 for (size_t i = 0; i < arraysize(kStateStrings); ++i) { |
| 175 if ((kStateStrings[i] != NULL) && (state == kStateStrings[i])) | 176 if ((kStateStrings[i] != NULL) && (state == kStateStrings[i])) |
| 176 return static_cast<DownloadItem::DownloadState>(i); | 177 return static_cast<DownloadItem::DownloadState>(i); |
| 177 } | 178 } |
| 178 return DownloadItem::MAX_DOWNLOAD_STATE; | 179 return DownloadItem::MAX_DOWNLOAD_STATE; |
| 179 } | 180 } |
| 180 | 181 |
| 181 bool ValidateFilename(const string16& filename) { | 182 bool ValidateFilename(const string16& filename) { |
| 182 // TODO(benjhayden): More robust validation of filename. | 183 if (filename.empty() || |
| 183 if ((filename.find('/') != string16::npos) || | 184 (filename.find('/') != string16::npos) || |
| 184 (filename.find('\\') != string16::npos)) | 185 (filename.find('\\') != string16::npos)) |
| 185 return false; | 186 return false; |
| 186 if (filename.size() >= 2u && filename[0] == L'.' && filename[1] == L'.') | 187 if ((filename.size() >= 2u) && |
| 188 (filename[0] == L'.') && |
| 189 (filename[1] == L'.')) |
| 187 return false; | 190 return false; |
| 188 return true; | 191 return true; |
| 189 } | 192 } |
| 190 | 193 |
| 191 std::string TimeToISO8601(const base::Time& t) { | 194 std::string TimeToISO8601(const base::Time& t) { |
| 192 base::Time::Exploded exploded; | 195 base::Time::Exploded exploded; |
| 193 t.UTCExplode(&exploded); | 196 t.UTCExplode(&exploded); |
| 194 return base::StringPrintf( | 197 return base::StringPrintf( |
| 195 "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", exploded.year, exploded.month, | 198 "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", exploded.year, exploded.month, |
| 196 exploded.day_of_month, exploded.hour, exploded.minute, exploded.second, | 199 exploded.day_of_month, exploded.hour, exploded.minute, exploded.second, |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 }; | 252 }; |
| 250 | 253 |
| 251 bool DownloadFileIconExtractorImpl::ExtractIconURLForPath( | 254 bool DownloadFileIconExtractorImpl::ExtractIconURLForPath( |
| 252 const FilePath& path, | 255 const FilePath& path, |
| 253 IconLoader::IconSize icon_size, | 256 IconLoader::IconSize icon_size, |
| 254 IconURLCallback callback) { | 257 IconURLCallback callback) { |
| 255 callback_ = callback; | 258 callback_ = callback; |
| 256 IconManager* im = g_browser_process->icon_manager(); | 259 IconManager* im = g_browser_process->icon_manager(); |
| 257 // The contents of the file at |path| may have changed since a previous | 260 // The contents of the file at |path| may have changed since a previous |
| 258 // request, in which case the associated icon may also have changed. | 261 // request, in which case the associated icon may also have changed. |
| 259 // Therefore, for the moment we always call LoadIcon instead of attempting | 262 // Therefore, always call LoadIcon instead of attempting a LookupIcon. |
| 260 // a LookupIcon. | |
| 261 im->LoadIcon(path, | 263 im->LoadIcon(path, |
| 262 icon_size, | 264 icon_size, |
| 263 base::Bind(&DownloadFileIconExtractorImpl::OnIconLoadComplete, | 265 base::Bind(&DownloadFileIconExtractorImpl::OnIconLoadComplete, |
| 264 base::Unretained(this)), | 266 base::Unretained(this)), |
| 265 &cancelable_task_tracker_); | 267 &cancelable_task_tracker_); |
| 266 return true; | 268 return true; |
| 267 } | 269 } |
| 268 | 270 |
| 269 void DownloadFileIconExtractorImpl::OnIconLoadComplete(gfx::Image* icon) { | 271 void DownloadFileIconExtractorImpl::OnIconLoadComplete(gfx::Image* icon) { |
| 270 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 272 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 394 // TODO(benjhayden): Consider switching from LazyInstance to explicit string | 396 // TODO(benjhayden): Consider switching from LazyInstance to explicit string |
| 395 // comparisons. | 397 // comparisons. |
| 396 static base::LazyInstance<SortTypeMap> sorter_types = | 398 static base::LazyInstance<SortTypeMap> sorter_types = |
| 397 LAZY_INSTANCE_INITIALIZER; | 399 LAZY_INSTANCE_INITIALIZER; |
| 398 if (sorter_types.Get().size() == 0) | 400 if (sorter_types.Get().size() == 0) |
| 399 InitSortTypeMap(sorter_types.Get()); | 401 InitSortTypeMap(sorter_types.Get()); |
| 400 | 402 |
| 401 std::vector<std::string> order_by_strs; | 403 std::vector<std::string> order_by_strs; |
| 402 base::SplitString(order_by_str, ' ', &order_by_strs); | 404 base::SplitString(order_by_str, ' ', &order_by_strs); |
| 403 for (std::vector<std::string>::const_iterator iter = order_by_strs.begin(); | 405 for (std::vector<std::string>::const_iterator iter = order_by_strs.begin(); |
| 404 iter != order_by_strs.end(); ++iter) { | 406 iter != order_by_strs.end(); ++iter) { |
| 405 std::string term_str = *iter; | 407 std::string term_str = *iter; |
| 406 if (term_str.empty()) | 408 if (term_str.empty()) |
| 407 continue; | 409 continue; |
| 408 DownloadQuery::SortDirection direction = DownloadQuery::ASCENDING; | 410 DownloadQuery::SortDirection direction = DownloadQuery::ASCENDING; |
| 409 if (term_str[0] == '-') { | 411 if (term_str[0] == '-') { |
| 410 direction = DownloadQuery::DESCENDING; | 412 direction = DownloadQuery::DESCENDING; |
| 411 term_str = term_str.substr(1); | 413 term_str = term_str.substr(1); |
| 412 } | 414 } |
| 413 SortTypeMap::const_iterator sorter_type = | 415 SortTypeMap::const_iterator sorter_type = |
| 414 sorter_types.Get().find(term_str); | 416 sorter_types.Get().find(term_str); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 529 base::SupportsUserData::Data* data = download_item->GetUserData(kKey); | 531 base::SupportsUserData::Data* data = download_item->GetUserData(kKey); |
| 530 return (data == NULL) ? NULL : | 532 return (data == NULL) ? NULL : |
| 531 static_cast<ExtensionDownloadsEventRouterData*>(data); | 533 static_cast<ExtensionDownloadsEventRouterData*>(data); |
| 532 } | 534 } |
| 533 | 535 |
| 534 explicit ExtensionDownloadsEventRouterData( | 536 explicit ExtensionDownloadsEventRouterData( |
| 535 DownloadItem* download_item, | 537 DownloadItem* download_item, |
| 536 scoped_ptr<base::DictionaryValue> json_item) | 538 scoped_ptr<base::DictionaryValue> json_item) |
| 537 : updated_(0), | 539 : updated_(0), |
| 538 changed_fired_(0), | 540 changed_fired_(0), |
| 539 json_(json_item.Pass()) { | 541 json_(json_item.Pass()), |
| 542 determiner_index_(-1), |
| 543 determined_overwrite_(false) { |
| 540 download_item->SetUserData(kKey, this); | 544 download_item->SetUserData(kKey, this); |
| 541 } | 545 } |
| 542 | 546 |
| 543 virtual ~ExtensionDownloadsEventRouterData() { | 547 virtual ~ExtensionDownloadsEventRouterData() { |
| 544 if (updated_ > 0) { | 548 if (updated_ > 0) { |
| 545 UMA_HISTOGRAM_PERCENTAGE("Download.OnChanged", | 549 UMA_HISTOGRAM_PERCENTAGE("Download.OnChanged", |
| 546 (changed_fired_ * 100 / updated_)); | 550 (changed_fired_ * 100 / updated_)); |
| 547 } | 551 } |
| 548 } | 552 } |
| 549 | 553 |
| 550 const base::DictionaryValue& json() const { return *json_.get(); } | 554 const base::DictionaryValue& json() const { return *json_.get(); } |
| 551 void set_json(scoped_ptr<base::DictionaryValue> json_item) { | 555 void set_json(scoped_ptr<base::DictionaryValue> json_item) { |
| 552 json_ = json_item.Pass(); | 556 json_ = json_item.Pass(); |
| 553 } | 557 } |
| 554 | 558 |
| 555 void OnItemUpdated() { ++updated_; } | 559 void OnItemUpdated() { ++updated_; } |
| 556 void OnChangedFired() { ++changed_fired_; } | 560 void OnChangedFired() { ++changed_fired_; } |
| 557 | 561 |
| 562 void set_filename_change_callbacks( |
| 563 const base::Closure& no_change, |
| 564 const ExtensionDownloadsEventRouter::FilenameChangedCallback& change) { |
| 565 filename_no_change_ = no_change; |
| 566 filename_change_ = change; |
| 567 } |
| 568 |
| 569 void AddPendingDeterminer(const std::string& extension_id, |
| 570 const std::string& sub_event_id) { |
| 571 determiners_.push_back(DeterminerInfo(extension_id, sub_event_id)); |
| 572 } |
| 573 |
| 574 bool DeterminerCallback( |
| 575 const std::string& extension_id, |
| 576 const std::string& sub_event_id, |
| 577 const FilePath& filename, |
| 578 bool overwrite) { |
| 579 bool found_info = false; |
| 580 for (int index = 0; index < static_cast<int>(determiners_.size()); |
| 581 ++index) { |
| 582 if ((determiners_[index].extension_id == extension_id) && |
| 583 (determiners_[index].sub_event_id == sub_event_id)) { |
| 584 DCHECK(!determiners_[index].reported); |
| 585 determiners_[index].reported = true; |
| 586 found_info = true; |
| 587 if (!filename.empty() && |
| 588 !filename.IsAbsolute() && |
| 589 (index > determiner_index_)) { |
| 590 determined_filename_ = filename; |
| 591 determined_overwrite_ = overwrite; |
| 592 determiner_index_ = index; |
| 593 } |
| 594 } |
| 595 } |
| 596 if (!found_info) |
| 597 return false; |
| 598 for (size_t index = 0; index < determiners_.size(); ++index) { |
| 599 if (!determiners_[index].reported) |
| 600 return true; |
| 601 } |
| 602 determiners_.clear(); |
| 603 if (determined_filename_.empty()) { |
| 604 filename_no_change_.Run(); |
| 605 } else { |
| 606 filename_change_.Run(determined_filename_, determined_overwrite_); |
| 607 } |
| 608 return true; |
| 609 } |
| 610 |
| 558 private: | 611 private: |
| 612 struct DeterminerInfo { |
| 613 DeterminerInfo(const std::string& e_id, const std::string& sub_id); |
| 614 ~DeterminerInfo(); |
| 615 |
| 616 std::string extension_id; |
| 617 std::string sub_event_id; |
| 618 bool reported; |
| 619 }; |
| 620 typedef std::vector<DeterminerInfo> DeterminerInfoVector; |
| 621 |
| 559 static const char kKey[]; | 622 static const char kKey[]; |
| 560 | 623 |
| 561 int updated_; | 624 int updated_; |
| 562 int changed_fired_; | 625 int changed_fired_; |
| 563 scoped_ptr<base::DictionaryValue> json_; | 626 scoped_ptr<base::DictionaryValue> json_; |
| 627 base::Closure filename_no_change_; |
| 628 ExtensionDownloadsEventRouter::FilenameChangedCallback filename_change_; |
| 629 DeterminerInfoVector determiners_; |
| 630 int determiner_index_; |
| 631 FilePath determined_filename_; |
| 632 bool determined_overwrite_; |
| 564 | 633 |
| 565 DISALLOW_COPY_AND_ASSIGN(ExtensionDownloadsEventRouterData); | 634 DISALLOW_COPY_AND_ASSIGN(ExtensionDownloadsEventRouterData); |
| 566 }; | 635 }; |
| 567 | 636 |
| 637 ExtensionDownloadsEventRouterData::DeterminerInfo::DeterminerInfo( |
| 638 const std::string& e_id, const std::string& sub_id) |
| 639 : extension_id(e_id), sub_event_id(sub_id) { |
| 640 } |
| 641 |
| 642 ExtensionDownloadsEventRouterData::DeterminerInfo::~DeterminerInfo() {} |
| 643 |
| 568 const char ExtensionDownloadsEventRouterData::kKey[] = | 644 const char ExtensionDownloadsEventRouterData::kKey[] = |
| 569 "DownloadItem ExtensionDownloadsEventRouterData"; | 645 "DownloadItem ExtensionDownloadsEventRouterData"; |
| 570 | 646 |
| 571 } // namespace | 647 } // namespace |
| 572 | 648 |
| 573 DownloadsDownloadFunction::DownloadsDownloadFunction() {} | 649 DownloadsDownloadFunction::DownloadsDownloadFunction() {} |
| 650 |
| 574 DownloadsDownloadFunction::~DownloadsDownloadFunction() {} | 651 DownloadsDownloadFunction::~DownloadsDownloadFunction() {} |
| 575 | 652 |
| 576 bool DownloadsDownloadFunction::RunImpl() { | 653 bool DownloadsDownloadFunction::RunImpl() { |
| 577 scoped_ptr<extensions::api::downloads::Download::Params> params( | 654 scoped_ptr<extensions::api::downloads::Download::Params> params( |
| 578 extensions::api::downloads::Download::Params::Create(*args_)); | 655 extensions::api::downloads::Download::Params::Create(*args_)); |
| 579 EXTENSION_FUNCTION_VALIDATE(params.get()); | 656 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 580 const extensions::api::downloads::DownloadOptions& options = params->options; | 657 const extensions::api::downloads::DownloadOptions& options = params->options; |
| 581 GURL download_url(options.url); | 658 GURL download_url(options.url); |
| 582 if (!download_url.is_valid() || | 659 if (!download_url.is_valid() || |
| 583 (!download_url.SchemeIs("data") && | 660 (!download_url.SchemeIs("data") && |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 660 DCHECK_EQ(net::OK, error); | 737 DCHECK_EQ(net::OK, error); |
| 661 SetResult(base::Value::CreateIntegerValue(item->GetId())); | 738 SetResult(base::Value::CreateIntegerValue(item->GetId())); |
| 662 } else { | 739 } else { |
| 663 DCHECK_NE(net::OK, error); | 740 DCHECK_NE(net::OK, error); |
| 664 error_ = net::ErrorToString(error); | 741 error_ = net::ErrorToString(error); |
| 665 } | 742 } |
| 666 SendResponse(error_.empty()); | 743 SendResponse(error_.empty()); |
| 667 } | 744 } |
| 668 | 745 |
| 669 DownloadsSearchFunction::DownloadsSearchFunction() {} | 746 DownloadsSearchFunction::DownloadsSearchFunction() {} |
| 747 |
| 670 DownloadsSearchFunction::~DownloadsSearchFunction() {} | 748 DownloadsSearchFunction::~DownloadsSearchFunction() {} |
| 671 | 749 |
| 672 bool DownloadsSearchFunction::RunImpl() { | 750 bool DownloadsSearchFunction::RunImpl() { |
| 673 scoped_ptr<extensions::api::downloads::Search::Params> params( | 751 scoped_ptr<extensions::api::downloads::Search::Params> params( |
| 674 extensions::api::downloads::Search::Params::Create(*args_)); | 752 extensions::api::downloads::Search::Params::Create(*args_)); |
| 675 EXTENSION_FUNCTION_VALIDATE(params.get()); | 753 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 676 DownloadManager* manager = NULL; | 754 DownloadManager* manager = NULL; |
| 677 DownloadManager* incognito_manager = NULL; | 755 DownloadManager* incognito_manager = NULL; |
| 678 GetManagers(profile(), include_incognito(), &manager, &incognito_manager); | 756 GetManagers(profile(), include_incognito(), &manager, &incognito_manager); |
| 679 DownloadQuery::DownloadVector results; | 757 DownloadQuery::DownloadVector results; |
| (...skipping 15 matching lines...) Expand all Loading... |
| 695 scoped_ptr<base::DictionaryValue> json_item(DownloadItemToJSON( | 773 scoped_ptr<base::DictionaryValue> json_item(DownloadItemToJSON( |
| 696 *it, off_record)); | 774 *it, off_record)); |
| 697 json_results->Append(json_item.release()); | 775 json_results->Append(json_item.release()); |
| 698 } | 776 } |
| 699 SetResult(json_results); | 777 SetResult(json_results); |
| 700 RecordApiFunctions(DOWNLOADS_FUNCTION_SEARCH); | 778 RecordApiFunctions(DOWNLOADS_FUNCTION_SEARCH); |
| 701 return true; | 779 return true; |
| 702 } | 780 } |
| 703 | 781 |
| 704 DownloadsPauseFunction::DownloadsPauseFunction() {} | 782 DownloadsPauseFunction::DownloadsPauseFunction() {} |
| 783 |
| 705 DownloadsPauseFunction::~DownloadsPauseFunction() {} | 784 DownloadsPauseFunction::~DownloadsPauseFunction() {} |
| 706 | 785 |
| 707 bool DownloadsPauseFunction::RunImpl() { | 786 bool DownloadsPauseFunction::RunImpl() { |
| 708 scoped_ptr<extensions::api::downloads::Pause::Params> params( | 787 scoped_ptr<extensions::api::downloads::Pause::Params> params( |
| 709 extensions::api::downloads::Pause::Params::Create(*args_)); | 788 extensions::api::downloads::Pause::Params::Create(*args_)); |
| 710 EXTENSION_FUNCTION_VALIDATE(params.get()); | 789 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 711 DownloadItem* download_item = GetDownloadIfInProgress( | 790 DownloadItem* download_item = GetDownloadIfInProgress( |
| 712 profile(), include_incognito(), params->download_id); | 791 profile(), include_incognito(), params->download_id); |
| 713 if (download_item == NULL) { | 792 if (download_item == NULL) { |
| 714 // This could be due to an invalid download ID, or it could be due to the | 793 // This could be due to an invalid download ID, or it could be due to the |
| 715 // download not being currently active. | 794 // download not being currently active. |
| 716 error_ = download_extension_errors::kInvalidOperationError; | 795 error_ = download_extension_errors::kInvalidOperationError; |
| 717 } else { | 796 } else { |
| 718 // If the item is already paused, this is a no-op and the | 797 // If the item is already paused, this is a no-op and the |
| 719 // operation will silently succeed. | 798 // operation will silently succeed. |
| 720 download_item->Pause(); | 799 download_item->Pause(); |
| 721 } | 800 } |
| 722 if (error_.empty()) | 801 if (error_.empty()) |
| 723 RecordApiFunctions(DOWNLOADS_FUNCTION_PAUSE); | 802 RecordApiFunctions(DOWNLOADS_FUNCTION_PAUSE); |
| 724 return error_.empty(); | 803 return error_.empty(); |
| 725 } | 804 } |
| 726 | 805 |
| 727 DownloadsResumeFunction::DownloadsResumeFunction() {} | 806 DownloadsResumeFunction::DownloadsResumeFunction() {} |
| 807 |
| 728 DownloadsResumeFunction::~DownloadsResumeFunction() {} | 808 DownloadsResumeFunction::~DownloadsResumeFunction() {} |
| 729 | 809 |
| 730 bool DownloadsResumeFunction::RunImpl() { | 810 bool DownloadsResumeFunction::RunImpl() { |
| 731 scoped_ptr<extensions::api::downloads::Resume::Params> params( | 811 scoped_ptr<extensions::api::downloads::Resume::Params> params( |
| 732 extensions::api::downloads::Resume::Params::Create(*args_)); | 812 extensions::api::downloads::Resume::Params::Create(*args_)); |
| 733 EXTENSION_FUNCTION_VALIDATE(params.get()); | 813 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 734 DownloadItem* download_item = GetDownloadIfInProgress( | 814 DownloadItem* download_item = GetDownloadIfInProgress( |
| 735 profile(), include_incognito(), params->download_id); | 815 profile(), include_incognito(), params->download_id); |
| 736 if (download_item == NULL) { | 816 if (download_item == NULL) { |
| 737 // This could be due to an invalid download ID, or it could be due to the | 817 // This could be due to an invalid download ID, or it could be due to the |
| 738 // download not being currently active. | 818 // download not being currently active. |
| 739 error_ = download_extension_errors::kInvalidOperationError; | 819 error_ = download_extension_errors::kInvalidOperationError; |
| 740 } else { | 820 } else { |
| 741 // Note that if the item isn't paused, this will be a no-op, and | 821 // Note that if the item isn't paused, this will be a no-op, and |
| 742 // we will silently treat the extension call as a success. | 822 // the extension call will seem successful. |
| 743 download_item->Resume(); | 823 download_item->Resume(); |
| 744 } | 824 } |
| 745 if (error_.empty()) | 825 if (error_.empty()) |
| 746 RecordApiFunctions(DOWNLOADS_FUNCTION_RESUME); | 826 RecordApiFunctions(DOWNLOADS_FUNCTION_RESUME); |
| 747 return error_.empty(); | 827 return error_.empty(); |
| 748 } | 828 } |
| 749 | 829 |
| 750 DownloadsCancelFunction::DownloadsCancelFunction() {} | 830 DownloadsCancelFunction::DownloadsCancelFunction() {} |
| 831 |
| 751 DownloadsCancelFunction::~DownloadsCancelFunction() {} | 832 DownloadsCancelFunction::~DownloadsCancelFunction() {} |
| 752 | 833 |
| 753 bool DownloadsCancelFunction::RunImpl() { | 834 bool DownloadsCancelFunction::RunImpl() { |
| 754 scoped_ptr<extensions::api::downloads::Resume::Params> params( | 835 scoped_ptr<extensions::api::downloads::Resume::Params> params( |
| 755 extensions::api::downloads::Resume::Params::Create(*args_)); | 836 extensions::api::downloads::Resume::Params::Create(*args_)); |
| 756 EXTENSION_FUNCTION_VALIDATE(params.get()); | 837 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 757 DownloadItem* download_item = GetDownloadIfInProgress( | 838 DownloadItem* download_item = GetDownloadIfInProgress( |
| 758 profile(), include_incognito(), params->download_id); | 839 profile(), include_incognito(), params->download_id); |
| 759 if (download_item != NULL) | 840 if (download_item != NULL) |
| 760 download_item->Cancel(true); | 841 download_item->Cancel(true); |
| 761 // |download_item| can be NULL if the download ID was invalid or if the | 842 // |download_item| can be NULL if the download ID was invalid or if the |
| 762 // download is not currently active. Either way, we don't consider it a | 843 // download is not currently active. Either way, it's not a failure. |
| 763 // failure. | |
| 764 RecordApiFunctions(DOWNLOADS_FUNCTION_CANCEL); | 844 RecordApiFunctions(DOWNLOADS_FUNCTION_CANCEL); |
| 765 return true; | 845 return true; |
| 766 } | 846 } |
| 767 | 847 |
| 768 DownloadsEraseFunction::DownloadsEraseFunction() {} | 848 DownloadsEraseFunction::DownloadsEraseFunction() {} |
| 849 |
| 769 DownloadsEraseFunction::~DownloadsEraseFunction() {} | 850 DownloadsEraseFunction::~DownloadsEraseFunction() {} |
| 770 | 851 |
| 771 bool DownloadsEraseFunction::RunImpl() { | 852 bool DownloadsEraseFunction::RunImpl() { |
| 772 scoped_ptr<extensions::api::downloads::Erase::Params> params( | 853 scoped_ptr<extensions::api::downloads::Erase::Params> params( |
| 773 extensions::api::downloads::Erase::Params::Create(*args_)); | 854 extensions::api::downloads::Erase::Params::Create(*args_)); |
| 774 EXTENSION_FUNCTION_VALIDATE(params.get()); | 855 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 775 DownloadManager* manager = NULL; | 856 DownloadManager* manager = NULL; |
| 776 DownloadManager* incognito_manager = NULL; | 857 DownloadManager* incognito_manager = NULL; |
| 777 GetManagers(profile(), include_incognito(), &manager, &incognito_manager); | 858 GetManagers(profile(), include_incognito(), &manager, &incognito_manager); |
| 778 DownloadQuery::DownloadVector results; | 859 DownloadQuery::DownloadVector results; |
| 779 RunDownloadQuery(params->query, | 860 RunDownloadQuery(params->query, |
| 780 manager, | 861 manager, |
| 781 incognito_manager, | 862 incognito_manager, |
| 782 &error_, | 863 &error_, |
| 783 &results); | 864 &results); |
| 784 if (!error_.empty()) | 865 if (!error_.empty()) |
| 785 return false; | 866 return false; |
| 786 base::ListValue* json_results = new base::ListValue(); | 867 base::ListValue* json_results = new base::ListValue(); |
| 787 for (DownloadManager::DownloadVector::const_iterator it = results.begin(); | 868 for (DownloadManager::DownloadVector::const_iterator it = results.begin(); |
| 788 it != results.end(); ++it) { | 869 it != results.end(); ++it) { |
| 789 json_results->Append(base::Value::CreateIntegerValue((*it)->GetId())); | 870 json_results->Append(base::Value::CreateIntegerValue((*it)->GetId())); |
| 790 (*it)->Remove(); | 871 (*it)->Remove(); |
| 791 } | 872 } |
| 792 SetResult(json_results); | 873 SetResult(json_results); |
| 793 RecordApiFunctions(DOWNLOADS_FUNCTION_ERASE); | 874 RecordApiFunctions(DOWNLOADS_FUNCTION_ERASE); |
| 794 return true; | 875 return true; |
| 795 } | 876 } |
| 796 | 877 |
| 797 DownloadsSetDestinationFunction::DownloadsSetDestinationFunction() {} | 878 DownloadsAcceptDangerFunction::DownloadsAcceptDangerFunction() {} |
| 798 DownloadsSetDestinationFunction::~DownloadsSetDestinationFunction() {} | |
| 799 | 879 |
| 800 bool DownloadsSetDestinationFunction::RunImpl() { | |
| 801 scoped_ptr<extensions::api::downloads::SetDestination::Params> params( | |
| 802 extensions::api::downloads::SetDestination::Params::Create(*args_)); | |
| 803 EXTENSION_FUNCTION_VALIDATE(params.get()); | |
| 804 error_ = download_extension_errors::kNotImplementedError; | |
| 805 if (error_.empty()) | |
| 806 RecordApiFunctions(DOWNLOADS_FUNCTION_SET_DESTINATION); | |
| 807 return error_.empty(); | |
| 808 } | |
| 809 | |
| 810 DownloadsAcceptDangerFunction::DownloadsAcceptDangerFunction() {} | |
| 811 DownloadsAcceptDangerFunction::~DownloadsAcceptDangerFunction() {} | 880 DownloadsAcceptDangerFunction::~DownloadsAcceptDangerFunction() {} |
| 812 | 881 |
| 813 bool DownloadsAcceptDangerFunction::RunImpl() { | 882 bool DownloadsAcceptDangerFunction::RunImpl() { |
| 814 scoped_ptr<extensions::api::downloads::AcceptDanger::Params> params( | 883 scoped_ptr<extensions::api::downloads::AcceptDanger::Params> params( |
| 815 extensions::api::downloads::AcceptDanger::Params::Create(*args_)); | 884 extensions::api::downloads::AcceptDanger::Params::Create(*args_)); |
| 816 EXTENSION_FUNCTION_VALIDATE(params.get()); | 885 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 817 error_ = download_extension_errors::kNotImplementedError; | 886 error_ = download_extension_errors::kNotImplementedError; |
| 818 if (error_.empty()) | 887 if (error_.empty()) |
| 819 RecordApiFunctions(DOWNLOADS_FUNCTION_ACCEPT_DANGER); | 888 RecordApiFunctions(DOWNLOADS_FUNCTION_ACCEPT_DANGER); |
| 820 return error_.empty(); | 889 return error_.empty(); |
| 821 } | 890 } |
| 822 | 891 |
| 823 DownloadsShowFunction::DownloadsShowFunction() {} | 892 DownloadsShowFunction::DownloadsShowFunction() {} |
| 893 |
| 824 DownloadsShowFunction::~DownloadsShowFunction() {} | 894 DownloadsShowFunction::~DownloadsShowFunction() {} |
| 825 | 895 |
| 826 bool DownloadsShowFunction::RunImpl() { | 896 bool DownloadsShowFunction::RunImpl() { |
| 827 scoped_ptr<extensions::api::downloads::Show::Params> params( | 897 scoped_ptr<extensions::api::downloads::Show::Params> params( |
| 828 extensions::api::downloads::Show::Params::Create(*args_)); | 898 extensions::api::downloads::Show::Params::Create(*args_)); |
| 829 EXTENSION_FUNCTION_VALIDATE(params.get()); | 899 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 830 DownloadItem* download_item = GetDownload( | 900 DownloadItem* download_item = GetDownload( |
| 831 profile(), include_incognito(), params->download_id); | 901 profile(), include_incognito(), params->download_id); |
| 832 if (!download_item) { | 902 if (!download_item) { |
| 833 error_ = download_extension_errors::kInvalidOperationError; | 903 error_ = download_extension_errors::kInvalidOperationError; |
| 834 return false; | 904 return false; |
| 835 } | 905 } |
| 836 download_item->ShowDownloadInShell(); | 906 download_item->ShowDownloadInShell(); |
| 837 RecordApiFunctions(DOWNLOADS_FUNCTION_SHOW); | 907 RecordApiFunctions(DOWNLOADS_FUNCTION_SHOW); |
| 838 return true; | 908 return true; |
| 839 } | 909 } |
| 840 | 910 |
| 841 DownloadsOpenFunction::DownloadsOpenFunction() {} | 911 DownloadsOpenFunction::DownloadsOpenFunction() {} |
| 912 |
| 842 DownloadsOpenFunction::~DownloadsOpenFunction() {} | 913 DownloadsOpenFunction::~DownloadsOpenFunction() {} |
| 843 | 914 |
| 844 bool DownloadsOpenFunction::RunImpl() { | 915 bool DownloadsOpenFunction::RunImpl() { |
| 845 scoped_ptr<extensions::api::downloads::Open::Params> params( | 916 scoped_ptr<extensions::api::downloads::Open::Params> params( |
| 846 extensions::api::downloads::Open::Params::Create(*args_)); | 917 extensions::api::downloads::Open::Params::Create(*args_)); |
| 847 EXTENSION_FUNCTION_VALIDATE(params.get()); | 918 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 848 DownloadItem* download_item = GetDownload( | 919 DownloadItem* download_item = GetDownload( |
| 849 profile(), include_incognito(), params->download_id); | 920 profile(), include_incognito(), params->download_id); |
| 850 if (!download_item || !download_item->IsComplete()) { | 921 if (!download_item || !download_item->IsComplete()) { |
| 851 error_ = download_extension_errors::kInvalidOperationError; | 922 error_ = download_extension_errors::kInvalidOperationError; |
| 852 return false; | 923 return false; |
| 853 } | 924 } |
| 854 download_item->OpenDownload(); | 925 download_item->OpenDownload(); |
| 855 RecordApiFunctions(DOWNLOADS_FUNCTION_OPEN); | 926 RecordApiFunctions(DOWNLOADS_FUNCTION_OPEN); |
| 856 return true; | 927 return true; |
| 857 } | 928 } |
| 858 | 929 |
| 859 DownloadsDragFunction::DownloadsDragFunction() {} | 930 DownloadsDragFunction::DownloadsDragFunction() {} |
| 931 |
| 860 DownloadsDragFunction::~DownloadsDragFunction() {} | 932 DownloadsDragFunction::~DownloadsDragFunction() {} |
| 861 | 933 |
| 862 bool DownloadsDragFunction::RunImpl() { | 934 bool DownloadsDragFunction::RunImpl() { |
| 863 scoped_ptr<extensions::api::downloads::Drag::Params> params( | 935 scoped_ptr<extensions::api::downloads::Drag::Params> params( |
| 864 extensions::api::downloads::Drag::Params::Create(*args_)); | 936 extensions::api::downloads::Drag::Params::Create(*args_)); |
| 865 EXTENSION_FUNCTION_VALIDATE(params.get()); | 937 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 866 DownloadItem* download_item = GetDownload( | 938 DownloadItem* download_item = GetDownload( |
| 867 profile(), include_incognito(), params->download_id); | 939 profile(), include_incognito(), params->download_id); |
| 868 content::WebContents* web_contents = | 940 content::WebContents* web_contents = |
| 869 dispatcher()->delegate()->GetAssociatedWebContents(); | 941 dispatcher()->delegate()->GetAssociatedWebContents(); |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 904 int icon_size = kDefaultIconSize; | 976 int icon_size = kDefaultIconSize; |
| 905 if (options && options->size.get()) | 977 if (options && options->size.get()) |
| 906 icon_size = *options->size.get(); | 978 icon_size = *options->size.get(); |
| 907 DownloadItem* download_item = GetDownload( | 979 DownloadItem* download_item = GetDownload( |
| 908 profile(), include_incognito(), params->download_id); | 980 profile(), include_incognito(), params->download_id); |
| 909 if (!download_item || download_item->GetTargetFilePath().empty()) { | 981 if (!download_item || download_item->GetTargetFilePath().empty()) { |
| 910 error_ = download_extension_errors::kInvalidOperationError; | 982 error_ = download_extension_errors::kInvalidOperationError; |
| 911 return false; | 983 return false; |
| 912 } | 984 } |
| 913 // In-progress downloads return the intermediate filename for GetFullPath() | 985 // In-progress downloads return the intermediate filename for GetFullPath() |
| 914 // which doesn't have the final extension. Therefore we won't be able to | 986 // which doesn't have the final extension. Therefore a good file icon can't be |
| 915 // derive a good file icon for it. So we use GetTargetFilePath() instead. | 987 // found, so use GetTargetFilePath() instead. |
| 916 DCHECK(icon_extractor_.get()); | 988 DCHECK(icon_extractor_.get()); |
| 917 DCHECK(icon_size == 16 || icon_size == 32); | 989 DCHECK(icon_size == 16 || icon_size == 32); |
| 918 EXTENSION_FUNCTION_VALIDATE(icon_extractor_->ExtractIconURLForPath( | 990 EXTENSION_FUNCTION_VALIDATE(icon_extractor_->ExtractIconURLForPath( |
| 919 download_item->GetTargetFilePath(), | 991 download_item->GetTargetFilePath(), |
| 920 IconLoaderSizeFromPixelSize(icon_size), | 992 IconLoaderSizeFromPixelSize(icon_size), |
| 921 base::Bind(&DownloadsGetFileIconFunction::OnIconURLExtracted, this))); | 993 base::Bind(&DownloadsGetFileIconFunction::OnIconURLExtracted, this))); |
| 922 return true; | 994 return true; |
| 923 } | 995 } |
| 924 | 996 |
| 925 void DownloadsGetFileIconFunction::OnIconURLExtracted(const std::string& url) { | 997 void DownloadsGetFileIconFunction::OnIconURLExtracted(const std::string& url) { |
| 926 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 998 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 927 if (url.empty()) { | 999 if (url.empty()) { |
| 928 error_ = download_extension_errors::kIconNotFoundError; | 1000 error_ = download_extension_errors::kIconNotFoundError; |
| 929 } else { | 1001 } else { |
| 930 RecordApiFunctions(DOWNLOADS_FUNCTION_GET_FILE_ICON); | 1002 RecordApiFunctions(DOWNLOADS_FUNCTION_GET_FILE_ICON); |
| 931 SetResult(base::Value::CreateStringValue(url)); | 1003 SetResult(base::Value::CreateStringValue(url)); |
| 932 } | 1004 } |
| 933 SendResponse(error_.empty()); | 1005 SendResponse(error_.empty()); |
| 934 } | 1006 } |
| 935 | 1007 |
| 1008 // The method by which extensions hook into the filename determination process |
| 1009 // is based on the method by which the webRequest API allows extensions to hook |
| 1010 // into the resource loading process. Extensions that wish to play a part in |
| 1011 // the filename determination process call |
| 1012 // chrome.downloads.onDeterminingFilename.addListener, which secretly (see |
| 1013 // chrome/renderer/resources/extensions/downloads_custom_bindings.js) calls |
| 1014 // DownloadsInternalAddFilenameDeterminerFunction (see ../downloads_internal/), |
| 1015 // which adds the extension's ID to the profile's ExtensionDownloadsEventRouter |
| 1016 // (EDER). When a download's filename is being determined, |
| 1017 // ChromeDownloadManagerDelegate::CheckVisitedReferrerBeforeDone (CVRBD) passes |
| 1018 // 2 callbacks to EDER::OnDownloadFilenameDetermined (ODFD), which stores the |
| 1019 // callbacks in the item's ExtensionDownloadsEventRouterData (EDERD) along with |
| 1020 // all of the extension IDs that are listening for onDeterminingFilename events. |
| 1021 // ODFD dispatches chrome.downloads.onDeterminingFilename. When the extension's |
| 1022 // event handler returns, downloads_custom_bindings.js calls |
| 1023 // DownloadsInternalDetermineFilenameFunction::RunImpl, which notifies the |
| 1024 // item's EDERD. When the last extension's event handler returns, EDERD calls |
| 1025 // one of the two callbacks that CVRBD passed to ODFD, allowing CDMD to complete |
| 1026 // the filename determination process. If multiple extensions wish to override |
| 1027 // the filename, then the last one wins. However, there's no deterministic way |
| 1028 // to determine which extension will finish last, so users are advised (in the |
| 1029 // developer documentation in downloads.idl) to try to use extensions that won't |
| 1030 // conflict. |
| 1031 |
| 1032 bool ExtensionDownloadsEventRouter::AddFilenameDeterminer( |
| 1033 Profile* profile, |
| 1034 bool include_incognito, |
| 1035 const std::string& ext_id, |
| 1036 const std::string& sub_event_id) { |
| 1037 if (include_incognito && profile->HasOffTheRecordProfile()) { |
| 1038 AddFilenameDeterminer(profile->GetOffTheRecordProfile(), |
| 1039 false, |
| 1040 ext_id, |
| 1041 sub_event_id); |
| 1042 } |
| 1043 ExtensionDownloadsEventRouter* router = |
| 1044 DownloadServiceFactory::GetForProfile(profile)->GetExtensionEventRouter(); |
| 1045 for (DeterminerVector::const_iterator iter = router->determiners_.begin(); |
| 1046 iter != router->determiners_.end(); ++iter) { |
| 1047 if (iter->first == ext_id && iter->second == sub_event_id) |
| 1048 return false; |
| 1049 } |
| 1050 router->determiners_.push_back(make_pair(ext_id, sub_event_id)); |
| 1051 return true; |
| 1052 } |
| 1053 |
| 1054 bool ExtensionDownloadsEventRouter::RemoveFilenameDeterminer( |
| 1055 Profile* profile, |
| 1056 bool include_incognito, |
| 1057 const std::string& ext_id, |
| 1058 const std::string& sub_event_id) { |
| 1059 if (include_incognito && profile->HasOffTheRecordProfile()) { |
| 1060 RemoveFilenameDeterminer(profile->GetOffTheRecordProfile(), |
| 1061 false, |
| 1062 ext_id, |
| 1063 sub_event_id); |
| 1064 } |
| 1065 ExtensionDownloadsEventRouter* router = |
| 1066 DownloadServiceFactory::GetForProfile(profile)->GetExtensionEventRouter(); |
| 1067 for (DeterminerVector::iterator iter = router->determiners_.begin(); |
| 1068 iter != router->determiners_.end(); ++iter) { |
| 1069 if (iter->first == ext_id && iter->second == sub_event_id) { |
| 1070 router->determiners_.erase(iter); |
| 1071 return true; |
| 1072 } |
| 1073 } |
| 1074 return false; |
| 1075 } |
| 1076 |
| 1077 bool ExtensionDownloadsEventRouter::DetermineFilename( |
| 1078 Profile* profile, |
| 1079 bool include_incognito, |
| 1080 const std::string& ext_id, |
| 1081 const std::string& sub_event_id, |
| 1082 int download_id, |
| 1083 const FilePath& filename, |
| 1084 bool overwrite) { |
| 1085 DownloadItem* item = GetDownloadIfInProgress( |
| 1086 profile, include_incognito, download_id); |
| 1087 if (!item) |
| 1088 return false; |
| 1089 ExtensionDownloadsEventRouterData* data = |
| 1090 ExtensionDownloadsEventRouterData::Get(item); |
| 1091 if (!data) |
| 1092 return false; |
| 1093 return data->DeterminerCallback(ext_id, sub_event_id, filename, overwrite); |
| 1094 } |
| 1095 |
| 936 ExtensionDownloadsEventRouter::ExtensionDownloadsEventRouter( | 1096 ExtensionDownloadsEventRouter::ExtensionDownloadsEventRouter( |
| 937 Profile* profile, | 1097 Profile* profile, |
| 938 DownloadManager* manager) | 1098 DownloadManager* manager) |
| 939 : profile_(profile), | 1099 : profile_(profile), |
| 940 ALLOW_THIS_IN_INITIALIZER_LIST(notifier_(manager, this)) { | 1100 ALLOW_THIS_IN_INITIALIZER_LIST(notifier_(manager, this)) { |
| 941 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1101 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 942 DCHECK(profile_); | 1102 DCHECK(profile_); |
| 1103 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, |
| 1104 content::Source<Profile>(profile_)); |
| 1105 } |
| 1106 |
| 1107 void ExtensionDownloadsEventRouter::Observe( |
| 1108 int type, |
| 1109 const content::NotificationSource& source, |
| 1110 const content::NotificationDetails& details) { |
| 1111 switch (type) { |
| 1112 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { |
| 1113 const extensions::Extension* extension = content::Details< |
| 1114 extensions::UnloadedExtensionInfo>(details)->extension; |
| 1115 for (DeterminerVector::iterator iter = determiners_.begin(); |
| 1116 iter != determiners_.end(); ++iter) { |
| 1117 if (iter->first == extension->id()) |
| 1118 iter = determiners_.erase(iter); |
| 1119 } |
| 1120 break; |
| 1121 } |
| 1122 default: |
| 1123 NOTREACHED(); |
| 1124 break; |
| 1125 } |
| 943 } | 1126 } |
| 944 | 1127 |
| 945 ExtensionDownloadsEventRouter::~ExtensionDownloadsEventRouter() { | 1128 ExtensionDownloadsEventRouter::~ExtensionDownloadsEventRouter() { |
| 946 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 947 } | 1130 } |
| 948 | 1131 |
| 949 void ExtensionDownloadsEventRouter::OnDownloadCreated( | 1132 void ExtensionDownloadsEventRouter::OnDownloadCreated( |
| 950 DownloadManager* manager, DownloadItem* download_item) { | 1133 DownloadManager* manager, DownloadItem* download_item) { |
| 951 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1134 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 952 if (download_item->IsTemporary()) | 1135 if (download_item->IsTemporary()) |
| 953 return; | 1136 return; |
| 954 | 1137 |
| 955 scoped_ptr<base::DictionaryValue> json_item( | 1138 scoped_ptr<base::DictionaryValue> json_item( |
| 956 DownloadItemToJSON(download_item, profile_->IsOffTheRecord())); | 1139 DownloadItemToJSON(download_item, profile_->IsOffTheRecord())); |
| 957 DispatchEvent(extensions::event_names::kOnDownloadCreated, | 1140 DispatchEvent(extensions::event_names::kOnDownloadCreated, |
| 958 json_item->DeepCopy()); | 1141 json_item->DeepCopy()); |
| 959 if (!ExtensionDownloadsEventRouterData::Get(download_item)) | 1142 if (!ExtensionDownloadsEventRouterData::Get(download_item)) |
| 960 new ExtensionDownloadsEventRouterData(download_item, json_item.Pass()); | 1143 new ExtensionDownloadsEventRouterData(download_item, json_item.Pass()); |
| 961 } | 1144 } |
| 962 | 1145 |
| 1146 void ExtensionDownloadsEventRouter::OnDownloadFilenameDetermined( |
| 1147 DownloadItem* item, |
| 1148 const FilePath& suggested_path, |
| 1149 const base::Closure& no_change, |
| 1150 const FilenameChangedCallback& change) { |
| 1151 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1152 if (determiners_.empty()) { |
| 1153 no_change.Run(); |
| 1154 return; |
| 1155 } |
| 1156 |
| 1157 ExtensionDownloadsEventRouterData* data = |
| 1158 ExtensionDownloadsEventRouterData::Get(item); |
| 1159 data->set_filename_change_callbacks(no_change, change); |
| 1160 std::set<std::string> sub_events; |
| 1161 for (DeterminerVector::const_iterator iter = determiners_.begin(); |
| 1162 iter != determiners_.end(); ++iter) { |
| 1163 data->AddPendingDeterminer(iter->first, iter->second); |
| 1164 sub_events.insert(iter->second); |
| 1165 } |
| 1166 std::string event_name( |
| 1167 extensions::event_names::kOnDownloadDeterminingFilename); |
| 1168 event_name += "/"; |
| 1169 for (std::set<std::string>::const_iterator iter = sub_events.begin(); |
| 1170 iter != sub_events.end(); ++iter) { |
| 1171 base::DictionaryValue* json = DownloadItemToJSON( |
| 1172 item, profile_->IsOffTheRecord()).release(); |
| 1173 json->SetString(kFilenameKey, suggested_path.LossyDisplayName()); |
| 1174 DispatchEvent((event_name + (*iter)).c_str(), json); |
| 1175 } |
| 1176 } |
| 1177 |
| 963 void ExtensionDownloadsEventRouter::OnDownloadUpdated( | 1178 void ExtensionDownloadsEventRouter::OnDownloadUpdated( |
| 964 DownloadManager* manager, DownloadItem* download_item) { | 1179 DownloadManager* manager, DownloadItem* download_item) { |
| 965 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1180 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 966 if (download_item->IsTemporary()) | 1181 if (download_item->IsTemporary()) |
| 967 return; | 1182 return; |
| 968 | 1183 |
| 969 ExtensionDownloadsEventRouterData* data = | 1184 ExtensionDownloadsEventRouterData* data = |
| 970 ExtensionDownloadsEventRouterData::Get(download_item); | 1185 ExtensionDownloadsEventRouterData::Get(download_item); |
| 971 if (!data) { | 1186 if (!data) { |
| 972 // The download_item probably transitioned from temporary to not temporary. | 1187 // The download_item probably transitioned from temporary to not temporary. |
| 973 OnDownloadCreated(manager, download_item); | 1188 OnDownloadCreated(manager, download_item); |
| 974 return; | 1189 return; |
| 975 } | 1190 } |
| 976 scoped_ptr<base::DictionaryValue> new_json(DownloadItemToJSON( | 1191 scoped_ptr<base::DictionaryValue> new_json(DownloadItemToJSON( |
| 977 download_item, profile_->IsOffTheRecord())); | 1192 download_item, profile_->IsOffTheRecord())); |
| 978 scoped_ptr<base::DictionaryValue> delta(new base::DictionaryValue()); | 1193 scoped_ptr<base::DictionaryValue> delta(new base::DictionaryValue()); |
| 979 delta->SetInteger(kIdKey, download_item->GetId()); | 1194 delta->SetInteger(kIdKey, download_item->GetId()); |
| 980 std::set<std::string> new_fields; | 1195 std::set<std::string> new_fields; |
| 981 bool changed = false; | 1196 bool changed = false; |
| 982 | 1197 |
| 983 // For each field in the new json representation of the download_item except | 1198 // For each field in the new json representation of the download_item except |
| 984 // the bytesReceived field, if the field has changed from the previous old | 1199 // the bytesReceived field, if the field has changed from the previous old |
| 985 // json, set the differences in the |delta| object and remember that something | 1200 // json, set the differences in the |delta| object and remember that something |
| 986 // significant changed. | 1201 // significant changed. |
| 987 for (base::DictionaryValue::Iterator iter(*new_json.get()); | 1202 for (base::DictionaryValue::Iterator iter(*new_json.get()); |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1032 void ExtensionDownloadsEventRouter::DispatchEvent( | 1247 void ExtensionDownloadsEventRouter::DispatchEvent( |
| 1033 const char* event_name, base::Value* arg) { | 1248 const char* event_name, base::Value* arg) { |
| 1034 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1249 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1035 scoped_ptr<base::ListValue> args(new base::ListValue()); | 1250 scoped_ptr<base::ListValue> args(new base::ListValue()); |
| 1036 args->Append(arg); | 1251 args->Append(arg); |
| 1037 std::string json_args; | 1252 std::string json_args; |
| 1038 base::JSONWriter::Write(args.get(), &json_args); | 1253 base::JSONWriter::Write(args.get(), &json_args); |
| 1039 // There is a one EDER for each on-record Profile, and a separate EDER for | 1254 // There is a one EDER for each on-record Profile, and a separate EDER for |
| 1040 // each off-record Profile, so there is exactly one EDER for each | 1255 // each off-record Profile, so there is exactly one EDER for each |
| 1041 // DownloadManager. EDER only watches its own DM, so all the items that an | 1256 // DownloadManager. EDER only watches its own DM, so all the items that an |
| 1042 // EDER sees are either all on-record or all off-record. However, we want | 1257 // EDER sees are either all on-record or all off-record. However, extensions |
| 1043 // extensions in off-record contexts to see on-record items. So, if this EDER | 1258 // in off-record contexts should see on-record items. So, if this EDER is |
| 1044 // is watching an on-record DM, and there is a corresponding off-record | 1259 // watching an on-record DM, and there is a corresponding off-record Profile, |
| 1045 // Profile, then dispatch this event to both the on-record Profile and the | 1260 // then dispatch this event to both the on-record Profile and the off-record |
| 1046 // off-record Profile. There may or may not be an off-record Profile, so send | 1261 // Profile. There may or may not be an off-record Profile, so send a *copy* |
| 1047 // a *copy* of |args| to the off-record Profile, and Pass() |args| | 1262 // of |args| to the off-record Profile, and Pass() |args| to the Profile that |
| 1048 // to the Profile that we know is there. | 1263 // is certainly there. |
| 1049 if (profile_->HasOffTheRecordProfile() && | 1264 if (profile_->HasOffTheRecordProfile() && |
| 1050 !profile_->IsOffTheRecord()) { | 1265 !profile_->IsOffTheRecord()) { |
| 1051 DispatchEventInternal( | 1266 DispatchEventInternal( |
| 1052 profile_->GetOffTheRecordProfile(), | 1267 profile_->GetOffTheRecordProfile(), |
| 1053 event_name, | 1268 event_name, |
| 1054 json_args, | 1269 json_args, |
| 1055 scoped_ptr<base::ListValue>(args->DeepCopy())); | 1270 scoped_ptr<base::ListValue>(args->DeepCopy())); |
| 1056 } | 1271 } |
| 1057 DispatchEventInternal(profile_, event_name, json_args, args.Pass()); | 1272 DispatchEventInternal(profile_, event_name, json_args, args.Pass()); |
| 1058 } | 1273 } |
| OLD | NEW |