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