fingerprintjs not loading in chrome extension - javascript

I am trying to load fingerprintjs in my chrome extension and for some reason it is not loading.
The documentation says to use this approach, which works fine in standalone web sites, just not in chrome extensions
<script>
function initFingerprintJS() {
FingerprintJS.load().then(fp => {
// The FingerprintJS agent is ready.
// Get a visitor identifier when you'd like to.
fp.get().then(result => {
// This is the visitor identifier:
const visitorId = result.visitorId;
console.log("visitorId", visitorId);
});
});
}
</script>
<script async src="fp.min.js" onload="initFingerprintJS();"></script>
For chrome extension I added created a JS file initFingerprint.js that holds the init code like so:
var visitorId = null; //will hold the actual fingerprint
function initFingerprintJS() {
console.log("inside initFingerprintJS");
FingerprintJS.load().then(fp => {
console.log("loaded initFingerprintJS");
fp.get().then(result => {
console.log("initFingerprintJS got result", result)
visitorId = result.visitorId; // This is the visitor identifier
console.log("visitorId", visitorId);
});
});
}
initFingerprintJS();
In background.html, I added this:
<script async src="fp.min.js"></script>
<script async src="initFingerprint.js"></script>
I have tried with async in there and not in there, but still no luck. This line will print, but none of the other lines below it.
inside initFingerprintJS
What am I doing wrong? I appreciate any help. thank you

Remove <script> tag for fp.min.js from the html and create the script element yourself in initFingerprint.js so you can use the onload event directly:
loadScript('fp.min.js').then(initFingerprintJS);
function loadScript(url) {
return new Promise((resolve, reject) => {
const el = document.createElement('script');
el.onload = resolve;
el.onerror = reject;
el.src = url;
document.documentElement.appendChild(el);
});
}
async function initFingerprintJS() {
visitorId = await (await FingerprintJS.load()).get();
console.log('visitorId', visitorId);
}

Related

Button Event not Triggering After Ajax Call

I'm working on a Kirby site and I followed the 'Load More' tutorial for a website blog I am working on. Everything is working; however, I am also using an AJAX call for my parent pages. (I'm using swup library).
Normally, I would bind an event after an AJAX request to the document using .on() in jQuery; however, I can't seem to figure out how to do the same within the template/new.js file in pure Javascript.
Here's my code as per the tutorial:
const element = document.querySelector('.articles');
const button = document.querySelector('.load-more');
let page = parseInt(element.getAttribute('data-page'));
console.log(element.getAttribute('data-page'))
const fetchArticles = async () => {
let url = 'news.json/page:2';
try {
const response = await fetch(url);
const {
html,
more
} = await response.json();
button.hidden = !more;
element.innerHTML += html;
page++;
} catch (error) {
console.log('Fetch error: ', error);
}
}
button.addEventListener('click', fetchArticles);
Any help is greatly appreciated.

Load new web page without reloading loading scripts errors

I Am trying to make a web app load new pages without reloading in the browser. Some pages work fine while other raise errors since scripts are not loaded. The following code is the one to load a new page
function loadPage(target, savePushState){
$(".page-content").fadeOut(function(){
$('body').load(target, function(data) {
$(".page-content").fadeIn(function(){
var newTitle = $(data).filter('title').text();
document.title = newTitle;
if(savePushState){
var obj = { Title: newTitle, Url: target };
window.history.pushState(obj, obj.Title, obj.Url);
}
});
});
});
}
The page links with remote scripts specifically datatbles.net occasionally don't work.
Any tweaks to make it run smooth please.
The problem you've got is you haven't really thought about dependency management. You've got an elegant way of changing page, but no method to handle the requirements of those pages in terms of CSS/JS.
There's various tutorials and even frameworks that manage this sort of thing. One thing you could do is to declare each valid route's (i.e. page's) dependencies up front, and then load them when you call the route.
Since your loaded HTML seems to depend on JS before it can properly appear, we'll force the insertion of the HTML to wait for any and all JS dependencies to load.
const routes = {
'page1.html': {
js: ['https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js'],
css: ['https://guidecore.xyz/assets/css/main.css']
}
/* ... */
};
const pageContent = $('.page-content'); //<-- let's cache this element
function loadPage(target, savePushState) {
pageContent.fadeOut(function() {
//let's load dependencies
const promises = [];
['js', 'css'].forEach(type => {
routes[target] && (routes[target][type] ?? []).forEach(uri => {
if (type == 'js')
promises.push(fetch(uri)
.then(response => response.text())
.then(code => {
const el = document.createElement('script');
el.textContent = code;
document.body.appendChild(el);
})
);
else {
const el = document.createElement('link');
el.href = uri;
el.rel = 'stylesheet';
document.head.appendChild(el);
}
});
});
//wait for JS dependencies to load before we get new HTML
Promise.all(promises).then(() => {
$('body').load(target, function(data) {
pageContent.fadeIn(function(){
let newTitle = $(data).filter('title').text();
document.title = newTitle;
if(savePushState) {
var obj = { Title: newTitle, Url: target };
window.history.pushState(obj, obj.Title, obj.Url);
}
});
});
});
});
}
loadPage('page1.html');

Sending message from background script to content script (multiple browsers)

I have a working prototype of an extension that works on Chrome but when I try to run it on Firefox i get the following error:
Unchecked lastError value: Error: Could not establish connection. Receiving end does not exist.
I use this code to differentiate between browsers:
window.namespace = (function () {
return window.msBrowser ||
window.browser ||
window.chrome;
})();
the following part is to detect when the user clicks on the extension icon (so that I know to activate it):
let show_floater = false; // to know if extension should be active
window.namespace.browserAction.onClicked.addListener(function(tab) {
buttonClicked(tab);
});
function buttonClicked(tab) {
show_floater = !show_floater;
console.log('coding intensifies');
// Send message to content_script of tab.id
window.namespace.tabs.sendMessage(tab.id, show_floater); // <-- ERROR IS HERE
}
All this code is in my background script.
The handling of the message in my content script is as follows
window.namespace.runtime.onMessage.addListener(gotMessage);
let injected = false;
function gotMessage(show_floater, sender, sendResponse) {
// Here I just do stuff
console.log("I'm working here!");
}
Online I saw that people that had this problem usually did not include <all_urls> in the manifest. In my case I already had that so I'm kinda lost here. From my understanding both Chrome and Firefox should use the same methods to send and receive messages. Is my way of distinguishing between browsers flawed?
CHANGES
Here I found a solution.
Background:
chrome.browserAction.onClicked.addListener(function (event) {
chrome.tabs.executeScript(null, {
file: 'js/content.js', /* my content script */ }, () => {
connect() //this is where I call my function to establish a
connection });
});
});
function connect() {
chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
const port = chrome.tabs.connect(tabs[0].id);
show_floater = !show_floater;
port.postMessage(show_floater);
// port.onMessage.addListener((response) => {
// html = response.html;
// title = response.title;
// description = response.description;
// });
});
contentscript:
chrome.runtime.onConnect.addListener((port) => {
port.onMessage.addListener((show_floater) => {
else if (!injected) {
injected = true;
let link = document.createElement("link");
link.className = 'beebole_css';
link.href = "https://localhost/css/test.css";
link.type = "text/css";
link.rel = "stylesheet";
document.querySelector("head").appendChild(link);
let s = document.createElement("script");
s.className = 'beebole_js';
s.src = "https://localhost/js/test.js";
s.type = 'text/javascript';
// document.body.appendChild(s);
document.querySelector('body').appendChild(s);
}
});
});
Again, this code works perfectly on Chrome but on Firefox it give the following error:
Loading failed for the <script> with source “https://localhost/js/test.js”.
I suggest you use https://github.com/mozilla/webextension-polyfill for cross browser compatibility.

How do I load a page and immediately edit the DOM in electron?

I'm trying to create a markdown editor.
So far: I have loaded the index page. I'm using fs.readdir to get the titles of all the markdown files and display them in the sidebar. Then, on clicking on of these title #content get's the content.
module.exports = (win) => {
fs.readdir( './data', (err, data) =>{
data.map(title => {
if(title.split('.md').length==2){
el = document.createElement("li"); // get gave it the title ..
el.addEventListener('click', function(e){
fs.readFile(`./data/${title}`, (err, data) => {
document.getElementById('content').innerHTML = data;
});
})
document.getElementById('titles').appendChild(el) // title are on the page
The problem is when I introduce another page
I have a preferences page
win.loadURL(path.join('file://', __dirname, '../static/preferences.html'))
It has the same sidebar, hence I import the same code to get the titles. But now when I click one of the links, I don't want document.getElementById('content').innerHTML = data; but I want to load the index page and then inject the content
So far I tried this
const checkPageState = (pageName, callback) => {
if(pageName === "preferences"){
ipcRenderer.send(GO_TO_PAGE, 'index')
}
setTimeout(callback(), 1000);
}
...
el.addEventListener('click', function(e){
checkPageState(win, ()=>{
fs.readFile(`./data/${title}`, (err, data) => {
if (err) throw err;
fileDir = `./data/${title}`;
document.getElementById('content').innerHTML = data;
});
})
})
My thinking was ipcRenderer.send(GO_TO_PAGE, 'index') would load the index page (which it does) when wait for a bit and then inject the data into the index page. It doesn't!
How can I do this?
I recently tried to do this as well and it was kinda tricky but I found something that worked:
In electron when it tries to go to another page I stop it from going to it with:
win.webContents.on('will-navigate', function (evt, url) {
evt.preventDefault();
win.webContents.executeJavaScript('makeHiddenPageIframe("' + url + '");');
});
Then it calls the makeHiddenPageIframe function defined on the page.
Then in the page I define the makeHiddenPageIframe function:
function makeHiddenPageIframe (url) {
var hiddenPage = document.createElement("iframe");
hiddenPage.setAttribute("src", url);
hiddenPage.style.display = 'none';
document.body.appendChild(hiddenPage);
hiddenPage.onload = function () {
var frameDocument = hiddenPage.document;
if (hiddenPage.contentDocument) {
frameDocument = hiddenPage.contentDocument;
} else if (hiddenPage.contentWindow) {
frameDocument = hiddenPage.contentWindow.document;
}
document.open();
document.write(frameDocument.documentElement.innerHTML);
document.close();
window.history.pushState("", document.title, url.replace('https://' + window.location.hostname, ''));
}
}
This then makes a iframe and loads the page in there then once it has loaded copy all the html from the iframe to the parent window so it seems like the switch happened instantly.
Also the window.history.pushState thing at the bottom was when you overwrite the html the url stays the same so when you reload it goes back to the original page but the window.history.pushState changes the url without reloading the page.
Any form of navigation will do the iframe load so you would keep your win.loadURL( to go to another markdown page.
The 'will-navigate' event docs.
window.history.pushState ref.
I hope this helps :)

Listening for Automatically-Triggered Client Events with page.on('customEvent', fn)

This gist seems to cover what I want to do, but it appears to be a thought experiment, rather than working code. In any case, I'm having trouble getting it to work for me.
I'm opening a page in PhantomJs that loads a JavaScript library and starts a process. When the process completes, that library triggers an event within the context of the instance object. I'd like to either
(a) set up PhantomJS to listen for the right event in the instance object in the client page
OR
(b) add some code to the client page that "bubbles-up" the event to window and set up PhantomJS to listen for that.
Here's what I've tried for option B.
client.html:
<html>
<body>
<script src='https://example.com/library.js'></script>
<script>
function sendWindowEvent() {
// I've also tried document, top.parent, etc.
window.dispatchEvent( new CustomEvent('myEvent', {
detail: {
message: "Hello World!",
time: new Date(),
},
bubbles: true,
cancelable: true
}));
}
var instance = new myLibrary.constructor();
instance.addEventListener("onInitialized", sendWindowEvent);
instance.start();
</script>
</body>
</html>
In node.js app:
const headlessBrowser = await phantom.create();
const page = await headlessBrowser.createPage();
await page.on('onResourceRequested', (requestData) => {
console.info('Requesting', requestData.url); // displays http://localhost:1337/client.html & https://example.com/library.js
});
await page.on('myEvent', async (evt) => {
console.log('event detected:', evt); // never triggered
});
const openStatus = await page.open('http://localhost:1337/client.html');
console.log('phantom status:', openStatus); // displays true
Any ideas on what I'm missing? Is this not a supported feature? Thanks in advance.
page.on event listeners are responding to specific technical events generated by PhantomJS, not by its target page. To receive native page events you will have to subscribe to them in the browser context:
await page.evaluate(function(){
window.addEventListener("myEvent", function(e){ console.log(e)})
});
Be sure to subscribe to page.onConsoleMessage callback to get that message.
window.callPhantom() was what I was looking for. Documentation is here.
client.html:
<html>
<body>
<script src='https://example.com/library.js'></script>
<script>
function sendWindowEvent() {
if (typeof window.callPhantom === 'function') {
window.callPhantom({hello: 'world'});
}
}
var instance = new myLibrary.constructor();
instance.addEventListener("onInitialized", sendWindowEvent);
instance.start();
</script>
</body>
</html>
In node.js app:
const headlessBrowser = await phantom.create();
const page = await headlessBrowser.createPage();
page.on('onCallback', data => {
console.log('CALLBACK: ' + JSON.stringify(data)); // Prints 'CALLBACK: {"hello":"world"}'
});
page.open('http://localhost:1337/client.html');

Categories