Adding instrumentation to locate the source of jankiness
[chromium-blink-merge.git] / chrome / browser / extensions / extension_install_prompt.h
blob57f00cb64676e2439d24e43de257f57c29e221e6
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 "chrome/browser/extensions/crx_installer_error.h"
19 #include "chrome/browser/extensions/extension_install_prompt_experiment.h"
20 #include "extensions/common/url_pattern.h"
21 #include "third_party/skia/include/core/SkBitmap.h"
22 #include "ui/gfx/image/image.h"
23 #include "ui/gfx/image/image_skia.h"
24 #include "ui/gfx/native_widget_types.h"
26 class ExtensionInstallUI;
27 class Profile;
29 namespace base {
30 class DictionaryValue;
31 class MessageLoop;
32 } // namespace base
34 namespace content {
35 class PageNavigator;
36 class WebContents;
39 namespace extensions {
40 class BundleInstaller;
41 class Extension;
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 // A setting to cause extension/app installs from the webstore skip the normal
56 // confirmation dialog. This should only be used in tests.
57 enum AutoConfirmForTests {
58 NONE, // The prompt will show normally.
59 ACCEPT, // The prompt will always accept.
60 CANCEL, // The prompt will always cancel.
62 static AutoConfirmForTests g_auto_confirm_for_tests;
64 // This enum is associated with Extensions.InstallPrompt_Type UMA histogram.
65 // Do not modify existing values and add new values only to the end.
66 enum PromptType {
67 UNSET_PROMPT_TYPE = -1,
68 INSTALL_PROMPT = 0,
69 INLINE_INSTALL_PROMPT,
70 BUNDLE_INSTALL_PROMPT,
71 RE_ENABLE_PROMPT,
72 PERMISSIONS_PROMPT,
73 EXTERNAL_INSTALL_PROMPT,
74 POST_INSTALL_PERMISSIONS_PROMPT,
75 LAUNCH_PROMPT,
76 REMOTE_INSTALL_PROMPT,
77 REPAIR_PROMPT,
78 NUM_PROMPT_TYPES
81 // Enumeration for permissions and retained files details.
82 enum DetailsType {
83 PERMISSIONS_DETAILS = 0,
84 WITHHELD_PERMISSIONS_DETAILS,
85 RETAINED_FILES_DETAILS,
86 RETAINED_DEVICES_DETAILS,
89 // This enum is used to differentiate regular and withheld permissions for
90 // segregation in the install prompt.
91 enum PermissionsType {
92 REGULAR_PERMISSIONS = 0,
93 WITHHELD_PERMISSIONS,
94 ALL_PERMISSIONS,
97 static std::string PromptTypeToString(PromptType type);
99 // Extra information needed to display an installation or uninstallation
100 // prompt. Gets populated with raw data and exposes getters for formatted
101 // strings so that the GTK/views/Cocoa install dialogs don't have to repeat
102 // that logic.
103 // Ref-counted because we pass around the prompt independent of the full
104 // ExtensionInstallPrompt.
105 class Prompt : public base::RefCountedThreadSafe<Prompt> {
106 public:
107 explicit Prompt(PromptType type);
109 // Sets the permission list for this prompt.
110 void SetPermissions(const std::vector<base::string16>& permissions,
111 PermissionsType permissions_type);
112 // Sets the permission list details for this prompt.
113 void SetPermissionsDetails(const std::vector<base::string16>& details,
114 PermissionsType permissions_type);
115 void SetIsShowingDetails(DetailsType type,
116 size_t index,
117 bool is_showing_details);
118 void SetWebstoreData(const std::string& localized_user_count,
119 bool show_user_count,
120 double average_rating,
121 int rating_count);
122 void SetUserNameFromProfile(Profile* profile);
124 PromptType type() const { return type_; }
125 void set_type(PromptType type) { type_ = type; }
127 // Getters for UI element labels.
128 base::string16 GetDialogTitle() const;
129 base::string16 GetHeading() const;
130 int GetDialogButtons() const;
131 bool HasAcceptButtonLabel() const;
132 base::string16 GetAcceptButtonLabel() const;
133 bool HasAbortButtonLabel() const;
134 base::string16 GetAbortButtonLabel() const;
135 base::string16 GetPermissionsHeading(
136 PermissionsType permissions_type) const;
137 base::string16 GetRetainedFilesHeading() const;
138 base::string16 GetRetainedDevicesHeading() const;
140 bool ShouldShowPermissions() const;
141 bool ShouldShowExplanationText() const;
143 // Getters for webstore metadata. Only populated when the type is
144 // INLINE_INSTALL_PROMPT.
146 // The star display logic replicates the one used by the webstore (from
147 // components.ratingutils.setFractionalYellowStars). Callers pass in an
148 // "appender", which will be repeatedly called back with the star images
149 // that they append to the star display area.
150 typedef void(*StarAppender)(const gfx::ImageSkia*, void*);
151 void AppendRatingStars(StarAppender appender, void* data) const;
152 base::string16 GetRatingCount() const;
153 base::string16 GetUserCount() const;
154 size_t GetPermissionCount(PermissionsType permissions_type) const;
155 size_t GetPermissionsDetailsCount(PermissionsType permissions_type) const;
156 base::string16 GetPermission(size_t index,
157 PermissionsType permissions_type) const;
158 base::string16 GetPermissionsDetails(
159 size_t index,
160 PermissionsType permissions_type) const;
161 bool GetIsShowingDetails(DetailsType type, size_t index) const;
162 size_t GetRetainedFileCount() const;
163 base::string16 GetRetainedFile(size_t index) const;
164 size_t GetRetainedDeviceCount() const;
165 base::string16 GetRetainedDeviceMessageString(size_t index) const;
167 // Populated for BUNDLE_INSTALL_PROMPT.
168 const extensions::BundleInstaller* bundle() const { return bundle_; }
169 void set_bundle(const extensions::BundleInstaller* bundle) {
170 bundle_ = bundle;
173 // Populated for all other types.
174 const extensions::Extension* extension() const { return extension_; }
175 void set_extension(const extensions::Extension* extension) {
176 extension_ = extension;
179 // May be populated for POST_INSTALL_PERMISSIONS_PROMPT.
180 void set_retained_files(const std::vector<base::FilePath>& retained_files) {
181 retained_files_ = retained_files;
183 void set_retained_device_messages(
184 const std::vector<base::string16>& retained_device_messages) {
185 retained_device_messages_ = retained_device_messages;
188 const gfx::Image& icon() const { return icon_; }
189 void set_icon(const gfx::Image& icon) { icon_ = icon; }
191 bool has_webstore_data() const { return has_webstore_data_; }
193 const ExtensionInstallPromptExperiment* experiment() const {
194 return experiment_.get();
196 void set_experiment(ExtensionInstallPromptExperiment* experiment) {
197 experiment_ = experiment;
200 private:
201 friend class base::RefCountedThreadSafe<Prompt>;
203 struct InstallPromptPermissions {
204 InstallPromptPermissions();
205 ~InstallPromptPermissions();
207 std::vector<base::string16> permissions;
208 std::vector<base::string16> details;
209 std::vector<bool> is_showing_details;
212 virtual ~Prompt();
214 bool ShouldDisplayRevokeButton() const;
216 // Returns the InstallPromptPermissions corresponding to
217 // |permissions_type|.
218 InstallPromptPermissions& GetPermissionsForType(
219 PermissionsType permissions_type);
220 const InstallPromptPermissions& GetPermissionsForType(
221 PermissionsType permissions_type) const;
223 bool ShouldDisplayRevokeFilesButton() const;
225 PromptType type_;
227 // Permissions that are being requested (may not be all of an extension's
228 // permissions if only additional ones are being requested)
229 InstallPromptPermissions prompt_permissions_;
230 // Permissions that will be withheld upon install.
231 InstallPromptPermissions withheld_prompt_permissions_;
233 bool is_showing_details_for_retained_files_;
234 bool is_showing_details_for_retained_devices_;
236 // The extension or bundle being installed.
237 const extensions::Extension* extension_;
238 const extensions::BundleInstaller* bundle_;
240 // The icon to be displayed.
241 gfx::Image icon_;
243 // These fields are populated only when the prompt type is
244 // INLINE_INSTALL_PROMPT
245 // Already formatted to be locale-specific.
246 std::string localized_user_count_;
247 // Range is kMinExtensionRating to kMaxExtensionRating
248 double average_rating_;
249 int rating_count_;
251 // Whether we should display the user count (we anticipate this will be
252 // false if localized_user_count_ represents the number zero).
253 bool show_user_count_;
255 // Whether or not this prompt has been populated with data from the
256 // webstore.
257 bool has_webstore_data_;
259 std::vector<base::FilePath> retained_files_;
260 std::vector<base::string16> retained_device_messages_;
262 scoped_refptr<ExtensionInstallPromptExperiment> experiment_;
264 DISALLOW_COPY_AND_ASSIGN(Prompt);
267 static const int kMinExtensionRating = 0;
268 static const int kMaxExtensionRating = 5;
270 class Delegate {
271 public:
272 // We call this method to signal that the installation should continue.
273 virtual void InstallUIProceed() = 0;
275 // We call this method to signal that the installation should stop, with
276 // |user_initiated| true if the installation was stopped by the user.
277 virtual void InstallUIAbort(bool user_initiated) = 0;
279 protected:
280 virtual ~Delegate() {}
283 // Parameters to show a prompt dialog. Two sets of the
284 // parameters are supported: either use a parent WebContents or use a
285 // parent NativeWindow + a PageNavigator.
286 struct ShowParams {
287 explicit ShowParams(content::WebContents* contents);
288 ShowParams(gfx::NativeWindow window, content::PageNavigator* navigator);
290 // Parent web contents of the install UI dialog. This can be NULL.
291 content::WebContents* parent_web_contents;
293 // NativeWindow parent and navigator. If initialized using a parent web
294 // contents, these are derived from it.
295 gfx::NativeWindow parent_window;
296 content::PageNavigator* navigator;
299 typedef base::Callback<void(const ExtensionInstallPrompt::ShowParams&,
300 ExtensionInstallPrompt::Delegate*,
301 scoped_refptr<ExtensionInstallPrompt::Prompt>)>
302 ShowDialogCallback;
304 // Callback to show the default extension install dialog.
305 // The implementations of this function are platform-specific.
306 static ShowDialogCallback GetDefaultShowDialogCallback();
308 // Creates a dummy extension from the |manifest|, replacing the name and
309 // description with the localizations if provided.
310 static scoped_refptr<extensions::Extension> GetLocalizedExtensionForDisplay(
311 const base::DictionaryValue* manifest,
312 int flags, // Extension::InitFromValueFlags
313 const std::string& id,
314 const std::string& localized_name,
315 const std::string& localized_description,
316 std::string* error);
318 // Creates a prompt with a parent web content.
319 explicit ExtensionInstallPrompt(content::WebContents* contents);
321 // Creates a prompt with a profile, a native window and a page navigator.
322 ExtensionInstallPrompt(Profile* profile,
323 gfx::NativeWindow native_window,
324 content::PageNavigator* navigator);
326 virtual ~ExtensionInstallPrompt();
328 ExtensionInstallUI* install_ui() const { return install_ui_.get(); }
330 content::WebContents* parent_web_contents() const {
331 return show_params_.parent_web_contents;
334 // This is called by the bundle installer to verify whether the bundle
335 // should be installed.
337 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
338 virtual void ConfirmBundleInstall(
339 extensions::BundleInstaller* bundle,
340 const extensions::PermissionSet* permissions);
342 // This is called by the standalone installer to verify whether the install
343 // from the webstore should proceed.
345 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
346 virtual void ConfirmStandaloneInstall(Delegate* delegate,
347 const extensions::Extension* extension,
348 SkBitmap* icon,
349 scoped_refptr<Prompt> prompt);
351 // This is called by the installer to verify whether the installation from
352 // the webstore should proceed. |show_dialog_callback| is optional and can be
353 // NULL.
355 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
356 virtual void ConfirmWebstoreInstall(
357 Delegate* delegate,
358 const extensions::Extension* extension,
359 const SkBitmap* icon,
360 const ShowDialogCallback& show_dialog_callback);
362 // This is called by the installer to verify whether the installation should
363 // proceed. This is declared virtual for testing. |show_dialog_callback| is
364 // optional and can be NULL.
366 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
367 virtual void ConfirmInstall(Delegate* delegate,
368 const extensions::Extension* extension,
369 const ShowDialogCallback& show_dialog_callback);
371 // This is called by the app handler launcher to verify whether the app
372 // should be re-enabled. This is declared virtual for testing.
374 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
375 virtual void ConfirmReEnable(Delegate* delegate,
376 const extensions::Extension* extension);
378 // This is called by the external install alert UI to verify whether the
379 // extension should be enabled (external extensions are installed disabled).
381 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
382 virtual void ConfirmExternalInstall(
383 Delegate* delegate,
384 const extensions::Extension* extension,
385 const ShowDialogCallback& show_dialog_callback,
386 scoped_refptr<Prompt> prompt);
388 // This is called by the extension permissions API to verify whether an
389 // extension may be granted additional permissions.
391 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
392 virtual void ConfirmPermissions(Delegate* delegate,
393 const extensions::Extension* extension,
394 const extensions::PermissionSet* permissions);
396 // This is called by the app handler launcher to review what permissions the
397 // extension or app currently has.
399 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
400 virtual void ReviewPermissions(
401 Delegate* delegate,
402 const extensions::Extension* extension,
403 const std::vector<base::FilePath>& retained_file_paths,
404 const std::vector<base::string16>& retained_device_messages);
406 // Installation was successful. This is declared virtual for testing.
407 virtual void OnInstallSuccess(const extensions::Extension* extension,
408 SkBitmap* icon);
410 // Installation failed. This is declared virtual for testing.
411 virtual void OnInstallFailure(const extensions::CrxInstallerError& error);
413 void set_callback_for_test(const ShowDialogCallback& show_dialog_callback) {
414 show_dialog_callback_ = show_dialog_callback;
417 protected:
418 friend class extensions::ExtensionWebstorePrivateApiTest;
419 friend class WebstoreStartupInstallUnpackFailureTest;
421 // Whether or not we should record the oauth2 grant upon successful install.
422 bool record_oauth2_grant_;
424 private:
425 friend class GalleryInstallApiTestObserver;
427 // Sets the icon that will be used in any UI. If |icon| is NULL, or contains
428 // an empty bitmap, then a default icon will be used instead.
429 void SetIcon(const SkBitmap* icon);
431 // ImageLoader callback.
432 void OnImageLoaded(const gfx::Image& image);
434 // Starts the process of showing a confirmation UI, which is split into two.
435 // 1) Set off a 'load icon' task.
436 // 2) Handle the load icon response and show the UI (OnImageLoaded).
437 void LoadImageIfNeeded();
439 // Shows the actual UI (the icon should already be loaded).
440 void ShowConfirmation();
442 base::MessageLoop* ui_loop_;
444 // The extensions installation icon.
445 SkBitmap icon_;
447 // The extension we are showing the UI for, if type is not
448 // BUNDLE_INSTALL_PROMPT.
449 const extensions::Extension* extension_;
451 // The bundle we are showing the UI for, if type BUNDLE_INSTALL_PROMPT.
452 const extensions::BundleInstaller* bundle_;
454 // A custom set of permissions to show in the install prompt instead of the
455 // extension's active permissions.
456 scoped_refptr<const extensions::PermissionSet> custom_permissions_;
458 // The object responsible for doing the UI specific actions.
459 scoped_ptr<ExtensionInstallUI> install_ui_;
461 // Parameters to show the confirmation UI.
462 ShowParams show_params_;
464 // The delegate we will call Proceed/Abort on after confirmation UI.
465 Delegate* delegate_;
467 // A pre-filled prompt.
468 scoped_refptr<Prompt> prompt_;
470 // Used to show the confirm dialog.
471 ShowDialogCallback show_dialog_callback_;
474 #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_PROMPT_H_