Clean up extension confirmation prompts and make them consistent between Views and...
[chromium-blink-merge.git] / chrome / browser / extensions / extension_install_prompt.h
blob32243c5aba082a0af8cbd6724bf7c3edc59e5123
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 NUM_PROMPT_TYPES
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.
77 enum DetailsType {
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,
88 WITHHELD_PERMISSIONS,
89 ALL_PERMISSIONS,
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
97 // that logic.
98 // Ref-counted because we pass around the prompt independent of the full
99 // ExtensionInstallPrompt.
100 class Prompt : public base::RefCountedThreadSafe<Prompt> {
101 public:
102 explicit Prompt(PromptType type);
104 void SetPermissions(const extensions::PermissionMessageStrings& permissions,
105 PermissionsType permissions_type);
106 void SetIsShowingDetails(DetailsType type,
107 size_t index,
108 bool is_showing_details);
109 void SetWebstoreData(const std::string& localized_user_count,
110 bool show_user_count,
111 double average_rating,
112 int rating_count);
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(
146 size_t index,
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) {
157 bundle_ = 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_; }
187 private:
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;
199 virtual ~Prompt();
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;
212 PromptType type_;
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.
230 gfx::Image icon_;
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_;
238 int rating_count_;
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
245 // webstore.
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;
257 class Delegate {
258 public:
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;
266 protected:
267 virtual ~Delegate() {}
270 typedef base::Callback<void(ExtensionInstallPromptShowParams*,
271 ExtensionInstallPrompt::Delegate*,
272 scoped_refptr<ExtensionInstallPrompt::Prompt>)>
273 ShowDialogCallback;
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,
287 std::string* error);
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,
318 SkBitmap* icon,
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
323 // NULL.
325 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
326 virtual void ConfirmWebstoreInstall(
327 Delegate* delegate,
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(
346 Delegate* delegate,
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(
363 Delegate* delegate,
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(
381 Delegate* delegate,
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,
388 SkBitmap* icon);
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;
397 protected:
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_;
404 private:
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();
422 Profile* profile_;
424 base::MessageLoop* ui_loop_;
426 // The extensions installation icon.
427 SkBitmap 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.
451 Delegate* delegate_;
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_