I'm building a Chrome Extension that needs to detect DOM events (click, mouseover, etc.) on any tab the user switches to or opens during a recording session. The way that seems most appropriate to do this is using the scripting API to inject a script that set's the appropriate event listeners and can post messages back to the chrome.runtime API to collect data.
However, I'm unable to inject the content Script successfully. My project is a Vue3 + Vite + Manifest V3 Chrome Extension, and in my background.js on the appropriate chrome.tabs listeners I'm executing:
chrome.scripting.executeScript({
target: { tabId },
files: ['src/content_scripts/events.js']
});
The documentation clearly states that a relative path from the directory root is required. However, no matter how I structure that path, it says the file isn't found.
The exact error I'm receiving is:
Uncaught (in promise) Error: Could not load file: 'src/content_scripts/events.js'.
Also, my manifest.js file is:
{
"manifest_version": 3,
"name": "walkthrough.ai capturer",
"version": "1.0.0",
"icons": {
"16": "icons/icon16.png",
"32": "icons/icon32.png",
"48": "icons/icon48.png",
"128": "icons/icon128x128.png"
},
"permissions": [
"desktopCapture",
"tabCapture",
"scripting",
"activeTab",
"tabs"
],
"host_permissions": ["https://*/*", "http://*/*"],
"action": {
"default_icon": {
"16": "icons/icon16.png",
"32": "icons/icon32.png"
},
"default_title": "Open Options"
},
"background": {
"service_worker": "src/background/index.js",
"type": "module"
}
}
Any ideas on what could be happening?
Thank you
How about using
chrome.runtime.getURL('where content script is from you are calling this API')
instead of moving the content script file to public folder?
That way I get my file path correctly after building the project.
After doing some more digging on #wOxxOm 's suggestion, I was able to figure it out.
The content script wasn't showing up in the build folder, which is where the scripting API was looking for it to be a relative import from.
In order to solve the issue, I put the content script in my /public folder so that it gets placed in the /dist folder when the project is built.
This worked for now. Thank you!
Related
I'm in the process of updating my chrome extension from manifest v2 to v3.
Here's the old manifest:
Manifest V2:
{
"manifest_version": 2,
"name": "Legacy Search Assistant",
"version": "0.1.1",
"content_scripts": [
{
"matches": [
"https://*.legacysite.io/*","*://*/api*"
],
"js": ["jquery-3.6.0.min.js","content.js"]
}
],
"options_page": "options.html",
"background": {
"scripts": ["jsencrypt.min.js", "jquery-3.6.0.min.js", "background.js"]
},
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html",
"default_title": "Legacy Search"
},
"permissions": [
"storage"
]
}
Since jsencrypt.min.js was already loaded in the manifest I was able to call it's functions in background.js, but now that I've gone to manifest v3 I am having problems getting the service worker to access this library.
For example, when I make this call in background.js:
importScripts("/scripts/jsencrypt.min.js");
It throws the following error:
Error handling response: Error: Failed to execute 'importScripts' on 'WorkerGlobalScope': The script at 'chrome-extension://<extension ID>/scripts/jsencrypt.min.js' failed to load.
If I click the link in the error it takes me directly to the library I want loaded.
I've already tried all of the fixes in this answer. Please help if you can.
importScripts() is old way to load scripts in workers.
Now we can use more modern, ES modules instead.
Starting from Chrome 91, we can use JavaScript modules in service workers.
Just set type property to module in the manifest.
{
"manifest_version": 3,
"background": {
"service_worker": "background.js",
"type": "module"
}
This loads the service worker as an ES module, which lets you use the import keyword in the service worker to import other modules. Ex-
// background.js
import * as module from './scripts/jsencrypt.min.js';
But make sure that the script you are importing like ./scripts/jsencrypt.min.js in this case, has exported the required code that you want to use.
Learn about ES modules
The solution I ended up using was to move all usage of jsencrypt to the content.js. This allowed the module to function correctly and will not expose the public key in the environment we use our chrome extension in.
After creation and initializing of the jsencrypt object I pass it to the background script via a message.
I've made a Chrome extension that works perfectly fine in dev mode but was rejected for the following reasons:
Violation:
The package contains “MyExt.crx” file which is not a valid file
The “news.js” and other files mentioned in the manifest are not available in the package which is throwing an error while
installing.
How to rectify: Please package your extension properly and re-submit on the developer dashboard.
Additional Information: Permissions usage was not validated as the js files are not available in the package
I wonder if I misunderstood how it's supposed to work and wrongly used content_scripts.
Btw, yes, I did the tutorial and I read the documentation (more than once).
First of all, here is my project, pretty simple:
My popup (when you click the extension) has several checkboxes that store and load their state through chrome.storage.sync.set and chrome.storage.sync.get.
The files news.js and blocks.js change the DOM of the website, depending on the checkboxes.
Here is my manifest:
{
"manifest_version": 3,
"name": "MyExtension",
"version": "1.0",
"description": "Blabla",
"content_scripts": [
{
"matches": ["https://www.randomsite.com/*"],
"js": ["news.js", "blocks.js"]
}
],
"permissions": ["storage"],
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "/images/logo16.png",
"32": "/images/logo32.png",
"48": "/images/logo48.png",
"128": "/images/logo128.png"
}
},
"icons": {
"16": "/images/logo16.png",
"32": "/images/logo32.png",
"48": "/images/logo48.png",
"128": "/images/logo128.png"
}
}
What I wanted to do is the extension to work on randomsite.com only.
I don't understand what is wrong here, does anyone have any idea?
As wOxxOm commented, the problem was the ZIP I submitted. I read somewhere I had to submit the CRX file in a ZIP, but it's not the case. The ZIP must contain the folders and files of the project. The official documentation explains this right: https://developer.chrome.com/docs/extensions/mv3/hosting/
I am developing a chrome extension using react which has a background script and multiple browser action js files. This is my project structure
MyExtension
|__build
|__public
| |__images
| |__scripts
| |__index.html
| |__manifest.json
|
|__src
|
|___browser action js files...
And this is my manifest.json
{
"name": "MyExtension",
"version": "0.0.1",
"manifest_version": 2,
"description": "MyExtension",
"icons": {
"16": "images/icon-16.png",
"128": "images/icon-128.png"
},
"default_locale": "en",
"background": {
"scripts": [
"scripts/background.js"
],
"persistent": false
},
"permissions": [
"background",
"notifications",
"tabs",
"storage",
"alarms",
"webNavigation",
"*://*/"
],
"browser_action": {
"default_icon": {
"16": "images/icon-16.png",
"19": "images/icon-19.png",
"38": "images/icon-38.png",
"128": "images/icon-128.png"
},
"default_title": "MyExtension",
"default_popup": "index.html"
},
"web_accessible_resources": [
"images/icon-48.png"
],
"content_security_policy": "script-src 'self' 'sha256-
5As4+3YpY62+l38PsxCEkjB1R4YtyktBtRScTJ3fyLU='; object-src 'self'"
}
I use the command npm run build for building the project where build is set to react-scripts build. Earlier, I used to debug the browser action files by inspecting the extension popup and setting breakpoints in js files under the src directory in the Source directory of the chrome developer tools window. I used to debug the background script by clicking on the background page link in the chrome://extensions page which is shown in the image below.
But recently, I notice that the browser action source files are not present under the 'Sources' tab as shown in the image below.
I just get two chunk.js files which seem to be the bundled version of all my files in the src directory. They have a lot of auto-generated code and hence I am not able to set breakpoints in the files I want.
Is there any way for me to get the individual source files to appear in the Sources tab of the Developer Tools Window?
Do I need to reference the auth.js in my manifest for this code to work?
I am building a Google Chrome Extension that will provide a YouTube video in a popup after querying YouTube. To do this with javascript, I am told that I must first set up an auth.js.
I built the auth.js just as mentioned here. I made sure to get a project id from the Developer Console.
Here is my manifest.json
{
"manifest_version": 2,
"name": "myOverlay",
"description": "This extension will create a popout that links to a video specific to the current webpage",
"version": "1.0",
"permissions": [
"tabs",
"https://*.youtube.com/",
"https://*.ytimg.com/"
],
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"content_security_policy":
"script-src 'self' https://*.youtube.com https://*.ytimg.com; object-src 'self'"
}
No, just reference auth.js from popup.html like normal.
Any files within the extension directory are found automatically, you don't need to tell the manifest about them.
I want to use AngularJS in a Chrome extension but I have an error like this:
Error: SECURITY_ERR: DOM Exception 18
Error: An attempt was made to break through the security policy of the user agent.
at new listConnection
manifest.json :
{
"name": "Chrome auditor connection",
"version": "1",
"icons": { "48": "icone.png",
"128": "icone.png" },
"description": "Chrome-auditor-connection is an extension for Google Chrome browser. It ensures that nobody connects to your browser with your profile.",
"background": {
"scripts": [
"chrome_ex_oauthsimple.js",
"chrome_ex_oauth.js",
"background.js"
]
},
"browser_action": {
"default_title": "Chrome auditor connection",
"default_icon": "icone.png",
"default_popup": "index.html"
},
"permissions": [
"storage"
],
"web_accessible_resources": ["index.html"],
"sandbox": {
"pages": ["index.html","index.js","angular.min.js"]
},
"manifest_version": 2
}
index.js :
function listConnection( $scope) {
$scope.connections = JSON.parse(localStorage['connectionHistory']);
}
I think the JSON.parse() is blocked by the Chrome "Content Security Policy" (CSP).
Do you have any solution?
Your index.js is sandboxed as defined in your manifest.json file.
"A sandboxed page will not have access to extension or app APIs"
So it can't access localstorage.
Remove the sandbox or use something like https://github.com/jamesmortensen/chrome-sandbox-storageAPI for sandboxed pages.
There are two answers for you:
Add ng-csp to your <html> tag, like this <html ng-csp ng-app="AngularAppName"> . See this SO answer
Add this line to manifest.json file
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self' "
Problems in your code
These are some of problems i see so far with code shared!.
Your index.html is being used as default_popup, web_accessible_resources and in sandbox Pages . It is functionally incorrect, what is you want to develop?
Why do you want to put angular.min.js in sandbox location?
Is index.js used by index.html, if so there is no need to list it explicitly.
Storage is an object per domain, your localstorage differs from sandbox and other pages.