blob: 5599116564692e1df6e0cfa59ca2c4f7268ec326 [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"
rdevlin.cronin66209492015-06-10 20:44:0527#include "extensions/browser/extension_dialog_auto_confirm.h"
[email protected]21db9ef2014-05-16 02:06:2728#include "extensions/browser/extension_prefs.h"
[email protected]411f8ae2014-05-22 11:12:2329#include "extensions/browser/extension_util.h"
[email protected]326e6f02014-06-20 04:53:3730#include "extensions/browser/image_loader.h"
pkotwicza57a1f322014-10-21 00:24:3031#include "extensions/browser/install/extension_install_ui.h"
[email protected]cda103d2014-04-04 16:22:3932#include "extensions/common/constants.h"
[email protected]e4452d32013-11-15 23:07:4133#include "extensions/common/extension.h"
[email protected]4b7908842014-04-07 23:50:2234#include "extensions/common/extension_icon_set.h"
[email protected]993da5e2013-03-23 21:25:1635#include "extensions/common/extension_resource.h"
[email protected]5ef835a2013-11-08 20:42:5736#include "extensions/common/feature_switch.h"
[email protected]d42c11152013-08-22 19:36:3237#include "extensions/common/manifest.h"
[email protected]6bf90612013-08-15 00:36:2738#include "extensions/common/manifest_constants.h"
[email protected]0db486f2014-04-09 19:32:2239#include "extensions/common/manifest_handlers/icons_handler.h"
treib7496f63c2015-03-04 12:18:5340#include "extensions/common/manifest_handlers/permissions_parser.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;
treib7b45a34b2015-04-16 11:48:0253using extensions::PermissionMessageString;
54using extensions::PermissionMessageStrings;
[email protected]c2e66e12012-06-27 06:27:0655using extensions::PermissionSet;
[email protected]c82da8c42012-06-08 19:49:1156
[email protected]612a1cb12012-10-17 13:18:0357namespace {
58
rdevlin.cronin5f6b69d2014-09-20 01:23:3559bool AllowWebstoreData(ExtensionInstallPrompt::PromptType type) {
60 return type == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT ||
61 type == ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT ||
62 type == ExtensionInstallPrompt::REPAIR_PROMPT;
63}
64
[email protected]c82da8c42012-06-08 19:49:1165static const int kTitleIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2766 0, // The regular install prompt depends on what's being installed.
67 IDS_EXTENSION_INLINE_INSTALL_PROMPT_TITLE,
68 IDS_EXTENSION_INSTALL_PROMPT_TITLE,
69 IDS_EXTENSION_RE_ENABLE_PROMPT_TITLE,
70 IDS_EXTENSION_PERMISSIONS_PROMPT_TITLE,
71 IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_TITLE,
72 IDS_EXTENSION_POST_INSTALL_PERMISSIONS_PROMPT_TITLE,
73 IDS_EXTENSION_LAUNCH_APP_PROMPT_TITLE,
74 0, // The remote install prompt depends on what's being installed.
rdevlin.cronin5f6b69d2014-09-20 01:23:3575 0, // The repair install prompt depends on what's being installed.
treib2d2f5372015-03-01 12:20:4976 0, // The delegated install prompt depends on what's being installed.
[email protected]c82da8c42012-06-08 19:49:1177};
78static const int kHeadingIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2779 IDS_EXTENSION_INSTALL_PROMPT_HEADING,
80 0, // Inline installs use the extension name.
81 0, // Heading for bundle installs depends on the bundle contents.
82 IDS_EXTENSION_RE_ENABLE_PROMPT_HEADING,
83 IDS_EXTENSION_PERMISSIONS_PROMPT_HEADING,
84 0, // External installs use different strings for extensions/apps.
85 IDS_EXTENSION_POST_INSTALL_PERMISSIONS_PROMPT_HEADING,
86 IDS_EXTENSION_LAUNCH_APP_PROMPT_HEADING,
87 IDS_EXTENSION_REMOTE_INSTALL_PROMPT_HEADING,
treib2d2f5372015-03-01 12:20:4988 IDS_EXTENSION_REPAIR_PROMPT_HEADING,
89 IDS_EXTENSION_INSTALL_PROMPT_HEADING,
[email protected]15d267b42013-02-14 23:43:3290};
91static const int kButtons[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2792 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_OK | ui::DIALOG_BUTTON_CANCEL,
97 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
98 ui::DIALOG_BUTTON_CANCEL,
99 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
100 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
rdevlin.cronin5f6b69d2014-09-20 01:23:35101 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
treib2d2f5372015-03-01 12:20:49102 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
[email protected]c82da8c42012-06-08 19:49:11103};
104static const int kAcceptButtonIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:27105 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
106 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
107 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
108 IDS_EXTENSION_PROMPT_RE_ENABLE_BUTTON,
109 IDS_EXTENSION_PROMPT_PERMISSIONS_BUTTON,
110 0, // External installs use different strings for extensions/apps.
reillygc64d3dd2014-09-29 21:10:11111 0, // Different strings depending on the files and devices retained.
[email protected]21db9ef2014-05-16 02:06:27112 IDS_EXTENSION_PROMPT_LAUNCH_BUTTON,
113 IDS_EXTENSION_PROMPT_REMOTE_INSTALL_BUTTON,
rdevlin.cronin5f6b69d2014-09-20 01:23:35114 IDS_EXTENSION_PROMPT_REPAIR_BUTTON,
treib2d2f5372015-03-01 12:20:49115 IDS_EXTENSION_PROMPT_PERMISSIONS_BUTTON,
[email protected]c82da8c42012-06-08 19:49:11116};
117static const int kAbortButtonIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:27118 0, // These all use the platform's default cancel label.
119 0,
120 0,
121 0,
122 IDS_EXTENSION_PROMPT_PERMISSIONS_ABORT_BUTTON,
123 IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ABORT_BUTTON,
124 IDS_CLOSE,
125 0, // Platform dependent cancel button.
126 0,
rdevlin.cronin5f6b69d2014-09-20 01:23:35127 0,
treib2d2f5372015-03-01 12:20:49128 IDS_EXTENSION_PROMPT_PERMISSIONS_ABORT_BUTTON,
[email protected]c82da8c42012-06-08 19:49:11129};
[email protected]21db9ef2014-05-16 02:06:27130static const int
131 kPermissionsHeaderIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
132 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
133 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
134 IDS_EXTENSION_PROMPT_THESE_WILL_HAVE_ACCESS_TO,
135 IDS_EXTENSION_PROMPT_WILL_NOW_HAVE_ACCESS_TO,
136 IDS_EXTENSION_PROMPT_WANTS_ACCESS_TO,
137 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
138 IDS_EXTENSION_PROMPT_CAN_ACCESS,
139 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
140 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
rdevlin.cronin5f6b69d2014-09-20 01:23:35141 IDS_EXTENSION_PROMPT_CAN_ACCESS,
treib2d2f5372015-03-01 12:20:49142 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
[email protected]c82da8c42012-06-08 19:49:11143};
144
[email protected]dd46a4ce2012-09-15 10:50:50145// Returns bitmap for the default icon with size equal to the default icon's
146// pixel size under maximal supported scale factor.
147SkBitmap GetDefaultIconBitmapForMaxScaleFactor(bool is_app) {
[email protected]702d8b42013-02-27 20:55:50148 const gfx::ImageSkia& image = is_app ?
[email protected]7eb20e32014-04-30 08:50:56149 extensions::util::GetDefaultAppIcon() :
150 extensions::util::GetDefaultExtensionIcon();
[email protected]50b66262013-09-24 03:25:48151 return image.GetRepresentation(
152 gfx::ImageSkia::GetMaxSupportedScale()).sk_bitmap();
[email protected]dd46a4ce2012-09-15 10:50:50153}
154
[email protected]af6efb22012-10-12 02:23:05155// If auto confirm is enabled then posts a task to proceed with or cancel the
156// install and returns true. Otherwise returns false.
157bool AutoConfirmPrompt(ExtensionInstallPrompt::Delegate* delegate) {
rdevlin.cronin66209492015-06-10 20:44:05158 switch (extensions::ScopedTestDialogAutoConfirm::GetAutoConfirmValue()) {
159 case extensions::ScopedTestDialogAutoConfirm::NONE:
160 LOG(WARNING) << "None!";
[email protected]2a74d6f62014-07-24 11:53:47161 return false;
162 // We use PostTask instead of calling the delegate directly here, because in
163 // the real implementations it's highly likely the message loop will be
164 // pumping a few times before the user clicks accept or cancel.
rdevlin.cronin66209492015-06-10 20:44:05165 case extensions::ScopedTestDialogAutoConfirm::ACCEPT:
166 LOG(WARNING) << "Proceeding!";
[email protected]2a74d6f62014-07-24 11:53:47167 base::MessageLoop::current()->PostTask(
168 FROM_HERE,
169 base::Bind(&ExtensionInstallPrompt::Delegate::InstallUIProceed,
170 base::Unretained(delegate)));
171 return true;
rdevlin.cronin66209492015-06-10 20:44:05172 case extensions::ScopedTestDialogAutoConfirm::CANCEL:
173 LOG(WARNING) << "Canceling!";
[email protected]2a74d6f62014-07-24 11:53:47174 base::MessageLoop::current()->PostTask(
175 FROM_HERE,
176 base::Bind(&ExtensionInstallPrompt::Delegate::InstallUIAbort,
177 base::Unretained(delegate),
178 true));
179 return true;
[email protected]af6efb22012-10-12 02:23:05180 }
181
182 NOTREACHED();
183 return false;
184}
185
[email protected]91e51d612012-10-21 23:03:05186Profile* ProfileForWebContents(content::WebContents* web_contents) {
187 if (!web_contents)
188 return NULL;
189 return Profile::FromBrowserContext(web_contents->GetBrowserContext());
190}
191
[email protected]c82da8c42012-06-08 19:49:11192} // namespace
193
gpdavis.chromium0fbac4d2014-09-19 20:57:54194ExtensionInstallPrompt::Prompt::InstallPromptPermissions::
195 InstallPromptPermissions() {
196}
197ExtensionInstallPrompt::Prompt::InstallPromptPermissions::
198 ~InstallPromptPermissions() {
199}
200
rdevlin.cronin092c6772014-11-20 23:52:40201ExtensionInstallPrompt::PromptType
202ExtensionInstallPrompt::g_last_prompt_type_for_tests =
203 ExtensionInstallPrompt::UNSET_PROMPT_TYPE;
204
[email protected]eeb0d3e12014-08-15 15:10:44205// This should match the PromptType enum.
206std::string ExtensionInstallPrompt::PromptTypeToString(PromptType type) {
207 switch (type) {
208 case ExtensionInstallPrompt::INSTALL_PROMPT:
209 return "INSTALL_PROMPT";
210 case ExtensionInstallPrompt::INLINE_INSTALL_PROMPT:
211 return "INLINE_INSTALL_PROMPT";
212 case ExtensionInstallPrompt::BUNDLE_INSTALL_PROMPT:
213 return "BUNDLE_INSTALL_PROMPT";
214 case ExtensionInstallPrompt::RE_ENABLE_PROMPT:
215 return "RE_ENABLE_PROMPT";
216 case ExtensionInstallPrompt::PERMISSIONS_PROMPT:
217 return "PERMISSIONS_PROMPT";
218 case ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT:
219 return "EXTERNAL_INSTALL_PROMPT";
220 case ExtensionInstallPrompt::POST_INSTALL_PERMISSIONS_PROMPT:
221 return "POST_INSTALL_PERMISSIONS_PROMPT";
222 case ExtensionInstallPrompt::LAUNCH_PROMPT:
223 return "LAUNCH_PROMPT";
224 case ExtensionInstallPrompt::REMOTE_INSTALL_PROMPT:
225 return "REMOTE_INSTALL_PROMPT";
rdevlin.cronin5f6b69d2014-09-20 01:23:35226 case ExtensionInstallPrompt::REPAIR_PROMPT:
227 return "REPAIR_PROMPT";
treib2d2f5372015-03-01 12:20:49228 case ExtensionInstallPrompt::DELEGATED_PERMISSIONS_PROMPT:
229 return "DELEGATED_PERMISSIONS_PROMPT";
[email protected]eeb0d3e12014-08-15 15:10:44230 case ExtensionInstallPrompt::UNSET_PROMPT_TYPE:
231 case ExtensionInstallPrompt::NUM_PROMPT_TYPES:
232 break;
233 }
234 return "OTHER";
235}
236
[email protected]5db2e882012-12-20 10:17:26237ExtensionInstallPrompt::Prompt::Prompt(PromptType type)
[email protected]c82da8c42012-06-08 19:49:11238 : type_(type),
[email protected]79a6f99a2013-08-29 00:32:58239 is_showing_details_for_retained_files_(false),
reillygc64d3dd2014-09-29 21:10:11240 is_showing_details_for_retained_devices_(false),
[email protected]c82da8c42012-06-08 19:49:11241 extension_(NULL),
242 bundle_(NULL),
243 average_rating_(0.0),
[email protected]dcde34b32013-07-31 02:28:45244 rating_count_(0),
[email protected]34b5f7f2014-01-29 02:48:11245 show_user_count_(false),
246 has_webstore_data_(false) {
[email protected]c82da8c42012-06-08 19:49:11247}
248
249ExtensionInstallPrompt::Prompt::~Prompt() {
250}
251
252void ExtensionInstallPrompt::Prompt::SetPermissions(
treib7b45a34b2015-04-16 11:48:02253 const PermissionMessageStrings& permissions,
gpdavis.chromium0fbac4d2014-09-19 20:57:54254 PermissionsType permissions_type) {
255 InstallPromptPermissions& install_permissions =
256 GetPermissionsForType(permissions_type);
sashabeabd5df2014-11-06 02:38:25257
treib7b45a34b2015-04-16 11:48:02258 install_permissions.permissions.clear();
259 install_permissions.details.clear();
260 install_permissions.is_showing_details.clear();
sashabeabd5df2014-11-06 02:38:25261
treib7b45a34b2015-04-16 11:48:02262 for (const PermissionMessageString& str : permissions) {
263 install_permissions.permissions.push_back(str.message);
264 // Add a dash to the front of each permission detail.
265 base::string16 details;
266 if (!str.submessages.empty()) {
sashabeabd5df2014-11-06 02:38:25267 std::vector<base::string16> detail_lines_with_bullets;
treib7b45a34b2015-04-16 11:48:02268 for (const auto& detail_line : str.submessages) {
sashabeabd5df2014-11-06 02:38:25269 detail_lines_with_bullets.push_back(base::ASCIIToUTF16("- ") +
270 detail_line);
treib7b45a34b2015-04-16 11:48:02271 }
sashabeabd5df2014-11-06 02:38:25272
treib7b45a34b2015-04-16 11:48:02273 details = JoinString(detail_lines_with_bullets, '\n');
sashabeabd5df2014-11-06 02:38:25274 }
treib7b45a34b2015-04-16 11:48:02275 install_permissions.details.push_back(details);
276 install_permissions.is_showing_details.push_back(false);
sashabeabd5df2014-11-06 02:38:25277 }
[email protected]79a6f99a2013-08-29 00:32:58278}
279
280void ExtensionInstallPrompt::Prompt::SetIsShowingDetails(
281 DetailsType type,
282 size_t index,
283 bool is_showing_details) {
284 switch (type) {
285 case PERMISSIONS_DETAILS:
gpdavis.chromium0fbac4d2014-09-19 20:57:54286 prompt_permissions_.is_showing_details[index] = is_showing_details;
287 break;
288 case WITHHELD_PERMISSIONS_DETAILS:
289 withheld_prompt_permissions_.is_showing_details[index] =
290 is_showing_details;
[email protected]79a6f99a2013-08-29 00:32:58291 break;
[email protected]79a6f99a2013-08-29 00:32:58292 case RETAINED_FILES_DETAILS:
293 is_showing_details_for_retained_files_ = is_showing_details;
294 break;
reillygc64d3dd2014-09-29 21:10:11295 case RETAINED_DEVICES_DETAILS:
296 is_showing_details_for_retained_devices_ = is_showing_details;
297 break;
[email protected]79a6f99a2013-08-29 00:32:58298 }
[email protected]8ab7e6c2013-07-11 21:15:03299}
300
[email protected]34b5f7f2014-01-29 02:48:11301void ExtensionInstallPrompt::Prompt::SetWebstoreData(
[email protected]c82da8c42012-06-08 19:49:11302 const std::string& localized_user_count,
[email protected]dcde34b32013-07-31 02:28:45303 bool show_user_count,
[email protected]c82da8c42012-06-08 19:49:11304 double average_rating,
305 int rating_count) {
rdevlin.cronin5f6b69d2014-09-20 01:23:35306 CHECK(AllowWebstoreData(type_));
[email protected]c82da8c42012-06-08 19:49:11307 localized_user_count_ = localized_user_count;
[email protected]dcde34b32013-07-31 02:28:45308 show_user_count_ = show_user_count;
[email protected]c82da8c42012-06-08 19:49:11309 average_rating_ = average_rating;
310 rating_count_ = rating_count;
[email protected]34b5f7f2014-01-29 02:48:11311 has_webstore_data_ = true;
[email protected]c82da8c42012-06-08 19:49:11312}
313
[email protected]6a72a632013-12-12 22:22:00314base::string16 ExtensionInstallPrompt::Prompt::GetDialogTitle() const {
[email protected]c82da8c42012-06-08 19:49:11315 int resource_id = kTitleIds[type_];
316
317 if (type_ == INSTALL_PROMPT) {
318 if (extension_->is_app())
319 resource_id = IDS_EXTENSION_INSTALL_APP_PROMPT_TITLE;
320 else if (extension_->is_theme())
321 resource_id = IDS_EXTENSION_INSTALL_THEME_PROMPT_TITLE;
322 else
323 resource_id = IDS_EXTENSION_INSTALL_EXTENSION_PROMPT_TITLE;
[email protected]612a1cb12012-10-17 13:18:03324 } else if (type_ == EXTERNAL_INSTALL_PROMPT) {
325 return l10n_util::GetStringFUTF16(
[email protected]04338722013-12-24 23:18:05326 resource_id, base::UTF8ToUTF16(extension_->name()));
[email protected]21db9ef2014-05-16 02:06:27327 } else if (type_ == REMOTE_INSTALL_PROMPT) {
328 if (extension_->is_app())
329 resource_id = IDS_EXTENSION_REMOTE_INSTALL_APP_PROMPT_TITLE;
330 else
331 resource_id = IDS_EXTENSION_REMOTE_INSTALL_EXTENSION_PROMPT_TITLE;
rdevlin.cronin5f6b69d2014-09-20 01:23:35332 } else if (type_ == REPAIR_PROMPT) {
333 if (extension_->is_app())
334 resource_id = IDS_EXTENSION_REPAIR_APP_PROMPT_TITLE;
335 else
336 resource_id = IDS_EXTENSION_REPAIR_EXTENSION_PROMPT_TITLE;
treib2d2f5372015-03-01 12:20:49337 } else if (type_ == DELEGATED_PERMISSIONS_PROMPT) {
338 DCHECK(!delegated_username_.empty());
339 if (extension_->is_app())
340 resource_id = IDS_EXTENSION_DELEGATED_INSTALL_APP_PROMPT_TITLE;
341 else
342 resource_id = IDS_EXTENSION_DELEGATED_INSTALL_EXTENSION_PROMPT_TITLE;
343 return l10n_util::GetStringFUTF16(
344 resource_id, base::UTF8ToUTF16(delegated_username_));
[email protected]c82da8c42012-06-08 19:49:11345 }
346
347 return l10n_util::GetStringUTF16(resource_id);
348}
349
[email protected]6a72a632013-12-12 22:22:00350base::string16 ExtensionInstallPrompt::Prompt::GetHeading() const {
[email protected]c82da8c42012-06-08 19:49:11351 if (type_ == INLINE_INSTALL_PROMPT) {
[email protected]04338722013-12-24 23:18:05352 return base::UTF8ToUTF16(extension_->name());
[email protected]c82da8c42012-06-08 19:49:11353 } else if (type_ == BUNDLE_INSTALL_PROMPT) {
354 return bundle_->GetHeadingTextFor(BundleInstaller::Item::STATE_PENDING);
[email protected]612a1cb12012-10-17 13:18:03355 } else if (type_ == EXTERNAL_INSTALL_PROMPT) {
[email protected]846606012012-10-19 18:42:25356 int resource_id = -1;
357 if (extension_->is_app())
358 resource_id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_HEADING_APP;
359 else if (extension_->is_theme())
360 resource_id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_HEADING_THEME;
361 else
362 resource_id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_HEADING_EXTENSION;
363 return l10n_util::GetStringUTF16(resource_id);
[email protected]c82da8c42012-06-08 19:49:11364 } else {
365 return l10n_util::GetStringFUTF16(
[email protected]04338722013-12-24 23:18:05366 kHeadingIds[type_], base::UTF8ToUTF16(extension_->name()));
[email protected]c82da8c42012-06-08 19:49:11367 }
368}
369
[email protected]15d267b42013-02-14 23:43:32370int ExtensionInstallPrompt::Prompt::GetDialogButtons() const {
reillygc64d3dd2014-09-29 21:10:11371 if (type_ == POST_INSTALL_PERMISSIONS_PROMPT && ShouldDisplayRevokeButton()) {
[email protected]a2886e8b2013-06-08 05:15:02372 return kButtons[type_] | ui::DIALOG_BUTTON_OK;
373 }
374
[email protected]15d267b42013-02-14 23:43:32375 return kButtons[type_];
376}
377
378bool ExtensionInstallPrompt::Prompt::HasAcceptButtonLabel() const {
reillygc64d3dd2014-09-29 21:10:11379 if (type_ == POST_INSTALL_PERMISSIONS_PROMPT)
380 return ShouldDisplayRevokeButton();
381
[email protected]a2886e8b2013-06-08 05:15:02382 if (kAcceptButtonIds[type_] == 0)
383 return false;
384
[email protected]a2886e8b2013-06-08 05:15:02385 return true;
[email protected]15d267b42013-02-14 23:43:32386}
387
[email protected]6a72a632013-12-12 22:22:00388base::string16 ExtensionInstallPrompt::Prompt::GetAcceptButtonLabel() const {
[email protected]846606012012-10-19 18:42:25389 if (type_ == EXTERNAL_INSTALL_PROMPT) {
390 int id = -1;
391 if (extension_->is_app())
392 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_APP;
393 else if (extension_->is_theme())
394 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_THEME;
395 else
396 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_EXTENSION;
397 return l10n_util::GetStringUTF16(id);
reillygc64d3dd2014-09-29 21:10:11398 } else if (type_ == POST_INSTALL_PERMISSIONS_PROMPT) {
399 int id = -1;
400 if (GetRetainedFileCount() && GetRetainedDeviceCount()) {
401 id =
402 IDS_EXTENSION_PROMPT_PERMISSIONS_CLEAR_RETAINED_FILES_AND_DEVICES_BUTTON;
403 } else if (GetRetainedFileCount()) {
404 id = IDS_EXTENSION_PROMPT_PERMISSIONS_CLEAR_RETAINED_FILES_BUTTON;
405 } else {
406 DCHECK_LT(0U, GetRetainedDeviceCount());
407 id = IDS_EXTENSION_PROMPT_PERMISSIONS_CLEAR_RETAINED_DEVICES_BUTTON;
408 }
409 return l10n_util::GetStringUTF16(id);
[email protected]846606012012-10-19 18:42:25410 }
[email protected]c82da8c42012-06-08 19:49:11411 return l10n_util::GetStringUTF16(kAcceptButtonIds[type_]);
412}
413
414bool ExtensionInstallPrompt::Prompt::HasAbortButtonLabel() const {
415 return kAbortButtonIds[type_] > 0;
416}
417
[email protected]6a72a632013-12-12 22:22:00418base::string16 ExtensionInstallPrompt::Prompt::GetAbortButtonLabel() const {
[email protected]c82da8c42012-06-08 19:49:11419 CHECK(HasAbortButtonLabel());
420 return l10n_util::GetStringUTF16(kAbortButtonIds[type_]);
421}
422
gpdavis.chromium0fbac4d2014-09-19 20:57:54423base::string16 ExtensionInstallPrompt::Prompt::GetPermissionsHeading(
424 PermissionsType permissions_type) const {
425 switch (permissions_type) {
426 case REGULAR_PERMISSIONS:
427 return l10n_util::GetStringUTF16(kPermissionsHeaderIds[type_]);
428 case WITHHELD_PERMISSIONS:
429 return l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WITHHELD);
430 case ALL_PERMISSIONS:
431 default:
432 NOTREACHED();
433 return base::string16();
434 }
[email protected]c82da8c42012-06-08 19:49:11435}
436
[email protected]6a72a632013-12-12 22:22:00437base::string16 ExtensionInstallPrompt::Prompt::GetRetainedFilesHeading() const {
jshin3a6c36bb2015-04-09 21:58:08438 return l10n_util::GetPluralStringFUTF16(
439 IDS_EXTENSION_PROMPT_RETAINED_FILES, GetRetainedFileCount());
[email protected]8ab7e6c2013-07-11 21:15:03440}
441
reillygc64d3dd2014-09-29 21:10:11442base::string16 ExtensionInstallPrompt::Prompt::GetRetainedDevicesHeading()
443 const {
jshin3a6c36bb2015-04-09 21:58:08444 return l10n_util::GetPluralStringFUTF16(
445 IDS_EXTENSION_PROMPT_RETAINED_DEVICES, GetRetainedDeviceCount());
reillygc64d3dd2014-09-29 21:10:11446}
447
[email protected]f2cd8992013-06-11 17:30:18448bool ExtensionInstallPrompt::Prompt::ShouldShowPermissions() const {
gpdavis.chromium0fbac4d2014-09-19 20:57:54449 return GetPermissionCount(ALL_PERMISSIONS) > 0 ||
450 type_ == POST_INSTALL_PERMISSIONS_PROMPT;
[email protected]f2cd8992013-06-11 17:30:18451}
452
[email protected]c82da8c42012-06-08 19:49:11453void ExtensionInstallPrompt::Prompt::AppendRatingStars(
454 StarAppender appender, void* data) const {
455 CHECK(appender);
rdevlin.cronin5f6b69d2014-09-20 01:23:35456 CHECK(AllowWebstoreData(type_));
[email protected]c82da8c42012-06-08 19:49:11457 int rating_integer = floor(average_rating_);
458 double rating_fractional = average_rating_ - rating_integer;
459
460 if (rating_fractional > 0.66) {
461 rating_integer++;
462 }
463
464 if (rating_fractional < 0.33 || rating_fractional > 0.66) {
465 rating_fractional = 0;
466 }
467
468 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
469 int i;
470 for (i = 0; i < rating_integer; i++) {
471 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_ON), data);
472 }
473 if (rating_fractional) {
474 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_HALF_LEFT), data);
475 i++;
476 }
477 for (; i < kMaxExtensionRating; i++) {
478 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_OFF), data);
479 }
480}
481
[email protected]6a72a632013-12-12 22:22:00482base::string16 ExtensionInstallPrompt::Prompt::GetRatingCount() const {
rdevlin.cronin5f6b69d2014-09-20 01:23:35483 CHECK(AllowWebstoreData(type_));
[email protected]6725048e2013-10-24 21:47:14484 return l10n_util::GetStringFUTF16(IDS_EXTENSION_RATING_COUNT,
485 base::IntToString16(rating_count_));
[email protected]c82da8c42012-06-08 19:49:11486}
487
[email protected]6a72a632013-12-12 22:22:00488base::string16 ExtensionInstallPrompt::Prompt::GetUserCount() const {
rdevlin.cronin5f6b69d2014-09-20 01:23:35489 CHECK(AllowWebstoreData(type_));
[email protected]dcde34b32013-07-31 02:28:45490
491 if (show_user_count_) {
[email protected]6725048e2013-10-24 21:47:14492 return l10n_util::GetStringFUTF16(IDS_EXTENSION_USER_COUNT,
493 base::UTF8ToUTF16(localized_user_count_));
[email protected]dcde34b32013-07-31 02:28:45494 }
[email protected]6725048e2013-10-24 21:47:14495 return base::string16();
[email protected]c82da8c42012-06-08 19:49:11496}
497
gpdavis.chromium0fbac4d2014-09-19 20:57:54498size_t ExtensionInstallPrompt::Prompt::GetPermissionCount(
499 PermissionsType permissions_type) const {
500 switch (permissions_type) {
501 case REGULAR_PERMISSIONS:
502 return prompt_permissions_.permissions.size();
503 case WITHHELD_PERMISSIONS:
504 return withheld_prompt_permissions_.permissions.size();
505 case ALL_PERMISSIONS:
506 return prompt_permissions_.permissions.size() +
507 withheld_prompt_permissions_.permissions.size();
508 default:
509 NOTREACHED();
510 return 0u;
511 }
[email protected]c82da8c42012-06-08 19:49:11512}
513
gpdavis.chromium0fbac4d2014-09-19 20:57:54514size_t ExtensionInstallPrompt::Prompt::GetPermissionsDetailsCount(
515 PermissionsType permissions_type) const {
516 switch (permissions_type) {
517 case REGULAR_PERMISSIONS:
518 return prompt_permissions_.details.size();
519 case WITHHELD_PERMISSIONS:
520 return withheld_prompt_permissions_.details.size();
521 case ALL_PERMISSIONS:
522 return prompt_permissions_.details.size() +
523 withheld_prompt_permissions_.details.size();
524 default:
525 NOTREACHED();
526 return 0u;
527 }
[email protected]8ab7e6c2013-07-11 21:15:03528}
529
gpdavis.chromium0fbac4d2014-09-19 20:57:54530base::string16 ExtensionInstallPrompt::Prompt::GetPermission(
531 size_t index,
532 PermissionsType permissions_type) const {
533 const InstallPromptPermissions& install_permissions =
534 GetPermissionsForType(permissions_type);
535 CHECK_LT(index, install_permissions.permissions.size());
536 return install_permissions.permissions[index];
[email protected]c82da8c42012-06-08 19:49:11537}
538
[email protected]6a72a632013-12-12 22:22:00539base::string16 ExtensionInstallPrompt::Prompt::GetPermissionsDetails(
gpdavis.chromium0fbac4d2014-09-19 20:57:54540 size_t index,
541 PermissionsType permissions_type) const {
542 const InstallPromptPermissions& install_permissions =
543 GetPermissionsForType(permissions_type);
544 CHECK_LT(index, install_permissions.details.size());
545 return install_permissions.details[index];
[email protected]8ab7e6c2013-07-11 21:15:03546}
547
[email protected]79a6f99a2013-08-29 00:32:58548bool ExtensionInstallPrompt::Prompt::GetIsShowingDetails(
549 DetailsType type, size_t index) const {
550 switch (type) {
551 case PERMISSIONS_DETAILS:
gpdavis.chromium0fbac4d2014-09-19 20:57:54552 CHECK_LT(index, prompt_permissions_.is_showing_details.size());
553 return prompt_permissions_.is_showing_details[index];
554 case WITHHELD_PERMISSIONS_DETAILS:
555 CHECK_LT(index, withheld_prompt_permissions_.is_showing_details.size());
556 return withheld_prompt_permissions_.is_showing_details[index];
[email protected]79a6f99a2013-08-29 00:32:58557 case RETAINED_FILES_DETAILS:
558 return is_showing_details_for_retained_files_;
reillygc64d3dd2014-09-29 21:10:11559 case RETAINED_DEVICES_DETAILS:
560 return is_showing_details_for_retained_devices_;
[email protected]79a6f99a2013-08-29 00:32:58561 }
562 return false;
563}
564
[email protected]a2886e8b2013-06-08 05:15:02565size_t ExtensionInstallPrompt::Prompt::GetRetainedFileCount() const {
566 return retained_files_.size();
567}
568
[email protected]6a72a632013-12-12 22:22:00569base::string16 ExtensionInstallPrompt::Prompt::GetRetainedFile(size_t index)
570 const {
[email protected]a2886e8b2013-06-08 05:15:02571 CHECK_LT(index, retained_files_.size());
[email protected]6725048e2013-10-24 21:47:14572 return retained_files_[index].AsUTF16Unsafe();
[email protected]a2886e8b2013-06-08 05:15:02573}
574
reillygc64d3dd2014-09-29 21:10:11575size_t ExtensionInstallPrompt::Prompt::GetRetainedDeviceCount() const {
576 return retained_device_messages_.size();
577}
578
579base::string16 ExtensionInstallPrompt::Prompt::GetRetainedDeviceMessageString(
580 size_t index) const {
581 CHECK_LT(index, retained_device_messages_.size());
582 return retained_device_messages_[index];
583}
584
585bool ExtensionInstallPrompt::Prompt::ShouldDisplayRevokeButton() const {
586 return !retained_files_.empty() || !retained_device_messages_.empty();
587}
588
gpdavis.chromium0fbac4d2014-09-19 20:57:54589ExtensionInstallPrompt::Prompt::InstallPromptPermissions&
590ExtensionInstallPrompt::Prompt::GetPermissionsForType(
591 PermissionsType permissions_type) {
592 DCHECK_NE(ALL_PERMISSIONS, permissions_type);
593 return permissions_type == REGULAR_PERMISSIONS ? prompt_permissions_
594 : withheld_prompt_permissions_;
595}
596
597const ExtensionInstallPrompt::Prompt::InstallPromptPermissions&
598ExtensionInstallPrompt::Prompt::GetPermissionsForType(
599 PermissionsType permissions_type) const {
600 DCHECK_NE(ALL_PERMISSIONS, permissions_type);
601 return permissions_type == REGULAR_PERMISSIONS ? prompt_permissions_
602 : withheld_prompt_permissions_;
603}
604
[email protected]a2886e8b2013-06-08 05:15:02605bool ExtensionInstallPrompt::Prompt::ShouldDisplayRevokeFilesButton() const {
606 return !retained_files_.empty();
607}
608
[email protected]c82da8c42012-06-08 19:49:11609// static
610scoped_refptr<Extension>
611 ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
[email protected]023b3d12013-12-23 18:46:49612 const base::DictionaryValue* manifest,
[email protected]c422a862012-07-31 15:46:13613 int flags,
[email protected]c82da8c42012-06-08 19:49:11614 const std::string& id,
615 const std::string& localized_name,
616 const std::string& localized_description,
617 std::string* error) {
[email protected]023b3d12013-12-23 18:46:49618 scoped_ptr<base::DictionaryValue> localized_manifest;
[email protected]c82da8c42012-06-08 19:49:11619 if (!localized_name.empty() || !localized_description.empty()) {
620 localized_manifest.reset(manifest->DeepCopy());
621 if (!localized_name.empty()) {
[email protected]6bf90612013-08-15 00:36:27622 localized_manifest->SetString(extensions::manifest_keys::kName,
[email protected]c82da8c42012-06-08 19:49:11623 localized_name);
624 }
625 if (!localized_description.empty()) {
[email protected]6bf90612013-08-15 00:36:27626 localized_manifest->SetString(extensions::manifest_keys::kDescription,
[email protected]c82da8c42012-06-08 19:49:11627 localized_description);
628 }
629 }
630
631 return Extension::Create(
[email protected]650b2d52013-02-10 03:41:45632 base::FilePath(),
[email protected]1d5e58b2013-01-31 08:41:40633 Manifest::INTERNAL,
[email protected]c82da8c42012-06-08 19:49:11634 localized_manifest.get() ? *localized_manifest.get() : *manifest,
[email protected]c422a862012-07-31 15:46:13635 flags,
[email protected]c82da8c42012-06-08 19:49:11636 id,
637 error);
638}
639
[email protected]7f165342014-02-12 09:22:22640ExtensionInstallPrompt::ExtensionInstallPrompt(content::WebContents* contents)
pkotwicza57a1f322014-10-21 00:24:30641 : profile_(ProfileForWebContents(contents)),
642 ui_loop_(base::MessageLoop::current()),
[email protected]c82da8c42012-06-08 19:49:11643 extension_(NULL),
[email protected]7f165342014-02-12 09:22:22644 bundle_(NULL),
pkotwicza57a1f322014-10-21 00:24:30645 install_ui_(extensions::CreateExtensionInstallUI(
646 ProfileForWebContents(contents))),
pkotwicz2f181782014-10-29 17:33:45647 show_params_(new ExtensionInstallPromptShowParams(contents)),
[email protected]d382baa2014-06-17 18:50:01648 delegate_(NULL) {
649}
[email protected]5db2e882012-12-20 10:17:26650
pkotwicz2175c622014-10-22 19:56:28651ExtensionInstallPrompt::ExtensionInstallPrompt(Profile* profile,
652 gfx::NativeWindow native_window)
pkotwicza57a1f322014-10-21 00:24:30653 : profile_(profile),
654 ui_loop_(base::MessageLoop::current()),
[email protected]5db2e882012-12-20 10:17:26655 extension_(NULL),
[email protected]7f165342014-02-12 09:22:22656 bundle_(NULL),
pkotwicza57a1f322014-10-21 00:24:30657 install_ui_(extensions::CreateExtensionInstallUI(profile)),
pkotwicz2f181782014-10-29 17:33:45658 show_params_(
659 new ExtensionInstallPromptShowParams(profile, native_window)),
[email protected]d382baa2014-06-17 18:50:01660 delegate_(NULL) {
661}
[email protected]c82da8c42012-06-08 19:49:11662
663ExtensionInstallPrompt::~ExtensionInstallPrompt() {
664}
665
666void ExtensionInstallPrompt::ConfirmBundleInstall(
667 extensions::BundleInstaller* bundle,
treibd9e1d9d2015-04-24 11:17:04668 const SkBitmap* icon,
[email protected]c2e66e12012-06-27 06:27:06669 const PermissionSet* permissions) {
[email protected]b3a25092013-05-28 22:08:16670 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11671 bundle_ = bundle;
gpdavis.chromium0fbac4d2014-09-19 20:57:54672 custom_permissions_ = permissions;
[email protected]c82da8c42012-06-08 19:49:11673 delegate_ = bundle;
[email protected]d382baa2014-06-17 18:50:01674 prompt_ = new Prompt(BUNDLE_INSTALL_PROMPT);
[email protected]c82da8c42012-06-08 19:49:11675
treibd9e1d9d2015-04-24 11:17:04676 SetIcon(icon);
[email protected]4e494872013-09-06 09:13:54677 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11678}
679
[email protected]734bcec2012-10-08 20:29:05680void ExtensionInstallPrompt::ConfirmStandaloneInstall(
[email protected]c82da8c42012-06-08 19:49:11681 Delegate* delegate,
682 const Extension* extension,
683 SkBitmap* icon,
[email protected]d382baa2014-06-17 18:50:01684 scoped_refptr<Prompt> prompt) {
[email protected]b3a25092013-05-28 22:08:16685 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11686 extension_ = extension;
[email protected]c82da8c42012-06-08 19:49:11687 delegate_ = delegate;
688 prompt_ = prompt;
[email protected]c82da8c42012-06-08 19:49:11689
690 SetIcon(icon);
[email protected]4e494872013-09-06 09:13:54691 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11692}
693
[email protected]af6efb22012-10-12 02:23:05694void ExtensionInstallPrompt::ConfirmWebstoreInstall(
695 Delegate* delegate,
696 const Extension* extension,
697 const SkBitmap* icon,
698 const ShowDialogCallback& show_dialog_callback) {
[email protected]c82da8c42012-06-08 19:49:11699 // SetIcon requires |extension_| to be set. ConfirmInstall will setup the
700 // remaining fields.
701 extension_ = extension;
702 SetIcon(icon);
[email protected]af6efb22012-10-12 02:23:05703 ConfirmInstall(delegate, extension, show_dialog_callback);
[email protected]c82da8c42012-06-08 19:49:11704}
705
[email protected]af6efb22012-10-12 02:23:05706void ExtensionInstallPrompt::ConfirmInstall(
707 Delegate* delegate,
708 const Extension* extension,
709 const ShowDialogCallback& show_dialog_callback) {
[email protected]b3a25092013-05-28 22:08:16710 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11711 extension_ = extension;
[email protected]c82da8c42012-06-08 19:49:11712 delegate_ = delegate;
[email protected]d382baa2014-06-17 18:50:01713 prompt_ = new Prompt(INSTALL_PROMPT);
[email protected]af6efb22012-10-12 02:23:05714 show_dialog_callback_ = show_dialog_callback;
[email protected]c82da8c42012-06-08 19:49:11715
716 // We special-case themes to not show any confirm UI. Instead they are
717 // immediately installed, and then we show an infobar (see OnInstallSuccess)
718 // to allow the user to revert if they don't like it.
719 //
720 // We don't do this in the case where off-store extension installs are
721 // disabled because in that case, we don't show the dangerous download UI, so
722 // we need the UI confirmation.
723 if (extension->is_theme()) {
724 if (extension->from_webstore() ||
[email protected]544471a2012-10-13 05:27:09725 extensions::FeatureSwitch::easy_off_store_install()->IsEnabled()) {
[email protected]c82da8c42012-06-08 19:49:11726 delegate->InstallUIProceed();
727 return;
728 }
729 }
730
731 LoadImageIfNeeded();
732}
733
treib2d2f5372015-03-01 12:20:49734void ExtensionInstallPrompt::ConfirmPermissionsForDelegatedInstall(
735 Delegate* delegate,
736 const Extension* extension,
737 const std::string& delegated_username,
738 const SkBitmap* icon) {
739 DCHECK(ui_loop_ == base::MessageLoop::current());
740 delegate_ = delegate;
741 extension_ = extension;
742 delegated_username_ = delegated_username;
743 SetIcon(icon);
744 prompt_ = new Prompt(DELEGATED_PERMISSIONS_PROMPT);
745 ShowConfirmation();
746}
747
[email protected]c82da8c42012-06-08 19:49:11748void ExtensionInstallPrompt::ConfirmReEnable(Delegate* delegate,
749 const Extension* extension) {
[email protected]b3a25092013-05-28 22:08:16750 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11751 extension_ = extension;
[email protected]c82da8c42012-06-08 19:49:11752 delegate_ = delegate;
[email protected]21db9ef2014-05-16 02:06:27753 bool is_remote_install =
pkotwicza57a1f322014-10-21 00:24:30754 profile_ &&
755 extensions::ExtensionPrefs::Get(profile_)->HasDisableReason(
[email protected]21db9ef2014-05-16 02:06:27756 extension->id(), extensions::Extension::DISABLE_REMOTE_INSTALL);
[email protected]411f8ae2014-05-22 11:12:23757 bool is_ephemeral =
pkotwicza57a1f322014-10-21 00:24:30758 extensions::util::IsEphemeralApp(extension->id(), profile_);
[email protected]d382baa2014-06-17 18:50:01759
760 PromptType type = UNSET_PROMPT_TYPE;
[email protected]411f8ae2014-05-22 11:12:23761 if (is_ephemeral)
[email protected]d382baa2014-06-17 18:50:01762 type = LAUNCH_PROMPT;
[email protected]21db9ef2014-05-16 02:06:27763 else if (is_remote_install)
[email protected]d382baa2014-06-17 18:50:01764 type = REMOTE_INSTALL_PROMPT;
[email protected]21db9ef2014-05-16 02:06:27765 else
[email protected]d382baa2014-06-17 18:50:01766 type = RE_ENABLE_PROMPT;
767 prompt_ = new Prompt(type);
768
[email protected]c82da8c42012-06-08 19:49:11769 LoadImageIfNeeded();
770}
771
[email protected]612a1cb12012-10-17 13:18:03772void ExtensionInstallPrompt::ConfirmExternalInstall(
[email protected]c8ff7c9e2013-04-20 12:36:27773 Delegate* delegate,
774 const Extension* extension,
[email protected]34b5f7f2014-01-29 02:48:11775 const ShowDialogCallback& show_dialog_callback,
[email protected]d382baa2014-06-17 18:50:01776 scoped_refptr<Prompt> prompt) {
[email protected]b3a25092013-05-28 22:08:16777 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]612a1cb12012-10-17 13:18:03778 extension_ = extension;
[email protected]612a1cb12012-10-17 13:18:03779 delegate_ = delegate;
[email protected]34b5f7f2014-01-29 02:48:11780 prompt_ = prompt;
[email protected]c8ff7c9e2013-04-20 12:36:27781 show_dialog_callback_ = show_dialog_callback;
[email protected]612a1cb12012-10-17 13:18:03782
783 LoadImageIfNeeded();
784}
785
[email protected]c82da8c42012-06-08 19:49:11786void ExtensionInstallPrompt::ConfirmPermissions(
787 Delegate* delegate,
788 const Extension* extension,
[email protected]c2e66e12012-06-27 06:27:06789 const PermissionSet* permissions) {
[email protected]b3a25092013-05-28 22:08:16790 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11791 extension_ = extension;
gpdavis.chromium0fbac4d2014-09-19 20:57:54792 custom_permissions_ = permissions;
[email protected]c82da8c42012-06-08 19:49:11793 delegate_ = delegate;
[email protected]d382baa2014-06-17 18:50:01794 prompt_ = new Prompt(PERMISSIONS_PROMPT);
[email protected]c82da8c42012-06-08 19:49:11795
796 LoadImageIfNeeded();
797}
798
[email protected]a2886e8b2013-06-08 05:15:02799void ExtensionInstallPrompt::ReviewPermissions(
800 Delegate* delegate,
801 const Extension* extension,
reillygc64d3dd2014-09-29 21:10:11802 const std::vector<base::FilePath>& retained_file_paths,
803 const std::vector<base::string16>& retained_device_messages) {
[email protected]b3a25092013-05-28 22:08:16804 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]15d267b42013-02-14 23:43:32805 extension_ = extension;
[email protected]d382baa2014-06-17 18:50:01806 prompt_ = new Prompt(POST_INSTALL_PERMISSIONS_PROMPT);
807 prompt_->set_retained_files(retained_file_paths);
reillygc64d3dd2014-09-29 21:10:11808 prompt_->set_retained_device_messages(retained_device_messages);
[email protected]15d267b42013-02-14 23:43:32809 delegate_ = delegate;
[email protected]15d267b42013-02-14 23:43:32810
811 LoadImageIfNeeded();
812}
813
[email protected]c82da8c42012-06-08 19:49:11814void ExtensionInstallPrompt::OnInstallSuccess(const Extension* extension,
815 SkBitmap* icon) {
816 extension_ = extension;
817 SetIcon(icon);
818
819 install_ui_->OnInstallSuccess(extension, &icon_);
820}
821
[email protected]bf3d9df2012-07-24 23:20:27822void ExtensionInstallPrompt::OnInstallFailure(
ginkage47e603e2015-02-27 08:42:41823 const extensions::CrxInstallError& error) {
[email protected]c82da8c42012-06-08 19:49:11824 install_ui_->OnInstallFailure(error);
825}
826
827void ExtensionInstallPrompt::SetIcon(const SkBitmap* image) {
828 if (image)
829 icon_ = *image;
830 else
831 icon_ = SkBitmap();
[email protected]dd46a4ce2012-09-15 10:50:50832 if (icon_.empty()) {
833 // Let's set default icon bitmap whose size is equal to the default icon's
834 // pixel size under maximal supported scale factor. If the bitmap is larger
835 // than the one we need, it will be scaled down by the ui code.
treibd9e1d9d2015-04-24 11:17:04836 icon_ = GetDefaultIconBitmapForMaxScaleFactor(
837 extension_ ? extension_->is_app() : false);
[email protected]dd46a4ce2012-09-15 10:50:50838 }
[email protected]c82da8c42012-06-08 19:49:11839}
840
[email protected]ec7de0c5a2012-11-16 07:40:47841void ExtensionInstallPrompt::OnImageLoaded(const gfx::Image& image) {
[email protected]c82da8c42012-06-08 19:49:11842 SetIcon(image.IsEmpty() ? NULL : image.ToSkBitmap());
[email protected]4e494872013-09-06 09:13:54843 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11844}
845
846void ExtensionInstallPrompt::LoadImageIfNeeded() {
847 // Bundle install prompts do not have an icon.
pkotwicza57a1f322014-10-21 00:24:30848 // Also |profile_| can be NULL in unit tests.
849 if (!icon_.empty() || !profile_) {
[email protected]4e494872013-09-06 09:13:54850 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11851 return;
852 }
853
[email protected]993da5e2013-03-23 21:25:16854 extensions::ExtensionResource image = extensions::IconsInfo::GetIconResource(
[email protected]702d8b42013-02-27 20:55:50855 extension_,
856 extension_misc::EXTENSION_ICON_LARGE,
857 ExtensionIconSet::MATCH_BIGGER);
[email protected]0d0ba182014-06-03 12:40:43858
859 // Load the image asynchronously. The response will be sent to OnImageLoaded.
pkotwicza57a1f322014-10-21 00:24:30860 extensions::ImageLoader* loader = extensions::ImageLoader::Get(profile_);
[email protected]0d0ba182014-06-03 12:40:43861
862 std::vector<extensions::ImageLoader::ImageRepresentation> images_list;
863 images_list.push_back(extensions::ImageLoader::ImageRepresentation(
864 image,
865 extensions::ImageLoader::ImageRepresentation::NEVER_RESIZE,
866 gfx::Size(),
867 ui::SCALE_FACTOR_100P));
868 loader->LoadImagesAsync(
869 extension_,
870 images_list,
[email protected]ec7de0c5a2012-11-16 07:40:47871 base::Bind(&ExtensionInstallPrompt::OnImageLoaded, AsWeakPtr()));
[email protected]c82da8c42012-06-08 19:49:11872}
873
874void ExtensionInstallPrompt::ShowConfirmation() {
gpdavis.chromium0fbac4d2014-09-19 20:57:54875 scoped_refptr<const PermissionSet> permissions_to_display;
876 if (custom_permissions_.get()) {
877 permissions_to_display = custom_permissions_;
878 } else if (extension_) {
879 // Initialize permissions if they have not already been set so that
880 // withheld permissions are displayed properly in the install prompt.
881 extensions::PermissionsUpdater(
pkotwicza57a1f322014-10-21 00:24:30882 profile_, extensions::PermissionsUpdater::INIT_FLAG_TRANSIENT)
gpdavis.chromium0fbac4d2014-09-19 20:57:54883 .InitializePermissions(extension_);
884 permissions_to_display =
885 extension_->permissions_data()->active_permissions();
treib7496f63c2015-03-04 12:18:53886 // For delegated installs, all optional permissions are pre-approved by the
887 // person who triggers the install, so add them to the list.
888 if (prompt_->type() == DELEGATED_PERMISSIONS_PROMPT) {
889 scoped_refptr<const PermissionSet> optional_permissions =
890 extensions::PermissionsParser::GetOptionalPermissions(extension_);
891 permissions_to_display = PermissionSet::CreateUnion(
892 permissions_to_display.get(),
893 optional_permissions.get());
894 }
gpdavis.chromium0fbac4d2014-09-19 20:57:54895 }
896
897 if (permissions_to_display.get() &&
[email protected]a397ec02014-08-08 15:48:13898 (!extension_ ||
899 !extensions::PermissionsData::ShouldSkipPermissionWarnings(
900 extension_->id()))) {
901 Manifest::Type type =
902 extension_ ? extension_->GetType() : Manifest::TYPE_UNKNOWN;
903 const extensions::PermissionMessageProvider* message_provider =
904 extensions::PermissionMessageProvider::Get();
treib7b45a34b2015-04-16 11:48:02905
906 prompt_->SetPermissions(message_provider->GetPermissionMessageStrings(
gpdavis.chromium0fbac4d2014-09-19 20:57:54907 permissions_to_display.get(), type),
908 REGULAR_PERMISSIONS);
gpdavis.chromium0fbac4d2014-09-19 20:57:54909
910 scoped_refptr<const extensions::PermissionSet> withheld =
treiba21dcd92015-04-03 05:26:41911 extension_ ? extension_->permissions_data()->withheld_permissions()
912 : nullptr;
913 if (withheld && !withheld->IsEmpty()) {
gpdavis.chromium0fbac4d2014-09-19 20:57:54914 prompt_->SetPermissions(
treib7b45a34b2015-04-16 11:48:02915 message_provider->GetPermissionMessageStrings(withheld.get(), type),
gpdavis.chromium0fbac4d2014-09-19 20:57:54916 PermissionsType::WITHHELD_PERMISSIONS);
917 }
[email protected]bebe1d02012-08-02 20:17:09918 }
[email protected]c82da8c42012-06-08 19:49:11919
[email protected]d382baa2014-06-17 18:50:01920 switch (prompt_->type()) {
[email protected]c82da8c42012-06-08 19:49:11921 case PERMISSIONS_PROMPT:
922 case RE_ENABLE_PROMPT:
923 case INLINE_INSTALL_PROMPT:
[email protected]612a1cb12012-10-17 13:18:03924 case EXTERNAL_INSTALL_PROMPT:
[email protected]15d267b42013-02-14 23:43:32925 case INSTALL_PROMPT:
[email protected]1a93d8d2013-10-27 23:09:20926 case LAUNCH_PROMPT:
[email protected]21db9ef2014-05-16 02:06:27927 case POST_INSTALL_PERMISSIONS_PROMPT:
rdevlin.cronin5f6b69d2014-09-20 01:23:35928 case REMOTE_INSTALL_PROMPT:
treib2d2f5372015-03-01 12:20:49929 case REPAIR_PROMPT:
930 case DELEGATED_PERMISSIONS_PROMPT: {
[email protected]d382baa2014-06-17 18:50:01931 prompt_->set_extension(extension_);
treib2d2f5372015-03-01 12:20:49932 prompt_->set_delegated_username(delegated_username_);
[email protected]c82da8c42012-06-08 19:49:11933 break;
934 }
935 case BUNDLE_INSTALL_PROMPT: {
[email protected]d382baa2014-06-17 18:50:01936 prompt_->set_bundle(bundle_);
[email protected]c82da8c42012-06-08 19:49:11937 break;
938 }
939 default:
940 NOTREACHED() << "Unknown message";
[email protected]af6efb22012-10-12 02:23:05941 return;
[email protected]c82da8c42012-06-08 19:49:11942 }
treibd9e1d9d2015-04-24 11:17:04943 prompt_->set_icon(gfx::Image::CreateFrom1xBitmap(icon_));
[email protected]af6efb22012-10-12 02:23:05944
rdevlin.cronin092c6772014-11-20 23:52:40945 g_last_prompt_type_for_tests = prompt_->type();
946
[email protected]af6efb22012-10-12 02:23:05947 if (AutoConfirmPrompt(delegate_))
948 return;
949
pkotwicz2f181782014-10-29 17:33:45950 if (show_params_->WasParentDestroyed()) {
951 delegate_->InstallUIAbort(false);
952 return;
953 }
954
[email protected]5db2e882012-12-20 10:17:26955 if (show_dialog_callback_.is_null())
pkotwicz2f181782014-10-29 17:33:45956 GetDefaultShowDialogCallback().Run(show_params_.get(), delegate_, prompt_);
[email protected]5db2e882012-12-20 10:17:26957 else
pkotwicz2f181782014-10-29 17:33:45958 show_dialog_callback_.Run(show_params_.get(), delegate_, prompt_);
[email protected]c82da8c42012-06-08 19:49:11959}