Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / extensions / extension_uninstall_dialog.cc
blobda9f0a061441515eb1f4ee38eafd1bab2c1abb14
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"
7 #include "base/bind.h"
8 #include "base/logging.h"
9 #include "base/message_loop/message_loop.h"
10 #include "base/metrics/histogram_macros.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/extensions/extension_util.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/browser_navigator.h"
16 #include "chrome/grit/generated_resources.h"
17 #include "extensions/browser/extension_dialog_auto_confirm.h"
18 #include "extensions/browser/extension_registry.h"
19 #include "extensions/browser/extension_system.h"
20 #include "extensions/browser/image_loader.h"
21 #include "extensions/common/constants.h"
22 #include "extensions/common/extension.h"
23 #include "extensions/common/extension_icon_set.h"
24 #include "extensions/common/extension_resource.h"
25 #include "extensions/common/extension_urls.h"
26 #include "extensions/common/manifest_handlers/icons_handler.h"
27 #include "extensions/common/manifest_url_handlers.h"
28 #include "ui/base/l10n/l10n_util.h"
29 #include "ui/base/page_transition_types.h"
30 #include "ui/base/window_open_disposition.h"
31 #include "ui/gfx/image/image.h"
32 #include "ui/gfx/image/image_skia.h"
34 namespace extensions {
36 namespace {
38 const char kExtensionRemovedError[] =
39 "Extension was removed before dialog closed.";
41 const char kReferrerId[] = "chrome-remove-extension-dialog";
43 // Returns bitmap for the default icon with size equal to the default icon's
44 // pixel size under maximal supported scale factor.
45 SkBitmap GetDefaultIconBitmapForMaxScaleFactor(bool is_app) {
46 const gfx::ImageSkia& image =
47 is_app ? util::GetDefaultAppIcon() : util::GetDefaultExtensionIcon();
48 return image.GetRepresentation(
49 gfx::ImageSkia::GetMaxSupportedScale()).sk_bitmap();
52 } // namespace
54 ExtensionUninstallDialog::ExtensionUninstallDialog(
55 Profile* profile,
56 ExtensionUninstallDialog::Delegate* delegate)
57 : profile_(profile),
58 delegate_(delegate),
59 uninstall_reason_(UNINSTALL_REASON_FOR_TESTING) {
62 ExtensionUninstallDialog::~ExtensionUninstallDialog() {
65 void ExtensionUninstallDialog::ConfirmUninstallByExtension(
66 const scoped_refptr<const Extension>& extension,
67 const scoped_refptr<const Extension>& triggering_extension,
68 UninstallReason reason,
69 UninstallSource source) {
70 triggering_extension_ = triggering_extension;
71 ConfirmUninstall(extension, reason, source);
74 void ExtensionUninstallDialog::ConfirmUninstall(
75 const scoped_refptr<const Extension>& extension,
76 UninstallReason reason,
77 UninstallSource source) {
78 DCHECK(thread_checker_.CalledOnValidThread());
80 UMA_HISTOGRAM_ENUMERATION("Extensions.UninstallSource", source,
81 NUM_UNINSTALL_SOURCES);
83 extension_ = extension;
84 uninstall_reason_ = reason;
85 // Bookmark apps may not have 128x128 icons so accept 64x64 icons.
86 const int icon_size = extension_->from_bookmark()
87 ? extension_misc::EXTENSION_ICON_SMALL * 2
88 : extension_misc::EXTENSION_ICON_LARGE;
89 ExtensionResource image = IconsInfo::GetIconResource(
90 extension_.get(), icon_size, ExtensionIconSet::MATCH_BIGGER);
92 // Load the image asynchronously. The response will be sent to OnImageLoaded.
93 ImageLoader* loader = ImageLoader::Get(profile_);
95 SetIcon(gfx::Image());
96 std::vector<ImageLoader::ImageRepresentation> images_list;
97 images_list.push_back(ImageLoader::ImageRepresentation(
98 image,
99 ImageLoader::ImageRepresentation::NEVER_RESIZE,
100 gfx::Size(),
101 ui::SCALE_FACTOR_100P));
102 loader->LoadImagesAsync(extension_.get(), images_list,
103 base::Bind(&ExtensionUninstallDialog::OnImageLoaded,
104 AsWeakPtr(), extension_->id()));
107 void ExtensionUninstallDialog::SetIcon(const gfx::Image& image) {
108 if (image.IsEmpty()) {
109 // Let's set default icon bitmap whose size is equal to the default icon's
110 // pixel size under maximal supported scale factor. If the bitmap is larger
111 // than the one we need, it will be scaled down by the ui code.
112 // TODO(tbarzic): We should use IconImage here and load the required bitmap
113 // lazily.
114 icon_ = gfx::ImageSkia::CreateFrom1xBitmap(
115 GetDefaultIconBitmapForMaxScaleFactor(extension_->is_app()));
116 } else {
117 icon_ = *image.ToImageSkia();
121 void ExtensionUninstallDialog::OnImageLoaded(const std::string& extension_id,
122 const gfx::Image& image) {
123 const Extension* target_extension =
124 ExtensionRegistry::Get(profile_)
125 ->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING);
126 if (!target_extension) {
127 delegate_->OnExtensionUninstallDialogClosed(
128 false, base::ASCIIToUTF16(kExtensionRemovedError));
129 return;
132 SetIcon(image);
134 switch (ScopedTestDialogAutoConfirm::GetAutoConfirmValue()) {
135 case ScopedTestDialogAutoConfirm::NONE:
136 Show();
137 break;
138 case ScopedTestDialogAutoConfirm::ACCEPT:
139 OnDialogClosed(CLOSE_ACTION_UNINSTALL);
140 break;
141 case ScopedTestDialogAutoConfirm::CANCEL:
142 OnDialogClosed(CLOSE_ACTION_CANCELED);
143 break;
147 std::string ExtensionUninstallDialog::GetHeadingText() {
148 if (triggering_extension_) {
149 return l10n_util::GetStringFUTF8(
150 IDS_EXTENSION_PROGRAMMATIC_UNINSTALL_PROMPT_HEADING,
151 base::UTF8ToUTF16(triggering_extension_->name()),
152 base::UTF8ToUTF16(extension_->name()));
154 return l10n_util::GetStringFUTF8(IDS_EXTENSION_UNINSTALL_PROMPT_HEADING,
155 base::UTF8ToUTF16(extension_->name()));
158 bool ExtensionUninstallDialog::ShouldShowReportAbuseCheckbox() const {
159 return ManifestURL::UpdatesFromGallery(extension_.get());
162 void ExtensionUninstallDialog::OnDialogClosed(CloseAction action) {
163 // We don't want to artificially weight any of the options, so only record if
164 // reporting abuse was available.
165 if (ShouldShowReportAbuseCheckbox()) {
166 UMA_HISTOGRAM_ENUMERATION("Extensions.UninstallDialogAction",
167 action,
168 CLOSE_ACTION_LAST);
171 bool success = false;
172 base::string16 error;
173 switch (action) {
174 case CLOSE_ACTION_UNINSTALL_AND_REPORT_ABUSE:
175 HandleReportAbuse();
176 // Fall through.
177 case CLOSE_ACTION_UNINSTALL: {
178 const Extension* current_extension =
179 ExtensionRegistry::Get(profile_)->GetExtensionById(
180 extension_->id(), ExtensionRegistry::EVERYTHING);
181 if (current_extension) {
182 success =
183 ExtensionSystem::Get(profile_)
184 ->extension_service()
185 ->UninstallExtension(extension_->id(), uninstall_reason_,
186 base::Bind(&base::DoNothing), &error);
187 } else {
188 error = base::ASCIIToUTF16(kExtensionRemovedError);
190 break;
192 case CLOSE_ACTION_CANCELED:
193 error = base::ASCIIToUTF16("User canceled uninstall dialog");
194 break;
195 case CLOSE_ACTION_LAST:
196 NOTREACHED();
199 delegate_->OnExtensionUninstallDialogClosed(success, error);
202 void ExtensionUninstallDialog::HandleReportAbuse() {
203 chrome::NavigateParams params(
204 profile_,
205 extension_urls::GetWebstoreReportAbuseUrl(extension_->id(), kReferrerId),
206 ui::PAGE_TRANSITION_LINK);
207 params.disposition = NEW_FOREGROUND_TAB;
208 chrome::Navigate(&params);
211 } // namespace extensions