I have previously intercepted, paused, inserted a body, then continued a fetch() request made from any tab or window using Fetch.enable, listening for Fetch.requestPaused and other Fetch domain definitions, something like this
chrome.debugger.onEvent.addListener(async ({
tabId
}, message, params) => {
console.log(tabId, message, params);
if (
message === 'Fetch.requestPaused' &&
/^chrome-extension|ext_stream/.test(params.request.url)
) {
await chrome.debugger.sendCommand({
tabId
}, 'Fetch.fulfillRequest', {
responseCode: 200,
requestId: params.requestId,
requestHeaders: params.request.headers,
body: bytesArrToBase64(
encoder.encode(
JSON.stringify([...Uint8Array.from({
length: 1764
}, () => 255)])
)
),
});
await chrome.debugger.sendCommand({
tabId
}, 'Fetch.continueRequest', {
requestId: params.requestId,
});
} else {
await chrome.debugger.sendCommand({
tabId
}, 'Fetch.continueRequest', {
requestId: params.requestId,
});
}
});
const tabId = tab.id;
await chrome.debugger.attach({
tabId
}, '1.3');
await chrome.debugger.sendCommand({
tabId
}, 'Fetch.enable', {
patterns: [{
requestStage: "Request",
resourceType: "XHR",
urlPattern: '*ext_stream'
}]
});
Now I’m working on intercepting a WebTransport request, then start a local WebTransport server using Native Messaging, then continue the request.
First iteration of code. I ordinarily wouldn’t ask questions about my first draft. Generally I hack away at for a while before asking about any part of the process. Here goes, anyway, using Network.webTransportCreated
globalThis.port;
chrome.debugger.onEvent.addListener(async ({
tabId
}, message, params) => {
if (message === "Network.webTransportCreated" &&
params.url ===
"https://localhost:4433/path") {
if (globalThis.port === undefined) {
globalThis.port = chrome.runtime.connectNative(chrome.runtime.getManifest().short_name);
port.onMessage.addListener(async (e) => {
console.log(e);
});
port.onDisconnect.addListener(async (e) => {
if (chrome.runtime.lastError) {
console.log(chrome.runtime.lastError);
}
console.log(e);
});
} else {
// ...
}
}
});
At least this is my initial concept for what I want to do. If the Dev Tools Protocol, or other extension API’s don’t have an explicit or implicit way to do this, then I’ll just do this another way. I’ve done this different ways in the past.
I looked. Didn’t find anything that was obvious to me in the Network domain that will facilitate the process I’m able to do with Fetch domain and fetch().
The Network.webTransportCreated event is dispatched when the request is made from the arbitrary Web page console or Snippets. The code looks something like this
(async () => {
try {
const serverCertificateHashes = [
{
"algorithm": "sha-256",
// Hardcoding the certificate here
// after serilizing to JSON for import with {type: "json"}...
"value": Uint8Array.of(
0, 1, 2, ...
),
},
];
const client = new WebTransport(
`https://localhost:4433/path`,
{
serverCertificateHashes,
},
);
// ...
The request doesn’t pause though. It usually takes between 200 to 300 milliseconds to start a node or deno or bun, etc. server using Native Messaging to launch the application; startup time of the executable. So the server is not started in time to handle the request.
I also tried making two (2) WebTransport requests. The first just to start the local WebTransport server. Then the error has to be handled, which involves including async code in error handling code. I think the double request to do one thing pattern has some technical debt. If all else fails, I’ll retry that, though.
Just curious if I’m missing something in the Network domain or extension API’s that could be used for this case – pausing a created WebTransport request, then continuing that request, programmatically?