From c9d88b9728ade8427e1f53e5ef209aaaecbbca2f Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Wed, 15 Feb 2017 22:27:06 +1100 Subject: [PATCH 01/20] chromeipass: Initial WebExtension support for Firefox --- chromeipass/background/browserAction.js | 8 +-- chromeipass/background/event.js | 9 +-- chromeipass/background/init.js | 36 ++++++------ chromeipass/background/keepass.js | 2 +- chromeipass/background/page.js | 8 +-- chromeipass/chromeipass.js | 76 ++++++++++++------------- chromeipass/options/options.js | 33 +++++------ chromeipass/popups/popup.js | 18 +++--- chromeipass/popups/popup_functions.js | 17 +++--- chromeipass/popups/popup_httpauth.js | 9 +-- chromeipass/popups/popup_login.js | 8 +-- chromeipass/popups/popup_remember.js | 28 ++++----- documentation/chromeIPass.md | 9 ++- 13 files changed, 131 insertions(+), 130 deletions(-) diff --git a/chromeipass/background/browserAction.js b/chromeipass/background/browserAction.js index 7e5508b..4b31d22 100644 --- a/chromeipass/background/browserAction.js +++ b/chromeipass/background/browserAction.js @@ -14,13 +14,13 @@ browserAction.show = function(callback, tab) { data = page.tabs[tab.id].stack[page.tabs[tab.id].stack.length - 1]; } - chrome.browserAction.setIcon({ + browser.browserAction.setIcon({ tabId: tab.id, path: "/icons/19x19/" + browserAction.generateIconName(data.iconType, data.icon) }); if(data.popup) { - chrome.browserAction.setPopup({ + browser.browserAction.setPopup({ tabId: tab.id, popup: "popups/" + data.popup }); @@ -57,7 +57,7 @@ browserAction.update = function(interval) { data.intervalIcon.index = 0; } - chrome.browserAction.setIcon({ + browser.browserAction.setIcon({ tabId: page.currentTabId, path: "/icons/19x19/" + browserAction.generateIconName(null, data.intervalIcon.icons[data.intervalIcon.index]) }); @@ -264,4 +264,4 @@ browserAction.generateIconName = function(iconType, icon) { name += "_19x19.png"; return name; -} \ No newline at end of file +} diff --git a/chromeipass/background/event.js b/chromeipass/background/event.js index 17e591f..7884f55 100644 --- a/chromeipass/background/event.js +++ b/chromeipass/background/event.js @@ -43,12 +43,7 @@ event.invoke = function(handler, callback, senderTabId, args, secondTime) { // remove information from no longer existing tabs page.removePageInformationFromNotExistingTabs(); - chrome.tabs.get(senderTabId, function(tab) { - //chrome.tabs.query({"active": true, "windowId": chrome.windows.WINDOW_ID_CURRENT}, function(tabs) { - //if (tabs.length === 0) - // return; // For example: only the background devtools or a popup are opened - //var tab = tabs[0]; - + browser.tabs.get(senderTabId).then(function(tab) { if(!tab) { return; } @@ -242,4 +237,4 @@ event.messageHandlers = { 'update_available_keepasshttp': event.onUpdateAvailableKeePassHttp, 'generate_password': keepass.generatePassword, 'copy_password': keepass.copyPassword -}; \ No newline at end of file +}; diff --git a/chromeipass/background/init.js b/chromeipass/background/init.js index 8c6e314..a1cf560 100644 --- a/chromeipass/background/init.js +++ b/chromeipass/background/init.js @@ -7,7 +7,7 @@ page.initOpenedTabs(); // initial connection with KeePassHttp keepass.getDatabaseHash(null); // set initial tab-ID -chrome.tabs.query({"active": true, "windowId": chrome.windows.WINDOW_ID_CURRENT}, function(tabs) { +browser.tabs.query({"active": true, "currentWindow": true}).then(function(tabs) { if (tabs.length === 0) return; // For example: only the background devtools or a popup are opened page.currentTabId = tabs[0].id; @@ -21,9 +21,9 @@ var _interval = 250; * functions if tab is created in foreground * @param {object} tab */ -chrome.tabs.onCreated.addListener(function(tab) { +browser.tabs.onCreated.addListener(function(tab) { if(tab.id > 0) { - //console.log("chrome.tabs.onCreated(" + tab.id+ ")"); + //console.log("browser.tabs.onCreated(" + tab.id+ ")"); if(tab.selected) { page.currentTabId = tab.id; event.invoke(page.switchTab, null, tab.id, []); @@ -36,7 +36,7 @@ chrome.tabs.onCreated.addListener(function(tab) { * @param {integer} tabId * @param {object} removeInfo */ -chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) { +browser.tabs.onRemoved.addListener(function(tabId, removeInfo) { delete page.tabs[tabId]; if(page.currentTabId == tabId) { page.currentTabId = -1; @@ -48,12 +48,12 @@ chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) { * Invoke functions to retrieve credentials for focused tab * @param {object} activeInfo */ -chrome.tabs.onActivated.addListener(function(activeInfo) { +browser.tabs.onActivated.addListener(function(activeInfo) { // remove possible credentials from old tab information page.clearCredentials(page.currentTabId, true); browserAction.removeRememberPopup(null, {"id": page.currentTabId}, true); - chrome.tabs.get(activeInfo.tabId, function(info) { + browser.tabs.get(activeInfo.tabId).then(function(info) { //console.log(info.id + ": " + info.url); if(info && info.id) { page.currentTabId = info.id; @@ -70,7 +70,7 @@ chrome.tabs.onActivated.addListener(function(activeInfo) { * @param {integer} tabId * @param {object} changeInfo */ -chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { +browser.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { if(changeInfo.status == "complete") { event.invoke(browserAction.removeRememberPopup, null, tabId, []); } @@ -80,24 +80,26 @@ chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { /** * Retrieve Credentials and try auto-login for HTTPAuth requests */ +/* TODO: Not supported in Firefox/WebExtensions chrome.webRequest.onAuthRequired.addListener(httpAuth.handleRequest, { urls: [""] }, ["asyncBlocking"] ); +*/ /** * Interaction between background-script and front-script */ -chrome.extension.onMessage.addListener(event.onMessage); +browser.runtime.onMessage.addListener(event.onMessage); /** * Add context menu entry for filling in username + password */ -chrome.contextMenus.create({ +browser.contextMenus.create({ "title": "Fill &User + Pass", "contexts": [ "editable" ], "onclick": function(info, tab) { - chrome.tabs.sendMessage(tab.id, { + browser.tabs.sendMessage(tab.id, { action: "fill_user_pass" }); } @@ -106,11 +108,11 @@ chrome.contextMenus.create({ /** * Add context menu entry for filling in only password which matches for given username */ -chrome.contextMenus.create({ +browser.contextMenus.create({ "title": "Fill &Pass Only", "contexts": [ "editable" ], "onclick": function(info, tab) { - chrome.tabs.sendMessage(tab.id, { + browser.tabs.sendMessage(tab.id, { action: "fill_pass_only" }); } @@ -119,11 +121,11 @@ chrome.contextMenus.create({ /** * Add context menu entry for creating icon for generate-password dialog */ -chrome.contextMenus.create({ +browser.contextMenus.create({ "title": "Show Password &Generator Icons", "contexts": [ "editable" ], "onclick": function(info, tab) { - chrome.tabs.sendMessage(tab.id, { + browser.tabs.sendMessage(tab.id, { action: "activate_password_generator" }); } @@ -132,11 +134,11 @@ chrome.contextMenus.create({ /** * Add context menu entry for creating icon for generate-password dialog */ -chrome.contextMenus.create({ +browser.contextMenus.create({ "title": "&Save credentials", "contexts": [ "editable" ], "onclick": function(info, tab) { - chrome.tabs.sendMessage(tab.id, { + browser.tabs.sendMessage(tab.id, { action: "remember_credentials" }); } @@ -148,4 +150,4 @@ chrome.contextMenus.create({ */ window.setInterval(function() { browserAction.update(_interval); -}, _interval); \ No newline at end of file +}, _interval); diff --git a/chromeipass/background/keepass.js b/chromeipass/background/keepass.js index 12cafdf..4fe2950 100644 --- a/chromeipass/background/keepass.js +++ b/chromeipass/background/keepass.js @@ -204,7 +204,7 @@ keepass.generatePassword = function (callback, tab, forceCallback) { } keepass.copyPassword = function(callback, tab, password) { - var bg = chrome.extension.getBackgroundPage(); + var bg = browser.runtime.getBackgroundPage(); var c2c = bg.document.getElementById("copy2clipboard"); if(!c2c) { var input = document.createElement('input'); diff --git a/chromeipass/background/page.js b/chromeipass/background/page.js index ce136bd..24bf516 100644 --- a/chromeipass/background/page.js +++ b/chromeipass/background/page.js @@ -37,7 +37,7 @@ page.initSettings = function() { } page.initOpenedTabs = function() { - chrome.tabs.query({}, function(tabs) { + browser.tabs.query({}).then(function(tabs) { for(var i = 0; i < tabs.length; i++) { page.createTabEntry(tabs[i].id); } @@ -53,7 +53,7 @@ page.isValidProtocol = function(url) { page.switchTab = function(callback, tab) { browserAction.showDefault(null, tab); - chrome.tabs.sendMessage(tab.id, {action: "activated_tab"}); + browser.tabs.sendMessage(tab.id, {action: "activated_tab"}); } page.clearCredentials = function(tabId, complete) { @@ -67,7 +67,7 @@ page.clearCredentials = function(tabId, complete) { if(complete) { page.tabs[tabId].loginList = []; - chrome.tabs.sendMessage(tabId, { + browser.tabs.sendMessage(tabId, { action: "clear_credentials" }); } @@ -85,7 +85,7 @@ page.createTabEntry = function(tabId) { page.removePageInformationFromNotExistingTabs = function() { var rand = Math.floor(Math.random()*1001); if(rand == 28) { - chrome.tabs.query({}, function(tabs) { + browser.tabs.query({}).then(function(tabs) { var $tabIds = {}; var $infoIds = Object.keys(page.tabs); diff --git a/chromeipass/chromeipass.js b/chromeipass/chromeipass.js index ed07d8d..a78dae6 100644 --- a/chromeipass/chromeipass.js +++ b/chromeipass/chromeipass.js @@ -1,7 +1,7 @@ // contains already called method names var _called = {}; -chrome.extension.onMessage.addListener(function(req, sender, callback) { +browser.runtime.onMessage.addListener(function(req, sender, callback) { if ('action' in req) { if(req.action == "fill_user_pass_with_specific_login") { if(cip.credentials[req.id]) { @@ -48,9 +48,9 @@ chrome.extension.onMessage.addListener(function(req, sender, callback) { cipEvents.triggerActivatedTab(); } else if (req.action == "redetect_fields") { - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ "action": "get_settings", - }, function(response) { + }).then(function(response) { cip.settings = response.data; cip.initCredentialFields(true); }); @@ -231,9 +231,9 @@ cipPassword.createDialog = function() { .css("float", "left") .click(function(e) { e.preventDefault(); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: "generate_password" - }, cipPassword.callbackGeneratedPassword); + }).then(cipPassword.callbackGeneratedPassword); }); $divFloat.append($btnGenerate); @@ -246,10 +246,10 @@ cipPassword.createDialog = function() { .click(function(e) { e.preventDefault(); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: "copy_password", args: [cIPJQ("input#cip-genpw-textfield-password").val()] - }, cipPassword.callbackPasswordCopied); + }).then(cipPassword.callbackPasswordCopied); }); $divFloat.append($btnClipboard); @@ -316,10 +316,10 @@ cipPassword.createDialog = function() { } // copy password to clipboard - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: "copy_password", args: [$password] - }, cipPassword.callbackPasswordCopied); + }).then(cipPassword.callbackPasswordCopied); } }); $dialog.append($btnFillIn); @@ -446,9 +446,9 @@ cipPassword.callbackGeneratedPassword = function(entries) { } cipPassword.onRequestPassword = function() { - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ 'action': 'generate_password' - }, cipPassword.callbackGeneratedPassword); + }).then(cipPassword.callbackGeneratedPassword); } cipPassword.checkObservedElements = function() { @@ -632,7 +632,7 @@ cipDefine.initDescription = function() { "fields": fieldIds }; - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'save_settings', args: [cip.settings] }); @@ -658,12 +658,12 @@ cipDefine.initDescription = function() { .click(function(e) { delete cip.settings["defined-credential-fields"][document.location.origin]; - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'save_settings', args: [cip.settings] }); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'load_settings' }); @@ -793,8 +793,7 @@ cipDefine.prepareStep3 = function() { } - -cipFields = {} +var cipFields = {} cipFields.inputQueryPattern = "input[type='text'], input[type='email'], input[type='password'], input[type='tel'], input[type='number'], input:not([type])"; // unique number as new IDs for input fields @@ -1134,9 +1133,10 @@ cIPJQ(function() { }); cip.init = function() { - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ "action": "get_settings", - }, function(response) { + }).then(function(response) { + console.log("got response!"); cip.settings = response.data; cip.initCredentialFields(); }); @@ -1159,7 +1159,7 @@ cip.initCredentialFields = function(forceCall) { cipFields.prepareCombinations(cipFields.combinations); if(cipFields.combinations.length == 0) { - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ 'action': 'show_default_browseraction' }); return; @@ -1169,10 +1169,10 @@ cip.initCredentialFields = function(forceCall) { cip.submitUrl = cip.getFormActionUrl(cipFields.combinations[0]); if(cip.settings.autoRetrieveCredentials) { - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ 'action': 'retrieve_credentials', 'args': [ cip.url, cip.submitUrl ] - }, cip.retrieveCredentialsCallback); + }).then(cip.retrieveCredentialsCallback); } } // end function init @@ -1190,10 +1190,10 @@ cip.initPasswordGenerator = function(inputs) { cip.receiveCredentialsIfNecessary = function () { if(cip.credentials.length == 0) { - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ 'action': 'retrieve_credentials', 'args': [ cip.url, cip.submitUrl ] - }, cip.retrieveCredentialsCallback); + }).then(cip.retrieveCredentialsCallback); } } @@ -1235,7 +1235,7 @@ cip.prepareFieldsForCredentials = function(autoFillInForSingle) { } // generate popup-list of usernames + descriptions - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ 'action': 'popup_login', 'args': [[cip.credentials[0].Login + " (" + cip.credentials[0].Name + ")"]] }); @@ -1263,7 +1263,7 @@ cip.preparePageForMultipleCredentials = function(credentials) { } // generate popup-list of usernames + descriptions - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ 'action': 'popup_login', 'args': [usernames] }); @@ -1331,10 +1331,10 @@ cip.fillInCredentials = function(combination, onlyPassword, suppressWarnings) { cip.url = document.location.origin; cip.submitUrl = action; - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ 'action': 'retrieve_credentials', 'args': [ cip.url, cip.submitUrl, false, true ] - }, function(credentials) { + }).then(function(credentials) { cip.retrieveCredentialsCallback(credentials, true); cip.fillIn(combination, onlyPassword, suppressWarnings); }); @@ -1385,7 +1385,7 @@ cip.fillInFromActiveElementPassOnly = function(suppressWarnings) { if(!_f(combination.password)) { var message = "Unable to find a password field"; - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'alert', args: [message] }); @@ -1453,7 +1453,7 @@ cip.fillIn = function(combination, onlyPassword, suppressWarnings) { // no credentials available if (cip.credentials.length == 0 && !suppressWarnings) { var message = "No logins found."; - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'alert', args: [message] }); @@ -1486,7 +1486,7 @@ cip.fillIn = function(combination, onlyPassword, suppressWarnings) { if(!filledIn) { if(!suppressWarnings) { var message = "Error #101\nCannot find fields to fill in."; - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'alert', args: [message] }); @@ -1516,7 +1516,7 @@ cip.fillIn = function(combination, onlyPassword, suppressWarnings) { if(!filledIn) { if(!suppressWarnings) { var message = "Error #102\nCannot find fields to fill in."; - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'alert', args: [message] }); @@ -1570,7 +1570,7 @@ cip.fillIn = function(combination, onlyPassword, suppressWarnings) { if(!suppressWarnings) { var message = "Error #105\nMore than one login was found in KeePass!\n" + "Press the chromeIPass icon for more options."; - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'alert', args: [message] }); @@ -1579,7 +1579,7 @@ cip.fillIn = function(combination, onlyPassword, suppressWarnings) { else if(countPasswords < 1) { if(!suppressWarnings) { var message = "Error #103\nNo credentials for given username found."; - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'alert', args: [message] }); @@ -1590,7 +1590,7 @@ cip.fillIn = function(combination, onlyPassword, suppressWarnings) { if(!suppressWarnings) { var message = "Error #104\nMore than one login was found in KeePass!\n" + "Press the chromeIPass icon for more options."; - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'alert', args: [message] }); @@ -1683,7 +1683,7 @@ cip.rememberCredentials = function(usernameValue, passwordValue) { } } - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ 'action': 'set_remember_credentials', 'args': [usernameValue, passwordValue, url, usernameExists, credentialsList] }); @@ -1696,7 +1696,7 @@ cip.rememberCredentials = function(usernameValue, passwordValue) { -cipEvents = {}; +var cipEvents = {}; cipEvents.clearCredentials = function() { cip.credentials = []; @@ -1721,9 +1721,9 @@ cipEvents.triggerActivatedTab = function() { // initCredentialFields calls also "retrieve_credentials", to prevent it // check of init() was already called if(_called.initCredentialFields && (cip.url || cip.submitUrl) && cip.settings.autoRetrieveCredentials) { - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ 'action': 'retrieve_credentials', 'args': [ cip.url, cip.submitUrl ] - }, cip.retrieveCredentialsCallback); + }).then(cip.retrieveCredentialsCallback); } } diff --git a/chromeipass/options/options.js b/chromeipass/options/options.js index 136d455..cce53d5 100644 --- a/chromeipass/options/options.js +++ b/chromeipass/options/options.js @@ -36,7 +36,7 @@ options.initGeneralSettings = function() { options.settings[$(this).attr("name")] = $(this).is(':checked'); localStorage.settings = JSON.stringify(options.settings); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'load_settings' }); }); @@ -51,21 +51,21 @@ options.initGeneralSettings = function() { options.settings[$(this).attr("name")] = $(this).val(); localStorage.settings = JSON.stringify(options.settings); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'load_settings' }); }); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: "get_keepasshttp_versions" - }, options.showKeePassHttpVersions); + }).then(options.showKeePassHttpVersions); $("#tab-general-settings button.checkUpdateKeePassHttp:first").click(function(e) { e.preventDefault(); $(this).attr("disabled", true); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: "check_update_keepasshttp" - }, options.showKeePassHttpVersions); + }).then(options.showKeePassHttpVersions); }); $("#showDangerousSettings").click(function() { @@ -94,7 +94,7 @@ options.initGeneralSettings = function() { localStorage.settings = JSON.stringify(options.settings); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'load_settings' }); }); @@ -113,7 +113,7 @@ options.initGeneralSettings = function() { localStorage.settings = JSON.stringify(options.settings); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'load_settings' }); }); @@ -128,7 +128,7 @@ options.initGeneralSettings = function() { localStorage.settings = JSON.stringify(options.settings); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'load_settings' }); }); @@ -143,7 +143,7 @@ options.initGeneralSettings = function() { localStorage.settings = JSON.stringify(options.settings); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'load_settings' }); }); @@ -158,7 +158,7 @@ options.initGeneralSettings = function() { localStorage.settings = JSON.stringify(options.settings); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'load_settings' }); }); @@ -197,7 +197,7 @@ options.initConnectedDatabases = function() { delete options.keyRing[$hash]; localStorage.keyRing = JSON.stringify(options.keyRing); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'load_keyring' }); @@ -220,7 +220,7 @@ options.initConnectedDatabases = function() { options.keyRing[$hash].icon = $icon; localStorage.keyRing = JSON.stringify(options.keyRing); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'load_keyring' }); }); @@ -250,7 +250,7 @@ options.initConnectedDatabases = function() { $("#tab-connected-databases table tbody:first tr.empty:first").show(); } $("#connect-button").click(function() { - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: "associate" }); }); @@ -276,7 +276,7 @@ options.initSpecifiedCredentialFields = function() { delete options.settings["defined-credential-fields"][$url]; localStorage.settings = JSON.stringify(options.settings); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'load_settings' }); @@ -310,5 +310,6 @@ options.initSpecifiedCredentialFields = function() { } options.initAbout = function() { - $("#tab-about em.versionCIP").text(chrome.app.getDetails().version); + var manifest = browser.runtime.getManifest(); + $("#tab-about em.versionCIP").text(manifest.version); } diff --git a/chromeipass/popups/popup.js b/chromeipass/popups/popup.js index e33fbb6..a04900f 100644 --- a/chromeipass/popups/popup.js +++ b/chromeipass/popups/popup.js @@ -36,38 +36,38 @@ function status_response(r) { $(function() { $("#connect-button").click(function() { - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: "associate" }); close(); }); $("#reconnect-button").click(function() { - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: "associate" }); close(); }); $("#reload-status-button").click(function() { - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: "get_status" - }, status_response); + }).then(status_response); }); $("#redetect-fields-button").click(function() { - chrome.tabs.query({"active": true, "windowId": chrome.windows.WINDOW_ID_CURRENT}, function(tabs) { + browser.tabs.query({"active": true, "currentWindow": true}).then(function(tabs) { if (tabs.length === 0) return; // For example: only the background devtools or a popup are opened var tab = tabs[0]; - chrome.tabs.sendMessage(tab.id, { + browser.tabs.sendMessage(tab.id, { action: "redetect_fields" }); }); }); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: "get_status" - }, status_response); -}); \ No newline at end of file + }).then(status_response); +}); diff --git a/chromeipass/popups/popup_functions.js b/chromeipass/popups/popup_functions.js index 48e94da..ef1fd59 100644 --- a/chromeipass/popups/popup_functions.js +++ b/chromeipass/popups/popup_functions.js @@ -1,6 +1,6 @@ var $ = cIPJQ.noConflict(true); var _settings = typeof(localStorage.settings)=='undefined' ? {} : JSON.parse(localStorage.settings); -//var global = chrome.extension.getBackgroundPage(); +//var global = browser.runtime.getBackgroundPage(); function updateAvailableResponse(available) { if(available) { @@ -13,15 +13,14 @@ function updateAvailableResponse(available) { function initSettings() { $("#settings #btn-options").click(function() { - close(); - chrome.tabs.create({ - url: "../options/options.html" - }) + browser.tabs.create({ + url: "/options/options.html" + }).then(close); }); $("#settings #btn-choose-credential-fields").click(function() { - var global = chrome.extension.getBackgroundPage(); - chrome.tabs.sendMessage(global.page.currentTabId, { + var global = browser.runtime.getBackgroundPage(); + browser.tabs.sendMessage(global.page.currentTabId, { action: "choose_credential_fields" }); close(); @@ -32,7 +31,7 @@ function initSettings() { $(function() { initSettings(); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: "update_available_keepasshttp" - }, updateAvailableResponse); + }).then(updateAvailableResponse); }); diff --git a/chromeipass/popups/popup_httpauth.js b/chromeipass/popups/popup_httpauth.js index 49494ac..85a367e 100644 --- a/chromeipass/popups/popup_httpauth.js +++ b/chromeipass/popups/popup_httpauth.js @@ -1,8 +1,9 @@ $(function() { - var global = chrome.extension.getBackgroundPage(); + var global = browser.runtime.getBackgroundPage(); - chrome.tabs.getSelected(null, function(tab) { + browser.tabs.query({"active": true, "currentWindow": true}).then(function(tabs) { //var data = global.tab_httpauth_list["tab" + tab.id]; + var tab = tabs[0]; var data = global.page.tabs[tab.id].loginList; var ul = document.getElementById("login-list"); for (var i = 0; i < data.logins.length; i++) { @@ -12,10 +13,10 @@ $(function() { li.appendChild(a); $(a).data("url", data.url.replace(/:\/\//g, "://" + data.logins[i].Login + ":" + data.logins[i].Password + "@")); $(a).click(function() { - chrome.tabs.update(tab.id, {"url": $(this).data("url")}); + browser.tabs.update(tab.id, {"url": $(this).data("url")}); close(); }); ul.appendChild(li); } }); -}); \ No newline at end of file +}); diff --git a/chromeipass/popups/popup_login.js b/chromeipass/popups/popup_login.js index e84100d..a381122 100644 --- a/chromeipass/popups/popup_login.js +++ b/chromeipass/popups/popup_login.js @@ -1,7 +1,7 @@ $(function() { - var global = chrome.extension.getBackgroundPage(); + var global = browser.runtime.getBackgroundPage(); - chrome.tabs.query({"active": true, "windowId": chrome.windows.WINDOW_ID_CURRENT}, function(tabs) { + browser.tabs.query({"active": true, "currentWindow": true}).then(function(tabs) { if (tabs.length === 0) return; // For example: only the background devtools or a popup are opened var tab = tabs[0]; @@ -16,7 +16,7 @@ $(function() { a.setAttribute("id", "" + i); a.addEventListener('click', function(e) { var id = e.target.id; - chrome.tabs.sendMessage(tab.id, { + browser.tabs.sendMessage(tab.id, { action: 'fill_user_pass_with_specific_login', id: id }); @@ -25,4 +25,4 @@ $(function() { ul.appendChild(li); } }); -}); \ No newline at end of file +}); diff --git a/chromeipass/popups/popup_remember.js b/chromeipass/popups/popup_remember.js index b0380ab..4c7c114 100644 --- a/chromeipass/popups/popup_remember.js +++ b/chromeipass/popups/popup_remember.js @@ -20,10 +20,10 @@ function _initialize(tab) { $(".information-username:first span:first").text(_tab.credentials.username); $("#btn-new").click(function(e) { - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'add_credentials', args: [_tab.credentials.username, _tab.credentials.password, _tab.credentials.url] - }, _verifyResult); + }).then(_verifyResult); }); $("#btn-update").click(function(e) { @@ -31,10 +31,10 @@ function _initialize(tab) { // only one entry which could be updated if(_tab.credentials.list.length == 1) { - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'update_credentials', args: [_tab.credentials.list[0].Uuid, _tab.credentials.username, _tab.credentials.password, _tab.credentials.url] - }, _verifyResult); + }).then(_verifyResult); } else { $(".credentials:first .username-new:first strong:first").text(_tab.credentials.username); @@ -56,10 +56,10 @@ function _initialize(tab) { .data("entryId", i) .click(function(e) { e.preventDefault(); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'update_credentials', args: [_tab.credentials.list[$(this).data("entryId")].Uuid, _tab.credentials.username, _tab.credentials.password, _tab.credentials.url] - }, _verifyResult); + }).then(_verifyResult); }); if(_tab.credentials.usernameExists && _tab.credentials.username == _tab.credentials.list[i].Login) { @@ -97,11 +97,11 @@ function _verifyResult(code) { } function _close() { - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'remove_credentials_from_tab_information' }); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'pop_stack' }); @@ -109,16 +109,16 @@ function _close() { } $(function() { - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'stack_add', args: ["icon_remember_red_background_19x19.png", "popup_remember.html", 10, true, 0] }); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'get_tab_information' - }, _initialize); + }).then(_initialize); - chrome.extension.sendMessage({ + browser.runtime.sendMessage({ action: 'get_connected_database' - }, _connected_database); -}); \ No newline at end of file + }).then(_connected_database); +}); diff --git a/documentation/chromeIPass.md b/documentation/chromeIPass.md index 3333741..caca680 100644 --- a/documentation/chromeIPass.md +++ b/documentation/chromeIPass.md @@ -1,7 +1,9 @@ # chromeIPass -is an extension for the browser Google Chrome to send and receive credentials from KeePass(XC). -
It can be downloaded from [Chrome Web Store](https://chrome.google.com/webstore/detail/chromeipass/ompiailgknfdndiefoaoiligalphfdae). +Is a WebExtension for browsers to send and receive credentials from KeePass(XC). + +* For Google Chrome, it can be downloaded from [Chrome Web Store](https://chrome.google.com/webstore/detail/chromeipass/ompiailgknfdndiefoaoiligalphfdae). +* For Firefox, Work In Progress... Please read at least the section [Important information](#6-important-information). @@ -73,7 +75,8 @@ It is recommended to disable the built-in Chrome password management when using ### 2.2 Installation 1. Your database in KeePass has to be unlocked. -2. Go to the [Chrome Web Store](https://chrome.google.com/webstore/detail/chromeipass/ompiailgknfdndiefoaoiligalphfdae) and install the extension chromeIPass. +2. Install the extension. + - For Chrome, the ChromeIPass extension is available in the [Chrome Web Store](https://chrome.google.com/webstore/detail/chromeipass/ompiailgknfdndiefoaoiligalphfdae). 3. Now there is a new browser icon available:
![browser-icon](https://raw.github.com/pfn/passifox/master/documentation/images/cip-browser-icon.png) From 91eabf1be8119306247d320a02111e1e30068e14 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Thu, 16 Feb 2017 21:52:55 +1100 Subject: [PATCH 02/20] chromeipass: Add browser-polyfill for Chrome compatibility (part tested) browser-poyfill.min.js comes from https://github.com/mozilla/webextension-polyfill master branch 77af627d0 with following two pull requests cherry-picked on top: https://github.com/mozilla/webextension-polyfill/pull/11 https://github.com/mozilla/webextension-polyfill/pull/22 --- chromeipass/browser-polyfill.min.js | 9 +++++++++ chromeipass/manifest.json | 11 +++++++++-- chromeipass/options/options.html | 1 + chromeipass/popups/popup.html | 1 + chromeipass/popups/popup_login.html | 1 + chromeipass/popups/popup_multiple-fields.html | 1 + chromeipass/popups/popup_remember.html | 1 + 7 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 chromeipass/browser-polyfill.min.js diff --git a/chromeipass/browser-polyfill.min.js b/chromeipass/browser-polyfill.min.js new file mode 100644 index 0000000..47125a6 --- /dev/null +++ b/chromeipass/browser-polyfill.min.js @@ -0,0 +1,9 @@ +"use strict";if("undefined"==typeof browser){this.browser=(()=>{class c extends WeakMap{constructor(m,n=void 0){super(n),this.createItem=m}get(m){return this.has(m)||this.set(m,this.createItem(m)),super.get(m)}}const d=m=>{return m&&"object"==typeof m&&"function"==typeof m.then},e=m=>{return(...n)=>{chrome.runtime.lastError?m.reject(chrome.runtime.lastError):1===n.length?m.resolve(n[0]):m.resolve(n)}},f=(m,n)=>{const o=p=>1==p?"argument":"arguments";return function(q,...r){if(r.lengthn.maxArgs)throw new Error(`Expected at most ${n.maxArgs} ${o(n.maxArgs)} for ${m}(), got ${r.length}`);return new Promise((s,t)=>{q[m](...r,e({resolve:s,reject:t}))})}},g=(m,n,o)=>{return new Proxy(n,{apply(p,q,r){return o.call(q,m,...r)}})};let h=Function.call.bind(Object.prototype.hasOwnProperty);const i=(m,n={},o={})=>{let p=Object.create(null),q={has(r,s){return s in r||s in p},get(r,s){if(s in p)return p[s];if(s in r){let u=r[s];if("function"==typeof u){if("function"==typeof n[s])u=g(r,r[s],n[s]);else if(h(o,s)){let v=f(s,o[s]);u=g(r,r[s],v)}else u=u.bind(r);}else if("object"==typeof u&&null!==u&&(h(n,s)||h(o,s)))u=i(u,n[s],o[s]);else return Object.defineProperty(p,s,{configurable:!0,enumerable:!0,get(){return r[s]},set(v){r[s]=v}}),u;return p[s]=u,u}},set(r,s,t){return s in p?p[s]=t:r[s]=t,!0},defineProperty(r,s,t){return Reflect.defineProperty(p,s,t)},deleteProperty(r,s){return Reflect.deleteProperty(p,s)}};return new Proxy(m,q)},k=new c(m=>{return"function"==typeof m?function(o,p,q){let r=!1,s=m(o,p,function(t){r=!0,q(t)});return r||!0===s?s:d(s)?(s.then(q,t=>{console.error(t),q(t)}),!0):void(void 0!==s&&q(s))}:m}),l={runtime:{onMessage:(m=>({addListener(n,o,...p){n.addListener(m.get(o),...p)},hasListener(n,o){return n.hasListener(m.get(o))},removeListener(n,o){n.removeListener(m.get(o))}}))(k)}};return i(chrome,l,{alarms:{clear:{minArgs:0,maxArgs:1},clearAll:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getAll:{minArgs:0,maxArgs:0}},bookmarks:{create:{minArgs:1,maxArgs:1},"export":{minArgs:0,maxArgs:0},get:{minArgs:1,maxArgs:1},getChildren:{minArgs:1,maxArgs:1},getRecent:{minArgs:1,maxArgs:1},getTree:{minArgs:0,maxArgs:0},getSubTree:{minArgs:1,maxArgs:1},"import":{minArgs:0,maxArgs:0},move:{minArgs:2,maxArgs:2},remove:{minArgs:1,maxArgs:1},removeTree:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1},update:{minArgs:2,maxArgs:2}},browserAction:{getBadgeBackgroundColor:{minArgs:1,maxArgs:1},getBadgeText:{minArgs:1,maxArgs:1},getPopup:{minArgs:1,maxArgs:1},getTitle:{minArgs:1,maxArgs:1},setIcon:{minArgs:1,maxArgs:1}},commands:{getAll:{minArgs:0,maxArgs:0}},contextMenus:{update:{minArgs:2,maxArgs:2},remove:{minArgs:1,maxArgs:1},removeAll:{minArgs:0,maxArgs:0}},cookies:{get:{minArgs:1,maxArgs:1},getAll:{minArgs:1,maxArgs:1},getAllCookieStores:{minArgs:0,maxArgs:0},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}},downloads:{download:{minArgs:1,maxArgs:1},cancel:{minArgs:1,maxArgs:1},erase:{minArgs:1,maxArgs:1},getFileIcon:{minArgs:1,maxArgs:2},open:{minArgs:1,maxArgs:1},pause:{minArgs:1,maxArgs:1},removeFile:{minArgs:1,maxArgs:1},resume:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1},show:{minArgs:1,maxArgs:1}},extension:{isAllowedFileSchemeAccess:{minArgs:0,maxArgs:0},isAllowedIncognitoAccess:{minArgs:0,maxArgs:0}},history:{addUrl:{minArgs:1,maxArgs:1},getVisits:{minArgs:1,maxArgs:1},deleteAll:{minArgs:0,maxArgs:0},deleteRange:{minArgs:1,maxArgs:1},deleteUrl:{minArgs:1,maxArgs:1},search:{minArgs:1,maxArgs:1}},i18n:{detectLanguage:{minArgs:1,maxArgs:1},getAcceptLanguages:{minArgs:0,maxArgs:0}},idle:{queryState:{minArgs:1,maxArgs:1}},management:{get:{minArgs:1,maxArgs:1},getAll:{minArgs:0,maxArgs:0},getSelf:{minArgs:0,maxArgs:0},uninstallSelf:{minArgs:0,maxArgs:1}},notifications:{clear:{minArgs:1,maxArgs:1},create:{minArgs:1,maxArgs:2},getAll:{minArgs:0,maxArgs:0},getPermissionLevel:{minArgs:0,maxArgs:0},update:{minArgs:2,maxArgs:2}},pageAction:{getPopup:{minArgs:1,maxArgs:1},getTitle:{minArgs:1,maxArgs:1},hide:{minArgs:0,maxArgs:0},setIcon:{minArgs:1,maxArgs:1},show:{minArgs:0,maxArgs:0}},runtime:{getBackgroundPage:{minArgs:0,maxArgs:0},getBrowserInfo:{minArgs:0,maxArgs:0},getPlatformInfo:{minArgs:0,maxArgs:0},openOptionsPage:{minArgs:0,maxArgs:0},requestUpdateCheck:{minArgs:0,maxArgs:0},sendMessage:{minArgs:1,maxArgs:3},sendNativeMessage:{minArgs:2,maxArgs:2},setUninstallURL:{minArgs:1,maxArgs:1}},storage:{local:{clear:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}},managed:{get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1}},sync:{clear:{minArgs:0,maxArgs:0},get:{minArgs:0,maxArgs:1},getBytesInUse:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},set:{minArgs:1,maxArgs:1}}},tabs:{create:{minArgs:1,maxArgs:1},captureVisibleTab:{minArgs:0,maxArgs:2},detectLanguage:{minArgs:0,maxArgs:1},duplicate:{minArgs:1,maxArgs:1},executeScript:{minArgs:1,maxArgs:2},get:{minArgs:1,maxArgs:1},getCurrent:{minArgs:0,maxArgs:0},getZoom:{minArgs:0,maxArgs:1},getZoomSettings:{minArgs:0,maxArgs:1},highlight:{minArgs:1,maxArgs:1},insertCSS:{minArgs:1,maxArgs:2},move:{minArgs:2,maxArgs:2},reload:{minArgs:0,maxArgs:2},remove:{minArgs:1,maxArgs:1},query:{minArgs:1,maxArgs:1},removeCSS:{minArgs:1,maxArgs:2},sendMessage:{minArgs:2,maxArgs:3},setZoom:{minArgs:1,maxArgs:2},setZoomSettings:{minArgs:1,maxArgs:2},update:{minArgs:1,maxArgs:2}},webNavigation:{getAllFrames:{minArgs:1,maxArgs:1},getFrame:{minArgs:1,maxArgs:1}},webRequest:{handlerBehaviorChanged:{minArgs:0,maxArgs:0}},windows:{create:{minArgs:0,maxArgs:1},get:{minArgs:1,maxArgs:2},getAll:{minArgs:0,maxArgs:1},getCurrent:{minArgs:0,maxArgs:1},getLastFocused:{minArgs:0,maxArgs:1},remove:{minArgs:1,maxArgs:1},update:{minArgs:2,maxArgs:2}}})})()} +//# sourceMappingURL=browser-polyfill.min.js.map + + +// webextension-polyfill v.0.1.0 (https://github.com/mozilla/webextension-polyfill) + +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ \ No newline at end of file diff --git a/chromeipass/manifest.json b/chromeipass/manifest.json index 57a7d5e..3cdbe38 100644 --- a/chromeipass/manifest.json +++ b/chromeipass/manifest.json @@ -21,6 +21,7 @@ "options_page": "options/options.html", "background": { "scripts": [ + "browser-polyfill.min.js", "background/aes.js", "background/cryptoHelpers.js", "background/utf8.js", @@ -35,8 +36,14 @@ "content_scripts": [ { "matches": ["http://*/*", "https://*/*"], - "js": ["jquery-1.11.1.min.js", "jquery-ui-1.10.2.custom.min.js", "chromeipass.js"], - "css": ["jquery-ui-1.10.2.custom.min.css", "bootstrap-btn.css", "chromeipass.css"], + "js": ["browser-polyfill.min.js", + "jquery-1.11.1.min.js", + "jquery-ui-1.10.2.custom.min.js", + "chromeipass.js" + ], + "css": ["jquery-ui-1.10.2.custom.min.css", + "bootstrap-btn.css", + "chromeipass.css"], "run_at": "document_idle", "all_frames": true } diff --git a/chromeipass/options/options.html b/chromeipass/options/options.html index 72ef470..b93ba38 100644 --- a/chromeipass/options/options.html +++ b/chromeipass/options/options.html @@ -6,6 +6,7 @@ + diff --git a/chromeipass/popups/popup.html b/chromeipass/popups/popup.html index c218f59..8927a00 100644 --- a/chromeipass/popups/popup.html +++ b/chromeipass/popups/popup.html @@ -3,6 +3,7 @@ KeePass - Popup + diff --git a/chromeipass/popups/popup_login.html b/chromeipass/popups/popup_login.html index ff25dfa..a50e297 100644 --- a/chromeipass/popups/popup_login.html +++ b/chromeipass/popups/popup_login.html @@ -3,6 +3,7 @@ KeePass - Popup + diff --git a/chromeipass/popups/popup_multiple-fields.html b/chromeipass/popups/popup_multiple-fields.html index 731b226..2604ca7 100644 --- a/chromeipass/popups/popup_multiple-fields.html +++ b/chromeipass/popups/popup_multiple-fields.html @@ -3,6 +3,7 @@ KeePass - Popup + diff --git a/chromeipass/popups/popup_remember.html b/chromeipass/popups/popup_remember.html index 142c604..7088512 100644 --- a/chromeipass/popups/popup_remember.html +++ b/chromeipass/popups/popup_remember.html @@ -3,6 +3,7 @@ KeePass - Popup + From b316d6ef99388c6ea48bf2bac07ded2e36483ff9 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Sun, 19 Feb 2017 14:40:10 +1100 Subject: [PATCH 03/20] chromeipass: Fix usage of webextension getBackgroundPage (returns promise) --- chromeipass/background/keepass.js | 31 +++++++++--------- chromeipass/chromeipass.js | 1 - chromeipass/popups/popup_functions.js | 10 +++--- chromeipass/popups/popup_httpauth.js | 38 +++++++++++----------- chromeipass/popups/popup_login.js | 46 +++++++++++++-------------- 5 files changed, 63 insertions(+), 63 deletions(-) diff --git a/chromeipass/background/keepass.js b/chromeipass/background/keepass.js index 4fe2950..962120e 100644 --- a/chromeipass/background/keepass.js +++ b/chromeipass/background/keepass.js @@ -204,21 +204,22 @@ keepass.generatePassword = function (callback, tab, forceCallback) { } keepass.copyPassword = function(callback, tab, password) { - var bg = browser.runtime.getBackgroundPage(); - var c2c = bg.document.getElementById("copy2clipboard"); - if(!c2c) { - var input = document.createElement('input'); - input.type = "text"; - input.id = "copy2clipboard"; - bg.document.getElementsByTagName('body')[0].appendChild(input); - c2c = bg.document.getElementById("copy2clipboard"); - } - - c2c.value = password; - c2c.select(); - document.execCommand("copy"); - c2c.value = ""; - callback(true); + browser.runtime.getBackgroundPage().then(function (bg) { + var c2c = bg.document.getElementById("copy2clipboard"); + if(!c2c) { + var input = document.createElement('input'); + input.type = "text"; + input.id = "copy2clipboard"; + bg.document.getElementsByTagName('body')[0].appendChild(input); + c2c = bg.document.getElementById("copy2clipboard"); + } + + c2c.value = password; + c2c.select(); + document.execCommand("copy"); + c2c.value = ""; + callback(true); + }); } keepass.associate = function(callback, tab) { diff --git a/chromeipass/chromeipass.js b/chromeipass/chromeipass.js index a78dae6..5185375 100644 --- a/chromeipass/chromeipass.js +++ b/chromeipass/chromeipass.js @@ -1136,7 +1136,6 @@ cip.init = function() { browser.runtime.sendMessage({ "action": "get_settings", }).then(function(response) { - console.log("got response!"); cip.settings = response.data; cip.initCredentialFields(); }); diff --git a/chromeipass/popups/popup_functions.js b/chromeipass/popups/popup_functions.js index ef1fd59..bab7241 100644 --- a/chromeipass/popups/popup_functions.js +++ b/chromeipass/popups/popup_functions.js @@ -1,6 +1,5 @@ var $ = cIPJQ.noConflict(true); var _settings = typeof(localStorage.settings)=='undefined' ? {} : JSON.parse(localStorage.settings); -//var global = browser.runtime.getBackgroundPage(); function updateAvailableResponse(available) { if(available) { @@ -19,11 +18,12 @@ function initSettings() { }); $("#settings #btn-choose-credential-fields").click(function() { - var global = browser.runtime.getBackgroundPage(); - browser.tabs.sendMessage(global.page.currentTabId, { - action: "choose_credential_fields" + browser.runtime.getBackgroundPage().then(function(global) { + browser.tabs.sendMessage(global.page.currentTabId, { + action: "choose_credential_fields" + }); + close(); }); - close(); }); } diff --git a/chromeipass/popups/popup_httpauth.js b/chromeipass/popups/popup_httpauth.js index 85a367e..873467c 100644 --- a/chromeipass/popups/popup_httpauth.js +++ b/chromeipass/popups/popup_httpauth.js @@ -1,22 +1,22 @@ $(function() { - var global = browser.runtime.getBackgroundPage(); - - browser.tabs.query({"active": true, "currentWindow": true}).then(function(tabs) { - //var data = global.tab_httpauth_list["tab" + tab.id]; - var tab = tabs[0]; - var data = global.page.tabs[tab.id].loginList; - var ul = document.getElementById("login-list"); - for (var i = 0; i < data.logins.length; i++) { - var li = document.createElement("li"); - var a = document.createElement("a"); - a.textContent = data.logins[i].Login + " (" + data.logins[i].Name + ")"; - li.appendChild(a); - $(a).data("url", data.url.replace(/:\/\//g, "://" + data.logins[i].Login + ":" + data.logins[i].Password + "@")); - $(a).click(function() { - browser.tabs.update(tab.id, {"url": $(this).data("url")}); - close(); - }); - ul.appendChild(li); - } + browser.runtime.getBackgroundPage().then(function(global) { + browser.tabs.query({"active": true, "currentWindow": true}).then(function(tabs) { + //var data = global.tab_httpauth_list["tab" + tab.id]; + var tab = tabs[0]; + var data = global.page.tabs[tab.id].loginList; + var ul = document.getElementById("login-list"); + for (var i = 0; i < data.logins.length; i++) { + var li = document.createElement("li"); + var a = document.createElement("a"); + a.textContent = data.logins[i].Login + " (" + data.logins[i].Name + ")"; + li.appendChild(a); + $(a).data("url", data.url.replace(/:\/\//g, "://" + data.logins[i].Login + ":" + data.logins[i].Password + "@")); + $(a).click(function() { + browser.tabs.update(tab.id, {"url": $(this).data("url")}); + close(); + }); + ul.appendChild(li); + } + }); }); }); diff --git a/chromeipass/popups/popup_login.js b/chromeipass/popups/popup_login.js index a381122..8f169ab 100644 --- a/chromeipass/popups/popup_login.js +++ b/chromeipass/popups/popup_login.js @@ -1,28 +1,28 @@ $(function() { - var global = browser.runtime.getBackgroundPage(); + browser.runtime.getBackgroundPage().then(function(global) { + browser.tabs.query({"active": true, "currentWindow": true}).then(function(tabs) { + if (tabs.length === 0) + return; // For example: only the background devtools or a popup are opened + var tab = tabs[0]; - browser.tabs.query({"active": true, "currentWindow": true}).then(function(tabs) { - if (tabs.length === 0) - return; // For example: only the background devtools or a popup are opened - var tab = tabs[0]; - - var logins = global.page.tabs[tab.id].loginList; - var ul = document.getElementById("login-list"); - for (var i = 0; i < logins.length; i++) { - var li = document.createElement("li"); - var a = document.createElement("a"); - a.textContent = logins[i]; - li.appendChild(a); - a.setAttribute("id", "" + i); - a.addEventListener('click', function(e) { - var id = e.target.id; - browser.tabs.sendMessage(tab.id, { - action: 'fill_user_pass_with_specific_login', - id: id + var logins = global.page.tabs[tab.id].loginList; + var ul = document.getElementById("login-list"); + for (var i = 0; i < logins.length; i++) { + var li = document.createElement("li"); + var a = document.createElement("a"); + a.textContent = logins[i]; + li.appendChild(a); + a.setAttribute("id", "" + i); + a.addEventListener('click', function(e) { + var id = e.target.id; + browser.tabs.sendMessage(tab.id, { + action: 'fill_user_pass_with_specific_login', + id: id + }); + close(); }); - close(); - }); - ul.appendChild(li); - } + ul.appendChild(li); + } + }); }); }); From 863e846664328c4052722078709dbb4191b54693 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Sun, 19 Feb 2017 14:56:13 +1100 Subject: [PATCH 04/20] chromeipass: Display "Generate Password" key icons on Firefox chrome-extension:// doesn't seem to have a static equivalent, so find at runtime using .getURL() and build a style tag. Bit ickier. :/ --- chromeipass/chromeipass.css | 4 +--- chromeipass/chromeipass.js | 12 ++++++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/chromeipass/chromeipass.css b/chromeipass/chromeipass.css index 17cc2b6..91a9f66 100644 --- a/chromeipass/chromeipass.css +++ b/chromeipass/chromeipass.css @@ -45,12 +45,10 @@ .cip-genpw-icon.cip-icon-key-small { width: 16px; height: 16px; - background-image: url(chrome-extension://__MSG_@@extension_id__/icons/key_16x16.png); } .cip-genpw-icon.cip-icon-key-big { width: 24px; height: 24px; - background-image: url(chrome-extension://__MSG_@@extension_id__/icons/key_24x24.png); } .cip-genpw-password-frame { margin-top: 5px !important; @@ -169,4 +167,4 @@ border: 2px solid deepskyblue; color: #efefef; background-color:rgba(30,144,255,0.4); -} \ No newline at end of file +} diff --git a/chromeipass/chromeipass.js b/chromeipass/chromeipass.js index 5185375..efc0be7 100644 --- a/chromeipass/chromeipass.js +++ b/chromeipass/chromeipass.js @@ -181,6 +181,18 @@ cipPassword.init = function() { window.setInterval(function() { cipPassword.checkObservedElements(); }, 400); + + /* Append extension-local background-image URLs to + 'generate password' icon CSS classes */ + var make_keyicon_css = function(nested_class, icon_size) { + return ".cip-genpw-icon." + nested_class + " {" + + "background-image: url(" + + browser.runtime.getURL("/icons/key_"+icon_size+".png") + + "); }\n"; + } + var styleStr = make_keyicon_css("cip-icon-key-small", "16x16") + + make_keyicon_css("cip-icon-key-big", "24x24"); + cIPJQ('').appendTo('head'); } cipPassword.initField = function(field, inputs, pos) { From 955a06314ff53d47b2ee8c6e577132979c3c7398 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Sun, 19 Feb 2017 15:11:33 +1100 Subject: [PATCH 05/20] chromeipass: Move clipboard copy operation to foreground tab (FF compat) Firefox doesn't allow clipboard copy on the background tab. Verified still working in Chromium. --- chromeipass/background/event.js | 1 - chromeipass/background/keepass.js | 19 ------------------- chromeipass/chromeipass.js | 26 ++++++++++++-------------- 3 files changed, 12 insertions(+), 34 deletions(-) diff --git a/chromeipass/background/event.js b/chromeipass/background/event.js index 7884f55..bd45752 100644 --- a/chromeipass/background/event.js +++ b/chromeipass/background/event.js @@ -236,5 +236,4 @@ event.messageHandlers = { 'stack_add': browserAction.stackAdd, 'update_available_keepasshttp': event.onUpdateAvailableKeePassHttp, 'generate_password': keepass.generatePassword, - 'copy_password': keepass.copyPassword }; diff --git a/chromeipass/background/keepass.js b/chromeipass/background/keepass.js index 962120e..b1aa4b7 100644 --- a/chromeipass/background/keepass.js +++ b/chromeipass/background/keepass.js @@ -203,25 +203,6 @@ keepass.generatePassword = function (callback, tab, forceCallback) { callback(passwords); } -keepass.copyPassword = function(callback, tab, password) { - browser.runtime.getBackgroundPage().then(function (bg) { - var c2c = bg.document.getElementById("copy2clipboard"); - if(!c2c) { - var input = document.createElement('input'); - input.type = "text"; - input.id = "copy2clipboard"; - bg.document.getElementsByTagName('body')[0].appendChild(input); - c2c = bg.document.getElementById("copy2clipboard"); - } - - c2c.value = password; - c2c.select(); - document.execCommand("copy"); - c2c.value = ""; - callback(true); - }); -} - keepass.associate = function(callback, tab) { if(keepass.isAssociated()) { return; diff --git a/chromeipass/chromeipass.js b/chromeipass/chromeipass.js index efc0be7..f719447 100644 --- a/chromeipass/chromeipass.js +++ b/chromeipass/chromeipass.js @@ -255,14 +255,8 @@ cipPassword.createDialog = function() { .addClass("b2c-btn") .addClass("b2c-btn-small") .css("float", "right") - .click(function(e) { - e.preventDefault(); + .click(cipPassword.copyPasswordToClipboard); - browser.runtime.sendMessage({ - action: "copy_password", - args: [cIPJQ("input#cip-genpw-textfield-password").val()] - }).then(cipPassword.callbackPasswordCopied); - }); $divFloat.append($btnClipboard); $dialog.append($divFloat); @@ -327,11 +321,7 @@ cipPassword.createDialog = function() { } } - // copy password to clipboard - browser.runtime.sendMessage({ - action: "copy_password", - args: [$password] - }).then(cipPassword.callbackPasswordCopied); + cipPassword.copyPasswordToClipboard(); } }); $dialog.append($btnFillIn); @@ -427,10 +417,18 @@ cipPassword.setIconPosition = function($icon, $field) { .css("left", $field.offset().left + $field.outerWidth() - $icon.data("size") - $icon.data("offset")) } -cipPassword.callbackPasswordCopied = function(bool) { - if(bool) { +cipPassword.copyPasswordToClipboard = function(e) { + if (e) { + e.preventDefault(); + } + + var input = cIPJQ("input#cip-genpw-textfield-password"); + input.select() + var success = document.execCommand("copy"); + if(success) { cIPJQ("#cip-genpw-btn-clipboard").addClass("b2c-btn-success"); } + cIPJQ("#cip-genpw-dialog").select(); } cipPassword.callbackGeneratedPassword = function(entries) { From 8a897b36a12b36472d59df3f3a29c6523ceeca21 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Sun, 19 Feb 2017 15:39:53 +1100 Subject: [PATCH 06/20] chromeipass: Re-enable onAuthRequested (HTTP Auth) for Chrome, hide on Firefox Uses the cross-browser webextensions API for onAuthRequested, so it may also work in Opera or Edge(?), and could start working some day in Firefox if Mozilla adds support. --- chromeipass/background/init.js | 12 +++++++----- chromeipass/options/options.html | 2 +- chromeipass/options/options.js | 7 +++++++ 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/chromeipass/background/init.js b/chromeipass/background/init.js index a1cf560..727c2f5 100644 --- a/chromeipass/background/init.js +++ b/chromeipass/background/init.js @@ -79,12 +79,14 @@ browser.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { /** * Retrieve Credentials and try auto-login for HTTPAuth requests + * + * (Intercepting HTTP auth currently unsupported in Firefox.) */ -/* TODO: Not supported in Firefox/WebExtensions -chrome.webRequest.onAuthRequired.addListener(httpAuth.handleRequest, - { urls: [""] }, ["asyncBlocking"] -); -*/ +if (browser.webRequest.onAuthRequired) { + browser.webRequest.onAuthRequired.addListener(httpAuth.handleRequest, + { urls: [""] }, ["asyncBlocking"] + ); +} /** * Interaction between background-script and front-script diff --git a/chromeipass/options/options.html b/chromeipass/options/options.html index b93ba38..e007a97 100644 --- a/chromeipass/options/options.html +++ b/chromeipass/options/options.html @@ -226,7 +226,7 @@

General Settings


-

+

diff --git a/chromeipass/options/options.js b/chromeipass/options/options.js index cce53d5..c1fb061 100644 --- a/chromeipass/options/options.js +++ b/chromeipass/options/options.js @@ -162,6 +162,13 @@ options.initGeneralSettings = function() { action: 'load_settings' }); }); + + if (!browser.webRequest.onAuthRequired) { + /* onAuthRequired isn't supported on current Firefox, + so hide this feature. + */ + $("#http-auth-options").hide(); + } }; options.showKeePassHttpVersions = function(response) { From 37ea426aa7e5174bf0d553bdd69991ad1b2f7b16 Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Sun, 19 Feb 2017 16:01:56 +1100 Subject: [PATCH 07/20] chromeipass: Hide Chrome Web Store link on settings page, if not Chrome/Chromium --- chromeipass/options/options.html | 2 +- chromeipass/options/options.js | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/chromeipass/options/options.html b/chromeipass/options/options.html index e007a97..931e537 100644 --- a/chromeipass/options/options.html +++ b/chromeipass/options/options.html @@ -428,7 +428,7 @@

About

Developed by Perry Nguyen and Lukas Schulze.

- Visit extension's page in Chrome Web store + Visit extension's page in Chrome Web store

Visit project's page in GitHub. diff --git a/chromeipass/options/options.js b/chromeipass/options/options.js index c1fb061..ee5cd32 100644 --- a/chromeipass/options/options.js +++ b/chromeipass/options/options.js @@ -319,4 +319,8 @@ options.initSpecifiedCredentialFields = function() { options.initAbout = function() { var manifest = browser.runtime.getManifest(); $("#tab-about em.versionCIP").text(manifest.version); + if (!(/Chrome/.test(navigator.userAgent) && /Google/.test(navigator.vendor))) { + /* Not Chrome or Chromium */ + $("#chrome-web-store-link").remove(); + } } From 3b17eaf2888ee3ef4da0568ec72964888cc1ac9a Mon Sep 17 00:00:00 2001 From: Andy Brandt Date: Tue, 15 Aug 2017 11:27:14 -0500 Subject: [PATCH 08/20] move cip.init() so it's run after everything is defined. seems to fix issues in waterfox. --- chromeipass/chromeipass.js | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/chromeipass/chromeipass.js b/chromeipass/chromeipass.js index f719447..53c5eaf 100644 --- a/chromeipass/chromeipass.js +++ b/chromeipass/chromeipass.js @@ -1138,10 +1138,6 @@ cip.submitUrl = null; // received credentials from KeePassHTTP cip.credentials = []; -cIPJQ(function() { - cip.init(); -}); - cip.init = function() { browser.runtime.sendMessage({ "action": "get_settings", @@ -1703,7 +1699,9 @@ cip.rememberCredentials = function(usernameValue, passwordValue) { return false; }; - +cIPJQ(function() { + cip.init(); +}); var cipEvents = {}; From 6d894768ff149a9fecba8eff300710523ac96cdc Mon Sep 17 00:00:00 2001 From: Andy Brandt Date: Tue, 15 Aug 2017 11:28:22 -0500 Subject: [PATCH 09/20] async httpauth working for firefox (supported in firefox v54 and up) --- chromeipass/background/httpauth.js | 31 ++++++++++++++++-------------- chromeipass/background/init.js | 6 +++--- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/chromeipass/background/httpauth.js b/chromeipass/background/httpauth.js index 762f8c9..48fc6ed 100644 --- a/chromeipass/background/httpauth.js +++ b/chromeipass/background/httpauth.js @@ -2,26 +2,29 @@ var httpAuth = httpAuth || {}; httpAuth.pendingCallbacks = []; httpAuth.requestId = ""; -httpAuth.callback = null; httpAuth.tabId = 0; httpAuth.url = null; httpAuth.isProxy = false; httpAuth.proxyUrl = null; +httpAuth.resolve = null; -httpAuth.handleRequest = function (details, callback) { - if(httpAuth.requestId == details.requestId || !page.tabs[details.tabId]) { - callback({}); - } - else { - httpAuth.requestId = details.requestId; - httpAuth.pendingCallbacks.push(callback); - httpAuth.processPendingCallbacks(details); - } +httpAuth.handleRequest = function (details) { + return new Promise((resolve, reject) => { + if(httpAuth.requestId == details.requestId || !page.tabs[details.tabId]) { + resolve({cancel: true}); + } + else { + httpAuth.requestId = details.requestId; + httpAuth.pendingCallbacks.push(details); + httpAuth.resolve = resolve; + httpAuth.processPendingCallbacks(details); + } + }); } httpAuth.processPendingCallbacks = function(details) { - httpAuth.callback = httpAuth.pendingCallbacks.pop(); + //httpAuth.callback = httpAuth.pendingCallbacks.pop(); httpAuth.tabId = details.tabId; httpAuth.url = details.url; httpAuth.isProxy = details.isProxy; @@ -47,7 +50,7 @@ httpAuth.loginOrShowCredentials = function(logins) { //generate popup-list for HTTP Auth usernames + descriptions if(page.settings.autoFillAndSend) { - httpAuth.callback({ + httpAuth.resolve({ authCredentials: { username: logins[0].Login, password: logins[0].Password @@ -55,11 +58,11 @@ httpAuth.loginOrShowCredentials = function(logins) { }); } else { - httpAuth.callback({}); + httpAuth.resolve({cancel:true}); } } // no logins found else { - httpAuth.callback({}); + httpAuth.resolve({cancel:true}); } } diff --git a/chromeipass/background/init.js b/chromeipass/background/init.js index 727c2f5..1057d15 100644 --- a/chromeipass/background/init.js +++ b/chromeipass/background/init.js @@ -50,7 +50,7 @@ browser.tabs.onRemoved.addListener(function(tabId, removeInfo) { */ browser.tabs.onActivated.addListener(function(activeInfo) { // remove possible credentials from old tab information - page.clearCredentials(page.currentTabId, true); + page.clearCredentials(page.currentTabId, true); browserAction.removeRememberPopup(null, {"id": page.currentTabId}, true); browser.tabs.get(activeInfo.tabId).then(function(info) { @@ -84,8 +84,8 @@ browser.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) { */ if (browser.webRequest.onAuthRequired) { browser.webRequest.onAuthRequired.addListener(httpAuth.handleRequest, - { urls: [""] }, ["asyncBlocking"] - ); + { urls: [""] }, ["blocking"] + ); } /** From 8da91c2c925ce99dbf793b3b77e0fe651d48ba4b Mon Sep 17 00:00:00 2001 From: Andy Brandt Date: Tue, 15 Aug 2017 11:28:34 -0500 Subject: [PATCH 10/20] update version to 2.8.1 --- chromeipass/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chromeipass/manifest.json b/chromeipass/manifest.json index 3cdbe38..351baa5 100644 --- a/chromeipass/manifest.json +++ b/chromeipass/manifest.json @@ -1,6 +1,6 @@ { "name": "chromeIPass", - "version": "2.8.0", + "version": "2.8.1", "manifest_version": 2, "description": "KeePass integration for browser Chrome using KeePassHttp", "icons": { From b2222a91d677e9416c080db39a5f07fd70440e96 Mon Sep 17 00:00:00 2001 From: Andy Brandt Date: Tue, 15 Aug 2017 12:23:56 -0500 Subject: [PATCH 11/20] remove unused pendingCallbacks, and reject the promise so it still prompts for credentials if none are found --- chromeipass/background/httpauth.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/chromeipass/background/httpauth.js b/chromeipass/background/httpauth.js index 48fc6ed..d3fce43 100644 --- a/chromeipass/background/httpauth.js +++ b/chromeipass/background/httpauth.js @@ -1,30 +1,29 @@ var httpAuth = httpAuth || {}; -httpAuth.pendingCallbacks = []; httpAuth.requestId = ""; httpAuth.tabId = 0; httpAuth.url = null; httpAuth.isProxy = false; httpAuth.proxyUrl = null; httpAuth.resolve = null; +httpAuth.reject = null; httpAuth.handleRequest = function (details) { return new Promise((resolve, reject) => { if(httpAuth.requestId == details.requestId || !page.tabs[details.tabId]) { - resolve({cancel: true}); + reject({}); } else { httpAuth.requestId = details.requestId; - httpAuth.pendingCallbacks.push(details); httpAuth.resolve = resolve; + httpAuth.reject = reject; httpAuth.processPendingCallbacks(details); } }); } httpAuth.processPendingCallbacks = function(details) { - //httpAuth.callback = httpAuth.pendingCallbacks.pop(); httpAuth.tabId = details.tabId; httpAuth.url = details.url; httpAuth.isProxy = details.isProxy; @@ -58,11 +57,11 @@ httpAuth.loginOrShowCredentials = function(logins) { }); } else { - httpAuth.resolve({cancel:true}); + httpAuth.reject({}); } } // no logins found else { - httpAuth.resolve({cancel:true}); + httpAuth.reject({}); } } From 4ee91f83b60c62e8ab7c5c8cdf1a1ee041feed52 Mon Sep 17 00:00:00 2001 From: Andy Brandt Date: Tue, 15 Aug 2017 12:35:51 -0500 Subject: [PATCH 12/20] update version to 2.8.2 --- chromeipass/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chromeipass/manifest.json b/chromeipass/manifest.json index 351baa5..78d9591 100644 --- a/chromeipass/manifest.json +++ b/chromeipass/manifest.json @@ -1,6 +1,6 @@ { "name": "chromeIPass", - "version": "2.8.1", + "version": "2.8.2", "manifest_version": 2, "description": "KeePass integration for browser Chrome using KeePassHttp", "icons": { From 86ed1c3565f3496bb4576e9dd1818722ac994162 Mon Sep 17 00:00:00 2001 From: Andy Brandt Date: Fri, 25 Aug 2017 13:46:32 -0500 Subject: [PATCH 13/20] hack to show alerts in firefox --- chromeipass/background/event.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chromeipass/background/event.js b/chromeipass/background/event.js index bd45752..7cbd2aa 100644 --- a/chromeipass/background/event.js +++ b/chromeipass/background/event.js @@ -80,7 +80,7 @@ event.invoke = function(handler, callback, senderTabId, args, secondTime) { event.onShowAlert = function(callback, tab, message) { if( page.settings.supressAlerts ){ console.log(message); } - else { alert(message); } + else { browser.tabs.executeScript({code: 'alert(\''+message+'\')'}); } } event.onLoadSettings = function(callback, tab) { From 88a81871d79b7d7ca8d72f449fcf803126d9a178 Mon Sep 17 00:00:00 2001 From: Andy Brandt Date: Fri, 25 Aug 2017 13:46:55 -0500 Subject: [PATCH 14/20] update version to 2.8.3 --- chromeipass/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chromeipass/manifest.json b/chromeipass/manifest.json index 78d9591..aa1515a 100644 --- a/chromeipass/manifest.json +++ b/chromeipass/manifest.json @@ -1,6 +1,6 @@ { "name": "chromeIPass", - "version": "2.8.2", + "version": "2.8.3", "manifest_version": 2, "description": "KeePass integration for browser Chrome using KeePassHttp", "icons": { From 49f84b69520efecc9d3dcf718f1df342d31aabd1 Mon Sep 17 00:00:00 2001 From: Andy Brandt Date: Tue, 29 Aug 2017 13:12:00 -0500 Subject: [PATCH 15/20] update version to 2.8.4, remove "Chrome" from description --- chromeipass/manifest.json | 29 ++++++++++++++++------------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/chromeipass/manifest.json b/chromeipass/manifest.json index f041c98..778fbaf 100644 --- a/chromeipass/manifest.json +++ b/chromeipass/manifest.json @@ -1,8 +1,8 @@ { "name": "chromeIPass", - "version": "2.8.3", - "manifest_version": 2, - "description": "KeePass integration for browser Chrome using KeePassHttp", + "version": "2.8.4", + "manifest_version": 2, + "description": "KeePass integration for browsers using KeePassHttp", "icons": { "16": "icons/keepass_16x16.png", "48": "icons/keepass_48x48.png", @@ -11,8 +11,8 @@ "browser_action": { "default_icon": { - "19": "icons/19x19/icon_normal_blue_19x19.png", - "38": "icons/keepass_38x38.png" + "19": "icons/19x19/icon_normal_blue_19x19.png", + "38": "icons/keepass_38x38.png" }, "default_title": "chromeIPass", "default_popup": "popups/popup.html" @@ -36,14 +36,17 @@ "content_scripts": [ { "matches": ["http://*/*", "https://*/*"], - "js": ["browser-polyfill.min.js", - "jquery-1.11.1.min.js", - "jquery-ui-1.10.2.custom.min.js", - "chromeipass.js" - ], - "css": ["jquery-ui-1.10.2.custom.min.css", - "bootstrap-btn.css", - "chromeipass.css"], + "js": [ + "browser-polyfill.min.js", + "jquery-1.11.1.min.js", + "jquery-ui-1.10.2.custom.min.js", + "chromeipass.js" + ], + "css": [ + "jquery-ui-1.10.2.custom.min.css", + "bootstrap-btn.css", + "chromeipass.css" + ], "run_at": "document_idle", "all_frames": true } From 3ae33bfb26d4d401efabd6e409cd3bfc1d69768b Mon Sep 17 00:00:00 2001 From: Andy Brandt Date: Thu, 31 Aug 2017 14:32:32 -0500 Subject: [PATCH 16/20] first attempt at using storage api to store settings --- chromeipass/background/browserAction.js | 85 +++++++++--------- chromeipass/background/event.js | 37 ++++---- chromeipass/background/init.js | 30 ++++--- chromeipass/background/keepass.js | 51 +++++++---- chromeipass/background/page.js | 96 ++++++++++++-------- chromeipass/chromeipass.js | 92 +++++++++---------- chromeipass/manifest.json | 1 + chromeipass/options/options.js | 113 ++++++++++-------------- chromeipass/popups/popup_functions.js | 1 - 9 files changed, 265 insertions(+), 241 deletions(-) diff --git a/chromeipass/background/browserAction.js b/chromeipass/background/browserAction.js index 4b31d22..03ba174 100644 --- a/chromeipass/background/browserAction.js +++ b/chromeipass/background/browserAction.js @@ -34,12 +34,12 @@ browserAction.update = function(interval) { var 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) { browserAction.stackPop(page.currentTabId); browserAction.show(null, {"id": page.currentTabId}); page.clearCredentials(page.currentTabId); - return; + return; } data.visibleForMilliSeconds -= interval; } @@ -74,10 +74,10 @@ browserAction.showDefault = function(callback, tab) { stackData.iconType = "cross"; } - if(page.tabs[tab.id].loginList.length > 0) { - stackData.iconType = "questionmark"; - stackData.popup = "popup_login.html"; - } + if(page.tabs[tab.id].loginList.length > 0) { + stackData.iconType = "questionmark"; + stackData.popup = "popup_login.html"; + } browserAction.stackUnshift(stackData, tab.id); @@ -183,12 +183,12 @@ browserAction.removeRememberPopup = function(callback, tab, removeImmediately) { } if(page.tabs[tab.id].stack.length == 0) { - page.clearCredentials(tab.id); + page.clearCredentials(tab.id); return; } var data = page.tabs[tab.id].stack[page.tabs[tab.id].stack.length - 1]; - if(removeImmediately || !isNaN(data.visibleForPageUpdates)) { + if(removeImmediately || !isNaN(data.visibleForPageUpdates)) { var currentMS = Date.now(); if( removeImmediately || (data.visibleForPageUpdates <= 0 && data.redirectOffset > 0)) { browserAction.stackPop(tab.id); @@ -199,47 +199,48 @@ browserAction.removeRememberPopup = function(callback, tab, removeImmediately) { else if (!isNaN(data.visibleForPageUpdates) && data.redirectOffset > 0 && currentMS >= data.redirectOffset) { data.visibleForPageUpdates = data.visibleForPageUpdates - 1; } - } + } }; browserAction.setRememberPopup = function(tabId, username, password, url, usernameExists, credentialsList) { - var settings = typeof(localStorage.settings)=='undefined' ? {} : JSON.parse(localStorage.settings); - - var id = tabId || page.currentTabId; - - var timeoutMinMillis = parseInt(getValueOrDefault(settings, "blinkMinTimeout", BLINK_TIMEOUT_REDIRECT_THRESHOLD_TIME_DEFAULT, 0)) ; - if (timeoutMinMillis > 0) { - timeoutMinMillis += Date.now(); - } - var blinkTimeout = getValueOrDefault(settings, "blinkTimeout", BLINK_TIMEOUT_DEFAULT, 0); - var pageUpdateAllowance = getValueOrDefault(settings, "allowedRedirect", BLINK_TIMEOUT_REDIRECT_COUNT_DEFAULT, 0); + browser.storage.local.get({'settings': {}}).then(function(item) { + var settings = item.settings; + var id = tabId || page.currentTabId; - var stackData = { - visibleForMilliSeconds: blinkTimeout, - visibleForPageUpdates: pageUpdateAllowance, - redirectOffset: timeoutMinMillis, - level: 10, - intervalIcon: { - index: 0, - counter: 0, - max: 2, - icons: ["icon_remember_red_background_19x19.png", "icon_remember_red_lock_19x19.png"] - }, - icon: "icon_remember_red_background_19x19.png", - popup: "popup_remember.html" - } + var timeoutMinMillis = parseInt(getValueOrDefault(settings, "blinkMinTimeout", BLINK_TIMEOUT_REDIRECT_THRESHOLD_TIME_DEFAULT, 0)) ; + if (timeoutMinMillis > 0) { + timeoutMinMillis += Date.now(); + } + var blinkTimeout = getValueOrDefault(settings, "blinkTimeout", BLINK_TIMEOUT_DEFAULT, 0); + var pageUpdateAllowance = getValueOrDefault(settings, "allowedRedirect", BLINK_TIMEOUT_REDIRECT_COUNT_DEFAULT, 0); + + var stackData = { + visibleForMilliSeconds: blinkTimeout, + visibleForPageUpdates: pageUpdateAllowance, + redirectOffset: timeoutMinMillis, + level: 10, + intervalIcon: { + index: 0, + counter: 0, + max: 2, + icons: ["icon_remember_red_background_19x19.png", "icon_remember_red_lock_19x19.png"] + }, + icon: "icon_remember_red_background_19x19.png", + popup: "popup_remember.html" + } - browserAction.stackPush(stackData, id); + browserAction.stackPush(stackData, id); - page.tabs[id].credentials = { - "username": username, - "password": password, - "url": url, - "usernameExists": usernameExists, - "list": credentialsList - }; + page.tabs[id].credentials = { + "username": username, + "password": password, + "url": url, + "usernameExists": usernameExists, + "list": credentialsList + }; - browserAction.show(null, {"id": id}); + browserAction.show(null, {"id": id}); + }); } function getValueOrDefault(settings, key, defaultVal, min) { diff --git a/chromeipass/background/event.js b/chromeipass/background/event.js index 7cbd2aa..b7f750d 100644 --- a/chromeipass/background/event.js +++ b/chromeipass/background/event.js @@ -77,34 +77,38 @@ event.invoke = function(handler, callback, senderTabId, args, secondTime) { }); } - event.onShowAlert = function(callback, tab, message) { if( page.settings.supressAlerts ){ console.log(message); } else { browser.tabs.executeScript({code: 'alert(\''+message+'\')'}); } } event.onLoadSettings = function(callback, tab) { - page.settings = (typeof(localStorage.settings) == 'undefined') ? {} : JSON.parse(localStorage.settings); + browser.storage.local.get({'settings': {}}).then((item) => { + callback(item.settings); + }, (err) => { + console.log('error loading settings: ' + err); + }); } event.onLoadKeyRing = function(callback, tab) { - keepass.keyRing = (typeof(localStorage.keyRing) == 'undefined') ? {} : JSON.parse(localStorage.keyRing); - if(keepass.isAssociated() && !keepass.keyRing[keepass.associated.hash]) { - keepass.associated = { - "value": false, - "hash": null - }; - } -} - -event.onGetSettings = function(callback, tab) { - event.onLoadSettings(); - callback({ data: page.settings }); + browser.storage.local.get({'keyRing': {}}).then(function(item) { + keepass.keyRing = item.keyRing; + if(keepass.isAssociated() && !keepass.keyRing[keepass.associated.hash]) { + keepass.associated = { + "value": false, + "hash": null + }; + } + callback(item.keyRing); + }, (err) => { + console.log('error loading keyRing: ' + err); + }); } event.onSaveSettings = function(callback, tab, settings) { - localStorage.settings = JSON.stringify(settings); - event.onLoadSettings(); + browser.storage.local.set({'settings': settings}).then(function() { + event.onLoadSettings(); + }); } event.onGetStatus = function(callback, tab) { @@ -219,7 +223,6 @@ event.messageHandlers = { 'check_update_keepasshttp': event.onCheckUpdateKeePassHttp, 'get_connected_database': event.onGetConnectedDatabase, 'get_keepasshttp_versions': event.onGetKeePassHttpVersions, - 'get_settings': event.onGetSettings, 'get_status': event.onGetStatus, 'get_tab_information': event.onGetTabInformation, 'load_keyring': event.onLoadKeyRing, diff --git a/chromeipass/background/init.js b/chromeipass/background/init.js index dc3fa17..0c88d7e 100644 --- a/chromeipass/background/init.js +++ b/chromeipass/background/init.js @@ -1,17 +1,23 @@ // since version 2.0 the extension is using a keyRing instead of a single key-name-pair -keepass.convertKeyToKeyRing(); -// load settings -page.initSettings(); -// create tab information structure for every opened tab -page.initOpenedTabs(); -// initial connection with KeePassHttp -keepass.getDatabaseHash(null); -// set initial tab-ID -browser.tabs.query({"active": true, "currentWindow": true}).then(function(tabs) { - if (tabs.length === 0) - return; // For example: only the background devtools or a popup are opened - page.currentTabId = tabs[0].id; +keepass.migrateKeyRing().then(() => { + // load settings + page.initSettings().then(() => { + // initial connection with KeePassHttp + keepass.getDatabaseHash(null); + + // create tab information structure for every opened tab + page.initOpenedTabs(); + + // set initial tab-ID + browser.tabs.query({"active": true, "currentWindow": true}).then(function(tabs) { + if (tabs.length === 0) + return; // For example: only the background devtools or a popup are opened + page.currentTabId = tabs[0].id; + browserAction.show(null, tabs[0]); + }); + }); }); + // Milliseconds for intervall (e.g. to update browserAction) var _interval = 250; diff --git a/chromeipass/background/keepass.js b/chromeipass/background/keepass.js index b1aa4b7..d30bc51 100644 --- a/chromeipass/background/keepass.js +++ b/chromeipass/background/keepass.js @@ -5,18 +5,23 @@ keepass.isDatabaseClosed = false; keepass.isKeePassHttpAvailable = false; keepass.isEncryptionKeyUnrecognized = false; keepass.currentKeePassHttp = {"version": 0, "versionParsed": 0}; -keepass.latestKeePassHttp = (typeof(localStorage.latestKeePassHttp) == 'undefined') ? {"version": 0, "versionParsed": 0, "lastChecked": null} : JSON.parse(localStorage.latestKeePassHttp); keepass.keySize = 8; // wtf? stupid cryptoHelpers keepass.pluginUrlDefault = "http://localhost:19455/"; keepass.latestVersionUrl = "https://passifox.appspot.com/kph/latest-version.txt"; keepass.cacheTimeout = 30 * 1000; // milliseconds keepass.databaseHash = "no-hash"; //no-hash = keepasshttp is too old and does not return a hash value -keepass.keyRing = (typeof(localStorage.keyRing) == 'undefined') ? {} : JSON.parse(localStorage.keyRing); keepass.keyId = "chromeipass-cryptokey-name"; keepass.keyBody = "chromeipass-key"; keepass.to_s = cryptoHelpers.convertByteArrayToString; keepass.to_b = cryptoHelpers.convertStringToByteArray; +browser.storage.local.get({ + 'latestKeePassHttp': {'version': 0, 'versionParsed': 0, 'lastChecked': null}, + 'keyRing': {}}) + .then((item) => { + keepass.latestKeePassHttp = item.latestKeePassHttp; + keepass.keyRing = item.keyRing; +}); keepass.addCredentials = function(callback, tab, username, password, url) { keepass.updateCredentials(callback, tab, null, username, password, url); @@ -315,17 +320,29 @@ keepass.checkStatus = function (status, tab) { return success; } -keepass.convertKeyToKeyRing = function() { - if(keepass.keyId in localStorage && keepass.keyBody in localStorage && !("keyRing" in localStorage)) { - var hash = keepass.getDatabaseHash(null); - keepass.saveKey(hash, localStorage[keepass.keyId], localStorage[keepass.keyBody]); - } - - if("keyRing" in localStorage) { - delete localStorage[keepass.keyId]; - delete localStorage[keepass.keyBody]; - } -} +keepass.migrateKeyRing = () => { + return new Promise((resolve, reject) => { + browser.storage.local.get('keyRing').then((item) => { + var keyring = item.keyRing; + if ('keyRing' in localStorage) { + if (!keyring) { + keyring = JSON.parse(localStorage['keyRing']); + browser.storage.local.set({'keyRing': keyring}); + } + delete localStorage['keyRing']; + } + if (keepass.keyId in localStorage && keepass.keyBody in localStorage) { + if (!keyring) { + var hash = keepass.getDatabaseHash(null); + keepass.saveKey(hash, localStorage[keepass.keyId], localStorage[keepass.keyBody]); + } + delete localStorage[keepass.keyId]; + delete localStorage[keepass.keyBody]; + } + resolve(); + }); + }); +}; keepass.saveKey = function(hash, id, key) { if(!(hash in keepass.keyRing)) { @@ -341,19 +358,19 @@ keepass.saveKey = function(hash, id, key) { keepass.keyRing[hash].id = id; keepass.keyRing[hash].key = key; } - localStorage.keyRing = JSON.stringify(keepass.keyRing); + browser.storage.local.set({'keyRing': keepass.keyRing}); } keepass.updateLastUsed = function(hash) { if((hash in keepass.keyRing)) { keepass.keyRing[hash].lastUsed = new Date(); - localStorage.keyRing = JSON.stringify(keepass.keyRing); + browser.storage.local.set({'keyRing': keepass.keyRing}); } } keepass.deleteKey = function(hash) { delete keepass.keyRing[hash]; - localStorage.keyRing = JSON.stringify(keepass.keyRing); + browser.storage.local.set({'keyRing': keepass.keyRing}); } keepass.getIconColor = function() { @@ -410,7 +427,7 @@ keepass.checkForNewKeePassHttpVersion = function() { } if($version != -1) { - localStorage.latestKeePassHttp = JSON.stringify(keepass.latestKeePassHttp); + browser.storage.local.set({'latestKeePassHttp': keepass.latestKeePassHttp}); } keepass.latestKeePassHttp.lastChecked = new Date(); } diff --git a/chromeipass/background/page.js b/chromeipass/background/page.js index 24bf516..4f61a73 100644 --- a/chromeipass/background/page.js +++ b/chromeipass/background/page.js @@ -4,36 +4,57 @@ var page = {}; page.tabs = {}; page.currentTabId = -1; -page.settings = (typeof(localStorage.settings) == 'undefined') ? {} : JSON.parse(localStorage.settings); page.blockedTabs = {}; +page.migrateSettings = () => { + return new Promise((resolve, reject) => { + var old = localStorage.getItem('settings'); + if (old) { + var settings = JSON.parse(old); + browser.storage.local.set({'settings': settings}).then(() => { + localStorage.removeItem(item); + resolve(obj); + }); + } else { + event.onLoadSettings((settings) => { + resolve(settings); + }); + } + }); +}; + page.initSettings = function() { - event.onLoadSettings(); - if(!("checkUpdateKeePassHttp" in page.settings)) { - page.settings.checkUpdateKeePassHttp = 3; - } - if(!("autoCompleteUsernames" in page.settings)) { - page.settings.autoCompleteUsernames = 1; - } - if(!("autoFillAndSend" in page.settings)) { - page.settings.autoFillAndSend = 1; - } - if(!("usePasswordGenerator" in page.settings)) { - page.settings.usePasswordGenerator = 1; - } - if(!("autoFillSingleEntry" in page.settings)) { - page.settings.autoFillSingleEntry = 1; - } - if(!("autoRetrieveCredentials" in page.settings)) { - page.settings.autoRetrieveCredentials = 1; - } - if(!("hostname" in page.settings)) { - page.settings.hostname = "localhost"; - } - if(!("port" in page.settings)) { - page.settings.port = "19455"; - } - localStorage.settings = JSON.stringify(page.settings); + return new Promise((resolve, reject) => { + page.migrateSettings().then((settings) => { + page.settings = settings; + if(!("checkUpdateKeePassHttp" in page.settings)) { + page.settings.checkUpdateKeePassHttp = 3; + } + if(!("autoCompleteUsernames" in page.settings)) { + page.settings.autoCompleteUsernames = 1; + } + if(!("autoFillAndSend" in page.settings)) { + page.settings.autoFillAndSend = 1; + } + if(!("usePasswordGenerator" in page.settings)) { + page.settings.usePasswordGenerator = 1; + } + if(!("autoFillSingleEntry" in page.settings)) { + page.settings.autoFillSingleEntry = 1; + } + if(!("autoRetrieveCredentials" in page.settings)) { + page.settings.autoRetrieveCredentials = 1; + } + if(!("hostname" in page.settings)) { + page.settings.hostname = "localhost"; + } + if(!("port" in page.settings)) { + page.settings.port = "19455"; + } + browser.storage.local.set({'settings': page.settings}); + resolve(); + }); + }); } page.initOpenedTabs = function() { @@ -64,13 +85,13 @@ page.clearCredentials = function(tabId, complete) { page.tabs[tabId].credentials = {}; delete page.tabs[tabId].credentials; - if(complete) { - page.tabs[tabId].loginList = []; + if(complete) { + page.tabs[tabId].loginList = []; - browser.tabs.sendMessage(tabId, { - action: "clear_credentials" - }); - } + browser.tabs.sendMessage(tabId, { + action: "clear_credentials" + }); + } } page.createTabEntry = function(tabId) { @@ -113,11 +134,10 @@ page.debugConsole = function() { page.sprintf = function(input, args) { return input.replace(/{(\d+)}/g, function(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; + }); } page.debugDummy = function() {}; diff --git a/chromeipass/chromeipass.js b/chromeipass/chromeipass.js index b19f0a6..aa330a8 100644 --- a/chromeipass/chromeipass.js +++ b/chromeipass/chromeipass.js @@ -16,10 +16,10 @@ browser.runtime.onMessage.addListener(function(req, sender, callback) { combination = cipFields.getCombination("password", cip.p); } - var list = {}; + var list = {}; if(cip.fillInStringFields(combination.fields, cip.credentials[req.id].StringFields, list)) { - cipForm.destroy(false, {"password": list.list[0], "username": list.list[1]}); - } + cipForm.destroy(false, {"password": list.list[0], "username": list.list[1]}); + } } // wish I could clear out _logins and _u, but a subsequent // selection may be requested. @@ -49,9 +49,9 @@ browser.runtime.onMessage.addListener(function(req, sender, callback) { } else if (req.action == "redetect_fields") { browser.runtime.sendMessage({ - "action": "get_settings", - }).then(function(response) { - cip.settings = response.data; + "action": "load_settings", + }).then(function(settings) { + cip.settings = settings; cip.initCredentialFields(true); }); } @@ -163,7 +163,7 @@ cipPassword.init = function() { }, 400); /* Append extension-local background-image URLs to - 'generate password' icon CSS classes */ + 'generate password' icon CSS classes */ var make_keyicon_css = function(nested_class, icon_size) { return ".cip-genpw-icon." + nested_class + " {" + "background-image: url(" + @@ -488,16 +488,16 @@ cipForm.init = function(form, credentialFields) { } cipForm.destroy = function(form, credentialFields) { - if(form === false && credentialFields) { - var field = _f(credentialFields.password) || _f(credentialFields.username); + if(form === false && credentialFields) { + var field = _f(credentialFields.password) || _f(credentialFields.username); if(field) { form = field.closest("form"); } - } + } - if(form && cIPJQ(form).length > 0) { - cIPJQ(form).unbind('submit', cipForm.onSubmit); - } + if(form && cIPJQ(form).length > 0) { + cIPJQ(form).unbind('submit', cipForm.onSubmit); + } } cipForm.setInputFields = function(form, credentialFields) { @@ -769,7 +769,7 @@ cipDefine.prepareStep3 = function() { cIPJQ("button#b2c-btn-dismiss").click(); return; } - */ + */ if(!cipDefine.selection.username && !cipDefine.selection.password) { cIPJQ("button#b2c-btn-confirm:first").removeClass("b2c-btn-primary").attr("disabled", true); @@ -889,7 +889,7 @@ cipFields.getCombination = function(givenType, fieldId) { "password": null }; - var newCombi = false; + var newCombi = false; if(givenType == "username") { var passwordField = cipFields.getPasswordField(fieldId, true); var passwordId = null; @@ -900,7 +900,7 @@ cipFields.getCombination = function(givenType, fieldId) { "username": fieldId, "password": passwordId }; - newCombi = true; + newCombi = true; } else if(givenType == "password") { var usernameField = cipFields.getUsernameField(fieldId, true); @@ -912,7 +912,7 @@ cipFields.getCombination = function(givenType, fieldId) { "username": usernameId, "password": fieldId }; - newCombi = true; + newCombi = true; } if(combination.username || combination.password) { @@ -925,9 +925,9 @@ cipFields.getCombination = function(givenType, fieldId) { } } - if(newCombi) { - combination.isNew = true; - } + if(newCombi) { + combination.isNew = true; + } return combination; } @@ -1120,9 +1120,9 @@ cip.credentials = []; cip.init = function() { browser.runtime.sendMessage({ - "action": "get_settings", - }).then(function(response) { - cip.settings = response.data; + "action": "load_settings", + }).then(function(settings) { + cip.settings = settings; cip.initCredentialFields(); }); } @@ -1153,12 +1153,12 @@ cip.initCredentialFields = function(forceCall) { cip.url = document.location.origin; cip.submitUrl = cip.getFormActionUrl(cipFields.combinations[0]); - if(cip.settings.autoRetrieveCredentials) { - browser.runtime.sendMessage({ - 'action': 'retrieve_credentials', - 'args': [ cip.url, cip.submitUrl ] - }).then(cip.retrieveCredentialsCallback); - } + if(cip.settings.autoRetrieveCredentials) { + browser.runtime.sendMessage({ + 'action': 'retrieve_credentials', + 'args': [ cip.url, cip.submitUrl ] + }).then(cip.retrieveCredentialsCallback); + } } // end function init cip.initPasswordGenerator = function(inputs) { @@ -1266,9 +1266,9 @@ cip.preparePageForMultipleCredentials = function(credentials) { cip.getFormActionUrl = function(combination) { var field = _f(combination.password) || _f(combination.username); - if(field == null) { - return null; - } + if(field == null) { + return null; + } var form = field.closest("form"); var action = null; @@ -1401,14 +1401,14 @@ cip.setValue = function(field, value) { cip.fillInStringFields = function(fields, StringFields, filledInFields) { var $filledIn = false; - filledInFields.list = []; + filledInFields.list = []; if(fields && StringFields && fields.length > 0 && StringFields.length > 0) { - for(var i = 0; i < fields.length; i++) { + for(var i = 0; i < fields.length; i++) { var $sf = _fs(fields[i]); if($sf && StringFields[i]) { //$sf.val(StringFields[i].Value); cip.setValue($sf, StringFields[i].Value); - filledInFields.list.push(fields[i]); + filledInFields.list.push(fields[i]); $filledIn = true; } } @@ -1462,11 +1462,11 @@ cip.fillIn = function(combination, onlyPassword, suppressWarnings) { filledIn = true; } - var list = {}; + var list = {}; if(cip.fillInStringFields(combination.fields, cip.credentials[0].StringFields, list)) { - cipForm.destroy(false, {"password": list.list[0], "username": list.list[1]}); - filledIn = true; - } + cipForm.destroy(false, {"password": list.list[0], "username": list.list[1]}); + filledIn = true; + } if(!filledIn) { if(!suppressWarnings) { @@ -1492,11 +1492,11 @@ cip.fillIn = function(combination, onlyPassword, suppressWarnings) { filledIn = true; } - var list = {}; + var list = {}; if(cip.fillInStringFields(combination.fields, cip.credentials[combination.loginId].StringFields, list)) { - cipForm.destroy(false, {"password": list.list[0], "username": list.list[1]}); - filledIn = true; - } + cipForm.destroy(false, {"password": list.list[0], "username": list.list[1]}); + filledIn = true; + } if(!filledIn) { if(!suppressWarnings) { @@ -1544,10 +1544,10 @@ cip.fillIn = function(combination, onlyPassword, suppressWarnings) { pField.data("unchanged", true); } - var list = {}; + var list = {}; if(cip.fillInStringFields(combination.fields, valStringFields, list)) { - cipForm.destroy(false, {"password": list.list[0], "username": list.list[1]}); - } + cipForm.destroy(false, {"password": list.list[0], "username": list.list[1]}); + } } // user has to select correct credentials by himself diff --git a/chromeipass/manifest.json b/chromeipass/manifest.json index 778fbaf..e5d984a 100644 --- a/chromeipass/manifest.json +++ b/chromeipass/manifest.json @@ -85,6 +85,7 @@ "activeTab", "contextMenus", "clipboardWrite", + "storage", "tabs", "webRequest", "webRequestBlocking", diff --git a/chromeipass/options/options.js b/chromeipass/options/options.js index ee5cd32..41ce09d 100644 --- a/chromeipass/options/options.js +++ b/chromeipass/options/options.js @@ -3,17 +3,34 @@ if(cIPJQ) { } $(function() { - options.initMenu(); - options.initGeneralSettings(); - options.initConnectedDatabases(); - options.initSpecifiedCredentialFields(); - options.initAbout(); + browser.runtime.sendMessage({ action: 'load_settings' }).then((settings) => { + options.settings = settings; + browser.runtime.sendMessage({ action: 'load_keyring' }).then((keyRing) => { + options.keyRing = keyRing; + options.initMenu(); + options.initGeneralSettings(); + options.initConnectedDatabases(); + options.initSpecifiedCredentialFields(); + options.initAbout(); + }); + }); }); var options = options || {}; -options.settings = typeof(localStorage.settings)=='undefined' ? {} : JSON.parse(localStorage.settings); -options.keyRing = typeof(localStorage.keyRing)=='undefined' ? {} : JSON.parse(localStorage.keyRing); +options.saveSettings = function() { + browser.storage.local.set({'settings': options.settings}); + browser.runtime.sendMessage({ + action: 'load_settings' + }); +}; + +options.saveKeyRing = function() { + browser.storage.local.set({'keyRing': options.keyRing}); + browser.runtime.sendMessage({ + action: 'load_keyring' + }); +}; options.initMenu = function() { $(".navbar:first ul.nav:first li a").click(function(e) { @@ -34,11 +51,7 @@ options.initGeneralSettings = function() { $("#tab-general-settings input[type=checkbox]").change(function() { options.settings[$(this).attr("name")] = $(this).is(':checked'); - localStorage.settings = JSON.stringify(options.settings); - - browser.runtime.sendMessage({ - action: 'load_settings' - }); + options.saveSettings(); }); $("#tab-general-settings input[type=radio]").each(function() { @@ -49,11 +62,7 @@ options.initGeneralSettings = function() { $("#tab-general-settings input[type=radio]").change(function() { options.settings[$(this).attr("name")] = $(this).val(); - localStorage.settings = JSON.stringify(options.settings); - - browser.runtime.sendMessage({ - action: 'load_settings' - }); + options.saveSettings(); }); browser.runtime.sendMessage({ @@ -69,8 +78,8 @@ options.initGeneralSettings = function() { }); $("#showDangerousSettings").click(function() { - $('#dangerousSettings').is(":visible") ? $(this).text("Show these settings anyway") : $(this).text("Hide"); - $("#dangerousSettings").toggle(); + $('#dangerousSettings').is(":visible") ? $(this).text("Show these settings anyway") : $(this).text("Hide"); + $("#dangerousSettings").toggle(); }); $("#hostname").val(options.settings["hostname"]); @@ -92,11 +101,7 @@ options.initGeneralSettings = function() { $("#port").closest(".control-group").removeClass("error").addClass("success"); setTimeout(function() {$("#port").closest(".control-group").removeClass("success")}, 2500); - localStorage.settings = JSON.stringify(options.settings); - - browser.runtime.sendMessage({ - action: 'load_settings' - }); + options.saveSettings(); }); $("#hostnameButton").click(function() { @@ -111,62 +116,45 @@ options.initGeneralSettings = function() { $("#hostname").closest(".control-group").removeClass("error").addClass("success"); setTimeout(function() {$("#hostname").closest(".control-group").removeClass("success")}, 2500); - localStorage.settings = JSON.stringify(options.settings); - - browser.runtime.sendMessage({ - action: 'load_settings' - }); + options.saveSettings(); }); - $("#blinkTimeoutButton").click(function(){ + $("#blinkTimeoutButton").click(function(){ var blinkTimeout = $.trim($("#blinkTimeout").val()); var blinkTimeoutval = parseInt(blinkTimeout); - - options.settings["blinkTimeout"] = blinkTimeoutval.toString(); + + options.settings["blinkTimeout"] = blinkTimeoutval.toString(); + $("#blinkTimeout").closest(".control-group").removeClass("error").addClass("success"); setTimeout(function() {$("#blinkTimeout").closest(".control-group").removeClass("success")}, 2500); - localStorage.settings = JSON.stringify(options.settings); - - browser.runtime.sendMessage({ - action: 'load_settings' - }); + options.saveSettings(); }); $("#blinkMinTimeoutButton").click(function(){ var blinkMinTimeout = $.trim($("#blinkMinTimeout").val()); var blinkMinTimeoutval = parseInt(blinkMinTimeout); - - options.settings["blinkMinTimeout"] = blinkMinTimeoutval.toString(); + + options.settings["blinkMinTimeout"] = blinkMinTimeoutval.toString(); $("#blinkMinTimeout").closest(".control-group").removeClass("error").addClass("success"); setTimeout(function() {$("#blinkMinTimeout").closest(".control-group").removeClass("success")}, 2500); - localStorage.settings = JSON.stringify(options.settings); - - browser.runtime.sendMessage({ - action: 'load_settings' - }); + options.saveSettings(); }); $("#allowedRedirectButton").click(function(){ var allowedRedirect = $.trim($("#allowedRedirect").val()); var allowedRedirectval = parseInt(allowedRedirect); - - options.settings["allowedRedirect"] = allowedRedirectval.toString(); + + options.settings["allowedRedirect"] = allowedRedirectval.toString(); $("#allowedRedirect").closest(".control-group").removeClass("error").addClass("success"); setTimeout(function() {$("#allowedRedirect").closest(".control-group").removeClass("success")}, 2500); - localStorage.settings = JSON.stringify(options.settings); - - browser.runtime.sendMessage({ - action: 'load_settings' - }); + options.saveSettings(); }); if (!browser.webRequest.onAuthRequired) { - /* onAuthRequired isn't supported on current Firefox, - so hide this feature. - */ + /* onAuthRequired isn't supported on current Firefox, so hide this feature. */ $("#http-auth-options").hide(); } }; @@ -202,11 +190,7 @@ options.initConnectedDatabases = function() { $("#tab-connected-databases #tr-cd-" + $hash).remove(); delete options.keyRing[$hash]; - localStorage.keyRing = JSON.stringify(options.keyRing); - - browser.runtime.sendMessage({ - action: 'load_keyring' - }); + options.saveKeyRing(); if($("#tab-connected-databases table tbody:first tr").length > 2) { $("#tab-connected-databases table tbody:first tr.empty:first").hide(); @@ -226,10 +210,7 @@ options.initConnectedDatabases = function() { $(this).parent().parent().find("a.dropdown-toggle:first").find("img:first").attr("src", "/icons/19x19/icon_normal_" + $icon + "_19x19.png"); options.keyRing[$hash].icon = $icon; - localStorage.keyRing = JSON.stringify(options.keyRing); - browser.runtime.sendMessage({ - action: 'load_keyring' - }); + options.saveKeyRing(); }); var $trClone = $("#tab-connected-databases table tr.clone:first").clone(true); @@ -281,11 +262,7 @@ options.initSpecifiedCredentialFields = function() { $("#tab-specified-fields #" + $trId).remove(); delete options.settings["defined-credential-fields"][$url]; - localStorage.settings = JSON.stringify(options.settings); - - browser.runtime.sendMessage({ - action: 'load_settings' - }); + options.saveSettings(); if($("#tab-specified-fields table tbody:first tr").length > 2) { $("#tab-specified-fields table tbody:first tr.empty:first").hide(); diff --git a/chromeipass/popups/popup_functions.js b/chromeipass/popups/popup_functions.js index bab7241..f517f91 100644 --- a/chromeipass/popups/popup_functions.js +++ b/chromeipass/popups/popup_functions.js @@ -1,5 +1,4 @@ var $ = cIPJQ.noConflict(true); -var _settings = typeof(localStorage.settings)=='undefined' ? {} : JSON.parse(localStorage.settings); function updateAvailableResponse(available) { if(available) { From bc09e10111dd1d90e0783ff3c84bc354c115e623 Mon Sep 17 00:00:00 2001 From: Andy Brandt Date: Thu, 31 Aug 2017 14:45:01 -0500 Subject: [PATCH 17/20] update project page to my own, add credits for firefox compatibility, update copyright year --- chromeipass/options/options.html | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/chromeipass/options/options.html b/chromeipass/options/options.html index 206189c..48bccca 100644 --- a/chromeipass/options/options.html +++ b/chromeipass/options/options.html @@ -425,13 +425,14 @@

Remove specified credential fields?

About


- Developed by Perry Nguyen and Lukas Schulze. + Developed by Perry Nguyen and Lukas Schulze.
+ WebExtension (Firefox) compatibility by Angus Gratton and Andy Brandt.

Visit extension's page in Chrome Web store

- Visit project's page in GitHub. + Visit project's page in GitHub.


@@ -445,7 +446,7 @@

About


From 66940f7ec20a9f9b3ca1d798366f4ea4d68227f7 Mon Sep 17 00:00:00 2001 From: Andy Brandt Date: Thu, 31 Aug 2017 14:50:06 -0500 Subject: [PATCH 18/20] update version to 2.8.5 --- chromeipass/manifest.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chromeipass/manifest.json b/chromeipass/manifest.json index e5d984a..89fbc7b 100644 --- a/chromeipass/manifest.json +++ b/chromeipass/manifest.json @@ -1,6 +1,6 @@ { "name": "chromeIPass", - "version": "2.8.4", + "version": "2.8.5", "manifest_version": 2, "description": "KeePass integration for browsers using KeePassHttp", "icons": { From 75c8838f33148657e4aa8583831f9dd51e9406b3 Mon Sep 17 00:00:00 2001 From: Andy Brandt Date: Thu, 31 Aug 2017 15:07:11 -0500 Subject: [PATCH 19/20] whoops, properly remove old settings --- chromeipass/background/page.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chromeipass/background/page.js b/chromeipass/background/page.js index 4f61a73..a23cf12 100644 --- a/chromeipass/background/page.js +++ b/chromeipass/background/page.js @@ -12,7 +12,7 @@ page.migrateSettings = () => { if (old) { var settings = JSON.parse(old); browser.storage.local.set({'settings': settings}).then(() => { - localStorage.removeItem(item); + localStorage.removeItem('settings'); resolve(obj); }); } else { From 7b24957146476e446a7914b46e69fdd0d0b979c2 Mon Sep 17 00:00:00 2001 From: Andy Brandt Date: Thu, 31 Aug 2017 15:12:30 -0500 Subject: [PATCH 20/20] add addon id --- chromeipass/manifest.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/chromeipass/manifest.json b/chromeipass/manifest.json index 89fbc7b..7052714 100644 --- a/chromeipass/manifest.json +++ b/chromeipass/manifest.json @@ -9,6 +9,12 @@ "128": "icons/keepass_128x128.png" }, + "applications": { + "gecko": { + "id": "chromeipass@addons.brandt.tech" + } + }, + "browser_action": { "default_icon": { "19": "icons/19x19/icon_normal_blue_19x19.png",