1 // 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.
5 #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_PROMPT_H_
6 #define CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_PROMPT_H_
11 #include "base/callback.h"
12 #include "base/compiler_specific.h"
13 #include "base/files/file_path.h"
14 #include "base/memory/ref_counted.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/memory/weak_ptr.h"
17 #include "base/strings/string16.h"
18 #include "extensions/common/permissions/permission_message_provider.h"
19 #include "extensions/common/url_pattern.h"
20 #include "third_party/skia/include/core/SkBitmap.h"
21 #include "ui/gfx/image/image.h"
22 #include "ui/gfx/image/image_skia.h"
23 #include "ui/gfx/native_widget_types.h"
25 class ExtensionInstallPromptShowParams
;
29 class DictionaryValue
;
37 namespace extensions
{
38 class BundleInstaller
;
39 class CrxInstallError
;
41 class ExtensionInstallUI
;
42 class ExtensionWebstorePrivateApiTest
;
43 class MockGetAuthTokenFunction
;
45 } // namespace extensions
48 class InfoBarDelegate
;
51 // Displays all the UI around extension installation.
52 class ExtensionInstallPrompt
53 : public base::SupportsWeakPtr
<ExtensionInstallPrompt
> {
55 // This enum is associated with Extensions.InstallPrompt_Type UMA histogram.
56 // Do not modify existing values and add new values only to the end.
58 UNSET_PROMPT_TYPE
= -1,
60 INLINE_INSTALL_PROMPT
,
61 BUNDLE_INSTALL_PROMPT
,
64 EXTERNAL_INSTALL_PROMPT
,
65 POST_INSTALL_PERMISSIONS_PROMPT
,
67 REMOTE_INSTALL_PROMPT
,
69 DELEGATED_PERMISSIONS_PROMPT
,
73 // The last prompt type to display; only used for testing.
74 static PromptType g_last_prompt_type_for_tests
;
76 // Enumeration for permissions and retained files details.
78 PERMISSIONS_DETAILS
= 0,
79 WITHHELD_PERMISSIONS_DETAILS
,
80 RETAINED_FILES_DETAILS
,
81 RETAINED_DEVICES_DETAILS
,
84 // This enum is used to differentiate regular and withheld permissions for
85 // segregation in the install prompt.
86 enum PermissionsType
{
87 REGULAR_PERMISSIONS
= 0,
92 static std::string
PromptTypeToString(PromptType type
);
94 // Extra information needed to display an installation or uninstallation
95 // prompt. Gets populated with raw data and exposes getters for formatted
96 // strings so that the GTK/views/Cocoa install dialogs don't have to repeat
98 // Ref-counted because we pass around the prompt independent of the full
99 // ExtensionInstallPrompt.
100 class Prompt
: public base::RefCountedThreadSafe
<Prompt
> {
102 explicit Prompt(PromptType type
);
104 void SetPermissions(const extensions::PermissionMessageStrings
& permissions
,
105 PermissionsType permissions_type
);
106 void SetIsShowingDetails(DetailsType type
,
108 bool is_showing_details
);
109 void SetWebstoreData(const std::string
& localized_user_count
,
110 bool show_user_count
,
111 double average_rating
,
114 PromptType
type() const { return type_
; }
115 void set_type(PromptType type
) { type_
= type
; }
117 // Getters for UI element labels.
118 base::string16
GetDialogTitle() const;
119 int GetDialogButtons() const;
120 // Returns the empty string when there should be no "accept" button.
121 base::string16
GetAcceptButtonLabel() const;
122 base::string16
GetAbortButtonLabel() const;
123 base::string16
GetPermissionsHeading(
124 PermissionsType permissions_type
) const;
125 base::string16
GetRetainedFilesHeading() const;
126 base::string16
GetRetainedDevicesHeading() const;
128 bool ShouldShowPermissions() const;
130 // Getters for webstore metadata. Only populated when the type is
131 // INLINE_INSTALL_PROMPT, EXTERNAL_INSTALL_PROMPT, or REPAIR_PROMPT.
133 // The star display logic replicates the one used by the webstore (from
134 // components.ratingutils.setFractionalYellowStars). Callers pass in an
135 // "appender", which will be repeatedly called back with the star images
136 // that they append to the star display area.
137 typedef void(*StarAppender
)(const gfx::ImageSkia
*, void*);
138 void AppendRatingStars(StarAppender appender
, void* data
) const;
139 base::string16
GetRatingCount() const;
140 base::string16
GetUserCount() const;
141 size_t GetPermissionCount(PermissionsType permissions_type
) const;
142 size_t GetPermissionsDetailsCount(PermissionsType permissions_type
) const;
143 base::string16
GetPermission(size_t index
,
144 PermissionsType permissions_type
) const;
145 base::string16
GetPermissionsDetails(
147 PermissionsType permissions_type
) const;
148 bool GetIsShowingDetails(DetailsType type
, size_t index
) const;
149 size_t GetRetainedFileCount() const;
150 base::string16
GetRetainedFile(size_t index
) const;
151 size_t GetRetainedDeviceCount() const;
152 base::string16
GetRetainedDeviceMessageString(size_t index
) const;
154 // Populated for BUNDLE_INSTALL_PROMPT.
155 const extensions::BundleInstaller
* bundle() const { return bundle_
; }
156 void set_bundle(const extensions::BundleInstaller
* bundle
) {
160 // Populated for all other types.
161 const extensions::Extension
* extension() const { return extension_
; }
162 void set_extension(const extensions::Extension
* extension
) {
163 extension_
= extension
;
166 // May be populated for POST_INSTALL_PERMISSIONS_PROMPT.
167 void set_retained_files(const std::vector
<base::FilePath
>& retained_files
) {
168 retained_files_
= retained_files
;
170 void set_retained_device_messages(
171 const std::vector
<base::string16
>& retained_device_messages
) {
172 retained_device_messages_
= retained_device_messages
;
175 const std::string
& delegated_username() const {
176 return delegated_username_
;
178 void set_delegated_username(const std::string
& delegated_username
) {
179 delegated_username_
= delegated_username
;
182 const gfx::Image
& icon() const { return icon_
; }
183 void set_icon(const gfx::Image
& icon
) { icon_
= icon
; }
185 bool has_webstore_data() const { return has_webstore_data_
; }
188 friend class base::RefCountedThreadSafe
<Prompt
>;
190 struct InstallPromptPermissions
{
191 InstallPromptPermissions();
192 ~InstallPromptPermissions();
194 std::vector
<base::string16
> permissions
;
195 std::vector
<base::string16
> details
;
196 std::vector
<bool> is_showing_details
;
201 bool ShouldDisplayRevokeButton() const;
203 // Returns the InstallPromptPermissions corresponding to
204 // |permissions_type|.
205 InstallPromptPermissions
& GetPermissionsForType(
206 PermissionsType permissions_type
);
207 const InstallPromptPermissions
& GetPermissionsForType(
208 PermissionsType permissions_type
) const;
210 bool ShouldDisplayRevokeFilesButton() const;
214 // Permissions that are being requested (may not be all of an extension's
215 // permissions if only additional ones are being requested)
216 InstallPromptPermissions prompt_permissions_
;
217 // Permissions that will be withheld upon install.
218 InstallPromptPermissions withheld_prompt_permissions_
;
220 bool is_showing_details_for_retained_files_
;
221 bool is_showing_details_for_retained_devices_
;
223 // The extension or bundle being installed.
224 const extensions::Extension
* extension_
;
225 const extensions::BundleInstaller
* bundle_
;
227 std::string delegated_username_
;
229 // The icon to be displayed.
232 // These fields are populated only when the prompt type is
233 // INLINE_INSTALL_PROMPT
234 // Already formatted to be locale-specific.
235 std::string localized_user_count_
;
236 // Range is kMinExtensionRating to kMaxExtensionRating
237 double average_rating_
;
240 // Whether we should display the user count (we anticipate this will be
241 // false if localized_user_count_ represents the number zero).
242 bool show_user_count_
;
244 // Whether or not this prompt has been populated with data from the
246 bool has_webstore_data_
;
248 std::vector
<base::FilePath
> retained_files_
;
249 std::vector
<base::string16
> retained_device_messages_
;
251 DISALLOW_COPY_AND_ASSIGN(Prompt
);
254 static const int kMinExtensionRating
= 0;
255 static const int kMaxExtensionRating
= 5;
259 // We call this method to signal that the installation should continue.
260 virtual void InstallUIProceed() = 0;
262 // We call this method to signal that the installation should stop, with
263 // |user_initiated| true if the installation was stopped by the user.
264 virtual void InstallUIAbort(bool user_initiated
) = 0;
267 virtual ~Delegate() {}
270 typedef base::Callback
<void(ExtensionInstallPromptShowParams
*,
271 ExtensionInstallPrompt::Delegate
*,
272 scoped_refptr
<ExtensionInstallPrompt::Prompt
>)>
275 // Callback to show the default extension install dialog.
276 // The implementations of this function are platform-specific.
277 static ShowDialogCallback
GetDefaultShowDialogCallback();
279 // Creates a dummy extension from the |manifest|, replacing the name and
280 // description with the localizations if provided.
281 static scoped_refptr
<extensions::Extension
> GetLocalizedExtensionForDisplay(
282 const base::DictionaryValue
* manifest
,
283 int flags
, // Extension::InitFromValueFlags
284 const std::string
& id
,
285 const std::string
& localized_name
,
286 const std::string
& localized_description
,
289 // Creates a prompt with a parent web content.
290 explicit ExtensionInstallPrompt(content::WebContents
* contents
);
292 // Creates a prompt with a profile and a native window. The most recently
293 // active browser window (or a new browser window if there are no browser
294 // windows) is used if a new tab needs to be opened.
295 ExtensionInstallPrompt(Profile
* profile
, gfx::NativeWindow native_window
);
297 virtual ~ExtensionInstallPrompt();
299 extensions::ExtensionInstallUI
* install_ui() const {
300 return install_ui_
.get();
303 // This is called by the bundle installer to verify whether the bundle
304 // should be installed.
306 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
307 virtual void ConfirmBundleInstall(
308 extensions::BundleInstaller
* bundle
,
309 const SkBitmap
* icon
,
310 const extensions::PermissionSet
* permissions
);
312 // This is called by the standalone installer to verify whether the install
313 // from the webstore should proceed.
315 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
316 virtual void ConfirmStandaloneInstall(Delegate
* delegate
,
317 const extensions::Extension
* extension
,
319 scoped_refptr
<Prompt
> prompt
);
321 // This is called by the installer to verify whether the installation from
322 // the webstore should proceed. |show_dialog_callback| is optional and can be
325 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
326 virtual void ConfirmWebstoreInstall(
328 const extensions::Extension
* extension
,
329 const SkBitmap
* icon
,
330 const ShowDialogCallback
& show_dialog_callback
);
332 // This is called by the installer to verify whether the installation should
333 // proceed. This is declared virtual for testing. |show_dialog_callback| is
334 // optional and can be NULL.
336 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
337 virtual void ConfirmInstall(Delegate
* delegate
,
338 const extensions::Extension
* extension
,
339 const ShowDialogCallback
& show_dialog_callback
);
341 // This is called by the webstore API to verify the permissions for a
342 // delegated install.
344 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
345 virtual void ConfirmPermissionsForDelegatedInstall(
347 const extensions::Extension
* extension
,
348 const std::string
& delegated_username
,
349 const SkBitmap
* icon
);
351 // This is called by the app handler launcher to verify whether the app
352 // should be re-enabled. This is declared virtual for testing.
354 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
355 virtual void ConfirmReEnable(Delegate
* delegate
,
356 const extensions::Extension
* extension
);
358 // This is called by the external install alert UI to verify whether the
359 // extension should be enabled (external extensions are installed disabled).
361 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
362 virtual void ConfirmExternalInstall(
364 const extensions::Extension
* extension
,
365 const ShowDialogCallback
& show_dialog_callback
,
366 scoped_refptr
<Prompt
> prompt
);
368 // This is called by the extension permissions API to verify whether an
369 // extension may be granted additional permissions.
371 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
372 virtual void ConfirmPermissions(Delegate
* delegate
,
373 const extensions::Extension
* extension
,
374 const extensions::PermissionSet
* permissions
);
376 // This is called by the app handler launcher to review what permissions the
377 // extension or app currently has.
379 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
380 virtual void ReviewPermissions(
382 const extensions::Extension
* extension
,
383 const std::vector
<base::FilePath
>& retained_file_paths
,
384 const std::vector
<base::string16
>& retained_device_messages
);
386 // Installation was successful. This is declared virtual for testing.
387 virtual void OnInstallSuccess(const extensions::Extension
* extension
,
390 // Installation failed. This is declared virtual for testing.
391 virtual void OnInstallFailure(const extensions::CrxInstallError
& error
);
393 void set_callback_for_test(const ShowDialogCallback
& show_dialog_callback
) {
394 show_dialog_callback_
= show_dialog_callback
;
398 friend class extensions::ExtensionWebstorePrivateApiTest
;
399 friend class WebstoreStartupInstallUnpackFailureTest
;
401 // Whether or not we should record the oauth2 grant upon successful install.
402 bool record_oauth2_grant_
;
405 friend class GalleryInstallApiTestObserver
;
407 // Sets the icon that will be used in any UI. If |icon| is NULL, or contains
408 // an empty bitmap, then a default icon will be used instead.
409 void SetIcon(const SkBitmap
* icon
);
411 // ImageLoader callback.
412 void OnImageLoaded(const gfx::Image
& image
);
414 // Starts the process of showing a confirmation UI, which is split into two.
415 // 1) Set off a 'load icon' task.
416 // 2) Handle the load icon response and show the UI (OnImageLoaded).
417 void LoadImageIfNeeded();
419 // Shows the actual UI (the icon should already be loaded).
420 void ShowConfirmation();
424 base::MessageLoop
* ui_loop_
;
426 // The extensions installation icon.
429 // The extension we are showing the UI for, if type is not
430 // BUNDLE_INSTALL_PROMPT.
431 const extensions::Extension
* extension_
;
433 // The bundle we are showing the UI for, if type BUNDLE_INSTALL_PROMPT.
434 const extensions::BundleInstaller
* bundle_
;
436 // The name of the user we are asking about, if type
437 // DELEGATED_PERMISSIONS_PROMPT.
438 std::string delegated_username_
;
440 // A custom set of permissions to show in the install prompt instead of the
441 // extension's active permissions.
442 scoped_refptr
<const extensions::PermissionSet
> custom_permissions_
;
444 // The object responsible for doing the UI specific actions.
445 scoped_ptr
<extensions::ExtensionInstallUI
> install_ui_
;
447 // Parameters to show the confirmation UI.
448 scoped_ptr
<ExtensionInstallPromptShowParams
> show_params_
;
450 // The delegate we will call Proceed/Abort on after confirmation UI.
453 // A pre-filled prompt.
454 scoped_refptr
<Prompt
> prompt_
;
456 // Used to show the confirm dialog.
457 ShowDialogCallback show_dialog_callback_
;
460 #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_PROMPT_H_