OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/extensions/extension_disabled_ui.h" | 5 #include "chrome/browser/extensions/extension_disabled_ui.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/callback_forward.h" |
10 #include "base/lazy_instance.h" | 11 #include "base/lazy_instance.h" |
11 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
12 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
| 14 #include "base/memory/weak_ptr.h" |
13 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
14 #include "base/metrics/histogram.h" | 16 #include "base/metrics/histogram.h" |
15 #include "base/strings/utf_string_conversions.h" | 17 #include "base/strings/utf_string_conversions.h" |
16 #include "chrome/app/chrome_command_ids.h" | 18 #include "chrome/app/chrome_command_ids.h" |
17 #include "chrome/browser/chrome_notification_types.h" | 19 #include "chrome/browser/chrome_notification_types.h" |
18 #include "chrome/browser/extensions/extension_install_prompt.h" | 20 #include "chrome/browser/extensions/extension_install_prompt.h" |
19 #include "chrome/browser/extensions/extension_install_ui.h" | 21 #include "chrome/browser/extensions/extension_install_ui.h" |
20 #include "chrome/browser/extensions/extension_service.h" | 22 #include "chrome/browser/extensions/extension_service.h" |
21 #include "chrome/browser/extensions/extension_uninstall_dialog.h" | 23 #include "chrome/browser/extensions/extension_uninstall_dialog.h" |
22 #include "chrome/browser/extensions/image_loader.h" | 24 #include "chrome/browser/extensions/image_loader.h" |
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 | 163 |
162 // ExtensionUninstallDialog::Delegate implementation. | 164 // ExtensionUninstallDialog::Delegate implementation. |
163 virtual void ExtensionUninstallAccepted() OVERRIDE; | 165 virtual void ExtensionUninstallAccepted() OVERRIDE; |
164 virtual void ExtensionUninstallCanceled() OVERRIDE; | 166 virtual void ExtensionUninstallCanceled() OVERRIDE; |
165 | 167 |
166 // content::NotificationObserver implementation. | 168 // content::NotificationObserver implementation. |
167 virtual void Observe(int type, | 169 virtual void Observe(int type, |
168 const content::NotificationSource& source, | 170 const content::NotificationSource& source, |
169 const content::NotificationDetails& details) OVERRIDE; | 171 const content::NotificationDetails& details) OVERRIDE; |
170 | 172 |
| 173 // Callback to notify UI that extension has been removed. |
| 174 void HandleExtensionRemoved(const Extension* extension); |
| 175 |
171 private: | 176 private: |
172 ExtensionService* service_; | 177 base::WeakPtr<ExtensionService> service_weak_; |
173 const Extension* extension_; | 178 const Extension* extension_; |
174 gfx::Image icon_; | 179 gfx::Image icon_; |
175 | 180 |
176 // How the user responded to the error; used for metrics. | 181 // How the user responded to the error; used for metrics. |
177 enum UserResponse { | 182 enum UserResponse { |
178 IGNORED, | 183 IGNORED, |
179 REENABLE, | 184 REENABLE, |
180 UNINSTALL, | 185 UNINSTALL, |
181 EXTENSION_DISABLED_UI_BUCKET_BOUNDARY | 186 EXTENSION_DISABLED_UI_BUCKET_BOUNDARY |
182 }; | 187 }; |
183 UserResponse user_response_; | 188 UserResponse user_response_; |
184 | 189 |
185 scoped_ptr<ExtensionUninstallDialog> uninstall_dialog_; | 190 scoped_ptr<ExtensionUninstallDialog> uninstall_dialog_; |
186 | 191 |
187 // Menu command ID assigned for this extension's error. | 192 // Menu command ID assigned for this extension's error. |
188 int menu_command_id_; | 193 int menu_command_id_; |
189 | 194 |
190 content::NotificationRegistrar registrar_; | 195 content::NotificationRegistrar registrar_; |
| 196 base::WeakPtrFactory<ExtensionDisabledGlobalError> weak_factory_; |
| 197 base::Callback<void(const Extension*)> on_removed_callback_; |
191 }; | 198 }; |
192 | 199 |
193 // TODO(yoz): create error at startup for disabled extensions. | 200 // TODO(yoz): create error at startup for disabled extensions. |
194 ExtensionDisabledGlobalError::ExtensionDisabledGlobalError( | 201 ExtensionDisabledGlobalError::ExtensionDisabledGlobalError( |
195 ExtensionService* service, | 202 ExtensionService* service, |
196 const Extension* extension, | 203 const Extension* extension, |
197 const gfx::Image& icon) | 204 const gfx::Image& icon) |
198 : service_(service), | 205 : service_weak_(service->AsWeakPtr()), |
199 extension_(extension), | 206 extension_(extension), |
200 icon_(icon), | 207 icon_(icon), |
201 user_response_(IGNORED), | 208 user_response_(IGNORED), |
202 menu_command_id_(GetMenuCommandID()) { | 209 menu_command_id_(GetMenuCommandID()), |
| 210 weak_factory_(this) { |
203 if (icon_.IsEmpty()) { | 211 if (icon_.IsEmpty()) { |
204 icon_ = gfx::Image( | 212 icon_ = gfx::Image( |
205 gfx::ImageSkiaOperations::CreateResizedImage( | 213 gfx::ImageSkiaOperations::CreateResizedImage( |
206 extension_->is_app() ? | 214 extension_->is_app() ? |
207 extensions::IconsInfo::GetDefaultAppIcon() : | 215 extensions::IconsInfo::GetDefaultAppIcon() : |
208 extensions::IconsInfo::GetDefaultExtensionIcon(), | 216 extensions::IconsInfo::GetDefaultExtensionIcon(), |
209 skia::ImageOperations::RESIZE_BEST, | 217 skia::ImageOperations::RESIZE_BEST, |
210 gfx::Size(kIconSize, kIconSize))); | 218 gfx::Size(kIconSize, kIconSize))); |
211 } | 219 } |
212 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, | 220 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, |
213 content::Source<Profile>(service->profile())); | 221 content::Source<Profile>(service->profile())); |
214 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_REMOVED, | 222 if (service_weak_.get()) { |
215 content::Source<Profile>(service->profile())); | 223 on_removed_callback_ = base::Bind( |
| 224 &ExtensionDisabledGlobalError::HandleExtensionRemoved, |
| 225 weak_factory_.GetWeakPtr()); |
| 226 service_weak_->RegisterExtensionRemovedCallback(on_removed_callback_); |
| 227 } |
| 228 |
216 } | 229 } |
217 | 230 |
218 ExtensionDisabledGlobalError::~ExtensionDisabledGlobalError() { | 231 ExtensionDisabledGlobalError::~ExtensionDisabledGlobalError() { |
| 232 if (service_weak_.get()) |
| 233 service_weak_->RemoveExtensionRemovedCallback(on_removed_callback_); |
219 ReleaseMenuCommandID(menu_command_id_); | 234 ReleaseMenuCommandID(menu_command_id_); |
220 UMA_HISTOGRAM_ENUMERATION("Extensions.DisabledUIUserResponse", | 235 UMA_HISTOGRAM_ENUMERATION("Extensions.DisabledUIUserResponse", |
221 user_response_, | 236 user_response_, |
222 EXTENSION_DISABLED_UI_BUCKET_BOUNDARY); | 237 EXTENSION_DISABLED_UI_BUCKET_BOUNDARY); |
223 } | 238 } |
224 | 239 |
225 GlobalError::Severity ExtensionDisabledGlobalError::GetSeverity() { | 240 GlobalError::Severity ExtensionDisabledGlobalError::GetSeverity() { |
226 return SEVERITY_LOW; | 241 return SEVERITY_LOW; |
227 } | 242 } |
228 | 243 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
283 } | 298 } |
284 | 299 |
285 void ExtensionDisabledGlobalError::OnBubbleViewDidClose(Browser* browser) { | 300 void ExtensionDisabledGlobalError::OnBubbleViewDidClose(Browser* browser) { |
286 } | 301 } |
287 | 302 |
288 void ExtensionDisabledGlobalError::BubbleViewAcceptButtonPressed( | 303 void ExtensionDisabledGlobalError::BubbleViewAcceptButtonPressed( |
289 Browser* browser) { | 304 Browser* browser) { |
290 // Delay extension reenabling so this bubble closes properly. | 305 // Delay extension reenabling so this bubble closes properly. |
291 base::MessageLoop::current()->PostTask(FROM_HERE, | 306 base::MessageLoop::current()->PostTask(FROM_HERE, |
292 base::Bind(&ExtensionService::GrantPermissionsAndEnableExtension, | 307 base::Bind(&ExtensionService::GrantPermissionsAndEnableExtension, |
293 service_->AsWeakPtr(), extension_)); | 308 service_weak_, extension_)); |
294 } | 309 } |
295 | 310 |
296 void ExtensionDisabledGlobalError::BubbleViewCancelButtonPressed( | 311 void ExtensionDisabledGlobalError::BubbleViewCancelButtonPressed( |
297 Browser* browser) { | 312 Browser* browser) { |
298 #if !defined(OS_ANDROID) | 313 #if !defined(OS_ANDROID) |
299 uninstall_dialog_.reset( | 314 uninstall_dialog_.reset(ExtensionUninstallDialog::Create( |
300 ExtensionUninstallDialog::Create(service_->profile(), browser, this)); | 315 service_weak_->profile(), browser, this)); |
301 // Delay showing the uninstall dialog, so that this function returns | 316 // Delay showing the uninstall dialog, so that this function returns |
302 // immediately, to close the bubble properly. See crbug.com/121544. | 317 // immediately, to close the bubble properly. See crbug.com/121544. |
303 base::MessageLoop::current()->PostTask(FROM_HERE, | 318 base::MessageLoop::current()->PostTask(FROM_HERE, |
304 base::Bind(&ExtensionUninstallDialog::ConfirmUninstall, | 319 base::Bind(&ExtensionUninstallDialog::ConfirmUninstall, |
305 uninstall_dialog_->AsWeakPtr(), extension_)); | 320 uninstall_dialog_->AsWeakPtr(), extension_)); |
306 #endif // !defined(OS_ANDROID) | 321 #endif // !defined(OS_ANDROID) |
307 } | 322 } |
308 | 323 |
309 void ExtensionDisabledGlobalError::ExtensionUninstallAccepted() { | 324 void ExtensionDisabledGlobalError::ExtensionUninstallAccepted() { |
310 service_->UninstallExtension(extension_->id(), false, NULL); | 325 if (service_weak_.get()) |
| 326 service_weak_->UninstallExtension(extension_->id(), false, NULL); |
311 } | 327 } |
312 | 328 |
313 void ExtensionDisabledGlobalError::ExtensionUninstallCanceled() { | 329 void ExtensionDisabledGlobalError::ExtensionUninstallCanceled() { |
314 // Nothing happens, and the error is still there. | 330 // Nothing happens, and the error is still there. |
315 } | 331 } |
316 | 332 |
317 void ExtensionDisabledGlobalError::Observe( | 333 void ExtensionDisabledGlobalError::Observe( |
318 int type, | 334 int type, |
319 const content::NotificationSource& source, | 335 const content::NotificationSource& source, |
320 const content::NotificationDetails& details) { | 336 const content::NotificationDetails& details) { |
321 // The error is invalidated if the extension has been loaded or removed. | 337 // The error is invalidated if the extension has been loaded or removed. |
322 DCHECK(type == chrome::NOTIFICATION_EXTENSION_LOADED || | 338 DCHECK(type == chrome::NOTIFICATION_EXTENSION_LOADED); |
323 type == chrome::NOTIFICATION_EXTENSION_REMOVED); | |
324 const Extension* extension = content::Details<const Extension>(details).ptr(); | 339 const Extension* extension = content::Details<const Extension>(details).ptr(); |
325 if (extension != extension_) | 340 if (extension != extension_) |
326 return; | 341 return; |
327 GlobalErrorServiceFactory::GetForProfile(service_->profile())-> | 342 if (service_weak_.get()) { |
328 RemoveGlobalError(this); | 343 GlobalErrorServiceFactory::GetForProfile(service_weak_->profile())-> |
329 | 344 RemoveGlobalError(this); |
330 if (type == chrome::NOTIFICATION_EXTENSION_LOADED) | 345 } |
331 user_response_ = REENABLE; | 346 user_response_ = REENABLE; |
332 else if (type == chrome::NOTIFICATION_EXTENSION_REMOVED) | |
333 user_response_ = UNINSTALL; | |
334 delete this; | 347 delete this; |
335 } | 348 } |
336 | 349 |
| 350 void ExtensionDisabledGlobalError::HandleExtensionRemoved( |
| 351 const Extension* extension) { |
| 352 if (extension != extension_) |
| 353 return; |
| 354 if (service_weak_.get()) { |
| 355 GlobalErrorServiceFactory::GetForProfile(service_weak_->profile())-> |
| 356 RemoveGlobalError(this); |
| 357 } |
| 358 user_response_ = UNINSTALL; |
| 359 delete this; |
| 360 } |
| 361 |
337 // Globals -------------------------------------------------------------------- | 362 // Globals -------------------------------------------------------------------- |
338 | 363 |
339 namespace extensions { | 364 namespace extensions { |
340 | 365 |
341 void AddExtensionDisabledErrorWithIcon(base::WeakPtr<ExtensionService> service, | 366 void AddExtensionDisabledErrorWithIcon(base::WeakPtr<ExtensionService> service, |
342 const std::string& extension_id, | 367 const std::string& extension_id, |
343 const gfx::Image& icon) { | 368 const gfx::Image& icon) { |
344 if (!service.get()) | 369 if (!service.get()) |
345 return; | 370 return; |
346 const Extension* extension = service->GetInstalledExtension(extension_id); | 371 const Extension* extension = service->GetInstalledExtension(extension_id); |
(...skipping 18 matching lines...) Expand all Loading... |
365 void ShowExtensionDisabledDialog(ExtensionService* service, | 390 void ShowExtensionDisabledDialog(ExtensionService* service, |
366 content::WebContents* web_contents, | 391 content::WebContents* web_contents, |
367 const Extension* extension) { | 392 const Extension* extension) { |
368 scoped_ptr<ExtensionInstallPrompt> install_ui( | 393 scoped_ptr<ExtensionInstallPrompt> install_ui( |
369 new ExtensionInstallPrompt(web_contents)); | 394 new ExtensionInstallPrompt(web_contents)); |
370 // This object manages its own lifetime. | 395 // This object manages its own lifetime. |
371 new ExtensionDisabledDialogDelegate(service, install_ui.Pass(), extension); | 396 new ExtensionDisabledDialogDelegate(service, install_ui.Pass(), extension); |
372 } | 397 } |
373 | 398 |
374 } // namespace extensions | 399 } // namespace extensions |
OLD | NEW |