1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/ui/pdf/adobe_reader_info_win.h"
12 #include "base/bind.h"
13 #include "base/callback.h"
14 #include "base/file_version_info.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h"
17 #include "base/strings/utf_string_conversions.h"
18 #include "base/win/registry.h"
19 #include "base/win/windows_version.h"
20 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/plugins/plugin_finder.h"
22 #include "chrome/browser/plugins/plugin_metadata.h"
23 #include "chrome/browser/plugins/plugin_prefs.h"
24 #include "chrome/browser/profiles/profile.h"
25 #include "chrome/browser/profiles/profile_manager.h"
26 #include "content/public/browser/plugin_service.h"
30 // Hardcoded value for the secure version of Acrobat Reader.
31 const char kSecureVersion
[] = "11.0.8.4";
33 const char kAdobeReaderIdentifier
[] = "adobe-reader";
34 const char kPdfMimeType
[] = "application/pdf";
35 const base::char16 kRegistryAcrobat
[] = L
"Acrobat.exe";
36 const base::char16 kRegistryAcrobatReader
[] = L
"AcroRd32.exe";
37 const base::char16 kRegistryApps
[] =
38 L
"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths";
39 const base::char16 kRegistryPath
[] = L
"Path";
41 // Gets the installed path for a registered app.
42 base::FilePath
GetInstalledPath(const base::char16
* app
) {
43 base::string16
reg_path(kRegistryApps
);
44 reg_path
.append(L
"\\");
47 base::FilePath filepath
;
48 base::win::RegKey
hkcu_key(HKEY_CURRENT_USER
, reg_path
.c_str(), KEY_READ
);
50 // As of Win7 AppPaths can also be registered in HKCU: http://goo.gl/UgFOf.
51 if (base::win::GetVersion() >= base::win::VERSION_WIN7
&&
52 hkcu_key
.ReadValue(kRegistryPath
, &path
) == ERROR_SUCCESS
) {
53 filepath
= base::FilePath(path
);
55 base::win::RegKey
hklm_key(HKEY_LOCAL_MACHINE
, reg_path
.c_str(), KEY_READ
);
56 if (hklm_key
.ReadValue(kRegistryPath
, &path
) == ERROR_SUCCESS
) {
57 filepath
= base::FilePath(path
);
60 return filepath
.Append(app
);
63 bool IsPdfMimeType(const content::WebPluginMimeType
& plugin_mime_type
) {
64 return plugin_mime_type
.mime_type
== kPdfMimeType
;
67 AdobeReaderPluginInfo
GetReaderPlugin(
69 const std::vector
<content::WebPluginInfo
>& plugins
) {
70 AdobeReaderPluginInfo reader_info
;
71 reader_info
.is_installed
= false;
72 reader_info
.is_enabled
= false;
73 reader_info
.is_secure
= false;
75 PluginFinder
* plugin_finder
= PluginFinder::GetInstance();
76 for (size_t i
= 0; i
< plugins
.size(); ++i
) {
77 const content::WebPluginInfo
& plugin
= plugins
[i
];
78 if (plugin
.is_pepper_plugin())
80 if (std::find_if(plugin
.mime_types
.begin(), plugin
.mime_types
.end(),
81 IsPdfMimeType
) == plugin
.mime_types
.end())
83 scoped_ptr
<PluginMetadata
> plugin_metadata(
84 plugin_finder
->GetPluginMetadata(plugins
[i
]));
85 if (plugin_metadata
->identifier() != kAdobeReaderIdentifier
)
88 reader_info
.is_installed
= true;
91 scoped_refptr
<PluginPrefs
> plugin_prefs
=
92 PluginPrefs::GetForProfile(profile
);
93 PluginPrefs::PolicyStatus plugin_status
=
94 plugin_prefs
->PolicyStatusForPlugin(plugin_metadata
->name());
95 reader_info
.is_enabled
= plugin_status
!= PluginPrefs::POLICY_DISABLED
;
98 // Adobe Reader will likely always come up as "requires_authorization".
99 // See http://crbug.com/311655.
100 PluginMetadata::SecurityStatus security_stat
=
101 plugin_metadata
->GetSecurityStatus(plugins
[i
]);
102 reader_info
.is_secure
=
103 security_stat
== PluginMetadata::SECURITY_STATUS_UP_TO_DATE
||
104 security_stat
== PluginMetadata::SECURITY_STATUS_REQUIRES_AUTHORIZATION
;
106 reader_info
.plugin_info
= plugins
[i
];
112 void OnGotPluginInfo(Profile
* profile
,
113 const GetAdobeReaderPluginInfoCallback
& callback
,
114 const std::vector
<content::WebPluginInfo
>& plugins
) {
115 if (!g_browser_process
->profile_manager()->IsValidProfile(profile
))
117 callback
.Run(GetReaderPlugin(profile
, plugins
));
120 bool IsAdobeReaderDefaultPDFViewerInternal(base::FilePath
* path
) {
121 base::char16 app_cmd_buf
[MAX_PATH
];
122 DWORD app_cmd_buf_len
= MAX_PATH
;
123 HRESULT hr
= AssocQueryString(ASSOCF_NONE
, ASSOCSTR_COMMAND
, L
".pdf", L
"open",
124 app_cmd_buf
, &app_cmd_buf_len
);
128 // Looks for the install paths for Acrobat / Reader.
129 base::FilePath install_path
= GetInstalledPath(kRegistryAcrobatReader
);
130 if (install_path
.empty())
131 install_path
= GetInstalledPath(kRegistryAcrobat
);
132 if (install_path
.empty())
135 base::string16
app_cmd(app_cmd_buf
);
136 bool found
= app_cmd
.find(install_path
.value()) != base::string16::npos
;
138 *path
= install_path
;
144 void GetAdobeReaderPluginInfoAsync(
146 const GetAdobeReaderPluginInfoCallback
& callback
) {
147 DCHECK(!callback
.is_null());
148 content::PluginService::GetInstance()->GetPlugins(
149 base::Bind(&OnGotPluginInfo
, profile
, callback
));
152 bool GetAdobeReaderPluginInfo(Profile
* profile
,
153 AdobeReaderPluginInfo
* reader_info
) {
155 std::vector
<content::WebPluginInfo
> plugins
;
156 bool up_to_date
= content::PluginService::GetInstance()->GetPluginInfoArray(
157 GURL(), kPdfMimeType
, false, &plugins
, NULL
);
158 *reader_info
= GetReaderPlugin(profile
, plugins
);
162 bool IsAdobeReaderDefaultPDFViewer() {
163 return IsAdobeReaderDefaultPDFViewerInternal(NULL
);
166 bool IsAdobeReaderUpToDate() {
167 base::FilePath install_path
;
168 bool is_default
= IsAdobeReaderDefaultPDFViewerInternal(&install_path
);
172 scoped_ptr
<FileVersionInfo
> file_version_info(
173 FileVersionInfo::CreateFileVersionInfo(install_path
));
174 if (!file_version_info
)
177 std::string reader_version
=
178 base::UTF16ToUTF8(file_version_info
->product_version());
179 // Convert 1.2.03.45 to 1.2.3.45 so base::Version considers it as valid.
180 for (int i
= 1; i
<= 9; ++i
) {
181 std::string from
= base::StringPrintf(".0%d", i
);
182 std::string to
= base::StringPrintf(".%d", i
);
183 base::ReplaceSubstringsAfterOffset(&reader_version
, 0, from
, to
);
185 base::Version
file_version(reader_version
);
186 return file_version
.IsValid() && !file_version
.IsOlderThan(kSecureVersion
);