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

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

Issue 7825035: Implement chrome.experimental.downloads.search() (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: rewrite Created 9 years, 1 month 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/downloads_extension_api.cc
diff --git a/chrome/browser/download/downloads_extension_api.cc b/chrome/browser/download/downloads_extension_api.cc
new file mode 100644
index 0000000000000000000000000000000000000000..63279418a982d480f10382b244dafdbc1edce5b0
--- /dev/null
+++ b/chrome/browser/download/downloads_extension_api.cc
@@ -0,0 +1,773 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/download/downloads_extension_api.h"
+
+#include <algorithm>
+#include <cctype>
+#include <iterator>
+#include <set>
+#include <string>
+
+#include "base/bind.h"
+#include "base/callback.h"
+#include "base/json/json_writer.h"
+#include "base/logging.h"
+#include "base/metrics/histogram.h"
+#include "base/stl_util.h"
+#include "base/string16.h"
+#include "base/string_split.h"
+#include "base/string_util.h"
+#include "base/stringprintf.h"
+#include "base/values.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/download/download_service.h"
+#include "chrome/browser/download/download_service_factory.h"
+#include "chrome/browser/download/download_util.h"
+#include "chrome/browser/extensions/extension_event_names.h"
+#include "chrome/browser/extensions/extension_event_router.h"
+#include "chrome/browser/icon_loader.h"
+#include "chrome/browser/icon_manager.h"
+#include "chrome/browser/renderer_host/chrome_render_message_filter.h"
+#include "chrome/browser/ui/browser_list.h"
+#include "content/browser/download/download_file_manager.h"
+#include "content/browser/download/download_item.h"
+#include "content/browser/download/download_query.h"
+#include "content/browser/download/download_types.h"
+#include "content/browser/download/interrupt_reasons.h"
+#include "content/browser/renderer_host/render_process_host.h"
+#include "content/browser/renderer_host/render_view_host.h"
+#include "content/browser/renderer_host/resource_dispatcher_host.h"
+#include "net/http/http_util.h"
+#include "net/url_request/url_request.h"
+
+using content::BrowserThread;
+using download_util::DownloadQuery;
+
+namespace {
+
+namespace constants {
+
+// Error messages
+const char kNotImplemented[] = "NotImplemented";
+const char kGenericError[] = "I'm afraid I can't do that.";
+const char kInvalidURL[] = "Invalid URL";
+
+// Parameter keys
+const char kBodyKey[] = "body";
+const char kBytesReceivedKey[] = "bytesReceived";
+const char kDangerAcceptedKey[] = "dangerAccepted";
+const char kDangerFile[] = "file";
+const char kDangerKey[] = "danger";
+const char kDangerSafe[] = "safe";
+const char kDangerUrl[] = "url";
+const char kEndTimeKey[] = "endTime";
+const char kEndedAfterKey[] = "endedAfter";
+const char kEndedBeforeKey[] = "endedBefore";
+const char kErrorKey[] = "error";
+const char kFileSizeGreaterKey[] = "fileSizeGreater";
+const char kFileSizeKey[] = "fileSize";
+const char kFileSizeLessKey[] = "fileSizeLess";
+const char kFilenameKey[] = "filename";
+const char kFilenameRegexKey[] = "filenameRegex";
+const char kHeaderNameKey[] = "name";
+const char kHeaderValueKey[] = "value";
+const char kHeadersKey[] = "headers";
+const char kIdKey[] = "id";
+const char kLimitKey[] = "limit";
+const char kMethodKey[] = "method";
+const char kMimeKey[] = "mime";
+const char kOrderByKey[] = "orderBy";
+const char kPausedKey[] = "paused";
+const char kQueryKey[] = "query";
+const char kSaveAsKey[] = "saveAs";
+const char kStartTimeKey[] = "startTime";
+const char kStartedAfterKey[] = "startedAfter";
+const char kStartedBeforeKey[] = "startedBefore";
+const char kStateComplete[] = "complete";
+const char kStateInProgress[] = "in_progress";
+const char kStateInterrupted[] = "interrupted";
+const char kStateKey[] = "state";
+const char kTotalBytesGreaterKey[] = "totalBytesGreater";
+const char kTotalBytesKey[] = "totalBytes";
+const char kTotalBytesLessKey[] = "totalBytesLess";
+const char kUrlKey[] = "url";
+const char kUrlRegexKey[] = "urlRegex";
+
+const char* DangerString(DownloadItem::DangerType danger) {
+ switch (danger) {
+ case DownloadItem::NOT_DANGEROUS: return kDangerSafe;
+ case DownloadItem::DANGEROUS_FILE: return kDangerFile;
+ case DownloadItem::DANGEROUS_URL: return kDangerUrl;
+ default:
+ NOTREACHED();
+ return "";
+ }
+}
+
+const char* StateString(DownloadItem::DownloadState state) {
+ switch (state) {
+ case DownloadItem::IN_PROGRESS: return kStateInProgress;
+ case DownloadItem::COMPLETE: return kStateComplete;
+ case DownloadItem::INTERRUPTED: // fall through
+ case DownloadItem::CANCELLED: return kStateInterrupted;
+ case DownloadItem::REMOVING: // fall through
+ default:
+ NOTREACHED();
+ return "";
+ }
+}
+
+DownloadItem::DangerType DangerEnumFromString(const std::string& danger) {
+ if (danger == kDangerSafe) return DownloadItem::NOT_DANGEROUS;
+ if (danger == kDangerFile) return DownloadItem::DANGEROUS_FILE;
+ if (danger == kDangerUrl) return DownloadItem::DANGEROUS_URL;
+ return DownloadItem::DANGEROUS_TYPE_MAX;
+}
+
+DownloadItem::DownloadState StateEnumFromString(const std::string& state) {
+ if (state == kStateInProgress) return DownloadItem::IN_PROGRESS;
+ if (state == kStateComplete) return DownloadItem::COMPLETE;
+ if (state == kStateInterrupted) return DownloadItem::INTERRUPTED;
+ return DownloadItem::MAX_DOWNLOAD_STATE;
+}
+
+} // namespace constants
+
+base::DictionaryValue* DownloadItemToJSON(DownloadItem* item) {
+ base::DictionaryValue* json = new base::DictionaryValue();
+ json->SetInteger(constants::kIdKey, item->id());
+ json->SetString(constants::kUrlKey, item->original_url().spec());
+ json->SetString(constants::kFilenameKey,
+ item->full_path().LossyDisplayName());
+ json->SetString(constants::kDangerKey,
+ constants::DangerString(item->GetDangerType()));
+ if (item->safety_state() != DownloadItem::SAFE)
+ json->SetBoolean(constants::kDangerAcceptedKey,
+ item->safety_state() == DownloadItem::DANGEROUS_BUT_VALIDATED);
+ json->SetString(constants::kStateKey,
+ constants::StateString(item->state()));
+ json->SetBoolean(constants::kPausedKey, item->is_paused());
+ json->SetString(constants::kMimeKey, item->mime_type());
+ // TODO(benjhayden): Change startTime to a double!
+ json->SetInteger(constants::kStartTimeKey,
+ (item->start_time() - base::Time::UnixEpoch()).InMilliseconds());
+ json->SetInteger(constants::kBytesReceivedKey, item->received_bytes());
+ json->SetInteger(constants::kTotalBytesKey, item->total_bytes());
+ if (item->state() == DownloadItem::INTERRUPTED)
+ json->SetInteger(constants::kErrorKey,
+ static_cast<int>(item->last_reason()));
+ // TODO(benjhayden): Implement endTime and fileSize.
+ // json->SetInteger(constants::kEndTimeKey, -1);
+ json->SetInteger(constants::kFileSizeKey, item->total_bytes());
+ return json;
+}
+
+template <typename T>
+bool GetJsonValue(base::DictionaryValue* json, const char* name, T* value);
+
+template<>
+bool GetJsonValue(base::DictionaryValue* json, const char* name, int* value) {
+ return json->GetInteger(name, value);
+}
+
+template<>
+bool GetJsonValue(base::DictionaryValue* json, const char* name,
+ string16* value) {
+ return json->GetString(name, value);
+}
+
+template<>
+bool GetJsonValue(base::DictionaryValue* json, const char* name,
+ std::string* value) {
+ return json->GetString(name, value);
+}
+
+template<>
+bool GetJsonValue(base::DictionaryValue* json, const char* name, bool* value) {
+ return json->GetBoolean(name, value);
+}
+
+struct SortFieldParsePair {
+ const char* json_name;
+ const DownloadQuery::SortFieldName field_name;
+};
+
+const SortFieldParsePair sort_field_parse_pairs[] = {
+ {constants::kBytesReceivedKey, DownloadQuery::SORT_FIELD_BYTES_RECEIVED},
+ {constants::kDangerKey, DownloadQuery::SORT_FIELD_DANGER},
+ {constants::kDangerAcceptedKey, DownloadQuery::SORT_FIELD_DANGER_ACCEPTED},
+ {constants::kEndTimeKey, DownloadQuery::SORT_FIELD_END_TIME},
+ {constants::kErrorKey, DownloadQuery::SORT_FIELD_ERROR},
+ {constants::kFilenameKey, DownloadQuery::SORT_FIELD_FILENAME},
+ {constants::kFileSizeKey, DownloadQuery::SORT_FIELD_FILE_SIZE},
+ {constants::kMimeKey, DownloadQuery::SORT_FIELD_MIME},
+ {constants::kPausedKey, DownloadQuery::SORT_FIELD_PAUSED},
+ {constants::kStartTimeKey, DownloadQuery::SORT_FIELD_START_TIME},
+ {constants::kStateKey, DownloadQuery::SORT_FIELD_STATE},
+ {constants::kTotalBytesKey, DownloadQuery::SORT_FIELD_TOTAL_BYTES},
+ {constants::kUrlKey, DownloadQuery::SORT_FIELD_URL},
+};
+
+bool DownloadSearchOrderByStringToEnum(
+ const std::string& json_name, DownloadQuery::SortFieldName* field_name) {
+ for (uint32 i = 0; i < arraysize(sort_field_parse_pairs); ++i) {
+ if (json_name == sort_field_parse_pairs[i].json_name) {
+ *field_name = sort_field_parse_pairs[i].field_name;
+ return true;
+ }
+ }
+ return false;
+}
+
+} // anonymous namespace
+
+bool DownloadsFunctionInterface::RunImplImpl(
+ DownloadsFunctionInterface* pimpl) {
+ CHECK(pimpl);
+ if (!pimpl->ParseArgs()) return false;
+ UMA_HISTOGRAM_ENUMERATION(
+ "Download.ApiFunctions", pimpl->function(), DOWNLOADS_FUNCTION_LAST);
+ pimpl->RunInternal();
+ return true;
+}
+
+SyncDownloadsFunction::SyncDownloadsFunction(
+ DownloadsFunctionInterface::DownloadsFunctionName function)
+ : function_(function) {
+}
+
+SyncDownloadsFunction::~SyncDownloadsFunction() {}
+
+bool SyncDownloadsFunction::RunImpl() {
+ return DownloadsFunctionInterface::RunImplImpl(this);
+}
+
+DownloadsFunctionInterface::DownloadsFunctionName
+SyncDownloadsFunction::function() const {
+ return function_;
+}
+
+AsyncDownloadsFunction::AsyncDownloadsFunction(
+ DownloadsFunctionInterface::DownloadsFunctionName function)
+ : function_(function) {
+}
+
+AsyncDownloadsFunction::~AsyncDownloadsFunction() {}
+
+bool AsyncDownloadsFunction::RunImpl() {
+ return DownloadsFunctionInterface::RunImplImpl(this);
+}
+
+DownloadsFunctionInterface::DownloadsFunctionName
+AsyncDownloadsFunction::function() const {
+ return function_;
+}
+
+DownloadsDownloadFunction::DownloadsDownloadFunction()
+ : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_DOWNLOAD) {
+}
+
+DownloadsDownloadFunction::~DownloadsDownloadFunction() {}
+
+DownloadsDownloadFunction::IOData::IOData()
+ : save_as(false),
+ extra_headers(NULL),
+ method("GET"),
+ rdh(NULL),
+ resource_context(NULL),
+ render_process_host_id(0),
+ render_view_host_routing_id(0) {
+}
+
+DownloadsDownloadFunction::IOData::~IOData() {}
+
+bool DownloadsDownloadFunction::ParseArgs() {
+ base::DictionaryValue* options = NULL;
+ std::string url;
+ iodata_.reset(new IOData());
+ EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options));
+ EXTENSION_FUNCTION_VALIDATE(options->GetString(constants::kUrlKey, &url));
+ iodata_->url = GURL(url);
+ if (!iodata_->url.is_valid()) {
+ error_ = constants::kInvalidURL;
+ return false;
+ }
+ if (options->HasKey(constants::kFilenameKey))
+ EXTENSION_FUNCTION_VALIDATE(options->GetString(
+ constants::kFilenameKey, &iodata_->filename));
+ // TODO(benjhayden): More robust validation of filename.
+ if (((iodata_->filename[0] == L'.') && (iodata_->filename[1] == L'.')) ||
+ (iodata_->filename[0] == L'/')) {
+ error_ = constants::kGenericError;
+ return false;
+ }
+ if (options->HasKey(constants::kSaveAsKey))
+ EXTENSION_FUNCTION_VALIDATE(options->GetBoolean(
+ constants::kSaveAsKey, &iodata_->save_as));
+ if (options->HasKey(constants::kMethodKey))
+ EXTENSION_FUNCTION_VALIDATE(options->GetString(
+ constants::kMethodKey, &iodata_->method));
+ // It's ok to use a pointer to extra_headers without DeepCopy()ing because
+ // |args_| (which owns *extra_headers) is guaranteed to live as long as
+ // |this|.
+ if (options->HasKey(constants::kHeadersKey))
+ EXTENSION_FUNCTION_VALIDATE(options->GetList(
+ constants::kHeadersKey, &iodata_->extra_headers));
+ if (options->HasKey(constants::kBodyKey))
+ EXTENSION_FUNCTION_VALIDATE(options->GetString(
+ constants::kBodyKey, &iodata_->post_body));
+ if (iodata_->extra_headers != NULL) {
+ for (size_t index = 0; index < iodata_->extra_headers->GetSize(); ++index) {
+ base::DictionaryValue* header = NULL;
+ std::string name, value;
+ EXTENSION_FUNCTION_VALIDATE(iodata_->extra_headers->GetDictionary(
+ index, &header));
+ EXTENSION_FUNCTION_VALIDATE(header->GetString(
+ constants::kHeaderNameKey, &name));
+ EXTENSION_FUNCTION_VALIDATE(header->GetString(
+ constants::kHeaderValueKey, &value));
+ if (!net::HttpUtil::IsSafeHeader(name)) {
+ error_ = constants::kGenericError;
+ return false;
+ }
+ }
+ }
+ iodata_->rdh = g_browser_process->resource_dispatcher_host();
+ iodata_->resource_context = &profile()->GetResourceContext();
+ iodata_->render_process_host_id = render_view_host()->process()->id();
+ iodata_->render_view_host_routing_id = render_view_host()->routing_id();
+ return true;
+}
+
+void DownloadsDownloadFunction::RunInternal() {
+ VLOG(1) << __FUNCTION__ << " " << iodata_->url.spec();
+ if (!BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
+ &DownloadsDownloadFunction::BeginDownloadOnIOThread, this))) {
+ error_ = constants::kGenericError;
+ SendResponse(error_.empty());
+ }
+}
+
+void DownloadsDownloadFunction::BeginDownloadOnIOThread() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ DVLOG(1) << __FUNCTION__ << " " << iodata_->url.spec();
+ DownloadSaveInfo save_info;
+ // TODO(benjhayden) Ensure that this filename is interpreted as a path
+ // relative to the default downloads directory without allowing '..'.
+ save_info.suggested_name = iodata_->filename;
+ net::URLRequest* request = new net::URLRequest(iodata_->url, iodata_->rdh);
+ request->set_method(iodata_->method);
+ if (iodata_->extra_headers != NULL) {
+ for (size_t index = 0; index < iodata_->extra_headers->GetSize(); ++index) {
+ base::DictionaryValue* header = NULL;
+ std::string name, value;
+ CHECK(iodata_->extra_headers->GetDictionary(index, &header));
+ CHECK(header->GetString("name", &name));
+ CHECK(header->GetString("value", &value));
+ request->SetExtraRequestHeaderByName(name, value, false/*overwrite*/);
+ }
+ }
+ if (!iodata_->post_body.empty()) {
+ request->AppendBytesToUpload(iodata_->post_body.data(),
+ iodata_->post_body.size());
+ }
+ iodata_->rdh->BeginDownload(
+ request,
+ save_info,
+ iodata_->save_as,
+ base::Bind(&DownloadsDownloadFunction::OnStarted, this),
+ iodata_->render_process_host_id,
+ iodata_->render_view_host_routing_id,
+ *(iodata_->resource_context));
+ iodata_.reset();
+}
+
+void DownloadsDownloadFunction::OnStarted(DownloadId dl_id, net::Error error) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
+ VLOG(1) << __FUNCTION__ << " " << dl_id << " " << error;
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
+ &DownloadsDownloadFunction::RespondOnUIThread, this,
+ dl_id.local(), error));
+}
+
+void DownloadsDownloadFunction::RespondOnUIThread(int dl_id, net::Error error) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ VLOG(1) << __FUNCTION__;
+ if (dl_id >= 0) {
+ result_.reset(base::Value::CreateIntegerValue(dl_id));
+ } else {
+ error_ = net::ErrorToString(error);
+ }
+ SendResponse(error_.empty());
+}
+
+DownloadsSearchFunction::DownloadsSearchFunction()
+ : SyncDownloadsFunction(DOWNLOADS_FUNCTION_SEARCH),
+ get_id_(0),
+ has_get_id_(false) {
+}
+
+DownloadsSearchFunction::~DownloadsSearchFunction() {}
+
+template <typename ValueType>
+bool DownloadsSearchFunction::Parse(
+ base::DictionaryValue* json,
+ const char* json_name,
+ DownloadQuery::FilterFieldName filter_name) {
+ if (json->HasKey(json_name)) {
+ ValueType value;
+ EXTENSION_FUNCTION_VALIDATE(GetJsonValue(json, json_name, &value));
+ if (!query_.Filter(filter_name, value)) {
+ error_ = constants::kGenericError; // TODO(benjhayden)
+ return false;
+ }
+ }
+ return true;
+}
+
+bool DownloadsSearchFunction::ParseArgs() {
+ base::DictionaryValue* query_json = NULL;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &query_json));
+ if (query_json->HasKey(constants::kDangerKey)) {
+ std::string danger;
+ EXTENSION_FUNCTION_VALIDATE(query_json->GetString(
+ constants::kDangerKey, &danger));
+ if (!query_.Filter(DownloadQuery::FILTER_FIELD_DANGER,
+ constants::DangerEnumFromString(danger))) {
+ error_ = constants::kGenericError; // TODO
+ return false;
+ }
+ }
+ if (query_json->HasKey(constants::kStateKey)) {
+ std::string state;
+ EXTENSION_FUNCTION_VALIDATE(query_json->GetString(
+ constants::kStateKey, &state));
+ if (!query_.Filter(DownloadQuery::FILTER_FIELD_STATE,
+ constants::StateEnumFromString(state))) {
+ error_ = constants::kGenericError; // TODO
+ return false;
+ }
+ }
+ if (query_json->HasKey(constants::kIdKey)) {
+ EXTENSION_FUNCTION_VALIDATE(query_json->GetInteger(
+ constants::kIdKey, &get_id_));
+ has_get_id_ = true;
+ }
+ if (query_json->HasKey(constants::kOrderByKey)) {
+ std::string order_by_str;
+ EXTENSION_FUNCTION_VALIDATE(query_json->GetString(
+ constants::kOrderByKey, &order_by_str));
+ std::vector<std::string> order_by_strs;
+ base::SplitString(order_by_str, ' ', &order_by_strs);
+ for (std::vector<std::string>::const_iterator iter = order_by_strs.begin();
+ iter != order_by_strs.end(); ++iter) {
+ std::string term_str = *iter;
+ DownloadQuery::SortFieldDirection direction = DownloadQuery::ASCENDING;
+ if (term_str[0] == '-') {
+ direction = DownloadQuery::DESCENDING;
+ term_str = term_str.substr(1);
+ }
+ DownloadQuery::SortFieldName field_enum;
+ if (!DownloadSearchOrderByStringToEnum(term_str, &field_enum)) {
+ error_ = constants::kGenericError; // TODO
+ return false;
+ }
+ query_.Sort(field_enum, direction);
+ }
+ }
+ if (query_json->HasKey(constants::kLimitKey)) {
+ int limit = 0;
+ EXTENSION_FUNCTION_VALIDATE(query_json->GetInteger(
+ constants::kLimitKey, &limit));
+ query_.Limit(limit);
+ }
+ return Parse<int>(query_json, constants::kStartTimeKey,
+ DownloadQuery::FILTER_FIELD_START_TIME) &&
+ Parse<int>(query_json, constants::kEndTimeKey,
+ DownloadQuery::FILTER_FIELD_END_TIME) &&
+ Parse<int>(query_json, constants::kStartedBeforeKey,
+ DownloadQuery::FILTER_FIELD_STARTED_BEFORE) &&
+ Parse<int>(query_json, constants::kStartedAfterKey,
+ DownloadQuery::FILTER_FIELD_STARTED_AFTER) &&
+ Parse<int>(query_json, constants::kEndedBeforeKey,
+ DownloadQuery::FILTER_FIELD_ENDED_BEFORE) &&
+ Parse<int>(query_json, constants::kEndedAfterKey,
+ DownloadQuery::FILTER_FIELD_ENDED_AFTER) &&
+ Parse<int>(query_json, constants::kBytesReceivedKey,
+ DownloadQuery::FILTER_FIELD_BYTES_RECEIVED) &&
+ Parse<int>(query_json, constants::kTotalBytesKey,
+ DownloadQuery::FILTER_FIELD_TOTAL_BYTES) &&
+ Parse<int>(query_json, constants::kTotalBytesGreaterKey,
+ DownloadQuery::FILTER_FIELD_TOTAL_BYTES_GREATER) &&
+ Parse<int>(query_json, constants::kTotalBytesLessKey,
+ DownloadQuery::FILTER_FIELD_TOTAL_BYTES_LESS) &&
+ Parse<int>(query_json, constants::kFileSizeKey,
+ DownloadQuery::FILTER_FIELD_FILE_SIZE) &&
+ Parse<int>(query_json, constants::kFileSizeGreaterKey,
+ DownloadQuery::FILTER_FIELD_FILE_SIZE_GREATER) &&
+ Parse<int>(query_json, constants::kFileSizeLessKey,
+ DownloadQuery::FILTER_FIELD_FILE_SIZE_LESS) &&
+ Parse<int>(query_json, constants::kErrorKey,
+ DownloadQuery::FILTER_FIELD_ERROR) &&
+ Parse<bool>(query_json, constants::kDangerAcceptedKey,
+ DownloadQuery::FILTER_FIELD_DANGER_ACCEPTED) &&
+ Parse<bool>(query_json, constants::kPausedKey,
+ DownloadQuery::FILTER_FIELD_PAUSED) &&
+ Parse<string16>(query_json, constants::kFilenameKey,
+ DownloadQuery::FILTER_FIELD_FILENAME) &&
+ Parse<std::string>(query_json, constants::kMimeKey,
+ DownloadQuery::FILTER_FIELD_MIME) &&
+ Parse<std::string>(query_json, constants::kQueryKey,
+ DownloadQuery::FILTER_FIELD_QUERY) &&
+ Parse<std::string>(query_json, constants::kFilenameRegexKey,
+ DownloadQuery::FILTER_FIELD_FILENAME_REGEX) &&
+ Parse<std::string>(query_json, constants::kUrlRegexKey,
+ DownloadQuery::FILTER_FIELD_URL_REGEX) &&
+ Parse<std::string>(query_json, constants::kUrlKey,
+ DownloadQuery::FILTER_FIELD_URL);
+}
+
+void DownloadsSearchFunction::RunInternal() {
+ DownloadManager::DownloadVector cpp_results;
+ if (has_get_id_) {
+ DownloadItem* item = profile()->GetDownloadManager()->GetDownloadItem(
+ get_id_);
+ if (item && query_.Matches(*item))
+ cpp_results.push_back(item);
+ } else {
+ profile()->GetDownloadManager()->Search(query_, &cpp_results);
+ }
+ base::ListValue* json_results = new base::ListValue();
+ for (DownloadManager::DownloadVector::const_iterator it = cpp_results.begin();
+ it != cpp_results.end(); ++it) {
+ json_results->Append(DownloadItemToJSON(*it));
+ }
+ result_.reset(json_results);
+}
+
+DownloadsPauseFunction::DownloadsPauseFunction()
+ : SyncDownloadsFunction(DOWNLOADS_FUNCTION_PAUSE) {
+}
+
+DownloadsPauseFunction::~DownloadsPauseFunction() {}
+
+bool DownloadsPauseFunction::ParseArgs() {
+ int dl_id = 0;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
+ VLOG(1) << __FUNCTION__ << " " << dl_id;
+ error_ = constants::kNotImplemented;
+ return false;
+}
+
+void DownloadsPauseFunction::RunInternal() {
+ NOTIMPLEMENTED();
+}
+
+DownloadsResumeFunction::DownloadsResumeFunction()
+ : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_RESUME) {
+}
+
+DownloadsResumeFunction::~DownloadsResumeFunction() {}
+
+bool DownloadsResumeFunction::ParseArgs() {
+ int dl_id = 0;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
+ VLOG(1) << __FUNCTION__ << " " << dl_id;
+ error_ = constants::kNotImplemented;
+ return false;
+}
+
+void DownloadsResumeFunction::RunInternal() {
+ NOTIMPLEMENTED();
+}
+
+DownloadsCancelFunction::DownloadsCancelFunction()
+ : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_CANCEL) {
+}
+
+DownloadsCancelFunction::~DownloadsCancelFunction() {}
+
+bool DownloadsCancelFunction::ParseArgs() {
+ int dl_id = 0;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
+ VLOG(1) << __FUNCTION__ << " " << dl_id;
+ error_ = constants::kNotImplemented;
+ return false;
+}
+
+void DownloadsCancelFunction::RunInternal() {
+ NOTIMPLEMENTED();
+}
+
+DownloadsEraseFunction::DownloadsEraseFunction()
+ : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_ERASE) {
+}
+
+DownloadsEraseFunction::~DownloadsEraseFunction() {}
+
+bool DownloadsEraseFunction::ParseArgs() {
+ base::DictionaryValue* query_json = NULL;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &query_json));
+ error_ = constants::kNotImplemented;
+ return false;
+}
+
+void DownloadsEraseFunction::RunInternal() {
+ NOTIMPLEMENTED();
+}
+
+DownloadsSetDestinationFunction::DownloadsSetDestinationFunction()
+ : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_SET_DESTINATION) {
+}
+
+DownloadsSetDestinationFunction::~DownloadsSetDestinationFunction() {}
+
+bool DownloadsSetDestinationFunction::ParseArgs() {
+ int dl_id = 0;
+ std::string path;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
+ EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &path));
+ VLOG(1) << __FUNCTION__ << " " << dl_id << " " << &path;
+ error_ = constants::kNotImplemented;
+ return false;
+}
+
+void DownloadsSetDestinationFunction::RunInternal() {
+ NOTIMPLEMENTED();
+}
+
+DownloadsAcceptDangerFunction::DownloadsAcceptDangerFunction()
+ : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_ACCEPT_DANGER) {
+}
+
+DownloadsAcceptDangerFunction::~DownloadsAcceptDangerFunction() {}
+
+bool DownloadsAcceptDangerFunction::ParseArgs() {
+ int dl_id = 0;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
+ VLOG(1) << __FUNCTION__ << " " << dl_id;
+ error_ = constants::kNotImplemented;
+ return false;
+}
+
+void DownloadsAcceptDangerFunction::RunInternal() {
+ NOTIMPLEMENTED();
+}
+
+DownloadsShowFunction::DownloadsShowFunction()
+ : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_SHOW) {
+}
+
+DownloadsShowFunction::~DownloadsShowFunction() {}
+
+bool DownloadsShowFunction::ParseArgs() {
+ int dl_id = 0;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
+ VLOG(1) << __FUNCTION__ << " " << dl_id;
+ error_ = constants::kNotImplemented;
+ return false;
+}
+
+void DownloadsShowFunction::RunInternal() {
+ NOTIMPLEMENTED();
+}
+
+DownloadsDragFunction::DownloadsDragFunction()
+ : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_DRAG) {
+}
+
+DownloadsDragFunction::~DownloadsDragFunction() {}
+
+bool DownloadsDragFunction::ParseArgs() {
+ int dl_id = 0;
+ EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
+ VLOG(1) << __FUNCTION__ << " " << dl_id;
+ error_ = constants::kNotImplemented;
+ return false;
+}
+
+void DownloadsDragFunction::RunInternal() {
+ NOTIMPLEMENTED();
+}
+
+ExtensionDownloadsEventRouter::ExtensionDownloadsEventRouter(
+ Profile* profile)
+ : profile_(profile),
+ manager_(
+ profile ?
+ DownloadServiceFactory::GetForProfile(profile)->GetDownloadManager() :
+ NULL) {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ DCHECK(profile_);
+ DCHECK(manager_);
+ manager_->AddObserver(this);
+}
+
+ExtensionDownloadsEventRouter::~ExtensionDownloadsEventRouter() {
+ if (manager_ != NULL)
+ manager_->RemoveObserver(this);
+}
+
+void ExtensionDownloadsEventRouter::ModelChanged() {
+ DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
+ if (manager_ == NULL)
+ return;
+ DownloadManager::DownloadVector current_vec;
+ manager_->SearchDownloads(string16(), &current_vec);
+ DownloadIdSet current_set;
+ ItemMap current_map;
+ for (DownloadManager::DownloadVector::const_iterator iter =
+ current_vec.begin();
+ iter != current_vec.end(); ++iter) {
+ DownloadItem* item = *iter;
+ int item_id = item->id();
+ // TODO(benjhayden): Remove the following line when every item's id >= 0,
+ // which will allow firing onErased events for items from the history.
+ if (item_id < 0) continue;
+ DCHECK(current_map.find(item_id) == current_map.end());
+ current_set.insert(item_id);
+ current_map[item_id] = item;
+ }
+ DownloadIdSet new_set; // current_set - downloads_;
+ DownloadIdSet erased_set; // downloads_ - 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(),
+ new_insertor);
+ std::set_difference(downloads_.begin(), downloads_.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]));
+ }
+ for (DownloadIdSet::const_iterator iter = erased_set.begin();
+ iter != erased_set.end(); ++iter) {
+ DispatchEvent(extension_event_names::kOnDownloadErased,
+ base::Value::CreateIntegerValue(*iter));
+ }
+ downloads_.swap(current_set);
+}
+
+void ExtensionDownloadsEventRouter::ManagerGoingDown() {
+ manager_->RemoveObserver(this);
+ manager_ = NULL;
+}
+
+void ExtensionDownloadsEventRouter::DispatchEvent(
+ const char* event_name, base::Value* arg) {
+ ListValue args;
+ args.Append(arg);
+ std::string json_args;
+ base::JSONWriter::Write(&args, false, &json_args);
+ profile_->GetExtensionEventRouter()->DispatchEventToRenderers(
+ event_name,
+ json_args,
+ profile_,
+ GURL());
+}
« no previous file with comments | « chrome/browser/download/downloads_extension_api.h ('k') | chrome/browser/download/downloads_extension_apitest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698