diff options
author | thestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-15 23:39:05 +0000 |
---|---|---|
committer | thestig@chromium.org <thestig@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2014-07-15 23:39:05 +0000 |
commit | f486f3abe8c53042eb8c0c7dae7abdfaeab5d593 (patch) | |
tree | ecb26541f0146a74f1dd8d3e2a0c35179d5aac37 | |
parent | 0652727b28e1692766a6848821bc5859d93d3cf5 (diff) | |
download | chromium_src-f486f3abe8c53042eb8c0c7dae7abdfaeab5d593.zip chromium_src-f486f3abe8c53042eb8c0c7dae7abdfaeab5d593.tar.gz chromium_src-f486f3abe8c53042eb8c0c7dae7abdfaeab5d593.tar.bz2 |
Merge 281172 "Windows: Add an "Open in Adobe Reader" menu item f..."
> Windows: Add an "Open in Adobe Reader" menu item for PDF files in the download shelf.
>
> BUG=370746
>
> Review URL: https://codereview.chromium.org/324593004
TBR=thestig@chromium.org
Review URL: https://codereview.chromium.org/393033007
git-svn-id: svn://svn.chromium.org/chrome/branches/2062/src@283274 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/download/chrome_download_manager_delegate.cc | 55 | ||||
-rw-r--r-- | chrome/browser/download/chrome_download_manager_delegate.h | 3 | ||||
-rw-r--r-- | chrome/browser/download/download_prefs.cc | 45 | ||||
-rw-r--r-- | chrome/browser/download/download_prefs.h | 13 | ||||
-rw-r--r-- | chrome/browser/download/download_shelf_context_menu.cc | 84 | ||||
-rw-r--r-- | chrome/browser/download/download_shelf_context_menu.h | 12 | ||||
-rw-r--r-- | chrome/browser/download/download_target_determiner.cc | 66 | ||||
-rw-r--r-- | chrome/browser/download/download_target_determiner.h | 24 | ||||
-rw-r--r-- | chrome/browser/ui/pdf/pdf_unsupported_feature.cc | 144 | ||||
-rw-r--r-- | chrome/chrome_browser_ui.gypi | 2 | ||||
-rw-r--r-- | chrome/common/pref_names.cc | 6 | ||||
-rw-r--r-- | chrome/common/pref_names.h | 3 |
12 files changed, 320 insertions, 137 deletions
diff --git a/chrome/browser/download/chrome_download_manager_delegate.cc b/chrome/browser/download/chrome_download_manager_delegate.cc index 2a8d6c6..8e81539 100644 --- a/chrome/browser/download/chrome_download_manager_delegate.cc +++ b/chrome/browser/download/chrome_download_manager_delegate.cc @@ -184,29 +184,6 @@ std::string GetMimeType(const base::FilePath& path) { return mime_type; } -bool IsOpenInBrowserPreferreredForFile(const base::FilePath& path) { - // On Android, always prefer opening with an external app. On ChromeOS, there - // are no external apps so just allow all opens to be handled by the "System." -#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && defined(ENABLE_PLUGINS) - // TODO(asanka): Consider other file types and MIME types. - // http://crbug.com/323561 - if (path.MatchesExtension(FILE_PATH_LITERAL(".pdf")) || - path.MatchesExtension(FILE_PATH_LITERAL(".htm")) || - path.MatchesExtension(FILE_PATH_LITERAL(".html")) || - path.MatchesExtension(FILE_PATH_LITERAL(".shtm")) || - path.MatchesExtension(FILE_PATH_LITERAL(".shtml")) || - path.MatchesExtension(FILE_PATH_LITERAL(".svg")) || - path.MatchesExtension(FILE_PATH_LITERAL(".xht")) || - path.MatchesExtension(FILE_PATH_LITERAL(".xhtm")) || - path.MatchesExtension(FILE_PATH_LITERAL(".xhtml")) || - path.MatchesExtension(FILE_PATH_LITERAL(".xsl")) || - path.MatchesExtension(FILE_PATH_LITERAL(".xslt"))) { - return true; - } -#endif - return false; -} - } // namespace ChromeDownloadManagerDelegate::ChromeDownloadManagerDelegate(Profile* profile) @@ -722,3 +699,35 @@ void ChromeDownloadManagerDelegate::OnDownloadTargetDetermined( target_info->danger_type, target_info->intermediate_path); } + +bool ChromeDownloadManagerDelegate::IsOpenInBrowserPreferreredForFile( + const base::FilePath& path) { + // On Windows, PDFs should open in Acrobat Reader if the user chooses. +#if defined(OS_WIN) + if (path.MatchesExtension(FILE_PATH_LITERAL(".pdf")) && + DownloadTargetDeterminer::IsAdobeReaderUpToDate()) { + return !download_prefs_->ShouldOpenPdfInAdobeReader(); + } +#endif + + // On Android, always prefer opening with an external app. On ChromeOS, there + // are no external apps so just allow all opens to be handled by the "System." +#if !defined(OS_ANDROID) && !defined(OS_CHROMEOS) && defined(ENABLE_PLUGINS) + // TODO(asanka): Consider other file types and MIME types. + // http://crbug.com/323561 + if (path.MatchesExtension(FILE_PATH_LITERAL(".pdf")) || + path.MatchesExtension(FILE_PATH_LITERAL(".htm")) || + path.MatchesExtension(FILE_PATH_LITERAL(".html")) || + path.MatchesExtension(FILE_PATH_LITERAL(".shtm")) || + path.MatchesExtension(FILE_PATH_LITERAL(".shtml")) || + path.MatchesExtension(FILE_PATH_LITERAL(".svg")) || + path.MatchesExtension(FILE_PATH_LITERAL(".xht")) || + path.MatchesExtension(FILE_PATH_LITERAL(".xhtm")) || + path.MatchesExtension(FILE_PATH_LITERAL(".xhtml")) || + path.MatchesExtension(FILE_PATH_LITERAL(".xsl")) || + path.MatchesExtension(FILE_PATH_LITERAL(".xslt"))) { + return true; + } +#endif + return false; +} diff --git a/chrome/browser/download/chrome_download_manager_delegate.h b/chrome/browser/download/chrome_download_manager_delegate.h index 7cf2c45..ff89300 100644 --- a/chrome/browser/download/chrome_download_manager_delegate.h +++ b/chrome/browser/download/chrome_download_manager_delegate.h @@ -170,6 +170,9 @@ class ChromeDownloadManagerDelegate const content::DownloadTargetCallback& callback, scoped_ptr<DownloadTargetInfo> target_info); + // Returns true if |path| should open in the browser. + bool IsOpenInBrowserPreferreredForFile(const base::FilePath& path); + Profile* profile_; uint32 next_download_id_; IdCallbackVector id_callbacks_; diff --git a/chrome/browser/download/download_prefs.cc b/chrome/browser/download/download_prefs.cc index 750e11b..99abc2c 100644 --- a/chrome/browser/download/download_prefs.cc +++ b/chrome/browser/download/download_prefs.cc @@ -22,6 +22,7 @@ #include "chrome/browser/download/download_extensions.h" #include "chrome/browser/download/download_service.h" #include "chrome/browser/download/download_service_factory.h" +#include "chrome/browser/download/download_target_determiner.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/profiles/profile_manager.h" #include "chrome/common/chrome_paths.h" @@ -37,6 +38,10 @@ #include "chrome/browser/chromeos/file_manager/path_util.h" #endif +#if defined(OS_WIN) +#include "chrome/browser/ui/pdf/adobe_reader_info_win.h" +#endif + using content::BrowserContext; using content::BrowserThread; using content::DownloadManager; @@ -91,7 +96,7 @@ class DefaultDownloadDirectory { DISALLOW_COPY_AND_ASSIGN(DefaultDownloadDirectory); }; -static base::LazyInstance<DefaultDownloadDirectory> +base::LazyInstance<DefaultDownloadDirectory> g_default_download_directory = LAZY_INSTANCE_INITIALIZER; } // namespace @@ -126,6 +131,11 @@ DownloadPrefs::DownloadPrefs(Profile* profile) : profile_(profile) { GetDefaultDownloadDirectoryForProfile())); #endif // defined(OS_CHROMEOS) +#if defined(OS_WIN) + should_open_pdf_in_adobe_reader_ = + prefs->GetBoolean(prefs::kOpenPdfDownloadInAdobeReader); +#endif + // If the download path is dangerous we forcefully reset it. But if we do // so we set a flag to make sure we only do it once, to avoid fighting // the user if he really wants it on an unsafe place such as the desktop. @@ -194,6 +204,12 @@ void DownloadPrefs::RegisterProfilePrefs( prefs::kSaveFileDefaultDirectory, default_download_path, user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); +#if defined(OS_WIN) + registry->RegisterBooleanPref( + prefs::kOpenPdfDownloadInAdobeReader, + false, + user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); +#endif } base::FilePath DownloadPrefs::GetDefaultDownloadDirectoryForProfile() const { @@ -268,6 +284,10 @@ bool DownloadPrefs::IsDownloadPathManaged() const { } bool DownloadPrefs::IsAutoOpenUsed() const { +#if defined(OS_WIN) + if (ShouldOpenPdfInAdobeReader()) + return true; +#endif return !auto_open_.empty(); } @@ -278,6 +298,12 @@ bool DownloadPrefs::IsAutoOpenEnabledBasedOnExtension( return false; DCHECK(extension[0] == base::FilePath::kExtensionSeparator); extension.erase(0, 1); +#if defined(OS_WIN) + if (extension == FILE_PATH_LITERAL("pdf") && + DownloadTargetDeterminer::IsAdobeReaderUpToDate() && + ShouldOpenPdfInAdobeReader()) + return true; +#endif return auto_open_.find(extension) != auto_open_.end(); } @@ -305,7 +331,24 @@ void DownloadPrefs::DisableAutoOpenBasedOnExtension( SaveAutoOpenState(); } +#if defined(OS_WIN) +void DownloadPrefs::SetShouldOpenPdfInAdobeReader(bool should_open) { + if (should_open_pdf_in_adobe_reader_ == should_open) + return; + should_open_pdf_in_adobe_reader_ = should_open; + profile_->GetPrefs()->SetBoolean(prefs::kOpenPdfDownloadInAdobeReader, + should_open); +} + +bool DownloadPrefs::ShouldOpenPdfInAdobeReader() const { + return should_open_pdf_in_adobe_reader_; +} +#endif + void DownloadPrefs::ResetAutoOpen() { +#if defined(OS_WIN) + SetShouldOpenPdfInAdobeReader(false); +#endif auto_open_.clear(); SaveAutoOpenState(); } diff --git a/chrome/browser/download/download_prefs.h b/chrome/browser/download/download_prefs.h index eca19d3..8d3db57 100644 --- a/chrome/browser/download/download_prefs.h +++ b/chrome/browser/download/download_prefs.h @@ -73,6 +73,15 @@ class DownloadPrefs { // Disables auto-open based on file extension. void DisableAutoOpenBasedOnExtension(const base::FilePath& file_name); +#if defined(OS_WIN) + // Store the user preference to disk. If |should_open| is true, also disable + // the built-in PDF plugin. If |should_open| is false, enable the PDF plugin. + void SetShouldOpenPdfInAdobeReader(bool should_open); + + // Return whether the user prefers to open PDF downloads in Adobe Reader. + bool ShouldOpenPdfInAdobeReader() const; +#endif + void ResetAutoOpen(); private: @@ -94,6 +103,10 @@ class DownloadPrefs { AutoOpenCompareFunctor> AutoOpenSet; AutoOpenSet auto_open_; +#if defined(OS_WIN) + bool should_open_pdf_in_adobe_reader_; +#endif + DISALLOW_COPY_AND_ASSIGN(DownloadPrefs); }; diff --git a/chrome/browser/download/download_shelf_context_menu.cc b/chrome/browser/download/download_shelf_context_menu.cc index b7f0858..55704c9 100644 --- a/chrome/browser/download/download_shelf_context_menu.cc +++ b/chrome/browser/download/download_shelf_context_menu.cc @@ -9,6 +9,7 @@ #include "chrome/browser/download/download_crx_util.h" #include "chrome/browser/download/download_item_model.h" #include "chrome/browser/download/download_prefs.h" +#include "chrome/browser/download/download_target_determiner.h" #include "chrome/browser/safe_browsing/download_protection_service.h" #include "chrome/browser/safe_browsing/safe_browsing_service.h" #include "chrome/common/url_constants.h" @@ -20,15 +21,18 @@ #include "grit/generated_resources.h" #include "ui/base/l10n/l10n_util.h" +#if defined(OS_WIN) +#include "chrome/browser/ui/pdf/adobe_reader_info_win.h" +#endif + using content::DownloadItem; -using extensions::Extension; namespace { // Returns true if downloads resumption is enabled. bool IsDownloadResumptionEnabled() { - const CommandLine& command_line = *CommandLine::ForCurrentProcess(); - return command_line.HasSwitch(switches::kEnableDownloadResumption); + return base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableDownloadResumption); } } // namespace @@ -44,6 +48,14 @@ DownloadShelfContextMenu::DownloadShelfContextMenu( navigator_(navigator) { DCHECK(download_item_); download_item_->AddObserver(this); + +#if defined(OS_WIN) + is_pdf_reader_up_to_date_ = false; + if (IsDownloadPdf() && IsAdobeReaderDefaultPDFViewer()) { + is_pdf_reader_up_to_date_ = + DownloadTargetDeterminer::IsAdobeReaderUpToDate(); + } +#endif // defined(OS_WIN) } ui::SimpleMenuModel* DownloadShelfContextMenu::GetMenuModel() { @@ -97,6 +109,7 @@ bool DownloadShelfContextMenu::IsCommandIdEnabled(int command_id) const { case LEARN_MORE_INTERRUPTED: return true; } + NOTREACHED(); return false; } @@ -109,6 +122,13 @@ bool DownloadShelfContextMenu::IsCommandIdChecked(int command_id) const { return download_item_->GetOpenWhenComplete() || download_crx_util::IsExtensionDownload(*download_item_); case ALWAYS_OPEN_TYPE: +#if defined(OS_WIN) + if (CanOpenPdfInReader()) { + DownloadPrefs* prefs = DownloadPrefs::FromBrowserContext( + download_item_->GetBrowserContext()); + return prefs->ShouldOpenPdfInAdobeReader(); + } +#endif return download_item_->ShouldOpenFileBasedOnExtension(); case TOGGLE_PAUSE: return download_item_->IsPaused(); @@ -116,6 +136,16 @@ bool DownloadShelfContextMenu::IsCommandIdChecked(int command_id) const { return false; } +bool DownloadShelfContextMenu::IsCommandIdVisible(int command_id) const { + if (!download_item_) + return false; + + if (command_id == PLATFORM_OPEN) + return (DownloadItemModel(download_item_).ShouldPreferOpeningInBrowser()); + + return true; +} + void DownloadShelfContextMenu::ExecuteCommand(int command_id, int event_flags) { if (!download_item_) return; @@ -128,13 +158,22 @@ void DownloadShelfContextMenu::ExecuteCommand(int command_id, int event_flags) { download_item_->OpenDownload(); break; case ALWAYS_OPEN_TYPE: { + bool is_checked = IsCommandIdChecked(ALWAYS_OPEN_TYPE); DownloadPrefs* prefs = DownloadPrefs::FromBrowserContext( download_item_->GetBrowserContext()); +#if defined(OS_WIN) + if (CanOpenPdfInReader()) { + prefs->SetShouldOpenPdfInAdobeReader(!is_checked); + DownloadItemModel(download_item_).SetShouldPreferOpeningInBrowser( + is_checked); + break; + } +#endif base::FilePath path = download_item_->GetTargetFilePath(); - if (!IsCommandIdChecked(ALWAYS_OPEN_TYPE)) - prefs->EnableAutoOpenBasedOnExtension(path); - else + if (is_checked) prefs->DisableAutoOpenBasedOnExtension(path); + else + prefs->EnableAutoOpenBasedOnExtension(path); break; } case PLATFORM_OPEN: @@ -203,7 +242,7 @@ base::string16 DownloadShelfContextMenu::GetLabelForCommandId( return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_OPEN_WHEN_COMPLETE); return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_OPEN); case ALWAYS_OPEN_TYPE: - return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_ALWAYS_OPEN_TYPE); + return l10n_util::GetStringUTF16(GetAlwaysOpenStringId()); case PLATFORM_OPEN: return l10n_util::GetStringUTF16(IDS_DOWNLOAD_MENU_PLATFORM_OPEN); case CANCEL: @@ -250,7 +289,7 @@ ui::SimpleMenuModel* DownloadShelfContextMenu::GetInProgressMenuModel() { in_progress_download_menu_model_->AddCheckItemWithStringId( OPEN_WHEN_COMPLETE, IDS_DOWNLOAD_MENU_OPEN_WHEN_COMPLETE); in_progress_download_menu_model_->AddCheckItemWithStringId( - ALWAYS_OPEN_TYPE, IDS_DOWNLOAD_MENU_ALWAYS_OPEN_TYPE); + ALWAYS_OPEN_TYPE, GetAlwaysOpenStringId()); in_progress_download_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR); in_progress_download_menu_model_->AddItemWithStringId( TOGGLE_PAUSE, IDS_DOWNLOAD_MENU_PAUSE_ITEM); @@ -272,10 +311,9 @@ ui::SimpleMenuModel* DownloadShelfContextMenu::GetFinishedMenuModel() { finished_download_menu_model_->AddItemWithStringId( OPEN_WHEN_COMPLETE, IDS_DOWNLOAD_MENU_OPEN); finished_download_menu_model_->AddCheckItemWithStringId( - ALWAYS_OPEN_TYPE, IDS_DOWNLOAD_MENU_ALWAYS_OPEN_TYPE); - if (DownloadItemModel(download_item_).ShouldPreferOpeningInBrowser()) - finished_download_menu_model_->AddItemWithStringId( - PLATFORM_OPEN, IDS_DOWNLOAD_MENU_PLATFORM_OPEN); + ALWAYS_OPEN_TYPE, GetAlwaysOpenStringId()); + finished_download_menu_model_->AddItemWithStringId( + PLATFORM_OPEN, IDS_DOWNLOAD_MENU_PLATFORM_OPEN); finished_download_menu_model_->AddSeparator(ui::NORMAL_SEPARATOR); finished_download_menu_model_->AddItemWithStringId( SHOW_IN_FOLDER, IDS_DOWNLOAD_MENU_SHOW); @@ -333,8 +371,7 @@ ui::SimpleMenuModel* DownloadShelfContextMenu::GetMaybeMaliciousMenuModel() { return maybe_malicious_download_menu_model_.get(); } -ui::SimpleMenuModel* -DownloadShelfContextMenu::GetMaliciousMenuModel() { +ui::SimpleMenuModel* DownloadShelfContextMenu::GetMaliciousMenuModel() { if (malicious_download_menu_model_) return malicious_download_menu_model_.get(); @@ -346,3 +383,22 @@ DownloadShelfContextMenu::GetMaliciousMenuModel() { return malicious_download_menu_model_.get(); } + +int DownloadShelfContextMenu::GetAlwaysOpenStringId() const { +#if defined(OS_WIN) + if (CanOpenPdfInReader()) + return IDS_DOWNLOAD_MENU_ALWAYS_OPEN_PDF_IN_READER; +#endif + return IDS_DOWNLOAD_MENU_ALWAYS_OPEN_TYPE; +} + +#if defined(OS_WIN) +bool DownloadShelfContextMenu::IsDownloadPdf() const { + base::FilePath path = download_item_->GetTargetFilePath(); + return path.MatchesExtension(FILE_PATH_LITERAL(".pdf")); +} + +bool DownloadShelfContextMenu::CanOpenPdfInReader() const { + return (is_pdf_reader_up_to_date_ && IsDownloadPdf()); +} +#endif diff --git a/chrome/browser/download/download_shelf_context_menu.h b/chrome/browser/download/download_shelf_context_menu.h index 15b6504..a5d8a5eb 100644 --- a/chrome/browser/download/download_shelf_context_menu.h +++ b/chrome/browser/download/download_shelf_context_menu.h @@ -52,6 +52,7 @@ class DownloadShelfContextMenu : public ui::SimpleMenuModel::Delegate, // ui::SimpleMenuModel::Delegate: virtual bool IsCommandIdEnabled(int command_id) const OVERRIDE; virtual bool IsCommandIdChecked(int command_id) const OVERRIDE; + virtual bool IsCommandIdVisible(int command_id) const OVERRIDE; virtual void ExecuteCommand(int command_id, int event_flags) OVERRIDE; virtual bool GetAcceleratorForCommandId( int command_id, @@ -73,6 +74,13 @@ class DownloadShelfContextMenu : public ui::SimpleMenuModel::Delegate, ui::SimpleMenuModel* GetMaybeMaliciousMenuModel(); ui::SimpleMenuModel* GetMaliciousMenuModel(); + int GetAlwaysOpenStringId() const; + +#if defined(OS_WIN) + bool IsDownloadPdf() const; + bool CanOpenPdfInReader() const; +#endif + // We show slightly different menus if the download is in progress vs. if the // download has finished. scoped_ptr<ui::SimpleMenuModel> in_progress_download_menu_model_; @@ -87,6 +95,10 @@ class DownloadShelfContextMenu : public ui::SimpleMenuModel::Delegate, // Used to open tabs. content::PageNavigator* navigator_; +#if defined(OS_WIN) + bool is_pdf_reader_up_to_date_; +#endif + DISALLOW_COPY_AND_ASSIGN(DownloadShelfContextMenu); }; diff --git a/chrome/browser/download/download_target_determiner.cc b/chrome/browser/download/download_target_determiner.cc index e7bb16d..971a904 100644 --- a/chrome/browser/download/download_target_determiner.cc +++ b/chrome/browser/download/download_target_determiner.cc @@ -33,6 +33,10 @@ #include "content/public/common/webplugininfo.h" #endif +#if defined(OS_WIN) +#include "chrome/browser/ui/pdf/adobe_reader_info_win.h" +#endif + using content::BrowserThread; using content::DownloadItem; @@ -56,7 +60,12 @@ void VisitCountsToVisitedBefore( (first_visit.LocalMidnight() < base::Time::Now().LocalMidnight())); } -} // namespace +#if defined(OS_WIN) +// Keeps track of whether Adobe Reader is up to date. +bool g_is_adobe_reader_up_to_date_ = false; +#endif + +} // namespace DownloadTargetInfo::DownloadTargetInfo() : is_filetype_handled_safely(false) {} @@ -131,6 +140,9 @@ void DownloadTargetDeterminer::DoLoop() { case STATE_DETERMINE_IF_HANDLED_SAFELY_BY_BROWSER: result = DoDetermineIfHandledSafely(); break; + case STATE_DETERMINE_IF_ADOBE_READER_UP_TO_DATE: + result = DoDetermineIfAdobeReaderUpToDate(); + break; case STATE_CHECK_DOWNLOAD_URL: result = DoCheckDownloadUrl(); break; @@ -447,8 +459,8 @@ void IsHandledBySafePlugin(content::ResourceContext* resource_context, BrowserThread::UI, FROM_HERE, base::Bind(callback, is_handled_safely)); } -} // namespace -#endif // ENABLE_PLUGINS +} // namespace +#endif // defined(ENABLE_PLUGINS) DownloadTargetDeterminer::Result DownloadTargetDeterminer::DoDetermineIfHandledSafely() { @@ -457,7 +469,7 @@ DownloadTargetDeterminer::Result DCHECK(!local_path_.empty()); DCHECK(!is_filetype_handled_safely_); - next_state_ = STATE_CHECK_DOWNLOAD_URL; + next_state_ = STATE_DETERMINE_IF_ADOBE_READER_UP_TO_DATE; if (mime_type_.empty()) return CONTINUE; @@ -485,14 +497,51 @@ DownloadTargetDeterminer::Result #endif } +#if defined(ENABLE_PLUGINS) void DownloadTargetDeterminer::DetermineIfHandledSafelyDone( bool is_handled_safely) { DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); DVLOG(20) << "Is file type handled safely: " << is_filetype_handled_safely_; - DCHECK_EQ(STATE_CHECK_DOWNLOAD_URL, next_state_); + DCHECK_EQ(STATE_DETERMINE_IF_ADOBE_READER_UP_TO_DATE, next_state_); is_filetype_handled_safely_ = is_handled_safely; DoLoop(); } +#endif + +DownloadTargetDeterminer::Result + DownloadTargetDeterminer::DoDetermineIfAdobeReaderUpToDate() { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + + next_state_ = STATE_CHECK_DOWNLOAD_URL; + +#if defined(OS_WIN) + if (!local_path_.MatchesExtension(FILE_PATH_LITERAL(".pdf"))) + return CONTINUE; + if (!IsAdobeReaderDefaultPDFViewer()) + return CONTINUE; + + base::PostTaskAndReplyWithResult( + BrowserThread::GetBlockingPool(), + FROM_HERE, + base::Bind(&::IsAdobeReaderUpToDate), + base::Bind(&DownloadTargetDeterminer::DetermineIfAdobeReaderUpToDateDone, + weak_ptr_factory_.GetWeakPtr())); + return QUIT_DOLOOP; +#else + return CONTINUE; +#endif +} + +#if defined(OS_WIN) +void DownloadTargetDeterminer::DetermineIfAdobeReaderUpToDateDone( + bool adobe_reader_up_to_date) { + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); + DVLOG(20) << "Is Adobe Reader Up To Date: " << adobe_reader_up_to_date; + DCHECK_EQ(STATE_CHECK_DOWNLOAD_URL, next_state_); + g_is_adobe_reader_up_to_date_ = adobe_reader_up_to_date; + DoLoop(); +} +#endif DownloadTargetDeterminer::Result DownloadTargetDeterminer::DoCheckDownloadUrl() { @@ -821,3 +870,10 @@ base::FilePath DownloadTargetDeterminer::GetCrDownloadPath( const base::FilePath& suggested_path) { return base::FilePath(suggested_path.value() + kCrdownloadSuffix); } + +#if defined(OS_WIN) +// static +bool DownloadTargetDeterminer::IsAdobeReaderUpToDate() { + return g_is_adobe_reader_up_to_date_; +} +#endif diff --git a/chrome/browser/download/download_target_determiner.h b/chrome/browser/download/download_target_determiner.h index a244331..4f6e5c0 100644 --- a/chrome/browser/download/download_target_determiner.h +++ b/chrome/browser/download/download_target_determiner.h @@ -79,6 +79,13 @@ class DownloadTargetDeterminer // Returns a .crdownload intermediate path for the |suggested_path|. static base::FilePath GetCrDownloadPath(const base::FilePath& suggested_path); +#if defined(OS_WIN) + // Returns true if Adobe Reader is up to date. This information refreshed + // only when Start() gets called for a PDF and Adobe Reader is the default + // System PDF viewer. + static bool IsAdobeReaderUpToDate(); +#endif + private: // The main workflow is controlled via a set of state transitions. Each state // has an associated handler. The handler for STATE_FOO is DoFoo. Each handler @@ -93,6 +100,7 @@ class DownloadTargetDeterminer STATE_DETERMINE_LOCAL_PATH, STATE_DETERMINE_MIME_TYPE, STATE_DETERMINE_IF_HANDLED_SAFELY_BY_BROWSER, + STATE_DETERMINE_IF_ADOBE_READER_UP_TO_DATE, STATE_CHECK_DOWNLOAD_URL, STATE_CHECK_VISITED_REFERRER_BEFORE, STATE_DETERMINE_INTERMEDIATE_PATH, @@ -205,12 +213,26 @@ class DownloadTargetDeterminer // Determine if the file type can be handled safely by the browser if it were // to be opened via a file:// URL. // Next state: - // - STATE_CHECK_DOWNLOAD_URL. + // - STATE_DETERMINE_IF_ADOBE_READER_UP_TO_DATE. Result DoDetermineIfHandledSafely(); +#if defined(ENABLE_PLUGINS) // Callback invoked when a decision is available about whether the file type // can be handled safely by the browser. void DetermineIfHandledSafelyDone(bool is_handled_safely); +#endif + + // Determine if Adobe Reader is up to date. Only do the check on Windows for + // .pdf file targets. + // Next state: + // - STATE_CHECK_DOWNLOAD_URL. + Result DoDetermineIfAdobeReaderUpToDate(); + +#if defined(OS_WIN) + // Callback invoked when a decision is available about whether Adobe Reader + // is up to date. + void DetermineIfAdobeReaderUpToDateDone(bool adobe_reader_up_to_date); +#endif // Checks whether the downloaded URL is malicious. Invokes the // DownloadProtectionService via the delegate. diff --git a/chrome/browser/ui/pdf/pdf_unsupported_feature.cc b/chrome/browser/ui/pdf/pdf_unsupported_feature.cc index 6252408..4ae28c0 100644 --- a/chrome/browser/ui/pdf/pdf_unsupported_feature.cc +++ b/chrome/browser/ui/pdf/pdf_unsupported_feature.cc @@ -6,13 +6,9 @@ #include "base/bind.h" #include "base/memory/scoped_ptr.h" -#include "base/prefs/pref_service.h" #include "base/strings/utf_string_conversions.h" -#include "base/values.h" -#include "base/version.h" #include "chrome/browser/lifetime/application_lifetime.h" #include "chrome/browser/plugins/chrome_plugin_service_filter.h" -#include "chrome/browser/plugins/plugin_finder.h" #include "chrome/browser/plugins/plugin_metadata.h" #include "chrome/browser/plugins/plugin_prefs.h" #include "chrome/browser/profiles/profile.h" @@ -21,46 +17,39 @@ #include "chrome/browser/ui/pdf/open_pdf_in_reader_prompt_delegate.h" #include "chrome/browser/ui/pdf/pdf_tab_helper.h" #include "chrome/common/chrome_content_client.h" -#include "chrome/common/pref_names.h" #include "content/public/browser/interstitial_page.h" #include "content/public/browser/interstitial_page_delegate.h" #include "content/public/browser/navigation_details.h" #include "content/public/browser/navigation_entry.h" -#include "content/public/browser/plugin_service.h" +#include "content/public/browser/page_navigator.h" #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" #include "content/public/browser/user_metrics.h" #include "content/public/browser/web_contents.h" -#include "content/public/common/page_transition_types.h" #include "grit/browser_resources.h" #include "grit/generated_resources.h" -#include "grit/theme_resources.h" #include "ui/base/l10n/l10n_util.h" #include "ui/base/resource/resource_bundle.h" #include "ui/base/webui/jstemplate_builder.h" -#include "ui/gfx/image/image.h" #if defined(OS_WIN) #include "base/win/metro.h" +#include "chrome/browser/ui/pdf/adobe_reader_info_win.h" #endif using base::UserMetricsAction; using content::InterstitialPage; using content::OpenURLParams; -using content::PluginService; using content::Referrer; using content::WebContents; using content::WebPluginInfo; +#if defined(OS_WIN) namespace { const char kAdobeReaderUpdateUrl[] = "http://www.adobe.com/go/getreader_chrome"; -#if defined(OS_WIN) && defined(ENABLE_PLUGIN_INSTALLATION) -const char kAdobeReaderIdentifier[] = "adobe-reader"; -#endif - // The prompt delegate used to ask the user if they want to use Adobe Reader // by default. class PDFEnableAdobeReaderPromptDelegate @@ -244,10 +233,9 @@ class PDFUnsupportedFeatureInterstitial class PDFUnsupportedFeaturePromptDelegate : public OpenPDFInReaderPromptDelegate { public: - // |reader| is NULL if Adobe Reader isn't installed. - PDFUnsupportedFeaturePromptDelegate(WebContents* web_contents, - const content::WebPluginInfo* reader, - PluginFinder* plugin_finder); + PDFUnsupportedFeaturePromptDelegate( + WebContents* web_contents, + const AdobeReaderPluginInfo& reader_info); virtual ~PDFUnsupportedFeaturePromptDelegate(); // OpenPDFInReaderPromptDelegate: @@ -261,38 +249,19 @@ class PDFUnsupportedFeaturePromptDelegate private: WebContents* web_contents_; - bool reader_installed_; - bool reader_vulnerable_; - WebPluginInfo reader_webplugininfo_; + const AdobeReaderPluginInfo reader_info_; DISALLOW_IMPLICIT_CONSTRUCTORS(PDFUnsupportedFeaturePromptDelegate); }; PDFUnsupportedFeaturePromptDelegate::PDFUnsupportedFeaturePromptDelegate( WebContents* web_contents, - const content::WebPluginInfo* reader, - PluginFinder* plugin_finder) + const AdobeReaderPluginInfo& reader_info) : web_contents_(web_contents), - reader_installed_(!!reader), - reader_vulnerable_(false) { - if (!reader_installed_) { - content::RecordAction( - UserMetricsAction("PDF_InstallReaderInfoBarShown")); - return; - } - - content::RecordAction(UserMetricsAction("PDF_UseReaderInfoBarShown")); - reader_webplugininfo_ = *reader; - -#if defined(ENABLE_PLUGIN_INSTALLATION) - scoped_ptr<PluginMetadata> plugin_metadata( - plugin_finder->GetPluginMetadata(reader_webplugininfo_)); - - reader_vulnerable_ = plugin_metadata->GetSecurityStatus(*reader) != - PluginMetadata::SECURITY_STATUS_UP_TO_DATE; -#else - NOTREACHED(); -#endif + reader_info_(reader_info) { + content::RecordAction(reader_info_.is_installed ? + UserMetricsAction("PDF_UseReaderInfoBarShown") : + UserMetricsAction("PDF_InstallReaderInfoBarShown")); } PDFUnsupportedFeaturePromptDelegate::~PDFUnsupportedFeaturePromptDelegate() { @@ -304,15 +273,12 @@ base::string16 PDFUnsupportedFeaturePromptDelegate::GetMessageText() const { base::string16 PDFUnsupportedFeaturePromptDelegate::GetAcceptButtonText() const { -#if defined(OS_WIN) if (base::win::IsMetroProcess()) return l10n_util::GetStringUTF16(IDS_PDF_BUBBLE_METRO_MODE_LINK); -#endif - if (reader_installed_) - return l10n_util::GetStringUTF16(IDS_PDF_BUBBLE_OPEN_IN_READER_LINK); - - return l10n_util::GetStringUTF16(IDS_PDF_BUBBLE_INSTALL_READER_LINK); + return l10n_util::GetStringUTF16( + reader_info_.is_installed ? IDS_PDF_BUBBLE_OPEN_IN_READER_LINK + : IDS_PDF_BUBBLE_INSTALL_READER_LINK); } base::string16 PDFUnsupportedFeaturePromptDelegate::GetCancelButtonText() @@ -326,14 +292,12 @@ bool PDFUnsupportedFeaturePromptDelegate::ShouldExpire( } void PDFUnsupportedFeaturePromptDelegate::Accept() { -#if defined(OS_WIN) if (base::win::IsMetroProcess()) { chrome::AttemptRestartWithModeSwitch(); return; } -#endif - if (!reader_installed_) { + if (!reader_info_.is_installed) { content::RecordAction(UserMetricsAction("PDF_InstallReaderInfoBarOK")); OpenReaderUpdateURL(web_contents_); return; @@ -341,8 +305,9 @@ void PDFUnsupportedFeaturePromptDelegate::Accept() { content::RecordAction(UserMetricsAction("PDF_UseReaderInfoBarOK")); - if (reader_vulnerable_) { - new PDFUnsupportedFeatureInterstitial(web_contents_, reader_webplugininfo_); + if (!reader_info_.is_secure) { + new PDFUnsupportedFeatureInterstitial(web_contents_, + reader_info_.plugin_info); return; } @@ -351,61 +316,54 @@ void PDFUnsupportedFeaturePromptDelegate::Accept() { OpenPDFInReaderPromptDelegate* delegate = new PDFEnableAdobeReaderPromptDelegate(profile); - OpenUsingReader(web_contents_, reader_webplugininfo_, delegate); + OpenUsingReader(web_contents_, reader_info_.plugin_info, delegate); } void PDFUnsupportedFeaturePromptDelegate::Cancel() { - content::RecordAction(reader_installed_ ? + content::RecordAction(reader_info_.is_installed ? UserMetricsAction("PDF_UseReaderInfoBarCancel") : UserMetricsAction("PDF_InstallReaderInfoBarCancel")); } -#if defined(OS_WIN) && defined(ENABLE_PLUGIN_INSTALLATION) -void GotPluginsCallback(int process_id, - int routing_id, - const std::vector<content::WebPluginInfo>& plugins) { - WebContents* web_contents = - tab_util::GetWebContentsByID(process_id, routing_id); - if (!web_contents) +void MaybeShowOpenPDFInReaderPrompt(WebContents* web_contents, + const AdobeReaderPluginInfo& reader_info) { + // If the Reader plugin is disabled by policy, don't prompt them. + if (!reader_info.is_installed || !reader_info.is_enabled) return; - const content::WebPluginInfo* reader = NULL; - PluginFinder* plugin_finder = PluginFinder::GetInstance(); - for (size_t i = 0; i < plugins.size(); ++i) { - scoped_ptr<PluginMetadata> plugin_metadata( - plugin_finder->GetPluginMetadata(plugins[i])); - if (plugin_metadata->identifier() != kAdobeReaderIdentifier) - continue; - - DCHECK(!reader); - reader = &plugins[i]; - // If the Reader plugin is disabled by policy, don't prompt them. - Profile* profile = - Profile::FromBrowserContext(web_contents->GetBrowserContext()); - PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(profile); - if (plugin_prefs->PolicyStatusForPlugin(plugin_metadata->name()) == - PluginPrefs::POLICY_DISABLED) { - return; - } - break; - } - scoped_ptr<OpenPDFInReaderPromptDelegate> prompt( - new PDFUnsupportedFeaturePromptDelegate( - web_contents, reader, plugin_finder)); + new PDFUnsupportedFeaturePromptDelegate(web_contents, reader_info)); PDFTabHelper* pdf_tab_helper = PDFTabHelper::FromWebContents(web_contents); pdf_tab_helper->ShowOpenInReaderPrompt(prompt.Pass()); } -#endif // defined(OS_WIN) && defined(ENABLE_PLUGIN_INSTALLATION) + +void GotPluginsCallback(int process_id, + int routing_id, + const AdobeReaderPluginInfo& reader_info) { + WebContents* web_contents = + tab_util::GetWebContentsByID(process_id, routing_id); + if (web_contents) + MaybeShowOpenPDFInReaderPrompt(web_contents, reader_info); +} } // namespace +#endif // defined(OS_WIN) -void PDFHasUnsupportedFeature(content::WebContents* web_contents) { -#if defined(OS_WIN) && defined(ENABLE_PLUGIN_INSTALLATION) +void PDFHasUnsupportedFeature(WebContents* web_contents) { +#if defined(OS_WIN) // Only works for Windows for now. For Mac, we'll have to launch the file // externally since Adobe Reader doesn't work inside Chrome. - PluginService::GetInstance()->GetPlugins(base::Bind(&GotPluginsCallback, - web_contents->GetRenderProcessHost()->GetID(), - web_contents->GetRenderViewHost()->GetRoutingID())); -#endif + Profile* profile = + Profile::FromBrowserContext(web_contents->GetBrowserContext()); + AdobeReaderPluginInfo reader_info; + if (GetAdobeReaderPluginInfo(profile, &reader_info)) { + MaybeShowOpenPDFInReaderPrompt(web_contents, reader_info); + return; + } + GetAdobeReaderPluginInfoAsync( + profile, + base::Bind(&GotPluginsCallback, + web_contents->GetRenderProcessHost()->GetID(), + web_contents->GetRenderViewHost()->GetRoutingID())); +#endif // defined(OS_WIN) } diff --git a/chrome/chrome_browser_ui.gypi b/chrome/chrome_browser_ui.gypi index 80f33ce..86921f7 100644 --- a/chrome/chrome_browser_ui.gypi +++ b/chrome/chrome_browser_ui.gypi @@ -1271,6 +1271,8 @@ 'browser/ui/passwords/password_manager_presenter.cc', 'browser/ui/passwords/password_manager_presenter.h', 'browser/ui/passwords/password_ui_view.h', + 'browser/ui/pdf/adobe_reader_info_win.cc', + 'browser/ui/pdf/adobe_reader_info_win.h', 'browser/ui/pdf/open_pdf_in_reader_prompt_delegate.h', 'browser/ui/pdf/pdf_tab_helper.cc', 'browser/ui/pdf/pdf_tab_helper.h', diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 5fe8c1d..2885c1b 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -1529,6 +1529,12 @@ const char kDownloadDefaultDirectory[] = "download.default_directory"; // upgrade a unsafe location to a safe location. const char kDownloadDirUpgraded[] = "download.directory_upgrade"; +#if defined(OS_WIN) +// Whether downloaded PDFs should be opened in Adobe Acrobat Reader. +const char kOpenPdfDownloadInAdobeReader[] = + "download.open_pdf_in_adobe_reader"; +#endif + // String which specifies where to save html files to by default. const char kSaveFileDefaultDirectory[] = "savefile.default_directory"; diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 09e4533..6e0a457 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -495,6 +495,9 @@ extern const char kMemoryCacheSize[]; extern const char kDownloadDefaultDirectory[]; extern const char kDownloadExtensionsToOpen[]; extern const char kDownloadDirUpgraded[]; +#if defined(OS_WIN) +extern const char kOpenPdfDownloadInAdobeReader[]; +#endif extern const char kSaveFileDefaultDirectory[]; extern const char kSaveFileType[]; |