@gxp-dev/tools 2.0.63 → 2.0.65
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +32 -31
- package/bin/gx-devtools.js +74 -54
- package/bin/lib/cli.js +23 -21
- package/bin/lib/commands/add-dependency.js +366 -325
- package/bin/lib/commands/assets.js +137 -139
- package/bin/lib/commands/build.js +169 -174
- package/bin/lib/commands/datastore.js +181 -183
- package/bin/lib/commands/dev.js +127 -131
- package/bin/lib/commands/extensions.js +147 -149
- package/bin/lib/commands/extract-config.js +73 -67
- package/bin/lib/commands/index.js +12 -12
- package/bin/lib/commands/init.js +342 -240
- package/bin/lib/commands/publish.js +69 -75
- package/bin/lib/commands/socket.js +69 -69
- package/bin/lib/commands/ssl.js +14 -14
- package/bin/lib/constants.js +10 -24
- package/bin/lib/tui/App.tsx +761 -705
- package/bin/lib/tui/components/AIPanel.tsx +191 -171
- package/bin/lib/tui/components/CommandInput.tsx +394 -343
- package/bin/lib/tui/components/GeminiPanel.tsx +175 -151
- package/bin/lib/tui/components/Header.tsx +23 -21
- package/bin/lib/tui/components/LogPanel.tsx +244 -220
- package/bin/lib/tui/components/TabBar.tsx +50 -48
- package/bin/lib/tui/components/WelcomeScreen.tsx +126 -71
- package/bin/lib/tui/index.tsx +37 -39
- package/bin/lib/tui/services/AIService.ts +518 -462
- package/bin/lib/tui/services/ExtensionService.ts +140 -129
- package/bin/lib/tui/services/GeminiService.ts +367 -337
- package/bin/lib/tui/services/ServiceManager.ts +344 -322
- package/bin/lib/tui/services/SocketService.ts +168 -168
- package/bin/lib/tui/services/ViteService.ts +88 -88
- package/bin/lib/tui/services/index.ts +47 -22
- package/bin/lib/utils/ai-scaffold.js +291 -280
- package/bin/lib/utils/extract-config.js +157 -140
- package/bin/lib/utils/files.js +82 -86
- package/bin/lib/utils/index.js +7 -7
- package/bin/lib/utils/paths.js +34 -34
- package/bin/lib/utils/prompts.js +194 -169
- package/bin/lib/utils/ssl.js +79 -81
- package/browser-extensions/README.md +0 -1
- package/browser-extensions/chrome/background.js +244 -237
- package/browser-extensions/chrome/content.js +32 -29
- package/browser-extensions/chrome/devtools.html +7 -7
- package/browser-extensions/chrome/devtools.js +19 -19
- package/browser-extensions/chrome/inspector.js +802 -767
- package/browser-extensions/chrome/manifest.json +71 -63
- package/browser-extensions/chrome/panel.html +674 -636
- package/browser-extensions/chrome/panel.js +722 -712
- package/browser-extensions/chrome/popup.html +586 -543
- package/browser-extensions/chrome/popup.js +282 -244
- package/browser-extensions/chrome/rules.json +1 -1
- package/browser-extensions/chrome/test-chrome.html +216 -136
- package/browser-extensions/chrome/test-mixed-content.html +284 -189
- package/browser-extensions/chrome/test-uri-pattern.html +221 -198
- package/browser-extensions/firefox/README.md +9 -6
- package/browser-extensions/firefox/background.js +221 -218
- package/browser-extensions/firefox/content.js +55 -52
- package/browser-extensions/firefox/debug-errors.html +386 -228
- package/browser-extensions/firefox/debug-https.html +153 -105
- package/browser-extensions/firefox/devtools.html +7 -7
- package/browser-extensions/firefox/devtools.js +23 -20
- package/browser-extensions/firefox/inspector.js +802 -767
- package/browser-extensions/firefox/manifest.json +68 -68
- package/browser-extensions/firefox/panel.html +674 -636
- package/browser-extensions/firefox/panel.js +722 -712
- package/browser-extensions/firefox/popup.html +572 -535
- package/browser-extensions/firefox/popup.js +281 -236
- package/browser-extensions/firefox/test-gramercy.html +170 -125
- package/browser-extensions/firefox/test-imports.html +59 -55
- package/browser-extensions/firefox/test-masking.html +231 -140
- package/browser-extensions/firefox/test-uri-pattern.html +221 -198
- package/dist/tui/App.d.ts +1 -1
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +154 -150
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/components/AIPanel.d.ts.map +1 -1
- package/dist/tui/components/AIPanel.js +42 -35
- package/dist/tui/components/AIPanel.js.map +1 -1
- package/dist/tui/components/CommandInput.d.ts +1 -1
- package/dist/tui/components/CommandInput.d.ts.map +1 -1
- package/dist/tui/components/CommandInput.js +92 -62
- package/dist/tui/components/CommandInput.js.map +1 -1
- package/dist/tui/components/GeminiPanel.d.ts.map +1 -1
- package/dist/tui/components/GeminiPanel.js +37 -30
- package/dist/tui/components/GeminiPanel.js.map +1 -1
- package/dist/tui/components/Header.d.ts.map +1 -1
- package/dist/tui/components/Header.js +1 -1
- package/dist/tui/components/Header.js.map +1 -1
- package/dist/tui/components/LogPanel.d.ts +1 -1
- package/dist/tui/components/LogPanel.d.ts.map +1 -1
- package/dist/tui/components/LogPanel.js +26 -24
- package/dist/tui/components/LogPanel.js.map +1 -1
- package/dist/tui/components/TabBar.d.ts +2 -2
- package/dist/tui/components/TabBar.d.ts.map +1 -1
- package/dist/tui/components/TabBar.js +11 -11
- package/dist/tui/components/TabBar.js.map +1 -1
- package/dist/tui/components/WelcomeScreen.d.ts.map +1 -1
- package/dist/tui/components/WelcomeScreen.js +6 -6
- package/dist/tui/components/WelcomeScreen.js.map +1 -1
- package/dist/tui/index.d.ts.map +1 -1
- package/dist/tui/index.js +8 -8
- package/dist/tui/index.js.map +1 -1
- package/dist/tui/services/AIService.d.ts +2 -2
- package/dist/tui/services/AIService.d.ts.map +1 -1
- package/dist/tui/services/AIService.js +165 -125
- package/dist/tui/services/AIService.js.map +1 -1
- package/dist/tui/services/ExtensionService.d.ts +1 -1
- package/dist/tui/services/ExtensionService.d.ts.map +1 -1
- package/dist/tui/services/ExtensionService.js +33 -26
- package/dist/tui/services/ExtensionService.js.map +1 -1
- package/dist/tui/services/GeminiService.d.ts +1 -1
- package/dist/tui/services/GeminiService.d.ts.map +1 -1
- package/dist/tui/services/GeminiService.js +87 -76
- package/dist/tui/services/GeminiService.js.map +1 -1
- package/dist/tui/services/ServiceManager.d.ts +3 -3
- package/dist/tui/services/ServiceManager.d.ts.map +1 -1
- package/dist/tui/services/ServiceManager.js +72 -58
- package/dist/tui/services/ServiceManager.js.map +1 -1
- package/dist/tui/services/SocketService.d.ts.map +1 -1
- package/dist/tui/services/SocketService.js +32 -32
- package/dist/tui/services/SocketService.js.map +1 -1
- package/dist/tui/services/ViteService.d.ts.map +1 -1
- package/dist/tui/services/ViteService.js +26 -28
- package/dist/tui/services/ViteService.js.map +1 -1
- package/dist/tui/services/index.d.ts +6 -6
- package/dist/tui/services/index.d.ts.map +1 -1
- package/dist/tui/services/index.js +6 -6
- package/dist/tui/services/index.js.map +1 -1
- package/mcp/gxp-api-server.js +83 -81
- package/package.json +109 -93
- package/runtime/PortalContainer.vue +258 -234
- package/runtime/dev-tools/DevToolsModal.vue +153 -155
- package/runtime/dev-tools/LayoutSwitcher.vue +144 -140
- package/runtime/dev-tools/MockDataEditor.vue +456 -433
- package/runtime/dev-tools/SocketSimulator.vue +379 -371
- package/runtime/dev-tools/StoreInspector.vue +517 -455
- package/runtime/dev-tools/index.js +5 -5
- package/runtime/fallback-layouts/PrivateLayout.vue +2 -2
- package/runtime/fallback-layouts/PublicLayout.vue +2 -2
- package/runtime/fallback-layouts/SystemLayout.vue +2 -2
- package/runtime/gxpStringsPlugin.js +159 -134
- package/runtime/index.html +17 -19
- package/runtime/main.js +24 -22
- package/runtime/mock-api/auth-middleware.js +15 -15
- package/runtime/mock-api/image-generator.js +46 -46
- package/runtime/mock-api/index.js +55 -55
- package/runtime/mock-api/response-generator.js +116 -105
- package/runtime/mock-api/route-generator.js +107 -84
- package/runtime/mock-api/socket-triggers.js +94 -93
- package/runtime/mock-api/spec-loader.js +79 -80
- package/runtime/package.json +3 -0
- package/runtime/server.js +68 -68
- package/runtime/stores/gxpPortalConfigStore.js +204 -186
- package/runtime/stores/index.js +2 -2
- package/runtime/vite-inspector-plugin.js +858 -707
- package/runtime/vite-source-tracker-plugin.js +132 -113
- package/runtime/vite.config.js +191 -139
- package/scripts/launch-chrome.js +41 -41
- package/scripts/pack-chrome.js +38 -39
- package/socket-events/AiSessionMessageCreated.json +17 -17
- package/socket-events/SocialStreamPostCreated.json +23 -23
- package/socket-events/SocialStreamPostVariantCompleted.json +22 -22
- package/template/.claude/agents/gxp-developer.md +100 -99
- package/template/.claude/settings.json +7 -7
- package/template/AGENTS.md +30 -23
- package/template/GEMINI.md +20 -20
- package/template/README.md +70 -53
- package/template/app-manifest.json +2 -4
- package/template/configuration.json +10 -10
- package/template/default-styling.css +1 -1
- package/template/index.html +18 -20
- package/template/main.js +24 -22
- package/template/src/DemoPage.vue +415 -362
- package/template/src/Plugin.vue +76 -85
- package/template/src/stores/index.js +3 -3
- package/template/src/stores/test-data.json +164 -172
- package/template/theme-layouts/AdditionalStyling.css +50 -50
- package/template/theme-layouts/PrivateLayout.vue +8 -12
- package/template/theme-layouts/PublicLayout.vue +8 -12
- package/template/theme-layouts/SystemLayout.vue +8 -12
- package/template/vite.extend.js +45 -0
- package/template/vite.config.js +0 -409
|
@@ -25,17 +25,17 @@ let config = {
|
|
|
25
25
|
maskingMode: false,
|
|
26
26
|
clearCacheOnEnable: true,
|
|
27
27
|
disableCacheForRedirects: true,
|
|
28
|
-
}
|
|
28
|
+
}
|
|
29
29
|
|
|
30
|
-
let notificationTimeouts = new Map()
|
|
31
|
-
let cacheBlacklist = new Set()
|
|
30
|
+
let notificationTimeouts = new Map()
|
|
31
|
+
let cacheBlacklist = new Set()
|
|
32
32
|
|
|
33
33
|
// Initialize extension
|
|
34
|
-
chrome.runtime.onStartup.addListener(initializeExtension)
|
|
35
|
-
chrome.runtime.onInstalled.addListener(initializeExtension)
|
|
34
|
+
chrome.runtime.onStartup.addListener(initializeExtension)
|
|
35
|
+
chrome.runtime.onInstalled.addListener(initializeExtension)
|
|
36
36
|
|
|
37
37
|
async function initializeExtension() {
|
|
38
|
-
console.log("[JavaScript Proxy] Initializing extension...")
|
|
38
|
+
console.log("[JavaScript Proxy] Initializing extension...")
|
|
39
39
|
try {
|
|
40
40
|
// Load saved configuration
|
|
41
41
|
const defaultConfig = {
|
|
@@ -66,22 +66,22 @@ async function initializeExtension() {
|
|
|
66
66
|
maskingMode: false,
|
|
67
67
|
clearCacheOnEnable: true,
|
|
68
68
|
disableCacheForRedirects: true,
|
|
69
|
-
}
|
|
69
|
+
}
|
|
70
70
|
|
|
71
|
-
const result = await chrome.storage.sync.get(defaultConfig)
|
|
72
|
-
config = result
|
|
71
|
+
const result = await chrome.storage.sync.get(defaultConfig)
|
|
72
|
+
config = result
|
|
73
73
|
|
|
74
74
|
// Migrate legacy configuration to new rules format
|
|
75
|
-
config = migrateConfig(config)
|
|
75
|
+
config = migrateConfig(config)
|
|
76
76
|
|
|
77
|
-
console.log("[JavaScript Proxy] Loaded configuration:", config)
|
|
77
|
+
console.log("[JavaScript Proxy] Loaded configuration:", config)
|
|
78
78
|
|
|
79
|
-
updateIcon()
|
|
80
|
-
updateRequestListener()
|
|
79
|
+
updateIcon()
|
|
80
|
+
updateRequestListener()
|
|
81
81
|
|
|
82
|
-
console.log("[JavaScript Proxy] Extension initialized successfully")
|
|
82
|
+
console.log("[JavaScript Proxy] Extension initialized successfully")
|
|
83
83
|
} catch (error) {
|
|
84
|
-
console.error("[JavaScript Proxy] Failed to initialize:", error)
|
|
84
|
+
console.error("[JavaScript Proxy] Failed to initialize:", error)
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
|
|
@@ -107,7 +107,7 @@ function migrateConfig(config) {
|
|
|
107
107
|
returnBlank: false,
|
|
108
108
|
useCustomPattern: false,
|
|
109
109
|
},
|
|
110
|
-
}
|
|
110
|
+
}
|
|
111
111
|
} else {
|
|
112
112
|
// Ensure all required fields exist
|
|
113
113
|
if (!config.rules.js) {
|
|
@@ -119,7 +119,7 @@ function migrateConfig(config) {
|
|
|
119
119
|
redirectUrl:
|
|
120
120
|
config.redirectUrl || "https://localhost:3060/src/Plugin.vue",
|
|
121
121
|
useCustomPattern: config.useCustomPattern || false,
|
|
122
|
-
}
|
|
122
|
+
}
|
|
123
123
|
}
|
|
124
124
|
if (!config.rules.css) {
|
|
125
125
|
config.rules.css = {
|
|
@@ -129,16 +129,16 @@ function migrateConfig(config) {
|
|
|
129
129
|
redirectUrl: "",
|
|
130
130
|
returnBlank: true,
|
|
131
131
|
useCustomPattern: false,
|
|
132
|
-
}
|
|
132
|
+
}
|
|
133
133
|
}
|
|
134
134
|
}
|
|
135
135
|
|
|
136
|
-
return config
|
|
136
|
+
return config
|
|
137
137
|
}
|
|
138
138
|
|
|
139
139
|
// Update toolbar icon based on state
|
|
140
140
|
function updateIcon() {
|
|
141
|
-
const iconPath = config.enabled ? "icons/gx_on" : "icons/gx_off"
|
|
141
|
+
const iconPath = config.enabled ? "icons/gx_on" : "icons/gx_off"
|
|
142
142
|
chrome.action.setIcon({
|
|
143
143
|
path: {
|
|
144
144
|
16: `${iconPath}_16.png`,
|
|
@@ -146,39 +146,39 @@ function updateIcon() {
|
|
|
146
146
|
64: `${iconPath}_64.png`,
|
|
147
147
|
128: `${iconPath}_128.png`,
|
|
148
148
|
},
|
|
149
|
-
})
|
|
149
|
+
})
|
|
150
150
|
|
|
151
151
|
const title = config.enabled
|
|
152
152
|
? "JavaScript Proxy (ON)"
|
|
153
|
-
: "JavaScript Proxy (OFF)"
|
|
154
|
-
chrome.action.setTitle({ title })
|
|
153
|
+
: "JavaScript Proxy (OFF)"
|
|
154
|
+
chrome.action.setTitle({ title })
|
|
155
155
|
}
|
|
156
156
|
|
|
157
157
|
// Cache management functions
|
|
158
158
|
async function clearCacheForPattern(urlPattern) {
|
|
159
159
|
try {
|
|
160
|
-
console.log(`[JavaScript Proxy] Clearing cache for pattern: ${urlPattern}`)
|
|
160
|
+
console.log(`[JavaScript Proxy] Clearing cache for pattern: ${urlPattern}`)
|
|
161
161
|
|
|
162
162
|
// Clear browser cache
|
|
163
163
|
await chrome.browsingData.removeCache({
|
|
164
164
|
origins: [], // Empty array means all origins
|
|
165
165
|
since: 0, // Clear all cache entries
|
|
166
|
-
})
|
|
166
|
+
})
|
|
167
167
|
|
|
168
168
|
// Clear service worker caches by injecting script into active tabs
|
|
169
|
-
await clearServiceWorkerCaches(urlPattern)
|
|
169
|
+
await clearServiceWorkerCaches(urlPattern)
|
|
170
170
|
|
|
171
|
-
console.log("[JavaScript Proxy] Cache cleared successfully")
|
|
171
|
+
console.log("[JavaScript Proxy] Cache cleared successfully")
|
|
172
172
|
} catch (error) {
|
|
173
|
-
console.error("[JavaScript Proxy] Error clearing cache:", error)
|
|
174
|
-
throw error
|
|
173
|
+
console.error("[JavaScript Proxy] Error clearing cache:", error)
|
|
174
|
+
throw error // Re-throw to let the caller handle the error
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
177
|
|
|
178
178
|
async function clearServiceWorkerCaches(urlPattern) {
|
|
179
179
|
try {
|
|
180
180
|
// Get all active tabs
|
|
181
|
-
const tabs = await chrome.tabs.query({})
|
|
181
|
+
const tabs = await chrome.tabs.query({})
|
|
182
182
|
|
|
183
183
|
// Inject the script into each tab
|
|
184
184
|
for (const tab of tabs) {
|
|
@@ -193,20 +193,20 @@ async function clearServiceWorkerCaches(urlPattern) {
|
|
|
193
193
|
func: async function (pattern) {
|
|
194
194
|
try {
|
|
195
195
|
if ("caches" in window) {
|
|
196
|
-
const cacheNames = await caches.keys()
|
|
197
|
-
const regex = new RegExp(pattern, "i")
|
|
196
|
+
const cacheNames = await caches.keys()
|
|
197
|
+
const regex = new RegExp(pattern, "i")
|
|
198
198
|
|
|
199
199
|
for (const cacheName of cacheNames) {
|
|
200
|
-
const cache = await caches.open(cacheName)
|
|
201
|
-
const requests = await cache.keys()
|
|
200
|
+
const cache = await caches.open(cacheName)
|
|
201
|
+
const requests = await cache.keys()
|
|
202
202
|
|
|
203
203
|
for (const request of requests) {
|
|
204
204
|
if (regex.test(request.url)) {
|
|
205
|
-
await cache.delete(request)
|
|
205
|
+
await cache.delete(request)
|
|
206
206
|
console.log(
|
|
207
207
|
"[JavaScript Proxy] Deleted from cache:",
|
|
208
|
-
request.url
|
|
209
|
-
)
|
|
208
|
+
request.url,
|
|
209
|
+
)
|
|
210
210
|
}
|
|
211
211
|
}
|
|
212
212
|
}
|
|
@@ -219,77 +219,77 @@ async function clearServiceWorkerCaches(urlPattern) {
|
|
|
219
219
|
navigator.serviceWorker.controller.postMessage({
|
|
220
220
|
type: "CLEAR_CACHE_FOR_PATTERN",
|
|
221
221
|
pattern: pattern,
|
|
222
|
-
})
|
|
222
|
+
})
|
|
223
223
|
}
|
|
224
224
|
}
|
|
225
225
|
} catch (error) {
|
|
226
226
|
console.error(
|
|
227
227
|
"[JavaScript Proxy] Error clearing service worker cache:",
|
|
228
|
-
error
|
|
229
|
-
)
|
|
228
|
+
error,
|
|
229
|
+
)
|
|
230
230
|
}
|
|
231
231
|
},
|
|
232
232
|
args: [urlPattern.replace(/\\/g, "\\\\")],
|
|
233
|
-
})
|
|
233
|
+
})
|
|
234
234
|
}
|
|
235
235
|
} catch (error) {
|
|
236
236
|
// Tab might not allow script injection, continue with others
|
|
237
237
|
console.debug(
|
|
238
238
|
`[JavaScript Proxy] Could not inject cache clear script into tab ${tab.id}:`,
|
|
239
|
-
error
|
|
240
|
-
)
|
|
239
|
+
error,
|
|
240
|
+
)
|
|
241
241
|
}
|
|
242
242
|
}
|
|
243
243
|
|
|
244
|
-
console.log("[JavaScript Proxy] Service worker cache clearing attempted")
|
|
244
|
+
console.log("[JavaScript Proxy] Service worker cache clearing attempted")
|
|
245
245
|
} catch (error) {
|
|
246
246
|
console.error(
|
|
247
247
|
"[JavaScript Proxy] Error clearing service worker caches:",
|
|
248
|
-
error
|
|
249
|
-
)
|
|
248
|
+
error,
|
|
249
|
+
)
|
|
250
250
|
}
|
|
251
251
|
}
|
|
252
252
|
|
|
253
253
|
async function addToCacheBlacklist(url) {
|
|
254
254
|
try {
|
|
255
|
-
const urlObj = new URL(url)
|
|
256
|
-
const origin = urlObj.origin
|
|
257
|
-
cacheBlacklist.add(origin)
|
|
258
|
-
console.log(`[JavaScript Proxy] Added ${origin} to cache blacklist`)
|
|
255
|
+
const urlObj = new URL(url)
|
|
256
|
+
const origin = urlObj.origin
|
|
257
|
+
cacheBlacklist.add(origin)
|
|
258
|
+
console.log(`[JavaScript Proxy] Added ${origin} to cache blacklist`)
|
|
259
259
|
} catch (error) {
|
|
260
|
-
console.error("[JavaScript Proxy] Error adding to cache blacklist:", error)
|
|
260
|
+
console.error("[JavaScript Proxy] Error adding to cache blacklist:", error)
|
|
261
261
|
}
|
|
262
262
|
}
|
|
263
263
|
|
|
264
264
|
function shouldDisableCache(url) {
|
|
265
|
-
if (!config.disableCacheForRedirects) return false
|
|
265
|
+
if (!config.disableCacheForRedirects) return false
|
|
266
266
|
|
|
267
267
|
try {
|
|
268
268
|
// Check against all enabled rules
|
|
269
269
|
for (const [ruleType, rule] of Object.entries(config.rules || {})) {
|
|
270
270
|
if (rule.enabled) {
|
|
271
271
|
const pattern =
|
|
272
|
-
rule.useCustomPattern && rule.pattern ? rule.pattern : rule.pattern
|
|
273
|
-
const regex = new RegExp(pattern, "i")
|
|
272
|
+
rule.useCustomPattern && rule.pattern ? rule.pattern : rule.pattern
|
|
273
|
+
const regex = new RegExp(pattern, "i")
|
|
274
274
|
if (regex.test(url)) {
|
|
275
|
-
return true
|
|
275
|
+
return true
|
|
276
276
|
}
|
|
277
277
|
}
|
|
278
278
|
}
|
|
279
279
|
|
|
280
280
|
// Fallback to legacy pattern for backward compatibility
|
|
281
281
|
if (config.urlPattern) {
|
|
282
|
-
const regex = new RegExp(config.urlPattern, "i")
|
|
283
|
-
return regex.test(url)
|
|
282
|
+
const regex = new RegExp(config.urlPattern, "i")
|
|
283
|
+
return regex.test(url)
|
|
284
284
|
}
|
|
285
285
|
|
|
286
|
-
return false
|
|
286
|
+
return false
|
|
287
287
|
} catch (error) {
|
|
288
288
|
console.error(
|
|
289
289
|
"[JavaScript Proxy] Error checking cache disable pattern:",
|
|
290
|
-
error
|
|
291
|
-
)
|
|
292
|
-
return false
|
|
290
|
+
error,
|
|
291
|
+
)
|
|
292
|
+
return false
|
|
293
293
|
}
|
|
294
294
|
}
|
|
295
295
|
|
|
@@ -299,27 +299,27 @@ async function updateRequestListener() {
|
|
|
299
299
|
try {
|
|
300
300
|
await chrome.declarativeNetRequest.updateDynamicRules({
|
|
301
301
|
removeRuleIds: [1, 2, 3, 4, 5], // Remove up to 5 rules
|
|
302
|
-
})
|
|
302
|
+
})
|
|
303
303
|
} catch (error) {
|
|
304
304
|
// Rules might not exist, that's fine
|
|
305
305
|
}
|
|
306
306
|
|
|
307
307
|
if (config.enabled && !config.maskingMode) {
|
|
308
|
-
const rulesToAdd = []
|
|
309
|
-
let ruleId = 1
|
|
308
|
+
const rulesToAdd = []
|
|
309
|
+
let ruleId = 1
|
|
310
310
|
|
|
311
311
|
// Process each rule type
|
|
312
312
|
for (const [ruleType, rule] of Object.entries(config.rules || {})) {
|
|
313
313
|
if (rule.enabled && rule.pattern) {
|
|
314
314
|
if (rule.returnBlank) {
|
|
315
315
|
// For blank returns, we'll handle in webRequest (can't return blank with declarativeNetRequest)
|
|
316
|
-
continue
|
|
316
|
+
continue
|
|
317
317
|
}
|
|
318
318
|
|
|
319
319
|
if (rule.redirectUrl) {
|
|
320
320
|
// Clear cache if enabled
|
|
321
321
|
if (config.clearCacheOnEnable) {
|
|
322
|
-
await clearCacheForPattern(rule.pattern)
|
|
322
|
+
await clearCacheForPattern(rule.pattern)
|
|
323
323
|
}
|
|
324
324
|
|
|
325
325
|
// Add redirect rule using declarativeNetRequest
|
|
@@ -336,9 +336,9 @@ async function updateRequestListener() {
|
|
|
336
336
|
regexFilter: rule.pattern,
|
|
337
337
|
resourceTypes: ruleType === "js" ? ["script"] : ["stylesheet"],
|
|
338
338
|
},
|
|
339
|
-
}
|
|
339
|
+
}
|
|
340
340
|
|
|
341
|
-
rulesToAdd.push(redirectRule)
|
|
341
|
+
rulesToAdd.push(redirectRule)
|
|
342
342
|
}
|
|
343
343
|
}
|
|
344
344
|
}
|
|
@@ -346,7 +346,7 @@ async function updateRequestListener() {
|
|
|
346
346
|
// Add legacy rule for backward compatibility
|
|
347
347
|
if (config.urlPattern && config.redirectUrl && rulesToAdd.length === 0) {
|
|
348
348
|
if (config.clearCacheOnEnable) {
|
|
349
|
-
await clearCacheForPattern(config.urlPattern)
|
|
349
|
+
await clearCacheForPattern(config.urlPattern)
|
|
350
350
|
}
|
|
351
351
|
|
|
352
352
|
const legacyRule = {
|
|
@@ -362,30 +362,30 @@ async function updateRequestListener() {
|
|
|
362
362
|
regexFilter: config.urlPattern,
|
|
363
363
|
resourceTypes: ["script"],
|
|
364
364
|
},
|
|
365
|
-
}
|
|
365
|
+
}
|
|
366
366
|
|
|
367
|
-
rulesToAdd.push(legacyRule)
|
|
367
|
+
rulesToAdd.push(legacyRule)
|
|
368
368
|
}
|
|
369
369
|
|
|
370
370
|
if (rulesToAdd.length > 0) {
|
|
371
371
|
try {
|
|
372
372
|
await chrome.declarativeNetRequest.updateDynamicRules({
|
|
373
373
|
addRules: rulesToAdd,
|
|
374
|
-
})
|
|
375
|
-
console.log("[JavaScript Proxy] Added redirect rules:", rulesToAdd)
|
|
374
|
+
})
|
|
375
|
+
console.log("[JavaScript Proxy] Added redirect rules:", rulesToAdd)
|
|
376
376
|
} catch (error) {
|
|
377
|
-
console.error("[JavaScript Proxy] Error adding redirect rules:", error)
|
|
377
|
+
console.error("[JavaScript Proxy] Error adding redirect rules:", error)
|
|
378
378
|
}
|
|
379
379
|
}
|
|
380
380
|
}
|
|
381
381
|
|
|
382
382
|
// For masking mode or blank returns, we need webRequest API
|
|
383
|
-
updateWebRequestListener()
|
|
383
|
+
updateWebRequestListener()
|
|
384
384
|
}
|
|
385
385
|
|
|
386
386
|
// Handle web requests for masking mode and blank returns (fallback to webRequest for complex logic)
|
|
387
387
|
function handleRequest(details) {
|
|
388
|
-
if (!config.enabled) return {}
|
|
388
|
+
if (!config.enabled) return {}
|
|
389
389
|
|
|
390
390
|
// Skip data URLs and blob URLs
|
|
391
391
|
if (
|
|
@@ -394,61 +394,61 @@ function handleRequest(details) {
|
|
|
394
394
|
details.url.startsWith("chrome:") ||
|
|
395
395
|
details.url.startsWith("chrome-extension:")
|
|
396
396
|
) {
|
|
397
|
-
return {}
|
|
397
|
+
return {}
|
|
398
398
|
}
|
|
399
399
|
|
|
400
400
|
try {
|
|
401
401
|
// Check each rule type
|
|
402
402
|
for (const [ruleType, rule] of Object.entries(config.rules || {})) {
|
|
403
|
-
if (!rule.enabled || !rule.pattern) continue
|
|
403
|
+
if (!rule.enabled || !rule.pattern) continue
|
|
404
404
|
|
|
405
405
|
// Check if this rule type matches the resource type
|
|
406
|
-
if (ruleType === "js" && details.type !== "script") continue
|
|
407
|
-
if (ruleType === "css" && details.type !== "stylesheet") continue
|
|
406
|
+
if (ruleType === "js" && details.type !== "script") continue
|
|
407
|
+
if (ruleType === "css" && details.type !== "stylesheet") continue
|
|
408
408
|
|
|
409
|
-
const regex = new RegExp(rule.pattern, "i")
|
|
409
|
+
const regex = new RegExp(rule.pattern, "i")
|
|
410
410
|
|
|
411
411
|
// Test the full URL against the pattern
|
|
412
412
|
if (regex.test(details.url)) {
|
|
413
413
|
// Handle blank return for CSS
|
|
414
414
|
if (rule.returnBlank) {
|
|
415
415
|
console.log(
|
|
416
|
-
`[JavaScript Proxy] Returning blank for ${ruleType}: ${details.url}
|
|
417
|
-
)
|
|
416
|
+
`[JavaScript Proxy] Returning blank for ${ruleType}: ${details.url}`,
|
|
417
|
+
)
|
|
418
418
|
// Return a data URL with empty content
|
|
419
419
|
const blankUrl =
|
|
420
420
|
ruleType === "css"
|
|
421
421
|
? "data:text/css;charset=utf-8,"
|
|
422
|
-
: "data:text/javascript;charset=utf-8,"
|
|
423
|
-
return { redirectUrl: blankUrl }
|
|
422
|
+
: "data:text/javascript;charset=utf-8,"
|
|
423
|
+
return { redirectUrl: blankUrl }
|
|
424
424
|
}
|
|
425
425
|
|
|
426
426
|
// Handle masking mode or rules without declarativeNetRequest redirect
|
|
427
427
|
if (config.maskingMode || !rule.redirectUrl) {
|
|
428
428
|
if (rule.redirectUrl) {
|
|
429
|
-
let newUrl = rule.redirectUrl
|
|
429
|
+
let newUrl = rule.redirectUrl
|
|
430
430
|
|
|
431
431
|
// Ensure URL has protocol
|
|
432
432
|
if (!newUrl.includes("://")) {
|
|
433
|
-
newUrl = "https://" + newUrl
|
|
433
|
+
newUrl = "https://" + newUrl
|
|
434
434
|
}
|
|
435
435
|
|
|
436
436
|
// Check if this would create a redirect loop
|
|
437
437
|
if (details.url === newUrl || details.url.includes("localhost")) {
|
|
438
438
|
console.log(
|
|
439
|
-
`[JavaScript Proxy] Skipping redirect loop: ${details.url}
|
|
440
|
-
)
|
|
441
|
-
return {}
|
|
439
|
+
`[JavaScript Proxy] Skipping redirect loop: ${details.url}`,
|
|
440
|
+
)
|
|
441
|
+
return {}
|
|
442
442
|
}
|
|
443
443
|
|
|
444
444
|
// Store original URL for header modification
|
|
445
|
-
storeOriginalUrl(details.requestId, details.url, newUrl)
|
|
445
|
+
storeOriginalUrl(details.requestId, details.url, newUrl)
|
|
446
446
|
|
|
447
447
|
console.log(
|
|
448
|
-
`[JavaScript Proxy] Masking ${ruleType}: ${details.url} (routing to ${newUrl})
|
|
449
|
-
)
|
|
448
|
+
`[JavaScript Proxy] Masking ${ruleType}: ${details.url} (routing to ${newUrl})`,
|
|
449
|
+
)
|
|
450
450
|
|
|
451
|
-
return { redirectUrl: newUrl }
|
|
451
|
+
return { redirectUrl: newUrl }
|
|
452
452
|
}
|
|
453
453
|
}
|
|
454
454
|
}
|
|
@@ -456,52 +456,52 @@ function handleRequest(details) {
|
|
|
456
456
|
|
|
457
457
|
// Fallback to legacy pattern for backward compatibility
|
|
458
458
|
if (config.maskingMode && config.urlPattern) {
|
|
459
|
-
const regex = new RegExp(config.urlPattern, "i")
|
|
459
|
+
const regex = new RegExp(config.urlPattern, "i")
|
|
460
460
|
|
|
461
461
|
if (regex.test(details.url) && details.type === "script") {
|
|
462
|
-
let newUrl = config.redirectUrl
|
|
462
|
+
let newUrl = config.redirectUrl
|
|
463
463
|
|
|
464
464
|
if (!newUrl.includes("://")) {
|
|
465
|
-
newUrl = "https://" + newUrl
|
|
465
|
+
newUrl = "https://" + newUrl
|
|
466
466
|
}
|
|
467
467
|
|
|
468
468
|
if (details.url === newUrl || details.url.includes("localhost")) {
|
|
469
469
|
console.log(
|
|
470
|
-
`[JavaScript Proxy] Skipping redirect loop: ${details.url}
|
|
471
|
-
)
|
|
472
|
-
return {}
|
|
470
|
+
`[JavaScript Proxy] Skipping redirect loop: ${details.url}`,
|
|
471
|
+
)
|
|
472
|
+
return {}
|
|
473
473
|
}
|
|
474
474
|
|
|
475
|
-
storeOriginalUrl(details.requestId, details.url, newUrl)
|
|
475
|
+
storeOriginalUrl(details.requestId, details.url, newUrl)
|
|
476
476
|
|
|
477
477
|
console.log(
|
|
478
|
-
`[JavaScript Proxy] Legacy masking: ${details.url} (routing to ${newUrl})
|
|
479
|
-
)
|
|
478
|
+
`[JavaScript Proxy] Legacy masking: ${details.url} (routing to ${newUrl})`,
|
|
479
|
+
)
|
|
480
480
|
|
|
481
|
-
return { redirectUrl: newUrl }
|
|
481
|
+
return { redirectUrl: newUrl }
|
|
482
482
|
}
|
|
483
483
|
}
|
|
484
484
|
} catch (error) {
|
|
485
|
-
console.error("[JavaScript Proxy] Error processing request:", error)
|
|
485
|
+
console.error("[JavaScript Proxy] Error processing request:", error)
|
|
486
486
|
}
|
|
487
487
|
|
|
488
|
-
return {}
|
|
488
|
+
return {}
|
|
489
489
|
}
|
|
490
490
|
|
|
491
491
|
// Store mapping of request IDs to proxy info for header modification
|
|
492
|
-
const pendingProxyRequests = new Map()
|
|
492
|
+
const pendingProxyRequests = new Map()
|
|
493
493
|
|
|
494
494
|
function storeOriginalUrl(requestId, originalUrl, redirectUrl) {
|
|
495
495
|
pendingProxyRequests.set(requestId, {
|
|
496
496
|
originalUrl,
|
|
497
497
|
redirectUrl,
|
|
498
498
|
timestamp: Date.now(),
|
|
499
|
-
})
|
|
499
|
+
})
|
|
500
500
|
|
|
501
501
|
// Clean up old entries after 30 seconds
|
|
502
502
|
setTimeout(() => {
|
|
503
|
-
pendingProxyRequests.delete(requestId)
|
|
504
|
-
}, 30000)
|
|
503
|
+
pendingProxyRequests.delete(requestId)
|
|
504
|
+
}, 30000)
|
|
505
505
|
}
|
|
506
506
|
|
|
507
507
|
// Update webRequest listener for masking mode
|
|
@@ -511,19 +511,19 @@ function updateWebRequestListener() {
|
|
|
511
511
|
chrome.webRequest &&
|
|
512
512
|
chrome.webRequest.onBeforeRequest.hasListener(handleRequest)
|
|
513
513
|
) {
|
|
514
|
-
chrome.webRequest.onBeforeRequest.removeListener(handleRequest)
|
|
514
|
+
chrome.webRequest.onBeforeRequest.removeListener(handleRequest)
|
|
515
515
|
}
|
|
516
516
|
if (
|
|
517
517
|
chrome.webRequest &&
|
|
518
518
|
chrome.webRequest.onBeforeSendHeaders.hasListener(handleRequestHeaders)
|
|
519
519
|
) {
|
|
520
|
-
chrome.webRequest.onBeforeSendHeaders.removeListener(handleRequestHeaders)
|
|
520
|
+
chrome.webRequest.onBeforeSendHeaders.removeListener(handleRequestHeaders)
|
|
521
521
|
}
|
|
522
522
|
if (
|
|
523
523
|
chrome.webRequest &&
|
|
524
524
|
chrome.webRequest.onHeadersReceived.hasListener(handleResponseHeaders)
|
|
525
525
|
) {
|
|
526
|
-
chrome.webRequest.onHeadersReceived.removeListener(handleResponseHeaders)
|
|
526
|
+
chrome.webRequest.onHeadersReceived.removeListener(handleResponseHeaders)
|
|
527
527
|
}
|
|
528
528
|
|
|
529
529
|
// Check if we need webRequest for any features
|
|
@@ -531,60 +531,60 @@ function updateWebRequestListener() {
|
|
|
531
531
|
config.maskingMode ||
|
|
532
532
|
config.disableCacheForRedirects ||
|
|
533
533
|
Object.values(config.rules || {}).some(
|
|
534
|
-
(rule) => rule.enabled && rule.returnBlank
|
|
535
|
-
)
|
|
534
|
+
(rule) => rule.enabled && rule.returnBlank,
|
|
535
|
+
)
|
|
536
536
|
|
|
537
537
|
// Add webRequest listeners for masking mode, cache control, or blank returns
|
|
538
538
|
if (config.enabled && chrome.webRequest && needsWebRequest) {
|
|
539
539
|
chrome.webRequest.onBeforeRequest.addListener(
|
|
540
540
|
handleRequest,
|
|
541
541
|
{ urls: ["<all_urls>"] },
|
|
542
|
-
["blocking"]
|
|
543
|
-
)
|
|
542
|
+
["blocking"],
|
|
543
|
+
)
|
|
544
544
|
|
|
545
545
|
chrome.webRequest.onBeforeSendHeaders.addListener(
|
|
546
546
|
handleRequestHeaders,
|
|
547
547
|
{ urls: ["<all_urls>"] },
|
|
548
|
-
["blocking", "requestHeaders"]
|
|
549
|
-
)
|
|
548
|
+
["blocking", "requestHeaders"],
|
|
549
|
+
)
|
|
550
550
|
|
|
551
551
|
chrome.webRequest.onHeadersReceived.addListener(
|
|
552
552
|
handleResponseHeaders,
|
|
553
553
|
{ urls: ["<all_urls>"] },
|
|
554
|
-
["blocking", "responseHeaders"]
|
|
555
|
-
)
|
|
554
|
+
["blocking", "responseHeaders"],
|
|
555
|
+
)
|
|
556
556
|
|
|
557
557
|
console.log(
|
|
558
|
-
"[JavaScript Proxy] WebRequest listeners enabled for masking mode"
|
|
559
|
-
)
|
|
558
|
+
"[JavaScript Proxy] WebRequest listeners enabled for masking mode",
|
|
559
|
+
)
|
|
560
560
|
} else {
|
|
561
|
-
console.log("[JavaScript Proxy] WebRequest listeners disabled")
|
|
561
|
+
console.log("[JavaScript Proxy] WebRequest listeners disabled")
|
|
562
562
|
}
|
|
563
563
|
}
|
|
564
564
|
|
|
565
565
|
// Handle request headers for masking mode and cache control
|
|
566
566
|
function handleRequestHeaders(details) {
|
|
567
|
-
if (!config.enabled) return {}
|
|
567
|
+
if (!config.enabled) return {}
|
|
568
568
|
|
|
569
569
|
// Initialize modifications
|
|
570
|
-
const modifications = { requestHeaders: details.requestHeaders }
|
|
571
|
-
let hasModifications = false
|
|
570
|
+
const modifications = { requestHeaders: details.requestHeaders }
|
|
571
|
+
let hasModifications = false
|
|
572
572
|
|
|
573
573
|
// Handle masking mode
|
|
574
574
|
if (config.maskingMode) {
|
|
575
|
-
const proxyInfo = pendingProxyRequests.get(details.requestId)
|
|
575
|
+
const proxyInfo = pendingProxyRequests.get(details.requestId)
|
|
576
576
|
if (proxyInfo) {
|
|
577
577
|
// Add/modify headers to properly route to localhost
|
|
578
578
|
const hostHeader = modifications.requestHeaders.find(
|
|
579
|
-
(h) => h.name.toLowerCase() === "host"
|
|
580
|
-
)
|
|
579
|
+
(h) => h.name.toLowerCase() === "host",
|
|
580
|
+
)
|
|
581
581
|
if (hostHeader) {
|
|
582
582
|
try {
|
|
583
|
-
const proxyUrl = new URL(proxyInfo.redirectUrl)
|
|
584
|
-
hostHeader.value = proxyUrl.host
|
|
585
|
-
hasModifications = true
|
|
583
|
+
const proxyUrl = new URL(proxyInfo.redirectUrl)
|
|
584
|
+
hostHeader.value = proxyUrl.host
|
|
585
|
+
hasModifications = true
|
|
586
586
|
} catch (error) {
|
|
587
|
-
console.error("[JavaScript Proxy] Error parsing proxy URL:", error)
|
|
587
|
+
console.error("[JavaScript Proxy] Error parsing proxy URL:", error)
|
|
588
588
|
}
|
|
589
589
|
}
|
|
590
590
|
}
|
|
@@ -602,39 +602,39 @@ function handleRequestHeaders(details) {
|
|
|
602
602
|
{ name: "Expires", value: "0" },
|
|
603
603
|
{ name: "If-None-Match", value: "*" },
|
|
604
604
|
{ name: "If-Modified-Since", value: "Thu, 01 Jan 1970 00:00:00 GMT" },
|
|
605
|
-
]
|
|
605
|
+
]
|
|
606
606
|
|
|
607
607
|
cacheHeaders.forEach((cacheHeader) => {
|
|
608
608
|
const existingHeader = modifications.requestHeaders.find(
|
|
609
|
-
(h) => h.name.toLowerCase() === cacheHeader.name.toLowerCase()
|
|
610
|
-
)
|
|
609
|
+
(h) => h.name.toLowerCase() === cacheHeader.name.toLowerCase(),
|
|
610
|
+
)
|
|
611
611
|
if (existingHeader) {
|
|
612
|
-
existingHeader.value = cacheHeader.value
|
|
612
|
+
existingHeader.value = cacheHeader.value
|
|
613
613
|
} else {
|
|
614
|
-
modifications.requestHeaders.push(cacheHeader)
|
|
614
|
+
modifications.requestHeaders.push(cacheHeader)
|
|
615
615
|
}
|
|
616
|
-
hasModifications = true
|
|
617
|
-
})
|
|
616
|
+
hasModifications = true
|
|
617
|
+
})
|
|
618
618
|
|
|
619
619
|
console.log(
|
|
620
|
-
`[JavaScript Proxy] Added cache-busting headers for: ${details.url}
|
|
621
|
-
)
|
|
620
|
+
`[JavaScript Proxy] Added cache-busting headers for: ${details.url}`,
|
|
621
|
+
)
|
|
622
622
|
}
|
|
623
623
|
|
|
624
|
-
return hasModifications ? modifications : {}
|
|
624
|
+
return hasModifications ? modifications : {}
|
|
625
625
|
}
|
|
626
626
|
|
|
627
627
|
// Handle response headers for masking mode and cache control
|
|
628
628
|
function handleResponseHeaders(details) {
|
|
629
|
-
if (!config.enabled) return {}
|
|
629
|
+
if (!config.enabled) return {}
|
|
630
630
|
|
|
631
631
|
// Initialize modifications
|
|
632
|
-
const modifications = { responseHeaders: details.responseHeaders }
|
|
633
|
-
let hasModifications = false
|
|
632
|
+
const modifications = { responseHeaders: details.responseHeaders }
|
|
633
|
+
let hasModifications = false
|
|
634
634
|
|
|
635
635
|
// Handle masking mode
|
|
636
636
|
if (config.maskingMode) {
|
|
637
|
-
const proxyInfo = pendingProxyRequests.get(details.requestId)
|
|
637
|
+
const proxyInfo = pendingProxyRequests.get(details.requestId)
|
|
638
638
|
if (proxyInfo) {
|
|
639
639
|
// Add CORS headers if needed
|
|
640
640
|
const corsHeaders = [
|
|
@@ -647,19 +647,19 @@ function handleResponseHeaders(details) {
|
|
|
647
647
|
name: "Access-Control-Allow-Headers",
|
|
648
648
|
value: "Content-Type, Authorization",
|
|
649
649
|
},
|
|
650
|
-
]
|
|
650
|
+
]
|
|
651
651
|
|
|
652
652
|
corsHeaders.forEach((corsHeader) => {
|
|
653
653
|
const existingHeader = modifications.responseHeaders.find(
|
|
654
|
-
(h) => h.name.toLowerCase() === corsHeader.name.toLowerCase()
|
|
655
|
-
)
|
|
654
|
+
(h) => h.name.toLowerCase() === corsHeader.name.toLowerCase(),
|
|
655
|
+
)
|
|
656
656
|
if (existingHeader) {
|
|
657
|
-
existingHeader.value = corsHeader.value
|
|
657
|
+
existingHeader.value = corsHeader.value
|
|
658
658
|
} else {
|
|
659
|
-
modifications.responseHeaders.push(corsHeader)
|
|
659
|
+
modifications.responseHeaders.push(corsHeader)
|
|
660
660
|
}
|
|
661
|
-
hasModifications = true
|
|
662
|
-
})
|
|
661
|
+
hasModifications = true
|
|
662
|
+
})
|
|
663
663
|
}
|
|
664
664
|
}
|
|
665
665
|
|
|
@@ -677,197 +677,204 @@ function handleResponseHeaders(details) {
|
|
|
677
677
|
{ name: "ETag", value: `"${Date.now()}-${Math.random()}"` },
|
|
678
678
|
{ name: "Vary", value: "*" },
|
|
679
679
|
{ name: "X-Cache-Control", value: "no-cache" },
|
|
680
|
-
]
|
|
680
|
+
]
|
|
681
681
|
|
|
682
682
|
cacheHeaders.forEach((cacheHeader) => {
|
|
683
683
|
const existingHeader = modifications.responseHeaders.find(
|
|
684
|
-
(h) => h.name.toLowerCase() === cacheHeader.name.toLowerCase()
|
|
685
|
-
)
|
|
684
|
+
(h) => h.name.toLowerCase() === cacheHeader.name.toLowerCase(),
|
|
685
|
+
)
|
|
686
686
|
if (existingHeader) {
|
|
687
|
-
existingHeader.value = cacheHeader.value
|
|
687
|
+
existingHeader.value = cacheHeader.value
|
|
688
688
|
} else {
|
|
689
|
-
modifications.responseHeaders.push(cacheHeader)
|
|
689
|
+
modifications.responseHeaders.push(cacheHeader)
|
|
690
690
|
}
|
|
691
|
-
hasModifications = true
|
|
692
|
-
})
|
|
691
|
+
hasModifications = true
|
|
692
|
+
})
|
|
693
693
|
|
|
694
694
|
console.log(
|
|
695
|
-
`[JavaScript Proxy] Added response cache-busting headers for: ${details.url}
|
|
696
|
-
)
|
|
695
|
+
`[JavaScript Proxy] Added response cache-busting headers for: ${details.url}`,
|
|
696
|
+
)
|
|
697
697
|
}
|
|
698
698
|
|
|
699
699
|
if (hasModifications) {
|
|
700
700
|
console.log(
|
|
701
|
-
`[JavaScript Proxy] Modified response headers for: ${details.url}
|
|
702
|
-
)
|
|
701
|
+
`[JavaScript Proxy] Modified response headers for: ${details.url}`,
|
|
702
|
+
)
|
|
703
703
|
}
|
|
704
704
|
|
|
705
|
-
return hasModifications ? modifications : {}
|
|
705
|
+
return hasModifications ? modifications : {}
|
|
706
706
|
}
|
|
707
707
|
|
|
708
708
|
// Show desktop notification for proxy activity (when using masking mode)
|
|
709
709
|
function showProxyNotification(from, to, requestType = "") {
|
|
710
|
-
const shortFrom = from.length > 50 ? from.substring(0, 47) + "..." : from
|
|
711
|
-
const shortTo = to.length > 30 ? to.substring(0, 27) + "..." : to
|
|
710
|
+
const shortFrom = from.length > 50 ? from.substring(0, 47) + "..." : from
|
|
711
|
+
const shortTo = to.length > 30 ? to.substring(0, 27) + "..." : to
|
|
712
712
|
|
|
713
|
-
const notificationId = `proxy-${Date.now()}
|
|
713
|
+
const notificationId = `proxy-${Date.now()}`
|
|
714
714
|
|
|
715
715
|
chrome.notifications.create(notificationId, {
|
|
716
716
|
type: "basic",
|
|
717
717
|
iconUrl: "icons/gx_on_64.png",
|
|
718
718
|
title: "JavaScript Proxy Active",
|
|
719
719
|
message: `${requestType}\n${shortFrom}\n→ ${shortTo}`,
|
|
720
|
-
})
|
|
720
|
+
})
|
|
721
721
|
|
|
722
722
|
// Clear existing timeout for this type
|
|
723
723
|
if (notificationTimeouts.has("proxy")) {
|
|
724
|
-
clearTimeout(notificationTimeouts.get("proxy"))
|
|
724
|
+
clearTimeout(notificationTimeouts.get("proxy"))
|
|
725
725
|
}
|
|
726
726
|
|
|
727
727
|
// Auto-dismiss after 3 seconds
|
|
728
728
|
const timeoutId = setTimeout(() => {
|
|
729
|
-
chrome.notifications.clear(notificationId)
|
|
730
|
-
notificationTimeouts.delete("proxy")
|
|
731
|
-
}, 3000)
|
|
729
|
+
chrome.notifications.clear(notificationId)
|
|
730
|
+
notificationTimeouts.delete("proxy")
|
|
731
|
+
}, 3000)
|
|
732
732
|
|
|
733
|
-
notificationTimeouts.set("proxy", timeoutId)
|
|
733
|
+
notificationTimeouts.set("proxy", timeoutId)
|
|
734
734
|
}
|
|
735
735
|
|
|
736
736
|
// ============================================================
|
|
737
737
|
// DevTools Panel Communication
|
|
738
738
|
// ============================================================
|
|
739
739
|
|
|
740
|
-
const devtoolsConnections = new Map()
|
|
740
|
+
const devtoolsConnections = new Map()
|
|
741
741
|
|
|
742
742
|
chrome.runtime.onConnect.addListener((port) => {
|
|
743
|
-
if (port.name ===
|
|
743
|
+
if (port.name === "gxp-devtools-panel") {
|
|
744
744
|
const extensionListener = (message, port) => {
|
|
745
|
-
if (message.name ===
|
|
746
|
-
devtoolsConnections.set(message.tabId, port)
|
|
747
|
-
console.log(
|
|
745
|
+
if (message.name === "init") {
|
|
746
|
+
devtoolsConnections.set(message.tabId, port)
|
|
747
|
+
console.log("[GxP DevTools] Panel connected for tab:", message.tabId)
|
|
748
748
|
}
|
|
749
749
|
|
|
750
750
|
// Forward messages to content script
|
|
751
751
|
if (message.tabId && message.action) {
|
|
752
752
|
chrome.tabs.sendMessage(message.tabId, message, (response) => {
|
|
753
|
-
port.postMessage(response)
|
|
754
|
-
})
|
|
753
|
+
port.postMessage(response)
|
|
754
|
+
})
|
|
755
755
|
}
|
|
756
|
-
}
|
|
756
|
+
}
|
|
757
757
|
|
|
758
|
-
port.onMessage.addListener(extensionListener)
|
|
758
|
+
port.onMessage.addListener(extensionListener)
|
|
759
759
|
|
|
760
760
|
port.onDisconnect.addListener(() => {
|
|
761
761
|
// Remove the connection when panel is closed
|
|
762
762
|
for (const [tabId, connectedPort] of devtoolsConnections.entries()) {
|
|
763
763
|
if (connectedPort === port) {
|
|
764
|
-
devtoolsConnections.delete(tabId)
|
|
765
|
-
console.log(
|
|
766
|
-
break
|
|
764
|
+
devtoolsConnections.delete(tabId)
|
|
765
|
+
console.log("[GxP DevTools] Panel disconnected for tab:", tabId)
|
|
766
|
+
break
|
|
767
767
|
}
|
|
768
768
|
}
|
|
769
|
-
})
|
|
769
|
+
})
|
|
770
770
|
}
|
|
771
|
-
})
|
|
771
|
+
})
|
|
772
772
|
|
|
773
773
|
// Forward messages from content script to DevTools panel
|
|
774
774
|
function forwardToDevTools(tabId, message) {
|
|
775
|
-
const port = devtoolsConnections.get(tabId)
|
|
775
|
+
const port = devtoolsConnections.get(tabId)
|
|
776
776
|
if (port) {
|
|
777
777
|
try {
|
|
778
|
-
port.postMessage(message)
|
|
778
|
+
port.postMessage(message)
|
|
779
779
|
} catch (error) {
|
|
780
|
-
console.error(
|
|
780
|
+
console.error("[GxP DevTools] Error forwarding to panel:", error)
|
|
781
781
|
}
|
|
782
782
|
}
|
|
783
783
|
}
|
|
784
784
|
|
|
785
785
|
// Handle messages from popup
|
|
786
786
|
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
787
|
-
console.log("[JavaScript Proxy] Received message:", request)
|
|
787
|
+
console.log("[JavaScript Proxy] Received message:", request)
|
|
788
788
|
|
|
789
789
|
// Handle messages from content script about element selection
|
|
790
|
-
if (request.type ===
|
|
791
|
-
forwardToDevTools(sender.tab.id, request)
|
|
792
|
-
return
|
|
790
|
+
if (request.type === "elementSelected" && sender.tab) {
|
|
791
|
+
forwardToDevTools(sender.tab.id, request)
|
|
792
|
+
return
|
|
793
793
|
}
|
|
794
794
|
|
|
795
795
|
switch (request.action) {
|
|
796
796
|
case "toggleProxy":
|
|
797
|
-
config.enabled = request.enabled
|
|
798
|
-
chrome.storage.sync.set({ enabled: config.enabled })
|
|
799
|
-
updateIcon()
|
|
800
|
-
updateRequestListener()
|
|
797
|
+
config.enabled = request.enabled
|
|
798
|
+
chrome.storage.sync.set({ enabled: config.enabled })
|
|
799
|
+
updateIcon()
|
|
800
|
+
updateRequestListener()
|
|
801
801
|
// Clear cache when enabling the proxy
|
|
802
802
|
if (config.enabled && config.clearCacheOnEnable) {
|
|
803
|
-
clearCacheForPattern(config.urlPattern)
|
|
803
|
+
clearCacheForPattern(config.urlPattern)
|
|
804
804
|
}
|
|
805
|
-
sendResponse({ success: true, enabled: config.enabled })
|
|
806
|
-
return false
|
|
805
|
+
sendResponse({ success: true, enabled: config.enabled })
|
|
806
|
+
return false // Synchronous response
|
|
807
807
|
|
|
808
808
|
case "updateConfig":
|
|
809
|
-
config = { ...config, ...request.config }
|
|
810
|
-
chrome.storage.sync.set(config)
|
|
811
|
-
updateIcon()
|
|
812
|
-
updateRequestListener()
|
|
813
|
-
sendResponse({ success: true })
|
|
814
|
-
return false
|
|
809
|
+
config = { ...config, ...request.config }
|
|
810
|
+
chrome.storage.sync.set(config)
|
|
811
|
+
updateIcon()
|
|
812
|
+
updateRequestListener()
|
|
813
|
+
sendResponse({ success: true })
|
|
814
|
+
return false // Synchronous response
|
|
815
815
|
|
|
816
816
|
case "getConfig":
|
|
817
|
-
sendResponse(config)
|
|
818
|
-
return false
|
|
817
|
+
sendResponse(config)
|
|
818
|
+
return false // Synchronous response
|
|
819
819
|
|
|
820
820
|
case "clearCache":
|
|
821
821
|
console.log(
|
|
822
822
|
"[JavaScript Proxy] Starting cache clear for pattern:",
|
|
823
|
-
config.urlPattern
|
|
824
|
-
)
|
|
823
|
+
config.urlPattern,
|
|
824
|
+
)
|
|
825
825
|
clearCacheForPattern(config.urlPattern)
|
|
826
826
|
.then(() => {
|
|
827
|
-
console.log("[JavaScript Proxy] Cache clear completed successfully")
|
|
828
|
-
sendResponse({ success: true })
|
|
827
|
+
console.log("[JavaScript Proxy] Cache clear completed successfully")
|
|
828
|
+
sendResponse({ success: true })
|
|
829
829
|
})
|
|
830
830
|
.catch((error) => {
|
|
831
|
-
console.error("[JavaScript Proxy] Cache clear error:", error)
|
|
831
|
+
console.error("[JavaScript Proxy] Cache clear error:", error)
|
|
832
832
|
sendResponse({
|
|
833
833
|
success: false,
|
|
834
834
|
error: error.message || error.toString(),
|
|
835
|
-
})
|
|
836
|
-
})
|
|
837
|
-
return true
|
|
835
|
+
})
|
|
836
|
+
})
|
|
837
|
+
return true // Keep message channel open for async response
|
|
838
838
|
|
|
839
839
|
case "openDevTools":
|
|
840
840
|
// Open DevTools for the specified tab
|
|
841
841
|
// Note: Chrome doesn't have a direct API to open DevTools to a specific panel
|
|
842
842
|
// We inject a script that triggers the inspector and prompt user to open DevTools
|
|
843
843
|
if (request.tabId) {
|
|
844
|
-
chrome.scripting
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
844
|
+
chrome.scripting
|
|
845
|
+
.executeScript({
|
|
846
|
+
target: { tabId: request.tabId },
|
|
847
|
+
func: () => {
|
|
848
|
+
// Log a message suggesting to open DevTools
|
|
849
|
+
console.log(
|
|
850
|
+
"%c[GxP Inspector] Inspector enabled! Press F12 or Ctrl+Shift+J to open DevTools and see the GxP Inspector panel.",
|
|
851
|
+
"color: #667eea; font-weight: bold; font-size: 14px;",
|
|
852
|
+
)
|
|
853
|
+
},
|
|
854
|
+
})
|
|
855
|
+
.catch((err) =>
|
|
856
|
+
console.log("[GxP DevTools] Could not inject script:", err),
|
|
857
|
+
)
|
|
851
858
|
}
|
|
852
|
-
sendResponse({ success: true })
|
|
853
|
-
return false
|
|
859
|
+
sendResponse({ success: true })
|
|
860
|
+
return false
|
|
854
861
|
|
|
855
862
|
default:
|
|
856
|
-
console.warn("[JavaScript Proxy] Unknown action:", request.action)
|
|
857
|
-
sendResponse({ success: false, error: "Unknown action" })
|
|
858
|
-
return false
|
|
863
|
+
console.warn("[JavaScript Proxy] Unknown action:", request.action)
|
|
864
|
+
sendResponse({ success: false, error: "Unknown action" })
|
|
865
|
+
return false // Synchronous response
|
|
859
866
|
}
|
|
860
|
-
})
|
|
867
|
+
})
|
|
861
868
|
|
|
862
869
|
// Clear expired proxy requests periodically
|
|
863
870
|
setInterval(() => {
|
|
864
|
-
const now = Date.now()
|
|
871
|
+
const now = Date.now()
|
|
865
872
|
for (const [requestId, info] of pendingProxyRequests.entries()) {
|
|
866
873
|
if (now - info.timestamp > 30000) {
|
|
867
|
-
pendingProxyRequests.delete(requestId)
|
|
874
|
+
pendingProxyRequests.delete(requestId)
|
|
868
875
|
}
|
|
869
876
|
}
|
|
870
|
-
}, 10000)
|
|
877
|
+
}, 10000)
|
|
871
878
|
|
|
872
879
|
// Initialize on startup
|
|
873
|
-
initializeExtension()
|
|
880
|
+
initializeExtension()
|