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

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"]
}

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

Call API from popup.js to background script through message passing in Chrome Extension

I would like to call an API when a button is pressed on extension popup. But the API is not called and unable to retrieve any response from fetch API.
I tried the followings:
Added API endpoint to host_permissions in manifest file.
Created a UI with a button. The UI shows when I click the extension icon.
In popup.js, added event handler to the button. When button is clicked it sends a message to the background.js file with API URL.
In background.js, I have added a listener to listen the message and call the API.
manifest.js
{
"name": "Product Extractor Extension",
"description": "Extract product data from predefined websites.",
"version": "1.0",
"manifest_version": 3,
"permissions": [
"storage",
"activeTab",
"scripting"
],
"host_permissions": [
"https://jsonplaceholder.typicode.com/*"
],
"action": {
"default_popup": "popup.html",
"default_title": "Kevin"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
],
"background": {
"service_worker": "background.js"
}
}
popup.html
<button class="signInButton" id="signInButton">
Sign In
</button>
popup.js
document.getElementById("signInButton").onclick = function() {
chrome.runtime.sendMessage({
contentScriptQuery: "userLogin",
url: 'https://jsonplaceholder.typicode.com/todos/1'
}, function(response) {
console.log(response);
});
}
background.js
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
switch (request.contentScriptQuery) {
case "userLogin":
fetch("https://jsonplaceholder.typicode.com/todos/1")
.then((response) => response.json())
.then((json) => sendResponse("kerk"));
break;
}
return true;
});

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 Extensions content calls callback to background but parameter is undefined

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.

How To Initiate A Message Request From Content Script On Tab Change?

I've an extension which need to keenly keep an eye on the URL of the very active tab in the browser [chrome]. Currently, I've been able to track those URL's which user load/reload from start. But if there is a tab change, the content script doesn't send message to background script and get back anything.
In fact I want to reload content.js script on tab change of user as well.
Here's what I've done till now:
CONTENT.JS:
// Code here....
chrome.extension.sendMessage({ wants: 'URL' }, function(res) {
var urlResponse = res.url;
});
// Code here....
Works pretty well, but this content.js doesn't fire on tab change. Instead it fires when a document is changed in same tab (like visiting new link, etc)
BACKGROUND.JS:
chrome.extension.onMessage.addListener(
function(script, sender, sendResponse) {
if (script.wants == 'URL') {
sendResponse({ maskedURL: sender.tab.url });
}
}
);
MANIFEST.JSON:
{
"manifest_version": 2,
"name": "NAME HERE",
"description": "DESC HERE",
"version": "1.1",
"options_page": "options.html",
"browser_action": {
"default_title": "NAME",
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"icons": { "16": "icon.png",
"48": "icon.png",
"128": "icon.png" },
"permissions": [
"storage",
"<all_urls>",
"tabs"
],
"content_scripts": [
{
"matches": ["http://*/*","https://*/*"],
"js": ["content.js"]
}
],
"web_accessible_resources": [
"bg.png",
"*.woff",
"*.woff2"
],
"background": {
"scripts": ["background.js"]
}
}
Thank you!
EDIT: Xan please have a look:
Could not understand your question properly but I will try to clarify to the best of my knowledge.
content.js is run once when a new page is opened or an existing page is refreshed.It cant access the details of the currently active tab.
If you want to know about any details of the tabs,use chrome.tabs API in background.js
chrome.tabs.onActivated.addListener(activeInfo){ //Fired when an active tab is changed
chrome.tabs.query({'active':true,'currentWindow':true},function(array_of_tabs){//Gives details of the active tab in the current window.
alert(array_of_tabs[0].url);
});

Categories

Resources