@@ -42,10 +42,6 @@ def __init__(
4242 self .clear_cookies = clear_cookies
4343 self .clear_storage = clear_storage
4444
45- # Connection state tracking
46- self ._connection_lost = False
47- self ._connection_lost_lock = threading .Lock ()
48-
4945 # Response tracking for synchronous commands
5046 self .pending_responses = {}
5147 self .response_lock = threading .Lock ()
@@ -71,15 +67,8 @@ def __init__(
7167
7268 def send (self , method , params = None ):
7369 """Send CDP command and return sequence ID."""
74- if self ._connection_lost :
75- raise ConnectionError ("WebSocket connection is closed" )
7670 self .seq += 1
77- try :
78- self .ws .send (json .dumps ({"id" : self .seq , "method" : method , "params" : params or {}}))
79- except (websocket .WebSocketConnectionClosedException , OSError , ConnectionError ) as e :
80- with self ._connection_lost_lock :
81- self ._connection_lost = True
82- raise ConnectionError (f"WebSocket connection lost: { e } " )
71+ self .ws .send (json .dumps ({"id" : self .seq , "method" : method , "params" : params or {}}))
8372 return self .seq
8473
8574 def send_and_wait (self , method , params = None , timeout = 10 ):
@@ -111,14 +100,6 @@ def send_and_wait(self, method, params=None, timeout=10):
111100
112101 def setup_cdp (self , navigate_to = None ):
113102 """Setup CDP domains and configuration."""
114- # Enable Target domain to receive target lifecycle events (if on browser WebSocket)
115- # Note: This may not work on tab WebSockets, but that's okay - we'll catch disconnections
116- try :
117- self .send ("Target.setDiscoverTargets" , {"discover" : True })
118- except Exception as e :
119- # This is expected to fail on tab WebSockets - Target domain is browser-level
120- logger .debug (f"Could not enable Target domain (expected on tab WebSockets): { e } " )
121-
122103 # Enable basic domains
123104 self .send ("Page.enable" )
124105 self .send ("Runtime.enable" )
@@ -167,14 +148,6 @@ def setup_cdp(self, navigate_to=None):
167148
168149 def handle_message (self , msg ):
169150 """Handle incoming CDP message by delegating to appropriate monitors."""
170- # Check for target lifecycle events (tab closure)
171- method = msg .get ("method" )
172- if method == "Target.targetDestroyed" :
173- logger .info ("Tab was closed. Connection will be lost. Saving assets..." )
174- with self ._connection_lost_lock :
175- self ._connection_lost = True
176- return
177-
178151 # Try network monitor first
179152 if self .network_monitor .handle_network_message (msg , self ):
180153 return
@@ -229,84 +202,44 @@ def _handle_command_reply(self, msg):
229202
230203 return False
231204
232- def _generate_assets (self ):
233- """Generate all monitoring assets. Works even if connection is lost."""
234- try :
235- # Final cookie sync using native CDP (only if connection is still alive)
236- if not self ._connection_lost :
237- try :
238- self .storage_monitor .monitor_cookie_changes (self )
239- except Exception as e :
240- logger .debug (f"Could not sync cookies (connection may be lost): { e } " )
241- except Exception as e :
242- logger .debug (f"Error in cookie sync: { e } " )
205+ def run (self ):
206+ """Main message processing loop."""
207+ logger .info ("Blocking trackers & capturing network/storage… Press Ctrl+C to stop." )
243208
244- # Consolidate all transactions into a single JSON file (works with cached data)
245209 try :
210+ while True :
211+ msg = json .loads (self .ws .recv ())
212+ self .handle_message (msg )
213+ except KeyboardInterrupt :
214+ logger .info ("\n Stopped. Saving assets..." )
215+ # Final cookie sync using native CDP (no delay needed)
216+ self .storage_monitor .monitor_cookie_changes (self )
217+
218+ # Consolidate all transactions into a single JSON file
246219 consolidated_path = f"{ self .output_dir } /consolidated_transactions.json"
247220 self .network_monitor .consolidate_transactions (consolidated_path )
248- except Exception as e :
249- logger .warning (f"Could not consolidate transactions: { e } " )
250-
251- # Generate HAR file from consolidated transactions (works with cached data)
252- try :
221+
222+ # Generate HAR file from consolidated transactions
253223 har_path = f"{ self .output_dir } /network.har"
254224 self .network_monitor .generate_har_from_transactions (har_path , "Web Hacker Session" )
255- except Exception as e :
256- logger .warning (f"Could not generate HAR file: { e } " )
257-
258- # Consolidate all interactions into a single JSON file (works with cached data)
259- try :
225+
226+ # Consolidate all interactions into a single JSON file
260227 interaction_dir = self .paths .get ('interaction_dir' , f"{ self .output_dir } /interaction" )
261228 consolidated_interactions_path = os .path .join (interaction_dir , "consolidated_interactions.json" )
262229 self .interaction_monitor .consolidate_interactions (consolidated_interactions_path )
263- except Exception as e :
264- logger .warning (f"Could not consolidate interactions: { e } " )
265-
266- def run (self ):
267- """Main message processing loop."""
268- logger .info ("Blocking trackers & capturing network/storage… Press Ctrl+C to stop." )
269-
270- try :
271- while True :
272- try :
273- msg = json .loads (self .ws .recv ())
274- self .handle_message (msg )
275-
276- # Check if connection was lost due to tab closure
277- if self ._connection_lost :
278- logger .info ("Tab closed. Saving assets..." )
279- break
280- except (websocket .WebSocketConnectionClosedException , OSError , ConnectionError ) as e :
281- # WebSocket connection lost (tab closed, browser closed, etc.)
282- logger .info (f"Connection lost: { e } . Saving assets..." )
283- with self ._connection_lost_lock :
284- self ._connection_lost = True
285- break
286- except json .JSONDecodeError as e :
287- logger .warning (f"Failed to parse message: { e } " )
288- continue
289- except KeyboardInterrupt :
290- logger .info ("\n Stopped by user. Saving assets..." )
291230 finally :
292- # Always generate assets, even if connection is lost
293- self ._generate_assets ()
294-
295- # Close WebSocket if still open
296231 try :
297- if self .ws and not self ._connection_lost :
298- self .ws .close ()
299- except Exception :
232+ self .ws .close ()
233+ except :
300234 pass
301235
302236 def get_monitoring_summary (self ):
303237 """Get summary of all monitoring activities."""
304- # Trigger final cookie check using native CDP (only if connection is still alive)
305- if not self ._connection_lost :
306- try :
307- self .storage_monitor .monitor_cookie_changes (self )
308- except Exception as e :
309- logger .debug (f"Could not sync cookies for summary: { e } " )
238+ # Trigger final cookie check using native CDP (no delay needed)
239+ try :
240+ self .storage_monitor .monitor_cookie_changes (self )
241+ except :
242+ pass
310243
311244 storage_summary = self .storage_monitor .get_storage_summary ()
312245 network_summary = self .network_monitor .get_network_summary ()
@@ -316,4 +249,4 @@ def get_monitoring_summary(self):
316249 "network" : network_summary ,
317250 "storage" : storage_summary ,
318251 "interaction" : interaction_summary ,
319- }
252+ }
0 commit comments