Thu, 15 Jan 2015 21:03:48 +0100
Integrate friendly tips from Tor colleagues to make (or not) 4.5 alpha 3;
This includes removal of overloaded (but unused) methods, and addition of
a overlooked call to DataStruct::SetData(nsISupports, uint32_t, bool.)
michael@0 | 1 | <!DOCTYPE HTML> |
michael@0 | 2 | <html> |
michael@0 | 3 | <!-- |
michael@0 | 4 | https://bugzilla.mozilla.org/show_bug.cgi?id=897221 |
michael@0 | 5 | --> |
michael@0 | 6 | <head> |
michael@0 | 7 | <title>Test for User Agent Updates</title> |
michael@0 | 8 | <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script> |
michael@0 | 9 | <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" /> |
michael@0 | 10 | </head> |
michael@0 | 11 | <body> |
michael@0 | 12 | <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=897221">Mozilla Bug 897221</a> |
michael@0 | 13 | <p id="display"></p> |
michael@0 | 14 | <div id="content" style="display: none"></div> |
michael@0 | 15 | <pre id="test"> |
michael@0 | 16 | <script class="testbody" type="text/javascript"> |
michael@0 | 17 | |
michael@0 | 18 | const PREF_APP_UPDATE_TIMERMINIMUMDELAY = "app.update.timerMinimumDelay"; |
michael@0 | 19 | const PREF_UPDATES = "general.useragent.updates."; |
michael@0 | 20 | const PREF_UPDATES_ENABLED = PREF_UPDATES + "enabled"; |
michael@0 | 21 | const PREF_UPDATES_URL = PREF_UPDATES + "url"; |
michael@0 | 22 | const PREF_UPDATES_INTERVAL = PREF_UPDATES + "interval"; |
michael@0 | 23 | const PREF_UPDATES_TIMEOUT = PREF_UPDATES + "timeout"; |
michael@0 | 24 | |
michael@0 | 25 | const KEY_PREFDIR = "PrefD"; |
michael@0 | 26 | const KEY_APPDIR = "XCurProcD"; |
michael@0 | 27 | const FILE_UPDATES = "ua-update.json"; |
michael@0 | 28 | |
michael@0 | 29 | const DEFAULT_UA = navigator.userAgent; |
michael@0 | 30 | const UA_OVERRIDE = "DummyUserAgent"; |
michael@0 | 31 | const UA_ALT_OVERRIDE = "AltUserAgent"; |
michael@0 | 32 | |
michael@0 | 33 | const UA_PARTIAL_FROM = "\\wozilla"; // /\wozilla |
michael@0 | 34 | const UA_PARTIAL_SEP = "#"; |
michael@0 | 35 | const UA_PARTIAL_TO = UA_OVERRIDE; |
michael@0 | 36 | const UA_PARTIAL_OVERRIDE = UA_PARTIAL_FROM + UA_PARTIAL_SEP + UA_PARTIAL_TO; |
michael@0 | 37 | const UA_PARTIAL_EXPECTED = DEFAULT_UA.replace(new RegExp(UA_PARTIAL_FROM, 'g'), UA_PARTIAL_TO); |
michael@0 | 38 | |
michael@0 | 39 | function getUA(host) { |
michael@0 | 40 | var url = location.pathname; |
michael@0 | 41 | url = host + url.slice(0, url.lastIndexOf('/')) + '/user_agent.sjs'; |
michael@0 | 42 | |
michael@0 | 43 | var xhr = new XMLHttpRequest(); |
michael@0 | 44 | xhr.open('GET', url, false); // sync request |
michael@0 | 45 | xhr.send(); |
michael@0 | 46 | is(xhr.status, 200, 'request failed'); |
michael@0 | 47 | is(typeof xhr.response, 'string', 'invalid response'); |
michael@0 | 48 | return xhr.response; |
michael@0 | 49 | } |
michael@0 | 50 | |
michael@0 | 51 | const OVERRIDES = [ |
michael@0 | 52 | { |
michael@0 | 53 | domain: 'example.org', |
michael@0 | 54 | override: '%DATE%', |
michael@0 | 55 | host: 'http://example.org' |
michael@0 | 56 | }, |
michael@0 | 57 | { |
michael@0 | 58 | domain: 'test1.example.org', |
michael@0 | 59 | override: '%PRODUCT%', |
michael@0 | 60 | expected: SpecialPowers.Services.appinfo.name, |
michael@0 | 61 | host: 'http://test1.example.org' |
michael@0 | 62 | }, |
michael@0 | 63 | { |
michael@0 | 64 | domain: 'test2.example.org', |
michael@0 | 65 | override: '%APP_ID%', |
michael@0 | 66 | expected: SpecialPowers.Services.appinfo.ID, |
michael@0 | 67 | host: 'http://test2.example.org' |
michael@0 | 68 | }, |
michael@0 | 69 | { |
michael@0 | 70 | domain: 'sub1.test1.example.org', |
michael@0 | 71 | override: '%APP_VERSION%', |
michael@0 | 72 | expected: SpecialPowers.Services.appinfo.version, |
michael@0 | 73 | host: 'http://sub1.test1.example.org' |
michael@0 | 74 | }, |
michael@0 | 75 | { |
michael@0 | 76 | domain: 'sub2.test1.example.org', |
michael@0 | 77 | override: '%BUILD_ID%', |
michael@0 | 78 | expected: SpecialPowers.Services.appinfo.appBuildID, |
michael@0 | 79 | host: 'http://sub2.test1.example.org' |
michael@0 | 80 | }, |
michael@0 | 81 | { |
michael@0 | 82 | domain: 'sub1.test2.example.org', |
michael@0 | 83 | override: '%OS%', |
michael@0 | 84 | expected: SpecialPowers.Services.appinfo.OS, |
michael@0 | 85 | host: 'http://sub1.test2.example.org' |
michael@0 | 86 | }, |
michael@0 | 87 | { |
michael@0 | 88 | domain: 'sub2.test2.example.org', |
michael@0 | 89 | override: UA_PARTIAL_OVERRIDE, |
michael@0 | 90 | expected: UA_PARTIAL_EXPECTED, |
michael@0 | 91 | host: 'http://sub2.test2.example.org' |
michael@0 | 92 | }, |
michael@0 | 93 | ]; |
michael@0 | 94 | |
michael@0 | 95 | function getServerURL() { |
michael@0 | 96 | var url = location.pathname; |
michael@0 | 97 | return location.origin + url.slice(0, url.lastIndexOf('/')) + '/user_agent_update.sjs?'; |
michael@0 | 98 | } |
michael@0 | 99 | |
michael@0 | 100 | function getUpdateURL() { |
michael@0 | 101 | var url = getServerURL(); |
michael@0 | 102 | var overrides = {}; |
michael@0 | 103 | overrides[location.hostname] = UA_OVERRIDE; |
michael@0 | 104 | OVERRIDES.forEach(function (val) { |
michael@0 | 105 | overrides[val.domain] = val.override; |
michael@0 | 106 | }); |
michael@0 | 107 | url = url + encodeURIComponent(JSON.stringify(overrides)).replace(/%25/g, '%'); |
michael@0 | 108 | return url; |
michael@0 | 109 | } |
michael@0 | 110 | |
michael@0 | 111 | function testDownload(callback) { |
michael@0 | 112 | var startTime = Date.now(); |
michael@0 | 113 | var url = getUpdateURL(); |
michael@0 | 114 | isnot(navigator.userAgent, UA_OVERRIDE, 'UA already overridden'); |
michael@0 | 115 | info('Waiting for UA update: ' + url); |
michael@0 | 116 | SpecialPowers.pushPrefEnv({ |
michael@0 | 117 | set: [ |
michael@0 | 118 | [PREF_UPDATES_ENABLED, true], |
michael@0 | 119 | [PREF_UPDATES_URL, url], |
michael@0 | 120 | [PREF_UPDATES_TIMEOUT, 10000], |
michael@0 | 121 | [PREF_UPDATES_INTERVAL, 1] // 1 second interval |
michael@0 | 122 | ] |
michael@0 | 123 | }, function waitForUpdate() setTimeout(function () { |
michael@0 | 124 | if (navigator.userAgent !== UA_OVERRIDE) { |
michael@0 | 125 | waitForUpdate(); |
michael@0 | 126 | return; |
michael@0 | 127 | } |
michael@0 | 128 | info('Overrode navigator UA'); |
michael@0 | 129 | is(getUA(location.origin), UA_OVERRIDE, 'Header UA not overridden'); |
michael@0 | 130 | |
michael@0 | 131 | var updateTime = parseInt(getUA('http://example.org')); |
michael@0 | 132 | ok(startTime <= updateTime, 'Update was before start time'); |
michael@0 | 133 | ok(updateTime <= Date.now(), 'Update was after present time'); |
michael@0 | 134 | |
michael@0 | 135 | OVERRIDES.forEach(function (val) { |
michael@0 | 136 | val.expected && is(getUA(val.host), val.expected, |
michael@0 | 137 | 'Incorrect URL parameter: ' + val.override); |
michael@0 | 138 | }); |
michael@0 | 139 | callback(); |
michael@0 | 140 | }, 100)); |
michael@0 | 141 | } |
michael@0 | 142 | |
michael@0 | 143 | function testBadUpdate(callback) { |
michael@0 | 144 | var url = getServerURL() + 'invalid-json'; |
michael@0 | 145 | var prevOverride = navigator.userAgent; |
michael@0 | 146 | SpecialPowers.pushPrefEnv({ |
michael@0 | 147 | set: [ |
michael@0 | 148 | [PREF_UPDATES_URL, url], |
michael@0 | 149 | [PREF_UPDATES_INTERVAL, 1] // 1 second interval |
michael@0 | 150 | ] |
michael@0 | 151 | }, function () setTimeout(function () { |
michael@0 | 152 | // We want to make sure a bad update doesn't cancel out previous overrides. |
michael@0 | 153 | // We do this by waiting for 5 seconds (assuming the update occurs within 5 |
michael@0 | 154 | // seconds), and check that the previous override hasn't changed. |
michael@0 | 155 | is(navigator.userAgent, prevOverride, |
michael@0 | 156 | 'Invalid update deleted previous override'); |
michael@0 | 157 | callback(); |
michael@0 | 158 | }, 5000)); |
michael@0 | 159 | } |
michael@0 | 160 | |
michael@0 | 161 | function testProfileLoad(callback) { |
michael@0 | 162 | var file = FU.getFile(KEY_APPDIR, [FILE_UPDATES]).path; |
michael@0 | 163 | var encoder = SpecialPowers.wrap(new TextEncoder()); |
michael@0 | 164 | var overrides = {}; |
michael@0 | 165 | overrides[location.hostname] = UA_ALT_OVERRIDE; |
michael@0 | 166 | var bytes = encoder.encode(JSON.stringify(overrides)); |
michael@0 | 167 | |
michael@0 | 168 | var badfile = FU.getFile(KEY_PREFDIR, [FILE_UPDATES]).path; |
michael@0 | 169 | var badbytes = encoder.encode("null"); |
michael@0 | 170 | |
michael@0 | 171 | OSF.writeAtomic(file, bytes, {tmpPath: file + ".tmp"}).then( |
michael@0 | 172 | () => OSF.writeAtomic(badfile, badbytes, {tmpPath: badfile + ".tmp"}) |
michael@0 | 173 | ).then( |
michael@0 | 174 | () => { |
michael@0 | 175 | SpecialPowers.pushPrefEnv({ |
michael@0 | 176 | set: [[PREF_UPDATES_ENABLED, true]] |
michael@0 | 177 | }, function () { |
michael@0 | 178 | // initialize UserAgentOverrides.jsm and |
michael@0 | 179 | // UserAgentUpdates.jsm and load saved file |
michael@0 | 180 | UAO.init(); |
michael@0 | 181 | (function waitForLoad() { |
michael@0 | 182 | if (navigator.userAgent !== UA_ALT_OVERRIDE) { |
michael@0 | 183 | setTimeout(waitForLoad, 100); |
michael@0 | 184 | return; |
michael@0 | 185 | } |
michael@0 | 186 | is(getUA(location.origin), UA_ALT_OVERRIDE, 'Did not apply saved override'); |
michael@0 | 187 | saveFilePreviousSize = file.fileSize; |
michael@0 | 188 | callback(); |
michael@0 | 189 | })(); |
michael@0 | 190 | }); |
michael@0 | 191 | }, |
michael@0 | 192 | (reason) => { |
michael@0 | 193 | throw reason |
michael@0 | 194 | } |
michael@0 | 195 | ); |
michael@0 | 196 | } |
michael@0 | 197 | |
michael@0 | 198 | function testProfileSave(callback) { |
michael@0 | 199 | info('Waiting for saving to profile'); |
michael@0 | 200 | var file = FU.getFile(KEY_PREFDIR, [FILE_UPDATES]).path; |
michael@0 | 201 | (function waitForSave() { |
michael@0 | 202 | OSF.exists(file).then( |
michael@0 | 203 | (exists) => { |
michael@0 | 204 | if (!exists) { |
michael@0 | 205 | setTimeout(waitForSave, 100); |
michael@0 | 206 | return; |
michael@0 | 207 | } |
michael@0 | 208 | return OSF.read(file).then( |
michael@0 | 209 | (bytes) => { |
michael@0 | 210 | info('Saved new overrides'); |
michael@0 | 211 | var decoder = SpecialPowers.wrap(new TextDecoder()); |
michael@0 | 212 | var overrides = JSON.parse(decoder.decode(bytes)); |
michael@0 | 213 | is(overrides[location.hostname], UA_OVERRIDE, 'Incorrect saved override'); |
michael@0 | 214 | OVERRIDES.forEach(function (val) { |
michael@0 | 215 | val.expected && is(overrides[val.domain], val.expected, |
michael@0 | 216 | 'Incorrect saved override: ' + val.override); |
michael@0 | 217 | }); |
michael@0 | 218 | callback(); |
michael@0 | 219 | } |
michael@0 | 220 | ); |
michael@0 | 221 | } |
michael@0 | 222 | ).then(null, |
michael@0 | 223 | (reason) => { |
michael@0 | 224 | throw reason |
michael@0 | 225 | } |
michael@0 | 226 | ); |
michael@0 | 227 | })(); |
michael@0 | 228 | } |
michael@0 | 229 | |
michael@0 | 230 | SimpleTest.waitForExplicitFinish(); |
michael@0 | 231 | |
michael@0 | 232 | SpecialPowers.Cu.import("resource://gre/modules/FileUtils.jsm", window); |
michael@0 | 233 | var FU = SpecialPowers.wrap(FileUtils); |
michael@0 | 234 | |
michael@0 | 235 | SpecialPowers.Cu.import("resource://gre/modules/osfile.jsm", window); |
michael@0 | 236 | var OSF = SpecialPowers.wrap(OS).File; |
michael@0 | 237 | |
michael@0 | 238 | // Load UserAgentOverrides.jsm after we load update timer manager |
michael@0 | 239 | var UAO = null; |
michael@0 | 240 | |
michael@0 | 241 | var saveFilePreviousSize = 0; |
michael@0 | 242 | |
michael@0 | 243 | SpecialPowers.pushPrefEnv({ |
michael@0 | 244 | set: [ |
michael@0 | 245 | [PREF_APP_UPDATE_TIMERMINIMUMDELAY, 0] |
michael@0 | 246 | ] |
michael@0 | 247 | }, function () { |
michael@0 | 248 | // Enter update timer manager test mode |
michael@0 | 249 | (SpecialPowers.Cc["@mozilla.org/updates/timer-manager;1"].getService( |
michael@0 | 250 | SpecialPowers.Ci.nsIObserver)).observe(null, "utm-test-init", ""); |
michael@0 | 251 | |
michael@0 | 252 | SpecialPowers.Cu.import('resource://gre/modules/UserAgentOverrides.jsm', window); |
michael@0 | 253 | UAO = SpecialPowers.wrap(UserAgentOverrides); |
michael@0 | 254 | UAO.uninit(); |
michael@0 | 255 | |
michael@0 | 256 | // testProfileLoad, testDownload, and testProfileSave must run in this order |
michael@0 | 257 | // because testDownload depends on testProfileLoad to call UAO.init() |
michael@0 | 258 | // and testProfileSave depends on testDownload to save overrides to the profile |
michael@0 | 259 | testProfileLoad(function() |
michael@0 | 260 | testDownload(function() |
michael@0 | 261 | testBadUpdate(function() |
michael@0 | 262 | testProfileSave(SimpleTest.finish) |
michael@0 | 263 | ) |
michael@0 | 264 | ) |
michael@0 | 265 | ); |
michael@0 | 266 | }); |
michael@0 | 267 | |
michael@0 | 268 | </script> |
michael@0 | 269 | </pre> |
michael@0 | 270 | </body> |
michael@0 | 271 | </html> |
michael@0 | 272 |