mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-22 16:29:09 +01:00
convert some content scripts to ts
This commit is contained in:
parent
4fe710f8e7
commit
898fa7a095
@ -1,5 +1,5 @@
|
|||||||
document.addEventListener('DOMContentLoaded', (event) => {
|
document.addEventListener('DOMContentLoaded', (event) => {
|
||||||
let pageHref = null;
|
let pageHref: string = null;
|
||||||
const isSafari = (typeof safari !== 'undefined') && navigator.userAgent.indexOf(' Safari/') !== -1 &&
|
const isSafari = (typeof safari !== 'undefined') && navigator.userAgent.indexOf(' Safari/') !== -1 &&
|
||||||
navigator.userAgent.indexOf('Chrome') === -1;
|
navigator.userAgent.indexOf('Chrome') === -1;
|
||||||
|
|
||||||
@ -7,9 +7,9 @@ document.addEventListener('DOMContentLoaded', (event) => {
|
|||||||
const responseCommand = 'autofillerAutofillOnPageLoadEnabledResponse';
|
const responseCommand = 'autofillerAutofillOnPageLoadEnabledResponse';
|
||||||
safari.self.tab.dispatchMessage('bitwarden', {
|
safari.self.tab.dispatchMessage('bitwarden', {
|
||||||
command: 'bgGetDataForTab',
|
command: 'bgGetDataForTab',
|
||||||
responseCommand: responseCommand
|
responseCommand: responseCommand,
|
||||||
});
|
});
|
||||||
safari.self.addEventListener('message', (msgEvent) => {
|
safari.self.addEventListener('message', (msgEvent: any) => {
|
||||||
const msg = msgEvent.message;
|
const msg = msgEvent.message;
|
||||||
if (msg.command === responseCommand && msg.data.autofillEnabled === true) {
|
if (msg.command === responseCommand && msg.data.autofillEnabled === true) {
|
||||||
setInterval(doFillIfNeeded, 500);
|
setInterval(doFillIfNeeded, 500);
|
||||||
@ -18,8 +18,8 @@ document.addEventListener('DOMContentLoaded', (event) => {
|
|||||||
return;
|
return;
|
||||||
} else {
|
} else {
|
||||||
const enabledKey = 'enableAutoFillOnPageLoad';
|
const enabledKey = 'enableAutoFillOnPageLoad';
|
||||||
chrome.storage.local.get(enabledKey, (obj) => {
|
chrome.storage.local.get(enabledKey, (obj: any) => {
|
||||||
if (obj && obj[enabledKey] === true) {
|
if (obj != null && obj[enabledKey] === true) {
|
||||||
setInterval(doFillIfNeeded, 500);
|
setInterval(doFillIfNeeded, 500);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -30,7 +30,7 @@ document.addEventListener('DOMContentLoaded', (event) => {
|
|||||||
pageHref = window.location.href;
|
pageHref = window.location.href;
|
||||||
const msg = {
|
const msg = {
|
||||||
command: 'bgCollectPageDetails',
|
command: 'bgCollectPageDetails',
|
||||||
sender: 'autofiller'
|
sender: 'autofiller',
|
||||||
};
|
};
|
||||||
|
|
||||||
if (isSafari) {
|
if (isSafari) {
|
@ -1,450 +0,0 @@
|
|||||||
document.addEventListener('DOMContentLoaded', (event) => {
|
|
||||||
if (window.location.hostname.indexOf('vault.bitwarden.com') > -1) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var pageDetails = [],
|
|
||||||
formData = [],
|
|
||||||
barType = null,
|
|
||||||
pageHref = null,
|
|
||||||
observer = null,
|
|
||||||
domObservationCollectTimeout = null,
|
|
||||||
collectIfNeededTimeout = null,
|
|
||||||
observeDomTimeout = null,
|
|
||||||
iframed = isIframed(),
|
|
||||||
submitButtonNames = ['log in', 'sign in', 'login', 'go', 'submit', 'continue', 'next'],
|
|
||||||
notificationBarData = null,
|
|
||||||
isSafari = (typeof safari !== 'undefined') && navigator.userAgent.indexOf(' Safari/') !== -1 &&
|
|
||||||
navigator.userAgent.indexOf('Chrome') === -1;
|
|
||||||
|
|
||||||
if (isSafari) {
|
|
||||||
const responseCommand = 'notificationBarDataResponse';
|
|
||||||
safari.self.tab.dispatchMessage('bitwarden', {
|
|
||||||
command: 'bgGetDataForTab',
|
|
||||||
responseCommand: responseCommand
|
|
||||||
});
|
|
||||||
safari.self.addEventListener('message', (msgEvent) => {
|
|
||||||
const msg = msgEvent.message;
|
|
||||||
if (msg.command === responseCommand && msg.data) {
|
|
||||||
notificationBarData = msg.data;
|
|
||||||
if (notificationBarData.neverDomains &&
|
|
||||||
notificationBarData.neverDomains.hasOwnProperty(window.location.hostname)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (notificationBarData.disabledNotification === true) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
collectIfNeededWithTimeout();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
processMessages(msg, () => { /* do nothing on send response for Safari */ });
|
|
||||||
}, false);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
chrome.storage.local.get('neverDomains', (obj) => {
|
|
||||||
var domains = obj.neverDomains;
|
|
||||||
if (domains && domains.hasOwnProperty(window.location.hostname)) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
chrome.storage.local.get('disableAddLoginNotification', (obj) => {
|
|
||||||
if (!obj || !obj.disableAddLoginNotification) {
|
|
||||||
collectIfNeededWithTimeout();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
|
||||||
processMessages(msg, sendResponse);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function processMessages(msg, sendResponse) {
|
|
||||||
if (msg.command === 'openNotificationBar') {
|
|
||||||
if (iframed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
closeExistingAndOpenBar(msg.data.type, msg.data.typeData);
|
|
||||||
sendResponse();
|
|
||||||
return true;
|
|
||||||
} else if (msg.command === 'closeNotificationBar') {
|
|
||||||
if (iframed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
closeBar(true);
|
|
||||||
sendResponse();
|
|
||||||
return true;
|
|
||||||
} else if (msg.command === 'adjustNotificationBar') {
|
|
||||||
if (iframed) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
adjustBar(msg.data);
|
|
||||||
sendResponse();
|
|
||||||
return true;
|
|
||||||
} else if (msg.command === 'notificationBarPageDetails') {
|
|
||||||
pageDetails.push(msg.data.details);
|
|
||||||
watchForms(msg.data.forms);
|
|
||||||
sendResponse();
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function isIframed() {
|
|
||||||
try {
|
|
||||||
return window.self !== window.top;
|
|
||||||
} catch (e) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function observeDom() {
|
|
||||||
var bodies = document.querySelectorAll('body');
|
|
||||||
if (bodies && bodies.length > 0) {
|
|
||||||
observer = new window.MutationObserver((mutations) => {
|
|
||||||
if (!mutations || !mutations.length || pageHref !== window.location.href) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var doCollect = false;
|
|
||||||
for (var i = 0; i < mutations.length; i++) {
|
|
||||||
if (!mutations[i].addedNodes || !mutations[i].addedNodes.length) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var j = 0; j < mutations[i].addedNodes.length; j++) {
|
|
||||||
var addedNode = mutations[i].addedNodes[j];
|
|
||||||
if (!addedNode) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (addedNode.tagName && addedNode.tagName.toLowerCase() == 'form' &&
|
|
||||||
(!addedNode.dataset || !addedNode.dataset.bitwardenWatching)) {
|
|
||||||
doCollect = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!addedNode.querySelectorAll) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var forms = mutations[i].addedNodes[j].querySelectorAll('form:not([data-bitwarden-watching])');
|
|
||||||
if (forms && forms.length) {
|
|
||||||
doCollect = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doCollect) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (doCollect) {
|
|
||||||
if (domObservationCollectTimeout) {
|
|
||||||
clearTimeout(domObservationCollectTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
domObservationCollectTimeout = setTimeout(collect, 1000);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
observer.observe(bodies[0], { childList: true, subtree: true });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function collectIfNeededWithTimeout() {
|
|
||||||
if (collectIfNeededTimeout) {
|
|
||||||
clearTimeout(collectIfNeededTimeout);
|
|
||||||
}
|
|
||||||
collectIfNeededTimeout = setTimeout(collectIfNeeded, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
function collectIfNeeded() {
|
|
||||||
if (pageHref !== window.location.href) {
|
|
||||||
pageHref = window.location.href;
|
|
||||||
if (observer) {
|
|
||||||
observer.disconnect();
|
|
||||||
observer = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
collect();
|
|
||||||
|
|
||||||
if (observeDomTimeout) {
|
|
||||||
clearTimeout(observeDomTimeout);
|
|
||||||
}
|
|
||||||
observeDomTimeout = setTimeout(observeDom, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (collectIfNeededTimeout) {
|
|
||||||
clearTimeout(collectIfNeededTimeout);
|
|
||||||
}
|
|
||||||
collectIfNeededTimeout = setTimeout(collectIfNeeded, 1000);
|
|
||||||
}
|
|
||||||
|
|
||||||
function collect() {
|
|
||||||
sendPlatformMessage({
|
|
||||||
command: 'bgCollectPageDetails',
|
|
||||||
sender: 'notificationBar'
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function watchForms(forms) {
|
|
||||||
if (!forms || !forms.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < forms.length; i++) {
|
|
||||||
var form = null,
|
|
||||||
formId = forms[i].form ? forms[i].form.htmlID : null;
|
|
||||||
|
|
||||||
if (formId && formId !== '') {
|
|
||||||
form = document.getElementById(formId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!form) {
|
|
||||||
var index = parseInt(forms[i].form.opid.split('__')[2]);
|
|
||||||
form = document.getElementsByTagName('form')[index];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (form && form.dataset.bitwardenWatching !== '1') {
|
|
||||||
var formDataObj = {
|
|
||||||
data: forms[i],
|
|
||||||
formEl: form,
|
|
||||||
usernameEl: null,
|
|
||||||
passwordEl: null
|
|
||||||
};
|
|
||||||
locateFields(formDataObj);
|
|
||||||
formData.push(formDataObj);
|
|
||||||
listen(form);
|
|
||||||
form.dataset.bitwardenWatching = '1';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function listen(form) {
|
|
||||||
form.removeEventListener('submit', formSubmitted, false);
|
|
||||||
form.addEventListener('submit', formSubmitted, false);
|
|
||||||
var submitButton = form.querySelector(
|
|
||||||
'input[type="submit"], input[type="image"], button[type="submit"], button:not([type])');
|
|
||||||
if (submitButton) {
|
|
||||||
submitButton.removeEventListener('click', formSubmitted, false);
|
|
||||||
submitButton.addEventListener('click', formSubmitted, false);
|
|
||||||
} else {
|
|
||||||
var possibleSubmitButtons = form.querySelectorAll('a, span, button[type="button"], input[type="button"]');
|
|
||||||
for (var i = 0; i < possibleSubmitButtons.length; i++) {
|
|
||||||
var button = possibleSubmitButtons[i];
|
|
||||||
if (!button || !button.tagName) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var buttonText;
|
|
||||||
if (button.tagName.toLowerCase() === 'input') {
|
|
||||||
buttonText = button.value;
|
|
||||||
} else {
|
|
||||||
buttonText = button.innerText;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!buttonText) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
buttonText = buttonText.trim().toLowerCase();
|
|
||||||
if (submitButtonNames.indexOf(buttonText) > -1) {
|
|
||||||
button.removeEventListener('click', formSubmitted, false);
|
|
||||||
button.addEventListener('click', formSubmitted, false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function locateFields(formDataObj) {
|
|
||||||
var passwordId = formDataObj.data.password ? formDataObj.data.password.htmlID : null,
|
|
||||||
usernameId = formDataObj.data.username ? formDataObj.data.username.htmlID : null,
|
|
||||||
passwordName = formDataObj.data.password ? formDataObj.data.password.htmlName : null,
|
|
||||||
usernameName = formDataObj.data.username ? formDataObj.data.username.htmlName : null,
|
|
||||||
inputs = document.getElementsByTagName('input');
|
|
||||||
|
|
||||||
if (passwordId && passwordId !== '') {
|
|
||||||
try {
|
|
||||||
formDataObj.passwordEl = formDataObj.formEl.querySelector('#' + passwordId);
|
|
||||||
}
|
|
||||||
catch (e) { }
|
|
||||||
}
|
|
||||||
if (!formDataObj.passwordEl && passwordName !== '') {
|
|
||||||
formDataObj.passwordEl = formDataObj.formEl.querySelector('input[name="' + passwordName + '"]');
|
|
||||||
}
|
|
||||||
if (!formDataObj.passwordEl && formDataObj.passwordEl) {
|
|
||||||
formDataObj.passwordEl = inputs[formDataObj.data.password.elementNumber];
|
|
||||||
if (formDataObj.passwordEl && formDataObj.passwordEl.type !== 'password') {
|
|
||||||
formDataObj.passwordEl = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!formDataObj.passwordEl) {
|
|
||||||
formDataObj.passwordEl = formDataObj.formEl.querySelector('input[type="password"]');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (usernameId && usernameId !== '') {
|
|
||||||
try {
|
|
||||||
formDataObj.usernameEl = formDataObj.formEl.querySelector('#' + usernameId);
|
|
||||||
}
|
|
||||||
catch (e) { }
|
|
||||||
}
|
|
||||||
if (!formDataObj.usernameEl && usernameName !== '') {
|
|
||||||
formDataObj.usernameEl = formDataObj.formEl.querySelector('input[name="' + usernameName + '"]');
|
|
||||||
}
|
|
||||||
if (!formDataObj.usernameEl && formDataObj.data.username) {
|
|
||||||
formDataObj.usernameEl = inputs[formDataObj.data.username.elementNumber];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function formSubmitted(e) {
|
|
||||||
var form = null;
|
|
||||||
if (e.type === 'click') {
|
|
||||||
form = e.target.closest('form');
|
|
||||||
} else {
|
|
||||||
form = e.target;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!form || form.dataset.bitwardenProcessed === '1') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (var i = 0; i < formData.length; i++) {
|
|
||||||
if (formData[i].formEl === form) {
|
|
||||||
if (!formData[i].usernameEl || !formData[i].passwordEl) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var login = {
|
|
||||||
username: formData[i].usernameEl.value,
|
|
||||||
password: formData[i].passwordEl.value,
|
|
||||||
url: document.URL
|
|
||||||
};
|
|
||||||
|
|
||||||
if (login.username && login.username !== '' && login.password && login.password !== '') {
|
|
||||||
form.dataset.bitwardenProcessed = '1';
|
|
||||||
setTimeout(() => {
|
|
||||||
form.dataset.bitwardenProcessed = '0';
|
|
||||||
}, 500);
|
|
||||||
|
|
||||||
sendPlatformMessage({
|
|
||||||
command: 'bgAddLogin',
|
|
||||||
login: login
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeExistingAndOpenBar(type, typeData) {
|
|
||||||
var barPage = 'notification/bar.html';
|
|
||||||
switch (type) {
|
|
||||||
case 'info':
|
|
||||||
barPage = barPage + '?info=' + typeData.text;
|
|
||||||
break;
|
|
||||||
case 'warning':
|
|
||||||
barPage = barPage + '?warning=' + typeData.text;
|
|
||||||
break;
|
|
||||||
case 'error':
|
|
||||||
barPage = barPage + '?error=' + typeData.text;
|
|
||||||
break;
|
|
||||||
case 'success':
|
|
||||||
barPage = barPage + '?success=' + typeData.text;
|
|
||||||
break;
|
|
||||||
case 'add':
|
|
||||||
barPage = barPage + '?add=1';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var frame = document.getElementById('bit-notification-bar-iframe');
|
|
||||||
if (frame && frame.src.indexOf(barPage) >= 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
closeBar(false);
|
|
||||||
openBar(type, barPage);
|
|
||||||
}
|
|
||||||
|
|
||||||
function openBar(type, barPage) {
|
|
||||||
barType = type;
|
|
||||||
|
|
||||||
if (!document.body) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var barPageUrl = isSafari ? (safari.extension.baseURI + barPage) : chrome.extension.getURL(barPage);
|
|
||||||
|
|
||||||
var iframe = document.createElement('iframe');
|
|
||||||
iframe.style.cssText = 'height: 42px; width: 100%; border: 0;';
|
|
||||||
iframe.id = 'bit-notification-bar-iframe';
|
|
||||||
|
|
||||||
var frameDiv = document.createElement('div');
|
|
||||||
frameDiv.id = 'bit-notification-bar';
|
|
||||||
frameDiv.style.cssText = 'height: 42px; width: 100%; top: 0; left: 0; padding: 0; position: fixed; z-index: 2147483647; visibility: visible;';
|
|
||||||
frameDiv.appendChild(iframe);
|
|
||||||
document.body.appendChild(frameDiv);
|
|
||||||
|
|
||||||
iframe.contentWindow.location = barPageUrl;
|
|
||||||
|
|
||||||
var spacer = document.createElement('div');
|
|
||||||
spacer.id = 'bit-notification-bar-spacer';
|
|
||||||
spacer.style.cssText = 'height: 42px;';
|
|
||||||
document.body.insertBefore(spacer, document.body.firstChild);
|
|
||||||
}
|
|
||||||
|
|
||||||
function closeBar(explicitClose) {
|
|
||||||
var el = document.getElementById('bit-notification-bar');
|
|
||||||
if (el) {
|
|
||||||
el.parentElement.removeChild(el);
|
|
||||||
}
|
|
||||||
|
|
||||||
el = document.getElementById('bit-notification-bar-spacer');
|
|
||||||
if (el) {
|
|
||||||
el.parentElement.removeChild(el);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!explicitClose) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (barType) {
|
|
||||||
case 'add':
|
|
||||||
sendPlatformMessage({
|
|
||||||
command: 'bgAddClose'
|
|
||||||
});
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function adjustBar(data) {
|
|
||||||
if (data.height !== 42) {
|
|
||||||
var newHeight = data.height + 'px';
|
|
||||||
doHeightAdjustment('bit-notification-bar-iframe', newHeight);
|
|
||||||
doHeightAdjustment('bit-notification-bar', newHeight);
|
|
||||||
doHeightAdjustment('bit-notification-bar-spacer', newHeight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function doHeightAdjustment(elId, heightStyle) {
|
|
||||||
var el = document.getElementById(elId);
|
|
||||||
if (el) {
|
|
||||||
el.style.height = heightStyle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function sendPlatformMessage(msg) {
|
|
||||||
if (isSafari) {
|
|
||||||
safari.self.tab.dispatchMessage('bitwarden', msg);
|
|
||||||
} else {
|
|
||||||
chrome.runtime.sendMessage(msg);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
450
src/content/notificationBar.ts
Normal file
450
src/content/notificationBar.ts
Normal file
@ -0,0 +1,450 @@
|
|||||||
|
document.addEventListener('DOMContentLoaded', (event) => {
|
||||||
|
if (window.location.hostname.indexOf('vault.bitwarden.com') > -1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const pageDetails: any[] = [];
|
||||||
|
const formData: any[] = [];
|
||||||
|
let barType: string = null;
|
||||||
|
let pageHref: string = null;
|
||||||
|
let observer: MutationObserver = null;
|
||||||
|
let domObservationCollectTimeout: number = null;
|
||||||
|
let collectIfNeededTimeout: number = null;
|
||||||
|
let observeDomTimeout: number = null;
|
||||||
|
const inIframe = isInIframe();
|
||||||
|
const submitButtonNames = new Set(['log in', 'sign in', 'login', 'go', 'submit', 'continue', 'next']);
|
||||||
|
let notificationBarData = null;
|
||||||
|
const isSafari = (typeof safari !== 'undefined') && navigator.userAgent.indexOf(' Safari/') !== -1 &&
|
||||||
|
navigator.userAgent.indexOf('Chrome') === -1;
|
||||||
|
|
||||||
|
if (isSafari) {
|
||||||
|
const responseCommand = 'notificationBarDataResponse';
|
||||||
|
safari.self.tab.dispatchMessage('bitwarden', {
|
||||||
|
command: 'bgGetDataForTab',
|
||||||
|
responseCommand: responseCommand,
|
||||||
|
});
|
||||||
|
safari.self.addEventListener('message', (msgEvent: any) => {
|
||||||
|
const msg = msgEvent.message;
|
||||||
|
if (msg.command === responseCommand && msg.data) {
|
||||||
|
notificationBarData = msg.data;
|
||||||
|
if (notificationBarData.neverDomains &&
|
||||||
|
notificationBarData.neverDomains.hasOwnProperty(window.location.hostname)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (notificationBarData.disabledNotification === true) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
collectIfNeededWithTimeout();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
processMessages(msg, () => { /* do nothing on send response for Safari */ });
|
||||||
|
}, false);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
chrome.storage.local.get('neverDomains', (ndObj: any) => {
|
||||||
|
const domains = ndObj.neverDomains;
|
||||||
|
if (domains != null && domains.hasOwnProperty(window.location.hostname)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
chrome.storage.local.get('disableAddLoginNotification', (disObj: any) => {
|
||||||
|
if (disObj == null || !disObj.disableAddLoginNotification) {
|
||||||
|
collectIfNeededWithTimeout();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
chrome.runtime.onMessage.addListener((msg: any, sender: any, sendResponse: Function) => {
|
||||||
|
processMessages(msg, sendResponse);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function processMessages(msg: any, sendResponse: Function) {
|
||||||
|
if (msg.command === 'openNotificationBar') {
|
||||||
|
if (inIframe) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
closeExistingAndOpenBar(msg.data.type, msg.data.typeData);
|
||||||
|
sendResponse();
|
||||||
|
return true;
|
||||||
|
} else if (msg.command === 'closeNotificationBar') {
|
||||||
|
if (inIframe) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
closeBar(true);
|
||||||
|
sendResponse();
|
||||||
|
return true;
|
||||||
|
} else if (msg.command === 'adjustNotificationBar') {
|
||||||
|
if (inIframe) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
adjustBar(msg.data);
|
||||||
|
sendResponse();
|
||||||
|
return true;
|
||||||
|
} else if (msg.command === 'notificationBarPageDetails') {
|
||||||
|
pageDetails.push(msg.data.details);
|
||||||
|
watchForms(msg.data.forms);
|
||||||
|
sendResponse();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isInIframe() {
|
||||||
|
try {
|
||||||
|
return window.self !== window.top;
|
||||||
|
} catch {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function observeDom() {
|
||||||
|
const bodies = document.querySelectorAll('body');
|
||||||
|
if (bodies && bodies.length > 0) {
|
||||||
|
observer = new MutationObserver((mutations) => {
|
||||||
|
if (mutations == null || mutations.length === 0 || pageHref !== window.location.href) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let doCollect = false;
|
||||||
|
for (let i = 0; i < mutations.length; i++) {
|
||||||
|
const mutation = mutations[i];
|
||||||
|
if (mutation.addedNodes == null || mutation.addedNodes.length === 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let j = 0; j < mutation.addedNodes.length; j++) {
|
||||||
|
const addedNode: any = mutation.addedNodes[j];
|
||||||
|
if (addedNode == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (addedNode.tagName != null && addedNode.tagName.toLowerCase() === 'form' &&
|
||||||
|
(addedNode.dataset == null || !addedNode.dataset.bitwardenWatching)) {
|
||||||
|
doCollect = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!addedNode.querySelectorAll) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const forms = addedNode.querySelectorAll('form:not([data-bitwarden-watching])');
|
||||||
|
if (forms != null && forms.length > 0) {
|
||||||
|
doCollect = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doCollect) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (doCollect) {
|
||||||
|
if (domObservationCollectTimeout != null) {
|
||||||
|
window.clearTimeout(domObservationCollectTimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
domObservationCollectTimeout = window.setTimeout(collect, 1000);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
observer.observe(bodies[0], { childList: true, subtree: true });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function collectIfNeededWithTimeout() {
|
||||||
|
if (collectIfNeededTimeout != null) {
|
||||||
|
window.clearTimeout(collectIfNeededTimeout);
|
||||||
|
}
|
||||||
|
collectIfNeededTimeout = window.setTimeout(collectIfNeeded, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function collectIfNeeded() {
|
||||||
|
if (pageHref !== window.location.href) {
|
||||||
|
pageHref = window.location.href;
|
||||||
|
if (observer) {
|
||||||
|
observer.disconnect();
|
||||||
|
observer = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
collect();
|
||||||
|
|
||||||
|
if (observeDomTimeout != null) {
|
||||||
|
window.clearTimeout(observeDomTimeout);
|
||||||
|
}
|
||||||
|
observeDomTimeout = window.setTimeout(observeDom, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (collectIfNeededTimeout != null) {
|
||||||
|
window.clearTimeout(collectIfNeededTimeout);
|
||||||
|
}
|
||||||
|
collectIfNeededTimeout = window.setTimeout(collectIfNeeded, 1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
function collect() {
|
||||||
|
sendPlatformMessage({
|
||||||
|
command: 'bgCollectPageDetails',
|
||||||
|
sender: 'notificationBar',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function watchForms(forms: any[]) {
|
||||||
|
if (forms == null || forms.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
forms.forEach((f: any) => {
|
||||||
|
const formId: string = f.form != null ? f.form.htmlID : null;
|
||||||
|
let formEl: HTMLElement = null;
|
||||||
|
if (formId != null && formId !== '') {
|
||||||
|
formEl = document.getElementById(formId);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formEl == null) {
|
||||||
|
const index = parseInt(f.form.opid.split('__')[2], null);
|
||||||
|
formEl = document.getElementsByTagName('form')[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (formEl != null && formEl.dataset.bitwardenWatching !== '1') {
|
||||||
|
const formDataObj: any = {
|
||||||
|
data: f,
|
||||||
|
formEl: formEl,
|
||||||
|
usernameEl: null,
|
||||||
|
passwordEl: null,
|
||||||
|
};
|
||||||
|
locateFields(formDataObj);
|
||||||
|
formData.push(formDataObj);
|
||||||
|
listen(formEl);
|
||||||
|
formEl.dataset.bitwardenWatching = '1';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function listen(form: HTMLElement) {
|
||||||
|
form.removeEventListener('submit', formSubmitted, false);
|
||||||
|
form.addEventListener('submit', formSubmitted, false);
|
||||||
|
const submitButton = form.querySelector('input[type="submit"], input[type="image"], ' +
|
||||||
|
'button[type="submit"], button:not([type])');
|
||||||
|
if (submitButton != null) {
|
||||||
|
submitButton.removeEventListener('click', formSubmitted, false);
|
||||||
|
submitButton.addEventListener('click', formSubmitted, false);
|
||||||
|
} else {
|
||||||
|
const possibleSubmitButtons = form.querySelectorAll('a, span, button[type="button"], ' +
|
||||||
|
'input[type="button"]') as NodeListOf<HTMLElement>;
|
||||||
|
possibleSubmitButtons.forEach((button) => {
|
||||||
|
if (button == null || button.tagName == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let buttonText: string = null;
|
||||||
|
if (button.tagName.toLowerCase() === 'input') {
|
||||||
|
buttonText = (button as HTMLInputElement).value;
|
||||||
|
} else {
|
||||||
|
buttonText = button.innerText;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buttonText == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
buttonText = buttonText.trim().toLowerCase();
|
||||||
|
if (submitButtonNames.has(buttonText)) {
|
||||||
|
button.removeEventListener('click', formSubmitted, false);
|
||||||
|
button.addEventListener('click', formSubmitted, false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function locateFields(formDataObj: any) {
|
||||||
|
const passwordId: string = formDataObj.data.password != null ? formDataObj.data.password.htmlID : null;
|
||||||
|
const usernameId: string = formDataObj.data.username != null ? formDataObj.data.username.htmlID : null;
|
||||||
|
const passwordName: string = formDataObj.data.password != null ? formDataObj.data.password.htmlName : null;
|
||||||
|
const usernameName: string = formDataObj.data.username != null ? formDataObj.data.username.htmlName : null;
|
||||||
|
const inputs = document.getElementsByTagName('input');
|
||||||
|
|
||||||
|
if (passwordId != null && passwordId !== '') {
|
||||||
|
try {
|
||||||
|
formDataObj.passwordEl = formDataObj.formEl.querySelector('#' + passwordId);
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
if (formDataObj.passwordEl == null && passwordName !== '') {
|
||||||
|
formDataObj.passwordEl = formDataObj.formEl.querySelector('input[name="' + passwordName + '"]');
|
||||||
|
}
|
||||||
|
if (formDataObj.passwordEl == null && formDataObj.passwordEl != null) {
|
||||||
|
formDataObj.passwordEl = inputs[formDataObj.data.password.elementNumber];
|
||||||
|
if (formDataObj.passwordEl != null && formDataObj.passwordEl.type !== 'password') {
|
||||||
|
formDataObj.passwordEl = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (formDataObj.passwordEl == null) {
|
||||||
|
formDataObj.passwordEl = formDataObj.formEl.querySelector('input[type="password"]');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (usernameId != null && usernameId !== '') {
|
||||||
|
try {
|
||||||
|
formDataObj.usernameEl = formDataObj.formEl.querySelector('#' + usernameId);
|
||||||
|
} catch { }
|
||||||
|
}
|
||||||
|
if (formDataObj.usernameEl == null && usernameName !== '') {
|
||||||
|
formDataObj.usernameEl = formDataObj.formEl.querySelector('input[name="' + usernameName + '"]');
|
||||||
|
}
|
||||||
|
if (formDataObj.usernameEl == null && formDataObj.data.username != null) {
|
||||||
|
formDataObj.usernameEl = inputs[formDataObj.data.username.elementNumber];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function formSubmitted(e: Event) {
|
||||||
|
let form: HTMLFormElement = null;
|
||||||
|
if (e.type === 'click') {
|
||||||
|
form = (e.target as HTMLElement).closest('form');
|
||||||
|
} else {
|
||||||
|
form = e.target as HTMLFormElement;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (form == null || form.dataset.bitwardenProcessed === '1') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < formData.length; i++) {
|
||||||
|
if (formData[i].formEl !== form) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (formData[i].usernameEl == null || formData[i].passwordEl == null) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const login = {
|
||||||
|
username: formData[i].usernameEl.value,
|
||||||
|
password: formData[i].passwordEl.value,
|
||||||
|
url: document.URL,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (login.username != null && login.username !== '' && login.password != null && login.password !== '') {
|
||||||
|
form.dataset.bitwardenProcessed = '1';
|
||||||
|
window.setTimeout(() => {
|
||||||
|
form.dataset.bitwardenProcessed = '0';
|
||||||
|
}, 500);
|
||||||
|
|
||||||
|
sendPlatformMessage({
|
||||||
|
command: 'bgAddLogin',
|
||||||
|
login: login,
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeExistingAndOpenBar(type: string, typeData: any) {
|
||||||
|
let barPage = 'notification/bar.html';
|
||||||
|
switch (type) {
|
||||||
|
case 'info':
|
||||||
|
barPage = barPage + '?info=' + typeData.text;
|
||||||
|
break;
|
||||||
|
case 'warning':
|
||||||
|
barPage = barPage + '?warning=' + typeData.text;
|
||||||
|
break;
|
||||||
|
case 'error':
|
||||||
|
barPage = barPage + '?error=' + typeData.text;
|
||||||
|
break;
|
||||||
|
case 'success':
|
||||||
|
barPage = barPage + '?success=' + typeData.text;
|
||||||
|
break;
|
||||||
|
case 'add':
|
||||||
|
barPage = barPage + '?add=1';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
const frame = document.getElementById('bit-notification-bar-iframe') as HTMLIFrameElement;
|
||||||
|
if (frame != null && frame.src.indexOf(barPage) >= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
closeBar(false);
|
||||||
|
openBar(type, barPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
function openBar(type: string, barPage: string) {
|
||||||
|
barType = type;
|
||||||
|
|
||||||
|
if (document.body == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const barPageUrl: string = isSafari ? (safari.extension.baseURI + barPage) : chrome.extension.getURL(barPage);
|
||||||
|
|
||||||
|
const iframe = document.createElement('iframe');
|
||||||
|
iframe.style.cssText = 'height: 42px; width: 100%; border: 0;';
|
||||||
|
iframe.id = 'bit-notification-bar-iframe';
|
||||||
|
|
||||||
|
const frameDiv = document.createElement('div');
|
||||||
|
frameDiv.id = 'bit-notification-bar';
|
||||||
|
frameDiv.style.cssText = 'height: 42px; width: 100%; top: 0; left: 0; padding: 0; position: fixed; ' +
|
||||||
|
'z-index: 2147483647; visibility: visible;';
|
||||||
|
frameDiv.appendChild(iframe);
|
||||||
|
document.body.appendChild(frameDiv);
|
||||||
|
|
||||||
|
(iframe.contentWindow.location as any) = barPageUrl;
|
||||||
|
|
||||||
|
const spacer = document.createElement('div');
|
||||||
|
spacer.id = 'bit-notification-bar-spacer';
|
||||||
|
spacer.style.cssText = 'height: 42px;';
|
||||||
|
document.body.insertBefore(spacer, document.body.firstChild);
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeBar(explicitClose: boolean) {
|
||||||
|
const barEl = document.getElementById('bit-notification-bar');
|
||||||
|
if (barEl != null) {
|
||||||
|
barEl.parentElement.removeChild(barEl);
|
||||||
|
}
|
||||||
|
|
||||||
|
const spacerEl = document.getElementById('bit-notification-bar-spacer');
|
||||||
|
if (spacerEl) {
|
||||||
|
spacerEl.parentElement.removeChild(spacerEl);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!explicitClose) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (barType) {
|
||||||
|
case 'add':
|
||||||
|
sendPlatformMessage({
|
||||||
|
command: 'bgAddClose',
|
||||||
|
});
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function adjustBar(data: any) {
|
||||||
|
if (data != null && data.height !== 42) {
|
||||||
|
const newHeight = data.height + 'px';
|
||||||
|
doHeightAdjustment('bit-notification-bar-iframe', newHeight);
|
||||||
|
doHeightAdjustment('bit-notification-bar', newHeight);
|
||||||
|
doHeightAdjustment('bit-notification-bar-spacer', newHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function doHeightAdjustment(elId: string, heightStyle: string) {
|
||||||
|
const el = document.getElementById(elId);
|
||||||
|
if (el != null) {
|
||||||
|
el.style.height = heightStyle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function sendPlatformMessage(msg: any) {
|
||||||
|
if (isSafari) {
|
||||||
|
safari.self.tab.dispatchMessage('bitwarden', msg);
|
||||||
|
} else {
|
||||||
|
chrome.runtime.sendMessage(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
@ -160,8 +160,8 @@ const config = {
|
|||||||
'popup/main': './src/popup/main.ts',
|
'popup/main': './src/popup/main.ts',
|
||||||
'background': './src/background.ts',
|
'background': './src/background.ts',
|
||||||
'content/autofill': './src/content/autofill.js',
|
'content/autofill': './src/content/autofill.js',
|
||||||
'content/autofiller': './src/content/autofiller.js',
|
'content/autofiller': './src/content/autofiller.ts',
|
||||||
'content/notificationBar': './src/content/notificationBar.js',
|
'content/notificationBar': './src/content/notificationBar.ts',
|
||||||
'content/shortcuts': './src/content/shortcuts.js',
|
'content/shortcuts': './src/content/shortcuts.js',
|
||||||
'notification/bar': './src/notification/bar.js',
|
'notification/bar': './src/notification/bar.js',
|
||||||
'downloader/downloader': './src/downloader/downloader.ts',
|
'downloader/downloader': './src/downloader/downloader.ts',
|
||||||
|
Loading…
Reference in New Issue
Block a user