// 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_MENU_MANAGER_H_
#define CHROME_BROWSER_EXTENSIONS_MENU_MANAGER_H_

#include <stddef.h>
#include <stdint.h>

#include <map>
#include <memory>
#include <set>
#include <string>
#include <vector>

#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/scoped_observer.h"
#include "base/strings/string16.h"
#include "base/values.h"
#include "chrome/browser/extensions/extension_icon_manager.h"
#include "components/keyed_service/core/keyed_service.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "extensions/browser/extension_registry_observer.h"
#include "extensions/common/url_pattern_set.h"
#include "ui/gfx/image/image.h"

namespace content {
class BrowserContext;
class RenderFrameHost;
class WebContents;
struct ContextMenuParams;
}

namespace extensions {
class Extension;
class ExtensionRegistry;
class StateStore;

// Represents a menu item added by an extension.
class MenuItem {
 public:
  using List = std::vector<MenuItem*>;
  using OwnedList = std::vector<std::unique_ptr<MenuItem>>;

  // Key used to identify which extension a menu item belongs to.  A menu item
  // can also belong to a <webview>, in which case |webview_embedder_process_id|
  // and |webview_instance_id| will be non-zero. When two ExtensionKeys are
  // compared, an empty |extension_id| will match any other extension ID. This
  // allows menu items belonging to webviews to be found with only the two
  // webview IDs when the extension ID is not known. This is currently done from
  // ChromeExtensionsBrowserClient::CleanUpWebView().
  struct ExtensionKey {
    std::string extension_id;
    int webview_embedder_process_id;
    int webview_instance_id;

    ExtensionKey();
    explicit ExtensionKey(const std::string& extension_id);
    ExtensionKey(const std::string& extension_id,
                 int webview_embedder_process_id,
                 int webview_instance_id);

    bool operator==(const ExtensionKey& other) const;
    bool operator!=(const ExtensionKey& other) const;
    bool operator<(const ExtensionKey& other) const;

    bool empty() const;
  };

  // An Id uniquely identifies a context menu item registered by an extension.
  struct Id {
    Id();
    // Since the unique ID (uid or string_uid) is parsed from API arguments,
    // the normal usage is to set the uid or string_uid immediately after
    // construction.
    Id(bool incognito, const ExtensionKey& extension_key);
    ~Id();

    bool operator==(const Id& other) const;
    bool operator!=(const Id& other) const;
    bool operator<(const Id& other) const;

    bool incognito;
    ExtensionKey extension_key;
    // Only one of uid or string_uid will be defined.
    int uid;
    std::string string_uid;
  };

  // For context menus, these are the contexts where an item can appear.
  enum Context {
    ALL = 1,
    PAGE = 2,
    SELECTION = 4,
    LINK = 8,
    EDITABLE = 16,
    IMAGE = 32,
    VIDEO = 64,
    AUDIO = 128,
    FRAME = 256,
    LAUNCHER = 512,
    BROWSER_ACTION = 1024,
    PAGE_ACTION = 2048
  };

  // An item can be only one of these types.
  enum Type {
    NORMAL,
    CHECKBOX,
    RADIO,
    SEPARATOR
  };

  // A list of Contexts for an item.
  class ContextList {
   public:
    ContextList() : value_(0) {}
    explicit ContextList(Context context) : value_(context) {}
    ContextList(const ContextList& other) : value_(other.value_) {}

    void operator=(const ContextList& other) {
      value_ = other.value_;
    }

    bool operator==(const ContextList& other) const {
      return value_ == other.value_;
    }

    bool operator!=(const ContextList& other) const {
      return !(*this == other);
    }

    bool Contains(Context context) const {
      return (value_ & context) > 0;
    }

    void Add(Context context) {
      value_ |= context;
    }

    std::unique_ptr<base::Value> ToValue() const {
      return std::unique_ptr<base::Value>(
          new base::Value(static_cast<int>(value_)));
    }

    bool Populate(const base::Value& value) {
      int int_value;
      if (!value.GetAsInteger(&int_value) || int_value < 0)
        return false;
      value_ = int_value;
      return true;
    }

   private:
    uint32_t value_;  // A bitmask of Context values.
  };

  MenuItem(const Id& id,
           const std::string& title,
           bool checked,
           bool enabled,
           Type type,
           const ContextList& contexts);
  virtual ~MenuItem();

  // Simple accessor methods.
  bool incognito() const { return id_.incognito; }
  const std::string& extension_id() const {
    return id_.extension_key.extension_id;
  }
  const std::string& title() const { return title_; }
  const OwnedList& children() { return children_; }
  const Id& id() const { return id_; }
  Id* parent_id() const { return parent_id_.get(); }
  int child_count() const { return children_.size(); }
  const ContextList& contexts() const { return contexts_; }
  Type type() const { return type_; }
  bool checked() const { return checked_; }
  bool enabled() const { return enabled_; }
  const URLPatternSet& document_url_patterns() const {
    return document_url_patterns_;
  }
  const URLPatternSet& target_url_patterns() const {
    return target_url_patterns_;
  }

  // Simple mutator methods.
  void set_title(const std::string& new_title) { title_ = new_title; }
  void set_contexts(ContextList contexts) { contexts_ = contexts; }
  void set_type(Type type) { type_ = type; }
  void set_enabled(bool enabled) { enabled_ = enabled; }
  void set_document_url_patterns(const URLPatternSet& patterns) {
    document_url_patterns_ = patterns;
  }
  void set_target_url_patterns(const URLPatternSet& patterns) {
    target_url_patterns_ = patterns;
  }

  // Returns the title with any instances of %s replaced by |selection|. The
  // result will be no longer than |max_length|.
  base::string16 TitleWithReplacement(const base::string16& selection,
                                size_t max_length) const;

  // Sets the checked state to |checked|. Returns true if successful.
  bool SetChecked(bool checked);

  // Converts to Value for serialization to preferences.
  std::unique_ptr<base::DictionaryValue> ToValue() const;

  // Returns a new MenuItem created from |value|, or NULL if there is
  // an error.
  static std::unique_ptr<MenuItem> Populate(const std::string& extension_id,
                                            const base::DictionaryValue& value,
                                            std::string* error);

  // Sets any document and target URL patterns from |properties|.
  bool PopulateURLPatterns(std::vector<std::string>* document_url_patterns,
                           std::vector<std::string>* target_url_patterns,
                           std::string* error);

 protected:
  friend class MenuManager;

  // Adds |item| and sets its parent_id_.
  void AddChild(std::unique_ptr<MenuItem> item);

  // Removes the child item from this parent and returns it.
  std::unique_ptr<MenuItem> ReleaseChild(const Id& child_id, bool recursive);

  // Recursively appends all descendant items (children, grandchildren, etc.)
  // to the output |list|.
  void GetFlattenedSubtree(MenuItem::List* list);

  // Recursively removes all descendant items (children, grandchildren, etc.),
  // returning the ids of the removed items.
  std::set<Id> RemoveAllDescendants();

 private:
  // The unique id for this item.
  Id id_;

  // What gets shown in the menu for this item.
  std::string title_;

  Type type_;

  // This should only be true for items of type CHECKBOX or RADIO.
  bool checked_;

  // If the item is enabled or not.
  bool enabled_;

  // In what contexts should the item be shown?
  ContextList contexts_;

  // If this item is a child of another item, the unique id of its parent. If
  // this is a top-level item with no parent, this will be NULL.
  std::unique_ptr<Id> parent_id_;

  // Patterns for restricting what documents this item will appear for. This
  // applies to the frame where the click took place.
  URLPatternSet document_url_patterns_;

  // Patterns for restricting where items appear based on the src/href
  // attribute of IMAGE/AUDIO/VIDEO/LINK tags.
  URLPatternSet target_url_patterns_;

  // Any children this item may have.
  OwnedList children_;

  DISALLOW_COPY_AND_ASSIGN(MenuItem);
};

// This class keeps track of menu items added by extensions.
class MenuManager : public content::NotificationObserver,
                    public base::SupportsWeakPtr<MenuManager>,
                    public KeyedService,
                    public ExtensionRegistryObserver {
 public:
  static const char kOnContextMenus[];
  static const char kOnWebviewContextMenus[];

  MenuManager(content::BrowserContext* context, StateStore* store_);
  ~MenuManager() override;

  // Convenience function to get the MenuManager for a browser context.
  static MenuManager* Get(content::BrowserContext* context);

  // Returns the keys of extensions which have menu items registered.
  std::set<MenuItem::ExtensionKey> ExtensionIds();

  // Returns a list of all the *top-level* menu items (added via AddContextItem)
  // for the given extension specified by |extension_key|, *not* including child
  // items (added via AddChildItem); although those can be reached via the
  // top-level items' children. A view can then decide how to display these,
  // including whether to put them into a submenu if there are more than 1.
  const MenuItem::OwnedList* MenuItems(
      const MenuItem::ExtensionKey& extension_key);

  // Adds a top-level menu item for an extension, requiring the |extension|
  // pointer so it can load the icon for the extension. Returns a boolean
  // indicating success or failure.
  bool AddContextItem(const Extension* extension,
                      std::unique_ptr<MenuItem> item);

  // Add an item as a child of another item which has been previously added.
  // Returns a boolean indicating success or failure.
  bool AddChildItem(const MenuItem::Id& parent_id,
                    std::unique_ptr<MenuItem> child);

  // Makes existing item with |child_id| a child of the item with |parent_id|.
  // If the child item was already a child of another parent, this will remove
  // it from that parent first. It is an error to try and move an item to be a
  // child of one of its own descendants. It is legal to pass NULL for
  // |parent_id|, which means the item should be moved to the top-level.
  bool ChangeParent(const MenuItem::Id& child_id,
                    const MenuItem::Id* parent_id);

  // Removes a context menu item with the given id (whether it is a top-level
  // item or a child of some other item), returning true if the item was found
  // and removed or false otherwise.
  bool RemoveContextMenuItem(const MenuItem::Id& id);

  // Removes all items for the given extension specified by |extension_key|.
  void RemoveAllContextItems(const MenuItem::ExtensionKey& extension_key);

  // Returns the item with the given |id| or NULL.
  MenuItem* GetItemById(const MenuItem::Id& id) const;

  // Notify the MenuManager that an item has been updated not through
  // an explicit call into MenuManager. For example, if an item is
  // acquired by a call to GetItemById and changed, then this should be called.
  // Returns true if the item was found or false otherwise.
  bool ItemUpdated(const MenuItem::Id& id);

  // Called when a menu item is clicked on by the user.
  void ExecuteCommand(content::BrowserContext* context,
                      content::WebContents* web_contents,
                      content::RenderFrameHost* render_frame_host,
                      const content::ContextMenuParams& params,
                      const MenuItem::Id& menu_item_id);

  // This returns a image of width/height kFaviconSize, loaded either from an
  // entry specified in the extension's 'icon' section of the manifest, or a
  // default extension icon.
  gfx::Image GetIconForExtension(const std::string& extension_id);

  // content::NotificationObserver implementation.
  void Observe(int type,
               const content::NotificationSource& source,
               const content::NotificationDetails& details) override;

  // ExtensionRegistryObserver implementation.
  void OnExtensionLoaded(content::BrowserContext* browser_context,
                         const Extension* extension) override;
  void OnExtensionUnloaded(content::BrowserContext* browser_context,
                           const Extension* extension,
                           UnloadedExtensionInfo::Reason reason) override;

  // Stores the menu items for the extension in the state storage.
  void WriteToStorage(const Extension* extension,
                      const MenuItem::ExtensionKey& extension_key);

  // Reads menu items for the extension from the state storage. Any invalid
  // items are ignored.
  void ReadFromStorage(const std::string& extension_id,
                       std::unique_ptr<base::Value> value);

  // Removes all "incognito" "split" mode context items.
  void RemoveAllIncognitoContextItems();

 private:
  FRIEND_TEST_ALL_PREFIXES(MenuManagerTest, DeleteParent);
  FRIEND_TEST_ALL_PREFIXES(MenuManagerTest, RemoveOneByOne);

  // This is a helper function which takes care of de-selecting any other radio
  // items in the same group (i.e. that are adjacent in the list).
  void RadioItemSelected(MenuItem* item);

  // Make sure that there is only one radio item selected at once in any run.
  // If there are no radio items selected, then the first item in the run
  // will get selected. If there are multiple radio items selected, then only
  // the last one will get selected.
  void SanitizeRadioList(const MenuItem::OwnedList& item_list);

  // Returns true if item is a descendant of an item with id |ancestor_id|.
  bool DescendantOf(MenuItem* item, const MenuItem::Id& ancestor_id);

  // We keep items organized by mapping ExtensionKey to a list of items.
  std::map<MenuItem::ExtensionKey, MenuItem::OwnedList> context_items_;

  // This lets us make lookup by id fast. It maps id to MenuItem* for
  // all items the menu manager knows about, including all children of top-level
  // items.
  std::map<MenuItem::Id, MenuItem*> items_by_id_;

  content::NotificationRegistrar registrar_;

  // Listen to extension load, unloaded notifications.
  ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver>
      extension_registry_observer_;

  ExtensionIconManager icon_manager_;

  content::BrowserContext* browser_context_;

  // Owned by ExtensionSystem.
  StateStore* store_;

  DISALLOW_COPY_AND_ASSIGN(MenuManager);
};

}  // namespace extensions

#endif  // CHROME_BROWSER_EXTENSIONS_MENU_MANAGER_H_
