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