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

Side by Side Diff: third_party/WebKit/Source/core/page/CustomContextMenuProvider.cpp

Issue 2905763003: Rollback ContextMenu (Closed)
Patch Set: Delete icon-related code from ContextMenuItem class Created 3 years, 6 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
(Empty)
1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "core/page/CustomContextMenuProvider.h"
6
7 #include "core/dom/Document.h"
8 #include "core/dom/ElementTraversal.h"
9 #include "core/events/EventDispatcher.h"
10 #include "core/events/MouseEvent.h"
11 #include "core/html/HTMLMenuElement.h"
12 #include "core/html/HTMLMenuItemElement.h"
13 #include "core/page/ContextMenuController.h"
14 #include "core/page/Page.h"
15 #include "platform/ContextMenu.h"
16
17 namespace blink {
18
19 using namespace HTMLNames;
20
21 CustomContextMenuProvider::CustomContextMenuProvider(HTMLMenuElement& menu,
22 HTMLElement& subject)
23 : menu_(menu), subject_element_(subject) {}
24
25 CustomContextMenuProvider::~CustomContextMenuProvider() {}
26
27 DEFINE_TRACE(CustomContextMenuProvider) {
28 visitor->Trace(menu_);
29 visitor->Trace(subject_element_);
30 visitor->Trace(menu_items_);
31 ContextMenuProvider::Trace(visitor);
32 }
33
34 void CustomContextMenuProvider::PopulateContextMenu(ContextMenu* menu) {
35 PopulateContextMenuItems(*menu_, *menu);
36 }
37
38 void CustomContextMenuProvider::ContextMenuItemSelected(
39 const ContextMenuItem* item) {
40 if (HTMLElement* element = MenuItemAt(item->Action())) {
41 MouseEvent* click = MouseEvent::Create(
42 EventTypeNames::click, menu_->GetDocument().domWindow(),
43 Event::Create(), SimulatedClickCreationScope::kFromUserAgent);
44 click->SetRelatedTarget(subject_element_.Get());
45 element->DispatchEvent(click);
46 }
47 }
48
49 void CustomContextMenuProvider::ContextMenuCleared() {
50 menu_items_.clear();
51 subject_element_ = nullptr;
52 }
53
54 void CustomContextMenuProvider::AppendSeparator(ContextMenu& context_menu) {
55 // Avoid separators at the start of any menu and submenu.
56 if (!context_menu.Items().size())
57 return;
58
59 // Collapse all sequences of two or more adjacent separators in the menu or
60 // any submenus to a single separator.
61 ContextMenuItem last_item = context_menu.Items().back();
62 if (last_item.GetType() == kSeparatorType)
63 return;
64
65 context_menu.AppendItem(ContextMenuItem(
66 kSeparatorType, kContextMenuItemCustomTagNoAction, String(), String()));
67 }
68
69 void CustomContextMenuProvider::AppendMenuItem(HTMLMenuItemElement* menu_item,
70 ContextMenu& context_menu) {
71 // Avoid menuitems with no label.
72 String label_string = menu_item->label();
73 if (label_string.IsEmpty())
74 return;
75
76 menu_items_.push_back(menu_item);
77
78 bool enabled = !menu_item->FastHasAttribute(disabledAttr);
79 String icon = menu_item->FastGetAttribute(iconAttr);
80 if (!icon.IsEmpty()) {
81 // To obtain the absolute URL of the icon when the attribute's value is not
82 // the empty string, the attribute's value must be resolved relative to the
83 // element.
84 KURL icon_url = KURL(menu_item->baseURI(), icon);
85 icon = icon_url.GetString();
86 }
87 ContextMenuAction action = static_cast<ContextMenuAction>(
88 kContextMenuItemBaseCustomTag + menu_items_.size() - 1);
89 if (DeprecatedEqualIgnoringCase(menu_item->FastGetAttribute(typeAttr),
90 "checkbox") ||
91 DeprecatedEqualIgnoringCase(menu_item->FastGetAttribute(typeAttr),
92 "radio"))
93 context_menu.AppendItem(
94 ContextMenuItem(kCheckableActionType, action, label_string, icon,
95 enabled, menu_item->FastHasAttribute(checkedAttr)));
96 else
97 context_menu.AppendItem(ContextMenuItem(kActionType, action, label_string,
98 icon, enabled, false));
99 }
100
101 void CustomContextMenuProvider::PopulateContextMenuItems(
102 const HTMLMenuElement& menu,
103 ContextMenu& context_menu) {
104 HTMLElement* next_element = Traversal<HTMLElement>::FirstWithin(menu);
105 while (next_element) {
106 if (isHTMLHRElement(*next_element)) {
107 AppendSeparator(context_menu);
108 next_element = Traversal<HTMLElement>::Next(*next_element, &menu);
109 } else if (isHTMLMenuElement(*next_element)) {
110 ContextMenu sub_menu;
111 String label_string = next_element->FastGetAttribute(labelAttr);
112 if (label_string.IsNull()) {
113 AppendSeparator(context_menu);
114 PopulateContextMenuItems(*toHTMLMenuElement(next_element),
115 context_menu);
116 AppendSeparator(context_menu);
117 } else if (!label_string.IsEmpty()) {
118 PopulateContextMenuItems(*toHTMLMenuElement(next_element), sub_menu);
119 context_menu.AppendItem(
120 ContextMenuItem(kSubmenuType, kContextMenuItemCustomTagNoAction,
121 label_string, String(), &sub_menu));
122 }
123 next_element = Traversal<HTMLElement>::NextSibling(*next_element);
124 } else if (isHTMLMenuItemElement(*next_element)) {
125 AppendMenuItem(toHTMLMenuItemElement(next_element), context_menu);
126 if (kContextMenuItemBaseCustomTag + menu_items_.size() >=
127 kContextMenuItemLastCustomTag)
128 break;
129 next_element = Traversal<HTMLElement>::Next(*next_element, &menu);
130 } else {
131 next_element = Traversal<HTMLElement>::Next(*next_element, &menu);
132 }
133 }
134
135 // Remove separators at the end of the menu and any submenus.
136 while (context_menu.Items().size() &&
137 context_menu.Items().back().GetType() == kSeparatorType)
138 context_menu.RemoveLastItem();
139 }
140
141 HTMLElement* CustomContextMenuProvider::MenuItemAt(unsigned menu_id) {
142 int item_index = menu_id - kContextMenuItemBaseCustomTag;
143 if (item_index < 0 ||
144 static_cast<unsigned long>(item_index) >= menu_items_.size())
145 return nullptr;
146 return menu_items_[item_index].Get();
147 }
148
149 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698