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_install_prompt.h"
9 #include "base/command_line.h"
10 #include "base/message_loop/message_loop.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/strings/utf_string_conversions.h"
16 #include "chrome/browser/extensions/bundle_installer.h"
17 #include "chrome/browser/extensions/extension_install_ui.h"
18 #include "chrome/browser/extensions/extension_util.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/ui/browser.h"
21 #include "chrome/browser/ui/browser_window.h"
22 #include "chrome/common/chrome_switches.h"
23 #include "chrome/common/pref_names.h"
24 #include "content/public/browser/web_contents.h"
25 #include "extensions/browser/extension_prefs.h"
26 #include "extensions/browser/extension_util.h"
27 #include "extensions/browser/image_loader.h"
28 #include "extensions/common/constants.h"
29 #include "extensions/common/extension.h"
30 #include "extensions/common/extension_icon_set.h"
31 #include "extensions/common/extension_resource.h"
32 #include "extensions/common/feature_switch.h"
33 #include "extensions/common/manifest.h"
34 #include "extensions/common/manifest_constants.h"
35 #include "extensions/common/manifest_handlers/icons_handler.h"
36 #include "extensions/common/permissions/permission_message_provider.h"
37 #include "extensions/common/permissions/permission_set.h"
38 #include "extensions/common/permissions/permissions_data.h"
39 #include "extensions/common/url_pattern.h"
40 #include "grit/chromium_strings.h"
41 #include "grit/generated_resources.h"
42 #include "grit/theme_resources.h"
43 #include "ui/base/l10n/l10n_util.h"
44 #include "ui/base/resource/resource_bundle.h"
45 #include "ui/gfx/image/image.h"
47 using extensions::BundleInstaller;
48 using extensions::Extension;
49 using extensions::Manifest;
50 using extensions::PermissionSet;
54 static const int kTitleIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
55 0, // The regular install prompt depends on what's being installed.
56 IDS_EXTENSION_INLINE_INSTALL_PROMPT_TITLE,
57 IDS_EXTENSION_INSTALL_PROMPT_TITLE,
58 IDS_EXTENSION_RE_ENABLE_PROMPT_TITLE,
59 IDS_EXTENSION_PERMISSIONS_PROMPT_TITLE,
60 IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_TITLE,
61 IDS_EXTENSION_POST_INSTALL_PERMISSIONS_PROMPT_TITLE,
62 IDS_EXTENSION_LAUNCH_APP_PROMPT_TITLE,
63 0, // The remote install prompt depends on what's being installed.
65 static const int kHeadingIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
66 IDS_EXTENSION_INSTALL_PROMPT_HEADING,
67 0, // Inline installs use the extension name.
68 0, // Heading for bundle installs depends on the bundle contents.
69 IDS_EXTENSION_RE_ENABLE_PROMPT_HEADING,
70 IDS_EXTENSION_PERMISSIONS_PROMPT_HEADING,
71 0, // External installs use different strings for extensions/apps.
72 IDS_EXTENSION_POST_INSTALL_PERMISSIONS_PROMPT_HEADING,
73 IDS_EXTENSION_LAUNCH_APP_PROMPT_HEADING,
74 IDS_EXTENSION_REMOTE_INSTALL_PROMPT_HEADING,
76 static const int kButtons[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
77 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
78 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
79 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
80 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
81 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
82 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
83 ui::DIALOG_BUTTON_CANCEL,
84 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
85 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
87 static const int kAcceptButtonIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
88 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
89 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
90 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
91 IDS_EXTENSION_PROMPT_RE_ENABLE_BUTTON,
92 IDS_EXTENSION_PROMPT_PERMISSIONS_BUTTON,
93 0, // External installs use different strings for extensions/apps.
94 IDS_EXTENSION_PROMPT_PERMISSIONS_CLEAR_RETAINED_FILES_BUTTON,
95 IDS_EXTENSION_PROMPT_LAUNCH_BUTTON,
96 IDS_EXTENSION_PROMPT_REMOTE_INSTALL_BUTTON,
98 static const int kAbortButtonIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
99 0, // These all use the platform's default cancel label.
103 IDS_EXTENSION_PROMPT_PERMISSIONS_ABORT_BUTTON,
104 IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ABORT_BUTTON,
106 0, // Platform dependent cancel button.
110 kPermissionsHeaderIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
111 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
112 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
113 IDS_EXTENSION_PROMPT_THESE_WILL_HAVE_ACCESS_TO,
114 IDS_EXTENSION_PROMPT_WILL_NOW_HAVE_ACCESS_TO,
115 IDS_EXTENSION_PROMPT_WANTS_ACCESS_TO,
116 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
117 IDS_EXTENSION_PROMPT_CAN_ACCESS,
118 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
119 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
122 // Returns bitmap for the default icon with size equal to the default icon's
123 // pixel size under maximal supported scale factor.
124 SkBitmap GetDefaultIconBitmapForMaxScaleFactor(bool is_app) {
125 const gfx::ImageSkia& image = is_app ?
126 extensions::util::GetDefaultAppIcon() :
127 extensions::util::GetDefaultExtensionIcon();
128 return image.GetRepresentation(
129 gfx::ImageSkia::GetMaxSupportedScale()).sk_bitmap();
132 // If auto confirm is enabled then posts a task to proceed with or cancel the
133 // install and returns true. Otherwise returns false.
134 bool AutoConfirmPrompt(ExtensionInstallPrompt::Delegate* delegate) {
135 const CommandLine* cmdline = CommandLine::ForCurrentProcess();
136 if (!cmdline->HasSwitch(switches::kAppsGalleryInstallAutoConfirmForTests))
138 std::string value = cmdline->GetSwitchValueASCII(
139 switches::kAppsGalleryInstallAutoConfirmForTests);
141 // We use PostTask instead of calling the delegate directly here, because in
142 // the real implementations it's highly likely the message loop will be
143 // pumping a few times before the user clicks accept or cancel.
144 if (value == "accept") {
145 base::MessageLoop::current()->PostTask(
147 base::Bind(&ExtensionInstallPrompt::Delegate::InstallUIProceed,
148 base::Unretained(delegate)));
152 if (value == "cancel") {
153 base::MessageLoop::current()->PostTask(
155 base::Bind(&ExtensionInstallPrompt::Delegate::InstallUIAbort,
156 base::Unretained(delegate),
165 Profile* ProfileForWebContents(content::WebContents* web_contents) {
168 return Profile::FromBrowserContext(web_contents->GetBrowserContext());
171 gfx::NativeWindow NativeWindowForWebContents(content::WebContents* contents) {
175 return contents->GetTopLevelNativeWindow();
180 ExtensionInstallPrompt::Prompt::Prompt(PromptType type)
182 is_showing_details_for_retained_files_(false),
185 average_rating_(0.0),
187 show_user_count_(false),
188 has_webstore_data_(false) {
191 ExtensionInstallPrompt::Prompt::~Prompt() {
194 void ExtensionInstallPrompt::Prompt::SetPermissions(
195 const std::vector<base::string16>& permissions) {
196 permissions_ = permissions;
199 void ExtensionInstallPrompt::Prompt::SetPermissionsDetails(
200 const std::vector<base::string16>& details) {
202 is_showing_details_for_permissions_.clear();
203 for (size_t i = 0; i < details.size(); ++i)
204 is_showing_details_for_permissions_.push_back(false);
207 void ExtensionInstallPrompt::Prompt::SetIsShowingDetails(
210 bool is_showing_details) {
212 case PERMISSIONS_DETAILS:
213 is_showing_details_for_permissions_[index] = is_showing_details;
215 case RETAINED_FILES_DETAILS:
216 is_showing_details_for_retained_files_ = is_showing_details;
221 void ExtensionInstallPrompt::Prompt::SetWebstoreData(
222 const std::string& localized_user_count,
223 bool show_user_count,
224 double average_rating,
226 CHECK(type_ == INLINE_INSTALL_PROMPT || type_ == EXTERNAL_INSTALL_PROMPT);
227 localized_user_count_ = localized_user_count;
228 show_user_count_ = show_user_count;
229 average_rating_ = average_rating;
230 rating_count_ = rating_count;
231 has_webstore_data_ = true;
234 base::string16 ExtensionInstallPrompt::Prompt::GetDialogTitle() const {
235 int resource_id = kTitleIds[type_];
237 if (type_ == INSTALL_PROMPT) {
238 if (extension_->is_app())
239 resource_id = IDS_EXTENSION_INSTALL_APP_PROMPT_TITLE;
240 else if (extension_->is_theme())
241 resource_id = IDS_EXTENSION_INSTALL_THEME_PROMPT_TITLE;
243 resource_id = IDS_EXTENSION_INSTALL_EXTENSION_PROMPT_TITLE;
244 } else if (type_ == EXTERNAL_INSTALL_PROMPT) {
245 return l10n_util::GetStringFUTF16(
246 resource_id, base::UTF8ToUTF16(extension_->name()));
247 } else if (type_ == REMOTE_INSTALL_PROMPT) {
248 if (extension_->is_app())
249 resource_id = IDS_EXTENSION_REMOTE_INSTALL_APP_PROMPT_TITLE;
251 resource_id = IDS_EXTENSION_REMOTE_INSTALL_EXTENSION_PROMPT_TITLE;
254 return l10n_util::GetStringUTF16(resource_id);
257 base::string16 ExtensionInstallPrompt::Prompt::GetHeading() const {
258 if (type_ == INLINE_INSTALL_PROMPT) {
259 return base::UTF8ToUTF16(extension_->name());
260 } else if (type_ == BUNDLE_INSTALL_PROMPT) {
261 return bundle_->GetHeadingTextFor(BundleInstaller::Item::STATE_PENDING);
262 } else if (type_ == EXTERNAL_INSTALL_PROMPT) {
263 int resource_id = -1;
264 if (extension_->is_app())
265 resource_id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_HEADING_APP;
266 else if (extension_->is_theme())
267 resource_id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_HEADING_THEME;
269 resource_id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_HEADING_EXTENSION;
270 return l10n_util::GetStringUTF16(resource_id);
272 return l10n_util::GetStringFUTF16(
273 kHeadingIds[type_], base::UTF8ToUTF16(extension_->name()));
277 int ExtensionInstallPrompt::Prompt::GetDialogButtons() const {
278 if (type_ == POST_INSTALL_PERMISSIONS_PROMPT &&
279 ShouldDisplayRevokeFilesButton()) {
280 return kButtons[type_] | ui::DIALOG_BUTTON_OK;
283 return kButtons[type_];
286 bool ExtensionInstallPrompt::Prompt::ShouldShowExplanationText() const {
287 return type_ == INSTALL_PROMPT &&
288 extension_->is_extension() && experiment_ && experiment_->text_only();
291 bool ExtensionInstallPrompt::Prompt::HasAcceptButtonLabel() const {
292 if (kAcceptButtonIds[type_] == 0)
295 if (type_ == POST_INSTALL_PERMISSIONS_PROMPT)
296 return ShouldDisplayRevokeFilesButton();
301 base::string16 ExtensionInstallPrompt::Prompt::GetAcceptButtonLabel() const {
302 if (type_ == EXTERNAL_INSTALL_PROMPT) {
304 if (extension_->is_app())
305 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_APP;
306 else if (extension_->is_theme())
307 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_THEME;
309 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_EXTENSION;
310 return l10n_util::GetStringUTF16(id);
312 if (ShouldShowExplanationText())
313 return experiment_->GetOkButtonText();
314 return l10n_util::GetStringUTF16(kAcceptButtonIds[type_]);
317 bool ExtensionInstallPrompt::Prompt::HasAbortButtonLabel() const {
318 if (ShouldShowExplanationText())
320 return kAbortButtonIds[type_] > 0;
323 base::string16 ExtensionInstallPrompt::Prompt::GetAbortButtonLabel() const {
324 CHECK(HasAbortButtonLabel());
325 if (ShouldShowExplanationText())
326 return experiment_->GetCancelButtonText();
327 return l10n_util::GetStringUTF16(kAbortButtonIds[type_]);
330 base::string16 ExtensionInstallPrompt::Prompt::GetPermissionsHeading() const {
331 return l10n_util::GetStringUTF16(kPermissionsHeaderIds[type_]);
334 base::string16 ExtensionInstallPrompt::Prompt::GetRetainedFilesHeading() const {
335 const int kRetainedFilesMessageIDs[6] = {
336 IDS_EXTENSION_PROMPT_RETAINED_FILES_DEFAULT,
337 IDS_EXTENSION_PROMPT_RETAINED_FILE_SINGULAR,
338 IDS_EXTENSION_PROMPT_RETAINED_FILES_ZERO,
339 IDS_EXTENSION_PROMPT_RETAINED_FILES_TWO,
340 IDS_EXTENSION_PROMPT_RETAINED_FILES_FEW,
341 IDS_EXTENSION_PROMPT_RETAINED_FILES_MANY,
343 std::vector<int> message_ids;
344 for (size_t i = 0; i < arraysize(kRetainedFilesMessageIDs); i++) {
345 message_ids.push_back(kRetainedFilesMessageIDs[i]);
347 return l10n_util::GetPluralStringFUTF16(message_ids, GetRetainedFileCount());
350 bool ExtensionInstallPrompt::Prompt::ShouldShowPermissions() const {
351 return GetPermissionCount() > 0 || type_ == POST_INSTALL_PERMISSIONS_PROMPT;
354 void ExtensionInstallPrompt::Prompt::AppendRatingStars(
355 StarAppender appender, void* data) const {
357 CHECK(type_ == INLINE_INSTALL_PROMPT || type_ == EXTERNAL_INSTALL_PROMPT);
358 int rating_integer = floor(average_rating_);
359 double rating_fractional = average_rating_ - rating_integer;
361 if (rating_fractional > 0.66) {
365 if (rating_fractional < 0.33 || rating_fractional > 0.66) {
366 rating_fractional = 0;
369 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
371 for (i = 0; i < rating_integer; i++) {
372 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_ON), data);
374 if (rating_fractional) {
375 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_HALF_LEFT), data);
378 for (; i < kMaxExtensionRating; i++) {
379 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_OFF), data);
383 base::string16 ExtensionInstallPrompt::Prompt::GetRatingCount() const {
384 CHECK(type_ == INLINE_INSTALL_PROMPT || type_ == EXTERNAL_INSTALL_PROMPT);
385 return l10n_util::GetStringFUTF16(IDS_EXTENSION_RATING_COUNT,
386 base::IntToString16(rating_count_));
389 base::string16 ExtensionInstallPrompt::Prompt::GetUserCount() const {
390 CHECK(type_ == INLINE_INSTALL_PROMPT || type_ == EXTERNAL_INSTALL_PROMPT);
392 if (show_user_count_) {
393 return l10n_util::GetStringFUTF16(IDS_EXTENSION_USER_COUNT,
394 base::UTF8ToUTF16(localized_user_count_));
396 return base::string16();
399 size_t ExtensionInstallPrompt::Prompt::GetPermissionCount() const {
400 return permissions_.size();
403 size_t ExtensionInstallPrompt::Prompt::GetPermissionsDetailsCount() const {
404 return details_.size();
407 base::string16 ExtensionInstallPrompt::Prompt::GetPermission(size_t index)
409 CHECK_LT(index, permissions_.size());
410 return permissions_[index];
413 base::string16 ExtensionInstallPrompt::Prompt::GetPermissionsDetails(
414 size_t index) const {
415 CHECK_LT(index, details_.size());
416 return details_[index];
419 bool ExtensionInstallPrompt::Prompt::GetIsShowingDetails(
420 DetailsType type, size_t index) const {
422 case PERMISSIONS_DETAILS:
423 CHECK_LT(index, is_showing_details_for_permissions_.size());
424 return is_showing_details_for_permissions_[index];
425 case RETAINED_FILES_DETAILS:
426 return is_showing_details_for_retained_files_;
431 size_t ExtensionInstallPrompt::Prompt::GetRetainedFileCount() const {
432 return retained_files_.size();
435 base::string16 ExtensionInstallPrompt::Prompt::GetRetainedFile(size_t index)
437 CHECK_LT(index, retained_files_.size());
438 return retained_files_[index].AsUTF16Unsafe();
441 bool ExtensionInstallPrompt::Prompt::ShouldDisplayRevokeFilesButton() const {
442 return !retained_files_.empty();
445 ExtensionInstallPrompt::ShowParams::ShowParams(content::WebContents* contents)
446 : parent_web_contents(contents),
447 parent_window(NativeWindowForWebContents(contents)),
448 navigator(contents) {
451 ExtensionInstallPrompt::ShowParams::ShowParams(
452 gfx::NativeWindow window,
453 content::PageNavigator* navigator)
454 : parent_web_contents(NULL),
455 parent_window(window),
456 navigator(navigator) {
460 scoped_refptr<Extension>
461 ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
462 const base::DictionaryValue* manifest,
464 const std::string& id,
465 const std::string& localized_name,
466 const std::string& localized_description,
467 std::string* error) {
468 scoped_ptr<base::DictionaryValue> localized_manifest;
469 if (!localized_name.empty() || !localized_description.empty()) {
470 localized_manifest.reset(manifest->DeepCopy());
471 if (!localized_name.empty()) {
472 localized_manifest->SetString(extensions::manifest_keys::kName,
475 if (!localized_description.empty()) {
476 localized_manifest->SetString(extensions::manifest_keys::kDescription,
477 localized_description);
481 return Extension::Create(
484 localized_manifest.get() ? *localized_manifest.get() : *manifest,
490 ExtensionInstallPrompt::ExtensionInstallPrompt(content::WebContents* contents)
491 : ui_loop_(base::MessageLoop::current()),
494 install_ui_(ExtensionInstallUI::Create(ProfileForWebContents(contents))),
495 show_params_(contents),
499 ExtensionInstallPrompt::ExtensionInstallPrompt(
501 gfx::NativeWindow native_window,
502 content::PageNavigator* navigator)
503 : ui_loop_(base::MessageLoop::current()),
506 install_ui_(ExtensionInstallUI::Create(profile)),
507 show_params_(native_window, navigator),
511 ExtensionInstallPrompt::~ExtensionInstallPrompt() {
514 void ExtensionInstallPrompt::ConfirmBundleInstall(
515 extensions::BundleInstaller* bundle,
516 const PermissionSet* permissions) {
517 DCHECK(ui_loop_ == base::MessageLoop::current());
519 permissions_ = permissions;
521 prompt_ = new Prompt(BUNDLE_INSTALL_PROMPT);
526 void ExtensionInstallPrompt::ConfirmStandaloneInstall(
528 const Extension* extension,
530 scoped_refptr<Prompt> prompt) {
531 DCHECK(ui_loop_ == base::MessageLoop::current());
532 extension_ = extension;
533 permissions_ = extension->permissions_data()->active_permissions();
534 delegate_ = delegate;
541 void ExtensionInstallPrompt::ConfirmWebstoreInstall(
543 const Extension* extension,
544 const SkBitmap* icon,
545 const ShowDialogCallback& show_dialog_callback) {
546 // SetIcon requires |extension_| to be set. ConfirmInstall will setup the
548 extension_ = extension;
550 ConfirmInstall(delegate, extension, show_dialog_callback);
553 void ExtensionInstallPrompt::ConfirmInstall(
555 const Extension* extension,
556 const ShowDialogCallback& show_dialog_callback) {
557 DCHECK(ui_loop_ == base::MessageLoop::current());
558 extension_ = extension;
559 permissions_ = extension->permissions_data()->active_permissions();
560 delegate_ = delegate;
561 prompt_ = new Prompt(INSTALL_PROMPT);
562 show_dialog_callback_ = show_dialog_callback;
564 // We special-case themes to not show any confirm UI. Instead they are
565 // immediately installed, and then we show an infobar (see OnInstallSuccess)
566 // to allow the user to revert if they don't like it.
568 // We don't do this in the case where off-store extension installs are
569 // disabled because in that case, we don't show the dangerous download UI, so
570 // we need the UI confirmation.
571 if (extension->is_theme()) {
572 if (extension->from_webstore() ||
573 extensions::FeatureSwitch::easy_off_store_install()->IsEnabled()) {
574 delegate->InstallUIProceed();
582 void ExtensionInstallPrompt::ConfirmReEnable(Delegate* delegate,
583 const Extension* extension) {
584 DCHECK(ui_loop_ == base::MessageLoop::current());
585 extension_ = extension;
586 permissions_ = extension->permissions_data()->active_permissions();
587 delegate_ = delegate;
588 bool is_remote_install =
589 install_ui_->profile() &&
590 extensions::ExtensionPrefs::Get(install_ui_->profile())->HasDisableReason(
591 extension->id(), extensions::Extension::DISABLE_REMOTE_INSTALL);
593 extensions::util::IsEphemeralApp(extension->id(), install_ui_->profile());
595 PromptType type = UNSET_PROMPT_TYPE;
597 type = LAUNCH_PROMPT;
598 else if (is_remote_install)
599 type = REMOTE_INSTALL_PROMPT;
601 type = RE_ENABLE_PROMPT;
602 prompt_ = new Prompt(type);
607 void ExtensionInstallPrompt::ConfirmExternalInstall(
609 const Extension* extension,
610 const ShowDialogCallback& show_dialog_callback,
611 scoped_refptr<Prompt> prompt) {
612 DCHECK(ui_loop_ == base::MessageLoop::current());
613 extension_ = extension;
614 permissions_ = extension->permissions_data()->active_permissions();
615 delegate_ = delegate;
617 show_dialog_callback_ = show_dialog_callback;
622 void ExtensionInstallPrompt::ConfirmPermissions(
624 const Extension* extension,
625 const PermissionSet* permissions) {
626 DCHECK(ui_loop_ == base::MessageLoop::current());
627 extension_ = extension;
628 permissions_ = permissions;
629 delegate_ = delegate;
630 prompt_ = new Prompt(PERMISSIONS_PROMPT);
635 void ExtensionInstallPrompt::ReviewPermissions(
637 const Extension* extension,
638 const std::vector<base::FilePath>& retained_file_paths) {
639 DCHECK(ui_loop_ == base::MessageLoop::current());
640 extension_ = extension;
641 permissions_ = extension->permissions_data()->active_permissions();
642 prompt_ = new Prompt(POST_INSTALL_PERMISSIONS_PROMPT);
643 prompt_->set_retained_files(retained_file_paths);
644 delegate_ = delegate;
649 void ExtensionInstallPrompt::OnInstallSuccess(const Extension* extension,
651 extension_ = extension;
654 install_ui_->OnInstallSuccess(extension, &icon_);
657 void ExtensionInstallPrompt::OnInstallFailure(
658 const extensions::CrxInstallerError& error) {
659 install_ui_->OnInstallFailure(error);
662 void ExtensionInstallPrompt::SetIcon(const SkBitmap* image) {
668 // Let's set default icon bitmap whose size is equal to the default icon's
669 // pixel size under maximal supported scale factor. If the bitmap is larger
670 // than the one we need, it will be scaled down by the ui code.
671 icon_ = GetDefaultIconBitmapForMaxScaleFactor(extension_->is_app());
675 void ExtensionInstallPrompt::OnImageLoaded(const gfx::Image& image) {
676 SetIcon(image.IsEmpty() ? NULL : image.ToSkBitmap());
680 void ExtensionInstallPrompt::LoadImageIfNeeded() {
681 // Bundle install prompts do not have an icon.
682 // Also |install_ui_.profile()| can be NULL in unit tests.
683 if (!icon_.empty() || !install_ui_->profile()) {
688 extensions::ExtensionResource image = extensions::IconsInfo::GetIconResource(
690 extension_misc::EXTENSION_ICON_LARGE,
691 ExtensionIconSet::MATCH_BIGGER);
693 // Load the image asynchronously. The response will be sent to OnImageLoaded.
694 extensions::ImageLoader* loader =
695 extensions::ImageLoader::Get(install_ui_->profile());
697 std::vector<extensions::ImageLoader::ImageRepresentation> images_list;
698 images_list.push_back(extensions::ImageLoader::ImageRepresentation(
700 extensions::ImageLoader::ImageRepresentation::NEVER_RESIZE,
702 ui::SCALE_FACTOR_100P));
703 loader->LoadImagesAsync(
706 base::Bind(&ExtensionInstallPrompt::OnImageLoaded, AsWeakPtr()));
709 void ExtensionInstallPrompt::ShowConfirmation() {
710 if (prompt_->type() == INSTALL_PROMPT)
711 prompt_->set_experiment(ExtensionInstallPromptExperiment::Find());
713 prompt_->set_experiment(ExtensionInstallPromptExperiment::ControlGroup());
715 if (permissions_.get()) {
717 const extensions::PermissionsData* permissions_data =
718 extension_->permissions_data();
719 prompt_->SetPermissions(permissions_data->GetPermissionMessageStrings());
720 prompt_->SetPermissionsDetails(
721 permissions_data->GetPermissionMessageDetailsStrings());
723 const extensions::PermissionMessageProvider* message_provider =
724 extensions::PermissionMessageProvider::Get();
725 prompt_->SetPermissions(message_provider->GetWarningMessages(
726 permissions_, Manifest::TYPE_UNKNOWN));
727 prompt_->SetPermissionsDetails(
728 message_provider->GetWarningMessagesDetails(permissions_,
729 Manifest::TYPE_UNKNOWN));
733 switch (prompt_->type()) {
734 case PERMISSIONS_PROMPT:
735 case RE_ENABLE_PROMPT:
736 case INLINE_INSTALL_PROMPT:
737 case EXTERNAL_INSTALL_PROMPT:
740 case POST_INSTALL_PERMISSIONS_PROMPT:
741 case REMOTE_INSTALL_PROMPT: {
742 prompt_->set_extension(extension_);
743 prompt_->set_icon(gfx::Image::CreateFrom1xBitmap(icon_));
746 case BUNDLE_INSTALL_PROMPT: {
747 prompt_->set_bundle(bundle_);
751 NOTREACHED() << "Unknown message";
755 if (AutoConfirmPrompt(delegate_))
758 if (show_dialog_callback_.is_null())
759 GetDefaultShowDialogCallback().Run(show_params_, delegate_, prompt_);
761 show_dialog_callback_.Run(show_params_, delegate_, prompt_);