Chromium Code Reviews| 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/extensions/api/downloads/downloads_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" |
| 16 #include "base/callback.h" | 16 #include "base/callback.h" |
| 17 #include "base/file_util.h" | |
| 17 #include "base/files/file_path.h" | 18 #include "base/files/file_path.h" |
| 18 #include "base/json/json_writer.h" | 19 #include "base/json/json_writer.h" |
| 19 #include "base/lazy_instance.h" | 20 #include "base/lazy_instance.h" |
| 20 #include "base/logging.h" | 21 #include "base/logging.h" |
| 21 #include "base/memory/weak_ptr.h" | 22 #include "base/memory/weak_ptr.h" |
| 22 #include "base/metrics/histogram.h" | 23 #include "base/metrics/histogram.h" |
| 23 #include "base/stl_util.h" | 24 #include "base/stl_util.h" |
| 24 #include "base/strings/string16.h" | 25 #include "base/strings/string16.h" |
| 25 #include "base/strings/string_split.h" | 26 #include "base/strings/string_split.h" |
| 26 #include "base/strings/string_util.h" | 27 #include "base/strings/string_util.h" |
| 27 #include "base/strings/stringprintf.h" | 28 #include "base/strings/stringprintf.h" |
| 28 #include "base/values.h" | 29 #include "base/values.h" |
| 29 #include "chrome/browser/browser_process.h" | 30 #include "chrome/browser/browser_process.h" |
| 30 #include "chrome/browser/chrome_notification_types.h" | 31 #include "chrome/browser/chrome_notification_types.h" |
| 31 #include "chrome/browser/download/download_danger_prompt.h" | 32 #include "chrome/browser/download/download_danger_prompt.h" |
| 32 #include "chrome/browser/download/download_file_icon_extractor.h" | 33 #include "chrome/browser/download/download_file_icon_extractor.h" |
| 34 #include "chrome/browser/download/download_prefs.h" | |
| 33 #include "chrome/browser/download/download_query.h" | 35 #include "chrome/browser/download/download_query.h" |
| 34 #include "chrome/browser/download/download_service.h" | 36 #include "chrome/browser/download/download_service.h" |
| 35 #include "chrome/browser/download/download_service_factory.h" | 37 #include "chrome/browser/download/download_service_factory.h" |
| 38 #include "chrome/browser/download/download_shelf.h" | |
| 36 #include "chrome/browser/download/download_util.h" | 39 #include "chrome/browser/download/download_util.h" |
| 37 #include "chrome/browser/extensions/event_names.h" | 40 #include "chrome/browser/extensions/event_names.h" |
| 38 #include "chrome/browser/extensions/event_router.h" | 41 #include "chrome/browser/extensions/event_router.h" |
| 39 #include "chrome/browser/extensions/extension_function_dispatcher.h" | 42 #include "chrome/browser/extensions/extension_function_dispatcher.h" |
| 40 #include "chrome/browser/extensions/extension_info_map.h" | 43 #include "chrome/browser/extensions/extension_info_map.h" |
| 41 #include "chrome/browser/extensions/extension_prefs.h" | 44 #include "chrome/browser/extensions/extension_prefs.h" |
| 42 #include "chrome/browser/extensions/extension_service.h" | 45 #include "chrome/browser/extensions/extension_service.h" |
| 43 #include "chrome/browser/extensions/extension_system.h" | 46 #include "chrome/browser/extensions/extension_system.h" |
| 44 #include "chrome/browser/icon_loader.h" | 47 #include "chrome/browser/icon_loader.h" |
| 45 #include "chrome/browser/icon_manager.h" | 48 #include "chrome/browser/icon_manager.h" |
| 49 #include "chrome/browser/platform_util.h" | |
| 46 #include "chrome/browser/renderer_host/chrome_render_message_filter.h" | 50 #include "chrome/browser/renderer_host/chrome_render_message_filter.h" |
| 47 #include "chrome/browser/ui/browser.h" | 51 #include "chrome/browser/ui/browser.h" |
| 52 #include "chrome/browser/ui/browser_window.h" | |
| 48 #include "chrome/common/cancelable_task_tracker.h" | 53 #include "chrome/common/cancelable_task_tracker.h" |
| 49 #include "chrome/common/extensions/api/downloads.h" | 54 #include "chrome/common/extensions/api/downloads.h" |
| 50 #include "chrome/common/extensions/permissions/permissions_data.h" | 55 #include "chrome/common/extensions/permissions/permissions_data.h" |
| 51 #include "content/public/browser/download_interrupt_reasons.h" | 56 #include "content/public/browser/download_interrupt_reasons.h" |
| 52 #include "content/public/browser/download_item.h" | 57 #include "content/public/browser/download_item.h" |
| 53 #include "content/public/browser/download_save_info.h" | 58 #include "content/public/browser/download_save_info.h" |
| 54 #include "content/public/browser/download_url_parameters.h" | 59 #include "content/public/browser/download_url_parameters.h" |
| 55 #include "content/public/browser/notification_service.h" | 60 #include "content/public/browser/notification_service.h" |
| 56 #include "content/public/browser/render_process_host.h" | 61 #include "content/public/browser/render_process_host.h" |
| 57 #include "content/public/browser/render_view_host.h" | 62 #include "content/public/browser/render_view_host.h" |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 68 | 73 |
| 69 namespace events = extensions::event_names; | 74 namespace events = extensions::event_names; |
| 70 | 75 |
| 71 using content::BrowserContext; | 76 using content::BrowserContext; |
| 72 using content::BrowserThread; | 77 using content::BrowserThread; |
| 73 using content::DownloadItem; | 78 using content::DownloadItem; |
| 74 using content::DownloadManager; | 79 using content::DownloadManager; |
| 75 | 80 |
| 76 namespace download_extension_errors { | 81 namespace download_extension_errors { |
| 77 | 82 |
| 78 // Error messages | 83 const char kEmptyFile[] = "Filename not yet determined"; |
| 79 const char kGenericError[] = "I'm afraid I can't do that"; | 84 const char kFileAlreadyDeleted[] = "Download file already deleted"; |
| 80 const char kIconNotFoundError[] = "Icon not found"; | 85 const char kIconNotFound[] = "Icon not found"; |
| 81 const char kInvalidDangerTypeError[] = "Invalid danger type"; | 86 const char kInvalidDangerType[] = "Invalid danger type"; |
| 82 const char kInvalidFilenameError[] = "Invalid filename"; | 87 const char kInvalidFilename[] = "Invalid filename"; |
| 83 const char kInvalidFilterError[] = "Invalid query filter"; | 88 const char kInvalidFilter[] = "Invalid query filter"; |
| 84 const char kInvalidOperationError[] = "Invalid operation"; | 89 const char kInvalidHeader[] = "Invalid request header"; |
| 85 const char kInvalidOrderByError[] = "Invalid orderBy field"; | 90 const char kInvalidId[] = "Invalid downloadId"; |
| 91 const char kInvalidOrderBy[] = "Invalid orderBy field"; | |
| 86 const char kInvalidQueryLimit[] = "Invalid query limit"; | 92 const char kInvalidQueryLimit[] = "Invalid query limit"; |
| 87 const char kInvalidStateError[] = "Invalid state"; | 93 const char kInvalidState[] = "Invalid state"; |
| 88 const char kInvalidURLError[] = "Invalid URL"; | 94 const char kInvalidURL[] = "Invalid URL"; |
| 89 const char kNotImplementedError[] = "NotImplemented"; | 95 const char kInvisibleContext[] = "Javascript execution context is not visible " |
| 90 const char kTooManyListenersError[] = "Each extension may have at most one " | 96 "(tab, window, popup bubble)"; |
| 97 const char kNotComplete[] = "Download must be complete"; | |
| 98 const char kNotDangerous[] = "Download must be dangerous"; | |
| 99 const char kNotImplemented[] = "NotImplemented"; | |
| 100 const char kNotInProgress[] = "Download must be in progress"; | |
| 101 const char kNotPermittedURL[] = "In order to access that URL, this extension " | |
| 102 "must add the host to \"permissions\" in manifest.json"; | |
| 103 const char kNotResumable[] = "DownloadItem.canResume must be true"; | |
| 104 const char kOpenPermission[] = "The \"downloads.open\" permission is required"; | |
| 105 const char kTooManyListeners[] = "Each extension may have at most one " | |
| 91 "onDeterminingFilename listener between all of its renderer execution " | 106 "onDeterminingFilename listener between all of its renderer execution " |
| 92 "contexts."; | 107 "contexts."; |
| 108 const char kUnexpectedDeterminer[] = "Unexpected determineFilename call"; | |
| 93 | 109 |
| 94 } // namespace download_extension_errors | 110 } // namespace download_extension_errors |
| 95 | 111 |
| 112 namespace errors = download_extension_errors; | |
| 113 | |
| 96 namespace { | 114 namespace { |
| 97 | 115 |
| 98 // Default icon size for getFileIcon() in pixels. | 116 // Default icon size for getFileIcon() in pixels. |
| 99 const int kDefaultIconSize = 32; | 117 const int kDefaultIconSize = 32; |
| 100 | 118 |
| 101 // Parameter keys | 119 // Parameter keys |
| 102 const char kBytesReceivedKey[] = "bytesReceived"; | 120 const char kBytesReceivedKey[] = "bytesReceived"; |
| 103 const char kDangerAcceptedKey[] = "dangerAccepted"; | 121 const char kCanResumeKey[] = "canResume"; |
| 122 const char kDangerAccepted[] = "accepted"; | |
| 104 const char kDangerContent[] = "content"; | 123 const char kDangerContent[] = "content"; |
| 105 const char kDangerFile[] = "file"; | 124 const char kDangerFile[] = "file"; |
| 125 const char kDangerHost[] = "host"; | |
| 106 const char kDangerKey[] = "danger"; | 126 const char kDangerKey[] = "danger"; |
| 107 const char kDangerSafe[] = "safe"; | 127 const char kDangerSafe[] = "safe"; |
| 108 const char kDangerUncommon[] = "uncommon"; | 128 const char kDangerUncommon[] = "uncommon"; |
| 109 const char kDangerUnwanted[] = "unwanted"; | 129 const char kDangerUnwanted[] = "unwanted"; |
| 110 const char kDangerAccepted[] = "accepted"; | |
| 111 const char kDangerHost[] = "host"; | |
| 112 const char kDangerUrl[] = "url"; | 130 const char kDangerUrl[] = "url"; |
| 113 const char kEndTimeKey[] = "endTime"; | 131 const char kEndTimeKey[] = "endTime"; |
| 114 const char kEndedAfterKey[] = "endedAfter"; | 132 const char kEndedAfterKey[] = "endedAfter"; |
| 115 const char kEndedBeforeKey[] = "endedBefore"; | 133 const char kEndedBeforeKey[] = "endedBefore"; |
| 116 const char kErrorKey[] = "error"; | 134 const char kErrorKey[] = "error"; |
| 135 const char kEstimatedEndTimeKey[] = "estimatedEndTime"; | |
| 117 const char kExistsKey[] = "exists"; | 136 const char kExistsKey[] = "exists"; |
| 118 const char kFileSizeKey[] = "fileSize"; | 137 const char kFileSizeKey[] = "fileSize"; |
| 119 const char kFilenameKey[] = "filename"; | 138 const char kFilenameKey[] = "filename"; |
| 120 const char kFilenameRegexKey[] = "filenameRegex"; | 139 const char kFilenameRegexKey[] = "filenameRegex"; |
| 121 const char kIdKey[] = "id"; | 140 const char kIdKey[] = "id"; |
| 122 const char kIncognito[] = "incognito"; | 141 const char kIncognitoKey[] = "incognito"; |
| 123 const char kMimeKey[] = "mime"; | 142 const char kMimeKey[] = "mime"; |
| 124 const char kPausedKey[] = "paused"; | 143 const char kPausedKey[] = "paused"; |
| 125 const char kQueryKey[] = "query"; | 144 const char kQueryKey[] = "query"; |
| 145 const char kReferrerUrlKey[] = "referrer"; | |
| 126 const char kStartTimeKey[] = "startTime"; | 146 const char kStartTimeKey[] = "startTime"; |
| 127 const char kStartedAfterKey[] = "startedAfter"; | 147 const char kStartedAfterKey[] = "startedAfter"; |
| 128 const char kStartedBeforeKey[] = "startedBefore"; | 148 const char kStartedBeforeKey[] = "startedBefore"; |
| 129 const char kStateComplete[] = "complete"; | 149 const char kStateComplete[] = "complete"; |
| 130 const char kStateInProgress[] = "in_progress"; | 150 const char kStateInProgress[] = "in_progress"; |
| 131 const char kStateInterrupted[] = "interrupted"; | 151 const char kStateInterrupted[] = "interrupted"; |
| 132 const char kStateKey[] = "state"; | 152 const char kStateKey[] = "state"; |
| 133 const char kTotalBytesGreaterKey[] = "totalBytesGreater"; | 153 const char kTotalBytesGreaterKey[] = "totalBytesGreater"; |
| 134 const char kTotalBytesKey[] = "totalBytes"; | 154 const char kTotalBytesKey[] = "totalBytes"; |
| 135 const char kTotalBytesLessKey[] = "totalBytesLess"; | 155 const char kTotalBytesLessKey[] = "totalBytesLess"; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 209 } | 229 } |
| 210 | 230 |
| 211 scoped_ptr<base::DictionaryValue> DownloadItemToJSON( | 231 scoped_ptr<base::DictionaryValue> DownloadItemToJSON( |
| 212 DownloadItem* download_item, | 232 DownloadItem* download_item, |
| 213 bool incognito) { | 233 bool incognito) { |
| 214 base::DictionaryValue* json = new base::DictionaryValue(); | 234 base::DictionaryValue* json = new base::DictionaryValue(); |
| 215 json->SetBoolean(kExistsKey, !download_item->GetFileExternallyRemoved()); | 235 json->SetBoolean(kExistsKey, !download_item->GetFileExternallyRemoved()); |
| 216 json->SetInteger(kIdKey, download_item->GetId()); | 236 json->SetInteger(kIdKey, download_item->GetId()); |
| 217 const GURL& url = download_item->GetOriginalUrl(); | 237 const GURL& url = download_item->GetOriginalUrl(); |
| 218 json->SetString(kUrlKey, (url.is_valid() ? url.spec() : std::string())); | 238 json->SetString(kUrlKey, (url.is_valid() ? url.spec() : std::string())); |
| 239 const GURL& referrer = download_item->GetReferrerUrl(); | |
| 240 json->SetString(kReferrerUrlKey, (referrer.is_valid() ? referrer.spec() | |
| 241 : std::string())); | |
| 219 json->SetString(kFilenameKey, | 242 json->SetString(kFilenameKey, |
| 220 download_item->GetTargetFilePath().LossyDisplayName()); | 243 download_item->GetTargetFilePath().LossyDisplayName()); |
| 221 json->SetString(kDangerKey, DangerString(download_item->GetDangerType())); | 244 json->SetString(kDangerKey, DangerString(download_item->GetDangerType())); |
| 222 if (download_item->GetDangerType() != | |
| 223 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) | |
| 224 json->SetBoolean(kDangerAcceptedKey, | |
| 225 download_item->GetDangerType() == | |
| 226 content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED); | |
| 227 json->SetString(kStateKey, StateString(download_item->GetState())); | 245 json->SetString(kStateKey, StateString(download_item->GetState())); |
| 246 json->SetBoolean(kCanResumeKey, download_item->CanResume()); | |
| 228 json->SetBoolean(kPausedKey, download_item->IsPaused()); | 247 json->SetBoolean(kPausedKey, download_item->IsPaused()); |
| 229 json->SetString(kMimeKey, download_item->GetMimeType()); | 248 json->SetString(kMimeKey, download_item->GetMimeType()); |
| 230 json->SetString(kStartTimeKey, TimeToISO8601(download_item->GetStartTime())); | 249 json->SetString(kStartTimeKey, TimeToISO8601(download_item->GetStartTime())); |
| 231 json->SetInteger(kBytesReceivedKey, download_item->GetReceivedBytes()); | 250 json->SetInteger(kBytesReceivedKey, download_item->GetReceivedBytes()); |
| 232 json->SetInteger(kTotalBytesKey, download_item->GetTotalBytes()); | 251 json->SetInteger(kTotalBytesKey, download_item->GetTotalBytes()); |
| 233 json->SetBoolean(kIncognito, incognito); | 252 json->SetBoolean(kIncognitoKey, incognito); |
| 234 if (download_item->GetState() == DownloadItem::INTERRUPTED) { | 253 if (download_item->GetState() == DownloadItem::INTERRUPTED) { |
| 235 json->SetInteger(kErrorKey, static_cast<int>( | 254 json->SetString(kErrorKey, content::InterruptReasonDebugString( |
| 236 download_item->GetLastReason())); | 255 download_item->GetLastReason())); |
| 237 } else if (download_item->GetState() == DownloadItem::CANCELLED) { | 256 } else if (download_item->GetState() == DownloadItem::CANCELLED) { |
| 238 json->SetInteger(kErrorKey, static_cast<int>( | 257 json->SetString(kErrorKey, content::InterruptReasonDebugString( |
| 239 content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED)); | 258 content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED)); |
| 240 } | 259 } |
| 241 if (!download_item->GetEndTime().is_null()) | 260 if (!download_item->GetEndTime().is_null()) |
| 242 json->SetString(kEndTimeKey, TimeToISO8601(download_item->GetEndTime())); | 261 json->SetString(kEndTimeKey, TimeToISO8601(download_item->GetEndTime())); |
| 262 base::TimeDelta time_remaining; | |
| 263 if (download_item->TimeRemaining(&time_remaining)) { | |
| 264 base::Time now = base::Time::Now(); | |
| 265 json->SetString(kEstimatedEndTimeKey, TimeToISO8601(now + time_remaining)); | |
| 266 } | |
| 243 // TODO(benjhayden): Implement fileSize. | 267 // TODO(benjhayden): Implement fileSize. |
| 244 json->SetInteger(kFileSizeKey, download_item->GetTotalBytes()); | 268 json->SetInteger(kFileSizeKey, download_item->GetTotalBytes()); |
| 245 return scoped_ptr<base::DictionaryValue>(json); | 269 return scoped_ptr<base::DictionaryValue>(json); |
| 246 } | 270 } |
| 247 | 271 |
| 248 class DownloadFileIconExtractorImpl : public DownloadFileIconExtractor { | 272 class DownloadFileIconExtractorImpl : public DownloadFileIconExtractor { |
| 249 public: | 273 public: |
| 250 DownloadFileIconExtractorImpl() {} | 274 DownloadFileIconExtractorImpl() {} |
| 251 | 275 |
| 252 virtual ~DownloadFileIconExtractorImpl() {} | 276 virtual ~DownloadFileIconExtractorImpl() {} |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 293 default: | 317 default: |
| 294 NOTREACHED(); | 318 NOTREACHED(); |
| 295 return IconLoader::NORMAL; | 319 return IconLoader::NORMAL; |
| 296 } | 320 } |
| 297 } | 321 } |
| 298 | 322 |
| 299 typedef base::hash_map<std::string, DownloadQuery::FilterType> FilterTypeMap; | 323 typedef base::hash_map<std::string, DownloadQuery::FilterType> FilterTypeMap; |
| 300 | 324 |
| 301 void InitFilterTypeMap(FilterTypeMap& filter_types) { | 325 void InitFilterTypeMap(FilterTypeMap& filter_types) { |
| 302 filter_types[kBytesReceivedKey] = DownloadQuery::FILTER_BYTES_RECEIVED; | 326 filter_types[kBytesReceivedKey] = DownloadQuery::FILTER_BYTES_RECEIVED; |
| 303 filter_types[kDangerAcceptedKey] = DownloadQuery::FILTER_DANGER_ACCEPTED; | |
| 304 filter_types[kExistsKey] = DownloadQuery::FILTER_EXISTS; | 327 filter_types[kExistsKey] = DownloadQuery::FILTER_EXISTS; |
| 305 filter_types[kFilenameKey] = DownloadQuery::FILTER_FILENAME; | 328 filter_types[kFilenameKey] = DownloadQuery::FILTER_FILENAME; |
| 306 filter_types[kFilenameRegexKey] = DownloadQuery::FILTER_FILENAME_REGEX; | 329 filter_types[kFilenameRegexKey] = DownloadQuery::FILTER_FILENAME_REGEX; |
| 307 filter_types[kMimeKey] = DownloadQuery::FILTER_MIME; | 330 filter_types[kMimeKey] = DownloadQuery::FILTER_MIME; |
| 308 filter_types[kPausedKey] = DownloadQuery::FILTER_PAUSED; | 331 filter_types[kPausedKey] = DownloadQuery::FILTER_PAUSED; |
| 309 filter_types[kQueryKey] = DownloadQuery::FILTER_QUERY; | 332 filter_types[kQueryKey] = DownloadQuery::FILTER_QUERY; |
| 310 filter_types[kEndedAfterKey] = DownloadQuery::FILTER_ENDED_AFTER; | 333 filter_types[kEndedAfterKey] = DownloadQuery::FILTER_ENDED_AFTER; |
| 311 filter_types[kEndedBeforeKey] = DownloadQuery::FILTER_ENDED_BEFORE; | 334 filter_types[kEndedBeforeKey] = DownloadQuery::FILTER_ENDED_BEFORE; |
| 312 filter_types[kEndTimeKey] = DownloadQuery::FILTER_END_TIME; | 335 filter_types[kEndTimeKey] = DownloadQuery::FILTER_END_TIME; |
| 313 filter_types[kStartedAfterKey] = DownloadQuery::FILTER_STARTED_AFTER; | 336 filter_types[kStartedAfterKey] = DownloadQuery::FILTER_STARTED_AFTER; |
| 314 filter_types[kStartedBeforeKey] = DownloadQuery::FILTER_STARTED_BEFORE; | 337 filter_types[kStartedBeforeKey] = DownloadQuery::FILTER_STARTED_BEFORE; |
| 315 filter_types[kStartTimeKey] = DownloadQuery::FILTER_START_TIME; | 338 filter_types[kStartTimeKey] = DownloadQuery::FILTER_START_TIME; |
| 316 filter_types[kTotalBytesKey] = DownloadQuery::FILTER_TOTAL_BYTES; | 339 filter_types[kTotalBytesKey] = DownloadQuery::FILTER_TOTAL_BYTES; |
| 317 filter_types[kTotalBytesGreaterKey] = | 340 filter_types[kTotalBytesGreaterKey] = |
| 318 DownloadQuery::FILTER_TOTAL_BYTES_GREATER; | 341 DownloadQuery::FILTER_TOTAL_BYTES_GREATER; |
| 319 filter_types[kTotalBytesLessKey] = DownloadQuery::FILTER_TOTAL_BYTES_LESS; | 342 filter_types[kTotalBytesLessKey] = DownloadQuery::FILTER_TOTAL_BYTES_LESS; |
| 320 filter_types[kUrlKey] = DownloadQuery::FILTER_URL; | 343 filter_types[kUrlKey] = DownloadQuery::FILTER_URL; |
| 321 filter_types[kUrlRegexKey] = DownloadQuery::FILTER_URL_REGEX; | 344 filter_types[kUrlRegexKey] = DownloadQuery::FILTER_URL_REGEX; |
| 322 } | 345 } |
| 323 | 346 |
| 324 typedef base::hash_map<std::string, DownloadQuery::SortType> SortTypeMap; | 347 typedef base::hash_map<std::string, DownloadQuery::SortType> SortTypeMap; |
| 325 | 348 |
| 326 void InitSortTypeMap(SortTypeMap& sorter_types) { | 349 void InitSortTypeMap(SortTypeMap& sorter_types) { |
| 327 sorter_types[kBytesReceivedKey] = DownloadQuery::SORT_BYTES_RECEIVED; | 350 sorter_types[kBytesReceivedKey] = DownloadQuery::SORT_BYTES_RECEIVED; |
| 328 sorter_types[kDangerKey] = DownloadQuery::SORT_DANGER; | 351 sorter_types[kDangerKey] = DownloadQuery::SORT_DANGER; |
| 329 sorter_types[kDangerAcceptedKey] = DownloadQuery::SORT_DANGER_ACCEPTED; | |
| 330 sorter_types[kEndTimeKey] = DownloadQuery::SORT_END_TIME; | 352 sorter_types[kEndTimeKey] = DownloadQuery::SORT_END_TIME; |
| 331 sorter_types[kExistsKey] = DownloadQuery::SORT_EXISTS; | 353 sorter_types[kExistsKey] = DownloadQuery::SORT_EXISTS; |
| 332 sorter_types[kFilenameKey] = DownloadQuery::SORT_FILENAME; | 354 sorter_types[kFilenameKey] = DownloadQuery::SORT_FILENAME; |
| 333 sorter_types[kMimeKey] = DownloadQuery::SORT_MIME; | 355 sorter_types[kMimeKey] = DownloadQuery::SORT_MIME; |
| 334 sorter_types[kPausedKey] = DownloadQuery::SORT_PAUSED; | 356 sorter_types[kPausedKey] = DownloadQuery::SORT_PAUSED; |
| 335 sorter_types[kStartTimeKey] = DownloadQuery::SORT_START_TIME; | 357 sorter_types[kStartTimeKey] = DownloadQuery::SORT_START_TIME; |
| 336 sorter_types[kStateKey] = DownloadQuery::SORT_STATE; | 358 sorter_types[kStateKey] = DownloadQuery::SORT_STATE; |
| 337 sorter_types[kTotalBytesKey] = DownloadQuery::SORT_TOTAL_BYTES; | 359 sorter_types[kTotalBytesKey] = DownloadQuery::SORT_TOTAL_BYTES; |
| 338 sorter_types[kUrlKey] = DownloadQuery::SORT_URL; | 360 sorter_types[kUrlKey] = DownloadQuery::SORT_URL; |
| 339 } | 361 } |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 365 DownloadItem* GetDownload(Profile* profile, bool include_incognito, int id) { | 387 DownloadItem* GetDownload(Profile* profile, bool include_incognito, int id) { |
| 366 DownloadManager* manager = NULL; | 388 DownloadManager* manager = NULL; |
| 367 DownloadManager* incognito_manager = NULL; | 389 DownloadManager* incognito_manager = NULL; |
| 368 GetManagers(profile, include_incognito, &manager, &incognito_manager); | 390 GetManagers(profile, include_incognito, &manager, &incognito_manager); |
| 369 DownloadItem* download_item = manager->GetDownload(id); | 391 DownloadItem* download_item = manager->GetDownload(id); |
| 370 if (!download_item && incognito_manager) | 392 if (!download_item && incognito_manager) |
| 371 download_item = incognito_manager->GetDownload(id); | 393 download_item = incognito_manager->GetDownload(id); |
| 372 return download_item; | 394 return download_item; |
| 373 } | 395 } |
| 374 | 396 |
| 375 DownloadItem* GetDownloadIfInProgress( | |
| 376 Profile* profile, | |
| 377 bool include_incognito, | |
| 378 int id) { | |
| 379 DownloadItem* download_item = GetDownload(profile, include_incognito, id); | |
| 380 if (download_item && (download_item->GetState() == DownloadItem::IN_PROGRESS)) | |
| 381 return download_item; | |
| 382 return NULL; | |
| 383 } | |
| 384 | |
| 385 enum DownloadsFunctionName { | 397 enum DownloadsFunctionName { |
| 386 DOWNLOADS_FUNCTION_DOWNLOAD = 0, | 398 DOWNLOADS_FUNCTION_DOWNLOAD = 0, |
| 387 DOWNLOADS_FUNCTION_SEARCH = 1, | 399 DOWNLOADS_FUNCTION_SEARCH = 1, |
| 388 DOWNLOADS_FUNCTION_PAUSE = 2, | 400 DOWNLOADS_FUNCTION_PAUSE = 2, |
| 389 DOWNLOADS_FUNCTION_RESUME = 3, | 401 DOWNLOADS_FUNCTION_RESUME = 3, |
| 390 DOWNLOADS_FUNCTION_CANCEL = 4, | 402 DOWNLOADS_FUNCTION_CANCEL = 4, |
| 391 DOWNLOADS_FUNCTION_ERASE = 5, | 403 DOWNLOADS_FUNCTION_ERASE = 5, |
| 392 DOWNLOADS_FUNCTION_SET_DESTINATION = 6, | 404 DOWNLOADS_FUNCTION_SET_DESTINATION = 6, |
| 393 DOWNLOADS_FUNCTION_ACCEPT_DANGER = 7, | 405 DOWNLOADS_FUNCTION_ACCEPT_DANGER = 7, |
| 394 DOWNLOADS_FUNCTION_SHOW = 8, | 406 DOWNLOADS_FUNCTION_SHOW = 8, |
| 395 DOWNLOADS_FUNCTION_DRAG = 9, | 407 DOWNLOADS_FUNCTION_DRAG = 9, |
| 396 DOWNLOADS_FUNCTION_GET_FILE_ICON = 10, | 408 DOWNLOADS_FUNCTION_GET_FILE_ICON = 10, |
| 397 DOWNLOADS_FUNCTION_OPEN = 11, | 409 DOWNLOADS_FUNCTION_OPEN = 11, |
| 410 DOWNLOADS_FUNCTION_DELETE_FILE = 12, | |
| 411 DOWNLOADS_FUNCTION_SET_SHELF_VISIBLE = 13, | |
| 412 DOWNLOADS_FUNCTION_SHOW_DEFAULT_FOLDER = 14, | |
| 398 // Insert new values here, not at the beginning. | 413 // Insert new values here, not at the beginning. |
| 399 DOWNLOADS_FUNCTION_LAST | 414 DOWNLOADS_FUNCTION_LAST |
| 400 }; | 415 }; |
| 401 | 416 |
| 402 void RecordApiFunctions(DownloadsFunctionName function) { | 417 void RecordApiFunctions(DownloadsFunctionName function) { |
| 403 UMA_HISTOGRAM_ENUMERATION("Download.ApiFunctions", | 418 UMA_HISTOGRAM_ENUMERATION("Download.ApiFunctions", |
| 404 function, | 419 function, |
| 405 DOWNLOADS_FUNCTION_LAST); | 420 DOWNLOADS_FUNCTION_LAST); |
| 406 } | 421 } |
| 407 | 422 |
| 408 void CompileDownloadQueryOrderBy( | 423 void CompileDownloadQueryOrderBy( |
| 409 const std::string& order_by_str, std::string* error, DownloadQuery* query) { | 424 const std::vector<std::string>& order_by_strs, |
| 425 std::string* error, | |
| 426 DownloadQuery* query) { | |
| 410 // TODO(benjhayden): Consider switching from LazyInstance to explicit string | 427 // TODO(benjhayden): Consider switching from LazyInstance to explicit string |
| 411 // comparisons. | 428 // comparisons. |
| 412 static base::LazyInstance<SortTypeMap> sorter_types = | 429 static base::LazyInstance<SortTypeMap> sorter_types = |
| 413 LAZY_INSTANCE_INITIALIZER; | 430 LAZY_INSTANCE_INITIALIZER; |
| 414 if (sorter_types.Get().size() == 0) | 431 if (sorter_types.Get().size() == 0) |
| 415 InitSortTypeMap(sorter_types.Get()); | 432 InitSortTypeMap(sorter_types.Get()); |
| 416 | 433 |
| 417 std::vector<std::string> order_by_strs; | |
| 418 base::SplitString(order_by_str, ' ', &order_by_strs); | |
| 419 for (std::vector<std::string>::const_iterator iter = order_by_strs.begin(); | 434 for (std::vector<std::string>::const_iterator iter = order_by_strs.begin(); |
| 420 iter != order_by_strs.end(); ++iter) { | 435 iter != order_by_strs.end(); ++iter) { |
| 421 std::string term_str = *iter; | 436 std::string term_str = *iter; |
| 422 if (term_str.empty()) | 437 if (term_str.empty()) |
| 423 continue; | 438 continue; |
| 424 DownloadQuery::SortDirection direction = DownloadQuery::ASCENDING; | 439 DownloadQuery::SortDirection direction = DownloadQuery::ASCENDING; |
| 425 if (term_str[0] == '-') { | 440 if (term_str[0] == '-') { |
| 426 direction = DownloadQuery::DESCENDING; | 441 direction = DownloadQuery::DESCENDING; |
| 427 term_str = term_str.substr(1); | 442 term_str = term_str.substr(1); |
| 428 } | 443 } |
| 429 SortTypeMap::const_iterator sorter_type = | 444 SortTypeMap::const_iterator sorter_type = |
| 430 sorter_types.Get().find(term_str); | 445 sorter_types.Get().find(term_str); |
| 431 if (sorter_type == sorter_types.Get().end()) { | 446 if (sorter_type == sorter_types.Get().end()) { |
| 432 *error = download_extension_errors::kInvalidOrderByError; | 447 *error = errors::kInvalidOrderBy; |
| 433 return; | 448 return; |
| 434 } | 449 } |
| 435 query->AddSorter(sorter_type->second, direction); | 450 query->AddSorter(sorter_type->second, direction); |
| 436 } | 451 } |
| 437 } | 452 } |
| 438 | 453 |
| 439 void RunDownloadQuery( | 454 void RunDownloadQuery( |
| 440 const extensions::api::downloads::DownloadQuery& query_in, | 455 const extensions::api::downloads::DownloadQuery& query_in, |
| 441 DownloadManager* manager, | 456 DownloadManager* manager, |
| 442 DownloadManager* incognito_manager, | 457 DownloadManager* incognito_manager, |
| 443 std::string* error, | 458 std::string* error, |
| 444 DownloadQuery::DownloadVector* results) { | 459 DownloadQuery::DownloadVector* results) { |
| 445 // TODO(benjhayden): Consider switching from LazyInstance to explicit string | 460 // TODO(benjhayden): Consider switching from LazyInstance to explicit string |
| 446 // comparisons. | 461 // comparisons. |
| 447 static base::LazyInstance<FilterTypeMap> filter_types = | 462 static base::LazyInstance<FilterTypeMap> filter_types = |
| 448 LAZY_INSTANCE_INITIALIZER; | 463 LAZY_INSTANCE_INITIALIZER; |
| 449 if (filter_types.Get().size() == 0) | 464 if (filter_types.Get().size() == 0) |
| 450 InitFilterTypeMap(filter_types.Get()); | 465 InitFilterTypeMap(filter_types.Get()); |
| 451 | 466 |
| 452 DownloadQuery query_out; | 467 DownloadQuery query_out; |
| 453 | 468 |
| 469 size_t limit = 1000; | |
| 454 if (query_in.limit.get()) { | 470 if (query_in.limit.get()) { |
| 455 if (*query_in.limit.get() < 0) { | 471 if (*query_in.limit.get() < 0) { |
| 456 *error = download_extension_errors::kInvalidQueryLimit; | 472 *error = errors::kInvalidQueryLimit; |
| 457 return; | 473 return; |
| 458 } | 474 } |
| 459 query_out.Limit(*query_in.limit.get()); | 475 limit = *query_in.limit.get(); |
| 460 } | 476 } |
| 477 if (limit > 0) { | |
| 478 query_out.Limit(limit); | |
| 479 } | |
| 480 | |
| 461 std::string state_string = | 481 std::string state_string = |
| 462 extensions::api::downloads::ToString(query_in.state); | 482 extensions::api::downloads::ToString(query_in.state); |
| 463 if (!state_string.empty()) { | 483 if (!state_string.empty()) { |
| 464 DownloadItem::DownloadState state = StateEnumFromString(state_string); | 484 DownloadItem::DownloadState state = StateEnumFromString(state_string); |
| 465 if (state == DownloadItem::MAX_DOWNLOAD_STATE) { | 485 if (state == DownloadItem::MAX_DOWNLOAD_STATE) { |
| 466 *error = download_extension_errors::kInvalidStateError; | 486 *error = errors::kInvalidState; |
| 467 return; | 487 return; |
| 468 } | 488 } |
| 469 query_out.AddFilter(state); | 489 query_out.AddFilter(state); |
| 470 } | 490 } |
| 471 std::string danger_string = | 491 std::string danger_string = |
| 472 extensions::api::downloads::ToString(query_in.danger); | 492 extensions::api::downloads::ToString(query_in.danger); |
| 473 if (!danger_string.empty()) { | 493 if (!danger_string.empty()) { |
| 474 content::DownloadDangerType danger_type = DangerEnumFromString( | 494 content::DownloadDangerType danger_type = DangerEnumFromString( |
| 475 danger_string); | 495 danger_string); |
| 476 if (danger_type == content::DOWNLOAD_DANGER_TYPE_MAX) { | 496 if (danger_type == content::DOWNLOAD_DANGER_TYPE_MAX) { |
| 477 *error = download_extension_errors::kInvalidDangerTypeError; | 497 *error = errors::kInvalidDangerType; |
| 478 return; | 498 return; |
| 479 } | 499 } |
| 480 query_out.AddFilter(danger_type); | 500 query_out.AddFilter(danger_type); |
| 481 } | 501 } |
| 482 if (query_in.order_by.get()) { | 502 if (query_in.order_by.get()) { |
| 483 CompileDownloadQueryOrderBy(*query_in.order_by.get(), error, &query_out); | 503 CompileDownloadQueryOrderBy(*query_in.order_by.get(), error, &query_out); |
| 484 if (!error->empty()) | 504 if (!error->empty()) |
| 485 return; | 505 return; |
| 486 } | 506 } |
| 487 | 507 |
| 488 scoped_ptr<base::DictionaryValue> query_in_value(query_in.ToValue().Pass()); | 508 scoped_ptr<base::DictionaryValue> query_in_value(query_in.ToValue().Pass()); |
| 489 for (base::DictionaryValue::Iterator query_json_field(*query_in_value.get()); | 509 for (base::DictionaryValue::Iterator query_json_field(*query_in_value.get()); |
| 490 !query_json_field.IsAtEnd(); query_json_field.Advance()) { | 510 !query_json_field.IsAtEnd(); query_json_field.Advance()) { |
| 491 FilterTypeMap::const_iterator filter_type = | 511 FilterTypeMap::const_iterator filter_type = |
| 492 filter_types.Get().find(query_json_field.key()); | 512 filter_types.Get().find(query_json_field.key()); |
| 493 if (filter_type != filter_types.Get().end()) { | 513 if (filter_type != filter_types.Get().end()) { |
| 494 if (!query_out.AddFilter(filter_type->second, query_json_field.value())) { | 514 if (!query_out.AddFilter(filter_type->second, query_json_field.value())) { |
| 495 *error = download_extension_errors::kInvalidFilterError; | 515 *error = errors::kInvalidFilter; |
| 496 return; | 516 return; |
| 497 } | 517 } |
| 498 } | 518 } |
| 499 } | 519 } |
| 500 | 520 |
| 501 DownloadQuery::DownloadVector all_items; | 521 DownloadQuery::DownloadVector all_items; |
| 502 if (query_in.id.get()) { | 522 if (query_in.id.get()) { |
| 503 DownloadItem* download_item = manager->GetDownload(*query_in.id.get()); | 523 DownloadItem* download_item = manager->GetDownload(*query_in.id.get()); |
| 504 if (!download_item && incognito_manager) | 524 if (!download_item && incognito_manager) |
| 505 download_item = incognito_manager->GetDownload(*query_in.id.get()); | 525 download_item = incognito_manager->GetDownload(*query_in.id.get()); |
| 506 if (download_item) | 526 if (download_item) |
| 507 all_items.push_back(download_item); | 527 all_items.push_back(download_item); |
| 508 } else { | 528 } else { |
| 509 manager->GetAllDownloads(&all_items); | 529 manager->GetAllDownloads(&all_items); |
| 510 if (incognito_manager) | 530 if (incognito_manager) |
| 511 incognito_manager->GetAllDownloads(&all_items); | 531 incognito_manager->GetAllDownloads(&all_items); |
| 512 } | 532 } |
| 513 query_out.AddFilter(base::Bind(&IsNotTemporaryDownloadFilter)); | 533 query_out.AddFilter(base::Bind(&IsNotTemporaryDownloadFilter)); |
| 514 query_out.Search(all_items.begin(), all_items.end(), results); | 534 query_out.Search(all_items.begin(), all_items.end(), results); |
| 515 } | 535 } |
| 516 | 536 |
| 537 DownloadPathReservationTracker::FilenameConflictAction ConvertConflictAction( | |
| 538 extensions::api::downloads::FilenameConflictAction action) { | |
| 539 switch (action) { | |
| 540 case extensions::api::downloads::FILENAME_CONFLICT_ACTION_NONE: | |
| 541 case extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY: | |
| 542 return DownloadPathReservationTracker::UNIQUIFY; | |
| 543 case extensions::api::downloads::FILENAME_CONFLICT_ACTION_OVERWRITE: | |
| 544 return DownloadPathReservationTracker::OVERWRITE; | |
| 545 case extensions::api::downloads::FILENAME_CONFLICT_ACTION_PROMPT: | |
| 546 return DownloadPathReservationTracker::PROMPT; | |
| 547 } | |
| 548 NOTREACHED(); | |
| 549 return DownloadPathReservationTracker::UNIQUIFY; | |
| 550 } | |
| 551 | |
| 517 class ExtensionDownloadsEventRouterData : public base::SupportsUserData::Data { | 552 class ExtensionDownloadsEventRouterData : public base::SupportsUserData::Data { |
| 518 public: | 553 public: |
| 519 static ExtensionDownloadsEventRouterData* Get(DownloadItem* download_item) { | 554 static ExtensionDownloadsEventRouterData* Get(DownloadItem* download_item) { |
| 520 base::SupportsUserData::Data* data = download_item->GetUserData(kKey); | 555 base::SupportsUserData::Data* data = download_item->GetUserData(kKey); |
| 521 return (data == NULL) ? NULL : | 556 return (data == NULL) ? NULL : |
| 522 static_cast<ExtensionDownloadsEventRouterData*>(data); | 557 static_cast<ExtensionDownloadsEventRouterData*>(data); |
| 523 } | 558 } |
| 524 | 559 |
| 525 static void Remove(DownloadItem* download_item) { | 560 static void Remove(DownloadItem* download_item) { |
| 526 download_item->RemoveUserData(kKey); | 561 download_item->RemoveUserData(kKey); |
| 527 } | 562 } |
| 528 | 563 |
| 529 explicit ExtensionDownloadsEventRouterData( | 564 explicit ExtensionDownloadsEventRouterData( |
| 530 DownloadItem* download_item, | 565 DownloadItem* download_item, |
| 531 scoped_ptr<base::DictionaryValue> json_item) | 566 scoped_ptr<base::DictionaryValue> json_item) |
| 532 : updated_(0), | 567 : updated_(0), |
| 533 changed_fired_(0), | 568 changed_fired_(0), |
| 534 json_(json_item.Pass()), | 569 json_(json_item.Pass()), |
| 570 creator_conflict_action_( | |
| 571 extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY), | |
| 535 determined_conflict_action_( | 572 determined_conflict_action_( |
| 536 extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY) { | 573 extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY) { |
| 537 download_item->SetUserData(kKey, this); | 574 download_item->SetUserData(kKey, this); |
| 538 } | 575 } |
| 539 | 576 |
| 540 virtual ~ExtensionDownloadsEventRouterData() { | 577 virtual ~ExtensionDownloadsEventRouterData() { |
| 541 if (updated_ > 0) { | 578 if (updated_ > 0) { |
| 542 UMA_HISTOGRAM_PERCENTAGE("Download.OnChanged", | 579 UMA_HISTOGRAM_PERCENTAGE("Download.OnChanged", |
| 543 (changed_fired_ * 100 / updated_)); | 580 (changed_fired_ * 100 / updated_)); |
| 544 } | 581 } |
| 545 } | 582 } |
| 546 | 583 |
| 547 const base::DictionaryValue& json() const { return *json_.get(); } | 584 const base::DictionaryValue& json() const { return *json_.get(); } |
| 548 void set_json(scoped_ptr<base::DictionaryValue> json_item) { | 585 void set_json(scoped_ptr<base::DictionaryValue> json_item) { |
| 549 json_ = json_item.Pass(); | 586 json_ = json_item.Pass(); |
| 550 } | 587 } |
| 551 | 588 |
| 552 void OnItemUpdated() { ++updated_; } | 589 void OnItemUpdated() { ++updated_; } |
| 553 void OnChangedFired() { ++changed_fired_; } | 590 void OnChangedFired() { ++changed_fired_; } |
| 554 | 591 |
| 555 void set_filename_change_callbacks( | 592 void set_filename_change_callbacks( |
| 556 const base::Closure& no_change, | 593 const base::Closure& no_change, |
| 557 const ExtensionDownloadsEventRouter::FilenameChangedCallback& change) { | 594 const ExtensionDownloadsEventRouter::FilenameChangedCallback& change) { |
| 558 filename_no_change_ = no_change; | 595 filename_no_change_ = no_change; |
| 559 filename_change_ = change; | 596 filename_change_ = change; |
| 597 determined_filename_ = creator_suggested_filename_; | |
| 598 determined_conflict_action_ = creator_conflict_action_; | |
| 599 // determiner_.install_time should default to 0 so that creator suggestions | |
| 600 // should be lower priority than any actual onDeterminingFilename listeners. | |
| 560 } | 601 } |
| 561 | 602 |
| 562 void ClearPendingDeterminers() { | 603 void ClearPendingDeterminers() { |
| 563 determined_filename_.clear(); | 604 determined_filename_.clear(); |
| 564 determined_conflict_action_ = | 605 determined_conflict_action_ = |
| 565 extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY; | 606 extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY; |
| 566 determiner_ = DeterminerInfo(); | 607 determiner_ = DeterminerInfo(); |
| 567 filename_no_change_ = base::Closure(); | 608 filename_no_change_ = base::Closure(); |
| 568 filename_change_ = ExtensionDownloadsEventRouter::FilenameChangedCallback(); | 609 filename_change_ = ExtensionDownloadsEventRouter::FilenameChangedCallback(); |
| 569 weak_ptr_factory_.reset(); | 610 weak_ptr_factory_.reset(); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 597 | 638 |
| 598 bool DeterminerAlreadyReported(const std::string& extension_id) { | 639 bool DeterminerAlreadyReported(const std::string& extension_id) { |
| 599 for (size_t index = 0; index < determiners_.size(); ++index) { | 640 for (size_t index = 0; index < determiners_.size(); ++index) { |
| 600 if (determiners_[index].extension_id == extension_id) { | 641 if (determiners_[index].extension_id == extension_id) { |
| 601 return determiners_[index].reported; | 642 return determiners_[index].reported; |
| 602 } | 643 } |
| 603 } | 644 } |
| 604 return false; | 645 return false; |
| 605 } | 646 } |
| 606 | 647 |
| 648 void CreatorSuggestedFilename( | |
| 649 const base::FilePath& filename, | |
| 650 extensions::api::downloads::FilenameConflictAction conflict_action) { | |
| 651 creator_suggested_filename_ = filename; | |
| 652 creator_conflict_action_ = conflict_action; | |
| 653 } | |
| 654 | |
| 655 base::FilePath creator_suggested_filename() const { | |
| 656 return creator_suggested_filename_; | |
| 657 } | |
| 658 | |
| 659 extensions::api::downloads::FilenameConflictAction | |
| 660 creator_conflict_action() const { | |
| 661 return creator_conflict_action_; | |
| 662 } | |
| 663 | |
| 664 void ResetCreatorSuggestion() { | |
| 665 creator_suggested_filename_.clear(); | |
| 666 creator_conflict_action_ = | |
| 667 extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY; | |
| 668 } | |
| 669 | |
| 607 // Returns false if this |extension_id| was not expected or if this | 670 // Returns false if this |extension_id| was not expected or if this |
| 608 // |extension_id| has already reported. The caller is responsible for | 671 // |extension_id| has already reported. The caller is responsible for |
| 609 // validating |filename|. | 672 // validating |filename|. |
| 610 bool DeterminerCallback( | 673 bool DeterminerCallback( |
| 611 const std::string& extension_id, | 674 const std::string& extension_id, |
| 612 const base::FilePath& filename, | 675 const base::FilePath& filename, |
| 613 extensions::api::downloads::FilenameConflictAction conflict_action) { | 676 extensions::api::downloads::FilenameConflictAction conflict_action) { |
| 614 bool found_info = false; | 677 bool found_info = false; |
| 615 for (size_t index = 0; index < determiners_.size(); ++index) { | 678 for (size_t index = 0; index < determiners_.size(); ++index) { |
| 616 if (determiners_[index].extension_id == extension_id) { | 679 if (determiners_[index].extension_id == extension_id) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 658 for (DeterminerInfoVector::iterator iter = determiners_.begin(); | 721 for (DeterminerInfoVector::iterator iter = determiners_.begin(); |
| 659 iter != determiners_.end(); ++iter) { | 722 iter != determiners_.end(); ++iter) { |
| 660 if (!iter->reported) | 723 if (!iter->reported) |
| 661 return; | 724 return; |
| 662 } | 725 } |
| 663 if (determined_filename_.empty()) { | 726 if (determined_filename_.empty()) { |
| 664 if (!filename_no_change_.is_null()) | 727 if (!filename_no_change_.is_null()) |
| 665 filename_no_change_.Run(); | 728 filename_no_change_.Run(); |
| 666 } else { | 729 } else { |
| 667 if (!filename_change_.is_null()) { | 730 if (!filename_change_.is_null()) { |
| 668 DownloadPathReservationTracker::FilenameConflictAction conflict_action = | 731 filename_change_.Run(determined_filename_, ConvertConflictAction( |
| 669 DownloadPathReservationTracker::UNIQUIFY; | 732 determined_conflict_action_)); |
| 670 if (determined_conflict_action_ == | |
| 671 extensions::api::downloads::FILENAME_CONFLICT_ACTION_OVERWRITE) | |
| 672 conflict_action = DownloadPathReservationTracker::OVERWRITE; | |
| 673 if (determined_conflict_action_ == | |
| 674 extensions::api::downloads::FILENAME_CONFLICT_ACTION_PROMPT) | |
| 675 conflict_action = DownloadPathReservationTracker::PROMPT; | |
| 676 filename_change_.Run(determined_filename_, conflict_action); | |
| 677 } | 733 } |
| 678 } | 734 } |
| 679 // Don't clear determiners_ immediately in case there's a second listener | 735 // Don't clear determiners_ immediately in case there's a second listener |
| 680 // for one of the extensions, so that DetermineFilename can return | 736 // for one of the extensions, so that DetermineFilename can return |
| 681 // kTooManyListenersError. After a few seconds, DetermineFilename will | 737 // kTooManyListeners. After a few seconds, DetermineFilename will return |
| 682 // return kInvalidOperationError instead of kTooManyListenersError so that | 738 // kUnexpectedDeterminer instead of kTooManyListeners so that determiners_ |
| 683 // determiners_ doesn't keep hogging memory. | 739 // doesn't keep hogging memory. |
| 684 weak_ptr_factory_.reset( | 740 weak_ptr_factory_.reset( |
| 685 new base::WeakPtrFactory<ExtensionDownloadsEventRouterData>(this)); | 741 new base::WeakPtrFactory<ExtensionDownloadsEventRouterData>(this)); |
| 686 base::MessageLoopForUI::current()->PostDelayedTask( | 742 base::MessageLoopForUI::current()->PostDelayedTask( |
| 687 FROM_HERE, | 743 FROM_HERE, |
| 688 base::Bind(&ExtensionDownloadsEventRouterData::ClearPendingDeterminers, | 744 base::Bind(&ExtensionDownloadsEventRouterData::ClearPendingDeterminers, |
| 689 weak_ptr_factory_->GetWeakPtr()), | 745 weak_ptr_factory_->GetWeakPtr()), |
| 690 base::TimeDelta::FromSeconds(30)); | 746 base::TimeDelta::FromSeconds(30)); |
| 691 } | 747 } |
| 692 | 748 |
| 693 int updated_; | 749 int updated_; |
| 694 int changed_fired_; | 750 int changed_fired_; |
| 695 scoped_ptr<base::DictionaryValue> json_; | 751 scoped_ptr<base::DictionaryValue> json_; |
| 696 | 752 |
| 697 base::Closure filename_no_change_; | 753 base::Closure filename_no_change_; |
| 698 ExtensionDownloadsEventRouter::FilenameChangedCallback filename_change_; | 754 ExtensionDownloadsEventRouter::FilenameChangedCallback filename_change_; |
| 699 | 755 |
| 700 DeterminerInfoVector determiners_; | 756 DeterminerInfoVector determiners_; |
| 701 | 757 |
| 758 base::FilePath creator_suggested_filename_; | |
| 759 extensions::api::downloads::FilenameConflictAction | |
| 760 creator_conflict_action_; | |
| 702 base::FilePath determined_filename_; | 761 base::FilePath determined_filename_; |
| 703 extensions::api::downloads::FilenameConflictAction | 762 extensions::api::downloads::FilenameConflictAction |
| 704 determined_conflict_action_; | 763 determined_conflict_action_; |
| 705 DeterminerInfo determiner_; | 764 DeterminerInfo determiner_; |
| 706 | 765 |
| 707 scoped_ptr<base::WeakPtrFactory<ExtensionDownloadsEventRouterData> > | 766 scoped_ptr<base::WeakPtrFactory<ExtensionDownloadsEventRouterData> > |
| 708 weak_ptr_factory_; | 767 weak_ptr_factory_; |
| 709 | 768 |
| 710 DISALLOW_COPY_AND_ASSIGN(ExtensionDownloadsEventRouterData); | 769 DISALLOW_COPY_AND_ASSIGN(ExtensionDownloadsEventRouterData); |
| 711 }; | 770 }; |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 789 Profile* profile, | 848 Profile* profile, |
| 790 const extensions::Extension* extension, | 849 const extensions::Extension* extension, |
| 791 base::ListValue* event_args) { | 850 base::ListValue* event_args) { |
| 792 *any_determiners = true; | 851 *any_determiners = true; |
| 793 base::Time installed = extensions::ExtensionSystem::Get( | 852 base::Time installed = extensions::ExtensionSystem::Get( |
| 794 profile)->extension_service()->extension_prefs()-> | 853 profile)->extension_service()->extension_prefs()-> |
| 795 GetInstallTime(extension->id()); | 854 GetInstallTime(extension->id()); |
| 796 data->AddPendingDeterminer(extension->id(), installed); | 855 data->AddPendingDeterminer(extension->id(), installed); |
| 797 } | 856 } |
| 798 | 857 |
| 858 bool Fault(bool error, | |
| 859 const char* message_in, | |
| 860 std::string* message_out) { | |
| 861 if (!error) | |
| 862 return false; | |
| 863 *message_out = message_in; | |
| 864 return true; | |
| 865 } | |
| 866 | |
| 867 bool InvalidId(DownloadItem* valid_item, std::string* message_out) { | |
| 868 return Fault(!valid_item, errors::kInvalidId, message_out); | |
| 869 } | |
| 870 | |
| 871 bool IsDownloadDeltaField(const std::string& field) { | |
| 872 return ((field == kUrlKey) || | |
| 873 (field == kFilenameKey) || | |
| 874 (field == kDangerKey) || | |
| 875 (field == kMimeKey) || | |
| 876 (field == kStartTimeKey) || | |
| 877 (field == kEndTimeKey) || | |
| 878 (field == kStateKey) || | |
| 879 (field == kCanResumeKey) || | |
| 880 (field == kPausedKey) || | |
| 881 (field == kErrorKey) || | |
| 882 (field == kTotalBytesKey) || | |
| 883 (field == kFileSizeKey) || | |
| 884 (field == kExistsKey)); | |
| 885 } | |
| 886 | |
| 799 } // namespace | 887 } // namespace |
| 800 | 888 |
| 801 DownloadsDownloadFunction::DownloadsDownloadFunction() {} | 889 DownloadsDownloadFunction::DownloadsDownloadFunction() {} |
| 802 | 890 |
| 803 DownloadsDownloadFunction::~DownloadsDownloadFunction() {} | 891 DownloadsDownloadFunction::~DownloadsDownloadFunction() {} |
| 804 | 892 |
| 805 bool DownloadsDownloadFunction::RunImpl() { | 893 bool DownloadsDownloadFunction::RunImpl() { |
| 806 scoped_ptr<extensions::api::downloads::Download::Params> params( | 894 scoped_ptr<extensions::api::downloads::Download::Params> params( |
| 807 extensions::api::downloads::Download::Params::Create(*args_)); | 895 extensions::api::downloads::Download::Params::Create(*args_)); |
| 808 EXTENSION_FUNCTION_VALIDATE(params.get()); | 896 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 809 const extensions::api::downloads::DownloadOptions& options = params->options; | 897 const extensions::api::downloads::DownloadOptions& options = params->options; |
| 810 GURL download_url(options.url); | 898 GURL download_url(options.url); |
| 811 if (!download_url.is_valid()) { | 899 if (Fault(!download_url.is_valid(), errors::kInvalidURL, &error_)) |
| 812 error_ = download_extension_errors::kInvalidURLError; | |
| 813 return false; | 900 return false; |
| 814 } | |
| 815 | 901 |
| 816 Profile* current_profile = profile(); | 902 Profile* current_profile = profile(); |
| 817 if (include_incognito() && profile()->HasOffTheRecordProfile()) | 903 if (include_incognito() && profile()->HasOffTheRecordProfile()) |
| 818 current_profile = profile()->GetOffTheRecordProfile(); | 904 current_profile = profile()->GetOffTheRecordProfile(); |
| 819 | 905 |
| 820 scoped_ptr<content::DownloadUrlParameters> download_params( | 906 scoped_ptr<content::DownloadUrlParameters> download_params( |
| 821 new content::DownloadUrlParameters( | 907 new content::DownloadUrlParameters( |
| 822 download_url, | 908 download_url, |
| 823 render_view_host()->GetProcess()->GetID(), | 909 render_view_host()->GetProcess()->GetID(), |
| 824 render_view_host()->GetRoutingID(), | 910 render_view_host()->GetRoutingID(), |
| 825 current_profile->GetResourceContext())); | 911 current_profile->GetResourceContext())); |
| 826 | 912 |
| 913 base::FilePath creator_suggested_filename; | |
| 827 if (options.filename.get()) { | 914 if (options.filename.get()) { |
| 828 // TODO(benjhayden): Make json_schema_compiler generate string16s instead of | 915 #if defined(OS_WIN) |
| 829 // std::strings. Can't get filename16 from options.ToValue() because that | 916 // Can't get filename16 from options.ToValue() because that converts it from |
| 830 // converts it from std::string. | 917 // std::string. |
| 831 base::DictionaryValue* options_value = NULL; | 918 base::DictionaryValue* options_value = NULL; |
| 832 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options_value)); | 919 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options_value)); |
| 833 string16 filename16; | 920 base::string16 filename16; |
| 834 EXTENSION_FUNCTION_VALIDATE(options_value->GetString( | 921 EXTENSION_FUNCTION_VALIDATE(options_value->GetString( |
| 835 kFilenameKey, &filename16)); | 922 kFilenameKey, &filename16)); |
| 836 #if defined(OS_WIN) | 923 creator_suggested_filename = base::FilePath(filename16); |
| 837 base::FilePath file_path(filename16); | |
| 838 #elif defined(OS_POSIX) | 924 #elif defined(OS_POSIX) |
| 839 base::FilePath file_path(*options.filename.get()); | 925 creator_suggested_filename = base::FilePath(*options.filename.get()); |
| 840 #endif | 926 #endif |
| 841 if (!net::IsSafePortableBasename(file_path) || | 927 if (!net::IsSafePortableRelativePath(creator_suggested_filename)) { |
| 842 (file_path.DirName().value() != base::FilePath::kCurrentDirectory)) { | 928 error_ = errors::kInvalidFilename; |
| 843 error_ = download_extension_errors::kInvalidFilenameError; | |
| 844 return false; | 929 return false; |
| 845 } | 930 } |
| 846 // TODO(benjhayden) Ensure that this filename is interpreted as a path | |
| 847 // relative to the default downloads directory without allowing '..'. | |
| 848 download_params->set_suggested_name(filename16); | |
| 849 } | 931 } |
| 850 | 932 |
| 851 if (options.save_as.get()) | 933 if (options.save_as.get()) |
| 852 download_params->set_prompt(*options.save_as.get()); | 934 download_params->set_prompt(*options.save_as.get()); |
| 853 | 935 |
| 854 if (options.headers.get()) { | 936 if (options.headers.get()) { |
| 855 typedef extensions::api::downloads::HeaderNameValuePair HeaderNameValuePair; | 937 typedef extensions::api::downloads::HeaderNameValuePair HeaderNameValuePair; |
| 856 for (std::vector<linked_ptr<HeaderNameValuePair> >::const_iterator iter = | 938 for (std::vector<linked_ptr<HeaderNameValuePair> >::const_iterator iter = |
| 857 options.headers->begin(); | 939 options.headers->begin(); |
| 858 iter != options.headers->end(); | 940 iter != options.headers->end(); |
| 859 ++iter) { | 941 ++iter) { |
| 860 const HeaderNameValuePair& name_value = **iter; | 942 const HeaderNameValuePair& name_value = **iter; |
| 861 if (!net::HttpUtil::IsSafeHeader(name_value.name)) { | 943 if (!net::HttpUtil::IsSafeHeader(name_value.name)) { |
| 862 error_ = download_extension_errors::kGenericError; | 944 error_ = errors::kInvalidHeader; |
| 863 return false; | 945 return false; |
| 864 } | 946 } |
| 865 download_params->add_request_header(name_value.name, name_value.value); | 947 download_params->add_request_header(name_value.name, name_value.value); |
| 866 } | 948 } |
| 867 } | 949 } |
| 868 | 950 |
| 869 std::string method_string = | 951 std::string method_string = |
| 870 extensions::api::downloads::ToString(options.method); | 952 extensions::api::downloads::ToString(options.method); |
| 871 if (!method_string.empty()) | 953 if (!method_string.empty()) |
| 872 download_params->set_method(method_string); | 954 download_params->set_method(method_string); |
| 873 if (options.body.get()) | 955 if (options.body.get()) |
| 874 download_params->set_post_body(*options.body.get()); | 956 download_params->set_post_body(*options.body.get()); |
| 875 download_params->set_callback(base::Bind( | 957 download_params->set_callback(base::Bind( |
| 876 &DownloadsDownloadFunction::OnStarted, this)); | 958 &DownloadsDownloadFunction::OnStarted, this, |
| 959 creator_suggested_filename, options.conflict_action)); | |
| 877 // Prevent login prompts for 401/407 responses. | 960 // Prevent login prompts for 401/407 responses. |
| 878 download_params->set_load_flags(net::LOAD_DO_NOT_PROMPT_FOR_LOGIN); | 961 download_params->set_load_flags(net::LOAD_DO_NOT_PROMPT_FOR_LOGIN); |
| 879 | 962 |
| 880 DownloadManager* manager = BrowserContext::GetDownloadManager( | 963 DownloadManager* manager = BrowserContext::GetDownloadManager( |
| 881 current_profile); | 964 current_profile); |
| 882 manager->DownloadUrl(download_params.Pass()); | 965 manager->DownloadUrl(download_params.Pass()); |
| 966 download_util::RecordDownloadSource(download_util::INITIATED_BY_EXTENSION); | |
| 883 RecordApiFunctions(DOWNLOADS_FUNCTION_DOWNLOAD); | 967 RecordApiFunctions(DOWNLOADS_FUNCTION_DOWNLOAD); |
| 884 return true; | 968 return true; |
| 885 } | 969 } |
| 886 | 970 |
| 887 void DownloadsDownloadFunction::OnStarted( | 971 void DownloadsDownloadFunction::OnStarted( |
| 888 DownloadItem* item, net::Error error) { | 972 const base::FilePath& creator_suggested_filename, |
| 973 extensions::api::downloads::FilenameConflictAction creator_conflict_action, | |
| 974 DownloadItem* item, | |
| 975 net::Error error) { | |
| 889 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 976 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 890 VLOG(1) << __FUNCTION__ << " " << item << " " << error; | 977 VLOG(1) << __FUNCTION__ << " " << item << " " << error; |
| 891 if (item) { | 978 if (item) { |
| 892 DCHECK_EQ(net::OK, error); | 979 DCHECK_EQ(net::OK, error); |
| 893 SetResult(base::Value::CreateIntegerValue(item->GetId())); | 980 SetResult(base::Value::CreateIntegerValue(item->GetId())); |
| 981 if (!creator_suggested_filename.empty()) { | |
| 982 ExtensionDownloadsEventRouterData* data = | |
| 983 ExtensionDownloadsEventRouterData::Get(item); | |
| 984 if (!data) { | |
| 985 data = new ExtensionDownloadsEventRouterData( | |
| 986 item, | |
| 987 scoped_ptr<base::DictionaryValue>(new base::DictionaryValue())); | |
| 988 } | |
| 989 data->CreatorSuggestedFilename( | |
| 990 creator_suggested_filename, creator_conflict_action); | |
| 991 } | |
| 894 } else { | 992 } else { |
| 895 DCHECK_NE(net::OK, error); | 993 DCHECK_NE(net::OK, error); |
| 896 error_ = net::ErrorToString(error); | 994 error_ = net::ErrorToString(error); |
| 897 } | 995 } |
| 898 SendResponse(error_.empty()); | 996 SendResponse(error_.empty()); |
| 899 } | 997 } |
| 900 | 998 |
| 901 DownloadsSearchFunction::DownloadsSearchFunction() {} | 999 DownloadsSearchFunction::DownloadsSearchFunction() {} |
| 902 | 1000 |
| 903 DownloadsSearchFunction::~DownloadsSearchFunction() {} | 1001 DownloadsSearchFunction::~DownloadsSearchFunction() {} |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 937 } | 1035 } |
| 938 | 1036 |
| 939 DownloadsPauseFunction::DownloadsPauseFunction() {} | 1037 DownloadsPauseFunction::DownloadsPauseFunction() {} |
| 940 | 1038 |
| 941 DownloadsPauseFunction::~DownloadsPauseFunction() {} | 1039 DownloadsPauseFunction::~DownloadsPauseFunction() {} |
| 942 | 1040 |
| 943 bool DownloadsPauseFunction::RunImpl() { | 1041 bool DownloadsPauseFunction::RunImpl() { |
| 944 scoped_ptr<extensions::api::downloads::Pause::Params> params( | 1042 scoped_ptr<extensions::api::downloads::Pause::Params> params( |
| 945 extensions::api::downloads::Pause::Params::Create(*args_)); | 1043 extensions::api::downloads::Pause::Params::Create(*args_)); |
| 946 EXTENSION_FUNCTION_VALIDATE(params.get()); | 1044 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 947 DownloadItem* download_item = GetDownloadIfInProgress( | 1045 DownloadItem* download_item = GetDownload( |
| 948 profile(), include_incognito(), params->download_id); | 1046 profile(), include_incognito(), params->download_id); |
| 949 if (download_item == NULL) { | 1047 if (InvalidId(download_item, &error_) || |
| 950 // This could be due to an invalid download ID, or it could be due to the | 1048 Fault(download_item->GetState() != DownloadItem::IN_PROGRESS, |
| 951 // download not being currently active. | 1049 errors::kNotInProgress, &error_)) |
| 952 error_ = download_extension_errors::kInvalidOperationError; | 1050 return false; |
| 953 } else { | 1051 // If the item is already paused, this is a no-op and the operation will |
| 954 // If the item is already paused, this is a no-op and the | 1052 // silently succeed. |
| 955 // operation will silently succeed. | 1053 download_item->Pause(); |
| 956 download_item->Pause(); | 1054 RecordApiFunctions(DOWNLOADS_FUNCTION_PAUSE); |
| 957 } | 1055 return true; |
| 958 if (error_.empty()) | |
| 959 RecordApiFunctions(DOWNLOADS_FUNCTION_PAUSE); | |
| 960 return error_.empty(); | |
| 961 } | 1056 } |
| 962 | 1057 |
| 963 DownloadsResumeFunction::DownloadsResumeFunction() {} | 1058 DownloadsResumeFunction::DownloadsResumeFunction() {} |
| 964 | 1059 |
| 965 DownloadsResumeFunction::~DownloadsResumeFunction() {} | 1060 DownloadsResumeFunction::~DownloadsResumeFunction() {} |
| 966 | 1061 |
| 967 bool DownloadsResumeFunction::RunImpl() { | 1062 bool DownloadsResumeFunction::RunImpl() { |
| 968 scoped_ptr<extensions::api::downloads::Resume::Params> params( | 1063 scoped_ptr<extensions::api::downloads::Resume::Params> params( |
| 969 extensions::api::downloads::Resume::Params::Create(*args_)); | 1064 extensions::api::downloads::Resume::Params::Create(*args_)); |
| 970 EXTENSION_FUNCTION_VALIDATE(params.get()); | 1065 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 971 DownloadItem* download_item = GetDownloadIfInProgress( | 1066 DownloadItem* download_item = GetDownload( |
| 972 profile(), include_incognito(), params->download_id); | 1067 profile(), include_incognito(), params->download_id); |
| 973 if (download_item == NULL) { | 1068 if (InvalidId(download_item, &error_) || |
| 974 // This could be due to an invalid download ID, or it could be due to the | 1069 Fault(download_item->IsPaused() && !download_item->CanResume(), |
|
asanka
2013/07/26 20:28:28
!download_item->CanResume() should be sufficient.
benjhayden
2013/07/28 17:37:54
We wanted it to be not an error to call resume() f
| |
| 975 // download not being currently active. | 1070 errors::kNotResumable, &error_)) |
| 976 error_ = download_extension_errors::kInvalidOperationError; | 1071 return false; |
| 977 } else { | 1072 // Note that if the item isn't paused, this will be a no-op, and the extension |
| 978 // Note that if the item isn't paused, this will be a no-op, and | 1073 // call will seem successful. |
| 979 // the extension call will seem successful. | 1074 download_item->Resume(); |
| 980 download_item->Resume(); | 1075 RecordApiFunctions(DOWNLOADS_FUNCTION_RESUME); |
| 981 } | 1076 return true; |
| 982 if (error_.empty()) | |
| 983 RecordApiFunctions(DOWNLOADS_FUNCTION_RESUME); | |
| 984 return error_.empty(); | |
| 985 } | 1077 } |
| 986 | 1078 |
| 987 DownloadsCancelFunction::DownloadsCancelFunction() {} | 1079 DownloadsCancelFunction::DownloadsCancelFunction() {} |
| 988 | 1080 |
| 989 DownloadsCancelFunction::~DownloadsCancelFunction() {} | 1081 DownloadsCancelFunction::~DownloadsCancelFunction() {} |
| 990 | 1082 |
| 991 bool DownloadsCancelFunction::RunImpl() { | 1083 bool DownloadsCancelFunction::RunImpl() { |
| 992 scoped_ptr<extensions::api::downloads::Resume::Params> params( | 1084 scoped_ptr<extensions::api::downloads::Resume::Params> params( |
| 993 extensions::api::downloads::Resume::Params::Create(*args_)); | 1085 extensions::api::downloads::Resume::Params::Create(*args_)); |
| 994 EXTENSION_FUNCTION_VALIDATE(params.get()); | 1086 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 995 DownloadItem* download_item = GetDownloadIfInProgress( | 1087 DownloadItem* download_item = GetDownload( |
| 996 profile(), include_incognito(), params->download_id); | 1088 profile(), include_incognito(), params->download_id); |
| 997 if (download_item != NULL) | 1089 if (download_item && |
| 1090 (download_item->GetState() == DownloadItem::IN_PROGRESS)) | |
| 998 download_item->Cancel(true); | 1091 download_item->Cancel(true); |
| 999 // |download_item| can be NULL if the download ID was invalid or if the | 1092 // |download_item| can be NULL if the download ID was invalid or if the |
| 1000 // download is not currently active. Either way, it's not a failure. | 1093 // download is not currently active. Either way, it's not a failure. |
| 1001 RecordApiFunctions(DOWNLOADS_FUNCTION_CANCEL); | 1094 RecordApiFunctions(DOWNLOADS_FUNCTION_CANCEL); |
| 1002 return true; | 1095 return true; |
| 1003 } | 1096 } |
| 1004 | 1097 |
| 1005 DownloadsEraseFunction::DownloadsEraseFunction() {} | 1098 DownloadsEraseFunction::DownloadsEraseFunction() {} |
| 1006 | 1099 |
| 1007 DownloadsEraseFunction::~DownloadsEraseFunction() {} | 1100 DownloadsEraseFunction::~DownloadsEraseFunction() {} |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 1025 for (DownloadManager::DownloadVector::const_iterator it = results.begin(); | 1118 for (DownloadManager::DownloadVector::const_iterator it = results.begin(); |
| 1026 it != results.end(); ++it) { | 1119 it != results.end(); ++it) { |
| 1027 json_results->Append(base::Value::CreateIntegerValue((*it)->GetId())); | 1120 json_results->Append(base::Value::CreateIntegerValue((*it)->GetId())); |
| 1028 (*it)->Remove(); | 1121 (*it)->Remove(); |
| 1029 } | 1122 } |
| 1030 SetResult(json_results); | 1123 SetResult(json_results); |
| 1031 RecordApiFunctions(DOWNLOADS_FUNCTION_ERASE); | 1124 RecordApiFunctions(DOWNLOADS_FUNCTION_ERASE); |
| 1032 return true; | 1125 return true; |
| 1033 } | 1126 } |
| 1034 | 1127 |
| 1128 DownloadsRemoveFileFunction::DownloadsRemoveFileFunction() {} | |
| 1129 | |
| 1130 DownloadsRemoveFileFunction::~DownloadsRemoveFileFunction() { | |
| 1131 if (item_) { | |
| 1132 item_->RemoveObserver(this); | |
| 1133 item_ = NULL; | |
| 1134 } | |
| 1135 } | |
| 1136 | |
| 1137 bool DownloadsRemoveFileFunction::RunImpl() { | |
| 1138 scoped_ptr<extensions::api::downloads::RemoveFile::Params> params( | |
| 1139 extensions::api::downloads::RemoveFile::Params::Create(*args_)); | |
| 1140 EXTENSION_FUNCTION_VALIDATE(params.get()); | |
| 1141 DownloadItem* download_item = GetDownload( | |
| 1142 profile(), include_incognito(), params->download_id); | |
| 1143 if (InvalidId(download_item, &error_) || | |
| 1144 Fault((download_item->GetState() != DownloadItem::COMPLETE), | |
| 1145 errors::kNotComplete, &error_) || | |
| 1146 Fault(download_item->GetFileExternallyRemoved(), | |
| 1147 errors::kFileAlreadyDeleted, &error_)) | |
| 1148 return false; | |
| 1149 item_ = download_item; | |
| 1150 item_->AddObserver(this); | |
| 1151 RecordApiFunctions(DOWNLOADS_FUNCTION_DELETE_FILE); | |
| 1152 download_item->DeleteFile(); | |
| 1153 return true; | |
| 1154 } | |
| 1155 | |
| 1156 void DownloadsRemoveFileFunction::OnDownloadUpdated(DownloadItem* download) { | |
| 1157 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 1158 DCHECK_EQ(item_, download); | |
| 1159 if (!item_->GetFileExternallyRemoved()) | |
| 1160 return; | |
| 1161 item_->RemoveObserver(this); | |
| 1162 item_ = NULL; | |
| 1163 SendResponse(true); | |
| 1164 } | |
| 1165 | |
| 1166 void DownloadsRemoveFileFunction::OnDownloadDestroyed(DownloadItem* download) { | |
| 1167 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | |
| 1168 DCHECK_EQ(item_, download); | |
| 1169 item_->RemoveObserver(this); | |
| 1170 item_ = NULL; | |
| 1171 SendResponse(true); | |
| 1172 } | |
| 1173 | |
| 1035 DownloadsAcceptDangerFunction::DownloadsAcceptDangerFunction() {} | 1174 DownloadsAcceptDangerFunction::DownloadsAcceptDangerFunction() {} |
| 1036 | 1175 |
| 1037 DownloadsAcceptDangerFunction::~DownloadsAcceptDangerFunction() {} | 1176 DownloadsAcceptDangerFunction::~DownloadsAcceptDangerFunction() {} |
| 1038 | 1177 |
| 1039 bool DownloadsAcceptDangerFunction::RunImpl() { | 1178 bool DownloadsAcceptDangerFunction::RunImpl() { |
| 1040 scoped_ptr<extensions::api::downloads::AcceptDanger::Params> params( | 1179 scoped_ptr<extensions::api::downloads::AcceptDanger::Params> params( |
| 1041 extensions::api::downloads::AcceptDanger::Params::Create(*args_)); | 1180 extensions::api::downloads::AcceptDanger::Params::Create(*args_)); |
| 1042 EXTENSION_FUNCTION_VALIDATE(params.get()); | 1181 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 1043 DownloadItem* download_item = GetDownloadIfInProgress( | 1182 DownloadItem* download_item = GetDownload( |
| 1044 profile(), include_incognito(), params->download_id); | 1183 profile(), include_incognito(), params->download_id); |
| 1045 content::WebContents* web_contents = | 1184 content::WebContents* web_contents = |
| 1046 dispatcher()->delegate()->GetVisibleWebContents(); | 1185 dispatcher()->delegate()->GetVisibleWebContents(); |
| 1047 if (!download_item || | 1186 if (InvalidId(download_item, &error_) || |
| 1048 !download_item->IsDangerous() || | 1187 Fault(download_item->GetState() != DownloadItem::IN_PROGRESS, |
| 1049 !web_contents) { | 1188 errors::kNotInProgress, &error_) || |
| 1050 error_ = download_extension_errors::kInvalidOperationError; | 1189 Fault(!download_item->IsDangerous(), errors::kNotDangerous, &error_) || |
| 1190 Fault(!web_contents, errors::kInvisibleContext, &error_)) | |
| 1051 return false; | 1191 return false; |
| 1052 } | |
| 1053 RecordApiFunctions(DOWNLOADS_FUNCTION_ACCEPT_DANGER); | 1192 RecordApiFunctions(DOWNLOADS_FUNCTION_ACCEPT_DANGER); |
| 1054 // DownloadDangerPrompt displays a modal dialog using native widgets that the | 1193 // DownloadDangerPrompt displays a modal dialog using native widgets that the |
| 1055 // user must either accept or cancel. It cannot be scripted. | 1194 // user must either accept or cancel. It cannot be scripted. |
| 1056 DownloadDangerPrompt::Create( | 1195 DownloadDangerPrompt::Create( |
| 1057 download_item, | 1196 download_item, |
| 1058 web_contents, | 1197 web_contents, |
| 1059 true, | 1198 true, |
| 1060 base::Bind(&DownloadsAcceptDangerFunction::DangerPromptCallback, | 1199 base::Bind(&DownloadsAcceptDangerFunction::DangerPromptCallback, |
| 1061 this, true, params->download_id), | 1200 this, params->download_id)); |
| 1062 base::Bind(&DownloadsAcceptDangerFunction::DangerPromptCallback, | |
| 1063 this, false, params->download_id)); | |
| 1064 // DownloadDangerPrompt deletes itself | 1201 // DownloadDangerPrompt deletes itself |
| 1065 return true; | 1202 return true; |
| 1066 } | 1203 } |
| 1067 | 1204 |
| 1068 void DownloadsAcceptDangerFunction::DangerPromptCallback( | 1205 void DownloadsAcceptDangerFunction::DangerPromptCallback( |
| 1069 bool accept, int download_id) { | 1206 int download_id, DownloadDangerPrompt::Action action) { |
| 1070 if (accept) { | 1207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1071 DownloadItem* download_item = GetDownloadIfInProgress( | 1208 DownloadItem* download_item = GetDownload( |
| 1072 profile(), include_incognito(), download_id); | 1209 profile(), include_incognito(), download_id); |
| 1073 if (download_item) | 1210 if (InvalidId(download_item, &error_) || |
| 1211 Fault(download_item->GetState() != DownloadItem::IN_PROGRESS, | |
| 1212 errors::kNotInProgress, &error_)) | |
| 1213 return; | |
| 1214 switch (action) { | |
| 1215 case DownloadDangerPrompt::ACCEPT: | |
| 1074 download_item->ValidateDangerousDownload(); | 1216 download_item->ValidateDangerousDownload(); |
| 1217 break; | |
| 1218 case DownloadDangerPrompt::CANCEL: | |
| 1219 download_item->Remove(); | |
| 1220 break; | |
| 1221 case DownloadDangerPrompt::DISMISS: | |
| 1222 break; | |
| 1075 } | 1223 } |
| 1076 SendResponse(error_.empty()); | 1224 SendResponse(error_.empty()); |
| 1077 } | 1225 } |
| 1078 | 1226 |
| 1079 DownloadsShowFunction::DownloadsShowFunction() {} | 1227 DownloadsShowFunction::DownloadsShowFunction() {} |
| 1080 | 1228 |
| 1081 DownloadsShowFunction::~DownloadsShowFunction() {} | 1229 DownloadsShowFunction::~DownloadsShowFunction() {} |
| 1082 | 1230 |
| 1083 bool DownloadsShowFunction::RunImpl() { | 1231 bool DownloadsShowFunction::RunImpl() { |
| 1084 scoped_ptr<extensions::api::downloads::Show::Params> params( | 1232 scoped_ptr<extensions::api::downloads::Show::Params> params( |
| 1085 extensions::api::downloads::Show::Params::Create(*args_)); | 1233 extensions::api::downloads::Show::Params::Create(*args_)); |
| 1086 EXTENSION_FUNCTION_VALIDATE(params.get()); | 1234 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 1087 DownloadItem* download_item = GetDownload( | 1235 DownloadItem* download_item = GetDownload( |
| 1088 profile(), include_incognito(), params->download_id); | 1236 profile(), include_incognito(), params->download_id); |
| 1089 if (!download_item) { | 1237 if (InvalidId(download_item, &error_)) |
| 1090 error_ = download_extension_errors::kInvalidOperationError; | |
| 1091 return false; | 1238 return false; |
| 1092 } | |
| 1093 download_item->ShowDownloadInShell(); | 1239 download_item->ShowDownloadInShell(); |
| 1094 RecordApiFunctions(DOWNLOADS_FUNCTION_SHOW); | 1240 RecordApiFunctions(DOWNLOADS_FUNCTION_SHOW); |
| 1095 return true; | 1241 return true; |
| 1096 } | 1242 } |
| 1097 | 1243 |
| 1244 DownloadsShowDefaultFolderFunction::DownloadsShowDefaultFolderFunction() {} | |
| 1245 | |
| 1246 DownloadsShowDefaultFolderFunction::~DownloadsShowDefaultFolderFunction() {} | |
| 1247 | |
| 1248 bool DownloadsShowDefaultFolderFunction::RunImpl() { | |
| 1249 DownloadManager* manager = NULL; | |
| 1250 DownloadManager* incognito_manager = NULL; | |
| 1251 GetManagers(profile(), include_incognito(), &manager, &incognito_manager); | |
| 1252 platform_util::OpenItem(DownloadPrefs::FromDownloadManager( | |
| 1253 manager)->DownloadPath()); | |
| 1254 RecordApiFunctions(DOWNLOADS_FUNCTION_SHOW_DEFAULT_FOLDER); | |
| 1255 return true; | |
| 1256 } | |
| 1257 | |
| 1098 DownloadsOpenFunction::DownloadsOpenFunction() {} | 1258 DownloadsOpenFunction::DownloadsOpenFunction() {} |
| 1099 | 1259 |
| 1100 DownloadsOpenFunction::~DownloadsOpenFunction() {} | 1260 DownloadsOpenFunction::~DownloadsOpenFunction() {} |
| 1101 | 1261 |
| 1102 bool DownloadsOpenFunction::RunImpl() { | 1262 bool DownloadsOpenFunction::RunImpl() { |
| 1103 scoped_ptr<extensions::api::downloads::Open::Params> params( | 1263 scoped_ptr<extensions::api::downloads::Open::Params> params( |
| 1104 extensions::api::downloads::Open::Params::Create(*args_)); | 1264 extensions::api::downloads::Open::Params::Create(*args_)); |
| 1105 EXTENSION_FUNCTION_VALIDATE(params.get()); | 1265 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 1106 DownloadItem* download_item = GetDownload( | 1266 DownloadItem* download_item = GetDownload( |
| 1107 profile(), include_incognito(), params->download_id); | 1267 profile(), include_incognito(), params->download_id); |
| 1108 if (!download_item || download_item->GetState() != DownloadItem::COMPLETE || | 1268 if (InvalidId(download_item, &error_) || |
| 1109 !GetExtension()->HasAPIPermission( | 1269 Fault(download_item->GetState() != DownloadItem::COMPLETE, |
| 1110 extensions::APIPermission::kDownloadsOpen)) { | 1270 errors::kNotComplete, &error_) || |
| 1111 error_ = download_extension_errors::kInvalidOperationError; | 1271 Fault(!GetExtension()->HasAPIPermission( |
| 1272 extensions::APIPermission::kDownloadsOpen), | |
| 1273 errors::kOpenPermission, &error_)) | |
| 1112 return false; | 1274 return false; |
| 1113 } | |
| 1114 download_item->OpenDownload(); | 1275 download_item->OpenDownload(); |
| 1115 RecordApiFunctions(DOWNLOADS_FUNCTION_OPEN); | 1276 RecordApiFunctions(DOWNLOADS_FUNCTION_OPEN); |
| 1116 return true; | 1277 return true; |
| 1117 } | 1278 } |
| 1118 | 1279 |
| 1119 DownloadsDragFunction::DownloadsDragFunction() {} | 1280 DownloadsDragFunction::DownloadsDragFunction() {} |
| 1120 | 1281 |
| 1121 DownloadsDragFunction::~DownloadsDragFunction() {} | 1282 DownloadsDragFunction::~DownloadsDragFunction() {} |
| 1122 | 1283 |
| 1123 bool DownloadsDragFunction::RunImpl() { | 1284 bool DownloadsDragFunction::RunImpl() { |
| 1124 scoped_ptr<extensions::api::downloads::Drag::Params> params( | 1285 scoped_ptr<extensions::api::downloads::Drag::Params> params( |
| 1125 extensions::api::downloads::Drag::Params::Create(*args_)); | 1286 extensions::api::downloads::Drag::Params::Create(*args_)); |
| 1126 EXTENSION_FUNCTION_VALIDATE(params.get()); | 1287 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 1127 DownloadItem* download_item = GetDownload( | 1288 DownloadItem* download_item = GetDownload( |
| 1128 profile(), include_incognito(), params->download_id); | 1289 profile(), include_incognito(), params->download_id); |
| 1129 content::WebContents* web_contents = | 1290 content::WebContents* web_contents = |
| 1130 dispatcher()->delegate()->GetVisibleWebContents(); | 1291 dispatcher()->delegate()->GetVisibleWebContents(); |
| 1131 if (!download_item || !web_contents) { | 1292 if (InvalidId(download_item, &error_) || |
| 1132 error_ = download_extension_errors::kInvalidOperationError; | 1293 Fault(!web_contents, errors::kInvisibleContext, &error_)) |
| 1133 return false; | 1294 return false; |
| 1134 } | |
| 1135 RecordApiFunctions(DOWNLOADS_FUNCTION_DRAG); | 1295 RecordApiFunctions(DOWNLOADS_FUNCTION_DRAG); |
| 1136 gfx::Image* icon = g_browser_process->icon_manager()->LookupIconFromFilepath( | 1296 gfx::Image* icon = g_browser_process->icon_manager()->LookupIconFromFilepath( |
| 1137 download_item->GetTargetFilePath(), IconLoader::NORMAL); | 1297 download_item->GetTargetFilePath(), IconLoader::NORMAL); |
| 1138 gfx::NativeView view = web_contents->GetView()->GetNativeView(); | 1298 gfx::NativeView view = web_contents->GetView()->GetNativeView(); |
| 1139 { | 1299 { |
| 1140 // Enable nested tasks during DnD, while |DragDownload()| blocks. | 1300 // Enable nested tasks during DnD, while |DragDownload()| blocks. |
| 1141 base::MessageLoop::ScopedNestableTaskAllower allow( | 1301 base::MessageLoop::ScopedNestableTaskAllower allow( |
| 1142 base::MessageLoop::current()); | 1302 base::MessageLoop::current()); |
| 1143 download_util::DragDownload(download_item, icon, view); | 1303 download_util::DragDownload(download_item, icon, view); |
| 1144 } | 1304 } |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 1161 scoped_ptr<extensions::api::downloads::GetFileIcon::Params> params( | 1321 scoped_ptr<extensions::api::downloads::GetFileIcon::Params> params( |
| 1162 extensions::api::downloads::GetFileIcon::Params::Create(*args_)); | 1322 extensions::api::downloads::GetFileIcon::Params::Create(*args_)); |
| 1163 EXTENSION_FUNCTION_VALIDATE(params.get()); | 1323 EXTENSION_FUNCTION_VALIDATE(params.get()); |
| 1164 const extensions::api::downloads::GetFileIconOptions* options = | 1324 const extensions::api::downloads::GetFileIconOptions* options = |
| 1165 params->options.get(); | 1325 params->options.get(); |
| 1166 int icon_size = kDefaultIconSize; | 1326 int icon_size = kDefaultIconSize; |
| 1167 if (options && options->size.get()) | 1327 if (options && options->size.get()) |
| 1168 icon_size = *options->size.get(); | 1328 icon_size = *options->size.get(); |
| 1169 DownloadItem* download_item = GetDownload( | 1329 DownloadItem* download_item = GetDownload( |
| 1170 profile(), include_incognito(), params->download_id); | 1330 profile(), include_incognito(), params->download_id); |
| 1171 if (!download_item || download_item->GetTargetFilePath().empty()) { | 1331 if (InvalidId(download_item, &error_) || |
| 1172 error_ = download_extension_errors::kInvalidOperationError; | 1332 Fault(download_item->GetTargetFilePath().empty(), |
| 1333 errors::kEmptyFile, &error_)) | |
| 1173 return false; | 1334 return false; |
| 1174 } | |
| 1175 // In-progress downloads return the intermediate filename for GetFullPath() | 1335 // In-progress downloads return the intermediate filename for GetFullPath() |
| 1176 // which doesn't have the final extension. Therefore a good file icon can't be | 1336 // which doesn't have the final extension. Therefore a good file icon can't be |
| 1177 // found, so use GetTargetFilePath() instead. | 1337 // found, so use GetTargetFilePath() instead. |
| 1178 DCHECK(icon_extractor_.get()); | 1338 DCHECK(icon_extractor_.get()); |
| 1179 DCHECK(icon_size == 16 || icon_size == 32); | 1339 DCHECK(icon_size == 16 || icon_size == 32); |
| 1180 EXTENSION_FUNCTION_VALIDATE(icon_extractor_->ExtractIconURLForPath( | 1340 EXTENSION_FUNCTION_VALIDATE(icon_extractor_->ExtractIconURLForPath( |
| 1181 download_item->GetTargetFilePath(), | 1341 download_item->GetTargetFilePath(), |
| 1182 IconLoaderSizeFromPixelSize(icon_size), | 1342 IconLoaderSizeFromPixelSize(icon_size), |
| 1183 base::Bind(&DownloadsGetFileIconFunction::OnIconURLExtracted, this))); | 1343 base::Bind(&DownloadsGetFileIconFunction::OnIconURLExtracted, this))); |
| 1184 return true; | 1344 return true; |
| 1185 } | 1345 } |
| 1186 | 1346 |
| 1187 void DownloadsGetFileIconFunction::OnIconURLExtracted(const std::string& url) { | 1347 void DownloadsGetFileIconFunction::OnIconURLExtracted(const std::string& url) { |
| 1188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1348 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1189 if (url.empty()) { | 1349 if (Fault(url.empty(), errors::kIconNotFound, &error_)) { |
| 1190 error_ = download_extension_errors::kIconNotFoundError; | 1350 SendResponse(false); |
| 1191 } else { | 1351 return; |
| 1192 RecordApiFunctions(DOWNLOADS_FUNCTION_GET_FILE_ICON); | |
| 1193 SetResult(base::Value::CreateStringValue(url)); | |
| 1194 } | 1352 } |
| 1195 SendResponse(error_.empty()); | 1353 RecordApiFunctions(DOWNLOADS_FUNCTION_GET_FILE_ICON); |
| 1354 SetResult(base::Value::CreateStringValue(url)); | |
| 1355 SendResponse(true); | |
| 1196 } | 1356 } |
| 1197 | 1357 |
| 1198 ExtensionDownloadsEventRouter::ExtensionDownloadsEventRouter( | 1358 ExtensionDownloadsEventRouter::ExtensionDownloadsEventRouter( |
| 1199 Profile* profile, | 1359 Profile* profile, |
| 1200 DownloadManager* manager) | 1360 DownloadManager* manager) |
| 1201 : profile_(profile), | 1361 : profile_(profile), |
| 1202 notifier_(manager, this) { | 1362 notifier_(manager, this) { |
| 1203 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1363 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1204 DCHECK(profile_); | 1364 DCHECK(profile_); |
| 1205 extensions::EventRouter* router = extensions::ExtensionSystem::Get(profile_)-> | 1365 extensions::EventRouter* router = extensions::ExtensionSystem::Get(profile_)-> |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1260 item, profile_->IsOffTheRecord()).release(); | 1420 item, profile_->IsOffTheRecord()).release(); |
| 1261 json->SetString(kFilenameKey, suggested_path.LossyDisplayName()); | 1421 json->SetString(kFilenameKey, suggested_path.LossyDisplayName()); |
| 1262 DispatchEvent(events::kOnDownloadDeterminingFilename, | 1422 DispatchEvent(events::kOnDownloadDeterminingFilename, |
| 1263 false, | 1423 false, |
| 1264 base::Bind(&OnDeterminingFilenameWillDispatchCallback, | 1424 base::Bind(&OnDeterminingFilenameWillDispatchCallback, |
| 1265 &any_determiners, | 1425 &any_determiners, |
| 1266 data), | 1426 data), |
| 1267 json); | 1427 json); |
| 1268 if (!any_determiners) { | 1428 if (!any_determiners) { |
| 1269 data->ClearPendingDeterminers(); | 1429 data->ClearPendingDeterminers(); |
| 1270 no_change.Run(); | 1430 if (!data->creator_suggested_filename().empty()) { |
| 1431 change.Run(data->creator_suggested_filename(), | |
| 1432 ConvertConflictAction(data->creator_conflict_action())); | |
| 1433 // If all listeners are removed, don't keep |data| around. | |
| 1434 data->ResetCreatorSuggestion(); | |
| 1435 } else { | |
| 1436 no_change.Run(); | |
| 1437 } | |
| 1271 } | 1438 } |
| 1272 } | 1439 } |
| 1273 | 1440 |
| 1274 bool ExtensionDownloadsEventRouter::DetermineFilename( | 1441 bool ExtensionDownloadsEventRouter::DetermineFilename( |
| 1275 Profile* profile, | 1442 Profile* profile, |
| 1276 bool include_incognito, | 1443 bool include_incognito, |
| 1277 const std::string& ext_id, | 1444 const std::string& ext_id, |
| 1278 int download_id, | 1445 int download_id, |
| 1279 const base::FilePath& const_filename, | 1446 const base::FilePath& const_filename, |
| 1280 extensions::api::downloads::FilenameConflictAction conflict_action, | 1447 extensions::api::downloads::FilenameConflictAction conflict_action, |
| 1281 std::string* error) { | 1448 std::string* error) { |
| 1282 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1449 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1283 DownloadItem* item = GetDownload(profile, include_incognito, download_id); | 1450 DownloadItem* item = GetDownload(profile, include_incognito, download_id); |
| 1284 if (!item) { | |
| 1285 *error = download_extension_errors::kInvalidOperationError; | |
| 1286 return false; | |
| 1287 } | |
| 1288 ExtensionDownloadsEventRouterData* data = | 1451 ExtensionDownloadsEventRouterData* data = |
| 1289 ExtensionDownloadsEventRouterData::Get(item); | 1452 item ? ExtensionDownloadsEventRouterData::Get(item) : NULL; |
| 1290 if (!data) { | |
| 1291 *error = download_extension_errors::kInvalidOperationError; | |
| 1292 return false; | |
| 1293 } | |
| 1294 // maxListeners=1 in downloads.idl and suggestCallback in | 1453 // maxListeners=1 in downloads.idl and suggestCallback in |
| 1295 // downloads_custom_bindings.js should prevent duplicate DeterminerCallback | 1454 // downloads_custom_bindings.js should prevent duplicate DeterminerCallback |
| 1296 // calls from the same renderer, but an extension may have more than one | 1455 // calls from the same renderer, but an extension may have more than one |
| 1297 // renderer, so don't DCHECK(!reported). | 1456 // renderer, so don't DCHECK(!reported). |
| 1298 if (data->DeterminerAlreadyReported(ext_id)) { | 1457 if (InvalidId(item, error) || |
| 1299 *error = download_extension_errors::kTooManyListenersError; | 1458 Fault(item->GetState() != DownloadItem::IN_PROGRESS, |
| 1459 errors::kNotInProgress, error) || | |
| 1460 Fault(!data, errors::kUnexpectedDeterminer, error) || | |
| 1461 Fault(data->DeterminerAlreadyReported(ext_id), | |
| 1462 errors::kTooManyListeners, error)) | |
| 1300 return false; | 1463 return false; |
| 1301 } | |
| 1302 if (item->GetState() != DownloadItem::IN_PROGRESS) { | |
| 1303 *error = download_extension_errors::kInvalidOperationError; | |
| 1304 return false; | |
| 1305 } | |
| 1306 base::FilePath::StringType filename_str(const_filename.value()); | 1464 base::FilePath::StringType filename_str(const_filename.value()); |
| 1307 // Allow windows-style directory separators on all platforms. | 1465 // Allow windows-style directory separators on all platforms. |
| 1308 std::replace(filename_str.begin(), filename_str.end(), | 1466 std::replace(filename_str.begin(), filename_str.end(), |
| 1309 FILE_PATH_LITERAL('\\'), FILE_PATH_LITERAL('/')); | 1467 FILE_PATH_LITERAL('\\'), FILE_PATH_LITERAL('/')); |
| 1310 base::FilePath filename(filename_str); | 1468 base::FilePath filename(filename_str); |
| 1311 bool valid_filename = net::IsSafePortableRelativePath(filename); | 1469 bool valid_filename = net::IsSafePortableRelativePath(filename); |
| 1312 filename = (valid_filename ? filename.NormalizePathSeparators() : | 1470 filename = (valid_filename ? filename.NormalizePathSeparators() : |
| 1313 base::FilePath()); | 1471 base::FilePath()); |
| 1314 if (!data->DeterminerCallback(ext_id, filename, conflict_action)) { | 1472 // If the invalid filename check is moved to before DeterminerCallback(), then |
| 1315 // Nobody expects this ext_id! | 1473 // it will block forever waiting for this ext_id to report. |
| 1316 *error = download_extension_errors::kInvalidOperationError; | 1474 if (Fault(!data->DeterminerCallback(ext_id, filename, conflict_action), |
| 1475 errors::kUnexpectedDeterminer, error) || | |
| 1476 Fault((!const_filename.empty() && !valid_filename), | |
| 1477 errors::kInvalidFilename, error)) | |
| 1317 return false; | 1478 return false; |
| 1318 } | |
| 1319 if (!const_filename.empty() && !valid_filename) { | |
| 1320 // If this is moved to before DeterminerCallback(), then it will block | |
| 1321 // forever waiting for this ext_id to report. | |
| 1322 *error = download_extension_errors::kInvalidFilenameError; | |
| 1323 return false; | |
| 1324 } | |
| 1325 return true; | 1479 return true; |
| 1326 } | 1480 } |
| 1327 | 1481 |
| 1328 void ExtensionDownloadsEventRouter::OnListenerRemoved( | 1482 void ExtensionDownloadsEventRouter::OnListenerRemoved( |
| 1329 const extensions::EventListenerInfo& details) { | 1483 const extensions::EventListenerInfo& details) { |
| 1330 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 1484 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 1331 DownloadManager* manager = notifier_.GetManager(); | 1485 DownloadManager* manager = notifier_.GetManager(); |
| 1332 if (!manager) | 1486 if (!manager) |
| 1333 return; | 1487 return; |
| 1334 bool determiner_removed = ( | 1488 bool determiner_removed = ( |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 1350 if (!data) | 1504 if (!data) |
| 1351 continue; | 1505 continue; |
| 1352 if (determiner_removed) { | 1506 if (determiner_removed) { |
| 1353 // Notify any items that may be waiting for callbacks from this | 1507 // Notify any items that may be waiting for callbacks from this |
| 1354 // extension/determiner. This will almost always be a no-op, however, it | 1508 // extension/determiner. This will almost always be a no-op, however, it |
| 1355 // is possible for an extension renderer to be unloaded while a download | 1509 // is possible for an extension renderer to be unloaded while a download |
| 1356 // item is waiting for a determiner. In that case, the download item | 1510 // item is waiting for a determiner. In that case, the download item |
| 1357 // should proceed. | 1511 // should proceed. |
| 1358 data->DeterminerRemoved(details.extension_id); | 1512 data->DeterminerRemoved(details.extension_id); |
| 1359 } | 1513 } |
| 1360 if (!any_listeners) { | 1514 if (!any_listeners && |
| 1515 data->creator_suggested_filename().empty()) { | |
| 1361 ExtensionDownloadsEventRouterData::Remove(*iter); | 1516 ExtensionDownloadsEventRouterData::Remove(*iter); |
| 1362 } | 1517 } |
| 1363 } | 1518 } |
| 1364 } | 1519 } |
| 1365 | 1520 |
| 1366 // That's all the methods that have to do with filename determination. The rest | 1521 // That's all the methods that have to do with filename determination. The rest |
| 1367 // have to do with the other, less special events. | 1522 // have to do with the other, less special events. |
| 1368 | 1523 |
| 1369 void ExtensionDownloadsEventRouter::OnDownloadCreated( | 1524 void ExtensionDownloadsEventRouter::OnDownloadCreated( |
| 1370 DownloadManager* manager, DownloadItem* download_item) { | 1525 DownloadManager* manager, DownloadItem* download_item) { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1420 std::set<std::string> new_fields; | 1575 std::set<std::string> new_fields; |
| 1421 bool changed = false; | 1576 bool changed = false; |
| 1422 | 1577 |
| 1423 // For each field in the new json representation of the download_item except | 1578 // For each field in the new json representation of the download_item except |
| 1424 // the bytesReceived field, if the field has changed from the previous old | 1579 // the bytesReceived field, if the field has changed from the previous old |
| 1425 // json, set the differences in the |delta| object and remember that something | 1580 // json, set the differences in the |delta| object and remember that something |
| 1426 // significant changed. | 1581 // significant changed. |
| 1427 for (base::DictionaryValue::Iterator iter(*new_json.get()); | 1582 for (base::DictionaryValue::Iterator iter(*new_json.get()); |
| 1428 !iter.IsAtEnd(); iter.Advance()) { | 1583 !iter.IsAtEnd(); iter.Advance()) { |
| 1429 new_fields.insert(iter.key()); | 1584 new_fields.insert(iter.key()); |
| 1430 if (iter.key() != kBytesReceivedKey) { | 1585 if (IsDownloadDeltaField(iter.key())) { |
| 1431 const base::Value* old_value = NULL; | 1586 const base::Value* old_value = NULL; |
| 1432 if (!data->json().HasKey(iter.key()) || | 1587 if (!data->json().HasKey(iter.key()) || |
| 1433 (data->json().Get(iter.key(), &old_value) && | 1588 (data->json().Get(iter.key(), &old_value) && |
| 1434 !iter.value().Equals(old_value))) { | 1589 !iter.value().Equals(old_value))) { |
| 1435 delta->Set(iter.key() + ".current", iter.value().DeepCopy()); | 1590 delta->Set(iter.key() + ".current", iter.value().DeepCopy()); |
| 1436 if (old_value) | 1591 if (old_value) |
| 1437 delta->Set(iter.key() + ".previous", old_value->DeepCopy()); | 1592 delta->Set(iter.key() + ".previous", old_value->DeepCopy()); |
| 1438 changed = true; | 1593 changed = true; |
| 1439 } | 1594 } |
| 1440 } | 1595 } |
| 1441 } | 1596 } |
| 1442 | 1597 |
| 1443 // If a field was in the previous json but is not in the new json, set the | 1598 // If a field was in the previous json but is not in the new json, set the |
| 1444 // difference in |delta|. | 1599 // difference in |delta|. |
| 1445 for (base::DictionaryValue::Iterator iter(data->json()); | 1600 for (base::DictionaryValue::Iterator iter(data->json()); |
| 1446 !iter.IsAtEnd(); iter.Advance()) { | 1601 !iter.IsAtEnd(); iter.Advance()) { |
| 1447 if (new_fields.find(iter.key()) == new_fields.end()) { | 1602 if ((new_fields.find(iter.key()) == new_fields.end()) && |
| 1603 IsDownloadDeltaField(iter.key())) { | |
| 1604 // estimatedEndTime disappears after completion, but bytesReceived stays. | |
| 1448 delta->Set(iter.key() + ".previous", iter.value().DeepCopy()); | 1605 delta->Set(iter.key() + ".previous", iter.value().DeepCopy()); |
| 1449 changed = true; | 1606 changed = true; |
| 1450 } | 1607 } |
| 1451 } | 1608 } |
| 1452 | 1609 |
| 1453 // Update the OnChangedStat and dispatch the event if something significant | 1610 // Update the OnChangedStat and dispatch the event if something significant |
| 1454 // changed. Replace the stored json with the new json. | 1611 // changed. Replace the stored json with the new json. |
| 1455 data->OnItemUpdated(); | 1612 data->OnItemUpdated(); |
| 1456 if (changed) { | 1613 if (changed) { |
| 1457 DispatchEvent(events::kOnDownloadChanged, | 1614 DispatchEvent(events::kOnDownloadChanged, |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1501 DownloadsNotificationSource notification_source; | 1658 DownloadsNotificationSource notification_source; |
| 1502 notification_source.event_name = event_name; | 1659 notification_source.event_name = event_name; |
| 1503 notification_source.profile = profile_; | 1660 notification_source.profile = profile_; |
| 1504 content::Source<DownloadsNotificationSource> content_source( | 1661 content::Source<DownloadsNotificationSource> content_source( |
| 1505 ¬ification_source); | 1662 ¬ification_source); |
| 1506 content::NotificationService::current()->Notify( | 1663 content::NotificationService::current()->Notify( |
| 1507 chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT, | 1664 chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT, |
| 1508 content_source, | 1665 content_source, |
| 1509 content::Details<std::string>(&json_args)); | 1666 content::Details<std::string>(&json_args)); |
| 1510 } | 1667 } |
| OLD | NEW |