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

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

Issue 12850002: Move download filename determintion into a separate class. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix tests on Android Created 7 years, 7 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
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "chrome/browser/download/download_target_determiner.h"
6
7 #include "base/prefs/pref_service.h"
8 #include "base/rand_util.h"
9 #include "base/stringprintf.h"
10 #include "base/time.h"
11 #include "chrome/browser/download/chrome_download_manager_delegate.h"
12 #include "chrome/browser/download/download_crx_util.h"
13 #include "chrome/browser/download/download_extensions.h"
14 #include "chrome/browser/download/download_prefs.h"
15 #include "chrome/browser/download/download_util.h"
16 #include "chrome/browser/extensions/webstore_installer.h"
17 #include "chrome/browser/history/history_service.h"
18 #include "chrome/browser/history/history_service_factory.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/common/extensions/extension.h"
21 #include "chrome/common/extensions/feature_switch.h"
22 #include "chrome/common/pref_names.h"
23 #include "content/public/browser/browser_context.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "grit/generated_resources.h"
26 #include "net/base/net_util.h"
27 #include "ui/base/l10n/l10n_util.h"
28
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;
35 using content::DownloadItem;
36
37 namespace {
38
39 // Condenses the results from HistoryService::GetVisibleVisitCountToHost() to a
40 // 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
42 // midnight.
43 void VisitCountsToVisitedBefore(
44 const base::Callback<void(bool)>& callback,
45 HistoryService::Handle unused_handle,
46 bool found_visits,
47 int count,
48 base::Time first_visit) {
49 callback.Run(
50 found_visits && count > 0 &&
51 (first_visit.LocalMidnight() < base::Time::Now().LocalMidnight()));
52 }
53
54 } // namespace
55
56 DownloadTargetDeterminerDelegate::~DownloadTargetDeterminerDelegate() {
57 }
58
59 DownloadTargetDeterminer::DownloadTargetDeterminer(
60 DownloadItem* download,
61 DownloadPrefs* download_prefs,
62 const base::FilePath& last_selected_directory,
63 DownloadTargetDeterminerDelegate* delegate,
64 const content::DownloadTargetCallback& callback)
65 : next_state_(STATE_GENERATE_TARGET_PATH),
66 should_prompt_(false),
67 conflict_action_(download->GetForcedFilePath().empty() ?
68 DownloadPathReservationTracker::UNIQUIFY :
69 DownloadPathReservationTracker::OVERWRITE),
70 danger_type_(download->GetDangerType()),
71 download_(download),
72 download_prefs_(download_prefs),
73 delegate_(delegate),
74 last_selected_directory_(last_selected_directory),
75 completion_callback_(callback),
76 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)) {
77 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
78 DCHECK(download_);
79 DCHECK(delegate);
80 download_->AddObserver(this);
81
82 DoLoop();
83 }
84
85 DownloadTargetDeterminer::~DownloadTargetDeterminer() {
86 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
87 DCHECK(download_);
88 DCHECK(completion_callback_.is_null());
89 download_->RemoveObserver(this);
90 }
91
92 void DownloadTargetDeterminer::DoLoop() {
93 Result result = CONTINUE;
94 do {
95 State current_state = next_state_;
96 next_state_ = STATE_NONE;
97
98 switch (current_state) {
99 case STATE_GENERATE_TARGET_PATH:
100 result = DoGenerateTargetPath();
101 break;
102 case STATE_NOTIFY_EXTENSIONS:
103 result = DoNotifyExtensions();
104 break;
105 case STATE_RESERVE_VIRTUAL_PATH:
106 result = DoReserveVirtualPath();
107 break;
108 case STATE_PROMPT_USER_FOR_DOWNLOAD_PATH:
109 result = DoPromptUserForDownloadPath();
110 break;
111 case STATE_DETERMINE_LOCAL_PATH:
112 result = DoDetermineLocalPath();
113 break;
114 case STATE_CHECK_DOWNLOAD_URL:
115 result = DoCheckDownloadUrl();
116 break;
117 case STATE_DETERMINE_INTERMEDIATE_PATH:
118 result = DoDetermineIntermediatePath();
119 break;
120 case STATE_CHECK_VISITED_REFERRER_BEFORE:
121 result = DoCheckVisitedReferrerBefore();
122 break;
123 case STATE_NONE:
124 NOTREACHED();
125 return;
126 }
127 } while (result == CONTINUE);
128 // Note that if a callback completes synchronously, the handler will still
129 // return QUIT_DOLOOP. In this case, an inner DoLoop() may complete the target
130 // determination and delete |this|.
131
132 if (result == COMPLETE)
133 ScheduleCallbackAndDeleteSelf();
134 }
135
136 DownloadTargetDeterminer::Result
137 DownloadTargetDeterminer::DoGenerateTargetPath() {
138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
139 DCHECK(virtual_path_.empty());
140 DCHECK(local_path_.empty());
141 bool is_forced_path = !download_->GetForcedFilePath().empty();
142
143 next_state_ = STATE_NOTIFY_EXTENSIONS;
144
145 // If we don't have a forced path, we should construct a path for the
146 // download. Forced paths are only specified for programmatic downloads
147 // (WebStore, Drag&Drop). Treat the path as a virtual path. We will eventually
148 // determine whether this is a local path and if not, figure out a local path.
149 if (!is_forced_path) {
150 std::string default_filename(
151 l10n_util::GetStringUTF8(IDS_DEFAULT_DOWNLOAD_FILENAME));
152 base::FilePath generated_filename = net::GenerateFileName(
153 download_->GetURL(),
154 download_->GetContentDisposition(),
155 GetProfile()->GetPrefs()->GetString(prefs::kDefaultCharset),
156 download_->GetSuggestedFilename(),
157 download_->GetMimeType(),
158 default_filename);
159 should_prompt_ = ShouldPromptForDownload(generated_filename);
160 base::FilePath target_directory;
161 if (should_prompt_ && !last_selected_directory_.empty()) {
162 DCHECK(!download_prefs_->IsDownloadPathManaged());
163 // If the user is going to be prompted and the user has been prompted
164 // before, then always prefer the last directory that the user selected.
165 target_directory = last_selected_directory_;
166 } else {
167 target_directory = download_prefs_->DownloadPath();
168 }
169 virtual_path_ = target_directory.Append(generated_filename);
170 } else {
171 DCHECK(!should_prompt_);
172 virtual_path_ = download_->GetForcedFilePath();
173 }
174 DCHECK(virtual_path_.IsAbsolute());
175 DVLOG(20) << "Generated virtual path: " << virtual_path_.AsUTF8Unsafe();
176
177 // If the download is DOA, don't bother going any further. This would be the
178 // case for a download that failed to initialize (e.g. the initial temporary
179 // file couldn't be created because both the downloads directory and the
180 // temporary directory are unwriteable).
181 //
182 // A virtual path is determined for DOA downloads for display purposes. This
183 // is why this check is performed here instead of at the start.
184 if (!download_->IsInProgress())
185 return COMPLETE;
186 return CONTINUE;
187 }
188
189 DownloadTargetDeterminer::Result
190 DownloadTargetDeterminer::DoNotifyExtensions() {
191 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
192 DCHECK(!virtual_path_.empty());
193
194 next_state_ = STATE_RESERVE_VIRTUAL_PATH;
195
196 // If the target path is forced or if we don't have an extensions event
197 // router, then proceed with the original path.
198 if (!download_->GetForcedFilePath().empty())
199 return CONTINUE;
200
201 delegate_->NotifyExtensions(download_, virtual_path_,
202 base::Bind(&DownloadTargetDeterminer::NotifyExtensionsDone,
203 weak_ptr_factory_.GetWeakPtr()));
204 return QUIT_DOLOOP;
205 }
206
207 void DownloadTargetDeterminer::NotifyExtensionsDone(
208 const base::FilePath& suggested_path,
209 DownloadPathReservationTracker::FilenameConflictAction conflict_action) {
210 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
211 DVLOG(20) << "Extension suggested path: " << suggested_path.AsUTF8Unsafe();
212
213 if (!suggested_path.empty()) {
214 // If an extension overrides the filename, then the target directory will be
215 // forced to download_prefs_->DownloadPath() since extensions cannot place
216 // downloaded files anywhere except there. This prevents subdirectories from
217 // accumulating: if an extension is allowed to say that a file should go in
218 // last_download_path/music/foo.mp3, then last_download_path will accumulate
219 // the subdirectory /music/ so that the next download may end up in
220 // Downloads/music/music/music/bar.mp3.
221 base::FilePath new_path(download_prefs_->DownloadPath().Append(
222 suggested_path).NormalizePathSeparators());
223 // Do not pass a mime type to GenerateSafeFileName so that it does not force
224 // the filename to have an extension if the (Chrome) extension does not
225 // suggest it.
226 net::GenerateSafeFileName(std::string(), false, &new_path);
227 virtual_path_ = new_path;
228 conflict_action_ = conflict_action;
229 }
230
231 DoLoop();
232 }
233
234 DownloadTargetDeterminer::Result
235 DownloadTargetDeterminer::DoReserveVirtualPath() {
236 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
237 DCHECK(!virtual_path_.empty());
238
239 next_state_ = STATE_PROMPT_USER_FOR_DOWNLOAD_PATH;
240
241 delegate_->ReserveVirtualPath(
242 download_, virtual_path_, conflict_action_,
243 base::Bind(&DownloadTargetDeterminer::ReserveVirtualPathDone,
244 weak_ptr_factory_.GetWeakPtr()));
245 return QUIT_DOLOOP;
246 }
247
248 void DownloadTargetDeterminer::ReserveVirtualPathDone(
249 const base::FilePath& path, bool verified) {
250 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
251 DVLOG(20) << "Reserved path: " << path.AsUTF8Unsafe()
252 << " Verified:" << verified;
253 should_prompt_ = (should_prompt_ || !verified);
254 virtual_path_ = path;
255 DoLoop();
256 }
257
258 DownloadTargetDeterminer::Result
259 DownloadTargetDeterminer::DoPromptUserForDownloadPath() {
260 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
261 DCHECK(!virtual_path_.empty());
262
263 next_state_ = STATE_DETERMINE_LOCAL_PATH;
264
265 if (should_prompt_) {
266 delegate_->PromptUserForDownloadPath(
267 download_,
268 virtual_path_,
269 base::Bind(&DownloadTargetDeterminer::PromptUserForDownloadPathDone,
270 weak_ptr_factory_.GetWeakPtr()));
271 return QUIT_DOLOOP;
272 }
273 return CONTINUE;
274 }
275
276 void DownloadTargetDeterminer::PromptUserForDownloadPathDone(
277 const base::FilePath& virtual_path) {
278 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
279 DVLOG(20) << "User selected path:" << virtual_path.AsUTF8Unsafe();
280 if (virtual_path.empty()) {
281 CancelOnFailureAndDeleteSelf();
282 return;
283 }
284 virtual_path_ = virtual_path;
285 DoLoop();
286 }
287
288 DownloadTargetDeterminer::Result
289 DownloadTargetDeterminer::DoDetermineLocalPath() {
290 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
291 DCHECK(!virtual_path_.empty());
292 DCHECK(local_path_.empty());
293
294 next_state_ = STATE_CHECK_DOWNLOAD_URL;
295
296 delegate_->DetermineLocalPath(
297 download_,
298 virtual_path_,
299 base::Bind(&DownloadTargetDeterminer::DetermineLocalPathDone,
300 weak_ptr_factory_.GetWeakPtr()));
301 return QUIT_DOLOOP;
302 }
303
304 void DownloadTargetDeterminer::DetermineLocalPathDone(
305 const base::FilePath& local_path) {
306 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
307 DVLOG(20) << "Local path: " << local_path.AsUTF8Unsafe();
308 if (local_path.empty()) {
309 // Path subsitution failed.
310 CancelOnFailureAndDeleteSelf();
311 return;
312 }
313 local_path_ = local_path;
314 DoLoop();
315 }
316
317 DownloadTargetDeterminer::Result
318 DownloadTargetDeterminer::DoCheckDownloadUrl() {
319 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
320 DCHECK(!virtual_path_.empty());
321 next_state_ = STATE_CHECK_VISITED_REFERRER_BEFORE;
322 delegate_->CheckDownloadUrl(
323 download_,
324 virtual_path_,
325 base::Bind(&DownloadTargetDeterminer::CheckDownloadUrlDone,
326 weak_ptr_factory_.GetWeakPtr()));
327 return QUIT_DOLOOP;
328 }
329
330 void DownloadTargetDeterminer::CheckDownloadUrlDone(
331 content::DownloadDangerType danger_type) {
332 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
333 DVLOG(20) << "URL Check Result:" << danger_type;
334 danger_type_ = danger_type;
335 DoLoop();
336 }
337
338 DownloadTargetDeterminer::Result
339 DownloadTargetDeterminer::DoCheckVisitedReferrerBefore() {
340 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
341
342 next_state_ = STATE_DETERMINE_INTERMEDIATE_PATH;
343
344 // Checking if there are prior visits to the referrer is only necessary if the
345 // danger level of the download depends on the file type. This excludes cases
346 // where the download has already been deemed dangerous, or where the user is
347 // going to be prompted or where this is a programmatic download.
348 if (danger_type_ != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS ||
349 should_prompt_ ||
350 !download_->GetForcedFilePath().empty()) {
351 return CONTINUE;
352 }
353
354 // Assume that:
355 // IsDangerousFile(VISITED_REFERRER) => IsDangerousFile(NO_VISITS_...)
356 // I.e. having visited a referrer only lowers a file's danger level.
357 if (IsDangerousFile(NO_VISITS_TO_REFERRER)) {
358 // Only need to ping the history DB if the download would be considered safe
359 // if there are prior visits and is considered dangerous otherwise.
360 if (!IsDangerousFile(VISITED_REFERRER)) {
361 // HistoryServiceFactory redirects incognito profiles to on-record
362 // profiles. There's no history for on-record profiles in unit_tests.
363 HistoryService* history_service = HistoryServiceFactory::GetForProfile(
364 GetProfile(), Profile::EXPLICIT_ACCESS);
365
366 if (history_service && download_->GetReferrerUrl().is_valid()) {
367 history_service->GetVisibleVisitCountToHost(
368 download_->GetReferrerUrl(), &history_consumer_,
369 base::Bind(&VisitCountsToVisitedBefore, base::Bind(
370 &DownloadTargetDeterminer::CheckVisitedReferrerBeforeDone,
371 weak_ptr_factory_.GetWeakPtr())));
372 return QUIT_DOLOOP;
373 }
374 }
375
376 // If the danger level doesn't depend on having visited the refererrer URL
377 // or if original profile doesn't have a HistoryService or the referrer url
378 // is invalid, then assume the referrer has not been visited before.
379 danger_type_ = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
380 }
381 return CONTINUE;
382 }
383
384 void DownloadTargetDeterminer::CheckVisitedReferrerBeforeDone(
385 bool visited_referrer_before) {
386 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
387 if (IsDangerousFile(
388 visited_referrer_before ? VISITED_REFERRER : NO_VISITS_TO_REFERRER))
389 danger_type_ = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
390 DoLoop();
391 }
392
393 DownloadTargetDeterminer::Result
394 DownloadTargetDeterminer::DoDetermineIntermediatePath() {
395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
396 DCHECK(!virtual_path_.empty());
397 DCHECK(!local_path_.empty());
398 DCHECK(intermediate_path_.empty());
399
400 next_state_ = STATE_NONE;
401
402 // Note that the intermediate filename is always uniquified (i.e. if a file by
403 // the same name exists, it is never overwritten). Therefore the code below
404 // does not attempt to find a name that doesn't conflict with an existing
405 // file.
406
407 // If the actual target of the download is a virtual path, then the local path
408 // is considered to point to a temporary path. A separate intermediate path is
409 // unnecessary since the local path already serves that purpose.
410 if (virtual_path_.BaseName() != local_path_.BaseName()) {
411 intermediate_path_ = local_path_;
412 return COMPLETE;
413 }
414
415 // If the download has a forced path and is safe, then just use the
416 // target path. In practice the temporary download file that was created prior
417 // to download filename determination is already named
418 // download_->GetForcedFilePath().
419 if (danger_type_ == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS &&
420 !download_->GetForcedFilePath().empty()) {
421 DCHECK_EQ(download_->GetForcedFilePath().value(), local_path_.value());
422 intermediate_path_ = local_path_;
423 return COMPLETE;
424 }
425
426 // Other safe downloads get a .crdownload suffix for their intermediate name.
427 if (danger_type_ == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) {
428 intermediate_path_ = download_util::GetCrDownloadPath(local_path_);
429 return COMPLETE;
430 }
431
432 // Dangerous downloads receive a random intermediate name that looks like:
433 // 'Unconfirmed <random>.crdownload'.
434 const base::FilePath::CharType kUnconfirmedFormatSuffix[] =
435 FILE_PATH_LITERAL(" %d.crdownload");
436 // Range of the <random> uniquifier.
437 const int kUnconfirmedUniquifierRange = 1000000;
438 #if defined(OS_WIN)
439 string16 unconfirmed_format =
440 l10n_util::GetStringUTF16(IDS_DOWNLOAD_UNCONFIRMED_PREFIX);
441 #else
442 std::string unconfirmed_format =
443 l10n_util::GetStringUTF8(IDS_DOWNLOAD_UNCONFIRMED_PREFIX);
444 #endif
445 unconfirmed_format.append(kUnconfirmedFormatSuffix);
446
447 base::FilePath::StringType file_name = base::StringPrintf(
448 unconfirmed_format.c_str(),
449 base::RandInt(0, kUnconfirmedUniquifierRange));
450 intermediate_path_ = local_path_.DirName().Append(file_name);
451 return COMPLETE;
452 }
453
454 void DownloadTargetDeterminer::ScheduleCallbackAndDeleteSelf() {
455 DCHECK(download_);
456 DVLOG(20) << "Scheduling callback. Virtual:" << virtual_path_.AsUTF8Unsafe()
457 << " Local:" << local_path_.AsUTF8Unsafe()
458 << " Intermediate:" << intermediate_path_.AsUTF8Unsafe()
459 << " Should prompt:" << should_prompt_
460 << " Danger type:" << danger_type_;
461 MessageLoop::current()->PostTask(
462 FROM_HERE,
463 base::Bind(completion_callback_,
464 local_path_,
465 (should_prompt_ ? DownloadItem::TARGET_DISPOSITION_PROMPT :
466 DownloadItem::TARGET_DISPOSITION_OVERWRITE),
467 danger_type_,
468 intermediate_path_));
469 completion_callback_.Reset();
470 delete this;
471 }
472
473 void DownloadTargetDeterminer::CancelOnFailureAndDeleteSelf() {
474 // Path substitution failed.
475 virtual_path_.clear();
476 local_path_.clear();
477 intermediate_path_.clear();
478 ScheduleCallbackAndDeleteSelf();
479 }
480
481 Profile* DownloadTargetDeterminer::GetProfile() {
482 DCHECK(download_->GetBrowserContext());
483 return Profile::FromBrowserContext(download_->GetBrowserContext());
484 }
485
486 bool DownloadTargetDeterminer::ShouldPromptForDownload(
487 const base::FilePath& filename) {
488 // If the download path is forced, don't prompt.
489 if (!download_->GetForcedFilePath().empty()) {
490 // 'Save As' downloads shouldn't have a forced path.
491 DCHECK_NE(DownloadItem::TARGET_DISPOSITION_PROMPT,
492 download_->GetTargetDisposition());
493 return false;
494 }
495
496 // Don't ask where to save if the download path is managed. Even if the user
497 // wanted to be prompted for "all" downloads, or if this was a 'Save As'
498 // download.
499 if (download_prefs_->IsDownloadPathManaged())
500 return false;
501
502 // Prompt if this is a 'Save As' download.
503 if (download_->GetTargetDisposition() ==
504 DownloadItem::TARGET_DISPOSITION_PROMPT)
505 return true;
506
507 // Check if the user has the "Always prompt for download location" preference
508 // set. If so we prompt for most downloads except for the following scenarios:
509 // 1) Extension installation. Note that we only care here about the case where
510 // an extension is installed, not when one is downloaded with "save as...".
511 // 2) Filetypes marked "always open." If the user just wants this file opened,
512 // don't bother asking where to keep it.
513 if (download_prefs_->PromptForDownload() &&
514 !download_crx_util::IsExtensionDownload(*download_) &&
515 !extensions::Extension::IsExtension(filename) &&
516 !download_prefs_->IsAutoOpenEnabledBasedOnExtension(filename))
517 return true;
518
519 // Otherwise, don't prompt. Note that the user might still be prompted if
520 // there are unresolved conflicts during path reservation (e.g. due to the
521 // target path being unwriteable or because there are too many conflicting
522 // files), or if an extension signals that the user be prompted on a filename
523 // conflict.
524 return false;
525 }
526
527 bool DownloadTargetDeterminer::IsDangerousFile(PriorVisitsToReferrer visits) {
528 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
529 const bool is_extension_download =
530 download_crx_util::IsExtensionDownload(*download_);
531
532 // User-initiated extension downloads from pref-whitelisted sources are not
533 // considered dangerous.
534 if (download_->HasUserGesture() &&
535 is_extension_download &&
536 download_crx_util::OffStoreInstallAllowedByPrefs(
537 GetProfile(), *download_)) {
538 return false;
539 }
540
541 // Extensions that are not from the gallery are considered dangerous.
542 // When off-store install is disabled we skip this, since in this case, we
543 // will not offer to install the extension.
544 if (extensions::FeatureSwitch::easy_off_store_install()->IsEnabled() &&
545 is_extension_download &&
546 !extensions::WebstoreInstaller::GetAssociatedApproval(*download_)) {
547 return true;
548 }
549
550 // Anything the user has marked auto-open is OK if it's user-initiated.
551 if (download_prefs_->IsAutoOpenEnabledBasedOnExtension(virtual_path_) &&
552 download_->HasUserGesture())
553 return false;
554
555 switch (download_util::GetFileDangerLevel(virtual_path_.BaseName())) {
556 case download_util::NotDangerous:
557 return false;
558
559 case download_util::AllowOnUserGesture:
560 // "Allow on user gesture" is OK when we have a user gesture and the
561 // hosting page has been visited before today.
562 if (download_->GetTransitionType() &
563 content::PAGE_TRANSITION_FROM_ADDRESS_BAR) {
564 return false;
565 }
566 return !download_->HasUserGesture() || visits == NO_VISITS_TO_REFERRER;
567
568 case download_util::Dangerous:
569 return true;
570 }
571 NOTREACHED();
572 return false;
573 }
574
575 void DownloadTargetDeterminer::OnDownloadDestroyed(
576 DownloadItem* download) {
577 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
578 DCHECK_EQ(download_, download);
579 CancelOnFailureAndDeleteSelf();
580 }
581
582 // static
583 void DownloadTargetDeterminer::Start(
584 content::DownloadItem* download,
585 DownloadPrefs* download_prefs,
586 const base::FilePath& last_selected_directory,
587 DownloadTargetDeterminerDelegate* delegate,
588 const content::DownloadTargetCallback& callback) {
589 // DownloadTargetDeterminer owns itself and will self destruct when the job is
590 // complete or the download item is destroyed. The callback is always invoked
591 // asynchronously.
592 new DownloadTargetDeterminer(download, download_prefs,
593 last_selected_directory, delegate, callback);
594 }
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