Check if Chrome extension installed in unpacked mode - google-chrome-extension

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');

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.

How to test Chrome onUpdateAvailable in extension

I wanted to test onUpdateAvailable event in chrome extension.
https://developer.chrome.com/extensions/runtime#method-requestUpdateCheck
I have tried updating the maniefest version but it didn't work.
Can someone help?
You can specify "update_url" in your manifest file which is mapped to your local server and change it when you need.
The URL should be a link to an XML document, you can check example here.

Chromedriver extension id does not match key in manifest.json

I am testing a chrome extension using selenium webdriver.js and chromedriver. I've been able to successfully launch chrome, with my extension installed, but the extension id is randomly generated instead of matching the key property of my manifest.json. This makes it impossible to test extension pages like the options page.
manifest.json
// ...
"key": "pjnhffdkdckcagdmfmidafhppbomjdjg", // id from chrome web store
// ...
test.js
var webdriver = require('selenium-webdriver');
var chrome = require('selenium-webdriver/chrome');
// load unpacked extension
var chromeOptions = new chrome.Options();
chromeOptions.addArguments('load-extension=/path/to/my/extension');
var service = new chrome.ServiceBuilder().build();
var driver = chrome.createDriver(chromeOptions, service)
// this page is not available T_T
driver.get('chrome-extension://pjnhffdkdckcagdmfmidafhppbomjdjg/html/options.html');
My assumption is that the extension id would match the key (and it does when installing from the web store), but this does not seem to be true for loading the extension via chromedriver. Is there a way to get the loaded extension to have a consistent ID? Or should I take another approach?
The manifest key value is not the extension ID. You have to install the extension from the web store and look in the manifest.json file on your desk. Use they key value inside that file. The documentation describes how to find the install directory.
I was having the same issue.
Just load your extensions from a crx file and you will get a consistent id.

Get chrome extension's id using extension's name

I have a extension which I loaded in google chrome. Now I'm writting a script from which I want to get the extension's id according to the extension's name. In this case, the extension is like a server and my script in java project is the client.
I need is to get the id of the extension outside, from external project
Your extension id is supposed to remain static; It should never change, even when developing. You can simply keep a global variable.
var idOfOtherApplication = "ccokanilabejbblhdenlechhcggmopnp";
Getting an extensions id from its name would be unreliable because multiple extensions can have the same name.
To find the id of an extension go to chrome://extensions. To find the id of the current extension programmatically simply call one of the following:
var idOfThisApplication = chrome.i18n.getMessage("##extension_id");
var idOfThisApplication = chrome.runtime.id;
Both of these methods require no extra permissions.

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