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

Unified Diff: chrome/browser/download/download_extension_api.cc

Issue 8203005: Implement chrome.experimental.downloads.onChanged (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: " Created 8 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 side-by-side diff with in-line comments
Download patch
Index: chrome/browser/download/download_extension_api.cc
diff --git a/chrome/browser/download/download_extension_api.cc b/chrome/browser/download/download_extension_api.cc
index 34055e06e2b5302cb7332feaaa0f3eb02c0f94d3..35748ff6af8e849c1fcdd36fdd2db7436c35d915 100644
--- a/chrome/browser/download/download_extension_api.cc
+++ b/chrome/browser/download/download_extension_api.cc
@@ -35,6 +35,7 @@
#include "chrome/browser/ui/webui/web_ui_util.h"
#include "content/browser/download/download_id.h"
#include "content/browser/download/download_state_info.h"
+#include "content/browser/download/download_stats.h"
#include "content/browser/download/download_types.h"
#include "content/browser/download/interrupt_reasons.h"
#include "content/browser/renderer_host/render_view_host.h"
@@ -42,7 +43,6 @@
#include "content/public/browser/download_item.h"
#include "content/public/browser/render_process_host.h"
#include "net/http/http_util.h"
-#include "net/url_request/url_request.h"
using content::BrowserThread;
using content::DownloadItem;
@@ -665,11 +665,16 @@ base::DictionaryValue* DownloadItemToJSON(DownloadItem* item) {
json->SetInteger(kFileSizeKey, item->GetTotalBytes());
return json;
}
+
+typedef std::set<int> DownloadIdSet;
+
} // anonymous namespace
ExtensionDownloadsEventRouter::ExtensionDownloadsEventRouter(Profile* profile)
: profile_(profile),
- manager_(NULL) {
+ manager_(NULL),
+ delete_item_jsons_(&item_jsons_),
+ delete_on_changed_stats_(&on_changed_stats_) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
DCHECK(profile_);
// Register a callback with the DownloadService for this profile to be called
@@ -685,12 +690,70 @@ ExtensionDownloadsEventRouter::ExtensionDownloadsEventRouter(Profile* profile)
void ExtensionDownloadsEventRouter::Init(DownloadManager* manager) {
DCHECK(manager_ == NULL);
manager_ = manager;
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
manager_->AddObserver(this);
}
ExtensionDownloadsEventRouter::~ExtensionDownloadsEventRouter() {
if (manager_ != NULL)
manager_->RemoveObserver(this);
+ for (ItemMap::const_iterator iter = downloads_.begin();
+ iter != downloads_.end(); ++iter) {
+ if (iter->second != NULL)
+ iter->second->RemoveObserver(this);
+ }
+}
+
+ExtensionDownloadsEventRouter::OnChangedStat::OnChangedStat()
+ : fires(0), total(0) {
+}
+
+ExtensionDownloadsEventRouter::OnChangedStat::~OnChangedStat() {
+ download_stats::RecordOnChanged(fires * 100 / total);
+}
+
+void ExtensionDownloadsEventRouter::OnDownloadUpdated(DownloadItem* item) {
+ int download_id = item->GetId();
+ if (item->GetState() == DownloadItem::REMOVING) {
+ // Remove item from downloads_, but keep the id in downloads_ so that we
+ // 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.
+ ItemMap::const_iterator it = downloads_.find(download_id);
+ DCHECK(it != downloads_.end());
+ DCHECK(it->second == item);
+ downloads_[download_id] = NULL;
+ item->RemoveObserver(this);
+ return;
+ }
+ base::DictionaryValue* current_json = item_jsons_[download_id];
+ scoped_ptr<base::DictionaryValue> new_json(DownloadItemToJSON(item));
+ scoped_ptr<base::DictionaryValue> delta(new base::DictionaryValue());
+ delta->SetInteger(kIdKey, download_id);
+ bool changed = false;
+ for (base::DictionaryValue::key_iterator key = new_json->begin_keys();
+ key != new_json->end_keys(); ++key) {
+ if (*key != kBytesReceivedKey) {
+ base::Value* new_value = NULL;
+ base::Value* old_value = NULL;
+ 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.
+ (!current_json->HasKey(*key) ||
+ (current_json->Get(*key, &old_value) &&
+ !new_value->Equals(old_value)))) {
+ delta->Set(*key + ".old", (old_value ? old_value->DeepCopy()
+ : base::Value::CreateNullValue()));
+ delta->Set(*key + ".new", new_value->DeepCopy());
+ changed = true;
+ }
+ }
+ }
+ ++(on_changed_stats_[download_id]->total);
+ if (changed) {
+ DispatchEvent(extension_event_names::kOnDownloadChanged, delta.release());
+ ++(on_changed_stats_[download_id]->fires);
+ }
+ current_json->Swap(new_json.get());
+}
+
+void ExtensionDownloadsEventRouter::OnDownloadOpened(DownloadItem* item) {
}
void ExtensionDownloadsEventRouter::ModelChanged() {
@@ -699,7 +762,11 @@ void ExtensionDownloadsEventRouter::ModelChanged() {
return;
DownloadManager::DownloadVector current_vec;
manager_->SearchDownloads(string16(), &current_vec);
- DownloadIdSet current_set;
+ DownloadIdSet current_set, prev_set;
+ for (ItemMap::const_iterator iter = downloads_.begin();
+ iter != downloads_.end(); ++iter) {
+ prev_set.insert(iter->first);
+ }
ItemMap current_map;
for (DownloadManager::DownloadVector::const_iterator iter =
current_vec.begin();
@@ -713,28 +780,36 @@ void ExtensionDownloadsEventRouter::ModelChanged() {
current_set.insert(item_id);
current_map[item_id] = item;
}
- DownloadIdSet new_set; // current_set - downloads_;
- DownloadIdSet erased_set; // downloads_ - current_set;
+ 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
+ DownloadIdSet erased_set; // prev_set - current_set;
std::insert_iterator<DownloadIdSet> new_insertor(new_set, new_set.begin());
std::insert_iterator<DownloadIdSet> erased_insertor(
erased_set, erased_set.begin());
std::set_difference(current_set.begin(), current_set.end(),
- downloads_.begin(), downloads_.end(),
+ prev_set.begin(), prev_set.end(),
new_insertor);
- std::set_difference(downloads_.begin(), downloads_.end(),
+ std::set_difference(prev_set.begin(), prev_set.end(),
current_set.begin(), current_set.end(),
erased_insertor);
for (DownloadIdSet::const_iterator iter = new_set.begin();
iter != new_set.end(); ++iter) {
DispatchEvent(extension_event_names::kOnDownloadCreated,
DownloadItemToJSON(current_map[*iter]));
+ DCHECK(item_jsons_.find(*iter) == item_jsons_.end());
+ on_changed_stats_[*iter] = new OnChangedStat();
+ item_jsons_[*iter] = DownloadItemToJSON(current_map[*iter]);
+ current_map[*iter]->AddObserver(this);
}
for (DownloadIdSet::const_iterator iter = erased_set.begin();
iter != erased_set.end(); ++iter) {
DispatchEvent(extension_event_names::kOnDownloadErased,
base::Value::CreateIntegerValue(*iter));
+ delete item_jsons_[*iter];
+ item_jsons_.erase(*iter);
+ delete on_changed_stats_[*iter];
+ on_changed_stats_.erase(*iter);
}
- downloads_.swap(current_set);
+ downloads_.swap(current_map);
}
void ExtensionDownloadsEventRouter::ManagerGoingDown() {

Powered by Google App Engine
This is Rietveld 408576698