I can't get a response from my content script to show up in my popup.html. When this code runs and the find button is clicked, "Hello from response!" prints, but the variable response is printed as undefined. The ultimate goal is to get the current tab's DOM into my script file so that I can parse through it. I'm using a single time message to a content script to get the DOM, but it's not being returned and is showing up as undefined. I'm looking for any help possible. Thanks.
popup.html:
<!DOCTYPE html>
<html>
<body>
<head>
<script src="script.js"></script>
</head>
<form >
Find: <input id="find" type="text"> </input>
</form>
<button id="find_button"> Find </button>
</body>
</html>
manifest.json:
{
"name": "Enhanced Find",
"version": "1.0",
"manifest_version": 2,
"description": "Ctrl+F, but better",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"tabs",
"*://*/*"
],
"background":{
"scripts": ["script.js"],
"persistent": true
},
"content_scripts":[
{
"matches": ["http://*/*", "https://*/*"],
"js": ["content_script.js"],
"run_at": "document_end"
}
]
}
script.js:
var bkg = chrome.extension.getBackgroundPage();
function eventHandler(){
var input = document.getElementById("find");
var text = input.value;
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
var tab = tabs[0];
var url = tab.url;
chrome.tabs.sendMessage(tab.id, {method: "getDocuments"}, function(response){
bkg.console.log("Hello from response!");
bkg.console.log(response);
});
});
}
content_script.js:
var bkg = chrome.extension.getBackgroundPage();
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse){
if(request.method == "getDOM"){
sendResponse({data : bkg.document});
}else{
sendResponse({});
}
});
I can't get a response from my content script to show up in my popup.html. When this code runs and the find button is clicked, "Hello from response!" prints, but the variable response is printed as undefined. The ultimate goal is to get the current tab's DOM into my script file so that I can parse through it. I'm using a single time message to a content script to get the DOM, but it's not being returned and is showing up as undefined. I'm looking for any help possible. Thanks.
popup.html:
<!DOCTYPE html>
<html>
<body>
<head>
<script src="script.js"></script>
</head>
<form >
Find: <input id="find" type="text"> </input>
</form>
<button id="find_button"> Find </button>
</body>
</html>
manifest.json:
{
"name": "Enhanced Find",
"version": "1.0",
"manifest_version": 2,
"description": "Ctrl+F, but better",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"permissions": [
"tabs",
"*://*/*"
],
"background":{
"scripts": ["script.js"],
"persistent": true
},
"content_scripts":[
{
"matches": ["http://*/*", "https://*/*"],
"js": ["content_script.js"],
"run_at": "document_end"
}
]
}
script.js:
var bkg = chrome.extension.getBackgroundPage();
function eventHandler(){
var input = document.getElementById("find");
var text = input.value;
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
var tab = tabs[0];
var url = tab.url;
chrome.tabs.sendMessage(tab.id, {method: "getDocuments"}, function(response){
bkg.console.log("Hello from response!");
bkg.console.log(response);
});
});
}
content_script.js:
var bkg = chrome.extension.getBackgroundPage();
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse){
if(request.method == "getDOM"){
sendResponse({data : bkg.document});
}else{
sendResponse({});
}
});
Share
Improve this question
asked Oct 28, 2013 at 17:16
user2929018user2929018
711 silver badge3 bronze badges
3
|
1 Answer
Reset to default 21There are quite a few issues with your code (see my comment above).
Some suggestions/considerations first:
Do not inject your content script into all webpages. Inject programmatically and only when the user wants to search.
It might be a better idea to do the "searching" right in the content script, where you have direct access to the DOM and can manipulate it (e.g. highlight search results etc). You might need to adjust your permissions if you go for this approach, but always try to keep them to a minimum (e.g. don't use
tabs
whereactiveTab
would suffice, etc).Keep in mind that, once the popup is closed/hidden (e.g. a tab receives focus), all JS executing in the context of the popup is aborted.
If you want some sort of persistence (even temporary), e.g. remembering the recent results or last search term, you can use something like chrome.storage or localStorage.
Finally, sample code from my demo version of your extension:
Extension files organization:
extension-root-directory/
|
|_____fg/
| |_____content.js
|
|_____popup/
| |_____popup.html
| |_____popup.js
|
|_____manifest.json
manifest.json:
{
"manifest_version": 2,
"name": "Test Extension",
"version": "0.0",
"offline_enabled": true,
"content_scripts": [
{
"matches": [
"http://*/*",
"https://*/*"
],
"js": ["fg/content.js"],
"run_at": "document_end",
}
],
"browser_action": {
"default_title": "Test Extension",
"default_popup": "popup/popup.html"
}
}
content.js:
// Listen for message...
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
// If the request asks for the DOM content...
if (request.method && (request.method === "getDOM")) {
// ...send back the content of the <html> element
// (Note: You can't send back the current '#document',
// because it is recognised as a circular object and
// cannot be converted to a JSON string.)
var html = document.all[0];
sendResponse({ "htmlContent": html.innerHTML });
}
});
popup.html:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="popup.js"></script>
</head>
<body>
Search:
<input type="text" id="search" />
<input type="button" id="searchBtn" value=" Find "
style="width:100%;" />
</body>
</html>
popup.js:
window.addEventListener("DOMContentLoaded", function() {
var inp = document.getElementById("search");
var btn = document.getElementById("searchBtn");
btn.addEventListener("click", function() {
var searchTerm = inp.value;
if (!inp.value) {
alert("Please, enter a term to search for !");
} else {
// Get the active tab
chrome.tabs.query({
active: true,
currentWindow: true
}, function(tabs) {
// If there is an active tab...
if (tabs.length > 0) {
// ...send a message requesting the DOM...
chrome.tabs.sendMessage(tabs[0].id, {
method: "getDOM"
}, function(response) {
if (chrome.runtime.lastError) {
// An error occurred :(
console.log("ERROR: ", chrome.runtime.lastError);
} else {
// Do something useful with the HTML content
console.log([
"<html>",
response.htmlContent,
"</html>"
].join("\n"));
}
});
}
});
}
});
});
{method: "getDocuments"}
, but listen for{method: "getDOM"}
. 2. Even if the messages would match, you would send back the document of your background page. 3. You are running two separate instances ofscript.js
: one in your background page and one in your popup. 4. You seem to need to get some terms (such as background page, popup, content script) straight. 5. You are using a persistent background page, when an event page (non-persistent background page) would be equally effective, but significantly more "resource-friendly". – gkalpak Commented Oct 28, 2013 at 17:55