Grayed out icon when logged out. field context script for highlighting login fields.
|
@ -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
|
||||
});
|
||||
}
|
||||
|
|
|
@ -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<a.length&&(a=a.substr(0,254)+'...SNIPPED');return a;default:return a.value}}function m(a){return a.options?(a=Array.prototype.slice.call(a.options).map(function(a){var d=a.text,d=d?q(d).replace(/\\s/mg,'').replace(/[~`!@$%^&*()\\-_+=:;'\"\\[\\]|\\\\,<.>\\?]/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&&0<a.labels.length)d=Array.prototype.slice.call(a.labels);else{a.id&&(d=d.concat(Array.prototype.slice.call(x(c,'label[for='+JSON.stringify(a.id)+']'))));if(a.name){g=
|
||||
x(c,'label[for='+JSON.stringify(a.name)+']');for(var b=0;b<g.length;b++)-1===d.indexOf(g[b])&&d.push(g[b])}for(g=a;g&&g!=c;g=g.parentNode)'label'===q(g.tagName)&&-1===d.indexOf(g)&&d.push(g)}0===d.length&&(g=a.parentNode,'dd'===g.tagName.toLowerCase()&&'dt'===g.previousElementSibling.tagName.toLowerCase()&&d.push(g.previousElementSibling));return 0<d.length?d.map(function(a){return(a.textContent||a.innerText).replace(/^\\s+/,'').replace(/\\s+$/,'').replace('\\n','').replace(/\\s{2,}/,' ')}).join(''):
|
||||
null}function f(a,c,d,b){void 0!==b&&b===d||null===d||void 0===d||(a[c]=d)}function q(a){return'string'===typeof a?a.toLowerCase():(''+a).toLowerCase()}function x(a,c){var d=[];try{d=a.querySelectorAll(c)}catch(b){}return d}var u=c.defaultView?c.defaultView:window,n=RegExp('((\\\\b|_|-)pin(\\\\b|_|-)|password|passwort|kennwort|(\\\\b|_|-)passe(\\\\b|_|-)|contraseña|senha|密码|adgangskode|hasło|wachtwoord)','i'),v=Array.prototype.slice.call(x(c,'form')).map(function(a,c){var d={},e='__form__'+c;a.opid=e;d.opid=
|
||||
e;f(d,'htmlName',b(a,'name'));f(d,'htmlID',b(a,'id'));e=b(a,'action');e=new URL(e,window.location.href);f(d,'htmlAction',e?e.href:null);f(d,'htmlMethod',b(a,'method'));return d}),F=Array.prototype.slice.call(z(c)).map(function(a,e){var d={},l='__'+e,k=-1==a.maxLength?999:a.maxLength;if(!k||'number'===typeof k&&isNaN(k))k=999;c.elementsByOPID[l]=a;a.opid=l;d.opid=l;d.elementNumber=e;f(d,'maxLength',Math.min(k,999),999);d.visible=A(a);d.viewable=B(a);f(d,'htmlID',b(a,'id'));f(d,'htmlName',b(a,'name'));
|
||||
f(d,'htmlClass',b(a,'class'));f(d,'tabindex',b(a,'tabindex'));f(d,'title',b(a,'title'));f(d,'userEdited',!!a.dataset['com.agilebits.onepassword.userEdited']);if('hidden'!=q(a.type)){f(d,'label-tag',t(a));f(d,'label-data',b(a,'data-label'));f(d,'label-aria',b(a,'aria-label'));f(d,'label-top',s(a));l=[];for(k=a;k&&k.nextSibling;){k=k.nextSibling;if(C(k))break;D(l,k)}f(d,'label-right',l.join(''));l=[];E(a,l);l=l.reverse().join('');f(d,'label-left',l);f(d,'placeholder',b(a,'placeholder'))}f(d,'rel',b(a,
|
||||
'rel'));f(d,'type',q(b(a,'type')));f(d,'value',p(a));f(d,'checked',a.checked,!1);f(d,'autoCompleteType',a.getAttribute('x-autocompletetype')||a.getAttribute('autocompletetype')||a.getAttribute('autocomplete'),'off');f(d,'disabled',a.disabled);f(d,'readonly',a.b||a.readOnly);f(d,'selectInfo',m(a));f(d,'aria-hidden','true'==a.getAttribute('aria-hidden'),!1);f(d,'aria-disabled','true'==a.getAttribute('aria-disabled'),!1);f(d,'aria-haspopup','true'==a.getAttribute('aria-haspopup'),!1);f(d,'data-unmasked',
|
||||
a.dataset.unmasked);f(d,'data-stripe',b(a,'data-stripe'));f(d,'onepasswordFieldType',a.dataset.onepasswordFieldType||a.type);f(d,'onepasswordDesignation',a.dataset.onepasswordDesignation);f(d,'onepasswordSignInUrl',a.dataset.onepasswordSignInUrl);f(d,'onepasswordSectionTitle',a.dataset.onepasswordSectionTitle);f(d,'onepasswordSectionFieldKind',a.dataset.onepasswordSectionFieldKind);f(d,'onepasswordSectionFieldTitle',a.dataset.onepasswordSectionFieldTitle);f(d,'onepasswordSectionFieldValue',a.dataset.onepasswordSectionFieldValue);
|
||||
a.form&&(d.form=b(a.form,'opid'));f(d,'fakeTested',h(d,a),!1);return d});F.filter(function(a){return a.fakeTested}).forEach(function(a){var b=c.elementsByOPID[a.opid];b.getBoundingClientRect();var d=b.value;!b||b&&'function'!==typeof b.click||b.click();w(b,!1);b.dispatchEvent(G(b,'keydown'));b.dispatchEvent(G(b,'keypress'));b.dispatchEvent(G(b,'keyup'));b.value!==d&&(b.value=d);b.click&&b.click();a.postFakeTestVisible=A(b);a.postFakeTestViewable=B(b);a.postFakeTestType=b.type;a=b.value;var d=b.ownerDocument.createEvent('HTMLEvents'),
|
||||
e=b.ownerDocument.createEvent('HTMLEvents');b.dispatchEvent(G(b,'keydown'));b.dispatchEvent(G(b,'keypress'));b.dispatchEvent(G(b,'keyup'));e.initEvent('input',!0,!0);b.dispatchEvent(e);d.initEvent('change',!0,!0);b.dispatchEvent(d);b.blur();b.value!==a&&(b.value=a)});u={documentUUID:e,title:c.title,url:u.location.href,documentUrl:c.location.href,tabUrl:u.location.href,forms:function(a){var b={};a.forEach(function(a){b[a.opid]=a});return b}(v),fields:F,collectedTimestamp:(new Date).getTime()};(v=document.querySelector('[data-onepassword-title]'))&&
|
||||
v.dataset[DISPLAY_TITLE_ATTRIBUE]&&(u.displayTitle=v.dataset.onepasswordTitle);return u};document.elementForOPID=H;function G(c,e){var b;I?(b=document.createEvent('KeyboardEvent'),b.initKeyEvent(e,!0,!1,null,!1,!1,!1,!1,0,0)):(b=c.ownerDocument.createEvent('Events'),b.initEvent(e,!0,!1),b.charCode=0,b.keyCode=0,b.which=0,b.srcElement=c,b.target=c);return b}window.LOGIN_TITLES=[/^\\W*log\\W*[oi]n\\W*$/i,/log\\W*[oi]n (?:securely|now)/i,/^\\W*sign\\W*[oi]n\\W*$/i,'continue','submit','weiter','accès','вход','connexion','entrar','anmelden','accedi','valider','登录','लॉग इन करें','change password'];
|
||||
window.LOGIN_RED_HERRING_TITLES=['already have an account','sign in with'];window.REGISTER_TITLES='register;sign up;signup;join;регистрация;inscription;regístrate;cadastre-se;registrieren;registrazione;注册;साइन अप करें'.split(';');window.SEARCH_TITLES='search find поиск найти искать recherche suchen buscar suche ricerca procurar 検索'.split(' ');window.FORGOT_PASSWORD_TITLES='forgot geändert vergessen hilfe changeemail español'.split(' ');window.REMEMBER_ME_TITLES=['remember me','rememberme','keep me signed in'];
|
||||
window.BACK_TITLES=['back','назад'];function y(c){var e=null;c&&(e=c.replace(/^\\s+|\\s+$|\\r?\\n.*$/mg,''),e=0<e.length?e:null);return e}function D(c,e){var b;b='';3===e.nodeType?b=e.nodeValue:1===e.nodeType&&(b=e.textContent||e.innerText);(b=y(b))&&c.push(b)}function C(c){var e;c&&void 0!==c?(e='select option input form textarea button table iframe body head script'.split(' '),c?(c=c?(c.tagName||'').toLowerCase():'',e=e.constructor==Array?0<=e.indexOf(c):c===e):e=!1):e=!0;return e}
|
||||
function E(c,e,b){var h;for(b||(b=0);c&&c.previousSibling;){c=c.previousSibling;if(C(c))return;D(e,c)}if(c&&0===e.length){for(h=null;!h;){c=c.parentElement||c.parentNode;if(!c)return;for(h=c.previousSibling;h&&!C(h)&&h.lastChild;)h=h.lastChild}C(h)||(D(e,h),0===e.length&&E(h,e,b+1))}}
|
||||
function A(c){var e=c;c=(c=c.ownerDocument)?c.defaultView:{};for(var b;e&&e!==document;){b=c.getComputedStyle?c.getComputedStyle(e,null):e.style;if(!b)return!0;if('none'===b.display||'hidden'==b.visibility)return!1;e=e.parentNode}return e===document}
|
||||
function B(c){var e=c.ownerDocument.documentElement,b=c.getBoundingClientRect(),h=e.scrollWidth,p=e.scrollHeight,m=b.left-e.clientLeft,e=b.top-e.clientTop,s;if(!A(c)||!c.offsetParent||10>c.clientWidth||10>c.clientHeight)return!1;var t=c.getClientRects();if(0===t.length)return!1;for(var f=0;f<t.length;f++)if(s=t[f],s.left>h||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<c.labels.length)return 0<=Array.prototype.slice.call(c.labels).indexOf(b);b=b.parentNode}return b===c}
|
||||
function H(c){var e;if(void 0===c||null===c)return null;try{var b=Array.prototype.slice.call(z(document)),h=b.filter(function(b){return b.opid==c});if(0<h.length)e=h[0],1<h.length&&console.warn('More than one element found with opid '+c);else{var p=parseInt(c.split('__')[1],10);isNaN(p)||(e=b[p])}}catch(m){console.error('An unexpected error occurred: '+m)}finally{return e}};var I='object'===typeof tabs||'object'===typeof self&&'object'===typeof self.port;function z(c){var e=[];try{e=c.querySelectorAll('input, select, button')}catch(b){}return e}function w(c,e){if(e){var b=c.value;c.focus();c.value!==b&&(c.value=b)}else c.focus()};
|
||||
return JSON.stringify(r(document, 'oneshotUUID'));
|
||||
}
|
||||
|
||||
/*
|
||||
End 1Password Extension
|
||||
*/
|
||||
})();
|
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 461 B |
After Width: | Height: | Size: 487 B |
After Width: | Height: | Size: 726 B |
After Width: | Height: | Size: 853 B |
After Width: | Height: | Size: 1006 B |
After Width: | Height: | Size: 1.8 KiB |
|
@ -23,6 +23,11 @@
|
|||
"js": [ "content/overlay.js" ],
|
||||
"matches": [ "http://*/*", "https://*/*", "file:///*" ],
|
||||
"run_at": "document_start"
|
||||
},
|
||||
{
|
||||
"js": [ "content/field.js" ],
|
||||
"matches": [ "http://*/*", "https://*/*", "file:///*" ],
|
||||
"run_at": "document_start"
|
||||
}
|
||||
],
|
||||
"background": {
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
if (response.profile) {
|
||||
userService.setUserId(response.profile.id, function () {
|
||||
userService.setEmail(response.profile.email, function () {
|
||||
chrome.runtime.sendMessage({ command: 'loggedIn' });
|
||||
deferred.resolve(response);
|
||||
});
|
||||
});
|
||||
|
@ -51,6 +52,7 @@
|
|||
tokenService.setToken(response.token, function () {
|
||||
userService.setUserId(response.profile.id, function () {
|
||||
userService.setEmail(response.profile.email, function () {
|
||||
chrome.runtime.sendMessage({ command: 'loggedIn' });
|
||||
deferred.resolve(response);
|
||||
});
|
||||
});
|
||||
|
@ -72,6 +74,7 @@
|
|||
folderService.clear(userId, function () {
|
||||
$rootScope.vaultSites = null;
|
||||
$rootScope.vaultFolders = null;
|
||||
chrome.runtime.sendMessage({ command: 'loggedOut' });
|
||||
callback();
|
||||
});
|
||||
});
|
||||
|
|