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

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

Issue 55063002: Prefer opening PDF downloads in the browser. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Tests + rebase 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"
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
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
29 using content::BrowserThread; 36 using content::BrowserThread;
30 using content::DownloadItem; 37 using content::DownloadItem;
31 38
32 namespace { 39 namespace {
33 40
34 const base::FilePath::CharType kCrdownloadSuffix[] = 41 const base::FilePath::CharType kCrdownloadSuffix[] =
35 FILE_PATH_LITERAL(".crdownload"); 42 FILE_PATH_LITERAL(".crdownload");
36 43
37 // Condenses the results from HistoryService::GetVisibleVisitCountToHost() to a 44 // Condenses the results from HistoryService::GetVisibleVisitCountToHost() to a
38 // single bool. A host is considered visited before if prior visible visits were 45 // single bool. A host is considered visited before if prior visible visits were
39 // found in history and the first such visit was earlier than the most recent 46 // found in history and the first such visit was earlier than the most recent
40 // midnight. 47 // midnight.
41 void VisitCountsToVisitedBefore( 48 void VisitCountsToVisitedBefore(
42 const base::Callback<void(bool)>& callback, 49 const base::Callback<void(bool)>& callback,
43 HistoryService::Handle unused_handle, 50 HistoryService::Handle unused_handle,
44 bool found_visits, 51 bool found_visits,
45 int count, 52 int count,
46 base::Time first_visit) { 53 base::Time first_visit) {
47 callback.Run( 54 callback.Run(
48 found_visits && count > 0 && 55 found_visits && count > 0 &&
49 (first_visit.LocalMidnight() < base::Time::Now().LocalMidnight())); 56 (first_visit.LocalMidnight() < base::Time::Now().LocalMidnight()));
50 } 57 }
51 58
59 #if defined(ENABLE_PLUGINS)
60 typedef std::vector<content::WebPluginInfo> PluginVector;
61
62 bool IsSafePluginAvailableForProfile(scoped_ptr<PluginVector> plugins,
63 Profile* profile) {
64 using content::WebPluginInfo;
65
66 if (plugins->size() == 0)
67 return false;
68
69 scoped_refptr<PluginPrefs> plugin_prefs = PluginPrefs::GetForProfile(profile);
70 if (!plugin_prefs)
71 return false;
72
73 for (PluginVector::iterator plugin = plugins->begin();
74 plugin != plugins->end(); ++plugin) {
75 if (plugin_prefs->IsPluginEnabled(*plugin) &&
76 (plugin->type == WebPluginInfo::PLUGIN_TYPE_PEPPER_IN_PROCESS ||
77 plugin->type == WebPluginInfo::PLUGIN_TYPE_PEPPER_OUT_OF_PROCESS))
78 return true;
79 }
80 return false;
81 }
82
83 base::Callback<bool(Profile*)> GetPluginListVerifier(
84 const std::string& mime_type) {
85 DCHECK(!mime_type.empty());
86
87 scoped_ptr<PluginVector> plugins(new PluginVector);
88 content::PluginService* plugin_service =
89 content::PluginService::GetInstance();
90 if (plugin_service)
91 plugin_service->GetPluginInfoArray(
92 GURL(), mime_type, false, plugins.get(), NULL);
93 return base::Bind(&IsSafePluginAvailableForProfile, base::Passed(&plugins));
94 }
95 #endif // ENABLE_PLUGINS
Randy Smith (Not in Mondays) 2013/11/04 19:53:26 I'm a bit torn about this code organization. On t
asanka 2013/11/04 21:20:11 I tried that, but it still seemed a bit confusing.
96
52 } // namespace 97 } // namespace
53 98
99 DownloadTargetInfo::DownloadTargetInfo()
100 : is_filetype_handled_securely(false) {}
101
102 DownloadTargetInfo::~DownloadTargetInfo() {}
103
54 DownloadTargetDeterminerDelegate::~DownloadTargetDeterminerDelegate() { 104 DownloadTargetDeterminerDelegate::~DownloadTargetDeterminerDelegate() {
55 } 105 }
56 106
57 DownloadTargetDeterminer::DownloadTargetDeterminer( 107 DownloadTargetDeterminer::DownloadTargetDeterminer(
58 DownloadItem* download, 108 DownloadItem* download,
59 const base::FilePath& initial_virtual_path, 109 const base::FilePath& initial_virtual_path,
60 DownloadPrefs* download_prefs, 110 DownloadPrefs* download_prefs,
61 DownloadTargetDeterminerDelegate* delegate, 111 DownloadTargetDeterminerDelegate* delegate,
62 const content::DownloadTargetCallback& callback) 112 const CompletionCallback& callback)
63 : next_state_(STATE_GENERATE_TARGET_PATH), 113 : next_state_(STATE_GENERATE_TARGET_PATH),
64 should_prompt_(false), 114 should_prompt_(false),
65 should_notify_extensions_(false), 115 should_notify_extensions_(false),
66 create_target_directory_(false), 116 create_target_directory_(false),
67 conflict_action_(DownloadPathReservationTracker::OVERWRITE), 117 conflict_action_(DownloadPathReservationTracker::OVERWRITE),
68 danger_type_(download->GetDangerType()), 118 danger_type_(download->GetDangerType()),
69 virtual_path_(initial_virtual_path), 119 virtual_path_(initial_virtual_path),
120 is_filetype_handled_securely_(false),
70 download_(download), 121 download_(download),
71 is_resumption_(download_->GetLastReason() != 122 is_resumption_(download_->GetLastReason() !=
72 content::DOWNLOAD_INTERRUPT_REASON_NONE && 123 content::DOWNLOAD_INTERRUPT_REASON_NONE &&
73 !initial_virtual_path.empty()), 124 !initial_virtual_path.empty()),
74 download_prefs_(download_prefs), 125 download_prefs_(download_prefs),
75 delegate_(delegate), 126 delegate_(delegate),
76 completion_callback_(callback), 127 completion_callback_(callback),
77 weak_ptr_factory_(this) { 128 weak_ptr_factory_(this) {
78 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
79 DCHECK(download_); 130 DCHECK(download_);
(...skipping 25 matching lines...) Expand all
105 break; 156 break;
106 case STATE_RESERVE_VIRTUAL_PATH: 157 case STATE_RESERVE_VIRTUAL_PATH:
107 result = DoReserveVirtualPath(); 158 result = DoReserveVirtualPath();
108 break; 159 break;
109 case STATE_PROMPT_USER_FOR_DOWNLOAD_PATH: 160 case STATE_PROMPT_USER_FOR_DOWNLOAD_PATH:
110 result = DoPromptUserForDownloadPath(); 161 result = DoPromptUserForDownloadPath();
111 break; 162 break;
112 case STATE_DETERMINE_LOCAL_PATH: 163 case STATE_DETERMINE_LOCAL_PATH:
113 result = DoDetermineLocalPath(); 164 result = DoDetermineLocalPath();
114 break; 165 break;
166 case STATE_DETERMINE_MIME_TYPE:
167 result = DoDetermineMimeType();
168 break;
169 case STATE_DETERMINE_IF_HANDLED_BY_BROWSER:
170 result = DoDetermineIfHandledByBrowser();
171 break;
115 case STATE_CHECK_DOWNLOAD_URL: 172 case STATE_CHECK_DOWNLOAD_URL:
116 result = DoCheckDownloadUrl(); 173 result = DoCheckDownloadUrl();
117 break; 174 break;
118 case STATE_DETERMINE_INTERMEDIATE_PATH: 175 case STATE_DETERMINE_INTERMEDIATE_PATH:
119 result = DoDetermineIntermediatePath(); 176 result = DoDetermineIntermediatePath();
120 break; 177 break;
121 case STATE_CHECK_VISITED_REFERRER_BEFORE: 178 case STATE_CHECK_VISITED_REFERRER_BEFORE:
122 result = DoCheckVisitedReferrerBefore(); 179 result = DoCheckVisitedReferrerBefore();
123 break; 180 break;
124 case STATE_NONE: 181 case STATE_NONE:
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 download_prefs_->SetSaveFilePath(virtual_path_.DirName()); 355 download_prefs_->SetSaveFilePath(virtual_path_.DirName());
299 DoLoop(); 356 DoLoop();
300 } 357 }
301 358
302 DownloadTargetDeterminer::Result 359 DownloadTargetDeterminer::Result
303 DownloadTargetDeterminer::DoDetermineLocalPath() { 360 DownloadTargetDeterminer::DoDetermineLocalPath() {
304 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 361 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
305 DCHECK(!virtual_path_.empty()); 362 DCHECK(!virtual_path_.empty());
306 DCHECK(local_path_.empty()); 363 DCHECK(local_path_.empty());
307 364
308 next_state_ = STATE_CHECK_DOWNLOAD_URL; 365 next_state_ = STATE_DETERMINE_MIME_TYPE;
309 366
310 delegate_->DetermineLocalPath( 367 delegate_->DetermineLocalPath(
311 download_, 368 download_,
312 virtual_path_, 369 virtual_path_,
313 base::Bind(&DownloadTargetDeterminer::DetermineLocalPathDone, 370 base::Bind(&DownloadTargetDeterminer::DetermineLocalPathDone,
314 weak_ptr_factory_.GetWeakPtr())); 371 weak_ptr_factory_.GetWeakPtr()));
315 return QUIT_DOLOOP; 372 return QUIT_DOLOOP;
316 } 373 }
317 374
318 void DownloadTargetDeterminer::DetermineLocalPathDone( 375 void DownloadTargetDeterminer::DetermineLocalPathDone(
319 const base::FilePath& local_path) { 376 const base::FilePath& local_path) {
320 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 377 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
321 DVLOG(20) << "Local path: " << local_path.AsUTF8Unsafe(); 378 DVLOG(20) << "Local path: " << local_path.AsUTF8Unsafe();
322 if (local_path.empty()) { 379 if (local_path.empty()) {
323 // Path subsitution failed. 380 // Path subsitution failed.
324 CancelOnFailureAndDeleteSelf(); 381 CancelOnFailureAndDeleteSelf();
325 return; 382 return;
326 } 383 }
327 local_path_ = local_path; 384 local_path_ = local_path;
328 DoLoop(); 385 DoLoop();
329 } 386 }
330 387
331 DownloadTargetDeterminer::Result 388 DownloadTargetDeterminer::Result
389 DownloadTargetDeterminer::DoDetermineMimeType() {
390 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
391 DCHECK(!virtual_path_.empty());
392 DCHECK(!local_path_.empty());
393 DCHECK(mime_type_.empty());
394
395 next_state_ = STATE_DETERMINE_IF_HANDLED_BY_BROWSER;
396
397 if (virtual_path_ == local_path_) {
398 delegate_->GetFileMimeType(
399 local_path_,
400 base::Bind(&DownloadTargetDeterminer::DetermineMimeTypeDone,
401 weak_ptr_factory_.GetWeakPtr()));
402 return QUIT_DOLOOP;
403 }
404 return CONTINUE;
405 }
406
407 void DownloadTargetDeterminer::DetermineMimeTypeDone(
408 const std::string& mime_type) {
409 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
410 DVLOG(20) << "MIME type: " << mime_type;
411 mime_type_ = mime_type;
412 DoLoop();
413 }
414
415 DownloadTargetDeterminer::Result
416 DownloadTargetDeterminer::DoDetermineIfHandledByBrowser() {
417 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
418 DCHECK(!virtual_path_.empty());
419 DCHECK(!local_path_.empty());
420 DCHECK(!is_filetype_handled_securely_);
421
422 next_state_ = STATE_CHECK_DOWNLOAD_URL;
423
424 if (mime_type_.empty())
425 return CONTINUE;
426
427 if (net::IsSupportedMimeType(mime_type_)) {
428 is_filetype_handled_securely_ = true;
429 return CONTINUE;
430 }
431
432 BrowserThread::PostTaskAndReplyWithResult(
433 BrowserThread::IO,
434 FROM_HERE,
435 base::Bind(&GetPluginListVerifier, mime_type_),
436 base::Bind(&DownloadTargetDeterminer::DetermineIfHandledByBrowserDone,
437 weak_ptr_factory_.GetWeakPtr()));
438 return QUIT_DOLOOP;
439 }
440
441 void DownloadTargetDeterminer::DetermineIfHandledByBrowserDone(
442 const base::Callback<bool(Profile*)>& callback) {
443 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
444 is_filetype_handled_securely_ = callback.Run(GetProfile());
445 DVLOG(20) << "Is file type handled securely: "
446 << is_filetype_handled_securely_;
447 DoLoop();
448 }
449
450 DownloadTargetDeterminer::Result
332 DownloadTargetDeterminer::DoCheckDownloadUrl() { 451 DownloadTargetDeterminer::DoCheckDownloadUrl() {
333 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 452 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
334 DCHECK(!virtual_path_.empty()); 453 DCHECK(!virtual_path_.empty());
335 next_state_ = STATE_CHECK_VISITED_REFERRER_BEFORE; 454 next_state_ = STATE_CHECK_VISITED_REFERRER_BEFORE;
336 delegate_->CheckDownloadUrl( 455 delegate_->CheckDownloadUrl(
337 download_, 456 download_,
338 virtual_path_, 457 virtual_path_,
339 base::Bind(&DownloadTargetDeterminer::CheckDownloadUrlDone, 458 base::Bind(&DownloadTargetDeterminer::CheckDownloadUrlDone,
340 weak_ptr_factory_.GetWeakPtr())); 459 weak_ptr_factory_.GetWeakPtr()));
341 return QUIT_DOLOOP; 460 return QUIT_DOLOOP;
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 return COMPLETE; 596 return COMPLETE;
478 } 597 }
479 598
480 void DownloadTargetDeterminer::ScheduleCallbackAndDeleteSelf() { 599 void DownloadTargetDeterminer::ScheduleCallbackAndDeleteSelf() {
481 DCHECK(download_); 600 DCHECK(download_);
482 DVLOG(20) << "Scheduling callback. Virtual:" << virtual_path_.AsUTF8Unsafe() 601 DVLOG(20) << "Scheduling callback. Virtual:" << virtual_path_.AsUTF8Unsafe()
483 << " Local:" << local_path_.AsUTF8Unsafe() 602 << " Local:" << local_path_.AsUTF8Unsafe()
484 << " Intermediate:" << intermediate_path_.AsUTF8Unsafe() 603 << " Intermediate:" << intermediate_path_.AsUTF8Unsafe()
485 << " Should prompt:" << should_prompt_ 604 << " Should prompt:" << should_prompt_
486 << " Danger type:" << danger_type_; 605 << " Danger type:" << danger_type_;
606 scoped_ptr<DownloadTargetInfo> target_info(new DownloadTargetInfo);
607
608 target_info->target_path = local_path_;
609 target_info->target_disposition =
610 (HasPromptedForPath() || should_prompt_
611 ? DownloadItem::TARGET_DISPOSITION_PROMPT
612 : DownloadItem::TARGET_DISPOSITION_OVERWRITE);
613 target_info->danger_type = danger_type_;
614 target_info->intermediate_path = intermediate_path_;
615 target_info->mime_type = mime_type_;
616 target_info->is_filetype_handled_securely = is_filetype_handled_securely_;
Randy Smith (Not in Mondays) 2013/11/04 19:53:26 Long-term thought: One of the goals I had for the
asanka 2013/11/04 21:20:11 Yup. We can look at it when we revisit the handlin
617
487 base::MessageLoop::current()->PostTask( 618 base::MessageLoop::current()->PostTask(
488 FROM_HERE, 619 FROM_HERE, base::Bind(completion_callback_, base::Passed(&target_info)));
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_));
496 completion_callback_.Reset(); 620 completion_callback_.Reset();
497 delete this; 621 delete this;
498 } 622 }
499 623
500 void DownloadTargetDeterminer::CancelOnFailureAndDeleteSelf() { 624 void DownloadTargetDeterminer::CancelOnFailureAndDeleteSelf() {
501 // Path substitution failed. 625 // Path substitution failed.
502 virtual_path_.clear(); 626 virtual_path_.clear();
503 local_path_.clear(); 627 local_path_.clear();
504 intermediate_path_.clear(); 628 intermediate_path_.clear();
505 ScheduleCallbackAndDeleteSelf(); 629 ScheduleCallbackAndDeleteSelf();
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 } 748 }
625 749
626 void DownloadTargetDeterminer::OnDownloadDestroyed( 750 void DownloadTargetDeterminer::OnDownloadDestroyed(
627 DownloadItem* download) { 751 DownloadItem* download) {
628 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 752 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
629 DCHECK_EQ(download_, download); 753 DCHECK_EQ(download_, download);
630 CancelOnFailureAndDeleteSelf(); 754 CancelOnFailureAndDeleteSelf();
631 } 755 }
632 756
633 // static 757 // static
634 void DownloadTargetDeterminer::Start( 758 void DownloadTargetDeterminer::Start(content::DownloadItem* download,
635 content::DownloadItem* download, 759 const base::FilePath& initial_virtual_path,
636 const base::FilePath& initial_virtual_path, 760 DownloadPrefs* download_prefs,
637 DownloadPrefs* download_prefs, 761 DownloadTargetDeterminerDelegate* delegate,
638 DownloadTargetDeterminerDelegate* delegate, 762 const CompletionCallback& callback) {
639 const content::DownloadTargetCallback& callback) {
640 // DownloadTargetDeterminer owns itself and will self destruct when the job is 763 // DownloadTargetDeterminer owns itself and will self destruct when the job is
641 // complete or the download item is destroyed. The callback is always invoked 764 // complete or the download item is destroyed. The callback is always invoked
642 // asynchronously. 765 // asynchronously.
643 new DownloadTargetDeterminer(download, initial_virtual_path, download_prefs, 766 new DownloadTargetDeterminer(download, initial_virtual_path, download_prefs,
644 delegate, callback); 767 delegate, callback);
645 } 768 }
646 769
647 // static 770 // static
648 base::FilePath DownloadTargetDeterminer::GetCrDownloadPath( 771 base::FilePath DownloadTargetDeterminer::GetCrDownloadPath(
649 const base::FilePath& suggested_path) { 772 const base::FilePath& suggested_path) {
650 return base::FilePath(suggested_path.value() + kCrdownloadSuffix); 773 return base::FilePath(suggested_path.value() + kCrdownloadSuffix);
651 } 774 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698