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

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

Issue 186213003: <webview>: Context menu API implementation CL. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Put ExtensionKey into MenuItem::Id. Created 6 years, 9 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/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/strings/string_util.h" 12 #include "base/strings/string_util.h"
13 #include "base/strings/utf_string_conversions.h" 13 #include "base/strings/utf_string_conversions.h"
14 #include "base/values.h" 14 #include "base/values.h"
15 #include "chrome/browser/chrome_notification_types.h" 15 #include "chrome/browser/chrome_notification_types.h"
16 #include "chrome/browser/extensions/event_names.h" 16 #include "chrome/browser/extensions/event_names.h"
17 #include "chrome/browser/extensions/extension_service.h" 17 #include "chrome/browser/extensions/extension_service.h"
18 #include "chrome/browser/extensions/extension_tab_util.h" 18 #include "chrome/browser/extensions/extension_tab_util.h"
19 #include "chrome/browser/extensions/menu_manager_factory.h" 19 #include "chrome/browser/extensions/menu_manager_factory.h"
20 #include "chrome/browser/extensions/state_store.h" 20 #include "chrome/browser/extensions/state_store.h"
21 #include "chrome/browser/extensions/tab_helper.h" 21 #include "chrome/browser/extensions/tab_helper.h"
22 #include "chrome/browser/guestview/webview/webview_guest.h"
22 #include "chrome/browser/profiles/profile.h" 23 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/common/extensions/api/context_menus.h" 24 #include "chrome/common/extensions/api/context_menus.h"
24 #include "content/public/browser/notification_details.h" 25 #include "content/public/browser/notification_details.h"
25 #include "content/public/browser/notification_service.h" 26 #include "content/public/browser/notification_service.h"
26 #include "content/public/browser/notification_source.h" 27 #include "content/public/browser/notification_source.h"
27 #include "content/public/browser/web_contents.h" 28 #include "content/public/browser/web_contents.h"
28 #include "content/public/common/context_menu_params.h" 29 #include "content/public/common/context_menu_params.h"
29 #include "extensions/browser/event_router.h" 30 #include "extensions/browser/event_router.h"
30 #include "extensions/browser/extension_system.h" 31 #include "extensions/browser/extension_system.h"
31 #include "extensions/common/extension.h" 32 #include "extensions/common/extension.h"
(...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after
315 316
316 // static 317 // static
317 MenuManager* MenuManager::Get(Profile* profile) { 318 MenuManager* MenuManager::Get(Profile* profile) {
318 return MenuManagerFactory::GetForProfile(profile); 319 return MenuManagerFactory::GetForProfile(profile);
319 } 320 }
320 321
321 std::set<std::string> MenuManager::ExtensionIds() { 322 std::set<std::string> MenuManager::ExtensionIds() {
322 std::set<std::string> id_set; 323 std::set<std::string> id_set;
323 for (MenuItemMap::const_iterator i = context_items_.begin(); 324 for (MenuItemMap::const_iterator i = context_items_.begin();
324 i != context_items_.end(); ++i) { 325 i != context_items_.end(); ++i) {
325 id_set.insert(i->first); 326 id_set.insert(i->first.extension_id);
326 } 327 }
327 return id_set; 328 return id_set;
328 } 329 }
329 330
330 const MenuItem::List* MenuManager::MenuItems( 331 const MenuItem::List* MenuManager::MenuItems(
331 const std::string& extension_id) { 332 const MenuItem::ExtensionKey& key) {
332 MenuItemMap::iterator i = context_items_.find(extension_id); 333 MenuItemMap::iterator i = context_items_.find(key);
333 if (i != context_items_.end()) { 334 if (i != context_items_.end()) {
334 return &(i->second); 335 return &(i->second);
335 } 336 }
336 return NULL; 337 return NULL;
337 } 338 }
338 339
339 bool MenuManager::AddContextItem( 340 bool MenuManager::AddContextItem(const Extension* extension, MenuItem* item) {
340 const Extension* extension, 341 const MenuItem::ExtensionKey& key = item->id().extension_key;
341 MenuItem* item) {
342 const std::string& extension_id = item->extension_id();
343 // The item must have a non-empty extension id, and not have already been 342 // The item must have a non-empty extension id, and not have already been
344 // added. 343 // added.
345 if (extension_id.empty() || ContainsKey(items_by_id_, item->id())) 344 if (key.empty() || ContainsKey(items_by_id_, item->id()))
346 return false; 345 return false;
347 346
348 DCHECK_EQ(extension->id(), extension_id); 347 DCHECK_EQ(extension->id(), key.extension_id);
349 348
350 bool first_item = !ContainsKey(context_items_, extension_id); 349 bool first_item = !ContainsKey(context_items_, key);
351 context_items_[extension_id].push_back(item); 350 context_items_[key].push_back(item);
352 items_by_id_[item->id()] = item; 351 items_by_id_[item->id()] = item;
353 352
354 if (item->type() == MenuItem::RADIO) { 353 if (item->type() == MenuItem::RADIO) {
355 if (item->checked()) 354 if (item->checked())
356 RadioItemSelected(item); 355 RadioItemSelected(item);
357 else 356 else
358 SanitizeRadioList(context_items_[extension_id]); 357 SanitizeRadioList(context_items_[key]);
359 } 358 }
360 359
361 // If this is the first item for this extension, start loading its icon. 360 // If this is the first item for this extension, start loading its icon.
362 if (first_item) 361 if (first_item)
363 icon_manager_.LoadIcon(profile_, extension); 362 icon_manager_.LoadIcon(profile_, extension);
364 363
365 return true; 364 return true;
366 } 365 }
367 366
368 bool MenuManager::AddChildItem(const MenuItem::Id& parent_id, 367 bool MenuManager::AddChildItem(const MenuItem::Id& parent_id,
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
417 NOTREACHED(); 416 NOTREACHED();
418 return false; 417 return false;
419 } 418 }
420 MenuItem* taken = 419 MenuItem* taken =
421 old_parent->ReleaseChild(child_id, false /* non-recursive search*/); 420 old_parent->ReleaseChild(child_id, false /* non-recursive search*/);
422 DCHECK(taken == child); 421 DCHECK(taken == child);
423 SanitizeRadioList(old_parent->children()); 422 SanitizeRadioList(old_parent->children());
424 } else { 423 } else {
425 // This is a top-level item, so we need to pull it out of our list of 424 // This is a top-level item, so we need to pull it out of our list of
426 // top-level items. 425 // top-level items.
427 MenuItemMap::iterator i = context_items_.find(child->extension_id()); 426 const MenuItem::ExtensionKey& child_key = child->id().extension_key;
427 MenuItemMap::iterator i = context_items_.find(child_key);
428 if (i == context_items_.end()) { 428 if (i == context_items_.end()) {
429 NOTREACHED(); 429 NOTREACHED();
430 return false; 430 return false;
431 } 431 }
432 MenuItem::List& list = i->second; 432 MenuItem::List& list = i->second;
433 MenuItem::List::iterator j = std::find(list.begin(), list.end(), 433 MenuItem::List::iterator j = std::find(list.begin(), list.end(), child);
434 child);
435 if (j == list.end()) { 434 if (j == list.end()) {
436 NOTREACHED(); 435 NOTREACHED();
437 return false; 436 return false;
438 } 437 }
439 list.erase(j); 438 list.erase(j);
440 SanitizeRadioList(list); 439 SanitizeRadioList(list);
441 } 440 }
442 441
443 if (new_parent) { 442 if (new_parent) {
444 new_parent->AddChild(child); 443 new_parent->AddChild(child);
445 SanitizeRadioList(new_parent->children()); 444 SanitizeRadioList(new_parent->children());
446 } else { 445 } else {
447 context_items_[child->extension_id()].push_back(child); 446 const MenuItem::ExtensionKey& child_key = child->id().extension_key;
447 context_items_[child_key].push_back(child);
448 child->parent_id_.reset(NULL); 448 child->parent_id_.reset(NULL);
449 SanitizeRadioList(context_items_[child->extension_id()]); 449 SanitizeRadioList(context_items_[child_key]);
450 } 450 }
451 return true; 451 return true;
452 } 452 }
453 453
454 bool MenuManager::RemoveContextMenuItem(const MenuItem::Id& id) { 454 bool MenuManager::RemoveContextMenuItem(const MenuItem::Id& id) {
455 if (!ContainsKey(items_by_id_, id)) 455 if (!ContainsKey(items_by_id_, id))
456 return false; 456 return false;
457 457
458 MenuItem* menu_item = GetItemById(id); 458 MenuItem* menu_item = GetItemById(id);
459 DCHECK(menu_item); 459 DCHECK(menu_item);
460 std::string extension_id = menu_item->extension_id(); 460 MenuItemMap::iterator i = context_items_.find(id.extension_key);
461 MenuItemMap::iterator i = context_items_.find(extension_id);
462 if (i == context_items_.end()) { 461 if (i == context_items_.end()) {
463 NOTREACHED(); 462 NOTREACHED();
464 return false; 463 return false;
465 } 464 }
466 465
467 bool result = false; 466 bool result = false;
468 std::set<MenuItem::Id> items_removed; 467 std::set<MenuItem::Id> items_removed;
469 MenuItem::List& list = i->second; 468 MenuItem::List& list = i->second;
470 MenuItem::List::iterator j; 469 MenuItem::List::iterator j;
471 for (j = list.begin(); j < list.end(); ++j) { 470 for (j = list.begin(); j < list.end(); ++j) {
(...skipping 24 matching lines...) Expand all
496 495
497 // Clear entries from the items_by_id_ map. 496 // Clear entries from the items_by_id_ map.
498 std::set<MenuItem::Id>::iterator removed_iter; 497 std::set<MenuItem::Id>::iterator removed_iter;
499 for (removed_iter = items_removed.begin(); 498 for (removed_iter = items_removed.begin();
500 removed_iter != items_removed.end(); 499 removed_iter != items_removed.end();
501 ++removed_iter) { 500 ++removed_iter) {
502 items_by_id_.erase(*removed_iter); 501 items_by_id_.erase(*removed_iter);
503 } 502 }
504 503
505 if (list.empty()) { 504 if (list.empty()) {
506 context_items_.erase(extension_id); 505 context_items_.erase(id.extension_key);
507 icon_manager_.RemoveIcon(extension_id); 506 icon_manager_.RemoveIcon(id.extension_key.extension_id);
508 } 507 }
509 return result; 508 return result;
510 } 509 }
511 510
512 void MenuManager::RemoveAllContextItems(const std::string& extension_id) { 511 void MenuManager::RemoveAllContextItems(
512 const MenuItem::ExtensionKey& extension_key) {
513 MenuItem::List::iterator i; 513 MenuItem::List::iterator i;
514 for (i = context_items_[extension_id].begin(); 514 for (i = context_items_[extension_key].begin();
515 i != context_items_[extension_id].end(); ++i) { 515 i != context_items_[extension_key].end();
516 ++i) {
516 MenuItem* item = *i; 517 MenuItem* item = *i;
517 items_by_id_.erase(item->id()); 518 items_by_id_.erase(item->id());
518 519
519 // Remove descendants from this item and erase them from the lookup cache. 520 // Remove descendants from this item and erase them from the lookup cache.
520 std::set<MenuItem::Id> removed_ids = item->RemoveAllDescendants(); 521 std::set<MenuItem::Id> removed_ids = item->RemoveAllDescendants();
521 std::set<MenuItem::Id>::const_iterator j; 522 std::set<MenuItem::Id>::const_iterator j;
522 for (j = removed_ids.begin(); j != removed_ids.end(); ++j) { 523 for (j = removed_ids.begin(); j != removed_ids.end(); ++j) {
523 items_by_id_.erase(*j); 524 items_by_id_.erase(*j);
524 } 525 }
525 } 526 }
526 STLDeleteElements(&context_items_[extension_id]); 527 STLDeleteElements(&context_items_[extension_key]);
527 context_items_.erase(extension_id); 528 context_items_.erase(extension_key);
528 icon_manager_.RemoveIcon(extension_id); 529 icon_manager_.RemoveIcon(extension_key.extension_id);
529 } 530 }
530 531
531 MenuItem* MenuManager::GetItemById(const MenuItem::Id& id) const { 532 MenuItem* MenuManager::GetItemById(const MenuItem::Id& id) const {
532 std::map<MenuItem::Id, MenuItem*>::const_iterator i = 533 std::map<MenuItem::Id, MenuItem*>::const_iterator i =
533 items_by_id_.find(id); 534 items_by_id_.find(id);
534 if (i != items_by_id_.end()) 535 if (i != items_by_id_.end())
535 return i->second; 536 return i->second;
536 else 537 else
537 return NULL; 538 return NULL;
538 } 539 }
539 540
540 void MenuManager::RadioItemSelected(MenuItem* item) { 541 void MenuManager::RadioItemSelected(MenuItem* item) {
541 // If this is a child item, we need to get a handle to the list from its 542 // If this is a child item, we need to get a handle to the list from its
542 // parent. Otherwise get a handle to the top-level list. 543 // parent. Otherwise get a handle to the top-level list.
543 const MenuItem::List* list = NULL; 544 const MenuItem::List* list = NULL;
544 if (item->parent_id()) { 545 if (item->parent_id()) {
545 MenuItem* parent = GetItemById(*item->parent_id()); 546 MenuItem* parent = GetItemById(*item->parent_id());
546 if (!parent) { 547 if (!parent) {
547 NOTREACHED(); 548 NOTREACHED();
548 return; 549 return;
549 } 550 }
550 list = &(parent->children()); 551 list = &(parent->children());
551 } else { 552 } else {
552 if (context_items_.find(item->extension_id()) == context_items_.end()) { 553 const MenuItem::ExtensionKey& key = item->id().extension_key;
554 if (context_items_.find(key) == context_items_.end()) {
553 NOTREACHED(); 555 NOTREACHED();
554 return; 556 return;
555 } 557 }
556 list = &context_items_[item->extension_id()]; 558 list = &context_items_[key];
557 } 559 }
558 560
559 // Find where |item| is in the list. 561 // Find where |item| is in the list.
560 MenuItem::List::const_iterator item_location; 562 MenuItem::List::const_iterator item_location;
561 for (item_location = list->begin(); item_location != list->end(); 563 for (item_location = list->begin(); item_location != list->end();
562 ++item_location) { 564 ++item_location) {
563 if (*item_location == item) 565 if (*item_location == item)
564 break; 566 break;
565 } 567 }
566 if (item_location == list->end()) { 568 if (item_location == list->end()) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
603 if (!event_router) 605 if (!event_router)
604 return; 606 return;
605 607
606 MenuItem* item = GetItemById(menu_item_id); 608 MenuItem* item = GetItemById(menu_item_id);
607 if (!item) 609 if (!item)
608 return; 610 return;
609 611
610 // ExtensionService/Extension can be NULL in unit tests :( 612 // ExtensionService/Extension can be NULL in unit tests :(
611 ExtensionService* service = 613 ExtensionService* service =
612 ExtensionSystem::Get(profile_)->extension_service(); 614 ExtensionSystem::Get(profile_)->extension_service();
613 const Extension* extension = service ? 615 const Extension* extension =
614 service->extensions()->GetByID(menu_item_id.extension_id) : NULL; 616 service ? service->extensions()->GetByID(item->extension_id()) : NULL;
615 617
616 if (item->type() == MenuItem::RADIO) 618 if (item->type() == MenuItem::RADIO)
617 RadioItemSelected(item); 619 RadioItemSelected(item);
618 620
619 scoped_ptr<base::ListValue> args(new base::ListValue()); 621 scoped_ptr<base::ListValue> args(new base::ListValue());
620 622
621 base::DictionaryValue* properties = new base::DictionaryValue(); 623 base::DictionaryValue* properties = new base::DictionaryValue();
622 SetIdKeyValue(properties, "menuItemId", item->id()); 624 SetIdKeyValue(properties, "menuItemId", item->id());
623 if (item->parent_id()) 625 if (item->parent_id())
624 SetIdKeyValue(properties, "parentMenuItemId", *item->parent_id()); 626 SetIdKeyValue(properties, "parentMenuItemId", *item->parent_id());
(...skipping 14 matching lines...) Expand all
639 AddURLProperty(properties, "linkUrl", params.unfiltered_link_url); 641 AddURLProperty(properties, "linkUrl", params.unfiltered_link_url);
640 AddURLProperty(properties, "srcUrl", params.src_url); 642 AddURLProperty(properties, "srcUrl", params.src_url);
641 AddURLProperty(properties, "pageUrl", params.page_url); 643 AddURLProperty(properties, "pageUrl", params.page_url);
642 AddURLProperty(properties, "frameUrl", params.frame_url); 644 AddURLProperty(properties, "frameUrl", params.frame_url);
643 645
644 if (params.selection_text.length() > 0) 646 if (params.selection_text.length() > 0)
645 properties->SetString("selectionText", params.selection_text); 647 properties->SetString("selectionText", params.selection_text);
646 648
647 properties->SetBoolean("editable", params.is_editable); 649 properties->SetBoolean("editable", params.is_editable);
648 650
651 WebViewGuest* webview_guest = WebViewGuest::FromWebContents(web_contents);
652 if (webview_guest) {
653 // This is used in webview_custom_bindings.js.
654 // The property is not exposed to developer API.
655 properties->SetInteger("webviewInstanceId",
656 webview_guest->view_instance_id());
657 }
658
649 args->Append(properties); 659 args->Append(properties);
650 660
651 // Add the tab info to the argument list. 661 // Add the tab info to the argument list.
652 // No tab info in a platform app. 662 // No tab info in a platform app.
653 if (!extension || !extension->is_platform_app()) { 663 if (!extension || !extension->is_platform_app()) {
654 // Note: web_contents are NULL in unit tests :( 664 // Note: web_contents are NULL in unit tests :(
655 if (web_contents) { 665 if (web_contents) {
656 args->Append(ExtensionTabUtil::CreateTabValue(web_contents)); 666 args->Append(ExtensionTabUtil::CreateTabValue(web_contents));
657 } else { 667 } else {
658 args->Append(new base::DictionaryValue()); 668 args->Append(new base::DictionaryValue());
659 } 669 }
660 } 670 }
661 671
662 if (item->type() == MenuItem::CHECKBOX || 672 if (item->type() == MenuItem::CHECKBOX ||
663 item->type() == MenuItem::RADIO) { 673 item->type() == MenuItem::RADIO) {
664 bool was_checked = item->checked(); 674 bool was_checked = item->checked();
665 properties->SetBoolean("wasChecked", was_checked); 675 properties->SetBoolean("wasChecked", was_checked);
666 676
667 // RADIO items always get set to true when you click on them, but CHECKBOX 677 // RADIO items always get set to true when you click on them, but CHECKBOX
668 // items get their state toggled. 678 // items get their state toggled.
669 bool checked = 679 bool checked =
670 (item->type() == MenuItem::RADIO) ? true : !was_checked; 680 (item->type() == MenuItem::RADIO) ? true : !was_checked;
671 681
672 item->SetChecked(checked); 682 item->SetChecked(checked);
673 properties->SetBoolean("checked", item->checked()); 683 properties->SetBoolean("checked", item->checked());
674 684
675 if (extension) 685 if (extension)
676 WriteToStorage(extension); 686 WriteToStorage(extension, item->id().extension_key);
677 } 687 }
678 688
679 // Note: web_contents are NULL in unit tests :( 689 // Note: web_contents are NULL in unit tests :(
680 if (web_contents && extensions::TabHelper::FromWebContents(web_contents)) { 690 if (web_contents && extensions::TabHelper::FromWebContents(web_contents)) {
681 extensions::TabHelper::FromWebContents(web_contents)-> 691 extensions::TabHelper::FromWebContents(web_contents)->
682 active_tab_permission_granter()->GrantIfRequested(extension); 692 active_tab_permission_granter()->GrantIfRequested(extension);
683 } 693 }
684 694
685 { 695 {
696 // Dispatch to menu item's .onclick handler.
686 scoped_ptr<Event> event(new Event( 697 scoped_ptr<Event> event(new Event(
687 event_names::kOnContextMenus, 698 event_names::kOnContextMenus,
688 scoped_ptr<base::ListValue>(args->DeepCopy()))); 699 scoped_ptr<base::ListValue>(args->DeepCopy())));
689 event->restrict_to_browser_context = profile; 700 event->restrict_to_browser_context = profile;
690 event->user_gesture = EventRouter::USER_GESTURE_ENABLED; 701 event->user_gesture = EventRouter::USER_GESTURE_ENABLED;
691 event_router->DispatchEventToExtension(item->extension_id(), event.Pass()); 702 event_router->DispatchEventToExtension(item->extension_id(), event.Pass());
692 } 703 }
693 { 704 {
694 scoped_ptr<Event> event(new Event(context_menus::OnClicked::kEventName, 705 // Dispatch to .contextMenus.onClicked handler.
695 args.Pass())); 706 scoped_ptr<Event> event(
707 new Event(webview_guest ? event_names::kOnWebviewContextMenus
708 : context_menus::OnClicked::kEventName,
709 args.Pass()));
696 event->restrict_to_browser_context = profile; 710 event->restrict_to_browser_context = profile;
697 event->user_gesture = EventRouter::USER_GESTURE_ENABLED; 711 event->user_gesture = EventRouter::USER_GESTURE_ENABLED;
712 if (webview_guest)
713 event->filter_info.SetInstanceID(webview_guest->view_instance_id());
698 event_router->DispatchEventToExtension(item->extension_id(), event.Pass()); 714 event_router->DispatchEventToExtension(item->extension_id(), event.Pass());
699 } 715 }
700 } 716 }
701 717
702 void MenuManager::SanitizeRadioList(const MenuItem::List& item_list) { 718 void MenuManager::SanitizeRadioList(const MenuItem::List& item_list) {
703 MenuItem::List::const_iterator i = item_list.begin(); 719 MenuItem::List::const_iterator i = item_list.begin();
704 while (i != item_list.end()) { 720 while (i != item_list.end()) {
705 if ((*i)->type() != MenuItem::RADIO) { 721 if ((*i)->type() != MenuItem::RADIO) {
706 ++i; 722 ++i;
707 break; 723 break;
(...skipping 28 matching lines...) Expand all
736 bool MenuManager::ItemUpdated(const MenuItem::Id& id) { 752 bool MenuManager::ItemUpdated(const MenuItem::Id& id) {
737 if (!ContainsKey(items_by_id_, id)) 753 if (!ContainsKey(items_by_id_, id))
738 return false; 754 return false;
739 755
740 MenuItem* menu_item = GetItemById(id); 756 MenuItem* menu_item = GetItemById(id);
741 DCHECK(menu_item); 757 DCHECK(menu_item);
742 758
743 if (menu_item->parent_id()) { 759 if (menu_item->parent_id()) {
744 SanitizeRadioList(GetItemById(*menu_item->parent_id())->children()); 760 SanitizeRadioList(GetItemById(*menu_item->parent_id())->children());
745 } else { 761 } else {
746 std::string extension_id = menu_item->extension_id(); 762 MenuItemMap::iterator i =
747 MenuItemMap::iterator i = context_items_.find(extension_id); 763 context_items_.find(menu_item->id().extension_key);
748 if (i == context_items_.end()) { 764 if (i == context_items_.end()) {
749 NOTREACHED(); 765 NOTREACHED();
750 return false; 766 return false;
751 } 767 }
752 SanitizeRadioList(i->second); 768 SanitizeRadioList(i->second);
753 } 769 }
754 770
755 return true; 771 return true;
756 } 772 }
757 773
758 void MenuManager::WriteToStorage(const Extension* extension) { 774 void MenuManager::WriteToStorage(const Extension* extension,
775 const MenuItem::ExtensionKey& extension_key) {
759 if (!BackgroundInfo::HasLazyBackgroundPage(extension)) 776 if (!BackgroundInfo::HasLazyBackgroundPage(extension))
760 return; 777 return;
761 const MenuItem::List* top_items = MenuItems(extension->id()); 778 if (extension_key.webview_instance_id)
Fady Samuel 2014/03/05 17:54:10 A comment above this would be useful.
lazyboy 2014/03/05 18:27:59 Done.
779 return;
780 const MenuItem::List* top_items = MenuItems(extension_key);
762 MenuItem::List all_items; 781 MenuItem::List all_items;
763 if (top_items) { 782 if (top_items) {
764 for (MenuItem::List::const_iterator i = top_items->begin(); 783 for (MenuItem::List::const_iterator i = top_items->begin();
765 i != top_items->end(); ++i) { 784 i != top_items->end(); ++i) {
785 DCHECK(!(*i)->id().extension_key.webview_instance_id);
766 (*i)->GetFlattenedSubtree(&all_items); 786 (*i)->GetFlattenedSubtree(&all_items);
767 } 787 }
768 } 788 }
769 789
770 if (store_) 790 if (store_) {
771 store_->SetExtensionValue(extension->id(), kContextMenusKey, 791 store_->SetExtensionValue(extension->id(), kContextMenusKey,
772 MenuItemsToValue(all_items)); 792 MenuItemsToValue(all_items));
793 }
773 } 794 }
774 795
775 void MenuManager::ReadFromStorage(const std::string& extension_id, 796 void MenuManager::ReadFromStorage(const std::string& extension_id,
776 scoped_ptr<base::Value> value) { 797 scoped_ptr<base::Value> value) {
777 const Extension* extension = 798 const Extension* extension =
778 ExtensionSystem::Get(profile_)->extension_service()->extensions()-> 799 ExtensionSystem::Get(profile_)->extension_service()->extensions()->
779 GetByID(extension_id); 800 GetByID(extension_id);
780 if (!extension) 801 if (!extension)
781 return; 802 return;
782 803
(...skipping 14 matching lines...) Expand all
797 } 818 }
798 819
799 void MenuManager::Observe(int type, 820 void MenuManager::Observe(int type,
800 const content::NotificationSource& source, 821 const content::NotificationSource& source,
801 const content::NotificationDetails& details) { 822 const content::NotificationDetails& details) {
802 switch (type) { 823 switch (type) {
803 case chrome::NOTIFICATION_EXTENSION_UNLOADED: { 824 case chrome::NOTIFICATION_EXTENSION_UNLOADED: {
804 // Remove menu items for disabled/uninstalled extensions. 825 // Remove menu items for disabled/uninstalled extensions.
805 const Extension* extension = 826 const Extension* extension =
806 content::Details<UnloadedExtensionInfo>(details)->extension; 827 content::Details<UnloadedExtensionInfo>(details)->extension;
807 if (ContainsKey(context_items_, extension->id())) { 828 MenuItem::ExtensionKey extension_key(extension->id());
808 RemoveAllContextItems(extension->id()); 829 if (ContainsKey(context_items_, extension_key)) {
830 RemoveAllContextItems(extension_key);
809 } 831 }
810 break; 832 break;
811 } 833 }
812 case chrome::NOTIFICATION_EXTENSION_LOADED: { 834 case chrome::NOTIFICATION_EXTENSION_LOADED: {
813 const Extension* extension = 835 const Extension* extension =
814 content::Details<const Extension>(details).ptr(); 836 content::Details<const Extension>(details).ptr();
815 if (store_ && BackgroundInfo::HasLazyBackgroundPage(extension)) { 837 if (store_ && BackgroundInfo::HasLazyBackgroundPage(extension)) {
816 store_->GetExtensionValue(extension->id(), kContextMenusKey, 838 store_->GetExtensionValue(extension->id(), kContextMenusKey,
817 base::Bind(&MenuManager::ReadFromStorage, 839 base::Bind(&MenuManager::ReadFromStorage,
818 AsWeakPtr(), extension->id())); 840 AsWeakPtr(), extension->id()));
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
852 items_to_remove.insert(iter->first); 874 items_to_remove.insert(iter->first);
853 } 875 }
854 876
855 std::set<MenuItem::Id>::iterator remove_iter; 877 std::set<MenuItem::Id>::iterator remove_iter;
856 for (remove_iter = items_to_remove.begin(); 878 for (remove_iter = items_to_remove.begin();
857 remove_iter != items_to_remove.end(); 879 remove_iter != items_to_remove.end();
858 ++remove_iter) 880 ++remove_iter)
859 RemoveContextMenuItem(*remove_iter); 881 RemoveContextMenuItem(*remove_iter);
860 } 882 }
861 883
884 MenuItem::ExtensionKey::ExtensionKey() : webview_instance_id(0) {}
885
886 MenuItem::ExtensionKey::ExtensionKey(const std::string& extension_id,
887 int webview_instance_id)
888 : extension_id(extension_id), webview_instance_id(webview_instance_id) {}
889
890 MenuItem::ExtensionKey::ExtensionKey(const std::string& extension_id)
891 : extension_id(extension_id), webview_instance_id(0) {}
892
893 bool MenuItem::ExtensionKey::operator==(const ExtensionKey& other) const {
894 return extension_id == other.extension_id &&
895 webview_instance_id == other.webview_instance_id;
896 }
897
898 bool MenuItem::ExtensionKey::operator<(const ExtensionKey& other) const {
899 if (webview_instance_id != other.webview_instance_id)
900 return webview_instance_id < other.webview_instance_id;
901
902 return extension_id < other.extension_id;
903 }
904
905 bool MenuItem::ExtensionKey::operator!=(const ExtensionKey& other) const {
906 return !(*this == other);
907 }
908
909 bool MenuItem::ExtensionKey::empty() const {
910 return extension_id.empty() && !webview_instance_id;
911 }
912
862 MenuItem::Id::Id() : incognito(false), uid(0) {} 913 MenuItem::Id::Id() : incognito(false), uid(0) {}
863 914
864 MenuItem::Id::Id(bool incognito, const std::string& extension_id) 915 MenuItem::Id::Id(bool incognito, const std::string& extension_id)
865 : incognito(incognito), extension_id(extension_id), uid(0) {} 916 : incognito(incognito), extension_key(extension_id), uid(0) {}
866 917
867 MenuItem::Id::~Id() { 918 MenuItem::Id::~Id() {
868 } 919 }
869 920
870 bool MenuItem::Id::operator==(const Id& other) const { 921 bool MenuItem::Id::operator==(const Id& other) const {
871 return (incognito == other.incognito && 922 return (incognito == other.incognito &&
872 extension_id == other.extension_id && 923 extension_key == other.extension_key && uid == other.uid &&
873 uid == other.uid &&
874 string_uid == other.string_uid); 924 string_uid == other.string_uid);
875 } 925 }
876 926
877 bool MenuItem::Id::operator!=(const Id& other) const { 927 bool MenuItem::Id::operator!=(const Id& other) const {
878 return !(*this == other); 928 return !(*this == other);
879 } 929 }
880 930
881 bool MenuItem::Id::operator<(const Id& other) const { 931 bool MenuItem::Id::operator<(const Id& other) const {
882 if (incognito < other.incognito) 932 if (incognito < other.incognito)
883 return true; 933 return true;
884 if (incognito == other.incognito) { 934 if (incognito == other.incognito) {
885 if (extension_id < other.extension_id) 935 if (extension_key < other.extension_key)
886 return true; 936 return true;
887 if (extension_id == other.extension_id) { 937 if (extension_key == other.extension_key) {
888 if (uid < other.uid) 938 if (uid < other.uid)
889 return true; 939 return true;
890 if (uid == other.uid) 940 if (uid == other.uid)
891 return string_uid < other.string_uid; 941 return string_uid < other.string_uid;
892 } 942 }
893 } 943 }
894 return false; 944 return false;
895 } 945 }
896 946
897 } // namespace extensions 947 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698