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

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: 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/guestview.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 470 matching lines...) Expand 10 before | Expand all | Expand 10 after
502 items_by_id_.erase(*removed_iter); 503 items_by_id_.erase(*removed_iter);
503 } 504 }
504 505
505 if (list.empty()) { 506 if (list.empty()) {
506 context_items_.erase(extension_id); 507 context_items_.erase(extension_id);
507 icon_manager_.RemoveIcon(extension_id); 508 icon_manager_.RemoveIcon(extension_id);
508 } 509 }
509 return result; 510 return result;
510 } 511 }
511 512
513 void MenuManager::RemoveAllWebviewContextItems(const std::string& extension_id,
514 int webview_instance_id) {
515 MenuItem::List::iterator i;
516 for (i = context_items_[extension_id].begin();
Fady Samuel 2014/03/04 01:56:46 I think it would be much cleaner if context items
lazyboy 2014/03/04 16:11:31 Hmmm, for most cases, webview_instance_id is 0, ad
Fady Samuel 2014/03/04 16:36:00 There is no additional indirection being added in
lazyboy 2014/03/04 20:50:24 Included instance id to the key, called MenuItem::
517 i != context_items_[extension_id].end();
518 ++i) {
519 MenuItem* item = *i;
520 if (item->id().webview_instance_id != webview_instance_id)
521 continue;
522 items_by_id_.erase(item->id());
523
524 // Remove descendants from this item and erase them from the lookup cache.
525 std::set<MenuItem::Id> removed_ids = item->RemoveAllDescendants();
526 std::set<MenuItem::Id>::const_iterator j;
527 for (j = removed_ids.begin(); j != removed_ids.end(); ++j)
528 items_by_id_.erase(*j);
529 }
530
531 // TODO(lazyboy): Consider better data structure. We are naivly iterating
532 // through each items in the extension and remvoving the ones that belong
533 // to the webview.
534 MenuItem::List& items = context_items_[extension_id];
535 i = items.begin();
536 MenuItem::List::iterator check_iter = items.begin();
537 MenuItem::List::iterator insert_iter = items.begin();
538
539 while (check_iter != items.end()) {
540 int item_webview_instance_id = (*check_iter)->id().webview_instance_id;
541 if (item_webview_instance_id != webview_instance_id) {
542 *insert_iter = *check_iter;
543 ++insert_iter;
544 } else {
545 delete *check_iter;
546 }
547 ++check_iter;
548 }
549
550 // Shrink.
551 items.resize(insert_iter - items.begin());
552 if (!items.size())
553 context_items_.erase(extension_id);
554 }
555
512 void MenuManager::RemoveAllContextItems(const std::string& extension_id) { 556 void MenuManager::RemoveAllContextItems(const std::string& extension_id) {
513 MenuItem::List::iterator i; 557 MenuItem::List::iterator i;
514 for (i = context_items_[extension_id].begin(); 558 for (i = context_items_[extension_id].begin();
515 i != context_items_[extension_id].end(); ++i) { 559 i != context_items_[extension_id].end(); ++i) {
516 MenuItem* item = *i; 560 MenuItem* item = *i;
517 items_by_id_.erase(item->id()); 561 items_by_id_.erase(item->id());
518 562
519 // Remove descendants from this item and erase them from the lookup cache. 563 // Remove descendants from this item and erase them from the lookup cache.
520 std::set<MenuItem::Id> removed_ids = item->RemoveAllDescendants(); 564 std::set<MenuItem::Id> removed_ids = item->RemoveAllDescendants();
521 std::set<MenuItem::Id>::const_iterator j; 565 std::set<MenuItem::Id>::const_iterator j;
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
639 AddURLProperty(properties, "linkUrl", params.unfiltered_link_url); 683 AddURLProperty(properties, "linkUrl", params.unfiltered_link_url);
640 AddURLProperty(properties, "srcUrl", params.src_url); 684 AddURLProperty(properties, "srcUrl", params.src_url);
641 AddURLProperty(properties, "pageUrl", params.page_url); 685 AddURLProperty(properties, "pageUrl", params.page_url);
642 AddURLProperty(properties, "frameUrl", params.frame_url); 686 AddURLProperty(properties, "frameUrl", params.frame_url);
643 687
644 if (params.selection_text.length() > 0) 688 if (params.selection_text.length() > 0)
645 properties->SetString("selectionText", params.selection_text); 689 properties->SetString("selectionText", params.selection_text);
646 690
647 properties->SetBoolean("editable", params.is_editable); 691 properties->SetBoolean("editable", params.is_editable);
648 692
693 GuestView* guest_view = GuestView::FromWebContents(web_contents);
694 if (guest_view)
695 properties->SetInteger("webviewInstanceId", guest_view->view_instance_id());
Fady Samuel 2014/03/04 01:56:46 What is this?
lazyboy 2014/03/04 16:11:31 This is a property on the onClick event.
Fady Samuel 2014/03/04 16:36:00 Is this visible to the developer? What's it used f
lazyboy 2014/03/04 20:50:24 Yes. This is to indicate which webview the event c
lazyboy 2014/03/04 21:13:49 As discussed offline, I've removed exposing webvie
696
649 args->Append(properties); 697 args->Append(properties);
650 698
651 // Add the tab info to the argument list. 699 // Add the tab info to the argument list.
652 // No tab info in a platform app. 700 // No tab info in a platform app.
653 if (!extension || !extension->is_platform_app()) { 701 if (!extension || !extension->is_platform_app()) {
654 // Note: web_contents are NULL in unit tests :( 702 // Note: web_contents are NULL in unit tests :(
655 if (web_contents) { 703 if (web_contents) {
656 args->Append(ExtensionTabUtil::CreateTabValue(web_contents)); 704 args->Append(ExtensionTabUtil::CreateTabValue(web_contents));
657 } else { 705 } else {
658 args->Append(new base::DictionaryValue()); 706 args->Append(new base::DictionaryValue());
(...skipping 17 matching lines...) Expand all
676 WriteToStorage(extension); 724 WriteToStorage(extension);
677 } 725 }
678 726
679 // Note: web_contents are NULL in unit tests :( 727 // Note: web_contents are NULL in unit tests :(
680 if (web_contents && extensions::TabHelper::FromWebContents(web_contents)) { 728 if (web_contents && extensions::TabHelper::FromWebContents(web_contents)) {
681 extensions::TabHelper::FromWebContents(web_contents)-> 729 extensions::TabHelper::FromWebContents(web_contents)->
682 active_tab_permission_granter()->GrantIfRequested(extension); 730 active_tab_permission_granter()->GrantIfRequested(extension);
683 } 731 }
684 732
685 { 733 {
734 // Dispatch to menu item's .onclick handler.
686 scoped_ptr<Event> event(new Event( 735 scoped_ptr<Event> event(new Event(
687 event_names::kOnContextMenus, 736 event_names::kOnContextMenus,
688 scoped_ptr<base::ListValue>(args->DeepCopy()))); 737 scoped_ptr<base::ListValue>(args->DeepCopy())));
689 event->restrict_to_browser_context = profile; 738 event->restrict_to_browser_context = profile;
690 event->user_gesture = EventRouter::USER_GESTURE_ENABLED; 739 event->user_gesture = EventRouter::USER_GESTURE_ENABLED;
691 event_router->DispatchEventToExtension(item->extension_id(), event.Pass()); 740 event_router->DispatchEventToExtension(item->extension_id(), event.Pass());
692 } 741 }
693 { 742 {
694 scoped_ptr<Event> event(new Event(context_menus::OnClicked::kEventName, 743 // Dispatch to .contextMenus.onClicked handler.
695 args.Pass())); 744 scoped_ptr<Event> event(
745 new Event(guest_view ? event_names::kOnWebviewContextMenus
746 : context_menus::OnClicked::kEventName,
747 args.Pass()));
696 event->restrict_to_browser_context = profile; 748 event->restrict_to_browser_context = profile;
697 event->user_gesture = EventRouter::USER_GESTURE_ENABLED; 749 event->user_gesture = EventRouter::USER_GESTURE_ENABLED;
750 if (guest_view)
751 event->filter_info.SetInstanceID(guest_view->view_instance_id());
698 event_router->DispatchEventToExtension(item->extension_id(), event.Pass()); 752 event_router->DispatchEventToExtension(item->extension_id(), event.Pass());
699 } 753 }
700 } 754 }
701 755
702 void MenuManager::SanitizeRadioList(const MenuItem::List& item_list) { 756 void MenuManager::SanitizeRadioList(const MenuItem::List& item_list) {
703 MenuItem::List::const_iterator i = item_list.begin(); 757 MenuItem::List::const_iterator i = item_list.begin();
704 while (i != item_list.end()) { 758 while (i != item_list.end()) {
705 if ((*i)->type() != MenuItem::RADIO) { 759 if ((*i)->type() != MenuItem::RADIO) {
706 ++i; 760 ++i;
707 break; 761 break;
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
756 } 810 }
757 811
758 void MenuManager::WriteToStorage(const Extension* extension) { 812 void MenuManager::WriteToStorage(const Extension* extension) {
759 if (!BackgroundInfo::HasLazyBackgroundPage(extension)) 813 if (!BackgroundInfo::HasLazyBackgroundPage(extension))
760 return; 814 return;
761 const MenuItem::List* top_items = MenuItems(extension->id()); 815 const MenuItem::List* top_items = MenuItems(extension->id());
762 MenuItem::List all_items; 816 MenuItem::List all_items;
763 if (top_items) { 817 if (top_items) {
764 for (MenuItem::List::const_iterator i = top_items->begin(); 818 for (MenuItem::List::const_iterator i = top_items->begin();
765 i != top_items->end(); ++i) { 819 i != top_items->end(); ++i) {
820 if ((*i)->id().webview_instance_id)
821 continue;
766 (*i)->GetFlattenedSubtree(&all_items); 822 (*i)->GetFlattenedSubtree(&all_items);
767 } 823 }
768 } 824 }
769 825
770 if (store_) 826 if (store_) {
771 store_->SetExtensionValue(extension->id(), kContextMenusKey, 827 store_->SetExtensionValue(extension->id(), kContextMenusKey,
772 MenuItemsToValue(all_items)); 828 MenuItemsToValue(all_items));
829 }
773 } 830 }
774 831
775 void MenuManager::ReadFromStorage(const std::string& extension_id, 832 void MenuManager::ReadFromStorage(const std::string& extension_id,
776 scoped_ptr<base::Value> value) { 833 scoped_ptr<base::Value> value) {
777 const Extension* extension = 834 const Extension* extension =
778 ExtensionSystem::Get(profile_)->extension_service()->extensions()-> 835 ExtensionSystem::Get(profile_)->extension_service()->extensions()->
779 GetByID(extension_id); 836 GetByID(extension_id);
780 if (!extension) 837 if (!extension)
781 return; 838 return;
782 839
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
852 items_to_remove.insert(iter->first); 909 items_to_remove.insert(iter->first);
853 } 910 }
854 911
855 std::set<MenuItem::Id>::iterator remove_iter; 912 std::set<MenuItem::Id>::iterator remove_iter;
856 for (remove_iter = items_to_remove.begin(); 913 for (remove_iter = items_to_remove.begin();
857 remove_iter != items_to_remove.end(); 914 remove_iter != items_to_remove.end();
858 ++remove_iter) 915 ++remove_iter)
859 RemoveContextMenuItem(*remove_iter); 916 RemoveContextMenuItem(*remove_iter);
860 } 917 }
861 918
862 MenuItem::Id::Id() : incognito(false), uid(0) {} 919 MenuItem::Id::Id() : incognito(false), uid(0), webview_instance_id(0) {}
863 920
864 MenuItem::Id::Id(bool incognito, const std::string& extension_id) 921 MenuItem::Id::Id(bool incognito, const std::string& extension_id)
865 : incognito(incognito), extension_id(extension_id), uid(0) {} 922 : incognito(incognito),
923 extension_id(extension_id),
924 uid(0),
925 webview_instance_id(0) {}
866 926
867 MenuItem::Id::~Id() { 927 MenuItem::Id::~Id() {
868 } 928 }
869 929
870 bool MenuItem::Id::operator==(const Id& other) const { 930 bool MenuItem::Id::operator==(const Id& other) const {
871 return (incognito == other.incognito && 931 return (incognito == other.incognito && extension_id == other.extension_id &&
872 extension_id == other.extension_id && 932 uid == other.uid && string_uid == other.string_uid &&
873 uid == other.uid && 933 webview_instance_id == other.webview_instance_id);
874 string_uid == other.string_uid);
875 } 934 }
876 935
877 bool MenuItem::Id::operator!=(const Id& other) const { 936 bool MenuItem::Id::operator!=(const Id& other) const {
878 return !(*this == other); 937 return !(*this == other);
879 } 938 }
880 939
881 bool MenuItem::Id::operator<(const Id& other) const { 940 bool MenuItem::Id::operator<(const Id& other) const {
882 if (incognito < other.incognito) 941 if (incognito < other.incognito)
883 return true; 942 return true;
884 if (incognito == other.incognito) { 943 if (incognito == other.incognito) {
885 if (extension_id < other.extension_id) 944 if (extension_id < other.extension_id)
886 return true; 945 return true;
887 if (extension_id == other.extension_id) { 946 if (extension_id == other.extension_id) {
888 if (uid < other.uid) 947 if (webview_instance_id < other.webview_instance_id)
889 return true; 948 return true;
890 if (uid == other.uid) 949
891 return string_uid < other.string_uid; 950 if (webview_instance_id == other.webview_instance_id) {
951 if (uid < other.uid)
952 return true;
953 if (uid == other.uid)
954 return string_uid < other.string_uid;
955 }
892 } 956 }
893 } 957 }
894 return false; 958 return false;
895 } 959 }
896 960
897 } // namespace extensions 961 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698