- add sources.
[platform/framework/web/crosswalk.git] / src / chrome / browser / plugins / plugin_infobar_delegates.cc
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/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"
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_root_window_host_win.h"
43 #endif
44 #endif
45
46 using content::UserMetricsAction;
47
48
49 // PluginInfoBarDelegate ------------------------------------------------------
50
51 PluginInfoBarDelegate::PluginInfoBarDelegate(InfoBarService* infobar_service,
52                                              const std::string& identifier)
53     : ConfirmInfoBarDelegate(infobar_service),
54       identifier_(identifier) {
55 }
56
57 PluginInfoBarDelegate::~PluginInfoBarDelegate() {
58 }
59
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));
65   return false;
66 }
67
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_));
74 }
75
76 int PluginInfoBarDelegate::GetIconID() const {
77   return IDR_INFOBAR_PLUGIN_INSTALL;
78 }
79
80 string16 PluginInfoBarDelegate::GetLinkText() const {
81   return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
82 }
83
84
85 // UnauthorizedPluginInfoBarDelegate ------------------------------------------
86
87 // static
88 void UnauthorizedPluginInfoBarDelegate::Create(
89     InfoBarService* infobar_service,
90     HostContentSettingsMap* content_settings,
91     const string16& name,
92     const std::string& identifier) {
93   infobar_service->AddInfoBar(scoped_ptr<InfoBarDelegate>(
94       new UnauthorizedPluginInfoBarDelegate(infobar_service, content_settings,
95                                             name, identifier)));
96
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"));
113   }
114 }
115
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),
123       name_(name) {
124 }
125
126 UnauthorizedPluginInfoBarDelegate::~UnauthorizedPluginInfoBarDelegate() {
127   content::RecordAction(UserMetricsAction("BlockedPluginInfobar.Closed"));
128 }
129
130 std::string UnauthorizedPluginInfoBarDelegate::GetLearnMoreURL() const {
131   return chrome::kBlockedPluginLearnMoreURL;
132 }
133
134 string16 UnauthorizedPluginInfoBarDelegate::GetMessageText() const {
135   return l10n_util::GetStringFUTF16(IDS_PLUGIN_NOT_AUTHORIZED, name_);
136 }
137
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);
142 }
143
144 bool UnauthorizedPluginInfoBarDelegate::Accept() {
145   content::RecordAction(
146       UserMetricsAction("BlockedPluginInfobar.AllowThisTime"));
147   LoadBlockedPlugins();
148   return true;
149 }
150
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();
157   return true;
158 }
159
160 void UnauthorizedPluginInfoBarDelegate::InfoBarDismissed() {
161   content::RecordAction(UserMetricsAction("BlockedPluginInfobar.Dismissed"));
162 }
163
164 bool UnauthorizedPluginInfoBarDelegate::LinkClicked(
165     WindowOpenDisposition disposition) {
166   content::RecordAction(UserMetricsAction("BlockedPluginInfobar.LearnMore"));
167   return PluginInfoBarDelegate::LinkClicked(disposition);
168 }
169
170
171 #if defined(ENABLE_PLUGIN_INSTALLATION)
172
173 // OutdatedPluginInfoBarDelegate ----------------------------------------------
174
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,
188               name))));
189 }
190
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()),
199       message_(message) {
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"));
220   }
221 }
222
223 OutdatedPluginInfoBarDelegate::~OutdatedPluginInfoBarDelegate() {
224   content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Closed"));
225 }
226
227 std::string OutdatedPluginInfoBarDelegate::GetLearnMoreURL() const {
228   return chrome::kOutdatedPluginLearnMoreURL;
229 }
230
231 string16 OutdatedPluginInfoBarDelegate::GetMessageText() const {
232   return message_;
233 }
234
235 string16 OutdatedPluginInfoBarDelegate::GetButtonLabel(
236     InfoBarButton button) const {
237   return l10n_util::GetStringUTF16((button == BUTTON_OK) ?
238       IDS_PLUGIN_UPDATE : IDS_PLUGIN_ENABLE_TEMPORARILY);
239 }
240
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());
250   else
251     installer()->StartInstalling(plugin_url, web_contents());
252   return false;
253 }
254
255 bool OutdatedPluginInfoBarDelegate::Cancel() {
256   content::RecordAction(
257       UserMetricsAction("OutdatedPluginInfobar.AllowThisTime"));
258   LoadBlockedPlugins();
259   return true;
260 }
261
262 void OutdatedPluginInfoBarDelegate::InfoBarDismissed() {
263   content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.Dismissed"));
264 }
265
266 bool OutdatedPluginInfoBarDelegate::LinkClicked(
267     WindowOpenDisposition disposition) {
268   content::RecordAction(UserMetricsAction("OutdatedPluginInfobar.LearnMore"));
269   return PluginInfoBarDelegate::LinkClicked(disposition);
270 }
271
272 void OutdatedPluginInfoBarDelegate::DownloadStarted() {
273   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOADING,
274                                                 plugin_metadata_->name()));
275 }
276
277 void OutdatedPluginInfoBarDelegate::DownloadError(const std::string& message) {
278   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_ERROR_SHORT,
279                                                 plugin_metadata_->name()));
280 }
281
282 void OutdatedPluginInfoBarDelegate::DownloadCancelled() {
283   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_CANCELLED,
284                                                 plugin_metadata_->name()));
285 }
286
287 void OutdatedPluginInfoBarDelegate::DownloadFinished() {
288   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_UPDATING,
289                                                 plugin_metadata_->name()));
290 }
291
292 void OutdatedPluginInfoBarDelegate::OnlyWeakObserversLeft() {
293   if (owner())
294     owner()->RemoveInfoBar(this);
295 }
296
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())
303     return;
304   PluginInstallerInfoBarDelegate::Replace(
305       this, installer(), plugin_metadata_->Clone(), false, message);
306 }
307
308
309 // PluginInstallerInfoBarDelegate ---------------------------------------------
310
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());
317 #if defined(OS_WIN)
318   if (base::win::IsMetroProcess()) {
319     PluginMetroModeInfoBarDelegate::Create(
320         infobar_service, PluginMetroModeInfoBarDelegate::MISSING_PLUGIN, name);
321     return;
322   }
323 #endif
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,
331               name))));
332
333 }
334
335 void PluginInstallerInfoBarDelegate::Replace(
336     InfoBarDelegate* infobar,
337     PluginInstaller* installer,
338     scoped_ptr<PluginMetadata> plugin_metadata,
339     bool new_install,
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,
346           message)));
347 }
348
349 PluginInstallerInfoBarDelegate::PluginInstallerInfoBarDelegate(
350     InfoBarService* infobar_service,
351     PluginInstaller* installer,
352     scoped_ptr<PluginMetadata> plugin_metadata,
353     const InstallCallback& callback,
354     bool new_install,
355     const string16& message)
356     : ConfirmInfoBarDelegate(infobar_service),
357       WeakPluginInstallerObserver(installer),
358       plugin_metadata_(plugin_metadata.Pass()),
359       callback_(callback),
360       new_install_(new_install),
361       message_(message) {
362 }
363
364 PluginInstallerInfoBarDelegate::~PluginInstallerInfoBarDelegate() {
365 }
366
367 int PluginInstallerInfoBarDelegate::GetIconID() const {
368   return IDR_INFOBAR_PLUGIN_INSTALL;
369 }
370
371 string16 PluginInstallerInfoBarDelegate::GetMessageText() const {
372   return message_;
373 }
374
375 int PluginInstallerInfoBarDelegate::GetButtons() const {
376   return callback_.is_null() ? BUTTON_NONE : BUTTON_OK;
377 }
378
379 string16 PluginInstallerInfoBarDelegate::GetButtonLabel(
380     InfoBarButton button) const {
381   DCHECK_EQ(BUTTON_OK, button);
382   return l10n_util::GetStringUTF16(IDS_PLUGININSTALLER_INSTALLPLUGIN_BUTTON);
383 }
384
385 bool PluginInstallerInfoBarDelegate::Accept() {
386   callback_.Run(plugin_metadata_.get());
387   return false;
388 }
389
390 string16 PluginInstallerInfoBarDelegate::GetLinkText() const {
391   return l10n_util::GetStringUTF16(new_install_ ?
392       IDS_PLUGININSTALLER_PROBLEMSINSTALLING :
393       IDS_PLUGININSTALLER_PROBLEMSUPDATING);
394 }
395
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"));
402   }
403   web_contents()->OpenURL(content::OpenURLParams(
404       url, content::Referrer(),
405       (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
406       content::PAGE_TRANSITION_LINK, false));
407   return false;
408 }
409
410 void PluginInstallerInfoBarDelegate::DownloadStarted() {
411   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOADING,
412                                                 plugin_metadata_->name()));
413 }
414
415 void PluginInstallerInfoBarDelegate::DownloadCancelled() {
416   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_CANCELLED,
417                                                 plugin_metadata_->name()));
418 }
419
420 void PluginInstallerInfoBarDelegate::DownloadError(const std::string& message) {
421   ReplaceWithInfoBar(l10n_util::GetStringFUTF16(IDS_PLUGIN_DOWNLOAD_ERROR_SHORT,
422                                                 plugin_metadata_->name()));
423 }
424
425 void PluginInstallerInfoBarDelegate::DownloadFinished() {
426   ReplaceWithInfoBar(
427       l10n_util::GetStringFUTF16(
428           new_install_ ? IDS_PLUGIN_INSTALLING : IDS_PLUGIN_UPDATING,
429           plugin_metadata_->name()));
430 }
431
432 void PluginInstallerInfoBarDelegate::OnlyWeakObserversLeft() {
433   if (owner())
434     owner()->RemoveInfoBar(this);
435 }
436
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())
443     return;
444   Replace(this, installer(), plugin_metadata_->Clone(), new_install_, message);
445 }
446
447
448 #if defined(OS_WIN)
449
450 // PluginMetroModeInfoBarDelegate ---------------------------------------------
451
452 // static
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)));
459 }
460
461 PluginMetroModeInfoBarDelegate::PluginMetroModeInfoBarDelegate(
462     InfoBarService* infobar_service,
463     PluginMetroModeInfoBarDelegate::Mode mode,
464     const string16& name)
465     : ConfirmInfoBarDelegate(infobar_service),
466       mode_(mode),
467       name_(name) {
468 }
469
470 PluginMetroModeInfoBarDelegate::~PluginMetroModeInfoBarDelegate() {
471 }
472
473 int PluginMetroModeInfoBarDelegate::GetIconID() const {
474   return IDR_INFOBAR_PLUGIN_INSTALL;
475 }
476
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_);
480 }
481
482 int PluginMetroModeInfoBarDelegate::GetButtons() const {
483   return BUTTON_OK;
484 }
485
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);
490 #else
491   return l10n_util::GetStringUTF16((mode_ == MISSING_PLUGIN) ?
492       IDS_WIN8_DESKTOP_RESTART : IDS_WIN8_DESKTOP_OPEN);
493 #endif
494 }
495
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))
500     return;
501   base::FilePath shortcut_path(
502       ShellIntegration::GetStartMenuShortcut(exe_path));
503
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(
508       shortcut_path, url);
509 }
510 #endif
511
512 bool PluginMetroModeInfoBarDelegate::Accept() {
513   chrome::AttemptRestartToDesktopMode();
514   return true;
515 }
516
517 string16 PluginMetroModeInfoBarDelegate::GetLinkText() const {
518   return l10n_util::GetStringUTF16(IDS_LEARN_MORE);
519 }
520
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"),
530       content::Referrer(),
531       (disposition == CURRENT_TAB) ? NEW_FOREGROUND_TAB : disposition,
532       content::PAGE_TRANSITION_LINK, false));
533   return false;
534 }
535
536 #endif  // defined(OS_WIN)
537
538 #endif  // defined(ENABLE_PLUGIN_INSTALLATION)