146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles)// Copyright 2014 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)var $console = window.console;
65d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Returns a function that logs a 'not available' error to the console and
95d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * returns undefined.
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} messagePrefix text to prepend to the exception message.
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function generateDisabledMethodStub(messagePrefix, opt_messageSuffix) {
145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  var message = messagePrefix + ' is not available in packaged apps.';
155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (opt_messageSuffix) message = message + ' ' + opt_messageSuffix;
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return function() {
175d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    $console.error(message);
185d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    return;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Returns a function that throws a 'not available' error.
245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *
255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @param {string} messagePrefix text to prepend to the exception message.
265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */
275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)function generateThrowingMethodStub(messagePrefix, opt_messageSuffix) {
285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  var message = messagePrefix + ' is not available in packaged apps.';
295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  if (opt_messageSuffix) message = message + ' ' + opt_messageSuffix;
305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  return function() {
315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    throw new Error(message);
325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  };
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/**
365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Replaces the given methods of the passed in object with stubs that log
375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * 'not available' errors to the console and return undefined.
385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *
395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * This should be used on methods attached via non-configurable properties,
405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * such as window.alert. disableGetters should be used when possible, because
415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * it is friendlier towards feature detection.
425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *
435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * In most cases, the useThrowingStubs should be false, so the stubs used to
445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * replace the methods log an error to the console, but allow the calling code
455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * to continue. We shouldn't break library code that uses feature detection
465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * responsibly, such as:
475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *     if(window.confirm) {
485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *       var result = window.confirm('Are you sure you want to delete ...?');
495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *       ...
505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *     }
515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *
525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * useThrowingStubs should only be true for methods that are deprecated in the
535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Web platform, and should not be used by a responsible library, even in
545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * conjunction with feature detection. A great example is document.write(), as
555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * the HTML5 specification recommends against using it, and says that its
565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * behavior is unreliable. No reasonable library code should ever use it.
575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * HTML5 spec: http://www.w3.org/TR/html5/dom.html#dom-document-write
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Object} object The object with methods to disable. The prototype is
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     preferred.
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} objectName The display name to use in the error message
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     thrown by the stub (this is the name that the object is commonly referred
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     to by web developers, e.g. "document" instead of "HTMLDocument").
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Array.<string>} methodNames names of methods to disable.
655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @param {Boolean} useThrowingStubs if true, the replaced methods will throw
665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *     an error instead of silently returning undefined
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
685d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)function disableMethods(object, objectName, methodNames, useThrowingStubs) {
697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  $Array.forEach(methodNames, function(methodName) {
705d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    var messagePrefix = objectName + '.' + methodName + '()';
715d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    object[methodName] = useThrowingStubs ?
725d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        generateThrowingMethodStub(messagePrefix) :
735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        generateDisabledMethodStub(messagePrefix);
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  });
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/**
785d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Replaces the given properties of the passed in object with stubs that log
795d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * 'not available' warnings to the console and return undefined when gotten. If
805d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * a property's setter is later invoked, the getter and setter are restored to
815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * default behaviors.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Object} object The object with properties to disable. The prototype
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     is preferred.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {string} objectName The display name to use in the error message
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     thrown by the getter stub (this is the name that the object is commonly
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     referred to by web developers, e.g. "document" instead of
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *     "HTMLDocument").
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * @param {Array.<string>} propertyNames names of properties to disable.
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function disableGetters(object, objectName, propertyNames, opt_messageSuffix) {
927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  $Array.forEach(propertyNames, function(propertyName) {
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var stub = generateDisabledMethodStub(objectName + '.' + propertyName,
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                          opt_messageSuffix);
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    stub._is_platform_app_disabled_getter = true;
965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    $Object.defineProperty(object, propertyName, {
975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      configurable: true,
985d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      enumerable: false,
995d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      get: stub,
1005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      set: function(value) {
1015d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        var descriptor = $Object.getOwnPropertyDescriptor(this, propertyName);
1025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        if (!descriptor || !descriptor.get ||
1035d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)            descriptor.get._is_platform_app_disabled_getter) {
1045d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          // The stub getter is still defined.  Blow-away the property to
1055d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          // restore default getter/setter behaviors and re-create it with the
1065d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          // given value.
1075d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          delete this[propertyName];
1085d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          this[propertyName] = value;
1095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        } else {
1105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          // Do nothing.  If some custom getter (not ours) has been defined,
1115d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          // there would be no way to read back the value stored by a default
1125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          // setter. Also, the only way to clear a custom getter is to first
1135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          // delete the property.  Therefore, the value we have here should
1145d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          // just go into a black hole.
1155d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        }
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    });
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  });
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1215d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)/**
1225d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * Replaces the given properties of the passed in object with stubs that log
1235d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * 'not available' warnings to the console when set.
1245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *
1255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @param {Object} object The object with properties to disable. The prototype
1265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *     is preferred.
1275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @param {string} objectName The display name to use in the error message
1285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *     thrown by the setter stub (this is the name that the object is commonly
1295d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *     referred to by web developers, e.g. "document" instead of
1305d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) *     "HTMLDocument").
1315d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * @param {Array.<string>} propertyNames names of properties to disable.
1325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) */
1335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)function disableSetters(object, objectName, propertyNames, opt_messageSuffix) {
1345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  $Array.forEach(propertyNames, function(propertyName) {
1355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    var stub = generateDisabledMethodStub(objectName + '.' + propertyName,
1365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                                          opt_messageSuffix);
1375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    $Object.defineProperty(object, propertyName, {
1385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      configurable: true,
1395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      enumerable: false,
1405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      get: function() {
1415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        return;
1425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      },
1435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      set: stub
1445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    });
1455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  });
1465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}
1475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Disable benign Document methods.
1495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)disableMethods(HTMLDocument.prototype, 'document', ['open', 'clear', 'close']);
1505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)
1515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// Replace evil Document methods with exception-throwing stubs.
1525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)disableMethods(HTMLDocument.prototype, 'document', ['write', 'writeln'], true);
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Disable history.
1550529e5d033099cbfc42635f6f6183833b09dff6eBen MurdochObject.defineProperty(window, "history", { value: {} });
1565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)disableGetters(window.history, 'history', ['back', 'forward', 'go', 'length']);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Disable find.
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)disableMethods(Window.prototype, 'window', ['find']);
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Disable modal dialogs. Shell windows disable these anyway, but it's nice to
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// warn.
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)disableMethods(Window.prototype, 'window', ['alert', 'confirm', 'prompt']);
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Disable window.*bar.
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)disableGetters(window, 'window',
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ['locationbar', 'menubar', 'personalbar', 'scrollbars', 'statusbar',
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     'toolbar']);
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Disable window.localStorage.
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Sometimes DOM security policy prevents us from doing this (e.g. for data:
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// URLs) so wrap in try-catch.
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)try {
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  disableGetters(window, 'window',
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ['localStorage'],
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      'Use chrome.storage.local instead.');
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} catch (e) {}
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Document instance properties that we wish to disable need to be set when
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the document begins loading, since only then will the "document" reference
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// point to the page's document (it will be reset between now and then).
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We can't listen for the "readystatechange" event on the document (because
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the object that it's dispatched on doesn't exist yet), but we can instead
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// do it at the window level in the capturing phase.
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)window.addEventListener('readystatechange', function(event) {
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (document.readyState != 'loading')
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Deprecated document properties from
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // https://developer.mozilla.org/en/DOM/document.
191868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // To deprecate document.all, simply changing its getter and setter would
192868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // activate its cache mechanism, and degrade the performance. Here we assign
193868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // it first to 'undefined' to avoid this.
194868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  document.all = undefined;
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  disableGetters(document, 'document',
1965d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      ['alinkColor', 'all', 'bgColor', 'fgColor', 'linkColor', 'vlinkColor']);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}, true);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Disable onunload, onbeforeunload.
2005d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)disableSetters(Window.prototype, 'window', ['onbeforeunload', 'onunload']);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)var windowAddEventListener = Window.prototype.addEventListener;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Window.prototype.addEventListener = function(type) {
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (type === 'unload' || type === 'beforeunload')
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    generateDisabledMethodStub(type)();
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  else
206eb525c5499e34cc9c4b825d6d9e75bb07cc06aceBen Murdoch    return $Function.apply(windowAddEventListener, window, arguments);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
208