Why Google Chrome invalidate a valid WebExtension's manifest.json - google-chrome-extension

Chrome invalidate a valid manifest
While importing valid unpacked extension.
(manifest confirmed by https://manifest-validator.appspot.com/)
this error appears, and the extension do not get loaded.
Only one of 'browser_action', 'page_action', and 'app' can be
specified.
Manifest does not contain duplication of the neither mentioned in the error.
manifest.json
{
"applications": {
"gecko": {
"id": "addon#example.com",
"strict_min_version": "42.0"
}
},
"background": {
"scripts": ["jquery.js", "my-background.js"],
"page": "my-background.html"
},
"browser_action": {
"default_icon": "userInterface/browser_action_button/airplay_icon.svg",
"default_title": "LightDictionary",
"default_popup": "userInterface/browser_action_button/popup.html"
},
"commands": {
"_execute_browser_action": {
"suggested_key": {
"default": "Ctrl+Shift+Y"
}
}
},
"content_security_policy": "script-src 'self' https://example.com; object-src 'self'",
"content_scripts": [
{
"exclude_matches": ["*://developer.mozilla.org/*"],
"matches": ["*://*.mozilla.org/*"],
"js": ["borderify.js"]
}
],
"default_locale": "en",
"description": "none",
"icons": {
"48": "userInterface/browser_action_button/airplay_icon.svg",
"96": "userInterface/browser_action_button/airplay_icon.svg"
},
"manifest_version": 2,
"name": "LightDictionary",
"page_action": {
"default_icon": {
"19": "userInterface/browser_action_button/airplay_icon.svg",
"38": "userInterface/browser_action_button/airplay_icon.svg"
},
"default_title": "LightDictionary",
"default_popup": "userInterface/browser_action_button/popup.html"
},
"permissions": ["webNavigation"],
"version": "0.1",
"web_accessible_resources": ["images/my-image.png"]
}

I have talked to Mozilla MDN maintainer on their IRC channel and I came to the conclusion, that the so called "cross-browser extension" manifest.json published on:
https://developer.mozilla.org/en-US/Add-ons/WebExtensions/manifest.json
Was incompatible with Chrome, and only works on the Firefox browser due to:
Chrome has strict check on the manifest, and the way Chrome handles manifest differs from the way Firefox does it. Chrome is slow to adopt technologies that are supported by the Firefox.
So, the only way to make the manifest cross-browser compatible: is
to take quick manifest.json example suggested by MDN
load it into Chrome (chrome://extensions, Turn on developer mode, Load Unpacked)
check the errors and remove what is asked by the chrome.
Things to keep in mind:
Chrome does not support .svg format icons, this leads to not showing specified icon. While Firefox does support it, it is suggestive to not use svg for a cross browser extension.
Futher comment to read: https://hacks.mozilla.org/2017/06/cross-browser-extensions-available-now-in-firefox/#comment-21268

You can only have one of the properties that it specifies in the error.
Only one of 'browser_action', 'page_action', and 'app' can be specified.
You have both a browser_action property & a page_action property in your json object.
Remove one of these from the object to fix it.

Related

Chrome extension fails to load when I add icons

I've been learning how to make a Chrome extension and have been stuck on just adding an icon for a while now, I've copy pasted code that supposedly works but I keep getting this error:
Could not load icon 'icon16.png' specified in 'icons'.
Could not load manifest.
My code:
{
"manifest_version": 3,
"name": "extension",
"description": "test",
"version": "1.0",
"browser_action": {
"default_icon": "icon48.png"
},
"icons": {
"16": "icon16.png",
"48": "icon48.png",
"128": "icon128.png"
},
"content_scripts": [
{
"js": [
"test.js"
],
"matches": [
"https://www.test.com/*"
]
}
]
}
I've triple checked that every image is in fact a PNG and is of the right size. I have a single directory with manifest.json, test.js, and all three images (as well as a.prettierrc file, although I doubt that has any impact).
If I remove the icons part of manifest.json the extension works perfectly.
The error about not being able to load the manifest is likely related to:
"browser_action": {
"default_icon": "icon48.png"
},
which is from Manifest Version 2. The "browser_action" field should be changed to:
"action": {
"default_icon": "icon48.png"
},
For further reference see here: Action API unification

Chrome cannot load action icon depending on policy

I am trying to change my extension's icon from a background page (manifest v2), using:
chrome.browserAction.setIcon({path:{'48':'images/iconready.png'}});
By default, I get a surprising:
Could not load action icon 'images/iconready.png'.
Context
_generated_background_page.html
Stack Trace
_generated_background_page.html:0 (anonymous function)
Nothing to see here, move along.
as well as:
Unchecked runtime.lastError: Could not load action icon 'images/iconready.png'.
Here is my manifest:
{
"name": "myname",
"version": "1.0",
"description": "my description",
"manifest_version": 2,
"icons": {
"48": "images/icon.png"
},
"browser_action": {
"default_icon": "images/icon.png",
"default_popup": "hello.html"
},
"background": {
"scripts": [
"background.js"
],
"persistent": true
},
"web_accessible_resources":[
"images/icon.png",
"images/iconbusy.png",
"images/icondisc.png",
"images/iconready.png"
],
"permissions": [
"notifications",
"activeTab", "tabs",
"webRequest", "webRequestBlocking",
"proxy",
"webNavigation",
"https://*/*",
"http://*/*",
"<all_urls>"
]
}
(note that I've tried it with and without the "web_accessible_resources" part, it doesn't change a thing)
I've tried adding the following, and suddenly, it works, and I DO see the icon changing, which means that my code, path etc. is valid:
"content_security_policy": "default-src 'self';img-src *",
However, my extension does need connect permissions, thus the previous line MUST be something like this instead:
"content_security_policy": "default-src 'self';connect-src *;img-src *",
Unfortunately, as soon as I add the connect-src permission, the icon doesn't load anymore and gives the same error again.
Note that this is chromium on linux. Could this be a nasty bug?
What could I be doing wrong?
Thanks!

Default Icons in manifest for Chrome Extension

I have this piece of code in my manifest:
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html",
"default_icon": {
"16": "images/16x16.png",
"48": "images/48x48.png",
"128": "images/128x128.png"
}
},
It was working fine until today and now I am getting a 'duplicate key' error.
I know there are two entries for default_icon -- one for the old way of declaring a single icon, and the new way for declaring for specific sizes -- however it was not causing an issue when uploading the new packages until now. Did something change?
If I remove the first declaration, what that cause any issues?
Update:
I'm now getting an error where I can upload the zip file now, but publishing fails with 'Internal Publish Error'. When I first upload the zip, I did get a warning 'Invalid Manifest Content' but no other details. All of this was working until recently. Here is my manifest:
{
"web_accessible_resources": [
"files/*",
"js/languages.json"
],
"name": "Workspace Manager",
"version": "0.962",
"manifest_version": 2,
"short_name": "Workspace Tab Manager extension.",
"description": "Tab Manager and Productivity Extension - save tabs as workspaces and revisit them in the future",
"icons": {
"16": "images/16x16.png",
"48": "images/48x48.png",
"128": "images/128x128.png"
},
"background": {
"scripts": ["background.js"],
"persistent": false
},
"browser_action": {
"default_icon": {
"16": "images/16x16.png",
"48": "images/48x48.png",
"128": "images/128x128.png"
},
"default_popup": "popup.html"
},
"permissions": [
"tabs",
"storage"
],
"content_security_policy": "script-src 'self' https://ajax.googleapis.com https://ssl.google-analytics.com https://www.googletagmanager.com; object-src 'self'"
}
It turns out that duplicate keys are no longer allowed. And to fix it, you not only need to delete one of the duplicates (as I did), but you need to unpublish your extension entirely and then republish.
It wasn't clear on what would happen when unpublishing. Essentially, you extension will disappear from the Webstore and when you republish, it takes longer than usual to review it. (it took about 2 days vs the normal couple hours). In that time it will say 'pending' but when it does get approved, everything in your store will be restored and it will be as though nothing happened.

Enable Chrome extension action button only on one host

I've been trying to migrate one of my Chrome extensions to manifest v3, and I'm having trouble with the page_action. In manifest v3, the page_action and browser_action are merged into action, which is all good, but it's not clear to me how I can get the behavior I had previously with the new APIs.
A bit of background; the extension in question is only supposed to run on one host (let's say https://example.com). As such, I want to grey out the icon on pages with a different host. It has a popup with some settings but the main functionality is inserted via a content script (this works).
The old extension using manifest v2 used
{
"manifest_version": 2,
"name": "...",
"description": "...",
"version": "...",
"permissions": ["declarativeContent", "storage", "https://example.com/", "tabs"],
"page_action": {
"default_icon": { ... },
"default_popup": "popup.html"
},
"background": {
"scripts": ["background.js"],
"persistent": false
},
"icons": { ... },
"content_scripts": [{
"js": ["content.js"],
"matches": ["https://example.com/*", "https://www.example.com/*"]
}]
}
and in background.js I used
chrome.runtime.onInstalled.addListener(function(){
const pageUrl = {hostEquals: 'www.example.com'};
const {
onPageChanged,
PageStateMatcher,
ShowPageAction
} = chrome.declarativeContent;
onPageChanged.removeRules(undefined, function(){
onPageChanged.addRules([{
conditions: [new PageStateMatcher({pageUrl})],
actions: [new ShowPageAction()]
}]);
});
});
this works fine and the icon gets greyed out except on https://example.com. When migrating, the manifest looks like
{
"manifest_version": 3,
"name": ...,
"description": ...,
"version": ...,
"permissions": ["storage", "tabs", "declarativeContent", "activeTab"],
"background": {"service_worker": "service-worker.js"},
"action": {
"default_icon": { ... },
"default_popup": "popup/index.html"
},
"icons": { ... },
"content_scripts": [{
"matches": ["*://*.example.com/*"],
"js": ["content/detect-theme.js"]
}]
}
I cannot seem to get this to work properly. I've tried adding host_permissions, removing the declarativeContent-related code (as it doesn't seem to affect the icon whatsoever) but the extension stays available on all hosts. I know I can use the chrome.action.enable and chrome.action.disable methods to simulate this behavior but it seems overkill for such a simple use-case.
Actually, the action being available even on other pages is not breaking by any means, but I would like to make it more clear to my users that the extension only does things on https://example.com and nowhere else. Perhaps this is not even the right approach; if it isn't, I accept that as an answer as well.
TLDR; how do I only enable the (page-)action on a specific host with manifest v3?
Had the same issue myself, and I just solved it!
I fixed it by disabling the extension in the handler before adding the activation rule. I've removed the actual handler for brevity.
chrome.runtime.onInstalled.addListener(() => {
chrome.action.disable(); // The important line!
// actual handler...
});
I would guess that ShowPageAction doesn't disable the extension by default anymore.

chrome extension doesn't load

made my first chorme ext. and it works fine on old comp.
now with new one try to load unpacked ext. and it don't works at all. i see my ext popup ad bg.html but content script didn't loads at all, neiter images that shold be on target page.
other unpacked ext works fine. but mine refuse works( help me please!
manifest.json:
{
"background_page": "bg.html",
"name": "lardi trans",
"version": "1.0",
"icons": {
"48": "icon_48.png"
},
"browser_action": {
"default_icon": "icon_48.png",
"default_title": "Lardi Trans",
"default_popup": "popup.html"
},
"permissions": [
"tabs",
"notifications",
"http://lardi-trans.com/gruz/*",
"http://lardi-trans.com/trans/*",
"unlimitedStorage"
],
"content_scripts": [{
"matches": [
"http://lardi-trans.com/gruz/*",
"http://lardi-trans.com/trans/*"
],
"css": ["extent_styles.css"],
"js": ["jq.js", "script.js"],
"run_at": "document_end"
}]
}
screenshots of page where ext should be i mark place where must appears my form
console shot
and other ext scripts loads like this ! screenshot2 (5 times same script? WTF??) but anyway i can't see my ext script.js (why it din't loads?)
You do not have to give the link of css to manifest.json file. Just, call it in bg.html
My manifest.json file
{
"name": "Example",
"version": "2.0",
"description": "Example.com Description",
"icons": { "16":"Images/Example/16x16.png", "32":"Images/Example/32x32.png", "48": "Images/Example/48x48.png", "64": "Images/Example/64x64.png", "128": "Images/Example/128x128.png" },
"app":
{
"default_icon": "../Images/Example/icon.png",
"launch":
{
"local_path": "Pages/Index.html"
}
},
"permissions": [ "http://www.Example.com/",
"http://*.Example.com/",
"https://www.Example.com/",
"https://*.Example.com/",
"unlimitedStorage",
"tabs",
"notifications"
],
"options_page": "Pages/Options.html",
"background_page": "Pages/Background.html"
}
If that answer helped you, please mark it as an answer...
If you are still taking errors, please ask them to bottom of that answer.
Best Regards.
EDIT:
View errors - Steps;
Click your extension button to open it.
Open the debug window in Google Chrome with F12 key.
Click "Console" tab page.
Take a screenshot of it, and post the picture in your question.
With that way everybody can help you =)
EDIT 2:
ok your question seems looking littlebit different now.
Here is algorithm;
Download the site sourcecode of target webpage with jquery,
Insert your css line in head tag with json,
Store new source code in localStorage( html5 )
When it's done, refresh the page with js, and read new source code from localStorage
And show it in html.
if anyone interests, problem solved, by some reason in manifest add unprop whitespases "content_scripts": [{
"matches": ["http://lardi-trans.com/gruz/*","http://lardi-trans.com/trans/*"],
this works!))

Resources