Add a webstorePrivate API to show a permission prompt for delegated bundle installs
[chromium-blink-merge.git] / chrome / browser / extensions / extension_install_prompt.h
bloba931e5f7673f6980e33ef1de80bd78f28b7a6d17
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_
8 #include <string>
9 #include <vector>
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;
26 class Profile;
28 namespace base {
29 class DictionaryValue;
30 class MessageLoop;
31 } // namespace base
33 namespace content {
34 class WebContents;
37 namespace extensions {
38 class BundleInstaller;
39 class CrxInstallError;
40 class Extension;
41 class ExtensionInstallUI;
42 class ExtensionWebstorePrivateApiTest;
43 class MockGetAuthTokenFunction;
44 class PermissionSet;
45 } // namespace extensions
47 namespace infobars {
48 class InfoBarDelegate;
51 // Displays all the UI around extension installation.
52 class ExtensionInstallPrompt
53 : public base::SupportsWeakPtr<ExtensionInstallPrompt> {
54 public:
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.
57 enum PromptType {
58 UNSET_PROMPT_TYPE = -1,
59 INSTALL_PROMPT = 0,
60 INLINE_INSTALL_PROMPT,
61 BUNDLE_INSTALL_PROMPT,
62 RE_ENABLE_PROMPT,
63 PERMISSIONS_PROMPT,
64 EXTERNAL_INSTALL_PROMPT,
65 POST_INSTALL_PERMISSIONS_PROMPT,
66 LAUNCH_PROMPT,
67 REMOTE_INSTALL_PROMPT,
68 REPAIR_PROMPT,
69 DELEGATED_PERMISSIONS_PROMPT,
70 DELEGATED_BUNDLE_PERMISSIONS_PROMPT,
71 NUM_PROMPT_TYPES
74 // The last prompt type to display; only used for testing.
75 static PromptType g_last_prompt_type_for_tests;
77 // Enumeration for permissions and retained files details.
78 enum DetailsType {
79 PERMISSIONS_DETAILS = 0,
80 WITHHELD_PERMISSIONS_DETAILS,
81 RETAINED_FILES_DETAILS,
82 RETAINED_DEVICES_DETAILS,
85 // This enum is used to differentiate regular and withheld permissions for
86 // segregation in the install prompt.
87 enum PermissionsType {
88 REGULAR_PERMISSIONS = 0,
89 WITHHELD_PERMISSIONS,
90 ALL_PERMISSIONS,
93 static std::string PromptTypeToString(PromptType type);
95 // Extra information needed to display an installation or uninstallation
96 // prompt. Gets populated with raw data and exposes getters for formatted
97 // strings so that the GTK/views/Cocoa install dialogs don't have to repeat
98 // that logic.
99 // Ref-counted because we pass around the prompt independent of the full
100 // ExtensionInstallPrompt.
101 class Prompt : public base::RefCountedThreadSafe<Prompt> {
102 public:
103 explicit Prompt(PromptType type);
105 void SetPermissions(const extensions::PermissionMessageStrings& permissions,
106 PermissionsType permissions_type);
107 void SetIsShowingDetails(DetailsType type,
108 size_t index,
109 bool is_showing_details);
110 void SetWebstoreData(const std::string& localized_user_count,
111 bool show_user_count,
112 double average_rating,
113 int rating_count);
115 PromptType type() const { return type_; }
116 void set_type(PromptType type) { type_ = type; }
118 // Getters for UI element labels.
119 base::string16 GetDialogTitle() const;
120 int GetDialogButtons() const;
121 // Returns the empty string when there should be no "accept" button.
122 base::string16 GetAcceptButtonLabel() const;
123 base::string16 GetAbortButtonLabel() const;
124 base::string16 GetPermissionsHeading(
125 PermissionsType permissions_type) const;
126 base::string16 GetRetainedFilesHeading() const;
127 base::string16 GetRetainedDevicesHeading() const;
129 bool ShouldShowPermissions() const;
131 // Getters for webstore metadata. Only populated when the type is
132 // INLINE_INSTALL_PROMPT, EXTERNAL_INSTALL_PROMPT, or REPAIR_PROMPT.
134 // The star display logic replicates the one used by the webstore (from
135 // components.ratingutils.setFractionalYellowStars). Callers pass in an
136 // "appender", which will be repeatedly called back with the star images
137 // that they append to the star display area.
138 typedef void(*StarAppender)(const gfx::ImageSkia*, void*);
139 void AppendRatingStars(StarAppender appender, void* data) const;
140 base::string16 GetRatingCount() const;
141 base::string16 GetUserCount() const;
142 size_t GetPermissionCount(PermissionsType permissions_type) const;
143 size_t GetPermissionsDetailsCount(PermissionsType permissions_type) const;
144 base::string16 GetPermission(size_t index,
145 PermissionsType permissions_type) const;
146 base::string16 GetPermissionsDetails(
147 size_t index,
148 PermissionsType permissions_type) const;
149 bool GetIsShowingDetails(DetailsType type, size_t index) const;
150 size_t GetRetainedFileCount() const;
151 base::string16 GetRetainedFile(size_t index) const;
152 size_t GetRetainedDeviceCount() const;
153 base::string16 GetRetainedDeviceMessageString(size_t index) const;
155 // Populated for BUNDLE_INSTALL_PROMPT and
156 // DELEGATED_BUNDLE_PERMISSIONS_PROMPT.
157 const extensions::BundleInstaller* bundle() const { return bundle_; }
158 void set_bundle(const extensions::BundleInstaller* bundle) {
159 bundle_ = bundle;
162 // Populated for all other types.
163 const extensions::Extension* extension() const { return extension_; }
164 void set_extension(const extensions::Extension* extension) {
165 extension_ = extension;
168 // May be populated for POST_INSTALL_PERMISSIONS_PROMPT.
169 void set_retained_files(const std::vector<base::FilePath>& retained_files) {
170 retained_files_ = retained_files;
172 void set_retained_device_messages(
173 const std::vector<base::string16>& retained_device_messages) {
174 retained_device_messages_ = retained_device_messages;
177 const std::string& delegated_username() const {
178 return delegated_username_;
180 void set_delegated_username(const std::string& delegated_username) {
181 delegated_username_ = delegated_username;
184 const gfx::Image& icon() const { return icon_; }
185 void set_icon(const gfx::Image& icon) { icon_ = icon; }
187 bool has_webstore_data() const { return has_webstore_data_; }
189 private:
190 friend class base::RefCountedThreadSafe<Prompt>;
192 struct InstallPromptPermissions {
193 InstallPromptPermissions();
194 ~InstallPromptPermissions();
196 std::vector<base::string16> permissions;
197 std::vector<base::string16> details;
198 std::vector<bool> is_showing_details;
201 virtual ~Prompt();
203 bool ShouldDisplayRevokeButton() const;
205 // Returns the InstallPromptPermissions corresponding to
206 // |permissions_type|.
207 InstallPromptPermissions& GetPermissionsForType(
208 PermissionsType permissions_type);
209 const InstallPromptPermissions& GetPermissionsForType(
210 PermissionsType permissions_type) const;
212 bool ShouldDisplayRevokeFilesButton() const;
214 PromptType type_;
216 // Permissions that are being requested (may not be all of an extension's
217 // permissions if only additional ones are being requested)
218 InstallPromptPermissions prompt_permissions_;
219 // Permissions that will be withheld upon install.
220 InstallPromptPermissions withheld_prompt_permissions_;
222 bool is_showing_details_for_retained_files_;
223 bool is_showing_details_for_retained_devices_;
225 // The extension or bundle being installed.
226 const extensions::Extension* extension_;
227 const extensions::BundleInstaller* bundle_;
229 std::string delegated_username_;
231 // The icon to be displayed.
232 gfx::Image icon_;
234 // These fields are populated only when the prompt type is
235 // INLINE_INSTALL_PROMPT
236 // Already formatted to be locale-specific.
237 std::string localized_user_count_;
238 // Range is kMinExtensionRating to kMaxExtensionRating
239 double average_rating_;
240 int rating_count_;
242 // Whether we should display the user count (we anticipate this will be
243 // false if localized_user_count_ represents the number zero).
244 bool show_user_count_;
246 // Whether or not this prompt has been populated with data from the
247 // webstore.
248 bool has_webstore_data_;
250 std::vector<base::FilePath> retained_files_;
251 std::vector<base::string16> retained_device_messages_;
253 DISALLOW_COPY_AND_ASSIGN(Prompt);
256 static const int kMinExtensionRating = 0;
257 static const int kMaxExtensionRating = 5;
259 class Delegate {
260 public:
261 // We call this method to signal that the installation should continue.
262 virtual void InstallUIProceed() = 0;
264 // We call this method to signal that the installation should stop, with
265 // |user_initiated| true if the installation was stopped by the user.
266 virtual void InstallUIAbort(bool user_initiated) = 0;
268 protected:
269 virtual ~Delegate() {}
272 typedef base::Callback<void(ExtensionInstallPromptShowParams*,
273 ExtensionInstallPrompt::Delegate*,
274 scoped_refptr<ExtensionInstallPrompt::Prompt>)>
275 ShowDialogCallback;
277 // Callback to show the default extension install dialog.
278 // The implementations of this function are platform-specific.
279 static ShowDialogCallback GetDefaultShowDialogCallback();
281 // Creates a dummy extension from the |manifest|, replacing the name and
282 // description with the localizations if provided.
283 static scoped_refptr<extensions::Extension> GetLocalizedExtensionForDisplay(
284 const base::DictionaryValue* manifest,
285 int flags, // Extension::InitFromValueFlags
286 const std::string& id,
287 const std::string& localized_name,
288 const std::string& localized_description,
289 std::string* error);
291 // Creates a prompt with a parent web content.
292 explicit ExtensionInstallPrompt(content::WebContents* contents);
294 // Creates a prompt with a profile and a native window. The most recently
295 // active browser window (or a new browser window if there are no browser
296 // windows) is used if a new tab needs to be opened.
297 ExtensionInstallPrompt(Profile* profile, gfx::NativeWindow native_window);
299 virtual ~ExtensionInstallPrompt();
301 extensions::ExtensionInstallUI* install_ui() const {
302 return install_ui_.get();
305 // This is called by the bundle installer to verify whether the bundle
306 // should be installed.
308 // We *MUST* eventually call either Proceed() or Abort() on |bundle|.
309 virtual void ConfirmBundleInstall(
310 extensions::BundleInstaller* bundle,
311 const SkBitmap* icon,
312 const extensions::PermissionSet* permissions);
314 // This is called by the bundle installer to verify the permissions for a
315 // delegated bundle install.
317 // We *MUST* eventually call either Proceed() or Abort() on |bundle|.
318 virtual void ConfirmPermissionsForDelegatedBundleInstall(
319 extensions::BundleInstaller* bundle,
320 const std::string& delegated_username,
321 const SkBitmap* icon,
322 const extensions::PermissionSet* permissions);
324 // This is called by the standalone installer to verify whether the install
325 // from the webstore should proceed.
327 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
328 virtual void ConfirmStandaloneInstall(Delegate* delegate,
329 const extensions::Extension* extension,
330 SkBitmap* icon,
331 scoped_refptr<Prompt> prompt);
333 // This is called by the installer to verify whether the installation from
334 // the webstore should proceed. |show_dialog_callback| is optional and can be
335 // NULL.
337 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
338 virtual void ConfirmWebstoreInstall(
339 Delegate* delegate,
340 const extensions::Extension* extension,
341 const SkBitmap* icon,
342 const ShowDialogCallback& show_dialog_callback);
344 // This is called by the installer to verify whether the installation should
345 // proceed. This is declared virtual for testing. |show_dialog_callback| is
346 // optional and can be NULL.
348 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
349 virtual void ConfirmInstall(Delegate* delegate,
350 const extensions::Extension* extension,
351 const ShowDialogCallback& show_dialog_callback);
353 // This is called by the webstore API to verify the permissions for a
354 // delegated install.
356 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
357 virtual void ConfirmPermissionsForDelegatedInstall(
358 Delegate* delegate,
359 const extensions::Extension* extension,
360 const std::string& delegated_username,
361 const SkBitmap* icon);
363 // This is called by the app handler launcher to verify whether the app
364 // should be re-enabled. This is declared virtual for testing.
366 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
367 virtual void ConfirmReEnable(Delegate* delegate,
368 const extensions::Extension* extension);
370 // This is called by the external install alert UI to verify whether the
371 // extension should be enabled (external extensions are installed disabled).
373 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
374 virtual void ConfirmExternalInstall(
375 Delegate* delegate,
376 const extensions::Extension* extension,
377 const ShowDialogCallback& show_dialog_callback,
378 scoped_refptr<Prompt> prompt);
380 // This is called by the extension permissions API to verify whether an
381 // extension may be granted additional permissions.
383 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
384 virtual void ConfirmPermissions(Delegate* delegate,
385 const extensions::Extension* extension,
386 const extensions::PermissionSet* permissions);
388 // This is called by the app handler launcher to review what permissions the
389 // extension or app currently has.
391 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
392 virtual void ReviewPermissions(
393 Delegate* delegate,
394 const extensions::Extension* extension,
395 const std::vector<base::FilePath>& retained_file_paths,
396 const std::vector<base::string16>& retained_device_messages);
398 // Installation was successful. This is declared virtual for testing.
399 virtual void OnInstallSuccess(const extensions::Extension* extension,
400 SkBitmap* icon);
402 // Installation failed. This is declared virtual for testing.
403 virtual void OnInstallFailure(const extensions::CrxInstallError& error);
405 void set_callback_for_test(const ShowDialogCallback& show_dialog_callback) {
406 show_dialog_callback_ = show_dialog_callback;
409 protected:
410 friend class extensions::ExtensionWebstorePrivateApiTest;
411 friend class WebstoreStartupInstallUnpackFailureTest;
413 // Whether or not we should record the oauth2 grant upon successful install.
414 bool record_oauth2_grant_;
416 private:
417 friend class GalleryInstallApiTestObserver;
419 // Sets the icon that will be used in any UI. If |icon| is NULL, or contains
420 // an empty bitmap, then a default icon will be used instead.
421 void SetIcon(const SkBitmap* icon);
423 // ImageLoader callback.
424 void OnImageLoaded(const gfx::Image& image);
426 // Starts the process of showing a confirmation UI, which is split into two.
427 // 1) Set off a 'load icon' task.
428 // 2) Handle the load icon response and show the UI (OnImageLoaded).
429 void LoadImageIfNeeded();
431 // Shows the actual UI (the icon should already be loaded).
432 void ShowConfirmation();
434 Profile* profile_;
436 base::MessageLoop* ui_loop_;
438 // The extensions installation icon.
439 SkBitmap icon_;
441 // The extension we are showing the UI for, if type is not
442 // BUNDLE_INSTALL_PROMPT or DELEGATED_BUNDLE_PERMISSIONS_PROMPT.
443 const extensions::Extension* extension_;
445 // The bundle we are showing the UI for, if type BUNDLE_INSTALL_PROMPT or
446 // DELEGATED_BUNDLE_PERMISSIONS_PROMPT.
447 const extensions::BundleInstaller* bundle_;
449 // The name of the user we are asking about, if type
450 // DELEGATED_PERMISSIONS_PROMPT or DELEGATED_BUNDLE_PERMISSIONS_PROMPT.
451 std::string delegated_username_;
453 // A custom set of permissions to show in the install prompt instead of the
454 // extension's active permissions.
455 scoped_refptr<const extensions::PermissionSet> custom_permissions_;
457 // The object responsible for doing the UI specific actions.
458 scoped_ptr<extensions::ExtensionInstallUI> install_ui_;
460 // Parameters to show the confirmation UI.
461 scoped_ptr<ExtensionInstallPromptShowParams> show_params_;
463 // The delegate we will call Proceed/Abort on after confirmation UI.
464 Delegate* delegate_;
466 // A pre-filled prompt.
467 scoped_refptr<Prompt> prompt_;
469 // Used to show the confirm dialog.
470 ShowDialogCallback show_dialog_callback_;
473 #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_PROMPT_H_