I have a Chrome extension that can (if you allow access to file URLs) grab your local pdf file that you have open in chrome and send it on to our API for processing. This is done by fetching the pdf with XMLHttpRequest
to file:///Users/user/whatever/testfile.pdf
from the background script.
When migrating to manifest v3 for a Chrome extension the background script becomes a service worker. In a service worker only fetch
is available, not XMLHttpRequest
. Problem is, fetch only supports http and https, not file:// urls. So how can I make the same feature of having the Chrome extension fetching/getting the local file?
EDIT: Things I also tried:
Making the XMLHttpRequest from injected iframe as suggested by answer.
This gives error net:ERR_UNKNOWN_URL_SCHEME
when making the request
Making the XMLHttpRequest from injected content script.
This gives error Access to XMLHttpRequest at 'file:///.../testfile1.docx.pdf' from origin 'null' has been blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, chrome-untrusted, https.
From what I can understand from a lot of research access to file://
is in general blocked and Chrome extension background scripts used to be an exception to this. Seems to me it was never allowed from content scripts or action popups.
My manifest.json for reference:
{
"manifest_version": 3,
"name": "..",
"version": "0.1",
"icons": {
"16": "assets/icon-16x16.png",
"48": "assets/icon-48x48.png",
"128": "assets/icon-128x128.png"
},
"action": {
"default_title": ".."
},
"background": {
"service_worker": "background.js"
},
"permissions": [
"webRequest",
"activeTab",
"scripting",
"storage",
"unlimitedStorage",
"identity",
"pageCapture"
],
"host_permissions": [
"<all_urls>"
],
"web_accessible_resources": [{
"resources": ["iframe.html"],
"matches": [],
"extension_ids": []
}]
}
The content script is injected programmatically (using webextension-polyfill
for promise support)
browser.action.onClicked.addListener(async (tab: Tab) => {
await browser.scripting.executeScript({files: [ "inject.js" ], target: {tabId: tab.id}});
});
In Google Chrome, links to local files are disabled, unlike IE. This extension allows you to open a link to a local file by clicking it.
You can just use chrome. runtime. getManifest() to access the manifest data - you don't need to GET it and parse it.
First check if manifest. json is applied in the browser. For that open developer window by pressing shortcut F12. In Application tab, click Manifest option and see if it displays information that you have set.
The manifest file uses JSON format to describe the important information about the extension. It contains fields that are required and recommended while others are optional depending on the extension you are building. name refers to the name of the extension and should be up to 45 characters.
Chrome 98 and older can't do it in the background service worker for the reasons you mentioned.
There was also a bug that prevented doing it in a normal visible chrome-extension://
page or iframe. It's fixed in Chrome 91.
Use fetch
in Chrome 99 and newer.
In older versions use the following workarounds.
A ManifestV3 extension can use the new File System API to read the contents of the file, for example inside the iframe exposed via web_accessible_resources.
Use a content script that runs in the tab with that pdf:
matches
in manifest.json should contain <all_urls>
or file://*/*
and file access should be enabled by the user in
chrome://extensions UI for your extension. Alternatively you can use
activeTab
permission and programmatic injection when the user
clicks your extension's icon or invokes it through the context menu.iframe.html
file exposed in web_accessible_resources
iframe.html
loads iframe.js
which uses XMLHttpRequest as usual. Since the iframe has chrome-extension://
URL its environment
is the same as your old background script so you can do everything
you did before right there.An alternative solution is to use any other visible page of your
extension like the action
popup or options page or any other
chrome-extension:// page belonging to your extension as they can
access the file://
URL via XMLHttpRequest same as before.
chrome://extensions
page for this extension.If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With