summaryrefslogtreecommitdiffstats
path: root/toolkit/mozapps/update/UpdateTelemetry.sys.mjs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--toolkit/mozapps/update/UpdateTelemetry.sys.mjs652
1 files changed, 652 insertions, 0 deletions
diff --git a/toolkit/mozapps/update/UpdateTelemetry.sys.mjs b/toolkit/mozapps/update/UpdateTelemetry.sys.mjs
new file mode 100644
index 0000000000..20fb0ab4a4
--- /dev/null
+++ b/toolkit/mozapps/update/UpdateTelemetry.sys.mjs
@@ -0,0 +1,652 @@
+/* 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 { AppConstants } from "resource://gre/modules/AppConstants.sys.mjs";
+
+import {
+ BitsError,
+ BitsUnknownError,
+} from "resource://gre/modules/Bits.sys.mjs";
+
+export var AUSTLMY = {
+ // Telemetry for the application update background update check occurs when
+ // the background update timer fires after the update interval which is
+ // determined by the app.update.interval preference and its telemetry
+ // histogram IDs have the suffix '_NOTIFY'.
+ // Telemetry for the externally initiated background update check occurs when
+ // a call is made to |checkForBackgroundUpdates| which is typically initiated
+ // by an application when it has determined that the application should have
+ // received an update. This has separate telemetry so it is possible to
+ // analyze using the telemetry data systems that have not been updating when
+ // they should have.
+
+ // The update check was performed by the call to checkForBackgroundUpdates in
+ // nsUpdateService.js.
+ EXTERNAL: "EXTERNAL",
+ // The update check was performed by the call to notify in nsUpdateService.js.
+ NOTIFY: "NOTIFY",
+ // The update check was performed after an update is already ready. There is
+ // currently no way for a user to initiate an update check when there is a
+ // ready update (the UI just prompts you to install the ready update). So
+ // subsequent update checks are necessarily "notify" update checks, not
+ // "external" ones.
+ SUBSEQUENT: "SUBSEQUENT",
+
+ /**
+ * Values for the UPDATE_CHECK_CODE_NOTIFY and UPDATE_CHECK_CODE_EXTERNAL
+ * Telemetry histograms.
+ */
+ // No update found (no notification)
+ CHK_NO_UPDATE_FOUND: 0,
+ // Update will be downloaded in the background (background download)
+ CHK_DOWNLOAD_UPDATE: 1,
+ // Showing prompt due to preference (update notification)
+ CHK_SHOWPROMPT_PREF: 3,
+ // Already has an active update in progress (no notification)
+ CHK_HAS_ACTIVEUPDATE: 8,
+ // A background download is already in progress (no notification)
+ CHK_IS_DOWNLOADING: 9,
+ // An update is already staged (no notification)
+ CHK_IS_STAGED: 10,
+ // An update is already downloaded (no notification)
+ CHK_IS_DOWNLOADED: 11,
+ // Note: codes 12-13 were removed along with the |app.update.enabled| pref.
+ // Unable to check for updates per hasUpdateMutex() (no notification)
+ CHK_NO_MUTEX: 14,
+ // Unable to check for updates per gCanCheckForUpdates (no notification). This
+ // should be covered by other codes and is recorded just in case.
+ CHK_UNABLE_TO_CHECK: 15,
+ // Note: code 16 was removed when the feature for disabling updates for the
+ // session was removed.
+ // Unable to perform a background check while offline (no notification)
+ CHK_OFFLINE: 17,
+ // Note: codes 18 - 21 were removed along with the certificate checking code.
+ // General update check failure and threshold reached
+ // (check failure notification)
+ CHK_GENERAL_ERROR_PROMPT: 22,
+ // General update check failure and threshold not reached (no notification)
+ CHK_GENERAL_ERROR_SILENT: 23,
+ // No compatible update found though there were updates (no notification)
+ CHK_NO_COMPAT_UPDATE_FOUND: 24,
+ // Update found for a previous version (no notification)
+ CHK_UPDATE_PREVIOUS_VERSION: 25,
+ // Update found without a type attribute (no notification)
+ CHK_UPDATE_INVALID_TYPE: 27,
+ // The system is no longer supported (system unsupported notification)
+ CHK_UNSUPPORTED: 28,
+ // Unable to apply updates (manual install to update notification)
+ CHK_UNABLE_TO_APPLY: 29,
+ // Unable to check for updates due to no OS version (no notification)
+ CHK_NO_OS_VERSION: 30,
+ // Unable to check for updates due to no OS ABI (no notification)
+ CHK_NO_OS_ABI: 31,
+ // Invalid update url (no notification)
+ CHK_INVALID_DEFAULT_URL: 32,
+ // Update elevation failures or cancelations threshold reached for this
+ // version, OSX only (no notification)
+ CHK_ELEVATION_DISABLED_FOR_VERSION: 35,
+ // User opted out of elevated updates for the available update version, OSX
+ // only (no notification)
+ CHK_ELEVATION_OPTOUT_FOR_VERSION: 36,
+ // Update checks disabled by enterprise policy
+ CHK_DISABLED_BY_POLICY: 37,
+ // Update check failed due to write error
+ CHK_ERR_WRITE_FAILURE: 38,
+ // Update check was delayed because another instance of the application is
+ // currently running
+ CHK_OTHER_INSTANCE: 39,
+ // Cannot yet download update because no partial patch is available and an
+ // update has already been downloaded.
+ CHK_NO_PARTIAL_PATCH: 40,
+
+ /**
+ * Submit a telemetry ping for the update check result code or a telemetry
+ * ping for a count type histogram count when no update was found. The no
+ * update found ping is separate since it is the typical result, is less
+ * interesting than the other result codes, and it is easier to analyze the
+ * other codes without including it.
+ *
+ * @param aSuffix
+ * The histogram id suffix for histogram IDs:
+ * UPDATE_CHECK_CODE_EXTERNAL
+ * UPDATE_CHECK_CODE_NOTIFY
+ * UPDATE_CHECK_CODE_SUBSEQUENT
+ * UPDATE_CHECK_NO_UPDATE_EXTERNAL
+ * UPDATE_CHECK_NO_UPDATE_NOTIFY
+ * UPDATE_CHECK_NO_UPDATE_SUBSEQUENT
+ * @param aCode
+ * An integer value as defined by the values that start with CHK_ in
+ * the above section.
+ */
+ pingCheckCode: function UT_pingCheckCode(aSuffix, aCode) {
+ try {
+ if (aCode == this.CHK_NO_UPDATE_FOUND) {
+ let id = "UPDATE_CHECK_NO_UPDATE_" + aSuffix;
+ // count type histogram
+ Services.telemetry.getHistogramById(id).add();
+ } else {
+ let id = "UPDATE_CHECK_CODE_" + aSuffix;
+ // enumerated type histogram
+ Services.telemetry.getHistogramById(id).add(aCode);
+ }
+ } catch (e) {
+ console.error(e);
+ }
+ },
+
+ /**
+ * Submit a telemetry ping for a failed update check's unhandled error code
+ * when the pingCheckCode is CHK_GENERAL_ERROR_SILENT. The histogram is a
+ * keyed count type with key names that are prefixed with 'AUS_CHECK_EX_ERR_'.
+ *
+ * @param aSuffix
+ * The histogram id suffix for histogram IDs:
+ * UPDATE_CHECK_EXTENDED_ERROR_EXTERNAL
+ * UPDATE_CHECK_EXTENDED_ERROR_NOTIFY
+ * UPDATE_CHECK_EXTENDED_ERROR_SUBSEQUENT
+ * @param aCode
+ * The extended error value return by a failed update check.
+ */
+ pingCheckExError: function UT_pingCheckExError(aSuffix, aCode) {
+ try {
+ let id = "UPDATE_CHECK_EXTENDED_ERROR_" + aSuffix;
+ let val = "AUS_CHECK_EX_ERR_" + aCode;
+ // keyed count type histogram
+ Services.telemetry.getKeyedHistogramById(id).add(val);
+ } catch (e) {
+ console.error(e);
+ }
+ },
+
+ // The state code and if present the status error code were read on startup.
+ STARTUP: "STARTUP",
+ // The state code and status error code if present were read after staging.
+ STAGE: "STAGE",
+
+ // Patch type Complete
+ PATCH_COMPLETE: "COMPLETE",
+ // Patch type partial
+ PATCH_PARTIAL: "PARTIAL",
+ // Patch type unknown
+ PATCH_UNKNOWN: "UNKNOWN",
+
+ /**
+ * Values for the UPDATE_DOWNLOAD_CODE_COMPLETE, UPDATE_DOWNLOAD_CODE_PARTIAL,
+ * and UPDATE_DOWNLOAD_CODE_UNKNOWN Telemetry histograms.
+ */
+ DWNLD_SUCCESS: 0,
+ DWNLD_RETRY_OFFLINE: 1,
+ DWNLD_RETRY_NET_TIMEOUT: 2,
+ DWNLD_RETRY_CONNECTION_REFUSED: 3,
+ DWNLD_RETRY_NET_RESET: 4,
+ DWNLD_ERR_NO_UPDATE: 5,
+ DWNLD_ERR_NO_UPDATE_PATCH: 6,
+ DWNLD_ERR_PATCH_SIZE_LARGER: 8,
+ DWNLD_ERR_PATCH_SIZE_NOT_EQUAL: 9,
+ DWNLD_ERR_BINDING_ABORTED: 10,
+ DWNLD_ERR_ABORT: 11,
+ DWNLD_ERR_DOCUMENT_NOT_CACHED: 12,
+ DWNLD_ERR_VERIFY_NO_REQUEST: 13,
+ DWNLD_ERR_VERIFY_PATCH_SIZE_NOT_EQUAL: 14,
+ DWNLD_ERR_WRITE_FAILURE: 15,
+ // Temporary failure code to see if there are failures without an update phase
+ DWNLD_UNKNOWN_PHASE_ERR_WRITE_FAILURE: 40,
+
+ /**
+ * Submit a telemetry ping for the update download result code.
+ *
+ * @param aIsComplete
+ * If true the histogram is for a patch type complete, if false the
+ * histogram is for a patch type partial, and when undefined the
+ * histogram is for an unknown patch type. This is used to determine
+ * the histogram ID out of the following histogram IDs:
+ * UPDATE_DOWNLOAD_CODE_COMPLETE
+ * UPDATE_DOWNLOAD_CODE_PARTIAL
+ * UPDATE_DOWNLOAD_CODE_UNKNOWN
+ * @param aCode
+ * An integer value as defined by the values that start with DWNLD_ in
+ * the above section.
+ */
+ pingDownloadCode: function UT_pingDownloadCode(aIsComplete, aCode) {
+ let patchType = this.PATCH_UNKNOWN;
+ if (aIsComplete === true) {
+ patchType = this.PATCH_COMPLETE;
+ } else if (aIsComplete === false) {
+ patchType = this.PATCH_PARTIAL;
+ }
+ try {
+ let id = "UPDATE_DOWNLOAD_CODE_" + patchType;
+ // enumerated type histogram
+ Services.telemetry.getHistogramById(id).add(aCode);
+ } catch (e) {
+ console.error(e);
+ }
+ },
+
+ // Previous state codes are defined in pingStateAndStatusCodes() in
+ // nsUpdateService.js
+ STATE_WRITE_FAILURE: 14,
+
+ /**
+ * Submit a telemetry ping for the update status state code.
+ *
+ * @param aSuffix
+ * The histogram id suffix for histogram IDs:
+ * UPDATE_STATE_CODE_COMPLETE_STARTUP
+ * UPDATE_STATE_CODE_PARTIAL_STARTUP
+ * UPDATE_STATE_CODE_UNKNOWN_STARTUP
+ * UPDATE_STATE_CODE_COMPLETE_STAGE
+ * UPDATE_STATE_CODE_PARTIAL_STAGE
+ * UPDATE_STATE_CODE_UNKNOWN_STAGE
+ * @param aCode
+ * An integer value as defined by the values that start with STATE_ in
+ * the above section for the update state from the update.status file.
+ */
+ pingStateCode: function UT_pingStateCode(aSuffix, aCode) {
+ try {
+ let id = "UPDATE_STATE_CODE_" + aSuffix;
+ // enumerated type histogram
+ Services.telemetry.getHistogramById(id).add(aCode);
+ } catch (e) {
+ console.error(e);
+ }
+ },
+
+ /**
+ * Submit a telemetry ping for the update status error code. This does not
+ * submit a success value which can be determined from the state code.
+ *
+ * @param aSuffix
+ * The histogram id suffix for histogram IDs:
+ * UPDATE_STATUS_ERROR_CODE_COMPLETE_STARTUP
+ * UPDATE_STATUS_ERROR_CODE_PARTIAL_STARTUP
+ * UPDATE_STATUS_ERROR_CODE_UNKNOWN_STARTUP
+ * UPDATE_STATUS_ERROR_CODE_COMPLETE_STAGE
+ * UPDATE_STATUS_ERROR_CODE_PARTIAL_STAGE
+ * UPDATE_STATUS_ERROR_CODE_UNKNOWN_STAGE
+ * @param aCode
+ * An integer value for the error code from the update.status file.
+ */
+ pingStatusErrorCode: function UT_pingStatusErrorCode(aSuffix, aCode) {
+ try {
+ let id = "UPDATE_STATUS_ERROR_CODE_" + aSuffix;
+ // enumerated type histogram
+ Services.telemetry.getHistogramById(id).add(aCode);
+ } catch (e) {
+ console.error(e);
+ }
+ },
+
+ /**
+ * Submit a telemetry ping for a failing binary transparency result.
+ *
+ * @param aSuffix
+ * Key to use on the update.binarytransparencyresult collection.
+ * Must be one of "COMPLETE_STARTUP", "PARTIAL_STARTUP",
+ * "UNKNOWN_STARTUP", "COMPLETE_STAGE", "PARTIAL_STAGE",
+ * "UNKNOWN_STAGE".
+ * @param aCode
+ * An integer value for the error code from the update.bt file.
+ */
+ pingBinaryTransparencyResult: function UT_pingBinaryTransparencyResult(
+ aSuffix,
+ aCode
+ ) {
+ try {
+ let id = "update.binarytransparencyresult";
+ let key = aSuffix.toLowerCase().replace("_", "-");
+ Services.telemetry.keyedScalarSet(id, key, aCode);
+ } catch (e) {
+ console.error(e);
+ }
+ },
+
+ /**
+ * Records a failed BITS update download using Telemetry.
+ * In addition to the BITS Result histogram, this also sends an
+ * update.bitshresult scalar value.
+ *
+ * @param aIsComplete
+ * If true the histogram is for a patch type complete, if false the
+ * histogram is for a patch type partial. This will determine the
+ * histogram id out of the following histogram ids:
+ * UPDATE_BITS_RESULT_COMPLETE
+ * UPDATE_BITS_RESULT_PARTIAL
+ * This value is also used to determine the key for the keyed scalar
+ * update.bitshresult (key is either "COMPLETE" or "PARTIAL")
+ * @param aError
+ * The BitsError that occurred. See Bits.jsm for details on BitsError.
+ */
+ pingBitsError: function UT_pingBitsError(aIsComplete, aError) {
+ if (AppConstants.platform != "win") {
+ console.error(
+ "Warning: Attempted to submit BITS telemetry on a " +
+ "non-Windows platform"
+ );
+ return;
+ }
+ if (!(aError instanceof BitsError)) {
+ console.error("Error sending BITS Error ping: Error is not a BitsError");
+ aError = new BitsUnknownError();
+ }
+ // Coerce the error to integer
+ let type = +aError.type;
+ if (isNaN(type)) {
+ console.error(
+ "Error sending BITS Error ping: Either error is not a " +
+ "BitsError, or error type is not an integer."
+ );
+ type = Ci.nsIBits.ERROR_TYPE_UNKNOWN;
+ } else if (type == Ci.nsIBits.ERROR_TYPE_SUCCESS) {
+ console.error(
+ "Error sending BITS Error ping: The error type must not " +
+ "be the success type."
+ );
+ type = Ci.nsIBits.ERROR_TYPE_UNKNOWN;
+ }
+ this._pingBitsResult(aIsComplete, type);
+
+ if (aError.codeType == Ci.nsIBits.ERROR_CODE_TYPE_HRESULT) {
+ let scalarKey;
+ if (aIsComplete) {
+ scalarKey = this.PATCH_COMPLETE;
+ } else {
+ scalarKey = this.PATCH_PARTIAL;
+ }
+ try {
+ Services.telemetry.keyedScalarSet(
+ "update.bitshresult",
+ scalarKey,
+ aError.code
+ );
+ } catch (e) {
+ console.error(e);
+ }
+ }
+ },
+
+ /**
+ * Records a successful BITS update download using Telemetry.
+ *
+ * @param aIsComplete
+ * If true the histogram is for a patch type complete, if false the
+ * histogram is for a patch type partial. This will determine the
+ * histogram id out of the following histogram ids:
+ * UPDATE_BITS_RESULT_COMPLETE
+ * UPDATE_BITS_RESULT_PARTIAL
+ */
+ pingBitsSuccess: function UT_pingBitsSuccess(aIsComplete) {
+ if (AppConstants.platform != "win") {
+ console.error(
+ "Warning: Attempted to submit BITS telemetry on a " +
+ "non-Windows platform"
+ );
+ return;
+ }
+ this._pingBitsResult(aIsComplete, Ci.nsIBits.ERROR_TYPE_SUCCESS);
+ },
+
+ /**
+ * This is the helper function that does all the work for pingBitsError and
+ * pingBitsSuccess. It submits a telemetry ping indicating the result of the
+ * BITS update download.
+ *
+ * @param aIsComplete
+ * If true the histogram is for a patch type complete, if false the
+ * histogram is for a patch type partial. This will determine the
+ * histogram id out of the following histogram ids:
+ * UPDATE_BITS_RESULT_COMPLETE
+ * UPDATE_BITS_RESULT_PARTIAL
+ * @param aResultType
+ * The result code. This will be one of the ERROR_TYPE_* values defined
+ * in the nsIBits interface.
+ */
+ _pingBitsResult: function UT_pingBitsResult(aIsComplete, aResultType) {
+ let patchType;
+ if (aIsComplete) {
+ patchType = this.PATCH_COMPLETE;
+ } else {
+ patchType = this.PATCH_PARTIAL;
+ }
+ try {
+ let id = "UPDATE_BITS_RESULT_" + patchType;
+ Services.telemetry.getHistogramById(id).add(aResultType);
+ } catch (e) {
+ console.error(e);
+ }
+ },
+
+ /**
+ * Submit the interval in days since the last notification for this background
+ * update check or a boolean if the last notification is in the future.
+ *
+ * @param aSuffix
+ * The histogram id suffix for histogram IDs:
+ * UPDATE_INVALID_LASTUPDATETIME_EXTERNAL
+ * UPDATE_INVALID_LASTUPDATETIME_NOTIFY
+ * UPDATE_INVALID_LASTUPDATETIME_SUBSEQUENT
+ * UPDATE_LAST_NOTIFY_INTERVAL_DAYS_EXTERNAL
+ * UPDATE_LAST_NOTIFY_INTERVAL_DAYS_NOTIFY
+ * UPDATE_LAST_NOTIFY_INTERVAL_DAYS_SUBSEQUENT
+ */
+ pingLastUpdateTime: function UT_pingLastUpdateTime(aSuffix) {
+ const PREF_APP_UPDATE_LASTUPDATETIME =
+ "app.update.lastUpdateTime.background-update-timer";
+ if (Services.prefs.prefHasUserValue(PREF_APP_UPDATE_LASTUPDATETIME)) {
+ let lastUpdateTimeSeconds = Services.prefs.getIntPref(
+ PREF_APP_UPDATE_LASTUPDATETIME
+ );
+ if (lastUpdateTimeSeconds) {
+ let currentTimeSeconds = Math.round(Date.now() / 1000);
+ if (lastUpdateTimeSeconds > currentTimeSeconds) {
+ try {
+ let id = "UPDATE_INVALID_LASTUPDATETIME_" + aSuffix;
+ // count type histogram
+ Services.telemetry.getHistogramById(id).add();
+ } catch (e) {
+ console.error(e);
+ }
+ } else {
+ let intervalDays =
+ (currentTimeSeconds - lastUpdateTimeSeconds) / (60 * 60 * 24);
+ try {
+ let id = "UPDATE_LAST_NOTIFY_INTERVAL_DAYS_" + aSuffix;
+ // exponential type histogram
+ Services.telemetry.getHistogramById(id).add(intervalDays);
+ } catch (e) {
+ console.error(e);
+ }
+ }
+ }
+ }
+ },
+
+ /**
+ * Submit a telemetry ping for a boolean type histogram that indicates if the
+ * service is installed and a telemetry ping for a boolean type histogram that
+ * indicates if the service was at some point installed and is now
+ * uninstalled.
+ *
+ * @param aSuffix
+ * The histogram id suffix for histogram IDs:
+ * UPDATE_SERVICE_INSTALLED_EXTERNAL
+ * UPDATE_SERVICE_INSTALLED_NOTIFY
+ * UPDATE_SERVICE_INSTALLED_SUBSEQUENT
+ * UPDATE_SERVICE_MANUALLY_UNINSTALLED_EXTERNAL
+ * UPDATE_SERVICE_MANUALLY_UNINSTALLED_NOTIFY
+ * UPDATE_SERVICE_MANUALLY_UNINSTALLED_SUBSEQUENT
+ * @param aInstalled
+ * Whether the service is installed.
+ */
+ pingServiceInstallStatus: function UT_PSIS(aSuffix, aInstalled) {
+ // Report the error but don't throw since it is more important to
+ // successfully update than to throw.
+ if (!("@mozilla.org/windows-registry-key;1" in Cc)) {
+ console.error(Cr.NS_ERROR_NOT_AVAILABLE);
+ return;
+ }
+
+ try {
+ let id = "UPDATE_SERVICE_INSTALLED_" + aSuffix;
+ // boolean type histogram
+ Services.telemetry.getHistogramById(id).add(aInstalled);
+ } catch (e) {
+ console.error(e);
+ }
+
+ let attempted = 0;
+ try {
+ let wrk = Cc["@mozilla.org/windows-registry-key;1"].createInstance(
+ Ci.nsIWindowsRegKey
+ );
+ wrk.open(
+ wrk.ROOT_KEY_LOCAL_MACHINE,
+ "SOFTWARE\\Mozilla\\MaintenanceService",
+ wrk.ACCESS_READ | wrk.WOW64_64
+ );
+ // Was the service at some point installed, but is now uninstalled?
+ attempted = wrk.readIntValue("Attempted");
+ wrk.close();
+ } catch (e) {
+ // Since this will throw if the registry key doesn't exist (e.g. the
+ // service has never been installed) don't report an error.
+ }
+
+ try {
+ let id = "UPDATE_SERVICE_MANUALLY_UNINSTALLED_" + aSuffix;
+ if (!aInstalled && attempted) {
+ // count type histogram
+ Services.telemetry.getHistogramById(id).add();
+ }
+ } catch (e) {
+ console.error(e);
+ }
+ },
+
+ /**
+ * Submit a telemetry ping for a count type histogram when the expected value
+ * does not equal the boolean value of a pref or if the pref isn't present
+ * when the expected value does not equal default value. This lessens the
+ * amount of data submitted to telemetry.
+ *
+ * @param aID
+ * The histogram ID to report to.
+ * @param aPref
+ * The preference to check.
+ * @param aDefault
+ * The default value when the preference isn't present.
+ * @param aExpected (optional)
+ * If specified and the value is the same as the value that will be
+ * added the value won't be added to telemetry.
+ */
+ pingBoolPref: function UT_pingBoolPref(aID, aPref, aDefault, aExpected) {
+ try {
+ let val = aDefault;
+ if (Services.prefs.getPrefType(aPref) != Ci.nsIPrefBranch.PREF_INVALID) {
+ val = Services.prefs.getBoolPref(aPref);
+ }
+ if (val != aExpected) {
+ // count type histogram
+ Services.telemetry.getHistogramById(aID).add();
+ }
+ } catch (e) {
+ console.error(e);
+ }
+ },
+
+ /**
+ * Submit a telemetry ping for a histogram with the integer value of a
+ * preference when it is not the expected value or the default value when it
+ * is not the expected value. This lessens the amount of data submitted to
+ * telemetry.
+ *
+ * @param aID
+ * The histogram ID to report to.
+ * @param aPref
+ * The preference to check.
+ * @param aDefault
+ * The default value when the pref is not set.
+ * @param aExpected (optional)
+ * If specified and the value is the same as the value that will be
+ * added the value won't be added to telemetry.
+ */
+ pingIntPref: function UT_pingIntPref(aID, aPref, aDefault, aExpected) {
+ try {
+ let val = aDefault;
+ if (Services.prefs.getPrefType(aPref) != Ci.nsIPrefBranch.PREF_INVALID) {
+ val = Services.prefs.getIntPref(aPref);
+ }
+ if (aExpected === undefined || val != aExpected) {
+ // enumerated or exponential type histogram
+ Services.telemetry.getHistogramById(aID).add(val);
+ }
+ } catch (e) {
+ console.error(e);
+ }
+ },
+
+ /**
+ * Submit a telemetry ping for all histogram types that take a single
+ * parameter to the telemetry add function and the count type histogram when
+ * the aExpected parameter is specified. If the aExpected parameter is
+ * specified and it equals the value specified by the aValue
+ * parameter the telemetry submission will be skipped.
+ *
+ * @param aID
+ * The histogram ID to report to.
+ * @param aValue
+ * The value to add when aExpected is not defined or the value to
+ * check if it is equal to when aExpected is defined.
+ * @param aExpected (optional)
+ * If specified and the value is the same as the value specified by
+ * aValue parameter the submission will be skipped.
+ */
+ pingGeneric: function UT_pingGeneric(aID, aValue, aExpected) {
+ try {
+ if (aExpected === undefined) {
+ Services.telemetry.getHistogramById(aID).add(aValue);
+ } else if (aValue != aExpected) {
+ // count type histogram
+ Services.telemetry.getHistogramById(aID).add();
+ }
+ } catch (e) {
+ console.error(e);
+ }
+ },
+
+ /**
+ * Valid keys for the update.moveresult scalar.
+ */
+ MOVE_RESULT_SUCCESS: "SUCCESS",
+ MOVE_RESULT_UNKNOWN_FAILURE: "UNKNOWN_FAILURE",
+
+ /**
+ * Reports the passed result of attempting to move the downloading update
+ * into the ready update directory.
+ */
+ pingMoveResult: function UT_pingMoveResult(aResult) {
+ Services.telemetry.keyedScalarAdd("update.move_result", aResult, 1);
+ },
+
+ pingSuppressPrompts: function UT_pingSuppressPrompts() {
+ try {
+ let val = Services.prefs.getBoolPref("app.update.suppressPrompts", false);
+ if (val === true) {
+ Services.telemetry.scalarSet("update.suppress_prompts", true);
+ }
+ } catch (e) {
+ console.error(e);
+ }
+ },
+
+ pingPinPolicy: function UT_pingPinPolicy(updatePin) {
+ try {
+ Services.telemetry.scalarSet("update.version_pin", updatePin);
+ } catch (e) {
+ console.error(e);
+ }
+ },
+};
+
+Object.freeze(AUSTLMY);