Chrome extension: Could not load javascript file - google-chrome-extension

I have posted another question regarding my Chrome extension here.
But I have one more question about extensions themselves. I only need a content script for the modification of the Tumblr-Dashboard, no background page or something else, right?
Here is the manifest.json file:
{
"name": "Tumblr - Tiled Dashboard",
"version": "0.0.54",
"manifest_version": 2,
"description": "This extension modifies the look of your Tumblr dashboard.",
"icons": {
"16": "images/icon_16.png",
"48": "images/icon_48.png",
"128": "images/icon_128.png"
},
"content_scripts": [
{
"matches": [ "*://*.tumblr.com/dashboard" ],
"css": [ "styles.css" ],
"js": [ "jquery-2.1.3.min.js", "masonry.min.js", "code.js" ]
}
],
"homepage_url": "mypage",
"author": "myname"
}
To start, I ask if this is alright? I have read a lot about the manifest.json file and everything seems to work fine when I try out the extension locally. But when I pack the extension and upload it, there are two problems:
I cannot find the extension when I search for it
When I use the link to find the extension, and I want to install it (tried that on 2 different PCs), I get an error, telling me that the jquery-2.1.3.min.js file could not be loaded. I therefore changed the order of my JavaScript files to test if it was a problem related to the jQuery file, but having masonry.min.js as the first file in the array resulted in the same error.
Why does this happen? Is the manifest.json file ok? Do I need some special permissions?
Edit:
This is a screenshot of when I try to install the extension from the Chrome Web Store (where I also can't find it by search).

I took a look inside your extension's ZIP file before downloading it, and the result was the following:
*Inspected using Chrome extension source viewer by Rob Wu
The problem here, is that you've uploaded a packed CRX file inside of your ZIP file, instead of your extension source code. You should instead upload a ZIP file containing your extension's root. Since that you're including the manifest.json file, the Web Store doesn't notice anything wrong until you try to install the extension, because the manifest is well written, but when Chromes tries to access the files declared, it fails and returns an error, because those files do not exist.
Quoting from the upload page of the Chrome Web Store Developer Dashboard:
Uploading an item:
Upload a ZIP file of your item directory, not a packaged CRX file.
Include a well-designed product icon in your manifest (more info).
Read the documentation about creating and packaging apps.
Need more help? Check out the Chrome Web Store developer documentation.
So, you should create a ZIP file of your extension's root directory, containing all the files of your extension. Your ZIP file should then look like the following:

I had the same "Could not load javascript file" error, then I noticed that my_custom_script.js file was not builded in dist directory (I'm using npm). You can move it manually and try to reload plugin to check is this problem.
Solution to me was adding new entry to webpack.config.js like this:
entry: {
'my_custom_script': './my_custom_script.js',
'background': './background.js',
'popup/popup': './popup/popup.js',
'options/options': './options/options.js',
},

Related

Auto update Chrome extension during development with CI/CD and update.xml

I have a Chrome Extension in development, locally which is a React application.
I have set up a CI/CD pipeline so that the React app is built with yarn build to produce the dist directory containing the app files and the manifest.json. The pipeline then uses this npm package to create the .crx file and upload it to a public storage location along with the update.xml file which has been updated with a new version number and URL to the new .crx file.
I created a private key (key.pem) locally and stored in a key vault so that the "packing" job in CI pipeline uses the same private key each time. The public key has been added to the manifest.json so that the app ID stays the same each time.
Update2.xml
<?xml version='1.0' encoding='UTF-8'?>
<gupdate xmlns='http://www.google.com/update2/response' protocol='2.0'>
<app appid='blahblahooaejaldnohkhmaedknkfogn'>
<updatecheck codebase='https://mypubliccrxstorage.blob.core.windows.net/crx/myapp-1.0.20210702.22.crx' version='1.0.20210702.22' />
</app>
</gupdate>
manifest.json
{
...
"manifest_version": 2,
"version": "1.0.20210702.22",
"key": "<my-public-key",
...
"update_url": "https://mypubliccrxstorage.blob.core.windows.net/crx/update2.xml"
}
Steps to install and update:
Go to chrome://extensions/ > developer mode > load unpacked > select local dist directory.
The unpacked extension appears in the list of extensions with app id: blahblahooaejaldnohkhmaedknkfogn
Select the extension and click "Update"
Expected result:
Chrome queries the remote update.xml file, sees a version later than the initially installed version, downloads and installs the new crx file from the specified location.
Actual result:
The extension is not updated.
Note: I downloaded the crt generated by the CI/CD from the storage location and uploaded it here. The public key shown by that online tool matches the value of key in the manifest.json and the calculated app id matches the one in update.xml.
To dig a little deeper I opened Fiddler4 and sniffed the calls made by Chrome. Although I don't understand everything, part of one of the responses was:
<?xml version="1.0" encoding="UTF-8"?><gupdate xmlns="http://www.google.com/update2/response" protocol="2.0" server="prod"><daystart elapsed_days="5296" elapsed_seconds="28389"/><app appid="mgndgikekgjfcpckkfioiadnlibdjbkf" status="error-unknownApplication"/><app appid="apbllhlpimnkljppmmdbiipfbjjimjgj" cohort="1::" cohortname="" status="ok"><updatecheck _esbAllowlist="false" status="noupdate"/></app></gupdate>
That "app id" is not mine (or is that the Chrome app id?), but the status of "error-unknownApplication" perhaps gives some hint as to what is going on.
No protection setting in Chrome allows an extension to update. This setting also allows to drag and drop .crx into chromium extensions.
Installing the chrome extension by "Load unpacked" button at chrome://extensions "ties" the install to the file system and doesn't allow for updates.
The extension needs to be installed via the .crt file for updating to work.
The ability to do this has been removed in Chrome for security reasons.
However you can use Chrome's developer version, Chromium to install the .crt file by dragging and dropping. Installing in this way allows the extension to be updated using the method in the original question (if everything is configured correctly).
This workaround was acceptable in my case.

Extension loading a content script triggers a warning when published to the chrome web store

I'd like to split my Chrome extension's script into several files. For this purpose, as far as I understand, I need to add a "content_scripts" property to the manifest file. When I publish to the Chrome Web Store, I get a warning message that my extension requires extensive permissions and that reviewing the extension will take more time, and that I'd better do it differently.
Originally, I had one single js file including data and functions. I don't like that, so I wanted to have separate js files for data and functions. So I took the data to a new data.js file and the only way I've found to make it work is to have a "content_script" property inside the manifest file.
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["data.js"]
}
],
The "matches" property seems to be required. My understanding is that this <all_url> value causes the Chrome Store to warn me that this is too much of a permission. They advise me to use "permissions": ["activeTab"] instead. But I already have that in my manifest. So I'm a bit confused as to how I could just add a content script without requiring additional permission, since it's just another embedded js file, and I don't see why that would require more permission than the original background javascript file.
Finally, I managed using several separate js files by referencing them from the background script :
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(tab.id, {file:"script1.js"});
chrome.tabs.executeScript(tab.id, {file:"script2.js"});
});
It works fine, and doesn't cause the Chrome Web Store to prompt a permission warning. So it seems a much better way for what I intended to do.

Check if Chrome extension installed in unpacked mode

Is there a way to detect whether I'm running an extension that was installed from my .crx file or the extension was loaded as via 'Load unpacked extension...' button?
I'm aware about ID differences in that case, but I don't want to rely on hardcoded strings in the code.
If by "installed from my .crx file" you mean installed from Chrome Web Store you can simply check extension manifest.json for value of update_url attribute. CWS adds it when you upload your extension.
If you have a self-hosted .crx file, get your extension information using chrome.management.getSelf() and check installType of returned ExtensionInfo object. If it says "development" that means that extension was loaded unpacked in developer mode. "normal" means that it was installed from .crx file.
Here is a code sample how to do this:
function isDevMode() {
return !('update_url' in chrome.runtime.getManifest());
}
or
const isProdMode = 'update_url' in chrome.runtime.getManifest()
An extension is running in developer mode (i.e. unpacked), when it does not contain the update_url field in its manifest.
This works because an unpacked extension's JSON manifest file should not contain the update_url field. This field is automatically added when publishing via the Chrome Developer Dashboard.
For example, debug logs that only appear during development.
const IS_DEV_MODE = !('update_url' in chrome.runtime.getManifest());
function debugLog(str) {
if (IS_DEV_MODE) console.log(str);
}
debugLog('This only appears in developer mode');

icon error in createNotification in Chrome extension

In my Chrome Extension, I am using webkitNotifications.createNotification to alert users. It's a great tool!! In the sample code given, the first parameter is optional and specifies an an icon and the Google instructions claim that it can be a local reference. When I use a local file, I get a broken image link. This even occurs when I use the sample for Notification Demo located here - http://code.google.com/chrome/extensions/samples.html#f799e26ceef2367cf836f24bcb47df4398b0df58
Does anyone else have this issue?
The icon is listed in my manifest file.
I can get around this by using a complete web reference, but I like to use this tool for error notifications and sometimes the error is caused by an interruption of internet access.
I am using chrome version 18.0.1025.151 m.
Thanks!
The problem with their sample is they have included "manifest_version": 2 in their manifest but not added a "web_accessible_resources" listing what resources should be available to pages.
You can read more about manifest_version 2 and what changes it introduces here....
http://code.google.com/chrome/extensions/manifestVersion.html
...and about web_accessible_resources here....
http://code.google.com/chrome/extensions/manifest.html#web_accessible_resources
To fix the problem in the sample, you can either remove the manifest version 2 bit (even the docs say this wont be required for a while yet). Or you can add the following to the manifest....
"web_accessible_resources": [
"48.png"
]
"Web Accessible" means the resources is being accessed from your server so you must make sure to include the path to the resources in your javascript and in the manifest,json.

Get local file inside the extension folder in Chrome

I know that I can't get a local file from within the extension directory. It is possible to get a file that is inside the extension directory itself?
You can use chrome.runtime.getURL to get a fully-qualified URL to a resource.
// Outputs path to the file regardless if it exits
> chrome.runtime.getURL('assets/extension-icon.png');
"chrome-extension://kfcphocilcidmjolfgicbchdfjjlfkmh/assets/extension-icon.png"
The chrome-extension protocol plus the extension id, will be the address for the extension's root directory.
If you need something more powerful, you might also use HTML5's FileSystem API which can create, read, write and list files from a sandbox in the current user's local file system.
On Chrome 17 or later, for this to work you must include the web_accessible_resources section to allow an image packed within the extension to be injected into a web page. http://developer.chrome.com/extensions/manifest.html#web_accessible_resources
{...
"web_accessible_resources": [
"images/my-awesome-image1.png",
"images/my-amazing-icon1.png"
],...}
(courtesy of jhaury)

Resources