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