@gxp-dev/tools 2.0.14 → 2.0.15
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/bin/lib/tui/App.tsx +24 -21
- package/browser-extensions/firefox/popup.html +478 -519
- package/browser-extensions/firefox/popup.js +444 -500
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +24 -22
- package/dist/tui/App.js.map +1 -1
- package/package.json +1 -1
|
@@ -1,555 +1,499 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
clearCacheOnEnable: envDefaults.clearCacheOnEnable !== false,
|
|
46
|
-
disableCacheForRedirects: envDefaults.disableCacheForRedirects !== false,
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
// Global state
|
|
50
|
-
let config = { ...DEFAULT_CONFIG };
|
|
51
|
-
let pendingChanges = false;
|
|
52
|
-
|
|
53
|
-
// DOM elements
|
|
54
|
-
const elements = {
|
|
55
|
-
// Status and main toggle
|
|
56
|
-
statusMessage: null,
|
|
57
|
-
masterToggle: null,
|
|
58
|
-
statusInfo: null,
|
|
59
|
-
|
|
60
|
-
// JavaScript rule elements
|
|
61
|
-
jsRuleContainer: null,
|
|
62
|
-
jsRuleToggle: null,
|
|
63
|
-
jsRedirectUrl: null,
|
|
64
|
-
jsUseCustomPattern: null,
|
|
65
|
-
jsPattern: null,
|
|
66
|
-
jsPatternGroup: null,
|
|
67
|
-
|
|
68
|
-
// CSS rule elements
|
|
69
|
-
cssRuleContainer: null,
|
|
70
|
-
cssRuleToggle: null,
|
|
71
|
-
cssRedirectUrl: null,
|
|
72
|
-
cssReturnBlank: null,
|
|
73
|
-
cssUseCustomPattern: null,
|
|
74
|
-
cssPattern: null,
|
|
75
|
-
cssPatternGroup: null,
|
|
76
|
-
cssRedirectGroup: null,
|
|
77
|
-
|
|
78
|
-
// Advanced settings
|
|
79
|
-
advancedHeader: null,
|
|
80
|
-
advancedContent: null,
|
|
81
|
-
advancedToggle: null,
|
|
82
|
-
maskingMode: null,
|
|
83
|
-
clearCacheOnEnable: null,
|
|
84
|
-
disableCacheForRedirects: null,
|
|
85
|
-
|
|
86
|
-
// Action buttons
|
|
87
|
-
saveBtn: null,
|
|
88
|
-
clearCacheBtn: null,
|
|
89
|
-
};
|
|
90
|
-
|
|
91
|
-
// Initialize popup
|
|
92
|
-
document.addEventListener("DOMContentLoaded", async () => {
|
|
93
|
-
try {
|
|
94
|
-
initializeElements();
|
|
95
|
-
setupEventListeners();
|
|
96
|
-
await loadConfiguration();
|
|
97
|
-
updateUI();
|
|
98
|
-
console.log("[JavaScript Proxy] Popup initialized successfully");
|
|
99
|
-
} catch (error) {
|
|
100
|
-
console.error("[JavaScript Proxy] Error initializing popup:", error);
|
|
101
|
-
showStatus("Error initializing popup: " + error.message, "error");
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
|
|
105
|
-
// Initialize DOM elements
|
|
106
|
-
function initializeElements() {
|
|
107
|
-
// Get all elements and store in global object
|
|
108
|
-
for (const key in elements) {
|
|
109
|
-
const element = document.getElementById(key);
|
|
110
|
-
if (!element) {
|
|
111
|
-
throw new Error(`Required element not found: ${key}`);
|
|
112
|
-
}
|
|
113
|
-
elements[key] = element;
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Setup event listeners
|
|
118
|
-
function setupEventListeners() {
|
|
119
|
-
// Master toggle
|
|
120
|
-
elements.masterToggle.addEventListener("change", handleMasterToggle);
|
|
121
|
-
|
|
122
|
-
// Rule toggles
|
|
123
|
-
elements.jsRuleToggle.addEventListener("change", () =>
|
|
124
|
-
handleRuleToggle("js")
|
|
125
|
-
);
|
|
126
|
-
elements.cssRuleToggle.addEventListener("change", () =>
|
|
127
|
-
handleRuleToggle("css")
|
|
128
|
-
);
|
|
129
|
-
|
|
130
|
-
// JavaScript rule events
|
|
131
|
-
elements.jsRedirectUrl.addEventListener("input", () =>
|
|
132
|
-
handleFieldChange("js", "redirectUrl")
|
|
133
|
-
);
|
|
134
|
-
elements.jsUseCustomPattern.addEventListener("change", () =>
|
|
135
|
-
handleCustomPatternToggle("js")
|
|
136
|
-
);
|
|
137
|
-
elements.jsPattern.addEventListener("input", () =>
|
|
138
|
-
handleFieldChange("js", "pattern")
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
// CSS rule events
|
|
142
|
-
elements.cssRedirectUrl.addEventListener("input", () =>
|
|
143
|
-
handleFieldChange("css", "redirectUrl")
|
|
144
|
-
);
|
|
145
|
-
elements.cssReturnBlank.addEventListener("change", handleCssBlankToggle);
|
|
146
|
-
elements.cssUseCustomPattern.addEventListener("change", () =>
|
|
147
|
-
handleCustomPatternToggle("css")
|
|
148
|
-
);
|
|
149
|
-
elements.cssPattern.addEventListener("input", () =>
|
|
150
|
-
handleFieldChange("css", "pattern")
|
|
151
|
-
);
|
|
152
|
-
|
|
153
|
-
// Advanced settings toggle
|
|
154
|
-
elements.advancedHeader.addEventListener("click", toggleAdvancedSettings);
|
|
155
|
-
|
|
156
|
-
// Advanced settings checkboxes
|
|
157
|
-
elements.maskingMode.addEventListener("change", () =>
|
|
158
|
-
handleAdvancedSettingChange("maskingMode")
|
|
159
|
-
);
|
|
160
|
-
elements.clearCacheOnEnable.addEventListener("change", () =>
|
|
161
|
-
handleAdvancedSettingChange("clearCacheOnEnable")
|
|
162
|
-
);
|
|
163
|
-
elements.disableCacheForRedirects.addEventListener("change", () =>
|
|
164
|
-
handleAdvancedSettingChange("disableCacheForRedirects")
|
|
165
|
-
);
|
|
166
|
-
|
|
167
|
-
// Action buttons
|
|
168
|
-
elements.saveBtn.addEventListener("click", saveConfiguration);
|
|
169
|
-
elements.clearCacheBtn.addEventListener("click", clearCache);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
// Load configuration from storage
|
|
173
|
-
async function loadConfiguration() {
|
|
1
|
+
document.addEventListener("DOMContentLoaded", async function () {
|
|
2
|
+
// Get all DOM elements
|
|
3
|
+
const toggleButton = document.getElementById("toggleButton");
|
|
4
|
+
const toggleText = document.getElementById("toggleText");
|
|
5
|
+
const saveBtn = document.getElementById("saveBtn");
|
|
6
|
+
const clearCacheBtn = document.getElementById("clearCacheBtn");
|
|
7
|
+
const statusMessage = document.getElementById("statusMessage");
|
|
8
|
+
const maskingMode = document.getElementById("maskingMode");
|
|
9
|
+
const clearCacheOnEnable = document.getElementById("clearCacheOnEnable");
|
|
10
|
+
const disableCacheForRedirects = document.getElementById("disableCacheForRedirects");
|
|
11
|
+
|
|
12
|
+
// Tab elements
|
|
13
|
+
const tabs = document.querySelectorAll(".tab");
|
|
14
|
+
const tabContents = document.querySelectorAll(".tab-content");
|
|
15
|
+
const jsBadge = document.getElementById("jsBadge");
|
|
16
|
+
const cssBadge = document.getElementById("cssBadge");
|
|
17
|
+
|
|
18
|
+
// Inspector elements
|
|
19
|
+
const inspectorToggle = document.getElementById("inspectorToggle");
|
|
20
|
+
const inspectorText = document.getElementById("inspectorText");
|
|
21
|
+
|
|
22
|
+
// Inspector state
|
|
23
|
+
let inspectorEnabled = false;
|
|
24
|
+
|
|
25
|
+
// JS Rule elements
|
|
26
|
+
const jsRuleToggle = document.getElementById("jsRuleToggle");
|
|
27
|
+
const jsRuleContent = document.getElementById("jsRuleContent");
|
|
28
|
+
const jsRedirectUrl = document.getElementById("jsRedirectUrl");
|
|
29
|
+
const jsUseCustomPattern = document.getElementById("jsUseCustomPattern");
|
|
30
|
+
const jsPatternGroup = document.getElementById("jsPatternGroup");
|
|
31
|
+
const jsPattern = document.getElementById("jsPattern");
|
|
32
|
+
|
|
33
|
+
// CSS Rule elements
|
|
34
|
+
const cssRuleToggle = document.getElementById("cssRuleToggle");
|
|
35
|
+
const cssRuleContent = document.getElementById("cssRuleContent");
|
|
36
|
+
const cssRedirectUrl = document.getElementById("cssRedirectUrl");
|
|
37
|
+
const cssReturnBlank = document.getElementById("cssReturnBlank");
|
|
38
|
+
const cssRedirectGroup = document.getElementById("cssRedirectGroup");
|
|
39
|
+
const cssUseCustomPattern = document.getElementById("cssUseCustomPattern");
|
|
40
|
+
const cssPatternGroup = document.getElementById("cssPatternGroup");
|
|
41
|
+
const cssPattern = document.getElementById("cssPattern");
|
|
42
|
+
|
|
43
|
+
// Load environment-based defaults from defaults.json (generated by launch script)
|
|
44
|
+
let envDefaults = {};
|
|
174
45
|
try {
|
|
175
|
-
const
|
|
176
|
-
if (
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
config = migrateConfig(config);
|
|
46
|
+
const response = await fetch(browser.runtime.getURL("defaults.json"));
|
|
47
|
+
if (response.ok) {
|
|
48
|
+
envDefaults = await response.json();
|
|
49
|
+
console.log("[GxP DevTools] Loaded environment defaults:", envDefaults);
|
|
180
50
|
}
|
|
181
|
-
console.log("[JavaScript Proxy] Loaded configuration:", config);
|
|
182
51
|
} catch (error) {
|
|
183
|
-
console.
|
|
184
|
-
showStatus("Error loading configuration: " + error.message, "error");
|
|
52
|
+
console.log("[GxP DevTools] No environment defaults found, using hardcoded defaults");
|
|
185
53
|
}
|
|
186
|
-
}
|
|
187
54
|
|
|
188
|
-
//
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
55
|
+
// Build default redirect URL from env defaults or fallback
|
|
56
|
+
const defaultRedirectUrl = envDefaults.jsRedirectUrl || "https://localhost:3060/src/Plugin.vue";
|
|
57
|
+
|
|
58
|
+
// Default configuration (merged with environment defaults)
|
|
59
|
+
const defaultConfig = {
|
|
60
|
+
enabled: envDefaults.enabled || false,
|
|
61
|
+
redirectUrl: defaultRedirectUrl,
|
|
62
|
+
urlPattern: "uploads\\/plugin-version\\/\\d+\\/file_name\\/.*\\.js(\\?.*)?",
|
|
63
|
+
useCustomPattern: envDefaults.jsUseCustomPattern || false,
|
|
64
|
+
rules: {
|
|
193
65
|
js: {
|
|
194
66
|
enabled: true,
|
|
195
|
-
pattern:
|
|
196
|
-
redirectUrl:
|
|
197
|
-
useCustomPattern:
|
|
67
|
+
pattern: "uploads\\/plugin-version\\/\\d+\\/file_name\\/.*\\.js(\\?.*)?",
|
|
68
|
+
redirectUrl: defaultRedirectUrl,
|
|
69
|
+
useCustomPattern: envDefaults.jsUseCustomPattern || false,
|
|
198
70
|
},
|
|
199
71
|
css: {
|
|
200
|
-
enabled:
|
|
201
|
-
pattern:
|
|
202
|
-
redirectUrl: "",
|
|
203
|
-
returnBlank:
|
|
204
|
-
useCustomPattern: false,
|
|
72
|
+
enabled: envDefaults.cssRuleEnabled !== false,
|
|
73
|
+
pattern: "uploads\\/plugin-version\\/\\d+\\/style_file_name\\/.*\\.css(\\?.*)?",
|
|
74
|
+
redirectUrl: envDefaults.cssRedirectUrl || "",
|
|
75
|
+
returnBlank: envDefaults.cssReturnBlank !== false,
|
|
76
|
+
useCustomPattern: envDefaults.cssUseCustomPattern || false,
|
|
205
77
|
},
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
78
|
+
},
|
|
79
|
+
maskingMode: false,
|
|
80
|
+
clearCacheOnEnable: envDefaults.clearCacheOnEnable !== false,
|
|
81
|
+
disableCacheForRedirects: envDefaults.disableCacheForRedirects !== false,
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
// Load current configuration
|
|
85
|
+
let config = {};
|
|
86
|
+
try {
|
|
87
|
+
const result = await browser.runtime.sendMessage({ action: "getConfig" });
|
|
88
|
+
if (!result || Object.keys(result).length === 0) {
|
|
89
|
+
config = defaultConfig;
|
|
90
|
+
console.log("[GxP DevTools] Initialized with environment defaults");
|
|
91
|
+
} else {
|
|
92
|
+
config = { ...defaultConfig, ...result };
|
|
93
|
+
config = migrateConfig(config, defaultConfig);
|
|
216
94
|
}
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
95
|
+
} catch (error) {
|
|
96
|
+
console.error("[GxP DevTools] Error loading config:", error);
|
|
97
|
+
config = defaultConfig;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Initialize UI
|
|
101
|
+
updateUI();
|
|
102
|
+
setupTabNavigation();
|
|
103
|
+
|
|
104
|
+
function migrateConfig(config, defaults = defaultConfig) {
|
|
105
|
+
if (!config.rules) {
|
|
106
|
+
config.rules = {
|
|
107
|
+
js: {
|
|
108
|
+
enabled: true,
|
|
109
|
+
pattern: config.urlPattern || defaults.rules.js.pattern,
|
|
110
|
+
redirectUrl: config.redirectUrl || defaults.rules.js.redirectUrl,
|
|
111
|
+
useCustomPattern: config.useCustomPattern || defaults.rules.js.useCustomPattern,
|
|
112
|
+
},
|
|
113
|
+
css: {
|
|
114
|
+
enabled: defaults.rules.css.enabled,
|
|
115
|
+
pattern: defaults.rules.css.pattern,
|
|
116
|
+
redirectUrl: defaults.rules.css.redirectUrl,
|
|
117
|
+
returnBlank: defaults.rules.css.returnBlank,
|
|
118
|
+
useCustomPattern: defaults.rules.css.useCustomPattern,
|
|
119
|
+
},
|
|
224
120
|
};
|
|
225
121
|
}
|
|
122
|
+
return config;
|
|
226
123
|
}
|
|
227
124
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
125
|
+
function setupTabNavigation() {
|
|
126
|
+
tabs.forEach((tab) => {
|
|
127
|
+
tab.addEventListener("click", () => {
|
|
128
|
+
const tabName = tab.dataset.tab;
|
|
129
|
+
|
|
130
|
+
// Update active tab
|
|
131
|
+
tabs.forEach((t) => t.classList.remove("active"));
|
|
132
|
+
tab.classList.add("active");
|
|
133
|
+
|
|
134
|
+
// Show corresponding content
|
|
135
|
+
tabContents.forEach((content) => {
|
|
136
|
+
content.classList.remove("active");
|
|
137
|
+
if (content.id === `${tabName}Tab`) {
|
|
138
|
+
content.classList.add("active");
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function updateUI() {
|
|
146
|
+
// Update toggle button
|
|
147
|
+
if (config.enabled) {
|
|
148
|
+
toggleButton.classList.add("enabled");
|
|
149
|
+
toggleText.textContent = "ON";
|
|
150
|
+
} else {
|
|
151
|
+
toggleButton.classList.remove("enabled");
|
|
152
|
+
toggleText.textContent = "OFF";
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// Update global settings
|
|
156
|
+
maskingMode.checked = config.maskingMode || false;
|
|
157
|
+
clearCacheOnEnable.checked = config.clearCacheOnEnable !== false;
|
|
158
|
+
disableCacheForRedirects.checked = config.disableCacheForRedirects !== false;
|
|
159
|
+
|
|
160
|
+
// Update JS rule
|
|
161
|
+
if (config.rules && config.rules.js) {
|
|
162
|
+
jsRuleToggle.checked = config.rules.js.enabled;
|
|
163
|
+
jsRedirectUrl.value = config.rules.js.redirectUrl || "";
|
|
164
|
+
jsUseCustomPattern.checked = config.rules.js.useCustomPattern || false;
|
|
165
|
+
jsPattern.value = config.rules.js.pattern || "";
|
|
166
|
+
|
|
167
|
+
// Update JS badge
|
|
168
|
+
if (config.rules.js.enabled) {
|
|
169
|
+
jsBadge.textContent = "ON";
|
|
170
|
+
jsBadge.classList.remove("disabled");
|
|
171
|
+
jsBadge.classList.add("enabled");
|
|
172
|
+
jsRuleContent.classList.remove("rule-disabled");
|
|
173
|
+
} else {
|
|
174
|
+
jsBadge.textContent = "OFF";
|
|
175
|
+
jsBadge.classList.remove("enabled");
|
|
176
|
+
jsBadge.classList.add("disabled");
|
|
177
|
+
jsRuleContent.classList.add("rule-disabled");
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
// Toggle custom pattern input visibility
|
|
181
|
+
if (config.rules.js.useCustomPattern) {
|
|
182
|
+
jsPatternGroup.classList.remove("hidden");
|
|
183
|
+
} else {
|
|
184
|
+
jsPatternGroup.classList.add("hidden");
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Update CSS rule
|
|
189
|
+
if (config.rules && config.rules.css) {
|
|
190
|
+
cssRuleToggle.checked = config.rules.css.enabled;
|
|
191
|
+
cssRedirectUrl.value = config.rules.css.redirectUrl || "";
|
|
192
|
+
cssReturnBlank.checked = config.rules.css.returnBlank || false;
|
|
193
|
+
cssUseCustomPattern.checked = config.rules.css.useCustomPattern || false;
|
|
194
|
+
cssPattern.value = config.rules.css.pattern || "";
|
|
195
|
+
|
|
196
|
+
// Update CSS badge
|
|
197
|
+
if (config.rules.css.enabled) {
|
|
198
|
+
cssBadge.textContent = "ON";
|
|
199
|
+
cssBadge.classList.remove("disabled");
|
|
200
|
+
cssBadge.classList.add("enabled");
|
|
201
|
+
cssRuleContent.classList.remove("rule-disabled");
|
|
202
|
+
} else {
|
|
203
|
+
cssBadge.textContent = "OFF";
|
|
204
|
+
cssBadge.classList.remove("enabled");
|
|
205
|
+
cssBadge.classList.add("disabled");
|
|
206
|
+
cssRuleContent.classList.add("rule-disabled");
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// Toggle redirect section based on blank return setting
|
|
271
210
|
if (config.rules.css.returnBlank) {
|
|
272
|
-
|
|
211
|
+
cssRedirectGroup.classList.add("hidden");
|
|
212
|
+
} else {
|
|
213
|
+
cssRedirectGroup.classList.remove("hidden");
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
// Toggle custom pattern input visibility
|
|
217
|
+
if (config.rules.css.useCustomPattern) {
|
|
218
|
+
cssPatternGroup.classList.remove("hidden");
|
|
273
219
|
} else {
|
|
274
|
-
|
|
220
|
+
cssPatternGroup.classList.add("hidden");
|
|
275
221
|
}
|
|
276
222
|
}
|
|
277
223
|
}
|
|
278
224
|
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
} else {
|
|
287
|
-
elements.statusInfo.textContent = "Extension is currently disabled";
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
// Update rule container visual states
|
|
292
|
-
function updateRuleContainerStates() {
|
|
293
|
-
// Disable rule containers when master toggle is off
|
|
294
|
-
elements.jsRuleContainer.classList.toggle("disabled", !config.enabled);
|
|
295
|
-
elements.cssRuleContainer.classList.toggle("disabled", !config.enabled);
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// Update pattern field visibility for a rule
|
|
299
|
-
function updatePatternVisibility(ruleType) {
|
|
300
|
-
const rule = config.rules[ruleType];
|
|
301
|
-
const patternGroup = elements[`${ruleType}PatternGroup`];
|
|
302
|
-
|
|
303
|
-
if (rule.useCustomPattern) {
|
|
304
|
-
patternGroup.classList.remove("hidden");
|
|
305
|
-
} else {
|
|
306
|
-
patternGroup.classList.add("hidden");
|
|
307
|
-
}
|
|
308
|
-
}
|
|
309
|
-
|
|
310
|
-
// Update CSS redirect URL visibility based on blank return setting
|
|
311
|
-
function updateCssRedirectVisibility() {
|
|
312
|
-
if (config.rules.css.returnBlank) {
|
|
313
|
-
elements.cssRedirectGroup.classList.add("hidden");
|
|
314
|
-
} else {
|
|
315
|
-
elements.cssRedirectGroup.classList.remove("hidden");
|
|
225
|
+
function showStatus(message, isSuccess = true) {
|
|
226
|
+
statusMessage.textContent = message;
|
|
227
|
+
statusMessage.className = `status ${isSuccess ? "success" : "error"}`;
|
|
228
|
+
|
|
229
|
+
setTimeout(() => {
|
|
230
|
+
statusMessage.className = "status";
|
|
231
|
+
}, 3000);
|
|
316
232
|
}
|
|
317
|
-
}
|
|
318
233
|
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
elements.saveBtn.disabled = !pendingChanges;
|
|
322
|
-
elements.saveBtn.textContent = pendingChanges ? "Save Changes" : "No Changes";
|
|
323
|
-
}
|
|
234
|
+
function validateRedirectUrl(url) {
|
|
235
|
+
if (!url || url.trim() === "") return null;
|
|
324
236
|
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
237
|
+
try {
|
|
238
|
+
new URL(url);
|
|
239
|
+
return null;
|
|
240
|
+
} catch {
|
|
241
|
+
if (url.includes("://")) return "Invalid URL format";
|
|
328
242
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
243
|
+
try {
|
|
244
|
+
new URL("https://" + url);
|
|
245
|
+
return null;
|
|
246
|
+
} catch {
|
|
247
|
+
return "Invalid URL format";
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
335
251
|
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
);
|
|
345
|
-
} else {
|
|
346
|
-
throw new Error(response ? response.error : "Unknown error");
|
|
252
|
+
function validatePattern(pattern) {
|
|
253
|
+
if (!pattern || pattern.trim() === "") return "URL pattern is required";
|
|
254
|
+
|
|
255
|
+
try {
|
|
256
|
+
new RegExp(pattern);
|
|
257
|
+
return null;
|
|
258
|
+
} catch {
|
|
259
|
+
return "Invalid regular expression pattern";
|
|
347
260
|
}
|
|
348
|
-
} catch (error) {
|
|
349
|
-
console.error("[JavaScript Proxy] Error toggling proxy:", error);
|
|
350
|
-
showStatus("Error toggling extension: " + error.message, "error");
|
|
351
|
-
// Revert the toggle
|
|
352
|
-
elements.masterToggle.checked = config.enabled;
|
|
353
261
|
}
|
|
354
|
-
}
|
|
355
262
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
setPendingChanges(true);
|
|
361
|
-
updateUI();
|
|
362
|
-
}
|
|
363
|
-
|
|
364
|
-
// Handle field changes
|
|
365
|
-
function handleFieldChange(ruleType, fieldName) {
|
|
366
|
-
const element =
|
|
367
|
-
elements[
|
|
368
|
-
`${ruleType}${fieldName.charAt(0).toUpperCase() + fieldName.slice(1)}`
|
|
369
|
-
];
|
|
370
|
-
config.rules[ruleType][fieldName] = element.value;
|
|
371
|
-
setPendingChanges(true);
|
|
372
|
-
updateUI();
|
|
373
|
-
}
|
|
374
|
-
|
|
375
|
-
// Handle custom pattern toggle
|
|
376
|
-
function handleCustomPatternToggle(ruleType) {
|
|
377
|
-
const toggle = elements[`${ruleType}UseCustomPattern`];
|
|
378
|
-
config.rules[ruleType].useCustomPattern = toggle.checked;
|
|
379
|
-
setPendingChanges(true);
|
|
380
|
-
updatePatternVisibility(ruleType);
|
|
381
|
-
updateSaveButtonState();
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
// Handle CSS blank return toggle
|
|
385
|
-
function handleCssBlankToggle() {
|
|
386
|
-
config.rules.css.returnBlank = elements.cssReturnBlank.checked;
|
|
387
|
-
setPendingChanges(true);
|
|
388
|
-
updateCssRedirectVisibility();
|
|
389
|
-
updateUI();
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
// Handle advanced setting changes
|
|
393
|
-
function handleAdvancedSettingChange(settingName) {
|
|
394
|
-
config[settingName] = elements[settingName].checked;
|
|
395
|
-
setPendingChanges(true);
|
|
396
|
-
updateSaveButtonState();
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
// Toggle advanced settings panel
|
|
400
|
-
function toggleAdvancedSettings() {
|
|
401
|
-
const isHidden = elements.advancedContent.classList.contains("hidden");
|
|
402
|
-
|
|
403
|
-
if (isHidden) {
|
|
404
|
-
elements.advancedContent.classList.remove("hidden");
|
|
405
|
-
elements.advancedToggle.textContent = "Hide ▲";
|
|
406
|
-
} else {
|
|
407
|
-
elements.advancedContent.classList.add("hidden");
|
|
408
|
-
elements.advancedToggle.textContent = "Show ▼";
|
|
263
|
+
function normalizeUrl(url) {
|
|
264
|
+
if (!url || url.trim() === "") return "";
|
|
265
|
+
if (!url.includes("://")) return "https://" + url;
|
|
266
|
+
return url;
|
|
409
267
|
}
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
// Set pending changes state
|
|
413
|
-
function setPendingChanges(hasPendingChanges) {
|
|
414
|
-
pendingChanges = hasPendingChanges;
|
|
415
|
-
updateSaveButtonState();
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
// Validate configuration
|
|
419
|
-
function validateConfig() {
|
|
420
|
-
const errors = [];
|
|
421
|
-
|
|
422
|
-
// Check JavaScript rule
|
|
423
|
-
if (config.rules.js.enabled) {
|
|
424
|
-
if (!config.rules.js.redirectUrl) {
|
|
425
|
-
errors.push(
|
|
426
|
-
"JavaScript redirect URL is required when JS rule is enabled"
|
|
427
|
-
);
|
|
428
|
-
} else {
|
|
429
|
-
try {
|
|
430
|
-
new URL(config.rules.js.redirectUrl);
|
|
431
|
-
} catch (e) {
|
|
432
|
-
errors.push("JavaScript redirect URL is not valid");
|
|
433
|
-
}
|
|
434
|
-
}
|
|
435
268
|
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
);
|
|
440
|
-
}
|
|
269
|
+
// Event listeners
|
|
270
|
+
toggleButton.addEventListener("click", async function () {
|
|
271
|
+
config.enabled = !config.enabled;
|
|
441
272
|
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
273
|
+
try {
|
|
274
|
+
const response = await browser.runtime.sendMessage({
|
|
275
|
+
action: "toggleProxy",
|
|
276
|
+
enabled: config.enabled,
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
if (response && response.success) {
|
|
280
|
+
updateUI();
|
|
281
|
+
showStatus(config.enabled ? "Proxy enabled" : "Proxy disabled");
|
|
282
|
+
} else {
|
|
283
|
+
throw new Error(response ? response.error : "Unknown error");
|
|
447
284
|
}
|
|
285
|
+
} catch (error) {
|
|
286
|
+
console.error("[GxP DevTools] Error toggling proxy:", error);
|
|
287
|
+
showStatus("Error toggling proxy", false);
|
|
288
|
+
// Revert the change
|
|
289
|
+
config.enabled = !config.enabled;
|
|
448
290
|
}
|
|
449
|
-
}
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
// Global settings event listeners
|
|
294
|
+
maskingMode.addEventListener("change", function () {
|
|
295
|
+
config.maskingMode = this.checked;
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
clearCacheOnEnable.addEventListener("change", function () {
|
|
299
|
+
config.clearCacheOnEnable = this.checked;
|
|
300
|
+
});
|
|
301
|
+
|
|
302
|
+
disableCacheForRedirects.addEventListener("change", function () {
|
|
303
|
+
config.disableCacheForRedirects = this.checked;
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
// JS rule event listeners
|
|
307
|
+
jsRuleToggle.addEventListener("change", function () {
|
|
308
|
+
if (!config.rules) config.rules = {};
|
|
309
|
+
if (!config.rules.js) config.rules.js = { ...defaultConfig.rules.js };
|
|
310
|
+
config.rules.js.enabled = this.checked;
|
|
311
|
+
updateUI();
|
|
312
|
+
});
|
|
450
313
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
if (!config.rules.
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
}
|
|
314
|
+
jsUseCustomPattern.addEventListener("change", function () {
|
|
315
|
+
if (!config.rules) config.rules = {};
|
|
316
|
+
if (!config.rules.js) config.rules.js = { ...defaultConfig.rules.js };
|
|
317
|
+
config.rules.js.useCustomPattern = this.checked;
|
|
318
|
+
updateUI();
|
|
319
|
+
});
|
|
458
320
|
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
321
|
+
// CSS rule event listeners
|
|
322
|
+
cssRuleToggle.addEventListener("change", function () {
|
|
323
|
+
if (!config.rules) config.rules = {};
|
|
324
|
+
if (!config.rules.css) config.rules.css = { ...defaultConfig.rules.css };
|
|
325
|
+
config.rules.css.enabled = this.checked;
|
|
326
|
+
updateUI();
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
cssReturnBlank.addEventListener("change", function () {
|
|
330
|
+
if (!config.rules) config.rules = {};
|
|
331
|
+
if (!config.rules.css) config.rules.css = { ...defaultConfig.rules.css };
|
|
332
|
+
config.rules.css.returnBlank = this.checked;
|
|
333
|
+
updateUI();
|
|
334
|
+
});
|
|
335
|
+
|
|
336
|
+
cssUseCustomPattern.addEventListener("change", function () {
|
|
337
|
+
if (!config.rules) config.rules = {};
|
|
338
|
+
if (!config.rules.css) config.rules.css = { ...defaultConfig.rules.css };
|
|
339
|
+
config.rules.css.useCustomPattern = this.checked;
|
|
340
|
+
updateUI();
|
|
341
|
+
});
|
|
342
|
+
|
|
343
|
+
clearCacheBtn.addEventListener("click", async function () {
|
|
344
|
+
try {
|
|
345
|
+
this.textContent = "Clearing...";
|
|
346
|
+
this.disabled = true;
|
|
347
|
+
|
|
348
|
+
const response = await browser.runtime.sendMessage({ action: "clearCache" });
|
|
349
|
+
|
|
350
|
+
if (response && response.success) {
|
|
351
|
+
showStatus("Cache cleared successfully");
|
|
352
|
+
} else {
|
|
353
|
+
showStatus("Error clearing cache: " + (response?.error || "Unknown error"), false);
|
|
464
354
|
}
|
|
355
|
+
} catch (error) {
|
|
356
|
+
console.error("[GxP DevTools] Error clearing cache:", error);
|
|
357
|
+
showStatus("Error clearing cache", false);
|
|
358
|
+
} finally {
|
|
359
|
+
this.textContent = "Clear Cache";
|
|
360
|
+
this.disabled = false;
|
|
465
361
|
}
|
|
362
|
+
});
|
|
363
|
+
|
|
364
|
+
saveBtn.addEventListener("click", async function () {
|
|
365
|
+
if (!config.rules) config.rules = {};
|
|
366
|
+
if (!config.rules.js) config.rules.js = { ...defaultConfig.rules.js };
|
|
367
|
+
if (!config.rules.css) config.rules.css = { ...defaultConfig.rules.css };
|
|
368
|
+
|
|
369
|
+
// Get values from inputs
|
|
370
|
+
const jsRedirectUrlValue = jsRedirectUrl.value.trim();
|
|
371
|
+
const jsPatternValue = config.rules.js.useCustomPattern
|
|
372
|
+
? jsPattern.value.trim()
|
|
373
|
+
: defaultConfig.rules.js.pattern;
|
|
374
|
+
|
|
375
|
+
const cssRedirectUrlValue = cssRedirectUrl.value.trim();
|
|
376
|
+
const cssPatternValue = config.rules.css.useCustomPattern
|
|
377
|
+
? cssPattern.value.trim()
|
|
378
|
+
: defaultConfig.rules.css.pattern;
|
|
379
|
+
|
|
380
|
+
// Validate JS rule if enabled
|
|
381
|
+
if (config.rules.js.enabled) {
|
|
382
|
+
if (!jsRedirectUrlValue) {
|
|
383
|
+
showStatus("JavaScript redirect URL is required when JS rule is enabled", false);
|
|
384
|
+
return;
|
|
385
|
+
}
|
|
466
386
|
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
"
|
|
470
|
-
|
|
471
|
-
|
|
387
|
+
const jsUrlError = validateRedirectUrl(jsRedirectUrlValue);
|
|
388
|
+
if (jsUrlError) {
|
|
389
|
+
showStatus("JavaScript rule: " + jsUrlError, false);
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
472
392
|
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
393
|
+
if (config.rules.js.useCustomPattern) {
|
|
394
|
+
const jsPatternError = validatePattern(jsPatternValue);
|
|
395
|
+
if (jsPatternError) {
|
|
396
|
+
showStatus("JavaScript rule: " + jsPatternError, false);
|
|
397
|
+
return;
|
|
398
|
+
}
|
|
478
399
|
}
|
|
479
400
|
}
|
|
480
|
-
}
|
|
481
401
|
|
|
482
|
-
|
|
483
|
-
|
|
402
|
+
// Validate CSS rule if enabled
|
|
403
|
+
if (config.rules.css.enabled) {
|
|
404
|
+
if (!config.rules.css.returnBlank && !cssRedirectUrlValue) {
|
|
405
|
+
showStatus("CSS redirect URL is required when not returning blank", false);
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
484
408
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
409
|
+
if (!config.rules.css.returnBlank && cssRedirectUrlValue) {
|
|
410
|
+
const cssUrlError = validateRedirectUrl(cssRedirectUrlValue);
|
|
411
|
+
if (cssUrlError) {
|
|
412
|
+
showStatus("CSS rule: " + cssUrlError, false);
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
488
416
|
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
417
|
+
if (config.rules.css.useCustomPattern) {
|
|
418
|
+
const cssPatternError = validatePattern(cssPatternValue);
|
|
419
|
+
if (cssPatternError) {
|
|
420
|
+
showStatus("CSS rule: " + cssPatternError, false);
|
|
421
|
+
return;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
495
424
|
}
|
|
496
425
|
|
|
497
|
-
//
|
|
498
|
-
|
|
499
|
-
|
|
426
|
+
// Update config with form values
|
|
427
|
+
config.rules.js.redirectUrl = normalizeUrl(jsRedirectUrlValue);
|
|
428
|
+
config.rules.js.pattern = jsPatternValue;
|
|
429
|
+
config.rules.css.redirectUrl = normalizeUrl(cssRedirectUrlValue);
|
|
430
|
+
config.rules.css.pattern = cssPatternValue;
|
|
500
431
|
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
432
|
+
try {
|
|
433
|
+
this.disabled = true;
|
|
434
|
+
this.textContent = "Saving...";
|
|
435
|
+
|
|
436
|
+
const response = await browser.runtime.sendMessage({
|
|
437
|
+
action: "updateConfig",
|
|
438
|
+
config: config,
|
|
439
|
+
});
|
|
440
|
+
|
|
441
|
+
if (response && response.success) {
|
|
442
|
+
updateUI();
|
|
443
|
+
showStatus("Configuration saved successfully");
|
|
444
|
+
} else {
|
|
445
|
+
throw new Error(response ? response.error : "Unknown error");
|
|
446
|
+
}
|
|
447
|
+
} catch (error) {
|
|
448
|
+
console.error("[GxP DevTools] Error saving config:", error);
|
|
449
|
+
showStatus("Error saving configuration", false);
|
|
450
|
+
} finally {
|
|
451
|
+
this.disabled = false;
|
|
452
|
+
this.textContent = "Save Configuration";
|
|
453
|
+
}
|
|
454
|
+
});
|
|
506
455
|
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
456
|
+
// Component Inspector
|
|
457
|
+
function updateInspectorUI() {
|
|
458
|
+
if (inspectorEnabled) {
|
|
459
|
+
inspectorToggle.classList.add("enabled");
|
|
460
|
+
inspectorText.textContent = "ON";
|
|
510
461
|
} else {
|
|
511
|
-
|
|
462
|
+
inspectorToggle.classList.remove("enabled");
|
|
463
|
+
inspectorText.textContent = "OFF";
|
|
512
464
|
}
|
|
513
|
-
} catch (error) {
|
|
514
|
-
console.error("[JavaScript Proxy] Error saving configuration:", error);
|
|
515
|
-
showStatus("Error saving configuration: " + error.message, "error");
|
|
516
|
-
} finally {
|
|
517
|
-
updateSaveButtonState();
|
|
518
465
|
}
|
|
519
|
-
}
|
|
520
|
-
|
|
521
|
-
// Clear cache
|
|
522
|
-
async function clearCache() {
|
|
523
|
-
try {
|
|
524
|
-
elements.clearCacheBtn.disabled = true;
|
|
525
|
-
elements.clearCacheBtn.textContent = "Clearing...";
|
|
526
466
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
467
|
+
async function getInspectorState() {
|
|
468
|
+
try {
|
|
469
|
+
const [tab] = await browser.tabs.query({ active: true, currentWindow: true });
|
|
470
|
+
if (tab?.id) {
|
|
471
|
+
const response = await browser.tabs.sendMessage(tab.id, { action: "getInspectorState" });
|
|
472
|
+
if (response) {
|
|
473
|
+
inspectorEnabled = response.enabled;
|
|
474
|
+
updateInspectorUI();
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
} catch (error) {
|
|
478
|
+
console.log("[GxP DevTools] Could not get inspector state:", error);
|
|
535
479
|
}
|
|
536
|
-
} catch (error) {
|
|
537
|
-
console.error("[JavaScript Proxy] Error clearing cache:", error);
|
|
538
|
-
showStatus("Error clearing cache: " + error.message, "error");
|
|
539
|
-
} finally {
|
|
540
|
-
elements.clearCacheBtn.disabled = false;
|
|
541
|
-
elements.clearCacheBtn.textContent = "Clear Cache";
|
|
542
480
|
}
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
}
|
|
481
|
+
|
|
482
|
+
inspectorToggle.addEventListener("click", async function () {
|
|
483
|
+
try {
|
|
484
|
+
const [tab] = await browser.tabs.query({ active: true, currentWindow: true });
|
|
485
|
+
if (tab?.id) {
|
|
486
|
+
const response = await browser.tabs.sendMessage(tab.id, { action: "toggleInspector" });
|
|
487
|
+
if (response) {
|
|
488
|
+
inspectorEnabled = response.enabled;
|
|
489
|
+
updateInspectorUI();
|
|
490
|
+
showStatus(inspectorEnabled ? "Inspector enabled" : "Inspector disabled");
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
} catch (error) {
|
|
494
|
+
showStatus("Could not toggle inspector. Make sure you're on a web page.", false);
|
|
495
|
+
}
|
|
496
|
+
});
|
|
497
|
+
|
|
498
|
+
getInspectorState();
|
|
499
|
+
});
|