OLD | NEW |
| (Empty) |
1 // Copyright (c) 2012 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. | |
4 | |
5 #include "chrome/browser/ui/pdf/pdf_unsupported_feature.h" | |
6 | |
7 #include <memory> | |
8 #include <utility> | |
9 | |
10 #include "base/bind.h" | |
11 #include "base/macros.h" | |
12 #include "base/memory/ptr_util.h" | |
13 #include "base/strings/utf_string_conversions.h" | |
14 #include "build/build_config.h" | |
15 #include "chrome/browser/lifetime/application_lifetime.h" | |
16 #include "chrome/browser/plugins/chrome_plugin_service_filter.h" | |
17 #include "chrome/browser/plugins/plugin_metadata.h" | |
18 #include "chrome/browser/plugins/plugin_prefs.h" | |
19 #include "chrome/browser/profiles/profile.h" | |
20 #include "chrome/browser/renderer_preferences_util.h" | |
21 #include "chrome/browser/tab_contents/tab_util.h" | |
22 #include "chrome/common/chrome_content_client.h" | |
23 #include "chrome/grit/browser_resources.h" | |
24 #include "chrome/grit/generated_resources.h" | |
25 #include "components/pdf/browser/open_pdf_in_reader_prompt_client.h" | |
26 #include "components/pdf/browser/pdf_web_contents_helper.h" | |
27 #include "components/strings/grit/components_strings.h" | |
28 #include "content/public/browser/interstitial_page.h" | |
29 #include "content/public/browser/interstitial_page_delegate.h" | |
30 #include "content/public/browser/navigation_details.h" | |
31 #include "content/public/browser/navigation_entry.h" | |
32 #include "content/public/browser/page_navigator.h" | |
33 #include "content/public/browser/render_frame_host.h" | |
34 #include "content/public/browser/render_process_host.h" | |
35 #include "content/public/browser/render_view_host.h" | |
36 #include "content/public/browser/user_metrics.h" | |
37 #include "content/public/browser/web_contents.h" | |
38 #include "content/public/common/renderer_preferences.h" | |
39 #include "ui/base/l10n/l10n_util.h" | |
40 #include "ui/base/resource/resource_bundle.h" | |
41 #include "ui/base/webui/jstemplate_builder.h" | |
42 | |
43 #if defined(OS_WIN) | |
44 #include "chrome/browser/ui/pdf/adobe_reader_info_win.h" | |
45 #endif | |
46 | |
47 using base::UserMetricsAction; | |
48 using content::InterstitialPage; | |
49 using content::OpenURLParams; | |
50 using content::Referrer; | |
51 using content::WebContents; | |
52 using content::WebPluginInfo; | |
53 | |
54 #if defined(OS_WIN) | |
55 namespace { | |
56 | |
57 const char kAdobeReaderUpdateUrl[] = "http://www.adobe.com/go/getreader_chrome"; | |
58 | |
59 // The prompt delegate used to ask the user if they want to use Adobe Reader | |
60 // by default. | |
61 class PDFEnableAdobeReaderPromptClient | |
62 : public pdf::OpenPDFInReaderPromptClient { | |
63 public: | |
64 explicit PDFEnableAdobeReaderPromptClient(Profile* profile); | |
65 ~PDFEnableAdobeReaderPromptClient() override; | |
66 | |
67 // pdf::OpenPDFInReaderPromptClient | |
68 base::string16 GetMessageText() const override; | |
69 base::string16 GetAcceptButtonText() const override; | |
70 base::string16 GetCancelButtonText() const override; | |
71 bool ShouldExpire( | |
72 const content::LoadCommittedDetails& details) const override; | |
73 void Accept() override; | |
74 void Cancel() override; | |
75 | |
76 private: | |
77 void OnYes(); | |
78 void OnNo(); | |
79 | |
80 Profile* profile_; | |
81 | |
82 DISALLOW_IMPLICIT_CONSTRUCTORS(PDFEnableAdobeReaderPromptClient); | |
83 }; | |
84 | |
85 PDFEnableAdobeReaderPromptClient::PDFEnableAdobeReaderPromptClient( | |
86 Profile* profile) | |
87 : profile_(profile) { | |
88 content::RecordAction(UserMetricsAction("PDF_EnableReaderInfoBarShown")); | |
89 } | |
90 | |
91 PDFEnableAdobeReaderPromptClient::~PDFEnableAdobeReaderPromptClient() { | |
92 } | |
93 | |
94 bool PDFEnableAdobeReaderPromptClient::ShouldExpire( | |
95 const content::LoadCommittedDetails& details) const { | |
96 ui::PageTransition transition = | |
97 ui::PageTransitionStripQualifier(details.entry->GetTransitionType()); | |
98 // We don't want to expire on a reload, because that is how we open the PDF in | |
99 // Reader. | |
100 return !details.is_in_page && | |
101 !ui::PageTransitionCoreTypeIs(transition, ui::PAGE_TRANSITION_RELOAD); | |
102 } | |
103 | |
104 void PDFEnableAdobeReaderPromptClient::Accept() { | |
105 content::RecordAction(UserMetricsAction("PDF_EnableReaderInfoBarOK")); | |
106 PluginPrefs* plugin_prefs = PluginPrefs::GetForProfile(profile_).get(); | |
107 plugin_prefs->EnablePluginGroup( | |
108 true, base::ASCIIToUTF16(PluginMetadata::kAdobeReaderGroupName)); | |
109 plugin_prefs->EnablePluginGroup( | |
110 false, base::ASCIIToUTF16(ChromeContentClient::kPDFPluginName)); | |
111 } | |
112 | |
113 void PDFEnableAdobeReaderPromptClient::Cancel() { | |
114 content::RecordAction(UserMetricsAction("PDF_EnableReaderInfoBarCancel")); | |
115 } | |
116 | |
117 base::string16 PDFEnableAdobeReaderPromptClient::GetAcceptButtonText() const { | |
118 return l10n_util::GetStringUTF16(IDS_PDF_INFOBAR_ALWAYS_USE_READER_BUTTON); | |
119 } | |
120 | |
121 base::string16 PDFEnableAdobeReaderPromptClient::GetCancelButtonText() const { | |
122 return l10n_util::GetStringUTF16(IDS_DONE); | |
123 } | |
124 | |
125 base::string16 PDFEnableAdobeReaderPromptClient::GetMessageText() const { | |
126 return l10n_util::GetStringUTF16(IDS_PDF_INFOBAR_QUESTION_ALWAYS_USE_READER); | |
127 } | |
128 | |
129 // Launch the url to get the latest Adbobe Reader installer. | |
130 void OpenReaderUpdateURL(WebContents* web_contents) { | |
131 OpenURLParams params(GURL(kAdobeReaderUpdateUrl), Referrer(), | |
132 WindowOpenDisposition::NEW_FOREGROUND_TAB, | |
133 ui::PAGE_TRANSITION_LINK, false); | |
134 web_contents->OpenURL(params); | |
135 } | |
136 | |
137 // Opens the PDF using Adobe Reader. | |
138 void OpenUsingReader(WebContents* web_contents, | |
139 const WebPluginInfo& reader_plugin, | |
140 pdf::OpenPDFInReaderPromptClient* client) { | |
141 ChromePluginServiceFilter::GetInstance()->OverridePluginForFrame( | |
142 web_contents->GetRenderProcessHost()->GetID(), | |
143 web_contents->GetMainFrame()->GetRoutingID(), | |
144 web_contents->GetURL(), | |
145 reader_plugin); | |
146 web_contents->ReloadFocusedFrame(false); | |
147 | |
148 pdf::PDFWebContentsHelper* pdf_tab_helper = | |
149 pdf::PDFWebContentsHelper::FromWebContents(web_contents); | |
150 if (client) | |
151 pdf_tab_helper->ShowOpenInReaderPrompt(base::WrapUnique(client)); | |
152 } | |
153 | |
154 // An interstitial to be used when the user chooses to open a PDF using Adobe | |
155 // Reader, but it is out of date. | |
156 class PDFUnsupportedFeatureInterstitial | |
157 : public content::InterstitialPageDelegate { | |
158 public: | |
159 PDFUnsupportedFeatureInterstitial( | |
160 WebContents* web_contents, | |
161 const WebPluginInfo& reader_webplugininfo) | |
162 : web_contents_(web_contents), | |
163 reader_webplugininfo_(reader_webplugininfo) { | |
164 content::RecordAction(UserMetricsAction("PDF_ReaderInterstitialShown")); | |
165 interstitial_page_ = InterstitialPage::Create( | |
166 web_contents, false, web_contents->GetURL(), this); | |
167 interstitial_page_->Show(); | |
168 } | |
169 | |
170 protected: | |
171 // InterstitialPageDelegate implementation. | |
172 std::string GetHTMLContents() override { | |
173 base::DictionaryValue strings; | |
174 strings.SetString( | |
175 "title", | |
176 l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_TITLE)); | |
177 strings.SetString( | |
178 "headLine", | |
179 l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_BODY)); | |
180 strings.SetString( | |
181 "update", | |
182 l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_UPDATE)); | |
183 strings.SetString( | |
184 "open_with_reader", | |
185 l10n_util::GetStringUTF16( | |
186 IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_PROCEED)); | |
187 strings.SetString( | |
188 "ok", | |
189 l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_OK)); | |
190 strings.SetString( | |
191 "cancel", | |
192 l10n_util::GetStringUTF16(IDS_READER_OUT_OF_DATE_BLOCKING_PAGE_CANCEL)); | |
193 | |
194 base::StringPiece html(ResourceBundle::GetSharedInstance(). | |
195 GetRawDataResource(IDR_READER_OUT_OF_DATE_HTML)); | |
196 | |
197 return webui::GetI18nTemplateHtml(html, &strings); | |
198 } | |
199 | |
200 void CommandReceived(const std::string& command) override { | |
201 if (command == "0") { | |
202 content::RecordAction( | |
203 UserMetricsAction("PDF_ReaderInterstitialCancel")); | |
204 interstitial_page_->DontProceed(); | |
205 return; | |
206 } | |
207 | |
208 if (command == "1") { | |
209 content::RecordAction( | |
210 UserMetricsAction("PDF_ReaderInterstitialUpdate")); | |
211 OpenReaderUpdateURL(web_contents_); | |
212 } else if (command == "2") { | |
213 content::RecordAction( | |
214 UserMetricsAction("PDF_ReaderInterstitialIgnore")); | |
215 // Pretend that the plugin is up to date so that we don't block it. | |
216 reader_webplugininfo_.version = base::ASCIIToUTF16("11.0.0.0"); | |
217 OpenUsingReader(web_contents_, reader_webplugininfo_, NULL); | |
218 } else { | |
219 NOTREACHED(); | |
220 } | |
221 interstitial_page_->Proceed(); | |
222 } | |
223 | |
224 void OverrideRendererPrefs(content::RendererPreferences* prefs) override { | |
225 Profile* profile = | |
226 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); | |
227 renderer_preferences_util::UpdateFromSystemSettings( | |
228 prefs, profile, web_contents_); | |
229 } | |
230 | |
231 private: | |
232 WebContents* web_contents_; | |
233 WebPluginInfo reader_webplugininfo_; | |
234 InterstitialPage* interstitial_page_; // Owns us. | |
235 | |
236 DISALLOW_COPY_AND_ASSIGN(PDFUnsupportedFeatureInterstitial); | |
237 }; | |
238 | |
239 // The delegate for the bubble used to inform the user that we don't support a | |
240 // feature in the PDF. | |
241 class PDFUnsupportedFeaturePromptClient | |
242 : public pdf::OpenPDFInReaderPromptClient { | |
243 public: | |
244 PDFUnsupportedFeaturePromptClient(WebContents* web_contents, | |
245 const AdobeReaderPluginInfo& reader_info); | |
246 ~PDFUnsupportedFeaturePromptClient() override; | |
247 | |
248 // pdf::OpenPDFInReaderPromptClient: | |
249 base::string16 GetMessageText() const override; | |
250 base::string16 GetAcceptButtonText() const override; | |
251 base::string16 GetCancelButtonText() const override; | |
252 bool ShouldExpire( | |
253 const content::LoadCommittedDetails& details) const override; | |
254 void Accept() override; | |
255 void Cancel() override; | |
256 | |
257 private: | |
258 WebContents* web_contents_; | |
259 const AdobeReaderPluginInfo reader_info_; | |
260 | |
261 DISALLOW_IMPLICIT_CONSTRUCTORS(PDFUnsupportedFeaturePromptClient); | |
262 }; | |
263 | |
264 PDFUnsupportedFeaturePromptClient::PDFUnsupportedFeaturePromptClient( | |
265 WebContents* web_contents, | |
266 const AdobeReaderPluginInfo& reader_info) | |
267 : web_contents_(web_contents), reader_info_(reader_info) { | |
268 content::RecordAction(reader_info_.is_installed ? | |
269 UserMetricsAction("PDF_UseReaderInfoBarShown") : | |
270 UserMetricsAction("PDF_InstallReaderInfoBarShown")); | |
271 } | |
272 | |
273 PDFUnsupportedFeaturePromptClient::~PDFUnsupportedFeaturePromptClient() { | |
274 } | |
275 | |
276 base::string16 PDFUnsupportedFeaturePromptClient::GetMessageText() const { | |
277 return l10n_util::GetStringUTF16(IDS_PDF_BUBBLE_MESSAGE); | |
278 } | |
279 | |
280 base::string16 PDFUnsupportedFeaturePromptClient::GetAcceptButtonText() const { | |
281 return l10n_util::GetStringUTF16( | |
282 reader_info_.is_installed ? IDS_PDF_BUBBLE_OPEN_IN_READER_LINK | |
283 : IDS_PDF_BUBBLE_INSTALL_READER_LINK); | |
284 } | |
285 | |
286 base::string16 PDFUnsupportedFeaturePromptClient::GetCancelButtonText() const { | |
287 return l10n_util::GetStringUTF16(IDS_DONE); | |
288 } | |
289 | |
290 bool PDFUnsupportedFeaturePromptClient::ShouldExpire( | |
291 const content::LoadCommittedDetails& details) const { | |
292 return !details.is_in_page; | |
293 } | |
294 | |
295 void PDFUnsupportedFeaturePromptClient::Accept() { | |
296 if (!reader_info_.is_installed) { | |
297 content::RecordAction(UserMetricsAction("PDF_InstallReaderInfoBarOK")); | |
298 OpenReaderUpdateURL(web_contents_); | |
299 return; | |
300 } | |
301 | |
302 content::RecordAction(UserMetricsAction("PDF_UseReaderInfoBarOK")); | |
303 | |
304 if (!reader_info_.is_secure) { | |
305 new PDFUnsupportedFeatureInterstitial(web_contents_, | |
306 reader_info_.plugin_info); | |
307 return; | |
308 } | |
309 | |
310 Profile* profile = | |
311 Profile::FromBrowserContext(web_contents_->GetBrowserContext()); | |
312 pdf::OpenPDFInReaderPromptClient* client = | |
313 new PDFEnableAdobeReaderPromptClient(profile); | |
314 | |
315 OpenUsingReader(web_contents_, reader_info_.plugin_info, client); | |
316 } | |
317 | |
318 void PDFUnsupportedFeaturePromptClient::Cancel() { | |
319 content::RecordAction(reader_info_.is_installed ? | |
320 UserMetricsAction("PDF_UseReaderInfoBarCancel") : | |
321 UserMetricsAction("PDF_InstallReaderInfoBarCancel")); | |
322 } | |
323 | |
324 void MaybeShowOpenPDFInReaderPrompt(WebContents* web_contents, | |
325 const AdobeReaderPluginInfo& reader_info) { | |
326 // If the Reader plugin is disabled by policy, don't prompt them. | |
327 if (!reader_info.is_installed || !reader_info.is_enabled) | |
328 return; | |
329 | |
330 std::unique_ptr<pdf::OpenPDFInReaderPromptClient> prompt( | |
331 new PDFUnsupportedFeaturePromptClient(web_contents, reader_info)); | |
332 pdf::PDFWebContentsHelper* pdf_tab_helper = | |
333 pdf::PDFWebContentsHelper::FromWebContents(web_contents); | |
334 pdf_tab_helper->ShowOpenInReaderPrompt(std::move(prompt)); | |
335 } | |
336 | |
337 void GotPluginsCallback(int process_id, | |
338 int routing_id, | |
339 const AdobeReaderPluginInfo& reader_info) { | |
340 WebContents* web_contents = | |
341 tab_util::GetWebContentsByID(process_id, routing_id); | |
342 if (web_contents) | |
343 MaybeShowOpenPDFInReaderPrompt(web_contents, reader_info); | |
344 } | |
345 | |
346 } // namespace | |
347 #endif // defined(OS_WIN) | |
348 | |
349 void PDFHasUnsupportedFeature(WebContents* web_contents) { | |
350 #if defined(OS_WIN) | |
351 // Only works for Windows for now. For Mac, we'll have to launch the file | |
352 // externally since Adobe Reader doesn't work inside Chrome. | |
353 Profile* profile = | |
354 Profile::FromBrowserContext(web_contents->GetBrowserContext()); | |
355 AdobeReaderPluginInfo reader_info; | |
356 if (GetAdobeReaderPluginInfo(profile, &reader_info)) { | |
357 MaybeShowOpenPDFInReaderPrompt(web_contents, reader_info); | |
358 return; | |
359 } | |
360 GetAdobeReaderPluginInfoAsync( | |
361 profile, | |
362 base::Bind(&GotPluginsCallback, | |
363 web_contents->GetRenderProcessHost()->GetID(), | |
364 web_contents->GetRenderViewHost()->GetRoutingID())); | |
365 #endif // defined(OS_WIN) | |
366 } | |
OLD | NEW |