Is it possible to catch requests from another extension? - google-chrome-extension

In my extension I use chrome.webRequest to catch requests from any web pages and it works like a charm.
But I can not catch any requests initialized from another extension.
My manifest:
"permissions": [
"tabs",
"webRequest",
"webRequestBlocking",
"<all_urls>"
],
background.js:
chrome.webRequest.onBeforeRequest.addListener(function (data) {
console.log('catched', data);
}, {urls: ['<all_urls>']});
Tests:
open tab with http://google.com:
catched https://www.google.com/
open extension console and run fetch('http://google.com'):
catched http://google.com/
open another extension console and run fetch('http://google.com'):
// no output
Does anybody know if is it possible and if so, how to set it up?
Thanks!

Updated
My previous answer it not correct, see #Rob W's comments.
But when #Xan mentioned that extension URLs were visible to other extensions, it became apparent that this behavior is undesirable and a security issue, so I removed the ability for extensions to see other extensions' requests
Previous answer
It's not allowed to handle requests sent from other extensions.
In addition, even certain requests with URLs using one of the above schemes are hidden, e.g., chrome-extension://other_extension_id where other_extension_id is not the ID of the extension to handle the request, https://www.google.com/chrome, and others (this list is not complete).

Related

Can I use Chrome declarativeNetRequest to completely replace Chrome webRequest?

I found chrome.declarativeNetRequest only supports static rules, What I want is to call some custom methods before actions like redirect/request. I haven't found a solution so far. I'm not sure if I can still do this under the Manifest V3.
There are two usecases for my extension.
Before the redirect, I need to execute custom method.
chrome.webRequest.onBeforeRequest.addListener(
function(requestDetails) {
//
// I can get id from requestDetails.url,
// then do some custom business logic.
//
custom_function(requestDetails.url);
return {redirectUrl:"javascript:"};
},
{urls: [ "url_pattern?id=*" ]},
["blocking"]
);
Before some request, I want add/modify requestHeaders according to the user's browser.
chrome.webRequest.onBeforeSendHeaders.addListener(
function (details) {
details.requestHeaders.push({
"name": "User-Agent",
"value": navigator.userAgent + "version_1.0.0"
});
return {requestHeaders: details.requestHeaders};
},
{
urls: ["*://url_pattern"],
types: ["xmlhttprequest"]
},
["blocking", "requestHeaders"]
);
#wOxxOm Thank you very much for your patient answer !
I prefer to spinner.html. But I have another problem.
I can't set the regexSubstitution to the extension address,
I can use the extensionPath, but the corresponding capture groups doesn't work here.
"regexFilter": "google.com*"
The following are all incorrect:
can't use the corresponding capture groups.
"extensionPath": "/spinner.html?url=\\0"
can't use the extension's address.
"regexSubstitution": "spinner.html?url=\\0"
Is my configuration incorrect?
Adding/deleting headers can only accept static values and it's shown in the official example.
Conditionally adding/deleting/modifying headers based on response headers is tracked in https://crbug.com/1141166.
Nontrivial transformations that exceed the functionality of the actions listed in the documentation naturally cannot be re-implemented.
When https://crbug.com/1262147 is fixed we will be able to define a declarativeNetRequest rule to redirect to a page inside your extension via regexSubstitution or extensionPath and append the original URL as a parameter. This page will act as an interstitial, it will display some kind of UI or a simple progress spinner, process the URL parameters, and redirect the current tab to another URL.
In many cases this approach would introduce flicker and unnecessary visual fuss while the interstitial is displayed shortly, thus frustrating users who will likely abandon using such extensions altogether. Chromium team members who work on extensions seem to think this obscene workaround is acceptable so it's likely they'll roll with it, see also https://crbug.com/1013582.
Use the observational webRequest (without 'blocking' parameter) and chrome.tabs.update to redirect the tab. The downside is that the original request will be sent to the remote server. And this approach obviously won't work for iframes, to redirect those you'll have to inject/declare a content script, to which your webRequest listener would send a message with a frameId parameter.
Keep a visible tab with an html page from your extension, and use the blocking chrome.webRequest inside its scripts. It's a terrible UX, of course, even though endorsed by the Chromium's extensions team, with many extensions using this kludge the user's browsers will have to keep a lot of such tabs open.
P.S. The blocking webRequest will be still available for force-installed extensions via policies, but it's not something most users would be willing to use.

Intercepting requests and returning a local file using chrome extensions

I want to intercept a request and return a local file as the response using a chrome extension. The user is going to provide the local file path.
Requirements
I want to do this only through the extension (ideally). No additional installations, no chrome apps, other 3rd party apps should be needed. I'm happy to provide whatever permissions are needed in the manifest, but this will ship, so it can't be in dev-mode / i.e. can't have dev-only APIs.
The files that the user can select aren't going to be from the extension package, I think the chrome.runtime.getURL allows reading from the relative URLs within the package, but it didn't work for exact paths for other files.
I'm aware that by setting up a server in either on localhost, or elsewhere and by redirecting to that URL; this could be achieved, but I'm not interested in that; I'm looking for an out of the box solution which will help me pass local files as responses.
Also - I'd be happy if there's a workaround - one that I thought was reading the contents of the file that user selected and streaming those contents from memory / or putting them into a temporary location that the file:// can work with, but couldn't find any way around this yet.
Current state
I'm using the snippet below to handle interception:
// API that I'm using
chrome.webRequest.onBeforeRequest.addListener(function(request){...})
Manifest looks like this:
{
...
"background": {
"scripts": ["background.js"],
"persistent": true
},
"permissions": [
"activeTab",
"tabs",
"http://*/*",
"https://*/*",
"file://*/*",
"webRequest",
"webRequestBlocking"
]
}
I've been able to intercept requests and redirect to other http(s) URLs - this works fine. I'm also receiving the user input for the file path just fine, using <input type="file"/> for this.
Redirecting the request path to be a file doesn't work though; for obvious security reasons. This is the bit that I'm stuck. Being a bit more descriptive below:
chrome.webRequest.onBeforeRequest.addListener(function(request){
// works fine
if (request.url === 'https://someurl') {
return {redirectUrl : 'https://someotherurl'};
}
// doesn't work - and I'm looking for a solution for this scenario
else if (request.url === 'https://someurl2') {
return {redirectUrl: 'file://somefileondisk' };
}
});
and this doesn't:

How to programmatically enable flash in Chrome? [duplicate]

chrome.tabs returns undefined despite the fact I set tabs in the permissions block.
"permissions": [
"tabs",
"http://*/*",
"https://*/*"
],
"content_scripts": [
{
"matches": [
"http://*/*",
"https://*/*"
],
"js": [
"js/myScript.js"
],
"all_frames": true
}
],
But in myScript.js the following returns undefined.
chrome.tabs
As content script has its own limitations,
chrome.tabs is only available in background scripts and popup scripts.
If you wanna to use chrome.tabs then pass message from content_script to background script and play with chrome.tabs.
Content scripts have only limited access to Chrome APIs. This access does not include the API you are trying to use (e.g. chrome.tabs). If you need to use that API, you will have to do so in a background script1.
As listed in Chrome's content scripts documentation, the APIs available to a content script are [I have placed deprecated methods in strikethrough format]:
extension ( getURL , inIncognitoContext , lastError , onRequest , sendRequest )
i18n
runtime ( connect , getManifest , getURL , id , onConnect , onMessage , sendMessage )
storage
A couple of the listed APIs are deprecated and have been for some time. Those that are deprecated have moved to different locations (also listed above):
extension.onRequest ➞ runtime.onMessage
extension.sendRequest ➞ runtime.sendMessage
While not officially deprecated, extension.lastError is also available as runtime.lastError. At this point, it is usually referred to at that location:
extension.lastError ➞ runtime.lastError
Partition your extension into background scripts and content scripts
You are going to need to separate your code into what needs to be in a background script and what needs to be in content scripts, based on the capabilities available to each type of script. Content scripts have access to the DOM of the web page into which they are injected, but limited access to extension APIs. Background scripts have full access to the extension APIs, but no access to web page content. You should read the Chrome extension overview, and the pages linked from there, to get a feel for what functionality should be located in which type of script.
It is common to need to communicate between your content scripts and background scripts. To do so you can use message passing. This allows you to communicate information between the two scripts to accomplish things which are not possible using only one type of script.
For instance, in your content script, you may need information which is only available from one of the other Chrome APIs, or you need something to happen which can most appropriately (or only) be done through one of the other Chrome extension APIs. In these cases, you will need to send a message to your background script, using chrome.runtime.sendMessage(), to tell it what needs to be done, while providing enough informaiton for it to be able to do so. Your background script can then return the desired information, if any, to your content script. Alternately, you will have times when the processing will primarily be done in the background script. The background script may inject a content script, or just message an already injected script, to obtain information from a page, or make changes to the web page.
Background script means any script that is in the background context. In addition to actual background scripts, this includes popups and options pages, etc. However, the only page that you can be sure to have consistently available to receive messages from a content script are your actual background scripts defined in manifest.json. Other pages may be available at some times as a result of the user's interaction with the browser, but they are not available consistently.
This answer was moved from a duplicate question, and then modified.
https://developer.chrome.com/extensions/tabs#method-getSelected shows
getSelected
chrome.tabs.getSelected(integer windowId, function
callback)
Deprecated since Chrome 33. Please use tabs.query {active: true}.
Gets the tab that is selected in the specified window.
Maybe, you should use chrome.tabs.query in popup.js like this
chrome.tabs.query({active: true, currentWindow: true}, function(tabs){
console.log(tabs[0].url);
});
, reload your extension and check the result in the inspect element of your extension.
result image
code image
https://developer.chrome.com/extensions/tabs#type-Tab shows that
The URL the tab is displaying. This property is only present if the extension's manifest includes the "tabs" permission.(Just for remind someone forgot. I was forgot it when I just test it.)
Check this answer also https://stackoverflow.com/a/6718277/449345
This one worked for me
chrome.tabs.getSelected(null, function(tab){
console.log(tab);
});

Error thrown when executing chrome.extension.getBackgroundPage()

I am working on my first extension and am trying to create a simple extension to inject a draggable div on a page. That works nicely, but I want to preserve the location of the div on the background page (I'm also trying out local storage, but want to understand why this isn't working).
I do not need a button so have not created a popup.html file, which, I believe, is entirely optional. It certainly has worked so far just injecting javascript files.
However, I now get the following error thrown when executing chrome.extension.getBackgroundPage():
Uncaught Error: chrome.extension.getBackgroundPage can only be used in extension processes. See the content scripts documentation for more details.
The content scripts documentation did not seem to identify anything wrong with my approach: http://code.google.com/chrome/extensions/content_scripts.html
Here is a redacted manifest I am using:
{
"name": "My helper",
"version": "1.0",
"description": "Tastes great",
"background_page": "background.html",
"content_scripts": [
{
"matches":["https://page.of.interest/*"],
"run_at":"document_idle",
"js":[ "jquery.js", "jquery-ui-1.8.17.custom.min.js", "my_content_script.js"],
"css": [ "my_content_script.css" ]
}
],
"permissions": [
"background"
]
}
So I am running this statement inside "my_content_script.js". Is this NOT considered part of the extension process? Can I only run this on a popup.html (or other possibly?) file?
If this is the case, then maybe it is easier to just use localstorage rather than trying to communicate through the dom with the extension process.
Hope I've been clear despite my ignorance about some of these concepts.
I don't think the docs explicitly say you can't use chrome.extension.getBackgroundPage() from a content_script but because the content_script has permissions more oriented with the page it is being run on it isn't allowed access. The docs do mention a few methods you can use however.
Unlike the other chrome.* APIs, parts of chrome.extension can be used by content scripts:
You will have to use message passing to communicate between the background_page and the content_script.
You have to use the chrome.cookies.get() in background.html, and then do the communication between your content script and background.html for exchanging cookie data.

chrome.tabs.executeScript not working?

I am trying to learn to use the chrome.tabs.executeScript commend. I've created a simple extension with a browser action. My background.html file currently looks like this:
<html>
<script>
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript(null,{code:"document.body.bgColor='red'"});
chrome.tabs.executeScript(null, {file: "content_script.js"});
});
</script>
</html>
The "content_script.js" file contains document.body.bgColor='red'.
When pushing the browser action's button nothing happens. Obviously I'm missing something very basic.
I've checked with console.log that indeed control reaches the chrome.tabs.executeScript calls when the browser action is pressed. Otherwise I'm not sure how to even check if my content script's code is run (it seems not; console.log I put in the content script has no effect, but maybe it shouldn't have one even if the script is run successfully).
Make sure you have domain and tab permissions in the manifest:
"permissions": [
"tabs", "http://*/*", "https://*/*"
]
Then to change body color try:
chrome.tabs.executeScript(null,{code:"document.body.style.backgroundColor='red'"});
Also keep in mind that content scripts are not injected into any chrome:// or extension gallery pages.
For those of you still having issues, you need to make sure to reload the extension's permissions in Chrome.
Go to chrome://extensions , scroll to your extension, and click on "reload". Make sure that your permissions have been updated by clicking on the permissions link right next to your extension.
You actually don't need and don't want the 'tabs' permission for executeScript.
"permissions": [
"http://*/*",
"https://*/*"
]
Should be enough.
It's not recommended to use http://*/* and https://*/*. From the Google documentation:
To inject a programmatic content script, provide the activeTab permission in the manifest. This grants secure access to the active site's host and temporary access to the tabs permission, enabling the content script to run on the current active tab without specifying cross-origin permissions.
Instead, (as suggested in the page) just use activeTab permission.
Remark: more explanation for the security issue
Without activeTab, this extension would need to request full, persistent access to every web site, just so that it could do its work if it happened to be called upon by the user. This is a lot of power to entrust to such a simple extension. And if the extension is ever compromised, the attacker gets access to everything the extension had.
In contrast, an extension with the activeTab permission only obtains access to a tab in response to an explicit user gesture. If the extension is compromised the attacker would need to wait for the user to invoke the extension before obtaining access. And that access only lasts until the tab is navigated or is closed.
(emphasis mine)
In the example code posted by the OP, activeTab is sufficient.
However, if the extension is more complex and needs to work "automatically" (i.e. without the user clicking the button); then this method will not work and additional permission is required.
Most of the answers above seems to be working fine for manifest version 2 but when it comes manifest-3 their seems to be some workaround to make the content-script load in the latest manifest 3.We need to use the following steps to execute content script in manifest 3
First adding permission "scripting" in manifest
"permissions": [
"storage",
"tabs",
"activeTab",
"scripting"
]
Once the scripting perimission is provided, we can use the scripting api like below
In background.js,
chrome.tabs.query({}, (tabList) => {
if (!tabList.length) return;
tabList.forEach((tab) => {
chrome.scripting.executeScript(
{
files: ['contentScript.js'],
target: {
tabId: tab.id,
allFrames: true
}
}
);
});
});
In the above code we are executing the contentScript for all the available tabs in tab browser.

Resources