Merge extensions/python/xpcom changes from DOM_AGNOSTIC2_BRANCH into the
trunk. git-svn-id: svn://10.0.0.236/trunk@187878 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
@@ -38,11 +38,16 @@
|
||||
|
||||
DEPTH =../../..
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
DIRS = \
|
||||
src \
|
||||
test/test_component \
|
||||
$(NULL)
|
||||
|
||||
ifdef ENABLE_TESTS
|
||||
DIRS += test $(NULL)
|
||||
endif
|
||||
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
@@ -53,7 +58,7 @@ PYSRCS_XPCOM = \
|
||||
components.py \
|
||||
file.py \
|
||||
nsError.py \
|
||||
register.py \
|
||||
primitives.py \
|
||||
shutdown.py \
|
||||
xpcom_consts.py \
|
||||
xpt.py \
|
||||
|
||||
@@ -39,18 +39,10 @@
|
||||
# The XPCOM (Cross Platform COM) package.
|
||||
import exceptions
|
||||
|
||||
|
||||
import sys
|
||||
#sys.stdout = open("pystdout.log", "w")
|
||||
if sys.version_info >= (2, 3):
|
||||
# sick off the new hex() warnings, and no time to digest what the
|
||||
# impact will be!
|
||||
import warnings
|
||||
warnings.filterwarnings("ignore", category=FutureWarning, append=1)
|
||||
|
||||
# A global "verbose" flag - currently used by the
|
||||
# server package to print trace messages
|
||||
verbose = 0
|
||||
# Map of nsresult -> constant_name.
|
||||
hr_map = {}
|
||||
|
||||
# The standard XPCOM exception object.
|
||||
@@ -72,10 +64,10 @@ class Exception(exceptions.Exception):
|
||||
message = hr_map.get(self.errno)
|
||||
if message is None:
|
||||
message = ""
|
||||
return "0x%x (%s)" % (self.errno, message)
|
||||
return "%d (%s)" % (self.errno, message)
|
||||
|
||||
# An alias for Exception - allows code to say "from xpcom import COMException"
|
||||
# rather than "Exception" - thereby preventing clashes.
|
||||
# rather than "Exception", preventing clashes with the builtin Exception
|
||||
COMException = Exception
|
||||
|
||||
# Exceptions thrown by servers. It can be good for diagnostics to
|
||||
@@ -83,7 +75,7 @@ COMException = Exception
|
||||
# and a normal exception which may simply be propagating down.
|
||||
# (When ServerException objects are thrown across the XPConnect
|
||||
# gateway they will be converted back to normal client exceptions if
|
||||
# subsequently re-caught by Python
|
||||
# subsequently re-caught by Python)
|
||||
class ServerException(Exception):
|
||||
def __init__(self, errno=None, *args, **kw):
|
||||
if errno is None:
|
||||
@@ -91,4 +83,82 @@ class ServerException(Exception):
|
||||
errno = nsError.NS_ERROR_FAILURE
|
||||
Exception.__init__(self, errno, *args, **kw)
|
||||
|
||||
# Some global functions.
|
||||
# Logging support - setup the 'xpcom' logger to write to the Mozilla
|
||||
# console service, and also to sys.stderr, or optionally a file.
|
||||
# Environment variables supports:
|
||||
# PYXPCOM_LOG_FILE=filename - if set, used instead of sys.stderr.
|
||||
# PYXPCOM_LOG_LEVEL=level - level may be a number or a logging level
|
||||
# constant (eg, 'debug', 'error')
|
||||
# Later it may make sense to allow a different log level to be set for
|
||||
# the file than for the console service.
|
||||
import logging
|
||||
class ConsoleServiceStream:
|
||||
# enough of a stream to keep logging happy
|
||||
def flush(self):
|
||||
pass
|
||||
def write(self, msg):
|
||||
import _xpcom
|
||||
_xpcom.LogConsoleMessage(msg)
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
def setupLogging():
|
||||
import sys, os, threading, thread
|
||||
hdlr = logging.StreamHandler(ConsoleServiceStream())
|
||||
fmt = logging.Formatter(logging.BASIC_FORMAT)
|
||||
hdlr.setFormatter(fmt)
|
||||
# There is a bug in 2.3 and 2.4.x logging module in that it doesn't
|
||||
# use an RLock, leading to deadlocks in some cases (specifically,
|
||||
# logger.warning("ob is %r", ob), and where repr(ob) itself tries to log)
|
||||
# Later versions of logging use an RLock, so we detect an "old" style
|
||||
# handler and update its lock
|
||||
if type(hdlr.lock) == thread.LockType:
|
||||
hdlr.lock = threading.RLock()
|
||||
|
||||
logger.addHandler(hdlr)
|
||||
# The console handler in mozilla does not go to the console!?
|
||||
# Add a handler to print to stderr, or optionally a file
|
||||
# PYXPCOM_LOG_FILE can specify a filename
|
||||
filename = os.environ.get("PYXPCOM_LOG_FILE")
|
||||
stream = sys.stderr # this is what logging uses as default
|
||||
if filename:
|
||||
try:
|
||||
# open without buffering so never pending output
|
||||
stream = open(filename, "wU", 0)
|
||||
except IOError, why:
|
||||
print >> sys.stderr, "pyxpcom failed to open log file '%s': %s" \
|
||||
% (filename, why)
|
||||
# stream remains default
|
||||
|
||||
hdlr = logging.StreamHandler(stream)
|
||||
# see above - fix a deadlock problem on this handler too.
|
||||
if type(hdlr.lock) == thread.LockType:
|
||||
hdlr.lock = threading.RLock()
|
||||
|
||||
fmt = logging.Formatter(logging.BASIC_FORMAT)
|
||||
hdlr.setFormatter(fmt)
|
||||
logger.addHandler(hdlr)
|
||||
# Allow PYXPCOM_LOG_LEVEL to set the level
|
||||
level = os.environ.get("PYXPCOM_LOG_LEVEL")
|
||||
if level:
|
||||
try:
|
||||
level = int(level)
|
||||
except ValueError:
|
||||
try:
|
||||
# might be a symbolic name - all are upper-case
|
||||
level = int(getattr(logging, level.upper()))
|
||||
except (AttributeError, ValueError):
|
||||
logger.warning("The PYXPCOM_LOG_LEVEL variable specifies an "
|
||||
"invalid level")
|
||||
level = None
|
||||
if level:
|
||||
logger.setLevel(level)
|
||||
|
||||
logger = logging.getLogger('xpcom')
|
||||
# If someone else has already setup this logger, leave things alone.
|
||||
if len(logger.handlers) == 0:
|
||||
setupLogging()
|
||||
|
||||
# Cleanup namespace - but leave 'logger' there for people to use, so they
|
||||
# don't need to know the exact name of the logger.
|
||||
del ConsoleServiceStream, logging, setupLogging
|
||||
|
||||
@@ -37,15 +37,18 @@
|
||||
|
||||
import os
|
||||
import new
|
||||
from xpcom import xpt, COMException, nsError
|
||||
import logging
|
||||
from xpcom import xpt, COMException, nsError, logger
|
||||
|
||||
# Suck in stuff from _xpcom we use regularly to prevent a module lookup
|
||||
from xpcom._xpcom import IID_nsISupports, IID_nsIClassInfo, IID_nsISupportsCString, IID_nsISupportsWeakReference, \
|
||||
IID_nsIWeakReference, XPTI_GetInterfaceInfoManager, GetComponentManager, XPTC_InvokeByIndex
|
||||
from xpcom._xpcom import IID_nsISupports, IID_nsIClassInfo, \
|
||||
IID_nsISupportsCString, IID_nsISupportsString, \
|
||||
IID_nsISupportsWeakReference, IID_nsIWeakReference, \
|
||||
XPTI_GetInterfaceInfoManager, GetComponentManager, XPTC_InvokeByIndex
|
||||
|
||||
# Attribute names we may be __getattr__'d for, but know we don't want to delegate
|
||||
# Could maybe just look for startswith("__") but this may screw things for some objects.
|
||||
_special_getattr_names = ["__del__", "__len__", "__nonzero__"]
|
||||
_special_getattr_names = ["__del__", "__len__", "__nonzero__", "__eq__", "__neq__"]
|
||||
|
||||
_just_int_interfaces = ["nsISupportsPRInt32", "nsISupportsPRInt16", "nsISupportsPRUint32", "nsISupportsPRUint16", "nsISupportsPRUint8", "nsISupportsPRBool"]
|
||||
_just_long_interfaces = ["nsISupportsPRInt64", "nsISupportsPRUint64"]
|
||||
@@ -176,6 +179,21 @@ class _XPCOMBase:
|
||||
def __hash__(self):
|
||||
return hash(self._comobj_)
|
||||
|
||||
# The basic rich compare ops for equality
|
||||
def __eq__(self, other):
|
||||
try:
|
||||
other = other._comobj_
|
||||
except AttributeError:
|
||||
pass
|
||||
return self._comobj_ == other
|
||||
|
||||
def __neq__(self, other):
|
||||
try:
|
||||
other = other._comobj_
|
||||
except AttributeError:
|
||||
pass
|
||||
return self._comobj_ != other
|
||||
|
||||
# See if the object support strings.
|
||||
def __str__(self):
|
||||
try:
|
||||
@@ -184,6 +202,13 @@ class _XPCOMBase:
|
||||
except COMException:
|
||||
return self.__repr__()
|
||||
|
||||
def __unicode__(self):
|
||||
try:
|
||||
prin = self._comobj_.QueryInterface(IID_nsISupportsString)
|
||||
except COMException:
|
||||
return unicode(str(self))
|
||||
return prin.data
|
||||
|
||||
# Try the numeric support.
|
||||
def _do_conversion(self, interface_names, cvt):
|
||||
iim = XPTI_GetInterfaceInfoManager()
|
||||
@@ -206,7 +231,7 @@ class _XPCOMBase:
|
||||
return self._do_conversion(_float_interfaces, float)
|
||||
|
||||
class Component(_XPCOMBase):
|
||||
def __init__(self, ob, iid):
|
||||
def __init__(self, ob, iid = IID_nsISupports):
|
||||
assert not hasattr(ob, "_comobj_"), "Should be a raw nsIWhatever, not a wrapped one"
|
||||
ob_name = None
|
||||
if not hasattr(ob, "IID"):
|
||||
@@ -220,7 +245,7 @@ class Component(_XPCOMBase):
|
||||
self.__dict__['_interfaces_'] = {} # keyed by IID
|
||||
self.__dict__['_interface_names_'] = {} # keyed by IID name
|
||||
self.__dict__['_interface_infos_'] = {} # keyed by IID
|
||||
self.__dict__['_name_to_interface_name_'] = {}
|
||||
self.__dict__['_name_to_interface_iid_'] = {}
|
||||
self.__dict__['_tried_classinfo_'] = 0
|
||||
|
||||
if ob_name is None:
|
||||
@@ -256,10 +281,11 @@ class Component(_XPCOMBase):
|
||||
for nominated_iid in interface_infos:
|
||||
# Interface may appear twice in the class info list, so check this here.
|
||||
if not self.__dict__['_interface_infos_'].has_key(nominated_iid):
|
||||
self._remember_interface_info(nominated_iid)
|
||||
# Just invoke our QI on the object
|
||||
self.queryInterface(nominated_iid)
|
||||
if real_cid is not None:
|
||||
contractid_info = {}
|
||||
contractid_info['_name_to_interface_name_'] = self.__dict__['_name_to_interface_name_']
|
||||
contractid_info['_name_to_interface_iid_'] = self.__dict__['_name_to_interface_iid_']
|
||||
contractid_info['_interface_infos_'] = self.__dict__['_interface_infos_']
|
||||
contractid_info_cache[real_cid] = contractid_info
|
||||
else:
|
||||
@@ -269,26 +295,28 @@ class Component(_XPCOMBase):
|
||||
self.__dict__['_com_classinfo_'] = classinfo
|
||||
|
||||
def _remember_interface_info(self, iid):
|
||||
method_infos, getters, setters, constants = BuildInterfaceInfo(iid)
|
||||
# Remember all the names so we can delegate
|
||||
assert not self.__dict__['_interface_infos_'].has_key(iid), "Already remembered this interface!"
|
||||
self.__dict__['_interface_infos_'][iid] = method_infos, getters, setters, constants
|
||||
interface_name = iid.name
|
||||
names = self.__dict__['_name_to_interface_name_']
|
||||
for name in method_infos.keys(): names[name] = interface_name
|
||||
for name in getters.keys(): names[name] = interface_name
|
||||
for name in setters.keys(): names[name] = interface_name
|
||||
for name in constants.keys(): names[name] = interface_name
|
||||
# XXX - there is no good reason to cache this only in each instance
|
||||
# It should be cached at the module level, so we don't need to
|
||||
# rebuild the world for each new object.
|
||||
iis = self.__dict__['_interface_infos_']
|
||||
assert not iis.has_key(iid), "Already remembered this interface!"
|
||||
try:
|
||||
method_infos, getters, setters, constants = BuildInterfaceInfo(iid)
|
||||
except COMException, why:
|
||||
# Failing to build an interface info generally isn't a real
|
||||
# problem - its probably just that the interface is non-scriptable.
|
||||
logger.info("Failed to build interface info for %s: %s", iid, why)
|
||||
# Remember the fact we failed.
|
||||
iis[iid] = None
|
||||
return
|
||||
|
||||
def _make_interface_info(self, ob, iid):
|
||||
interface_infos = self._interface_infos_
|
||||
assert not self._interfaces_.has_key(iid), "Already have made this interface"
|
||||
method_infos, getters, setters, constants = interface_infos[iid]
|
||||
new_interface = _Interface(ob, iid, method_infos, getters, setters, constants)
|
||||
self._interfaces_[iid] = new_interface
|
||||
self._interface_names_[iid.name] = new_interface
|
||||
# No point remembering these.
|
||||
del interface_infos[iid]
|
||||
# Remember all the names so we can delegate
|
||||
iis[iid] = method_infos, getters, setters, constants
|
||||
names = self.__dict__['_name_to_interface_iid_']
|
||||
for name in method_infos.keys(): names[name] = iid
|
||||
for name in getters.keys(): names[name] = iid
|
||||
for name in setters.keys(): names[name] = iid
|
||||
for name in constants.keys(): names[name] = iid
|
||||
|
||||
def QueryInterface(self, iid):
|
||||
if self._interfaces_.has_key(iid):
|
||||
@@ -297,10 +325,24 @@ class Component(_XPCOMBase):
|
||||
# Haven't seen this before - do a real QI.
|
||||
if not self._interface_infos_.has_key(iid):
|
||||
self._remember_interface_info(iid)
|
||||
ret = self._comobj_.QueryInterface(iid, 0)
|
||||
# print "Component QI for", iid, "yielded", ret
|
||||
self._make_interface_info(ret, iid)
|
||||
assert self._interfaces_.has_key(iid) and self._interface_names_.has_key(iid.name), "Making the interface didn't update the maps"
|
||||
iface_info = self._interface_infos_[iid]
|
||||
if iface_info is None:
|
||||
# We have tried, but failed, to get this interface info. Its
|
||||
# unlikely to work later either - its probably non-scriptable.
|
||||
# That means our component wrappers are useless - so just return a
|
||||
# raw nsISupports object with no wrapper.
|
||||
return self._comobj_.QueryInterface(iid, 0)
|
||||
|
||||
raw_iface = self._comobj_.QueryInterface(iid, 0)
|
||||
|
||||
method_infos, getters, setters, constants = iface_info
|
||||
new_interface = _Interface(raw_iface, iid, method_infos,
|
||||
getters, setters, constants)
|
||||
self._interfaces_[iid] = new_interface
|
||||
self._interface_names_[iid.name] = new_interface
|
||||
# As we 'flatten' objects when possible, a QI on an object just
|
||||
# returns ourself - all the methods etc on this interface are
|
||||
# available.
|
||||
return self
|
||||
|
||||
queryInterface = QueryInterface # Alternate name.
|
||||
@@ -312,47 +354,51 @@ class Component(_XPCOMBase):
|
||||
interface = self.__dict__['_interface_names_'].get(attr, None)
|
||||
if interface is not None:
|
||||
return interface
|
||||
interface_name = self.__dict__['_name_to_interface_name_'].get(attr, None)
|
||||
# See if we know the IID of an interface providing this attribute
|
||||
iid = self.__dict__['_name_to_interface_iid_'].get(attr, None)
|
||||
# This may be first time trying this interface - get the nsIClassInfo
|
||||
if interface_name is None and not self._tried_classinfo_:
|
||||
if iid is None and not self._tried_classinfo_:
|
||||
self._build_all_supported_interfaces_()
|
||||
interface_name = self.__dict__['_name_to_interface_name_'].get(attr, None)
|
||||
|
||||
if interface_name is not None:
|
||||
interface = self.__dict__['_interface_names_'].get(interface_name, None)
|
||||
iid = self.__dict__['_name_to_interface_iid_'].get(attr, None)
|
||||
# If the request is for an interface name, it may now be
|
||||
# available.
|
||||
interface = self.__dict__['_interface_names_'].get(attr, None)
|
||||
if interface is not None:
|
||||
return interface
|
||||
|
||||
if iid is not None:
|
||||
interface = self.__dict__['_interfaces_'].get(iid, None)
|
||||
if interface is None:
|
||||
iid = XPTI_GetInterfaceInfoManager().GetInfoForName(interface_name).GetIID()
|
||||
self.QueryInterface(iid)
|
||||
interface = self.__dict__['_interface_names_'][interface_name]
|
||||
interface = self.__dict__['_interfaces_'][iid]
|
||||
return getattr(interface, attr)
|
||||
# Some interfaces may provide this name via "native" support.
|
||||
# Loop over all interfaces, and if found, cache it for next time.
|
||||
for interface in self.__dict__['_interfaces_'].values():
|
||||
try:
|
||||
ret = getattr(interface, attr)
|
||||
self.__dict__['_name_to_interface_name_'][attr] = interface._iid_.name
|
||||
self.__dict__['_name_to_interface_iid_'][attr] = interface._iid_
|
||||
return ret
|
||||
except AttributeError:
|
||||
pass
|
||||
raise AttributeError, "XPCOM component '%s' has no attribute '%s'" % (self._object_name_, attr)
|
||||
|
||||
def __setattr__(self, attr, val):
|
||||
interface_name = self._name_to_interface_name_.get(attr, None)
|
||||
iid = self._name_to_interface_iid_.get(attr, None)
|
||||
# This may be first time trying this interface - get the nsIClassInfo
|
||||
if interface_name is None and not self._tried_classinfo_:
|
||||
if iid is None and not self._tried_classinfo_:
|
||||
self._build_all_supported_interfaces_()
|
||||
interface_name = self.__dict__['_name_to_interface_name_'].get(attr, None)
|
||||
if interface_name is not None:
|
||||
interface = self._interface_names_.get(interface_name, None)
|
||||
iid = self.__dict__['_name_to_interface_iid_'].get(attr, None)
|
||||
if iid is not None:
|
||||
interface = self._interfaces_.get(iid, None)
|
||||
if interface is None:
|
||||
iid = XPTI_GetInterfaceInfoManager().GetInfoForName(interface_name).GetIID()
|
||||
self.QueryInterface(iid)
|
||||
interface = self.__dict__['_interface_names_'][interface_name]
|
||||
interface = self.__dict__['_interfaces_'][iid]
|
||||
setattr(interface, attr, val)
|
||||
return
|
||||
raise AttributeError, "XPCOM component '%s' has no attribute '%s'" % (self._object_name_, attr)
|
||||
def __repr__(self):
|
||||
# We can advantage from nsIClassInfo - use it.
|
||||
|
||||
def _get_classinfo_repr_(self):
|
||||
try:
|
||||
if not self._tried_classinfo_:
|
||||
self._build_all_supported_interfaces_()
|
||||
@@ -362,13 +408,21 @@ class Component(_XPCOMBase):
|
||||
# we are flagged as *not* having built, so the error is seen
|
||||
# by the first caller who actually *needs* this to work.
|
||||
self.__dict__['_tried_classinfo_'] = 0
|
||||
infos = self.__dict__['_interface_infos_']
|
||||
if infos:
|
||||
iface_names = ",".join([iid.name for iid in infos.keys()])
|
||||
iface_desc = " (implementing %s)" % (iface_names,)
|
||||
else:
|
||||
iface_desc = " (with no class info)"
|
||||
return "<XPCOM component '%s'%s>" % (self._object_name_,iface_desc)
|
||||
|
||||
iface_names = self.__dict__['_interface_names_'].keys()
|
||||
try:
|
||||
iface_names.remove("nsISupports")
|
||||
except ValueError:
|
||||
pass
|
||||
iface_names.sort()
|
||||
|
||||
iface_desc = "implementing %s" % (",".join(iface_names),)
|
||||
return iface_desc
|
||||
|
||||
def __repr__(self):
|
||||
# We can advantage from nsIClassInfo - use it.
|
||||
iface_desc = self._get_classinfo_repr_()
|
||||
return "<XPCOM component '%s' (%s)>" % (self._object_name_,iface_desc)
|
||||
|
||||
class _Interface(_XPCOMBase):
|
||||
def __init__(self, comobj, iid, method_infos, getters, setters, constants):
|
||||
@@ -403,7 +457,7 @@ class _Interface(_XPCOMBase):
|
||||
if len(param_infos)!=1: # Only expecting a retval
|
||||
raise RuntimeError, "Can't get properties with this many args!"
|
||||
args = ( param_infos, () )
|
||||
return XPTC_InvokeByIndex(self, method_index, args)
|
||||
return XPTC_InvokeByIndex(self._comobj_, method_index, args)
|
||||
|
||||
# See if we have a method info waiting to be turned into a method.
|
||||
# Do this last as it is a one-off hit.
|
||||
@@ -431,7 +485,7 @@ class _Interface(_XPCOMBase):
|
||||
if len(param_infos)!=1: # Only expecting a single input val
|
||||
raise RuntimeError, "Can't set properties with this many args!"
|
||||
real_param_infos = ( param_infos, (val,) )
|
||||
return XPTC_InvokeByIndex(self, method_index, real_param_infos)
|
||||
return XPTC_InvokeByIndex(self._comobj_, method_index, real_param_infos)
|
||||
|
||||
def __repr__(self):
|
||||
return "<XPCOM interface '%s'>" % (self._object_name_,)
|
||||
@@ -453,7 +507,7 @@ class WeakReference:
|
||||
>>> some_ob = components.classes['...']
|
||||
>>> weak_ref = WeakReference(some_ob)
|
||||
>>> new_ob = weak_ref() # new_ob is effectively "some_ob" at this point
|
||||
>>> # EXCEPT: new_ob may be None of some_ob has already died - a
|
||||
>>> # EXCEPT: new_ob may be None if some_ob has already died - a
|
||||
>>> # weak reference does not keep the object alive (that is the point)
|
||||
|
||||
You should never hold onto this resulting strong object for a long time,
|
||||
|
||||
@@ -251,24 +251,17 @@ def _TestLocalFile():
|
||||
test_file.close()
|
||||
# Make sure Python can read it OK.
|
||||
f = open(fname, "r")
|
||||
if f.read() != data:
|
||||
print "Eeek - Python could not read the data back correctly!"
|
||||
assert f.read() == data, "Eeek - Python could not read the data back correctly!"
|
||||
f.close()
|
||||
# For the sake of the test, try a re-init.
|
||||
test_file.init(fname, "r")
|
||||
got = str(test_file.read())
|
||||
if got != data:
|
||||
print "Read the wrong data back - %r" % (got,)
|
||||
else:
|
||||
print "Read the correct data."
|
||||
assert got == data, got
|
||||
test_file.close()
|
||||
# Try reading in chunks.
|
||||
test_file = LocalFile(fname, "r")
|
||||
got = test_file.read(10) + test_file.read()
|
||||
if got != data:
|
||||
print "Chunks the wrong data back - %r" % (got,)
|
||||
else:
|
||||
print "Chunks read the correct data."
|
||||
assert got == data, got
|
||||
test_file.close()
|
||||
# Open the same file again for writing - this should delete the old one.
|
||||
if not os.path.isfile(fname):
|
||||
@@ -278,16 +271,12 @@ def _TestLocalFile():
|
||||
test_file.close()
|
||||
# Make sure Python can read it OK.
|
||||
f = open(fname, "r")
|
||||
if f.read() != data:
|
||||
print "Eeek - Python could not read the data back correctly after recreating an existing file!"
|
||||
assert f.read() == data, "Eeek - Python could not read the data back correctly after recreating an existing file!"
|
||||
f.close()
|
||||
|
||||
# XXX - todo - test "a" mode!
|
||||
finally:
|
||||
try:
|
||||
os.unlink(fname)
|
||||
except OSError, details:
|
||||
print "Error removing temp test file:", details
|
||||
os.unlink(fname)
|
||||
|
||||
def _TestAll():
|
||||
# A mini test suite.
|
||||
@@ -302,17 +291,13 @@ def _TestAll():
|
||||
url = LocalFileToURL(fname)
|
||||
# First try passing a URL as a string.
|
||||
_DoTestRead( URIFile( url.spec), expected)
|
||||
print "Open as string test worked."
|
||||
# Now with a URL object.
|
||||
_DoTestRead( URIFile( url ), expected)
|
||||
print "Open as URL test worked."
|
||||
|
||||
_DoTestBufferRead( URIFile( url ), expected)
|
||||
print "File test using buffers worked."
|
||||
|
||||
# For the sake of testing, do our pointless, demo object!
|
||||
_DoTestRead( LocalFile(fname), expected )
|
||||
print "Local file read test worked."
|
||||
|
||||
# Now do the full test of our pointless, demo object!
|
||||
_TestLocalFile()
|
||||
@@ -330,4 +315,4 @@ if __name__=='__main__':
|
||||
print "No URL specified on command line - performing self-test"
|
||||
_TestAll()
|
||||
else:
|
||||
_TestURI(sys.argv[1])
|
||||
_TestURI(sys.argv[1])
|
||||
|
||||
@@ -98,10 +98,13 @@ NS_ERROR_PROXY_INVALID_OUT_PARAMETER = ( -2147418095)
|
||||
##### END OF GENERATED CODE
|
||||
#####
|
||||
def NS_ERROR_GENERATE_FAILURE(module,code):
|
||||
return (NS_ERROR_SEVERITY_ERROR<<31) | ((module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | (code)
|
||||
# slightly optimized, and avoids 2.3->2.4 long/int changes
|
||||
# return (NS_ERROR_SEVERITY_ERROR<<31) | ((module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | (code)
|
||||
return -2147483648 | ((module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | (code)
|
||||
|
||||
def NS_ERROR_GENERATE_SUCCESS(module,code):
|
||||
return (NS_ERROR_SEVERITY_SUCCESS<<31) | ((module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | (code)
|
||||
#return (NS_ERROR_SEVERITY_SUCCESS<<31) | ((module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | (code)
|
||||
return ((module+NS_ERROR_MODULE_BASE_OFFSET)<<16) | (code)
|
||||
|
||||
NS_BASE_STREAM_CLOSED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 2)
|
||||
NS_BASE_STREAM_OSERROR = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 3)
|
||||
|
||||
39
mozilla/extensions/python/xpcom/primitives.py
Normal file
39
mozilla/extensions/python/xpcom/primitives.py
Normal file
@@ -0,0 +1,39 @@
|
||||
# Various utilities for working with nsISupportsPrimitive
|
||||
from xpcom import components
|
||||
|
||||
_primitives_map = {}
|
||||
|
||||
def _build_map():
|
||||
ifaces = components.interfaces
|
||||
iface = ifaces.nsISupportsPrimitive
|
||||
m = _primitives_map
|
||||
|
||||
m[iface.TYPE_ID] = ifaces.nsISupportsID
|
||||
m[iface.TYPE_CSTRING] = ifaces.nsISupportsCString
|
||||
m[iface.TYPE_STRING] = ifaces.nsISupportsString
|
||||
m[iface.TYPE_PRBOOL] = ifaces.nsISupportsPRBool
|
||||
m[iface.TYPE_PRUINT8] = ifaces.nsISupportsPRUint8
|
||||
m[iface.TYPE_PRUINT16] = ifaces.nsISupportsPRUint16
|
||||
m[iface.TYPE_PRUINT32] = ifaces.nsISupportsPRUint32
|
||||
m[iface.TYPE_PRUINT64] = ifaces.nsISupportsPRUint64
|
||||
m[iface.TYPE_PRINT16] = ifaces.nsISupportsPRInt16
|
||||
m[iface.TYPE_PRINT32] = ifaces.nsISupportsPRInt32
|
||||
m[iface.TYPE_PRINT64] = ifaces.nsISupportsPRInt64
|
||||
m[iface.TYPE_PRTIME] = ifaces.nsISupportsPRTime
|
||||
m[iface.TYPE_CHAR] = ifaces.nsISupportsChar
|
||||
m[iface.TYPE_FLOAT] = ifaces.nsISupportsFloat
|
||||
m[iface.TYPE_DOUBLE] = ifaces.nsISupportsDouble
|
||||
# Do interface pointer specially - it provides the IID.
|
||||
#m[iface.TYPE_INTERFACE_POINTER] = ifaces.nsISupportsDouble
|
||||
|
||||
def GetPrimitive(ob):
|
||||
if len(_primitives_map)==0:
|
||||
_build_map()
|
||||
|
||||
prin = ob.QueryInterface(components.interfaces.nsISupportsPrimitive)
|
||||
try:
|
||||
better = _primitives_map[prin.type]
|
||||
except KeyError:
|
||||
raise ValueError, "This primitive type (%d) is not supported" % (prin.type,)
|
||||
prin = prin.QueryInterface(better)
|
||||
return prin.data
|
||||
@@ -39,8 +39,7 @@
|
||||
#
|
||||
# Hardly worth its own source file!
|
||||
import xpcom
|
||||
from xpcom import components, nsError, _xpcom
|
||||
|
||||
from xpcom import components, nsError, _xpcom, logger
|
||||
|
||||
class Factory:
|
||||
_com_interfaces_ = components.interfaces.nsIFactory
|
||||
@@ -53,18 +52,17 @@ class Factory:
|
||||
if outer is not None:
|
||||
raise xpcom.ServerException(nsError.NS_ERROR_NO_AGGREGATION)
|
||||
|
||||
if xpcom.verbose:
|
||||
print "Python Factory creating", self.klass.__name__
|
||||
logger.debug("Python Factory creating %s", self.klass.__name__)
|
||||
try:
|
||||
return self.klass()
|
||||
except:
|
||||
# An exception here may not be obvious to the user - none
|
||||
# of their code has been called yet. It can be handy on
|
||||
# failure to tell the user what class failed!
|
||||
_xpcom.LogWarning("Creation of class '%r' failed!\nException details follow\n" % (self.klass,))
|
||||
logger.error("Creation of class '%r' failed!\nException details follow\n",
|
||||
self.klass)
|
||||
# The framework itself will also report the error.
|
||||
raise
|
||||
|
||||
def lockServer(self, lock):
|
||||
if xpcom.verbose:
|
||||
print "Python Factory LockServer called -", lock
|
||||
|
||||
logger.debug("Python Factory LockServer called '%s'", lock)
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
import xpcom
|
||||
from xpcom import components
|
||||
from xpcom import components, nsError
|
||||
import xpcom.shutdown
|
||||
|
||||
import module
|
||||
@@ -93,6 +93,8 @@ class ModuleLoader:
|
||||
|
||||
def _getCOMModuleForLocation(self, componentFile):
|
||||
fqn = componentFile.path
|
||||
if not fqn.endswith(".py"):
|
||||
raise xpcom.ServerException(nsError.NS_ERROR_INVALID_ARG)
|
||||
mod = self.com_modules.get(fqn)
|
||||
if mod is not None:
|
||||
return mod
|
||||
|
||||
@@ -35,12 +35,14 @@
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
from xpcom import xpcom_consts, _xpcom, client, nsError, ServerException, COMException
|
||||
from xpcom import xpcom_consts, _xpcom, client, nsError, logger
|
||||
from xpcom import ServerException, COMException
|
||||
import xpcom
|
||||
import traceback
|
||||
import xpcom.server
|
||||
import operator
|
||||
import types
|
||||
import logging
|
||||
|
||||
|
||||
IID_nsISupports = _xpcom.IID_nsISupports
|
||||
IID_nsIVariant = _xpcom.IID_nsIVariant
|
||||
@@ -237,12 +239,11 @@ class DefaultPolicy:
|
||||
if dt == xpcom_consts.VTYPE_ID:
|
||||
return interface.getAsID()
|
||||
# all else fails...
|
||||
print "Warning: nsIVariant type %d not supported - returning a string" % (dt,)
|
||||
logger.warning("Warning: nsIVariant type %d not supported - returning a string", dt)
|
||||
try:
|
||||
return interface.getAsString()
|
||||
except COMException:
|
||||
print "Error: failed to get Variant as a string - returning variant object"
|
||||
traceback.print_exc()
|
||||
logger.exception("Error: failed to get Variant as a string - returning variant object")
|
||||
return interface
|
||||
|
||||
return client.Component(interface, iid)
|
||||
@@ -278,17 +279,27 @@ class DefaultPolicy:
|
||||
exc_val = exc_info[1]
|
||||
is_server_exception = isinstance(exc_val, ServerException)
|
||||
if is_server_exception:
|
||||
if xpcom.verbose:
|
||||
print "** Information: '%s' raised COM Exception %s" % (func_name, exc_val)
|
||||
traceback.print_exception(exc_info[0], exc_val, exc_info[2])
|
||||
print "** Returning nsresult from existing exception", exc_val
|
||||
return exc_val.errno
|
||||
# Unhandled exception - always print a warning.
|
||||
print "** Unhandled exception calling '%s'" % (func_name,)
|
||||
traceback.print_exception(exc_info[0], exc_val, exc_info[2])
|
||||
print "** Returning nsresult of NS_ERROR_FAILURE"
|
||||
return nsError.NS_ERROR_FAILURE
|
||||
# When a component raised an explicit COM exception, it is
|
||||
# considered 'normal' - however, we still write a debug log
|
||||
# record to help track these otherwise silent exceptions.
|
||||
|
||||
# Note that Python 2.3 does not allow an explicit exc_info tuple
|
||||
# and passing 'True' will not work as there is no exception pending.
|
||||
# Trick things!
|
||||
if logger.isEnabledFor(logging.DEBUG):
|
||||
try:
|
||||
raise exc_info[0], exc_info[1], exc_info[2]
|
||||
except:
|
||||
logger.debug("'%s' raised COM Exception %s",
|
||||
func_name, exc_val, exc_info = 1)
|
||||
return exc_val.errno
|
||||
# Unhandled exception - always print a warning and the traceback.
|
||||
# As above, trick the logging module to handle Python 2.3
|
||||
try:
|
||||
raise exc_info[0], exc_info[1], exc_info[2]
|
||||
except:
|
||||
logger.exception("Unhandled exception calling '%s'", func_name)
|
||||
return nsError.NS_ERROR_FAILURE
|
||||
|
||||
# Called whenever an unhandled Python exception is detected as a result
|
||||
# of _CallMethod_ - this exception may have been raised during the _CallMethod_
|
||||
@@ -306,8 +317,12 @@ class DefaultPolicy:
|
||||
import xpcom.xpt
|
||||
m = xpcom.xpt.Method(info, index, None)
|
||||
func_repr = m.Describe().lstrip()
|
||||
except:
|
||||
except COMException:
|
||||
func_repr = "%s(%r)" % (name, param_descs)
|
||||
except:
|
||||
# any other errors are evil!? Log it
|
||||
self._doHandleException("<building method repr>", sys.exc_info())
|
||||
# And fall through to logging the original error.
|
||||
return self._doHandleException(func_repr, exc_info)
|
||||
|
||||
# Called whenever a gateway fails due to anything other than _CallMethod_.
|
||||
@@ -318,7 +333,7 @@ class DefaultPolicy:
|
||||
|
||||
_supports_primitives_data_ = [
|
||||
("nsISupportsCString", "__str__", str),
|
||||
("nsISupportsString", "__str__", str),
|
||||
("nsISupportsString", "__unicode__", unicode),
|
||||
("nsISupportsPRUint64", "__long__", long),
|
||||
("nsISupportsPRInt64", "__long__", long),
|
||||
("nsISupportsPRUint32", "__int__", int),
|
||||
|
||||
@@ -55,81 +55,179 @@ static char *PyTraceback_AsString(PyObject *exc_tb);
|
||||
// The internal helper that actually moves the
|
||||
// formatted string to the target!
|
||||
|
||||
void LogMessage(const char *prefix, const char *pszMessageText)
|
||||
// Only used in really bad situations!
|
||||
static void _PanicErrorWrite(const char *msg)
|
||||
{
|
||||
nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
||||
NS_ABORT_IF_FALSE(consoleService, "Where is the console service?");
|
||||
if (consoleService)
|
||||
consoleService->LogStringMessage(NS_ConvertASCIItoUCS2(pszMessageText).get());
|
||||
else
|
||||
PR_fprintf(PR_STDERR,"%s\n", pszMessageText);
|
||||
consoleService->LogStringMessage(NS_ConvertASCIItoUCS2(msg).get());
|
||||
PR_fprintf(PR_STDERR,"%s\n", msg);
|
||||
}
|
||||
|
||||
void LogMessage(const char *prefix, nsACString &text)
|
||||
// Called when our "normal" error logger fails.
|
||||
static void HandleLogError(const char *pszMessageText)
|
||||
{
|
||||
nsCAutoString streamout;
|
||||
|
||||
_PanicErrorWrite("Failed to log an error record");
|
||||
if (PyXPCOM_FormatCurrentException(streamout))
|
||||
_PanicErrorWrite(streamout.get());
|
||||
_PanicErrorWrite("Original error follows:");
|
||||
_PanicErrorWrite(pszMessageText);
|
||||
}
|
||||
|
||||
static const char *LOGGER_WARNING = "warning";
|
||||
static const char *LOGGER_ERROR = "error";
|
||||
static const char *LOGGER_DEBUG = "debug";
|
||||
|
||||
// Our "normal" error logger - calls back to the logging module.
|
||||
void DoLogMessage(const char *methodName, const char *pszMessageText)
|
||||
{
|
||||
// We use the logging module now. Originally this code called
|
||||
// the logging module directly by way of the C API's
|
||||
// PyImport_ImportModule/PyObject_CallMethod etc. However, this
|
||||
// causes problems when there is no Python caller on the stack -
|
||||
// the logging module's findCaller method fails with a None frame.
|
||||
// We now work around this by calling PyRun_SimpleString - this
|
||||
// causes a new frame to be created for executing the compiled
|
||||
// string, and the logging module no longer fails.
|
||||
// XXX - this implementation is less than ideal - findCaller now
|
||||
// returns ("<string>", 2). Ideally we would compile with a
|
||||
// filename something similar to "<pydom error reporter>".
|
||||
|
||||
// But this also means we need a clear error state...
|
||||
PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
|
||||
PyErr_Fetch(&exc_typ, &exc_val, &exc_tb);
|
||||
// We will execute:
|
||||
// import logging
|
||||
// logging.getLogger('xpcom').{warning/error/etc}("%s", {msg_text})
|
||||
nsCAutoString c("import logging\nlogging.getLogger('xpcom').");
|
||||
c += methodName;
|
||||
c += "('%s', ";
|
||||
// Pull a trick to ensure a valid string - use Python repr!
|
||||
PyObject *obMessage = PyString_FromString(pszMessageText);
|
||||
if (obMessage) {
|
||||
PyObject *repr = PyObject_Repr(obMessage);
|
||||
if (repr) {
|
||||
c += PyString_AsString(repr);
|
||||
Py_DECREF(repr);
|
||||
}
|
||||
Py_DECREF(obMessage);
|
||||
}
|
||||
c += ")\n";
|
||||
if (PyRun_SimpleString(c.get()) != 0) {
|
||||
HandleLogError(pszMessageText);
|
||||
}
|
||||
PyErr_Restore(exc_typ, exc_val, exc_tb);
|
||||
}
|
||||
|
||||
void LogMessage(const char *methodName, const char *pszMessageText)
|
||||
{
|
||||
// Be careful to save and restore the Python exception state
|
||||
// before calling back to Python, or we lose the original error.
|
||||
PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
|
||||
PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);
|
||||
DoLogMessage(methodName, pszMessageText);
|
||||
PyErr_Restore(exc_typ, exc_val, exc_tb);
|
||||
}
|
||||
|
||||
|
||||
void LogMessage(const char *methodName, nsACString &text)
|
||||
{
|
||||
char *c = ToNewCString(text);
|
||||
LogMessage(prefix, c);
|
||||
LogMessage(methodName, c);
|
||||
nsCRT::free(c);
|
||||
}
|
||||
|
||||
// A helper for the various logging routines.
|
||||
static void VLogF(const char *prefix, const char *fmt, va_list argptr)
|
||||
static void VLogF(const char *methodName, const char *fmt, va_list argptr)
|
||||
{
|
||||
char buff[512];
|
||||
// Use safer NS_ functions.
|
||||
PR_vsnprintf(buff, sizeof(buff), fmt, argptr);
|
||||
|
||||
vsprintf(buff, fmt, argptr);
|
||||
LogMessage(methodName, buff);
|
||||
}
|
||||
|
||||
LogMessage(prefix, buff);
|
||||
PRBool PyXPCOM_FormatCurrentException(nsCString &streamout)
|
||||
{
|
||||
PRBool ok = PR_FALSE;
|
||||
PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
|
||||
PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);
|
||||
PyErr_NormalizeException( &exc_typ, &exc_val, &exc_tb);
|
||||
if (exc_typ) {
|
||||
ok = PyXPCOM_FormatGivenException(streamout, exc_typ, exc_val,
|
||||
exc_tb);
|
||||
}
|
||||
PyErr_Restore(exc_typ, exc_val, exc_tb);
|
||||
return ok;
|
||||
}
|
||||
|
||||
PRBool PyXPCOM_FormatGivenException(nsCString &streamout,
|
||||
PyObject *exc_typ, PyObject *exc_val,
|
||||
PyObject *exc_tb)
|
||||
{
|
||||
if (!exc_typ)
|
||||
return PR_FALSE;
|
||||
streamout += "\n";
|
||||
|
||||
if (exc_tb) {
|
||||
const char *szTraceback = PyTraceback_AsString(exc_tb);
|
||||
if (szTraceback == NULL)
|
||||
streamout += "Can't get the traceback info!";
|
||||
else {
|
||||
streamout += "Traceback (most recent call last):\n";
|
||||
streamout += szTraceback;
|
||||
PyMem_Free((void *)szTraceback);
|
||||
}
|
||||
}
|
||||
PyObject *temp = PyObject_Str(exc_typ);
|
||||
if (temp) {
|
||||
streamout += PyString_AsString(temp);
|
||||
Py_DECREF(temp);
|
||||
} else
|
||||
streamout += "Can't convert exception to a string!";
|
||||
streamout += ": ";
|
||||
if (exc_val != NULL) {
|
||||
temp = PyObject_Str(exc_val);
|
||||
if (temp) {
|
||||
streamout += PyString_AsString(temp);
|
||||
Py_DECREF(temp);
|
||||
} else
|
||||
streamout += "Can't convert exception value to a string!";
|
||||
}
|
||||
return PR_TRUE;
|
||||
}
|
||||
|
||||
void PyXPCOM_LogError(const char *fmt, ...)
|
||||
{
|
||||
va_list marker;
|
||||
va_start(marker, fmt);
|
||||
VLogF("PyXPCOM Error: ", fmt, marker);
|
||||
// NOTE: It is tricky to use logger.exception here - the exception
|
||||
// state when called back from the C code is clear. Only Python 2.4
|
||||
// and later allows an explicit exc_info tuple().
|
||||
|
||||
// Don't use VLogF here, instead arrange for exception info and
|
||||
// traceback to be in the same buffer.
|
||||
char buff[512];
|
||||
PR_vsnprintf(buff, sizeof(buff), fmt, marker);
|
||||
// If we have a Python exception, also log that:
|
||||
PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL;
|
||||
PyErr_Fetch( &exc_typ, &exc_val, &exc_tb);
|
||||
if (exc_typ) {
|
||||
PyErr_NormalizeException( &exc_typ, &exc_val, &exc_tb);
|
||||
nsCAutoString streamout;
|
||||
|
||||
if (exc_tb) {
|
||||
const char *szTraceback = PyTraceback_AsString(exc_tb);
|
||||
if (szTraceback == NULL)
|
||||
streamout += "Can't get the traceback info!";
|
||||
else {
|
||||
streamout += "Traceback (most recent call last):\n";
|
||||
streamout += szTraceback;
|
||||
PyMem_Free((void *)szTraceback);
|
||||
}
|
||||
}
|
||||
PyObject *temp = PyObject_Str(exc_typ);
|
||||
if (temp) {
|
||||
streamout += PyString_AsString(temp);
|
||||
Py_DECREF(temp);
|
||||
} else
|
||||
streamout += "Can't convert exception to a string!";
|
||||
streamout += ": ";
|
||||
if (exc_val != NULL) {
|
||||
temp = PyObject_Str(exc_val);
|
||||
if (temp) {
|
||||
streamout += PyString_AsString(temp);
|
||||
Py_DECREF(temp);
|
||||
} else
|
||||
streamout += "Can't convert exception value to a string!";
|
||||
}
|
||||
streamout += "\n";
|
||||
LogMessage("PyXPCOM Exception:", streamout);
|
||||
nsCAutoString streamout(buff);
|
||||
if (PyXPCOM_FormatCurrentException(streamout)) {
|
||||
LogMessage(LOGGER_ERROR, streamout);
|
||||
}
|
||||
PyErr_Restore(exc_typ, exc_val, exc_tb);
|
||||
}
|
||||
|
||||
void PyXPCOM_LogWarning(const char *fmt, ...)
|
||||
{
|
||||
va_list marker;
|
||||
va_start(marker, fmt);
|
||||
VLogF("PyXPCOM Warning: ", fmt, marker);
|
||||
VLogF(LOGGER_WARNING, fmt, marker);
|
||||
}
|
||||
|
||||
void PyXPCOM_Log(const char *level, const nsCString &msg)
|
||||
{
|
||||
DoLogMessage(level, msg.get());
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@@ -137,7 +235,7 @@ void PyXPCOM_LogDebug(const char *fmt, ...)
|
||||
{
|
||||
va_list marker;
|
||||
va_start(marker, fmt);
|
||||
VLogF("PyXPCOM Debug: ", fmt, marker);
|
||||
VLogF(LOGGER_DEBUG, fmt, marker);
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -156,7 +254,17 @@ nsresult PyXPCOM_SetCOMErrorFromPyException()
|
||||
if (!PyErr_Occurred())
|
||||
// No error occurred
|
||||
return NS_OK;
|
||||
return NS_ERROR_FAILURE;
|
||||
nsresult rv = NS_ERROR_FAILURE;
|
||||
if (PyErr_ExceptionMatches(PyExc_MemoryError))
|
||||
rv = NS_ERROR_OUT_OF_MEMORY;
|
||||
// todo:
|
||||
// * Set an exception using the exception service.
|
||||
|
||||
// Once we have returned to the xpcom caller, we don't want to leave a
|
||||
// Python exception pending - it may get noticed when the next call
|
||||
// is made on the same thread.
|
||||
PyErr_Clear();
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* Obtains a string from a Python traceback.
|
||||
|
||||
@@ -43,22 +43,23 @@ srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
pyexecdir = @libdir@/python$(PYTHON_VER_DOTTED)/site-packages
|
||||
|
||||
DIRS = loader $(NULL)
|
||||
DIRS = module loader $(NULL)
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = pyxpcom
|
||||
LIBRARY_NAME = _xpcom$(PYTHON_DEBUG_SUFFIX)
|
||||
LIBRARY_NAME = pyxpcom
|
||||
#MODULE_NAME =
|
||||
REQUIRES = xpcom string $(NULL)
|
||||
MOZILLA_INTERNAL_API = 1
|
||||
FORCE_SHARED_LIB = 1
|
||||
FORCE_USE_PIC = 1
|
||||
|
||||
DLL_SUFFIX=$(PYTHON_DLL_SUFFIX)
|
||||
LOCAL_INCLUDES = $(PYTHON_INCLUDES)
|
||||
EXTRA_LIBS += $(PYTHON_LIBS)
|
||||
|
||||
EXPORTS = PyXPCOM.h
|
||||
|
||||
CPPSRCS= \
|
||||
ErrorUtils.cpp \
|
||||
PyGBase.cpp \
|
||||
@@ -80,33 +81,18 @@ CPPSRCS= \
|
||||
TypeObject.cpp \
|
||||
VariantUtils.cpp \
|
||||
dllmain.cpp \
|
||||
xpcom.cpp \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
|
||||
IMPORT_LIBRARY := $(SHARED_LIBRARY:.pyd=.lib)
|
||||
|
||||
# Install into our Python directory
|
||||
# default build installs into bin and lib - remove them
|
||||
libs::
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
$(INSTALL) -m 555 $(SHARED_LIBRARY) $(DIST)/bin/python/xpcom
|
||||
ifeq ($(OS_ARCH),Darwin)
|
||||
# Don't use the EXTRA_DSO_LDOPTS from rules.mk, it breaks the python module
|
||||
EXTRA_DSO_LDOPTS = -bundle $(MOZ_COMPONENT_LIBS)
|
||||
else
|
||||
$(INSTALL) -m 555 $(SHARED_LIBRARY) $(DIST)/bin/python/xpcom
|
||||
mv $(DIST)/bin/python/xpcom/$(SHARED_LIBRARY) $(DIST)/bin/python/xpcom/_xpcom.so
|
||||
endif
|
||||
rm -f $(DIST)/bin/$(SHARED_LIBRARY)
|
||||
rm -f $(DIST)/lib/$(IMPORT_LIBRARY)
|
||||
|
||||
install::
|
||||
ifneq ($(OS_ARCH),WINNT)
|
||||
$(SYSINSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(DISTDIR)$(pyexecdir)/xpcom
|
||||
mv $(DISTDIR)$(pyexecdir)/xpcom/$(SHARED_LIBRARY) $(DISTDIR)$(pyexecdir)/xpcom/_xpcom$(PYTHON_DLL_SUFFIX)
|
||||
EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
|
||||
endif
|
||||
|
||||
clobber::
|
||||
rm -f *.ilk *.pdb
|
||||
rm -f *.ilk *.pdb *.exp *.lib *.pyd
|
||||
|
||||
|
||||
@@ -271,8 +271,18 @@ PyG_Base::MakeInterfaceParam(nsISupports *pis,
|
||||
PyObject *result = NULL;
|
||||
|
||||
// get the basic interface first, as if we fail, we can try and use this.
|
||||
nsIID iid_check = piid ? *piid : NS_GET_IID(nsISupports);
|
||||
obISupports = Py_nsISupports::PyObjectFromInterface(pis, iid_check, PR_TRUE, PR_FALSE);
|
||||
// If we don't know the IID, we must explicitly query for nsISupports.
|
||||
nsCOMPtr<nsISupports> piswrap;
|
||||
nsIID iid_check;
|
||||
if (piid) {
|
||||
iid_check = *piid;
|
||||
piswrap = pis;
|
||||
} else {
|
||||
iid_check = NS_GET_IID(nsISupports);
|
||||
pis->QueryInterface(iid_check, getter_AddRefs(piswrap));
|
||||
}
|
||||
|
||||
obISupports = Py_nsISupports::PyObjectFromInterface(piswrap, iid_check, PR_FALSE);
|
||||
if (!obISupports)
|
||||
goto done;
|
||||
if (piid==NULL) {
|
||||
@@ -346,7 +356,11 @@ PyG_Base::QueryInterface(REFNSIID iid, void** ppv)
|
||||
CEnterLeavePython celp;
|
||||
|
||||
PyObject * ob = Py_nsIID::PyObjectFromIID(iid);
|
||||
PyObject * this_interface_ob = Py_nsISupports::PyObjectFromInterface((nsIInternalPython *)this, NS_GET_IID(nsISupports), PR_TRUE, PR_FALSE);
|
||||
// must say this is an 'internal' call, else we recurse QI into
|
||||
// oblivion.
|
||||
PyObject * this_interface_ob = Py_nsISupports::PyObjectFromInterface(
|
||||
(nsXPTCStubBase *)this,
|
||||
iid, PR_FALSE, PR_TRUE);
|
||||
if ( !ob || !this_interface_ob) {
|
||||
Py_XDECREF(ob);
|
||||
Py_XDECREF(this_interface_ob);
|
||||
@@ -355,7 +369,7 @@ PyG_Base::QueryInterface(REFNSIID iid, void** ppv)
|
||||
|
||||
PyObject *result = PyObject_CallMethod(m_pPyObject, "_QueryInterface_",
|
||||
"OO",
|
||||
this_interface_ob, ob);
|
||||
this_interface_ob, ob);
|
||||
Py_DECREF(ob);
|
||||
Py_DECREF(this_interface_ob);
|
||||
|
||||
@@ -426,6 +440,7 @@ PyG_Base::GetWeakReference(nsIWeakReference **ret)
|
||||
if (ret==nsnull) return NS_ERROR_INVALID_POINTER;
|
||||
if (!m_pWeakRef) {
|
||||
// First query for a weak reference - create it.
|
||||
// XXX - this looks like it needs thread safety!?
|
||||
m_pWeakRef = new PyXPCOM_GatewayWeakReference(this);
|
||||
NS_ABORT_IF_FALSE(m_pWeakRef, "Shouldn't be able to fail creating a weak reference!");
|
||||
if (!m_pWeakRef)
|
||||
@@ -444,17 +459,17 @@ nsresult PyG_Base::HandleNativeGatewayError(const char *szMethodName)
|
||||
// good error reporting is critical for users to know WTF
|
||||
// is going on - especially with TypeErrors etc in their
|
||||
// return values (ie, after the Python code has successfully
|
||||
// existed, but we encountered errors unpacking their
|
||||
// exited, but we encountered errors unpacking their
|
||||
// result values for the COM caller - there is literally no
|
||||
// way to catch these exceptions from Python code, as their
|
||||
// is no Python function on the call-stack)
|
||||
// is no Python function directly on the call-stack)
|
||||
|
||||
// First line of attack in an error is to call-back on the policy.
|
||||
// If the callback of the error handler succeeds and returns an
|
||||
// integer (for the nsresult), we take no further action.
|
||||
|
||||
// If this callback fails, we log _2_ exceptions - the error handler
|
||||
// error, and the original error.
|
||||
// If this callback fails, we log _2_ exceptions - the error
|
||||
// handler error, and the original error.
|
||||
|
||||
PRBool bProcessMainError = PR_TRUE; // set to false if our exception handler does its thing!
|
||||
PyObject *exc_typ, *exc_val, *exc_tb;
|
||||
@@ -696,10 +711,10 @@ PyObject *PyG_Base::UnwrapPythonObject(void)
|
||||
|
||||
Some special support to help with object identity.
|
||||
|
||||
In the simplest case, assume a Python COM object is
|
||||
In the simplest case, assume a Python XPCOM object is
|
||||
supporting a function "nsIWhatever GetWhatever()",
|
||||
so implements it as:
|
||||
return this
|
||||
return self
|
||||
it is almost certain they intend returning
|
||||
the same COM OBJECT to the caller! Thus, if a user of this COM
|
||||
object does:
|
||||
@@ -709,7 +724,7 @@ PyObject *PyG_Base::UnwrapPythonObject(void)
|
||||
|
||||
We almost certainly expect p1==p2==foo.
|
||||
|
||||
We previously _did_ have special support for the "this"
|
||||
We previously _did_ have special support for the "self"
|
||||
example above, but this implements a generic scheme that
|
||||
works for _all_ objects.
|
||||
|
||||
@@ -803,12 +818,11 @@ void AddDefaultGateway(PyObject *instance, nsISupports *gateway)
|
||||
NS_ABORT_IF_FALSE(swr, "Our gateway failed with a weak reference query");
|
||||
// Create the new default gateway - get a weak reference for our gateway.
|
||||
if (swr) {
|
||||
nsIWeakReference *pWeakReference = NULL;
|
||||
swr->GetWeakReference( &pWeakReference );
|
||||
nsCOMPtr<nsIWeakReference> pWeakReference;
|
||||
swr->GetWeakReference( getter_AddRefs(pWeakReference) );
|
||||
if (pWeakReference) {
|
||||
PyObject *ob_new_weak = Py_nsISupports::PyObjectFromInterface(pWeakReference,
|
||||
NS_GET_IID(nsIWeakReference),
|
||||
PR_FALSE, /* bAddRef */
|
||||
PR_FALSE ); /* bMakeNicePyObject */
|
||||
// pWeakReference reference consumed.
|
||||
if (ob_new_weak) {
|
||||
|
||||
@@ -80,7 +80,7 @@ PyG_nsIModule::GetClassObject(nsIComponentManager *aCompMgr,
|
||||
NS_PRECONDITION(r_classObj, "null pointer");
|
||||
*r_classObj = nsnull;
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *cm = Py_nsISupports::PyObjectFromInterface(aCompMgr, NS_GET_IID(nsIComponentManager), PR_TRUE);
|
||||
PyObject *cm = PyObject_FromNSInterface(aCompMgr, NS_GET_IID(nsIComponentManager));
|
||||
PyObject *iid = Py_nsIID::PyObjectFromIID(aIID);
|
||||
PyObject *clsid = Py_nsIID::PyObjectFromIID(aClass);
|
||||
const char *methodName = "getClassObject";
|
||||
@@ -110,8 +110,8 @@ PyG_nsIModule::RegisterSelf(nsIComponentManager *aCompMgr,
|
||||
NS_PRECONDITION(aCompMgr, "null pointer");
|
||||
NS_PRECONDITION(aPath, "null pointer");
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *cm = Py_nsISupports::PyObjectFromInterface(aCompMgr, NS_GET_IID(nsIComponentManager), PR_TRUE);
|
||||
PyObject *path = Py_nsISupports::PyObjectFromInterface(aPath, NS_GET_IID(nsIFile), PR_TRUE);
|
||||
PyObject *cm = PyObject_FromNSInterface(aCompMgr, NS_GET_IID(nsIComponentManager));
|
||||
PyObject *path = PyObject_FromNSInterface(aPath, NS_GET_IID(nsIFile));
|
||||
const char *methodName = "registerSelf";
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OOzz", cm, path, registryLocation, componentType);
|
||||
Py_XDECREF(cm);
|
||||
@@ -127,8 +127,8 @@ PyG_nsIModule::UnregisterSelf(nsIComponentManager* aCompMgr,
|
||||
NS_PRECONDITION(aCompMgr, "null pointer");
|
||||
NS_PRECONDITION(aPath, "null pointer");
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *cm = Py_nsISupports::PyObjectFromInterface(aCompMgr, NS_GET_IID(nsIComponentManager), PR_TRUE);
|
||||
PyObject *path = Py_nsISupports::PyObjectFromInterface(aPath, NS_GET_IID(nsIFile), PR_TRUE);
|
||||
PyObject *cm = PyObject_FromNSInterface(aCompMgr, NS_GET_IID(nsIComponentManager));
|
||||
PyObject *path = PyObject_FromNSInterface(aPath, NS_GET_IID(nsIFile));
|
||||
const char *methodName = "unregisterSelf";
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OOz", cm, path, registryLocation);
|
||||
Py_XDECREF(cm);
|
||||
@@ -143,7 +143,7 @@ PyG_nsIModule::CanUnload(nsIComponentManager *aCompMgr, PRBool *okToUnload)
|
||||
NS_PRECONDITION(okToUnload, "null pointer");
|
||||
CEnterLeavePython _celp;
|
||||
// we are shutting down - don't ask for a nice wrapped object.
|
||||
PyObject *cm = Py_nsISupports::PyObjectFromInterface(aCompMgr, NS_GET_IID(nsIComponentManager), PR_TRUE, PR_FALSE);
|
||||
PyObject *cm = PyObject_FromNSInterface(aCompMgr, NS_GET_IID(nsIComponentManager), PR_FALSE);
|
||||
const char *methodName = "canUnload";
|
||||
PyObject *ret = NULL;
|
||||
nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "O", cm);
|
||||
|
||||
@@ -96,7 +96,8 @@ PyXPCOM_XPTStub::CallMethod(PRUint16 methodIndex,
|
||||
if (obMI==NULL)
|
||||
goto done;
|
||||
// base object is passed raw.
|
||||
obThisObject = Py_nsISupports::PyObjectFromInterface((nsIInternalPython*)this, NS_GET_IID(nsISupports), PR_TRUE, PR_FALSE);
|
||||
obThisObject = PyObject_FromNSInterface((nsXPTCStubBase *)this,
|
||||
m_iid, PR_FALSE);
|
||||
obParams = arg_helper.MakePyArgs();
|
||||
if (obParams==NULL)
|
||||
goto done;
|
||||
|
||||
@@ -93,14 +93,14 @@ static PyObject *PyGetHelperForLanguage(PyObject *self, PyObject *args)
|
||||
return NULL;
|
||||
|
||||
nsresult r;
|
||||
nsISupports *pi;
|
||||
nsCOMPtr<nsISupports> pi;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetHelperForLanguage(language, &pi);
|
||||
r = pI->GetHelperForLanguage(language, getter_AddRefs(pi));
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
return Py_nsISupports::PyObjectFromInterface(pi, NS_GET_IID(nsISupports), PR_FALSE);
|
||||
return Py_nsISupports::PyObjectFromInterface(pi, NS_GET_IID(nsISupports));
|
||||
}
|
||||
|
||||
static PyObject *MakeStringOrNone(char *v)
|
||||
|
||||
@@ -81,16 +81,16 @@ static PyObject *PyCreateInstanceByContractID(PyObject *self, PyObject *args)
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
|
||||
nsISupports *pis;
|
||||
nsCOMPtr<nsISupports> pis;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->CreateInstanceByContractID(pid, NULL, iid, (void **)&pis);
|
||||
r = pI->CreateInstanceByContractID(pid, NULL, iid, getter_AddRefs(pis));
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
/* Return a type based on the IID (with no extra ref) */
|
||||
return Py_nsISupports::PyObjectFromInterface(pis, iid, PR_FALSE, PR_FALSE);
|
||||
return Py_nsISupports::PyObjectFromInterface(pis, iid, PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *PyCreateInstance(PyObject *self, PyObject *args)
|
||||
@@ -117,16 +117,16 @@ static PyObject *PyCreateInstance(PyObject *self, PyObject *args)
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
|
||||
nsISupports *pis;
|
||||
nsCOMPtr<nsISupports> pis;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->CreateInstance(classID, NULL, iid, (void **)&pis);
|
||||
r = pI->CreateInstance(classID, NULL, iid, getter_AddRefs(pis));
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
/* Return a type based on the IID (with no extra ref) */
|
||||
return Py_nsISupports::PyObjectFromInterface(pis, iid, PR_FALSE, PR_FALSE);
|
||||
return Py_nsISupports::PyObjectFromInterface(pis, iid, PR_FALSE);
|
||||
}
|
||||
|
||||
struct PyMethodDef
|
||||
|
||||
@@ -121,7 +121,9 @@ static PyObject *PyCurrentItem(PyObject *self, PyObject *args)
|
||||
}
|
||||
pRet = temp;
|
||||
}
|
||||
return Py_nsISupports::PyObjectFromInterface(pRet, iid, PR_FALSE);
|
||||
PyObject *ret = Py_nsISupports::PyObjectFromInterface(pRet, iid);
|
||||
NS_IF_RELEASE(pRet);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// A method added for Python performance if you really need
|
||||
@@ -179,7 +181,8 @@ static PyObject *PyFetchBlock(PyObject *self, PyObject *args)
|
||||
ret = PyList_New(n_fetched);
|
||||
if (ret)
|
||||
for (int i=0;i<n_fetched;i++) {
|
||||
PyObject *new_ob = Py_nsISupports::PyObjectFromInterface(fetched[i], iid, PR_FALSE);
|
||||
PyObject *new_ob = Py_nsISupports::PyObjectFromInterface(fetched[i], iid);
|
||||
NS_IF_RELEASE(fetched[i]);
|
||||
PyList_SET_ITEM(ret, i, new_ob);
|
||||
}
|
||||
} else
|
||||
|
||||
@@ -54,7 +54,7 @@
|
||||
nsIID Py_nsIID_NULL = {0,0,0,{0,0,0,0,0,0,0,0}};
|
||||
|
||||
// @pymethod <o Py_nsIID>|xpcom|IID|Creates a new IID object
|
||||
PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args)
|
||||
PYXPCOM_EXPORT PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *obIID;
|
||||
PyObject *obBuf;
|
||||
|
||||
@@ -128,14 +128,14 @@ static PyObject *PyGetParent(PyObject *self, PyObject *args)
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pRet;
|
||||
nsCOMPtr<nsIInterfaceInfo> pRet;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetParent(&pRet);
|
||||
r = pI->GetParent(getter_AddRefs(pRet));
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIInterfaceInfo), PR_FALSE, PR_FALSE);
|
||||
return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIInterfaceInfo), PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *PyGetMethodCount(PyObject *self, PyObject *args)
|
||||
@@ -288,11 +288,11 @@ static PyObject *PyGetInfoForParam(PyObject *self, PyObject *args)
|
||||
if (!__GetMethodInfoHelper(pii, mi, pi, &pmi))
|
||||
return NULL;
|
||||
const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi);
|
||||
nsIInterfaceInfo *pnewii = nsnull;
|
||||
nsresult n = pii->GetInfoForParam(mi, ¶m_info, &pnewii);
|
||||
nsCOMPtr<nsIInterfaceInfo> pnewii;
|
||||
nsresult n = pii->GetInfoForParam(mi, ¶m_info, getter_AddRefs(pnewii));
|
||||
if (NS_FAILED(n))
|
||||
return PyXPCOM_BuildPyException(n);
|
||||
return Py_nsISupports::PyObjectFromInterface(pnewii, NS_GET_IID(nsIInterfaceInfo), PR_FALSE);
|
||||
return Py_nsISupports::PyObjectFromInterface(pnewii, NS_GET_IID(nsIInterfaceInfo));
|
||||
}
|
||||
|
||||
static PyObject *PyGetIIDForParam(PyObject *self, PyObject *args)
|
||||
|
||||
@@ -73,10 +73,10 @@ static PyObject *PyGetInfoForIID(PyObject *self, PyObject *args)
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pi;
|
||||
nsCOMPtr<nsIInterfaceInfo> pi;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetInfoForIID(&iid, &pi);
|
||||
r = pI->GetInfoForIID(&iid, getter_AddRefs(pi));
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
@@ -85,7 +85,7 @@ static PyObject *PyGetInfoForIID(PyObject *self, PyObject *args)
|
||||
nsIID new_iid = NS_GET_IID(nsIInterfaceInfo);
|
||||
// Can not auto-wrap the interface info manager as it is critical to
|
||||
// building the support we need for autowrap.
|
||||
return Py_nsISupports::PyObjectFromInterface(pi, new_iid, PR_FALSE, PR_FALSE);
|
||||
return Py_nsISupports::PyObjectFromInterface(pi, new_iid, PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *PyGetInfoForName(PyObject *self, PyObject *args)
|
||||
@@ -98,10 +98,10 @@ static PyObject *PyGetInfoForName(PyObject *self, PyObject *args)
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIInterfaceInfo *pi;
|
||||
nsCOMPtr<nsIInterfaceInfo> pi;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->GetInfoForName(name, &pi);
|
||||
r = pI->GetInfoForName(name, getter_AddRefs(pi));
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
@@ -109,7 +109,7 @@ static PyObject *PyGetInfoForName(PyObject *self, PyObject *args)
|
||||
/* Return a type based on the IID (with no extra ref) */
|
||||
// Can not auto-wrap the interface info manager as it is critical to
|
||||
// building the support we need for autowrap.
|
||||
return Py_nsISupports::PyObjectFromInterface(pi, NS_GET_IID(nsIInterfaceInfo), PR_FALSE, PR_FALSE);
|
||||
return Py_nsISupports::PyObjectFromInterface(pi, NS_GET_IID(nsIInterfaceInfo), PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *PyGetNameForIID(PyObject *self, PyObject *args)
|
||||
@@ -171,15 +171,15 @@ static PyObject *PyEnumerateInterfaces(PyObject *self, PyObject *args)
|
||||
if (pI==NULL)
|
||||
return NULL;
|
||||
|
||||
nsIEnumerator *pRet;
|
||||
nsCOMPtr<nsIEnumerator> pRet;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pI->EnumerateInterfaces(&pRet);
|
||||
r = pI->EnumerateInterfaces(getter_AddRefs(pRet));
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIEnumerator), PR_FALSE);
|
||||
return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIEnumerator));
|
||||
}
|
||||
|
||||
// TODO:
|
||||
|
||||
@@ -109,7 +109,9 @@ static PyObject *PyGetNext(PyObject *self, PyObject *args)
|
||||
}
|
||||
pRet = temp;
|
||||
}
|
||||
return Py_nsISupports::PyObjectFromInterface(pRet, iid, PR_FALSE);
|
||||
PyObject *ret = Py_nsISupports::PyObjectFromInterface(pRet, iid);
|
||||
NS_IF_RELEASE(pRet);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// A method added for Python performance if you really need
|
||||
@@ -169,7 +171,8 @@ static PyObject *PyFetchBlock(PyObject *self, PyObject *args)
|
||||
ret = PyList_New(n_fetched);
|
||||
if (ret)
|
||||
for (int i=0;i<n_fetched;i++) {
|
||||
PyObject *new_ob = Py_nsISupports::PyObjectFromInterface(fetched[i], iid, PR_FALSE);
|
||||
PyObject *new_ob = Py_nsISupports::PyObjectFromInterface(fetched[i], iid);
|
||||
NS_IF_RELEASE(fetched[i]);
|
||||
PyList_SET_ITEM(ret, i, new_ob);
|
||||
}
|
||||
} else
|
||||
|
||||
@@ -46,10 +46,19 @@
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
|
||||
static PRInt32 cInterfaces=0;
|
||||
static PyObject *g_obFuncMakeInterfaceCount = NULL; // XXX - never released!!!
|
||||
|
||||
PyObject *PyObject_FromNSInterface( nsISupports *aInterface,
|
||||
const nsIID &iid,
|
||||
PRBool bMakeNicePyObject /*= PR_TRUE */)
|
||||
{
|
||||
return Py_nsISupports::PyObjectFromInterface(aInterface, iid,
|
||||
bMakeNicePyObject);
|
||||
}
|
||||
|
||||
PRInt32
|
||||
_PyXPCOM_GetInterfaceCount(void)
|
||||
{
|
||||
@@ -99,15 +108,9 @@ Py_nsISupports::SafeRelease(Py_nsISupports *ob)
|
||||
return;
|
||||
if (ob->m_obj)
|
||||
{
|
||||
long rcnt;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
rcnt = ob->m_obj->Release();
|
||||
ob->m_obj = nsnull;
|
||||
Py_END_ALLOW_THREADS;
|
||||
|
||||
#ifdef _DEBUG_LIFETIMES
|
||||
LogF(buf, " SafeRelease(%ld) -> %s at 0x%0lx, nsISupports at 0x%0lx - Release() returned %ld",GetCurrentThreadId(), ob->ob_type->tp_name,ob, ob->m_obj,rcnt);
|
||||
#endif
|
||||
ob->m_obj = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +120,23 @@ Py_nsISupports::getattr(const char *name)
|
||||
if (strcmp(name, "IID")==0)
|
||||
return Py_nsIID::PyObjectFromIID( m_iid );
|
||||
|
||||
// Support for __unicode__ until we get a tp_unicode slot.
|
||||
if (strcmp(name, "__unicode__")==0) {
|
||||
nsresult rv;
|
||||
PRUnichar *val = NULL;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
{ // scope to kill pointer while thread-lock released.
|
||||
nsCOMPtr<nsISupportsString> ss( do_QueryInterface(m_obj, &rv ));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = ss->ToString(&val);
|
||||
} // end-scope
|
||||
Py_END_ALLOW_THREADS;
|
||||
PyObject *ret = NS_FAILED(rv) ?
|
||||
PyXPCOM_BuildPyException(rv) :
|
||||
PyObject_FromNSString(val);
|
||||
if (val) nsMemory::Free(val);
|
||||
return ret;
|
||||
}
|
||||
PyXPCOM_TypeObject *this_type = (PyXPCOM_TypeObject *)ob_type;
|
||||
return Py_FindMethodInChain(&this_type->chain, this, (char *)name);
|
||||
}
|
||||
@@ -231,8 +251,13 @@ Py_nsISupports::InterfaceFromPyObject(PyObject *ob,
|
||||
Py_DECREF(sub_ob);
|
||||
}
|
||||
}
|
||||
*ppv = PyObject_AsVariant(ob);
|
||||
return *ppv != NULL;
|
||||
nsresult nr = PyObject_AsVariant(ob, (nsIVariant **)ppv);
|
||||
if (NS_FAILED(nr)) {
|
||||
PyXPCOM_BuildPyException(nr);
|
||||
return PR_FALSE;
|
||||
}
|
||||
NS_ASSERTION(ppv != nsnull, "PyObject_AsVariant worked but gave null!");
|
||||
return PR_TRUE;
|
||||
}
|
||||
// end of variant support.
|
||||
|
||||
@@ -273,33 +298,11 @@ Py_nsISupports::RegisterInterface( const nsIID &iid, PyTypeObject *t)
|
||||
}
|
||||
}
|
||||
|
||||
/*static */PyObject *
|
||||
Py_nsISupports::PyObjectFromInterfaceOrVariant(nsISupports *pis,
|
||||
const nsIID &riid,
|
||||
PRBool bAddRef,
|
||||
PRBool bMakeNicePyObject /* = PR_TRUE */)
|
||||
{
|
||||
// Quick exit.
|
||||
if (pis==NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
if (riid.Equals(NS_GET_IID(nsIVariant))) {
|
||||
PyObject *ret = PyObject_FromVariant((nsIVariant *)pis);
|
||||
// If we were asked not to add a reference, then there
|
||||
// will be a spare reference on pis() - remove it.
|
||||
if (!bAddRef)
|
||||
pis->Release();
|
||||
return ret;
|
||||
}
|
||||
return PyObjectFromInterface(pis, riid, bAddRef, bMakeNicePyObject);
|
||||
}
|
||||
|
||||
/*static */PyObject *
|
||||
Py_nsISupports::PyObjectFromInterface(nsISupports *pis,
|
||||
const nsIID &riid,
|
||||
PRBool bAddRef,
|
||||
PRBool bMakeNicePyObject /* = PR_TRUE */)
|
||||
PRBool bMakeNicePyObject, /* = PR_TRUE */
|
||||
PRBool bIsInternalCall /* = PR_FALSE */)
|
||||
{
|
||||
// Quick exit.
|
||||
if (pis==NULL) {
|
||||
@@ -307,9 +310,15 @@ Py_nsISupports::PyObjectFromInterface(nsISupports *pis,
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
// FIXME: if !bAddRef, in all error cases, do NS_RELEASE(pis) before return
|
||||
// since that means we have a spare reference
|
||||
|
||||
if (!bIsInternalCall) {
|
||||
#ifdef NS_DEBUG
|
||||
nsISupports *queryResult = nsnull;
|
||||
pis->QueryInterface(riid, (void **)&queryResult);
|
||||
NS_ASSERTION(queryResult == pis, "QueryInterface needed");
|
||||
NS_IF_RELEASE(queryResult);
|
||||
#endif
|
||||
}
|
||||
|
||||
PyTypeObject *createType = NULL;
|
||||
// If the IID is for nsISupports, don't bother with
|
||||
// a map lookup as we know the type!
|
||||
@@ -341,16 +350,15 @@ Py_nsISupports::PyObjectFromInterface(nsISupports *pis,
|
||||
PyXPCOM_LogF("XPCOM Object created at 0x%0xld, nsISupports at 0x%0xld",
|
||||
ret, ret->m_obj);
|
||||
#endif
|
||||
if (ret && bAddRef && pis) pis->AddRef();
|
||||
if (ret && bMakeNicePyObject)
|
||||
return MakeInterfaceResult(ret, riid);
|
||||
return MakeDefaultWrapper(ret, riid);
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Call back into Python, passing a raw nsIInterface object, getting back
|
||||
// the object to actually pass to Python.
|
||||
PyObject *
|
||||
Py_nsISupports::MakeInterfaceResult(PyObject *pyis,
|
||||
Py_nsISupports::MakeDefaultWrapper(PyObject *pyis,
|
||||
const nsIID &iid)
|
||||
{
|
||||
NS_PRECONDITION(pyis, "NULL pyobject!");
|
||||
@@ -411,10 +419,17 @@ Py_nsISupports::QueryInterface(PyObject *self, PyObject *args)
|
||||
nsISupports *pMyIS = GetI(self);
|
||||
if (pMyIS==NULL) return NULL;
|
||||
|
||||
nsISupports *pis;
|
||||
// Optimization, If we already wrap the IID, just return
|
||||
// ourself.
|
||||
if (!bWrap && iid.Equals(((Py_nsISupports *)self)->m_iid)) {
|
||||
Py_INCREF(self);
|
||||
return self;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsISupports> pis;
|
||||
nsresult r;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
r = pMyIS->QueryInterface(iid, (void **)&pis);
|
||||
r = pMyIS->QueryInterface(iid, getter_AddRefs(pis));
|
||||
Py_END_ALLOW_THREADS;
|
||||
|
||||
/* Note that this failure may include E_NOINTERFACE */
|
||||
@@ -422,7 +437,7 @@ Py_nsISupports::QueryInterface(PyObject *self, PyObject *args)
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
/* Return a type based on the IID (with no extra ref) */
|
||||
return PyObjectFromInterface(pis, iid, PR_FALSE, (PRBool)bWrap);
|
||||
return ((Py_nsISupports *)self)->MakeInterfaceResult(pis, iid, (PRBool)bWrap);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -64,13 +64,10 @@ static PyObject *MyChar( char c) {
|
||||
return PyString_FromStringAndSize(&c, 1);
|
||||
}
|
||||
static PyObject *MyUChar( PRUnichar c) {
|
||||
return PyUnicode_FromPRUnichar(&c, 1);
|
||||
return PyObject_FromNSString( &c, 1);
|
||||
}
|
||||
static PyObject *MyUnicode( PRUnichar *p) {
|
||||
return PyUnicode_FromPRUnichar(p, nsCRT::strlen(p));
|
||||
}
|
||||
static PyObject *MyISupports( nsISupports *p) {
|
||||
return Py_nsISupports::PyObjectFromInterface(p, NS_GET_IID(nsISupports), PR_FALSE);
|
||||
return PyObject_FromNSString(p);
|
||||
}
|
||||
|
||||
#define GET_SIMPLE(Type, FuncGet, FuncConvert) \
|
||||
@@ -123,32 +120,49 @@ GET_SIMPLE(double, GetAsDouble, PyFloat_FromDouble)
|
||||
GET_SIMPLE(PRBool, GetAsBool, MyBool)
|
||||
GET_SIMPLE(char, GetAsChar, MyChar)
|
||||
GET_SIMPLE(PRUnichar, GetAsWChar, MyUChar)
|
||||
GET_SIMPLE(nsISupports *, GetAsISupports, MyISupports)
|
||||
GET_SIMPLE(nsIID, GetAsID, Py_nsIID::PyObjectFromIID)
|
||||
|
||||
GET_ALLOCATED(char *, GetAsString, PyString_FromString, nsMemory::Free)
|
||||
GET_ALLOCATED(PRUnichar *, GetAsWString, MyUnicode, nsMemory::Free)
|
||||
GET_ALLOCATED_SIZE(char *, GetAsStringWithSize, PyString_FromStringAndSize, nsMemory::Free)
|
||||
GET_ALLOCATED_SIZE(PRUnichar *, GetAsWStringWithSize, PyUnicode_FromPRUnichar, nsMemory::Free)
|
||||
GET_ALLOCATED_SIZE(PRUnichar *, GetAsWStringWithSize, PyObject_FromNSString, nsMemory::Free)
|
||||
|
||||
static PyObject *GetAsInterface(PyObject *self, PyObject *args) {
|
||||
nsIVariant *pI = GetI(self);
|
||||
if (pI==NULL) return NULL;
|
||||
if (!PyArg_ParseTuple(args, ":GetAsInterface")) return NULL;
|
||||
nsISupports *p;
|
||||
nsCOMPtr<nsISupports> p;
|
||||
nsIID *iid;
|
||||
nsresult nr = pI->GetAsInterface(&iid, (void **)&p);
|
||||
nsresult nr = pI->GetAsInterface(&iid, getter_AddRefs(p));
|
||||
if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr);
|
||||
return Py_nsISupports::PyObjectFromInterface(p, *iid, PR_FALSE);
|
||||
return Py_nsISupports::PyObjectFromInterface(p, *iid);
|
||||
}
|
||||
|
||||
extern PyObject *PyObject_FromVariantArray( nsIVariant *v);
|
||||
static PyObject *GetAsISupports(PyObject *self, PyObject *args) {
|
||||
nsIVariant *pI = GetI(self);
|
||||
if (pI==NULL) return NULL;
|
||||
if (!PyArg_ParseTuple(args, ":GetAsInterface")) return NULL;
|
||||
nsCOMPtr<nsISupports> p;
|
||||
nsIID *iid;
|
||||
nsresult nr = pI->GetAsInterface(&iid, getter_AddRefs(p));
|
||||
if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr);
|
||||
return Py_nsISupports::PyObjectFromInterface(p, *iid);
|
||||
}
|
||||
|
||||
extern PyObject *PyObject_FromVariantArray( Py_nsISupports*, nsIVariant *v);
|
||||
|
||||
static PyObject *GetAsArray(PyObject *self, PyObject *args) {
|
||||
nsIVariant *pI = GetI(self);
|
||||
if (pI==NULL) return NULL;
|
||||
if (!PyArg_ParseTuple(args, ":GetAsArray")) return NULL;
|
||||
return PyObject_FromVariantArray(pI);
|
||||
return PyObject_FromVariantArray((Py_nsISupports *)self, pI);
|
||||
}
|
||||
|
||||
static PyObject *Get(PyObject *self, PyObject *args) {
|
||||
nsIVariant *pI = GetI(self);
|
||||
if (pI==NULL) return NULL;
|
||||
if (!PyArg_ParseTuple(args, ":Get")) return NULL;
|
||||
return PyObject_FromVariant((Py_nsISupports *)self, pI);
|
||||
}
|
||||
|
||||
struct PyMethodDef
|
||||
@@ -175,6 +189,7 @@ PyMethods_IVariant[] =
|
||||
{ "getAsInterface", GetAsInterface, 1},
|
||||
{ "getAsArray", GetAsArray, 1},
|
||||
{ "getAsID", GetAsID, 1},
|
||||
{ "get", Get, 1},
|
||||
{NULL}
|
||||
};
|
||||
|
||||
|
||||
@@ -49,26 +49,46 @@
|
||||
#ifndef __PYXPCOM_H__
|
||||
#define __PYXPCOM_H__
|
||||
|
||||
#ifdef XP_WIN
|
||||
# ifdef BUILD_PYXPCOM
|
||||
/* We are building the main dll */
|
||||
# define PYXPCOM_EXPORT __declspec(dllexport)
|
||||
# else
|
||||
/* This module uses the dll */
|
||||
# define PYXPCOM_EXPORT __declspec(dllimport)
|
||||
# endif // BUILD_PYXPCOM
|
||||
#include "nsIAllocator.h"
|
||||
#include "nsIWeakReference.h"
|
||||
#include "nsIInterfaceInfoManager.h"
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIComponentManagerObsolete.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIVariant.h"
|
||||
#include "nsIModule.h"
|
||||
|
||||
// We need these libs!
|
||||
# pragma comment(lib, "xpcom.lib")
|
||||
# pragma comment(lib, "nspr4.lib")
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsCRT.h"
|
||||
#include "xptcall.h"
|
||||
#include "xpt_xdr.h"
|
||||
|
||||
#else // XP_WIN
|
||||
# define PYXPCOM_EXPORT
|
||||
#endif // XP_WIN
|
||||
#ifdef HAVE_LONG_LONG
|
||||
// Mozilla also defines this - we undefine it to
|
||||
// prevent a compiler warning.
|
||||
# undef HAVE_LONG_LONG
|
||||
#endif // HAVE_LONG_LONG
|
||||
|
||||
#ifdef _POSIX_C_SOURCE // Ditto here
|
||||
# undef _POSIX_C_SOURCE
|
||||
#endif // _POSIX_C_SOURCE
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#ifdef BUILD_PYXPCOM
|
||||
/* We are building the main dll */
|
||||
# define PYXPCOM_EXPORT NS_EXPORT
|
||||
#else
|
||||
/* This module uses the dll */
|
||||
# define PYXPCOM_EXPORT NS_IMPORT
|
||||
#endif // BUILD_PYXPCOM
|
||||
|
||||
// An IID we treat as NULL when passing as a reference.
|
||||
extern nsIID Py_nsIID_NULL;
|
||||
extern PYXPCOM_EXPORT nsIID Py_nsIID_NULL;
|
||||
|
||||
class Py_nsISupports;
|
||||
|
||||
/*************************************************************************
|
||||
**************************************************************************
|
||||
@@ -94,6 +114,13 @@ PYXPCOM_EXPORT PyObject *PyXPCOM_BuildPyException(nsresult res);
|
||||
// NOTE: this function assumes it is operating within the Python context
|
||||
PYXPCOM_EXPORT nsresult PyXPCOM_SetCOMErrorFromPyException();
|
||||
|
||||
// Write current exception and traceback to a string.
|
||||
PYXPCOM_EXPORT PRBool PyXPCOM_FormatCurrentException(nsCString &streamout);
|
||||
// Write specified exception and traceback to a string.
|
||||
PYXPCOM_EXPORT PRBool PyXPCOM_FormatGivenException(nsCString &streamout,
|
||||
PyObject *exc_typ, PyObject *exc_val,
|
||||
PyObject *exc_tb);
|
||||
|
||||
// A couple of logging/error functions. These probably end up
|
||||
// being written to the console service.
|
||||
|
||||
@@ -108,6 +135,9 @@ PYXPCOM_EXPORT void PyXPCOM_LogWarning(const char *fmt, ...);
|
||||
// As it's designed for user error/warning, it exists in non-debug builds.
|
||||
PYXPCOM_EXPORT void PyXPCOM_LogError(const char *fmt, ...);
|
||||
|
||||
// The raw one
|
||||
PYXPCOM_EXPORT void PyXPCOM_Log(const char *level, const nsCString &msg);
|
||||
|
||||
#ifdef DEBUG
|
||||
// Mainly designed for developers of the XPCOM package.
|
||||
// Only enabled in debug builds.
|
||||
@@ -117,9 +147,27 @@ PYXPCOM_EXPORT void PyXPCOM_LogDebug(const char *fmt, ...);
|
||||
#define PYXPCOM_LOG_DEBUG()
|
||||
#endif // DEBUG
|
||||
|
||||
// Create a Unicode Object from the PRUnichar buffer src of the given size
|
||||
#define PyUnicode_FromPRUnichar(src, size) \
|
||||
PyUnicode_DecodeUTF16((char*)(src),sizeof(PRUnichar)*(size),NULL,NULL)
|
||||
// Some utility converters
|
||||
// moz strings to PyObject.
|
||||
PYXPCOM_EXPORT PyObject *PyObject_FromNSString( const nsACString &s,
|
||||
PRBool bAssumeUTF8 = PR_FALSE );
|
||||
PYXPCOM_EXPORT PyObject *PyObject_FromNSString( const nsAString &s );
|
||||
PYXPCOM_EXPORT PyObject *PyObject_FromNSString( const PRUnichar *s,
|
||||
PRUint32 len = (PRUint32)-1);
|
||||
|
||||
// PyObjects to moz strings. As per the moz string guide, we pass a reference
|
||||
// to an abstract string
|
||||
PYXPCOM_EXPORT PRBool PyObject_AsNSString( PyObject *ob, nsAString &aStr);
|
||||
|
||||
// Variants.
|
||||
PYXPCOM_EXPORT nsresult PyObject_AsVariant( PyObject *ob, nsIVariant **aRet);
|
||||
PYXPCOM_EXPORT PyObject *PyObject_FromVariant( Py_nsISupports *parent,
|
||||
nsIVariant *v);
|
||||
|
||||
// Interfaces - these are the "official" functions
|
||||
PYXPCOM_EXPORT PyObject *PyObject_FromNSInterface( nsISupports *aInterface,
|
||||
const nsIID &iid,
|
||||
PRBool bMakeNicePyObject = PR_TRUE);
|
||||
|
||||
/*************************************************************************
|
||||
**************************************************************************
|
||||
@@ -129,8 +177,6 @@ PYXPCOM_EXPORT void PyXPCOM_LogDebug(const char *fmt, ...);
|
||||
**************************************************************************
|
||||
*************************************************************************/
|
||||
|
||||
class Py_nsISupports;
|
||||
|
||||
typedef Py_nsISupports* (* PyXPCOM_I_CTOR)(nsISupports *, const nsIID &);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -174,6 +220,9 @@ public:
|
||||
class PYXPCOM_EXPORT Py_nsISupports : public PyObject
|
||||
{
|
||||
public:
|
||||
// Check if a Python object can safely be cast to an Py_nsISupports,
|
||||
// and optionally check that the object is wrapping the specified
|
||||
// interface.
|
||||
static PRBool Check( PyObject *ob, const nsIID &checkIID = Py_nsIID_NULL) {
|
||||
Py_nsISupports *self = static_cast<Py_nsISupports *>(ob);
|
||||
if (ob==NULL || !PyXPCOM_TypeObject::IsType(ob->ob_type ))
|
||||
@@ -184,31 +233,24 @@ public:
|
||||
}
|
||||
// Get the nsISupports interface from the PyObject WITH NO REF COUNT ADDED
|
||||
static nsISupports *GetI(PyObject *self, nsIID *ret_iid = NULL);
|
||||
nsISupports *m_obj;
|
||||
nsCOMPtr<nsISupports> m_obj;
|
||||
nsIID m_iid;
|
||||
|
||||
// Given an nsISupports and an Interface ID, create and return an object
|
||||
// Does not QI the object - the caller must ensure the nsISupports object
|
||||
// is really a pointer to an object identified by the IID.
|
||||
// PRBool bAddRef indicates if a COM reference count should be added to the interface.
|
||||
// This depends purely on the context in which it is called. If the interface is obtained
|
||||
// from a function that creates a new ref (eg, ???) then you should use
|
||||
// FALSE. If you receive the pointer as (eg) a param to a gateway function, then
|
||||
// you normally need to pass TRUE, as this is truly a new reference.
|
||||
// *** ALWAYS take the time to get this right. ***
|
||||
// is really a pointer to an object identified by the IID (although
|
||||
// debug builds should check this)
|
||||
// PRBool bMakeNicePyObject indicates if we should call back into
|
||||
// Python to wrap the object. This allows Python code to
|
||||
// see the correct xpcom.client.Interface object even when calling
|
||||
// xpcom function directly.
|
||||
// xpcom functions directly from C++.
|
||||
// NOTE: There used to be a bAddRef param to this as an internal
|
||||
// optimization, but since removed. This function *always* takes a
|
||||
// reference to the nsISupports.
|
||||
static PyObject *PyObjectFromInterface(nsISupports *ps,
|
||||
const nsIID &iid,
|
||||
PRBool bAddRef,
|
||||
PRBool bMakeNicePyObject = PR_TRUE);
|
||||
|
||||
static PyObject *PyObjectFromInterfaceOrVariant(nsISupports *ps,
|
||||
const nsIID &iid,
|
||||
PRBool bAddRef,
|
||||
PRBool bMakeNicePyObject = PR_TRUE);
|
||||
PRBool bMakeNicePyObject = PR_TRUE,
|
||||
PRBool bIsInternalCall = PR_FALSE);
|
||||
|
||||
// Given a Python object that is a registered COM type, return a given
|
||||
// interface pointer on its underlying object, with a NEW REFERENCE ADDED.
|
||||
@@ -238,8 +280,8 @@ public:
|
||||
static PyObject *QueryInterface(PyObject *self, PyObject *args);
|
||||
|
||||
// Internal (sort-of) objects.
|
||||
static PyXPCOM_TypeObject *type;
|
||||
static PyMethodDef methods[];
|
||||
static NS_EXPORT_STATIC_MEMBER_(PyXPCOM_TypeObject) *type;
|
||||
static NS_EXPORT_STATIC_MEMBER_(PyMethodDef) methods[];
|
||||
static PyObject *mapIIDToType;
|
||||
static void SafeRelease(Py_nsISupports *ob);
|
||||
static void RegisterInterface( const nsIID &iid, PyTypeObject *t);
|
||||
@@ -248,6 +290,14 @@ public:
|
||||
virtual ~Py_nsISupports();
|
||||
virtual PyObject *getattr(const char *name);
|
||||
virtual int setattr(const char *name, PyObject *val);
|
||||
// A virtual function to sub-classes can customize the way
|
||||
// nsISupports objects are returned from their methods.
|
||||
// ps is a new object just obtained from some operation performed on us
|
||||
virtual PyObject *MakeInterfaceResult(nsISupports *ps, const nsIID &iid,
|
||||
PRBool bMakeNicePyObject = PR_TRUE) {
|
||||
return PyObjectFromInterface(ps, iid, bMakeNicePyObject);
|
||||
}
|
||||
|
||||
protected:
|
||||
// ctor is protected - must create objects via
|
||||
// PyObjectFromInterface()
|
||||
@@ -255,7 +305,9 @@ protected:
|
||||
const nsIID &iid,
|
||||
PyTypeObject *type);
|
||||
|
||||
static PyObject *MakeInterfaceResult(PyObject *pyis, const nsIID &iid);
|
||||
// Make a default wrapper for an ISupports (which is an
|
||||
// xpcom.client.Component instance)
|
||||
static PyObject *MakeDefaultWrapper(PyObject *pyis, const nsIID &iid);
|
||||
|
||||
};
|
||||
|
||||
@@ -296,8 +348,8 @@ public:
|
||||
static long PyTypeMethod_hash(PyObject *self);
|
||||
static PyObject *PyTypeMethod_str(PyObject *self);
|
||||
static void PyTypeMethod_dealloc(PyObject *self);
|
||||
static PyTypeObject type;
|
||||
static PyMethodDef methods[];
|
||||
static NS_EXPORT_STATIC_MEMBER_(PyTypeObject) type;
|
||||
static NS_EXPORT_STATIC_MEMBER_(PyMethodDef) methods[];
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////
|
||||
@@ -307,7 +359,7 @@ class PythonTypeDescriptor; // Forward declare.
|
||||
|
||||
class PYXPCOM_EXPORT PyXPCOM_InterfaceVariantHelper {
|
||||
public:
|
||||
PyXPCOM_InterfaceVariantHelper();
|
||||
PyXPCOM_InterfaceVariantHelper(Py_nsISupports *parent);
|
||||
~PyXPCOM_InterfaceVariantHelper();
|
||||
PRBool Init(PyObject *obParams);
|
||||
PRBool FillArray();
|
||||
@@ -327,6 +379,7 @@ protected:
|
||||
PyObject *m_typedescs; // desc of _all_ params, including hidden.
|
||||
PythonTypeDescriptor *m_python_type_desc_array;
|
||||
void **m_buffer_array;
|
||||
Py_nsISupports *m_parent;
|
||||
|
||||
};
|
||||
|
||||
@@ -457,6 +510,11 @@ private:
|
||||
return GATEWAY_BASE::ThisAsIID(iid); \
|
||||
} \
|
||||
|
||||
extern PYXPCOM_EXPORT void AddDefaultGateway(PyObject *instance, nsISupports *gateway);
|
||||
|
||||
extern PYXPCOM_EXPORT PRInt32 _PyXPCOM_GetGatewayCount(void);
|
||||
extern PYXPCOM_EXPORT PRInt32 _PyXPCOM_GetInterfaceCount(void);
|
||||
|
||||
|
||||
// Weak Reference class. This is a true COM object, representing
|
||||
// a weak reference to a Python object. For each Python XPCOM object,
|
||||
@@ -496,7 +554,7 @@ private:
|
||||
nsresult BackFillVariant( PyObject *ob, int index);
|
||||
PyObject *MakeSingleParam(int index, PythonTypeDescriptor &td);
|
||||
PRBool GetIIDForINTERFACE_ID(int index, const nsIID **ppret);
|
||||
nsresult GetArrayType(PRUint8 index, PRUint8 *ret);
|
||||
nsresult GetArrayType(PRUint8 index, PRUint8 *ret, nsIID **ppiid);
|
||||
PRUint32 GetSizeIs( int var_index, PRBool is_arg1);
|
||||
PRBool SetSizeIs( int var_index, PRBool is_arg1, PRUint32 new_size);
|
||||
PRBool CanSetSizeIs( int var_index, PRBool is_arg1 );
|
||||
@@ -520,9 +578,6 @@ PyObject *PyObject_FromXPTParamDescriptor( const XPTParamDescriptor *d);
|
||||
PyObject *PyObject_FromXPTMethodDescriptor( const XPTMethodDescriptor *d);
|
||||
PyObject *PyObject_FromXPTConstant( const XPTConstDescriptor *d);
|
||||
|
||||
nsIVariant *PyObject_AsVariant( PyObject *ob);
|
||||
PyObject *PyObject_FromVariant( nsIVariant *v);
|
||||
|
||||
// DLL reference counting functions.
|
||||
// Although we maintain the count, we never actually
|
||||
// finalize Python when it hits zero!
|
||||
@@ -579,8 +634,8 @@ public:
|
||||
|
||||
// NEVER new one of these objects - only use on the stack!
|
||||
|
||||
extern PYXPCOM_EXPORT void PyXPCOM_MakePendingCalls();
|
||||
extern PYXPCOM_EXPORT PRBool PyXPCOM_Globals_Ensure();
|
||||
PYXPCOM_EXPORT void PyXPCOM_MakePendingCalls();
|
||||
PYXPCOM_EXPORT PRBool PyXPCOM_Globals_Ensure();
|
||||
|
||||
// For 2.3, use the PyGILState_ calls
|
||||
#if (PY_VERSION_HEX >= 0x02030000)
|
||||
@@ -605,12 +660,12 @@ public:
|
||||
};
|
||||
#else
|
||||
|
||||
extern PYXPCOM_EXPORT PyInterpreterState *PyXPCOM_InterpreterState;
|
||||
extern PYXPCOM_EXPORT PRBool PyXPCOM_ThreadState_Ensure();
|
||||
extern PYXPCOM_EXPORT void PyXPCOM_ThreadState_Free();
|
||||
extern PYXPCOM_EXPORT void PyXPCOM_ThreadState_Clear();
|
||||
extern PYXPCOM_EXPORT void PyXPCOM_InterpreterLock_Acquire();
|
||||
extern PYXPCOM_EXPORT void PyXPCOM_InterpreterLock_Release();
|
||||
PYXPCOM_EXPORT PyInterpreterState *PyXPCOM_InterpreterState;
|
||||
PYXPCOM_EXPORT PRBool PyXPCOM_ThreadState_Ensure();
|
||||
PYXPCOM_EXPORT void PyXPCOM_ThreadState_Free();
|
||||
PYXPCOM_EXPORT void PyXPCOM_ThreadState_Clear();
|
||||
PYXPCOM_EXPORT void PyXPCOM_InterpreterLock_Acquire();
|
||||
PYXPCOM_EXPORT void PyXPCOM_InterpreterLock_Release();
|
||||
|
||||
// Pre 2.3 thread-state dances.
|
||||
class CEnterLeavePython {
|
||||
@@ -662,11 +717,11 @@ extern struct PyMethodDef Methods[]; \
|
||||
class ClassName : public Py_nsISupports \
|
||||
{ \
|
||||
public: \
|
||||
static PyXPCOM_TypeObject *type; \
|
||||
static PYXPCOM_EXPORT PyXPCOM_TypeObject *type; \
|
||||
static Py_nsISupports *Constructor(nsISupports *pInitObj, const nsIID &iid) { \
|
||||
return new ClassName(pInitObj, iid); \
|
||||
} \
|
||||
static void InitType(PyObject *iidNameDict) { \
|
||||
static void InitType() { \
|
||||
type = new PyXPCOM_TypeObject( \
|
||||
#InterfaceName, \
|
||||
Py_nsISupports::type, \
|
||||
@@ -675,9 +730,6 @@ public: \
|
||||
Constructor); \
|
||||
const nsIID &iid = NS_GET_IID(InterfaceName); \
|
||||
RegisterInterface(iid, type); \
|
||||
PyObject *iid_ob = Py_nsIID::PyObjectFromIID(iid); \
|
||||
PyDict_SetItemString(iidNameDict, "IID_"#InterfaceName, iid_ob); \
|
||||
Py_DECREF(iid_ob); \
|
||||
} \
|
||||
protected: \
|
||||
ClassName(nsISupports *p, const nsIID &iid) : \
|
||||
@@ -700,7 +752,7 @@ public: \
|
||||
static Py_nsISupports *Constructor(nsISupports *pInitObj, const nsIID &iid) { \
|
||||
return new ClassName(pInitObj, iid); \
|
||||
} \
|
||||
static void InitType(PyObject *iidNameDict) { \
|
||||
static void InitType() { \
|
||||
type = new PyXPCOM_TypeObject( \
|
||||
#InterfaceName, \
|
||||
Py_nsISupports::type, \
|
||||
@@ -709,9 +761,6 @@ public: \
|
||||
Constructor); \
|
||||
const nsIID &iid = NS_GET_IID(InterfaceName); \
|
||||
RegisterInterface(iid, type); \
|
||||
PyObject *iid_ob = Py_nsIID::PyObjectFromIID(iid); \
|
||||
PyDict_SetItemString(iidNameDict, "IID_"#InterfaceName, iid_ob); \
|
||||
Py_DECREF(iid_ob); \
|
||||
} \
|
||||
virtual PyObject *getattr(const char *name); \
|
||||
virtual int setattr(const char *name, PyObject *val); \
|
||||
@@ -740,5 +789,4 @@ PyXPCOM_ATTR_INTERFACE_DECLARE(Py_nsIClassInfo, nsIClassInfo, PyMethods_IClassIn
|
||||
PyXPCOM_ATTR_INTERFACE_DECLARE(Py_nsIVariant, nsIVariant, PyMethods_IVariant)
|
||||
// deprecated, but retained for backward compatibility:
|
||||
PyXPCOM_INTERFACE_DECLARE(Py_nsIComponentManagerObsolete, nsIComponentManagerObsolete, PyMethods_IComponentManagerObsolete)
|
||||
|
||||
#endif // __PYXPCOM_H__
|
||||
|
||||
@@ -49,29 +49,6 @@
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include <Python.h>
|
||||
|
||||
#ifdef HAVE_LONG_LONG
|
||||
// Mozilla also defines this - we undefine it to
|
||||
// prevent a compiler warning.
|
||||
# undef HAVE_LONG_LONG
|
||||
#endif // HAVE_LONG_LONG
|
||||
|
||||
#include "nsIAllocator.h"
|
||||
#include "nsIWeakReference.h"
|
||||
#include "nsIInterfaceInfoManager.h"
|
||||
#include "nsIClassInfo.h"
|
||||
#include "nsIComponentManager.h"
|
||||
#include "nsIComponentManagerObsolete.h"
|
||||
#include "nsIServiceManager.h"
|
||||
#include "nsIInputStream.h"
|
||||
#include "nsIVariant.h"
|
||||
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsCRT.h"
|
||||
#include "xptcall.h"
|
||||
#include "xpt_xdr.h"
|
||||
|
||||
// This header is considered internal - hence
|
||||
// we can use it to trigger "exports"
|
||||
#define BUILD_PYXPCOM
|
||||
|
||||
@@ -152,7 +152,7 @@ PyObject *PyObject_FromXPTConstant( const XPTConstDescriptor *c)
|
||||
v = PyString_FromStringAndSize(&c->value.ch, 1);
|
||||
break;
|
||||
case TD_WCHAR:
|
||||
v = PyUnicode_FromPRUnichar((PRUnichar *)&c->value.wch, 1);
|
||||
v = PyObject_FromNSString((PRUnichar *)&c->value.wch, 1);
|
||||
break;
|
||||
// TD_VOID = 13,
|
||||
case TD_PNSIID:
|
||||
@@ -163,7 +163,7 @@ PyObject *PyObject_FromXPTConstant( const XPTConstDescriptor *c)
|
||||
v = PyString_FromString(c->value.str);
|
||||
break;
|
||||
case TD_PWSTRING:
|
||||
v = PyUnicode_FromPRUnichar((PRUnichar *)c->value.wstr, nsCRT::strlen((PRUnichar *)c->value.wstr));
|
||||
v = PyObject_FromNSString((PRUnichar *)c->value.wstr, nsCRT::strlen((PRUnichar *)c->value.wstr));
|
||||
break;
|
||||
// TD_INTERFACE_TYPE = 18,
|
||||
// TD_INTERFACE_IS_TYPE = 19,
|
||||
|
||||
@@ -69,10 +69,10 @@ static PyTypeObject PyInterfaceType_Type = {
|
||||
0, /*tp_hash*/
|
||||
0, /*tp_call*/
|
||||
0, /*tp_str*/
|
||||
0, /*tp_xxx1*/
|
||||
0, /*tp_xxx2*/
|
||||
0, /*tp_xxx3*/
|
||||
0, /*tp_xxx4*/
|
||||
0, /* tp_getattro */
|
||||
0, /*tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
0, /* tp_flags */
|
||||
"Define the behavior of a PythonCOM Interface type.",
|
||||
};
|
||||
|
||||
@@ -149,7 +149,8 @@ PyXPCOM_TypeObject::Py_repr(PyObject *self)
|
||||
iid_repr = pis->m_iid.ToString();
|
||||
// XXX - need some sort of buffer overflow.
|
||||
char buf[512];
|
||||
sprintf(buf, "<XPCOM object (%s) at 0x%p/0x%p>", iid_repr, self, pis->m_obj);
|
||||
sprintf(buf, "<XPCOM object (%s) at 0x%p/0x%p>",
|
||||
iid_repr, (void *)self, (void *)pis->m_obj.get());
|
||||
nsMemory::Free(iid_repr);
|
||||
return PyString_FromString(buf);
|
||||
}
|
||||
@@ -199,9 +200,24 @@ PyXPCOM_TypeObject::PyXPCOM_TypeObject( const char *name, PyXPCOM_TypeObject *pB
|
||||
0, /* tp_as_number*/
|
||||
0, /* tp_as_sequence */
|
||||
0, /* tp_as_mapping */
|
||||
Py_hash, /* tp_hash */
|
||||
Py_hash, /* tp_hash */
|
||||
0, /* tp_call */
|
||||
Py_str, /* tp_str */
|
||||
0, /* tp_getattro */
|
||||
0, /*tp_setattro */
|
||||
0, /* tp_as_buffer */
|
||||
0, /* tp_flags */
|
||||
0, /* tp_doc */
|
||||
0, /* tp_traverse */
|
||||
0, /* tp_clear */
|
||||
0, /* tp_richcompare */
|
||||
0, /* tp_weaklistoffset */
|
||||
0, /* tp_iter */
|
||||
0, /* tp_iternext */
|
||||
0, /* tp_methods */
|
||||
0, /* tp_members */
|
||||
0, /* tp_getset */
|
||||
0, /* tp_base */
|
||||
};
|
||||
|
||||
*((PyTypeObject *)this) = type_template;
|
||||
|
||||
@@ -72,6 +72,9 @@ IsNullDOMString( const nsACString& aString )
|
||||
return PR_FALSE;
|
||||
}
|
||||
|
||||
#define PyUnicode_FromPRUnichar(src, size) \
|
||||
PyUnicode_DecodeUTF16((char*)(src),sizeof(PRUnichar)*(size),NULL,NULL)
|
||||
|
||||
// Create a zero-terminated PRUnichar buffer from a Python unicode.
|
||||
// On success, returns 0. On failure, returns -1 and sets an exception.
|
||||
// dest_out must not be null. size_out may be null.
|
||||
@@ -104,7 +107,7 @@ PyUnicode_AsPRUnichar(PyObject *obj, PRUnichar **dest_out, PRUint32 *size_out)
|
||||
return 0;
|
||||
}
|
||||
|
||||
PyObject *PyObject_FromNSString( const nsACString &s, PRBool bAssumeUTF8 = PR_FALSE )
|
||||
PyObject *PyObject_FromNSString( const nsACString &s, PRBool bAssumeUTF8 /*= PR_FALSE */)
|
||||
{
|
||||
PyObject *ret;
|
||||
if (IsNullDOMString(s)) {
|
||||
@@ -134,12 +137,51 @@ PyObject *PyObject_FromNSString( const nsAString &s )
|
||||
ret = Py_None;
|
||||
Py_INCREF(Py_None);
|
||||
} else {
|
||||
const nsPromiseFlatString& temp = PromiseFlatString(s);
|
||||
ret = PyUnicode_FromPRUnichar(temp.get(), temp.Length());
|
||||
const nsPromiseFlatString& temp = PromiseFlatString(s);
|
||||
ret = PyUnicode_FromPRUnichar(temp.get(), temp.Length());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
PyObject *PyObject_FromNSString( const PRUnichar *s,
|
||||
PRUint32 len /* = (PRUint32)-1*/)
|
||||
{
|
||||
return PyUnicode_FromPRUnichar(s,
|
||||
len==((PRUint32)-1)? nsCRT::strlen(s) : len);
|
||||
}
|
||||
|
||||
PRBool PyObject_AsNSString( PyObject *val, nsAString &aStr)
|
||||
{
|
||||
if (val == Py_None) {
|
||||
aStr.Truncate();
|
||||
return NS_OK;
|
||||
}
|
||||
PyObject *val_use = NULL;
|
||||
PRBool ok = PR_TRUE;
|
||||
if (!PyString_Check(val) && !PyUnicode_Check(val)) {
|
||||
PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
|
||||
ok = PR_FALSE;
|
||||
}
|
||||
if (ok && (val_use = PyUnicode_FromObject(val))==NULL)
|
||||
ok = PR_FALSE;
|
||||
if (ok) {
|
||||
if (PyUnicode_GET_SIZE(val_use) == 0) {
|
||||
aStr.Truncate();
|
||||
}
|
||||
else {
|
||||
PRUint32 nch;
|
||||
PRUnichar *tempo;
|
||||
// can we do this without the copy?
|
||||
if (PyUnicode_AsPRUnichar(val_use, &tempo, &nch) < 0)
|
||||
return PR_FALSE;
|
||||
aStr.Assign(tempo, nch);
|
||||
nsMemory::Free(tempo);
|
||||
}
|
||||
}
|
||||
Py_XDECREF(val_use);
|
||||
return ok;
|
||||
}
|
||||
|
||||
// Array utilities
|
||||
static PRUint32 GetArrayElementSize( PRUint8 t)
|
||||
{
|
||||
@@ -247,7 +289,8 @@ void FreeSingleArray(void *array_ptr, PRUint32 sequence_size, PRUint8 array_type
|
||||
#define BREAK_FALSE {rc=PR_FALSE;break;}
|
||||
|
||||
|
||||
PRBool FillSingleArray(void *array_ptr, PyObject *sequence_ob, PRUint32 sequence_size, PRUint32 array_element_size, PRUint8 array_type)
|
||||
PRBool FillSingleArray(void *array_ptr, PyObject *sequence_ob, PRUint32 sequence_size,
|
||||
PRUint32 array_element_size, PRUint8 array_type, nsIID *pIID)
|
||||
{
|
||||
PRUint8 *pthis = (PRUint8 *)array_ptr;
|
||||
NS_ABORT_IF_FALSE(pthis, "Don't have a valid array to fill!");
|
||||
@@ -441,7 +484,8 @@ PRBool FillSingleArray(void *array_ptr, PyObject *sequence_ob, PRUint32 sequence
|
||||
return rc;
|
||||
}
|
||||
|
||||
PyObject *UnpackSingleArray(void *array_ptr, PRUint32 sequence_size, PRUint8 array_type, nsIID *iid)
|
||||
static PyObject *UnpackSingleArray(Py_nsISupports *parent, void *array_ptr,
|
||||
PRUint32 sequence_size, PRUint8 array_type, nsIID *iid)
|
||||
{
|
||||
if (array_ptr==NULL) {
|
||||
Py_INCREF(Py_None);
|
||||
@@ -514,7 +558,17 @@ PyObject *UnpackSingleArray(void *array_ptr, PRUint32 sequence_size, PRUint8 arr
|
||||
case nsXPTType::T_INTERFACE_IS:
|
||||
case nsXPTType::T_INTERFACE: {
|
||||
nsISupports **pp = (nsISupports **)pthis;
|
||||
val = Py_nsISupports::PyObjectFromInterface(*pp, iid ? *iid : NS_GET_IID(nsISupports), PR_TRUE);
|
||||
// If we have an owning parent, let it create
|
||||
// the object for us.
|
||||
if (iid && iid->Equals(NS_GET_IID(nsIVariant)))
|
||||
val = PyObject_FromVariant(parent, (nsIVariant *)*pp);
|
||||
else if (parent)
|
||||
val = parent->MakeInterfaceResult(*pp, iid ? *iid : NS_GET_IID(nsISupports));
|
||||
else
|
||||
val = Py_nsISupports::PyObjectFromInterface(
|
||||
*pp,
|
||||
iid ? *iid : NS_GET_IID(nsISupports),
|
||||
PR_TRUE);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
@@ -592,14 +646,11 @@ static PRUint16 BestVariantTypeForPyObject( PyObject *ob, BVFTResult *pdata = NU
|
||||
return (PRUint16)-1;
|
||||
}
|
||||
|
||||
nsIVariant *PyObject_AsVariant( PyObject *ob)
|
||||
nsresult PyObject_AsVariant( PyObject *ob, nsIVariant **aRet)
|
||||
{
|
||||
nsresult nr = NS_ERROR_UNEXPECTED;
|
||||
nsCOMPtr<nsIWritableVariant> v = do_CreateInstance("@mozilla.org/variant;1", &nr);
|
||||
if (NS_FAILED(nr)) {
|
||||
PyXPCOM_BuildPyException(nr);
|
||||
return NULL;
|
||||
}
|
||||
nsresult nr = NS_OK;
|
||||
nsCOMPtr<nsIWritableVariant> v = do_CreateInstance("@mozilla.org/variant;1", &nr);
|
||||
NS_ENSURE_SUCCESS(nr, nr);
|
||||
// *sigh* - I tried the abstract API (PyNumber_Check, etc)
|
||||
// but our COM instances too often qualify.
|
||||
BVFTResult cvt_result;
|
||||
@@ -628,6 +679,7 @@ nsIVariant *PyObject_AsVariant( PyObject *ob)
|
||||
PRUint32 nch;
|
||||
PRUnichar *p;
|
||||
if (PyUnicode_AsPRUnichar(ob, &p, &nch) < 0) {
|
||||
PyXPCOM_LogWarning("Failed to convert object to unicode", ob->ob_type->tp_name);
|
||||
nr = NS_ERROR_UNEXPECTED;
|
||||
break;
|
||||
}
|
||||
@@ -665,12 +717,11 @@ nsIVariant *PyObject_AsVariant( PyObject *ob)
|
||||
int cb_buffer_pointer = seq_length * element_size;
|
||||
void *buffer_pointer;
|
||||
if ((buffer_pointer = (void *)nsMemory::Alloc(cb_buffer_pointer)) == nsnull) {
|
||||
PyErr_NoMemory();
|
||||
nr = NS_ERROR_UNEXPECTED;
|
||||
nr = NS_ERROR_OUT_OF_MEMORY;
|
||||
break;
|
||||
}
|
||||
memset(buffer_pointer, 0, cb_buffer_pointer);
|
||||
if (FillSingleArray(buffer_pointer, ob, seq_length, element_size, array_type)) {
|
||||
if (FillSingleArray(buffer_pointer, ob, seq_length, element_size, array_type, nsnull)) {
|
||||
nr = v->SetAsArray(array_type, &NS_GET_IID(nsISupports), seq_length, buffer_pointer);
|
||||
FreeSingleArray(buffer_pointer, seq_length, array_type);
|
||||
} else
|
||||
@@ -679,22 +730,22 @@ nsIVariant *PyObject_AsVariant( PyObject *ob)
|
||||
break;
|
||||
}
|
||||
case nsIDataType::VTYPE_EMPTY:
|
||||
v->SetAsEmpty();
|
||||
nr = v->SetAsEmpty();
|
||||
break;
|
||||
case nsIDataType::VTYPE_EMPTY_ARRAY:
|
||||
v->SetAsEmptyArray();
|
||||
nr = v->SetAsEmptyArray();
|
||||
break;
|
||||
case (PRUint16)-1:
|
||||
PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be converted to an nsIVariant", ob->ob_type->tp_name);
|
||||
return NULL;
|
||||
PyXPCOM_LogWarning("Objects of type '%s' can not be converted to an nsIVariant", ob->ob_type->tp_name);
|
||||
nr = NS_ERROR_UNEXPECTED;
|
||||
default:
|
||||
NS_ABORT_IF_FALSE(0, "BestVariantTypeForPyObject() returned a variant type not handled here!");
|
||||
PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be converted to an nsIVariant", ob->ob_type->tp_name);
|
||||
return NULL;
|
||||
PyXPCOM_LogWarning("Objects of type '%s' can not be converted to an nsIVariant", ob->ob_type->tp_name);
|
||||
nr = NS_ERROR_UNEXPECTED;
|
||||
}
|
||||
nsIVariant *ret;
|
||||
v->QueryInterface(NS_GET_IID(nsIVariant), (void **)&ret);
|
||||
return ret;
|
||||
if (NS_FAILED(nr))
|
||||
return nr;
|
||||
return v->QueryInterface(NS_GET_IID(nsIVariant), (void **)aRet);
|
||||
}
|
||||
|
||||
static PyObject *MyBool_FromBool(PRBool v)
|
||||
@@ -703,10 +754,6 @@ static PyObject *MyBool_FromBool(PRBool v)
|
||||
Py_INCREF(ret);
|
||||
return ret;
|
||||
}
|
||||
static PyObject *MyObject_FromInterface(nsISupports *p)
|
||||
{
|
||||
return Py_nsISupports::PyObjectFromInterface(p, NS_GET_IID(nsISupports), PR_FALSE);
|
||||
}
|
||||
|
||||
#define GET_FROM_V(Type, FuncGet, FuncConvert) { \
|
||||
Type t; \
|
||||
@@ -715,7 +762,7 @@ static PyObject *MyObject_FromInterface(nsISupports *p)
|
||||
break; \
|
||||
}
|
||||
|
||||
PyObject *PyObject_FromVariantArray( nsIVariant *v)
|
||||
PyObject *PyObject_FromVariantArray( Py_nsISupports *parent, nsIVariant *v)
|
||||
{
|
||||
nsresult nr;
|
||||
NS_PRECONDITION(v, "NULL variant!");
|
||||
@@ -732,13 +779,13 @@ PyObject *PyObject_FromVariantArray( nsIVariant *v)
|
||||
PRUint32 count;
|
||||
nr = v->GetAsArray(&type, &iid, &count, &p);
|
||||
if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr);
|
||||
PyObject *ret = UnpackSingleArray(p, count, (PRUint8)type, &iid);
|
||||
PyObject *ret = UnpackSingleArray(parent, p, count, (PRUint8)type, &iid);
|
||||
FreeSingleArray(p, count, (PRUint8)type);
|
||||
nsMemory::Free(p);
|
||||
return ret;
|
||||
}
|
||||
|
||||
PyObject *PyObject_FromVariant( nsIVariant *v)
|
||||
PyObject *PyObject_FromVariant( Py_nsISupports *parent, nsIVariant *v)
|
||||
{
|
||||
if (!v) {
|
||||
Py_INCREF(Py_None);
|
||||
@@ -757,7 +804,7 @@ PyObject *PyObject_FromVariant( nsIVariant *v)
|
||||
Py_INCREF(Py_None);
|
||||
break;
|
||||
case nsIDataType::VTYPE_ARRAY:
|
||||
ret = PyObject_FromVariantArray(v);
|
||||
ret = PyObject_FromVariantArray(parent, v);
|
||||
break;
|
||||
case nsIDataType::VTYPE_INT8:
|
||||
case nsIDataType::VTYPE_INT16:
|
||||
@@ -799,13 +846,23 @@ PyObject *PyObject_FromVariant( nsIVariant *v)
|
||||
}
|
||||
case nsIDataType::VTYPE_ID:
|
||||
GET_FROM_V(nsIID, v->GetAsID, Py_nsIID::PyObjectFromIID);
|
||||
case nsIDataType::VTYPE_INTERFACE:
|
||||
GET_FROM_V(nsISupports *, v->GetAsISupports, MyObject_FromInterface);
|
||||
case nsIDataType::VTYPE_INTERFACE: {
|
||||
nsCOMPtr<nsISupports> p;
|
||||
if (NS_FAILED(nr=v->GetAsISupports(getter_AddRefs(p)))) goto done;
|
||||
if (parent)
|
||||
ret = parent->MakeInterfaceResult(p, NS_GET_IID(nsISupports));
|
||||
else
|
||||
ret = Py_nsISupports::PyObjectFromInterface(
|
||||
p, NS_GET_IID(nsISupports), PR_TRUE);
|
||||
break;
|
||||
}
|
||||
case nsIDataType::VTYPE_INTERFACE_IS: {
|
||||
nsISupports *p;
|
||||
nsCOMPtr<nsISupports> p;
|
||||
nsIID *iid;
|
||||
if (NS_FAILED(nr=v->GetAsInterface(&iid, (void **)&p))) goto done;
|
||||
ret = Py_nsISupports::PyObjectFromInterface(p, *iid, PR_FALSE);
|
||||
if (NS_FAILED(nr=v->GetAsInterface(&iid, getter_AddRefs(p)))) goto done;
|
||||
// If the variant itself holds a variant, we should
|
||||
// probably unpack that too?
|
||||
ret = parent->MakeInterfaceResult(p, *iid);
|
||||
break;
|
||||
// case nsIDataType::VTYPE_WCHAR_STR
|
||||
// case nsIDataType::VTYPE_UTF8STRING
|
||||
@@ -899,16 +956,20 @@ Helpers when CALLING interfaces.
|
||||
**************************************************************************
|
||||
*************************************************************************/
|
||||
|
||||
PyXPCOM_InterfaceVariantHelper::PyXPCOM_InterfaceVariantHelper()
|
||||
PyXPCOM_InterfaceVariantHelper::PyXPCOM_InterfaceVariantHelper(Py_nsISupports *parent)
|
||||
{
|
||||
m_var_array=nsnull;
|
||||
m_buffer_array=nsnull;
|
||||
m_pyparams=nsnull;
|
||||
m_num_array = 0;
|
||||
// Parent should never die before we do, but let's not take the chance.
|
||||
m_parent = parent;
|
||||
Py_INCREF(parent);
|
||||
}
|
||||
|
||||
PyXPCOM_InterfaceVariantHelper::~PyXPCOM_InterfaceVariantHelper()
|
||||
{
|
||||
Py_DECREF(m_parent);
|
||||
Py_XDECREF(m_pyparams);
|
||||
for (int i=0;i<m_num_array;i++) {
|
||||
if (m_var_array) {
|
||||
@@ -1217,35 +1278,17 @@ PRBool PyXPCOM_InterfaceVariantHelper::FillInVariant(const PythonTypeDescriptor
|
||||
break;
|
||||
case nsXPTType::T_ASTRING:
|
||||
case nsXPTType::T_DOMSTRING: {
|
||||
if (val==Py_None) {
|
||||
ns_v.val.p = new nsString();
|
||||
} else {
|
||||
if (!PyString_Check(val) && !PyUnicode_Check(val)) {
|
||||
PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
|
||||
BREAK_FALSE;
|
||||
}
|
||||
if ((val_use = PyUnicode_FromObject(val))==NULL)
|
||||
BREAK_FALSE;
|
||||
// Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode!
|
||||
NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a unicode object!");
|
||||
if (PyUnicode_GET_SIZE(val_use) == 0) {
|
||||
ns_v.val.p = new nsString();
|
||||
}
|
||||
else {
|
||||
PRUint32 nch;
|
||||
PRUnichar *tempo;
|
||||
if (PyUnicode_AsPRUnichar(val_use, &tempo, &nch) < 0)
|
||||
BREAK_FALSE;
|
||||
ns_v.val.p = new nsString(tempo, nch);
|
||||
nsMemory::Free(tempo);
|
||||
}
|
||||
}
|
||||
if (!ns_v.val.p) {
|
||||
nsString *s = new nsString();
|
||||
if (!s) {
|
||||
PyErr_NoMemory();
|
||||
BREAK_FALSE;
|
||||
}
|
||||
ns_v.val.p = s;
|
||||
// We created it - flag as such for cleanup.
|
||||
ns_v.flags |= nsXPTCVariant::VAL_IS_DOMSTR;
|
||||
|
||||
if (!PyObject_AsNSString(val, *s))
|
||||
BREAK_FALSE;
|
||||
break;
|
||||
}
|
||||
case nsXPTType::T_CSTRING:
|
||||
@@ -1440,7 +1483,7 @@ PRBool PyXPCOM_InterfaceVariantHelper::FillInVariant(const PythonTypeDescriptor
|
||||
cb_this_buffer_pointer = 1;
|
||||
MAKE_VALUE_BUFFER(cb_this_buffer_pointer);
|
||||
memset(this_buffer_pointer, 0, cb_this_buffer_pointer);
|
||||
rc = FillSingleArray(this_buffer_pointer, val, seq_length, element_size, array_type&XPT_TDP_TAGMASK);
|
||||
rc = FillSingleArray(this_buffer_pointer, val, seq_length, element_size, array_type&XPT_TDP_TAGMASK, nsnull);
|
||||
if (!rc) break;
|
||||
rc = SetSizeIs(value_index, PR_FALSE, seq_length);
|
||||
if (!rc) break;
|
||||
@@ -1658,9 +1701,12 @@ PyObject *PyXPCOM_InterfaceVariantHelper::MakeSinglePythonResult(int index)
|
||||
if (!Py_nsIID::IIDFromPyObject(td.extra, &iid))
|
||||
break;
|
||||
nsISupports *iret = *((nsISupports **)ns_v.ptr);
|
||||
// We _do_ add a reference here, as our cleanup code will
|
||||
// remove this reference should we own it.
|
||||
ret = Py_nsISupports::PyObjectFromInterfaceOrVariant(iret, iid, PR_TRUE);
|
||||
// Our cleanup code manages iret reference ownership, and our
|
||||
// new object takes its own.
|
||||
if (iid.Equals(NS_GET_IID(nsIVariant)))
|
||||
ret = PyObject_FromVariant(m_parent, (nsIVariant *)iret);
|
||||
else
|
||||
ret = m_parent->MakeInterfaceResult(iret, iid);
|
||||
break;
|
||||
}
|
||||
case nsXPTType::T_INTERFACE_IS: {
|
||||
@@ -1674,15 +1720,18 @@ PyObject *PyXPCOM_InterfaceVariantHelper::MakeSinglePythonResult(int index)
|
||||
iid = NS_GET_IID(nsISupports);
|
||||
else
|
||||
iid = *piid;
|
||||
} else
|
||||
} else {
|
||||
// This is a pretty serious problem, but not Python's fault!
|
||||
// Just return an nsISupports and hope the caller does whatever
|
||||
// QI they need before using it.
|
||||
NS_ERROR("Failed to get the IID for T_INTERFACE_IS!");
|
||||
iid = NS_GET_IID(nsISupports);
|
||||
}
|
||||
nsISupports *iret = *((nsISupports **)ns_v.ptr);
|
||||
// We _do_ add a reference here, as our cleanup code will
|
||||
// remove this reference should we own it.
|
||||
ret = Py_nsISupports::PyObjectFromInterfaceOrVariant(iret, iid, PR_TRUE);
|
||||
if (iid.Equals(NS_GET_IID(nsIVariant)))
|
||||
ret = PyObject_FromVariant(m_parent, (nsIVariant *)iret);
|
||||
else
|
||||
ret = m_parent->MakeInterfaceResult(iret, iid);
|
||||
break;
|
||||
}
|
||||
case nsXPTType::T_ARRAY: {
|
||||
@@ -1696,7 +1745,7 @@ PyObject *PyXPCOM_InterfaceVariantHelper::MakeSinglePythonResult(int index)
|
||||
}
|
||||
PRUint8 array_type = (PRUint8)PyInt_AsLong(td.extra);
|
||||
PRUint32 seq_size = GetSizeIs(index, PR_FALSE);
|
||||
ret = UnpackSingleArray(* ((void **)ns_v.ptr), seq_size, array_type&XPT_TDP_TAGMASK, NULL);
|
||||
ret = UnpackSingleArray(m_parent, * ((void **)ns_v.ptr), seq_size, array_type&XPT_TDP_TAGMASK, NULL);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -2032,17 +2081,20 @@ PyObject *PyXPCOM_GatewayVariantHelper::MakeSingleParam(int index, PythonTypeDes
|
||||
case nsXPTType::T_ARRAY: {
|
||||
void *t = DEREF_IN_OR_OUT(ns_v.val.p, void *);
|
||||
if (t==NULL) {
|
||||
ret = Py_None;
|
||||
Py_INCREF(Py_None);
|
||||
// JS may send us a NULL here occasionally - as the
|
||||
// type is array, we silently convert this to a zero
|
||||
// length list, a-la JS.
|
||||
ret = PyList_New(0);
|
||||
} else {
|
||||
PRUint8 array_type;
|
||||
nsresult ns = GetArrayType(index, &array_type);
|
||||
nsIID *piid;
|
||||
nsresult ns = GetArrayType(index, &array_type, &piid);
|
||||
if (NS_FAILED(ns)) {
|
||||
PyXPCOM_BuildPyException(ns);
|
||||
break;
|
||||
}
|
||||
PRUint32 seq_size = GetSizeIs(index, PR_FALSE);
|
||||
ret = UnpackSingleArray(t, seq_size, array_type&XPT_TDP_TAGMASK, NULL);
|
||||
ret = UnpackSingleArray(NULL, t, seq_size, array_type&XPT_TDP_TAGMASK, piid);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2081,7 +2133,7 @@ PyObject *PyXPCOM_GatewayVariantHelper::MakeSingleParam(int index, PythonTypeDes
|
||||
return ret;
|
||||
}
|
||||
|
||||
nsresult PyXPCOM_GatewayVariantHelper::GetArrayType(PRUint8 index, PRUint8 *ret)
|
||||
nsresult PyXPCOM_GatewayVariantHelper::GetArrayType(PRUint8 index, PRUint8 *ret, nsIID **iid)
|
||||
{
|
||||
nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService(
|
||||
NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID));
|
||||
@@ -2098,6 +2150,13 @@ nsresult PyXPCOM_GatewayVariantHelper::GetArrayType(PRUint8 index, PRUint8 *ret)
|
||||
rc = ii->GetTypeForParam(m_method_index, ¶m_info, 1, &datumType);
|
||||
if (NS_FAILED(rc))
|
||||
return rc;
|
||||
if (iid) {
|
||||
*iid = (nsIID *)&NS_GET_IID(nsISupports);
|
||||
if (XPT_TDP_TAG(datumType)==nsXPTType::T_INTERFACE ||
|
||||
XPT_TDP_TAG(datumType)==nsXPTType::T_INTERFACE_IS ||
|
||||
XPT_TDP_TAG(datumType)==nsXPTType::T_ARRAY)
|
||||
ii->GetIIDForParam(m_method_index, ¶m_info, iid);
|
||||
}
|
||||
*ret = datumType.flags;
|
||||
return NS_OK;
|
||||
}
|
||||
@@ -2253,29 +2312,8 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index
|
||||
case nsXPTType::T_DOMSTRING: {
|
||||
nsAString *ws = (nsAString *)ns_v.val.p;
|
||||
NS_ABORT_IF_FALSE(ws->Length() == 0, "Why does this writable string already have chars??");
|
||||
if (val == Py_None) {
|
||||
(*ws) = (PRUnichar *)nsnull;
|
||||
} else {
|
||||
if (!PyString_Check(val) && !PyUnicode_Check(val)) {
|
||||
PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object");
|
||||
BREAK_FALSE;
|
||||
}
|
||||
val_use = PyUnicode_FromObject(val);
|
||||
if (!val_use)
|
||||
BREAK_FALSE;
|
||||
NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didn't return a Unicode object!");
|
||||
if (PyUnicode_GET_SIZE(val_use) == 0) {
|
||||
ws->Assign((PRUnichar*)NULL, 0);
|
||||
}
|
||||
else {
|
||||
PRUint32 nch;
|
||||
PRUnichar *sz;
|
||||
if (PyUnicode_AsPRUnichar(val_use, &sz, &nch) < 0)
|
||||
BREAK_FALSE;
|
||||
ws->Assign(sz, nch);
|
||||
nsMemory::Free(sz);
|
||||
}
|
||||
}
|
||||
if (!PyObject_AsNSString(val, *ws))
|
||||
BREAK_FALSE;
|
||||
break;
|
||||
}
|
||||
case nsXPTType::T_CSTRING: {
|
||||
@@ -2389,8 +2427,6 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index
|
||||
break;
|
||||
}
|
||||
case nsXPTType::T_INTERFACE_IS: {
|
||||
// We do allow NULL here, even tho doing so will no-doubt crash some objects.
|
||||
// (but there will certainly be objects out there that will allow NULL :-(
|
||||
const nsIID *piid;
|
||||
if (!GetIIDForINTERFACE_ID(pi->type.argnum, &piid))
|
||||
BREAK_FALSE;
|
||||
@@ -2521,7 +2557,8 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index
|
||||
// If it is an existing array of the correct size, keep it.
|
||||
PRUint32 sequence_size = 0;
|
||||
PRUint8 array_type;
|
||||
nsresult ns = GetArrayType(index, &array_type);
|
||||
nsIID *piid;
|
||||
nsresult ns = GetArrayType(index, &array_type, &piid);
|
||||
if (NS_FAILED(ns))
|
||||
return ns;
|
||||
PRUint32 element_size = GetArrayElementSize(array_type);
|
||||
@@ -2548,7 +2585,7 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index
|
||||
bBackFill = pi->IsIn();
|
||||
}
|
||||
if (bBackFill)
|
||||
rc = FillSingleArray(*(void **)ns_v.val.p, val, sequence_size, element_size, array_type&XPT_TDP_TAGMASK);
|
||||
rc = FillSingleArray(*(void **)ns_v.val.p, val, sequence_size, element_size, array_type&XPT_TDP_TAGMASK, piid);
|
||||
else {
|
||||
// If it is an existing array, free it.
|
||||
void **pp = (void **)ns_v.val.p;
|
||||
@@ -2563,7 +2600,7 @@ nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index
|
||||
if (nbytes==0) nbytes = 1; // avoid assertion about 0 bytes
|
||||
*pp = (void *)nsMemory::Alloc(nbytes);
|
||||
memset(*pp, 0, nbytes);
|
||||
rc = FillSingleArray(*pp, val, sequence_size, element_size, array_type&XPT_TDP_TAGMASK);
|
||||
rc = FillSingleArray(*pp, val, sequence_size, element_size, array_type&XPT_TDP_TAGMASK, piid);
|
||||
if (!rc) break;
|
||||
if (bCanSetSizeIs)
|
||||
rc = SetSizeIs(index, PR_FALSE, sequence_size);
|
||||
|
||||
@@ -47,6 +47,8 @@
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include <prthread.h>
|
||||
#include "nsIThread.h"
|
||||
#include "nsILocalFile.h"
|
||||
|
||||
#ifdef XP_WIN
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
@@ -58,6 +60,17 @@
|
||||
static PRInt32 g_cLockCount = 0;
|
||||
static PRLock *g_lockMain = nsnull;
|
||||
|
||||
PYXPCOM_EXPORT PyObject *PyXPCOM_Error = NULL;
|
||||
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIComponentManager, nsIComponentManager, PyMethods_IComponentManager)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIInterfaceInfoManager, nsIInterfaceInfoManager, PyMethods_IInterfaceInfoManager)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIEnumerator, nsIEnumerator, PyMethods_IEnumerator)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsISimpleEnumerator, nsISimpleEnumerator, PyMethods_ISimpleEnumerator)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIInterfaceInfo, nsIInterfaceInfo, PyMethods_IInterfaceInfo)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIInputStream, nsIInputStream, PyMethods_IInputStream)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIClassInfo, nsIClassInfo, PyMethods_IClassInfo)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIVariant, nsIVariant, PyMethods_IVariant)
|
||||
|
||||
#ifndef PYXPCOM_USE_PYGILSTATE
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
@@ -245,3 +258,86 @@ struct DllInitializer {
|
||||
pyxpcom_destruct();
|
||||
}
|
||||
} dll_initializer;
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Other helpers/global functions.
|
||||
//
|
||||
PRBool PyXPCOM_Globals_Ensure()
|
||||
{
|
||||
PRBool rc = PR_TRUE;
|
||||
|
||||
#ifndef PYXPCOM_USE_PYGILSTATE
|
||||
PyXPCOM_InterpreterState_Ensure();
|
||||
#endif
|
||||
|
||||
// The exception object - we load it from .py code!
|
||||
if (PyXPCOM_Error == NULL) {
|
||||
rc = PR_FALSE;
|
||||
PyObject *mod = NULL;
|
||||
|
||||
mod = PyImport_ImportModule("xpcom");
|
||||
if (mod!=NULL) {
|
||||
PyXPCOM_Error = PyObject_GetAttrString(mod, "Exception");
|
||||
Py_DECREF(mod);
|
||||
}
|
||||
rc = (PyXPCOM_Error != NULL);
|
||||
}
|
||||
if (!rc)
|
||||
return rc;
|
||||
|
||||
static PRBool bHaveInitXPCOM = PR_FALSE;
|
||||
if (!bHaveInitXPCOM) {
|
||||
nsCOMPtr<nsIThread> thread_check;
|
||||
// xpcom appears to assert if already initialized
|
||||
// Is there an official way to determine this?
|
||||
if (NS_FAILED(nsIThread::GetMainThread(getter_AddRefs(thread_check)))) {
|
||||
// not already initialized.
|
||||
#ifdef XP_WIN
|
||||
// On Windows, we need to locate the Mozilla bin
|
||||
// directory. This by using locating a Moz DLL we depend
|
||||
// on, and assume it lives in that bin dir. Different
|
||||
// moz build types (eg, xulrunner, suite) package
|
||||
// XPCOM itself differently - but all appear to require
|
||||
// nspr4.dll - so this is what we use.
|
||||
char landmark[MAX_PATH+1];
|
||||
HMODULE hmod = GetModuleHandle("nspr4.dll");
|
||||
if (hmod==NULL) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "We dont appear to be linked against nspr4.dll.");
|
||||
return PR_FALSE;
|
||||
}
|
||||
GetModuleFileName(hmod, landmark, sizeof(landmark)/sizeof(landmark[0]));
|
||||
char *end = landmark + (strlen(landmark)-1);
|
||||
while (end > landmark && *end != '\\')
|
||||
end--;
|
||||
if (end > landmark) *end = '\0';
|
||||
|
||||
nsCOMPtr<nsILocalFile> ns_bin_dir;
|
||||
NS_ConvertASCIItoUCS2 strLandmark(landmark);
|
||||
NS_NewLocalFile(strLandmark, PR_FALSE, getter_AddRefs(ns_bin_dir));
|
||||
nsresult rv = NS_InitXPCOM2(nsnull, ns_bin_dir, nsnull);
|
||||
#else
|
||||
// Elsewhere, Mozilla can find it itself (we hope!)
|
||||
nsresult rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
|
||||
#endif // XP_WIN
|
||||
if (NS_FAILED(rv)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "The XPCOM subsystem could not be initialized");
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
// Even if xpcom was already init, we want to flag it as init!
|
||||
bHaveInitXPCOM = PR_TRUE;
|
||||
// Register our custom interfaces.
|
||||
|
||||
Py_nsISupports::InitType();
|
||||
Py_nsIComponentManager::InitType();
|
||||
Py_nsIInterfaceInfoManager::InitType();
|
||||
Py_nsIEnumerator::InitType();
|
||||
Py_nsISimpleEnumerator::InitType();
|
||||
Py_nsIInterfaceInfo::InitType();
|
||||
Py_nsIInputStream::InitType();
|
||||
Py_nsIClassInfo::InitType();
|
||||
Py_nsIVariant::InitType();
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,14 +46,22 @@ include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
LIBRARY_NAME = pyloader
|
||||
IS_COMPONENT = 1
|
||||
REQUIRES = xpcom string xpcom_obsolete $(NULL)
|
||||
REQUIRES = pyxpcom xpcom string xpcom_obsolete $(NULL)
|
||||
MOZILLA_INTERNAL_API = 1
|
||||
FORCE_SHARED_LIB = 1
|
||||
FORCE_USE_PIC = 1
|
||||
|
||||
LOCAL_INCLUDES = $(PYTHON_INCLUDES)
|
||||
|
||||
EXTRA_LIBS += $(PYTHON_LIBS)
|
||||
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
EXTRA_LIBS += $(DIST)/lib/pyxpcom.lib
|
||||
else
|
||||
EXTRA_LIBS += -lpyxpcom
|
||||
endif
|
||||
|
||||
|
||||
CPPSRCS = \
|
||||
pyloader.cpp \
|
||||
$(NULL)
|
||||
|
||||
@@ -41,26 +41,13 @@
|
||||
//
|
||||
// The main loader and registrar for Python. A thin DLL that is designed to live in
|
||||
// the xpcom "components" directory. Simply locates and loads the standard
|
||||
// _xpcom support module and transfers control to that.
|
||||
// pyxpcom core library and transfers control to that.
|
||||
|
||||
#include <Python.h>
|
||||
#include <PyXPCOM.h>
|
||||
|
||||
#ifdef HAVE_LONG_LONG
|
||||
#undef HAVE_LONG_LONG
|
||||
#endif
|
||||
|
||||
#include "nsISupports.h"
|
||||
#include "nsIModule.h"
|
||||
#include "nsDirectoryServiceDefs.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsString.h"
|
||||
#include "nsXPIDLString.h"
|
||||
#include "nsString.h"
|
||||
#include "stdlib.h"
|
||||
#include "stdarg.h"
|
||||
|
||||
#include "nsReadableUtils.h"
|
||||
#include "nsCRT.h"
|
||||
#include "nspr.h" // PR_fprintf
|
||||
|
||||
#if (PY_VERSION_HEX >= 0x02030000)
|
||||
@@ -86,9 +73,6 @@ typedef nsresult (*pfnPyXPCOM_NSGetModule)(nsIComponentManager *servMgr,
|
||||
nsIModule** result);
|
||||
|
||||
|
||||
pfnPyXPCOM_NSGetModule pfnEntryPoint = nsnull;
|
||||
|
||||
|
||||
static void LogError(const char *fmt, ...);
|
||||
static void LogDebug(const char *fmt, ...);
|
||||
|
||||
@@ -133,6 +117,63 @@ void AddStandardPaths()
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// This is the main entry point that delegates into Python
|
||||
nsresult PyXPCOM_NSGetModule(nsIComponentManager *servMgr,
|
||||
nsIFile* location,
|
||||
nsIModule** result)
|
||||
{
|
||||
NS_PRECONDITION(result!=NULL, "null result pointer in PyXPCOM_NSGetModule!");
|
||||
NS_PRECONDITION(location!=NULL, "null nsIFile pointer in PyXPCOM_NSGetModule!");
|
||||
NS_PRECONDITION(servMgr!=NULL, "null servMgr pointer in PyXPCOM_NSGetModule!");
|
||||
#ifndef LOADER_LINKS_WITH_PYTHON
|
||||
if (!Py_IsInitialized()) {
|
||||
Py_Initialize();
|
||||
if (!Py_IsInitialized()) {
|
||||
PyXPCOM_LogError("Python initialization failed!\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
PyEval_InitThreads();
|
||||
#ifndef PYXPCOM_USE_PYGILSTATE
|
||||
PyXPCOM_InterpreterState_Ensure();
|
||||
#endif
|
||||
PyEval_SaveThread();
|
||||
}
|
||||
#endif // LOADER_LINKS_WITH_PYTHON
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *func = NULL;
|
||||
PyObject *obServMgr = NULL;
|
||||
PyObject *obLocation = NULL;
|
||||
PyObject *wrap_ret = NULL;
|
||||
PyObject *args = NULL;
|
||||
PyObject *mod = PyImport_ImportModule("xpcom.server");
|
||||
if (!mod) goto done;
|
||||
func = PyObject_GetAttrString(mod, "NS_GetModule");
|
||||
if (func==NULL) goto done;
|
||||
obServMgr = Py_nsISupports::PyObjectFromInterface(servMgr, NS_GET_IID(nsIComponentManager));
|
||||
if (obServMgr==NULL) goto done;
|
||||
obLocation = Py_nsISupports::PyObjectFromInterface(location, NS_GET_IID(nsIFile));
|
||||
if (obLocation==NULL) goto done;
|
||||
args = Py_BuildValue("OO", obServMgr, obLocation);
|
||||
if (args==NULL) goto done;
|
||||
wrap_ret = PyEval_CallObject(func, args);
|
||||
if (wrap_ret==NULL) goto done;
|
||||
Py_nsISupports::InterfaceFromPyObject(wrap_ret, NS_GET_IID(nsIModule), (nsISupports **)result, PR_FALSE, PR_FALSE);
|
||||
done:
|
||||
nsresult nr = NS_OK;
|
||||
if (PyErr_Occurred()) {
|
||||
PyXPCOM_LogError("Obtaining the module object from Python failed.\n");
|
||||
nr = PyXPCOM_SetCOMErrorFromPyException();
|
||||
}
|
||||
Py_XDECREF(func);
|
||||
Py_XDECREF(obServMgr);
|
||||
Py_XDECREF(obLocation);
|
||||
Py_XDECREF(wrap_ret);
|
||||
Py_XDECREF(mod);
|
||||
Py_XDECREF(args);
|
||||
return nr;
|
||||
}
|
||||
|
||||
extern "C" NS_EXPORT nsresult NSGetModule(nsIComponentManager *servMgr,
|
||||
nsIFile* location,
|
||||
nsIModule** result)
|
||||
@@ -152,7 +193,6 @@ extern "C" NS_EXPORT nsresult NSGetModule(nsIComponentManager *servMgr,
|
||||
#ifndef NS_DEBUG
|
||||
Py_OptimizeFlag = 1;
|
||||
#endif // NS_DEBUG
|
||||
AddStandardPaths();
|
||||
PyEval_InitThreads();
|
||||
NS_TIMELINE_STOP_TIMER("PyXPCOM: Python initializing");
|
||||
NS_TIMELINE_MARK_TIMER("PyXPCOM: Python initializing");
|
||||
@@ -177,25 +217,6 @@ extern "C" NS_EXPORT nsresult NSGetModule(nsIComponentManager *servMgr,
|
||||
#else
|
||||
PyGILState_STATE state = PyGILState_Ensure();
|
||||
#endif // PYXPCOM_USE_PYGILSTATE
|
||||
if (pfnEntryPoint == nsnull) {
|
||||
PyObject *mod = PyImport_ImportModule("xpcom._xpcom");
|
||||
if (mod==NULL) {
|
||||
LogError("Could not import the Python XPCOM extension\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
PyObject *obpfn = PyObject_GetAttrString(mod, "_NSGetModule_FuncPtr");
|
||||
void *pfn = NULL;
|
||||
if (obpfn) {
|
||||
NS_ABORT_IF_FALSE(PyLong_Check(obpfn)||PyInt_Check(obpfn), "xpcom._NSGetModule_FuncPtr is not a long!");
|
||||
pfn = PyLong_AsVoidPtr(obpfn);
|
||||
}
|
||||
pfnEntryPoint = (pfnPyXPCOM_NSGetModule)pfn;
|
||||
}
|
||||
if (pfnEntryPoint==NULL) {
|
||||
LogError("Could not load main Python entry point\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
#ifdef MOZ_TIMELINE
|
||||
// If the timeline service is installed, see if we can install our hooks.
|
||||
if (NULL==PyImport_ImportModule("timeline_hook")) {
|
||||
@@ -204,6 +225,10 @@ extern "C" NS_EXPORT nsresult NSGetModule(nsIComponentManager *servMgr,
|
||||
PyErr_Clear(); // but don't care if we can't.
|
||||
}
|
||||
#endif
|
||||
// Add the standard paths always - we may not have been the first to
|
||||
// init Python.
|
||||
AddStandardPaths();
|
||||
|
||||
#ifndef PYXPCOM_USE_PYGILSTATE
|
||||
// Abandon the thread-lock, as the first thing Python does
|
||||
// is re-establish the lock (the Python thread-state story SUCKS!!!)
|
||||
@@ -226,7 +251,7 @@ extern "C" NS_EXPORT nsresult NSGetModule(nsIComponentManager *servMgr,
|
||||
NS_TIMELINE_STOP_TIMER("PyXPCOM: Python threadstate setup");
|
||||
NS_TIMELINE_MARK_TIMER("PyXPCOM: Python threadstate setup");
|
||||
NS_TIMELINE_START_TIMER("PyXPCOM: PyXPCOM NSGetModule entry point");
|
||||
nsresult rc = (*pfnEntryPoint)(servMgr, location, result);
|
||||
nsresult rc = PyXPCOM_NSGetModule(servMgr, location, result);
|
||||
NS_TIMELINE_STOP_TIMER("PyXPCOM: PyXPCOM NSGetModule entry point");
|
||||
NS_TIMELINE_MARK_TIMER("PyXPCOM: PyXPCOM NSGetModule entry point");
|
||||
return rc;
|
||||
|
||||
94
mozilla/extensions/python/xpcom/src/module/Makefile.in
Normal file
94
mozilla/extensions/python/xpcom/src/module/Makefile.in
Normal file
@@ -0,0 +1,94 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is mozilla.org
|
||||
# Portions created by the Initial Developer are Copyright (C) 2002
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Mark Hammond <mhammond@skippinet.com.au> (original author)
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# The xpcom._xpcom module
|
||||
|
||||
DEPTH=../../../../..
|
||||
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
pyexecdir = @libdir@/python$(PYTHON_VER_DOTTED)/site-packages
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
LIBRARY_NAME = _xpcom$(PYTHON_DEBUG_SUFFIX)
|
||||
REQUIRES = pyxpcom xpcom string $(NULL)
|
||||
MOZILLA_INTERNAL_API = 1
|
||||
FORCE_SHARED_LIB = 1
|
||||
FORCE_USE_PIC = 1
|
||||
|
||||
DLL_SUFFIX=$(PYTHON_DLL_SUFFIX)
|
||||
LOCAL_INCLUDES = $(PYTHON_INCLUDES)
|
||||
|
||||
EXTRA_LIBS += $(PYTHON_LIBS)
|
||||
|
||||
ifeq ($(OS_ARCH), WINNT)
|
||||
EXTRA_LIBS += $(DIST)/lib/pyxpcom.lib
|
||||
else
|
||||
EXTRA_LIBS += -lpyxpcom
|
||||
endif
|
||||
|
||||
CPPSRCS= \
|
||||
_xpcom.cpp \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/config.mk
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
EXTRA_DSO_LDOPTS += $(MOZ_COMPONENT_LIBS)
|
||||
IMPORT_LIBRARY := $(SHARED_LIBRARY:.pyd=.lib)
|
||||
|
||||
# Install into our Python directory
|
||||
# default build installs into bin and lib - remove them
|
||||
libs::
|
||||
ifeq ($(OS_ARCH),WINNT)
|
||||
$(INSTALL) -m 555 $(SHARED_LIBRARY) $(DIST)/bin/python/xpcom
|
||||
else
|
||||
$(INSTALL) -m 555 $(SHARED_LIBRARY) $(DIST)/bin/python/xpcom
|
||||
mv $(DIST)/bin/python/xpcom/$(SHARED_LIBRARY) $(DIST)/bin/python/xpcom/_xpcom.so
|
||||
endif
|
||||
rm -f $(DIST)/bin/$(SHARED_LIBRARY)
|
||||
rm -f $(DIST)/lib/$(IMPORT_LIBRARY)
|
||||
|
||||
install::
|
||||
ifneq ($(OS_ARCH),WINNT)
|
||||
$(SYSINSTALL) $(IFLAGS2) $(SHARED_LIBRARY) $(DISTDIR)$(pyexecdir)/xpcom
|
||||
mv $(DISTDIR)$(pyexecdir)/xpcom/$(SHARED_LIBRARY) $(DISTDIR)$(pyexecdir)/xpcom/_xpcom$(PYTHON_DLL_SUFFIX)
|
||||
endif
|
||||
|
||||
clobber::
|
||||
rm -f *.ilk *.pdb
|
||||
@@ -45,14 +45,13 @@
|
||||
//
|
||||
// (c) 2000, ActiveState corp.
|
||||
|
||||
#include "PyXPCOM_std.h"
|
||||
#include "nsIThread.h"
|
||||
#include "PyXPCOM.h"
|
||||
#include "nsXPCOM.h"
|
||||
#include "nsISupportsPrimitives.h"
|
||||
#include "nsIModule.h"
|
||||
#include "nsIFile.h"
|
||||
#include "nsILocalFile.h"
|
||||
#include "nsIComponentRegistrar.h"
|
||||
#include "nsIConsoleService.h"
|
||||
#include "nspr.h" // PR_fprintf
|
||||
|
||||
#ifdef XP_WIN
|
||||
#ifndef WIN32_LEAN_AND_MEAN
|
||||
@@ -64,85 +63,12 @@
|
||||
#include "nsIEventQueue.h"
|
||||
#include "nsIProxyObjectManager.h"
|
||||
|
||||
PYXPCOM_EXPORT PyObject *PyXPCOM_Error = NULL;
|
||||
extern PRInt32 _PyXPCOM_GetGatewayCount(void);
|
||||
extern PRInt32 _PyXPCOM_GetInterfaceCount(void);
|
||||
|
||||
extern void AddDefaultGateway(PyObject *instance, nsISupports *gateway);
|
||||
|
||||
#define LOADER_LINKS_WITH_PYTHON
|
||||
|
||||
#ifndef PYXPCOM_USE_PYGILSTATE
|
||||
extern void PyXPCOM_InterpreterState_Ensure();
|
||||
extern PYXPCOM_EXPORT void PyXPCOM_InterpreterState_Ensure();
|
||||
#endif
|
||||
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIComponentManager, nsIComponentManager, PyMethods_IComponentManager)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIInterfaceInfoManager, nsIInterfaceInfoManager, PyMethods_IInterfaceInfoManager)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIEnumerator, nsIEnumerator, PyMethods_IEnumerator)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsISimpleEnumerator, nsISimpleEnumerator, PyMethods_ISimpleEnumerator)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIInterfaceInfo, nsIInterfaceInfo, PyMethods_IInterfaceInfo)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIInputStream, nsIInputStream, PyMethods_IInputStream)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIClassInfo, nsIClassInfo, PyMethods_IClassInfo)
|
||||
PyXPCOM_INTERFACE_DEFINE(Py_nsIVariant, nsIVariant, PyMethods_IVariant)
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// This is the main entry point called by the Python component
|
||||
// loader.
|
||||
extern "C" NS_EXPORT nsresult PyXPCOM_NSGetModule(nsIComponentManager *servMgr,
|
||||
nsIFile* location,
|
||||
nsIModule** result)
|
||||
{
|
||||
NS_PRECONDITION(result!=NULL, "null result pointer in PyXPCOM_NSGetModule!");
|
||||
NS_PRECONDITION(location!=NULL, "null nsIFile pointer in PyXPCOM_NSGetModule!");
|
||||
NS_PRECONDITION(servMgr!=NULL, "null servMgr pointer in PyXPCOM_NSGetModule!");
|
||||
#ifndef LOADER_LINKS_WITH_PYTHON
|
||||
if (!Py_IsInitialized()) {
|
||||
Py_Initialize();
|
||||
if (!Py_IsInitialized()) {
|
||||
PyXPCOM_LogError("Python initialization failed!\n");
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
PyEval_InitThreads();
|
||||
#ifndef PYXPCOM_USE_PYGILSTATE
|
||||
PyXPCOM_InterpreterState_Ensure();
|
||||
#endif
|
||||
PyEval_SaveThread();
|
||||
}
|
||||
#endif // LOADER_LINKS_WITH_PYTHON
|
||||
CEnterLeavePython _celp;
|
||||
PyObject *func = NULL;
|
||||
PyObject *obServMgr = NULL;
|
||||
PyObject *obLocation = NULL;
|
||||
PyObject *wrap_ret = NULL;
|
||||
PyObject *args = NULL;
|
||||
PyObject *mod = PyImport_ImportModule("xpcom.server");
|
||||
if (!mod) goto done;
|
||||
func = PyObject_GetAttrString(mod, "NS_GetModule");
|
||||
if (func==NULL) goto done;
|
||||
obServMgr = Py_nsISupports::PyObjectFromInterface(servMgr, NS_GET_IID(nsIComponentManager), PR_TRUE);
|
||||
if (obServMgr==NULL) goto done;
|
||||
obLocation = Py_nsISupports::PyObjectFromInterface(location, NS_GET_IID(nsIFile), PR_TRUE);
|
||||
if (obLocation==NULL) goto done;
|
||||
args = Py_BuildValue("OO", obServMgr, obLocation);
|
||||
if (args==NULL) goto done;
|
||||
wrap_ret = PyEval_CallObject(func, args);
|
||||
if (wrap_ret==NULL) goto done;
|
||||
Py_nsISupports::InterfaceFromPyObject(wrap_ret, NS_GET_IID(nsIModule), (nsISupports **)result, PR_FALSE, PR_FALSE);
|
||||
done:
|
||||
nsresult nr = NS_OK;
|
||||
if (PyErr_Occurred()) {
|
||||
PyXPCOM_LogError("Obtaining the module object from Python failed.\n");
|
||||
nr = PyXPCOM_SetCOMErrorFromPyException();
|
||||
}
|
||||
Py_XDECREF(func);
|
||||
Py_XDECREF(obServMgr);
|
||||
Py_XDECREF(obLocation);
|
||||
Py_XDECREF(wrap_ret);
|
||||
Py_XDECREF(mod);
|
||||
Py_XDECREF(args);
|
||||
return nr;
|
||||
}
|
||||
|
||||
// "boot-strap" methods - interfaces we need to get the base
|
||||
// interface support!
|
||||
|
||||
@@ -151,15 +77,33 @@ PyXPCOMMethod_GetComponentManager(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
nsIComponentManager* cm;
|
||||
nsCOMPtr<nsIComponentManager> cm;
|
||||
nsresult rv;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
rv = NS_GetComponentManager(&cm);
|
||||
rv = NS_GetComponentManager(getter_AddRefs(cm));
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(rv) )
|
||||
return PyXPCOM_BuildPyException(rv);
|
||||
|
||||
return Py_nsISupports::PyObjectFromInterface(cm, NS_GET_IID(nsIComponentManager), PR_FALSE, PR_FALSE);
|
||||
return Py_nsISupports::PyObjectFromInterface(cm, NS_GET_IID(nsIComponentManager), PR_FALSE);
|
||||
}
|
||||
|
||||
// No xpcom callable way to get at the registrar, even though the interface
|
||||
// is scriptable.
|
||||
static PyObject *
|
||||
PyXPCOMMethod_GetComponentRegistrar(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
nsCOMPtr<nsIComponentRegistrar> cm;
|
||||
nsresult rv;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
rv = NS_GetComponentRegistrar(getter_AddRefs(cm));
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(rv) )
|
||||
return PyXPCOM_BuildPyException(rv);
|
||||
|
||||
return Py_nsISupports::PyObjectFromInterface(cm, NS_GET_IID(nsISupports), PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
@@ -167,16 +111,16 @@ PyXPCOMMethod_GetServiceManager(PyObject *self, PyObject *args)
|
||||
{
|
||||
if (!PyArg_ParseTuple(args, ""))
|
||||
return NULL;
|
||||
nsIServiceManager* sm;
|
||||
nsCOMPtr<nsIServiceManager> sm;
|
||||
nsresult rv;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
rv = NS_GetServiceManager(&sm);
|
||||
rv = NS_GetServiceManager(getter_AddRefs(sm));
|
||||
Py_END_ALLOW_THREADS;
|
||||
if ( NS_FAILED(rv) )
|
||||
return PyXPCOM_BuildPyException(rv);
|
||||
|
||||
// Return a type based on the IID.
|
||||
return Py_nsISupports::PyObjectFromInterface(sm, NS_GET_IID(nsIServiceManager), PR_FALSE);
|
||||
return Py_nsISupports::PyObjectFromInterface(sm, NS_GET_IID(nsIServiceManager));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
@@ -192,7 +136,7 @@ PyXPCOMMethod_XPTI_GetInterfaceInfoManager(PyObject *self, PyObject *args)
|
||||
/* Return a type based on the IID (with no extra ref) */
|
||||
// Can not auto-wrap the interface info manager as it is critical to
|
||||
// building the support we need for autowrap.
|
||||
return Py_nsISupports::PyObjectFromInterface(im, NS_GET_IID(nsIInterfaceInfoManager), PR_TRUE, PR_FALSE);
|
||||
return Py_nsISupports::PyObjectFromInterface(im, NS_GET_IID(nsIInterfaceInfoManager), PR_FALSE);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
@@ -209,6 +153,11 @@ PyXPCOMMethod_XPTC_InvokeByIndex(PyObject *self, PyObject *args)
|
||||
if (!PyArg_ParseTuple(args, "OiO", &obIS, &index, &obParams))
|
||||
return NULL;
|
||||
|
||||
if (!Py_nsISupports::Check(obIS)) {
|
||||
return PyErr_Format(PyExc_TypeError,
|
||||
"First param must be a native nsISupports wrapper (got %s)",
|
||||
obIS->ob_type->tp_name);
|
||||
}
|
||||
// Ack! We must ask for the "native" interface supported by
|
||||
// the object, not specifically nsISupports, else we may not
|
||||
// back the same pointer (eg, Python, following identity rules,
|
||||
@@ -220,7 +169,7 @@ PyXPCOMMethod_XPTC_InvokeByIndex(PyObject *self, PyObject *args)
|
||||
PR_FALSE))
|
||||
return NULL;
|
||||
|
||||
PyXPCOM_InterfaceVariantHelper arg_helper;
|
||||
PyXPCOM_InterfaceVariantHelper arg_helper((Py_nsISupports *)obIS);
|
||||
if (!arg_helper.Init(obParams))
|
||||
return NULL;
|
||||
|
||||
@@ -249,8 +198,8 @@ PyXPCOMMethod_WrapObject(PyObject *self, PyObject *args)
|
||||
if (!Py_nsIID::IIDFromPyObject(obIID, &iid))
|
||||
return NULL;
|
||||
|
||||
nsISupports *ret = NULL;
|
||||
nsresult r = PyXPCOM_XPTStub::CreateNew(ob, iid, (void **)&ret);
|
||||
nsCOMPtr<nsISupports> ret;
|
||||
nsresult r = PyXPCOM_XPTStub::CreateNew(ob, iid, getter_AddRefs(ret));
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
|
||||
@@ -259,7 +208,7 @@ PyXPCOMMethod_WrapObject(PyObject *self, PyObject *args)
|
||||
AddDefaultGateway(ob, ret); // inject a weak reference to myself into the instance.
|
||||
|
||||
// Now wrap it in an interface.
|
||||
return Py_nsISupports::PyObjectFromInterface(ret, iid, PR_FALSE, bWrapClient);
|
||||
return Py_nsISupports::PyObjectFromInterface(ret, iid, bWrapClient);
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
@@ -327,8 +276,8 @@ PyXPCOMMethod_NS_ShutdownXPCOM(PyObject *self, PyObject *args)
|
||||
nr = NS_ShutdownXPCOM(nsnull);
|
||||
Py_END_ALLOW_THREADS;
|
||||
|
||||
// Don't raise an exception - as we are probably shutting down
|
||||
// and don't really care - just return the status
|
||||
// Dont raise an exception - as we are probably shutting down
|
||||
// and dont really case - just return the status
|
||||
return PyInt_FromLong(nr);
|
||||
}
|
||||
|
||||
@@ -360,7 +309,7 @@ PyXPCOMMethod_GetProxyForObject(PyObject *self, PyObject *args)
|
||||
}
|
||||
|
||||
nsresult rv_proxy;
|
||||
nsISupports *presult = nsnull;
|
||||
nsCOMPtr<nsISupports> presult;
|
||||
Py_BEGIN_ALLOW_THREADS;
|
||||
nsCOMPtr<nsIProxyObjectManager> proxyMgr =
|
||||
do_GetService(kProxyObjectManagerCID, &rv_proxy);
|
||||
@@ -370,7 +319,7 @@ PyXPCOMMethod_GetProxyForObject(PyObject *self, PyObject *args)
|
||||
iid,
|
||||
pob,
|
||||
flags,
|
||||
(void **)&presult);
|
||||
getter_AddRefs(presult));
|
||||
}
|
||||
if (pQueueRelease)
|
||||
pQueueRelease->Release();
|
||||
@@ -378,24 +327,69 @@ PyXPCOMMethod_GetProxyForObject(PyObject *self, PyObject *args)
|
||||
|
||||
PyObject *result;
|
||||
if (NS_SUCCEEDED(rv_proxy) ) {
|
||||
result = Py_nsISupports::PyObjectFromInterface(presult, iid, PR_FALSE);
|
||||
result = Py_nsISupports::PyObjectFromInterface(presult, iid);
|
||||
} else {
|
||||
result = PyXPCOM_BuildPyException(rv_proxy);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyXPCOMMethod_MakeVariant(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *ob;
|
||||
if (!PyArg_ParseTuple(args, "O:MakeVariant", &ob))
|
||||
return NULL;
|
||||
nsCOMPtr<nsIVariant> pVar;
|
||||
nsresult nr = PyObject_AsVariant(ob, getter_AddRefs(pVar));
|
||||
if (NS_FAILED(nr))
|
||||
return PyXPCOM_BuildPyException(nr);
|
||||
if (pVar == nsnull) {
|
||||
NS_ERROR("PyObject_AsVariant worked but returned a NULL ptr!");
|
||||
return PyXPCOM_BuildPyException(NS_ERROR_UNEXPECTED);
|
||||
}
|
||||
return Py_nsISupports::PyObjectFromInterface(pVar, NS_GET_IID(nsIVariant));
|
||||
}
|
||||
|
||||
static PyObject *
|
||||
PyXPCOMMethod_GetVariantValue(PyObject *self, PyObject *args)
|
||||
{
|
||||
PyObject *ob, *obParent = NULL;
|
||||
if (!PyArg_ParseTuple(args, "O|O:GetVariantValue", &ob, &obParent))
|
||||
return NULL;
|
||||
|
||||
nsCOMPtr<nsIVariant> var;
|
||||
if (!Py_nsISupports::InterfaceFromPyObject(ob,
|
||||
NS_GET_IID(nsISupports),
|
||||
getter_AddRefs(var),
|
||||
PR_FALSE))
|
||||
return PyErr_Format(PyExc_ValueError,
|
||||
"Object is not an nsIVariant (got %s)",
|
||||
ob->ob_type->tp_name);
|
||||
|
||||
Py_nsISupports *parent = nsnull;
|
||||
if (obParent && obParent != Py_None) {
|
||||
if (!Py_nsISupports::Check(obParent)) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"Object not an nsISupports wrapper");
|
||||
return NULL;
|
||||
}
|
||||
parent = (Py_nsISupports *)obParent;
|
||||
}
|
||||
return PyObject_FromVariant(parent, var);
|
||||
}
|
||||
|
||||
PyObject *PyGetSpecialDirectory(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *dirname;
|
||||
if (!PyArg_ParseTuple(args, "s:GetSpecialDirectory", &dirname))
|
||||
return NULL;
|
||||
nsIFile *file = NULL;
|
||||
nsresult r = NS_GetSpecialDirectory(dirname, &file);
|
||||
nsCOMPtr<nsIFile> file;
|
||||
nsresult r = NS_GetSpecialDirectory(dirname, getter_AddRefs(file));
|
||||
if ( NS_FAILED(r) )
|
||||
return PyXPCOM_BuildPyException(r);
|
||||
// returned object swallows our reference.
|
||||
return Py_nsISupports::PyObjectFromInterface(file, NS_GET_IID(nsIFile), PR_FALSE);
|
||||
return Py_nsISupports::PyObjectFromInterface(file, NS_GET_IID(nsIFile));
|
||||
}
|
||||
|
||||
PyObject *AllocateBuffer(PyObject *self, PyObject *args)
|
||||
@@ -406,31 +400,38 @@ PyObject *AllocateBuffer(PyObject *self, PyObject *args)
|
||||
return PyBuffer_New(bufSize);
|
||||
}
|
||||
|
||||
PyObject *LogWarning(PyObject *self, PyObject *args)
|
||||
// Writes a message to the console service. This could be done via pure
|
||||
// Python code, but is useful when the logging code is actually the
|
||||
// xpcom .py framework itself (ie, we don't want our logging framework to
|
||||
// call back into the very code generating the log messages!
|
||||
PyObject *LogConsoleMessage(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *msg;
|
||||
if (!PyArg_ParseTuple(args, "s", &msg))
|
||||
return NULL;
|
||||
PyXPCOM_LogWarning("%s", msg);
|
||||
|
||||
nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID);
|
||||
if (consoleService)
|
||||
consoleService->LogStringMessage(NS_ConvertASCIItoUCS2(msg).get());
|
||||
else {
|
||||
// This either means no such service, or in shutdown - hardly worth
|
||||
// the warning, and not worth reporting an error to Python about - its
|
||||
// log handler would just need to catch and ignore it.
|
||||
// And as this is only called by this logging setup, any messages should
|
||||
// still go to stderr or a logfile.
|
||||
NS_WARNING("pyxpcom can't log console message.");
|
||||
}
|
||||
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
PyObject *LogError(PyObject *self, PyObject *args)
|
||||
{
|
||||
char *msg;
|
||||
if (!PyArg_ParseTuple(args, "s", &msg))
|
||||
return NULL;
|
||||
PyXPCOM_LogError("%s", msg);
|
||||
Py_INCREF(Py_None);
|
||||
return Py_None;
|
||||
}
|
||||
|
||||
extern PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args);
|
||||
extern PYXPCOM_EXPORT PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args);
|
||||
|
||||
static struct PyMethodDef xpcom_methods[]=
|
||||
{
|
||||
{"GetComponentManager", PyXPCOMMethod_GetComponentManager, 1},
|
||||
{"GetComponentRegistrar", PyXPCOMMethod_GetComponentRegistrar, 1},
|
||||
{"XPTI_GetInterfaceInfoManager", PyXPCOMMethod_XPTI_GetInterfaceInfoManager, 1},
|
||||
{"XPTC_InvokeByIndex", PyXPCOMMethod_XPTC_InvokeByIndex, 1},
|
||||
{"GetServiceManager", PyXPCOMMethod_GetServiceManager, 1},
|
||||
@@ -445,83 +446,13 @@ static struct PyMethodDef xpcom_methods[]=
|
||||
{"GetProxyForObject", PyXPCOMMethod_GetProxyForObject, 1},
|
||||
{"GetSpecialDirectory", PyGetSpecialDirectory, 1},
|
||||
{"AllocateBuffer", AllocateBuffer, 1},
|
||||
{"LogWarning", LogWarning, 1},
|
||||
{"LogError", LogError, 1},
|
||||
{"LogConsoleMessage", LogConsoleMessage, 1, "Write a message to the xpcom console service"},
|
||||
{"MakeVariant", PyXPCOMMethod_MakeVariant, 1},
|
||||
{"GetVariantValue", PyXPCOMMethod_GetVariantValue, 1},
|
||||
// These should no longer be used - just use the logging.getLogger('pyxpcom')...
|
||||
{ NULL }
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Other helpers/global functions.
|
||||
//
|
||||
PRBool PyXPCOM_Globals_Ensure()
|
||||
{
|
||||
PRBool rc = PR_TRUE;
|
||||
|
||||
#ifndef PYXPCOM_USE_PYGILSTATE
|
||||
PyXPCOM_InterpreterState_Ensure();
|
||||
#endif
|
||||
|
||||
// The exception object - we load it from .py code!
|
||||
if (PyXPCOM_Error == NULL) {
|
||||
rc = PR_FALSE;
|
||||
PyObject *mod = NULL;
|
||||
|
||||
mod = PyImport_ImportModule("xpcom");
|
||||
if (mod!=NULL) {
|
||||
PyXPCOM_Error = PyObject_GetAttrString(mod, "Exception");
|
||||
Py_DECREF(mod);
|
||||
}
|
||||
rc = (PyXPCOM_Error != NULL);
|
||||
}
|
||||
if (!rc)
|
||||
return rc;
|
||||
|
||||
static PRBool bHaveInitXPCOM = PR_FALSE;
|
||||
if (!bHaveInitXPCOM) {
|
||||
nsCOMPtr<nsIThread> thread_check;
|
||||
// xpcom appears to assert if already initialized
|
||||
// Is there an official way to determine this?
|
||||
if (NS_FAILED(nsIThread::GetMainThread(getter_AddRefs(thread_check)))) {
|
||||
// not already initialized.
|
||||
#ifdef XP_WIN
|
||||
// On Windows, we need to locate the Mozilla bin
|
||||
// directory. This by using locating a Moz DLL we depend
|
||||
// on, and assume it lives in that bin dir. Different
|
||||
// moz build types (eg, xulrunner, suite) package
|
||||
// XPCOM itself differently - but all appear to require
|
||||
// nspr4.dll - so this is what we use.
|
||||
char landmark[MAX_PATH+1];
|
||||
HMODULE hmod = GetModuleHandle("nspr4.dll");
|
||||
if (hmod==NULL) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "We dont appear to be linked against nspr4.dll.");
|
||||
return PR_FALSE;
|
||||
}
|
||||
GetModuleFileName(hmod, landmark, sizeof(landmark)/sizeof(landmark[0]));
|
||||
char *end = landmark + (strlen(landmark)-1);
|
||||
while (end > landmark && *end != '\\')
|
||||
end--;
|
||||
if (end > landmark) *end = '\0';
|
||||
|
||||
nsCOMPtr<nsILocalFile> ns_bin_dir;
|
||||
NS_ConvertASCIItoUCS2 strLandmark(landmark);
|
||||
NS_NewLocalFile(strLandmark, PR_FALSE, getter_AddRefs(ns_bin_dir));
|
||||
nsresult rv = NS_InitXPCOM2(nsnull, ns_bin_dir, nsnull);
|
||||
#else
|
||||
// Elsewhere, Mozilla can find it itself (we hope!)
|
||||
nsresult rv = NS_InitXPCOM2(nsnull, nsnull, nsnull);
|
||||
#endif // XP_WIN
|
||||
if (NS_FAILED(rv)) {
|
||||
PyErr_SetString(PyExc_RuntimeError, "The XPCOM subsystem could not be initialized");
|
||||
return PR_FALSE;
|
||||
}
|
||||
}
|
||||
// Even if xpcom was already init, we want to flag it as init!
|
||||
bHaveInitXPCOM = PR_TRUE;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
#define REGISTER_IID(t) { \
|
||||
PyObject *iid_ob = Py_nsIID::PyObjectFromIID(NS_GET_IID(t)); \
|
||||
PyDict_SetItemString(dict, "IID_"#t, iid_ob); \
|
||||
@@ -562,16 +493,9 @@ init_xpcom() {
|
||||
}
|
||||
PyDict_SetItemString(dict, "IIDType", (PyObject *)&Py_nsIID::type);
|
||||
|
||||
// register our entry point.
|
||||
PyObject *obFuncPtr = PyLong_FromVoidPtr((void *)&PyXPCOM_NSGetModule);
|
||||
if (obFuncPtr)
|
||||
PyDict_SetItemString(dict,
|
||||
"_NSGetModule_FuncPtr",
|
||||
obFuncPtr);
|
||||
Py_XDECREF(obFuncPtr);
|
||||
|
||||
REGISTER_IID(nsISupports);
|
||||
REGISTER_IID(nsISupportsCString);
|
||||
REGISTER_IID(nsISupportsString);
|
||||
REGISTER_IID(nsIModule);
|
||||
REGISTER_IID(nsIFactory);
|
||||
REGISTER_IID(nsIWeakReference);
|
||||
@@ -579,20 +503,33 @@ init_xpcom() {
|
||||
REGISTER_IID(nsIClassInfo);
|
||||
REGISTER_IID(nsIServiceManager);
|
||||
REGISTER_IID(nsIComponentRegistrar);
|
||||
|
||||
// Register our custom interfaces.
|
||||
REGISTER_IID(nsIComponentManager);
|
||||
REGISTER_IID(nsIInterfaceInfoManager);
|
||||
REGISTER_IID(nsIEnumerator);
|
||||
REGISTER_IID(nsISimpleEnumerator);
|
||||
REGISTER_IID(nsIInterfaceInfo);
|
||||
REGISTER_IID(nsIInputStream);
|
||||
REGISTER_IID(nsIClassInfo);
|
||||
REGISTER_IID(nsIVariant);
|
||||
// for backward compatibility:
|
||||
REGISTER_IID(nsIComponentManagerObsolete);
|
||||
|
||||
Py_nsISupports::InitType();
|
||||
Py_nsIComponentManager::InitType(dict);
|
||||
Py_nsIInterfaceInfoManager::InitType(dict);
|
||||
Py_nsIEnumerator::InitType(dict);
|
||||
Py_nsISimpleEnumerator::InitType(dict);
|
||||
Py_nsIInterfaceInfo::InitType(dict);
|
||||
Py_nsIInputStream::InitType(dict);
|
||||
Py_nsIClassInfo::InitType(dict);
|
||||
Py_nsIVariant::InitType(dict);
|
||||
|
||||
// No good reason not to expose this impl detail, and tests can use it
|
||||
REGISTER_IID(nsIInternalPython);
|
||||
// We have special support for proxies - may as well add their constants!
|
||||
REGISTER_INT(PROXY_SYNC);
|
||||
REGISTER_INT(PROXY_ASYNC);
|
||||
REGISTER_INT(PROXY_ALWAYS);
|
||||
// Build flags that may be useful.
|
||||
PyObject *ob = PyBool_FromLong(
|
||||
#ifdef NS_DEBUG
|
||||
1
|
||||
#else
|
||||
0
|
||||
#endif
|
||||
);
|
||||
PyDict_SetItemString(dict, "NS_DEBUG", ob);
|
||||
Py_DECREF(ob);
|
||||
}
|
||||
52
mozilla/extensions/python/xpcom/test/Makefile.in
Normal file
52
mozilla/extensions/python/xpcom/test/Makefile.in
Normal file
@@ -0,0 +1,52 @@
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org code
|
||||
#
|
||||
# The Initial Developer of the Original Code is mozilla.org.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2005
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Mark Hammond: author
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH =../../../..
|
||||
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
DIRS = test_component $(NULL)
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
||||
check::
|
||||
@echo "Running Python XPCOM tests"
|
||||
@$(PYTHON)$(PYTHON_DEBUG_SUFFIX) $(srcdir)/regrtest.py
|
||||
@@ -1,8 +0,0 @@
|
||||
test_com_exceptions
|
||||
** Unhandled exception calling 'int8 do_short(in int16, inout int16, out int16, out retval int16);'
|
||||
** Returning nsresult of NS_ERROR_FAILURE
|
||||
** Unhandled exception calling 'int8 do_unsigned_short(in uint16, inout uint16, out uint16, out retval uint16);'
|
||||
** Returning nsresult of NS_ERROR_FAILURE
|
||||
** Unhandled exception calling 'int8 do_unsigned_long_long(in uint64, inout uint64, out uint64, out retval uint64);'
|
||||
** Returning nsresult of NS_ERROR_FAILURE
|
||||
The xpcom exception tests passed
|
||||
@@ -1,7 +0,0 @@
|
||||
test_comfile
|
||||
Open as string test worked.
|
||||
Open as URL test worked.
|
||||
File test using buffers worked.
|
||||
Local file read test worked.
|
||||
Read the correct data.
|
||||
Chunks read the correct data.
|
||||
@@ -1,4 +0,0 @@
|
||||
test_components
|
||||
The interfaces object appeared to work!
|
||||
The classes object appeared to work!
|
||||
The ID function appeared to work!
|
||||
@@ -1,2 +0,0 @@
|
||||
test_isupports_primitives
|
||||
The nsISupports primitive interface tests appeared to work
|
||||
@@ -1 +0,0 @@
|
||||
test_streams
|
||||
@@ -1,4 +0,0 @@
|
||||
test_test_component
|
||||
Testing the Python.TestComponent component
|
||||
The Python test component worked!
|
||||
Javascript could successfully use the Python test component.
|
||||
@@ -1,2 +0,0 @@
|
||||
test_weakreferences
|
||||
Weak-reference tests appear to have worked!
|
||||
@@ -1,4 +1,6 @@
|
||||
# test tools for the pyxpcom
|
||||
# test tools for the pyxpcom bindings
|
||||
from xpcom import _xpcom
|
||||
import unittest
|
||||
|
||||
# export a "getmemusage()" function that returns a useful "bytes used" count
|
||||
# for the current process. Growth in this when doing the same thing over and
|
||||
@@ -70,3 +72,55 @@ if have_pdh:
|
||||
else:
|
||||
def getmemusage():
|
||||
return 0
|
||||
|
||||
# Test runner utilities, including some support for builtin leak tests.
|
||||
class TestLoader(unittest.TestLoader):
|
||||
def loadTestsFromTestCase(self, testCaseClass):
|
||||
"""Return a suite of all tests cases contained in testCaseClass"""
|
||||
leak_tests = []
|
||||
for name in self.getTestCaseNames(testCaseClass):
|
||||
real_test = testCaseClass(name)
|
||||
leak_test = self._getTestWrapper(real_test)
|
||||
leak_tests.append(leak_test)
|
||||
return self.suiteClass(leak_tests)
|
||||
def _getTestWrapper(self, test):
|
||||
# later! see pywin32's win32/test/util.py
|
||||
return test
|
||||
def loadTestsFromModule(self, mod):
|
||||
if hasattr(mod, "suite"):
|
||||
ret = mod.suite()
|
||||
else:
|
||||
ret = unittest.TestLoader.loadTestsFromModule(self, mod)
|
||||
assert ret.countTestCases() > 0, "No tests in %r" % (mod,)
|
||||
return ret
|
||||
def loadTestsFromName(self, name, module=None):
|
||||
test = unittest.TestLoader.loadTestsFromName(self, name, module)
|
||||
if isinstance(test, unittest.TestSuite):
|
||||
pass # hmmm? print "Don't wrap suites yet!", test._tests
|
||||
elif isinstance(test, unittest.TestCase):
|
||||
test = self._getTestWrapper(test)
|
||||
else:
|
||||
print "XXX - what is", test
|
||||
return test
|
||||
|
||||
# A base class our tests should derive from (well, one day it will be)
|
||||
TestCase = unittest.TestCase
|
||||
|
||||
def suite_from_functions(*funcs):
|
||||
suite = unittest.TestSuite()
|
||||
for func in funcs:
|
||||
suite.addTest(unittest.FunctionTestCase(func))
|
||||
return suite
|
||||
|
||||
def testmain(*args, **kw):
|
||||
new_kw = kw.copy()
|
||||
if not new_kw.has_key('testLoader'):
|
||||
new_kw['testLoader'] = TestLoader()
|
||||
try:
|
||||
unittest.main(*args, **new_kw)
|
||||
finally:
|
||||
_xpcom.NS_ShutdownXPCOM()
|
||||
ni = _xpcom._GetInterfaceCount()
|
||||
ng = _xpcom._GetGatewayCount()
|
||||
if ni or ng:
|
||||
print "********* WARNING - Leaving with %d/%d objects alive" % (ni,ng)
|
||||
|
||||
@@ -42,28 +42,50 @@ import os
|
||||
import sys
|
||||
|
||||
import unittest
|
||||
import test.regrtest # The standard Python test suite.
|
||||
|
||||
path = os.path.abspath(os.path.split(sys.argv[0])[0])
|
||||
# This sucks - python now uses "test." - so to worm around this,
|
||||
# we append our test path to the test packages!
|
||||
test.__path__.append(path)
|
||||
# A little magic to create a single "test suite" from all test_ files
|
||||
# in this dir. A single suite makes for prettier output test :)
|
||||
def suite():
|
||||
# Loop over all test_*.py files here
|
||||
try:
|
||||
me = __file__
|
||||
except NameError:
|
||||
me = sys.argv[0]
|
||||
me = os.path.abspath(me)
|
||||
files = os.listdir(os.path.dirname(me))
|
||||
suite = unittest.TestSuite()
|
||||
# XXX - add the others here!
|
||||
#suite.addTest(unittest.FunctionTestCase(import_all))
|
||||
for file in files:
|
||||
base, ext = os.path.splitext(file)
|
||||
if ext=='.py' and os.path.basename(base).startswith("test_"):
|
||||
mod = __import__(base)
|
||||
if hasattr(mod, "suite"):
|
||||
test = mod.suite()
|
||||
else:
|
||||
test = unittest.defaultTestLoader.loadTestsFromModule(mod)
|
||||
suite.addTest(test)
|
||||
return suite
|
||||
|
||||
class CustomLoader(unittest.TestLoader):
|
||||
def loadTestsFromModule(self, module):
|
||||
return suite()
|
||||
|
||||
tests = []
|
||||
for arg in sys.argv[1:]:
|
||||
if arg[0] not in "-/":
|
||||
tests.append(arg)
|
||||
tests = tests or test.regrtest.findtests(path, [])
|
||||
try:
|
||||
# unittest based tests first - hopefully soon this will be the default!
|
||||
if not sys.argv[1:]:
|
||||
for t in "test_misc test_streams".split():
|
||||
m = __import__(t)
|
||||
try:
|
||||
unittest.main(m)
|
||||
except SystemExit:
|
||||
pass
|
||||
test.regrtest.main(tests, path)
|
||||
unittest.TestProgram(testLoader=CustomLoader())(argv=sys.argv)
|
||||
finally:
|
||||
from xpcom import _xpcom
|
||||
_xpcom.NS_ShutdownXPCOM() # To get leak stats and otherwise ensure life is good.
|
||||
ni = _xpcom._GetInterfaceCount()
|
||||
ng = _xpcom._GetGatewayCount()
|
||||
if ni or ng:
|
||||
# The old 'regrtest' that was not based purely on unittest did not
|
||||
# do this check at the end - it relied on each module doing it itself.
|
||||
# Thus, these leaks are not new, just newly noticed :) Likely to be
|
||||
# something silly like module globals.
|
||||
if ni == 6 and ng == 1:
|
||||
print "Sadly, there are 6/1 leaks, but these appear normal and benign"
|
||||
else:
|
||||
print "********* WARNING - Leaving with %d/%d objects alive" % (ni,ng)
|
||||
else:
|
||||
print "yay! Our leaks have all vanished!"
|
||||
|
||||
@@ -36,8 +36,12 @@
|
||||
|
||||
# Test pyxpcom exception.
|
||||
|
||||
from xpcom import components, nsError, ServerException, COMException
|
||||
from xpcom import components, nsError, ServerException, COMException, logger
|
||||
from xpcom.server import WrapObject
|
||||
from pyxpcom_test_tools import testmain
|
||||
|
||||
import unittest
|
||||
import logging
|
||||
|
||||
class PythonFailingComponent:
|
||||
# Re-use the test interface for this test.
|
||||
@@ -75,29 +79,46 @@ class PythonFailingComponent:
|
||||
# Report of a crash in this case - test it!
|
||||
raise ServerException, "A bad exception param"
|
||||
|
||||
def _testit(expected_errno, func, *args):
|
||||
try:
|
||||
apply(func, args)
|
||||
except COMException, what:
|
||||
if what.errno != expected_errno:
|
||||
raise
|
||||
class TestHandler(logging.Handler):
|
||||
def __init__(self, level=logging.ERROR): # only counting error records
|
||||
logging.Handler.__init__(self, level)
|
||||
self.records = []
|
||||
|
||||
def reset(self):
|
||||
self.records = []
|
||||
|
||||
def test():
|
||||
# For the benefit of the test suite, we print some reassuring messages.
|
||||
import sys
|
||||
sys.__stderr__.write("***** NOTE: Three tracebacks below this is normal\n")
|
||||
ob = WrapObject( PythonFailingComponent(), components.interfaces.nsIPythonTestInterfaceExtra)
|
||||
_testit(nsError.NS_ERROR_FAILURE, ob.do_boolean, 0, 0)
|
||||
_testit(nsError.NS_ERROR_NOT_IMPLEMENTED, ob.do_octet, 0, 0)
|
||||
_testit(nsError.NS_ERROR_FAILURE, ob.do_short, 0, 0)
|
||||
_testit(nsError.NS_ERROR_FAILURE, ob.do_unsigned_short, 0, 0)
|
||||
_testit(nsError.NS_ERROR_FAILURE, ob.do_long, 0, 0)
|
||||
_testit(nsError.NS_ERROR_NOT_IMPLEMENTED, ob.do_unsigned_long, 0, 0)
|
||||
_testit(nsError.NS_ERROR_NOT_IMPLEMENTED, ob.do_long_long, 0, 0)
|
||||
_testit(nsError.NS_ERROR_FAILURE, ob.do_unsigned_long_long, 0, 0)
|
||||
print "The xpcom exception tests passed"
|
||||
# For the benefit of the test suite, some more reassuring messages.
|
||||
sys.__stderr__.write("***** NOTE: Three tracebacks printed above this is normal\n")
|
||||
sys.__stderr__.write("***** It is testing the Python XPCOM Exception semantics\n")
|
||||
def handle(self, record):
|
||||
self.records.append(record)
|
||||
|
||||
test()
|
||||
class ExceptionTests(unittest.TestCase):
|
||||
|
||||
def _testit(self, expected_errno, num_tracebacks, func, *args):
|
||||
|
||||
# Screw with the logger
|
||||
old_handlers = logger.handlers
|
||||
test_handler = TestHandler()
|
||||
logger.handlers = [test_handler]
|
||||
|
||||
try:
|
||||
try:
|
||||
apply(func, args)
|
||||
except COMException, what:
|
||||
if what.errno != expected_errno:
|
||||
raise
|
||||
finally:
|
||||
logger.handlers = old_handlers
|
||||
self.failUnlessEqual(num_tracebacks, len(test_handler.records))
|
||||
|
||||
def testEmAll(self):
|
||||
ob = WrapObject( PythonFailingComponent(), components.interfaces.nsIPythonTestInterfaceExtra)
|
||||
self._testit(nsError.NS_ERROR_FAILURE, 0, ob.do_boolean, 0, 0)
|
||||
self._testit(nsError.NS_ERROR_NOT_IMPLEMENTED, 0, ob.do_octet, 0, 0)
|
||||
self._testit(nsError.NS_ERROR_FAILURE, 1, ob.do_short, 0, 0)
|
||||
self._testit(nsError.NS_ERROR_FAILURE, 1, ob.do_unsigned_short, 0, 0)
|
||||
self._testit(nsError.NS_ERROR_FAILURE, 0, ob.do_long, 0, 0)
|
||||
self._testit(nsError.NS_ERROR_NOT_IMPLEMENTED, 0, ob.do_unsigned_long, 0, 0)
|
||||
self._testit(nsError.NS_ERROR_NOT_IMPLEMENTED, 0, ob.do_long_long, 0, 0)
|
||||
self._testit(nsError.NS_ERROR_FAILURE, 1, ob.do_unsigned_long_long, 0, 0)
|
||||
|
||||
if __name__=='__main__':
|
||||
testmain()
|
||||
|
||||
@@ -36,6 +36,14 @@
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
"""Test the xpcom.file module."""
|
||||
# Called "test_comfile" as Python has a standard test called test_file :-(
|
||||
from pyxpcom_test_tools import suite_from_functions, testmain
|
||||
|
||||
import xpcom.file
|
||||
xpcom.file._TestAll()
|
||||
|
||||
# Make this test run under our std test suite
|
||||
def suite():
|
||||
return suite_from_functions(xpcom.file._TestAll)
|
||||
|
||||
if __name__=='__main__':
|
||||
testmain()
|
||||
|
||||
|
||||
@@ -212,6 +212,7 @@ interface nsIPythonTestInterfaceExtra : nsIPythonTestInterface
|
||||
void AppendArray(inout PRUint32 count, [array, size_is(count)]in PRInt32 array1, [array, size_is(count)]inout PRInt32 array2);
|
||||
void AppendVariant(in nsIVariant variant, inout nsIVariant result);
|
||||
nsIVariant CopyVariant(in nsIVariant variant);
|
||||
nsIVariant SumVariants(in PRUint32 incount, [array, size_is(incount)]in nsIVariant variants);
|
||||
};
|
||||
|
||||
// DOM String support is a "recent" (01/2001) addition to XPCOM. These test
|
||||
|
||||
@@ -365,6 +365,14 @@ class PythonTestComponent:
|
||||
def CopyVariant(self, invar):
|
||||
return invar
|
||||
|
||||
def SumVariants(self, variants):
|
||||
if len(variants) == 0:
|
||||
return None
|
||||
result = variants[0]
|
||||
for v in variants[1:]:
|
||||
result += v
|
||||
return result
|
||||
|
||||
# Some tests for the "new" (Feb-2001) DOMString type.
|
||||
def GetDOMStringResult( self, length ):
|
||||
# Result: DOMString &
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"""
|
||||
|
||||
import xpcom.components
|
||||
from pyxpcom_test_tools import suite_from_functions, testmain
|
||||
|
||||
if not __debug__:
|
||||
raise RuntimeError, "This test uses assert, so must be run in debug mode"
|
||||
@@ -63,9 +64,7 @@ def test_interfaces():
|
||||
assert len(xpcom.components.interfaces.keys()) == len(xpcom.components.interfaces.values()) == \
|
||||
len(xpcom.components.interfaces.items()) == len(xpcom.components.interfaces) == \
|
||||
num_fetched, "The collection lengths were wrong"
|
||||
if num_nsisupports != 1:
|
||||
print "Didn't find exactly 1 nsiSupports!"
|
||||
print "The interfaces object appeared to work!"
|
||||
assert num_nsisupports == 1, "Didn't find exactly 1 nsiSupports!"
|
||||
|
||||
def test_classes():
|
||||
# Need a well-known contractID here?
|
||||
@@ -81,8 +80,7 @@ def test_classes():
|
||||
for name, klass in xpcom.components.classes.items():
|
||||
num_fetched = num_fetched + 1
|
||||
if name == prog_id:
|
||||
if klass.clsid != clsid:
|
||||
print "Eeek - didn't get the correct IID - got", klass.clsid
|
||||
assert klass.clsid == clsid, "Eeek - didn't get the correct IID - got %s" %klass.clsid
|
||||
num_mine = num_mine + 1
|
||||
|
||||
# xpcom appears to add charset info to the contractid!?
|
||||
@@ -98,15 +96,14 @@ def test_classes():
|
||||
raise RuntimeError, "Didn't get any classes!!!"
|
||||
if num_mine != 1:
|
||||
raise RuntimeError, "Didn't find exactly 1 of my contractid! (%d)" % (num_mine,)
|
||||
print "The classes object appeared to work!"
|
||||
|
||||
def test_id():
|
||||
id = xpcom.components.ID(str(xpcom._xpcom.IID_nsISupports))
|
||||
assert id == xpcom._xpcom.IID_nsISupports
|
||||
print "The ID function appeared to work!"
|
||||
|
||||
# Make this test run under our std test suite
|
||||
def suite():
|
||||
return suite_from_functions(test_interfaces, test_classes, test_id)
|
||||
|
||||
# regrtest doesn't like if __name__=='__main__' blocks - it fails when running as a test!
|
||||
test_interfaces()
|
||||
test_classes()
|
||||
test_id()
|
||||
if __name__=='__main__':
|
||||
testmain()
|
||||
|
||||
@@ -41,10 +41,13 @@
|
||||
# only if our class doesn't provide explicit support.
|
||||
|
||||
from xpcom import components
|
||||
from xpcom import primitives
|
||||
import xpcom.server, xpcom.client
|
||||
from pyxpcom_test_tools import testmain
|
||||
import unittest
|
||||
|
||||
class NoSupportsString:
|
||||
_com_interfaces_ = [components.interfaces.nsISupports]
|
||||
pass
|
||||
|
||||
class ImplicitSupportsString:
|
||||
_com_interfaces_ = [components.interfaces.nsISupports]
|
||||
@@ -52,13 +55,36 @@ class ImplicitSupportsString:
|
||||
return "<MyImplicitStrObject>"
|
||||
|
||||
class ExplicitSupportsString:
|
||||
_com_interfaces_ = [components.interfaces.nsISupports, components.interfaces.nsISupportsCString]
|
||||
_com_interfaces_ = [components.interfaces.nsISupportsPrimitive,
|
||||
components.interfaces.nsISupportsCString]
|
||||
type = components.interfaces.nsISupportsPrimitive.TYPE_CSTRING
|
||||
test_data = "<MyExplicitStrObject>"
|
||||
# __str__ will be ignored by XPCOM, as we have _explicit_ support.
|
||||
def __str__(self):
|
||||
return "<MyImplicitStrObject>"
|
||||
# This is the one that will be used.
|
||||
# These are the ones that will be used.
|
||||
def get_data(self):
|
||||
return self.test_data
|
||||
def toString(self):
|
||||
return "<MyExplicitStrObject>"
|
||||
return self.test_data
|
||||
|
||||
class ImplicitSupportsUnicode:
|
||||
_com_interfaces_ = [components.interfaces.nsISupports]
|
||||
test_data = u"Copyright \xa9 the initial developer"
|
||||
def __unicode__(self):
|
||||
# An extended character in unicode tests can't hurt!
|
||||
return self.test_data
|
||||
|
||||
class ExplicitSupportsUnicode:
|
||||
_com_interfaces_ = [components.interfaces.nsISupportsPrimitive,
|
||||
components.interfaces.nsISupportsString]
|
||||
type = components.interfaces.nsISupportsPrimitive.TYPE_STRING
|
||||
# __unicode__ will be ignored by XPCOM, as we have _explicit_ support.
|
||||
test_data = u"Copyright \xa9 the initial developer"
|
||||
def __unicode__(self):
|
||||
return self.test_data
|
||||
def get_data(self):
|
||||
return self.test_data
|
||||
|
||||
class ImplicitSupportsInt:
|
||||
_com_interfaces_ = [components.interfaces.nsISupports]
|
||||
@@ -66,7 +92,9 @@ class ImplicitSupportsInt:
|
||||
return 99
|
||||
|
||||
class ExplicitSupportsInt:
|
||||
_com_interfaces_ = [components.interfaces.nsISupportsPRInt32]
|
||||
_com_interfaces_ = [components.interfaces.nsISupportsPrimitive,
|
||||
components.interfaces.nsISupportsPRInt32]
|
||||
type = components.interfaces.nsISupportsPrimitive.TYPE_PRINT32
|
||||
def get_data(self):
|
||||
return 99
|
||||
|
||||
@@ -76,12 +104,16 @@ class ImplicitSupportsLong:
|
||||
return 99L
|
||||
|
||||
class ExplicitSupportsLong:
|
||||
_com_interfaces_ = [components.interfaces.nsISupportsPRInt64]
|
||||
_com_interfaces_ = [components.interfaces.nsISupportsPrimitive,
|
||||
components.interfaces.nsISupportsPRInt64]
|
||||
type = components.interfaces.nsISupportsPrimitive.TYPE_PRINT64
|
||||
def get_data(self):
|
||||
return 99
|
||||
|
||||
class ExplicitSupportsFloat:
|
||||
_com_interfaces_ = [components.interfaces.nsISupportsDouble]
|
||||
_com_interfaces_ = [components.interfaces.nsISupportsPrimitive,
|
||||
components.interfaces.nsISupportsDouble]
|
||||
type = components.interfaces.nsISupportsPrimitive.TYPE_DOUBLE
|
||||
def get_data(self):
|
||||
return 99.99
|
||||
|
||||
@@ -90,61 +122,86 @@ class ImplicitSupportsFloat:
|
||||
def __float__(self):
|
||||
return 99.99
|
||||
|
||||
def test():
|
||||
import xpcom.server, xpcom.client
|
||||
ob = xpcom.server.WrapObject( NoSupportsString(), components.interfaces.nsISupports)
|
||||
if not str(ob).startswith("<XPCOM "):
|
||||
raise RuntimeError, "Wrong str() value: %s" % (ob,)
|
||||
class PrimitivesTestCase(unittest.TestCase):
|
||||
def testNoSupports(self):
|
||||
ob = xpcom.server.WrapObject( NoSupportsString(), components.interfaces.nsISupports)
|
||||
if not str(ob).startswith("<XPCOM "):
|
||||
raise RuntimeError, "Wrong str() value: %s" % (ob,)
|
||||
|
||||
ob = xpcom.server.WrapObject( ImplicitSupportsString(), components.interfaces.nsISupports)
|
||||
if str(ob) != "<MyImplicitStrObject>":
|
||||
raise RuntimeError, "Wrong str() value: %s" % (ob,)
|
||||
def testImplicitString(self):
|
||||
ob = xpcom.server.WrapObject( ImplicitSupportsString(), components.interfaces.nsISupports)
|
||||
self.failUnlessEqual(str(ob), "<MyImplicitStrObject>")
|
||||
|
||||
ob = xpcom.server.WrapObject( ExplicitSupportsString(), components.interfaces.nsISupports)
|
||||
if str(ob) != "<MyExplicitStrObject>":
|
||||
raise RuntimeError, "Wrong str() value: %s" % (ob,)
|
||||
def testExplicitString(self):
|
||||
ob = xpcom.server.WrapObject( ExplicitSupportsString(), components.interfaces.nsISupports)
|
||||
self.failUnlessEqual(str(ob), "<MyExplicitStrObject>")
|
||||
|
||||
# Try our conversions.
|
||||
try:
|
||||
int(ob)
|
||||
raise RuntimeError, "Expected to get a ValueError converting this COM object to an int"
|
||||
except ValueError:
|
||||
pass
|
||||
ob = xpcom.server.WrapObject( ExplicitSupportsInt(), components.interfaces.nsISupports)
|
||||
if int(ob) != 99:
|
||||
raise RuntimeError, "Bad value: %s" % (int(ob),)
|
||||
if float(ob) != 99.0:
|
||||
raise RuntimeError, "Bad value: %s" % (float(ob),)
|
||||
def testImplicitUnicode(self):
|
||||
ob = xpcom.server.WrapObject( ImplicitSupportsUnicode(), components.interfaces.nsISupports)
|
||||
self.failUnlessEqual(unicode(ob), ImplicitSupportsUnicode.test_data)
|
||||
|
||||
ob = xpcom.server.WrapObject( ImplicitSupportsInt(), components.interfaces.nsISupports)
|
||||
if int(ob) != 99:
|
||||
raise RuntimeError, "Bad value: %s" % (int(ob),)
|
||||
if float(ob) != 99.0:
|
||||
raise RuntimeError, "Bad value: %s" % (float(ob),)
|
||||
def testExplicitUnicode(self):
|
||||
ob = xpcom.server.WrapObject( ExplicitSupportsUnicode(), components.interfaces.nsISupports)
|
||||
self.failUnlessEqual(unicode(ob), ExplicitSupportsUnicode.test_data)
|
||||
|
||||
ob = xpcom.server.WrapObject( ExplicitSupportsLong(), components.interfaces.nsISupports)
|
||||
if long(ob) != 99 or not repr(long(ob)).endswith("L"):
|
||||
raise RuntimeError, "Bad value: %s" % (repr(long(ob)),)
|
||||
if float(ob) != 99.0:
|
||||
raise RuntimeError, "Bad value: %s" % (float(ob),)
|
||||
def testConvertInt(self):
|
||||
# Try our conversions.
|
||||
ob = xpcom.server.WrapObject( ExplicitSupportsString(), components.interfaces.nsISupports)
|
||||
self.failUnlessRaises( ValueError, int, ob)
|
||||
|
||||
ob = xpcom.server.WrapObject( ImplicitSupportsLong(), components.interfaces.nsISupports)
|
||||
if long(ob) != 99 or not repr(long(ob)).endswith("L"):
|
||||
raise RuntimeError, "Bad value: %s" % (repr(long(ob)),)
|
||||
if float(ob) != 99.0:
|
||||
raise RuntimeError, "Bad value: %s" % (float(ob),)
|
||||
def testExplicitInt(self):
|
||||
ob = xpcom.server.WrapObject( ExplicitSupportsInt(), components.interfaces.nsISupports)
|
||||
self.failUnlessAlmostEqual(float(ob), 99.0)
|
||||
self.failUnlessEqual(int(ob), 99)
|
||||
|
||||
ob = xpcom.server.WrapObject( ExplicitSupportsFloat(), components.interfaces.nsISupports)
|
||||
if float(ob) != 99.99:
|
||||
raise RuntimeError, "Bad value: %s" % (float(ob),)
|
||||
if int(ob) != 99:
|
||||
raise RuntimeError, "Bad value: %s" % (int(ob),)
|
||||
def testImplicitInt(self):
|
||||
ob = xpcom.server.WrapObject( ImplicitSupportsInt(), components.interfaces.nsISupports)
|
||||
self.failUnlessAlmostEqual(float(ob), 99.0)
|
||||
self.failUnlessEqual(int(ob), 99)
|
||||
|
||||
ob = xpcom.server.WrapObject( ImplicitSupportsFloat(), components.interfaces.nsISupports)
|
||||
if float(ob) != 99.99:
|
||||
raise RuntimeError, "Bad value: %s" % (float(ob),)
|
||||
if int(ob) != 99:
|
||||
raise RuntimeError, "Bad value: %s" % (int(ob),)
|
||||
def testExplicitLong(self):
|
||||
ob = xpcom.server.WrapObject( ExplicitSupportsLong(), components.interfaces.nsISupports)
|
||||
if long(ob) != 99 or not repr(long(ob)).endswith("L"):
|
||||
raise RuntimeError, "Bad value: %s" % (repr(long(ob)),)
|
||||
self.failUnlessAlmostEqual(float(ob), 99.0)
|
||||
|
||||
print "The nsISupports primitive interface tests appeared to work"
|
||||
test()
|
||||
def testImplicitLong(self):
|
||||
ob = xpcom.server.WrapObject( ImplicitSupportsLong(), components.interfaces.nsISupports)
|
||||
if long(ob) != 99 or not repr(long(ob)).endswith("L"):
|
||||
raise RuntimeError, "Bad value: %s" % (repr(long(ob)),)
|
||||
self.failUnlessAlmostEqual(float(ob), 99.0)
|
||||
|
||||
def testExplicitFloat(self):
|
||||
ob = xpcom.server.WrapObject( ExplicitSupportsFloat(), components.interfaces.nsISupports)
|
||||
self.failUnlessEqual(float(ob), 99.99)
|
||||
self.failUnlessEqual(int(ob), 99)
|
||||
|
||||
def testImplicitFloat(self):
|
||||
ob = xpcom.server.WrapObject( ImplicitSupportsFloat(), components.interfaces.nsISupports)
|
||||
self.failUnlessEqual(float(ob), 99.99)
|
||||
self.failUnlessEqual(int(ob), 99)
|
||||
|
||||
class PrimitivesModuleTestCase(unittest.TestCase):
|
||||
def testExplicitString(self):
|
||||
ob = xpcom.server.WrapObject( ExplicitSupportsString(), components.interfaces.nsISupports)
|
||||
self.failUnlessEqual(primitives.GetPrimitive(ob), "<MyExplicitStrObject>")
|
||||
|
||||
def testExplicitUnicode(self):
|
||||
ob = xpcom.server.WrapObject( ExplicitSupportsUnicode(), components.interfaces.nsISupports)
|
||||
self.failUnlessEqual(primitives.GetPrimitive(ob), ExplicitSupportsUnicode.test_data)
|
||||
self.failUnlessEqual(type(primitives.GetPrimitive(ob)), unicode)
|
||||
|
||||
def testExplicitInt(self):
|
||||
ob = xpcom.server.WrapObject( ExplicitSupportsInt(), components.interfaces.nsISupports)
|
||||
self.failUnlessEqual(primitives.GetPrimitive(ob), 99)
|
||||
|
||||
def testExplicitLong(self):
|
||||
ob = xpcom.server.WrapObject( ExplicitSupportsLong(), components.interfaces.nsISupports)
|
||||
self.failUnlessEqual(primitives.GetPrimitive(ob), 99)
|
||||
|
||||
def testExplicitFloat(self):
|
||||
ob = xpcom.server.WrapObject( ExplicitSupportsFloat(), components.interfaces.nsISupports)
|
||||
self.failUnlessEqual(primitives.GetPrimitive(ob), 99.99)
|
||||
|
||||
if __name__=='__main__':
|
||||
testmain()
|
||||
|
||||
@@ -41,6 +41,7 @@ import xpcom.server
|
||||
import xpcom._xpcom
|
||||
import xpcom.components
|
||||
import string
|
||||
from pyxpcom_test_tools import testmain
|
||||
|
||||
import unittest
|
||||
|
||||
@@ -223,10 +224,13 @@ class TestUnwrap(unittest.TestCase):
|
||||
return
|
||||
self.failUnlessRaises(ValueError, xpcom.server.UnwrapObject, ob)
|
||||
|
||||
class TestNonScriptable(unittest.TestCase):
|
||||
def testQI(self):
|
||||
# Test we can QI for a non-scriptable interface. We can't *do* much
|
||||
# with it (other than pass it on), but we should still work and get
|
||||
# a basic wrapper.
|
||||
ob = xpcom.components.classes["Python.TestComponent"].createInstance()
|
||||
ob = ob.queryInterface(xpcom._xpcom.IID_nsIInternalPython)
|
||||
|
||||
if __name__=='__main__':
|
||||
unittest.main()
|
||||
xpcom._xpcom.NS_ShutdownXPCOM()
|
||||
ni = xpcom._xpcom._GetInterfaceCount()
|
||||
ng = xpcom._xpcom._GetGatewayCount()
|
||||
if ni or ng:
|
||||
print "********* WARNING - Leaving with %d/%d objects alive" % (ni,ng)
|
||||
testmain()
|
||||
|
||||
@@ -39,6 +39,7 @@ import xpcom
|
||||
from xpcom import _xpcom, components, COMException, ServerException, nsError
|
||||
from StringIO import StringIO
|
||||
import unittest
|
||||
from pyxpcom_test_tools import testmain
|
||||
|
||||
test_data = "abcdefeghijklmnopqrstuvwxyz"
|
||||
|
||||
@@ -92,4 +93,4 @@ class StreamTests(unittest.TestCase):
|
||||
# stream observer mechanism has changed - we should test that.
|
||||
|
||||
if __name__=='__main__':
|
||||
unittest.main()
|
||||
testmain()
|
||||
|
||||
@@ -130,5 +130,9 @@ v2[3] = 6;
|
||||
if (c.SumArrays(v.length, v, v2) != 21)
|
||||
throw("Could not sum an array of integers!");
|
||||
|
||||
var count = new Object();
|
||||
count.value = 0;
|
||||
var out = [];
|
||||
c.DoubleStringArray(count, out);
|
||||
|
||||
print("javascript successfully tested the Python test component.");
|
||||
|
||||
@@ -40,6 +40,8 @@ import xpcom.components
|
||||
import xpcom._xpcom
|
||||
import xpcom.nsError
|
||||
|
||||
MakeVariant = xpcom._xpcom.MakeVariant
|
||||
|
||||
try:
|
||||
import gc
|
||||
except ImportError:
|
||||
@@ -406,11 +408,19 @@ def test_derived_interface(c, test_flat = 0):
|
||||
test_method(c.CopyVariant, (("foo","bar"),), ["foo", "bar"])
|
||||
test_method(c.CopyVariant, ((component_iid,component_iid),), [component_iid,component_iid])
|
||||
test_method(c.CopyVariant, ((c,c),), [c,c])
|
||||
sup = c.queryInterface(xpcom.components.interfaces.nsISupports)._comobj_
|
||||
test_method(c.CopyVariant, ((sup, sup),), [sup,sup])
|
||||
test_method(c.AppendVariant, (1,2), 3)
|
||||
test_method(c.AppendVariant, ((1,2),(3,4)), 10)
|
||||
test_method(c.AppendVariant, ("bar", "foo"), "foobar")
|
||||
test_method(c.AppendVariant, (None, None), None)
|
||||
|
||||
test_method(c.SumVariants, ([],), None)
|
||||
# Array's dont expose their interface, so we are unable to auto-wrap
|
||||
# variant arrays, as they aren't aware if the IID of the array
|
||||
test_method(c.SumVariants, ([MakeVariant(1),MakeVariant(2),MakeVariant(3)],), 6)
|
||||
test_method(c.SumVariants, ([MakeVariant('foo'), MakeVariant('bar')],), 'foobar')
|
||||
|
||||
if not test_flat:
|
||||
c = c.queryInterface(xpcom.components.interfaces.nsIPythonTestInterfaceDOMStrings)
|
||||
# NULL DOM strings don't work yet.
|
||||
@@ -491,29 +501,20 @@ def test_from_js():
|
||||
raise RuntimeError, "Can not find '%s'" % (fname,)
|
||||
# Note we _dont_ pump the test output out, as debug "xpcshell" spews
|
||||
# extra debug info that will cause our output comparison to fail.
|
||||
try:
|
||||
data = os.popen('xpcshell "' + fname + '"').readlines()
|
||||
good = 0
|
||||
for line in data:
|
||||
if line.strip() == "javascript successfully tested the Python test component.":
|
||||
good = 1
|
||||
if good:
|
||||
print "Javascript could successfully use the Python test component."
|
||||
else:
|
||||
print "** The javascript test appeared to fail! Test output follows **"
|
||||
print "".join(data)
|
||||
print "** End of javascript test output **"
|
||||
|
||||
except os.error, why:
|
||||
print "Error executing the javascript test program:", why
|
||||
|
||||
data = os.popen('xpcshell "' + fname + '"').readlines()
|
||||
good = 0
|
||||
for line in data:
|
||||
if line.strip() == "javascript successfully tested the Python test component.":
|
||||
good = 1
|
||||
if not good:
|
||||
print "** The javascript test appeared to fail! Test output follows **"
|
||||
print "".join(data)
|
||||
print "** End of javascript test output **"
|
||||
raise RuntimeError, "test failed"
|
||||
|
||||
def doit(num_loops = -1):
|
||||
if "-v" in sys.argv: # Hack the verbose flag for the server
|
||||
xpcom.verbose = 1
|
||||
# Do the test lots of times - can help shake-out ref-count bugs.
|
||||
print "Testing the Python.TestComponent component"
|
||||
if num_loops == -1: num_loops = 10
|
||||
if num_loops == -1: num_loops = 5
|
||||
for i in xrange(num_loops):
|
||||
test_all()
|
||||
|
||||
@@ -535,38 +536,40 @@ def doit(num_loops = -1):
|
||||
# Sometimes we get spurious counts off by 1 or 2.
|
||||
# This can't indicate a real leak, as we have looped
|
||||
# more than twice!
|
||||
if abs(lost)>2:
|
||||
if abs(lost)>3: # 2 or 3 :)
|
||||
print "*** Lost %d references" % (lost,)
|
||||
|
||||
# sleep to allow the OS to recover
|
||||
time.sleep(1)
|
||||
mem_lost = getmemusage() - mem_usage
|
||||
# working set size is fickle, and when we were leaking strings, this test
|
||||
# would report a leak of 100MB. So we allow a 2MB buffer - but even this
|
||||
# would report a leak of 100MB. So we allow a 3MB buffer - but even this
|
||||
# may still occasionally report spurious warnings. If you are really
|
||||
# worried, bump the counter to a huge value, and if there is a leak it will
|
||||
# show.
|
||||
if mem_lost > 2000000:
|
||||
if mem_lost > 3000000:
|
||||
print "*** Lost %.6f MB of memory" % (mem_lost/1000000.0,)
|
||||
|
||||
if num_errors:
|
||||
print "There were", num_errors, "errors testing the Python component :-("
|
||||
else:
|
||||
print "The Python test component worked!"
|
||||
assert num_errors==0, "There were %d errors testing the Python component" % (num_errors,)
|
||||
|
||||
# regrtest doesn't like if __name__=='__main__' blocks - it fails when running as a test!
|
||||
num_iters = -1
|
||||
if __name__=='__main__' and len(sys.argv) > 1:
|
||||
num_iters = int(sys.argv[1])
|
||||
|
||||
doit(num_iters)
|
||||
test_from_js()
|
||||
def suite():
|
||||
from pyxpcom_test_tools import suite_from_functions
|
||||
return suite_from_functions(doit, test_from_js)
|
||||
|
||||
if __name__=='__main__':
|
||||
# But we can only do this if _not_ testing - otherwise we
|
||||
# screw up any tests that want to run later.
|
||||
num_iters = 10 # times times is *lots* - we do a fair bit of work!
|
||||
if __name__=='__main__' and len(sys.argv) > 1:
|
||||
num_iters = int(sys.argv[1])
|
||||
|
||||
if "-v" in sys.argv: # Hack the verbose flag for the server
|
||||
xpcom.verbose = 1
|
||||
|
||||
print "Testing the Python.TestComponent component"
|
||||
doit(num_iters)
|
||||
print "The Python test component worked."
|
||||
test_from_js()
|
||||
print "JS successfully used our Python test component."
|
||||
xpcom._xpcom.NS_ShutdownXPCOM()
|
||||
ni = xpcom._xpcom._GetInterfaceCount()
|
||||
ng = xpcom._xpcom._GetGatewayCount()
|
||||
if ni or ng:
|
||||
print "********* WARNING - Leaving with %d/%d objects alive" % (ni,ng)
|
||||
print "test completed with %d interfaces and %d objects." % (ni, ng)
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
# test_weakreferences.py - Test our weak reference implementation.
|
||||
from xpcom import components, _xpcom
|
||||
import xpcom.server, xpcom.client
|
||||
from pyxpcom_test_tools import suite_from_functions, testmain
|
||||
|
||||
try:
|
||||
from sys import gettotalrefcount
|
||||
@@ -104,13 +105,10 @@ def test_refcount(num_loops=-1):
|
||||
# more than twice!
|
||||
if abs(lost)>2:
|
||||
print "*** Lost %d references" % (lost,)
|
||||
|
||||
test_refcount()
|
||||
|
||||
print "Weak-reference tests appear to have worked!"
|
||||
# Make this test run under our std test suite
|
||||
def suite():
|
||||
return suite_from_functions(test_refcount)
|
||||
|
||||
if __name__=='__main__':
|
||||
_xpcom.NS_ShutdownXPCOM()
|
||||
ni = xpcom._xpcom._GetInterfaceCount()
|
||||
ng = xpcom._xpcom._GetGatewayCount()
|
||||
if ni or ng:
|
||||
print "********* WARNING - Leaving with %d/%d objects alive" % (ni,ng)
|
||||
testmain()
|
||||
|
||||
@@ -36,32 +36,33 @@
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
# regxpcom.py - basically the standard regxpcom.cpp ported to Python.
|
||||
# In general, you should use regxpcom.exe instead of this.
|
||||
|
||||
from xpcom import components, _xpcom
|
||||
from xpcom.client import Component
|
||||
import sys
|
||||
import os
|
||||
|
||||
registrar = Component(_xpcom.GetComponentRegistrar(),
|
||||
components.interfaces.nsIComponentRegistrar)
|
||||
|
||||
def ProcessArgs(args):
|
||||
|
||||
unregister = 0
|
||||
for arg in args:
|
||||
spec = components.classes['@mozilla.org/file/local;1'].createInstance()
|
||||
spec = spec.QueryInterface(components.interfaces.nsILocalFile)
|
||||
spec.initWithPath(os.path.abspath(arg))
|
||||
if arg == "-u":
|
||||
unregister = 1
|
||||
registrar.autoUnregister(spec)
|
||||
print "Successfully unregistered", spec.path
|
||||
else:
|
||||
spec = components.classes['@mozilla.org/file/local;1'].createInstance()
|
||||
spec = spec.QueryInterface(components.interfaces.nsILocalFile)
|
||||
spec.initWithPath(os.path.abspath(arg))
|
||||
if unregister:
|
||||
components.manager.autoUnregisterComponent( components.manager.NS_Startup, spec)
|
||||
print "Successfully unregistered", spec.path
|
||||
else:
|
||||
components.manager.autoRegisterComponent( components.manager.NS_Startup, spec)
|
||||
print "Successfully registered", spec.path
|
||||
unregister = 0
|
||||
registrar.autoRegister(spec)
|
||||
print "Successfully registered", spec.path
|
||||
|
||||
import xpcom
|
||||
if len(sys.argv) < 2:
|
||||
components.manager.autoRegister( components.manager.NS_Startup, None)
|
||||
registrar.autoRegister( None)
|
||||
else:
|
||||
ProcessArgs(sys.argv[1:])
|
||||
|
||||
_xpcom.NS_ShutdownXPCOM()
|
||||
#_xpcom.NS_ShutdownXPCOM()
|
||||
|
||||
@@ -76,15 +76,10 @@ from xpcom_consts import *
|
||||
class Interface:
|
||||
def __init__(self, iid):
|
||||
iim = xpcom._xpcom.XPTI_GetInterfaceInfoManager()
|
||||
try:
|
||||
if hasattr(iid, "upper"): # Is it a stringy thing.
|
||||
item = iim.GetInfoForName(iid)
|
||||
else:
|
||||
item = iim.GetInfoForIID(iid)
|
||||
except xpcom.COMException:
|
||||
name = getattr(iid, "name", str(iid))
|
||||
print "Failed to get info for IID '%s'" % (name,)
|
||||
raise
|
||||
if hasattr(iid, "upper"): # Is it a stringy thing.
|
||||
item = iim.GetInfoForName(iid)
|
||||
else:
|
||||
item = iim.GetInfoForIID(iid)
|
||||
self.interface_info = item
|
||||
self.namespace = "" # where does this come from?
|
||||
self.methods = Methods(item)
|
||||
|
||||
Reference in New Issue
Block a user