Add a webstorePrivate API to show a permission prompt for delegated bundle installs
[chromium-blink-merge.git] / chrome / browser / extensions / extension_uninstall_dialog.cc
blob16c6a721c8b552dc1b55b0939a3af7e1dd39fb20
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 // Returns bitmap for the default icon with size equal to the default icon's
42 // pixel size under maximal supported scale factor.
43 SkBitmap GetDefaultIconBitmapForMaxScaleFactor(bool is_app) {
44 const gfx::ImageSkia& image =
45 is_app ? util::GetDefaultAppIcon() : util::GetDefaultExtensionIcon();
46 return image.GetRepresentation(
47 gfx::ImageSkia::GetMaxSupportedScale()).sk_bitmap();
50 } // namespace
52 ExtensionUninstallDialog::ExtensionUninstallDialog(
53 Profile* profile,
54 ExtensionUninstallDialog::Delegate* delegate)
55 : profile_(profile),
56 delegate_(delegate),
57 uninstall_reason_(UNINSTALL_REASON_FOR_TESTING) {
60 ExtensionUninstallDialog::~ExtensionUninstallDialog() {
63 void ExtensionUninstallDialog::ConfirmUninstallByExtension(
64 const scoped_refptr<const Extension>& extension,
65 const scoped_refptr<const Extension>& triggering_extension,
66 UninstallReason reason) {
67 triggering_extension_ = triggering_extension;
68 ConfirmUninstall(extension, reason);
71 void ExtensionUninstallDialog::ConfirmUninstall(
72 const scoped_refptr<const Extension>& extension,
73 UninstallReason reason) {
74 DCHECK(thread_checker_.CalledOnValidThread());
75 extension_ = extension;
76 uninstall_reason_ = reason;
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_.get(), icon_size, ExtensionIconSet::MATCH_BIGGER);
84 // Load the image asynchronously. The response will be sent to OnImageLoaded.
85 ImageLoader* loader = ImageLoader::Get(profile_);
87 SetIcon(gfx::Image());
88 std::vector<ImageLoader::ImageRepresentation> images_list;
89 images_list.push_back(ImageLoader::ImageRepresentation(
90 image,
91 ImageLoader::ImageRepresentation::NEVER_RESIZE,
92 gfx::Size(),
93 ui::SCALE_FACTOR_100P));
94 loader->LoadImagesAsync(extension_.get(), images_list,
95 base::Bind(&ExtensionUninstallDialog::OnImageLoaded,
96 AsWeakPtr(), extension_->id()));
99 void ExtensionUninstallDialog::SetIcon(const gfx::Image& image) {
100 if (image.IsEmpty()) {
101 // Let's set default icon bitmap whose size is equal to the default icon's
102 // pixel size under maximal supported scale factor. If the bitmap is larger
103 // than the one we need, it will be scaled down by the ui code.
104 // TODO(tbarzic): We should use IconImage here and load the required bitmap
105 // lazily.
106 icon_ = gfx::ImageSkia::CreateFrom1xBitmap(
107 GetDefaultIconBitmapForMaxScaleFactor(extension_->is_app()));
108 } else {
109 icon_ = *image.ToImageSkia();
113 void ExtensionUninstallDialog::OnImageLoaded(const std::string& extension_id,
114 const gfx::Image& image) {
115 const Extension* target_extension =
116 ExtensionRegistry::Get(profile_)
117 ->GetExtensionById(extension_id, ExtensionRegistry::EVERYTHING);
118 if (!target_extension) {
119 delegate_->OnExtensionUninstallDialogClosed(
120 false, base::ASCIIToUTF16(kExtensionRemovedError));
121 return;
124 SetIcon(image);
126 switch (ScopedTestDialogAutoConfirm::GetAutoConfirmValue()) {
127 case ScopedTestDialogAutoConfirm::NONE:
128 Show();
129 break;
130 case ScopedTestDialogAutoConfirm::ACCEPT:
131 OnDialogClosed(CLOSE_ACTION_UNINSTALL);
132 break;
133 case ScopedTestDialogAutoConfirm::CANCEL:
134 OnDialogClosed(CLOSE_ACTION_CANCELED);
135 break;
139 std::string ExtensionUninstallDialog::GetHeadingText() {
140 if (triggering_extension_) {
141 return l10n_util::GetStringFUTF8(
142 IDS_EXTENSION_PROGRAMMATIC_UNINSTALL_PROMPT_HEADING,
143 base::UTF8ToUTF16(triggering_extension_->name()),
144 base::UTF8ToUTF16(extension_->name()));
146 return l10n_util::GetStringFUTF8(IDS_EXTENSION_UNINSTALL_PROMPT_HEADING,
147 base::UTF8ToUTF16(extension_->name()));
150 bool ExtensionUninstallDialog::ShouldShowReportAbuseCheckbox() const {
151 return ManifestURL::UpdatesFromGallery(extension_.get());
154 void ExtensionUninstallDialog::OnDialogClosed(CloseAction action) {
155 // We don't want to artificially weight any of the options, so only record if
156 // reporting abuse was available.
157 if (ShouldShowReportAbuseCheckbox()) {
158 UMA_HISTOGRAM_ENUMERATION("Extensions.UninstallDialogAction",
159 action,
160 CLOSE_ACTION_LAST);
163 bool success = false;
164 base::string16 error;
165 switch (action) {
166 case CLOSE_ACTION_UNINSTALL_AND_REPORT_ABUSE:
167 HandleReportAbuse();
168 // Fall through.
169 case CLOSE_ACTION_UNINSTALL: {
170 const Extension* current_extension =
171 ExtensionRegistry::Get(profile_)->GetExtensionById(
172 extension_->id(), ExtensionRegistry::EVERYTHING);
173 if (current_extension) {
174 success =
175 ExtensionSystem::Get(profile_)
176 ->extension_service()
177 ->UninstallExtension(extension_->id(), uninstall_reason_,
178 base::Bind(&base::DoNothing), &error);
179 } else {
180 error = base::ASCIIToUTF16(kExtensionRemovedError);
182 break;
184 case CLOSE_ACTION_CANCELED:
185 error = base::ASCIIToUTF16("User canceled uninstall dialog");
186 break;
187 case CLOSE_ACTION_LAST:
188 NOTREACHED();
191 delegate_->OnExtensionUninstallDialogClosed(success, error);
194 void ExtensionUninstallDialog::HandleReportAbuse() {
195 chrome::NavigateParams params(
196 profile_,
197 extension_urls::GetWebstoreReportAbuseUrl(extension_->id()),
198 ui::PAGE_TRANSITION_LINK);
199 params.disposition = NEW_FOREGROUND_TAB;
200 chrome::Navigate(&params);
203 } // namespace extensions