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

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: Merge with r203194 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)
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;
(...skipping 16 matching lines...) Expand all
51 (first_visit.LocalMidnight() < base::Time::Now().LocalMidnight())); 52 (first_visit.LocalMidnight() < base::Time::Now().LocalMidnight()));
52 } 53 }
53 54
54 } // namespace 55 } // namespace
55 56
56 DownloadTargetDeterminerDelegate::~DownloadTargetDeterminerDelegate() { 57 DownloadTargetDeterminerDelegate::~DownloadTargetDeterminerDelegate() {
57 } 58 }
58 59
59 DownloadTargetDeterminer::DownloadTargetDeterminer( 60 DownloadTargetDeterminer::DownloadTargetDeterminer(
60 DownloadItem* download, 61 DownloadItem* download,
62 const base::FilePath& initial_virtual_path,
61 DownloadPrefs* download_prefs, 63 DownloadPrefs* download_prefs,
62 DownloadTargetDeterminerDelegate* delegate, 64 DownloadTargetDeterminerDelegate* delegate,
63 const content::DownloadTargetCallback& callback) 65 const content::DownloadTargetCallback& callback)
64 : next_state_(STATE_GENERATE_TARGET_PATH), 66 : next_state_(STATE_GENERATE_TARGET_PATH),
65 should_prompt_(false), 67 should_prompt_(false),
66 create_directory_(false), 68 should_notify_extensions_(false),
67 conflict_action_(download->GetForcedFilePath().empty() ? 69 create_target_directory_(false),
68 DownloadPathReservationTracker::UNIQUIFY : 70 conflict_action_(DownloadPathReservationTracker::OVERWRITE),
69 DownloadPathReservationTracker::OVERWRITE),
70 danger_type_(download->GetDangerType()), 71 danger_type_(download->GetDangerType()),
72 virtual_path_(initial_virtual_path),
71 download_(download), 73 download_(download),
74 is_resumption_(download_->GetLastReason() !=
75 content::DOWNLOAD_INTERRUPT_REASON_NONE &&
76 !initial_virtual_path.empty()),
72 download_prefs_(download_prefs), 77 download_prefs_(download_prefs),
73 delegate_(delegate), 78 delegate_(delegate),
74 completion_callback_(callback), 79 completion_callback_(callback),
75 weak_ptr_factory_(this) { 80 weak_ptr_factory_(this) {
76 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 81 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
77 DCHECK(download_); 82 DCHECK(download_);
78 DCHECK(delegate); 83 DCHECK(delegate);
79 download_->AddObserver(this); 84 download_->AddObserver(this);
80 85
81 DoLoop(); 86 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 133 // return QUIT_DOLOOP. In this case, an inner DoLoop() may complete the target
129 // determination and delete |this|. 134 // determination and delete |this|.
130 135
131 if (result == COMPLETE) 136 if (result == COMPLETE)
132 ScheduleCallbackAndDeleteSelf(); 137 ScheduleCallbackAndDeleteSelf();
133 } 138 }
134 139
135 DownloadTargetDeterminer::Result 140 DownloadTargetDeterminer::Result
136 DownloadTargetDeterminer::DoGenerateTargetPath() { 141 DownloadTargetDeterminer::DoGenerateTargetPath() {
137 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 142 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
138 DCHECK(virtual_path_.empty());
139 DCHECK(local_path_.empty()); 143 DCHECK(local_path_.empty());
144 DCHECK(!should_prompt_);
145 DCHECK(!should_notify_extensions_);
146 DCHECK_EQ(DownloadPathReservationTracker::OVERWRITE, conflict_action_);
140 bool is_forced_path = !download_->GetForcedFilePath().empty(); 147 bool is_forced_path = !download_->GetForcedFilePath().empty();
141 148
142 next_state_ = STATE_NOTIFY_EXTENSIONS; 149 next_state_ = STATE_NOTIFY_EXTENSIONS;
143 150
144 // If we don't have a forced path, we should construct a path for the 151 if (!virtual_path_.empty() && HasPromptedForPath() && !is_forced_path) {
145 // download. Forced paths are only specified for programmatic downloads 152 // 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 153 // 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. 154 // and reuse the selection.
148 if (!is_forced_path) { 155 should_prompt_ = ShouldPromptForDownload(virtual_path_);
149 std::string default_filename( 156 } else if (!is_forced_path) {
157 // If we don't have a forced path, we should construct a path for the
158 // download. Forced paths are only specified for programmatic downloads
159 // (WebStore, Drag&Drop). Treat the path as a virtual path. We will
160 // eventually determine whether this is a local path and if not, figure out
161 // a local path.
162 std::string default_filename(
150 l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME)); 163 l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME));
151 base::FilePath generated_filename = net::GenerateFileName( 164 base::FilePath generated_filename = net::GenerateFileName(
152 download_->GetURL(), 165 download_->GetURL(),
153 download_->GetContentDisposition(), 166 download_->GetContentDisposition(),
154 GetProfile()->GetPrefs()->GetString(prefs::kDefaultCharset), 167 GetProfile()->GetPrefs()->GetString(prefs::kDefaultCharset),
155 download_->GetSuggestedFilename(), 168 download_->GetSuggestedFilename(),
156 download_->GetMimeType(), 169 download_->GetMimeType(),
157 default_filename); 170 default_filename);
158 should_prompt_ = ShouldPromptForDownload(generated_filename); 171 should_prompt_ = ShouldPromptForDownload(generated_filename);
159 base::FilePath target_directory; 172 base::FilePath target_directory;
160 if (should_prompt_) { 173 if (should_prompt_) {
161 DCHECK(!download_prefs_->IsDownloadPathManaged()); 174 DCHECK(!download_prefs_->IsDownloadPathManaged());
162 // If the user is going to be prompted and the user has been prompted 175 // 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. 176 // before, then always prefer the last directory that the user selected.
164 target_directory = download_prefs_->SaveFilePath(); 177 target_directory = download_prefs_->SaveFilePath();
165 } else { 178 } else {
166 target_directory = download_prefs_->DownloadPath(); 179 target_directory = download_prefs_->DownloadPath();
167 } 180 }
168 virtual_path_ = target_directory.Append(generated_filename); 181 virtual_path_ = target_directory.Append(generated_filename);
182 conflict_action_ = DownloadPathReservationTracker::UNIQUIFY;
183 should_notify_extensions_ = true;
169 } else { 184 } else {
170 DCHECK(!should_prompt_);
171 virtual_path_ = download_->GetForcedFilePath(); 185 virtual_path_ = download_->GetForcedFilePath();
186 // If this is a resumed download which was previously interrupted due to an
187 // issue with the forced path, the user is still not prompted. If the path
188 // supplied to a programmatic download is invalid, then the caller needs to
189 // intervene.
172 } 190 }
173 DCHECK(virtual_path_.IsAbsolute()); 191 DCHECK(virtual_path_.IsAbsolute());
174 DVLOG(20) << "Generated virtual path: " << virtual_path_.AsUTF8Unsafe(); 192 DVLOG(20) << "Generated virtual path: " << virtual_path_.AsUTF8Unsafe();
175 193
176 // If the download is DOA, don't bother going any further. This would be the 194 // 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 195 // 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 196 // file couldn't be created because both the downloads directory and the
179 // temporary directory are unwriteable). 197 // temporary directory are unwriteable).
180 // 198 //
181 // A virtual path is determined for DOA downloads for display purposes. This 199 // 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. 200 // is why this check is performed here instead of at the start.
183 if (download_->GetState() != DownloadItem::IN_PROGRESS) 201 if (download_->GetState() != DownloadItem::IN_PROGRESS)
184 return COMPLETE; 202 return COMPLETE;
185 return CONTINUE; 203 return CONTINUE;
186 } 204 }
187 205
188 DownloadTargetDeterminer::Result 206 DownloadTargetDeterminer::Result
189 DownloadTargetDeterminer::DoNotifyExtensions() { 207 DownloadTargetDeterminer::DoNotifyExtensions() {
190 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 208 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
191 DCHECK(!virtual_path_.empty()); 209 DCHECK(!virtual_path_.empty());
192 210
193 next_state_ = STATE_RESERVE_VIRTUAL_PATH; 211 next_state_ = STATE_RESERVE_VIRTUAL_PATH;
194 212
195 // If the target path is forced or if we don't have an extensions event 213 if (!should_notify_extensions_)
196 // router, then proceed with the original path.
197 if (!download_->GetForcedFilePath().empty())
198 return CONTINUE; 214 return CONTINUE;
199 215
200 delegate_->NotifyExtensions(download_, virtual_path_, 216 delegate_->NotifyExtensions(download_, virtual_path_,
201 base::Bind(&DownloadTargetDeterminer::NotifyExtensionsDone, 217 base::Bind(&DownloadTargetDeterminer::NotifyExtensionsDone,
202 weak_ptr_factory_.GetWeakPtr())); 218 weak_ptr_factory_.GetWeakPtr()));
203 return QUIT_DOLOOP; 219 return QUIT_DOLOOP;
204 } 220 }
205 221
206 void DownloadTargetDeterminer::NotifyExtensionsDone( 222 void DownloadTargetDeterminer::NotifyExtensionsDone(
207 const base::FilePath& suggested_path, 223 const base::FilePath& suggested_path,
208 DownloadPathReservationTracker::FilenameConflictAction conflict_action) { 224 DownloadPathReservationTracker::FilenameConflictAction conflict_action) {
209 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 225 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
210 DVLOG(20) << "Extension suggested path: " << suggested_path.AsUTF8Unsafe(); 226 DVLOG(20) << "Extension suggested path: " << suggested_path.AsUTF8Unsafe();
211 227
212 if (!suggested_path.empty()) { 228 if (!suggested_path.empty()) {
213 // If an extension overrides the filename, then the target directory will be 229 // If an extension overrides the filename, then the target directory will be
214 // forced to download_prefs_->DownloadPath() since extensions cannot place 230 // forced to download_prefs_->DownloadPath() since extensions cannot place
215 // downloaded files anywhere except there. This prevents subdirectories from 231 // downloaded files anywhere except there. This prevents subdirectories from
216 // accumulating: if an extension is allowed to say that a file should go in 232 // 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 233 // 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 234 // the subdirectory /music/ so that the next download may end up in
219 // Downloads/music/music/music/bar.mp3. 235 // Downloads/music/music/music/bar.mp3.
220 base::FilePath new_path(download_prefs_->DownloadPath().Append( 236 base::FilePath new_path(download_prefs_->DownloadPath().Append(
221 suggested_path).NormalizePathSeparators()); 237 suggested_path).NormalizePathSeparators());
222 // Do not pass a mime type to GenerateSafeFileName so that it does not force 238 // 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 239 // the filename to have an extension if the (Chrome) extension does not
224 // suggest it. 240 // suggest it.
225 net::GenerateSafeFileName(std::string(), false, &new_path); 241 net::GenerateSafeFileName(std::string(), false, &new_path);
226 virtual_path_ = new_path; 242 virtual_path_ = new_path;
227 create_directory_ = true; 243 create_target_directory_ = true;
228 conflict_action_ = conflict_action; 244 conflict_action_ = conflict_action;
229 } 245 }
230 246
231 DoLoop(); 247 DoLoop();
232 } 248 }
233 249
234 DownloadTargetDeterminer::Result 250 DownloadTargetDeterminer::Result
235 DownloadTargetDeterminer::DoReserveVirtualPath() { 251 DownloadTargetDeterminer::DoReserveVirtualPath() {
236 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 252 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
237 DCHECK(!virtual_path_.empty()); 253 DCHECK(!virtual_path_.empty());
238 254
239 next_state_ = STATE_PROMPT_USER_FOR_DOWNLOAD_PATH; 255 next_state_ = STATE_PROMPT_USER_FOR_DOWNLOAD_PATH;
240 256
241 delegate_->ReserveVirtualPath( 257 delegate_->ReserveVirtualPath(
242 download_, virtual_path_, create_directory_, conflict_action_, 258 download_, virtual_path_, create_target_directory_, conflict_action_,
243 base::Bind(&DownloadTargetDeterminer::ReserveVirtualPathDone, 259 base::Bind(&DownloadTargetDeterminer::ReserveVirtualPathDone,
244 weak_ptr_factory_.GetWeakPtr())); 260 weak_ptr_factory_.GetWeakPtr()));
245 return QUIT_DOLOOP; 261 return QUIT_DOLOOP;
246 } 262 }
247 263
248 void DownloadTargetDeterminer::ReserveVirtualPathDone( 264 void DownloadTargetDeterminer::ReserveVirtualPathDone(
249 const base::FilePath& path, bool verified) { 265 const base::FilePath& path, bool verified) {
250 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 266 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
251 DVLOG(20) << "Reserved path: " << path.AsUTF8Unsafe() 267 DVLOG(20) << "Reserved path: " << path.AsUTF8Unsafe()
252 << " Verified:" << verified; 268 << " Verified:" << verified;
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
339 DownloadTargetDeterminer::Result 355 DownloadTargetDeterminer::Result
340 DownloadTargetDeterminer::DoCheckVisitedReferrerBefore() { 356 DownloadTargetDeterminer::DoCheckVisitedReferrerBefore() {
341 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 357 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
342 358
343 next_state_ = STATE_DETERMINE_INTERMEDIATE_PATH; 359 next_state_ = STATE_DETERMINE_INTERMEDIATE_PATH;
344 360
345 // Checking if there are prior visits to the referrer is only necessary if the 361 // 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 362 // 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 363 // 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. 364 // going to be prompted or where this is a programmatic download.
349 if (danger_type_ != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS || 365 if (danger_type_ != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS)
350 should_prompt_ ||
351 !download_->GetForcedFilePath().empty()) {
352 return CONTINUE; 366 return CONTINUE;
353 }
354 367
355 // Assume that: 368 // Assume that:
356 // IsDangerousFile(VISITED_REFERRER) => IsDangerousFile(NO_VISITS_...) 369 // IsDangerousFile(VISITED_REFERRER) => IsDangerousFile(NO_VISITS_...)
357 // I.e. having visited a referrer only lowers a file's danger level. 370 // I.e. having visited a referrer only lowers a file's danger level.
358 if (IsDangerousFile(NO_VISITS_TO_REFERRER)) { 371 if (IsDangerousFile(NO_VISITS_TO_REFERRER)) {
359 // Only need to ping the history DB if the download would be considered safe 372 // 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. 373 // if there are prior visits and is considered dangerous otherwise.
361 if (!IsDangerousFile(VISITED_REFERRER)) { 374 if (!IsDangerousFile(VISITED_REFERRER)) {
362 // HistoryServiceFactory redirects incognito profiles to on-record 375 // HistoryServiceFactory redirects incognito profiles to on-record
363 // profiles. There's no history for on-record profiles in unit_tests. 376 // 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; 403 danger_type_ = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
391 DoLoop(); 404 DoLoop();
392 } 405 }
393 406
394 DownloadTargetDeterminer::Result 407 DownloadTargetDeterminer::Result
395 DownloadTargetDeterminer::DoDetermineIntermediatePath() { 408 DownloadTargetDeterminer::DoDetermineIntermediatePath() {
396 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 409 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
397 DCHECK(!virtual_path_.empty()); 410 DCHECK(!virtual_path_.empty());
398 DCHECK(!local_path_.empty()); 411 DCHECK(!local_path_.empty());
399 DCHECK(intermediate_path_.empty()); 412 DCHECK(intermediate_path_.empty());
413 DCHECK(!virtual_path_.MatchesExtension(FILE_PATH_LITERAL(".crdownload")));
414 DCHECK(!local_path_.MatchesExtension(FILE_PATH_LITERAL(".crdownload")));
400 415
401 next_state_ = STATE_NONE; 416 next_state_ = STATE_NONE;
402 417
403 // Note that the intermediate filename is always uniquified (i.e. if a file by 418 // 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 419 // 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 420 // does not attempt to find a name that doesn't conflict with an existing
406 // file. 421 // file.
407 422
408 // If the actual target of the download is a virtual path, then the local path 423 // 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 424 // is considered to point to a temporary path. A separate intermediate path is
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
456 DCHECK(download_); 471 DCHECK(download_);
457 DVLOG(20) << "Scheduling callback. Virtual:" << virtual_path_.AsUTF8Unsafe() 472 DVLOG(20) << "Scheduling callback. Virtual:" << virtual_path_.AsUTF8Unsafe()
458 << " Local:" << local_path_.AsUTF8Unsafe() 473 << " Local:" << local_path_.AsUTF8Unsafe()
459 << " Intermediate:" << intermediate_path_.AsUTF8Unsafe() 474 << " Intermediate:" << intermediate_path_.AsUTF8Unsafe()
460 << " Should prompt:" << should_prompt_ 475 << " Should prompt:" << should_prompt_
461 << " Danger type:" << danger_type_; 476 << " Danger type:" << danger_type_;
462 base::MessageLoop::current()->PostTask( 477 base::MessageLoop::current()->PostTask(
463 FROM_HERE, 478 FROM_HERE,
464 base::Bind(completion_callback_, 479 base::Bind(completion_callback_,
465 local_path_, 480 local_path_,
466 (should_prompt_ ? DownloadItem::TARGET_DISPOSITION_PROMPT : 481 (HasPromptedForPath() || should_prompt_
467 DownloadItem::TARGET_DISPOSITION_OVERWRITE), 482 ? DownloadItem::TARGET_DISPOSITION_PROMPT
483 : DownloadItem::TARGET_DISPOSITION_OVERWRITE),
468 danger_type_, 484 danger_type_,
469 intermediate_path_)); 485 intermediate_path_));
470 completion_callback_.Reset(); 486 completion_callback_.Reset();
471 delete this; 487 delete this;
472 } 488 }
473 489
474 void DownloadTargetDeterminer::CancelOnFailureAndDeleteSelf() { 490 void DownloadTargetDeterminer::CancelOnFailureAndDeleteSelf() {
475 // Path substitution failed. 491 // Path substitution failed.
476 virtual_path_.clear(); 492 virtual_path_.clear();
477 local_path_.clear(); 493 local_path_.clear();
478 intermediate_path_.clear(); 494 intermediate_path_.clear();
479 ScheduleCallbackAndDeleteSelf(); 495 ScheduleCallbackAndDeleteSelf();
480 } 496 }
481 497
482 Profile* DownloadTargetDeterminer::GetProfile() { 498 Profile* DownloadTargetDeterminer::GetProfile() {
483 DCHECK(download_->GetBrowserContext()); 499 DCHECK(download_->GetBrowserContext());
484 return Profile::FromBrowserContext(download_->GetBrowserContext()); 500 return Profile::FromBrowserContext(download_->GetBrowserContext());
485 } 501 }
486 502
487 bool DownloadTargetDeterminer::ShouldPromptForDownload( 503 bool DownloadTargetDeterminer::ShouldPromptForDownload(
488 const base::FilePath& filename) { 504 const base::FilePath& filename) const {
505 if (is_resumption_) {
506 // For resumed downloads, if the target disposition or prefs require
507 // prompting, the user has already been prompted. Try to respect the user's
508 // selection, unless we've discovered that the target path cannot be used
509 // for some reason.
510 content::DownloadInterruptReason reason = download_->GetLastReason();
511 return (reason == content::DOWNLOAD_INTERRUPT_REASON_FILE_ACCESS_DENIED ||
512 reason == content::DOWNLOAD_INTERRUPT_REASON_FILE_NO_SPACE ||
513 reason == content::DOWNLOAD_INTERRUPT_REASON_FILE_TOO_LARGE);
514 }
515
489 // If the download path is forced, don't prompt. 516 // If the download path is forced, don't prompt.
490 if (!download_->GetForcedFilePath().empty()) { 517 if (!download_->GetForcedFilePath().empty()) {
491 // 'Save As' downloads shouldn't have a forced path. 518 // 'Save As' downloads shouldn't have a forced path.
492 DCHECK_NE(DownloadItem::TARGET_DISPOSITION_PROMPT, 519 DCHECK(DownloadItem::TARGET_DISPOSITION_PROMPT !=
493 download_->GetTargetDisposition()); 520 download_->GetTargetDisposition());
494 return false; 521 return false;
495 } 522 }
496 523
497 // Don't ask where to save if the download path is managed. Even if the user 524 // 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' 525 // wanted to be prompted for "all" downloads, or if this was a 'Save As'
499 // download. 526 // download.
500 if (download_prefs_->IsDownloadPathManaged()) 527 if (download_prefs_->IsDownloadPathManaged())
501 return false; 528 return false;
502 529
503 // Prompt if this is a 'Save As' download. 530 // Prompt if this is a 'Save As' download.
(...skipping 14 matching lines...) Expand all
518 return true; 545 return true;
519 546
520 // Otherwise, don't prompt. Note that the user might still be prompted if 547 // 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 548 // there are unresolved conflicts during path reservation (e.g. due to the
522 // target path being unwriteable or because there are too many conflicting 549 // 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 550 // files), or if an extension signals that the user be prompted on a filename
524 // conflict. 551 // conflict.
525 return false; 552 return false;
526 } 553 }
527 554
555 bool DownloadTargetDeterminer::HasPromptedForPath() const {
556 return (is_resumption_ && download_->GetTargetDisposition() ==
557 DownloadItem::TARGET_DISPOSITION_PROMPT);
558 }
559
528 bool DownloadTargetDeterminer::IsDangerousFile(PriorVisitsToReferrer visits) { 560 bool DownloadTargetDeterminer::IsDangerousFile(PriorVisitsToReferrer visits) {
529 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 561 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
562
563 // If the user has has been prompted or will be, assume that the user has
564 // approved the download. A programmatic download is considered safe unless it
565 // contains malware.
566 if (HasPromptedForPath() || should_prompt_ ||
567 !download_->GetForcedFilePath().empty())
568 return false;
569
530 const bool is_extension_download = 570 const bool is_extension_download =
531 download_crx_util::IsExtensionDownload(*download_); 571 download_crx_util::IsExtensionDownload(*download_);
532 572
533 // User-initiated extension downloads from pref-whitelisted sources are not 573 // User-initiated extension downloads from pref-whitelisted sources are not
534 // considered dangerous. 574 // considered dangerous.
535 if (download_->HasUserGesture() && 575 if (download_->HasUserGesture() &&
536 is_extension_download && 576 is_extension_download &&
537 download_crx_util::OffStoreInstallAllowedByPrefs( 577 download_crx_util::OffStoreInstallAllowedByPrefs(
538 GetProfile(), *download_)) { 578 GetProfile(), *download_)) {
539 return false; 579 return false;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 void DownloadTargetDeterminer::OnDownloadDestroyed( 616 void DownloadTargetDeterminer::OnDownloadDestroyed(
577 DownloadItem* download) { 617 DownloadItem* download) {
578 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 618 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
579 DCHECK_EQ(download_, download); 619 DCHECK_EQ(download_, download);
580 CancelOnFailureAndDeleteSelf(); 620 CancelOnFailureAndDeleteSelf();
581 } 621 }
582 622
583 // static 623 // static
584 void DownloadTargetDeterminer::Start( 624 void DownloadTargetDeterminer::Start(
585 content::DownloadItem* download, 625 content::DownloadItem* download,
626 const base::FilePath& initial_virtual_path,
586 DownloadPrefs* download_prefs, 627 DownloadPrefs* download_prefs,
587 DownloadTargetDeterminerDelegate* delegate, 628 DownloadTargetDeterminerDelegate* delegate,
588 const content::DownloadTargetCallback& callback) { 629 const content::DownloadTargetCallback& callback) {
589 // DownloadTargetDeterminer owns itself and will self destruct when the job is 630 // DownloadTargetDeterminer owns itself and will self destruct when the job is
590 // complete or the download item is destroyed. The callback is always invoked 631 // complete or the download item is destroyed. The callback is always invoked
591 // asynchronously. 632 // asynchronously.
592 new DownloadTargetDeterminer(download, download_prefs, delegate, callback); 633 new DownloadTargetDeterminer(download, initial_virtual_path, download_prefs,
634 delegate, callback);
593 } 635 }
594 636
595 // static 637 // static
596 base::FilePath DownloadTargetDeterminer::GetCrDownloadPath( 638 base::FilePath DownloadTargetDeterminer::GetCrDownloadPath(
597 const base::FilePath& suggested_path) { 639 const base::FilePath& suggested_path) {
598 return base::FilePath(suggested_path.value() + 640 return base::FilePath(suggested_path.value() +
599 FILE_PATH_LITERAL(".crdownload")); 641 FILE_PATH_LITERAL(".crdownload"));
600 } 642 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698