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

Unified Diff: chrome/browser/extensions/extension_downloads_api.cc

Issue 7825035: Implement chrome.experimental.downloads.search() (Closed) Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: merge Created 9 years, 2 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/extensions/extension_downloads_api.cc
diff --git a/chrome/browser/extensions/extension_downloads_api.cc b/chrome/browser/extensions/extension_downloads_api.cc
index 0e1470eb1c556a3fa32a6b071d38e7cda9143ced..800785656aba43137e08b92a7f9f64de234688a5 100644
--- a/chrome/browser/extensions/extension_downloads_api.cc
+++ b/chrome/browser/extensions/extension_downloads_api.cc
@@ -17,6 +17,7 @@
#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"
@@ -24,7 +25,6 @@
#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_downloads_api_constants.h"
#include "chrome/browser/extensions/extension_event_names.h"
#include "chrome/browser/extensions/extension_event_router.h"
#include "chrome/browser/icon_loader.h"
@@ -41,7 +41,185 @@
#include "net/http/http_util.h"
#include "net/url_request/url_request.h"
-namespace constants = extension_downloads_api_constants;
+namespace {
+
+using download_util::DownloadQuery;
+
+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
cbentzel 2011/10/20 18:18:53 Is this an intentional fall through here? It may g
+ 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) {
cbentzel 2011/10/20 18:18:53 This seems like a good use of template specializat
+ 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) {
@@ -224,20 +402,149 @@ void DownloadsDownloadFunction::RespondOnUIThread(int dl_id, net::Error error) {
}
DownloadsSearchFunction::DownloadsSearchFunction()
- : SyncDownloadsFunction(DOWNLOADS_FUNCTION_SEARCH) {
+ : SyncDownloadsFunction(DOWNLOADS_FUNCTION_SEARCH),
+ get_id_(0),
+ has_get_id_(false) {
}
DownloadsSearchFunction::~DownloadsSearchFunction() {}
+template <typename ValueType>
+bool DownloadsSearchFunction::Parse(
cbentzel 2011/10/20 18:18:53 I think this could be a non-member function if it
+ 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_.Set(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));
- error_ = constants::kNotImplemented;
- return false;
+ if (query_json->HasKey(constants::kDangerKey)) {
+ std::string danger;
+ EXTENSION_FUNCTION_VALIDATE(query_json->GetString(
+ constants::kDangerKey, &danger));
+ if (!query_.Set(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_.Set(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)) {
asanka 2011/10/20 19:29:16 The extensions API doc should be updated to mentio
+ 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);
+ DownloadQuery::OrderTerms order_terms;
+ for (std::vector<std::string>::const_iterator iter = order_by_strs.begin();
+ iter != order_by_strs.end(); ++iter) {
+ std::string term_str = *iter;
+ bool ascending = true;
+ if (term_str[0] == '-') {
+ ascending = false;
+ term_str = term_str.substr(1);
+ }
+ DownloadQuery::SortFieldName field_enum;
+ if (!DownloadSearchOrderByStringToEnum(term_str, &field_enum)) {
+ error_ = constants::kGenericError; // TODO
+ return false;
+ }
+ order_terms.push_back(DownloadQuery::OrderTerm(field_enum, ascending));
+ }
+ query_.OrderBy(order_terms);
+ }
+ 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() {
- NOTIMPLEMENTED();
+ 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()
@@ -385,35 +692,6 @@ void DownloadsDragFunction::RunInternal() {
NOTIMPLEMENTED();
}
-namespace {
-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()));
- 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());
- 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;
-}
-} // anonymous namespace
-
ExtensionDownloadsEventRouter::ExtensionDownloadsEventRouter(
Profile* profile)
: profile_(profile),

Powered by Google App Engine
This is Rietveld 408576698