passing massage from injected js to background.js in chrome extesion - google-chrome-extension

I have a problem with passing data from injected js to background.js
injected js name "getDOM.js" and injected with this code in background.js
chrome.contextMenus.onClicked.addListener(function(info, tab){
chrome.tabs.executeScript(tab.id, {file: "getDOM.js"})
});
i want to pass data from getDOM.js to background.js, so in background.js there is a function that will be ran when context menu clicked
this is the function in background.js :
function SetLinks(info, tab) {
chrome.extension.sendMessage({greeting: "GetURL"},
function (response) {
tabURL = response.navURL;
alert(tabURL);
});
}
as you can see i tried to send a massage and want to get tabURL (this is just for test)
in getDOM.js file i've wrote this code :
chrome.extension.onMessage.addListener(function(request,sender,sendResponse)
{
if( request.greeting === "GetURL" )
{
sendResponse( {navURL:'test'} );
}
});
so the navURL must be returned. but it not working
it works reverse, i mean if i was trying for sending request "from" getDOM.js it will work. it seams the request function should be in getDOM.js otherwise it will not work. please help me
I also tried it this way :
background.js
function SetLinks(info, tab) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "GetURL"}, function(response) {
alert(response.navURL);
});
});
}
chrome.contextMenus.onClicked.addListener(SetLinks);
// Set up context menu tree at install time.
chrome.runtime.onInstalled.addListener(function() {
// Create one test item for each context type.
var contexts = ["page","selection","link","editable","image","video",
"audio"];
var context = contexts[1];
var title = "test";
var id = chrome.contextMenus.create({"title": title, "contexts":[context],
"id": "context" + context});
});
chrome.contextMenus.onClicked.addListener(function(info, tab){
chrome.tabs.executeScript(tab.id, {file: "getDOM.js"})
});
getDOM.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.greeting === "GetURL")
sendResponse({navURL:'test'});
});
but still not working

Sending a request from the extension/background.js to a content script that you need to specify which tab to send it to. https://developer.chrome.com/extensions/messaging.
I created the sample code and tested it works with me as below:
Background.js:
chrome.contextMenus.create({"title": "sample text", "contexts":["page"],
"id": "ViewAlert"
});
function contextClicked(info, tab) {
if (info.menuItemId == "ViewAlert" ) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "GetURL"}, function(response) {
alert(response.navURL);
});
});
}
};
chrome.contextMenus.onClicked.addListener(contextClicked);
Content.js:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.greeting === "GetURL")
sendResponse({navURL:'test'});
});
Also keep in mind to add "permissions": ["contextMenus"...] in your manifest.

i have found the solution
background.js
chrome.contextMenus.onClicked.addListener(function(info, tab){
chrome.tabs.executeScript(tab.id, {file: "getDOM.js"})
});
chrome.contextMenus.onClicked.addListener(function(info, tab){
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "GetURL"}, function(response) {
alert(response.navURL);
});
});
});
getDOM.js
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if (request.greeting === "GetURL")
sendResponse({navURL:'test'});
});

Related

chrome.runtime.sendMessage not working with Asynchronous calls from Multiple Tabs

I have a popup with a button like shown below
I am having a click function like below in popup.js
$('#fetch_article').on('click',()=>{
chrome.tabs.query({currentWindow: true, active: true}, function(tabs){
const url=tabs[0].url;
chrome.storage.local.get(['session_articles'],(data)=>{
let articles=data.session_articles || [];
if(articles.length<=0 && Object.keys(articles).length === 0){
articles.unshift({url:url,state:'Fetching',data:null});
fetcArticles(url);
}else{
// Check if URL already exists
const linkFound = articles.find(link=>link.url===url);
if(linkFound===undefined){
articles.unshift({url:url,state:'Fetching',data:null});
fetcArticles(url);
}
}
chrome.storage.local.set({'session_articles':articles}, function() {
refreshArticles();
});
});
});
})
function fetcArticles(url){
chrome.runtime.sendMessage({type: "fetch_article",url:url},(response)=>{
if(response.type==='success'){
chrome.storage.local.get(['session_articles'],(data)=>{
let articles=data.session_articles;
const linkIndex = articles.findIndex(link=>link.url===response.data.url);
if(linkIndex!==-1){
articles[linkIndex].state='Done';
articles[linkIndex].data={summary:response.data.summary,title:response.data.title};
chrome.storage.local.set({'session_articles':articles}, function() {
refreshArticles();
});
}else{
console.error("Error in Fetching articles from session");
}
});
}else{
console.error("Could not Fetch article, So deleting it from storage");
removerArticleFromStorage(url);
}
});
}
In Backgroun.js
chrome.runtime.onMessage.addListener( (request, sender, sendResponse) => {
switch (request.type) {
case "fetch_article":
$.ajax({
type: "POST",
url: "http://someajaxurl.com/method",
data: JSON.stringify({url:request.url}),
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function(response){
if(response.type==='error'){
sendResponse({type:'error',msg:response.msg});
}else{
response.data.url=request.url;
sendResponse({type:'success',data:response.data});
}
}
});
return true;
break;
default:
sendResponse({type:'error',msg:'Nothing Found Here...'});
break;
}
});
This works all good if I click the fetch article button and stays in that tab, but if I click the fetch article button in Tab1 and Move to Tab2 The fetcArticles callback is not working expectedly. What I am doing wrong here.

How can activate chrome.runtime.onMessage.addListener for a specific tab?

I am creating a chrome extension and I am using Message Passing for this process. The process is this:
1.- popup.js send a request to background when I clicked on an element of popup.
function sendMessageToContent(contactName){
chrome.runtime.sendMessage({elementValue: contactName}, function(response) {
console.log(response.farewell);
});
}
2.- background.js listens the request.
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
if(request.elementValue != null){
var accessToken = localStorage.getItem('accessToken');
var instanceUrl = localStorage.getItem('instanceUrl');
getContactByName(accessToken,instanceUrl,request.elementValue);
sendResponse({farewell: "ContactResponse"});
}
});
and it sends another request to content.js.
function getContactByName(accessToken,instanceUrl,contactName){
var urlQuery = 'query';
fetch(instanceUrl+urlQuery,{
method: 'get',
headers: new Headers({
'Authorization': 'Bearer '+accessToken,
'Content-Type': 'application/json'
})
})
.then(response => {
if(response.status != 200){
showAuthNotification();
}
return response.json()
})
.then(data => {
for(var i = 0; i<data.totalSize; i++){
contact.push({name:data.records[i].Name, email:data.records[i].Email, id:data.records[i].Id});
}
localStorage.setItem('contactInfo', JSON.stringify(contact));
chrome.tabs.query({}, function (tab) {
chrome.tabs.update(tab[4].id, {active: true});
chrome.tabs.sendMessage(tab[4].id, {message: "OK"});
}
});
})
.catch(function (error) {
console.log('Request failure: ', error);
})
}
3.- The problem is in this step, after the background's request is sent it should open a specific tab and the listener on the content.js should take the request. this process only works when I am in the current tab, when I active the other tab using chrome.tabs.update(tab[4].id, {active: true}); the listener
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
console.log(request.message);
});
doesn't listen the request.
How could I do that the listener is active for all requests or for a specific tab not just for the current tap?

Obtain the tabId of new created tab

How do I get the tabId of a new created tab? My tabId I want to send in sendMessage is undefinded.
How do I get the tabId?
Later I need the tabId to update the tabs....
popup.js
$(document).ready(function () {
"use strict";
$('button').on('click', function () {
chrome.tabs.create({
url: "http://google.de"
}, function(tab) {
});
chrome.runtime.sendMessage({content: tabId, type:'urlDe'});
window.close();
});
chrome.tabs.create({
url: "http://google.com"
}, function(tab) {
});
chrome.runtime.sendMessage({content: tabId, type:'urlCom'});
window.close();
});
});
background.js
chrome.runtime.onMessage.addListener(function(request) {
if (request.type === 'urlDe') {
alert(request.type + request.content);
} else if (request.type === 'urlCom') {
alert(request.type + request.content);
}
});
You need to access to the tabId via tab.id in your callback function, because chrome.tabs.create is async function:
chrome.tabs.create({
url: "http://google.de"
}, function(tab) {
chrome.runtime.sendMessage({content: tab.id, type:'urlDe'});
});
});
More information are in documentation or in this question.

Is it possible to POST from the same URL without refreshing the page?

I'm using ajax to do so and am responding with res.end on the backend but so far, I can only POST once. Here is my code:
Server
app.post("/awesome", passwordless.restricted({ failureRedirect: "/" }), (req, res, next) => {
// ...do a bunch of stuff
res.end();
});
Client
$("[data-new-save]").on("click", function () {
$.ajax({
url: "/awesome",
type: "POST",
data: awesomeDetails,
success: function () {
console.log("Cool beans");
refreshContent(); // Re-renders content
// Feedback
$("nav").after("<div class=\"flash success\">Success!</div>");
setTimeout(function () {
$(".flash").remove();
}, 5000);
},
error: function () {
console.log("Welp");
// Feedback
$(".navigation").after("<div class=\"flash error\">Failure</div>");
setTimeout(function () {
$(".flash").remove();
}, 5000);
}
});
});
This sounds like a case for event-delegation. The best guess I have is that your refreshContent() function is removing the original [data-new-save] elements and creating new ones. This will cause the bound click event to be removed as well as it is a property of the DOM nodes that existed when it was originally called. You can get around this by delegating the event to a DOM node that does not get "refreshed", I'm assuming that the <body> tag does not get redrawn, only some set of children, so if you target <body> and look for selectors that match "[data-new-save]" it should function properly:
$('body').on('click', "[data-new-save]", function () {
$.ajax({
url: "/awesome",
type: "POST",
data: awesomeDetails,
success: function () {
console.log("Cool beans");
refreshContent(); // Re-renders content
// Feedback
$("nav").after("<div class=\"flash success\">Success!</div>");
setTimeout(function () {
$(".flash").remove();
}, 5000);
},
error: function () {
console.log("Welp");
// Feedback
$(".navigation").after("<div class=\"flash error\">Failure</div>");
setTimeout(function () {
$(".flash").remove();
}, 5000);
}
});
});
This is what i used for something similar:
$(document).ready(function () {
$('#myform').on('submit', function(e) {
e.preventDefault();
$.ajax({
url : $(this).attr('action') || window.location.pathname,
type: "GET",
data: $(this).serialize(),
success: function (data) {
$("#form_output").html(data);
},
error: function (jXHR, textStatus, errorThrown) {
alert(errorThrown);
}
});
});
});

Node js + PhantomJs: send data to page.evaluate

How can I send variable from server to page.evaluate ?
var test = 'Lorem Ipsum';
phantom = require('phantom')
phantom.create(function(ph){
ph.createPage(function(page) {
page.open("http://www.google.com", function(status) {
page.evaluate(function(){
$('body').html(test);
});
page.render('google.pdf', function(){
console.log('Page Rendered');
ph.exit();
});
});
});
});
Thank you in advance for your help.
Edit1
Now it look like
var message = function(){
return {message: 'Hello Word'};
};
phantom = require('phantom')
phantom.create(function(ph){
ph.createPage(function(page) {
page.open("http://www.google.com", function(status) {
page.evaluate(function(content){
$('body').html(content);
}, message);
page.render('google.pdf', function(){
console.log('Page Rendered');
ph.exit();
});
});
});
});
Now I haven't any error, but I don't know how can I handle this object to use it in page.evaluate
try with
page.evaluate(function (...) {...}, function (err, data){...}, arg1, arg2, ...);
example:
var message = 'hello world';
page.evaluate(function(content){
$('body').html(content);
return 'any data'
}, function (err, anydata) {}, message);
Adding jquery to page
page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js', function(err) {
//jQuery Loaded.
//Wait for a bit if site have AJAX
setTimeout(function() {
return page.evaluate(function() {
// USE JQUERY HERE
//
//
return
}, function(err, result) {
console.log(result);
ph.exit();
});
}, 3000);
});
see readme at:
https://github.com/alexscheelmeyer/node-phantom

Resources