chrome google extension send message data from background to ui - google-chrome

I have read several forums here , here, and here but didn't solve my issue.
On load, I need to pass the data from background.js (coming from an api response) to my content script so that It would populate my dropdown menu. I have tried several codes but nothing worked. It doesn't have error, just that nothing happens.
the following commented and un-commented codes inside sendTocontent are what I have tried in background.js. Pls note that if I use the tabs[0].id - this is empty array or sometimes not defined so I had to work around for the lasttabid - I figured this must be the issue but how ??? That's all I see in the documentation.
background.js
var lastTabId = -1;
function sendMessage() {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
lastTabId = tabs[0].id;
chrome.tabs.sendMessage(lastTabId, "Background page started.");
});
}
sendMessage();
let uri=chrome.runtime.getURL('');
chrome.storage.local.set({ "chrome_uri" :uri })
chrome.runtime.onMessage.addListener(function(request, sender) {
var environment = "http://localhost:9126/";
$.ajax({
url: environment + "Plugin/list",
type:'get',
success:function(data){
var profiles = JSON.parse(data.Content);
sendTocontent(profiles);
}
})
});
function sendTocontent(somedata){
// chrome.tabs.query({currentWindow: true},
// function(tabs) {
// chrome.tabs.sendMessage( tabs[0].id, {sender:'background', somedata:somedata});
// })
// chrome.extension.sendMessage({somedata: "hello"}, function(response) {
// console.log(response);
// });
// chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
// chrome.tabs.sendMessage(lastTabId, {action: "open_dialog_box"}, function(response) {});
// });
chrome.tabs.sendRequest(
lastTabId,
{'profileList': true});
}
this is my contentscript called toolbar.js:
//i tried this
chrome.runtime.onMessage.addListener(function(request, sender) {
if (request.sender=='background') {
alert("Request sent sucesss")
}
});
//i tried this
chrome.extension.onMessage.addListener(
function(request, sender, sendResponse) {
chrome.pageAction.show(sender.tab.id);
}
);
function onExtensionMessage(request) {
if (request['profileList'] != undefined) {
alert("onExtensionMessage")
}
}
//i tried this
chrome.extension.onRequest.addListener(onExtensionMessage);
excerpt from my manifest:
"background" : {
"scripts" : ["js/jquery.js","background.js"]
},
"content_scripts": [
{
"matches": ["*://*/*"],
"js": ["js/jquery.js","js/toolbar.js"],
"css": ["button.css"]
}
],
permissions": ["storage", "activeTab", "tabs"],

The correct solution is actually trivial.
The content script sends a message to the background script.
chrome.runtime.sendMessage({action: 'getProfiles'}, profiles => {
console.log(profiles);
//useProfiles(profiles);
});
The background script fetches the URL and responds with the result.
chrome.runtime.onMessage((msg, sender, sendResponse) => {
if (msg.action === 'getProfiles') {
fetch('http://localhost:9126/Plugin/list')
.then(r => r.json())
.then(json => sendResponse(json.Content));
// keep the channel open for sendResponse while `fetch` runs asynchronously
return true;
}
});
Yep, this is the entire code.

Related

Pause chrome.webRequest.onBeforeRequest until message | Chrome extension

I am working on a chrome extension and I am having trouble pausing web requests until message is received from Script.js.
chrome.webRequest.onBeforeRequest.addListener(function (e){
chrome.tabs.executeScript(null, {code:"var eventURL = JSON.parse('" + encodeToPassToContentScript(e) + "');"}, function(){
chrome.tabs.executeScript(null, { code:`(async function() {
//console.log('E URL', eventURL.url);
if (eventURL.url.match("some condition")){
var iframe = document.createElement('iframe');
iframe.src = url ;
document.body.prepend(iframe);
iframe.addEventListener("load", function() {
console.log('Iframe loaded');
// Gather data
chrome.runtime.sendMessage(extraData, function(response){
console.log('extraData', extraData);
console.log('response sent', response);
});
});
}
})()`}, () => {
new Promise(resolve => {
chrome.runtime.onMessage.addListener(function listener(result) {
chrome.runtime.onMessage.removeListener(listener);
console.log('RES', result)
resolve(result);
});
}).then(result => {
console.log('RES', result);
});
});
})
return {cancel: false};
}, {
urls:["<all_urls>"],
types:["xmlhttprequest"]
}, ["blocking","requestBody"]);
I have the code above. My goal is filtering web request -> prepending iframe to the current tab, gathering some data from Iframe -> sending message to background.js -> continue the web request.

Chrome Extension unable to send message from background to content script successfully

I am trying to create an extension that, in the background script, opens a specified URL, and then sends a message to said tab that was opened in the content script side, but I am getting an error and I'm not sure where I'm going wrong.
Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.
background.js
let targetTab = "http://google.com"
main();
function main() {
let active = true;
let tabId = null;
let tabUrl = null;
if (active) {
chrome.tabs.create({
url: targetTab,
}, (tab) => {
console.log("Tab ID Generated: " + tab.id);
tabId = tab.id;
chrome.tabs.query({}, function (tabs) {
tabs.forEach(tab => {
console.log(tab.url);
if (tab.url !== targetTab) {
chrome.tabs.remove(tab.id);
}
})
console.log("Tab ID Sent: " + tabId);
chrome.tabs.sendMessage(tabId, {
tabId,
tabUrl,
}, (response) => {
console.log(JSON.stringify(response));
})
})
})
}
}
content.js
chrome.runtime.onMessage.addListener(
(request, sender, sendResponse) => {
if (chrome.runtime.lastError) {
console.log(chrome.runtime.lastError);
}
console.log("Got Message");
sendResponse({message: "hi to you"});
});

Chrome-extension: How to send message from content.js to popup.js - Page_Action

Chrome v64.
I want to send a message from content.js to popup.js.
I managed to send a message from popup.js to content.js. But how to do it the opposite way? I have also downloaded a sample extensions, which also don't work.
Do I have to add a special permission?
I tried one time messaging and long running message channel.
Permissions:
"permissions": [
"background",
"tabs",
"activeTab",
"storage",
"webRequest",
Content.js
chrome.runtime.sendMessage({
data: "mauzen"
}, function (response) {
return true;
});
debugger;
var port = chrome.runtime.connect({
name: "knockknock"
});
port.postMessage({
joke: "Knock knock"
});
port.onMessage.addListener(function (msg) {
debugger;
if (msg.question == "Who's there?")
port.postMessage({
answer: "Madame"
});
else if (msg.question == "Madame who?")
port.postMessage({
answer: "Madame... Bovary"
});
});
Background.js
chrome.runtime.onMessage.addListener(function (request, sender, sendResponse) {
sendResponse({
data: "background"
});
if (request.data === "success") {
alert("success");
} else {
//alert(request.data);
}
});
console.assert(port.name == "knockknock");
port.onMessage.addListener(function (msg) {
if (msg.joke == "Knock knock")
port.postMessage({
question: "Who's there?"
});
else if (msg.answer == "Madame")
port.postMessage({
question: "Madame who?"
});
else {
port.postMessage({
question: "background"
});
}
});
Popup.js
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
sendResponse({
data: "popup"
});
if (message.data === "success") {
alert("success");
} else {
// alert(message.data);
}
});
chrome.runtime.onConnect.addListener(function (port) {
console.assert(port.name == "knockknock");
port.onMessage.addListener(function (msg) {
if (msg.joke == "Knock knock")
port.postMessage({
question: "Who's there?"
});
else if (msg.answer == "Madame")
port.postMessage({
question: "Madame who?"
});
else {
port.postMessage({
question: "popup"
});
}
});
});
This is what I found out, testing around a bit.
To send a message from the content.js script to your popup you do the following:
chrome.runtime.sendMessage({
data: "Hello popup, how are you"
}, function (response) {
console.dir(response);
});
and in your popup.js:
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
sendResponse({
data: "I am fine, thank you. How is life in the background?"
});
});
The message sent from content.js to popup.js will only be received, when your Popup is active (=open), i.e. you click on your page_action (browser_action) icon in the toolbar and the popup appears, then it is open/active. And only then, it can send and receive messages!
You can test it like this
Put the following script in you content.js:
var timer = 0;
var si = setInterval(() => {
try {
chrome.runtime.sendMessage({
data: "Hello popup, how are you"
}, function (response) {
console.dir(response);
});
timer++;
if (timer === 5) {
clearInterval(si);
}
} catch (error) {
// debugger;
console.log(error);
}
}, 2000);
and in your **popup.js:**
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
alert("I am popup!");
sendResponse({
data: "I am fine, thank you. How is life in the background?"
});
});
As long as the setInterval executes you can click on your extension icon, to open the popup, then it will show an alert.
From your code it looks like you are sending a message from your content script to the background and popup script, as opposite to what you described.
Sending a message from your extension to content script requires you to use chrome.tabs.sendMessage, see https://developer.chrome.com/apps/messaging

Chrome extension sending message from iFrame to event page then to content script

I have inserted an iframe from content script. It works fine. But if I want to display parent's html content on iframe, I have to use messaging to communicate between iframe and content script, but it doesn't work. Then I tries to send message from iframe to "event page" then to "content script". Once content script receives the message, it will query the html content and reply. It doesn't work either. How can I make it work?
content script:
var iframe = document.createElement('iframe');
iframe.id = "popup";
iframe.src = chrome.runtime.getURL('frame.html');
document.body.appendChild(iframe);
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
if (msg.from === 'event' && msg.method == 'ping') {
sendResponse({ data: 'pong' });
}
});
event page:
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
if (msg.from === 'popup' && msg.method === 'ping') {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
from: 'event',
method:'ping'}, function(response) {
sendResponse(response.data);
});
});
}
});
frame.js
// This callback function is never called, so no response is returned.
// But I can see message's sent successfully to event page from logs.
chrome.runtime.sendMessage({from: 'popup', method:'ping'},
function(response) {
$timeout(function(){
$scope.welcomeMsg = response;
}, 0);
});
I found a related question. https://stackoverflow.com/a/20077854/772481
From the documentation for chrome.runtime.onMessage.addListener:
This function becomes invalid when the event listener returns, unless you return true from the event listener to indicate you wish to send a response asynchronously (this will keep the message channel open to the other end until sendResponse is called).
So I have to return true to indicate the sendResponse is async.
event page:
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
if (msg.from === 'popup' && msg.method === 'ping') {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {
from: 'event',
method:'ping'}, function(response) {
sendResponse(response.data);
});
});
return true; // <-- Indicate that sendResponse will be async
}
});

How to render jsonp fetched in BackboneJS?

I'm new in BackboneJS, and I can't render information from JSONP. If I put the data into a data.json and I fetch it, the count appears in the console, but when I use JSONP never re-render.
I don't know if is some kind of delay for obtain the data, but the event of "change" and "reset" are not being trigged by the collection to re-render the view.
The code I have is the next:
// Collection
define([
'underscore',
'backbone',
'models/EstablecimientoModel'],function(_, Backbone, EstablecimientoModel){
var EstablecimientoCollection = Backbone.Collection.extend({
model: EstablecimientoModel,
initialize: function(models, options) {
console.log("Establecimiento initialize");
},
url: function() {
return '../js/establecimientos.json';
//return 'http://localhost:3000/establecimiento';
},
parse: function(data) {
console.log("End of loading data " + JSON.stringify(data) + " datos");
return data;
},
});
return EstablecimientoCollection;
});
// Router
define([
'jquery',
'underscore',
'backbone',
'views/establecimiento/EstablecimientoView',
'jqm'
], function($, _, Backbone,EstablecimientoView) {
'use strict';
var Router = Backbone.Router.extend({
//definition of routes
routes: {
'nearMe' : 'nearMe',
},
nearMe: function(actions) {
var estaColl = new EstablecimientoCollection();
var establecimientoView = new EstablecimientoView({ collection: estaColl });
//estaColl.fetch();
//establecimientoView.render();
this.changePage(establecimientoView);
},
init: true,
changePage: function(view) {
//add the attribute data-role="page" for each view's div
$(view.el).attr('data-role','page');
view.render();
// append to the DOM
$('body').append($(view.el));
var transition = $.mobile.defaultPageTransition;
if(this.firstPage) {
transition = 'none';
this.firstPage = false;
}
// Remove page from DOM when it’s being replaced
$('div[data-role="page"]').on('pagehide', function (event, ui) {
$(this).remove();
});
$.mobile.changePage($(view.el), { transition: transition, changeHash: false });
} // end of changePage()
});
return Router;
});
// View
define([
'jquery',
'underscore',
'backbone',
'collections/EstablecimientoCollection',
'text!templates/establecimiento/establecimientoTemplate.html'
],function($, _, Backbone, EstablecimientoCollection, establecimientoTemplate) {
var EstablecimientoView = Backbone.View.extend({
initialize: function() {
var self = this;
_.bindAll(this,"render");
this.collection.on("change",self.render);
this.collection.fetch({ dataType: 'jsonp', success: function(){ self.render() }});
}, //end of initialize()
template: _.template(establecimientoTemplate),
render: function(eventName) {
console.log("render");
console.log(this.collection.length);
return this;
}, //end of render()
});
return EstablecimientoView;
});
When you fetch your data, make sure you're setting the dataType for your fetch call. Fetch is wrapping a jQuery/Zepto ajax call, so you'll need to set the same parameters you would with those.
this.collection.fetch({
reset: true,
dataType: 'jsonp',
success: function () {
// do stuff
}
});
Also, I'd have your view listen for the events published by the collection rather than calling the view's render directly from the fetch's success callback.