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.7.79";
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 PluginPrefs
* plugin_prefs
= PluginPrefs::GetForProfile(profile
);
92 PluginPrefs::PolicyStatus plugin_status
=
93 plugin_prefs
->PolicyStatusForPlugin(plugin_metadata
->name());
94 reader_info
.is_enabled
= plugin_status
!= PluginPrefs::POLICY_DISABLED
;
97 PluginMetadata::SecurityStatus security_status
=
98 plugin_metadata
->GetSecurityStatus(plugins
[i
]);
99 reader_info
.is_secure
=
100 security_status
== PluginMetadata::SECURITY_STATUS_UP_TO_DATE
;
102 reader_info
.plugin_info
= plugins
[i
];
108 void OnGotPluginInfo(Profile
* profile
,
109 const GetAdobeReaderPluginInfoCallback
& callback
,
110 const std::vector
<content::WebPluginInfo
>& plugins
) {
111 if (!g_browser_process
->profile_manager()->IsValidProfile(profile
))
113 callback
.Run(GetReaderPlugin(profile
, plugins
));
116 bool IsAdobeReaderDefaultPDFViewerInternal(base::FilePath
* path
) {
117 base::char16 app_cmd_buf
[MAX_PATH
];
118 DWORD app_cmd_buf_len
= MAX_PATH
;
119 HRESULT hr
= AssocQueryString(ASSOCF_NONE
, ASSOCSTR_COMMAND
, L
".pdf", L
"open",
120 app_cmd_buf
, &app_cmd_buf_len
);
124 // Looks for the install paths for Acrobat / Reader.
125 base::FilePath install_path
= GetInstalledPath(kRegistryAcrobatReader
);
126 if (install_path
.empty())
127 install_path
= GetInstalledPath(kRegistryAcrobat
);
128 if (install_path
.empty())
131 base::string16
app_cmd(app_cmd_buf
);
132 bool found
= app_cmd
.find(install_path
.value()) != base::string16::npos
;
134 *path
= install_path
;
140 void GetAdobeReaderPluginInfoAsync(
142 const GetAdobeReaderPluginInfoCallback
& callback
) {
143 DCHECK(!callback
.is_null());
144 content::PluginService::GetInstance()->GetPlugins(
145 base::Bind(&OnGotPluginInfo
, profile
, callback
));
148 bool GetAdobeReaderPluginInfo(Profile
* profile
,
149 AdobeReaderPluginInfo
* reader_info
) {
151 std::vector
<content::WebPluginInfo
> plugins
;
152 bool up_to_date
= content::PluginService::GetInstance()->GetPluginInfoArray(
153 GURL(), kPdfMimeType
, false, &plugins
, NULL
);
154 *reader_info
= GetReaderPlugin(profile
, plugins
);
158 bool IsAdobeReaderDefaultPDFViewer() {
159 return IsAdobeReaderDefaultPDFViewerInternal(NULL
);
162 bool IsAdobeReaderUpToDate() {
163 base::FilePath install_path
;
164 bool is_default
= IsAdobeReaderDefaultPDFViewerInternal(&install_path
);
168 scoped_ptr
<FileVersionInfo
> file_version_info(
169 FileVersionInfo::CreateFileVersionInfo(install_path
));
170 if (!file_version_info
)
173 std::string reader_version
=
174 base::UTF16ToUTF8(file_version_info
->product_version());
175 // Convert 1.2.03.45 to 1.2.3.45 so base::Version considers it as valid.
176 for (int i
= 1; i
<= 9; ++i
) {
177 std::string from
= base::StringPrintf(".0%d", i
);
178 std::string to
= base::StringPrintf(".%d", i
);
179 ReplaceSubstringsAfterOffset(&reader_version
, 0, from
, to
);
181 base::Version
file_version(reader_version
);
182 return file_version
.IsValid() && !file_version
.IsOlderThan(kSecureVersion
);