content script can not handle message from background after chrome.tabs.executeScript - javascript

chrome : 54.0.2840.87
This is my first chrome extension and I am new to javascript.
my manifest.json :
"background": {
"persistent": true,
"scripts": ["lib/jquery/jquery-3.1.1.min.js", "background.js"]
},
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["content-scriptA.js",
"lib/jquery/jquery-3.1.1.min.js"],
"css": ["res/css/ms-0.0.1.css"]
}],
"content_security_policy": "script-src 'self' https://connect.facebook.net; object-src 'self'",
"permissions": [
"activeTab",
"tabs",
"storage",
"identity",
"<all_urls>"
],
background.js :
chrome.runtime.onMessage.addListener(function(request, sender, sendResponse) {
if (message_from_A) {
chrome.tabs.query({currentWindow: true, active: false}, function(tabs) {
chrome.tabs.executeScript(null, {file: "content-scriptB.js"});
});
}
if (message_from_B) {
chrome.tabs.query({currentWindow: true, active: false}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {to : "A", do: "..."});
});
});
and
chrome.runtime.onMessage.addListener(function(request, sender, response) {
console.log("...");
});
handlers for content-scriptA.js, content-scriptB.js each.
content-scriptA is for rendering A.html, content-scriptB is for rendering B.html in the same iframe while using my extension.
What I want do is when user wants to go back to A.html from B.html, render A.html with content-scriptA.js.
When I execute content-scriptB.js I thought both A.js and B.js are going, but when I sendMessage from background, none of them answered.
I tried to use port, reload same script and so on, but still can't find the way TT
Thanks for any help, and reading my question.

Related

Sending HTMLVideoElement with chrome.runtime.sendMessage?

I'm pretty new to chrome extension development, I'm trying to make a better PiP (Picture in Picture) that doesn't have the maximum window size limitation.
I'm using this extension as reference, it basically behaves the same way as the default PiP works with video.requestPictureInPicture() which is what I don't want to use because extension popup has limited window size.
Instead, I have a index.html page with my extension that is loaded with window.open in background.js, this index page will have a video element that the HTMLVideoElement is passed to.
I've tried using chrome.runtime.sendMessage to send the video to the video.js that the index.html page loads, but this doesn't seem to work with a HTMLVideoElement? I read elsewhere that I should do JSON.stringify/JSON.parse for this object but that results in undefined.
Relevant manifest.json:
"background": {
"service_worker": "background.js"
},
"content_scripts": [{
"all_frames": true,
"js": [ "content.js" ],
"matches": [ "*://*/*" ],
"run_at": "document_start"
}],
"web_accessible_resources": [{
"resources": [ "index.html" ],
"matches": [ "*://*/*" ]
}],
"manifest_version": 3,
"permissions": [ "storage", "scripting", "activeTab", "tabs" ],
content.js:
const videos = new Set();
window.addEventListener('canplay', e => {
if(e.target.tagName === 'VIDEO') {
videos.add(e.target);
chrome.runtime.sendMessage({
method: 'VIDEO_PLAYING'
});
}
}, true);
background.js:
await chrome.scripting.executeScript({
...
var win = window.open(chrome.runtime.getURL('index.html'), 'PiP');
win.focus();
chrome.runtime.sendMessage({
method: 'VIDEO',
data: JSON.stringify(video)
});
video.js: - this is the js that is just included on index.html
const onMessage = (request, sender) => {
if(request.method === 'VIDEO') {
var data = JSON.parse(request.data);
console.log(video.src); //undefined
}
};
chrome.runtime.onMessage.addListener(onMessage);
Maybe my method of going about doing this is entirely wrong. Are there other ways I can pass such objects to index.html like this?

Popup.html is the same in all tabs (Chrome extension)

My extension checks for broken images on a website. Everything works fine if I open an URL at a time but if I open several URLs from one site, the summary in popup.html is always the same as the active tab (it's not updated for each site).
I don't know how to refer to the actual URL of the analysis and avoid the "active tab". Any ideas?
Manifest.json
{
"name": "Test",
"permissions": ["activeTab", "declarativeContent", "storage","tabs"],
"version": "1.0.0",
"description": "Test",
"background": {
"scripts": ["background.js"],
"persistent": false
},
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*", "https://www.google.com/_/chrome/newtab*"],
"exclude_globs": ["*#*"],
"js": ["jquery-3.4.1.min.js", "content.js"]
}
],
"web_accessible_resources": ["popup.html"],
"browser_action": {
"default_icon": {
"16": "images/ico.png",
"32": "images/ico.png",
"48": "images/ico.png",
"128": "images/ico.png"
}
},
"manifest_version": 2
}
Content.js
chrome.runtime.onMessage.addListener((msg, sender, response) => {
if (msg.subject === 'DOMInfo') {
var domInfo = {
images: number_images
};
response(domInfo);
}
});
Popup.js
window.addEventListener('DOMContentLoaded', () => {
chrome.tabs.query({
active: true,
currentWindow: true
}, tabs => {
chrome.tabs.sendMessage(
tabs[0].id,
{subject: 'DOMInfo'},
setDOMInfo);
});
});
I'm pretty sure is the tabs[0].id that causes the problem but I'm not sure how I can refer to the current URL that run the content.js script and make sure the popup.html gets the analysis from this URL. Any ideas?
In the background.js I had no problem referring the sender tab:
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse)
{
chrome.tabs.query({active:true, windowType:"normal", currentWindow: true},function(d){
var tabId = sender.tab.id;
....
Assuming popup.html is loaded into an iframe inside the web pages by your content script, you need chrome.tabs.getCurrent that returns the tab where this code is running so each iframe will find its own tab:
chrome.tabs.getCurrent(tab => {
chrome.tabs.sendMessage(tab.id, {subject: 'DOMInfo'}, callback);
});
P.S. When using sender.tab.id you don't need chrome.tabs.query - you already have the id.

Firefox addon: sendMessage not working in tabs.onUpdated but does in browserAction.onClicked (background.js)

I'm working on migrating my Chrome extension into a Firefox addon. Honestly didn't think it would be that hard, but I've been trying to fix an issue of the background not wanting to send a message to the content script. (And yes, I've read everything online, but it just won't send the message inside an onUpdated listener)
EDIT
When I tried to put following line into the browserAction.onClicked listener it works, but it does not work in onUpdated?
browser.browserAction.onClicked.addListener(function(tab) {
browser.tabs.sendMessage(tab.id, {action: "isInstalled"});
});
END EDIT
And yes, the content script IS loaded, checked with an alert for the hostname.
Here's the code I used in the Chrome extension (background):
chrome.tabs.query({active: true, currentWindow: true}, ([tab]) => {
chrome.tabs.sendMessage(tab.id, {
action: 'isInstalled'
});
});
Now here's what I have tried in Firefox addon (background):
var gettingActiveTab = browser.tabs.query({active: true, currentWindow: true});
gettingActiveTab.then((tabs) => {
browser.tabs.sendMessage(tabs[0].id, {greeting: "hello"});
});
Which is inside the browser.tabs.onUpdated listener as follows:
browser.tabs.onUpdated.addListener(function(tabId, changeInfo, tabInfo){
if(changeInfo.status === "complete"){
...
}
});
I also tried this, as I thought it would work: (yes tabId is correct).
browser.tabs.sendMessage(tabId, {action: "isInstalled"});
Now here's the onMessage listener on content script
browser.runtime.onMessage.addListener(function(request, sender) {
if(request.action == "isInstalled"){
alert("received");
var isInstalledNode = document.createElement('div');
isInstalledNode.id = 'extension-is-installed';
document.body.appendChild(isInstalledNode);
}
});
I keep getting the following error: "Error: Could not establish connection. Receiving end does not exist." which makes absolutely no sense for me.. Can anyone see the problem?
By the way, here's the manifest file:
{
"name": "Addon name",
"version": "1.3.0",
"manifest_version": 2,
"description": "...",
"icons": {
"48": "assets/images/icon_48_active.png",
"96": "assets/images/icon_96_active.png"
},
"browser_action": {
"default_title": "Name"
},
"background": {
"scripts":["background.js"]
},
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["contentscript.js"]
}
],
"permissions": [
"cookies", "tabs", "http://*/*", "https://*/*"
],
"web_accessible_resources": [
"modal.html", "assets/images/*"
]
}

how to send message from backgroundjs to content script in chrome extension?

I am working on chrome extension and I've stuck on a very specific part where backgroundjs is suppose to send a message to current active tab .
This is my manifest file
manifest.json
{
"manifest_version": 2,
"name": "test",
"description": "Some_Test",
"version": "1.0",
"background": {
"page": "background.html"
},
"content_scripts": [
{
"matches": [ "http://*/*", "https://*/*" ],
"js": [ "content.js" ]
}
],
"permissions": [
"background",
"activeTab",
"tabs",
"http://*/*",
"https://*/*"
],
"browser_action": {
"default_popup": "popup.html"
}
}
popup.html
<html>
<body>
<button id="read-button">Read</button>
<script type="text/javascript" src="popup.js"></script>
</body>
</html>
popup.js
function readObject(e) {
console.log(chrome.extension.getBackgroundPage().read());
}
document.getElementById('read-button').addEventListener('click', readObject);
background.html
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<script type="text/javascript" src="background.js"></script>
</body>
</html>
background.js
function read() {
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.sendMessage(tabs[0].id, { greeting: "hello" }, function (response) {
return response.farewell;
});
});
}
content.js
chrome.runtime.onMessage.addListener(
function (request, sender, sendResponse) {
console.log("hello");
if (request.greeting == "hello")
sendResponse({ farewell: "goodbye" });
});
This is where the error is :
chrome.tabs.sendMessage(tabs[0].id, { greeting: "hello" }, function (response) {
return response.farewell;
});
It seems that I cannot access tabs[0] object or I am unable to understand the Array which it returns, because i want to access the active tab and tabs[0] simply means it is getting the first tab in the browser and not the active tab.
I think this can only happen if the active window is the Developer Tools of the background page.
Just switch to a normal browser window when testing the extension or define read() function in popup.js and remove the background page altogether if it's not absolutely needed.

google chrome extension browserAction.onClicked

i can't figure out how to make it work. My script works by itself. but doesn't work with background.js. I want my google extension to work only if the user clicks on it's icon, so I have created the file background.js and putted the code:
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, {file: "change_content.js"});
});
my manifest.json here:
{
"manifest_version": 2,
"name": "Name",
"description": "change content.",
"version": "3.0",
"browser_action": {
"default_icon": "icon.png"
},
"content_scripts": [
{
"matches": ["http://*/*"],
"js": ["change_content.js"]
}
],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"permissions": [
"tabs", "http://*/*"
]
}
and here is the change_content.js:
var oldSource = document.documentElement.innerHTML;
document.body.innerHTML = changeContent(oldSource);
function changeContent(source){
.....
}
The reason you are having the issue where change_content.js is executing before you press the button is because thats how content scripts work. If you include a content script in your manifest.json it will load and execute that script. Try removing the "content_scripts" section from the manifest and you should see it work as it should.
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null, {file: "change_content.js"});
});
I've got a feeling the error lies in you using "null" as it might be searching for a tab with the tabId - null, you should try doing this instead?
chrome.tabs.executeScript({file: "change_content.js"});

Categories

Resources