mirror of
https://github.com/keepassxreboot/keepassxc-browser.git
synced 2026-03-11 08:54:43 +00:00
Update popup content dynamically
This commit is contained in:
parent
a2748198b0
commit
9e9314722b
16 changed files with 330 additions and 380 deletions
|
|
@ -122,6 +122,8 @@
|
|||
"importScripts": "readonly",
|
||||
"IMPROVED_DETECTION_PREDEFINED_SITELIST": "readonly",
|
||||
"initColorTheme": "readonly",
|
||||
"initializeHttpAuthLoginList": "readonly",
|
||||
"initializeLoginList": "readonly",
|
||||
"isEdge": "readonly",
|
||||
"isFirefox": "readonly",
|
||||
"keepass": "readonly",
|
||||
|
|
@ -164,9 +166,12 @@
|
|||
"ORANGE_BUTTON": "readonly",
|
||||
"page": "readonly",
|
||||
"Pixels": "readonly",
|
||||
"PublicKeyCredential": "readonly",
|
||||
"PopupIcon": "readonly",
|
||||
"PopupState": "readonly",
|
||||
"PREDEFINED_SITELIST": "readonly",
|
||||
"PublicKeyCredential": "readonly",
|
||||
"RED_BUTTON": "readonly",
|
||||
"removeAllChildren": "readonly",
|
||||
"retrieveColorScheme": "readonly",
|
||||
"sendMessage": "readonly",
|
||||
"showNotification": "readonly",
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@
|
|||
const browserActionWrapper = browser.action || browser.browserAction;
|
||||
const browserAction = {};
|
||||
|
||||
browserAction.show = async function(tab, popupData) {
|
||||
browserAction.updatePopupIcon = async function(tab, popupData) {
|
||||
popupData ??= page.popupData;
|
||||
page.popupData = popupData;
|
||||
|
||||
|
|
@ -12,15 +12,10 @@ browserAction.show = async function(tab, popupData) {
|
|||
});
|
||||
|
||||
if (popupData.popup && tab?.id) {
|
||||
browserActionWrapper.setPopup({
|
||||
tabId: tab.id,
|
||||
popup: `popups/${popupData.popup}.html`
|
||||
});
|
||||
|
||||
let badgeText = '';
|
||||
if (popupData.popup === 'popup_login') {
|
||||
if (popupData.popup === PopupState.LOGIN) {
|
||||
badgeText = page.tabs[tab.id]?.loginList?.length;
|
||||
} else if (popupData.popup === 'popup_httpauth') {
|
||||
} else if (popupData.popup === PopupState.HTTP_AUTH) {
|
||||
badgeText = page.tabs[tab.id]?.loginList?.logins?.length;
|
||||
}
|
||||
|
||||
|
|
@ -28,10 +23,10 @@ browserAction.show = async function(tab, popupData) {
|
|||
}
|
||||
};
|
||||
|
||||
browserAction.showDefault = async function(tab) {
|
||||
browserAction.updatePopup = async function(tab) {
|
||||
const popupData = {
|
||||
iconType: 'normal',
|
||||
popup: 'popup'
|
||||
iconType: PopupIcon.NORMAL,
|
||||
popup: PopupState.DEFAULT
|
||||
};
|
||||
|
||||
const response = await keepass.isConfigured().catch((err) => {
|
||||
|
|
@ -39,11 +34,11 @@ browserAction.showDefault = async function(tab) {
|
|||
});
|
||||
|
||||
if (!response && !keepass.isKeePassXCAvailable) {
|
||||
popupData.iconType = 'cross';
|
||||
popupData.iconType = PopupIcon.CROSS;
|
||||
} else if (!keepass.isAssociated() && !keepass.isDatabaseClosed) {
|
||||
popupData.iconType = 'bang';
|
||||
popupData.iconType = PopupIcon.BANG;
|
||||
} else if (keepass.isKeePassXCAvailable && keepass.isDatabaseClosed) {
|
||||
popupData.iconType = 'locked';
|
||||
popupData.iconType = PopupIcon.LOCKED;
|
||||
}
|
||||
|
||||
// Get the current tab if no tab given
|
||||
|
|
@ -52,13 +47,21 @@ browserAction.showDefault = async function(tab) {
|
|||
return;
|
||||
}
|
||||
|
||||
// Credentials are available
|
||||
if (page?.tabs[tab.id]?.loginList.length > 0) {
|
||||
popupData.iconType = 'normal';
|
||||
popupData.popup = 'popup_login';
|
||||
popupData.iconType = PopupIcon.NORMAL;
|
||||
popupData.popup = PopupState.LOGIN;
|
||||
browserAction.setBadgeText(tab?.id, page.tabs[tab.id]?.loginList.length);
|
||||
}
|
||||
|
||||
await browserAction.show(tab, popupData);
|
||||
// HTTP Basic Auth credentials are available
|
||||
if (page.tabs[tab.id]?.loginList?.logins?.length > 0) {
|
||||
popupData.iconType = PopupIcon.NORMAL;
|
||||
popupData.popup = PopupState.HTTP_AUTH;
|
||||
browserAction.setBadgeText(tab?.id, page.tabs[tab.id]?.loginList?.logins?.length);
|
||||
}
|
||||
|
||||
await browserAction.updatePopupIcon(tab, popupData);
|
||||
};
|
||||
|
||||
browserAction.setBadgeText = function(tabId, badgeText) {
|
||||
|
|
@ -73,7 +76,7 @@ browserAction.setBadgeText = function(tabId, badgeText) {
|
|||
browserAction.generateIconName = async function(iconType) {
|
||||
let name = 'icon_';
|
||||
name += (await keepass.keePassXCUpdateAvailable()) ? 'new_' : '';
|
||||
name += (!iconType || iconType === 'normal') ? 'normal' : iconType;
|
||||
name += (!iconType || iconType === PopupIcon.NORMAL) ? PopupIcon.NORMAL : iconType;
|
||||
|
||||
let style = 'colored';
|
||||
if (page?.settings?.useMonochromeToolbarIcon) {
|
||||
|
|
|
|||
|
|
@ -398,7 +398,7 @@ function onDisconnected() {
|
|||
keepass.databaseHash = '';
|
||||
|
||||
page.clearAllLogins();
|
||||
keepass.updatePopup('cross');
|
||||
keepass.updatePopup(PopupIcon.CROSS);
|
||||
keepass.updateDatabaseHashToContent();
|
||||
logError(`Failed to connect: ${(browser.runtime.lastError === null ? 'Unknown error' : browser.runtime.lastError.message)}`);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ kpxcEvent.showStatus = async function(tab, configured, internalPoll) {
|
|||
}
|
||||
|
||||
if (!internalPoll) {
|
||||
browserAction.showDefault(tab);
|
||||
browserAction.updatePopup(tab);
|
||||
}
|
||||
|
||||
const errorMessage = page.tabs[tab.id]?.errorMessage ?? undefined;
|
||||
|
|
@ -30,7 +30,6 @@ kpxcEvent.showStatus = async function(tab, configured, internalPoll) {
|
|||
|
||||
return {
|
||||
associated: keepass.isAssociated(),
|
||||
|
||||
configured: configured,
|
||||
databaseClosed: keepass.isDatabaseClosed,
|
||||
encryptionKeyUnrecognized: keepass.isEncryptionKeyUnrecognized,
|
||||
|
|
@ -38,6 +37,7 @@ kpxcEvent.showStatus = async function(tab, configured, internalPoll) {
|
|||
iframeDetected: iframeDetected,
|
||||
identifier: keyId,
|
||||
keePassXCAvailable: keepass.isKeePassXCAvailable,
|
||||
popupData: page.popupData,
|
||||
showGettingStartedGuideAlert: page.settings.showGettingStartedGuideAlert,
|
||||
showTroubleshootingGuideAlert: page.settings.showTroubleshootingGuideAlert,
|
||||
usernameFieldDetected: usernameFieldDetected
|
||||
|
|
@ -154,13 +154,13 @@ kpxcEvent.onRemoveCredentialsFromTabInformation = async function(tab) {
|
|||
|
||||
kpxcEvent.onLoginPopup = async function(tab, logins) {
|
||||
const popupData = {
|
||||
iconType: 'normal',
|
||||
popup: 'popup_login'
|
||||
iconType: PopupIcon.NORMAL,
|
||||
popup: PopupState.LOGIN
|
||||
};
|
||||
|
||||
if (tab?.id) {
|
||||
page.tabs[tab.id].loginList = logins;
|
||||
await browserAction.show(tab, popupData);
|
||||
await browserAction.updatePopupIcon(tab, popupData);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -170,12 +170,14 @@ kpxcEvent.initHttpAuth = async function() {
|
|||
|
||||
kpxcEvent.onHTTPAuthPopup = async function(tab, data) {
|
||||
const popupData = {
|
||||
iconType: 'normal',
|
||||
popup: 'popup_httpauth'
|
||||
iconType: PopupIcon.NORMAL,
|
||||
popup: PopupState.HTTP_AUTH
|
||||
};
|
||||
|
||||
page.tabs[tab.id].loginList = data;
|
||||
await browserAction.show(tab, popupData);
|
||||
if (tab?.id) {
|
||||
page.tabs[tab.id].loginList = data;
|
||||
await browserAction.updatePopupIcon(tab, popupData);
|
||||
}
|
||||
};
|
||||
|
||||
kpxcEvent.onUsernameFieldDetected = async function(tab, detected) {
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ const initListeners = async function() {
|
|||
}
|
||||
|
||||
if (changeInfo.status === 'complete' && tab?.id) {
|
||||
browserAction.showDefault(tab);
|
||||
browserAction.updatePopup(tab);
|
||||
if (!page.tabs[tab.id]) {
|
||||
page.createTabEntry(tab.id);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ keepass.updateCredentials = async function(tab, args = []) {
|
|||
const [ entryId, username, password, url, group, groupUuid ] = args;
|
||||
const taResponse = await keepass.testAssociation(tab);
|
||||
if (!taResponse) {
|
||||
browserAction.showDefault(tab);
|
||||
browserAction.updatePopup(tab);
|
||||
return [];
|
||||
}
|
||||
|
||||
|
|
@ -108,7 +108,7 @@ keepass.retrieveCredentials = async function(tab, args = []) {
|
|||
const [ url, submiturl, triggerUnlock = false, httpAuth = false ] = args;
|
||||
const taResponse = await keepass.testAssociation(tab, [ false, triggerUnlock ]);
|
||||
if (!taResponse) {
|
||||
browserAction.showDefault(tab);
|
||||
browserAction.updatePopup(tab);
|
||||
return [];
|
||||
}
|
||||
|
||||
|
|
@ -145,14 +145,14 @@ keepass.retrieveCredentials = async function(tab, args = []) {
|
|||
|
||||
if (entries.length === 0) {
|
||||
// Questionmark-icon is not triggered, so we have to trigger for the normal symbol
|
||||
browserAction.showDefault(tab);
|
||||
browserAction.updatePopup(tab);
|
||||
}
|
||||
|
||||
logDebug(`Found ${entries.length} entries for url ${url}`);
|
||||
return entries;
|
||||
}
|
||||
|
||||
browserAction.showDefault(tab);
|
||||
browserAction.updatePopup(tab);
|
||||
return [];
|
||||
} catch (err) {
|
||||
logError(`retrieveCredentials failed: ${err}`);
|
||||
|
|
@ -168,7 +168,7 @@ keepass.generatePassword = async function(tab) {
|
|||
try {
|
||||
const taResponse = await keepass.testAssociation(tab);
|
||||
if (!taResponse) {
|
||||
browserAction.showDefault(tab);
|
||||
browserAction.updatePopup(tab);
|
||||
return '';
|
||||
}
|
||||
|
||||
|
|
@ -235,7 +235,7 @@ keepass.associate = async function(tab) {
|
|||
keepass.associated.value = true;
|
||||
keepass.associated.hash = response.hash || 0;
|
||||
|
||||
browserAction.showDefault(tab);
|
||||
browserAction.updatePopup(tab);
|
||||
return AssociatedAction.NEW_ASSOCIATION;
|
||||
}
|
||||
|
||||
|
|
@ -468,7 +468,7 @@ keepass.getDatabaseGroups = async function(tab) {
|
|||
try {
|
||||
const taResponse = await keepass.testAssociation(tab, [ false ]);
|
||||
if (!taResponse) {
|
||||
browserAction.showDefault(tab);
|
||||
browserAction.updatePopup(tab);
|
||||
return [];
|
||||
}
|
||||
|
||||
|
|
@ -495,7 +495,7 @@ keepass.getDatabaseGroups = async function(tab) {
|
|||
return groups;
|
||||
}
|
||||
|
||||
browserAction.showDefault(tab);
|
||||
browserAction.updatePopup(tab);
|
||||
return [];
|
||||
} catch (err) {
|
||||
logError(`getDatabaseGroups failed: ${err}`);
|
||||
|
|
@ -508,7 +508,7 @@ keepass.createNewGroup = async function(tab, args = []) {
|
|||
const [ groupName ] = args;
|
||||
const taResponse = await keepass.testAssociation(tab, [ false ]);
|
||||
if (!taResponse) {
|
||||
browserAction.showDefault(tab);
|
||||
browserAction.updatePopup(tab);
|
||||
return [];
|
||||
}
|
||||
|
||||
|
|
@ -534,7 +534,7 @@ keepass.createNewGroup = async function(tab, args = []) {
|
|||
logError('getDatabaseGroups rejected');
|
||||
}
|
||||
|
||||
browserAction.showDefault(tab);
|
||||
browserAction.updatePopup(tab);
|
||||
return [];
|
||||
} catch (err) {
|
||||
logError(`createNewGroup failed: ${err}`);
|
||||
|
|
@ -602,7 +602,7 @@ keepass.passkeysRegister = async function(tab, args = []) {
|
|||
try {
|
||||
const taResponse = await keepass.testAssociation(tab, [ false ]);
|
||||
if (!taResponse || !keepass.isConnected || args.length < 2) {
|
||||
browserAction.showDefault(tab);
|
||||
browserAction.updatePopup(tab);
|
||||
return [];
|
||||
}
|
||||
|
||||
|
|
@ -623,7 +623,7 @@ keepass.passkeysRegister = async function(tab, args = []) {
|
|||
return response;
|
||||
}
|
||||
|
||||
browserAction.showDefault(tab);
|
||||
browserAction.updatePopup(tab);
|
||||
return [];
|
||||
} catch (err) {
|
||||
logError(`passkeysRegister failed: ${err}`);
|
||||
|
|
@ -635,7 +635,7 @@ keepass.passkeysGet = async function(tab, args = []) {
|
|||
try {
|
||||
const taResponse = await keepass.testAssociation(tab, [ false ]);
|
||||
if (!taResponse || !keepass.isConnected || args.length < 2) {
|
||||
browserAction.showDefault(tab);
|
||||
browserAction.updatePopup(tab);
|
||||
return [];
|
||||
}
|
||||
|
||||
|
|
@ -656,7 +656,7 @@ keepass.passkeysGet = async function(tab, args = []) {
|
|||
return response;
|
||||
}
|
||||
|
||||
browserAction.showDefault(tab);
|
||||
browserAction.updatePopup(tab);
|
||||
return [];
|
||||
} catch (err) {
|
||||
logError(`passkeysGet failed: ${err}`);
|
||||
|
|
@ -910,7 +910,7 @@ keepass.handleError = function(tab, errorCode, errorMessage = '') {
|
|||
|
||||
keepass.updatePopup = function() {
|
||||
if (page && page.tabs.length > 0) {
|
||||
browserAction.showDefault();
|
||||
browserAction.updatePopup();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -56,8 +56,8 @@ page.submittedCredentials = {};
|
|||
page.tabs = [];
|
||||
|
||||
page.popupData = {
|
||||
iconType: 'normal',
|
||||
popup: 'popup'
|
||||
iconType: PopupIcon.NORMAL,
|
||||
popup: PopupState.DEFAULT
|
||||
};
|
||||
|
||||
page.initSettings = async function() {
|
||||
|
|
@ -118,7 +118,7 @@ page.initOpenedTabs = async function() {
|
|||
}
|
||||
|
||||
page.currentTabId = currentTab?.id;
|
||||
browserAction.showDefault(currentTab);
|
||||
browserAction.updatePopup(currentTab);
|
||||
} catch (err) {
|
||||
logError('page.initOpenedTabs error: ' + err);
|
||||
return Promise.reject();
|
||||
|
|
@ -154,7 +154,7 @@ page.switchTab = async function(tab) {
|
|||
}
|
||||
}, page.settings.clearCredentialsTimeout * 1000);
|
||||
|
||||
browserAction.showDefault(tab);
|
||||
browserAction.updatePopup(tab);
|
||||
if (tab?.id) {
|
||||
browser.tabs.sendMessage(tab.id, { action: 'activated_tab' }).catch((e) => {
|
||||
logError('Cannot send activated_tab message: ' + e.message);
|
||||
|
|
@ -397,7 +397,7 @@ page.updateContextMenu = async function(tab, credentials) {
|
|||
};
|
||||
|
||||
page.updatePopup = function(tab) {
|
||||
browserAction.showDefault(tab);
|
||||
browserAction.updatePopup(tab);
|
||||
};
|
||||
|
||||
page.setAllowIframes = async function(tab, args = []) {
|
||||
|
|
|
|||
|
|
@ -26,23 +26,6 @@ const URL_WILDCARD = '1kpxcwc1';
|
|||
const schemeSegment = '(\\*|http|https|ws|wss|ftp)';
|
||||
const hostSegment = '(\\*|(?:\\*\\.)?(?:[^/*]+))?';
|
||||
|
||||
const isFirefox = function() {
|
||||
return navigator.userAgent.indexOf('Firefox') !== -1 || navigator.userAgent.indexOf('Gecko/') !== -1;
|
||||
};
|
||||
|
||||
const isEdge = function() {
|
||||
return navigator.userAgent.indexOf('Edg') !== -1;
|
||||
};
|
||||
|
||||
const showNotification = function(message) {
|
||||
browser.notifications.create({
|
||||
'type': 'basic',
|
||||
'iconUrl': browser.runtime.getURL('icons/keepassxc_64x64.png'),
|
||||
'title': 'KeePassXC-Browser',
|
||||
'message': message
|
||||
});
|
||||
};
|
||||
|
||||
const AssociatedAction = {
|
||||
NOT_ASSOCIATED: 0,
|
||||
ASSOCIATED: 1,
|
||||
|
|
@ -61,6 +44,38 @@ const ManualFill = {
|
|||
BOTH: 2
|
||||
};
|
||||
|
||||
// Popup icon types
|
||||
const PopupIcon = {
|
||||
BANG: 'bang',
|
||||
CROSS: 'cross',
|
||||
LOCKED: 'locked',
|
||||
NORMAL: 'normal'
|
||||
};
|
||||
|
||||
// Popup states
|
||||
const PopupState = {
|
||||
DEFAULT: 'default',
|
||||
HTTP_AUTH: 'http_auth',
|
||||
LOGIN: 'login'
|
||||
};
|
||||
|
||||
const isFirefox = function() {
|
||||
return navigator.userAgent.indexOf('Firefox') !== -1 || navigator.userAgent.indexOf('Gecko/') !== -1;
|
||||
};
|
||||
|
||||
const isEdge = function() {
|
||||
return navigator.userAgent.indexOf('Edg') !== -1;
|
||||
};
|
||||
|
||||
const showNotification = function(message) {
|
||||
browser.notifications.create({
|
||||
'type': 'basic',
|
||||
'iconUrl': browser.runtime.getURL('icons/keepassxc_64x64.png'),
|
||||
'title': 'KeePassXC-Browser',
|
||||
'message': message
|
||||
});
|
||||
};
|
||||
|
||||
const compareVersion = function(minimum, current, canBeEqual = true) {
|
||||
if (!minimum || !current || minimum?.indexOf('.') === -1 || current?.indexOf('.') === -1) {
|
||||
return false;
|
||||
|
|
@ -182,6 +197,12 @@ const getCurrentTab = async function() {
|
|||
return tabs?.length > 0 ? tabs[0] : undefined;
|
||||
};
|
||||
|
||||
const removeAllChildren = function(elem) {
|
||||
while (elem?.hasChildNodes()) {
|
||||
elem.removeChild(elem.lastChild);
|
||||
}
|
||||
};
|
||||
|
||||
// Exports for tests
|
||||
if (typeof module === 'object') {
|
||||
module.exports = {
|
||||
|
|
|
|||
|
|
@ -140,9 +140,7 @@ class Autocomplete {
|
|||
await kpxc.updateTOTPList();
|
||||
|
||||
// Clear the login items from div
|
||||
while (this.list.hasChildNodes()) {
|
||||
this.list.removeChild(this.list.lastChild);
|
||||
}
|
||||
removeAllChildren(this.list);
|
||||
|
||||
// Update credentials to menu div
|
||||
for (const c of this.elements) {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
<body>
|
||||
<div class="container">
|
||||
<div id="settings" class="settings">
|
||||
<!-- Buttons in the top area -->
|
||||
<div class="action-buttons-area">
|
||||
<button id="options-button" class="btn btn-sm btn-success" data-i18n="[title]popupSettingsText">
|
||||
<i class="fa fa-cog" aria-hidden="true"></i>
|
||||
|
|
@ -31,6 +32,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Alerts -->
|
||||
<div id="popup-alerts">
|
||||
<div id="update-available" class="alert alert-warning">
|
||||
<span data-i18n="popupUpdateAvailable"></span>
|
||||
|
|
@ -41,22 +43,28 @@
|
|||
<div id="getting-started-guide" class="alert alert-info alert-dismissible">
|
||||
<span data-i18n="popupGettingStartedText"></span>
|
||||
<br>
|
||||
<a target="_blank" class="alert-link" href="https://keepassxc.org/docs/KeePassXC_GettingStarted.html#_setup_browser_integration"><span data-i18n="popupGettingStartedLinkText"></span></a>
|
||||
<a target="_blank" class="alert-link" href="https://keepassxc.org/docs/KeePassXC_GettingStarted.html#_setup_browser_integration">
|
||||
<span data-i18n="popupGettingStartedLinkText"></span>
|
||||
</a>
|
||||
<button type="button" id="getting-started-alert-close-button" class="btn-close" data-bs-dismiss="alert" data-i18n="[title]popupAlertHide"></button>
|
||||
</div>
|
||||
|
||||
<div id="troubleshooting-guide" class="alert alert-info alert-dismissible">
|
||||
<span data-i18n="popupTroubleshootingText"></span>
|
||||
<br>
|
||||
<a target="_blank" class="alert-link" href="https://github.com/keepassxreboot/keepassxc-browser/wiki/Troubleshooting-guide"><span data-i18n="popupTroubleshootingLinkText"></span></a>
|
||||
<a target="_blank" class="alert-link" href="https://github.com/keepassxreboot/keepassxc-browser/wiki/Troubleshooting-guide">
|
||||
<span data-i18n="popupTroubleshootingLinkText"></span>
|
||||
</a>
|
||||
<button type="button" id="troubleshooting-guide-alert-close-button" class="btn-close" data-bs-dismiss="alert" data-i18n="[title]popupAlertHide"></button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Loading -->
|
||||
<div id="initial-state">
|
||||
<div class="loader"></div> <p data-i18n="popupCheckingStatus"></p>
|
||||
</div>
|
||||
|
||||
<!-- Database open but not connected -->
|
||||
<div id="not-configured">
|
||||
<p data-i18n="popupNotConfigured"></p>
|
||||
<div class="right-align">
|
||||
|
|
@ -67,6 +75,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Needs reconnect -->
|
||||
<div id="need-reconfigure">
|
||||
<p data-i18n="popupNeedReconfigure"></p>
|
||||
<p id="left-margin">
|
||||
|
|
@ -85,6 +94,7 @@
|
|||
<span data-i18n="popupConfiguredNotAssociated" data-i18n-placeholder="<span class='bg-warning' id='unassociated-identifier'></span>"></span>
|
||||
</div>
|
||||
|
||||
<!-- Database open and connected -->
|
||||
<div id="configured-and-associated">
|
||||
<p data-i18n="popupConfiguredAndAssociated" data-i18n-placeholder="<span class='bg-success' id='associated-identifier'></span>"></p>
|
||||
<div class="right-align">
|
||||
|
|
@ -95,6 +105,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Error message -->
|
||||
<div id="error-encountered">
|
||||
<p data-i18n="popupErrorEncountered"></p>
|
||||
<p id="left-margin">
|
||||
|
|
@ -108,6 +119,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Database not opened message -->
|
||||
<div id="database-not-opened">
|
||||
<p data-i18n="popupErrorEncountered"></p>
|
||||
<p id="left-margin">
|
||||
|
|
@ -121,6 +133,29 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Login list -->
|
||||
<div id="credentials-list" class="credentials" style="display: none">
|
||||
<p data-i18n="popupLoginText"></p>
|
||||
<div id="filter-block">
|
||||
<label for="login-filter" data-i18n="popupFilterText"></label>
|
||||
<input type="text" id="login-filter">
|
||||
</div>
|
||||
<div id="login-list" class="list-group"></div>
|
||||
</div>
|
||||
|
||||
<!-- HTTP Auth login list-->
|
||||
<div id="http-auth-credentials-list" class="credentials" style="display: none">
|
||||
<p data-i18n="popupAuthText"></p>
|
||||
<div id="http-auth-login-list" class="list-group"></div>
|
||||
<p>
|
||||
<button id="btn-dismiss" class="btn btn-sm btn-danger" data-i18n="[title]dismissHttpAuthButtonTitle">
|
||||
<i class="fa fa-remove" aria-hidden="true"></i>
|
||||
<span data-i18n="popupButtonDismissHttpAuth"></span>
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Username-only field detected message -->
|
||||
<div id="username-field-detected">
|
||||
<hr>
|
||||
<p data-i18n="popupUsernameFieldDetected"></p>
|
||||
|
|
@ -132,6 +167,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Iframe detected message -->
|
||||
<div id="iframe-detected" style="display: none">
|
||||
<hr>
|
||||
<p data-i18n="popupIframeDetected"></p>
|
||||
|
|
|
|||
|
|
@ -1,16 +1,10 @@
|
|||
'use strict';
|
||||
|
||||
const POLLING_INTERVAL = 1000; // ms
|
||||
let previousStatus;
|
||||
let reloadCount = 0;
|
||||
|
||||
HTMLElement.prototype.show = function() {
|
||||
this.style.display = 'block';
|
||||
};
|
||||
|
||||
HTMLElement.prototype.hide = function() {
|
||||
this.style.display = 'none';
|
||||
};
|
||||
|
||||
function statusResponse(r) {
|
||||
function hideAll() {
|
||||
$('#initial-state').hide();
|
||||
$('#error-encountered').hide();
|
||||
$('#need-reconfigure').hide();
|
||||
|
|
@ -20,49 +14,79 @@ function statusResponse(r) {
|
|||
$('#lock-database-button').hide();
|
||||
$('#getting-started-guide').hide();
|
||||
$('#database-not-opened').hide();
|
||||
$('#credentials-list').hide();
|
||||
$('#http-auth-credentials-list').hide();
|
||||
}
|
||||
|
||||
if (!r.keePassXCAvailable) {
|
||||
$('#error-message').textContent = r.error;
|
||||
function handleStatusResponse(response) {
|
||||
hideAll();
|
||||
|
||||
// Error situations
|
||||
if (!response.keePassXCAvailable) {
|
||||
$('#error-message').textContent = response.error;
|
||||
$('#error-encountered').show();
|
||||
|
||||
if (r.showGettingStartedGuideAlert) {
|
||||
if (response.showGettingStartedGuideAlert) {
|
||||
$('#getting-started-guide').show();
|
||||
}
|
||||
|
||||
if (r.showTroubleshootingGuideAlert && reloadCount >= 2) {
|
||||
if (response.showTroubleshootingGuideAlert && reloadCount >= 2) {
|
||||
$('#troubleshooting-guide').show();
|
||||
} else {
|
||||
$('#troubleshooting-guide').hide();
|
||||
}
|
||||
} else if (r.keePassXCAvailable && r.databaseClosed) {
|
||||
$('#database-error-message').textContent = r.error;
|
||||
return;
|
||||
} else if (response.keePassXCAvailable && response.databaseClosed) {
|
||||
$('#database-error-message').textContent = response.error;
|
||||
$('#database-not-opened').show();
|
||||
} else if (!r.configured) {
|
||||
return;
|
||||
} else if (!response.configured) {
|
||||
$('#not-configured').show();
|
||||
} else if (r.encryptionKeyUnrecognized) {
|
||||
return;
|
||||
} else if (response.encryptionKeyUnrecognized) {
|
||||
$('#need-reconfigure').show();
|
||||
$('#need-reconfigure-message').textContent = r.error;
|
||||
} else if (!r.associated) {
|
||||
$('#need-reconfigure-message').textContent = response.error;
|
||||
return;
|
||||
} else if (!response.associated) {
|
||||
$('#need-reconfigure').show();
|
||||
$('#need-reconfigure-message').textContent = r.error;
|
||||
} else if (r.error) {
|
||||
$('#need-reconfigure-message').textContent = response.error;
|
||||
return;
|
||||
} else if (response.error) {
|
||||
$('#error-encountered').show();
|
||||
$('#error-message').textContent = r.error;
|
||||
} else {
|
||||
$('#configured-and-associated').show();
|
||||
$('#associated-identifier').textContent = r.identifier;
|
||||
$('#lock-database-button').show();
|
||||
|
||||
if (r.usernameFieldDetected) {
|
||||
$('#username-field-detected').show();
|
||||
}
|
||||
|
||||
if (r.iframeDetected) {
|
||||
$('#iframe-detected').show();
|
||||
}
|
||||
|
||||
reloadCount = 0;
|
||||
$('#error-message').textContent = response.error;
|
||||
return;
|
||||
}
|
||||
|
||||
// Show the popup content based on status
|
||||
if (response?.popupData?.popup === PopupState.LOGIN) {
|
||||
$('#credentials-list').show();
|
||||
$('#configured-and-associated').hide();
|
||||
initializeLoginList();
|
||||
} else if (response?.popupData?.popup === PopupState.HTTP_AUTH) {
|
||||
$('#http-auth-credentials-list').show();
|
||||
$('#configured-and-associated').hide();
|
||||
initializeHttpAuthLoginList();
|
||||
} else {
|
||||
// PopupState.DEFAULT
|
||||
$('#credentials-list').hide();
|
||||
$('#http-auth-credentials-list').hide();
|
||||
$('#configured-and-associated').show();
|
||||
$('#associated-identifier').textContent = response.identifier;
|
||||
}
|
||||
|
||||
$('#lock-database-button').show();
|
||||
|
||||
// Show button for adding Username-Only Detection for the site
|
||||
if (response.usernameFieldDetected) {
|
||||
$('#username-field-detected').show();
|
||||
}
|
||||
|
||||
// Show button for allowing Cross-Origin IFrames for the site
|
||||
if (response.iframeDetected) {
|
||||
$('#iframe-detected').show();
|
||||
}
|
||||
|
||||
reloadCount = 0;
|
||||
}
|
||||
|
||||
const sendMessageToTab = async function(message) {
|
||||
|
|
@ -99,7 +123,7 @@ const sendMessageToTab = async function(message) {
|
|||
});
|
||||
|
||||
$('#reload-status-button').addEventListener('click', async () => {
|
||||
statusResponse(await browser.runtime.sendMessage({
|
||||
handleStatusResponse(await browser.runtime.sendMessage({
|
||||
action: 'reconnect'
|
||||
}));
|
||||
|
||||
|
|
@ -111,7 +135,7 @@ const sendMessageToTab = async function(message) {
|
|||
});
|
||||
|
||||
$('#reopen-database-button').addEventListener('click', async () => {
|
||||
statusResponse(await browser.runtime.sendMessage({
|
||||
handleStatusResponse(await browser.runtime.sendMessage({
|
||||
action: 'get_status',
|
||||
args: [ false, true ] // Set forcePopup to true
|
||||
}));
|
||||
|
|
@ -124,13 +148,13 @@ const sendMessageToTab = async function(message) {
|
|||
return;
|
||||
}
|
||||
|
||||
statusResponse(await browser.runtime.sendMessage({
|
||||
handleStatusResponse(await browser.runtime.sendMessage({
|
||||
action: 'get_status'
|
||||
}));
|
||||
});
|
||||
|
||||
$('#lock-database-button').addEventListener('click', async () => {
|
||||
statusResponse(await browser.runtime.sendMessage({
|
||||
handleStatusResponse(await browser.runtime.sendMessage({
|
||||
action: 'lock_database'
|
||||
}));
|
||||
});
|
||||
|
|
@ -159,9 +183,37 @@ const sendMessageToTab = async function(message) {
|
|||
});
|
||||
});
|
||||
|
||||
statusResponse(await browser.runtime.sendMessage({
|
||||
action: 'get_status'
|
||||
}).catch((err) => {
|
||||
logError('Could not get status: ' + err);
|
||||
}));
|
||||
// For HTTP Basic Auth
|
||||
$('#btn-dismiss').addEventListener('click', async () => {
|
||||
// Return empty credentials
|
||||
browser.runtime.sendMessage({
|
||||
action: 'fill_http_auth',
|
||||
args: { login: '', password: '' }
|
||||
});
|
||||
|
||||
close();
|
||||
});
|
||||
|
||||
async function getNewStatus() {
|
||||
return await browser.runtime.sendMessage({
|
||||
action: 'get_status'
|
||||
}).catch((err) => {
|
||||
logError('Could not get status: ' + err);
|
||||
});
|
||||
}
|
||||
|
||||
// Get status right after popup has been opened
|
||||
handleStatusResponse(await getNewStatus());
|
||||
|
||||
// Poll status
|
||||
setInterval(async () => {
|
||||
// Check if the popup state has been changed or database has been opened/closed
|
||||
const currentStatus = await getNewStatus();
|
||||
if (previousStatus?.popupData?.popup !== currentStatus?.popupData?.popup
|
||||
|| previousStatus?.databaseClosed !== currentStatus?.databaseClosed
|
||||
|| previousStatus?.keePassXCAvailable !== currentStatus?.keePassXCAvailable) {
|
||||
previousStatus = currentStatus;
|
||||
handleStatusResponse(currentStatus);
|
||||
}
|
||||
}, POLLING_INTERVAL);
|
||||
})();
|
||||
|
|
|
|||
|
|
@ -53,8 +53,103 @@ async function getLoginData() {
|
|||
return logins;
|
||||
}
|
||||
|
||||
// Initializes the default login list
|
||||
async function initializeLoginList() {
|
||||
const tab = await getCurrentTab();
|
||||
if (!tab) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const logins = await getLoginData();
|
||||
const loginList = document.getElementById('login-list');
|
||||
|
||||
// Empty any existing values
|
||||
removeAllChildren(loginList);
|
||||
|
||||
for (const [ i, login ] of logins.entries()) {
|
||||
const a = document.createElement('a');
|
||||
a.textContent = login.text;
|
||||
a.setAttribute('class', 'list-group-item');
|
||||
a.setAttribute('id', '' + i);
|
||||
|
||||
a.addEventListener('click', (e) => {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
|
||||
const id = e.target.id;
|
||||
browser.tabs.sendMessage(tab?.id, {
|
||||
action: 'fill_user_pass_with_specific_login',
|
||||
id: Number(id),
|
||||
uuid: login?.uuid
|
||||
});
|
||||
|
||||
close();
|
||||
});
|
||||
|
||||
loginList.appendChild(a);
|
||||
}
|
||||
|
||||
if (logins.length > 1) {
|
||||
$('#filter-block').show();
|
||||
const filter = document.getElementById('login-filter');
|
||||
filter.addEventListener('keyup', (e) => {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
|
||||
const val = filter.value;
|
||||
const re = new RegExp(val, 'i');
|
||||
const links = loginList.getElementsByTagName('a');
|
||||
for (const i in links) {
|
||||
if (links.hasOwnProperty(i)) {
|
||||
const found = String(links[i].textContent).match(re) !== null;
|
||||
links[i].style = found ? '' : 'display: none;';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
filter.focus();
|
||||
}
|
||||
}
|
||||
|
||||
// Intitializes the login list for HTTP Basic Auth
|
||||
async function initializeHttpAuthLoginList() {
|
||||
const data = await getLoginData();
|
||||
const loginList = document.getElementById('http-auth-login-list');
|
||||
|
||||
// Empty any existing values
|
||||
removeAllChildren(loginList);
|
||||
|
||||
for (const [ i, login ] of data.logins.entries()) {
|
||||
const a = document.createElement('a');
|
||||
a.textContent = login.login + ' (' + login.name + ')';
|
||||
a.setAttribute('class', 'list-group-item');
|
||||
a.setAttribute('id', '' + i);
|
||||
|
||||
a.addEventListener('click', (e) => {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
|
||||
const credentials = data.logins[Number(e.target.id)];
|
||||
browser.runtime.sendMessage({
|
||||
action: 'fill_http_auth',
|
||||
args: credentials
|
||||
});
|
||||
|
||||
close();
|
||||
});
|
||||
|
||||
loginList.appendChild(a);
|
||||
}
|
||||
}
|
||||
|
||||
(async () => {
|
||||
if (document.readyState === 'complete' || (document.readyState !== 'loading' && !document.documentElement.doScroll)) {
|
||||
if (
|
||||
document.readyState === 'complete' ||
|
||||
(document.readyState !== 'loading' && !document.documentElement.doScroll)
|
||||
) {
|
||||
await initSettings();
|
||||
} else {
|
||||
document.addEventListener('DOMContentLoaded', initSettings);
|
||||
|
|
|
|||
|
|
@ -1,65 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title data-i18n="popupTitle"></title>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="../css/colors.css">
|
||||
<link rel="stylesheet" href="popup.css">
|
||||
<link rel="stylesheet" href="../bootstrap/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="../fonts/fork-awesome.min.css">
|
||||
<script src="../common/browser-polyfill.min.js"></script>
|
||||
<script src="../common/global.js"></script>
|
||||
<script src="../common/global_ui.js"></script>
|
||||
<script src="../bootstrap/bootstrap.min.js"></script>
|
||||
<script src="popup_functions.js"></script>
|
||||
<script defer src="popup_httpauth.js"></script>
|
||||
<script defer src="../common/translate.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div id="settings" class="settings">
|
||||
<div class="function-buttons-area">
|
||||
<button id="options-button" class="btn btn-sm btn-success" data-i18n="[title]popupSettingsText">
|
||||
<i class="fa fa-cog" aria-hidden="true"></i>
|
||||
</button>
|
||||
<button id="choose-custom-login-fields-button" class="btn btn-sm btn-warning" data-i18n="[title]popupChooseCredentialsText"></button>
|
||||
</div>
|
||||
<div class="lock-button-area">
|
||||
<button id="lock-database-button" class="btn btn-sm btn-danger" data-i18n="[title]lockDatabase">
|
||||
<i class="fa fa-lock" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="update-available" class="alert alert-warning">
|
||||
<span data-i18n="popupUpdateAvailable"></span>
|
||||
<br>
|
||||
<a target="_blank" class="alert-link" href="https://keepassxc.org/download"><span data-i18n="popupDownloadNewVersion"></span></a>.
|
||||
</div>
|
||||
|
||||
<div class="credentials">
|
||||
<p data-i18n="popupAuthText"></p>
|
||||
<div id="login-list" class="list-group"></div>
|
||||
<p>
|
||||
<button id="btn-dismiss" class="btn btn-sm btn-danger" data-i18n="[title]dismissHttpAuthButtonTitle">
|
||||
<i class="fa fa-remove" aria-hidden="true"></i>
|
||||
<span data-i18n="popupButtonDismissHttpAuth"></span>
|
||||
</button>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div id="database-not-opened">
|
||||
<p data-i18n="popupErrorEncountered"></p>
|
||||
<p style="margin-left: 1em">
|
||||
<code id="database-error-message"></code>
|
||||
</p>
|
||||
<div class="right-align">
|
||||
<button id="reopen-database-button" class="btn btn-sm btn-primary" data-i18n="[title]reopenDatabaseButtonTitle">
|
||||
<i class="fa fa-lock" aria-hidden="true"></i>
|
||||
<span data-i18n="popupReopenButton"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,54 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
(async () => {
|
||||
await initColorTheme();
|
||||
|
||||
$('#lock-database-button').show();
|
||||
|
||||
const data = await getLoginData();
|
||||
const ll = document.getElementById('login-list');
|
||||
|
||||
for (const [ i, login ] of data.logins.entries()) {
|
||||
const a = document.createElement('a');
|
||||
a.setAttribute('class', 'list-group-item');
|
||||
a.textContent = login.login + ' (' + login.name + ')';
|
||||
a.setAttribute('id', '' + i);
|
||||
|
||||
a.addEventListener('click', (e) => {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
|
||||
const credentials = data.logins[Number(e.target.id)];
|
||||
browser.runtime.sendMessage({
|
||||
action: 'fill_http_auth',
|
||||
args: credentials
|
||||
});
|
||||
|
||||
close();
|
||||
});
|
||||
ll.appendChild(a);
|
||||
}
|
||||
|
||||
$('#lock-database-button').addEventListener('click', function() {
|
||||
browser.runtime.sendMessage({
|
||||
action: 'lock_database'
|
||||
});
|
||||
|
||||
$('.credentials').hide();
|
||||
$('#btn-dismiss').hide();
|
||||
$('#database-not-opened').show();
|
||||
$('#lock-database-button').hide();
|
||||
$('#database-error-message').textContent = tr('errorMessageDatabaseNotOpened');
|
||||
});
|
||||
|
||||
$('#btn-dismiss').addEventListener('click', async () => {
|
||||
// Return empty credentials
|
||||
browser.runtime.sendMessage({
|
||||
action: 'fill_http_auth',
|
||||
args: { login: '', password: '' }
|
||||
});
|
||||
|
||||
close();
|
||||
});
|
||||
})();
|
||||
|
|
@ -1,63 +0,0 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title data-i18n="popupTitle"></title>
|
||||
<meta charset="UTF-8">
|
||||
<link rel="stylesheet" href="../css/colors.css">
|
||||
<link rel="stylesheet" href="popup.css">
|
||||
<link rel="stylesheet" href="../bootstrap/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="../fonts/fork-awesome.min.css">
|
||||
<script src="../common/browser-polyfill.min.js"></script>
|
||||
<script src="../common/global.js"></script>
|
||||
<script src="../common/global_ui.js"></script>
|
||||
<script src="../bootstrap/bootstrap.min.js"></script>
|
||||
<script src="popup_functions.js"></script>
|
||||
<script defer src="popup_login.js"></script>
|
||||
<script defer src="../common/translate.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div id="settings" class="settings">
|
||||
<div class="function-buttons-area">
|
||||
<button id="options-button" class="btn btn-sm btn-success" data-i18n="[title]popupSettingsText">
|
||||
<i class="fa fa-cog" aria-hidden="true"></i>
|
||||
</button>
|
||||
<button id="choose-custom-login-fields-button" class="btn btn-sm btn-warning" data-i18n="[title]popupChooseCredentialsText"></button>
|
||||
</div>
|
||||
<div class="lock-button-area">
|
||||
<button id="lock-database-button" class="btn btn-sm btn-danger" data-i18n="[title]lockDatabase">
|
||||
<i class="fa fa-lock" aria-hidden="true"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="update-available" class="alert alert-warning">
|
||||
<span data-i18n="popupUpdateAvailable"></span>
|
||||
<br>
|
||||
<a target="_blank" class="alert-link" href="https://keepassxc.org/download"><span data-i18n="popupDownloadNewVersion"></span></a>.
|
||||
</div>
|
||||
|
||||
<div id="credentialsList" class="credentials">
|
||||
<p data-i18n="popupLoginText"></p>
|
||||
<div id="filter-block">
|
||||
<label for="login-filter" data-i18n="popupFilterText"></label>
|
||||
<input type="text" id="login-filter">
|
||||
</div>
|
||||
<div id="login-list" class="list-group"></div>
|
||||
</div>
|
||||
|
||||
<div id="database-not-opened">
|
||||
<p data-i18n="popupErrorEncountered"></p>
|
||||
<p style="margin-left: 1em">
|
||||
<code id="database-error-message"></code>
|
||||
</p>
|
||||
<div class="right-align">
|
||||
<button id="reopen-database-button" class="btn btn-sm btn-primary" data-i18n="[title]reopenDatabaseButtonTitle">
|
||||
<i class="fa fa-lock" aria-hidden="true"></i>
|
||||
<span data-i18n="popupReopenButton"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -1,80 +0,0 @@
|
|||
'use strict';
|
||||
|
||||
(async () => {
|
||||
await initColorTheme();
|
||||
|
||||
$('#lock-database-button').show();
|
||||
|
||||
const tab = await getCurrentTab();
|
||||
if (!tab) {
|
||||
return [];
|
||||
}
|
||||
|
||||
const logins = await getLoginData();
|
||||
const ll = document.getElementById('login-list');
|
||||
|
||||
for (const [ i, login ] of logins.entries()) {
|
||||
const uuid = login.uuid;
|
||||
const a = document.createElement('a');
|
||||
a.textContent = login.text;
|
||||
a.setAttribute('class', 'list-group-item');
|
||||
a.setAttribute('id', '' + i);
|
||||
|
||||
a.addEventListener('click', (e) => {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
|
||||
const id = e.target.id;
|
||||
browser.tabs.sendMessage(tab?.id, {
|
||||
action: 'fill_user_pass_with_specific_login',
|
||||
id: Number(id),
|
||||
uuid: uuid
|
||||
});
|
||||
|
||||
close();
|
||||
});
|
||||
|
||||
ll.appendChild(a);
|
||||
}
|
||||
|
||||
if (logins.length > 1) {
|
||||
$('#filter-block').show();
|
||||
const filter = document.getElementById('login-filter');
|
||||
filter.addEventListener('keyup', (e) => {
|
||||
if (!e.isTrusted) {
|
||||
return;
|
||||
}
|
||||
|
||||
const val = filter.value;
|
||||
const re = new RegExp(val, 'i');
|
||||
const links = ll.getElementsByTagName('a');
|
||||
for (const i in links) {
|
||||
if (links.hasOwnProperty(i)) {
|
||||
const found = String(links[i].textContent).match(re) !== null;
|
||||
links[i].style = found ? '' : 'display: none;';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
filter.focus();
|
||||
}
|
||||
|
||||
$('#lock-database-button').addEventListener('click', (e) => {
|
||||
browser.runtime.sendMessage({
|
||||
action: 'lock_database'
|
||||
});
|
||||
|
||||
$('#credentialsList').hide();
|
||||
$('#database-not-opened').show();
|
||||
$('#lock-database-button').hide();
|
||||
$('#database-error-message').textContent = tr('errorMessageDatabaseNotOpened');
|
||||
});
|
||||
|
||||
$('#reopen-database-button').addEventListener('click', (e) => {
|
||||
browser.runtime.sendMessage({
|
||||
action: 'get_status',
|
||||
args: [ false, true ] // Set forcePopup to true
|
||||
});
|
||||
});
|
||||
})();
|
||||
Loading…
Reference in a new issue