blob: 299fa059edc0e232d44a706095bfea391824e303 [file] [log] [blame]
[email protected]7dddebc32012-01-11 22:01:031// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]2e3b5202010-03-23 06:52:412// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#ifndef CHROME_BROWSER_EXTENSIONS_EXTENSION_MENU_MANAGER_H_
6#define CHROME_BROWSER_EXTENSIONS_EXTENSION_MENU_MANAGER_H_
[email protected]32b76ef2010-07-26 23:08:247#pragma once
[email protected]2e3b5202010-03-23 06:52:418
9#include <map>
10#include <set>
11#include <string>
12#include <vector>
13
14#include "base/basictypes.h"
[email protected]17902752011-08-31 22:52:5415#include "base/compiler_specific.h"
[email protected]2b07c93f2010-08-02 23:13:0416#include "base/gtest_prod_util.h"
[email protected]3b63f8f42011-03-28 01:54:1517#include "base/memory/scoped_ptr.h"
[email protected]2e3b5202010-03-23 06:52:4118#include "base/string16.h"
[email protected]b671760b2010-07-15 21:13:4719#include "chrome/browser/extensions/extension_icon_manager.h"
[email protected]cced75a2011-05-20 08:31:1220#include "chrome/common/extensions/url_pattern_set.h"
[email protected]6c2381d2011-10-19 02:52:5321#include "content/public/browser/notification_observer.h"
22#include "content/public/browser/notification_registrar.h"
[email protected]2e3b5202010-03-23 06:52:4123
[email protected]2e3b5202010-03-23 06:52:4124
[email protected]052c92702010-06-25 07:25:5225class Extension;
[email protected]2e3b5202010-03-23 06:52:4126class Profile;
[email protected]b671760b2010-07-15 21:13:4727class SkBitmap;
[email protected]ea049a02011-12-25 21:37:0928
29namespace content {
30class WebContents;
[email protected]35be7ec2012-02-12 20:42:5131struct ContextMenuParams;
[email protected]ea049a02011-12-25 21:37:0932}
[email protected]2e3b5202010-03-23 06:52:4133
34// Represents a menu item added by an extension.
35class ExtensionMenuItem {
36 public:
[email protected]63a414b52010-06-03 23:20:4937 // A list of ExtensionMenuItem's.
38 typedef std::vector<ExtensionMenuItem*> List;
[email protected]2e3b5202010-03-23 06:52:4139
[email protected]5a7b5eaf2010-11-02 20:52:1940 // An Id uniquely identifies a context menu item registered by an extension.
41 struct Id {
42 Id();
[email protected]3a1275d2011-03-28 18:49:5843 Id(Profile* profile, const std::string& extension_id, int uid);
[email protected]5a7b5eaf2010-11-02 20:52:1944 ~Id();
45
46 bool operator==(const Id& other) const;
47 bool operator!=(const Id& other) const;
48 bool operator<(const Id& other) const;
49
50 Profile* profile;
51 std::string extension_id;
52 int uid;
53 };
[email protected]9e9d7912010-07-18 21:05:2854
[email protected]a11fa342010-07-09 16:56:0055 // For context menus, these are the contexts where an item can appear.
[email protected]2e3b5202010-03-23 06:52:4156 enum Context {
57 ALL = 1,
58 PAGE = 2,
59 SELECTION = 4,
60 LINK = 8,
61 EDITABLE = 16,
62 IMAGE = 32,
63 VIDEO = 64,
64 AUDIO = 128,
[email protected]0e5e8d52011-04-06 21:02:5165 FRAME = 256,
[email protected]2e3b5202010-03-23 06:52:4166 };
67
68 // An item can be only one of these types.
69 enum Type {
70 NORMAL,
71 CHECKBOX,
72 RADIO,
73 SEPARATOR
74 };
75
[email protected]a11fa342010-07-09 16:56:0076 // A list of Contexts for an item.
[email protected]2e3b5202010-03-23 06:52:4177 class ContextList {
78 public:
79 ContextList() : value_(0) {}
80 explicit ContextList(Context context) : value_(context) {}
81 ContextList(const ContextList& other) : value_(other.value_) {}
82
83 void operator=(const ContextList& other) {
84 value_ = other.value_;
85 }
86
[email protected]66dbfb2c2010-05-12 20:20:1587 bool operator==(const ContextList& other) const {
88 return value_ == other.value_;
89 }
90
91 bool operator!=(const ContextList& other) const {
92 return !(*this == other);
93 }
94
[email protected]2e3b5202010-03-23 06:52:4195 bool Contains(Context context) const {
96 return (value_ & context) > 0;
97 }
98
99 void Add(Context context) {
100 value_ |= context;
101 }
102
103 private:
104 uint32 value_; // A bitmask of Context values.
105 };
106
[email protected]3a1275d2011-03-28 18:49:58107 ExtensionMenuItem(const Id& id,
108 const std::string& title,
109 bool checked,
[email protected]d4a8b7a2012-04-03 07:27:13110 bool enabled,
[email protected]3a1275d2011-03-28 18:49:58111 Type type,
[email protected]f4f04592010-07-14 20:40:13112 const ContextList& contexts);
[email protected]2e3b5202010-03-23 06:52:41113 virtual ~ExtensionMenuItem();
114
115 // Simple accessor methods.
[email protected]5a7b5eaf2010-11-02 20:52:19116 const std::string& extension_id() const { return id_.extension_id; }
[email protected]2e3b5202010-03-23 06:52:41117 const std::string& title() const { return title_; }
[email protected]63a414b52010-06-03 23:20:49118 const List& children() { return children_; }
[email protected]f4f04592010-07-14 20:40:13119 const Id& id() const { return id_; }
120 Id* parent_id() const { return parent_id_.get(); }
[email protected]2e3b5202010-03-23 06:52:41121 int child_count() const { return children_.size(); }
122 ContextList contexts() const { return contexts_; }
[email protected]2e3b5202010-03-23 06:52:41123 Type type() const { return type_; }
124 bool checked() const { return checked_; }
[email protected]d4a8b7a2012-04-03 07:27:13125 bool enabled() const { return enabled_; }
[email protected]cced75a2011-05-20 08:31:12126 const URLPatternSet& document_url_patterns() const {
[email protected]9e9d7912010-07-18 21:05:28127 return document_url_patterns_;
128 }
[email protected]cced75a2011-05-20 08:31:12129 const URLPatternSet& target_url_patterns() const {
[email protected]9e9d7912010-07-18 21:05:28130 return target_url_patterns_;
131 }
[email protected]2e3b5202010-03-23 06:52:41132
[email protected]66dbfb2c2010-05-12 20:20:15133 // Simple mutator methods.
[email protected]48329f92011-03-28 19:38:22134 void set_title(const std::string& new_title) { title_ = new_title; }
[email protected]66dbfb2c2010-05-12 20:20:15135 void set_contexts(ContextList contexts) { contexts_ = contexts; }
[email protected]66dbfb2c2010-05-12 20:20:15136 void set_type(Type type) { type_ = type; }
[email protected]d4a8b7a2012-04-03 07:27:13137 void set_enabled(bool enabled) { enabled_ = enabled; }
[email protected]cced75a2011-05-20 08:31:12138 void set_document_url_patterns(const URLPatternSet& patterns) {
[email protected]9e9d7912010-07-18 21:05:28139 document_url_patterns_ = patterns;
140 }
[email protected]cced75a2011-05-20 08:31:12141 void set_target_url_patterns(const URLPatternSet& patterns) {
[email protected]9e9d7912010-07-18 21:05:28142 target_url_patterns_ = patterns;
143 }
[email protected]66dbfb2c2010-05-12 20:20:15144
[email protected]745feedb2010-08-02 04:08:07145 // Returns the title with any instances of %s replaced by |selection|. The
146 // result will be no longer than |max_length|.
147 string16 TitleWithReplacement(const string16& selection,
148 size_t max_length) const;
[email protected]2e3b5202010-03-23 06:52:41149
[email protected]66dbfb2c2010-05-12 20:20:15150 // Set the checked state to |checked|. Returns true if successful.
151 bool SetChecked(bool checked);
152
[email protected]2e3b5202010-03-23 06:52:41153 protected:
154 friend class ExtensionMenuManager;
155
[email protected]2e3b5202010-03-23 06:52:41156 // Takes ownership of |item| and sets its parent_id_.
157 void AddChild(ExtensionMenuItem* item);
158
[email protected]66dbfb2c2010-05-12 20:20:15159 // Takes the child item from this parent. The item is returned and the caller
160 // then owns the pointer.
[email protected]f4f04592010-07-14 20:40:13161 ExtensionMenuItem* ReleaseChild(const Id& child_id, bool recursive);
[email protected]66dbfb2c2010-05-12 20:20:15162
163 // Recursively removes all descendant items (children, grandchildren, etc.),
164 // returning the ids of the removed items.
[email protected]f4f04592010-07-14 20:40:13165 std::set<Id> RemoveAllDescendants();
[email protected]66dbfb2c2010-05-12 20:20:15166
[email protected]2e3b5202010-03-23 06:52:41167 private:
[email protected]f4f04592010-07-14 20:40:13168 // The unique id for this item.
169 Id id_;
[email protected]2e3b5202010-03-23 06:52:41170
171 // What gets shown in the menu for this item.
172 std::string title_;
173
[email protected]2e3b5202010-03-23 06:52:41174 Type type_;
175
176 // This should only be true for items of type CHECKBOX or RADIO.
177 bool checked_;
178
[email protected]d4a8b7a2012-04-03 07:27:13179 // If the item is enabled or not.
180 bool enabled_;
181
[email protected]2e3b5202010-03-23 06:52:41182 // In what contexts should the item be shown?
183 ContextList contexts_;
184
[email protected]2e3b5202010-03-23 06:52:41185 // If this item is a child of another item, the unique id of its parent. If
[email protected]f4f04592010-07-14 20:40:13186 // this is a top-level item with no parent, this will be NULL.
187 scoped_ptr<Id> parent_id_;
[email protected]2e3b5202010-03-23 06:52:41188
[email protected]9e9d7912010-07-18 21:05:28189 // Patterns for restricting what documents this item will appear for. This
190 // applies to the frame where the click took place.
[email protected]cced75a2011-05-20 08:31:12191 URLPatternSet document_url_patterns_;
[email protected]9e9d7912010-07-18 21:05:28192
193 // Patterns for restricting where items appear based on the src/href
194 // attribute of IMAGE/AUDIO/VIDEO/LINK tags.
[email protected]cced75a2011-05-20 08:31:12195 URLPatternSet target_url_patterns_;
[email protected]9e9d7912010-07-18 21:05:28196
[email protected]2e3b5202010-03-23 06:52:41197 // Any children this item may have.
198 List children_;
199
200 DISALLOW_COPY_AND_ASSIGN(ExtensionMenuItem);
201};
202
203// This class keeps track of menu items added by extensions.
[email protected]6c2381d2011-10-19 02:52:53204class ExtensionMenuManager : public content::NotificationObserver {
[email protected]2e3b5202010-03-23 06:52:41205 public:
[email protected]8b280302011-10-13 22:22:23206 explicit ExtensionMenuManager(Profile* profile);
[email protected]2e3b5202010-03-23 06:52:41207 virtual ~ExtensionMenuManager();
208
209 // Returns the ids of extensions which have menu items registered.
210 std::set<std::string> ExtensionIds();
211
212 // Returns a list of all the *top-level* menu items (added via AddContextItem)
213 // for the given extension id, *not* including child items (added via
214 // AddChildItem); although those can be reached via the top-level items'
[email protected]63a414b52010-06-03 23:20:49215 // children. A view can then decide how to display these, including whether to
216 // put them into a submenu if there are more than 1.
217 const ExtensionMenuItem::List* MenuItems(const std::string& extension_id);
[email protected]2e3b5202010-03-23 06:52:41218
[email protected]052c92702010-06-25 07:25:52219 // Adds a top-level menu item for an extension, requiring the |extension|
220 // pointer so it can load the icon for the extension. Takes ownership of
[email protected]f4f04592010-07-14 20:40:13221 // |item|. Returns a boolean indicating success or failure.
[email protected]9adb9692010-10-29 23:14:02222 bool AddContextItem(const Extension* extension, ExtensionMenuItem* item);
[email protected]2e3b5202010-03-23 06:52:41223
224 // Add an item as a child of another item which has been previously added, and
[email protected]f4f04592010-07-14 20:40:13225 // takes ownership of |item|. Returns a boolean indicating success or failure.
226 bool AddChildItem(const ExtensionMenuItem::Id& parent_id,
227 ExtensionMenuItem* child);
[email protected]2e3b5202010-03-23 06:52:41228
[email protected]66dbfb2c2010-05-12 20:20:15229 // Makes existing item with |child_id| a child of the item with |parent_id|.
230 // If the child item was already a child of another parent, this will remove
231 // it from that parent first. It is an error to try and move an item to be a
[email protected]f4f04592010-07-14 20:40:13232 // child of one of its own descendants. It is legal to pass NULL for
233 // |parent_id|, which means the item should be moved to the top-level.
234 bool ChangeParent(const ExtensionMenuItem::Id& child_id,
235 const ExtensionMenuItem::Id* parent_id);
[email protected]66dbfb2c2010-05-12 20:20:15236
[email protected]2e3b5202010-03-23 06:52:41237 // Removes a context menu item with the given id (whether it is a top-level
238 // item or a child of some other item), returning true if the item was found
239 // and removed or false otherwise.
[email protected]f4f04592010-07-14 20:40:13240 bool RemoveContextMenuItem(const ExtensionMenuItem::Id& id);
[email protected]2e3b5202010-03-23 06:52:41241
[email protected]66dbfb2c2010-05-12 20:20:15242 // Removes all items for the given extension id.
[email protected]48329f92011-03-28 19:38:22243 void RemoveAllContextItems(const std::string& extension_id);
[email protected]66dbfb2c2010-05-12 20:20:15244
[email protected]2e3b5202010-03-23 06:52:41245 // Returns the item with the given |id| or NULL.
[email protected]f4f04592010-07-14 20:40:13246 ExtensionMenuItem* GetItemById(const ExtensionMenuItem::Id& id) const;
[email protected]2e3b5202010-03-23 06:52:41247
[email protected]7dddebc32012-01-11 22:01:03248 // Notify the ExtensionMenuManager that an item has been updated not through
249 // an explicit call into ExtensionMenuManager. For example, if an item is
250 // acquired by a call to GetItemById and changed, then this should be called.
251 // Returns true if the item was found or false otherwise.
252 bool ItemUpdated(const ExtensionMenuItem::Id& id);
253
[email protected]2e3b5202010-03-23 06:52:41254 // Called when a menu item is clicked on by the user.
[email protected]ea049a02011-12-25 21:37:09255 void ExecuteCommand(Profile* profile, content::WebContents* web_contents,
[email protected]35be7ec2012-02-12 20:42:51256 const content::ContextMenuParams& params,
[email protected]f4f04592010-07-14 20:40:13257 const ExtensionMenuItem::Id& menuItemId);
[email protected]2e3b5202010-03-23 06:52:41258
[email protected]f23a8c12011-03-15 14:43:43259 // This returns a bitmap of width/height kFaviconSize, loaded either from an
[email protected]052c92702010-06-25 07:25:52260 // entry specified in the extension's 'icon' section of the manifest, or a
261 // default extension icon.
262 const SkBitmap& GetIconForExtension(const std::string& extension_id);
263
[email protected]6c2381d2011-10-19 02:52:53264 // Implements the content::NotificationObserver interface.
265 virtual void Observe(int type, const content::NotificationSource& source,
266 const content::NotificationDetails& details) OVERRIDE;
[email protected]052c92702010-06-25 07:25:52267
[email protected]2e3b5202010-03-23 06:52:41268 private:
[email protected]2b07c93f2010-08-02 23:13:04269 FRIEND_TEST_ALL_PREFIXES(ExtensionMenuManagerTest, DeleteParent);
[email protected]f50da8592010-10-28 23:39:32270 FRIEND_TEST_ALL_PREFIXES(ExtensionMenuManagerTest, RemoveOneByOne);
[email protected]2b07c93f2010-08-02 23:13:04271
[email protected]2e3b5202010-03-23 06:52:41272 // This is a helper function which takes care of de-selecting any other radio
273 // items in the same group (i.e. that are adjacent in the list).
274 void RadioItemSelected(ExtensionMenuItem* item);
275
[email protected]7dddebc32012-01-11 22:01:03276 // Make sure that there is only one radio item selected at once in any run.
277 // If there are no radio items selected, then the first item in the run
278 // will get selected. If there are multiple radio items selected, then only
279 // the last one will get selcted.
280 void SanitizeRadioList(const ExtensionMenuItem::List& item_list);
281
[email protected]66dbfb2c2010-05-12 20:20:15282 // Returns true if item is a descendant of an item with id |ancestor_id|.
[email protected]f4f04592010-07-14 20:40:13283 bool DescendantOf(ExtensionMenuItem* item,
284 const ExtensionMenuItem::Id& ancestor_id);
[email protected]66dbfb2c2010-05-12 20:20:15285
[email protected]2e3b5202010-03-23 06:52:41286 // We keep items organized by mapping an extension id to a list of items.
287 typedef std::map<std::string, ExtensionMenuItem::List> MenuItemMap;
288 MenuItemMap context_items_;
289
290 // This lets us make lookup by id fast. It maps id to ExtensionMenuItem* for
291 // all items the menu manager knows about, including all children of top-level
292 // items.
[email protected]f4f04592010-07-14 20:40:13293 std::map<ExtensionMenuItem::Id, ExtensionMenuItem*> items_by_id_;
[email protected]2e3b5202010-03-23 06:52:41294
[email protected]6c2381d2011-10-19 02:52:53295 content::NotificationRegistrar registrar_;
[email protected]2e3b5202010-03-23 06:52:41296
[email protected]b671760b2010-07-15 21:13:47297 ExtensionIconManager icon_manager_;
[email protected]052c92702010-06-25 07:25:52298
[email protected]2e3b5202010-03-23 06:52:41299 DISALLOW_COPY_AND_ASSIGN(ExtensionMenuManager);
300};
301
302#endif // CHROME_BROWSER_EXTENSIONS_EXTENSION_MENU_MANAGER_H_