--- a/mobile/android/components/LoginManagerPrompter.js
+++ b/mobile/android/components/LoginManagerPrompter.js
@@ -5,16 +5,25 @@
const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
+/* Constants for password prompt telemetry.
+ * Mirrored in nsLoginManagerPrompter.js */
+const PROMPT_RES_SAVE = 1;
+const PROMPT_RES_UPDATE = 2;
+const PROMPT_RES_NOTNOW = 3;
+const PROMPT_RES_NEVER = 4;
+const PROMPT_RES_DISMISS = 5;
+const PROMPT_RES_REMOVE = 6;
+
/* ==================== LoginManagerPrompter ==================== */
/*
* LoginManagerPrompter
*
* Implements interfaces for prompting the user to enter/save/change auth info.
*
* nsILoginManagerPrompter: Used by Login Manager for saving/changing logins
* found in HTML forms.
@@ -170,27 +179,31 @@ LoginManagerPrompter.prototype = {
} else {
notificationText = this._getLocalizedString("savePasswordNoUser", [displayHost]);
}
// The callbacks in |buttons| have a closure to access the variables
// in scope here; set one to |this._pwmgr| so we can get back to pwmgr
// without a getService() call.
var pwmgr = this._pwmgr;
+ let promptHistogram = Services.telemetry.getHistogramById("PWMGR_PROMPT_SELECTION_STATE");
+
var buttons = [
{
label: this._getLocalizedString("saveButton"),
callback: function() {
pwmgr.addLogin(aLogin);
+ promptHistogram.add(PROMPT_RES_SAVE);
}
},
{
label: this._getLocalizedString("dontSaveButton"),
callback: function() {
+ promptHistogram.add(PROMPT_RES_NOTNOW);
// Don't set a permanent exception
}
}
];
this._showLoginNotification("password-save", notificationText, buttons);
},
@@ -220,27 +233,30 @@ LoginManagerPrompter.prototype = {
} else {
notificationText = this._getLocalizedString("updatePasswordNoUser");
}
// The callbacks in |buttons| have a closure to access the variables
// in scope here; set one to |this._pwmgr| so we can get back to pwmgr
// without a getService() call.
var self = this;
+ let promptHistogram = Services.telemetry.getHistogramById("PWMGR_PROMPT_SELECTION_STATE");
var buttons = [
{
label: this._getLocalizedString("updateButton"),
callback: function() {
self._updateLogin(aOldLogin, aNewPassword);
+ promptHistogram.add(PROMPT_RES_UPDATE);
}
},
{
label: this._getLocalizedString("dontUpdateButton"),
callback: function() {
+ promptHistogram.add(PROMPT_RES_NOTNOW);
// do nothing
}
}
];
this._showLoginNotification("password-change", notificationText, buttons);
},
--- a/toolkit/components/passwordmgr/nsLoginManagerPrompter.js
+++ b/toolkit/components/passwordmgr/nsLoginManagerPrompter.js
@@ -8,16 +8,25 @@ const Cc = Components.classes;
const Ci = Components.interfaces;
const Cr = Components.results;
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
Components.utils.import("resource://gre/modules/Services.jsm");
Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
Components.utils.import("resource://gre/modules/SharedPromptUtils.jsm");
+/* Constants for password prompt telemetry.
+ * Mirrored in mobile/android/components/LoginManagerPrompter.js */
+const PROMPT_RES_SAVE = 1;
+const PROMPT_RES_UPDATE = 2;
+const PROMPT_RES_NOTNOW = 3;
+const PROMPT_RES_NEVER = 4;
+const PROMPT_RES_DISMISS = 5;
+const PROMPT_RES_REMOVE = 6;
+
/*
* LoginManagerPromptFactory
*
* Implements nsIPromptFactory
*
* Invoked by [toolkit/components/prompts/src/nsPrompter.js]
*/
function LoginManagerPromptFactory() {
@@ -465,16 +474,17 @@ LoginManagerPrompter.prototype = {
var newLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
newLogin.init(hostname, null, realm, username,
aPassword.value, "", "");
this.log("New login seen for " + realm);
this._pwmgr.addLogin(newLogin);
+ this.log("2: New login added");
}
return ok;
},
/* ---------- nsIAuthPrompt helpers ---------- */
@@ -614,20 +624,24 @@ LoginManagerPrompter.prototype = {
this.log("New login seen for " + username +
" @ " + hostname + " (" + httpRealm + ")");
var newLogin = Cc["@mozilla.org/login-manager/loginInfo;1"].
createInstance(Ci.nsILoginInfo);
newLogin.init(hostname, null, httpRealm,
username, password, "", "");
var notifyObj = this._getPopupNote() || notifyBox;
- if (notifyObj)
+ if (notifyObj) {
this._showSaveLoginNotification(notifyObj, newLogin);
- else
+ this.log("3a: showing notification");
+ }
+ else {
this._pwmgr.addLogin(newLogin);
+ this.log("3b: New login added");
+ }
} else if (password != selectedLogin.password) {
this.log("Updating password for " + username +
" @ " + hostname + " (" + httpRealm + ")");
var notifyObj = this._getPopupNote() || notifyBox;
if (notifyObj)
this._showChangeLoginNotification(notifyObj,
@@ -767,30 +781,37 @@ LoginManagerPrompter.prototype = {
newBar.timeout = Date.now() + 20000; // 20 seconds
if (oldBar) {
this.log("(...and removing old " + aName + " notification bar)");
aNotifyBox.removeNotification(oldBar);
}
},
+ _notificationCallback : function (aEvent) {
+ switch(aEvent) {
+ case "dismissed":
+ this.log("*** dismiss");
+ Services.telemetry.getHistogramById("PWMGR_PROMPT_SELECTION_STATE").add(PROMPT_RES_DISMISS);
+ break;
+ }
+ },
/*
* _showSaveLoginNotification
*
* Displays a notification bar or a popup notification, to allow the user
* to save the specified login. This allows the user to see the results of
* their login, and only save a login which they know worked.
*
* @param aNotifyObj
* A notification box or a popup notification.
*/
_showSaveLoginNotification : function (aNotifyObj, aLogin) {
-
- // Ugh. We can't use the strings from the popup window, because they
+ // Ugh. We can't use the strings from the popup window, because they
// have the access key marked in the string (eg "Mo&zilla"), along
// with some weird rules for handling access keys that do not occur
// in the string, for L10N. See commonDialog.js's setLabelForNode().
var neverButtonText =
this._getLocalizedString("notifyBarNeverRememberButtonText");
var neverButtonAccessKey =
this._getLocalizedString("notifyBarNeverRememberButtonAccessKey");
var rememberButtonText =
@@ -811,78 +832,93 @@ LoginManagerPrompter.prototype = {
[displayHost]);
}
// The callbacks in |buttons| have a closure to access the variables
// in scope here; set one to |this._pwmgr| so we can get back to pwmgr
// without a getService() call.
var pwmgr = this._pwmgr;
+ let promptHistogram = Services.telemetry.getHistogramById("PWMGR_PROMPT_SELECTION_STATE");
+ let self = this;
+
// Notification is a PopupNotification
if (aNotifyObj == this._getPopupNote()) {
// "Remember" button
var mainAction = {
label: rememberButtonText,
accessKey: rememberButtonAccessKey,
callback: function(aNotifyObj, aButton) {
+ self.log("*** save1");
+ promptHistogram.add(PROMPT_RES_SAVE);
pwmgr.addLogin(aLogin);
browser.focus();
}
};
var secondaryActions = [
// "Never for this site" button
{
label: neverButtonText,
accessKey: neverButtonAccessKey,
callback: function(aNotifyObj, aButton) {
+ self.log("*** never1");
+ promptHistogram.add(PROMPT_RES_NEVER);
pwmgr.setLoginSavingEnabled(aLogin.hostname, false);
browser.focus();
}
}
];
var { browser } = this._getNotifyWindow();
aNotifyObj.show(browser, "password-save", notificationText,
"password-notification-icon", mainAction,
secondaryActions, { timeout: Date.now() + 10000,
- persistWhileVisible: true });
+ persistWhileVisible: true,
+ eventCallback: this._notificationCallback.bind(this) });
} else {
var notNowButtonText =
this._getLocalizedString("notifyBarNotNowButtonText");
var notNowButtonAccessKey =
this._getLocalizedString("notifyBarNotNowButtonAccessKey");
var buttons = [
// "Remember" button
{
label: rememberButtonText,
accessKey: rememberButtonAccessKey,
popup: null,
callback: function(aNotifyObj, aButton) {
+ self.log("*** save2");
+ promptHistogram.add(PROMPT_RES_SAVE);
pwmgr.addLogin(aLogin);
}
},
// "Never for this site" button
{
label: neverButtonText,
accessKey: neverButtonAccessKey,
popup: null,
callback: function(aNotifyObj, aButton) {
+ self.log("*** never2");
+ promptHistogram.add(PROMPT_RES_NEVER);
pwmgr.setLoginSavingEnabled(aLogin.hostname, false);
}
},
// "Not now" button
{
label: notNowButtonText,
accessKey: notNowButtonAccessKey,
popup: null,
- callback: function() { /* NOP */ }
+ callback: function() {
+ self.log("*** notnow2");
+ promptHistogram.add(PROMPT_RES_NOTNOW);
+ }
}
];
this._showLoginNotification(aNotifyObj, "password-save",
notificationText, buttons);
}
},
@@ -918,16 +954,17 @@ LoginManagerPrompter.prototype = {
/*
* _showSaveLoginDialog
*
* Called when we detect a new login in a form submission,
* asks the user what to do.
*
*/
_showSaveLoginDialog : function (aLogin) {
+ this.log("====== 4: showSaveLoginDialog ======");
const buttonFlags = Ci.nsIPrompt.BUTTON_POS_1_DEFAULT +
(Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_0) +
(Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_1) +
(Ci.nsIPrompt.BUTTON_TITLE_IS_STRING * Ci.nsIPrompt.BUTTON_POS_2);
var displayHost = this._getShortDisplayHost(aLogin.hostname);
var dialogText;
@@ -1018,57 +1055,64 @@ LoginManagerPrompter.prototype = {
var changeButtonAccessKey =
this._getLocalizedString("notifyBarUpdateButtonAccessKey");
// The callbacks in |buttons| have a closure to access the variables
// in scope here; set one to |this._pwmgr| so we can get back to pwmgr
// without a getService() call.
var self = this;
+ let promptHistogram = Services.telemetry.getHistogramById("PWMGR_PROMPT_SELECTION_STATE");
// Notification is a PopupNotification
if (aNotifyObj == this._getPopupNote()) {
// "Yes" button
var mainAction = {
label: changeButtonText,
accessKey: changeButtonAccessKey,
popup: null,
callback: function(aNotifyObj, aButton) {
self._updateLogin(aOldLogin, aNewPassword);
+ self.log("*** update3");
+ promptHistogram.add(PROMPT_RES_UPDATE);
}
};
var { browser } = this._getNotifyWindow();
aNotifyObj.show(browser, "password-change", notificationText,
"password-notification-icon", mainAction,
null, { timeout: Date.now() + 10000,
- persistWhileVisible: true });
+ persistWhileVisible: true,
+ eventCallback: this._notificationCallback.bind(this) });
} else {
var dontChangeButtonText =
this._getLocalizedString("notifyBarDontChangeButtonText");
var dontChangeButtonAccessKey =
this._getLocalizedString("notifyBarDontChangeButtonAccessKey");
var buttons = [
// "Yes" button
{
label: changeButtonText,
accessKey: changeButtonAccessKey,
popup: null,
callback: function(aNotifyObj, aButton) {
+ self.log("*** update4");
+ promptHistogram.add(PROMPT_RES_UPDATE);
self._updateLogin(aOldLogin, aNewPassword);
}
},
// "No" button
{
label: dontChangeButtonText,
accessKey: dontChangeButtonAccessKey,
popup: null,
callback: function(aNotifyObj, aButton) {
- // do nothing
+ self.log("*** notnow4");
+ promptHistogram.add(PROMPT_RES_NOTNOW);
}
}
];
this._showLoginNotification(aNotifyObj, "password-change",
notificationText, buttons);
}
},
--- a/toolkit/components/telemetry/Histograms.json
+++ b/toolkit/components/telemetry/Histograms.json
@@ -7332,16 +7332,22 @@
},
"PWMGR_LOGIN_LAST_USED_DAYS": {
"expires_in_version": "never",
"kind": "exponential",
"high": 750,
"n_buckets" : 40,
"description": "Time in days each saved login was last used"
},
+ "PWMGR_PROMPT_SELECTION_STATE": {
+ "expires_in_version": "never",
+ "kind": "enumerated",
+ "n_values": 10,
+ "description": "Selection made by user through prompt for creating or modifying a login"
+ },
"PWMGR_SAVING_ENABLED": {
"expires_in_version": "never",
"kind": "boolean",
"description": "Number of users who have password saving on globally"
},
"PWMGR_USERNAME_PRESENT": {
"expires_in_version": "never",
"kind": "boolean",