diff --git a/keepassxc-browser/background/browserAction.js b/keepassxc-browser/background/browserAction.js index d2fdb7d..98a5bfd 100755 --- a/keepassxc-browser/background/browserAction.js +++ b/keepassxc-browser/background/browserAction.js @@ -202,6 +202,14 @@ browserAction.removeRememberPopup = function(callback, tab, removeImmediately) { browserAction.setRememberPopup = function(tabId, username, password, url, usernameExists, credentialsList) { browser.storage.local.get({'settings': {}}).then(function(item) { const settings = item.settings; + + // Don't show anything if the site is in the ignore list + for (const site in settings.ignoredSites) { + if (site === url) { + return; + } + } + const id = tabId || page.currentTabId; let timeoutMinMillis = Number(getValueOrDefault(settings, 'blinkMinTimeout', BLINK_TIMEOUT_REDIRECT_THRESHOLD_TIME_DEFAULT, 0)); @@ -240,7 +248,29 @@ browserAction.setRememberPopup = function(tabId, username, password, url, userna browserAction.show(null, {'id': id}); if (page.settings.showLoginNotifications) { - showNotification('Create or modify the credentials by clicking on the extension icon.'); + const message = 'Create or modify the credentials by clicking on the extension icon.'; + const buttons = [ + { + 'title': 'Close' + }, + { + 'title': 'Never ask for this page' + }]; + + browser.notifications.create({ + 'type': 'basic', + 'iconUrl': browser.extension.getURL('icons/keepassxc_64x64.png'), + 'title': 'KeePassXC-Browser', + 'message': message, + 'buttons': buttons + }); + + browser.notifications.onButtonClicked.addListener((id, index) => { + browser.notifications.clear(id); + if (index === 1) { + browserAction.ignoreSite(url); + } + }); } }); }; @@ -269,3 +299,21 @@ browserAction.generateIconName = function(iconType, icon) { return name; }; + +browserAction.ignoreSite = function(url) { + browser.windows.getCurrent().then((win) => { + // Get current active window + browser.tabs.query({ 'active': true, 'currentWindow': true }).then((tabs) => { + const tab = tabs[0]; + + // Send the message to the current tab's content script + browser.runtime.getBackgroundPage().then((global) => { + browser.tabs.sendMessage(tab.id, { + action: 'ignore-site', + args: [url] + }); + }); + }); + }); +}; + diff --git a/keepassxc-browser/keepassxc-browser.js b/keepassxc-browser/keepassxc-browser.js index c9561b8..4473548 100755 --- a/keepassxc-browser/keepassxc-browser.js +++ b/keepassxc-browser/keepassxc-browser.js @@ -30,48 +30,41 @@ browser.runtime.onMessage.addListener(function(req, sender, callback) { cipForm.destroy(false, {'password': list.list[0], 'username': list.list[1]}); } } - } - else if (req.action === 'fill_user_pass') { + } else if (req.action === 'fill_user_pass') { _called.manualFillRequested = 'both'; cip.receiveCredentialsIfNecessary().then((response) => { cip.fillInFromActiveElement(false); }); - } - else if (req.action === 'fill_pass_only') { + } else if (req.action === 'fill_pass_only') { _called.manualFillRequested = 'pass'; cip.receiveCredentialsIfNecessary().then((response) => { cip.fillInFromActiveElement(false, true); // passOnly to true }); - } - else if (req.action === 'fill_totp') { + } else if (req.action === 'fill_totp') { cip.receiveCredentialsIfNecessary().then((response) => { cip.fillInFromActiveElementTOTPOnly(false); }); - } - else if (req.action === 'activate_password_generator') { + } else if (req.action === 'activate_password_generator') { cip.initPasswordGenerator(cipFields.getAllFields()); - } - else if (req.action === 'remember_credentials') { + } else if (req.action === 'remember_credentials') { cip.contextMenuRememberCredentials(); - } - else if (req.action === 'choose_credential_fields') { + } else if (req.action === 'choose_credential_fields') { cipDefine.init(); - } - else if (req.action === 'clear_credentials') { + } else if (req.action === 'clear_credentials') { cipEvents.clearCredentials(); callback(); - } - else if (req.action === 'activated_tab') { + } else if (req.action === 'activated_tab') { cipEvents.triggerActivatedTab(); callback(); - } - else if (req.action === 'redetect_fields') { + } else if (req.action === 'redetect_fields') { browser.runtime.sendMessage({ action: 'load_settings', }).then((response) => { cip.settings = response; cip.initCredentialFields(true); }); + } else if (req.action === 'ignore-site') { + cip.ignoreSite(req.args); } } }); @@ -1827,6 +1820,25 @@ cip.rememberCredentials = function(usernameValue, passwordValue) { return false; }; +cip.ignoreSite = function(sites) { + if (!sites || sites.length === 0) { + return; + } + + const site = sites[0]; + if (!cip.settings['ignoredSites']) { + cip.settings['ignoredSites'] = {}; + } + + cip.settings['ignoredSites'][site] = { + url: site + }; + + browser.runtime.sendMessage({ + action: 'save_settings', + args: [cip.settings] + }); +}; var cipEvents = {}; diff --git a/keepassxc-browser/options/options.html b/keepassxc-browser/options/options.html index 4c1a702..597b2af 100644 --- a/keepassxc-browser/options/options.html +++ b/keepassxc-browser/options/options.html @@ -20,6 +20,7 @@
  • General
  • Connected Databases
  • Specified credential fields
  • +
  • Ignored sites
  • About
  • @@ -288,6 +289,52 @@ + +
    +

    Ignored sites

    +
    +

    + Sites in this list are ignored when new credentials are detected. +
    + Go to the page with new credentials, click the blinking KeePassXC-Browser icon or the notification and select Never ask for this page. +

    + + + + + + + + + + + + + + + + +
    Page URLDelete
    No ignored sites found.
    + +
    +

    About

    diff --git a/keepassxc-browser/options/options.js b/keepassxc-browser/options/options.js index e7db3aa..dc53bcd 100644 --- a/keepassxc-browser/options/options.js +++ b/keepassxc-browser/options/options.js @@ -17,6 +17,7 @@ $(function() { options.initGeneralSettings(); options.initConnectedDatabases(); options.initSpecifiedCredentialFields(); + options.initIgnoredSites(); options.initAbout(); }); }); @@ -173,8 +174,7 @@ options.initConnectedDatabases = function() { if ($('#tab-connected-databases table tbody:first tr').length > 2) { $('#tab-connected-databases table tbody:first tr.empty:first').hide(); - } - else { + } else { $('#tab-connected-databases table tbody:first tr.empty:first').show(); } }); @@ -201,8 +201,7 @@ options.initConnectedDatabases = function() { if ($('#tab-connected-databases table tbody:first tr').length > 2) { $('#tab-connected-databases table tbody:first tr.empty:first').hide(); - } - else { + } else { $('#tab-connected-databases table tbody:first tr.empty:first').show(); } @@ -235,8 +234,7 @@ options.initSpecifiedCredentialFields = function() { if ($('#tab-specified-fields table tbody:first tr').length > 2) { $('#tab-specified-fields table tbody:first tr.empty:first').hide(); - } - else { + } else { $('#tab-specified-fields table tbody:first tr.empty:first').show(); } }); @@ -248,7 +246,7 @@ options.initSpecifiedCredentialFields = function() { const $tr = $trClone.clone(true); $tr.data('url', url); $tr.attr('id', 'tr-scf' + counter); - counter += 1; + ++counter; $tr.children('td:first').text(url); $('#tab-specified-fields table tbody:first').append($tr); @@ -256,12 +254,58 @@ options.initSpecifiedCredentialFields = function() { if ($('#tab-specified-fields table tbody:first tr').length > 2) { $('#tab-specified-fields table tbody:first tr.empty:first').hide(); - } - else { + } else { $('#tab-specified-fields table tbody:first tr.empty:first').show(); } }; +options.initIgnoredSites = function() { + $('#dialogDeleteIgnoredSite').modal({keyboard: true, show: false, backdrop: true}); + $('#tab-ignored-sites tr.clone:first button.delete:first').click(function(e) { + e.preventDefault(); + $('#dialogDeleteIgnoredSite').data('url', $(this).closest('tr').data('url')); + $('#dialogDeleteIgnoredSite').data('tr-id', $(this).closest('tr').attr('id')); + $('#dialogDeleteIgnoredSite .modal-body:first strong:first').text($(this).closest('tr').children('td:first').text()); + $('#dialogDeleteIgnoredSite').modal('show'); + }); + + $('#dialogDeleteIgnoredSite .modal-footer:first button.yes:first').click(function(e) { + $('#dialogDeleteIgnoredSite').modal('hide'); + + const $url = $('#dialogDeleteIgnoredSite').data('url'); + const $trId = $('#dialogDeleteIgnoredSite').data('tr-id'); + $('#tab-ignored-sites #' + $trId).remove(); + + delete options.settings['ignoredSites'][$url]; + options.saveSettings(); + + if ($('#tab-ignored-sites table tbody:first tr').length > 2) { + $('#tab-ignored-sites table tbody:first tr.empty:first').hide(); + } else { + $('#tab-ignored-sites table tbody:first tr.empty:first').show(); + } + }); + + const $trClone = $('#tab-ignored-sites table tr.clone:first').clone(true); + $trClone.removeClass('clone'); + let counter = 1; + for (let url in options.settings['ignoredSites']) { + const $tr = $trClone.clone(true); + $tr.data('url', url); + $tr.attr('id', 'tr-scf' + counter); + ++counter; + + $tr.children('td:first').text(url); + $('#tab-ignored-sites table tbody:first').append($tr); + } + + if ($('#tab-ignored-sites table tbody:first tr').length > 2) { + $('#tab-ignored-sites table tbody:first tr.empty:first').hide(); + } else { + $('#tab-ignored-sites table tbody:first tr.empty:first').show(); + } +}; + options.initAbout = function() { $('#tab-about em.versionCIP').text(browser.runtime.getManifest().version); if (isFirefox()) { diff --git a/keepassxc-browser/popups/popup_remember.html b/keepassxc-browser/popups/popup_remember.html index 86ad865..6d367b4 100644 --- a/keepassxc-browser/popups/popup_remember.html +++ b/keepassxc-browser/popups/popup_remember.html @@ -32,6 +32,7 @@ +

    diff --git a/keepassxc-browser/popups/popup_remember.js b/keepassxc-browser/popups/popup_remember.js index be79328..5c0505a 100644 --- a/keepassxc-browser/popups/popup_remember.js +++ b/keepassxc-browser/popups/popup_remember.js @@ -78,6 +78,21 @@ function _initialize(tab) { e.preventDefault(); _close(); }); + + $('#btn-ignore').click(function(e) { + browser.windows.getCurrent().then((win) => { + browser.tabs.query({ 'active': true, 'currentWindow': true }).then((tabs) => { + const tab = tabs[0]; + browser.runtime.getBackgroundPage().then((global) => { + browser.tabs.sendMessage(tab.id, { + action: 'ignore-site', + args: [_tab.credentials.url] + }); + _close(); + }); + }); + }); + }); } function _connected_database(db) {