Version 0.5.0

This commit is contained in:
varjolintu 2018-01-22 15:20:55 +02:00
parent c55999ea1c
commit ff03e5fc04
25 changed files with 3955 additions and 3861 deletions

View file

@ -1,3 +1,15 @@
0.5.0 (22-01-2018)
=========================
- Fixed an error when filling only a password
- Credential retrieval is allowed when only one input field is visible (TOTP)
- Asynchronous receiveCredentialsIfNecessary()
- Send triggerUnlock with request that need to popup KeePassXC to front
- Added verifyDatabaseResponse to get_databasehash
- Renamed keepassxc-browser to KeePassXC-Browser
- Removed duplicate retrieve_credentials requests
- Fixed identation
- Added support for credential filling through user interaction when database is closed
0.4.8 (06-01-2018) 0.4.8 (06-01-2018)
========================= =========================
- Changed native messaging host name to org.keepassxc.keepassxc_browser - Changed native messaging host name to org.keepassxc.keepassxc_browser

View file

@ -5,261 +5,261 @@ const BLINK_TIMEOUT_REDIRECT_THRESHOLD_TIME_DEFAULT = -1;
const BLINK_TIMEOUT_REDIRECT_COUNT_DEFAULT = 1; const BLINK_TIMEOUT_REDIRECT_COUNT_DEFAULT = 1;
browserAction.show = function(callback, tab) { browserAction.show = function(callback, tab) {
let data = {}; let data = {};
if (!page.tabs[tab.id] || page.tabs[tab.id].stack.length == 0) { if (!page.tabs[tab.id] || page.tabs[tab.id].stack.length == 0) {
browserAction.showDefault(callback, tab); browserAction.showDefault(callback, tab);
return; return;
} }
else { else {
data = page.tabs[tab.id].stack[page.tabs[tab.id].stack.length - 1]; data = page.tabs[tab.id].stack[page.tabs[tab.id].stack.length - 1];
} }
browser.browserAction.setIcon({ browser.browserAction.setIcon({
tabId: tab.id, tabId: tab.id,
path: '/icons/19x19/' + browserAction.generateIconName(data.iconType, data.icon) path: '/icons/19x19/' + browserAction.generateIconName(data.iconType, data.icon)
}); });
if (data.popup) { if (data.popup) {
browser.browserAction.setPopup({ browser.browserAction.setPopup({
tabId: tab.id, tabId: tab.id,
popup: 'popups/' + data.popup popup: 'popups/' + data.popup
}); });
} }
}; };
browserAction.update = function(interval) { browserAction.update = function(interval) {
if (!page.tabs[page.currentTabId] || page.tabs[page.currentTabId].stack.length === 0) { if (!page.tabs[page.currentTabId] || page.tabs[page.currentTabId].stack.length === 0) {
return; return;
} }
let data = page.tabs[page.currentTabId].stack[page.tabs[page.currentTabId].stack.length - 1]; let data = page.tabs[page.currentTabId].stack[page.tabs[page.currentTabId].stack.length - 1];
if (typeof data.visibleForMilliSeconds !== 'undefined') { if (typeof data.visibleForMilliSeconds !== 'undefined') {
if (data.visibleForMilliSeconds <= 0) { if (data.visibleForMilliSeconds <= 0) {
browserAction.stackPop(page.currentTabId); browserAction.stackPop(page.currentTabId);
browserAction.show(null, {'id': page.currentTabId}); browserAction.show(null, {'id': page.currentTabId});
page.clearCredentials(page.currentTabId); page.clearCredentials(page.currentTabId);
return; return;
} }
data.visibleForMilliSeconds -= interval; data.visibleForMilliSeconds -= interval;
} }
if (data.intervalIcon) { if (data.intervalIcon) {
data.intervalIcon.counter += 1; data.intervalIcon.counter += 1;
if (data.intervalIcon.counter < data.intervalIcon.max) { if (data.intervalIcon.counter < data.intervalIcon.max) {
return; return;
} }
data.intervalIcon.counter = 0; data.intervalIcon.counter = 0;
data.intervalIcon.index += 1; data.intervalIcon.index += 1;
if (data.intervalIcon.index > data.intervalIcon.icons.length - 1) { if (data.intervalIcon.index > data.intervalIcon.icons.length - 1) {
data.intervalIcon.index = 0; data.intervalIcon.index = 0;
} }
browser.browserAction.setIcon({ browser.browserAction.setIcon({
tabId: page.currentTabId, tabId: page.currentTabId,
path: '/icons/19x19/' + browserAction.generateIconName(null, data.intervalIcon.icons[data.intervalIcon.index]) path: '/icons/19x19/' + browserAction.generateIconName(null, data.intervalIcon.icons[data.intervalIcon.index])
}); });
} }
}; };
browserAction.showDefault = function(callback, tab) { browserAction.showDefault = function(callback, tab) {
let stackData = { let stackData = {
level: 1, level: 1,
iconType: 'normal', iconType: 'normal',
popup: 'popup.html' popup: 'popup.html'
}; };
keepass.isConfigured().then((response) => { keepass.isConfigured().then((response) => {
if (!response || keepass.isDatabaseClosed || !keepass.isKeePassXCAvailable || page.tabs[tab.id].errorMessage) { if (!response || keepass.isDatabaseClosed || !keepass.isKeePassXCAvailable || page.tabs[tab.id].errorMessage) {
stackData.iconType = 'cross'; stackData.iconType = 'cross';
} }
if (page.tabs[tab.id].loginList.length > 0) { if (page.tabs[tab.id].loginList.length > 0) {
stackData.iconType = 'questionmark'; stackData.iconType = 'questionmark';
stackData.popup = 'popup_login.html'; stackData.popup = 'popup_login.html';
} }
browserAction.stackUnshift(stackData, tab.id); browserAction.stackUnshift(stackData, tab.id);
browserAction.show(null, tab); browserAction.show(null, tab);
}); });
}; };
browserAction.stackAdd = function(callback, tab, icon, popup, level, push, visibleForMilliSeconds, visibleForPageUpdates, redirectOffset, dontShow) { browserAction.stackAdd = function(callback, tab, icon, popup, level, push, visibleForMilliSeconds, visibleForPageUpdates, redirectOffset, dontShow) {
const id = tab.id || page.currentTabId; const id = tab.id || page.currentTabId;
if (!level) { if (!level) {
level = 1; level = 1;
} }
let stackData = { let stackData = {
level: level, level: level,
icon: icon icon: icon
}; };
if (popup) { if (popup) {
stackData.popup = popup; stackData.popup = popup;
} }
if (visibleForMilliSeconds) { if (visibleForMilliSeconds) {
stackData.visibleForMilliSeconds = visibleForMilliSeconds; stackData.visibleForMilliSeconds = visibleForMilliSeconds;
} }
if (visibleForPageUpdates) { if (visibleForPageUpdates) {
stackData.visibleForPageUpdates = visibleForPageUpdates; stackData.visibleForPageUpdates = visibleForPageUpdates;
} }
if (redirectOffset) { if (redirectOffset) {
stackData.redirectOffset = redirectOffset; stackData.redirectOffset = redirectOffset;
} }
if (push) { if (push) {
browserAction.stackPush(stackData, id); browserAction.stackPush(stackData, id);
} }
else { else {
browserAction.stackUnshift(stackData, id); browserAction.stackUnshift(stackData, id);
} }
if (!dontShow) { if (!dontShow) {
browserAction.show(null, {'id': id}); browserAction.show(null, {'id': id});
} }
}; };
browserAction.removeLevelFromStack = function(callback, tab, level, type, dontShow) { browserAction.removeLevelFromStack = function(callback, tab, level, type, dontShow) {
if (!page.tabs[tab.id]) { if (!page.tabs[tab.id]) {
return; return;
} }
if (!type) { if (!type) {
type = '<='; type = '<=';
} }
let newStack = []; let newStack = [];
for (const i of page.tabs[tab.id].stack) { for (const i of page.tabs[tab.id].stack) {
if ( if (
(type == '<' && i.level >= level) || (type == '<' && i.level >= level) ||
(type == '<=' && i.level > level) || (type == '<=' && i.level > level) ||
(type == '=' && i.level != level) || (type == '=' && i.level != level) ||
(type == '==' && i.level != level) || (type == '==' && i.level != level) ||
(type == '!=' && i.level == level) || (type == '!=' && i.level == level) ||
(type == '>' && i.level <= level) || (type == '>' && i.level <= level) ||
(type == '>=' && i.level < level) (type == '>=' && i.level < level)
) { ) {
newStack.push(i); newStack.push(i);
} }
} }
page.tabs[tab.id].stack = newStack; page.tabs[tab.id].stack = newStack;
if (!dontShow) { if (!dontShow) {
browserAction.show(callback, tab); browserAction.show(callback, tab);
} }
}; };
browserAction.stackPop = function(tabId) { browserAction.stackPop = function(tabId) {
const id = tabId || page.currentTabId; const id = tabId || page.currentTabId;
page.tabs[id].stack.pop(); page.tabs[id].stack.pop();
}; };
browserAction.stackPush = function(data, tabId) { browserAction.stackPush = function(data, tabId) {
const id = tabId || page.currentTabId; const id = tabId || page.currentTabId;
browserAction.removeLevelFromStack(null, {'id': id}, data.level, '<=', true); browserAction.removeLevelFromStack(null, {'id': id}, data.level, '<=', true);
page.tabs[id].stack.push(data); page.tabs[id].stack.push(data);
}; };
browserAction.stackUnshift = function(data, tabId) { browserAction.stackUnshift = function(data, tabId) {
const id = tabId || page.currentTabId; const id = tabId || page.currentTabId;
browserAction.removeLevelFromStack(null, {'id': id}, data.level, '<=', true); browserAction.removeLevelFromStack(null, {'id': id}, data.level, '<=', true);
page.tabs[id].stack.unshift(data); page.tabs[id].stack.unshift(data);
}; };
browserAction.removeRememberPopup = function(callback, tab, removeImmediately) { browserAction.removeRememberPopup = function(callback, tab, removeImmediately) {
if (!page.tabs[tab.id]) { if (!page.tabs[tab.id]) {
return; return;
} }
if( page.tabs[tab.id].stack.length == 0) { if( page.tabs[tab.id].stack.length == 0) {
page.clearCredentials(tab.id); page.clearCredentials(tab.id);
return; return;
} }
const data = page.tabs[tab.id].stack[page.tabs[tab.id].stack.length - 1]; const data = page.tabs[tab.id].stack[page.tabs[tab.id].stack.length - 1];
if (removeImmediately || !isNaN(data.visibleForPageUpdates)) { if (removeImmediately || !isNaN(data.visibleForPageUpdates)) {
const currentMS = Date.now(); const currentMS = Date.now();
if (removeImmediately || (data.visibleForPageUpdates <= 0 && data.redirectOffset > 0)) { if (removeImmediately || (data.visibleForPageUpdates <= 0 && data.redirectOffset > 0)) {
browserAction.stackPop(tab.id); browserAction.stackPop(tab.id);
browserAction.show(null, {"id": tab.id}); browserAction.show(null, {"id": tab.id});
page.clearCredentials(tab.id); page.clearCredentials(tab.id);
return; return;
} }
else if (!isNaN(data.visibleForPageUpdates) && data.redirectOffset > 0 && currentMS >= data.redirectOffset) { else if (!isNaN(data.visibleForPageUpdates) && data.redirectOffset > 0 && currentMS >= data.redirectOffset) {
data.visibleForPageUpdates = data.visibleForPageUpdates - 1; data.visibleForPageUpdates = data.visibleForPageUpdates - 1;
} }
} }
}; };
browserAction.setRememberPopup = function(tabId, username, password, url, usernameExists, credentialsList) { browserAction.setRememberPopup = function(tabId, username, password, url, usernameExists, credentialsList) {
const settings = typeof(localStorage.settings) === 'undefined' ? {} : JSON.parse(localStorage.settings); const settings = typeof(localStorage.settings) === 'undefined' ? {} : JSON.parse(localStorage.settings);
const id = tabId || page.currentTabId; const id = tabId || page.currentTabId;
let timeoutMinMillis = Number(getValueOrDefault(settings, 'blinkMinTimeout', BLINK_TIMEOUT_REDIRECT_THRESHOLD_TIME_DEFAULT, 0)); let timeoutMinMillis = Number(getValueOrDefault(settings, 'blinkMinTimeout', BLINK_TIMEOUT_REDIRECT_THRESHOLD_TIME_DEFAULT, 0));
if (timeoutMinMillis > 0) { if (timeoutMinMillis > 0) {
timeoutMinMillis += Date.now(); timeoutMinMillis += Date.now();
} }
const blinkTimeout = getValueOrDefault(settings, 'blinkTimeout', BLINK_TIMEOUT_DEFAULT, 0); const blinkTimeout = getValueOrDefault(settings, 'blinkTimeout', BLINK_TIMEOUT_DEFAULT, 0);
const pageUpdateAllowance = getValueOrDefault(settings, 'allowedRedirect', BLINK_TIMEOUT_REDIRECT_COUNT_DEFAULT, 0); const pageUpdateAllowance = getValueOrDefault(settings, 'allowedRedirect', BLINK_TIMEOUT_REDIRECT_COUNT_DEFAULT, 0);
const stackData = { const stackData = {
visibleForMilliSeconds: blinkTimeout, visibleForMilliSeconds: blinkTimeout,
visibleForPageUpdates: pageUpdateAllowance, visibleForPageUpdates: pageUpdateAllowance,
redirectOffset: timeoutMinMillis, redirectOffset: timeoutMinMillis,
level: 10, level: 10,
intervalIcon: { intervalIcon: {
index: 0, index: 0,
counter: 0, counter: 0,
max: 2, max: 2,
icons: ['icon_remember_red_background_19x19.png', 'icon_remember_red_lock_19x19.png'] icons: ['icon_remember_red_background_19x19.png', 'icon_remember_red_lock_19x19.png']
}, },
icon: 'icon_remember_red_background_19x19.png', icon: 'icon_remember_red_background_19x19.png',
popup: 'popup_remember.html' popup: 'popup_remember.html'
}; };
browserAction.stackPush(stackData, id); browserAction.stackPush(stackData, id);
page.tabs[id].credentials = { page.tabs[id].credentials = {
username: username, username: username,
password: password, password: password,
url: url, url: url,
usernameExists: usernameExists, usernameExists: usernameExists,
list: credentialsList list: credentialsList
}; };
browserAction.show(null, {'id': id}); browserAction.show(null, {'id': id});
}; };
function getValueOrDefault(settings, key, defaultVal, min) { function getValueOrDefault(settings, key, defaultVal, min) {
try { try {
let val = settings[key]; let val = settings[key];
if (isNaN(val) || val < min) { if (isNaN(val) || val < min) {
val = defaultVal; val = defaultVal;
} }
return val; return val;
} catch(e) { } catch(e) {
return defaultVal; return defaultVal;
} }
} }
browserAction.generateIconName = function(iconType, icon) { browserAction.generateIconName = function(iconType, icon) {
if (icon) { if (icon) {
return icon; return icon;
} }
let name = 'icon_'; let name = 'icon_';
name += (keepass.keePassXCUpdateAvailable()) ? 'new_' : ''; name += (keepass.keePassXCUpdateAvailable()) ? 'new_' : '';
name += (!iconType || iconType === 'normal') ? 'normal' : iconType; name += (!iconType || iconType === 'normal') ? 'normal' : iconType;
name += '_19x19.png'; name += '_19x19.png';
return name; return name;
}; };

View file

@ -1,21 +1,21 @@
const kpxcEvent = {}; const kpxcEvent = {};
kpxcEvent.onMessage = function(request, sender, callback) { kpxcEvent.onMessage = function(request, sender, callback) {
if (request.action in kpxcEvent.messageHandlers) { if (request.action in kpxcEvent.messageHandlers) {
//console.log('onMessage(' + request.action + ') for #' + sender.tab.id); //console.log('onMessage(' + request.action + ') for #' + sender.tab.id);
if (!sender.hasOwnProperty('tab') || sender.tab.id < 1) { if (!sender.hasOwnProperty('tab') || sender.tab.id < 1) {
sender.tab = {}; sender.tab = {};
sender.tab.id = page.currentTabId; sender.tab.id = page.currentTabId;
} }
kpxcEvent.invoke(kpxcEvent.messageHandlers[request.action], callback, sender.tab.id, request.args); kpxcEvent.invoke(kpxcEvent.messageHandlers[request.action], callback, sender.tab.id, request.args);
// onMessage closes channel for callback automatically // onMessage closes channel for callback automatically
// if this method does not return true // if this method does not return true
if (callback) { if (callback !== undefined) {
return true; return true;
} }
} }
}; };
/** /**
@ -30,272 +30,272 @@ kpxcEvent.onMessage = function(request, sender, callback) {
* @returns null (asynchronous) * @returns null (asynchronous)
*/ */
kpxcEvent.invoke = function(handler, callback, senderTabId, args, secondTime) { kpxcEvent.invoke = function(handler, callback, senderTabId, args, secondTime) {
if (senderTabId < 1) { if (senderTabId < 1) {
return; return;
} }
if (!page.tabs[senderTabId]) { if (!page.tabs[senderTabId]) {
page.createTabEntry(senderTabId); page.createTabEntry(senderTabId);
} }
// remove information from no longer existing tabs // remove information from no longer existing tabs
page.removePageInformationFromNotExistingTabs(); page.removePageInformationFromNotExistingTabs();
browser.tabs.get(senderTabId).then((tab) => { browser.tabs.get(senderTabId).then((tab) => {
if (!tab) { if (!tab) {
return; return;
} }
if (!tab.url) { if (!tab.url) {
// Issue 6877: tab URL is not set directly after you opened a window // Issue 6877: tab URL is not set directly after you opened a window
// using window.open() // using window.open()
if (!secondTime) { if (!secondTime) {
window.setTimeout(function() { window.setTimeout(function() {
kpxcEvent.invoke(handler, callback, senderTabId, args, true); kpxcEvent.invoke(handler, callback, senderTabId, args, true);
}, 250); }, 250);
} }
return; return;
} }
if (!page.tabs[tab.id]) { if (!page.tabs[tab.id]) {
page.createTabEntry(tab.id); page.createTabEntry(tab.id);
} }
args = args || []; args = args || [];
args.unshift(tab); args.unshift(tab);
args.unshift(callback); args.unshift(callback);
if (handler) { if (handler) {
handler.apply(this, args); handler.apply(this, args);
} }
else { else {
console.log('undefined handler for tab ' + tab.id); console.log('undefined handler for tab ' + tab.id);
} }
}).catch((e) => {console.log(e);}); }).catch((e) => {console.log(e);});
}; };
kpxcEvent.onShowAlert = function(callback, tab, message) { kpxcEvent.onShowAlert = function(callback, tab, message) {
if (page.settings.supressAlerts) { console.log(message); } if (page.settings.supressAlerts) { console.log(message); }
else { alert(message); } else { alert(message); }
}; };
kpxcEvent.showStatus = function(configured, tab, callback) { kpxcEvent.showStatus = function(configured, tab, callback) {
let keyId = null; let keyId = null;
if (configured) { if (configured) {
keyId = keepass.keyRing[keepass.databaseHash].id; keyId = keepass.keyRing[keepass.databaseHash].id;
} }
browserAction.showDefault(null, tab); browserAction.showDefault(null, tab);
const errorMessage = page.tabs[tab.id].errorMessage; const errorMessage = page.tabs[tab.id].errorMessage;
callback({ callback({
identifier: keyId, identifier: keyId,
configured: configured, configured: configured,
databaseClosed: keepass.isDatabaseClosed, databaseClosed: keepass.isDatabaseClosed,
keePassXCAvailable: keepass.isKeePassXCAvailable, keePassXCAvailable: keepass.isKeePassXCAvailable,
encryptionKeyUnrecognized: keepass.isEncryptionKeyUnrecognized, encryptionKeyUnrecognized: keepass.isEncryptionKeyUnrecognized,
associated: keepass.isAssociated(), associated: keepass.isAssociated(),
error: errorMessage ? errorMessage : null error: errorMessage ? errorMessage : null
}); });
}; };
kpxcEvent.onLoadSettings = function(callback, tab) { kpxcEvent.onLoadSettings = function(callback, tab) {
page.initSettings().then((settings) => { page.initSettings().then((settings) => {
callback(settings); callback(settings);
}, (err) => { }, (err) => {
console.log('error loading settings: ' + err); console.log('error loading settings: ' + err);
}); });
}; };
kpxcEvent.onLoadKeyRing = function(callback, tab) { kpxcEvent.onLoadKeyRing = function(callback, tab) {
browser.storage.local.get({'keyRing': {}}).then(function(item) { browser.storage.local.get({'keyRing': {}}).then(function(item) {
keepass.keyRing = item.keyRing; keepass.keyRing = item.keyRing;
if (keepass.isAssociated() && !keepass.keyRing[keepass.associated.hash]) { if (keepass.isAssociated() && !keepass.keyRing[keepass.associated.hash]) {
keepass.associated = { keepass.associated = {
"value": false, "value": false,
"hash": null "hash": null
}; };
} }
callback(item.keyRing); callback(item.keyRing);
}, (err) => { }, (err) => {
console.log('error loading keyRing: ' + err); console.log('error loading keyRing: ' + err);
}); });
}; };
kpxcEvent.onSaveSettings = function(callback, tab, settings) { kpxcEvent.onSaveSettings = function(callback, tab, settings) {
browser.storage.local.set({'settings': settings}).then(function() { browser.storage.local.set({'settings': settings}).then(function() {
kpxcEvent.onLoadSettings(callback, tab); kpxcEvent.onLoadSettings(callback, tab);
}); });
}; };
kpxcEvent.onGetStatus = function(callback, tab, internalPoll = false) { kpxcEvent.onGetStatus = function(callback, tab, internalPoll = false, triggerUnlock = false) {
// When internalPoll is true the event is triggered from content script in intervals -> don't poll KeePassXC // When internalPoll is true the event is triggered from content script in intervals -> don't poll KeePassXC
if (!internalPoll) { if (!internalPoll) {
keepass.testAssociation((response) => { keepass.testAssociation((response) => {
if (!response) { if (!response) {
kpxcEvent.showStatus(false, tab, callback); kpxcEvent.showStatus(false, tab, callback);
return; return;
} }
keepass.isConfigured().then((configured) => { keepass.isConfigured().then((configured) => {
kpxcEvent.showStatus(configured, tab, callback); kpxcEvent.showStatus(configured, tab, callback);
}); });
}, tab, true); }, tab, true, triggerUnlock);
} else { } else {
keepass.isConfigured().then((configured) => { keepass.isConfigured().then((configured) => {
kpxcEvent.showStatus(configured, tab, callback); kpxcEvent.showStatus(configured, tab, callback);
}); });
} }
}; };
kpxcEvent.onReconnect = function(callback, tab) { kpxcEvent.onReconnect = function(callback, tab) {
keepass.connectToNative(); keepass.connectToNative();
// Add a small timeout after reconnecting. Just to make sure. It's not pretty, I know :( // Add a small timeout after reconnecting. Just to make sure. It's not pretty, I know :(
setTimeout(() => { setTimeout(() => {
keepass.generateNewKeyPair(); keepass.generateNewKeyPair();
keepass.changePublicKeys(tab).then((pkRes) => { keepass.changePublicKeys(tab).then((pkRes) => {
keepass.getDatabaseHash((gdRes) => { keepass.getDatabaseHash((gdRes) => {
if (gdRes) { if (gdRes) {
keepass.testAssociation((response) => { keepass.testAssociation((response) => {
keepass.isConfigured().then((configured) => { keepass.isConfigured().then((configured) => {
kpxcEvent.showStatus(configured, tab, callback); kpxcEvent.showStatus(configured, tab, callback);
}).catch((e) => {console.log(e);}); }).catch((e) => {console.log(e);});
}, tab); }, tab);
} }
}, null); }, null);
}); });
}, 2000); }, 2000);
}; };
kpxcEvent.lockDatabase = function(callback, tab) { kpxcEvent.lockDatabase = function(callback, tab) {
keepass.lockDatabase(tab).then((response => { keepass.lockDatabase(tab).then((response => {
kpxcEvent.showStatus(true, tab, callback); kpxcEvent.showStatus(true, tab, callback);
})); }));
}; };
kpxcEvent.onPopStack = function(callback, tab) { kpxcEvent.onPopStack = function(callback, tab) {
browserAction.stackPop(tab.id); browserAction.stackPop(tab.id);
browserAction.show(null, tab); browserAction.show(null, tab);
}; };
kpxcEvent.onGetTabInformation = function(callback, tab) { kpxcEvent.onGetTabInformation = function(callback, tab) {
const id = tab.id || page.currentTabId; const id = tab.id || page.currentTabId;
callback(page.tabs[id]); callback(page.tabs[id]);
}; };
kpxcEvent.onGetConnectedDatabase = function(callback, tab) { kpxcEvent.onGetConnectedDatabase = function(callback, tab) {
callback({ callback({
count: Object.keys(keepass.keyRing).length, count: Object.keys(keepass.keyRing).length,
identifier: (keepass.keyRing[keepass.associated.hash]) ? keepass.keyRing[keepass.associated.hash].id : null identifier: (keepass.keyRing[keepass.associated.hash]) ? keepass.keyRing[keepass.associated.hash].id : null
}); });
}; };
kpxcEvent.onGetKeePassXCVersions = function(callback, tab) { kpxcEvent.onGetKeePassXCVersions = function(callback, tab) {
if(keepass.currentKeePassXC.version == 0) { if(keepass.currentKeePassXC.version == 0) {
keepass.getDatabaseHash((res) => { keepass.getDatabaseHash((res) => {
callback({"current": keepass.currentKeePassXC.version, "latest": keepass.currentKeePassXC.version}); callback({"current": keepass.currentKeePassXC.version, "latest": keepass.currentKeePassXC.version});
}, tab); }, tab);
} else { } else {
callback({"current": keepass.currentKeePassXC.version, "latest": keepass.currentKeePassXC.version}); callback({"current": keepass.currentKeePassXC.version, "latest": keepass.currentKeePassXC.version});
} }
}; };
kpxcEvent.onCheckUpdateKeePassXC = function(callback, tab) { kpxcEvent.onCheckUpdateKeePassXC = function(callback, tab) {
keepass.checkForNewKeePassXCVersion(); keepass.checkForNewKeePassXCVersion();
callback({current: keepass.currentKeePassXC.version, latest: keepass.latestKeePassXC.version}); callback({current: keepass.currentKeePassXC.version, latest: keepass.latestKeePassXC.version});
}; };
kpxcEvent.onUpdateAvailableKeePassXC = function(callback, tab) { kpxcEvent.onUpdateAvailableKeePassXC = function(callback, tab) {
callback(keepass.keePassXCUpdateAvailable()); callback(keepass.keePassXCUpdateAvailable());
}; };
kpxcEvent.onRemoveCredentialsFromTabInformation = function(callback, tab) { kpxcEvent.onRemoveCredentialsFromTabInformation = function(callback, tab) {
const id = tab.id || page.currentTabId; const id = tab.id || page.currentTabId;
page.clearCredentials(id); page.clearCredentials(id);
}; };
kpxcEvent.onSetRememberPopup = function(callback, tab, username, password, url, usernameExists, credentialsList) { kpxcEvent.onSetRememberPopup = function(callback, tab, username, password, url, usernameExists, credentialsList) {
browserAction.setRememberPopup(tab.id, username, password, url, usernameExists, credentialsList); browserAction.setRememberPopup(tab.id, username, password, url, usernameExists, credentialsList);
}; };
kpxcEvent.onLoginPopup = function(callback, tab, logins) { kpxcEvent.onLoginPopup = function(callback, tab, logins) {
let stackData = { let stackData = {
level: 1, level: 1,
iconType: 'questionmark', iconType: 'questionmark',
popup: 'popup_login.html' popup: 'popup_login.html'
}; };
browserAction.stackUnshift(stackData, tab.id); browserAction.stackUnshift(stackData, tab.id);
page.tabs[tab.id].loginList = logins; page.tabs[tab.id].loginList = logins;
browserAction.show(null, tab); browserAction.show(null, tab);
}; };
kpxcEvent.initHttpAuth = function(callback) { kpxcEvent.initHttpAuth = function(callback) {
httpAuth.init(); httpAuth.init();
callback(); callback();
} }
kpxcEvent.onHTTPAuthPopup = function(callback, tab, data) { kpxcEvent.onHTTPAuthPopup = function(callback, tab, data) {
let stackData = { let stackData = {
level: 1, level: 1,
iconType: 'questionmark', iconType: 'questionmark',
popup: 'popup_httpauth.html' popup: 'popup_httpauth.html'
}; };
browserAction.stackUnshift(stackData, tab.id); browserAction.stackUnshift(stackData, tab.id);
page.tabs[tab.id].loginList = data; page.tabs[tab.id].loginList = data;
browserAction.show(null, tab); browserAction.show(null, tab);
}; };
kpxcEvent.onMultipleFieldsPopup = function(callback, tab) { kpxcEvent.onMultipleFieldsPopup = function(callback, tab) {
let stackData = { let stackData = {
level: 1, level: 1,
iconType: 'normal', iconType: 'normal',
popup: 'popup_multiple-fields.html' popup: 'popup_multiple-fields.html'
}; };
browserAction.stackUnshift(stackData, tab.id); browserAction.stackUnshift(stackData, tab.id);
browserAction.show(null, tab); browserAction.show(null, tab);
}; };
kpxcEvent.pageClearLogins = function(callback, tab) { kpxcEvent.pageClearLogins = function(callback, tab) {
page.clearLogins(tab.id); page.clearLogins(tab.id);
callback(); callback();
}; };
kpxcEvent.oldDatabaseHash = 'no-hash'; kpxcEvent.oldDatabaseHash = 'no-hash';
kpxcEvent.checkDatabaseHash = function(callback, tab) { kpxcEvent.checkDatabaseHash = function(callback, tab) {
keepass.checkDatabaseHash((response) => { keepass.checkDatabaseHash((response) => {
callback({old: kpxcEvent.oldDatabaseHash, new: response}); callback({old: kpxcEvent.oldDatabaseHash, new: response});
kpxcEvent.oldDatabaseHash = response; kpxcEvent.oldDatabaseHash = response;
}); });
}; };
// all methods named in this object have to be declared BEFORE this! // all methods named in this object have to be declared BEFORE this!
kpxcEvent.messageHandlers = { kpxcEvent.messageHandlers = {
'add_credentials': keepass.addCredentials, 'add_credentials': keepass.addCredentials,
'alert': kpxcEvent.onShowAlert, 'alert': kpxcEvent.onShowAlert,
'associate': keepass.associate, 'associate': keepass.associate,
'check_update_keepassxc': kpxcEvent.onCheckUpdateKeePassXC, 'check_databasehash': kpxcEvent.checkDatabaseHash,
'get_connected_database': kpxcEvent.onGetConnectedDatabase, 'check_update_keepassxc': kpxcEvent.onCheckUpdateKeePassXC,
'get_keepassxc_versions': kpxcEvent.onGetKeePassXCVersions, 'generate_password': keepass.generatePassword,
'get_status': kpxcEvent.onGetStatus, 'get_connected_database': kpxcEvent.onGetConnectedDatabase,
'get_tab_information': kpxcEvent.onGetTabInformation, 'get_keepassxc_versions': kpxcEvent.onGetKeePassXCVersions,
'init_http_auth': kpxcEvent.initHttpAuth, 'get_status': kpxcEvent.onGetStatus,
'load_keyring': kpxcEvent.onLoadKeyRing, 'get_tab_information': kpxcEvent.onGetTabInformation,
'load_settings': kpxcEvent.onLoadSettings, 'init_http_auth': kpxcEvent.initHttpAuth,
'page_clear_logins': kpxcEvent.pageClearLogins, 'load_keyring': kpxcEvent.onLoadKeyRing,
'pop_stack': kpxcEvent.onPopStack, 'load_settings': kpxcEvent.onLoadSettings,
'popup_login': kpxcEvent.onLoginPopup, 'lock-database': kpxcEvent.lockDatabase,
'popup_multiple-fields': kpxcEvent.onMultipleFieldsPopup, 'page_clear_logins': kpxcEvent.pageClearLogins,
'remove_credentials_from_tab_information': kpxcEvent.onRemoveCredentialsFromTabInformation, 'pop_stack': kpxcEvent.onPopStack,
'retrieve_credentials': keepass.retrieveCredentials, 'popup_login': kpxcEvent.onLoginPopup,
'show_default_browseraction': browserAction.showDefault, 'popup_multiple-fields': kpxcEvent.onMultipleFieldsPopup,
'update_credentials': keepass.updateCredentials, 'reconnect': kpxcEvent.onReconnect,
'save_settings': kpxcEvent.onSaveSettings, 'remove_credentials_from_tab_information': kpxcEvent.onRemoveCredentialsFromTabInformation,
'set_remember_credentials': kpxcEvent.onSetRememberPopup, 'retrieve_credentials': keepass.retrieveCredentials,
'stack_add': browserAction.stackAdd, 'show_default_browseraction': browserAction.showDefault,
'update_available_keepassxc': kpxcEvent.onUpdateAvailableKeePassXC, 'update_credentials': keepass.updateCredentials,
'generate_password': keepass.generatePassword, 'save_settings': kpxcEvent.onSaveSettings,
'reconnect': kpxcEvent.onReconnect, 'set_remember_credentials': kpxcEvent.onSetRememberPopup,
'lock-database': kpxcEvent.lockDatabase, 'stack_add': browserAction.stackAdd,
'check_databasehash': kpxcEvent.checkDatabaseHash 'update_available_keepassxc': kpxcEvent.onUpdateAvailableKeePassXC
}; };

View file

@ -4,82 +4,82 @@ httpAuth.requests = [];
httpAuth.pendingCallbacks = []; httpAuth.pendingCallbacks = [];
httpAuth.init = function() { httpAuth.init = function() {
let handleReq = httpAuth.handleRequestPromise; let handleReq = httpAuth.handleRequestPromise;
let reqType = 'blocking'; let reqType = 'blocking';
if (!isFirefox()) { if (!isFirefox()) {
handleReq = httpAuth.handleRequestCallback; handleReq = httpAuth.handleRequestCallback;
reqType = 'asyncBlocking'; reqType = 'asyncBlocking';
} }
if (browser.webRequest.onAuthRequired.hasListener(handleReq)) { if (browser.webRequest.onAuthRequired.hasListener(handleReq)) {
browser.webRequest.onAuthRequired.removeListener(handleReq); browser.webRequest.onAuthRequired.removeListener(handleReq);
browser.webRequest.onCompleted.removeListener(httpAuth.requestCompleted); browser.webRequest.onCompleted.removeListener(httpAuth.requestCompleted);
browser.webRequest.onErrorOccurred.removeListener(httpAuth.requestCompleted); browser.webRequest.onErrorOccurred.removeListener(httpAuth.requestCompleted);
} }
// only intercept http auth requests if the option is turned on. // only intercept http auth requests if the option is turned on.
if (page.settings.autoFillAndSend) { if (page.settings.autoFillAndSend) {
const opts = { urls: ['<all_urls>'] }; const opts = { urls: ['<all_urls>'] };
browser.webRequest.onAuthRequired.addListener(handleReq, opts, [reqType]); browser.webRequest.onAuthRequired.addListener(handleReq, opts, [reqType]);
browser.webRequest.onCompleted.addListener(httpAuth.requestCompleted, opts); browser.webRequest.onCompleted.addListener(httpAuth.requestCompleted, opts);
browser.webRequest.onErrorOccurred.addListener(httpAuth.requestCompleted, opts); browser.webRequest.onErrorOccurred.addListener(httpAuth.requestCompleted, opts);
} }
}; };
httpAuth.requestCompleted = function(details) { httpAuth.requestCompleted = function(details) {
let index = httpAuth.requests.indexOf(details.requestId); let index = httpAuth.requests.indexOf(details.requestId);
if (index >= 0) { if (index >= 0) {
httpAuth.requests.splice(index, 1); httpAuth.requests.splice(index, 1);
} }
}; };
httpAuth.handleRequestPromise = function(details) { httpAuth.handleRequestPromise = function(details) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
httpAuth.processPendingCallbacks(details, resolve, reject); httpAuth.processPendingCallbacks(details, resolve, reject);
}); });
}; };
httpAuth.handleRequestCallback = function(details, callback) { httpAuth.handleRequestCallback = function(details, callback) {
httpAuth.processPendingCallbacks(details, callback, callback); httpAuth.processPendingCallbacks(details, callback, callback);
}; };
httpAuth.processPendingCallbacks = function(details, resolve, reject) { httpAuth.processPendingCallbacks = function(details, resolve, reject) {
if (httpAuth.requests.indexOf(details.requestId) >= 0 || !page.tabs[details.tabId]) { if (httpAuth.requests.indexOf(details.requestId) >= 0 || !page.tabs[details.tabId]) {
reject({}); reject({});
return; return;
} }
httpAuth.requests.push(details.requestId); httpAuth.requests.push(details.requestId);
if (details.challenger) { if (details.challenger) {
details.proxyUrl = details.challenger.host; details.proxyUrl = details.challenger.host;
} }
details.searchUrl = (details.isProxy && details.proxyUrl) ? details.proxyUrl : details.url; details.searchUrl = (details.isProxy && details.proxyUrl) ? details.proxyUrl : details.url;
keepass.retrieveCredentials((logins) => { keepass.retrieveCredentials((logins) => {
httpAuth.loginOrShowCredentials(logins, details, resolve, reject); httpAuth.loginOrShowCredentials(logins, details, resolve, reject);
}, { "id": details.tabId }, details.searchUrl, details.searchUrl, true); }, { "id": details.tabId }, details.searchUrl, details.searchUrl, true);
}; };
httpAuth.loginOrShowCredentials = function(logins, details, resolve, reject) { httpAuth.loginOrShowCredentials = function(logins, details, resolve, reject) {
// at least one login found --> use first to login // at least one login found --> use first to login
if (logins.length > 0 && page.settings.autoFillAndSend) { if (logins.length > 0 && page.settings.autoFillAndSend) {
if (logins.length === 1) { if (logins.length === 1) {
resolve({ resolve({
authCredentials: { authCredentials: {
username: logins[0].login, username: logins[0].login,
password: logins[0].password password: logins[0].password
} }
}); });
} else { } else {
kpxcEvent.onHTTPAuthPopup(null, { 'id': details.tabId }, { 'logins': logins, 'url': details.searchUrl, 'resolve': resolve }); kpxcEvent.onHTTPAuthPopup(null, { 'id': details.tabId }, { 'logins': logins, 'url': details.searchUrl, 'resolve': resolve });
} }
} }
// no logins found // no logins found
else { else {
reject({}); reject({});
} }
}; };

View file

@ -1,14 +1,14 @@
keepass.migrateKeyRing().then(() => { keepass.migrateKeyRing().then(() => {
page.initSettings().then(() => { page.initSettings().then(() => {
page.initOpenedTabs().then(() => { page.initOpenedTabs().then(() => {
httpAuth.init(); httpAuth.init();
keepass.connectToNative(); keepass.connectToNative();
keepass.generateNewKeyPair(); keepass.generateNewKeyPair();
keepass.changePublicKeys(null).then((pkRes) => { keepass.changePublicKeys(null).then((pkRes) => {
keepass.getDatabaseHash((gdRes) => {}, null); keepass.getDatabaseHash((gdRes) => {}, null);
}); });
}); });
}); });
}); });
// Milliseconds for intervall (e.g. to update browserAction) // Milliseconds for intervall (e.g. to update browserAction)
@ -21,13 +21,13 @@ const _interval = 250;
* @param {object} tab * @param {object} tab
*/ */
browser.tabs.onCreated.addListener((tab) => { browser.tabs.onCreated.addListener((tab) => {
if (tab.id > 0) { if (tab.id > 0) {
//console.log('browser.tabs.onCreated(' + tab.id+ ')'); //console.log('browser.tabs.onCreated(' + tab.id+ ')');
if (tab.selected) { if (tab.selected) {
page.currentTabId = tab.id; page.currentTabId = tab.id;
kpxcEvent.invoke(page.switchTab, null, tab.id, []); kpxcEvent.invoke(page.switchTab, null, tab.id, []);
} }
} }
}); });
/** /**
@ -36,10 +36,10 @@ browser.tabs.onCreated.addListener((tab) => {
* @param {object} removeInfo * @param {object} removeInfo
*/ */
browser.tabs.onRemoved.addListener((tabId, removeInfo) => { browser.tabs.onRemoved.addListener((tabId, removeInfo) => {
delete page.tabs[tabId]; delete page.tabs[tabId];
if (page.currentTabId === tabId) { if (page.currentTabId === tabId) {
page.currentTabId = -1; page.currentTabId = -1;
} }
}); });
/** /**
@ -48,19 +48,19 @@ browser.tabs.onRemoved.addListener((tabId, removeInfo) => {
* @param {object} activeInfo * @param {object} activeInfo
*/ */
browser.tabs.onActivated.addListener((activeInfo) => { browser.tabs.onActivated.addListener((activeInfo) => {
// remove possible credentials from old tab information // remove possible credentials from old tab information
page.clearCredentials(page.currentTabId, true); page.clearCredentials(page.currentTabId, true);
browserAction.removeRememberPopup(null, {'id': page.currentTabId}, true); browserAction.removeRememberPopup(null, {'id': page.currentTabId}, true);
browser.tabs.get(activeInfo.tabId).then((info) => { browser.tabs.get(activeInfo.tabId).then((info) => {
if (info && info.id) { if (info && info.id) {
page.currentTabId = info.id; page.currentTabId = info.id;
if (info.status === 'complete') { if (info.status === 'complete') {
//console.log('kpxcEvent.invoke(page.switchTab, null, '+info.id + ', []);'); //console.log('kpxcEvent.invoke(page.switchTab, null, '+info.id + ', []);');
kpxcEvent.invoke(page.switchTab, null, info.id, []); kpxcEvent.invoke(page.switchTab, null, info.id, []);
} }
} }
}); });
}); });
/** /**
@ -69,60 +69,68 @@ browser.tabs.onActivated.addListener((activeInfo) => {
* @param {object} changeInfo * @param {object} changeInfo
*/ */
browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => { browser.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
if (changeInfo.status === 'complete') { if (changeInfo.status === 'complete') {
kpxcEvent.invoke(browserAction.removeRememberPopup, null, tabId, []); kpxcEvent.invoke(browserAction.removeRememberPopup, null, tabId, []);
} }
}); });
browser.runtime.onMessage.addListener(kpxcEvent.onMessage); browser.runtime.onMessage.addListener(kpxcEvent.onMessage);
const contextMenuItems = [ const contextMenuItems = [
{title: 'Fill User + Pass', action: 'fill_user_pass'}, {title: 'Fill User + Pass', action: 'fill_user_pass'},
{title: 'Fill Pass Only', action: 'fill_pass_only'}, {title: 'Fill Pass Only', action: 'fill_pass_only'},
{title: 'Fill TOTP', action: 'fill_totp'}, {title: 'Fill TOTP', action: 'fill_totp'},
{title: 'Show Password Generator Icons', action: 'activate_password_generator'}, {title: 'Show Password Generator Icons', action: 'activate_password_generator'},
{title: 'Save credentials', action: 'remember_credentials'} {title: 'Save credentials', action: 'remember_credentials'}
]; ];
let menuContexts = ['editable']; let menuContexts = ['editable'];
if (isFirefox()) { if (isFirefox()) {
menuContexts.push('password'); menuContexts.push('password');
} }
// Create context menu items // Create context menu items
for (const item of contextMenuItems) { for (const item of contextMenuItems) {
browser.contextMenus.create({ browser.contextMenus.create({
title: item.title, title: item.title,
contexts: menuContexts, contexts: menuContexts,
onclick: (info, tab) => { onclick: (info, tab) => {
browser.tabs.sendMessage(tab.id, { browser.tabs.sendMessage(tab.id, {
action: item.action action: item.action
}).catch((e) => {console.log(e);}); }).catch((e) => {console.log(e);});
} }
}); });
} }
// Listen for keyboard shortcuts specified by user // Listen for keyboard shortcuts specified by user
browser.commands.onCommand.addListener((command) => { browser.commands.onCommand.addListener((command) => {
if (command === 'fill-username-password') { if (command === 'fill-username-password') {
browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => { browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => {
if (tabs.length) { if (tabs.length) {
browser.tabs.sendMessage(tabs[0].id, { action: 'fill_user_pass' }); browser.tabs.sendMessage(tabs[0].id, { action: 'fill_user_pass' });
} }
}); });
} }
if (command === 'fill-password') { if (command === 'fill-password') {
browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => { browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => {
if (tabs.length) { if (tabs.length) {
browser.tabs.sendMessage(tabs[0].id, { action: 'fill_pass_only' }); browser.tabs.sendMessage(tabs[0].id, { action: 'fill_pass_only' });
} }
}); });
} }
if (command === 'fill-totp') {
browser.tabs.query({ active: true, currentWindow: true }).then((tabs) => {
if (tabs.length) {
browser.tabs.sendMessage(tabs[0].id, { action: 'fill_totp' });
}
});
}
}); });
// Interval which updates the browserAction (e.g. blinking icon) // Interval which updates the browserAction (e.g. blinking icon)
window.setInterval(function() { window.setInterval(function() {
browserAction.update(_interval); browserAction.update(_interval);
}, _interval); }, _interval);

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,10 @@
const defaultSettings = { const defaultSettings = {
checkUpdateKeePassXC: 3, checkUpdateKeePassXC: 3,
autoCompleteUsernames: true, autoCompleteUsernames: true,
autoFillAndSend: true, autoFillAndSend: true,
usePasswordGenerator: true, usePasswordGenerator: true,
autoFillSingleEntry: false, autoFillSingleEntry: false,
autoRetrieveCredentials: true autoRetrieveCredentials: true
}; };
var page = {}; var page = {};
@ -13,72 +13,72 @@ page.currentTabId = -1;
page.blockedTabs = {}; page.blockedTabs = {};
page.initSettings = function() { page.initSettings = function() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
browser.storage.local.get({'settings': {}}).then((item) => { browser.storage.local.get({'settings': {}}).then((item) => {
page.settings = item.settings; page.settings = item.settings;
if (!('checkUpdateKeePassXC' in page.settings)) { if (!('checkUpdateKeePassXC' in page.settings)) {
page.settings.checkUpdateKeePassXC = defaultSettings.checkUpdateKeePassXC; page.settings.checkUpdateKeePassXC = defaultSettings.checkUpdateKeePassXC;
} }
if (!('autoCompleteUsernames' in page.settings)) { if (!('autoCompleteUsernames' in page.settings)) {
page.settings.autoCompleteUsernames = defaultSettings.autoCompleteUsernames; page.settings.autoCompleteUsernames = defaultSettings.autoCompleteUsernames;
} }
if (!('autoFillAndSend' in page.settings)) { if (!('autoFillAndSend' in page.settings)) {
page.settings.autoFillAndSend = defaultSettings.autoFillAndSend; page.settings.autoFillAndSend = defaultSettings.autoFillAndSend;
} }
if (!('usePasswordGenerator' in page.settings)) { if (!('usePasswordGenerator' in page.settings)) {
page.settings.usePasswordGenerator = defaultSettings.usePasswordGenerator; page.settings.usePasswordGenerator = defaultSettings.usePasswordGenerator;
} }
if (!('autoFillSingleEntry' in page.settings)) { if (!('autoFillSingleEntry' in page.settings)) {
page.settings.autoFillSingleEntry = defaultSettings.autoFillSingleEntry; page.settings.autoFillSingleEntry = defaultSettings.autoFillSingleEntry;
} }
if (!('autoRetrieveCredentials' in page.settings)) { if (!('autoRetrieveCredentials' in page.settings)) {
page.settings.autoRetrieveCredentials = defaultSettings.autoRetrieveCredentials; page.settings.autoRetrieveCredentials = defaultSettings.autoRetrieveCredentials;
} }
browser.storage.local.set({'settings': page.settings}); browser.storage.local.set({'settings': page.settings});
resolve(page.settings); resolve(page.settings);
}); });
}); });
}; };
page.initOpenedTabs = function() { page.initOpenedTabs = function() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
browser.tabs.query({}).then((tabs) => { browser.tabs.query({}).then((tabs) => {
for (const i of tabs) { for (const i of tabs) {
page.createTabEntry(i.id); page.createTabEntry(i.id);
} }
// set initial tab-ID // set initial tab-ID
browser.tabs.query({ 'active': true, 'currentWindow': true }).then((tabs) => { browser.tabs.query({ 'active': true, 'currentWindow': true }).then((tabs) => {
if (tabs.length === 0) { if (tabs.length === 0) {
resolve(); resolve();
return; // For example: only the background devtools or a popup are opened return; // For example: only the background devtools or a popup are opened
} }
page.currentTabId = tabs[0].id; page.currentTabId = tabs[0].id;
browserAction.show(null, tabs[0]); browserAction.show(null, tabs[0]);
resolve(); resolve();
}); });
}); });
}); });
}; };
page.isValidProtocol = function(url) { page.isValidProtocol = function(url) {
let protocol = url.substring(0, url.indexOf(':')); let protocol = url.substring(0, url.indexOf(':'));
protocol = protocol.toLowerCase(); protocol = protocol.toLowerCase();
return !(url.indexOf('.') === -1 || (protocol !== 'http' && protocol !== 'https' && protocol !== 'ftp' && protocol !== 'sftp')); return !(url.indexOf('.') === -1 || (protocol !== 'http' && protocol !== 'https' && protocol !== 'ftp' && protocol !== 'sftp'));
}; };
page.switchTab = function(callback, tab) { page.switchTab = function(callback, tab) {
browserAction.showDefault(null, tab); browserAction.showDefault(null, tab);
browser.tabs.sendMessage(tab.id, {action: 'activated_tab'}).catch((e) => {}); browser.tabs.sendMessage(tab.id, {action: 'activated_tab'}).catch((e) => {});
}; };
page.clearCredentials = function(tabId, complete) { page.clearCredentials = function(tabId, complete) {
if (!page.tabs[tabId]) { if (!page.tabs[tabId]) {
return; return;
} }
page.tabs[tabId].credentials = {}; page.tabs[tabId].credentials = {};
delete page.tabs[tabId].credentials; delete page.tabs[tabId].credentials;
if (complete) { if (complete) {
page.clearLogins(tabId); page.clearLogins(tabId);
@ -90,48 +90,48 @@ page.clearCredentials = function(tabId, complete) {
}; };
page.clearLogins = function(tabId) { page.clearLogins = function(tabId) {
page.tabs[tabId].loginList = []; page.tabs[tabId].loginList = [];
}; };
page.createTabEntry = function(tabId) { page.createTabEntry = function(tabId) {
page.tabs[tabId] = { page.tabs[tabId] = {
'stack': [], 'stack': [],
'errorMessage': null, 'errorMessage': null,
'loginList': {} 'loginList': {}
}; };
}; };
page.removePageInformationFromNotExistingTabs = function() { page.removePageInformationFromNotExistingTabs = function() {
let rand = Math.floor(Math.random()*1001); let rand = Math.floor(Math.random()*1001);
if (rand === 28) { if (rand === 28) {
browser.tabs.query({}).then(function(tabs) { browser.tabs.query({}).then(function(tabs) {
let $tabIds = []; let $tabIds = [];
const $infoIds = Object.keys(page.tabs); const $infoIds = Object.keys(page.tabs);
for (const t of tabs) { for (const t of tabs) {
$tabIds[t.id] = true; $tabIds[t.id] = true;
} }
for (const i of $infoIds) { for (const i of $infoIds) {
if (!(i in $tabIds)) { if (!(i in $tabIds)) {
delete page.tabs[i]; delete page.tabs[i];
} }
} }
}); });
} }
}; };
page.debugConsole = function() { page.debugConsole = function() {
if (arguments.length > 1) { if (arguments.length > 1) {
console.log(page.sprintf(arguments[0], arguments)); console.log(page.sprintf(arguments[0], arguments));
} }
else { else {
console.log(arguments[0]); console.log(arguments[0]);
} }
}; };
page.sprintf = function(input, args) { page.sprintf = function(input, args) {
return input.replace(/{(\d+)}/g, (match, number) => { return input.replace(/{(\d+)}/g, (match, number) => {
return typeof args[number] !== 'undefined' ? (typeof args[number] === 'object' ? JSON.stringify(args[number]) : args[number]) : match; return typeof args[number] !== 'undefined' ? (typeof args[number] === 'object' ? JSON.stringify(args[number]) : args[number]) : match;
}); });
}; };
@ -141,12 +141,12 @@ page.debugDummy = function() {};
page.debug = page.debugDummy; page.debug = page.debugDummy;
page.setDebug = function(bool) { page.setDebug = function(bool) {
if (bool) { if (bool) {
page.debug = page.debugConsole; page.debug = page.debugConsole;
return 'Debug mode enabled'; return 'Debug mode enabled';
} }
else { else {
page.debug = page.debugDummy; page.debug = page.debugDummy;
return 'Debug mode disabled'; return 'Debug mode disabled';
} }
}; };

View file

@ -1,6 +1,6 @@
var isFirefox = function() { var isFirefox = function() {
if (!(/Chrome/.test(navigator.userAgent) && /Google/.test(navigator.vendor))) { if (!(/Chrome/.test(navigator.userAgent) && /Google/.test(navigator.vendor))) {
return true; return true;
} }
return false; return false;
}; };

View file

@ -1,22 +1,22 @@
.kpxc .ui-autocomplete li.ui-menu-item { .kpxc .ui-autocomplete li.ui-menu-item {
text-align: left !important; text-align: left !important;
font-size: .9em !important; font-size: .9em !important;
font-weight: normal !important; font-weight: normal !important;
font-style: normal !important; font-style: normal !important;
font-family: Verdana, Arial, sans-serif !important; font-family: Verdana, Arial, sans-serif !important;
color: #222222 !important; color: #222222 !important;
} }
.ui-helper-hidden-accessible { .ui-helper-hidden-accessible {
display: none !important; display: none !important;
} }
.kpxc .ui-dialog-titlebar-close { .kpxc .ui-dialog-titlebar-close {
visibility: hidden !important; visibility: hidden !important;
} }
.kpxc .ui-dialog { .kpxc .ui-dialog {
font-size: 12px !important; font-size: 12px !important;
} }
.kpxc .ui-widget-overlay { .kpxc .ui-widget-overlay {
@ -24,12 +24,12 @@
} }
.kpxc .dialog-form .ui-dialog-content .ui-widget-content { .kpxc .dialog-form .ui-dialog-content .ui-widget-content {
max-height: 80px !important; max-height: 80px !important;
} }
.kpxc .ui-dialog-titlebar { .kpxc .ui-dialog-titlebar {
background-color: #3a8233; background-color: #3a8233;
color: #fff; color: #fff;
} }
.kpxc .ui-dialog .ui-dialog-buttonpane { .kpxc .ui-dialog .ui-dialog-buttonpane {
@ -41,164 +41,164 @@
} }
.kpxc .ui-button .ui-button-text .ui-button { .kpxc .ui-button .ui-button-text .ui-button {
font-size: .10em !important; font-size: .10em !important;
} }
input.genpw-text { input.genpw-text {
font-size: .9em !important; font-size: .9em !important;
padding: .4em; padding: .4em;
border-radius: 4px; border-radius: 4px;
border-top-right-radius: 0; border-top-right-radius: 0;
border-bottom-right-radius: 0; border-bottom-right-radius: 0;
border-collapse: separate; border-collapse: separate;
width: 100%; width: 100%;
} }
.genpw-input-group-addon { .genpw-input-group-addon {
font-size: inherit !important; font-size: inherit !important;
background-color: #eee; background-color: #eee;
border: 1px solid #ccc; border: 1px solid #ccc;
padding: .4em; padding: .4em;
border-radius: 4px; border-radius: 4px;
border-top-left-radius: 0; border-top-left-radius: 0;
border-bottom-left-radius: 0; border-bottom-left-radius: 0;
white-space: nowrap; white-space: nowrap;
vertical-align: middle; vertical-align: middle;
display: table-cell; display: table-cell;
border-collapse: separate; border-collapse: separate;
} }
.kpxc .genpw-input-group { .kpxc .genpw-input-group {
position: relative; position: relative;
display: table; display: table;
border-collapse: separate; border-collapse: separate;
width: 100%; width: 100%;
} }
.cip-genpw-icon { .cip-genpw-icon {
position: absolute; position: absolute;
cursor: pointer; cursor: pointer;
} }
.cip-genpw-icon.key { .cip-genpw-icon.key {
background: url('chrome-extension://__MSG_@@extension_id__/icons/key.png') right no-repeat; background: url('chrome-extension://__MSG_@@extension_id__/icons/key.png') right no-repeat;
background-size: contain; background-size: contain;
} }
.cip-genpw-icon.key-moz { .cip-genpw-icon.key-moz {
background: url('moz-extension://__MSG_@@extension_id__/icons/key.png') right no-repeat; background: url('moz-extension://__MSG_@@extension_id__/icons/key.png') right no-repeat;
background-size: contain; background-size: contain;
} }
.kpxc .cip-genpw-checkbox { .kpxc .cip-genpw-checkbox {
-webkit-appearance: checkbox !important; -webkit-appearance: checkbox !important;
-moz-appearance: checkbox !important; -moz-appearance: checkbox !important;
appearance: checkbox !important; appearance: checkbox !important;
} }
#cip-genpw-btn-fillin { #cip-genpw-btn-fillin {
margin-right: 5px; margin-right: 5px;
} }
.b2c-modal-backdrop { .b2c-modal-backdrop {
position: fixed; position: fixed;
top: 0; top: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
z-index: 2147483645; z-index: 2147483645;
} }
.b2c-modal-backdrop:after { .b2c-modal-backdrop:after {
content:''; content:'';
position: fixed; position: fixed;
top: 0; top: 0;
right: 0; right: 0;
bottom: 0; bottom: 0;
left: 0; left: 0;
background-color: #000000; background-color: #000000;
opacity: 0.8; opacity: 0.8;
filter: alpha(opacity=80); filter: alpha(opacity=80);
} }
#b2c-cipDefine-fields { #b2c-cipDefine-fields {
z-index: 2147483646; z-index: 2147483646;
} }
#b2c-cipDefine-description { #b2c-cipDefine-description {
z-index: 2147483646; z-index: 2147483646;
color: #efefef; color: #efefef;
border: 2px solid #555555; border: 2px solid #555555;
padding: 7px 5px; padding: 7px 5px;
position: absolute; position: absolute;
top: 100px; top: 100px;
left: 150px; left: 150px;
text-align: left; text-align: left;
cursor: pointer; cursor: pointer;
background-color:rgba(255,255,255,0.3); background-color:rgba(255,255,255,0.3);
font-size: 15px; font-size: 15px;
} }
#b2c-cipDefine-description div:first-of-type { #b2c-cipDefine-description div:first-of-type {
margin-top: 0; margin-top: 0;
padding-top: 0; padding-top: 0;
text-align: left; text-align: left;
color: #efefef; color: #efefef;
padding-bottom: 8px; padding-bottom: 8px;
font-weight: bold; font-weight: bold;
font-size: 160%; font-size: 160%;
} }
#b2c-cipDefine-description p { #b2c-cipDefine-description p {
margin-top: 10px; margin-top: 10px;
padding-top: 10px; padding-top: 10px;
color: #efefef; color: #efefef;
border-top: 2px solid #666666; border-top: 2px solid #666666;
line-height: 110%; line-height: 110%;
} }
#b2c-help { #b2c-help {
margin-bottom: 3px; margin-bottom: 3px;
} }
.b2c-fixed-field { .b2c-fixed-field {
position: absolute; position: absolute;
border: 2px solid #efefef; border: 2px solid #efefef;
cursor: pointer; cursor: pointer;
z-index: 2147483646; z-index: 2147483646;
text-align: left; text-align: left;
font-weight: bold; font-weight: bold;
background-color:rgba(239,239,239,0.4); background-color:rgba(239,239,239,0.4);
} }
.b2c-fixed-hover-field { .b2c-fixed-hover-field {
border: 2px solid orange; border: 2px solid orange;
background-color:rgba(255,165,239,0.4); background-color:rgba(255,165,239,0.4);
} }
.b2c-fixed-password-field { .b2c-fixed-password-field {
border: 2px solid red; border: 2px solid red;
color: #efefef; color: #efefef;
background-color:rgba(255,0,0,0.4); background-color:rgba(255,0,0,0.4);
} }
.b2c-fixed-username-field { .b2c-fixed-username-field {
border: 2px solid limegreen; border: 2px solid limegreen;
color: #efefef; color: #efefef;
background-color:rgba(50,205,50,0.4); background-color:rgba(50,205,50,0.4);
} }
.b2c-fixed-string-field { .b2c-fixed-string-field {
border: 2px solid deepskyblue; border: 2px solid deepskyblue;
color: #efefef; color: #efefef;
background-color:rgba(30,144,255,0.4); background-color:rgba(30,144,255,0.4);
} }
.b2c-input-append { .b2c-input-append {
display: inline-block; display: inline-block;
margin-bottom: 10px; margin-bottom: 10px;
white-space: nowrap; white-space: nowrap;
vertical-align: middle; vertical-align: middle;
} }
.b2c-input-append input, .b2c-input-append input,
@ -206,23 +206,23 @@ input.genpw-text {
.b2c-input-append .b2c-uneditable-input, .b2c-input-append .b2c-uneditable-input,
.b2c-input-append .b2c-dropdown-menu, .b2c-input-append .b2c-dropdown-menu,
.b2c-input-append .b2c-popover { .b2c-input-append .b2c-popover {
font-size: 14px; font-size: 14px;
} }
.b2c-input-append input, .b2c-input-append input,
.b2c-input-append select, .b2c-input-append select,
.b2c-input-append .b2c-uneditable-input { .b2c-input-append .b2c-uneditable-input {
position: relative; position: relative;
margin-bottom: 0; margin-bottom: 0;
*margin-left: 0; *margin-left: 0;
vertical-align: top; vertical-align: top;
-webkit-border-radius: 0 4px 4px 0; -webkit-border-radius: 0 4px 4px 0;
-moz-border-radius: 0 4px 4px 0; -moz-border-radius: 0 4px 4px 0;
border-radius: 0 4px 4px 0; border-radius: 0 4px 4px 0;
} }
.b2c-input-append input:focus, .b2c-input-append input:focus,
.b2c-input-append select:focus, .b2c-input-append select:focus,
.b2c-input-append .b2c-b2c-uneditable-input:focus { .b2c-input-append .b2c-b2c-uneditable-input:focus {
z-index: 2; z-index: 2;
} }

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,7 @@
{ {
"manifest_version": 2, "manifest_version": 2,
"name": "keepassxc-browser", "name": "KeePassXC-Browser",
"version": "0.4.8", "version": "0.5.0",
"description": "KeePassXC integration for modern web browsers", "description": "KeePassXC integration for modern web browsers",
"author": "KeePassXC Team", "author": "KeePassXC Team",
"icons": { "icons": {
@ -15,7 +15,7 @@
"19": "icons/keepassxc_19x19.png", "19": "icons/keepassxc_19x19.png",
"38": "icons/keepassxc_38x38.png" "38": "icons/keepassxc_38x38.png"
}, },
"default_title": "keepassxc-browser", "default_title": "KeePassXC-Browser",
"default_popup": "popups/popup.html" "default_popup": "popups/popup.html"
}, },
"options_ui": { "options_ui": {
@ -65,16 +65,23 @@
"description": "Insert username + password", "description": "Insert username + password",
"suggested_key": { "suggested_key": {
"default": "Alt+Shift+U", "default": "Alt+Shift+U",
"mac": "Alt+Shift+U" "mac": "MacCtrl+Shift+U"
} }
}, },
"fill-password": { "fill-password": {
"description": "Insert a password", "description": "Insert a password",
"suggested_key": { "suggested_key": {
"default": "Alt+Shift+P", "default": "Alt+Shift+P",
"mac": "Alt+Shift+P" "mac": "MacCtrl+Shift+P"
} }
} },
"fill-totp": {
"description": "Insert a TOTP",
"suggested_key": {
"default": "Alt+Shift+T",
"mac": "MacCtrl+Shift+T"
}
}
}, },
"web_accessible_resources": [ "web_accessible_resources": [
"icons/key.png" "icons/key.png"

View file

@ -1,143 +1,142 @@
body { body {
padding-top: 20px; padding-top: 20px;
padding-bottom: 60px; padding-bottom: 60px;
} }
/* Custom container */ /* Custom container */
.container { .container {
margin: 0 auto; margin: 0 auto;
max-width: 1000px; max-width: 1000px;
} }
.container > hr { .container > hr {
margin: 30px 0; margin: 30px 0;
} }
/* Custom navbar */ /* Custom navbar */
.navbar-default { .navbar-default {
background-color: #3a8233; background-color: #3a8233;
border-color: #01520e; border-color: #01520e;
display: inline-block; display: inline-block;
float: none; float: none;
width: 100%; width: 100%;
} }
.navbar-default .navbar-brand { .navbar-default .navbar-brand {
color: #ffffff; color: #ffffff;
} }
.navbar-default .navbar-brand:hover, .navbar-default .navbar-brand:hover,
.navbar-default .navbar-brand:focus { .navbar-default .navbar-brand:focus {
color: #ffffff; color: #ffffff;
} }
.navbar-default .navbar-text { .navbar-default .navbar-text {
color: #ffffff; color: #ffffff;
} }
.navbar-default .navbar-nav > li > a { .navbar-default .navbar-nav > li > a {
color: #ffffff; color: #ffffff;
text-align: center;
text-align: center;
} }
.navbar-default .navbar-nav > li > a:hover, .navbar-default .navbar-nav > li > a:hover,
.navbar-default .navbar-nav > li > a:focus { .navbar-default .navbar-nav > li > a:focus {
color: #cccccc; color: #cccccc;
} }
.navbar-default .navbar-nav > .active > a, .navbar-default .navbar-nav > .active > a,
.navbar-default .navbar-nav > .active > a:hover, .navbar-default .navbar-nav > .active > a:hover,
.navbar-default .navbar-nav > .active > a:focus { .navbar-default .navbar-nav > .active > a:focus {
color: #ffffff; color: #ffffff;
background-color: #01520e; background-color: #01520e;
} }
.navbar-default .navbar-nav > .open > a, .navbar-default .navbar-nav > .open > a,
.navbar-default .navbar-nav > .open > a:hover, .navbar-default .navbar-nav > .open > a:hover,
.navbar-default .navbar-nav > .open > a:focus { .navbar-default .navbar-nav > .open > a:focus {
color: #ffffff; color: #ffffff;
background-color: #01520e; background-color: #01520e;
} }
.navbar-default .navbar-toggle { .navbar-default .navbar-toggle {
border-color: #01520e; border-color: #01520e;
} }
.navbar-default .navbar-toggle:hover, .navbar-default .navbar-toggle:hover,
.navbar-default .navbar-toggle:focus { .navbar-default .navbar-toggle:focus {
background-color: #01520e; background-color: #01520e;
} }
.navbar-default .navbar-toggle .icon-bar { .navbar-default .navbar-toggle .icon-bar {
background-color: #ffffff; background-color: #ffffff;
} }
.navbar-default .navbar-collapse, .navbar-default .navbar-collapse,
.navbar-default .navbar-form { .navbar-default .navbar-form {
border-color: #ffffff; border-color: #ffffff;
} }
.navbar-default .navbar-link { .navbar-default .navbar-link {
color: #ffffff; color: #ffffff;
} }
.navbar-default .navbar-link:hover { .navbar-default .navbar-link:hover {
color: #ffffff; color: #ffffff;
} }
@media (max-width: 767px) { @media (max-width: 767px) {
.navbar-default .navbar-nav .open .dropdown-menu > li > a { .navbar-default .navbar-nav .open .dropdown-menu > li > a {
color: #ffffff; color: #ffffff;
} }
.navbar-default .navbar-nav .open .dropdown-menu > li > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,
.navbar-default .navbar-nav .open .dropdown-menu > li > a:focus { .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {
color: #ffffff; color: #ffffff;
} }
.navbar-default .navbar-nav .open .dropdown-menu > .active > a, .navbar-default .navbar-nav .open .dropdown-menu > .active > a,
.navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover, .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,
.navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus { .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {
color: #ffffff; color: #ffffff;
background-color: #01520e; background-color: #01520e;
} }
} }
.tab { .tab {
display: none; display: none;
} }
h2+hr { h2+hr {
margin-top: 0; margin-top: 0;
} }
#tab-connected-databases .color.dropdown .dropdown-menu { #tab-connected-databases .color.dropdown .dropdown-menu {
width: 180px; width: 180px;
padding: 7px 10px; padding: 7px 10px;
line-height: 175%; line-height: 175%;
} }
#tab-connected-databases .color.dropdown .dropdown-menu a { #tab-connected-databases .color.dropdown .dropdown-menu a {
margin-right: 3px; margin-right: 3px;
} }
#tab-connected-databases .color.dropdown a.dropdown-toggle img { #tab-connected-databases .color.dropdown a.dropdown-toggle img {
margin-right: 5px; margin-right: 5px;
} }
tr.clone { tr.clone {
display: none; display: none;
} }
td.last-used, td.last-used,
td.created { td.created {
white-space: nowrap; white-space: nowrap;
} }
.bold { .bold {
font-weight: bold; font-weight: bold;
} }
.radio.inline, .radio.inline,
.checkbox.inline { .checkbox.inline {
display: inline-block; display: inline-block;
white-space: nowrap; white-space: nowrap;
} }
.radio.inline + .radio.inline, .radio.inline + .radio.inline,
.checkbox.inline + .checkbox.inline { .checkbox.inline + .checkbox.inline {
margin-left: 40px; margin-left: 40px;
} }
.checkUpdateKeePassXC { .checkUpdateKeePassXC {
margin-left: 40px; margin-left: 40px;
} }
#dangerousSettings { #dangerousSettings {
display: none; display: none;
} }

View file

@ -1,297 +1,300 @@
<!DOCTYPE html> <!DOCTYPE html>
<html> <html>
<head> <head>
<title>Settings | keepassxc-browser</title> <title>Settings | KeePassXC-Browser</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="stylesheet" href="bootstrap.min.css" /> <link rel="stylesheet" href="bootstrap.min.css" />
<link rel="stylesheet" href="options.css" /> <link rel="stylesheet" href="options.css" />
<script type="text/javascript" src="../browser-polyfill.min.js"></script> <script type="text/javascript" src="../browser-polyfill.min.js"></script>
<script type="text/javascript" src="../global.js"></script> <script type="text/javascript" src="../global.js"></script>
<script type="text/javascript" src="../jquery-3.2.1.min.js"></script> <script type="text/javascript" src="../jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="bootstrap.min.js"></script> <script type="text/javascript" src="bootstrap.min.js"></script>
<script type="text/javascript" src="options.js"></script> <script type="text/javascript" src="options.js"></script>
</head> </head>
<body> <body>
<div class="container"> <div class="container">
<h3 class="muted"><img src="/icons/keepassxc_48x48.png" alt="logo" /> keepassxc-browser</h3> <h3 class="muted"><img src="/icons/keepassxc_48x48.png" alt="logo" /> KeePassXC-Browser</h3>
<nav class="navbar navbar-default"> <nav class="navbar navbar-default">
<ul class="nav navbar-nav"> <ul class="nav navbar-nav">
<li class="active"><a href="#general-settings">General</a></li> <li class="active"><a href="#general-settings">General</a></li>
<li><a href="#connected-databases">Connected Databases</a></li> <li><a href="#connected-databases">Connected Databases</a></li>
<li><a href="#specified-fields">Specified credential fields</a></li> <li><a href="#specified-fields">Specified credential fields</a></li>
<li><a href="#about">About</a></li> <li><a href="#about">About</a></li>
</ul> </ul>
</nav> </nav>
<!-- General Settings --> <!-- General Settings -->
<div class="tab" id="tab-general-settings"> <div class="tab" id="tab-general-settings">
<h2>General Settings</h2> <h2>General Settings</h2>
<hr /> <hr />
<p> <p>
If you just want to insert username + password into the fields where your focus is, press <code>Ctrl + Shift + U</code>. If you just want to insert username + password into the fields where your focus is, press <code>Ctrl + Shift + U</code>.
<br /> <br />
If you only want to insert the password, just press <code>Ctrl + Shift + P</code>. If you only want to insert the password, just press <code>Ctrl + Shift + P</code>.
<span id="chrome-only">You can customize these shortcuts on <code>chrome://extensions/configureCommands</code> page</span> <span id="chrome-only">You can customize these shortcuts on <code>chrome://extensions/configureCommands</code> page</span>
</p> </p>
<p> <p>
<div class="form-group"> <div class="form-group">
<label for="blinkTimeout">Blink Time:</label> <label for="blinkTimeout">Blink Time:</label>
<div class="control-group"> <div class="control-group">
<div class="input-append"> <div class="input-append">
<input type="number" id="blinkTimeout" placeholder="7500" value="7500" /> <input type="number" id="blinkTimeout" placeholder="7500" value="7500" />
<button class="btn btn-sm btn-primary" id="blinkTimeoutButton" type="button"><span class="glyphicon glyphicon-floppy-disk"></span> Save</button> <button class="btn btn-sm btn-primary" id="blinkTimeoutButton" type="button"><span class="glyphicon glyphicon-floppy-disk"></span> Save</button>
</div> </div>
</div> </div>
<span class="help-inline"> <span class="help-inline">
What is the maximum time (ms) the icon should blink after detecting new credentials What is the maximum time (ms) the icon should blink after detecting new credentials
<br /> <br />
Default: 7500 Default: 7500
</span> </span>
</div> </div>
</p> </p>
<p> <p>
<div class="form-group"> <div class="form-group">
<label for="blinkMinTimeout">Redirect Offset:</label> <label for="blinkMinTimeout">Redirect Offset:</label>
<div class="control-group"> <div class="control-group">
<div class="input-append"> <div class="input-append">
<input type="number" id="blinkMinTimeout" placeholder="2000" value="2000" /> <input type="number" id="blinkMinTimeout" placeholder="2000" value="2000" />
<button class="btn btn-sm btn-primary" id="blinkMinTimeoutButton" type="button"><span class="glyphicon glyphicon-floppy-disk"></span> Save</button> <button class="btn btn-sm btn-primary" id="blinkMinTimeoutButton" type="button"><span class="glyphicon glyphicon-floppy-disk"></span> Save</button>
</div> </div>
</div> </div>
<span class="help-inline"> <span class="help-inline">
What is the minimum time (ms) the icon should blink before deactivating due to page redirects. What is the minimum time (ms) the icon should blink before deactivating due to page redirects.
<br /> <br />
-1 to only use <i>Blink Time</i> ignoring Redirect Allowance (old behavior) -1 to only use <i>Blink Time</i> ignoring Redirect Allowance (old behavior)
<br /> <br />
Default: -1, Recommended: 2000 Default: -1, Recommended: 2000
</span> </span>
</div> </div>
</p> </p>
<p> <p>
<div class="form-group"> <div class="form-group">
<label for="allowedRedirect">Redirect Allowance:</label> <label for="allowedRedirect">Redirect Allowance:</label>
<div class="control-group"> <div class="control-group">
<div class="input-append"> <div class="input-append">
<input type="number" id="allowedRedirect" placeholder="1" value="1" /> <input type="number" id="allowedRedirect" placeholder="1" value="1" />
<button class="btn btn-sm btn-primary" id="allowedRedirectButton" type="button"><span class="glyphicon glyphicon-floppy-disk"></span> Save</button> <button class="btn btn-sm btn-primary" id="allowedRedirectButton" type="button"><span class="glyphicon glyphicon-floppy-disk"></span> Save</button>
</div> </div>
</div> </div>
<span class="help-inline"> <span class="help-inline">
How many pages should the tab cycle through after the redirect offset before deactivating the icon How many pages should the tab cycle through after the redirect offset before deactivating the icon
<br /> <br />
Default: 1 Default: 1
</span> </span>
</div> </div>
</p> </p>
<hr /> <hr />
<p> <p>
<div class="checkbox"> <div class="checkbox">
<label class="checkbox"> <label class="checkbox">
<input type="checkbox" name="usePasswordGenerator" value="true" /> Activate password generator. <input type="checkbox" name="usePasswordGenerator" value="true" /> Activate password generator.
</label> </label>
<span class="help-block">For all password-fields there will be an icon added to generate a new password.<br /> <span class="help-block">
It is generated by KeePassXC with the profile for automatically generated passwords for new entries.</span> For all password-fields there will be an icon added to generate a new password.
</div> <br />
</p> It is generated by KeePassXC with the profile for automatically generated passwords for new entries.</span>
<hr /> </div>
<p> </p>
<div class="checkbox"> <hr />
<label class="checkbox"> <p>
<input type="checkbox" name="autoRetrieveCredentials" value="true" /> Automatically retrieve credentials. <div class="checkbox">
</label> <label class="checkbox">
<span class="help-block">keepassxc-browser will immediately retrieve the credentials when the tab is activated.</span> <input type="checkbox" name="autoRetrieveCredentials" value="true" /> Automatically retrieve credentials.
</div> </label>
</p> <span class="help-block">KeePassXC-Browser will immediately retrieve the credentials when the tab is activated.</span>
<hr /> </div>
<p> </p>
<div class="checkbox"> <hr />
<label class="checkbox"> <p>
<input type="checkbox" name="autoFillSingleEntry" value="false" /> Automatically fill-in single credentials entry. <div class="checkbox">
</label> <label class="checkbox">
<span class="help-block">If keepassxc-browser does only receive a single entry from KeePassXC it automatically fills this credentials into the found credential fields.</span> <input type="checkbox" name="autoFillSingleEntry" value="false" /> Automatically fill-in single credentials entry.
<span class="bg-danger">Warning! Using auto-fill is not safe. Use at your own risk.</span> </label>
</div> <span class="help-block">If KeePassXC-Browser does only receive a single entry from KeePassXC it automatically fills this credentials into the found credential fields.</span>
</p> <span class="bg-danger">Warning! Using auto-fill is not safe. Use at your own risk.</span>
<hr /> </div>
<p> </p>
<div class="checkbox"> <hr />
<label class="checkbox"> <p>
<input type="checkbox" name="autoCompleteUsernames" value="true" /> Activate autocomplete for username fields. <div class="checkbox">
</label> <label class="checkbox">
<span class="help-block">For all username fields on a page a dropdown list appears which contains all available credentials.</span> <input type="checkbox" name="autoCompleteUsernames" value="true" /> Activate autocomplete for username fields.
</div> </label>
</p> <span class="help-block">For all username fields on a page a dropdown list appears which contains all available credentials.</span>
<hr /> </div>
<p> </p>
Check for updates of KeePassXC: <hr />
<br /> <p>
<label class="radio-inline"><input type="radio" name="checkUpdateKeePassXC" value="3" /> every 3 days</label> Check for updates of KeePassXC:
<label class="radio-inline"><input type="radio" name="checkUpdateKeePassXC" value="7" /> every week</label> <br />
<label class="radio-inline"><input type="radio" name="checkUpdateKeePassXC" value="30" /> every month</label> <label class="radio-inline"><input type="radio" name="checkUpdateKeePassXC" value="3" /> every 3 days</label>
<label class="radio-inline"><input type="radio" name="checkUpdateKeePassXC" value="0" /> never</label> <label class="radio-inline"><input type="radio" name="checkUpdateKeePassXC" value="7" /> every week</label>
</p> <label class="radio-inline"><input type="radio" name="checkUpdateKeePassXC" value="30" /> every month</label>
<div class="help-block kphVersion"> <label class="radio-inline"><input type="radio" name="checkUpdateKeePassXC" value="0" /> never</label>
keepassxc-browser needs KeePassXC to retrieve credentials. </p>
<br /> <div class="help-block kphVersion">
You can download the latest stable version from here: <a target="_blank" href="https://keepassxc.org/">https://keepassxc.org/</a> KeePassXC-Browser needs KeePassXC to retrieve credentials.
<br /> <br />
<br /> You can download the latest stable version from here: <a target="_blank" href="https://keepassxc.org/">https://keepassxc.org/</a>
<div> <br />
You are running KeePassXC version: <em class="yourVersion"></em> <br />
</div> <div>
<div> You are running KeePassXC version: <em class="yourVersion"></em>
Latest available version of KeePassXC: <em class="latestVersion"></em> </div>
<button class="btn btn-sm btn-primary checkUpdateKeePassXC"><span class="glyphicon glyphicon-refresh"></span> Check for updates</button> <div>
</div> Latest available version of KeePassXC: <em class="latestVersion"></em>
</div> <button class="btn btn-sm btn-primary checkUpdateKeePassXC"><span class="glyphicon glyphicon-refresh"></span> Check for updates</button>
<hr /> </div>
<p> </div>
<div class="checkbox"> <hr />
<label class="checkbox"> <p>
<input type="checkbox" name="autoFillAndSend" value="1" /> Auto fill HTTP Auth dialogs and send them. <div class="checkbox">
</label> <label class="checkbox">
<span class="help-block"> <input type="checkbox" name="autoFillAndSend" value="1" /> Auto fill HTTP Auth dialogs and send them.
If credentials are found for a page and the login-type is an HTTP Auth request, keepassxc-browser tries to login with the first given credentials. </label>
<br /> <span class="help-block">
An HTTP Auth dialog looks like this: If credentials are found for a page and the login-type is an HTTP Auth request, KeePassXC-Browser tries to login with the first given credentials.
</span> <br />
</div> An HTTP Auth dialog looks like this:
<img src="/options/http-auth-dialog.png" alt="http-auth-dialog" /> </span>
</p> </div>
</div> <img src="/options/http-auth-dialog.png" alt="http-auth-dialog" />
</p>
</div>
<!-- Connected Databases --> <!-- Connected Databases -->
<div class="tab" id="tab-connected-databases"> <div class="tab" id="tab-connected-databases">
<h2>Connected Databases</h2> <h2>Connected Databases</h2>
<hr /> <hr />
<p> <p>
The following KeePassXC databases are connected to keepassxc-browser. The following KeePassXC databases are connected to KeePassXC-Browser.
</p> </p>
<table class="table table-striped table-bordered table-hover"> <table class="table table-striped table-bordered table-hover">
<thead> <thead>
<tr> <tr>
<th>Identifier</th> <th>Identifier</th>
<th>Key</th> <th>Key</th>
<th>Last used</th> <th>Last used</th>
<th>Created</th> <th>Created</th>
<th>Delete</th> <th>Delete</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr class="empty"> <tr class="empty">
<td colspan="5">No connected databases found.</td> <td colspan="5">No connected databases found.</td>
</tr> </tr>
<tr class="clone"> <tr class="clone">
<td></td> <td></td>
<td></td> <td></td>
<td class="last-used"></td> <td class="last-used"></td>
<td class="created"></td> <td class="created"></td>
<td><button class="btn delete btn-danger"><span class="glyphicon glyphicon-remove-sign"></span> Remove</button></td> <td><button class="btn delete btn-danger"><span class="glyphicon glyphicon-remove-sign"></span> Remove</button></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div style="text-align: right"> <div style="text-align: right">
<button id="connect-button" class="btn btn-primary"><span class="glyphicon glyphicon-link"></span> Connect</button> <button id="connect-button" class="btn btn-primary"><span class="glyphicon glyphicon-link"></span> Connect</button>
</div> </div>
<div id="dialogDeleteConnectedDatabase" class="modal fade" tabindex="-1" role="dialog"> <div id="dialogDeleteConnectedDatabase" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 class="modal-title" id="myModalLabel">Remove identifier from database list?</h3> <h3 class="modal-title" id="myModalLabel">Remove identifier from database list?</h3>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<p>Do you really want to remove the identifier <span class="bold"></span> from the database list?</p> <p>Do you really want to remove the identifier <span class="bold"></span> from the database list?</p>
<p class="help-block">You can reconnect your database at any time.</p> <p class="help-block">You can reconnect your database at any time.</p>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button class="btn btn-default" data-dismiss="modal" aria-hidden="true"><span class="glyphicon glyphicon-remove"></span> Cancel</button> <button class="btn btn-default" data-dismiss="modal" aria-hidden="true"><span class="glyphicon glyphicon-remove"></span> Cancel</button>
<button class="btn yes btn-primary"><span class="glyphicon glyphicon-ok"></span> Yes, remove now</button> <button class="btn yes btn-primary"><span class="glyphicon glyphicon-ok"></span> Yes, remove now</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- Specified credential fields --> <!-- Specified credential fields -->
<div class="tab" id="tab-specified-fields"> <div class="tab" id="tab-specified-fields">
<h2>Specified credential fields</h2> <h2>Specified credential fields</h2>
<hr /> <hr />
<p> <p>
If keepassxc-browser detects the wrong credential fields, you are able to specify the correct fields by yourself. If KeePassXC-Browser detects the wrong credential fields, you are able to specify the correct fields by yourself.
<br /> <br />
Just go to the page and click on the keepassxc-browser-Icon, now select <em>Choose own credential fields for this page</em>. Just go to the page and click on the KeePassXC-Browser-Icon, now select <em>Choose own credential fields for this page</em>.
<br /> <br />
On this page you can manage theses specified credential fields. On this page you can manage theses specified credential fields.
</p> </p>
<table class="table table-striped table-bordered table-hover"> <table class="table table-striped table-bordered table-hover">
<thead> <thead>
<tr> <tr>
<th>Page URL</th> <th>Page URL</th>
<th>Delete</th> <th>Delete</th>
</tr> </tr>
</thead> </thead>
<tbody> <tbody>
<tr class="empty"> <tr class="empty">
<td colspan="2">No specified credential fields found.</td> <td colspan="2">No specified credential fields found.</td>
</tr> </tr>
<tr class="clone"> <tr class="clone">
<td></td> <td></td>
<td><button class="btn delete btn-danger btn"><span class="glyphicon glyphicon-remove-sign"></span> Remove</button></td> <td><button class="btn delete btn-danger btn"><span class="glyphicon glyphicon-remove-sign"></span> Remove</button></td>
</tr> </tr>
</tbody> </tbody>
</table> </table>
<div id="dialogDeleteSpecifiedCredentialFields" class="modal fade" tabindex="-1" role="dialog"> <div id="dialogDeleteSpecifiedCredentialFields" class="modal fade" tabindex="-1" role="dialog">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h3 id="myModalLabel">Remove specified credential fields?</h3> <h3 id="myModalLabel">Remove specified credential fields?</h3>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<p>Do you really want to remove the specified credential fields on the page <strong></strong>?</p> <p>Do you really want to remove the specified credential fields on the page <strong></strong>?</p>
<p class="help-block">keepassxc-browser will automatically detect the credential fields the next time you visit this page.</p> <p class="help-block">KeePassXC-Browser will automatically detect the credential fields the next time you visit this page.</p>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button> <button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
<button class="btn yes btn-primary">Yes, remove now</button> <button class="btn yes btn-primary">Yes, remove now</button>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<!-- About --> <!-- About -->
<div class="tab" id="tab-about"> <div class="tab" id="tab-about">
<h2>About</h2> <h2>About</h2>
<hr /> <hr />
<p> <p>
Developed by <a target="_blank" href="https://github.com/pfn/">Perry Nguyen</a>, <a target="_blank" href="http://lukas-schulze.de">Lukas Schulze</a>, Developed by <a target="_blank" href="https://github.com/pfn/">Perry Nguyen</a>, <a target="_blank" href="http://lukas-schulze.de">Lukas Schulze</a>,
<a target="_blank" href="https://github.com/smorks">Andy Brandt</a> and <a target="_blank" href="https://github.com/varjolintu/">Sami Vänttinen</a> <a target="_blank" href="https://github.com/smorks">Andy Brandt</a> and <a target="_blank" href="https://github.com/varjolintu/">Sami Vänttinen</a>
</p> </p>
<p> <p>
<a target="_blank" href="https://chrome.google.com/webstore/detail/keepassxc-browser/iopaggbpplllidnfmcghoonnokmjoicf">Visit extension's page in Chrome Web store</a> <a target="_blank" href="https://chrome.google.com/webstore/detail/keepassxc-browser/iopaggbpplllidnfmcghoonnokmjoicf">Visit extension's page in Chrome Web store</a>
</p> </p>
<p> <p>
<a target="_blank" href="https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/">Visit extension's page in Mozilla's Add-ons page</a> <a target="_blank" href="https://addons.mozilla.org/en-US/firefox/addon/keepassxc-browser/">Visit extension's page in Mozilla's Add-ons page</a>
</p> </p>
<p> <p>
<a target="_blank" href="https://github.com/varjolintu/keepassxc-browser">Visit project's page in GitHub</a>. <a target="_blank" href="https://github.com/keepassxreboot/keepassxc-browser">Visit project's page in GitHub</a>.
</p> </p>
<hr /> <hr />
<p> <p>
keepassxc-browser Version: <em class="versionCIP"></em> KeePassXC-Browser Version: <em class="versionCIP"></em>
</p> </p>
<p> <p>
KeePassXC Version: <em class="versionKPH"></em> KeePassXC Version: <em class="versionKPH"></em>
</p> </p>
</div> </div>
<hr> <hr>
<div class="footer"> <div class="footer">
<p>2010-2017 - Perry Nguyen, Lukas Schulze, Angus Gratton, Andy Brandt, Sami Vänttinen</p> <p>2010-2017 - Perry Nguyen, Lukas Schulze</p>
</div> <p>2017-2018 - Angus Gratton, Andy Brandt, Sami Vänttinen</p>
</div> <!-- /container --> </div>
</body> </div> <!-- /container -->
</body>
</html> </html>

View file

@ -1,264 +1,264 @@
if (jQuery) { if (jQuery) {
var $ = jQuery.noConflict(true); var $ = jQuery.noConflict(true);
} }
$(function() { $(function() {
browser.runtime.sendMessage({ action: 'load_settings' }).then((settings) => { browser.runtime.sendMessage({ action: 'load_settings' }).then((settings) => {
options.settings = settings; options.settings = settings;
browser.runtime.sendMessage({ action: 'load_keyring' }).then((keyRing) => { browser.runtime.sendMessage({ action: 'load_keyring' }).then((keyRing) => {
options.keyRing = keyRing; options.keyRing = keyRing;
options.initMenu(); options.initMenu();
options.initGeneralSettings(); options.initGeneralSettings();
options.initConnectedDatabases(); options.initConnectedDatabases();
options.initSpecifiedCredentialFields(); options.initSpecifiedCredentialFields();
options.initAbout(); options.initAbout();
}); });
}); });
}); });
var options = options || {}; var options = options || {};
options.initMenu = function() { options.initMenu = function() {
$('.navbar:first ul.nav:first li a').click(function(e) { $('.navbar:first ul.nav:first li a').click(function(e) {
e.preventDefault(); e.preventDefault();
$('.navbar:first ul.nav:first li').removeClass('active'); $('.navbar:first ul.nav:first li').removeClass('active');
$(this).parent('li').addClass('active'); $(this).parent('li').addClass('active');
$('div.tab').hide(); $('div.tab').hide();
$('div.tab#tab-' + $(this).attr('href').substring(1)).fadeIn(); $('div.tab#tab-' + $(this).attr('href').substring(1)).fadeIn();
}); });
$('div.tab:first').show(); $('div.tab:first').show();
}; };
options.saveSettingsPromise = function() { options.saveSettingsPromise = function() {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
browser.storage.local.set({'settings': options.settings}).then((item) => { browser.storage.local.set({'settings': options.settings}).then((item) => {
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'load_settings' action: 'load_settings'
}).then((settings) => { }).then((settings) => {
resolve(settings); resolve(settings);
}); });
}); });
}); });
} }
options.saveSetting = function(name) { options.saveSetting = function(name) {
const $id = '#' + name; const $id = '#' + name;
$($id).closest('.control-group').removeClass('error').addClass('success'); $($id).closest('.control-group').removeClass('error').addClass('success');
setTimeout(() => { $($id).closest('.control-group').removeClass('success'); }, 2500); setTimeout(() => { $($id).closest('.control-group').removeClass('success'); }, 2500);
browser.storage.local.set({'settings': options.settings}); browser.storage.local.set({'settings': options.settings});
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'load_settings' action: 'load_settings'
}); });
}; };
options.saveSettings = function() { options.saveSettings = function() {
browser.storage.local.set({'settings': options.settings}); browser.storage.local.set({'settings': options.settings});
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'load_settings' action: 'load_settings'
}); });
}; };
options.saveKeyRing = function() { options.saveKeyRing = function() {
browser.storage.local.set({'keyRing': options.keyRing}); browser.storage.local.set({'keyRing': options.keyRing});
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'load_keyring' action: 'load_keyring'
}); });
}; };
options.initGeneralSettings = function() { options.initGeneralSettings = function() {
$('#tab-general-settings input[type=checkbox]').each(function() { $('#tab-general-settings input[type=checkbox]').each(function() {
$(this).attr('checked', options.settings[$(this).attr('name')]); $(this).attr('checked', options.settings[$(this).attr('name')]);
}); });
$('#tab-general-settings input[type=checkbox]').change(function() { $('#tab-general-settings input[type=checkbox]').change(function() {
const name = $(this).attr('name'); const name = $(this).attr('name');
options.settings[name] = $(this).is(':checked'); options.settings[name] = $(this).is(':checked');
options.saveSettingsPromise().then((x) => { options.saveSettingsPromise().then((x) => {
if (name === 'autoFillAndSend') { if (name === 'autoFillAndSend') {
browser.runtime.sendMessage({action: 'init_http_auth'}); browser.runtime.sendMessage({action: 'init_http_auth'});
} }
}); });
}); });
$('#tab-general-settings input[type=radio]').each(function() { $('#tab-general-settings input[type=radio]').each(function() {
if ($(this).val() === options.settings[$(this).attr('name')]) { if ($(this).val() === options.settings[$(this).attr('name')]) {
$(this).attr('checked', options.settings[$(this).attr('name')]); $(this).attr('checked', options.settings[$(this).attr('name')]);
} }
}); });
$('#tab-general-settings input[type=radio]').change(function() { $('#tab-general-settings input[type=radio]').change(function() {
options.settings[$(this).attr('name')] = $(this).val(); options.settings[$(this).attr('name')] = $(this).val();
options.saveSettings(); options.saveSettings();
}); });
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'get_keepassxc_versions' action: 'get_keepassxc_versions'
}).then(options.showKeePassXCVersions); }).then(options.showKeePassXCVersions);
$('#tab-general-settings button.checkUpdateKeePassXC:first').click(function(e) { $('#tab-general-settings button.checkUpdateKeePassXC:first').click(function(e) {
e.preventDefault(); e.preventDefault();
$(this).attr('disabled', true); $(this).attr('disabled', true);
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'check_update_keepassxc' action: 'check_update_keepassxc'
}).then(options.showKeePassXCVersions); }).then(options.showKeePassXCVersions);
}); });
$('#blinkTimeout').val(options.settings['blinkTimeout']); $('#blinkTimeout').val(options.settings['blinkTimeout']);
$('#blinkMinTimeout').val(options.settings['blinkMinTimeout']); $('#blinkMinTimeout').val(options.settings['blinkMinTimeout']);
$('#allowedRedirect').val(options.settings['allowedRedirect']); $('#allowedRedirect').val(options.settings['allowedRedirect']);
$('#blinkTimeoutButton').click(function(){ $('#blinkTimeoutButton').click(function(){
const blinkTimeout = $.trim($('#blinkTimeout').val()); const blinkTimeout = $.trim($('#blinkTimeout').val());
const blinkTimeoutval = Number(blinkTimeout); const blinkTimeoutval = Number(blinkTimeout);
options.settings['blinkTimeout'] = String(blinkTimeoutval); options.settings['blinkTimeout'] = String(blinkTimeoutval);
options.saveSetting('blinkTimeout'); options.saveSetting('blinkTimeout');
}); });
$('#blinkMinTimeoutButton').click(function(){ $('#blinkMinTimeoutButton').click(function(){
const blinkMinTimeout = $.trim($('#blinkMinTimeout').val()); const blinkMinTimeout = $.trim($('#blinkMinTimeout').val());
const blinkMinTimeoutval = Number(blinkMinTimeout); const blinkMinTimeoutval = Number(blinkMinTimeout);
options.settings['blinkMinTimeout'] = String(blinkMinTimeoutval); options.settings['blinkMinTimeout'] = String(blinkMinTimeoutval);
options.saveSetting('blinkMinTimeout'); options.saveSetting('blinkMinTimeout');
}); });
$('#allowedRedirectButton').click(function(){ $('#allowedRedirectButton').click(function(){
const allowedRedirect = $.trim($('#allowedRedirect').val()); const allowedRedirect = $.trim($('#allowedRedirect').val());
const allowedRedirectval = Number(allowedRedirect); const allowedRedirectval = Number(allowedRedirect);
options.settings['allowedRedirect'] = String(allowedRedirectval); options.settings['allowedRedirect'] = String(allowedRedirectval);
options.saveSetting('allowedRedirect'); options.saveSetting('allowedRedirect');
}); });
}; };
options.showKeePassXCVersions = function(response) { options.showKeePassXCVersions = function(response) {
if (response.current <= 0) { if (response.current <= 0) {
response.current = 'unknown'; response.current = 'unknown';
} }
if (response.latest <= 0) { if (response.latest <= 0) {
response.latest = 'unknown'; response.latest = 'unknown';
} }
$('#tab-general-settings .kphVersion:first em.yourVersion:first').text(response.current); $('#tab-general-settings .kphVersion:first em.yourVersion:first').text(response.current);
$('#tab-general-settings .kphVersion:first em.latestVersion:first').text(response.latest); $('#tab-general-settings .kphVersion:first em.latestVersion:first').text(response.latest);
$('#tab-about em.versionKPH').text(response.current); $('#tab-about em.versionKPH').text(response.current);
$('#tab-general-settings button.checkUpdateKeePassXC:first').attr('disabled', false); $('#tab-general-settings button.checkUpdateKeePassXC:first').attr('disabled', false);
}; };
options.initConnectedDatabases = function() { options.initConnectedDatabases = function() {
$('#dialogDeleteConnectedDatabase').modal({keyboard: true, show: false, backdrop: true}); $('#dialogDeleteConnectedDatabase').modal({keyboard: true, show: false, backdrop: true});
$('#tab-connected-databases tr.clone:first button.delete:first').click(function(e) { $('#tab-connected-databases tr.clone:first button.delete:first').click(function(e) {
e.preventDefault(); e.preventDefault();
$('#dialogDeleteConnectedDatabase').data('hash', $(this).closest('tr').data('hash')); $('#dialogDeleteConnectedDatabase').data('hash', $(this).closest('tr').data('hash'));
$('#dialogDeleteConnectedDatabase .modal-body:first span:first').text($(this).closest('tr').children('td:first').text()); $('#dialogDeleteConnectedDatabase .modal-body:first span:first').text($(this).closest('tr').children('td:first').text());
$('#dialogDeleteConnectedDatabase').modal('show'); $('#dialogDeleteConnectedDatabase').modal('show');
}); });
$('#dialogDeleteConnectedDatabase .modal-footer:first button.yes:first').click(function(e) { $('#dialogDeleteConnectedDatabase .modal-footer:first button.yes:first').click(function(e) {
$('#dialogDeleteConnectedDatabase').modal('hide'); $('#dialogDeleteConnectedDatabase').modal('hide');
const $hash = $('#dialogDeleteConnectedDatabase').data('hash'); const $hash = $('#dialogDeleteConnectedDatabase').data('hash');
$('#tab-connected-databases #tr-cd-' + $hash).remove(); $('#tab-connected-databases #tr-cd-' + $hash).remove();
delete options.keyRing[$hash]; delete options.keyRing[$hash];
options.saveKeyRing(); options.saveKeyRing();
if ($('#tab-connected-databases table tbody:first tr').length > 2) { if ($('#tab-connected-databases table tbody:first tr').length > 2) {
$('#tab-connected-databases table tbody:first tr.empty:first').hide(); $('#tab-connected-databases table tbody:first tr.empty:first').hide();
} }
else { else {
$('#tab-connected-databases table tbody:first tr.empty:first').show(); $('#tab-connected-databases table tbody:first tr.empty:first').show();
} }
}); });
$('#tab-connected-databases tr.clone:first .dropdown-menu:first').width('230px'); $('#tab-connected-databases tr.clone:first .dropdown-menu:first').width('230px');
const $trClone = $('#tab-connected-databases table tr.clone:first').clone(true); const $trClone = $('#tab-connected-databases table tr.clone:first').clone(true);
$trClone.removeClass('clone'); $trClone.removeClass('clone');
for (let hash in options.keyRing) { for (let hash in options.keyRing) {
const $tr = $trClone.clone(true); const $tr = $trClone.clone(true);
$tr.data('hash', hash); $tr.data('hash', hash);
$tr.attr('id', 'tr-cd-' + hash); $tr.attr('id', 'tr-cd-' + hash);
$('a.dropdown-toggle:first img:first', $tr).attr('src', '/icons/19x19/icon_normal_19x19.png'); $('a.dropdown-toggle:first img:first', $tr).attr('src', '/icons/19x19/icon_normal_19x19.png');
$tr.children('td:first').text(options.keyRing[hash].id); $tr.children('td:first').text(options.keyRing[hash].id);
$tr.children('td:eq(1)').text(options.keyRing[hash].key); $tr.children('td:eq(1)').text(options.keyRing[hash].key);
const lastUsed = (options.keyRing[hash].lastUsed) ? new Date(options.keyRing[hash].lastUsed).toLocaleString() : 'unknown'; const lastUsed = (options.keyRing[hash].lastUsed) ? new Date(options.keyRing[hash].lastUsed).toLocaleString() : 'unknown';
$tr.children('td:eq(2)').text(lastUsed); $tr.children('td:eq(2)').text(lastUsed);
const date = (options.keyRing[hash].created) ? new Date(options.keyRing[hash].created).toLocaleDateString() : 'unknown'; const date = (options.keyRing[hash].created) ? new Date(options.keyRing[hash].created).toLocaleDateString() : 'unknown';
$tr.children('td:eq(3)').text(date); $tr.children('td:eq(3)').text(date);
$('#tab-connected-databases table tbody:first').append($tr); $('#tab-connected-databases table tbody:first').append($tr);
} }
if ($('#tab-connected-databases table tbody:first tr').length > 2) { if ($('#tab-connected-databases table tbody:first tr').length > 2) {
$('#tab-connected-databases table tbody:first tr.empty:first').hide(); $('#tab-connected-databases table tbody:first tr.empty:first').hide();
} }
else { else {
$('#tab-connected-databases table tbody:first tr.empty:first').show(); $('#tab-connected-databases table tbody:first tr.empty:first').show();
} }
$('#connect-button').click(function() { $('#connect-button').click(function() {
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'associate' action: 'associate'
}); });
}); });
}; };
options.initSpecifiedCredentialFields = function() { options.initSpecifiedCredentialFields = function() {
$('#dialogDeleteSpecifiedCredentialFields').modal({keyboard: true, show: false, backdrop: true}); $('#dialogDeleteSpecifiedCredentialFields').modal({keyboard: true, show: false, backdrop: true});
$('#tab-specified-fields tr.clone:first button.delete:first').click(function(e) { $('#tab-specified-fields tr.clone:first button.delete:first').click(function(e) {
e.preventDefault(); e.preventDefault();
$('#dialogDeleteSpecifiedCredentialFields').data('url', $(this).closest('tr').data('url')); $('#dialogDeleteSpecifiedCredentialFields').data('url', $(this).closest('tr').data('url'));
$('#dialogDeleteSpecifiedCredentialFields').data('tr-id', $(this).closest('tr').attr('id')); $('#dialogDeleteSpecifiedCredentialFields').data('tr-id', $(this).closest('tr').attr('id'));
$('#dialogDeleteSpecifiedCredentialFields .modal-body:first strong:first').text($(this).closest('tr').children('td:first').text()); $('#dialogDeleteSpecifiedCredentialFields .modal-body:first strong:first').text($(this).closest('tr').children('td:first').text());
$('#dialogDeleteSpecifiedCredentialFields').modal('show'); $('#dialogDeleteSpecifiedCredentialFields').modal('show');
}); });
$('#dialogDeleteSpecifiedCredentialFields .modal-footer:first button.yes:first').click(function(e) { $('#dialogDeleteSpecifiedCredentialFields .modal-footer:first button.yes:first').click(function(e) {
$('#dialogDeleteSpecifiedCredentialFields').modal('hide'); $('#dialogDeleteSpecifiedCredentialFields').modal('hide');
const $url = $('#dialogDeleteSpecifiedCredentialFields').data('url'); const $url = $('#dialogDeleteSpecifiedCredentialFields').data('url');
const $trId = $('#dialogDeleteSpecifiedCredentialFields').data('tr-id'); const $trId = $('#dialogDeleteSpecifiedCredentialFields').data('tr-id');
$('#tab-specified-fields #' + $trId).remove(); $('#tab-specified-fields #' + $trId).remove();
delete options.settings['defined-credential-fields'][$url]; delete options.settings['defined-credential-fields'][$url];
options.saveSettings(); options.saveSettings();
if ($('#tab-specified-fields table tbody:first tr').length > 2) { if ($('#tab-specified-fields table tbody:first tr').length > 2) {
$('#tab-specified-fields table tbody:first tr.empty:first').hide(); $('#tab-specified-fields table tbody:first tr.empty:first').hide();
} }
else { else {
$('#tab-specified-fields table tbody:first tr.empty:first').show(); $('#tab-specified-fields table tbody:first tr.empty:first').show();
} }
}); });
const $trClone = $('#tab-specified-fields table tr.clone:first').clone(true); const $trClone = $('#tab-specified-fields table tr.clone:first').clone(true);
$trClone.removeClass('clone'); $trClone.removeClass('clone');
let counter = 1; let counter = 1;
for (let url in options.settings['defined-credential-fields']) { for (let url in options.settings['defined-credential-fields']) {
const $tr = $trClone.clone(true); const $tr = $trClone.clone(true);
$tr.data('url', url); $tr.data('url', url);
$tr.attr('id', 'tr-scf' + counter); $tr.attr('id', 'tr-scf' + counter);
counter += 1; counter += 1;
$tr.children('td:first').text(url); $tr.children('td:first').text(url);
$('#tab-specified-fields table tbody:first').append($tr); $('#tab-specified-fields table tbody:first').append($tr);
} }
if ($('#tab-specified-fields table tbody:first tr').length > 2) { if ($('#tab-specified-fields table tbody:first tr').length > 2) {
$('#tab-specified-fields table tbody:first tr.empty:first').hide(); $('#tab-specified-fields table tbody:first tr.empty:first').hide();
} }
else { else {
$('#tab-specified-fields table tbody:first tr.empty:first').show(); $('#tab-specified-fields table tbody:first tr.empty:first').show();
} }
}; };
options.initAbout = function() { options.initAbout = function() {
$('#tab-about em.versionCIP').text(browser.runtime.getManifest().version); $('#tab-about em.versionCIP').text(browser.runtime.getManifest().version);
if (isFirefox()) { if (isFirefox()) {
$('#chrome-only').remove(); $('#chrome-only').remove();
} }
}; };

View file

@ -1,75 +1,75 @@
body { body {
font-family: sans-serif; font-family: sans-serif;
min-width: 440px; min-width: 440px;
max-width: 440px; max-width: 440px;
overflow-x: hidden; overflow-x: hidden;
background-color: #eee; background-color: #eee;
font-size: 15px; font-size: 15px;
padding: 8px; padding: 8px;
} }
.credentials ul { .credentials ul {
margin-left: 0; margin-left: 0;
margin-right: 0; margin-right: 0;
padding-left: 0; padding-left: 0;
padding-right: 0; padding-right: 0;
list-style-position: inside; list-style-position: inside;
} }
.credentials li { .credentials li {
list-style: none; list-style: none;
padding-top: 1px; padding-top: 1px;
padding-bottom: 1px; padding-bottom: 1px;
padding-left: 5px; padding-left: 5px;
padding-right: 5px; padding-right: 5px;
margin-left: 10px; margin-left: 10px;
margin-right: 5px; margin-right: 5px;
} }
.credentials a { .credentials a {
color: #333; color: #333;
} }
.credentials a:hover { .credentials a:hover {
text-decoration: none; text-decoration: none;
} }
.credentials li:hover { .credentials li:hover {
cursor: pointer; cursor: pointer;
background: #ddd; background: #ddd;
} }
.settings { .settings {
padding-bottom: 10px; padding-bottom: 10px;
margin-bottom: 10px; margin-bottom: 10px;
border-bottom: 1px solid #333; border-bottom: 1px solid #333;
font-size: 90%; font-size: 90%;
text-align: left; text-align: left;
} }
.settings label { .settings label {
display: block; display: block;
} }
.settings label input { .settings label input {
vertical-align: middle; vertical-align: middle;
} }
.settings .description { .settings .description {
margin-top: 3px; margin-top: 3px;
font-size: 80%; font-size: 80%;
color: #787878; color: #787878;
} }
.small { .small {
margin-top: 3px; margin-top: 3px;
margin-left: 12px; margin-left: 12px;
font-size: 80%; font-size: 80%;
color: #787878; color: #787878;
} }
#update-available { #update-available {
padding-top: 10px; padding-top: 10px;
margin-top: 10px; margin-top: 10px;
padding-bottom: 0px; padding-bottom: 0px;
margin-bottom: 0px; margin-bottom: 0px;
text-align: left; text-align: left;
} }
#update-available a:hover, #update-available a:hover,
#update-available a:active { #update-available a:active {
text-decoration: underline; text-decoration: underline;
} }
#lock-database-button { #lock-database-button {
float: right; float: right;
height: 30px; height: 30px;
} }

View file

@ -1,99 +1,99 @@
<html> <html>
<head> <head>
<title>KeePassXC - Popup</title> <title>KeePassXC - Popup</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="stylesheet" href="popup.css" /> <link rel="stylesheet" href="popup.css" />
<link rel="stylesheet" href="../options/bootstrap.min.css" /> <link rel="stylesheet" href="../options/bootstrap.min.css" />
<script type="text/javascript" src="../browser-polyfill.min.js"></script> <script type="text/javascript" src="../browser-polyfill.min.js"></script>
<script type="text/javascript" src="../global.js"></script> <script type="text/javascript" src="../global.js"></script>
<script type="text/javascript" src="../jquery-3.2.1.min.js"></script> <script type="text/javascript" src="../jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="../options/bootstrap.min.js" /></script> <script type="text/javascript" src="../options/bootstrap.min.js" /></script>
<script type="text/javascript" src="popup_functions.js" /></script> <script type="text/javascript" src="popup_functions.js" /></script>
<script type="text/javascript" src="popup.js" /></script> <script type="text/javascript" src="popup.js" /></script>
</head> </head>
<body> <body>
<div class="container"> <div class="container">
<div id="settings" class="settings"> <div id="settings" class="settings">
<button id="btn-options" class="btn btn-sm btn-success"><span class="glyphicon glyphicon-cog"></span> Settings</button> <button id="btn-options" class="btn btn-sm btn-success"><span class="glyphicon glyphicon-cog"></span> Settings</button>
<button id="btn-choose-credential-fields" class="btn btn-sm btn-warning"><span class="glyphicon glyphicon-list-alt"></span> Choose own credential fields for this page</button> <button id="btn-choose-credential-fields" class="btn btn-sm btn-warning"><span class="glyphicon glyphicon-list-alt"></span> Choose own credential fields for this page</button>
<button id="lock-database-button" class="btn btn-danger" title="Lock database"><span class="glyphicon glyphicon-lock"></span></button> <button id="lock-database-button" class="btn btn-danger" title="Lock database"><span class="glyphicon glyphicon-lock"></span></button>
<div id="update-available" class="alert alert-danger"> <div id="update-available" class="alert alert-danger">
You use an old version of KeePassXC. You use an old version of KeePassXC.
<br /> <br />
<a target="_blank" class="alert-link" href="https://keepassxc.org/download">Please download the latest version from keepassxc.org</a>. <a target="_blank" class="alert-link" href="https://keepassxc.org/download">Please download the latest version from keepassxc.org</a>.
</div> </div>
</div> </div>
<div id="initial-state"> <div id="initial-state">
<p><img style="margin-right: 1em" src="throbber.gif"/> Checking status...</p> <p><img style="margin-right: 1em" src="throbber.gif"/> Checking status...</p>
</div> </div>
<div id="not-configured" style="display: none"> <div id="not-configured" style="display: none">
<p> <p>
keepassxc-browser has not been configured. KeePassXC-Browser has not been configured.
Press the connect button to register and pair with KeePassXC. Press the connect button to register and pair with KeePassXC.
</p> </p>
<div style="text-align: right"> <div style="text-align: right">
<button id="connect-button" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-link"></span> Connect</button> <button id="connect-button" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-link"></span> Connect</button>
</div> </div>
</div> </div>
<div id="need-reconfigure" style="display: none"> <div id="need-reconfigure" style="display: none">
<p> <p>
keepassxc-browser has been disconnected from KeePassXC. KeePassXC-Browser has been disconnected from KeePassXC.
</p> </p>
<code id="need-reconfigure-message"></code> <code id="need-reconfigure-message"></code>
<p> <p>
Press the reconnect button to establish a new connection. Press the reconnect button to establish a new connection.
</p> </p>
<div style="text-align: right"> <div style="text-align: right">
<button id="reconnect-button" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-refresh"></span> Reconnect</button> <button id="reconnect-button" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-refresh"></span> Reconnect</button>
</div> </div>
</div> </div>
<div id="configured-not-associated" style="display: none"> <div id="configured-not-associated" style="display: none">
<p> <p>
keepassxc-browser has been configured using the identifier KeePassXC-Browser has been configured using the identifier
<em id="unassociated-identifier"></em> and has not yet <em id="unassociated-identifier"></em> and has not yet
connected to KeePassXC. connected to KeePassXC.
</p> </p>
</div> </div>
<div id="configured-and-associated" style="display: none"> <div id="configured-and-associated" style="display: none">
<p> <p>
keepassxc-browser has been configured using the identifier KeePassXC-Browser has been configured using the identifier
"<em id="associated-identifier"></em>" and is successfully "<em id="associated-identifier"></em>" and is successfully
connected to KeePassXC. connected to KeePassXC.
</p> </p>
<div style="text-align: right"> <div style="text-align: right">
<button id="redetect-fields-button" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-list-alt"></span> Redetect credential fields</button> <button id="redetect-fields-button" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-list-alt"></span> Redetect credential fields</button>
</div> </div>
</div> </div>
<div id="error-encountered" style="display: none"> <div id="error-encountered" style="display: none">
<p> <p>
keepassxc-browser has encountered an error: KeePassXC-Browser has encountered an error:
</p> </p>
<p style="margin-left: 1em"> <p style="margin-left: 1em">
<code id="error-message"></code> <code id="error-message"></code>
</p> </p>
<div style="text-align: right"> <div style="text-align: right">
<button id="reload-status-button" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-refresh"></span> Reload</button> <button id="reload-status-button" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-refresh"></span> Reload</button>
</div> </div>
</div> </div>
<div id="database-not-opened" style="display: none"> <div id="database-not-opened" style="display: none">
<p> <p>
keepassxc-browser has encountered an error: KeePassXC-Browser has encountered an error:
</p> </p>
<p style="margin-left: 1em"> <p style="margin-left: 1em">
<code id="database-error-message"></code> <code id="database-error-message"></code>
</p> </p>
<div style="text-align: right"> <div style="text-align: right">
<button id="reopen-database-button" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-lock"></span> Reopen database</button> <button id="reopen-database-button" class="btn btn-sm btn-primary"><span class="glyphicon glyphicon-lock"></span> Reopen database</button>
</div> </div>
</div> </div>
</div> </div>
</body> </body>
</html> </html>

View file

@ -1,89 +1,90 @@
function status_response(r) { function status_response(r) {
$('#initial-state').hide(); $('#initial-state').hide();
$('#error-encountered').hide(); $('#error-encountered').hide();
$('#need-reconfigure').hide(); $('#need-reconfigure').hide();
$('#not-configured').hide(); $('#not-configured').hide();
$('#configured-and-associated').hide(); $('#configured-and-associated').hide();
$('#configured-not-associated').hide(); $('#configured-not-associated').hide();
$('#lock-database-button').hide(); $('#lock-database-button').hide();
if (!r.keePassXCAvailable) { if (!r.keePassXCAvailable) {
$('#error-message').html(r.error); $('#error-message').html(r.error);
$('#error-encountered').show(); $('#error-encountered').show();
} }
else if (r.keePassXCAvailable && r.databaseClosed) { else if (r.keePassXCAvailable && r.databaseClosed) {
$('#database-error-message').html(r.error); $('#database-error-message').html(r.error);
$('#database-not-opened').show(); $('#database-not-opened').show();
} }
else if (!r.configured) { else if (!r.configured) {
$('#not-configured').show(); $('#not-configured').show();
} }
else if (r.encryptionKeyUnrecognized) { else if (r.encryptionKeyUnrecognized) {
$('#need-reconfigure').show(); $('#need-reconfigure').show();
$('#need-reconfigure-message').html(r.error); $('#need-reconfigure-message').html(r.error);
} }
else if (!r.associated) { else if (!r.associated) {
$('#need-reconfigure').show(); $('#need-reconfigure').show();
$('#need-reconfigure-message').html(r.error); $('#need-reconfigure-message').html(r.error);
} }
else if (r.error !== null) { else if (r.error !== null) {
$('#error-encountered').show(); $('#error-encountered').show();
$('#error-message').html(r.error); $('#error-message').html(r.error);
} }
else { else {
$('#configured-and-associated').show(); $('#configured-and-associated').show();
$('#associated-identifier').html(r.identifier); $('#associated-identifier').html(r.identifier);
$('#lock-database-button').show(); $('#lock-database-button').show();
} }
} }
$(function() { $(function() {
$('#connect-button').click(function() { $('#connect-button').click(function() {
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'associate' action: 'associate'
}); });
close(); close();
}); });
$('#reconnect-button').click(function() { $('#reconnect-button').click(function() {
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'associate' action: 'associate'
}); });
close(); close();
}); });
$('#reload-status-button').click(function() { $('#reload-status-button').click(function() {
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'reconnect' action: 'reconnect'
}).then(status_response); }).then(status_response);
}); });
$('#reopen-database-button').click(function() { $('#reopen-database-button').click(function() {
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'get_status' action: 'get_status',
}).then(status_response); args: [ false, true ] // Set forcePopup to true
}); }).then(status_response);
});
$('#redetect-fields-button').click(function() { $('#redetect-fields-button').click(function() {
browser.tabs.query({"active": true, "currentWindow": true}).then(function(tabs) { browser.tabs.query({"active": true, "currentWindow": true}).then(function(tabs) {
if (tabs.length === 0) { if (tabs.length === 0) {
return; // For example: only the background devtools or a popup are opened return; // For example: only the background devtools or a popup are opened
} }
let tab = tabs[0]; let tab = tabs[0];
browser.tabs.sendMessage(tab.id, { browser.tabs.sendMessage(tab.id, {
action: 'redetect_fields' action: 'redetect_fields'
}); });
}); });
}); });
$('#lock-database-button').click(function() { $('#lock-database-button').click(function() {
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'lock-database' action: 'lock-database'
}).then(status_response); }).then(status_response);
}); });
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: "get_status" action: "get_status"
}).then(status_response); }).then(status_response);
}); });

View file

@ -1,34 +1,34 @@
var $ = jQuery.noConflict(true); var $ = jQuery.noConflict(true);
function updateAvailableResponse(available) { function updateAvailableResponse(available) {
if (available) { if (available) {
$('#update-available').show(); $('#update-available').show();
} }
else { else {
$('#update-available').hide(); $('#update-available').hide();
} }
} }
function initSettings() { function initSettings() {
$ ('#settings #btn-options').click(function() { $('#settings #btn-options').click(function() {
browser.runtime.openOptionsPage().then(close()); browser.runtime.openOptionsPage().then(close());
}); });
$ ('#settings #btn-choose-credential-fields').click(function() { $('#settings #btn-choose-credential-fields').click(function() {
browser.runtime.getBackgroundPage().then((global) => { browser.runtime.getBackgroundPage().then((global) => {
browser.tabs.sendMessage(global.page.currentTabId, { browser.tabs.sendMessage(global.page.currentTabId, {
action: 'choose_credential_fields' action: 'choose_credential_fields'
}); });
close(); close();
}); });
}); });
} }
$(function() { $(function() {
initSettings(); initSettings();
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'update_available_keepassxc' action: 'update_available_keepassxc'
}).then(updateAvailableResponse); }).then(updateAvailableResponse);
}); });

View file

@ -1,36 +1,36 @@
<html> <html>
<head> <head>
<title>keepassxc-browser - Popup</title> <title>KeePassXC-Browser - Popup</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="stylesheet" href="popup.css" /> <link rel="stylesheet" href="popup.css" />
<link rel="stylesheet" href="../options/bootstrap.min.css" /> <link rel="stylesheet" href="../options/bootstrap.min.css" />
<script type="text/javascript" src="../browser-polyfill.min.js"></script> <script type="text/javascript" src="../browser-polyfill.min.js"></script>
<script type="text/javascript" src="../global.js"></script> <script type="text/javascript" src="../global.js"></script>
<script type="text/javascript" src="../jquery-3.2.1.min.js"></script> <script type="text/javascript" src="../jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="../options/bootstrap.min.js" /></script> <script type="text/javascript" src="../options/bootstrap.min.js" /></script>
<script type="text/javascript" src="popup_functions.js"></script> <script type="text/javascript" src="popup_functions.js"></script>
<script type="text/javascript" src="popup_httpauth.js"></script> <script type="text/javascript" src="popup_httpauth.js"></script>
</head> </head>
<body> <body>
<div class="container"> <div class="container">
<div id="settings" class="settings"> <div id="settings" class="settings">
<button id="btn-options" class="btn btn-sm btn-success"><span class="glyphicon glyphicon-cog"></span> Settings</button> <button id="btn-options" class="btn btn-sm btn-success"><span class="glyphicon glyphicon-cog"></span> Settings</button>
<button id="btn-choose-credential-fields" class="btn btn-sm btn-warning"><span class="glyphicon glyphicon-list-alt"></span> Choose own credential fields for this page</button> <button id="btn-choose-credential-fields" class="btn btn-sm btn-warning"><span class="glyphicon glyphicon-list-alt"></span> Choose own credential fields for this page</button>
<button id="lock-database-button" class="btn btn-danger" title="Lock database"><span class="glyphicon glyphicon-lock"></span></button> <button id="lock-database-button" class="btn btn-danger" title="Lock database"><span class="glyphicon glyphicon-lock"></span></button>
<div id="update-available" class="alert alert-danger"> <div id="update-available" class="alert alert-danger">
You use an old version of KeePassXC. You use an old version of KeePassXC.
<br /> <br />
<a target="_blank" class="alert-link" href="https://keepassxc.org/download">Please download the latest version from keepassxc.org</a>. <a target="_blank" class="alert-link" href="https://keepassxc.org/download">Please download the latest version from keepassxc.org</a>.
</div> </div>
</div> </div>
<div class="credentials"> <div class="credentials">
<p> <p>
Select the login information you would like to get logged in with: Select the login information you would like to get logged in with:
</p> </p>
<ul id="login-list"></ul> <ul id="login-list"></ul>
</div> </div>
</div> </div>
</body> </body>
</html> </html>

View file

@ -1,35 +1,35 @@
$(function() { $(function() {
browser.runtime.getBackgroundPage().then((global) => { browser.runtime.getBackgroundPage().then((global) => {
browser.tabs.query({'active': true, 'currentWindow': true}).then((tabs) => { browser.tabs.query({'active': true, 'currentWindow': true}).then((tabs) => {
let tab = tabs[0]; let tab = tabs[0];
const data = global.page.tabs[tab.id].loginList; const data = global.page.tabs[tab.id].loginList;
let ul = document.getElementById('login-list'); let ul = document.getElementById('login-list');
for (let i = 0; i < data.logins.length; i++) { for (let i = 0; i < data.logins.length; i++) {
const li = document.createElement('li'); const li = document.createElement('li');
const a = document.createElement('a'); const a = document.createElement('a');
a.textContent = data.logins[i].login + " (" + data.logins[i].name + ")"; a.textContent = data.logins[i].login + " (" + data.logins[i].name + ")";
li.appendChild(a); li.appendChild(a);
$(a).data('creds', data.logins[i]); $(a).data('creds', data.logins[i]);
$(a).click(function () { $(a).click(function () {
if (data.resolve) { if (data.resolve) {
const creds = $(this).data('creds'); const creds = $(this).data('creds');
data.resolve({ data.resolve({
authCredentials: { authCredentials: {
username: creds.login, username: creds.login,
password: creds.password password: creds.password
} }
}); });
} }
close(); close();
}); });
ul.appendChild(li); ul.appendChild(li);
} }
}); });
}); });
$('#lock-database-button').click(function() { $('#lock-database-button').click(function() {
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'lock-database' action: 'lock-database'
}).then(status_response); }).then(status_response);
}); });
}); });

View file

@ -1,36 +1,36 @@
<html> <html>
<head> <head>
<title>KeePassXC - Popup</title> <title>KeePassXC - Popup</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="stylesheet" href="popup.css" /> <link rel="stylesheet" href="popup.css" />
<link rel="stylesheet" href="../options/bootstrap.min.css" /> <link rel="stylesheet" href="../options/bootstrap.min.css" />
<script type="text/javascript" src="../browser-polyfill.min.js"></script> <script type="text/javascript" src="../browser-polyfill.min.js"></script>
<script type="text/javascript" src="../global.js"></script> <script type="text/javascript" src="../global.js"></script>
<script type="text/javascript" src="../jquery-3.2.1.min.js"></script> <script type="text/javascript" src="../jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="../options/bootstrap.min.js" /></script> <script type="text/javascript" src="../options/bootstrap.min.js" /></script>
<script type="text/javascript" src="popup_functions.js"></script> <script type="text/javascript" src="popup_functions.js"></script>
<script type="text/javascript" src="popup_login.js"></script> <script type="text/javascript" src="popup_login.js"></script>
</head> </head>
<body> <body>
<div class="container"> <div class="container">
<div id="settings" class="settings"> <div id="settings" class="settings">
<button id="btn-options" class="btn btn-sm btn-success"><span class="glyphicon glyphicon-cog"></span> Settings</button> <button id="btn-options" class="btn btn-sm btn-success"><span class="glyphicon glyphicon-cog"></span> Settings</button>
<button id="btn-choose-credential-fields" class="btn btn-sm btn-warning"><span class="glyphicon glyphicon-list-alt"></span> Choose own credential fields for this page</button> <button id="btn-choose-credential-fields" class="btn btn-sm btn-warning"><span class="glyphicon glyphicon-list-alt"></span> Choose own credential fields for this page</button>
<button id="lock-database-button" class="btn btn-danger" title="Lock database"><span class="glyphicon glyphicon-lock"></span></button> <button id="lock-database-button" class="btn btn-danger" title="Lock database"><span class="glyphicon glyphicon-lock"></span></button>
<div id="update-available" class="alert alert-danger"> <div id="update-available" class="alert alert-danger">
You use an old version of KeePassXC. You use an old version of KeePassXC.
<br /> <br />
<a target="_blank" class="alert-link" href="https://keepassxc.org/download">Please download the latest version from keepassxc.org</a>. <a target="_blank" class="alert-link" href="https://keepassxc.org/download">Please download the latest version from keepassxc.org</a>.
</div> </div>
</div> </div>
<div class="credentials"> <div class="credentials">
<p> <p>
Select the login information you would like to get entered into the page: Select the login information you would like to get entered into the page:
</p> </p>
<ul id="login-list"></ul> <ul id="login-list"></ul>
</div> </div>
</div> </div>
</body> </body>
</html> </html>

View file

@ -1,36 +1,36 @@
$(function() { $(function() {
browser.runtime.getBackgroundPage().then((global) => { browser.runtime.getBackgroundPage().then((global) => {
browser.tabs.query({"active": true, "currentWindow": true}).then((tabs) => { browser.tabs.query({"active": true, "currentWindow": true}).then((tabs) => {
if (tabs.length === 0) { if (tabs.length === 0) {
return; // For example: only the background devtools or a popup are opened return; // For example: only the background devtools or a popup are opened
} }
const tab = tabs[0]; const tab = tabs[0];
const logins = global.page.tabs[tab.id].loginList; const logins = global.page.tabs[tab.id].loginList;
let ul = document.getElementById('login-list'); let ul = document.getElementById('login-list');
for (let i = 0; i < logins.length; i++) { for (let i = 0; i < logins.length; i++) {
const li = document.createElement('li'); const li = document.createElement('li');
const a = document.createElement('a'); const a = document.createElement('a');
a.textContent = logins[i]; a.textContent = logins[i];
li.setAttribute('class', 'list-group-item'); li.setAttribute('class', 'list-group-item');
li.appendChild(a); li.appendChild(a);
a.setAttribute('id', '' + i); a.setAttribute('id', '' + i);
a.addEventListener('click', (e) => { a.addEventListener('click', (e) => {
const id = e.target.id; const id = e.target.id;
browser.tabs.sendMessage(tab.id, { browser.tabs.sendMessage(tab.id, {
action: 'fill_user_pass_with_specific_login', action: 'fill_user_pass_with_specific_login',
id: id id: id
}); });
close(); close();
}); });
ul.appendChild(li); ul.appendChild(li);
} }
}); });
}); });
$('#lock-database-button').click(function() { $('#lock-database-button').click(function() {
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'lock-database' action: 'lock-database'
}); });
}); });
}); });

View file

@ -1,36 +1,36 @@
<html> <html>
<head> <head>
<title>keepassxc-browser - Popup</title> <title>KeePassXC-Browser - Popup</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="stylesheet" href="popup.css" /> <link rel="stylesheet" href="popup.css" />
<link rel="stylesheet" href="../options/bootstrap.min.css" /> <link rel="stylesheet" href="../options/bootstrap.min.css" />
<script type="text/javascript" src="../browser-polyfill.min.js"></script> <script type="text/javascript" src="../browser-polyfill.min.js"></script>
<script type="text/javascript" src="../global.js"></script> <script type="text/javascript" src="../global.js"></script>
<script type="text/javascript" src="../jquery-3.2.1.min.js"></script> <script type="text/javascript" src="../jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="../options/bootstrap.min.js" /></script> <script type="text/javascript" src="../options/bootstrap.min.js" /></script>
<script type="text/javascript" src="popup_functions.js"></script> <script type="text/javascript" src="popup_functions.js"></script>
</head> </head>
<body> <body>
<div class="container"> <div class="container">
<div id="settings" class="settings"> <div id="settings" class="settings">
<button id="btn-options" class="btn btn-sm btn-success"><span class="glyphicon glyphicon-cog"></span> Settings</button> <button id="btn-options" class="btn btn-sm btn-success"><span class="glyphicon glyphicon-cog"></span> Settings</button>
<button id="btn-choose-credential-fields" class="btn btn-sm btn-warning"><span class="glyphicon glyphicon-list-alt"></span> Choose own credential fields for this page</button> <button id="btn-choose-credential-fields" class="btn btn-sm btn-warning"><span class="glyphicon glyphicon-list-alt"></span> Choose own credential fields for this page</button>
<button id="lock-database-button" class="btn btn-danger" title="Lock database"><span class="glyphicon glyphicon-lock"></span></button> <button id="lock-database-button" class="btn btn-danger" title="Lock database"><span class="glyphicon glyphicon-lock"></span></button>
<div id="update-available" class="alert alert-danger"> <div id="update-available" class="alert alert-danger">
You use an old version of KeePassXC. You use an old version of KeePassXC.
<br /> <br />
<a target="_blank" class="alert-link" href="https://keepassxc.org/download">Please download the latest version from keepassxc.org</a>. <a target="_blank" class="alert-link" href="https://keepassxc.org/download">Please download the latest version from keepassxc.org</a>.
</div>
</div>
<div>
<p>
keepassxc-browser found more than one password field on this page. To enter your
logins, right-click on one of the password fields, and choose either the
"<code>Fill User + Pass</code>" or "<code>Fill Pass Only</code>" command.
</p>
</div>
</div> </div>
</body> </div>
<div>
<p>
KeePassXC-Browser found more than one password field on this page. To enter your
logins, right-click on one of the password fields, and choose either the
"<code>Fill User + Pass</code>" or "<code>Fill Pass Only</code>" command.
</p>
</div>
</div>
</body>
</html> </html>

View file

@ -1,51 +1,51 @@
<html> <html>
<head> <head>
<title>keepassxc-browser - Popup</title> <title>KeePassXC-Browser - Popup</title>
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="stylesheet" href="popup.css" /> <link rel="stylesheet" href="popup.css" />
<link rel="stylesheet" href="../options/bootstrap.min.css" /> <link rel="stylesheet" href="../options/bootstrap.min.css" />
<script type="text/javascript" src="../browser-polyfill.min.js"></script> <script type="text/javascript" src="../browser-polyfill.min.js"></script>
<script type="text/javascript" src="../global.js"></script> <script type="text/javascript" src="../global.js"></script>
<script type="text/javascript" src="../jquery-3.2.1.min.js"></script> <script type="text/javascript" src="../jquery-3.2.1.min.js"></script>
<script type="text/javascript" src="../options/bootstrap.min.js" /></script> <script type="text/javascript" src="../options/bootstrap.min.js" /></script>
<script type="text/javascript" src="popup_functions.js"></script> <script type="text/javascript" src="popup_functions.js"></script>
<script type="text/javascript" src="popup_remember.js"></script> <script type="text/javascript" src="popup_remember.js"></script>
<style type="text/css"> <style type="text/css">
.credentials {display: none; border-top: 1px solid #333;} .credentials {display: none; border-top: 1px solid #333;}
.connected-database {display: none; font-size: 85%; color: #787878;} .connected-database {display: none; font-size: 85%; color: #787878;}
.credentials .username-new {display: none;} .credentials .username-new {display: none;}
.credentials .username-exists {display: none;} .credentials .username-exists {display: none;}
.small { font-weight: bold; } .small { font-weight: bold; }
.small .normal { font-weight: normal; } .small .normal { font-weight: normal; }
</style> </style>
</head> </head>
<body> <body>
<div class="buttons"> <div class="buttons">
<p> <p>
Username or password changed! Save it? Username or password changed! Save it?
<br /> <br />
<span class="small information-url">Url: <span class="normal"></span></span> <span class="small information-url">Url: <span class="normal"></span></span>
<br /> <br />
<span class="small information-username">Username: <span class="normal"></span></span> <span class="small information-username">Username: <span class="normal"></span></span>
</p> </p>
<p> <p>
<button id="btn-new" class="btn btn-sm btn-success"><span class="glyphicon glyphicon-pencil"></span> New</button> <button id="btn-new" class="btn btn-sm btn-success"><span class="glyphicon glyphicon-pencil"></span> New</button>
<button id="btn-update" class="btn btn-sm btn-warning"><span class="glyphicon glyphicon-refresh"></span> Update</button> <button id="btn-update" class="btn btn-sm btn-warning"><span class="glyphicon glyphicon-refresh"></span> Update</button>
<button id="btn-dismiss" class="btn btn-sm btn-danger"><span class="glyphicon glyphicon-remove"></span> Dismiss</button> <button id="btn-dismiss" class="btn btn-sm btn-danger"><span class="glyphicon glyphicon-remove"></span> Dismiss</button>
</p> </p>
</div> </div>
<div class="connected-database"> <div class="connected-database">
<p>Credentials will be saved in connected database with identifier <em></em>.</p> <p>Credentials will be saved in connected database with identifier <em></em>.</p>
</div> </div>
<div class="credentials"> <div class="credentials">
<p class="username-new">The used username <strong></strong> is currently not saved!</p> <p class="username-new">The used username <strong></strong> is currently not saved!</p>
<p class="username-exists">The credentials with the used username <strong></strong> are marked bold.</p> <p class="username-exists">The credentials with the used username <strong></strong> are marked bold.</p>
<p> <p>
Please choose the credentials you want to update: Please choose the credentials you want to update:
</p> </p>
<ul id="list"></ul> <ul id="list"></ul>
</div> </div>
</body> </body>
</html> </html>

View file

@ -1,124 +1,124 @@
var _tab; var _tab;
function _initialize(tab) { function _initialize(tab) {
_tab = tab; _tab = tab;
// no credentials set or credentials already cleared // no credentials set or credentials already cleared
if (!_tab.credentials.username) { if (!_tab.credentials.username) {
_close(); _close();
return; return;
} }
// no existing credentials to update --> disable update-button // no existing credentials to update --> disable update-button
if (_tab.credentials.list.length === 0) { if (_tab.credentials.list.length === 0) {
$('#btn-update').attr('disabled', true).removeClass('btn-warning'); $('#btn-update').attr('disabled', true).removeClass('btn-warning');
} }
let url = _tab.credentials.url; let url = _tab.credentials.url;
url = (url.length > 50) ? url.substring(0, 50) + '...' : url; url = (url.length > 50) ? url.substring(0, 50) + '...' : url;
$('.information-url:first span:first').text(url); $('.information-url:first span:first').text(url);
$('.information-username:first span:first').text(_tab.credentials.username); $('.information-username:first span:first').text(_tab.credentials.username);
$('#btn-new').click(function(e) { $('#btn-new').click(function(e) {
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'add_credentials', action: 'add_credentials',
args: [_tab.credentials.username, _tab.credentials.password, _tab.credentials.url] args: [_tab.credentials.username, _tab.credentials.password, _tab.credentials.url]
}).then(_verifyResult); }).then(_verifyResult);
}); });
$('#btn-update').click(function(e) { $('#btn-update').click(function(e) {
e.preventDefault(); e.preventDefault();
// only one entry which could be updated // only one entry which could be updated
if(_tab.credentials.list.length === 1) { if(_tab.credentials.list.length === 1) {
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'update_credentials', action: 'update_credentials',
args: [_tab.credentials.list[0].uuid, _tab.credentials.username, _tab.credentials.password, _tab.credentials.url] args: [_tab.credentials.list[0].uuid, _tab.credentials.username, _tab.credentials.password, _tab.credentials.url]
}).then(_verifyResult); }).then(_verifyResult);
} }
else { else {
$('.credentials:first .username-new:first strong:first').text(_tab.credentials.username); $('.credentials:first .username-new:first strong:first').text(_tab.credentials.username);
$('.credentials:first .username-exists:first strong:first').text(_tab.credentials.username); $('.credentials:first .username-exists:first strong:first').text(_tab.credentials.username);
if (_tab.credentials.usernameExists) { if (_tab.credentials.usernameExists) {
$('.credentials:first .username-new:first').hide(); $('.credentials:first .username-new:first').hide();
$('.credentials:first .username-exists:first').show(); $('.credentials:first .username-exists:first').show();
} }
else { else {
$('.credentials:first .username-new:first').show(); $('.credentials:first .username-new:first').show();
$('.credentials:first .username-exists:first').hide(); $('.credentials:first .username-exists:first').hide();
} }
for (let i = 0; i < _tab.credentials.list.length; i++) { for (let i = 0; i < _tab.credentials.list.length; i++) {
let $a = $('<a>') let $a = $('<a>')
.attr('href', '#') .attr('href', '#')
.text(_tab.credentials.list[i].login + ' (' + _tab.credentials.list[i].name + ')') .text(_tab.credentials.list[i].login + ' (' + _tab.credentials.list[i].name + ')')
.data('entryId', i) .data('entryId', i)
.click(function(e) { .click(function(e) {
e.preventDefault(); e.preventDefault();
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'update_credentials', action: 'update_credentials',
args: [_tab.credentials.list[$(this).data('entryId')].uuid, _tab.credentials.username, _tab.credentials.password, _tab.credentials.url] args: [_tab.credentials.list[$(this).data('entryId')].uuid, _tab.credentials.username, _tab.credentials.password, _tab.credentials.url]
}).then(_verifyResult); }).then(_verifyResult);
}); });
if (_tab.credentials.usernameExists && _tab.credentials.username === _tab.credentials.list[i].login) { if (_tab.credentials.usernameExists && _tab.credentials.username === _tab.credentials.list[i].login) {
$a.css('font-weight', 'bold'); $a.css('font-weight', 'bold');
} }
const $li = $('<li class=\"list-group-item\">').append($a); const $li = $('<li class=\"list-group-item\">').append($a);
$('ul#list').append($li); $('ul#list').append($li);
} }
$('.credentials').show(); $('.credentials').show();
} }
}); });
$('#btn-dismiss').click(function(e) { $('#btn-dismiss').click(function(e) {
e.preventDefault(); e.preventDefault();
_close(); _close();
}); });
} }
function _connected_database(db) { function _connected_database(db) {
if (db.count > 1 && db.identifier) { if (db.count > 1 && db.identifier) {
$('.connected-database:first em:first').text(db.identifier); $('.connected-database:first em:first').text(db.identifier);
$('.connected-database:first').show(); $('.connected-database:first').show();
} }
else { else {
$('.connected-database:first').hide(); $('.connected-database:first').hide();
} }
} }
function _verifyResult(code) { function _verifyResult(code) {
if (code === 'success') { if (code === 'success') {
_close(); _close();
} }
} }
function _close() { function _close() {
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'remove_credentials_from_tab_information' action: 'remove_credentials_from_tab_information'
}); });
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'pop_stack' action: 'pop_stack'
}); });
close(); close();
} }
$(function() { $(function() {
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'stack_add', action: 'stack_add',
args: ['icon_remember_red_background_19x19.png', 'popup_remember.html', 10, true, 0] args: ['icon_remember_red_background_19x19.png', 'popup_remember.html', 10, true, 0]
}); });
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'get_tab_information' action: 'get_tab_information'
}).then(_initialize); }).then(_initialize);
browser.runtime.sendMessage({ browser.runtime.sendMessage({
action: 'get_connected_database' action: 'get_connected_database'
}).then(_connected_database); }).then(_connected_database);
}); });