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

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

Issue 8935016: Contributed by Eriq Augustine <eriq.augustine@gmail.com> (Closed) Base URL: http://src.chromium.org/svn/trunk/src/
Patch Set: '' Created 8 years, 11 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2011 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/extension_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"
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
132 // added. 132 // added.
133 if (extension_id.empty() || ContainsKey(items_by_id_, item->id())) 133 if (extension_id.empty() || ContainsKey(items_by_id_, item->id()))
134 return false; 134 return false;
135 135
136 DCHECK_EQ(extension->id(), extension_id); 136 DCHECK_EQ(extension->id(), extension_id);
137 137
138 bool first_item = !ContainsKey(context_items_, extension_id); 138 bool first_item = !ContainsKey(context_items_, extension_id);
139 context_items_[extension_id].push_back(item); 139 context_items_[extension_id].push_back(item);
140 items_by_id_[item->id()] = item; 140 items_by_id_[item->id()] = item;
141 141
142 if (item->type() == ExtensionMenuItem::RADIO && item->checked()) 142 if (item->type() == ExtensionMenuItem::RADIO) {
143 RadioItemSelected(item); 143 if (item->checked()) {
144 RadioItemSelected(item);
145 } else {
146 SanitizeRadioList(context_items_[extension_id]);
147 }
148 }
asargent_no_longer_on_chrome 2012/01/06 21:17:42 nit: other code uses the optional style practice o
144 149
145 // If this is the first item for this extension, start loading its icon. 150 // If this is the first item for this extension, start loading its icon.
146 if (first_item) 151 if (first_item)
147 icon_manager_.LoadIcon(extension); 152 icon_manager_.LoadIcon(extension);
148 153
149 return true; 154 return true;
150 } 155 }
151 156
152 bool ExtensionMenuManager::AddChildItem(const ExtensionMenuItem::Id& parent_id, 157 bool ExtensionMenuManager::AddChildItem(const ExtensionMenuItem::Id& parent_id,
153 ExtensionMenuItem* child) { 158 ExtensionMenuItem* child) {
154 ExtensionMenuItem* parent = GetItemById(parent_id); 159 ExtensionMenuItem* parent = GetItemById(parent_id);
155 if (!parent || parent->type() != ExtensionMenuItem::NORMAL || 160 if (!parent || parent->type() != ExtensionMenuItem::NORMAL ||
156 parent->extension_id() != child->extension_id() || 161 parent->extension_id() != child->extension_id() ||
157 ContainsKey(items_by_id_, child->id())) 162 ContainsKey(items_by_id_, child->id()))
158 return false; 163 return false;
159 parent->AddChild(child); 164 parent->AddChild(child);
160 items_by_id_[child->id()] = child; 165 items_by_id_[child->id()] = child;
166
167 if (child->type() == ExtensionMenuItem::RADIO) {
168 SanitizeRadioList(parent->children());
169 }
170
161 return true; 171 return true;
162 } 172 }
163 173
164 bool ExtensionMenuManager::DescendantOf( 174 bool ExtensionMenuManager::DescendantOf(
165 ExtensionMenuItem* item, 175 ExtensionMenuItem* item,
166 const ExtensionMenuItem::Id& ancestor_id) { 176 const ExtensionMenuItem::Id& ancestor_id) {
167 // Work our way up the tree until we find the ancestor or NULL. 177 // Work our way up the tree until we find the ancestor or NULL.
168 ExtensionMenuItem::Id* id = item->parent_id(); 178 ExtensionMenuItem::Id* id = item->parent_id();
169 while (id != NULL) { 179 while (id != NULL) {
170 DCHECK(*id != item->id()); // Catch circular graphs. 180 DCHECK(*id != item->id()); // Catch circular graphs.
(...skipping 23 matching lines...) Expand all
194 ExtensionMenuItem::Id* old_parent_id = child->parent_id(); 204 ExtensionMenuItem::Id* old_parent_id = child->parent_id();
195 if (old_parent_id != NULL) { 205 if (old_parent_id != NULL) {
196 ExtensionMenuItem* old_parent = GetItemById(*old_parent_id); 206 ExtensionMenuItem* old_parent = GetItemById(*old_parent_id);
197 if (!old_parent) { 207 if (!old_parent) {
198 NOTREACHED(); 208 NOTREACHED();
199 return false; 209 return false;
200 } 210 }
201 ExtensionMenuItem* taken = 211 ExtensionMenuItem* taken =
202 old_parent->ReleaseChild(child_id, false /* non-recursive search*/); 212 old_parent->ReleaseChild(child_id, false /* non-recursive search*/);
203 DCHECK(taken == child); 213 DCHECK(taken == child);
214 SanitizeRadioList(old_parent->children());
204 } else { 215 } else {
205 // This is a top-level item, so we need to pull it out of our list of 216 // This is a top-level item, so we need to pull it out of our list of
206 // top-level items. 217 // top-level items.
207 MenuItemMap::iterator i = context_items_.find(child->extension_id()); 218 MenuItemMap::iterator i = context_items_.find(child->extension_id());
208 if (i == context_items_.end()) { 219 if (i == context_items_.end()) {
209 NOTREACHED(); 220 NOTREACHED();
210 return false; 221 return false;
211 } 222 }
212 ExtensionMenuItem::List& list = i->second; 223 ExtensionMenuItem::List& list = i->second;
213 ExtensionMenuItem::List::iterator j = std::find(list.begin(), list.end(), 224 ExtensionMenuItem::List::iterator j = std::find(list.begin(), list.end(),
214 child); 225 child);
215 if (j == list.end()) { 226 if (j == list.end()) {
216 NOTREACHED(); 227 NOTREACHED();
217 return false; 228 return false;
218 } 229 }
219 list.erase(j); 230 list.erase(j);
231 SanitizeRadioList(list);
220 } 232 }
221 233
222 if (new_parent) { 234 if (new_parent) {
223 new_parent->AddChild(child); 235 new_parent->AddChild(child);
236 SanitizeRadioList(new_parent->children());
224 } else { 237 } else {
225 context_items_[child->extension_id()].push_back(child); 238 context_items_[child->extension_id()].push_back(child);
226 child->parent_id_.reset(NULL); 239 child->parent_id_.reset(NULL);
240 SanitizeRadioList(context_items_[child->extension_id()]);
227 } 241 }
228 return true; 242 return true;
229 } 243 }
230 244
231 bool ExtensionMenuManager::RemoveContextMenuItem( 245 bool ExtensionMenuManager::RemoveContextMenuItem(
232 const ExtensionMenuItem::Id& id) { 246 const ExtensionMenuItem::Id& id) {
233 if (!ContainsKey(items_by_id_, id)) 247 if (!ContainsKey(items_by_id_, id))
234 return false; 248 return false;
235 249
236 ExtensionMenuItem* menu_item = GetItemById(id); 250 ExtensionMenuItem* menu_item = GetItemById(id);
(...skipping 10 matching lines...) Expand all
247 ExtensionMenuItem::List& list = i->second; 261 ExtensionMenuItem::List& list = i->second;
248 ExtensionMenuItem::List::iterator j; 262 ExtensionMenuItem::List::iterator j;
249 for (j = list.begin(); j < list.end(); ++j) { 263 for (j = list.begin(); j < list.end(); ++j) {
250 // See if the current top-level item is a match. 264 // See if the current top-level item is a match.
251 if ((*j)->id() == id) { 265 if ((*j)->id() == id) {
252 items_removed = (*j)->RemoveAllDescendants(); 266 items_removed = (*j)->RemoveAllDescendants();
253 items_removed.insert(id); 267 items_removed.insert(id);
254 delete *j; 268 delete *j;
255 list.erase(j); 269 list.erase(j);
256 result = true; 270 result = true;
271 SanitizeRadioList(list);
257 break; 272 break;
258 } else { 273 } else {
259 // See if the item to remove was found as a descendant of the current 274 // See if the item to remove was found as a descendant of the current
260 // top-level item. 275 // top-level item.
261 ExtensionMenuItem* child = (*j)->ReleaseChild(id, true /* recursive */); 276 ExtensionMenuItem* child = (*j)->ReleaseChild(id, true /* recursive */);
262 if (child) { 277 if (child) {
263 items_removed = child->RemoveAllDescendants(); 278 items_removed = child->RemoveAllDescendants();
264 items_removed.insert(id); 279 items_removed.insert(id);
280 SanitizeRadioList(GetItemById(*child->parent_id())->children());
265 delete child; 281 delete child;
266 result = true; 282 result = true;
267 break; 283 break;
268 } 284 }
269 } 285 }
270 } 286 }
271 DCHECK(result); // The check at the very top should have prevented this. 287 DCHECK(result); // The check at the very top should have prevented this.
272 288
273 // Clear entries from the items_by_id_ map. 289 // Clear entries from the items_by_id_ map.
274 std::set<ExtensionMenuItem::Id>::iterator removed_iter; 290 std::set<ExtensionMenuItem::Id>::iterator removed_iter;
(...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 properties->SetBoolean("checked", item->checked()); 458 properties->SetBoolean("checked", item->checked());
443 } 459 }
444 460
445 std::string json_args; 461 std::string json_args;
446 base::JSONWriter::Write(&args, false, &json_args); 462 base::JSONWriter::Write(&args, false, &json_args);
447 std::string event_name = "contextMenus"; 463 std::string event_name = "contextMenus";
448 event_router->DispatchEventToExtension( 464 event_router->DispatchEventToExtension(
449 item->extension_id(), event_name, json_args, profile, GURL()); 465 item->extension_id(), event_name, json_args, profile, GURL());
450 } 466 }
451 467
468 void ExtensionMenuManager::SanitizeRadioList(
469 const ExtensionMenuItem::List& item_list) {
470 ExtensionMenuItem::List::const_iterator i = item_list.begin();
471 while (i != item_list.end()) {
472 if ((*i)->type() == ExtensionMenuItem::RADIO) {
asargent_no_longer_on_chrome 2012/01/06 21:17:42 nit: you could improve readability slightly by mak
473 // If there are multiple items selected, the last one will override the
474 // others.
475 ExtensionMenuItem::List::const_iterator last_checked = item_list.end();
476 ExtensionMenuItem::List::const_iterator radio_run_iter;
477 for (radio_run_iter = i; radio_run_iter != item_list.end();
478 ++radio_run_iter) {
479 if ((*radio_run_iter)->type() != ExtensionMenuItem::RADIO) {
480 break;
481 }
482
483 if ((*radio_run_iter)->checked()) {
484 last_checked = radio_run_iter;
485 (*radio_run_iter)->SetChecked(false);
486 }
487 }
488
489 // If radio items were found in this run,
490 // check the first radio item in the list (i).
asargent_no_longer_on_chrome 2012/01/06 21:17:42 nit: this comment isn't quite right. It could be s
491 if (last_checked != item_list.end()) {
492 (*last_checked)->SetChecked(true);
493 } else {
494 (*i)->SetChecked(true);
495 }
496
497 i = radio_run_iter;
498 } else {
499 ++i;
500 }
501 }
502 }
503
504 bool ExtensionMenuManager::ItemUpdated(const ExtensionMenuItem::Id& id) {
505 if (!ContainsKey(items_by_id_, id))
506 return false;
507
508 ExtensionMenuItem* menu_item = GetItemById(id);
509 DCHECK(menu_item);
510
511 if (menu_item->parent_id()) {
512 SanitizeRadioList(GetItemById(*menu_item->parent_id())->children());
513 } else {
514 std::string extension_id = menu_item->extension_id();
515 MenuItemMap::iterator i = context_items_.find(extension_id);
516 if (i == context_items_.end()) {
517 NOTREACHED();
518 return false;
519 }
520 SanitizeRadioList(i->second);
521 }
522
523 return true;
524 }
525
452 void ExtensionMenuManager::Observe( 526 void ExtensionMenuManager::Observe(
453 int type, 527 int type,
454 const content::NotificationSource& source, 528 const content::NotificationSource& source,
455 const content::NotificationDetails& details) { 529 const content::NotificationDetails& details) {
456 DCHECK(type == chrome::NOTIFICATION_EXTENSION_UNLOADED); 530 DCHECK(type == chrome::NOTIFICATION_EXTENSION_UNLOADED);
457 531
458 // Remove menu items for disabled/uninstalled extensions. 532 // Remove menu items for disabled/uninstalled extensions.
459 const Extension* extension = 533 const Extension* extension =
460 content::Details<UnloadedExtensionInfo>(details)->extension; 534 content::Details<UnloadedExtensionInfo>(details)->extension;
461 if (ContainsKey(context_items_, extension->id())) { 535 if (ContainsKey(context_items_, extension->id())) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
495 if (profile < other.profile) 569 if (profile < other.profile)
496 return true; 570 return true;
497 if (profile == other.profile) { 571 if (profile == other.profile) {
498 if (extension_id < other.extension_id) 572 if (extension_id < other.extension_id)
499 return true; 573 return true;
500 if (extension_id == other.extension_id) 574 if (extension_id == other.extension_id)
501 return uid < other.uid; 575 return uid < other.uid;
502 } 576 }
503 return false; 577 return false;
504 } 578 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698