Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 'use strict';
3 /* global getMainChromeWindow, AccessFuTest, GestureSettings, GestureTracker,
4 SimpleTest, getBoundsForDOMElm, Point, Utils */
5 /* exported loadJSON, eventMap */
7 const Ci = Components.interfaces;
8 const Cu = Components.utils;
10 Cu.import('resource://gre/modules/accessibility/Utils.jsm');
11 Cu.import('resource://gre/modules/Geometry.jsm');
12 Cu.import("resource://gre/modules/accessibility/Gestures.jsm");
14 var win = getMainChromeWindow(window);
16 /**
17 * Convert inch based point coordinates into pixels.
18 * @param {Array} aPoints Array of coordinates in inches.
19 * @return {Array} Array of coordinates in pixels.
20 */
21 function convertPointCoordinates(aPoints) {
22 var dpi = Utils.dpi;
23 return aPoints.map(function convert(aPoint) {
24 return {
25 x: aPoint.x * dpi,
26 y: aPoint.y * dpi,
27 identifier: aPoint.identifier
28 };
29 });
30 }
32 /**
33 * For a given list of points calculate their coordinates in relation to the
34 * document body.
35 * @param {Array} aTouchPoints An array of objects of the following format: {
36 * base: {String}, // Id of an element to server as a base for the touch.
37 * x: {Number}, // An optional x offset from the base element's geometric
38 * // centre.
39 * y: {Number} // An optional y offset from the base element's geometric
40 * // centre.
41 * }
42 * @return {JSON} An array of {x, y} coordinations.
43 */
44 function calculateTouchListCoordinates(aTouchPoints) {
45 var coords = [];
46 for (var i = 0, target = aTouchPoints[i]; i < aTouchPoints.length; ++i) {
47 var bounds = getBoundsForDOMElm(target.base);
48 var parentBounds = getBoundsForDOMElm('root');
49 var point = new Point(target.x || 0, target.y || 0);
50 point.scale(Utils.dpi);
51 point.add(bounds[0], bounds[1]);
52 point.add(bounds[2] / 2, bounds[3] / 2);
53 point.subtract(parentBounds[0], parentBounds[0]);
54 coords.push({
55 x: point.x,
56 y: point.y
57 });
58 }
59 return coords;
60 }
62 /**
63 * Send a touch event with specified touchPoints.
64 * @param {Array} aTouchPoints An array of points to be associated with
65 * touches.
66 * @param {String} aName A name of the touch event.
67 */
68 function sendTouchEvent(aTouchPoints, aName) {
69 var touchList = sendTouchEvent.touchList;
70 if (aName === 'touchend') {
71 sendTouchEvent.touchList = null;
72 } else {
73 var coords = calculateTouchListCoordinates(aTouchPoints);
74 var touches = [];
75 for (var i = 0; i < coords.length; ++i) {
76 var {x, y} = coords[i];
77 var node = document.elementFromPoint(x, y);
78 var touch = document.createTouch(window, node, aName === 'touchstart' ?
79 1 : touchList.item(i).identifier, x, y, x, y);
80 touches.push(touch);
81 }
82 touchList = document.createTouchList(touches);
83 sendTouchEvent.touchList = touchList;
84 }
85 var evt = document.createEvent('TouchEvent');
86 evt.initTouchEvent(aName, true, true, window, 0, false, false, false, false,
87 touchList, touchList, touchList);
88 document.dispatchEvent(evt);
89 }
91 sendTouchEvent.touchList = null;
93 /**
94 * A map of event names to the functions that actually send them.
95 * @type {Object}
96 */
97 var eventMap = {
98 touchstart: sendTouchEvent,
99 touchend: sendTouchEvent,
100 touchmove: sendTouchEvent
101 };
103 var originalDwellThreshold = GestureSettings.dwellThreshold;
104 var originalSwipeMaxDuration = GestureSettings.swipeMaxDuration;
106 /**
107 * Attach a listener for the mozAccessFuGesture event that tests its
108 * type.
109 * @param {Array} aExpectedGestures A stack of expected event types.
110 * Note: the listener is removed once the stack reaches 0.
111 */
112 function testMozAccessFuGesture(aExpectedGestures) {
113 var types = typeof aExpectedGestures === "string" ?
114 [aExpectedGestures] : aExpectedGestures;
115 function handleGesture(aEvent) {
116 if (aEvent.detail.type !== types[0]) {
117 // The is not the event of interest.
118 return;
119 }
120 ok(true, 'Received correct mozAccessFuGesture: ' + types.shift() + '.');
121 if (types.length === 0) {
122 win.removeEventListener('mozAccessFuGesture', handleGesture);
123 if (AccessFuTest.sequenceCleanup) {
124 AccessFuTest.sequenceCleanup();
125 }
126 AccessFuTest.nextTest();
127 }
128 }
129 win.addEventListener('mozAccessFuGesture', handleGesture);
130 }
132 /**
133 * Reset the thresholds and max delays that affect gesture rejection.
134 * @param {Number} aTimeStamp Gesture time stamp.
135 * @param {Boolean} aRemoveDwellThreshold An optional flag to reset dwell
136 * threshold.
137 * @param {Boolean} aRemoveSwipeMaxDuration An optional flag to reset swipe max
138 * duration.
139 */
140 function setTimers(aTimeStamp, aRemoveDwellThreshold, aRemoveSwipeMaxDuration) {
141 if (!aRemoveDwellThreshold && !aRemoveSwipeMaxDuration) {
142 return;
143 }
144 if (aRemoveDwellThreshold) {
145 GestureSettings.dwellThreshold = 0;
146 }
147 if (aRemoveSwipeMaxDuration) {
148 GestureSettings.swipeMaxDuration = 0;
149 }
150 GestureTracker.current.clearTimer();
151 GestureTracker.current.startTimer(aTimeStamp);
152 }
154 function resetTimers() {
155 GestureSettings.dwellThreshold = originalDwellThreshold;
156 GestureSettings.swipeMaxDuration = originalSwipeMaxDuration;
157 }
159 /**
160 * An extention to AccessFuTest that adds an ability to test a sequence of
161 * pointer events and their expected mozAccessFuGesture events.
162 * @param {Object} aSequence An object that has a list of pointer events to be
163 * generated and the expected mozAccessFuGesture events.
164 */
165 AccessFuTest.addSequence = function AccessFuTest_addSequence(aSequence) {
166 AccessFuTest.addFunc(function testSequence() {
167 testMozAccessFuGesture(aSequence.expectedGestures);
168 var events = aSequence.events;
169 function fireEvent(aEvent) {
170 var event = {
171 points: convertPointCoordinates(aEvent.points),
172 type: aEvent.type
173 };
174 var timeStamp = Date.now();
175 resetTimers();
176 GestureTracker.handle(event, timeStamp);
177 setTimers(timeStamp, aEvent.removeDwellThreshold,
178 aEvent.removeSwipeMaxDuration);
179 processEvents();
180 }
181 function processEvents() {
182 if (events.length === 0) {
183 return;
184 }
185 var event = events.shift();
186 SimpleTest.executeSoon(function() {
187 fireEvent(event);
188 });
189 }
190 processEvents();
191 });
192 };
194 /**
195 * A helper function that loads JSON files.
196 * @param {String} aPath A path to a JSON file.
197 * @param {Function} aCallback A callback to be called on success.
198 */
199 function loadJSON(aPath, aCallback) {
200 var request = new XMLHttpRequest();
201 request.open('GET', aPath, true);
202 request.responseType = 'json';
203 request.onload = function onload() {
204 aCallback(request.response);
205 };
206 request.send();
207 }