| OLD | NEW |
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 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 | 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 "config.h" | 5 #include "config.h" |
| 6 #include "core/page/CustomContextMenuProvider.h" | 6 #include "core/page/CustomContextMenuProvider.h" |
| 7 | 7 |
| 8 #include "core/dom/Document.h" | 8 #include "core/dom/Document.h" |
| 9 #include "core/dom/ElementTraversal.h" | 9 #include "core/dom/ElementTraversal.h" |
| 10 #include "core/events/EventDispatcher.h" | 10 #include "core/events/EventDispatcher.h" |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 62 // Avoid separators at the start of any menu and submenu. | 62 // Avoid separators at the start of any menu and submenu. |
| 63 if (!contextMenu.items().size()) | 63 if (!contextMenu.items().size()) |
| 64 return; | 64 return; |
| 65 | 65 |
| 66 // Collapse all sequences of two or more adjacent separators in the menu or | 66 // Collapse all sequences of two or more adjacent separators in the menu or |
| 67 // any submenus to a single separator. | 67 // any submenus to a single separator. |
| 68 ContextMenuItem lastItem = contextMenu.items().last(); | 68 ContextMenuItem lastItem = contextMenu.items().last(); |
| 69 if (lastItem.type() == SeparatorType) | 69 if (lastItem.type() == SeparatorType) |
| 70 return; | 70 return; |
| 71 | 71 |
| 72 contextMenu.appendItem(ContextMenuItem(SeparatorType, ContextMenuItemCustomT
agNoAction, String())); | 72 contextMenu.appendItem(ContextMenuItem(SeparatorType, ContextMenuItemCustomT
agNoAction, String(), String())); |
| 73 } | 73 } |
| 74 | 74 |
| 75 void CustomContextMenuProvider::appendMenuItem(HTMLMenuItemElement* menuItem, Co
ntextMenu& contextMenu) | 75 void CustomContextMenuProvider::appendMenuItem(HTMLMenuItemElement* menuItem, Co
ntextMenu& contextMenu) |
| 76 { | 76 { |
| 77 // Avoid menuitems with no label. | 77 // Avoid menuitems with no label. |
| 78 String labelString = menuItem->fastGetAttribute(labelAttr); | 78 String labelString = menuItem->fastGetAttribute(labelAttr); |
| 79 if (labelString.isEmpty()) | 79 if (labelString.isEmpty()) |
| 80 return; | 80 return; |
| 81 | 81 |
| 82 m_menuItems.append(menuItem); | 82 m_menuItems.append(menuItem); |
| 83 | 83 |
| 84 bool enabled = !menuItem->fastHasAttribute(disabledAttr); | 84 bool enabled = !menuItem->fastHasAttribute(disabledAttr); |
| 85 String icon = menuItem->fastGetAttribute(iconAttr); |
| 86 if (!icon.isEmpty()) { |
| 87 // To obtain the absolute URL of the icon when the attribute's value is
not the empty string, |
| 88 // the attribute's value must be resolved relative to the element. |
| 89 KURL iconURL = KURL(menuItem->baseURI(), icon); |
| 90 icon = iconURL.string(); |
| 91 } |
| 85 ContextMenuAction action = static_cast<ContextMenuAction>(ContextMenuItemBas
eCustomTag + m_menuItems.size() - 1); | 92 ContextMenuAction action = static_cast<ContextMenuAction>(ContextMenuItemBas
eCustomTag + m_menuItems.size() - 1); |
| 86 if (equalIgnoringCase(menuItem->fastGetAttribute(typeAttr), "checkbox") || e
qualIgnoringCase(menuItem->fastGetAttribute(typeAttr), "radio")) | 93 if (equalIgnoringCase(menuItem->fastGetAttribute(typeAttr), "checkbox") || e
qualIgnoringCase(menuItem->fastGetAttribute(typeAttr), "radio")) |
| 87 contextMenu.appendItem(ContextMenuItem(CheckableActionType, action, labe
lString, enabled, menuItem->fastHasAttribute(checkedAttr))); | 94 contextMenu.appendItem(ContextMenuItem(CheckableActionType, action, labe
lString, icon, enabled, menuItem->fastHasAttribute(checkedAttr))); |
| 88 else | 95 else |
| 89 contextMenu.appendItem(ContextMenuItem(ActionType, action, labelString,
enabled, false)); | 96 contextMenu.appendItem(ContextMenuItem(ActionType, action, labelString,
icon, enabled, false)); |
| 90 } | 97 } |
| 91 | 98 |
| 92 void CustomContextMenuProvider::populateContextMenuItems(const HTMLMenuElement&
menu, ContextMenu& contextMenu) | 99 void CustomContextMenuProvider::populateContextMenuItems(const HTMLMenuElement&
menu, ContextMenu& contextMenu) |
| 93 { | 100 { |
| 94 HTMLElement* nextElement = Traversal<HTMLElement>::firstWithin(menu); | 101 HTMLElement* nextElement = Traversal<HTMLElement>::firstWithin(menu); |
| 95 while (nextElement) { | 102 while (nextElement) { |
| 96 if (isHTMLHRElement(*nextElement)) { | 103 if (isHTMLHRElement(*nextElement)) { |
| 97 appendSeparator(contextMenu); | 104 appendSeparator(contextMenu); |
| 98 nextElement = Traversal<HTMLElement>::next(*nextElement, &menu); | 105 nextElement = Traversal<HTMLElement>::next(*nextElement, &menu); |
| 99 } else if (isHTMLMenuElement(*nextElement)) { | 106 } else if (isHTMLMenuElement(*nextElement)) { |
| 100 ContextMenu subMenu; | 107 ContextMenu subMenu; |
| 101 String labelString = nextElement->fastGetAttribute(labelAttr); | 108 String labelString = nextElement->fastGetAttribute(labelAttr); |
| 102 if (labelString.isNull()) { | 109 if (labelString.isNull()) { |
| 103 appendSeparator(contextMenu); | 110 appendSeparator(contextMenu); |
| 104 populateContextMenuItems(*toHTMLMenuElement(nextElement), contex
tMenu); | 111 populateContextMenuItems(*toHTMLMenuElement(nextElement), contex
tMenu); |
| 105 appendSeparator(contextMenu); | 112 appendSeparator(contextMenu); |
| 106 } else if (!labelString.isEmpty()) { | 113 } else if (!labelString.isEmpty()) { |
| 107 populateContextMenuItems(*toHTMLMenuElement(nextElement), subMen
u); | 114 populateContextMenuItems(*toHTMLMenuElement(nextElement), subMen
u); |
| 108 contextMenu.appendItem(ContextMenuItem(SubmenuType, ContextMenuI
temCustomTagNoAction, labelString, &subMenu)); | 115 contextMenu.appendItem(ContextMenuItem(SubmenuType, ContextMenuI
temCustomTagNoAction, labelString, String(), &subMenu)); |
| 109 } | 116 } |
| 110 nextElement = Traversal<HTMLElement>::nextSibling(*nextElement); | 117 nextElement = Traversal<HTMLElement>::nextSibling(*nextElement); |
| 111 } else if (isHTMLMenuItemElement(*nextElement)) { | 118 } else if (isHTMLMenuItemElement(*nextElement)) { |
| 112 appendMenuItem(toHTMLMenuItemElement(nextElement), contextMenu); | 119 appendMenuItem(toHTMLMenuItemElement(nextElement), contextMenu); |
| 113 if (ContextMenuItemBaseCustomTag + m_menuItems.size() >= ContextMenu
ItemLastCustomTag) | 120 if (ContextMenuItemBaseCustomTag + m_menuItems.size() >= ContextMenu
ItemLastCustomTag) |
| 114 break; | 121 break; |
| 115 nextElement = Traversal<HTMLElement>::next(*nextElement, &menu); | 122 nextElement = Traversal<HTMLElement>::next(*nextElement, &menu); |
| 116 } else { | 123 } else { |
| 117 nextElement = Traversal<HTMLElement>::next(*nextElement, &menu); | 124 nextElement = Traversal<HTMLElement>::next(*nextElement, &menu); |
| 118 } | 125 } |
| 119 } | 126 } |
| 120 | 127 |
| 121 // Remove separators at the end of the menu and any submenus. | 128 // Remove separators at the end of the menu and any submenus. |
| 122 while (contextMenu.items().size() && contextMenu.items().last().type() == Se
paratorType) | 129 while (contextMenu.items().size() && contextMenu.items().last().type() == Se
paratorType) |
| 123 contextMenu.removeLastItem(); | 130 contextMenu.removeLastItem(); |
| 124 } | 131 } |
| 125 | 132 |
| 126 HTMLElement* CustomContextMenuProvider::menuItemAt(unsigned menuId) | 133 HTMLElement* CustomContextMenuProvider::menuItemAt(unsigned menuId) |
| 127 { | 134 { |
| 128 int itemIndex = menuId - ContextMenuItemBaseCustomTag; | 135 int itemIndex = menuId - ContextMenuItemBaseCustomTag; |
| 129 if (itemIndex < 0 || static_cast<unsigned long>(itemIndex) >= m_menuItems.si
ze()) | 136 if (itemIndex < 0 || static_cast<unsigned long>(itemIndex) >= m_menuItems.si
ze()) |
| 130 return nullptr; | 137 return nullptr; |
| 131 return m_menuItems[itemIndex].get(); | 138 return m_menuItems[itemIndex].get(); |
| 132 } | 139 } |
| 133 | 140 |
| 134 } // namespace blink | 141 } // namespace blink |
| OLD | NEW |