Thu, 15 Jan 2015 15:59:08 +0100
Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 2 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 3 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 4 | |
michael@0 | 5 | 'use strict'; |
michael@0 | 6 | |
michael@0 | 7 | const { emit } = require('sdk/event/core'); |
michael@0 | 8 | const { EventTarget } = require('sdk/event/target'); |
michael@0 | 9 | const { Loader } = require('sdk/test/loader'); |
michael@0 | 10 | |
michael@0 | 11 | exports['test add a listener'] = function(assert) { |
michael@0 | 12 | let events = [ { name: 'event#1' }, 'event#2' ]; |
michael@0 | 13 | let target = EventTarget(); |
michael@0 | 14 | |
michael@0 | 15 | target.on('message', function(message) { |
michael@0 | 16 | assert.equal(this, target, 'this is a target object'); |
michael@0 | 17 | assert.equal(message, events.shift(), 'message is emitted event'); |
michael@0 | 18 | }); |
michael@0 | 19 | |
michael@0 | 20 | emit(target, 'message', events[0]); |
michael@0 | 21 | emit(target, 'message', events[0]); |
michael@0 | 22 | }; |
michael@0 | 23 | |
michael@0 | 24 | exports['test pass in listeners'] = function(assert) { |
michael@0 | 25 | let actual = [ ]; |
michael@0 | 26 | let target = EventTarget({ |
michael@0 | 27 | onMessage: function onMessage(message) { |
michael@0 | 28 | assert.equal(this, target, 'this is an event target'); |
michael@0 | 29 | actual.push(1); |
michael@0 | 30 | }, |
michael@0 | 31 | onFoo: null, |
michael@0 | 32 | onbla: function() { |
michael@0 | 33 | assert.fail('`onbla` is not supposed to be called'); |
michael@0 | 34 | } |
michael@0 | 35 | }); |
michael@0 | 36 | target.on('message', function(message) { |
michael@0 | 37 | assert.equal(this, target, 'this is an event target'); |
michael@0 | 38 | actual.push(2); |
michael@0 | 39 | }); |
michael@0 | 40 | |
michael@0 | 41 | emit(target, 'message'); |
michael@0 | 42 | emit(target, 'missing'); |
michael@0 | 43 | |
michael@0 | 44 | assert.deepEqual([ 1, 2 ], actual, 'all listeners trigerred in right order'); |
michael@0 | 45 | }; |
michael@0 | 46 | |
michael@0 | 47 | exports['test that listener is unique per type'] = function(assert) { |
michael@0 | 48 | let actual = [] |
michael@0 | 49 | let target = EventTarget(); |
michael@0 | 50 | function listener() { actual.push(1) } |
michael@0 | 51 | target.on('message', listener); |
michael@0 | 52 | target.on('message', listener); |
michael@0 | 53 | target.on('message', listener); |
michael@0 | 54 | target.on('foo', listener); |
michael@0 | 55 | target.on('foo', listener); |
michael@0 | 56 | |
michael@0 | 57 | emit(target, 'message'); |
michael@0 | 58 | assert.deepEqual([ 1 ], actual, 'only one message listener added'); |
michael@0 | 59 | emit(target, 'foo'); |
michael@0 | 60 | assert.deepEqual([ 1, 1 ], actual, 'same listener added for other event'); |
michael@0 | 61 | }; |
michael@0 | 62 | |
michael@0 | 63 | exports['test event type matters'] = function(assert) { |
michael@0 | 64 | let target = EventTarget(); |
michael@0 | 65 | target.on('message', function() { |
michael@0 | 66 | assert.fail('no event is expected'); |
michael@0 | 67 | }); |
michael@0 | 68 | target.on('done', function() { |
michael@0 | 69 | assert.pass('event is emitted'); |
michael@0 | 70 | }); |
michael@0 | 71 | |
michael@0 | 72 | emit(target, 'foo'); |
michael@0 | 73 | emit(target, 'done'); |
michael@0 | 74 | }; |
michael@0 | 75 | |
michael@0 | 76 | exports['test all arguments are pasesd'] = function(assert) { |
michael@0 | 77 | let foo = { name: 'foo' }, bar = 'bar'; |
michael@0 | 78 | let target = EventTarget(); |
michael@0 | 79 | target.on('message', function(a, b) { |
michael@0 | 80 | assert.equal(a, foo, 'first argument passed'); |
michael@0 | 81 | assert.equal(b, bar, 'second argument passed'); |
michael@0 | 82 | }); |
michael@0 | 83 | emit(target, 'message', foo, bar); |
michael@0 | 84 | }; |
michael@0 | 85 | |
michael@0 | 86 | exports['test no side-effects in emit'] = function(assert) { |
michael@0 | 87 | let target = EventTarget(); |
michael@0 | 88 | target.on('message', function() { |
michael@0 | 89 | assert.pass('first listener is called'); |
michael@0 | 90 | target.on('message', function() { |
michael@0 | 91 | assert.fail('second listener is called'); |
michael@0 | 92 | }); |
michael@0 | 93 | }); |
michael@0 | 94 | emit(target, 'message'); |
michael@0 | 95 | }; |
michael@0 | 96 | |
michael@0 | 97 | exports['test order of propagation'] = function(assert) { |
michael@0 | 98 | let actual = []; |
michael@0 | 99 | let target = EventTarget(); |
michael@0 | 100 | target.on('message', function() { actual.push(1); }); |
michael@0 | 101 | target.on('message', function() { actual.push(2); }); |
michael@0 | 102 | target.on('message', function() { actual.push(3); }); |
michael@0 | 103 | emit(target, 'message'); |
michael@0 | 104 | assert.deepEqual([ 1, 2, 3 ], actual, 'called in order they were added'); |
michael@0 | 105 | }; |
michael@0 | 106 | |
michael@0 | 107 | exports['test remove a listener'] = function(assert) { |
michael@0 | 108 | let target = EventTarget(); |
michael@0 | 109 | let actual = []; |
michael@0 | 110 | target.on('message', function listener() { |
michael@0 | 111 | actual.push(1); |
michael@0 | 112 | target.on('message', function() { |
michael@0 | 113 | target.removeListener('message', listener); |
michael@0 | 114 | actual.push(2); |
michael@0 | 115 | }) |
michael@0 | 116 | }); |
michael@0 | 117 | |
michael@0 | 118 | target.off('message'); // must do nothing. |
michael@0 | 119 | emit(target, 'message'); |
michael@0 | 120 | assert.deepEqual([ 1 ], actual, 'first listener called'); |
michael@0 | 121 | emit(target, 'message'); |
michael@0 | 122 | assert.deepEqual([ 1, 1, 2 ], actual, 'second listener called'); |
michael@0 | 123 | emit(target, 'message'); |
michael@0 | 124 | assert.deepEqual([ 1, 1, 2, 2, 2 ], actual, 'first listener removed'); |
michael@0 | 125 | }; |
michael@0 | 126 | |
michael@0 | 127 | exports['test error handling'] = function(assert) { |
michael@0 | 128 | let target = EventTarget(); |
michael@0 | 129 | let error = Error('boom!'); |
michael@0 | 130 | |
michael@0 | 131 | target.on('message', function() { throw error; }) |
michael@0 | 132 | target.on('error', function(boom) { |
michael@0 | 133 | assert.equal(boom, error, 'thrown exception causes error event'); |
michael@0 | 134 | }); |
michael@0 | 135 | emit(target, 'message'); |
michael@0 | 136 | }; |
michael@0 | 137 | |
michael@0 | 138 | exports['test unhandled errors'] = function(assert) { |
michael@0 | 139 | let exceptions = []; |
michael@0 | 140 | let loader = Loader(module); |
michael@0 | 141 | let { emit } = loader.require('sdk/event/core'); |
michael@0 | 142 | let { EventTarget } = loader.require('sdk/event/target'); |
michael@0 | 143 | Object.defineProperties(loader.sandbox('sdk/event/core'), { |
michael@0 | 144 | console: { value: { |
michael@0 | 145 | exception: function(e) { |
michael@0 | 146 | exceptions.push(e); |
michael@0 | 147 | } |
michael@0 | 148 | }} |
michael@0 | 149 | }); |
michael@0 | 150 | let target = EventTarget(); |
michael@0 | 151 | let boom = Error('Boom!'); |
michael@0 | 152 | let drax = Error('Draax!!'); |
michael@0 | 153 | |
michael@0 | 154 | target.on('message', function() { throw boom; }); |
michael@0 | 155 | |
michael@0 | 156 | emit(target, 'message'); |
michael@0 | 157 | assert.ok(~String(exceptions[0]).indexOf('Boom!'), |
michael@0 | 158 | 'unhandled exception is logged'); |
michael@0 | 159 | |
michael@0 | 160 | target.on('error', function() { throw drax; }); |
michael@0 | 161 | emit(target, 'message'); |
michael@0 | 162 | assert.ok(~String(exceptions[1]).indexOf('Draax!'), |
michael@0 | 163 | 'error in error handler is logged'); |
michael@0 | 164 | }; |
michael@0 | 165 | |
michael@0 | 166 | exports['test target is chainable'] = function (assert, done) { |
michael@0 | 167 | let loader = Loader(module); |
michael@0 | 168 | let exceptions = []; |
michael@0 | 169 | let { EventTarget } = loader.require('sdk/event/target'); |
michael@0 | 170 | let { emit } = loader.require('sdk/event/core'); |
michael@0 | 171 | Object.defineProperties(loader.sandbox('sdk/event/core'), { |
michael@0 | 172 | console: { value: { |
michael@0 | 173 | exception: function(e) { |
michael@0 | 174 | exceptions.push(e); |
michael@0 | 175 | } |
michael@0 | 176 | }} |
michael@0 | 177 | }); |
michael@0 | 178 | |
michael@0 | 179 | let emitter = EventTarget(); |
michael@0 | 180 | let boom = Error('Boom'); |
michael@0 | 181 | let onceCalled = 0; |
michael@0 | 182 | |
michael@0 | 183 | emitter.once('oneTime', function () { |
michael@0 | 184 | assert.equal(++onceCalled, 1, 'once event called only once'); |
michael@0 | 185 | }).on('data', function (message) { |
michael@0 | 186 | assert.equal(message, 'message', 'handles event'); |
michael@0 | 187 | emit(emitter, 'oneTime'); |
michael@0 | 188 | emit(emitter, 'data2', 'message2'); |
michael@0 | 189 | }).on('phony', function () { |
michael@0 | 190 | assert.fail('removeListener does not remove chained event'); |
michael@0 | 191 | }).removeListener('phony') |
michael@0 | 192 | .on('data2', function (message) { |
michael@0 | 193 | assert.equal(message, 'message2', 'handle chained event'); |
michael@0 | 194 | emit(emitter, 'oneTime'); |
michael@0 | 195 | throw boom; |
michael@0 | 196 | }).on('error', function (error) { |
michael@0 | 197 | assert.equal(error, boom, 'error handled in chained event'); |
michael@0 | 198 | done(); |
michael@0 | 199 | }); |
michael@0 | 200 | |
michael@0 | 201 | emit(emitter, 'data', 'message'); |
michael@0 | 202 | }; |
michael@0 | 203 | |
michael@0 | 204 | require('test').run(exports); |
michael@0 | 205 |