A new improvement in PHoneyC DOM emulation code was committed in SVN r1624. The idea is to better emulate the DOM behaviour depending on the selected browser personality. Let’s take a look at the code starting from the personalities definition in config.py.
39 UserAgents = [
40 (1,
41 “Internet Explorer 6.0 (Windows 2000)”,
42 “Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727)”,
43 “Mozilla”,
44 “Microsoft Internet Explorer”,
45 “4.0 (compatible; MSIE 6.0; Windows NT 5.0; .NET CLR 1.1.4322; .NET CLR 2.0.50727)”,
46 “ie60″,
47 ),
48 (2,
49 “Internet Explorer 6.1 (Windows XP)”,
50 “Mozilla/4.0 (compatible; MSIE 6.1; Windows XP; .NET CLR 1.1.4322; .NET CLR 2.0.50727)”,
51 “Mozilla”,
52 “Microsoft Internet Explorer”,
53 “4.0 (compatible; MSIE 6.1; Windows XP; .NET CLR 1.1.4322; .NET CLR 2.0.50727)”,
54 “ie61″,
55 ),
56 (3,
57 “Internet Explorer 7.0 (Windows XP)”,
58 “Mozilla/4.0 (Windows; MSIE 7.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)”,
59 “Mozilla”,
60 “Microsoft Internet Explorer”,
61 “4.0 (Windows; MSIE 7.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727)”,
62 “ie70″,
63 ),
64 (4,
65 “Internet Explorer 8.0 (Windows XP)”,
66 “Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; (R1 1.5); .NET CLR 1.1.4322; .NET CLR 2.0.50727)”,
67 “Mozilla”,
68 “Microsoft Internet Explorer”,
69 “4.0 (compatible; MSIE 8.0; Windows NT 5.1; Trident/4.0; (R1 1.5); .NET CLR 1.1.4322; .NET CLR 2.0.50727)”,
70 “ie80″,
71 ),
72 ]
It’s important to realize that each personality was added a tag (i.e. ie80). Taking a look at DOM/Window.py the following code can be seen.
229 def __init_methods(self):
230 for attr in dir(self):
231 prefix = “_Window__window_%s_” % (config.browserTag, )
232 if attr.startswith(prefix):
233 p = attr.split(prefix)[1]
234 self.__dict__[‘__cx’].add_global(p, getattr(self, attr))
235 self.__dict__[‘__cx’].execute(“window.%s = %s;” % (p, p, ))
Let’s consider an example and assume the Internet Explorer 8.0 personality was selected. It’s easy to realize that the prefix would assume the value _Window__window_ie80_. A few simple wrappers were created, one per personality, to each method as shown in the following code.
340 def __window_back(self):
341 “””
342 Returns the window to the previous item in the history.
343 Syntax
344
345 window.back()
346
347 Parameters
348
349 None.
350 “””
351 pass
352
353 def __window_ie60_back(self):
354 self.__window_back()
355
356 def __window_ie61_back(self):
357 self.__window_back()
358
359 def __window_ie70_back(self):
360 self.__window_back()
361
362 def __window_ie80_back(self):
363 self.__window_back()
364
365 def __window_firefox_back(self):
366 self.__window_back()
This is a quite simple situation but what if you want to define addEventListener method just for Firefox personalities and attachEvent just for Internet Explorer ones? Really simple to do!
1191 def __window_attachEvent(self, sEvent, fpNotify):
1192 if dataetc.isevent(sEvent, ‘window’):
1193 self.__dict__[sEvent] = fpNotify
1194
1195 def __window_ie60_attachEvent(self, sEvent, fpNotify):
1196 self.__window_attachEvent(sEvent, fpNotify)
1197
1198 def __window_ie61_attachEvent(self, sEvent, fpNotify):
1199 self.__window_attachEvent(sEvent, fpNotify)
1200
1201 def __window_ie70_attachEvent(self, sEvent, fpNotify):
1202 self.__window_attachEvent(sEvent, fpNotify)
1203
1204 def __window_ie80_attachEvent(self, sEvent, fpNotify):
1205 self.__window_attachEvent(sEvent, fpNotify)
1206
1207
1208 def __window_detachEvent(self, sEvent, fpNotify):
1209 if sEvent in self.__dict__ and self.__dict__[sEvent] == fpNotify:
1210 del self.__dict__[sEvent]
1211
1212 def __window_ie60_detachEvent(self, sEvent, fpNotify):
1213 self.__window_detachEvent(sEvent, fpNotify)
1214
1215 def __window_ie61_detachEvent(self, sEvent, fpNotify):
1216 self.__window_detachEvent(sEvent, fpNotify)
1217
1218 def __window_ie70_detachEvent(self, sEvent, fpNotify):
1219 self.__window_detachEvent(sEvent, fpNotify)
1220
1221 def __window_ie80_detachEvent(self, sEvent, fpNotify):
1222 self.__window_detachEvent(sEvent, fpNotify)
1223
1224
1225 def __window_addEventListener(self, type, listener, useCapture = False):
1226 if dataetc.isevent(type, ‘window’):
1227 self.__dict__[type] = listener
1228
1229 def __window_firefox_addEventListener(self, type, listener, useCapture = False):
1230 self.__window_addEventListener(type, listener, useCapture = False)
1231
1232
1233 def __window_removeEventListener(self, type, listener, useCapture = False):
1234 if type in self.__dict__ and self.__dict__[type] == listener:
1235 del self.__dict__[type]
1236
1237 def __window_firefox_removeEventListener(self, type, listener, useCapture = False):
1238 self.__window_removeEventListener(type, listener, useCapture = False)
Moreover this approach could allow to insert specific code within the wrappers if needed while implementing the method functionalities in the higher level __window_<method_name> wrapper.