blob: 3712420e24a7336252aa58c3b549b37f664cf396 [file] [log] [blame]
[email protected]c82da8c42012-06-08 19:49:111// 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.
4
5#include "chrome/browser/extensions/extension_install_prompt.h"
6
dcheng1fc00f12015-12-26 22:18:037#include <utility>
8
rdevlin.cronin41593052016-01-08 01:40:129#include "base/callback_helpers.h"
skyostilf221b7de2015-06-11 20:36:3210#include "base/location.h"
dchengc963c7142016-04-08 03:55:2211#include "base/memory/ptr_util.h"
[email protected]3ea1b182013-02-08 22:38:4112#include "base/strings/string_number_conversions.h"
[email protected]00e7bef2013-06-10 20:35:1713#include "base/strings/string_util.h"
[email protected]112158af2013-06-07 23:46:1814#include "base/strings/utf_string_conversions.h"
skyostilf221b7de2015-06-11 20:36:3215#include "base/thread_task_runner_handle.h"
[email protected]c82da8c42012-06-08 19:49:1116#include "chrome/browser/extensions/bundle_installer.h"
pkotwicz2f181782014-10-29 17:33:4517#include "chrome/browser/extensions/extension_install_prompt_show_params.h"
[email protected]7eb20e32014-04-30 08:50:5618#include "chrome/browser/extensions/extension_util.h"
gpdavis.chromium0fbac4d2014-09-19 20:57:5419#include "chrome/browser/extensions/permissions_updater.h"
[email protected]c82da8c42012-06-08 19:49:1120#include "chrome/browser/profiles/profile.h"
pkotwicza57a1f322014-10-21 00:24:3021#include "chrome/browser/ui/extensions/extension_install_ui_factory.h"
[email protected]af39f002014-08-22 10:18:1822#include "chrome/grit/chromium_strings.h"
23#include "chrome/grit/generated_resources.h"
[email protected]91e51d612012-10-21 23:03:0524#include "content/public/browser/web_contents.h"
rdevlin.cronin66209492015-06-10 20:44:0525#include "extensions/browser/extension_dialog_auto_confirm.h"
[email protected]21db9ef2014-05-16 02:06:2726#include "extensions/browser/extension_prefs.h"
[email protected]411f8ae2014-05-22 11:12:2327#include "extensions/browser/extension_util.h"
[email protected]326e6f02014-06-20 04:53:3728#include "extensions/browser/image_loader.h"
pkotwicza57a1f322014-10-21 00:24:3029#include "extensions/browser/install/extension_install_ui.h"
[email protected]cda103d2014-04-04 16:22:3930#include "extensions/common/constants.h"
[email protected]e4452d32013-11-15 23:07:4131#include "extensions/common/extension.h"
[email protected]4b7908842014-04-07 23:50:2232#include "extensions/common/extension_icon_set.h"
[email protected]993da5e2013-03-23 21:25:1633#include "extensions/common/extension_resource.h"
[email protected]5ef835a2013-11-08 20:42:5734#include "extensions/common/feature_switch.h"
[email protected]d42c11152013-08-22 19:36:3235#include "extensions/common/manifest.h"
[email protected]6bf90612013-08-15 00:36:2736#include "extensions/common/manifest_constants.h"
[email protected]0db486f2014-04-09 19:32:2237#include "extensions/common/manifest_handlers/icons_handler.h"
treib7496f63c2015-03-04 12:18:5338#include "extensions/common/manifest_handlers/permissions_parser.h"
treibf9dce312015-08-27 17:33:3539#include "extensions/common/permissions/permission_message_provider.h"
[email protected]5a55f3f2013-10-29 01:08:2940#include "extensions/common/permissions/permission_set.h"
[email protected]e4452d32013-11-15 23:07:4141#include "extensions/common/permissions/permissions_data.h"
drogerfaa2e032016-01-07 17:33:5342#include "grit/components_strings.h"
[email protected]2a281332012-07-11 22:20:2343#include "grit/theme_resources.h"
[email protected]c82da8c42012-06-08 19:49:1144#include "ui/base/l10n/l10n_util.h"
45#include "ui/base/resource/resource_bundle.h"
pkotwicz7fd01192014-10-09 04:43:5046#include "ui/base/ui_base_types.h"
rdevlin.cronin3fe4bd32016-01-12 18:45:4047#include "ui/gfx/image/image_skia.h"
[email protected]c82da8c42012-06-08 19:49:1148
[email protected]c82da8c42012-06-08 19:49:1149using extensions::BundleInstaller;
50using extensions::Extension;
[email protected]1d5e58b2013-01-31 08:41:4051using extensions::Manifest;
treibf9dce312015-08-27 17:33:3552using extensions::PermissionMessage;
53using extensions::PermissionMessages;
[email protected]c2e66e12012-06-27 06:27:0654using extensions::PermissionSet;
[email protected]c82da8c42012-06-08 19:49:1155
[email protected]612a1cb12012-10-17 13:18:0356namespace {
57
rdevlin.cronin5f6b69d2014-09-20 01:23:3558bool AllowWebstoreData(ExtensionInstallPrompt::PromptType type) {
59 return type == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT ||
60 type == ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT ||
61 type == ExtensionInstallPrompt::REPAIR_PROMPT;
62}
63
[email protected]c82da8c42012-06-08 19:49:1164static const int kTitleIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2765 IDS_EXTENSION_INSTALL_PROMPT_TITLE,
treibd35862252015-06-15 12:50:5166 IDS_EXTENSION_INSTALL_PROMPT_TITLE,
67 0, // Heading for bundle installs depends on the bundle contents.
[email protected]21db9ef2014-05-16 02:06:2768 IDS_EXTENSION_RE_ENABLE_PROMPT_TITLE,
69 IDS_EXTENSION_PERMISSIONS_PROMPT_TITLE,
treibd35862252015-06-15 12:50:5170 0, // External installs use different strings for extensions/apps/themes.
[email protected]21db9ef2014-05-16 02:06:2771 IDS_EXTENSION_POST_INSTALL_PERMISSIONS_PROMPT_TITLE,
72 IDS_EXTENSION_LAUNCH_APP_PROMPT_TITLE,
treibd35862252015-06-15 12:50:5173 IDS_EXTENSION_REMOTE_INSTALL_PROMPT_TITLE,
74 IDS_EXTENSION_REPAIR_PROMPT_TITLE,
75 IDS_EXTENSION_DELEGATED_INSTALL_PROMPT_TITLE,
treibe36431582015-06-24 15:59:0576 0, // Heading for delegated bundle installs depends on the bundle contents.
[email protected]15d267b42013-02-14 23:43:3277};
78static const int kButtons[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2779 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_OK | ui::DIALOG_BUTTON_CANCEL,
84 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
treibd35862252015-06-15 12:50:5185 // The "OK" button in the post install permissions dialog allows revoking
86 // file/device access, and is only shown if such permissions exist; see
87 // ShouldDisplayRevokeButton().
[email protected]21db9ef2014-05-16 02:06:2788 ui::DIALOG_BUTTON_CANCEL,
89 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
90 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
rdevlin.cronin5f6b69d2014-09-20 01:23:3591 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
treib2d2f5372015-03-01 12:20:4992 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
treibe36431582015-06-24 15:59:0593 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
[email protected]c82da8c42012-06-08 19:49:1194};
95static const int kAcceptButtonIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
treibd35862252015-06-15 12:50:5196 0, // Regular installs use different strings for extensions/apps/themes.
97 0, // Inline installs as well.
[email protected]21db9ef2014-05-16 02:06:2798 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
99 IDS_EXTENSION_PROMPT_RE_ENABLE_BUTTON,
100 IDS_EXTENSION_PROMPT_PERMISSIONS_BUTTON,
treibd35862252015-06-15 12:50:51101 0, // External installs use different strings for extensions/apps/themes.
reillygc64d3dd2014-09-29 21:10:11102 0, // Different strings depending on the files and devices retained.
[email protected]21db9ef2014-05-16 02:06:27103 IDS_EXTENSION_PROMPT_LAUNCH_BUTTON,
treibd35862252015-06-15 12:50:51104 0, // Remote installs use different strings for extensions/apps.
105 0, // Repairs use different strings for extensions/apps.
106 0, // Delegated installs use different strings for extensions/apps/themes.
treibe36431582015-06-24 15:59:05107 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
[email protected]c82da8c42012-06-08 19:49:11108};
109static const int kAbortButtonIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
treibd35862252015-06-15 12:50:51110 IDS_CANCEL,
111 IDS_CANCEL,
112 IDS_CANCEL,
113 IDS_CANCEL,
[email protected]21db9ef2014-05-16 02:06:27114 IDS_EXTENSION_PROMPT_PERMISSIONS_ABORT_BUTTON,
115 IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ABORT_BUTTON,
116 IDS_CLOSE,
treibd35862252015-06-15 12:50:51117 IDS_CANCEL,
118 IDS_CANCEL,
119 IDS_CANCEL,
120 IDS_CANCEL,
treibe36431582015-06-24 15:59:05121 IDS_CANCEL,
[email protected]c82da8c42012-06-08 19:49:11122};
[email protected]21db9ef2014-05-16 02:06:27123static const int
124 kPermissionsHeaderIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
125 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
126 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
127 IDS_EXTENSION_PROMPT_THESE_WILL_HAVE_ACCESS_TO,
128 IDS_EXTENSION_PROMPT_WILL_NOW_HAVE_ACCESS_TO,
129 IDS_EXTENSION_PROMPT_WANTS_ACCESS_TO,
130 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
131 IDS_EXTENSION_PROMPT_CAN_ACCESS,
132 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
133 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
rdevlin.cronin5f6b69d2014-09-20 01:23:35134 IDS_EXTENSION_PROMPT_CAN_ACCESS,
treib2d2f5372015-03-01 12:20:49135 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
treibe36431582015-06-24 15:59:05136 IDS_EXTENSION_PROMPT_THESE_WILL_HAVE_ACCESS_TO,
[email protected]c82da8c42012-06-08 19:49:11137};
138
[email protected]dd46a4ce2012-09-15 10:50:50139// Returns bitmap for the default icon with size equal to the default icon's
140// pixel size under maximal supported scale factor.
141SkBitmap GetDefaultIconBitmapForMaxScaleFactor(bool is_app) {
[email protected]702d8b42013-02-27 20:55:50142 const gfx::ImageSkia& image = is_app ?
[email protected]7eb20e32014-04-30 08:50:56143 extensions::util::GetDefaultAppIcon() :
144 extensions::util::GetDefaultExtensionIcon();
[email protected]50b66262013-09-24 03:25:48145 return image.GetRepresentation(
146 gfx::ImageSkia::GetMaxSupportedScale()).sk_bitmap();
[email protected]dd46a4ce2012-09-15 10:50:50147}
148
[email protected]af6efb22012-10-12 02:23:05149// If auto confirm is enabled then posts a task to proceed with or cancel the
150// install and returns true. Otherwise returns false.
rdevlin.cronin41593052016-01-08 01:40:12151bool AutoConfirmPrompt(ExtensionInstallPrompt::DoneCallback* callback) {
rdevlin.cronin66209492015-06-10 20:44:05152 switch (extensions::ScopedTestDialogAutoConfirm::GetAutoConfirmValue()) {
153 case extensions::ScopedTestDialogAutoConfirm::NONE:
[email protected]2a74d6f62014-07-24 11:53:47154 return false;
rdevlin.cronin41593052016-01-08 01:40:12155 // We use PostTask instead of calling the callback directly here, because in
[email protected]2a74d6f62014-07-24 11:53:47156 // the real implementations it's highly likely the message loop will be
157 // pumping a few times before the user clicks accept or cancel.
rdevlin.cronin66209492015-06-10 20:44:05158 case extensions::ScopedTestDialogAutoConfirm::ACCEPT:
[email protected]2a74d6f62014-07-24 11:53:47159 base::MessageLoop::current()->PostTask(
rdevlin.cronin41593052016-01-08 01:40:12160 FROM_HERE, base::Bind(base::ResetAndReturn(callback),
161 ExtensionInstallPrompt::Result::ACCEPTED));
[email protected]2a74d6f62014-07-24 11:53:47162 return true;
rdevlin.cronin66209492015-06-10 20:44:05163 case extensions::ScopedTestDialogAutoConfirm::CANCEL:
skyostilf221b7de2015-06-11 20:36:32164 base::ThreadTaskRunnerHandle::Get()->PostTask(
rdevlin.cronin41593052016-01-08 01:40:12165 FROM_HERE, base::Bind(base::ResetAndReturn(callback),
166 ExtensionInstallPrompt::Result::USER_CANCELED));
[email protected]2a74d6f62014-07-24 11:53:47167 return true;
[email protected]af6efb22012-10-12 02:23:05168 }
169
170 NOTREACHED();
171 return false;
172}
173
[email protected]91e51d612012-10-21 23:03:05174Profile* ProfileForWebContents(content::WebContents* web_contents) {
175 if (!web_contents)
176 return NULL;
177 return Profile::FromBrowserContext(web_contents->GetBrowserContext());
178}
179
[email protected]c82da8c42012-06-08 19:49:11180} // namespace
181
gpdavis.chromium0fbac4d2014-09-19 20:57:54182ExtensionInstallPrompt::Prompt::InstallPromptPermissions::
183 InstallPromptPermissions() {
184}
185ExtensionInstallPrompt::Prompt::InstallPromptPermissions::
186 ~InstallPromptPermissions() {
187}
188
rdevlin.cronin092c6772014-11-20 23:52:40189ExtensionInstallPrompt::PromptType
190ExtensionInstallPrompt::g_last_prompt_type_for_tests =
191 ExtensionInstallPrompt::UNSET_PROMPT_TYPE;
192
[email protected]eeb0d3e12014-08-15 15:10:44193// This should match the PromptType enum.
194std::string ExtensionInstallPrompt::PromptTypeToString(PromptType type) {
195 switch (type) {
196 case ExtensionInstallPrompt::INSTALL_PROMPT:
197 return "INSTALL_PROMPT";
198 case ExtensionInstallPrompt::INLINE_INSTALL_PROMPT:
199 return "INLINE_INSTALL_PROMPT";
200 case ExtensionInstallPrompt::BUNDLE_INSTALL_PROMPT:
201 return "BUNDLE_INSTALL_PROMPT";
202 case ExtensionInstallPrompt::RE_ENABLE_PROMPT:
203 return "RE_ENABLE_PROMPT";
204 case ExtensionInstallPrompt::PERMISSIONS_PROMPT:
205 return "PERMISSIONS_PROMPT";
206 case ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT:
207 return "EXTERNAL_INSTALL_PROMPT";
208 case ExtensionInstallPrompt::POST_INSTALL_PERMISSIONS_PROMPT:
209 return "POST_INSTALL_PERMISSIONS_PROMPT";
[email protected]eeb0d3e12014-08-15 15:10:44210 case ExtensionInstallPrompt::REMOTE_INSTALL_PROMPT:
211 return "REMOTE_INSTALL_PROMPT";
rdevlin.cronin5f6b69d2014-09-20 01:23:35212 case ExtensionInstallPrompt::REPAIR_PROMPT:
213 return "REPAIR_PROMPT";
treib2d2f5372015-03-01 12:20:49214 case ExtensionInstallPrompt::DELEGATED_PERMISSIONS_PROMPT:
215 return "DELEGATED_PERMISSIONS_PROMPT";
treibe36431582015-06-24 15:59:05216 case ExtensionInstallPrompt::DELEGATED_BUNDLE_PERMISSIONS_PROMPT:
217 return "DELEGATED_BUNDLE_PERMISSIONS_PROMPT";
benwells1dd4acd2015-12-09 02:20:24218 case ExtensionInstallPrompt::LAUNCH_PROMPT_DEPRECATED:
219 NOTREACHED();
220 // fall through:
[email protected]eeb0d3e12014-08-15 15:10:44221 case ExtensionInstallPrompt::UNSET_PROMPT_TYPE:
222 case ExtensionInstallPrompt::NUM_PROMPT_TYPES:
223 break;
224 }
225 return "OTHER";
226}
227
[email protected]5db2e882012-12-20 10:17:26228ExtensionInstallPrompt::Prompt::Prompt(PromptType type)
[email protected]c82da8c42012-06-08 19:49:11229 : type_(type),
[email protected]79a6f99a2013-08-29 00:32:58230 is_showing_details_for_retained_files_(false),
reillygc64d3dd2014-09-29 21:10:11231 is_showing_details_for_retained_devices_(false),
[email protected]c82da8c42012-06-08 19:49:11232 extension_(NULL),
233 bundle_(NULL),
234 average_rating_(0.0),
[email protected]dcde34b32013-07-31 02:28:45235 rating_count_(0),
[email protected]34b5f7f2014-01-29 02:48:11236 show_user_count_(false),
237 has_webstore_data_(false) {
[email protected]c82da8c42012-06-08 19:49:11238}
239
240ExtensionInstallPrompt::Prompt::~Prompt() {
241}
242
243void ExtensionInstallPrompt::Prompt::SetPermissions(
treibf9dce312015-08-27 17:33:35244 const PermissionMessages& permissions,
gpdavis.chromium0fbac4d2014-09-19 20:57:54245 PermissionsType permissions_type) {
246 InstallPromptPermissions& install_permissions =
247 GetPermissionsForType(permissions_type);
sashabeabd5df2014-11-06 02:38:25248
treib7b45a34b2015-04-16 11:48:02249 install_permissions.permissions.clear();
250 install_permissions.details.clear();
251 install_permissions.is_showing_details.clear();
sashabeabd5df2014-11-06 02:38:25252
treibf9dce312015-08-27 17:33:35253 for (const PermissionMessage& msg : permissions) {
treib8d2de482015-08-04 16:36:48254 install_permissions.permissions.push_back(msg.message());
treib7b45a34b2015-04-16 11:48:02255 // Add a dash to the front of each permission detail.
256 base::string16 details;
treib8d2de482015-08-04 16:36:48257 if (!msg.submessages().empty()) {
sashabeabd5df2014-11-06 02:38:25258 std::vector<base::string16> detail_lines_with_bullets;
treib8d2de482015-08-04 16:36:48259 for (const auto& detail_line : msg.submessages()) {
sashabeabd5df2014-11-06 02:38:25260 detail_lines_with_bullets.push_back(base::ASCIIToUTF16("- ") +
261 detail_line);
treib7b45a34b2015-04-16 11:48:02262 }
sashabeabd5df2014-11-06 02:38:25263
brettwd94a22142015-07-15 05:19:26264 details = base::JoinString(detail_lines_with_bullets,
265 base::ASCIIToUTF16("\n"));
sashabeabd5df2014-11-06 02:38:25266 }
treib7b45a34b2015-04-16 11:48:02267 install_permissions.details.push_back(details);
268 install_permissions.is_showing_details.push_back(false);
sashabeabd5df2014-11-06 02:38:25269 }
[email protected]79a6f99a2013-08-29 00:32:58270}
271
272void ExtensionInstallPrompt::Prompt::SetIsShowingDetails(
273 DetailsType type,
274 size_t index,
275 bool is_showing_details) {
276 switch (type) {
277 case PERMISSIONS_DETAILS:
gpdavis.chromium0fbac4d2014-09-19 20:57:54278 prompt_permissions_.is_showing_details[index] = is_showing_details;
279 break;
280 case WITHHELD_PERMISSIONS_DETAILS:
281 withheld_prompt_permissions_.is_showing_details[index] =
282 is_showing_details;
[email protected]79a6f99a2013-08-29 00:32:58283 break;
[email protected]79a6f99a2013-08-29 00:32:58284 case RETAINED_FILES_DETAILS:
285 is_showing_details_for_retained_files_ = is_showing_details;
286 break;
reillygc64d3dd2014-09-29 21:10:11287 case RETAINED_DEVICES_DETAILS:
288 is_showing_details_for_retained_devices_ = is_showing_details;
289 break;
[email protected]79a6f99a2013-08-29 00:32:58290 }
[email protected]8ab7e6c2013-07-11 21:15:03291}
292
[email protected]34b5f7f2014-01-29 02:48:11293void ExtensionInstallPrompt::Prompt::SetWebstoreData(
[email protected]c82da8c42012-06-08 19:49:11294 const std::string& localized_user_count,
[email protected]dcde34b32013-07-31 02:28:45295 bool show_user_count,
[email protected]c82da8c42012-06-08 19:49:11296 double average_rating,
297 int rating_count) {
rdevlin.cronin5f6b69d2014-09-20 01:23:35298 CHECK(AllowWebstoreData(type_));
[email protected]c82da8c42012-06-08 19:49:11299 localized_user_count_ = localized_user_count;
[email protected]dcde34b32013-07-31 02:28:45300 show_user_count_ = show_user_count;
[email protected]c82da8c42012-06-08 19:49:11301 average_rating_ = average_rating;
302 rating_count_ = rating_count;
[email protected]34b5f7f2014-01-29 02:48:11303 has_webstore_data_ = true;
[email protected]c82da8c42012-06-08 19:49:11304}
305
[email protected]6a72a632013-12-12 22:22:00306base::string16 ExtensionInstallPrompt::Prompt::GetDialogTitle() const {
treibd35862252015-06-15 12:50:51307 int id = kTitleIds[type_];
treibe36431582015-06-24 15:59:05308 if (type_ == BUNDLE_INSTALL_PROMPT ||
309 type_ == DELEGATED_BUNDLE_PERMISSIONS_PROMPT) {
[email protected]c82da8c42012-06-08 19:49:11310 return bundle_->GetHeadingTextFor(BundleInstaller::Item::STATE_PENDING);
[email protected]c82da8c42012-06-08 19:49:11311 }
treibd35862252015-06-15 12:50:51312 if (type_ == DELEGATED_PERMISSIONS_PROMPT) {
313 return l10n_util::GetStringFUTF16(id, base::UTF8ToUTF16(extension_->name()),
314 base::UTF8ToUTF16(delegated_username_));
315 }
316 if (type_ == EXTERNAL_INSTALL_PROMPT) {
317 if (extension_->is_app())
318 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_TITLE_APP;
319 else if (extension_->is_theme())
320 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_TITLE_THEME;
321 else
322 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_TITLE_EXTENSION;
323 }
324 return l10n_util::GetStringFUTF16(id, base::UTF8ToUTF16(extension_->name()));
[email protected]c82da8c42012-06-08 19:49:11325}
326
[email protected]15d267b42013-02-14 23:43:32327int ExtensionInstallPrompt::Prompt::GetDialogButtons() const {
reillygc64d3dd2014-09-29 21:10:11328 if (type_ == POST_INSTALL_PERMISSIONS_PROMPT && ShouldDisplayRevokeButton()) {
[email protected]a2886e8b2013-06-08 05:15:02329 return kButtons[type_] | ui::DIALOG_BUTTON_OK;
330 }
331
[email protected]15d267b42013-02-14 23:43:32332 return kButtons[type_];
333}
334
[email protected]6a72a632013-12-12 22:22:00335base::string16 ExtensionInstallPrompt::Prompt::GetAcceptButtonLabel() const {
treibd35862252015-06-15 12:50:51336 int id = kAcceptButtonIds[type_];
337
338 if (type_ == INSTALL_PROMPT || type_ == INLINE_INSTALL_PROMPT ||
339 type_ == DELEGATED_PERMISSIONS_PROMPT) {
340 if (extension_->is_app())
341 id = IDS_EXTENSION_INSTALL_PROMPT_ACCEPT_BUTTON_APP;
342 else if (extension_->is_theme())
343 id = IDS_EXTENSION_INSTALL_PROMPT_ACCEPT_BUTTON_THEME;
344 else
345 id = IDS_EXTENSION_INSTALL_PROMPT_ACCEPT_BUTTON_EXTENSION;
346 } else if (type_ == EXTERNAL_INSTALL_PROMPT) {
[email protected]846606012012-10-19 18:42:25347 if (extension_->is_app())
348 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_APP;
349 else if (extension_->is_theme())
350 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_THEME;
351 else
352 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_EXTENSION;
reillygc64d3dd2014-09-29 21:10:11353 } else if (type_ == POST_INSTALL_PERMISSIONS_PROMPT) {
reillygc64d3dd2014-09-29 21:10:11354 if (GetRetainedFileCount() && GetRetainedDeviceCount()) {
355 id =
356 IDS_EXTENSION_PROMPT_PERMISSIONS_CLEAR_RETAINED_FILES_AND_DEVICES_BUTTON;
357 } else if (GetRetainedFileCount()) {
358 id = IDS_EXTENSION_PROMPT_PERMISSIONS_CLEAR_RETAINED_FILES_BUTTON;
treibd35862252015-06-15 12:50:51359 } else if (GetRetainedDeviceCount()) {
reillygc64d3dd2014-09-29 21:10:11360 id = IDS_EXTENSION_PROMPT_PERMISSIONS_CLEAR_RETAINED_DEVICES_BUTTON;
361 }
treibd35862252015-06-15 12:50:51362 // If there are neither retained files nor devices, leave id 0 so there
363 // will be no "accept" button.
364 } else if (type_ == REMOTE_INSTALL_PROMPT) {
365 if (extension_->is_app())
366 id = IDS_EXTENSION_PROMPT_REMOTE_INSTALL_BUTTON_APP;
367 else
368 id = IDS_EXTENSION_PROMPT_REMOTE_INSTALL_BUTTON_EXTENSION;
369 } else if (type_ == REPAIR_PROMPT) {
370 if (extension_->is_app())
371 id = IDS_EXTENSION_PROMPT_REPAIR_BUTTON_APP;
372 else
373 id = IDS_EXTENSION_PROMPT_REPAIR_BUTTON_EXTENSION;
[email protected]846606012012-10-19 18:42:25374 }
treibd35862252015-06-15 12:50:51375 return id ? l10n_util::GetStringUTF16(id) : base::string16();
[email protected]c82da8c42012-06-08 19:49:11376}
377
[email protected]6a72a632013-12-12 22:22:00378base::string16 ExtensionInstallPrompt::Prompt::GetAbortButtonLabel() const {
[email protected]c82da8c42012-06-08 19:49:11379 return l10n_util::GetStringUTF16(kAbortButtonIds[type_]);
380}
381
gpdavis.chromium0fbac4d2014-09-19 20:57:54382base::string16 ExtensionInstallPrompt::Prompt::GetPermissionsHeading(
383 PermissionsType permissions_type) const {
384 switch (permissions_type) {
385 case REGULAR_PERMISSIONS:
386 return l10n_util::GetStringUTF16(kPermissionsHeaderIds[type_]);
387 case WITHHELD_PERMISSIONS:
388 return l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WITHHELD);
389 case ALL_PERMISSIONS:
390 default:
391 NOTREACHED();
392 return base::string16();
393 }
[email protected]c82da8c42012-06-08 19:49:11394}
395
[email protected]6a72a632013-12-12 22:22:00396base::string16 ExtensionInstallPrompt::Prompt::GetRetainedFilesHeading() const {
jshin3a6c36bb2015-04-09 21:58:08397 return l10n_util::GetPluralStringFUTF16(
398 IDS_EXTENSION_PROMPT_RETAINED_FILES, GetRetainedFileCount());
[email protected]8ab7e6c2013-07-11 21:15:03399}
400
reillygc64d3dd2014-09-29 21:10:11401base::string16 ExtensionInstallPrompt::Prompt::GetRetainedDevicesHeading()
402 const {
jshin3a6c36bb2015-04-09 21:58:08403 return l10n_util::GetPluralStringFUTF16(
404 IDS_EXTENSION_PROMPT_RETAINED_DEVICES, GetRetainedDeviceCount());
reillygc64d3dd2014-09-29 21:10:11405}
406
[email protected]f2cd8992013-06-11 17:30:18407bool ExtensionInstallPrompt::Prompt::ShouldShowPermissions() const {
gpdavis.chromium0fbac4d2014-09-19 20:57:54408 return GetPermissionCount(ALL_PERMISSIONS) > 0 ||
409 type_ == POST_INSTALL_PERMISSIONS_PROMPT;
[email protected]f2cd8992013-06-11 17:30:18410}
411
asargent0a1c15f2015-12-09 02:25:21412bool ExtensionInstallPrompt::Prompt::ShouldUseTabModalDialog() const {
413 // For inline install, we want the install prompt to be tab modal so that the
414 // dialog is always clearly associated with the page that made the inline
415 // install request.
416 return type_ == INLINE_INSTALL_PROMPT;
417}
418
[email protected]c82da8c42012-06-08 19:49:11419void ExtensionInstallPrompt::Prompt::AppendRatingStars(
420 StarAppender appender, void* data) const {
421 CHECK(appender);
rdevlin.cronin5f6b69d2014-09-20 01:23:35422 CHECK(AllowWebstoreData(type_));
[email protected]c82da8c42012-06-08 19:49:11423 int rating_integer = floor(average_rating_);
424 double rating_fractional = average_rating_ - rating_integer;
425
426 if (rating_fractional > 0.66) {
427 rating_integer++;
428 }
429
430 if (rating_fractional < 0.33 || rating_fractional > 0.66) {
431 rating_fractional = 0;
432 }
433
434 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
435 int i;
436 for (i = 0; i < rating_integer; i++) {
437 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_ON), data);
438 }
439 if (rating_fractional) {
440 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_HALF_LEFT), data);
441 i++;
442 }
443 for (; i < kMaxExtensionRating; i++) {
444 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_OFF), data);
445 }
446}
447
[email protected]6a72a632013-12-12 22:22:00448base::string16 ExtensionInstallPrompt::Prompt::GetRatingCount() const {
rdevlin.cronin5f6b69d2014-09-20 01:23:35449 CHECK(AllowWebstoreData(type_));
[email protected]6725048e2013-10-24 21:47:14450 return l10n_util::GetStringFUTF16(IDS_EXTENSION_RATING_COUNT,
451 base::IntToString16(rating_count_));
[email protected]c82da8c42012-06-08 19:49:11452}
453
[email protected]6a72a632013-12-12 22:22:00454base::string16 ExtensionInstallPrompt::Prompt::GetUserCount() const {
rdevlin.cronin5f6b69d2014-09-20 01:23:35455 CHECK(AllowWebstoreData(type_));
[email protected]dcde34b32013-07-31 02:28:45456
457 if (show_user_count_) {
[email protected]6725048e2013-10-24 21:47:14458 return l10n_util::GetStringFUTF16(IDS_EXTENSION_USER_COUNT,
459 base::UTF8ToUTF16(localized_user_count_));
[email protected]dcde34b32013-07-31 02:28:45460 }
[email protected]6725048e2013-10-24 21:47:14461 return base::string16();
[email protected]c82da8c42012-06-08 19:49:11462}
463
gpdavis.chromium0fbac4d2014-09-19 20:57:54464size_t ExtensionInstallPrompt::Prompt::GetPermissionCount(
465 PermissionsType permissions_type) const {
466 switch (permissions_type) {
467 case REGULAR_PERMISSIONS:
468 return prompt_permissions_.permissions.size();
469 case WITHHELD_PERMISSIONS:
470 return withheld_prompt_permissions_.permissions.size();
471 case ALL_PERMISSIONS:
472 return prompt_permissions_.permissions.size() +
473 withheld_prompt_permissions_.permissions.size();
474 default:
475 NOTREACHED();
476 return 0u;
477 }
[email protected]c82da8c42012-06-08 19:49:11478}
479
gpdavis.chromium0fbac4d2014-09-19 20:57:54480size_t ExtensionInstallPrompt::Prompt::GetPermissionsDetailsCount(
481 PermissionsType permissions_type) const {
482 switch (permissions_type) {
483 case REGULAR_PERMISSIONS:
484 return prompt_permissions_.details.size();
485 case WITHHELD_PERMISSIONS:
486 return withheld_prompt_permissions_.details.size();
487 case ALL_PERMISSIONS:
488 return prompt_permissions_.details.size() +
489 withheld_prompt_permissions_.details.size();
490 default:
491 NOTREACHED();
492 return 0u;
493 }
[email protected]8ab7e6c2013-07-11 21:15:03494}
495
gpdavis.chromium0fbac4d2014-09-19 20:57:54496base::string16 ExtensionInstallPrompt::Prompt::GetPermission(
497 size_t index,
498 PermissionsType permissions_type) const {
499 const InstallPromptPermissions& install_permissions =
500 GetPermissionsForType(permissions_type);
501 CHECK_LT(index, install_permissions.permissions.size());
502 return install_permissions.permissions[index];
[email protected]c82da8c42012-06-08 19:49:11503}
504
[email protected]6a72a632013-12-12 22:22:00505base::string16 ExtensionInstallPrompt::Prompt::GetPermissionsDetails(
gpdavis.chromium0fbac4d2014-09-19 20:57:54506 size_t index,
507 PermissionsType permissions_type) const {
508 const InstallPromptPermissions& install_permissions =
509 GetPermissionsForType(permissions_type);
510 CHECK_LT(index, install_permissions.details.size());
511 return install_permissions.details[index];
[email protected]8ab7e6c2013-07-11 21:15:03512}
513
[email protected]79a6f99a2013-08-29 00:32:58514bool ExtensionInstallPrompt::Prompt::GetIsShowingDetails(
515 DetailsType type, size_t index) const {
516 switch (type) {
517 case PERMISSIONS_DETAILS:
gpdavis.chromium0fbac4d2014-09-19 20:57:54518 CHECK_LT(index, prompt_permissions_.is_showing_details.size());
519 return prompt_permissions_.is_showing_details[index];
520 case WITHHELD_PERMISSIONS_DETAILS:
521 CHECK_LT(index, withheld_prompt_permissions_.is_showing_details.size());
522 return withheld_prompt_permissions_.is_showing_details[index];
[email protected]79a6f99a2013-08-29 00:32:58523 case RETAINED_FILES_DETAILS:
524 return is_showing_details_for_retained_files_;
reillygc64d3dd2014-09-29 21:10:11525 case RETAINED_DEVICES_DETAILS:
526 return is_showing_details_for_retained_devices_;
[email protected]79a6f99a2013-08-29 00:32:58527 }
528 return false;
529}
530
[email protected]a2886e8b2013-06-08 05:15:02531size_t ExtensionInstallPrompt::Prompt::GetRetainedFileCount() const {
532 return retained_files_.size();
533}
534
[email protected]6a72a632013-12-12 22:22:00535base::string16 ExtensionInstallPrompt::Prompt::GetRetainedFile(size_t index)
536 const {
[email protected]a2886e8b2013-06-08 05:15:02537 CHECK_LT(index, retained_files_.size());
[email protected]6725048e2013-10-24 21:47:14538 return retained_files_[index].AsUTF16Unsafe();
[email protected]a2886e8b2013-06-08 05:15:02539}
540
reillygc64d3dd2014-09-29 21:10:11541size_t ExtensionInstallPrompt::Prompt::GetRetainedDeviceCount() const {
542 return retained_device_messages_.size();
543}
544
545base::string16 ExtensionInstallPrompt::Prompt::GetRetainedDeviceMessageString(
546 size_t index) const {
547 CHECK_LT(index, retained_device_messages_.size());
548 return retained_device_messages_[index];
549}
550
551bool ExtensionInstallPrompt::Prompt::ShouldDisplayRevokeButton() const {
552 return !retained_files_.empty() || !retained_device_messages_.empty();
553}
554
gpdavis.chromium0fbac4d2014-09-19 20:57:54555ExtensionInstallPrompt::Prompt::InstallPromptPermissions&
556ExtensionInstallPrompt::Prompt::GetPermissionsForType(
557 PermissionsType permissions_type) {
558 DCHECK_NE(ALL_PERMISSIONS, permissions_type);
559 return permissions_type == REGULAR_PERMISSIONS ? prompt_permissions_
560 : withheld_prompt_permissions_;
561}
562
563const ExtensionInstallPrompt::Prompt::InstallPromptPermissions&
564ExtensionInstallPrompt::Prompt::GetPermissionsForType(
565 PermissionsType permissions_type) const {
566 DCHECK_NE(ALL_PERMISSIONS, permissions_type);
567 return permissions_type == REGULAR_PERMISSIONS ? prompt_permissions_
568 : withheld_prompt_permissions_;
569}
570
[email protected]a2886e8b2013-06-08 05:15:02571bool ExtensionInstallPrompt::Prompt::ShouldDisplayRevokeFilesButton() const {
572 return !retained_files_.empty();
573}
574
[email protected]c82da8c42012-06-08 19:49:11575// static
rdevlin.croninf84cab72015-12-12 03:45:23576ExtensionInstallPrompt::PromptType
577ExtensionInstallPrompt::GetReEnablePromptTypeForExtension(
578 content::BrowserContext* context,
579 const extensions::Extension* extension) {
580 bool is_remote_install =
581 context &&
582 extensions::ExtensionPrefs::Get(context)->HasDisableReason(
583 extension->id(), extensions::Extension::DISABLE_REMOTE_INSTALL);
584
585 return is_remote_install ? REMOTE_INSTALL_PROMPT : RE_ENABLE_PROMPT;
586}
587
588// static
[email protected]c82da8c42012-06-08 19:49:11589scoped_refptr<Extension>
590 ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
[email protected]023b3d12013-12-23 18:46:49591 const base::DictionaryValue* manifest,
[email protected]c422a862012-07-31 15:46:13592 int flags,
[email protected]c82da8c42012-06-08 19:49:11593 const std::string& id,
594 const std::string& localized_name,
595 const std::string& localized_description,
596 std::string* error) {
dchengc963c7142016-04-08 03:55:22597 std::unique_ptr<base::DictionaryValue> localized_manifest;
[email protected]c82da8c42012-06-08 19:49:11598 if (!localized_name.empty() || !localized_description.empty()) {
599 localized_manifest.reset(manifest->DeepCopy());
600 if (!localized_name.empty()) {
[email protected]6bf90612013-08-15 00:36:27601 localized_manifest->SetString(extensions::manifest_keys::kName,
[email protected]c82da8c42012-06-08 19:49:11602 localized_name);
603 }
604 if (!localized_description.empty()) {
[email protected]6bf90612013-08-15 00:36:27605 localized_manifest->SetString(extensions::manifest_keys::kDescription,
[email protected]c82da8c42012-06-08 19:49:11606 localized_description);
607 }
608 }
609
610 return Extension::Create(
[email protected]650b2d52013-02-10 03:41:45611 base::FilePath(),
[email protected]1d5e58b2013-01-31 08:41:40612 Manifest::INTERNAL,
[email protected]c82da8c42012-06-08 19:49:11613 localized_manifest.get() ? *localized_manifest.get() : *manifest,
[email protected]c422a862012-07-31 15:46:13614 flags,
[email protected]c82da8c42012-06-08 19:49:11615 id,
616 error);
617}
618
[email protected]7f165342014-02-12 09:22:22619ExtensionInstallPrompt::ExtensionInstallPrompt(content::WebContents* contents)
pkotwicza57a1f322014-10-21 00:24:30620 : profile_(ProfileForWebContents(contents)),
621 ui_loop_(base::MessageLoop::current()),
[email protected]c82da8c42012-06-08 19:49:11622 extension_(NULL),
pkotwicza57a1f322014-10-21 00:24:30623 install_ui_(extensions::CreateExtensionInstallUI(
624 ProfileForWebContents(contents))),
pkotwicz2f181782014-10-29 17:33:45625 show_params_(new ExtensionInstallPromptShowParams(contents)),
rdevlin.cronin3fe4bd32016-01-12 18:45:40626 did_call_show_dialog_(false),
627 weak_factory_(this) {
[email protected]d382baa2014-06-17 18:50:01628}
[email protected]5db2e882012-12-20 10:17:26629
pkotwicz2175c622014-10-22 19:56:28630ExtensionInstallPrompt::ExtensionInstallPrompt(Profile* profile,
631 gfx::NativeWindow native_window)
pkotwicza57a1f322014-10-21 00:24:30632 : profile_(profile),
633 ui_loop_(base::MessageLoop::current()),
[email protected]5db2e882012-12-20 10:17:26634 extension_(NULL),
pkotwicza57a1f322014-10-21 00:24:30635 install_ui_(extensions::CreateExtensionInstallUI(profile)),
pkotwicz2f181782014-10-29 17:33:45636 show_params_(
637 new ExtensionInstallPromptShowParams(profile, native_window)),
rdevlin.cronin3fe4bd32016-01-12 18:45:40638 did_call_show_dialog_(false),
639 weak_factory_(this) {
[email protected]d382baa2014-06-17 18:50:01640}
[email protected]c82da8c42012-06-08 19:49:11641
642ExtensionInstallPrompt::~ExtensionInstallPrompt() {
643}
644
rdevlin.croninf84cab72015-12-12 03:45:23645void ExtensionInstallPrompt::ShowDialog(
rdevlin.cronin41593052016-01-08 01:40:12646 const DoneCallback& done_callback,
[email protected]c82da8c42012-06-08 19:49:11647 const Extension* extension,
rdevlin.croninf84cab72015-12-12 03:45:23648 const SkBitmap* icon,
649 const ShowDialogCallback& show_dialog_callback) {
rdevlin.cronin41593052016-01-08 01:40:12650 ShowDialog(done_callback, extension, icon,
dchengc963c7142016-04-08 03:55:22651 base::WrapUnique(new Prompt(INSTALL_PROMPT)),
652 show_dialog_callback);
rdevlin.cronin2e252692015-12-15 21:47:02653}
654
655void ExtensionInstallPrompt::ShowDialog(
rdevlin.cronin41593052016-01-08 01:40:12656 const DoneCallback& done_callback,
rdevlin.cronin2e252692015-12-15 21:47:02657 const Extension* extension,
658 const SkBitmap* icon,
dchengc963c7142016-04-08 03:55:22659 std::unique_ptr<Prompt> prompt,
rdevlin.cronin2e252692015-12-15 21:47:02660 const ShowDialogCallback& show_dialog_callback) {
rdevlin.cronin41593052016-01-08 01:40:12661 ShowDialog(done_callback, extension, icon, std::move(prompt), nullptr,
rdevlin.croninf84cab72015-12-12 03:45:23662 show_dialog_callback);
663}
664
665void ExtensionInstallPrompt::ShowDialog(
rdevlin.cronin41593052016-01-08 01:40:12666 const DoneCallback& done_callback,
rdevlin.croninf84cab72015-12-12 03:45:23667 const Extension* extension,
668 const SkBitmap* icon,
dchengc963c7142016-04-08 03:55:22669 std::unique_ptr<Prompt> prompt,
670 std::unique_ptr<const PermissionSet> custom_permissions,
rdevlin.croninf84cab72015-12-12 03:45:23671 const ShowDialogCallback& show_dialog_callback) {
[email protected]b3a25092013-05-28 22:08:16672 DCHECK(ui_loop_ == base::MessageLoop::current());
rdevlin.cronin2e252692015-12-15 21:47:02673 DCHECK(prompt);
[email protected]c82da8c42012-06-08 19:49:11674 extension_ = extension;
rdevlin.cronin41593052016-01-08 01:40:12675 done_callback_ = done_callback;
rdevlin.croninfc1499f2015-12-21 18:22:00676 if (icon && !icon->empty())
677 SetIcon(icon);
dcheng1fc00f12015-12-26 22:18:03678 prompt_ = std::move(prompt);
679 custom_permissions_ = std::move(custom_permissions);
[email protected]af6efb22012-10-12 02:23:05680 show_dialog_callback_ = show_dialog_callback;
[email protected]c82da8c42012-06-08 19:49:11681
682 // We special-case themes to not show any confirm UI. Instead they are
683 // immediately installed, and then we show an infobar (see OnInstallSuccess)
684 // to allow the user to revert if they don't like it.
685 //
686 // We don't do this in the case where off-store extension installs are
687 // disabled because in that case, we don't show the dangerous download UI, so
688 // we need the UI confirmation.
689 if (extension->is_theme()) {
690 if (extension->from_webstore() ||
[email protected]544471a2012-10-13 05:27:09691 extensions::FeatureSwitch::easy_off_store_install()->IsEnabled()) {
rdevlin.cronin41593052016-01-08 01:40:12692 base::ResetAndReturn(&done_callback_).Run(Result::ACCEPTED);
[email protected]c82da8c42012-06-08 19:49:11693 return;
694 }
695 }
696
697 LoadImageIfNeeded();
698}
699
[email protected]c82da8c42012-06-08 19:49:11700void ExtensionInstallPrompt::OnInstallSuccess(const Extension* extension,
701 SkBitmap* icon) {
702 extension_ = extension;
703 SetIcon(icon);
704
705 install_ui_->OnInstallSuccess(extension, &icon_);
706}
707
[email protected]bf3d9df2012-07-24 23:20:27708void ExtensionInstallPrompt::OnInstallFailure(
ginkage47e603e2015-02-27 08:42:41709 const extensions::CrxInstallError& error) {
[email protected]c82da8c42012-06-08 19:49:11710 install_ui_->OnInstallFailure(error);
711}
712
713void ExtensionInstallPrompt::SetIcon(const SkBitmap* image) {
714 if (image)
715 icon_ = *image;
716 else
717 icon_ = SkBitmap();
[email protected]dd46a4ce2012-09-15 10:50:50718 if (icon_.empty()) {
719 // Let's set default icon bitmap whose size is equal to the default icon's
720 // pixel size under maximal supported scale factor. If the bitmap is larger
721 // than the one we need, it will be scaled down by the ui code.
treibd9e1d9d2015-04-24 11:17:04722 icon_ = GetDefaultIconBitmapForMaxScaleFactor(
723 extension_ ? extension_->is_app() : false);
[email protected]dd46a4ce2012-09-15 10:50:50724 }
[email protected]c82da8c42012-06-08 19:49:11725}
726
[email protected]ec7de0c5a2012-11-16 07:40:47727void ExtensionInstallPrompt::OnImageLoaded(const gfx::Image& image) {
[email protected]c82da8c42012-06-08 19:49:11728 SetIcon(image.IsEmpty() ? NULL : image.ToSkBitmap());
[email protected]4e494872013-09-06 09:13:54729 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11730}
731
732void ExtensionInstallPrompt::LoadImageIfNeeded() {
rdevlin.croninf84cab72015-12-12 03:45:23733 // Don't override an icon that was passed in. Also, bundle installs don't have
734 // an icon (or a specific extension), and profile_| can be null in unit tests.
735 if (!extension_ || !icon_.empty() || !profile_) {
[email protected]4e494872013-09-06 09:13:54736 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11737 return;
738 }
739
[email protected]993da5e2013-03-23 21:25:16740 extensions::ExtensionResource image = extensions::IconsInfo::GetIconResource(
[email protected]702d8b42013-02-27 20:55:50741 extension_,
742 extension_misc::EXTENSION_ICON_LARGE,
743 ExtensionIconSet::MATCH_BIGGER);
[email protected]0d0ba182014-06-03 12:40:43744
745 // Load the image asynchronously. The response will be sent to OnImageLoaded.
pkotwicza57a1f322014-10-21 00:24:30746 extensions::ImageLoader* loader = extensions::ImageLoader::Get(profile_);
[email protected]0d0ba182014-06-03 12:40:43747
748 std::vector<extensions::ImageLoader::ImageRepresentation> images_list;
749 images_list.push_back(extensions::ImageLoader::ImageRepresentation(
750 image,
751 extensions::ImageLoader::ImageRepresentation::NEVER_RESIZE,
752 gfx::Size(),
753 ui::SCALE_FACTOR_100P));
754 loader->LoadImagesAsync(
755 extension_,
756 images_list,
rdevlin.cronin3fe4bd32016-01-12 18:45:40757 base::Bind(&ExtensionInstallPrompt::OnImageLoaded,
758 weak_factory_.GetWeakPtr()));
[email protected]c82da8c42012-06-08 19:49:11759}
760
761void ExtensionInstallPrompt::ShowConfirmation() {
dchengc963c7142016-04-08 03:55:22762 std::unique_ptr<const PermissionSet> permissions_wrapper;
rdevlin.cronine2d0fd02015-09-24 22:35:49763 const PermissionSet* permissions_to_display = nullptr;
gpdavis.chromium0fbac4d2014-09-19 20:57:54764 if (custom_permissions_.get()) {
rdevlin.cronine2d0fd02015-09-24 22:35:49765 permissions_to_display = custom_permissions_.get();
gpdavis.chromium0fbac4d2014-09-19 20:57:54766 } else if (extension_) {
767 // Initialize permissions if they have not already been set so that
768 // withheld permissions are displayed properly in the install prompt.
769 extensions::PermissionsUpdater(
pkotwicza57a1f322014-10-21 00:24:30770 profile_, extensions::PermissionsUpdater::INIT_FLAG_TRANSIENT)
gpdavis.chromium0fbac4d2014-09-19 20:57:54771 .InitializePermissions(extension_);
772 permissions_to_display =
rdevlin.cronind630c302015-09-30 20:19:33773 &extension_->permissions_data()->active_permissions();
treib7496f63c2015-03-04 12:18:53774 // For delegated installs, all optional permissions are pre-approved by the
775 // person who triggers the install, so add them to the list.
treibe36431582015-06-24 15:59:05776 if (prompt_->type() == DELEGATED_PERMISSIONS_PROMPT ||
777 prompt_->type() == DELEGATED_BUNDLE_PERMISSIONS_PROMPT) {
rdevlin.cronind630c302015-09-30 20:19:33778 const PermissionSet& optional_permissions =
treib7496f63c2015-03-04 12:18:53779 extensions::PermissionsParser::GetOptionalPermissions(extension_);
rdevlin.cronine2d0fd02015-09-24 22:35:49780 permissions_wrapper = PermissionSet::CreateUnion(*permissions_to_display,
rdevlin.cronind630c302015-09-30 20:19:33781 optional_permissions);
rdevlin.cronine2d0fd02015-09-24 22:35:49782 permissions_to_display = permissions_wrapper.get();
treib7496f63c2015-03-04 12:18:53783 }
gpdavis.chromium0fbac4d2014-09-19 20:57:54784 }
785
rdevlin.cronine2d0fd02015-09-24 22:35:49786 if (permissions_to_display &&
[email protected]a397ec02014-08-08 15:48:13787 (!extension_ ||
788 !extensions::PermissionsData::ShouldSkipPermissionWarnings(
789 extension_->id()))) {
790 Manifest::Type type =
791 extension_ ? extension_->GetType() : Manifest::TYPE_UNKNOWN;
792 const extensions::PermissionMessageProvider* message_provider =
793 extensions::PermissionMessageProvider::Get();
treib7b45a34b2015-04-16 11:48:02794
treib8d2de482015-08-04 16:36:48795 prompt_->SetPermissions(message_provider->GetPermissionMessages(
796 message_provider->GetAllPermissionIDs(
rdevlin.cronind630c302015-09-30 20:19:33797 *permissions_to_display, type)),
gpdavis.chromium0fbac4d2014-09-19 20:57:54798 REGULAR_PERMISSIONS);
gpdavis.chromium0fbac4d2014-09-19 20:57:54799
rdevlin.cronine2d0fd02015-09-24 22:35:49800 const PermissionSet* withheld =
rdevlin.cronind630c302015-09-30 20:19:33801 extension_ ? &extension_->permissions_data()->withheld_permissions()
treiba21dcd92015-04-03 05:26:41802 : nullptr;
803 if (withheld && !withheld->IsEmpty()) {
gpdavis.chromium0fbac4d2014-09-19 20:57:54804 prompt_->SetPermissions(
treib8d2de482015-08-04 16:36:48805 message_provider->GetPermissionMessages(
rdevlin.cronind630c302015-09-30 20:19:33806 message_provider->GetAllPermissionIDs(*withheld, type)),
treib8d2de482015-08-04 16:36:48807 WITHHELD_PERMISSIONS);
gpdavis.chromium0fbac4d2014-09-19 20:57:54808 }
[email protected]bebe1d02012-08-02 20:17:09809 }
[email protected]c82da8c42012-06-08 19:49:11810
[email protected]d382baa2014-06-17 18:50:01811 switch (prompt_->type()) {
[email protected]c82da8c42012-06-08 19:49:11812 case PERMISSIONS_PROMPT:
813 case RE_ENABLE_PROMPT:
814 case INLINE_INSTALL_PROMPT:
[email protected]612a1cb12012-10-17 13:18:03815 case EXTERNAL_INSTALL_PROMPT:
[email protected]15d267b42013-02-14 23:43:32816 case INSTALL_PROMPT:
[email protected]21db9ef2014-05-16 02:06:27817 case POST_INSTALL_PERMISSIONS_PROMPT:
rdevlin.cronin5f6b69d2014-09-20 01:23:35818 case REMOTE_INSTALL_PROMPT:
treib2d2f5372015-03-01 12:20:49819 case REPAIR_PROMPT:
820 case DELEGATED_PERMISSIONS_PROMPT: {
[email protected]d382baa2014-06-17 18:50:01821 prompt_->set_extension(extension_);
[email protected]c82da8c42012-06-08 19:49:11822 break;
823 }
treibe36431582015-06-24 15:59:05824 case BUNDLE_INSTALL_PROMPT:
825 case DELEGATED_BUNDLE_PERMISSIONS_PROMPT: {
rdevlin.croninf84cab72015-12-12 03:45:23826 DCHECK(prompt_->bundle());
[email protected]c82da8c42012-06-08 19:49:11827 break;
828 }
benwells1dd4acd2015-12-09 02:20:24829 case LAUNCH_PROMPT_DEPRECATED:
[email protected]c82da8c42012-06-08 19:49:11830 default:
831 NOTREACHED() << "Unknown message";
[email protected]af6efb22012-10-12 02:23:05832 return;
[email protected]c82da8c42012-06-08 19:49:11833 }
treibd9e1d9d2015-04-24 11:17:04834 prompt_->set_icon(gfx::Image::CreateFrom1xBitmap(icon_));
[email protected]af6efb22012-10-12 02:23:05835
pkotwicz2f181782014-10-29 17:33:45836 if (show_params_->WasParentDestroyed()) {
rdevlin.cronin41593052016-01-08 01:40:12837 base::ResetAndReturn(&done_callback_).Run(Result::ABORTED);
pkotwicz2f181782014-10-29 17:33:45838 return;
839 }
840
rdevlin.croninca5bf2da2015-12-17 21:21:08841 g_last_prompt_type_for_tests = prompt_->type();
842 did_call_show_dialog_ = true;
843
rdevlin.cronin41593052016-01-08 01:40:12844 if (AutoConfirmPrompt(&done_callback_))
rdevlin.croninca5bf2da2015-12-17 21:21:08845 return;
846
[email protected]5db2e882012-12-20 10:17:26847 if (show_dialog_callback_.is_null())
rdevlin.cronin41593052016-01-08 01:40:12848 show_dialog_callback_ = GetDefaultShowDialogCallback();
849 base::ResetAndReturn(&show_dialog_callback_)
850 .Run(show_params_.get(), base::ResetAndReturn(&done_callback_),
851 std::move(prompt_));
[email protected]c82da8c42012-06-08 19:49:11852}