Created
February 8, 2020 18:04
-
-
Save feliperohdee/e41a96fa95ca206e00f825f46cda93f3 to your computer and use it in GitHub Desktop.
chrome.debugger intercept scripts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(async () => { | |
const scripts = new Map([ | |
['app', chrome.runtime.getURL('static/app.js')], | |
['app2', chrome.runtime.getURL('static/app2.js')], | |
['progress', chrome.runtime.getURL('static/progress.js')] | |
]); | |
const p = async (fn, ...args) => { | |
return new Promise((resolve, reject) => { | |
return fn(...[...args, (...response) => { | |
if (chrome.runtime.lastError) { | |
return reject(chrome.runtime.lastError.message); | |
} | |
resolve(...response); | |
}]); | |
}); | |
}; | |
const wait = async time => { | |
return new Promise(resolve => { | |
setTimeout(resolve, time); | |
}); | |
}; | |
const getScript = async (key, request) => { | |
const headers = [{ | |
name: 'ii', | |
value: 'true' | |
}]; | |
const response = await fetch(request.url, { | |
headers: new Headers(request.headers) | |
}); | |
response.headers.forEach((value, name) => { | |
headers.push({ | |
name, | |
value | |
}); | |
}); | |
if (!scripts.has(key)) { | |
return null; | |
} | |
await wait(1500); | |
const script = await fetch(scripts.get(key)); | |
return { | |
body: btoa(unescape(encodeURIComponent(await script.text()))), | |
headers | |
}; | |
}; | |
class Tab { | |
constructor(id) { | |
this.id = id; | |
this.attached = false; | |
this.intercepting = false; | |
this.scripts = 0; | |
this.status = 'loading'; | |
} | |
close() { | |
chrome.tabs.remove(this.id); | |
} | |
async attach() { | |
if (this.attached) { | |
return; | |
} | |
await p(chrome.debugger.attach, { | |
tabId: this.id | |
}, '1.0'); | |
this.attached = true; | |
} | |
async detach() { | |
if (!this.attached) { | |
return; | |
} | |
await p(chrome.debugger.detach, { | |
tabId: this.id | |
}); | |
this.attached = false; | |
this.intercepting = false; | |
} | |
async fullFillRequest(requestId, script) { | |
if (!this.attached) { | |
return; | |
} | |
await p(chrome.debugger.sendCommand, { | |
tabId: this.id | |
}, 'Fetch.fulfillRequest', { | |
requestId, | |
responseCode: 200, | |
responseHeaders: script.headers, | |
body: script.body | |
}); | |
return scripts.size === ++this.scripts; | |
} | |
async intercept() { | |
if (this.intercepting) { | |
return; | |
} | |
await p(chrome.debugger.sendCommand, { | |
tabId: this.id | |
}, 'Fetch.enable', { | |
patterns: [{ | |
urlPattern: '*/progress*.js' | |
}, { | |
urlPattern: '*/app*.js' | |
}] | |
}); | |
this.intercepting = true; | |
} | |
} | |
class Tabs extends Map { | |
add(id) { | |
const tab = new Tab(id); | |
super.set(id, tab); | |
return tab; | |
} | |
} | |
const tabs = new Tabs(); | |
const init = async () => { | |
const { | |
id | |
} = await p(chrome.tabs.create, { | |
url: 'https://web.whatsapp.com' | |
}); | |
const tab = tabs.add(id); | |
await tab.attach(); | |
await tab.intercept(); | |
}; | |
chrome.browserAction.onClicked.addListener(init); | |
chrome.tabs.onUpdated.addListener(async (tabId, info) => { | |
const tab = tabs.get(tabId); | |
if (tab && info.status) { | |
if ( | |
tab.status === 'complete' && | |
info.status === 'loading' | |
) { | |
tab.close(); | |
init(); | |
} else { | |
tab.status = info.status; | |
} | |
} | |
}); | |
chrome.tabs.onRemoved.addListener(tabId => { | |
tabs.delete(tabId); | |
}); | |
chrome.debugger.onEvent.addListener(async (source, method, params) => { | |
if (tabs.has(source.tabId)) { | |
if (method === 'Fetch.requestPaused') { | |
const { | |
request, | |
requestId | |
} = params; | |
let key; | |
if (request.url.includes('/progress.')) { | |
key = 'progress'; | |
} else if (request.url.includes('/app.')) { | |
key = 'app'; | |
} else if (request.url.includes('/app2.')) { | |
key = 'app2'; | |
} | |
const script = await getScript(key, request); | |
const tab = tabs.get(source.tabId); | |
if (script && tab) { | |
const ready = await tab.fullFillRequest(requestId, script); | |
if (ready) { | |
await tab.detach(); | |
} | |
} | |
} | |
} | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment