blob: 24bd6a09909c79f7faa4c1f4c25a00e355fb998b [file] [log] [blame]
[email protected]c82da8c42012-06-08 19:49:111// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/extensions/extension_install_prompt.h"
6
7#include <map>
8
9#include "base/command_line.h"
[email protected]b19fe572013-07-18 04:54:2610#include "base/message_loop/message_loop.h"
[email protected]3853a4c2013-02-11 17:15:5711#include "base/prefs/pref_service.h"
[email protected]3ea1b182013-02-08 22:38:4112#include "base/strings/string_number_conversions.h"
[email protected]00e7bef2013-06-10 20:35:1713#include "base/strings/string_util.h"
14#include "base/strings/stringprintf.h"
[email protected]112158af2013-06-07 23:46:1815#include "base/strings/utf_string_conversions.h"
[email protected]c82da8c42012-06-08 19:49:1116#include "chrome/browser/extensions/bundle_installer.h"
[email protected]7eb20e32014-04-30 08:50:5617#include "chrome/browser/extensions/extension_util.h"
gpdavis.chromium0fbac4d2014-09-19 20:57:5418#include "chrome/browser/extensions/permissions_updater.h"
[email protected]c82da8c42012-06-08 19:49:1119#include "chrome/browser/profiles/profile.h"
pkotwicza57a1f322014-10-21 00:24:3020#include "chrome/browser/ui/extensions/extension_install_ui_factory.h"
[email protected]c82da8c42012-06-08 19:49:1121#include "chrome/common/chrome_switches.h"
[email protected]fc5077942012-08-15 21:37:5922#include "chrome/common/pref_names.h"
[email protected]af39f002014-08-22 10:18:1823#include "chrome/grit/chromium_strings.h"
24#include "chrome/grit/generated_resources.h"
[email protected]91e51d612012-10-21 23:03:0525#include "content/public/browser/web_contents.h"
[email protected]21db9ef2014-05-16 02:06:2726#include "extensions/browser/extension_prefs.h"
[email protected]411f8ae2014-05-22 11:12:2327#include "extensions/browser/extension_util.h"
[email protected]326e6f02014-06-20 04:53:3728#include "extensions/browser/image_loader.h"
pkotwicza57a1f322014-10-21 00:24:3029#include "extensions/browser/install/extension_install_ui.h"
[email protected]cda103d2014-04-04 16:22:3930#include "extensions/common/constants.h"
[email protected]e4452d32013-11-15 23:07:4131#include "extensions/common/extension.h"
[email protected]4b7908842014-04-07 23:50:2232#include "extensions/common/extension_icon_set.h"
[email protected]993da5e2013-03-23 21:25:1633#include "extensions/common/extension_resource.h"
[email protected]5ef835a2013-11-08 20:42:5734#include "extensions/common/feature_switch.h"
[email protected]d42c11152013-08-22 19:36:3235#include "extensions/common/manifest.h"
[email protected]6bf90612013-08-15 00:36:2736#include "extensions/common/manifest_constants.h"
[email protected]0db486f2014-04-09 19:32:2237#include "extensions/common/manifest_handlers/icons_handler.h"
[email protected]c41003472013-10-19 15:37:2538#include "extensions/common/permissions/permission_message_provider.h"
[email protected]5a55f3f2013-10-29 01:08:2939#include "extensions/common/permissions/permission_set.h"
[email protected]e4452d32013-11-15 23:07:4140#include "extensions/common/permissions/permissions_data.h"
[email protected]885c0e92012-11-13 20:27:4241#include "extensions/common/url_pattern.h"
[email protected]2a281332012-07-11 22:20:2342#include "grit/theme_resources.h"
[email protected]c82da8c42012-06-08 19:49:1143#include "ui/base/l10n/l10n_util.h"
44#include "ui/base/resource/resource_bundle.h"
pkotwicz7fd01192014-10-09 04:43:5045#include "ui/base/ui_base_types.h"
[email protected]c82da8c42012-06-08 19:49:1146#include "ui/gfx/image/image.h"
47
[email protected]c82da8c42012-06-08 19:49:1148using extensions::BundleInstaller;
49using extensions::Extension;
[email protected]1d5e58b2013-01-31 08:41:4050using extensions::Manifest;
[email protected]c2e66e12012-06-27 06:27:0651using extensions::PermissionSet;
[email protected]c82da8c42012-06-08 19:49:1152
[email protected]612a1cb12012-10-17 13:18:0353namespace {
54
rdevlin.cronin5f6b69d2014-09-20 01:23:3555bool AllowWebstoreData(ExtensionInstallPrompt::PromptType type) {
56 return type == ExtensionInstallPrompt::INLINE_INSTALL_PROMPT ||
57 type == ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT ||
58 type == ExtensionInstallPrompt::REPAIR_PROMPT;
59}
60
[email protected]c82da8c42012-06-08 19:49:1161static const int kTitleIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2762 0, // The regular install prompt depends on what's being installed.
63 IDS_EXTENSION_INLINE_INSTALL_PROMPT_TITLE,
64 IDS_EXTENSION_INSTALL_PROMPT_TITLE,
65 IDS_EXTENSION_RE_ENABLE_PROMPT_TITLE,
66 IDS_EXTENSION_PERMISSIONS_PROMPT_TITLE,
67 IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_TITLE,
68 IDS_EXTENSION_POST_INSTALL_PERMISSIONS_PROMPT_TITLE,
69 IDS_EXTENSION_LAUNCH_APP_PROMPT_TITLE,
70 0, // The remote install prompt depends on what's being installed.
rdevlin.cronin5f6b69d2014-09-20 01:23:3571 0, // The repair install prompt depends on what's being installed.
[email protected]c82da8c42012-06-08 19:49:1172};
73static const int kHeadingIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2774 IDS_EXTENSION_INSTALL_PROMPT_HEADING,
75 0, // Inline installs use the extension name.
76 0, // Heading for bundle installs depends on the bundle contents.
77 IDS_EXTENSION_RE_ENABLE_PROMPT_HEADING,
78 IDS_EXTENSION_PERMISSIONS_PROMPT_HEADING,
79 0, // External installs use different strings for extensions/apps.
80 IDS_EXTENSION_POST_INSTALL_PERMISSIONS_PROMPT_HEADING,
81 IDS_EXTENSION_LAUNCH_APP_PROMPT_HEADING,
82 IDS_EXTENSION_REMOTE_INSTALL_PROMPT_HEADING,
rdevlin.cronin5f6b69d2014-09-20 01:23:3583 IDS_EXTENSION_REPAIR_PROMPT_HEADING
[email protected]15d267b42013-02-14 23:43:3284};
85static const int kButtons[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2786 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
87 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
88 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
89 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
90 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
91 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
92 ui::DIALOG_BUTTON_CANCEL,
93 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
94 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
rdevlin.cronin5f6b69d2014-09-20 01:23:3595 ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL,
[email protected]c82da8c42012-06-08 19:49:1196};
97static const int kAcceptButtonIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:2798 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
99 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
100 IDS_EXTENSION_PROMPT_INSTALL_BUTTON,
101 IDS_EXTENSION_PROMPT_RE_ENABLE_BUTTON,
102 IDS_EXTENSION_PROMPT_PERMISSIONS_BUTTON,
103 0, // External installs use different strings for extensions/apps.
reillygc64d3dd2014-09-29 21:10:11104 0, // Different strings depending on the files and devices retained.
[email protected]21db9ef2014-05-16 02:06:27105 IDS_EXTENSION_PROMPT_LAUNCH_BUTTON,
106 IDS_EXTENSION_PROMPT_REMOTE_INSTALL_BUTTON,
rdevlin.cronin5f6b69d2014-09-20 01:23:35107 IDS_EXTENSION_PROMPT_REPAIR_BUTTON,
[email protected]c82da8c42012-06-08 19:49:11108};
109static const int kAbortButtonIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
[email protected]21db9ef2014-05-16 02:06:27110 0, // These all use the platform's default cancel label.
111 0,
112 0,
113 0,
114 IDS_EXTENSION_PROMPT_PERMISSIONS_ABORT_BUTTON,
115 IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ABORT_BUTTON,
116 IDS_CLOSE,
117 0, // Platform dependent cancel button.
118 0,
rdevlin.cronin5f6b69d2014-09-20 01:23:35119 0,
[email protected]c82da8c42012-06-08 19:49:11120};
[email protected]21db9ef2014-05-16 02:06:27121static const int
122 kPermissionsHeaderIds[ExtensionInstallPrompt::NUM_PROMPT_TYPES] = {
123 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
124 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
125 IDS_EXTENSION_PROMPT_THESE_WILL_HAVE_ACCESS_TO,
126 IDS_EXTENSION_PROMPT_WILL_NOW_HAVE_ACCESS_TO,
127 IDS_EXTENSION_PROMPT_WANTS_ACCESS_TO,
128 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
129 IDS_EXTENSION_PROMPT_CAN_ACCESS,
130 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
131 IDS_EXTENSION_PROMPT_WILL_HAVE_ACCESS_TO,
rdevlin.cronin5f6b69d2014-09-20 01:23:35132 IDS_EXTENSION_PROMPT_CAN_ACCESS,
[email protected]c82da8c42012-06-08 19:49:11133};
[email protected]c82da8c42012-06-08 19:49:11134
[email protected]dd46a4ce2012-09-15 10:50:50135// Returns bitmap for the default icon with size equal to the default icon's
136// pixel size under maximal supported scale factor.
137SkBitmap GetDefaultIconBitmapForMaxScaleFactor(bool is_app) {
[email protected]702d8b42013-02-27 20:55:50138 const gfx::ImageSkia& image = is_app ?
[email protected]7eb20e32014-04-30 08:50:56139 extensions::util::GetDefaultAppIcon() :
140 extensions::util::GetDefaultExtensionIcon();
[email protected]50b66262013-09-24 03:25:48141 return image.GetRepresentation(
142 gfx::ImageSkia::GetMaxSupportedScale()).sk_bitmap();
[email protected]dd46a4ce2012-09-15 10:50:50143}
144
[email protected]af6efb22012-10-12 02:23:05145// If auto confirm is enabled then posts a task to proceed with or cancel the
146// install and returns true. Otherwise returns false.
147bool AutoConfirmPrompt(ExtensionInstallPrompt::Delegate* delegate) {
[email protected]2a74d6f62014-07-24 11:53:47148 switch (ExtensionInstallPrompt::g_auto_confirm_for_tests) {
149 case ExtensionInstallPrompt::NONE:
150 return false;
151 // We use PostTask instead of calling the delegate directly here, because in
152 // the real implementations it's highly likely the message loop will be
153 // pumping a few times before the user clicks accept or cancel.
154 case ExtensionInstallPrompt::ACCEPT:
155 base::MessageLoop::current()->PostTask(
156 FROM_HERE,
157 base::Bind(&ExtensionInstallPrompt::Delegate::InstallUIProceed,
158 base::Unretained(delegate)));
159 return true;
160 case ExtensionInstallPrompt::CANCEL:
161 base::MessageLoop::current()->PostTask(
162 FROM_HERE,
163 base::Bind(&ExtensionInstallPrompt::Delegate::InstallUIAbort,
164 base::Unretained(delegate),
165 true));
166 return true;
[email protected]af6efb22012-10-12 02:23:05167 }
168
169 NOTREACHED();
170 return false;
171}
172
[email protected]91e51d612012-10-21 23:03:05173Profile* ProfileForWebContents(content::WebContents* web_contents) {
174 if (!web_contents)
175 return NULL;
176 return Profile::FromBrowserContext(web_contents->GetBrowserContext());
177}
178
[email protected]5db2e882012-12-20 10:17:26179gfx::NativeWindow NativeWindowForWebContents(content::WebContents* contents) {
180 if (!contents)
181 return NULL;
182
[email protected]fc2b46b2014-05-03 16:33:45183 return contents->GetTopLevelNativeWindow();
[email protected]5db2e882012-12-20 10:17:26184}
185
[email protected]c82da8c42012-06-08 19:49:11186} // namespace
187
gpdavis.chromium0fbac4d2014-09-19 20:57:54188ExtensionInstallPrompt::Prompt::InstallPromptPermissions::
189 InstallPromptPermissions() {
190}
191ExtensionInstallPrompt::Prompt::InstallPromptPermissions::
192 ~InstallPromptPermissions() {
193}
194
[email protected]2a74d6f62014-07-24 11:53:47195// static
196ExtensionInstallPrompt::AutoConfirmForTests
197ExtensionInstallPrompt::g_auto_confirm_for_tests = ExtensionInstallPrompt::NONE;
198
[email protected]eeb0d3e12014-08-15 15:10:44199// This should match the PromptType enum.
200std::string ExtensionInstallPrompt::PromptTypeToString(PromptType type) {
201 switch (type) {
202 case ExtensionInstallPrompt::INSTALL_PROMPT:
203 return "INSTALL_PROMPT";
204 case ExtensionInstallPrompt::INLINE_INSTALL_PROMPT:
205 return "INLINE_INSTALL_PROMPT";
206 case ExtensionInstallPrompt::BUNDLE_INSTALL_PROMPT:
207 return "BUNDLE_INSTALL_PROMPT";
208 case ExtensionInstallPrompt::RE_ENABLE_PROMPT:
209 return "RE_ENABLE_PROMPT";
210 case ExtensionInstallPrompt::PERMISSIONS_PROMPT:
211 return "PERMISSIONS_PROMPT";
212 case ExtensionInstallPrompt::EXTERNAL_INSTALL_PROMPT:
213 return "EXTERNAL_INSTALL_PROMPT";
214 case ExtensionInstallPrompt::POST_INSTALL_PERMISSIONS_PROMPT:
215 return "POST_INSTALL_PERMISSIONS_PROMPT";
216 case ExtensionInstallPrompt::LAUNCH_PROMPT:
217 return "LAUNCH_PROMPT";
218 case ExtensionInstallPrompt::REMOTE_INSTALL_PROMPT:
219 return "REMOTE_INSTALL_PROMPT";
rdevlin.cronin5f6b69d2014-09-20 01:23:35220 case ExtensionInstallPrompt::REPAIR_PROMPT:
221 return "REPAIR_PROMPT";
[email protected]eeb0d3e12014-08-15 15:10:44222 case ExtensionInstallPrompt::UNSET_PROMPT_TYPE:
223 case ExtensionInstallPrompt::NUM_PROMPT_TYPES:
224 break;
225 }
226 return "OTHER";
227}
228
[email protected]5db2e882012-12-20 10:17:26229ExtensionInstallPrompt::Prompt::Prompt(PromptType type)
[email protected]c82da8c42012-06-08 19:49:11230 : type_(type),
[email protected]79a6f99a2013-08-29 00:32:58231 is_showing_details_for_retained_files_(false),
reillygc64d3dd2014-09-29 21:10:11232 is_showing_details_for_retained_devices_(false),
[email protected]c82da8c42012-06-08 19:49:11233 extension_(NULL),
234 bundle_(NULL),
235 average_rating_(0.0),
[email protected]dcde34b32013-07-31 02:28:45236 rating_count_(0),
[email protected]34b5f7f2014-01-29 02:48:11237 show_user_count_(false),
238 has_webstore_data_(false) {
[email protected]c82da8c42012-06-08 19:49:11239}
240
241ExtensionInstallPrompt::Prompt::~Prompt() {
242}
243
244void ExtensionInstallPrompt::Prompt::SetPermissions(
gpdavis.chromium0fbac4d2014-09-19 20:57:54245 const std::vector<base::string16>& permissions,
246 PermissionsType permissions_type) {
247 GetPermissionsForType(permissions_type).permissions = permissions;
[email protected]c82da8c42012-06-08 19:49:11248}
249
[email protected]8ab7e6c2013-07-11 21:15:03250void ExtensionInstallPrompt::Prompt::SetPermissionsDetails(
gpdavis.chromium0fbac4d2014-09-19 20:57:54251 const std::vector<base::string16>& details,
252 PermissionsType permissions_type) {
253 InstallPromptPermissions& install_permissions =
254 GetPermissionsForType(permissions_type);
255 install_permissions.details = details;
256 install_permissions.is_showing_details.clear();
257 install_permissions.is_showing_details.insert(
258 install_permissions.is_showing_details.begin(), details.size(), false);
[email protected]79a6f99a2013-08-29 00:32:58259}
260
261void ExtensionInstallPrompt::Prompt::SetIsShowingDetails(
262 DetailsType type,
263 size_t index,
264 bool is_showing_details) {
265 switch (type) {
266 case PERMISSIONS_DETAILS:
gpdavis.chromium0fbac4d2014-09-19 20:57:54267 prompt_permissions_.is_showing_details[index] = is_showing_details;
268 break;
269 case WITHHELD_PERMISSIONS_DETAILS:
270 withheld_prompt_permissions_.is_showing_details[index] =
271 is_showing_details;
[email protected]79a6f99a2013-08-29 00:32:58272 break;
[email protected]79a6f99a2013-08-29 00:32:58273 case RETAINED_FILES_DETAILS:
274 is_showing_details_for_retained_files_ = is_showing_details;
275 break;
reillygc64d3dd2014-09-29 21:10:11276 case RETAINED_DEVICES_DETAILS:
277 is_showing_details_for_retained_devices_ = is_showing_details;
278 break;
[email protected]79a6f99a2013-08-29 00:32:58279 }
[email protected]8ab7e6c2013-07-11 21:15:03280}
281
[email protected]34b5f7f2014-01-29 02:48:11282void ExtensionInstallPrompt::Prompt::SetWebstoreData(
[email protected]c82da8c42012-06-08 19:49:11283 const std::string& localized_user_count,
[email protected]dcde34b32013-07-31 02:28:45284 bool show_user_count,
[email protected]c82da8c42012-06-08 19:49:11285 double average_rating,
286 int rating_count) {
rdevlin.cronin5f6b69d2014-09-20 01:23:35287 CHECK(AllowWebstoreData(type_));
[email protected]c82da8c42012-06-08 19:49:11288 localized_user_count_ = localized_user_count;
[email protected]dcde34b32013-07-31 02:28:45289 show_user_count_ = show_user_count;
[email protected]c82da8c42012-06-08 19:49:11290 average_rating_ = average_rating;
291 rating_count_ = rating_count;
[email protected]34b5f7f2014-01-29 02:48:11292 has_webstore_data_ = true;
[email protected]c82da8c42012-06-08 19:49:11293}
294
[email protected]6a72a632013-12-12 22:22:00295base::string16 ExtensionInstallPrompt::Prompt::GetDialogTitle() const {
[email protected]c82da8c42012-06-08 19:49:11296 int resource_id = kTitleIds[type_];
297
298 if (type_ == INSTALL_PROMPT) {
299 if (extension_->is_app())
300 resource_id = IDS_EXTENSION_INSTALL_APP_PROMPT_TITLE;
301 else if (extension_->is_theme())
302 resource_id = IDS_EXTENSION_INSTALL_THEME_PROMPT_TITLE;
303 else
304 resource_id = IDS_EXTENSION_INSTALL_EXTENSION_PROMPT_TITLE;
[email protected]612a1cb12012-10-17 13:18:03305 } else if (type_ == EXTERNAL_INSTALL_PROMPT) {
306 return l10n_util::GetStringFUTF16(
[email protected]04338722013-12-24 23:18:05307 resource_id, base::UTF8ToUTF16(extension_->name()));
[email protected]21db9ef2014-05-16 02:06:27308 } else if (type_ == REMOTE_INSTALL_PROMPT) {
309 if (extension_->is_app())
310 resource_id = IDS_EXTENSION_REMOTE_INSTALL_APP_PROMPT_TITLE;
311 else
312 resource_id = IDS_EXTENSION_REMOTE_INSTALL_EXTENSION_PROMPT_TITLE;
rdevlin.cronin5f6b69d2014-09-20 01:23:35313 } else if (type_ == REPAIR_PROMPT) {
314 if (extension_->is_app())
315 resource_id = IDS_EXTENSION_REPAIR_APP_PROMPT_TITLE;
316 else
317 resource_id = IDS_EXTENSION_REPAIR_EXTENSION_PROMPT_TITLE;
[email protected]c82da8c42012-06-08 19:49:11318 }
319
320 return l10n_util::GetStringUTF16(resource_id);
321}
322
[email protected]6a72a632013-12-12 22:22:00323base::string16 ExtensionInstallPrompt::Prompt::GetHeading() const {
[email protected]c82da8c42012-06-08 19:49:11324 if (type_ == INLINE_INSTALL_PROMPT) {
[email protected]04338722013-12-24 23:18:05325 return base::UTF8ToUTF16(extension_->name());
[email protected]c82da8c42012-06-08 19:49:11326 } else if (type_ == BUNDLE_INSTALL_PROMPT) {
327 return bundle_->GetHeadingTextFor(BundleInstaller::Item::STATE_PENDING);
[email protected]612a1cb12012-10-17 13:18:03328 } else if (type_ == EXTERNAL_INSTALL_PROMPT) {
[email protected]846606012012-10-19 18:42:25329 int resource_id = -1;
330 if (extension_->is_app())
331 resource_id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_HEADING_APP;
332 else if (extension_->is_theme())
333 resource_id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_HEADING_THEME;
334 else
335 resource_id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_HEADING_EXTENSION;
336 return l10n_util::GetStringUTF16(resource_id);
[email protected]c82da8c42012-06-08 19:49:11337 } else {
338 return l10n_util::GetStringFUTF16(
[email protected]04338722013-12-24 23:18:05339 kHeadingIds[type_], base::UTF8ToUTF16(extension_->name()));
[email protected]c82da8c42012-06-08 19:49:11340 }
341}
342
[email protected]15d267b42013-02-14 23:43:32343int ExtensionInstallPrompt::Prompt::GetDialogButtons() const {
reillygc64d3dd2014-09-29 21:10:11344 if (type_ == POST_INSTALL_PERMISSIONS_PROMPT && ShouldDisplayRevokeButton()) {
[email protected]a2886e8b2013-06-08 05:15:02345 return kButtons[type_] | ui::DIALOG_BUTTON_OK;
346 }
347
[email protected]15d267b42013-02-14 23:43:32348 return kButtons[type_];
349}
350
[email protected]62a28d7c2013-12-28 01:34:49351bool ExtensionInstallPrompt::Prompt::ShouldShowExplanationText() const {
dchengc7047942014-08-26 05:05:31352 return type_ == INSTALL_PROMPT && extension_->is_extension() &&
353 experiment_.get() && experiment_->text_only();
[email protected]62a28d7c2013-12-28 01:34:49354}
355
[email protected]15d267b42013-02-14 23:43:32356bool ExtensionInstallPrompt::Prompt::HasAcceptButtonLabel() const {
reillygc64d3dd2014-09-29 21:10:11357 if (type_ == POST_INSTALL_PERMISSIONS_PROMPT)
358 return ShouldDisplayRevokeButton();
359
[email protected]a2886e8b2013-06-08 05:15:02360 if (kAcceptButtonIds[type_] == 0)
361 return false;
362
[email protected]a2886e8b2013-06-08 05:15:02363 return true;
[email protected]15d267b42013-02-14 23:43:32364}
365
[email protected]6a72a632013-12-12 22:22:00366base::string16 ExtensionInstallPrompt::Prompt::GetAcceptButtonLabel() const {
[email protected]846606012012-10-19 18:42:25367 if (type_ == EXTERNAL_INSTALL_PROMPT) {
368 int id = -1;
369 if (extension_->is_app())
370 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_APP;
371 else if (extension_->is_theme())
372 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_THEME;
373 else
374 id = IDS_EXTENSION_EXTERNAL_INSTALL_PROMPT_ACCEPT_BUTTON_EXTENSION;
375 return l10n_util::GetStringUTF16(id);
reillygc64d3dd2014-09-29 21:10:11376 } else if (type_ == POST_INSTALL_PERMISSIONS_PROMPT) {
377 int id = -1;
378 if (GetRetainedFileCount() && GetRetainedDeviceCount()) {
379 id =
380 IDS_EXTENSION_PROMPT_PERMISSIONS_CLEAR_RETAINED_FILES_AND_DEVICES_BUTTON;
381 } else if (GetRetainedFileCount()) {
382 id = IDS_EXTENSION_PROMPT_PERMISSIONS_CLEAR_RETAINED_FILES_BUTTON;
383 } else {
384 DCHECK_LT(0U, GetRetainedDeviceCount());
385 id = IDS_EXTENSION_PROMPT_PERMISSIONS_CLEAR_RETAINED_DEVICES_BUTTON;
386 }
387 return l10n_util::GetStringUTF16(id);
[email protected]846606012012-10-19 18:42:25388 }
[email protected]62a28d7c2013-12-28 01:34:49389 if (ShouldShowExplanationText())
390 return experiment_->GetOkButtonText();
[email protected]c82da8c42012-06-08 19:49:11391 return l10n_util::GetStringUTF16(kAcceptButtonIds[type_]);
392}
393
394bool ExtensionInstallPrompt::Prompt::HasAbortButtonLabel() const {
[email protected]62a28d7c2013-12-28 01:34:49395 if (ShouldShowExplanationText())
396 return true;
[email protected]c82da8c42012-06-08 19:49:11397 return kAbortButtonIds[type_] > 0;
398}
399
[email protected]6a72a632013-12-12 22:22:00400base::string16 ExtensionInstallPrompt::Prompt::GetAbortButtonLabel() const {
[email protected]c82da8c42012-06-08 19:49:11401 CHECK(HasAbortButtonLabel());
[email protected]62a28d7c2013-12-28 01:34:49402 if (ShouldShowExplanationText())
403 return experiment_->GetCancelButtonText();
[email protected]c82da8c42012-06-08 19:49:11404 return l10n_util::GetStringUTF16(kAbortButtonIds[type_]);
405}
406
gpdavis.chromium0fbac4d2014-09-19 20:57:54407base::string16 ExtensionInstallPrompt::Prompt::GetPermissionsHeading(
408 PermissionsType permissions_type) const {
409 switch (permissions_type) {
410 case REGULAR_PERMISSIONS:
411 return l10n_util::GetStringUTF16(kPermissionsHeaderIds[type_]);
412 case WITHHELD_PERMISSIONS:
413 return l10n_util::GetStringUTF16(IDS_EXTENSION_PROMPT_WITHHELD);
414 case ALL_PERMISSIONS:
415 default:
416 NOTREACHED();
417 return base::string16();
418 }
[email protected]c82da8c42012-06-08 19:49:11419}
420
[email protected]6a72a632013-12-12 22:22:00421base::string16 ExtensionInstallPrompt::Prompt::GetRetainedFilesHeading() const {
[email protected]4f1e1082013-09-23 10:30:53422 const int kRetainedFilesMessageIDs[6] = {
423 IDS_EXTENSION_PROMPT_RETAINED_FILES_DEFAULT,
424 IDS_EXTENSION_PROMPT_RETAINED_FILE_SINGULAR,
425 IDS_EXTENSION_PROMPT_RETAINED_FILES_ZERO,
426 IDS_EXTENSION_PROMPT_RETAINED_FILES_TWO,
427 IDS_EXTENSION_PROMPT_RETAINED_FILES_FEW,
428 IDS_EXTENSION_PROMPT_RETAINED_FILES_MANY,
429 };
reillygc64d3dd2014-09-29 21:10:11430 std::vector<int> message_ids(
431 kRetainedFilesMessageIDs,
432 kRetainedFilesMessageIDs + arraysize(kRetainedFilesMessageIDs));
433
[email protected]4f1e1082013-09-23 10:30:53434 return l10n_util::GetPluralStringFUTF16(message_ids, GetRetainedFileCount());
[email protected]8ab7e6c2013-07-11 21:15:03435}
436
reillygc64d3dd2014-09-29 21:10:11437base::string16 ExtensionInstallPrompt::Prompt::GetRetainedDevicesHeading()
438 const {
439 const int kRetainedDevicesMessageIDs[6] = {
440 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_DEFAULT,
441 IDS_EXTENSION_PROMPT_RETAINED_DEVICE_SINGULAR,
442 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_ZERO,
443 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_TWO,
444 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_FEW,
445 IDS_EXTENSION_PROMPT_RETAINED_DEVICES_MANY,
446 };
447 std::vector<int> message_ids(
448 kRetainedDevicesMessageIDs,
449 kRetainedDevicesMessageIDs + arraysize(kRetainedDevicesMessageIDs));
450
451 return l10n_util::GetPluralStringFUTF16(message_ids,
452 GetRetainedDeviceCount());
453}
454
[email protected]f2cd8992013-06-11 17:30:18455bool ExtensionInstallPrompt::Prompt::ShouldShowPermissions() const {
gpdavis.chromium0fbac4d2014-09-19 20:57:54456 return GetPermissionCount(ALL_PERMISSIONS) > 0 ||
457 type_ == POST_INSTALL_PERMISSIONS_PROMPT;
[email protected]f2cd8992013-06-11 17:30:18458}
459
[email protected]c82da8c42012-06-08 19:49:11460void ExtensionInstallPrompt::Prompt::AppendRatingStars(
461 StarAppender appender, void* data) const {
462 CHECK(appender);
rdevlin.cronin5f6b69d2014-09-20 01:23:35463 CHECK(AllowWebstoreData(type_));
[email protected]c82da8c42012-06-08 19:49:11464 int rating_integer = floor(average_rating_);
465 double rating_fractional = average_rating_ - rating_integer;
466
467 if (rating_fractional > 0.66) {
468 rating_integer++;
469 }
470
471 if (rating_fractional < 0.33 || rating_fractional > 0.66) {
472 rating_fractional = 0;
473 }
474
475 ResourceBundle& rb = ResourceBundle::GetSharedInstance();
476 int i;
477 for (i = 0; i < rating_integer; i++) {
478 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_ON), data);
479 }
480 if (rating_fractional) {
481 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_HALF_LEFT), data);
482 i++;
483 }
484 for (; i < kMaxExtensionRating; i++) {
485 appender(rb.GetImageSkiaNamed(IDR_EXTENSIONS_RATING_STAR_OFF), data);
486 }
487}
488
[email protected]6a72a632013-12-12 22:22:00489base::string16 ExtensionInstallPrompt::Prompt::GetRatingCount() const {
rdevlin.cronin5f6b69d2014-09-20 01:23:35490 CHECK(AllowWebstoreData(type_));
[email protected]6725048e2013-10-24 21:47:14491 return l10n_util::GetStringFUTF16(IDS_EXTENSION_RATING_COUNT,
492 base::IntToString16(rating_count_));
[email protected]c82da8c42012-06-08 19:49:11493}
494
[email protected]6a72a632013-12-12 22:22:00495base::string16 ExtensionInstallPrompt::Prompt::GetUserCount() const {
rdevlin.cronin5f6b69d2014-09-20 01:23:35496 CHECK(AllowWebstoreData(type_));
[email protected]dcde34b32013-07-31 02:28:45497
498 if (show_user_count_) {
[email protected]6725048e2013-10-24 21:47:14499 return l10n_util::GetStringFUTF16(IDS_EXTENSION_USER_COUNT,
500 base::UTF8ToUTF16(localized_user_count_));
[email protected]dcde34b32013-07-31 02:28:45501 }
[email protected]6725048e2013-10-24 21:47:14502 return base::string16();
[email protected]c82da8c42012-06-08 19:49:11503}
504
gpdavis.chromium0fbac4d2014-09-19 20:57:54505size_t ExtensionInstallPrompt::Prompt::GetPermissionCount(
506 PermissionsType permissions_type) const {
507 switch (permissions_type) {
508 case REGULAR_PERMISSIONS:
509 return prompt_permissions_.permissions.size();
510 case WITHHELD_PERMISSIONS:
511 return withheld_prompt_permissions_.permissions.size();
512 case ALL_PERMISSIONS:
513 return prompt_permissions_.permissions.size() +
514 withheld_prompt_permissions_.permissions.size();
515 default:
516 NOTREACHED();
517 return 0u;
518 }
[email protected]c82da8c42012-06-08 19:49:11519}
520
gpdavis.chromium0fbac4d2014-09-19 20:57:54521size_t ExtensionInstallPrompt::Prompt::GetPermissionsDetailsCount(
522 PermissionsType permissions_type) const {
523 switch (permissions_type) {
524 case REGULAR_PERMISSIONS:
525 return prompt_permissions_.details.size();
526 case WITHHELD_PERMISSIONS:
527 return withheld_prompt_permissions_.details.size();
528 case ALL_PERMISSIONS:
529 return prompt_permissions_.details.size() +
530 withheld_prompt_permissions_.details.size();
531 default:
532 NOTREACHED();
533 return 0u;
534 }
[email protected]8ab7e6c2013-07-11 21:15:03535}
536
gpdavis.chromium0fbac4d2014-09-19 20:57:54537base::string16 ExtensionInstallPrompt::Prompt::GetPermission(
538 size_t index,
539 PermissionsType permissions_type) const {
540 const InstallPromptPermissions& install_permissions =
541 GetPermissionsForType(permissions_type);
542 CHECK_LT(index, install_permissions.permissions.size());
543 return install_permissions.permissions[index];
[email protected]c82da8c42012-06-08 19:49:11544}
545
[email protected]6a72a632013-12-12 22:22:00546base::string16 ExtensionInstallPrompt::Prompt::GetPermissionsDetails(
gpdavis.chromium0fbac4d2014-09-19 20:57:54547 size_t index,
548 PermissionsType permissions_type) const {
549 const InstallPromptPermissions& install_permissions =
550 GetPermissionsForType(permissions_type);
551 CHECK_LT(index, install_permissions.details.size());
552 return install_permissions.details[index];
[email protected]8ab7e6c2013-07-11 21:15:03553}
554
[email protected]79a6f99a2013-08-29 00:32:58555bool ExtensionInstallPrompt::Prompt::GetIsShowingDetails(
556 DetailsType type, size_t index) const {
557 switch (type) {
558 case PERMISSIONS_DETAILS:
gpdavis.chromium0fbac4d2014-09-19 20:57:54559 CHECK_LT(index, prompt_permissions_.is_showing_details.size());
560 return prompt_permissions_.is_showing_details[index];
561 case WITHHELD_PERMISSIONS_DETAILS:
562 CHECK_LT(index, withheld_prompt_permissions_.is_showing_details.size());
563 return withheld_prompt_permissions_.is_showing_details[index];
[email protected]79a6f99a2013-08-29 00:32:58564 case RETAINED_FILES_DETAILS:
565 return is_showing_details_for_retained_files_;
reillygc64d3dd2014-09-29 21:10:11566 case RETAINED_DEVICES_DETAILS:
567 return is_showing_details_for_retained_devices_;
[email protected]79a6f99a2013-08-29 00:32:58568 }
569 return false;
570}
571
[email protected]a2886e8b2013-06-08 05:15:02572size_t ExtensionInstallPrompt::Prompt::GetRetainedFileCount() const {
573 return retained_files_.size();
574}
575
[email protected]6a72a632013-12-12 22:22:00576base::string16 ExtensionInstallPrompt::Prompt::GetRetainedFile(size_t index)
577 const {
[email protected]a2886e8b2013-06-08 05:15:02578 CHECK_LT(index, retained_files_.size());
[email protected]6725048e2013-10-24 21:47:14579 return retained_files_[index].AsUTF16Unsafe();
[email protected]a2886e8b2013-06-08 05:15:02580}
581
reillygc64d3dd2014-09-29 21:10:11582size_t ExtensionInstallPrompt::Prompt::GetRetainedDeviceCount() const {
583 return retained_device_messages_.size();
584}
585
586base::string16 ExtensionInstallPrompt::Prompt::GetRetainedDeviceMessageString(
587 size_t index) const {
588 CHECK_LT(index, retained_device_messages_.size());
589 return retained_device_messages_[index];
590}
591
592bool ExtensionInstallPrompt::Prompt::ShouldDisplayRevokeButton() const {
593 return !retained_files_.empty() || !retained_device_messages_.empty();
594}
595
gpdavis.chromium0fbac4d2014-09-19 20:57:54596ExtensionInstallPrompt::Prompt::InstallPromptPermissions&
597ExtensionInstallPrompt::Prompt::GetPermissionsForType(
598 PermissionsType permissions_type) {
599 DCHECK_NE(ALL_PERMISSIONS, permissions_type);
600 return permissions_type == REGULAR_PERMISSIONS ? prompt_permissions_
601 : withheld_prompt_permissions_;
602}
603
604const ExtensionInstallPrompt::Prompt::InstallPromptPermissions&
605ExtensionInstallPrompt::Prompt::GetPermissionsForType(
606 PermissionsType permissions_type) const {
607 DCHECK_NE(ALL_PERMISSIONS, permissions_type);
608 return permissions_type == REGULAR_PERMISSIONS ? prompt_permissions_
609 : withheld_prompt_permissions_;
610}
611
[email protected]a2886e8b2013-06-08 05:15:02612bool ExtensionInstallPrompt::Prompt::ShouldDisplayRevokeFilesButton() const {
613 return !retained_files_.empty();
614}
615
[email protected]5db2e882012-12-20 10:17:26616ExtensionInstallPrompt::ShowParams::ShowParams(content::WebContents* contents)
617 : parent_web_contents(contents),
618 parent_window(NativeWindowForWebContents(contents)),
619 navigator(contents) {
620}
621
622ExtensionInstallPrompt::ShowParams::ShowParams(
623 gfx::NativeWindow window,
624 content::PageNavigator* navigator)
625 : parent_web_contents(NULL),
626 parent_window(window),
627 navigator(navigator) {
628}
629
[email protected]c82da8c42012-06-08 19:49:11630// static
631scoped_refptr<Extension>
632 ExtensionInstallPrompt::GetLocalizedExtensionForDisplay(
[email protected]023b3d12013-12-23 18:46:49633 const base::DictionaryValue* manifest,
[email protected]c422a862012-07-31 15:46:13634 int flags,
[email protected]c82da8c42012-06-08 19:49:11635 const std::string& id,
636 const std::string& localized_name,
637 const std::string& localized_description,
638 std::string* error) {
[email protected]023b3d12013-12-23 18:46:49639 scoped_ptr<base::DictionaryValue> localized_manifest;
[email protected]c82da8c42012-06-08 19:49:11640 if (!localized_name.empty() || !localized_description.empty()) {
641 localized_manifest.reset(manifest->DeepCopy());
642 if (!localized_name.empty()) {
[email protected]6bf90612013-08-15 00:36:27643 localized_manifest->SetString(extensions::manifest_keys::kName,
[email protected]c82da8c42012-06-08 19:49:11644 localized_name);
645 }
646 if (!localized_description.empty()) {
[email protected]6bf90612013-08-15 00:36:27647 localized_manifest->SetString(extensions::manifest_keys::kDescription,
[email protected]c82da8c42012-06-08 19:49:11648 localized_description);
649 }
650 }
651
652 return Extension::Create(
[email protected]650b2d52013-02-10 03:41:45653 base::FilePath(),
[email protected]1d5e58b2013-01-31 08:41:40654 Manifest::INTERNAL,
[email protected]c82da8c42012-06-08 19:49:11655 localized_manifest.get() ? *localized_manifest.get() : *manifest,
[email protected]c422a862012-07-31 15:46:13656 flags,
[email protected]c82da8c42012-06-08 19:49:11657 id,
658 error);
659}
660
[email protected]7f165342014-02-12 09:22:22661ExtensionInstallPrompt::ExtensionInstallPrompt(content::WebContents* contents)
pkotwicza57a1f322014-10-21 00:24:30662 : profile_(ProfileForWebContents(contents)),
663 ui_loop_(base::MessageLoop::current()),
[email protected]c82da8c42012-06-08 19:49:11664 extension_(NULL),
[email protected]7f165342014-02-12 09:22:22665 bundle_(NULL),
pkotwicza57a1f322014-10-21 00:24:30666 install_ui_(extensions::CreateExtensionInstallUI(
667 ProfileForWebContents(contents))),
[email protected]5db2e882012-12-20 10:17:26668 show_params_(contents),
[email protected]d382baa2014-06-17 18:50:01669 delegate_(NULL) {
670}
[email protected]5db2e882012-12-20 10:17:26671
672ExtensionInstallPrompt::ExtensionInstallPrompt(
673 Profile* profile,
674 gfx::NativeWindow native_window,
675 content::PageNavigator* navigator)
pkotwicza57a1f322014-10-21 00:24:30676 : profile_(profile),
677 ui_loop_(base::MessageLoop::current()),
[email protected]5db2e882012-12-20 10:17:26678 extension_(NULL),
[email protected]7f165342014-02-12 09:22:22679 bundle_(NULL),
pkotwicza57a1f322014-10-21 00:24:30680 install_ui_(extensions::CreateExtensionInstallUI(profile)),
[email protected]5db2e882012-12-20 10:17:26681 show_params_(native_window, navigator),
[email protected]d382baa2014-06-17 18:50:01682 delegate_(NULL) {
683}
[email protected]c82da8c42012-06-08 19:49:11684
685ExtensionInstallPrompt::~ExtensionInstallPrompt() {
686}
687
688void ExtensionInstallPrompt::ConfirmBundleInstall(
689 extensions::BundleInstaller* bundle,
[email protected]c2e66e12012-06-27 06:27:06690 const PermissionSet* permissions) {
[email protected]b3a25092013-05-28 22:08:16691 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11692 bundle_ = bundle;
gpdavis.chromium0fbac4d2014-09-19 20:57:54693 custom_permissions_ = permissions;
[email protected]c82da8c42012-06-08 19:49:11694 delegate_ = bundle;
[email protected]d382baa2014-06-17 18:50:01695 prompt_ = new Prompt(BUNDLE_INSTALL_PROMPT);
[email protected]c82da8c42012-06-08 19:49:11696
[email protected]4e494872013-09-06 09:13:54697 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11698}
699
[email protected]734bcec2012-10-08 20:29:05700void ExtensionInstallPrompt::ConfirmStandaloneInstall(
[email protected]c82da8c42012-06-08 19:49:11701 Delegate* delegate,
702 const Extension* extension,
703 SkBitmap* icon,
[email protected]d382baa2014-06-17 18:50:01704 scoped_refptr<Prompt> prompt) {
[email protected]b3a25092013-05-28 22:08:16705 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11706 extension_ = extension;
[email protected]c82da8c42012-06-08 19:49:11707 delegate_ = delegate;
708 prompt_ = prompt;
[email protected]c82da8c42012-06-08 19:49:11709
710 SetIcon(icon);
[email protected]4e494872013-09-06 09:13:54711 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11712}
713
[email protected]af6efb22012-10-12 02:23:05714void ExtensionInstallPrompt::ConfirmWebstoreInstall(
715 Delegate* delegate,
716 const Extension* extension,
717 const SkBitmap* icon,
718 const ShowDialogCallback& show_dialog_callback) {
[email protected]c82da8c42012-06-08 19:49:11719 // SetIcon requires |extension_| to be set. ConfirmInstall will setup the
720 // remaining fields.
721 extension_ = extension;
722 SetIcon(icon);
[email protected]af6efb22012-10-12 02:23:05723 ConfirmInstall(delegate, extension, show_dialog_callback);
[email protected]c82da8c42012-06-08 19:49:11724}
725
[email protected]af6efb22012-10-12 02:23:05726void ExtensionInstallPrompt::ConfirmInstall(
727 Delegate* delegate,
728 const Extension* extension,
729 const ShowDialogCallback& show_dialog_callback) {
[email protected]b3a25092013-05-28 22:08:16730 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11731 extension_ = extension;
[email protected]c82da8c42012-06-08 19:49:11732 delegate_ = delegate;
[email protected]d382baa2014-06-17 18:50:01733 prompt_ = new Prompt(INSTALL_PROMPT);
[email protected]af6efb22012-10-12 02:23:05734 show_dialog_callback_ = show_dialog_callback;
[email protected]c82da8c42012-06-08 19:49:11735
736 // We special-case themes to not show any confirm UI. Instead they are
737 // immediately installed, and then we show an infobar (see OnInstallSuccess)
738 // to allow the user to revert if they don't like it.
739 //
740 // We don't do this in the case where off-store extension installs are
741 // disabled because in that case, we don't show the dangerous download UI, so
742 // we need the UI confirmation.
743 if (extension->is_theme()) {
744 if (extension->from_webstore() ||
[email protected]544471a2012-10-13 05:27:09745 extensions::FeatureSwitch::easy_off_store_install()->IsEnabled()) {
[email protected]c82da8c42012-06-08 19:49:11746 delegate->InstallUIProceed();
747 return;
748 }
749 }
750
751 LoadImageIfNeeded();
752}
753
754void ExtensionInstallPrompt::ConfirmReEnable(Delegate* delegate,
755 const Extension* extension) {
[email protected]b3a25092013-05-28 22:08:16756 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11757 extension_ = extension;
[email protected]c82da8c42012-06-08 19:49:11758 delegate_ = delegate;
[email protected]21db9ef2014-05-16 02:06:27759 bool is_remote_install =
pkotwicza57a1f322014-10-21 00:24:30760 profile_ &&
761 extensions::ExtensionPrefs::Get(profile_)->HasDisableReason(
[email protected]21db9ef2014-05-16 02:06:27762 extension->id(), extensions::Extension::DISABLE_REMOTE_INSTALL);
[email protected]411f8ae2014-05-22 11:12:23763 bool is_ephemeral =
pkotwicza57a1f322014-10-21 00:24:30764 extensions::util::IsEphemeralApp(extension->id(), profile_);
[email protected]d382baa2014-06-17 18:50:01765
766 PromptType type = UNSET_PROMPT_TYPE;
[email protected]411f8ae2014-05-22 11:12:23767 if (is_ephemeral)
[email protected]d382baa2014-06-17 18:50:01768 type = LAUNCH_PROMPT;
[email protected]21db9ef2014-05-16 02:06:27769 else if (is_remote_install)
[email protected]d382baa2014-06-17 18:50:01770 type = REMOTE_INSTALL_PROMPT;
[email protected]21db9ef2014-05-16 02:06:27771 else
[email protected]d382baa2014-06-17 18:50:01772 type = RE_ENABLE_PROMPT;
773 prompt_ = new Prompt(type);
774
[email protected]c82da8c42012-06-08 19:49:11775 LoadImageIfNeeded();
776}
777
[email protected]612a1cb12012-10-17 13:18:03778void ExtensionInstallPrompt::ConfirmExternalInstall(
[email protected]c8ff7c9e2013-04-20 12:36:27779 Delegate* delegate,
780 const Extension* extension,
[email protected]34b5f7f2014-01-29 02:48:11781 const ShowDialogCallback& show_dialog_callback,
[email protected]d382baa2014-06-17 18:50:01782 scoped_refptr<Prompt> prompt) {
[email protected]b3a25092013-05-28 22:08:16783 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]612a1cb12012-10-17 13:18:03784 extension_ = extension;
[email protected]612a1cb12012-10-17 13:18:03785 delegate_ = delegate;
[email protected]34b5f7f2014-01-29 02:48:11786 prompt_ = prompt;
[email protected]c8ff7c9e2013-04-20 12:36:27787 show_dialog_callback_ = show_dialog_callback;
[email protected]612a1cb12012-10-17 13:18:03788
789 LoadImageIfNeeded();
790}
791
[email protected]c82da8c42012-06-08 19:49:11792void ExtensionInstallPrompt::ConfirmPermissions(
793 Delegate* delegate,
794 const Extension* extension,
[email protected]c2e66e12012-06-27 06:27:06795 const PermissionSet* permissions) {
[email protected]b3a25092013-05-28 22:08:16796 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]c82da8c42012-06-08 19:49:11797 extension_ = extension;
gpdavis.chromium0fbac4d2014-09-19 20:57:54798 custom_permissions_ = permissions;
[email protected]c82da8c42012-06-08 19:49:11799 delegate_ = delegate;
[email protected]d382baa2014-06-17 18:50:01800 prompt_ = new Prompt(PERMISSIONS_PROMPT);
[email protected]c82da8c42012-06-08 19:49:11801
802 LoadImageIfNeeded();
803}
804
[email protected]a2886e8b2013-06-08 05:15:02805void ExtensionInstallPrompt::ReviewPermissions(
806 Delegate* delegate,
807 const Extension* extension,
reillygc64d3dd2014-09-29 21:10:11808 const std::vector<base::FilePath>& retained_file_paths,
809 const std::vector<base::string16>& retained_device_messages) {
[email protected]b3a25092013-05-28 22:08:16810 DCHECK(ui_loop_ == base::MessageLoop::current());
[email protected]15d267b42013-02-14 23:43:32811 extension_ = extension;
[email protected]d382baa2014-06-17 18:50:01812 prompt_ = new Prompt(POST_INSTALL_PERMISSIONS_PROMPT);
813 prompt_->set_retained_files(retained_file_paths);
reillygc64d3dd2014-09-29 21:10:11814 prompt_->set_retained_device_messages(retained_device_messages);
[email protected]15d267b42013-02-14 23:43:32815 delegate_ = delegate;
[email protected]15d267b42013-02-14 23:43:32816
817 LoadImageIfNeeded();
818}
819
[email protected]c82da8c42012-06-08 19:49:11820void ExtensionInstallPrompt::OnInstallSuccess(const Extension* extension,
821 SkBitmap* icon) {
822 extension_ = extension;
823 SetIcon(icon);
824
825 install_ui_->OnInstallSuccess(extension, &icon_);
826}
827
[email protected]bf3d9df2012-07-24 23:20:27828void ExtensionInstallPrompt::OnInstallFailure(
829 const extensions::CrxInstallerError& error) {
[email protected]c82da8c42012-06-08 19:49:11830 install_ui_->OnInstallFailure(error);
831}
832
833void ExtensionInstallPrompt::SetIcon(const SkBitmap* image) {
834 if (image)
835 icon_ = *image;
836 else
837 icon_ = SkBitmap();
[email protected]dd46a4ce2012-09-15 10:50:50838 if (icon_.empty()) {
839 // Let's set default icon bitmap whose size is equal to the default icon's
840 // pixel size under maximal supported scale factor. If the bitmap is larger
841 // than the one we need, it will be scaled down by the ui code.
842 icon_ = GetDefaultIconBitmapForMaxScaleFactor(extension_->is_app());
843 }
[email protected]c82da8c42012-06-08 19:49:11844}
845
[email protected]ec7de0c5a2012-11-16 07:40:47846void ExtensionInstallPrompt::OnImageLoaded(const gfx::Image& image) {
[email protected]c82da8c42012-06-08 19:49:11847 SetIcon(image.IsEmpty() ? NULL : image.ToSkBitmap());
[email protected]4e494872013-09-06 09:13:54848 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11849}
850
851void ExtensionInstallPrompt::LoadImageIfNeeded() {
852 // Bundle install prompts do not have an icon.
pkotwicza57a1f322014-10-21 00:24:30853 // Also |profile_| can be NULL in unit tests.
854 if (!icon_.empty() || !profile_) {
[email protected]4e494872013-09-06 09:13:54855 ShowConfirmation();
[email protected]c82da8c42012-06-08 19:49:11856 return;
857 }
858
[email protected]993da5e2013-03-23 21:25:16859 extensions::ExtensionResource image = extensions::IconsInfo::GetIconResource(
[email protected]702d8b42013-02-27 20:55:50860 extension_,
861 extension_misc::EXTENSION_ICON_LARGE,
862 ExtensionIconSet::MATCH_BIGGER);
[email protected]0d0ba182014-06-03 12:40:43863
864 // Load the image asynchronously. The response will be sent to OnImageLoaded.
pkotwicza57a1f322014-10-21 00:24:30865 extensions::ImageLoader* loader = extensions::ImageLoader::Get(profile_);
[email protected]0d0ba182014-06-03 12:40:43866
867 std::vector<extensions::ImageLoader::ImageRepresentation> images_list;
868 images_list.push_back(extensions::ImageLoader::ImageRepresentation(
869 image,
870 extensions::ImageLoader::ImageRepresentation::NEVER_RESIZE,
871 gfx::Size(),
872 ui::SCALE_FACTOR_100P));
873 loader->LoadImagesAsync(
874 extension_,
875 images_list,
[email protected]ec7de0c5a2012-11-16 07:40:47876 base::Bind(&ExtensionInstallPrompt::OnImageLoaded, AsWeakPtr()));
[email protected]c82da8c42012-06-08 19:49:11877}
878
[email protected]c82da8c42012-06-08 19:49:11879void ExtensionInstallPrompt::ShowConfirmation() {
[email protected]d382baa2014-06-17 18:50:01880 if (prompt_->type() == INSTALL_PROMPT)
881 prompt_->set_experiment(ExtensionInstallPromptExperiment::Find());
[email protected]62a28d7c2013-12-28 01:34:49882 else
[email protected]d382baa2014-06-17 18:50:01883 prompt_->set_experiment(ExtensionInstallPromptExperiment::ControlGroup());
[email protected]62a28d7c2013-12-28 01:34:49884
gpdavis.chromium0fbac4d2014-09-19 20:57:54885 scoped_refptr<const PermissionSet> permissions_to_display;
886 if (custom_permissions_.get()) {
887 permissions_to_display = custom_permissions_;
888 } else if (extension_) {
889 // Initialize permissions if they have not already been set so that
890 // withheld permissions are displayed properly in the install prompt.
891 extensions::PermissionsUpdater(
pkotwicza57a1f322014-10-21 00:24:30892 profile_, extensions::PermissionsUpdater::INIT_FLAG_TRANSIENT)
gpdavis.chromium0fbac4d2014-09-19 20:57:54893 .InitializePermissions(extension_);
894 permissions_to_display =
895 extension_->permissions_data()->active_permissions();
896 }
897
898 if (permissions_to_display.get() &&
[email protected]a397ec02014-08-08 15:48:13899 (!extension_ ||
900 !extensions::PermissionsData::ShouldSkipPermissionWarnings(
901 extension_->id()))) {
902 Manifest::Type type =
903 extension_ ? extension_->GetType() : Manifest::TYPE_UNKNOWN;
904 const extensions::PermissionMessageProvider* message_provider =
905 extensions::PermissionMessageProvider::Get();
gpdavis.chromium0fbac4d2014-09-19 20:57:54906 prompt_->SetPermissions(message_provider->GetWarningMessages(
907 permissions_to_display.get(), type),
908 REGULAR_PERMISSIONS);
909 prompt_->SetPermissionsDetails(message_provider->GetWarningMessagesDetails(
910 permissions_to_display.get(), type),
911 REGULAR_PERMISSIONS);
912
913 scoped_refptr<const extensions::PermissionSet> withheld =
914 extension_->permissions_data()->withheld_permissions();
915 if (!withheld->IsEmpty()) {
916 prompt_->SetPermissions(
917 message_provider->GetWarningMessages(withheld.get(), type),
918 PermissionsType::WITHHELD_PERMISSIONS);
919 prompt_->SetPermissionsDetails(
920 message_provider->GetWarningMessagesDetails(withheld.get(), type),
921 PermissionsType::WITHHELD_PERMISSIONS);
922 }
[email protected]bebe1d02012-08-02 20:17:09923 }
[email protected]c82da8c42012-06-08 19:49:11924
[email protected]d382baa2014-06-17 18:50:01925 switch (prompt_->type()) {
[email protected]c82da8c42012-06-08 19:49:11926 case PERMISSIONS_PROMPT:
927 case RE_ENABLE_PROMPT:
928 case INLINE_INSTALL_PROMPT:
[email protected]612a1cb12012-10-17 13:18:03929 case EXTERNAL_INSTALL_PROMPT:
[email protected]15d267b42013-02-14 23:43:32930 case INSTALL_PROMPT:
[email protected]1a93d8d2013-10-27 23:09:20931 case LAUNCH_PROMPT:
[email protected]21db9ef2014-05-16 02:06:27932 case POST_INSTALL_PERMISSIONS_PROMPT:
rdevlin.cronin5f6b69d2014-09-20 01:23:35933 case REMOTE_INSTALL_PROMPT:
934 case REPAIR_PROMPT: {
[email protected]d382baa2014-06-17 18:50:01935 prompt_->set_extension(extension_);
936 prompt_->set_icon(gfx::Image::CreateFrom1xBitmap(icon_));
[email protected]c82da8c42012-06-08 19:49:11937 break;
938 }
939 case BUNDLE_INSTALL_PROMPT: {
[email protected]d382baa2014-06-17 18:50:01940 prompt_->set_bundle(bundle_);
[email protected]c82da8c42012-06-08 19:49:11941 break;
942 }
943 default:
944 NOTREACHED() << "Unknown message";
[email protected]af6efb22012-10-12 02:23:05945 return;
[email protected]c82da8c42012-06-08 19:49:11946 }
[email protected]af6efb22012-10-12 02:23:05947
948 if (AutoConfirmPrompt(delegate_))
949 return;
950
[email protected]5db2e882012-12-20 10:17:26951 if (show_dialog_callback_.is_null())
952 GetDefaultShowDialogCallback().Run(show_params_, delegate_, prompt_);
953 else
954 show_dialog_callback_.Run(show_params_, delegate_, prompt_);
[email protected]c82da8c42012-06-08 19:49:11955}