blob: 0af21940338ff4a6ee58dd25248b0c960ba20dba [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"
[email protected]00e7bef2013-06-10 20:35:1713#include "base/strings/string_util.h"
14#include "base/strings/stringprintf.h"
[email protected]112158af2013-06-07 23:46:1815#include "base/strings/utf_string_conversions.h"
[email protected]c82da8c42012-06-08 19:49:1116#include "chrome/browser/extensions/bundle_installer.h"
[email protected]c82da8c42012-06-08 19:49:1117#include "chrome/browser/extensions/extension_install_ui.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"
[email protected]c82da8c42012-06-08 19:49:1121#include "chrome/common/chrome_switches.h"
[email protected]fc5077942012-08-15 21:37:5922#include "chrome/common/pref_names.h"
[email protected]af39f002014-08-22 10:18:1823#include "chrome/grit/chromium_strings.h"
24#include "chrome/grit/generated_resources.h"
[email protected]91e51d612012-10-21 23:03:0525#include "content/public/browser/web_contents.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"
[email protected]cda103d2014-04-04 16:22:3929#include "extensions/common/constants.h"
[email protected]e4452d32013-11-15 23:07:4130#include "extensions/common/extension.h"
[email protected]4b7908842014-04-07 23:50:2231#include "extensions/common/extension_icon_set.h"
[email protected]993da5e2013-03-23 21:25:1632#include "extensions/common/extension_resource.h"
[email protected]5ef835a2013-11-08 20:42:5733#include "extensions/common/feature_switch.h"
[email protected]d42c11152013-08-22 19:36:3234#include "extensions/common/manifest.h"
[email protected]6bf90612013-08-15 00:36:2735#include "extensions/common/manifest_constants.h"
[email protected]0db486f2014-04-09 19:32:2236#include "extensions/common/manifest_handlers/icons_handler.h"
[email protected]c41003472013-10-19 15:37:2537#include "extensions/common/permissions/permission_message_provider.h"
[email protected]5a55f3f2013-10-29 01:08:2938#include "extensions/common/permissions/permission_set.h"
[email protected]e4452d32013-11-15 23:07:4139#include "extensions/common/permissions/permissions_data.h"
[email protected]885c0e92012-11-13 20:27:4240#include "extensions/common/url_pattern.h"
[email protected]2a281332012-07-11 22:20:2341#include "grit/theme_resources.h"
[email protected]c82da8c42012-06-08 19:49:1142#include "ui/base/l10n/l10n_util.h"
43#include "ui/base/resource/resource_bundle.h"
pkotwicz7fd01192014-10-09 04:43:5044#include "ui/base/ui_base_types.h"
[email protected]c82da8c42012-06-08 19:49:1145#include "ui/gfx/image/image.h"
46
[email protected]c82da8c42012-06-08 19:49:1147using extensions::BundleInstaller;
48using extensions::Extension;
[email protected]1d5e58b2013-01-31 08:41:4049using extensions::Manifest;
[email protected]c2e66e12012-06-27 06:27:0650using extensions::PermissionSet;
[email protected]c82da8c42012-06-08 19:49:1151
[email protected]612a1cb12012-10-17 13:18:0352namespace {
53
rdevlin.cronin5f6b69d2014-09-20 01:23:3554bool AllowWebstoreData(ExtensionInstallPrompt::PromptType type) {
55 return type == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT ||
56 type == ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT ||
57 type == ExtensionInstallPrompt::REPAIR_PROMPT;
58}
59
[email protected]c82da8c42012-06-08 19:49:1160static const int kTitleIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2761 0, // The regular install prompt depends on what's being installed.
62 IDS_EXTENSION_INLINE_INSTALL_PROMPT_TITLE,
63 IDS_EXTENSION_INSTALL_PROMPT_TITLE,
64 IDS_EXTENSION_RE_ENABLE_PROMPT_TITLE,
65 IDS_EXTENSION_PERMISSIONS_PROMPT_TITLE,
66 IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_TITLE,
67 IDS_EXTENSION_POST_INSTALL_PERMISSIONS_PROMPT_TITLE,
68 IDS_EXTENSION_LAUNCH_APP_PROMPT_TITLE,
69 0, // The remote install prompt depends on what's being installed.
rdevlin.cronin5f6b69d2014-09-20 01:23:3570 0, // The repair install prompt depends on what's being installed.
[email protected]c82da8c42012-06-08 19:49:1171};
72static const int kHeadingIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2773 IDS_EXTENSION_INSTALL_PROMPT_HEADING,
74 0, // Inline installs use the extension name.
75 0, // Heading for bundle installs depends on the bundle contents.
76 IDS_EXTENSION_RE_ENABLE_PROMPT_HEADING,
77 IDS_EXTENSION_PERMISSIONS_PROMPT_HEADING,
78 0, // External installs use different strings for extensions/apps.
79 IDS_EXTENSION_POST_INSTALL_PERMISSIONS_PROMPT_HEADING,
80 IDS_EXTENSION_LAUNCH_APP_PROMPT_HEADING,
81 IDS_EXTENSION_REMOTE_INSTALL_PROMPT_HEADING,
rdevlin.cronin5f6b69d2014-09-20 01:23:3582 IDS_EXTENSION_REPAIR_PROMPT_HEADING
[email protected]15d267b42013-02-14 23:43:3283};
84static const int kButtons[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2785 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
86 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
87 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_CANCEL,
92 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
93 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
rdevlin.cronin5f6b69d2014-09-20 01:23:3594 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
[email protected]c82da8c42012-06-08 19:49:1195};
96static const int kAcceptButtonIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2797 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
98 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
99 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
100 IDS_EXTENSION_PROMPT_RE_ENABLE_BUTTON,
101 IDS_EXTENSION_PROMPT_PERMISSIONS_BUTTON,
102 0, // External installs use different strings for extensions/apps.
reillygc64d3dd2014-09-29 21:10:11103 0, // Different strings depending on the files and devices retained.
[email protected]21db9ef2014-05-16 02:06:27104 IDS_EXTENSION_PROMPT_LAUNCH_BUTTON,
105 IDS_EXTENSION_PROMPT_REMOTE_INSTALL_BUTTON,
rdevlin.cronin5f6b69d2014-09-20 01:23:35106 IDS_EXTENSION_PROMPT_REPAIR_BUTTON,
[email protected]c82da8c42012-06-08 19:49:11107};
108static const int kAbortButtonIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:27109 0, // These all use the platform's default cancel label.
110 0,
111 0,
112 0,
113 IDS_EXTENSION_PROMPT_PERMISSIONS_ABORT_BUTTON,
114 IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ABORT_BUTTON,
115 IDS_CLOSE,
116 0, // Platform dependent cancel button.
117 0,
rdevlin.cronin5f6b69d2014-09-20 01:23:35118 0,
[email protected]c82da8c42012-06-08 19:49:11119};
[email protected]21db9ef2014-05-16 02:06:27120static const int
121 kPermissionsHeaderIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
122 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
123 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
124 IDS_EXTENSION_PROMPT_THESE_WILL_HAVE_ACCESS_TO,
125 IDS_EXTENSION_PROMPT_WILL_NOW_HAVE_ACCESS_TO,
126 IDS_EXTENSION_PROMPT_WANTS_ACCESS_TO,
127 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
128 IDS_EXTENSION_PROMPT_CAN_ACCESS,
129 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
130 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
rdevlin.cronin5f6b69d2014-09-20 01:23:35131 IDS_EXTENSION_PROMPT_CAN_ACCESS,
[email protected]c82da8c42012-06-08 19:49:11132};
[email protected]c82da8c42012-06-08 19:49:11133
[email protected]dd46a4ce2012-09-15 10:50:50134// Returns bitmap for the default icon with size equal to the default icon's
135// pixel size under maximal supported scale factor.
136SkBitmap GetDefaultIconBitmapForMaxScaleFactor(bool is_app) {
[email protected]702d8b42013-02-27 20:55:50137 const gfx::ImageSkia& image = is_app ?
[email protected]7eb20e32014-04-30 08:50:56138 extensions::util::GetDefaultAppIcon() :
139 extensions::util::GetDefaultExtensionIcon();
[email protected]50b66262013-09-24 03:25:48140 return image.GetRepresentation(
141 gfx::ImageSkia::GetMaxSupportedScale()).sk_bitmap();
[email protected]dd46a4ce2012-09-15 10:50:50142}
143
[email protected]af6efb22012-10-12 02:23:05144// If auto confirm is enabled then posts a task to proceed with or cancel the
145// install and returns true. Otherwise returns false.
146bool AutoConfirmPrompt(ExtensionInstallPrompt::Delegate* delegate) {
[email protected]2a74d6f62014-07-24 11:53:47147 switch (ExtensionInstallPrompt::g_auto_confirm_for_tests) {
148 case ExtensionInstallPrompt::NONE:
149 return false;
150 // We use PostTask instead of calling the delegate directly here, because in
151 // the real implementations it's highly likely the message loop will be
152 // pumping a few times before the user clicks accept or cancel.
153 case ExtensionInstallPrompt::ACCEPT:
154 base::MessageLoop::current()->PostTask(
155 FROM_HERE,
156 base::Bind(&ExtensionInstallPrompt::Delegate::InstallUIProceed,
157 base::Unretained(delegate)));
158 return true;
159 case ExtensionInstallPrompt::CANCEL:
160 base::MessageLoop::current()->PostTask(
161 FROM_HERE,
162 base::Bind(&ExtensionInstallPrompt::Delegate::InstallUIAbort,
163 base::Unretained(delegate),
164 true));
165 return true;
[email protected]af6efb22012-10-12 02:23:05166 }
167
168 NOTREACHED();
169 return false;
170}
171
[email protected]91e51d612012-10-21 23:03:05172Profile* ProfileForWebContents(content::WebContents* web_contents) {
173 if (!web_contents)
174 return NULL;
175 return Profile::FromBrowserContext(web_contents->GetBrowserContext());
176}
177
[email protected]5db2e882012-12-20 10:17:26178gfx::NativeWindow NativeWindowForWebContents(content::WebContents* contents) {
179 if (!contents)
180 return NULL;
181
[email protected]fc2b46b2014-05-03 16:33:45182 return contents->GetTopLevelNativeWindow();
[email protected]5db2e882012-12-20 10:17:26183}
184
[email protected]c82da8c42012-06-08 19:49:11185} // namespace
186
gpdavis.chromium0fbac4d2014-09-19 20:57:54187ExtensionInstallPrompt::Prompt::InstallPromptPermissions::
188 InstallPromptPermissions() {
189}
190ExtensionInstallPrompt::Prompt::InstallPromptPermissions::
191 ~InstallPromptPermissions() {
192}
193
[email protected]2a74d6f62014-07-24 11:53:47194// static
195ExtensionInstallPrompt::AutoConfirmForTests
196ExtensionInstallPrompt::g_auto_confirm_for_tests = ExtensionInstallPrompt::NONE;
197
[email protected]eeb0d3e12014-08-15 15:10:44198// This should match the PromptType enum.
199std::string ExtensionInstallPrompt::PromptTypeToString(PromptType type) {
200 switch (type) {
201 case ExtensionInstallPrompt::INSTALL_PROMPT:
202 return "INSTALL_PROMPT";
203 case ExtensionInstallPrompt::INLINE_INSTALL_PROMPT:
204 return "INLINE_INSTALL_PROMPT";
205 case ExtensionInstallPrompt::BUNDLE_INSTALL_PROMPT:
206 return "BUNDLE_INSTALL_PROMPT";
207 case ExtensionInstallPrompt::RE_ENABLE_PROMPT:
208 return "RE_ENABLE_PROMPT";
209 case ExtensionInstallPrompt::PERMISSIONS_PROMPT:
210 return "PERMISSIONS_PROMPT";
211 case ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT:
212 return "EXTERNAL_INSTALL_PROMPT";
213 case ExtensionInstallPrompt::POST_INSTALL_PERMISSIONS_PROMPT:
214 return "POST_INSTALL_PERMISSIONS_PROMPT";
215 case ExtensionInstallPrompt::LAUNCH_PROMPT:
216 return "LAUNCH_PROMPT";
217 case ExtensionInstallPrompt::REMOTE_INSTALL_PROMPT:
218 return "REMOTE_INSTALL_PROMPT";
rdevlin.cronin5f6b69d2014-09-20 01:23:35219 case ExtensionInstallPrompt::REPAIR_PROMPT:
220 return "REPAIR_PROMPT";
[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(
gpdavis.chromium0fbac4d2014-09-19 20:57:54244 const std::vector<base::string16>& permissions,
245 PermissionsType permissions_type) {
246 GetPermissionsForType(permissions_type).permissions = permissions;
[email protected]c82da8c42012-06-08 19:49:11247}
248
[email protected]8ab7e6c2013-07-11 21:15:03249void ExtensionInstallPrompt::Prompt::SetPermissionsDetails(
gpdavis.chromium0fbac4d2014-09-19 20:57:54250 const std::vector<base::string16>& details,
251 PermissionsType permissions_type) {
252 InstallPromptPermissions& install_permissions =
253 GetPermissionsForType(permissions_type);
254 install_permissions.details = details;
255 install_permissions.is_showing_details.clear();
256 install_permissions.is_showing_details.insert(
257 install_permissions.is_showing_details.begin(), details.size(), false);
[email protected]79a6f99a2013-08-29 00:32:58258}
259
260void ExtensionInstallPrompt::Prompt::SetIsShowingDetails(
261 DetailsType type,
262 size_t index,
263 bool is_showing_details) {
264 switch (type) {
265 case PERMISSIONS_DETAILS:
gpdavis.chromium0fbac4d2014-09-19 20:57:54266 prompt_permissions_.is_showing_details[index] = is_showing_details;
267 break;
268 case WITHHELD_PERMISSIONS_DETAILS:
269 withheld_prompt_permissions_.is_showing_details[index] =
270 is_showing_details;
[email protected]79a6f99a2013-08-29 00:32:58271 break;
[email protected]79a6f99a2013-08-29 00:32:58272 case RETAINED_FILES_DETAILS:
273 is_showing_details_for_retained_files_ = is_showing_details;
274 break;
reillygc64d3dd2014-09-29 21:10:11275 case RETAINED_DEVICES_DETAILS:
276 is_showing_details_for_retained_devices_ = is_showing_details;
277 break;
[email protected]79a6f99a2013-08-29 00:32:58278 }
[email protected]8ab7e6c2013-07-11 21:15:03279}
280
[email protected]34b5f7f2014-01-29 02:48:11281void ExtensionInstallPrompt::Prompt::SetWebstoreData(
[email protected]c82da8c42012-06-08 19:49:11282 const std::string& localized_user_count,
[email protected]dcde34b32013-07-31 02:28:45283 bool show_user_count,
[email protected]c82da8c42012-06-08 19:49:11284 double average_rating,
285 int rating_count) {
rdevlin.cronin5f6b69d2014-09-20 01:23:35286 CHECK(AllowWebstoreData(type_));
[email protected]c82da8c42012-06-08 19:49:11287 localized_user_count_ = localized_user_count;
[email protected]dcde34b32013-07-31 02:28:45288 show_user_count_ = show_user_count;
[email protected]c82da8c42012-06-08 19:49:11289 average_rating_ = average_rating;
290 rating_count_ = rating_count;
[email protected]34b5f7f2014-01-29 02:48:11291 has_webstore_data_ = true;
[email protected]c82da8c42012-06-08 19:49:11292}
293
[email protected]6a72a632013-12-12 22:22:00294base::string16 ExtensionInstallPrompt::Prompt::GetDialogTitle() const {
[email protected]c82da8c42012-06-08 19:49:11295 int resource_id = kTitleIds[type_];
296
297 if (type_ == INSTALL_PROMPT) {
298 if (extension_->is_app())
299 resource_id = IDS_EXTENSION_INSTALL_APP_PROMPT_TITLE;
300 else if (extension_->is_theme())
301 resource_id = IDS_EXTENSION_INSTALL_THEME_PROMPT_TITLE;
302 else
303 resource_id = IDS_EXTENSION_INSTALL_EXTENSION_PROMPT_TITLE;
[email protected]612a1cb12012-10-17 13:18:03304 } else if (type_ == EXTERNAL_INSTALL_PROMPT) {
305 return l10n_util::GetStringFUTF16(
[email protected]04338722013-12-24 23:18:05306 resource_id, base::UTF8ToUTF16(extension_->name()));
[email protected]21db9ef2014-05-16 02:06:27307 } else if (type_ == REMOTE_INSTALL_PROMPT) {
308 if (extension_->is_app())
309 resource_id = IDS_EXTENSION_REMOTE_INSTALL_APP_PROMPT_TITLE;
310 else
311 resource_id = IDS_EXTENSION_REMOTE_INSTALL_EXTENSION_PROMPT_TITLE;
rdevlin.cronin5f6b69d2014-09-20 01:23:35312 } else if (type_ == REPAIR_PROMPT) {
313 if (extension_->is_app())
314 resource_id = IDS_EXTENSION_REPAIR_APP_PROMPT_TITLE;
315 else
316 resource_id = IDS_EXTENSION_REPAIR_EXTENSION_PROMPT_TITLE;
[email protected]c82da8c42012-06-08 19:49:11317 }
318
319 return l10n_util::GetStringUTF16(resource_id);
320}
321
[email protected]6a72a632013-12-12 22:22:00322base::string16 ExtensionInstallPrompt::Prompt::GetHeading() const {
[email protected]c82da8c42012-06-08 19:49:11323 if (type_ == INLINE_INSTALL_PROMPT) {
[email protected]04338722013-12-24 23:18:05324 return base::UTF8ToUTF16(extension_->name());
[email protected]c82da8c42012-06-08 19:49:11325 } else if (type_ == BUNDLE_INSTALL_PROMPT) {
326 return bundle_->GetHeadingTextFor(BundleInstaller::Item::STATE_PENDING);
[email protected]612a1cb12012-10-17 13:18:03327 } else if (type_ == EXTERNAL_INSTALL_PROMPT) {
[email protected]846606012012-10-19 18:42:25328 int resource_id = -1;
329 if (extension_->is_app())
330 resource_id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_HEADING_APP;
331 else if (extension_->is_theme())
332 resource_id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_HEADING_THEME;
333 else
334 resource_id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_HEADING_EXTENSION;
335 return l10n_util::GetStringUTF16(resource_id);
[email protected]c82da8c42012-06-08 19:49:11336 } else {
337 return l10n_util::GetStringFUTF16(
[email protected]04338722013-12-24 23:18:05338 kHeadingIds[type_], base::UTF8ToUTF16(extension_->name()));
[email protected]c82da8c42012-06-08 19:49:11339 }
340}
341
[email protected]15d267b42013-02-14 23:43:32342int ExtensionInstallPrompt::Prompt::GetDialogButtons() const {
reillygc64d3dd2014-09-29 21:10:11343 if (type_ == POST_INSTALL_PERMISSIONS_PROMPT && ShouldDisplayRevokeButton()) {
[email protected]a2886e8b2013-06-08 05:15:02344 return kButtons[type_] | ui::DIALOG_BUTTON_OK;
345 }
346
[email protected]15d267b42013-02-14 23:43:32347 return kButtons[type_];
348}
349
[email protected]62a28d7c2013-12-28 01:34:49350bool ExtensionInstallPrompt::Prompt::ShouldShowExplanationText() const {
dchengc7047942014-08-26 05:05:31351 return type_ == INSTALL_PROMPT && extension_->is_extension() &&
352 experiment_.get() && experiment_->text_only();
[email protected]62a28d7c2013-12-28 01:34:49353}
354
[email protected]15d267b42013-02-14 23:43:32355bool ExtensionInstallPrompt::Prompt::HasAcceptButtonLabel() const {
reillygc64d3dd2014-09-29 21:10:11356 if (type_ == POST_INSTALL_PERMISSIONS_PROMPT)
357 return ShouldDisplayRevokeButton();
358
[email protected]a2886e8b2013-06-08 05:15:02359 if (kAcceptButtonIds[type_] == 0)
360 return false;
361
[email protected]a2886e8b2013-06-08 05:15:02362 return true;
[email protected]15d267b42013-02-14 23:43:32363}
364
[email protected]6a72a632013-12-12 22:22:00365base::string16 ExtensionInstallPrompt::Prompt::GetAcceptButtonLabel() const {
[email protected]846606012012-10-19 18:42:25366 if (type_ == EXTERNAL_INSTALL_PROMPT) {
367 int id = -1;
368 if (extension_->is_app())
369 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_APP;
370 else if (extension_->is_theme())
371 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_THEME;
372 else
373 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_EXTENSION;
374 return l10n_util::GetStringUTF16(id);
reillygc64d3dd2014-09-29 21:10:11375 } else if (type_ == POST_INSTALL_PERMISSIONS_PROMPT) {
376 int id = -1;
377 if (GetRetainedFileCount() && GetRetainedDeviceCount()) {
378 id =
379 IDS_EXTENSION_PROMPT_PERMISSIONS_CLEAR_RETAINED_FILES_AND_DEVICES_BUTTON;
380 } else if (GetRetainedFileCount()) {
381 id = IDS_EXTENSION_PROMPT_PERMISSIONS_CLEAR_RETAINED_FILES_BUTTON;
382 } else {
383 DCHECK_LT(0U, GetRetainedDeviceCount());
384 id = IDS_EXTENSION_PROMPT_PERMISSIONS_CLEAR_RETAINED_DEVICES_BUTTON;
385 }
386 return l10n_util::GetStringUTF16(id);
[email protected]846606012012-10-19 18:42:25387 }
[email protected]62a28d7c2013-12-28 01:34:49388 if (ShouldShowExplanationText())
389 return experiment_->GetOkButtonText();
[email protected]c82da8c42012-06-08 19:49:11390 return l10n_util::GetStringUTF16(kAcceptButtonIds[type_]);
391}
392
393bool ExtensionInstallPrompt::Prompt::HasAbortButtonLabel() const {
[email protected]62a28d7c2013-12-28 01:34:49394 if (ShouldShowExplanationText())
395 return true;
[email protected]c82da8c42012-06-08 19:49:11396 return kAbortButtonIds[type_] > 0;
397}
398
[email protected]6a72a632013-12-12 22:22:00399base::string16 ExtensionInstallPrompt::Prompt::GetAbortButtonLabel() const {
[email protected]c82da8c42012-06-08 19:49:11400 CHECK(HasAbortButtonLabel());
[email protected]62a28d7c2013-12-28 01:34:49401 if (ShouldShowExplanationText())
402 return experiment_->GetCancelButtonText();
[email protected]c82da8c42012-06-08 19:49:11403 return l10n_util::GetStringUTF16(kAbortButtonIds[type_]);
404}
405
gpdavis.chromium0fbac4d2014-09-19 20:57:54406base::string16 ExtensionInstallPrompt::Prompt::GetPermissionsHeading(
407 PermissionsType permissions_type) const {
408 switch (permissions_type) {
409 case REGULAR_PERMISSIONS:
410 return l10n_util::GetStringUTF16(kPermissionsHeaderIds[type_]);
411 case WITHHELD_PERMISSIONS:
412 return l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WITHHELD);
413 case ALL_PERMISSIONS:
414 default:
415 NOTREACHED();
416 return base::string16();
417 }
[email protected]c82da8c42012-06-08 19:49:11418}
419
[email protected]6a72a632013-12-12 22:22:00420base::string16 ExtensionInstallPrompt::Prompt::GetRetainedFilesHeading() const {
[email protected]4f1e1082013-09-23 10:30:53421 const int kRetainedFilesMessageIDs[6] = {
422 IDS_EXTENSION_PROMPT_RETAINED_FILES_DEFAULT,
423 IDS_EXTENSION_PROMPT_RETAINED_FILE_SINGULAR,
424 IDS_EXTENSION_PROMPT_RETAINED_FILES_ZERO,
425 IDS_EXTENSION_PROMPT_RETAINED_FILES_TWO,
426 IDS_EXTENSION_PROMPT_RETAINED_FILES_FEW,
427 IDS_EXTENSION_PROMPT_RETAINED_FILES_MANY,
428 };
reillygc64d3dd2014-09-29 21:10:11429 std::vector<int> message_ids(
430 kRetainedFilesMessageIDs,
431 kRetainedFilesMessageIDs + arraysize(kRetainedFilesMessageIDs));
432
[email protected]4f1e1082013-09-23 10:30:53433 return l10n_util::GetPluralStringFUTF16(message_ids, GetRetainedFileCount());
[email protected]8ab7e6c2013-07-11 21:15:03434}
435
reillygc64d3dd2014-09-29 21:10:11436base::string16 ExtensionInstallPrompt::Prompt::GetRetainedDevicesHeading()
437 const {
438 const int kRetainedDevicesMessageIDs[6] = {
439 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_DEFAULT,
440 IDS_EXTENSION_PROMPT_RETAINED_DEVICE_SINGULAR,
441 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_ZERO,
442 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_TWO,
443 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_FEW,
444 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_MANY,
445 };
446 std::vector<int> message_ids(
447 kRetainedDevicesMessageIDs,
448 kRetainedDevicesMessageIDs + arraysize(kRetainedDevicesMessageIDs));
449
450 return l10n_util::GetPluralStringFUTF16(message_ids,
451 GetRetainedDeviceCount());
452}
453
[email protected]f2cd8992013-06-11 17:30:18454bool ExtensionInstallPrompt::Prompt::ShouldShowPermissions() const {
gpdavis.chromium0fbac4d2014-09-19 20:57:54455 return GetPermissionCount(ALL_PERMISSIONS) > 0 ||
456 type_ == POST_INSTALL_PERMISSIONS_PROMPT;
[email protected]f2cd8992013-06-11 17:30:18457}
458
[email protected]c82da8c42012-06-08 19:49:11459void ExtensionInstallPrompt::Prompt::AppendRatingStars(
460 StarAppender appender, void* data) const {
461 CHECK(appender);
rdevlin.cronin5f6b69d2014-09-20 01:23:35462 CHECK(AllowWebstoreData(type_));
[email protected]c82da8c42012-06-08 19:49:11463 int rating_integer = floor(average_rating_);
464 double rating_fractional = average_rating_ - rating_integer;
465
466 if (rating_fractional > 0.66) {
467 rating_integer++;
468 }
469
470 if (rating_fractional < 0.33 || rating_fractional > 0.66) {
471 rating_fractional = 0;
472 }
473
474 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
475 int i;
476 for (i = 0; i < rating_integer; i++) {
477 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_ON), data);
478 }
479 if (rating_fractional) {
480 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_HALF_LEFT), data);
481 i++;
482 }
483 for (; i < kMaxExtensionRating; i++) {
484 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_OFF), data);
485 }
486}
487
[email protected]6a72a632013-12-12 22:22:00488base::string16 ExtensionInstallPrompt::Prompt::GetRatingCount() const {
rdevlin.cronin5f6b69d2014-09-20 01:23:35489 CHECK(AllowWebstoreData(type_));
[email protected]6725048e2013-10-24 21:47:14490 return l10n_util::GetStringFUTF16(IDS_EXTENSION_RATING_COUNT,
491 base::IntToString16(rating_count_));
[email protected]c82da8c42012-06-08 19:49:11492}
493
[email protected]6a72a632013-12-12 22:22:00494base::string16 ExtensionInstallPrompt::Prompt::GetUserCount() const {
rdevlin.cronin5f6b69d2014-09-20 01:23:35495 CHECK(AllowWebstoreData(type_));
[email protected]dcde34b32013-07-31 02:28:45496
497 if (show_user_count_) {
[email protected]6725048e2013-10-24 21:47:14498 return l10n_util::GetStringFUTF16(IDS_EXTENSION_USER_COUNT,
499 base::UTF8ToUTF16(localized_user_count_));
[email protected]dcde34b32013-07-31 02:28:45500 }
[email protected]6725048e2013-10-24 21:47:14501 return base::string16();
[email protected]c82da8c42012-06-08 19:49:11502}
503
gpdavis.chromium0fbac4d2014-09-19 20:57:54504size_t ExtensionInstallPrompt::Prompt::GetPermissionCount(
505 PermissionsType permissions_type) const {
506 switch (permissions_type) {
507 case REGULAR_PERMISSIONS:
508 return prompt_permissions_.permissions.size();
509 case WITHHELD_PERMISSIONS:
510 return withheld_prompt_permissions_.permissions.size();
511 case ALL_PERMISSIONS:
512 return prompt_permissions_.permissions.size() +
513 withheld_prompt_permissions_.permissions.size();
514 default:
515 NOTREACHED();
516 return 0u;
517 }
[email protected]c82da8c42012-06-08 19:49:11518}
519
gpdavis.chromium0fbac4d2014-09-19 20:57:54520size_t ExtensionInstallPrompt::Prompt::GetPermissionsDetailsCount(
521 PermissionsType permissions_type) const {
522 switch (permissions_type) {
523 case REGULAR_PERMISSIONS:
524 return prompt_permissions_.details.size();
525 case WITHHELD_PERMISSIONS:
526 return withheld_prompt_permissions_.details.size();
527 case ALL_PERMISSIONS:
528 return prompt_permissions_.details.size() +
529 withheld_prompt_permissions_.details.size();
530 default:
531 NOTREACHED();
532 return 0u;
533 }
[email protected]8ab7e6c2013-07-11 21:15:03534}
535
gpdavis.chromium0fbac4d2014-09-19 20:57:54536base::string16 ExtensionInstallPrompt::Prompt::GetPermission(
537 size_t index,
538 PermissionsType permissions_type) const {
539 const InstallPromptPermissions& install_permissions =
540 GetPermissionsForType(permissions_type);
541 CHECK_LT(index, install_permissions.permissions.size());
542 return install_permissions.permissions[index];
[email protected]c82da8c42012-06-08 19:49:11543}
544
[email protected]6a72a632013-12-12 22:22:00545base::string16 ExtensionInstallPrompt::Prompt::GetPermissionsDetails(
gpdavis.chromium0fbac4d2014-09-19 20:57:54546 size_t index,
547 PermissionsType permissions_type) const {
548 const InstallPromptPermissions& install_permissions =
549 GetPermissionsForType(permissions_type);
550 CHECK_LT(index, install_permissions.details.size());
551 return install_permissions.details[index];
[email protected]8ab7e6c2013-07-11 21:15:03552}
553
[email protected]79a6f99a2013-08-29 00:32:58554bool ExtensionInstallPrompt::Prompt::GetIsShowingDetails(
555 DetailsType type, size_t index) const {
556 switch (type) {
557 case PERMISSIONS_DETAILS:
gpdavis.chromium0fbac4d2014-09-19 20:57:54558 CHECK_LT(index, prompt_permissions_.is_showing_details.size());
559 return prompt_permissions_.is_showing_details[index];
560 case WITHHELD_PERMISSIONS_DETAILS:
561 CHECK_LT(index, withheld_prompt_permissions_.is_showing_details.size());
562 return withheld_prompt_permissions_.is_showing_details[index];
[email protected]79a6f99a2013-08-29 00:32:58563 case RETAINED_FILES_DETAILS:
564 return is_showing_details_for_retained_files_;
reillygc64d3dd2014-09-29 21:10:11565 case RETAINED_DEVICES_DETAILS:
566 return is_showing_details_for_retained_devices_;
[email protected]79a6f99a2013-08-29 00:32:58567 }
568 return false;
569}
570
[email protected]a2886e8b2013-06-08 05:15:02571size_t ExtensionInstallPrompt::Prompt::GetRetainedFileCount() const {
572 return retained_files_.size();
573}
574
[email protected]6a72a632013-12-12 22:22:00575base::string16 ExtensionInstallPrompt::Prompt::GetRetainedFile(size_t index)
576 const {
[email protected]a2886e8b2013-06-08 05:15:02577 CHECK_LT(index, retained_files_.size());
[email protected]6725048e2013-10-24 21:47:14578 return retained_files_[index].AsUTF16Unsafe();
[email protected]a2886e8b2013-06-08 05:15:02579}
580
reillygc64d3dd2014-09-29 21:10:11581size_t ExtensionInstallPrompt::Prompt::GetRetainedDeviceCount() const {
582 return retained_device_messages_.size();
583}
584
585base::string16 ExtensionInstallPrompt::Prompt::GetRetainedDeviceMessageString(
586 size_t index) const {
587 CHECK_LT(index, retained_device_messages_.size());
588 return retained_device_messages_[index];
589}
590
591bool ExtensionInstallPrompt::Prompt::ShouldDisplayRevokeButton() const {
592 return !retained_files_.empty() || !retained_device_messages_.empty();
593}
594
gpdavis.chromium0fbac4d2014-09-19 20:57:54595ExtensionInstallPrompt::Prompt::InstallPromptPermissions&
596ExtensionInstallPrompt::Prompt::GetPermissionsForType(
597 PermissionsType permissions_type) {
598 DCHECK_NE(ALL_PERMISSIONS, permissions_type);
599 return permissions_type == REGULAR_PERMISSIONS ? prompt_permissions_
600 : withheld_prompt_permissions_;
601}
602
603const ExtensionInstallPrompt::Prompt::InstallPromptPermissions&
604ExtensionInstallPrompt::Prompt::GetPermissionsForType(
605 PermissionsType permissions_type) const {
606 DCHECK_NE(ALL_PERMISSIONS, permissions_type);
607 return permissions_type == REGULAR_PERMISSIONS ? prompt_permissions_
608 : withheld_prompt_permissions_;
609}
610
[email protected]a2886e8b2013-06-08 05:15:02611bool ExtensionInstallPrompt::Prompt::ShouldDisplayRevokeFilesButton() const {
612 return !retained_files_.empty();
613}
614
[email protected]5db2e882012-12-20 10:17:26615ExtensionInstallPrompt::ShowParams::ShowParams(content::WebContents* contents)
616 : parent_web_contents(contents),
617 parent_window(NativeWindowForWebContents(contents)),
618 navigator(contents) {
619}
620
621ExtensionInstallPrompt::ShowParams::ShowParams(
622 gfx::NativeWindow window,
623 content::PageNavigator* navigator)
624 : parent_web_contents(NULL),
625 parent_window(window),
626 navigator(navigator) {
627}
628
[email protected]c82da8c42012-06-08 19:49:11629// static
630scoped_refptr<Extension>
631 ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
[email protected]023b3d12013-12-23 18:46:49632 const base::DictionaryValue* manifest,
[email protected]c422a862012-07-31 15:46:13633 int flags,
[email protected]c82da8c42012-06-08 19:49:11634 const std::string& id,
635 const std::string& localized_name,
636 const std::string& localized_description,
637 std::string* error) {
[email protected]023b3d12013-12-23 18:46:49638 scoped_ptr<base::DictionaryValue> localized_manifest;
[email protected]c82da8c42012-06-08 19:49:11639 if (!localized_name.empty() || !localized_description.empty()) {
640 localized_manifest.reset(manifest->DeepCopy());
641 if (!localized_name.empty()) {
[email protected]6bf90612013-08-15 00:36:27642 localized_manifest->SetString(extensions::manifest_keys::kName,
[email protected]c82da8c42012-06-08 19:49:11643 localized_name);
644 }
645 if (!localized_description.empty()) {
[email protected]6bf90612013-08-15 00:36:27646 localized_manifest->SetString(extensions::manifest_keys::kDescription,
[email protected]c82da8c42012-06-08 19:49:11647 localized_description);
648 }
649 }
650
651 return Extension::Create(
[email protected]650b2d52013-02-10 03:41:45652 base::FilePath(),
[email protected]1d5e58b2013-01-31 08:41:40653 Manifest::INTERNAL,
[email protected]c82da8c42012-06-08 19:49:11654 localized_manifest.get() ? *localized_manifest.get() : *manifest,
[email protected]c422a862012-07-31 15:46:13655 flags,
[email protected]c82da8c42012-06-08 19:49:11656 id,
657 error);
658}
659
[email protected]7f165342014-02-12 09:22:22660ExtensionInstallPrompt::ExtensionInstallPrompt(content::WebContents* contents)
[email protected]ae209392014-05-22 23:43:20661 : ui_loop_(base::MessageLoop::current()),
[email protected]c82da8c42012-06-08 19:49:11662 extension_(NULL),
[email protected]7f165342014-02-12 09:22:22663 bundle_(NULL),
[email protected]91e51d612012-10-21 23:03:05664 install_ui_(ExtensionInstallUI::Create(ProfileForWebContents(contents))),
[email protected]5db2e882012-12-20 10:17:26665 show_params_(contents),
[email protected]d382baa2014-06-17 18:50:01666 delegate_(NULL) {
667}
[email protected]5db2e882012-12-20 10:17:26668
669ExtensionInstallPrompt::ExtensionInstallPrompt(
670 Profile* profile,
671 gfx::NativeWindow native_window,
672 content::PageNavigator* navigator)
[email protected]ae209392014-05-22 23:43:20673 : ui_loop_(base::MessageLoop::current()),
[email protected]5db2e882012-12-20 10:17:26674 extension_(NULL),
[email protected]7f165342014-02-12 09:22:22675 bundle_(NULL),
[email protected]5db2e882012-12-20 10:17:26676 install_ui_(ExtensionInstallUI::Create(profile)),
677 show_params_(native_window, navigator),
[email protected]d382baa2014-06-17 18:50:01678 delegate_(NULL) {
679}
[email protected]c82da8c42012-06-08 19:49:11680
681ExtensionInstallPrompt::~ExtensionInstallPrompt() {
682}
683
684void ExtensionInstallPrompt::ConfirmBundleInstall(
685 extensions::BundleInstaller* bundle,
[email protected]c2e66e12012-06-27 06:27:06686 const PermissionSet* permissions) {
[email protected]b3a25092013-05-28 22:08:16687 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11688 bundle_ = bundle;
gpdavis.chromium0fbac4d2014-09-19 20:57:54689 custom_permissions_ = permissions;
[email protected]c82da8c42012-06-08 19:49:11690 delegate_ = bundle;
[email protected]d382baa2014-06-17 18:50:01691 prompt_ = new Prompt(BUNDLE_INSTALL_PROMPT);
[email protected]c82da8c42012-06-08 19:49:11692
[email protected]4e494872013-09-06 09:13:54693 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11694}
695
[email protected]734bcec2012-10-08 20:29:05696void ExtensionInstallPrompt::ConfirmStandaloneInstall(
[email protected]c82da8c42012-06-08 19:49:11697 Delegate* delegate,
698 const Extension* extension,
699 SkBitmap* icon,
[email protected]d382baa2014-06-17 18:50:01700 scoped_refptr<Prompt> prompt) {
[email protected]b3a25092013-05-28 22:08:16701 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11702 extension_ = extension;
[email protected]c82da8c42012-06-08 19:49:11703 delegate_ = delegate;
704 prompt_ = prompt;
[email protected]c82da8c42012-06-08 19:49:11705
706 SetIcon(icon);
[email protected]4e494872013-09-06 09:13:54707 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11708}
709
[email protected]af6efb22012-10-12 02:23:05710void ExtensionInstallPrompt::ConfirmWebstoreInstall(
711 Delegate* delegate,
712 const Extension* extension,
713 const SkBitmap* icon,
714 const ShowDialogCallback& show_dialog_callback) {
[email protected]c82da8c42012-06-08 19:49:11715 // SetIcon requires |extension_| to be set. ConfirmInstall will setup the
716 // remaining fields.
717 extension_ = extension;
718 SetIcon(icon);
[email protected]af6efb22012-10-12 02:23:05719 ConfirmInstall(delegate, extension, show_dialog_callback);
[email protected]c82da8c42012-06-08 19:49:11720}
721
[email protected]af6efb22012-10-12 02:23:05722void ExtensionInstallPrompt::ConfirmInstall(
723 Delegate* delegate,
724 const Extension* extension,
725 const ShowDialogCallback& show_dialog_callback) {
[email protected]b3a25092013-05-28 22:08:16726 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11727 extension_ = extension;
[email protected]c82da8c42012-06-08 19:49:11728 delegate_ = delegate;
[email protected]d382baa2014-06-17 18:50:01729 prompt_ = new Prompt(INSTALL_PROMPT);
[email protected]af6efb22012-10-12 02:23:05730 show_dialog_callback_ = show_dialog_callback;
[email protected]c82da8c42012-06-08 19:49:11731
732 // We special-case themes to not show any confirm UI. Instead they are
733 // immediately installed, and then we show an infobar (see OnInstallSuccess)
734 // to allow the user to revert if they don't like it.
735 //
736 // We don't do this in the case where off-store extension installs are
737 // disabled because in that case, we don't show the dangerous download UI, so
738 // we need the UI confirmation.
739 if (extension->is_theme()) {
740 if (extension->from_webstore() ||
[email protected]544471a2012-10-13 05:27:09741 extensions::FeatureSwitch::easy_off_store_install()->IsEnabled()) {
[email protected]c82da8c42012-06-08 19:49:11742 delegate->InstallUIProceed();
743 return;
744 }
745 }
746
747 LoadImageIfNeeded();
748}
749
750void ExtensionInstallPrompt::ConfirmReEnable(Delegate* delegate,
751 const Extension* extension) {
[email protected]b3a25092013-05-28 22:08:16752 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11753 extension_ = extension;
[email protected]c82da8c42012-06-08 19:49:11754 delegate_ = delegate;
[email protected]21db9ef2014-05-16 02:06:27755 bool is_remote_install =
756 install_ui_->profile() &&
757 extensions::ExtensionPrefs::Get(install_ui_->profile())->HasDisableReason(
758 extension->id(), extensions::Extension::DISABLE_REMOTE_INSTALL);
[email protected]411f8ae2014-05-22 11:12:23759 bool is_ephemeral =
760 extensions::util::IsEphemeralApp(extension->id(), install_ui_->profile());
[email protected]d382baa2014-06-17 18:50:01761
762 PromptType type = UNSET_PROMPT_TYPE;
[email protected]411f8ae2014-05-22 11:12:23763 if (is_ephemeral)
[email protected]d382baa2014-06-17 18:50:01764 type = LAUNCH_PROMPT;
[email protected]21db9ef2014-05-16 02:06:27765 else if (is_remote_install)
[email protected]d382baa2014-06-17 18:50:01766 type = REMOTE_INSTALL_PROMPT;
[email protected]21db9ef2014-05-16 02:06:27767 else
[email protected]d382baa2014-06-17 18:50:01768 type = RE_ENABLE_PROMPT;
769 prompt_ = new Prompt(type);
770
[email protected]c82da8c42012-06-08 19:49:11771 LoadImageIfNeeded();
772}
773
[email protected]612a1cb12012-10-17 13:18:03774void ExtensionInstallPrompt::ConfirmExternalInstall(
[email protected]c8ff7c9e2013-04-20 12:36:27775 Delegate* delegate,
776 const Extension* extension,
[email protected]34b5f7f2014-01-29 02:48:11777 const ShowDialogCallback& show_dialog_callback,
[email protected]d382baa2014-06-17 18:50:01778 scoped_refptr<Prompt> prompt) {
[email protected]b3a25092013-05-28 22:08:16779 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]612a1cb12012-10-17 13:18:03780 extension_ = extension;
[email protected]612a1cb12012-10-17 13:18:03781 delegate_ = delegate;
[email protected]34b5f7f2014-01-29 02:48:11782 prompt_ = prompt;
[email protected]c8ff7c9e2013-04-20 12:36:27783 show_dialog_callback_ = show_dialog_callback;
[email protected]612a1cb12012-10-17 13:18:03784
785 LoadImageIfNeeded();
786}
787
[email protected]c82da8c42012-06-08 19:49:11788void ExtensionInstallPrompt::ConfirmPermissions(
789 Delegate* delegate,
790 const Extension* extension,
[email protected]c2e66e12012-06-27 06:27:06791 const PermissionSet* permissions) {
[email protected]b3a25092013-05-28 22:08:16792 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11793 extension_ = extension;
gpdavis.chromium0fbac4d2014-09-19 20:57:54794 custom_permissions_ = permissions;
[email protected]c82da8c42012-06-08 19:49:11795 delegate_ = delegate;
[email protected]d382baa2014-06-17 18:50:01796 prompt_ = new Prompt(PERMISSIONS_PROMPT);
[email protected]c82da8c42012-06-08 19:49:11797
798 LoadImageIfNeeded();
799}
800
[email protected]a2886e8b2013-06-08 05:15:02801void ExtensionInstallPrompt::ReviewPermissions(
802 Delegate* delegate,
803 const Extension* extension,
reillygc64d3dd2014-09-29 21:10:11804 const std::vector<base::FilePath>& retained_file_paths,
805 const std::vector<base::string16>& retained_device_messages) {
[email protected]b3a25092013-05-28 22:08:16806 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]15d267b42013-02-14 23:43:32807 extension_ = extension;
[email protected]d382baa2014-06-17 18:50:01808 prompt_ = new Prompt(POST_INSTALL_PERMISSIONS_PROMPT);
809 prompt_->set_retained_files(retained_file_paths);
reillygc64d3dd2014-09-29 21:10:11810 prompt_->set_retained_device_messages(retained_device_messages);
[email protected]15d267b42013-02-14 23:43:32811 delegate_ = delegate;
[email protected]15d267b42013-02-14 23:43:32812
813 LoadImageIfNeeded();
814}
815
[email protected]c82da8c42012-06-08 19:49:11816void ExtensionInstallPrompt::OnInstallSuccess(const Extension* extension,
817 SkBitmap* icon) {
818 extension_ = extension;
819 SetIcon(icon);
820
821 install_ui_->OnInstallSuccess(extension, &icon_);
822}
823
[email protected]bf3d9df2012-07-24 23:20:27824void ExtensionInstallPrompt::OnInstallFailure(
825 const extensions::CrxInstallerError& error) {
[email protected]c82da8c42012-06-08 19:49:11826 install_ui_->OnInstallFailure(error);
827}
828
829void ExtensionInstallPrompt::SetIcon(const SkBitmap* image) {
830 if (image)
831 icon_ = *image;
832 else
833 icon_ = SkBitmap();
[email protected]dd46a4ce2012-09-15 10:50:50834 if (icon_.empty()) {
835 // Let's set default icon bitmap whose size is equal to the default icon's
836 // pixel size under maximal supported scale factor. If the bitmap is larger
837 // than the one we need, it will be scaled down by the ui code.
838 icon_ = GetDefaultIconBitmapForMaxScaleFactor(extension_->is_app());
839 }
[email protected]c82da8c42012-06-08 19:49:11840}
841
[email protected]ec7de0c5a2012-11-16 07:40:47842void ExtensionInstallPrompt::OnImageLoaded(const gfx::Image& image) {
[email protected]c82da8c42012-06-08 19:49:11843 SetIcon(image.IsEmpty() ? NULL : image.ToSkBitmap());
[email protected]4e494872013-09-06 09:13:54844 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11845}
846
847void ExtensionInstallPrompt::LoadImageIfNeeded() {
848 // Bundle install prompts do not have an icon.
[email protected]5db2e882012-12-20 10:17:26849 // Also |install_ui_.profile()| can be NULL in unit tests.
850 if (!icon_.empty() || !install_ui_->profile()) {
[email protected]4e494872013-09-06 09:13:54851 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11852 return;
853 }
854
[email protected]993da5e2013-03-23 21:25:16855 extensions::ExtensionResource image = extensions::IconsInfo::GetIconResource(
[email protected]702d8b42013-02-27 20:55:50856 extension_,
857 extension_misc::EXTENSION_ICON_LARGE,
858 ExtensionIconSet::MATCH_BIGGER);
[email protected]0d0ba182014-06-03 12:40:43859
860 // Load the image asynchronously. The response will be sent to OnImageLoaded.
861 extensions::ImageLoader* loader =
862 extensions::ImageLoader::Get(install_ui_->profile());
863
864 std::vector<extensions::ImageLoader::ImageRepresentation> images_list;
865 images_list.push_back(extensions::ImageLoader::ImageRepresentation(
866 image,
867 extensions::ImageLoader::ImageRepresentation::NEVER_RESIZE,
868 gfx::Size(),
869 ui::SCALE_FACTOR_100P));
870 loader->LoadImagesAsync(
871 extension_,
872 images_list,
[email protected]ec7de0c5a2012-11-16 07:40:47873 base::Bind(&ExtensionInstallPrompt::OnImageLoaded, AsWeakPtr()));
[email protected]c82da8c42012-06-08 19:49:11874}
875
[email protected]c82da8c42012-06-08 19:49:11876void ExtensionInstallPrompt::ShowConfirmation() {
[email protected]d382baa2014-06-17 18:50:01877 if (prompt_->type() == INSTALL_PROMPT)
878 prompt_->set_experiment(ExtensionInstallPromptExperiment::Find());
[email protected]62a28d7c2013-12-28 01:34:49879 else
[email protected]d382baa2014-06-17 18:50:01880 prompt_->set_experiment(ExtensionInstallPromptExperiment::ControlGroup());
[email protected]62a28d7c2013-12-28 01:34:49881
gpdavis.chromium0fbac4d2014-09-19 20:57:54882 scoped_refptr<const PermissionSet> permissions_to_display;
883 if (custom_permissions_.get()) {
884 permissions_to_display = custom_permissions_;
885 } else if (extension_) {
886 // Initialize permissions if they have not already been set so that
887 // withheld permissions are displayed properly in the install prompt.
888 extensions::PermissionsUpdater(
889 install_ui_->profile(),
890 extensions::PermissionsUpdater::INIT_FLAG_TRANSIENT)
891 .InitializePermissions(extension_);
892 permissions_to_display =
893 extension_->permissions_data()->active_permissions();
894 }
895
896 if (permissions_to_display.get() &&
[email protected]a397ec02014-08-08 15:48:13897 (!extension_ ||
898 !extensions::PermissionsData::ShouldSkipPermissionWarnings(
899 extension_->id()))) {
900 Manifest::Type type =
901 extension_ ? extension_->GetType() : Manifest::TYPE_UNKNOWN;
902 const extensions::PermissionMessageProvider* message_provider =
903 extensions::PermissionMessageProvider::Get();
gpdavis.chromium0fbac4d2014-09-19 20:57:54904 prompt_->SetPermissions(message_provider->GetWarningMessages(
905 permissions_to_display.get(), type),
906 REGULAR_PERMISSIONS);
907 prompt_->SetPermissionsDetails(message_provider->GetWarningMessagesDetails(
908 permissions_to_display.get(), type),
909 REGULAR_PERMISSIONS);
910
911 scoped_refptr<const extensions::PermissionSet> withheld =
912 extension_->permissions_data()->withheld_permissions();
913 if (!withheld->IsEmpty()) {
914 prompt_->SetPermissions(
915 message_provider->GetWarningMessages(withheld.get(), type),
916 PermissionsType::WITHHELD_PERMISSIONS);
917 prompt_->SetPermissionsDetails(
918 message_provider->GetWarningMessagesDetails(withheld.get(), type),
919 PermissionsType::WITHHELD_PERMISSIONS);
920 }
[email protected]bebe1d02012-08-02 20:17:09921 }
[email protected]c82da8c42012-06-08 19:49:11922
[email protected]d382baa2014-06-17 18:50:01923 switch (prompt_->type()) {
[email protected]c82da8c42012-06-08 19:49:11924 case PERMISSIONS_PROMPT:
925 case RE_ENABLE_PROMPT:
926 case INLINE_INSTALL_PROMPT:
[email protected]612a1cb12012-10-17 13:18:03927 case EXTERNAL_INSTALL_PROMPT:
[email protected]15d267b42013-02-14 23:43:32928 case INSTALL_PROMPT:
[email protected]1a93d8d2013-10-27 23:09:20929 case LAUNCH_PROMPT:
[email protected]21db9ef2014-05-16 02:06:27930 case POST_INSTALL_PERMISSIONS_PROMPT:
rdevlin.cronin5f6b69d2014-09-20 01:23:35931 case REMOTE_INSTALL_PROMPT:
932 case REPAIR_PROMPT: {
[email protected]d382baa2014-06-17 18:50:01933 prompt_->set_extension(extension_);
934 prompt_->set_icon(gfx::Image::CreateFrom1xBitmap(icon_));
[email protected]c82da8c42012-06-08 19:49:11935 break;
936 }
937 case BUNDLE_INSTALL_PROMPT: {
[email protected]d382baa2014-06-17 18:50:01938 prompt_->set_bundle(bundle_);
[email protected]c82da8c42012-06-08 19:49:11939 break;
940 }
941 default:
942 NOTREACHED() << "Unknown message";
[email protected]af6efb22012-10-12 02:23:05943 return;
[email protected]c82da8c42012-06-08 19:49:11944 }
[email protected]af6efb22012-10-12 02:23:05945
946 if (AutoConfirmPrompt(delegate_))
947 return;
948
[email protected]5db2e882012-12-20 10:17:26949 if (show_dialog_callback_.is_null())
950 GetDefaultShowDialogCallback().Run(show_params_, delegate_, prompt_);
951 else
952 show_dialog_callback_.Run(show_params_, delegate_, prompt_);
[email protected]c82da8c42012-06-08 19:49:11953}