How can I use FaceDetector in a Chrome Extension? - google-chrome-extension

I have a very minimal Chrome Extension using the FaceDetector API.
However simply calling faceDetector.detect(image) fails with:
content.js:10 Uncaught (in promise) DOMException: Source would taint origin.
My content script is as follows:
;(async function(){
var faceDetector = new FaceDetector();
var image = document.querySelector("img")
var faces = await faceDetector.detect(image)
})();
My manifest.json has the following permissions:
"permissions": [
"tabs",
"<all_urls>"
],
"content_scripts": [
{
"matches": [
"http://*/*",
"https://*/*"
],
"js": ["js/content.js"],
"run_at": "document_end"
}
],
How can I make FaceDetector work on images on the page?
Update: converting to a canvas and detecting there produces a different error:
;(async function(){
console.log(`\n\n\nHi there!`)
var faceDetector = new FaceDetector();
var image = document.querySelector("img");
var canvas = document.createElement('canvas');
// Canvas is whatever size actual picture size is
canvas.width = image.naturalWidth;
canvas.height = image.naturalHeight;
console.log('Canvas full size', canvas.width, canvas.height)
// Canvas element is styled to size of image element (eg, handle retina)
canvas.style.height = `${image.height}px`;
canvas.style.width = `${image.width}px`;
console.log('Canvas size', image.width, image.height)
var context = canvas.getContext("2d");
context.drawImage(image,0,0);
console.log(`About to detect!`)
var faces = await faceDetector.detect(canvas);
// Line below fails with 'Invalid element or state.'
console.log(faces)
})();

Related

How to convert chart.js library chart to image in pure node.js without using HTML and CSS?

Currently I need a chart to display in Microsoft Bot framework. So I used chart.js
library to generate the chart. Now I want to convert it to the .png image format.So that I can display in Bot.
So How I convert chart.js chart to image in node.js without using HTML and CSS.
Here is my chart code
var Canvas = require('canvas')
, canvas = Canvas.createCanvas(500, 500)
, ctx = canvas.getContext('2d')
, Chart = require('nchart')
, fs = require('fs');
var myDoughnutChart = new Chart(ctx, {
type:'polarArea',
data:{
labels:['Strength','Skill','Health','Speed','Luck'],
datasets:[
{
label:'Points',
backgroundColor:['#f1c40f','#e67e22','#16a085','#16a085','#16a085'],
data:[10,20,55,30,10]
}
]
},
options: {
animation:{
animateScale : true
}
}
});
Here is an example of turning an nchart into a .png and base64 encoding it into an attachment:
const Canvas = require('canvas');
const Chart = require('nchart');
...
if (turnContext.activity.text == "chart")
{
let canvas = Canvas.createCanvas(500, 500);
let ctx = canvas.getContext('2d');
new Chart(ctx).Pie(
[
{
"value": 50
, "color": "#E2EAE9"
}
, {
"value": 100
, "color": "#D4CCC5"
}
, {
"value": 40
, "color": "#949FB1"
}
]
, {
scaleShowValues: true
, scaleFontSize: 24
}
);
const buf = canvas.toBuffer('image/png', { compressionLevel: 3, filters: canvas.PNG_FILTER_NONE })
const reply = { type: ActivityTypes.Message };
const base64Image = Buffer.from(buf).toString('base64');
reply.attachments = [{
name: 'architecture-resize.png',
contentType: 'image/png',
contentUrl: `data:image/png;base64,${ base64Image }`
}];
reply.text = 'Chart';
turnContext.sendActivity(reply);
}
Bot Framework Emulator:

Chrome extension - How to change text in page frames

I want to write a chrome extension that changes a text on all frames on a webpage. I wrote the following code, but with it, I can only change the text on regular pages, not frames. Any idea how to do it?
var elements = document.getElementsByTagName('*');
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
for (var j = 0; j < element.childNodes.length; j++) {
var node = element.childNodes[j];
if (node.nodeType === 3) {
var text = node.nodeValue;
var replacedText = text.replace('Hello', 'Hello2');
if (replacedText !== text) {
element.replaceChild(document.createTextNode(replacedText), node);
}
}
}
}
Set "all_frames": true in your manifest.json for content-script. (see declaration).
Example:
{
"name": "My extension",
...
"content_scripts": [
{
"matches": ["http://www.google.com/*"],
"js": ["content-script.js"],
"all_frames": true
}
],
...
}

How do I scrape a url from xml in Node.js?

My end goal is to have my app display thumbnails of the X most recent images from a given user's 500px.com account (it's a photography site). The site doesn't have an API, as far as I can tell, but it does have an rss feed for individual users, i.e. https://500px.com/janedoe/rss, that spits out xml.
Using xml2js, I can parse the xml into a js object and navigate to the "description" container that has the html that contains the url I want, like so (this is just a proof of concept using the first item in the rss feed):
var express = require('express');
var router = express.Router();
var request = require('request');
var parseString = require('xml2js').parseString;
var EventEmitter = require('events').EventEmitter;
var body = new EventEmitter();
/* GET home page. */
router.get('/', function(req, res, next) {
request("https://500px.com/janedoe/rss", function(error, response, data) {
body.data = data;
body.emit('update');
});
body.on('update', function() {
parseString(body.data, function (err, result) {
var photoLink = result.rss.channel[0].item[0].description[0];
res.render('index', { title: 'Express', photoName});
});
});
});
This puts the entire html contents of the "!CDATA" tag in the photoLink variable. What I want to do is target what's in img src within that html so I can pass the url as a string to be rendered on the page.
I can envision using string methods to look for the first "img src" tag and then read in until the end of the address, but are there more elegant and easy ways to do this?
Try this: in this example, i find all the image urls
const transform = require('camaro')
const cheerio = require('cheerio')
const xml = require('fs').readFileSync('feed.xml', 'utf-8')
const template = {
data: ['//item/description', '.']
}
const result = transform(xml, template)
const links = result.data.map(html => {
const $ = cheerio.load(html)
const links = $('img')
const urls = []
$(links).each(function(i, link) {
urls.push($(link).attr('src'))
})
return urls
})
console.log(links)
Output:
[ [ 'https://drscdn.500px.org/photo/629350/m%3D900/v2?webp=true&sig=4a9fa5788049efb196917cc3f1a55601af901c7157b59ec86c8aa3378c6ee557' ],
[ 'https://drscdn.500px.org/photo/625259/m%3D900/v2?webp=true&sig=55eab44535f05625ad25dae3e805b2559c1caeb4c97570d04ee0a77c52c7fb19' ],
[ 'https://drscdn.500px.org/photo/625253/m%3D900/v2?webp=true&sig=174d1b27e6f87e0a98192cf6ae051301681a51beb7297df9733956d2763af163' ],
[ 'https://drscdn.500px.org/photo/509064/m%3D900/v2?webp=true&sig=698e56114e1d8b67ad11823390f8456ae723d3a389191c43192718f18213caa8' ],
[ 'https://drscdn.500px.org/photo/509061/m%3D900/v2?webp=true&sig=2998212f82a1c3428cebb873830a99b908f463474045d4e5ebba3257808685dd' ],
[ 'https://drscdn.500px.org/photo/509060/m%3D900/v2?webp=true&sig=8082904fe1935c51fc301a0d10529475ee15124d3797f69cbaeac3fd6c5f0dcb' ],
[ 'https://drscdn.500px.org/photo/509056/m%3D900/v2?webp=true&sig=4b85086a7bf55709e77febb202636b0e09415c8ca3fc3657bfb889ad827b3cab' ] ]
You don't need a full parser for this just do it with regex :
var links = [];
var re = new RegExp("<img.*?src=['\"](.*?)['\"].*?>", "gmi");
var res;
while(res = re.exec(body)) links.push(res[1]);
Example :
var a = '<div class="quote"><div class="quote-profile"><img alt="voyages-sncf.com logo" class="img-responsive img-circle" style="height: 80px" src="/img/app_website/index/logo.jpg"> </div><!--//profile--><img alt="voyages-sncf.com logo" class="img-responsive img-circle" style="height: 80px" src="/img/app_website/index/logo2.jpg" data-attr = "lkjlk"/>'
var links = [];
var re = new RegExp("<img.*?src=['\"](.*?)['\"].*?>", "gmi");
var res;
while(res = re.exec(a)) links.push(res[1]);
//["/img/app_website/index/logo.jpg", "/img/app_website/index/logo2.jpg"]

401 unauthorized in NodeJS

I'm developing an application on MEAN stack which can upload an image from disk on application or we can send a image using chrome extension. Now I have done uploading an image from disk but when I'm trying to send image using chrome extension. On this url "http://localhost:9000/api/look/upload"; It gives an error 401 unauthorized
I'm attaching Route.js code, if any MEAN stack developer guide me where exactly is error? I will upload file as well. Thank You in advance
/**
* Main application routes
*/
'use strict';
var errors = require('./components/errors');
var auth = require('./auth/auth.service');
var path = require('path');
module.exports = function(app) {
// Insert routes below
app.use('/api/users', require('./api/user'));
app.use('/auth', require('./auth'));
app.use('/api/look', require('./api/look'));
app.use('/api/links', require('./api/imgScraper'));
app.use('/api/comments', require('./api/comments'));
app.post('/forgotpassword', require('./forgotpassword').reset);
// All undefined asset or api routes should return a 404
app.route('/:url(api|auth|components|app|bower_components|assets)/*')
.get(errors[404]);
app.route('/*')
.get(function(req, res) {
res.sendFile(path.resolve(app.get('appPath') + '/index.html'));
});
};
module.exportstest = function(app) {
app.use('/api/looktest', require('./api/looktest'));
};
JSON CODE Is here:
JSON CODE:
{
"name": "IBR Extension",
"version": "1.3",
"description": "Demonstrate screenshot functionality in the chrome.tabs api.",
"background": {
"persistent": false,
"scripts": ["ExtensionWorking.js"]
},
"browser_action": {
"default_icon": "camera.png",
"default_title": "Take a screen shot!"
},
"permissions": [
"tabs",
"activeTab",
"downloads",
"<all_urls>"
],
"manifest_version": 2
}
XHR code is here:
function reportBug(){
var imageData = document.getElementById("canvas").toDataURL();
var xhttp = new XMLHttpRequest();
var params = "imageData=" + imageData;
var url = "http://localhost:9000/api/look/upload";
xhttp.open( "POST", url, true ); // false for synchronous request
xhttp.send( params );
return xhttp.responseText;
}
Upload function is here:
exports.upload = function(req, res) {
console.log('abc');
var newLook = new Look();
var fileimage = req.middlewareStorage.fileimage;
console.log(req.body + "test test");
newLook.image = '/assets/images/uploads/' + fileimage;
newLook.email = req.body.email;
newLook.linkURL = req.body.linkURL;
newLook.title = req.body.title;
newLook.description = req.body.description;
newLook.userName = req.body.name;
newLook._creator = req.body._creator;
newLook.createTime = Date.now();
newLook.upVotes = 0;
newLook.save(function(err, look) {
if(err) {
console.log('error saving look');
return res.send(500);
} else {
console.log(look);
res.status(200)
.send(look);
}
});
};

Local storage data not returned to content script from backgound.js

In background.js, I store some data into local storage:
localStorage["domain"] = site; //Save the site to local storage for retrieval later when requested by the content script
localStorage["page"] = tab.title; //Save the page title to local storage for retrieval later
localStorage["url"] = tab.url; //Save the URL of the current page to local storage for retrieval
Later, my content script requests the data with
chrome.extension.sendRequest({name:"domain"},
function(response)
{
subjectStr = response.domain;
});
chrome.extension.sendRequest({name:"url"},
function(response)
{
bodyStr = "URL of last page visited: " + response.url;
});
and background.js responds with
//Wait for request for the site value and URL from content script
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse)
{
if (request.name == "url")
{
sendResponse({url: localStorage["url"]});
}
else
{
sendResponse({domain: localStorage["domain"] + ": " + localStorage["page"]});
}
}
);
However, the data is never received by the content script. Anyone see why?
Here's the manifest:
{
"name": "Test",
"version": "1.0",
"manifest_version": 2,
"description": "Test extension",
"browser_action": {
"default_icon": "no_msgs.png",
"default_title": "Press here to test."
},
"background": {
"scripts": ["background.js"]
},
"content_scripts": [{
"run_at": "document_end",
"js": ["postMsg.js"],
"matches": ["https://groups.google.com/forum/*"]
}],
"permissions": ["tabs",
"http://groups.google.com/forum/?fromgroups=#!forum/opencomments-site-discussions/*",
"https://groups.google.com/forum/?fromgroups=#!forum/opencomments-site-discussions/*"
]
}
and no_msgs.png:
no_msgs http://www.opencomments.com/no_msgs.png
and background.js:
var post_url = "https://groups.google.com/forum/?fromgroups=#!newtopic/opencomments-site-discussions";
chrome.browserAction.onClicked.addListener(function(main) {
});
function createEvent(tab){
}
function updateEvent(tabId, changeInfo, tab){
}
function miscEvent(tabId, eventInfo){
}
function getURL() {
chrome.tabs.getSelected(undefined, function(tab) {
var tmp = tab.url;
var site;
if (tab.url.indexOf("http://") == 0 || tab.url.indexOf("https://") == 0) {
site = getDomain(tab.url);
chrome.tabs.create({url: post_url});
localStorage["domain"] = site; //Save the site to local storage for retrieval later when requested by the content script
localStorage["page"] = tab.title; //Save the page title to local storage for retrieval later
localStorage["url"] = tab.url; //Save the URL of the current page to local storage for retrieval
}
});
}
//Wait for request for the site value and URL from content script
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse)
{
if (request.name == "url")
{
sendResponse({url: localStorage["url"]});
}
else
{
sendResponse({domain: localStorage["domain"] + ": " + localStorage["page"]});
}
}
);
//Fetches the domain from the URL
function getDomain(url){
var tmp = url.substring(url.indexOf("//") + 2);
var tmp2 = tmp.indexOf("/");
var str = tmp.substring(0, tmp2);
var index = str.indexOf(".");
while ((tmp = str.substring(index + 1)).indexOf(".") != -1){
str = str.substring(index + 1);
index = str.indexOf(".");
}
index = str.indexOf(".");
return str;
}
// Called when the user clicks on the browser action.
chrome.browserAction.onClicked.addListener(function(tab) {
getURL();
});
and finally postMsg.js:
var subjectStr = '';
var bodyStr = '';
chrome.extension.sendRequest({name:"domain"},
function(response) {
subjectStr = response.domain;
});
chrome.extension.sendRequest({name:"url"},
function(response) {
bodyStr = "URL of last page visited: " + response.url;
});
Works fine with your code, i used messages instead of requests.
Follow Rob W posts(link1, link2) for more information on sendMessage() vs sendRequest()
SAMPLE CODE AND OUTPUT
Output from background.js
Output from Content Script scripts.js
manifest.json
{
"name":"Local Storage",
"description":"Local Storage Demo",
"manifest_version":2,
"background":{
"scripts":["background.js"]
},
"content_scripts": [
{
"matches": ["https://www.google.co.in/*"],
"js": ["scripts.js"]
}
],
"permissions":[
"tabs","<all_urls>"
],
"version":"1"
}
background.js
function storeData(){
localStorage["domain"] = "google"; //Save the site to local storage for retrieval later when requested by the content script
localStorage["page"] = "Google"; //Save the page title to local storage for retrieval later
localStorage["url"] = "https://www.google.co.in/"; //Save the URL of the current page to local storage for retrieval
}
chrome.extension.onMessage.addListener(
function(request, sender, sendResponse)
{
console.log("request recieved is "+request);
if (request.name == "url")
{
console.log("sending response for request URL"+ localStorage["url"]);
sendResponse({url: localStorage["url"]});
}
else
{
console.log("sending response for request URL"+ localStorage["page"]);
sendResponse({domain: localStorage["domain"] + ": " + localStorage["page"]});
}
}
);
window.onload = function(){
storeData();
}
scripts.js
function requestBackground(){
chrome.extension.sendMessage({name:"domain"},
function(response)
{
console.log("response recived for response.domain "+response.domain);
});
chrome.extension.sendMessage({name:"url"},
function(response)
{
console.log("response recived for last page visited: " + response.url);
});
}
window.onload = function(){
requestBackground();
}
Let me know if it still fails.

Resources