├── .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 |
--------------------------------------------------------------------------------