Files
tubestation/toolkit/components/telemetry/hybrid-content/HybridContentTelemetry.jsm

123 lines
4.7 KiB
JavaScript

/* 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";
var EXPORTED_SYMBOLS = ["HybridContentTelemetry"];
ChromeUtils.import("resource://gre/modules/Log.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/TelemetryUtils.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
let HybridContentTelemetry = {
_logger: null,
_observerInstalled: false,
get _log() {
if (!this._logger) {
this._logger =
Log.repository.getLoggerWithMessagePrefix("Toolkit.Telemetry",
"HybridContentTelemetry::");
}
return this._logger;
},
/**
* Lazily initialized observer for the Telemetry upload preference. This is
* only ever executed if a page uses hybrid content telemetry and has enough
* privileges to run it.
*/
_lazyObserverInit() {
if (this._observerInstalled) {
// We only want to install the observers once, if needed.
return;
}
this._log.trace("_lazyObserverInit - installing the pref observers.");
XPCOMUtils.defineLazyPreferenceGetter(this, "_uploadEnabled",
TelemetryUtils.Preferences.FhrUploadEnabled,
false, /* aDefaultValue */
() => this._broadcastPolicyUpdate());
this._observerInstalled = true;
},
/**
* This is the handler for the async "HybridContentTelemetry:onTelemetryMessage"
* message. This function is getting called by the listener in nsBrowserGlue.js.
*/
onTelemetryMessage(aMessage, aData) {
if (!this._hybridContentEnabled) {
this._log.trace("onTelemetryMessage - hybrid content telemetry is disabled.");
return;
}
this._log.trace("onTelemetryMessage - Message received, dispatching API call.");
if (!aData ||
!("data" in aData) ||
!("name" in aData) ||
typeof aData.name != "string" ||
typeof aData.data != "object") {
this._log.error("onTelemetryMessage - received a malformed message.");
return;
}
this._dispatchAPICall(aData.name, aData.data, aMessage);
},
/**
* Broadcast the upload policy state to the pages using hybrid
* content telemetry.
*/
_broadcastPolicyUpdate() {
this._log.trace(`_broadcastPolicyUpdate - New value is ${this._uploadEnabled}.`);
Services.mm.broadcastAsyncMessage("HybridContentTelemetry:PolicyChanged",
{canUpload: this._uploadEnabled});
},
/**
* Dispatches the calls to the Telemetry service.
* @param {String} aEndpoint The name of the api endpoint to call.
* @param {Object} aData An object containing the data to pass to the API.
* @param {Object} aOriginalMessage The message object coming from the listener.
*/
_dispatchAPICall(aEndpoint, aData, aOriginalMessage) {
this._log.info(`_dispatchAPICall - processing "${aEndpoint}".`);
// We don't really care too much about validating the passed parameters.
// Telemetry will take care of that for us so there is little gain from
// duplicating that logic here. Just make sure we don't throw and report
// any error.
try {
switch (aEndpoint) {
case "init":
this._lazyObserverInit();
this._broadcastPolicyUpdate();
break;
case "registerEvents":
Services.telemetry.registerEvents(aData.category, aData.eventData);
break;
case "recordEvent":
// Don't pass "undefined" for the optional |value| and |extra|:
// the Telemetry API expects them to be "null" if something is being
// passed.
let check = (data, key) => (key in data && typeof data[key] != "undefined");
Services.telemetry.recordEvent(aData.category,
aData.method,
aData.object,
check(aData, "value") ? aData.value : null,
check(aData, "extra") ? aData.extra : null);
break;
default:
this._log.error(`_dispatchAPICall - unknown "${aEndpoint}"" API call.`);
}
} catch (e) {
this._log.error(`_dispatchAPICall - error executing "${aEndpoint}".`, e);
}
},
};
XPCOMUtils.defineLazyPreferenceGetter(HybridContentTelemetry, "_hybridContentEnabled",
TelemetryUtils.Preferences.HybridContentEnabled,
false /* aDefaultValue */);