| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_UI_H_ | 5 #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_UI_H_ |
| 6 #define CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_UI_H_ | 6 #define CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_UI_H_ |
| 7 #pragma once | 7 #pragma once |
| 8 | 8 |
| 9 #include <string> | 9 #include <string> |
| 10 #include <vector> | |
| 11 | 10 |
| 12 #include "base/compiler_specific.h" | 11 #include "base/compiler_specific.h" |
| 13 #include "base/string16.h" | 12 #include "base/string16.h" |
| 14 #include "chrome/browser/extensions/image_loading_tracker.h" | |
| 15 #include "chrome/common/extensions/url_pattern.h" | |
| 16 #include "third_party/skia/include/core/SkBitmap.h" | |
| 17 #include "ui/gfx/image/image.h" | |
| 18 #include "ui/gfx/image/image_skia.h" | |
| 19 #include "ui/gfx/native_widget_types.h" | |
| 20 | 13 |
| 21 class Browser; | 14 class Browser; |
| 22 class ExtensionPermissionSet; | |
| 23 class MessageLoop; | |
| 24 class Profile; | 15 class Profile; |
| 25 class InfoBarDelegate; | 16 class SkBitmap; |
| 26 class TabContents; | |
| 27 typedef TabContents TabContentsWrapper; | |
| 28 | |
| 29 namespace base { | |
| 30 class DictionaryValue; | |
| 31 } | |
| 32 | 17 |
| 33 namespace extensions { | 18 namespace extensions { |
| 34 class BundleInstaller; | |
| 35 class Extension; | 19 class Extension; |
| 36 class ExtensionWebstorePrivateApiTest; | 20 class ExtensionWebstorePrivateApiTest; |
| 37 } // namespace extensions | 21 } // namespace extensions |
| 38 | 22 |
| 39 // Displays all the UI around extension installation. | 23 // Interface that should be implemented for each platform to display all the UI |
| 40 class ExtensionInstallUI : public ImageLoadingTracker::Observer { | 24 // around extension installation. |
| 25 class ExtensionInstallUI { |
| 41 public: | 26 public: |
| 42 enum PromptType { | 27 static ExtensionInstallUI* Create(Profile* profile); |
| 43 UNSET_PROMPT_TYPE = -1, | |
| 44 INSTALL_PROMPT = 0, | |
| 45 INLINE_INSTALL_PROMPT, | |
| 46 BUNDLE_INSTALL_PROMPT, | |
| 47 RE_ENABLE_PROMPT, | |
| 48 PERMISSIONS_PROMPT, | |
| 49 NUM_PROMPT_TYPES | |
| 50 }; | |
| 51 | 28 |
| 52 // Extra information needed to display an installation or uninstallation | 29 virtual ~ExtensionInstallUI(); |
| 53 // prompt. Gets populated with raw data and exposes getters for formatted | |
| 54 // strings so that the GTK/views/Cocoa install dialogs don't have to repeat | |
| 55 // that logic. | |
| 56 class Prompt { | |
| 57 public: | |
| 58 explicit Prompt(PromptType type); | |
| 59 ~Prompt(); | |
| 60 | 30 |
| 61 void SetPermissions(const std::vector<string16>& permissions); | 31 // Called when an extension was installed. |
| 62 void SetInlineInstallWebstoreData(const std::string& localized_user_count, | 32 virtual void OnInstallSuccess(const extensions::Extension* extension, |
| 63 double average_rating, | 33 SkBitmap* icon) = 0; |
| 64 int rating_count); | 34 // Called when an extension failed to install. |
| 35 virtual void OnInstallFailure(const string16& error) = 0; |
| 65 | 36 |
| 66 PromptType type() const { return type_; } | 37 // Whether or not to show the default UI after completing the installation. |
| 67 void set_type(PromptType type) { type_ = type; } | 38 virtual void SetSkipPostInstallUI(bool skip_ui) = 0; |
| 68 | |
| 69 // Getters for UI element labels. | |
| 70 string16 GetDialogTitle() const; | |
| 71 string16 GetHeading() const; | |
| 72 string16 GetAcceptButtonLabel() const; | |
| 73 bool HasAbortButtonLabel() const; | |
| 74 string16 GetAbortButtonLabel() const; | |
| 75 string16 GetPermissionsHeading() const; | |
| 76 | |
| 77 // Getters for webstore metadata. Only populated when the type is | |
| 78 // INLINE_INSTALL_PROMPT. | |
| 79 | |
| 80 // The star display logic replicates the one used by the webstore (from | |
| 81 // components.ratingutils.setFractionalYellowStars). Callers pass in an | |
| 82 // "appender", which will be repeatedly called back with the star images | |
| 83 // that they append to the star display area. | |
| 84 typedef void(*StarAppender)(const gfx::ImageSkia*, void*); | |
| 85 void AppendRatingStars(StarAppender appender, void* data) const; | |
| 86 string16 GetRatingCount() const; | |
| 87 string16 GetUserCount() const; | |
| 88 size_t GetPermissionCount() const; | |
| 89 string16 GetPermission(size_t index) const; | |
| 90 | |
| 91 // Populated for BUNDLE_INSTALL_PROMPT. | |
| 92 const extensions::BundleInstaller* bundle() const { return bundle_; } | |
| 93 void set_bundle(const extensions::BundleInstaller* bundle) { | |
| 94 bundle_ = bundle; | |
| 95 } | |
| 96 | |
| 97 // Populated for all other types. | |
| 98 const extensions::Extension* extension() const { return extension_; } | |
| 99 void set_extension(const extensions::Extension* extension) { | |
| 100 extension_ = extension; | |
| 101 } | |
| 102 | |
| 103 const gfx::Image& icon() const { return icon_; } | |
| 104 void set_icon(const gfx::Image& icon) { icon_ = icon; } | |
| 105 | |
| 106 private: | |
| 107 PromptType type_; | |
| 108 // Permissions that are being requested (may not be all of an extension's | |
| 109 // permissions if only additional ones are being requested) | |
| 110 std::vector<string16> permissions_; | |
| 111 | |
| 112 // The extension or bundle being installed. | |
| 113 const extensions::Extension* extension_; | |
| 114 const extensions::BundleInstaller* bundle_; | |
| 115 | |
| 116 // The icon to be displayed. | |
| 117 gfx::Image icon_; | |
| 118 | |
| 119 // These fields are populated only when the prompt type is | |
| 120 // INLINE_INSTALL_PROMPT | |
| 121 // Already formatted to be locale-specific. | |
| 122 std::string localized_user_count_; | |
| 123 // Range is kMinExtensionRating to kMaxExtensionRating | |
| 124 double average_rating_; | |
| 125 int rating_count_; | |
| 126 }; | |
| 127 | |
| 128 static const int kMinExtensionRating = 0; | |
| 129 static const int kMaxExtensionRating = 5; | |
| 130 | |
| 131 class Delegate { | |
| 132 public: | |
| 133 // We call this method to signal that the installation should continue. | |
| 134 virtual void InstallUIProceed() = 0; | |
| 135 | |
| 136 // We call this method to signal that the installation should stop, with | |
| 137 // |user_initiated| true if the installation was stopped by the user. | |
| 138 virtual void InstallUIAbort(bool user_initiated) = 0; | |
| 139 | |
| 140 protected: | |
| 141 virtual ~Delegate() {} | |
| 142 }; | |
| 143 | |
| 144 // Creates a dummy extension from the |manifest|, replacing the name and | |
| 145 // description with the localizations if provided. | |
| 146 static scoped_refptr<extensions::Extension> GetLocalizedExtensionForDisplay( | |
| 147 const base::DictionaryValue* manifest, | |
| 148 const std::string& id, | |
| 149 const std::string& localized_name, | |
| 150 const std::string& localized_description, | |
| 151 std::string* error); | |
| 152 | |
| 153 explicit ExtensionInstallUI(Profile* profile); | |
| 154 virtual ~ExtensionInstallUI(); | |
| 155 | 39 |
| 156 // TODO(asargent) Normally we navigate to the new tab page when an app is | 40 // TODO(asargent) Normally we navigate to the new tab page when an app is |
| 157 // installed, but we're experimenting with instead showing a bubble when | 41 // installed, but we're experimenting with instead showing a bubble when |
| 158 // an app is installed which points to the new tab button. This may become | 42 // an app is installed which points to the new tab button. This may become |
| 159 // the default behavior in the future. | 43 // the default behavior in the future. |
| 160 void set_use_app_installed_bubble(bool use_bubble) { | 44 virtual void SetUseAppInstalledBubble(bool use_bubble) = 0; |
| 161 use_app_installed_bubble_ = use_bubble; | |
| 162 } | |
| 163 | |
| 164 // Whether or not to show the default UI after completing the installation. | |
| 165 void set_skip_post_install_ui(bool skip_ui) { | |
| 166 skip_post_install_ui_ = skip_ui; | |
| 167 } | |
| 168 | |
| 169 // This is called by the bundle installer to verify whether the bundle | |
| 170 // should be installed. | |
| 171 // | |
| 172 // We *MUST* eventually call either Proceed() or Abort() on |delegate|. | |
| 173 virtual void ConfirmBundleInstall(extensions::BundleInstaller* bundle, | |
| 174 const ExtensionPermissionSet* permissions); | |
| 175 | |
| 176 // This is called by the inline installer to verify whether the inline | |
| 177 // install from the webstore should proceed. | |
| 178 // | |
| 179 // We *MUST* eventually call either Proceed() or Abort() on |delegate|. | |
| 180 virtual void ConfirmInlineInstall(Delegate* delegate, | |
| 181 const extensions::Extension* extension, | |
| 182 SkBitmap* icon, | |
| 183 const Prompt& prompt); | |
| 184 | |
| 185 // This is called by the installer to verify whether the installation from | |
| 186 // the webstore should proceed. | |
| 187 // | |
| 188 // We *MUST* eventually call either Proceed() or Abort() on |delegate|. | |
| 189 virtual void ConfirmWebstoreInstall(Delegate* delegate, | |
| 190 const extensions::Extension* extension, | |
| 191 const SkBitmap* icon); | |
| 192 | |
| 193 // This is called by the installer to verify whether the installation should | |
| 194 // proceed. This is declared virtual for testing. | |
| 195 // | |
| 196 // We *MUST* eventually call either Proceed() or Abort() on |delegate|. | |
| 197 virtual void ConfirmInstall(Delegate* delegate, | |
| 198 const extensions::Extension* extension); | |
| 199 | |
| 200 // This is called by the app handler launcher to verify whether the app | |
| 201 // should be re-enabled. This is declared virtual for testing. | |
| 202 // | |
| 203 // We *MUST* eventually call either Proceed() or Abort() on |delegate|. | |
| 204 virtual void ConfirmReEnable(Delegate* delegate, | |
| 205 const extensions::Extension* extension); | |
| 206 | |
| 207 // This is called by the extension permissions API to verify whether an | |
| 208 // extension may be granted additional permissions. | |
| 209 // | |
| 210 // We *MUST* eventually call either Proceed() or Abort() on |delegate|. | |
| 211 virtual void ConfirmPermissions(Delegate* delegate, | |
| 212 const extensions::Extension* extension, | |
| 213 const ExtensionPermissionSet* permissions); | |
| 214 | |
| 215 // Installation was successful. This is declared virtual for testing. | |
| 216 virtual void OnInstallSuccess(const extensions::Extension* extension, | |
| 217 SkBitmap* icon); | |
| 218 | |
| 219 // Installation failed. This is declared virtual for testing. | |
| 220 virtual void OnInstallFailure(const string16& error); | |
| 221 | |
| 222 // ImageLoadingTracker::Observer: | |
| 223 virtual void OnImageLoaded(const gfx::Image& image, | |
| 224 const std::string& extension_id, | |
| 225 int index) OVERRIDE; | |
| 226 | 45 |
| 227 // Opens apps UI and animates the app icon for the app with id |app_id|. | 46 // Opens apps UI and animates the app icon for the app with id |app_id|. |
| 228 static void OpenAppInstalledUI(Browser* browser, const std::string& app_id); | 47 static void OpenAppInstalledUI(Browser* browser, const std::string& app_id); |
| 229 | 48 |
| 230 protected: | |
| 231 friend class extensions::ExtensionWebstorePrivateApiTest; | |
| 232 friend class WebstoreInlineInstallUnpackFailureTest; | |
| 233 | |
| 234 // Disables showing UI (ErrorBox, etc.) for install failures. To be used only | 49 // Disables showing UI (ErrorBox, etc.) for install failures. To be used only |
| 235 // in tests. | 50 // in tests. |
| 236 static void DisableFailureUIForTests(); | 51 static void DisableFailureUIForTests(); |
| 237 | 52 |
| 238 private: | 53 protected: |
| 239 friend class GalleryInstallApiTestObserver; | 54 ExtensionInstallUI(); |
| 240 | |
| 241 // Show an infobar for a newly-installed theme. previous_theme_id | |
| 242 // should be empty if the previous theme was the system/default | |
| 243 // theme. | |
| 244 static void ShowThemeInfoBar( | |
| 245 const std::string& previous_theme_id, bool previous_using_native_theme, | |
| 246 const extensions::Extension* new_theme, Profile* profile); | |
| 247 | |
| 248 // Sets the icon that will be used in any UI. If |icon| is NULL, or contains | |
| 249 // an empty bitmap, then a default icon will be used instead. | |
| 250 void SetIcon(const SkBitmap* icon); | |
| 251 | |
| 252 // Starts the process of showing a confirmation UI, which is split into two. | |
| 253 // 1) Set off a 'load icon' task. | |
| 254 // 2) Handle the load icon response and show the UI (OnImageLoaded). | |
| 255 void LoadImageIfNeeded(); | |
| 256 | |
| 257 // Shows the actual UI (the icon should already be loaded). | |
| 258 void ShowConfirmation(); | |
| 259 | |
| 260 // Returns the delegate to control the browser's info bar. This is | |
| 261 // within its own function due to its platform-specific nature. | |
| 262 static InfoBarDelegate* GetNewThemeInstalledInfoBarDelegate( | |
| 263 TabContentsWrapper* tab_contents, | |
| 264 const extensions::Extension* new_theme, | |
| 265 const std::string& previous_theme_id, | |
| 266 bool previous_using_native_theme); | |
| 267 | |
| 268 Profile* profile_; | |
| 269 MessageLoop* ui_loop_; | |
| 270 | |
| 271 // Used to undo theme installation. | |
| 272 std::string previous_theme_id_; | |
| 273 bool previous_using_native_theme_; | |
| 274 | |
| 275 // The extensions installation icon. | |
| 276 SkBitmap icon_; | |
| 277 | |
| 278 // The extension we are showing the UI for. | |
| 279 const extensions::Extension* extension_; | |
| 280 | |
| 281 // The bundle we are showing the UI for, if type BUNDLE_INSTALL_PROMPT. | |
| 282 const extensions::BundleInstaller* bundle_; | |
| 283 | |
| 284 // The permissions being prompted for. | |
| 285 scoped_refptr<const ExtensionPermissionSet> permissions_; | |
| 286 | |
| 287 // The delegate we will call Proceed/Abort on after confirmation UI. | |
| 288 Delegate* delegate_; | |
| 289 | |
| 290 // A pre-filled prompt. | |
| 291 Prompt prompt_; | |
| 292 | |
| 293 // The type of prompt we are going to show. | |
| 294 PromptType prompt_type_; | |
| 295 | |
| 296 // Keeps track of extension images being loaded on the File thread for the | |
| 297 // purpose of showing the install UI. | |
| 298 ImageLoadingTracker tracker_; | |
| 299 | |
| 300 // Whether to show an installed bubble on app install, or use the default | |
| 301 // action of opening a new tab page. | |
| 302 bool use_app_installed_bubble_; | |
| 303 | |
| 304 // Whether or not to show the default UI after completing the installation. | |
| 305 bool skip_post_install_ui_; | |
| 306 }; | 55 }; |
| 307 | 56 |
| 308 #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_UI_H_ | 57 #endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_UI_H_ |
| OLD | NEW |