Chromedriver extension id does not match key in manifest.json - google-chrome-extension

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.

Related

Chrome Extension Manifest V3 Loading Remote JSON Configuration

I am working on transitioning from Manifest 2 to Manifest 3 and in Manifest 2 I was pulling in a remotely hosted json file and using that to enable and disable settings. It has to be dynamic otherwise I'd include it in the extension itself. Looking at the migration guide from Google I see this:
In Chrome Extension manifest v3 remotely hosted code is no longer allowed. The migration documentation has two solutions.
Configuration-driven features and logic—In this approach, your
extension loads a remote configuration (for example a JSON file) at
runtime and caches the configuration locally. The extension then uses
this cached configuration to decide which features to enable.
Externalize logic with a remote service—Consider migrating application
logic from the extension to a remote web service that your extension
can call. (Essentially a form of message passing.) This provides you
the ability to keep code private and change the code on demand while
avoiding the extra overhead of resubmitting to the Chrome Web Store.
The first option sounds like what I am looking for, but I can't find any documentation on to achieve this approach. If anyone can point me in the right direction it would be greatly appreciated.
For reference this is how I was previously pulling it into the extension:
async function readJson() {
const response = await fetch('https://www.example.com/config.json');
console.log(response.ok);
if (!response.ok) {
const message = `An error has occured: ${response.status}`;
throw new Error(message);
}
const json = await response.json();
return json;
}

How to run setup code before extension loaded in puppeteer?

I am testing the behavior of a chrome extension using puppeteer.
Upon installation, the extension opens a page. I would like to do initial setup in the browser before the extension is loaded (for example, setting local storage or injecting a jest mock).
The problem I have now is that the extension gets loaded upon browser start, so I don't know of any way to execute setup code before the extension is loaded.
This is how I load the extension currently (which resides in the dist/chrome folder):
const browser = await puppeteer.launch({
args: [
'--disable-extensions-except=dist/chrome',
'--load-extension=dist/chrome',
],
headless: false,
ignoreDefaultArgs: ['--disable-extensions'],
});
How can I do initial setup before the extension is loaded?
Some options I can think of are: 1) load the extension after the browser is launched 2) intercept the extension installation and execute setup code before the extension initializes
I came searching for an answer and I found it reading your question, so I'm leaving it here in case I have to search for it again in the future ...
The trick is to create a "launcher" extension with the sole purpose running the setup code, before the actual extension is ran. It would look like:
'--disable-extensions-except=dist/launcher,dist/chrome',
'--load-extension=dist/launcher,dist/chrome',

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.

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

Access .pem file which has been automatically generated by the Chrome Webstore

I have the following problem: my Google Chrome extension has been submitted before the packaging mechanism (i.e. ship your own pem file to the webstore) was introduced.
Now I'd like to update the extension but since I don't have a pem file the webstore will automatically generate a new one, hence, my extension will have a new ID which causes the update mechanism to fail and I'd loose my existing user base.
Is it possible to get a pem file for the old extension or can I provide my own pem file w/o breaking the update mechansim.
Thanks,
Peter
If your extension is already in the Chrome Web Store, then you don't need to have a .pem file to submit an update. If your extension is not in the Web Store, but you'd like to move it there and keep the same ID, then you can upload your old .pem file with the name key.pem (see the documentation for details).
This isn't really an ideal solution but you can call it Plan B. The updated extension (with a new id) can automatically disable the old one, by looking for the old one's id.
chrome.management.getAll(function(ext){
if(ext.length===1) return;
for(var i=0; i<ext.length; i++){
if(ext[i].id!=="ENTER_OLD_EXTENSION_ID_HERE") continue;
chrome.management.setEnabled(ext[i].id,false);
}
});

Resources