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

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: @r176347 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 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698