This question already has an answer here:
executeScript is undefined or not a function in a ManifestV3 extension
(1 answer)
Closed 1 year ago.
I am trying to change chrome extension from manifest_version 2 to manifest_version 3.
Something about the executeScript doesn't work for me...
TypeError: Cannot read property 'executeScript' of undefined
That's part of my code:
chrome.webRequest.onResponseStarted.addListener(
details => {
chrome.scripting.executeScript(
{
target: { tabId: details.tabId },
files: ['foreground.js']
},
() => { });
},
{ urls: filteredURLs });
Thanks :)
Just added "scripting" to my "permissions".
{
...
"manifest_version": 3,
"background": {
"service_worker": "background.js"
},
"permissions": [
"webRequest",
"scripting"
],
...
}
Related
Problem
My chrome extension needs to inject the content script into all tabs when switched on and then when any new tabs are loaded etc.
By adding the content script to the manifest file I can satisfy the second requirement of having it loaded in newly loaded tabs.
To make it also inject the content script into tabs as soon as the extension is loaded or refreshed (there is no popup), I am using chrome.scripting.executeScript.
Problem is each time the extension is turned off/on or refreshed, the content script is loaded in again and any DOM manipulation from content script occurs multiple times.
So from reading another post, I liked the idea of sending a message to the content script, if I don't get a response (undefined) then I inject the script into this tab, if I do get a response then do nothing.
In my background logs I get this error Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist. which is what I would expect if the content script did not exist, but even when the content script is clearly being loaded, I still get the same error.
Any help greatly appreciated. And maybe this is not even the best approach for this, I am not sure. Ideally I would also want the extension to immediately stop working when it's turned off, but I haven't got around to this problem yet.
Manifest
{
"name": "Text highlighter",
"description": "Text highlighter",
"version": "1.0.0",
"manifest_version": 3,
"background": {
"service_worker": "background.js"
},
"options_ui": {
"page": "options.html",
"open_in_tab": false
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"],
"css": [ "styles.css" ]
}
],
"permissions": ["storage", "activeTab", "scripting", "tabs"],
"host_permissions": ["<all_urls>"]
}
self.oninstall = () => {
chrome.tabs.query({}, function(tabs) {
tabs.forEach((tab) => {
chrome.tabs.sendMessage(tab.id, true, (response) => {
console.log('response', response);
if(!response) {
chrome.scripting.executeScript({
target: {tabId: tab.id},
files: ['content.js']
});
chrome.scripting.insertCSS({
target: { tabId: tab.id },
files: ['styles.css']
});
}
});
});
});
};
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
console.log('request', request);
sendResponse(true);
return true;
});
I'm trying to reproduce this example with the manifest v3. But my action is always active - I expext it to be disabled on all pages without 'g' in a URL.
Thanks in advance!
manifest.json
{
"name":"Example",
"description":"description",
"version":"0.1",
"manifest_version":3,
"background":{
"service_worker":"background.js"
},
"permissions":[
"declarativeContent"
],
"action":{
"default_icon":{
"16":"/images/get_started16.png",
"32":"/images/get_started32.png",
"48":"/images/get_started48.png",
"128":"/images/get_started128.png"
},
"default_title":"press here to open"
},
"icons":{
"16":"/images/get_started16.png",
"32":"/images/get_started32.png",
"48":"/images/get_started48.png",
"128":"/images/get_started128.png"
}
}
background.js
chrome.runtime.onInstalled.addListener(() => {
// Replace all rules ...
chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
// With a new rule ...
chrome.declarativeContent.onPageChanged.addRules([
{
// That fires when a page's URL contains a 'g' ...
conditions: [
new chrome.declarativeContent.PageStateMatcher({
pageUrl: { urlContains: 'g' },
})
],
// And shows the extension's page action.
actions: [ new chrome.declarativeContent.ShowPageAction() ]
}
], function callback(details) {
console.log("chrome.declarativeContent.onPageChanged.addRules callback");
console.log(details);
});
});
});
as wOxxOm mentioned
this answer helped.
I follow the 'Getting started' tutorial of chrome extensions, but I get the below error.
I search google, somebody say can't access 'executeScript' in content.js, but the error is from popup.js.
I had tried change 'chrome.scripting.executeScript' to 'chrome.tabs.executeScript', it didn't work too.
error image
manifest.json
{
"name": "Getting Started Example",
"version": "1.0",
"description": "Build an Extension!",
"permissions": ["storage", "declarativeContent", "activeTab"],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"page_action": {
"default_popup": "popup.html"
},
"options_page": "options.html",
"manifest_version": 2
}
popup.js
let changeColor = document.getElementById('changeColor')
chrome.storage.sync.get('color', function(data) {
changeColor.style.backgroundColor = data.color;
changeColor.setAttribute('value', data.color)
});
changeColor.addEventListener('click', () =>
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.scripting.executeScript(
tabs[0].id,
{ function: setColor })
})
);
async function setColor() {
let {color} = await chrome.storage.sync.get(['color']);
document.body.style.backgroundColor = color;
};
The whole extension code
reference: chrome developers -> Getting started
The permissions in your manifest.json is missing one item, which is "scripting".
It should look like this:
…
"permissions": ["storage", "declarativeContent", "activeTab", "scripting"],
…
This is actually seen on the Getting Started page here.
You need scripting permissions to access scripting APIs. Add scripting to your manifest.js file.
"permissions": ["scripting", ...]
You either need to migrate to manifest v3 or use chrome.tabs.executeScript instead of chrome.scripting.executeScript
In my case, the exception log "Cannot read property 'executeScript' of undefined" was pretty misleading.
With correct manifests, it happened, and it was because of typo in the to be injected function, like below.
document.body.style.backgrounColor = color;
corrected it to
document.body.style.backgroundColor = color;
and it worked.
Remove and load the extension back! Despite adding "permissions": ["scripting"] this is what I had to do.
I found that chrome.scripting.executeScript works in popup but not in content scripts.
This is a super simple popup example in React. You click on the button and it shows the page title.
export function Popup() {
const [title, setTitle] = useState("");
const onClick = async () => {
const [tab] = await chrome.tabs.query({ currentWindow: true, active: true });
const [res] = await chrome.scripting.executeScript({
target: { tabId: tab.id },
func: () => document.title,
});
setTitle(res.result);
};
return (
<div className="popup">
<button onClick={onClick}>Click</button>
{title}
</div>
);
}
Recently, it is reported that the context menu of my app is vanished. If you remove the app and reinstall it, it works. But the vanishment happens again.
I found an error. I'm not sure if the error causes the vanishment of the context menu. But I'd like to fix this matter, because all I found is this.
This app shows texts you select in a page. When you select texts in an ordinaly page and click browser action button, it works without error. But if you try it on Google Docs, you will get error "Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist".
I'm afraid I don't know what to do with this. And I might have two problems. It'll be great help if you could give me some advice.
[manifest.js]
{
"manifest_version": 2,
"name": "Test Chrome Extension",
"short_name": "Test",
"version": "1.0",
"description": "This is a test.",
"icons": {
"128": "128.png"
},
"content_scripts": [{
"matches": ["<all_urls>"],
"js": ["googleDocsUtil.js", "content_scripts.js"]
}],
"background": {
"scripts": ["background.js"],
"persistent": true
},
"browser_action": {
"default_icon": {
"48": "48.png"
},
"default_title": "Test Chrome Extension"
},
"permissions": [
"contextMenus",
"tabs",
"background",
"http://*/*",
"https://*/*"
]
}
[background.js]
chrome.contextMenus.create({
type: 'normal',
id: 'testchromeextension',
title: 'Test Chrome Extension',
contexts:['selection']
});
chrome.contextMenus.onClicked.addListener(function(info,tab){
if( info.menuItemId == 'testchromeextension' ){
var selectedText = info.selectionText.replace(/ /g, "\n");
doSomething(selectedText);
}
});
chrome.browserAction.onClicked.addListener( function(tab) {
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, {method: "getSelection"}, function(response) {
doSomething(response.data);
});
});
});
function doSomething(selectedText) {
console.log(selectedText);
}
[content_scripts.js]
chrome.runtime.onMessage.addListener( function(request, sender, sendResponse) {
if (request.method == "getSelection") {
var post_val = window.getSelection().toString();
if ( !post_val ) {
var googleDocument = googleDocsUtil.getGoogleDocument();
post_val = googleDocument.selectedText;
}
sendResponse({data: post_val});
}
});
I believe this error is caused when you update the local version of an extension and then try to use the extension with its old/not-updated source code.
The fix: after you reload your local extension at chrome://extensions/, make sure you refresh the page you're using the extension on. You should no longer see the error.
I just updated my chrome extension to json version 2, and am trying to get my extension to work again. The problem is sendRequest was depreciated along the way. So I copy the code from https://developer.chrome.com/extensions/messaging.html into my script and modify it to my own variable names, and it doesn't work.
So then I go back and put in the original code and it still doesn't work. I have read multiple questions that are similar [and hopefully this won't get closed as a duplicate, because none of them were the same as my situation].
manifest.json:
{
"background": {
"page": "background.html"
},
... ... ...
"content_scripts": [ {
"css": [ "style.css" ],
"js": [ "jq.js", "script.js" ],
"matches": [ "http://*.craigslist.org/*/*.htm*" ]
} ],
... ... ...
"permissions": [ "tabs", "http://*.craigslist.org/*/*.htm*" ],
"manifest_version": 2,
"update_url": "http://clients2.google.com/service/update2/crx",
"version": "3.0"
}
background.html:
<html>
<script type='text/javascript'>
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
console.log(sender.tab ?
"from a content script:" + sender.tab.url :
"from the extension");
if (request.greeting == "hello")
sendResponse({farewell: "goodbye"});
});
});
</script>
</html>
script.js:
chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
console.log(response.farewell);
});
Now I run a page [on craigslist], and go to the Console and this is the error:
Port error: Could not establish connection. Receiving end does not exist.
TypeError: Cannot read property 'farewell' of undefined
at chrome-extension://dhmjefbokfkjpdbigkadjpgjeflchgea/script.js:9:23
I use Chrome Beta on Ubuntu 12.10 64-bit (Google Chrome: 27.0.1453.15 (Official Build 191758) beta)
You are sending messages from both your background and your content script, but not trying to receive them at all. Try listening for messages in one or both of those places. Also, inline code is against the CSP so move it all to an external file.
For example:
manifest.json
"background": {
"scripts": ["background.js"]
},
background.js
chrome.runtime.onMessage.addListener(function(message,sender,sendResponse){
sendResponse({farewell:"goodbye"});
});
script.js
chrome.runtime.sendMessage({greeting: "hello"}, function(response) {
console.log(response.farewell);
});
Also, chrome.tabs.getSelected() has been deprecated as well, so use chrome.tabs.query() instead.
background script
chrome.tabs.getAllInWindow(null, function(tabs) {
$.each(tabs, function() {
chrome.tabs.sendRequest(this.id, {"action":"action_name"} );
});
});
content script
chrome.extension.onRequest.addListener(function(request, sender, sendResponse){
if(request.action === 'action_name')
{
alert('handle event in the content script!!!!')
}
});