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