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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "chrome/browser/download/downloads_extension_api.h"
6
7 #include <algorithm>
8 #include <cctype>
9 #include <iterator>
10 #include <set>
11 #include <string>
12
13 #include "base/bind.h"
14 #include "base/callback.h"
15 #include "base/json/json_writer.h"
16 #include "base/logging.h"
17 #include "base/metrics/histogram.h"
18 #include "base/stl_util.h"
19 #include "base/string16.h"
20 #include "base/string_split.h"
21 #include "base/string_util.h"
22 #include "base/stringprintf.h"
23 #include "base/values.h"
24 #include "chrome/browser/browser_process.h"
25 #include "chrome/browser/download/download_service.h"
26 #include "chrome/browser/download/download_service_factory.h"
27 #include "chrome/browser/download/download_util.h"
28 #include "chrome/browser/extensions/extension_event_names.h"
29 #include "chrome/browser/extensions/extension_event_router.h"
30 #include "chrome/browser/icon_loader.h"
31 #include "chrome/browser/icon_manager.h"
32 #include "chrome/browser/renderer_host/chrome_render_message_filter.h"
33 #include "chrome/browser/ui/browser_list.h"
34 #include "content/browser/download/download_file_manager.h"
35 #include "content/browser/download/download_item.h"
36 #include "content/browser/download/download_query.h"
37 #include "content/browser/download/download_types.h"
38 #include "content/browser/download/interrupt_reasons.h"
39 #include "content/browser/renderer_host/render_process_host.h"
40 #include "content/browser/renderer_host/render_view_host.h"
41 #include "content/browser/renderer_host/resource_dispatcher_host.h"
42 #include "net/http/http_util.h"
43 #include "net/url_request/url_request.h"
44
45 using content::BrowserThread;
46 using download_util::DownloadQuery;
47
48 namespace {
49
50 namespace constants {
51
52 // Error messages
53 const char kNotImplemented[] = "NotImplemented";
54 const char kGenericError[] = "I'm afraid I can't do that.";
55 const char kInvalidURL[] = "Invalid URL";
56
57 // Parameter keys
58 const char kBodyKey[] = "body";
59 const char kBytesReceivedKey[] = "bytesReceived";
60 const char kDangerAcceptedKey[] = "dangerAccepted";
61 const char kDangerFile[] = "file";
62 const char kDangerKey[] = "danger";
63 const char kDangerSafe[] = "safe";
64 const char kDangerUrl[] = "url";
65 const char kEndTimeKey[] = "endTime";
66 const char kEndedAfterKey[] = "endedAfter";
67 const char kEndedBeforeKey[] = "endedBefore";
68 const char kErrorKey[] = "error";
69 const char kFileSizeGreaterKey[] = "fileSizeGreater";
70 const char kFileSizeKey[] = "fileSize";
71 const char kFileSizeLessKey[] = "fileSizeLess";
72 const char kFilenameKey[] = "filename";
73 const char kFilenameRegexKey[] = "filenameRegex";
74 const char kHeaderNameKey[] = "name";
75 const char kHeaderValueKey[] = "value";
76 const char kHeadersKey[] = "headers";
77 const char kIdKey[] = "id";
78 const char kLimitKey[] = "limit";
79 const char kMethodKey[] = "method";
80 const char kMimeKey[] = "mime";
81 const char kOrderByKey[] = "orderBy";
82 const char kPausedKey[] = "paused";
83 const char kQueryKey[] = "query";
84 const char kSaveAsKey[] = "saveAs";
85 const char kStartTimeKey[] = "startTime";
86 const char kStartedAfterKey[] = "startedAfter";
87 const char kStartedBeforeKey[] = "startedBefore";
88 const char kStateComplete[] = "complete";
89 const char kStateInProgress[] = "in_progress";
90 const char kStateInterrupted[] = "interrupted";
91 const char kStateKey[] = "state";
92 const char kTotalBytesGreaterKey[] = "totalBytesGreater";
93 const char kTotalBytesKey[] = "totalBytes";
94 const char kTotalBytesLessKey[] = "totalBytesLess";
95 const char kUrlKey[] = "url";
96 const char kUrlRegexKey[] = "urlRegex";
97
98 const char* DangerString(DownloadItem::DangerType danger) {
99 switch (danger) {
100 case DownloadItem::NOT_DANGEROUS: return kDangerSafe;
101 case DownloadItem::DANGEROUS_FILE: return kDangerFile;
102 case DownloadItem::DANGEROUS_URL: return kDangerUrl;
103 default:
104 NOTREACHED();
105 return "";
106 }
107 }
108
109 const char* StateString(DownloadItem::DownloadState state) {
110 switch (state) {
111 case DownloadItem::IN_PROGRESS: return kStateInProgress;
112 case DownloadItem::COMPLETE: return kStateComplete;
113 case DownloadItem::INTERRUPTED: // fall through
114 case DownloadItem::CANCELLED: return kStateInterrupted;
115 case DownloadItem::REMOVING: // fall through
116 default:
117 NOTREACHED();
118 return "";
119 }
120 }
121
122 DownloadItem::DangerType DangerEnumFromString(const std::string& danger) {
123 if (danger == kDangerSafe) return DownloadItem::NOT_DANGEROUS;
124 if (danger == kDangerFile) return DownloadItem::DANGEROUS_FILE;
125 if (danger == kDangerUrl) return DownloadItem::DANGEROUS_URL;
126 return DownloadItem::DANGEROUS_TYPE_MAX;
127 }
128
129 DownloadItem::DownloadState StateEnumFromString(const std::string& state) {
130 if (state == kStateInProgress) return DownloadItem::IN_PROGRESS;
131 if (state == kStateComplete) return DownloadItem::COMPLETE;
132 if (state == kStateInterrupted) return DownloadItem::INTERRUPTED;
133 return DownloadItem::MAX_DOWNLOAD_STATE;
134 }
135
136 } // namespace constants
137
138 base::DictionaryValue* DownloadItemToJSON(DownloadItem* item) {
139 base::DictionaryValue* json = new base::DictionaryValue();
140 json->SetInteger(constants::kIdKey, item->id());
141 json->SetString(constants::kUrlKey, item->original_url().spec());
142 json->SetString(constants::kFilenameKey,
143 item->full_path().LossyDisplayName());
144 json->SetString(constants::kDangerKey,
145 constants::DangerString(item->GetDangerType()));
146 if (item->safety_state() != DownloadItem::SAFE)
147 json->SetBoolean(constants::kDangerAcceptedKey,
148 item->safety_state() == DownloadItem::DANGEROUS_BUT_VALIDATED);
149 json->SetString(constants::kStateKey,
150 constants::StateString(item->state()));
151 json->SetBoolean(constants::kPausedKey, item->is_paused());
152 json->SetString(constants::kMimeKey, item->mime_type());
153 // TODO(benjhayden): Change startTime to a double!
154 json->SetInteger(constants::kStartTimeKey,
155 (item->start_time() - base::Time::UnixEpoch()).InMilliseconds());
156 json->SetInteger(constants::kBytesReceivedKey, item->received_bytes());
157 json->SetInteger(constants::kTotalBytesKey, item->total_bytes());
158 if (item->state() == DownloadItem::INTERRUPTED)
159 json->SetInteger(constants::kErrorKey,
160 static_cast<int>(item->last_reason()));
161 // TODO(benjhayden): Implement endTime and fileSize.
162 // json->SetInteger(constants::kEndTimeKey, -1);
163 json->SetInteger(constants::kFileSizeKey, item->total_bytes());
164 return json;
165 }
166
167 template <typename T>
168 bool GetJsonValue(base::DictionaryValue* json, const char* name, T* value);
169
170 template<>
171 bool GetJsonValue(base::DictionaryValue* json, const char* name, int* value) {
172 return json->GetInteger(name, value);
173 }
174
175 template<>
176 bool GetJsonValue(base::DictionaryValue* json, const char* name,
177 string16* value) {
178 return json->GetString(name, value);
179 }
180
181 template<>
182 bool GetJsonValue(base::DictionaryValue* json, const char* name,
183 std::string* value) {
184 return json->GetString(name, value);
185 }
186
187 template<>
188 bool GetJsonValue(base::DictionaryValue* json, const char* name, bool* value) {
189 return json->GetBoolean(name, value);
190 }
191
192 struct SortFieldParsePair {
193 const char* json_name;
194 const DownloadQuery::SortFieldName field_name;
195 };
196
197 const SortFieldParsePair sort_field_parse_pairs[] = {
198 {constants::kBytesReceivedKey, DownloadQuery::SORT_FIELD_BYTES_RECEIVED},
199 {constants::kDangerKey, DownloadQuery::SORT_FIELD_DANGER},
200 {constants::kDangerAcceptedKey, DownloadQuery::SORT_FIELD_DANGER_ACCEPTED},
201 {constants::kEndTimeKey, DownloadQuery::SORT_FIELD_END_TIME},
202 {constants::kErrorKey, DownloadQuery::SORT_FIELD_ERROR},
203 {constants::kFilenameKey, DownloadQuery::SORT_FIELD_FILENAME},
204 {constants::kFileSizeKey, DownloadQuery::SORT_FIELD_FILE_SIZE},
205 {constants::kMimeKey, DownloadQuery::SORT_FIELD_MIME},
206 {constants::kPausedKey, DownloadQuery::SORT_FIELD_PAUSED},
207 {constants::kStartTimeKey, DownloadQuery::SORT_FIELD_START_TIME},
208 {constants::kStateKey, DownloadQuery::SORT_FIELD_STATE},
209 {constants::kTotalBytesKey, DownloadQuery::SORT_FIELD_TOTAL_BYTES},
210 {constants::kUrlKey, DownloadQuery::SORT_FIELD_URL},
211 };
212
213 bool DownloadSearchOrderByStringToEnum(
214 const std::string& json_name, DownloadQuery::SortFieldName* field_name) {
215 for (uint32 i = 0; i < arraysize(sort_field_parse_pairs); ++i) {
216 if (json_name == sort_field_parse_pairs[i].json_name) {
217 *field_name = sort_field_parse_pairs[i].field_name;
218 return true;
219 }
220 }
221 return false;
222 }
223
224 } // anonymous namespace
225
226 bool DownloadsFunctionInterface::RunImplImpl(
227 DownloadsFunctionInterface* pimpl) {
228 CHECK(pimpl);
229 if (!pimpl->ParseArgs()) return false;
230 UMA_HISTOGRAM_ENUMERATION(
231 "Download.ApiFunctions", pimpl->function(), DOWNLOADS_FUNCTION_LAST);
232 pimpl->RunInternal();
233 return true;
234 }
235
236 SyncDownloadsFunction::SyncDownloadsFunction(
237 DownloadsFunctionInterface::DownloadsFunctionName function)
238 : function_(function) {
239 }
240
241 SyncDownloadsFunction::~SyncDownloadsFunction() {}
242
243 bool SyncDownloadsFunction::RunImpl() {
244 return DownloadsFunctionInterface::RunImplImpl(this);
245 }
246
247 DownloadsFunctionInterface::DownloadsFunctionName
248 SyncDownloadsFunction::function() const {
249 return function_;
250 }
251
252 AsyncDownloadsFunction::AsyncDownloadsFunction(
253 DownloadsFunctionInterface::DownloadsFunctionName function)
254 : function_(function) {
255 }
256
257 AsyncDownloadsFunction::~AsyncDownloadsFunction() {}
258
259 bool AsyncDownloadsFunction::RunImpl() {
260 return DownloadsFunctionInterface::RunImplImpl(this);
261 }
262
263 DownloadsFunctionInterface::DownloadsFunctionName
264 AsyncDownloadsFunction::function() const {
265 return function_;
266 }
267
268 DownloadsDownloadFunction::DownloadsDownloadFunction()
269 : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_DOWNLOAD) {
270 }
271
272 DownloadsDownloadFunction::~DownloadsDownloadFunction() {}
273
274 DownloadsDownloadFunction::IOData::IOData()
275 : save_as(false),
276 extra_headers(NULL),
277 method("GET"),
278 rdh(NULL),
279 resource_context(NULL),
280 render_process_host_id(0),
281 render_view_host_routing_id(0) {
282 }
283
284 DownloadsDownloadFunction::IOData::~IOData() {}
285
286 bool DownloadsDownloadFunction::ParseArgs() {
287 base::DictionaryValue* options = NULL;
288 std::string url;
289 iodata_.reset(new IOData());
290 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options));
291 EXTENSION_FUNCTION_VALIDATE(options->GetString(constants::kUrlKey, &url));
292 iodata_->url = GURL(url);
293 if (!iodata_->url.is_valid()) {
294 error_ = constants::kInvalidURL;
295 return false;
296 }
297 if (options->HasKey(constants::kFilenameKey))
298 EXTENSION_FUNCTION_VALIDATE(options->GetString(
299 constants::kFilenameKey, &iodata_->filename));
300 // TODO(benjhayden): More robust validation of filename.
301 if (((iodata_->filename[0] == L'.') && (iodata_->filename[1] == L'.')) ||
302 (iodata_->filename[0] == L'/')) {
303 error_ = constants::kGenericError;
304 return false;
305 }
306 if (options->HasKey(constants::kSaveAsKey))
307 EXTENSION_FUNCTION_VALIDATE(options->GetBoolean(
308 constants::kSaveAsKey, &iodata_->save_as));
309 if (options->HasKey(constants::kMethodKey))
310 EXTENSION_FUNCTION_VALIDATE(options->GetString(
311 constants::kMethodKey, &iodata_->method));
312 // It's ok to use a pointer to extra_headers without DeepCopy()ing because
313 // |args_| (which owns *extra_headers) is guaranteed to live as long as
314 // |this|.
315 if (options->HasKey(constants::kHeadersKey))
316 EXTENSION_FUNCTION_VALIDATE(options->GetList(
317 constants::kHeadersKey, &iodata_->extra_headers));
318 if (options->HasKey(constants::kBodyKey))
319 EXTENSION_FUNCTION_VALIDATE(options->GetString(
320 constants::kBodyKey, &iodata_->post_body));
321 if (iodata_->extra_headers != NULL) {
322 for (size_t index = 0; index < iodata_->extra_headers->GetSize(); ++index) {
323 base::DictionaryValue* header = NULL;
324 std::string name, value;
325 EXTENSION_FUNCTION_VALIDATE(iodata_->extra_headers->GetDictionary(
326 index, &header));
327 EXTENSION_FUNCTION_VALIDATE(header->GetString(
328 constants::kHeaderNameKey, &name));
329 EXTENSION_FUNCTION_VALIDATE(header->GetString(
330 constants::kHeaderValueKey, &value));
331 if (!net::HttpUtil::IsSafeHeader(name)) {
332 error_ = constants::kGenericError;
333 return false;
334 }
335 }
336 }
337 iodata_->rdh = g_browser_process->resource_dispatcher_host();
338 iodata_->resource_context = &profile()->GetResourceContext();
339 iodata_->render_process_host_id = render_view_host()->process()->id();
340 iodata_->render_view_host_routing_id = render_view_host()->routing_id();
341 return true;
342 }
343
344 void DownloadsDownloadFunction::RunInternal() {
345 VLOG(1) << __FUNCTION__ << " " << iodata_->url.spec();
346 if (!BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind(
347 &DownloadsDownloadFunction::BeginDownloadOnIOThread, this))) {
348 error_ = constants::kGenericError;
349 SendResponse(error_.empty());
350 }
351 }
352
353 void DownloadsDownloadFunction::BeginDownloadOnIOThread() {
354 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
355 DVLOG(1) << __FUNCTION__ << " " << iodata_->url.spec();
356 DownloadSaveInfo save_info;
357 // TODO(benjhayden) Ensure that this filename is interpreted as a path
358 // relative to the default downloads directory without allowing '..'.
359 save_info.suggested_name = iodata_->filename;
360 net::URLRequest* request = new net::URLRequest(iodata_->url, iodata_->rdh);
361 request->set_method(iodata_->method);
362 if (iodata_->extra_headers != NULL) {
363 for (size_t index = 0; index < iodata_->extra_headers->GetSize(); ++index) {
364 base::DictionaryValue* header = NULL;
365 std::string name, value;
366 CHECK(iodata_->extra_headers->GetDictionary(index, &header));
367 CHECK(header->GetString("name", &name));
368 CHECK(header->GetString("value", &value));
369 request->SetExtraRequestHeaderByName(name, value, false/*overwrite*/);
370 }
371 }
372 if (!iodata_->post_body.empty()) {
373 request->AppendBytesToUpload(iodata_->post_body.data(),
374 iodata_->post_body.size());
375 }
376 iodata_->rdh->BeginDownload(
377 request,
378 save_info,
379 iodata_->save_as,
380 base::Bind(&DownloadsDownloadFunction::OnStarted, this),
381 iodata_->render_process_host_id,
382 iodata_->render_view_host_routing_id,
383 *(iodata_->resource_context));
384 iodata_.reset();
385 }
386
387 void DownloadsDownloadFunction::OnStarted(DownloadId dl_id, net::Error error) {
388 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
389 VLOG(1) << __FUNCTION__ << " " << dl_id << " " << error;
390 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, base::Bind(
391 &DownloadsDownloadFunction::RespondOnUIThread, this,
392 dl_id.local(), error));
393 }
394
395 void DownloadsDownloadFunction::RespondOnUIThread(int dl_id, net::Error error) {
396 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
397 VLOG(1) << __FUNCTION__;
398 if (dl_id >= 0) {
399 result_.reset(base::Value::CreateIntegerValue(dl_id));
400 } else {
401 error_ = net::ErrorToString(error);
402 }
403 SendResponse(error_.empty());
404 }
405
406 DownloadsSearchFunction::DownloadsSearchFunction()
407 : SyncDownloadsFunction(DOWNLOADS_FUNCTION_SEARCH),
408 get_id_(0),
409 has_get_id_(false) {
410 }
411
412 DownloadsSearchFunction::~DownloadsSearchFunction() {}
413
414 template <typename ValueType>
415 bool DownloadsSearchFunction::Parse(
416 base::DictionaryValue* json,
417 const char* json_name,
418 DownloadQuery::FilterFieldName filter_name) {
419 if (json->HasKey(json_name)) {
420 ValueType value;
421 EXTENSION_FUNCTION_VALIDATE(GetJsonValue(json, json_name, &value));
422 if (!query_.Filter(filter_name, value)) {
423 error_ = constants::kGenericError; // TODO(benjhayden)
424 return false;
425 }
426 }
427 return true;
428 }
429
430 bool DownloadsSearchFunction::ParseArgs() {
431 base::DictionaryValue* query_json = NULL;
432 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &query_json));
433 if (query_json->HasKey(constants::kDangerKey)) {
434 std::string danger;
435 EXTENSION_FUNCTION_VALIDATE(query_json->GetString(
436 constants::kDangerKey, &danger));
437 if (!query_.Filter(DownloadQuery::FILTER_FIELD_DANGER,
438 constants::DangerEnumFromString(danger))) {
439 error_ = constants::kGenericError; // TODO
440 return false;
441 }
442 }
443 if (query_json->HasKey(constants::kStateKey)) {
444 std::string state;
445 EXTENSION_FUNCTION_VALIDATE(query_json->GetString(
446 constants::kStateKey, &state));
447 if (!query_.Filter(DownloadQuery::FILTER_FIELD_STATE,
448 constants::StateEnumFromString(state))) {
449 error_ = constants::kGenericError; // TODO
450 return false;
451 }
452 }
453 if (query_json->HasKey(constants::kIdKey)) {
454 EXTENSION_FUNCTION_VALIDATE(query_json->GetInteger(
455 constants::kIdKey, &get_id_));
456 has_get_id_ = true;
457 }
458 if (query_json->HasKey(constants::kOrderByKey)) {
459 std::string order_by_str;
460 EXTENSION_FUNCTION_VALIDATE(query_json->GetString(
461 constants::kOrderByKey, &order_by_str));
462 std::vector<std::string> order_by_strs;
463 base::SplitString(order_by_str, ' ', &order_by_strs);
464 for (std::vector<std::string>::const_iterator iter = order_by_strs.begin();
465 iter != order_by_strs.end(); ++iter) {
466 std::string term_str = *iter;
467 DownloadQuery::SortFieldDirection direction = DownloadQuery::ASCENDING;
468 if (term_str[0] == '-') {
469 direction = DownloadQuery::DESCENDING;
470 term_str = term_str.substr(1);
471 }
472 DownloadQuery::SortFieldName field_enum;
473 if (!DownloadSearchOrderByStringToEnum(term_str, &field_enum)) {
474 error_ = constants::kGenericError; // TODO
475 return false;
476 }
477 query_.Sort(field_enum, direction);
478 }
479 }
480 if (query_json->HasKey(constants::kLimitKey)) {
481 int limit = 0;
482 EXTENSION_FUNCTION_VALIDATE(query_json->GetInteger(
483 constants::kLimitKey, &limit));
484 query_.Limit(limit);
485 }
486 return Parse<int>(query_json, constants::kStartTimeKey,
487 DownloadQuery::FILTER_FIELD_START_TIME) &&
488 Parse<int>(query_json, constants::kEndTimeKey,
489 DownloadQuery::FILTER_FIELD_END_TIME) &&
490 Parse<int>(query_json, constants::kStartedBeforeKey,
491 DownloadQuery::FILTER_FIELD_STARTED_BEFORE) &&
492 Parse<int>(query_json, constants::kStartedAfterKey,
493 DownloadQuery::FILTER_FIELD_STARTED_AFTER) &&
494 Parse<int>(query_json, constants::kEndedBeforeKey,
495 DownloadQuery::FILTER_FIELD_ENDED_BEFORE) &&
496 Parse<int>(query_json, constants::kEndedAfterKey,
497 DownloadQuery::FILTER_FIELD_ENDED_AFTER) &&
498 Parse<int>(query_json, constants::kBytesReceivedKey,
499 DownloadQuery::FILTER_FIELD_BYTES_RECEIVED) &&
500 Parse<int>(query_json, constants::kTotalBytesKey,
501 DownloadQuery::FILTER_FIELD_TOTAL_BYTES) &&
502 Parse<int>(query_json, constants::kTotalBytesGreaterKey,
503 DownloadQuery::FILTER_FIELD_TOTAL_BYTES_GREATER) &&
504 Parse<int>(query_json, constants::kTotalBytesLessKey,
505 DownloadQuery::FILTER_FIELD_TOTAL_BYTES_LESS) &&
506 Parse<int>(query_json, constants::kFileSizeKey,
507 DownloadQuery::FILTER_FIELD_FILE_SIZE) &&
508 Parse<int>(query_json, constants::kFileSizeGreaterKey,
509 DownloadQuery::FILTER_FIELD_FILE_SIZE_GREATER) &&
510 Parse<int>(query_json, constants::kFileSizeLessKey,
511 DownloadQuery::FILTER_FIELD_FILE_SIZE_LESS) &&
512 Parse<int>(query_json, constants::kErrorKey,
513 DownloadQuery::FILTER_FIELD_ERROR) &&
514 Parse<bool>(query_json, constants::kDangerAcceptedKey,
515 DownloadQuery::FILTER_FIELD_DANGER_ACCEPTED) &&
516 Parse<bool>(query_json, constants::kPausedKey,
517 DownloadQuery::FILTER_FIELD_PAUSED) &&
518 Parse<string16>(query_json, constants::kFilenameKey,
519 DownloadQuery::FILTER_FIELD_FILENAME) &&
520 Parse<std::string>(query_json, constants::kMimeKey,
521 DownloadQuery::FILTER_FIELD_MIME) &&
522 Parse<std::string>(query_json, constants::kQueryKey,
523 DownloadQuery::FILTER_FIELD_QUERY) &&
524 Parse<std::string>(query_json, constants::kFilenameRegexKey,
525 DownloadQuery::FILTER_FIELD_FILENAME_REGEX) &&
526 Parse<std::string>(query_json, constants::kUrlRegexKey,
527 DownloadQuery::FILTER_FIELD_URL_REGEX) &&
528 Parse<std::string>(query_json, constants::kUrlKey,
529 DownloadQuery::FILTER_FIELD_URL);
530 }
531
532 void DownloadsSearchFunction::RunInternal() {
533 DownloadManager::DownloadVector cpp_results;
534 if (has_get_id_) {
535 DownloadItem* item = profile()->GetDownloadManager()->GetDownloadItem(
536 get_id_);
537 if (item && query_.Matches(*item))
538 cpp_results.push_back(item);
539 } else {
540 profile()->GetDownloadManager()->Search(query_, &cpp_results);
541 }
542 base::ListValue* json_results = new base::ListValue();
543 for (DownloadManager::DownloadVector::const_iterator it = cpp_results.begin();
544 it != cpp_results.end(); ++it) {
545 json_results->Append(DownloadItemToJSON(*it));
546 }
547 result_.reset(json_results);
548 }
549
550 DownloadsPauseFunction::DownloadsPauseFunction()
551 : SyncDownloadsFunction(DOWNLOADS_FUNCTION_PAUSE) {
552 }
553
554 DownloadsPauseFunction::~DownloadsPauseFunction() {}
555
556 bool DownloadsPauseFunction::ParseArgs() {
557 int dl_id = 0;
558 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
559 VLOG(1) << __FUNCTION__ << " " << dl_id;
560 error_ = constants::kNotImplemented;
561 return false;
562 }
563
564 void DownloadsPauseFunction::RunInternal() {
565 NOTIMPLEMENTED();
566 }
567
568 DownloadsResumeFunction::DownloadsResumeFunction()
569 : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_RESUME) {
570 }
571
572 DownloadsResumeFunction::~DownloadsResumeFunction() {}
573
574 bool DownloadsResumeFunction::ParseArgs() {
575 int dl_id = 0;
576 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
577 VLOG(1) << __FUNCTION__ << " " << dl_id;
578 error_ = constants::kNotImplemented;
579 return false;
580 }
581
582 void DownloadsResumeFunction::RunInternal() {
583 NOTIMPLEMENTED();
584 }
585
586 DownloadsCancelFunction::DownloadsCancelFunction()
587 : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_CANCEL) {
588 }
589
590 DownloadsCancelFunction::~DownloadsCancelFunction() {}
591
592 bool DownloadsCancelFunction::ParseArgs() {
593 int dl_id = 0;
594 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
595 VLOG(1) << __FUNCTION__ << " " << dl_id;
596 error_ = constants::kNotImplemented;
597 return false;
598 }
599
600 void DownloadsCancelFunction::RunInternal() {
601 NOTIMPLEMENTED();
602 }
603
604 DownloadsEraseFunction::DownloadsEraseFunction()
605 : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_ERASE) {
606 }
607
608 DownloadsEraseFunction::~DownloadsEraseFunction() {}
609
610 bool DownloadsEraseFunction::ParseArgs() {
611 base::DictionaryValue* query_json = NULL;
612 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &query_json));
613 error_ = constants::kNotImplemented;
614 return false;
615 }
616
617 void DownloadsEraseFunction::RunInternal() {
618 NOTIMPLEMENTED();
619 }
620
621 DownloadsSetDestinationFunction::DownloadsSetDestinationFunction()
622 : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_SET_DESTINATION) {
623 }
624
625 DownloadsSetDestinationFunction::~DownloadsSetDestinationFunction() {}
626
627 bool DownloadsSetDestinationFunction::ParseArgs() {
628 int dl_id = 0;
629 std::string path;
630 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
631 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &path));
632 VLOG(1) << __FUNCTION__ << " " << dl_id << " " << &path;
633 error_ = constants::kNotImplemented;
634 return false;
635 }
636
637 void DownloadsSetDestinationFunction::RunInternal() {
638 NOTIMPLEMENTED();
639 }
640
641 DownloadsAcceptDangerFunction::DownloadsAcceptDangerFunction()
642 : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_ACCEPT_DANGER) {
643 }
644
645 DownloadsAcceptDangerFunction::~DownloadsAcceptDangerFunction() {}
646
647 bool DownloadsAcceptDangerFunction::ParseArgs() {
648 int dl_id = 0;
649 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
650 VLOG(1) << __FUNCTION__ << " " << dl_id;
651 error_ = constants::kNotImplemented;
652 return false;
653 }
654
655 void DownloadsAcceptDangerFunction::RunInternal() {
656 NOTIMPLEMENTED();
657 }
658
659 DownloadsShowFunction::DownloadsShowFunction()
660 : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_SHOW) {
661 }
662
663 DownloadsShowFunction::~DownloadsShowFunction() {}
664
665 bool DownloadsShowFunction::ParseArgs() {
666 int dl_id = 0;
667 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
668 VLOG(1) << __FUNCTION__ << " " << dl_id;
669 error_ = constants::kNotImplemented;
670 return false;
671 }
672
673 void DownloadsShowFunction::RunInternal() {
674 NOTIMPLEMENTED();
675 }
676
677 DownloadsDragFunction::DownloadsDragFunction()
678 : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_DRAG) {
679 }
680
681 DownloadsDragFunction::~DownloadsDragFunction() {}
682
683 bool DownloadsDragFunction::ParseArgs() {
684 int dl_id = 0;
685 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id));
686 VLOG(1) << __FUNCTION__ << " " << dl_id;
687 error_ = constants::kNotImplemented;
688 return false;
689 }
690
691 void DownloadsDragFunction::RunInternal() {
692 NOTIMPLEMENTED();
693 }
694
695 ExtensionDownloadsEventRouter::ExtensionDownloadsEventRouter(
696 Profile* profile)
697 : profile_(profile),
698 manager_(
699 profile ?
700 DownloadServiceFactory::GetForProfile(profile)->GetDownloadManager() :
701 NULL) {
702 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
703 DCHECK(profile_);
704 DCHECK(manager_);
705 manager_->AddObserver(this);
706 }
707
708 ExtensionDownloadsEventRouter::~ExtensionDownloadsEventRouter() {
709 if (manager_ != NULL)
710 manager_->RemoveObserver(this);
711 }
712
713 void ExtensionDownloadsEventRouter::ModelChanged() {
714 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
715 if (manager_ == NULL)
716 return;
717 DownloadManager::DownloadVector current_vec;
718 manager_->SearchDownloads(string16(), &current_vec);
719 DownloadIdSet current_set;
720 ItemMap current_map;
721 for (DownloadManager::DownloadVector::const_iterator iter =
722 current_vec.begin();
723 iter != current_vec.end(); ++iter) {
724 DownloadItem* item = *iter;
725 int item_id = item->id();
726 // TODO(benjhayden): Remove the following line when every item's id >= 0,
727 // which will allow firing onErased events for items from the history.
728 if (item_id < 0) continue;
729 DCHECK(current_map.find(item_id) == current_map.end());
730 current_set.insert(item_id);
731 current_map[item_id] = item;
732 }
733 DownloadIdSet new_set; // current_set - downloads_;
734 DownloadIdSet erased_set; // downloads_ - current_set;
735 std::insert_iterator<DownloadIdSet> new_insertor(new_set, new_set.begin());
736 std::insert_iterator<DownloadIdSet> erased_insertor(
737 erased_set, erased_set.begin());
738 std::set_difference(current_set.begin(), current_set.end(),
739 downloads_.begin(), downloads_.end(),
740 new_insertor);
741 std::set_difference(downloads_.begin(), downloads_.end(),
742 current_set.begin(), current_set.end(),
743 erased_insertor);
744 for (DownloadIdSet::const_iterator iter = new_set.begin();
745 iter != new_set.end(); ++iter) {
746 DispatchEvent(extension_event_names::kOnDownloadCreated,
747 DownloadItemToJSON(current_map[*iter]));
748 }
749 for (DownloadIdSet::const_iterator iter = erased_set.begin();
750 iter != erased_set.end(); ++iter) {
751 DispatchEvent(extension_event_names::kOnDownloadErased,
752 base::Value::CreateIntegerValue(*iter));
753 }
754 downloads_.swap(current_set);
755 }
756
757 void ExtensionDownloadsEventRouter::ManagerGoingDown() {
758 manager_->RemoveObserver(this);
759 manager_ = NULL;
760 }
761
762 void ExtensionDownloadsEventRouter::DispatchEvent(
763 const char* event_name, base::Value* arg) {
764 ListValue args;
765 args.Append(arg);
766 std::string json_args;
767 base::JSONWriter::Write(&args, false, &json_args);
768 profile_->GetExtensionEventRouter()->DispatchEventToRenderers(
769 event_name,
770 json_args,
771 profile_,
772 GURL());
773 }
OLDNEW
« 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