Chromium Code Reviews| 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/download/download_extension_api.h" | 5 #include "chrome/browser/download/download_extension_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> |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 28 #include "chrome/browser/download/download_util.h" | 28 #include "chrome/browser/download/download_util.h" |
| 29 #include "chrome/browser/extensions/extension_event_names.h" | 29 #include "chrome/browser/extensions/extension_event_names.h" |
| 30 #include "chrome/browser/extensions/extension_event_router.h" | 30 #include "chrome/browser/extensions/extension_event_router.h" |
| 31 #include "chrome/browser/icon_loader.h" | 31 #include "chrome/browser/icon_loader.h" |
| 32 #include "chrome/browser/icon_manager.h" | 32 #include "chrome/browser/icon_manager.h" |
| 33 #include "chrome/browser/renderer_host/chrome_render_message_filter.h" | 33 #include "chrome/browser/renderer_host/chrome_render_message_filter.h" |
| 34 #include "chrome/browser/ui/browser_list.h" | 34 #include "chrome/browser/ui/browser_list.h" |
| 35 #include "chrome/browser/ui/webui/web_ui_util.h" | 35 #include "chrome/browser/ui/webui/web_ui_util.h" |
| 36 #include "content/browser/download/download_id.h" | 36 #include "content/browser/download/download_id.h" |
| 37 #include "content/browser/download/download_state_info.h" | 37 #include "content/browser/download/download_state_info.h" |
| 38 #include "content/browser/download/download_stats.h" | |
| 38 #include "content/browser/download/download_types.h" | 39 #include "content/browser/download/download_types.h" |
| 39 #include "content/browser/download/interrupt_reasons.h" | 40 #include "content/browser/download/interrupt_reasons.h" |
| 40 #include "content/browser/renderer_host/render_view_host.h" | 41 #include "content/browser/renderer_host/render_view_host.h" |
| 41 #include "content/browser/renderer_host/resource_dispatcher_host.h" | 42 #include "content/browser/renderer_host/resource_dispatcher_host.h" |
| 42 #include "content/public/browser/download_item.h" | 43 #include "content/public/browser/download_item.h" |
| 43 #include "content/public/browser/render_process_host.h" | 44 #include "content/public/browser/render_process_host.h" |
| 44 #include "net/http/http_util.h" | 45 #include "net/http/http_util.h" |
| 45 #include "net/url_request/url_request.h" | |
| 46 | 46 |
| 47 using content::BrowserThread; | 47 using content::BrowserThread; |
| 48 using content::DownloadItem; | 48 using content::DownloadItem; |
| 49 using content::DownloadManager; | 49 using content::DownloadManager; |
| 50 | 50 |
| 51 namespace download_extension_errors { | 51 namespace download_extension_errors { |
| 52 | 52 |
| 53 // Error messages | 53 // Error messages |
| 54 const char kGenericError[] = "I'm afraid I can't do that."; | 54 const char kGenericError[] = "I'm afraid I can't do that."; |
| 55 const char kIconNotFoundError[] = "Icon not found."; | 55 const char kIconNotFoundError[] = "Icon not found."; |
| (...skipping 602 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 658 (item->GetStartTime() - base::Time::UnixEpoch()).InMilliseconds()); | 658 (item->GetStartTime() - base::Time::UnixEpoch()).InMilliseconds()); |
| 659 json->SetInteger(kBytesReceivedKey, item->GetReceivedBytes()); | 659 json->SetInteger(kBytesReceivedKey, item->GetReceivedBytes()); |
| 660 json->SetInteger(kTotalBytesKey, item->GetTotalBytes()); | 660 json->SetInteger(kTotalBytesKey, item->GetTotalBytes()); |
| 661 if (item->GetState() == DownloadItem::INTERRUPTED) | 661 if (item->GetState() == DownloadItem::INTERRUPTED) |
| 662 json->SetInteger(kErrorKey, static_cast<int>(item->GetLastReason())); | 662 json->SetInteger(kErrorKey, static_cast<int>(item->GetLastReason())); |
| 663 // TODO(benjhayden): Implement endTime and fileSize. | 663 // TODO(benjhayden): Implement endTime and fileSize. |
| 664 // json->SetInteger(kEndTimeKey, -1); | 664 // json->SetInteger(kEndTimeKey, -1); |
| 665 json->SetInteger(kFileSizeKey, item->GetTotalBytes()); | 665 json->SetInteger(kFileSizeKey, item->GetTotalBytes()); |
| 666 return json; | 666 return json; |
| 667 } | 667 } |
| 668 | |
| 669 typedef std::set<int> DownloadIdSet; | |
| 670 | |
| 668 } // anonymous namespace | 671 } // anonymous namespace |
| 669 | 672 |
| 670 ExtensionDownloadsEventRouter::ExtensionDownloadsEventRouter(Profile* profile) | 673 ExtensionDownloadsEventRouter::ExtensionDownloadsEventRouter(Profile* profile) |
| 671 : profile_(profile), | 674 : profile_(profile), |
| 672 manager_(NULL) { | 675 manager_(NULL), |
| 676 delete_item_jsons_(&item_jsons_), | |
| 677 delete_on_changed_stats_(&on_changed_stats_) { | |
| 673 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 678 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 674 DCHECK(profile_); | 679 DCHECK(profile_); |
| 675 // Register a callback with the DownloadService for this profile to be called | 680 // Register a callback with the DownloadService for this profile to be called |
| 676 // when it creates the DownloadManager, or now if the manager already exists. | 681 // when it creates the DownloadManager, or now if the manager already exists. |
| 677 DownloadServiceFactory::GetForProfile(profile)->OnManagerCreated(base::Bind( | 682 DownloadServiceFactory::GetForProfile(profile)->OnManagerCreated(base::Bind( |
| 678 &ExtensionDownloadsEventRouter::Init, base::Unretained(this))); | 683 &ExtensionDownloadsEventRouter::Init, base::Unretained(this))); |
| 679 } | 684 } |
| 680 | 685 |
| 681 // The only public methods on this class are ModelChanged() and | 686 // The only public methods on this class are ModelChanged() and |
| 682 // ManagerGoingDown(), and they are only called by DownloadManager, so | 687 // ManagerGoingDown(), and they are only called by DownloadManager, so |
| 683 // there's no way for any methods on this class to be called before | 688 // there's no way for any methods on this class to be called before |
| 684 // DownloadService calls Init() via the OnManagerCreated Callback above. | 689 // DownloadService calls Init() via the OnManagerCreated Callback above. |
| 685 void ExtensionDownloadsEventRouter::Init(DownloadManager* manager) { | 690 void ExtensionDownloadsEventRouter::Init(DownloadManager* manager) { |
| 686 DCHECK(manager_ == NULL); | 691 DCHECK(manager_ == NULL); |
| 687 manager_ = manager; | 692 manager_ = manager; |
| 693 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 688 manager_->AddObserver(this); | 694 manager_->AddObserver(this); |
| 689 } | 695 } |
| 690 | 696 |
| 691 ExtensionDownloadsEventRouter::~ExtensionDownloadsEventRouter() { | 697 ExtensionDownloadsEventRouter::~ExtensionDownloadsEventRouter() { |
| 692 if (manager_ != NULL) | 698 if (manager_ != NULL) |
| 693 manager_->RemoveObserver(this); | 699 manager_->RemoveObserver(this); |
| 700 for (ItemMap::const_iterator iter = downloads_.begin(); | |
| 701 iter != downloads_.end(); ++iter) { | |
| 702 if (iter->second != NULL) | |
| 703 iter->second->RemoveObserver(this); | |
| 704 } | |
| 705 } | |
| 706 | |
| 707 ExtensionDownloadsEventRouter::OnChangedStat::OnChangedStat() | |
| 708 : fires(0), total(0) { | |
| 709 } | |
| 710 | |
| 711 ExtensionDownloadsEventRouter::OnChangedStat::~OnChangedStat() { | |
| 712 download_stats::RecordOnChanged(fires * 100 / total); | |
| 713 } | |
| 714 | |
| 715 void ExtensionDownloadsEventRouter::OnDownloadUpdated(DownloadItem* item) { | |
| 716 int download_id = item->GetId(); | |
| 717 if (item->GetState() == DownloadItem::REMOVING) { | |
| 718 // Remove item from downloads_, but keep the id in downloads_ so that we | |
| 719 // notice its absence in ModelChanged() and fire an onErased. | |
|
Randy Smith (Not in Mondays)
2012/01/15 18:47:13
Idea (i.e. the notch below "suggestion"; just some
benjhayden
2012/02/01 21:42:40
Done.
| |
| 720 ItemMap::const_iterator it = downloads_.find(download_id); | |
| 721 DCHECK(it != downloads_.end()); | |
| 722 DCHECK(it->second == item); | |
| 723 downloads_[download_id] = NULL; | |
| 724 item->RemoveObserver(this); | |
| 725 return; | |
| 726 } | |
| 727 base::DictionaryValue* current_json = item_jsons_[download_id]; | |
| 728 scoped_ptr<base::DictionaryValue> new_json(DownloadItemToJSON(item)); | |
| 729 scoped_ptr<base::DictionaryValue> delta(new base::DictionaryValue()); | |
| 730 delta->SetInteger(kIdKey, download_id); | |
| 731 bool changed = false; | |
| 732 for (base::DictionaryValue::key_iterator key = new_json->begin_keys(); | |
| 733 key != new_json->end_keys(); ++key) { | |
| 734 if (*key != kBytesReceivedKey) { | |
| 735 base::Value* new_value = NULL; | |
| 736 base::Value* old_value = NULL; | |
| 737 if (new_json->Get(*key, &new_value) && | |
|
Randy Smith (Not in Mondays)
2012/01/15 18:47:13
So this isn't performance critical code, but (:-})
benjhayden
2012/02/01 21:42:40
Done.
| |
| 738 (!current_json->HasKey(*key) || | |
| 739 (current_json->Get(*key, &old_value) && | |
| 740 !new_value->Equals(old_value)))) { | |
| 741 delta->Set(*key + ".old", (old_value ? old_value->DeepCopy() | |
| 742 : base::Value::CreateNullValue())); | |
| 743 delta->Set(*key + ".new", new_value->DeepCopy()); | |
| 744 changed = true; | |
| 745 } | |
| 746 } | |
| 747 } | |
| 748 ++(on_changed_stats_[download_id]->total); | |
| 749 if (changed) { | |
| 750 DispatchEvent(extension_event_names::kOnDownloadChanged, delta.release()); | |
| 751 ++(on_changed_stats_[download_id]->fires); | |
| 752 } | |
| 753 current_json->Swap(new_json.get()); | |
| 754 } | |
| 755 | |
| 756 void ExtensionDownloadsEventRouter::OnDownloadOpened(DownloadItem* item) { | |
| 694 } | 757 } |
| 695 | 758 |
| 696 void ExtensionDownloadsEventRouter::ModelChanged() { | 759 void ExtensionDownloadsEventRouter::ModelChanged() { |
| 697 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 760 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 698 if (manager_ == NULL) | 761 if (manager_ == NULL) |
| 699 return; | 762 return; |
| 700 DownloadManager::DownloadVector current_vec; | 763 DownloadManager::DownloadVector current_vec; |
| 701 manager_->SearchDownloads(string16(), ¤t_vec); | 764 manager_->SearchDownloads(string16(), ¤t_vec); |
| 702 DownloadIdSet current_set; | 765 DownloadIdSet current_set, prev_set; |
| 766 for (ItemMap::const_iterator iter = downloads_.begin(); | |
| 767 iter != downloads_.end(); ++iter) { | |
| 768 prev_set.insert(iter->first); | |
| 769 } | |
| 703 ItemMap current_map; | 770 ItemMap current_map; |
| 704 for (DownloadManager::DownloadVector::const_iterator iter = | 771 for (DownloadManager::DownloadVector::const_iterator iter = |
| 705 current_vec.begin(); | 772 current_vec.begin(); |
| 706 iter != current_vec.end(); ++iter) { | 773 iter != current_vec.end(); ++iter) { |
| 707 DownloadItem* item = *iter; | 774 DownloadItem* item = *iter; |
| 708 int item_id = item->GetId(); | 775 int item_id = item->GetId(); |
| 709 // TODO(benjhayden): Remove the following line when every item's id >= 0, | 776 // TODO(benjhayden): Remove the following line when every item's id >= 0, |
| 710 // which will allow firing onErased events for items from the history. | 777 // which will allow firing onErased events for items from the history. |
| 711 if (item_id < 0) continue; | 778 if (item_id < 0) continue; |
| 712 DCHECK(current_map.find(item_id) == current_map.end()); | 779 DCHECK(current_map.find(item_id) == current_map.end()); |
| 713 current_set.insert(item_id); | 780 current_set.insert(item_id); |
| 714 current_map[item_id] = item; | 781 current_map[item_id] = item; |
| 715 } | 782 } |
| 716 DownloadIdSet new_set; // current_set - downloads_; | 783 DownloadIdSet new_set; // current_set - prev_set; |
|
Randy Smith (Not in Mondays)
2012/01/15 18:47:13
semi-nit: I think this section would be clearer if
benjhayden
2012/02/01 21:42:40
erased_set isn't necessary now that the onErased i
| |
| 717 DownloadIdSet erased_set; // downloads_ - current_set; | 784 DownloadIdSet erased_set; // prev_set - current_set; |
| 718 std::insert_iterator<DownloadIdSet> new_insertor(new_set, new_set.begin()); | 785 std::insert_iterator<DownloadIdSet> new_insertor(new_set, new_set.begin()); |
| 719 std::insert_iterator<DownloadIdSet> erased_insertor( | 786 std::insert_iterator<DownloadIdSet> erased_insertor( |
| 720 erased_set, erased_set.begin()); | 787 erased_set, erased_set.begin()); |
| 721 std::set_difference(current_set.begin(), current_set.end(), | 788 std::set_difference(current_set.begin(), current_set.end(), |
| 722 downloads_.begin(), downloads_.end(), | 789 prev_set.begin(), prev_set.end(), |
| 723 new_insertor); | 790 new_insertor); |
| 724 std::set_difference(downloads_.begin(), downloads_.end(), | 791 std::set_difference(prev_set.begin(), prev_set.end(), |
| 725 current_set.begin(), current_set.end(), | 792 current_set.begin(), current_set.end(), |
| 726 erased_insertor); | 793 erased_insertor); |
| 727 for (DownloadIdSet::const_iterator iter = new_set.begin(); | 794 for (DownloadIdSet::const_iterator iter = new_set.begin(); |
| 728 iter != new_set.end(); ++iter) { | 795 iter != new_set.end(); ++iter) { |
| 729 DispatchEvent(extension_event_names::kOnDownloadCreated, | 796 DispatchEvent(extension_event_names::kOnDownloadCreated, |
| 730 DownloadItemToJSON(current_map[*iter])); | 797 DownloadItemToJSON(current_map[*iter])); |
| 798 DCHECK(item_jsons_.find(*iter) == item_jsons_.end()); | |
| 799 on_changed_stats_[*iter] = new OnChangedStat(); | |
| 800 item_jsons_[*iter] = DownloadItemToJSON(current_map[*iter]); | |
| 801 current_map[*iter]->AddObserver(this); | |
| 731 } | 802 } |
| 732 for (DownloadIdSet::const_iterator iter = erased_set.begin(); | 803 for (DownloadIdSet::const_iterator iter = erased_set.begin(); |
| 733 iter != erased_set.end(); ++iter) { | 804 iter != erased_set.end(); ++iter) { |
| 734 DispatchEvent(extension_event_names::kOnDownloadErased, | 805 DispatchEvent(extension_event_names::kOnDownloadErased, |
| 735 base::Value::CreateIntegerValue(*iter)); | 806 base::Value::CreateIntegerValue(*iter)); |
| 807 delete item_jsons_[*iter]; | |
| 808 item_jsons_.erase(*iter); | |
| 809 delete on_changed_stats_[*iter]; | |
| 810 on_changed_stats_.erase(*iter); | |
| 736 } | 811 } |
| 737 downloads_.swap(current_set); | 812 downloads_.swap(current_map); |
| 738 } | 813 } |
| 739 | 814 |
| 740 void ExtensionDownloadsEventRouter::ManagerGoingDown() { | 815 void ExtensionDownloadsEventRouter::ManagerGoingDown() { |
| 741 manager_->RemoveObserver(this); | 816 manager_->RemoveObserver(this); |
| 742 manager_ = NULL; | 817 manager_ = NULL; |
| 743 } | 818 } |
| 744 | 819 |
| 745 void ExtensionDownloadsEventRouter::DispatchEvent( | 820 void ExtensionDownloadsEventRouter::DispatchEvent( |
| 746 const char* event_name, base::Value* arg) { | 821 const char* event_name, base::Value* arg) { |
| 747 ListValue args; | 822 ListValue args; |
| 748 args.Append(arg); | 823 args.Append(arg); |
| 749 std::string json_args; | 824 std::string json_args; |
| 750 base::JSONWriter::Write(&args, false, &json_args); | 825 base::JSONWriter::Write(&args, false, &json_args); |
| 751 profile_->GetExtensionEventRouter()->DispatchEventToRenderers( | 826 profile_->GetExtensionEventRouter()->DispatchEventToRenderers( |
| 752 event_name, | 827 event_name, |
| 753 json_args, | 828 json_args, |
| 754 profile_, | 829 profile_, |
| 755 GURL()); | 830 GURL()); |
| 756 } | 831 } |
| OLD | NEW |