Skip to content

Instantly share code, notes, and snippets.

@ncalexan
Created August 31, 2020 17:19
Show Gist options
  • Save ncalexan/ee8c24a97e6148b9cca673848233209b to your computer and use it in GitHub Desktop.
Save ncalexan/ee8c24a97e6148b9cca673848233209b to your computer and use it in GitHub Desktop.
"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;
}
}
/**
* Returns a Promise which resolves when the given observer topic has been
* observed.
*
* @param {string} topic
* The topic to observe.
* @param {function(nsISupports, string)} [test]
* An optional test function which, when called with the
* observer's subject and data, should return true if this is the
* expected notification, false otherwise.
* @returns {Promise<object>}
*/
function promiseObserved(topic, test = () => true) {
return new Promise(resolve => {
let observer = (subject, topic, data) => {
if (test(subject, data)) {
Services.obs.removeObserver(observer, topic);
resolve({ subject, data });
}
};
Services.obs.addObserver(observer, topic);
});
};
// Determine if we're running on parent or child
var runningInParent = true;
try {
// Don't use Services.appinfo here as it disables replacing appinfo with stubs
// for test usage.
runningInParent =
// eslint-disable-next-line mozilla/use-services
Cc["@mozilla.org/xre/runtime;1"].getService(Ci.nsIXULRuntime).processType ==
Ci.nsIXULRuntime.PROCESS_TYPE_DEFAULT;
} catch (e) {}
/**
* Registers a directory with the profile service,
* and return the directory as an nsIFile.
*
* @param notifyProfileAfterChange Whether to notify for "profile-after-change".
* @return nsIFile of the profile directory.
*/
function do_get_profile(notifyProfileAfterChange = false) {
if (!runningInParent) {
console.info("Ignoring profile creation from child process.");
return null;
}
let env = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
// XXX generate this properly.
let profd = "/Users/nalexander/Mozilla/gecko/test-profile";
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
file.initWithPath(profd);
let provider = {
getFile(prop, persistent) {
persistent.value = true;
if (
prop == "ProfD" ||
prop == "ProfLD" ||
prop == "ProfDS" ||
prop == "ProfLDS" ||
prop == "TmpD"
) {
return file.clone();
}
return null;
},
QueryInterface: ChromeUtils.generateQI(["nsIDirectoryServiceProvider"]),
};
Services.dirsvc
.QueryInterface(Ci.nsIDirectoryService)
.registerProvider(provider);
try {
Services.dirsvc.undefine("TmpD");
} catch (e) {
// This throws if the key is not already registered, but that
// doesn't matter.
if (e.result != Cr.NS_ERROR_FAILURE) {
throw e;
}
}
// We need to update the crash events directory when the profile changes.
if (runningInParent && "@mozilla.org/toolkit/crash-reporter;1" in Cc) {
let crashReporter = Cc["@mozilla.org/toolkit/crash-reporter;1"].getService(
Ci.nsICrashReporter
);
crashReporter.UpdateCrashEventsDir();
}
// if (!_profileInitialized) {
Services.obs.notifyObservers(
null,
"profile-do-change",
"xpcshell-do-get-profile"
);
// _profileInitialized = true;
// if (notifyProfileAfterChange) {
Services.obs.notifyObservers(
null,
"profile-after-change",
"xpcshell-do-get-profile"
);
// }
// }
// The methods of 'provider' will retain this scope so null out everything
// to avoid spurious leak reports.
env = null;
profd = null;
provider = null;
return file.clone();
}
(() => {
let mgr = Cc["@mozilla.org/memory-reporter-manager;1"].
getService(Ci.nsIMemoryReporterManager);
let amounts = [
"vsize",
// "vsizeMaxContiguous",
"resident",
// "residentFast",
"residentPeak",
"residentUnique",
"heapAllocated",
"heapOverheadFraction",
"JSMainRuntimeGCHeap",
"JSMainRuntimeTemporaryPeak",
"JSMainRuntimeRealmsSystem",
"JSMainRuntimeRealmsUser",
// "imagesContentUsedUncompressed",
// "storageSQLite",
// "lowMemoryEventsVirtual",
// "lowMemoryEventsCommitSpace",
// "lowMemoryEventsPhysical",
// "ghostWindows",
// "pageFaultsHard",
];
for (let i = 0; i < amounts.length; i++) {
// try {
// If mgr[amounts[i]] throws an exception, just move on -- some amounts
// aren't available on all platforms. But if the attribute simply
// isn't present, that indicates the distinguished amounts have changed
// and this file hasn't been updated appropriately.
let dummy = mgr[amounts[i]];
console.log(`amounts: ${amounts[i]}: ${dummy}`);
// } catch (ex) {
// }
}
})();
const { XPCOMUtils } = ChromeUtils.import(
"resource://gre/modules/XPCOMUtils.jsm"
);
const { UpdateUtils } = ChromeUtils.import(
"resource://gre/modules/UpdateUtils.jsm"
);
ChromeUtils.import("resource://gre/modules/Services.jsm", this);
const PREF_APP_UPDATE_LOG = "app.update.log";
const PREF_APP_UPDATE_FILE_LOGGING = "app.update.log.file";
// XPCOMUtils.defineLazyGetter(this, "gLogEnabled", function aus_gLogEnabled() {
Services.prefs.setCharPref("browser.policies.loglevel", "debug");
Services.prefs.setBoolPref(PREF_APP_UPDATE_LOG, true);
// });
// Launching the socket process fails.
// File: ipc/glue/GeckoChildProcessHost.cpp
// 1725: MOZ_CRASH("Failed to get app path");
Services.prefs.setBoolPref("network.process.enabled", false);
// Addons, and in particular langpacks, are per-profile. Background
// tasks are always going to use a temporary profile so updating
// langpacks from a background task will require significant
// additional work.
Services.prefs.setBoolPref("app.update.langpack.enabled", false);
// Allow to import testing-common modules.
let protocolHandler = Services.io
.getProtocolHandler("resource")
.QueryInterface(Ci.nsIResProtocolHandler);
let modulesFile = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
let _TESTING_MODULES_DIR = "/Users/nalexander/Mozilla/objdirs/objdir-browser-artifact/_tests/modules/"
modulesFile.initWithPath(_TESTING_MODULES_DIR);
if (!modulesFile.exists()) {
throw new Error(
"Specified modules directory does not exist: " + _TESTING_MODULES_DIR
);
}
if (!modulesFile.isDirectory()) {
throw new Error(
"Specified modules directory is not a directory: " + _TESTING_MODULES_DIR
);
}
let modulesURI = Services.io.newFileURI(modulesFile);
protocolHandler.setSubstitution("testing-common", modulesURI);
const { updateAppInfo } = ChromeUtils.import("resource://testing-common/AppInfo.jsm");
// "https://aus5.mozilla.org/update/6/Firefox/81.0a1/20200818092452/Darwin_x86_64-gcc3/en-CA/nightly/Darwin%2018.7.0/ISET:SSE4_2,MEM:32768/default/default/update.xml"
/**
* Creates an nsIXULAppInfo
*
* @param aID
* The ID of the test application
* @param aName
* A name for the test application
* @param aVersion
* The version of the application
* @param aPlatformVersion
* The gecko version of the application
*/
function createAppInfo(aID, aName, aVersion, aPlatformVersion) {
updateAppInfo({
vendor: "Mozilla",
name: aName,
ID: aID,
version: aVersion,
appBuildID: "2007010101",
platformVersion: aPlatformVersion,
platformBuildID: "2007010101",
inSafeMode: false,
logConsoleErrors: true,
OS: "XPCShell",
XPCOMABI: "noarch-spidermonkey",
// XXX.
updateURL: "https://aus5.mozilla.org/update/6/Firefox/81.0a1/20200818092452/Darwin_x86_64-gcc3/en-CA/nightly/Darwin%2018.7.0/ISET:SSE4_2,MEM:32768/default/default/update.xml",
});
}
createAppInfo("[email protected]", "XPCShell", "1.0", "2.0");
// This initializes the policy engine for xpcshell tests
let policies = Cc["@mozilla.org/enterprisepolicies;1"].getService(
Ci.nsIObserver
);
policies.observe(null, "policies-startup", null);
// console.log(`Services.policies: ${Services.policies}`);
// if (Services.policies) {
// // // Initialize the Enterprise Policies service in the parent process
// // // In the content process it's loaded on demand when needed
// // if (XRE_IsParentProcess()) {
// // nsCOMPtr<nsIObserver> policies(
// // do_GetService("@mozilla.org/enterprisepolicies;1"));
// // if (policies) {
// // policies->Observe(nullptr, "policies-startup", nullptr);
// // }
// // }
// Services.policies.QueryInterface(Ci.nsIObserver).observe(null, "policies-startup", null);
// }
// let p = promiseObserved("EnterprisePolicies:AllPoliciesApplied");
let profile = do_get_profile();
console.log(`profile: ${profile.path}`);
try {
// Services.obs.notifyObservers(null, "policies-startup");
// Services.obs.notifyObservers(null, "EnterprisePolicies:Restart"); // policies-startup");
// spinResolve(p);
console.log(`Running task: after spinResolve`);
// console.log(`XREAppDist: ${Services.dirsvc.get("XREAppDist", Ci.nsIFile).path}`);
let activePolicies = Services.policies.getActivePolicies();
// if (policies) { // && "AppUpdateURL" in policies) {
console.log(`policies: ${JSON.stringify(activePolicies)}`);
// }
// }
// exit(0);
// const { AppUpdater } = ChromeUtils.import(
// "resource:///modules/AppUpdater.jsm"
// );
// XPCOMUtils.defineLazyModuleGetters(this, {
// AppUpdater: "resource:///modules/AppUpdater.jsm",
// // Services: "resource://gre/modules/Services.jsm",
// });
// XPCOMUtils.defineLazyGetter(this, "appUpdater", () => new AppUpdater());
(() => {
let env = Cc["@mozilla.org/process/environment;1"].getService(
Ci.nsIEnvironment
);
let profd = "/Users/nalexander/Mozilla/gecko/buprof"; // env.get("XPCSHELL_TEST_PROFILE_DIR");
let file = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
file.initWithPath(profd);
let updRootD = Cc["@mozilla.org/file/local;1"].createInstance(Ci.nsIFile);
updRootD.initWithPath("/Users/nalexander/Library/Caches/Mozilla/updates/Users/nalexander/Mozilla/objdirs/objdir-browser-artifact/dist/NightlyDebug");
let dirsvc = Cc["@mozilla.org/file/directory_service;1"].getService(
Ci.nsIDirectoryServiceProvider
);
let provider = {
getFile(prop, persistent) {
persistent.value = true;
if (
prop == "ProfD" ||
prop == "ProfLD" ||
prop == "ProfDS" ||
prop == "ProfLDS" ||
prop == "TmpD"
) {
return file.clone();
}
if (prop == "UpdRootD") {
return updRootD.clone();
}
return null;
},
QueryInterface: ChromeUtils.generateQI(["nsIDirectoryServiceProvider"]),
};
dirsvc
.QueryInterface(Ci.nsIDirectoryService)
.registerProvider(provider);
// try {
// dirsvc.undefine("TmpD");
// } catch (e) {
// // This throws if the key is not already registered, but that
// // doesn't matter.
// if (e.result != Cr.NS_ERROR_FAILURE) {
// throw e;
// }
// }
// // We need to update the crash events directory when the profile changes.
// if (runningInParent && "@mozilla.org/toolkit/crash-reporter;1" in Cc) {
// let crashReporter = Cc["@mozilla.org/toolkit/crash-reporter;1"].getService(
// Ci.nsICrashReporter
// );
// crashReporter.UpdateCrashEventsDir();
// }
// if (!_profileInitialized) {
// _Services.obs.notifyObservers(
// null,
// "profile-do-change",
// "xpcshell-do-get-profile"
// );
// _profileInitialized = true;
// if (notifyProfileAfterChange) {
// _Services.obs.notifyObservers(
// null,
// "profile-after-change",
// "xpcshell-do-get-profile"
// );
// }
// }
// The methods of 'provider' will retain this scope so null out everything
// to avoid spurious leak reports.
env = null;
profd = null;
provider = null;
return file.clone();
})();
let um = Cc["@mozilla.org/updates/update-manager;1"]
.getService(Ci.nsIUpdateManager);
let checker = Cc["@mozilla.org/updates/update-checker;1"]
.getService(Ci.nsIUpdateChecker);
let aus = Cc["@mozilla.org/updates/update-service;1"]
.getService(Ci.nsIApplicationUpdateService);
// // Clear prefs that could prevent a user from discovering available updates.
// if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_CANCELATIONS_OSX)) {
// Services.prefs.clearUserPref(PREF_APP_UPDATE_CANCELATIONS_OSX);
// }
// if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_ELEVATE_NEVER)) {
// Services.prefs.clearUserPref(PREF_APP_UPDATE_ELEVATE_NEVER);
// }
// let updateCheckListener = {
// _setStatus: (...args) => {
// console.log(`_setStatus: ${JSON.stringify(args)}`);
// },
// /**
// * See nsIUpdateService.idl
// */
// onCheckComplete: (aRequest, aUpdates, ...args) => {
// console.log(`onCheckComplete: ${JSON.stringify(args)}`);
// this.update = aus.selectUpdate(aUpdates);
// if (!this.update) {
// this._setStatus("AppUpdater.STATUS.NO_UPDATES_FOUND");
// return;
// }
// if (this.update.unsupported) {
// this._setStatus("AppUpdater.STATUS.UNSUPPORTED_SYSTEM");
// return;
// }
// if (!aus.canApplyUpdates) {
// this._setStatus("AppUpdater.STATUS.MANUAL_UPDATE");
// return;
// }
// if (!this.promiseAutoUpdateSetting) {
// this.promiseAutoUpdateSetting = UpdateUtils.getAppUpdateAutoEnabled();
// }
// this.promiseAutoUpdateSetting.then(updateAuto => {
// if (updateAuto) {
// // automatically download and install
// this.startDownload();
// } else {
// // ask
// this._setStatus("AppUpdater.STATUS.DOWNLOAD_AND_INSTALL");
// }
// });
// },
// /**
// * See nsIUpdateService.idl
// */
// onError: (aRequest, aUpdate, ...args) => {
// console.log(`onError: ${JSON.stringify(args)}`);
// // Errors in the update check are treated as no updates found. If the
// // update check fails repeatedly without a success the user will be
// // notified with the normal app update user interface so this is safe.
// this._setStatus("AppUpdater.STATUS.NO_UPDATES_FOUND");
// },
// /**
// * See nsISupports.idl
// */
// QueryInterface: ChromeUtils.generateQI(["nsIUpdateCheckListener"]),
// };
// try {
// checker.checkForUpdates(updateCheckListener, true);
// } catch (e) {
// dump(e);
// dump(e.stack);
// console.log(`e: ${e}`, e, e.stack);
// }
// spinResolve(new Promise(resolve => {}));
const { AppUpdater } = ChromeUtils.import(
"resource:///modules/AppUpdater.jsm"
);
let p = new Promise(resolve => {
try {
let appUpdater = new AppUpdater();
let _appUpdaterListener = (...args) => {
console.log(`_appUpdaterListener: ${JSON.stringify(args)}`);
// appUpdater.removeListener(_appUpdaterListener);
// resolve();
};
appUpdater.addListener(_appUpdaterListener);
appUpdater.check();
} catch (e) {
console.log(`e: ${e}`, e, e.stack);
throw e;
}
});
try {
spinResolve(p);
} catch (e) {
dump(e);
dump(e.stack);
console.log(`e: ${e}`, e, e.stack);
}
} finally {
if (true) { // _profileInitialized) {
// Since we have a profile, we will notify profile shutdown topics at
// the end of the current test, to ensure correct cleanup on shutdown.
_Services.obs.notifyObservers(null, "profile-change-net-teardown");
_Services.obs.notifyObservers(null, "profile-change-teardown");
_Services.obs.notifyObservers(null, "profile-before-change");
_Services.obs.notifyObservers(null, "profile-before-change-qm");
// _profileInitialized = false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment