OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/api/downloads/downloads_api.h" | 5 #include "chrome/browser/extensions/api/downloads/downloads_api.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cctype> | 8 #include <cctype> |
9 #include <iterator> | 9 #include <iterator> |
10 #include <set> | 10 #include <set> |
11 #include <string> | 11 #include <string> |
12 | 12 |
13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
14 #include "base/bind.h" | 14 #include "base/bind.h" |
15 #include "base/bind_helpers.h" | 15 #include "base/bind_helpers.h" |
16 #include "base/callback.h" | 16 #include "base/callback.h" |
| 17 #include "base/file_path.h" |
17 #include "base/json/json_writer.h" | 18 #include "base/json/json_writer.h" |
18 #include "base/lazy_instance.h" | 19 #include "base/lazy_instance.h" |
19 #include "base/logging.h" | 20 #include "base/logging.h" |
20 #include "base/metrics/histogram.h" | 21 #include "base/metrics/histogram.h" |
21 #include "base/stl_util.h" | 22 #include "base/stl_util.h" |
22 #include "base/string16.h" | 23 #include "base/string16.h" |
23 #include "base/string_split.h" | 24 #include "base/string_split.h" |
24 #include "base/string_util.h" | 25 #include "base/string_util.h" |
25 #include "base/stringprintf.h" | 26 #include "base/stringprintf.h" |
| 27 #include "base/strings/string_number_conversions.h" |
26 #include "base/values.h" | 28 #include "base/values.h" |
27 #include "chrome/browser/browser_process.h" | 29 #include "chrome/browser/browser_process.h" |
28 #include "chrome/browser/download/download_danger_prompt.h" | 30 #include "chrome/browser/download/download_danger_prompt.h" |
29 #include "chrome/browser/download/download_file_icon_extractor.h" | 31 #include "chrome/browser/download/download_file_icon_extractor.h" |
30 #include "chrome/browser/download/download_query.h" | 32 #include "chrome/browser/download/download_query.h" |
31 #include "chrome/browser/download/download_service.h" | 33 #include "chrome/browser/download/download_service.h" |
32 #include "chrome/browser/download/download_service_factory.h" | 34 #include "chrome/browser/download/download_service_factory.h" |
33 #include "chrome/browser/download/download_util.h" | 35 #include "chrome/browser/download/download_util.h" |
34 #include "chrome/browser/extensions/event_names.h" | 36 #include "chrome/browser/extensions/event_names.h" |
35 #include "chrome/browser/extensions/event_router.h" | 37 #include "chrome/browser/extensions/event_router.h" |
36 #include "chrome/browser/extensions/extension_function_dispatcher.h" | 38 #include "chrome/browser/extensions/extension_function_dispatcher.h" |
| 39 #include "chrome/browser/extensions/extension_info_map.h" |
| 40 #include "chrome/browser/extensions/extension_prefs.h" |
| 41 #include "chrome/browser/extensions/extension_service.h" |
37 #include "chrome/browser/extensions/extension_system.h" | 42 #include "chrome/browser/extensions/extension_system.h" |
38 #include "chrome/browser/icon_loader.h" | 43 #include "chrome/browser/icon_loader.h" |
39 #include "chrome/browser/icon_manager.h" | 44 #include "chrome/browser/icon_manager.h" |
40 #include "chrome/browser/renderer_host/chrome_render_message_filter.h" | 45 #include "chrome/browser/renderer_host/chrome_render_message_filter.h" |
41 #include "chrome/browser/ui/browser.h" | 46 #include "chrome/browser/ui/browser.h" |
42 #include "chrome/common/cancelable_task_tracker.h" | 47 #include "chrome/common/cancelable_task_tracker.h" |
43 #include "chrome/common/chrome_notification_types.h" | 48 #include "chrome/common/chrome_notification_types.h" |
44 #include "chrome/common/extensions/api/downloads.h" | 49 #include "chrome/common/extensions/api/downloads.h" |
45 #include "content/public/browser/download_interrupt_reasons.h" | 50 #include "content/public/browser/download_interrupt_reasons.h" |
46 #include "content/public/browser/download_item.h" | 51 #include "content/public/browser/download_item.h" |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
177 } | 182 } |
178 | 183 |
179 DownloadItem::DownloadState StateEnumFromString(const std::string& state) { | 184 DownloadItem::DownloadState StateEnumFromString(const std::string& state) { |
180 for (size_t i = 0; i < arraysize(kStateStrings); ++i) { | 185 for (size_t i = 0; i < arraysize(kStateStrings); ++i) { |
181 if ((kStateStrings[i] != NULL) && (state == kStateStrings[i])) | 186 if ((kStateStrings[i] != NULL) && (state == kStateStrings[i])) |
182 return static_cast<DownloadItem::DownloadState>(i); | 187 return static_cast<DownloadItem::DownloadState>(i); |
183 } | 188 } |
184 return DownloadItem::MAX_DOWNLOAD_STATE; | 189 return DownloadItem::MAX_DOWNLOAD_STATE; |
185 } | 190 } |
186 | 191 |
187 bool ValidateFilename(const string16& filename) { | 192 bool ValidateFilename(const base::FilePath& filename) { |
188 // TODO(benjhayden): More robust validation of filename. | 193 return !filename.empty() && |
189 if ((filename.find('/') != string16::npos) || | 194 (filename.BaseName().value() != base::FilePath::kCurrentDirectory) && |
190 (filename.find('\\') != string16::npos)) | 195 !filename.ReferencesParent() && |
191 return false; | 196 !filename.IsAbsolute(); |
192 if (filename.size() >= 2u && filename[0] == L'.' && filename[1] == L'.') | |
193 return false; | |
194 return true; | |
195 } | 197 } |
196 | 198 |
197 std::string TimeToISO8601(const base::Time& t) { | 199 std::string TimeToISO8601(const base::Time& t) { |
198 base::Time::Exploded exploded; | 200 base::Time::Exploded exploded; |
199 t.UTCExplode(&exploded); | 201 t.UTCExplode(&exploded); |
200 return base::StringPrintf( | 202 return base::StringPrintf( |
201 "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", exploded.year, exploded.month, | 203 "%04d-%02d-%02dT%02d:%02d:%02d.%03dZ", exploded.year, exploded.month, |
202 exploded.day_of_month, exploded.hour, exploded.minute, exploded.second, | 204 exploded.day_of_month, exploded.hour, exploded.minute, exploded.second, |
203 exploded.millisecond); | 205 exploded.millisecond); |
204 } | 206 } |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
256 }; | 258 }; |
257 | 259 |
258 bool DownloadFileIconExtractorImpl::ExtractIconURLForPath( | 260 bool DownloadFileIconExtractorImpl::ExtractIconURLForPath( |
259 const base::FilePath& path, | 261 const base::FilePath& path, |
260 IconLoader::IconSize icon_size, | 262 IconLoader::IconSize icon_size, |
261 IconURLCallback callback) { | 263 IconURLCallback callback) { |
262 callback_ = callback; | 264 callback_ = callback; |
263 IconManager* im = g_browser_process->icon_manager(); | 265 IconManager* im = g_browser_process->icon_manager(); |
264 // The contents of the file at |path| may have changed since a previous | 266 // The contents of the file at |path| may have changed since a previous |
265 // request, in which case the associated icon may also have changed. | 267 // request, in which case the associated icon may also have changed. |
266 // Therefore, for the moment we always call LoadIcon instead of attempting | 268 // Therefore, always call LoadIcon instead of attempting a LookupIcon. |
267 // a LookupIcon. | |
268 im->LoadIcon(path, | 269 im->LoadIcon(path, |
269 icon_size, | 270 icon_size, |
270 base::Bind(&DownloadFileIconExtractorImpl::OnIconLoadComplete, | 271 base::Bind(&DownloadFileIconExtractorImpl::OnIconLoadComplete, |
271 base::Unretained(this)), | 272 base::Unretained(this)), |
272 &cancelable_task_tracker_); | 273 &cancelable_task_tracker_); |
273 return true; | 274 return true; |
274 } | 275 } |
275 | 276 |
276 void DownloadFileIconExtractorImpl::OnIconLoadComplete(gfx::Image* icon) { | 277 void DownloadFileIconExtractorImpl::OnIconLoadComplete(gfx::Image* icon) { |
277 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
403 // TODO(benjhayden): Consider switching from LazyInstance to explicit string | 404 // TODO(benjhayden): Consider switching from LazyInstance to explicit string |
404 // comparisons. | 405 // comparisons. |
405 static base::LazyInstance<SortTypeMap> sorter_types = | 406 static base::LazyInstance<SortTypeMap> sorter_types = |
406 LAZY_INSTANCE_INITIALIZER; | 407 LAZY_INSTANCE_INITIALIZER; |
407 if (sorter_types.Get().size() == 0) | 408 if (sorter_types.Get().size() == 0) |
408 InitSortTypeMap(sorter_types.Get()); | 409 InitSortTypeMap(sorter_types.Get()); |
409 | 410 |
410 std::vector<std::string> order_by_strs; | 411 std::vector<std::string> order_by_strs; |
411 base::SplitString(order_by_str, ' ', &order_by_strs); | 412 base::SplitString(order_by_str, ' ', &order_by_strs); |
412 for (std::vector<std::string>::const_iterator iter = order_by_strs.begin(); | 413 for (std::vector<std::string>::const_iterator iter = order_by_strs.begin(); |
413 iter != order_by_strs.end(); ++iter) { | 414 iter != order_by_strs.end(); ++iter) { |
414 std::string term_str = *iter; | 415 std::string term_str = *iter; |
415 if (term_str.empty()) | 416 if (term_str.empty()) |
416 continue; | 417 continue; |
417 DownloadQuery::SortDirection direction = DownloadQuery::ASCENDING; | 418 DownloadQuery::SortDirection direction = DownloadQuery::ASCENDING; |
418 if (term_str[0] == '-') { | 419 if (term_str[0] == '-') { |
419 direction = DownloadQuery::DESCENDING; | 420 direction = DownloadQuery::DESCENDING; |
420 term_str = term_str.substr(1); | 421 term_str = term_str.substr(1); |
421 } | 422 } |
422 SortTypeMap::const_iterator sorter_type = | 423 SortTypeMap::const_iterator sorter_type = |
423 sorter_types.Get().find(term_str); | 424 sorter_types.Get().find(term_str); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
500 all_items.push_back(download_item); | 501 all_items.push_back(download_item); |
501 } else { | 502 } else { |
502 manager->GetAllDownloads(&all_items); | 503 manager->GetAllDownloads(&all_items); |
503 if (incognito_manager) | 504 if (incognito_manager) |
504 incognito_manager->GetAllDownloads(&all_items); | 505 incognito_manager->GetAllDownloads(&all_items); |
505 } | 506 } |
506 query_out.AddFilter(base::Bind(&IsNotTemporaryDownloadFilter)); | 507 query_out.AddFilter(base::Bind(&IsNotTemporaryDownloadFilter)); |
507 query_out.Search(all_items.begin(), all_items.end(), results); | 508 query_out.Search(all_items.begin(), all_items.end(), results); |
508 } | 509 } |
509 | 510 |
510 void DispatchEventInternal( | |
511 Profile* target_profile, | |
512 const char* event_name, | |
513 const std::string& json_args, | |
514 scoped_ptr<base::ListValue> event_args) { | |
515 if (!extensions::ExtensionSystem::Get(target_profile)->event_router()) | |
516 return; | |
517 scoped_ptr<extensions::Event> event(new extensions::Event( | |
518 event_name, event_args.Pass())); | |
519 event->restrict_to_profile = target_profile; | |
520 extensions::ExtensionSystem::Get(target_profile)->event_router()-> | |
521 BroadcastEvent(event.Pass()); | |
522 ExtensionDownloadsEventRouter::DownloadsNotificationSource | |
523 notification_source; | |
524 notification_source.event_name = event_name; | |
525 notification_source.profile = target_profile; | |
526 content::Source<ExtensionDownloadsEventRouter::DownloadsNotificationSource> | |
527 content_source(¬ification_source); | |
528 std::string args_copy(json_args); | |
529 content::NotificationService::current()->Notify( | |
530 chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT, | |
531 content_source, | |
532 content::Details<std::string>(&args_copy)); | |
533 } | |
534 | |
535 class ExtensionDownloadsEventRouterData : public base::SupportsUserData::Data { | 511 class ExtensionDownloadsEventRouterData : public base::SupportsUserData::Data { |
536 public: | 512 public: |
537 static ExtensionDownloadsEventRouterData* Get(DownloadItem* download_item) { | 513 static ExtensionDownloadsEventRouterData* Get(DownloadItem* download_item) { |
538 base::SupportsUserData::Data* data = download_item->GetUserData(kKey); | 514 base::SupportsUserData::Data* data = download_item->GetUserData(kKey); |
539 return (data == NULL) ? NULL : | 515 return (data == NULL) ? NULL : |
540 static_cast<ExtensionDownloadsEventRouterData*>(data); | 516 static_cast<ExtensionDownloadsEventRouterData*>(data); |
541 } | 517 } |
542 | 518 |
543 explicit ExtensionDownloadsEventRouterData( | 519 explicit ExtensionDownloadsEventRouterData( |
544 DownloadItem* download_item, | 520 DownloadItem* download_item, |
545 scoped_ptr<base::DictionaryValue> json_item) | 521 scoped_ptr<base::DictionaryValue> json_item) |
546 : updated_(0), | 522 : updated_(0), |
547 changed_fired_(0), | 523 changed_fired_(0), |
548 json_(json_item.Pass()) { | 524 json_(json_item.Pass()), |
| 525 determined_overwrite_(false) { |
549 download_item->SetUserData(kKey, this); | 526 download_item->SetUserData(kKey, this); |
550 } | 527 } |
551 | 528 |
552 virtual ~ExtensionDownloadsEventRouterData() { | 529 virtual ~ExtensionDownloadsEventRouterData() { |
553 if (updated_ > 0) { | 530 if (updated_ > 0) { |
554 UMA_HISTOGRAM_PERCENTAGE("Download.OnChanged", | 531 UMA_HISTOGRAM_PERCENTAGE("Download.OnChanged", |
555 (changed_fired_ * 100 / updated_)); | 532 (changed_fired_ * 100 / updated_)); |
556 } | 533 } |
557 } | 534 } |
558 | 535 |
559 const base::DictionaryValue& json() const { return *json_.get(); } | 536 const base::DictionaryValue& json() const { return *json_.get(); } |
560 void set_json(scoped_ptr<base::DictionaryValue> json_item) { | 537 void set_json(scoped_ptr<base::DictionaryValue> json_item) { |
561 json_ = json_item.Pass(); | 538 json_ = json_item.Pass(); |
562 } | 539 } |
563 | 540 |
564 void OnItemUpdated() { ++updated_; } | 541 void OnItemUpdated() { ++updated_; } |
565 void OnChangedFired() { ++changed_fired_; } | 542 void OnChangedFired() { ++changed_fired_; } |
566 | 543 |
| 544 void set_filename_change_callbacks( |
| 545 const base::Closure& no_change, |
| 546 const ExtensionDownloadsEventRouter::FilenameChangedCallback& change) { |
| 547 filename_no_change_ = no_change; |
| 548 filename_change_ = change; |
| 549 } |
| 550 |
| 551 void ClearPendingDeterminers() { |
| 552 determiners_.clear(); |
| 553 determined_filename_.clear(); |
| 554 determined_overwrite_ = false; |
| 555 determiner_ = DeterminerInfo(); |
| 556 filename_no_change_ = base::Closure(); |
| 557 filename_change_ = ExtensionDownloadsEventRouter::FilenameChangedCallback(); |
| 558 } |
| 559 |
| 560 void ExtensionUnloaded(const std::string& extension_id) { |
| 561 // Remove this extension from |determiners_|. |
| 562 for (DeterminerInfoVector::iterator iter = determiners_.begin(); |
| 563 iter != determiners_.end();) { |
| 564 if (iter->extension_id == extension_id) { |
| 565 iter = determiners_.erase(iter); |
| 566 } else { |
| 567 ++iter; |
| 568 } |
| 569 } |
| 570 // If we just removed the last unreported determiner, then we need to call a |
| 571 // callback. |
| 572 CheckAllDeterminersCalled(); |
| 573 } |
| 574 |
| 575 void DeterminerRemoved(const std::string& extension_id, |
| 576 int sub_event_id) { |
| 577 for (DeterminerInfoVector::iterator iter = determiners_.begin(); |
| 578 iter != determiners_.end();) { |
| 579 if ((iter->extension_id == extension_id) && |
| 580 (iter->sub_event_id == sub_event_id)) { |
| 581 iter = determiners_.erase(iter); |
| 582 } else { |
| 583 ++iter; |
| 584 } |
| 585 } |
| 586 // If we just removed the last unreported determiner, then we need to call a |
| 587 // callback. |
| 588 CheckAllDeterminersCalled(); |
| 589 } |
| 590 |
| 591 void AddPendingDeterminer(const std::string& extension_id, |
| 592 int sub_event_id, |
| 593 const base::Time& installed) { |
| 594 for (int index = 0; index < static_cast<int>(determiners_.size()); |
| 595 ++index) { |
| 596 if ((determiners_[index].extension_id == extension_id) && |
| 597 (determiners_[index].sub_event_id == sub_event_id)) { |
| 598 DCHECK(false) << extension_id << " " << sub_event_id; |
| 599 return; |
| 600 } |
| 601 } |
| 602 determiners_.push_back(DeterminerInfo( |
| 603 extension_id, sub_event_id, installed)); |
| 604 } |
| 605 |
| 606 bool DeterminerCallback( |
| 607 const std::string& extension_id, |
| 608 int sub_event_id, |
| 609 const base::FilePath& filename, |
| 610 bool overwrite) { |
| 611 bool filename_valid = ValidateFilename(filename); |
| 612 bool found_info = false; |
| 613 for (int index = 0; index < static_cast<int>(determiners_.size()); |
| 614 ++index) { |
| 615 if ((determiners_[index].extension_id == extension_id) && |
| 616 (determiners_[index].sub_event_id == sub_event_id)) { |
| 617 found_info = true; |
| 618 DCHECK(!determiners_[index].reported); |
| 619 determiners_[index].reported = true; |
| 620 if (!determiner_.extension_id.empty() && |
| 621 (determiners_[index].extension_id == determiner_.extension_id)) { |
| 622 DCHECK_NE(determiners_[index].sub_event_id, determiner_.sub_event_id); |
| 623 } |
| 624 // Do not use filename if another determiner has already overridden the |
| 625 // filename and they take precedence. Extensions that were installed |
| 626 // later take precedence over previous extensions, and listeners that |
| 627 // were added later take precedence over previous listeners. |
| 628 if (filename_valid && |
| 629 (determiner_.extension_id.empty() || |
| 630 ((determiners_[index].extension_id == determiner_.extension_id) ? |
| 631 (determiners_[index].sub_event_id > determiner_.sub_event_id) : |
| 632 (determiners_[index].install_time > determiner_.install_time)))) { |
| 633 determined_filename_ = filename; |
| 634 determined_overwrite_ = overwrite; |
| 635 determiner_ = determiners_[index]; |
| 636 } |
| 637 break; |
| 638 } |
| 639 } |
| 640 if (!found_info) |
| 641 return false; |
| 642 CheckAllDeterminersCalled(); |
| 643 return filename.empty() || filename_valid; |
| 644 } |
| 645 |
567 private: | 646 private: |
| 647 struct DeterminerInfo { |
| 648 DeterminerInfo(); |
| 649 DeterminerInfo(const std::string& e_id, |
| 650 int sub_id, |
| 651 const base::Time& installed); |
| 652 ~DeterminerInfo(); |
| 653 |
| 654 std::string extension_id; |
| 655 int sub_event_id; |
| 656 base::Time install_time; |
| 657 bool reported; |
| 658 }; |
| 659 typedef std::vector<DeterminerInfo> DeterminerInfoVector; |
| 660 |
568 static const char kKey[]; | 661 static const char kKey[]; |
569 | 662 |
| 663 // This is safe to call even while not waiting for determiners to call back; |
| 664 // in that case, the callbacks will be null so they won't be Run. |
| 665 void CheckAllDeterminersCalled() { |
| 666 for (DeterminerInfoVector::iterator iter = determiners_.begin(); |
| 667 iter != determiners_.end(); ++iter) { |
| 668 if (!iter->reported) |
| 669 return; |
| 670 } |
| 671 if (determined_filename_.empty()) { |
| 672 if (!filename_no_change_.is_null()) |
| 673 filename_no_change_.Run(); |
| 674 } else { |
| 675 if (!filename_change_.is_null()) |
| 676 filename_change_.Run(determined_filename_, determined_overwrite_); |
| 677 } |
| 678 ClearPendingDeterminers(); |
| 679 } |
| 680 |
570 int updated_; | 681 int updated_; |
571 int changed_fired_; | 682 int changed_fired_; |
572 scoped_ptr<base::DictionaryValue> json_; | 683 scoped_ptr<base::DictionaryValue> json_; |
573 | 684 |
| 685 base::Closure filename_no_change_; |
| 686 ExtensionDownloadsEventRouter::FilenameChangedCallback filename_change_; |
| 687 |
| 688 DeterminerInfoVector determiners_; |
| 689 |
| 690 base::FilePath determined_filename_; |
| 691 bool determined_overwrite_; |
| 692 DeterminerInfo determiner_; |
| 693 |
574 DISALLOW_COPY_AND_ASSIGN(ExtensionDownloadsEventRouterData); | 694 DISALLOW_COPY_AND_ASSIGN(ExtensionDownloadsEventRouterData); |
575 }; | 695 }; |
576 | 696 |
| 697 ExtensionDownloadsEventRouterData::DeterminerInfo::DeterminerInfo( |
| 698 const std::string& e_id, |
| 699 int sub_id, |
| 700 const base::Time& installed) |
| 701 : extension_id(e_id), |
| 702 sub_event_id(sub_id), |
| 703 install_time(installed), |
| 704 reported(false) { |
| 705 } |
| 706 |
| 707 ExtensionDownloadsEventRouterData::DeterminerInfo::DeterminerInfo() |
| 708 : reported(false) { |
| 709 } |
| 710 |
| 711 ExtensionDownloadsEventRouterData::DeterminerInfo::~DeterminerInfo() {} |
| 712 |
577 const char ExtensionDownloadsEventRouterData::kKey[] = | 713 const char ExtensionDownloadsEventRouterData::kKey[] = |
578 "DownloadItem ExtensionDownloadsEventRouterData"; | 714 "DownloadItem ExtensionDownloadsEventRouterData"; |
579 | 715 |
580 class ManagerDestructionObserver : public DownloadManager::Observer { | 716 class ManagerDestructionObserver : public DownloadManager::Observer { |
581 public: | 717 public: |
582 static void CheckForHistoryFilesRemoval(DownloadManager* manager) { | 718 static void CheckForHistoryFilesRemoval(DownloadManager* manager) { |
583 if (!manager) | 719 if (!manager) |
584 return; | 720 return; |
585 if (!manager_file_existence_last_checked_) | 721 if (!manager_file_existence_last_checked_) |
586 manager_file_existence_last_checked_ = | 722 manager_file_existence_last_checked_ = |
587 new std::map<DownloadManager*, ManagerDestructionObserver*>(); | 723 new std::map<DownloadManager*, ManagerDestructionObserver*>(); |
588 if (!(*manager_file_existence_last_checked_)[manager]) | 724 if (!(*manager_file_existence_last_checked_)[manager]) |
589 (*manager_file_existence_last_checked_)[manager] = | 725 (*manager_file_existence_last_checked_)[manager] = |
590 new ManagerDestructionObserver(manager); | 726 new ManagerDestructionObserver(manager); |
591 (*manager_file_existence_last_checked_)[manager] | 727 (*manager_file_existence_last_checked_)[manager]-> |
592 ->CheckForHistoryFilesRemovalInternal(); | 728 CheckForHistoryFilesRemovalInternal(); |
593 } | 729 } |
594 | 730 |
595 private: | 731 private: |
596 static const int kFileExistenceRateLimitSeconds = 10; | 732 static const int kFileExistenceRateLimitSeconds = 10; |
597 | 733 |
598 explicit ManagerDestructionObserver(DownloadManager* manager) | 734 explicit ManagerDestructionObserver(DownloadManager* manager) |
599 : manager_(manager) { | 735 : manager_(manager) { |
600 manager_->AddObserver(this); | 736 manager_->AddObserver(this); |
601 } | 737 } |
602 | 738 |
(...skipping 26 matching lines...) Expand all Loading... |
629 | 765 |
630 DISALLOW_COPY_AND_ASSIGN(ManagerDestructionObserver); | 766 DISALLOW_COPY_AND_ASSIGN(ManagerDestructionObserver); |
631 }; | 767 }; |
632 | 768 |
633 std::map<DownloadManager*, ManagerDestructionObserver*>* | 769 std::map<DownloadManager*, ManagerDestructionObserver*>* |
634 ManagerDestructionObserver::manager_file_existence_last_checked_ = NULL; | 770 ManagerDestructionObserver::manager_file_existence_last_checked_ = NULL; |
635 | 771 |
636 } // namespace | 772 } // namespace |
637 | 773 |
638 DownloadsDownloadFunction::DownloadsDownloadFunction() {} | 774 DownloadsDownloadFunction::DownloadsDownloadFunction() {} |
| 775 |
639 DownloadsDownloadFunction::~DownloadsDownloadFunction() {} | 776 DownloadsDownloadFunction::~DownloadsDownloadFunction() {} |
640 | 777 |
641 bool DownloadsDownloadFunction::RunImpl() { | 778 bool DownloadsDownloadFunction::RunImpl() { |
642 scoped_ptr<extensions::api::downloads::Download::Params> params( | 779 scoped_ptr<extensions::api::downloads::Download::Params> params( |
643 extensions::api::downloads::Download::Params::Create(*args_)); | 780 extensions::api::downloads::Download::Params::Create(*args_)); |
644 EXTENSION_FUNCTION_VALIDATE(params.get()); | 781 EXTENSION_FUNCTION_VALIDATE(params.get()); |
645 const extensions::api::downloads::DownloadOptions& options = params->options; | 782 const extensions::api::downloads::DownloadOptions& options = params->options; |
646 GURL download_url(options.url); | 783 GURL download_url(options.url); |
647 if (!download_url.is_valid() || | 784 if (!download_url.is_valid() || |
648 (!download_url.SchemeIs("data") && | 785 (!download_url.SchemeIs("data") && |
(...skipping 16 matching lines...) Expand all Loading... |
665 | 802 |
666 if (options.filename.get()) { | 803 if (options.filename.get()) { |
667 // TODO(benjhayden): Make json_schema_compiler generate string16s instead of | 804 // TODO(benjhayden): Make json_schema_compiler generate string16s instead of |
668 // std::strings. Can't get filename16 from options.ToValue() because that | 805 // std::strings. Can't get filename16 from options.ToValue() because that |
669 // converts it from std::string. | 806 // converts it from std::string. |
670 base::DictionaryValue* options_value = NULL; | 807 base::DictionaryValue* options_value = NULL; |
671 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options_value)); | 808 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options_value)); |
672 string16 filename16; | 809 string16 filename16; |
673 EXTENSION_FUNCTION_VALIDATE(options_value->GetString( | 810 EXTENSION_FUNCTION_VALIDATE(options_value->GetString( |
674 kFilenameKey, &filename16)); | 811 kFilenameKey, &filename16)); |
675 if (!ValidateFilename(filename16)) { | 812 #if defined(OS_WIN) |
| 813 base::FilePath file_path(filename16); |
| 814 #elif defined(OS_POSIX) |
| 815 base::FilePath file_path(*options.filename.get()); |
| 816 #endif |
| 817 if (!ValidateFilename(file_path) || |
| 818 (file_path.DirName().value() != base::FilePath::kCurrentDirectory)) { |
676 error_ = download_extension_errors::kGenericError; | 819 error_ = download_extension_errors::kGenericError; |
677 return false; | 820 return false; |
678 } | 821 } |
679 // TODO(benjhayden) Ensure that this filename is interpreted as a path | 822 // TODO(benjhayden) Ensure that this filename is interpreted as a path |
680 // relative to the default downloads directory without allowing '..'. | 823 // relative to the default downloads directory without allowing '..'. |
681 download_params->set_suggested_name(filename16); | 824 download_params->set_suggested_name(filename16); |
682 } | 825 } |
683 | 826 |
684 if (options.save_as.get()) | 827 if (options.save_as.get()) |
685 download_params->set_prompt(*options.save_as.get()); | 828 download_params->set_prompt(*options.save_as.get()); |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
725 DCHECK_EQ(net::OK, error); | 868 DCHECK_EQ(net::OK, error); |
726 SetResult(base::Value::CreateIntegerValue(item->GetId())); | 869 SetResult(base::Value::CreateIntegerValue(item->GetId())); |
727 } else { | 870 } else { |
728 DCHECK_NE(net::OK, error); | 871 DCHECK_NE(net::OK, error); |
729 error_ = net::ErrorToString(error); | 872 error_ = net::ErrorToString(error); |
730 } | 873 } |
731 SendResponse(error_.empty()); | 874 SendResponse(error_.empty()); |
732 } | 875 } |
733 | 876 |
734 DownloadsSearchFunction::DownloadsSearchFunction() {} | 877 DownloadsSearchFunction::DownloadsSearchFunction() {} |
| 878 |
735 DownloadsSearchFunction::~DownloadsSearchFunction() {} | 879 DownloadsSearchFunction::~DownloadsSearchFunction() {} |
736 | 880 |
737 bool DownloadsSearchFunction::RunImpl() { | 881 bool DownloadsSearchFunction::RunImpl() { |
738 scoped_ptr<extensions::api::downloads::Search::Params> params( | 882 scoped_ptr<extensions::api::downloads::Search::Params> params( |
739 extensions::api::downloads::Search::Params::Create(*args_)); | 883 extensions::api::downloads::Search::Params::Create(*args_)); |
740 EXTENSION_FUNCTION_VALIDATE(params.get()); | 884 EXTENSION_FUNCTION_VALIDATE(params.get()); |
741 DownloadManager* manager = NULL; | 885 DownloadManager* manager = NULL; |
742 DownloadManager* incognito_manager = NULL; | 886 DownloadManager* incognito_manager = NULL; |
743 GetManagers(profile(), include_incognito(), &manager, &incognito_manager); | 887 GetManagers(profile(), include_incognito(), &manager, &incognito_manager); |
744 ManagerDestructionObserver::CheckForHistoryFilesRemoval(manager); | 888 ManagerDestructionObserver::CheckForHistoryFilesRemoval(manager); |
(...skipping 17 matching lines...) Expand all Loading... |
762 scoped_ptr<base::DictionaryValue> json_item(DownloadItemToJSON( | 906 scoped_ptr<base::DictionaryValue> json_item(DownloadItemToJSON( |
763 *it, off_record)); | 907 *it, off_record)); |
764 json_results->Append(json_item.release()); | 908 json_results->Append(json_item.release()); |
765 } | 909 } |
766 SetResult(json_results); | 910 SetResult(json_results); |
767 RecordApiFunctions(DOWNLOADS_FUNCTION_SEARCH); | 911 RecordApiFunctions(DOWNLOADS_FUNCTION_SEARCH); |
768 return true; | 912 return true; |
769 } | 913 } |
770 | 914 |
771 DownloadsPauseFunction::DownloadsPauseFunction() {} | 915 DownloadsPauseFunction::DownloadsPauseFunction() {} |
| 916 |
772 DownloadsPauseFunction::~DownloadsPauseFunction() {} | 917 DownloadsPauseFunction::~DownloadsPauseFunction() {} |
773 | 918 |
774 bool DownloadsPauseFunction::RunImpl() { | 919 bool DownloadsPauseFunction::RunImpl() { |
775 scoped_ptr<extensions::api::downloads::Pause::Params> params( | 920 scoped_ptr<extensions::api::downloads::Pause::Params> params( |
776 extensions::api::downloads::Pause::Params::Create(*args_)); | 921 extensions::api::downloads::Pause::Params::Create(*args_)); |
777 EXTENSION_FUNCTION_VALIDATE(params.get()); | 922 EXTENSION_FUNCTION_VALIDATE(params.get()); |
778 DownloadItem* download_item = GetDownloadIfInProgress( | 923 DownloadItem* download_item = GetDownloadIfInProgress( |
779 profile(), include_incognito(), params->download_id); | 924 profile(), include_incognito(), params->download_id); |
780 if (download_item == NULL) { | 925 if (download_item == NULL) { |
781 // This could be due to an invalid download ID, or it could be due to the | 926 // This could be due to an invalid download ID, or it could be due to the |
782 // download not being currently active. | 927 // download not being currently active. |
783 error_ = download_extension_errors::kInvalidOperationError; | 928 error_ = download_extension_errors::kInvalidOperationError; |
784 } else { | 929 } else { |
785 // If the item is already paused, this is a no-op and the | 930 // If the item is already paused, this is a no-op and the |
786 // operation will silently succeed. | 931 // operation will silently succeed. |
787 download_item->Pause(); | 932 download_item->Pause(); |
788 } | 933 } |
789 if (error_.empty()) | 934 if (error_.empty()) |
790 RecordApiFunctions(DOWNLOADS_FUNCTION_PAUSE); | 935 RecordApiFunctions(DOWNLOADS_FUNCTION_PAUSE); |
791 return error_.empty(); | 936 return error_.empty(); |
792 } | 937 } |
793 | 938 |
794 DownloadsResumeFunction::DownloadsResumeFunction() {} | 939 DownloadsResumeFunction::DownloadsResumeFunction() {} |
| 940 |
795 DownloadsResumeFunction::~DownloadsResumeFunction() {} | 941 DownloadsResumeFunction::~DownloadsResumeFunction() {} |
796 | 942 |
797 bool DownloadsResumeFunction::RunImpl() { | 943 bool DownloadsResumeFunction::RunImpl() { |
798 scoped_ptr<extensions::api::downloads::Resume::Params> params( | 944 scoped_ptr<extensions::api::downloads::Resume::Params> params( |
799 extensions::api::downloads::Resume::Params::Create(*args_)); | 945 extensions::api::downloads::Resume::Params::Create(*args_)); |
800 EXTENSION_FUNCTION_VALIDATE(params.get()); | 946 EXTENSION_FUNCTION_VALIDATE(params.get()); |
801 DownloadItem* download_item = GetDownloadIfInProgress( | 947 DownloadItem* download_item = GetDownloadIfInProgress( |
802 profile(), include_incognito(), params->download_id); | 948 profile(), include_incognito(), params->download_id); |
803 if (download_item == NULL) { | 949 if (download_item == NULL) { |
804 // This could be due to an invalid download ID, or it could be due to the | 950 // This could be due to an invalid download ID, or it could be due to the |
805 // download not being currently active. | 951 // download not being currently active. |
806 error_ = download_extension_errors::kInvalidOperationError; | 952 error_ = download_extension_errors::kInvalidOperationError; |
807 } else { | 953 } else { |
808 // Note that if the item isn't paused, this will be a no-op, and | 954 // Note that if the item isn't paused, this will be a no-op, and |
809 // we will silently treat the extension call as a success. | 955 // the extension call will seem successful. |
810 download_item->Resume(); | 956 download_item->Resume(); |
811 } | 957 } |
812 if (error_.empty()) | 958 if (error_.empty()) |
813 RecordApiFunctions(DOWNLOADS_FUNCTION_RESUME); | 959 RecordApiFunctions(DOWNLOADS_FUNCTION_RESUME); |
814 return error_.empty(); | 960 return error_.empty(); |
815 } | 961 } |
816 | 962 |
817 DownloadsCancelFunction::DownloadsCancelFunction() {} | 963 DownloadsCancelFunction::DownloadsCancelFunction() {} |
| 964 |
818 DownloadsCancelFunction::~DownloadsCancelFunction() {} | 965 DownloadsCancelFunction::~DownloadsCancelFunction() {} |
819 | 966 |
820 bool DownloadsCancelFunction::RunImpl() { | 967 bool DownloadsCancelFunction::RunImpl() { |
821 scoped_ptr<extensions::api::downloads::Resume::Params> params( | 968 scoped_ptr<extensions::api::downloads::Resume::Params> params( |
822 extensions::api::downloads::Resume::Params::Create(*args_)); | 969 extensions::api::downloads::Resume::Params::Create(*args_)); |
823 EXTENSION_FUNCTION_VALIDATE(params.get()); | 970 EXTENSION_FUNCTION_VALIDATE(params.get()); |
824 DownloadItem* download_item = GetDownloadIfInProgress( | 971 DownloadItem* download_item = GetDownloadIfInProgress( |
825 profile(), include_incognito(), params->download_id); | 972 profile(), include_incognito(), params->download_id); |
826 if (download_item != NULL) | 973 if (download_item != NULL) |
827 download_item->Cancel(true); | 974 download_item->Cancel(true); |
828 // |download_item| can be NULL if the download ID was invalid or if the | 975 // |download_item| can be NULL if the download ID was invalid or if the |
829 // download is not currently active. Either way, we don't consider it a | 976 // download is not currently active. Either way, it's not a failure. |
830 // failure. | |
831 RecordApiFunctions(DOWNLOADS_FUNCTION_CANCEL); | 977 RecordApiFunctions(DOWNLOADS_FUNCTION_CANCEL); |
832 return true; | 978 return true; |
833 } | 979 } |
834 | 980 |
835 DownloadsEraseFunction::DownloadsEraseFunction() {} | 981 DownloadsEraseFunction::DownloadsEraseFunction() {} |
| 982 |
836 DownloadsEraseFunction::~DownloadsEraseFunction() {} | 983 DownloadsEraseFunction::~DownloadsEraseFunction() {} |
837 | 984 |
838 bool DownloadsEraseFunction::RunImpl() { | 985 bool DownloadsEraseFunction::RunImpl() { |
839 scoped_ptr<extensions::api::downloads::Erase::Params> params( | 986 scoped_ptr<extensions::api::downloads::Erase::Params> params( |
840 extensions::api::downloads::Erase::Params::Create(*args_)); | 987 extensions::api::downloads::Erase::Params::Create(*args_)); |
841 EXTENSION_FUNCTION_VALIDATE(params.get()); | 988 EXTENSION_FUNCTION_VALIDATE(params.get()); |
842 DownloadManager* manager = NULL; | 989 DownloadManager* manager = NULL; |
843 DownloadManager* incognito_manager = NULL; | 990 DownloadManager* incognito_manager = NULL; |
844 GetManagers(profile(), include_incognito(), &manager, &incognito_manager); | 991 GetManagers(profile(), include_incognito(), &manager, &incognito_manager); |
845 DownloadQuery::DownloadVector results; | 992 DownloadQuery::DownloadVector results; |
846 RunDownloadQuery(params->query, | 993 RunDownloadQuery(params->query, |
847 manager, | 994 manager, |
848 incognito_manager, | 995 incognito_manager, |
849 &error_, | 996 &error_, |
850 &results); | 997 &results); |
851 if (!error_.empty()) | 998 if (!error_.empty()) |
852 return false; | 999 return false; |
853 base::ListValue* json_results = new base::ListValue(); | 1000 base::ListValue* json_results = new base::ListValue(); |
854 for (DownloadManager::DownloadVector::const_iterator it = results.begin(); | 1001 for (DownloadManager::DownloadVector::const_iterator it = results.begin(); |
855 it != results.end(); ++it) { | 1002 it != results.end(); ++it) { |
856 json_results->Append(base::Value::CreateIntegerValue((*it)->GetId())); | 1003 json_results->Append(base::Value::CreateIntegerValue((*it)->GetId())); |
857 (*it)->Remove(); | 1004 (*it)->Remove(); |
858 } | 1005 } |
859 SetResult(json_results); | 1006 SetResult(json_results); |
860 RecordApiFunctions(DOWNLOADS_FUNCTION_ERASE); | 1007 RecordApiFunctions(DOWNLOADS_FUNCTION_ERASE); |
861 return true; | 1008 return true; |
862 } | 1009 } |
863 | 1010 |
864 DownloadsSetDestinationFunction::DownloadsSetDestinationFunction() {} | 1011 DownloadsAcceptDangerFunction::DownloadsAcceptDangerFunction() {} |
865 DownloadsSetDestinationFunction::~DownloadsSetDestinationFunction() {} | |
866 | 1012 |
867 bool DownloadsSetDestinationFunction::RunImpl() { | |
868 scoped_ptr<extensions::api::downloads::SetDestination::Params> params( | |
869 extensions::api::downloads::SetDestination::Params::Create(*args_)); | |
870 EXTENSION_FUNCTION_VALIDATE(params.get()); | |
871 error_ = download_extension_errors::kNotImplementedError; | |
872 if (error_.empty()) | |
873 RecordApiFunctions(DOWNLOADS_FUNCTION_SET_DESTINATION); | |
874 return error_.empty(); | |
875 } | |
876 | |
877 DownloadsAcceptDangerFunction::DownloadsAcceptDangerFunction() {} | |
878 DownloadsAcceptDangerFunction::~DownloadsAcceptDangerFunction() {} | 1013 DownloadsAcceptDangerFunction::~DownloadsAcceptDangerFunction() {} |
879 | 1014 |
880 bool DownloadsAcceptDangerFunction::RunImpl() { | 1015 bool DownloadsAcceptDangerFunction::RunImpl() { |
881 scoped_ptr<extensions::api::downloads::AcceptDanger::Params> params( | 1016 scoped_ptr<extensions::api::downloads::AcceptDanger::Params> params( |
882 extensions::api::downloads::AcceptDanger::Params::Create(*args_)); | 1017 extensions::api::downloads::AcceptDanger::Params::Create(*args_)); |
883 EXTENSION_FUNCTION_VALIDATE(params.get()); | 1018 EXTENSION_FUNCTION_VALIDATE(params.get()); |
884 DownloadItem* download_item = GetDownloadIfInProgress( | 1019 DownloadItem* download_item = GetDownloadIfInProgress( |
885 profile(), include_incognito(), params->download_id); | 1020 profile(), include_incognito(), params->download_id); |
886 content::WebContents* web_contents = | 1021 content::WebContents* web_contents = |
887 dispatcher()->delegate()->GetAssociatedWebContents(); | 1022 dispatcher()->delegate()->GetAssociatedWebContents(); |
(...skipping 23 matching lines...) Expand all Loading... |
911 if (accept) { | 1046 if (accept) { |
912 DownloadItem* download_item = GetDownloadIfInProgress( | 1047 DownloadItem* download_item = GetDownloadIfInProgress( |
913 profile(), include_incognito(), download_id); | 1048 profile(), include_incognito(), download_id); |
914 if (download_item) | 1049 if (download_item) |
915 download_item->DangerousDownloadValidated(); | 1050 download_item->DangerousDownloadValidated(); |
916 } | 1051 } |
917 SendResponse(error_.empty()); | 1052 SendResponse(error_.empty()); |
918 } | 1053 } |
919 | 1054 |
920 DownloadsShowFunction::DownloadsShowFunction() {} | 1055 DownloadsShowFunction::DownloadsShowFunction() {} |
| 1056 |
921 DownloadsShowFunction::~DownloadsShowFunction() {} | 1057 DownloadsShowFunction::~DownloadsShowFunction() {} |
922 | 1058 |
923 bool DownloadsShowFunction::RunImpl() { | 1059 bool DownloadsShowFunction::RunImpl() { |
924 scoped_ptr<extensions::api::downloads::Show::Params> params( | 1060 scoped_ptr<extensions::api::downloads::Show::Params> params( |
925 extensions::api::downloads::Show::Params::Create(*args_)); | 1061 extensions::api::downloads::Show::Params::Create(*args_)); |
926 EXTENSION_FUNCTION_VALIDATE(params.get()); | 1062 EXTENSION_FUNCTION_VALIDATE(params.get()); |
927 DownloadItem* download_item = GetDownload( | 1063 DownloadItem* download_item = GetDownload( |
928 profile(), include_incognito(), params->download_id); | 1064 profile(), include_incognito(), params->download_id); |
929 if (!download_item) { | 1065 if (!download_item) { |
930 error_ = download_extension_errors::kInvalidOperationError; | 1066 error_ = download_extension_errors::kInvalidOperationError; |
931 return false; | 1067 return false; |
932 } | 1068 } |
933 download_item->ShowDownloadInShell(); | 1069 download_item->ShowDownloadInShell(); |
934 RecordApiFunctions(DOWNLOADS_FUNCTION_SHOW); | 1070 RecordApiFunctions(DOWNLOADS_FUNCTION_SHOW); |
935 return true; | 1071 return true; |
936 } | 1072 } |
937 | 1073 |
938 DownloadsOpenFunction::DownloadsOpenFunction() {} | 1074 DownloadsOpenFunction::DownloadsOpenFunction() {} |
| 1075 |
939 DownloadsOpenFunction::~DownloadsOpenFunction() {} | 1076 DownloadsOpenFunction::~DownloadsOpenFunction() {} |
940 | 1077 |
941 bool DownloadsOpenFunction::RunImpl() { | 1078 bool DownloadsOpenFunction::RunImpl() { |
942 scoped_ptr<extensions::api::downloads::Open::Params> params( | 1079 scoped_ptr<extensions::api::downloads::Open::Params> params( |
943 extensions::api::downloads::Open::Params::Create(*args_)); | 1080 extensions::api::downloads::Open::Params::Create(*args_)); |
944 EXTENSION_FUNCTION_VALIDATE(params.get()); | 1081 EXTENSION_FUNCTION_VALIDATE(params.get()); |
945 DownloadItem* download_item = GetDownload( | 1082 DownloadItem* download_item = GetDownload( |
946 profile(), include_incognito(), params->download_id); | 1083 profile(), include_incognito(), params->download_id); |
947 if (!download_item || !download_item->IsComplete()) { | 1084 if (!download_item || !download_item->IsComplete()) { |
948 error_ = download_extension_errors::kInvalidOperationError; | 1085 error_ = download_extension_errors::kInvalidOperationError; |
949 return false; | 1086 return false; |
950 } | 1087 } |
951 download_item->OpenDownload(); | 1088 download_item->OpenDownload(); |
952 RecordApiFunctions(DOWNLOADS_FUNCTION_OPEN); | 1089 RecordApiFunctions(DOWNLOADS_FUNCTION_OPEN); |
953 return true; | 1090 return true; |
954 } | 1091 } |
955 | 1092 |
956 DownloadsDragFunction::DownloadsDragFunction() {} | 1093 DownloadsDragFunction::DownloadsDragFunction() {} |
| 1094 |
957 DownloadsDragFunction::~DownloadsDragFunction() {} | 1095 DownloadsDragFunction::~DownloadsDragFunction() {} |
958 | 1096 |
959 bool DownloadsDragFunction::RunImpl() { | 1097 bool DownloadsDragFunction::RunImpl() { |
960 scoped_ptr<extensions::api::downloads::Drag::Params> params( | 1098 scoped_ptr<extensions::api::downloads::Drag::Params> params( |
961 extensions::api::downloads::Drag::Params::Create(*args_)); | 1099 extensions::api::downloads::Drag::Params::Create(*args_)); |
962 EXTENSION_FUNCTION_VALIDATE(params.get()); | 1100 EXTENSION_FUNCTION_VALIDATE(params.get()); |
963 DownloadItem* download_item = GetDownload( | 1101 DownloadItem* download_item = GetDownload( |
964 profile(), include_incognito(), params->download_id); | 1102 profile(), include_incognito(), params->download_id); |
965 content::WebContents* web_contents = | 1103 content::WebContents* web_contents = |
966 dispatcher()->delegate()->GetAssociatedWebContents(); | 1104 dispatcher()->delegate()->GetAssociatedWebContents(); |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1001 int icon_size = kDefaultIconSize; | 1139 int icon_size = kDefaultIconSize; |
1002 if (options && options->size.get()) | 1140 if (options && options->size.get()) |
1003 icon_size = *options->size.get(); | 1141 icon_size = *options->size.get(); |
1004 DownloadItem* download_item = GetDownload( | 1142 DownloadItem* download_item = GetDownload( |
1005 profile(), include_incognito(), params->download_id); | 1143 profile(), include_incognito(), params->download_id); |
1006 if (!download_item || download_item->GetTargetFilePath().empty()) { | 1144 if (!download_item || download_item->GetTargetFilePath().empty()) { |
1007 error_ = download_extension_errors::kInvalidOperationError; | 1145 error_ = download_extension_errors::kInvalidOperationError; |
1008 return false; | 1146 return false; |
1009 } | 1147 } |
1010 // In-progress downloads return the intermediate filename for GetFullPath() | 1148 // In-progress downloads return the intermediate filename for GetFullPath() |
1011 // which doesn't have the final extension. Therefore we won't be able to | 1149 // which doesn't have the final extension. Therefore a good file icon can't be |
1012 // derive a good file icon for it. So we use GetTargetFilePath() instead. | 1150 // found, so use GetTargetFilePath() instead. |
1013 DCHECK(icon_extractor_.get()); | 1151 DCHECK(icon_extractor_.get()); |
1014 DCHECK(icon_size == 16 || icon_size == 32); | 1152 DCHECK(icon_size == 16 || icon_size == 32); |
1015 EXTENSION_FUNCTION_VALIDATE(icon_extractor_->ExtractIconURLForPath( | 1153 EXTENSION_FUNCTION_VALIDATE(icon_extractor_->ExtractIconURLForPath( |
1016 download_item->GetTargetFilePath(), | 1154 download_item->GetTargetFilePath(), |
1017 IconLoaderSizeFromPixelSize(icon_size), | 1155 IconLoaderSizeFromPixelSize(icon_size), |
1018 base::Bind(&DownloadsGetFileIconFunction::OnIconURLExtracted, this))); | 1156 base::Bind(&DownloadsGetFileIconFunction::OnIconURLExtracted, this))); |
1019 return true; | 1157 return true; |
1020 } | 1158 } |
1021 | 1159 |
1022 void DownloadsGetFileIconFunction::OnIconURLExtracted(const std::string& url) { | 1160 void DownloadsGetFileIconFunction::OnIconURLExtracted(const std::string& url) { |
1023 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1161 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1024 if (url.empty()) { | 1162 if (url.empty()) { |
1025 error_ = download_extension_errors::kIconNotFoundError; | 1163 error_ = download_extension_errors::kIconNotFoundError; |
1026 } else { | 1164 } else { |
1027 RecordApiFunctions(DOWNLOADS_FUNCTION_GET_FILE_ICON); | 1165 RecordApiFunctions(DOWNLOADS_FUNCTION_GET_FILE_ICON); |
1028 SetResult(base::Value::CreateStringValue(url)); | 1166 SetResult(base::Value::CreateStringValue(url)); |
1029 } | 1167 } |
1030 SendResponse(error_.empty()); | 1168 SendResponse(error_.empty()); |
1031 } | 1169 } |
1032 | 1170 |
| 1171 ExtensionDownloadsEventRouter::DeterminerId::DeterminerId( |
| 1172 const std::string& ext_id, |
| 1173 int sub_id, |
| 1174 bool incognito, |
| 1175 const base::Time& install) |
| 1176 : extension_id(ext_id), |
| 1177 sub_event_id(sub_id), |
| 1178 include_incognito(incognito), |
| 1179 installed(install) { |
| 1180 } |
| 1181 |
| 1182 ExtensionDownloadsEventRouter::DeterminerId::~DeterminerId() {} |
| 1183 |
1033 ExtensionDownloadsEventRouter::ExtensionDownloadsEventRouter( | 1184 ExtensionDownloadsEventRouter::ExtensionDownloadsEventRouter( |
1034 Profile* profile, | 1185 Profile* profile, |
1035 DownloadManager* manager) | 1186 DownloadManager* manager) |
1036 : profile_(profile), | 1187 : profile_(profile), |
1037 ALLOW_THIS_IN_INITIALIZER_LIST(notifier_(manager, this)) { | 1188 ALLOW_THIS_IN_INITIALIZER_LIST(notifier_(manager, this)) { |
1038 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1189 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1039 DCHECK(profile_); | 1190 DCHECK(profile_); |
| 1191 extensions::EventRouter* router = extensions::ExtensionSystem::Get(profile_)-> |
| 1192 event_router(); |
| 1193 if (router) |
| 1194 router->RegisterObserver(this, std::string( |
| 1195 extensions::event_names::kOnDownloadDeterminingFilename) + "/1"); |
1040 } | 1196 } |
1041 | 1197 |
1042 ExtensionDownloadsEventRouter::~ExtensionDownloadsEventRouter() { | 1198 ExtensionDownloadsEventRouter::~ExtensionDownloadsEventRouter() { |
1043 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1199 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1044 } | 1200 extensions::EventRouter* router = extensions::ExtensionSystem::Get(profile_)-> |
| 1201 event_router(); |
| 1202 if (router) |
| 1203 router->UnregisterObserver(this); |
| 1204 } |
| 1205 |
| 1206 // The method by which extensions hook into the filename determination process |
| 1207 // is based on the method by which the webRequest API allows extensions to hook |
| 1208 // into the resource loading process. Extensions that wish to play a part in |
| 1209 // the filename determination process call |
| 1210 // chrome.downloads.onDeterminingFilename.addListener, which secretly (see |
| 1211 // chrome/renderer/resources/extensions/downloads_custom_bindings.js) calls |
| 1212 // DownloadsInternalAddFilenameDeterminerFunction (see ../downloads_internal/), |
| 1213 // which adds the extension's ID to the profile's ExtensionDownloadsEventRouter |
| 1214 // (EDER). |
| 1215 // |
| 1216 // When a download's filename is being determined, |
| 1217 // ChromeDownloadManagerDelegate::CheckVisitedReferrerBeforeDone (CVRBD) passes |
| 1218 // 2 callbacks to EDER::OnDeterminingFilename (ODFD), which stores the |
| 1219 // callbacks in the item's ExtensionDownloadsEventRouterData (EDERD) along with |
| 1220 // all of the extension IDs that are listening for onDeterminingFilename events. |
| 1221 // ODFD dispatches chrome.downloads.onDeterminingFilename. |
| 1222 // |
| 1223 // When the extension's event handler returns, downloads_custom_bindings.js |
| 1224 // calls DownloadsInternalDetermineFilenameFunction::RunImpl, which notifies the |
| 1225 // item's EDERD. |
| 1226 // |
| 1227 // When the last extension's event handler returns, EDERD calls one of the two |
| 1228 // callbacks that CVRBD passed to ODFD, allowing CDMD to complete the filename |
| 1229 // determination process. If multiple extensions wish to override the filename, |
| 1230 // then the extension that was last installed wins; if multiple determiners |
| 1231 // within an extension compete, then the determiner that was last added wins. |
| 1232 |
| 1233 void ExtensionDownloadsEventRouter::OnDeterminingFilename( |
| 1234 DownloadItem* item, |
| 1235 const base::FilePath& suggested_path, |
| 1236 const base::Closure& no_change, |
| 1237 const FilenameChangedCallback& change) { |
| 1238 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1239 bool any_determiners = false; |
| 1240 |
| 1241 ExtensionDownloadsEventRouterData* data = |
| 1242 ExtensionDownloadsEventRouterData::Get(item); |
| 1243 data->ClearPendingDeterminers(); |
| 1244 data->set_filename_change_callbacks(no_change, change); |
| 1245 std::set<int> sub_events; |
| 1246 for (DeterminerVector::const_iterator iter = determiners_.begin(); |
| 1247 iter != determiners_.end(); ++iter) { |
| 1248 data->AddPendingDeterminer(iter->extension_id, |
| 1249 iter->sub_event_id, |
| 1250 iter->installed); |
| 1251 sub_events.insert(iter->sub_event_id); |
| 1252 any_determiners = true; |
| 1253 } |
| 1254 |
| 1255 if (profile_->IsOffTheRecord()) { |
| 1256 // If this DownloadItem is incognito and there are any |
| 1257 // incognito-spanning-mode extensions registered in the on-record EDER, then |
| 1258 // dispatch to them and wait for them as well. |
| 1259 ExtensionDownloadsEventRouter* router = |
| 1260 DownloadServiceFactory::GetForProfile( |
| 1261 profile_->GetOriginalProfile())->GetExtensionEventRouter(); |
| 1262 for (DeterminerVector::const_iterator iter = router->determiners_.begin(); |
| 1263 iter != router->determiners_.end(); ++iter) { |
| 1264 if (iter->include_incognito) { |
| 1265 data->AddPendingDeterminer(iter->extension_id, |
| 1266 iter->sub_event_id, |
| 1267 iter->installed); |
| 1268 sub_events.insert(iter->sub_event_id); |
| 1269 any_determiners = true; |
| 1270 } |
| 1271 } |
| 1272 } |
| 1273 |
| 1274 std::string event_name( |
| 1275 extensions::event_names::kOnDownloadDeterminingFilename); |
| 1276 event_name += "/"; |
| 1277 for (std::set<int>::const_iterator iter = sub_events.begin(); |
| 1278 iter != sub_events.end(); ++iter) { |
| 1279 base::DictionaryValue* json = DownloadItemToJSON( |
| 1280 item, profile_->IsOffTheRecord()).release(); |
| 1281 json->SetString(kFilenameKey, suggested_path.LossyDisplayName()); |
| 1282 // If there's a listener in an incognito extension renderer, then it will |
| 1283 // have registered its own determiner in the incognito EDER, which will be |
| 1284 // called for incognito downloads. |
| 1285 DispatchEvent((event_name + base::IntToString(*iter)).c_str(), false, json); |
| 1286 } |
| 1287 |
| 1288 if (!any_determiners) { |
| 1289 no_change.Run(); |
| 1290 return; |
| 1291 } |
| 1292 } |
| 1293 |
| 1294 bool ExtensionDownloadsEventRouter::DetermineFilename( |
| 1295 Profile* profile, |
| 1296 bool include_incognito, |
| 1297 const std::string& ext_id, |
| 1298 int sub_event_id, |
| 1299 int download_id, |
| 1300 const base::FilePath& filename, |
| 1301 bool overwrite) { |
| 1302 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1303 DownloadItem* item = GetDownloadIfInProgress( |
| 1304 profile, include_incognito, download_id); |
| 1305 if (!item) |
| 1306 return false; |
| 1307 ExtensionDownloadsEventRouterData* data = |
| 1308 ExtensionDownloadsEventRouterData::Get(item); |
| 1309 if (!data) |
| 1310 return false; |
| 1311 return data->DeterminerCallback(ext_id, sub_event_id, filename, overwrite); |
| 1312 } |
| 1313 |
| 1314 void ExtensionDownloadsEventRouter::OnListenerAdded( |
| 1315 const extensions::EventListenerInfo& details) { |
| 1316 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1317 // An extension has started listening for "onDeterminingFilename/N". It may |
| 1318 // start listening for "onDeterminingFilename/(N+1)", so add an EventRouter |
| 1319 // Observer to listen for when that listener is added. |
| 1320 if (!StartsWithASCII( |
| 1321 details.event_name, |
| 1322 (std::string(extensions::event_names::kOnDownloadDeterminingFilename) + |
| 1323 "/"), |
| 1324 true/*case_sensitive*/)) |
| 1325 return; |
| 1326 std::string sub_event_id_str = details.event_name.substr(strlen( |
| 1327 extensions::event_names::kOnDownloadDeterminingFilename) + 1); |
| 1328 int sub_event_id = -1; |
| 1329 if (!base::StringToInt(sub_event_id_str, &sub_event_id)) |
| 1330 return; |
| 1331 |
| 1332 // Only incognito/regular renderer processes receive onDeterminingFilename |
| 1333 // events for incognito/regular downloads. Do not automatically add this |
| 1334 // determiner to the other (incognito/regular) EDER; if the extension wants to |
| 1335 // listen for onDeterminingFilename in those extension renderer processes, |
| 1336 // then it will call addListener there, and |profile| will be |
| 1337 // incognito/regular for those addListener calls, so they will use the |
| 1338 // incognito/regular EDER. |
| 1339 bool already_added = false; |
| 1340 for (DeterminerVector::const_iterator iter = determiners_.begin(); |
| 1341 iter != determiners_.end(); ++iter) { |
| 1342 if (iter->extension_id == details.extension_id) { |
| 1343 DCHECK_NE(iter->sub_event_id, sub_event_id); |
| 1344 } |
| 1345 if ((iter->extension_id == details.extension_id) && |
| 1346 (iter->sub_event_id == sub_event_id)) { |
| 1347 already_added = true; |
| 1348 break; |
| 1349 } |
| 1350 } |
| 1351 const extensions::Extension* extension = extensions::ExtensionSystem::Get( |
| 1352 profile_)->extension_service()->GetExtensionById( |
| 1353 details.extension_id, false/*include_disabled*/); |
| 1354 if (!already_added && extension) { |
| 1355 base::Time installed = extensions::ExtensionSystem::Get(profile_)-> |
| 1356 extension_service()->extension_prefs()->GetInstallTime( |
| 1357 details.extension_id); |
| 1358 bool include_incognito = !extension->incognito_split_mode(); |
| 1359 determiners_.push_back(DeterminerId( |
| 1360 details.extension_id, sub_event_id, include_incognito, installed)); |
| 1361 } |
| 1362 |
| 1363 // It doesn't hurt to register as an observer for the same event_name more |
| 1364 // than once. |
| 1365 extensions::EventRouter* router = extensions::ExtensionSystem::Get(profile_)-> |
| 1366 event_router(); |
| 1367 if (!router) |
| 1368 return; |
| 1369 std::string next_listener(base::StringPrintf( |
| 1370 "%s/%d", |
| 1371 extensions::event_names::kOnDownloadDeterminingFilename, |
| 1372 sub_event_id + 1)); |
| 1373 router->RegisterObserver(this, next_listener); |
| 1374 } |
| 1375 |
| 1376 void ExtensionDownloadsEventRouter::OnListenerRemoved( |
| 1377 const extensions::EventListenerInfo& details) { |
| 1378 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1379 if (!StartsWithASCII( |
| 1380 details.event_name, |
| 1381 (std::string(extensions::event_names::kOnDownloadDeterminingFilename) + |
| 1382 "/"), |
| 1383 true/*case_sensitive*/)) |
| 1384 return; |
| 1385 std::string sub_event_id_str = details.event_name.substr(strlen( |
| 1386 extensions::event_names::kOnDownloadDeterminingFilename) + 1); |
| 1387 int sub_event_id = -1; |
| 1388 if (!base::StringToInt(sub_event_id_str, &sub_event_id)) |
| 1389 return; |
| 1390 DownloadManager* manager = notifier_.GetManager(); |
| 1391 if (!manager) |
| 1392 return; |
| 1393 DownloadManager::DownloadVector items; |
| 1394 manager->GetAllDownloads(&items); |
| 1395 for (DeterminerVector::iterator iter = determiners_.begin(); |
| 1396 iter != determiners_.end(); ++iter) { |
| 1397 if ((iter->extension_id == details.extension_id) && |
| 1398 (iter->sub_event_id == sub_event_id)) { |
| 1399 determiners_.erase(iter); |
| 1400 // Notify any items that may be waiting for callbacks from this |
| 1401 // determiner. |
| 1402 for (DownloadManager::DownloadVector::const_iterator iter = |
| 1403 items.begin(); |
| 1404 iter != items.end(); ++iter) { |
| 1405 ExtensionDownloadsEventRouterData* data = |
| 1406 ExtensionDownloadsEventRouterData::Get(*iter); |
| 1407 if (data) |
| 1408 data->DeterminerRemoved(details.extension_id, sub_event_id); |
| 1409 } |
| 1410 return; |
| 1411 } |
| 1412 } |
| 1413 } |
| 1414 |
| 1415 // That's all the methods that have to do with filename determination. The rest |
| 1416 // have to do with the other, less special events. |
1045 | 1417 |
1046 void ExtensionDownloadsEventRouter::OnDownloadCreated( | 1418 void ExtensionDownloadsEventRouter::OnDownloadCreated( |
1047 DownloadManager* manager, DownloadItem* download_item) { | 1419 DownloadManager* manager, DownloadItem* download_item) { |
1048 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1420 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1049 if (download_item->IsTemporary()) | 1421 if (download_item->IsTemporary()) |
1050 return; | 1422 return; |
1051 | 1423 |
1052 scoped_ptr<base::DictionaryValue> json_item( | 1424 scoped_ptr<base::DictionaryValue> json_item( |
1053 DownloadItemToJSON(download_item, profile_->IsOffTheRecord())); | 1425 DownloadItemToJSON(download_item, profile_->IsOffTheRecord())); |
1054 DispatchEvent(extensions::event_names::kOnDownloadCreated, | 1426 DispatchEvent(extensions::event_names::kOnDownloadCreated, |
| 1427 true, |
1055 json_item->DeepCopy()); | 1428 json_item->DeepCopy()); |
1056 if (!ExtensionDownloadsEventRouterData::Get(download_item)) | 1429 if (!ExtensionDownloadsEventRouterData::Get(download_item)) |
1057 new ExtensionDownloadsEventRouterData(download_item, json_item.Pass()); | 1430 new ExtensionDownloadsEventRouterData(download_item, json_item.Pass()); |
1058 } | 1431 } |
1059 | 1432 |
1060 void ExtensionDownloadsEventRouter::OnDownloadUpdated( | 1433 void ExtensionDownloadsEventRouter::OnDownloadUpdated( |
1061 DownloadManager* manager, DownloadItem* download_item) { | 1434 DownloadManager* manager, DownloadItem* download_item) { |
1062 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1435 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1063 if (download_item->IsTemporary()) | 1436 if (download_item->IsTemporary()) |
1064 return; | 1437 return; |
1065 | 1438 |
1066 ExtensionDownloadsEventRouterData* data = | 1439 ExtensionDownloadsEventRouterData* data = |
1067 ExtensionDownloadsEventRouterData::Get(download_item); | 1440 ExtensionDownloadsEventRouterData::Get(download_item); |
1068 if (!data) { | 1441 if (!data) { |
1069 // The download_item probably transitioned from temporary to not temporary. | 1442 // The download_item probably transitioned from temporary to not temporary. |
1070 OnDownloadCreated(manager, download_item); | 1443 OnDownloadCreated(manager, download_item); |
1071 return; | 1444 return; |
1072 } | 1445 } |
1073 scoped_ptr<base::DictionaryValue> new_json(DownloadItemToJSON( | 1446 scoped_ptr<base::DictionaryValue> new_json(DownloadItemToJSON( |
1074 download_item, profile_->IsOffTheRecord())); | 1447 download_item, profile_->IsOffTheRecord())); |
1075 scoped_ptr<base::DictionaryValue> delta(new base::DictionaryValue()); | 1448 scoped_ptr<base::DictionaryValue> delta(new base::DictionaryValue()); |
1076 delta->SetInteger(kIdKey, download_item->GetId()); | 1449 delta->SetInteger(kIdKey, download_item->GetId()); |
1077 std::set<std::string> new_fields; | 1450 std::set<std::string> new_fields; |
1078 bool changed = false; | 1451 bool changed = false; |
1079 | 1452 |
1080 // For each field in the new json representation of the download_item except | 1453 // For each field in the new json representation of the download_item except |
1081 // the bytesReceived field, if the field has changed from the previous old | 1454 // the bytesReceived field, if the field has changed from the previous old |
1082 // json, set the differences in the |delta| object and remember that something | 1455 // json, set the differences in the |delta| object and remember that something |
1083 // significant changed. | 1456 // significant changed. |
1084 for (base::DictionaryValue::Iterator iter(*new_json.get()); | 1457 for (base::DictionaryValue::Iterator iter(*new_json.get()); |
(...skipping 19 matching lines...) Expand all Loading... |
1104 if (new_fields.find(iter.key()) == new_fields.end()) { | 1477 if (new_fields.find(iter.key()) == new_fields.end()) { |
1105 delta->Set(iter.key() + ".previous", iter.value().DeepCopy()); | 1478 delta->Set(iter.key() + ".previous", iter.value().DeepCopy()); |
1106 changed = true; | 1479 changed = true; |
1107 } | 1480 } |
1108 } | 1481 } |
1109 | 1482 |
1110 // Update the OnChangedStat and dispatch the event if something significant | 1483 // Update the OnChangedStat and dispatch the event if something significant |
1111 // changed. Replace the stored json with the new json. | 1484 // changed. Replace the stored json with the new json. |
1112 data->OnItemUpdated(); | 1485 data->OnItemUpdated(); |
1113 if (changed) { | 1486 if (changed) { |
1114 DispatchEvent(extensions::event_names::kOnDownloadChanged, delta.release()); | 1487 DispatchEvent(extensions::event_names::kOnDownloadChanged, |
| 1488 true, |
| 1489 delta.release()); |
1115 data->OnChangedFired(); | 1490 data->OnChangedFired(); |
1116 } | 1491 } |
1117 data->set_json(new_json.Pass()); | 1492 data->set_json(new_json.Pass()); |
1118 } | 1493 } |
1119 | 1494 |
1120 void ExtensionDownloadsEventRouter::OnDownloadRemoved( | 1495 void ExtensionDownloadsEventRouter::OnDownloadRemoved( |
1121 DownloadManager* manager, DownloadItem* download_item) { | 1496 DownloadManager* manager, DownloadItem* download_item) { |
1122 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1497 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1123 if (download_item->IsTemporary()) | 1498 if (download_item->IsTemporary()) |
1124 return; | 1499 return; |
1125 DispatchEvent(extensions::event_names::kOnDownloadErased, | 1500 DispatchEvent(extensions::event_names::kOnDownloadErased, |
| 1501 true, |
1126 base::Value::CreateIntegerValue(download_item->GetId())); | 1502 base::Value::CreateIntegerValue(download_item->GetId())); |
1127 } | 1503 } |
1128 | 1504 |
1129 void ExtensionDownloadsEventRouter::DispatchEvent( | 1505 void ExtensionDownloadsEventRouter::DispatchEvent( |
1130 const char* event_name, base::Value* arg) { | 1506 const char* event_name, bool include_incognito, base::Value* arg) { |
1131 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1507 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1508 if (!extensions::ExtensionSystem::Get(profile_)->event_router()) |
| 1509 return; |
1132 scoped_ptr<base::ListValue> args(new base::ListValue()); | 1510 scoped_ptr<base::ListValue> args(new base::ListValue()); |
1133 args->Append(arg); | 1511 args->Append(arg); |
1134 std::string json_args; | 1512 std::string json_args; |
1135 base::JSONWriter::Write(args.get(), &json_args); | 1513 base::JSONWriter::Write(args.get(), &json_args); |
1136 // There is a one EDER for each on-record Profile, and a separate EDER for | 1514 scoped_ptr<extensions::Event> event(new extensions::Event( |
1137 // each off-record Profile, so there is exactly one EDER for each | 1515 event_name, args.Pass())); |
1138 // DownloadManager. EDER only watches its own DM, so all the items that an | 1516 // The downloads system wants to share on-record events with off-record |
1139 // EDER sees are either all on-record or all off-record. However, we want | 1517 // extension renderers even in incognito_split_mode because that's how |
1140 // extensions in off-record contexts to see on-record items. So, if this EDER | 1518 // chrome://downloads works. The "restrict_to_profile" mechanism does not |
1141 // is watching an on-record DM, and there is a corresponding off-record | 1519 // anticipate this, so it does not automatically prevent sharing off-record |
1142 // Profile, then dispatch this event to both the on-record Profile and the | 1520 // events with on-record extension renderers. |
1143 // off-record Profile. There may or may not be an off-record Profile, so send | 1521 event->restrict_to_profile = |
1144 // a *copy* of |args| to the off-record Profile, and Pass() |args| | 1522 (include_incognito && !profile_->IsOffTheRecord()) ? NULL : profile_; |
1145 // to the Profile that we know is there. | 1523 extensions::ExtensionSystem::Get(profile_)->event_router()-> |
1146 if (profile_->HasOffTheRecordProfile() && | 1524 BroadcastEvent(event.Pass()); |
1147 !profile_->IsOffTheRecord()) { | 1525 DownloadsNotificationSource notification_source; |
1148 DispatchEventInternal( | 1526 notification_source.event_name = event_name; |
1149 profile_->GetOffTheRecordProfile(), | 1527 notification_source.profile = profile_; |
1150 event_name, | 1528 content::Source<DownloadsNotificationSource> content_source( |
1151 json_args, | 1529 ¬ification_source); |
1152 scoped_ptr<base::ListValue>(args->DeepCopy())); | 1530 content::NotificationService::current()->Notify( |
1153 } | 1531 chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT, |
1154 DispatchEventInternal(profile_, event_name, json_args, args.Pass()); | 1532 content_source, |
| 1533 content::Details<std::string>(&json_args)); |
1155 } | 1534 } |
OLD | NEW |