This question has been already answered Chrome extension: How to show custom UI for a PDF file?
However, the answer seems outdated as it uses manifest V2. How to achieve same in manifest V3 ?
I tried
rules.json
With
[
{
"id": 1,
"priority": 1,
"action": {
"type": "redirect",
"redirect": {
"transform": {
"scheme": "chrome-extension",
"host": "mbojebcnkfasdfalsdfkjalsdkjfa",
"path": "/viewer.html",
"queryTransform": {
"addOrReplaceParams": [
{
"key": "file",
"value": "{url}"
}
]
}
}
}
},
"condition": {
"urlFilter": "*.pdf",
"resourceTypes": ["main_frame", "sub_frame"]
}
}
]
And this,
{
"manifest_version": 3,
"name": "Selection Popup",
"version": "1.0",
"description": "Shows a popup near text selection.",
"permissions": [
"scripting",
"contextMenus",
"activeTab",
"storage",
"tabs",
"declarativeNetRequest",
"declarativeNetRequestWithHostAccess"
],
"background": {
"service_worker": "background.js"
},
"declarative_net_request": {
"rule_resources": [
{
"id": "ruleset_1",
"enabled": true,
"path": "rules.json"
}
]
},
"action": {
"default_popup": "popup.html",
"default_icon": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
},
"options_page": "popup.html",
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": [
"content.js"
],
"css": [
"styles.css"
]
}
],
"web_accessible_resources": [
{
"resources": [
"popup.html",
"script.js",
"pdf.worker.min.js", "pdf.mjs"
],
"matches": [
"<all_urls>"
]
}
],
"icons": {
"16": "icons/icon16.png",
"48": "icons/icon48.png",
"128": "icons/icon128.png"
}
}
But when I open a local pdf file, nothing happens, it still uses the Chrome Default PDF viewer.
Goal is to achieve what this extension does:
https://chromewebstore.google.com/detail/pdf-viewer/oemmndcbldboiebfnladdacbdfmadadm
To redirect a URL, it must be in the extension's host permissions. Since you want to process PDFs on all hosts, you need "host_permissions": ["<all_urls>"]
To redirect to your own page while preserving the original URL and avoid hardcoding the id of the extension you need updateDynamicRules (see this answer) in the background script:
chrome.runtime.onInstalled.addListener(e => {
if (e.reason !== 'update' && e.reason !== 'install') return;
const EXT_PAGE = chrome.runtime.getURL('/viewer.html');
const ID = 1;
chrome.declarativeNetRequest.updateDynamicRules({
removeRuleIds: [ID],
addRules: [{
id: ID,
action: {
type: 'redirect',
redirect: {regexSubstitution: EXT_PAGE + '#\\0'},
},
condition: {
regexFilter: /^.+\.pdf(\?.*)?$/.source,
resourceTypes: ['main_frame', 'sub_frame'],
},
}],
});
});
Now your extension page (viewer.html) can read this URL:
const origUrl = location.hash.slice(1);
As of Chrome 127, we can also match by content type in declarativeNetRequest, but it's not yet enabled in the stable version, so I'm not demonstrating it.
To redirect to a page in your extension, it must be listed in web_accessible_resources:
"web_accessible_resources": [{
"resources": ["viewer.html"],
"matches": ["<all_urls>"]
}],
A published extension from the web store can't open local files by default. The user must enable file access manually in the extension's details in chrome://extensions
page.
Remove declarativeNetRequest
from permissions
because it unnecessarily adds a warning at installation and you already have declarativeNetRequestWithHostAccess
+ host_permissions
.
Remove declarative_net_request
from manifest.json.
You probably don't need content_scripts
running in all pages unconditionally.