diff --git a/src/background.js b/src/background.js index e3eca53e871..5d2949fee12 100644 --- a/src/background.js +++ b/src/background.js @@ -11,13 +11,46 @@ var autofillService = new AutofillService(); var passwordGenerationService = new PasswordGenerationService(); var appIdService = new AppIdService(); -chrome.runtime.onInstalled.addListener(function (details) { - ga('send', { - hitType: 'event', - eventAction: 'onInstalled ' + details.reason - }); +chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) { + if (msg.command === 'loggedOut') { + setIcon(true); + refreshBadgeAndMenu(); + } + else if (msg.command === 'loggedIn') { + setIcon(false); + } + else if (msg.command === 'syncCompleted' && msg.successfully) { + setTimeout(refreshBadgeAndMenu, 2000); + } }); +userService.isAuthenticated(function (isAuthenticated) { + setIcon(!isAuthenticated); +}); + +function setIcon(grayedOut) { + var suffix = ''; + if (grayedOut) { + suffix = '_gray'; + } + + chrome.browserAction.setIcon({ + path: { + '19': 'images/icon19' + suffix + '.png', + '38': 'images/icon38' + suffix + '.png', + } + }); +} + +if (chrome.runtime.onInstalled) { + chrome.runtime.onInstalled.addListener(function (details) { + ga('send', { + hitType: 'event', + eventAction: 'onInstalled ' + details.reason + }); + }); +} + function buildContextMenu() { chrome.contextMenus.removeAll(); chrome.contextMenus.create({ @@ -44,23 +77,16 @@ function buildContextMenu() { chrome.tabs.onActivated.addListener(function (activeInfo) { buildContextMenu(); - chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { - var tab = null; - if (tabs.length > 0) { - tab = tabs[0]; - } - - if (!tab || !tab.url) { - return; - } - - buildContextMenuOptions(tab.url); - }); + refreshBadgeAndMenu(); }); var loadedMenu = false; chrome.tabs.onReplaced.addListener(function (addedTabId, removedTabId) { - chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) { + refreshBadgeAndMenu(); +}); + +function refreshBadgeAndMenu() { + chrome.tabs.query({ active: true }, function (tabs) { var tab = null; if (tabs.length > 0) { tab = tabs[0]; @@ -70,13 +96,13 @@ chrome.tabs.onReplaced.addListener(function (addedTabId, removedTabId) { return; } - loadMenuAndUpdateBadge(tab.url, tab.id, false); + buildContextMenu(); + loadMenuAndUpdateBadge(tab.url, tab.id, true); }); -}); +} chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) { buildContextMenu(); - loadMenuAndUpdateBadge(tab.url, tabId, true); }); @@ -126,7 +152,7 @@ function loadMenuAndUpdateBadge(url, tabId, loadContextMenuOptions) { else { loadNoSitesContextMenuOptions(); chrome.browserAction.setBadgeText({ - text: null, + text: '', tabId: tabId }); } diff --git a/src/content/field.js b/src/content/field.js new file mode 100644 index 00000000000..e06a488ee8c --- /dev/null +++ b/src/content/field.js @@ -0,0 +1,166 @@ +!(function () { + chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) { + if (msg.command === 'setFieldOverlayIcons') { + setFieldOverlayIcons(); + sendResponse(); + return true; + } + }); + + document.addEventListener('DOMContentLoaded', function () { + setFieldOverlayIcons(); + + var bodies = document.querySelectorAll('body'); + if (bodies.length > 0) { + observeDOM(bodies[0], function () { + setTimeout(setFieldOverlayIcons, 1000); + }); + } + }, false); + + function setFieldOverlayIcons() { + var pageDetails = JSON.parse(collect(document)); + if (pageDetails) { + var fields = []; + + for (var i = 0; i < pageDetails.fields.length; i++) { + var f = pageDetails.fields[i]; + if (f.type === 'password') { + fields.push(f); + + var fieldJustBeforePassword = null; + for (var j = 0; j < pageDetails.fields.length; j++) { + var f2 = pageDetails.fields[j]; + if ((f2.type === 'text' || f2.type === 'email') && f2.elementNumber < f.elementNumber) { + fieldJustBeforePassword = f2; + } + } + + if (!fields.includes(fieldJustBeforePassword)) { + fields.push(fieldJustBeforePassword); + } + } + } + + for (i = 0; i < fields.length; i++) { + var element = getElement(fields[i].opid); + + // TODO: insert icon for popup + + //element.style.backgroundColor = 'yellow'; + } + } + } + + // ref http://stackoverflow.com/a/14570614/1090359 + var observeDOM = (function () { + var MutationObserver = window.MutationObserver || window.WebKitMutationObserver, + eventListenerSupported = window.addEventListener; + + return function (obj, callback) { + if (MutationObserver) { + // define a new observer + var obs = new MutationObserver(function (mutations, observer) { + if (mutations[0].addedNodes.length || mutations[0].removedNodes.length) { + callback(); + } + }); + // have the observer observe foo for changes in children + obs.observe(obj, { childList: true, subtree: true }); + } + else if (eventListenerSupported) { + obj.addEventListener('DOMNodeInserted', callback, false); + obj.addEventListener('DOMNodeRemoved', callback, false); + } + } + })(); + + function getElement(opid) { + if (!opid) { + return null; + } + + var element; + try { + var inputFields = Array.prototype.slice.call(document.querySelectorAll('input')); + var opidInputFields = inputFields.filter(function (b) { + return b.opid === opid; + }); + + if (opidInputFields.length > 0) { + element = opidInputFields[0]; + + if (opidInputFields.length > 1) { + console.warn('More than one element found with opid ' + opid); + } + } + else { + var index = parseInt(opid.split('__')[1], 10); + isNaN(index) || (element = inputFields[index]) + } + } + catch (e) { + console.error('An unexpected error occurred: ' + e); + } + finally { + return element; + } + } + + /* + 1Password Extension + + Lovingly handcrafted by Dave Teare, Michael Fey, Rad Azzouz, and Roustem Karimov. + Copyright (c) 2014 AgileBits. All rights reserved. + + ================================================================================ + + Copyright (c) 2014 AgileBits Inc. + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + */ + + function collect(document, undefined) { + document.elementsByOPID={};document.addEventListener('input',function(c){!1!==c.a&&'input'===c.target.tagName.toLowerCase()&&(c.target.dataset['com.agilebits.onepassword.userEdited']='yes')},!0); + function r(c,e){function b(a,g){var d=a[g];if('string'==typeof d)return d;d=a.getAttribute(g);return'string'==typeof d?d:null}function h(a,g){if(-1===['text','password'].indexOf(g.type.toLowerCase())||!(n.test(a.value)||n.test(a.htmlID)||n.test(a.htmlName)||n.test(a.placeholder)||n.test(a['label-tag'])||n.test(a['label-data'])||n.test(a['label-aria'])))return!1;if(!a.visible)return!0;if('password'==g.type.toLowerCase())return!1;var d=g.type;w(g,!0);return d!==g.type}function p(a){switch(q(a.type)){case 'checkbox':return a.checked? + '✓':'';case 'hidden':a=a.value;if(!a||'number'!=typeof a.length)return'';254\\?]/mg,''):null;return[d?d:null,a.value]}),{options:a}):null}function s(a){var c;for(a=a.parentElement||a.parentNode;a&&'td'!=q(a.tagName);)a=a.parentElement||a.parentNode;if(!a|| + void 0===a)return null;c=a.parentElement||a.parentNode;if('tr'!=c.tagName.toLowerCase())return null;c=c.previousElementSibling;if(!c||'tr'!=(c.tagName+'').toLowerCase()||c.cells&&a.cellIndex>=c.cells.length)return null;a=c.cells[a.cellIndex];a=a.textContent||a.innerText;return a=y(a)}function t(a){var g,d=[];if(a.labels&&a.labels.length&&0c.clientWidth||10>c.clientHeight)return!1;var t=c.getClientRects();if(0===t.length)return!1;for(var f=0;fh||0>s.right)return!1;if(0>m||m>h||0>e||e>p)return!1;for(b=c.ownerDocument.elementFromPoint(m+(b.right>window.innerWidth?(window.innerWidth-m)/2:b.width/2),e+(b.bottom>window.innerHeight? + (window.innerHeight-e)/2:b.height/2));b&&b!==c&&b!==document;){if(b.tagName&&'string'===typeof b.tagName&&'label'===b.tagName.toLowerCase()&&c.labels&&0