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

Side by Side Diff: chrome/browser/download/download_target_determiner.cc

Issue 14640020: [Resumption 9/11] Handle filename determination for resumed downloads. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix GCC build Created 7 years, 6 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 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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/download/download_target_determiner.h" 5 #include "chrome/browser/download/download_target_determiner.h"
6 6
7 #include "base/prefs/pref_service.h" 7 #include "base/prefs/pref_service.h"
8 #include "base/rand_util.h" 8 #include "base/rand_util.h"
9 #include "base/stringprintf.h" 9 #include "base/stringprintf.h"
10 #include "base/time.h" 10 #include "base/time.h"
11 #include "chrome/browser/download/chrome_download_manager_delegate.h" 11 #include "chrome/browser/download/chrome_download_manager_delegate.h"
12 #include "chrome/browser/download/download_crx_util.h" 12 #include "chrome/browser/download/download_crx_util.h"
13 #include "chrome/browser/download/download_extensions.h" 13 #include "chrome/browser/download/download_extensions.h"
14 #include "chrome/browser/download/download_prefs.h" 14 #include "chrome/browser/download/download_prefs.h"
15 #include "chrome/browser/download/download_util.h" 15 #include "chrome/browser/download/download_util.h"
16 #include "chrome/browser/extensions/webstore_installer.h" 16 #include "chrome/browser/extensions/webstore_installer.h"
17 #include "chrome/browser/history/history_service.h" 17 #include "chrome/browser/history/history_service.h"
18 #include "chrome/browser/history/history_service_factory.h" 18 #include "chrome/browser/history/history_service_factory.h"
19 #include "chrome/browser/profiles/profile.h" 19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/common/extensions/extension.h" 20 #include "chrome/common/extensions/extension.h"
21 #include "chrome/common/extensions/feature_switch.h" 21 #include "chrome/common/extensions/feature_switch.h"
22 #include "chrome/common/pref_names.h" 22 #include "chrome/common/pref_names.h"
23 #include "content/public/browser/browser_context.h" 23 #include "content/public/browser/browser_context.h"
24 #include "content/public/browser/browser_thread.h" 24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/download_interrupt_reasons.h"
25 #include "grit/generated_resources.h" 26 #include "grit/generated_resources.h"
26 #include "net/base/net_util.h" 27 #include "net/base/net_util.h"
27 #include "ui/base/l10n/l10n_util.h" 28 #include "ui/base/l10n/l10n_util.h"
28 29
29 #if defined(OS_CHROMEOS) 30 #if defined(OS_CHROMEOS)
hashimoto 2013/06/03 06:31:03 nit: Is this include needed?
asanka 2013/06/03 18:35:31 Apparently not. Thanks!
30 #include "chrome/browser/chromeos/drive/download_handler.h" 31 #include "chrome/browser/chromeos/drive/download_handler.h"
31 #include "chrome/browser/chromeos/drive/file_system_util.h" 32 #include "chrome/browser/chromeos/drive/file_system_util.h"
32 #endif 33 #endif
33 34
34 using content::BrowserThread; 35 using content::BrowserThread;
35 using content::DownloadItem; 36 using content::DownloadItem;
36 37
37 namespace { 38 namespace {
38 39
40 const base::FilePath::CharType kCrdownloadSuffix[] =
41 FILE_PATH_LITERAL(".crdownload");
42
39 // Condenses the results from HistoryService::GetVisibleVisitCountToHost() to a 43 // Condenses the results from HistoryService::GetVisibleVisitCountToHost() to a
40 // single bool. A host is considered visited before if prior visible visits were 44 // single bool. A host is considered visited before if prior visible visits were
41 // found in history and the first such visit was earlier than the most recent 45 // found in history and the first such visit was earlier than the most recent
42 // midnight. 46 // midnight.
43 void VisitCountsToVisitedBefore( 47 void VisitCountsToVisitedBefore(
44 const base::Callback<void(bool)>& callback, 48 const base::Callback<void(bool)>& callback,
45 HistoryService::Handle unused_handle, 49 HistoryService::Handle unused_handle,
46 bool found_visits, 50 bool found_visits,
47 int count, 51 int count,
48 base::Time first_visit) { 52 base::Time first_visit) {
49 callback.Run( 53 callback.Run(
50 found_visits && count > 0 && 54 found_visits && count > 0 &&
51 (first_visit.LocalMidnight() < base::Time::Now().LocalMidnight())); 55 (first_visit.LocalMidnight() < base::Time::Now().LocalMidnight()));
52 } 56 }
53 57
54 } // namespace 58 } // namespace
55 59
56 DownloadTargetDeterminerDelegate::~DownloadTargetDeterminerDelegate() { 60 DownloadTargetDeterminerDelegate::~DownloadTargetDeterminerDelegate() {
57 } 61 }
58 62
59 DownloadTargetDeterminer::DownloadTargetDeterminer( 63 DownloadTargetDeterminer::DownloadTargetDeterminer(
60 DownloadItem* download, 64 DownloadItem* download,
65 const base::FilePath& initial_virtual_path,
61 DownloadPrefs* download_prefs, 66 DownloadPrefs* download_prefs,
62 DownloadTargetDeterminerDelegate* delegate, 67 DownloadTargetDeterminerDelegate* delegate,
63 const content::DownloadTargetCallback& callback) 68 const content::DownloadTargetCallback& callback)
64 : next_state_(STATE_GENERATE_TARGET_PATH), 69 : next_state_(STATE_GENERATE_TARGET_PATH),
65 should_prompt_(false), 70 should_prompt_(false),
66 create_directory_(false), 71 should_notify_extensions_(false),
67 conflict_action_(download->GetForcedFilePath().empty() ? 72 create_target_directory_(false),
68 DownloadPathReservationTracker::UNIQUIFY : 73 conflict_action_(DownloadPathReservationTracker::OVERWRITE),
69 DownloadPathReservationTracker::OVERWRITE),
70 danger_type_(download->GetDangerType()), 74 danger_type_(download->GetDangerType()),
75 virtual_path_(initial_virtual_path),
71 download_(download), 76 download_(download),
77 is_resumption_(download_->GetLastReason() !=
78 content::DOWNLOAD_INTERRUPT_REASON_NONE &&
79 !initial_virtual_path.empty()),
72 download_prefs_(download_prefs), 80 download_prefs_(download_prefs),
73 delegate_(delegate), 81 delegate_(delegate),
74 completion_callback_(callback), 82 completion_callback_(callback),
75 weak_ptr_factory_(this) { 83 weak_ptr_factory_(this) {
76 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 84 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
77 DCHECK(download_); 85 DCHECK(download_);
78 DCHECK(delegate); 86 DCHECK(delegate);
79 download_->AddObserver(this); 87 download_->AddObserver(this);
80 88
81 DoLoop(); 89 DoLoop();
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
128 // return QUIT_DOLOOP. In this case, an inner DoLoop() may complete the target 136 // return QUIT_DOLOOP. In this case, an inner DoLoop() may complete the target
129 // determination and delete |this|. 137 // determination and delete |this|.
130 138
131 if (result == COMPLETE) 139 if (result == COMPLETE)
132 ScheduleCallbackAndDeleteSelf(); 140 ScheduleCallbackAndDeleteSelf();
133 } 141 }
134 142
135 DownloadTargetDeterminer::Result 143 DownloadTargetDeterminer::Result
136 DownloadTargetDeterminer::DoGenerateTargetPath() { 144 DownloadTargetDeterminer::DoGenerateTargetPath() {
137 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 145 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
138 DCHECK(virtual_path_.empty());
139 DCHECK(local_path_.empty()); 146 DCHECK(local_path_.empty());
147 DCHECK(!should_prompt_);
148 DCHECK(!should_notify_extensions_);
149 DCHECK_EQ(DownloadPathReservationTracker::OVERWRITE, conflict_action_);
140 bool is_forced_path = !download_->GetForcedFilePath().empty(); 150 bool is_forced_path = !download_->GetForcedFilePath().empty();
141 151
142 next_state_ = STATE_NOTIFY_EXTENSIONS; 152 next_state_ = STATE_NOTIFY_EXTENSIONS;
143 153
144 // If we don't have a forced path, we should construct a path for the 154 if (!virtual_path_.empty() && HasPromptedForPath() && !is_forced_path) {
145 // download. Forced paths are only specified for programmatic downloads 155 // The download is being resumed and the user has already been prompted for
146 // (WebStore, Drag&Drop). Treat the path as a virtual path. We will eventually 156 // a path. Assume that it's okay to overwrite the file if there's a conflict
147 // determine whether this is a local path and if not, figure out a local path. 157 // and reuse the selection.
148 if (!is_forced_path) { 158 should_prompt_ = ShouldPromptForDownload(virtual_path_);
149 std::string default_filename( 159 } else if (!is_forced_path) {
160 // If we don't have a forced path, we should construct a path for the
161 // download. Forced paths are only specified for programmatic downloads
162 // (WebStore, Drag&Drop). Treat the path as a virtual path. We will
163 // eventually determine whether this is a local path and if not, figure out
164 // a local path.
165 std::string default_filename(
150 l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME)); 166 l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME));
151 base::FilePath generated_filename = net::GenerateFileName( 167 base::FilePath generated_filename = net::GenerateFileName(
152 download_->GetURL(), 168 download_->GetURL(),
153 download_->GetContentDisposition(), 169 download_->GetContentDisposition(),
154 GetProfile()->GetPrefs()->GetString(prefs::kDefaultCharset), 170 GetProfile()->GetPrefs()->GetString(prefs::kDefaultCharset),
155 download_->GetSuggestedFilename(), 171 download_->GetSuggestedFilename(),
156 download_->GetMimeType(), 172 download_->GetMimeType(),
157 default_filename); 173 default_filename);
158 should_prompt_ = ShouldPromptForDownload(generated_filename); 174 should_prompt_ = ShouldPromptForDownload(generated_filename);
159 base::FilePath target_directory; 175 base::FilePath target_directory;
160 if (should_prompt_) { 176 if (should_prompt_) {
161 DCHECK(!download_prefs_->IsDownloadPathManaged()); 177 DCHECK(!download_prefs_->IsDownloadPathManaged());
162 // If the user is going to be prompted and the user has been prompted 178 // If the user is going to be prompted and the user has been prompted
163 // before, then always prefer the last directory that the user selected. 179 // before, then always prefer the last directory that the user selected.
164 target_directory = download_prefs_->SaveFilePath(); 180 target_directory = download_prefs_->SaveFilePath();
165 } else { 181 } else {
166 target_directory = download_prefs_->DownloadPath(); 182 target_directory = download_prefs_->DownloadPath();
167 } 183 }
168 virtual_path_ = target_directory.Append(generated_filename); 184 virtual_path_ = target_directory.Append(generated_filename);
185 conflict_action_ = DownloadPathReservationTracker::UNIQUIFY;
186 should_notify_extensions_ = true;
169 } else { 187 } else {
170 DCHECK(!should_prompt_);
171 virtual_path_ = download_->GetForcedFilePath(); 188 virtual_path_ = download_->GetForcedFilePath();
189 // If this is a resumed download which was previously interrupted due to an
190 // issue with the forced path, the user is still not prompted. If the path
191 // supplied to a programmatic download is invalid, then the caller needs to
192 // intervene.
172 } 193 }
173 DCHECK(virtual_path_.IsAbsolute()); 194 DCHECK(virtual_path_.IsAbsolute());
174 DVLOG(20) << "Generated virtual path: " << virtual_path_.AsUTF8Unsafe(); 195 DVLOG(20) << "Generated virtual path: " << virtual_path_.AsUTF8Unsafe();
175 196
176 // If the download is DOA, don't bother going any further. This would be the 197 // If the download is DOA, don't bother going any further. This would be the
177 // case for a download that failed to initialize (e.g. the initial temporary 198 // case for a download that failed to initialize (e.g. the initial temporary
178 // file couldn't be created because both the downloads directory and the 199 // file couldn't be created because both the downloads directory and the
179 // temporary directory are unwriteable). 200 // temporary directory are unwriteable).
180 // 201 //
181 // A virtual path is determined for DOA downloads for display purposes. This 202 // A virtual path is determined for DOA downloads for display purposes. This
182 // is why this check is performed here instead of at the start. 203 // is why this check is performed here instead of at the start.
183 if (download_->GetState() != DownloadItem::IN_PROGRESS) 204 if (download_->GetState() != DownloadItem::IN_PROGRESS)
184 return COMPLETE; 205 return COMPLETE;
185 return CONTINUE; 206 return CONTINUE;
186 } 207 }
187 208
188 DownloadTargetDeterminer::Result 209 DownloadTargetDeterminer::Result
189 DownloadTargetDeterminer::DoNotifyExtensions() { 210 DownloadTargetDeterminer::DoNotifyExtensions() {
190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 211 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
191 DCHECK(!virtual_path_.empty()); 212 DCHECK(!virtual_path_.empty());
192 213
193 next_state_ = STATE_RESERVE_VIRTUAL_PATH; 214 next_state_ = STATE_RESERVE_VIRTUAL_PATH;
194 215
195 // If the target path is forced or if we don't have an extensions event 216 if (!should_notify_extensions_)
196 // router, then proceed with the original path.
197 if (!download_->GetForcedFilePath().empty())
198 return CONTINUE; 217 return CONTINUE;
199 218
200 delegate_->NotifyExtensions(download_, virtual_path_, 219 delegate_->NotifyExtensions(download_, virtual_path_,
201 base::Bind(&DownloadTargetDeterminer::NotifyExtensionsDone, 220 base::Bind(&DownloadTargetDeterminer::NotifyExtensionsDone,
202 weak_ptr_factory_.GetWeakPtr())); 221 weak_ptr_factory_.GetWeakPtr()));
203 return QUIT_DOLOOP; 222 return QUIT_DOLOOP;
204 } 223 }
205 224
206 void DownloadTargetDeterminer::NotifyExtensionsDone( 225 void DownloadTargetDeterminer::NotifyExtensionsDone(
207 const base::FilePath& suggested_path, 226 const base::FilePath& suggested_path,
208 DownloadPathReservationTracker::FilenameConflictAction conflict_action) { 227 DownloadPathReservationTracker::FilenameConflictAction conflict_action) {
209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 228 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
210 DVLOG(20) << "Extension suggested path: " << suggested_path.AsUTF8Unsafe(); 229 DVLOG(20) << "Extension suggested path: " << suggested_path.AsUTF8Unsafe();
211 230
212 if (!suggested_path.empty()) { 231 if (!suggested_path.empty()) {
213 // If an extension overrides the filename, then the target directory will be 232 // If an extension overrides the filename, then the target directory will be
214 // forced to download_prefs_->DownloadPath() since extensions cannot place 233 // forced to download_prefs_->DownloadPath() since extensions cannot place
215 // downloaded files anywhere except there. This prevents subdirectories from 234 // downloaded files anywhere except there. This prevents subdirectories from
216 // accumulating: if an extension is allowed to say that a file should go in 235 // accumulating: if an extension is allowed to say that a file should go in
217 // last_download_path/music/foo.mp3, then last_download_path will accumulate 236 // last_download_path/music/foo.mp3, then last_download_path will accumulate
218 // the subdirectory /music/ so that the next download may end up in 237 // the subdirectory /music/ so that the next download may end up in
219 // Downloads/music/music/music/bar.mp3. 238 // Downloads/music/music/music/bar.mp3.
220 base::FilePath new_path(download_prefs_->DownloadPath().Append( 239 base::FilePath new_path(download_prefs_->DownloadPath().Append(
221 suggested_path).NormalizePathSeparators()); 240 suggested_path).NormalizePathSeparators());
222 // Do not pass a mime type to GenerateSafeFileName so that it does not force 241 // Do not pass a mime type to GenerateSafeFileName so that it does not force
223 // the filename to have an extension if the (Chrome) extension does not 242 // the filename to have an extension if the (Chrome) extension does not
224 // suggest it. 243 // suggest it.
225 net::GenerateSafeFileName(std::string(), false, &new_path); 244 net::GenerateSafeFileName(std::string(), false, &new_path);
226 virtual_path_ = new_path; 245 virtual_path_ = new_path;
227 create_directory_ = true; 246 create_target_directory_ = true;
228 conflict_action_ = conflict_action; 247 conflict_action_ = conflict_action;
229 } 248 }
230 249
231 DoLoop(); 250 DoLoop();
232 } 251 }
233 252
234 DownloadTargetDeterminer::Result 253 DownloadTargetDeterminer::Result
235 DownloadTargetDeterminer::DoReserveVirtualPath() { 254 DownloadTargetDeterminer::DoReserveVirtualPath() {
236 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 255 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
237 DCHECK(!virtual_path_.empty()); 256 DCHECK(!virtual_path_.empty());
238 257
239 next_state_ = STATE_PROMPT_USER_FOR_DOWNLOAD_PATH; 258 next_state_ = STATE_PROMPT_USER_FOR_DOWNLOAD_PATH;
240 259
241 delegate_->ReserveVirtualPath( 260 delegate_->ReserveVirtualPath(
242 download_, virtual_path_, create_directory_, conflict_action_, 261 download_, virtual_path_, create_target_directory_, conflict_action_,
243 base::Bind(&DownloadTargetDeterminer::ReserveVirtualPathDone, 262 base::Bind(&DownloadTargetDeterminer::ReserveVirtualPathDone,
244 weak_ptr_factory_.GetWeakPtr())); 263 weak_ptr_factory_.GetWeakPtr()));
245 return QUIT_DOLOOP; 264 return QUIT_DOLOOP;
246 } 265 }
247 266
248 void DownloadTargetDeterminer::ReserveVirtualPathDone( 267 void DownloadTargetDeterminer::ReserveVirtualPathDone(
249 const base::FilePath& path, bool verified) { 268 const base::FilePath& path, bool verified) {
250 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 269 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
251 DVLOG(20) << "Reserved path: " << path.AsUTF8Unsafe() 270 DVLOG(20) << "Reserved path: " << path.AsUTF8Unsafe()
252 << " Verified:" << verified; 271 << " Verified:" << verified;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 DownloadTargetDeterminer::Result 358 DownloadTargetDeterminer::Result
340 DownloadTargetDeterminer::DoCheckVisitedReferrerBefore() { 359 DownloadTargetDeterminer::DoCheckVisitedReferrerBefore() {
341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 360 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
342 361
343 next_state_ = STATE_DETERMINE_INTERMEDIATE_PATH; 362 next_state_ = STATE_DETERMINE_INTERMEDIATE_PATH;
344 363
345 // Checking if there are prior visits to the referrer is only necessary if the 364 // Checking if there are prior visits to the referrer is only necessary if the
346 // danger level of the download depends on the file type. This excludes cases 365 // danger level of the download depends on the file type. This excludes cases
347 // where the download has already been deemed dangerous, or where the user is 366 // where the download has already been deemed dangerous, or where the user is
348 // going to be prompted or where this is a programmatic download. 367 // going to be prompted or where this is a programmatic download.
349 if (danger_type_ != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS || 368 if (danger_type_ != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)
350 should_prompt_ ||
351 !download_->GetForcedFilePath().empty()) {
352 return CONTINUE; 369 return CONTINUE;
353 }
354 370
355 // Assume that: 371 // Assume that:
356 // IsDangerousFile(VISITED_REFERRER) => IsDangerousFile(NO_VISITS_...) 372 // IsDangerousFile(VISITED_REFERRER) => IsDangerousFile(NO_VISITS_...)
357 // I.e. having visited a referrer only lowers a file's danger level. 373 // I.e. having visited a referrer only lowers a file's danger level.
358 if (IsDangerousFile(NO_VISITS_TO_REFERRER)) { 374 if (IsDangerousFile(NO_VISITS_TO_REFERRER)) {
359 // Only need to ping the history DB if the download would be considered safe 375 // Only need to ping the history DB if the download would be considered safe
360 // if there are prior visits and is considered dangerous otherwise. 376 // if there are prior visits and is considered dangerous otherwise.
361 if (!IsDangerousFile(VISITED_REFERRER)) { 377 if (!IsDangerousFile(VISITED_REFERRER)) {
362 // HistoryServiceFactory redirects incognito profiles to on-record 378 // HistoryServiceFactory redirects incognito profiles to on-record
363 // profiles. There's no history for on-record profiles in unit_tests. 379 // profiles. There's no history for on-record profiles in unit_tests.
(...skipping 26 matching lines...) Expand all
390 danger_type_ = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE; 406 danger_type_ = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
391 DoLoop(); 407 DoLoop();
392 } 408 }
393 409
394 DownloadTargetDeterminer::Result 410 DownloadTargetDeterminer::Result
395 DownloadTargetDeterminer::DoDetermineIntermediatePath() { 411 DownloadTargetDeterminer::DoDetermineIntermediatePath() {
396 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 412 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
397 DCHECK(!virtual_path_.empty()); 413 DCHECK(!virtual_path_.empty());
398 DCHECK(!local_path_.empty()); 414 DCHECK(!local_path_.empty());
399 DCHECK(intermediate_path_.empty()); 415 DCHECK(intermediate_path_.empty());
416 DCHECK(!virtual_path_.MatchesExtension(kCrdownloadSuffix));
417 DCHECK(!local_path_.MatchesExtension(kCrdownloadSuffix));
400 418
401 next_state_ = STATE_NONE; 419 next_state_ = STATE_NONE;
402 420
403 // Note that the intermediate filename is always uniquified (i.e. if a file by 421 // Note that the intermediate filename is always uniquified (i.e. if a file by
404 // the same name exists, it is never overwritten). Therefore the code below 422 // the same name exists, it is never overwritten). Therefore the code below
405 // does not attempt to find a name that doesn't conflict with an existing 423 // does not attempt to find a name that doesn't conflict with an existing
406 // file. 424 // file.
407 425
408 // If the actual target of the download is a virtual path, then the local path 426 // If the actual target of the download is a virtual path, then the local path
409 // is considered to point to a temporary path. A separate intermediate path is 427 // is considered to point to a temporary path. A separate intermediate path is
(...skipping 13 matching lines...) Expand all
423 intermediate_path_ = local_path_; 441 intermediate_path_ = local_path_;
424 return COMPLETE; 442 return COMPLETE;
425 } 443 }
426 444
427 // Other safe downloads get a .crdownload suffix for their intermediate name. 445 // Other safe downloads get a .crdownload suffix for their intermediate name.
428 if (danger_type_ == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) { 446 if (danger_type_ == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) {
429 intermediate_path_ = GetCrDownloadPath(local_path_); 447 intermediate_path_ = GetCrDownloadPath(local_path_);
430 return COMPLETE; 448 return COMPLETE;
431 } 449 }
432 450
451 // If this is a resumed download, then re-use the existing intermediate path
452 // if one is available. A resumed download shouldn't cause a non-dangerous
453 // download to be considered dangerous upon resumption. Therefore the
454 // intermediate file should already be in the correct form.
455 if (is_resumption_ && !download_->GetFullPath().empty() &&
456 local_path_.DirName() == download_->GetFullPath().DirName()) {
457 DCHECK_NE(content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS,
458 download_->GetDangerType());
459 DCHECK_EQ(kCrdownloadSuffix, download_->GetFullPath().Extension());
460 intermediate_path_ = download_->GetFullPath();
461 return COMPLETE;
462 }
463
433 // Dangerous downloads receive a random intermediate name that looks like: 464 // Dangerous downloads receive a random intermediate name that looks like:
434 // 'Unconfirmed <random>.crdownload'. 465 // 'Unconfirmed <random>.crdownload'.
435 const base::FilePath::CharType kUnconfirmedFormatSuffix[] = 466 const base::FilePath::CharType kUnconfirmedFormatSuffix[] =
436 FILE_PATH_LITERAL(" %d.crdownload"); 467 FILE_PATH_LITERAL(" %d.crdownload");
437 // Range of the <random> uniquifier. 468 // Range of the <random> uniquifier.
438 const int kUnconfirmedUniquifierRange = 1000000; 469 const int kUnconfirmedUniquifierRange = 1000000;
439 #if defined(OS_WIN) 470 #if defined(OS_WIN)
440 string16 unconfirmed_format = 471 string16 unconfirmed_format =
441 l10n_util::GetStringUTF16(IDS_DOWNLOAD_UNCONFIRMED_PREFIX); 472 l10n_util::GetStringUTF16(IDS_DOWNLOAD_UNCONFIRMED_PREFIX);
442 #else 473 #else
(...skipping 13 matching lines...) Expand all
456 DCHECK(download_); 487 DCHECK(download_);
457 DVLOG(20) << "Scheduling callback. Virtual:" << virtual_path_.AsUTF8Unsafe() 488 DVLOG(20) << "Scheduling callback. Virtual:" << virtual_path_.AsUTF8Unsafe()
458 << " Local:" << local_path_.AsUTF8Unsafe() 489 << " Local:" << local_path_.AsUTF8Unsafe()
459 << " Intermediate:" << intermediate_path_.AsUTF8Unsafe() 490 << " Intermediate:" << intermediate_path_.AsUTF8Unsafe()
460 << " Should prompt:" << should_prompt_ 491 << " Should prompt:" << should_prompt_
461 << " Danger type:" << danger_type_; 492 << " Danger type:" << danger_type_;
462 base::MessageLoop::current()->PostTask( 493 base::MessageLoop::current()->PostTask(
463 FROM_HERE, 494 FROM_HERE,
464 base::Bind(completion_callback_, 495 base::Bind(completion_callback_,
465 local_path_, 496 local_path_,
466 (should_prompt_ ? DownloadItem::TARGET_DISPOSITION_PROMPT : 497 (HasPromptedForPath() || should_prompt_
467 DownloadItem::TARGET_DISPOSITION_OVERWRITE), 498 ? DownloadItem::TARGET_DISPOSITION_PROMPT
499 : DownloadItem::TARGET_DISPOSITION_OVERWRITE),
468 danger_type_, 500 danger_type_,
469 intermediate_path_)); 501 intermediate_path_));
470 completion_callback_.Reset(); 502 completion_callback_.Reset();
471 delete this; 503 delete this;
472 } 504 }
473 505
474 void DownloadTargetDeterminer::CancelOnFailureAndDeleteSelf() { 506 void DownloadTargetDeterminer::CancelOnFailureAndDeleteSelf() {
475 // Path substitution failed. 507 // Path substitution failed.
476 virtual_path_.clear(); 508 virtual_path_.clear();
477 local_path_.clear(); 509 local_path_.clear();
478 intermediate_path_.clear(); 510 intermediate_path_.clear();
479 ScheduleCallbackAndDeleteSelf(); 511 ScheduleCallbackAndDeleteSelf();
480 } 512 }
481 513
482 Profile* DownloadTargetDeterminer::GetProfile() { 514 Profile* DownloadTargetDeterminer::GetProfile() {
483 DCHECK(download_->GetBrowserContext()); 515 DCHECK(download_->GetBrowserContext());
484 return Profile::FromBrowserContext(download_->GetBrowserContext()); 516 return Profile::FromBrowserContext(download_->GetBrowserContext());
485 } 517 }
486 518
487 bool DownloadTargetDeterminer::ShouldPromptForDownload( 519 bool DownloadTargetDeterminer::ShouldPromptForDownload(
488 const base::FilePath& filename) { 520 const base::FilePath& filename) const {
521 if (is_resumption_) {
522 // For resumed downloads, if the target disposition or prefs require
523 // prompting, the user has already been prompted. Try to respect the user's
524 // selection, unless we've discovered that the target path cannot be used
525 // for some reason.
526 content::DownloadInterruptReason reason = download_->GetLastReason();
527 return (reason == content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED ||
528 reason == content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE ||
529 reason == content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE);
530 }
531
489 // If the download path is forced, don't prompt. 532 // If the download path is forced, don't prompt.
490 if (!download_->GetForcedFilePath().empty()) { 533 if (!download_->GetForcedFilePath().empty()) {
491 // 'Save As' downloads shouldn't have a forced path. 534 // 'Save As' downloads shouldn't have a forced path.
492 DCHECK_NE(DownloadItem::TARGET_DISPOSITION_PROMPT, 535 DCHECK(DownloadItem::TARGET_DISPOSITION_PROMPT !=
493 download_->GetTargetDisposition()); 536 download_->GetTargetDisposition());
494 return false; 537 return false;
495 } 538 }
496 539
497 // Don't ask where to save if the download path is managed. Even if the user 540 // Don't ask where to save if the download path is managed. Even if the user
498 // wanted to be prompted for "all" downloads, or if this was a 'Save As' 541 // wanted to be prompted for "all" downloads, or if this was a 'Save As'
499 // download. 542 // download.
500 if (download_prefs_->IsDownloadPathManaged()) 543 if (download_prefs_->IsDownloadPathManaged())
501 return false; 544 return false;
502 545
503 // Prompt if this is a 'Save As' download. 546 // Prompt if this is a 'Save As' download.
(...skipping 14 matching lines...) Expand all
518 return true; 561 return true;
519 562
520 // Otherwise, don't prompt. Note that the user might still be prompted if 563 // Otherwise, don't prompt. Note that the user might still be prompted if
521 // there are unresolved conflicts during path reservation (e.g. due to the 564 // there are unresolved conflicts during path reservation (e.g. due to the
522 // target path being unwriteable or because there are too many conflicting 565 // target path being unwriteable or because there are too many conflicting
523 // files), or if an extension signals that the user be prompted on a filename 566 // files), or if an extension signals that the user be prompted on a filename
524 // conflict. 567 // conflict.
525 return false; 568 return false;
526 } 569 }
527 570
571 bool DownloadTargetDeterminer::HasPromptedForPath() const {
572 return (is_resumption_ && download_->GetTargetDisposition() ==
573 DownloadItem::TARGET_DISPOSITION_PROMPT);
574 }
575
528 bool DownloadTargetDeterminer::IsDangerousFile(PriorVisitsToReferrer visits) { 576 bool DownloadTargetDeterminer::IsDangerousFile(PriorVisitsToReferrer visits) {
529 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 577 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
578
579 // If the user has has been prompted or will be, assume that the user has
580 // approved the download. A programmatic download is considered safe unless it
581 // contains malware.
582 if (HasPromptedForPath() || should_prompt_ ||
583 !download_->GetForcedFilePath().empty())
584 return false;
585
530 const bool is_extension_download = 586 const bool is_extension_download =
531 download_crx_util::IsExtensionDownload(*download_); 587 download_crx_util::IsExtensionDownload(*download_);
532 588
533 // User-initiated extension downloads from pref-whitelisted sources are not 589 // User-initiated extension downloads from pref-whitelisted sources are not
534 // considered dangerous. 590 // considered dangerous.
535 if (download_->HasUserGesture() && 591 if (download_->HasUserGesture() &&
536 is_extension_download && 592 is_extension_download &&
537 download_crx_util::OffStoreInstallAllowedByPrefs( 593 download_crx_util::OffStoreInstallAllowedByPrefs(
538 GetProfile(), *download_)) { 594 GetProfile(), *download_)) {
539 return false; 595 return false;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 void DownloadTargetDeterminer::OnDownloadDestroyed( 632 void DownloadTargetDeterminer::OnDownloadDestroyed(
577 DownloadItem* download) { 633 DownloadItem* download) {
578 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 634 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
579 DCHECK_EQ(download_, download); 635 DCHECK_EQ(download_, download);
580 CancelOnFailureAndDeleteSelf(); 636 CancelOnFailureAndDeleteSelf();
581 } 637 }
582 638
583 // static 639 // static
584 void DownloadTargetDeterminer::Start( 640 void DownloadTargetDeterminer::Start(
585 content::DownloadItem* download, 641 content::DownloadItem* download,
642 const base::FilePath& initial_virtual_path,
586 DownloadPrefs* download_prefs, 643 DownloadPrefs* download_prefs,
587 DownloadTargetDeterminerDelegate* delegate, 644 DownloadTargetDeterminerDelegate* delegate,
588 const content::DownloadTargetCallback& callback) { 645 const content::DownloadTargetCallback& callback) {
589 // DownloadTargetDeterminer owns itself and will self destruct when the job is 646 // DownloadTargetDeterminer owns itself and will self destruct when the job is
590 // complete or the download item is destroyed. The callback is always invoked 647 // complete or the download item is destroyed. The callback is always invoked
591 // asynchronously. 648 // asynchronously.
592 new DownloadTargetDeterminer(download, download_prefs, delegate, callback); 649 new DownloadTargetDeterminer(download, initial_virtual_path, download_prefs,
650 delegate, callback);
593 } 651 }
594 652
595 // static 653 // static
596 base::FilePath DownloadTargetDeterminer::GetCrDownloadPath( 654 base::FilePath DownloadTargetDeterminer::GetCrDownloadPath(
597 const base::FilePath& suggested_path) { 655 const base::FilePath& suggested_path) {
598 return base::FilePath(suggested_path.value() + 656 return base::FilePath(suggested_path.value() + kCrdownloadSuffix);
599 FILE_PATH_LITERAL(".crdownload"));
600 } 657 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698