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

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

Issue 61623006: Revert 233460 "Prefer opening PDF downloads in the browser." (Closed) Base URL: svn://svn.chromium.org/chrome/
Patch Set: Created 7 years, 1 month 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/strings/stringprintf.h" 9 #include "base/strings/stringprintf.h"
10 #include "base/time/time.h" 10 #include "base/time/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/extensions/webstore_installer.h" 15 #include "chrome/browser/extensions/webstore_installer.h"
16 #include "chrome/browser/history/history_service.h" 16 #include "chrome/browser/history/history_service.h"
17 #include "chrome/browser/history/history_service_factory.h" 17 #include "chrome/browser/history/history_service_factory.h"
18 #include "chrome/browser/profiles/profile.h" 18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/common/extensions/feature_switch.h" 19 #include "chrome/common/extensions/feature_switch.h"
20 #include "chrome/common/pref_names.h" 20 #include "chrome/common/pref_names.h"
21 #include "content/public/browser/browser_context.h" 21 #include "content/public/browser/browser_context.h"
22 #include "content/public/browser/browser_thread.h" 22 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/download_interrupt_reasons.h" 23 #include "content/public/browser/download_interrupt_reasons.h"
24 #include "extensions/common/constants.h" 24 #include "extensions/common/constants.h"
25 #include "grit/generated_resources.h" 25 #include "grit/generated_resources.h"
26 #include "net/base/mime_util.h"
27 #include "net/base/net_util.h" 26 #include "net/base/net_util.h"
28 #include "ui/base/l10n/l10n_util.h" 27 #include "ui/base/l10n/l10n_util.h"
29 28
30 #if defined(ENABLE_PLUGINS)
31 #include "chrome/browser/plugins/plugin_prefs.h"
32 #include "content/public/browser/plugin_service.h"
33 #include "content/public/common/webplugininfo.h"
34 #endif
35
36 using content::BrowserThread; 29 using content::BrowserThread;
37 using content::DownloadItem; 30 using content::DownloadItem;
38 31
39 namespace { 32 namespace {
40 33
41 const base::FilePath::CharType kCrdownloadSuffix[] = 34 const base::FilePath::CharType kCrdownloadSuffix[] =
42 FILE_PATH_LITERAL(".crdownload"); 35 FILE_PATH_LITERAL(".crdownload");
43 36
44 // Condenses the results from HistoryService::GetVisibleVisitCountToHost() to a 37 // Condenses the results from HistoryService::GetVisibleVisitCountToHost() to a
45 // single bool. A host is considered visited before if prior visible visits were 38 // single bool. A host is considered visited before if prior visible visits were
46 // found in history and the first such visit was earlier than the most recent 39 // found in history and the first such visit was earlier than the most recent
47 // midnight. 40 // midnight.
48 void VisitCountsToVisitedBefore( 41 void VisitCountsToVisitedBefore(
49 const base::Callback<void(bool)>& callback, 42 const base::Callback<void(bool)>& callback,
50 HistoryService::Handle unused_handle, 43 HistoryService::Handle unused_handle,
51 bool found_visits, 44 bool found_visits,
52 int count, 45 int count,
53 base::Time first_visit) { 46 base::Time first_visit) {
54 callback.Run( 47 callback.Run(
55 found_visits && count > 0 && 48 found_visits && count > 0 &&
56 (first_visit.LocalMidnight() < base::Time::Now().LocalMidnight())); 49 (first_visit.LocalMidnight() < base::Time::Now().LocalMidnight()));
57 } 50 }
58 51
59 } // namespace 52 } // namespace
60 53
61 DownloadTargetInfo::DownloadTargetInfo()
62 : is_filetype_handled_securely(false) {}
63
64 DownloadTargetInfo::~DownloadTargetInfo() {}
65
66 DownloadTargetDeterminerDelegate::~DownloadTargetDeterminerDelegate() { 54 DownloadTargetDeterminerDelegate::~DownloadTargetDeterminerDelegate() {
67 } 55 }
68 56
69 DownloadTargetDeterminer::DownloadTargetDeterminer( 57 DownloadTargetDeterminer::DownloadTargetDeterminer(
70 DownloadItem* download, 58 DownloadItem* download,
71 const base::FilePath& initial_virtual_path, 59 const base::FilePath& initial_virtual_path,
72 DownloadPrefs* download_prefs, 60 DownloadPrefs* download_prefs,
73 DownloadTargetDeterminerDelegate* delegate, 61 DownloadTargetDeterminerDelegate* delegate,
74 const CompletionCallback& callback) 62 const content::DownloadTargetCallback& callback)
75 : next_state_(STATE_GENERATE_TARGET_PATH), 63 : next_state_(STATE_GENERATE_TARGET_PATH),
76 should_prompt_(false), 64 should_prompt_(false),
77 should_notify_extensions_(false), 65 should_notify_extensions_(false),
78 create_target_directory_(false), 66 create_target_directory_(false),
79 conflict_action_(DownloadPathReservationTracker::OVERWRITE), 67 conflict_action_(DownloadPathReservationTracker::OVERWRITE),
80 danger_type_(download->GetDangerType()), 68 danger_type_(download->GetDangerType()),
81 virtual_path_(initial_virtual_path), 69 virtual_path_(initial_virtual_path),
82 is_filetype_handled_securely_(false),
83 download_(download), 70 download_(download),
84 is_resumption_(download_->GetLastReason() != 71 is_resumption_(download_->GetLastReason() !=
85 content::DOWNLOAD_INTERRUPT_REASON_NONE && 72 content::DOWNLOAD_INTERRUPT_REASON_NONE &&
86 !initial_virtual_path.empty()), 73 !initial_virtual_path.empty()),
87 download_prefs_(download_prefs), 74 download_prefs_(download_prefs),
88 delegate_(delegate), 75 delegate_(delegate),
89 completion_callback_(callback), 76 completion_callback_(callback),
90 weak_ptr_factory_(this) { 77 weak_ptr_factory_(this) {
91 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 78 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
92 DCHECK(download_); 79 DCHECK(download_);
(...skipping 25 matching lines...) Expand all
118 break; 105 break;
119 case STATE_RESERVE_VIRTUAL_PATH: 106 case STATE_RESERVE_VIRTUAL_PATH:
120 result = DoReserveVirtualPath(); 107 result = DoReserveVirtualPath();
121 break; 108 break;
122 case STATE_PROMPT_USER_FOR_DOWNLOAD_PATH: 109 case STATE_PROMPT_USER_FOR_DOWNLOAD_PATH:
123 result = DoPromptUserForDownloadPath(); 110 result = DoPromptUserForDownloadPath();
124 break; 111 break;
125 case STATE_DETERMINE_LOCAL_PATH: 112 case STATE_DETERMINE_LOCAL_PATH:
126 result = DoDetermineLocalPath(); 113 result = DoDetermineLocalPath();
127 break; 114 break;
128 case STATE_DETERMINE_MIME_TYPE:
129 result = DoDetermineMimeType();
130 break;
131 case STATE_DETERMINE_IF_HANDLED_BY_BROWSER:
132 result = DoDetermineIfHandledByBrowser();
133 break;
134 case STATE_CHECK_DOWNLOAD_URL: 115 case STATE_CHECK_DOWNLOAD_URL:
135 result = DoCheckDownloadUrl(); 116 result = DoCheckDownloadUrl();
136 break; 117 break;
137 case STATE_DETERMINE_INTERMEDIATE_PATH: 118 case STATE_DETERMINE_INTERMEDIATE_PATH:
138 result = DoDetermineIntermediatePath(); 119 result = DoDetermineIntermediatePath();
139 break; 120 break;
140 case STATE_CHECK_VISITED_REFERRER_BEFORE: 121 case STATE_CHECK_VISITED_REFERRER_BEFORE:
141 result = DoCheckVisitedReferrerBefore(); 122 result = DoCheckVisitedReferrerBefore();
142 break; 123 break;
143 case STATE_NONE: 124 case STATE_NONE:
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
317 download_prefs_->SetSaveFilePath(virtual_path_.DirName()); 298 download_prefs_->SetSaveFilePath(virtual_path_.DirName());
318 DoLoop(); 299 DoLoop();
319 } 300 }
320 301
321 DownloadTargetDeterminer::Result 302 DownloadTargetDeterminer::Result
322 DownloadTargetDeterminer::DoDetermineLocalPath() { 303 DownloadTargetDeterminer::DoDetermineLocalPath() {
323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 304 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
324 DCHECK(!virtual_path_.empty()); 305 DCHECK(!virtual_path_.empty());
325 DCHECK(local_path_.empty()); 306 DCHECK(local_path_.empty());
326 307
327 next_state_ = STATE_DETERMINE_MIME_TYPE; 308 next_state_ = STATE_CHECK_DOWNLOAD_URL;
328 309
329 delegate_->DetermineLocalPath( 310 delegate_->DetermineLocalPath(
330 download_, 311 download_,
331 virtual_path_, 312 virtual_path_,
332 base::Bind(&DownloadTargetDeterminer::DetermineLocalPathDone, 313 base::Bind(&DownloadTargetDeterminer::DetermineLocalPathDone,
333 weak_ptr_factory_.GetWeakPtr())); 314 weak_ptr_factory_.GetWeakPtr()));
334 return QUIT_DOLOOP; 315 return QUIT_DOLOOP;
335 } 316 }
336 317
337 void DownloadTargetDeterminer::DetermineLocalPathDone( 318 void DownloadTargetDeterminer::DetermineLocalPathDone(
338 const base::FilePath& local_path) { 319 const base::FilePath& local_path) {
339 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 320 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
340 DVLOG(20) << "Local path: " << local_path.AsUTF8Unsafe(); 321 DVLOG(20) << "Local path: " << local_path.AsUTF8Unsafe();
341 if (local_path.empty()) { 322 if (local_path.empty()) {
342 // Path subsitution failed. 323 // Path subsitution failed.
343 CancelOnFailureAndDeleteSelf(); 324 CancelOnFailureAndDeleteSelf();
344 return; 325 return;
345 } 326 }
346 local_path_ = local_path; 327 local_path_ = local_path;
347 DoLoop(); 328 DoLoop();
348 } 329 }
349 330
350 DownloadTargetDeterminer::Result 331 DownloadTargetDeterminer::Result
351 DownloadTargetDeterminer::DoDetermineMimeType() {
352 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
353 DCHECK(!virtual_path_.empty());
354 DCHECK(!local_path_.empty());
355 DCHECK(mime_type_.empty());
356
357 next_state_ = STATE_DETERMINE_IF_HANDLED_BY_BROWSER;
358
359 if (virtual_path_ == local_path_) {
360 delegate_->GetFileMimeType(
361 local_path_,
362 base::Bind(&DownloadTargetDeterminer::DetermineMimeTypeDone,
363 weak_ptr_factory_.GetWeakPtr()));
364 return QUIT_DOLOOP;
365 }
366 return CONTINUE;
367 }
368
369 void DownloadTargetDeterminer::DetermineMimeTypeDone(
370 const std::string& mime_type) {
371 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
372 DVLOG(20) << "MIME type: " << mime_type;
373 mime_type_ = mime_type;
374 DoLoop();
375 }
376
377 #if defined(ENABLE_PLUGINS)
378 // The code below is used by DoDetermineIfHandledByBrowser to determine if the
379 // file type is handled by a sandboxed plugin.
380 namespace {
381
382 typedef std::vector<content::WebPluginInfo> PluginVector;
383
384 // Returns true if there is a plugin in |plugins| that is sandboxed and enabled
385 // for |profile|.
386 bool IsSafePluginAvailableForProfile(scoped_ptr<PluginVector> plugins,
387 Profile* profile) {
388 using content::WebPluginInfo;
389 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
390
391 if (plugins->size() == 0)
392 return false;
393
394 scoped_refptr<PluginPrefs> plugin_prefs = PluginPrefs::GetForProfile(profile);
395 if (!plugin_prefs)
396 return false;
397
398 for (PluginVector::iterator plugin = plugins->begin();
399 plugin != plugins->end(); ++plugin) {
400 if (plugin_prefs->IsPluginEnabled(*plugin) &&
401 (plugin->type == WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS ||
402 plugin->type == WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS))
403 return true;
404 }
405 return false;
406 }
407
408 // Returns a callback that determines if a sandboxed plugin is available to
409 // handle |mime_type| for a specific profile. The returned callback must be
410 // invoked on the UI thread, while this function should be called on the IO
411 // thread.
412 base::Callback<bool(Profile*)> GetSafePluginChecker(
413 const GURL& url,
414 const std::string& mime_type) {
415 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
416 DCHECK(!mime_type.empty());
417
418 scoped_ptr<PluginVector> plugins(new PluginVector);
419 content::PluginService* plugin_service =
420 content::PluginService::GetInstance();
421 if (plugin_service)
422 plugin_service->GetPluginInfoArray(
423 url, mime_type, false, plugins.get(), NULL);
424 return base::Bind(&IsSafePluginAvailableForProfile, base::Passed(&plugins));
425 }
426
427 } // namespace
428 #endif // ENABLE_PLUGINS
429
430 DownloadTargetDeterminer::Result
431 DownloadTargetDeterminer::DoDetermineIfHandledByBrowser() {
432 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
433 DCHECK(!virtual_path_.empty());
434 DCHECK(!local_path_.empty());
435 DCHECK(!is_filetype_handled_securely_);
436
437 next_state_ = STATE_CHECK_DOWNLOAD_URL;
438
439 if (mime_type_.empty())
440 return CONTINUE;
441
442 if (net::IsSupportedMimeType(mime_type_)) {
443 is_filetype_handled_securely_ = true;
444 return CONTINUE;
445 }
446
447 #if defined(ENABLE_PLUGINS)
448 BrowserThread::PostTaskAndReplyWithResult(
449 BrowserThread::IO,
450 FROM_HERE,
451 base::Bind(&GetSafePluginChecker,
452 net::FilePathToFileURL(local_path_), mime_type_),
453 base::Bind(&DownloadTargetDeterminer::DetermineIfHandledByBrowserDone,
454 weak_ptr_factory_.GetWeakPtr()));
455 return QUIT_DOLOOP;
456 #else
457 return CONTINUE;
458 #endif
459 }
460
461 void DownloadTargetDeterminer::DetermineIfHandledByBrowserDone(
462 const base::Callback<bool(Profile*)>& callback) {
463 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
464 is_filetype_handled_securely_ = callback.Run(GetProfile());
465 DVLOG(20) << "Is file type handled securely: "
466 << is_filetype_handled_securely_;
467 DoLoop();
468 }
469
470 DownloadTargetDeterminer::Result
471 DownloadTargetDeterminer::DoCheckDownloadUrl() { 332 DownloadTargetDeterminer::DoCheckDownloadUrl() {
472 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 333 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
473 DCHECK(!virtual_path_.empty()); 334 DCHECK(!virtual_path_.empty());
474 next_state_ = STATE_CHECK_VISITED_REFERRER_BEFORE; 335 next_state_ = STATE_CHECK_VISITED_REFERRER_BEFORE;
475 delegate_->CheckDownloadUrl( 336 delegate_->CheckDownloadUrl(
476 download_, 337 download_,
477 virtual_path_, 338 virtual_path_,
478 base::Bind(&DownloadTargetDeterminer::CheckDownloadUrlDone, 339 base::Bind(&DownloadTargetDeterminer::CheckDownloadUrlDone,
479 weak_ptr_factory_.GetWeakPtr())); 340 weak_ptr_factory_.GetWeakPtr()));
480 return QUIT_DOLOOP; 341 return QUIT_DOLOOP;
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
616 return COMPLETE; 477 return COMPLETE;
617 } 478 }
618 479
619 void DownloadTargetDeterminer::ScheduleCallbackAndDeleteSelf() { 480 void DownloadTargetDeterminer::ScheduleCallbackAndDeleteSelf() {
620 DCHECK(download_); 481 DCHECK(download_);
621 DVLOG(20) << "Scheduling callback. Virtual:" << virtual_path_.AsUTF8Unsafe() 482 DVLOG(20) << "Scheduling callback. Virtual:" << virtual_path_.AsUTF8Unsafe()
622 << " Local:" << local_path_.AsUTF8Unsafe() 483 << " Local:" << local_path_.AsUTF8Unsafe()
623 << " Intermediate:" << intermediate_path_.AsUTF8Unsafe() 484 << " Intermediate:" << intermediate_path_.AsUTF8Unsafe()
624 << " Should prompt:" << should_prompt_ 485 << " Should prompt:" << should_prompt_
625 << " Danger type:" << danger_type_; 486 << " Danger type:" << danger_type_;
626 scoped_ptr<DownloadTargetInfo> target_info(new DownloadTargetInfo);
627
628 target_info->target_path = local_path_;
629 target_info->target_disposition =
630 (HasPromptedForPath() || should_prompt_
631 ? DownloadItem::TARGET_DISPOSITION_PROMPT
632 : DownloadItem::TARGET_DISPOSITION_OVERWRITE);
633 target_info->danger_type = danger_type_;
634 target_info->intermediate_path = intermediate_path_;
635 target_info->mime_type = mime_type_;
636 target_info->is_filetype_handled_securely = is_filetype_handled_securely_;
637
638 base::MessageLoop::current()->PostTask( 487 base::MessageLoop::current()->PostTask(
639 FROM_HERE, base::Bind(completion_callback_, base::Passed(&target_info))); 488 FROM_HERE,
489 base::Bind(completion_callback_,
490 local_path_,
491 (HasPromptedForPath() || should_prompt_
492 ? DownloadItem::TARGET_DISPOSITION_PROMPT
493 : DownloadItem::TARGET_DISPOSITION_OVERWRITE),
494 danger_type_,
495 intermediate_path_));
640 completion_callback_.Reset(); 496 completion_callback_.Reset();
641 delete this; 497 delete this;
642 } 498 }
643 499
644 void DownloadTargetDeterminer::CancelOnFailureAndDeleteSelf() { 500 void DownloadTargetDeterminer::CancelOnFailureAndDeleteSelf() {
645 // Path substitution failed. 501 // Path substitution failed.
646 virtual_path_.clear(); 502 virtual_path_.clear();
647 local_path_.clear(); 503 local_path_.clear();
648 intermediate_path_.clear(); 504 intermediate_path_.clear();
649 ScheduleCallbackAndDeleteSelf(); 505 ScheduleCallbackAndDeleteSelf();
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
768 } 624 }
769 625
770 void DownloadTargetDeterminer::OnDownloadDestroyed( 626 void DownloadTargetDeterminer::OnDownloadDestroyed(
771 DownloadItem* download) { 627 DownloadItem* download) {
772 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 628 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
773 DCHECK_EQ(download_, download); 629 DCHECK_EQ(download_, download);
774 CancelOnFailureAndDeleteSelf(); 630 CancelOnFailureAndDeleteSelf();
775 } 631 }
776 632
777 // static 633 // static
778 void DownloadTargetDeterminer::Start(content::DownloadItem* download, 634 void DownloadTargetDeterminer::Start(
779 const base::FilePath& initial_virtual_path, 635 content::DownloadItem* download,
780 DownloadPrefs* download_prefs, 636 const base::FilePath& initial_virtual_path,
781 DownloadTargetDeterminerDelegate* delegate, 637 DownloadPrefs* download_prefs,
782 const CompletionCallback& callback) { 638 DownloadTargetDeterminerDelegate* delegate,
639 const content::DownloadTargetCallback& callback) {
783 // DownloadTargetDeterminer owns itself and will self destruct when the job is 640 // DownloadTargetDeterminer owns itself and will self destruct when the job is
784 // complete or the download item is destroyed. The callback is always invoked 641 // complete or the download item is destroyed. The callback is always invoked
785 // asynchronously. 642 // asynchronously.
786 new DownloadTargetDeterminer(download, initial_virtual_path, download_prefs, 643 new DownloadTargetDeterminer(download, initial_virtual_path, download_prefs,
787 delegate, callback); 644 delegate, callback);
788 } 645 }
789 646
790 // static 647 // static
791 base::FilePath DownloadTargetDeterminer::GetCrDownloadPath( 648 base::FilePath DownloadTargetDeterminer::GetCrDownloadPath(
792 const base::FilePath& suggested_path) { 649 const base::FilePath& suggested_path) {
793 return base::FilePath(suggested_path.value() + kCrdownloadSuffix); 650 return base::FilePath(suggested_path.value() + kCrdownloadSuffix);
794 } 651 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698