Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(306)

Side by Side Diff: chrome/browser/extensions/menu_manager.cc

Issue 10664037: Moved ExtensionMenuManager and ExtensionMenuItem into extensions namespace (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Merged with latest master Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 #include "chrome/browser/extensions/extension_menu_manager.h" 5 #include "chrome/browser/extensions/menu_manager.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/json/json_writer.h" 9 #include "base/json/json_writer.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/stl_util.h" 11 #include "base/stl_util.h"
12 #include "base/string_util.h" 12 #include "base/string_util.h"
13 #include "base/utf_string_conversions.h" 13 #include "base/utf_string_conversions.h"
14 #include "base/values.h" 14 #include "base/values.h"
15 #include "chrome/browser/extensions/extension_event_names.h" 15 #include "chrome/browser/extensions/extension_event_names.h"
16 #include "chrome/browser/extensions/extension_event_router.h" 16 #include "chrome/browser/extensions/extension_event_router.h"
17 #include "chrome/browser/extensions/extension_service.h" 17 #include "chrome/browser/extensions/extension_service.h"
18 #include "chrome/browser/extensions/extension_system.h" 18 #include "chrome/browser/extensions/extension_system.h"
19 #include "chrome/browser/extensions/extension_tab_helper.h" 19 #include "chrome/browser/extensions/extension_tab_helper.h"
20 #include "chrome/browser/extensions/extension_tab_util.h" 20 #include "chrome/browser/extensions/extension_tab_util.h"
21 #include "chrome/browser/extensions/state_store.h" 21 #include "chrome/browser/extensions/state_store.h"
22 #include "chrome/browser/profiles/profile.h" 22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/ui/tab_contents/tab_contents.h" 23 #include "chrome/browser/ui/tab_contents/tab_contents.h"
24 #include "chrome/common/chrome_notification_types.h" 24 #include "chrome/common/chrome_notification_types.h"
25 #include "chrome/common/extensions/extension.h" 25 #include "chrome/common/extensions/extension.h"
26 #include "content/public/browser/notification_details.h" 26 #include "content/public/browser/notification_details.h"
27 #include "content/public/browser/notification_source.h" 27 #include "content/public/browser/notification_source.h"
28 #include "content/public/browser/web_contents.h" 28 #include "content/public/browser/web_contents.h"
29 #include "content/public/common/context_menu_params.h" 29 #include "content/public/common/context_menu_params.h"
30 #include "ui/base/text/text_elider.h" 30 #include "ui/base/text/text_elider.h"
31 #include "ui/gfx/favicon_size.h" 31 #include "ui/gfx/favicon_size.h"
32 32
33 using content::WebContents; 33 using content::WebContents;
34 34
35 namespace extensions {
36
35 namespace { 37 namespace {
36 38
37 // Keys for serialization to and from Value to store in the preferences. 39 // Keys for serialization to and from Value to store in the preferences.
38 const char kContextMenusKey[] = "context_menus"; 40 const char kContextMenusKey[] = "context_menus";
39 41
40 const char kCheckedKey[] = "checked"; 42 const char kCheckedKey[] = "checked";
41 const char kContextsKey[] = "contexts"; 43 const char kContextsKey[] = "contexts";
42 const char kDocumentURLPatternsKey[] = "document_url_patterns"; 44 const char kDocumentURLPatternsKey[] = "document_url_patterns";
43 const char kEnabledKey[] = "enabled"; 45 const char kEnabledKey[] = "enabled";
44 const char kIncognitoKey[] = "incognito"; 46 const char kIncognitoKey[] = "incognito";
45 const char kParentUIDKey[] = "parent_uid"; 47 const char kParentUIDKey[] = "parent_uid";
46 const char kStringUIDKey[] = "string_uid"; 48 const char kStringUIDKey[] = "string_uid";
47 const char kTargetURLPatternsKey[] = "target_url_patterns"; 49 const char kTargetURLPatternsKey[] = "target_url_patterns";
48 const char kTitleKey[] = "title"; 50 const char kTitleKey[] = "title";
49 const char kTypeKey[] = "type"; 51 const char kTypeKey[] = "type";
50 52
51 void SetIdKeyValue(base::DictionaryValue* properties, 53 void SetIdKeyValue(base::DictionaryValue* properties,
52 const char* key, 54 const char* key,
53 const ExtensionMenuItem::Id& id) { 55 const MenuItem::Id& id) {
54 if (id.uid == 0) 56 if (id.uid == 0)
55 properties->SetString(key, id.string_uid); 57 properties->SetString(key, id.string_uid);
56 else 58 else
57 properties->SetInteger(key, id.uid); 59 properties->SetInteger(key, id.uid);
58 } 60 }
59 61
60 ExtensionMenuItem::List MenuItemsFromValue(const std::string& extension_id, 62 MenuItem::List MenuItemsFromValue(const std::string& extension_id,
61 base::Value* value) { 63 base::Value* value) {
62 ExtensionMenuItem::List items; 64 MenuItem::List items;
63 65
64 base::ListValue* list = NULL; 66 base::ListValue* list = NULL;
65 if (!value || !value->GetAsList(&list)) 67 if (!value || !value->GetAsList(&list))
66 return items; 68 return items;
67 69
68 for (size_t i = 0; i < list->GetSize(); ++i) { 70 for (size_t i = 0; i < list->GetSize(); ++i) {
69 base::DictionaryValue* dict = NULL; 71 base::DictionaryValue* dict = NULL;
70 if (!list->GetDictionary(i, &dict)) 72 if (!list->GetDictionary(i, &dict))
71 continue; 73 continue;
72 ExtensionMenuItem* item = ExtensionMenuItem::Populate( 74 MenuItem* item = MenuItem::Populate(
73 extension_id, *dict, NULL); 75 extension_id, *dict, NULL);
74 if (!item) 76 if (!item)
75 continue; 77 continue;
76 items.push_back(item); 78 items.push_back(item);
77 } 79 }
78 return items; 80 return items;
79 } 81 }
80 82
81 scoped_ptr<base::Value> MenuItemsToValue( 83 scoped_ptr<base::Value> MenuItemsToValue(const MenuItem::List& items) {
82 const ExtensionMenuItem::List& items) {
83 scoped_ptr<base::ListValue> list(new ListValue()); 84 scoped_ptr<base::ListValue> list(new ListValue());
84 for (size_t i = 0; i < items.size(); ++i) 85 for (size_t i = 0; i < items.size(); ++i)
85 list->Append(items[i]->ToValue().release()); 86 list->Append(items[i]->ToValue().release());
86 return scoped_ptr<Value>(list.release()); 87 return scoped_ptr<Value>(list.release());
87 } 88 }
88 89
89 } // namespace 90 } // namespace
90 91
91 ExtensionMenuItem::ExtensionMenuItem(const Id& id, 92 MenuItem::MenuItem(const Id& id,
92 const std::string& title, 93 const std::string& title,
93 bool checked, 94 bool checked,
94 bool enabled, 95 bool enabled,
95 Type type, 96 Type type,
96 const ContextList& contexts) 97 const ContextList& contexts)
97 : id_(id), 98 : id_(id),
98 title_(title), 99 title_(title),
99 type_(type), 100 type_(type),
100 checked_(checked), 101 checked_(checked),
101 enabled_(enabled), 102 enabled_(enabled),
102 contexts_(contexts), 103 contexts_(contexts),
103 parent_id_(0) { 104 parent_id_(0) {
104 } 105 }
105 106
106 ExtensionMenuItem::~ExtensionMenuItem() { 107 MenuItem::~MenuItem() {
107 STLDeleteElements(&children_); 108 STLDeleteElements(&children_);
108 } 109 }
109 110
110 ExtensionMenuItem* ExtensionMenuItem::ReleaseChild(const Id& child_id, 111 MenuItem* MenuItem::ReleaseChild(const Id& child_id,
111 bool recursive) { 112 bool recursive) {
112 for (List::iterator i = children_.begin(); i != children_.end(); ++i) { 113 for (List::iterator i = children_.begin(); i != children_.end(); ++i) {
113 ExtensionMenuItem* child = NULL; 114 MenuItem* child = NULL;
114 if ((*i)->id() == child_id) { 115 if ((*i)->id() == child_id) {
115 child = *i; 116 child = *i;
116 children_.erase(i); 117 children_.erase(i);
117 return child; 118 return child;
118 } else if (recursive) { 119 } else if (recursive) {
119 child = (*i)->ReleaseChild(child_id, recursive); 120 child = (*i)->ReleaseChild(child_id, recursive);
120 if (child) 121 if (child)
121 return child; 122 return child;
122 } 123 }
123 } 124 }
124 return NULL; 125 return NULL;
125 } 126 }
126 127
127 void ExtensionMenuItem::GetFlattenedSubtree(ExtensionMenuItem::List* list) { 128 void MenuItem::GetFlattenedSubtree(MenuItem::List* list) {
128 list->push_back(this); 129 list->push_back(this);
129 for (List::iterator i = children_.begin(); i != children_.end(); ++i) 130 for (List::iterator i = children_.begin(); i != children_.end(); ++i)
130 (*i)->GetFlattenedSubtree(list); 131 (*i)->GetFlattenedSubtree(list);
131 } 132 }
132 133
133 std::set<ExtensionMenuItem::Id> ExtensionMenuItem::RemoveAllDescendants() { 134 std::set<MenuItem::Id> MenuItem::RemoveAllDescendants() {
134 std::set<Id> result; 135 std::set<Id> result;
135 for (List::iterator i = children_.begin(); i != children_.end(); ++i) { 136 for (List::iterator i = children_.begin(); i != children_.end(); ++i) {
136 ExtensionMenuItem* child = *i; 137 MenuItem* child = *i;
137 result.insert(child->id()); 138 result.insert(child->id());
138 std::set<Id> removed = child->RemoveAllDescendants(); 139 std::set<Id> removed = child->RemoveAllDescendants();
139 result.insert(removed.begin(), removed.end()); 140 result.insert(removed.begin(), removed.end());
140 } 141 }
141 STLDeleteElements(&children_); 142 STLDeleteElements(&children_);
142 return result; 143 return result;
143 } 144 }
144 145
145 string16 ExtensionMenuItem::TitleWithReplacement( 146 string16 MenuItem::TitleWithReplacement(
146 const string16& selection, size_t max_length) const { 147 const string16& selection, size_t max_length) const {
147 string16 result = UTF8ToUTF16(title_); 148 string16 result = UTF8ToUTF16(title_);
148 // TODO(asargent) - Change this to properly handle %% escaping so you can 149 // TODO(asargent) - Change this to properly handle %% escaping so you can
149 // put "%s" in titles that won't get substituted. 150 // put "%s" in titles that won't get substituted.
150 ReplaceSubstringsAfterOffset(&result, 0, ASCIIToUTF16("%s"), selection); 151 ReplaceSubstringsAfterOffset(&result, 0, ASCIIToUTF16("%s"), selection);
151 152
152 if (result.length() > max_length) 153 if (result.length() > max_length)
153 result = ui::TruncateString(result, max_length); 154 result = ui::TruncateString(result, max_length);
154 return result; 155 return result;
155 } 156 }
156 157
157 bool ExtensionMenuItem::SetChecked(bool checked) { 158 bool MenuItem::SetChecked(bool checked) {
158 if (type_ != CHECKBOX && type_ != RADIO) 159 if (type_ != CHECKBOX && type_ != RADIO)
159 return false; 160 return false;
160 checked_ = checked; 161 checked_ = checked;
161 return true; 162 return true;
162 } 163 }
163 164
164 void ExtensionMenuItem::AddChild(ExtensionMenuItem* item) { 165 void MenuItem::AddChild(MenuItem* item) {
165 item->parent_id_.reset(new Id(id_)); 166 item->parent_id_.reset(new Id(id_));
166 children_.push_back(item); 167 children_.push_back(item);
167 } 168 }
168 169
169 scoped_ptr<DictionaryValue> ExtensionMenuItem::ToValue() const { 170 scoped_ptr<DictionaryValue> MenuItem::ToValue() const {
170 scoped_ptr<DictionaryValue> value(new DictionaryValue); 171 scoped_ptr<DictionaryValue> value(new DictionaryValue);
171 // Should only be called for extensions with event pages, which only have 172 // Should only be called for extensions with event pages, which only have
172 // string IDs for items. 173 // string IDs for items.
173 DCHECK_EQ(0, id_.uid); 174 DCHECK_EQ(0, id_.uid);
174 value->SetString(kStringUIDKey, id_.string_uid); 175 value->SetString(kStringUIDKey, id_.string_uid);
175 value->SetBoolean(kIncognitoKey, id_.incognito); 176 value->SetBoolean(kIncognitoKey, id_.incognito);
176 value->SetInteger(kTypeKey, type_); 177 value->SetInteger(kTypeKey, type_);
177 if (type_ != SEPARATOR) 178 if (type_ != SEPARATOR)
178 value->SetString(kTitleKey, title_); 179 value->SetString(kTitleKey, title_);
179 if (type_ == CHECKBOX || type_ == RADIO) 180 if (type_ == CHECKBOX || type_ == RADIO)
180 value->SetBoolean(kCheckedKey, checked_); 181 value->SetBoolean(kCheckedKey, checked_);
181 value->SetBoolean(kEnabledKey, enabled_); 182 value->SetBoolean(kEnabledKey, enabled_);
182 value->Set(kContextsKey, contexts_.ToValue().release()); 183 value->Set(kContextsKey, contexts_.ToValue().release());
183 if (parent_id_.get()) { 184 if (parent_id_.get()) {
184 DCHECK_EQ(0, parent_id_->uid); 185 DCHECK_EQ(0, parent_id_->uid);
185 value->SetString(kParentUIDKey, parent_id_->string_uid); 186 value->SetString(kParentUIDKey, parent_id_->string_uid);
186 } 187 }
187 value->Set(kDocumentURLPatternsKey, 188 value->Set(kDocumentURLPatternsKey,
188 document_url_patterns_.ToValue().release()); 189 document_url_patterns_.ToValue().release());
189 value->Set(kTargetURLPatternsKey, target_url_patterns_.ToValue().release()); 190 value->Set(kTargetURLPatternsKey, target_url_patterns_.ToValue().release());
190 return value.Pass(); 191 return value.Pass();
191 } 192 }
192 193
193 // static 194 // static
194 ExtensionMenuItem* ExtensionMenuItem::Populate(const std::string& extension_id, 195 MenuItem* MenuItem::Populate(const std::string& extension_id,
195 const DictionaryValue& value, 196 const DictionaryValue& value,
196 std::string* error) { 197 std::string* error) {
197 bool incognito = false; 198 bool incognito = false;
198 if (!value.GetBoolean(kIncognitoKey, &incognito)) 199 if (!value.GetBoolean(kIncognitoKey, &incognito))
199 return NULL; 200 return NULL;
200 Id id(incognito, extension_id); 201 Id id(incognito, extension_id);
201 if (!value.GetString(kStringUIDKey, &id.string_uid)) 202 if (!value.GetString(kStringUIDKey, &id.string_uid))
202 return NULL; 203 return NULL;
203 int type_int; 204 int type_int;
204 Type type; 205 Type type;
205 if (!value.GetInteger(kTypeKey, &type_int)) 206 if (!value.GetInteger(kTypeKey, &type_int))
206 return NULL; 207 return NULL;
207 type = static_cast<Type>(type_int); 208 type = static_cast<Type>(type_int);
208 std::string title; 209 std::string title;
209 if (type != SEPARATOR && !value.GetString(kTitleKey, &title)) 210 if (type != SEPARATOR && !value.GetString(kTitleKey, &title))
210 return NULL; 211 return NULL;
211 bool checked; 212 bool checked;
212 if ((type == CHECKBOX || type == RADIO) && 213 if ((type == CHECKBOX || type == RADIO) &&
213 !value.GetBoolean(kCheckedKey, &checked)) { 214 !value.GetBoolean(kCheckedKey, &checked)) {
214 return NULL; 215 return NULL;
215 } 216 }
216 bool enabled = true; 217 bool enabled = true;
217 if (!value.GetBoolean(kEnabledKey, &enabled)) 218 if (!value.GetBoolean(kEnabledKey, &enabled))
218 return NULL; 219 return NULL;
219 ContextList contexts; 220 ContextList contexts;
220 Value* contexts_value = NULL; 221 Value* contexts_value = NULL;
221 if (!value.Get(kContextsKey, &contexts_value)) 222 if (!value.Get(kContextsKey, &contexts_value))
222 return NULL; 223 return NULL;
223 if (!contexts.Populate(*contexts_value)) 224 if (!contexts.Populate(*contexts_value))
224 return NULL; 225 return NULL;
225 226
226 scoped_ptr<ExtensionMenuItem> result(new ExtensionMenuItem( 227 scoped_ptr<MenuItem> result(new MenuItem(
227 id, title, checked, enabled, type, contexts)); 228 id, title, checked, enabled, type, contexts));
228 229
229 if (!result->PopulateURLPatterns( 230 if (!result->PopulateURLPatterns(
230 value, kDocumentURLPatternsKey, kTargetURLPatternsKey, error)) 231 value, kDocumentURLPatternsKey, kTargetURLPatternsKey, error))
231 return NULL; 232 return NULL;
232 233
233 // parent_id is filled in from the value, but it might not be valid. It's left 234 // parent_id is filled in from the value, but it might not be valid. It's left
234 // to be validated upon being added (via AddChildItem) to the menu manager. 235 // to be validated upon being added (via AddChildItem) to the menu manager.
235 scoped_ptr<Id> parent_id(new Id(incognito, extension_id)); 236 scoped_ptr<Id> parent_id(new Id(incognito, extension_id));
236 if (value.HasKey(kParentUIDKey)) { 237 if (value.HasKey(kParentUIDKey)) {
237 if (!value.GetString(kParentUIDKey, &parent_id->string_uid)) 238 if (!value.GetString(kParentUIDKey, &parent_id->string_uid))
238 return NULL; 239 return NULL;
239 result->parent_id_.swap(parent_id); 240 result->parent_id_.swap(parent_id);
240 } 241 }
241 return result.release(); 242 return result.release();
242 } 243 }
243 244
244 bool ExtensionMenuItem::PopulateURLPatterns( 245 bool MenuItem::PopulateURLPatterns(const DictionaryValue& properties,
245 const DictionaryValue& properties, 246 const char* document_url_patterns_key,
246 const char* document_url_patterns_key, 247 const char* target_url_patterns_key,
247 const char* target_url_patterns_key, 248 std::string* error) {
248 std::string* error) {
249 if (properties.HasKey(document_url_patterns_key)) { 249 if (properties.HasKey(document_url_patterns_key)) {
250 ListValue* list = NULL; 250 ListValue* list = NULL;
251 if (!properties.GetList(document_url_patterns_key, &list)) 251 if (!properties.GetList(document_url_patterns_key, &list))
252 return false; 252 return false;
253 if (!document_url_patterns_.Populate( 253 if (!document_url_patterns_.Populate(
254 *list, URLPattern::SCHEME_ALL, true, error)) { 254 *list, URLPattern::SCHEME_ALL, true, error)) {
255 return false; 255 return false;
256 } 256 }
257 } 257 }
258 if (properties.HasKey(target_url_patterns_key)) { 258 if (properties.HasKey(target_url_patterns_key)) {
259 ListValue* list = NULL; 259 ListValue* list = NULL;
260 if (!properties.GetList(target_url_patterns_key, &list)) 260 if (!properties.GetList(target_url_patterns_key, &list))
261 return false; 261 return false;
262 if (!target_url_patterns_.Populate( 262 if (!target_url_patterns_.Populate(
263 *list, URLPattern::SCHEME_ALL, true, error)) { 263 *list, URLPattern::SCHEME_ALL, true, error)) {
264 return false; 264 return false;
265 } 265 }
266 } 266 }
267 return true; 267 return true;
268 } 268 }
269 269
270 ExtensionMenuManager::ExtensionMenuManager(Profile* profile) 270 MenuManager::MenuManager(Profile* profile)
271 : profile_(profile) { 271 : profile_(profile) {
272 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED, 272 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_LOADED,
273 content::Source<Profile>(profile)); 273 content::Source<Profile>(profile));
274 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 274 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED,
275 content::Source<Profile>(profile)); 275 content::Source<Profile>(profile));
276 276
277 extensions::StateStore* store = ExtensionSystem::Get(profile_)->state_store(); 277 StateStore* store = ExtensionSystem::Get(profile_)->state_store();
278 if (store) 278 if (store)
279 store->RegisterKey(kContextMenusKey); 279 store->RegisterKey(kContextMenusKey);
280 } 280 }
281 281
282 ExtensionMenuManager::~ExtensionMenuManager() { 282 MenuManager::~MenuManager() {
283 MenuItemMap::iterator i; 283 MenuItemMap::iterator i;
284 for (i = context_items_.begin(); i != context_items_.end(); ++i) { 284 for (i = context_items_.begin(); i != context_items_.end(); ++i) {
285 STLDeleteElements(&(i->second)); 285 STLDeleteElements(&(i->second));
286 } 286 }
287 } 287 }
288 288
289 std::set<std::string> ExtensionMenuManager::ExtensionIds() { 289 std::set<std::string> MenuManager::ExtensionIds() {
290 std::set<std::string> id_set; 290 std::set<std::string> id_set;
291 for (MenuItemMap::const_iterator i = context_items_.begin(); 291 for (MenuItemMap::const_iterator i = context_items_.begin();
292 i != context_items_.end(); ++i) { 292 i != context_items_.end(); ++i) {
293 id_set.insert(i->first); 293 id_set.insert(i->first);
294 } 294 }
295 return id_set; 295 return id_set;
296 } 296 }
297 297
298 const ExtensionMenuItem::List* ExtensionMenuManager::MenuItems( 298 const MenuItem::List* MenuManager::MenuItems(
299 const std::string& extension_id) { 299 const std::string& extension_id) {
300 MenuItemMap::iterator i = context_items_.find(extension_id); 300 MenuItemMap::iterator i = context_items_.find(extension_id);
301 if (i != context_items_.end()) { 301 if (i != context_items_.end()) {
302 return &(i->second); 302 return &(i->second);
303 } 303 }
304 return NULL; 304 return NULL;
305 } 305 }
306 306
307 bool ExtensionMenuManager::AddContextItem( 307 bool MenuManager::AddContextItem(
308 const extensions::Extension* extension, 308 const Extension* extension,
309 ExtensionMenuItem* item) { 309 MenuItem* item) {
310 const std::string& extension_id = item->extension_id(); 310 const std::string& extension_id = item->extension_id();
311 // The item must have a non-empty extension id, and not have already been 311 // The item must have a non-empty extension id, and not have already been
312 // added. 312 // added.
313 if (extension_id.empty() || ContainsKey(items_by_id_, item->id())) 313 if (extension_id.empty() || ContainsKey(items_by_id_, item->id()))
314 return false; 314 return false;
315 315
316 DCHECK_EQ(extension->id(), extension_id); 316 DCHECK_EQ(extension->id(), extension_id);
317 317
318 bool first_item = !ContainsKey(context_items_, extension_id); 318 bool first_item = !ContainsKey(context_items_, extension_id);
319 context_items_[extension_id].push_back(item); 319 context_items_[extension_id].push_back(item);
320 items_by_id_[item->id()] = item; 320 items_by_id_[item->id()] = item;
321 321
322 if (item->type() == ExtensionMenuItem::RADIO) { 322 if (item->type() == MenuItem::RADIO) {
323 if (item->checked()) 323 if (item->checked())
324 RadioItemSelected(item); 324 RadioItemSelected(item);
325 else 325 else
326 SanitizeRadioList(context_items_[extension_id]); 326 SanitizeRadioList(context_items_[extension_id]);
327 } 327 }
328 328
329 // If this is the first item for this extension, start loading its icon. 329 // If this is the first item for this extension, start loading its icon.
330 if (first_item) 330 if (first_item)
331 icon_manager_.LoadIcon(extension); 331 icon_manager_.LoadIcon(extension);
332 332
333 return true; 333 return true;
334 } 334 }
335 335
336 bool ExtensionMenuManager::AddChildItem(const ExtensionMenuItem::Id& parent_id, 336 bool MenuManager::AddChildItem(const MenuItem::Id& parent_id,
337 ExtensionMenuItem* child) { 337 MenuItem* child) {
338 ExtensionMenuItem* parent = GetItemById(parent_id); 338 MenuItem* parent = GetItemById(parent_id);
339 if (!parent || parent->type() != ExtensionMenuItem::NORMAL || 339 if (!parent || parent->type() != MenuItem::NORMAL ||
340 parent->incognito() != child->incognito() || 340 parent->incognito() != child->incognito() ||
341 parent->extension_id() != child->extension_id() || 341 parent->extension_id() != child->extension_id() ||
342 ContainsKey(items_by_id_, child->id())) 342 ContainsKey(items_by_id_, child->id()))
343 return false; 343 return false;
344 parent->AddChild(child); 344 parent->AddChild(child);
345 items_by_id_[child->id()] = child; 345 items_by_id_[child->id()] = child;
346 346
347 if (child->type() == ExtensionMenuItem::RADIO) 347 if (child->type() == MenuItem::RADIO)
348 SanitizeRadioList(parent->children()); 348 SanitizeRadioList(parent->children());
349 return true; 349 return true;
350 } 350 }
351 351
352 bool ExtensionMenuManager::DescendantOf( 352 bool MenuManager::DescendantOf(MenuItem* item,
353 ExtensionMenuItem* item, 353 const MenuItem::Id& ancestor_id) {
354 const ExtensionMenuItem::Id& ancestor_id) {
355 // Work our way up the tree until we find the ancestor or NULL. 354 // Work our way up the tree until we find the ancestor or NULL.
356 ExtensionMenuItem::Id* id = item->parent_id(); 355 MenuItem::Id* id = item->parent_id();
357 while (id != NULL) { 356 while (id != NULL) {
358 DCHECK(*id != item->id()); // Catch circular graphs. 357 DCHECK(*id != item->id()); // Catch circular graphs.
359 if (*id == ancestor_id) 358 if (*id == ancestor_id)
360 return true; 359 return true;
361 ExtensionMenuItem* next = GetItemById(*id); 360 MenuItem* next = GetItemById(*id);
362 if (!next) { 361 if (!next) {
363 NOTREACHED(); 362 NOTREACHED();
364 return false; 363 return false;
365 } 364 }
366 id = next->parent_id(); 365 id = next->parent_id();
367 } 366 }
368 return false; 367 return false;
369 } 368 }
370 369
371 bool ExtensionMenuManager::ChangeParent( 370 bool MenuManager::ChangeParent(const MenuItem::Id& child_id,
372 const ExtensionMenuItem::Id& child_id, 371 const MenuItem::Id* parent_id) {
373 const ExtensionMenuItem::Id* parent_id) { 372 MenuItem* child = GetItemById(child_id);
374 ExtensionMenuItem* child = GetItemById(child_id); 373 MenuItem* new_parent = parent_id ? GetItemById(*parent_id) : NULL;
375 ExtensionMenuItem* new_parent = parent_id ? GetItemById(*parent_id) : NULL;
376 if ((parent_id && (child_id == *parent_id)) || !child || 374 if ((parent_id && (child_id == *parent_id)) || !child ||
377 (!new_parent && parent_id != NULL) || 375 (!new_parent && parent_id != NULL) ||
378 (new_parent && (DescendantOf(new_parent, child_id) || 376 (new_parent && (DescendantOf(new_parent, child_id) ||
379 child->incognito() != new_parent->incognito() || 377 child->incognito() != new_parent->incognito() ||
380 child->extension_id() != new_parent->extension_id()))) 378 child->extension_id() != new_parent->extension_id())))
381 return false; 379 return false;
382 380
383 ExtensionMenuItem::Id* old_parent_id = child->parent_id(); 381 MenuItem::Id* old_parent_id = child->parent_id();
384 if (old_parent_id != NULL) { 382 if (old_parent_id != NULL) {
385 ExtensionMenuItem* old_parent = GetItemById(*old_parent_id); 383 MenuItem* old_parent = GetItemById(*old_parent_id);
386 if (!old_parent) { 384 if (!old_parent) {
387 NOTREACHED(); 385 NOTREACHED();
388 return false; 386 return false;
389 } 387 }
390 ExtensionMenuItem* taken = 388 MenuItem* taken =
391 old_parent->ReleaseChild(child_id, false /* non-recursive search*/); 389 old_parent->ReleaseChild(child_id, false /* non-recursive search*/);
392 DCHECK(taken == child); 390 DCHECK(taken == child);
393 SanitizeRadioList(old_parent->children()); 391 SanitizeRadioList(old_parent->children());
394 } else { 392 } else {
395 // This is a top-level item, so we need to pull it out of our list of 393 // This is a top-level item, so we need to pull it out of our list of
396 // top-level items. 394 // top-level items.
397 MenuItemMap::iterator i = context_items_.find(child->extension_id()); 395 MenuItemMap::iterator i = context_items_.find(child->extension_id());
398 if (i == context_items_.end()) { 396 if (i == context_items_.end()) {
399 NOTREACHED(); 397 NOTREACHED();
400 return false; 398 return false;
401 } 399 }
402 ExtensionMenuItem::List& list = i->second; 400 MenuItem::List& list = i->second;
403 ExtensionMenuItem::List::iterator j = std::find(list.begin(), list.end(), 401 MenuItem::List::iterator j = std::find(list.begin(), list.end(),
404 child); 402 child);
405 if (j == list.end()) { 403 if (j == list.end()) {
406 NOTREACHED(); 404 NOTREACHED();
407 return false; 405 return false;
408 } 406 }
409 list.erase(j); 407 list.erase(j);
410 SanitizeRadioList(list); 408 SanitizeRadioList(list);
411 } 409 }
412 410
413 if (new_parent) { 411 if (new_parent) {
414 new_parent->AddChild(child); 412 new_parent->AddChild(child);
415 SanitizeRadioList(new_parent->children()); 413 SanitizeRadioList(new_parent->children());
416 } else { 414 } else {
417 context_items_[child->extension_id()].push_back(child); 415 context_items_[child->extension_id()].push_back(child);
418 child->parent_id_.reset(NULL); 416 child->parent_id_.reset(NULL);
419 SanitizeRadioList(context_items_[child->extension_id()]); 417 SanitizeRadioList(context_items_[child->extension_id()]);
420 } 418 }
421 return true; 419 return true;
422 } 420 }
423 421
424 bool ExtensionMenuManager::RemoveContextMenuItem( 422 bool MenuManager::RemoveContextMenuItem(const MenuItem::Id& id) {
425 const ExtensionMenuItem::Id& id) {
426 if (!ContainsKey(items_by_id_, id)) 423 if (!ContainsKey(items_by_id_, id))
427 return false; 424 return false;
428 425
429 ExtensionMenuItem* menu_item = GetItemById(id); 426 MenuItem* menu_item = GetItemById(id);
430 DCHECK(menu_item); 427 DCHECK(menu_item);
431 std::string extension_id = menu_item->extension_id(); 428 std::string extension_id = menu_item->extension_id();
432 MenuItemMap::iterator i = context_items_.find(extension_id); 429 MenuItemMap::iterator i = context_items_.find(extension_id);
433 if (i == context_items_.end()) { 430 if (i == context_items_.end()) {
434 NOTREACHED(); 431 NOTREACHED();
435 return false; 432 return false;
436 } 433 }
437 434
438 bool result = false; 435 bool result = false;
439 std::set<ExtensionMenuItem::Id> items_removed; 436 std::set<MenuItem::Id> items_removed;
440 ExtensionMenuItem::List& list = i->second; 437 MenuItem::List& list = i->second;
441 ExtensionMenuItem::List::iterator j; 438 MenuItem::List::iterator j;
442 for (j = list.begin(); j < list.end(); ++j) { 439 for (j = list.begin(); j < list.end(); ++j) {
443 // See if the current top-level item is a match. 440 // See if the current top-level item is a match.
444 if ((*j)->id() == id) { 441 if ((*j)->id() == id) {
445 items_removed = (*j)->RemoveAllDescendants(); 442 items_removed = (*j)->RemoveAllDescendants();
446 items_removed.insert(id); 443 items_removed.insert(id);
447 delete *j; 444 delete *j;
448 list.erase(j); 445 list.erase(j);
449 result = true; 446 result = true;
450 SanitizeRadioList(list); 447 SanitizeRadioList(list);
451 break; 448 break;
452 } else { 449 } else {
453 // See if the item to remove was found as a descendant of the current 450 // See if the item to remove was found as a descendant of the current
454 // top-level item. 451 // top-level item.
455 ExtensionMenuItem* child = (*j)->ReleaseChild(id, true /* recursive */); 452 MenuItem* child = (*j)->ReleaseChild(id, true /* recursive */);
456 if (child) { 453 if (child) {
457 items_removed = child->RemoveAllDescendants(); 454 items_removed = child->RemoveAllDescendants();
458 items_removed.insert(id); 455 items_removed.insert(id);
459 SanitizeRadioList(GetItemById(*child->parent_id())->children()); 456 SanitizeRadioList(GetItemById(*child->parent_id())->children());
460 delete child; 457 delete child;
461 result = true; 458 result = true;
462 break; 459 break;
463 } 460 }
464 } 461 }
465 } 462 }
466 DCHECK(result); // The check at the very top should have prevented this. 463 DCHECK(result); // The check at the very top should have prevented this.
467 464
468 // Clear entries from the items_by_id_ map. 465 // Clear entries from the items_by_id_ map.
469 std::set<ExtensionMenuItem::Id>::iterator removed_iter; 466 std::set<MenuItem::Id>::iterator removed_iter;
470 for (removed_iter = items_removed.begin(); 467 for (removed_iter = items_removed.begin();
471 removed_iter != items_removed.end(); 468 removed_iter != items_removed.end();
472 ++removed_iter) { 469 ++removed_iter) {
473 items_by_id_.erase(*removed_iter); 470 items_by_id_.erase(*removed_iter);
474 } 471 }
475 472
476 if (list.empty()) { 473 if (list.empty()) {
477 context_items_.erase(extension_id); 474 context_items_.erase(extension_id);
478 icon_manager_.RemoveIcon(extension_id); 475 icon_manager_.RemoveIcon(extension_id);
479 } 476 }
480 return result; 477 return result;
481 } 478 }
482 479
483 void ExtensionMenuManager::RemoveAllContextItems( 480 void MenuManager::RemoveAllContextItems(const std::string& extension_id) {
484 const std::string& extension_id) { 481 MenuItem::List::iterator i;
485 ExtensionMenuItem::List::iterator i;
486 for (i = context_items_[extension_id].begin(); 482 for (i = context_items_[extension_id].begin();
487 i != context_items_[extension_id].end(); ++i) { 483 i != context_items_[extension_id].end(); ++i) {
488 ExtensionMenuItem* item = *i; 484 MenuItem* item = *i;
489 items_by_id_.erase(item->id()); 485 items_by_id_.erase(item->id());
490 486
491 // Remove descendants from this item and erase them from the lookup cache. 487 // Remove descendants from this item and erase them from the lookup cache.
492 std::set<ExtensionMenuItem::Id> removed_ids = item->RemoveAllDescendants(); 488 std::set<MenuItem::Id> removed_ids = item->RemoveAllDescendants();
493 std::set<ExtensionMenuItem::Id>::const_iterator j; 489 std::set<MenuItem::Id>::const_iterator j;
494 for (j = removed_ids.begin(); j != removed_ids.end(); ++j) { 490 for (j = removed_ids.begin(); j != removed_ids.end(); ++j) {
495 items_by_id_.erase(*j); 491 items_by_id_.erase(*j);
496 } 492 }
497 } 493 }
498 STLDeleteElements(&context_items_[extension_id]); 494 STLDeleteElements(&context_items_[extension_id]);
499 context_items_.erase(extension_id); 495 context_items_.erase(extension_id);
500 icon_manager_.RemoveIcon(extension_id); 496 icon_manager_.RemoveIcon(extension_id);
501 } 497 }
502 498
503 ExtensionMenuItem* ExtensionMenuManager::GetItemById( 499 MenuItem* MenuManager::GetItemById(const MenuItem::Id& id) const {
504 const ExtensionMenuItem::Id& id) const { 500 std::map<MenuItem::Id, MenuItem*>::const_iterator i =
505 std::map<ExtensionMenuItem::Id, ExtensionMenuItem*>::const_iterator i =
506 items_by_id_.find(id); 501 items_by_id_.find(id);
507 if (i != items_by_id_.end()) 502 if (i != items_by_id_.end())
508 return i->second; 503 return i->second;
509 else 504 else
510 return NULL; 505 return NULL;
511 } 506 }
512 507
513 void ExtensionMenuManager::RadioItemSelected(ExtensionMenuItem* item) { 508 void MenuManager::RadioItemSelected(MenuItem* item) {
514 // If this is a child item, we need to get a handle to the list from its 509 // If this is a child item, we need to get a handle to the list from its
515 // parent. Otherwise get a handle to the top-level list. 510 // parent. Otherwise get a handle to the top-level list.
516 const ExtensionMenuItem::List* list = NULL; 511 const MenuItem::List* list = NULL;
517 if (item->parent_id()) { 512 if (item->parent_id()) {
518 ExtensionMenuItem* parent = GetItemById(*item->parent_id()); 513 MenuItem* parent = GetItemById(*item->parent_id());
519 if (!parent) { 514 if (!parent) {
520 NOTREACHED(); 515 NOTREACHED();
521 return; 516 return;
522 } 517 }
523 list = &(parent->children()); 518 list = &(parent->children());
524 } else { 519 } else {
525 if (context_items_.find(item->extension_id()) == context_items_.end()) { 520 if (context_items_.find(item->extension_id()) == context_items_.end()) {
526 NOTREACHED(); 521 NOTREACHED();
527 return; 522 return;
528 } 523 }
529 list = &context_items_[item->extension_id()]; 524 list = &context_items_[item->extension_id()];
530 } 525 }
531 526
532 // Find where |item| is in the list. 527 // Find where |item| is in the list.
533 ExtensionMenuItem::List::const_iterator item_location; 528 MenuItem::List::const_iterator item_location;
534 for (item_location = list->begin(); item_location != list->end(); 529 for (item_location = list->begin(); item_location != list->end();
535 ++item_location) { 530 ++item_location) {
536 if (*item_location == item) 531 if (*item_location == item)
537 break; 532 break;
538 } 533 }
539 if (item_location == list->end()) { 534 if (item_location == list->end()) {
540 NOTREACHED(); // We should have found the item. 535 NOTREACHED(); // We should have found the item.
541 return; 536 return;
542 } 537 }
543 538
544 // Iterate backwards from |item| and uncheck any adjacent radio items. 539 // Iterate backwards from |item| and uncheck any adjacent radio items.
545 ExtensionMenuItem::List::const_iterator i; 540 MenuItem::List::const_iterator i;
546 if (item_location != list->begin()) { 541 if (item_location != list->begin()) {
547 i = item_location; 542 i = item_location;
548 do { 543 do {
549 --i; 544 --i;
550 if ((*i)->type() != ExtensionMenuItem::RADIO) 545 if ((*i)->type() != MenuItem::RADIO)
551 break; 546 break;
552 (*i)->SetChecked(false); 547 (*i)->SetChecked(false);
553 } while (i != list->begin()); 548 } while (i != list->begin());
554 } 549 }
555 550
556 // Now iterate forwards from |item| and uncheck any adjacent radio items. 551 // Now iterate forwards from |item| and uncheck any adjacent radio items.
557 for (i = item_location + 1; i != list->end(); ++i) { 552 for (i = item_location + 1; i != list->end(); ++i) {
558 if ((*i)->type() != ExtensionMenuItem::RADIO) 553 if ((*i)->type() != MenuItem::RADIO)
559 break; 554 break;
560 (*i)->SetChecked(false); 555 (*i)->SetChecked(false);
561 } 556 }
562 } 557 }
563 558
564 static void AddURLProperty(DictionaryValue* dictionary, 559 static void AddURLProperty(DictionaryValue* dictionary,
565 const std::string& key, const GURL& url) { 560 const std::string& key, const GURL& url) {
566 if (!url.is_empty()) 561 if (!url.is_empty())
567 dictionary->SetString(key, url.possibly_invalid_spec()); 562 dictionary->SetString(key, url.possibly_invalid_spec());
568 } 563 }
569 564
570 void ExtensionMenuManager::ExecuteCommand( 565 void MenuManager::ExecuteCommand(Profile* profile,
571 Profile* profile, 566 WebContents* web_contents,
572 WebContents* web_contents, 567 const content::ContextMenuParams& params,
573 const content::ContextMenuParams& params, 568 const MenuItem::Id& menu_item_id) {
574 const ExtensionMenuItem::Id& menu_item_id) {
575 ExtensionEventRouter* event_router = profile->GetExtensionEventRouter(); 569 ExtensionEventRouter* event_router = profile->GetExtensionEventRouter();
576 if (!event_router) 570 if (!event_router)
577 return; 571 return;
578 572
579 ExtensionMenuItem* item = GetItemById(menu_item_id); 573 MenuItem* item = GetItemById(menu_item_id);
580 if (!item) 574 if (!item)
581 return; 575 return;
582 576
583 // ExtensionService/Extension can be NULL in unit tests :( 577 // ExtensionService/Extension can be NULL in unit tests :(
584 ExtensionService* service = 578 ExtensionService* service =
585 ExtensionSystem::Get(profile_)->extension_service(); 579 ExtensionSystem::Get(profile_)->extension_service();
586 const extensions::Extension* extension = service ? 580 const Extension* extension = service ?
587 service->extensions()->GetByID(menu_item_id.extension_id) : NULL; 581 service->extensions()->GetByID(menu_item_id.extension_id) : NULL;
588 582
589 if (item->type() == ExtensionMenuItem::RADIO) 583 if (item->type() == MenuItem::RADIO)
590 RadioItemSelected(item); 584 RadioItemSelected(item);
591 585
592 ListValue args; 586 ListValue args;
593 587
594 DictionaryValue* properties = new DictionaryValue(); 588 DictionaryValue* properties = new DictionaryValue();
595 SetIdKeyValue(properties, "menuItemId", item->id()); 589 SetIdKeyValue(properties, "menuItemId", item->id());
596 if (item->parent_id()) 590 if (item->parent_id())
597 SetIdKeyValue(properties, "parentMenuItemId", item->id()); 591 SetIdKeyValue(properties, "parentMenuItemId", item->id());
598 592
599 switch (params.media_type) { 593 switch (params.media_type) {
(...skipping 21 matching lines...) Expand all
621 615
622 args.Append(properties); 616 args.Append(properties);
623 617
624 // Add the tab info to the argument list. 618 // Add the tab info to the argument list.
625 // Note: web_contents only NULL in unit tests :( 619 // Note: web_contents only NULL in unit tests :(
626 if (web_contents) 620 if (web_contents)
627 args.Append(ExtensionTabUtil::CreateTabValue(web_contents)); 621 args.Append(ExtensionTabUtil::CreateTabValue(web_contents));
628 else 622 else
629 args.Append(new DictionaryValue()); 623 args.Append(new DictionaryValue());
630 624
631 if (item->type() == ExtensionMenuItem::CHECKBOX || 625 if (item->type() == MenuItem::CHECKBOX ||
632 item->type() == ExtensionMenuItem::RADIO) { 626 item->type() == MenuItem::RADIO) {
633 bool was_checked = item->checked(); 627 bool was_checked = item->checked();
634 properties->SetBoolean("wasChecked", was_checked); 628 properties->SetBoolean("wasChecked", was_checked);
635 629
636 // RADIO items always get set to true when you click on them, but CHECKBOX 630 // RADIO items always get set to true when you click on them, but CHECKBOX
637 // items get their state toggled. 631 // items get their state toggled.
638 bool checked = 632 bool checked =
639 (item->type() == ExtensionMenuItem::RADIO) ? true : !was_checked; 633 (item->type() == MenuItem::RADIO) ? true : !was_checked;
640 634
641 item->SetChecked(checked); 635 item->SetChecked(checked);
642 properties->SetBoolean("checked", item->checked()); 636 properties->SetBoolean("checked", item->checked());
643 637
644 if (extension) 638 if (extension)
645 WriteToStorage(extension); 639 WriteToStorage(extension);
646 } 640 }
647 641
648 TabContents* tab_contents = web_contents ? 642 TabContents* tab_contents = web_contents ?
649 TabContents::FromWebContents(web_contents) : NULL; 643 TabContents::FromWebContents(web_contents) : NULL;
650 if (tab_contents && extension) { 644 if (tab_contents && extension) {
651 tab_contents->extension_tab_helper()->active_tab_permission_manager()-> 645 tab_contents->extension_tab_helper()->active_tab_permission_manager()->
652 GrantIfRequested(extension); 646 GrantIfRequested(extension);
653 } 647 }
654 648
655 std::string json_args; 649 std::string json_args;
656 base::JSONWriter::Write(&args, &json_args); 650 base::JSONWriter::Write(&args, &json_args);
657 event_router->DispatchEventToExtension( 651 event_router->DispatchEventToExtension(
658 item->extension_id(), extension_event_names::kOnContextMenus, 652 item->extension_id(), extension_event_names::kOnContextMenus,
659 json_args, profile, GURL(), 653 json_args, profile, GURL(),
660 ExtensionEventRouter::USER_GESTURE_ENABLED); 654 ExtensionEventRouter::USER_GESTURE_ENABLED);
661 event_router->DispatchEventToExtension( 655 event_router->DispatchEventToExtension(
662 item->extension_id(), extension_event_names::kOnContextMenuClicked, 656 item->extension_id(), extension_event_names::kOnContextMenuClicked,
663 json_args, profile, GURL(), 657 json_args, profile, GURL(),
664 ExtensionEventRouter::USER_GESTURE_ENABLED); 658 ExtensionEventRouter::USER_GESTURE_ENABLED);
665 } 659 }
666 660
667 void ExtensionMenuManager::SanitizeRadioList( 661 void MenuManager::SanitizeRadioList(const MenuItem::List& item_list) {
668 const ExtensionMenuItem::List& item_list) { 662 MenuItem::List::const_iterator i = item_list.begin();
669 ExtensionMenuItem::List::const_iterator i = item_list.begin();
670 while (i != item_list.end()) { 663 while (i != item_list.end()) {
671 if ((*i)->type() != ExtensionMenuItem::RADIO) { 664 if ((*i)->type() != MenuItem::RADIO) {
672 ++i; 665 ++i;
673 break; 666 break;
674 } 667 }
675 668
676 // Uncheck any checked radio items in the run, and at the end reset 669 // Uncheck any checked radio items in the run, and at the end reset
677 // the appropriate one to checked. If no check radio items were found, 670 // the appropriate one to checked. If no check radio items were found,
678 // then check the first radio item in the run. 671 // then check the first radio item in the run.
679 ExtensionMenuItem::List::const_iterator last_checked = item_list.end(); 672 MenuItem::List::const_iterator last_checked = item_list.end();
680 ExtensionMenuItem::List::const_iterator radio_run_iter; 673 MenuItem::List::const_iterator radio_run_iter;
681 for (radio_run_iter = i; radio_run_iter != item_list.end(); 674 for (radio_run_iter = i; radio_run_iter != item_list.end();
682 ++radio_run_iter) { 675 ++radio_run_iter) {
683 if ((*radio_run_iter)->type() != ExtensionMenuItem::RADIO) { 676 if ((*radio_run_iter)->type() != MenuItem::RADIO) {
684 break; 677 break;
685 } 678 }
686 679
687 if ((*radio_run_iter)->checked()) { 680 if ((*radio_run_iter)->checked()) {
688 last_checked = radio_run_iter; 681 last_checked = radio_run_iter;
689 (*radio_run_iter)->SetChecked(false); 682 (*radio_run_iter)->SetChecked(false);
690 } 683 }
691 } 684 }
692 685
693 if (last_checked != item_list.end()) 686 if (last_checked != item_list.end())
694 (*last_checked)->SetChecked(true); 687 (*last_checked)->SetChecked(true);
695 else 688 else
696 (*i)->SetChecked(true); 689 (*i)->SetChecked(true);
697 690
698 i = radio_run_iter; 691 i = radio_run_iter;
699 } 692 }
700 } 693 }
701 694
702 bool ExtensionMenuManager::ItemUpdated(const ExtensionMenuItem::Id& id) { 695 bool MenuManager::ItemUpdated(const MenuItem::Id& id) {
703 if (!ContainsKey(items_by_id_, id)) 696 if (!ContainsKey(items_by_id_, id))
704 return false; 697 return false;
705 698
706 ExtensionMenuItem* menu_item = GetItemById(id); 699 MenuItem* menu_item = GetItemById(id);
707 DCHECK(menu_item); 700 DCHECK(menu_item);
708 701
709 if (menu_item->parent_id()) { 702 if (menu_item->parent_id()) {
710 SanitizeRadioList(GetItemById(*menu_item->parent_id())->children()); 703 SanitizeRadioList(GetItemById(*menu_item->parent_id())->children());
711 } else { 704 } else {
712 std::string extension_id = menu_item->extension_id(); 705 std::string extension_id = menu_item->extension_id();
713 MenuItemMap::iterator i = context_items_.find(extension_id); 706 MenuItemMap::iterator i = context_items_.find(extension_id);
714 if (i == context_items_.end()) { 707 if (i == context_items_.end()) {
715 NOTREACHED(); 708 NOTREACHED();
716 return false; 709 return false;
717 } 710 }
718 SanitizeRadioList(i->second); 711 SanitizeRadioList(i->second);
719 } 712 }
720 713
721 return true; 714 return true;
722 } 715 }
723 716
724 void ExtensionMenuManager::WriteToStorage( 717 void MenuManager::WriteToStorage(const Extension* extension) {
725 const extensions::Extension* extension) {
726 if (!extension->has_lazy_background_page()) 718 if (!extension->has_lazy_background_page())
727 return; 719 return;
728 const ExtensionMenuItem::List* top_items = MenuItems(extension->id()); 720 const MenuItem::List* top_items = MenuItems(extension->id());
729 ExtensionMenuItem::List all_items; 721 MenuItem::List all_items;
730 if (top_items) { 722 if (top_items) {
731 for (ExtensionMenuItem::List::const_iterator i = top_items->begin(); 723 for (MenuItem::List::const_iterator i = top_items->begin();
732 i != top_items->end(); ++i) { 724 i != top_items->end(); ++i) {
733 (*i)->GetFlattenedSubtree(&all_items); 725 (*i)->GetFlattenedSubtree(&all_items);
734 } 726 }
735 } 727 }
736 728
737 extensions::StateStore* store = ExtensionSystem::Get(profile_)->state_store(); 729 StateStore* store = ExtensionSystem::Get(profile_)->state_store();
738 if (store) 730 if (store)
739 store->SetExtensionValue(extension->id(), kContextMenusKey, 731 store->SetExtensionValue(extension->id(), kContextMenusKey,
740 MenuItemsToValue(all_items)); 732 MenuItemsToValue(all_items));
741 } 733 }
742 734
743 void ExtensionMenuManager::ReadFromStorage(const std::string& extension_id, 735 void MenuManager::ReadFromStorage(const std::string& extension_id,
744 scoped_ptr<base::Value> value) { 736 scoped_ptr<base::Value> value) {
745 const extensions::Extension* extension = 737 const Extension* extension =
746 ExtensionSystem::Get(profile_)->extension_service()->extensions()-> 738 ExtensionSystem::Get(profile_)->extension_service()->extensions()->
747 GetByID(extension_id); 739 GetByID(extension_id);
748 if (!extension) 740 if (!extension)
749 return; 741 return;
750 742
751 ExtensionMenuItem::List items = MenuItemsFromValue(extension_id, value.get()); 743 MenuItem::List items = MenuItemsFromValue(extension_id, value.get());
752 for (size_t i = 0; i < items.size(); ++i) { 744 for (size_t i = 0; i < items.size(); ++i) {
753 if (items[i]->parent_id()) { 745 if (items[i]->parent_id()) {
754 // Parent IDs are stored in the parent_id field for convenience, but 746 // Parent IDs are stored in the parent_id field for convenience, but
755 // they have not yet been validated. Separate them out here. 747 // they have not yet been validated. Separate them out here.
756 // Because of the order in which we store items in the prefs, parents will 748 // Because of the order in which we store items in the prefs, parents will
757 // precede children, so we should already know about any parent items. 749 // precede children, so we should already know about any parent items.
758 scoped_ptr<ExtensionMenuItem::Id> parent_id; 750 scoped_ptr<MenuItem::Id> parent_id;
759 parent_id.swap(items[i]->parent_id_); 751 parent_id.swap(items[i]->parent_id_);
760 AddChildItem(*parent_id, items[i]); 752 AddChildItem(*parent_id, items[i]);
761 } else { 753 } else {
762 AddContextItem(extension, items[i]); 754 AddContextItem(extension, items[i]);
763 } 755 }
764 } 756 }
765 } 757 }
766 758
767 void ExtensionMenuManager::Observe( 759 void MenuManager::Observe(int type,
768 int type, 760 const content::NotificationSource& source,
769 const content::NotificationSource& source, 761 const content::NotificationDetails& details) {
770 const content::NotificationDetails& details) {
771 if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) { 762 if (type == chrome::NOTIFICATION_EXTENSION_UNLOADED) {
772 // Remove menu items for disabled/uninstalled extensions. 763 // Remove menu items for disabled/uninstalled extensions.
773 const extensions::Extension* extension = 764 const Extension* extension =
774 content::Details<extensions::UnloadedExtensionInfo>(details)->extension; 765 content::Details<UnloadedExtensionInfo>(details)->extension;
775 if (ContainsKey(context_items_, extension->id())) { 766 if (ContainsKey(context_items_, extension->id())) {
776 RemoveAllContextItems(extension->id()); 767 RemoveAllContextItems(extension->id());
777 } 768 }
778 } else if (type == chrome::NOTIFICATION_EXTENSION_LOADED) { 769 } else if (type == chrome::NOTIFICATION_EXTENSION_LOADED) {
779 const extensions::Extension* extension = 770 const Extension* extension =
780 content::Details<const extensions::Extension>(details).ptr(); 771 content::Details<const Extension>(details).ptr();
781 extensions::StateStore* store = 772 StateStore* store = ExtensionSystem::Get(profile_)->state_store();
782 ExtensionSystem::Get(profile_)->state_store();
783 if (store && extension->has_lazy_background_page()) { 773 if (store && extension->has_lazy_background_page()) {
784 store->GetExtensionValue(extension->id(), kContextMenusKey, 774 store->GetExtensionValue(extension->id(), kContextMenusKey,
785 base::Bind(&ExtensionMenuManager::ReadFromStorage, 775 base::Bind(&MenuManager::ReadFromStorage,
786 AsWeakPtr(), extension->id())); 776 AsWeakPtr(), extension->id()));
787 } 777 }
788 } 778 }
789 } 779 }
790 780
791 const SkBitmap& ExtensionMenuManager::GetIconForExtension( 781 const SkBitmap& MenuManager::GetIconForExtension(
792 const std::string& extension_id) { 782 const std::string& extension_id) {
793 return icon_manager_.GetIcon(extension_id); 783 return icon_manager_.GetIcon(extension_id);
794 } 784 }
795 785
796 ExtensionMenuItem::Id::Id() 786 MenuItem::Id::Id()
797 : incognito(false), extension_id(""), uid(0), string_uid("") { 787 : incognito(false), extension_id(""), uid(0), string_uid("") {
798 } 788 }
799 789
800 ExtensionMenuItem::Id::Id(bool incognito, const std::string& extension_id) 790 MenuItem::Id::Id(bool incognito, const std::string& extension_id)
801 : incognito(incognito), extension_id(extension_id), uid(0), 791 : incognito(incognito), extension_id(extension_id), uid(0),
802 string_uid("") { 792 string_uid("") {
803 } 793 }
804 794
805 ExtensionMenuItem::Id::~Id() { 795 MenuItem::Id::~Id() {
806 } 796 }
807 797
808 bool ExtensionMenuItem::Id::operator==(const Id& other) const { 798 bool MenuItem::Id::operator==(const Id& other) const {
809 return (incognito == other.incognito && 799 return (incognito == other.incognito &&
810 extension_id == other.extension_id && 800 extension_id == other.extension_id &&
811 uid == other.uid && 801 uid == other.uid &&
812 string_uid == other.string_uid); 802 string_uid == other.string_uid);
813 } 803 }
814 804
815 bool ExtensionMenuItem::Id::operator!=(const Id& other) const { 805 bool MenuItem::Id::operator!=(const Id& other) const {
816 return !(*this == other); 806 return !(*this == other);
817 } 807 }
818 808
819 bool ExtensionMenuItem::Id::operator<(const Id& other) const { 809 bool MenuItem::Id::operator<(const Id& other) const {
820 if (incognito < other.incognito) 810 if (incognito < other.incognito)
821 return true; 811 return true;
822 if (incognito == other.incognito) { 812 if (incognito == other.incognito) {
823 if (extension_id < other.extension_id) 813 if (extension_id < other.extension_id)
824 return true; 814 return true;
825 if (extension_id == other.extension_id) { 815 if (extension_id == other.extension_id) {
826 if (uid < other.uid) 816 if (uid < other.uid)
827 return true; 817 return true;
828 if (uid == other.uid) 818 if (uid == other.uid)
829 return string_uid < other.string_uid; 819 return string_uid < other.string_uid;
830 } 820 }
831 } 821 }
832 return false; 822 return false;
833 } 823 }
824
825 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/browser/extensions/menu_manager.h ('k') | chrome/browser/extensions/menu_manager_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698