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/plugins/plugin_infobar_delegates.h"
8 #include "base/path_service.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/browser/content_settings/host_content_settings_map.h"
11 #include "chrome/browser/google/google_util.h"
12 #include "chrome/browser/infobars/infobar.h"
13 #include "chrome/browser/infobars/infobar_service.h"
14 #include "chrome/browser/lifetime/application_lifetime.h"
15 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
16 #include "chrome/browser/plugins/plugin_metadata.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/shell_integration.h"
19 #include "chrome/browser/ui/browser_commands.h"
20 #include "chrome/common/url_constants.h"
21 #include "content/public/browser/render_process_host.h"
22 #include "content/public/browser/render_view_host.h"
23 #include "content/public/browser/user_metrics.h"
24 #include "content/public/browser/web_contents.h"
25 #include "grit/generated_resources.h"
26 #include "grit/locale_settings.h"
27 #include "grit/theme_resources.h"
28 #include "ui/base/l10n/l10n_util.h"
30 #if defined(ENABLE_PLUGIN_INSTALLATION)
32 #include "base/win/metro.h"
34 #include "chrome/browser/plugins/plugin_installer.h"
39 #include "ui/base/win/shell.h"
42 #include "ui/aura/remote_window_tree_host_win.h"
46 using base::UserMetricsAction;
49 // PluginInfoBarDelegate ------------------------------------------------------
51 PluginInfoBarDelegate::PluginInfoBarDelegate(const std::string& identifier)
52 : ConfirmInfoBarDelegate(),
53 identifier_(identifier) {
56 PluginInfoBarDelegate::~PluginInfoBarDelegate() {
59 bool PluginInfoBarDelegate::LinkClicked(WindowOpenDisposition disposition) {
60 web_contents()->OpenURL(content::OpenURLParams(
61 GURL(GetLearnMoreURL()), content::Referrer(),
62 (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
63 content::PAGE_TRANSITION_LINK, false));
67 void PluginInfoBarDelegate::LoadBlockedPlugins() {
68 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
69 web_contents(), true, identifier_);
72 int PluginInfoBarDelegate::GetIconID() const {
73 return IDR_INFOBAR_PLUGIN_INSTALL;
76 base::string16 PluginInfoBarDelegate::GetLinkText() const {
77 return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
81 // UnauthorizedPluginInfoBarDelegate ------------------------------------------
84 void UnauthorizedPluginInfoBarDelegate::Create(
85 InfoBarService* infobar_service,
86 HostContentSettingsMap* content_settings,
87 const base::string16& name,
88 const std::string& identifier) {
89 infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
90 scoped_ptr<ConfirmInfoBarDelegate>(new UnauthorizedPluginInfoBarDelegate(
91 content_settings, name, identifier))));
93 content::RecordAction(UserMetricsAction("BlockedPluginInfobar.Shown"));
94 std::string utf8_name(base::UTF16ToUTF8(name));
95 if (utf8_name == PluginMetadata::kJavaGroupName) {
96 content::RecordAction(UserMetricsAction("BlockedPluginInfobar.Shown.Java"));
97 } else if (utf8_name == PluginMetadata::kQuickTimeGroupName) {
98 content::RecordAction(
99 UserMetricsAction("BlockedPluginInfobar.Shown.QuickTime"));
100 } else if (utf8_name == PluginMetadata::kShockwaveGroupName) {
101 content::RecordAction(
102 UserMetricsAction("BlockedPluginInfobar.Shown.Shockwave"));
103 } else if (utf8_name == PluginMetadata::kRealPlayerGroupName) {
104 content::RecordAction(
105 UserMetricsAction("BlockedPluginInfobar.Shown.RealPlayer"));
106 } else if (utf8_name == PluginMetadata::kWindowsMediaPlayerGroupName) {
107 content::RecordAction(
108 UserMetricsAction("BlockedPluginInfobar.Shown.WindowsMediaPlayer"));
112 UnauthorizedPluginInfoBarDelegate::UnauthorizedPluginInfoBarDelegate(
113 HostContentSettingsMap* content_settings,
114 const base::string16& name,
115 const std::string& identifier)
116 : PluginInfoBarDelegate(identifier),
117 content_settings_(content_settings),
121 UnauthorizedPluginInfoBarDelegate::~UnauthorizedPluginInfoBarDelegate() {
122 content::RecordAction(UserMetricsAction("BlockedPluginInfobar.Closed"));
125 std::string UnauthorizedPluginInfoBarDelegate::GetLearnMoreURL() const {
126 return chrome::kBlockedPluginLearnMoreURL;
129 base::string16 UnauthorizedPluginInfoBarDelegate::GetMessageText() const {
130 return l10n_util::GetStringFUTF16(IDS_PLUGIN_NOT_AUTHORIZED, name_);
133 base::string16 UnauthorizedPluginInfoBarDelegate::GetButtonLabel(
134 InfoBarButton button) const {
135 return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
136 IDS_PLUGIN_ENABLE_TEMPORARILY : IDS_PLUGIN_ENABLE_ALWAYS);
139 bool UnauthorizedPluginInfoBarDelegate::Accept() {
140 content::RecordAction(
141 UserMetricsAction("BlockedPluginInfobar.AllowThisTime"));
142 LoadBlockedPlugins();
146 bool UnauthorizedPluginInfoBarDelegate::Cancel() {
147 content::RecordAction(UserMetricsAction("BlockedPluginInfobar.AlwaysAllow"));
148 const GURL& url = web_contents()->GetURL();
149 content_settings_->AddExceptionForURL(url, url, CONTENT_SETTINGS_TYPE_PLUGINS,
150 CONTENT_SETTING_ALLOW);
151 LoadBlockedPlugins();
155 void UnauthorizedPluginInfoBarDelegate::InfoBarDismissed() {
156 content::RecordAction(UserMetricsAction("BlockedPluginInfobar.Dismissed"));
159 bool UnauthorizedPluginInfoBarDelegate::LinkClicked(
160 WindowOpenDisposition disposition) {
161 content::RecordAction(UserMetricsAction("BlockedPluginInfobar.LearnMore"));
162 return PluginInfoBarDelegate::LinkClicked(disposition);
166 #if defined(ENABLE_PLUGIN_INSTALLATION)
168 // OutdatedPluginInfoBarDelegate ----------------------------------------------
170 void OutdatedPluginInfoBarDelegate::Create(
171 InfoBarService* infobar_service,
172 PluginInstaller* installer,
173 scoped_ptr<PluginMetadata> plugin_metadata) {
174 // Copy the name out of |plugin_metadata| now, since the Pass() call below
175 // will make it impossible to get at.
176 base::string16 name(plugin_metadata->name());
177 infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
178 scoped_ptr<ConfirmInfoBarDelegate>(new OutdatedPluginInfoBarDelegate(
179 installer, plugin_metadata.Pass(), l10n_util::GetStringFUTF16(
180 (installer->state() == PluginInstaller::INSTALLER_STATE_IDLE) ?
181 IDS_PLUGIN_OUTDATED_PROMPT : IDS_PLUGIN_DOWNLOADING,
185 OutdatedPluginInfoBarDelegate::OutdatedPluginInfoBarDelegate(
186 PluginInstaller* installer,
187 scoped_ptr<PluginMetadata> plugin_metadata,
188 const base::string16& message)
189 : PluginInfoBarDelegate(plugin_metadata->identifier()),
190 WeakPluginInstallerObserver(installer),
191 plugin_metadata_(plugin_metadata.Pass()),
193 content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Shown"));
194 std::string name = base::UTF16ToUTF8(plugin_metadata_->name());
195 if (name == PluginMetadata::kJavaGroupName) {
196 content::RecordAction(
197 UserMetricsAction("OutdatedPluginInfobar.Shown.Java"));
198 } else if (name == PluginMetadata::kQuickTimeGroupName) {
199 content::RecordAction(
200 UserMetricsAction("OutdatedPluginInfobar.Shown.QuickTime"));
201 } else if (name == PluginMetadata::kShockwaveGroupName) {
202 content::RecordAction(
203 UserMetricsAction("OutdatedPluginInfobar.Shown.Shockwave"));
204 } else if (name == PluginMetadata::kRealPlayerGroupName) {
205 content::RecordAction(
206 UserMetricsAction("OutdatedPluginInfobar.Shown.RealPlayer"));
207 } else if (name == PluginMetadata::kSilverlightGroupName) {
208 content::RecordAction(
209 UserMetricsAction("OutdatedPluginInfobar.Shown.Silverlight"));
210 } else if (name == PluginMetadata::kAdobeReaderGroupName) {
211 content::RecordAction(
212 UserMetricsAction("OutdatedPluginInfobar.Shown.Reader"));
216 OutdatedPluginInfoBarDelegate::~OutdatedPluginInfoBarDelegate() {
217 content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Closed"));
220 std::string OutdatedPluginInfoBarDelegate::GetLearnMoreURL() const {
221 return chrome::kOutdatedPluginLearnMoreURL;
224 base::string16 OutdatedPluginInfoBarDelegate::GetMessageText() const {
228 base::string16 OutdatedPluginInfoBarDelegate::GetButtonLabel(
229 InfoBarButton button) const {
230 return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
231 IDS_PLUGIN_UPDATE : IDS_PLUGIN_ENABLE_TEMPORARILY);
234 bool OutdatedPluginInfoBarDelegate::Accept() {
235 DCHECK_EQ(PluginInstaller::INSTALLER_STATE_IDLE, installer()->state());
236 content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Update"));
237 // A call to any of |OpenDownloadURL()| or |StartInstalling()| will
238 // result in deleting ourselves. Accordingly, we make sure to
239 // not pass a reference to an object that can go away.
240 GURL plugin_url(plugin_metadata_->plugin_url());
241 if (plugin_metadata_->url_for_display())
242 installer()->OpenDownloadURL(plugin_url, web_contents());
244 installer()->StartInstalling(plugin_url, web_contents());
248 bool OutdatedPluginInfoBarDelegate::Cancel() {
249 content::RecordAction(
250 UserMetricsAction("OutdatedPluginInfobar.AllowThisTime"));
251 LoadBlockedPlugins();
255 void OutdatedPluginInfoBarDelegate::InfoBarDismissed() {
256 content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Dismissed"));
259 bool OutdatedPluginInfoBarDelegate::LinkClicked(
260 WindowOpenDisposition disposition) {
261 content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.LearnMore"));
262 return PluginInfoBarDelegate::LinkClicked(disposition);
265 void OutdatedPluginInfoBarDelegate::DownloadStarted() {
266 ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOADING,
267 plugin_metadata_->name()));
270 void OutdatedPluginInfoBarDelegate::DownloadError(const std::string& message) {
271 ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_ERROR_SHORT,
272 plugin_metadata_->name()));
275 void OutdatedPluginInfoBarDelegate::DownloadCancelled() {
276 ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_CANCELLED,
277 plugin_metadata_->name()));
280 void OutdatedPluginInfoBarDelegate::DownloadFinished() {
281 ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_UPDATING,
282 plugin_metadata_->name()));
285 void OutdatedPluginInfoBarDelegate::OnlyWeakObserversLeft() {
286 infobar()->RemoveSelf();
289 void OutdatedPluginInfoBarDelegate::ReplaceWithInfoBar(
290 const base::string16& message) {
291 // Return early if the message doesn't change. This is important in case the
292 // PluginInstaller is still iterating over its observers (otherwise we would
293 // keep replacing infobar delegates infinitely).
294 if ((message_ == message) || !infobar()->owner())
296 PluginInstallerInfoBarDelegate::Replace(
297 infobar(), installer(), plugin_metadata_->Clone(), false, message);
301 // PluginInstallerInfoBarDelegate ---------------------------------------------
303 void PluginInstallerInfoBarDelegate::Create(
304 InfoBarService* infobar_service,
305 PluginInstaller* installer,
306 scoped_ptr<PluginMetadata> plugin_metadata,
307 const InstallCallback& callback) {
308 base::string16 name(plugin_metadata->name());
310 if (base::win::IsMetroProcess()) {
311 PluginMetroModeInfoBarDelegate::Create(
312 infobar_service, PluginMetroModeInfoBarDelegate::MISSING_PLUGIN, name);
316 infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
317 scoped_ptr<ConfirmInfoBarDelegate>(new PluginInstallerInfoBarDelegate(
318 installer, plugin_metadata.Pass(), callback, true,
319 l10n_util::GetStringFUTF16(
320 (installer->state() == PluginInstaller::INSTALLER_STATE_IDLE) ?
321 IDS_PLUGININSTALLER_INSTALLPLUGIN_PROMPT :
322 IDS_PLUGIN_DOWNLOADING,
327 void PluginInstallerInfoBarDelegate::Replace(
329 PluginInstaller* installer,
330 scoped_ptr<PluginMetadata> plugin_metadata,
332 const base::string16& message) {
333 DCHECK(infobar->owner());
334 infobar->owner()->ReplaceInfoBar(infobar,
335 ConfirmInfoBarDelegate::CreateInfoBar(scoped_ptr<ConfirmInfoBarDelegate>(
336 new PluginInstallerInfoBarDelegate(
337 installer, plugin_metadata.Pass(),
338 PluginInstallerInfoBarDelegate::InstallCallback(), new_install,
342 PluginInstallerInfoBarDelegate::PluginInstallerInfoBarDelegate(
343 PluginInstaller* installer,
344 scoped_ptr<PluginMetadata> plugin_metadata,
345 const InstallCallback& callback,
347 const base::string16& message)
348 : ConfirmInfoBarDelegate(),
349 WeakPluginInstallerObserver(installer),
350 plugin_metadata_(plugin_metadata.Pass()),
352 new_install_(new_install),
356 PluginInstallerInfoBarDelegate::~PluginInstallerInfoBarDelegate() {
359 int PluginInstallerInfoBarDelegate::GetIconID() const {
360 return IDR_INFOBAR_PLUGIN_INSTALL;
363 base::string16 PluginInstallerInfoBarDelegate::GetMessageText() const {
367 int PluginInstallerInfoBarDelegate::GetButtons() const {
368 return callback_.is_null() ? BUTTON_NONE : BUTTON_OK;
371 base::string16 PluginInstallerInfoBarDelegate::GetButtonLabel(
372 InfoBarButton button) const {
373 DCHECK_EQ(BUTTON_OK, button);
374 return l10n_util::GetStringUTF16(IDS_PLUGININSTALLER_INSTALLPLUGIN_BUTTON);
377 bool PluginInstallerInfoBarDelegate::Accept() {
378 callback_.Run(plugin_metadata_.get());
382 base::string16 PluginInstallerInfoBarDelegate::GetLinkText() const {
383 return l10n_util::GetStringUTF16(new_install_ ?
384 IDS_PLUGININSTALLER_PROBLEMSINSTALLING :
385 IDS_PLUGININSTALLER_PROBLEMSUPDATING);
388 bool PluginInstallerInfoBarDelegate::LinkClicked(
389 WindowOpenDisposition disposition) {
390 GURL url(plugin_metadata_->help_url());
391 if (url.is_empty()) {
392 url = google_util::AppendGoogleLocaleParam(GURL(
393 "https://www.google.com/support/chrome/bin/answer.py?answer=142064"));
395 web_contents()->OpenURL(content::OpenURLParams(
396 url, content::Referrer(),
397 (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
398 content::PAGE_TRANSITION_LINK, false));
402 void PluginInstallerInfoBarDelegate::DownloadStarted() {
403 ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOADING,
404 plugin_metadata_->name()));
407 void PluginInstallerInfoBarDelegate::DownloadCancelled() {
408 ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_CANCELLED,
409 plugin_metadata_->name()));
412 void PluginInstallerInfoBarDelegate::DownloadError(const std::string& message) {
413 ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_ERROR_SHORT,
414 plugin_metadata_->name()));
417 void PluginInstallerInfoBarDelegate::DownloadFinished() {
419 l10n_util::GetStringFUTF16(
420 new_install_ ? IDS_PLUGIN_INSTALLING : IDS_PLUGIN_UPDATING,
421 plugin_metadata_->name()));
424 void PluginInstallerInfoBarDelegate::OnlyWeakObserversLeft() {
425 infobar()->RemoveSelf();
428 void PluginInstallerInfoBarDelegate::ReplaceWithInfoBar(
429 const base::string16& message) {
430 // Return early if the message doesn't change. This is important in case the
431 // PluginInstaller is still iterating over its observers (otherwise we would
432 // keep replacing infobar delegates infinitely).
433 if ((message_ == message) || !infobar()->owner())
435 Replace(infobar(), installer(), plugin_metadata_->Clone(), new_install_,
442 // PluginMetroModeInfoBarDelegate ---------------------------------------------
445 void PluginMetroModeInfoBarDelegate::Create(
446 InfoBarService* infobar_service,
447 PluginMetroModeInfoBarDelegate::Mode mode,
448 const base::string16& name) {
449 infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
450 scoped_ptr<ConfirmInfoBarDelegate>(
451 new PluginMetroModeInfoBarDelegate(mode, name))));
454 PluginMetroModeInfoBarDelegate::PluginMetroModeInfoBarDelegate(
455 PluginMetroModeInfoBarDelegate::Mode mode,
456 const base::string16& name)
457 : ConfirmInfoBarDelegate(),
462 PluginMetroModeInfoBarDelegate::~PluginMetroModeInfoBarDelegate() {
465 int PluginMetroModeInfoBarDelegate::GetIconID() const {
466 return IDR_INFOBAR_PLUGIN_INSTALL;
469 base::string16 PluginMetroModeInfoBarDelegate::GetMessageText() const {
470 return l10n_util::GetStringFUTF16((mode_ == MISSING_PLUGIN) ?
471 IDS_METRO_MISSING_PLUGIN_PROMPT : IDS_METRO_NPAPI_PLUGIN_PROMPT, name_);
474 int PluginMetroModeInfoBarDelegate::GetButtons() const {
478 base::string16 PluginMetroModeInfoBarDelegate::GetButtonLabel(
479 InfoBarButton button) const {
480 #if defined(USE_AURA) && defined(USE_ASH)
481 return l10n_util::GetStringUTF16(IDS_WIN8_DESKTOP_RESTART);
483 return l10n_util::GetStringUTF16((mode_ == MISSING_PLUGIN) ?
484 IDS_WIN8_DESKTOP_RESTART : IDS_WIN8_DESKTOP_OPEN);
488 #if defined(USE_AURA) && defined(USE_ASH)
489 void LaunchDesktopInstanceHelper(const base::string16& url) {
490 base::FilePath exe_path;
491 if (!PathService::Get(base::FILE_EXE, &exe_path))
493 base::FilePath shortcut_path(
494 ShellIntegration::GetStartMenuShortcut(exe_path));
496 // Actually launching the process needs to happen in the metro viewer,
497 // otherwise it won't automatically transition to desktop. So we have
498 // to send an IPC to the viewer to do the ShellExecute.
499 aura::RemoteWindowTreeHostWin::Instance()->HandleOpenURLOnDesktop(
504 bool PluginMetroModeInfoBarDelegate::Accept() {
505 chrome::AttemptRestartToDesktopMode();
509 base::string16 PluginMetroModeInfoBarDelegate::GetLinkText() const {
510 return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
513 bool PluginMetroModeInfoBarDelegate::LinkClicked(
514 WindowOpenDisposition disposition) {
515 // TODO(shrikant): We may need to change language a little at following
516 // support URLs. With new approach we will just restart for both missing
517 // and not missing mode.
518 web_contents()->OpenURL(content::OpenURLParams(
519 GURL((mode_ == MISSING_PLUGIN) ?
520 "https://support.google.com/chrome/?p=ib_display_in_desktop" :
521 "https://support.google.com/chrome/?p=ib_redirect_to_desktop"),
523 (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
524 content::PAGE_TRANSITION_LINK, false));
528 #endif // defined(OS_WIN)
530 #endif // defined(ENABLE_PLUGIN_INSTALLATION)