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

Unified Diff: ios/web/web_state/js/resources/context_menu.js

Issue 2800003002: Pull context menu related APIs from core.js to their own file. (Closed)
Patch Set: git squash commit for context-menu. Created 3 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « ios/web/BUILD.gn ('k') | ios/web/web_state/js/resources/core.js » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ios/web/web_state/js/resources/context_menu.js
diff --git a/ios/web/web_state/js/resources/context_menu.js b/ios/web/web_state/js/resources/context_menu.js
new file mode 100644
index 0000000000000000000000000000000000000000..ffd654bc361ad3ac54019befef6a87f13cc96606
--- /dev/null
+++ b/ios/web/web_state/js/resources/context_menu.js
@@ -0,0 +1,269 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @fileoverview APIs used by CRWContextMenuController.
+ */
+
+goog.provide('__crWeb.contextMenu');
+
+/** Beginning of anonymous object */
+(function() {
+
+ /**
+ * Returns the url of the image or link under the selected point. Returns an
+ * empty string if no links or images are found.
+ * @param {number} x Horizontal center of the selected point.
+ * @param {number} y Vertical center of the selected point.
+ * @return {!Object} An object of the form {
+ * href, // URL of the link under the point
+ * innerText, // innerText of the link, if the selected element is a link
+ * src, // src of the image, if the selected element is an image
+ * title, // title of the image, if the selected
+ * referrerPolicy
+ * }
+ * where:
+ * <ul>
+ * <li>href, innerText are set if the selected element is a link.
+ * <li>src, title are set if the selected element is an image.
+ * <li>href is also set if the selected element is an image with a link.
+ * <li>referrerPolicy is the referrer policy to use for navigations away
+ * from the current page.
+ * </ul>
+ */
+ __gCrWeb['getElementFromPoint'] = function(x, y) {
+ var hitCoordinates = spiralCoordinates_(x, y);
+ for (var index = 0; index < hitCoordinates.length; index++) {
+ var coordinates = hitCoordinates[index];
+
+ var element = elementFromPoint_(coordinates.x, coordinates.y);
+ if (!element || !element.tagName) {
+ // Nothing under the hit point. Try the next hit point.
+ continue;
+ }
+
+ if (getComputedWebkitTouchCallout_(element) === 'none')
+ continue;
+ // Also check element's ancestors. A bound on the level is used here to
+ // avoid large overhead when no links or images are found.
+ var level = 0;
+ while (++level < 8 && element && element != document) {
+ var tagName = element.tagName;
+ if (!tagName)
+ continue;
+ tagName = tagName.toLowerCase();
+
+ if (tagName === 'input' || tagName === 'textarea' ||
+ tagName === 'select' || tagName === 'option') {
+ // If the element is a known input element, stop the spiral search and
+ // return empty results.
+ return {};
+ }
+
+ if (tagName === 'a' && element.href) {
+ // Found a link.
+ return {
+ href: element.href,
+ 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;
+ 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;
+ }
+ parent = parent.parentNode;
+ }
+ return result;
+ }
+ element = element.parentNode;
+ }
+ }
+ return {};
+ };
+
+ /**
+ * Suppresses the next click such that they are not handled by JS click
+ * event handlers.
+ * @type {void}
+ */
+ __gCrWeb['suppressNextClick'] = function() {
+ var suppressNextClick = function(evt) {
+ evt.preventDefault();
+ document.removeEventListener('click', suppressNextClick, false);
+ };
+ document.addEventListener('click', suppressNextClick);
+ };
+
+ /**
+ * Returns the margin in points around touchable elements (e.g. links for
+ * custom context menu).
+ * @type {number}
+ */
+ __gCrWeb['getPageWidth'] = function() {
+ var documentElement = document.documentElement;
+ var documentBody = document.body;
+ return Math.max(documentElement.clientWidth,
+ documentElement.scrollWidth,
+ documentElement.offsetWidth,
+ documentBody.scrollWidth,
+ documentBody.offsetWidth);
+ };
+
+ /**
+ * Implementation of document.elementFromPoint that is working for iOS4 and
+ * iOS5 and that also goes into frames and iframes.
+ * @private
+ */
+ var elementFromPoint_ = function(x, y) {
+ var elementFromPointIsUsingViewPortCoordinates = function(win) {
+ if (win.pageYOffset > 0) { // Page scrolled down.
+ return (win.document.elementFromPoint(
+ 0, win.pageYOffset + win.innerHeight - 1) === null);
+ }
+ if (win.pageXOffset > 0) { // Page scrolled to the right.
+ return (win.document.elementFromPoint(
+ win.pageXOffset + win.innerWidth - 1, 0) === null);
+ }
+ return false; // No scrolling, don't care.
+ };
+
+ var newCoordinate = function(x, y) {
+ var coordinates = {
+ x: x, y: y,
+ viewPortX: x - window.pageXOffset, viewPortY: y - window.pageYOffset,
+ useViewPortCoordinates: false,
+ window: window
+ };
+ return coordinates;
+ };
+
+ // Returns the coordinates of the upper left corner of |obj| in the
+ // coordinates of the window that |obj| is in.
+ var getPositionInWindow = function(obj) {
+ var coord = { x: 0, y: 0 };
+ while (obj.offsetParent) {
+ coord.x += obj.offsetLeft;
+ coord.y += obj.offsetTop;
+ obj = obj.offsetParent;
+ }
+ return coord;
+ };
+
+ var elementsFromCoordinates = function(coordinates) {
+ coordinates.useViewPortCoordinates = coordinates.useViewPortCoordinates ||
+ elementFromPointIsUsingViewPortCoordinates(coordinates.window);
+
+ var currentElement = null;
+ if (coordinates.useViewPortCoordinates) {
+ currentElement = coordinates.window.document.elementFromPoint(
+ coordinates.viewPortX, coordinates.viewPortY);
+ } else {
+ currentElement = coordinates.window.document.elementFromPoint(
+ coordinates.x, coordinates.y);
+ }
+ // We have to check for tagName, because if a selection is made by the
+ // UIWebView, the element we will get won't have one.
+ if (!currentElement || !currentElement.tagName) {
+ return null;
+ }
+ if (currentElement.tagName.toLowerCase() === 'iframe' ||
+ currentElement.tagName.toLowerCase() === 'frame') {
+ // The following condition is true if the iframe is in a different
+ // domain; no further information is accessible.
+ if (typeof(currentElement.contentWindow.document) == 'undefined') {
+ return currentElement;
+ }
+ var framePosition = getPositionInWindow(currentElement);
+ coordinates.viewPortX -=
+ framePosition.x - coordinates.window.pageXOffset;
+ coordinates.viewPortY -=
+ framePosition.y - coordinates.window.pageYOffset;
+ coordinates.window = currentElement.contentWindow;
+ coordinates.x -= framePosition.x + coordinates.window.pageXOffset;
+ coordinates.y -= framePosition.y + coordinates.window.pageYOffset;
+ return elementsFromCoordinates(coordinates);
+ }
+ return currentElement;
+ };
+
+ return elementsFromCoordinates(newCoordinate(x, y));
+ };
+
+ /** @private */
+ var spiralCoordinates_ = function(x, y) {
+ var MAX_ANGLE = Math.PI * 2.0 * 3.0;
+ var POINT_COUNT = 30;
+ var ANGLE_STEP = MAX_ANGLE / POINT_COUNT;
+ var TOUCH_MARGIN = 25;
+ var SPEED = TOUCH_MARGIN / MAX_ANGLE;
+
+ var coordinates = [];
+ for (var index = 0; index < POINT_COUNT; index++) {
+ var angle = ANGLE_STEP * index;
+ var radius = angle * SPEED;
+
+ coordinates.push({x: x + Math.round(Math.cos(angle) * radius),
+ y: y + Math.round(Math.sin(angle) * radius)});
+ }
+
+ return coordinates;
+ };
+
+ /** @private */
+ var getComputedWebkitTouchCallout_ = function(element) {
+ return window.getComputedStyle(element, null)['webkitTouchCallout'];
+ };
+
+ /**
+ * Gets the referrer policy to use for navigations away from the current page.
+ * If a link element is passed, and it includes a rel=noreferrer tag, that
+ * will override the page setting.
+ * @param {HTMLElement=} opt_linkElement The link triggering the navigation.
+ * @return {string} The policy string.
+ * @private
+ */
+ var getReferrerPolicy_ = function(opt_linkElement) {
+ if (opt_linkElement) {
+ var rel = opt_linkElement.getAttribute('rel');
+ if (rel && rel.toLowerCase() == 'noreferrer') {
+ return 'never';
+ }
+ }
+
+ var metaTags = document.getElementsByTagName('meta');
+ for (var i = 0; i < metaTags.length; ++i) {
+ if (metaTags[i].name.toLowerCase() == 'referrer') {
+ return metaTags[i].content.toLowerCase();
+ }
+ }
+ return 'default';
+ };
+
+}()); // End of anonymouse object
« no previous file with comments | « ios/web/BUILD.gn ('k') | ios/web/web_state/js/resources/core.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698