I'm trying to communicate with the content script of the tab that has just been switched to using message passing. Here is my code in the background.js script.
chrome.tabs.onActivated.addListener(function(activeInfo) {
chrome.tabs.sendMessage(activeInfo.tabId, { greeting: "hello" }, function(response) {
console.log(response.farewell);
});
});
And here is my code in my content script:
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
sendResponse({ farewell: "goodbye" });
loadContent();
});
Is the content script no longer listening in an inactive tab even when it's switched back to that tab? Why does this only run in a newly opened tab?
To further clarify why I want to do this, sometimes tabs are left open without reloading, and my script has already been executed. When information pertaining to the script changes using the popup options, I want the content to reload on tab change, and a particular function to run again without reloading the page. Therefore, injecting the content script is less than ideal since it's already been executed.
Try this :
background.js
chrome.tabs.onActivated.addListener(function(activeInfo) {
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
chrome.tabs.sendMessage(activeInfo.tabId,
{ greeting: "hello" }, function(response) {
console.log(response.farewell);
});
});
});
Related
I have a Chrome extension (content script) with a popup window. When the user clicks a "Start" button in the popup window, I'd like a new tab to open to a url (say www.test.com), and for the content script to be injected into that tab. Not just executed once, but injected so that it will work on (www.test.com/*) on that same tab. Not in other tabs - just that one.
Here's what I have now:
chrome.tabs.create({
'url': 'http://test.com/shop/new'
}, function(tab) {
chrome.tabs.executeScript(tab.id, {
'file': 'script.js'
});
});
But, chrome.tabs.executeScript is being used, which only executes the script once. The script redirects the page to 'http://test.com/shop/new/xxx', but since the script is only executed once, it stops working when the page changes. Again - how can I make it so that the script is injected into all 'http://test.com/shop/*' pages in that tab?
A good idea is to make a script that is always injected into http://test.com/shop/* (via manifest):
"content_scripts" : [
{
matches: ["http://test.com/shop/*"],
js: ["script.js"]
}
],
Then, in the script, ask the background page if it should be active for this ID:
// script.js
chrome.runtime.sendMessage({shouldIRun : true}, function(response){
if(response) {
// Actually do stuff
}
});
And in the background script, keep a record of tabs that you want it to apply to:
// Background script
var activeTabs = {}; // Slightly more difficult with event pages
// At some point when you enable it, e.g. in a browserAction.onClicked listener
activeTabs[tabId] = true;
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if(message.shouldIRun) {
// Double negation to ensure true/false
sendResponse(!!activeTabs[sender.tab.id]);
}
});
// It's a good idea to clear the stray entries
chrome.tabs.onRemoved.addListener(function(tabId, removeInfo) {
delete activeTabs[tabId];
});
// Sometimes this can also happen
chrome.tabs.onReplaced.addListener(function(addedTabId, removedTabId) {
if(!!activeTabs[removedTabId]) activeTabs[addedTabId] = true;
delete activeTabs[removedTabId];
});
I'd like to launch the print dialog on button click in my google chrome extension. The code seems to be working when the extension's html file is opened as a standalone file, but not when it's loaded as an extension.
HTML:
<input id="print_page" type="button" value="Print" onclick="print_p()" />
JavaScript: function print_p(){ window.print();}
Any idea as to what's wrong?
Aside from the inline JavaScript problem that I mentioned as a duplicate, it seems that invoking the print dialog from a popup (or a background page) is impossible.
A workaround would be to have a "print helper" page in your extension, that opens in a normal tab and can open a print dialog.
A possible architecture:
On a click in a popup, data to print is being sent to the background page:
function printClick(){
chrome.runtime.sendMessage({ print: true, data: whateverYouWantToPrint });
}
It's routed through the background page so that you don't have to worry about popup closing.
In the background page, a helper page is opened:
var printData;
chrome.runtime.onMessage.addListener( function(request, sender, sendResponse){
if(request.print) {
printData = request.data;
chrome.tabs.create(
{ url: chrome.runtime.getURL("print.html") }
);
}
// ...
});
In the print helper page, a script print.js requests the data, formats it as required and invokes the print dialog:
chrome.runtime.sendMessage({ getPrintData: true }, function(response){
formatDataIntoPage(response.data);
window.print();
});
Back in the background page, serve the data on request from print helper:
chrome.runtime.onMessage.addListener( function(request, sender, sendResponse){
// ...
if(request.getPrintData) {
sendResponse({ data: printData });
}
});
Suppose I want to run a content script when I click a button in the popup page in a google chrome extension?
I have tried the following:
//popup.js
document.addEventListener('DOMContentLoaded', function () {
document.querySelector('button').addEventListener('click', clicked);
main();
});
function clicked(){
chrome.tabs.getCurrent(
function(tab){
console.log(tab);
chrome.tabs.sendMessage(tab.id, "doSomething");
}
);
}
And in the content script:
chrome.extension.onMessage.addListener(
function(message, sender, sendResponse){
console.log("hello world");
}
);
The problem is that the tab in the callback from chrome.tabs.getCurrent( ) is undefined.
Have you given permissions for tabs in manifest.json as shown here.
"permissions": [
"tabs"
],
Moreover tab.id which the following code returns is of popup view (NOT A CONTENT SCRIPT TAB.ID)
chrome.tabs.getCurrent(
function(tab){
console.log(tab);
chrome.tabs.sendMessage(tab.id, "doSomething");
}
);
If you want to send message to tab you are browsing use following code's tab.id, it gives correct results
chrome.tabs.query({"status":"complete","windowId":chrome.windows.WINDOW_ID_CURRENT,"active":true}, function(tabs){
console.log(JSON.stringify(tabs[0]));
console.log(tabs[0].id);
});
Let me know if you need more information
The answer provided by #Sudarshan is valid and works fine, but I just found another solution to my problem. Just thought i put it here:
function clicked() {
chrome.tabs.executeScript(null,
{code:"console.log('hello world');"});
}
It will inject and execute the script.
I'm a javascript novice writing my first Chrome extension and I'm stuck on message passing. My extension includes a background script, a browser action icon, and a content script. The content script (a timer that measures the number of second spent in tab) needs to update the background script and change the icon when the tab is closed, but since the content script cannot access the tab onRemove event, it needs to listen for a message from the background script.
Here's how I've set up the background script listener to listen for closed tabs:
// Listen for closed tabs.
chrome.tabs.onRemoved.addListener(function(tab) {
send_closed_message();
});
function send_closed_message () {
chrome.tabs.getSelected(null, function(tab) {
console.log("sending tab_closed to tab " + tab.id);
chrome.tabs.sendRequest(tab.id, {close: true},
function(response) {
console.log(response.timer_stop); });
});
}
And here's the function in the content script that listens for this message.
function main () {
console.log("main()");
timer = new Timer();
timer.start();
// Listen for window focus
window.addEventListener('focus', function() { timer.start(); } );
// Listen for window blur
window.addEventListener('blur', function() { timer.stop(); } );
// Listen for tab close
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url:
"from the extension");
if (request.close === true) {
sendResponse({timer_stop: "stopped"});
timer.stop();
}
});
}
I do not see a response from the content script in the background script console. Since I'm closing the tab, I can't view the content script console. Where is the message going wrong? Is there a better way to debug this? Is there another way the content script could listen for when its tab closes?
I believe the onRemoved on background happens when the tab is already being closed, so probably there is no enough time for the context to receive your message and replay back to the background script.
Maybe is a good idea for the context to keep sending messagens to background every second with its count value. And when the background receives the onRemoved event it simply uses the last received value as the live time of that page.
Google Chrome Extensions Message Passing Problem :
In this Chrome Extension
My Popup Page:
chrome.browserAction.onClicked.addListener(getMessage);
getMessage();
function getMessage()
{
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {greeting: "hello"}, function(response) {
console.log(response.farewell);
});//getting response from content script
});
}
My Script Page :
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
if (request.greeting == "hello")
sendResponse({farewell: "goodbye"});
else
sendResponse({});
});
I am not getting any response from the content script.
Edits:
As per #serg , i have moved the code to the background page. But still, it is not working
You can't have chrome.browserAction.onClicked listener if you have popup page attached to the browser action button, it won't fire.
Remove popup, leave only button
Move everything into background page.
Replace tab.id with null.
Remove createFile(); call at the beginning as it won't do anything in this case (content script isn't ready to listen yet).
Don't use alerts for debugging extension, use console.log().