Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Side by Side Diff: chrome/browser/extensions/api/downloads/downloads_api.cc

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

Powered by Google App Engine
This is Rietveld 408576698