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