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/scoped_ptr.h"
15 #include "base/strings/string16.h"
16 #include "chrome/browser/extensions/crx_installer_error.h"
17 #include "chrome/browser/extensions/extension_install_prompt_experiment.h"
18 #include "extensions/common/url_pattern.h"
19 #include "google_apis/gaia/oauth2_mint_token_flow.h"
20 #include "google_apis/gaia/oauth2_token_service.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"
27 class ExtensionInstallUI
;
31 class DictionaryValue
;
40 namespace extensions
{
41 class BundleInstaller
;
43 class ExtensionWebstorePrivateApiTest
;
44 class MockGetAuthTokenFunction
;
46 } // namespace extensions
49 class InfoBarDelegate
;
52 // Displays all the UI around extension installation.
53 class ExtensionInstallPrompt
54 : public OAuth2MintTokenFlow::Delegate
,
55 public OAuth2TokenService::Consumer
,
56 public base::SupportsWeakPtr
<ExtensionInstallPrompt
> {
58 // This enum is associated with Extensions.InstallPrompt_Type UMA histogram.
59 // Do not modify existing values and add new values only to the end.
61 UNSET_PROMPT_TYPE
= -1,
63 INLINE_INSTALL_PROMPT
,
64 BUNDLE_INSTALL_PROMPT
,
67 EXTERNAL_INSTALL_PROMPT
,
68 POST_INSTALL_PERMISSIONS_PROMPT
,
74 PERMISSIONS_DETAILS
= 0,
76 RETAINED_FILES_DETAILS
,
79 // Extra information needed to display an installation or uninstallation
80 // prompt. Gets populated with raw data and exposes getters for formatted
81 // strings so that the GTK/views/Cocoa install dialogs don't have to repeat
85 explicit Prompt(PromptType type
);
88 // Sets the permission list for this prompt.
89 void SetPermissions(const std::vector
<base::string16
>& permissions
);
90 // Sets the permission list details for this prompt.
91 void SetPermissionsDetails(const std::vector
<base::string16
>& details
);
92 void SetIsShowingDetails(DetailsType type
,
94 bool is_showing_details
);
95 void SetWebstoreData(const std::string
& localized_user_count
,
97 double average_rating
,
99 void SetOAuthIssueAdvice(const IssueAdviceInfo
& issue_advice
);
100 void SetUserNameFromProfile(Profile
* profile
);
102 PromptType
type() const { return type_
; }
103 void set_type(PromptType type
) { type_
= type
; }
105 // Getters for UI element labels.
106 base::string16
GetDialogTitle() const;
107 base::string16
GetHeading() const;
108 int GetDialogButtons() const;
109 bool HasAcceptButtonLabel() const;
110 base::string16
GetAcceptButtonLabel() const;
111 bool HasAbortButtonLabel() const;
112 base::string16
GetAbortButtonLabel() const;
113 base::string16
GetPermissionsHeading() const;
114 base::string16
GetOAuthHeading() const;
115 base::string16
GetRetainedFilesHeading() const;
117 bool ShouldShowPermissions() const;
118 bool ShouldShowExplanationText() const;
120 // Getters for webstore metadata. Only populated when the type is
121 // INLINE_INSTALL_PROMPT.
123 // The star display logic replicates the one used by the webstore (from
124 // components.ratingutils.setFractionalYellowStars). Callers pass in an
125 // "appender", which will be repeatedly called back with the star images
126 // that they append to the star display area.
127 typedef void(*StarAppender
)(const gfx::ImageSkia
*, void*);
128 void AppendRatingStars(StarAppender appender
, void* data
) const;
129 base::string16
GetRatingCount() const;
130 base::string16
GetUserCount() const;
131 size_t GetPermissionCount() const;
132 size_t GetPermissionsDetailsCount() const;
133 base::string16
GetPermission(size_t index
) const;
134 base::string16
GetPermissionsDetails(size_t index
) const;
135 bool GetIsShowingDetails(DetailsType type
, size_t index
) const;
136 size_t GetOAuthIssueCount() const;
137 const IssueAdviceInfoEntry
& GetOAuthIssue(size_t index
) const;
138 size_t GetRetainedFileCount() const;
139 base::string16
GetRetainedFile(size_t index
) const;
141 // Populated for BUNDLE_INSTALL_PROMPT.
142 const extensions::BundleInstaller
* bundle() const { return bundle_
; }
143 void set_bundle(const extensions::BundleInstaller
* bundle
) {
147 // Populated for all other types.
148 const extensions::Extension
* extension() const { return extension_
; }
149 void set_extension(const extensions::Extension
* extension
) {
150 extension_
= extension
;
153 // May be populated for POST_INSTALL_PERMISSIONS_PROMPT.
154 void set_retained_files(const std::vector
<base::FilePath
>& retained_files
) {
155 retained_files_
= retained_files
;
158 const gfx::Image
& icon() const { return icon_
; }
159 void set_icon(const gfx::Image
& icon
) { icon_
= icon
; }
161 bool has_webstore_data() const { return has_webstore_data_
; }
163 const ExtensionInstallPromptExperiment
* experiment() const {
166 void set_experiment(ExtensionInstallPromptExperiment
* experiment
) {
167 experiment_
= experiment
;
171 bool ShouldDisplayRevokeFilesButton() const;
175 // Permissions that are being requested (may not be all of an extension's
176 // permissions if only additional ones are being requested)
177 std::vector
<base::string16
> permissions_
;
178 std::vector
<base::string16
> details_
;
179 std::vector
<bool> is_showing_details_for_permissions_
;
180 std::vector
<bool> is_showing_details_for_oauth_
;
181 bool is_showing_details_for_retained_files_
;
183 // Descriptions and details for OAuth2 permissions to display to the user.
184 // These correspond to permission scopes.
185 IssueAdviceInfo oauth_issue_advice_
;
187 // User name to be used in Oauth heading label.
188 base::string16 oauth_user_name_
;
190 // The extension or bundle being installed.
191 const extensions::Extension
* extension_
;
192 const extensions::BundleInstaller
* bundle_
;
194 // The icon to be displayed.
197 // These fields are populated only when the prompt type is
198 // INLINE_INSTALL_PROMPT
199 // Already formatted to be locale-specific.
200 std::string localized_user_count_
;
201 // Range is kMinExtensionRating to kMaxExtensionRating
202 double average_rating_
;
205 // Whether we should display the user count (we anticipate this will be
206 // false if localized_user_count_ represents the number zero).
207 bool show_user_count_
;
209 // Whether or not this prompt has been populated with data from the
211 bool has_webstore_data_
;
213 std::vector
<base::FilePath
> retained_files_
;
215 scoped_refptr
<ExtensionInstallPromptExperiment
> experiment_
;
218 static const int kMinExtensionRating
= 0;
219 static const int kMaxExtensionRating
= 5;
223 // We call this method to signal that the installation should continue.
224 virtual void InstallUIProceed() = 0;
226 // We call this method to signal that the installation should stop, with
227 // |user_initiated| true if the installation was stopped by the user.
228 virtual void InstallUIAbort(bool user_initiated
) = 0;
231 virtual ~Delegate() {}
234 // Parameters to show a prompt dialog. Two sets of the
235 // parameters are supported: either use a parent WebContents or use a
236 // parent NativeWindow + a PageNavigator.
238 explicit ShowParams(content::WebContents
* contents
);
239 ShowParams(gfx::NativeWindow window
, content::PageNavigator
* navigator
);
241 // Parent web contents of the install UI dialog. This can be NULL.
242 content::WebContents
* parent_web_contents
;
244 // NativeWindow parent and navigator. If initialized using a parent web
245 // contents, these are derived from it.
246 gfx::NativeWindow parent_window
;
247 content::PageNavigator
* navigator
;
250 typedef base::Callback
<void(const ExtensionInstallPrompt::ShowParams
&,
251 ExtensionInstallPrompt::Delegate
*,
252 const ExtensionInstallPrompt::Prompt
&)>
255 // Callback to show the default extension install dialog.
256 // The implementations of this function are platform-specific.
257 static ShowDialogCallback
GetDefaultShowDialogCallback();
259 // Creates a dummy extension from the |manifest|, replacing the name and
260 // description with the localizations if provided.
261 static scoped_refptr
<extensions::Extension
> GetLocalizedExtensionForDisplay(
262 const base::DictionaryValue
* manifest
,
263 int flags
, // Extension::InitFromValueFlags
264 const std::string
& id
,
265 const std::string
& localized_name
,
266 const std::string
& localized_description
,
269 // Creates a prompt with a parent web content.
270 explicit ExtensionInstallPrompt(content::WebContents
* contents
);
272 // Creates a prompt with a profile, a native window and a page navigator.
273 ExtensionInstallPrompt(Profile
* profile
,
274 gfx::NativeWindow native_window
,
275 content::PageNavigator
* navigator
);
277 virtual ~ExtensionInstallPrompt();
279 ExtensionInstallUI
* install_ui() const { return install_ui_
.get(); }
281 bool record_oauth2_grant() const { return record_oauth2_grant_
; }
283 content::WebContents
* parent_web_contents() const {
284 return show_params_
.parent_web_contents
;
287 // This is called by the bundle installer to verify whether the bundle
288 // should be installed.
290 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
291 virtual void ConfirmBundleInstall(
292 extensions::BundleInstaller
* bundle
,
293 const extensions::PermissionSet
* permissions
);
295 // This is called by the standalone installer to verify whether the install
296 // from the webstore should proceed.
298 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
299 virtual void ConfirmStandaloneInstall(Delegate
* delegate
,
300 const extensions::Extension
* extension
,
302 const Prompt
& prompt
);
304 // This is called by the installer to verify whether the installation from
305 // the webstore should proceed. |show_dialog_callback| is optional and can be
308 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
309 virtual void ConfirmWebstoreInstall(
311 const extensions::Extension
* extension
,
312 const SkBitmap
* icon
,
313 const ShowDialogCallback
& show_dialog_callback
);
315 // This is called by the installer to verify whether the installation should
316 // proceed. This is declared virtual for testing. |show_dialog_callback| is
317 // optional and can be NULL.
319 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
320 virtual void ConfirmInstall(Delegate
* delegate
,
321 const extensions::Extension
* extension
,
322 const ShowDialogCallback
& show_dialog_callback
);
324 // This is called by the app handler launcher to verify whether the app
325 // should be re-enabled. This is declared virtual for testing.
327 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
328 virtual void ConfirmReEnable(Delegate
* delegate
,
329 const extensions::Extension
* extension
);
331 // This is called by the external install alert UI to verify whether the
332 // extension should be enabled (external extensions are installed disabled).
334 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
335 virtual void ConfirmExternalInstall(
337 const extensions::Extension
* extension
,
338 const ShowDialogCallback
& show_dialog_callback
,
339 const Prompt
& prompt
);
341 // This is called by the extension permissions API to verify whether an
342 // extension may be granted additional permissions.
344 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
345 virtual void ConfirmPermissions(Delegate
* delegate
,
346 const extensions::Extension
* extension
,
347 const extensions::PermissionSet
* permissions
);
349 // This is called by the extension identity API to verify whether an
350 // extension can be granted an OAuth2 token.
352 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
353 virtual void ConfirmIssueAdvice(Delegate
* delegate
,
354 const extensions::Extension
* extension
,
355 const IssueAdviceInfo
& issue_advice
);
357 // This is called by the app handler launcher to review what permissions the
358 // extension or app currently has.
360 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
361 virtual void ReviewPermissions(
363 const extensions::Extension
* extension
,
364 const std::vector
<base::FilePath
>& retained_file_paths
);
366 // Installation was successful. This is declared virtual for testing.
367 virtual void OnInstallSuccess(const extensions::Extension
* extension
,
370 // Installation failed. This is declared virtual for testing.
371 virtual void OnInstallFailure(const extensions::CrxInstallerError
& error
);
374 friend class extensions::ExtensionWebstorePrivateApiTest
;
375 friend class extensions::MockGetAuthTokenFunction
;
376 friend class WebstoreStartupInstallUnpackFailureTest
;
378 // Whether or not we should record the oauth2 grant upon successful install.
379 bool record_oauth2_grant_
;
382 friend class GalleryInstallApiTestObserver
;
384 // Sets the icon that will be used in any UI. If |icon| is NULL, or contains
385 // an empty bitmap, then a default icon will be used instead.
386 void SetIcon(const SkBitmap
* icon
);
388 // ImageLoader callback.
389 void OnImageLoaded(const gfx::Image
& image
);
391 // Starts the process of showing a confirmation UI, which is split into two.
392 // 1) Set off a 'load icon' task.
393 // 2) Handle the load icon response and show the UI (OnImageLoaded).
394 void LoadImageIfNeeded();
396 // OAuth2TokenService::Consumer implementation:
397 virtual void OnGetTokenSuccess(const OAuth2TokenService::Request
* request
,
398 const std::string
& access_token
,
399 const base::Time
& expiration_time
) OVERRIDE
;
400 virtual void OnGetTokenFailure(const OAuth2TokenService::Request
* request
,
401 const GoogleServiceAuthError
& error
) OVERRIDE
;
403 // OAuth2MintTokenFlow::Delegate implementation:
404 virtual void OnIssueAdviceSuccess(
405 const IssueAdviceInfo
& issue_advice
) OVERRIDE
;
406 virtual void OnMintTokenFailure(
407 const GoogleServiceAuthError
& error
) OVERRIDE
;
409 // Shows the actual UI (the icon should already be loaded).
410 void ShowConfirmation();
412 base::MessageLoop
* ui_loop_
;
414 // The extensions installation icon.
417 // The extension we are showing the UI for, if type is not
418 // BUNDLE_INSTALL_PROMPT.
419 const extensions::Extension
* extension_
;
421 // The bundle we are showing the UI for, if type BUNDLE_INSTALL_PROMPT.
422 const extensions::BundleInstaller
* bundle_
;
424 // The permissions being prompted for.
425 scoped_refptr
<const extensions::PermissionSet
> permissions_
;
427 // The object responsible for doing the UI specific actions.
428 scoped_ptr
<ExtensionInstallUI
> install_ui_
;
430 // Parameters to show the confirmation UI.
431 ShowParams show_params_
;
433 // The delegate we will call Proceed/Abort on after confirmation UI.
436 // A pre-filled prompt.
439 scoped_ptr
<OAuth2TokenService::Request
> login_token_request_
;
440 scoped_ptr
<OAuth2MintTokenFlow
> token_flow_
;
442 // Used to show the confirm dialog.
443 ShowDialogCallback show_dialog_callback_
;
446 #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_PROMPT_H_