blob: de42c48bccd38eeacee8c40d89e532d2550055b1 [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
7#include <map>
8
9#include "base/command_line.h"
[email protected]b19fe572013-07-18 04:54:2610#include "base/message_loop/message_loop.h"
[email protected]3853a4c2013-02-11 17:15:5711#include "base/prefs/pref_service.h"
[email protected]3ea1b182013-02-08 22:38:4112#include "base/strings/string_number_conversions.h"
sashabeabd5df2014-11-06 02:38:2513#include "base/strings/string_split.h"
[email protected]00e7bef2013-06-10 20:35:1714#include "base/strings/string_util.h"
15#include "base/strings/stringprintf.h"
[email protected]112158af2013-06-07 23:46:1816#include "base/strings/utf_string_conversions.h"
[email protected]c82da8c42012-06-08 19:49:1117#include "chrome/browser/extensions/bundle_installer.h"
pkotwicz2f181782014-10-29 17:33:4518#include "chrome/browser/extensions/extension_install_prompt_show_params.h"
[email protected]7eb20e32014-04-30 08:50:5619#include "chrome/browser/extensions/extension_util.h"
gpdavis.chromium0fbac4d2014-09-19 20:57:5420#include "chrome/browser/extensions/permissions_updater.h"
[email protected]c82da8c42012-06-08 19:49:1121#include "chrome/browser/profiles/profile.h"
pkotwicza57a1f322014-10-21 00:24:3022#include "chrome/browser/ui/extensions/extension_install_ui_factory.h"
[email protected]c82da8c42012-06-08 19:49:1123#include "chrome/common/chrome_switches.h"
[email protected]af39f002014-08-22 10:18:1824#include "chrome/grit/chromium_strings.h"
25#include "chrome/grit/generated_resources.h"
[email protected]91e51d612012-10-21 23:03:0526#include "content/public/browser/web_contents.h"
[email protected]21db9ef2014-05-16 02:06:2727#include "extensions/browser/extension_prefs.h"
[email protected]411f8ae2014-05-22 11:12:2328#include "extensions/browser/extension_util.h"
[email protected]326e6f02014-06-20 04:53:3729#include "extensions/browser/image_loader.h"
pkotwicza57a1f322014-10-21 00:24:3030#include "extensions/browser/install/extension_install_ui.h"
[email protected]cda103d2014-04-04 16:22:3931#include "extensions/common/constants.h"
[email protected]e4452d32013-11-15 23:07:4132#include "extensions/common/extension.h"
[email protected]4b7908842014-04-07 23:50:2233#include "extensions/common/extension_icon_set.h"
[email protected]993da5e2013-03-23 21:25:1634#include "extensions/common/extension_resource.h"
[email protected]5ef835a2013-11-08 20:42:5735#include "extensions/common/feature_switch.h"
[email protected]d42c11152013-08-22 19:36:3236#include "extensions/common/manifest.h"
[email protected]6bf90612013-08-15 00:36:2737#include "extensions/common/manifest_constants.h"
[email protected]0db486f2014-04-09 19:32:2238#include "extensions/common/manifest_handlers/icons_handler.h"
[email protected]c41003472013-10-19 15:37:2539#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"
[email protected]885c0e92012-11-13 20:27:4242#include "extensions/common/url_pattern.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"
[email protected]c82da8c42012-06-08 19:49:1147#include "ui/gfx/image/image.h"
48
[email protected]c82da8c42012-06-08 19:49:1149using extensions::BundleInstaller;
50using extensions::Extension;
[email protected]1d5e58b2013-01-31 08:41:4051using extensions::Manifest;
[email protected]c2e66e12012-06-27 06:27:0652using extensions::PermissionSet;
[email protected]c82da8c42012-06-08 19:49:1153
[email protected]612a1cb12012-10-17 13:18:0354namespace {
55
rdevlin.cronin5f6b69d2014-09-20 01:23:3556bool AllowWebstoreData(ExtensionInstallPrompt::PromptType type) {
57 return type == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT ||
58 type == ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT ||
59 type == ExtensionInstallPrompt::REPAIR_PROMPT;
60}
61
[email protected]c82da8c42012-06-08 19:49:1162static const int kTitleIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2763 0, // The regular install prompt depends on what's being installed.
64 IDS_EXTENSION_INLINE_INSTALL_PROMPT_TITLE,
65 IDS_EXTENSION_INSTALL_PROMPT_TITLE,
66 IDS_EXTENSION_RE_ENABLE_PROMPT_TITLE,
67 IDS_EXTENSION_PERMISSIONS_PROMPT_TITLE,
68 IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_TITLE,
69 IDS_EXTENSION_POST_INSTALL_PERMISSIONS_PROMPT_TITLE,
70 IDS_EXTENSION_LAUNCH_APP_PROMPT_TITLE,
71 0, // The remote install prompt depends on what's being installed.
rdevlin.cronin5f6b69d2014-09-20 01:23:3572 0, // The repair install prompt depends on what's being installed.
[email protected]c82da8c42012-06-08 19:49:1173};
74static const int kHeadingIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2775 IDS_EXTENSION_INSTALL_PROMPT_HEADING,
76 0, // Inline installs use the extension name.
77 0, // Heading for bundle installs depends on the bundle contents.
78 IDS_EXTENSION_RE_ENABLE_PROMPT_HEADING,
79 IDS_EXTENSION_PERMISSIONS_PROMPT_HEADING,
80 0, // External installs use different strings for extensions/apps.
81 IDS_EXTENSION_POST_INSTALL_PERMISSIONS_PROMPT_HEADING,
82 IDS_EXTENSION_LAUNCH_APP_PROMPT_HEADING,
83 IDS_EXTENSION_REMOTE_INSTALL_PROMPT_HEADING,
rdevlin.cronin5f6b69d2014-09-20 01:23:3584 IDS_EXTENSION_REPAIR_PROMPT_HEADING
[email protected]15d267b42013-02-14 23:43:3285};
86static const int kButtons[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2787 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
88 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
89 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
90 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
91 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
92 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
93 ui::DIALOG_BUTTON_CANCEL,
94 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
95 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
rdevlin.cronin5f6b69d2014-09-20 01:23:3596 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
[email protected]c82da8c42012-06-08 19:49:1197};
98static const int kAcceptButtonIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2799 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
100 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
101 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
102 IDS_EXTENSION_PROMPT_RE_ENABLE_BUTTON,
103 IDS_EXTENSION_PROMPT_PERMISSIONS_BUTTON,
104 0, // External installs use different strings for extensions/apps.
reillygc64d3dd2014-09-29 21:10:11105 0, // Different strings depending on the files and devices retained.
[email protected]21db9ef2014-05-16 02:06:27106 IDS_EXTENSION_PROMPT_LAUNCH_BUTTON,
107 IDS_EXTENSION_PROMPT_REMOTE_INSTALL_BUTTON,
rdevlin.cronin5f6b69d2014-09-20 01:23:35108 IDS_EXTENSION_PROMPT_REPAIR_BUTTON,
[email protected]c82da8c42012-06-08 19:49:11109};
110static const int kAbortButtonIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:27111 0, // These all use the platform's default cancel label.
112 0,
113 0,
114 0,
115 IDS_EXTENSION_PROMPT_PERMISSIONS_ABORT_BUTTON,
116 IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ABORT_BUTTON,
117 IDS_CLOSE,
118 0, // Platform dependent cancel button.
119 0,
rdevlin.cronin5f6b69d2014-09-20 01:23:35120 0,
[email protected]c82da8c42012-06-08 19:49:11121};
[email protected]21db9ef2014-05-16 02:06:27122static const int
123 kPermissionsHeaderIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
124 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
125 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
126 IDS_EXTENSION_PROMPT_THESE_WILL_HAVE_ACCESS_TO,
127 IDS_EXTENSION_PROMPT_WILL_NOW_HAVE_ACCESS_TO,
128 IDS_EXTENSION_PROMPT_WANTS_ACCESS_TO,
129 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
130 IDS_EXTENSION_PROMPT_CAN_ACCESS,
131 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
132 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
rdevlin.cronin5f6b69d2014-09-20 01:23:35133 IDS_EXTENSION_PROMPT_CAN_ACCESS,
[email protected]c82da8c42012-06-08 19:49:11134};
135
[email protected]dd46a4ce2012-09-15 10:50:50136// Returns bitmap for the default icon with size equal to the default icon's
137// pixel size under maximal supported scale factor.
138SkBitmap GetDefaultIconBitmapForMaxScaleFactor(bool is_app) {
[email protected]702d8b42013-02-27 20:55:50139 const gfx::ImageSkia& image = is_app ?
[email protected]7eb20e32014-04-30 08:50:56140 extensions::util::GetDefaultAppIcon() :
141 extensions::util::GetDefaultExtensionIcon();
[email protected]50b66262013-09-24 03:25:48142 return image.GetRepresentation(
143 gfx::ImageSkia::GetMaxSupportedScale()).sk_bitmap();
[email protected]dd46a4ce2012-09-15 10:50:50144}
145
[email protected]af6efb22012-10-12 02:23:05146// If auto confirm is enabled then posts a task to proceed with or cancel the
147// install and returns true. Otherwise returns false.
148bool AutoConfirmPrompt(ExtensionInstallPrompt::Delegate* delegate) {
[email protected]2a74d6f62014-07-24 11:53:47149 switch (ExtensionInstallPrompt::g_auto_confirm_for_tests) {
150 case ExtensionInstallPrompt::NONE:
151 return false;
152 // We use PostTask instead of calling the delegate directly here, because in
153 // the real implementations it's highly likely the message loop will be
154 // pumping a few times before the user clicks accept or cancel.
155 case ExtensionInstallPrompt::ACCEPT:
156 base::MessageLoop::current()->PostTask(
157 FROM_HERE,
158 base::Bind(&ExtensionInstallPrompt::Delegate::InstallUIProceed,
159 base::Unretained(delegate)));
160 return true;
161 case ExtensionInstallPrompt::CANCEL:
162 base::MessageLoop::current()->PostTask(
163 FROM_HERE,
164 base::Bind(&ExtensionInstallPrompt::Delegate::InstallUIAbort,
165 base::Unretained(delegate),
166 true));
167 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
[email protected]2a74d6f62014-07-24 11:53:47189// static
190ExtensionInstallPrompt::AutoConfirmForTests
191ExtensionInstallPrompt::g_auto_confirm_for_tests = ExtensionInstallPrompt::NONE;
192
rdevlin.cronin092c6772014-11-20 23:52:40193ExtensionInstallPrompt::PromptType
194ExtensionInstallPrompt::g_last_prompt_type_for_tests =
195 ExtensionInstallPrompt::UNSET_PROMPT_TYPE;
196
[email protected]eeb0d3e12014-08-15 15:10:44197// This should match the PromptType enum.
198std::string ExtensionInstallPrompt::PromptTypeToString(PromptType type) {
199 switch (type) {
200 case ExtensionInstallPrompt::INSTALL_PROMPT:
201 return "INSTALL_PROMPT";
202 case ExtensionInstallPrompt::INLINE_INSTALL_PROMPT:
203 return "INLINE_INSTALL_PROMPT";
204 case ExtensionInstallPrompt::BUNDLE_INSTALL_PROMPT:
205 return "BUNDLE_INSTALL_PROMPT";
206 case ExtensionInstallPrompt::RE_ENABLE_PROMPT:
207 return "RE_ENABLE_PROMPT";
208 case ExtensionInstallPrompt::PERMISSIONS_PROMPT:
209 return "PERMISSIONS_PROMPT";
210 case ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT:
211 return "EXTERNAL_INSTALL_PROMPT";
212 case ExtensionInstallPrompt::POST_INSTALL_PERMISSIONS_PROMPT:
213 return "POST_INSTALL_PERMISSIONS_PROMPT";
214 case ExtensionInstallPrompt::LAUNCH_PROMPT:
215 return "LAUNCH_PROMPT";
216 case ExtensionInstallPrompt::REMOTE_INSTALL_PROMPT:
217 return "REMOTE_INSTALL_PROMPT";
rdevlin.cronin5f6b69d2014-09-20 01:23:35218 case ExtensionInstallPrompt::REPAIR_PROMPT:
219 return "REPAIR_PROMPT";
[email protected]eeb0d3e12014-08-15 15:10:44220 case ExtensionInstallPrompt::UNSET_PROMPT_TYPE:
221 case ExtensionInstallPrompt::NUM_PROMPT_TYPES:
222 break;
223 }
224 return "OTHER";
225}
226
[email protected]5db2e882012-12-20 10:17:26227ExtensionInstallPrompt::Prompt::Prompt(PromptType type)
[email protected]c82da8c42012-06-08 19:49:11228 : type_(type),
[email protected]79a6f99a2013-08-29 00:32:58229 is_showing_details_for_retained_files_(false),
reillygc64d3dd2014-09-29 21:10:11230 is_showing_details_for_retained_devices_(false),
[email protected]c82da8c42012-06-08 19:49:11231 extension_(NULL),
232 bundle_(NULL),
233 average_rating_(0.0),
[email protected]dcde34b32013-07-31 02:28:45234 rating_count_(0),
[email protected]34b5f7f2014-01-29 02:48:11235 show_user_count_(false),
236 has_webstore_data_(false) {
[email protected]c82da8c42012-06-08 19:49:11237}
238
239ExtensionInstallPrompt::Prompt::~Prompt() {
240}
241
242void ExtensionInstallPrompt::Prompt::SetPermissions(
gpdavis.chromium0fbac4d2014-09-19 20:57:54243 const std::vector<base::string16>& permissions,
244 PermissionsType permissions_type) {
245 GetPermissionsForType(permissions_type).permissions = permissions;
[email protected]c82da8c42012-06-08 19:49:11246}
247
[email protected]8ab7e6c2013-07-11 21:15:03248void ExtensionInstallPrompt::Prompt::SetPermissionsDetails(
gpdavis.chromium0fbac4d2014-09-19 20:57:54249 const std::vector<base::string16>& details,
250 PermissionsType permissions_type) {
251 InstallPromptPermissions& install_permissions =
252 GetPermissionsForType(permissions_type);
sashabeabd5df2014-11-06 02:38:25253
254 // Add a dash to the front of each permission detail.
255 for (const auto& details_entry : details) {
256 if (!details_entry.empty()) {
257 std::vector<base::string16> detail_lines;
258 base::SplitString(details_entry, base::char16('\n'), &detail_lines);
259
260 std::vector<base::string16> detail_lines_with_bullets;
261 for (const auto& detail_line : detail_lines)
262 detail_lines_with_bullets.push_back(base::ASCIIToUTF16("- ") +
263 detail_line);
264
265 install_permissions.details.push_back(
266 JoinString(detail_lines_with_bullets, '\n'));
267 } else {
268 install_permissions.details.push_back(details_entry);
269 }
270 }
271
gpdavis.chromium0fbac4d2014-09-19 20:57:54272 install_permissions.is_showing_details.clear();
273 install_permissions.is_showing_details.insert(
274 install_permissions.is_showing_details.begin(), details.size(), false);
[email protected]79a6f99a2013-08-29 00:32:58275}
276
277void ExtensionInstallPrompt::Prompt::SetIsShowingDetails(
278 DetailsType type,
279 size_t index,
280 bool is_showing_details) {
281 switch (type) {
282 case PERMISSIONS_DETAILS:
gpdavis.chromium0fbac4d2014-09-19 20:57:54283 prompt_permissions_.is_showing_details[index] = is_showing_details;
284 break;
285 case WITHHELD_PERMISSIONS_DETAILS:
286 withheld_prompt_permissions_.is_showing_details[index] =
287 is_showing_details;
[email protected]79a6f99a2013-08-29 00:32:58288 break;
[email protected]79a6f99a2013-08-29 00:32:58289 case RETAINED_FILES_DETAILS:
290 is_showing_details_for_retained_files_ = is_showing_details;
291 break;
reillygc64d3dd2014-09-29 21:10:11292 case RETAINED_DEVICES_DETAILS:
293 is_showing_details_for_retained_devices_ = is_showing_details;
294 break;
[email protected]79a6f99a2013-08-29 00:32:58295 }
[email protected]8ab7e6c2013-07-11 21:15:03296}
297
[email protected]34b5f7f2014-01-29 02:48:11298void ExtensionInstallPrompt::Prompt::SetWebstoreData(
[email protected]c82da8c42012-06-08 19:49:11299 const std::string& localized_user_count,
[email protected]dcde34b32013-07-31 02:28:45300 bool show_user_count,
[email protected]c82da8c42012-06-08 19:49:11301 double average_rating,
302 int rating_count) {
rdevlin.cronin5f6b69d2014-09-20 01:23:35303 CHECK(AllowWebstoreData(type_));
[email protected]c82da8c42012-06-08 19:49:11304 localized_user_count_ = localized_user_count;
[email protected]dcde34b32013-07-31 02:28:45305 show_user_count_ = show_user_count;
[email protected]c82da8c42012-06-08 19:49:11306 average_rating_ = average_rating;
307 rating_count_ = rating_count;
[email protected]34b5f7f2014-01-29 02:48:11308 has_webstore_data_ = true;
[email protected]c82da8c42012-06-08 19:49:11309}
310
[email protected]6a72a632013-12-12 22:22:00311base::string16 ExtensionInstallPrompt::Prompt::GetDialogTitle() const {
[email protected]c82da8c42012-06-08 19:49:11312 int resource_id = kTitleIds[type_];
313
314 if (type_ == INSTALL_PROMPT) {
315 if (extension_->is_app())
316 resource_id = IDS_EXTENSION_INSTALL_APP_PROMPT_TITLE;
317 else if (extension_->is_theme())
318 resource_id = IDS_EXTENSION_INSTALL_THEME_PROMPT_TITLE;
319 else
320 resource_id = IDS_EXTENSION_INSTALL_EXTENSION_PROMPT_TITLE;
[email protected]612a1cb12012-10-17 13:18:03321 } else if (type_ == EXTERNAL_INSTALL_PROMPT) {
322 return l10n_util::GetStringFUTF16(
[email protected]04338722013-12-24 23:18:05323 resource_id, base::UTF8ToUTF16(extension_->name()));
[email protected]21db9ef2014-05-16 02:06:27324 } else if (type_ == REMOTE_INSTALL_PROMPT) {
325 if (extension_->is_app())
326 resource_id = IDS_EXTENSION_REMOTE_INSTALL_APP_PROMPT_TITLE;
327 else
328 resource_id = IDS_EXTENSION_REMOTE_INSTALL_EXTENSION_PROMPT_TITLE;
rdevlin.cronin5f6b69d2014-09-20 01:23:35329 } else if (type_ == REPAIR_PROMPT) {
330 if (extension_->is_app())
331 resource_id = IDS_EXTENSION_REPAIR_APP_PROMPT_TITLE;
332 else
333 resource_id = IDS_EXTENSION_REPAIR_EXTENSION_PROMPT_TITLE;
[email protected]c82da8c42012-06-08 19:49:11334 }
335
336 return l10n_util::GetStringUTF16(resource_id);
337}
338
[email protected]6a72a632013-12-12 22:22:00339base::string16 ExtensionInstallPrompt::Prompt::GetHeading() const {
[email protected]c82da8c42012-06-08 19:49:11340 if (type_ == INLINE_INSTALL_PROMPT) {
[email protected]04338722013-12-24 23:18:05341 return base::UTF8ToUTF16(extension_->name());
[email protected]c82da8c42012-06-08 19:49:11342 } else if (type_ == BUNDLE_INSTALL_PROMPT) {
343 return bundle_->GetHeadingTextFor(BundleInstaller::Item::STATE_PENDING);
[email protected]612a1cb12012-10-17 13:18:03344 } else if (type_ == EXTERNAL_INSTALL_PROMPT) {
[email protected]846606012012-10-19 18:42:25345 int resource_id = -1;
346 if (extension_->is_app())
347 resource_id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_HEADING_APP;
348 else if (extension_->is_theme())
349 resource_id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_HEADING_THEME;
350 else
351 resource_id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_HEADING_EXTENSION;
352 return l10n_util::GetStringUTF16(resource_id);
[email protected]c82da8c42012-06-08 19:49:11353 } else {
354 return l10n_util::GetStringFUTF16(
[email protected]04338722013-12-24 23:18:05355 kHeadingIds[type_], base::UTF8ToUTF16(extension_->name()));
[email protected]c82da8c42012-06-08 19:49:11356 }
357}
358
[email protected]15d267b42013-02-14 23:43:32359int ExtensionInstallPrompt::Prompt::GetDialogButtons() const {
reillygc64d3dd2014-09-29 21:10:11360 if (type_ == POST_INSTALL_PERMISSIONS_PROMPT && ShouldDisplayRevokeButton()) {
[email protected]a2886e8b2013-06-08 05:15:02361 return kButtons[type_] | ui::DIALOG_BUTTON_OK;
362 }
363
[email protected]15d267b42013-02-14 23:43:32364 return kButtons[type_];
365}
366
[email protected]62a28d7c2013-12-28 01:34:49367bool ExtensionInstallPrompt::Prompt::ShouldShowExplanationText() const {
dchengc7047942014-08-26 05:05:31368 return type_ == INSTALL_PROMPT && extension_->is_extension() &&
369 experiment_.get() && experiment_->text_only();
[email protected]62a28d7c2013-12-28 01:34:49370}
371
[email protected]15d267b42013-02-14 23:43:32372bool ExtensionInstallPrompt::Prompt::HasAcceptButtonLabel() const {
reillygc64d3dd2014-09-29 21:10:11373 if (type_ == POST_INSTALL_PERMISSIONS_PROMPT)
374 return ShouldDisplayRevokeButton();
375
[email protected]a2886e8b2013-06-08 05:15:02376 if (kAcceptButtonIds[type_] == 0)
377 return false;
378
[email protected]a2886e8b2013-06-08 05:15:02379 return true;
[email protected]15d267b42013-02-14 23:43:32380}
381
[email protected]6a72a632013-12-12 22:22:00382base::string16 ExtensionInstallPrompt::Prompt::GetAcceptButtonLabel() const {
[email protected]846606012012-10-19 18:42:25383 if (type_ == EXTERNAL_INSTALL_PROMPT) {
384 int id = -1;
385 if (extension_->is_app())
386 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_APP;
387 else if (extension_->is_theme())
388 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_THEME;
389 else
390 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_EXTENSION;
391 return l10n_util::GetStringUTF16(id);
reillygc64d3dd2014-09-29 21:10:11392 } else if (type_ == POST_INSTALL_PERMISSIONS_PROMPT) {
393 int id = -1;
394 if (GetRetainedFileCount() && GetRetainedDeviceCount()) {
395 id =
396 IDS_EXTENSION_PROMPT_PERMISSIONS_CLEAR_RETAINED_FILES_AND_DEVICES_BUTTON;
397 } else if (GetRetainedFileCount()) {
398 id = IDS_EXTENSION_PROMPT_PERMISSIONS_CLEAR_RETAINED_FILES_BUTTON;
399 } else {
400 DCHECK_LT(0U, GetRetainedDeviceCount());
401 id = IDS_EXTENSION_PROMPT_PERMISSIONS_CLEAR_RETAINED_DEVICES_BUTTON;
402 }
403 return l10n_util::GetStringUTF16(id);
[email protected]846606012012-10-19 18:42:25404 }
[email protected]62a28d7c2013-12-28 01:34:49405 if (ShouldShowExplanationText())
406 return experiment_->GetOkButtonText();
[email protected]c82da8c42012-06-08 19:49:11407 return l10n_util::GetStringUTF16(kAcceptButtonIds[type_]);
408}
409
410bool ExtensionInstallPrompt::Prompt::HasAbortButtonLabel() const {
[email protected]62a28d7c2013-12-28 01:34:49411 if (ShouldShowExplanationText())
412 return true;
[email protected]c82da8c42012-06-08 19:49:11413 return kAbortButtonIds[type_] > 0;
414}
415
[email protected]6a72a632013-12-12 22:22:00416base::string16 ExtensionInstallPrompt::Prompt::GetAbortButtonLabel() const {
[email protected]c82da8c42012-06-08 19:49:11417 CHECK(HasAbortButtonLabel());
[email protected]62a28d7c2013-12-28 01:34:49418 if (ShouldShowExplanationText())
419 return experiment_->GetCancelButtonText();
[email protected]c82da8c42012-06-08 19:49:11420 return l10n_util::GetStringUTF16(kAbortButtonIds[type_]);
421}
422
gpdavis.chromium0fbac4d2014-09-19 20:57:54423base::string16 ExtensionInstallPrompt::Prompt::GetPermissionsHeading(
424 PermissionsType permissions_type) const {
425 switch (permissions_type) {
426 case REGULAR_PERMISSIONS:
427 return l10n_util::GetStringUTF16(kPermissionsHeaderIds[type_]);
428 case WITHHELD_PERMISSIONS:
429 return l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WITHHELD);
430 case ALL_PERMISSIONS:
431 default:
432 NOTREACHED();
433 return base::string16();
434 }
[email protected]c82da8c42012-06-08 19:49:11435}
436
[email protected]6a72a632013-12-12 22:22:00437base::string16 ExtensionInstallPrompt::Prompt::GetRetainedFilesHeading() const {
[email protected]4f1e1082013-09-23 10:30:53438 const int kRetainedFilesMessageIDs[6] = {
439 IDS_EXTENSION_PROMPT_RETAINED_FILES_DEFAULT,
440 IDS_EXTENSION_PROMPT_RETAINED_FILE_SINGULAR,
441 IDS_EXTENSION_PROMPT_RETAINED_FILES_ZERO,
442 IDS_EXTENSION_PROMPT_RETAINED_FILES_TWO,
443 IDS_EXTENSION_PROMPT_RETAINED_FILES_FEW,
444 IDS_EXTENSION_PROMPT_RETAINED_FILES_MANY,
445 };
reillygc64d3dd2014-09-29 21:10:11446 std::vector<int> message_ids(
447 kRetainedFilesMessageIDs,
448 kRetainedFilesMessageIDs + arraysize(kRetainedFilesMessageIDs));
449
[email protected]4f1e1082013-09-23 10:30:53450 return l10n_util::GetPluralStringFUTF16(message_ids, GetRetainedFileCount());
[email protected]8ab7e6c2013-07-11 21:15:03451}
452
reillygc64d3dd2014-09-29 21:10:11453base::string16 ExtensionInstallPrompt::Prompt::GetRetainedDevicesHeading()
454 const {
455 const int kRetainedDevicesMessageIDs[6] = {
456 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_DEFAULT,
457 IDS_EXTENSION_PROMPT_RETAINED_DEVICE_SINGULAR,
458 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_ZERO,
459 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_TWO,
460 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_FEW,
461 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_MANY,
462 };
463 std::vector<int> message_ids(
464 kRetainedDevicesMessageIDs,
465 kRetainedDevicesMessageIDs + arraysize(kRetainedDevicesMessageIDs));
466
467 return l10n_util::GetPluralStringFUTF16(message_ids,
468 GetRetainedDeviceCount());
469}
470
[email protected]f2cd8992013-06-11 17:30:18471bool ExtensionInstallPrompt::Prompt::ShouldShowPermissions() const {
gpdavis.chromium0fbac4d2014-09-19 20:57:54472 return GetPermissionCount(ALL_PERMISSIONS) > 0 ||
473 type_ == POST_INSTALL_PERMISSIONS_PROMPT;
[email protected]f2cd8992013-06-11 17:30:18474}
475
[email protected]c82da8c42012-06-08 19:49:11476void ExtensionInstallPrompt::Prompt::AppendRatingStars(
477 StarAppender appender, void* data) const {
478 CHECK(appender);
rdevlin.cronin5f6b69d2014-09-20 01:23:35479 CHECK(AllowWebstoreData(type_));
[email protected]c82da8c42012-06-08 19:49:11480 int rating_integer = floor(average_rating_);
481 double rating_fractional = average_rating_ - rating_integer;
482
483 if (rating_fractional > 0.66) {
484 rating_integer++;
485 }
486
487 if (rating_fractional < 0.33 || rating_fractional > 0.66) {
488 rating_fractional = 0;
489 }
490
491 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
492 int i;
493 for (i = 0; i < rating_integer; i++) {
494 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_ON), data);
495 }
496 if (rating_fractional) {
497 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_HALF_LEFT), data);
498 i++;
499 }
500 for (; i < kMaxExtensionRating; i++) {
501 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_OFF), data);
502 }
503}
504
[email protected]6a72a632013-12-12 22:22:00505base::string16 ExtensionInstallPrompt::Prompt::GetRatingCount() const {
rdevlin.cronin5f6b69d2014-09-20 01:23:35506 CHECK(AllowWebstoreData(type_));
[email protected]6725048e2013-10-24 21:47:14507 return l10n_util::GetStringFUTF16(IDS_EXTENSION_RATING_COUNT,
508 base::IntToString16(rating_count_));
[email protected]c82da8c42012-06-08 19:49:11509}
510
[email protected]6a72a632013-12-12 22:22:00511base::string16 ExtensionInstallPrompt::Prompt::GetUserCount() const {
rdevlin.cronin5f6b69d2014-09-20 01:23:35512 CHECK(AllowWebstoreData(type_));
[email protected]dcde34b32013-07-31 02:28:45513
514 if (show_user_count_) {
[email protected]6725048e2013-10-24 21:47:14515 return l10n_util::GetStringFUTF16(IDS_EXTENSION_USER_COUNT,
516 base::UTF8ToUTF16(localized_user_count_));
[email protected]dcde34b32013-07-31 02:28:45517 }
[email protected]6725048e2013-10-24 21:47:14518 return base::string16();
[email protected]c82da8c42012-06-08 19:49:11519}
520
gpdavis.chromium0fbac4d2014-09-19 20:57:54521size_t ExtensionInstallPrompt::Prompt::GetPermissionCount(
522 PermissionsType permissions_type) const {
523 switch (permissions_type) {
524 case REGULAR_PERMISSIONS:
525 return prompt_permissions_.permissions.size();
526 case WITHHELD_PERMISSIONS:
527 return withheld_prompt_permissions_.permissions.size();
528 case ALL_PERMISSIONS:
529 return prompt_permissions_.permissions.size() +
530 withheld_prompt_permissions_.permissions.size();
531 default:
532 NOTREACHED();
533 return 0u;
534 }
[email protected]c82da8c42012-06-08 19:49:11535}
536
gpdavis.chromium0fbac4d2014-09-19 20:57:54537size_t ExtensionInstallPrompt::Prompt::GetPermissionsDetailsCount(
538 PermissionsType permissions_type) const {
539 switch (permissions_type) {
540 case REGULAR_PERMISSIONS:
541 return prompt_permissions_.details.size();
542 case WITHHELD_PERMISSIONS:
543 return withheld_prompt_permissions_.details.size();
544 case ALL_PERMISSIONS:
545 return prompt_permissions_.details.size() +
546 withheld_prompt_permissions_.details.size();
547 default:
548 NOTREACHED();
549 return 0u;
550 }
[email protected]8ab7e6c2013-07-11 21:15:03551}
552
gpdavis.chromium0fbac4d2014-09-19 20:57:54553base::string16 ExtensionInstallPrompt::Prompt::GetPermission(
554 size_t index,
555 PermissionsType permissions_type) const {
556 const InstallPromptPermissions& install_permissions =
557 GetPermissionsForType(permissions_type);
558 CHECK_LT(index, install_permissions.permissions.size());
559 return install_permissions.permissions[index];
[email protected]c82da8c42012-06-08 19:49:11560}
561
[email protected]6a72a632013-12-12 22:22:00562base::string16 ExtensionInstallPrompt::Prompt::GetPermissionsDetails(
gpdavis.chromium0fbac4d2014-09-19 20:57:54563 size_t index,
564 PermissionsType permissions_type) const {
565 const InstallPromptPermissions& install_permissions =
566 GetPermissionsForType(permissions_type);
567 CHECK_LT(index, install_permissions.details.size());
568 return install_permissions.details[index];
[email protected]8ab7e6c2013-07-11 21:15:03569}
570
[email protected]79a6f99a2013-08-29 00:32:58571bool ExtensionInstallPrompt::Prompt::GetIsShowingDetails(
572 DetailsType type, size_t index) const {
573 switch (type) {
574 case PERMISSIONS_DETAILS:
gpdavis.chromium0fbac4d2014-09-19 20:57:54575 CHECK_LT(index, prompt_permissions_.is_showing_details.size());
576 return prompt_permissions_.is_showing_details[index];
577 case WITHHELD_PERMISSIONS_DETAILS:
578 CHECK_LT(index, withheld_prompt_permissions_.is_showing_details.size());
579 return withheld_prompt_permissions_.is_showing_details[index];
[email protected]79a6f99a2013-08-29 00:32:58580 case RETAINED_FILES_DETAILS:
581 return is_showing_details_for_retained_files_;
reillygc64d3dd2014-09-29 21:10:11582 case RETAINED_DEVICES_DETAILS:
583 return is_showing_details_for_retained_devices_;
[email protected]79a6f99a2013-08-29 00:32:58584 }
585 return false;
586}
587
[email protected]a2886e8b2013-06-08 05:15:02588size_t ExtensionInstallPrompt::Prompt::GetRetainedFileCount() const {
589 return retained_files_.size();
590}
591
[email protected]6a72a632013-12-12 22:22:00592base::string16 ExtensionInstallPrompt::Prompt::GetRetainedFile(size_t index)
593 const {
[email protected]a2886e8b2013-06-08 05:15:02594 CHECK_LT(index, retained_files_.size());
[email protected]6725048e2013-10-24 21:47:14595 return retained_files_[index].AsUTF16Unsafe();
[email protected]a2886e8b2013-06-08 05:15:02596}
597
reillygc64d3dd2014-09-29 21:10:11598size_t ExtensionInstallPrompt::Prompt::GetRetainedDeviceCount() const {
599 return retained_device_messages_.size();
600}
601
602base::string16 ExtensionInstallPrompt::Prompt::GetRetainedDeviceMessageString(
603 size_t index) const {
604 CHECK_LT(index, retained_device_messages_.size());
605 return retained_device_messages_[index];
606}
607
608bool ExtensionInstallPrompt::Prompt::ShouldDisplayRevokeButton() const {
609 return !retained_files_.empty() || !retained_device_messages_.empty();
610}
611
gpdavis.chromium0fbac4d2014-09-19 20:57:54612ExtensionInstallPrompt::Prompt::InstallPromptPermissions&
613ExtensionInstallPrompt::Prompt::GetPermissionsForType(
614 PermissionsType permissions_type) {
615 DCHECK_NE(ALL_PERMISSIONS, permissions_type);
616 return permissions_type == REGULAR_PERMISSIONS ? prompt_permissions_
617 : withheld_prompt_permissions_;
618}
619
620const ExtensionInstallPrompt::Prompt::InstallPromptPermissions&
621ExtensionInstallPrompt::Prompt::GetPermissionsForType(
622 PermissionsType permissions_type) const {
623 DCHECK_NE(ALL_PERMISSIONS, permissions_type);
624 return permissions_type == REGULAR_PERMISSIONS ? prompt_permissions_
625 : withheld_prompt_permissions_;
626}
627
[email protected]a2886e8b2013-06-08 05:15:02628bool ExtensionInstallPrompt::Prompt::ShouldDisplayRevokeFilesButton() const {
629 return !retained_files_.empty();
630}
631
[email protected]c82da8c42012-06-08 19:49:11632// static
633scoped_refptr<Extension>
634 ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
[email protected]023b3d12013-12-23 18:46:49635 const base::DictionaryValue* manifest,
[email protected]c422a862012-07-31 15:46:13636 int flags,
[email protected]c82da8c42012-06-08 19:49:11637 const std::string& id,
638 const std::string& localized_name,
639 const std::string& localized_description,
640 std::string* error) {
[email protected]023b3d12013-12-23 18:46:49641 scoped_ptr<base::DictionaryValue> localized_manifest;
[email protected]c82da8c42012-06-08 19:49:11642 if (!localized_name.empty() || !localized_description.empty()) {
643 localized_manifest.reset(manifest->DeepCopy());
644 if (!localized_name.empty()) {
[email protected]6bf90612013-08-15 00:36:27645 localized_manifest->SetString(extensions::manifest_keys::kName,
[email protected]c82da8c42012-06-08 19:49:11646 localized_name);
647 }
648 if (!localized_description.empty()) {
[email protected]6bf90612013-08-15 00:36:27649 localized_manifest->SetString(extensions::manifest_keys::kDescription,
[email protected]c82da8c42012-06-08 19:49:11650 localized_description);
651 }
652 }
653
654 return Extension::Create(
[email protected]650b2d52013-02-10 03:41:45655 base::FilePath(),
[email protected]1d5e58b2013-01-31 08:41:40656 Manifest::INTERNAL,
[email protected]c82da8c42012-06-08 19:49:11657 localized_manifest.get() ? *localized_manifest.get() : *manifest,
[email protected]c422a862012-07-31 15:46:13658 flags,
[email protected]c82da8c42012-06-08 19:49:11659 id,
660 error);
661}
662
[email protected]7f165342014-02-12 09:22:22663ExtensionInstallPrompt::ExtensionInstallPrompt(content::WebContents* contents)
pkotwicza57a1f322014-10-21 00:24:30664 : profile_(ProfileForWebContents(contents)),
665 ui_loop_(base::MessageLoop::current()),
[email protected]c82da8c42012-06-08 19:49:11666 extension_(NULL),
[email protected]7f165342014-02-12 09:22:22667 bundle_(NULL),
pkotwicza57a1f322014-10-21 00:24:30668 install_ui_(extensions::CreateExtensionInstallUI(
669 ProfileForWebContents(contents))),
pkotwicz2f181782014-10-29 17:33:45670 show_params_(new ExtensionInstallPromptShowParams(contents)),
[email protected]d382baa2014-06-17 18:50:01671 delegate_(NULL) {
672}
[email protected]5db2e882012-12-20 10:17:26673
pkotwicz2175c622014-10-22 19:56:28674ExtensionInstallPrompt::ExtensionInstallPrompt(Profile* profile,
675 gfx::NativeWindow native_window)
pkotwicza57a1f322014-10-21 00:24:30676 : profile_(profile),
677 ui_loop_(base::MessageLoop::current()),
[email protected]5db2e882012-12-20 10:17:26678 extension_(NULL),
[email protected]7f165342014-02-12 09:22:22679 bundle_(NULL),
pkotwicza57a1f322014-10-21 00:24:30680 install_ui_(extensions::CreateExtensionInstallUI(profile)),
pkotwicz2f181782014-10-29 17:33:45681 show_params_(
682 new ExtensionInstallPromptShowParams(profile, native_window)),
[email protected]d382baa2014-06-17 18:50:01683 delegate_(NULL) {
684}
[email protected]c82da8c42012-06-08 19:49:11685
686ExtensionInstallPrompt::~ExtensionInstallPrompt() {
687}
688
689void ExtensionInstallPrompt::ConfirmBundleInstall(
690 extensions::BundleInstaller* bundle,
[email protected]c2e66e12012-06-27 06:27:06691 const PermissionSet* permissions) {
[email protected]b3a25092013-05-28 22:08:16692 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11693 bundle_ = bundle;
gpdavis.chromium0fbac4d2014-09-19 20:57:54694 custom_permissions_ = permissions;
[email protected]c82da8c42012-06-08 19:49:11695 delegate_ = bundle;
[email protected]d382baa2014-06-17 18:50:01696 prompt_ = new Prompt(BUNDLE_INSTALL_PROMPT);
[email protected]c82da8c42012-06-08 19:49:11697
[email protected]4e494872013-09-06 09:13:54698 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11699}
700
[email protected]734bcec2012-10-08 20:29:05701void ExtensionInstallPrompt::ConfirmStandaloneInstall(
[email protected]c82da8c42012-06-08 19:49:11702 Delegate* delegate,
703 const Extension* extension,
704 SkBitmap* icon,
[email protected]d382baa2014-06-17 18:50:01705 scoped_refptr<Prompt> prompt) {
[email protected]b3a25092013-05-28 22:08:16706 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11707 extension_ = extension;
[email protected]c82da8c42012-06-08 19:49:11708 delegate_ = delegate;
709 prompt_ = prompt;
[email protected]c82da8c42012-06-08 19:49:11710
711 SetIcon(icon);
[email protected]4e494872013-09-06 09:13:54712 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11713}
714
[email protected]af6efb22012-10-12 02:23:05715void ExtensionInstallPrompt::ConfirmWebstoreInstall(
716 Delegate* delegate,
717 const Extension* extension,
718 const SkBitmap* icon,
719 const ShowDialogCallback& show_dialog_callback) {
[email protected]c82da8c42012-06-08 19:49:11720 // SetIcon requires |extension_| to be set. ConfirmInstall will setup the
721 // remaining fields.
722 extension_ = extension;
723 SetIcon(icon);
[email protected]af6efb22012-10-12 02:23:05724 ConfirmInstall(delegate, extension, show_dialog_callback);
[email protected]c82da8c42012-06-08 19:49:11725}
726
[email protected]af6efb22012-10-12 02:23:05727void ExtensionInstallPrompt::ConfirmInstall(
728 Delegate* delegate,
729 const Extension* extension,
730 const ShowDialogCallback& show_dialog_callback) {
[email protected]b3a25092013-05-28 22:08:16731 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11732 extension_ = extension;
[email protected]c82da8c42012-06-08 19:49:11733 delegate_ = delegate;
[email protected]d382baa2014-06-17 18:50:01734 prompt_ = new Prompt(INSTALL_PROMPT);
[email protected]af6efb22012-10-12 02:23:05735 show_dialog_callback_ = show_dialog_callback;
[email protected]c82da8c42012-06-08 19:49:11736
737 // We special-case themes to not show any confirm UI. Instead they are
738 // immediately installed, and then we show an infobar (see OnInstallSuccess)
739 // to allow the user to revert if they don't like it.
740 //
741 // We don't do this in the case where off-store extension installs are
742 // disabled because in that case, we don't show the dangerous download UI, so
743 // we need the UI confirmation.
744 if (extension->is_theme()) {
745 if (extension->from_webstore() ||
[email protected]544471a2012-10-13 05:27:09746 extensions::FeatureSwitch::easy_off_store_install()->IsEnabled()) {
[email protected]c82da8c42012-06-08 19:49:11747 delegate->InstallUIProceed();
748 return;
749 }
750 }
751
752 LoadImageIfNeeded();
753}
754
755void ExtensionInstallPrompt::ConfirmReEnable(Delegate* delegate,
756 const Extension* extension) {
[email protected]b3a25092013-05-28 22:08:16757 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11758 extension_ = extension;
[email protected]c82da8c42012-06-08 19:49:11759 delegate_ = delegate;
[email protected]21db9ef2014-05-16 02:06:27760 bool is_remote_install =
pkotwicza57a1f322014-10-21 00:24:30761 profile_ &&
762 extensions::ExtensionPrefs::Get(profile_)->HasDisableReason(
[email protected]21db9ef2014-05-16 02:06:27763 extension->id(), extensions::Extension::DISABLE_REMOTE_INSTALL);
[email protected]411f8ae2014-05-22 11:12:23764 bool is_ephemeral =
pkotwicza57a1f322014-10-21 00:24:30765 extensions::util::IsEphemeralApp(extension->id(), profile_);
[email protected]d382baa2014-06-17 18:50:01766
767 PromptType type = UNSET_PROMPT_TYPE;
[email protected]411f8ae2014-05-22 11:12:23768 if (is_ephemeral)
[email protected]d382baa2014-06-17 18:50:01769 type = LAUNCH_PROMPT;
[email protected]21db9ef2014-05-16 02:06:27770 else if (is_remote_install)
[email protected]d382baa2014-06-17 18:50:01771 type = REMOTE_INSTALL_PROMPT;
[email protected]21db9ef2014-05-16 02:06:27772 else
[email protected]d382baa2014-06-17 18:50:01773 type = RE_ENABLE_PROMPT;
774 prompt_ = new Prompt(type);
775
[email protected]c82da8c42012-06-08 19:49:11776 LoadImageIfNeeded();
777}
778
[email protected]612a1cb12012-10-17 13:18:03779void ExtensionInstallPrompt::ConfirmExternalInstall(
[email protected]c8ff7c9e2013-04-20 12:36:27780 Delegate* delegate,
781 const Extension* extension,
[email protected]34b5f7f2014-01-29 02:48:11782 const ShowDialogCallback& show_dialog_callback,
[email protected]d382baa2014-06-17 18:50:01783 scoped_refptr<Prompt> prompt) {
[email protected]b3a25092013-05-28 22:08:16784 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]612a1cb12012-10-17 13:18:03785 extension_ = extension;
[email protected]612a1cb12012-10-17 13:18:03786 delegate_ = delegate;
[email protected]34b5f7f2014-01-29 02:48:11787 prompt_ = prompt;
[email protected]c8ff7c9e2013-04-20 12:36:27788 show_dialog_callback_ = show_dialog_callback;
[email protected]612a1cb12012-10-17 13:18:03789
790 LoadImageIfNeeded();
791}
792
[email protected]c82da8c42012-06-08 19:49:11793void ExtensionInstallPrompt::ConfirmPermissions(
794 Delegate* delegate,
795 const Extension* extension,
[email protected]c2e66e12012-06-27 06:27:06796 const PermissionSet* permissions) {
[email protected]b3a25092013-05-28 22:08:16797 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11798 extension_ = extension;
gpdavis.chromium0fbac4d2014-09-19 20:57:54799 custom_permissions_ = permissions;
[email protected]c82da8c42012-06-08 19:49:11800 delegate_ = delegate;
[email protected]d382baa2014-06-17 18:50:01801 prompt_ = new Prompt(PERMISSIONS_PROMPT);
[email protected]c82da8c42012-06-08 19:49:11802
803 LoadImageIfNeeded();
804}
805
[email protected]a2886e8b2013-06-08 05:15:02806void ExtensionInstallPrompt::ReviewPermissions(
807 Delegate* delegate,
808 const Extension* extension,
reillygc64d3dd2014-09-29 21:10:11809 const std::vector<base::FilePath>& retained_file_paths,
810 const std::vector<base::string16>& retained_device_messages) {
[email protected]b3a25092013-05-28 22:08:16811 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]15d267b42013-02-14 23:43:32812 extension_ = extension;
[email protected]d382baa2014-06-17 18:50:01813 prompt_ = new Prompt(POST_INSTALL_PERMISSIONS_PROMPT);
814 prompt_->set_retained_files(retained_file_paths);
reillygc64d3dd2014-09-29 21:10:11815 prompt_->set_retained_device_messages(retained_device_messages);
[email protected]15d267b42013-02-14 23:43:32816 delegate_ = delegate;
[email protected]15d267b42013-02-14 23:43:32817
818 LoadImageIfNeeded();
819}
820
[email protected]c82da8c42012-06-08 19:49:11821void ExtensionInstallPrompt::OnInstallSuccess(const Extension* extension,
822 SkBitmap* icon) {
823 extension_ = extension;
824 SetIcon(icon);
825
826 install_ui_->OnInstallSuccess(extension, &icon_);
827}
828
[email protected]bf3d9df2012-07-24 23:20:27829void ExtensionInstallPrompt::OnInstallFailure(
ginkage47e603e2015-02-27 08:42:41830 const extensions::CrxInstallError& error) {
[email protected]c82da8c42012-06-08 19:49:11831 install_ui_->OnInstallFailure(error);
832}
833
834void ExtensionInstallPrompt::SetIcon(const SkBitmap* image) {
835 if (image)
836 icon_ = *image;
837 else
838 icon_ = SkBitmap();
[email protected]dd46a4ce2012-09-15 10:50:50839 if (icon_.empty()) {
840 // Let's set default icon bitmap whose size is equal to the default icon's
841 // pixel size under maximal supported scale factor. If the bitmap is larger
842 // than the one we need, it will be scaled down by the ui code.
843 icon_ = GetDefaultIconBitmapForMaxScaleFactor(extension_->is_app());
844 }
[email protected]c82da8c42012-06-08 19:49:11845}
846
[email protected]ec7de0c5a2012-11-16 07:40:47847void ExtensionInstallPrompt::OnImageLoaded(const gfx::Image& image) {
[email protected]c82da8c42012-06-08 19:49:11848 SetIcon(image.IsEmpty() ? NULL : image.ToSkBitmap());
[email protected]4e494872013-09-06 09:13:54849 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11850}
851
852void ExtensionInstallPrompt::LoadImageIfNeeded() {
853 // Bundle install prompts do not have an icon.
pkotwicza57a1f322014-10-21 00:24:30854 // Also |profile_| can be NULL in unit tests.
855 if (!icon_.empty() || !profile_) {
[email protected]4e494872013-09-06 09:13:54856 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11857 return;
858 }
859
[email protected]993da5e2013-03-23 21:25:16860 extensions::ExtensionResource image = extensions::IconsInfo::GetIconResource(
[email protected]702d8b42013-02-27 20:55:50861 extension_,
862 extension_misc::EXTENSION_ICON_LARGE,
863 ExtensionIconSet::MATCH_BIGGER);
[email protected]0d0ba182014-06-03 12:40:43864
865 // Load the image asynchronously. The response will be sent to OnImageLoaded.
pkotwicza57a1f322014-10-21 00:24:30866 extensions::ImageLoader* loader = extensions::ImageLoader::Get(profile_);
[email protected]0d0ba182014-06-03 12:40:43867
868 std::vector<extensions::ImageLoader::ImageRepresentation> images_list;
869 images_list.push_back(extensions::ImageLoader::ImageRepresentation(
870 image,
871 extensions::ImageLoader::ImageRepresentation::NEVER_RESIZE,
872 gfx::Size(),
873 ui::SCALE_FACTOR_100P));
874 loader->LoadImagesAsync(
875 extension_,
876 images_list,
[email protected]ec7de0c5a2012-11-16 07:40:47877 base::Bind(&ExtensionInstallPrompt::OnImageLoaded, AsWeakPtr()));
[email protected]c82da8c42012-06-08 19:49:11878}
879
880void ExtensionInstallPrompt::ShowConfirmation() {
[email protected]d382baa2014-06-17 18:50:01881 if (prompt_->type() == INSTALL_PROMPT)
882 prompt_->set_experiment(ExtensionInstallPromptExperiment::Find());
[email protected]62a28d7c2013-12-28 01:34:49883 else
[email protected]d382baa2014-06-17 18:50:01884 prompt_->set_experiment(ExtensionInstallPromptExperiment::ControlGroup());
[email protected]62a28d7c2013-12-28 01:34:49885
gpdavis.chromium0fbac4d2014-09-19 20:57:54886 scoped_refptr<const PermissionSet> permissions_to_display;
887 if (custom_permissions_.get()) {
888 permissions_to_display = custom_permissions_;
889 } else if (extension_) {
890 // Initialize permissions if they have not already been set so that
891 // withheld permissions are displayed properly in the install prompt.
892 extensions::PermissionsUpdater(
pkotwicza57a1f322014-10-21 00:24:30893 profile_, extensions::PermissionsUpdater::INIT_FLAG_TRANSIENT)
gpdavis.chromium0fbac4d2014-09-19 20:57:54894 .InitializePermissions(extension_);
895 permissions_to_display =
896 extension_->permissions_data()->active_permissions();
897 }
898
899 if (permissions_to_display.get() &&
[email protected]a397ec02014-08-08 15:48:13900 (!extension_ ||
901 !extensions::PermissionsData::ShouldSkipPermissionWarnings(
902 extension_->id()))) {
903 Manifest::Type type =
904 extension_ ? extension_->GetType() : Manifest::TYPE_UNKNOWN;
905 const extensions::PermissionMessageProvider* message_provider =
906 extensions::PermissionMessageProvider::Get();
gpdavis.chromium0fbac4d2014-09-19 20:57:54907 prompt_->SetPermissions(message_provider->GetWarningMessages(
908 permissions_to_display.get(), type),
909 REGULAR_PERMISSIONS);
910 prompt_->SetPermissionsDetails(message_provider->GetWarningMessagesDetails(
911 permissions_to_display.get(), type),
912 REGULAR_PERMISSIONS);
913
914 scoped_refptr<const extensions::PermissionSet> withheld =
915 extension_->permissions_data()->withheld_permissions();
916 if (!withheld->IsEmpty()) {
917 prompt_->SetPermissions(
918 message_provider->GetWarningMessages(withheld.get(), type),
919 PermissionsType::WITHHELD_PERMISSIONS);
920 prompt_->SetPermissionsDetails(
921 message_provider->GetWarningMessagesDetails(withheld.get(), type),
922 PermissionsType::WITHHELD_PERMISSIONS);
923 }
[email protected]bebe1d02012-08-02 20:17:09924 }
[email protected]c82da8c42012-06-08 19:49:11925
[email protected]d382baa2014-06-17 18:50:01926 switch (prompt_->type()) {
[email protected]c82da8c42012-06-08 19:49:11927 case PERMISSIONS_PROMPT:
928 case RE_ENABLE_PROMPT:
929 case INLINE_INSTALL_PROMPT:
[email protected]612a1cb12012-10-17 13:18:03930 case EXTERNAL_INSTALL_PROMPT:
[email protected]15d267b42013-02-14 23:43:32931 case INSTALL_PROMPT:
[email protected]1a93d8d2013-10-27 23:09:20932 case LAUNCH_PROMPT:
[email protected]21db9ef2014-05-16 02:06:27933 case POST_INSTALL_PERMISSIONS_PROMPT:
rdevlin.cronin5f6b69d2014-09-20 01:23:35934 case REMOTE_INSTALL_PROMPT:
935 case REPAIR_PROMPT: {
[email protected]d382baa2014-06-17 18:50:01936 prompt_->set_extension(extension_);
937 prompt_->set_icon(gfx::Image::CreateFrom1xBitmap(icon_));
[email protected]c82da8c42012-06-08 19:49:11938 break;
939 }
940 case BUNDLE_INSTALL_PROMPT: {
[email protected]d382baa2014-06-17 18:50:01941 prompt_->set_bundle(bundle_);
[email protected]c82da8c42012-06-08 19:49:11942 break;
943 }
944 default:
945 NOTREACHED() << "Unknown message";
[email protected]af6efb22012-10-12 02:23:05946 return;
[email protected]c82da8c42012-06-08 19:49:11947 }
[email protected]af6efb22012-10-12 02:23:05948
rdevlin.cronin092c6772014-11-20 23:52:40949 g_last_prompt_type_for_tests = prompt_->type();
950
[email protected]af6efb22012-10-12 02:23:05951 if (AutoConfirmPrompt(delegate_))
952 return;
953
pkotwicz2f181782014-10-29 17:33:45954 if (show_params_->WasParentDestroyed()) {
955 delegate_->InstallUIAbort(false);
956 return;
957 }
958
[email protected]5db2e882012-12-20 10:17:26959 if (show_dialog_callback_.is_null())
pkotwicz2f181782014-10-29 17:33:45960 GetDefaultShowDialogCallback().Run(show_params_.get(), delegate_, prompt_);
[email protected]5db2e882012-12-20 10:17:26961 else
pkotwicz2f181782014-10-29 17:33:45962 show_dialog_callback_.Run(show_params_.get(), delegate_, prompt_);
[email protected]c82da8c42012-06-08 19:49:11963}