172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be
3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file.
4c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
5c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_disabled_infobar_delegate.h"
6c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
73345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include <string>
83345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick
93345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick#include "base/utf_string_conversions.h"
10c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/browser/extensions/extension_install_ui.h"
1121d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/extensions/extension_service.h"
12dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/ui/browser_list.h"
14c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension_file_util.h"
15c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "chrome/common/extensions/extension_resource.h"
16dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "content/browser/tab_contents/tab_contents.h"
17ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_details.h"
18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_registrar.h"
19ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_source.h"
20c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch#include "grit/generated_resources.h"
2172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/l10n/l10n_util.h"
2272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
2372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// ExtensionDisabledDialogDelegate --------------------------------------------
24c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
25c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochclass ExtensionDisabledDialogDelegate
26c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    : public ExtensionInstallUI::Delegate,
27c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      public base::RefCountedThreadSafe<ExtensionDisabledDialogDelegate> {
28c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
29c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ExtensionDisabledDialogDelegate(Profile* profile,
3021d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                  ExtensionService* service,
3172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                  const Extension* extension);
32c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
33c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch private:
34c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  friend class base::RefCountedThreadSafe<ExtensionDisabledDialogDelegate>;
35c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
3672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual ~ExtensionDisabledDialogDelegate();
3772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
3872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // ExtensionInstallUI::Delegate:
3972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual void InstallUIProceed();
4072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual void InstallUIAbort();
41c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
42c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // The UI for showing the install dialog when enabling.
43c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  scoped_ptr<ExtensionInstallUI> install_ui_;
44c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  ExtensionService* service_;
46513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const Extension* extension_;
47c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
48c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
4972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenExtensionDisabledDialogDelegate::ExtensionDisabledDialogDelegate(
5072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    Profile* profile,
5172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ExtensionService* service,
5272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const Extension* extension)
5372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    : service_(service), extension_(extension) {
5472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  AddRef();  // Balanced in Proceed or Abort.
5572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
5672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  install_ui_.reset(new ExtensionInstallUI(profile));
57ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  install_ui_->ConfirmReEnable(this, extension_);
5872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
5972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
6072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenExtensionDisabledDialogDelegate::~ExtensionDisabledDialogDelegate() {
6172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
6272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
6372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ExtensionDisabledDialogDelegate::InstallUIProceed() {
6472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  service_->GrantPermissionsAndEnableExtension(extension_);
6572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  Release();
6672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
6772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
6872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ExtensionDisabledDialogDelegate::InstallUIAbort() {
69ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen  ExtensionService::RecordPermissionMessagesHistogram(
70ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen      extension_, "Extensions.Permissions_ReEnableCancel");
71ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen
7272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // Do nothing. The extension will remain disabled.
7372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  Release();
7472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
7572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
7672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
7772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// ExtensionDisabledInfobarDelegate -------------------------------------------
7872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
7972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenclass ExtensionDisabledInfobarDelegate : public ConfirmInfoBarDelegate,
8072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                         public NotificationObserver {
81c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch public:
82c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  ExtensionDisabledInfobarDelegate(TabContents* tab_contents,
8321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen                                   ExtensionService* service,
8472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                   const Extension* extension);
85c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
8672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen private:
8772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual ~ExtensionDisabledInfobarDelegate();
8872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
8972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // ConfirmInfoBarDelegate:
9072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual void InfoBarClosed();
9172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual string16 GetMessageText() const;
9272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual int GetButtons() const;
9372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual string16 GetButtonLabel(InfoBarButton button) const;
9472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  virtual bool Accept();
9572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
9672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // NotificationObserver:
97c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  virtual void Observe(NotificationType type,
98c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch                       const NotificationSource& source,
9972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                       const NotificationDetails& details);
100c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
101c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  NotificationRegistrar registrar_;
102c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TabContents* tab_contents_;
10321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen  ExtensionService* service_;
104513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch  const Extension* extension_;
105c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch};
106c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
10772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenExtensionDisabledInfobarDelegate::ExtensionDisabledInfobarDelegate(
10872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    TabContents* tab_contents,
10972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    ExtensionService* service,
11072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const Extension* extension)
11172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    : ConfirmInfoBarDelegate(tab_contents),
11272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      tab_contents_(tab_contents),
11372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      service_(service),
11472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      extension_(extension) {
11572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // The user might re-enable the extension in other ways, so watch for that.
11672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  registrar_.Add(this, NotificationType::EXTENSION_LOADED,
11772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                 Source<Profile>(service->profile()));
11872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
11972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                 Source<Profile>(service->profile()));
12072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
12172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
12272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian MonsenExtensionDisabledInfobarDelegate::~ExtensionDisabledInfobarDelegate() {
12372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
12472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
12572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ExtensionDisabledInfobarDelegate::InfoBarClosed() {
12672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  delete this;
12772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
12872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
12972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstring16 ExtensionDisabledInfobarDelegate::GetMessageText() const {
13072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return l10n_util::GetStringFUTF16(extension_->is_app() ?
13172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      IDS_APP_DISABLED_INFOBAR_LABEL : IDS_EXTENSION_DISABLED_INFOBAR_LABEL,
13272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      UTF8ToUTF16(extension_->name()));
13372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
13472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
13572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenint ExtensionDisabledInfobarDelegate::GetButtons() const {
13672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return BUTTON_OK;
13772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
13872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
13972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenstring16 ExtensionDisabledInfobarDelegate::GetButtonLabel(
14072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    InfoBarButton button) const {
14172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  DCHECK_EQ(BUTTON_OK, button);
14272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return l10n_util::GetStringUTF16(
14372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen      IDS_EXTENSION_DISABLED_INFOBAR_ENABLE_BUTTON);
14472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
14572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
14672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenbool ExtensionDisabledInfobarDelegate::Accept() {
14772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // This object manages its own lifetime.
14872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  new ExtensionDisabledDialogDelegate(tab_contents_->profile(), service_,
14972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen                                      extension_);
15072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  return true;
15172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
15272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
15372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsenvoid ExtensionDisabledInfobarDelegate::Observe(
15472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    NotificationType type,
15572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const NotificationSource& source,
15672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    const NotificationDetails& details) {
15772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // TODO(mpcomplete): RemoveInfoBar doesn't seem to always result in us getting
15872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  // deleted.
15972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  const Extension* extension;
16072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (type.value == NotificationType::EXTENSION_LOADED) {
16172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    extension = Details<const Extension>(details).ptr();
16272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  } else {
16372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    DCHECK_EQ(NotificationType::EXTENSION_UNLOADED, type.value);
16472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    UnloadedExtensionInfo* info = Details<UnloadedExtensionInfo>(details).ptr();
16572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    extension = (info->reason == UnloadedExtensionInfo::DISABLE) ?
16672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen        info->extension : NULL;
16772a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  }
16872a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen  if (extension == extension_)
16972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen    tab_contents_->RemoveInfoBar(this);
17072a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen}
17172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
17272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
17372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Globals --------------------------------------------------------------------
17472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen
17521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ShowExtensionDisabledUI(ExtensionService* service, Profile* profile,
176513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                             const Extension* extension) {
177c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  Browser* browser = BrowserList::GetLastActiveWithProfile(profile);
178c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!browser)
179c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
180c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
181c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  TabContents* tab_contents = browser->GetSelectedTabContents();
182c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  if (!tab_contents)
183c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch    return;
184c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
185c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  tab_contents->AddInfoBar(new ExtensionDisabledInfobarDelegate(
186c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch      tab_contents, service, extension));
187c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
188c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch
18921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsenvoid ShowExtensionDisabledDialog(ExtensionService* service, Profile* profile,
190513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch                                 const Extension* extension) {
191c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  // This object manages its own lifetime.
192c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch  new ExtensionDisabledDialogDelegate(profile, service, extension);
193c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch}
194