• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
ExtensionDisabledDialogDelegate(Profile * profile,ExtensionService * service,const Extension * extension)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 
~ExtensionDisabledDialogDelegate()60 ExtensionDisabledDialogDelegate::~ExtensionDisabledDialogDelegate() {
61 }
62 
InstallUIProceed()63 void ExtensionDisabledDialogDelegate::InstallUIProceed() {
64   service_->GrantPermissionsAndEnableExtension(extension_);
65   Release();
66 }
67 
InstallUIAbort()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 
ExtensionDisabledInfobarDelegate(TabContents * tab_contents,ExtensionService * service,const Extension * extension)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 
~ExtensionDisabledInfobarDelegate()122 ExtensionDisabledInfobarDelegate::~ExtensionDisabledInfobarDelegate() {
123 }
124 
InfoBarClosed()125 void ExtensionDisabledInfobarDelegate::InfoBarClosed() {
126   delete this;
127 }
128 
GetMessageText() const129 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 
GetButtons() const135 int ExtensionDisabledInfobarDelegate::GetButtons() const {
136   return BUTTON_OK;
137 }
138 
GetButtonLabel(InfoBarButton button) const139 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 
Accept()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 
Observe(NotificationType type,const NotificationSource & source,const NotificationDetails & details)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 
ShowExtensionDisabledUI(ExtensionService * service,Profile * profile,const Extension * extension)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 
ShowExtensionDisabledDialog(ExtensionService * service,Profile * profile,const Extension * extension)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