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 "chrome/browser/chrome_notification_types.h"
11 #include "chrome/browser/extensions/image_loader.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/ui/browser.h"
14 #include "chrome/common/extensions/extension.h"
15 #include "chrome/common/extensions/extension_constants.h"
16 #include "chrome/common/extensions/extension_icon_set.h"
17 #include "chrome/common/extensions/manifest_handlers/icons_handler.h"
18 #include "content/public/browser/notification_service.h"
19 #include "content/public/browser/notification_source.h"
20 #include "extensions/common/extension_resource.h"
21 #include "grit/generated_resources.h"
22 #include "grit/theme_resources.h"
23 #include "ui/base/resource/resource_bundle.h"
24 #include "ui/gfx/image/image.h"
25 #include "ui/gfx/image/image_skia.h"
29 // Returns pixel size under maximal scale factor for the icon whose device
30 // independent size is |size_in_dip|
31 int GetSizeForMaxScaleFactor(int size_in_dip
) {
32 float max_scale_factor_scale
= gfx::ImageSkia::GetMaxSupportedScale();
34 return static_cast<int>(size_in_dip
* max_scale_factor_scale
);
37 // Returns bitmap for the default icon with size equal to the default icon's
38 // pixel size under maximal supported scale factor.
39 SkBitmap
GetDefaultIconBitmapForMaxScaleFactor(bool is_app
) {
40 const gfx::ImageSkia
& image
= is_app
?
41 extensions::IconsInfo::GetDefaultAppIcon() :
42 extensions::IconsInfo::GetDefaultExtensionIcon();
43 return image
.GetRepresentation(
44 gfx::ImageSkia::GetMaxSupportedScale()).sk_bitmap();
49 // Size of extension icon in top left of dialog.
50 static const int kIconSize
= 69;
52 ExtensionUninstallDialog::ExtensionUninstallDialog(
55 ExtensionUninstallDialog::Delegate
* delegate
)
60 state_(kImageIsLoading
),
61 ui_loop_(base::MessageLoop::current()) {
64 chrome::NOTIFICATION_BROWSER_CLOSED
,
65 content::Source
<Browser
>(browser
));
69 ExtensionUninstallDialog::~ExtensionUninstallDialog() {
72 void ExtensionUninstallDialog::ConfirmUninstall(
73 const extensions::Extension
* extension
) {
74 DCHECK(ui_loop_
== base::MessageLoop::current());
75 extension_
= extension
;
76 extensions::ExtensionResource image
= extensions::IconsInfo::GetIconResource(
78 extension_misc::EXTENSION_ICON_LARGE
,
79 ExtensionIconSet::MATCH_BIGGER
);
80 // Load the icon whose pixel size is large enough to be displayed under
81 // maximal supported scale factor. UI code will scale the icon down if needed.
82 int pixel_size
= GetSizeForMaxScaleFactor(kIconSize
);
84 // Load the image asynchronously. The response will be sent to OnImageLoaded.
85 state_
= kImageIsLoading
;
86 extensions::ImageLoader
* loader
=
87 extensions::ImageLoader::Get(profile_
);
88 loader
->LoadImageAsync(extension_
, image
,
89 gfx::Size(pixel_size
, pixel_size
),
90 base::Bind(&ExtensionUninstallDialog::OnImageLoaded
,
94 void ExtensionUninstallDialog::SetIcon(const gfx::Image
& image
) {
95 if (image
.IsEmpty()) {
96 // Let's set default icon bitmap whose size is equal to the default icon's
97 // pixel size under maximal supported scale factor. If the bitmap is larger
98 // than the one we need, it will be scaled down by the ui code.
99 // TODO(tbarzic): We should use IconImage here and load the required bitmap
101 icon_
= gfx::ImageSkia::CreateFrom1xBitmap(
102 GetDefaultIconBitmapForMaxScaleFactor(extension_
->is_app()));
104 icon_
= *image
.ToImageSkia();
108 void ExtensionUninstallDialog::OnImageLoaded(const gfx::Image
& image
) {
111 // Show the dialog unless the browser has been closed while we were waiting
113 DCHECK(state_
== kImageIsLoading
|| state_
== kBrowserIsClosing
);
114 if (state_
== kImageIsLoading
) {
115 state_
= kDialogIsShowing
;
120 void ExtensionUninstallDialog::Observe(
122 const content::NotificationSource
& source
,
123 const content::NotificationDetails
& details
) {
124 DCHECK(type
== chrome::NOTIFICATION_BROWSER_CLOSED
);
127 // If the browser is closed while waiting for the image, we need to send a
128 // "cancel" event here, because there will not be another opportunity to
129 // notify the delegate of the cancellation as we won't open the dialog.
130 if (state_
== kImageIsLoading
) {
131 state_
= kBrowserIsClosing
;
132 delegate_
->ExtensionUninstallCanceled();