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

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

Powered by Google App Engine
This is Rietveld 408576698