/* Any copyright is dedicated to the Public Domain. http://creativecommons.org/publicdomain/zero/1.0/ */ const { TelemetryController } = ChromeUtils.importESModule( "resource://gre/modules/TelemetryController.sys.mjs" ); const { TelemetrySession } = ChromeUtils.importESModule( "resource://gre/modules/TelemetrySession.sys.mjs" ); const { ContentTaskUtils } = ChromeUtils.importESModule( "resource://testing-common/ContentTaskUtils.sys.mjs" ); const MESSAGE_CHILD_TEST_DONE = "ChildTest:Done"; const UINT_SCALAR = "telemetry.test.unsigned_int_kind"; const KEYED_UINT_SCALAR = "telemetry.test.keyed_unsigned_int"; const KEYED_BOOL_SCALAR = "telemetry.test.keyed_boolean_kind"; const CONTENT_ONLY_UINT_SCALAR = "telemetry.test.content_only_uint"; const ALL_PROCESSES_UINT_SCALAR = "telemetry.test.all_processes_uint"; const ALL_CHILD_PROCESSES_STRING_SCALAR = "telemetry.test.all_child_processes_string"; function run_child_test() { // Attempt to set some scalar values from the "content" process. // The next scalars are not allowed to be recorded in the content process. Telemetry.scalarSet(UINT_SCALAR, 1); Telemetry.keyedScalarSet(KEYED_UINT_SCALAR, "should-not-be-recorded", 1); // The next scalars shou be recorded in only the content process. Telemetry.scalarSet(CONTENT_ONLY_UINT_SCALAR, 37); Telemetry.scalarSet(ALL_CHILD_PROCESSES_STRING_SCALAR, "all-child-processes"); // The next scalar will be recorded in the parent and content processes. Telemetry.keyedScalarSet(KEYED_BOOL_SCALAR, "content-key", true); Telemetry.keyedScalarSet(KEYED_BOOL_SCALAR, "content-key2", false); Telemetry.scalarSet(ALL_PROCESSES_UINT_SCALAR, 37); } function setParentScalars() { // The following scalars are not allowed to be recorded in the parent process. Telemetry.scalarSet(CONTENT_ONLY_UINT_SCALAR, 15); Telemetry.scalarSet(ALL_CHILD_PROCESSES_STRING_SCALAR, "all-child-processes"); // The next ones will be recorded only in the parent. Telemetry.scalarSet(UINT_SCALAR, 15); // This last batch will be available both in the parent and child processes. Telemetry.keyedScalarSet(KEYED_BOOL_SCALAR, "parent-key", false); Telemetry.scalarSet(ALL_PROCESSES_UINT_SCALAR, 37); } function checkParentScalars(processData) { const scalars = processData.scalars; const keyedScalars = processData.keyedScalars; // Check the plain scalars, make sure we're only recording what we expect. Assert.ok( !(CONTENT_ONLY_UINT_SCALAR in scalars), "Scalars must not be recorded in other processes unless allowed." ); Assert.ok( !(ALL_CHILD_PROCESSES_STRING_SCALAR in scalars), "Scalars must not be recorded in other processes unless allowed." ); Assert.ok( UINT_SCALAR in scalars, `${UINT_SCALAR} must be recorded in the parent process.` ); Assert.equal( scalars[UINT_SCALAR], 15, `${UINT_SCALAR} must have the correct value (parent process).` ); Assert.ok( ALL_PROCESSES_UINT_SCALAR in scalars, `${ALL_PROCESSES_UINT_SCALAR} must be recorded in the parent process.` ); Assert.equal( scalars[ALL_PROCESSES_UINT_SCALAR], 37, `${ALL_PROCESSES_UINT_SCALAR} must have the correct value (parent process).` ); // Now check the keyed scalars. Assert.ok( KEYED_BOOL_SCALAR in keyedScalars, `${KEYED_BOOL_SCALAR} must be recorded in the parent process.` ); Assert.ok( "parent-key" in keyedScalars[KEYED_BOOL_SCALAR], `${KEYED_BOOL_SCALAR} must be recorded in the parent process.` ); Assert.equal( Object.keys(keyedScalars[KEYED_BOOL_SCALAR]).length, 1, `${KEYED_BOOL_SCALAR} must only contain the expected key in parent process.` ); Assert.equal( keyedScalars[KEYED_BOOL_SCALAR]["parent-key"], false, `${KEYED_BOOL_SCALAR} must have the correct value (parent process).` ); } function checkContentScalars(processData) { const scalars = processData.scalars; const keyedScalars = processData.keyedScalars; // Check the plain scalars for the content process. Assert.ok( !(UINT_SCALAR in scalars), "Scalars must not be recorded in other processes unless allowed." ); Assert.ok( !(KEYED_UINT_SCALAR in keyedScalars), "Keyed scalars must not be recorded in other processes unless allowed." ); Assert.ok( CONTENT_ONLY_UINT_SCALAR in scalars, `${CONTENT_ONLY_UINT_SCALAR} must be recorded in the content process.` ); Assert.equal( scalars[CONTENT_ONLY_UINT_SCALAR], 37, `${CONTENT_ONLY_UINT_SCALAR} must have the correct value (content process).` ); Assert.ok( ALL_CHILD_PROCESSES_STRING_SCALAR in scalars, `${ALL_CHILD_PROCESSES_STRING_SCALAR} must be recorded in the content process.` ); Assert.equal( scalars[ALL_CHILD_PROCESSES_STRING_SCALAR], "all-child-processes", `${ALL_CHILD_PROCESSES_STRING_SCALAR} must have the correct value (content process).` ); Assert.ok( ALL_PROCESSES_UINT_SCALAR in scalars, `${ALL_PROCESSES_UINT_SCALAR} must be recorded in the content process.` ); Assert.equal( scalars[ALL_PROCESSES_UINT_SCALAR], 37, `${ALL_PROCESSES_UINT_SCALAR} must have the correct value (content process).` ); // Check the keyed scalars. Assert.ok( KEYED_BOOL_SCALAR in keyedScalars, `${KEYED_BOOL_SCALAR} must be recorded in the content process.` ); Assert.ok( "content-key" in keyedScalars[KEYED_BOOL_SCALAR], `${KEYED_BOOL_SCALAR} must be recorded in the content process.` ); Assert.ok( "content-key2" in keyedScalars[KEYED_BOOL_SCALAR], `${KEYED_BOOL_SCALAR} must be recorded in the content process.` ); Assert.equal( keyedScalars[KEYED_BOOL_SCALAR]["content-key"], true, `${KEYED_BOOL_SCALAR} must have the correct value (content process).` ); Assert.equal( keyedScalars[KEYED_BOOL_SCALAR]["content-key2"], false, `${KEYED_BOOL_SCALAR} must have the correct value (content process).` ); Assert.equal( Object.keys(keyedScalars[KEYED_BOOL_SCALAR]).length, 2, `${KEYED_BOOL_SCALAR} must contain the expected keys in content process.` ); } /** * This function waits until content scalars are reported into the * scalar snapshot. */ async function waitForContentScalars() { await ContentTaskUtils.waitForCondition(() => { const scalars = Telemetry.getSnapshotForScalars("main", false); return Object.keys(scalars).includes("content"); }); } add_task(async function () { if (!runningInParent) { TelemetryController.testSetupContent(); run_child_test(); do_send_remote_message(MESSAGE_CHILD_TEST_DONE); return; } // Setup. do_get_profile(true); await loadAddonManager(APP_ID, APP_NAME, APP_VERSION, PLATFORM_VERSION); finishAddonManagerStartup(); fakeIntlReady(); await TelemetryController.testSetup(); if (runningInParent) { setParentScalars(); // Make sure we don't generate unexpected pings due to pref changes. await setEmptyPrefWatchlist(); } // Run test in child, don't wait for it to finish: just wait for the // MESSAGE_CHILD_TEST_DONE. run_test_in_child("test_ChildScalars.js"); await do_await_remote_message(MESSAGE_CHILD_TEST_DONE); // Once scalars are set by the content process, they don't immediately get // sent to the parent process. Wait for the Telemetry IPC Timer to trigger // and batch send the data back to the parent process. await waitForContentScalars(); // Get an "environment-changed" ping rather than a "test-ping", as // scalar measurements are only supported in subsession pings. const payload = TelemetrySession.getPayload("environment-change"); // Validate the scalar data. Assert.ok("processes" in payload, "Should have processes section"); Assert.ok( "content" in payload.processes, "Should have child process section" ); Assert.ok( "scalars" in payload.processes.content, "Child process section should have scalars." ); Assert.ok( "keyedScalars" in payload.processes.content, "Child process section should have keyed scalars." ); checkParentScalars(payload.processes.parent); checkContentScalars(payload.processes.content); do_test_finished(); });