const elem = document.getElementById("example")
const shadow_root = chrome.dom.openOrClosedShadowRoot(elem)
closed でも指定の要素の ShadowRoot を取得できる
input タグの内部など open/closed ではなく useragent の ShadowRoot は流石に取れない
const elem = document.getElementById("example")
const shadow_root = chrome.dom.openOrClosedShadowRoot(elem)
const connectPageScript = (name, script, onmessage) => {
const key_prefix = `p-cs-messaging [${name}] `
const scr = document.createElement("script")
scr.innerHTML = `
window.addEventListener("${key_prefix}to-page", eve => {
window.oncsmessage && window.oncsmessage(eve.detail)
})
window.send = msg => window.dispatchEvent(new CustomEvent("${key_prefix}to-cscript", { detail: msg }))
${script}
`
document.head.append(scr)
window.addEventListener(key_prefix + "to-cscript", eve => onmessage(eve.detail))
const send = msg => window.dispatchEvent(new CustomEvent(key_prefix + "to-page", { detail: msg }))
return send
}
const script = `
window.xyz = 100
window.oncsmessage = msg => {
console.log(1, msg)
setTimeout(() => send({ frompage: true, xyz: window.xyz }), 1000)
}
`
const onmessage = msg => {
console.log(2, msg)
}
const send = connectPageScript("foo", script, onmessage)
window.xyz = 200
send({ fromcs: true, xyz: window.xyz })
// 1 {fromcs: true, xyz: 200}
// (1 秒後)
// 2 {frompage: true, xyz: 100}
export const remoteFetch = (url, type, option) => {
return new Promise((resolve, reject) => {
chrome.runtime.sendMessage({ url, type, option }, res => {
if (res) {
if (res.error) {
reject(new Error(res.error))
return
}
if (res.result) {
if (type === "buffer") {
resolve(Uint8Array.from(res.result).buffer)
} else {
resolve(res.result)
}
return
}
} else {
reject("Something went wrong.")
}
})
})
}
const remoteFetchListener = (req, sender, sendResponse) => {
if (!req.url) {
sendError("missing url")
return false
}
try {
new URL(req.url)
} catch {
sendError("Invalid URL: " + req.url)
return false
}
fetch(req.url, req.option)
.then(async res => {
if (!res.ok) {
throw new Error("Rensponse is not ok: " + res.status)
}
let result = null
if (req.type === "json") {
result = await res.json()
} else if (req.type === "buffer") {
const ab = await res.arrayBuffer()
result = Array.from(new Uint8Array(ab))
} else {
result = await res.text()
}
sendResponse({ result })
})
.catch(err => {
sendError("Fetch error: " + err.message)
})
return true
function sendError(message) {
sendResponse({ error: message })
}
}
export const listenRemoteFetch = () => {
chrome.runtime.onMessage.addListener(remoteFetchListener)
}
export const unlistenRemoteFetch = () => {
chrome.runtime.onMessage.removeListener(remoteFetchListener)
}
import { remoteFetch } from "./remoteFetch.js"
remoteFetch(url, "text").then(console.log)
import { listenRemoteFetch } from "./remoteFetch.js"
listenRemoteFetch()
"background": {
"scripts": ["bg.js"]
}
"background": {
"page": "bg.html"
}
<!doctype html>
<meta charset="utf-8"/>
<script src="bg.js" type="module"></script>
chrome-extension://niloccemoadcdkdjlinkgdfekeahmflj/options.html
なのでchrome-extension://niloccemoadcdkdjlinkgdfekeahmflj/manifest.json
chrome.webRequest.onBeforeRequest.addListener(details => {
if(details.method === "POST"){
return {cancel: true}
}
}, {urls: ["<all_urls>"]}, ["blocking"])
chrome.webRequest.onBeforeRequest.addListener(details => {
if(details.method === "POST"){
return {redirectUrl: "javascript:void 0"}
}
}, {urls: ["<all_urls>"]}, ["blocking"])
{
"content_scripts": [
{
"matches": ["<all_urls>"],
"css": ["style.css"],
"js": ["script.js"]
}
],
}
chrome.storage.local.get({enabled: true, mode: "default"}, ({enabled, mode}) => {
if(!enabled) return
switch(mode){
// some cases
}
})
// content script
chrome.runtime.sendMessage("require-cscript-data", ({enabled, mode}) => {
if(!enabled) return
switch(mode){
// some cases
}
})
// background
let enabled = true
let mode = "default"
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
if(message === "require-cscript-data"){
sendResponse({enabled, mode})
}
})