Chrome Extension Manifest V3 Libraries in Background - javascript

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.

Related

Trouble with Injecting Content Scripts into Chrome Tab (Manifest V3)

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!

Is my Chrome extension code correct (Google rejected it but it works locally)?

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/

Security error in firefox ext while fetching a file

While fetching a files contents with the following code in a background.js file:
function readFile(filename) {
let response = fetch(`file:///${filename}`);
console.log(response);
}
I get the following error:
Security Error: Content at moz-extension://86d386b7-2904-441f-8dbe-47f0af9b6bfb/_generated_background_page.html may not load or link to file:///C:/Users/rando/Downloads/jest-26.6.1.zip.
TypeError: NetworkError when attempting to fetch resource.
My manifest file looks like this:
"permissions": [
"webNavigation",
"webRequest",
"webRequestBlocking",
"cookies",
"tabs",
"http://*/*",
"https://*/*",
"ws://*/*",
"wss://*/*",
"storage",
"downloads",
"sessions",
"file://*/*"
],
"background": {
"scripts": [
"app/scripts/background.js"
],
"persistent": true
},
How do I solve this error and fetch the contents of the file using the background.js file?
Extension access to local file system file:/// has been blocked since Firefox 57 for security reasons.
Extensions can use the input type="file" to launch the file picker on user-click.
Extensions also can:
read files that are packed within the extension
communicate with a software on the local computer via Native messaging
get files via HTTP/s, if the localhost has a server running

Should manifest.json reference auth.js?

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.

Use AngularJS in a Chrome extension

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.

Categories

Resources