| Index: chrome/browser/extensions/api/downloads/downloads_api.cc
|
| diff --git a/chrome/browser/extensions/api/downloads/downloads_api.cc b/chrome/browser/extensions/api/downloads/downloads_api.cc
|
| index 7273640ba14c7b2e9a24784fdc63b51bb7fc7c87..dc0a0a771df5c2a71efc0b484431d775d83201ca 100644
|
| --- a/chrome/browser/extensions/api/downloads/downloads_api.cc
|
| +++ b/chrome/browser/extensions/api/downloads/downloads_api.cc
|
| @@ -29,6 +29,7 @@
|
| #include "chrome/browser/browser_process.h"
|
| #include "chrome/browser/download/download_danger_prompt.h"
|
| #include "chrome/browser/download/download_file_icon_extractor.h"
|
| +#include "chrome/browser/download/download_prefs.h"
|
| #include "chrome/browser/download/download_query.h"
|
| #include "chrome/browser/download/download_service.h"
|
| #include "chrome/browser/download/download_service_factory.h"
|
| @@ -42,6 +43,7 @@
|
| #include "chrome/browser/extensions/extension_system.h"
|
| #include "chrome/browser/icon_loader.h"
|
| #include "chrome/browser/icon_manager.h"
|
| +#include "chrome/browser/platform_util.h"
|
| #include "chrome/browser/renderer_host/chrome_render_message_filter.h"
|
| #include "chrome/browser/ui/browser.h"
|
| #include "chrome/common/cancelable_task_tracker.h"
|
| @@ -87,6 +89,8 @@ const char kInvalidOrderByError[] = "Invalid orderBy field";
|
| const char kInvalidQueryLimit[] = "Invalid query limit";
|
| const char kInvalidStateError[] = "Invalid state";
|
| const char kInvalidURLError[] = "Invalid URL";
|
| +const char kNotPermittedURLError[] = "In order to access that URL, this "
|
| + "extension must add the host to \"permissions\" in manifest.json";
|
| const char kNotImplementedError[] = "NotImplemented";
|
| const char kTooManyListenersError[] = "Each extension may have at most one "
|
| "onDeterminingFilename listener between all of its renderer execution "
|
| @@ -101,19 +105,20 @@ const int kDefaultIconSize = 32;
|
|
|
| // Parameter keys
|
| const char kBytesReceivedKey[] = "bytesReceived";
|
| -const char kDangerAcceptedKey[] = "dangerAccepted";
|
| +const char kCanResumeKey[] = "canResume";
|
| +const char kDangerAccepted[] = "accepted";
|
| const char kDangerContent[] = "content";
|
| const char kDangerFile[] = "file";
|
| +const char kDangerHost[] = "host";
|
| const char kDangerKey[] = "danger";
|
| const char kDangerSafe[] = "safe";
|
| const char kDangerUncommon[] = "uncommon";
|
| -const char kDangerAccepted[] = "accepted";
|
| -const char kDangerHost[] = "host";
|
| const char kDangerUrl[] = "url";
|
| const char kEndTimeKey[] = "endTime";
|
| const char kEndedAfterKey[] = "endedAfter";
|
| const char kEndedBeforeKey[] = "endedBefore";
|
| const char kErrorKey[] = "error";
|
| +const char kEstimatedEndTimeKey[] = "estimatedEndTime";
|
| const char kExistsKey[] = "exists";
|
| const char kFileSizeKey[] = "fileSize";
|
| const char kFilenameKey[] = "filename";
|
| @@ -123,6 +128,7 @@ const char kIncognito[] = "incognito";
|
| const char kMimeKey[] = "mime";
|
| const char kPausedKey[] = "paused";
|
| const char kQueryKey[] = "query";
|
| +const char kReferrerUrlKey[] = "referrer";
|
| const char kStartTimeKey[] = "startTime";
|
| const char kStartedAfterKey[] = "startedAfter";
|
| const char kStartedBeforeKey[] = "startedBefore";
|
| @@ -215,15 +221,14 @@ scoped_ptr<base::DictionaryValue> DownloadItemToJSON(
|
| json->SetInteger(kIdKey, download_item->GetId());
|
| const GURL& url = download_item->GetOriginalUrl();
|
| json->SetString(kUrlKey, (url.is_valid() ? url.spec() : std::string()));
|
| + const GURL& referrer = download_item->GetReferrerUrl();
|
| + json->SetString(kReferrerUrlKey, (referrer.is_valid() ? referrer.spec()
|
| + : std::string()));
|
| json->SetString(kFilenameKey,
|
| download_item->GetTargetFilePath().LossyDisplayName());
|
| json->SetString(kDangerKey, DangerString(download_item->GetDangerType()));
|
| - if (download_item->GetDangerType() !=
|
| - content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)
|
| - json->SetBoolean(kDangerAcceptedKey,
|
| - download_item->GetDangerType() ==
|
| - content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED);
|
| json->SetString(kStateKey, StateString(download_item->GetState()));
|
| + json->SetBoolean(kCanResumeKey, download_item->CanResume());
|
| json->SetBoolean(kPausedKey, download_item->IsPaused());
|
| json->SetString(kMimeKey, download_item->GetMimeType());
|
| json->SetString(kStartTimeKey, TimeToISO8601(download_item->GetStartTime()));
|
| @@ -239,6 +244,11 @@ scoped_ptr<base::DictionaryValue> DownloadItemToJSON(
|
| }
|
| if (!download_item->GetEndTime().is_null())
|
| json->SetString(kEndTimeKey, TimeToISO8601(download_item->GetEndTime()));
|
| + base::TimeDelta time_remaining;
|
| + if (download_item->TimeRemaining(&time_remaining)) {
|
| + base::Time now = base::Time::Now();
|
| + json->SetString(kEstimatedEndTimeKey, TimeToISO8601(now + time_remaining));
|
| + }
|
| // TODO(benjhayden): Implement fileSize.
|
| json->SetInteger(kFileSizeKey, download_item->GetTotalBytes());
|
| return scoped_ptr<base::DictionaryValue>(json);
|
| @@ -299,7 +309,6 @@ typedef base::hash_map<std::string, DownloadQuery::FilterType> FilterTypeMap;
|
|
|
| void InitFilterTypeMap(FilterTypeMap& filter_types) {
|
| filter_types[kBytesReceivedKey] = DownloadQuery::FILTER_BYTES_RECEIVED;
|
| - filter_types[kDangerAcceptedKey] = DownloadQuery::FILTER_DANGER_ACCEPTED;
|
| filter_types[kExistsKey] = DownloadQuery::FILTER_EXISTS;
|
| filter_types[kFilenameKey] = DownloadQuery::FILTER_FILENAME;
|
| filter_types[kFilenameRegexKey] = DownloadQuery::FILTER_FILENAME_REGEX;
|
| @@ -325,7 +334,6 @@ typedef base::hash_map<std::string, DownloadQuery::SortType> SortTypeMap;
|
| void InitSortTypeMap(SortTypeMap& sorter_types) {
|
| sorter_types[kBytesReceivedKey] = DownloadQuery::SORT_BYTES_RECEIVED;
|
| sorter_types[kDangerKey] = DownloadQuery::SORT_DANGER;
|
| - sorter_types[kDangerAcceptedKey] = DownloadQuery::SORT_DANGER_ACCEPTED;
|
| sorter_types[kEndTimeKey] = DownloadQuery::SORT_END_TIME;
|
| sorter_types[kExistsKey] = DownloadQuery::SORT_EXISTS;
|
| sorter_types[kFilenameKey] = DownloadQuery::SORT_FILENAME;
|
| @@ -807,13 +815,15 @@ bool DownloadsDownloadFunction::RunImpl() {
|
| EXTENSION_FUNCTION_VALIDATE(params.get());
|
| const extensions::api::downloads::DownloadOptions& options = params->options;
|
| GURL download_url(options.url);
|
| - if (!download_url.is_valid() ||
|
| - (!download_url.SchemeIs("data") &&
|
| - download_url.GetOrigin() != GetExtension()->url().GetOrigin() &&
|
| - !extensions::PermissionsData::HasHostPermission(GetExtension(),
|
| - download_url))) {
|
| + if (!download_url.is_valid()) {
|
| error_ = download_extension_errors::kInvalidURLError;
|
| return false;
|
| + } else if (!download_url.SchemeIs("data") &&
|
| + download_url.GetOrigin() != GetExtension()->url().GetOrigin() &&
|
| + !extensions::PermissionsData::HasHostPermission(GetExtension(),
|
| + download_url)) {
|
| + error_ = download_extension_errors::kNotPermittedURLError;
|
| + return false;
|
| }
|
|
|
| Profile* current_profile = profile();
|
| @@ -1063,19 +1073,29 @@ bool DownloadsAcceptDangerFunction::RunImpl() {
|
| base::Bind(&DownloadsAcceptDangerFunction::DangerPromptCallback,
|
| this, true, params->download_id),
|
| base::Bind(&DownloadsAcceptDangerFunction::DangerPromptCallback,
|
| - this, false, params->download_id));
|
| + this, false, params->download_id),
|
| + base::Bind(&DownloadsAcceptDangerFunction::DangerPromptDestroyed,
|
| + this));
|
| // DownloadDangerPrompt deletes itself
|
| return true;
|
| }
|
|
|
| void DownloadsAcceptDangerFunction::DangerPromptCallback(
|
| bool accept, int download_id) {
|
| + DownloadItem* download_item = GetDownloadIfInProgress(
|
| + profile(), include_incognito(), download_id);
|
| + if (!download_item) {
|
| + error_ = download_extension_errors::kInvalidOperationError;
|
| + return;
|
| + }
|
| if (accept) {
|
| - DownloadItem* download_item = GetDownloadIfInProgress(
|
| - profile(), include_incognito(), download_id);
|
| - if (download_item)
|
| - download_item->ValidateDangerousDownload();
|
| + download_item->ValidateDangerousDownload();
|
| + } else {
|
| + download_item->Remove();
|
| }
|
| +}
|
| +
|
| +void DownloadsAcceptDangerFunction::DangerPromptDestroyed() {
|
| SendResponse(error_.empty());
|
| }
|
|
|
| @@ -1087,13 +1107,21 @@ bool DownloadsShowFunction::RunImpl() {
|
| scoped_ptr<extensions::api::downloads::Show::Params> params(
|
| extensions::api::downloads::Show::Params::Create(*args_));
|
| EXTENSION_FUNCTION_VALIDATE(params.get());
|
| - DownloadItem* download_item = GetDownload(
|
| - profile(), include_incognito(), params->download_id);
|
| - if (!download_item) {
|
| - error_ = download_extension_errors::kInvalidOperationError;
|
| - return false;
|
| + if (params->download_id) {
|
| + DownloadItem* download_item = GetDownload(
|
| + profile(), include_incognito(), *params->download_id);
|
| + if (!download_item) {
|
| + error_ = download_extension_errors::kInvalidOperationError;
|
| + return false;
|
| + }
|
| + download_item->ShowDownloadInShell();
|
| + } else {
|
| + DownloadManager* manager = NULL;
|
| + DownloadManager* incognito_manager = NULL;
|
| + GetManagers(profile(), include_incognito(), &manager, &incognito_manager);
|
| + platform_util::OpenItem(DownloadPrefs::FromDownloadManager(
|
| + manager)->DownloadPath());
|
| }
|
| - download_item->ShowDownloadInShell();
|
| RecordApiFunctions(DOWNLOADS_FUNCTION_SHOW);
|
| return true;
|
| }
|
| @@ -1428,7 +1456,8 @@ void ExtensionDownloadsEventRouter::OnDownloadUpdated(
|
| for (base::DictionaryValue::Iterator iter(*new_json.get());
|
| !iter.IsAtEnd(); iter.Advance()) {
|
| new_fields.insert(iter.key());
|
| - if (iter.key() != kBytesReceivedKey) {
|
| + if ((iter.key() != kBytesReceivedKey) &&
|
| + (iter.key() != kEstimatedEndTimeKey)) {
|
| const base::Value* old_value = NULL;
|
| if (!data->json().HasKey(iter.key()) ||
|
| (data->json().Get(iter.key(), &old_value) &&
|
| @@ -1445,7 +1474,9 @@ void ExtensionDownloadsEventRouter::OnDownloadUpdated(
|
| // difference in |delta|.
|
| for (base::DictionaryValue::Iterator iter(data->json());
|
| !iter.IsAtEnd(); iter.Advance()) {
|
| - if (new_fields.find(iter.key()) == new_fields.end()) {
|
| + if ((new_fields.find(iter.key()) == new_fields.end()) &&
|
| + (iter.key() != kEstimatedEndTimeKey)) {
|
| + // estimatedEndTime disappears after completion, but bytesReceived stays.
|
| delta->Set(iter.key() + ".previous", iter.value().DeepCopy());
|
| changed = true;
|
| }
|
|
|