| Index: ios/web/web_state/js/resources/core.js
|
| diff --git a/ios/web/web_state/js/resources/core.js b/ios/web/web_state/js/resources/core.js
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..5e5d0dd3376909a4e903206653c0511c5a1fc125
|
| --- /dev/null
|
| +++ b/ios/web/web_state/js/resources/core.js
|
| @@ -0,0 +1,646 @@
|
| +// Copyright 2012 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.
|
| +
|
| +// This file adheres to closure-compiler conventions in order to enable
|
| +// compilation with ADVANCED_OPTIMIZATIONS. In particular, members that are to
|
| +// be accessed externally should be specified in this['style'] as opposed to
|
| +// this.style because member identifiers are minified by default.
|
| +// See http://goo.gl/FwOgy
|
| +
|
| +goog.provide('__crweb.core');
|
| +
|
| +/**
|
| + * The Chrome object is populated in an anonymous object defined at
|
| + * initialization to prevent polluting the global namespace.
|
| + */
|
| +
|
| +/* Beginning of anonymous object. */
|
| +new function() {
|
| + // TODO(jimblackler): use this namespace as a wrapper for all externally-
|
| + // visible functions, to be consistent with other JS scripts. crbug.com/380390
|
| + __gCrWeb['core'] = {};
|
| +
|
| + // JavaScript errors are logged on the main application side. The handler is
|
| + // added ASAP to catch any errors in startup. Note this does not appear to
|
| + // work in iOS < 5.
|
| + window.addEventListener('error', function(event) {
|
| + // Sadly, event.filename and event.lineno are always 'undefined' and '0'
|
| + // with UIWebView.
|
| + invokeOnHost_({'command': 'window.error',
|
| + 'message': event.message.toString()});
|
| + });
|
| +
|
| + /**
|
| + * Margin in points around touchable elements (e.g. links for custom context
|
| + * menu).
|
| + * @type {number}
|
| + */
|
| + var touchMargin_ = 25;
|
| +
|
| + __gCrWeb['innerSizeAsString'] = function() {
|
| + return window.innerWidth + '/' + window.innerHeight;
|
| + };
|
| +
|
| + // Implementation of document.elementFromPoint that is working for iOS4 and
|
| + // iOS5 and that also goes into frames and iframes.
|
| + 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') {
|
| + invokeOnHost_({
|
| + 'command': 'window.error',
|
| + 'message': 'iframe contentWindow.document is not accessible.'});
|
| + 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));
|
| + };
|
| +
|
| + var spiralCoordinates = function(x, y) {
|
| + var coordinates = [];
|
| +
|
| + var maxAngle = Math.PI * 2.0 * 3.0;
|
| + var pointCount = 30;
|
| + var angleStep = maxAngle / pointCount;
|
| + var speed = touchMargin_ / maxAngle;
|
| +
|
| + for (var index = 0; index < pointCount; index++) {
|
| + var angle = angleStep * 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;
|
| + };
|
| +
|
| + // Returns the url of the image or link under the selected point. Returns an
|
| + // empty string if no links or images are found.
|
| + __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 __gCrWeb.common.JSONStringify(
|
| + {href: element.href,
|
| + referrerPolicy: getReferrerPolicy_(element)});
|
| + }
|
| +
|
| + 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 __gCrWeb.common.JSONStringify(result);
|
| + }
|
| + element = element.parentNode;
|
| + }
|
| + }
|
| + return '{}';
|
| + };
|
| +
|
| + // Returns true if the top window or any frames inside contain an input
|
| + // field of type 'password'.
|
| + __gCrWeb['hasPasswordField'] = function() {
|
| + return hasPasswordField_(window);
|
| + };
|
| +
|
| + // Returns a string that is formatted according to the JSON syntax rules.
|
| + // This is equivalent to the built-in JSON.stringify() function, but is
|
| + // less likely to be overridden by the website itself. This public function
|
| + // should not be used if spoofing it would create a security vulnerability.
|
| + // The |__gCrWeb| object itself does not use it; it uses its private
|
| + // counterpart instead.
|
| + // Prevents websites from changing stringify's behavior by adding the
|
| + // method toJSON() by temporarily removing it.
|
| + __gCrWeb['stringify'] = function(value) {
|
| + if (value === null)
|
| + return 'null';
|
| + if (value === undefined)
|
| + return undefined;
|
| + if (typeof(value.toJSON) == 'function') {
|
| + var originalToJSON = value.toJSON;
|
| + value.toJSON = undefined;
|
| + var stringifiedValue = __gCrWeb.common.JSONStringify(value);
|
| + value.toJSON = originalToJSON;
|
| + return stringifiedValue;
|
| + }
|
| + return __gCrWeb.common.JSONStringify(value);
|
| + };
|
| +
|
| + /*
|
| + * Adds the listeners that are used to handle forms, enabling autofill and
|
| + * the replacement method to dismiss the keyboard needed because of the
|
| + * Autofill keyboard accessory.
|
| + */
|
| + function addFormEventListeners_() {
|
| + // Focus and input events for form elements are messaged to the main
|
| + // application for broadcast to CRWWebControllerObservers.
|
| + // This is done with a single event handler for each type being added to the
|
| + // main document element which checks the source element of the event; this
|
| + // is much easier to manage than adding handlers to individual elements.
|
| + var formActivity = function(evt) {
|
| + var srcElement = evt.srcElement;
|
| + var fieldName = srcElement.name || '';
|
| + var value = srcElement.value || '';
|
| +
|
| + var msg = {
|
| + 'command': 'form.activity',
|
| + 'formName': __gCrWeb.common.getFormIdentifier(evt.srcElement.form),
|
| + 'fieldName': fieldName,
|
| + 'type': evt.type,
|
| + 'value': value
|
| + };
|
| + if (evt.keyCode)
|
| + msg.keyCode = evt.keyCode;
|
| + invokeOnHost_(msg);
|
| + };
|
| +
|
| + // Focus events performed on the 'capture' phase otherwise they are often
|
| + // not received.
|
| + document.addEventListener('focus', formActivity, true);
|
| + document.addEventListener('blur', formActivity, true);
|
| + document.addEventListener('change', formActivity, true);
|
| +
|
| + // Text input is watched at the bubbling phase as this seems adequate in
|
| + // practice and it is less obtrusive to page scripts than capture phase.
|
| + document.addEventListener('input', formActivity, false);
|
| + document.addEventListener('keyup', formActivity, false);
|
| + };
|
| +
|
| + // Returns true if the supplied window or any frames inside contain an input
|
| + // field of type 'password'.
|
| + // @private
|
| + var hasPasswordField_ = function(win) {
|
| + var doc = win.document;
|
| +
|
| + // We may will not be allowed to read the 'document' property from a frame
|
| + // that is in a different domain.
|
| + if (!doc) {
|
| + return false;
|
| + }
|
| +
|
| + if (doc.querySelector('input[type=password]')) {
|
| + return true;
|
| + }
|
| +
|
| + var frames = win.frames;
|
| + for (var i = 0; i < frames.length; i++) {
|
| + if (hasPasswordField_(frames[i])) {
|
| + return true;
|
| + }
|
| + }
|
| +
|
| + return false;
|
| + };
|
| +
|
| + function invokeOnHost_(command) {
|
| + __gCrWeb.message.invokeOnHost(command);
|
| + };
|
| +
|
| + function invokeOnHostImmediate_(command) {
|
| + __gCrWeb.message.invokeOnHostImmediate(command);
|
| + };
|
| +
|
| + /**
|
| + * 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} linkElement The link triggering the navigation.
|
| + * @return {String} The policy string.
|
| + * @private
|
| + */
|
| + var getReferrerPolicy_ = function(linkElement) {
|
| + if (linkElement) {
|
| + var rel = 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';
|
| + };
|
| +
|
| + // Provides a way for other injected javascript to access the page's referrer
|
| + // policy.
|
| + __gCrWeb['getPageReferrerPolicy'] = function() {
|
| + return getReferrerPolicy_();
|
| + };
|
| +
|
| + // Various aspects of global DOM behavior are overridden here.
|
| +
|
| + // A popstate event needs to be fired anytime the active history entry
|
| + // changes. Either via back, forward, go navigation or by loading the URL,
|
| + // clicking on a link, etc.
|
| + __gCrWeb['dispatchPopstateEvent'] = function(stateObject) {
|
| + var popstateEvent = window.document.createEvent('HTMLEvents');
|
| + popstateEvent.initEvent('popstate', true, false);
|
| + if (stateObject)
|
| + popstateEvent.state = JSON.parse(stateObject);
|
| +
|
| + // setTimeout() is used in order to return immediately. Otherwise the
|
| + // dispatchEvent call waits for all event handlers to return, which could
|
| + // cause a ReentryGuard failure.
|
| + window.setTimeout(function() {
|
| + window.dispatchEvent(popstateEvent);
|
| + }, 0);
|
| + };
|
| +
|
| + // Keep the original replaceState() method. It's needed to update UIWebView's
|
| + // URL and window.history.state property during history navigations that don't
|
| + // cause a page load.
|
| + var originalWindowHistoryReplaceState = window.history.replaceState;
|
| + __gCrWeb['replaceWebViewURL'] = function(url, stateObject) {
|
| + originalWindowHistoryReplaceState.call(history, stateObject, null, url);
|
| + };
|
| +
|
| + // Intercept window.history methods to call back/forward natively.
|
| + window.history.back = function() {
|
| + invokeOnHost_({'command': 'window.history.back'});
|
| + };
|
| + window.history.forward = function() {
|
| + invokeOnHost_({'command': 'window.history.forward'});
|
| + };
|
| + window.history.go = function(delta) {
|
| + invokeOnHost_({'command': 'window.history.go', 'value': delta});
|
| + };
|
| + window.history.pushState = function(stateObject, pageTitle, pageUrl) {
|
| + __gCrWeb.core_dynamic.historyWillChangeState();
|
| + // Calling stringify() on undefined causes a JSON parse error.
|
| + var serializedState =
|
| + typeof(stateObject) == 'undefined' ? '' :
|
| + __gCrWeb.common.JSONStringify(stateObject);
|
| + pageUrl = pageUrl || window.location.href;
|
| + originalWindowHistoryReplaceState.call(history, stateObject, null, pageUrl);
|
| + invokeOnHost_({'command': 'window.history.didPushState',
|
| + 'stateObject': serializedState,
|
| + 'baseUrl': document.baseURI,
|
| + 'pageUrl': pageUrl.toString()});
|
| + };
|
| + window.history.replaceState = function(stateObject, pageTitle, pageUrl) {
|
| + __gCrWeb.core_dynamic.historyWillChangeState();
|
| + // Calling stringify() on undefined causes a JSON parse error.
|
| + var serializedState =
|
| + typeof(stateObject) == 'undefined' ? '' :
|
| + __gCrWeb.common.JSONStringify(stateObject);
|
| + pageUrl = pageUrl || window.location.href;
|
| + originalWindowHistoryReplaceState.call(history, stateObject, null, pageUrl);
|
| + invokeOnHost_({'command': 'window.history.didReplaceState',
|
| + 'stateObject': serializedState,
|
| + 'baseUrl': document.baseURI,
|
| + 'pageUrl': pageUrl.toString()});
|
| + };
|
| +
|
| + __gCrWeb['getFullyQualifiedURL'] = function(originalURL) {
|
| + // A dummy anchor (never added to the document) is used to obtain the
|
| + // fully-qualified URL of |originalURL|.
|
| + var anchor = document.createElement('a');
|
| + anchor.href = originalURL;
|
| + return anchor.href;
|
| + };
|
| +
|
| + // Intercept window.close calls.
|
| + window.close = function() {
|
| + invokeOnHost_({'command': 'window.close.self'});
|
| + };
|
| +
|
| + window.addEventListener('hashchange', function(evt) {
|
| + invokeOnHost_({'command': 'window.hashchange'});
|
| + });
|
| +
|
| + __gCrWeb.core_dynamic.addEventListeners();
|
| +
|
| + // Returns if a frame with |name| is found in |currentWindow|.
|
| + // Note frame.name is undefined for cross domain frames.
|
| + var hasFrame_ = function(currentWindow, name) {
|
| + if (currentWindow.name === name)
|
| + return true;
|
| +
|
| + var frames = currentWindow.frames;
|
| + for (var index = 0; index < frames.length; ++index) {
|
| + var frame = frames[index];
|
| + if (frame === undefined)
|
| + continue;
|
| + if (hasFrame_(frame, name))
|
| + return true;
|
| + }
|
| + return false;
|
| + };
|
| +
|
| + // Checks if |node| is an anchor to be opened in the current tab.
|
| + var isInternaLink_ = function(node) {
|
| + if (!node instanceof HTMLAnchorElement)
|
| + return false;
|
| +
|
| + // Anchor with href='javascript://.....' will be opened in the current tab
|
| + // for simplicity.
|
| + if (node.href.indexOf('javascript:') == 0)
|
| + return true;
|
| +
|
| + // UIWebView will take care of the following cases.
|
| + //
|
| + // - If the given browsing context name is the empty string or '_self', then
|
| + // the chosen browsing context must be the current one.
|
| + //
|
| + // - If the given browsing context name is '_parent', then the chosen
|
| + // browsing context must be the parent browsing context of the current
|
| + // one, unless there is no one, in which case the chosen browsing context
|
| + // must be the current browsing context.
|
| + //
|
| + // - If the given browsing context name is '_top', then the chosen browsing
|
| + // context must be the top-level browsing context of the current one, if
|
| + // there is one, or else the current browsing context.
|
| + //
|
| + // Here an undefined target is considered in the same way as an empty
|
| + // target.
|
| + if (node.target === undefined || node.target === '' ||
|
| + node.target === '_self' || node.target === '_parent' ||
|
| + node.target === '_top') {
|
| + return true;
|
| + }
|
| +
|
| + // A new browsing context is being requested for an '_blank' target.
|
| + if (node.target === '_blank')
|
| + return false;
|
| +
|
| + // Otherwise UIWebView will take care of the case where there exists a
|
| + // browsing context whose name is the same as the given browsing context
|
| + // name. If there is no such a browsing context, a new browsing context is
|
| + // being requested.
|
| + return hasFrame_(window, node.target);
|
| + };
|
| +
|
| + var getTargetLink_ = function(target) {
|
| + var node = target;
|
| + // Find the closest ancester that is a link.
|
| + while (node) {
|
| + if (node instanceof HTMLAnchorElement)
|
| + break;
|
| + node = node.parentNode;
|
| + }
|
| + return node;
|
| + };
|
| +
|
| + var setExternalRequest_ = function(href, target) {
|
| + if (typeof(target) == 'undefined' || target == '_blank' || target == '') {
|
| + target = '' + Date.now() + '-' + Math.random();
|
| + }
|
| + if (typeof(href) == 'undefined') {
|
| + // W3C recommended behavior.
|
| + href = 'about:blank';
|
| + }
|
| + // ExternalRequest messages need to be handled before the expected
|
| + // shouldStartLoadWithRequest, as such we cannot wait for the regular
|
| + // message queue invoke which delays to avoid illegal recursion into
|
| + // UIWebView. This immediate class of messages is handled ASAP by
|
| + // CRWWebController.
|
| + invokeOnHostImmediate_({'command': 'externalRequest',
|
| + 'href': href,
|
| + 'target': target,
|
| + 'referrerPolicy': getReferrerPolicy_()});
|
| + };
|
| +
|
| + var resetExternalRequest_ = function() {
|
| + invokeOnHost_({'command': 'resetExternalRequest'});
|
| + };
|
| +
|
| + var clickBubbleListener_ = function(evt) {
|
| + if (evt['defaultPrevented']) {
|
| + resetExternalRequest_();
|
| + }
|
| + // Remove the listener.
|
| + evt.currentTarget.removeEventListener(
|
| + 'click', clickBubbleListener_, false);
|
| + };
|
| +
|
| + var getComputedWebkitTouchCallout_ = function(element) {
|
| + return window.getComputedStyle(element, null)['webkitTouchCallout'];
|
| + };
|
| +
|
| + /**
|
| + * This method applies the various document-level overrides. Sometimes the
|
| + * document object gets reset in the early stages of the page lifecycle, so
|
| + * this is exposed as a method for the application to invoke later. That way
|
| + * the window-level overrides can be applied as soon as possible.
|
| + */
|
| + __gCrWeb.core.documentInject = function() {
|
| + // Perform web view specific operations requiring document.body presence.
|
| + // If necessary returns and waits for document to be present.
|
| + if (!__gCrWeb.core_dynamic.documentInject())
|
| + return;
|
| +
|
| + document.addEventListener('click', function(evt) {
|
| + var node = getTargetLink_(evt.target);
|
| +
|
| + if (!node)
|
| + return;
|
| +
|
| + if (isInternaLink_(node)) {
|
| + return;
|
| + }
|
| + setExternalRequest_(node.href, node.target);
|
| + // Add listener to the target and its immediate ancesters. These event
|
| + // listeners will be removed if they get called. The listeners for some
|
| + // elements might never be removed, but if multiple identical event
|
| + // listeners are registered on the same event target with the same
|
| + // parameters the duplicate instances are discarded.
|
| + for (var level = 0; level < 5; ++level) {
|
| + if (node && node != document) {
|
| + node.addEventListener('click', clickBubbleListener_, false);
|
| + node = node.parentNode;
|
| + } else {
|
| + break;
|
| + }
|
| + }
|
| + }, true);
|
| +
|
| + // Intercept clicks on anchors (links) during bubbling phase so that the
|
| + // browser can handle target type appropriately.
|
| + document.addEventListener('click', function(evt) {
|
| + var node = getTargetLink_(evt.target);
|
| +
|
| + if (!node)
|
| + return;
|
| +
|
| + if (isInternaLink_(node)) {
|
| + if (evt['defaultPrevented'])
|
| + return;
|
| + // Internal link. The web view will handle navigation, but register
|
| + // the anchor for UIWebView to start the progress indicator ASAP and
|
| + // notify web controller as soon as possible of impending navigation.
|
| + if (__gCrWeb.core_dynamic.handleInternalClickEvent) {
|
| + __gCrWeb.core_dynamic.handleInternalClickEvent(node);
|
| + }
|
| + return;
|
| + } else {
|
| + // Resets the external request if it has been canceled, otherwise
|
| + // updates the href in case it has been changed.
|
| + if (evt['defaultPrevented'])
|
| + resetExternalRequest_();
|
| + else
|
| + setExternalRequest_(node.href, node.target);
|
| + }
|
| + }, false);
|
| +
|
| + // Capture form submit actions.
|
| + document.addEventListener('submit', function(evt) {
|
| + if (evt['defaultPrevented'])
|
| + return;
|
| +
|
| + var form = evt.target;
|
| + var targetsFrame = form.target && hasFrame_(window, form.target);
|
| + // TODO(stuartmorgan): Handle external targets. crbug.com/233543
|
| +
|
| + var action = form.getAttribute('action');
|
| + // Default action is to re-submit to same page.
|
| + if (!action)
|
| + action = document.location.href;
|
| + invokeOnHost_({
|
| + 'command': 'document.submit',
|
| + 'formName': __gCrWeb.common.getFormIdentifier(evt.srcElement),
|
| + 'href': __gCrWeb['getFullyQualifiedURL'](action),
|
| + 'targetsFrame': targetsFrame
|
| + });
|
| + }, false);
|
| +
|
| + addFormEventListeners_();
|
| +
|
| + // Handle or wait for and handle document load completion, if applicable.
|
| + if (__gCrWeb.core_dynamic.handleDocumentLoaded)
|
| + __gCrWeb.core_dynamic.handleDocumentLoaded();
|
| +
|
| + return true;
|
| + };
|
| +
|
| + __gCrWeb.core.documentInject();
|
| +
|
| + // Form prototype loaded with event to supply Autocomplete API
|
| + // functionality.
|
| + HTMLFormElement.prototype.requestAutocomplete = function() {
|
| + invokeOnHost_(
|
| + {'command': 'form.requestAutocomplete',
|
| + 'formName': __gCrWeb.common.getFormIdentifier(this)});
|
| + };
|
| +} // End of anonymous object
|
|
|