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

Side by Side Diff: chrome/browser/extensions/api/downloads/downloads_api.cc

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

Powered by Google App Engine
This is Rietveld 408576698