Bug 1292360 - Add attribution data to the telemetry environment block; r=gfritzsche, data-review=bsmedberg

MozReview-Commit-ID: 4sltJYJrrFS

--HG--
extra : source : 6935ec84dc8e8944d1dcb8a41b2592cc7899e45b
This commit is contained in:
Matt Howell 2016-08-24 10:01:10 -07:00
parent 154bc7b5ef
commit da5646acec
3 changed files with 74 additions and 0 deletions

View File

@ -24,6 +24,8 @@ Cu.import("resource://gre/modules/AppConstants.jsm");
const Utils = TelemetryUtils;
XPCOMUtils.defineLazyModuleGetter(this, "AttributionCode",
"resource:///modules/AttributionCode.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ctypes",
"resource://gre/modules/ctypes.jsm");
if (AppConstants.platform !== "gonk") {
@ -42,6 +44,8 @@ const CHANGE_THROTTLE_INTERVAL_MS = 5 * 60 * 1000;
// The maximum length of a string (e.g. description) in the addons section.
const MAX_ADDON_STRING_LENGTH = 100;
// The maximum length of a string value in the settings.attribution object.
const MAX_ATTRIBUTION_STRING_LENGTH = 100;
/**
* This is a policy object used to override behavior for testing.
@ -764,6 +768,7 @@ function EnvironmentCache() {
this._currentEnvironment.profile = {};
p.push(this._updateProfile());
p.push(this._updateAttribution());
let setup = () => {
this._initTask = null;
@ -1178,6 +1183,21 @@ EnvironmentCache.prototype = {
}
}),
/**
* Update the cached attribution data object.
* @returns Promise<> resolved when the I/O is complete.
*/
_updateAttribution: Task.async(function* () {
let data = yield AttributionCode.getAttrDataAsync();
if (Object.keys(data).length > 0) {
this._currentEnvironment.settings.attribution = {};
for (let key in data) {
this._currentEnvironment.settings.attribution[key] =
limitStringToLength(data[key], MAX_ATTRIBUTION_STRING_LENGTH);
}
}
}),
/**
* Get the partner data in object form.
* @return Object containing the partner data.

View File

@ -61,6 +61,13 @@ Structure:
"pref.name.url": "<user-set>" // For some privacy-sensitive prefs
// only the fact that the value has been changed is recorded
},
attribution: { // optional, only present if the installation has attribution data
// all of these values are optional.
source: <string>, // referring partner domain, when install happens via a known partner
medium: <string>, // category of the source, such as "organic" for a search engine
campaign: <string>, // identifier of the particular campaign that led to the download of the product
content: <string>, // identifier to indicate the particular link within a campaign
},
},
profile: {
creationDate: <integer>, // integer days since UNIX epoch, e.g. 16446
@ -318,6 +325,15 @@ The following is a partial list of collected preferences.
- ``security.sandbox.content.level``: The meanings of the values are OS dependent, but 0 means not sandboxed for all OS. Details of the meanings can be found in the `Firefox prefs file <http://hg.mozilla.org/mozilla-central/file/tip/browser/app/profile/firefox.js>`_.
attribution
~~~~~~~~~~~
This object contains the attribution data for the product installation.
Attribution data is used to link installations of Firefox with the source that the user arrived at the Firefox download page from. It would indicate, for instance, when a user executed a web search for Firefox and arrived at the download page from there, directly navigated to the site, clicked on a link from a particular social media campaign, etc.
The attribution data is included in some versions of the default Firefox installer for Windows (the "stub" installer) and stored as part of the installation. All platforms other than Windows and also Windows installations that did not use the stub installer do not have this data and will not include the ``attribution`` object.
partner
-------

View File

@ -2,6 +2,7 @@
* http://creativecommons.org/publicdomain/zero/1.0/ */
Cu.import("resource://gre/modules/AddonManager.jsm");
Cu.import("resource:///modules/AttributionCode.jsm");
Cu.import("resource://gre/modules/TelemetryEnvironment.jsm", this);
Cu.import("resource://gre/modules/Preferences.jsm", this);
Cu.import("resource://gre/modules/PromiseUtils.jsm", this);
@ -71,6 +72,9 @@ const PLUGIN_UPDATED_TOPIC = "plugins-list-updated";
// system add-ons are enabled at startup, so record date when the test starts
const SYSTEM_ADDON_INSTALL_DATE = Date.now();
// Valid attribution code to write so that settings.attribution can be tested.
const ATTRIBUTION_CODE = "source%3Dgoogle.com";
/**
* Used to mock plugin tags in our fake plugin host.
*/
@ -268,6 +272,31 @@ function spoofPartnerInfo() {
}
}
function getAttributionFile() {
let file = Services.dirsvc.get("LocalAppData", Ci.nsIFile);
file.append("mozilla");
file.append(AppConstants.MOZ_APP_NAME);
file.append("postSigningData");
return file;
}
function spoofAttributionData() {
if (gIsWindows) {
AttributionCode._clearCache();
let stream = Cc["@mozilla.org/network/file-output-stream;1"].
createInstance(Ci.nsIFileOutputStream);
stream.init(getAttributionFile(), -1, -1, 0);
stream.write(ATTRIBUTION_CODE, ATTRIBUTION_CODE.length);
}
}
function cleanupAttributionData() {
if (gIsWindows) {
getAttributionFile().remove(false);
AttributionCode._clearCache();
}
}
/**
* Check that a value is a string and not empty.
*
@ -382,6 +411,11 @@ function checkSettingsSection(data) {
checkString(data.settings.defaultSearchEngine);
Assert.equal(typeof data.settings.defaultSearchEngineData, "object");
}
if ("attribution" in data.settings) {
Assert.equal(typeof data.settings.attribution, "object");
Assert.equal(data.settings.attribution.source, "google.com");
}
}
function checkProfileSection(data) {
@ -767,6 +801,10 @@ function run_test() {
// Spoof the the hotfixVersion
Preferences.set("extensions.hotfix.lastVersion", APP_HOTFIX_VERSION);
// Create the attribution data file, so that settings.attribution will exist.
spoofAttributionData();
do_register_cleanup(cleanupAttributionData);
run_next_test();
}