Commit 1e1006ab authored by Eugene But's avatar Eugene But Committed by Commit Bot

Fixed context menu handling for -webkit-touch-callout styled elements.

Context menu is sometimes invoked for parent elements. f.e. a link can
be a parent element of an image and even though user has pressed on the
image, context menu is still shown for link, not for image.

This CL checks -webkit-touch-callout style on element it is about to
present a menu for (which can be a parent). Before the change
-webkit-touch-callout was always checked for a parent causing system
context menu to show up.

Bug: 736480
Change-Id: I9239d75a1bfd9926dd67d1c742763c56837b0c38
Reviewed-on: https://chromium-review.googlesource.com/578215
Commit-Queue: Eugene But <eugenebut@chromium.org>
Reviewed-by: default avatarMike Dougherty <michaeldo@chromium.org>
Cr-Commit-Position: refs/heads/master@{#488423}
parent b2ffed36
...@@ -204,4 +204,24 @@ TEST_F(ContextMenuJsTest, LinkOfImage) { ...@@ -204,4 +204,24 @@ TEST_F(ContextMenuJsTest, LinkOfImage) {
} }
} }
// Tests context menu invoked on an image with "-webkit-touch-callout:none"
// style and parent link.
TEST_F(ContextMenuJsTest, LinkOfImageWithCalloutNone) {
// A page with an image surrounded by a link.
static const char image_html[] =
"<a href='%s'>"
"<img style='width:9;height:9;display:block;-webkit-touch-callout:none;'>"
"</a>";
// A page with a link to a destination URL.
LoadHtml(base::StringPrintf(image_html, "http://destination"));
id result = ExecuteGetElementFromPointJavaScript(5, 5);
NSDictionary* expected_result = @{
kContextMenuElementInnerText : @"",
kContextMenuElementReferrerPolicy : @"default",
kContextMenuElementHyperlink : @"http://destination/",
};
EXPECT_NSEQ(expected_result, result);
}
} // namespace web } // namespace web
...@@ -76,8 +76,6 @@ goog.provide('__crWeb.contextMenu'); ...@@ -76,8 +76,6 @@ goog.provide('__crWeb.contextMenu');
continue; continue;
} }
if (getComputedWebkitTouchCallout_(element) === 'none')
continue;
// Also check element's ancestors. A bound on the level is used here to // Also check element's ancestors. A bound on the level is used here to
// avoid large overhead when no links or images are found. // avoid large overhead when no links or images are found.
var level = 0; var level = 0;
...@@ -94,46 +92,48 @@ goog.provide('__crWeb.contextMenu'); ...@@ -94,46 +92,48 @@ goog.provide('__crWeb.contextMenu');
return {}; return {};
} }
if (tagName === 'a' && element.href) { if (getComputedWebkitTouchCallout_(element) !== 'none') {
// Found a link. if (tagName === 'a' && element.href) {
return { // Found a link.
href: element.href, return {
referrerPolicy: getReferrerPolicy_(element), href: element.href,
innerText: element.innerText referrerPolicy: getReferrerPolicy_(element),
}; innerText: element.innerText
} };
if (tagName === 'img' && element.src) {
// Found an image.
var result = {
src: element.src,
referrerPolicy: getReferrerPolicy_()
};
// Copy the title, if any.
if (element.title) {
result.title = element.title;
} }
// Check if the image is also a link.
var parent = element.parentNode; if (tagName === 'img' && element.src) {
while (parent) { // Found an image.
if (parent.tagName && var result = {
parent.tagName.toLowerCase() === 'a' && src: element.src,
parent.href) { referrerPolicy: getReferrerPolicy_()
// This regex identifies strings like void(0), };
// void(0) ;void(0);, ;;;; // Copy the title, if any.
// which result in a NOP when executed as JavaScript. if (element.title) {
var regex = RegExp("^javascript:(?:(?:void\\(0\\)|;)\\s*)+$"); result.title = element.title;
if (parent.href.match(regex)) { }
parent = parent.parentNode; // Check if the image is also a link.
continue; var parent = element.parentNode;
while (parent) {
if (parent.tagName &&
parent.tagName.toLowerCase() === 'a' &&
parent.href) {
// This regex identifies strings like void(0),
// void(0) ;void(0);, ;;;;
// which result in a NOP when executed as JavaScript.
var regex = RegExp("^javascript:(?:(?:void\\(0\\)|;)\\s*)+$");
if (parent.href.match(regex)) {
parent = parent.parentNode;
continue;
}
result.href = parent.href;
result.referrerPolicy = getReferrerPolicy_(parent);
break;
} }
result.href = parent.href; parent = parent.parentNode;
result.referrerPolicy = getReferrerPolicy_(parent);
break;
} }
parent = parent.parentNode; return result;
} }
return result;
} }
element = element.parentNode; element = element.parentNode;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment