Created
October 22, 2020 17:22
-
-
Save ncalexan/942b3c9e2ea4a8fbcd80431d8ba6e4c2 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */ | |
/* vim: set sts=2 sw=2 et tw=80: */ | |
/* 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/. */ | |
"use strict"; | |
// Copied form | |
// taskcluster/docker/periodic-updates/scripts/getHSTSPreloadList.js, | |
// which simplified a version from | |
// browser/components/migration/MigrationUtils.jsm. | |
function spinResolve(promise) { | |
if (!(promise instanceof Promise)) { | |
return promise; | |
} | |
let done = false; | |
let result = null; | |
let error = null; | |
promise | |
.catch(e => { | |
dump(e); | |
console.log(`e: ${e}`, e, e.stack); | |
error = e; | |
}) | |
.then(r => { | |
result = r; | |
done = true; | |
}); | |
let tm = Cc["@mozilla.org/thread-manager;1"].getService(Ci.nsIThreadManager); | |
tm.spinEventLoopUntil(() => done); | |
if (error) { | |
throw error; | |
} else { | |
return result; | |
} | |
} | |
const { Services } = ChromeUtils.import( | |
"resource://gre/modules/Services.jsm" | |
); | |
const { Subprocess } = ChromeUtils.import( | |
"resource://gre/modules/Subprocess.jsm" | |
); | |
async function schedule() { | |
let uid = 501; // XXX | |
let file = Services.dirsvc.get("Home", Ci.nsIFile); | |
file.append("Library"); | |
file.append("LaunchAgents"); | |
// file.append("MOZ_MACBUNDLE_ID"); | |
let MOZ_MACBUNDLE_ID = "org.mozilla.firefoxnightly"; // TODO. | |
let hash = "1"; // TODO: differentiate installations. Hash of `UpdRootD`, perhaps? | |
let short_label = "update"; | |
let long_label = `${MOZ_MACBUNDLE_ID}.${hash}.backgroundtask.${short_label}`; | |
file.append(`${long_label}.plist`); | |
const doc = new DOMParser().parseFromString("<plist></plist>", "text/xml"); | |
const root = doc.documentElement; | |
root.setAttribute("version", "1.0"); | |
// <?xml version="1.0" encoding="UTF-8"?> | |
// <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" | |
// "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | |
// <plist version="1.0"> | |
// <dict> | |
// <key>Label</key> | |
// <string>MyAgent</string> | |
// <key>ProgramArguments</key> | |
// <array> | |
// <string>/path/to/script/or/program</string> | |
// </array> | |
// </dict> | |
// </plist> | |
let dict = doc.createElement("dict"); | |
root.appendChild(dict); | |
let key = doc.createElement("key"); | |
key.textContent = "Label"; | |
dict.appendChild(key); | |
let string = doc.createElement("string"); | |
let MOZ_APP_DISPLAYNAME = "MOZ_APP_DISPLAYNAME"; // TODO | |
string.textContent = long_label; // "${MOZ_APP_DISPLAYNAME} ${label} background task"; | |
dict.appendChild(string); | |
key = doc.createElement("key"); | |
key.textContent = "ProgramArguments"; | |
dict.appendChild(key); | |
let array = doc.createElement("array"); | |
dict.appendChild(array); | |
for (let x of [Services.dirsvc.get("XREExeF", Ci.nsIFile).path, | |
"--xpcshell", | |
"-e", | |
"dump('test\\n')"]) { | |
let string = doc.createElement("string"); | |
string.textContent = x; | |
array.appendChild(string); | |
} | |
const de = Ci.nsIDocumentEncoder; | |
let flags = de.OutputLFLineBreak | de.OutputFormatted; // TODO: figure out why this isn't wrapping. | |
let enc = Cu.createDocumentEncoder("text/xml"); | |
enc.setCharset("UTF-8"); | |
enc.init(doc, "text/xml", flags); | |
// Ci.nsIDocumentEncoder.OutputLFLineBreak | Ci.nsIDocumentEncoder.OutputFormatted); | |
let plist = `<?xml version="1.0" encoding="UTF-8"?>\n`; | |
plist += `<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n`; | |
plist += enc.encodeToString(); | |
dump(plist); | |
await IOUtils.writeAtomic(file.path, new TextEncoder().encode(plist)); | |
console.log(`path: ${file.path}`); | |
let bootout = await Subprocess.call({ | |
command: "/bin/launchctl", | |
arguments: ["bootout", `gui/${uid}`, file.path], | |
environment: {}, | |
stderr: "stdout", | |
}); | |
let stdout = await bootout.stdout.readString(); | |
console.log(stdout); | |
// let { exitCode } = | |
await bootout.wait(); | |
let bootstrap = await Subprocess.call({ | |
command: "/bin/launchctl", | |
arguments: ["bootstrap", `gui/${uid}`, file.path], | |
environment: {}, | |
stderr: "stdout", | |
}); | |
stdout = await bootstrap.stdout.readString(); | |
console.log(stdout); | |
let { exitCode } = await bootstrap.wait(); | |
if (exitCode != 0) { | |
throw new Components.Exception( | |
`Failed to run launchctl: ${exitCode}`, | |
Cr.NS_ERROR_UNEXPECTED | |
); | |
} | |
} | |
spinResolve(schedule().then(console.log)); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment