| // Copyright 2012 The Chromium Authors | 
 | // Use of this source code is governed by a BSD-style license that can be | 
 | // found in the LICENSE file. | 
 |  | 
 | #ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_PROMPT_H_ | 
 | #define CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_PROMPT_H_ | 
 |  | 
 | #include <stddef.h> | 
 |  | 
 | #include <memory> | 
 | #include <string> | 
 | #include <vector> | 
 |  | 
 | #include "base/callback.h" | 
 | #include "base/files/file_path.h" | 
 | #include "base/memory/raw_ptr.h" | 
 | #include "base/memory/ref_counted.h" | 
 | #include "base/memory/weak_ptr.h" | 
 | #include "base/observer_list.h" | 
 | #include "base/observer_list_types.h" | 
 | #include "base/threading/thread_checker.h" | 
 | #include "chrome/browser/extensions/install_prompt_permissions.h" | 
 | #include "chrome/common/buildflags.h" | 
 | #include "extensions/common/permissions/permission_message.h" | 
 | #include "third_party/skia/include/core/SkBitmap.h" | 
 | #include "ui/gfx/image/image.h" | 
 | #include "ui/gfx/native_widget_types.h" | 
 |  | 
 | class ExtensionInstallPromptShowParams; | 
 | class Profile; | 
 |  | 
 | namespace base { | 
 | class DictionaryValue; | 
 | }  // namespace base | 
 |  | 
 | namespace content { | 
 | class BrowserContext; | 
 | class WebContents; | 
 | } | 
 |  | 
 | namespace extensions { | 
 | class CrxInstallError; | 
 | class Extension; | 
 | class ExtensionInstallUI; | 
 | class PermissionSet; | 
 | }  // namespace extensions | 
 |  | 
 | namespace gfx { | 
 | class ImageSkia; | 
 | } | 
 |  | 
 | // Displays all the UI around extension installation. | 
 | class ExtensionInstallPrompt { | 
 |  public: | 
 |   // This enum is associated with Extensions.InstallPrompt_Type UMA histogram. | 
 |   // Do not modify existing values and add new values only to the end. | 
 |   enum PromptType { | 
 |     UNSET_PROMPT_TYPE = -1, | 
 |     INSTALL_PROMPT = 0, | 
 |     // INLINE_INSTALL_PROMPT_DEPRECATED = 1, | 
 |     // BUNDLE_INSTALL_PROMPT_DEPRECATED = 2, | 
 |     RE_ENABLE_PROMPT = 3, | 
 |     PERMISSIONS_PROMPT = 4, | 
 |     EXTERNAL_INSTALL_PROMPT = 5, | 
 |     POST_INSTALL_PERMISSIONS_PROMPT = 6, | 
 |     // LAUNCH_PROMPT_DEPRECATED = 7, | 
 |     REMOTE_INSTALL_PROMPT = 8, | 
 |     REPAIR_PROMPT = 9, | 
 |     DELEGATED_PERMISSIONS_PROMPT = 10, | 
 |     // DELEGATED_BUNDLE_PERMISSIONS_PROMPT_DEPRECATED = 11, | 
 |     WEBSTORE_WIDGET_PROMPT = 12, | 
 |     EXTENSION_REQUEST_PROMPT = 13, | 
 |     EXTENSION_PENDING_REQUEST_PROMPT = 14, | 
 |     NUM_PROMPT_TYPES = 15, | 
 |     // WAIT! Are you adding a new prompt type? Does it *install an extension*? | 
 |     // If not, please create a new dialog, rather than adding more functionality | 
 |     // to this class - it's already too full. | 
 |   }; | 
 |  | 
 |   // The last prompt type to display; only used for testing. | 
 |   static PromptType g_last_prompt_type_for_tests; | 
 |  | 
 |   // Interface for observing events on the prompt. | 
 |   class Observer : public base::CheckedObserver { | 
 |    public: | 
 |     // Called right before the dialog is about to show. | 
 |     virtual void OnDialogOpened() = 0; | 
 |  | 
 |     // Called when the user clicks accept on the dialog. | 
 |     virtual void OnDialogAccepted() = 0; | 
 |  | 
 |     // Called when the user clicks cancel on the dialog, presses 'x' or escape. | 
 |     virtual void OnDialogCanceled() = 0; | 
 |   }; | 
 |  | 
 |   // Extra information needed to display an installation or uninstallation | 
 |   // prompt. Gets populated with raw data and exposes getters for formatted | 
 |   // strings so that the GTK/views/Cocoa install dialogs don't have to repeat | 
 |   // that logic. | 
 |   class Prompt { | 
 |    public: | 
 |     explicit Prompt(PromptType type); | 
 |  | 
 |     Prompt(const Prompt&) = delete; | 
 |     Prompt& operator=(const Prompt&) = delete; | 
 |  | 
 |     ~Prompt(); | 
 |  | 
 |     void AddPermissionSet(const extensions::PermissionSet& permissions); | 
 |     void AddPermissionMessages( | 
 |         const extensions::PermissionMessages& permissions); | 
 |     void SetWebstoreData(const std::string& localized_user_count, | 
 |                          bool show_user_count, | 
 |                          double average_rating, | 
 |                          int rating_count); | 
 |  | 
 |     PromptType type() const { return type_; } | 
 |  | 
 |     // Getters for UI element labels. | 
 |     std::u16string GetDialogTitle() const; | 
 |     int GetDialogButtons() const; | 
 |     // Returns the empty string when there should be no "accept" button. | 
 |     std::u16string GetAcceptButtonLabel() const; | 
 |     std::u16string GetAbortButtonLabel() const; | 
 |     std::u16string GetPermissionsHeading() const; | 
 |     std::u16string GetRetainedFilesHeading() const; | 
 |     std::u16string GetRetainedDevicesHeading() const; | 
 |  | 
 | #if BUILDFLAG(ENABLE_SUPERVISED_USERS) | 
 |     void set_requires_parent_permission(bool requires_parent_permission) { | 
 |       requires_parent_permission_ = requires_parent_permission; | 
 |     } | 
 |  | 
 |     bool requires_parent_permission() const { | 
 |       return requires_parent_permission_; | 
 |     } | 
 | #endif  // BUILDFLAG(ENABLE_SUPERVISED_USERS) | 
 |  | 
 |     bool ShouldShowPermissions() const; | 
 |     bool ShouldDisplayWithholdingUI() const; | 
 |  | 
 |     // Getters for webstore metadata. Only populated when the type is | 
 |     // INLINE_INSTALL_PROMPT, EXTERNAL_INSTALL_PROMPT, or REPAIR_PROMPT. | 
 |  | 
 |     // The star display logic replicates the one used by the webstore (from | 
 |     // components.ratingutils.setFractionalYellowStars). Callers pass in an | 
 |     // "appender", which will be repeatedly called back with the star images | 
 |     // that they append to the star display area. | 
 |     typedef void(*StarAppender)(const gfx::ImageSkia*, void*); | 
 |     void AppendRatingStars(StarAppender appender, void* data) const; | 
 |     std::u16string GetRatingCount() const; | 
 |     std::u16string GetUserCount() const; | 
 |     size_t GetPermissionCount() const; | 
 |     std::u16string GetPermission(size_t index) const; | 
 |     std::u16string GetPermissionsDetails(size_t index) const; | 
 |     size_t GetRetainedFileCount() const; | 
 |     std::u16string GetRetainedFile(size_t index) const; | 
 |     size_t GetRetainedDeviceCount() const; | 
 |     std::u16string GetRetainedDeviceMessageString(size_t index) const; | 
 |  | 
 |     const extensions::Extension* extension() const { return extension_; } | 
 |     void set_extension(const extensions::Extension* extension) { | 
 |       extension_ = extension; | 
 |     } | 
 |  | 
 |     // May be populated for POST_INSTALL_PERMISSIONS_PROMPT. | 
 |     void set_retained_files(const std::vector<base::FilePath>& retained_files) { | 
 |       retained_files_ = retained_files; | 
 |     } | 
 |     void set_retained_device_messages( | 
 |         const std::vector<std::u16string>& retained_device_messages) { | 
 |       retained_device_messages_ = retained_device_messages; | 
 |     } | 
 |  | 
 |     const std::string& delegated_username() const { | 
 |       return delegated_username_; | 
 |     } | 
 |     void set_delegated_username(const std::string& delegated_username) { | 
 |       delegated_username_ = delegated_username; | 
 |     } | 
 |  | 
 |     const gfx::Image& icon() const { return icon_; } | 
 |     void set_icon(const gfx::Image& icon) { icon_ = icon; } | 
 |  | 
 |     double average_rating() const { return average_rating_; } | 
 |     int rating_count() const { return rating_count_; } | 
 |  | 
 |     bool has_webstore_data() const { return has_webstore_data_; } | 
 |  | 
 |     void AddObserver(Observer* observer); | 
 |     void RemoveObserver(Observer* observer); | 
 |  | 
 |     // Called right before the dialog is about to show. | 
 |     void OnDialogOpened(); | 
 |  | 
 |     // Called when the user clicks accept on the dialog. | 
 |     void OnDialogAccepted(); | 
 |  | 
 |     // Called when the user clicks cancel on the dialog, presses 'x' or escape. | 
 |     void OnDialogCanceled(); | 
 |  | 
 |    private: | 
 |     bool ShouldDisplayRevokeButton() const; | 
 |  | 
 |     const PromptType type_; | 
 |  | 
 |     // Permissions that are being requested (may not be all of an extension's | 
 |     // permissions if only additional ones are being requested) | 
 |     extensions::InstallPromptPermissions prompt_permissions_; | 
 |  | 
 | #if BUILDFLAG(ENABLE_SUPERVISED_USERS) | 
 |     // True if the current user is a child. | 
 |     bool requires_parent_permission_ = false; | 
 | #endif  // BUILDFLAG(ENABLE_SUPERVISED_USERS) | 
 |  | 
 |     bool is_requesting_host_permissions_; | 
 |  | 
 |     // The extension being installed. | 
 |     raw_ptr<const extensions::Extension> extension_; | 
 |  | 
 |     std::string delegated_username_; | 
 |  | 
 |     // The icon to be displayed. | 
 |     gfx::Image icon_; | 
 |  | 
 |     // These fields are populated only when the prompt type is | 
 |     // INLINE_INSTALL_PROMPT | 
 |     // Already formatted to be locale-specific. | 
 |     std::string localized_user_count_; | 
 |     // Range is kMinExtensionRating to kMaxExtensionRating | 
 |     double average_rating_; | 
 |     int rating_count_; | 
 |  | 
 |     // Whether we should display the user count (we anticipate this will be | 
 |     // false if localized_user_count_ represents the number zero). | 
 |     bool show_user_count_; | 
 |  | 
 |     // Whether or not this prompt has been populated with data from the | 
 |     // webstore. | 
 |     bool has_webstore_data_; | 
 |  | 
 |     std::vector<base::FilePath> retained_files_; | 
 |     std::vector<std::u16string> retained_device_messages_; | 
 |  | 
 |     base::ObserverList<Observer> observers_; | 
 |   }; | 
 |  | 
 |   static const int kMinExtensionRating = 0; | 
 |   static const int kMaxExtensionRating = 5; | 
 |  | 
 |   enum class Result { | 
 |     ACCEPTED, | 
 |     ACCEPTED_AND_OPTION_CHECKED, | 
 |     USER_CANCELED, | 
 |     ABORTED, | 
 |   }; | 
 |  | 
 |   struct DoneCallbackPayload { | 
 |     explicit DoneCallbackPayload(Result result); | 
 |     DoneCallbackPayload(Result result, std::string justification); | 
 |     ~DoneCallbackPayload() = default; | 
 |  | 
 |     const Result result; | 
 |     const std::string justification; | 
 |   }; | 
 |  | 
 |   using DoneCallback = base::OnceCallback<void(DoneCallbackPayload payload)>; | 
 |  | 
 |   using ShowDialogCallback = base::RepeatingCallback<void( | 
 |       std::unique_ptr<ExtensionInstallPromptShowParams>, | 
 |       DoneCallback, | 
 |       std::unique_ptr<ExtensionInstallPrompt::Prompt>)>; | 
 |  | 
 |   // Callback to show the default extension install dialog. | 
 |   // The implementations of this function are platform-specific. | 
 |   static ShowDialogCallback GetDefaultShowDialogCallback(); | 
 |  | 
 |   // Returns the appropriate prompt type for the given |extension|. | 
 |   // TODO(devlin): This method is yucky - callers probably only care about one | 
 |   // prompt type. We just need to comb through and figure out what it is. | 
 |   static PromptType GetReEnablePromptTypeForExtension( | 
 |       content::BrowserContext* context, | 
 |       const extensions::Extension* extension); | 
 |  | 
 |   // Creates a dummy extension from the |manifest|, replacing the name and | 
 |   // description with the localizations if provided. | 
 |   static scoped_refptr<extensions::Extension> GetLocalizedExtensionForDisplay( | 
 |       const base::DictionaryValue* manifest, | 
 |       int flags,  // Extension::InitFromValueFlags | 
 |       const std::string& id, | 
 |       const std::string& localized_name, | 
 |       const std::string& localized_description, | 
 |       std::string* error); | 
 |  | 
 |   // Creates a prompt with a parent web content. | 
 |   explicit ExtensionInstallPrompt(content::WebContents* contents); | 
 |  | 
 |   // Creates a prompt with a profile and a native window. The most recently | 
 |   // active browser window (or a new browser window if there are no browser | 
 |   // windows) is used if a new tab needs to be opened. | 
 |   ExtensionInstallPrompt(Profile* profile, gfx::NativeWindow native_window); | 
 |  | 
 |   ExtensionInstallPrompt(const ExtensionInstallPrompt&) = delete; | 
 |   ExtensionInstallPrompt& operator=(const ExtensionInstallPrompt&) = delete; | 
 |  | 
 |   virtual ~ExtensionInstallPrompt(); | 
 |  | 
 |   extensions::ExtensionInstallUI* install_ui() const { | 
 |     return install_ui_.get(); | 
 |   } | 
 |  | 
 |   // Starts the process to show the install dialog. Loads the icon (if |icon| is | 
 |   // null), sets up the Prompt, and calls |show_dialog_callback| when ready to | 
 |   // show. | 
 |   // |extension| can be null in the case of a bndle install. | 
 |   // If |icon| is null, this will attempt to load the extension's icon. | 
 |   // |prompt| is used to pass in a prompt with additional data (like retained | 
 |   // device permissions) or a different type. If not provided, |prompt| will | 
 |   // be created as an INSTALL_PROMPT. | 
 |   // |custom_permissions| will be used if provided; otherwise, the extensions | 
 |   // current permissions are used. | 
 |   // | 
 |   // The |install_callback| *MUST* eventually be called. | 
 |   void ShowDialog(DoneCallback install_callback, | 
 |                   const extensions::Extension* extension, | 
 |                   const SkBitmap* icon, | 
 |                   const ShowDialogCallback& show_dialog_callback); | 
 |   void ShowDialog(DoneCallback install_callback, | 
 |                   const extensions::Extension* extension, | 
 |                   const SkBitmap* icon, | 
 |                   std::unique_ptr<Prompt> prompt, | 
 |                   const ShowDialogCallback& show_dialog_callback); | 
 |   // Declared virtual for testing purposes. | 
 |   // Note: if all you want to do is automatically confirm or cancel, prefer | 
 |   // ScopedTestDialogAutoConfirm from extension_dialog_auto_confirm.h | 
 |   virtual void ShowDialog( | 
 |       DoneCallback install_callback, | 
 |       const extensions::Extension* extension, | 
 |       const SkBitmap* icon, | 
 |       std::unique_ptr<Prompt> prompt, | 
 |       std::unique_ptr<const extensions::PermissionSet> custom_permissions, | 
 |       const ShowDialogCallback& show_dialog_callback); | 
 |  | 
 |   // Installation was successful. This is declared virtual for testing. | 
 |   virtual void OnInstallSuccess( | 
 |       scoped_refptr<const extensions::Extension> extension, | 
 |       SkBitmap* icon); | 
 |  | 
 |   // Installation failed. This is declared virtual for testing. | 
 |   virtual void OnInstallFailure(const extensions::CrxInstallError& error); | 
 |  | 
 |   bool did_call_show_dialog() const { return did_call_show_dialog_; } | 
 |  | 
 |   std::unique_ptr<Prompt> GetPromptForTesting(); | 
 |  | 
 |  private: | 
 |   // Sets the icon that will be used in any UI. If |icon| is NULL, or contains | 
 |   // an empty bitmap, then a default icon will be used instead. | 
 |   void SetIcon(const SkBitmap* icon); | 
 |  | 
 |   // ImageLoader callback. | 
 |   void OnImageLoaded(const gfx::Image& image); | 
 |  | 
 |   // Starts the process of showing a confirmation UI, which is split into two. | 
 |   // 1) Set off a 'load icon' task. | 
 |   // 2) Handle the load icon response and show the UI (OnImageLoaded). | 
 |   void LoadImageIfNeeded(); | 
 |  | 
 |   // Shows the actual UI (the icon should already be loaded). | 
 |   void ShowConfirmation(); | 
 |  | 
 |   // If auto confirm is enabled then posts a task to proceed with or cancel the | 
 |   // install and returns true. Otherwise returns false. | 
 |   bool AutoConfirmPromptIfEnabled(); | 
 |  | 
 |   raw_ptr<Profile> profile_; | 
 |  | 
 |   base::ThreadChecker ui_thread_checker_; | 
 |  | 
 |   // The extensions installation icon. | 
 |   SkBitmap icon_; | 
 |  | 
 |   // The extension we are showing the UI for. | 
 |   scoped_refptr<const extensions::Extension> extension_; | 
 |  | 
 |   // A custom set of permissions to show in the install prompt instead of the | 
 |   // extension's active permissions. | 
 |   std::unique_ptr<const extensions::PermissionSet> custom_permissions_; | 
 |  | 
 |   // The object responsible for doing the UI specific actions. | 
 |   std::unique_ptr<extensions::ExtensionInstallUI> install_ui_; | 
 |  | 
 |   // Parameters to show the confirmation UI. | 
 |   std::unique_ptr<ExtensionInstallPromptShowParams> show_params_; | 
 |  | 
 |   // The callback to run with the result. | 
 |   DoneCallback done_callback_; | 
 |  | 
 |   // A pre-filled prompt. | 
 |   std::unique_ptr<Prompt> prompt_; | 
 |  | 
 |   // Used to show the confirm dialog. | 
 |   ShowDialogCallback show_dialog_callback_; | 
 |  | 
 |   // Whether or not the |show_dialog_callback_| was called. | 
 |   bool did_call_show_dialog_; | 
 |  | 
 |   base::WeakPtrFactory<ExtensionInstallPrompt> weak_factory_{this}; | 
 | }; | 
 |  | 
 | #endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_PROMPT_H_ |