1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
/* General Partial MAR File Patch Apply Test */
const { setTimeout } = ChromeUtils.importESModule(
"resource://gre/modules/Timer.sys.mjs"
);
const { BackgroundTasksTestUtils } = ChromeUtils.importESModule(
"resource://testing-common/BackgroundTasksTestUtils.sys.mjs"
);
BackgroundTasksTestUtils.init(this);
const do_backgroundtask = BackgroundTasksTestUtils.do_backgroundtask.bind(
BackgroundTasksTestUtils
);
async function run_test() {
// Without omnijars, the background task apparatus will fail to find task
// definitions.
{
let omniJa = Services.dirsvc.get("XCurProcD", Ci.nsIFile);
omniJa.append("omni.ja");
if (!omniJa.exists()) {
Assert.ok(
false,
"This test requires a packaged build, " +
"run 'mach package' and then use 'mach xpcshell-test --xre-path=...'"
);
return;
}
}
if (!setupTestCommon()) {
return;
}
// `channel-prefs.js` (or `ChannelPrefs.framework/ChannelPrefs on macOS`) is
// required for Firefox to launch, including in background task mode. The
// testing partial MAR updates `channel-prefs.js` to have contents
// `FromPartial`, which is not a valid prefs file and causes Firefox to crash.
// However, `channel-prefs.js` is listed as `add-if-not
// "defaults/pref/channel-prefs.js" "defaults/pref/channel-prefs.js"`, so it
// won't be updated if it already exists. The manipulations below arrange a)
// for the file to exist and b) for the comparison afterward to succeed.
gTestFiles = gTestFilesPartialSuccess;
let channelPrefs = getTestFileByName(FILE_CHANNEL_PREFS);
let f = gGREDirOrig.clone();
if (AppConstants.platform == "macosx") {
f = f.parent;
f.append("Frameworks");
f.append("ChannelPrefs.framework");
f.append("ChannelPrefs");
} else {
f.append("defaults");
f.append("pref");
f.append("channel-prefs.js");
}
// `originalFile` is a relative path, so we can't just point to the one in the
// original GRE directory.
channelPrefs.originalFile = null;
channelPrefs.originalContents = readFile(f);
channelPrefs.compareContents = channelPrefs.originalContents;
gTestDirs = gTestDirsPartialSuccess;
// The third parameter will test that a relative path that contains a
// directory traversal to the post update binary doesn't execute.
await setupUpdaterTest(FILE_PARTIAL_MAR, false, "test/../", true, {
// We need packaged JavaScript to run background tasks.
requiresOmnijar: true,
});
// `0/00/00text2` is just a random file in the testing partial MAR that does
// not exist before the update and is always written by the update.
let exitCode;
exitCode = await do_backgroundtask("file_exists", {
extraArgs: [getApplyDirFile(DIR_RESOURCES + "0/00/00text2").path],
});
// Before updating, file doesn't exist.
Assert.equal(11, exitCode);
// This task will wait 10 seconds before exiting, which should overlap with
// the update below. We wait for some output from the wait background task,
// so that there is meaningful overlap.
let taskStarted = Promise.withResolvers();
let p = do_backgroundtask("wait", {
onStdoutLine: (line, proc) => {
// This sentinel seems pretty safe: it's printed by the task itself and so
// there should be a straight line between future test failures and
// logging changes.
if (line.includes("runBackgroundTask: wait")) {
taskStarted.resolve(proc);
}
},
});
let proc = await taskStarted.promise;
runUpdate(STATE_SUCCEEDED, false, 0, true);
checkAppBundleModTime();
await testPostUpdateProcessing();
checkPostUpdateRunningFile(false);
checkFilesAfterUpdateSuccess(getApplyDirFile);
checkUpdateLogContents(LOG_PARTIAL_SUCCESS);
await waitForUpdateXMLFiles();
await checkUpdateManager(STATE_NONE, false, STATE_SUCCEEDED, 0, 1);
// Once we've seen what we want, there's no need to let the task wait complete.
await proc.kill();
Assert.ok("Waiting for background task to die after kill()");
exitCode = await p;
// Windows does not support killing processes gracefully, so they will
// always exit with -9 there.
let retVal = AppConstants.platform == "win" ? -9 : -15;
Assert.equal(retVal, exitCode);
exitCode = await do_backgroundtask("file_exists", {
extraArgs: [getApplyDirFile(DIR_RESOURCES + "0/00/00text2").path],
});
// After updating, file exists.
Assert.equal(0, exitCode);
// This finishes the test, so must be last.
checkCallbackLog();
}
|