My manifest:
{
"name":"name",
"version":"0.1",
"manifest_version":2,
"description":"name app",
"background":{
"scripts":[
"scripts/modernizr.min.js",
"scripts/background.js"
],
"persistent": false
},
"content_scripts": [
{
"matches": ["https://*/*", "http://*/*"],
"js": ["scripts/content.js"],
"run_at": "document_end"
}
],
"permissions":[
"contextMenus",
"tabs",
"http://*/*",
"https://*/*"
],
"icons":{
"16":"images/icon_16.png",
"128":"images/icon_128.png"
}
}
Background.js has a function that is called:
chrome.contextMenus.onClicked.addListener( function( info, tab )
{
... stuff ...
chrome.tabs.sendMessage( tab.id, { action: "showLibraryUI", library: library }, function( response ){} );
} );
In content.js I have a function that listens, but it is never called:
chrome.runtime.onMessage.addListener( function( request, sender, sendResponse )
{
...stuff...
} );
In _generated_background_page.html for the extension I see this:
Port: Could not establish connection. Receiving end does not exist.
lastError:29
set lastError:29
dispatchOnDisconnect miscellaneous_bindings:259
I couldn't find a solution for manifest > 2.0 in the other posts here on SO.
I found the solution to my problem. I had a syntax error in my content.js. This resulted in the content.js not running, and the listener not being present.
Related
I have developed a Chrome extension
On Chrome everything works as I expect
I am now trying to migrate the extension to Firefox
It tells me that the developed extension is compatible with Firefox (I used this link https://www.extensiontest.com/)
However, I have some problems
I have a devtools_script ("VariableGrid.js") which sends messages to the ContentScript via chrome.tabs.query
chrome.tabs.query({ active: true, currentWindow: true }, function (tabs) {
chrome.tabs.sendMessage(chrome.devtools.inspectedWindow.tabId, { from: "FromExample", message: "MessageExample" }, (response) => {
......
});
});
My ContentScript replies to the message like this
chrome.runtime.onMessage.addListener(
(request, sender, sendResponse) => {
......
});
On Firefox chrome.tabs is undefined
I tried using browser.tabs but it's the same
I read that tabs can only be used on background script
Why does this work on my Chrome extension and not on Firefox?
If I tried to move that piece of code to the background script I would still have a problem:
chrome.devtools.inspectedWindow.tabId is undefined
my Manifest is like this
{
"browser_specific_settings": {
"gecko": {
"id": "addon#example.com",
"strict_min_version": "42.0"
}
},
"name": "xxxx",
"description": "xxxx",
"version": "0.0.0.1",
"browser_action": {
"default_popup": "Popup.html"
},
"manifest_version": 2,
"background": {
"scripts":["jquery.min.js", "background.js"],
"persistent": true
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["jquery.min.js", "Content.js"]
}
],
"web_accessible_resources": [
"Content.js"
],
"devtools_page": "Devtools.html",
"permissions": [
"webRequest",
"webRequestBlocking",
"tabs",
"activeTab",
"notifications",
"storage",
"http://*/",
"https://*/",
"<all_urls>"
]
}
I am creating a Firefox extension, where I want to get the stack trace each time a network request is sent. Currently, I inject a content script to access the stack but cannot get the content script to send the stack trace back to background script. Specifically, I listen for a message in content script (from background script) with browser.runtime.onMessage.addListener and call my code in the content script to get me the stack trace but it seems that when I am inside the browser.runtime.onMessage.addListener I cannot call JS methods that I injected with the content script. Any ideas on how I can get the stack trace when a network request is initiated?
background.js:
browser.webRequest.onBeforeSendHeaders.addListener(
function (details) {
if (details.tabId == -1) {
return;
}
browser.tabs.sendMessage(details.tabId, { content: details.url });
},
{
urls: [
"http://*/*",
"https://*/*",
],
},
["requestHeaders", "blocking"]
);
content_script.js
function getPageScript() {
return "function codeToInject() {console.trace();} codeToInject();";
}
function insertScript(text) {
var parent = document.documentElement,
script = document.createElement('script');
script.text = text;
script.async = false;
parent.insertBefore(script, parent.firstChild);
}
browser.runtime.onMessage.addListener(returnStack);
function returnStack() {
insertScript(getPageScript());
}
manifest.json
{
"manifest_version": 2,
"name": "call-stack-retrieval",
"version": "0.0",
"background": {
"persistent": true,
"scripts": [
"background.js"
]
},
"content_scripts": [{
"all_frames": true,
"js": [
"content_script.js"
],
"match_about_blank": false,
"matches": [
"<all_urls>"
],
"run_at": "document_start"
}],
"permissions": [
"tabs",
"<all_urls>",
"contextMenus",
"webRequest",
"webRequestBlocking",
"webNavigation",
"storage",
"unlimitedStorage",
"notifications"
]
}
Does chrome have an api to disable (and thus gray out) chrome extensions on certain urls or do I just have to have a if statement that checks the url and switches out the icon accordingly?
You could use chrome.declarativeContent, it allows you to show page action depending on the URL of a web page and the CSS selectors its content matches.
You could create conditions ( yes, you could use regex) and actions ( ShowPageAction SetIcon) via a constructor like new chrome.declarativeContent.PageStateMatcher and new chrome.declarativeContent.ShowPageAction(). Detailed sample are listed in the api documentation.
var rule2 = {
conditions: [
new chrome.declarativeContent.PageStateMatcher({
pageUrl: { hostEquals: 'www.google.com', schemes: ['https'] },
css: ["input[type='password']"]
}),
new chrome.declarativeContent.PageStateMatcher({
css: ["video"]
})
],
actions: [ new chrome.declarativeContent.ShowPageAction() ]
};
chrome.runtime.onInstalled.addListener(function(details) {
chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
chrome.declarativeContent.onPageChanged.addRules([rule2]);
});
});
add to manifest.js:
"background": { "scripts": ["background.js"] },
"content_scripts" :[
{
"matches" : [
"*://*.example.com/*"
],
"js" : ["main.js"],
"run_at" : "document_idle"
}
]
main.js:
chrome.runtime.sendMessage({type:'showPageAction'});
background.js:
chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){
if(message.type === 'showPageAction'){
chrome.pageAction.show(sender.tab.id);
}
});
You use browserAction instead of browserAction, but there are some things to note:
According to my test, you cannot use "<all_urls>" and "activeTab" in "content_scripts" and "Permissions", otherwise the icon will always be colored.
"content_scripts": [
{
"matches": ["<all_urls>"], // error
"js": ["content.js"],
}
],
"permissions": ["<all_urls>", "activeTab", "storage", "tabs", "declarativeContent"], // error
narrow down
"content_scripts": [
{
"matches": ["http://127.0.0.1/*"],
"js": ["content.js"],
}
],
"permissions": ["storage", "tabs", "declarativeContent"],
background.js
let rule1 = {
conditions: [
new chrome.declarativeContent.PageStateMatcher({
pageUrl: { hostEquals: '127.0.0.1' },
}),
],
actions: [new chrome.declarativeContent.ShowPageAction()],
};
chrome.declarativeContent.onPageChanged.removeRules(undefined, data => {
chrome.declarativeContent.onPageChanged.addRules([rule1], data => {
console.log('addRules', data);
});
});
The removeRules operation is performed because the rule will be added repeatedly every time the extension is refreshed.
Reference question link
https://stackoverflow.com/a/63434774/9854149
I got this error with below code :
Could not establish connection. Receiving end does not exist.
my background.js
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {greeting: "hello"}, function(response) {
if(chrome.runtime.lastError) {
console.error(chrome.runtime.lastError.message);
return;
}
console.log(response.farewell);
console.log('ytr');
});
});
and my contentScript.js
chrome.extension.onMessage.addListener(function (request, sender, sendResponse) {
alert(request.greeting);
});
part of my manifest.json
"background": {
"scripts": ["background.js"]
},
"permissions": [
"https://*/*",
"http://*/*",
"activeTab",
"storage",
"tabs"
],
"content_scripts": [
{
"matches": ["https://*/*", "http://*/*"],
"js": ["jquery.js","contentScript.js"],
"css": ["style.css"]
}
]
I wonder what's wrong in my case.
You are probably running this code while the devtools window is active. I can reproduce the problem by running that code from the background page console, but not when a regular tab is active. Try running console.log("URL = " + tabs[0].url) to see if the active tab is the one you really expect it to be.
I got result but it returns two alerts "Content: This is a test" but in scripts I send only 1 post.
It works perfect but two answers is too annoying. Help pls.
Manifest:
{
"name": "Test",
"version": "1.0",
"manifest_version": 2,
"description": "Test",
"background": {
"scripts": ["event.js"],
"persistent": true
},
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
"permissions": [ "tabs", "http://*/*", "https://*/*" ],
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["content.js"],
"run_at": "document_end",
"all_frames": true
}
],
"browser_action": {
"name": "Do Action",
"default_icon": "icon.png",
"default_popup": "popup.html"
}}
Popup script.js:
$("#myButton").click(function(){
chrome.tabs.getSelected(null, function(tab)
{
chrome.tabs.executeScript(tab.id, { file: "content.js" }, function()
{
var port = chrome.tabs.connect(tab.id, { name: "port-conn" });
port.postMessage({ data: "This is a test" });
port.onMessage.addListener(function (msg)
{
alert("Content: " + msg.answer);
});
});
});
}...
content.js:
chrome.extension.onConnect.addListener(function(port) {
port.onMessage.addListener(function(msg) {
port.postMessage({answer: msg.data});
});
});
Content.js is specified first in manifest so it is now loading when your extension is loaded. Then you are using it via executeScript so it runs the second time.
do these changes.
Popup script.js:
chrome.tabs.getSelected(null, function(tab){
var port = chrome.tabs.connect(tab.id, { name: "port-conn" });
port.onMessage.addListener(function (msg)
{
alert("Content: " + msg.answer);
});
$("#myButton").click(function(){
port.postMessage({ data: "This is a test" });
});
});
That is the point of messaging. if it did not work then you HAVE TO USE BACKGROUND SCRIPT AS WELL that just forwards message between content and popup
Problem solved.
In manifest
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["content.js"],
"run_at": "document_end",
"all_frames": true
}
],
it runs content.js on every page and
{ file: "content.js" }
Run it again in active tab. So thats why one tab run content twice.