1+ // This devtools page runs alongside the panel and handles console log injection
2+ // It has access to chrome.devtools.inspectedWindow.eval for the inspected tab
3+
4+ // Injection code that hijacks console methods
5+ const injectionCode = `
6+ (function() {
7+ const isOverridden = !console.log.toString().includes('[native code]');
8+
9+ // Check if already injected
10+ if (isOverridden) {
11+ return;
12+ }
13+
14+ // Store original console methods
15+ const originalConsole = {
16+ log: console.log,
17+ error: console.error,
18+ warn: console.warn,
19+ info: console.info,
20+ debug: console.debug,
21+ trace: console.trace,
22+ table: console.table,
23+ group: console.group,
24+ groupCollapsed: console.groupCollapsed,
25+ groupEnd: console.groupEnd,
26+ clear: console.clear
27+ };
28+
29+ // Helper to serialize arguments
30+ function serializeArgs(args) {
31+ return Array.from(args).map(arg => {
32+ try {
33+ if (arg === undefined) return 'undefined';
34+ if (arg === null) return 'null';
35+ if (typeof arg === 'function') return arg.toString();
36+ if (typeof arg === 'object') {
37+ // Handle circular references
38+ const seen = new WeakSet();
39+ return JSON.stringify(arg, function(key, value) {
40+ if (typeof value === 'object' && value !== null) {
41+ if (seen.has(value)) return '[Circular]';
42+ seen.add(value);
43+ }
44+ if (typeof value === 'function') return value.toString();
45+ return value;
46+ });
47+ }
48+ return String(arg);
49+ } catch (e) {
50+ return String(arg);
51+ }
52+ });
53+ }
54+
55+ originalConsole.log('[Kapture] overriding console methods');
56+
57+ // Override console methods (all except clear)
58+ ['log', 'error', 'warn', 'info', 'debug', 'trace', 'table', 'group', 'groupCollapsed', 'groupEnd'].forEach(level => {
59+ console[level] = function(...args) {
60+ // Create log entry
61+ const event = new CustomEvent('kapture-console', {
62+ detail: {
63+ level: level,
64+ args: serializeArgs(args),
65+ timestamp: new Date().toISOString(),
66+ stack: new Error().stack
67+ }
68+ });
69+
70+ // Dispatch event for content script to capture
71+ window.dispatchEvent(event);
72+
73+ // Call original method
74+ originalConsole[level].apply(console, args);
75+ };
76+ });
77+
78+ // Override console.clear
79+ console.clear = function() {
80+ // Dispatch clear event
81+ const event = new CustomEvent('kapture-console', {
82+ detail: {
83+ level: 'clear'
84+ }
85+ });
86+ originalConsole.log('[Kapture] Dispatching console clear event');
87+ window.dispatchEvent(event);
88+
89+ // Call original method
90+ originalConsole.clear.apply(console);
91+ };
92+
93+ // Log that injection is complete
94+ originalConsole.log('[Kapture] Console capture injected into page context');
95+ })();
96+ ` ;
97+
98+ // Track if we've injected for this tab
99+ let injected = false ;
100+
101+ // Function to inject the console hijacking code
102+ function injectConsoleHijack ( ) {
103+ if ( injected ) return ;
104+
105+ chrome . devtools . inspectedWindow . eval ( injectionCode , ( result , error ) => {
106+ if ( error ) {
107+ console . error ( '[Kapture DevTools Page] Failed to inject console hijack:' , error ) ;
108+ } else {
109+ console . log ( '[Kapture DevTools Page] Console hijack injected successfully' ) ;
110+ injected = true ;
111+ }
112+ } ) ;
113+ }
114+
115+ // Inject immediately when devtools page loads
116+ injectConsoleHijack ( ) ;
117+
118+ // Re-inject on navigation (page reload)
119+ chrome . devtools . network . onNavigated . addListener ( ( ) => {
120+ console . log ( '[Kapture DevTools Page] Page navigated, re-injecting console hijack' ) ;
121+ injected = false ;
122+ // Small delay to ensure page is ready
123+ setTimeout ( injectConsoleHijack , 100 ) ;
124+ } ) ;
125+
126+ // Listen for messages from the background script to check if DevTools is open
127+ chrome . runtime . onMessage . addListener ( ( request , sender , sendResponse ) => {
128+ if ( request . type === 'checkDevToolsOpen' ) {
129+ // If this script is running, DevTools is open
130+ sendResponse ( { devToolsOpen : true , tabId : chrome . devtools . inspectedWindow . tabId } ) ;
131+ return true ;
132+ }
133+ } ) ;
0 commit comments