Display a favicon in a Chrome extension newtab page using manifest v3 - google-chrome-extension

I have recently migrated my chrome extension to manifest v3 using this guide:
https://developer.chrome.com/docs/extensions/mv3/intro/mv3-migration/
The v3 manifest.json file no longer supports using chrome://favicon/. Looking through the documentation I could not find an alternative. There were some articles I found that said it might be moved to a new favicon permission and be available under the google.favicon namespace. However they were all older and speculative, I tried these speculations to no avail.

The new API was just released as part of Chrome 104!
To use it, first add the favicon permission to your manifest.json:
{
...
"permissions": ["favicon"],
...
}
Then you can load the favicon using your chrome extension's id, for example:
const faviconSrc = `chrome-extension://${chrome.runtime.id}/_favicon/?pageUrl=${encodeURIComponent(url)}&size=32`;

it seems like they forget to build this api, you can star this issue on the page or leave a comment to tell them.

Issue 104102: Create a new API permission for access to favicons was fixed on June 13, 2022.
chrome://favicon Replacement for Extensions document mentions the API:
var faviconUrl = new URL('chrome-extension://<id>/_favicon');
faviconUrl.searchParams.append('page_url', 'http://example.com');
let image = document.createElement('img');
image.src = faviconUrl.href;
// src is 'chrome-extension://<id>/?page_url=http%3A%2F%2Fexample.com%2F'
Note that there's a mistake on the last line. It should be:
// src is 'chrome-extension://<id>/_favicon?page_url=http%3A%2F%2Fexample.com%2F'
Unfortunately, I still hasn't been able to get this API working on Chrome Canary 105.0.5174.0, which should include the changes from the resolved bug already. I'm getting Failed to load resource: net::ERR_FAILED errors.

Related

Chrome extension chrome favicon permission [duplicate]

I have recently migrated my chrome extension to manifest v3 using this guide:
https://developer.chrome.com/docs/extensions/mv3/intro/mv3-migration/
The v3 manifest.json file no longer supports using chrome://favicon/. Looking through the documentation I could not find an alternative. There were some articles I found that said it might be moved to a new favicon permission and be available under the google.favicon namespace. However they were all older and speculative, I tried these speculations to no avail.
The new API was just released as part of Chrome 104!
To use it, first add the favicon permission to your manifest.json:
{
...
"permissions": ["favicon"],
...
}
Then you can load the favicon using your chrome extension's id, for example:
const faviconSrc = `chrome-extension://${chrome.runtime.id}/_favicon/?pageUrl=${encodeURIComponent(url)}&size=32`;
it seems like they forget to build this api, you can star this issue on the page or leave a comment to tell them.
Issue 104102: Create a new API permission for access to favicons was fixed on June 13, 2022.
chrome://favicon Replacement for Extensions document mentions the API:
var faviconUrl = new URL('chrome-extension://<id>/_favicon');
faviconUrl.searchParams.append('page_url', 'http://example.com');
let image = document.createElement('img');
image.src = faviconUrl.href;
// src is 'chrome-extension://<id>/?page_url=http%3A%2F%2Fexample.com%2F'
Note that there's a mistake on the last line. It should be:
// src is 'chrome-extension://<id>/_favicon?page_url=http%3A%2F%2Fexample.com%2F'
Unfortunately, I still hasn't been able to get this API working on Chrome Canary 105.0.5174.0, which should include the changes from the resolved bug already. I'm getting Failed to load resource: net::ERR_FAILED errors.

Are these permissions mandatory in my Chrome extension?

I'm working on a chrome extension which must get in touch with some apis.
The first version had this permission in the manifest :
"permissions": [ "API_1" ],
And I could contact this API:
var xhr = new XMLHttpRequest();
xhr.open('GET', "API_1" + someArguments, true);
xhr.onreadystatechange = function()
{
// ...
}
This version is already published, but now I need my extension to contact another API, so I'm using the same code with the new API:
var xhr = new XMLHttpRequest();
xhr.open('GET', "API_2" + someArguments, true);
xhr.onreadystatechange = function()
{
// ...
}
In this new version I don't have any warning or error whatever there is no permission for "API_2". If I add permission for API_2, installed extensions will be disabled on update. So my question is : Are permissions for API_1 and API_2 really mandatory?
If that's all you're using the API host permission for, it depends on exactly one thing: CORS policy of the remote server.
When making XHR requests, if the request is cross-domain (which, from an extension, always except for content scripts on that same domain) - Chrome will examine CORS headers in server's reply.
By default, if the server does not indicate anything, cross-domain requests are not allowed by the web security model. This is typical if you're requesting something that was never intended to be a public API. Listing the API match pattern in permissions overrides this.
However, for public API it is typical to include a permissive CORS header (after all, other web applications that may use this API cannot override the security model, only extensions can). In that case, the permission is not necessary.
Its hard to know without listing the API's, but google's documentation provides a simple way to check how new permissions will affect warnings:
If you'd like to see exactly which warnings your users will get, package your extension into a .crx file, and install it.
To see the warnings users will get when your extension is autoupdated, you can go to a little more trouble and set up an autoupdate server. To do this, first create an update manifest and point to it from your extension, using the "update_url" key (see Autoupdating). Next, package the extension into a new .crx file, and install the app from this .crx file. Now, change the extension's manifest to contain the new permissions, and repackage the extension. Finally, update the extension (and all other extensions that have outstanding updates) by clicking the chrome://extensions page's Update extensions now button.
Basically, create two test extensions, one being your original and another being your updated. Follow this process to go through a simulated update, and you will see what warnings you get, if any.
If you leave out API_2 permissions in the update and everything is fine, then its permissions are not mandatory to include in the manifest.
Source

After deletion of chrome extension remove some html elements from website

Hi I am new to chrome extension. I have build the basic chrome extension and I want to install it using inline installation. I followed the following link :
https://developer.chrome.com/webstore/inline_installation#already-installed
All is working properly. I want to check if extension is already installed or not so I referred the above document, whenever user install the extension at that time we are appending the new div using content script to my installation page on website. If that div is present it means the extension is already installed.
Following code is added in my content_script of chrome extension for appending the div whenever the extension is installed:
var isInstalledNode = document.createElement('div');
isInstalledNode.id = 'extension-is-installed';
document.body.appendChild(isInstalledNode);
Then my installation page can check for the presence of that DOM node, which signals that the extension is already installed:
if (document.getElementById('extension-is-installed')) {
document.getElementById('install-button').style.display = 'none';
}
But I am facing one problem, whenever I deleted my extension from settings/extensions, still the div is present on extension's installation page.
Is their any provision to remove the div when my extension is deleted or removed from browser?
You can't catch the uninstallation event for your own extension, though there is an management.onUninstalled, it is used for listening to other extensions/apps. See following answer for more details:
How to listen to uninstallation event in javascript from a chrome extension?
I just come up with two workarounds, one is creating another extension to listen to the uninstall of your first extension; another one is using runtime.setUninstallURL to visit a URL upon uninstallation, you can do something in server if you want.
BTW, for isInstalledNode, you needn't/shouldn't set the id, since there may be other elements in the webpage with the same id, you just need to create the node and use document.body.contains(isIntalledNode) to check if it exists.

How to inject javascript into Chrome DevTools itself

Ok, so just the other day I learned that you can inspect the devtools if it is in its own window(explained here). I also learned that you can style the devtools with your own css by editing the Custom.css file in your profile on your computer(more on that here).
What I want to do is not only add css, but also javascript, via a chrome extension. I am very aware of devtools pages, but those do not do what I want. Pretty much I want to get a content script to run on the devtools inspector itself. I found one extension that does exactly this, but for the life of me I have not been able to replicate it(even when copy-pasting the code!!). The extension is the "Discover DevTools Companion extension" from Code School(on the webstore). They even explain how it works, but I still have had no luck. That was the only extension I have found that does what I want. So I guess what I'm really asking is if its just me that cannot get it to work or if others that try are having trouble also.
Usually, you cannot create a Chrome extension which injects code in a devtools page.
The "Discover DevTools Companion" extension from now on, referred to as DDC is allowed to do this, because this extension is whitelisted in the source code of Chromium: (this is no longer the case)
// Whitelist "Discover DevTools Companion" extension from Google that
// needs the ability to script DevTools pages. Companion will assist
// online courses and will be needed while the online educational programs
// are in place.
scripting_whitelist_.push_back("angkfkebojeancgemegoedelbnjgcgme");
If you want to publish an extension in the Chrome Web Store with these capabilities, give up.
If you want to create such an extension for personal / internal use, read further.
Method 1: Impersonate the DDC a whitelisted extension
The easiest way to create an extension with such permissions is to create an extension with the extension ID of a whitelisted extension (e.g. ChromeVox). This is achieved by copying the "key" key of its manifest file to your extension's manifest (see also: How to get the key?). This is a minimal example:
manifest.json
{
// WARNING: Do NOT load this extension if you use ChromeVox!
// WARNING: Do NOT load this extension if you use ChromeVox!
// WARNING: This is a REALLY BIG HAMMER.
"content_scripts": [{
"js": [ "run_as_devtools.js" ],
"matches": [ "<all_urls>" ]
}],
// This is the key for kgejglhpjiefppelpmljglcjbhoiplfn (ChromeVox)
"key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDEGBi/oD7Yl/Y16w3+gee/95/EUpRZ2U6c+8orV5ei+3CRsBsoXI/DPGBauZ3rWQ47aQnfoG00sXigFdJA2NhNK9OgmRA2evnsRRbjYm2BG1twpaLsgQPPus3PyczbDCvhFu8k24wzFyEtxLrfxAGBseBPb9QrCz7B4k2QgxD/CwIDAQAB",
"manifest_version": 2,
"name": "Elevated Devtools extension",
"version": "1.0"
}
run_as_devtools.js
if (location.protocol === 'chrome-devtools:') (function() {
'use strict';
// Whatever you want to do with the devtools.
})();
Note: This method is truly a hack. Since the extension shares the same ID as ChromeVox, both extensions cannot co-exist. And if Chrome decides to remove the whitelisted extension, then your permissions will evaporate.
Instead of filtering via the content script, you can also use the include_globs key to restrict the content script to devtools only.
Method 2: Modify resources.pak
I suggest to go with method 1 if possible. When method 1 fails (e.g. because the extension is no longer whitelisted), use the next method.
Get paktools.py, unpack.py and pack.py from DennisKehrig/patch_devtools (on Github).
Locate your Chrome directory containing resources.pak.
Run python2 unpack.py resources.pak, which creates a directory resources containing all files (all file names are numbers).
Locate the file containing a script which runs in the context of the developer tools. Add your desired code there.
Remove resources.pak
Run python2 pack.py resources to create the new resources.pak file.
Note: resources.pak may be replaced when Chrome is updated, so I suggest to create a script which automates my described algorithm. That shouldn't be too difficult.
If you're interested, you can look up the .pak file format in ui/base/resource/data_pack_literal.cc (description in human language).
For those googlers who end up at this page (as I did) looking for something else, this page answers the question of manipulating DevTools ITSELF - not adding jQuery to DevTools, or injecting javaScript onto a web page. For those, see here instead:
Inject jQuery into DevTools (Chrome or Firefox):
Firefox DevTools: Automatically injecting jQuery
Inject your own javascript/css onto any web page:
How to edit a website's background colors

How do you integrate Universal Analytics in to Chrome Extensions?

The chrome extension guide has a tutorial for the old analytics install: https://developer.chrome.com/extensions/tut_analytics.html
The instructions just say to link to the https version and update the manifest to allow loading scripts from that URL. So those should still apply to the new version. And in fact I can see the script loading from the server.
Once the script loads analytics does not properly initialize it self and never processes it's internal queue (ga.f) to send those events to the server. There is no error in the console. It's just quietly does nothing.
My guess is that the new Universal Analytics is just not set up to run in the the extension environment but the universal docs make no mention of that: https://developers.google.com/analytics/devguides/collection/analyticsjs/
does anyone know if it's even possible to add Universal Analytics to an extension yet and when that might be added?
There's an issue for that on Google code: The solution is to pass analytics your own protocol check function or simply null for no checking, in an official way.
This has to come after ga('create', ...) :
ga('set', 'checkProtocolTask', null); // Disable file protocol checking.
So you don't need to modify the original analytics.js script. Just include the standard tracking code snippet (dont' forget to add the "https:" prefix) and add "https://www.google-analytics.com" to your Content Security Policy.
A note to ayal gelles' solution:
It is not necessary to add chrome-extension://... to the Content Security Policy since it's already included in the 'self' statement. Also, instead of loading the script via hardcoded URL you should use chrome.runtime.getURL("path/to/analytics.js"). This way you don't need to know your extension's ID, Chrome will fill it in for you.
I wrote up a blog post on this - How to add Google’s Universal Analytics tracking to a Chrome extension
Here's the guts of it:
// Standard Google Universal Analytics code
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga'); // Note: https protocol here
ga('create', 'UA-XXXXX-YY', 'auto');
ga('set', 'checkProtocolTask', function(){});
ga('send', 'pageview', '/options.html');
There are 3 points I’d particularly like to highlight:
Specify “https” at the start of the script address to match with the listing in the manifest.json file
Override checkProtocolTask with an empty function
Send a virtual pageview by specifying the path – /options.html – otherwise Google Analytics will reject a URL in the format chrome-extension://gdocgfhmbfbbbmhnhmmejncjdcbjkhfc/options.html
I just encountered this and seem to have hacked my way through. This might break at some point or not be fully functional, but here goes:
Download the GA uglified+minified source code from here: https://www.google-analytics.com/analytics.js, put in your chrome extension folder, where it could be later loaded by the background page.
In it, find a function that looks something like this:
function Oa(){var a=M[B][E];if("http:"!=a&&"https:"!=a)throw"abort";}.
This is the "point of failure" since our "protocol" is "chrome-extension:" and not either of the two.
So.. change this function to be something like:
function Oa(){var a=M[B][E];if("chrome-extension:"!=a&&"http:"!=a&&"https:"!=a)throw"abort";}
add a "Content Security Policy" of this sort to your manifest file, make sure it points to YOUR LOCAL version of analytics.js you have just modified:
"content_security_policy": "script-src 'self' chrome-extension://EXTENSIONID/path/to/analytics.js; object-src 'self'",
Change the GA snippet to ALSO point to that same file, something like this:
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','chrome-extension://EXTENSIONID/path/to/analytics.js','ga');
hope this helps.
I managed to get Google Analytics up and running using Chrome Platform Analytics (CPA). The only confusing part is how to set up a property in the administration console of GA. I had to create a Mobile Application property, which is not too intuitive.
Also, I created an options page that lets users disable analytics if desired, to comply with the opt-out requirements.
I hope that helps!
Regarding new analytics.js (as opposite to old ga.js) this example works for me:
function setupGoogleAnalytics() {
if (!window.ga) {
(function(){
window.ga = function() {
(window.ga.q = window.ga.q || []).push(arguments);
}, window.ga.l = 1 * new Date();
var tag = 'script';
var a = document.createElement(tag);
var m = document.getElementsByTagName(tag)[0];
a.async = 1;
a.src = 'https://www.google-analytics.com/analytics.js';
m.parentNode.insertBefore(a, m);
})();
ga('create', 'UA-XXXXXXX-Y', 'auto');
ga('set', 'checkProtocolTask', null);
}
}
Please note that you need to add following content_security_policy snippet to the manifest.json:
{
...
"content_security_policy": "script-src 'self' https://www.google-analytics.com; object-src 'self'"
...
}
There's a way to use the Measurement Protocol to communicate with Google Analytics.
I have developed a script for that :
https://github.com/melalj/universal-ga-extension

Resources