| Index: chrome/renderer/resources/extensions/platform_app.js
|
| diff --git a/chrome/renderer/resources/extensions/platform_app.js b/chrome/renderer/resources/extensions/platform_app.js
|
| index 78a13ffe01e51ea4049d8abccc37a02f59f24695..0982a6a18ea0b4371208292f1fd14f6ed4d3b921 100644
|
| --- a/chrome/renderer/resources/extensions/platform_app.js
|
| +++ b/chrome/renderer/resources/extensions/platform_app.js
|
| @@ -2,22 +2,59 @@
|
| // Use of this source code is governed by a BSD-style license that can be
|
| // found in the LICENSE file.
|
|
|
| +var $console = window.console;
|
| +
|
| /**
|
| - * Returns a function that throws a 'not available' exception when called.
|
| + * Returns a function that logs a 'not available' error to the console and
|
| + * returns undefined.
|
| *
|
| * @param {string} messagePrefix text to prepend to the exception message.
|
| */
|
| function generateDisabledMethodStub(messagePrefix, opt_messageSuffix) {
|
| + var message = messagePrefix + ' is not available in packaged apps.';
|
| + if (opt_messageSuffix) message = message + ' ' + opt_messageSuffix;
|
| return function() {
|
| - var message = messagePrefix + ' is not available in packaged apps.';
|
| - if (opt_messageSuffix) message = message + ' ' + opt_messageSuffix;
|
| - throw message;
|
| + $console.error(message);
|
| + return;
|
| };
|
| }
|
|
|
| /**
|
| - * Replaces the given methods of the passed in object with stubs that throw
|
| - * 'not available' exceptions when called.
|
| + * Returns a function that throws a 'not available' error.
|
| + *
|
| + * @param {string} messagePrefix text to prepend to the exception message.
|
| + */
|
| +function generateThrowingMethodStub(messagePrefix, opt_messageSuffix) {
|
| + var message = messagePrefix + ' is not available in packaged apps.';
|
| + if (opt_messageSuffix) message = message + ' ' + opt_messageSuffix;
|
| + return function() {
|
| + throw new Error(message);
|
| + };
|
| +}
|
| +
|
| +/**
|
| + * Replaces the given methods of the passed in object with stubs that log
|
| + * 'not available' errors to the console and return undefined.
|
| + *
|
| + * This should be used on methods attached via non-configurable properties,
|
| + * such as window.alert. disableGetters should be used when possible, because
|
| + * it is friendlier towards feature detection.
|
| + *
|
| + * In most cases, the useThrowingStubs should be false, so the stubs used to
|
| + * replace the methods log an error to the console, but allow the calling code
|
| + * to continue. We shouldn't break library code that uses feature detection
|
| + * responsibly, such as:
|
| + * if(window.confirm) {
|
| + * var result = window.confirm('Are you sure you want to delete ...?');
|
| + * ...
|
| + * }
|
| + *
|
| + * useThrowingStubs should only be true for methods that are deprecated in the
|
| + * Web platform, and should not be used by a responsible library, even in
|
| + * conjunction with feature detection. A great example is document.write(), as
|
| + * the HTML5 specification recommends against using it, and says that its
|
| + * behavior is unreliable. No reasonable library code should ever use it.
|
| + * HTML5 spec: http://www.w3.org/TR/html5/dom.html#dom-document-write
|
| *
|
| * @param {Object} object The object with methods to disable. The prototype is
|
| * preferred.
|
| @@ -25,18 +62,23 @@ function generateDisabledMethodStub(messagePrefix, opt_messageSuffix) {
|
| * thrown by the stub (this is the name that the object is commonly referred
|
| * to by web developers, e.g. "document" instead of "HTMLDocument").
|
| * @param {Array.<string>} methodNames names of methods to disable.
|
| + * @param {Boolean} useThrowingStubs if true, the replaced methods will throw
|
| + * an error instead of silently returning undefined
|
| */
|
| -function disableMethods(object, objectName, methodNames) {
|
| +function disableMethods(object, objectName, methodNames, useThrowingStubs) {
|
| $Array.forEach(methodNames, function(methodName) {
|
| - object[methodName] =
|
| - generateDisabledMethodStub(objectName + '.' + methodName + '()');
|
| + var messagePrefix = objectName + '.' + methodName + '()';
|
| + object[methodName] = useThrowingStubs ?
|
| + generateThrowingMethodStub(messagePrefix) :
|
| + generateDisabledMethodStub(messagePrefix);
|
| });
|
| }
|
|
|
| /**
|
| - * Replaces the given properties of the passed in object with stubs that throw
|
| - * 'not available' exceptions when gotten. If a property's setter is later
|
| - * invoked, the getter and setter are restored to default behaviors.
|
| + * Replaces the given properties of the passed in object with stubs that log
|
| + * 'not available' warnings to the console and return undefined when gotten. If
|
| + * a property's setter is later invoked, the getter and setter are restored to
|
| + * default behaviors.
|
| *
|
| * @param {Object} object The object with properties to disable. The prototype
|
| * is preferred.
|
| @@ -51,36 +93,67 @@ function disableGetters(object, objectName, propertyNames, opt_messageSuffix) {
|
| var stub = generateDisabledMethodStub(objectName + '.' + propertyName,
|
| opt_messageSuffix);
|
| stub._is_platform_app_disabled_getter = true;
|
| - object.__defineGetter__(propertyName, stub);
|
| -
|
| - object.__defineSetter__(propertyName, function(value) {
|
| - var getter = this.__lookupGetter__(propertyName);
|
| - if (!getter || getter._is_platform_app_disabled_getter) {
|
| - // The stub getter is still defined. Blow-away the property to restore
|
| - // default getter/setter behaviors and re-create it with the given
|
| - // value.
|
| - delete this[propertyName];
|
| - this[propertyName] = value;
|
| - } else {
|
| - // Do nothing. If some custom getter (not ours) has been defined, there
|
| - // would be no way to read back the value stored by a default setter.
|
| - // Also, the only way to clear a custom getter is to first delete the
|
| - // property. Therefore, the value we have here should just go into a
|
| - // black hole.
|
| + $Object.defineProperty(object, propertyName, {
|
| + configurable: true,
|
| + enumerable: false,
|
| + get: stub,
|
| + set: function(value) {
|
| + var descriptor = $Object.getOwnPropertyDescriptor(this, propertyName);
|
| + if (!descriptor || !descriptor.get ||
|
| + descriptor.get._is_platform_app_disabled_getter) {
|
| + // The stub getter is still defined. Blow-away the property to
|
| + // restore default getter/setter behaviors and re-create it with the
|
| + // given value.
|
| + delete this[propertyName];
|
| + this[propertyName] = value;
|
| + } else {
|
| + // Do nothing. If some custom getter (not ours) has been defined,
|
| + // there would be no way to read back the value stored by a default
|
| + // setter. Also, the only way to clear a custom getter is to first
|
| + // delete the property. Therefore, the value we have here should
|
| + // just go into a black hole.
|
| + }
|
| }
|
| });
|
| });
|
| }
|
|
|
| -// Disable document.open|close|write|etc.
|
| -disableMethods(HTMLDocument.prototype, 'document',
|
| - ['open', 'clear', 'close', 'write', 'writeln']);
|
| +/**
|
| + * Replaces the given properties of the passed in object with stubs that log
|
| + * 'not available' warnings to the console when set.
|
| + *
|
| + * @param {Object} object The object with properties to disable. The prototype
|
| + * is preferred.
|
| + * @param {string} objectName The display name to use in the error message
|
| + * thrown by the setter stub (this is the name that the object is commonly
|
| + * referred to by web developers, e.g. "document" instead of
|
| + * "HTMLDocument").
|
| + * @param {Array.<string>} propertyNames names of properties to disable.
|
| + */
|
| +function disableSetters(object, objectName, propertyNames, opt_messageSuffix) {
|
| + $Array.forEach(propertyNames, function(propertyName) {
|
| + var stub = generateDisabledMethodStub(objectName + '.' + propertyName,
|
| + opt_messageSuffix);
|
| + $Object.defineProperty(object, propertyName, {
|
| + configurable: true,
|
| + enumerable: false,
|
| + get: function() {
|
| + return;
|
| + },
|
| + set: stub
|
| + });
|
| + });
|
| +}
|
| +
|
| +// Disable benign Document methods.
|
| +disableMethods(HTMLDocument.prototype, 'document', ['open', 'clear', 'close']);
|
| +
|
| +// Replace evil Document methods with exception-throwing stubs.
|
| +disableMethods(HTMLDocument.prototype, 'document', ['write', 'writeln'], true);
|
|
|
| // Disable history.
|
| window.history = {};
|
| -disableMethods(window.history, 'history',
|
| - ['back', 'forward', 'go']);
|
| -disableGetters(window.history, 'history', ['length']);
|
| +disableGetters(window.history, 'history', ['back', 'forward', 'go', 'length']);
|
|
|
| // Disable find.
|
| disableMethods(Window.prototype, 'window', ['find']);
|
| @@ -120,15 +193,11 @@ window.addEventListener('readystatechange', function(event) {
|
| // it first to 'undefined' to avoid this.
|
| document.all = undefined;
|
| disableGetters(document, 'document',
|
| - ['alinkColor', 'all', 'bgColor', 'fgColor', 'linkColor',
|
| - 'vlinkColor']);
|
| + ['alinkColor', 'all', 'bgColor', 'fgColor', 'linkColor', 'vlinkColor']);
|
| }, true);
|
|
|
| // Disable onunload, onbeforeunload.
|
| -Window.prototype.__defineSetter__(
|
| - 'onbeforeunload', generateDisabledMethodStub('onbeforeunload'));
|
| -Window.prototype.__defineSetter__(
|
| - 'onunload', generateDisabledMethodStub('onunload'));
|
| +disableSetters(Window.prototype, 'window', ['onbeforeunload', 'onunload']);
|
| var windowAddEventListener = Window.prototype.addEventListener;
|
| Window.prototype.addEventListener = function(type) {
|
| if (type === 'unload' || type === 'beforeunload')
|
|
|