@@ -88,6 +88,8 @@ def __init__(self, options, job, task, use_devtools_video, is_webkit, is_ios):
88
88
self .main_thread_blocked = False
89
89
self .stylesheets = {}
90
90
self .headers = {}
91
+ self .execution_contexts = {}
92
+ self .execution_context = None
91
93
self .trace_parser = None
92
94
self .prepare ()
93
95
self .html_body = False
@@ -564,6 +566,12 @@ def stop_recording(self):
564
566
# Add the audit issues to the page data
565
567
if len (self .audit_issues ):
566
568
self .task ['page_data' ]['audit_issues' ] = self .audit_issues
569
+ # Add the list of execution contexts
570
+ contexts = []
571
+ for id in self .execution_contexts :
572
+ contexts .append (self .execution_contexts [id ])
573
+ if len (contexts ):
574
+ self .task ['page_data' ]['execution_contexts' ] = contexts
567
575
# Process the timeline data
568
576
if self .trace_parser is not None :
569
577
start = monotonic ()
@@ -1174,7 +1182,7 @@ def colors_are_similar(self, color1, color2, threshold=15):
1174
1182
similar = False
1175
1183
return similar
1176
1184
1177
- def execute_js (self , script ):
1185
+ def execute_js (self , script , use_execution_context = False ):
1178
1186
"""Run the provided JS in the browser and return the result"""
1179
1187
if self .must_exit :
1180
1188
return
@@ -1183,18 +1191,35 @@ def execute_js(self, script):
1183
1191
if self .is_webkit :
1184
1192
response = self .send_command ('Runtime.evaluate' , {'expression' : script , 'returnByValue' : True }, timeout = 30 , wait = True )
1185
1193
else :
1186
- response = self .send_command ("Runtime.evaluate" ,
1187
- {'expression' : script ,
1188
- 'awaitPromise' : True ,
1189
- 'returnByValue' : True ,
1190
- 'timeout' : 30000 },
1191
- wait = True , timeout = 30 )
1194
+ params = {'expression' : script ,
1195
+ 'awaitPromise' : True ,
1196
+ 'returnByValue' : True ,
1197
+ 'timeout' : 30000 }
1198
+ if use_execution_context and self .execution_context is not None :
1199
+ params ['contextId' ] = self .execution_context
1200
+ response = self .send_command ("Runtime.evaluate" , params , wait = True , timeout = 30 )
1192
1201
if response is not None and 'result' in response and \
1193
1202
'result' in response ['result' ] and \
1194
1203
'value' in response ['result' ]['result' ]:
1195
1204
ret = response ['result' ]['result' ]['value' ]
1196
1205
return ret
1197
1206
1207
+ def set_execution_context (self , target ):
1208
+ """ Set the js execution context by matching id, origin or name """
1209
+ if len (target ):
1210
+ parts = target .split ('=' , 1 )
1211
+ if len (parts ) == 2 :
1212
+ key = parts [0 ].strip ()
1213
+ value = parts [1 ].strip ()
1214
+ if key in ['id' , 'name' , 'origin' ] and len (value ):
1215
+ for id in self .execution_contexts :
1216
+ context = self .execution_contexts [id ]
1217
+ if key in context and context [key ] == value :
1218
+ self .execution_context = id
1219
+ break
1220
+ else :
1221
+ self .execution_context = None
1222
+
1198
1223
def set_header (self , header ):
1199
1224
"""Add/modify a header on the outbound requests"""
1200
1225
if header is not None and len (header ):
@@ -1309,6 +1334,7 @@ def enable_target(self, target_id=None):
1309
1334
self .send_command ('Network.enable' , {}, target_id = target_id )
1310
1335
self .send_command ('Console.enable' , {}, target_id = target_id )
1311
1336
self .send_command ('Log.enable' , {}, target_id = target_id )
1337
+ self .send_command ('Runtime.enable' , {}, target_id = target_id )
1312
1338
self .send_command ('Log.startViolationsReport' , {'config' : [{'name' : 'discouragedAPIUse' , 'threshold' : - 1 }]}, target_id = target_id )
1313
1339
self .send_command ('Audits.enable' , {}, target_id = target_id )
1314
1340
self .job ['shaper' ].apply (target_id = target_id )
@@ -1423,6 +1449,8 @@ def process_message(self, msg, target_id=None):
1423
1449
self .process_css_event (event , msg )
1424
1450
elif category == 'Debugger' :
1425
1451
self .process_debugger_event (event , msg )
1452
+ elif category == 'Runtime' :
1453
+ self .process_runtime_event (event , msg )
1426
1454
elif category == 'Target' :
1427
1455
log_event = False
1428
1456
self .process_target_event (event , msg )
@@ -1545,6 +1573,26 @@ def process_debugger_event(self, event, msg):
1545
1573
if event == 'paused' :
1546
1574
self .send_command ('Debugger.resume' , {})
1547
1575
1576
+ def process_runtime_event (self , event , msg ):
1577
+ """Handle Runtime.* events"""
1578
+ if event == 'executionContextCreated' :
1579
+ if 'params' in msg and 'context' in msg ['params' ] and 'id' in msg ['params' ]['context' ] and 'origin' :
1580
+ context = msg ['params' ]['context' ]
1581
+ id = context ['id' ]
1582
+ ctx = {'id' : id }
1583
+ if 'origin' in context :
1584
+ ctx ['origin' ] = context ['origin' ]
1585
+ if 'name' in context :
1586
+ ctx ['name' ] = context ['name' ]
1587
+ self .execution_contexts [id ] = ctx
1588
+ logging .debug ('Execution context created: %s' , json .dumps (context ))
1589
+ elif event == 'executionContextDestroyed' :
1590
+ if 'params' in msg and 'executionContextId' in msg ['params' ]:
1591
+ id = msg ['params' ]['executionContextId' ]
1592
+ if id in self .execution_contexts :
1593
+ del self .execution_contexts [id ]
1594
+ logging .debug ('Execution context %d deleted' , id )
1595
+
1548
1596
def process_network_event (self , event , msg , target_id = None ):
1549
1597
"""Process Network.* dev tools events"""
1550
1598
if event == 'requestIntercepted' :
0 commit comments