annotate pydershell/pydershell.py @ 21:1950b0b5bcd8

It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
author Atul Varma <varmaa@toolness.com>
date Mon, 07 Sep 2009 15:33:35 -0700
parents 8dd18f864351
children 9413bebf2ee6
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
11
74f27983a350 Added more to pydershell.
Atul Varma <varmaa@toolness.com>
parents: 10
diff changeset
1 #! /usr/bin/env python
74f27983a350 Added more to pydershell.
Atul Varma <varmaa@toolness.com>
parents: 10
diff changeset
2
10
fb25af17bae6 Added pydershell.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
3 import sys
fb25af17bae6 Added pydershell.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
4 import time
fb25af17bae6 Added pydershell.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
5 import threading
fb25af17bae6 Added pydershell.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
6 import traceback
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
7 import weakref
21
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
8 import types
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
9
10
fb25af17bae6 Added pydershell.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
10 import pydermonkey
fb25af17bae6 Added pydershell.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
11
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
12 class ContextWatchdogThread(threading.Thread):
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
13 """
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
14 Watches active JS contexts and triggers their operation callbacks
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
15 at a regular interval.
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
16 """
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
17
13
2a3313bfe574 Minor refactoring.
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
18 DEFAULT_INTERVAL = 0.25
2a3313bfe574 Minor refactoring.
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
19
2a3313bfe574 Minor refactoring.
Atul Varma <varmaa@toolness.com>
parents: 12
diff changeset
20 def __init__(self, interval=DEFAULT_INTERVAL):
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
21 threading.Thread.__init__(self)
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
22 self._lock = threading.Lock()
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
23 self._stop = threading.Event()
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
24 self._contexts = []
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
25 self.interval = interval
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
26 self.setDaemon(True)
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
27
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
28 def add_context(self, cx):
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
29 self._lock.acquire()
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
30 try:
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
31 self._contexts.append(weakref.ref(cx))
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
32 finally:
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
33 self._lock.release()
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
34
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
35 def join(self):
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
36 self._stop.set()
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
37 threading.Thread.join(self)
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
38
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
39 def run(self):
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
40 while not self._stop.isSet():
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
41 time.sleep(self.interval)
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
42 new_list = []
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
43 self._lock.acquire()
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
44 try:
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
45 for weakcx in self._contexts:
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
46 cx = weakcx()
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
47 if cx:
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
48 new_list.append(weakcx)
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
49 cx.trigger_operation_callback()
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
50 self._contexts = new_list
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
51 finally:
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
52 self._lock.release()
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
53
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
54 # Create a global watchdog.
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
55 watchdog = ContextWatchdogThread()
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
56 watchdog.start()
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
57
11
74f27983a350 Added more to pydershell.
Atul Varma <varmaa@toolness.com>
parents: 10
diff changeset
58 class InternalError(BaseException):
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
59 """
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
60 Represents an error in a JS-wrapped Python function that wasn't
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
61 expected to happen; because it's derived from BaseException, it
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
62 unrolls the whole JS/Python stack so that the error can be
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
63 reported to the outermost calling code.
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
64 """
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
65
11
74f27983a350 Added more to pydershell.
Atul Varma <varmaa@toolness.com>
parents: 10
diff changeset
66 def __init__(self):
74f27983a350 Added more to pydershell.
Atul Varma <varmaa@toolness.com>
parents: 10
diff changeset
67 BaseException.__init__(self)
74f27983a350 Added more to pydershell.
Atul Varma <varmaa@toolness.com>
parents: 10
diff changeset
68 self.exc_info = sys.exc_info()
74f27983a350 Added more to pydershell.
Atul Varma <varmaa@toolness.com>
parents: 10
diff changeset
69
17
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
70 class SafeJsObjectWrapper(object):
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
71 """
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
72 Securely wraps a JS object to behave like any normal Python object.
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
73 """
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
74
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
75 __slots__ = ['_jsobject', '_sandbox', '_this']
17
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
76
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
77 def __init__(self, sandbox, jsobject, this):
17
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
78 if not isinstance(jsobject, pydermonkey.Object):
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
79 raise TypeError("Cannot wrap '%s' object" %
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
80 type(jsobject).__name__)
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
81 object.__setattr__(self, '_sandbox', sandbox)
17
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
82 object.__setattr__(self, '_jsobject', jsobject)
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
83 object.__setattr__(self, '_this', this)
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
84
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
85 @property
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
86 def wrapped_jsobject(self):
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
87 return self._jsobject
17
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
88
18
69e5523ebdc6 Separated out SafeJsObjectWrapper into itself and a new subclass, SafeJsFunctionWrapper, so that callable() works properly on instances.
Atul Varma <varmaa@toolness.com>
parents: 17
diff changeset
89 def _wrap_to_python(self, jsvalue):
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
90 return self._sandbox.wrap_jsobject(jsvalue, self._jsobject)
18
69e5523ebdc6 Separated out SafeJsObjectWrapper into itself and a new subclass, SafeJsFunctionWrapper, so that callable() works properly on instances.
Atul Varma <varmaa@toolness.com>
parents: 17
diff changeset
91
69e5523ebdc6 Separated out SafeJsObjectWrapper into itself and a new subclass, SafeJsFunctionWrapper, so that callable() works properly on instances.
Atul Varma <varmaa@toolness.com>
parents: 17
diff changeset
92 def _wrap_to_js(self, value):
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
93 return self._sandbox.wrap_pyobject(value)
17
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
94
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
95 def __eq__(self, other):
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
96 if isinstance(other, SafeJsObjectWrapper):
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
97 return self._jsobject == other._jsobject
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
98 else:
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
99 return False
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
100
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
101 def __str__(self):
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
102 return self.toString()
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
103
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
104 def __unicode__(self):
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
105 return self.toString()
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
106
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
107 def __setitem__(self, item, value):
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
108 self.__setattr__(item, value)
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
109
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
110 def __setattr__(self, name, value):
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
111 cx = self._sandbox.cx
17
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
112 jsobject = self._jsobject
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
113
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
114 cx.define_property(jsobject, name,
18
69e5523ebdc6 Separated out SafeJsObjectWrapper into itself and a new subclass, SafeJsFunctionWrapper, so that callable() works properly on instances.
Atul Varma <varmaa@toolness.com>
parents: 17
diff changeset
115 self._wrap_to_js(value))
17
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
116
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
117 def __getitem__(self, item):
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
118 return self.__getattr__(item)
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
119
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
120 def __getattr__(self, name):
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
121 cx = self._sandbox.cx
17
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
122 jsobject = self._jsobject
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
123
18
69e5523ebdc6 Separated out SafeJsObjectWrapper into itself and a new subclass, SafeJsFunctionWrapper, so that callable() works properly on instances.
Atul Varma <varmaa@toolness.com>
parents: 17
diff changeset
124 return self._wrap_to_python(cx.get_property(jsobject, name))
17
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
125
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
126 def __contains__(self, item):
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
127 cx = self._sandbox.cx
17
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
128 jsobject = self._jsobject
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
129
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
130 return cx.has_property(jsobject, item)
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
131
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
132 def __iter__(self):
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
133 cx = self._sandbox.cx
17
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
134 jsobject = self._jsobject
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
135
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
136 properties = cx.enumerate(jsobject)
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
137 for property in properties:
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
138 yield property
1d62177c5c27 Added a safe js object wrapper.
Atul Varma <varmaa@toolness.com>
parents: 16
diff changeset
139
18
69e5523ebdc6 Separated out SafeJsObjectWrapper into itself and a new subclass, SafeJsFunctionWrapper, so that callable() works properly on instances.
Atul Varma <varmaa@toolness.com>
parents: 17
diff changeset
140 class SafeJsFunctionWrapper(SafeJsObjectWrapper):
69e5523ebdc6 Separated out SafeJsObjectWrapper into itself and a new subclass, SafeJsFunctionWrapper, so that callable() works properly on instances.
Atul Varma <varmaa@toolness.com>
parents: 17
diff changeset
141 """
69e5523ebdc6 Separated out SafeJsObjectWrapper into itself and a new subclass, SafeJsFunctionWrapper, so that callable() works properly on instances.
Atul Varma <varmaa@toolness.com>
parents: 17
diff changeset
142 Securely wraps a JS function to behave like any normal Python object.
69e5523ebdc6 Separated out SafeJsObjectWrapper into itself and a new subclass, SafeJsFunctionWrapper, so that callable() works properly on instances.
Atul Varma <varmaa@toolness.com>
parents: 17
diff changeset
143 """
69e5523ebdc6 Separated out SafeJsObjectWrapper into itself and a new subclass, SafeJsFunctionWrapper, so that callable() works properly on instances.
Atul Varma <varmaa@toolness.com>
parents: 17
diff changeset
144
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
145 def __init__(self, sandbox, jsfunction, this):
18
69e5523ebdc6 Separated out SafeJsObjectWrapper into itself and a new subclass, SafeJsFunctionWrapper, so that callable() works properly on instances.
Atul Varma <varmaa@toolness.com>
parents: 17
diff changeset
146 if not isinstance(jsfunction, pydermonkey.Function):
69e5523ebdc6 Separated out SafeJsObjectWrapper into itself and a new subclass, SafeJsFunctionWrapper, so that callable() works properly on instances.
Atul Varma <varmaa@toolness.com>
parents: 17
diff changeset
147 raise TypeError("Cannot wrap '%s' object" %
69e5523ebdc6 Separated out SafeJsObjectWrapper into itself and a new subclass, SafeJsFunctionWrapper, so that callable() works properly on instances.
Atul Varma <varmaa@toolness.com>
parents: 17
diff changeset
148 type(jsobject).__name__)
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
149 SafeJsObjectWrapper.__init__(self, sandbox, jsfunction, this)
18
69e5523ebdc6 Separated out SafeJsObjectWrapper into itself and a new subclass, SafeJsFunctionWrapper, so that callable() works properly on instances.
Atul Varma <varmaa@toolness.com>
parents: 17
diff changeset
150
69e5523ebdc6 Separated out SafeJsObjectWrapper into itself and a new subclass, SafeJsFunctionWrapper, so that callable() works properly on instances.
Atul Varma <varmaa@toolness.com>
parents: 17
diff changeset
151 def __call__(self, *args):
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
152 cx = self._sandbox.cx
18
69e5523ebdc6 Separated out SafeJsObjectWrapper into itself and a new subclass, SafeJsFunctionWrapper, so that callable() works properly on instances.
Atul Varma <varmaa@toolness.com>
parents: 17
diff changeset
153 jsobject = self._jsobject
69e5523ebdc6 Separated out SafeJsObjectWrapper into itself and a new subclass, SafeJsFunctionWrapper, so that callable() works properly on instances.
Atul Varma <varmaa@toolness.com>
parents: 17
diff changeset
154 this = self._this
69e5523ebdc6 Separated out SafeJsObjectWrapper into itself and a new subclass, SafeJsFunctionWrapper, so that callable() works properly on instances.
Atul Varma <varmaa@toolness.com>
parents: 17
diff changeset
155
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
156 arglist = []
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
157 for arg in args:
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
158 arglist.append(self._wrap_to_js(arg))
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
159
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
160 obj = cx.call_function(this, jsobject, tuple(arglist))
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
161 return self._wrap_to_python(obj)
11
74f27983a350 Added more to pydershell.
Atul Varma <varmaa@toolness.com>
parents: 10
diff changeset
162
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
163 def format_stack(js_stack):
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
164 """
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
165 Returns a formatted Python-esque stack traceback of the given
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
166 JS stack.
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
167 """
10
fb25af17bae6 Added pydershell.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
168
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
169 STACK_LINE =" File \"%(filename)s\", line %(lineno)d, in %(name)s"
10
fb25af17bae6 Added pydershell.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
170
fb25af17bae6 Added pydershell.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
171 lines = []
fb25af17bae6 Added pydershell.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
172 while js_stack:
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
173 script = js_stack['script']
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
174 function = js_stack['function']
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
175 if script:
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
176 frameinfo = dict(filename = script.filename,
16
a78570a423ea Show code excerpts in js stack tracebacks
Atul Varma <varmaa@toolness.com>
parents: 15
diff changeset
177 lineno = js_stack['lineno'],
a78570a423ea Show code excerpts in js stack tracebacks
Atul Varma <varmaa@toolness.com>
parents: 15
diff changeset
178 name = '<module>')
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
179 elif function and not function.is_python:
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
180 frameinfo = dict(filename = function.filename,
16
a78570a423ea Show code excerpts in js stack tracebacks
Atul Varma <varmaa@toolness.com>
parents: 15
diff changeset
181 lineno = js_stack['lineno'],
a78570a423ea Show code excerpts in js stack tracebacks
Atul Varma <varmaa@toolness.com>
parents: 15
diff changeset
182 name = function.name)
10
fb25af17bae6 Added pydershell.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
183 else:
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
184 frameinfo = None
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
185 if frameinfo:
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
186 lines.insert(0, STACK_LINE % frameinfo)
16
a78570a423ea Show code excerpts in js stack tracebacks
Atul Varma <varmaa@toolness.com>
parents: 15
diff changeset
187 try:
a78570a423ea Show code excerpts in js stack tracebacks
Atul Varma <varmaa@toolness.com>
parents: 15
diff changeset
188 filelines = open(frameinfo['filename']).readlines()
a78570a423ea Show code excerpts in js stack tracebacks
Atul Varma <varmaa@toolness.com>
parents: 15
diff changeset
189 line = filelines[frameinfo['lineno'] - 1].strip()
a78570a423ea Show code excerpts in js stack tracebacks
Atul Varma <varmaa@toolness.com>
parents: 15
diff changeset
190 lines.insert(1, " %s" % line)
a78570a423ea Show code excerpts in js stack tracebacks
Atul Varma <varmaa@toolness.com>
parents: 15
diff changeset
191 except Exception:
a78570a423ea Show code excerpts in js stack tracebacks
Atul Varma <varmaa@toolness.com>
parents: 15
diff changeset
192 pass
10
fb25af17bae6 Added pydershell.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
193 js_stack = js_stack['caller']
fb25af17bae6 Added pydershell.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
194 lines.insert(0, "Traceback (most recent call last):")
fb25af17bae6 Added pydershell.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
195 return '\n'.join(lines)
fb25af17bae6 Added pydershell.
Atul Varma <varmaa@toolness.com>
parents:
diff changeset
196
21
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
197 class JsExposedObject(object):
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
198 """
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
199 Trivial base/mixin class for any Python classes that choose to
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
200 expose themselves to JS code.
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
201 """
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
202
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
203 pass
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
204
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
205 class JsSandbox(object):
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
206 """
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
207 A JS runtime and associated functionality capable of securely
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
208 loading and executing scripts.
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
209 """
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
210
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
211 def __init__(self, watchdog=watchdog):
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
212 rt = pydermonkey.Runtime()
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
213 cx = rt.new_context()
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
214 root = cx.new_object()
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
215 cx.init_standard_classes(root)
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
216
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
217 cx.set_operation_callback(self._opcb)
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
218 cx.set_throw_hook(self._throwhook)
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
219 watchdog.add_context(cx)
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
220
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
221 self.rt = rt
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
222 self.cx = cx
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
223 self.curr_exc = None
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
224 self.py_stack = None
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
225 self.js_stack = None
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
226 self.__py_to_js = {}
21
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
227 self.__type_protos = {}
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
228 self.root = self.wrap_jsobject(root, root)
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
229
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
230 def finish(self):
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
231 for jsobj in self.__py_to_js.values():
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
232 self.cx.clear_object_private(jsobj)
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
233 del self.__py_to_js
21
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
234 del self.__type_protos
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
235 del self.curr_exc
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
236 del self.py_stack
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
237 del self.js_stack
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
238 del self.cx
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
239 del self.rt
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
240
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
241 def _opcb(self, cx):
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
242 # Don't do anything; if a keyboard interrupt was triggered,
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
243 # it'll get raised here automatically.
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
244 pass
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
245
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
246 def _throwhook(self, cx):
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
247 curr_exc = cx.get_pending_exception()
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
248 if self.curr_exc != curr_exc:
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
249 self.curr_exc = curr_exc
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
250 self.py_stack = traceback.extract_stack()
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
251 self.js_stack = cx.get_stack()
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
252
21
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
253 def __wrap_pycallable(self, func, pyproto=None):
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
254 if func in self.__py_to_js:
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
255 return self.__py_to_js[func]
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
256
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
257 if hasattr(func, '__name__'):
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
258 name = func.__name__
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
259 else:
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
260 name = ""
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
261
21
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
262 if pyproto:
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
263 def wrapper(func_cx, this, args):
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
264 try:
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
265 arglist = []
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
266 for arg in args:
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
267 arglist.append(self.wrap_jsobject(arg))
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
268 instance = func_cx.get_object_private(this)
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
269 if instance is None or not isinstance(instance, pyproto):
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
270 raise pydermonkey.error("Method type mismatch")
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
271
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
272 # TODO: Fill in extra required params with
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
273 # pymonkey.undefined? or automatically throw an
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
274 # exception to calling js code?
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
275 return self.wrap_pyobject(func(instance, *arglist))
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
276 except pydermonkey.error:
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
277 raise
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
278 except Exception:
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
279 raise InternalError()
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
280 else:
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
281 def wrapper(func_cx, this, args):
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
282 try:
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
283 arglist = []
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
284 for arg in args:
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
285 arglist.append(self.wrap_jsobject(arg))
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
286
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
287 # TODO: Fill in extra required params with
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
288 # pymonkey.undefined? or automatically throw an
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
289 # exception to calling js code?
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
290 return self.wrap_pyobject(func(*arglist))
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
291 except pydermonkey.error:
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
292 raise
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
293 except Exception:
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
294 raise InternalError()
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
295 wrapper.wrapped_pyobject = func
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
296 wrapper.__name__ = name
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
297
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
298 jsfunc = self.cx.new_function(wrapper, name)
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
299 self.__py_to_js[func] = jsfunc
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
300
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
301 return jsfunc
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
302
21
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
303 def __wrap_pyinstance(self, value):
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
304 pyproto = type(value)
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
305 if pyproto not in self.__type_protos:
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
306 jsproto = self.cx.new_object()
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
307 for name in dir(pyproto):
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
308 attr = getattr(pyproto, name)
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
309 if (isinstance(attr, types.UnboundMethodType) and
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
310 hasattr(attr, '__jsexposed__') and
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
311 attr.__jsexposed__):
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
312 jsmethod = self.__wrap_pycallable(attr, pyproto)
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
313 self.cx.define_property(jsproto, name, jsmethod)
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
314 self.__type_protos[pyproto] = jsproto
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
315 return self.cx.new_object(value, self.__type_protos[pyproto])
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
316
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
317 def wrap_pyobject(self, value):
21
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
318 if (isinstance(value, (int, basestring, float, bool)) or
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
319 value is pydermonkey.undefined or
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
320 value is None):
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
321 return value
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
322 if isinstance(value, SafeJsObjectWrapper):
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
323 # It's already wrapped, just unwrap it.
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
324 return value.wrapped_jsobject
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
325 elif callable(value):
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
326 return self.__wrap_pycallable(value)
21
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
327 elif isinstance(value, JsExposedObject):
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
328 return self.__wrap_pyinstance(value)
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
329 else:
21
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
330 raise TypeError("Can't expose objects of type '' to JS." %
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
331 type(value).__name__)
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
332
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
333 def wrap_jsobject(self, jsvalue, this=None):
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
334 if this is None:
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
335 this = self.root.wrapped_jsobject
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
336 if isinstance(jsvalue, pydermonkey.Function):
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
337 if jsvalue.is_python:
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
338 # It's a Python function, just unwrap it.
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
339 return self.cx.get_object_private(jsvalue).wrapped_pyobject
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
340 return SafeJsFunctionWrapper(self, jsvalue, this)
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
341 elif isinstance(jsvalue, pydermonkey.Object):
21
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
342 # It's a wrapped Python object instance, just unwrap it.
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
343 instance = self.cx.get_object_private(jsvalue)
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
344 if instance:
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
345 if not isinstance(instance, JsExposedObject):
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
346 raise AssertionError("Object private is not of type "
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
347 "JsExposedObject")
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
348 return instance
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
349 else:
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
350 return SafeJsObjectWrapper(self, jsvalue, this)
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
351 else:
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
352 # It's a primitive value.
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
353 return jsvalue
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
354
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
355 def run_script(self, filename):
20
8dd18f864351 pydershell now exits with a nonzero return code if the script it calls throws an exception.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
356 retval = -1
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
357 contents = open(filename).read()
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
358 cx = self.cx
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
359 try:
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
360 cx.evaluate_script(self.root.wrapped_jsobject, contents,
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
361 filename, 1)
20
8dd18f864351 pydershell now exits with a nonzero return code if the script it calls throws an exception.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
362 retval = 0
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
363 except pydermonkey.error, e:
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
364 print format_stack(self.js_stack)
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
365 print e.args[1]
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
366 except InternalError, e:
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
367 print "An internal error occurred."
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
368 traceback.print_tb(e.exc_info[2])
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
369 print e.exc_info[1]
20
8dd18f864351 pydershell now exits with a nonzero return code if the script it calls throws an exception.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
370 return retval
12
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
371
f024e41d0fb9 More refactoring, a bit more documentation.
Atul Varma <varmaa@toolness.com>
parents: 11
diff changeset
372 if __name__ == '__main__':
21
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
373 sandbox = JsSandbox()
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
374
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
375 class Baz(JsExposedObject):
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
376 def woozle(self, blap):
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
377 return blap + 5
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
378 woozle.__jsexposed__ = True
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
379
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
380 def baz():
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
381 return Baz()
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
382 sandbox.root.baz = baz
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
383
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
384 def bar(obj):
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
385 print obj.bar()
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
386 sandbox.root.bar = bar
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
387
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
388 def foo(callback):
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
389 return callback()
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
390 sandbox.root.foo = foo
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
391
21
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
392 def ensureBaz(baz):
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
393 if not isinstance(baz, Baz):
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
394 print "Uhoh"
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
395 else:
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
396 print "ok"
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
397 sandbox.root.ensureBaz = ensureBaz
1950b0b5bcd8 It's now possible to expose python class instances to JS, if they're declared the right way (for security purposes).
Atul Varma <varmaa@toolness.com>
parents: 20
diff changeset
398
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
399 def jsprint(string):
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
400 print string
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
401 sandbox.root['print'] = jsprint
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
402
20
8dd18f864351 pydershell now exits with a nonzero return code if the script it calls throws an exception.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
403 retval = sandbox.run_script('test.js')
19
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
404
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
405 sandbox.finish()
057260102960 Made wrapping of python objects much nicer.
Atul Varma <varmaa@toolness.com>
parents: 18
diff changeset
406 del sandbox
15
351525e95a45 Added memory leak detection.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
407
351525e95a45 Added memory leak detection.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
408 import gc
351525e95a45 Added memory leak detection.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
409 gc.collect()
351525e95a45 Added memory leak detection.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
410 if pydermonkey.get_debug_info()['runtime_count']:
351525e95a45 Added memory leak detection.
Atul Varma <varmaa@toolness.com>
parents: 14
diff changeset
411 print "WARNING: JS runtime was not destroyed."
20
8dd18f864351 pydershell now exits with a nonzero return code if the script it calls throws an exception.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
412
8dd18f864351 pydershell now exits with a nonzero return code if the script it calls throws an exception.
Atul Varma <varmaa@toolness.com>
parents: 19
diff changeset
413 sys.exit(retval)