blob: 45047b8bf9355ed813eb16a00f251142e19ee139 [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"
treib7496f63c2015-03-04 12:18:5339#include "extensions/common/manifest_handlers/permissions_parser.h"
[email protected]c41003472013-10-19 15:37:2540#include "extensions/common/permissions/permission_message_provider.h"
[email protected]5a55f3f2013-10-29 01:08:2941#include "extensions/common/permissions/permission_set.h"
[email protected]e4452d32013-11-15 23:07:4142#include "extensions/common/permissions/permissions_data.h"
[email protected]885c0e92012-11-13 20:27:4243#include "extensions/common/url_pattern.h"
[email protected]2a281332012-07-11 22:20:2344#include "grit/theme_resources.h"
[email protected]c82da8c42012-06-08 19:49:1145#include "ui/base/l10n/l10n_util.h"
46#include "ui/base/resource/resource_bundle.h"
pkotwicz7fd01192014-10-09 04:43:5047#include "ui/base/ui_base_types.h"
[email protected]c82da8c42012-06-08 19:49:1148#include "ui/gfx/image/image.h"
49
[email protected]c82da8c42012-06-08 19:49:1150using extensions::BundleInstaller;
51using extensions::Extension;
[email protected]1d5e58b2013-01-31 08:41:4052using extensions::Manifest;
[email protected]c2e66e12012-06-27 06:27:0653using extensions::PermissionSet;
[email protected]c82da8c42012-06-08 19:49:1154
[email protected]612a1cb12012-10-17 13:18:0355namespace {
56
rdevlin.cronin5f6b69d2014-09-20 01:23:3557bool AllowWebstoreData(ExtensionInstallPrompt::PromptType type) {
58 return type == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT ||
59 type == ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT ||
60 type == ExtensionInstallPrompt::REPAIR_PROMPT;
61}
62
[email protected]c82da8c42012-06-08 19:49:1163static const int kTitleIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2764 0, // The regular install prompt depends on what's being installed.
65 IDS_EXTENSION_INLINE_INSTALL_PROMPT_TITLE,
66 IDS_EXTENSION_INSTALL_PROMPT_TITLE,
67 IDS_EXTENSION_RE_ENABLE_PROMPT_TITLE,
68 IDS_EXTENSION_PERMISSIONS_PROMPT_TITLE,
69 IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_TITLE,
70 IDS_EXTENSION_POST_INSTALL_PERMISSIONS_PROMPT_TITLE,
71 IDS_EXTENSION_LAUNCH_APP_PROMPT_TITLE,
72 0, // The remote install prompt depends on what's being installed.
rdevlin.cronin5f6b69d2014-09-20 01:23:3573 0, // The repair install prompt depends on what's being installed.
treib2d2f5372015-03-01 12:20:4974 0, // The delegated install prompt depends on what's being installed.
[email protected]c82da8c42012-06-08 19:49:1175};
76static const int kHeadingIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2777 IDS_EXTENSION_INSTALL_PROMPT_HEADING,
78 0, // Inline installs use the extension name.
79 0, // Heading for bundle installs depends on the bundle contents.
80 IDS_EXTENSION_RE_ENABLE_PROMPT_HEADING,
81 IDS_EXTENSION_PERMISSIONS_PROMPT_HEADING,
82 0, // External installs use different strings for extensions/apps.
83 IDS_EXTENSION_POST_INSTALL_PERMISSIONS_PROMPT_HEADING,
84 IDS_EXTENSION_LAUNCH_APP_PROMPT_HEADING,
85 IDS_EXTENSION_REMOTE_INSTALL_PROMPT_HEADING,
treib2d2f5372015-03-01 12:20:4986 IDS_EXTENSION_REPAIR_PROMPT_HEADING,
87 IDS_EXTENSION_INSTALL_PROMPT_HEADING,
[email protected]15d267b42013-02-14 23:43:3288};
89static const int kButtons[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2790 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_OK | ui::DIALOG_BUTTON_CANCEL,
94 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
95 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
96 ui::DIALOG_BUTTON_CANCEL,
97 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
98 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
rdevlin.cronin5f6b69d2014-09-20 01:23:3599 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
treib2d2f5372015-03-01 12:20:49100 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
[email protected]c82da8c42012-06-08 19:49:11101};
102static const int kAcceptButtonIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:27103 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
104 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
105 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
106 IDS_EXTENSION_PROMPT_RE_ENABLE_BUTTON,
107 IDS_EXTENSION_PROMPT_PERMISSIONS_BUTTON,
108 0, // External installs use different strings for extensions/apps.
reillygc64d3dd2014-09-29 21:10:11109 0, // Different strings depending on the files and devices retained.
[email protected]21db9ef2014-05-16 02:06:27110 IDS_EXTENSION_PROMPT_LAUNCH_BUTTON,
111 IDS_EXTENSION_PROMPT_REMOTE_INSTALL_BUTTON,
rdevlin.cronin5f6b69d2014-09-20 01:23:35112 IDS_EXTENSION_PROMPT_REPAIR_BUTTON,
treib2d2f5372015-03-01 12:20:49113 IDS_EXTENSION_PROMPT_PERMISSIONS_BUTTON,
[email protected]c82da8c42012-06-08 19:49:11114};
115static const int kAbortButtonIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:27116 0, // These all use the platform's default cancel label.
117 0,
118 0,
119 0,
120 IDS_EXTENSION_PROMPT_PERMISSIONS_ABORT_BUTTON,
121 IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ABORT_BUTTON,
122 IDS_CLOSE,
123 0, // Platform dependent cancel button.
124 0,
rdevlin.cronin5f6b69d2014-09-20 01:23:35125 0,
treib2d2f5372015-03-01 12:20:49126 IDS_EXTENSION_PROMPT_PERMISSIONS_ABORT_BUTTON,
[email protected]c82da8c42012-06-08 19:49:11127};
[email protected]21db9ef2014-05-16 02:06:27128static const int
129 kPermissionsHeaderIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
130 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
131 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
132 IDS_EXTENSION_PROMPT_THESE_WILL_HAVE_ACCESS_TO,
133 IDS_EXTENSION_PROMPT_WILL_NOW_HAVE_ACCESS_TO,
134 IDS_EXTENSION_PROMPT_WANTS_ACCESS_TO,
135 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
136 IDS_EXTENSION_PROMPT_CAN_ACCESS,
137 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
138 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
rdevlin.cronin5f6b69d2014-09-20 01:23:35139 IDS_EXTENSION_PROMPT_CAN_ACCESS,
treib2d2f5372015-03-01 12:20:49140 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
[email protected]c82da8c42012-06-08 19:49:11141};
142
[email protected]dd46a4ce2012-09-15 10:50:50143// Returns bitmap for the default icon with size equal to the default icon's
144// pixel size under maximal supported scale factor.
145SkBitmap GetDefaultIconBitmapForMaxScaleFactor(bool is_app) {
[email protected]702d8b42013-02-27 20:55:50146 const gfx::ImageSkia& image = is_app ?
[email protected]7eb20e32014-04-30 08:50:56147 extensions::util::GetDefaultAppIcon() :
148 extensions::util::GetDefaultExtensionIcon();
[email protected]50b66262013-09-24 03:25:48149 return image.GetRepresentation(
150 gfx::ImageSkia::GetMaxSupportedScale()).sk_bitmap();
[email protected]dd46a4ce2012-09-15 10:50:50151}
152
[email protected]af6efb22012-10-12 02:23:05153// If auto confirm is enabled then posts a task to proceed with or cancel the
154// install and returns true. Otherwise returns false.
155bool AutoConfirmPrompt(ExtensionInstallPrompt::Delegate* delegate) {
[email protected]2a74d6f62014-07-24 11:53:47156 switch (ExtensionInstallPrompt::g_auto_confirm_for_tests) {
157 case ExtensionInstallPrompt::NONE:
158 return false;
159 // We use PostTask instead of calling the delegate directly here, because in
160 // the real implementations it's highly likely the message loop will be
161 // pumping a few times before the user clicks accept or cancel.
162 case ExtensionInstallPrompt::ACCEPT:
163 base::MessageLoop::current()->PostTask(
164 FROM_HERE,
165 base::Bind(&ExtensionInstallPrompt::Delegate::InstallUIProceed,
166 base::Unretained(delegate)));
167 return true;
168 case ExtensionInstallPrompt::CANCEL:
169 base::MessageLoop::current()->PostTask(
170 FROM_HERE,
171 base::Bind(&ExtensionInstallPrompt::Delegate::InstallUIAbort,
172 base::Unretained(delegate),
173 true));
174 return true;
[email protected]af6efb22012-10-12 02:23:05175 }
176
177 NOTREACHED();
178 return false;
179}
180
[email protected]91e51d612012-10-21 23:03:05181Profile* ProfileForWebContents(content::WebContents* web_contents) {
182 if (!web_contents)
183 return NULL;
184 return Profile::FromBrowserContext(web_contents->GetBrowserContext());
185}
186
[email protected]c82da8c42012-06-08 19:49:11187} // namespace
188
gpdavis.chromium0fbac4d2014-09-19 20:57:54189ExtensionInstallPrompt::Prompt::InstallPromptPermissions::
190 InstallPromptPermissions() {
191}
192ExtensionInstallPrompt::Prompt::InstallPromptPermissions::
193 ~InstallPromptPermissions() {
194}
195
[email protected]2a74d6f62014-07-24 11:53:47196// static
197ExtensionInstallPrompt::AutoConfirmForTests
198ExtensionInstallPrompt::g_auto_confirm_for_tests = ExtensionInstallPrompt::NONE;
199
rdevlin.cronin092c6772014-11-20 23:52:40200ExtensionInstallPrompt::PromptType
201ExtensionInstallPrompt::g_last_prompt_type_for_tests =
202 ExtensionInstallPrompt::UNSET_PROMPT_TYPE;
203
[email protected]eeb0d3e12014-08-15 15:10:44204// This should match the PromptType enum.
205std::string ExtensionInstallPrompt::PromptTypeToString(PromptType type) {
206 switch (type) {
207 case ExtensionInstallPrompt::INSTALL_PROMPT:
208 return "INSTALL_PROMPT";
209 case ExtensionInstallPrompt::INLINE_INSTALL_PROMPT:
210 return "INLINE_INSTALL_PROMPT";
211 case ExtensionInstallPrompt::BUNDLE_INSTALL_PROMPT:
212 return "BUNDLE_INSTALL_PROMPT";
213 case ExtensionInstallPrompt::RE_ENABLE_PROMPT:
214 return "RE_ENABLE_PROMPT";
215 case ExtensionInstallPrompt::PERMISSIONS_PROMPT:
216 return "PERMISSIONS_PROMPT";
217 case ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT:
218 return "EXTERNAL_INSTALL_PROMPT";
219 case ExtensionInstallPrompt::POST_INSTALL_PERMISSIONS_PROMPT:
220 return "POST_INSTALL_PERMISSIONS_PROMPT";
221 case ExtensionInstallPrompt::LAUNCH_PROMPT:
222 return "LAUNCH_PROMPT";
223 case ExtensionInstallPrompt::REMOTE_INSTALL_PROMPT:
224 return "REMOTE_INSTALL_PROMPT";
rdevlin.cronin5f6b69d2014-09-20 01:23:35225 case ExtensionInstallPrompt::REPAIR_PROMPT:
226 return "REPAIR_PROMPT";
treib2d2f5372015-03-01 12:20:49227 case ExtensionInstallPrompt::DELEGATED_PERMISSIONS_PROMPT:
228 return "DELEGATED_PERMISSIONS_PROMPT";
[email protected]eeb0d3e12014-08-15 15:10:44229 case ExtensionInstallPrompt::UNSET_PROMPT_TYPE:
230 case ExtensionInstallPrompt::NUM_PROMPT_TYPES:
231 break;
232 }
233 return "OTHER";
234}
235
[email protected]5db2e882012-12-20 10:17:26236ExtensionInstallPrompt::Prompt::Prompt(PromptType type)
[email protected]c82da8c42012-06-08 19:49:11237 : type_(type),
[email protected]79a6f99a2013-08-29 00:32:58238 is_showing_details_for_retained_files_(false),
reillygc64d3dd2014-09-29 21:10:11239 is_showing_details_for_retained_devices_(false),
[email protected]c82da8c42012-06-08 19:49:11240 extension_(NULL),
241 bundle_(NULL),
242 average_rating_(0.0),
[email protected]dcde34b32013-07-31 02:28:45243 rating_count_(0),
[email protected]34b5f7f2014-01-29 02:48:11244 show_user_count_(false),
245 has_webstore_data_(false) {
[email protected]c82da8c42012-06-08 19:49:11246}
247
248ExtensionInstallPrompt::Prompt::~Prompt() {
249}
250
251void ExtensionInstallPrompt::Prompt::SetPermissions(
gpdavis.chromium0fbac4d2014-09-19 20:57:54252 const std::vector<base::string16>& permissions,
253 PermissionsType permissions_type) {
254 GetPermissionsForType(permissions_type).permissions = permissions;
[email protected]c82da8c42012-06-08 19:49:11255}
256
[email protected]8ab7e6c2013-07-11 21:15:03257void ExtensionInstallPrompt::Prompt::SetPermissionsDetails(
gpdavis.chromium0fbac4d2014-09-19 20:57:54258 const std::vector<base::string16>& details,
259 PermissionsType permissions_type) {
260 InstallPromptPermissions& install_permissions =
261 GetPermissionsForType(permissions_type);
sashabeabd5df2014-11-06 02:38:25262
263 // Add a dash to the front of each permission detail.
264 for (const auto& details_entry : details) {
265 if (!details_entry.empty()) {
266 std::vector<base::string16> detail_lines;
267 base::SplitString(details_entry, base::char16('\n'), &detail_lines);
268
269 std::vector<base::string16> detail_lines_with_bullets;
270 for (const auto& detail_line : detail_lines)
271 detail_lines_with_bullets.push_back(base::ASCIIToUTF16("- ") +
272 detail_line);
273
274 install_permissions.details.push_back(
275 JoinString(detail_lines_with_bullets, '\n'));
276 } else {
277 install_permissions.details.push_back(details_entry);
278 }
279 }
280
gpdavis.chromium0fbac4d2014-09-19 20:57:54281 install_permissions.is_showing_details.clear();
282 install_permissions.is_showing_details.insert(
283 install_permissions.is_showing_details.begin(), details.size(), false);
[email protected]79a6f99a2013-08-29 00:32:58284}
285
286void ExtensionInstallPrompt::Prompt::SetIsShowingDetails(
287 DetailsType type,
288 size_t index,
289 bool is_showing_details) {
290 switch (type) {
291 case PERMISSIONS_DETAILS:
gpdavis.chromium0fbac4d2014-09-19 20:57:54292 prompt_permissions_.is_showing_details[index] = is_showing_details;
293 break;
294 case WITHHELD_PERMISSIONS_DETAILS:
295 withheld_prompt_permissions_.is_showing_details[index] =
296 is_showing_details;
[email protected]79a6f99a2013-08-29 00:32:58297 break;
[email protected]79a6f99a2013-08-29 00:32:58298 case RETAINED_FILES_DETAILS:
299 is_showing_details_for_retained_files_ = is_showing_details;
300 break;
reillygc64d3dd2014-09-29 21:10:11301 case RETAINED_DEVICES_DETAILS:
302 is_showing_details_for_retained_devices_ = is_showing_details;
303 break;
[email protected]79a6f99a2013-08-29 00:32:58304 }
[email protected]8ab7e6c2013-07-11 21:15:03305}
306
[email protected]34b5f7f2014-01-29 02:48:11307void ExtensionInstallPrompt::Prompt::SetWebstoreData(
[email protected]c82da8c42012-06-08 19:49:11308 const std::string& localized_user_count,
[email protected]dcde34b32013-07-31 02:28:45309 bool show_user_count,
[email protected]c82da8c42012-06-08 19:49:11310 double average_rating,
311 int rating_count) {
rdevlin.cronin5f6b69d2014-09-20 01:23:35312 CHECK(AllowWebstoreData(type_));
[email protected]c82da8c42012-06-08 19:49:11313 localized_user_count_ = localized_user_count;
[email protected]dcde34b32013-07-31 02:28:45314 show_user_count_ = show_user_count;
[email protected]c82da8c42012-06-08 19:49:11315 average_rating_ = average_rating;
316 rating_count_ = rating_count;
[email protected]34b5f7f2014-01-29 02:48:11317 has_webstore_data_ = true;
[email protected]c82da8c42012-06-08 19:49:11318}
319
[email protected]6a72a632013-12-12 22:22:00320base::string16 ExtensionInstallPrompt::Prompt::GetDialogTitle() const {
[email protected]c82da8c42012-06-08 19:49:11321 int resource_id = kTitleIds[type_];
322
323 if (type_ == INSTALL_PROMPT) {
324 if (extension_->is_app())
325 resource_id = IDS_EXTENSION_INSTALL_APP_PROMPT_TITLE;
326 else if (extension_->is_theme())
327 resource_id = IDS_EXTENSION_INSTALL_THEME_PROMPT_TITLE;
328 else
329 resource_id = IDS_EXTENSION_INSTALL_EXTENSION_PROMPT_TITLE;
[email protected]612a1cb12012-10-17 13:18:03330 } else if (type_ == EXTERNAL_INSTALL_PROMPT) {
331 return l10n_util::GetStringFUTF16(
[email protected]04338722013-12-24 23:18:05332 resource_id, base::UTF8ToUTF16(extension_->name()));
[email protected]21db9ef2014-05-16 02:06:27333 } else if (type_ == REMOTE_INSTALL_PROMPT) {
334 if (extension_->is_app())
335 resource_id = IDS_EXTENSION_REMOTE_INSTALL_APP_PROMPT_TITLE;
336 else
337 resource_id = IDS_EXTENSION_REMOTE_INSTALL_EXTENSION_PROMPT_TITLE;
rdevlin.cronin5f6b69d2014-09-20 01:23:35338 } else if (type_ == REPAIR_PROMPT) {
339 if (extension_->is_app())
340 resource_id = IDS_EXTENSION_REPAIR_APP_PROMPT_TITLE;
341 else
342 resource_id = IDS_EXTENSION_REPAIR_EXTENSION_PROMPT_TITLE;
treib2d2f5372015-03-01 12:20:49343 } else if (type_ == DELEGATED_PERMISSIONS_PROMPT) {
344 DCHECK(!delegated_username_.empty());
345 if (extension_->is_app())
346 resource_id = IDS_EXTENSION_DELEGATED_INSTALL_APP_PROMPT_TITLE;
347 else
348 resource_id = IDS_EXTENSION_DELEGATED_INSTALL_EXTENSION_PROMPT_TITLE;
349 return l10n_util::GetStringFUTF16(
350 resource_id, base::UTF8ToUTF16(delegated_username_));
[email protected]c82da8c42012-06-08 19:49:11351 }
352
353 return l10n_util::GetStringUTF16(resource_id);
354}
355
[email protected]6a72a632013-12-12 22:22:00356base::string16 ExtensionInstallPrompt::Prompt::GetHeading() const {
[email protected]c82da8c42012-06-08 19:49:11357 if (type_ == INLINE_INSTALL_PROMPT) {
[email protected]04338722013-12-24 23:18:05358 return base::UTF8ToUTF16(extension_->name());
[email protected]c82da8c42012-06-08 19:49:11359 } else if (type_ == BUNDLE_INSTALL_PROMPT) {
360 return bundle_->GetHeadingTextFor(BundleInstaller::Item::STATE_PENDING);
[email protected]612a1cb12012-10-17 13:18:03361 } else if (type_ == EXTERNAL_INSTALL_PROMPT) {
[email protected]846606012012-10-19 18:42:25362 int resource_id = -1;
363 if (extension_->is_app())
364 resource_id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_HEADING_APP;
365 else if (extension_->is_theme())
366 resource_id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_HEADING_THEME;
367 else
368 resource_id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_HEADING_EXTENSION;
369 return l10n_util::GetStringUTF16(resource_id);
[email protected]c82da8c42012-06-08 19:49:11370 } else {
371 return l10n_util::GetStringFUTF16(
[email protected]04338722013-12-24 23:18:05372 kHeadingIds[type_], base::UTF8ToUTF16(extension_->name()));
[email protected]c82da8c42012-06-08 19:49:11373 }
374}
375
[email protected]15d267b42013-02-14 23:43:32376int ExtensionInstallPrompt::Prompt::GetDialogButtons() const {
reillygc64d3dd2014-09-29 21:10:11377 if (type_ == POST_INSTALL_PERMISSIONS_PROMPT && ShouldDisplayRevokeButton()) {
[email protected]a2886e8b2013-06-08 05:15:02378 return kButtons[type_] | ui::DIALOG_BUTTON_OK;
379 }
380
[email protected]15d267b42013-02-14 23:43:32381 return kButtons[type_];
382}
383
[email protected]62a28d7c2013-12-28 01:34:49384bool ExtensionInstallPrompt::Prompt::ShouldShowExplanationText() const {
dchengc7047942014-08-26 05:05:31385 return type_ == INSTALL_PROMPT && extension_->is_extension() &&
386 experiment_.get() && experiment_->text_only();
[email protected]62a28d7c2013-12-28 01:34:49387}
388
[email protected]15d267b42013-02-14 23:43:32389bool ExtensionInstallPrompt::Prompt::HasAcceptButtonLabel() const {
reillygc64d3dd2014-09-29 21:10:11390 if (type_ == POST_INSTALL_PERMISSIONS_PROMPT)
391 return ShouldDisplayRevokeButton();
392
[email protected]a2886e8b2013-06-08 05:15:02393 if (kAcceptButtonIds[type_] == 0)
394 return false;
395
[email protected]a2886e8b2013-06-08 05:15:02396 return true;
[email protected]15d267b42013-02-14 23:43:32397}
398
[email protected]6a72a632013-12-12 22:22:00399base::string16 ExtensionInstallPrompt::Prompt::GetAcceptButtonLabel() const {
[email protected]846606012012-10-19 18:42:25400 if (type_ == EXTERNAL_INSTALL_PROMPT) {
401 int id = -1;
402 if (extension_->is_app())
403 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_APP;
404 else if (extension_->is_theme())
405 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_THEME;
406 else
407 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_EXTENSION;
408 return l10n_util::GetStringUTF16(id);
reillygc64d3dd2014-09-29 21:10:11409 } else if (type_ == POST_INSTALL_PERMISSIONS_PROMPT) {
410 int id = -1;
411 if (GetRetainedFileCount() && GetRetainedDeviceCount()) {
412 id =
413 IDS_EXTENSION_PROMPT_PERMISSIONS_CLEAR_RETAINED_FILES_AND_DEVICES_BUTTON;
414 } else if (GetRetainedFileCount()) {
415 id = IDS_EXTENSION_PROMPT_PERMISSIONS_CLEAR_RETAINED_FILES_BUTTON;
416 } else {
417 DCHECK_LT(0U, GetRetainedDeviceCount());
418 id = IDS_EXTENSION_PROMPT_PERMISSIONS_CLEAR_RETAINED_DEVICES_BUTTON;
419 }
420 return l10n_util::GetStringUTF16(id);
[email protected]846606012012-10-19 18:42:25421 }
[email protected]62a28d7c2013-12-28 01:34:49422 if (ShouldShowExplanationText())
423 return experiment_->GetOkButtonText();
[email protected]c82da8c42012-06-08 19:49:11424 return l10n_util::GetStringUTF16(kAcceptButtonIds[type_]);
425}
426
427bool ExtensionInstallPrompt::Prompt::HasAbortButtonLabel() const {
[email protected]62a28d7c2013-12-28 01:34:49428 if (ShouldShowExplanationText())
429 return true;
[email protected]c82da8c42012-06-08 19:49:11430 return kAbortButtonIds[type_] > 0;
431}
432
[email protected]6a72a632013-12-12 22:22:00433base::string16 ExtensionInstallPrompt::Prompt::GetAbortButtonLabel() const {
[email protected]c82da8c42012-06-08 19:49:11434 CHECK(HasAbortButtonLabel());
[email protected]62a28d7c2013-12-28 01:34:49435 if (ShouldShowExplanationText())
436 return experiment_->GetCancelButtonText();
[email protected]c82da8c42012-06-08 19:49:11437 return l10n_util::GetStringUTF16(kAbortButtonIds[type_]);
438}
439
gpdavis.chromium0fbac4d2014-09-19 20:57:54440base::string16 ExtensionInstallPrompt::Prompt::GetPermissionsHeading(
441 PermissionsType permissions_type) const {
442 switch (permissions_type) {
443 case REGULAR_PERMISSIONS:
444 return l10n_util::GetStringUTF16(kPermissionsHeaderIds[type_]);
445 case WITHHELD_PERMISSIONS:
446 return l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WITHHELD);
447 case ALL_PERMISSIONS:
448 default:
449 NOTREACHED();
450 return base::string16();
451 }
[email protected]c82da8c42012-06-08 19:49:11452}
453
[email protected]6a72a632013-12-12 22:22:00454base::string16 ExtensionInstallPrompt::Prompt::GetRetainedFilesHeading() const {
[email protected]4f1e1082013-09-23 10:30:53455 const int kRetainedFilesMessageIDs[6] = {
456 IDS_EXTENSION_PROMPT_RETAINED_FILES_DEFAULT,
457 IDS_EXTENSION_PROMPT_RETAINED_FILE_SINGULAR,
458 IDS_EXTENSION_PROMPT_RETAINED_FILES_ZERO,
459 IDS_EXTENSION_PROMPT_RETAINED_FILES_TWO,
460 IDS_EXTENSION_PROMPT_RETAINED_FILES_FEW,
461 IDS_EXTENSION_PROMPT_RETAINED_FILES_MANY,
462 };
reillygc64d3dd2014-09-29 21:10:11463 std::vector<int> message_ids(
464 kRetainedFilesMessageIDs,
465 kRetainedFilesMessageIDs + arraysize(kRetainedFilesMessageIDs));
466
[email protected]4f1e1082013-09-23 10:30:53467 return l10n_util::GetPluralStringFUTF16(message_ids, GetRetainedFileCount());
[email protected]8ab7e6c2013-07-11 21:15:03468}
469
reillygc64d3dd2014-09-29 21:10:11470base::string16 ExtensionInstallPrompt::Prompt::GetRetainedDevicesHeading()
471 const {
472 const int kRetainedDevicesMessageIDs[6] = {
473 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_DEFAULT,
474 IDS_EXTENSION_PROMPT_RETAINED_DEVICE_SINGULAR,
475 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_ZERO,
476 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_TWO,
477 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_FEW,
478 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_MANY,
479 };
480 std::vector<int> message_ids(
481 kRetainedDevicesMessageIDs,
482 kRetainedDevicesMessageIDs + arraysize(kRetainedDevicesMessageIDs));
483
484 return l10n_util::GetPluralStringFUTF16(message_ids,
485 GetRetainedDeviceCount());
486}
487
[email protected]f2cd8992013-06-11 17:30:18488bool ExtensionInstallPrompt::Prompt::ShouldShowPermissions() const {
gpdavis.chromium0fbac4d2014-09-19 20:57:54489 return GetPermissionCount(ALL_PERMISSIONS) > 0 ||
490 type_ == POST_INSTALL_PERMISSIONS_PROMPT;
[email protected]f2cd8992013-06-11 17:30:18491}
492
[email protected]c82da8c42012-06-08 19:49:11493void ExtensionInstallPrompt::Prompt::AppendRatingStars(
494 StarAppender appender, void* data) const {
495 CHECK(appender);
rdevlin.cronin5f6b69d2014-09-20 01:23:35496 CHECK(AllowWebstoreData(type_));
[email protected]c82da8c42012-06-08 19:49:11497 int rating_integer = floor(average_rating_);
498 double rating_fractional = average_rating_ - rating_integer;
499
500 if (rating_fractional > 0.66) {
501 rating_integer++;
502 }
503
504 if (rating_fractional < 0.33 || rating_fractional > 0.66) {
505 rating_fractional = 0;
506 }
507
508 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
509 int i;
510 for (i = 0; i < rating_integer; i++) {
511 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_ON), data);
512 }
513 if (rating_fractional) {
514 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_HALF_LEFT), data);
515 i++;
516 }
517 for (; i < kMaxExtensionRating; i++) {
518 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_OFF), data);
519 }
520}
521
[email protected]6a72a632013-12-12 22:22:00522base::string16 ExtensionInstallPrompt::Prompt::GetRatingCount() const {
rdevlin.cronin5f6b69d2014-09-20 01:23:35523 CHECK(AllowWebstoreData(type_));
[email protected]6725048e2013-10-24 21:47:14524 return l10n_util::GetStringFUTF16(IDS_EXTENSION_RATING_COUNT,
525 base::IntToString16(rating_count_));
[email protected]c82da8c42012-06-08 19:49:11526}
527
[email protected]6a72a632013-12-12 22:22:00528base::string16 ExtensionInstallPrompt::Prompt::GetUserCount() const {
rdevlin.cronin5f6b69d2014-09-20 01:23:35529 CHECK(AllowWebstoreData(type_));
[email protected]dcde34b32013-07-31 02:28:45530
531 if (show_user_count_) {
[email protected]6725048e2013-10-24 21:47:14532 return l10n_util::GetStringFUTF16(IDS_EXTENSION_USER_COUNT,
533 base::UTF8ToUTF16(localized_user_count_));
[email protected]dcde34b32013-07-31 02:28:45534 }
[email protected]6725048e2013-10-24 21:47:14535 return base::string16();
[email protected]c82da8c42012-06-08 19:49:11536}
537
gpdavis.chromium0fbac4d2014-09-19 20:57:54538size_t ExtensionInstallPrompt::Prompt::GetPermissionCount(
539 PermissionsType permissions_type) const {
540 switch (permissions_type) {
541 case REGULAR_PERMISSIONS:
542 return prompt_permissions_.permissions.size();
543 case WITHHELD_PERMISSIONS:
544 return withheld_prompt_permissions_.permissions.size();
545 case ALL_PERMISSIONS:
546 return prompt_permissions_.permissions.size() +
547 withheld_prompt_permissions_.permissions.size();
548 default:
549 NOTREACHED();
550 return 0u;
551 }
[email protected]c82da8c42012-06-08 19:49:11552}
553
gpdavis.chromium0fbac4d2014-09-19 20:57:54554size_t ExtensionInstallPrompt::Prompt::GetPermissionsDetailsCount(
555 PermissionsType permissions_type) const {
556 switch (permissions_type) {
557 case REGULAR_PERMISSIONS:
558 return prompt_permissions_.details.size();
559 case WITHHELD_PERMISSIONS:
560 return withheld_prompt_permissions_.details.size();
561 case ALL_PERMISSIONS:
562 return prompt_permissions_.details.size() +
563 withheld_prompt_permissions_.details.size();
564 default:
565 NOTREACHED();
566 return 0u;
567 }
[email protected]8ab7e6c2013-07-11 21:15:03568}
569
gpdavis.chromium0fbac4d2014-09-19 20:57:54570base::string16 ExtensionInstallPrompt::Prompt::GetPermission(
571 size_t index,
572 PermissionsType permissions_type) const {
573 const InstallPromptPermissions& install_permissions =
574 GetPermissionsForType(permissions_type);
575 CHECK_LT(index, install_permissions.permissions.size());
576 return install_permissions.permissions[index];
[email protected]c82da8c42012-06-08 19:49:11577}
578
[email protected]6a72a632013-12-12 22:22:00579base::string16 ExtensionInstallPrompt::Prompt::GetPermissionsDetails(
gpdavis.chromium0fbac4d2014-09-19 20:57:54580 size_t index,
581 PermissionsType permissions_type) const {
582 const InstallPromptPermissions& install_permissions =
583 GetPermissionsForType(permissions_type);
584 CHECK_LT(index, install_permissions.details.size());
585 return install_permissions.details[index];
[email protected]8ab7e6c2013-07-11 21:15:03586}
587
[email protected]79a6f99a2013-08-29 00:32:58588bool ExtensionInstallPrompt::Prompt::GetIsShowingDetails(
589 DetailsType type, size_t index) const {
590 switch (type) {
591 case PERMISSIONS_DETAILS:
gpdavis.chromium0fbac4d2014-09-19 20:57:54592 CHECK_LT(index, prompt_permissions_.is_showing_details.size());
593 return prompt_permissions_.is_showing_details[index];
594 case WITHHELD_PERMISSIONS_DETAILS:
595 CHECK_LT(index, withheld_prompt_permissions_.is_showing_details.size());
596 return withheld_prompt_permissions_.is_showing_details[index];
[email protected]79a6f99a2013-08-29 00:32:58597 case RETAINED_FILES_DETAILS:
598 return is_showing_details_for_retained_files_;
reillygc64d3dd2014-09-29 21:10:11599 case RETAINED_DEVICES_DETAILS:
600 return is_showing_details_for_retained_devices_;
[email protected]79a6f99a2013-08-29 00:32:58601 }
602 return false;
603}
604
[email protected]a2886e8b2013-06-08 05:15:02605size_t ExtensionInstallPrompt::Prompt::GetRetainedFileCount() const {
606 return retained_files_.size();
607}
608
[email protected]6a72a632013-12-12 22:22:00609base::string16 ExtensionInstallPrompt::Prompt::GetRetainedFile(size_t index)
610 const {
[email protected]a2886e8b2013-06-08 05:15:02611 CHECK_LT(index, retained_files_.size());
[email protected]6725048e2013-10-24 21:47:14612 return retained_files_[index].AsUTF16Unsafe();
[email protected]a2886e8b2013-06-08 05:15:02613}
614
reillygc64d3dd2014-09-29 21:10:11615size_t ExtensionInstallPrompt::Prompt::GetRetainedDeviceCount() const {
616 return retained_device_messages_.size();
617}
618
619base::string16 ExtensionInstallPrompt::Prompt::GetRetainedDeviceMessageString(
620 size_t index) const {
621 CHECK_LT(index, retained_device_messages_.size());
622 return retained_device_messages_[index];
623}
624
625bool ExtensionInstallPrompt::Prompt::ShouldDisplayRevokeButton() const {
626 return !retained_files_.empty() || !retained_device_messages_.empty();
627}
628
gpdavis.chromium0fbac4d2014-09-19 20:57:54629ExtensionInstallPrompt::Prompt::InstallPromptPermissions&
630ExtensionInstallPrompt::Prompt::GetPermissionsForType(
631 PermissionsType permissions_type) {
632 DCHECK_NE(ALL_PERMISSIONS, permissions_type);
633 return permissions_type == REGULAR_PERMISSIONS ? prompt_permissions_
634 : withheld_prompt_permissions_;
635}
636
637const ExtensionInstallPrompt::Prompt::InstallPromptPermissions&
638ExtensionInstallPrompt::Prompt::GetPermissionsForType(
639 PermissionsType permissions_type) const {
640 DCHECK_NE(ALL_PERMISSIONS, permissions_type);
641 return permissions_type == REGULAR_PERMISSIONS ? prompt_permissions_
642 : withheld_prompt_permissions_;
643}
644
[email protected]a2886e8b2013-06-08 05:15:02645bool ExtensionInstallPrompt::Prompt::ShouldDisplayRevokeFilesButton() const {
646 return !retained_files_.empty();
647}
648
[email protected]c82da8c42012-06-08 19:49:11649// static
650scoped_refptr<Extension>
651 ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
[email protected]023b3d12013-12-23 18:46:49652 const base::DictionaryValue* manifest,
[email protected]c422a862012-07-31 15:46:13653 int flags,
[email protected]c82da8c42012-06-08 19:49:11654 const std::string& id,
655 const std::string& localized_name,
656 const std::string& localized_description,
657 std::string* error) {
[email protected]023b3d12013-12-23 18:46:49658 scoped_ptr<base::DictionaryValue> localized_manifest;
[email protected]c82da8c42012-06-08 19:49:11659 if (!localized_name.empty() || !localized_description.empty()) {
660 localized_manifest.reset(manifest->DeepCopy());
661 if (!localized_name.empty()) {
[email protected]6bf90612013-08-15 00:36:27662 localized_manifest->SetString(extensions::manifest_keys::kName,
[email protected]c82da8c42012-06-08 19:49:11663 localized_name);
664 }
665 if (!localized_description.empty()) {
[email protected]6bf90612013-08-15 00:36:27666 localized_manifest->SetString(extensions::manifest_keys::kDescription,
[email protected]c82da8c42012-06-08 19:49:11667 localized_description);
668 }
669 }
670
671 return Extension::Create(
[email protected]650b2d52013-02-10 03:41:45672 base::FilePath(),
[email protected]1d5e58b2013-01-31 08:41:40673 Manifest::INTERNAL,
[email protected]c82da8c42012-06-08 19:49:11674 localized_manifest.get() ? *localized_manifest.get() : *manifest,
[email protected]c422a862012-07-31 15:46:13675 flags,
[email protected]c82da8c42012-06-08 19:49:11676 id,
677 error);
678}
679
[email protected]7f165342014-02-12 09:22:22680ExtensionInstallPrompt::ExtensionInstallPrompt(content::WebContents* contents)
pkotwicza57a1f322014-10-21 00:24:30681 : profile_(ProfileForWebContents(contents)),
682 ui_loop_(base::MessageLoop::current()),
[email protected]c82da8c42012-06-08 19:49:11683 extension_(NULL),
[email protected]7f165342014-02-12 09:22:22684 bundle_(NULL),
pkotwicza57a1f322014-10-21 00:24:30685 install_ui_(extensions::CreateExtensionInstallUI(
686 ProfileForWebContents(contents))),
pkotwicz2f181782014-10-29 17:33:45687 show_params_(new ExtensionInstallPromptShowParams(contents)),
[email protected]d382baa2014-06-17 18:50:01688 delegate_(NULL) {
689}
[email protected]5db2e882012-12-20 10:17:26690
pkotwicz2175c622014-10-22 19:56:28691ExtensionInstallPrompt::ExtensionInstallPrompt(Profile* profile,
692 gfx::NativeWindow native_window)
pkotwicza57a1f322014-10-21 00:24:30693 : profile_(profile),
694 ui_loop_(base::MessageLoop::current()),
[email protected]5db2e882012-12-20 10:17:26695 extension_(NULL),
[email protected]7f165342014-02-12 09:22:22696 bundle_(NULL),
pkotwicza57a1f322014-10-21 00:24:30697 install_ui_(extensions::CreateExtensionInstallUI(profile)),
pkotwicz2f181782014-10-29 17:33:45698 show_params_(
699 new ExtensionInstallPromptShowParams(profile, native_window)),
[email protected]d382baa2014-06-17 18:50:01700 delegate_(NULL) {
701}
[email protected]c82da8c42012-06-08 19:49:11702
703ExtensionInstallPrompt::~ExtensionInstallPrompt() {
704}
705
706void ExtensionInstallPrompt::ConfirmBundleInstall(
707 extensions::BundleInstaller* bundle,
[email protected]c2e66e12012-06-27 06:27:06708 const PermissionSet* permissions) {
[email protected]b3a25092013-05-28 22:08:16709 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11710 bundle_ = bundle;
gpdavis.chromium0fbac4d2014-09-19 20:57:54711 custom_permissions_ = permissions;
[email protected]c82da8c42012-06-08 19:49:11712 delegate_ = bundle;
[email protected]d382baa2014-06-17 18:50:01713 prompt_ = new Prompt(BUNDLE_INSTALL_PROMPT);
[email protected]c82da8c42012-06-08 19:49:11714
[email protected]4e494872013-09-06 09:13:54715 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11716}
717
[email protected]734bcec2012-10-08 20:29:05718void ExtensionInstallPrompt::ConfirmStandaloneInstall(
[email protected]c82da8c42012-06-08 19:49:11719 Delegate* delegate,
720 const Extension* extension,
721 SkBitmap* icon,
[email protected]d382baa2014-06-17 18:50:01722 scoped_refptr<Prompt> prompt) {
[email protected]b3a25092013-05-28 22:08:16723 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11724 extension_ = extension;
[email protected]c82da8c42012-06-08 19:49:11725 delegate_ = delegate;
726 prompt_ = prompt;
[email protected]c82da8c42012-06-08 19:49:11727
728 SetIcon(icon);
[email protected]4e494872013-09-06 09:13:54729 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11730}
731
[email protected]af6efb22012-10-12 02:23:05732void ExtensionInstallPrompt::ConfirmWebstoreInstall(
733 Delegate* delegate,
734 const Extension* extension,
735 const SkBitmap* icon,
736 const ShowDialogCallback& show_dialog_callback) {
[email protected]c82da8c42012-06-08 19:49:11737 // SetIcon requires |extension_| to be set. ConfirmInstall will setup the
738 // remaining fields.
739 extension_ = extension;
740 SetIcon(icon);
[email protected]af6efb22012-10-12 02:23:05741 ConfirmInstall(delegate, extension, show_dialog_callback);
[email protected]c82da8c42012-06-08 19:49:11742}
743
[email protected]af6efb22012-10-12 02:23:05744void ExtensionInstallPrompt::ConfirmInstall(
745 Delegate* delegate,
746 const Extension* extension,
747 const ShowDialogCallback& show_dialog_callback) {
[email protected]b3a25092013-05-28 22:08:16748 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11749 extension_ = extension;
[email protected]c82da8c42012-06-08 19:49:11750 delegate_ = delegate;
[email protected]d382baa2014-06-17 18:50:01751 prompt_ = new Prompt(INSTALL_PROMPT);
[email protected]af6efb22012-10-12 02:23:05752 show_dialog_callback_ = show_dialog_callback;
[email protected]c82da8c42012-06-08 19:49:11753
754 // We special-case themes to not show any confirm UI. Instead they are
755 // immediately installed, and then we show an infobar (see OnInstallSuccess)
756 // to allow the user to revert if they don't like it.
757 //
758 // We don't do this in the case where off-store extension installs are
759 // disabled because in that case, we don't show the dangerous download UI, so
760 // we need the UI confirmation.
761 if (extension->is_theme()) {
762 if (extension->from_webstore() ||
[email protected]544471a2012-10-13 05:27:09763 extensions::FeatureSwitch::easy_off_store_install()->IsEnabled()) {
[email protected]c82da8c42012-06-08 19:49:11764 delegate->InstallUIProceed();
765 return;
766 }
767 }
768
769 LoadImageIfNeeded();
770}
771
treib2d2f5372015-03-01 12:20:49772void ExtensionInstallPrompt::ConfirmPermissionsForDelegatedInstall(
773 Delegate* delegate,
774 const Extension* extension,
775 const std::string& delegated_username,
776 const SkBitmap* icon) {
777 DCHECK(ui_loop_ == base::MessageLoop::current());
778 delegate_ = delegate;
779 extension_ = extension;
780 delegated_username_ = delegated_username;
781 SetIcon(icon);
782 prompt_ = new Prompt(DELEGATED_PERMISSIONS_PROMPT);
783 ShowConfirmation();
784}
785
[email protected]c82da8c42012-06-08 19:49:11786void ExtensionInstallPrompt::ConfirmReEnable(Delegate* delegate,
787 const Extension* extension) {
[email protected]b3a25092013-05-28 22:08:16788 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11789 extension_ = extension;
[email protected]c82da8c42012-06-08 19:49:11790 delegate_ = delegate;
[email protected]21db9ef2014-05-16 02:06:27791 bool is_remote_install =
pkotwicza57a1f322014-10-21 00:24:30792 profile_ &&
793 extensions::ExtensionPrefs::Get(profile_)->HasDisableReason(
[email protected]21db9ef2014-05-16 02:06:27794 extension->id(), extensions::Extension::DISABLE_REMOTE_INSTALL);
[email protected]411f8ae2014-05-22 11:12:23795 bool is_ephemeral =
pkotwicza57a1f322014-10-21 00:24:30796 extensions::util::IsEphemeralApp(extension->id(), profile_);
[email protected]d382baa2014-06-17 18:50:01797
798 PromptType type = UNSET_PROMPT_TYPE;
[email protected]411f8ae2014-05-22 11:12:23799 if (is_ephemeral)
[email protected]d382baa2014-06-17 18:50:01800 type = LAUNCH_PROMPT;
[email protected]21db9ef2014-05-16 02:06:27801 else if (is_remote_install)
[email protected]d382baa2014-06-17 18:50:01802 type = REMOTE_INSTALL_PROMPT;
[email protected]21db9ef2014-05-16 02:06:27803 else
[email protected]d382baa2014-06-17 18:50:01804 type = RE_ENABLE_PROMPT;
805 prompt_ = new Prompt(type);
806
[email protected]c82da8c42012-06-08 19:49:11807 LoadImageIfNeeded();
808}
809
[email protected]612a1cb12012-10-17 13:18:03810void ExtensionInstallPrompt::ConfirmExternalInstall(
[email protected]c8ff7c9e2013-04-20 12:36:27811 Delegate* delegate,
812 const Extension* extension,
[email protected]34b5f7f2014-01-29 02:48:11813 const ShowDialogCallback& show_dialog_callback,
[email protected]d382baa2014-06-17 18:50:01814 scoped_refptr<Prompt> prompt) {
[email protected]b3a25092013-05-28 22:08:16815 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]612a1cb12012-10-17 13:18:03816 extension_ = extension;
[email protected]612a1cb12012-10-17 13:18:03817 delegate_ = delegate;
[email protected]34b5f7f2014-01-29 02:48:11818 prompt_ = prompt;
[email protected]c8ff7c9e2013-04-20 12:36:27819 show_dialog_callback_ = show_dialog_callback;
[email protected]612a1cb12012-10-17 13:18:03820
821 LoadImageIfNeeded();
822}
823
[email protected]c82da8c42012-06-08 19:49:11824void ExtensionInstallPrompt::ConfirmPermissions(
825 Delegate* delegate,
826 const Extension* extension,
[email protected]c2e66e12012-06-27 06:27:06827 const PermissionSet* permissions) {
[email protected]b3a25092013-05-28 22:08:16828 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11829 extension_ = extension;
gpdavis.chromium0fbac4d2014-09-19 20:57:54830 custom_permissions_ = permissions;
[email protected]c82da8c42012-06-08 19:49:11831 delegate_ = delegate;
[email protected]d382baa2014-06-17 18:50:01832 prompt_ = new Prompt(PERMISSIONS_PROMPT);
[email protected]c82da8c42012-06-08 19:49:11833
834 LoadImageIfNeeded();
835}
836
[email protected]a2886e8b2013-06-08 05:15:02837void ExtensionInstallPrompt::ReviewPermissions(
838 Delegate* delegate,
839 const Extension* extension,
reillygc64d3dd2014-09-29 21:10:11840 const std::vector<base::FilePath>& retained_file_paths,
841 const std::vector<base::string16>& retained_device_messages) {
[email protected]b3a25092013-05-28 22:08:16842 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]15d267b42013-02-14 23:43:32843 extension_ = extension;
[email protected]d382baa2014-06-17 18:50:01844 prompt_ = new Prompt(POST_INSTALL_PERMISSIONS_PROMPT);
845 prompt_->set_retained_files(retained_file_paths);
reillygc64d3dd2014-09-29 21:10:11846 prompt_->set_retained_device_messages(retained_device_messages);
[email protected]15d267b42013-02-14 23:43:32847 delegate_ = delegate;
[email protected]15d267b42013-02-14 23:43:32848
849 LoadImageIfNeeded();
850}
851
[email protected]c82da8c42012-06-08 19:49:11852void ExtensionInstallPrompt::OnInstallSuccess(const Extension* extension,
853 SkBitmap* icon) {
854 extension_ = extension;
855 SetIcon(icon);
856
857 install_ui_->OnInstallSuccess(extension, &icon_);
858}
859
[email protected]bf3d9df2012-07-24 23:20:27860void ExtensionInstallPrompt::OnInstallFailure(
ginkage47e603e2015-02-27 08:42:41861 const extensions::CrxInstallError& error) {
[email protected]c82da8c42012-06-08 19:49:11862 install_ui_->OnInstallFailure(error);
863}
864
865void ExtensionInstallPrompt::SetIcon(const SkBitmap* image) {
866 if (image)
867 icon_ = *image;
868 else
869 icon_ = SkBitmap();
[email protected]dd46a4ce2012-09-15 10:50:50870 if (icon_.empty()) {
871 // Let's set default icon bitmap whose size is equal to the default icon's
872 // pixel size under maximal supported scale factor. If the bitmap is larger
873 // than the one we need, it will be scaled down by the ui code.
874 icon_ = GetDefaultIconBitmapForMaxScaleFactor(extension_->is_app());
875 }
[email protected]c82da8c42012-06-08 19:49:11876}
877
[email protected]ec7de0c5a2012-11-16 07:40:47878void ExtensionInstallPrompt::OnImageLoaded(const gfx::Image& image) {
[email protected]c82da8c42012-06-08 19:49:11879 SetIcon(image.IsEmpty() ? NULL : image.ToSkBitmap());
[email protected]4e494872013-09-06 09:13:54880 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11881}
882
883void ExtensionInstallPrompt::LoadImageIfNeeded() {
884 // Bundle install prompts do not have an icon.
pkotwicza57a1f322014-10-21 00:24:30885 // Also |profile_| can be NULL in unit tests.
886 if (!icon_.empty() || !profile_) {
[email protected]4e494872013-09-06 09:13:54887 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11888 return;
889 }
890
[email protected]993da5e2013-03-23 21:25:16891 extensions::ExtensionResource image = extensions::IconsInfo::GetIconResource(
[email protected]702d8b42013-02-27 20:55:50892 extension_,
893 extension_misc::EXTENSION_ICON_LARGE,
894 ExtensionIconSet::MATCH_BIGGER);
[email protected]0d0ba182014-06-03 12:40:43895
896 // Load the image asynchronously. The response will be sent to OnImageLoaded.
pkotwicza57a1f322014-10-21 00:24:30897 extensions::ImageLoader* loader = extensions::ImageLoader::Get(profile_);
[email protected]0d0ba182014-06-03 12:40:43898
899 std::vector<extensions::ImageLoader::ImageRepresentation> images_list;
900 images_list.push_back(extensions::ImageLoader::ImageRepresentation(
901 image,
902 extensions::ImageLoader::ImageRepresentation::NEVER_RESIZE,
903 gfx::Size(),
904 ui::SCALE_FACTOR_100P));
905 loader->LoadImagesAsync(
906 extension_,
907 images_list,
[email protected]ec7de0c5a2012-11-16 07:40:47908 base::Bind(&ExtensionInstallPrompt::OnImageLoaded, AsWeakPtr()));
[email protected]c82da8c42012-06-08 19:49:11909}
910
911void ExtensionInstallPrompt::ShowConfirmation() {
[email protected]d382baa2014-06-17 18:50:01912 if (prompt_->type() == INSTALL_PROMPT)
913 prompt_->set_experiment(ExtensionInstallPromptExperiment::Find());
[email protected]62a28d7c2013-12-28 01:34:49914 else
[email protected]d382baa2014-06-17 18:50:01915 prompt_->set_experiment(ExtensionInstallPromptExperiment::ControlGroup());
[email protected]62a28d7c2013-12-28 01:34:49916
gpdavis.chromium0fbac4d2014-09-19 20:57:54917 scoped_refptr<const PermissionSet> permissions_to_display;
918 if (custom_permissions_.get()) {
919 permissions_to_display = custom_permissions_;
920 } else if (extension_) {
921 // Initialize permissions if they have not already been set so that
922 // withheld permissions are displayed properly in the install prompt.
923 extensions::PermissionsUpdater(
pkotwicza57a1f322014-10-21 00:24:30924 profile_, extensions::PermissionsUpdater::INIT_FLAG_TRANSIENT)
gpdavis.chromium0fbac4d2014-09-19 20:57:54925 .InitializePermissions(extension_);
926 permissions_to_display =
927 extension_->permissions_data()->active_permissions();
treib7496f63c2015-03-04 12:18:53928 // For delegated installs, all optional permissions are pre-approved by the
929 // person who triggers the install, so add them to the list.
930 if (prompt_->type() == DELEGATED_PERMISSIONS_PROMPT) {
931 scoped_refptr<const PermissionSet> optional_permissions =
932 extensions::PermissionsParser::GetOptionalPermissions(extension_);
933 permissions_to_display = PermissionSet::CreateUnion(
934 permissions_to_display.get(),
935 optional_permissions.get());
936 }
gpdavis.chromium0fbac4d2014-09-19 20:57:54937 }
938
939 if (permissions_to_display.get() &&
[email protected]a397ec02014-08-08 15:48:13940 (!extension_ ||
941 !extensions::PermissionsData::ShouldSkipPermissionWarnings(
942 extension_->id()))) {
943 Manifest::Type type =
944 extension_ ? extension_->GetType() : Manifest::TYPE_UNKNOWN;
945 const extensions::PermissionMessageProvider* message_provider =
946 extensions::PermissionMessageProvider::Get();
gpdavis.chromium0fbac4d2014-09-19 20:57:54947 prompt_->SetPermissions(message_provider->GetWarningMessages(
948 permissions_to_display.get(), type),
949 REGULAR_PERMISSIONS);
950 prompt_->SetPermissionsDetails(message_provider->GetWarningMessagesDetails(
951 permissions_to_display.get(), type),
952 REGULAR_PERMISSIONS);
953
954 scoped_refptr<const extensions::PermissionSet> withheld =
955 extension_->permissions_data()->withheld_permissions();
956 if (!withheld->IsEmpty()) {
957 prompt_->SetPermissions(
958 message_provider->GetWarningMessages(withheld.get(), type),
959 PermissionsType::WITHHELD_PERMISSIONS);
960 prompt_->SetPermissionsDetails(
961 message_provider->GetWarningMessagesDetails(withheld.get(), type),
962 PermissionsType::WITHHELD_PERMISSIONS);
963 }
[email protected]bebe1d02012-08-02 20:17:09964 }
[email protected]c82da8c42012-06-08 19:49:11965
[email protected]d382baa2014-06-17 18:50:01966 switch (prompt_->type()) {
[email protected]c82da8c42012-06-08 19:49:11967 case PERMISSIONS_PROMPT:
968 case RE_ENABLE_PROMPT:
969 case INLINE_INSTALL_PROMPT:
[email protected]612a1cb12012-10-17 13:18:03970 case EXTERNAL_INSTALL_PROMPT:
[email protected]15d267b42013-02-14 23:43:32971 case INSTALL_PROMPT:
[email protected]1a93d8d2013-10-27 23:09:20972 case LAUNCH_PROMPT:
[email protected]21db9ef2014-05-16 02:06:27973 case POST_INSTALL_PERMISSIONS_PROMPT:
rdevlin.cronin5f6b69d2014-09-20 01:23:35974 case REMOTE_INSTALL_PROMPT:
treib2d2f5372015-03-01 12:20:49975 case REPAIR_PROMPT:
976 case DELEGATED_PERMISSIONS_PROMPT: {
[email protected]d382baa2014-06-17 18:50:01977 prompt_->set_extension(extension_);
978 prompt_->set_icon(gfx::Image::CreateFrom1xBitmap(icon_));
treib2d2f5372015-03-01 12:20:49979 prompt_->set_delegated_username(delegated_username_);
[email protected]c82da8c42012-06-08 19:49:11980 break;
981 }
982 case BUNDLE_INSTALL_PROMPT: {
[email protected]d382baa2014-06-17 18:50:01983 prompt_->set_bundle(bundle_);
[email protected]c82da8c42012-06-08 19:49:11984 break;
985 }
986 default:
987 NOTREACHED() << "Unknown message";
[email protected]af6efb22012-10-12 02:23:05988 return;
[email protected]c82da8c42012-06-08 19:49:11989 }
[email protected]af6efb22012-10-12 02:23:05990
rdevlin.cronin092c6772014-11-20 23:52:40991 g_last_prompt_type_for_tests = prompt_->type();
992
[email protected]af6efb22012-10-12 02:23:05993 if (AutoConfirmPrompt(delegate_))
994 return;
995
pkotwicz2f181782014-10-29 17:33:45996 if (show_params_->WasParentDestroyed()) {
997 delegate_->InstallUIAbort(false);
998 return;
999 }
1000
[email protected]5db2e882012-12-20 10:17:261001 if (show_dialog_callback_.is_null())
pkotwicz2f181782014-10-29 17:33:451002 GetDefaultShowDialogCallback().Run(show_params_.get(), delegate_, prompt_);
[email protected]5db2e882012-12-20 10:17:261003 else
pkotwicz2f181782014-10-29 17:33:451004 show_dialog_callback_.Run(show_params_.get(), delegate_, prompt_);
[email protected]c82da8c42012-06-08 19:49:111005}