Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim: set ts=2 et sw=2 tw=80: */
3 /* Any copyright is dedicated to the Public Domain.
4 * http://creativecommons.org/publicdomain/zero/1.0/
5 */
7 const PREF_POSTUPDATE = "app.update.postupdate";
8 const PREF_MSTONE = "browser.startup.homepage_override.mstone";
9 const PREF_OVERRIDE_URL = "startup.homepage_override_url";
11 const DEFAULT_PREF_URL = "http://pref.example.com/";
12 const DEFAULT_UPDATE_URL = "http://example.com/";
14 const XML_EMPTY = "<?xml version=\"1.0\"?><updates xmlns=" +
15 "\"http://www.mozilla.org/2005/app-update\"></updates>";
17 const XML_PREFIX = "<updates xmlns=\"http://www.mozilla.org/2005/app-update\"" +
18 "><update appVersion=\"1.0\" buildID=\"20080811053724\" " +
19 "channel=\"nightly\" displayVersion=\"Version 1.0\" " +
20 "extensionVersion=\"1.0\" installDate=\"1238441400314\" " +
21 "isCompleteUpdate=\"true\" name=\"Update Test 1.0\" " +
22 "serviceURL=\"https://example.com/\" showNeverForVersion=" +
23 "\"false\" showPrompt=\"false\" type=" +
24 "\"minor\" version=\"version 1.0\" detailsURL=" +
25 "\"http://example.com/\" previousAppVersion=\"1.0\" " +
26 "statusText=\"The Update was successfully installed\" " +
27 "foregroundDownload=\"true\"";
29 const XML_SUFFIX = "><patch type=\"complete\" URL=\"http://example.com/\" " +
30 "hashFunction=\"MD5\" hashValue=" +
31 "\"6232cd43a1c77e30191c53a329a3f99d\" size=\"775\" " +
32 "selected=\"true\" state=\"succeeded\"/></update></updates>";
34 // nsBrowserContentHandler.js defaultArgs tests
35 const BCH_TESTS = [
36 {
37 description: "no mstone change and no update",
38 noPostUpdatePref: true,
39 noMstoneChange: true
40 }, {
41 description: "mstone changed and no update",
42 noPostUpdatePref: true,
43 prefURL: DEFAULT_PREF_URL
44 }, {
45 description: "no mstone change and update with 'showURL' for actions",
46 actions: "showURL",
47 noMstoneChange: true
48 }, {
49 description: "update without actions",
50 prefURL: DEFAULT_PREF_URL
51 }, {
52 description: "update with 'showURL' for actions",
53 actions: "showURL",
54 prefURL: DEFAULT_PREF_URL
55 }, {
56 description: "update with 'showURL' for actions and openURL",
57 actions: "showURL",
58 openURL: DEFAULT_UPDATE_URL
59 }, {
60 description: "update with 'showURL showAlert' for actions",
61 actions: "showAlert showURL",
62 prefURL: DEFAULT_PREF_URL
63 }, {
64 description: "update with 'showAlert showURL' for actions and openURL",
65 actions: "showAlert showURL",
66 openURL: DEFAULT_UPDATE_URL
67 }, {
68 description: "update with 'showURL showNotification' for actions",
69 actions: "showURL showNotification",
70 prefURL: DEFAULT_PREF_URL
71 }, {
72 description: "update with 'showNotification showURL' for actions and " +
73 "openURL",
74 actions: "showNotification showURL",
75 openURL: DEFAULT_UPDATE_URL
76 }, {
77 description: "update with 'showAlert showURL showNotification' for actions",
78 actions: "showAlert showURL showNotification",
79 prefURL: DEFAULT_PREF_URL
80 }, {
81 description: "update with 'showNotification showURL showAlert' for " +
82 "actions and openURL",
83 actions: "showNotification showURL showAlert",
84 openURL: DEFAULT_UPDATE_URL
85 }, {
86 description: "update with 'showAlert' for actions",
87 actions: "showAlert"
88 }, {
89 description: "update with 'showAlert showNotification' for actions",
90 actions: "showAlert showNotification"
91 }, {
92 description: "update with 'showNotification' for actions",
93 actions: "showNotification"
94 }, {
95 description: "update with 'showNotification showAlert' for actions",
96 actions: "showNotification showAlert"
97 }, {
98 description: "update with 'silent' for actions",
99 actions: "silent"
100 }, {
101 description: "update with 'silent showURL showAlert showNotification' " +
102 "for actions and openURL",
103 actions: "silent showURL showAlert showNotification"
104 }
105 ];
107 var gOriginalMStone;
108 var gOriginalOverrideURL;
110 this.__defineGetter__("gBG", function() {
111 delete this.gBG;
112 return this.gBG = Cc["@mozilla.org/browser/browserglue;1"].
113 getService(Ci.nsIBrowserGlue).
114 QueryInterface(Ci.nsIObserver);
115 });
117 function test()
118 {
119 waitForExplicitFinish();
121 // Reset the startup page pref since it may have been set by other tests
122 // and we will assume it is default.
123 Services.prefs.clearUserPref('browser.startup.page');
125 if (gPrefService.prefHasUserValue(PREF_MSTONE)) {
126 gOriginalMStone = gPrefService.getCharPref(PREF_MSTONE);
127 }
129 if (gPrefService.prefHasUserValue(PREF_OVERRIDE_URL)) {
130 gOriginalOverrideURL = gPrefService.getCharPref(PREF_OVERRIDE_URL);
131 }
133 testDefaultArgs();
134 }
136 var gWindowCatcher = {
137 windowsOpen: 0,
138 finishCalled: false,
139 start: function() {
140 Services.ww.registerNotification(this);
141 },
143 finish: function(aFunc) {
144 Services.ww.unregisterNotification(this);
145 this.finishFunc = aFunc;
146 if (this.windowsOpen > 0)
147 return;
149 this.finishFunc();
150 },
152 closeWindow: function (win) {
153 info("window catcher closing window: " + win.document.documentURI);
154 win.close();
155 this.windowsOpen--;
156 if (this.finishFunc) {
157 this.finish(this.finishFunc);
158 }
159 },
161 windowLoad: function (win) {
162 executeSoon(this.closeWindow.bind(this, win));
163 },
165 observe: function(subject, topic, data) {
166 if (topic != "domwindowopened")
167 return;
169 this.windowsOpen++;
170 let win = subject.QueryInterface(Ci.nsIDOMWindow);
171 info("window catcher caught window opening: " + win.document.documentURI);
172 win.addEventListener("load", function () {
173 win.removeEventListener("load", arguments.callee, false);
174 gWindowCatcher.windowLoad(win);
175 }, false);
176 }
177 };
179 function finish_test()
180 {
181 // Reset browser.startup.homepage_override.mstone to the original value or
182 // clear it if it didn't exist.
183 if (gOriginalMStone) {
184 gPrefService.setCharPref(PREF_MSTONE, gOriginalMStone);
185 } else if (gPrefService.prefHasUserValue(PREF_MSTONE)) {
186 gPrefService.clearUserPref(PREF_MSTONE);
187 }
189 // Reset startup.homepage_override_url to the original value or clear it if
190 // it didn't exist.
191 if (gOriginalOverrideURL) {
192 gPrefService.setCharPref(PREF_OVERRIDE_URL, gOriginalOverrideURL);
193 } else if (gPrefService.prefHasUserValue(PREF_OVERRIDE_URL)) {
194 gPrefService.clearUserPref(PREF_OVERRIDE_URL);
195 }
197 writeUpdatesToXMLFile(XML_EMPTY);
198 reloadUpdateManagerData();
200 finish();
201 }
203 // Test the defaultArgs returned by nsBrowserContentHandler after an update
204 function testDefaultArgs()
205 {
206 // Clear any pre-existing override in defaultArgs that are hanging around.
207 // This will also set the browser.startup.homepage_override.mstone preference
208 // if it isn't already set.
209 Cc["@mozilla.org/browser/clh;1"].getService(Ci.nsIBrowserHandler).defaultArgs;
211 let originalMstone = gPrefService.getCharPref(PREF_MSTONE);
213 gPrefService.setCharPref(PREF_OVERRIDE_URL, DEFAULT_PREF_URL);
215 writeUpdatesToXMLFile(XML_EMPTY);
216 reloadUpdateManagerData();
218 for (let i = 0; i < BCH_TESTS.length; i++) {
219 let test = BCH_TESTS[i];
220 ok(true, "Test nsBrowserContentHandler " + (i + 1) + ": " + test.description);
222 if (test.actions) {
223 let actionsXML = " actions=\"" + test.actions + "\"";
224 if (test.openURL) {
225 actionsXML += " openURL=\"" + test.openURL + "\"";
226 }
227 writeUpdatesToXMLFile(XML_PREFIX + actionsXML + XML_SUFFIX);
228 } else {
229 writeUpdatesToXMLFile(XML_EMPTY);
230 }
232 reloadUpdateManagerData();
234 let noOverrideArgs = Cc["@mozilla.org/browser/clh;1"].
235 getService(Ci.nsIBrowserHandler).defaultArgs;
237 let overrideArgs = "";
238 if (test.prefURL) {
239 overrideArgs = test.prefURL;
240 } else if (test.openURL) {
241 overrideArgs = test.openURL;
242 }
244 if (overrideArgs == "" && noOverrideArgs) {
245 overrideArgs = noOverrideArgs;
246 } else if (noOverrideArgs) {
247 overrideArgs += "|" + noOverrideArgs;
248 }
250 if (test.noMstoneChange === undefined) {
251 gPrefService.setCharPref(PREF_MSTONE, "PreviousMilestone");
252 }
254 if (test.noPostUpdatePref == undefined) {
255 gPrefService.setBoolPref(PREF_POSTUPDATE, true);
256 }
258 let defaultArgs = Cc["@mozilla.org/browser/clh;1"].
259 getService(Ci.nsIBrowserHandler).defaultArgs;
260 is(defaultArgs, overrideArgs, "correct value returned by defaultArgs");
262 if (test.noMstoneChange === undefined || test.noMstoneChange != true) {
263 let newMstone = gPrefService.getCharPref(PREF_MSTONE);
264 is(originalMstone, newMstone, "preference " + PREF_MSTONE +
265 " should have been updated");
266 }
268 if (gPrefService.prefHasUserValue(PREF_POSTUPDATE)) {
269 gPrefService.clearUserPref(PREF_POSTUPDATE);
270 }
271 }
273 testShowNotification();
274 }
276 // nsBrowserGlue.js _showUpdateNotification notification tests
277 const BG_NOTIFY_TESTS = [
278 {
279 description: "'silent showNotification' actions should not display a notification",
280 actions: "silent showNotification"
281 }, {
282 description: "'showNotification' for actions should display a notification",
283 actions: "showNotification"
284 }, {
285 description: "no actions and empty updates.xml",
286 }, {
287 description: "'showAlert' for actions should not display a notification",
288 actions: "showAlert"
289 }, {
290 // This test MUST be the last test in the array to test opening the url
291 // provided by the updates.xml.
292 description: "'showNotification' for actions with custom notification " +
293 "attributes should display a notification",
294 actions: "showNotification",
295 notificationText: "notification text",
296 notificationURL: DEFAULT_UPDATE_URL,
297 notificationButtonLabel: "button label",
298 notificationButtonAccessKey: "b"
299 }
300 ];
302 // Test showing a notification after an update
303 // _showUpdateNotification in nsBrowserGlue.js
304 function testShowNotification()
305 {
306 let gTestBrowser = gBrowser.selectedBrowser;
307 let notifyBox = gBrowser.getNotificationBox(gTestBrowser);
309 // Catches any windows opened by these tests (e.g. alert windows) and closes
310 // them
311 gWindowCatcher.start();
313 for (let i = 0; i < BG_NOTIFY_TESTS.length; i++) {
314 let test = BG_NOTIFY_TESTS[i];
315 ok(true, "Test showNotification " + (i + 1) + ": " + test.description);
317 if (test.actions) {
318 let actionsXML = " actions=\"" + test.actions + "\"";
319 if (test.notificationText) {
320 actionsXML += " notificationText=\"" + test.notificationText + "\"";
321 }
322 if (test.notificationURL) {
323 actionsXML += " notificationURL=\"" + test.notificationURL + "\"";
324 }
325 if (test.notificationButtonLabel) {
326 actionsXML += " notificationButtonLabel=\"" + test.notificationButtonLabel + "\"";
327 }
328 if (test.notificationButtonAccessKey) {
329 actionsXML += " notificationButtonAccessKey=\"" + test.notificationButtonAccessKey + "\"";
330 }
331 writeUpdatesToXMLFile(XML_PREFIX + actionsXML + XML_SUFFIX);
332 } else {
333 writeUpdatesToXMLFile(XML_EMPTY);
334 }
336 reloadUpdateManagerData();
337 gPrefService.setBoolPref(PREF_POSTUPDATE, true);
339 gBG.observe(null, "browser-glue-test", "post-update-notification");
341 let updateBox = notifyBox.getNotificationWithValue("post-update-notification");
342 if (test.actions && test.actions.indexOf("showNotification") != -1 &&
343 test.actions.indexOf("silent") == -1) {
344 ok(updateBox, "Update notification box should have been displayed");
345 if (updateBox) {
346 if (test.notificationText) {
347 is(updateBox.label, test.notificationText, "Update notification box " +
348 "should have the label provided by the update");
349 }
350 if (test.notificationButtonLabel) {
351 var button = updateBox.getElementsByTagName("button").item(0);
352 is(button.label, test.notificationButtonLabel, "Update notification " +
353 "box button should have the label provided by the update");
354 if (test.notificationButtonAccessKey) {
355 let accessKey = button.getAttribute("accesskey");
356 is(accessKey, test.notificationButtonAccessKey, "Update " +
357 "notification box button should have the accesskey " +
358 "provided by the update");
359 }
360 }
361 // The last test opens an url and verifies the url from the updates.xml
362 // is correct.
363 if (i == (BG_NOTIFY_TESTS.length - 1)) {
364 // Wait for any windows caught by the windowcatcher to close
365 gWindowCatcher.finish(function () {
366 button.click();
367 gBrowser.selectedBrowser.addEventListener("load", function () {
368 gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
369 testNotificationURL();
370 }, true);
371 });
372 } else {
373 notifyBox.removeAllNotifications(true);
374 }
375 } else if (i == (BG_NOTIFY_TESTS.length - 1)) {
376 // If updateBox is null the test has already reported errors so bail
377 finish_test();
378 }
379 } else {
380 ok(!updateBox, "Update notification box should not have been displayed");
381 }
383 let prefHasUserValue = gPrefService.prefHasUserValue(PREF_POSTUPDATE);
384 is(prefHasUserValue, false, "preference " + PREF_POSTUPDATE +
385 " shouldn't have a user value");
386 }
387 }
389 // Test opening the url provided by the updates.xml in the last test
390 function testNotificationURL()
391 {
392 ok(true, "Test testNotificationURL: clicking the notification button " +
393 "opened the url specified by the update");
394 let href = gBrowser.selectedBrowser.contentWindow.location.href;
395 let expectedURL = BG_NOTIFY_TESTS[BG_NOTIFY_TESTS.length - 1].notificationURL;
396 is(href, expectedURL, "The url opened from the notification should be the " +
397 "url provided by the update");
398 gBrowser.removeCurrentTab();
399 window.focus();
400 finish_test();
401 }
403 /* Reloads the update metadata from disk */
404 function reloadUpdateManagerData()
405 {
406 Cc["@mozilla.org/updates/update-manager;1"].getService(Ci.nsIUpdateManager).
407 QueryInterface(Ci.nsIObserver).observe(null, "um-reload-update-data", "");
408 }
411 function writeUpdatesToXMLFile(aText)
412 {
413 const PERMS_FILE = 0644;
415 const MODE_WRONLY = 0x02;
416 const MODE_CREATE = 0x08;
417 const MODE_TRUNCATE = 0x20;
419 let file = Cc["@mozilla.org/file/directory_service;1"].
420 getService(Ci.nsIProperties).
421 get("UpdRootD", Ci.nsIFile);
422 file.append("updates.xml");
423 let fos = Cc["@mozilla.org/network/file-output-stream;1"].
424 createInstance(Ci.nsIFileOutputStream);
425 if (!file.exists()) {
426 file.create(Ci.nsILocalFile.NORMAL_FILE_TYPE, PERMS_FILE);
427 }
428 fos.init(file, MODE_WRONLY | MODE_CREATE | MODE_TRUNCATE, PERMS_FILE, 0);
429 fos.write(aText, aText.length);
430 fos.close();
431 }