зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1553546, moving telemetry environment isWoW data and installYear data off-main-thread and implementing them on an idle task instead of on the main thread during startup r=mconley,chutten
Differential Revision: https://phabricator.services.mozilla.com/D43549 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
970d3a1d9b
Коммит
a6deb8b6f9
|
@ -1101,6 +1101,8 @@ EnvironmentCache.prototype = {
|
|||
async delayedInit() {
|
||||
if (AppConstants.platform == "win") {
|
||||
this._hddData = await Services.sysinfo.diskInfo;
|
||||
this._processData = await Services.sysinfo.processInfo;
|
||||
let osData = await Services.sysinfo.osInfo;
|
||||
let oldEnv = null;
|
||||
if (!this._initTask) {
|
||||
// We've finished creating the initial env, so notify for the update
|
||||
|
@ -1111,9 +1113,19 @@ EnvironmentCache.prototype = {
|
|||
// instead of all the consumers.
|
||||
oldEnv = this.currentEnvironment;
|
||||
}
|
||||
|
||||
this._osData = this._getOSData();
|
||||
|
||||
// Augment the return values from the promises with cached values
|
||||
this._osData = Object.assign(osData, this._osData);
|
||||
|
||||
this._currentEnvironment.system.os = this._getOSData();
|
||||
this._currentEnvironment.system.hdd = this._getHDDData();
|
||||
this._currentEnvironment.system.isWow64 = this._getProcessData().isWow64;
|
||||
this._currentEnvironment.system.isWowARM64 = this._getProcessData().isWowARM64;
|
||||
|
||||
if (!this._initTask) {
|
||||
this._onEnvironmentChange("hdd-info", oldEnv);
|
||||
this._onEnvironmentChange("system-info", oldEnv);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -1785,12 +1797,17 @@ EnvironmentCache.prototype = {
|
|||
return partnerData;
|
||||
},
|
||||
|
||||
_cpuData: null,
|
||||
/**
|
||||
* Get the CPU information.
|
||||
* @return Object containing the CPU information data.
|
||||
*/
|
||||
_getCpuData() {
|
||||
let cpuData = {
|
||||
_getCPUData() {
|
||||
if (this._cpuData) {
|
||||
return this._cpuData;
|
||||
}
|
||||
|
||||
this._cpuData = {
|
||||
count: getSysinfoProperty("cpucount", null),
|
||||
cores: getSysinfoProperty("cpucores", null),
|
||||
vendor: getSysinfoProperty("cpuvendor", null),
|
||||
|
@ -1828,9 +1845,21 @@ EnvironmentCache.prototype = {
|
|||
}
|
||||
}
|
||||
|
||||
cpuData.extensions = availableExts;
|
||||
this._cpuData.extensions = availableExts;
|
||||
|
||||
return cpuData;
|
||||
return this._cpuData;
|
||||
},
|
||||
|
||||
_processData: null,
|
||||
/**
|
||||
* Get the process information.
|
||||
* @return Object containing the process information data.
|
||||
*/
|
||||
_getProcessData() {
|
||||
if (this._processData) {
|
||||
return this._processData;
|
||||
}
|
||||
return {};
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1851,19 +1880,23 @@ EnvironmentCache.prototype = {
|
|||
};
|
||||
},
|
||||
|
||||
_osData: null,
|
||||
/**
|
||||
* Get the OS information.
|
||||
* @return Object containing the OS data.
|
||||
*/
|
||||
_getOSData() {
|
||||
let data = {
|
||||
if (this._osData) {
|
||||
return this._osData;
|
||||
}
|
||||
this._osData = {
|
||||
name: forceToStringOrNull(getSysinfoProperty("name", null)),
|
||||
version: forceToStringOrNull(getSysinfoProperty("version", null)),
|
||||
locale: forceToStringOrNull(getSystemLocale()),
|
||||
};
|
||||
|
||||
if (AppConstants.platform == "android") {
|
||||
data.kernelVersion = forceToStringOrNull(
|
||||
this._osData.kernelVersion = forceToStringOrNull(
|
||||
getSysinfoProperty("kernel_version", null)
|
||||
);
|
||||
} else if (AppConstants.platform === "win") {
|
||||
|
@ -1872,13 +1905,13 @@ EnvironmentCache.prototype = {
|
|||
"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
|
||||
|
||||
let versionInfo = getWindowsVersionInfo();
|
||||
data.servicePackMajor = versionInfo.servicePackMajor;
|
||||
data.servicePackMinor = versionInfo.servicePackMinor;
|
||||
data.windowsBuildNumber = versionInfo.buildNumber;
|
||||
this._osData.servicePackMajor = versionInfo.servicePackMajor;
|
||||
this._osData.servicePackMinor = versionInfo.servicePackMinor;
|
||||
this._osData.windowsBuildNumber = versionInfo.buildNumber;
|
||||
// We only need the UBR if we're at or above Windows 10.
|
||||
if (
|
||||
typeof data.version === "string" &&
|
||||
Services.vc.compare(data.version, "10") >= 0
|
||||
typeof this._osData.version === "string" &&
|
||||
Services.vc.compare(this._osData.version, "10") >= 0
|
||||
) {
|
||||
// Query the UBR key and only add it to the environment if it's available.
|
||||
// |readRegKey| doesn't throw, but rather returns 'undefined' on error.
|
||||
|
@ -1888,12 +1921,11 @@ EnvironmentCache.prototype = {
|
|||
"UBR",
|
||||
Ci.nsIWindowsRegKey.WOW64_64
|
||||
);
|
||||
data.windowsUBR = ubr !== undefined ? ubr : null;
|
||||
this._osData.windowsUBR = ubr !== undefined ? ubr : null;
|
||||
}
|
||||
data.installYear = getSysinfoProperty("installYear", null);
|
||||
}
|
||||
|
||||
return data;
|
||||
return this._osData;
|
||||
},
|
||||
|
||||
_hddData: null,
|
||||
|
@ -2011,7 +2043,7 @@ EnvironmentCache.prototype = {
|
|||
let data = {
|
||||
memoryMB,
|
||||
virtualMaxMB: virtualMB,
|
||||
cpu: this._getCpuData(),
|
||||
cpu: this._getCPUData(),
|
||||
os: this._getOSData(),
|
||||
hdd: this._getHDDData(),
|
||||
gfx: this._getGFXData(),
|
||||
|
@ -2019,8 +2051,7 @@ EnvironmentCache.prototype = {
|
|||
};
|
||||
|
||||
if (AppConstants.platform === "win") {
|
||||
data.isWow64 = getSysinfoProperty("isWow64", null);
|
||||
data.isWowARM64 = getSysinfoProperty("isWowARM64", null);
|
||||
data = { ...this._getProcessData(), ...data };
|
||||
} else if (AppConstants.platform == "android") {
|
||||
data.device = this._getDeviceData();
|
||||
}
|
||||
|
|
|
@ -186,6 +186,14 @@ var SysInfo = {
|
|||
return this._genuine.QueryInterface(Ci.nsISystemInfo).diskInfo;
|
||||
},
|
||||
|
||||
get osInfo() {
|
||||
return this._genuine.QueryInterface(Ci.nsISystemInfo).osInfo;
|
||||
},
|
||||
|
||||
get processInfo() {
|
||||
return this._genuine.QueryInterface(Ci.nsISystemInfo).processInfo;
|
||||
},
|
||||
|
||||
QueryInterface: ChromeUtils.generateQI(["nsIPropertyBag2", "nsISystemInfo"]),
|
||||
};
|
||||
|
||||
|
@ -595,7 +603,7 @@ function checkGfxAdapter(data) {
|
|||
}
|
||||
}
|
||||
|
||||
function checkSystemSection(data) {
|
||||
function checkSystemSection(data, assertProcessData) {
|
||||
const EXPECTED_FIELDS = [
|
||||
"memoryMB",
|
||||
"cpu",
|
||||
|
@ -636,16 +644,18 @@ function checkSystemSection(data) {
|
|||
}
|
||||
|
||||
if (gIsWindows) {
|
||||
Assert.equal(
|
||||
typeof data.system.isWow64,
|
||||
"boolean",
|
||||
"isWow64 must be available on Windows and have the correct type."
|
||||
);
|
||||
Assert.equal(
|
||||
typeof data.system.isWowARM64,
|
||||
"boolean",
|
||||
"isWowARM64 must be available on Windows and have the correct type."
|
||||
);
|
||||
if (assertProcessData) {
|
||||
Assert.equal(
|
||||
typeof data.system.isWow64,
|
||||
"boolean",
|
||||
"isWow64 must be available on Windows and have the correct type."
|
||||
);
|
||||
Assert.equal(
|
||||
typeof data.system.isWowARM64,
|
||||
"boolean",
|
||||
"isWowARM64 must be available on Windows and have the correct type."
|
||||
);
|
||||
}
|
||||
Assert.ok(
|
||||
"virtualMaxMB" in data.system,
|
||||
"virtualMaxMB must be available."
|
||||
|
@ -1011,13 +1021,17 @@ function checkExperimentsSection(data) {
|
|||
}
|
||||
|
||||
function checkEnvironmentData(data, options = {}) {
|
||||
const { isInitial = false, expectBrokenAddons = false } = options;
|
||||
const {
|
||||
isInitial = false,
|
||||
expectBrokenAddons = false,
|
||||
assertProcessData = false,
|
||||
} = options;
|
||||
|
||||
checkBuildSection(data);
|
||||
checkSettingsSection(data);
|
||||
checkProfileSection(data);
|
||||
checkPartnerSection(data, isInitial);
|
||||
checkSystemSection(data);
|
||||
checkSystemSection(data, assertProcessData);
|
||||
checkAddonsSection(data, expectBrokenAddons);
|
||||
}
|
||||
|
||||
|
@ -1109,7 +1123,7 @@ add_task(async function test_checkEnvironment() {
|
|||
Services.obs.notifyObservers(null, DISTRIBUTION_CUSTOMIZATION_COMPLETE_TOPIC);
|
||||
|
||||
environmentData = TelemetryEnvironment.currentEnvironment;
|
||||
checkEnvironmentData(environmentData);
|
||||
checkEnvironmentData(environmentData, { assertProcessData: true });
|
||||
});
|
||||
|
||||
add_task(async function test_prefWatchPolicies() {
|
||||
|
@ -2485,6 +2499,40 @@ if (gIsWindows) {
|
|||
checkString(data.system.hdd[k].type);
|
||||
}
|
||||
});
|
||||
|
||||
add_task(async function test_environmentProcessInfo() {
|
||||
await TelemetryEnvironment.testCleanRestart().onInitialized();
|
||||
let data = TelemetryEnvironment.currentEnvironment;
|
||||
Assert.deepEqual(data.system.isWow64, null, "Should have no data yet.");
|
||||
await TelemetryEnvironment.delayedInit();
|
||||
data = TelemetryEnvironment.currentEnvironment;
|
||||
Assert.equal(
|
||||
typeof data.system.isWow64,
|
||||
"boolean",
|
||||
"isWow64 must be a boolean."
|
||||
);
|
||||
Assert.equal(
|
||||
typeof data.system.isWowARM64,
|
||||
"boolean",
|
||||
"isWowARM64 must be a boolean."
|
||||
);
|
||||
});
|
||||
|
||||
add_task(async function test_environmentOSInfo() {
|
||||
await TelemetryEnvironment.testCleanRestart().onInitialized();
|
||||
let data = TelemetryEnvironment.currentEnvironment;
|
||||
Assert.deepEqual(
|
||||
data.system.os.installYear,
|
||||
null,
|
||||
"Should have no data yet."
|
||||
);
|
||||
await TelemetryEnvironment.delayedInit();
|
||||
data = TelemetryEnvironment.currentEnvironment;
|
||||
Assert.ok(
|
||||
Number.isFinite(data.system.os.installYear),
|
||||
"Install year must be a number."
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
add_task(async function test_environmentShutdown() {
|
||||
|
|
|
@ -102,6 +102,40 @@ static void SimpleParseKeyValuePairs(
|
|||
|
||||
#if defined(XP_WIN)
|
||||
namespace {
|
||||
nsresult CollectProcessInfo(ProcessInfo& info) {
|
||||
// IsWow64Process2 is only available on Windows 10+, so we have to dynamically
|
||||
// check for its existence.
|
||||
typedef BOOL(WINAPI * LPFN_IWP2)(HANDLE, USHORT*, USHORT*);
|
||||
LPFN_IWP2 iwp2 = reinterpret_cast<LPFN_IWP2>(
|
||||
GetProcAddress(GetModuleHandle(L"kernel32"), "IsWow64Process2"));
|
||||
BOOL isWow64 = false;
|
||||
USHORT processMachine = IMAGE_FILE_MACHINE_UNKNOWN;
|
||||
USHORT nativeMachine = IMAGE_FILE_MACHINE_UNKNOWN;
|
||||
BOOL gotWow64Value;
|
||||
if (iwp2) {
|
||||
gotWow64Value = iwp2(GetCurrentProcess(), &processMachine, &nativeMachine);
|
||||
if (gotWow64Value) {
|
||||
info.isWow64 = (processMachine != IMAGE_FILE_MACHINE_UNKNOWN);
|
||||
}
|
||||
} else {
|
||||
gotWow64Value = IsWow64Process(GetCurrentProcess(), &isWow64);
|
||||
// The function only indicates a WOW64 environment if it's 32-bit x86
|
||||
// running on x86-64, so emulate what IsWow64Process2 would have given.
|
||||
if (gotWow64Value && info.isWow64) {
|
||||
processMachine = IMAGE_FILE_MACHINE_I386;
|
||||
nativeMachine = IMAGE_FILE_MACHINE_AMD64;
|
||||
}
|
||||
}
|
||||
NS_WARNING_ASSERTION(gotWow64Value, "IsWow64Process failed");
|
||||
if (gotWow64Value) {
|
||||
// Set this always, even for the x86-on-arm64 case.
|
||||
// Additional information if we're running x86-on-arm64
|
||||
info.isWowARM64 = (processMachine == IMAGE_FILE_MACHINE_I386 &&
|
||||
nativeMachine == IMAGE_FILE_MACHINE_ARM64);
|
||||
}
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
static nsresult GetFolderDiskInfo(nsIFile* file, FolderDiskInfo& info) {
|
||||
info.model.Truncate();
|
||||
info.revision.Truncate();
|
||||
|
@ -213,7 +247,7 @@ static nsresult CollectDiskInfo(nsIFile* greDir, nsIFile* winDir,
|
|||
return GetFolderDiskInfo(profDir, info.profile);
|
||||
}
|
||||
|
||||
nsresult GetInstallYear(uint32_t& aYear) {
|
||||
static nsresult CollectOSInfo(OSInfo& info) {
|
||||
HKEY hKey;
|
||||
LONG status = RegOpenKeyExW(
|
||||
HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", 0,
|
||||
|
@ -245,7 +279,7 @@ nsresult GetInstallYear(uint32_t& aYear) {
|
|||
return NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
|
||||
aYear = 1900UL + time.tm_year;
|
||||
info.installYear = 1900UL + time.tm_year;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -784,53 +818,6 @@ nsresult nsSystemInfo::Init() {
|
|||
return rv;
|
||||
}
|
||||
|
||||
// IsWow64Process2 is only available on Windows 10+, so we have to dynamically
|
||||
// check for its existence.
|
||||
typedef BOOL(WINAPI * LPFN_IWP2)(HANDLE, USHORT*, USHORT*);
|
||||
LPFN_IWP2 iwp2 = reinterpret_cast<LPFN_IWP2>(
|
||||
GetProcAddress(GetModuleHandle(L"kernel32"), "IsWow64Process2"));
|
||||
BOOL isWow64 = false;
|
||||
USHORT processMachine = IMAGE_FILE_MACHINE_UNKNOWN;
|
||||
USHORT nativeMachine = IMAGE_FILE_MACHINE_UNKNOWN;
|
||||
BOOL gotWow64Value;
|
||||
if (iwp2) {
|
||||
gotWow64Value = iwp2(GetCurrentProcess(), &processMachine, &nativeMachine);
|
||||
if (gotWow64Value) {
|
||||
isWow64 = (processMachine != IMAGE_FILE_MACHINE_UNKNOWN);
|
||||
}
|
||||
} else {
|
||||
gotWow64Value = IsWow64Process(GetCurrentProcess(), &isWow64);
|
||||
// The function only indicates a WOW64 environment if it's 32-bit x86
|
||||
// running on x86-64, so emulate what IsWow64Process2 would have given.
|
||||
if (gotWow64Value && isWow64) {
|
||||
processMachine = IMAGE_FILE_MACHINE_I386;
|
||||
nativeMachine = IMAGE_FILE_MACHINE_AMD64;
|
||||
}
|
||||
}
|
||||
NS_WARNING_ASSERTION(gotWow64Value, "IsWow64Process failed");
|
||||
if (gotWow64Value) {
|
||||
// Set this always, even for the x86-on-arm64 case.
|
||||
rv = SetPropertyAsBool(NS_LITERAL_STRING("isWow64"), !!isWow64);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
// Additional information if we're running x86-on-arm64
|
||||
bool isWowARM64 = (processMachine == IMAGE_FILE_MACHINE_I386 &&
|
||||
nativeMachine == IMAGE_FILE_MACHINE_ARM64);
|
||||
rv = SetPropertyAsBool(NS_LITERAL_STRING("isWowARM64"), !!isWowARM64);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t installYear = 0;
|
||||
if (NS_SUCCEEDED(GetInstallYear(installYear))) {
|
||||
rv = SetPropertyAsUint32(NS_LITERAL_STRING("installYear"), installYear);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
# ifndef __MINGW32__
|
||||
nsAutoString avInfo, antiSpyInfo, firewallInfo;
|
||||
if (NS_SUCCEEDED(
|
||||
|
@ -1096,8 +1083,28 @@ static bool GetJSObjForDiskInfo(JSContext* aCx, JS::Handle<JSObject*> aParent,
|
|||
JS::Rooted<JS::Value> val(aCx, JS::ObjectValue(*jsInfo));
|
||||
return JS_SetProperty(aCx, aParent, propName, val);
|
||||
}
|
||||
|
||||
JSObject* GetJSObjForOSInfo(JSContext* aCx, const OSInfo& info) {
|
||||
JS::Rooted<JSObject*> jsInfo(aCx, JS_NewPlainObject(aCx));
|
||||
|
||||
JS::Rooted<JS::Value> valInstallYear(aCx, JS::Int32Value(info.installYear));
|
||||
JS_SetProperty(aCx, jsInfo, "installYear", valInstallYear);
|
||||
return jsInfo;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
JSObject* GetJSObjForProcessInfo(JSContext* aCx, const ProcessInfo& info) {
|
||||
JS::Rooted<JSObject*> jsInfo(aCx, JS_NewPlainObject(aCx));
|
||||
|
||||
JS::Rooted<JS::Value> valisWow64(aCx, JS::BooleanValue(info.isWow64));
|
||||
JS_SetProperty(aCx, jsInfo, "isWow64", valisWow64);
|
||||
|
||||
JS::Rooted<JS::Value> valisWowARM64(aCx, JS::BooleanValue(info.isWowARM64));
|
||||
JS_SetProperty(aCx, jsInfo, "isWowARM64", valisWowARM64);
|
||||
return jsInfo;
|
||||
}
|
||||
|
||||
RefPtr<mozilla::LazyIdleThread> nsSystemInfo::GetHelperThread() {
|
||||
if (!mLazyHelperThread) {
|
||||
mLazyHelperThread =
|
||||
|
@ -1106,6 +1113,63 @@ RefPtr<mozilla::LazyIdleThread> nsSystemInfo::GetHelperThread() {
|
|||
return mLazyHelperThread;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSystemInfo::GetOsInfo(JSContext* aCx, Promise** aResult) {
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*aResult = nullptr;
|
||||
if (!XRE_IsParentProcess()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
#if defined(XP_WIN)
|
||||
nsIGlobalObject* global = xpc::CurrentNativeGlobal(aCx);
|
||||
if (NS_WARN_IF(!global)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
ErrorResult erv;
|
||||
RefPtr<Promise> promise = Promise::Create(global, erv);
|
||||
if (NS_WARN_IF(erv.Failed())) {
|
||||
return erv.StealNSResult();
|
||||
}
|
||||
|
||||
if (!mOSInfoPromise) {
|
||||
RefPtr<mozilla::LazyIdleThread> lazyIOThread = GetHelperThread();
|
||||
|
||||
mOSInfoPromise = InvokeAsync(lazyIOThread, __func__, []() {
|
||||
OSInfo info;
|
||||
nsresult rv = CollectOSInfo(info);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return OSInfoPromise::CreateAndResolve(info, __func__);
|
||||
}
|
||||
return OSInfoPromise::CreateAndReject(rv, __func__);
|
||||
});
|
||||
};
|
||||
|
||||
// Chain the new promise to the extant mozpromise
|
||||
RefPtr<Promise> capturedPromise = promise;
|
||||
mOSInfoPromise->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[capturedPromise](const OSInfo& info) {
|
||||
AutoJSAPI jsapi;
|
||||
if (NS_WARN_IF(!jsapi.Init(capturedPromise->GetGlobalObject()))) {
|
||||
capturedPromise->MaybeReject(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
JSContext* cx = jsapi.cx();
|
||||
JS::Rooted<JS::Value> val(
|
||||
cx, JS::ObjectValue(*GetJSObjForOSInfo(cx, info)));
|
||||
capturedPromise->MaybeResolve(val);
|
||||
},
|
||||
[capturedPromise](const nsresult rv) {
|
||||
// Resolve with null when installYear is not available from the system
|
||||
capturedPromise->MaybeResolve(JS::NullHandleValue);
|
||||
});
|
||||
|
||||
promise.forget(aResult);
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSystemInfo::GetDiskInfo(JSContext* aCx, Promise** aResult) {
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
|
@ -1159,9 +1223,8 @@ nsSystemInfo::GetDiskInfo(JSContext* aCx, Promise** aResult) {
|
|||
mDiskInfoPromise->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[capturedPromise](const DiskInfo& info) {
|
||||
RefPtr<nsIGlobalObject> global = capturedPromise->GetGlobalObject();
|
||||
AutoJSAPI jsapi;
|
||||
if (!global || !jsapi.Init(global)) {
|
||||
if (NS_WARN_IF(!jsapi.Init(capturedPromise->GetGlobalObject()))) {
|
||||
capturedPromise->MaybeReject(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
@ -1236,9 +1299,8 @@ nsSystemInfo::GetCountryCode(JSContext* aCx, Promise** aResult) {
|
|||
mCountryCodePromise->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[capturedPromise](const nsString& countryCode) {
|
||||
RefPtr<nsIGlobalObject> global = capturedPromise->GetGlobalObject();
|
||||
AutoJSAPI jsapi;
|
||||
if (!global || !jsapi.Init(global)) {
|
||||
if (NS_WARN_IF(!jsapi.Init(capturedPromise->GetGlobalObject()))) {
|
||||
capturedPromise->MaybeReject(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
|
@ -1258,3 +1320,61 @@ nsSystemInfo::GetCountryCode(JSContext* aCx, Promise** aResult) {
|
|||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsSystemInfo::GetProcessInfo(JSContext* aCx, Promise** aResult) {
|
||||
NS_ENSURE_ARG_POINTER(aResult);
|
||||
*aResult = nullptr;
|
||||
|
||||
if (!XRE_IsParentProcess()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
#if defined(XP_WIN)
|
||||
nsIGlobalObject* global = xpc::CurrentNativeGlobal(aCx);
|
||||
if (NS_WARN_IF(!global)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
ErrorResult erv;
|
||||
RefPtr<Promise> promise = Promise::Create(global, erv);
|
||||
if (NS_WARN_IF(erv.Failed())) {
|
||||
return erv.StealNSResult();
|
||||
}
|
||||
|
||||
if (!mProcessInfoPromise) {
|
||||
RefPtr<mozilla::LazyIdleThread> lazyIOThread = GetHelperThread();
|
||||
|
||||
mProcessInfoPromise = InvokeAsync(lazyIOThread, __func__, []() {
|
||||
ProcessInfo info;
|
||||
nsresult rv = CollectProcessInfo(info);
|
||||
if (NS_SUCCEEDED(rv)) {
|
||||
return ProcessInfoPromise::CreateAndResolve(info, __func__);
|
||||
}
|
||||
return ProcessInfoPromise::CreateAndReject(rv, __func__);
|
||||
});
|
||||
};
|
||||
|
||||
// Chain the new promise to the extant mozpromise
|
||||
RefPtr<Promise> capturedPromise = promise;
|
||||
mProcessInfoPromise->Then(
|
||||
GetMainThreadSerialEventTarget(), __func__,
|
||||
[capturedPromise](const ProcessInfo& info) {
|
||||
AutoJSAPI jsapi;
|
||||
if (NS_WARN_IF(!jsapi.Init(capturedPromise->GetGlobalObject()))) {
|
||||
capturedPromise->MaybeReject(NS_ERROR_UNEXPECTED);
|
||||
return;
|
||||
}
|
||||
JSContext* cx = jsapi.cx();
|
||||
JS::Rooted<JS::Value> val(
|
||||
cx, JS::ObjectValue(*GetJSObjForProcessInfo(cx, info)));
|
||||
capturedPromise->MaybeResolve(val);
|
||||
},
|
||||
[capturedPromise](const nsresult rv) {
|
||||
// Resolve with null when installYear is not available from the system
|
||||
capturedPromise->MaybeResolve(JS::NullHandleValue);
|
||||
});
|
||||
|
||||
promise.forget(aResult);
|
||||
#endif
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -28,12 +28,27 @@ struct DiskInfo {
|
|||
FolderDiskInfo system;
|
||||
};
|
||||
|
||||
struct OSInfo {
|
||||
uint32_t installYear;
|
||||
};
|
||||
|
||||
struct ProcessInfo {
|
||||
bool isWow64;
|
||||
bool isWowARM64;
|
||||
};
|
||||
|
||||
typedef mozilla::MozPromise<DiskInfo, nsresult, /* IsExclusive */ false>
|
||||
DiskInfoPromise;
|
||||
|
||||
typedef mozilla::MozPromise<nsAutoString, nsresult, /* IsExclusive */ false>
|
||||
CountryCodePromise;
|
||||
|
||||
typedef mozilla::MozPromise<OSInfo, nsresult, /* IsExclusive */ false>
|
||||
OSInfoPromise;
|
||||
|
||||
typedef mozilla::MozPromise<ProcessInfo, nsresult, /* IsExclusive */ false>
|
||||
ProcessInfoPromise;
|
||||
|
||||
class nsSystemInfo final : public nsISystemInfo, public nsHashPropertyBag {
|
||||
public:
|
||||
NS_DECL_ISUPPORTS_INHERITED
|
||||
|
@ -64,6 +79,8 @@ class nsSystemInfo final : public nsISystemInfo, public nsHashPropertyBag {
|
|||
|
||||
RefPtr<DiskInfoPromise> mDiskInfoPromise;
|
||||
RefPtr<CountryCodePromise> mCountryCodePromise;
|
||||
RefPtr<OSInfoPromise> mOSInfoPromise;
|
||||
RefPtr<ProcessInfoPromise> mProcessInfoPromise;
|
||||
RefPtr<mozilla::LazyIdleThread> mLazyHelperThread;
|
||||
RefPtr<mozilla::LazyIdleThread> GetHelperThread();
|
||||
};
|
||||
|
|
|
@ -22,4 +22,19 @@ interface nsISystemInfo : nsISupports
|
|||
*/
|
||||
[implicit_jscontext]
|
||||
readonly attribute Promise countryCode;
|
||||
|
||||
/**
|
||||
* Asynchronously gets OS info on the system's install year.
|
||||
* Note: only implemented on Windows, will return null elsewhere.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
readonly attribute Promise osInfo;
|
||||
|
||||
/**
|
||||
* Asynchronously gets process info that indicates if the process is running
|
||||
* under Wow64 and WowARM64.
|
||||
* Note: only implemented on Windows, will return null elsewhere.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
readonly attribute Promise processInfo;
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче