@@ -185,13 +185,46 @@ def execute_cdp_command(self, command, params=None):
185185 body = body )
186186
187187
188+ class ChromeDriverTracingProtocolPart (ProtocolPart ):
189+ name = "tracing"
190+
191+ def setup (self ):
192+ self .webdriver = self .parent .webdriver
193+
194+ def get_trace (self ):
195+ """Retrieve trace events accumulated by ChromeDriver.
196+
197+ This also clears ChromeDriver's internal buffer of logged events.
198+
199+ Returns:
200+ JSON in the trace array format [0].
201+
202+ [0]: https://docs.google.com/document/d/1CvAClvFfyA5R-PhYUmn5OOQtYMH4h6I0nSsKchNAySU/preview?tab=t.0#heading=h.f2f0yd51wi15
203+ """
204+ # Not a standard WebDriver method.
205+ perf_data = self .webdriver .send_session_command ("POST" , "se/log" , {
206+ "type" : "performance" ,
207+ })
208+ events = []
209+ for entry in perf_data :
210+ # Unwrap the inner trace event and discard the unnecessary
211+ # ChromeDriver-added fields.
212+ data_collected_event = json .loads (entry ["message" ]).get ("message" , {})
213+ if data_collected_event .get ("method" ) != "Tracing.dataCollected" :
214+ continue
215+ if trace_event := data_collected_event .get ("params" ):
216+ events .append (trace_event )
217+ return events
218+
219+
188220class ChromeDriverProtocol (WebDriverProtocol ):
189221 implements = [
190222 ChromeDriverBaseProtocolPart ,
191223 ChromeDriverDevToolsProtocolPart ,
192224 ChromeDriverFedCMProtocolPart ,
193225 ChromeDriverTestDriverProtocolPart ,
194226 ChromeDriverTestharnessProtocolPart ,
227+ ChromeDriverTracingProtocolPart ,
195228 ]
196229 for base_part in WebDriverProtocol .implements :
197230 if base_part .name not in {part .name for part in implements }:
@@ -213,6 +246,7 @@ class ChromeDriverBidiProtocol(WebDriverBidiProtocol):
213246 ChromeDriverDevToolsProtocolPart ,
214247 ChromeDriverFedCMProtocolPart ,
215248 ChromeDriverTestharnessProtocolPart ,
249+ ChromeDriverTracingProtocolPart ,
216250 ]
217251 for base_part in WebDriverBidiProtocol .implements :
218252 if base_part .name not in {part .name for part in implements }:
@@ -258,24 +292,39 @@ def convert_result(self, test, result, **kwargs):
258292class ChromeDriverCrashTestExecutor (WebDriverCrashtestExecutor ):
259293 protocol_cls = ChromeDriverProtocol
260294
261- def __init__ (self , * args , sanitizer_enabled = False , ** kwargs ):
295+ def __init__ (self , * args , sanitizer_enabled = False , enable_tracing = False , ** kwargs ):
262296 super ().__init__ (* args , ** kwargs )
263297 self .sanitizer_enabled = sanitizer_enabled
298+ self .enable_tracing = enable_tracing
299+
300+ def do_test (self , test ):
301+ file_result , subtest_results = super ().do_test (test )
302+ if self .enable_tracing :
303+ file_result .extra ["trace" ] = self .protocol .tracing .get_trace ()
304+ return file_result , subtest_results
264305
265306
266307@_evaluate_sanitized_result
267308class ChromeDriverRefTestExecutor (WebDriverRefTestExecutor ):
268309 protocol_cls = ChromeDriverProtocol
269310
270- def __init__ (self , * args , sanitizer_enabled = False , ** kwargs ):
311+ def __init__ (self , * args , sanitizer_enabled = False , enable_tracing = False , ** kwargs ):
271312 super ().__init__ (* args , ** kwargs )
272313 self .sanitizer_enabled = sanitizer_enabled
314+ self .enable_tracing = enable_tracing
315+
316+ def do_test (self , test ):
317+ file_result , subtest_results = super ().do_test (test )
318+ if self .enable_tracing :
319+ file_result .extra ["trace" ] = self .protocol .tracing .get_trace ()
320+ return file_result , subtest_results
273321
274322
275323@_evaluate_sanitized_result
276324class ChromeDriverTestharnessExecutor (WebDriverTestharnessExecutor ):
277325
278- def __init__ (self , * args , sanitizer_enabled = False , reuse_window = False , ** kwargs ):
326+ def __init__ (self , * args , sanitizer_enabled = False , enable_tracing = False , reuse_window = False ,
327+ ** kwargs ):
279328 require_webdriver_bidi = kwargs .get ("browser_settings" , {}).get (
280329 "require_webdriver_bidi" , None )
281330 if require_webdriver_bidi :
@@ -285,6 +334,7 @@ def __init__(self, *args, sanitizer_enabled=False, reuse_window=False, **kwargs)
285334
286335 super ().__init__ (* args , ** kwargs )
287336 self .sanitizer_enabled = sanitizer_enabled
337+ self .enable_tracing = enable_tracing
288338 self .reuse_window = reuse_window
289339
290340 def create_test_window (self , protocol ):
@@ -312,11 +362,24 @@ def create_test_window(self, protocol):
312362 self .protocol .testharness .persistent_test_window = test_window
313363 return test_window
314364
365+ def do_test (self , test ):
366+ file_result , subtest_results = super ().do_test (test )
367+ if self .enable_tracing :
368+ file_result .extra ["trace" ] = self .protocol .tracing .get_trace ()
369+ return file_result , subtest_results
370+
315371
316372@_evaluate_sanitized_result
317373class ChromeDriverPrintRefTestExecutor (WebDriverPrintRefTestExecutor ):
318374 protocol_cls = ChromeDriverProtocol
319375
320- def __init__ (self , * args , sanitizer_enabled = False , ** kwargs ):
376+ def __init__ (self , * args , sanitizer_enabled = False , enable_tracing = False , ** kwargs ):
321377 super ().__init__ (* args , ** kwargs )
322378 self .sanitizer_enabled = sanitizer_enabled
379+ self .enable_tracing = enable_tracing
380+
381+ def do_test (self , test ):
382+ file_result , subtest_results = super ().do_test (test )
383+ if self .enable_tracing :
384+ file_result .extra ["trace" ] = self .protocol .tracing .get_trace ()
385+ return file_result , subtest_results
0 commit comments