rename cookie_grabber -> tmwd_cdp_bridge (CDP bridge extension)
This commit is contained in:
43
assets/tmwd_cdp_bridge/background.js
Normal file
43
assets/tmwd_cdp_bridge/background.js
Normal file
@@ -0,0 +1,43 @@
|
||||
// background.js - Cookie + CDP Bridge
|
||||
chrome.runtime.onInstalled.addListener(() => console.log('CDP Bridge installed'));
|
||||
|
||||
chrome.runtime.onMessage.addListener((msg, sender, sendResponse) => {
|
||||
if (msg.action === 'getCookies') {
|
||||
handleGetCookies(msg, sender).then(sendResponse);
|
||||
return true;
|
||||
}
|
||||
if (msg.action === 'cdp') {
|
||||
handleCDP(msg, sender).then(sendResponse);
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
async function handleGetCookies(msg, sender) {
|
||||
try {
|
||||
const url = msg.url || sender.tab?.url;
|
||||
const origin = url.match(/^https?:\/\/[^\/]+/)[0];
|
||||
const all = await chrome.cookies.getAll({ url });
|
||||
const part = await chrome.cookies.getAll({ url, partitionKey: { topLevelSite: origin } }).catch(() => []);
|
||||
const merged = [...all];
|
||||
for (const c of part) {
|
||||
if (!merged.some(x => x.name === c.name && x.domain === c.domain)) merged.push(c);
|
||||
}
|
||||
return { ok: true, data: merged };
|
||||
} catch (e) {
|
||||
return { ok: false, error: e.message };
|
||||
}
|
||||
}
|
||||
|
||||
async function handleCDP(msg, sender) {
|
||||
const tabId = msg.tabId || sender.tab?.id;
|
||||
if (!tabId) return { ok: false, error: 'no tabId' };
|
||||
try {
|
||||
await chrome.debugger.attach({ tabId }, '1.3');
|
||||
const result = await chrome.debugger.sendCommand({ tabId }, msg.method, msg.params || {});
|
||||
await chrome.debugger.detach({ tabId });
|
||||
return { ok: true, data: result };
|
||||
} catch (e) {
|
||||
try { await chrome.debugger.detach({ tabId }); } catch (_) {}
|
||||
return { ok: false, error: e.message };
|
||||
}
|
||||
}
|
||||
31
assets/tmwd_cdp_bridge/content.js
Normal file
31
assets/tmwd_cdp_bridge/content.js
Normal file
@@ -0,0 +1,31 @@
|
||||
// content.js - DOM trigger bridge
|
||||
const TID = '__ljq_ctrl';
|
||||
|
||||
new MutationObserver(muts => {
|
||||
for (const m of muts) for (const n of m.addedNodes) {
|
||||
if (n.id === TID || (n.querySelector && n.querySelector('#' + TID))) {
|
||||
const el = n.id === TID ? n : n.querySelector('#' + TID);
|
||||
handle(el);
|
||||
}
|
||||
}
|
||||
}).observe(document.documentElement, { childList: true, subtree: true });
|
||||
|
||||
async function handle(el) {
|
||||
try {
|
||||
const cmd = el.dataset.cmd || 'cookies';
|
||||
let resp;
|
||||
if (cmd === 'cookies') {
|
||||
resp = await chrome.runtime.sendMessage({ action: 'getCookies', url: location.href });
|
||||
} else if (cmd === 'cdp') {
|
||||
const method = el.dataset.method;
|
||||
const params = el.dataset.params ? JSON.parse(el.dataset.params) : {};
|
||||
const tabId = el.dataset.tabid ? parseInt(el.dataset.tabid) : undefined;
|
||||
resp = await chrome.runtime.sendMessage({ action: 'cdp', method, params, tabId });
|
||||
} else {
|
||||
resp = { ok: false, error: 'unknown cmd: ' + cmd };
|
||||
}
|
||||
el.textContent = JSON.stringify(resp);
|
||||
} catch (e) {
|
||||
el.textContent = JSON.stringify({ ok: false, error: e.message });
|
||||
}
|
||||
}
|
||||
28
assets/tmwd_cdp_bridge/manifest.json
Normal file
28
assets/tmwd_cdp_bridge/manifest.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"manifest_version": 3,
|
||||
"name": "Cookie Grabber",
|
||||
"version": "2.0",
|
||||
"description": "Cookie viewer + CDP bridge",
|
||||
"permissions": [
|
||||
"cookies",
|
||||
"tabs",
|
||||
"activeTab",
|
||||
"debugger"
|
||||
],
|
||||
"host_permissions": ["<all_urls>"],
|
||||
"background": {
|
||||
"service_worker": "background.js"
|
||||
},
|
||||
"content_scripts": [
|
||||
{
|
||||
"matches": ["<all_urls>"],
|
||||
"js": ["content.js"],
|
||||
"run_at": "document_idle",
|
||||
"all_frames": true
|
||||
}
|
||||
],
|
||||
"action": {
|
||||
"default_popup": "popup.html",
|
||||
"default_title": "Cookie Grabber"
|
||||
}
|
||||
}
|
||||
19
assets/tmwd_cdp_bridge/popup.html
Normal file
19
assets/tmwd_cdp_bridge/popup.html
Normal file
@@ -0,0 +1,19 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<style>
|
||||
body{width:420px;max-height:500px;margin:0;padding:8px;font:12px monospace;background:#1e1e1e;color:#d4d4d4;overflow-y:auto}
|
||||
h3{margin:4px 0;color:#569cd6}
|
||||
button{background:#264f78;color:#fff;border:none;padding:4px 12px;cursor:pointer;border-radius:3px;margin-bottom:6px}
|
||||
button:hover{background:#37699e}
|
||||
pre{white-space:pre-wrap;word-break:break-all;margin:0;padding:6px;background:#252526;border-radius:3px;max-height:420px;overflow-y:auto}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h3>🍪 Cookies</h3>
|
||||
<button id="refresh">刷新</button>
|
||||
<pre id="out">点击刷新获取 cookies...</pre>
|
||||
<script src="popup.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
24
assets/tmwd_cdp_bridge/popup.js
Normal file
24
assets/tmwd_cdp_bridge/popup.js
Normal file
@@ -0,0 +1,24 @@
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const out = document.getElementById('out');
|
||||
const btn = document.getElementById('refresh');
|
||||
btn.addEventListener('click', fetchCookies);
|
||||
fetchCookies();
|
||||
});
|
||||
|
||||
async function fetchCookies() {
|
||||
const out = document.getElementById('out');
|
||||
try {
|
||||
const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
|
||||
if (!tab?.url) { out.textContent = 'No active tab'; return; }
|
||||
const resp = await chrome.runtime.sendMessage({ action: 'getCookies', url: tab.url });
|
||||
if (!resp?.ok) { out.textContent = 'Error: ' + (resp?.error || 'unknown'); return; }
|
||||
if (!resp.data.length) { out.textContent = '(no cookies)'; return; }
|
||||
// 展示带标记
|
||||
out.textContent = resp.data.map(c =>
|
||||
`${c.name}=${c.value}` + (c.httpOnly ? ' [H]' : '') + (c.secure ? ' [S]' : '') + (c.partitionKey ? ' [P]' : '')
|
||||
).join('\n');
|
||||
// 自动复制 name=value; 格式到剪贴板
|
||||
const str = resp.data.map(c => `${c.name}=${c.value}`).join('; ');
|
||||
await navigator.clipboard.writeText(str);
|
||||
} catch (e) { out.textContent = 'Error: ' + e.message; }
|
||||
}
|
||||
Reference in New Issue
Block a user