This commit is contained in:
Paul Sawaya 2012-11-29 17:38:34 -08:00
Родитель 5da5673e0f
Коммит 51172163c1
11 изменённых файлов: 227 добавлений и 29 удалений

Просмотреть файл

@ -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"
]
}