├── .gitignore ├── assets ├── icons │ ├── ws-48.png │ ├── ws-96.png │ ├── ws-16_logo.png │ ├── ws-32_logo.png │ ├── ws-16_logo_inact.png │ └── ws-32_logo_inact.png ├── ws-list.html ├── ws-list.js └── ws-list.css ├── package.json ├── manifest.json └── background └── main.js /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules/ 3 | 4 | *.sublime-* -------------------------------------------------------------------------------- /assets/icons/ws-48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbnuqw/ws-detector/HEAD/assets/icons/ws-48.png -------------------------------------------------------------------------------- /assets/icons/ws-96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbnuqw/ws-detector/HEAD/assets/icons/ws-96.png -------------------------------------------------------------------------------- /assets/icons/ws-16_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbnuqw/ws-detector/HEAD/assets/icons/ws-16_logo.png -------------------------------------------------------------------------------- /assets/icons/ws-32_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbnuqw/ws-detector/HEAD/assets/icons/ws-32_logo.png -------------------------------------------------------------------------------- /assets/icons/ws-16_logo_inact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbnuqw/ws-detector/HEAD/assets/icons/ws-16_logo_inact.png -------------------------------------------------------------------------------- /assets/icons/ws-32_logo_inact.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mbnuqw/ws-detector/HEAD/assets/icons/ws-32_logo_inact.png -------------------------------------------------------------------------------- /assets/ws-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /assets/ws-list.js: -------------------------------------------------------------------------------- 1 | const Port = window.browser.runtime.connect({ name: 'ws-list-port' }) 2 | const ListEl = document.getElementById('ws_list') 3 | 4 | Port.onMessage.addListener(wsTab => { 5 | wsTab.ws.map(ws => { 6 | let wsUrlEl = document.createElement('div') 7 | wsUrlEl.classList.add('ws-url') 8 | wsUrlEl.setAttribute('title', ws) 9 | wsUrlEl.innerText = ws 10 | ListEl.appendChild(wsUrlEl) 11 | }) 12 | }) 13 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "ws-detector", 3 | "version": "1.2.3", 4 | "description": "WebExtension for detecting websocket connection.", 5 | "scripts": { 6 | "dev": "web-ext run -f firefox-nightly", 7 | "build": "web-ext build -a dist/ -i *.lock ./package.json", 8 | "lint": "./node_modules/.bin/web-ext lint" 9 | }, 10 | "main": "background/main.js", 11 | "author": "", 12 | "license": "MIT", 13 | "dependencies": { 14 | "web-ext": "3.1.1" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "manifest_version": 2, 3 | "name": "WebSocket Detector", 4 | "version": "1.2.3", 5 | 6 | "description": "Detects websocket connection.", 7 | "homepage_url": "https://github.com/mbnuqw/ws-detector", 8 | "icons": { 9 | "48": "./assets/icons/ws-48.png", 10 | "96": "./assets/icons/ws-96.png" 11 | }, 12 | "permissions": ["webRequest", "tabs", ""], 13 | 14 | "page_action": { 15 | "default_icon": { 16 | "19": "./assets/icons/ws-16_logo_inact.png", 17 | "38": "./assets/icons/ws-32_logo_inact.png" 18 | }, 19 | "default_title": "WebSocket not detected" 20 | }, 21 | 22 | "background": { 23 | "scripts": ["background/main.js"] 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /assets/ws-list.css: -------------------------------------------------------------------------------- 1 | html { 2 | position: relative; 3 | padding: 0; 4 | margin: 0; 5 | } 6 | 7 | body { 8 | position: relative; 9 | width: 100%; 10 | max-height: 300px; 11 | overflow-y: auto; 12 | padding: 0; 13 | margin: 0; 14 | } 15 | 16 | .ws-list { 17 | position: relative; 18 | padding: 12px 0; 19 | margin: 0; 20 | } 21 | 22 | .ws-url { 23 | position: relative; 24 | display: block; 25 | max-width: 350px; 26 | min-width: 160px; 27 | padding: 0 24px; 28 | margin: 0 0 8px 0; 29 | font-size: 12px; 30 | color: #ea6913; 31 | text-indent: 0; 32 | font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 33 | 'Helvetica Neue', Arial, system-ui, sans-serif; 34 | white-space: nowrap; 35 | overflow: hidden; 36 | text-overflow: ellipsis; 37 | } 38 | 39 | .ws-url:last-of-type { 40 | margin: 0 0 2px; 41 | } 42 | -------------------------------------------------------------------------------- /background/main.js: -------------------------------------------------------------------------------- 1 | const WSTabs = [] 2 | const UrlPathRe = /^(.+:\/(\/[^\?]+)+?)(\?)?.*$/ 3 | 4 | /** 5 | * Update pageAction: title, icon, popup 6 | **/ 7 | function UpdatePageAction(tab) { 8 | if (!tab.ws.length) { 9 | window.browser.pageAction.hide(tab.id) 10 | window.browser.pageAction.setTitle({ 11 | tabId: tab.id, 12 | title: 'WebSocket not detected', 13 | }) 14 | window.browser.pageAction.setIcon({ 15 | tabId: tab.id, 16 | path: { 17 | '19': './assets/icons/ws-16_logo_inact.png', 18 | '38': './assets/icons/ws-32_logo_inact.png', 19 | }, 20 | }) 21 | window.browser.pageAction.setPopup({ 22 | tabId: tab.id, 23 | popup: '', 24 | }) 25 | } else { 26 | window.browser.pageAction.show(tab.id) 27 | window.browser.pageAction.setTitle({ 28 | tabId: tab.id, 29 | title: 'WebSocket detected', 30 | }) 31 | window.browser.pageAction.setIcon({ 32 | tabId: tab.id, 33 | path: { 34 | '19': './assets/icons/ws-16_logo.png', 35 | '38': './assets/icons/ws-32_logo.png', 36 | }, 37 | }) 38 | window.browser.pageAction.setPopup({ 39 | tabId: tab.id, 40 | popup: './assets/ws-list.html', 41 | }) 42 | } 43 | } 44 | 45 | // Setup communication with popup 46 | window.browser.runtime.onConnect.addListener(port => { 47 | // Send message to popup with active tab info 48 | browser.tabs.query({ active: true, currentWindow: true }).then(tabs => { 49 | port.postMessage(WSTabs.find(t => t.id === tabs[0].id)) 50 | }) 51 | }) 52 | 53 | // Handle requests 54 | window.browser.webRequest.onHeadersReceived.addListener( 55 | req => { 56 | if (req.type !== 'websocket' && req.type !== 'main_frame') return 57 | 58 | let targetTab = WSTabs.find(t => t.id === req.tabId) 59 | 60 | // Reset ws popup for this tab 61 | if (targetTab && !req.documentUrl && req.parentFrameId === -1) { 62 | targetTab.ws = [] 63 | UpdatePageAction(targetTab) 64 | return 65 | } 66 | 67 | let urlPath = UrlPathRe.exec(req.url)[1] 68 | 69 | if (targetTab) { 70 | // Check if there is similar ws url 71 | let wsUrlIndex = targetTab.ws.findIndex( 72 | url => url.indexOf(urlPath) !== -1 73 | ) 74 | 75 | if (wsUrlIndex === -1) 76 | // Add new ws url 77 | targetTab.ws.push(req.url) 78 | else 79 | // Replace similar ws url with new one 80 | targetTab.ws.splice(wsUrlIndex, 1, req.url) 81 | } else { 82 | // Create 83 | targetTab = { 84 | id: req.tabId, 85 | originUrl: req.originUrl, 86 | ws: [req.url], 87 | } 88 | WSTabs.push(targetTab) 89 | } 90 | 91 | UpdatePageAction(targetTab) 92 | }, 93 | { 94 | urls: [''], 95 | } 96 | ) 97 | 98 | // Handle tab closing 99 | window.browser.tabs.onRemoved.addListener(tabId => { 100 | let targetIndex = WSTabs.findIndex(t => t.id === tabId) 101 | if (targetIndex !== -1) WSTabs.splice(targetIndex, 1) 102 | }) 103 | --------------------------------------------------------------------------------