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