PIN entry in infobar
This commit is contained in:
Родитель
5da5673e0f
Коммит
51172163c1
|
@ -1,6 +1,11 @@
|
|||
11/29 Paul Sawaya
|
||||
|
||||
Added signup/login content page, and infobar that reminds the user to signup/login.
|
||||
Added PIN entry in infobar.
|
||||
|
||||
11/28 Paul Sawaya
|
||||
|
||||
Reorganized code, as per https://gist.github.com/4127665.
|
||||
|
||||
11/27 Paul Sawaya
|
||||
|
||||
|
|
|
@ -6,6 +6,10 @@
|
|||
* browser (ie, which tab is currently active) and send messages to the observer
|
||||
* script running on that page.
|
||||
*
|
||||
* Note that none of these functions check whether logins are PIN locked. In order
|
||||
* to keep with the current security model, you must prompt for a PIN before form
|
||||
* filling.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
@ -26,15 +30,7 @@ function getActiveTab(callback) {
|
|||
// popup. Fills in the forms on the current page.
|
||||
function formFillCurrentTab() {
|
||||
getActiveTab(function(tab) {
|
||||
var tabID = tab.id;
|
||||
getPageDataForPopup(function (logins) {
|
||||
// TODO: Find out how to present a user with a choice if they have
|
||||
// more than one login saved for the current domain.
|
||||
chrome.tabs.sendMessage(tabID,{
|
||||
type: 'fill_form',
|
||||
login: logins[0]
|
||||
});
|
||||
});
|
||||
formFillTab(tab);
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -42,8 +38,17 @@ function getPageDataForPopup(callback) {
|
|||
getActiveTab(function(tab) {
|
||||
var newURL = new Uri(tab.url);
|
||||
getLoginsForSite(newURL.host(),function(logins) {
|
||||
// if (logins.length == 0) return;
|
||||
callback(logins);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function formFillTab(tab) {
|
||||
var newURL = new Uri(tab.url);
|
||||
getLoginsForSite(newURL.host(),function(logins) {
|
||||
chrome.tabs.sendMessage(tab.id,{
|
||||
type: 'fill_form',
|
||||
login: logins[0]
|
||||
});
|
||||
});
|
||||
}
|
|
@ -25,9 +25,9 @@ var infobarHooks = {
|
|||
case 'never_for_this_site':
|
||||
neverSaveOnSite(notificationObj.notification.hostname);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
console.log("Unknown response from infobar!");
|
||||
console.log("Unknown response from password_observed infobar!");
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
@ -35,5 +35,14 @@ var infobarHooks = {
|
|||
if (infobarResponse.user_action == 'launch_signup') {
|
||||
startFirstRunFlow();
|
||||
}
|
||||
},
|
||||
'pin_entry': function(notificationObj,infobarResponse) {
|
||||
if (infobarResponse.pin_valid) {
|
||||
console.log(notificationObj)
|
||||
chrome.tabs.get(notificationObj.tabID, function(tab) {
|
||||
console.log('form filling tab');
|
||||
formFillTab(tab);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ function initSkyCrane() {
|
|||
// Content-to-chrome message handlers
|
||||
//
|
||||
|
||||
// TODO: Handle "fill_form" message
|
||||
var messageHandlers = {
|
||||
'add_login': function(message,tabID) {
|
||||
var notificationObj = message;
|
||||
|
@ -76,28 +75,38 @@ var messageHandlers = {
|
|||
}
|
||||
});
|
||||
// TODO: Send new login to server
|
||||
// TODO: Enable SkyCrane page action for all tabs on this domain.
|
||||
});
|
||||
},
|
||||
'login_success': function(message,tabID) {
|
||||
console.log('Successfully logged in with ',JSON.stringify(message));
|
||||
});
|
||||
},
|
||||
'observing_page': function(message,tabID) {
|
||||
console.log('got observing_page\n',JSON.stringify(message));
|
||||
// See if we can automatically log user into this page. If not, there's nothing to do
|
||||
// See if there are login forms on this page. If not, there's nothing to do
|
||||
// on the observing_page notification, so bail.
|
||||
if (message.num_login_forms == 0) return;
|
||||
|
||||
// Search for logins for this particular site
|
||||
getLoginsForSite(message.hostname, function(logins) {
|
||||
if (logins.length == 0) return;
|
||||
|
||||
if (logins.length == 1) {
|
||||
// Check if the login is not PIN locked. If it's not, form fill the page now.
|
||||
if (!logins[0].pin_locked) {
|
||||
// Is the login for this site PIN locked?
|
||||
if (logins[0].pin_locked) {
|
||||
// If it is, show the PIN entry infobar.
|
||||
displayInfobar({
|
||||
notify: true,
|
||||
tabID: tabID,
|
||||
notification: {
|
||||
type: 'pin_entry',
|
||||
// Include the tabID in the notification so the infobar handler
|
||||
// can trigger autofill in the correct tab.
|
||||
tabID: tabID
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
// If it's not, form fill the page now.
|
||||
chrome.tabs.sendMessage(tabID,{
|
||||
type: 'fill_form',
|
||||
login: logins[0]
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
// If there's only a single login form on the page, we're fine. Otherwise,
|
||||
|
@ -118,12 +127,17 @@ var messageHandlers = {
|
|||
// TODO: Prompt user for choice of logins
|
||||
}
|
||||
});
|
||||
},
|
||||
'validate_pin': function(message,tabID,sendResponse) {
|
||||
sendResponse({
|
||||
'is_valid': validatePIN(message.pin)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
|
||||
if (request.type && messageHandlers[request.type]) {
|
||||
messageHandlers[request.type].call(messageHandlers,request.message,sender.tab.id);
|
||||
messageHandlers[request.type].call(messageHandlers,request.message,sender.tab.id,sendResponse);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -134,7 +148,8 @@ chrome.extension.onMessage.addListener(function(request, sender, sendResponse) {
|
|||
function displayInfobar(notificationObj) {
|
||||
var infobarPaths = {
|
||||
password_observed: "/infobars/remember_password_infobar.html",
|
||||
signup_nag: "/infobars/signup_nag_infobar.html"
|
||||
signup_nag: "/infobars/signup_nag_infobar.html",
|
||||
pin_entry: "/infobars/pin_entry_infobar.html"
|
||||
};
|
||||
// Make sure we have a HTML infobar for this type of notification
|
||||
if (!infobarPaths[notificationObj.notification.type]) return;
|
||||
|
@ -167,7 +182,7 @@ function testInfobarNotification() {
|
|||
notify: true,
|
||||
tabID: tab.id,
|
||||
notification: {
|
||||
type: 'password_observed',
|
||||
type: 'pin_entry',
|
||||
formEl: {},
|
||||
formSubmitURL: "",
|
||||
hash: "bc74f4f071a5a33f00ab88a6d6385b5e6638b86c",
|
||||
|
|
|
@ -233,7 +233,8 @@
|
|||
hostname: window.location.host,
|
||||
// Report if there is a single login-type form on the page, so we can attempt automated sign-in
|
||||
// if there's a login stored.
|
||||
single_login_form: (formsByType[1] && formsByType[1].length == 1)
|
||||
single_login_form: (formsByType[1] && formsByType[1].length == 1),
|
||||
num_login_forms: formsByType[1].length
|
||||
}
|
||||
});
|
||||
})();
|
|
@ -0,0 +1,60 @@
|
|||
body {
|
||||
background: -webkit-linear-gradient(top, #707070 0%,#3A3A3C 100%);
|
||||
font-size:10pt;
|
||||
color:white;
|
||||
font-family:sans-serif;
|
||||
}
|
||||
|
||||
a {
|
||||
color:red;
|
||||
}
|
||||
|
||||
/* Modified from bootstrap.css .btn*/
|
||||
button {
|
||||
background: -webkit-linear-gradient(top, #4b4b4b 0%,#191919 100%);
|
||||
|
||||
display: inline-block;
|
||||
*display: inline;
|
||||
padding: 2px 7px;
|
||||
margin-bottom: 0;
|
||||
*margin-left: .3em;
|
||||
font-size: 10pt;
|
||||
line-height: 20px;
|
||||
*line-height: 20px;
|
||||
color: white;
|
||||
text-align: center;
|
||||
text-shadow: 0 1px 1px rgba(255, 255, 255, 0.75);
|
||||
vertical-align: middle;
|
||||
cursor: pointer;
|
||||
background-repeat: repeat-x;
|
||||
border: 1px solid #bbbbbb;
|
||||
*border: 0;
|
||||
border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25);
|
||||
border-color: #e6e6e6 #e6e6e6 #bfbfbf;
|
||||
border-bottom-color: #a2a2a2;
|
||||
-webkit-border-radius: 4px;
|
||||
*zoom: 1;
|
||||
-webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.2), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
button:hover {
|
||||
background: -webkit-linear-gradient(top, #191919 0%,#4b4b4b 100%);
|
||||
}
|
||||
|
||||
input.pin-digit {
|
||||
background: -webkit-linear-gradient(top, #505050 0%,#2A2A2A 100%);
|
||||
border:1px #3e3e3e;
|
||||
width:20px;
|
||||
height:25px;
|
||||
border-radius:5px;
|
||||
color:white;
|
||||
}
|
||||
|
||||
input.pin-digit.wrong-pin {
|
||||
background: -webkit-linear-gradient(top, #a00000 0%,#2A2A2A 100%);
|
||||
border:1px #720000;
|
||||
}
|
||||
|
||||
#pin-entry {
|
||||
margin-left:20px;
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
<html>
|
||||
<head>
|
||||
<link href="gombot_infobar.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<span id="pin-entry-prompt">
|
||||
Enter PIN.
|
||||
</span>
|
||||
|
||||
<span id="pin-entry">
|
||||
<input id="digit1" class="pin-digit" maxlength="1" type="password" tabindex="1"/>
|
||||
<input id="digit2" class="pin-digit" maxlength="1" type="password" tabindex="2"/>
|
||||
<input id="digit3" class="pin-digit" maxlength="1" type="password" tabindex="3"/>
|
||||
<input id="digit4" class="pin-digit" maxlength="1" type="password" tabindex="4"/>
|
||||
</span>
|
||||
<!-- gives you window.CompleteInfobar() which you call with
|
||||
a javascript object to end your infobar -->
|
||||
<script src="/infobar/api.js"></script>
|
||||
<script src="/lib/jquery.js"></script>
|
||||
<script src="pin_entry_infobar.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,59 @@
|
|||
// TODO: Unite this, common/pin_entry.js, and pages/common/x-tags/pin/pin.js into something
|
||||
// reusable and not jQuery dependant.
|
||||
|
||||
$(document).ready(function() {
|
||||
function getEnteredPIN() {
|
||||
// Using .get() because jQuery .map returns an object and not an array.
|
||||
return $('.pin-digit').get().map(function(x) { return x.value; } ).join('');
|
||||
}
|
||||
|
||||
$('.pin-digit').keypress(function(evt) {
|
||||
var input = this;
|
||||
// Did the user type a digit?
|
||||
if (evt.charCode >= '0'.charCodeAt(0) && evt.charCode <= '9'.charCodeAt(0)) {
|
||||
// Wait a beat so that we have what the user entered.
|
||||
setTimeout(function() {
|
||||
if ($(input).val().length == 1) {
|
||||
if ($(input).attr('tabindex') == 4) {
|
||||
// User finished entering PIN
|
||||
chrome.extension.sendMessage({
|
||||
type: 'validate_pin',
|
||||
message: {
|
||||
pin: getEnteredPIN()
|
||||
}
|
||||
},
|
||||
function(response) {
|
||||
if (response.is_valid) {
|
||||
CompleteInfobar({
|
||||
type: 'pin_entry',
|
||||
pin_valid: true
|
||||
});
|
||||
}
|
||||
else {
|
||||
// TODO: Prompt for master password after three failures
|
||||
$('.pin-digit').addClass('wrong-pin');
|
||||
$('#pin-entry-prompt').html('Incorrect PIN. Try again.');
|
||||
resetPINForm();
|
||||
}
|
||||
});
|
||||
}
|
||||
else {
|
||||
// Advance focus to the element with the next tabindex.
|
||||
$('[tabindex="'+ ($(input).attr('tabindex')+1) + '"]').focus();
|
||||
}
|
||||
}
|
||||
},1);
|
||||
}
|
||||
else {
|
||||
// Make sure this character won't get typed.
|
||||
evt.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
function resetPINForm() {
|
||||
$('.pin-digit').val('');
|
||||
$('#digit1').focus();
|
||||
}
|
||||
|
||||
resetPINForm();
|
||||
});
|
|
@ -0,0 +1,12 @@
|
|||
<html>
|
||||
<head>
|
||||
<link href="gombot_infobar.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
Gombot can securely store this login for you. <a id="signup-link" href="#">Sign up</a> now!
|
||||
<!-- gives you window.CompleteInfobar() which you call with
|
||||
a javascript object to end your infobar -->
|
||||
<script src="/infobar/api.js"></script>
|
||||
<script src="signup_nag_infobar.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,9 @@
|
|||
window.addEventListener('load', function() {
|
||||
console.log(document.getElementById('signup-link'));
|
||||
document.getElementById('signup-link').addEventListener('click', function() {
|
||||
CompleteInfobar({
|
||||
type: 'signup_nag',
|
||||
user_action: 'launch_signup'
|
||||
});
|
||||
});
|
||||
});
|
|
@ -35,6 +35,7 @@
|
|||
"common/pin_entry.js",
|
||||
"common/pin_entry.css",
|
||||
"infobars/remember_password_infobar.html",
|
||||
"infobars/signup_nag_infobar.html"
|
||||
"infobars/signup_nag_infobar.html",
|
||||
"infobars/pin_entry_infobar.html"
|
||||
]
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче