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

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: Address comments. Created 7 years, 8 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/drive_download_handler.h"
31 #include "chrome/browser/chromeos/drive/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 if (!download_->IsInProgress())
182 return COMPLETE;
183 return CONTINUE;
184 }
185
186 DownloadTargetDeterminer::Result
187 DownloadTargetDeterminer::DoNotifyExtensions() {
188 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
189 DCHECK(!virtual_path_.empty());
190
191 next_state_ = STATE_RESERVE_VIRTUAL_PATH;
192
193 // If the target path is forced or if we don't have an extensions event
194 // router, then proceed with the original path.
195 if (!download_->GetForcedFilePath().empty())
196 return CONTINUE;
197
198 delegate_->NotifyExtensions(download_, virtual_path_,
199 base::Bind(&DownloadTargetDeterminer::NotifyExtensionsDone,
200 weak_ptr_factory_.GetWeakPtr()));
201 return QUIT_DOLOOP;
202 }
203
204 void DownloadTargetDeterminer::NotifyExtensionsDone(
205 const base::FilePath& suggested_path,
206 DownloadPathReservationTracker::FilenameConflictAction conflict_action) {
207 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
208 DVLOG(20) << "Extension suggested path: " << suggested_path.AsUTF8Unsafe();
209
210 if (!suggested_path.empty()) {
211 // If an extension overrides the filename, then the target directory will be
212 // forced to download_prefs_->DownloadPath() since extensions cannot place
213 // downloaded files anywhere except there. This prevents subdirectories from
214 // accumulating: if an extension is allowed to say that a file should go in
215 // last_download_path/music/foo.mp3, then last_download_path will accumulate
216 // the subdirectory /music/ so that the next download may end up in
217 // Downloads/music/music/music/bar.mp3.
218 base::FilePath new_path(download_prefs_->DownloadPath().Append(
219 suggested_path).NormalizePathSeparators());
220 // Do not pass a mime type to GenerateSafeFileName so that it does not force
221 // the filename to have an extension if the (Chrome) extension does not
222 // suggest it.
223 net::GenerateSafeFileName(std::string(), false, &new_path);
224 virtual_path_ = new_path;
225 conflict_action_ = conflict_action;
226 }
227
228 DoLoop();
229 }
230
231 DownloadTargetDeterminer::Result
232 DownloadTargetDeterminer::DoReserveVirtualPath() {
233 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
234 DCHECK(!virtual_path_.empty());
235
236 next_state_ = STATE_PROMPT_USER_FOR_DOWNLOAD_PATH;
237
238 delegate_->ReserveVirtualPath(
239 download_, virtual_path_, conflict_action_,
240 base::Bind(&DownloadTargetDeterminer::ReserveVirtualPathDone,
241 weak_ptr_factory_.GetWeakPtr()));
242 return QUIT_DOLOOP;
243 }
244
245 void DownloadTargetDeterminer::ReserveVirtualPathDone(
246 const base::FilePath& path, bool verified) {
247 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
248 DVLOG(20) << "Reserved path: " << path.AsUTF8Unsafe()
249 << " Verified:" << verified;
250 should_prompt_ = (should_prompt_ || !verified);
251 if (verified)
252 virtual_path_ = path;
253 DoLoop();
254 }
255
256 DownloadTargetDeterminer::Result
257 DownloadTargetDeterminer::DoPromptUserForDownloadPath() {
258 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
259 DCHECK(!virtual_path_.empty());
260
261 next_state_ = STATE_DETERMINE_LOCAL_PATH;
262
263 if (should_prompt_) {
264 delegate_->PromptUserForDownloadPath(
265 download_,
266 virtual_path_,
267 base::Bind(&DownloadTargetDeterminer::PromptUserForDownloadPathDone,
268 weak_ptr_factory_.GetWeakPtr()));
269 return QUIT_DOLOOP;
270 }
271 return CONTINUE;
272 }
273
274 void DownloadTargetDeterminer::PromptUserForDownloadPathDone(
275 const base::FilePath& virtual_path) {
276 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
277 DVLOG(20) << "User selected path:" << virtual_path.AsUTF8Unsafe();
278 if (virtual_path.empty()) {
279 CancelOnFailureAndDeleteSelf();
280 return;
281 }
282 virtual_path_ = virtual_path;
283 DoLoop();
284 }
285
286 DownloadTargetDeterminer::Result
287 DownloadTargetDeterminer::DoDetermineLocalPath() {
288 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
289 DCHECK(!virtual_path_.empty());
290 DCHECK(local_path_.empty());
291
292 next_state_ = STATE_CHECK_DOWNLOAD_URL;
293
294 delegate_->DetermineLocalPath(
295 download_,
296 virtual_path_,
297 base::Bind(&DownloadTargetDeterminer::DetermineLocalPathDone,
298 weak_ptr_factory_.GetWeakPtr()));
299 return QUIT_DOLOOP;
300 }
301
302 void DownloadTargetDeterminer::DetermineLocalPathDone(
303 const base::FilePath& local_path) {
304 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
305 DVLOG(20) << "Local path: " << local_path.AsUTF8Unsafe();
306 if (local_path.empty()) {
307 // Path subsitution failed.
308 CancelOnFailureAndDeleteSelf();
309 return;
310 }
311 local_path_ = local_path;
312 DoLoop();
313 }
314
315 DownloadTargetDeterminer::Result
316 DownloadTargetDeterminer::DoCheckDownloadUrl() {
317 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
318 DCHECK(!virtual_path_.empty());
319 next_state_ = STATE_CHECK_VISITED_REFERRER_BEFORE;
320 delegate_->CheckDownloadUrl(
321 download_,
322 virtual_path_,
323 base::Bind(&DownloadTargetDeterminer::CheckDownloadUrlDone,
324 weak_ptr_factory_.GetWeakPtr()));
325 return QUIT_DOLOOP;
326 }
327
328 void DownloadTargetDeterminer::CheckDownloadUrlDone(
329 content::DownloadDangerType danger_type) {
330 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
331 DVLOG(20) << "URL Check Result:" << danger_type;
332 danger_type_ = danger_type;
333 DoLoop();
334 }
335
336 DownloadTargetDeterminer::Result
337 DownloadTargetDeterminer::DoCheckVisitedReferrerBefore() {
338 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
339
340 next_state_ = STATE_DETERMINE_INTERMEDIATE_PATH;
341
342 // Checking if there are prior visits to the referrer is only necessary if the
343 // danger level of the download depends on the file type. This excludes cases
344 // where the download has already been deemed dangerous, or where the user is
345 // going to be prompted or where this is a programmatic download.
346 if (danger_type_ != content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS ||
347 should_prompt_ ||
348 !download_->GetForcedFilePath().empty()) {
349 return CONTINUE;
350 }
351
352 // Assume that:
353 // IsDangerousFile(VISITED_REFERRER) => IsDangerousFile(NO_VISITS_...)
354 // I.e. having visited a referrer only lowers a file's danger level.
355 if (IsDangerousFile(NO_VISITS_TO_REFERRER)) {
356 // Only need to ping the history DB if the download would be considered safe
357 // if there are prior visits and is considered dangerous otherwise.
358 if (!IsDangerousFile(VISITED_REFERRER)) {
359 // HistoryServiceFactory redirects incognito profiles to on-record
360 // profiles. There's no history for on-record profiles in unit_tests.
361 HistoryService* history_service = HistoryServiceFactory::GetForProfile(
362 GetProfile(), Profile::EXPLICIT_ACCESS);
363
364 if (history_service && download_->GetReferrerUrl().is_valid()) {
365 history_service->GetVisibleVisitCountToHost(
366 download_->GetReferrerUrl(), &history_consumer_,
367 base::Bind(&VisitCountsToVisitedBefore, base::Bind(
368 &DownloadTargetDeterminer::CheckVisitedReferrerBeforeDone,
369 weak_ptr_factory_.GetWeakPtr())));
370 return QUIT_DOLOOP;
371 }
372 }
373
374 // If the danger level doesn't depend on having visited the refererrer URL
375 // or if original profile doesn't have a HistoryService or the referrer url
376 // is invalid, then assume the referrer has not been visited before.
377 danger_type_ = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
378 }
379 return CONTINUE;
380 }
381
382 void DownloadTargetDeterminer::CheckVisitedReferrerBeforeDone(
383 bool visited_referrer_before) {
384 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
385 if (IsDangerousFile(
386 visited_referrer_before ? VISITED_REFERRER : NO_VISITS_TO_REFERRER))
387 danger_type_ = content::DOWNLOAD_DANGER_TYPE_DANGEROUS_FILE;
388 DoLoop();
389 }
390
391 DownloadTargetDeterminer::Result
392 DownloadTargetDeterminer::DoDetermineIntermediatePath() {
393 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
394 DCHECK(!virtual_path_.empty());
395 DCHECK(!local_path_.empty());
396 DCHECK(intermediate_path_.empty());
397
398 next_state_ = STATE_NONE;
399
400 // Note that the intermediate filename is always uniquified (i.e. if a file by
401 // the same name exists, it is never overwritten). Therefore the code below
402 // does not attempt to find a name that doesn't conflict with an existing
403 // file.
404
405 // If the actual target of the download is a virtual path, then the local path
406 // is considered to point to a temporary path. A separate intermediate path is
407 // unnecessary since the local path already serves that purpose.
408 if (virtual_path_.BaseName() != local_path_.BaseName()) {
409 intermediate_path_ = local_path_;
410 return COMPLETE;
411 }
412
413 // If the download has a forced path and is safe, then just use the
414 // target path. In practice the temporary download file that was created prior
415 // to download filename determination is already named
416 // download_->GetForcedFilePath().
417 if (danger_type_ == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS &&
418 !download_->GetForcedFilePath().empty()) {
419 DCHECK_EQ(download_->GetForcedFilePath().value(), local_path_.value());
420 intermediate_path_ = local_path_;
421 return COMPLETE;
422 }
423
424 // Other safe downloads get a .crdownload suffix for their intermediate name.
425 if (danger_type_ == content::DOWNLOAD_DANGER_TYPE_NOT_DANGEROUS) {
426 intermediate_path_ = download_util::GetCrDownloadPath(local_path_);
427 return COMPLETE;
428 }
429
430 // Dangerous downloads receive a random intermediate name that looks like:
431 // 'Unconfirmed <random>.crdownload'.
432 const base::FilePath::CharType kUnconfirmedFormatSuffix[] =
433 FILE_PATH_LITERAL(" %d.crdownload");
434 // Range of the <random> uniquifier.
435 const int kUnconfirmedUniquifierRange = 1000000;
436 #if defined(OS_WIN)
437 string16 unconfirmed_format =
438 l10n_util::GetStringUTF16(IDS_DOWNLOAD_UNCONFIRMED_PREFIX);
439 #else
440 std::string unconfirmed_format =
441 l10n_util::GetStringUTF8(IDS_DOWNLOAD_UNCONFIRMED_PREFIX);
442 #endif
443 unconfirmed_format.append(kUnconfirmedFormatSuffix);
444
445 base::FilePath::StringType file_name = base::StringPrintf(
446 unconfirmed_format.c_str(),
447 base::RandInt(0, kUnconfirmedUniquifierRange));
448 intermediate_path_ = local_path_.DirName().Append(file_name);
449 return COMPLETE;
450 }
451
452 void DownloadTargetDeterminer::ScheduleCallbackAndDeleteSelf() {
453 DCHECK(download_);
454 DVLOG(20) << "Scheduling callback. Virtual:" << virtual_path_.AsUTF8Unsafe()
455 << " Local:" << local_path_.AsUTF8Unsafe()
456 << " Intermediate:" << intermediate_path_.AsUTF8Unsafe()
457 << " Should prompt:" << should_prompt_
458 << " Danger type:" << danger_type_;
459 MessageLoop::current()->PostTask(
460 FROM_HERE,
461 base::Bind(completion_callback_,
462 local_path_,
463 (should_prompt_ ? DownloadItem::TARGET_DISPOSITION_PROMPT :
464 DownloadItem::TARGET_DISPOSITION_OVERWRITE),
465 danger_type_,
466 intermediate_path_));
467 completion_callback_.Reset();
468 delete this;
469 }
470
471 void DownloadTargetDeterminer::CancelOnFailureAndDeleteSelf() {
472 // Path substitution failed.
473 virtual_path_.clear();
474 local_path_.clear();
475 intermediate_path_.clear();
476 ScheduleCallbackAndDeleteSelf();
477 }
478
479 Profile* DownloadTargetDeterminer::GetProfile() {
480 DCHECK(download_->GetBrowserContext());
481 return Profile::FromBrowserContext(download_->GetBrowserContext());
482 }
483
484 bool DownloadTargetDeterminer::ShouldPromptForDownload(
485 const base::FilePath& filename) {
486 // If the download path is forced, don't prompt.
487 if (!download_->GetForcedFilePath().empty()) {
488 // 'Save As' downloads shouldn't have a forced path.
489 DCHECK_NE(DownloadItem::TARGET_DISPOSITION_PROMPT,
490 download_->GetTargetDisposition());
491 return false;
492 }
493
494 // Don't ask where to save if the download path is managed. Even if the user
495 // wanted to be prompted for "all" downloads, or if this was a 'Save As'
496 // download.
497 if (download_prefs_->IsDownloadPathManaged())
498 return false;
499
500 // Prompt if this is a 'Save As' download.
501 if (download_->GetTargetDisposition() ==
502 DownloadItem::TARGET_DISPOSITION_PROMPT)
503 return true;
504
505 // Check if the user has the "Always prompt for download location" preference
506 // set. If so we prompt for most downloads except for the following scenarios:
507 // 1) Extension installation. Note that we only care here about the case where
508 // an extension is installed, not when one is downloaded with "save as...".
509 // 2) Filetypes marked "always open." If the user just wants this file opened,
510 // don't bother asking where to keep it.
511 if (download_prefs_->PromptForDownload() &&
512 !download_crx_util::IsExtensionDownload(*download_) &&
513 !extensions::Extension::IsExtension(filename) &&
514 !download_prefs_->IsAutoOpenEnabledBasedOnExtension(filename))
515 return true;
516
517 // Otherwise, don't prompt. Note that the user might still be prompted if
518 // there are unresolved conflicts during path reservation (e.g. due to the
519 // target path being unwriteable or because there are too many conflicting
520 // files), or if an extension signals that the user be prompted on a filename
521 // conflict.
522 return false;
523 }
524
525 bool DownloadTargetDeterminer::IsDangerousFile(PriorVisitsToReferrer visits) {
526 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
527 const bool is_extension_download =
528 download_crx_util::IsExtensionDownload(*download_);
529
530 // User-initiated extension downloads from pref-whitelisted sources are not
531 // considered dangerous.
532 if (download_->HasUserGesture() &&
533 is_extension_download &&
534 download_crx_util::OffStoreInstallAllowedByPrefs(
535 GetProfile(), *download_)) {
536 return false;
537 }
538
539 // Extensions that are not from the gallery are considered dangerous.
540 // When off-store install is disabled we skip this, since in this case, we
541 // will not offer to install the extension.
542 if (extensions::FeatureSwitch::easy_off_store_install()->IsEnabled() &&
543 is_extension_download &&
544 !extensions::WebstoreInstaller::GetAssociatedApproval(*download_)) {
545 return true;
546 }
547
548 // Anything the user has marked auto-open is OK if it's user-initiated.
549 if (download_prefs_->IsAutoOpenEnabledBasedOnExtension(virtual_path_) &&
550 download_->HasUserGesture())
551 return false;
552
553 switch (download_util::GetFileDangerLevel(virtual_path_.BaseName())) {
554 case download_util::NotDangerous:
555 return false;
556
557 case download_util::AllowOnUserGesture:
558 // "Allow on user gesture" is OK when we have a user gesture and the
559 // hosting page has been visited before today.
560 if (download_->GetTransitionType() &
561 content::PAGE_TRANSITION_FROM_ADDRESS_BAR) {
562 return false;
563 }
564 return !download_->HasUserGesture() || visits == NO_VISITS_TO_REFERRER;
565
566 case download_util::Dangerous:
567 return true;
568 }
569 NOTREACHED();
570 return false;
571 }
572
573 void DownloadTargetDeterminer::OnDownloadDestroyed(
574 DownloadItem* download) {
575 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
576 DCHECK_EQ(download_, download);
577 CancelOnFailureAndDeleteSelf();
578 }
579
580 // static
581 void DownloadTargetDeterminer::Start(
582 content::DownloadItem* download,
583 DownloadPrefs* download_prefs,
584 const base::FilePath& last_selected_directory,
585 DownloadTargetDeterminerDelegate* delegate,
586 const content::DownloadTargetCallback& callback) {
587 // DownloadTargetDeterminer owns itself and will self destruct when the job is
588 // complete or the download item is destroyed. The callback is always invoked
589 // asynchronously.
590 new DownloadTargetDeterminer(download, download_prefs,
591 last_selected_directory, delegate, callback);
592 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698