Sending message from popup.js in Chrome extension to background.js - google-chrome

What is the proper way to send a message (and get a response) to background.js from popup.js in a Chrome extension? Every method I try ends up with an error that:
"Port: Could not establish connection. Receiving end does not exist."
I would prefer to use chrome.extension.sendMessage() over chrome.extension.connect() with port.postMessage(), but neither method seems to have worked.
What I am trying to do is wire a button in the popup.html to call into some javascript in popup.js which calls back to background.js in an effort to get info about the currentTab() that was topMost (ie:to get the current URL string to show in the popup.html)
Right now in popup.js (wired to the action of the button) I have:
function getURL()
{
chrome.extension.sendMessage({greeting: "GetURL"},
function(response) { tabURL = response.navURL });
$("#tabURL").text(tabURL);
}
In background.js I have:
chrome.extension.onMessage.addListener( function(request,sender,sendResponse)
{
if( request.greeting == "GetURL" )
{
var tabURL = "Not set yet";
chrome.tabs.getCurrent(function(tab){
tabURL = tab.url;
});
sendResponse( {navURL:tabURL} );
}
}
Any ideas?

Just to clarify, we talking about communication between popup page from browserAction and background script?
Anyway you have quite a few errors in your code.
First your totally ignore the fact that all callbacks in chrome api are asynchronous.
In background page
var tabURL = "Not set yet";
chrome.tabs.getCurrent(function(tab){
tabURL = tab.url;
}); //this will be invoked somewhere in the future
sendResponse( {navURL:tabURL} );
//navUrl will be always Not set yet because callback of getCurrent hasn't been called yet
Same in popup.js
chrome.runtime.sendMessage({greeting: "GetURL"},
function(response) { tabURL = response.navURL });//callback will be invoked somewhere in the future
$("#tabURL").text(tabURL)//tabURL will display something totally different from what you have been expected
Second error is that chrome.tabs.getCurrent doesn't give you the current tab selected by user in main window. The docs says:
Gets the tab that this script call is being made from. May be
undefined if called from a non-tab context (for example: a background
page or popup view).
So you will get undefined for all of your requests, because you call it in background page. What you need to do is to use method chrome.tabs.query to obtain currently active tabs.
So after fixing all problems new code should look something like this:
background.js
chrome.runtime.onMessage.addListener( function(request,sender,sendResponse)
{
if( request.greeting === "GetURL" )
{
var tabURL = "Not set yet";
chrome.tabs.query({active:true},function(tabs){
if(tabs.length === 0) {
sendResponse({});
return;
}
tabURL = tabs[0].url;
sendResponse( {navURL:tabURL} );
});
}
}
popup.js
function getURL() {
chrome.runtime.sendMessage({greeting: "GetURL"},
function (response) {
tabURL = response.navURL;
$("#tabURL").text(tabURL);
});
}

Related

chrome ext many loads on update page

In app use content script for all pages, and send message to active page on complete loaded page, but I have many calls of script sometimes 2 and more:
You can see that here
Code implimentation:
chrome.tabs.onCreated.addListener(function (tabs) {
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
if(changeInfo.status === "complete") {
let tabid = tab.id;
console.log("Site is valid: url -> " + tab.url)
chrome.tabs.executeScript(tab.id, {
file: '/injections/mobile.bet365.com.js',
});
console.log(tab);
setTimeout(function () {
console.log("timeout was set")
chrome.tabs.query({}, function (tabs) {
let countOpenedTabsFrom = tabs.length;
let opener = 1;
// на целевой вкладке
chrome.tabs.sendMessage(tabid, {
message: "start_app",
opener: opener,
queuenumber: countOpenedTabsFrom
}, function (response) {
console.log(response);
});
});
}, 500);
}
And executed script have many queries too.
Why is this happen?
Every time onCreated event fires, you're adding a new onUpdated listener.
When, after that, onUpdated event fires, all of them are executed, leading to the behavior you're seeing.
You either need to de-register the handlers when they are done, or register the handler only once. See chrome.events docs (which describe common points of all event objects in other APIs) for ideas on how to implement that.
Note that the code inside chrome.tabs.onCreated listener does not use the tabs parameter at all, so it's not clear why do you even need to listen to onCreated.

Chrome extension create new tab and send message from popup.js to content script of new tab

I am developing a chrome extension where my popup.js receives a message from a content script on the current page and creates an array. Then on a button press, popup.js creates a new tab (which has a content script running) and sends that content script a message containing the array.
My popup.js:
//this message is sent from a different content script (for current page), not shown here
chrome.runtime.onMessage.addListener(function(request, sender) {
if (request.action === "getSource") {
var arr = JSON.parse(request.source);
//create new tab
chrome.tabs.create({url: "newtab.html"}, function(tab){
//send message to new tab
chrome.tabs.sendMessage(tab.id{
action: "getDataArray",
source: JSON.stringify(arr)
});
}
});
newtab-contentscript.js:
$(document).ready( function() {
chrome.runtime.onMessage.addListener(function(request, sender) {
if (request.action === "getDataArray") {
$("#result").html(JSON.parse(request.source));
}
});
newtab.html:
<script src="newtab-contentscript.js"></script>
Problem: The newtab-contentscript.js never seems to receive the message.
Are the any mistakes with how I am creating a tab or sending the message. Do you have any suggestions to how to fix this issue?
As we discussed in the comments, I guess maybe $(document).ready is too late to receive messages from chrome.tabs.sendMessage, you can test it by comparing timestamps of console.log inside the callback and on the first line of the new tab's content scripts, as #wOxxOm mentioned.
I just suggest moving message logic to background (event) page and starting the message passing from newtab-contentscript.js, in which you could control when to start sending the message.
A sample code
background.js
let source = null;
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
// sent from another content script, intended for saving source
if(request.action === 'putSource') {
source = request.source;
chrome.tabs.create({ url: 'newtab.html' });
}
// sent from newtab-contentscript, to get the source
if(request.action === 'getSource') {
sendResponse({ source: source });
}
});
newtab-contentscript.js
chrome.runtime.sendMessage({action: 'getSource'}, function(response) {
$('#result').html(response.source);
});

Clicking, pasting text and uploading files from extension

So I'm basically developing an automated click-paste-and-upload system for mutiple texts and files inside a google page.
This method helped me get the instances of objects that I'm looking for: buttons, textboxes, richtextboxes, etc.
Now I want to work with them.
So for example I know the id of a button , and the function subscribed to its click event. How do I trigger the click event from the extension ? I've tried injecting a script with the click event handler (discovered with DOM inspector) at "document_startup" but I don't get an error or anything else.
Here's the content script! The loggerhead function should have inserted the script but I don't think it did. What might be the reason for the blow code not giving anything?
// Runs a function for every added DOM element that matches a filter
// filter -- either function(DOM_node){/*...*/}, returns true or false
// OR a jQuery selector
// callback -- function(DOM_node){/*...*/}
function watchNodes(filter, callback){
observer = new MutationObserver( function (mutations) {
mutations.forEach( function (mutation){
if(typeof filter === "function"){
$(mutation.addedNodes).filter(
function(i){ return filter(this); }
).each(
function(i){ callback(this); }
);
} else {
$(mutation.addedNodes).filter(filter).each(
function(i){ callback(this); }
);
}
});
});
// For every added element, a mutation will be processed
// with mutation.taget == parent
// and mutation.addedNodes containing the added element
observer.observe(document, { subtree: true, childList: true });
}
function loggerhead(node) {
console.log("passhead");
//also inject jquery
var jqueryEl = document.createElement('script');
jqueryEl.setAttribute('src', chrome.extension.getURL('jquery-1.11.1.min.js'));
jqueryEl.setAttribute('type', 'text/javascript');
var scriptEl = document.createElement('script');
scriptEl.setAttribute('src', chrome.extension.getURL('script.js'));
scriptEl.setAttribute('type', 'text/javascript');
node.appendChild(jqueryEl);
node.appendChild(scriptEl);
}
watchNodes("head", loggerhead);
// method not working
//var gmailHead = jQuery("head", document).get(0);
script.js contains the function of subscribed to the click event of the button that I've managed to find through the DOM inspector:
function Cdb(b){return function(){if(Vbb()){return Ddb(b,this,arguments)}else{var a=Ddb(b,this,arguments);a!=null&&(a=a.val);return a}}}
You should try to call the existing click handler like
buttonElement.click()

Chrome API : Reloading current tab with a url using method in Content.js

I want to reload the page with url by scanning content of it. I designed this method in javascript to see if the url has specific stirng in it
Content.Js
function init() {
var d = document.location.href;
d = toggleDevMode(d);
return d;
}
function toggleDevMode(url) {
var hasDevModeOn = '?core.apexpages.devmode.url=1';
if (url.indexOf(hasDevModeOn) != -1) {
//toggle
url = url.substring(0, url.lastIndexOf(hasDevModeOn));
} else if (url.indexOf("salesforce.com") == -1) {
url = url + hasDevModeOn;
} else {
url = url;
}
return url;
}
Functionality I want
I want if user click on icon, it run the script calling method I defined in content.js onClick Event and checks url.
Based on Logic I defined here, url will be modified.
I want reload the tab with modified url. I tried this piece of code
chrome.browserAction.onClicked.addListener(function (activeTab) {
var newURL = init();
chrome.tabs.create({
url: newURL
});
});
But it doesn't work. Please advice how can I call these method onclick event
You don't need a content script to do this. Discard your init function. Put your toggleDevMode function together with the following code in a background script. Make sure your manifest specify the activeTab permission.
chrome.browserAction.onClicked.addListener(function (activeTab) {
var newURL = toggleDevMode(activeTab.url);
chrome.tabs.update({
url: newURL
});
});
EDIT: Replace your current permissions section from your manifest by the following:
"permissions": [
"activeTab"
],

Chrome extension - Message Passing

I'm trying to get the info that is set on the Options Page to alter the behavior of my extension.
Basically, if a checkbox on OptionsPage is set to true, the extension runs, otherwise it doesn't.
I'm returning true on the background.html for testing purposes, but still, it doesn't work.
Would you guys help me out? Thanks!
Code being injected to the page:
if(chrome.extension.sendRequest() == 'true')
alert("checkbox set to true");
else
alert("it is disabled");
background.html
<script>
chrome.extension.onRequest.addListener(function(){
return true;
}
</script>
If you have an options page and you want to communicate to the background page, you can simply do, chrome.extension.getBackgroundPage()
Options Page communicating to the Background Page
options.html
var bkg = chrome.extension.getBackgroundPage()
bkg.startExtension();
bkg.stopExtension();
background.html
function startExtension() {
console.log('Starting Extension');
}
function stopExtension() {
console.log('Stopping Extension');
}
Content Script communicating to the Background Page
When you are referring to "Code being injected to the page" is that any website? If so, you would need to use a content script with Message Passing. To do so, you can do this.
content_script.js
chrome.extension.sendRequest({action:'start'}, function(response) {
console.log('Start action sent');
});
background.html
function onRequest(request, sender, sendResponse) {
if (request.action == 'start')
startExtension()
else if (request.action == 'stop')
stopExtension()
sendResponse({});
};
chrome.extension.onRequest.addListener(onRequest);
In any case, message passing is a good read for anyone coming into extensions.