/* 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/. */ "use strict"; const EXPORTED_SYMBOLS = ["AboutWelcomeTelemetry"]; const { XPCOMUtils } = ChromeUtils.importESModule( "resource://gre/modules/XPCOMUtils.sys.mjs" ); const lazy = {}; ChromeUtils.defineESModuleGetters(lazy, { ClientID: "resource://gre/modules/ClientID.sys.mjs", TelemetrySession: "resource://gre/modules/TelemetrySession.sys.mjs", }); XPCOMUtils.defineLazyModuleGetters(lazy, { PingCentre: "resource:///modules/PingCentre.jsm", AttributionCode: "resource:///modules/AttributionCode.jsm", }); XPCOMUtils.defineLazyPreferenceGetter( lazy, "structuredIngestionEndpointBase", "browser.newtabpage.activity-stream.telemetry.structuredIngestion.endpoint", "" ); XPCOMUtils.defineLazyGetter(lazy, "telemetryClientId", () => lazy.ClientID.getClientID() ); XPCOMUtils.defineLazyGetter( lazy, "browserSessionId", () => lazy.TelemetrySession.getMetadata("").sessionId ); const TELEMETRY_TOPIC = "about:welcome"; const PING_TYPE = "onboarding"; const PING_VERSION = "1"; const STRUCTURED_INGESTION_NAMESPACE_MS = "messaging-system"; class AboutWelcomeTelemetry { constructor() { XPCOMUtils.defineLazyPreferenceGetter( this, "telemetryEnabled", "browser.newtabpage.activity-stream.telemetry", false ); } /** * Lazily initialize PingCentre for Activity Stream to send pings */ get pingCentre() { Object.defineProperty(this, "pingCentre", { value: new lazy.PingCentre({ topic: TELEMETRY_TOPIC }), }); return this.pingCentre; } _generateStructuredIngestionEndpoint() { const uuid = Services.uuid.generateUUID().toString(); // Structured Ingestion does not support the UUID generated by Services.uuid, // because it contains leading and trailing braces. Need to trim them first. const docID = uuid.slice(1, -1); const extension = `${STRUCTURED_INGESTION_NAMESPACE_MS}/${PING_TYPE}/${PING_VERSION}/${docID}`; return `${lazy.structuredIngestionEndpointBase}/${extension}`; } /** * Attach browser attribution data to a ping payload. * * It intentionally queries the *cached* attribution data other than calling * `getAttrDataAsync()` in order to minimize the overhead here. * For the same reason, we are not querying the attribution data from * `TelemetryEnvironment.currentEnvironment.settings`. * * In practice, it's very likely that the attribution data is already read * and cached at some point by `AboutWelcomeParent`, so it should be able to * read the cached results for the most if not all of the pings. */ _maybeAttachAttribution(ping) { const attribution = lazy.AttributionCode.getCachedAttributionData(); if (attribution && Object.keys(attribution).length) { ping.attribution = attribution; } return ping; } async _createPing(event) { if (event.event_context && typeof event.event_context === "object") { event.event_context = JSON.stringify(event.event_context); } let ping = { ...event, addon_version: Services.appinfo.appBuildID, locale: Services.locale.appLocaleAsBCP47, client_id: await lazy.telemetryClientId, browser_session_id: lazy.browserSessionId, }; return this._maybeAttachAttribution(ping); } async sendTelemetry(event) { if (!this.telemetryEnabled) { return; } const ping = await this._createPing(event); this.pingCentre.sendStructuredIngestionPing( ping, this._generateStructuredIngestionEndpoint() ); } }