Bug 1963815 - remove the unused 'modules' legacy telemetry custom ping, r=chutten.
Differential Revision: https://phabricator.services.mozilla.com/D247776
This commit is contained in:
committed by
fqueze@mozilla.com
parent
2afb2fbaa6
commit
515f08637b
@@ -42,7 +42,6 @@ ChromeUtils.defineESModuleGetters(lazy, {
|
||||
TelemetryEnvironment: "resource://gre/modules/TelemetryEnvironment.sys.mjs",
|
||||
TelemetryEventPing: "resource://gre/modules/EventPing.sys.mjs",
|
||||
TelemetryHealthPing: "resource://gre/modules/HealthPing.sys.mjs",
|
||||
TelemetryModules: "resource://gre/modules/ModulesPing.sys.mjs",
|
||||
TelemetryReportingPolicy:
|
||||
"resource://gre/modules/TelemetryReportingPolicy.sys.mjs",
|
||||
TelemetrySend: "resource://gre/modules/TelemetrySend.sys.mjs",
|
||||
@@ -818,11 +817,8 @@ var Impl = {
|
||||
lazy.TelemetryStorage.removeFHRDatabase();
|
||||
|
||||
// The init sequence is forced to run on shutdown for short sessions and
|
||||
// we don't want to start TelemetryModules as the timer registration will fail.
|
||||
// we don't want to start everything.
|
||||
if (!this._shuttingDown) {
|
||||
// Report the modules loaded in the Firefox process.
|
||||
lazy.TelemetryModules.start();
|
||||
|
||||
// Send coverage ping.
|
||||
await lazy.CoveragePing.startup();
|
||||
|
||||
|
||||
@@ -91,7 +91,6 @@
|
||||
namespace {
|
||||
|
||||
using namespace mozilla;
|
||||
using mozilla::dom::AutoJSAPI;
|
||||
using mozilla::dom::Promise;
|
||||
using mozilla::Telemetry::CombinedStacks;
|
||||
using mozilla::Telemetry::EventExtraEntry;
|
||||
@@ -667,239 +666,6 @@ TelemetryImpl::GetAreUntrustedModuleLoadEventsReady(bool* ret) {
|
||||
#endif
|
||||
}
|
||||
|
||||
#if defined(MOZ_GECKO_PROFILER)
|
||||
class GetLoadedModulesResultRunnable final : public Runnable {
|
||||
nsMainThreadPtrHandle<Promise> mPromise;
|
||||
SharedLibraryInfo mRawModules;
|
||||
nsCOMPtr<nsIThread> mWorkerThread;
|
||||
# if defined(XP_WIN)
|
||||
nsTHashMap<nsStringHashKey, nsString> mCertSubjects;
|
||||
# endif // defined(XP_WIN)
|
||||
|
||||
public:
|
||||
GetLoadedModulesResultRunnable(const nsMainThreadPtrHandle<Promise>& aPromise,
|
||||
const SharedLibraryInfo& rawModules)
|
||||
: mozilla::Runnable("GetLoadedModulesResultRunnable"),
|
||||
mPromise(aPromise),
|
||||
mRawModules(rawModules),
|
||||
mWorkerThread(do_GetCurrentThread()) {
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
# if defined(XP_WIN)
|
||||
ObtainCertSubjects();
|
||||
# endif // defined(XP_WIN)
|
||||
}
|
||||
|
||||
NS_IMETHOD
|
||||
Run() override {
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
|
||||
mWorkerThread->Shutdown();
|
||||
|
||||
AutoJSAPI jsapi;
|
||||
if (NS_WARN_IF(!jsapi.Init(mPromise->GetGlobalObject()))) {
|
||||
mPromise->MaybeReject(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JSContext* cx = jsapi.cx();
|
||||
|
||||
JS::Rooted<JSObject*> moduleArray(cx, JS::NewArrayObject(cx, 0));
|
||||
if (!moduleArray) {
|
||||
mPromise->MaybeReject(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0, n = mRawModules.GetSize(); i != n; i++) {
|
||||
const SharedLibrary& info = mRawModules.GetEntry(i);
|
||||
|
||||
JS::Rooted<JSObject*> moduleObj(cx, JS_NewPlainObject(cx));
|
||||
if (!moduleObj) {
|
||||
mPromise->MaybeReject(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Module name.
|
||||
JS::Rooted<JSString*> moduleName(
|
||||
cx,
|
||||
JS_NewUCStringCopyZ(
|
||||
cx, NS_ConvertUTF8toUTF16(info.GetModuleName().c_str()).get()));
|
||||
if (!moduleName || !JS_DefineProperty(cx, moduleObj, "name", moduleName,
|
||||
JSPROP_ENUMERATE)) {
|
||||
mPromise->MaybeReject(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Module debug name.
|
||||
JS::Rooted<JS::Value> moduleDebugName(cx);
|
||||
|
||||
if (!info.GetDebugName().empty()) {
|
||||
JS::Rooted<JSString*> str_moduleDebugName(
|
||||
cx,
|
||||
JS_NewUCStringCopyZ(
|
||||
cx, NS_ConvertUTF8toUTF16(info.GetDebugName().c_str()).get()));
|
||||
if (!str_moduleDebugName) {
|
||||
mPromise->MaybeReject(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
moduleDebugName.setString(str_moduleDebugName);
|
||||
} else {
|
||||
moduleDebugName.setNull();
|
||||
}
|
||||
|
||||
if (!JS_DefineProperty(cx, moduleObj, "debugName", moduleDebugName,
|
||||
JSPROP_ENUMERATE)) {
|
||||
mPromise->MaybeReject(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Module Breakpad identifier.
|
||||
JS::Rooted<JS::Value> id(cx);
|
||||
|
||||
if (!info.GetBreakpadId().empty()) {
|
||||
JS::Rooted<JSString*> str_id(
|
||||
cx, JS_NewStringCopyZ(cx, info.GetBreakpadId().c_str()));
|
||||
if (!str_id) {
|
||||
mPromise->MaybeReject(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
id.setString(str_id);
|
||||
} else {
|
||||
id.setNull();
|
||||
}
|
||||
|
||||
if (!JS_DefineProperty(cx, moduleObj, "debugID", id, JSPROP_ENUMERATE)) {
|
||||
mPromise->MaybeReject(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// Module version.
|
||||
JS::Rooted<JS::Value> version(cx);
|
||||
|
||||
if (!info.GetVersion().empty()) {
|
||||
JS::Rooted<JSString*> v(
|
||||
cx, JS_NewStringCopyZ(cx, info.GetVersion().c_str()));
|
||||
if (!v) {
|
||||
mPromise->MaybeReject(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
version.setString(v);
|
||||
} else {
|
||||
version.setNull();
|
||||
}
|
||||
|
||||
if (!JS_DefineProperty(cx, moduleObj, "version", version,
|
||||
JSPROP_ENUMERATE)) {
|
||||
mPromise->MaybeReject(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
# if defined(XP_WIN)
|
||||
// Cert Subject.
|
||||
if (auto subject = mCertSubjects.Lookup(
|
||||
NS_ConvertUTF8toUTF16(info.GetModulePath().c_str()))) {
|
||||
JS::Rooted<JSString*> jsOrg(cx, ToJSString(cx, *subject));
|
||||
if (!jsOrg) {
|
||||
mPromise->MaybeReject(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
JS::Rooted<JS::Value> certSubject(cx);
|
||||
certSubject.setString(jsOrg);
|
||||
|
||||
if (!JS_DefineProperty(cx, moduleObj, "certSubject", certSubject,
|
||||
JSPROP_ENUMERATE)) {
|
||||
mPromise->MaybeReject(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
# endif // defined(XP_WIN)
|
||||
|
||||
if (!JS_DefineElement(cx, moduleArray, i, moduleObj, JSPROP_ENUMERATE)) {
|
||||
mPromise->MaybeReject(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
}
|
||||
|
||||
mPromise->MaybeResolve(moduleArray);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
# if defined(XP_WIN)
|
||||
void ObtainCertSubjects() {
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
|
||||
// NB: Currently we cannot lower this down to the profiler layer due to
|
||||
// differing startup dependencies between the profiler and DllServices.
|
||||
RefPtr<DllServices> dllSvc(DllServices::Get());
|
||||
|
||||
for (unsigned int i = 0, n = mRawModules.GetSize(); i != n; i++) {
|
||||
const SharedLibrary& info = mRawModules.GetEntry(i);
|
||||
|
||||
auto orgName = dllSvc->GetBinaryOrgName(
|
||||
NS_ConvertUTF8toUTF16(info.GetModulePath().c_str()).get());
|
||||
if (orgName) {
|
||||
mCertSubjects.InsertOrUpdate(
|
||||
NS_ConvertUTF8toUTF16(info.GetModulePath().c_str()),
|
||||
nsDependentString(orgName.get()));
|
||||
}
|
||||
}
|
||||
}
|
||||
# endif // defined(XP_WIN)
|
||||
};
|
||||
|
||||
class GetLoadedModulesRunnable final : public Runnable {
|
||||
nsMainThreadPtrHandle<Promise> mPromise;
|
||||
|
||||
public:
|
||||
explicit GetLoadedModulesRunnable(
|
||||
const nsMainThreadPtrHandle<Promise>& aPromise)
|
||||
: mozilla::Runnable("GetLoadedModulesRunnable"), mPromise(aPromise) {}
|
||||
|
||||
NS_IMETHOD
|
||||
Run() override {
|
||||
nsCOMPtr<nsIRunnable> resultRunnable = new GetLoadedModulesResultRunnable(
|
||||
mPromise, SharedLibraryInfo::GetInfoForSelf());
|
||||
return NS_DispatchToMainThread(resultRunnable);
|
||||
}
|
||||
};
|
||||
#endif // MOZ_GECKO_PROFILER
|
||||
|
||||
NS_IMETHODIMP
|
||||
TelemetryImpl::GetLoadedModules(JSContext* cx, Promise** aPromise) {
|
||||
#if defined(MOZ_GECKO_PROFILER)
|
||||
nsIGlobalObject* global = xpc::CurrentNativeGlobal(cx);
|
||||
if (NS_WARN_IF(!global)) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
ErrorResult result;
|
||||
RefPtr<Promise> promise = Promise::Create(global, result);
|
||||
if (NS_WARN_IF(result.Failed())) {
|
||||
return result.StealNSResult();
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIThread> getModulesThread;
|
||||
nsresult rv =
|
||||
NS_NewNamedThread("TelemetryModule", getter_AddRefs(getModulesThread));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
promise->MaybeReject(NS_ERROR_FAILURE);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsMainThreadPtrHandle<Promise> mainThreadPromise(
|
||||
new nsMainThreadPtrHolder<Promise>(
|
||||
"TelemetryImpl::GetLoadedModules::Promise", promise));
|
||||
nsCOMPtr<nsIRunnable> runnable =
|
||||
new GetLoadedModulesRunnable(mainThreadPromise);
|
||||
promise.forget(aPromise);
|
||||
|
||||
return getModulesThread->Dispatch(runnable, nsIEventTarget::DISPATCH_NORMAL);
|
||||
#else // MOZ_GECKO_PROFILER
|
||||
return NS_ERROR_NOT_IMPLEMENTED;
|
||||
#endif // MOZ_GECKO_PROFILER
|
||||
}
|
||||
|
||||
static bool IsValidBreakpadId(const std::string& breakpadId) {
|
||||
if (breakpadId.size() < 33) {
|
||||
return false;
|
||||
|
||||
@@ -246,29 +246,6 @@ interface nsITelemetry : nsISupports
|
||||
* will result in an empty array. */
|
||||
readonly attribute boolean areUntrustedModuleLoadEventsReady;
|
||||
|
||||
/*
|
||||
* Asynchronously get an array of the modules loaded in the process.
|
||||
*
|
||||
* The data has the following structure:
|
||||
*
|
||||
* [
|
||||
* {
|
||||
* "name": <string>, // Name of the module file (e.g. xul.dll)
|
||||
* "version": <string>, // Version of the module
|
||||
* "debugName": <string>, // ID of the debug information file
|
||||
* "debugID": <string>, // Name of the debug information file
|
||||
* "certSubject": <string>, // Name of the organization that signed the binary (Optional, only defined when present)
|
||||
* },
|
||||
* ...
|
||||
* ]
|
||||
*
|
||||
* @return A promise that resolves to an array of modules or rejects with
|
||||
NS_ERROR_FAILURE on failure.
|
||||
* @throws NS_ERROR_NOT_IMPLEMENTED if the Gecko profiler is not enabled.
|
||||
*/
|
||||
[implicit_jscontext]
|
||||
Promise getLoadedModules();
|
||||
|
||||
/*
|
||||
* An object with two fields: memoryMap and stacks.
|
||||
* * memoryMap is a list of loaded libraries.
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
|
||||
"modules" ping
|
||||
==============
|
||||
|
||||
This ping is sent once a week and includes the modules loaded in the Firefox process.
|
||||
|
||||
The client ID, profile group ID and environment are submitted with this ping.
|
||||
|
||||
Structure:
|
||||
|
||||
.. code-block:: js
|
||||
|
||||
{
|
||||
type: "modules",
|
||||
... common ping data
|
||||
clientId: <UUID>,
|
||||
profileGroupId: <UUID>,
|
||||
environment: { ... },
|
||||
payload: {
|
||||
version: 1,
|
||||
modules: [
|
||||
{
|
||||
name: <string>, // Name of the module file (e.g. xul.dll)
|
||||
version: <string>, // Version of the module
|
||||
debugID: <string>, // ID of the debug information file
|
||||
debugName: <string>, // Name of the debug information file
|
||||
certSubject: <string>, // Name of the organization that signed the binary (Optional, only defined when present)
|
||||
},
|
||||
...
|
||||
],
|
||||
}
|
||||
}
|
||||
|
||||
Notes
|
||||
~~~~~
|
||||
|
||||
The version information is only available on Windows, it is null on other platforms.
|
||||
|
||||
The debug name is the name of the PDB on Windows (which isn't always the same as the module name modulo the extension, e.g. the PDB for C:\Windows\SysWOW64\ntdll.dll is wntdll.pdb) and is the same as the module name on other platforms.
|
||||
|
||||
The debug ID is platform-dependent. It is compatible with the Breakpad ID used on Socorro.
|
||||
|
||||
Sometimes the debug name and debug ID are missing for Windows modules (often with malware). In this case, they will be "null".
|
||||
|
||||
The length of the modules array is limited to 512 entries.
|
||||
|
||||
The name and debug name are length limited, with a maximum of 64 characters.
|
||||
@@ -227,10 +227,6 @@ The following prefs are for testing purpose only.
|
||||
|
||||
Timeout until we decide whether a user is idle or not (seconds).
|
||||
|
||||
``toolkit.telemetry.modulesPing.interval``
|
||||
|
||||
Interval between "modules" ping transmissions.
|
||||
|
||||
``toolkit.telemetry.send.overrideOfficialCheck``
|
||||
|
||||
If true, allows sending pings on unofficial builds. Requires a restart.
|
||||
|
||||
@@ -126,7 +126,6 @@ EXTRA_JS_MODULES += [
|
||||
"pings/CoveragePing.sys.mjs",
|
||||
"pings/EventPing.sys.mjs",
|
||||
"pings/HealthPing.sys.mjs",
|
||||
"pings/ModulesPing.sys.mjs",
|
||||
"pings/TelemetrySession.sys.mjs",
|
||||
"pings/UntrustedModulesPing.sys.mjs",
|
||||
"pings/UpdatePing.sys.mjs",
|
||||
|
||||
@@ -1,116 +0,0 @@
|
||||
/* 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/. */
|
||||
|
||||
import { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
|
||||
import { Log } from "resource://gre/modules/Log.sys.mjs";
|
||||
import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
|
||||
|
||||
const lazy = {};
|
||||
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
TelemetryController: "resource://gre/modules/TelemetryController.sys.mjs",
|
||||
});
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(
|
||||
lazy,
|
||||
"gUpdateTimerManager",
|
||||
"@mozilla.org/updates/timer-manager;1",
|
||||
"nsIUpdateTimerManager"
|
||||
);
|
||||
|
||||
const LOGGER_NAME = "Toolkit.Telemetry";
|
||||
const LOGGER_PREFIX = "TelemetryModules::";
|
||||
|
||||
// The default is 1 week.
|
||||
const MODULES_PING_INTERVAL_SECONDS = 7 * 24 * 60 * 60;
|
||||
const MODULES_PING_INTERVAL_PREFERENCE =
|
||||
"toolkit.telemetry.modulesPing.interval";
|
||||
|
||||
const MAX_MODULES_NUM = 512;
|
||||
const MAX_NAME_LENGTH = 64;
|
||||
const TRUNCATION_DELIMITER = "\u2026";
|
||||
|
||||
export var TelemetryModules = Object.freeze({
|
||||
_log: Log.repository.getLoggerWithMessagePrefix(LOGGER_NAME, LOGGER_PREFIX),
|
||||
|
||||
start() {
|
||||
// The list of loaded modules is obtainable only when the profiler is enabled.
|
||||
// If it isn't, we don't want to send the ping at all.
|
||||
if (!AppConstants.MOZ_GECKO_PROFILER) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Use nsIUpdateTimerManager for a long-duration timer that survives across sessions.
|
||||
let interval = Services.prefs.getIntPref(
|
||||
MODULES_PING_INTERVAL_PREFERENCE,
|
||||
MODULES_PING_INTERVAL_SECONDS
|
||||
);
|
||||
lazy.gUpdateTimerManager.registerTimer(
|
||||
"telemetry_modules_ping",
|
||||
this,
|
||||
interval,
|
||||
interval != 0 // only skip the first interval if the interval is non-0
|
||||
);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the 'telemetry_modules_ping' timer fires.
|
||||
*/
|
||||
notify() {
|
||||
try {
|
||||
Services.telemetry.getLoadedModules().then(
|
||||
modules => {
|
||||
modules = modules.filter(module => !!module.name.length);
|
||||
|
||||
// Cut the list of modules to MAX_MODULES_NUM entries.
|
||||
if (modules.length > MAX_MODULES_NUM) {
|
||||
modules = modules.slice(0, MAX_MODULES_NUM);
|
||||
}
|
||||
|
||||
// Cut the file names of the modules to MAX_NAME_LENGTH characters.
|
||||
for (let module of modules) {
|
||||
if (module.name.length > MAX_NAME_LENGTH) {
|
||||
module.name =
|
||||
module.name.substr(0, MAX_NAME_LENGTH - 1) +
|
||||
TRUNCATION_DELIMITER;
|
||||
}
|
||||
|
||||
if (
|
||||
module.debugName !== null &&
|
||||
module.debugName.length > MAX_NAME_LENGTH
|
||||
) {
|
||||
module.debugName =
|
||||
module.debugName.substr(0, MAX_NAME_LENGTH - 1) +
|
||||
TRUNCATION_DELIMITER;
|
||||
}
|
||||
|
||||
if (
|
||||
module.certSubject !== undefined &&
|
||||
module.certSubject.length > MAX_NAME_LENGTH
|
||||
) {
|
||||
module.certSubject =
|
||||
module.certSubject.substr(0, MAX_NAME_LENGTH - 1) +
|
||||
TRUNCATION_DELIMITER;
|
||||
}
|
||||
}
|
||||
|
||||
lazy.TelemetryController.submitExternalPing(
|
||||
"modules",
|
||||
{
|
||||
version: 1,
|
||||
modules,
|
||||
},
|
||||
{
|
||||
addClientId: true,
|
||||
addEnvironment: true,
|
||||
}
|
||||
);
|
||||
},
|
||||
err => this._log.error("notify - promise failed", err)
|
||||
);
|
||||
} catch (ex) {
|
||||
this._log.error("notify - caught exception", ex);
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -2,26 +2,9 @@
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
/*
|
||||
* This source file is used to build different shared libraries:
|
||||
*
|
||||
* - libmodules-test; it is automatically built by our build system (see the
|
||||
* moz.build in the same directory as this file);
|
||||
*
|
||||
* - testUnicodePDB32.dll and testUnicodePDB64.dll; they can be built by
|
||||
* compiling this source file using MSVC and setting the target name to be
|
||||
* "libmodμles", then renaming the resulting file:
|
||||
* cl /Os /Zi modules-test.cpp /LINK /DLL /OUT:libmodμles.dll \
|
||||
* /nodefaultlib /entry:nothing /opt:ref
|
||||
* copy libmodμles.dll testUnicodePDB*ARCH*.dll
|
||||
*
|
||||
* - testNoPDB32.dll and testNoPDB64.dll; they can be built by compiling this
|
||||
* file using MSVC, without enabling generation of a PDB:
|
||||
* cl /Os modules-test.cpp /LINK /DLL /OUT:testNoPDB*ARCH*.dll \
|
||||
* /nodefaultlib /entry:nothing
|
||||
*
|
||||
* Clearly, for testUnicodePDB and testNoPDB both a 32-bit and a 64-bit version
|
||||
* have to be compiled, using the 32-bit and 64-bit MSVC toolchains.
|
||||
*
|
||||
* This source file is used to build the libmodules-test shared libraries;
|
||||
* it is automatically built by our build system (see the moz.build file
|
||||
* in the same directory as this file);
|
||||
*/
|
||||
|
||||
void nothing() {}
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,297 +0,0 @@
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
const { ctypes } = ChromeUtils.importESModule(
|
||||
"resource://gre/modules/ctypes.sys.mjs"
|
||||
);
|
||||
|
||||
const MAX_NAME_LENGTH = 64;
|
||||
|
||||
// The following libraries (except libxul) are all built from the
|
||||
// toolkit/components/telemetry/tests/modules-test.cpp file, which contains
|
||||
// instructions on how to build them.
|
||||
const libModules = ctypes.libraryName("modules-test");
|
||||
const libUnicode = ctypes.libraryName("modμles-test");
|
||||
const libLongName =
|
||||
"lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit_Fusce_sit_amet_tellus_non_magna_euismod_vestibulum_Vivamus_turpis_duis.dll";
|
||||
|
||||
function chooseDLL(x86, x64, aarch64) {
|
||||
let xpcomabi = Services.appinfo.XPCOMABI;
|
||||
let cpu = xpcomabi.split("-")[0];
|
||||
switch (cpu) {
|
||||
case "aarch64":
|
||||
return aarch64;
|
||||
case "x86_64":
|
||||
return x64;
|
||||
case "x86":
|
||||
return x86;
|
||||
// This case only happens on Android, which gets skipped below. The previous
|
||||
// code was returning the x86 version when testing for arm.
|
||||
case "arm":
|
||||
return x86;
|
||||
default:
|
||||
Assert.ok(false, "unexpected CPU type: " + cpu);
|
||||
return x86;
|
||||
}
|
||||
}
|
||||
|
||||
const libUnicodePDB = chooseDLL(
|
||||
"testUnicodePDB32.dll",
|
||||
"testUnicodePDB64.dll",
|
||||
"testUnicodePDBAArch64.dll"
|
||||
);
|
||||
const libNoPDB = chooseDLL(
|
||||
"testNoPDB32.dll",
|
||||
"testNoPDB64.dll",
|
||||
"testNoPDBAArch64.dll"
|
||||
);
|
||||
const libxul = PathUtils.filename(PathUtils.xulLibraryPath);
|
||||
|
||||
const libModulesFile = do_get_file(libModules).path;
|
||||
const libUnicodeFile = PathUtils.join(
|
||||
PathUtils.parent(libModulesFile),
|
||||
libUnicode
|
||||
);
|
||||
const libLongNameFile = PathUtils.join(
|
||||
PathUtils.parent(libModulesFile),
|
||||
libLongName
|
||||
);
|
||||
const libUnicodePDBFile = do_get_file(libUnicodePDB).path;
|
||||
const libNoPDBFile = do_get_file(libNoPDB).path;
|
||||
|
||||
let libModulesHandle,
|
||||
libUnicodeHandle,
|
||||
libLongNameHandle,
|
||||
libUnicodePDBHandle,
|
||||
libNoPDBHandle;
|
||||
|
||||
let expectedLibs;
|
||||
if (AppConstants.platform === "win") {
|
||||
const version = AppConstants.MOZ_APP_VERSION.substring(
|
||||
0,
|
||||
AppConstants.MOZ_APP_VERSION.indexOf(".") + 2
|
||||
);
|
||||
|
||||
expectedLibs = [
|
||||
{
|
||||
name: libxul,
|
||||
debugName: libxul.replace(".dll", ".pdb"),
|
||||
version,
|
||||
},
|
||||
{
|
||||
name: libModules,
|
||||
debugName: libModules.replace(".dll", ".pdb"),
|
||||
version,
|
||||
},
|
||||
{
|
||||
name: libUnicode,
|
||||
debugName: libModules.replace(".dll", ".pdb"),
|
||||
version,
|
||||
},
|
||||
{
|
||||
name: libLongName.substring(0, MAX_NAME_LENGTH - 1) + "…",
|
||||
debugName: libModules.replace(".dll", ".pdb"),
|
||||
version,
|
||||
},
|
||||
{
|
||||
name: libUnicodePDB,
|
||||
debugName: "libmodμles.pdb",
|
||||
version: null,
|
||||
},
|
||||
{
|
||||
name: libNoPDB,
|
||||
debugName: null,
|
||||
version: null,
|
||||
},
|
||||
{
|
||||
// We choose this DLL because it's guaranteed to exist in our process and
|
||||
// be signed on all Windows versions that we support.
|
||||
name: "ntdll.dll",
|
||||
// debugName changes depending on OS version and is irrelevant to this test
|
||||
// version changes depending on OS version and is irrelevant to this test
|
||||
certSubject: "Microsoft Windows",
|
||||
},
|
||||
];
|
||||
} else {
|
||||
expectedLibs = [
|
||||
{
|
||||
name: libxul,
|
||||
debugName: libxul,
|
||||
version: null,
|
||||
},
|
||||
{
|
||||
name: libModules,
|
||||
debugName: libModules,
|
||||
version: null,
|
||||
},
|
||||
{
|
||||
name: libUnicode,
|
||||
debugName: libUnicode,
|
||||
version: null,
|
||||
},
|
||||
{
|
||||
name: libLongName.substring(0, MAX_NAME_LENGTH - 1) + "…",
|
||||
debugName: libLongName.substring(0, MAX_NAME_LENGTH - 1) + "…",
|
||||
version: null,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
add_task(async function setup() {
|
||||
do_get_profile();
|
||||
|
||||
await IOUtils.copy(libModulesFile, libUnicodeFile);
|
||||
await IOUtils.copy(libModulesFile, libLongNameFile);
|
||||
|
||||
libModulesHandle = ctypes.open(libModulesFile);
|
||||
libUnicodeHandle = ctypes.open(libUnicodeFile);
|
||||
libLongNameHandle = ctypes.open(libLongNameFile);
|
||||
if (AppConstants.platform === "win") {
|
||||
libUnicodePDBHandle = ctypes.open(libUnicodePDBFile);
|
||||
libNoPDBHandle = ctypes.open(libNoPDBFile);
|
||||
}
|
||||
|
||||
// Pretend the untrustedmodules ping has already been sent now to get it out
|
||||
// of the way and avoid confusing the test with our PingServer receiving two
|
||||
// pings during our test.
|
||||
Services.prefs.setIntPref(
|
||||
"app.update.lastUpdateTime.telemetry_untrustedmodules_ping",
|
||||
Math.round(Date.now() / 1000)
|
||||
);
|
||||
|
||||
// Force the timer to fire (using a small interval).
|
||||
Cc["@mozilla.org/updates/timer-manager;1"]
|
||||
.getService(Ci.nsIObserver)
|
||||
.observe(null, "utm-test-init", "");
|
||||
Services.prefs.setIntPref("toolkit.telemetry.modulesPing.interval", 0);
|
||||
Services.prefs.setStringPref("app.update.url", "http://localhost");
|
||||
|
||||
// Start the local ping server and setup Telemetry to use it during the tests.
|
||||
PingServer.start();
|
||||
Services.prefs.setStringPref(
|
||||
TelemetryUtils.Preferences.Server,
|
||||
"http://localhost:" + PingServer.port
|
||||
);
|
||||
});
|
||||
|
||||
registerCleanupFunction(function () {
|
||||
if (libModulesHandle) {
|
||||
libModulesHandle.close();
|
||||
}
|
||||
if (libUnicodeHandle) {
|
||||
libUnicodeHandle.close();
|
||||
}
|
||||
if (libLongNameHandle) {
|
||||
libLongNameHandle.close();
|
||||
}
|
||||
if (libUnicodePDBHandle) {
|
||||
libUnicodePDBHandle.close();
|
||||
}
|
||||
if (libNoPDBHandle) {
|
||||
libNoPDBHandle.close();
|
||||
}
|
||||
|
||||
return IOUtils.remove(libUnicodeFile)
|
||||
.then(() => IOUtils.remove(libLongNameFile))
|
||||
.then(() => PingServer.stop());
|
||||
});
|
||||
|
||||
add_task(
|
||||
{
|
||||
skip_if: () => !AppConstants.MOZ_GECKO_PROFILER,
|
||||
},
|
||||
async function test_send_ping() {
|
||||
await TelemetryController.testSetup();
|
||||
|
||||
let found = await PingServer.promiseNextPing();
|
||||
Assert.ok(!!found, "Telemetry ping submitted.");
|
||||
Assert.strictEqual(found.type, "modules", "Ping type is 'modules'");
|
||||
Assert.ok(found.environment, "'modules' ping has an environment.");
|
||||
Assert.ok(!!found.clientId, "'modules' ping has a client ID.");
|
||||
Assert.ok(
|
||||
!!found.payload.modules,
|
||||
"Telemetry ping payload contains the 'modules' array."
|
||||
);
|
||||
|
||||
let nameComparator;
|
||||
if (AppConstants.platform === "win") {
|
||||
// Do case-insensitive checking of file/module names on Windows
|
||||
nameComparator = function (a, b) {
|
||||
if (typeof a === "string" && typeof b === "string") {
|
||||
return a.toLowerCase() === b.toLowerCase();
|
||||
}
|
||||
|
||||
return a === b;
|
||||
};
|
||||
} else {
|
||||
nameComparator = function (a, b) {
|
||||
return a === b;
|
||||
};
|
||||
}
|
||||
|
||||
for (let lib of expectedLibs) {
|
||||
let test_lib = found.payload.modules.find(module =>
|
||||
nameComparator(module.name, lib.name)
|
||||
);
|
||||
|
||||
Assert.ok(!!test_lib, "There is a '" + lib.name + "' module.");
|
||||
|
||||
if ("version" in lib) {
|
||||
if (lib.version !== null) {
|
||||
Assert.ok(
|
||||
test_lib.version.startsWith(lib.version),
|
||||
"The version of the " +
|
||||
lib.name +
|
||||
" module (" +
|
||||
test_lib.version +
|
||||
") is correct (it starts with '" +
|
||||
lib.version +
|
||||
"')."
|
||||
);
|
||||
} else {
|
||||
Assert.strictEqual(
|
||||
test_lib.version,
|
||||
null,
|
||||
"The version of the " + lib.name + " module is null."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if ("debugName" in lib) {
|
||||
Assert.ok(
|
||||
nameComparator(test_lib.debugName, lib.debugName),
|
||||
"The " + lib.name + " module has the correct debug name."
|
||||
);
|
||||
}
|
||||
|
||||
if (lib.debugName === null) {
|
||||
Assert.strictEqual(
|
||||
test_lib.debugID,
|
||||
null,
|
||||
"The " + lib.name + " module doesn't have a debug ID."
|
||||
);
|
||||
} else {
|
||||
Assert.greater(
|
||||
test_lib.debugID.length,
|
||||
0,
|
||||
"The " + lib.name + " module has a debug ID."
|
||||
);
|
||||
}
|
||||
|
||||
if ("certSubject" in lib) {
|
||||
Assert.strictEqual(
|
||||
test_lib.certSubject,
|
||||
lib.certSubject,
|
||||
"The " + lib.name + " module has the expected cert subject."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
let test_lib = found.payload.modules.find(
|
||||
module => module.name === libLongName
|
||||
);
|
||||
Assert.ok(!test_lib, "There isn't a '" + libLongName + "' module.");
|
||||
}
|
||||
);
|
||||
@@ -7,12 +7,6 @@ support-files = [
|
||||
"engine.xml",
|
||||
"system.xpi",
|
||||
"restartless.xpi",
|
||||
"testUnicodePDB32.dll",
|
||||
"testNoPDB32.dll",
|
||||
"testUnicodePDB64.dll",
|
||||
"testNoPDB64.dll",
|
||||
"testUnicodePDBAArch64.dll",
|
||||
"testNoPDBAArch64.dll",
|
||||
"!/toolkit/mozapps/extensions/test/xpcshell/head_addons.js",
|
||||
"../../../../mozapps/extensions/test/xpinstall/amosigned.xpi",
|
||||
"../../../../mozapps/extensions/test/xpcshell/data/webext-implicit-id.xpi",
|
||||
@@ -40,14 +34,6 @@ tags = "addons"
|
||||
|
||||
["test_MigratePendingPings.js"]
|
||||
|
||||
["test_ModulesPing.js"]
|
||||
skip-if = [
|
||||
"os == 'mac' && os_version == '10.15' && processor == 'x86_64'", # Bug 1713329
|
||||
"os == 'mac' && os_version == '11.20' && arch == 'aarch64'", # Bug 1707747
|
||||
"os == 'mac' && os_version == '14.70' && processor == 'x86_64'", # Bug 1929422
|
||||
"os == 'mac' && os_version == '15.30' && arch == 'aarch64'", # Bug 1707747
|
||||
]
|
||||
|
||||
["test_PingAPI.js"]
|
||||
|
||||
["test_PingSender.js"]
|
||||
|
||||
@@ -635,7 +635,6 @@ export interface LazyModules {
|
||||
"resource://gre/modules/MediaUtils.sys.mjs": typeof import("resource://gre/modules/MediaUtils.sys.mjs"),
|
||||
"resource://gre/modules/MessageManagerProxy.sys.mjs": typeof import("resource://gre/modules/MessageManagerProxy.sys.mjs"),
|
||||
"resource://gre/modules/Messaging.sys.mjs": typeof import("resource://gre/modules/Messaging.sys.mjs"),
|
||||
"resource://gre/modules/ModulesPing.sys.mjs": typeof import("resource://gre/modules/ModulesPing.sys.mjs"),
|
||||
"resource://gre/modules/NLP.sys.mjs": typeof import("resource://gre/modules/NLP.sys.mjs"),
|
||||
"resource://gre/modules/NativeManifests.sys.mjs": typeof import("resource://gre/modules/NativeManifests.sys.mjs"),
|
||||
"resource://gre/modules/NativeMessaging.sys.mjs": typeof import("resource://gre/modules/NativeMessaging.sys.mjs"),
|
||||
|
||||
@@ -6149,9 +6149,6 @@
|
||||
"resource://gre/modules/Messaging.sys.mjs": [
|
||||
"mobile/shared/modules/geckoview/Messaging.sys.mjs"
|
||||
],
|
||||
"resource://gre/modules/ModulesPing.sys.mjs": [
|
||||
"toolkit/components/telemetry/pings/ModulesPing.sys.mjs"
|
||||
],
|
||||
"resource://gre/modules/NLP.sys.mjs": [
|
||||
"toolkit/modules/NLP.sys.mjs"
|
||||
],
|
||||
|
||||
Reference in New Issue
Block a user