| 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(), ¤t_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());
|
| +}
|
|
|