Home | History | Annotate | Download | only in plugins
      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/plugins/plugin_infobar_delegates.h"
      6 
      7 #include "base/bind.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/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/url_constants.h"
     19 #include "components/google/core/browser/google_util.h"
     20 #include "components/infobars/core/infobar.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"
     29 
     30 #if defined(ENABLE_PLUGIN_INSTALLATION)
     31 #if defined(OS_WIN)
     32 #include "base/win/metro.h"
     33 #endif
     34 #include "chrome/browser/plugins/plugin_installer.h"
     35 #endif
     36 
     37 #if defined(OS_WIN)
     38 #include <shellapi.h>
     39 #include "ui/base/win/shell.h"
     40 
     41 #if defined(USE_AURA)
     42 #include "ui/aura/remote_window_tree_host_win.h"
     43 #endif
     44 #endif
     45 
     46 using base::UserMetricsAction;
     47 
     48 
     49 // PluginInfoBarDelegate ------------------------------------------------------
     50 
     51 PluginInfoBarDelegate::PluginInfoBarDelegate(const std::string& identifier)
     52     : ConfirmInfoBarDelegate(),
     53       identifier_(identifier) {
     54 }
     55 
     56 PluginInfoBarDelegate::~PluginInfoBarDelegate() {
     57 }
     58 
     59 bool PluginInfoBarDelegate::LinkClicked(WindowOpenDisposition disposition) {
     60   InfoBarService::WebContentsFromInfoBar(infobar())->OpenURL(
     61       content::OpenURLParams(
     62           GURL(GetLearnMoreURL()), content::Referrer(),
     63           (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
     64           content::PAGE_TRANSITION_LINK, false));
     65   return false;
     66 }
     67 
     68 void PluginInfoBarDelegate::LoadBlockedPlugins() {
     69   content::WebContents* web_contents =
     70       InfoBarService::WebContentsFromInfoBar(infobar());
     71   ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
     72       web_contents, true, identifier_);
     73 }
     74 
     75 int PluginInfoBarDelegate::GetIconID() const {
     76   return IDR_INFOBAR_PLUGIN_INSTALL;
     77 }
     78 
     79 base::string16 PluginInfoBarDelegate::GetLinkText() const {
     80   return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
     81 }
     82 
     83 
     84 // UnauthorizedPluginInfoBarDelegate ------------------------------------------
     85 
     86 // static
     87 void UnauthorizedPluginInfoBarDelegate::Create(
     88     InfoBarService* infobar_service,
     89     HostContentSettingsMap* content_settings,
     90     const base::string16& name,
     91     const std::string& identifier) {
     92   infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
     93       scoped_ptr<ConfirmInfoBarDelegate>(new UnauthorizedPluginInfoBarDelegate(
     94           content_settings, name, identifier))));
     95 
     96   content::RecordAction(UserMetricsAction("BlockedPluginInfobar.Shown"));
     97   std::string utf8_name(base::UTF16ToUTF8(name));
     98   if (utf8_name == PluginMetadata::kJavaGroupName) {
     99     content::RecordAction(UserMetricsAction("BlockedPluginInfobar.Shown.Java"));
    100   } else if (utf8_name == PluginMetadata::kQuickTimeGroupName) {
    101     content::RecordAction(
    102         UserMetricsAction("BlockedPluginInfobar.Shown.QuickTime"));
    103   } else if (utf8_name == PluginMetadata::kShockwaveGroupName) {
    104     content::RecordAction(
    105         UserMetricsAction("BlockedPluginInfobar.Shown.Shockwave"));
    106   } else if (utf8_name == PluginMetadata::kRealPlayerGroupName) {
    107     content::RecordAction(
    108         UserMetricsAction("BlockedPluginInfobar.Shown.RealPlayer"));
    109   } else if (utf8_name == PluginMetadata::kWindowsMediaPlayerGroupName) {
    110     content::RecordAction(
    111         UserMetricsAction("BlockedPluginInfobar.Shown.WindowsMediaPlayer"));
    112   }
    113 }
    114 
    115 UnauthorizedPluginInfoBarDelegate::UnauthorizedPluginInfoBarDelegate(
    116     HostContentSettingsMap* content_settings,
    117     const base::string16& name,
    118     const std::string& identifier)
    119     : PluginInfoBarDelegate(identifier),
    120       content_settings_(content_settings),
    121       name_(name) {
    122 }
    123 
    124 UnauthorizedPluginInfoBarDelegate::~UnauthorizedPluginInfoBarDelegate() {
    125   content::RecordAction(UserMetricsAction("BlockedPluginInfobar.Closed"));
    126 }
    127 
    128 std::string UnauthorizedPluginInfoBarDelegate::GetLearnMoreURL() const {
    129   return chrome::kBlockedPluginLearnMoreURL;
    130 }
    131 
    132 base::string16 UnauthorizedPluginInfoBarDelegate::GetMessageText() const {
    133   return l10n_util::GetStringFUTF16(IDS_PLUGIN_NOT_AUTHORIZED, name_);
    134 }
    135 
    136 base::string16 UnauthorizedPluginInfoBarDelegate::GetButtonLabel(
    137     InfoBarButton button) const {
    138   return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
    139       IDS_PLUGIN_ENABLE_TEMPORARILY : IDS_PLUGIN_ENABLE_ALWAYS);
    140 }
    141 
    142 bool UnauthorizedPluginInfoBarDelegate::Accept() {
    143   content::RecordAction(
    144       UserMetricsAction("BlockedPluginInfobar.AllowThisTime"));
    145   LoadBlockedPlugins();
    146   return true;
    147 }
    148 
    149 bool UnauthorizedPluginInfoBarDelegate::Cancel() {
    150   content::RecordAction(UserMetricsAction("BlockedPluginInfobar.AlwaysAllow"));
    151   const GURL& url = InfoBarService::WebContentsFromInfoBar(infobar())->GetURL();
    152   content_settings_->AddExceptionForURL(url, url, CONTENT_SETTINGS_TYPE_PLUGINS,
    153                                         CONTENT_SETTING_ALLOW);
    154   LoadBlockedPlugins();
    155   return true;
    156 }
    157 
    158 void UnauthorizedPluginInfoBarDelegate::InfoBarDismissed() {
    159   content::RecordAction(UserMetricsAction("BlockedPluginInfobar.Dismissed"));
    160 }
    161 
    162 bool UnauthorizedPluginInfoBarDelegate::LinkClicked(
    163     WindowOpenDisposition disposition) {
    164   content::RecordAction(UserMetricsAction("BlockedPluginInfobar.LearnMore"));
    165   return PluginInfoBarDelegate::LinkClicked(disposition);
    166 }
    167 
    168 
    169 #if defined(ENABLE_PLUGIN_INSTALLATION)
    170 
    171 // OutdatedPluginInfoBarDelegate ----------------------------------------------
    172 
    173 void OutdatedPluginInfoBarDelegate::Create(
    174     InfoBarService* infobar_service,
    175     PluginInstaller* installer,
    176     scoped_ptr<PluginMetadata> plugin_metadata) {
    177   // Copy the name out of |plugin_metadata| now, since the Pass() call below
    178   // will make it impossible to get at.
    179   base::string16 name(plugin_metadata->name());
    180   infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
    181       scoped_ptr<ConfirmInfoBarDelegate>(new OutdatedPluginInfoBarDelegate(
    182           installer, plugin_metadata.Pass(), l10n_util::GetStringFUTF16(
    183               (installer->state() == PluginInstaller::INSTALLER_STATE_IDLE) ?
    184                   IDS_PLUGIN_OUTDATED_PROMPT : IDS_PLUGIN_DOWNLOADING,
    185               name)))));
    186 }
    187 
    188 OutdatedPluginInfoBarDelegate::OutdatedPluginInfoBarDelegate(
    189     PluginInstaller* installer,
    190     scoped_ptr<PluginMetadata> plugin_metadata,
    191     const base::string16& message)
    192     : PluginInfoBarDelegate(plugin_metadata->identifier()),
    193       WeakPluginInstallerObserver(installer),
    194       plugin_metadata_(plugin_metadata.Pass()),
    195       message_(message) {
    196   content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Shown"));
    197   std::string name = base::UTF16ToUTF8(plugin_metadata_->name());
    198   if (name == PluginMetadata::kJavaGroupName) {
    199     content::RecordAction(
    200         UserMetricsAction("OutdatedPluginInfobar.Shown.Java"));
    201   } else if (name == PluginMetadata::kQuickTimeGroupName) {
    202     content::RecordAction(
    203         UserMetricsAction("OutdatedPluginInfobar.Shown.QuickTime"));
    204   } else if (name == PluginMetadata::kShockwaveGroupName) {
    205     content::RecordAction(
    206         UserMetricsAction("OutdatedPluginInfobar.Shown.Shockwave"));
    207   } else if (name == PluginMetadata::kRealPlayerGroupName) {
    208     content::RecordAction(
    209         UserMetricsAction("OutdatedPluginInfobar.Shown.RealPlayer"));
    210   } else if (name == PluginMetadata::kSilverlightGroupName) {
    211     content::RecordAction(
    212         UserMetricsAction("OutdatedPluginInfobar.Shown.Silverlight"));
    213   } else if (name == PluginMetadata::kAdobeReaderGroupName) {
    214     content::RecordAction(
    215         UserMetricsAction("OutdatedPluginInfobar.Shown.Reader"));
    216   }
    217 }
    218 
    219 OutdatedPluginInfoBarDelegate::~OutdatedPluginInfoBarDelegate() {
    220   content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Closed"));
    221 }
    222 
    223 std::string OutdatedPluginInfoBarDelegate::GetLearnMoreURL() const {
    224   return chrome::kOutdatedPluginLearnMoreURL;
    225 }
    226 
    227 base::string16 OutdatedPluginInfoBarDelegate::GetMessageText() const {
    228   return message_;
    229 }
    230 
    231 base::string16 OutdatedPluginInfoBarDelegate::GetButtonLabel(
    232     InfoBarButton button) const {
    233   return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
    234       IDS_PLUGIN_UPDATE : IDS_PLUGIN_ENABLE_TEMPORARILY);
    235 }
    236 
    237 bool OutdatedPluginInfoBarDelegate::Accept() {
    238   DCHECK_EQ(PluginInstaller::INSTALLER_STATE_IDLE, installer()->state());
    239   content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Update"));
    240   // A call to any of |OpenDownloadURL()| or |StartInstalling()| will
    241   // result in deleting ourselves. Accordingly, we make sure to
    242   // not pass a reference to an object that can go away.
    243   GURL plugin_url(plugin_metadata_->plugin_url());
    244   content::WebContents* web_contents =
    245       InfoBarService::WebContentsFromInfoBar(infobar());
    246   if (plugin_metadata_->url_for_display())
    247     installer()->OpenDownloadURL(plugin_url, web_contents);
    248   else
    249     installer()->StartInstalling(plugin_url, web_contents);
    250   return false;
    251 }
    252 
    253 bool OutdatedPluginInfoBarDelegate::Cancel() {
    254   content::RecordAction(
    255       UserMetricsAction("OutdatedPluginInfobar.AllowThisTime"));
    256   LoadBlockedPlugins();
    257   return true;
    258 }
    259 
    260 void OutdatedPluginInfoBarDelegate::InfoBarDismissed() {
    261   content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Dismissed"));
    262 }
    263 
    264 bool OutdatedPluginInfoBarDelegate::LinkClicked(
    265     WindowOpenDisposition disposition) {
    266   content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.LearnMore"));
    267   return PluginInfoBarDelegate::LinkClicked(disposition);
    268 }
    269 
    270 void OutdatedPluginInfoBarDelegate::DownloadStarted() {
    271   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOADING,
    272                                                 plugin_metadata_->name()));
    273 }
    274 
    275 void OutdatedPluginInfoBarDelegate::DownloadError(const std::string& message) {
    276   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_ERROR_SHORT,
    277                                                 plugin_metadata_->name()));
    278 }
    279 
    280 void OutdatedPluginInfoBarDelegate::DownloadCancelled() {
    281   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_CANCELLED,
    282                                                 plugin_metadata_->name()));
    283 }
    284 
    285 void OutdatedPluginInfoBarDelegate::DownloadFinished() {
    286   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_UPDATING,
    287                                                 plugin_metadata_->name()));
    288 }
    289 
    290 void OutdatedPluginInfoBarDelegate::OnlyWeakObserversLeft() {
    291   infobar()->RemoveSelf();
    292 }
    293 
    294 void OutdatedPluginInfoBarDelegate::ReplaceWithInfoBar(
    295     const base::string16& message) {
    296   // Return early if the message doesn't change. This is important in case the
    297   // PluginInstaller is still iterating over its observers (otherwise we would
    298   // keep replacing infobar delegates infinitely).
    299   if ((message_ == message) || !infobar()->owner())
    300     return;
    301   PluginInstallerInfoBarDelegate::Replace(
    302       infobar(), installer(), plugin_metadata_->Clone(), false, message);
    303 }
    304 
    305 
    306 // PluginInstallerInfoBarDelegate ---------------------------------------------
    307 
    308 void PluginInstallerInfoBarDelegate::Create(
    309     InfoBarService* infobar_service,
    310     PluginInstaller* installer,
    311     scoped_ptr<PluginMetadata> plugin_metadata,
    312     const InstallCallback& callback) {
    313   base::string16 name(plugin_metadata->name());
    314 #if defined(OS_WIN)
    315   if (base::win::IsMetroProcess()) {
    316     PluginMetroModeInfoBarDelegate::Create(
    317         infobar_service, PluginMetroModeInfoBarDelegate::MISSING_PLUGIN, name);
    318     return;
    319   }
    320 #endif
    321   infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
    322       scoped_ptr<ConfirmInfoBarDelegate>(new PluginInstallerInfoBarDelegate(
    323           installer, plugin_metadata.Pass(), callback, true,
    324           l10n_util::GetStringFUTF16(
    325               (installer->state() == PluginInstaller::INSTALLER_STATE_IDLE) ?
    326                   IDS_PLUGININSTALLER_INSTALLPLUGIN_PROMPT :
    327                   IDS_PLUGIN_DOWNLOADING,
    328               name)))));
    329 }
    330 
    331 void PluginInstallerInfoBarDelegate::Replace(
    332     infobars::InfoBar* infobar,
    333     PluginInstaller* installer,
    334     scoped_ptr<PluginMetadata> plugin_metadata,
    335     bool new_install,
    336     const base::string16& message) {
    337   DCHECK(infobar->owner());
    338   infobar->owner()->ReplaceInfoBar(infobar,
    339       ConfirmInfoBarDelegate::CreateInfoBar(scoped_ptr<ConfirmInfoBarDelegate>(
    340           new PluginInstallerInfoBarDelegate(
    341               installer, plugin_metadata.Pass(),
    342               PluginInstallerInfoBarDelegate::InstallCallback(), new_install,
    343               message))));
    344 }
    345 
    346 PluginInstallerInfoBarDelegate::PluginInstallerInfoBarDelegate(
    347     PluginInstaller* installer,
    348     scoped_ptr<PluginMetadata> plugin_metadata,
    349     const InstallCallback& callback,
    350     bool new_install,
    351     const base::string16& message)
    352     : ConfirmInfoBarDelegate(),
    353       WeakPluginInstallerObserver(installer),
    354       plugin_metadata_(plugin_metadata.Pass()),
    355       callback_(callback),
    356       new_install_(new_install),
    357       message_(message) {
    358 }
    359 
    360 PluginInstallerInfoBarDelegate::~PluginInstallerInfoBarDelegate() {
    361 }
    362 
    363 int PluginInstallerInfoBarDelegate::GetIconID() const {
    364   return IDR_INFOBAR_PLUGIN_INSTALL;
    365 }
    366 
    367 base::string16 PluginInstallerInfoBarDelegate::GetMessageText() const {
    368   return message_;
    369 }
    370 
    371 int PluginInstallerInfoBarDelegate::GetButtons() const {
    372   return callback_.is_null() ? BUTTON_NONE : BUTTON_OK;
    373 }
    374 
    375 base::string16 PluginInstallerInfoBarDelegate::GetButtonLabel(
    376     InfoBarButton button) const {
    377   DCHECK_EQ(BUTTON_OK, button);
    378   return l10n_util::GetStringUTF16(IDS_PLUGININSTALLER_INSTALLPLUGIN_BUTTON);
    379 }
    380 
    381 bool PluginInstallerInfoBarDelegate::Accept() {
    382   callback_.Run(plugin_metadata_.get());
    383   return false;
    384 }
    385 
    386 base::string16 PluginInstallerInfoBarDelegate::GetLinkText() const {
    387   return l10n_util::GetStringUTF16(new_install_ ?
    388       IDS_PLUGININSTALLER_PROBLEMSINSTALLING :
    389       IDS_PLUGININSTALLER_PROBLEMSUPDATING);
    390 }
    391 
    392 bool PluginInstallerInfoBarDelegate::LinkClicked(
    393     WindowOpenDisposition disposition) {
    394   GURL url(plugin_metadata_->help_url());
    395   if (url.is_empty()) {
    396     url = GURL(
    397         "https://www.google.com/support/chrome/bin/answer.py?answer=142064");
    398   }
    399   InfoBarService::WebContentsFromInfoBar(infobar())->OpenURL(
    400       content::OpenURLParams(
    401           url, content::Referrer(),
    402           (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
    403           content::PAGE_TRANSITION_LINK, false));
    404   return false;
    405 }
    406 
    407 void PluginInstallerInfoBarDelegate::DownloadStarted() {
    408   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOADING,
    409                                                 plugin_metadata_->name()));
    410 }
    411 
    412 void PluginInstallerInfoBarDelegate::DownloadCancelled() {
    413   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_CANCELLED,
    414                                                 plugin_metadata_->name()));
    415 }
    416 
    417 void PluginInstallerInfoBarDelegate::DownloadError(const std::string& message) {
    418   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_ERROR_SHORT,
    419                                                 plugin_metadata_->name()));
    420 }
    421 
    422 void PluginInstallerInfoBarDelegate::DownloadFinished() {
    423   ReplaceWithInfoBar(
    424       l10n_util::GetStringFUTF16(
    425           new_install_ ? IDS_PLUGIN_INSTALLING : IDS_PLUGIN_UPDATING,
    426           plugin_metadata_->name()));
    427 }
    428 
    429 void PluginInstallerInfoBarDelegate::OnlyWeakObserversLeft() {
    430   infobar()->RemoveSelf();
    431 }
    432 
    433 void PluginInstallerInfoBarDelegate::ReplaceWithInfoBar(
    434     const base::string16& message) {
    435   // Return early if the message doesn't change. This is important in case the
    436   // PluginInstaller is still iterating over its observers (otherwise we would
    437   // keep replacing infobar delegates infinitely).
    438   if ((message_ == message) || !infobar()->owner())
    439     return;
    440   Replace(infobar(), installer(), plugin_metadata_->Clone(), new_install_,
    441           message);
    442 }
    443 
    444 
    445 #if defined(OS_WIN)
    446 
    447 // PluginMetroModeInfoBarDelegate ---------------------------------------------
    448 
    449 // static
    450 void PluginMetroModeInfoBarDelegate::Create(
    451     InfoBarService* infobar_service,
    452     PluginMetroModeInfoBarDelegate::Mode mode,
    453     const base::string16& name) {
    454   infobar_service->AddInfoBar(ConfirmInfoBarDelegate::CreateInfoBar(
    455       scoped_ptr<ConfirmInfoBarDelegate>(
    456           new PluginMetroModeInfoBarDelegate(mode, name))));
    457 }
    458 
    459 PluginMetroModeInfoBarDelegate::PluginMetroModeInfoBarDelegate(
    460     PluginMetroModeInfoBarDelegate::Mode mode,
    461     const base::string16& name)
    462     : ConfirmInfoBarDelegate(),
    463       mode_(mode),
    464       name_(name) {
    465 }
    466 
    467 PluginMetroModeInfoBarDelegate::~PluginMetroModeInfoBarDelegate() {
    468 }
    469 
    470 int PluginMetroModeInfoBarDelegate::GetIconID() const {
    471   return IDR_INFOBAR_PLUGIN_INSTALL;
    472 }
    473 
    474 base::string16 PluginMetroModeInfoBarDelegate::GetMessageText() const {
    475   return l10n_util::GetStringFUTF16((mode_ == MISSING_PLUGIN) ?
    476       IDS_METRO_MISSING_PLUGIN_PROMPT : IDS_METRO_NPAPI_PLUGIN_PROMPT, name_);
    477 }
    478 
    479 int PluginMetroModeInfoBarDelegate::GetButtons() const {
    480   return BUTTON_OK;
    481 }
    482 
    483 base::string16 PluginMetroModeInfoBarDelegate::GetButtonLabel(
    484     InfoBarButton button) const {
    485 #if defined(USE_AURA) && defined(USE_ASH)
    486   return l10n_util::GetStringUTF16(IDS_WIN8_DESKTOP_RESTART);
    487 #else
    488   return l10n_util::GetStringUTF16((mode_ == MISSING_PLUGIN) ?
    489       IDS_WIN8_DESKTOP_RESTART : IDS_WIN8_DESKTOP_OPEN);
    490 #endif
    491 }
    492 
    493 #if defined(USE_AURA) && defined(USE_ASH)
    494 void LaunchDesktopInstanceHelper(const base::string16& url) {
    495   base::FilePath exe_path;
    496   if (!PathService::Get(base::FILE_EXE, &exe_path))
    497     return;
    498   base::FilePath shortcut_path(
    499       ShellIntegration::GetStartMenuShortcut(exe_path));
    500 
    501   // Actually launching the process needs to happen in the metro viewer,
    502   // otherwise it won't automatically transition to desktop.  So we have
    503   // to send an IPC to the viewer to do the ShellExecute.
    504   aura::RemoteWindowTreeHostWin::Instance()->HandleOpenURLOnDesktop(
    505       shortcut_path, url);
    506 }
    507 #endif
    508 
    509 bool PluginMetroModeInfoBarDelegate::Accept() {
    510   chrome::AttemptRestartToDesktopMode();
    511   return true;
    512 }
    513 
    514 base::string16 PluginMetroModeInfoBarDelegate::GetLinkText() const {
    515   return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
    516 }
    517 
    518 bool PluginMetroModeInfoBarDelegate::LinkClicked(
    519     WindowOpenDisposition disposition) {
    520   // TODO(shrikant): We may need to change language a little at following
    521   // support URLs. With new approach we will just restart for both missing
    522   // and not missing mode.
    523   InfoBarService::WebContentsFromInfoBar(infobar())->OpenURL(
    524       content::OpenURLParams(
    525           GURL((mode_ == MISSING_PLUGIN) ?
    526               "https://support.google.com/chrome/?p=ib_display_in_desktop" :
    527               "https://support.google.com/chrome/?p=ib_redirect_to_desktop"),
    528           content::Referrer(),
    529           (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
    530           content::PAGE_TRANSITION_LINK, false));
    531   return false;
    532 }
    533 
    534 #endif  // defined(OS_WIN)
    535 
    536 #endif  // defined(ENABLE_PLUGIN_INSTALLATION)
    537