123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370 |
- <!DOCTYPE HTML>
- <html>
- <!--
- https://bugzilla.mozilla.org/show_bug.cgi?id=897221
- -->
- <head>
- <title>Test for User Agent Updates</title>
- <script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
- </head>
- <body>
- <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=897221">Mozilla Bug 897221</a>
- <p id="display"></p>
- <div id="content" style="display: none"></div>
- <pre id="test">
- <script class="testbody" type="text/javascript">
- const PREF_APP_UPDATE_TIMERMINIMUMDELAY = "app.update.timerMinimumDelay";
- const PREF_UPDATES = "general.useragent.updates.";
- const PREF_UPDATES_ENABLED = PREF_UPDATES + "enabled";
- const PREF_UPDATES_URL = PREF_UPDATES + "url";
- const PREF_UPDATES_INTERVAL = PREF_UPDATES + "interval";
- const PREF_UPDATES_TIMEOUT = PREF_UPDATES + "timeout";
- const DEFAULT_UA = navigator.userAgent;
- const UA_OVERRIDE = "DummyUserAgent";
- const UA_ALT_OVERRIDE = "AltUserAgent";
- const UA_PARTIAL_FROM = "\\wozilla"; // /\wozilla
- const UA_PARTIAL_SEP = "#";
- const UA_PARTIAL_TO = UA_OVERRIDE;
- const UA_PARTIAL_OVERRIDE = UA_PARTIAL_FROM + UA_PARTIAL_SEP + UA_PARTIAL_TO;
- const UA_PARTIAL_EXPECTED = DEFAULT_UA.replace(new RegExp(UA_PARTIAL_FROM, 'g'), UA_PARTIAL_TO);
- function getUA(host) {
- var url = location.pathname;
- url = host + url.slice(0, url.lastIndexOf('/')) + '/user_agent.sjs';
- var xhr = new XMLHttpRequest();
- xhr.open('GET', url, false); // sync request
- xhr.send();
- is(xhr.status, 200, 'request failed');
- is(typeof xhr.response, 'string', 'invalid response');
- return xhr.response;
- }
- function testUAIFrame(host, expected, sameQ, message, testNavQ, navSameQ, navMessage, callback) {
- let url = location.pathname;
- url = host + url.slice(0, url.lastIndexOf('/')) + '/user_agent.sjs';
- let ifr = document.createElement('IFRAME');
- ifr.src = url;
- document.getElementById('content').appendChild(ifr);
- window.addEventListener("message", function recv(e) {
- ok(sameQ == (e.data.header.indexOf(expected) != -1), message);
- if (testNavQ) {
- ok(navSameQ == (e.data.nav.indexOf(expected) != -1), navMessage);
- }
- window.removeEventListener("message", recv, false);
- callback();
- }, false);
- }
- function testUAIFrameNoNav(host, expected, sameQ, message, callback) {
- testUAIFrame(host, expected, sameQ, message, false, true, '', callback);
- }
- const OVERRIDES = [
- {
- domain: 'example.org',
- override: '%DATE%',
- host: 'http://example.org'
- },
- {
- domain: 'test1.example.org',
- override: '%PRODUCT%',
- expected: SpecialPowers.Services.appinfo.name,
- host: 'http://test1.example.org'
- },
- {
- domain: 'test2.example.org',
- override: '%APP_ID%',
- expected: SpecialPowers.Services.appinfo.ID,
- host: 'http://test2.example.org'
- },
- {
- domain: 'sub1.test1.example.org',
- override: '%APP_VERSION%',
- expected: SpecialPowers.Services.appinfo.version,
- host: 'http://sub1.test1.example.org'
- },
- {
- domain: 'sub2.test1.example.org',
- override: '%BUILD_ID%',
- expected: SpecialPowers.Services.appinfo.appBuildID,
- host: 'http://sub2.test1.example.org'
- },
- {
- domain: 'sub1.test2.example.org',
- override: '%OS%',
- expected: SpecialPowers.Services.appinfo.OS,
- host: 'http://sub1.test2.example.org'
- },
- {
- domain: 'sub2.test2.example.org',
- override: UA_PARTIAL_OVERRIDE,
- expected: UA_PARTIAL_EXPECTED,
- host: 'http://sub2.test2.example.org'
- },
- ];
- function getServerURL() {
- var url = location.pathname;
- return location.origin + url.slice(0, url.lastIndexOf('/')) + '/user_agent_update.sjs?';
- }
- function getUpdateURL() {
- var url = getServerURL();
- var overrides = {};
- overrides[location.hostname] = UA_OVERRIDE;
- OVERRIDES.forEach(function (val) {
- overrides[val.domain] = val.override;
- });
- url = url + encodeURIComponent(JSON.stringify(overrides)).replace(/%25/g, '%');
- return url;
- }
- function testDownload(callback) {
- var startTime = Date.now();
- var url = getUpdateURL();
- isnot(navigator.userAgent, UA_OVERRIDE, 'UA already overridden');
- info('Waiting for UA update: ' + url);
- chromeScript.sendAsyncMessage("notify-on-update");
- SpecialPowers.pushPrefEnv({
- set: [
- [PREF_UPDATES_ENABLED, true],
- [PREF_UPDATES_URL, url],
- [PREF_UPDATES_TIMEOUT, 10000],
- [PREF_UPDATES_INTERVAL, 1] // 1 second interval
- ]
- });
- function waitForUpdate() {
- info("Update Happened");
- testUAIFrameNoNav(location.origin, UA_OVERRIDE, true, 'Header UA not overridden', function() {
- var updateTime = parseInt(getUA('http://example.org'));
- todo(startTime <= updateTime, 'Update was before start time');
- todo(updateTime <= Date.now(), 'Update was after present time');
- let overs = OVERRIDES;
- (function nextOverride() {
- val = overs.shift();
- if (val.expected) {
- testUAIFrameNoNav(val.host, val.expected, true, 'Incorrect URL parameter: ' + val.override, function() {
- overs.length ? nextOverride() : callback();
- });
- } else {
- nextOverride();
- }
- })();
- });
- }
- chromeScript.addMessageListener("useragent-update-complete", waitForUpdate);
- }
- function testBadUpdate(callback) {
- var url = getServerURL() + 'invalid-json';
- var prevOverride = navigator.userAgent;
- SpecialPowers.pushPrefEnv({
- set: [
- [PREF_UPDATES_URL, url],
- [PREF_UPDATES_INTERVAL, 1] // 1 second interval
- ]
- }, function () { setTimeout(function () {
- var ifr = document.createElement('IFRAME');
- ifr.src = "about:blank";
- ifr.addEventListener('load', function() {
- // We want to make sure a bad update doesn't cancel out previous
- // overrides. We do this by waiting for 5 seconds (assuming the update
- // occurs within 5 seconds), and check that the previous override hasn't
- // changed.
- is(navigator.userAgent, prevOverride,
- 'Invalid update deleted previous override');
- callback();
- }, false);
- document.getElementById('content').appendChild(ifr);
- }, 5000); });
- }
- SimpleTest.waitForExplicitFinish();
- SimpleTest.requestFlakyTimeout("Test sets timeouts to wait for updates to happen.");
- SpecialPowers.pushPrefEnv({
- set: [
- [PREF_APP_UPDATE_TIMERMINIMUMDELAY, 0]
- ]
- }, function () {
- chromeScript.sendSyncMessage("UAO-uninit");
- // Sets the OVERRIDES var in the chrome script.
- // We do this to avoid code duplication.
- chromeScript.sendSyncMessage("set-overrides", OVERRIDES);
- // testProfileLoad, testDownload, and testProfileSave must run in this order
- // because testDownload depends on testProfileLoad to call UAO.init()
- // and testProfileSave depends on testDownload to save overrides to the profile
- chromeScript.sendAsyncMessage("testProfileLoad", location.hostname);
- });
- const chromeScript = SpecialPowers.loadChromeScript(_ => {
- // Enter update timer manager test mode
- Components.classes["@mozilla.org/updates/timer-manager;1"].getService(
- Components.interfaces.nsIObserver).observe(null, "utm-test-init", "");
- Components.utils.import("resource://gre/modules/UserAgentOverrides.jsm");
- var _notifyOnUpdate = false;
- var UAO = UserAgentOverrides;
- UAO.uninit();
- Components.utils.import("resource://gre/modules/FileUtils.jsm");
- var FU = FileUtils;
- const { TextDecoder, TextEncoder, OS } = Components.utils.import("resource://gre/modules/osfile.jsm");
- var OSF = OS.File;
- const KEY_PREFDIR = "PrefD";
- const KEY_APPDIR = "XCurProcD";
- const FILE_UPDATES = "ua-update.json";
- const UA_OVERRIDE = "DummyUserAgent";
- const UA_ALT_OVERRIDE = "AltUserAgent";
- const PREF_UPDATES = "general.useragent.updates.";
- const PREF_UPDATES_ENABLED = PREF_UPDATES + "enabled";
- const PREF_UPDATES_LASTUPDATED = PREF_UPDATES + "lastupdated";
- Components.utils.import("resource://gre/modules/Services.jsm");
- Services.prefs.addObserver(PREF_UPDATES_LASTUPDATED, () => {
- if (_notifyOnUpdate) {
- _notifyOnUpdate = false; // Only notify once, for the first update.
- sendAsyncMessage("useragent-update-complete");
- }
- } , false);
- var OVERRIDES = null;
- function is(value, expected, message) {
- sendAsyncMessage("is-message", {value, expected, message});
- }
- function info(message) {
- sendAsyncMessage("info-message", message);
- }
- function testProfileSave(hostname) {
- info('Waiting for saving to profile');
- var file = FU.getFile(KEY_PREFDIR, [FILE_UPDATES]).path;
- (function waitForSave() {
- OSF.exists(file).then(
- (exists) => {
- if (!exists) {
- setTimeout(waitForSave, 100);
- return;
- }
- return OSF.read(file).then(
- (bytes) => {
- info('Saved new overrides');
- var decoder = new TextDecoder();
- var overrides = JSON.parse(decoder.decode(bytes));
- is(overrides[hostname], UA_OVERRIDE, 'Incorrect saved override');
- OVERRIDES.forEach(function (val) {
- val.expected && is(overrides[val.domain], val.expected,
- 'Incorrect saved override: ' + val.override);
- });
- sendAsyncMessage("testProfileSaveDone");
- }
- );
- }
- ).then(null,
- (reason) => {
- throw reason
- }
- );
- })();
- }
- function testProfileLoad(hostname) {
- var file = FU.getFile(KEY_APPDIR, [FILE_UPDATES]).path;
- var encoder = new TextEncoder();
- var overrides = {};
- overrides[hostname] = UA_ALT_OVERRIDE;
- var bytes = encoder.encode(JSON.stringify(overrides));
- var badfile = FU.getFile(KEY_PREFDIR, [FILE_UPDATES]).path;
- var badbytes = encoder.encode("null");
- OSF.writeAtomic(file, bytes, {tmpPath: file + ".tmp"}).then(
- () => OSF.writeAtomic(badfile, badbytes, {tmpPath: badfile + ".tmp"})
- ).then(
- () => {
- sendAsyncMessage("testProfileLoadDone");
- },
- (reason) => {
- throw reason
- }
- );
- }
- addMessageListener("testProfileSave", testProfileSave);
- addMessageListener("testProfileLoad", testProfileLoad);
- addMessageListener("set-overrides", function(overrides) { OVERRIDES = overrides});
- addMessageListener("UAO-init", function() { UAO.init(); });
- addMessageListener("UAO-uninit", function() { UAO.uninit(); });
- addMessageListener("notify-on-update", () => { _notifyOnUpdate = true });
- });
- chromeScript.addMessageListener("testProfileSaveDone", SimpleTest.finish);
- chromeScript.addMessageListener("testProfileLoadDone", function() {
- SpecialPowers.pushPrefEnv({
- set: [[PREF_UPDATES_ENABLED, true]]
- }, function () {
- // initialize UserAgentOverrides.jsm and
- // UserAgentUpdates.jsm and load saved file
- chromeScript.sendSyncMessage("UAO-init");
- (function waitForLoad() {
- var ifr = document.createElement('IFRAME');
- ifr.src = "about:blank";
- ifr.addEventListener('load', function() {
- var nav = ifr.contentWindow.navigator;
- if (nav.userAgent !== UA_ALT_OVERRIDE) {
- setTimeout(waitForLoad, 100);
- return;
- }
- testUAIFrameNoNav(location.origin, UA_ALT_OVERRIDE, true, 'Did not apply saved override', function () {
- testDownload(function() {
- testBadUpdate(function() {
- chromeScript.sendAsyncMessage("testProfileSave", location.hostname);
- })
- })
- });
- }, true);
- document.getElementById('content').appendChild(ifr);
- })();
- });
- });
- chromeScript.addMessageListener("is-message", function(params) {
- let {value, expected, message} = params;
- is(value, expected, message);
- });
- chromeScript.addMessageListener("info-message", function(message) {
- info(message);
- });
- </script>
- </pre>
- </body>
- </html>
|