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