Optional permissions for "content scripts" in Chrome Extension? - google-chrome-extension

For a Google Chrome extension, I would like to have optional permissions for a "content script" so that the content script is activated only if the user has granted this optional permission. The extension's manifest has a "content_scripts": [{..., "matches": "url"}] that triggers a non-optional request for permission to read and change everything at that URL.
The documentation on option permissions does not mention content scripts. And the documentation for RequestContentScript still says it is not available in stable builds.
Is there a way to do this?

You can use Firefox' browser.contentScripts.register() API and its Chrome polyfill to register new content scripts dynamically. In Chrome 96+ there's also chrome.scripting.registerContentScript, which does something similar.
You'll also have to watch for new permissions and register the scripts on the new hosts.
The module webext-dynamic-content-scripts takes care of all of this.

Related

Can a Chrome Extension detect if the Google Play Store is enabled or disabled on a Chromebook?

Chromebooks have an option, "Remove Google Play Store" in their settings. Is it possible for a Chrome browser extension (by itself) to detect if the Play Store is enabled or disabled on the Chromebook? If that is so, then how?
I don't see anything obvious in the Extension API docs to do this, but sometimes functionality can be somewhat obscure. Maybe there's a way to use the available APIs that I don't know about?
https://developer.chrome.com/extensions/api_index
Or maybe there's some other way...?
Thanks for any recommendations you can give!!
I've found a way to do it, but it isn't particularly secure. If someone else has a better way, please post it. Here is what I've found.
The Chromebook user must open this URL up in their Chrome browser and enable extensions on chrome:// URLS:
chrome://flags/#extensions-on-chrome-urls
The Chrome extension must have the following in its manifest.json:
"content_scripts": [
{
"js": ["my-content-script-file.js"],
"all_frames": true,
"matches": [
"chrome://os-settings/androidappsdetails",
"chrome://os-settings/apps",
"chrome://os-settings/"
]
}]
If everything is set up as I said above, then, when the settings window is open, the my-content-script-file.js file of the Chrome extension can read the HTML and add on-click events to the DOM elements in the settings window, just like a normal content script could with any other webpage.

Chrome extension - go to url without chrome.tabs

I have restrictions for including 'tabs' permission in manifest, exist any way to go to some url without using chrome.tabs in chrome extensions?
"tabs" permission used to be needed for all operations, but it's not needed anymore for a long time (since Chrome 7!).
The only thing that this permission grants is reading information about existing tabs.
Quoting the documentation itself (emphasis mine):
The majority of the chrome.tabs API can be used without declaring any
permission. However, the "tabs" permission is required in order to
populate the url, title, and favIconUrl properties of Tab.
So you can easily manipulate tabs (e.g. create or update them) without ever needing any permission.
Also, "activeTab" permission is worth a look.

moving from permissions to optional_permissions: how to handle content_scripts?

Originally posted this question here:
https://groups.google.com/a/chromium.org/d/msg/chromium-extensions/wbSpXvnO10A/nov36skmnQ0J
My extension has an optional feature that interacts with the user's gmail tab. We don't want to mention mail.google.com domains at all in the permission confirmation that the user sees when first installing the extension. So I moved that entry out of the manifest's permissions block and into the optional_permissions block. We also needed to use a content script tied to mail.google.com, but defining this in the manifest causes the 'mail.google.com' permission warning that is sppoking some users.
I've tried removing the content_script manifest block and using Programmatic Injection instead as describe here. http://developer.chrome.com/extensions/content_scripts.html#pi
However scripts injected that way are not content scripts and don't have access to the needed APIs (chrome.tabs, etc)
Is there some way to get the best of both worlds: use optional_permission, AND get the content scripts added to a matching URL, but only if the user has approved the optional permission?
It seems like you could create a background page, and call chrome.tabs.query against your optional origin to get a list of tabs that match that host. You can then call programmatic injection to the content script (chrome.tabs.executeScript). None of these require the "tabs" permission (many "tabs" functions don't require any special permission, and it intelligently lets you query for tabs whose origins match your optional permission)
You could call this every second or so to see if there are any new tabs for which you haven't yet called executeScript.
It would be nice if this were edge-triggered. See https://code.google.com/p/chromium/issues/detail?id=264704
You can actually get it to be mostly edge triggered by using chrome.tabs.onUpdated.addListener and simply trying to inject every time that is triggered (which will be every time a page loads in any tab, regardless of whether you have permission or not). You'll get a lot of errors in the background script's console when you don't have permission. It will be important to have your content script set a variable like _I_already_executed=true and check for its existence so that you're not injecting multiple times (this event gets triggered several times for each page load)
Now there's the contentScripts.register() API, which lets you programmatically register content scripts.
browser.contentScripts.register({
matches: ['https://mail.google.com/*'],
js: [{file: 'content.js'}]
});
This API is only available in Firefox but there's a Chrome polyfill you can use. The new scripts will work exactly like your regular content scripts in manifest.json.
For a more comprehensive solution you could look into my webext-domain-permission-toggle and webext-dynamic-content-scripts modules, which don't apply directly to your use case but can be helpful to who wants to drop the <all_urls> permission and inject content scripts on demand.

How can I call chrome.tabs.captureVisibleTab in an extension without asking for <all_urls> permission?

I'm writing a chrome extension and I want to take a screenshot of the tab in which the extension is running. The extension url is like "chrome-extension://abcde". Everything works if I include "tabs" and "<all_urls>" in my list of permissions, but I don't really want to ask for the <all_urls> permission.
I tried adding "chrome-extension://abcde" to permissions instead of <all_urls> and I get the error "You do not have permission to use 'tabs.captureVisibleTab'. Be sure to declare in your manifest what permissions you need."
How can I solve this?
You should specify the hosts you want to be able to capture in the permissions. Now you've set it to your own Extension ID so that's why it's probably not working.
captureVisibleTab - Captures the visible area of the currently active tab in the specified window. You must have host permission for the URL displayed by the tab.
http://code.google.com/chrome/extensions/tabs.html

Is there a limit on number of requests to Chrome history API from an extension?

When I was browsing through Chrome extension gallery I saw one author mentioned something about some possible limits on how many times you can search Chrome history through API. Is it true? I can't find any info on this.
This is not true at all, it is possible that he didn't declare the appropriate permissions to History in the .json file, and instead used a background page...
In the manifest.json file you are supposed to give the extension permissions... One of these permissions is to access the history file...
The permissions part of the json file that will allow access to the history file looks like this:
"permissions": [ "history" ]
And once you have access to the History file, You'll be able to use the search API as follows in your background page:
chrome.history.search(object query, function callback)
As long as your background page is running - which is whenever the browser is open - You'll be able to make as many searches as you please...

Resources