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

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: Destroy PluginService once we are done with our plugin tests. 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
52 } // namespace 59 } // namespace
53 60
61 DownloadTargetInfo::DownloadTargetInfo()
62 : is_filetype_handled_securely(false) {}
63
64 DownloadTargetInfo::~DownloadTargetInfo() {}
65
54 DownloadTargetDeterminerDelegate::~DownloadTargetDeterminerDelegate() { 66 DownloadTargetDeterminerDelegate::~DownloadTargetDeterminerDelegate() {
55 } 67 }
56 68
57 DownloadTargetDeterminer::DownloadTargetDeterminer( 69 DownloadTargetDeterminer::DownloadTargetDeterminer(
58 DownloadItem* download, 70 DownloadItem* download,
59 const base::FilePath& initial_virtual_path, 71 const base::FilePath& initial_virtual_path,
60 DownloadPrefs* download_prefs, 72 DownloadPrefs* download_prefs,
61 DownloadTargetDeterminerDelegate* delegate, 73 DownloadTargetDeterminerDelegate* delegate,
62 const content::DownloadTargetCallback& callback) 74 const CompletionCallback& callback)
63 : next_state_(STATE_GENERATE_TARGET_PATH), 75 : next_state_(STATE_GENERATE_TARGET_PATH),
64 should_prompt_(false), 76 should_prompt_(false),
65 should_notify_extensions_(false), 77 should_notify_extensions_(false),
66 create_target_directory_(false), 78 create_target_directory_(false),
67 conflict_action_(DownloadPathReservationTracker::OVERWRITE), 79 conflict_action_(DownloadPathReservationTracker::OVERWRITE),
68 danger_type_(download->GetDangerType()), 80 danger_type_(download->GetDangerType()),
69 virtual_path_(initial_virtual_path), 81 virtual_path_(initial_virtual_path),
82 is_filetype_handled_securely_(false),
70 download_(download), 83 download_(download),
71 is_resumption_(download_->GetLastReason() != 84 is_resumption_(download_->GetLastReason() !=
72 content::DOWNLOAD_INTERRUPT_REASON_NONE && 85 content::DOWNLOAD_INTERRUPT_REASON_NONE &&
73 !initial_virtual_path.empty()), 86 !initial_virtual_path.empty()),
74 download_prefs_(download_prefs), 87 download_prefs_(download_prefs),
75 delegate_(delegate), 88 delegate_(delegate),
76 completion_callback_(callback), 89 completion_callback_(callback),
77 weak_ptr_factory_(this) { 90 weak_ptr_factory_(this) {
78 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 91 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
79 DCHECK(download_); 92 DCHECK(download_);
(...skipping 25 matching lines...) Expand all
105 break; 118 break;
106 case STATE_RESERVE_VIRTUAL_PATH: 119 case STATE_RESERVE_VIRTUAL_PATH:
107 result = DoReserveVirtualPath(); 120 result = DoReserveVirtualPath();
108 break; 121 break;
109 case STATE_PROMPT_USER_FOR_DOWNLOAD_PATH: 122 case STATE_PROMPT_USER_FOR_DOWNLOAD_PATH:
110 result = DoPromptUserForDownloadPath(); 123 result = DoPromptUserForDownloadPath();
111 break; 124 break;
112 case STATE_DETERMINE_LOCAL_PATH: 125 case STATE_DETERMINE_LOCAL_PATH:
113 result = DoDetermineLocalPath(); 126 result = DoDetermineLocalPath();
114 break; 127 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;
115 case STATE_CHECK_DOWNLOAD_URL: 134 case STATE_CHECK_DOWNLOAD_URL:
116 result = DoCheckDownloadUrl(); 135 result = DoCheckDownloadUrl();
117 break; 136 break;
118 case STATE_DETERMINE_INTERMEDIATE_PATH: 137 case STATE_DETERMINE_INTERMEDIATE_PATH:
119 result = DoDetermineIntermediatePath(); 138 result = DoDetermineIntermediatePath();
120 break; 139 break;
121 case STATE_CHECK_VISITED_REFERRER_BEFORE: 140 case STATE_CHECK_VISITED_REFERRER_BEFORE:
122 result = DoCheckVisitedReferrerBefore(); 141 result = DoCheckVisitedReferrerBefore();
123 break; 142 break;
124 case STATE_NONE: 143 case STATE_NONE:
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 download_prefs_->SetSaveFilePath(virtual_path_.DirName()); 317 download_prefs_->SetSaveFilePath(virtual_path_.DirName());
299 DoLoop(); 318 DoLoop();
300 } 319 }
301 320
302 DownloadTargetDeterminer::Result 321 DownloadTargetDeterminer::Result
303 DownloadTargetDeterminer::DoDetermineLocalPath() { 322 DownloadTargetDeterminer::DoDetermineLocalPath() {
304 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 323 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
305 DCHECK(!virtual_path_.empty()); 324 DCHECK(!virtual_path_.empty());
306 DCHECK(local_path_.empty()); 325 DCHECK(local_path_.empty());
307 326
308 next_state_ = STATE_CHECK_DOWNLOAD_URL; 327 next_state_ = STATE_DETERMINE_MIME_TYPE;
309 328
310 delegate_->DetermineLocalPath( 329 delegate_->DetermineLocalPath(
311 download_, 330 download_,
312 virtual_path_, 331 virtual_path_,
313 base::Bind(&DownloadTargetDeterminer::DetermineLocalPathDone, 332 base::Bind(&DownloadTargetDeterminer::DetermineLocalPathDone,
314 weak_ptr_factory_.GetWeakPtr())); 333 weak_ptr_factory_.GetWeakPtr()));
315 return QUIT_DOLOOP; 334 return QUIT_DOLOOP;
316 } 335 }
317 336
318 void DownloadTargetDeterminer::DetermineLocalPathDone( 337 void DownloadTargetDeterminer::DetermineLocalPathDone(
319 const base::FilePath& local_path) { 338 const base::FilePath& local_path) {
320 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 339 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
321 DVLOG(20) << "Local path: " << local_path.AsUTF8Unsafe(); 340 DVLOG(20) << "Local path: " << local_path.AsUTF8Unsafe();
322 if (local_path.empty()) { 341 if (local_path.empty()) {
323 // Path subsitution failed. 342 // Path subsitution failed.
324 CancelOnFailureAndDeleteSelf(); 343 CancelOnFailureAndDeleteSelf();
325 return; 344 return;
326 } 345 }
327 local_path_ = local_path; 346 local_path_ = local_path;
328 DoLoop(); 347 DoLoop();
329 } 348 }
330 349
331 DownloadTargetDeterminer::Result 350 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
332 DownloadTargetDeterminer::DoCheckDownloadUrl() { 471 DownloadTargetDeterminer::DoCheckDownloadUrl() {
333 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 472 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
334 DCHECK(!virtual_path_.empty()); 473 DCHECK(!virtual_path_.empty());
335 next_state_ = STATE_CHECK_VISITED_REFERRER_BEFORE; 474 next_state_ = STATE_CHECK_VISITED_REFERRER_BEFORE;
336 delegate_->CheckDownloadUrl( 475 delegate_->CheckDownloadUrl(
337 download_, 476 download_,
338 virtual_path_, 477 virtual_path_,
339 base::Bind(&DownloadTargetDeterminer::CheckDownloadUrlDone, 478 base::Bind(&DownloadTargetDeterminer::CheckDownloadUrlDone,
340 weak_ptr_factory_.GetWeakPtr())); 479 weak_ptr_factory_.GetWeakPtr()));
341 return QUIT_DOLOOP; 480 return QUIT_DOLOOP;
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after
477 return COMPLETE; 616 return COMPLETE;
478 } 617 }
479 618
480 void DownloadTargetDeterminer::ScheduleCallbackAndDeleteSelf() { 619 void DownloadTargetDeterminer::ScheduleCallbackAndDeleteSelf() {
481 DCHECK(download_); 620 DCHECK(download_);
482 DVLOG(20) << "Scheduling callback. Virtual:" << virtual_path_.AsUTF8Unsafe() 621 DVLOG(20) << "Scheduling callback. Virtual:" << virtual_path_.AsUTF8Unsafe()
483 << " Local:" << local_path_.AsUTF8Unsafe() 622 << " Local:" << local_path_.AsUTF8Unsafe()
484 << " Intermediate:" << intermediate_path_.AsUTF8Unsafe() 623 << " Intermediate:" << intermediate_path_.AsUTF8Unsafe()
485 << " Should prompt:" << should_prompt_ 624 << " Should prompt:" << should_prompt_
486 << " Danger type:" << danger_type_; 625 << " 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
487 base::MessageLoop::current()->PostTask( 638 base::MessageLoop::current()->PostTask(
488 FROM_HERE, 639 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(); 640 completion_callback_.Reset();
497 delete this; 641 delete this;
498 } 642 }
499 643
500 void DownloadTargetDeterminer::CancelOnFailureAndDeleteSelf() { 644 void DownloadTargetDeterminer::CancelOnFailureAndDeleteSelf() {
501 // Path substitution failed. 645 // Path substitution failed.
502 virtual_path_.clear(); 646 virtual_path_.clear();
503 local_path_.clear(); 647 local_path_.clear();
504 intermediate_path_.clear(); 648 intermediate_path_.clear();
505 ScheduleCallbackAndDeleteSelf(); 649 ScheduleCallbackAndDeleteSelf();
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after
624 } 768 }
625 769
626 void DownloadTargetDeterminer::OnDownloadDestroyed( 770 void DownloadTargetDeterminer::OnDownloadDestroyed(
627 DownloadItem* download) { 771 DownloadItem* download) {
628 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 772 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
629 DCHECK_EQ(download_, download); 773 DCHECK_EQ(download_, download);
630 CancelOnFailureAndDeleteSelf(); 774 CancelOnFailureAndDeleteSelf();
631 } 775 }
632 776
633 // static 777 // static
634 void DownloadTargetDeterminer::Start( 778 void DownloadTargetDeterminer::Start(content::DownloadItem* download,
635 content::DownloadItem* download, 779 const base::FilePath& initial_virtual_path,
636 const base::FilePath& initial_virtual_path, 780 DownloadPrefs* download_prefs,
637 DownloadPrefs* download_prefs, 781 DownloadTargetDeterminerDelegate* delegate,
638 DownloadTargetDeterminerDelegate* delegate, 782 const CompletionCallback& callback) {
639 const content::DownloadTargetCallback& callback) {
640 // DownloadTargetDeterminer owns itself and will self destruct when the job is 783 // DownloadTargetDeterminer owns itself and will self destruct when the job is
641 // complete or the download item is destroyed. The callback is always invoked 784 // complete or the download item is destroyed. The callback is always invoked
642 // asynchronously. 785 // asynchronously.
643 new DownloadTargetDeterminer(download, initial_virtual_path, download_prefs, 786 new DownloadTargetDeterminer(download, initial_virtual_path, download_prefs,
644 delegate, callback); 787 delegate, callback);
645 } 788 }
646 789
647 // static 790 // static
648 base::FilePath DownloadTargetDeterminer::GetCrDownloadPath( 791 base::FilePath DownloadTargetDeterminer::GetCrDownloadPath(
649 const base::FilePath& suggested_path) { 792 const base::FilePath& suggested_path) {
650 return base::FilePath(suggested_path.value() + kCrdownloadSuffix); 793 return base::FilePath(suggested_path.value() + kCrdownloadSuffix);
651 } 794 }
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