// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// 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/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
#include "base/strings/string16.h"
#include "base/threading/thread_checker.h"
#include "build/build_config.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,
    NUM_PROMPT_TYPES = 12,
    WEBSTORE_WIDGET_PROMPT = 13,
  };

  // The last prompt type to display; only used for testing.
  static PromptType g_last_prompt_type_for_tests;

  // Enumeration for permissions and retained files details.
  enum DetailsType {
    PERMISSIONS_DETAILS = 0,
    RETAINED_FILES_DETAILS,
    RETAINED_DEVICES_DETAILS,
  };

  // 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();

    void AddPermissions(const extensions::PermissionMessages& permissions);
    void SetIsShowingDetails(DetailsType type,
                             size_t index,
                             bool is_showing_details);
    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.
    base::string16 GetDialogTitle() const;
    int GetDialogButtons() const;
    // Returns the empty string when there should be no "accept" button.
    base::string16 GetAcceptButtonLabel() const;
    base::string16 GetAbortButtonLabel() const;
    base::string16 GetPermissionsHeading() const;
    base::string16 GetRetainedFilesHeading() const;
    base::string16 GetRetainedDevicesHeading() const;

    bool ShouldShowPermissions() 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;
    base::string16 GetRatingCount() const;
    base::string16 GetUserCount() const;
    size_t GetPermissionCount() const;
    size_t GetPermissionsDetailsCount() const;
    base::string16 GetPermission(size_t index) const;
    base::string16 GetPermissionsDetails(size_t index) const;
    bool GetIsShowingDetails(DetailsType type, size_t index) const;
    size_t GetRetainedFileCount() const;
    base::string16 GetRetainedFile(size_t index) const;
    size_t GetRetainedDeviceCount() const;
    base::string16 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<base::string16>& 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_; }

   private:
    friend class base::RefCountedThreadSafe<Prompt>;

    struct InstallPromptPermissions {
      InstallPromptPermissions();
      ~InstallPromptPermissions();

      std::vector<base::string16> permissions;
      std::vector<base::string16> details;
      std::vector<bool> is_showing_details;
    };

    bool ShouldDisplayRevokeButton() const;

    bool ShouldDisplayRevokeFilesButton() 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)
    InstallPromptPermissions prompt_permissions_;

    bool is_showing_details_for_retained_files_;
    bool is_showing_details_for_retained_devices_;

    // The extension being installed.
    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<base::string16> retained_device_messages_;

    DISALLOW_COPY_AND_ASSIGN(Prompt);
  };

  static const int kMinExtensionRating = 0;
  static const int kMaxExtensionRating = 5;

  enum class Result {
    ACCEPTED,
    USER_CANCELED,
    ABORTED,
  };

  using DoneCallback = base::Callback<void(Result result)>;

  typedef base::Callback<void(ExtensionInstallPromptShowParams*,
                              const DoneCallback&,
                              std::unique_ptr<ExtensionInstallPrompt::Prompt>)>
      ShowDialogCallback;

  // 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);

  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(const DoneCallback& install_callback,
                  const extensions::Extension* extension,
                  const SkBitmap* icon,
                  const ShowDialogCallback& show_dialog_callback);
  void ShowDialog(const 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(
      const 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_; }

 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();

  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_;

  DISALLOW_COPY_AND_ASSIGN(ExtensionInstallPrompt);
};

#endif  // CHROME_BROWSER_EXTENSIONS_EXTENSION_INSTALL_PROMPT_H_
