@dynamicu/chromedebug-mcp 2.7.0 → 2.7.2
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/CLAUDE.md +16 -0
- package/chrome-extension/activation-manager.js +10 -10
- package/chrome-extension/background.js +473 -256
- package/chrome-extension/chrome-session-manager.js +5 -5
- package/chrome-extension/content.js +305 -119
- package/chrome-extension/data-buffer.js +5 -5
- package/chrome-extension/dom-tracker.js +9 -9
- package/chrome-extension/firebase-client.js +13 -13
- package/chrome-extension/frame-capture.js +20 -38
- package/chrome-extension/license-helper.js +9 -9
- package/chrome-extension/manifest.free.json +3 -3
- package/chrome-extension/network-tracker.js +9 -9
- package/chrome-extension/options.html +10 -0
- package/chrome-extension/options.js +20 -7
- package/chrome-extension/performance-monitor.js +17 -17
- package/chrome-extension/popup.html +8 -1
- package/chrome-extension/popup.js +71 -92
- package/chrome-extension/pro/frame-editor.html +23 -0
- package/chrome-extension/pro/frame-editor.js +101 -30
- package/chrome-extension/pro/function-tracker.js +10 -10
- package/chrome-extension/upload-manager.js +7 -7
- package/dist/chromedebug-extension-free.zip +0 -0
- package/package.json +1 -1
- package/src/database.js +69 -0
- package/src/validation/schemas.js +19 -13
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// Background script to handle server communication and recording
|
|
2
2
|
const EXTENSION_VERSION = '2.0.4-BUILD-20250119';
|
|
3
|
-
console.log(`[background.js] Loaded version: ${EXTENSION_VERSION}`);
|
|
3
|
+
// console.log(`[background.js] Loaded version: ${EXTENSION_VERSION}`);
|
|
4
4
|
|
|
5
5
|
// Import configuration and libraries
|
|
6
6
|
importScripts('extension-config.js');
|
|
@@ -93,7 +93,7 @@ async function checkUsageBeforeRecording() {
|
|
|
93
93
|
async function incrementUsageAfterRecording() {
|
|
94
94
|
// PRO version: skip tracking
|
|
95
95
|
if (isProVersion()) {
|
|
96
|
-
console.log('[Usage] PRO version - skipping usage tracking');
|
|
96
|
+
// console.log('[Usage] PRO version - skipping usage tracking');
|
|
97
97
|
return { success: true, count: 0, limit: Infinity, isPro: true };
|
|
98
98
|
}
|
|
99
99
|
|
|
@@ -108,7 +108,7 @@ async function incrementUsageAfterRecording() {
|
|
|
108
108
|
[USAGE_STORAGE_KEY]: { count: newCount, date: today }
|
|
109
109
|
});
|
|
110
110
|
|
|
111
|
-
console.log(`[Usage] Recording tracked: ${newCount}/${FREE_TIER_DAILY_LIMIT} today`);
|
|
111
|
+
// console.log(`[Usage] Recording tracked: ${newCount}/${FREE_TIER_DAILY_LIMIT} today`);
|
|
112
112
|
|
|
113
113
|
return { success: true, count: newCount, limit: FREE_TIER_DAILY_LIMIT };
|
|
114
114
|
}
|
|
@@ -154,7 +154,7 @@ class LogStreamer {
|
|
|
154
154
|
async init() {
|
|
155
155
|
// Skip initialization in browser-only mode
|
|
156
156
|
if (serverMode === 'browser-only') {
|
|
157
|
-
console.log('[LogStreamer] Skipping initialization - browser-only mode');
|
|
157
|
+
// console.log('[LogStreamer] Skipping initialization - browser-only mode');
|
|
158
158
|
return;
|
|
159
159
|
}
|
|
160
160
|
|
|
@@ -164,7 +164,7 @@ class LogStreamer {
|
|
|
164
164
|
// Start periodic streaming
|
|
165
165
|
this.startPeriodicStreaming();
|
|
166
166
|
|
|
167
|
-
console.log('[LogStreamer] Initialized with server availability:', this.serverAvailable);
|
|
167
|
+
// console.log('[LogStreamer] Initialized with server availability:', this.serverAvailable);
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
async checkServerAvailability() {
|
|
@@ -176,7 +176,7 @@ class LogStreamer {
|
|
|
176
176
|
});
|
|
177
177
|
if (response.ok) {
|
|
178
178
|
this.serverAvailable = true;
|
|
179
|
-
console.log(`[LogStreamer] Server available on port ${port}`);
|
|
179
|
+
// console.log(`[LogStreamer] Server available on port ${port}`);
|
|
180
180
|
return;
|
|
181
181
|
}
|
|
182
182
|
} catch (error) {
|
|
@@ -184,7 +184,7 @@ class LogStreamer {
|
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
186
|
this.serverAvailable = false;
|
|
187
|
-
console.log('[LogStreamer] No server available');
|
|
187
|
+
// console.log('[LogStreamer] No server available');
|
|
188
188
|
}
|
|
189
189
|
|
|
190
190
|
startPeriodicStreaming() {
|
|
@@ -227,7 +227,7 @@ class LogStreamer {
|
|
|
227
227
|
// This gives frames time to be processed before logs are associated
|
|
228
228
|
const timeSinceLastFrame = Date.now() - this.lastFrameCapture;
|
|
229
229
|
if (this.lastFrameCapture > 0 && timeSinceLastFrame < 100) {
|
|
230
|
-
console.log('[LogStreamer] Waiting for frame processing before streaming logs');
|
|
230
|
+
// console.log('[LogStreamer] Waiting for frame processing before streaming logs');
|
|
231
231
|
return; // Wait for next cycle
|
|
232
232
|
}
|
|
233
233
|
|
|
@@ -256,7 +256,7 @@ class LogStreamer {
|
|
|
256
256
|
// Method to notify LogStreamer when frame is captured
|
|
257
257
|
notifyFrameCapture() {
|
|
258
258
|
this.lastFrameCapture = Date.now();
|
|
259
|
-
console.log('[LogStreamer] Frame capture notification received');
|
|
259
|
+
// console.log('[LogStreamer] Frame capture notification received');
|
|
260
260
|
}
|
|
261
261
|
|
|
262
262
|
async sendToServer(batch) {
|
|
@@ -280,7 +280,7 @@ class LogStreamer {
|
|
|
280
280
|
const result = await response.json();
|
|
281
281
|
// Only log if we had to try multiple ports (first port failed)
|
|
282
282
|
if (port !== this.serverPorts[0]) {
|
|
283
|
-
console.log(`[LogStreamer] Connected to server on port ${port}`);
|
|
283
|
+
// console.log(`[LogStreamer] Connected to server on port ${port}`);
|
|
284
284
|
}
|
|
285
285
|
return result;
|
|
286
286
|
}
|
|
@@ -331,7 +331,7 @@ class LogStreamer {
|
|
|
331
331
|
if (now >= item.nextRetry && item.attempts < 3) {
|
|
332
332
|
try {
|
|
333
333
|
await this.sendToServer(item.batch);
|
|
334
|
-
console.log(`[LogStreamer] Retry successful for batch with ${item.batch.length} logs`);
|
|
334
|
+
// console.log(`[LogStreamer] Retry successful for batch with ${item.batch.length} logs`);
|
|
335
335
|
} catch (error) {
|
|
336
336
|
item.attempts++;
|
|
337
337
|
item.nextRetry = now + (1000 * Math.pow(2, item.attempts)); // Exponential backoff
|
|
@@ -389,7 +389,7 @@ class LogBuffer {
|
|
|
389
389
|
// Flush all buffers to Chrome storage
|
|
390
390
|
async flushAll() {
|
|
391
391
|
if (this.flushInProgress) {
|
|
392
|
-
console.log('[LogBuffer] Flush already in progress, waiting for completion...');
|
|
392
|
+
// console.log('[LogBuffer] Flush already in progress, waiting for completion...');
|
|
393
393
|
// Wait for current flush to complete instead of skipping
|
|
394
394
|
while (this.flushInProgress) {
|
|
395
395
|
await new Promise(resolve => setTimeout(resolve, 10));
|
|
@@ -402,7 +402,7 @@ class LogBuffer {
|
|
|
402
402
|
const startTime = Date.now();
|
|
403
403
|
|
|
404
404
|
try {
|
|
405
|
-
console.log(`[LogBuffer] Starting flushAll for ${this.tabBuffers.size} tabs`);
|
|
405
|
+
// console.log(`[LogBuffer] Starting flushAll for ${this.tabBuffers.size} tabs`);
|
|
406
406
|
|
|
407
407
|
for (const [tabId, tabBuffer] of this.tabBuffers) {
|
|
408
408
|
flushPromises.push(tabBuffer.flush());
|
|
@@ -410,7 +410,7 @@ class LogBuffer {
|
|
|
410
410
|
|
|
411
411
|
await Promise.all(flushPromises);
|
|
412
412
|
const duration = Date.now() - startTime;
|
|
413
|
-
console.log(`[LogBuffer] Successfully flushed all buffers for ${this.tabBuffers.size} tabs in ${duration}ms`);
|
|
413
|
+
// console.log(`[LogBuffer] Successfully flushed all buffers for ${this.tabBuffers.size} tabs in ${duration}ms`);
|
|
414
414
|
} catch (error) {
|
|
415
415
|
console.error('[LogBuffer] Error during flush operation:', error);
|
|
416
416
|
throw error; // Re-throw to ensure proper error handling upstream
|
|
@@ -431,7 +431,7 @@ class LogBuffer {
|
|
|
431
431
|
clearTab(tabId) {
|
|
432
432
|
if (this.tabBuffers.has(tabId)) {
|
|
433
433
|
this.tabBuffers.delete(tabId);
|
|
434
|
-
console.log(`[LogBuffer] Cleared buffer for tab ${tabId}`);
|
|
434
|
+
// console.log(`[LogBuffer] Cleared buffer for tab ${tabId}`);
|
|
435
435
|
}
|
|
436
436
|
}
|
|
437
437
|
|
|
@@ -457,7 +457,7 @@ class LogBuffer {
|
|
|
457
457
|
// Debug method to log current buffer state
|
|
458
458
|
logStats() {
|
|
459
459
|
const stats = this.getStats();
|
|
460
|
-
console.log('[LogBuffer] Current statistics:', stats);
|
|
460
|
+
// console.log('[LogBuffer] Current statistics:', stats);
|
|
461
461
|
return stats;
|
|
462
462
|
}
|
|
463
463
|
}
|
|
@@ -572,7 +572,7 @@ class LogTabBuffer {
|
|
|
572
572
|
}
|
|
573
573
|
|
|
574
574
|
this.totalLogsFlushed += this.buffer.length;
|
|
575
|
-
console.log(`[LogBuffer] Flushed ${this.buffer.length} logs for tab ${this.tabId} (total: ${this.totalLogsFlushed})`);
|
|
575
|
+
// console.log(`[LogBuffer] Flushed ${this.buffer.length} logs for tab ${this.tabId} (total: ${this.totalLogsFlushed})`);
|
|
576
576
|
|
|
577
577
|
// Clear the buffer
|
|
578
578
|
this.buffer = [];
|
|
@@ -715,7 +715,7 @@ class WorkflowLogBuffer {
|
|
|
715
715
|
}
|
|
716
716
|
|
|
717
717
|
this.totalLogsFlushed += this.buffer.length;
|
|
718
|
-
console.log(`[WorkflowLogBuffer] Flushed ${this.buffer.length} logs for tab ${this.tabId} (total: ${this.totalLogsFlushed})`);
|
|
718
|
+
// console.log(`[WorkflowLogBuffer] Flushed ${this.buffer.length} logs for tab ${this.tabId} (total: ${this.totalLogsFlushed})`);
|
|
719
719
|
|
|
720
720
|
// Clear the buffer
|
|
721
721
|
this.buffer = [];
|
|
@@ -746,7 +746,7 @@ class WorkflowLogBuffer {
|
|
|
746
746
|
if (this.buffer.length > 0) {
|
|
747
747
|
await this.performFlush();
|
|
748
748
|
}
|
|
749
|
-
console.log(`[WorkflowLogBuffer] Cleaned up buffer for tab ${this.tabId}`);
|
|
749
|
+
// console.log(`[WorkflowLogBuffer] Cleaned up buffer for tab ${this.tabId}`);
|
|
750
750
|
} catch (error) {
|
|
751
751
|
console.error(`[WorkflowLogBuffer] Error during cleanup for tab ${this.tabId}:`, error);
|
|
752
752
|
}
|
|
@@ -809,10 +809,10 @@ const DATA_PROTECTION_TIERS = {
|
|
|
809
809
|
async function initializeServices() {
|
|
810
810
|
try {
|
|
811
811
|
// FIRST: Initialize comprehensive error handling system
|
|
812
|
-
console.log('[Background] Initializing comprehensive error handling...');
|
|
812
|
+
// console.log('[Background] Initializing comprehensive error handling...');
|
|
813
813
|
const errorHandlingSuccess = await initializeErrorHandling();
|
|
814
814
|
if (errorHandlingSuccess) {
|
|
815
|
-
console.log('[Background] Comprehensive error handling initialized successfully');
|
|
815
|
+
// console.log('[Background] Comprehensive error handling initialized successfully');
|
|
816
816
|
} else {
|
|
817
817
|
console.warn('[Background] Error handling initialization failed - continuing with basic functionality');
|
|
818
818
|
}
|
|
@@ -820,16 +820,16 @@ async function initializeServices() {
|
|
|
820
820
|
// Initialize the data buffer
|
|
821
821
|
dataBuffer = new DataBuffer();
|
|
822
822
|
await dataBuffer.init();
|
|
823
|
-
console.log('[Background] Data buffer initialized');
|
|
823
|
+
// console.log('[Background] Data buffer initialized');
|
|
824
824
|
|
|
825
825
|
// Only create upload manager if data buffer initialized successfully
|
|
826
826
|
try {
|
|
827
827
|
uploadManager = new UploadManager(dataBuffer);
|
|
828
828
|
const serverAvailable = await uploadManager.init();
|
|
829
829
|
if (serverAvailable) {
|
|
830
|
-
console.log('[Background] Upload manager initialized with server');
|
|
830
|
+
// console.log('[Background] Upload manager initialized with server');
|
|
831
831
|
} else {
|
|
832
|
-
console.log('[Background] Upload manager initialized but no server available yet');
|
|
832
|
+
// console.log('[Background] Upload manager initialized but no server available yet');
|
|
833
833
|
}
|
|
834
834
|
} catch (uploadErr) {
|
|
835
835
|
console.error('[Background] Failed to initialize upload manager:', uploadErr);
|
|
@@ -841,7 +841,7 @@ async function initializeServices() {
|
|
|
841
841
|
try {
|
|
842
842
|
logStreamer = new LogStreamer();
|
|
843
843
|
await logStreamer.init();
|
|
844
|
-
console.log('[Background] Log streamer initialized');
|
|
844
|
+
// console.log('[Background] Log streamer initialized');
|
|
845
845
|
} catch (streamErr) {
|
|
846
846
|
console.error('[Background] Failed to initialize log streamer:', streamErr);
|
|
847
847
|
logStreamer = null;
|
|
@@ -850,7 +850,7 @@ async function initializeServices() {
|
|
|
850
850
|
// Initialize log buffer for race-condition-free storage
|
|
851
851
|
try {
|
|
852
852
|
logBuffer = new LogBuffer();
|
|
853
|
-
console.log('[Background] Log buffer initialized');
|
|
853
|
+
// console.log('[Background] Log buffer initialized');
|
|
854
854
|
} catch (bufferErr) {
|
|
855
855
|
console.error('[Background] Failed to initialize log buffer:', bufferErr);
|
|
856
856
|
logBuffer = null;
|
|
@@ -859,7 +859,7 @@ async function initializeServices() {
|
|
|
859
859
|
// Initialize browser recording manager for browser-only mode
|
|
860
860
|
try {
|
|
861
861
|
browserRecordingManager = new BrowserRecordingManager(dataBuffer);
|
|
862
|
-
console.log('[Background] Browser recording manager initialized');
|
|
862
|
+
// console.log('[Background] Browser recording manager initialized');
|
|
863
863
|
} catch (recordingErr) {
|
|
864
864
|
console.error('[Background] Failed to initialize browser recording manager:', recordingErr);
|
|
865
865
|
browserRecordingManager = null;
|
|
@@ -869,12 +869,12 @@ async function initializeServices() {
|
|
|
869
869
|
try {
|
|
870
870
|
if (!sessionManager) {
|
|
871
871
|
sessionManager = new ChromeExtensionSessionManager();
|
|
872
|
-
console.log('[Background] Session manager initialized');
|
|
872
|
+
// console.log('[Background] Session manager initialized');
|
|
873
873
|
}
|
|
874
874
|
|
|
875
875
|
// Recover any stuck sessions on startup
|
|
876
876
|
await sessionManager.recoverSessions();
|
|
877
|
-
console.log('[Background] Session recovery completed');
|
|
877
|
+
// console.log('[Background] Session recovery completed');
|
|
878
878
|
} catch (sessionErr) {
|
|
879
879
|
console.error('[Background] Failed to initialize session manager:', sessionErr);
|
|
880
880
|
// Session manager critical for recording - but don't fail completely
|
|
@@ -1012,12 +1012,12 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
1012
1012
|
}));
|
|
1013
1013
|
|
|
1014
1014
|
dataBuffer.addBatch(eventsWithRecordingId).then(() => {
|
|
1015
|
-
console.log(`[Background] Added ${eventsWithRecordingId.length} events to buffer for recording ${message.recordingId}`);
|
|
1015
|
+
// console.log(`[Background] Added ${eventsWithRecordingId.length} events to buffer for recording ${message.recordingId}`);
|
|
1016
1016
|
// Create a batch if we have enough events
|
|
1017
1017
|
return dataBuffer.createBatch(message.recordingId);
|
|
1018
1018
|
}).then(batch => {
|
|
1019
1019
|
if (batch) {
|
|
1020
|
-
console.log(`[Background] Created batch ${batch.id} with ${batch.events.length} events`);
|
|
1020
|
+
// console.log(`[Background] Created batch ${batch.id} with ${batch.events.length} events`);
|
|
1021
1021
|
// Process upload queue if upload manager is available
|
|
1022
1022
|
if (uploadManager) {
|
|
1023
1023
|
uploadManager.processUploadQueue();
|
|
@@ -1086,7 +1086,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
1086
1086
|
sessionId: message.sessionId
|
|
1087
1087
|
}).catch(() => {
|
|
1088
1088
|
// Content script might not be available
|
|
1089
|
-
console.log('[Background] Could not forward start-screen-capture-tracking to content script');
|
|
1089
|
+
// console.log('[Background] Could not forward start-screen-capture-tracking to content script');
|
|
1090
1090
|
});
|
|
1091
1091
|
}
|
|
1092
1092
|
sendResponse({ success: true });
|
|
@@ -1098,7 +1098,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
1098
1098
|
chrome.tabs.sendMessage(sender.tab.id, {
|
|
1099
1099
|
type: 'stop-screen-capture-tracking'
|
|
1100
1100
|
}).catch(() => {
|
|
1101
|
-
console.log('[Background] Could not forward stop-screen-capture-tracking to content script');
|
|
1101
|
+
// console.log('[Background] Could not forward stop-screen-capture-tracking to content script');
|
|
1102
1102
|
});
|
|
1103
1103
|
}
|
|
1104
1104
|
sendResponse({ success: true });
|
|
@@ -1128,7 +1128,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
1128
1128
|
frameIndex: frameIndex
|
|
1129
1129
|
};
|
|
1130
1130
|
screenInteractions.push(interaction);
|
|
1131
|
-
console.log('[Background] Visual feedback interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
|
|
1131
|
+
// console.log('[Background] Visual feedback interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
|
|
1132
1132
|
}
|
|
1133
1133
|
}).catch(error => {
|
|
1134
1134
|
console.error('Error validating recording state for interaction:', error);
|
|
@@ -1141,7 +1141,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
1141
1141
|
frameIndex: frameCounter.get(currentRecordingSessionId) || 0
|
|
1142
1142
|
};
|
|
1143
1143
|
screenInteractions.push(interaction);
|
|
1144
|
-
console.log('[Background] Visual feedback interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
|
|
1144
|
+
// console.log('[Background] Visual feedback interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
|
|
1145
1145
|
}
|
|
1146
1146
|
}
|
|
1147
1147
|
}
|
|
@@ -1154,7 +1154,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
1154
1154
|
chrome.tabs.sendMessage(sender.tab.id, {
|
|
1155
1155
|
type: 'screen-capture-frame-captured'
|
|
1156
1156
|
}).catch(() => {
|
|
1157
|
-
console.log('[Background] Could not forward frame flash to content script');
|
|
1157
|
+
// console.log('[Background] Could not forward frame flash to content script');
|
|
1158
1158
|
});
|
|
1159
1159
|
}
|
|
1160
1160
|
// Don't send response to avoid warnings
|
|
@@ -1165,7 +1165,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
1165
1165
|
if (logBuffer && sender.tab) {
|
|
1166
1166
|
const tabId = sender.tab.id;
|
|
1167
1167
|
const testLogsCount = message.count || 1000;
|
|
1168
|
-
console.log(`[Background] Starting LogBuffer race condition test with ${testLogsCount} logs for tab ${tabId}`);
|
|
1168
|
+
// console.log(`[Background] Starting LogBuffer race condition test with ${testLogsCount} logs for tab ${tabId}`);
|
|
1169
1169
|
|
|
1170
1170
|
// Simulate rapid log generation like a real high-volume scenario
|
|
1171
1171
|
const startTime = Date.now();
|
|
@@ -1188,8 +1188,8 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
1188
1188
|
Promise.all(logPromises).then(() => {
|
|
1189
1189
|
const endTime = Date.now();
|
|
1190
1190
|
const stats = logBuffer.getStats();
|
|
1191
|
-
console.log(`[Background] LogBuffer test completed in ${endTime - startTime}ms`);
|
|
1192
|
-
console.log(`[Background] Test results:`, stats);
|
|
1191
|
+
// console.log(`[Background] LogBuffer test completed in ${endTime - startTime}ms`);
|
|
1192
|
+
// console.log(`[Background] Test results:`, stats);
|
|
1193
1193
|
|
|
1194
1194
|
sendResponse({
|
|
1195
1195
|
success: true,
|
|
@@ -1219,7 +1219,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
1219
1219
|
// DEBUG: Get current LogBuffer statistics
|
|
1220
1220
|
if (logBuffer) {
|
|
1221
1221
|
const stats = logBuffer.getStats();
|
|
1222
|
-
console.log('[Background] LogBuffer stats requested:', stats);
|
|
1222
|
+
// console.log('[Background] LogBuffer stats requested:', stats);
|
|
1223
1223
|
sendResponse({
|
|
1224
1224
|
success: true,
|
|
1225
1225
|
stats: stats
|
|
@@ -1234,10 +1234,10 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
1234
1234
|
|
|
1235
1235
|
case 'getBrowserRecordings':
|
|
1236
1236
|
// Get all browser-only recordings from IndexedDB
|
|
1237
|
-
console.log('[Background] getBrowserRecordings - Manager exists:', !!browserRecordingManager);
|
|
1237
|
+
// console.log('[Background] getBrowserRecordings - Manager exists:', !!browserRecordingManager);
|
|
1238
1238
|
if (browserRecordingManager) {
|
|
1239
1239
|
browserRecordingManager.listRecordings().then(recordings => {
|
|
1240
|
-
console.log('[Background] Recordings retrieved from manager:', recordings);
|
|
1240
|
+
// console.log('[Background] Recordings retrieved from manager:', recordings);
|
|
1241
1241
|
sendResponse(recordings);
|
|
1242
1242
|
}).catch(error => {
|
|
1243
1243
|
console.error('[Background] Failed to get browser recordings:', error);
|
|
@@ -1284,7 +1284,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
1284
1284
|
// Get frames for a browser-only recording
|
|
1285
1285
|
if (dataBuffer && message.sessionId) {
|
|
1286
1286
|
dataBuffer.getBrowserFrames(message.sessionId).then(frames => {
|
|
1287
|
-
console.log(`[DEBUG] getBrowserRecordingFrames: Retrieved ${frames.length} frames from IndexedDB`);
|
|
1287
|
+
// console.log(`[DEBUG] getBrowserRecordingFrames: Retrieved ${frames.length} frames from IndexedDB`);
|
|
1288
1288
|
|
|
1289
1289
|
// Debug first frame to see structure
|
|
1290
1290
|
if (frames.length > 0) {
|
|
@@ -1298,7 +1298,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
1298
1298
|
frameIndex: firstFrame.frameIndex,
|
|
1299
1299
|
allKeys: Object.keys(firstFrame)
|
|
1300
1300
|
};
|
|
1301
|
-
console.log('[DEBUG] First frame structure:', JSON.stringify(debugInfo, null, 2));
|
|
1301
|
+
// console.log('[DEBUG] First frame structure:', JSON.stringify(debugInfo, null, 2));
|
|
1302
1302
|
}
|
|
1303
1303
|
|
|
1304
1304
|
// Transform frames to match frame editor's expected structure
|
|
@@ -1315,7 +1315,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
1315
1315
|
logsCount: transformedFrames[0].logs ? transformedFrames[0].logs.length : 0,
|
|
1316
1316
|
allKeys: Object.keys(transformedFrames[0])
|
|
1317
1317
|
} : 'No frames';
|
|
1318
|
-
console.log('[DEBUG] Transformed first frame:', JSON.stringify(transformDebug, null, 2));
|
|
1318
|
+
// console.log('[DEBUG] Transformed first frame:', JSON.stringify(transformDebug, null, 2));
|
|
1319
1319
|
|
|
1320
1320
|
sendResponse({ success: true, frames: transformedFrames });
|
|
1321
1321
|
}).catch(error => {
|
|
@@ -1341,7 +1341,7 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
1341
1341
|
default:
|
|
1342
1342
|
// Don't warn or respond for messages that should be handled by other listener (v2.0.6)
|
|
1343
1343
|
// This prevents intercepting workflow recording messages
|
|
1344
|
-
console.log('[Background v2.0.6] Message not handled by this listener:', messageType);
|
|
1344
|
+
// console.log('[Background v2.0.6] Message not handled by this listener:', messageType);
|
|
1345
1345
|
// Don't send response - let other listener handle it
|
|
1346
1346
|
return;
|
|
1347
1347
|
}
|
|
@@ -1351,13 +1351,13 @@ chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
|
|
|
1351
1351
|
|
|
1352
1352
|
// Session recovery on startup - handle any stuck recordings from previous session
|
|
1353
1353
|
chrome.runtime.onStartup.addListener(async () => {
|
|
1354
|
-
console.log('[Background] Extension startup detected - checking for stuck sessions');
|
|
1354
|
+
// console.log('[Background] Extension startup detected - checking for stuck sessions');
|
|
1355
1355
|
|
|
1356
1356
|
if (sessionManager) {
|
|
1357
1357
|
try {
|
|
1358
1358
|
// Use existing recovery method from session manager
|
|
1359
1359
|
await sessionManager.recoverSessions();
|
|
1360
|
-
console.log('[Background] Startup session recovery completed');
|
|
1360
|
+
// console.log('[Background] Startup session recovery completed');
|
|
1361
1361
|
} catch (error) {
|
|
1362
1362
|
console.error('[Background] Failed to recover sessions on startup:', error);
|
|
1363
1363
|
}
|
|
@@ -1368,19 +1368,33 @@ chrome.runtime.onStartup.addListener(async () => {
|
|
|
1368
1368
|
|
|
1369
1369
|
// Extension install/update
|
|
1370
1370
|
chrome.runtime.onInstalled.addListener(async (details) => {
|
|
1371
|
-
console.log('[Background] Extension installed/updated:', details.reason);
|
|
1371
|
+
// console.log('[Background] Extension installed/updated:', details.reason);
|
|
1372
1372
|
});
|
|
1373
1373
|
|
|
1374
1374
|
// Listen for tab updates to handle restore points
|
|
1375
1375
|
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
|
|
1376
1376
|
// Inject console logging on navigation during recording
|
|
1377
1377
|
if (changeInfo.status === 'loading') {
|
|
1378
|
-
//
|
|
1378
|
+
// Skip restricted URLs
|
|
1379
|
+
if (!tab.url || tab.url.startsWith('chrome://') || tab.url.startsWith('chrome-extension://')) {
|
|
1380
|
+
return;
|
|
1381
|
+
}
|
|
1382
|
+
|
|
1383
|
+
// Check for WORKFLOW recording first (takes priority)
|
|
1384
|
+
if (workflowRecordingTabs.has(tabId) && workflowIncludeLogs.get(tabId)) {
|
|
1385
|
+
// console.log('[Navigation] Re-injecting workflow console logging for tab:', tabId);
|
|
1386
|
+
self.ConsoleInterceptionLibrary.startConsoleInterception(tabId, WORKFLOW_RECORDING_CONSOLE_CONFIG).catch(err => {
|
|
1387
|
+
console.error('Failed to re-inject workflow console logging:', err);
|
|
1388
|
+
});
|
|
1389
|
+
return; // Don't also inject screen recording logs
|
|
1390
|
+
}
|
|
1391
|
+
|
|
1392
|
+
// Check for SCREEN recording
|
|
1379
1393
|
if (sessionManager) {
|
|
1380
1394
|
isCurrentlyRecordingAsync().then(async (recording) => {
|
|
1381
1395
|
const currentTabId = await getCurrentTabIdAsync();
|
|
1382
|
-
if (recording && tabId === currentTabId
|
|
1383
|
-
console.log('Re-injecting console logging for
|
|
1396
|
+
if (recording && tabId === currentTabId) {
|
|
1397
|
+
// console.log('[Navigation] Re-injecting screen recording console logging for tab:', tabId);
|
|
1384
1398
|
startCapturingLogs(tabId).catch(err => {
|
|
1385
1399
|
console.error('Failed to re-inject console logging:', err);
|
|
1386
1400
|
});
|
|
@@ -1389,9 +1403,9 @@ chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
|
|
|
1389
1403
|
console.error('Error checking recording state for navigation:', error);
|
|
1390
1404
|
});
|
|
1391
1405
|
} else {
|
|
1392
|
-
// Legacy fallback
|
|
1393
|
-
if (tabId === recordingTabId && isCurrentlyRecording
|
|
1394
|
-
console.log('Re-injecting console logging for
|
|
1406
|
+
// Legacy fallback for screen recording
|
|
1407
|
+
if (tabId === recordingTabId && isCurrentlyRecording) {
|
|
1408
|
+
// console.log('[Navigation] Re-injecting screen recording console logging (legacy) for tab:', tabId);
|
|
1395
1409
|
startCapturingLogs(tabId).catch(err => {
|
|
1396
1410
|
console.error('Failed to re-inject console logging:', err);
|
|
1397
1411
|
});
|
|
@@ -1470,7 +1484,7 @@ chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
|
|
|
1470
1484
|
chrome.tabs.onRemoved.addListener((tabId, removeInfo) => {
|
|
1471
1485
|
// Clean up any workflow recording state for closed tabs
|
|
1472
1486
|
if (workflowRecordingTabs.has(tabId)) {
|
|
1473
|
-
console.log(`[Workflow] Tab ${tabId} closed during recording, cleaning up`);
|
|
1487
|
+
// console.log(`[Workflow] Tab ${tabId} closed during recording, cleaning up`);
|
|
1474
1488
|
workflowRecordingTabs.delete(tabId);
|
|
1475
1489
|
workflowIncludeLogs.delete(tabId);
|
|
1476
1490
|
workflowScreenshotSettings.delete(tabId);
|
|
@@ -1481,7 +1495,7 @@ chrome.tabs.onRemoved.addListener((tabId, removeInfo) => {
|
|
|
1481
1495
|
if (buffer) {
|
|
1482
1496
|
buffer.cleanup().then(() => {
|
|
1483
1497
|
workflowLogBuffers.delete(tabId);
|
|
1484
|
-
console.log(`[Workflow] Cleaned up WorkflowLogBuffer for closed tab ${tabId}`);
|
|
1498
|
+
// console.log(`[Workflow] Cleaned up WorkflowLogBuffer for closed tab ${tabId}`);
|
|
1485
1499
|
}).catch(err => {
|
|
1486
1500
|
console.error(`[Workflow] Error cleaning up buffer for closed tab ${tabId}:`, err);
|
|
1487
1501
|
workflowLogBuffers.delete(tabId);
|
|
@@ -1519,11 +1533,148 @@ let isCurrentlyRecording = false; // DEPRECATED: Use isCurrentlyRecordingAsync()
|
|
|
1519
1533
|
let currentRecordingSessionId = null; // DEPRECATED: Use getCurrentSessionIdAsync() instead
|
|
1520
1534
|
let frameCounter = new Map(); // DEPRECATED: Session manager handles frame counting
|
|
1521
1535
|
|
|
1536
|
+
// =============================================================================
|
|
1537
|
+
// INACTIVITY AUTO-STOP - Stop recording if user is inactive
|
|
1538
|
+
// =============================================================================
|
|
1539
|
+
const DEFAULT_INACTIVITY_TIMEOUT_MS = 60 * 1000; // 60 seconds default (1 minute)
|
|
1540
|
+
let lastUserActivityTime = Date.now();
|
|
1541
|
+
let inactivityCheckInterval = null;
|
|
1542
|
+
let currentInactivityTimeout = DEFAULT_INACTIVITY_TIMEOUT_MS;
|
|
1543
|
+
let inactivityMonitoringStarted = false; // Track if monitoring has started
|
|
1544
|
+
let inactivityFallbackTimer = null; // Fallback timer if countdownComplete not received
|
|
1545
|
+
let inactivityDisabled = false; // User can disable for current session
|
|
1546
|
+
|
|
1547
|
+
/**
|
|
1548
|
+
* Start inactivity monitoring for a recording
|
|
1549
|
+
* @param {number} tabId - Tab ID to monitor
|
|
1550
|
+
*/
|
|
1551
|
+
async function startInactivityMonitoring(tabId) {
|
|
1552
|
+
// Mark as started (for fallback timer check)
|
|
1553
|
+
inactivityMonitoringStarted = true;
|
|
1554
|
+
|
|
1555
|
+
// Clear fallback timer since we're starting properly
|
|
1556
|
+
if (inactivityFallbackTimer) {
|
|
1557
|
+
clearTimeout(inactivityFallbackTimer);
|
|
1558
|
+
inactivityFallbackTimer = null;
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
// Load user's configured timeout from storage
|
|
1562
|
+
const settings = await chrome.storage.sync.get(['inactivityTimeout']);
|
|
1563
|
+
currentInactivityTimeout = (settings.inactivityTimeout || 60) * 1000; // Convert seconds to ms (default 60s)
|
|
1564
|
+
|
|
1565
|
+
lastUserActivityTime = Date.now();
|
|
1566
|
+
|
|
1567
|
+
// Tell content script to start tracking activity AND send config for countdown display
|
|
1568
|
+
try {
|
|
1569
|
+
await chrome.tabs.sendMessage(tabId, {
|
|
1570
|
+
action: 'startActivityTracking',
|
|
1571
|
+
inactivityTimeoutMs: currentInactivityTimeout,
|
|
1572
|
+
disabled: inactivityDisabled
|
|
1573
|
+
});
|
|
1574
|
+
} catch (error) {
|
|
1575
|
+
console.warn('[Inactivity] Could not start activity tracking in content script:', error.message);
|
|
1576
|
+
}
|
|
1577
|
+
|
|
1578
|
+
// Clear any existing interval
|
|
1579
|
+
if (inactivityCheckInterval) {
|
|
1580
|
+
clearInterval(inactivityCheckInterval);
|
|
1581
|
+
}
|
|
1582
|
+
|
|
1583
|
+
// If disabled, don't start the check interval
|
|
1584
|
+
if (inactivityDisabled) {
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1587
|
+
|
|
1588
|
+
// Check for inactivity every 2 seconds
|
|
1589
|
+
inactivityCheckInterval = setInterval(async () => {
|
|
1590
|
+
// Skip if disabled
|
|
1591
|
+
if (inactivityDisabled) return;
|
|
1592
|
+
|
|
1593
|
+
const timeSinceActivity = Date.now() - lastUserActivityTime;
|
|
1594
|
+
const timeRemaining = Math.max(0, currentInactivityTimeout - timeSinceActivity);
|
|
1595
|
+
|
|
1596
|
+
// Send countdown update to content script
|
|
1597
|
+
try {
|
|
1598
|
+
await chrome.tabs.sendMessage(tabId, {
|
|
1599
|
+
action: 'updateInactivityCountdown',
|
|
1600
|
+
timeRemaining: Math.ceil(timeRemaining / 1000),
|
|
1601
|
+
disabled: inactivityDisabled
|
|
1602
|
+
});
|
|
1603
|
+
} catch (e) {
|
|
1604
|
+
// Tab might be closed, ignore
|
|
1605
|
+
}
|
|
1606
|
+
|
|
1607
|
+
if (timeSinceActivity >= currentInactivityTimeout) {
|
|
1608
|
+
// Stop the recording first
|
|
1609
|
+
await stopRecording();
|
|
1610
|
+
|
|
1611
|
+
// Show notification with link to settings
|
|
1612
|
+
try {
|
|
1613
|
+
await chrome.notifications.create('inactivity-stop', {
|
|
1614
|
+
type: 'basic',
|
|
1615
|
+
iconUrl: 'icon128.png',
|
|
1616
|
+
title: 'Recording Auto-Stopped',
|
|
1617
|
+
message: `Recording stopped after ${Math.round(currentInactivityTimeout / 1000)}s of inactivity. Click to adjust timeout in Settings.`,
|
|
1618
|
+
priority: 2
|
|
1619
|
+
});
|
|
1620
|
+
} catch (e) {
|
|
1621
|
+
console.warn('[Inactivity] Could not show notification:', e.message);
|
|
1622
|
+
}
|
|
1623
|
+
}
|
|
1624
|
+
}, 2000); // Check every 2 seconds
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
/**
|
|
1628
|
+
* Stop inactivity monitoring
|
|
1629
|
+
* @param {number} tabId - Tab ID that was being monitored
|
|
1630
|
+
*/
|
|
1631
|
+
async function stopInactivityMonitoring(tabId) {
|
|
1632
|
+
if (inactivityCheckInterval) {
|
|
1633
|
+
clearInterval(inactivityCheckInterval);
|
|
1634
|
+
inactivityCheckInterval = null;
|
|
1635
|
+
}
|
|
1636
|
+
|
|
1637
|
+
// Clear fallback timer
|
|
1638
|
+
if (inactivityFallbackTimer) {
|
|
1639
|
+
clearTimeout(inactivityFallbackTimer);
|
|
1640
|
+
inactivityFallbackTimer = null;
|
|
1641
|
+
}
|
|
1642
|
+
|
|
1643
|
+
// Reset state for next recording
|
|
1644
|
+
inactivityMonitoringStarted = false;
|
|
1645
|
+
inactivityDisabled = false; // Reset disabled state for next session
|
|
1646
|
+
|
|
1647
|
+
// Tell content script to stop tracking
|
|
1648
|
+
if (tabId) {
|
|
1649
|
+
try {
|
|
1650
|
+
await chrome.tabs.sendMessage(tabId, { action: 'stopActivityTracking' });
|
|
1651
|
+
} catch (error) {
|
|
1652
|
+
// Tab might be closed, that's ok
|
|
1653
|
+
}
|
|
1654
|
+
}
|
|
1655
|
+
}
|
|
1656
|
+
|
|
1657
|
+
/**
|
|
1658
|
+
* Handle user activity report from content script
|
|
1659
|
+
* @param {number} timestamp - Activity timestamp
|
|
1660
|
+
*/
|
|
1661
|
+
function handleUserActivity(timestamp) {
|
|
1662
|
+
lastUserActivityTime = timestamp || Date.now();
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
// Handle notification clicks - open settings page when inactivity notification is clicked
|
|
1666
|
+
chrome.notifications.onClicked.addListener((notificationId) => {
|
|
1667
|
+
if (notificationId === 'inactivity-stop') {
|
|
1668
|
+
chrome.runtime.openOptionsPage();
|
|
1669
|
+
chrome.notifications.clear(notificationId);
|
|
1670
|
+
}
|
|
1671
|
+
});
|
|
1672
|
+
|
|
1522
1673
|
// Initialize session manager
|
|
1523
1674
|
(async function initializeSessionManager() {
|
|
1524
1675
|
try {
|
|
1525
1676
|
sessionManager = new ChromeExtensionSessionManager();
|
|
1526
|
-
console.log('[ChromeSessionManager] Initialized successfully');
|
|
1677
|
+
// console.log('[ChromeSessionManager] Initialized successfully');
|
|
1527
1678
|
} catch (error) {
|
|
1528
1679
|
console.error('[ChromeSessionManager] Failed to initialize:', error);
|
|
1529
1680
|
}
|
|
@@ -1659,7 +1810,7 @@ let workflowLogBuffers = new Map(); // Map of tabId to WorkflowLogBuffer instanc
|
|
|
1659
1810
|
*/
|
|
1660
1811
|
async function initializeErrorHandling() {
|
|
1661
1812
|
try {
|
|
1662
|
-
console.log('[ErrorHandling] Initializing comprehensive error handling system...');
|
|
1813
|
+
// console.log('[ErrorHandling] Initializing comprehensive error handling system...');
|
|
1663
1814
|
|
|
1664
1815
|
// Generate session ID if not exists
|
|
1665
1816
|
if (!errorHandlingState.sessionId) {
|
|
@@ -1682,11 +1833,11 @@ async function initializeErrorHandling() {
|
|
|
1682
1833
|
errorHandlingState.isInitialized = true;
|
|
1683
1834
|
errorHandlingState.currentState = 'NORMAL_OPERATION';
|
|
1684
1835
|
|
|
1685
|
-
console.log('[ErrorHandling] System initialization complete:', {
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
});
|
|
1836
|
+
// console.log('[ErrorHandling] System initialization complete:', {
|
|
1837
|
+
// sessionId: errorHandlingState.sessionId,
|
|
1838
|
+
// state: errorHandlingState.currentState,
|
|
1839
|
+
// circuitBreaker: errorHandlingState.circuitBreakerState
|
|
1840
|
+
// });
|
|
1690
1841
|
|
|
1691
1842
|
return true;
|
|
1692
1843
|
} catch (error) {
|
|
@@ -1711,7 +1862,7 @@ async function initializeBackupStorage() {
|
|
|
1711
1862
|
};
|
|
1712
1863
|
|
|
1713
1864
|
request.onsuccess = () => {
|
|
1714
|
-
console.log('[ErrorHandling] IndexedDB initialized successfully');
|
|
1865
|
+
// console.log('[ErrorHandling] IndexedDB initialized successfully');
|
|
1715
1866
|
resolve(request.result);
|
|
1716
1867
|
};
|
|
1717
1868
|
|
|
@@ -1741,7 +1892,7 @@ async function initializeBackupStorage() {
|
|
|
1741
1892
|
errorStore.createIndex('timestamp', 'timestamp', { unique: false });
|
|
1742
1893
|
}
|
|
1743
1894
|
|
|
1744
|
-
console.log('[ErrorHandling] IndexedDB schema created');
|
|
1895
|
+
// console.log('[ErrorHandling] IndexedDB schema created');
|
|
1745
1896
|
};
|
|
1746
1897
|
});
|
|
1747
1898
|
}
|
|
@@ -1752,7 +1903,7 @@ async function initializeBackupStorage() {
|
|
|
1752
1903
|
function initializeCircuitBreaker() {
|
|
1753
1904
|
errorHandlingState.circuitBreakerState = 'CLOSED';
|
|
1754
1905
|
errorHandlingState.failedSaveCount = 0;
|
|
1755
|
-
console.log('[ErrorHandling] Circuit breaker initialized in CLOSED state');
|
|
1906
|
+
// console.log('[ErrorHandling] Circuit breaker initialized in CLOSED state');
|
|
1756
1907
|
}
|
|
1757
1908
|
|
|
1758
1909
|
/**
|
|
@@ -1765,7 +1916,7 @@ async function setupNotificationSystem() {
|
|
|
1765
1916
|
await chrome.notifications.clear(notificationId);
|
|
1766
1917
|
}
|
|
1767
1918
|
|
|
1768
|
-
console.log('[ErrorHandling] Notification system ready');
|
|
1919
|
+
// console.log('[ErrorHandling] Notification system ready');
|
|
1769
1920
|
}
|
|
1770
1921
|
|
|
1771
1922
|
/**
|
|
@@ -1804,7 +1955,7 @@ async function cleanupOldBackups() {
|
|
|
1804
1955
|
}
|
|
1805
1956
|
};
|
|
1806
1957
|
|
|
1807
|
-
console.log('[ErrorHandling] Cleanup completed for data older than', ERROR_HANDLING_CONFIG.backupRetentionDays, 'days');
|
|
1958
|
+
// console.log('[ErrorHandling] Cleanup completed for data older than', ERROR_HANDLING_CONFIG.backupRetentionDays, 'days');
|
|
1808
1959
|
};
|
|
1809
1960
|
} catch (error) {
|
|
1810
1961
|
console.error('[ErrorHandling] Failed to cleanup old backups:', error);
|
|
@@ -1831,13 +1982,13 @@ async function handleSaveAttempt(saveFunction, data, context = {}) {
|
|
|
1831
1982
|
if (errorHandlingState.circuitBreakerState === 'OPEN') {
|
|
1832
1983
|
const timeSinceLastFailure = Date.now() - (errorHandlingState.lastError?.timestamp || 0);
|
|
1833
1984
|
if (timeSinceLastFailure < ERROR_HANDLING_CONFIG.resetTimeout) {
|
|
1834
|
-
console.log('[ErrorHandling] Circuit breaker OPEN, attempting backup instead');
|
|
1985
|
+
// console.log('[ErrorHandling] Circuit breaker OPEN, attempting backup instead');
|
|
1835
1986
|
await backupFailedData(data, context);
|
|
1836
1987
|
return { success: false, circuitBreakerOpen: true };
|
|
1837
1988
|
} else {
|
|
1838
1989
|
// Try half-open
|
|
1839
1990
|
errorHandlingState.circuitBreakerState = 'HALF_OPEN';
|
|
1840
|
-
console.log('[ErrorHandling] Circuit breaker moving to HALF_OPEN state');
|
|
1991
|
+
// console.log('[ErrorHandling] Circuit breaker moving to HALF_OPEN state');
|
|
1841
1992
|
}
|
|
1842
1993
|
}
|
|
1843
1994
|
|
|
@@ -1848,7 +1999,7 @@ async function handleSaveAttempt(saveFunction, data, context = {}) {
|
|
|
1848
1999
|
if (result && result.success !== false) {
|
|
1849
2000
|
errorHandlingState.circuitBreakerState = 'CLOSED';
|
|
1850
2001
|
errorHandlingState.failedSaveCount = 0;
|
|
1851
|
-
console.log('[ErrorHandling] Save successful, circuit breaker CLOSED');
|
|
2002
|
+
// console.log('[ErrorHandling] Save successful, circuit breaker CLOSED');
|
|
1852
2003
|
return { success: true, result };
|
|
1853
2004
|
} else {
|
|
1854
2005
|
throw new Error('Save function returned failure');
|
|
@@ -1888,7 +2039,7 @@ async function handleSaveFailure(error, data, context, attempt) {
|
|
|
1888
2039
|
// Attempt backup
|
|
1889
2040
|
try {
|
|
1890
2041
|
await backupFailedData(data, context);
|
|
1891
|
-
console.log('[ErrorHandling] Data backed up successfully');
|
|
2042
|
+
// console.log('[ErrorHandling] Data backed up successfully');
|
|
1892
2043
|
} catch (backupError) {
|
|
1893
2044
|
console.error('[ErrorHandling] CRITICAL: Backup also failed:', backupError);
|
|
1894
2045
|
await createUserNotification('CRITICAL', 'Data loss imminent - manual intervention required');
|
|
@@ -1984,7 +2135,7 @@ async function backupFailedData(data, context) {
|
|
|
1984
2135
|
const store = transaction.objectStore('sessionBackups');
|
|
1985
2136
|
|
|
1986
2137
|
store.add(backupData);
|
|
1987
|
-
console.log('[ErrorHandling] Data backed up with session ID:', errorHandlingState.sessionId);
|
|
2138
|
+
// console.log('[ErrorHandling] Data backed up with session ID:', errorHandlingState.sessionId);
|
|
1988
2139
|
};
|
|
1989
2140
|
|
|
1990
2141
|
// Also add to retained interactions if relevant
|
|
@@ -2025,7 +2176,7 @@ async function createUserNotification(priority, message) {
|
|
|
2025
2176
|
}
|
|
2026
2177
|
|
|
2027
2178
|
await chrome.notifications.create(notificationId, notificationOptions);
|
|
2028
|
-
console.log('[ErrorHandling] User notification created:', notificationId);
|
|
2179
|
+
// console.log('[ErrorHandling] User notification created:', notificationId);
|
|
2029
2180
|
|
|
2030
2181
|
// Set up notification click handlers
|
|
2031
2182
|
chrome.notifications.onButtonClicked.addListener((notifId, buttonIndex) => {
|
|
@@ -2045,16 +2196,16 @@ async function createUserNotification(priority, message) {
|
|
|
2045
2196
|
async function handleNotificationAction(buttonIndex, priority) {
|
|
2046
2197
|
switch (buttonIndex) {
|
|
2047
2198
|
case 0: // Retry Save
|
|
2048
|
-
console.log('[ErrorHandling] User requested retry');
|
|
2199
|
+
// console.log('[ErrorHandling] User requested retry');
|
|
2049
2200
|
await attemptRecovery();
|
|
2050
2201
|
break;
|
|
2051
2202
|
case 1: // View Details
|
|
2052
|
-
console.log('[ErrorHandling] User requested error details');
|
|
2203
|
+
// console.log('[ErrorHandling] User requested error details');
|
|
2053
2204
|
// Could open an options page or log details
|
|
2054
2205
|
break;
|
|
2055
2206
|
case 2: // Download Backup (for critical errors)
|
|
2056
2207
|
if (priority === 'CRITICAL') {
|
|
2057
|
-
console.log('[ErrorHandling] User requested backup download');
|
|
2208
|
+
// console.log('[ErrorHandling] User requested backup download');
|
|
2058
2209
|
await downloadBackupData();
|
|
2059
2210
|
}
|
|
2060
2211
|
break;
|
|
@@ -2074,14 +2225,14 @@ async function attemptRecovery() {
|
|
|
2074
2225
|
|
|
2075
2226
|
store.getAll().onsuccess = (event) => {
|
|
2076
2227
|
const backups = event.target.result;
|
|
2077
|
-
console.log('[ErrorHandling] Found', backups.length, 'backup records for recovery');
|
|
2228
|
+
// console.log('[ErrorHandling] Found', backups.length, 'backup records for recovery');
|
|
2078
2229
|
|
|
2079
2230
|
// Process each backup
|
|
2080
2231
|
backups.forEach(async (backup) => {
|
|
2081
2232
|
try {
|
|
2082
2233
|
// Attempt to save the backed up data
|
|
2083
2234
|
// This would call the original save function with the backed up data
|
|
2084
|
-
console.log('[ErrorHandling] Attempting recovery for session:', backup.sessionId);
|
|
2235
|
+
// console.log('[ErrorHandling] Attempting recovery for session:', backup.sessionId);
|
|
2085
2236
|
} catch (error) {
|
|
2086
2237
|
console.error('[ErrorHandling] Recovery failed for session:', backup.sessionId, error);
|
|
2087
2238
|
}
|
|
@@ -2124,7 +2275,7 @@ async function downloadBackupData() {
|
|
|
2124
2275
|
filename: `chrome-debug-backup-${Date.now()}.json`
|
|
2125
2276
|
});
|
|
2126
2277
|
|
|
2127
|
-
console.log('[ErrorHandling] Backup data download initiated');
|
|
2278
|
+
// console.log('[ErrorHandling] Backup data download initiated');
|
|
2128
2279
|
};
|
|
2129
2280
|
};
|
|
2130
2281
|
};
|
|
@@ -2140,7 +2291,7 @@ async function createOffscreenDocument() {
|
|
|
2140
2291
|
const hasDocument = await chrome.offscreen.hasDocument();
|
|
2141
2292
|
if (hasDocument) {
|
|
2142
2293
|
hasOffscreenDocument = true;
|
|
2143
|
-
console.log('Offscreen document already exists');
|
|
2294
|
+
// console.log('Offscreen document already exists');
|
|
2144
2295
|
return;
|
|
2145
2296
|
}
|
|
2146
2297
|
|
|
@@ -2151,12 +2302,12 @@ async function createOffscreenDocument() {
|
|
|
2151
2302
|
justification: 'Recording tab frames for Chrome Debug'
|
|
2152
2303
|
});
|
|
2153
2304
|
hasOffscreenDocument = true;
|
|
2154
|
-
console.log('Created new offscreen document');
|
|
2305
|
+
// console.log('Created new offscreen document');
|
|
2155
2306
|
} catch (error) {
|
|
2156
2307
|
if (error.message.includes('Only a single offscreen document may be created')) {
|
|
2157
2308
|
// Document already exists, just mark it as available
|
|
2158
2309
|
hasOffscreenDocument = true;
|
|
2159
|
-
console.log('Offscreen document already exists (caught error)');
|
|
2310
|
+
// console.log('Offscreen document already exists (caught error)');
|
|
2160
2311
|
} else {
|
|
2161
2312
|
throw error;
|
|
2162
2313
|
}
|
|
@@ -2174,7 +2325,7 @@ async function closeOffscreenDocument() {
|
|
|
2174
2325
|
}
|
|
2175
2326
|
|
|
2176
2327
|
chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
2177
|
-
console.log('Received message:', request.action || request.type || 'unknown');
|
|
2328
|
+
// console.log('Received message:', request.action || request.type || 'unknown');
|
|
2178
2329
|
|
|
2179
2330
|
if (request.action === 'sendToServer') {
|
|
2180
2331
|
// Primary port is 3028 - try it first, then fallback to others if needed
|
|
@@ -2182,11 +2333,11 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
|
2182
2333
|
|
|
2183
2334
|
async function tryPorts() {
|
|
2184
2335
|
let lastError = null;
|
|
2185
|
-
console.log('Trying to connect to server...');
|
|
2336
|
+
// console.log('Trying to connect to server...');
|
|
2186
2337
|
|
|
2187
2338
|
for (const port of ports) {
|
|
2188
2339
|
try {
|
|
2189
|
-
console.log(`Trying port ${port}...`);
|
|
2340
|
+
// console.log(`Trying port ${port}...`);
|
|
2190
2341
|
const controller = new AbortController();
|
|
2191
2342
|
const timeoutId = setTimeout(() => controller.abort(), DISCOVERY_TIMEOUT);
|
|
2192
2343
|
|
|
@@ -2203,7 +2354,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
|
2203
2354
|
|
|
2204
2355
|
if (response.ok) {
|
|
2205
2356
|
const result = await response.json();
|
|
2206
|
-
console.log(`Success on port ${port}:`, result);
|
|
2357
|
+
// console.log(`Success on port ${port}:`, result);
|
|
2207
2358
|
sendResponse({ success: true, result, port });
|
|
2208
2359
|
return;
|
|
2209
2360
|
} else {
|
|
@@ -2211,7 +2362,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
|
2211
2362
|
try {
|
|
2212
2363
|
const errorData = await response.json();
|
|
2213
2364
|
if (errorData.message || errorData.error) {
|
|
2214
|
-
console.log(`Port ${port} error:`, errorData);
|
|
2365
|
+
// console.log(`Port ${port} error:`, errorData);
|
|
2215
2366
|
sendResponse({
|
|
2216
2367
|
success: false,
|
|
2217
2368
|
result: errorData,
|
|
@@ -2223,11 +2374,11 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
|
2223
2374
|
// Response wasn't JSON
|
|
2224
2375
|
}
|
|
2225
2376
|
lastError = `Port ${port}: HTTP ${response.status}`;
|
|
2226
|
-
console.log(lastError);
|
|
2377
|
+
// console.log(lastError);
|
|
2227
2378
|
}
|
|
2228
2379
|
} catch (e) {
|
|
2229
2380
|
lastError = `Port ${port}: ${e.message}`;
|
|
2230
|
-
console.log(lastError);
|
|
2381
|
+
// console.log(lastError);
|
|
2231
2382
|
}
|
|
2232
2383
|
}
|
|
2233
2384
|
|
|
@@ -2305,7 +2456,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
|
2305
2456
|
|
|
2306
2457
|
// Session manager lease renewal handler
|
|
2307
2458
|
if (request.action === 'renewLease') {
|
|
2308
|
-
console.log('[Background] RENEW LEASE - Session:', request.sessionId, 'Manager exists:', !!sessionManager);
|
|
2459
|
+
// console.log('[Background] RENEW LEASE - Session:', request.sessionId, 'Manager exists:', !!sessionManager);
|
|
2309
2460
|
|
|
2310
2461
|
if (!sessionManager) {
|
|
2311
2462
|
console.error('[Background] Session manager not available');
|
|
@@ -2321,7 +2472,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
|
2321
2472
|
};
|
|
2322
2473
|
|
|
2323
2474
|
sessionManager.renewLease(leaseRequest).then((result) => {
|
|
2324
|
-
console.log('[Background] Lease renewed - Success:', result.success);
|
|
2475
|
+
// console.log('[Background] Lease renewed - Success:', result.success);
|
|
2325
2476
|
sendResponse(result);
|
|
2326
2477
|
}).catch((error) => {
|
|
2327
2478
|
console.error('[Background] Error renewing lease:', error);
|
|
@@ -2355,6 +2506,45 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
|
2355
2506
|
return true;
|
|
2356
2507
|
}
|
|
2357
2508
|
|
|
2509
|
+
// User activity handler for inactivity tracking
|
|
2510
|
+
if (request.action === 'userActivity') {
|
|
2511
|
+
handleUserActivity(request.timestamp);
|
|
2512
|
+
sendResponse({ success: true });
|
|
2513
|
+
return false; // Synchronous response
|
|
2514
|
+
}
|
|
2515
|
+
|
|
2516
|
+
// Countdown complete handler - content script finished 3-2-1 countdown
|
|
2517
|
+
if (request.action === 'countdownComplete') {
|
|
2518
|
+
// Start inactivity monitoring now that countdown is done
|
|
2519
|
+
// Use isCurrentlyRecording (the actual state variable)
|
|
2520
|
+
if (isCurrentlyRecording && recordingTabId && !inactivityMonitoringStarted) {
|
|
2521
|
+
startInactivityMonitoring(recordingTabId);
|
|
2522
|
+
}
|
|
2523
|
+
sendResponse({ success: true });
|
|
2524
|
+
return false;
|
|
2525
|
+
}
|
|
2526
|
+
|
|
2527
|
+
// Toggle inactivity timeout (user clicked disable/enable button)
|
|
2528
|
+
if (request.action === 'toggleInactivityTimeout') {
|
|
2529
|
+
inactivityDisabled = !inactivityDisabled;
|
|
2530
|
+
|
|
2531
|
+
if (inactivityDisabled) {
|
|
2532
|
+
// Stop the check interval but keep tracking activity
|
|
2533
|
+
if (inactivityCheckInterval) {
|
|
2534
|
+
clearInterval(inactivityCheckInterval);
|
|
2535
|
+
inactivityCheckInterval = null;
|
|
2536
|
+
}
|
|
2537
|
+
} else {
|
|
2538
|
+
// Restart monitoring
|
|
2539
|
+
if (recordingTabId && !inactivityCheckInterval) {
|
|
2540
|
+
startInactivityMonitoring(recordingTabId);
|
|
2541
|
+
}
|
|
2542
|
+
}
|
|
2543
|
+
|
|
2544
|
+
sendResponse({ success: true, disabled: inactivityDisabled });
|
|
2545
|
+
return false;
|
|
2546
|
+
}
|
|
2547
|
+
|
|
2358
2548
|
// Force stop session handler (emergency)
|
|
2359
2549
|
if (request.action === 'forceStopSession') {
|
|
2360
2550
|
if (!sessionManager) {
|
|
@@ -2408,7 +2598,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
|
2408
2598
|
*/
|
|
2409
2599
|
/*
|
|
2410
2600
|
if (request.action === 'takeStandaloneSnapshot') {
|
|
2411
|
-
console.log('Taking standalone snapshot for tab:', request.tabId);
|
|
2601
|
+
// console.log('Taking standalone snapshot for tab:', request.tabId);
|
|
2412
2602
|
takeStandaloneSnapshot(request.tabId, request.note).then((result) => {
|
|
2413
2603
|
sendResponse({ success: true, sessionId: result.sessionId });
|
|
2414
2604
|
}).catch((error) => {
|
|
@@ -2456,7 +2646,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
|
2456
2646
|
}
|
|
2457
2647
|
|
|
2458
2648
|
if (request.action === 'startRecordingFromContent') {
|
|
2459
|
-
console.log('Starting recording from content script');
|
|
2649
|
+
// console.log('Starting recording from content script');
|
|
2460
2650
|
const tabId = sender.tab.id;
|
|
2461
2651
|
|
|
2462
2652
|
// Store recording state and show notification
|
|
@@ -2480,14 +2670,14 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
|
2480
2670
|
}
|
|
2481
2671
|
|
|
2482
2672
|
if (request.action === 'deleteRecording') {
|
|
2483
|
-
console.log('Deleting recording:', request.recordingId);
|
|
2673
|
+
// console.log('Deleting recording:', request.recordingId);
|
|
2484
2674
|
deleteRecordingFromServer(request.recordingId, sendResponse);
|
|
2485
2675
|
return true;
|
|
2486
2676
|
}
|
|
2487
2677
|
|
|
2488
2678
|
// Workflow recording handlers
|
|
2489
2679
|
if (request.action === 'startWorkflowRecording') {
|
|
2490
|
-
console.log('Starting workflow recording for tab:', request.tabId);
|
|
2680
|
+
// console.log('Starting workflow recording for tab:', request.tabId);
|
|
2491
2681
|
startWorkflowRecording(
|
|
2492
2682
|
request.tabId,
|
|
2493
2683
|
request.includeLogsInExport,
|
|
@@ -2504,7 +2694,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
|
2504
2694
|
|
|
2505
2695
|
if (request.action === 'stopWorkflowRecording') {
|
|
2506
2696
|
const tabId = request.tabId || sender.tab?.id;
|
|
2507
|
-
console.log('Stopping workflow recording for tab:', tabId);
|
|
2697
|
+
// console.log('Stopping workflow recording for tab:', tabId);
|
|
2508
2698
|
// stopWorkflowRecording already returns { success: true, workflow: {...}, savedToServer: bool }
|
|
2509
2699
|
// so we pass it through directly - don't double-wrap!
|
|
2510
2700
|
stopWorkflowRecording(tabId).then(async (result) => {
|
|
@@ -2600,7 +2790,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
|
2600
2790
|
frameIndex: frameIndex
|
|
2601
2791
|
};
|
|
2602
2792
|
screenInteractions.push(interaction);
|
|
2603
|
-
console.log('Screen interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
|
|
2793
|
+
// console.log('Screen interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
|
|
2604
2794
|
}
|
|
2605
2795
|
}).catch(error => {
|
|
2606
2796
|
console.error('Error validating recording state for screen interaction:', error);
|
|
@@ -2613,7 +2803,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
|
2613
2803
|
frameIndex: frameCounter.get(currentRecordingSessionId) || 0
|
|
2614
2804
|
};
|
|
2615
2805
|
screenInteractions.push(interaction);
|
|
2616
|
-
console.log('Screen interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
|
|
2806
|
+
// console.log('Screen interaction recorded:', interaction.type, 'Total:', screenInteractions.length);
|
|
2617
2807
|
}
|
|
2618
2808
|
}
|
|
2619
2809
|
}
|
|
@@ -2729,18 +2919,18 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
|
2729
2919
|
|
|
2730
2920
|
// Handle workflow screenshot capture
|
|
2731
2921
|
if (request.action === 'captureWorkflowScreenshot' && sender.tab) {
|
|
2732
|
-
console.log('[SCREENSHOT-DEBUG] background.js - Received captureWorkflowScreenshot message');
|
|
2922
|
+
// console.log('[SCREENSHOT-DEBUG] background.js - Received captureWorkflowScreenshot message');
|
|
2733
2923
|
const tabId = sender.tab.id;
|
|
2734
2924
|
const settings = request.settings || {};
|
|
2735
|
-
console.log('[SCREENSHOT-DEBUG] background.js - tabId:', tabId);
|
|
2736
|
-
console.log('[SCREENSHOT-DEBUG] background.js - settings:', JSON.stringify(settings));
|
|
2925
|
+
// console.log('[SCREENSHOT-DEBUG] background.js - tabId:', tabId);
|
|
2926
|
+
// console.log('[SCREENSHOT-DEBUG] background.js - settings:', JSON.stringify(settings));
|
|
2737
2927
|
|
|
2738
2928
|
captureTabScreenshot(tabId, settings).then((screenshotData) => {
|
|
2739
|
-
console.log('[SCREENSHOT-DEBUG] background.js - captureTabScreenshot succeeded');
|
|
2740
|
-
console.log('[SCREENSHOT-DEBUG] background.js - screenshotData type:', typeof screenshotData);
|
|
2741
|
-
console.log('[SCREENSHOT-DEBUG] background.js - screenshotData length:', screenshotData?.length);
|
|
2742
|
-
console.log('[SCREENSHOT-DEBUG] background.js - screenshotData preview:', screenshotData?.substring(0, 100));
|
|
2743
|
-
console.log('[SCREENSHOT-DEBUG] background.js - Sending response with success: true');
|
|
2929
|
+
// console.log('[SCREENSHOT-DEBUG] background.js - captureTabScreenshot succeeded');
|
|
2930
|
+
// console.log('[SCREENSHOT-DEBUG] background.js - screenshotData type:', typeof screenshotData);
|
|
2931
|
+
// console.log('[SCREENSHOT-DEBUG] background.js - screenshotData length:', screenshotData?.length);
|
|
2932
|
+
// console.log('[SCREENSHOT-DEBUG] background.js - screenshotData preview:', screenshotData?.substring(0, 100));
|
|
2933
|
+
// console.log('[SCREENSHOT-DEBUG] background.js - Sending response with success: true');
|
|
2744
2934
|
sendResponse({ success: true, screenshotData });
|
|
2745
2935
|
}).catch((error) => {
|
|
2746
2936
|
console.error('[SCREENSHOT-DEBUG] background.js - captureTabScreenshot FAILED');
|
|
@@ -2774,7 +2964,7 @@ chrome.runtime.onMessage.addListener((request, sender, sendResponse) => {
|
|
|
2774
2964
|
/*
|
|
2775
2965
|
async function takeStandaloneSnapshot(tabId, note = '') {
|
|
2776
2966
|
try {
|
|
2777
|
-
console.log('Taking standalone snapshot for tab:', tabId);
|
|
2967
|
+
// console.log('Taking standalone snapshot for tab:', tabId);
|
|
2778
2968
|
|
|
2779
2969
|
// Create a unique session ID for the snapshot
|
|
2780
2970
|
const sessionId = `snapshot_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
@@ -2850,7 +3040,7 @@ async function takeStandaloneSnapshot(tabId, note = '') {
|
|
|
2850
3040
|
|
|
2851
3041
|
if (response.ok) {
|
|
2852
3042
|
const result = await response.json();
|
|
2853
|
-
console.log('Snapshot uploaded successfully:', sessionId);
|
|
3043
|
+
// console.log('Snapshot uploaded successfully:', sessionId);
|
|
2854
3044
|
uploadSuccess = true;
|
|
2855
3045
|
break;
|
|
2856
3046
|
}
|
|
@@ -2874,34 +3064,34 @@ async function takeStandaloneSnapshot(tabId, note = '') {
|
|
|
2874
3064
|
|
|
2875
3065
|
// Capture screenshot for workflow recording
|
|
2876
3066
|
async function captureTabScreenshot(tabId, settings) {
|
|
2877
|
-
console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - ENTRY');
|
|
2878
|
-
console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - tabId:', tabId);
|
|
2879
|
-
console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - settings:', JSON.stringify(settings));
|
|
3067
|
+
// console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - ENTRY');
|
|
3068
|
+
// console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - tabId:', tabId);
|
|
3069
|
+
// console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - settings:', JSON.stringify(settings));
|
|
2880
3070
|
|
|
2881
3071
|
try {
|
|
2882
3072
|
// Get the tab to find its window
|
|
2883
|
-
console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Getting tab info...');
|
|
3073
|
+
// console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Getting tab info...');
|
|
2884
3074
|
const tab = await chrome.tabs.get(tabId);
|
|
2885
3075
|
const windowId = tab.windowId;
|
|
2886
|
-
console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - windowId:', windowId);
|
|
2887
|
-
console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - tab.url:', tab.url);
|
|
3076
|
+
// console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - windowId:', windowId);
|
|
3077
|
+
// console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - tab.url:', tab.url);
|
|
2888
3078
|
|
|
2889
3079
|
const captureOptions = {
|
|
2890
3080
|
format: settings.format || 'jpeg',
|
|
2891
3081
|
quality: settings.quality || 30
|
|
2892
3082
|
};
|
|
2893
|
-
console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - captureOptions:', JSON.stringify(captureOptions));
|
|
2894
|
-
console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Calling chrome.tabs.captureVisibleTab...');
|
|
3083
|
+
// console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - captureOptions:', JSON.stringify(captureOptions));
|
|
3084
|
+
// console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Calling chrome.tabs.captureVisibleTab...');
|
|
2895
3085
|
|
|
2896
3086
|
const dataUrl = await chrome.tabs.captureVisibleTab(windowId, captureOptions);
|
|
2897
3087
|
|
|
2898
|
-
console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - captureVisibleTab SUCCESS');
|
|
2899
|
-
console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - dataUrl length:', dataUrl?.length);
|
|
2900
|
-
console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - dataUrl prefix:', dataUrl?.substring(0, 100));
|
|
3088
|
+
// console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - captureVisibleTab SUCCESS');
|
|
3089
|
+
// console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - dataUrl length:', dataUrl?.length);
|
|
3090
|
+
// console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - dataUrl prefix:', dataUrl?.substring(0, 100));
|
|
2901
3091
|
|
|
2902
3092
|
// If resolution is specified, resize the image
|
|
2903
3093
|
if (settings.maxWidth || settings.maxHeight) {
|
|
2904
|
-
console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Resizing required, maxWidth:', settings.maxWidth, 'maxHeight:', settings.maxHeight);
|
|
3094
|
+
// console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Resizing required, maxWidth:', settings.maxWidth, 'maxHeight:', settings.maxHeight);
|
|
2905
3095
|
// Create an image element to get dimensions
|
|
2906
3096
|
const img = new Image();
|
|
2907
3097
|
const canvas = new OffscreenCanvas(1, 1);
|
|
@@ -2941,8 +3131,8 @@ async function captureTabScreenshot(tabId, settings) {
|
|
|
2941
3131
|
});
|
|
2942
3132
|
}
|
|
2943
3133
|
|
|
2944
|
-
console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - No resize needed, returning dataUrl');
|
|
2945
|
-
console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Final dataUrl length:', dataUrl?.length);
|
|
3134
|
+
// console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - No resize needed, returning dataUrl');
|
|
3135
|
+
// console.log('[SCREENSHOT-DEBUG] captureTabScreenshot - Final dataUrl length:', dataUrl?.length);
|
|
2946
3136
|
return dataUrl;
|
|
2947
3137
|
} catch (error) {
|
|
2948
3138
|
console.error('[SCREENSHOT-DEBUG] captureTabScreenshot - EXCEPTION CAUGHT');
|
|
@@ -2956,7 +3146,7 @@ async function captureTabScreenshot(tabId, settings) {
|
|
|
2956
3146
|
// Start recording
|
|
2957
3147
|
// Detect if server is available (server mode vs browser-only mode)
|
|
2958
3148
|
async function detectServerMode() {
|
|
2959
|
-
console.log('[ServerDetection] Checking server availability...');
|
|
3149
|
+
// console.log('[ServerDetection] Checking server availability...');
|
|
2960
3150
|
|
|
2961
3151
|
for (const port of CONFIG_PORTS) {
|
|
2962
3152
|
try {
|
|
@@ -2970,7 +3160,7 @@ async function detectServerMode() {
|
|
|
2970
3160
|
]);
|
|
2971
3161
|
|
|
2972
3162
|
if (response.ok) {
|
|
2973
|
-
console.log(`[ServerDetection] Server detected on port ${port}`);
|
|
3163
|
+
// console.log(`[ServerDetection] Server detected on port ${port}`);
|
|
2974
3164
|
serverMode = 'server';
|
|
2975
3165
|
return 'server';
|
|
2976
3166
|
}
|
|
@@ -2979,7 +3169,7 @@ async function detectServerMode() {
|
|
|
2979
3169
|
}
|
|
2980
3170
|
}
|
|
2981
3171
|
|
|
2982
|
-
console.log('[ServerDetection] No server detected - using browser-only mode');
|
|
3172
|
+
// console.log('[ServerDetection] No server detected - using browser-only mode');
|
|
2983
3173
|
serverMode = 'browser-only';
|
|
2984
3174
|
return 'browser-only';
|
|
2985
3175
|
}
|
|
@@ -3007,7 +3197,7 @@ async function startRecording(tabId, settings = {}) {
|
|
|
3007
3197
|
try {
|
|
3008
3198
|
// Detect server mode before starting
|
|
3009
3199
|
await detectServerMode();
|
|
3010
|
-
console.log(`[Recording] Mode: ${serverMode}`);
|
|
3200
|
+
// console.log(`[Recording] Mode: ${serverMode}`);
|
|
3011
3201
|
|
|
3012
3202
|
// Check if session manager is available
|
|
3013
3203
|
if (!sessionManager) {
|
|
@@ -3028,12 +3218,12 @@ async function startRecording(tabId, settings = {}) {
|
|
|
3028
3218
|
|
|
3029
3219
|
// Start capturing console logs FIRST, before any other setup
|
|
3030
3220
|
const logsStarted = await startCapturingLogs(tabId);
|
|
3031
|
-
console.log('Console log capture started:', logsStarted);
|
|
3221
|
+
// console.log('Console log capture started:', logsStarted);
|
|
3032
3222
|
|
|
3033
3223
|
// Give console interception time to settle (increased from 100ms to 500ms for reliability)
|
|
3034
3224
|
if (logsStarted) {
|
|
3035
3225
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
3036
|
-
console.log('[Recording] Console interception ready');
|
|
3226
|
+
// console.log('[Recording] Console interception ready');
|
|
3037
3227
|
} else {
|
|
3038
3228
|
console.warn('[Recording] Console capture unavailable for this page - recording will proceed without console logs');
|
|
3039
3229
|
}
|
|
@@ -3046,7 +3236,7 @@ async function startRecording(tabId, settings = {}) {
|
|
|
3046
3236
|
targetTabId: tabId
|
|
3047
3237
|
});
|
|
3048
3238
|
|
|
3049
|
-
console.log('Got stream ID:', streamId);
|
|
3239
|
+
// console.log('Got stream ID:', streamId);
|
|
3050
3240
|
|
|
3051
3241
|
// Create session with session manager
|
|
3052
3242
|
const sessionConfig = {
|
|
@@ -3079,7 +3269,7 @@ async function startRecording(tabId, settings = {}) {
|
|
|
3079
3269
|
|
|
3080
3270
|
// STEP 4: Initialize browser-only recording if in browser-only mode
|
|
3081
3271
|
if (serverMode === 'browser-only' && browserRecordingManager) {
|
|
3082
|
-
console.log('[Recording] Initializing browser-only recording in IndexedDB');
|
|
3272
|
+
// console.log('[Recording] Initializing browser-only recording in IndexedDB');
|
|
3083
3273
|
const tab = await chrome.tabs.get(tabId);
|
|
3084
3274
|
await browserRecordingManager.startRecording(sessionId, {
|
|
3085
3275
|
tabId: tabId,
|
|
@@ -3112,7 +3302,19 @@ async function startRecording(tabId, settings = {}) {
|
|
|
3112
3302
|
// Update badge
|
|
3113
3303
|
chrome.action.setBadgeText({ text: 'REC' });
|
|
3114
3304
|
chrome.action.setBadgeBackgroundColor({ color: '#FF0000' });
|
|
3115
|
-
|
|
3305
|
+
|
|
3306
|
+
// DON'T start inactivity monitoring here - wait for countdownComplete message
|
|
3307
|
+
// This ensures the 10s timer starts AFTER the 3s visual countdown, not before
|
|
3308
|
+
// Set a fallback timer in case content script doesn't send countdownComplete
|
|
3309
|
+
inactivityMonitoringStarted = false;
|
|
3310
|
+
if (inactivityFallbackTimer) clearTimeout(inactivityFallbackTimer);
|
|
3311
|
+
inactivityFallbackTimer = setTimeout(async () => {
|
|
3312
|
+
// Use isCurrentlyRecording (the actual state variable)
|
|
3313
|
+
if (isCurrentlyRecording && !inactivityMonitoringStarted) {
|
|
3314
|
+
await startInactivityMonitoring(tabId);
|
|
3315
|
+
}
|
|
3316
|
+
}, 5000); // 5s = 3s countdown + 2s buffer
|
|
3317
|
+
|
|
3116
3318
|
// If on a restricted page, notify user
|
|
3117
3319
|
const tab = await chrome.tabs.get(tabId);
|
|
3118
3320
|
if (tab.url && (tab.url.startsWith('chrome://') || tab.url.startsWith('chrome-extension://'))) {
|
|
@@ -3133,12 +3335,12 @@ async function startRecording(tabId, settings = {}) {
|
|
|
3133
3335
|
sessionId: sessionId
|
|
3134
3336
|
}).catch(async (error) => {
|
|
3135
3337
|
// Content script might not be injected, try to inject it
|
|
3136
|
-
console.log('Could not notify content script, attempting to inject:', error);
|
|
3338
|
+
// console.log('Could not notify content script, attempting to inject:', error);
|
|
3137
3339
|
|
|
3138
3340
|
// First check if this tab allows content script injection
|
|
3139
3341
|
const tab = await chrome.tabs.get(tabId);
|
|
3140
3342
|
if (!tab.url || tab.url.startsWith('chrome://') || tab.url.startsWith('chrome-extension://') || tab.url.startsWith('moz-extension://')) {
|
|
3141
|
-
console.log('Cannot inject content script into restricted URL:', tab.url);
|
|
3343
|
+
// console.log('Cannot inject content script into restricted URL:', tab.url);
|
|
3142
3344
|
return;
|
|
3143
3345
|
}
|
|
3144
3346
|
|
|
@@ -3174,7 +3376,7 @@ async function startRecording(tabId, settings = {}) {
|
|
|
3174
3376
|
url: tab.url,
|
|
3175
3377
|
title: tab.title
|
|
3176
3378
|
});
|
|
3177
|
-
console.log('[Recording] Browser recording initialized for session:', sessionId);
|
|
3379
|
+
// console.log('[Recording] Browser recording initialized for session:', sessionId);
|
|
3178
3380
|
}
|
|
3179
3381
|
|
|
3180
3382
|
// Send stream ID, session info, and settings to offscreen document for frame capture
|
|
@@ -3194,7 +3396,7 @@ async function startRecording(tabId, settings = {}) {
|
|
|
3194
3396
|
}
|
|
3195
3397
|
});
|
|
3196
3398
|
|
|
3197
|
-
console.log('Recording started in', serverMode, 'mode');
|
|
3399
|
+
// console.log('Recording started in', serverMode, 'mode');
|
|
3198
3400
|
} catch (error) {
|
|
3199
3401
|
console.error('Error in startRecording:', error);
|
|
3200
3402
|
throw error;
|
|
@@ -3213,13 +3415,16 @@ async function stopRecording() {
|
|
|
3213
3415
|
// Check if currently recording via session manager
|
|
3214
3416
|
const currentlyRecording = await isCurrentlyRecordingAsync();
|
|
3215
3417
|
if (!currentlyRecording) {
|
|
3216
|
-
console.log('No active recording session to stop');
|
|
3418
|
+
// console.log('No active recording session to stop');
|
|
3217
3419
|
return { success: false, error: 'No active recording' };
|
|
3218
3420
|
}
|
|
3219
3421
|
|
|
3220
3422
|
// Store sessionId before clearing it
|
|
3221
3423
|
const stoppedSessionId = currentSession?.sessionId;
|
|
3222
3424
|
|
|
3425
|
+
// Stop inactivity monitoring
|
|
3426
|
+
await stopInactivityMonitoring(recordingTabId);
|
|
3427
|
+
|
|
3223
3428
|
// Capture frame count and duration for the response
|
|
3224
3429
|
let recordedFrameCount = 0;
|
|
3225
3430
|
let recordedDuration = 0;
|
|
@@ -3233,11 +3438,11 @@ async function stopRecording() {
|
|
|
3233
3438
|
} else {
|
|
3234
3439
|
recordedFrameCount = stopResult.frameCount || 0;
|
|
3235
3440
|
recordedDuration = stopResult.sessionDuration || 0;
|
|
3236
|
-
console.log(`Recording stopped. Duration: ${recordedDuration}ms, Frames: ${recordedFrameCount}`);
|
|
3441
|
+
// console.log(`Recording stopped. Duration: ${recordedDuration}ms, Frames: ${recordedFrameCount}`);
|
|
3237
3442
|
|
|
3238
3443
|
// Finalize browser-only recording if in browser-only mode
|
|
3239
3444
|
if (serverMode === 'browser-only' && browserRecordingManager) {
|
|
3240
|
-
console.log('[Browser-Only] Finalizing browser recording in IndexedDB');
|
|
3445
|
+
// console.log('[Browser-Only] Finalizing browser recording in IndexedDB');
|
|
3241
3446
|
await browserRecordingManager.stopRecording(currentSession.sessionId);
|
|
3242
3447
|
}
|
|
3243
3448
|
}
|
|
@@ -3248,10 +3453,10 @@ async function stopRecording() {
|
|
|
3248
3453
|
let flushCompleted = false;
|
|
3249
3454
|
if (logBuffer) {
|
|
3250
3455
|
try {
|
|
3251
|
-
console.log('[Background] Flushing all buffered logs before stop...');
|
|
3456
|
+
// console.log('[Background] Flushing all buffered logs before stop...');
|
|
3252
3457
|
await logBuffer.flushAll();
|
|
3253
3458
|
flushCompleted = true;
|
|
3254
|
-
console.log('[Background] Successfully flushed all buffered logs');
|
|
3459
|
+
// console.log('[Background] Successfully flushed all buffered logs');
|
|
3255
3460
|
} catch (flushError) {
|
|
3256
3461
|
console.error('[Background] Failed to flush logs during stop:', flushError);
|
|
3257
3462
|
// Continue with stop process even if flush fails
|
|
@@ -3271,25 +3476,25 @@ async function stopRecording() {
|
|
|
3271
3476
|
|
|
3272
3477
|
// CRITICAL: Store recordingTabId BEFORE clearing it (for cleanup)
|
|
3273
3478
|
const previousRecordingTabId = recordingTabId;
|
|
3274
|
-
console.log('[Background] previousRecordingTabId:', previousRecordingTabId, 'stoppedSessionId:', stoppedSessionId);
|
|
3479
|
+
// console.log('[Background] previousRecordingTabId:', previousRecordingTabId, 'stoppedSessionId:', stoppedSessionId);
|
|
3275
3480
|
|
|
3276
3481
|
// CRITICAL FIX: Send stop-screen-capture-tracking message to recording tab WITH sessionId
|
|
3277
3482
|
// so it can show the completion UI
|
|
3278
3483
|
if (previousRecordingTabId && stoppedSessionId) {
|
|
3279
3484
|
try {
|
|
3280
|
-
console.log('[Background] Sending recording-complete-show-ui message to tab:', previousRecordingTabId, 'with sessionId:', stoppedSessionId);
|
|
3485
|
+
// console.log('[Background] Sending recording-complete-show-ui message to tab:', previousRecordingTabId, 'with sessionId:', stoppedSessionId);
|
|
3281
3486
|
await chrome.tabs.sendMessage(previousRecordingTabId, {
|
|
3282
3487
|
type: 'recording-complete-show-ui',
|
|
3283
3488
|
sessionId: stoppedSessionId
|
|
3284
3489
|
}).catch((err) => {
|
|
3285
|
-
console.log('[Background] Could not send completion UI message to recording tab:', err);
|
|
3490
|
+
// console.log('[Background] Could not send completion UI message to recording tab:', err);
|
|
3286
3491
|
});
|
|
3287
|
-
console.log('[Background] Successfully sent recording-complete-show-ui message');
|
|
3492
|
+
// console.log('[Background] Successfully sent recording-complete-show-ui message');
|
|
3288
3493
|
} catch (error) {
|
|
3289
3494
|
console.error('[Background] Failed to send completion UI message:', error);
|
|
3290
3495
|
}
|
|
3291
3496
|
} else {
|
|
3292
|
-
console.log('[Background] NOT sending recording-complete-show-ui - missing previousRecordingTabId or stoppedSessionId');
|
|
3497
|
+
// console.log('[Background] NOT sending recording-complete-show-ui - missing previousRecordingTabId or stoppedSessionId');
|
|
3293
3498
|
}
|
|
3294
3499
|
|
|
3295
3500
|
// CRITICAL FIX: Send stop-screen-capture-tracking message to ALL content scripts
|
|
@@ -3301,13 +3506,13 @@ async function stopRecording() {
|
|
|
3301
3506
|
type: 'stop-screen-capture-tracking'
|
|
3302
3507
|
}).catch(() => {
|
|
3303
3508
|
// Ignore errors for tabs that don't have content scripts
|
|
3304
|
-
console.log(`[Background] Could not send cleanup message to tab ${tab.id}`);
|
|
3509
|
+
// console.log(`[Background] Could not send cleanup message to tab ${tab.id}`);
|
|
3305
3510
|
});
|
|
3306
3511
|
}
|
|
3307
3512
|
return Promise.resolve();
|
|
3308
3513
|
});
|
|
3309
3514
|
await Promise.all(cleanupPromises);
|
|
3310
|
-
console.log('[Background] Cleanup messages sent to all content scripts');
|
|
3515
|
+
// console.log('[Background] Cleanup messages sent to all content scripts');
|
|
3311
3516
|
} catch (error) {
|
|
3312
3517
|
console.error('[Background] Failed to send cleanup messages to content scripts:', error);
|
|
3313
3518
|
}
|
|
@@ -3315,7 +3520,7 @@ async function stopRecording() {
|
|
|
3315
3520
|
// CRITICAL FIX: Restore original console methods and remove event listeners
|
|
3316
3521
|
if (previousRecordingTabId) {
|
|
3317
3522
|
try {
|
|
3318
|
-
console.log('[Background] Stopping console log capture for tab:', previousRecordingTabId);
|
|
3523
|
+
// console.log('[Background] Stopping console log capture for tab:', previousRecordingTabId);
|
|
3319
3524
|
await stopCapturingLogs(previousRecordingTabId);
|
|
3320
3525
|
} catch (cleanupError) {
|
|
3321
3526
|
console.error('[Background] Failed to cleanup console interceptor:', cleanupError);
|
|
@@ -3339,11 +3544,11 @@ async function stopRecording() {
|
|
|
3339
3544
|
|
|
3340
3545
|
// CRITICAL: Clear pending frame queue to prevent infinite retry loop
|
|
3341
3546
|
if (stoppedSessionId && pendingFrameQueue.has(stoppedSessionId)) {
|
|
3342
|
-
console.log(`[FrameQueue] Clearing ${pendingFrameQueue.get(stoppedSessionId).length} pending frames for stopped session ${stoppedSessionId}`);
|
|
3547
|
+
// console.log(`[FrameQueue] Clearing ${pendingFrameQueue.get(stoppedSessionId).length} pending frames for stopped session ${stoppedSessionId}`);
|
|
3343
3548
|
pendingFrameQueue.delete(stoppedSessionId);
|
|
3344
3549
|
}
|
|
3345
3550
|
|
|
3346
|
-
console.log('Stop message sent to offscreen document');
|
|
3551
|
+
// console.log('Stop message sent to offscreen document');
|
|
3347
3552
|
|
|
3348
3553
|
// Notify popup to refresh recordings list
|
|
3349
3554
|
chrome.runtime.sendMessage({
|
|
@@ -3351,7 +3556,7 @@ async function stopRecording() {
|
|
|
3351
3556
|
sessionId: stoppedSessionId
|
|
3352
3557
|
}).catch(() => {
|
|
3353
3558
|
// Popup might not be open, that's okay
|
|
3354
|
-
console.log('[Background] Popup not available to notify of recording stop');
|
|
3559
|
+
// console.log('[Background] Popup not available to notify of recording stop');
|
|
3355
3560
|
});
|
|
3356
3561
|
|
|
3357
3562
|
// Format duration as human-readable string (e.g., "1m 30s" or "45s")
|
|
@@ -3380,7 +3585,7 @@ async function stopRecording() {
|
|
|
3380
3585
|
// CRITICAL FIX: Clean up console interceptor even on error
|
|
3381
3586
|
if (errorRecordingTabId) {
|
|
3382
3587
|
try {
|
|
3383
|
-
console.log('[Background] Emergency cleanup of console interceptor for tab:', errorRecordingTabId);
|
|
3588
|
+
// console.log('[Background] Emergency cleanup of console interceptor for tab:', errorRecordingTabId);
|
|
3384
3589
|
await stopCapturingLogs(errorRecordingTabId);
|
|
3385
3590
|
} catch (cleanupError) {
|
|
3386
3591
|
console.error('[Background] Failed to cleanup console interceptor during error handling:', cleanupError);
|
|
@@ -3407,25 +3612,25 @@ async function stopRecording() {
|
|
|
3407
3612
|
// Capture console logs from the recording tab
|
|
3408
3613
|
// REFACTORED: Now uses shared console-interception-library.js
|
|
3409
3614
|
async function startCapturingLogs(tabId) {
|
|
3410
|
-
console.log('[Screen Recording] Starting console interception using shared library');
|
|
3615
|
+
// console.log('[Screen Recording] Starting console interception using shared library');
|
|
3411
3616
|
return await self.ConsoleInterceptionLibrary.startConsoleInterception(tabId, SCREEN_RECORDING_CONSOLE_CONFIG);
|
|
3412
3617
|
}
|
|
3413
3618
|
|
|
3414
3619
|
// REFACTORED: Now uses shared console-interception-library.js via proper namespace
|
|
3415
3620
|
async function stopCapturingLogs(tabId) {
|
|
3416
|
-
console.log('[Screen Recording] Stopping console interception using shared library');
|
|
3621
|
+
// console.log('[Screen Recording] Stopping console interception using shared library');
|
|
3417
3622
|
return await self.ConsoleInterceptionLibrary.stopConsoleInterception(tabId, SCREEN_RECORDING_CONSOLE_CONFIG);
|
|
3418
3623
|
}
|
|
3419
3624
|
|
|
3420
3625
|
// Workflow Recording Functions
|
|
3421
3626
|
async function startWorkflowRecording(tabId, includeLogsInExport, sessionName = null, screenshotSettings = null) {
|
|
3422
3627
|
try {
|
|
3423
|
-
console.log('Starting workflow recording for tab:', tabId);
|
|
3628
|
+
// console.log('Starting workflow recording for tab:', tabId);
|
|
3424
3629
|
|
|
3425
3630
|
// Check if this tab allows content script injection
|
|
3426
3631
|
const tab = await chrome.tabs.get(tabId);
|
|
3427
3632
|
if (!tab.url || tab.url.startsWith('chrome://') || tab.url.startsWith('chrome-extension://') || tab.url.startsWith('moz-extension://')) {
|
|
3428
|
-
console.log('Cannot start workflow recording on restricted URL:', tab.url);
|
|
3633
|
+
// console.log('Cannot start workflow recording on restricted URL:', tab.url);
|
|
3429
3634
|
throw new Error('Cannot record workflows on restricted pages (chrome:// URLs)');
|
|
3430
3635
|
}
|
|
3431
3636
|
|
|
@@ -3446,7 +3651,7 @@ async function startWorkflowRecording(tabId, includeLogsInExport, sessionName =
|
|
|
3446
3651
|
if (includeLogsInExport) {
|
|
3447
3652
|
const buffer = new WorkflowLogBuffer(tabId);
|
|
3448
3653
|
workflowLogBuffers.set(tabId, buffer);
|
|
3449
|
-
console.log(`[Workflow] Initialized WorkflowLogBuffer for tab ${tabId}`);
|
|
3654
|
+
// console.log(`[Workflow] Initialized WorkflowLogBuffer for tab ${tabId}`);
|
|
3450
3655
|
}
|
|
3451
3656
|
|
|
3452
3657
|
// REFACTORED: Use shared console interception library via proper namespace (replaces 150+ lines of duplicate code)
|
|
@@ -3464,7 +3669,7 @@ async function startWorkflowRecording(tabId, includeLogsInExport, sessionName =
|
|
|
3464
3669
|
});
|
|
3465
3670
|
} catch (e) {
|
|
3466
3671
|
// Content script might already be injected
|
|
3467
|
-
console.log('Content script injection attempt:', e.message);
|
|
3672
|
+
// console.log('Content script injection attempt:', e.message);
|
|
3468
3673
|
}
|
|
3469
3674
|
|
|
3470
3675
|
// Tell the content script to start recording
|
|
@@ -3475,7 +3680,7 @@ async function startWorkflowRecording(tabId, includeLogsInExport, sessionName =
|
|
|
3475
3680
|
tabId: tabId
|
|
3476
3681
|
});
|
|
3477
3682
|
|
|
3478
|
-
console.log('Workflow recording started successfully');
|
|
3683
|
+
// console.log('Workflow recording started successfully');
|
|
3479
3684
|
} catch (error) {
|
|
3480
3685
|
console.error('Error starting workflow recording:', error);
|
|
3481
3686
|
throw error;
|
|
@@ -3484,7 +3689,7 @@ async function startWorkflowRecording(tabId, includeLogsInExport, sessionName =
|
|
|
3484
3689
|
|
|
3485
3690
|
async function stopWorkflowRecording(tabId) {
|
|
3486
3691
|
try {
|
|
3487
|
-
console.log('Stopping workflow recording for tab:', tabId);
|
|
3692
|
+
// console.log('Stopping workflow recording for tab:', tabId);
|
|
3488
3693
|
|
|
3489
3694
|
// Check if recording was active
|
|
3490
3695
|
if (!workflowRecordingTabs.has(tabId)) {
|
|
@@ -3503,7 +3708,7 @@ async function stopWorkflowRecording(tabId) {
|
|
|
3503
3708
|
|
|
3504
3709
|
// CRITICAL FIX: Restore original console methods and remove event listeners
|
|
3505
3710
|
try {
|
|
3506
|
-
console.log('[Workflow] Stopping console log capture for tab:', tabId);
|
|
3711
|
+
// console.log('[Workflow] Stopping console log capture for tab:', tabId);
|
|
3507
3712
|
await stopCapturingWorkflowLogs(tabId);
|
|
3508
3713
|
} catch (cleanupError) {
|
|
3509
3714
|
console.error('[Workflow] Failed to cleanup console interceptor:', cleanupError);
|
|
@@ -3515,19 +3720,19 @@ async function stopWorkflowRecording(tabId) {
|
|
|
3515
3720
|
let workflow = Array.isArray(workflowData) ? workflowData : (workflowData.actions || []);
|
|
3516
3721
|
let functionTraces = Array.isArray(workflowData) ? [] : (workflowData.functionTraces || []);
|
|
3517
3722
|
|
|
3518
|
-
console.log(`[Background] Received ${workflow.length} actions and ${functionTraces.length} function traces`);
|
|
3519
|
-
console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Checking actions for screenshot_data');
|
|
3723
|
+
// console.log(`[Background] Received ${workflow.length} actions and ${functionTraces.length} function traces`);
|
|
3724
|
+
// console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Checking actions for screenshot_data');
|
|
3520
3725
|
|
|
3521
3726
|
const actionsWithScreenshots = workflow.filter(a => a.screenshot_data);
|
|
3522
|
-
console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Actions WITH screenshot_data:', actionsWithScreenshots.length);
|
|
3727
|
+
// console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Actions WITH screenshot_data:', actionsWithScreenshots.length);
|
|
3523
3728
|
|
|
3524
3729
|
workflow.forEach((action, index) => {
|
|
3525
|
-
console.log(`[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Action ${index}:`, {
|
|
3526
|
-
|
|
3527
|
-
|
|
3528
|
-
|
|
3529
|
-
|
|
3530
|
-
});
|
|
3730
|
+
// console.log(`[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Action ${index}:`, {
|
|
3731
|
+
// type: action.type,
|
|
3732
|
+
// hasScreenshotData: !!action.screenshot_data,
|
|
3733
|
+
// screenshotDataLength: action.screenshot_data?.length,
|
|
3734
|
+
// screenshotPreview: action.screenshot_data?.substring(0, 50)
|
|
3735
|
+
// });
|
|
3531
3736
|
});
|
|
3532
3737
|
|
|
3533
3738
|
// If logs should be included, flush buffer and get them from session storage
|
|
@@ -3536,7 +3741,7 @@ async function stopWorkflowRecording(tabId) {
|
|
|
3536
3741
|
const buffer = workflowLogBuffers.get(tabId);
|
|
3537
3742
|
if (buffer) {
|
|
3538
3743
|
await buffer.flush();
|
|
3539
|
-
console.log(`[Workflow] Flushed buffer before retrieval, stats:`, buffer.getStats());
|
|
3744
|
+
// console.log(`[Workflow] Flushed buffer before retrieval, stats:`, buffer.getStats());
|
|
3540
3745
|
}
|
|
3541
3746
|
|
|
3542
3747
|
const result = await chrome.storage.session.get(`workflow_${tabId}`);
|
|
@@ -3585,7 +3790,7 @@ async function stopWorkflowRecording(tabId) {
|
|
|
3585
3790
|
if (bufferToCleanup) {
|
|
3586
3791
|
await bufferToCleanup.cleanup();
|
|
3587
3792
|
workflowLogBuffers.delete(tabId);
|
|
3588
|
-
console.log(`[Workflow] Cleaned up WorkflowLogBuffer for tab ${tabId}`);
|
|
3793
|
+
// console.log(`[Workflow] Cleaned up WorkflowLogBuffer for tab ${tabId}`);
|
|
3589
3794
|
}
|
|
3590
3795
|
|
|
3591
3796
|
await chrome.storage.session.remove(`workflow_${tabId}`);
|
|
@@ -3597,7 +3802,7 @@ async function stopWorkflowRecording(tabId) {
|
|
|
3597
3802
|
workflowStartTime: null
|
|
3598
3803
|
});
|
|
3599
3804
|
|
|
3600
|
-
console.log('Workflow recording stopped, returning workflow:', workflow);
|
|
3805
|
+
// console.log('Workflow recording stopped, returning workflow:', workflow);
|
|
3601
3806
|
|
|
3602
3807
|
// Try to save to server
|
|
3603
3808
|
try {
|
|
@@ -3610,11 +3815,11 @@ async function stopWorkflowRecording(tabId) {
|
|
|
3610
3815
|
// Retrieve the workflow ID that was generated at start
|
|
3611
3816
|
const storedData = await chrome.storage.local.get(['currentWorkflowId']);
|
|
3612
3817
|
const sessionId = storedData.currentWorkflowId || `workflow_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
|
|
3613
|
-
console.log('[Workflow] Using sessionId for save:', sessionId);
|
|
3818
|
+
// console.log('[Workflow] Using sessionId for save:', sessionId);
|
|
3614
3819
|
|
|
3615
3820
|
for (const port of serverPorts) {
|
|
3616
3821
|
try {
|
|
3617
|
-
console.log(`[Workflow] Attempting to save to server on port ${port}...`);
|
|
3822
|
+
// console.log(`[Workflow] Attempting to save to server on port ${port}...`);
|
|
3618
3823
|
|
|
3619
3824
|
const payloadData = {
|
|
3620
3825
|
sessionId: sessionId,
|
|
@@ -3628,19 +3833,19 @@ async function stopWorkflowRecording(tabId) {
|
|
|
3628
3833
|
functionTraces: functionTraces // Include function execution traces
|
|
3629
3834
|
};
|
|
3630
3835
|
|
|
3631
|
-
console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - HTTP POST payload being prepared');
|
|
3632
|
-
console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Payload actions count:', payloadData.actions.length);
|
|
3836
|
+
// console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - HTTP POST payload being prepared');
|
|
3837
|
+
// console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Payload actions count:', payloadData.actions.length);
|
|
3633
3838
|
|
|
3634
3839
|
const payloadActionsWithScreenshots = payloadData.actions.filter(a => a.screenshot_data);
|
|
3635
|
-
console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Payload actions WITH screenshot_data:', payloadActionsWithScreenshots.length);
|
|
3840
|
+
// console.log('[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Payload actions WITH screenshot_data:', payloadActionsWithScreenshots.length);
|
|
3636
3841
|
|
|
3637
3842
|
payloadData.actions.forEach((action, index) => {
|
|
3638
|
-
console.log(`[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Payload Action ${index}:`, {
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3642
|
-
|
|
3643
|
-
});
|
|
3843
|
+
// console.log(`[SCREENSHOT-DEBUG] background.stopWorkflowRecording - Payload Action ${index}:`, {
|
|
3844
|
+
// type: action.type,
|
|
3845
|
+
// hasScreenshotData: !!action.screenshot_data,
|
|
3846
|
+
// screenshotDataLength: action.screenshot_data?.length,
|
|
3847
|
+
// screenshotPreview: action.screenshot_data?.substring(0, 50)
|
|
3848
|
+
// });
|
|
3644
3849
|
});
|
|
3645
3850
|
|
|
3646
3851
|
const response = await fetch(`http://localhost:${port}/chromedebug/workflow-recording`, {
|
|
@@ -3653,15 +3858,15 @@ async function stopWorkflowRecording(tabId) {
|
|
|
3653
3858
|
|
|
3654
3859
|
if (response.ok) {
|
|
3655
3860
|
serverResult = await response.json();
|
|
3656
|
-
console.log(`[Workflow] Successfully saved to server on port ${port}`, serverResult);
|
|
3861
|
+
// console.log(`[Workflow] Successfully saved to server on port ${port}`, serverResult);
|
|
3657
3862
|
break;
|
|
3658
3863
|
} else {
|
|
3659
|
-
console.log(`[Workflow] Failed on port ${port}: ${response.status} ${response.statusText}`);
|
|
3864
|
+
// console.log(`[Workflow] Failed on port ${port}: ${response.status} ${response.statusText}`);
|
|
3660
3865
|
const errorText = await response.text();
|
|
3661
|
-
console.log(`[Workflow] Error response:`, errorText);
|
|
3866
|
+
// console.log(`[Workflow] Error response:`, errorText);
|
|
3662
3867
|
}
|
|
3663
3868
|
} catch (error) {
|
|
3664
|
-
console.log(`Failed to save to server on port ${port}:`, error.message);
|
|
3869
|
+
// console.log(`Failed to save to server on port ${port}:`, error.message);
|
|
3665
3870
|
}
|
|
3666
3871
|
}
|
|
3667
3872
|
|
|
@@ -3725,7 +3930,7 @@ async function stopWorkflowRecording(tabId) {
|
|
|
3725
3930
|
// CRITICAL FIX: Stop workflow console log capture and restore original methods
|
|
3726
3931
|
// REFACTORED: Now uses shared console-interception-library.js via proper namespace
|
|
3727
3932
|
async function stopCapturingWorkflowLogs(tabId) {
|
|
3728
|
-
console.log('[Workflow Recording] Stopping console interception using shared library');
|
|
3933
|
+
// console.log('[Workflow Recording] Stopping console interception using shared library');
|
|
3729
3934
|
return await self.ConsoleInterceptionLibrary.stopConsoleInterception(tabId, WORKFLOW_RECORDING_CONSOLE_CONFIG);
|
|
3730
3935
|
}
|
|
3731
3936
|
|
|
@@ -3764,7 +3969,7 @@ async function deleteRecordingFromServer(recordingId, sendResponse) {
|
|
|
3764
3969
|
|
|
3765
3970
|
if (deleteResult.success) {
|
|
3766
3971
|
deleted = true;
|
|
3767
|
-
console.log('Recording deleted successfully');
|
|
3972
|
+
// console.log('Recording deleted successfully');
|
|
3768
3973
|
sendResponse({ success: true });
|
|
3769
3974
|
return;
|
|
3770
3975
|
} else {
|
|
@@ -3786,11 +3991,11 @@ async function retryPendingFrames(sessionId) {
|
|
|
3786
3991
|
const pending = pendingFrameQueue.get(sessionId);
|
|
3787
3992
|
if (!pending || pending.length === 0) return;
|
|
3788
3993
|
|
|
3789
|
-
console.log(`[FrameQueue] Retrying ${pending.length} pending frame batches for session ${sessionId}`);
|
|
3994
|
+
// console.log(`[FrameQueue] Retrying ${pending.length} pending frame batches for session ${sessionId}`);
|
|
3790
3995
|
|
|
3791
3996
|
// Check if this is still the active recording session
|
|
3792
3997
|
if (currentSession?.sessionId !== sessionId) {
|
|
3793
|
-
console.log(`[FrameQueue] Session ${sessionId} is no longer active, clearing pending frames`);
|
|
3998
|
+
// console.log(`[FrameQueue] Session ${sessionId} is no longer active, clearing pending frames`);
|
|
3794
3999
|
pendingFrameQueue.delete(sessionId);
|
|
3795
4000
|
return;
|
|
3796
4001
|
}
|
|
@@ -3822,12 +4027,12 @@ async function retryPendingFrames(sessionId) {
|
|
|
3822
4027
|
await handleFrameBatch({ sessionId, frames }, true); // skipValidation=true
|
|
3823
4028
|
}
|
|
3824
4029
|
|
|
3825
|
-
console.log(`[FrameQueue] Successfully processed ${batches.length} pending batches`);
|
|
4030
|
+
// console.log(`[FrameQueue] Successfully processed ${batches.length} pending batches`);
|
|
3826
4031
|
}
|
|
3827
4032
|
|
|
3828
4033
|
// Handle frame batches from frame capture
|
|
3829
4034
|
async function handleFrameBatch(batchData, skipValidation = false) {
|
|
3830
|
-
console.log(`Processing frame batch for session ${batchData.sessionId}`);
|
|
4035
|
+
// console.log(`Processing frame batch for session ${batchData.sessionId}`);
|
|
3831
4036
|
|
|
3832
4037
|
try {
|
|
3833
4038
|
const sessionId = batchData.sessionId;
|
|
@@ -3881,7 +4086,7 @@ async function handleFrameBatch(batchData, skipValidation = false) {
|
|
|
3881
4086
|
frameCounter.set(sessionId, currentFrameIndex);
|
|
3882
4087
|
}
|
|
3883
4088
|
|
|
3884
|
-
console.log(`Assigning frame indices ${frameCounter.get(sessionId) - indexedFrames.length} to ${currentFrameIndex - 1}`);
|
|
4089
|
+
// console.log(`Assigning frame indices ${frameCounter.get(sessionId) - indexedFrames.length} to ${currentFrameIndex - 1}`);
|
|
3885
4090
|
|
|
3886
4091
|
// Find available server port using settings
|
|
3887
4092
|
const ports = await getServerPorts();
|
|
@@ -3907,7 +4112,7 @@ async function handleFrameBatch(batchData, skipValidation = false) {
|
|
|
3907
4112
|
|
|
3908
4113
|
if (uploadResponse.ok) {
|
|
3909
4114
|
const result = await uploadResponse.json();
|
|
3910
|
-
console.log(`Frame batch uploaded successfully to port ${port}:`, result);
|
|
4115
|
+
// console.log(`Frame batch uploaded successfully to port ${port}:`, result);
|
|
3911
4116
|
recordingServerPort = port; // Store the successful port
|
|
3912
4117
|
uploadSuccess = true;
|
|
3913
4118
|
|
|
@@ -3923,8 +4128,20 @@ async function handleFrameBatch(batchData, skipValidation = false) {
|
|
|
3923
4128
|
// Append new frames
|
|
3924
4129
|
sessionData.frames = sessionData.frames.concat(batchData.frames);
|
|
3925
4130
|
await chrome.storage.local.set({ [storageKey]: sessionData });
|
|
3926
|
-
console.log(`Saved ${batchData.frames.length} frames to local storage, total: ${sessionData.frames.length}`);
|
|
3927
|
-
|
|
4131
|
+
// console.log(`Saved ${batchData.frames.length} frames to local storage, total: ${sessionData.frames.length}`);
|
|
4132
|
+
|
|
4133
|
+
// Send frame count update to content script
|
|
4134
|
+
if (recordingTabId) {
|
|
4135
|
+
try {
|
|
4136
|
+
await chrome.tabs.sendMessage(recordingTabId, {
|
|
4137
|
+
action: 'updateFrameCount',
|
|
4138
|
+
frameCount: sessionData.frames.length
|
|
4139
|
+
});
|
|
4140
|
+
} catch (e) {
|
|
4141
|
+
// Tab might be closed, ignore
|
|
4142
|
+
}
|
|
4143
|
+
}
|
|
4144
|
+
|
|
3928
4145
|
break;
|
|
3929
4146
|
} else {
|
|
3930
4147
|
const errorText = await uploadResponse.text();
|
|
@@ -3933,16 +4150,16 @@ async function handleFrameBatch(batchData, skipValidation = false) {
|
|
|
3933
4150
|
}
|
|
3934
4151
|
} catch (e) {
|
|
3935
4152
|
lastError = e.message;
|
|
3936
|
-
console.log(`Failed to upload frame batch to port ${port}:`, e.message);
|
|
4153
|
+
// console.log(`Failed to upload frame batch to port ${port}:`, e.message);
|
|
3937
4154
|
}
|
|
3938
4155
|
}
|
|
3939
4156
|
|
|
3940
4157
|
if (!uploadSuccess) {
|
|
3941
|
-
console.log(`No server available - checking if browser-only mode`);
|
|
4158
|
+
// console.log(`No server available - checking if browser-only mode`);
|
|
3942
4159
|
|
|
3943
4160
|
// If in browser-only mode, store frames in IndexedDB
|
|
3944
4161
|
if (serverMode === 'browser-only' && browserRecordingManager) {
|
|
3945
|
-
console.log(`[Browser-Only] Storing ${indexedFrames.length} frames in IndexedDB`);
|
|
4162
|
+
// console.log(`[Browser-Only] Storing ${indexedFrames.length} frames in IndexedDB`);
|
|
3946
4163
|
// Use the browser recording session ID, not the frame capture session ID
|
|
3947
4164
|
const recordingSessionId = currentRecordingSessionId || batchData.sessionId;
|
|
3948
4165
|
for (const frame of indexedFrames) {
|
|
@@ -3959,7 +4176,7 @@ async function handleFrameBatch(batchData, skipValidation = false) {
|
|
|
3959
4176
|
absoluteTimestamp: frame.absoluteTimestamp // Don't use Date.now() fallback - preserve actual capture time
|
|
3960
4177
|
});
|
|
3961
4178
|
}
|
|
3962
|
-
console.log(`[Browser-Only] Frames stored successfully in IndexedDB for session ${recordingSessionId}`);
|
|
4179
|
+
// console.log(`[Browser-Only] Frames stored successfully in IndexedDB for session ${recordingSessionId}`);
|
|
3963
4180
|
} else {
|
|
3964
4181
|
// Server mode but no server available - show error
|
|
3965
4182
|
console.error(`CRITICAL: Failed to upload frame batch to any Chrome Debug server port. Last error: ${lastError}`);
|
|
@@ -3999,7 +4216,7 @@ async function getServerPorts() {
|
|
|
3999
4216
|
// Try to discover the active server port
|
|
4000
4217
|
const discoveredPort = await discoverActiveServerPort();
|
|
4001
4218
|
if (discoveredPort) {
|
|
4002
|
-
console.log(`Discovered Chrome Debug server on port ${discoveredPort}`);
|
|
4219
|
+
// console.log(`Discovered Chrome Debug server on port ${discoveredPort}`);
|
|
4003
4220
|
return [discoveredPort, ...defaultPorts.filter(p => p !== discoveredPort)];
|
|
4004
4221
|
}
|
|
4005
4222
|
|
|
@@ -4037,7 +4254,7 @@ async function discoverActiveServerPort() {
|
|
|
4037
4254
|
|
|
4038
4255
|
// Handle frame capture session completion
|
|
4039
4256
|
async function handleFrameCaptureComplete(sessionData) {
|
|
4040
|
-
console.log(`Frame capture session ${sessionData.sessionId} completed with ${sessionData.totalFrames} frames`);
|
|
4257
|
+
// console.log(`Frame capture session ${sessionData.sessionId} completed with ${sessionData.totalFrames} frames`);
|
|
4041
4258
|
|
|
4042
4259
|
try {
|
|
4043
4260
|
// Store the tab ID and session ID before clearing
|
|
@@ -4055,7 +4272,7 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4055
4272
|
let waitedTime = 0;
|
|
4056
4273
|
let flushCompleted = false;
|
|
4057
4274
|
|
|
4058
|
-
console.log('[Background] Waiting for LogBuffer flush completion...');
|
|
4275
|
+
// console.log('[Background] Waiting for LogBuffer flush completion...');
|
|
4059
4276
|
|
|
4060
4277
|
// Poll for flush completion status
|
|
4061
4278
|
while (waitedTime < maxWaitTime && !flushCompleted) {
|
|
@@ -4069,7 +4286,7 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4069
4286
|
}
|
|
4070
4287
|
|
|
4071
4288
|
if (flushCompleted) {
|
|
4072
|
-
console.log(`[Background] LogBuffer flush completed after ${waitedTime}ms`);
|
|
4289
|
+
// console.log(`[Background] LogBuffer flush completed after ${waitedTime}ms`);
|
|
4073
4290
|
} else {
|
|
4074
4291
|
console.warn(`[Background] LogBuffer flush verification timed out after ${waitedTime}ms`);
|
|
4075
4292
|
}
|
|
@@ -4077,9 +4294,9 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4077
4294
|
// Retrieve buffered logs for this tab
|
|
4078
4295
|
const logsResult = await chrome.storage.session.get(String(tabIdToNotify));
|
|
4079
4296
|
bufferedLogs = logsResult[tabIdToNotify] || [];
|
|
4080
|
-
console.log(`Retrieved ${bufferedLogs.length} buffered logs for post-processing`);
|
|
4297
|
+
// console.log(`Retrieved ${bufferedLogs.length} buffered logs for post-processing`);
|
|
4081
4298
|
if (bufferedLogs.length > 0) {
|
|
4082
|
-
console.log('First log:', bufferedLogs[0]);
|
|
4299
|
+
// console.log('First log:', bufferedLogs[0]);
|
|
4083
4300
|
}
|
|
4084
4301
|
|
|
4085
4302
|
// Clean up flush completion marker
|
|
@@ -4090,7 +4307,7 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4090
4307
|
// Fallback: Try to read logs anyway
|
|
4091
4308
|
const logsResult = await chrome.storage.session.get(String(tabIdToNotify));
|
|
4092
4309
|
bufferedLogs = logsResult[tabIdToNotify] || [];
|
|
4093
|
-
console.log(`Fallback: Retrieved ${bufferedLogs.length} buffered logs`);
|
|
4310
|
+
// console.log(`Fallback: Retrieved ${bufferedLogs.length} buffered logs`);
|
|
4094
4311
|
}
|
|
4095
4312
|
|
|
4096
4313
|
// Clear the buffered logs
|
|
@@ -4099,7 +4316,7 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4099
4316
|
// Send logs to server for association with frames with retry logic
|
|
4100
4317
|
// Skip server communication in browser-only mode (logs already in IndexedDB)
|
|
4101
4318
|
if (bufferedLogs.length > 0 && serverMode !== 'browser-only') {
|
|
4102
|
-
console.log(`[Server Mode] Associating ${bufferedLogs.length} logs with server...`);
|
|
4319
|
+
// console.log(`[Server Mode] Associating ${bufferedLogs.length} logs with server...`);
|
|
4103
4320
|
|
|
4104
4321
|
// Retry logic to handle race conditions
|
|
4105
4322
|
const maxRetries = 3;
|
|
@@ -4107,15 +4324,15 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4107
4324
|
let success = false;
|
|
4108
4325
|
let lastErrorDetails = null;
|
|
4109
4326
|
|
|
4110
|
-
console.log(`[LOG-ASSOC-DEBUG] ========== STARTING LOG ASSOCIATION ==========`);
|
|
4111
|
-
console.log(`[LOG-ASSOC-DEBUG] Session ID: ${sessionIdToUse}`);
|
|
4112
|
-
console.log(`[LOG-ASSOC-DEBUG] Number of logs to associate: ${bufferedLogs.length}`);
|
|
4113
|
-
console.log(`[LOG-ASSOC-DEBUG] Tab ID: ${tabIdToNotify}`);
|
|
4327
|
+
// console.log(`[LOG-ASSOC-DEBUG] ========== STARTING LOG ASSOCIATION ==========`);
|
|
4328
|
+
// console.log(`[LOG-ASSOC-DEBUG] Session ID: ${sessionIdToUse}`);
|
|
4329
|
+
// console.log(`[LOG-ASSOC-DEBUG] Number of logs to associate: ${bufferedLogs.length}`);
|
|
4330
|
+
// console.log(`[LOG-ASSOC-DEBUG] Tab ID: ${tabIdToNotify}`);
|
|
4114
4331
|
|
|
4115
4332
|
// PRE-FLIGHT CHECK: Verify frames exist in database before attempting log association
|
|
4116
4333
|
try {
|
|
4117
4334
|
const ports = await getServerPorts();
|
|
4118
|
-
console.log(`[LOG-ASSOC-DEBUG] PRE-FLIGHT: Checking if frames exist for session ${sessionIdToUse}...`);
|
|
4335
|
+
// console.log(`[LOG-ASSOC-DEBUG] PRE-FLIGHT: Checking if frames exist for session ${sessionIdToUse}...`);
|
|
4119
4336
|
for (const port of ports) {
|
|
4120
4337
|
try {
|
|
4121
4338
|
const checkResponse = await fetch(`http://localhost:${port}/chromedebug/frame-session/${sessionIdToUse}`, {
|
|
@@ -4125,7 +4342,7 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4125
4342
|
if (checkResponse.ok) {
|
|
4126
4343
|
const sessionData = await checkResponse.json();
|
|
4127
4344
|
const frameCount = sessionData.frames?.length || 0;
|
|
4128
|
-
console.log(`[LOG-ASSOC-DEBUG] PRE-FLIGHT: Found ${frameCount} frames on port ${port}`);
|
|
4345
|
+
// console.log(`[LOG-ASSOC-DEBUG] PRE-FLIGHT: Found ${frameCount} frames on port ${port}`);
|
|
4129
4346
|
if (frameCount === 0) {
|
|
4130
4347
|
console.warn(`[LOG-ASSOC-DEBUG] ⚠️ WARNING: Session exists but has 0 frames! This will cause log association to fail.`);
|
|
4131
4348
|
console.warn(`[LOG-ASSOC-DEBUG] Session data:`, sessionData);
|
|
@@ -4133,7 +4350,7 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4133
4350
|
break;
|
|
4134
4351
|
}
|
|
4135
4352
|
} catch (e) {
|
|
4136
|
-
console.log(`[LOG-ASSOC-DEBUG] PRE-FLIGHT: Could not check port ${port}:`, e.message);
|
|
4353
|
+
// console.log(`[LOG-ASSOC-DEBUG] PRE-FLIGHT: Could not check port ${port}:`, e.message);
|
|
4137
4354
|
}
|
|
4138
4355
|
}
|
|
4139
4356
|
} catch (preflightError) {
|
|
@@ -4143,22 +4360,22 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4143
4360
|
while (retryCount < maxRetries && !success) {
|
|
4144
4361
|
try {
|
|
4145
4362
|
const ports = await getServerPorts();
|
|
4146
|
-
console.log(`[LOG-ASSOC-DEBUG] Attempt ${retryCount + 1}/${maxRetries}: Trying ports:`, ports);
|
|
4363
|
+
// console.log(`[LOG-ASSOC-DEBUG] Attempt ${retryCount + 1}/${maxRetries}: Trying ports:`, ports);
|
|
4147
4364
|
|
|
4148
4365
|
for (const port of ports) {
|
|
4149
4366
|
try {
|
|
4150
|
-
console.log(`[LOG-ASSOC-DEBUG] Attempting port ${port}...`);
|
|
4367
|
+
// console.log(`[LOG-ASSOC-DEBUG] Attempting port ${port}...`);
|
|
4151
4368
|
const requestBody = {
|
|
4152
4369
|
sessionId: sessionIdToUse,
|
|
4153
4370
|
logs: bufferedLogs
|
|
4154
4371
|
};
|
|
4155
|
-
console.log(`[LOG-ASSOC-DEBUG] Request payload: sessionId=${sessionIdToUse}, logs.length=${bufferedLogs.length}`);
|
|
4372
|
+
// console.log(`[LOG-ASSOC-DEBUG] Request payload: sessionId=${sessionIdToUse}, logs.length=${bufferedLogs.length}`);
|
|
4156
4373
|
if (bufferedLogs.length > 0) {
|
|
4157
|
-
console.log(`[LOG-ASSOC-DEBUG] First log sample:`, {
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
|
|
4161
|
-
});
|
|
4374
|
+
// console.log(`[LOG-ASSOC-DEBUG] First log sample:`, {
|
|
4375
|
+
// timestamp: bufferedLogs[0].timestamp,
|
|
4376
|
+
// level: bufferedLogs[0].level,
|
|
4377
|
+
// message: bufferedLogs[0].message?.substring(0, 100)
|
|
4378
|
+
// });
|
|
4162
4379
|
}
|
|
4163
4380
|
|
|
4164
4381
|
const response = await fetch(`http://localhost:${port}/chromedebug/associate-logs`, {
|
|
@@ -4169,12 +4386,12 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4169
4386
|
body: JSON.stringify(requestBody)
|
|
4170
4387
|
});
|
|
4171
4388
|
|
|
4172
|
-
console.log(`[LOG-ASSOC-DEBUG] Port ${port} response status: ${response.status} ${response.statusText}`);
|
|
4389
|
+
// console.log(`[LOG-ASSOC-DEBUG] Port ${port} response status: ${response.status} ${response.statusText}`);
|
|
4173
4390
|
|
|
4174
4391
|
if (response.ok) {
|
|
4175
4392
|
const result = await response.json();
|
|
4176
|
-
console.log(`[LOG-ASSOC-DEBUG] ✅ SUCCESS on port ${port}:`, result);
|
|
4177
|
-
console.log(`Logs associated successfully on port ${port}:`, result);
|
|
4393
|
+
// console.log(`[LOG-ASSOC-DEBUG] ✅ SUCCESS on port ${port}:`, result);
|
|
4394
|
+
// console.log(`Logs associated successfully on port ${port}:`, result);
|
|
4178
4395
|
success = true;
|
|
4179
4396
|
|
|
4180
4397
|
// Fetch the updated session data with logs from server
|
|
@@ -4182,14 +4399,14 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4182
4399
|
const sessionResponse = await fetch(`http://localhost:${port}/chromedebug/frame-session/${sessionIdToUse}`);
|
|
4183
4400
|
if (sessionResponse.ok) {
|
|
4184
4401
|
const updatedSession = await sessionResponse.json();
|
|
4185
|
-
console.log(`[LOG-ASSOC-DEBUG] Fetched updated session: ${updatedSession.frames?.length || 0} frames`);
|
|
4186
|
-
console.log(`Fetched updated session with ${updatedSession.frames ? updatedSession.frames.length : 0} frames`);
|
|
4402
|
+
// console.log(`[LOG-ASSOC-DEBUG] Fetched updated session: ${updatedSession.frames?.length || 0} frames`);
|
|
4403
|
+
// console.log(`Fetched updated session with ${updatedSession.frames ? updatedSession.frames.length : 0} frames`);
|
|
4187
4404
|
|
|
4188
4405
|
// Update Chrome local storage with the frames that now have logs
|
|
4189
4406
|
const storageKey = sessionIdToUse;
|
|
4190
4407
|
await chrome.storage.local.set({ [storageKey]: updatedSession });
|
|
4191
|
-
console.log('[LOG-ASSOC-DEBUG] Updated local storage with frames containing logs');
|
|
4192
|
-
console.log('Updated local storage with frames containing logs');
|
|
4408
|
+
// console.log('[LOG-ASSOC-DEBUG] Updated local storage with frames containing logs');
|
|
4409
|
+
// console.log('Updated local storage with frames containing logs');
|
|
4193
4410
|
} else {
|
|
4194
4411
|
console.error(`[LOG-ASSOC-DEBUG] Failed to fetch updated session: ${sessionResponse.status}`);
|
|
4195
4412
|
console.error('Failed to fetch updated session data');
|
|
@@ -4225,15 +4442,15 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4225
4442
|
attempt: retryCount + 1
|
|
4226
4443
|
};
|
|
4227
4444
|
console.error(`[LOG-ASSOC-DEBUG] ❌ Port ${port} exception:`, e);
|
|
4228
|
-
console.log(`Failed to associate logs on port ${port}:`, e.message);
|
|
4445
|
+
// console.log(`Failed to associate logs on port ${port}:`, e.message);
|
|
4229
4446
|
}
|
|
4230
4447
|
}
|
|
4231
4448
|
|
|
4232
4449
|
if (!success) {
|
|
4233
4450
|
retryCount++;
|
|
4234
4451
|
if (retryCount < maxRetries) {
|
|
4235
|
-
console.log(`[LOG-ASSOC-DEBUG] Retrying in 1 second (attempt ${retryCount + 1}/${maxRetries})...`);
|
|
4236
|
-
console.log(`Retrying log association (attempt ${retryCount + 1}/${maxRetries})...`);
|
|
4452
|
+
// console.log(`[LOG-ASSOC-DEBUG] Retrying in 1 second (attempt ${retryCount + 1}/${maxRetries})...`);
|
|
4453
|
+
// console.log(`Retrying log association (attempt ${retryCount + 1}/${maxRetries})...`);
|
|
4237
4454
|
await new Promise(resolve => setTimeout(resolve, 1000));
|
|
4238
4455
|
}
|
|
4239
4456
|
}
|
|
@@ -4247,8 +4464,8 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4247
4464
|
}
|
|
4248
4465
|
}
|
|
4249
4466
|
|
|
4250
|
-
console.log(`[LOG-ASSOC-DEBUG] ========== LOG ASSOCIATION COMPLETE ==========`);
|
|
4251
|
-
console.log(`[LOG-ASSOC-DEBUG] Success: ${success}`);
|
|
4467
|
+
// console.log(`[LOG-ASSOC-DEBUG] ========== LOG ASSOCIATION COMPLETE ==========`);
|
|
4468
|
+
// console.log(`[LOG-ASSOC-DEBUG] Success: ${success}`);
|
|
4252
4469
|
if (!success && lastErrorDetails) {
|
|
4253
4470
|
console.error(`[LOG-ASSOC-DEBUG] Last error details:`, lastErrorDetails);
|
|
4254
4471
|
}
|
|
@@ -4279,12 +4496,12 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4279
4496
|
}
|
|
4280
4497
|
} else if (bufferedLogs.length > 0 && serverMode === 'browser-only') {
|
|
4281
4498
|
// Browser-only mode: Associate logs with frames in IndexedDB
|
|
4282
|
-
console.log(`[Browser-Only] Associating ${bufferedLogs.length} logs with frames in IndexedDB...`);
|
|
4499
|
+
// console.log(`[Browser-Only] Associating ${bufferedLogs.length} logs with frames in IndexedDB...`);
|
|
4283
4500
|
|
|
4284
4501
|
try {
|
|
4285
4502
|
// Get all frames for this session from IndexedDB
|
|
4286
4503
|
const frames = await dataBuffer.getBrowserFrames(sessionIdToUse);
|
|
4287
|
-
console.log(`[Browser-Only] Retrieved ${frames.length} frames from IndexedDB for log association`);
|
|
4504
|
+
// console.log(`[Browser-Only] Retrieved ${frames.length} frames from IndexedDB for log association`);
|
|
4288
4505
|
|
|
4289
4506
|
if (frames.length === 0) {
|
|
4290
4507
|
console.warn('[Browser-Only] No frames found - logs cannot be associated');
|
|
@@ -4328,7 +4545,7 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4328
4545
|
}
|
|
4329
4546
|
}
|
|
4330
4547
|
|
|
4331
|
-
console.log(`[Browser-Only] ✓ Associated logs with ${updatedCount} frames in IndexedDB`);
|
|
4548
|
+
// console.log(`[Browser-Only] ✓ Associated logs with ${updatedCount} frames in IndexedDB`);
|
|
4332
4549
|
}
|
|
4333
4550
|
} catch (error) {
|
|
4334
4551
|
console.error('[Browser-Only] Failed to associate logs with frames:', error);
|
|
@@ -4354,18 +4571,18 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4354
4571
|
// Save screen interactions to database
|
|
4355
4572
|
// Skip server communication in browser-only mode
|
|
4356
4573
|
if (screenInteractions.length > 0 && serverMode !== 'browser-only') {
|
|
4357
|
-
console.log(`[Server Mode] Saving ${screenInteractions.length} screen interactions to database`);
|
|
4574
|
+
// console.log(`[Server Mode] Saving ${screenInteractions.length} screen interactions to database`);
|
|
4358
4575
|
|
|
4359
4576
|
// Use comprehensive error handling for screen interactions save
|
|
4360
4577
|
const saveScreenInteractions = async (data, context) => {
|
|
4361
4578
|
// Diagnostic logging for screen interactions save
|
|
4362
|
-
console.log('[ScreenInteractions] Preparing to save interactions:', {
|
|
4363
|
-
|
|
4364
|
-
|
|
4365
|
-
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
});
|
|
4579
|
+
// console.log('[ScreenInteractions] Preparing to save interactions:', {
|
|
4580
|
+
// sessionId: context.sessionId,
|
|
4581
|
+
// dataType: typeof data,
|
|
4582
|
+
// isArray: Array.isArray(data),
|
|
4583
|
+
// interactionCount: Array.isArray(data) ? data.length : 'N/A',
|
|
4584
|
+
// hasComplexData: Array.isArray(data) && data.some(i => i.element_html && i.element_html.length > 100)
|
|
4585
|
+
// });
|
|
4369
4586
|
|
|
4370
4587
|
let lastError = null;
|
|
4371
4588
|
for (const port of CONFIG_PORTS) {
|
|
@@ -4375,7 +4592,7 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4375
4592
|
try {
|
|
4376
4593
|
// data is already { interactions: screenInteractions } from caller
|
|
4377
4594
|
serializedBody = JSON.stringify(data);
|
|
4378
|
-
console.log('[ScreenInteractions] JSON serialization successful, length:', serializedBody.length);
|
|
4595
|
+
// console.log('[ScreenInteractions] JSON serialization successful, length:', serializedBody.length);
|
|
4379
4596
|
} catch (serError) {
|
|
4380
4597
|
console.error('[ScreenInteractions] JSON serialization failed:', serError);
|
|
4381
4598
|
throw new Error(`JSON serialization failed: ${serError.message}`);
|
|
@@ -4392,7 +4609,7 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4392
4609
|
if (response.ok) {
|
|
4393
4610
|
// Only log if we had to try multiple ports
|
|
4394
4611
|
if (port !== CONFIG_PORTS[0]) {
|
|
4395
|
-
console.log(`[ScreenInteractions] Connected to server on port ${port}`);
|
|
4612
|
+
// console.log(`[ScreenInteractions] Connected to server on port ${port}`);
|
|
4396
4613
|
}
|
|
4397
4614
|
return { success: true, result: { saved: true } };
|
|
4398
4615
|
} else {
|
|
@@ -4416,13 +4633,13 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4416
4633
|
);
|
|
4417
4634
|
|
|
4418
4635
|
if (saveResult.success) {
|
|
4419
|
-
console.log('Screen interactions saved successfully with comprehensive error handling');
|
|
4636
|
+
// console.log('Screen interactions saved successfully with comprehensive error handling');
|
|
4420
4637
|
} else {
|
|
4421
4638
|
console.error('[ErrorHandling] Failed to save screen interactions after comprehensive error handling');
|
|
4422
4639
|
}
|
|
4423
4640
|
} else if (screenInteractions.length > 0 && serverMode === 'browser-only') {
|
|
4424
4641
|
// Browser-only mode: screen interactions not needed
|
|
4425
|
-
console.log(`[Browser-Only] ✓ Skipping screen interactions save (browser-only mode)`);
|
|
4642
|
+
// console.log(`[Browser-Only] ✓ Skipping screen interactions save (browser-only mode)`);
|
|
4426
4643
|
}
|
|
4427
4644
|
|
|
4428
4645
|
// Stop session via session manager if available
|
|
@@ -4430,7 +4647,7 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4430
4647
|
try {
|
|
4431
4648
|
const stopResult = await sessionManager.stopRecording(currentSession.sessionId, currentOwnerId);
|
|
4432
4649
|
if (stopResult.success) {
|
|
4433
|
-
console.log(`Session stopped via session manager. Duration: ${stopResult.sessionDuration}ms, Frames: ${stopResult.frameCount}`);
|
|
4650
|
+
// console.log(`Session stopped via session manager. Duration: ${stopResult.sessionDuration}ms, Frames: ${stopResult.frameCount}`);
|
|
4434
4651
|
} else {
|
|
4435
4652
|
console.warn('Failed to stop session via session manager:', stopResult.error?.message);
|
|
4436
4653
|
}
|
|
@@ -4482,7 +4699,7 @@ async function handleFrameCaptureComplete(sessionData) {
|
|
|
4482
4699
|
serverPort: recordingServerPort
|
|
4483
4700
|
}).catch(() => {});
|
|
4484
4701
|
} else {
|
|
4485
|
-
console.log('[Browser-Only] Skipping frameSessionComplete message - recording is in IndexedDB');
|
|
4702
|
+
// console.log('[Browser-Only] Skipping frameSessionComplete message - recording is in IndexedDB');
|
|
4486
4703
|
}
|
|
4487
4704
|
|
|
4488
4705
|
// Notify content script to hide recording indicator
|