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.
5 #include "chrome/browser/extensions/extension_uninstall_dialog.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/strings/utf_string_conversions.h"
11 #include "chrome/browser/chrome_notification_types.h"
12 #include "chrome/browser/extensions/extension_util.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "content/public/browser/notification_service.h"
16 #include "content/public/browser/notification_source.h"
17 #include "extensions/browser/extension_registry.h"
18 #include "extensions/browser/image_loader.h"
19 #include "extensions/common/constants.h"
20 #include "extensions/common/extension.h"
21 #include "extensions/common/extension_icon_set.h"
22 #include "extensions/common/extension_resource.h"
23 #include "extensions/common/manifest_handlers/icons_handler.h"
24 #include "grit/generated_resources.h"
25 #include "grit/theme_resources.h"
26 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/base/resource/resource_bundle.h"
28 #include "ui/gfx/image/image.h"
29 #include "ui/gfx/image/image_skia.h"
31 namespace extensions {
35 // Returns bitmap for the default icon with size equal to the default icon's
36 // pixel size under maximal supported scale factor.
37 SkBitmap GetDefaultIconBitmapForMaxScaleFactor(bool is_app) {
38 const gfx::ImageSkia& image =
39 is_app ? util::GetDefaultAppIcon() : util::GetDefaultExtensionIcon();
40 return image.GetRepresentation(
41 gfx::ImageSkia::GetMaxSupportedScale()).sk_bitmap();
46 ExtensionUninstallDialog::ExtensionUninstallDialog(
49 ExtensionUninstallDialog::Delegate* delegate)
54 triggering_extension_(NULL),
55 state_(kImageIsLoading),
56 ui_loop_(base::MessageLoop::current()) {
59 chrome::NOTIFICATION_BROWSER_CLOSED,
60 content::Source<Browser>(browser));
64 ExtensionUninstallDialog::~ExtensionUninstallDialog() {
67 void ExtensionUninstallDialog::ConfirmProgrammaticUninstall(
68 const Extension* extension,
69 const Extension* triggering_extension) {
70 triggering_extension_ = triggering_extension;
71 ConfirmUninstall(extension);
74 void ExtensionUninstallDialog::ConfirmUninstall(const Extension* extension) {
75 DCHECK(ui_loop_ == base::MessageLoop::current());
76 extension_ = extension;
77 // Bookmark apps may not have 128x128 icons so accept 64x64 icons.
78 const int icon_size = extension_->from_bookmark()
79 ? extension_misc::EXTENSION_ICON_SMALL * 2
80 : extension_misc::EXTENSION_ICON_LARGE;
81 ExtensionResource image = IconsInfo::GetIconResource(
82 extension_, icon_size, ExtensionIconSet::MATCH_BIGGER);
84 // Load the image asynchronously. The response will be sent to OnImageLoaded.
85 state_ = kImageIsLoading;
86 ImageLoader* loader = ImageLoader::Get(profile_);
88 std::vector<ImageLoader::ImageRepresentation> images_list;
89 images_list.push_back(ImageLoader::ImageRepresentation(
91 ImageLoader::ImageRepresentation::NEVER_RESIZE,
93 ui::SCALE_FACTOR_100P));
94 loader->LoadImagesAsync(extension_,
96 base::Bind(&ExtensionUninstallDialog::OnImageLoaded,
101 void ExtensionUninstallDialog::SetIcon(const gfx::Image& image) {
102 if (image.IsEmpty()) {
103 // Let's set default icon bitmap whose size is equal to the default icon's
104 // pixel size under maximal supported scale factor. If the bitmap is larger
105 // than the one we need, it will be scaled down by the ui code.
106 // TODO(tbarzic): We should use IconImage here and load the required bitmap
108 icon_ = gfx::ImageSkia::CreateFrom1xBitmap(
109 GetDefaultIconBitmapForMaxScaleFactor(extension_->is_app()));
111 icon_ = *image.ToImageSkia();
115 void ExtensionUninstallDialog::OnImageLoaded(const std::string& extension_id,
116 const gfx::Image& image) {
117 const Extension* target_extension =
118 ExtensionRegistry::Get(profile_)
119 ->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING);
120 if (!target_extension) {
121 delegate_->ExtensionUninstallCanceled();
127 // Show the dialog unless the browser has been closed while we were waiting
129 DCHECK(state_ == kImageIsLoading || state_ == kBrowserIsClosing);
130 if (state_ == kImageIsLoading) {
131 state_ = kDialogIsShowing;
136 void ExtensionUninstallDialog::Observe(
138 const content::NotificationSource& source,
139 const content::NotificationDetails& details) {
140 DCHECK(type == chrome::NOTIFICATION_BROWSER_CLOSED);
143 // If the browser is closed while waiting for the image, we need to send a
144 // "cancel" event here, because there will not be another opportunity to
145 // notify the delegate of the cancellation as we won't open the dialog.
146 if (state_ == kImageIsLoading) {
147 state_ = kBrowserIsClosing;
148 delegate_->ExtensionUninstallCanceled();
152 std::string ExtensionUninstallDialog::GetHeadingText() {
153 if (triggering_extension_) {
154 return l10n_util::GetStringFUTF8(
155 IDS_EXTENSION_PROGRAMMATIC_UNINSTALL_PROMPT_HEADING,
156 base::UTF8ToUTF16(triggering_extension_->name()),
157 base::UTF8ToUTF16(extension_->name()));
159 return l10n_util::GetStringFUTF8(IDS_EXTENSION_UNINSTALL_PROMPT_HEADING,
160 base::UTF8ToUTF16(extension_->name()));
163 } // namespace extensions