Home | History | Annotate | Download | only in extensions
      1 // Copyright (c) 2011 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/extensions/extension_disabled_infobar_delegate.h"
      6 
      7 #include <string>
      8 
      9 #include "base/utf_string_conversions.h"
     10 #include "chrome/browser/extensions/extension_install_ui.h"
     11 #include "chrome/browser/extensions/extension_service.h"
     12 #include "chrome/browser/tab_contents/confirm_infobar_delegate.h"
     13 #include "chrome/browser/ui/browser_list.h"
     14 #include "chrome/common/extensions/extension_file_util.h"
     15 #include "chrome/common/extensions/extension_resource.h"
     16 #include "content/browser/tab_contents/tab_contents.h"
     17 #include "content/common/notification_details.h"
     18 #include "content/common/notification_registrar.h"
     19 #include "content/common/notification_source.h"
     20 #include "grit/generated_resources.h"
     21 #include "ui/base/l10n/l10n_util.h"
     22 
     23 // ExtensionDisabledDialogDelegate --------------------------------------------
     24 
     25 class ExtensionDisabledDialogDelegate
     26     : public ExtensionInstallUI::Delegate,
     27       public base::RefCountedThreadSafe<ExtensionDisabledDialogDelegate> {
     28  public:
     29   ExtensionDisabledDialogDelegate(Profile* profile,
     30                                   ExtensionService* service,
     31                                   const Extension* extension);
     32 
     33  private:
     34   friend class base::RefCountedThreadSafe<ExtensionDisabledDialogDelegate>;
     35 
     36   virtual ~ExtensionDisabledDialogDelegate();
     37 
     38   // ExtensionInstallUI::Delegate:
     39   virtual void InstallUIProceed();
     40   virtual void InstallUIAbort();
     41 
     42   // The UI for showing the install dialog when enabling.
     43   scoped_ptr<ExtensionInstallUI> install_ui_;
     44 
     45   ExtensionService* service_;
     46   const Extension* extension_;
     47 };
     48 
     49 ExtensionDisabledDialogDelegate::ExtensionDisabledDialogDelegate(
     50     Profile* profile,
     51     ExtensionService* service,
     52     const Extension* extension)
     53     : service_(service), extension_(extension) {
     54   AddRef();  // Balanced in Proceed or Abort.
     55 
     56   install_ui_.reset(new ExtensionInstallUI(profile));
     57   install_ui_->ConfirmReEnable(this, extension_);
     58 }
     59 
     60 ExtensionDisabledDialogDelegate::~ExtensionDisabledDialogDelegate() {
     61 }
     62 
     63 void ExtensionDisabledDialogDelegate::InstallUIProceed() {
     64   service_->GrantPermissionsAndEnableExtension(extension_);
     65   Release();
     66 }
     67 
     68 void ExtensionDisabledDialogDelegate::InstallUIAbort() {
     69   ExtensionService::RecordPermissionMessagesHistogram(
     70       extension_, "Extensions.Permissions_ReEnableCancel");
     71 
     72   // Do nothing. The extension will remain disabled.
     73   Release();
     74 }
     75 
     76 
     77 // ExtensionDisabledInfobarDelegate -------------------------------------------
     78 
     79 class ExtensionDisabledInfobarDelegate : public ConfirmInfoBarDelegate,
     80                                          public NotificationObserver {
     81  public:
     82   ExtensionDisabledInfobarDelegate(TabContents* tab_contents,
     83                                    ExtensionService* service,
     84                                    const Extension* extension);
     85 
     86  private:
     87   virtual ~ExtensionDisabledInfobarDelegate();
     88 
     89   // ConfirmInfoBarDelegate:
     90   virtual void InfoBarClosed();
     91   virtual string16 GetMessageText() const;
     92   virtual int GetButtons() const;
     93   virtual string16 GetButtonLabel(InfoBarButton button) const;
     94   virtual bool Accept();
     95 
     96   // NotificationObserver:
     97   virtual void Observe(NotificationType type,
     98                        const NotificationSource& source,
     99                        const NotificationDetails& details);
    100 
    101   NotificationRegistrar registrar_;
    102   TabContents* tab_contents_;
    103   ExtensionService* service_;
    104   const Extension* extension_;
    105 };
    106 
    107 ExtensionDisabledInfobarDelegate::ExtensionDisabledInfobarDelegate(
    108     TabContents* tab_contents,
    109     ExtensionService* service,
    110     const Extension* extension)
    111     : ConfirmInfoBarDelegate(tab_contents),
    112       tab_contents_(tab_contents),
    113       service_(service),
    114       extension_(extension) {
    115   // The user might re-enable the extension in other ways, so watch for that.
    116   registrar_.Add(this, NotificationType::EXTENSION_LOADED,
    117                  Source<Profile>(service->profile()));
    118   registrar_.Add(this, NotificationType::EXTENSION_UNLOADED,
    119                  Source<Profile>(service->profile()));
    120 }
    121 
    122 ExtensionDisabledInfobarDelegate::~ExtensionDisabledInfobarDelegate() {
    123 }
    124 
    125 void ExtensionDisabledInfobarDelegate::InfoBarClosed() {
    126   delete this;
    127 }
    128 
    129 string16 ExtensionDisabledInfobarDelegate::GetMessageText() const {
    130   return l10n_util::GetStringFUTF16(extension_->is_app() ?
    131       IDS_APP_DISABLED_INFOBAR_LABEL : IDS_EXTENSION_DISABLED_INFOBAR_LABEL,
    132       UTF8ToUTF16(extension_->name()));
    133 }
    134 
    135 int ExtensionDisabledInfobarDelegate::GetButtons() const {
    136   return BUTTON_OK;
    137 }
    138 
    139 string16 ExtensionDisabledInfobarDelegate::GetButtonLabel(
    140     InfoBarButton button) const {
    141   DCHECK_EQ(BUTTON_OK, button);
    142   return l10n_util::GetStringUTF16(
    143       IDS_EXTENSION_DISABLED_INFOBAR_ENABLE_BUTTON);
    144 }
    145 
    146 bool ExtensionDisabledInfobarDelegate::Accept() {
    147   // This object manages its own lifetime.
    148   new ExtensionDisabledDialogDelegate(tab_contents_->profile(), service_,
    149                                       extension_);
    150   return true;
    151 }
    152 
    153 void ExtensionDisabledInfobarDelegate::Observe(
    154     NotificationType type,
    155     const NotificationSource& source,
    156     const NotificationDetails& details) {
    157   // TODO(mpcomplete): RemoveInfoBar doesn't seem to always result in us getting
    158   // deleted.
    159   const Extension* extension;
    160   if (type.value == NotificationType::EXTENSION_LOADED) {
    161     extension = Details<const Extension>(details).ptr();
    162   } else {
    163     DCHECK_EQ(NotificationType::EXTENSION_UNLOADED, type.value);
    164     UnloadedExtensionInfo* info = Details<UnloadedExtensionInfo>(details).ptr();
    165     extension = (info->reason == UnloadedExtensionInfo::DISABLE) ?
    166         info->extension : NULL;
    167   }
    168   if (extension == extension_)
    169     tab_contents_->RemoveInfoBar(this);
    170 }
    171 
    172 
    173 // Globals --------------------------------------------------------------------
    174 
    175 void ShowExtensionDisabledUI(ExtensionService* service, Profile* profile,
    176                              const Extension* extension) {
    177   Browser* browser = BrowserList::GetLastActiveWithProfile(profile);
    178   if (!browser)
    179     return;
    180 
    181   TabContents* tab_contents = browser->GetSelectedTabContents();
    182   if (!tab_contents)
    183     return;
    184 
    185   tab_contents->AddInfoBar(new ExtensionDisabledInfobarDelegate(
    186       tab_contents, service, extension));
    187 }
    188 
    189 void ShowExtensionDisabledDialog(ExtensionService* service, Profile* profile,
    190                                  const Extension* extension) {
    191   // This object manages its own lifetime.
    192   new ExtensionDisabledDialogDelegate(profile, service, extension);
    193 }
    194