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
Related
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.
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.
When i debug javaScript on devtool.
chrome.runtime
see "http://www.qq.com",it show:
chrome.runtime is undefined. see http preview.
But when i debug it on https site (https://www.qq.com ).it work fine. see https preview.
tips: all script run on top frame.
Can i change "chorme:flags" to enable it ?
i got why now.
"chrome.runtime.sendMessage" not exist when no extension installed.---since chrome 66+.
see:https://bugs.chromium.org/p/chromium/issues/detail?id=835287
Comment 29 by rdevlin....#chromium.org, Apr 25 For at least some of
these cases from the duped bugs, I think this was caused by revision
39f8939309fe39bccc17fa1280b6c7f25c411947. This modified the
externally_connectable property of the cryptotoken component extension
(automatically built into Chrome) to only accept incoming connections
from https URLs, whereas previously it was all URLs. When it was set
to all URLs, chrome.runtime.sendMessage would always be available
because any URL could potentially send a message to the cryptotoken
component extension.
However, this is working as intended. The cryptotoken extension only
accepts connections from https origins (so any others would be
ignored), and sending a message to any other extension would require
the receiving extension to list the URL in the externally_connectable
options. Additionally, this means that before, any extension relying
on this behavior would likely have failed to send the message, but
done so asynchronously (once the message failed to find an appropriate
receiver) rather than synchronously (since runtime is undefined). If
the extension lists the URL in externally_connectable, then
chrome.runtime should still be present. If the extension does not
list the site in externally_connectable, then chrome.runtime not being
available is intended behavior.
Is there any case in which chrome.runtime is undefined for
non-sandboxed chrome-extension:// pages, or for web pages where an
installed extension specifies that web page's URL in the
externally_connectable field of the manifest? If so, please attach an
extension that demonstrates this issue. If not, this sounds like it's
WAI.
fix: add one extionsion with:manifest.
"externally_connectable": {
"ids": [
"*"
],
"matches": [
"http://test.yoursite.in:9090/*",
"*://*.chromium.org/*"
]
},
thinks all.
Content Script can be injected programatically or permanently by declaring in Extension manifest file. Programatic injection require host permission, which is generally grant by browser or page action.
In my use case, I want to inject gmail, outlook.com and yahoo mail web site without user action. I can do by declaring all of them manifest, but by doing so require all data access to those account. Some use may want to grant only outlook.com, but not gmail. Programatic injection does not work because I need to know when to inject. Using tabs permission is also require another permission.
Is there any good way to optionally inject web site?
You cannot run code on a site without the appropriate permissions. Fortunately, you can add the host permissions to optional_permissions in the manifest file to declare them optional and still allow the extension to use them.
In response to a user gesture, you can use chrome.permission.request to request additional permissions. This API can only be used in extension pages (background page, popup page, options page, ...). As of Chrome 36.0.1957.0, the required user gesture also carries over from content scripts, so if you want to, you could add a click event listener from a content script and use chrome.runtime.sendMessage to send the request to the background page, which in turn calls chrome.permissions.request.
Optional code execution in tabs
After obtaining the host permissions (optional or mandatory), you have to somehow inject the content script (or CSS style) in the matching pages. There are a few options, in order of my preference:
Use the chrome.declarativeContent.RequestContentScript action to insert a content script in the page. Read the documentation if you want to learn how to use this API.
Use the webNavigation API (e.g. chrome.webNavigation.onCommitted) to detect when the user has navigated to the page, then use chrome.tabs.executeScript to insert the content script in the tab (or chrome.tabs.insertCSS to insert styles).
Use the tabs API (chrome.tabs.onUpdated) to detect that a page might have changed, and insert a content script in the page using chrome.tabs.executeScript.
I strongly recommend option 1, because it was specifically designed for this use case. Note: This API was added in Chrome 38, but only worked with optional permissions since Chrome 39. Despite the "WARNING: This action is still experimental and is not supported on stable builds of Chrome." in the documentation, the API is actually supported on stable. Initially the idea was to wait for a review before publishing the API on stable, but that review never came and so now this API has been working fine for almost two years.
The second and third options are similar. The difference between the two is that using the webNavigation API adds an additional permission warning ("Read your browsing history"). For this warning, you get an API that can efficiently filter the navigations, so the number of chrome.tabs.executeScript calls can be minimized.
If you don't want to put this extra permission warning in your permission dialog, then you could blindly try to inject on every tab. If your extension has the permission, then the injection will succeed. Otherwise, it fails. This doesn't sound very efficient, and it is not... ...on the bright side, this method does not require any additional permissions.
By using either of the latter two methods, your content script must be designed in such a way that it can handle multiple insertions (e.g. with a guard). Inserting in frames is also supported (allFrames:true), but only if your extension is allowed to access the tab's URL (or the frame's URL if frameId is set).
I advise against using declarativeContent APIs because they're deprecated and buggy with CSS, as described by the last comment on https://bugs.chromium.org/p/chromium/issues/detail?id=708115.
Use the new content script registration APIs instead. Here's what you need, in two parts:
Programmatic script injection
There's a new contentScripts.register() API which can programmatically register content scripts and they'll be loaded exactly like content_scripts defined in the manifest:
browser.contentScripts.register({
matches: ['https://your-dynamic-domain.example.com/*'],
js: [{file: 'content.js'}]
});
This API is only available in Firefox but there's a Chrome polyfill you can use. If you're using Manifest v3, there's the native chrome.scripting.registerContentScript which does the same thing but slightly differently.
Acquiring new permissions
By using chrome.permissions.request you can add new domains on which you can inject content scripts. An example would be:
// In a content script or options page
document.querySelector('button').addEventListener('click', () => {
chrome.permissions.request({
origins: ['https://your-dynamic-domain.example.com/*']
}, granted => {
if (granted) {
/* Use contentScripts.register */
}
});
});
And you'll have to add optional_permissions in your manifest.json to allow new origins to be requested:
{
"optional_permissions": [
"*://*/*"
]
}
In Manifest v3 this property was renamed to optional_host_permissions.
I also wrote some tools to further simplify this for you and for the end user, such as
webext-domain-permission-toggle and webext-dynamic-content-scripts. They will automatically register your scripts in the next browser launches and allow the user the remove the new permissions and scripts.
Since the existing answer is now a few years old, optional injection is now much easier and is described here. It says that to inject a new file conditionally, you can use the following code:
// The lines I have commented are in the documentation, but the uncommented
// lines are the important part
//chrome.runtime.onMessage.addListener((message, callback) => {
// if (message == “runContentScript”){
chrome.tabs.executeScript({
file: 'contentScript.js'
});
// }
//});
You will need the Active Tab Permission to do this.
I'm writing an extension that requests XML content from a server and displays data in a popup/dialog window. I've added the website to my manifest.json permissions like so:
"permissions": [
"http://*/*"
],
Later I added the following code to my background page:
function loadData() {
var url = "http://www.foo.com/api/data.xml";
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
...
xhr.send();
the problem is, that I get the cross-site security error "Origin chrome-extension://kafkefhcbdbpdlajophblggbkjloppll is not allowed by Access-Control-Allow-Origin. "
The thing is, with "http:///" in the permissions I can request "http://www.foo.com/api", but I can't find any way to allow "http://www.foo.com/api/data.xml".
I've tried both "http:////*" and http://www.foo.com/api/data.xml" in the "permissions". What else should I be doing?
This should work (SOP doesn't apply to chrome extensions),so there are three possibilities:
There is some mistake somewhere
Just to make sure use add <all urls> permission and check that extension really have this permission. (e.g. execute chrome.runtime.getManifest() in console when inspecting background page )
Server itself is checking Origin header and is rejecting request if origin value is unexpected
You can quickly check this by using some http tester and sending request manually (for example Dev Http Client for chrome, since I'm one of the developers). If it shows the same error, it means that the server is really checking origin header.
To fix this you will have to make server somehow accept your origin , or you can use chrome.webRequest to set valid origin header to all the requests sent to the target server (standard XHR api doesn't allow modification of Origin header)
Chrome bug
Well in this case you can only report this error and wait for the best