/* 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 { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs"; const lazy = {}; ChromeUtils.defineModuleGetter( lazy, "PingCentre", "resource:///modules/PingCentre.jsm" ); ChromeUtils.defineESModuleGetters(lazy, { pktApi: "chrome://pocket/content/pktApi.sys.mjs", TelemetryEnvironment: "resource://gre/modules/TelemetryEnvironment.sys.mjs", }); // List of namespaces for the structured ingestion system. // They are defined in https://github.com/mozilla-services/mozilla-pipeline-schemas const STRUCTURED_INGESTION_NAMESPACE_AS = "activity-stream"; const STRUCTURED_INGESTION_ENDPOINT_PREF = "browser.newtabpage.activity-stream.telemetry.structuredIngestion.endpoint"; // This is the topic for telemetry pings, used inside PingCentre. const POCKET_TELEMETRY_TOPIC = "pocket"; const PREF_IMPRESSION_ID = "browser.newtabpage.activity-stream.impressionId"; XPCOMUtils.defineLazyGetter(lazy, "pingCentre", () => { return new lazy.PingCentre({ topic: POCKET_TELEMETRY_TOPIC }); }); export var pktTelemetry = { get structuredIngestionEndpointBase() { if (!this._structuredIngestionEndpointBase) { this._structuredIngestionEndpointBase = Services.prefs.getStringPref( STRUCTURED_INGESTION_ENDPOINT_PREF, "" ); } return this._structuredIngestionEndpointBase; }, get impressionId() { if (!this._impressionId) { this._impressionId = this.getOrCreateImpressionId(); } return this._impressionId; }, // Sets or gets the impression id that's use for Pocket impressions. // The impression id cannot be tied to a client id. // This is the same impression id used in newtab pocket impressions. getOrCreateImpressionId() { let impressionId = Services.prefs.getStringPref(PREF_IMPRESSION_ID, ""); if (!impressionId) { impressionId = String(Services.uuid.generateUUID()); Services.prefs.setStringPref(PREF_IMPRESSION_ID, impressionId); } return impressionId; }, /** * createPingPayload - Create a ping for an impression stats * * @param {ob} data The data object to be included in the ping. * @return {obj} A telemetry ping */ createPingPayload(data) { // experiments, locale, version, and release_channel are provided by pingCentre. // model and events is provided in the data param. return { ...data, impression_id: this.impressionId, pocket_logged_in_status: lazy.pktApi.isUserLoggedIn(), profile_creation_date: this._profileCreationDate(), }; }, _profileCreationDate() { return ( lazy.TelemetryEnvironment.currentEnvironment.profile.resetDate || lazy.TelemetryEnvironment.currentEnvironment.profile.creationDate ); }, _generateUUID() { return String(Services.uuid.generateUUID()); }, /** * Generates an endpoint for Structured Ingestion telemetry pipeline. Note that * Structured Ingestion requires a different endpoint for each ping. See more * details about endpoint schema at: * https://github.com/mozilla/gcp-ingestion/blob/master/docs/edge.md#postput-request */ _generateStructuredIngestionEndpoint() { const uuid = this._generateUUID(); // Structured Ingestion does not support the UUID generated by gUUIDGenerator, // because it contains leading and trailing braces. Need to trim them first. const docID = uuid.slice(1, -1); const extension = `${STRUCTURED_INGESTION_NAMESPACE_AS}/pocket-button/1/${docID}`; return `${this.structuredIngestionEndpointBase}/${extension}`; }, /** * sendStructuredIngestionEvent - Sent a ping for an impression stats * * @param {ob} eventObject The data object to be included in the ping. */ sendStructuredIngestionEvent(eventObject) { lazy.pingCentre.sendStructuredIngestionPing( eventObject, this._generateStructuredIngestionEndpoint(), STRUCTURED_INGESTION_NAMESPACE_AS ); }, };