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"
7 #include "base/path_service.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "chrome/browser/content_settings/host_content_settings_map.h"
10 #include "chrome/browser/google/google_util.h"
11 #include "chrome/browser/infobars/infobar_service.h"
12 #include "chrome/browser/lifetime/application_lifetime.h"
13 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
14 #include "chrome/browser/plugins/plugin_metadata.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/shell_integration.h"
17 #include "chrome/browser/ui/browser_commands.h"
18 #include "chrome/common/render_messages.h"
19 #include "chrome/common/url_constants.h"
20 #include "content/public/browser/browser_thread.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_root_window_host_win.h"
46 using content::UserMetricsAction;
49 // PluginInfoBarDelegate ------------------------------------------------------
51 PluginInfoBarDelegate::PluginInfoBarDelegate(InfoBarService* infobar_service,
52 const std::string& identifier)
53 : ConfirmInfoBarDelegate(infobar_service),
54 identifier_(identifier) {
57 PluginInfoBarDelegate::~PluginInfoBarDelegate() {
60 bool PluginInfoBarDelegate::LinkClicked(WindowOpenDisposition disposition) {
61 web_contents()->OpenURL(content::OpenURLParams(
62 GURL(GetLearnMoreURL()), content::Referrer(),
63 (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
64 content::PAGE_TRANSITION_LINK, false));
68 void PluginInfoBarDelegate::LoadBlockedPlugins() {
69 content::RenderViewHost* host = web_contents()->GetRenderViewHost();
70 ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
71 host->GetProcess()->GetID());
72 host->Send(new ChromeViewMsg_LoadBlockedPlugins(
73 host->GetRoutingID(), identifier_));
76 int PluginInfoBarDelegate::GetIconID() const {
77 return IDR_INFOBAR_PLUGIN_INSTALL;
80 string16 PluginInfoBarDelegate::GetLinkText() const {
81 return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
85 // UnauthorizedPluginInfoBarDelegate ------------------------------------------
88 void UnauthorizedPluginInfoBarDelegate::Create(
89 InfoBarService* infobar_service,
90 HostContentSettingsMap* content_settings,
92 const std::string& identifier) {
93 infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>(
94 new UnauthorizedPluginInfoBarDelegate(infobar_service, content_settings,
97 content::RecordAction(UserMetricsAction("BlockedPluginInfobar.Shown"));
98 std::string utf8_name(UTF16ToUTF8(name));
99 if (utf8_name == PluginMetadata::kJavaGroupName) {
100 content::RecordAction(UserMetricsAction("BlockedPluginInfobar.Shown.Java"));
101 } else if (utf8_name == PluginMetadata::kQuickTimeGroupName) {
102 content::RecordAction(
103 UserMetricsAction("BlockedPluginInfobar.Shown.QuickTime"));
104 } else if (utf8_name == PluginMetadata::kShockwaveGroupName) {
105 content::RecordAction(
106 UserMetricsAction("BlockedPluginInfobar.Shown.Shockwave"));
107 } else if (utf8_name == PluginMetadata::kRealPlayerGroupName) {
108 content::RecordAction(
109 UserMetricsAction("BlockedPluginInfobar.Shown.RealPlayer"));
110 } else if (utf8_name == PluginMetadata::kWindowsMediaPlayerGroupName) {
111 content::RecordAction(
112 UserMetricsAction("BlockedPluginInfobar.Shown.WindowsMediaPlayer"));
116 UnauthorizedPluginInfoBarDelegate::UnauthorizedPluginInfoBarDelegate(
117 InfoBarService* infobar_service,
118 HostContentSettingsMap* content_settings,
119 const string16& name,
120 const std::string& identifier)
121 : PluginInfoBarDelegate(infobar_service, identifier),
122 content_settings_(content_settings),
126 UnauthorizedPluginInfoBarDelegate::~UnauthorizedPluginInfoBarDelegate() {
127 content::RecordAction(UserMetricsAction("BlockedPluginInfobar.Closed"));
130 std::string UnauthorizedPluginInfoBarDelegate::GetLearnMoreURL() const {
131 return chrome::kBlockedPluginLearnMoreURL;
134 string16 UnauthorizedPluginInfoBarDelegate::GetMessageText() const {
135 return l10n_util::GetStringFUTF16(IDS_PLUGIN_NOT_AUTHORIZED, name_);
138 string16 UnauthorizedPluginInfoBarDelegate::GetButtonLabel(
139 InfoBarButton button) const {
140 return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
141 IDS_PLUGIN_ENABLE_TEMPORARILY : IDS_PLUGIN_ENABLE_ALWAYS);
144 bool UnauthorizedPluginInfoBarDelegate::Accept() {
145 content::RecordAction(
146 UserMetricsAction("BlockedPluginInfobar.AllowThisTime"));
147 LoadBlockedPlugins();
151 bool UnauthorizedPluginInfoBarDelegate::Cancel() {
152 content::RecordAction(UserMetricsAction("BlockedPluginInfobar.AlwaysAllow"));
153 const GURL& url = web_contents()->GetURL();
154 content_settings_->AddExceptionForURL(url, url, CONTENT_SETTINGS_TYPE_PLUGINS,
155 std::string(), CONTENT_SETTING_ALLOW);
156 LoadBlockedPlugins();
160 void UnauthorizedPluginInfoBarDelegate::InfoBarDismissed() {
161 content::RecordAction(UserMetricsAction("BlockedPluginInfobar.Dismissed"));
164 bool UnauthorizedPluginInfoBarDelegate::LinkClicked(
165 WindowOpenDisposition disposition) {
166 content::RecordAction(UserMetricsAction("BlockedPluginInfobar.LearnMore"));
167 return PluginInfoBarDelegate::LinkClicked(disposition);
171 #if defined(ENABLE_PLUGIN_INSTALLATION)
173 // OutdatedPluginInfoBarDelegate ----------------------------------------------
175 void OutdatedPluginInfoBarDelegate::Create(
176 InfoBarService* infobar_service,
177 PluginInstaller* installer,
178 scoped_ptr<PluginMetadata> plugin_metadata) {
179 // Copy the name out of |plugin_metadata| now, since the Pass() call below
180 // will make it impossible to get at.
181 string16 name(plugin_metadata->name());
182 infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>(
183 new OutdatedPluginInfoBarDelegate(
184 infobar_service, installer, plugin_metadata.Pass(),
185 l10n_util::GetStringFUTF16(
186 (installer->state() == PluginInstaller::INSTALLER_STATE_IDLE) ?
187 IDS_PLUGIN_OUTDATED_PROMPT : IDS_PLUGIN_DOWNLOADING,
191 OutdatedPluginInfoBarDelegate::OutdatedPluginInfoBarDelegate(
192 InfoBarService* infobar_service,
193 PluginInstaller* installer,
194 scoped_ptr<PluginMetadata> plugin_metadata,
195 const string16& message)
196 : PluginInfoBarDelegate(infobar_service, plugin_metadata->identifier()),
197 WeakPluginInstallerObserver(installer),
198 plugin_metadata_(plugin_metadata.Pass()),
200 content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Shown"));
201 std::string name = UTF16ToUTF8(plugin_metadata_->name());
202 if (name == PluginMetadata::kJavaGroupName) {
203 content::RecordAction(
204 UserMetricsAction("OutdatedPluginInfobar.Shown.Java"));
205 } else if (name == PluginMetadata::kQuickTimeGroupName) {
206 content::RecordAction(
207 UserMetricsAction("OutdatedPluginInfobar.Shown.QuickTime"));
208 } else if (name == PluginMetadata::kShockwaveGroupName) {
209 content::RecordAction(
210 UserMetricsAction("OutdatedPluginInfobar.Shown.Shockwave"));
211 } else if (name == PluginMetadata::kRealPlayerGroupName) {
212 content::RecordAction(
213 UserMetricsAction("OutdatedPluginInfobar.Shown.RealPlayer"));
214 } else if (name == PluginMetadata::kSilverlightGroupName) {
215 content::RecordAction(
216 UserMetricsAction("OutdatedPluginInfobar.Shown.Silverlight"));
217 } else if (name == PluginMetadata::kAdobeReaderGroupName) {
218 content::RecordAction(
219 UserMetricsAction("OutdatedPluginInfobar.Shown.Reader"));
223 OutdatedPluginInfoBarDelegate::~OutdatedPluginInfoBarDelegate() {
224 content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Closed"));
227 std::string OutdatedPluginInfoBarDelegate::GetLearnMoreURL() const {
228 return chrome::kOutdatedPluginLearnMoreURL;
231 string16 OutdatedPluginInfoBarDelegate::GetMessageText() const {
235 string16 OutdatedPluginInfoBarDelegate::GetButtonLabel(
236 InfoBarButton button) const {
237 return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
238 IDS_PLUGIN_UPDATE : IDS_PLUGIN_ENABLE_TEMPORARILY);
241 bool OutdatedPluginInfoBarDelegate::Accept() {
242 DCHECK_EQ(PluginInstaller::INSTALLER_STATE_IDLE, installer()->state());
243 content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Update"));
244 // A call to any of |OpenDownloadURL()| or |StartInstalling()| will
245 // result in deleting ourselves. Accordingly, we make sure to
246 // not pass a reference to an object that can go away.
247 GURL plugin_url(plugin_metadata_->plugin_url());
248 if (plugin_metadata_->url_for_display())
249 installer()->OpenDownloadURL(plugin_url, web_contents());
251 installer()->StartInstalling(plugin_url, web_contents());
255 bool OutdatedPluginInfoBarDelegate::Cancel() {
256 content::RecordAction(
257 UserMetricsAction("OutdatedPluginInfobar.AllowThisTime"));
258 LoadBlockedPlugins();
262 void OutdatedPluginInfoBarDelegate::InfoBarDismissed() {
263 content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Dismissed"));
266 bool OutdatedPluginInfoBarDelegate::LinkClicked(
267 WindowOpenDisposition disposition) {
268 content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.LearnMore"));
269 return PluginInfoBarDelegate::LinkClicked(disposition);
272 void OutdatedPluginInfoBarDelegate::DownloadStarted() {
273 ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOADING,
274 plugin_metadata_->name()));
277 void OutdatedPluginInfoBarDelegate::DownloadError(const std::string& message) {
278 ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_ERROR_SHORT,
279 plugin_metadata_->name()));
282 void OutdatedPluginInfoBarDelegate::DownloadCancelled() {
283 ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_CANCELLED,
284 plugin_metadata_->name()));
287 void OutdatedPluginInfoBarDelegate::DownloadFinished() {
288 ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_UPDATING,
289 plugin_metadata_->name()));
292 void OutdatedPluginInfoBarDelegate::OnlyWeakObserversLeft() {
294 owner()->RemoveInfoBar(this);
297 void OutdatedPluginInfoBarDelegate::ReplaceWithInfoBar(
298 const string16& message) {
299 // Return early if the message doesn't change. This is important in case the
300 // PluginInstaller is still iterating over its observers (otherwise we would
301 // keep replacing infobar delegates infinitely).
302 if ((message_ == message) || !owner())
304 PluginInstallerInfoBarDelegate::Replace(
305 this, installer(), plugin_metadata_->Clone(), false, message);
309 // PluginInstallerInfoBarDelegate ---------------------------------------------
311 void PluginInstallerInfoBarDelegate::Create(
312 InfoBarService* infobar_service,
313 PluginInstaller* installer,
314 scoped_ptr<PluginMetadata> plugin_metadata,
315 const InstallCallback& callback) {
316 string16 name(plugin_metadata->name());
318 if (base::win::IsMetroProcess()) {
319 PluginMetroModeInfoBarDelegate::Create(
320 infobar_service, PluginMetroModeInfoBarDelegate::MISSING_PLUGIN, name);
324 infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>(
325 new PluginInstallerInfoBarDelegate(
326 infobar_service, installer, plugin_metadata.Pass(), callback, true,
327 l10n_util::GetStringFUTF16(
328 (installer->state() == PluginInstaller::INSTALLER_STATE_IDLE) ?
329 IDS_PLUGININSTALLER_INSTALLPLUGIN_PROMPT :
330 IDS_PLUGIN_DOWNLOADING,
335 void PluginInstallerInfoBarDelegate::Replace(
336 InfoBarDelegate* infobar,
337 PluginInstaller* installer,
338 scoped_ptr<PluginMetadata> plugin_metadata,
340 const string16& message) {
341 DCHECK(infobar->owner());
342 infobar->owner()->ReplaceInfoBar(infobar, scoped_ptr<InfoBarDelegate>(
343 new PluginInstallerInfoBarDelegate(
344 infobar->owner(), installer, plugin_metadata.Pass(),
345 PluginInstallerInfoBarDelegate::InstallCallback(), new_install,
349 PluginInstallerInfoBarDelegate::PluginInstallerInfoBarDelegate(
350 InfoBarService* infobar_service,
351 PluginInstaller* installer,
352 scoped_ptr<PluginMetadata> plugin_metadata,
353 const InstallCallback& callback,
355 const string16& message)
356 : ConfirmInfoBarDelegate(infobar_service),
357 WeakPluginInstallerObserver(installer),
358 plugin_metadata_(plugin_metadata.Pass()),
360 new_install_(new_install),
364 PluginInstallerInfoBarDelegate::~PluginInstallerInfoBarDelegate() {
367 int PluginInstallerInfoBarDelegate::GetIconID() const {
368 return IDR_INFOBAR_PLUGIN_INSTALL;
371 string16 PluginInstallerInfoBarDelegate::GetMessageText() const {
375 int PluginInstallerInfoBarDelegate::GetButtons() const {
376 return callback_.is_null() ? BUTTON_NONE : BUTTON_OK;
379 string16 PluginInstallerInfoBarDelegate::GetButtonLabel(
380 InfoBarButton button) const {
381 DCHECK_EQ(BUTTON_OK, button);
382 return l10n_util::GetStringUTF16(IDS_PLUGININSTALLER_INSTALLPLUGIN_BUTTON);
385 bool PluginInstallerInfoBarDelegate::Accept() {
386 callback_.Run(plugin_metadata_.get());
390 string16 PluginInstallerInfoBarDelegate::GetLinkText() const {
391 return l10n_util::GetStringUTF16(new_install_ ?
392 IDS_PLUGININSTALLER_PROBLEMSINSTALLING :
393 IDS_PLUGININSTALLER_PROBLEMSUPDATING);
396 bool PluginInstallerInfoBarDelegate::LinkClicked(
397 WindowOpenDisposition disposition) {
398 GURL url(plugin_metadata_->help_url());
399 if (url.is_empty()) {
400 url = google_util::AppendGoogleLocaleParam(GURL(
401 "https://www.google.com/support/chrome/bin/answer.py?answer=142064"));
403 web_contents()->OpenURL(content::OpenURLParams(
404 url, content::Referrer(),
405 (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
406 content::PAGE_TRANSITION_LINK, false));
410 void PluginInstallerInfoBarDelegate::DownloadStarted() {
411 ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOADING,
412 plugin_metadata_->name()));
415 void PluginInstallerInfoBarDelegate::DownloadCancelled() {
416 ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_CANCELLED,
417 plugin_metadata_->name()));
420 void PluginInstallerInfoBarDelegate::DownloadError(const std::string& message) {
421 ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_ERROR_SHORT,
422 plugin_metadata_->name()));
425 void PluginInstallerInfoBarDelegate::DownloadFinished() {
427 l10n_util::GetStringFUTF16(
428 new_install_ ? IDS_PLUGIN_INSTALLING : IDS_PLUGIN_UPDATING,
429 plugin_metadata_->name()));
432 void PluginInstallerInfoBarDelegate::OnlyWeakObserversLeft() {
434 owner()->RemoveInfoBar(this);
437 void PluginInstallerInfoBarDelegate::ReplaceWithInfoBar(
438 const string16& message) {
439 // Return early if the message doesn't change. This is important in case the
440 // PluginInstaller is still iterating over its observers (otherwise we would
441 // keep replacing infobar delegates infinitely).
442 if ((message_ == message) || !owner())
444 Replace(this, installer(), plugin_metadata_->Clone(), new_install_, message);
450 // PluginMetroModeInfoBarDelegate ---------------------------------------------
453 void PluginMetroModeInfoBarDelegate::Create(
454 InfoBarService* infobar_service,
455 PluginMetroModeInfoBarDelegate::Mode mode,
456 const string16& name) {
457 infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>(
458 new PluginMetroModeInfoBarDelegate(infobar_service, mode, name)));
461 PluginMetroModeInfoBarDelegate::PluginMetroModeInfoBarDelegate(
462 InfoBarService* infobar_service,
463 PluginMetroModeInfoBarDelegate::Mode mode,
464 const string16& name)
465 : ConfirmInfoBarDelegate(infobar_service),
470 PluginMetroModeInfoBarDelegate::~PluginMetroModeInfoBarDelegate() {
473 int PluginMetroModeInfoBarDelegate::GetIconID() const {
474 return IDR_INFOBAR_PLUGIN_INSTALL;
477 string16 PluginMetroModeInfoBarDelegate::GetMessageText() const {
478 return l10n_util::GetStringFUTF16((mode_ == MISSING_PLUGIN) ?
479 IDS_METRO_MISSING_PLUGIN_PROMPT : IDS_METRO_NPAPI_PLUGIN_PROMPT, name_);
482 int PluginMetroModeInfoBarDelegate::GetButtons() const {
486 string16 PluginMetroModeInfoBarDelegate::GetButtonLabel(
487 InfoBarButton button) const {
488 #if defined(USE_AURA) && defined(USE_ASH)
489 return l10n_util::GetStringUTF16(IDS_WIN8_DESKTOP_RESTART);
491 return l10n_util::GetStringUTF16((mode_ == MISSING_PLUGIN) ?
492 IDS_WIN8_DESKTOP_RESTART : IDS_WIN8_DESKTOP_OPEN);
496 #if defined(USE_AURA) && defined(USE_ASH)
497 void LaunchDesktopInstanceHelper(const string16& url) {
498 base::FilePath exe_path;
499 if (!PathService::Get(base::FILE_EXE, &exe_path))
501 base::FilePath shortcut_path(
502 ShellIntegration::GetStartMenuShortcut(exe_path));
504 // Actually launching the process needs to happen in the metro viewer,
505 // otherwise it won't automatically transition to desktop. So we have
506 // to send an IPC to the viewer to do the ShellExecute.
507 aura::RemoteRootWindowHostWin::Instance()->HandleOpenURLOnDesktop(
512 bool PluginMetroModeInfoBarDelegate::Accept() {
513 chrome::AttemptRestartToDesktopMode();
517 string16 PluginMetroModeInfoBarDelegate::GetLinkText() const {
518 return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
521 bool PluginMetroModeInfoBarDelegate::LinkClicked(
522 WindowOpenDisposition disposition) {
523 // TODO(shrikant): We may need to change language a little at following
524 // support URLs. With new approach we will just restart for both missing
525 // and not missing mode.
526 web_contents()->OpenURL(content::OpenURLParams(
527 GURL((mode_ == MISSING_PLUGIN) ?
528 "https://support.google.com/chrome/?p=ib_display_in_desktop" :
529 "https://support.google.com/chrome/?p=ib_redirect_to_desktop"),
531 (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
532 content::PAGE_TRANSITION_LINK, false));
536 #endif // defined(OS_WIN)
538 #endif // defined(ENABLE_PLUGIN_INSTALLATION)