Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(376)

Side by Side Diff: chrome/browser/extensions/external_install_ui.cc

Issue 11150002: New post-sideload UI: (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: sail Created 8 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2012 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/external_install_ui.h"
6
7 #include <string>
8
9 #include "base/bind.h"
10 #include "base/lazy_instance.h"
11 #include "base/memory/ref_counted.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/message_loop.h"
14 #include "base/metrics/histogram.h"
15 #include "base/utf_string_conversions.h"
16 #include "chrome/app/chrome_command_ids.h"
17 #include "chrome/browser/extensions/extension_install_prompt.h"
18 #include "chrome/browser/extensions/extension_service.h"
19 #include "chrome/browser/extensions/extension_uninstall_dialog.h"
20 #include "chrome/browser/profiles/profile.h"
21 #include "chrome/browser/ui/browser.h"
22 #include "chrome/browser/ui/global_error/global_error.h"
23 #include "chrome/browser/ui/global_error/global_error_service.h"
24 #include "chrome/browser/ui/global_error/global_error_service_factory.h"
25 #include "chrome/common/chrome_notification_types.h"
26 #include "chrome/common/extensions/extension.h"
27 #include "content/public/browser/notification_details.h"
28 #include "content/public/browser/notification_observer.h"
29 #include "content/public/browser/notification_registrar.h"
30 #include "content/public/browser/notification_source.h"
31 #include "grit/chromium_strings.h"
32 #include "grit/generated_resources.h"
33 #include "grit/theme_resources.h"
34 #include "ui/base/l10n/l10n_util.h"
35
36 namespace extensions {
37
38 static const int kMenuCommandId = IDC_EXTERNAL_EXTENSION_ALERT;
39
40 // ExternalInstallDialogDelegate --------------------------------------------
41
42 // TODO(mpcomplete): Get rid of the refcounting on this class, or document
43 // why it's necessary. Will do after refactoring to merge back with
44 // ExtensionDisabledDialogDelegate.
45 class ExternalInstallDialogDelegate
46 : public ExtensionInstallPrompt::Delegate,
47 public base::RefCountedThreadSafe<ExternalInstallDialogDelegate> {
48 public:
49 ExternalInstallDialogDelegate(Browser* browser,
50 ExtensionService* service,
51 const Extension* extension);
52
53 private:
54 friend class base::RefCountedThreadSafe<ExternalInstallDialogDelegate>;
55
56 virtual ~ExternalInstallDialogDelegate();
57
58 // ExtensionInstallPrompt::Delegate:
59 virtual void InstallUIProceed() OVERRIDE;
60 virtual void InstallUIAbort(bool user_initiated) OVERRIDE;
61
62 // The UI for showing the install dialog when enabling.
63 scoped_ptr<ExtensionInstallPrompt> install_ui_;
64
65 ExtensionService* service_;
66 const Extension* extension_;
67 };
68
69 ExternalInstallDialogDelegate::ExternalInstallDialogDelegate(
70 Browser* browser,
71 ExtensionService* service,
72 const Extension* extension)
73 : service_(service), extension_(extension) {
74 AddRef(); // Balanced in Proceed or Abort.
75
76 install_ui_.reset(chrome::CreateExtensionInstallPromptWithBrowser(browser));
77 install_ui_->ConfirmExternalInstall(this, extension_);
78 }
79
80 ExternalInstallDialogDelegate::~ExternalInstallDialogDelegate() {
81 }
82
83 void ExternalInstallDialogDelegate::InstallUIProceed() {
84 service_->GrantPermissionsAndEnableExtension(
85 extension_, install_ui_->record_oauth2_grant());
86 Release();
87 }
88
89 void ExternalInstallDialogDelegate::InstallUIAbort(bool user_initiated) {
90 service_->UninstallExtension(extension_->id(), false, NULL);
91 Release();
92 }
93
94 static void ShowExternalInstallDialog(ExtensionService* service,
95 Browser* browser,
96 const Extension* extension) {
97 // This object manages its own lifetime.
98 new ExternalInstallDialogDelegate(browser, service, extension);
99 }
100
101 // ExternalInstallGlobalError -----------------------------------------------
102
103 class ExternalInstallGlobalError : public GlobalError,
104 public content::NotificationObserver {
105 public:
106 ExternalInstallGlobalError(ExtensionService* service,
107 const Extension* extension);
108 virtual ~ExternalInstallGlobalError();
109
110 const Extension* extension() const { return extension_; }
111
112 // GlobalError implementation.
113 virtual bool HasBadge() OVERRIDE;
114 virtual int GetBadgeResourceID() OVERRIDE;
115 virtual bool HasMenuItem() OVERRIDE;
116 virtual int MenuItemCommandID() OVERRIDE;
117 virtual string16 MenuItemLabel() OVERRIDE;
118 virtual int MenuItemIconResourceID() OVERRIDE;
119 virtual void ExecuteMenuItem(Browser* browser) OVERRIDE;
120 virtual bool HasBubbleView() OVERRIDE;
121 virtual string16 GetBubbleViewTitle() OVERRIDE;
122 virtual string16 GetBubbleViewMessage() OVERRIDE;
123 virtual string16 GetBubbleViewAcceptButtonLabel() OVERRIDE;
124 virtual string16 GetBubbleViewCancelButtonLabel() OVERRIDE;
125 virtual void OnBubbleViewDidClose(Browser* browser) OVERRIDE;
126 virtual void BubbleViewAcceptButtonPressed(Browser* browser) OVERRIDE;
127 virtual void BubbleViewCancelButtonPressed(Browser* browser) OVERRIDE;
128
129 // content::NotificationObserver implementation.
130 virtual void Observe(int type,
131 const content::NotificationSource& source,
132 const content::NotificationDetails& details) OVERRIDE;
133
134 private:
135 ExtensionService* service_;
136 const Extension* extension_;
137
138 // How the user responded to the error; used for metrics.
139 enum UserResponse {
140 IGNORED,
141 REENABLE,
142 UNINSTALL,
143 USER_RESPONSE_BUCKET_BOUNDARY
144 };
145 UserResponse user_response_;
146
147 content::NotificationRegistrar registrar_;
148 };
149
150 ExternalInstallGlobalError::ExternalInstallGlobalError(
151 ExtensionService* service,
152 const Extension* extension)
153 : service_(service),
154 extension_(extension),
155 user_response_(IGNORED) {
156 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
157 content::Source<Profile>(service->profile()));
158 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
159 content::Source<Profile>(service->profile()));
160 }
161
162 ExternalInstallGlobalError::~ExternalInstallGlobalError() {
163 HISTOGRAM_ENUMERATION("Extensions.ExternalInstallUIUserResponse",
164 user_response_, USER_RESPONSE_BUCKET_BOUNDARY);
165 }
166
167 bool ExternalInstallGlobalError::HasBadge() {
168 return true;
169 }
170
171 int ExternalInstallGlobalError::GetBadgeResourceID() {
172 return IDR_UPDATE_BADGE_EXTENSION;
173 }
174
175 bool ExternalInstallGlobalError::HasMenuItem() {
176 return true;
177 }
178
179 int ExternalInstallGlobalError::MenuItemCommandID() {
180 return kMenuCommandId;
Yoyo Zhou 2012/10/16 23:28:05 nit: could be inlined.
181 }
182
183 int ExternalInstallGlobalError::MenuItemIconResourceID() {
184 return IDR_UPDATE_MENU_EXTENSION;
185 }
186
187 string16 ExternalInstallGlobalError::MenuItemLabel() {
188 return l10n_util::GetStringFUTF16(IDS_EXTENSION_EXTERNAL_INSTALL_ALERT,
189 UTF8ToUTF16(extension_->name()));
190 }
191
192 void ExternalInstallGlobalError::ExecuteMenuItem(Browser* browser) {
193 ShowExternalInstallDialog(service_, browser, extension_);
194 }
195
196 bool ExternalInstallGlobalError::HasBubbleView() {
197 return false;
198 }
199
200 string16 ExternalInstallGlobalError::GetBubbleViewTitle() {
201 return string16();
202 }
203
204 string16 ExternalInstallGlobalError::GetBubbleViewMessage() {
205 return string16();
206 }
207
208 string16 ExternalInstallGlobalError::GetBubbleViewAcceptButtonLabel() {
209 return string16();
210 }
211
212 string16 ExternalInstallGlobalError::GetBubbleViewCancelButtonLabel() {
213 return string16();
214 }
215
216 void ExternalInstallGlobalError::OnBubbleViewDidClose(Browser* browser) {
217 NOTREACHED();
218 }
219
220 void ExternalInstallGlobalError::BubbleViewAcceptButtonPressed(
221 Browser* browser) {
222 NOTREACHED();
223 }
224
225 void ExternalInstallGlobalError::BubbleViewCancelButtonPressed(
226 Browser* browser) {
227 NOTREACHED();
228 }
229
230 void ExternalInstallGlobalError::Observe(
231 int type,
232 const content::NotificationSource& source,
233 const content::NotificationDetails& details) {
234 const Extension* extension = NULL;
235 // The error is invalidated if the extension has been reloaded
236 // or unloaded.
237 if (type == chrome::NOTIFICATION_EXTENSION_LOADED) {
238 extension = content::Details<const Extension>(details).ptr();
239 } else {
240 DCHECK_EQ(chrome::NOTIFICATION_EXTENSION_UNLOADED, type);
241 extensions::UnloadedExtensionInfo* info =
242 content::Details<extensions::UnloadedExtensionInfo>(details).ptr();
243 extension = info->extension;
244 }
245 if (extension == extension_) {
246 // We only check for new external installs on startup, so these
247 // notifications are guaranteed to be user-initiated.
248 if (type == chrome::NOTIFICATION_EXTENSION_LOADED)
249 user_response_ = REENABLE;
250 else if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED)
251 user_response_ = UNINSTALL;
252
253 // This call deletes us (via Add/RemoveExternalInstallError).
254 service_->AcknowledgeExternalExtension(extension_->id());
255 }
256 }
257
258 // Public interface ---------------------------------------------------------
259
260 bool AddExternalInstallError(ExtensionService* service,
261 const Extension* extension) {
262 GlobalErrorService* error_service =
263 GlobalErrorServiceFactory::GetForProfile(service->profile());
264 GlobalError* error = error_service->GetGlobalErrorByMenuItemCommandID(
265 kMenuCommandId);
266 if (error) {
267 if (static_cast<ExternalInstallGlobalError*>(error)->extension() ==
268 extension) {
269 return false; // already showing
Yoyo Zhou 2012/10/16 23:28:05 Would you want this if the error was already showi
Matt Perry 2012/10/17 00:02:44 You're right. I had myself convinced that we neede
270 }
271 error_service->RemoveGlobalError(error);
272 delete error;
273 }
274
275 error_service->AddGlobalError(
276 new ExternalInstallGlobalError(service, extension));
277 return true;
278 }
279
280 void RemoveExternalInstallError(ExtensionService* service) {
281 GlobalErrorService* error_service =
282 GlobalErrorServiceFactory::GetForProfile(service->profile());
283 GlobalError* error = error_service->GetGlobalErrorByMenuItemCommandID(
284 kMenuCommandId);
285 if (error) {
286 error_service->RemoveGlobalError(error);
287 delete error;
288 }
289 }
290
291 bool HasExternalInstallError(ExtensionService* service) {
292 GlobalErrorService* error_service =
293 GlobalErrorServiceFactory::GetForProfile(service->profile());
294 GlobalError* error = error_service->GetGlobalErrorByMenuItemCommandID(
295 kMenuCommandId);
296 return !!error;
297 }
298
299 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698