mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 22:05:44 +00:00
Bug 1148026 - Add a skeleton of the login fill doorhanger. r=MattN
--HG-- extra : rebase_source : 83617f2f083b23ca96066f137cc605a5c3623e4f extra : amend_source : da993ee2338b78a4fab692b3fd5a459c39506690
This commit is contained in:
parent
a4a2afd118
commit
dcb8d107c1
@ -773,6 +773,14 @@ window[chromehidden~="toolbar"] toolbar:not(#nav-bar):not(#TabsToolbar):not(#pri
|
||||
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#click-to-play-plugins-notification");
|
||||
}
|
||||
|
||||
#password-fill-notification {
|
||||
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#password-fill-notification");
|
||||
}
|
||||
|
||||
.login-fill-item {
|
||||
-moz-binding: url("chrome://passwordmgr/content/login.xml#login");
|
||||
}
|
||||
|
||||
.plugin-popupnotification-centeritem {
|
||||
-moz-binding: url("chrome://browser/content/urlbarBindings.xml#plugin-popupnotification-center-item");
|
||||
}
|
||||
|
@ -62,6 +62,13 @@
|
||||
</popupnotificationcontent>
|
||||
</popupnotification>
|
||||
|
||||
<vbox id="login-fill-doorhanger" hidden="true">
|
||||
<description id="login-fill-testing"
|
||||
value="Thanks for testing the login fill doorhanger!"/>
|
||||
<textbox id="login-fill-filter"/>
|
||||
<richlistbox id="login-fill-list"/>
|
||||
</vbox>
|
||||
|
||||
#ifdef E10S_TESTING_ONLY
|
||||
<popupnotification id="enable-e10s-notification" hidden="true">
|
||||
<popupnotificationcontent orient="vertical"/>
|
||||
|
@ -2773,6 +2773,16 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
</handlers>
|
||||
</binding>
|
||||
|
||||
<!-- This is the XBL notification definition for the login fill doorhanger,
|
||||
which is empty because the actual panel is not implemented inside an XBL
|
||||
binding, but made of elements added to the notification panel. This
|
||||
allows accessing the full structure while the panel is hidden. -->
|
||||
<binding id="password-fill-notification" extends="chrome://global/content/bindings/notification.xml#popup-notification">
|
||||
<content>
|
||||
<children/>
|
||||
</content>
|
||||
</binding>
|
||||
|
||||
<binding id="splitmenu">
|
||||
<content>
|
||||
<xul:hbox anonid="menuitem" flex="1"
|
||||
|
@ -1862,6 +1862,7 @@ toolbarbutton.chevron > .toolbarbutton-icon {
|
||||
%include ../shared/devtools/commandline.inc.css
|
||||
%include ../shared/plugin-doorhanger.inc.css
|
||||
%include ../shared/badcontent-doorhanger.inc.css
|
||||
%include ../shared/login-doorhanger.inc.css
|
||||
|
||||
%include downloads/indicator.css
|
||||
|
||||
|
@ -3895,6 +3895,7 @@ notification[value="loop-sharing-notification"] .messageImage {
|
||||
%include ../shared/devtools/commandline.inc.css
|
||||
%include ../shared/plugin-doorhanger.inc.css
|
||||
%include ../shared/badcontent-doorhanger.inc.css
|
||||
%include ../shared/login-doorhanger.inc.css
|
||||
|
||||
%include downloads/indicator.css
|
||||
|
||||
|
19
browser/themes/shared/login-doorhanger.inc.css
Normal file
19
browser/themes/shared/login-doorhanger.inc.css
Normal file
@ -0,0 +1,19 @@
|
||||
#login-fill-testing {
|
||||
color: #b33;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#login-fill-list {
|
||||
border: 1px solid black;
|
||||
max-height: 20em;
|
||||
}
|
||||
|
||||
.login-hostname {
|
||||
margin: 4px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.login-username {
|
||||
margin: 4px;
|
||||
color: #888;
|
||||
}
|
@ -2456,6 +2456,7 @@ notification[value="loop-sharing-notification"] .messageImage {
|
||||
%include ../shared/devtools/commandline.inc.css
|
||||
%include ../shared/plugin-doorhanger.inc.css
|
||||
%include ../shared/badcontent-doorhanger.inc.css
|
||||
%include ../shared/login-doorhanger.inc.css
|
||||
|
||||
%include downloads/indicator.css
|
||||
|
||||
|
244
toolkit/components/passwordmgr/LoginDoorhangers.jsm
Normal file
244
toolkit/components/passwordmgr/LoginDoorhangers.jsm
Normal file
@ -0,0 +1,244 @@
|
||||
/* 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";
|
||||
|
||||
this.EXPORTED_SYMBOLS = [
|
||||
"LoginDoorhangers",
|
||||
];
|
||||
|
||||
const { classes: Cc, interfaces: Ci, utils: Cu, results: Cr } = Components;
|
||||
|
||||
Cu.import("resource://gre/modules/Services.jsm");
|
||||
|
||||
const XUL_NS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
|
||||
|
||||
this.LoginDoorhangers = {};
|
||||
|
||||
/**
|
||||
* Doorhanger for selecting and filling logins.
|
||||
*
|
||||
* @param {Object} properties
|
||||
* Properties from this object will be applied to the new instance.
|
||||
*/
|
||||
this.LoginDoorhangers.FillDoorhanger = function (properties) {
|
||||
this.onFilterInput = this.onFilterInput.bind(this);
|
||||
this.onListDblClick = this.onListDblClick.bind(this);
|
||||
this.onListKeyPress = this.onListKeyPress.bind(this);
|
||||
|
||||
this.filterString = properties.filterString;
|
||||
|
||||
if (properties.browser) {
|
||||
this.browser = properties.browser;
|
||||
}
|
||||
};
|
||||
|
||||
this.LoginDoorhangers.FillDoorhanger.prototype = {
|
||||
/**
|
||||
* Whether the elements for this doorhanger are currently in the document.
|
||||
*/
|
||||
bound: false,
|
||||
|
||||
/**
|
||||
* Associates the doorhanger with its browser. When the tab associated to this
|
||||
* browser is selected, the anchor icon for the doorhanger will appear.
|
||||
*
|
||||
* The browser may change during the lifetime of the doorhanger, in case the
|
||||
* web page is moved to a different chrome window by the swapDocShells method.
|
||||
*/
|
||||
set browser(browser) {
|
||||
this._browser = browser;
|
||||
|
||||
let doorhanger = this;
|
||||
let PopupNotifications = this.chomeDocument.defaultView.PopupNotifications;
|
||||
let notification = PopupNotifications.show(
|
||||
browser,
|
||||
"password-fill",
|
||||
"",
|
||||
"password-notification-icon",
|
||||
null,
|
||||
null,
|
||||
{
|
||||
dismissed: true,
|
||||
persistWhileVisible: true,
|
||||
eventCallback: function (topic, otherBrowser) {
|
||||
switch (topic) {
|
||||
case "shown":
|
||||
// Since we specified the "dismissed" option, this event will only
|
||||
// be called after the "show" method returns, so the reference to
|
||||
// "this.notification" will be available at this point.
|
||||
doorhanger.bound = true;
|
||||
doorhanger.bind();
|
||||
break;
|
||||
|
||||
case "dismissed":
|
||||
case "removed":
|
||||
if (doorhanger.bound) {
|
||||
doorhanger.unbind();
|
||||
}
|
||||
break;
|
||||
|
||||
case "swapping":
|
||||
this._browser = otherBrowser;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
this.notification = notification;
|
||||
notification.doorhanger = this;
|
||||
},
|
||||
get browser() {
|
||||
return this._browser;
|
||||
},
|
||||
_browser: null,
|
||||
|
||||
/**
|
||||
* DOM document to which the doorhanger is currently associated.
|
||||
*
|
||||
* This may change during the lifetime of the doorhanger, in case the web page
|
||||
* is moved to a different chrome window by the swapDocShells method.
|
||||
*/
|
||||
get chomeDocument() {
|
||||
return this.browser.ownerDocument;
|
||||
},
|
||||
|
||||
/**
|
||||
* Hides this notification, if the notification panel is currently open.
|
||||
*/
|
||||
hide() {
|
||||
let PopupNotifications = this.chomeDocument.defaultView.PopupNotifications;
|
||||
if (PopupNotifications.isPanelOpen) {
|
||||
PopupNotifications.panel.hidePopup();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Removes the doorhanger from the browser.
|
||||
*/
|
||||
remove() {
|
||||
this.notification.remove();
|
||||
},
|
||||
|
||||
/**
|
||||
* Binds this doorhanger to its UI controls.
|
||||
*/
|
||||
bind() {
|
||||
this.element = this.chomeDocument.getElementById("login-fill-doorhanger");
|
||||
this.list = this.chomeDocument.getElementById("login-fill-list");
|
||||
this.filter = this.chomeDocument.getElementById("login-fill-filter");
|
||||
|
||||
this.filter.setAttribute("value", this.filterString);
|
||||
|
||||
this.refreshList();
|
||||
|
||||
this.filter.addEventListener("input", this.onFilterInput);
|
||||
this.list.addEventListener("dblclick", this.onListDblClick);
|
||||
this.list.addEventListener("keypress", this.onListKeyPress);
|
||||
|
||||
// Move the main element to the notification panel for displaying.
|
||||
this.notification.owner.panel.firstElementChild.appendChild(this.element);
|
||||
this.element.hidden = false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Unbinds this doorhanger from its UI controls.
|
||||
*/
|
||||
unbind() {
|
||||
this.filter.removeEventListener("input", this.onFilterInput);
|
||||
this.list.removeEventListener("dblclick", this.onListDblClick);
|
||||
this.list.removeEventListener("keypress", this.onListKeyPress);
|
||||
|
||||
this.clearList();
|
||||
|
||||
// Place the element back in the document for the next time we need it.
|
||||
this.element.hidden = true;
|
||||
this.chomeDocument.getElementById("mainPopupSet").appendChild(this.element);
|
||||
},
|
||||
|
||||
/**
|
||||
* User-editable string used to filter the list of all logins.
|
||||
*/
|
||||
filterString: "",
|
||||
|
||||
/**
|
||||
* Handles text changes in the filter textbox.
|
||||
*/
|
||||
onFilterInput() {
|
||||
this.filterString = this.filter.value;
|
||||
this.refreshList();
|
||||
},
|
||||
|
||||
/**
|
||||
* Rebuilds the list of logins.
|
||||
*/
|
||||
refreshList() {
|
||||
this.clearList();
|
||||
|
||||
let formLogins = Services.logins.findLogins({}, "", "", null);
|
||||
let filterToUse = this.filterString.trim().toLowerCase();
|
||||
if (filterToUse) {
|
||||
formLogins = formLogins.filter(login => {
|
||||
return login.hostname.toLowerCase().indexOf(filterToUse) != -1 ||
|
||||
login.username.toLowerCase().indexOf(filterToUse) != -1 ;
|
||||
});
|
||||
}
|
||||
|
||||
for (let { hostname, username } of formLogins) {
|
||||
let item = this.chomeDocument.createElementNS(XUL_NS, "richlistitem");
|
||||
item.classList.add("login-fill-item");
|
||||
item.setAttribute("hostname", hostname);
|
||||
item.setAttribute("username", username);
|
||||
this.list.appendChild(item);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Clears the list of logins.
|
||||
*/
|
||||
clearList() {
|
||||
while (this.list.firstChild) {
|
||||
this.list.removeChild(this.list.firstChild);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Handles the action associated to a login item.
|
||||
*/
|
||||
onListDblClick(event) {
|
||||
if (event.button != 0 || !this.list.selectedItem) {
|
||||
return;
|
||||
}
|
||||
this.fillLogin();
|
||||
},
|
||||
onListKeyPress(event) {
|
||||
if (event.keyCode != Ci.nsIDOMKeyEvent.DOM_VK_RETURN ||
|
||||
!this.list.selectedItem) {
|
||||
return;
|
||||
}
|
||||
this.fillLogin();
|
||||
},
|
||||
fillLogin() {
|
||||
this.hide();
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves an existing FillDoorhanger associated with a browser, or null if an
|
||||
* associated doorhanger of that type cannot be found.
|
||||
*
|
||||
* @param An object with the following properties:
|
||||
* {
|
||||
* browser:
|
||||
* The <browser> element to which the doorhanger is associated.
|
||||
* }
|
||||
*/
|
||||
this.LoginDoorhangers.FillDoorhanger.find = function ({ browser }) {
|
||||
let PopupNotifications = browser.ownerDocument.defaultView.PopupNotifications;
|
||||
let notification = PopupNotifications.getNotification("password-fill",
|
||||
browser);
|
||||
return notification && notification.doorhanger;
|
||||
};
|
22
toolkit/components/passwordmgr/content/login.xml
Normal file
22
toolkit/components/passwordmgr/content/login.xml
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0"?>
|
||||
<!-- 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/. -->
|
||||
|
||||
<!DOCTYPE bindings SYSTEM "chrome://passwordmgr/locale/passwordManager.dtd">
|
||||
|
||||
<bindings id="login-bindings"
|
||||
xmlns="http://www.mozilla.org/xbl"
|
||||
xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
|
||||
xmlns:xbl="http://www.mozilla.org/xbl">
|
||||
|
||||
<binding id="login"
|
||||
extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
|
||||
<content orient="vertical">
|
||||
<xul:label class="login-hostname" crop="end"
|
||||
xbl:inherits="value=hostname"/>
|
||||
<xul:label class="login-username" crop="end"
|
||||
xbl:inherits="value=username"/>
|
||||
</content>
|
||||
</binding>
|
||||
</bindings>
|
@ -4,6 +4,7 @@
|
||||
|
||||
toolkit.jar:
|
||||
% content passwordmgr %content/passwordmgr/
|
||||
content/passwordmgr/login.xml (content/login.xml)
|
||||
* content/passwordmgr/passwordManager.xul (content/passwordManager.xul)
|
||||
* content/passwordmgr/passwordManager.js (content/passwordManager.js)
|
||||
* content/passwordmgr/passwordManagerExceptions.js (content/passwordManagerExceptions.js)
|
||||
|
@ -41,6 +41,7 @@ EXTRA_PP_JS_MODULES += [
|
||||
|
||||
EXTRA_JS_MODULES += [
|
||||
'InsecurePasswordUtils.jsm',
|
||||
'LoginDoorhangers.jsm',
|
||||
'LoginHelper.jsm',
|
||||
'LoginManagerContent.jsm',
|
||||
'LoginRecipes.jsm',
|
||||
|
Loading…
Reference in New Issue
Block a user