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/download/download_danger_prompt.h" | 31 #include "chrome/browser/download/download_danger_prompt.h" |
31 #include "chrome/browser/download/download_file_icon_extractor.h" | 32 #include "chrome/browser/download/download_file_icon_extractor.h" |
33 #include "chrome/browser/download/download_prefs.h" | |
32 #include "chrome/browser/download/download_query.h" | 34 #include "chrome/browser/download/download_query.h" |
33 #include "chrome/browser/download/download_service.h" | 35 #include "chrome/browser/download/download_service.h" |
34 #include "chrome/browser/download/download_service_factory.h" | 36 #include "chrome/browser/download/download_service_factory.h" |
37 #include "chrome/browser/download/download_shelf.h" | |
35 #include "chrome/browser/download/download_util.h" | 38 #include "chrome/browser/download/download_util.h" |
36 #include "chrome/browser/extensions/event_names.h" | 39 #include "chrome/browser/extensions/event_names.h" |
37 #include "chrome/browser/extensions/event_router.h" | 40 #include "chrome/browser/extensions/event_router.h" |
38 #include "chrome/browser/extensions/extension_function_dispatcher.h" | 41 #include "chrome/browser/extensions/extension_function_dispatcher.h" |
39 #include "chrome/browser/extensions/extension_info_map.h" | 42 #include "chrome/browser/extensions/extension_info_map.h" |
40 #include "chrome/browser/extensions/extension_prefs.h" | 43 #include "chrome/browser/extensions/extension_prefs.h" |
41 #include "chrome/browser/extensions/extension_service.h" | 44 #include "chrome/browser/extensions/extension_service.h" |
42 #include "chrome/browser/extensions/extension_system.h" | 45 #include "chrome/browser/extensions/extension_system.h" |
43 #include "chrome/browser/icon_loader.h" | 46 #include "chrome/browser/icon_loader.h" |
44 #include "chrome/browser/icon_manager.h" | 47 #include "chrome/browser/icon_manager.h" |
48 #include "chrome/browser/platform_util.h" | |
45 #include "chrome/browser/renderer_host/chrome_render_message_filter.h" | 49 #include "chrome/browser/renderer_host/chrome_render_message_filter.h" |
46 #include "chrome/browser/ui/browser.h" | 50 #include "chrome/browser/ui/browser.h" |
51 #include "chrome/browser/ui/browser_window.h" | |
47 #include "chrome/common/cancelable_task_tracker.h" | 52 #include "chrome/common/cancelable_task_tracker.h" |
48 #include "chrome/common/chrome_notification_types.h" | 53 #include "chrome/common/chrome_notification_types.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" |
(...skipping 13 matching lines...) Expand all Loading... | |
70 | 75 |
71 using content::BrowserContext; | 76 using content::BrowserContext; |
72 using content::BrowserThread; | 77 using content::BrowserThread; |
73 using content::DownloadId; | 78 using content::DownloadId; |
74 using content::DownloadItem; | 79 using content::DownloadItem; |
75 using content::DownloadManager; | 80 using content::DownloadManager; |
76 | 81 |
77 namespace download_extension_errors { | 82 namespace download_extension_errors { |
78 | 83 |
79 // Error messages | 84 // Error messages |
80 const char kGenericError[] = "I'm afraid I can't do that"; | |
81 const char kIconNotFoundError[] = "Icon not found"; | 85 const char kIconNotFoundError[] = "Icon not found"; |
82 const char kInvalidDangerTypeError[] = "Invalid danger type"; | 86 const char kInvalidDangerTypeError[] = "Invalid danger type"; |
83 const char kInvalidFilenameError[] = "Invalid filename"; | 87 const char kInvalidFilenameError[] = "Invalid filename"; |
84 const char kInvalidFilterError[] = "Invalid query filter"; | 88 const char kInvalidFilterError[] = "Invalid query filter"; |
89 const char kInvalidHeaderError[] = "Invalid request header"; | |
85 const char kInvalidOperationError[] = "Invalid operation"; | 90 const char kInvalidOperationError[] = "Invalid operation"; |
86 const char kInvalidOrderByError[] = "Invalid orderBy field"; | 91 const char kInvalidOrderByError[] = "Invalid orderBy field"; |
87 const char kInvalidQueryLimit[] = "Invalid query limit"; | 92 const char kInvalidQueryLimit[] = "Invalid query limit"; |
88 const char kInvalidStateError[] = "Invalid state"; | 93 const char kInvalidStateError[] = "Invalid state"; |
89 const char kInvalidURLError[] = "Invalid URL"; | 94 const char kInvalidURLError[] = "Invalid URL"; |
95 const char kNotPermittedURLError[] = "In order to access that URL, this " | |
96 "extension must add the host to \"permissions\" in manifest.json"; | |
90 const char kNotImplementedError[] = "NotImplemented"; | 97 const char kNotImplementedError[] = "NotImplemented"; |
91 const char kTooManyListenersError[] = "Each extension may have at most one " | 98 const char kTooManyListenersError[] = "Each extension may have at most one " |
92 "onDeterminingFilename listener between all of its renderer execution " | 99 "onDeterminingFilename listener between all of its renderer execution " |
93 "contexts."; | 100 "contexts."; |
94 | 101 |
95 } // namespace download_extension_errors | 102 } // namespace download_extension_errors |
96 | 103 |
97 namespace { | 104 namespace { |
98 | 105 |
99 // Default icon size for getFileIcon() in pixels. | 106 // Default icon size for getFileIcon() in pixels. |
100 const int kDefaultIconSize = 32; | 107 const int kDefaultIconSize = 32; |
101 | 108 |
102 // Parameter keys | 109 // Parameter keys |
103 const char kBytesReceivedKey[] = "bytesReceived"; | 110 const char kBytesReceivedKey[] = "bytesReceived"; |
104 const char kDangerAcceptedKey[] = "dangerAccepted"; | 111 const char kCanResumeKey[] = "canResume"; |
112 const char kDangerAccepted[] = "accepted"; | |
105 const char kDangerContent[] = "content"; | 113 const char kDangerContent[] = "content"; |
106 const char kDangerFile[] = "file"; | 114 const char kDangerFile[] = "file"; |
115 const char kDangerHost[] = "host"; | |
107 const char kDangerKey[] = "danger"; | 116 const char kDangerKey[] = "danger"; |
108 const char kDangerSafe[] = "safe"; | 117 const char kDangerSafe[] = "safe"; |
109 const char kDangerUncommon[] = "uncommon"; | 118 const char kDangerUncommon[] = "uncommon"; |
110 const char kDangerAccepted[] = "accepted"; | |
111 const char kDangerHost[] = "host"; | |
112 const char kDangerUrl[] = "url"; | 119 const char kDangerUrl[] = "url"; |
113 const char kEndTimeKey[] = "endTime"; | 120 const char kEndTimeKey[] = "endTime"; |
114 const char kEndedAfterKey[] = "endedAfter"; | 121 const char kEndedAfterKey[] = "endedAfter"; |
115 const char kEndedBeforeKey[] = "endedBefore"; | 122 const char kEndedBeforeKey[] = "endedBefore"; |
116 const char kErrorKey[] = "error"; | 123 const char kErrorKey[] = "error"; |
124 const char kEstimatedEndTimeKey[] = "estimatedEndTime"; | |
117 const char kExistsKey[] = "exists"; | 125 const char kExistsKey[] = "exists"; |
118 const char kFileSizeKey[] = "fileSize"; | 126 const char kFileSizeKey[] = "fileSize"; |
119 const char kFilenameKey[] = "filename"; | 127 const char kFilenameKey[] = "filename"; |
120 const char kFilenameRegexKey[] = "filenameRegex"; | 128 const char kFilenameRegexKey[] = "filenameRegex"; |
121 const char kIdKey[] = "id"; | 129 const char kIdKey[] = "id"; |
122 const char kIncognito[] = "incognito"; | 130 const char kIncognito[] = "incognito"; |
123 const char kMimeKey[] = "mime"; | 131 const char kMimeKey[] = "mime"; |
124 const char kPausedKey[] = "paused"; | 132 const char kPausedKey[] = "paused"; |
125 const char kQueryKey[] = "query"; | 133 const char kQueryKey[] = "query"; |
134 const char kReferrerUrlKey[] = "referrer"; | |
126 const char kStartTimeKey[] = "startTime"; | 135 const char kStartTimeKey[] = "startTime"; |
127 const char kStartedAfterKey[] = "startedAfter"; | 136 const char kStartedAfterKey[] = "startedAfter"; |
128 const char kStartedBeforeKey[] = "startedBefore"; | 137 const char kStartedBeforeKey[] = "startedBefore"; |
129 const char kStateComplete[] = "complete"; | 138 const char kStateComplete[] = "complete"; |
130 const char kStateInProgress[] = "in_progress"; | 139 const char kStateInProgress[] = "in_progress"; |
131 const char kStateInterrupted[] = "interrupted"; | 140 const char kStateInterrupted[] = "interrupted"; |
132 const char kStateKey[] = "state"; | 141 const char kStateKey[] = "state"; |
133 const char kTotalBytesGreaterKey[] = "totalBytesGreater"; | 142 const char kTotalBytesGreaterKey[] = "totalBytesGreater"; |
134 const char kTotalBytesKey[] = "totalBytes"; | 143 const char kTotalBytesKey[] = "totalBytes"; |
135 const char kTotalBytesLessKey[] = "totalBytesLess"; | 144 const char kTotalBytesLessKey[] = "totalBytesLess"; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
208 } | 217 } |
209 | 218 |
210 scoped_ptr<base::DictionaryValue> DownloadItemToJSON( | 219 scoped_ptr<base::DictionaryValue> DownloadItemToJSON( |
211 DownloadItem* download_item, | 220 DownloadItem* download_item, |
212 bool incognito) { | 221 bool incognito) { |
213 base::DictionaryValue* json = new base::DictionaryValue(); | 222 base::DictionaryValue* json = new base::DictionaryValue(); |
214 json->SetBoolean(kExistsKey, !download_item->GetFileExternallyRemoved()); | 223 json->SetBoolean(kExistsKey, !download_item->GetFileExternallyRemoved()); |
215 json->SetInteger(kIdKey, download_item->GetId()); | 224 json->SetInteger(kIdKey, download_item->GetId()); |
216 const GURL& url = download_item->GetOriginalUrl(); | 225 const GURL& url = download_item->GetOriginalUrl(); |
217 json->SetString(kUrlKey, (url.is_valid() ? url.spec() : std::string())); | 226 json->SetString(kUrlKey, (url.is_valid() ? url.spec() : std::string())); |
227 const GURL& referrer = download_item->GetReferrerUrl(); | |
228 json->SetString(kReferrerUrlKey, (referrer.is_valid() ? referrer.spec() | |
229 : std::string())); | |
218 json->SetString(kFilenameKey, | 230 json->SetString(kFilenameKey, |
219 download_item->GetTargetFilePath().LossyDisplayName()); | 231 download_item->GetTargetFilePath().LossyDisplayName()); |
220 json->SetString(kDangerKey, DangerString(download_item->GetDangerType())); | 232 json->SetString(kDangerKey, DangerString(download_item->GetDangerType())); |
221 if (download_item->GetDangerType() != | |
222 content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) | |
223 json->SetBoolean(kDangerAcceptedKey, | |
224 download_item->GetDangerType() == | |
225 content::DOWNLOAD_DANGER_TYPE_USER_VALIDATED); | |
226 json->SetString(kStateKey, StateString(download_item->GetState())); | 233 json->SetString(kStateKey, StateString(download_item->GetState())); |
234 json->SetBoolean(kCanResumeKey, download_item->CanResume()); | |
227 json->SetBoolean(kPausedKey, download_item->IsPaused()); | 235 json->SetBoolean(kPausedKey, download_item->IsPaused()); |
228 json->SetString(kMimeKey, download_item->GetMimeType()); | 236 json->SetString(kMimeKey, download_item->GetMimeType()); |
229 json->SetString(kStartTimeKey, TimeToISO8601(download_item->GetStartTime())); | 237 json->SetString(kStartTimeKey, TimeToISO8601(download_item->GetStartTime())); |
230 json->SetInteger(kBytesReceivedKey, download_item->GetReceivedBytes()); | 238 json->SetInteger(kBytesReceivedKey, download_item->GetReceivedBytes()); |
231 json->SetInteger(kTotalBytesKey, download_item->GetTotalBytes()); | 239 json->SetInteger(kTotalBytesKey, download_item->GetTotalBytes()); |
232 json->SetBoolean(kIncognito, incognito); | 240 json->SetBoolean(kIncognito, incognito); |
233 if (download_item->GetState() == DownloadItem::INTERRUPTED) { | 241 if (download_item->GetState() == DownloadItem::INTERRUPTED) { |
234 json->SetInteger(kErrorKey, static_cast<int>( | 242 json->SetString(kErrorKey, content::InterruptReasonDebugString( |
235 download_item->GetLastReason())); | 243 download_item->GetLastReason())); |
236 } else if (download_item->GetState() == DownloadItem::CANCELLED) { | 244 } else if (download_item->GetState() == DownloadItem::CANCELLED) { |
237 json->SetInteger(kErrorKey, static_cast<int>( | 245 json->SetString(kErrorKey, content::InterruptReasonDebugString( |
238 content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED)); | 246 content::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED)); |
239 } | 247 } |
240 if (!download_item->GetEndTime().is_null()) | 248 if (!download_item->GetEndTime().is_null()) |
241 json->SetString(kEndTimeKey, TimeToISO8601(download_item->GetEndTime())); | 249 json->SetString(kEndTimeKey, TimeToISO8601(download_item->GetEndTime())); |
250 base::TimeDelta time_remaining; | |
251 if (download_item->TimeRemaining(&time_remaining)) { | |
252 base::Time now = base::Time::Now(); | |
253 json->SetString(kEstimatedEndTimeKey, TimeToISO8601(now + time_remaining)); | |
254 } | |
242 // TODO(benjhayden): Implement fileSize. | 255 // TODO(benjhayden): Implement fileSize. |
243 json->SetInteger(kFileSizeKey, download_item->GetTotalBytes()); | 256 json->SetInteger(kFileSizeKey, download_item->GetTotalBytes()); |
244 return scoped_ptr<base::DictionaryValue>(json); | 257 return scoped_ptr<base::DictionaryValue>(json); |
245 } | 258 } |
246 | 259 |
247 class DownloadFileIconExtractorImpl : public DownloadFileIconExtractor { | 260 class DownloadFileIconExtractorImpl : public DownloadFileIconExtractor { |
248 public: | 261 public: |
249 DownloadFileIconExtractorImpl() {} | 262 DownloadFileIconExtractorImpl() {} |
250 | 263 |
251 virtual ~DownloadFileIconExtractorImpl() {} | 264 virtual ~DownloadFileIconExtractorImpl() {} |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
292 default: | 305 default: |
293 NOTREACHED(); | 306 NOTREACHED(); |
294 return IconLoader::NORMAL; | 307 return IconLoader::NORMAL; |
295 } | 308 } |
296 } | 309 } |
297 | 310 |
298 typedef base::hash_map<std::string, DownloadQuery::FilterType> FilterTypeMap; | 311 typedef base::hash_map<std::string, DownloadQuery::FilterType> FilterTypeMap; |
299 | 312 |
300 void InitFilterTypeMap(FilterTypeMap& filter_types) { | 313 void InitFilterTypeMap(FilterTypeMap& filter_types) { |
301 filter_types[kBytesReceivedKey] = DownloadQuery::FILTER_BYTES_RECEIVED; | 314 filter_types[kBytesReceivedKey] = DownloadQuery::FILTER_BYTES_RECEIVED; |
302 filter_types[kDangerAcceptedKey] = DownloadQuery::FILTER_DANGER_ACCEPTED; | |
303 filter_types[kExistsKey] = DownloadQuery::FILTER_EXISTS; | 315 filter_types[kExistsKey] = DownloadQuery::FILTER_EXISTS; |
304 filter_types[kFilenameKey] = DownloadQuery::FILTER_FILENAME; | 316 filter_types[kFilenameKey] = DownloadQuery::FILTER_FILENAME; |
305 filter_types[kFilenameRegexKey] = DownloadQuery::FILTER_FILENAME_REGEX; | 317 filter_types[kFilenameRegexKey] = DownloadQuery::FILTER_FILENAME_REGEX; |
306 filter_types[kMimeKey] = DownloadQuery::FILTER_MIME; | 318 filter_types[kMimeKey] = DownloadQuery::FILTER_MIME; |
307 filter_types[kPausedKey] = DownloadQuery::FILTER_PAUSED; | 319 filter_types[kPausedKey] = DownloadQuery::FILTER_PAUSED; |
308 filter_types[kQueryKey] = DownloadQuery::FILTER_QUERY; | 320 filter_types[kQueryKey] = DownloadQuery::FILTER_QUERY; |
309 filter_types[kEndedAfterKey] = DownloadQuery::FILTER_ENDED_AFTER; | 321 filter_types[kEndedAfterKey] = DownloadQuery::FILTER_ENDED_AFTER; |
310 filter_types[kEndedBeforeKey] = DownloadQuery::FILTER_ENDED_BEFORE; | 322 filter_types[kEndedBeforeKey] = DownloadQuery::FILTER_ENDED_BEFORE; |
311 filter_types[kEndTimeKey] = DownloadQuery::FILTER_END_TIME; | 323 filter_types[kEndTimeKey] = DownloadQuery::FILTER_END_TIME; |
312 filter_types[kStartedAfterKey] = DownloadQuery::FILTER_STARTED_AFTER; | 324 filter_types[kStartedAfterKey] = DownloadQuery::FILTER_STARTED_AFTER; |
313 filter_types[kStartedBeforeKey] = DownloadQuery::FILTER_STARTED_BEFORE; | 325 filter_types[kStartedBeforeKey] = DownloadQuery::FILTER_STARTED_BEFORE; |
314 filter_types[kStartTimeKey] = DownloadQuery::FILTER_START_TIME; | 326 filter_types[kStartTimeKey] = DownloadQuery::FILTER_START_TIME; |
315 filter_types[kTotalBytesKey] = DownloadQuery::FILTER_TOTAL_BYTES; | 327 filter_types[kTotalBytesKey] = DownloadQuery::FILTER_TOTAL_BYTES; |
316 filter_types[kTotalBytesGreaterKey] = | 328 filter_types[kTotalBytesGreaterKey] = |
317 DownloadQuery::FILTER_TOTAL_BYTES_GREATER; | 329 DownloadQuery::FILTER_TOTAL_BYTES_GREATER; |
318 filter_types[kTotalBytesLessKey] = DownloadQuery::FILTER_TOTAL_BYTES_LESS; | 330 filter_types[kTotalBytesLessKey] = DownloadQuery::FILTER_TOTAL_BYTES_LESS; |
319 filter_types[kUrlKey] = DownloadQuery::FILTER_URL; | 331 filter_types[kUrlKey] = DownloadQuery::FILTER_URL; |
320 filter_types[kUrlRegexKey] = DownloadQuery::FILTER_URL_REGEX; | 332 filter_types[kUrlRegexKey] = DownloadQuery::FILTER_URL_REGEX; |
321 } | 333 } |
322 | 334 |
323 typedef base::hash_map<std::string, DownloadQuery::SortType> SortTypeMap; | 335 typedef base::hash_map<std::string, DownloadQuery::SortType> SortTypeMap; |
324 | 336 |
325 void InitSortTypeMap(SortTypeMap& sorter_types) { | 337 void InitSortTypeMap(SortTypeMap& sorter_types) { |
326 sorter_types[kBytesReceivedKey] = DownloadQuery::SORT_BYTES_RECEIVED; | 338 sorter_types[kBytesReceivedKey] = DownloadQuery::SORT_BYTES_RECEIVED; |
327 sorter_types[kDangerKey] = DownloadQuery::SORT_DANGER; | 339 sorter_types[kDangerKey] = DownloadQuery::SORT_DANGER; |
328 sorter_types[kDangerAcceptedKey] = DownloadQuery::SORT_DANGER_ACCEPTED; | |
329 sorter_types[kEndTimeKey] = DownloadQuery::SORT_END_TIME; | 340 sorter_types[kEndTimeKey] = DownloadQuery::SORT_END_TIME; |
330 sorter_types[kExistsKey] = DownloadQuery::SORT_EXISTS; | 341 sorter_types[kExistsKey] = DownloadQuery::SORT_EXISTS; |
331 sorter_types[kFilenameKey] = DownloadQuery::SORT_FILENAME; | 342 sorter_types[kFilenameKey] = DownloadQuery::SORT_FILENAME; |
332 sorter_types[kMimeKey] = DownloadQuery::SORT_MIME; | 343 sorter_types[kMimeKey] = DownloadQuery::SORT_MIME; |
333 sorter_types[kPausedKey] = DownloadQuery::SORT_PAUSED; | 344 sorter_types[kPausedKey] = DownloadQuery::SORT_PAUSED; |
334 sorter_types[kStartTimeKey] = DownloadQuery::SORT_START_TIME; | 345 sorter_types[kStartTimeKey] = DownloadQuery::SORT_START_TIME; |
335 sorter_types[kStateKey] = DownloadQuery::SORT_STATE; | 346 sorter_types[kStateKey] = DownloadQuery::SORT_STATE; |
336 sorter_types[kTotalBytesKey] = DownloadQuery::SORT_TOTAL_BYTES; | 347 sorter_types[kTotalBytesKey] = DownloadQuery::SORT_TOTAL_BYTES; |
337 sorter_types[kUrlKey] = DownloadQuery::SORT_URL; | 348 sorter_types[kUrlKey] = DownloadQuery::SORT_URL; |
338 } | 349 } |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
387 DOWNLOADS_FUNCTION_PAUSE = 2, | 398 DOWNLOADS_FUNCTION_PAUSE = 2, |
388 DOWNLOADS_FUNCTION_RESUME = 3, | 399 DOWNLOADS_FUNCTION_RESUME = 3, |
389 DOWNLOADS_FUNCTION_CANCEL = 4, | 400 DOWNLOADS_FUNCTION_CANCEL = 4, |
390 DOWNLOADS_FUNCTION_ERASE = 5, | 401 DOWNLOADS_FUNCTION_ERASE = 5, |
391 DOWNLOADS_FUNCTION_SET_DESTINATION = 6, | 402 DOWNLOADS_FUNCTION_SET_DESTINATION = 6, |
392 DOWNLOADS_FUNCTION_ACCEPT_DANGER = 7, | 403 DOWNLOADS_FUNCTION_ACCEPT_DANGER = 7, |
393 DOWNLOADS_FUNCTION_SHOW = 8, | 404 DOWNLOADS_FUNCTION_SHOW = 8, |
394 DOWNLOADS_FUNCTION_DRAG = 9, | 405 DOWNLOADS_FUNCTION_DRAG = 9, |
395 DOWNLOADS_FUNCTION_GET_FILE_ICON = 10, | 406 DOWNLOADS_FUNCTION_GET_FILE_ICON = 10, |
396 DOWNLOADS_FUNCTION_OPEN = 11, | 407 DOWNLOADS_FUNCTION_OPEN = 11, |
408 DOWNLOADS_FUNCTION_DELETE_FILE = 12, | |
409 DOWNLOADS_FUNCTION_SET_SHELF_VISIBLE = 13, | |
397 // Insert new values here, not at the beginning. | 410 // Insert new values here, not at the beginning. |
398 DOWNLOADS_FUNCTION_LAST | 411 DOWNLOADS_FUNCTION_LAST |
399 }; | 412 }; |
400 | 413 |
401 void RecordApiFunctions(DownloadsFunctionName function) { | 414 void RecordApiFunctions(DownloadsFunctionName function) { |
402 UMA_HISTOGRAM_ENUMERATION("Download.ApiFunctions", | 415 UMA_HISTOGRAM_ENUMERATION("Download.ApiFunctions", |
403 function, | 416 function, |
404 DOWNLOADS_FUNCTION_LAST); | 417 DOWNLOADS_FUNCTION_LAST); |
405 } | 418 } |
406 | 419 |
407 void CompileDownloadQueryOrderBy( | 420 void CompileDownloadQueryOrderBy( |
408 const std::string& order_by_str, std::string* error, DownloadQuery* query) { | 421 const std::vector<std::string>& order_by_strs, |
422 std::string* error, | |
423 DownloadQuery* query) { | |
409 // TODO(benjhayden): Consider switching from LazyInstance to explicit string | 424 // TODO(benjhayden): Consider switching from LazyInstance to explicit string |
410 // comparisons. | 425 // comparisons. |
411 static base::LazyInstance<SortTypeMap> sorter_types = | 426 static base::LazyInstance<SortTypeMap> sorter_types = |
412 LAZY_INSTANCE_INITIALIZER; | 427 LAZY_INSTANCE_INITIALIZER; |
413 if (sorter_types.Get().size() == 0) | 428 if (sorter_types.Get().size() == 0) |
414 InitSortTypeMap(sorter_types.Get()); | 429 InitSortTypeMap(sorter_types.Get()); |
415 | 430 |
416 std::vector<std::string> order_by_strs; | |
417 base::SplitString(order_by_str, ' ', &order_by_strs); | |
418 for (std::vector<std::string>::const_iterator iter = order_by_strs.begin(); | 431 for (std::vector<std::string>::const_iterator iter = order_by_strs.begin(); |
419 iter != order_by_strs.end(); ++iter) { | 432 iter != order_by_strs.end(); ++iter) { |
420 std::string term_str = *iter; | 433 std::string term_str = *iter; |
421 if (term_str.empty()) | 434 if (term_str.empty()) |
422 continue; | 435 continue; |
423 DownloadQuery::SortDirection direction = DownloadQuery::ASCENDING; | 436 DownloadQuery::SortDirection direction = DownloadQuery::ASCENDING; |
424 if (term_str[0] == '-') { | 437 if (term_str[0] == '-') { |
425 direction = DownloadQuery::DESCENDING; | 438 direction = DownloadQuery::DESCENDING; |
426 term_str = term_str.substr(1); | 439 term_str = term_str.substr(1); |
427 } | 440 } |
(...skipping 15 matching lines...) Expand all Loading... | |
443 DownloadQuery::DownloadVector* results) { | 456 DownloadQuery::DownloadVector* results) { |
444 // TODO(benjhayden): Consider switching from LazyInstance to explicit string | 457 // TODO(benjhayden): Consider switching from LazyInstance to explicit string |
445 // comparisons. | 458 // comparisons. |
446 static base::LazyInstance<FilterTypeMap> filter_types = | 459 static base::LazyInstance<FilterTypeMap> filter_types = |
447 LAZY_INSTANCE_INITIALIZER; | 460 LAZY_INSTANCE_INITIALIZER; |
448 if (filter_types.Get().size() == 0) | 461 if (filter_types.Get().size() == 0) |
449 InitFilterTypeMap(filter_types.Get()); | 462 InitFilterTypeMap(filter_types.Get()); |
450 | 463 |
451 DownloadQuery query_out; | 464 DownloadQuery query_out; |
452 | 465 |
466 size_t limit = 1000; | |
453 if (query_in.limit.get()) { | 467 if (query_in.limit.get()) { |
454 if (*query_in.limit.get() < 0) { | 468 if (*query_in.limit.get() < 0) { |
455 *error = download_extension_errors::kInvalidQueryLimit; | 469 *error = download_extension_errors::kInvalidQueryLimit; |
456 return; | 470 return; |
457 } | 471 } |
458 query_out.Limit(*query_in.limit.get()); | 472 limit = *query_in.limit.get(); |
459 } | 473 } |
474 if (limit > 0) { | |
475 query_out.Limit(limit); | |
476 } | |
477 | |
460 std::string state_string = | 478 std::string state_string = |
461 extensions::api::downloads::ToString(query_in.state); | 479 extensions::api::downloads::ToString(query_in.state); |
462 if (!state_string.empty()) { | 480 if (!state_string.empty()) { |
463 DownloadItem::DownloadState state = StateEnumFromString(state_string); | 481 DownloadItem::DownloadState state = StateEnumFromString(state_string); |
464 if (state == DownloadItem::MAX_DOWNLOAD_STATE) { | 482 if (state == DownloadItem::MAX_DOWNLOAD_STATE) { |
465 *error = download_extension_errors::kInvalidStateError; | 483 *error = download_extension_errors::kInvalidStateError; |
466 return; | 484 return; |
467 } | 485 } |
468 query_out.AddFilter(state); | 486 query_out.AddFilter(state); |
469 } | 487 } |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
506 all_items.push_back(download_item); | 524 all_items.push_back(download_item); |
507 } else { | 525 } else { |
508 manager->GetAllDownloads(&all_items); | 526 manager->GetAllDownloads(&all_items); |
509 if (incognito_manager) | 527 if (incognito_manager) |
510 incognito_manager->GetAllDownloads(&all_items); | 528 incognito_manager->GetAllDownloads(&all_items); |
511 } | 529 } |
512 query_out.AddFilter(base::Bind(&IsNotTemporaryDownloadFilter)); | 530 query_out.AddFilter(base::Bind(&IsNotTemporaryDownloadFilter)); |
513 query_out.Search(all_items.begin(), all_items.end(), results); | 531 query_out.Search(all_items.begin(), all_items.end(), results); |
514 } | 532 } |
515 | 533 |
534 DownloadPathReservationTracker::FilenameConflictAction ConvertConflictAction( | |
535 extensions::api::downloads::FilenameConflictAction action) { | |
536 switch (action) { | |
537 case extensions::api::downloads::FILENAME_CONFLICT_ACTION_NONE: | |
538 case extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY: | |
539 return DownloadPathReservationTracker::UNIQUIFY; | |
540 case extensions::api::downloads::FILENAME_CONFLICT_ACTION_OVERWRITE: | |
541 return DownloadPathReservationTracker::OVERWRITE; | |
542 case extensions::api::downloads::FILENAME_CONFLICT_ACTION_PROMPT: | |
543 return DownloadPathReservationTracker::PROMPT; | |
544 } | |
545 NOTREACHED(); | |
546 return DownloadPathReservationTracker::UNIQUIFY; | |
547 } | |
548 | |
516 class ExtensionDownloadsEventRouterData : public base::SupportsUserData::Data { | 549 class ExtensionDownloadsEventRouterData : public base::SupportsUserData::Data { |
517 public: | 550 public: |
518 static ExtensionDownloadsEventRouterData* Get(DownloadItem* download_item) { | 551 static ExtensionDownloadsEventRouterData* Get(DownloadItem* download_item) { |
519 base::SupportsUserData::Data* data = download_item->GetUserData(kKey); | 552 base::SupportsUserData::Data* data = download_item->GetUserData(kKey); |
520 return (data == NULL) ? NULL : | 553 return (data == NULL) ? NULL : |
521 static_cast<ExtensionDownloadsEventRouterData*>(data); | 554 static_cast<ExtensionDownloadsEventRouterData*>(data); |
522 } | 555 } |
523 | 556 |
524 static void Remove(DownloadItem* download_item) { | 557 static void Remove(DownloadItem* download_item) { |
525 download_item->RemoveUserData(kKey); | 558 download_item->RemoveUserData(kKey); |
526 } | 559 } |
527 | 560 |
528 explicit ExtensionDownloadsEventRouterData( | 561 explicit ExtensionDownloadsEventRouterData( |
529 DownloadItem* download_item, | 562 DownloadItem* download_item, |
530 scoped_ptr<base::DictionaryValue> json_item) | 563 scoped_ptr<base::DictionaryValue> json_item) |
531 : updated_(0), | 564 : updated_(0), |
532 changed_fired_(0), | 565 changed_fired_(0), |
533 json_(json_item.Pass()), | 566 json_(json_item.Pass()), |
567 creator_conflict_action_( | |
568 extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY), | |
534 determined_conflict_action_( | 569 determined_conflict_action_( |
535 extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY) { | 570 extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY) { |
536 download_item->SetUserData(kKey, this); | 571 download_item->SetUserData(kKey, this); |
537 } | 572 } |
538 | 573 |
539 virtual ~ExtensionDownloadsEventRouterData() { | 574 virtual ~ExtensionDownloadsEventRouterData() { |
540 if (updated_ > 0) { | 575 if (updated_ > 0) { |
541 UMA_HISTOGRAM_PERCENTAGE("Download.OnChanged", | 576 UMA_HISTOGRAM_PERCENTAGE("Download.OnChanged", |
542 (changed_fired_ * 100 / updated_)); | 577 (changed_fired_ * 100 / updated_)); |
543 } | 578 } |
544 } | 579 } |
545 | 580 |
546 const base::DictionaryValue& json() const { return *json_.get(); } | 581 const base::DictionaryValue& json() const { return *json_.get(); } |
547 void set_json(scoped_ptr<base::DictionaryValue> json_item) { | 582 void set_json(scoped_ptr<base::DictionaryValue> json_item) { |
548 json_ = json_item.Pass(); | 583 json_ = json_item.Pass(); |
549 } | 584 } |
550 | 585 |
551 void OnItemUpdated() { ++updated_; } | 586 void OnItemUpdated() { ++updated_; } |
552 void OnChangedFired() { ++changed_fired_; } | 587 void OnChangedFired() { ++changed_fired_; } |
553 | 588 |
554 void set_filename_change_callbacks( | 589 void set_filename_change_callbacks( |
555 const base::Closure& no_change, | 590 const base::Closure& no_change, |
556 const ExtensionDownloadsEventRouter::FilenameChangedCallback& change) { | 591 const ExtensionDownloadsEventRouter::FilenameChangedCallback& change) { |
557 filename_no_change_ = no_change; | 592 filename_no_change_ = no_change; |
558 filename_change_ = change; | 593 filename_change_ = change; |
594 determined_filename_ = creator_suggested_filename_; | |
595 determined_conflict_action_ = creator_conflict_action_; | |
596 // determiner_.install_time should default to 0 so that creator suggestions | |
597 // should be lower priority than any actual onDeterminingFilename listeners. | |
559 } | 598 } |
560 | 599 |
561 void ClearPendingDeterminers() { | 600 void ClearPendingDeterminers() { |
562 determined_filename_.clear(); | 601 determined_filename_.clear(); |
563 determined_conflict_action_ = | 602 determined_conflict_action_ = |
564 extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY; | 603 extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY; |
565 determiner_ = DeterminerInfo(); | 604 determiner_ = DeterminerInfo(); |
566 filename_no_change_ = base::Closure(); | 605 filename_no_change_ = base::Closure(); |
567 filename_change_ = ExtensionDownloadsEventRouter::FilenameChangedCallback(); | 606 filename_change_ = ExtensionDownloadsEventRouter::FilenameChangedCallback(); |
568 weak_ptr_factory_.reset(); | 607 weak_ptr_factory_.reset(); |
(...skipping 27 matching lines...) Expand all Loading... | |
596 | 635 |
597 bool DeterminerAlreadyReported(const std::string& extension_id) { | 636 bool DeterminerAlreadyReported(const std::string& extension_id) { |
598 for (size_t index = 0; index < determiners_.size(); ++index) { | 637 for (size_t index = 0; index < determiners_.size(); ++index) { |
599 if (determiners_[index].extension_id == extension_id) { | 638 if (determiners_[index].extension_id == extension_id) { |
600 return determiners_[index].reported; | 639 return determiners_[index].reported; |
601 } | 640 } |
602 } | 641 } |
603 return false; | 642 return false; |
604 } | 643 } |
605 | 644 |
645 void CreatorSuggestedFilename( | |
646 const base::FilePath& filename, | |
647 extensions::api::downloads::FilenameConflictAction conflict_action) { | |
648 creator_suggested_filename_ = filename; | |
649 creator_conflict_action_ = conflict_action; | |
650 } | |
651 | |
652 base::FilePath creator_suggested_filename() const { | |
653 return creator_suggested_filename_; | |
654 } | |
655 | |
656 extensions::api::downloads::FilenameConflictAction | |
657 creator_conflict_action() const { | |
658 return creator_conflict_action_; | |
659 } | |
660 | |
661 void ResetCreatorSuggestion() { | |
662 creator_suggested_filename_.clear(); | |
663 creator_conflict_action_ = | |
664 extensions::api::downloads::FILENAME_CONFLICT_ACTION_UNIQUIFY; | |
665 } | |
666 | |
606 // Returns false if this |extension_id| was not expected or if this | 667 // Returns false if this |extension_id| was not expected or if this |
607 // |extension_id| has already reported. The caller is responsible for | 668 // |extension_id| has already reported. The caller is responsible for |
608 // validating |filename|. | 669 // validating |filename|. |
609 bool DeterminerCallback( | 670 bool DeterminerCallback( |
610 const std::string& extension_id, | 671 const std::string& extension_id, |
611 const base::FilePath& filename, | 672 const base::FilePath& filename, |
612 extensions::api::downloads::FilenameConflictAction conflict_action) { | 673 extensions::api::downloads::FilenameConflictAction conflict_action) { |
613 bool found_info = false; | 674 bool found_info = false; |
614 for (size_t index = 0; index < determiners_.size(); ++index) { | 675 for (size_t index = 0; index < determiners_.size(); ++index) { |
615 if (determiners_[index].extension_id == extension_id) { | 676 if (determiners_[index].extension_id == extension_id) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
657 for (DeterminerInfoVector::iterator iter = determiners_.begin(); | 718 for (DeterminerInfoVector::iterator iter = determiners_.begin(); |
658 iter != determiners_.end(); ++iter) { | 719 iter != determiners_.end(); ++iter) { |
659 if (!iter->reported) | 720 if (!iter->reported) |
660 return; | 721 return; |
661 } | 722 } |
662 if (determined_filename_.empty()) { | 723 if (determined_filename_.empty()) { |
663 if (!filename_no_change_.is_null()) | 724 if (!filename_no_change_.is_null()) |
664 filename_no_change_.Run(); | 725 filename_no_change_.Run(); |
665 } else { | 726 } else { |
666 if (!filename_change_.is_null()) { | 727 if (!filename_change_.is_null()) { |
667 DownloadPathReservationTracker::FilenameConflictAction conflict_action = | 728 filename_change_.Run(determined_filename_, ConvertConflictAction( |
668 DownloadPathReservationTracker::UNIQUIFY; | 729 determined_conflict_action_)); |
669 if (determined_conflict_action_ == | |
670 extensions::api::downloads::FILENAME_CONFLICT_ACTION_OVERWRITE) | |
671 conflict_action = DownloadPathReservationTracker::OVERWRITE; | |
672 if (determined_conflict_action_ == | |
673 extensions::api::downloads::FILENAME_CONFLICT_ACTION_PROMPT) | |
674 conflict_action = DownloadPathReservationTracker::PROMPT; | |
675 filename_change_.Run(determined_filename_, conflict_action); | |
676 } | 730 } |
677 } | 731 } |
678 // Don't clear determiners_ immediately in case there's a second listener | 732 // Don't clear determiners_ immediately in case there's a second listener |
679 // for one of the extensions, so that DetermineFilename can return | 733 // for one of the extensions, so that DetermineFilename can return |
680 // kTooManyListenersError. After a few seconds, DetermineFilename will | 734 // kTooManyListenersError. After a few seconds, DetermineFilename will |
681 // return kInvalidOperationError instead of kTooManyListenersError so that | 735 // return kInvalidOperationError instead of kTooManyListenersError so that |
682 // determiners_ doesn't keep hogging memory. | 736 // determiners_ doesn't keep hogging memory. |
683 weak_ptr_factory_.reset( | 737 weak_ptr_factory_.reset( |
684 new base::WeakPtrFactory<ExtensionDownloadsEventRouterData>(this)); | 738 new base::WeakPtrFactory<ExtensionDownloadsEventRouterData>(this)); |
685 base::MessageLoopForUI::current()->PostDelayedTask( | 739 base::MessageLoopForUI::current()->PostDelayedTask( |
686 FROM_HERE, | 740 FROM_HERE, |
687 base::Bind(&ExtensionDownloadsEventRouterData::ClearPendingDeterminers, | 741 base::Bind(&ExtensionDownloadsEventRouterData::ClearPendingDeterminers, |
688 weak_ptr_factory_->GetWeakPtr()), | 742 weak_ptr_factory_->GetWeakPtr()), |
689 base::TimeDelta::FromSeconds(30)); | 743 base::TimeDelta::FromSeconds(30)); |
690 } | 744 } |
691 | 745 |
692 int updated_; | 746 int updated_; |
693 int changed_fired_; | 747 int changed_fired_; |
694 scoped_ptr<base::DictionaryValue> json_; | 748 scoped_ptr<base::DictionaryValue> json_; |
695 | 749 |
696 base::Closure filename_no_change_; | 750 base::Closure filename_no_change_; |
697 ExtensionDownloadsEventRouter::FilenameChangedCallback filename_change_; | 751 ExtensionDownloadsEventRouter::FilenameChangedCallback filename_change_; |
698 | 752 |
699 DeterminerInfoVector determiners_; | 753 DeterminerInfoVector determiners_; |
700 | 754 |
755 base::FilePath creator_suggested_filename_; | |
756 extensions::api::downloads::FilenameConflictAction | |
757 creator_conflict_action_; | |
701 base::FilePath determined_filename_; | 758 base::FilePath determined_filename_; |
702 extensions::api::downloads::FilenameConflictAction | 759 extensions::api::downloads::FilenameConflictAction |
703 determined_conflict_action_; | 760 determined_conflict_action_; |
704 DeterminerInfo determiner_; | 761 DeterminerInfo determiner_; |
705 | 762 |
706 scoped_ptr<base::WeakPtrFactory<ExtensionDownloadsEventRouterData> > | 763 scoped_ptr<base::WeakPtrFactory<ExtensionDownloadsEventRouterData> > |
707 weak_ptr_factory_; | 764 weak_ptr_factory_; |
708 | 765 |
709 DISALLOW_COPY_AND_ASSIGN(ExtensionDownloadsEventRouterData); | 766 DISALLOW_COPY_AND_ASSIGN(ExtensionDownloadsEventRouterData); |
710 }; | 767 }; |
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
800 DownloadsDownloadFunction::DownloadsDownloadFunction() {} | 857 DownloadsDownloadFunction::DownloadsDownloadFunction() {} |
801 | 858 |
802 DownloadsDownloadFunction::~DownloadsDownloadFunction() {} | 859 DownloadsDownloadFunction::~DownloadsDownloadFunction() {} |
803 | 860 |
804 bool DownloadsDownloadFunction::RunImpl() { | 861 bool DownloadsDownloadFunction::RunImpl() { |
805 scoped_ptr<extensions::api::downloads::Download::Params> params( | 862 scoped_ptr<extensions::api::downloads::Download::Params> params( |
806 extensions::api::downloads::Download::Params::Create(*args_)); | 863 extensions::api::downloads::Download::Params::Create(*args_)); |
807 EXTENSION_FUNCTION_VALIDATE(params.get()); | 864 EXTENSION_FUNCTION_VALIDATE(params.get()); |
808 const extensions::api::downloads::DownloadOptions& options = params->options; | 865 const extensions::api::downloads::DownloadOptions& options = params->options; |
809 GURL download_url(options.url); | 866 GURL download_url(options.url); |
810 if (!download_url.is_valid() || | 867 if (!download_url.is_valid()) { |
811 (!download_url.SchemeIs("data") && | |
812 download_url.GetOrigin() != GetExtension()->url().GetOrigin() && | |
813 !extensions::PermissionsData::HasHostPermission(GetExtension(), | |
814 download_url))) { | |
815 error_ = download_extension_errors::kInvalidURLError; | 868 error_ = download_extension_errors::kInvalidURLError; |
816 return false; | 869 return false; |
870 } else if (!download_url.SchemeIs("data") && | |
871 download_url.GetOrigin() != GetExtension()->url().GetOrigin() && | |
872 !extensions::PermissionsData::HasHostPermission(GetExtension(), | |
873 download_url)) { | |
874 error_ = download_extension_errors::kNotPermittedURLError; | |
875 return false; | |
817 } | 876 } |
818 | 877 |
819 Profile* current_profile = profile(); | 878 Profile* current_profile = profile(); |
820 if (include_incognito() && profile()->HasOffTheRecordProfile()) | 879 if (include_incognito() && profile()->HasOffTheRecordProfile()) |
821 current_profile = profile()->GetOffTheRecordProfile(); | 880 current_profile = profile()->GetOffTheRecordProfile(); |
822 | 881 |
823 scoped_ptr<content::DownloadUrlParameters> download_params( | 882 scoped_ptr<content::DownloadUrlParameters> download_params( |
824 new content::DownloadUrlParameters( | 883 new content::DownloadUrlParameters( |
825 download_url, | 884 download_url, |
826 render_view_host()->GetProcess()->GetID(), | 885 render_view_host()->GetProcess()->GetID(), |
827 render_view_host()->GetRoutingID(), | 886 render_view_host()->GetRoutingID(), |
828 current_profile->GetResourceContext())); | 887 current_profile->GetResourceContext())); |
829 | 888 |
889 base::FilePath creator_suggested_filename; | |
830 if (options.filename.get()) { | 890 if (options.filename.get()) { |
831 // TODO(benjhayden): Make json_schema_compiler generate string16s instead of | 891 #if defined(OS_WIN) |
832 // std::strings. Can't get filename16 from options.ToValue() because that | 892 // Can't get filename16 from options.ToValue() because that converts it from |
833 // converts it from std::string. | 893 // std::string. |
834 base::DictionaryValue* options_value = NULL; | 894 base::DictionaryValue* options_value = NULL; |
835 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options_value)); | 895 EXTENSION_FUNCTION_VALIDATE(args_->GetDictionary(0, &options_value)); |
836 string16 filename16; | 896 base::string16 filename16; |
837 EXTENSION_FUNCTION_VALIDATE(options_value->GetString( | 897 EXTENSION_FUNCTION_VALIDATE(options_value->GetString( |
838 kFilenameKey, &filename16)); | 898 kFilenameKey, &filename16)); |
839 #if defined(OS_WIN) | 899 creator_suggested_filename = base::FilePath(filename16); |
840 base::FilePath file_path(filename16); | |
841 #elif defined(OS_POSIX) | 900 #elif defined(OS_POSIX) |
842 base::FilePath file_path(*options.filename.get()); | 901 creator_suggested_filename = base::FilePath(*options.filename.get()); |
843 #endif | 902 #endif |
844 if (!net::IsSafePortableBasename(file_path) || | 903 if (!net::IsSafePortableRelativePath(creator_suggested_filename)) { |
845 (file_path.DirName().value() != base::FilePath::kCurrentDirectory)) { | |
846 error_ = download_extension_errors::kInvalidFilenameError; | 904 error_ = download_extension_errors::kInvalidFilenameError; |
847 return false; | 905 return false; |
848 } | 906 } |
849 // TODO(benjhayden) Ensure that this filename is interpreted as a path | |
850 // relative to the default downloads directory without allowing '..'. | |
851 download_params->set_suggested_name(filename16); | |
852 } | 907 } |
853 | 908 |
854 if (options.save_as.get()) | 909 if (options.save_as.get()) |
855 download_params->set_prompt(*options.save_as.get()); | 910 download_params->set_prompt(*options.save_as.get()); |
856 | 911 |
857 if (options.headers.get()) { | 912 if (options.headers.get()) { |
858 typedef extensions::api::downloads::HeaderNameValuePair HeaderNameValuePair; | 913 typedef extensions::api::downloads::HeaderNameValuePair HeaderNameValuePair; |
859 for (std::vector<linked_ptr<HeaderNameValuePair> >::const_iterator iter = | 914 for (std::vector<linked_ptr<HeaderNameValuePair> >::const_iterator iter = |
860 options.headers->begin(); | 915 options.headers->begin(); |
861 iter != options.headers->end(); | 916 iter != options.headers->end(); |
862 ++iter) { | 917 ++iter) { |
863 const HeaderNameValuePair& name_value = **iter; | 918 const HeaderNameValuePair& name_value = **iter; |
864 if (!net::HttpUtil::IsSafeHeader(name_value.name)) { | 919 if (!net::HttpUtil::IsSafeHeader(name_value.name)) { |
865 error_ = download_extension_errors::kGenericError; | 920 error_ = download_extension_errors::kInvalidHeaderError; |
866 return false; | 921 return false; |
867 } | 922 } |
868 download_params->add_request_header(name_value.name, name_value.value); | 923 download_params->add_request_header(name_value.name, name_value.value); |
869 } | 924 } |
870 } | 925 } |
871 | 926 |
872 std::string method_string = | 927 std::string method_string = |
873 extensions::api::downloads::ToString(options.method); | 928 extensions::api::downloads::ToString(options.method); |
874 if (!method_string.empty()) | 929 if (!method_string.empty()) |
875 download_params->set_method(method_string); | 930 download_params->set_method(method_string); |
876 if (options.body.get()) | 931 if (options.body.get()) |
877 download_params->set_post_body(*options.body.get()); | 932 download_params->set_post_body(*options.body.get()); |
878 download_params->set_callback(base::Bind( | 933 download_params->set_callback(base::Bind( |
879 &DownloadsDownloadFunction::OnStarted, this)); | 934 &DownloadsDownloadFunction::OnStarted, this, |
935 creator_suggested_filename, options.conflict_action)); | |
880 // Prevent login prompts for 401/407 responses. | 936 // Prevent login prompts for 401/407 responses. |
881 download_params->set_load_flags(net::LOAD_DO_NOT_PROMPT_FOR_LOGIN); | 937 download_params->set_load_flags(net::LOAD_DO_NOT_PROMPT_FOR_LOGIN); |
882 | 938 |
883 DownloadManager* manager = BrowserContext::GetDownloadManager( | 939 DownloadManager* manager = BrowserContext::GetDownloadManager( |
884 current_profile); | 940 current_profile); |
885 manager->DownloadUrl(download_params.Pass()); | 941 manager->DownloadUrl(download_params.Pass()); |
886 RecordApiFunctions(DOWNLOADS_FUNCTION_DOWNLOAD); | 942 RecordApiFunctions(DOWNLOADS_FUNCTION_DOWNLOAD); |
887 return true; | 943 return true; |
888 } | 944 } |
889 | 945 |
890 void DownloadsDownloadFunction::OnStarted( | 946 void DownloadsDownloadFunction::OnStarted( |
891 DownloadItem* item, net::Error error) { | 947 const base::FilePath& creator_suggested_filename, |
948 extensions::api::downloads::FilenameConflictAction creator_conflict_action, | |
949 DownloadItem* item, | |
950 net::Error error) { | |
892 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 951 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
893 VLOG(1) << __FUNCTION__ << " " << item << " " << error; | 952 VLOG(1) << __FUNCTION__ << " " << item << " " << error; |
894 if (item) { | 953 if (item) { |
895 DCHECK_EQ(net::OK, error); | 954 DCHECK_EQ(net::OK, error); |
896 SetResult(base::Value::CreateIntegerValue(item->GetId())); | 955 SetResult(base::Value::CreateIntegerValue(item->GetId())); |
956 if (!creator_suggested_filename.empty()) { | |
957 ExtensionDownloadsEventRouterData* data = | |
958 ExtensionDownloadsEventRouterData::Get(item); | |
959 if (!data) { | |
960 data = new ExtensionDownloadsEventRouterData( | |
961 item, | |
962 scoped_ptr<base::DictionaryValue>(new base::DictionaryValue())); | |
963 } | |
964 data->CreatorSuggestedFilename( | |
965 creator_suggested_filename, creator_conflict_action); | |
966 } | |
897 } else { | 967 } else { |
898 DCHECK_NE(net::OK, error); | 968 DCHECK_NE(net::OK, error); |
899 error_ = net::ErrorToString(error); | 969 error_ = net::ErrorToString(error); |
900 } | 970 } |
901 SendResponse(error_.empty()); | 971 SendResponse(error_.empty()); |
902 } | 972 } |
903 | 973 |
904 DownloadsSearchFunction::DownloadsSearchFunction() {} | 974 DownloadsSearchFunction::DownloadsSearchFunction() {} |
905 | 975 |
906 DownloadsSearchFunction::~DownloadsSearchFunction() {} | 976 DownloadsSearchFunction::~DownloadsSearchFunction() {} |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1028 for (DownloadManager::DownloadVector::const_iterator it = results.begin(); | 1098 for (DownloadManager::DownloadVector::const_iterator it = results.begin(); |
1029 it != results.end(); ++it) { | 1099 it != results.end(); ++it) { |
1030 json_results->Append(base::Value::CreateIntegerValue((*it)->GetId())); | 1100 json_results->Append(base::Value::CreateIntegerValue((*it)->GetId())); |
1031 (*it)->Remove(); | 1101 (*it)->Remove(); |
1032 } | 1102 } |
1033 SetResult(json_results); | 1103 SetResult(json_results); |
1034 RecordApiFunctions(DOWNLOADS_FUNCTION_ERASE); | 1104 RecordApiFunctions(DOWNLOADS_FUNCTION_ERASE); |
1035 return true; | 1105 return true; |
1036 } | 1106 } |
1037 | 1107 |
1108 DownloadsDeleteFileFunction::DownloadsDeleteFileFunction() {} | |
1109 | |
1110 DownloadsDeleteFileFunction::~DownloadsDeleteFileFunction() {} | |
1111 | |
1112 bool DownloadsDeleteFileFunction::RunImpl() { | |
1113 scoped_ptr<extensions::api::downloads::DeleteFile::Params> params( | |
1114 extensions::api::downloads::DeleteFile::Params::Create(*args_)); | |
1115 EXTENSION_FUNCTION_VALIDATE(params.get()); | |
1116 DownloadItem* download_item = GetDownload( | |
1117 profile(), include_incognito(), params->download_id); | |
1118 if (!download_item || | |
1119 (download_item->GetState() == DownloadItem::IN_PROGRESS) || | |
1120 download_item->GetFileExternallyRemoved()) { | |
1121 error_ = download_extension_errors::kInvalidOperationError; | |
1122 return false; | |
1123 } | |
1124 | |
1125 RecordApiFunctions(DOWNLOADS_FUNCTION_DELETE_FILE); | |
1126 | |
1127 DownloadManager* manager = NULL; | |
1128 DownloadManager* incognito_manager = NULL; | |
1129 GetManagers(profile(), include_incognito(), &manager, &incognito_manager); | |
1130 ManagerDestructionObserver::CheckForHistoryFilesRemoval(manager); | |
1131 ManagerDestructionObserver::CheckForHistoryFilesRemoval(incognito_manager); | |
1132 | |
1133 BrowserThread::PostTaskAndReply( | |
1134 BrowserThread::FILE, FROM_HERE, | |
1135 base::Bind(&DownloadsDeleteFileFunction::DeleteOnFileThread, this, | |
1136 download_item->GetFullPath()), | |
asanka
2013/07/16 19:57:52
I'd avoid deleting files unless the download is CO
benjhayden
2013/07/19 15:53:55
Done.
| |
1137 base::Bind(&DownloadsDeleteFileFunction::RespondOnUIThread, this)); | |
1138 return true; | |
1139 } | |
1140 | |
1141 void DownloadsDeleteFileFunction::DeleteOnFileThread( | |
1142 const base::FilePath& path) { | |
1143 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | |
1144 if (file_util::DirectoryExists(path)) { | |
1145 error_ = download_extension_errors::kInvalidOperationError; | |
1146 return; | |
1147 } | |
1148 base::Delete(path, false); | |
1149 } | |
1150 | |
1151 void DownloadsDeleteFileFunction::RespondOnUIThread() { | |
1152 SendResponse(error_.empty()); | |
1153 } | |
1154 | |
1038 DownloadsAcceptDangerFunction::DownloadsAcceptDangerFunction() {} | 1155 DownloadsAcceptDangerFunction::DownloadsAcceptDangerFunction() {} |
1039 | 1156 |
1040 DownloadsAcceptDangerFunction::~DownloadsAcceptDangerFunction() {} | 1157 DownloadsAcceptDangerFunction::~DownloadsAcceptDangerFunction() {} |
1041 | 1158 |
1042 bool DownloadsAcceptDangerFunction::RunImpl() { | 1159 bool DownloadsAcceptDangerFunction::RunImpl() { |
1043 scoped_ptr<extensions::api::downloads::AcceptDanger::Params> params( | 1160 scoped_ptr<extensions::api::downloads::AcceptDanger::Params> params( |
1044 extensions::api::downloads::AcceptDanger::Params::Create(*args_)); | 1161 extensions::api::downloads::AcceptDanger::Params::Create(*args_)); |
1045 EXTENSION_FUNCTION_VALIDATE(params.get()); | 1162 EXTENSION_FUNCTION_VALIDATE(params.get()); |
1046 DownloadItem* download_item = GetDownloadIfInProgress( | 1163 DownloadItem* download_item = GetDownloadIfInProgress( |
1047 profile(), include_incognito(), params->download_id); | 1164 profile(), include_incognito(), params->download_id); |
1048 content::WebContents* web_contents = | 1165 content::WebContents* web_contents = |
1049 dispatcher()->delegate()->GetVisibleWebContents(); | 1166 dispatcher()->delegate()->GetVisibleWebContents(); |
1050 if (!download_item || | 1167 if (!download_item || |
1051 !download_item->IsDangerous() || | 1168 !download_item->IsDangerous() || |
1052 !web_contents) { | 1169 !web_contents) { |
1053 error_ = download_extension_errors::kInvalidOperationError; | 1170 error_ = download_extension_errors::kInvalidOperationError; |
1054 return false; | 1171 return false; |
1055 } | 1172 } |
1056 RecordApiFunctions(DOWNLOADS_FUNCTION_ACCEPT_DANGER); | 1173 RecordApiFunctions(DOWNLOADS_FUNCTION_ACCEPT_DANGER); |
1057 // DownloadDangerPrompt displays a modal dialog using native widgets that the | 1174 // DownloadDangerPrompt displays a modal dialog using native widgets that the |
1058 // user must either accept or cancel. It cannot be scripted. | 1175 // user must either accept or cancel. It cannot be scripted. |
1059 DownloadDangerPrompt::Create( | 1176 DownloadDangerPrompt::Create( |
1060 download_item, | 1177 download_item, |
1061 web_contents, | 1178 web_contents, |
1062 true, | 1179 true, |
1063 base::Bind(&DownloadsAcceptDangerFunction::DangerPromptCallback, | 1180 base::Bind(&DownloadsAcceptDangerFunction::DangerPromptCallback, |
1064 this, true, params->download_id), | 1181 this, params->download_id)); |
1065 base::Bind(&DownloadsAcceptDangerFunction::DangerPromptCallback, | |
1066 this, false, params->download_id)); | |
1067 // DownloadDangerPrompt deletes itself | 1182 // DownloadDangerPrompt deletes itself |
1068 return true; | 1183 return true; |
1069 } | 1184 } |
1070 | 1185 |
1071 void DownloadsAcceptDangerFunction::DangerPromptCallback( | 1186 void DownloadsAcceptDangerFunction::DangerPromptCallback( |
1072 bool accept, int download_id) { | 1187 int download_id, DownloadDangerPrompt::Action action) { |
1073 if (accept) { | 1188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
1074 DownloadItem* download_item = GetDownloadIfInProgress( | 1189 DownloadItem* download_item = GetDownloadIfInProgress( |
1075 profile(), include_incognito(), download_id); | 1190 profile(), include_incognito(), download_id); |
1076 if (download_item) | 1191 if (!download_item) { |
1192 error_ = download_extension_errors::kInvalidOperationError; | |
1193 return; | |
1194 } | |
1195 switch (action) { | |
1196 case DownloadDangerPrompt::ACCEPT: | |
1077 download_item->ValidateDangerousDownload(); | 1197 download_item->ValidateDangerousDownload(); |
1198 break; | |
1199 case DownloadDangerPrompt::CANCEL: | |
1200 download_item->Remove(); | |
1201 break; | |
1202 case DownloadDangerPrompt::DISMISS: | |
1203 break; | |
1078 } | 1204 } |
1079 SendResponse(error_.empty()); | 1205 SendResponse(error_.empty()); |
1080 } | 1206 } |
1081 | 1207 |
1082 DownloadsShowFunction::DownloadsShowFunction() {} | 1208 DownloadsShowFunction::DownloadsShowFunction() {} |
1083 | 1209 |
1084 DownloadsShowFunction::~DownloadsShowFunction() {} | 1210 DownloadsShowFunction::~DownloadsShowFunction() {} |
1085 | 1211 |
1086 bool DownloadsShowFunction::RunImpl() { | 1212 bool DownloadsShowFunction::RunImpl() { |
1087 scoped_ptr<extensions::api::downloads::Show::Params> params( | 1213 scoped_ptr<extensions::api::downloads::Show::Params> params( |
1088 extensions::api::downloads::Show::Params::Create(*args_)); | 1214 extensions::api::downloads::Show::Params::Create(*args_)); |
1089 EXTENSION_FUNCTION_VALIDATE(params.get()); | 1215 EXTENSION_FUNCTION_VALIDATE(params.get()); |
1090 DownloadItem* download_item = GetDownload( | 1216 if (params->download_id) { |
1091 profile(), include_incognito(), params->download_id); | 1217 DownloadItem* download_item = GetDownload( |
1092 if (!download_item) { | 1218 profile(), include_incognito(), *params->download_id); |
1093 error_ = download_extension_errors::kInvalidOperationError; | 1219 if (!download_item) { |
1094 return false; | 1220 error_ = download_extension_errors::kInvalidOperationError; |
1221 return false; | |
1222 } | |
1223 download_item->ShowDownloadInShell(); | |
1224 } else { | |
1225 DownloadManager* manager = NULL; | |
1226 DownloadManager* incognito_manager = NULL; | |
1227 GetManagers(profile(), include_incognito(), &manager, &incognito_manager); | |
1228 platform_util::OpenItem(DownloadPrefs::FromDownloadManager( | |
1229 manager)->DownloadPath()); | |
1095 } | 1230 } |
1096 download_item->ShowDownloadInShell(); | |
1097 RecordApiFunctions(DOWNLOADS_FUNCTION_SHOW); | 1231 RecordApiFunctions(DOWNLOADS_FUNCTION_SHOW); |
1098 return true; | 1232 return true; |
1099 } | 1233 } |
1100 | 1234 |
1101 DownloadsOpenFunction::DownloadsOpenFunction() {} | 1235 DownloadsOpenFunction::DownloadsOpenFunction() {} |
1102 | 1236 |
1103 DownloadsOpenFunction::~DownloadsOpenFunction() {} | 1237 DownloadsOpenFunction::~DownloadsOpenFunction() {} |
1104 | 1238 |
1105 bool DownloadsOpenFunction::RunImpl() { | 1239 bool DownloadsOpenFunction::RunImpl() { |
1106 scoped_ptr<extensions::api::downloads::Open::Params> params( | 1240 scoped_ptr<extensions::api::downloads::Open::Params> params( |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1139 gfx::NativeView view = web_contents->GetView()->GetNativeView(); | 1273 gfx::NativeView view = web_contents->GetView()->GetNativeView(); |
1140 { | 1274 { |
1141 // Enable nested tasks during DnD, while |DragDownload()| blocks. | 1275 // Enable nested tasks during DnD, while |DragDownload()| blocks. |
1142 base::MessageLoop::ScopedNestableTaskAllower allow( | 1276 base::MessageLoop::ScopedNestableTaskAllower allow( |
1143 base::MessageLoop::current()); | 1277 base::MessageLoop::current()); |
1144 download_util::DragDownload(download_item, icon, view); | 1278 download_util::DragDownload(download_item, icon, view); |
1145 } | 1279 } |
1146 return true; | 1280 return true; |
1147 } | 1281 } |
1148 | 1282 |
1283 DownloadsSetShelfVisibleFunction::DownloadsSetShelfVisibleFunction() {} | |
1284 | |
1285 DownloadsSetShelfVisibleFunction::~DownloadsSetShelfVisibleFunction() {} | |
1286 | |
1287 bool DownloadsSetShelfVisibleFunction::RunImpl() { | |
1288 scoped_ptr<extensions::api::downloads::SetShelfVisible::Params> params( | |
1289 extensions::api::downloads::SetShelfVisible::Params::Create(*args_)); | |
1290 EXTENSION_FUNCTION_VALIDATE(params.get()); | |
1291 DownloadShelf* shelf = GetCurrentBrowser()->window()->GetDownloadShelf(); | |
asanka
2013/07/16 19:57:52
Is it expected that this will operate on the forem
benjhayden
2013/07/19 15:53:55
Yep, it will probably primarily be called from bac
asanka
2013/07/23 21:13:48
The browser window for a download is determined by
asargent_no_longer_on_chrome
2013/07/23 21:36:57
Note that chrome can be running but with no curren
| |
1292 if (params->visible) { | |
1293 if (!shelf->IsShowing()) | |
1294 shelf->Show(); | |
asanka
2013/07/16 19:57:52
What's supposed to happen if there are no download
benjhayden
2013/07/19 15:53:55
Done.
| |
1295 } else { | |
1296 if (shelf->IsShowing()) | |
1297 shelf->Close(DownloadShelf::USER_ACTION); | |
1298 } | |
1299 RecordApiFunctions(DOWNLOADS_FUNCTION_SET_SHELF_VISIBLE); | |
1300 return true; | |
1301 } | |
1302 | |
1149 DownloadsGetFileIconFunction::DownloadsGetFileIconFunction() | 1303 DownloadsGetFileIconFunction::DownloadsGetFileIconFunction() |
1150 : icon_extractor_(new DownloadFileIconExtractorImpl()) { | 1304 : icon_extractor_(new DownloadFileIconExtractorImpl()) { |
1151 } | 1305 } |
1152 | 1306 |
1153 DownloadsGetFileIconFunction::~DownloadsGetFileIconFunction() {} | 1307 DownloadsGetFileIconFunction::~DownloadsGetFileIconFunction() {} |
1154 | 1308 |
1155 void DownloadsGetFileIconFunction::SetIconExtractorForTesting( | 1309 void DownloadsGetFileIconFunction::SetIconExtractorForTesting( |
1156 DownloadFileIconExtractor* extractor) { | 1310 DownloadFileIconExtractor* extractor) { |
1157 DCHECK(extractor); | 1311 DCHECK(extractor); |
1158 icon_extractor_.reset(extractor); | 1312 icon_extractor_.reset(extractor); |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1261 item, profile_->IsOffTheRecord()).release(); | 1415 item, profile_->IsOffTheRecord()).release(); |
1262 json->SetString(kFilenameKey, suggested_path.LossyDisplayName()); | 1416 json->SetString(kFilenameKey, suggested_path.LossyDisplayName()); |
1263 DispatchEvent(events::kOnDownloadDeterminingFilename, | 1417 DispatchEvent(events::kOnDownloadDeterminingFilename, |
1264 false, | 1418 false, |
1265 base::Bind(&OnDeterminingFilenameWillDispatchCallback, | 1419 base::Bind(&OnDeterminingFilenameWillDispatchCallback, |
1266 &any_determiners, | 1420 &any_determiners, |
1267 data), | 1421 data), |
1268 json); | 1422 json); |
1269 if (!any_determiners) { | 1423 if (!any_determiners) { |
1270 data->ClearPendingDeterminers(); | 1424 data->ClearPendingDeterminers(); |
1271 no_change.Run(); | 1425 if (!data->creator_suggested_filename().empty()) { |
1426 change.Run(data->creator_suggested_filename(), | |
1427 ConvertConflictAction(data->creator_conflict_action())); | |
1428 // If all listeners are removed, don't keep |data| around. | |
1429 data->ResetCreatorSuggestion(); | |
1430 } else { | |
1431 no_change.Run(); | |
1432 } | |
1272 } | 1433 } |
1273 } | 1434 } |
1274 | 1435 |
1275 bool ExtensionDownloadsEventRouter::DetermineFilename( | 1436 bool ExtensionDownloadsEventRouter::DetermineFilename( |
1276 Profile* profile, | 1437 Profile* profile, |
1277 bool include_incognito, | 1438 bool include_incognito, |
1278 const std::string& ext_id, | 1439 const std::string& ext_id, |
1279 int download_id, | 1440 int download_id, |
1280 const base::FilePath& const_filename, | 1441 const base::FilePath& const_filename, |
1281 extensions::api::downloads::FilenameConflictAction conflict_action, | 1442 extensions::api::downloads::FilenameConflictAction conflict_action, |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1351 if (!data) | 1512 if (!data) |
1352 continue; | 1513 continue; |
1353 if (determiner_removed) { | 1514 if (determiner_removed) { |
1354 // Notify any items that may be waiting for callbacks from this | 1515 // Notify any items that may be waiting for callbacks from this |
1355 // extension/determiner. This will almost always be a no-op, however, it | 1516 // extension/determiner. This will almost always be a no-op, however, it |
1356 // is possible for an extension renderer to be unloaded while a download | 1517 // is possible for an extension renderer to be unloaded while a download |
1357 // item is waiting for a determiner. In that case, the download item | 1518 // item is waiting for a determiner. In that case, the download item |
1358 // should proceed. | 1519 // should proceed. |
1359 data->DeterminerRemoved(details.extension_id); | 1520 data->DeterminerRemoved(details.extension_id); |
1360 } | 1521 } |
1361 if (!any_listeners) { | 1522 if (!any_listeners && |
1523 data->creator_suggested_filename().empty()) { | |
1362 ExtensionDownloadsEventRouterData::Remove(*iter); | 1524 ExtensionDownloadsEventRouterData::Remove(*iter); |
1363 } | 1525 } |
1364 } | 1526 } |
1365 } | 1527 } |
1366 | 1528 |
1367 // That's all the methods that have to do with filename determination. The rest | 1529 // That's all the methods that have to do with filename determination. The rest |
1368 // have to do with the other, less special events. | 1530 // have to do with the other, less special events. |
1369 | 1531 |
1370 void ExtensionDownloadsEventRouter::OnDownloadCreated( | 1532 void ExtensionDownloadsEventRouter::OnDownloadCreated( |
1371 DownloadManager* manager, DownloadItem* download_item) { | 1533 DownloadManager* manager, DownloadItem* download_item) { |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1421 std::set<std::string> new_fields; | 1583 std::set<std::string> new_fields; |
1422 bool changed = false; | 1584 bool changed = false; |
1423 | 1585 |
1424 // For each field in the new json representation of the download_item except | 1586 // For each field in the new json representation of the download_item except |
1425 // the bytesReceived field, if the field has changed from the previous old | 1587 // the bytesReceived field, if the field has changed from the previous old |
1426 // json, set the differences in the |delta| object and remember that something | 1588 // json, set the differences in the |delta| object and remember that something |
1427 // significant changed. | 1589 // significant changed. |
1428 for (base::DictionaryValue::Iterator iter(*new_json.get()); | 1590 for (base::DictionaryValue::Iterator iter(*new_json.get()); |
1429 !iter.IsAtEnd(); iter.Advance()) { | 1591 !iter.IsAtEnd(); iter.Advance()) { |
1430 new_fields.insert(iter.key()); | 1592 new_fields.insert(iter.key()); |
1431 if (iter.key() != kBytesReceivedKey) { | 1593 if ((iter.key() != kBytesReceivedKey) && |
1594 (iter.key() != kIdKey) && | |
1595 (iter.key() != kEstimatedEndTimeKey)) { | |
1432 const base::Value* old_value = NULL; | 1596 const base::Value* old_value = NULL; |
1433 if (!data->json().HasKey(iter.key()) || | 1597 if (!data->json().HasKey(iter.key()) || |
1434 (data->json().Get(iter.key(), &old_value) && | 1598 (data->json().Get(iter.key(), &old_value) && |
1435 !iter.value().Equals(old_value))) { | 1599 !iter.value().Equals(old_value))) { |
1436 delta->Set(iter.key() + ".current", iter.value().DeepCopy()); | 1600 delta->Set(iter.key() + ".current", iter.value().DeepCopy()); |
1437 if (old_value) | 1601 if (old_value) |
1438 delta->Set(iter.key() + ".previous", old_value->DeepCopy()); | 1602 delta->Set(iter.key() + ".previous", old_value->DeepCopy()); |
1439 changed = true; | 1603 changed = true; |
1440 } | 1604 } |
1441 } | 1605 } |
1442 } | 1606 } |
1443 | 1607 |
1444 // If a field was in the previous json but is not in the new json, set the | 1608 // If a field was in the previous json but is not in the new json, set the |
1445 // difference in |delta|. | 1609 // difference in |delta|. |
1446 for (base::DictionaryValue::Iterator iter(data->json()); | 1610 for (base::DictionaryValue::Iterator iter(data->json()); |
1447 !iter.IsAtEnd(); iter.Advance()) { | 1611 !iter.IsAtEnd(); iter.Advance()) { |
1448 if (new_fields.find(iter.key()) == new_fields.end()) { | 1612 if ((new_fields.find(iter.key()) == new_fields.end()) && |
1613 (iter.key() != kEstimatedEndTimeKey)) { | |
asanka
2013/07/16 19:57:52
Why exclude kEstimatedEndTimeKey? It can also disa
benjhayden
2013/07/19 15:53:55
estimatedEndTime is not in DownloadDelta because i
| |
1614 // estimatedEndTime disappears after completion, but bytesReceived stays. | |
1449 delta->Set(iter.key() + ".previous", iter.value().DeepCopy()); | 1615 delta->Set(iter.key() + ".previous", iter.value().DeepCopy()); |
1450 changed = true; | 1616 changed = true; |
1451 } | 1617 } |
1452 } | 1618 } |
1453 | 1619 |
1454 // Update the OnChangedStat and dispatch the event if something significant | 1620 // Update the OnChangedStat and dispatch the event if something significant |
1455 // changed. Replace the stored json with the new json. | 1621 // changed. Replace the stored json with the new json. |
1456 data->OnItemUpdated(); | 1622 data->OnItemUpdated(); |
1457 if (changed) { | 1623 if (changed) { |
1458 DispatchEvent(events::kOnDownloadChanged, | 1624 DispatchEvent(events::kOnDownloadChanged, |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1502 DownloadsNotificationSource notification_source; | 1668 DownloadsNotificationSource notification_source; |
1503 notification_source.event_name = event_name; | 1669 notification_source.event_name = event_name; |
1504 notification_source.profile = profile_; | 1670 notification_source.profile = profile_; |
1505 content::Source<DownloadsNotificationSource> content_source( | 1671 content::Source<DownloadsNotificationSource> content_source( |
1506 ¬ification_source); | 1672 ¬ification_source); |
1507 content::NotificationService::current()->Notify( | 1673 content::NotificationService::current()->Notify( |
1508 chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT, | 1674 chrome::NOTIFICATION_EXTENSION_DOWNLOADS_EVENT, |
1509 content_source, | 1675 content_source, |
1510 content::Details<std::string>(&json_args)); | 1676 content::Details<std::string>(&json_args)); |
1511 } | 1677 } |
OLD | NEW |