diff --git a/Firefox addon/Firefox addon.csproj b/Firefox addon/Firefox addon.csproj
index 5807fd5..47b82fc 100644
--- a/Firefox addon/Firefox addon.csproj
+++ b/Firefox addon/Firefox addon.csproj
@@ -70,7 +70,6 @@
-
@@ -129,7 +128,6 @@
-
diff --git a/Firefox addon/KeeFox/chrome/content/KFUI.js b/Firefox addon/KeeFox/chrome/content/KFUI.js
index 6643459..1795a02 100644
--- a/Firefox addon/KeeFox/chrome/content/KFUI.js
+++ b/Firefox addon/KeeFox/chrome/content/KFUI.js
@@ -135,7 +135,6 @@ keefox_win.UI = {
} finally
{
browser.messageManager.sendAsyncMessage("keefox:cancelFormRecording");
- keefox_org.metricsManager.pushEvent("feature", "SaveNever");
browser.passwordSaver = null;
}
}
@@ -201,14 +200,11 @@ keefox_win.UI = {
saveData.getLogin(function (login, urlMergeMode) {
if (saveData.update) {
- keefox_org.metricsManager.pushEvent("feature", "updateLogin",
- { "urlMergeMode": urlMergeMode, "filterState": filterState });
var result = keefox_org.updateLogin(login, saveData.oldLoginUUID, urlMergeMode, saveData.db);
keefox_win.notificationManager.remove("password-save");
browser.passwordSaver.showUpdateSuccessNotification();
}
else {
- keefox_org.metricsManager.pushEvent("feature", "addLogin");
var result = keefox_org.addLogin(login, saveData.group, saveData.db);
if (keefox_org._keeFoxExtension.prefs.getValue("rememberMRUGroup", false))
keefox_org._keeFoxExtension.prefs.setValue("MRUGroup-" + saveData.db, saveData.group);
diff --git a/Firefox addon/KeeFox/chrome/content/PasswordSaver.js b/Firefox addon/KeeFox/chrome/content/PasswordSaver.js
index 35f83fa..e584e73 100644
--- a/Firefox addon/KeeFox/chrome/content/PasswordSaver.js
+++ b/Firefox addon/KeeFox/chrome/content/PasswordSaver.js
@@ -437,7 +437,6 @@ keefox_win.PasswordSaver.prototype =
abortAndLaunchManualEdit: function ()
{
- keefox_org.metricsManager.pushEvent("feature", "abortAndLaunchManualEdit");
keefox_org.launchLoginEditor(this.saveData.oldLoginUUID, this.saveData.db);
keefox_win.notificationManager.remove("password-save");
},
diff --git a/Firefox addon/KeeFox/chrome/content/UninstallHelper.js b/Firefox addon/KeeFox/chrome/content/UninstallHelper.js
index f737d72..1712782 100644
--- a/Firefox addon/KeeFox/chrome/content/UninstallHelper.js
+++ b/Firefox addon/KeeFox/chrome/content/UninstallHelper.js
@@ -249,17 +249,6 @@ keefox_win.UninstallHelper.prototype =
if (extraText.value.length > 0)
extra = extraText.value.substr(0,15000);
- keefox_org.metricsManager.pushEvent("uninstall", "feedback",
- {
- "connectState": this.connectState,
- "setupState": this.setupState,
- "tutorialProgress": this.tutorialProgress,
- "varients": this.varients,
- "reason": reason,
- "extra": extra,
- "disable": this.disabling
- }, true);
-
let responseContainer = this.createResponseContainer(reason, this.connectState, this.setupState, this.tutorialProgress);
responseContainer.classList.add("disabled");
diff --git a/Firefox addon/KeeFox/chrome/content/commonDialog.js b/Firefox addon/KeeFox/chrome/content/commonDialog.js
index 469751c..71a095f 100644
--- a/Firefox addon/KeeFox/chrome/content/commonDialog.js
+++ b/Firefox addon/KeeFox/chrome/content/commonDialog.js
@@ -794,13 +794,11 @@ var keeFoxDialogManager = {
if (autoFill)
{
// fill in the best matching login
- keefox_org.metricsManager.pushEvent ("feature", "AutoFillDialog");
dialogFindLoginStorage.document.getElementById("loginTextbox").value = matchedLogins[bestMatch].username;
dialogFindLoginStorage.document.getElementById("password1Textbox").value = matchedLogins[bestMatch].password;
}
if (autoSubmit || dialogFindLoginStorage.mustAutoSubmit)
{
- keefox_org.metricsManager.pushEvent ("feature", "AutoSubmitDialog");
Dialog.onButton0();
close();
}
@@ -828,7 +826,6 @@ var keeFoxDialogManager = {
fill : function (username, password)
{
- keefox_org.metricsManager.pushEvent ("feature", "MatchedSubmitDialog");
document.getElementById("loginTextbox").value = username;
document.getElementById("password1Textbox").value = password;
Dialog.onButton0();
diff --git a/Firefox addon/KeeFox/chrome/content/formsWin.js b/Firefox addon/KeeFox/chrome/content/formsWin.js
index 79a3d56..585859e 100644
--- a/Firefox addon/KeeFox/chrome/content/formsWin.js
+++ b/Firefox addon/KeeFox/chrome/content/formsWin.js
@@ -86,9 +86,7 @@ keefox_win.loadAndAutoSubmit = function (button, ctrlClick, URL, uniqueID, dbFil
keefox_win.Logger.debug("loading and auto submitting button " + button + ctrlClick + ":" + URL);
else
keefox_win.Logger.debug("loading and auto submitting button " + button + ctrlClick + "...");
-
- keefox_org.metricsManager.pushEvent ("feature", "loadAndAutoSubmit");
-
+
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var newWindow = wm.getMostRecentWindow("navigator:browser") ||
diff --git a/Firefox addon/KeeFox/chrome/content/framescript/formsFillTab.js b/Firefox addon/KeeFox/chrome/content/framescript/formsFillTab.js
index f4794ff..8fd2da3 100644
--- a/Firefox addon/KeeFox/chrome/content/framescript/formsFillTab.js
+++ b/Firefox addon/KeeFox/chrome/content/framescript/formsFillTab.js
@@ -720,7 +720,6 @@ var scanForOrphanedFields = function (doc)
querySelectorAll: function() { return []; }, // Only use is for listing button elements
submit: function() { return; } // Not possible to submit a pseudo form unless a button with custom JS has already been found
};
- metricsManager.adjustAggregate("pseudoFormCreated", 1);
}
var tn = (new Date()).getTime();
@@ -1357,10 +1356,6 @@ var fillAndSubmit = function (automated, frameKey, formIndex, loginIndex)
&& matchResult.formReadyForSubmit)
{
Logger.info("Auto-submitting form...");
- if (automated)
- metricsManager.pushEvent ("feature", "AutoSubmit");
- else
- metricsManager.pushEvent ("feature", "ManualSubmit"); // Called "MatchedFill" previously (yes, I'm an idiot)
submitForm(form);
} else if (isMatchedLoginRequest)
{
@@ -1403,10 +1398,6 @@ var fillAndSubmit = function (automated, frameKey, formIndex, loginIndex)
"logins": matchingLoginsFromAllFrames,
"notifyUserOnSuccess": matchResult.notifyUserOnSuccess
});
- metricsManager.pushEvent ("feature", "AutoFill");
- } else
- {
- metricsManager.pushEvent ("feature", "ManualFill"); // Called "MatchedSubmit" previously (yes, I'm an idiot)
}
} else
{
diff --git a/Firefox addon/KeeFox/chrome/content/framescript/keefoxTab.js b/Firefox addon/KeeFox/chrome/content/framescript/keefoxTab.js
index e6c2bc9..27ea694 100644
--- a/Firefox addon/KeeFox/chrome/content/framescript/keefoxTab.js
+++ b/Firefox addon/KeeFox/chrome/content/framescript/keefoxTab.js
@@ -49,10 +49,9 @@ part of the global scope of this script from within a subscript so we work aroun
this by passing in our main keefox_tab object for direct manipulation within the
subscript. */
-// Load our logging, config and metrics subsystem proxies
+// Load our logging and config subsystem proxies
keefox_tab.scriptLoader.loadSubScript("chrome://keefox/content/framescript/proxies/logger.js", keefox_tab);
keefox_tab.scriptLoader.loadSubScript("chrome://keefox/content/framescript/proxies/config.js", keefox_tab);
-keefox_tab.scriptLoader.loadSubScript("chrome://keefox/content/framescript/proxies/metrics.js", keefox_tab);
// Load our other javascript
keefox_tab.scriptLoader.loadSubScript("chrome://keefox/content/shared/uriUtils.js", keefox_tab);
diff --git a/Firefox addon/KeeFox/chrome/content/framescript/proxies/metrics.js b/Firefox addon/KeeFox/chrome/content/framescript/proxies/metrics.js
deleted file mode 100644
index 5f47508..0000000
--- a/Firefox addon/KeeFox/chrome/content/framescript/proxies/metrics.js
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- KeeFox - Allows Firefox to communicate with KeePass (via the KeePassRPC KeePass plugin)
- Copyright 2015 Chris Tomlinson
-
- This implements a proxy/stub so we can continue to call the metricsManager from the
- frame script environment despite the real metricsManager living in chrome scope.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-"use strict";
-var metricsManager = {
- pushEvent: function (category, name, params) // string, string, object of keys/vals
- {
- sendAsyncMessage("keefox:metrics-pushEvent", {
- "category": category,
- "name": name,
- "params": params
- });
- },
-
- adjustAggregate: function (key, value)
- {
- sendAsyncMessage("keefox:metrics-adjustAggregate", {
- "key": key,
- "value": value
- });
- }
-};
\ No newline at end of file
diff --git a/Firefox addon/KeeFox/chrome/content/install.js b/Firefox addon/KeeFox/chrome/content/install.js
index 2e749c9..b26ed44 100644
--- a/Firefox addon/KeeFox/chrome/content/install.js
+++ b/Firefox addon/KeeFox/chrome/content/install.js
@@ -261,11 +261,6 @@ function prepareInstallPage()
break;
default: document.getElementById('ERRORInstallButtonMain').setAttribute('hidden', false); break;
}
-
- // Record key parts of above info to help find problems and plan future KeeFox priorities
- mainWindow.keefox_org.metricsManager.pushEvent ("setup", "displayed",
- { "installCase": installCase,
- "downgrade": (args.downWarning == "1" && args.currentKPRPCv && args.newKPRPCv) });
}
function installationError(error)
@@ -282,7 +277,6 @@ function installationError(error)
}
showSection('restartInstallationOption');
resetInstallation();
- mainWindow.keefox_org.metricsManager.pushEvent ("setup", "error", { "reason": error });
}
function resetInstallation()
@@ -296,8 +290,7 @@ function cancelCurrentDownload()
persist.cancelSave();
showSection("ERRORInstallDownloadCanceled");
showSection('restartInstallationOption');
- resetInstallation();
- mainWindow.keefox_org.metricsManager.pushEvent ("setup", "error", { "reason": "ERRORInstallDownloadCanceled" });
+ resetInstallation();
}
function hideInstallView() {
@@ -324,7 +317,6 @@ function checksumFailed() {
mainWindow.keefox_win.Logger.error("File checksum failed. Download corrupted?");
showSection("ERRORInstallDownloadChecksumFailed");
showSection('restartInstallationOption');
-mainWindow.keefox_org.metricsManager.pushEvent ("setup", "error", { "reason": "ERRORInstallDownloadChecksumFailed" });
}
/********************
@@ -776,7 +768,6 @@ functions initiated by user choice in UI
*/
function setupExeInstall()
{
- mainWindow.keefox_org.metricsManager.pushEvent ("setup", "installing", { "type": "dotNet.exe" });
hideInstallView();
showProgressView();
@@ -796,7 +787,6 @@ function setupExeInstall()
*/
function KPsetupExeSilentInstall()
{
- mainWindow.keefox_org.metricsManager.pushEvent ("setup", "installing", { "type": "KeePass.exe-silent" });
hideInstallView();
showProgressView();
@@ -818,7 +808,6 @@ function KPsetupExeSilentInstall()
*/
function copyKRPCToKnownKPLocationInstall()
{
- mainWindow.keefox_org.metricsManager.pushEvent ("setup", "installing", { "type": "copyKRPCToKnownKPLocation" });
hideInstallView();
let keePassLocation = mainWindow.keefox_org._keeFoxExtension.prefs
@@ -856,7 +845,6 @@ function copyKRPCToKnownKPLocationInstall()
*/
function copyKPToSpecificLocationInstall()
{
- mainWindow.keefox_org.metricsManager.pushEvent ("setup", "installing", { "type": "copyKPToSpecificLocation" });
// Cancel any automatically started downloads
try {
persist.cancelSave();
@@ -896,7 +884,6 @@ function copyKPToSpecificLocationInstall()
*/
function KPsetupExeInstall()
{
- mainWindow.keefox_org.metricsManager.pushEvent ("setup", "installing", { "type": "KeePass.exe" });
hideInstallView();
showProgressView();
@@ -933,8 +920,6 @@ function launchAndConnectToKeePass()
mainWindow.keefox_org.KeePassRPC.reconnectTimer.cancel();
mainWindow.keefox_org.KeePassRPC.reconnectVerySoon();
-
- mainWindow.keefox_org.metricsManager.pushEvent ("setup", "success");
// launch KeePass and then try to connect to KeePassRPC
mainWindow.keefox_org.launchKeePass();
diff --git a/Firefox addon/KeeFox/chrome/content/options.js b/Firefox addon/KeeFox/chrome/content/options.js
index 31720cc..9e1e94b 100644
--- a/Firefox addon/KeeFox/chrome/content/options.js
+++ b/Firefox addon/KeeFox/chrome/content/options.js
@@ -20,7 +20,7 @@ function onLoad(){
'lab-keePassRPCPort','lab-keePassRPCPortWarning','saveFavicons','lab-keePassDBToOpen','keePassDBToOpenBrowseButton',
'rememberMRUDB', 'rememberMRUGroup', 'lab-keePassRPCInstalledLocation', 'keePassRPCInstalledLocationBrowseButton', 'lab-keePassInstalledLocation', 'keePassInstalledLocationBrowseButton',
'lab-monoLocation','monoLocationBrowseButton','keePassRememberInstalledLocation','lab-keePassLocation',
- 'desc-site-specific','desc-site-specific-savepass','desc-site-specific-link','desc-site-specific-savepass-link','desc-ConnSL','desc-ConnSL-ManualLink-link','desc-conn-sl-client','slc-Low','slc-Medium','slc-High','sls-Low','sls-Medium','sls-High','desc-conn-sl-client-detail','desc-conn-sl-server','desc-conn-sl-server-detail','desc-conn-sl-low','desc-conn-sl-high','desc-commands-intro','desc-metrics','desc-metrics-link','lab-sendUsageMetrics','lab-maxMatchedLoginsInMainPanel','notifyWhenEntryUpdated'
+ 'desc-site-specific','desc-site-specific-savepass','desc-site-specific-link','desc-site-specific-savepass-link','desc-ConnSL','desc-ConnSL-ManualLink-link','desc-conn-sl-client','slc-Low','slc-Medium','slc-High','sls-Low','sls-Medium','sls-High','desc-conn-sl-client-detail','desc-conn-sl-server','desc-conn-sl-server-detail','desc-conn-sl-low','desc-conn-sl-high','desc-commands-intro','lab-maxMatchedLoginsInMainPanel','notifyWhenEntryUpdated'
],
['title','label','tooltiptext','accesskey','value']);
diff --git a/Firefox addon/KeeFox/chrome/content/options.xul b/Firefox addon/KeeFox/chrome/content/options.xul
index 9efd742..95f96bd 100644
--- a/Firefox addon/KeeFox/chrome/content/options.xul
+++ b/Firefox addon/KeeFox/chrome/content/options.xul
@@ -66,7 +66,6 @@
-
@@ -234,15 +233,6 @@
- %-KeeFox-pref-metrics-desc-% %-KeeFox-pref-metrics-link-%
-
-
-
diff --git a/Firefox addon/KeeFox/chrome/content/panel.js b/Firefox addon/KeeFox/chrome/content/panel.js
index bfcf3aa..7d0021c 100644
--- a/Firefox addon/KeeFox/chrome/content/panel.js
+++ b/Firefox addon/KeeFox/chrome/content/panel.js
@@ -965,7 +965,6 @@ keefox_win.panel = {
function (event) {
keefox_org.utils.copyStringToClipboard(usernameField.value);
keefox_win.panel.CustomizableUI.hidePanelForNode(keefox_win.panel._currentWindow.document.getElementById('keefox-panelview'));
- keefox_org.metricsManager.adjustAggregate("copyUsername", 1);
});
}
@@ -977,7 +976,6 @@ keefox_win.panel = {
function (event) {
keefox_org.utils.copyStringToClipboard(passwordField.value);
keefox_win.panel.CustomizableUI.hidePanelForNode(keefox_win.panel._currentWindow.document.getElementById('keefox-panelview'));
- keefox_org.metricsManager.adjustAggregate("copyPassword", 1);
});
}
if (otherFieldCount > 1 || passwordFieldCount > 1) {
@@ -999,7 +997,6 @@ keefox_win.panel = {
function (event) {
keefox_org.utils.copyStringToClipboard(o.value);
keefox_win.panel.CustomizableUI.hidePanelForNode(keefox_win.panel._currentWindow.document.getElementById('keefox-panelview'));
- keefox_org.metricsManager.adjustAggregate("copyOther", 1);
});
}
});
@@ -1015,7 +1012,6 @@ keefox_win.panel = {
function (event) {
keefox_org.utils.copyStringToClipboard(p.value);
keefox_win.panel.CustomizableUI.hidePanelForNode(keefox_win.panel._currentWindow.document.getElementById('keefox-panelview'));
- keefox_org.metricsManager.adjustAggregate("copyOther", 1);
});
}
});
@@ -1345,10 +1341,6 @@ keefox_win.panel = {
{
keefox_win.panel.addLoginContextActions(document, this.getAttribute('data-uuid'), this.getAttribute('data-fileName'));
keefox_win.panel.displayContextMenu(keefox_win.panel._currentWindow.document, event, 'KeeFox-login-context');
- if (keefox_win.SearchFilter.getFilterState(document, 'PanelSection') == "all")
- keefox_org.metricsManager.adjustAggregate("searchResultContextAll", 1);
- else
- keefox_org.metricsManager.adjustAggregate("searchResultContextCurrent", 1);
}
}, false);
loginItem.addEventListener("keefoxCommand", function (event) {
@@ -1361,20 +1353,12 @@ keefox_win.panel = {
keefox_win.panel.CustomizableUI.hidePanelForNode(
keefox_win.panel._currentWindow.document.getElementById('keefox-panelview'));
keefox_win.panel.hideSubSections();
- if (keefox_win.SearchFilter.getFilterState(keefox_win.panel._currentWindow.document, 'PanelSection') == "all")
- keefox_org.metricsManager.adjustAggregate("searchResultSelectedAll", 1);
- else
- keefox_org.metricsManager.adjustAggregate("searchResultSelectedCurrent", 1);
}, false);
loginItem.addEventListener("keefoxContext", function (event) {
keefox_win.panel.addLoginContextActions(document, this.getAttribute('data-uuid'), this.getAttribute('data-fileName'));
keefox_win.panel.displayContextMenu(keefox_win.panel._currentWindow.document,
{ target: event.detail.target, layerX: event.detail.layerX, layerY: event.detail.layerY },
'KeeFox-login-context');
- if (keefox_win.SearchFilter.getFilterState(keefox_win.panel._currentWindow.document, 'PanelSection') == "all")
- keefox_org.metricsManager.adjustAggregate("searchResultContextAll", 1);
- else
- keefox_org.metricsManager.adjustAggregate("searchResultContextCurrent", 1);
}, false);
loginItem.addEventListener("mouseenter", keefox_win.panel.onMouseEnterLogin, false);
@@ -1417,13 +1401,6 @@ keefox_win.panel = {
layerY: this.offsetTop + event.layerY
},
'KeeFox-login-context');
- keefox_org.metricsManager.adjustAggregate("loginContextButton", 1);
- if (event.target.parentNode.parentNode.parentNode.id == "KeeFox-PanelSubSection-SearchResults") {
- if (keefox_win.SearchFilter.getFilterState(keefox_win.panel._currentWindow.document, 'PanelSection') == "all")
- keefox_org.metricsManager.adjustAggregate("searchResultContextAll", 1);
- else
- keefox_org.metricsManager.adjustAggregate("searchResultContextCurrent", 1);
- }
}, false);
optionsMenuTrigger.setAttribute("id", "optionsMenuTrigger");
event.target.appendChild(optionsMenuTrigger);
@@ -1734,7 +1711,6 @@ keefox_win.panel = {
}, false);
profileItem.addEventListener("keefoxCommand", function (event) {
let kf = keefox_org;
- kf.metricsManager.pushEvent ("feature", "generatePasswordFromProfile");
kf.generatePassword(this.textContent, keefox_win.panel._currentWindow.gLastValidURLStr);
keefox_win.panel.CustomizableUI.hidePanelForNode(
keefox_win.panel._currentWindow.document.getElementById('keefox-panelview'));
@@ -1756,7 +1732,6 @@ keefox_win.panel = {
generatePassword: function () {
let kf = this._currentWindow.keefox_org;
- kf.metricsManager.pushEvent ("feature", "generatePassword");
kf.generatePassword(null, this._currentWindow.gLastValidURLStr);
},
diff --git a/Firefox addon/KeeFox/chrome/content/siteOptions.js b/Firefox addon/KeeFox/chrome/content/siteOptions.js
index 087343d..b189b45 100644
--- a/Firefox addon/KeeFox/chrome/content/siteOptions.js
+++ b/Firefox addon/KeeFox/chrome/content/siteOptions.js
@@ -296,7 +296,6 @@ function addSite()
var mainWindow = wm.getMostRecentWindow("navigator:browser") ||
wm.getMostRecentWindow("mail:3pane");
- mainWindow.keefox_org.metricsManager.pushEvent("feature", "SiteSpecificAdd");
configMan.setConfigForURL(newURL,{});
configMan.save();
go(newURL);
diff --git a/Firefox addon/KeeFox/defaults/preferences/prefs.js b/Firefox addon/KeeFox/defaults/preferences/prefs.js
index 98dd1ee..356e6a3 100644
--- a/Firefox addon/KeeFox/defaults/preferences/prefs.js
+++ b/Firefox addon/KeeFox/defaults/preferences/prefs.js
@@ -19,7 +19,6 @@ pref("extensions.keefox@chris.tomlinson.searchAllOpenDBs", true);
pref("extensions.keefox@chris.tomlinson.listAllOpenDBs", true);
pref("extensions.keefox@chris.tomlinson.connSLClient", 2);
pref("extensions.keefox@chris.tomlinson.connSLServerMin", 2);
-pref("extensions.keefox@chris.tomlinson.metricsUsageDisabled", false);
pref("extensions.keefox@chris.tomlinson.maxMatchedLoginsInMainPanel", 5);
pref("extensions.keefox@chris.tomlinson.maxAllLoginsInMainPanel", 0);
pref("extensions.keefox@chris.tomlinson.tabResultsCacheEnabled", true);
diff --git a/Firefox addon/KeeFox/modules/DataMigration.js b/Firefox addon/KeeFox/modules/DataMigration.js
index ed11c98..c58d2d7 100644
--- a/Firefox addon/KeeFox/modules/DataMigration.js
+++ b/Firefox addon/KeeFox/modules/DataMigration.js
@@ -64,8 +64,8 @@ var DataMigration = {
fullConfig.logMethodConsole = KFExtension.prefs.getValue("logMethodConsole", false);
fullConfig.logMethodFile = KFExtension.prefs.getValue("logMethodFile", false);
fullConfig.logSensitiveData = KFExtension.prefs.getValue("logSensitiveData", false);
- fullConfig.metricsUsageDisabled = KFExtension.prefs.getValue("metricsUsageDisabled", false);
- fullConfig.metricsUserId = KFExtension.prefs.getValue("metricsUserId", "");
+ fullConfig.metricsUsageDisabled = false;
+ fullConfig.metricsUserId = "";
fullConfig.notifyWhenEntryUpdated = KFExtension.prefs.getValue("notifyWhenEntryUpdated", true);
fullConfig.notifyWhenLateDiscovery = KFExtension.prefs.getValue("notifyWhenLateDiscovery", true);
fullConfig.notifyWhenLoggedOut = KFExtension.prefs.getValue("notifyWhenLoggedOut", false);
diff --git a/Firefox addon/KeeFox/modules/KF.js b/Firefox addon/KeeFox/modules/KF.js
index 02b1973..d28b5a1 100644
--- a/Firefox addon/KeeFox/modules/KF.js
+++ b/Firefox addon/KeeFox/modules/KF.js
@@ -32,7 +32,6 @@ var EXPORTED_SYMBOLS = ["keefox_org"];
Cu.import("resource://gre/modules/AddonManager.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://kfmod/KFLogger.js");
-Cu.import("resource://kfmod/metrics.js");
Cu.import("resource://kfmod/jsonrpcClient.js");
Cu.import("resource://kfmod/locales.js");
Cu.import("resource://kfmod/utils.js");
@@ -105,33 +104,6 @@ function KeeFox()
this.locale = new Localisation(["chrome://keefox/locale/keefox.properties"]);
- // Set up metrics recording but don't break the main addon if something unexpected happens
- try
- {
- // Most of the metrics manager startup code is asynchronous so there is a
- // race between the manager and the rest of the KeeFox startup code. I
- // think this has been covered in the design of the manager (e.g. with
- // temporary storage of metrics while the main storage subsystems
- // initialise) but even if I've got that 100% correct, it is a shame to
- // double-handle the activity that occurs before the manager is ready
- // so it may be worth refactoring a few other parts of KeeFox to allow
- // us to start the metrics manager initialisation sooner.
- this.metricsManager = metricsManager;
- let metricsUserId = this._keeFoxExtension.prefs.getValue("metricsUserId", "");
- if (!metricsUserId)
- {
- metricsUserId = this.utils.newGUID();
- this._keeFoxExtension.prefs.setValue("metricsUserId", metricsUserId);
- }
- this.metricsManager.init(this.locale.getCurrentLocale(), metricsUserId, this.utils.newGUID());
- } catch (e) {
- this._KFLog.error("Could not load metrics manager. Creating null functions to minimise disruption.");
- this.metricsManager = {};
- this.metricsManager.pushEvent = function () {};
- this.metricsManager.adjustAggregate = function () {};
- this.metricsManager.setApplicationMetadata = function () {};
- }
-
this.search = new Search(this, {
version: 1,
searchAllDatabases: this._keeFoxExtension.prefs.getValue("searchAllOpenDBs", true)
@@ -507,8 +479,6 @@ KeeFox.prototype = {
}
this.KeePassDatabases = newDatabases;
this.ActiveKeePassDatabaseIndex = newDatabaseActiveIndex;
- if (newDatabases.length > 0)
- this.metricsManager.adjustAggregate("avgOpenDatabases", newDatabases.length);
this._refreshKPDBCallback();
},
@@ -1228,8 +1198,6 @@ KeeFox.prototype = {
uninstallFeedback: function (disabling)
{
let [ connectState, setupState, setupActive, tutorialProgress ] = keefox_org.getAddonState();
- keefox_org.metricsManager.pushEvent("uninstall", disabling ? "disable" : "uninstall",
- { "connectState": connectState, "setupState": setupState, "setupActive": setupActive, "tutorialProgress": tutorialProgress }, true);
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var window = wm.getMostRecentWindow("navigator:browser") ||
@@ -1240,9 +1208,6 @@ KeeFox.prototype = {
abortedUninstallFeedback: function ()
{
let [ connectState, setupState, setupActive, tutorialProgress ] = keefox_org.getAddonState();
-
- keefox_org.metricsManager.pushEvent("uninstall", "abort", {
- "connectState": connectState, "setupState": setupState, "setupActive": setupActive, "tutorialProgress": tutorialProgress }, true);
},
getAddonState: function ()
diff --git a/Firefox addon/KeeFox/modules/TutorialHelper.js b/Firefox addon/KeeFox/modules/TutorialHelper.js
index 0da4c98..8c26f30 100644
--- a/Firefox addon/KeeFox/modules/TutorialHelper.js
+++ b/Firefox addon/KeeFox/modules/TutorialHelper.js
@@ -110,23 +110,13 @@ let TutorialHelper = function()
this.sendSetupStateToTutorial = function (browser) {
let [ connectState, setupState, setupActive, notUsed, dbState ] = browser.ownerGlobal.keefox_org.getAddonState();
- // We have probably already worked out our version string (but maybe not if the
- // tutorial page is loaded during session restore)
- if (browser.ownerGlobal.keefox_org.metricsManager.ii.addonVersion) {
+ Components.utils.import("resource://gre/modules/AddonManager.jsm");
+ AddonManager.getAddonByID("keefox@chris.tomlinson", function(addon) {
browser.messageManager.sendAsyncMessage("keefox:sendStatusToTutorialPage", {
"connectState": connectState, "setupState": setupState, "setupActive": setupActive,
- "version": browser.ownerGlobal.keefox_org.metricsManager.ii.addonVersion,
+ "version": addon.version,
"dbState": dbState });
- } else
- {
- Components.utils.import("resource://gre/modules/AddonManager.jsm");
- AddonManager.getAddonByID("keefox@chris.tomlinson", function(addon) {
- browser.messageManager.sendAsyncMessage("keefox:sendStatusToTutorialPage", {
- "connectState": connectState, "setupState": setupState, "setupActive": setupActive,
- "version": addon.version,
- "dbState": dbState });
- });
- }
+ });
};
this.mm = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
diff --git a/Firefox addon/KeeFox/modules/commands.js b/Firefox addon/KeeFox/modules/commands.js
index 945688f..5bede8f 100644
--- a/Firefox addon/KeeFox/modules/commands.js
+++ b/Firefox addon/KeeFox/modules/commands.js
@@ -405,7 +405,6 @@ function commandManager () {
let win = utils.getWindow();
if (!win) return;
- win.keefox_org.metricsManager.pushEvent ("feature", "detectForms");
var currentGBrowser = win.gBrowser;
// Notify all parts of the UI that might need to clear their matched logins data
win.keefox_win.mainUI.resetSearchInterface();
@@ -569,7 +568,6 @@ function commandManager () {
if (!keefox_org.commandManager.conditions[commandName]())
continue;
keefox_org._KFLog.debug("Executing command action: " + commandName);
- keefox_org.metricsManager.adjustAggregate("keyboardShortcutsPressed", 1);
//TODO:2: Pass event target information to action
keefox_org.commandManager.actions[commandName]();
break;
@@ -690,7 +688,6 @@ function commandManager () {
item.keeFoxValidContexts = this.commands[i].contextLocationFlags;
item.addEventListener("command", function(event) {
let kf = utils.getWindow().keefox_org;
- kf.metricsManager.adjustAggregate("contextMenuItemsPressed", 1);
kf.commandManager.actions[this.keeFoxCommandName]();
}, false);
}
diff --git a/Firefox addon/KeeFox/modules/jsonrpcClient.js b/Firefox addon/KeeFox/modules/jsonrpcClient.js
index c11cacb..5e9fbe5 100644
--- a/Firefox addon/KeeFox/modules/jsonrpcClient.js
+++ b/Firefox addon/KeeFox/modules/jsonrpcClient.js
@@ -179,9 +179,6 @@ jsonrpcClient.prototype.constructor = jsonrpcClient;
netRuntimeVersion = "Mono " + resultWrapper.result.monoVersion;
else
netRuntimeVersion = ".NET " + resultWrapper.result.nETversion;
-
- window.keefox_org.metricsManager.setApplicationMetadata(
- resultWrapper.result.keePassVersion, netRuntimeVersion);
}
diff --git a/Firefox addon/KeeFox/modules/metrics.js b/Firefox addon/KeeFox/modules/metrics.js
deleted file mode 100644
index 604930b..0000000
--- a/Firefox addon/KeeFox/modules/metrics.js
+++ /dev/null
@@ -1,824 +0,0 @@
-/*
- KeeFox - Allows Firefox to communicate with KeePass (via the KeePassRPC KeePass plugin)
- Copyright 2008-2014 Chris Tomlinson
-
- The metrics module collects anonymous statistics about key metrics and
- behaviours so we can improve KeeFox.
-
- https://addons.mozilla.org/en-US/firefox/addon/keefox/privacy/
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
-*/
-"use strict";
-
-let Cc = Components.classes;
-let Ci = Components.interfaces;
-let Cu = Components.utils;
-
-var EXPORTED_SYMBOLS = ["metricsManager"];
-Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/ISO8601DateUtils.jsm");
-Cu.import("resource://kfmod/KFLogger.js");
-Cu.import("resource://gre/modules/AddonManager.jsm");
-Cu.import("resource://gre/modules/Timer.jsm");
-Cu.importGlobalProperties(["XMLHttpRequest"]);
-
-// A struct to represent information that won't change for a given session.
-// In most cases, we'll only want to send this data once but there are a few exceptions.
-function ImmutableInformation()
-{
- this.userId;
- this.sessionId;
- this.OSType;
- this.OSVersion;
- this.browserType;
- this.browserVersion;
- this.addonVersion;
- this.locale;
- this.sessionStart;
- this.screenWidth;
- this.screenHeight;
- this.keePassVersion;
- this.netRuntimeVersion;
-}
-
-function mm () {
-
- // where we'll POST the data to
- this.url = "https://anonymousstats.keefox.org/in";
-
- // Usual logging object
- this._KFLog = KeeFoxLog;
-
- // Timer to process queued messages at regular intervals
- this.metricsTimer = null;
-
- // Track metrics data submitted before the module has finished initialising
- this.messagesQueue = [];
- this.aggregatesQueue = [];
- this.messagesReady = false;
- this.aggregatesReady = false;
- this.nextRequestTimeout = 30000; // 30 seconds
-
- this.init = function (locale, userId, sessionId)
- {
- this.ii = new ImmutableInformation();
-
- this.ii.locale = locale;
- this.ii.userId = userId;
- this.ii.sessionId = sessionId;
- this.ii.sessionStart = ISO8601DateUtils.create(new Date());
-
- this.ii.browserType = Services.appinfo.name;
- this.ii.browserVersion = Services.appinfo.version;
-
- // OS type
- this.ii.OSType = Services.appinfo.OS;
-
- // OS version string
- try {
- this.ii.OSversion = Components.classes["@mozilla.org/network/protocol;1?name=http"]
- .getService(Components.interfaces.nsIHttpProtocolHandler).oscpu;
- } catch (ex)
- {
- this.ii.OSversion = "Unknown";
- }
-
- // We need a closure on this metrics module so we can manipulate it in
- // the many callbacks required to keep things nice and asynchronous
- var mm = this;
-
- // We can't start sending metrics data until Firefox has told us what
- // we need to know (so far that's just the addon version)
- // Other code may log events before we get to this callback so
- // startSession will always make sure it is pushed to the front of the
- // queue before converting transient storage to persistent storage.
- // This might mean that the session start time is later than the first
- // events recorded in the session but if that becomes a problem it can
- // be resolved retrospectively during analysis becuase the session ID
- // is included with every message
- AddonManager.getAddonByID("keefox@chris.tomlinson", function(addon) {
- mm.metricsStartup (addon, mm);
- }
- );
- };
-
- this.metricsStartup = function (addon, mm) {
- mm._KFLog.debug("Metrics startup for KeeFox version: " + addon.version);
-
- mm.ii.addonVersion = addon.version;
-
- // Make sure indexedDB is available somewhere consistent regardless
- // of old Firefox differences.
- //
- // We can't assume that indexedDB and IDBKeyRange are accessed in the same
- // way because there are definitely some non-release builds of Firefox
- // where they differ but it does appear that they are consistently available
- // if initWindowless() works.
- if (typeof indexedDB !== "undefined")
- {
- mm.indexedDB = indexedDB;
- }
- if (!mm.indexedDB) {
- try {
- let idbManager = Cc["@mozilla.org/dom/indexeddb/manager;1"].
- getService(Ci.nsIIndexedDatabaseManager);
- idbManager.initWindowless(mm);
- } catch (e)
- {
- // May have just failed becuase the API changed again so that
- // calls to initWindowless now need to be replaced by...
- try
- {
- Cu.importGlobalProperties(["indexedDB"]);
- mm.indexedDB = indexedDB;
- }
- catch (ie)
- {
- // Still broken, we'll have to accept that the whole metrics
- // system is fragile until Firefox settles on a stable API for IndexedDB...
- mm._KFLog.info("KeeFox metrics system disabled due to exception: " + e + " and 2nd exception: " + ie);
- return;
- }
- }
- }
-
- if (!mm.IDBKeyRange) {
- mm.IDBKeyRange = IDBKeyRange;
- }
- if (!mm.IDBKeyRange) {
- try
- {
- Cu.importGlobalProperties(["IDBKeyRange"]);
- mm.IDBKeyRange = IDBKeyRange;
- }
- catch (e)
- {
- // Still broken, we'll have to accept that the whole metrics
- // system is fragile until Firefox settles on a stable API for IndexedDB...
- mm._KFLog.info("KeeFox metrics system disabled because IDBKeyRange is not available in this Firefox build. Exception: " + e);
- return;
- }
- }
-
- // Open a uniquely named database
- var request = mm.indexedDB.open("keefox@chris.tomlinson",4);
-
- // Not sure why this error could occur (no local disk space?) but
- // being able to track the failure might help us fix it in a
- // future KeeFox release
- request.onerror = function(event) {
- let errMsg = "";
- if (event.target.error.name)
- errMsg += event.target.error.name + " - ";
- if (event.target.error && event.target.error.message)
- errMsg += event.target.error.message;
-
- mm._KFLog.error("Metrics system could not open/create the indexedDB. " + errMsg);
-
- if (event.target.error.name == "VersionError")
- {
- // try fixing things by deleting the stored metrics and starting again
- var DBDeleteRequest = mm.indexedDB.deleteDatabase("keefox@chris.tomlinson");
- DBDeleteRequest.onerror = function(event) {
- mm._KFLog.error("Metrics system could delete the indexedDB.");
- };
- DBDeleteRequest.onsuccess = function(event) {
- mm._KFLog.warn("Metrics system deleted the indexedDB.");
- // Try again in a bit
- setTimeout(mm.metricsStartup, 10000, addon, mm);
- };
- } else
- {
- // Try again in a couple of minutes
- setTimeout(mm.metricsStartup, 120000, addon, mm);
- }
- };
-
- // This event handles the event whereby a new version of the database needs to be created
- // Either one has not been created before, or a new version number has been submitted via the
- // window.indexedDB.open line above
- request.onupgradeneeded = function(event) {
- mm._KFLog.debug("Metrics indexedDB version upgrade started");
- var db = event.target.result;
-
- db.onerror = function(event) {
- let errMsg = "";
- if (event.target.error.name)
- errMsg += event.target.error.name + " - ";
- if (event.target.error && event.target.error.message)
- errMsg += event.target.error.message;
- mm._KFLog.error("Metrics error: " + errMsg);
- };
- //db.deleteObjectStore("keefox@chris.tomlinson-metrics-data");
-
- // Create an objectStore for this database
- var objectStore = db.createObjectStore("keefox@chris.tomlinson-metrics-messages", { keyPath:"id" });
- var objectStore2 = db.createObjectStore("keefox@chris.tomlinson-metrics-data", { keyPath:"key" });
-
- mm._KFLog.debug("Metrics indexedDB version upgrade finished");
- };
- request.onsuccess = function(event) {
- if (!request.result)
- return;
-
- mm.db = request.result;
- mm.db.onerror = function(event) {
- let errMsg = "";
- if (event.target.error.name)
- errMsg += event.target.error.name + " - ";
- if (event.target.error && event.target.error.message)
- errMsg += event.target.error.message;
- mm._KFLog.error("Metrics error: " + errMsg);
- };
-
- // Find the highest id number we used in the last session, if it's
- // null, we'll just reset to 1 (this data is not sent to the metrics server)
- let objectStore = mm.db.transaction("keefox@chris.tomlinson-metrics-messages")
- .objectStore("keefox@chris.tomlinson-metrics-messages");
- objectStore.openCursor(null, "prev").onsuccess = function(event) {
- var cursor = event.target.result;
- if (cursor) {
- mm.nextId = cursor.key + 1;
- } else
- {
- mm.nextId = 1;
- }
-
- // count how many entries we already have queued up. Should
- // usually be 0 or a small number but when the profile has
- // been unable to send data for many months or years, the
- // number of queued events could start to eat into
- // available disk space so we put a limit on the total
- // number of entries.
- let req = objectStore.count();
- req.onsuccess = function(evt) {
- if (evt.target.result >= 100000)
- {
- // Too many stored entries: 100000 = 25MB @ 0.25KB per message
- mm._KFLog.error("Too many metrics messages. No new messages will be recorded.");
-
- // overwrite last stored message to record this error state
- mm.nextId--;
- let msg = {
- "type": "event",
- "userId": mm.ii.userId,
- "sessionId": mm.ii.sessionId,
- "category": "error",
- "name": "indexedDBFull",
- "params": { "message": "Too many messages" },
- "ts": ISO8601DateUtils.create(new Date())
- };
- mm.set("message",JSON.stringify(msg));
-
- // Keep trying to clear the message queue backlog
- mm._KFLog.debug("Creating a metrics timer.");
- mm.metricsTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-
- mm.metricsTimer.initWithCallback(mm.metricsTimerHandler,
- 15000,
- Components.interfaces.nsITimer.TYPE_ONE_SHOT);
-
- // Don't do the usual session init. Therefore any
- // messages created during this session will be logged
- // into the temporary arrays but never get pushed
- // into the main message database.
- return;
- }
-
- // Get server versions (these are probably unknown to start with
- // but following a successful KeePassRPC connection, they will
- // be stored for use in the next session)
- mm.getApplicationMetadata(function () {
-
- // push initial session start message
- mm.startSession(function () {
- mm._KFLog.debug("Started a metrics session.");
-
- // We know we've sent the startSession message now so
- // we can push any events that were queued temporarilly
- mm.messagesReady = true;
-
- // If any messages have been sent to us while initialising, process them now
- for (let i=0; i < mm.messagesQueue.length; i++)
- mm.set("message", mm.messagesQueue[i].message);
- mm.messagesQueue = [];
-
- // Remove the old session data now it has been sent
- mm.resetAggregates(function () {
- mm.aggregatesReady = true;
-
- // If any aggregate values have been sent to us while initialising, evaluate them now
- for (let i=0; i < mm.aggregatesQueue.length; i++)
- mm.adjustAggregate(mm.aggregatesQueue[i].key, mm.aggregatesQueue[i].value);
- mm.aggregatesQueue = [];
-
- // Start a regular check for queued items that need pushing to the metrics server
- // For users that have disabled the user data component, this is technically
- // un-necessary unless they re-enable the collection during this session but
- // it's a very cheap operation so firing the timer for everyone makes things simpler
- mm._KFLog.debug("Creating a metrics timer.");
- mm.metricsTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
-
- mm.metricsTimer.initWithCallback(mm.metricsTimerHandler,
- 15000,
- Components.interfaces.nsITimer.TYPE_ONE_SHOT);
- });
- });
- });
- };
- };
- };
- };
-
- this.startSession = function (callback)
- {
- var mm = this;
- var cb = callback;
- let oldMetrics = this.calculatePreviousSessionMetrics(function (event) {
- mm.systemData = {
- "type": "sessionStart",
- "userId": mm.ii.userId,
- "sessionId": mm.ii.sessionId,
- "sessionStart": mm.ii.sessionStart,
- "previousSessionMetrics": mm.previousSessionMetrics,
- "browserType": mm.ii.browserType,
- "browserVersion": mm.ii.browserVersion,
- "OSType": mm.ii.OSType,
- "OSversion": mm.ii.OSversion,
- "locale": mm.ii.locale,
- "addonVersion": mm.ii.addonVersion,
- "netRuntimeVersion": mm.ii.netRuntimeVersion,
- "keePassVersion": mm.ii.keePassVersion
- };
- mm.set("message", JSON.stringify(mm.systemData), function () { cb(); });
- });
- };
-
- this.pushEvent = function(category, name, params, direct) // string, string, object of keys/vals, bool
- {
- // direct events never contain usage data
- if (!direct && Services.prefs.getBoolPref("extensions.keefox@chris.tomlinson.metricsUsageDisabled"))
- return;
-
- let msg = {
- "type": direct ? "direct" : "event",
- "userId": this.ii.userId,
- "sessionId": this.ii.sessionId,
- "category": category,
- "name": name,
- "params": params,
- "ts": ISO8601DateUtils.create(new Date())
- };
- // Repeat basic system data for direct feedback to aid analysis
- if (direct) {
- msg.systemData = JSON.parse(JSON.stringify(this.systemData)); //TODO:2: less hacky clone. https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/The_structured_clone_algorithm ?
- delete msg.systemData.previousSessionMetrics;
- delete msg.systemData.type;
- delete msg.systemData.userId;
- delete msg.systemData.sessionId;
- }
-
- let jMsg = JSON.stringify(msg);
- if (direct)
- this.deliverMessageDirect(jMsg);
- else if (this.messagesReady)
- this.set("message", jMsg);
- else
- this.messagesQueue.push( { "message": jMsg } );
- };
-
- this.calculatePreviousSessionMetrics = function (callback)
- {
- if (Services.prefs.getBoolPref("extensions.keefox@chris.tomlinson.metricsUsageDisabled"))
- {
- this.previousSessionMetrics = null;
- callback();
- return;
- }
- this.previousSessionMetrics = {};
- var mm = this;
- var cb = callback;
- this.get("databaseLoginCount", function (event) {
- if (event.target.result)
- mm.previousSessionMetrics.databaseLoginCount = event.target.result.value;
- mm.get("contextMenuItemsPressed", function (event) {
- if (event.target.result)
- mm.previousSessionMetrics.contextMenuItemsPressed = event.target.result.value;
- mm.get("keyboardShortcutsPressed", function (event) {
- if (event.target.result)
- mm.previousSessionMetrics.keyboardShortcutsPressed = event.target.result.value;
- mm.get("avgOpenDatabases", function (event) {
- if (event.target.result)
- mm.previousSessionMetrics.avgOpenDatabases = event.target.result.value; // when any are open (so >= 1)
- mm.get("copyUsername", function (event) {
- if (event.target.result)
- mm.previousSessionMetrics.copyUsername = event.target.result.value;
- mm.get("copyPassword", function (event) {
- if (event.target.result)
- mm.previousSessionMetrics.copyPassword = event.target.result.value;
- mm.get("copyOther", function (event) {
- if (event.target.result)
- mm.previousSessionMetrics.copyOther = event.target.result.value;
- mm.get("searchResultSelectedAll", function (event) {
- if (event.target.result)
- mm.previousSessionMetrics.searchResultSelectedAll = event.target.result.value;
- mm.get("searchResultSelectedCurrent", function (event) {
- if (event.target.result)
- mm.previousSessionMetrics.searchResultSelectedCurrent = event.target.result.value;
- mm.get("searchResultContextAll", function (event) {
- if (event.target.result)
- mm.previousSessionMetrics.searchResultContextAll = event.target.result.value;
- mm.get("searchResultContextCurrent", function (event) {
- if (event.target.result)
- mm.previousSessionMetrics.searchResultContextCurrent = event.target.result.value;
- mm.get("loginContextButton", function (event) {
- if (event.target.result)
- mm.previousSessionMetrics.loginContextButton = event.target.result.value;
- mm.get("pseudoFormCreated", function (event) {
- if (event.target.result)
- mm.previousSessionMetrics.pseudoFormCreated = event.target.result.value;
- //TODO:2: Try to convert to Promises so we can avoid infinite callback indentation
- mm._KFLog.debug("calculatePreviousSessionMetrics finished");
- if (cb) cb();
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
- // future: timing e.g. time logged in to database, time taken to decrypt messages, time from setup screen displayed to successful login , etc. - some of these might be more suited to specific event params
- }
-
- this.getApplicationMetadata = function (callback)
- {
- this.ii.keePassVersion = "unknown";
- this.ii.netRuntimeVersion = "unknown";
-
- var mm = this;
- var cb = callback;
- this.get("keePassVersion", function (event) {
- if (event.target.result)
- mm.ii.keePassVersion = event.target.result.value;
- mm.get("netRuntimeVersion", function (event) {
- if (event.target.result)
- mm.ii.netRuntimeVersion = event.target.result.value;
- if (cb) cb();
- });
- });
- };
-
- this.setApplicationMetadata = function (keePassVersion, netRuntimeVersion)
- {
- this.set("keePassVersion", keePassVersion);
- this.set("netRuntimeVersion", netRuntimeVersion);
- };
-
- this.set = function (key, value, callback)
- {
- if (!this.db) return;
-
- let cb = callback;
- let mm = this;
-
- if (key === "message")
- {
- var newMessage = { "id": mm.nextId++, "msg": value };
- var request = mm.db.transaction(["keefox@chris.tomlinson-metrics-messages"], "readwrite")
- .objectStore("keefox@chris.tomlinson-metrics-messages").put(newMessage);
- request.onsuccess = function(e) {
- if (cb) cb();
- }
- }
- else
- {
- var newItem = { "key": key, "value": value };
- var request = mm.db.transaction(["keefox@chris.tomlinson-metrics-data"], "readwrite")
- .objectStore("keefox@chris.tomlinson-metrics-data").put(newItem);
- request.onsuccess = function(e) {
- if (cb) cb();
- }
- }
- };
-
- // messages are always retrieved in batches from a cursor so this
- // only deals with specific data metrics
- this.get = function (key, callback)
- {
- return this.db.transaction(["keefox@chris.tomlinson-metrics-data"], "readonly")
- .objectStore("keefox@chris.tomlinson-metrics-data").get(key).onsuccess = callback;
- };
-
- // Grab the messages waiting to be sent to the remote server
- this.processQueue = function ()
- {
- if (!this.db) return;
-
- let completeMessage = "";
- var objectStore = this.db.transaction("keefox@chris.tomlinson-metrics-messages")
- .objectStore("keefox@chris.tomlinson-metrics-messages");
- let mm = this;
-
- let cursorReq = objectStore.openCursor();
- cursorReq.onsuccess = function(event) {
- var cursor = event.target.result;
- if (cursor) {
- // Don't append exceptionally large messages to the current message
- // string - we'll leave it for next time and send it on its own
- if (completeMessage !== "" && completeMessage.length + cursor.value.msg.length > 250000)
- {
- try {
- mm.deliverMessage(completeMessage);
- } catch (e) {
- mm._KFLog.warn("Metrics processQueue failed to deliverMessage (large). We'll try again later.");
- }
- // Don't respawn here since deliverMessage should do that.
- // Stop iterating this cursor
- return;
- }
-
- mm.lastSentAttemptId = cursor.value.id;
- completeMessage += cursor.value.msg;
- cursor.continue();
- }
- else {
- // We've reached the end of the cursor, whether we
- // found any results is another matter...
- if (completeMessage.length > 0)
- mm.deliverMessage(completeMessage);
- else
- mm.metricsTimerRespawn();
- }
- };
-
- cursorReq.onerror = function(event) {
- // Try again later if something forced us to abort
- mm._KFLog.warn("Metrics processQueue failed to iterate cursor (" + cursorReq.error.name + ").");
- if (cursorReq.error.name == "AbortError") {
- mm.metricsTimerRespawn(60);
- }
- };
-
- };
-
- // Start the timer ready for the next queue processing operation
- this.metricsTimerRespawn = function (retry)
- {
- try {
- let DEFAULT_DELAY = 15;
- let secondsUntilNextProcess = DEFAULT_DELAY;
-
- // retry should have been set on failure but may also be set by server to manage load
- if (retry)
- { //TODO:1.6: Don't just listen to the server - do something more useful
- secondsUntilNextProcess = retry;
- if (secondsUntilNextProcess < DEFAULT_DELAY)
- secondsUntilNextProcess = DEFAULT_DELAY;
- }
-
- var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
- .getService(Ci.nsIWindowMediator);
- var window = wm.getMostRecentWindow("navigator:browser") ||
- wm.getMostRecentWindow("mail:3pane");
- var mm = window.keefox_org.metricsManager;
-
- mm.metricsTimer.initWithCallback(mm.metricsTimerHandler,
- secondsUntilNextProcess * 1000,
- Components.interfaces.nsITimer.TYPE_ONE_SHOT);
- } catch (e)
- {
- //TODO:1.6: Review need for this try/catch
- // Do nothing (can't be sure if we can log safely but this is just a test anyway for the moment...
- }
- };
-
- // Just process the message queue when the timer fires
- this.metricsTimerHandler = {
- notify: function(timer) {
- var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
- .getService(Ci.nsIWindowMediator);
- var window = wm.getMostRecentWindow("navigator:browser") ||
- wm.getMostRecentWindow("mail:3pane");
- var mm = window.keefox_org.metricsManager;
- mm.processQueue();
- }
- };
-
- this.createXMLHttpRequest = function () {
- let request;
- try {
- // Enable an anonymous request (no cookies). The only feasible risk from not
- // doing this is if someone takes control of the KeeFox metrics server and
- // starts parsing the Google Analytics tracking cookies that are used
- // elsewhere on the keefox.org domain. They'd also have to intercept the
- // analytics cookies on the way to the KeeFox website to have any hope of
- // linking activity on the keefox site to the metrics data. Google is obviously
- // best placed to initiate this attack but it's still going to be very
- // difficult for them and will provide no tangible benefit to them (or
- // any other attacker). Still, since we can, let's protect against the possibility.
- request = new XMLHttpRequest({ mozAnon: true });
- } catch (e) {
- // Protecting against future removal of mozAnon parameter
- request = new XMLHttpRequest();
- }
- return request;
- };
-
- // Send a message containing one or more metrics messages
- this.deliverMessage = function (msg)
- {
- var mm = this;
-
- // No need to debug metric data in normal circumstances, only dev work
- //this._KFLog.debug("METRIC to be sent: " + msg);
- this._KFLog.debug("metrics being sent");
-
- try{
- var request = this.createXMLHttpRequest();
- request.open("POST", this.url, true);
- request.addEventListener("load", function(event) {
- // Note our success position in the queue so we can remove the old ones
- mm.lastSentId = mm.lastSentAttemptId;
-
- // Remove the old messages
- var objectStore = mm.db.transaction("keefox@chris.tomlinson-metrics-messages","readwrite")
- .objectStore("keefox@chris.tomlinson-metrics-messages");
-
- let cursorReq = objectStore.openCursor(mm.IDBKeyRange.upperBound(mm.lastSentId));
- cursorReq.onsuccess = function(event) {
- var cursor = event.target.result;
- if (cursor) {
- cursor.delete();
- // This seemed to work too but maybe susceptible to concurrency bugs? objectStore.delete(cursor.primaryKey);
- cursor.continue();
- } else
- {
- mm.metricsTimerRespawn(15);
- }
- };
- cursorReq.onerror = function(event) {
- // Try again later if something forced us to abort
- mm._KFLog.warn("Metrics deliverMessage failed to iterate cursor (" + cursorReq.error.name + ").");
- if (cursorReq.error.name == "AbortError") {
- mm.metricsTimerRespawn(60);
- }
- };
-
- });
- request.addEventListener("error", function(event) {
- mm._KFLog.debug("Metrics could not be sent.");
- mm.metricsTimerRespawn();
- });
- request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
-
- // We'll set a timeout to prevent the metrics collection
- // hanging forever following a single dodgy connection.
-
- request.timeout = mm.nextRequestTimeout;
- request.ontimeout = function(event) {
- if (mm.nextRequestTimeout >= 1920000) { // 32 minutes
- mm._KFLog.info("Metrics timeout. Can't increase any higher. There is probably an internet connection fault.");
- } else {
- mm.nextRequestTimeout = mm.nextRequestTimeout * 2;
- mm._KFLog.debug("Metrics timeout. Increasing to " + mm.nextRequestTimeout + "ms");
- }
- mm.metricsTimerRespawn();
- };
- request.send(msg);
- } catch (ex)
- {
- mm._KFLog.error("Metrics error. Could not send because: " + ex);
- mm.metricsTimerRespawn(60);
- }
- };
-
- // Send a message containing one or more metrics messages directly to the metrics
- // server, out of sync with the usual regular message interval.
- this.deliverMessageDirect = function (msg) {
- // No need to debug metric data in normal circumstances, only dev work
- //this._KFLog.debug("METRIC to be sent directly: " + msg);
- this._KFLog.debug("metrics being sent directly");
-
- try {
- var request = this.createXMLHttpRequest();
- request.open("POST", this.url, true);
- request.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
- request.timeout = this.nextRequestTimeout;
- request.send(msg);
- } catch (ex) {
- this._KFLog.error("Metrics error. Could not send directly because: " + ex);
- }
- };
-
- // all aggregate data will be reset at the start of each session. Aggregation
- // across longer periods of time can still be done in some post-processing
- // of the received data but this short aggregation period will allow us to
- // spot changes quickly.
- this.resetAggregates = function (callback)
- {
- // We do this even if aggregate data collection has been disabled by
- // the user because they might re-enable it during this session
- let cb = callback;
- let mm = this;
- this._KFLog.debug("resetAggregates started");
- this.set("databaseLoginCount",{ value: 0.0 }, function () {
- mm.set("contextMenuItemsPressed",{ value: 0.0 }, function () {
- mm.set("keyboardShortcutsPressed",{ value: 0.0 }, function () {
- mm.set("avgOpenDatabases",{ avg: 0.0, count: 0 }, function () {
- mm.set("copyUsername",{ value: 0.0 }, function () {
- mm.set("copyPassword",{ value: 0.0 }, function () {
- mm.set("copyOther",{ value: 0.0 }, function () {
- mm.set("searchResultSelectedAll", { value: 0.0 }, function () {
- mm.set("searchResultSelectedCurrent", { value: 0.0 }, function () {
- mm.set("searchResultContextAll", { value: 0.0 }, function () {
- mm.set("searchResultContextCurrent", { value: 0.0 }, function () {
- mm.set("loginContextButton", { value: 0.0 }, function () {
- mm.set("pseudoFormCreated", { value: 0.0 }, function () {
- mm.aggregatesReady = true;
- mm._KFLog.debug("resetAggregates finished");
- if (cb) cb();
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
- });
- };
-
- this.adjustAggregate = function (key, value)
- {
- if (Services.prefs.getBoolPref("extensions.keefox@chris.tomlinson.metricsUsageDisabled"))
- return;
-
- var mm = this;
- if (this.aggregatesReady)
- {
- // We might log two new aggregate data points in a short period of time
- // and the async behaviour of indexedDB means that some of these data
- // points may be missed.
- // This might be particularly likely during startup since we have to just
- // fire all the queued events as quickly as possible to avoid race
- // conditions with newly created data points.
- // It should be possible to work around this with the co-operation of all
- // callers but I think it will be too complicated to be worthwhile now.
- this.get(key, function (event)
- {
- let result = event.target.result;
- let agg = result.value;
- if (agg.value != undefined)
- {
- if (agg.value > 0)
- agg.value = agg.value + value;
- else
- agg.value = value;
- } else if (agg.avg != undefined)
- {
- let newCount = agg.count + 1.0;
- let total = agg.avg * agg.count + value;
- agg.avg = total/newCount;
- agg.count = newCount;
- }
- mm.set(key, agg);
- }
- );
- } else
- {
- this.aggregatesQueue.push( { "key": key, "value": value } );
- }
- };
-
-}
-
-var metricsManager = new mm;
-
-let globalMM = Cc["@mozilla.org/globalmessagemanager;1"].getService(Ci.nsIMessageListenerManager);
-globalMM.addMessageListener("keefox:metrics-pushEvent", function (message) {
- metricsManager.pushEvent(message.data.category, message.data.name, message.data.params); });
-globalMM.addMessageListener("keefox:metrics-adjustAggregate", function (message) {
- metricsManager.adjustAggregate(message.data.key, message.data.value); });
\ No newline at end of file