Chrome Extensions content calls callback to background but parameter is undefined - javascript

I'm trying to set up a background script fetching data from content periodically and write it to a file (kind of webpage scraping)
Unfortunately I got stuck at the very beginning:
Background sends a message to content and the callback is called but the parameter is not passed correctly, it's "undefined" whatever I try...
Manifest:
{
"manifest_version": 2,
"name": "Test Extension",
"version": "0.0",
"background": {
"persistent": false,
"scripts": ["background.js"]
},
"content_scripts": [{
"matches" : ["<all_urls>"],
"js": ["content.js"]
}],
"browser_action": {
"default_title": "Test Extension"
},
"permissions": ["activeTab"]
}
content.js
chrome.runtime.onMessage.addListener(function (msg, sender, sendResponse) {
if (msg.text === 'report_back') {
sendResponse({data: "goodbye"});
}
});
background.js
chrome.browserAction.onClicked.addListener(function (tab) {
chrome.tabs.sendMessage(tab.id, {text: 'report_back'}, function(response) {
console.log(response.data);
});
});

If you are getting:
Error in event handler for (unknown): TypeError: Cannot read property 'data' of undefined at ...
I'm guessing you are clicking on the extension icon when you are in a tab like chrome://extensions
Try clicking on it from any other website and it should work.

Related

How to communicate between background.js and content.js using manifest v3 in building a Google Chrome extension?

I'm trying to send a request from background.js to content.js but it gives me an error saying:
Uncaught (in promise) Error: Could not establish connection. Receiving end does not exist.
I have even tried to use the google chrome example in their documentation and that did not work. Probably I'm missing something somewhere. I would appreciate your support!
Manifest.js
{
"name": "test",
"description": "test",
"version": "1.0.0",
"manifest_version": 3,
"author": "test",
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["scripts/content.js"]
}
],
"action": {
},
"background": {
"service_worker": "scripts/background.js"
},
"permissions": [
"tabs"
],
"host_permissions": [
"*://*/*"
]
}
content.js
chrome.runtime.onMessage.addListener( (request, sender, sendResponse) => {
console.log(request);
})
chrome.action.onClicked.addListener(
(tab) => {
chrome.tabs.sendMessage(tab.id, {response: "Hello World"})
}
)
The tree of folder is:
manifest.json
scripts/background.js
scripts/content.js
I found the mistake that I've been doing. The example in the documentation was fine but I was printing console.log(request) and checking the console of the extension itself and I should've checked the console of the current page since it was in content.js and not in the background.js

Cannot get Chrome extension background.js to communicate with content.js

Trying to send a message from background.js to content.js returns Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist.
I've tried:
background.js
chrome.tabs.onRemoved.addListener((tabId, removeInfo) => {
chrome.tabs.sendMessage(tabId, "some-random-message")
})
content.js
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
alert(message)
sendResponse("Successfully received message.")
})
Is this happening because I'm trying to send a message to my content script after that tab has been closed? If so, is there any way to still access the document in the content script after or while the tab is closing?
To add more info, I also did try using chrome.tabs.onCreated... instead of onRemoved but with no avail.
EDIT: Adding my manifest.json file.
{
"manifest_version": 3,
"name": "Some Extension Name",
"version": "0.0.1",
"action": {
"default_popup": "popup.html",
"default_title": "Some Extension Name"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["./content.js"]
}
],
"background": {
"service_worker": "./background.js"
},
"permissions": ["cookies", "tabs", "storage"]
}

Chrome extension on a React page

I have a simple chrome extension that auto-fills the form on a page with default values.
manifest.json file
{
"manifest_version": 2,
"name": "Form Filler",
"description": "This extension auto fills form in a specific page.",
"version": "1.0",
"icons": {
"128": "128x128.png"
},
"page_action": {
"default_icon": "19x19.png",
"default_popup": "popup.html",
"default_title": "Form Filler"
},
"options_page":"options.html",
"background": {
"scripts": ["eventPage.js"],
"persistent": false
},
"content_scripts":[
{
"matches": ["http://test-site.com/*"],
"js": ["content.js", "jquery-3.1.0.min.js"]
}
],
"permissions": [
"tabs",
"storage",
"http://test-site.com/*"
]
}
and this is content.js file
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse){
if (request.act == "fill"){
let name = request.name;
let email = request.email;
$('#name').val(name);
$('#email').val(email);
}
});
That works perfectly fine on a normal HTML page.
But it doesn't work on a react page.
I guess obvious reason is that things are handled by state and if I can somehow alter the state, I should be able to get it working.
I tried this code ( file = content.js )but no success
chrome.runtime.onMessage.addListener(function(request, sender) {
if (request.act == "fill") {
this.setState({"form.name": "My Name"});
}
}.bind(this));
This is the eventPage.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse){
if (request.todo == "showPageAction")
{
chrome.tabs.query({active:true,currentWindow: true}, function(tabs){
chrome.pageAction.show(tabs[0].id);
});
}
});
I am unable to access the state in the extension JS.
What would be the proper way to perform this task?

Chrome Extension error tab.url

I'm essentially just trying to get the current tab url if they're on youtube.com. I keep getting an error from the script.
Error:
Uncaught TypeError: Cannot call method 'getSelected' of undefined
Manifest
{
"name": "YouTube Fix",
"version": "0.0.1",
"manifest_version": 2,
"description": "Fix some of the annoying little things in YouTube.",
"icons": {
"16": "icon.png",
"48": "icon.png",
"128": "icon.png"
},
"content_scripts": [{
"matches": ["http://www.youtube.com/*"],
"js": ["background.js"],
"run_at": "document_start"
}],
"permissions": ["tabs"]
}
Background.js
//this is what is giving me the error:
chrome.tabs.getSelected(null, function (tab) {
myFunction(tab.url);
});
function myFunction(tablink) {
if (tablink == "http://www.youtube.com") {
window.location = "http://www.youtube.com/feed/subscriptions/u";
}
document.getElementById("comments-textarea").disabled = false;
}
The following forks fine, no need for chrome.tabs.getSelected(null, function (tab) {}),because your page always runs for "matches": ["http://www.youtube.com/*"],;
More over add this condition to your code if(document.getElementById("comments-textarea") != null){
Working background.js
if (window.location == "http://www.youtube.com") {
window.location = "http://www.youtube.com/feed/subscriptions/u";
}
if (document.getElementById("comments-textarea") != null) {
document.getElementById("comments-textarea").disabled = false;
}
manifest.json
{
"name": "YouTube Fix",
"version": "0.0.1",
"manifest_version": 2,
"description": "Fix some of the annoying little things in YouTube.",
"content_scripts": [{
"matches": ["http://www.youtube.com/*"],
"js": ["background.js"],
"run_at": "document_start"
}],
"permissions": ["tabs"]
}
Let me know if you need more information.
You're running background.js as a content script rather than a background or event page, and https://developer.chrome.com/extensions/content_scripts.html says that "content scripts have some limitations. They cannot … Use chrome.* APIs (except for parts of chrome.extension)"
Instead, you should put something like
"background": {
"scripts": ["background.js"],
"persistent": false
},
into your manifest. See https://developer.chrome.com/extensions/event_pages.html for more details.
Quoted from here: https://groups.google.com/a/chromium.org/forum/?fromgroups=#!topic/chromium-extensions/A5bMuwCfBkQ
chrome.tabs.getSelected() is deprecated. The following page explains
how to use chrome.tabs.query instead:
http://code.google.com/chrome/extensions/whats_new.html#16 The relevant bit of text is:
"""
The methods getAllInWindow() and getSelected() have been deprecated.
To get details about all tabs in the specified window, use
chrome.tabs.query() with the argument {'windowId': windowID}. To get
the tab that is selected in the specified window, use
chrome.tabs.query() with the argument {'active': true}.
"""
chrome.tabs.getSelected is deprecated. Use chrome.tabs.query instead:
chrome.tabs.query({
"active": true
}, function(tab){
console.log(tab[0]); //selected tab
});
Also, content scripts can not access chrome.tabs APIs. Do this:
chrome.extension.getBackgroundPage().chrome.tabs.query(...
(This might not work. Not tested.)

Content Script: Uncaught TypeError: Cannot read property 'onRequest' of undefined

I've been searching all over SO and reading through google docs but I can't seem to find a solution.
My Chrome extension is injecting a content script and I want to set an onRequest.listener in order to sendRequests to the content script. This is the script I used to for the onRequest.listener. The problem is I keep getting this error for some unknown reason.
Error Message:
Uncaught TypeError: Cannot ready property 'onRequest' of undefined
contentscript.js line 1;
Here's the relevant code...
Manifest.json
{
"name": "Injector Extension",
"version": "1.0",
"manifest_version": 1,
"icons": { "128": "icon.png" },
"browser_action": {
"default_icon": "icon.png",
"default_title": "Injector Extension",
"default_popup": "popup.html"
},
"options_page": "options.html",
"background": {
"page": "background.html"
},
"permissions": [
"tabs",
"http://*/*",
"https://*/*",
"unlimitedStorage"],
"content_scripts": [{
"matches": [" (injector specific url) "],
"js": ["contentscript.js"]
}],
"web_accessible_resources": ["js/script.js"]
}
content script
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.method == "fromPopup") {
// Send JSON data back to Popup.
sendResponse({data: "from Content Script to Popup"});
} else {
sendResponse({}); // snub them.
}
});
popup
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {method: "fromPopup", tabid: tab.id}, function(response) {
console.log(response.data);
});
});
chrome.extension.onRequest.addListener works only in extension context. It won't run inside a content script.
chrome.extension.sendRequest works in content script context
Update accordingly and will work.
Edit: Exemplifying simple message passing:
Extension script:
chrome.extension.onRequest.addListener(function(r,s,sr){
if(r==='HELLO') return sr.call(this,'BACK AT YOU');
});
Content script:
chrome.extension.sendRequest('HELLO', function(data){ alert(data); });
// will alert "BACK AT YOU"

Categories

Resources