var { AppConstants } = ChromeUtils.importESModule( "resource://gre/modules/AppConstants.sys.mjs"
);
let gProfD = do_get_profile();
// Setup that allows to use the profile service in xpcshell tests, // lifted from `toolkit/profile/xpcshell/head.js`. function setupProfileService() {
let gDataHome = gProfD.clone();
gDataHome.append("data");
gDataHome.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
let gDataHomeLocal = gProfD.clone();
gDataHomeLocal.append("local");
gDataHomeLocal.createUnique(Ci.nsIFile.DIRECTORY_TYPE, 0o755);
/** *Takea`key1\nvalue1\n...`stringencodingasusedbytheWindowsnative *notificationserverDLL,andsplititintoanobject,keeping`action\n...` *intact. * *@param{string}tstringencoding. *@returns{object}anobjectwithkeysandvalues.
*/ function parseOneEncoded(t) { var launch = {};
var lines = t.split("\n"); while (lines.length) { var key = lines.shift(); var value; if (key === "action") {
value = lines.join("\n");
lines = [];
} else {
value = lines.shift();
}
launch[key] = value;
}
*@returns{Array}apairofasimplifiedXMLstringandanobjectwith *`launch`and`actions`keys.
*/ function parseLaunchAndActions(s) { var document = new DOMParser().parseFromString(s, "text/xml"); var root = document.documentElement;
var launchString = root.getAttribute("launch");
root.setAttribute("launch", "launch"); var launch = parseOneEncoded(launchString);
// `actions` is keyed by "content" attribute.
let actions = {}; for (var actionElement of root.querySelectorAll("action")) { // `activationType="system"` is special. Leave them alone.
let systemActivationType =
actionElement.getAttribute("activationType") === "system";
let action = {};
let names = [...actionElement.attributes].map(attribute => attribute.name);
for (var name of names) {
let value = actionElement.getAttribute(name);
// Here is where we parse stringified-JSON to simplify comparisons. if (value.startsWith("{")) {
value = JSON.parse(value); if ("opaqueRelaunchData" in value) {
value.opaqueRelaunchData = JSON.parse(value.opaqueRelaunchData);
}
}
function escape(s) { return s
.replace(/&/g, "&")
.replace(/"/g, """)
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/\n/g, "
");
}
function unescape(s) { return s
.replace(/&/g, "&")
.replace(/"/g, '"')
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/
/g, "\n");
}
function testAlert(when, { serverEnabled, profD, isBackgroundTaskMode } = {}) {
let argumentString = action => { //
is "\n".
let s = ``; if (serverEnabled) {
s += `program
${AppConstants.MOZ_APP_NAME}`;
} else {
s += `skipNotificationServer
true`;
} if (serverEnabled && profD) {
s += `
profile
${profD.path}`;
} if (serverEnabled) {
s += "
windowsTag
";
} if (action) {
s += `
action
${escape(JSON.stringify(action))}`;
}
return s;
};
let parsedArgumentString = action =>
parseOneEncoded(unescape(argumentString(action)));
let settingsAction = isBackgroundTaskMode
? ""
: `<action content="Notification settings"/>`;
let alertsService = Cc["@mozilla.org/system-alerts-service;1"]
.getService(Ci.nsIAlertsService)
.QueryInterface(Ci.nsIWindowsAlertsService);
let name = "name";
let title = "title";
let text = "text";
let imageURL = "file:///image.png";
let actions = [
{ action: "action1", title: "title1", iconURL: "file:///iconURL1.png" },
{ action: "action2", title: "title2", iconURL: "file:///iconURL2.png" },
];
let opaqueRelaunchData = { foo: 1, bar: "two" };
let alert = makeAlert({ name, title, text });
let expected = `<toast launch="launch"><visual><binding template="ToastText03"><text id="1">title</text><text id="2">text</text></binding></visual><actions>${settingsAction}</actions></toast>`; Assert.deepEqual(
[
expected.replace("<actions></actions>", "<actions/>"),
{
launch: parsedArgumentString({ action: "" }),
actions: Object.fromEntries(
[parsedSettingsAction()].filter(x => x.length)
),
},
],
parseLaunchAndActions(alertsService.getXmlStringForWindowsAlert(alert)),
when
);
// Pretend that this is a background task.
bts.overrideBackgroundTaskNameForTesting("taskname");
Services.prefs.setBoolPref( "alerts.useSystemBackend.windows.notificationserver.enabled", true
);
testAlert( "when notification server pref is true in background task, no default profile",
{ serverEnabled: true, isBackgroundTaskMode: true }
);
let profileService = Cc["@mozilla.org/toolkit/profile-service;1"].getService(
Ci.nsIToolkitProfileService
);
let profilePath = do_get_profile();
profilePath.append(`test_windows_alert_service`);
let profile = profileService.createUniqueProfile(
profilePath, "test_windows_alert_service", "tests"
);
profileService.defaultProfile = profile;
testAlert( "when notification server pref is true in background task, default profile",
{ serverEnabled: true, isBackgroundTaskMode: true, profD: profilePath }
);
// No longer a background task,
bts.overrideBackgroundTaskNameForTesting("");
});
// This test checks whether `nsIWindowsalert.imagePathUnchecked` is used // in the generated XML used to display notifications.
add_task(async function test_image_unchecked_xml() {
let alertsService = Cc["@mozilla.org/system-alerts-service;1"].getService(
Ci.nsIWindowsAlertsService
);
let name = "name";
let title = "title";
let text = "text";
let imageURL = "chrome://branding/content/icon32.gif";
let alert = makeAlert({ name, title, text, imageURL });
let capturedXML = alertsService.getXmlStringForWindowsAlert(alert); Assert.ok(capturedXML, "Should have captured toast XML");
Assert.deepEqual(
src,
imageURL, "Check if image path is set in alert.imagePathUnchecked"
);
});
// This test makes sure that we can still get a notification xml without // images in it.
add_task(async function test_not_gif_xml() {
let alertsService = Cc["@mozilla.org/system-alerts-service;1"].getService(
Ci.nsIWindowsAlertsService
);
let name = "name";
let title = "title";
let text = "text";
let alert = makeAlert({ name, title, text });
let capturedXML = alertsService.getXmlStringForWindowsAlert(alert); Assert.ok(capturedXML, "Should have captured toast XML");
Assert.ok(
!src, "Ensure that imagePathUnchecked is not set since there is no image."
);
});
Messung V0.5 in Prozent
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.20Bemerkung:
(Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können 2026-09-30)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.