Revision: 5566
Author: [email protected]
Date: Mon Aug 19 23:20:21 2013 UTC
Log: Tame requestAnimationFrame.
https://codereview.appspot.com/12926048
Fixes <https://code.google.com/p/google-caja/issues/detail?id=1741>.
[email protected]
http://code.google.com/p/google-caja/source/detail?r=5566
Modified:
/trunk/src/com/google/caja/plugin/domado.js
/trunk/tests/com/google/caja/plugin/test-domado-events-guest.html
/trunk/tests/com/google/caja/plugin/test-scan-guest.js
=======================================
--- /trunk/src/com/google/caja/plugin/domado.js Tue Aug 13 20:15:28 2013 UTC
+++ /trunk/src/com/google/caja/plugin/domado.js Mon Aug 19 23:20:21 2013 UTC
@@ -1431,13 +1431,15 @@
}
/*
- * Implementations of setTimeout, setInterval, clearTimeout, and
- * clearInterval that only allow simple functions as timeouts and
- * that treat timeout ids as capabilities.
- * This is safe even if accessed across frame since the same
- * map is never used with more than one version of setTimeout.
+ * Generic wrapper for the timing APIs
+ * setTimeout/clearTimeout
+ * setInterval/clearInterval
+ * requestAnimationFrame/cancelAnimationFrame
+ * which treats timeout IDs as capabilities so that the guest cannot
clear
+ * a timeout it didn't set, and prevents the callback from being a
string
+ * value which would be evaluated outside the sandbox.
*/
- function tameSetAndClear(target, set, clear, setName, clearName) {
+ function tameSetAndClear(target, set, clear, setName, clearName,
passArg) {
var ids = new WeakMap();
makeFunctionAccessible(set);
makeFunctionAccessible(clear);
@@ -1457,9 +1459,9 @@
// * Passing a string-like object which gets taken as code.
// * Non-standard arguments to the callback.
// * Non-standard effects of callback's return value.
- var actionWrapper = function() {
- action();
- };
+ var actionWrapper = passArg
+ ? function(time) { action(+time); } // requestAnimationFrame
+ : function() { action(); }; // setTimeout, setInterval
id = set(actionWrapper, delayMillis | 0);
} else {
id = undefined;
@@ -7021,14 +7023,22 @@
// this way.
tameSetAndClear(
TameWindow.prototype,
- function (code, millis) { return window.setTimeout(code,
millis); },
- function (id) { return window.clearTimeout(id); },
- 'setTimeout', 'clearTimeout');
+ function(code, millis) { return window.setTimeout(code, millis);
},
+ function(id) { return window.clearTimeout(id); },
+ 'setTimeout', 'clearTimeout', false);
tameSetAndClear(
TameWindow.prototype,
- function (code, millis) { return window.setInterval(code,
millis); },
- function (id) { return window.clearInterval(id); },
- 'setInterval', 'clearInterval');
+ function(code, millis) { return window.setInterval(code,
millis); },
+ function(id) { return window.clearInterval(id); },
+ 'setInterval', 'clearInterval', false);
+ if (window.requestAnimationFrame) {
+ tameSetAndClear(
+ TameWindow.prototype,
+ function(code, ignored) { // no time arg like setTimeout has
+ return window.requestAnimationFrame(code); },
+ function(id) { return window.cancelAnimationFrame(id); },
+ 'requestAnimationFrame', 'cancelAnimationFrame', true);
+ }
var noopWindowFunctionProp = Props.markPropMaker(function(env) {
var prop = env.prop;
var notify = true;
=======================================
--- /trunk/tests/com/google/caja/plugin/test-domado-events-guest.html Wed
Aug 14 04:56:12 2013 UTC
+++ /trunk/tests/com/google/caja/plugin/test-domado-events-guest.html Mon
Aug 19 23:20:21 2013 UTC
@@ -457,6 +457,52 @@
});
</script>
+<p class="testcontainer" id="testRequestAnimationFrame">
+ requestAnimationFrame<br>
+</p>
+<script type="text/javascript">
+ var hasRAF =
directAccess.evalInHostFrame('!!window.requestAnimationFrame');
+ jsunitRegisterIf(hasRAF,
+ 'testRequestAnimationFrame',
+ function testRequestAnimationFrame() {
+ // We use the same cancel-wrapper as setTimeout does, so not bothering
to
+ // test cancel matching, just that the functionality works.
+
+ var frame1Ran = 0;
+ var frame2Ran = 0;
+ var frame2Time = -1;
+ var frame3Ran = 0;
+ function r1f(time) { frame1Ran++; }
+ function r2f(time) { frame2Ran++; frame2Time = time; }
+ function r3f(time) {
+ assertEquals('2 before 3', 2, frame2Ran);
+ assertEquals('same time as previous callback', frame2Time, time);
+ frame3Ran++;
+ final();
+ }
+
+ var r1 = requestAnimationFrame(r1f);
+ var r21 = requestAnimationFrame(r2f);
+ var r22 = requestAnimationFrame(r2f); // spec'd to queue duplicate
+ var r3 = requestAnimationFrame(jsunitCallback(r3f));
+
+ var cr = cancelAnimationFrame(r1);
+ assertEquals('cancel return value', undefined, cr);
+ cancelAnimationFrame(undefined); // should not fail
+
+ var final = jsunitCallback(function final_() {
+ requestAnimationFrame(jsunitCallback(function(time) {
+ assertEquals('final #1', 0, frame1Ran);
+ assertEquals('final #2', 2, frame2Ran);
+ assertEquals('final #3', 1, frame3Ran);
+ assertTrue('timing (' + frame2Time + ' ' + time + ')',
+ frame2Time < time);
+ pass('testRequestAnimationFrame');
+ }));
+ });
+ });
+</script>
+
<p class="clickme testcontainer" id="testInnerhtmlOnclick">
do not click yet
</p>
=======================================
--- /trunk/tests/com/google/caja/plugin/test-scan-guest.js Wed Aug 14
17:51:03 2013 UTC
+++ /trunk/tests/com/google/caja/plugin/test-scan-guest.js Mon Aug 19
23:20:21 2013 UTC
@@ -20,6 +20,7 @@
*
* @requires JSON, WeakMap, Proxy, document, console, location,
* setTimeout, clearTimeout, setInterval, clearInterval,
+ * requestAnimationFrame, cancelAnimationFrame,
* cajaVM, directAccess, inES5Mode, getUrlParam,
* assertTrue, assertEquals, pass, jsunitFail,
* Event, HTMLInputElement, HTMLMediaElement, HTMLTableRowElement,
@@ -1352,6 +1353,10 @@
argsByIdentity(clearTimeout, genCall());
argsByIdentity(setInterval, G.none);
argsByIdentity(clearInterval, genCall());
+ if (window.requestAnimationFrame) {
+ argsByIdentity(requestAnimationFrame, genCall(genString));
+ argsByIdentity(cancelAnimationFrame, genCall());
+ }
argsByIdentity(isNaN, genCall(genSmallInteger));
argsByIdentity(parseInt, genCall(genString));
argsByIdentity(parseFloat, genCall(genString));
--
---
You received this message because you are subscribed to the Google Groups "Google Caja Discuss" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/groups/opt_out.