OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/download/download_extension_api.h" | 5 #include "chrome/browser/extensions/api/downloads/downloads_api.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <cctype> | 8 #include <cctype> |
9 #include <iterator> | 9 #include <iterator> |
10 #include <set> | 10 #include <set> |
11 #include <string> | 11 #include <string> |
12 | 12 |
13 #include "base/basictypes.h" | 13 #include "base/basictypes.h" |
14 #include "base/bind.h" | 14 #include "base/bind.h" |
15 #include "base/bind_helpers.h" | 15 #include "base/bind_helpers.h" |
(...skipping 12 matching lines...) Expand all Loading... |
28 #include "chrome/browser/download/download_file_icon_extractor.h" | 28 #include "chrome/browser/download/download_file_icon_extractor.h" |
29 #include "chrome/browser/download/download_query.h" | 29 #include "chrome/browser/download/download_query.h" |
30 #include "chrome/browser/download/download_service.h" | 30 #include "chrome/browser/download/download_service.h" |
31 #include "chrome/browser/download/download_service_factory.h" | 31 #include "chrome/browser/download/download_service_factory.h" |
32 #include "chrome/browser/download/download_util.h" | 32 #include "chrome/browser/download/download_util.h" |
33 #include "chrome/browser/extensions/extension_event_names.h" | 33 #include "chrome/browser/extensions/extension_event_names.h" |
34 #include "chrome/browser/extensions/extension_event_router.h" | 34 #include "chrome/browser/extensions/extension_event_router.h" |
35 #include "chrome/browser/icon_loader.h" | 35 #include "chrome/browser/icon_loader.h" |
36 #include "chrome/browser/icon_manager.h" | 36 #include "chrome/browser/icon_manager.h" |
37 #include "chrome/browser/renderer_host/chrome_render_message_filter.h" | 37 #include "chrome/browser/renderer_host/chrome_render_message_filter.h" |
38 #include "chrome/browser/ui/browser_list.h" | 38 #include "chrome/browser/ui/browser.h" |
39 #include "chrome/browser/ui/webui/web_ui_util.h" | 39 #include "chrome/browser/ui/webui/web_ui_util.h" |
| 40 #include "chrome/common/extensions/api/downloads.h" |
40 #include "content/public/browser/download_interrupt_reasons.h" | 41 #include "content/public/browser/download_interrupt_reasons.h" |
41 #include "content/public/browser/download_item.h" | 42 #include "content/public/browser/download_item.h" |
42 #include "content/public/browser/download_save_info.h" | 43 #include "content/public/browser/download_save_info.h" |
| 44 #include "content/public/browser/download_url_parameters.h" |
43 #include "content/public/browser/render_process_host.h" | 45 #include "content/public/browser/render_process_host.h" |
44 #include "content/public/browser/render_view_host.h" | 46 #include "content/public/browser/render_view_host.h" |
45 #include "content/public/browser/resource_dispatcher_host.h" | 47 #include "content/public/browser/resource_dispatcher_host.h" |
46 #include "net/base/load_flags.h" | 48 #include "net/base/load_flags.h" |
47 #include "net/http/http_util.h" | 49 #include "net/http/http_util.h" |
48 #include "net/url_request/url_request.h" | 50 #include "net/url_request/url_request.h" |
49 | 51 |
50 using content::BrowserThread; | 52 using content::BrowserThread; |
51 using content::DownloadId; | 53 using content::DownloadId; |
52 using content::DownloadItem; | 54 using content::DownloadItem; |
53 using content::DownloadManager; | 55 using content::DownloadManager; |
| 56 using extensions::api::downloads::HeaderNameValuePair; |
54 | 57 |
55 namespace download_extension_errors { | 58 namespace download_extension_errors { |
56 | 59 |
57 // Error messages | 60 // Error messages |
58 const char kGenericError[] = "I'm afraid I can't do that."; | 61 const char kGenericError[] = "I'm afraid I can't do that."; |
59 const char kIconNotFoundError[] = "Icon not found."; | 62 const char kIconNotFoundError[] = "Icon not found."; |
60 const char kInvalidDangerTypeError[] = "Invalid danger type"; | 63 const char kInvalidDangerTypeError[] = "Invalid danger type"; |
61 const char kInvalidFilterError[] = "Invalid query filter"; | 64 const char kInvalidFilterError[] = "Invalid query filter"; |
62 const char kInvalidOperationError[] = "Invalid operation."; | 65 const char kInvalidOperationError[] = "Invalid operation."; |
63 const char kInvalidOrderByError[] = "Invalid orderBy field"; | 66 const char kInvalidOrderByError[] = "Invalid orderBy field"; |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 const char kStateInProgress[] = "in_progress"; | 112 const char kStateInProgress[] = "in_progress"; |
110 const char kStateInterrupted[] = "interrupted"; | 113 const char kStateInterrupted[] = "interrupted"; |
111 const char kStateKey[] = "state"; | 114 const char kStateKey[] = "state"; |
112 const char kTotalBytesKey[] = "totalBytes"; | 115 const char kTotalBytesKey[] = "totalBytes"; |
113 const char kTotalBytesGreaterKey[] = "totalBytesGreater"; | 116 const char kTotalBytesGreaterKey[] = "totalBytesGreater"; |
114 const char kTotalBytesLessKey[] = "totalBytesLess"; | 117 const char kTotalBytesLessKey[] = "totalBytesLess"; |
115 const char kUrlKey[] = "url"; | 118 const char kUrlKey[] = "url"; |
116 const char kUrlRegexKey[] = "urlRegex"; | 119 const char kUrlRegexKey[] = "urlRegex"; |
117 | 120 |
118 // Note: Any change to the danger type strings, should be accompanied by a | 121 // Note: Any change to the danger type strings, should be accompanied by a |
119 // corresponding change to {experimental.}downloads.json. | 122 // corresponding change to downloads.idl. |
120 const char* kDangerStrings[] = { | 123 const char* kDangerStrings[] = { |
121 kDangerSafe, | 124 kDangerSafe, |
122 kDangerFile, | 125 kDangerFile, |
123 kDangerUrl, | 126 kDangerUrl, |
124 kDangerContent, | 127 kDangerContent, |
125 kDangerSafe, | 128 kDangerSafe, |
126 kDangerUncommon, | 129 kDangerUncommon, |
127 }; | 130 }; |
128 COMPILE_ASSERT(arraysize(kDangerStrings) == content::DOWNLOAD_DANGER_TYPE_MAX, | 131 COMPILE_ASSERT(arraysize(kDangerStrings) == content::DOWNLOAD_DANGER_TYPE_MAX, |
129 download_danger_type_enum_changed); | 132 download_danger_type_enum_changed); |
130 | 133 |
131 // Note: Any change to the state strings, should be accompanied by a | 134 // Note: Any change to the state strings, should be accompanied by a |
132 // corresponding change to {experimental.}downloads.json. | 135 // corresponding change to downloads.idl. |
133 const char* kStateStrings[] = { | 136 const char* kStateStrings[] = { |
134 kStateInProgress, | 137 kStateInProgress, |
135 kStateComplete, | 138 kStateComplete, |
136 kStateInterrupted, | 139 kStateInterrupted, |
137 NULL, | 140 NULL, |
138 kStateInterrupted, | 141 kStateInterrupted, |
139 }; | 142 }; |
140 COMPILE_ASSERT(arraysize(kStateStrings) == DownloadItem::MAX_DOWNLOAD_STATE, | 143 COMPILE_ASSERT(arraysize(kStateStrings) == DownloadItem::MAX_DOWNLOAD_STATE, |
141 download_item_state_enum_changed); | 144 download_item_state_enum_changed); |
142 | 145 |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
314 bool include_incognito, | 317 bool include_incognito, |
315 DownloadManager** manager, DownloadManager** incognito_manager) { | 318 DownloadManager** manager, DownloadManager** incognito_manager) { |
316 *manager = DownloadServiceFactory::GetForProfile(profile)-> | 319 *manager = DownloadServiceFactory::GetForProfile(profile)-> |
317 GetDownloadManager(); | 320 GetDownloadManager(); |
318 *incognito_manager = NULL; | 321 *incognito_manager = NULL; |
319 if (include_incognito && profile->HasOffTheRecordProfile()) | 322 if (include_incognito && profile->HasOffTheRecordProfile()) |
320 *incognito_manager = DownloadServiceFactory::GetForProfile(profile-> | 323 *incognito_manager = DownloadServiceFactory::GetForProfile(profile-> |
321 GetOffTheRecordProfile())->GetDownloadManager(); | 324 GetOffTheRecordProfile())->GetDownloadManager(); |
322 } | 325 } |
323 | 326 |
324 DownloadItem* GetActiveItemInternal( | 327 DownloadItem* GetActiveItem( |
325 Profile* profile, | 328 Profile* profile, |
326 bool include_incognito, | 329 bool include_incognito, |
327 int id) { | 330 int id) { |
328 DownloadManager* manager = NULL; | 331 DownloadManager* manager = NULL; |
329 DownloadManager* incognito_manager = NULL; | 332 DownloadManager* incognito_manager = NULL; |
330 GetManagers(profile, include_incognito, &manager, &incognito_manager); | 333 GetManagers(profile, include_incognito, &manager, &incognito_manager); |
331 DownloadItem* download_item = manager->GetActiveDownloadItem(id); | 334 DownloadItem* download_item = manager->GetActiveDownloadItem(id); |
332 if (!download_item && incognito_manager) | 335 if (!download_item && incognito_manager) |
333 download_item = incognito_manager->GetActiveDownloadItem(id); | 336 download_item = incognito_manager->GetActiveDownloadItem(id); |
334 return download_item; | 337 return download_item; |
335 } | 338 } |
336 | 339 |
| 340 enum DownloadsFunctionName { |
| 341 DOWNLOADS_FUNCTION_DOWNLOAD = 0, |
| 342 DOWNLOADS_FUNCTION_SEARCH = 1, |
| 343 DOWNLOADS_FUNCTION_PAUSE = 2, |
| 344 DOWNLOADS_FUNCTION_RESUME = 3, |
| 345 DOWNLOADS_FUNCTION_CANCEL = 4, |
| 346 DOWNLOADS_FUNCTION_ERASE = 5, |
| 347 DOWNLOADS_FUNCTION_SET_DESTINATION = 6, |
| 348 DOWNLOADS_FUNCTION_ACCEPT_DANGER = 7, |
| 349 DOWNLOADS_FUNCTION_SHOW = 8, |
| 350 DOWNLOADS_FUNCTION_DRAG = 9, |
| 351 DOWNLOADS_FUNCTION_GET_FILE_ICON = 10, |
| 352 DOWNLOADS_FUNCTION_OPEN = 11, |
| 353 // Insert new values here, not at the beginning. |
| 354 DOWNLOADS_FUNCTION_LAST |
| 355 }; |
| 356 |
| 357 void RecordApiFunctions(DownloadsFunctionName function) { |
| 358 UMA_HISTOGRAM_ENUMERATION("Download.ApiFunctions", |
| 359 function, |
| 360 DOWNLOADS_FUNCTION_LAST); |
| 361 } |
| 362 |
| 363 void CompileDownloadQueryOrderBy( |
| 364 const std::string& order_by_str, std::string* error, DownloadQuery* query) { |
| 365 static base::LazyInstance<SortTypeMap> sorter_types = |
| 366 LAZY_INSTANCE_INITIALIZER; |
| 367 if (sorter_types.Get().size() == 0) |
| 368 InitSortTypeMap(sorter_types.Get()); |
| 369 |
| 370 std::vector<std::string> order_by_strs; |
| 371 base::SplitString(order_by_str, ' ', &order_by_strs); |
| 372 for (std::vector<std::string>::const_iterator iter = order_by_strs.begin(); |
| 373 iter != order_by_strs.end(); ++iter) { |
| 374 std::string term_str = *iter; |
| 375 if (term_str.empty()) |
| 376 continue; |
| 377 DownloadQuery::SortDirection direction = DownloadQuery::ASCENDING; |
| 378 if (term_str[0] == '-') { |
| 379 direction = DownloadQuery::DESCENDING; |
| 380 term_str = term_str.substr(1); |
| 381 } |
| 382 SortTypeMap::const_iterator sorter_type = |
| 383 sorter_types.Get().find(term_str); |
| 384 if (sorter_type == sorter_types.Get().end()) { |
| 385 *error = download_extension_errors::kInvalidOrderByError; |
| 386 return; |
| 387 } |
| 388 query->AddSorter(sorter_type->second, direction); |
| 389 } |
| 390 } |
| 391 |
| 392 void RunDownloadQuery( |
| 393 const extensions::api::downloads::DownloadQuery& query_in, |
| 394 Profile* profile, |
| 395 bool include_incognito, |
| 396 std::string* error, |
| 397 DownloadQuery::DownloadVector* results) { |
| 398 static base::LazyInstance<FilterTypeMap> filter_types = |
| 399 LAZY_INSTANCE_INITIALIZER; |
| 400 if (filter_types.Get().size() == 0) |
| 401 InitFilterTypeMap(filter_types.Get()); |
| 402 |
| 403 DownloadQuery query_out; |
| 404 |
| 405 if (query_in.limit.get()) { |
| 406 if (*query_in.limit.get() < 0) { |
| 407 *error = download_extension_errors::kInvalidQueryLimit; |
| 408 return; |
| 409 } |
| 410 query_out.Limit(*query_in.limit.get()); |
| 411 } |
| 412 if (query_in.state.get()) { |
| 413 DownloadItem::DownloadState state = StateEnumFromString( |
| 414 *query_in.state.get()); |
| 415 if (state == DownloadItem::MAX_DOWNLOAD_STATE) { |
| 416 *error = download_extension_errors::kInvalidStateError; |
| 417 return; |
| 418 } |
| 419 query_out.AddFilter(state); |
| 420 } |
| 421 if (query_in.danger.get()) { |
| 422 content::DownloadDangerType danger_type = |
| 423 DangerEnumFromString(*query_in.danger.get()); |
| 424 if (danger_type == content::DOWNLOAD_DANGER_TYPE_MAX) { |
| 425 *error = download_extension_errors::kInvalidDangerTypeError; |
| 426 return; |
| 427 } |
| 428 query_out.AddFilter(danger_type); |
| 429 } |
| 430 if (query_in.order_by.get()) { |
| 431 CompileDownloadQueryOrderBy(*query_in.order_by.get(), error, &query_out); |
| 432 if (!error->empty()) |
| 433 return; |
| 434 } |
| 435 |
| 436 scoped_ptr<base::DictionaryValue> query_in_value(query_in.ToValue().Pass()); |
| 437 for (base::DictionaryValue::Iterator query_json_field(*query_in_value.get()); |
| 438 query_json_field.HasNext(); query_json_field.Advance()) { |
| 439 FilterTypeMap::const_iterator filter_type = |
| 440 filter_types.Get().find(query_json_field.key()); |
| 441 if (filter_type != filter_types.Get().end()) { |
| 442 if (!query_out.AddFilter(filter_type->second, query_json_field.value())) { |
| 443 *error = download_extension_errors::kInvalidFilterError; |
| 444 return; |
| 445 } |
| 446 } |
| 447 } |
| 448 |
| 449 DownloadManager* manager = NULL; |
| 450 DownloadManager* incognito_manager = NULL; |
| 451 GetManagers(profile, include_incognito, &manager, &incognito_manager); |
| 452 DownloadQuery::DownloadVector all_items; |
| 453 if (query_in.id.get()) { |
| 454 DownloadItem* item = manager->GetDownloadItem(*query_in.id.get()); |
| 455 if (!item && incognito_manager) |
| 456 item = incognito_manager->GetDownloadItem(*query_in.id.get()); |
| 457 if (item) |
| 458 all_items.push_back(item); |
| 459 } else { |
| 460 manager->GetAllDownloads(FilePath(FILE_PATH_LITERAL("")), &all_items); |
| 461 if (incognito_manager) |
| 462 incognito_manager->GetAllDownloads( |
| 463 FilePath(FILE_PATH_LITERAL("")), &all_items); |
| 464 } |
| 465 query_out.Search(all_items.begin(), all_items.end(), results); |
| 466 } |
| 467 |
337 } // namespace | 468 } // namespace |
338 | 469 |
339 bool DownloadsFunctionInterface::RunImplImpl( | 470 DownloadsDownloadFunction::DownloadsDownloadFunction() {} |
340 DownloadsFunctionInterface* pimpl) { | |
341 CHECK(pimpl); | |
342 if (!pimpl->ParseArgs()) return false; | |
343 UMA_HISTOGRAM_ENUMERATION( | |
344 "Download.ApiFunctions", pimpl->function(), DOWNLOADS_FUNCTION_LAST); | |
345 return pimpl->RunInternal(); | |
346 } | |
347 | |
348 SyncDownloadsFunction::SyncDownloadsFunction( | |
349 DownloadsFunctionInterface::DownloadsFunctionName function) | |
350 : function_(function) { | |
351 } | |
352 | |
353 SyncDownloadsFunction::~SyncDownloadsFunction() {} | |
354 | |
355 bool SyncDownloadsFunction::RunImpl() { | |
356 return DownloadsFunctionInterface::RunImplImpl(this); | |
357 } | |
358 | |
359 DownloadsFunctionInterface::DownloadsFunctionName | |
360 SyncDownloadsFunction::function() const { | |
361 return function_; | |
362 } | |
363 | |
364 DownloadItem* SyncDownloadsFunction::GetActiveItem(int download_id) { | |
365 return GetActiveItemInternal(profile(), include_incognito(), download_id); | |
366 } | |
367 | |
368 AsyncDownloadsFunction::AsyncDownloadsFunction( | |
369 DownloadsFunctionInterface::DownloadsFunctionName function) | |
370 : function_(function) { | |
371 } | |
372 | |
373 AsyncDownloadsFunction::~AsyncDownloadsFunction() {} | |
374 | |
375 bool AsyncDownloadsFunction::RunImpl() { | |
376 return DownloadsFunctionInterface::RunImplImpl(this); | |
377 } | |
378 | |
379 DownloadsFunctionInterface::DownloadsFunctionName | |
380 AsyncDownloadsFunction::function() const { | |
381 return function_; | |
382 } | |
383 | |
384 DownloadItem* AsyncDownloadsFunction::GetActiveItem(int download_id) { | |
385 return GetActiveItemInternal(profile(), include_incognito(), download_id); | |
386 } | |
387 | |
388 DownloadsDownloadFunction::DownloadsDownloadFunction() | |
389 : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_DOWNLOAD) { | |
390 } | |
391 | |
392 DownloadsDownloadFunction::~DownloadsDownloadFunction() {} | 471 DownloadsDownloadFunction::~DownloadsDownloadFunction() {} |
393 | 472 |
394 DownloadsDownloadFunction::IOData::IOData() | 473 bool DownloadsDownloadFunction::RunImpl() { |
395 : save_as(false), | 474 scoped_ptr<extensions::api::downloads::Download::Params> params( |
396 extra_headers(NULL), | 475 extensions::api::downloads::Download::Params::Create(*args_)); |
397 method("GET"), | 476 EXTENSION_FUNCTION_VALIDATE(params.get()); |
398 rdh(NULL), | 477 RecordApiFunctions(DOWNLOADS_FUNCTION_DOWNLOAD); |
399 resource_context(NULL), | 478 const extensions::api::downloads::DownloadOptions& options = params->options; |
400 render_process_host_id(0), | 479 |
401 render_view_host_routing_id(0) { | 480 GURL url(options.url); |
402 } | 481 if (!url.is_valid() || |
403 | 482 (!url.SchemeIs("data") && |
404 DownloadsDownloadFunction::IOData::~IOData() {} | 483 url.GetOrigin() != GetExtension()->url().GetOrigin() && |
405 | 484 !GetExtension()->HasHostPermission(url))) { |
406 bool DownloadsDownloadFunction::ParseArgs() { | |
407 base::DictionaryValue* options = NULL; | |
408 std::string url; | |
409 iodata_.reset(new IOData()); | |
410 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options)); | |
411 EXTENSION_FUNCTION_VALIDATE(options->GetString(kUrlKey, &url)); | |
412 iodata_->url = GURL(url); | |
413 if (!iodata_->url.is_valid()) { | |
414 error_ = download_extension_errors::kInvalidURLError; | 485 error_ = download_extension_errors::kInvalidURLError; |
415 return false; | 486 return false; |
416 } | 487 } |
417 | 488 |
418 if (!iodata_->url.SchemeIs("data") && | 489 content::DownloadSaveInfo save_info; |
419 iodata_->url.GetOrigin() != GetExtension()->url().GetOrigin() && | 490 if (options.filename.get()) { |
420 !GetExtension()->HasHostPermission(iodata_->url)) { | 491 // TODO(benjhayden): Make json_schema_compiler generate string16s instead of |
421 error_ = download_extension_errors::kInvalidURLError; | 492 // std::strings. Can't get filename16 from options.ToValue() because that |
422 return false; | 493 // converts it from std::string. |
423 } | 494 base::DictionaryValue* options_value = NULL; |
424 | 495 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options_value)); |
425 if (options->HasKey(kFilenameKey)) { | 496 string16 filename16; |
426 EXTENSION_FUNCTION_VALIDATE(options->GetString( | 497 EXTENSION_FUNCTION_VALIDATE(options_value->GetString( |
427 kFilenameKey, &iodata_->filename)); | 498 kFilenameKey, &filename16)); |
428 if (!ValidateFilename(iodata_->filename)) { | 499 if (!ValidateFilename(filename16)) { |
429 error_ = download_extension_errors::kGenericError; | 500 error_ = download_extension_errors::kGenericError; |
430 return false; | 501 return false; |
431 } | 502 } |
432 } | 503 // TODO(benjhayden) Ensure that this filename is interpreted as a path |
433 | 504 // relative to the default downloads directory without allowing '..'. |
434 if (options->HasKey(kSaveAsKey)) { | 505 save_info.suggested_name = filename16; |
435 EXTENSION_FUNCTION_VALIDATE(options->GetBoolean( | 506 } |
436 kSaveAsKey, &iodata_->save_as)); | 507 |
437 } | 508 if (options.save_as.get()) |
438 | 509 save_info.prompt_for_save_location = *options.save_as.get(); |
439 if (options->HasKey(kMethodKey)) { | 510 |
440 EXTENSION_FUNCTION_VALIDATE(options->GetString( | 511 Profile* current_profile = profile(); |
441 kMethodKey, &iodata_->method)); | 512 if (include_incognito() && profile()->HasOffTheRecordProfile()) |
442 } | 513 current_profile = profile()->GetOffTheRecordProfile(); |
443 | 514 // TODO XXX test incognito download() |
444 // It's ok to use a pointer to extra_headers without DeepCopy()ing because | 515 |
445 // |args_| (which owns *extra_headers) is guaranteed to live as long as | 516 scoped_ptr<content::DownloadUrlParameters> download_params( |
446 // |this|. | 517 new content::DownloadUrlParameters( |
447 if (options->HasKey(kHeadersKey)) { | 518 url, |
448 EXTENSION_FUNCTION_VALIDATE(options->GetList( | 519 render_view_host()->GetProcess()->GetID(), |
449 kHeadersKey, &iodata_->extra_headers)); | 520 render_view_host()->GetRoutingID(), |
450 } | 521 current_profile->GetResourceContext(), |
451 | 522 save_info)); |
452 if (options->HasKey(kBodyKey)) { | 523 |
453 EXTENSION_FUNCTION_VALIDATE(options->GetString( | 524 if (options.headers.get()) { |
454 kBodyKey, &iodata_->post_body)); | 525 for (std::vector<linked_ptr<HeaderNameValuePair> >::const_iterator iter = |
455 } | 526 options.headers->begin(); |
456 | 527 iter != options.headers->end(); |
457 if (iodata_->extra_headers != NULL) { | 528 ++iter) { |
458 for (size_t index = 0; index < iodata_->extra_headers->GetSize(); ++index) { | 529 const HeaderNameValuePair& name_value = **iter; |
459 base::DictionaryValue* header = NULL; | 530 if (!net::HttpUtil::IsSafeHeader(name_value.name)) { |
460 std::string name; | |
461 EXTENSION_FUNCTION_VALIDATE(iodata_->extra_headers->GetDictionary( | |
462 index, &header)); | |
463 EXTENSION_FUNCTION_VALIDATE(header->GetString( | |
464 kHeaderNameKey, &name)); | |
465 if (header->HasKey(kHeaderBinaryValueKey)) { | |
466 base::ListValue* binary_value = NULL; | |
467 EXTENSION_FUNCTION_VALIDATE(header->GetList( | |
468 kHeaderBinaryValueKey, &binary_value)); | |
469 for (size_t char_i = 0; char_i < binary_value->GetSize(); ++char_i) { | |
470 int char_value = 0; | |
471 EXTENSION_FUNCTION_VALIDATE(binary_value->GetInteger( | |
472 char_i, &char_value)); | |
473 } | |
474 } else if (header->HasKey(kHeaderValueKey)) { | |
475 std::string value; | |
476 EXTENSION_FUNCTION_VALIDATE(header->GetString( | |
477 kHeaderValueKey, &value)); | |
478 } | |
479 if (!net::HttpUtil::IsSafeHeader(name)) { | |
480 error_ = download_extension_errors::kGenericError; | 531 error_ = download_extension_errors::kGenericError; |
481 return false; | 532 return false; |
482 } | 533 } |
483 } | 534 std::string value; |
484 } | 535 if (name_value.binary_value.get()) { |
485 iodata_->rdh = content::ResourceDispatcherHost::Get(); | 536 for (size_t char_i = 0; |
486 iodata_->resource_context = profile()->GetResourceContext(); | 537 char_i < name_value.binary_value->size(); |
487 iodata_->render_process_host_id = render_view_host()->GetProcess()->GetID(); | 538 ++char_i) { |
488 iodata_->render_view_host_routing_id = render_view_host()->GetRoutingID(); | 539 value.push_back((*name_value.binary_value.get())[char_i]); |
| 540 } |
| 541 } else if (name_value.value.get()) { |
| 542 value = *name_value.value.get(); |
| 543 } |
| 544 download_params->add_request_header(name_value.name, value); |
| 545 } |
| 546 } |
| 547 |
| 548 if (options.method.get()) |
| 549 download_params->set_method(*options.method.get()); |
| 550 if (options.body.get()) |
| 551 download_params->set_post_body(*options.body.get()); |
| 552 download_params->set_callback(base::Bind( |
| 553 &DownloadsDownloadFunction::OnStarted, this)); |
| 554 // Prevent login prompts for 401/407 responses. |
| 555 download_params->set_load_flags(net::LOAD_DO_NOT_PROMPT_FOR_LOGIN); |
| 556 |
| 557 DownloadManager* manager = DownloadServiceFactory::GetForProfile( |
| 558 current_profile)->GetDownloadManager(); |
| 559 manager->DownloadUrl(download_params.Pass()); |
489 return true; | 560 return true; |
490 } | 561 } |
491 | 562 |
492 bool DownloadsDownloadFunction::RunInternal() { | |
493 VLOG(1) << __FUNCTION__ << " " << iodata_->url.spec(); | |
494 if (!BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, base::Bind( | |
495 &DownloadsDownloadFunction::BeginDownloadOnIOThread, this))) { | |
496 error_ = download_extension_errors::kGenericError; | |
497 return false; | |
498 } | |
499 return true; | |
500 } | |
501 | |
502 void DownloadsDownloadFunction::BeginDownloadOnIOThread() { | |
503 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
504 DVLOG(1) << __FUNCTION__ << " " << iodata_->url.spec(); | |
505 content::DownloadSaveInfo save_info; | |
506 // TODO(benjhayden) Ensure that this filename is interpreted as a path | |
507 // relative to the default downloads directory without allowing '..'. | |
508 save_info.suggested_name = iodata_->filename; | |
509 save_info.prompt_for_save_location = iodata_->save_as; | |
510 | |
511 scoped_ptr<net::URLRequest> request(new net::URLRequest(iodata_->url, NULL)); | |
512 request->set_method(iodata_->method); | |
513 if (iodata_->extra_headers != NULL) { | |
514 for (size_t index = 0; index < iodata_->extra_headers->GetSize(); ++index) { | |
515 base::DictionaryValue* header = NULL; | |
516 std::string name, value; | |
517 CHECK(iodata_->extra_headers->GetDictionary(index, &header)); | |
518 CHECK(header->GetString(kHeaderNameKey, &name)); | |
519 if (header->HasKey(kHeaderBinaryValueKey)) { | |
520 base::ListValue* binary_value = NULL; | |
521 CHECK(header->GetList(kHeaderBinaryValueKey, &binary_value)); | |
522 for (size_t char_i = 0; char_i < binary_value->GetSize(); ++char_i) { | |
523 int char_value = 0; | |
524 CHECK(binary_value->GetInteger(char_i, &char_value)); | |
525 if ((0 <= char_value) && | |
526 (char_value <= 0xff)) { | |
527 value.push_back(char_value); | |
528 } | |
529 } | |
530 } else if (header->HasKey(kHeaderValueKey)) { | |
531 CHECK(header->GetString(kHeaderValueKey, &value)); | |
532 } | |
533 request->SetExtraRequestHeaderByName(name, value, false/*overwrite*/); | |
534 } | |
535 } | |
536 if (!iodata_->post_body.empty()) { | |
537 request->AppendBytesToUpload(iodata_->post_body.data(), | |
538 iodata_->post_body.size()); | |
539 } | |
540 | |
541 // Prevent login prompts for 401/407 responses. | |
542 request->set_load_flags(request->load_flags() | | |
543 net::LOAD_DO_NOT_PROMPT_FOR_LOGIN); | |
544 | |
545 net::Error error = iodata_->rdh->BeginDownload( | |
546 request.Pass(), | |
547 false, // is_content_initiated | |
548 iodata_->resource_context, | |
549 iodata_->render_process_host_id, | |
550 iodata_->render_view_host_routing_id, | |
551 false, // prefer_cache | |
552 save_info, | |
553 base::Bind(&DownloadsDownloadFunction::OnStarted, this)); | |
554 iodata_.reset(); | |
555 | |
556 if (error != net::OK) { | |
557 BrowserThread::PostTask( | |
558 BrowserThread::UI, FROM_HERE, | |
559 base::Bind(&DownloadsDownloadFunction::OnStarted, this, | |
560 DownloadId::Invalid(), error)); | |
561 } | |
562 } | |
563 | |
564 void DownloadsDownloadFunction::OnStarted(DownloadId dl_id, net::Error error) { | 563 void DownloadsDownloadFunction::OnStarted(DownloadId dl_id, net::Error error) { |
565 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 564 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
566 VLOG(1) << __FUNCTION__ << " " << dl_id << " " << error; | 565 VLOG(1) << __FUNCTION__ << " " << dl_id << " " << error; |
567 if (dl_id.local() >= 0) { | 566 if (dl_id.local() >= 0) { |
568 result_.reset(base::Value::CreateIntegerValue(dl_id.local())); | 567 result_.reset(base::Value::CreateIntegerValue(dl_id.local())); |
569 } else { | 568 } else { |
570 error_ = net::ErrorToString(error); | 569 error_ = net::ErrorToString(error); |
571 } | 570 } |
572 SendResponse(error_.empty()); | 571 SendResponse(error_.empty()); |
573 } | 572 } |
574 | 573 |
575 DownloadsSearchFunction::DownloadsSearchFunction() | 574 DownloadsSearchFunction::DownloadsSearchFunction() {} |
576 : SyncDownloadsFunction(DOWNLOADS_FUNCTION_SEARCH), | |
577 query_(new DownloadQuery()), | |
578 get_id_(0), | |
579 has_get_id_(false) { | |
580 } | |
581 | |
582 DownloadsSearchFunction::~DownloadsSearchFunction() {} | 575 DownloadsSearchFunction::~DownloadsSearchFunction() {} |
583 | 576 |
584 bool DownloadsSearchFunction::ParseArgs() { | 577 bool DownloadsSearchFunction::RunImpl() { |
585 static base::LazyInstance<FilterTypeMap> filter_types = | 578 scoped_ptr<extensions::api::downloads::Search::Params> params( |
586 LAZY_INSTANCE_INITIALIZER; | 579 extensions::api::downloads::Search::Params::Create(*args_)); |
587 if (filter_types.Get().size() == 0) | 580 EXTENSION_FUNCTION_VALIDATE(params.get()); |
588 InitFilterTypeMap(filter_types.Get()); | 581 RecordApiFunctions(DOWNLOADS_FUNCTION_SEARCH); |
589 | 582 DownloadQuery::DownloadVector results; |
590 base::DictionaryValue* query_json = NULL; | 583 RunDownloadQuery(params->query, profile(), include_incognito(), |
591 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &query_json)); | 584 &error_, &results); |
592 for (base::DictionaryValue::Iterator query_json_field(*query_json); | 585 if (!error_.empty()) |
593 query_json_field.HasNext(); query_json_field.Advance()) { | 586 return false; |
594 FilterTypeMap::const_iterator filter_type = | |
595 filter_types.Get().find(query_json_field.key()); | |
596 | |
597 if (filter_type != filter_types.Get().end()) { | |
598 if (!query_->AddFilter(filter_type->second, query_json_field.value())) { | |
599 error_ = download_extension_errors::kInvalidFilterError; | |
600 return false; | |
601 } | |
602 } else if (query_json_field.key() == kIdKey) { | |
603 EXTENSION_FUNCTION_VALIDATE(query_json_field.value().GetAsInteger( | |
604 &get_id_)); | |
605 has_get_id_ = true; | |
606 } else if (query_json_field.key() == kOrderByKey) { | |
607 if (!ParseOrderBy(query_json_field.value())) | |
608 return false; | |
609 } else if (query_json_field.key() == kDangerKey) { | |
610 std::string danger_str; | |
611 EXTENSION_FUNCTION_VALIDATE(query_json_field.value().GetAsString( | |
612 &danger_str)); | |
613 content::DownloadDangerType danger_type = | |
614 DangerEnumFromString(danger_str); | |
615 if (danger_type == content::DOWNLOAD_DANGER_TYPE_MAX) { | |
616 error_ = download_extension_errors::kInvalidDangerTypeError; | |
617 return false; | |
618 } | |
619 query_->AddFilter(danger_type); | |
620 } else if (query_json_field.key() == kStateKey) { | |
621 std::string state_str; | |
622 EXTENSION_FUNCTION_VALIDATE(query_json_field.value().GetAsString( | |
623 &state_str)); | |
624 DownloadItem::DownloadState state = StateEnumFromString(state_str); | |
625 if (state == DownloadItem::MAX_DOWNLOAD_STATE) { | |
626 error_ = download_extension_errors::kInvalidStateError; | |
627 return false; | |
628 } | |
629 query_->AddFilter(state); | |
630 } else if (query_json_field.key() == kLimitKey) { | |
631 int limit = 0; | |
632 EXTENSION_FUNCTION_VALIDATE(query_json_field.value().GetAsInteger( | |
633 &limit)); | |
634 if (limit < 0) { | |
635 error_ = download_extension_errors::kInvalidQueryLimit; | |
636 return false; | |
637 } | |
638 query_->Limit(limit); | |
639 } else { | |
640 EXTENSION_FUNCTION_VALIDATE(false); | |
641 } | |
642 } | |
643 return true; | |
644 } | |
645 | |
646 bool DownloadsSearchFunction::ParseOrderBy(const base::Value& order_by_value) { | |
647 static base::LazyInstance<SortTypeMap> sorter_types = | |
648 LAZY_INSTANCE_INITIALIZER; | |
649 if (sorter_types.Get().size() == 0) | |
650 InitSortTypeMap(sorter_types.Get()); | |
651 | |
652 std::string order_by_str; | |
653 EXTENSION_FUNCTION_VALIDATE(order_by_value.GetAsString(&order_by_str)); | |
654 std::vector<std::string> order_by_strs; | |
655 base::SplitString(order_by_str, ' ', &order_by_strs); | |
656 for (std::vector<std::string>::const_iterator iter = order_by_strs.begin(); | |
657 iter != order_by_strs.end(); ++iter) { | |
658 std::string term_str = *iter; | |
659 if (term_str.empty()) | |
660 continue; | |
661 DownloadQuery::SortDirection direction = DownloadQuery::ASCENDING; | |
662 if (term_str[0] == '-') { | |
663 direction = DownloadQuery::DESCENDING; | |
664 term_str = term_str.substr(1); | |
665 } | |
666 SortTypeMap::const_iterator sorter_type = | |
667 sorter_types.Get().find(term_str); | |
668 if (sorter_type == sorter_types.Get().end()) { | |
669 error_ = download_extension_errors::kInvalidOrderByError; | |
670 return false; | |
671 } | |
672 query_->AddSorter(sorter_type->second, direction); | |
673 } | |
674 return true; | |
675 } | |
676 | |
677 bool DownloadsSearchFunction::RunInternal() { | |
678 DownloadManager* manager = NULL; | |
679 DownloadManager* incognito_manager = NULL; | |
680 GetManagers(profile(), include_incognito(), &manager, &incognito_manager); | |
681 DownloadQuery::DownloadVector all_items, cpp_results; | |
682 if (has_get_id_) { | |
683 DownloadItem* item = manager->GetDownloadItem(get_id_); | |
684 if (!item && incognito_manager) | |
685 item = incognito_manager->GetDownloadItem(get_id_); | |
686 if (item) | |
687 all_items.push_back(item); | |
688 } else { | |
689 manager->GetAllDownloads(FilePath(FILE_PATH_LITERAL("")), &all_items); | |
690 if (incognito_manager) | |
691 incognito_manager->GetAllDownloads( | |
692 FilePath(FILE_PATH_LITERAL("")), &all_items); | |
693 } | |
694 query_->Search(all_items.begin(), all_items.end(), &cpp_results); | |
695 base::ListValue* json_results = new base::ListValue(); | 587 base::ListValue* json_results = new base::ListValue(); |
696 for (DownloadManager::DownloadVector::const_iterator it = cpp_results.begin(); | 588 for (DownloadManager::DownloadVector::const_iterator it = results.begin(); |
697 it != cpp_results.end(); ++it) { | 589 it != results.end(); ++it) { |
698 scoped_ptr<base::DictionaryValue> item(DownloadItemToJSON(*it)); | 590 scoped_ptr<base::DictionaryValue> item(DownloadItemToJSON(*it)); |
699 json_results->Append(item.release()); | 591 json_results->Append(item.release()); |
700 } | 592 } |
701 result_.reset(json_results); | 593 result_.reset(json_results); |
702 return true; | 594 return true; |
703 } | 595 } |
704 | 596 |
705 DownloadsPauseFunction::DownloadsPauseFunction() | 597 DownloadsPauseFunction::DownloadsPauseFunction() {} |
706 : SyncDownloadsFunction(DOWNLOADS_FUNCTION_PAUSE), | |
707 download_id_(DownloadId::Invalid().local()) { | |
708 } | |
709 | |
710 DownloadsPauseFunction::~DownloadsPauseFunction() {} | 598 DownloadsPauseFunction::~DownloadsPauseFunction() {} |
711 | 599 |
712 bool DownloadsPauseFunction::ParseArgs() { | 600 bool DownloadsPauseFunction::RunImpl() { |
713 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &download_id_)); | 601 scoped_ptr<extensions::api::downloads::Pause::Params> params( |
714 return true; | 602 extensions::api::downloads::Pause::Params::Create(*args_)); |
715 } | 603 EXTENSION_FUNCTION_VALIDATE(params.get()); |
716 | 604 RecordApiFunctions(DOWNLOADS_FUNCTION_PAUSE); |
717 bool DownloadsPauseFunction::RunInternal() { | 605 DownloadItem* download_item = GetActiveItem( |
718 DownloadItem* download_item = GetActiveItem(download_id_); | 606 profile(), include_incognito(), params->download_id); |
719 if ((download_item == NULL) || !download_item->IsInProgress()) { | 607 if ((download_item == NULL) || !download_item->IsInProgress()) { |
720 // This could be due to an invalid download ID, or it could be due to the | 608 // This could be due to an invalid download ID, or it could be due to the |
721 // download not being currently active. | 609 // download not being currently active. |
722 error_ = download_extension_errors::kInvalidOperationError; | 610 error_ = download_extension_errors::kInvalidOperationError; |
723 } else if (!download_item->IsPaused()) { | 611 } else if (!download_item->IsPaused()) { |
724 // If download_item->IsPaused() already then we treat it as a success. | 612 // If download_item->IsPaused() already then we treat it as a success. |
725 download_item->TogglePause(); | 613 download_item->TogglePause(); |
726 } | 614 } |
727 return error_.empty(); | 615 return error_.empty(); |
728 } | 616 } |
729 | 617 |
730 DownloadsResumeFunction::DownloadsResumeFunction() | 618 DownloadsResumeFunction::DownloadsResumeFunction() {} |
731 : SyncDownloadsFunction(DOWNLOADS_FUNCTION_RESUME), | |
732 download_id_(DownloadId::Invalid().local()) { | |
733 } | |
734 | |
735 DownloadsResumeFunction::~DownloadsResumeFunction() {} | 619 DownloadsResumeFunction::~DownloadsResumeFunction() {} |
736 | 620 |
737 bool DownloadsResumeFunction::ParseArgs() { | 621 bool DownloadsResumeFunction::RunImpl() { |
738 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &download_id_)); | 622 scoped_ptr<extensions::api::downloads::Resume::Params> params( |
739 return true; | 623 extensions::api::downloads::Resume::Params::Create(*args_)); |
740 } | 624 EXTENSION_FUNCTION_VALIDATE(params.get()); |
741 | 625 RecordApiFunctions(DOWNLOADS_FUNCTION_RESUME); |
742 bool DownloadsResumeFunction::RunInternal() { | 626 DownloadItem* download_item = GetActiveItem( |
743 DownloadItem* download_item = GetActiveItem(download_id_); | 627 profile(), include_incognito(), params->download_id); |
744 if (download_item == NULL) { | 628 if (download_item == NULL) { |
745 // This could be due to an invalid download ID, or it could be due to the | 629 // This could be due to an invalid download ID, or it could be due to the |
746 // download not being currently active. | 630 // download not being currently active. |
747 error_ = download_extension_errors::kInvalidOperationError; | 631 error_ = download_extension_errors::kInvalidOperationError; |
748 } else if (download_item->IsPaused()) { | 632 } else if (download_item->IsPaused()) { |
749 // If !download_item->IsPaused() already, then we treat it as a success. | 633 // If !download_item->IsPaused() already, then we treat it as a success. |
750 download_item->TogglePause(); | 634 download_item->TogglePause(); |
751 } | 635 } |
752 return error_.empty(); | 636 return error_.empty(); |
753 } | 637 } |
754 | 638 |
755 DownloadsCancelFunction::DownloadsCancelFunction() | 639 DownloadsCancelFunction::DownloadsCancelFunction() {} |
756 : SyncDownloadsFunction(DOWNLOADS_FUNCTION_CANCEL), | |
757 download_id_(DownloadId::Invalid().local()) { | |
758 } | |
759 | |
760 DownloadsCancelFunction::~DownloadsCancelFunction() {} | 640 DownloadsCancelFunction::~DownloadsCancelFunction() {} |
761 | 641 |
762 bool DownloadsCancelFunction::ParseArgs() { | 642 bool DownloadsCancelFunction::RunImpl() { |
763 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &download_id_)); | 643 scoped_ptr<extensions::api::downloads::Resume::Params> params( |
764 return true; | 644 extensions::api::downloads::Resume::Params::Create(*args_)); |
765 } | 645 EXTENSION_FUNCTION_VALIDATE(params.get()); |
766 | 646 RecordApiFunctions(DOWNLOADS_FUNCTION_CANCEL); |
767 bool DownloadsCancelFunction::RunInternal() { | 647 DownloadItem* download_item = GetActiveItem( |
768 DownloadItem* download_item = GetActiveItem(download_id_); | 648 profile(), include_incognito(), params->download_id); |
769 if (download_item != NULL) | 649 if (download_item != NULL) |
770 download_item->Cancel(true); | 650 download_item->Cancel(true); |
771 // |download_item| can be NULL if the download ID was invalid or if the | 651 // |download_item| can be NULL if the download ID was invalid or if the |
772 // download is not currently active. Either way, we don't consider it a | 652 // download is not currently active. Either way, we don't consider it a |
773 // failure. | 653 // failure. |
774 return error_.empty(); | 654 return error_.empty(); |
775 } | 655 } |
776 | 656 |
777 DownloadsEraseFunction::DownloadsEraseFunction() | 657 DownloadsEraseFunction::DownloadsEraseFunction() {} |
778 : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_ERASE) { | 658 DownloadsEraseFunction::~DownloadsEraseFunction() {} |
| 659 |
| 660 bool DownloadsEraseFunction::RunImpl() { |
| 661 scoped_ptr<extensions::api::downloads::Erase::Params> params( |
| 662 extensions::api::downloads::Erase::Params::Create(*args_)); |
| 663 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 664 RecordApiFunctions(DOWNLOADS_FUNCTION_ERASE); |
| 665 error_ = download_extension_errors::kNotImplementedError; |
| 666 return error_.empty(); |
779 } | 667 } |
780 | 668 |
781 DownloadsEraseFunction::~DownloadsEraseFunction() {} | 669 DownloadsSetDestinationFunction::DownloadsSetDestinationFunction() {} |
| 670 DownloadsSetDestinationFunction::~DownloadsSetDestinationFunction() {} |
782 | 671 |
783 bool DownloadsEraseFunction::ParseArgs() { | 672 bool DownloadsSetDestinationFunction::RunImpl() { |
784 base::DictionaryValue* query_json = NULL; | 673 scoped_ptr<extensions::api::downloads::SetDestination::Params> params( |
785 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &query_json)); | 674 extensions::api::downloads::SetDestination::Params::Create(*args_)); |
| 675 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 676 RecordApiFunctions(DOWNLOADS_FUNCTION_SET_DESTINATION); |
786 error_ = download_extension_errors::kNotImplementedError; | 677 error_ = download_extension_errors::kNotImplementedError; |
787 return false; | 678 return error_.empty(); |
788 } | 679 } |
789 | 680 |
790 bool DownloadsEraseFunction::RunInternal() { | 681 DownloadsAcceptDangerFunction::DownloadsAcceptDangerFunction() {} |
791 NOTIMPLEMENTED(); | 682 DownloadsAcceptDangerFunction::~DownloadsAcceptDangerFunction() {} |
792 return false; | 683 |
| 684 bool DownloadsAcceptDangerFunction::RunImpl() { |
| 685 scoped_ptr<extensions::api::downloads::AcceptDanger::Params> params( |
| 686 extensions::api::downloads::AcceptDanger::Params::Create(*args_)); |
| 687 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 688 RecordApiFunctions(DOWNLOADS_FUNCTION_ACCEPT_DANGER); |
| 689 error_ = download_extension_errors::kNotImplementedError; |
| 690 return error_.empty(); |
793 } | 691 } |
794 | 692 |
795 DownloadsSetDestinationFunction::DownloadsSetDestinationFunction() | 693 DownloadsShowFunction::DownloadsShowFunction() {} |
796 : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_SET_DESTINATION) { | 694 DownloadsShowFunction::~DownloadsShowFunction() {} |
| 695 |
| 696 bool DownloadsShowFunction::RunImpl() { |
| 697 scoped_ptr<extensions::api::downloads::Show::Params> params( |
| 698 extensions::api::downloads::Show::Params::Create(*args_)); |
| 699 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 700 RecordApiFunctions(DOWNLOADS_FUNCTION_SHOW); |
| 701 error_ = download_extension_errors::kNotImplementedError; |
| 702 return error_.empty(); |
797 } | 703 } |
798 | 704 |
799 DownloadsSetDestinationFunction::~DownloadsSetDestinationFunction() {} | 705 DownloadsOpenFunction::DownloadsOpenFunction() {} |
| 706 DownloadsOpenFunction::~DownloadsOpenFunction() {} |
800 | 707 |
801 bool DownloadsSetDestinationFunction::ParseArgs() { | 708 bool DownloadsOpenFunction::RunImpl() { |
802 int dl_id = 0; | 709 scoped_ptr<extensions::api::downloads::Open::Params> params( |
803 std::string path; | 710 extensions::api::downloads::Open::Params::Create(*args_)); |
804 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id)); | 711 EXTENSION_FUNCTION_VALIDATE(params.get()); |
805 EXTENSION_FUNCTION_VALIDATE(args_->GetString(1, &path)); | 712 RecordApiFunctions(DOWNLOADS_FUNCTION_OPEN); |
806 VLOG(1) << __FUNCTION__ << " " << dl_id << " " << &path; | |
807 error_ = download_extension_errors::kNotImplementedError; | 713 error_ = download_extension_errors::kNotImplementedError; |
808 return false; | 714 return error_.empty(); |
809 } | 715 } |
810 | 716 |
811 bool DownloadsSetDestinationFunction::RunInternal() { | 717 DownloadsDragFunction::DownloadsDragFunction() {} |
812 NOTIMPLEMENTED(); | |
813 return false; | |
814 } | |
815 | |
816 DownloadsAcceptDangerFunction::DownloadsAcceptDangerFunction() | |
817 : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_ACCEPT_DANGER) { | |
818 } | |
819 | |
820 DownloadsAcceptDangerFunction::~DownloadsAcceptDangerFunction() {} | |
821 | |
822 bool DownloadsAcceptDangerFunction::ParseArgs() { | |
823 int dl_id = 0; | |
824 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id)); | |
825 VLOG(1) << __FUNCTION__ << " " << dl_id; | |
826 error_ = download_extension_errors::kNotImplementedError; | |
827 return false; | |
828 } | |
829 | |
830 bool DownloadsAcceptDangerFunction::RunInternal() { | |
831 NOTIMPLEMENTED(); | |
832 return false; | |
833 } | |
834 | |
835 DownloadsShowFunction::DownloadsShowFunction() | |
836 : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_SHOW) { | |
837 } | |
838 | |
839 DownloadsShowFunction::~DownloadsShowFunction() {} | |
840 | |
841 bool DownloadsShowFunction::ParseArgs() { | |
842 int dl_id = 0; | |
843 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id)); | |
844 VLOG(1) << __FUNCTION__ << " " << dl_id; | |
845 error_ = download_extension_errors::kNotImplementedError; | |
846 return false; | |
847 } | |
848 | |
849 bool DownloadsShowFunction::RunInternal() { | |
850 NOTIMPLEMENTED(); | |
851 return false; | |
852 } | |
853 | |
854 DownloadsDragFunction::DownloadsDragFunction() | |
855 : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_DRAG) { | |
856 } | |
857 | |
858 DownloadsDragFunction::~DownloadsDragFunction() {} | 718 DownloadsDragFunction::~DownloadsDragFunction() {} |
859 | 719 |
860 bool DownloadsDragFunction::ParseArgs() { | 720 bool DownloadsDragFunction::RunImpl() { |
861 int dl_id = 0; | 721 scoped_ptr<extensions::api::downloads::Drag::Params> params( |
862 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id)); | 722 extensions::api::downloads::Drag::Params::Create(*args_)); |
863 VLOG(1) << __FUNCTION__ << " " << dl_id; | 723 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 724 RecordApiFunctions(DOWNLOADS_FUNCTION_DRAG); |
864 error_ = download_extension_errors::kNotImplementedError; | 725 error_ = download_extension_errors::kNotImplementedError; |
865 return false; | 726 return error_.empty(); |
866 } | |
867 | |
868 bool DownloadsDragFunction::RunInternal() { | |
869 NOTIMPLEMENTED(); | |
870 return false; | |
871 } | 727 } |
872 | 728 |
873 DownloadsGetFileIconFunction::DownloadsGetFileIconFunction() | 729 DownloadsGetFileIconFunction::DownloadsGetFileIconFunction() |
874 : AsyncDownloadsFunction(DOWNLOADS_FUNCTION_GET_FILE_ICON), | 730 : icon_extractor_(new DownloadFileIconExtractorImpl()) { |
875 icon_size_(kDefaultIconSize), | |
876 icon_extractor_(new DownloadFileIconExtractorImpl()) { | |
877 } | 731 } |
878 | 732 |
879 DownloadsGetFileIconFunction::~DownloadsGetFileIconFunction() {} | 733 DownloadsGetFileIconFunction::~DownloadsGetFileIconFunction() {} |
880 | 734 |
881 void DownloadsGetFileIconFunction::SetIconExtractorForTesting( | 735 void DownloadsGetFileIconFunction::SetIconExtractorForTesting( |
882 DownloadFileIconExtractor* extractor) { | 736 DownloadFileIconExtractor* extractor) { |
883 DCHECK(extractor); | 737 DCHECK(extractor); |
884 icon_extractor_.reset(extractor); | 738 icon_extractor_.reset(extractor); |
885 } | 739 } |
886 | 740 |
887 bool DownloadsGetFileIconFunction::ParseArgs() { | 741 bool DownloadsGetFileIconFunction::RunImpl() { |
888 int dl_id = 0; | 742 scoped_ptr<extensions::api::downloads::GetFileIcon::Params> params( |
889 EXTENSION_FUNCTION_VALIDATE(args_->GetInteger(0, &dl_id)); | 743 extensions::api::downloads::GetFileIcon::Params::Create(*args_)); |
890 | 744 EXTENSION_FUNCTION_VALIDATE(params.get()); |
891 base::DictionaryValue* options = NULL; | 745 UMA_HISTOGRAM_ENUMERATION("Download.ApiFunctions", |
892 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(1, &options)); | 746 DOWNLOADS_FUNCTION_GET_FILE_ICON, |
893 if (options->HasKey(kSizeKey)) { | 747 DOWNLOADS_FUNCTION_LAST); |
894 EXTENSION_FUNCTION_VALIDATE(options->GetInteger(kSizeKey, &icon_size_)); | 748 const extensions::api::downloads::GetFileIconOptions* options = |
895 // We only support 16px and 32px icons. This is enforced in | 749 params->options.get(); |
896 // experimental.downloads.json. | 750 int icon_size = kDefaultIconSize; |
897 DCHECK(icon_size_ == 16 || icon_size_ == 32); | 751 if (options && options->size.get()) |
898 } | 752 icon_size = *options->size.get(); |
899 | |
900 DownloadManager* manager = NULL; | 753 DownloadManager* manager = NULL; |
901 DownloadManager* incognito_manager = NULL; | 754 DownloadManager* incognito_manager = NULL; |
902 GetManagers(profile(), include_incognito(), &manager, &incognito_manager); | 755 GetManagers(profile(), include_incognito(), &manager, &incognito_manager); |
903 DownloadItem* download_item = manager->GetDownloadItem(dl_id); | 756 DownloadItem* download_item = manager->GetDownloadItem(params->download_id); |
904 if (!download_item && incognito_manager) | 757 if (!download_item && incognito_manager) |
905 download_item = incognito_manager->GetDownloadItem(dl_id); | 758 download_item = incognito_manager->GetDownloadItem(params->download_id); |
906 if (!download_item) { | 759 if (!download_item) { |
907 // The DownloadItem is is added to history when the path is determined. If | 760 // The DownloadItem is is added to history when the path is determined. If |
908 // the download is not in history, then we don't have a path / final | 761 // the download is not in history, then we don't have a path / final |
909 // filename and no icon. | 762 // filename and no icon. |
910 error_ = download_extension_errors::kInvalidOperationError; | 763 error_ = download_extension_errors::kInvalidOperationError; |
911 return false; | 764 return false; |
912 } | 765 } |
913 // In-progress downloads return the intermediate filename for GetFullPath() | 766 // In-progress downloads return the intermediate filename for GetFullPath() |
914 // which doesn't have the final extension. Therefore we won't be able to | 767 // which doesn't have the final extension. Therefore we won't be able to |
915 // derive a good file icon for it. So we use GetTargetFilePath() instead. | 768 // derive a good file icon for it. So we use GetTargetFilePath() instead. |
916 path_ = download_item->GetTargetFilePath(); | 769 FilePath path = download_item->GetTargetFilePath(); |
917 DCHECK(!path_.empty()); | 770 DCHECK(!path.empty()); |
918 return true; | |
919 } | |
920 | |
921 bool DownloadsGetFileIconFunction::RunInternal() { | |
922 DCHECK(!path_.empty()); | |
923 DCHECK(icon_extractor_.get()); | 771 DCHECK(icon_extractor_.get()); |
| 772 DCHECK(icon_size == 16 || icon_size == 32); |
924 EXTENSION_FUNCTION_VALIDATE(icon_extractor_->ExtractIconURLForPath( | 773 EXTENSION_FUNCTION_VALIDATE(icon_extractor_->ExtractIconURLForPath( |
925 path_, IconLoaderSizeFromPixelSize(icon_size_), | 774 path, IconLoaderSizeFromPixelSize(icon_size), |
926 base::Bind(&DownloadsGetFileIconFunction::OnIconURLExtracted, this))); | 775 base::Bind(&DownloadsGetFileIconFunction::OnIconURLExtracted, this))); |
927 return true; | 776 return true; |
928 } | 777 } |
929 | 778 |
930 void DownloadsGetFileIconFunction::OnIconURLExtracted(const std::string& url) { | 779 void DownloadsGetFileIconFunction::OnIconURLExtracted(const std::string& url) { |
931 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 780 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
932 if (url.empty()) | 781 if (url.empty()) |
933 error_ = download_extension_errors::kIconNotFoundError; | 782 error_ = download_extension_errors::kIconNotFoundError; |
934 else | 783 else |
935 result_.reset(base::Value::CreateStringValue(url)); | 784 result_.reset(base::Value::CreateStringValue(url)); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1010 // set the differences in the |delta| object and remember that something | 859 // set the differences in the |delta| object and remember that something |
1011 // significant changed. | 860 // significant changed. |
1012 for (base::DictionaryValue::Iterator iter(*new_json.get()); | 861 for (base::DictionaryValue::Iterator iter(*new_json.get()); |
1013 iter.HasNext(); iter.Advance()) { | 862 iter.HasNext(); iter.Advance()) { |
1014 new_fields.insert(iter.key()); | 863 new_fields.insert(iter.key()); |
1015 if (iter.key() != kBytesReceivedKey) { | 864 if (iter.key() != kBytesReceivedKey) { |
1016 base::Value* old_value = NULL; | 865 base::Value* old_value = NULL; |
1017 if (!old_json->HasKey(iter.key()) || | 866 if (!old_json->HasKey(iter.key()) || |
1018 (old_json->Get(iter.key(), &old_value) && | 867 (old_json->Get(iter.key(), &old_value) && |
1019 !iter.value().Equals(old_value))) { | 868 !iter.value().Equals(old_value))) { |
1020 delta->Set(iter.key() + ".new", iter.value().DeepCopy()); | 869 delta->Set(iter.key() + ".current", iter.value().DeepCopy()); |
1021 if (old_value) | 870 if (old_value) |
1022 delta->Set(iter.key() + ".old", old_value->DeepCopy()); | 871 delta->Set(iter.key() + ".previous", old_value->DeepCopy()); |
1023 changed = true; | 872 changed = true; |
1024 } | 873 } |
1025 } | 874 } |
1026 } | 875 } |
1027 | 876 |
1028 // If a field was in the previous json but is not in the new json, set the | 877 // If a field was in the previous json but is not in the new json, set the |
1029 // difference in |delta|. | 878 // difference in |delta|. |
1030 for (base::DictionaryValue::Iterator iter(*old_json); | 879 for (base::DictionaryValue::Iterator iter(*old_json); |
1031 iter.HasNext(); iter.Advance()) { | 880 iter.HasNext(); iter.Advance()) { |
1032 if (new_fields.find(iter.key()) == new_fields.end()) { | 881 if (new_fields.find(iter.key()) == new_fields.end()) { |
1033 delta->Set(iter.key() + ".old", iter.value().DeepCopy()); | 882 delta->Set(iter.key() + ".previous", iter.value().DeepCopy()); |
1034 changed = true; | 883 changed = true; |
1035 } | 884 } |
1036 } | 885 } |
1037 | 886 |
1038 // Update the OnChangedStat and dispatch the event if something significant | 887 // Update the OnChangedStat and dispatch the event if something significant |
1039 // changed. Replace the stored json with the new json. | 888 // changed. Replace the stored json with the new json. |
1040 ++(on_changed_stats_[download_id]->total); | 889 ++(on_changed_stats_[download_id]->total); |
1041 if (changed) { | 890 if (changed) { |
1042 DispatchEvent(extension_event_names::kOnDownloadChanged, delta.release()); | 891 DispatchEvent(extension_event_names::kOnDownloadChanged, delta.release()); |
1043 ++(on_changed_stats_[download_id]->fires); | 892 ++(on_changed_stats_[download_id]->fires); |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1112 ListValue args; | 961 ListValue args; |
1113 args.Append(arg); | 962 args.Append(arg); |
1114 std::string json_args; | 963 std::string json_args; |
1115 base::JSONWriter::Write(&args, &json_args); | 964 base::JSONWriter::Write(&args, &json_args); |
1116 profile_->GetExtensionEventRouter()->DispatchEventToRenderers( | 965 profile_->GetExtensionEventRouter()->DispatchEventToRenderers( |
1117 event_name, | 966 event_name, |
1118 json_args, | 967 json_args, |
1119 profile_, | 968 profile_, |
1120 GURL()); | 969 GURL()); |
1121 } | 970 } |
OLD | NEW |