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 "extensions/common/url_pattern.h"
18 #include "google_apis/gaia/oauth2_mint_token_flow.h"
19 #include "google_apis/gaia/oauth2_token_service.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"
26 class ExtensionInstallUI;
27 class InfoBarDelegate;
31 class DictionaryValue;
40 namespace extensions {
41 class BundleInstaller;
43 class ExtensionWebstorePrivateApiTest;
44 class MockGetAuthTokenFunction;
46 } // namespace extensions
48 // Displays all the UI around extension installation.
49 class ExtensionInstallPrompt
50 : public OAuth2MintTokenFlow::Delegate,
51 public OAuth2TokenService::Consumer,
52 public base::SupportsWeakPtr<ExtensionInstallPrompt> {
55 UNSET_PROMPT_TYPE = -1,
57 INLINE_INSTALL_PROMPT,
58 BUNDLE_INSTALL_PROMPT,
61 EXTERNAL_INSTALL_PROMPT,
62 POST_INSTALL_PERMISSIONS_PROMPT,
68 PERMISSIONS_DETAILS = 0,
70 RETAINED_FILES_DETAILS,
73 // Extra information needed to display an installation or uninstallation
74 // prompt. Gets populated with raw data and exposes getters for formatted
75 // strings so that the GTK/views/Cocoa install dialogs don't have to repeat
79 explicit Prompt(PromptType type);
82 // Sets the permission list for this prompt.
83 void SetPermissions(const std::vector<string16>& permissions);
84 // Sets the permission list details for this prompt.
85 void SetPermissionsDetails(const std::vector<string16>& details);
86 void SetIsShowingDetails(DetailsType type,
88 bool is_showing_details);
89 void SetInlineInstallWebstoreData(const std::string& localized_user_count,
91 double average_rating,
93 void SetOAuthIssueAdvice(const IssueAdviceInfo& issue_advice);
94 void SetUserNameFromProfile(Profile* profile);
96 PromptType type() const { return type_; }
97 void set_type(PromptType type) { type_ = type; }
99 // Getters for UI element labels.
100 string16 GetDialogTitle() const;
101 string16 GetHeading() const;
102 int GetDialogButtons() const;
103 bool HasAcceptButtonLabel() const;
104 string16 GetAcceptButtonLabel() const;
105 bool HasAbortButtonLabel() const;
106 string16 GetAbortButtonLabel() const;
107 string16 GetPermissionsHeading() const;
108 string16 GetOAuthHeading() const;
109 string16 GetRetainedFilesHeading() const;
111 bool ShouldShowPermissions() const;
113 // Getters for webstore metadata. Only populated when the type is
114 // INLINE_INSTALL_PROMPT.
116 // The star display logic replicates the one used by the webstore (from
117 // components.ratingutils.setFractionalYellowStars). Callers pass in an
118 // "appender", which will be repeatedly called back with the star images
119 // that they append to the star display area.
120 typedef void(*StarAppender)(const gfx::ImageSkia*, void*);
121 void AppendRatingStars(StarAppender appender, void* data) const;
122 string16 GetRatingCount() const;
123 string16 GetUserCount() const;
124 size_t GetPermissionCount() const;
125 size_t GetPermissionsDetailsCount() const;
126 string16 GetPermission(size_t index) const;
127 string16 GetPermissionsDetails(size_t index) const;
128 bool GetIsShowingDetails(DetailsType type, size_t index) const;
129 size_t GetOAuthIssueCount() const;
130 const IssueAdviceInfoEntry& GetOAuthIssue(size_t index) const;
131 size_t GetRetainedFileCount() const;
132 string16 GetRetainedFile(size_t index) const;
134 // Populated for BUNDLE_INSTALL_PROMPT.
135 const extensions::BundleInstaller* bundle() const { return bundle_; }
136 void set_bundle(const extensions::BundleInstaller* bundle) {
140 // Populated for all other types.
141 const extensions::Extension* extension() const { return extension_; }
142 void set_extension(const extensions::Extension* extension) {
143 extension_ = extension;
146 // May be populated for POST_INSTALL_PERMISSIONS_PROMPT.
147 void set_retained_files(const std::vector<base::FilePath>& retained_files) {
148 retained_files_ = retained_files;
151 const gfx::Image& icon() const { return icon_; }
152 void set_icon(const gfx::Image& icon) { icon_ = icon; }
155 bool ShouldDisplayRevokeFilesButton() const;
159 // Permissions that are being requested (may not be all of an extension's
160 // permissions if only additional ones are being requested)
161 std::vector<string16> permissions_;
162 std::vector<string16> details_;
163 std::vector<bool> is_showing_details_for_permissions_;
164 std::vector<bool> is_showing_details_for_oauth_;
165 bool is_showing_details_for_retained_files_;
167 // Descriptions and details for OAuth2 permissions to display to the user.
168 // These correspond to permission scopes.
169 IssueAdviceInfo oauth_issue_advice_;
171 // User name to be used in Oauth heading label.
172 string16 oauth_user_name_;
174 // The extension or bundle being installed.
175 const extensions::Extension* extension_;
176 const extensions::BundleInstaller* bundle_;
178 // The icon to be displayed.
181 // These fields are populated only when the prompt type is
182 // INLINE_INSTALL_PROMPT
183 // Already formatted to be locale-specific.
184 std::string localized_user_count_;
185 // Range is kMinExtensionRating to kMaxExtensionRating
186 double average_rating_;
189 // Whether we should display the user count (we anticipate this will be
190 // false if localized_user_count_ represents the number zero).
191 bool show_user_count_;
193 std::vector<base::FilePath> retained_files_;
196 static const int kMinExtensionRating = 0;
197 static const int kMaxExtensionRating = 5;
201 // We call this method to signal that the installation should continue.
202 virtual void InstallUIProceed() = 0;
204 // We call this method to signal that the installation should stop, with
205 // |user_initiated| true if the installation was stopped by the user.
206 virtual void InstallUIAbort(bool user_initiated) = 0;
209 virtual ~Delegate() {}
212 // Parameters to show a prompt dialog. Two sets of the
213 // parameters are supported: either use a parent WebContents or use a
214 // parent NativeWindow + a PageNavigator.
216 explicit ShowParams(content::WebContents* contents);
217 ShowParams(gfx::NativeWindow window, content::PageNavigator* navigator);
219 // Parent web contents of the install UI dialog. This can be NULL.
220 content::WebContents* parent_web_contents;
222 // NativeWindow parent and navigator. If initialized using a parent web
223 // contents, these are derived from it.
224 gfx::NativeWindow parent_window;
225 content::PageNavigator* navigator;
228 typedef base::Callback<void(const ExtensionInstallPrompt::ShowParams&,
229 ExtensionInstallPrompt::Delegate*,
230 const ExtensionInstallPrompt::Prompt&)>
233 // Callback to show the default extension install dialog.
234 // The implementations of this function are platform-specific.
235 static ShowDialogCallback GetDefaultShowDialogCallback();
237 // Creates a dummy extension from the |manifest|, replacing the name and
238 // description with the localizations if provided.
239 static scoped_refptr<extensions::Extension> GetLocalizedExtensionForDisplay(
240 const base::DictionaryValue* manifest,
241 int flags, // Extension::InitFromValueFlags
242 const std::string& id,
243 const std::string& localized_name,
244 const std::string& localized_description,
247 // Creates a prompt with a parent web content.
248 explicit ExtensionInstallPrompt(content::WebContents* contents);
250 // Creates a prompt with a profile, a native window and a page navigator.
251 ExtensionInstallPrompt(Profile* profile,
252 gfx::NativeWindow native_window,
253 content::PageNavigator* navigator);
255 virtual ~ExtensionInstallPrompt();
257 ExtensionInstallUI* install_ui() const { return install_ui_.get(); }
259 bool record_oauth2_grant() const { return record_oauth2_grant_; }
261 content::WebContents* parent_web_contents() const {
262 return show_params_.parent_web_contents;
265 // This is called by the bundle installer to verify whether the bundle
266 // should be installed.
268 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
269 virtual void ConfirmBundleInstall(
270 extensions::BundleInstaller* bundle,
271 const extensions::PermissionSet* permissions);
273 // This is called by the standalone installer to verify whether the install
274 // from the webstore should proceed.
276 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
277 virtual void ConfirmStandaloneInstall(Delegate* delegate,
278 const extensions::Extension* extension,
280 const Prompt& prompt);
282 // This is called by the installer to verify whether the installation from
283 // the webstore should proceed. |show_dialog_callback| is optional and can be
286 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
287 virtual void ConfirmWebstoreInstall(
289 const extensions::Extension* extension,
290 const SkBitmap* icon,
291 const ShowDialogCallback& show_dialog_callback);
293 // This is called by the installer to verify whether the installation should
294 // proceed. This is declared virtual for testing. |show_dialog_callback| is
295 // optional and can be NULL.
297 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
298 virtual void ConfirmInstall(Delegate* delegate,
299 const extensions::Extension* extension,
300 const ShowDialogCallback& show_dialog_callback);
302 // This is called by the app handler launcher to verify whether the app
303 // should be re-enabled. This is declared virtual for testing.
305 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
306 virtual void ConfirmReEnable(Delegate* delegate,
307 const extensions::Extension* extension);
309 // This is called by the external install alert UI to verify whether the
310 // extension should be enabled (external extensions are installed disabled).
312 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
313 virtual void ConfirmExternalInstall(
315 const extensions::Extension* extension,
316 const ShowDialogCallback& show_dialog_callback);
318 // This is called by the extension permissions API to verify whether an
319 // extension may be granted additional permissions.
321 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
322 virtual void ConfirmPermissions(Delegate* delegate,
323 const extensions::Extension* extension,
324 const extensions::PermissionSet* permissions);
326 // This is called by the extension identity API to verify whether an
327 // extension can be granted an OAuth2 token.
329 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
330 virtual void ConfirmIssueAdvice(Delegate* delegate,
331 const extensions::Extension* extension,
332 const IssueAdviceInfo& issue_advice);
334 // This is called by the app handler launcher to review what permissions the
335 // extension or app currently has.
337 // We *MUST* eventually call either Proceed() or Abort() on |delegate|.
338 virtual void ReviewPermissions(
340 const extensions::Extension* extension,
341 const std::vector<base::FilePath>& retained_file_paths);
343 // Installation was successful. This is declared virtual for testing.
344 virtual void OnInstallSuccess(const extensions::Extension* extension,
347 // Installation failed. This is declared virtual for testing.
348 virtual void OnInstallFailure(const extensions::CrxInstallerError& error);
351 friend class extensions::ExtensionWebstorePrivateApiTest;
352 friend class extensions::MockGetAuthTokenFunction;
353 friend class WebstoreStartupInstallUnpackFailureTest;
355 // Whether or not we should record the oauth2 grant upon successful install.
356 bool record_oauth2_grant_;
359 friend class GalleryInstallApiTestObserver;
361 // Sets the icon that will be used in any UI. If |icon| is NULL, or contains
362 // an empty bitmap, then a default icon will be used instead.
363 void SetIcon(const SkBitmap* icon);
365 // ImageLoader callback.
366 void OnImageLoaded(const gfx::Image& image);
368 // Starts the process of showing a confirmation UI, which is split into two.
369 // 1) Set off a 'load icon' task.
370 // 2) Handle the load icon response and show the UI (OnImageLoaded).
371 void LoadImageIfNeeded();
373 // OAuth2TokenService::Consumer implementation:
374 virtual void OnGetTokenSuccess(const OAuth2TokenService::Request* request,
375 const std::string& access_token,
376 const base::Time& expiration_time) OVERRIDE;
377 virtual void OnGetTokenFailure(const OAuth2TokenService::Request* request,
378 const GoogleServiceAuthError& error) OVERRIDE;
380 // OAuth2MintTokenFlow::Delegate implementation:
381 virtual void OnIssueAdviceSuccess(
382 const IssueAdviceInfo& issue_advice) OVERRIDE;
383 virtual void OnMintTokenFailure(
384 const GoogleServiceAuthError& error) OVERRIDE;
386 // Shows the actual UI (the icon should already be loaded).
387 void ShowConfirmation();
389 base::MessageLoop* ui_loop_;
391 // The extensions installation icon.
394 // The extension we are showing the UI for, if type is not
395 // BUNDLE_INSTALL_PROMPT.
396 const extensions::Extension* extension_;
398 // The bundle we are showing the UI for, if type BUNDLE_INSTALL_PROMPT.
399 const extensions::BundleInstaller* bundle_;
401 // The permissions being prompted for.
402 scoped_refptr<const extensions::PermissionSet> permissions_;
404 // The object responsible for doing the UI specific actions.
405 scoped_ptr<ExtensionInstallUI> install_ui_;
407 // Parameters to show the confirmation UI.
408 ShowParams show_params_;
410 // The delegate we will call Proceed/Abort on after confirmation UI.
413 // A pre-filled prompt.
416 scoped_ptr<OAuth2TokenService::Request> login_token_request_;
417 scoped_ptr<OAuth2MintTokenFlow> token_flow_;
419 // Used to show the confirm dialog.
420 ShowDialogCallback show_dialog_callback_;
423 #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_PROMPT_H_