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

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

Powered by Google App Engine
This is Rietveld 408576698