diff options
Diffstat (limited to 'toolkit/components/extensions/parent/ext-telemetry.js')
-rw-r--r-- | toolkit/components/extensions/parent/ext-telemetry.js | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/toolkit/components/extensions/parent/ext-telemetry.js b/toolkit/components/extensions/parent/ext-telemetry.js new file mode 100644 index 0000000000..cff568a038 --- /dev/null +++ b/toolkit/components/extensions/parent/ext-telemetry.js @@ -0,0 +1,195 @@ +/* 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"; + +ChromeUtils.defineESModuleGetters(this, { + TelemetryController: "resource://gre/modules/TelemetryController.sys.mjs", + TelemetryUtils: "resource://gre/modules/TelemetryUtils.sys.mjs", +}); + +const SCALAR_TYPES = { + count: Ci.nsITelemetry.SCALAR_TYPE_COUNT, + string: Ci.nsITelemetry.SCALAR_TYPE_STRING, + boolean: Ci.nsITelemetry.SCALAR_TYPE_BOOLEAN, +}; + +// Currently unsupported on Android: blocked on 1220177. +// See 1280234 c67 for discussion. +function desktopCheck() { + if (AppConstants.MOZ_BUILD_APP !== "browser") { + throw new ExtensionUtils.ExtensionError( + "This API is only supported on desktop" + ); + } +} + +this.telemetry = class extends ExtensionAPI { + getAPI(context) { + let { extension } = context; + return { + telemetry: { + submitPing(type, payload, options) { + desktopCheck(); + const manifest = extension.manifest; + if (manifest.telemetry) { + throw new ExtensionUtils.ExtensionError( + "Encryption settings are defined, use submitEncryptedPing instead." + ); + } + + try { + TelemetryController.submitExternalPing(type, payload, options); + } catch (ex) { + throw new ExtensionUtils.ExtensionError(ex); + } + }, + submitEncryptedPing(payload, options) { + desktopCheck(); + + const manifest = extension.manifest; + if (!manifest.telemetry) { + throw new ExtensionUtils.ExtensionError( + "Encrypted telemetry pings require ping_type and public_key to be set in manifest." + ); + } + + if (!(options.schemaName && options.schemaVersion)) { + throw new ExtensionUtils.ExtensionError( + "Encrypted telemetry pings require schema name and version to be set in options object." + ); + } + + try { + const type = manifest.telemetry.ping_type; + + // Optional manifest entries. + if (manifest.telemetry.study_name) { + options.studyName = manifest.telemetry.study_name; + } + options.addPioneerId = manifest.telemetry.pioneer_id === true; + + // Required manifest entries. + options.useEncryption = true; + options.publicKey = manifest.telemetry.public_key.key; + options.encryptionKeyId = manifest.telemetry.public_key.id; + options.schemaNamespace = manifest.telemetry.schemaNamespace; + + TelemetryController.submitExternalPing(type, payload, options); + } catch (ex) { + throw new ExtensionUtils.ExtensionError(ex); + } + }, + canUpload() { + desktopCheck(); + // Note: remove the ternary and direct pref check when + // TelemetryController.canUpload() is implemented (bug 1440089). + try { + const result = + "canUpload" in TelemetryController + ? TelemetryController.canUpload() + : Services.prefs.getBoolPref( + TelemetryUtils.Preferences.FhrUploadEnabled, + false + ); + return result; + } catch (ex) { + throw new ExtensionUtils.ExtensionError(ex); + } + }, + scalarAdd(name, value) { + desktopCheck(); + try { + Services.telemetry.scalarAdd(name, value); + } catch (ex) { + throw new ExtensionUtils.ExtensionError(ex); + } + }, + scalarSet(name, value) { + desktopCheck(); + try { + Services.telemetry.scalarSet(name, value); + } catch (ex) { + throw new ExtensionUtils.ExtensionError(ex); + } + }, + scalarSetMaximum(name, value) { + desktopCheck(); + try { + Services.telemetry.scalarSetMaximum(name, value); + } catch (ex) { + throw new ExtensionUtils.ExtensionError(ex); + } + }, + keyedScalarAdd(name, key, value) { + desktopCheck(); + try { + Services.telemetry.keyedScalarAdd(name, key, value); + } catch (ex) { + throw new ExtensionUtils.ExtensionError(ex); + } + }, + keyedScalarSet(name, key, value) { + desktopCheck(); + try { + Services.telemetry.keyedScalarSet(name, key, value); + } catch (ex) { + throw new ExtensionUtils.ExtensionError(ex); + } + }, + keyedScalarSetMaximum(name, key, value) { + desktopCheck(); + try { + Services.telemetry.keyedScalarSetMaximum(name, key, value); + } catch (ex) { + throw new ExtensionUtils.ExtensionError(ex); + } + }, + recordEvent(category, method, object, value, extra) { + desktopCheck(); + try { + Services.telemetry.recordEvent( + category, + method, + object, + value, + extra + ); + } catch (ex) { + throw new ExtensionUtils.ExtensionError(ex); + } + }, + registerScalars(category, data) { + desktopCheck(); + try { + // For each scalar in `data`, replace scalar.kind with + // the appropriate nsITelemetry constant. + Object.keys(data).forEach(scalar => { + data[scalar].kind = SCALAR_TYPES[data[scalar].kind]; + }); + Services.telemetry.registerScalars(category, data); + } catch (ex) { + throw new ExtensionUtils.ExtensionError(ex); + } + }, + setEventRecordingEnabled(category, enabled) { + desktopCheck(); + try { + Services.telemetry.setEventRecordingEnabled(category, enabled); + } catch (ex) { + throw new ExtensionUtils.ExtensionError(ex); + } + }, + registerEvents(category, data) { + desktopCheck(); + try { + Services.telemetry.registerEvents(category, data); + } catch (ex) { + throw new ExtensionUtils.ExtensionError(ex); + } + }, + }, + }; + } +}; |