This question already has answers here:
How to access the webpage DOM/HTML from an extension popup or background script?
(2 answers)
Closed 2 years ago.
I'm writing a chrome extension in which i need to click on a item on the webpage. The item can be found with document.getElementsByClassName("className")[0].click() but if I run this in the popup, it searches for the item in the popup menu instead. How can I make it return and click the item in the webpage?
You should make a content script and use that to perform the click. Content scripts are loaded in the context of the HTML page, as opposed to the extension popup.
You can message between your content script and your main extension code by using the messaging API.
Your extension code could send a message to the content script like this:
// Query the active tab in the current window (there will only be one)
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
// Send a message to that tab (found as tabs[0]),
chrome.tabs.sendMessage(tabs[0].id, {message: "perform_click"}, function(response) {
console.log("Click performed.");
});
});
And your content script could handle the request like this:
// Listen for events from the background script (main part of the extension)
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
// This function will be called in the content script to handle messages received from the main extension code.
// If the extension is requesting a click, we do that here
if (request.message == "perform_click") {
document.getElementsByClassName("className")[0].click()
}
});
Related
Use case:
website opens an extension popup window when a user clicks on a button
user performs some actions in the extension popup
a result of that action is sent back to the browser tab which initially opened the extension
Approach
(1) window.postMessage(data): Send a message to the content script where window.addEventListener("message", (event) => {...} is receiving the message event.
(2) chrome.runtime.sendMessage(event.data, function(response) {...}: This functionality is in the listener above and forwards the message to the background script where chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {...}) is receiving the message.
(3) Background scripts opens the extension as a dedicated popup window:
chrome.windows.getLastFocused().then((window) => {
const width = 600 + 100;
const height = 400 + 100;
const left = window.width - width;
chrome.windows.create({url: path, type: "popup", height: height, width: width, left: left, focused: true});
});
(4) After having processed some user actions within the extension popup a response message should be returned to the content script:
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {...})}
Problem
Everything works fine up to step (4). Because the extension popup has been opened programmatically as a dedicated popup window tabs[0].id contains a tab id from the extension popup window instead of the browser window which triggered the whole flow and where the content script runs.
How can the correct tab id be determined or forwarded along the chain to the popup?
Is this messaging scenario the right approach for my requirements?
Any feedback is very much appreciated!
In my background script, or anywhere but a content script, I am trying to listen for the active tab, or a newly opened tab.
I have this, but this is apparently incorrect:
What I am trying to do is to inject a content-script into the active tab. I don't want my content script to run for every tab/window, just for select tabs.
Does anyone know how to inject a content script for certain tabs? I can't figure it out. I assume the best way to inject content scripts is from the background script.
If you want to run a code in already activated tab (chrome.tabs.query):
chrome.tabs.query({active: true, currentWindow: true}, function(foundTabs) {
const activeTabId = foundTabs[0].id;
chrome.tabs.executeScript(activeTabId, {
file: 'inject.js'
});
})
In case you want to inject a file into every newly activated tab (chrome.tabs.onActivated):
chrome.tabs.onActivated.addListener(function(activeInfo) {
chrome.tabs.executeScript(activeInfo.tabId, {
file: 'inject.js'
});
});
Be sure to check if you have injected the file already, in order to prevent multiple injections.
For both cases, permissions should include tabs.
I was missing the:
"webNavigation"
permission in manifest.json. After adding that permission, I now have:
chrome.webNavigation.onDOMContentLoaded.addListener(function (details) {
const tabId = details.tabId;
chrome.tabs.executeScript(tabId, {
file: 'inject.js'
});
});
now it works.
some chrome API we cant access in content script in that case do that code in background.js and do according action from background js. if you want to do some action in content script in that case you need to communicate using send message
How am I going to write something when user clicks extension icon and loads the window?
I've already tried
window.onload = function() {
console.log("das");
}
and ]
$(document).ready(function(){
console.log('document is ready');
});
but still there isn't any log?
Maybe it's not the best idea but you can use chrome.tabs.sendMessage and chrome.runtime.onMessage.addListener to communicate between contentscript.js and popup.js
contentscript.js is running directly in page scope so you can easily detect when page is ready. After that you can send a message chrome.tabs.sendMessage(tabs.id, {action: 'pageReady'});. In popup.js you are listening to:
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (request.action === 'pageReady') {
// Do what you want to do on page ready
}
});
It should works good for you. You can also send response to the caller:
contentscript.js send information to the popup.js that page is ready.
popup.js do what you want to do (show table).
popup.js send information to the contentscript.js that table is added.
EDIT
I'm not sure about my solution because I found information that:
The popup, while being an extension page, is not a background page. It
is only accessible when it is open
I don't know if it is possible to listen on events in popup. You need to check it.
I'm trying to create a popup chrome extension that shows information about the DOM in the current page, which seems to require messaging. I've been able to send messages to the background, but I need the data to be specific to the current page, as the background is identical to all popups/pages.
In popup.js, I send a message when the DOM is loaded (should trigger when popup is clicked?)
document.addEventListener('DOMContentLoaded', function() {
chrome.runtime.sendMessage({method: "getTableData"}, function response() {
});
});
I also have a listener in the contentscript.js (and background.js for testing)
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if(request.method == "getTableData") {
console.log("table request found!");
}
});
Then, when I activate the popup, the background console outputs table request found!, while
the console for the current page doesn't.
Thanks.
You need to use chrome.tabs.sendMessage instead of chrome.runtime.sendMessage to send a message to a content script.
I want to execute a script on a precise tab of my browser. This script will give back a value.
I don't know what I have to use. The Doc says that contentScript are called on every loading of a new page. I just want to execute the script once the user clicked on a button in my popup.html.
In your contentScript file add listener like this:
chrome.extension.onMessage.addListener(function(msg, sender, sendResponse) {
//do job
sendResponse(...);
});
And in your popup.html on click event:
chrome.tabs.sendMessage(tabid, "message", function responseCallback(response) {
//...
});
more info http://developer.chrome.com/extensions/tabs.html#method-sendMessage