OLD | NEW |
---|---|
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 /** | 5 /** |
6 * Returns a function that logs a 'not available' error to the console and | 6 * Returns a function that logs a 'not available' error to the console and |
7 * returns undefined. | 7 * returns undefined. |
8 * | 8 * |
9 * @param {string} messagePrefix text to prepend to the exception message. | 9 * @param {string} messagePrefix text to prepend to the exception message. |
10 */ | 10 */ |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
59 * @param {string} objectName The display name to use in the error message | 59 * @param {string} objectName The display name to use in the error message |
60 * thrown by the stub (this is the name that the object is commonly referred | 60 * thrown by the stub (this is the name that the object is commonly referred |
61 * to by web developers, e.g. "document" instead of "HTMLDocument"). | 61 * to by web developers, e.g. "document" instead of "HTMLDocument"). |
62 * @param {Array<string>} methodNames names of methods to disable. | 62 * @param {Array<string>} methodNames names of methods to disable. |
63 * @param {Boolean} useThrowingStubs if true, the replaced methods will throw | 63 * @param {Boolean} useThrowingStubs if true, the replaced methods will throw |
64 * an error instead of silently returning undefined | 64 * an error instead of silently returning undefined |
65 */ | 65 */ |
66 function disableMethods(object, objectName, methodNames, useThrowingStubs) { | 66 function disableMethods(object, objectName, methodNames, useThrowingStubs) { |
67 $Array.forEach(methodNames, function(methodName) { | 67 $Array.forEach(methodNames, function(methodName) { |
68 var messagePrefix = objectName + '.' + methodName + '()'; | 68 var messagePrefix = objectName + '.' + methodName + '()'; |
69 object[methodName] = useThrowingStubs ? | 69 $Object.defineProperty(object, methodName, { |
70 generateThrowingMethodStub(messagePrefix) : | 70 configurable: false, |
71 generateDisabledMethodStub(messagePrefix); | 71 enumerable: false, |
72 value: useThrowingStubs ? | |
73 generateThrowingMethodStub(messagePrefix) : | |
74 generateDisabledMethodStub(messagePrefix) | |
75 }); | |
72 }); | 76 }); |
73 } | 77 } |
74 | 78 |
75 /** | 79 /** |
76 * Replaces the given properties of the passed in object with stubs that log | 80 * Replaces the given properties of the passed in object with stubs that log |
77 * 'not available' warnings to the console and return undefined when gotten. If | 81 * 'not available' warnings to the console and return undefined when gotten. If |
78 * a property's setter is later invoked, the getter and setter are restored to | 82 * a property's setter is later invoked, the getter and setter are restored to |
79 * default behaviors. | 83 * default behaviors. |
80 * | 84 * |
81 * @param {Object} object The object with properties to disable. The prototype | 85 * @param {Object} object The object with properties to disable. The prototype |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
126 * thrown by the setter stub (this is the name that the object is commonly | 130 * thrown by the setter stub (this is the name that the object is commonly |
127 * referred to by web developers, e.g. "document" instead of | 131 * referred to by web developers, e.g. "document" instead of |
128 * "HTMLDocument"). | 132 * "HTMLDocument"). |
129 * @param {Array<string>} propertyNames names of properties to disable. | 133 * @param {Array<string>} propertyNames names of properties to disable. |
130 */ | 134 */ |
131 function disableSetters(object, objectName, propertyNames, opt_messageSuffix) { | 135 function disableSetters(object, objectName, propertyNames, opt_messageSuffix) { |
132 $Array.forEach(propertyNames, function(propertyName) { | 136 $Array.forEach(propertyNames, function(propertyName) { |
133 var stub = generateDisabledMethodStub(objectName + '.' + propertyName, | 137 var stub = generateDisabledMethodStub(objectName + '.' + propertyName, |
134 opt_messageSuffix); | 138 opt_messageSuffix); |
135 $Object.defineProperty(object, propertyName, { | 139 $Object.defineProperty(object, propertyName, { |
136 configurable: true, | 140 configurable: false, |
137 enumerable: false, | 141 enumerable: false, |
138 get: function() { | 142 get: function() { |
139 return; | 143 return; |
140 }, | 144 }, |
141 set: stub | 145 set: stub |
142 }); | 146 }); |
143 }); | 147 }); |
144 } | 148 } |
145 | 149 |
146 // Disable benign Document methods. | 150 // Disable benign Document methods. |
147 disableMethods(HTMLDocument.prototype, 'document', ['open', 'clear', 'close']); | 151 disableMethods(Document.prototype, 'document', ['open', 'clear', 'close']); |
148 | 152 |
149 // Replace evil Document methods with exception-throwing stubs. | 153 // Replace evil Document methods with exception-throwing stubs. |
150 disableMethods(HTMLDocument.prototype, 'document', ['write', 'writeln'], true); | 154 disableMethods(Document.prototype, 'document', ['write', 'writeln'], true); |
151 | 155 |
152 // Disable history. | 156 // Disable history. |
153 Object.defineProperty(window, "history", { value: {} }); | 157 Object.defineProperty(window, "history", { value: {} }); |
154 disableGetters(window.history, 'history', | 158 disableGetters(window.history, 'history', |
155 ['back', 'forward', 'go', 'length', 'pushState', 'replaceState', 'state']); | 159 ['back', 'forward', 'go', 'length', 'pushState', 'replaceState', 'state']); |
156 | 160 |
157 // Disable find. | 161 // Disable find. |
158 disableMethods(window, 'window', ['find']); | 162 disableMethods(window, 'window', ['find']); |
159 disableMethods(Window.prototype, 'window', ['find']); | 163 disableMethods(Window.prototype, 'window', ['find']); |
160 | 164 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
195 document.all = undefined; | 199 document.all = undefined; |
196 disableGetters(document, 'document', | 200 disableGetters(document, 'document', |
197 ['alinkColor', 'all', 'bgColor', 'fgColor', 'linkColor', 'vlinkColor']); | 201 ['alinkColor', 'all', 'bgColor', 'fgColor', 'linkColor', 'vlinkColor']); |
198 }, true); | 202 }, true); |
199 | 203 |
200 // Disable onunload, onbeforeunload. | 204 // Disable onunload, onbeforeunload. |
201 disableSetters(window, 'window', ['onbeforeunload', 'onunload']); | 205 disableSetters(window, 'window', ['onbeforeunload', 'onunload']); |
202 disableSetters(Window.prototype, 'window', ['onbeforeunload', 'onunload']); | 206 disableSetters(Window.prototype, 'window', ['onbeforeunload', 'onunload']); |
203 var eventTargetAddEventListener = EventTarget.prototype.addEventListener; | 207 var eventTargetAddEventListener = EventTarget.prototype.addEventListener; |
204 EventTarget.prototype.addEventListener = function(type) { | 208 EventTarget.prototype.addEventListener = function(type) { |
205 if (type === 'unload' || type === 'beforeunload') | 209 // Note: == vs === (i.e., lax vs strict equality) is *important* here. Things |
210 // that eval to 'beforeunload' like String('beforeunload') also need to be | |
211 // blocked. | |
212 if (type == 'unload' || type == 'beforeunload') | |
robwu
2016/02/19 10:38:01
This does not work, there is a TOCTOU issue here,
Devlin
2016/02/19 20:43:59
sgtm, done.
| |
206 generateDisabledMethodStub(type)(); | 213 generateDisabledMethodStub(type)(); |
207 else | 214 else |
208 return $Function.apply(eventTargetAddEventListener, this, arguments); | 215 return $Function.apply(eventTargetAddEventListener, this, arguments); |
209 }; | 216 }; |
OLD | NEW |