Path: blob/trunk/third_party/closure/goog/dom/asserts.js
4509 views
/**1* @license2* Copyright The Closure Library Authors.3* SPDX-License-Identifier: Apache-2.04*/56goog.provide('goog.dom.asserts');78goog.require('goog.asserts');910goog.require('goog.utils');1112/**13* @fileoverview Custom assertions to ensure that an element has the appropriate14* type.15*16* Using a goog.dom.safe wrapper on an object on the incorrect type (via an17* incorrect static type cast) can result in security bugs: For instance,18* g.d.s.setAnchorHref ensures that the URL assigned to the .href attribute19* satisfies the SafeUrl contract, i.e., is safe to dereference as a hyperlink.20* However, the value assigned to a HTMLLinkElement's .href property requires21* the stronger TrustedResourceUrl contract, since it can refer to a stylesheet.22* Thus, using g.d.s.setAnchorHref on an (incorrectly statically typed) object23* of type HTMLLinkElement can result in a security vulnerability.24* Assertions of the correct run-time type help prevent such incorrect use.25*26* In some cases, code using the DOM API is tested using mock objects (e.g., a27* plain object such as {'href': url} instead of an actual Location object).28* To allow such mocking, the assertions permit objects of types that are not29* relevant DOM API objects at all (for instance, not Element or Location).30*31* Note that instanceof checks don't work straightforwardly in older versions of32* IE, or across frames (see,33* http://stackoverflow.com/questions/384286/javascript-isdom-how-do-you-check-if-a-javascript-object-is-a-dom-object,34* http://stackoverflow.com/questions/26248599/instanceof-htmlelement-in-iframe-is-not-element-or-object).35*36* Hence, these assertions may pass vacuously in such scenarios. The resulting37* risk of security bugs is limited by the following factors:38* - A bug can only arise in scenarios involving incorrect static typing (the39* wrapper methods are statically typed to demand objects of the appropriate,40* precise type).41* - Typically, code is tested and exercised in multiple browsers.42*/4344/**45* Asserts that a given object is a Location.46*47* To permit this assertion to pass in the context of tests where DOM APIs might48* be mocked, also accepts any other type except for subtypes of {!Element}.49* This is to ensure that, for instance, HTMLLinkElement is not being used in50* place of a Location, since this could result in security bugs due to stronger51* contracts required for assignments to the href property of the latter.52*53* @param {?Object} o The object whose type to assert.54* @return {!Location}55*/56goog.dom.asserts.assertIsLocation = function(o) {57'use strict';58if (goog.asserts.ENABLE_ASSERTS) {59var win = goog.dom.asserts.getWindow_(o);60if (win) {61if (!o || (!(o instanceof win.Location) && o instanceof win.Element)) {62goog.asserts.fail(63'Argument is not a Location (or a non-Element mock); got: %s',64goog.dom.asserts.debugStringForType_(o));65}66}67}68return /** @type {!Location} */ (o);69};707172/**73* Returns a string representation of a value's type.74*75* @param {*} value An object, or primitive.76* @return {string} The best display name for the value.77* @private78*/79goog.dom.asserts.debugStringForType_ = function(value) {80'use strict';81if (goog.utils.isObject(value)) {82try {83return /** @type {string|undefined} */ (value.constructor.displayName) ||84value.constructor.name || Object.prototype.toString.call(value);85} catch (e) {86return '<object could not be stringified>';87}88} else {89return value === undefined ? 'undefined' :90value === null ? 'null' : typeof value;91}92};9394/**95* Gets window of element.96* @param {?Object} o97* @return {?Window}98* @private99* @suppress {strictMissingProperties} ownerDocument not defined on Object100*/101goog.dom.asserts.getWindow_ = function(o) {102'use strict';103try {104var doc = o && o.ownerDocument;105// This can throw “Blocked a frame with origin "chrome-extension://..." from106// accessing a cross-origin frame” in Chrome extension.107var win =108doc && /** @type {?Window} */ (doc.defaultView || doc.parentWindow);109win = win || /** @type {!Window} */ (goog.global);110// This can throw “Permission denied to access property "Element" on111// cross-origin object”.112if (win.Element && win.Location) {113return win;114}115} catch (ex) {116}117return null;118};119120121