OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/pdf_unsupported_feature.h" | 5 #include "chrome/browser/pdf_unsupported_feature.h" |
6 | 6 |
7 #include "base/utf_string_conversions.h" | 7 #include "base/utf_string_conversions.h" |
8 #include "base/values.h" | 8 #include "base/values.h" |
9 #include "base/version.h" | 9 #include "base/version.h" |
| 10 #include "chrome/browser/metrics/user_metrics.h" |
10 #include "chrome/browser/plugin_service.h" | 11 #include "chrome/browser/plugin_service.h" |
11 #include "chrome/browser/renderer_host/render_process_host.h" | 12 #include "chrome/browser/renderer_host/render_process_host.h" |
12 #include "chrome/browser/renderer_host/render_view_host.h" | 13 #include "chrome/browser/renderer_host/render_view_host.h" |
13 #include "chrome/browser/tab_contents/infobar_delegate.h" | 14 #include "chrome/browser/tab_contents/infobar_delegate.h" |
14 #include "chrome/browser/tab_contents/interstitial_page.h" | 15 #include "chrome/browser/tab_contents/interstitial_page.h" |
15 #include "chrome/browser/tab_contents/tab_contents.h" | 16 #include "chrome/browser/tab_contents/tab_contents.h" |
16 #include "chrome/common/jstemplate_builder.h" | 17 #include "chrome/common/jstemplate_builder.h" |
| 18 #include "chrome/common/pepper_plugin_registry.h" |
17 #include "grit/browser_resources.h" | 19 #include "grit/browser_resources.h" |
18 #include "grit/generated_resources.h" | 20 #include "grit/generated_resources.h" |
19 #include "ui/base/l10n/l10n_util.h" | 21 #include "ui/base/l10n/l10n_util.h" |
20 #include "ui/base/resource/resource_bundle.h" | 22 #include "ui/base/resource/resource_bundle.h" |
21 #include "webkit/plugins/npapi/plugin_group.h" | 23 #include "webkit/plugins/npapi/plugin_group.h" |
22 #include "webkit/plugins/npapi/plugin_list.h" | 24 #include "webkit/plugins/npapi/plugin_list.h" |
23 #include "webkit/plugins/npapi/webplugininfo.h" | 25 #include "webkit/plugins/npapi/webplugininfo.h" |
24 | 26 |
25 using webkit::npapi::PluginGroup; | 27 using webkit::npapi::PluginGroup; |
26 using webkit::npapi::PluginList; | 28 using webkit::npapi::PluginList; |
27 using webkit::npapi::WebPluginInfo; | 29 using webkit::npapi::WebPluginInfo; |
28 | 30 |
29 // Only launch Adobe Reader X or later. | 31 // Only launch Adobe Reader X or later. |
30 static const uint16 kMinReaderVersionToUse = 10; | 32 static const uint16 kMinReaderVersionToUse = 10; |
31 | 33 |
32 namespace { | 34 namespace { |
33 | 35 |
| 36 // The info bar delegate used to ask the user if they want to use Adobe Reader |
| 37 // by default. |
| 38 class PDFEnableAdobeReaderConfirmInfoBarDelegate |
| 39 : public ConfirmInfoBarDelegate { |
| 40 public: |
| 41 PDFEnableAdobeReaderConfirmInfoBarDelegate( |
| 42 TabContents* tab_contents) |
| 43 : ConfirmInfoBarDelegate(tab_contents) { |
| 44 UserMetrics::RecordAction( |
| 45 UserMetricsAction("PDF_EnableReaderInfoBarShown")); |
| 46 } |
| 47 |
| 48 // ConfirmInfoBarDelegate |
| 49 virtual void InfoBarClosed() { |
| 50 delete this; |
| 51 } |
| 52 |
| 53 virtual void InfoBarDismissed() { |
| 54 Cancel(); |
| 55 } |
| 56 |
| 57 virtual Type GetInfoBarType() const { |
| 58 return PAGE_ACTION_TYPE; |
| 59 } |
| 60 |
| 61 virtual bool Accept() { |
| 62 UserMetrics::RecordAction( |
| 63 UserMetricsAction("PDF_EnableReaderInfoBarOK")); |
| 64 webkit::npapi::PluginList::Singleton()->EnableGroup( |
| 65 false, ASCIIToUTF16(PepperPluginRegistry::kPDFPluginName)); |
| 66 webkit::npapi::PluginList::Singleton()->EnableGroup( |
| 67 true, ASCIIToUTF16(webkit::npapi::PluginGroup::kAdobeReaderGroupName)); |
| 68 return true; |
| 69 } |
| 70 |
| 71 virtual bool Cancel() { |
| 72 UserMetrics::RecordAction( |
| 73 UserMetricsAction("PDF_EnableReaderInfoBarCancel")); |
| 74 return true; |
| 75 } |
| 76 |
| 77 virtual int GetButtons() const { |
| 78 return BUTTON_OK | BUTTON_CANCEL; |
| 79 } |
| 80 |
| 81 virtual string16 GetButtonLabel(InfoBarButton button) const { |
| 82 switch (button) { |
| 83 case BUTTON_OK: |
| 84 return l10n_util::GetStringUTF16( |
| 85 IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL); |
| 86 case BUTTON_CANCEL: |
| 87 return l10n_util::GetStringUTF16( |
| 88 IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL); |
| 89 default: |
| 90 // All buttons are labeled above. |
| 91 NOTREACHED() << "Bad button id " << button; |
| 92 return string16(); |
| 93 } |
| 94 } |
| 95 |
| 96 virtual string16 GetMessageText() const { |
| 97 return l10n_util::GetStringUTF16( |
| 98 IDS_PDF_INFOBAR_QUESTION_ALWAYS_USE_READER); |
| 99 } |
| 100 |
| 101 private: |
| 102 DISALLOW_IMPLICIT_CONSTRUCTORS(PDFEnableAdobeReaderConfirmInfoBarDelegate); |
| 103 }; |
| 104 |
34 // Launch the url to get the latest Adbobe Reader installer. | 105 // Launch the url to get the latest Adbobe Reader installer. |
35 void OpenReaderUpdateURL(TabContents* tab) { | 106 void OpenReaderUpdateURL(TabContents* tab) { |
36 tab->OpenURL(GURL(PluginGroup::kAdobeReaderUpdateURL), GURL(), CURRENT_TAB, | 107 tab->OpenURL(GURL(PluginGroup::kAdobeReaderUpdateURL), GURL(), CURRENT_TAB, |
37 PageTransition::LINK); | 108 PageTransition::LINK); |
38 } | 109 } |
39 | 110 |
40 // Opens the PDF using Adobe Reader. | 111 // Opens the PDF using Adobe Reader. |
41 void OpenUsingReader(TabContents* tab, const WebPluginInfo& reader_plugin) { | 112 void OpenUsingReader(TabContents* tab, |
| 113 const WebPluginInfo& reader_plugin, |
| 114 InfoBarDelegate* old_delegate) { |
42 PluginService::OverriddenPlugin plugin; | 115 PluginService::OverriddenPlugin plugin; |
43 plugin.render_process_id = tab->GetRenderProcessHost()->id(); | 116 plugin.render_process_id = tab->GetRenderProcessHost()->id(); |
44 plugin.render_view_id = tab->render_view_host()->routing_id(); | 117 plugin.render_view_id = tab->render_view_host()->routing_id(); |
45 plugin.url = tab->GetURL(); | 118 plugin.url = tab->GetURL(); |
46 plugin.plugin = reader_plugin; | 119 plugin.plugin = reader_plugin; |
| 120 // The plugin is disabled, so enable it to get around the renderer check. |
| 121 // Also give it a new version so that the renderer doesn't show the blocked |
| 122 // plugin UI if it's vulnerable, since we already went through the |
| 123 // interstitial. |
| 124 plugin.plugin.enabled = WebPluginInfo::USER_ENABLED; |
| 125 plugin.plugin.version = ASCIIToUTF16("11.0.0.0"); |
47 | 126 |
48 PluginService::GetInstance()->OverridePluginForTab(plugin); | 127 PluginService::GetInstance()->OverridePluginForTab(plugin); |
49 tab->render_view_host()->ReloadFrame(); | 128 tab->render_view_host()->ReloadFrame(); |
| 129 |
| 130 InfoBarDelegate* bar = new PDFEnableAdobeReaderConfirmInfoBarDelegate(tab); |
| 131 if (old_delegate) { |
| 132 tab->ReplaceInfoBar(old_delegate, bar); |
| 133 } else { |
| 134 tab->AddInfoBar(bar); |
| 135 } |
50 } | 136 } |
51 | 137 |
52 // An interstitial to be used when the user chooses to open a PDF using Adobe | 138 // An interstitial to be used when the user chooses to open a PDF using Adobe |
53 // Reader, but it is out of date. | 139 // Reader, but it is out of date. |
54 class PDFUnsupportedFeatureInterstitial : public InterstitialPage { | 140 class PDFUnsupportedFeatureInterstitial : public InterstitialPage { |
55 public: | 141 public: |
56 PDFUnsupportedFeatureInterstitial( | 142 PDFUnsupportedFeatureInterstitial( |
57 TabContents* tab, | 143 TabContents* tab, |
58 const WebPluginInfo& reader_webplugininfo) | 144 const WebPluginInfo& reader_webplugininfo) |
59 : InterstitialPage(tab, false, tab->GetURL()), | 145 : InterstitialPage(tab, false, tab->GetURL()), |
60 reader_webplugininfo_(reader_webplugininfo) { | 146 reader_webplugininfo_(reader_webplugininfo) { |
| 147 UserMetrics::RecordAction(UserMetricsAction("PDF_ReaderInterstitialShown")); |
61 } | 148 } |
62 | 149 |
63 protected: | 150 protected: |
64 // InterstitialPage implementation. | 151 // InterstitialPage implementation. |
65 virtual std::string GetHTMLContents() { | 152 virtual std::string GetHTMLContents() { |
66 DictionaryValue strings; | 153 DictionaryValue strings; |
67 strings.SetString( | 154 strings.SetString( |
68 "title", | 155 "title", |
69 l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_TITLE)); | 156 l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_TITLE)); |
70 strings.SetString( | 157 strings.SetString( |
(...skipping 14 matching lines...) Expand all Loading... |
85 l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_CANCEL)); | 172 l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_CANCEL)); |
86 | 173 |
87 base::StringPiece html(ResourceBundle::GetSharedInstance(). | 174 base::StringPiece html(ResourceBundle::GetSharedInstance(). |
88 GetRawDataResource(IDR_READER_OUT_OF_DATE_HTML)); | 175 GetRawDataResource(IDR_READER_OUT_OF_DATE_HTML)); |
89 | 176 |
90 return jstemplate_builder::GetI18nTemplateHtml(html, &strings); | 177 return jstemplate_builder::GetI18nTemplateHtml(html, &strings); |
91 } | 178 } |
92 | 179 |
93 virtual void CommandReceived(const std::string& command) { | 180 virtual void CommandReceived(const std::string& command) { |
94 if (command == "0") { | 181 if (command == "0") { |
| 182 UserMetrics::RecordAction( |
| 183 UserMetricsAction("PDF_ReaderInterstitialCancel")); |
95 DontProceed(); | 184 DontProceed(); |
96 return; | 185 return; |
97 } | 186 } |
98 | 187 |
99 if (command == "1") { | 188 if (command == "1") { |
| 189 UserMetrics::RecordAction( |
| 190 UserMetricsAction("PDF_ReaderInterstitialUpdate")); |
100 OpenReaderUpdateURL(tab()); | 191 OpenReaderUpdateURL(tab()); |
101 } else if (command == "2") { | 192 } else if (command == "2") { |
102 OpenUsingReader(tab(), reader_webplugininfo_); | 193 UserMetrics::RecordAction( |
| 194 UserMetricsAction("PDF_ReaderInterstitialIgnore")); |
| 195 OpenUsingReader(tab(), reader_webplugininfo_, NULL); |
103 } else { | 196 } else { |
104 NOTREACHED(); | 197 NOTREACHED(); |
105 } | 198 } |
106 Proceed(); | 199 Proceed(); |
107 } | 200 } |
108 | 201 |
109 private: | 202 private: |
110 WebPluginInfo reader_webplugininfo_; | 203 WebPluginInfo reader_webplugininfo_; |
111 | 204 |
112 DISALLOW_COPY_AND_ASSIGN(PDFUnsupportedFeatureInterstitial); | 205 DISALLOW_COPY_AND_ASSIGN(PDFUnsupportedFeatureInterstitial); |
113 }; | 206 }; |
114 | 207 |
115 // The info bar delegate used to inform the user that we don't support a feature | 208 // The info bar delegate used to inform the user that we don't support a feature |
116 // in the PDF. | 209 // in the PDF. |
117 class PDFUnsupportedFeatureConfirmInfoBarDelegate | 210 class PDFUnsupportedFeatureConfirmInfoBarDelegate |
118 : public ConfirmInfoBarDelegate { | 211 : public ConfirmInfoBarDelegate { |
119 public: | 212 public: |
120 PDFUnsupportedFeatureConfirmInfoBarDelegate( | 213 PDFUnsupportedFeatureConfirmInfoBarDelegate( |
121 TabContents* tab_contents, | 214 TabContents* tab_contents, |
122 PluginGroup* reader_group) // NULL if Adobe Reader isn't installed. | 215 PluginGroup* reader_group) // NULL if Adobe Reader isn't installed. |
123 : ConfirmInfoBarDelegate(tab_contents), | 216 : ConfirmInfoBarDelegate(tab_contents), |
124 tab_contents_(tab_contents), | 217 tab_contents_(tab_contents), |
125 reader_installed_(!!reader_group), | 218 reader_installed_(!!reader_group), |
126 reader_vulnerable_(false) { | 219 reader_vulnerable_(false) { |
127 if (reader_installed_) { | 220 if (reader_installed_) { |
| 221 UserMetrics::RecordAction(UserMetricsAction("PDF_UseReaderInfoBarShown")); |
128 std::vector<WebPluginInfo> plugins = reader_group->web_plugin_infos(); | 222 std::vector<WebPluginInfo> plugins = reader_group->web_plugin_infos(); |
129 DCHECK_EQ(plugins.size(), 1u); | 223 DCHECK_EQ(plugins.size(), 1u); |
130 reader_webplugininfo_ = plugins[0]; | 224 reader_webplugininfo_ = plugins[0]; |
131 | 225 |
132 reader_vulnerable_ = reader_group->IsVulnerable(); | 226 reader_vulnerable_ = reader_group->IsVulnerable(); |
133 if (!reader_vulnerable_) { | 227 if (!reader_vulnerable_) { |
134 scoped_ptr<Version> version(PluginGroup::CreateVersionFromString( | 228 scoped_ptr<Version> version(PluginGroup::CreateVersionFromString( |
135 reader_webplugininfo_.version)); | 229 reader_webplugininfo_.version)); |
136 if (version.get()) { | 230 if (version.get()) { |
137 if (version->components()[0] < kMinReaderVersionToUse) | 231 if (version->components()[0] < kMinReaderVersionToUse) |
138 reader_vulnerable_ = true; | 232 reader_vulnerable_ = true; |
139 } | 233 } |
140 } | 234 } |
| 235 } else { |
| 236 UserMetrics::RecordAction( |
| 237 UserMetricsAction("PDF_InstallReaderInfoBarShown")); |
141 } | 238 } |
142 } | 239 } |
143 | 240 |
144 // ConfirmInfoBarDelegate | 241 // ConfirmInfoBarDelegate |
145 virtual void InfoBarClosed() { | 242 virtual void InfoBarClosed() { |
146 delete this; | 243 delete this; |
147 } | 244 } |
148 virtual Type GetInfoBarType() { | 245 |
| 246 virtual void InfoBarDismissed() { |
| 247 Cancel(); |
| 248 } |
| 249 |
| 250 virtual Type GetInfoBarType() const { |
149 return PAGE_ACTION_TYPE; | 251 return PAGE_ACTION_TYPE; |
150 } | 252 } |
| 253 |
151 virtual bool Accept() { | 254 virtual bool Accept() { |
152 LaunchReader(); | 255 if (!reader_installed_) { |
| 256 UserMetrics::RecordAction( |
| 257 UserMetricsAction("PDF_InstallReaderInfoBarOK")); |
| 258 OpenReaderUpdateURL(tab_contents_); |
| 259 return true; |
| 260 } |
| 261 |
| 262 UserMetrics::RecordAction( |
| 263 UserMetricsAction("PDF_UseReaderInfoBarOK")); |
| 264 |
| 265 if (reader_vulnerable_) { |
| 266 PDFUnsupportedFeatureInterstitial* interstitial = new |
| 267 PDFUnsupportedFeatureInterstitial( |
| 268 tab_contents_, reader_webplugininfo_); |
| 269 interstitial->Show(); |
| 270 return true; |
| 271 } |
| 272 |
| 273 OpenUsingReader(tab_contents_, reader_webplugininfo_, this); |
| 274 return false; |
| 275 } |
| 276 |
| 277 virtual bool Cancel() { |
| 278 if (reader_installed_) { |
| 279 UserMetrics::RecordAction( |
| 280 UserMetricsAction("PDF_UseReaderInfoBarCancel")); |
| 281 } else { |
| 282 UserMetrics::RecordAction( |
| 283 UserMetricsAction("PDF_InstallReaderInfoBarCancel")); |
| 284 } |
153 return true; | 285 return true; |
154 } | 286 } |
| 287 |
155 virtual int GetButtons() const { | 288 virtual int GetButtons() const { |
156 return BUTTON_OK | BUTTON_CANCEL; | 289 return BUTTON_OK | BUTTON_CANCEL; |
157 } | 290 } |
| 291 |
158 virtual string16 GetButtonLabel(InfoBarButton button) const { | 292 virtual string16 GetButtonLabel(InfoBarButton button) const { |
159 switch (button) { | 293 switch (button) { |
160 case BUTTON_OK: | 294 case BUTTON_OK: |
161 return l10n_util::GetStringUTF16( | 295 return l10n_util::GetStringUTF16( |
162 IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL); | 296 IDS_CONFIRM_MESSAGEBOX_YES_BUTTON_LABEL); |
163 case BUTTON_CANCEL: | 297 case BUTTON_CANCEL: |
164 return l10n_util::GetStringUTF16( | 298 return l10n_util::GetStringUTF16( |
165 IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL); | 299 IDS_CONFIRM_MESSAGEBOX_NO_BUTTON_LABEL); |
166 default: | 300 default: |
167 // All buttons are labeled above. | 301 // All buttons are labeled above. |
168 NOTREACHED() << "Bad button id " << button; | 302 NOTREACHED() << "Bad button id " << button; |
169 return string16(); | 303 return string16(); |
170 } | 304 } |
171 } | 305 } |
| 306 |
172 virtual string16 GetMessageText() const { | 307 virtual string16 GetMessageText() const { |
173 return l10n_util::GetStringUTF16(reader_installed_ ? | 308 return l10n_util::GetStringUTF16(reader_installed_ ? |
174 IDS_PDF_INFOBAR_QUESTION_READER_INSTALLED : | 309 IDS_PDF_INFOBAR_QUESTION_READER_INSTALLED : |
175 IDS_PDF_INFOBAR_QUESTION_READER_NOT_INSTALLED); | 310 IDS_PDF_INFOBAR_QUESTION_READER_NOT_INSTALLED); |
176 } | 311 } |
177 | 312 |
178 private: | 313 private: |
179 void LaunchReader() { | |
180 if (!reader_installed_) { | |
181 OpenReaderUpdateURL(tab_contents_); | |
182 return; | |
183 } | |
184 | |
185 if (reader_vulnerable_) { | |
186 PDFUnsupportedFeatureInterstitial* interstitial = new | |
187 PDFUnsupportedFeatureInterstitial( | |
188 tab_contents_, reader_webplugininfo_); | |
189 interstitial->Show(); | |
190 return; | |
191 } | |
192 | |
193 OpenUsingReader(tab_contents_, reader_webplugininfo_); | |
194 } | |
195 | |
196 TabContents* tab_contents_; | 314 TabContents* tab_contents_; |
197 bool reader_installed_; | 315 bool reader_installed_; |
198 bool reader_vulnerable_; | 316 bool reader_vulnerable_; |
199 WebPluginInfo reader_webplugininfo_; | 317 WebPluginInfo reader_webplugininfo_; |
200 | 318 |
201 DISALLOW_IMPLICIT_CONSTRUCTORS(PDFUnsupportedFeatureConfirmInfoBarDelegate); | 319 DISALLOW_IMPLICIT_CONSTRUCTORS(PDFUnsupportedFeatureConfirmInfoBarDelegate); |
202 }; | 320 }; |
203 | 321 |
204 } // namespace | 322 } // namespace |
205 | 323 |
206 void PDFHasUnsupportedFeature(TabContents* tab) { | 324 void PDFHasUnsupportedFeature(TabContents* tab) { |
207 #if !defined(OS_WIN) | 325 #if !defined(OS_WIN) |
208 // Only works for Windows for now. For Mac, we'll have to launch the file | 326 // Only works for Windows for now. For Mac, we'll have to launch the file |
209 // externally since Adobe Reader doesn't work inside Chrome. | 327 // externally since Adobe Reader doesn't work inside Chrome. |
210 return; | 328 return; |
211 #endif | 329 #endif |
| 330 string16 reader_group_name(ASCIIToUTF16(PluginGroup::kAdobeReaderGroupName)); |
| 331 |
| 332 // If the Reader plugin is disabled by policy, don't prompt them. |
| 333 if (PluginGroup::IsPluginNameDisabledByPolicy(reader_group_name)) |
| 334 return; |
212 | 335 |
213 PluginGroup* reader_group = NULL; | 336 PluginGroup* reader_group = NULL; |
214 std::vector<PluginGroup> plugin_groups; | 337 std::vector<PluginGroup> plugin_groups; |
215 PluginList::Singleton()->GetPluginGroups( | 338 PluginList::Singleton()->GetPluginGroups( |
216 false, &plugin_groups); | 339 false, &plugin_groups); |
217 string16 reader_group_name(UTF8ToUTF16(PluginGroup::kAdobeReaderGroupName)); | |
218 for (size_t i = 0; i < plugin_groups.size(); ++i) { | 340 for (size_t i = 0; i < plugin_groups.size(); ++i) { |
219 if (plugin_groups[i].GetGroupName() == reader_group_name) { | 341 if (plugin_groups[i].GetGroupName() == reader_group_name) { |
220 reader_group = &plugin_groups[i]; | 342 reader_group = &plugin_groups[i]; |
221 break; | 343 break; |
222 } | 344 } |
223 } | 345 } |
224 | 346 |
225 // If the plugin is disabled by policy or by the user, don't prompt them. | |
226 if (reader_group && !reader_group->Enabled()) | |
227 return; | |
228 | |
229 tab->AddInfoBar(new PDFUnsupportedFeatureConfirmInfoBarDelegate( | 347 tab->AddInfoBar(new PDFUnsupportedFeatureConfirmInfoBarDelegate( |
230 tab, reader_group)); | 348 tab, reader_group)); |
231 } | 349 } |
OLD | NEW |