diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 16:49:04 +0000 |
commit | 16f504a9dca3fe3b70568f67b7d41241ae485288 (patch) | |
tree | c60f36ada0496ba928b7161059ba5ab1ab224f9d /src/libs/xpcom18a4/python | |
parent | Initial commit. (diff) | |
download | virtualbox-16f504a9dca3fe3b70568f67b7d41241ae485288.tar.xz virtualbox-16f504a9dca3fe3b70568f67b7d41241ae485288.zip |
Adding upstream version 7.0.6-dfsg.upstream/7.0.6-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/libs/xpcom18a4/python')
79 files changed, 21346 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/python/.cvsignore b/src/libs/xpcom18a4/python/.cvsignore new file mode 100644 index 00000000..9d5da30c --- /dev/null +++ b/src/libs/xpcom18a4/python/.cvsignore @@ -0,0 +1,4 @@ +*.pyc +*.pyo +*.idb +*.pdb
\ No newline at end of file diff --git a/src/libs/xpcom18a4/python/Makefile.kmk b/src/libs/xpcom18a4/python/Makefile.kmk new file mode 100644 index 00000000..b8dcd44a --- /dev/null +++ b/src/libs/xpcom18a4/python/Makefile.kmk @@ -0,0 +1,789 @@ +# $Id: Makefile.kmk $ +## @file +# Sub-Makefile for Python bindings +# + +# +# Copyright (C) 2009-2022 Oracle and/or its affiliates. +# +# This file is part of VirtualBox base platform packages, as +# available from https://www.virtualbox.org. +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation, in version 3 of the +# License. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see <https://www.gnu.org/licenses>. +# +# SPDX-License-Identifier: GPL-3.0-only +# + +SUB_DEPTH = ../../../.. +include $(KBUILD_PATH)/subheader.kmk + +# +# List of supported Python versions, defining a number of +# VBOX_PYTHON[26|27|31|32|32M|33|33M|34|34M|35|35M|36|36M|37|37M|38|38M|39|39M|310|310M|DEF]_[INC|LIB] variables +# which get picked up below. +# +ifeq ($(KBUILD_TARGET),darwin) # Relatively predictable, don't script. + ifn1of ($(VBOX_DEF_MACOSX_VERSION_MIN), 10.10 10.9 10.8 10.7 10.6 10.5 10.4) ## @todo @bugref{9790}: if $(VBOX_DEF_MACOSX_VERSION_MIN) vge 10.11 + VBOX_PYTHON_SUFFTBD := .tbd + else + VBOX_PYTHON_SUFFTBD := + endif + ifndef VBOX_WITHOUT_VBOXPYTHON_FOR_OSX_10_6 + if1of ($(VBOX_DEF_MACOSX_VERSION_MIN), 10.5 10.4) + VBOX_PYTHON26_INC = $(VBOX_PATH_MACOSX_SDK_10_6)/usr/include/python2.6 + VBOX_PYTHON26_LIB = $(VBOX_PATH_MACOSX_SDK_10_6)/usr/lib/libpython2.6.dylib + else if "$(VBOX_DEF_MACOSX_VERSION_MIN)" == "10.9" && "$(VBOX_XCODE_VERSION)" == "6.2" # 'effing 10.9 SDK in Xcode 6.2 is missing python. Stupid, stupid Apple!! + VBOX_PYTHON26_INC = $(VBOX_PATH_MACOSX_SDK)/../MacOSX10.10.sdk/System/Library/Frameworks/Python.framework/Versions/2.6/Headers + VBOX_PYTHON26_LIB = $(VBOX_PATH_MACOSX_SDK)/../MacOSX10.10.sdk/System/Library/Frameworks/Python.framework/Versions/2.6/Python + else if "$(VBOX_DEF_MACOSX_VERSION_MIN)" vlt "10.13" + VBOX_PYTHON26_INC = $(VBOX_PATH_MACOSX_SDK)/System/Library/Frameworks/Python.framework/Versions/2.6/Headers + VBOX_PYTHON26_LIB = $(VBOX_PATH_MACOSX_SDK)/System/Library/Frameworks/Python.framework/Versions/2.6/Python$(VBOX_PYTHON_SUFFTBD) + endif + if !defined(VBOX_OSE) || "$(wildcard $(VBOX_PYTHON26_LIB))" != "" + VBOX_PYTHON26_LIB_X86 = $(VBOX_PYTHON26_LIB) + else + VBOX_PYTHON26_INC = + VBOX_PYTHON26_LIB = + endif + endif + ifndef VBOX_WITHOUT_VBOXPYTHON_FOR_OSX_10_7 + if1of ($(VBOX_DEF_MACOSX_VERSION_MIN), 10.6 10.5 10.4) + VBOX_PYTHON27_INC = $(VBOX_PATH_MACOSX_SDK_10_7)/usr/include/python2.7 + VBOX_PYTHON27_LIB = $(VBOX_PATH_MACOSX_SDK_10_7)/usr/lib/libpython2.7.dylib + else if "$(VBOX_DEF_MACOSX_VERSION_MIN)" == "10.9" && "$(VBOX_XCODE_VERSION)" == "6.2" # 'effing 10.9 SDK in Xcode 6.2 is missing python. Stupid, stupid Apple!! + VBOX_PYTHON27_INC = $(VBOX_PATH_MACOSX_SDK)/../MacOSX10.10.sdk/System/Library/Frameworks/Python.framework/Versions/2.7/Headers + VBOX_PYTHON27_LIB = $(VBOX_PATH_MACOSX_SDK)/../MacOSX10.10.sdk/System/Library/Frameworks/Python.framework/Versions/2.7/Python + else + VBOX_PYTHON27_INC = $(VBOX_PATH_MACOSX_SDK)/System/Library/Frameworks/Python.framework/Versions/2.7/Headers + VBOX_PYTHON27_LIB = $(VBOX_PATH_MACOSX_SDK)/System/Library/Frameworks/Python.framework/Versions/2.7/Python$(VBOX_PYTHON_SUFFTBD) + endif + if !defined(VBOX_OSE) || "$(wildcard $(VBOX_PYTHON27_LIB))" != "" + VBOX_PYTHON27_LIB_X86 = $(VBOX_PYTHON27_LIB) + else + VBOX_PYTHON27_INC = + VBOX_PYTHON27_LIB = + endif + endif + # No Python 3.x yet as part of OSX versions including El Capitan, 10.11. + +else + # Use the script. + $(eval $(subst |,$(NL),$(shell $(VBOX_BLD_PYTHON) \ + $(PATH_SUB_CURRENT)/gen_python_deps.py \ + $(KBUILD_TARGET) \ + $(KBUILD_TARGET_ARCH) \ + $(if-expr defined(VBOX_WITH_MULTIVERSION_PYTHON),1,0)))) +endif + +ifndef VBOX_ONLY_SDK + +# +# Base Python Client Module - the C++/XPCOM bits (not actually built). +# +VBoxPythonBase_TEMPLATE = XPCOM +VBoxPythonBase_CXXFLAGS = -Wno-write-strings +VBoxPythonBase_CXXFLAGS.solaris = $(VBOX_GCC_Wno-unknown-pragmas) # /usr/include/python[23].[75]*/ceval.h:67: warning: ignoring #pragma no_inline(PyEval_EvalFrameEx) +VBoxPythonBase_DLLSUFF.darwin = .so +VBoxPythonBase_DEFS = \ + _IMPL_NS_COM \ + _IMPL_NS_BASE \ + EXPORT_XPTI_API \ + EXPORT_XPT_API \ + VBOX_PYXPCOM \ + VBOX_WITH_XPCOM \ + VBOX_PYXPCOM_VERSIONED +#VBoxPythonBase_DEFS.debug = \ +# VBOX_DEBUG_LIFETIMES +VBoxPythonBase_INCS = \ + src +VBoxPythonBase_SOURCES = \ + src/module/_xpcom.cpp \ + src/dllmain.cpp \ + src/ErrorUtils.cpp \ + src/PyGBase.cpp \ + src/PyGInputStream.cpp \ + src/PyGModule.cpp \ + src/PyGStub.cpp \ + src/PyGWeakReference.cpp \ + src/PyIClassInfo.cpp \ + src/PyIComponentManager.cpp \ + src/PyIComponentManagerObsolete.cpp \ + src/PyIEnumerator.cpp \ + src/PyIID.cpp \ + src/PyIInputStream.cpp \ + src/PyIInterfaceInfo.cpp \ + src/PyIInterfaceInfoManager.cpp \ + src/PyISimpleEnumerator.cpp \ + src/PyISupports.cpp \ + src/PyIVariant.cpp \ + src/Pyxpt_info.cpp \ + src/TypeObject.cpp \ + src/VariantUtils.cpp +VBoxPythonBase_LIBS = \ + $(PATH_STAGE_LIB)/VBoxCOM$(VBOX_SUFF_LIB) \ + $(PATH_STAGE_BIN)/VBoxXPCOM$(VBOX_SUFF_DLL) + +# pymalloc abi variant. +VBoxPythonBase_m_EXTENDS = VBoxPythonBase +VBoxPythonBase_m_DEFS = MODULE_NAME_SUFFIX=m $(VBoxPythonBase_DEFS) + +# 32-bit base. +VBoxPythonBase_x86_TEMPLATE = XPCOM-x86 +VBoxPythonBase_x86_EXTENDS = VBoxPythonBase +VBoxPythonBase_x86_DEFS = MODULE_NAME_SUFFIX=_x86 $(VBoxPythonBase_DEFS) +VBoxPythonBase_x86_LIBS = \ + $(PATH_STAGE_LIB)/VBoxCOM-x86$(VBOX_SUFF_LIB) \ + $(PATH_STAGE_BIN)/VBoxXPCOM-x86$(VBOX_SUFF_DLL) + +# 32-bit pymalloc abi variant. +VBoxPythonBase_x86_m_EXTENDS = VBoxPythonBase_x86 +VBoxPythonBase_x86_m_DEFS = MODULE_NAME_SUFFIX=_x86m $(VBoxPythonBase_DEFS) + + +ifdef VBOX_PYTHON26_INC +# +# Python 2.6 version +# +DLLS += VBoxPython2_6 +VBoxPython2_6_EXTENDS = VBoxPythonBase +VBoxPython2_6_EXTENDS_BY = appending + ifdef KMK_WITH_VERSION_COMPARE +VBoxPython2_6_TEMPLATE = XPCOM$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" vle "10.6",OSX106,) + else +VBoxPython2_6_TEMPLATE = XPCOM$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" <= "10.6",OSX106,) + endif +VBoxPython2_6_INCS = $(VBOX_PYTHON26_INC) +VBoxPython2_6_LIBS = $(VBOX_PYTHON26_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON26_LIB_X86 +DLLS += VBoxPython2_6_x86 +VBoxPython2_6_x86_EXTENDS = VBoxPythonBase_x86 +VBoxPython2_6_x86_EXTENDS_BY = appending + ifdef KMK_WITH_VERSION_COMPARE +VBoxPython2_6_x86_TEMPLATE = XPCOM$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" vle "10.6",OSX106,-x86) + else +VBoxPython2_6_x86_TEMPLATE = XPCOM$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" <= "10.6",OSX106,-x86) + endif +VBoxPython2_6_x86_INCS = $(VBOX_PYTHON26_INC) +VBoxPython2_6_x86_LIBS = $(VBOX_PYTHON26_LIB_X86) + endif + endif +endif + +ifdef VBOX_PYTHON27_INC +# +# Python 2.7 version +# +DLLS += VBoxPython2_7 +VBoxPython2_7_EXTENDS = VBoxPythonBase +VBoxPython2_7_EXTENDS_BY = appending + ifdef KMK_WITH_VERSION_COMPARE +VBoxPython2_7_TEMPLATE = XPCOM$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" vle "10.7",OSX107,) + else +VBoxPython2_7_TEMPLATE = XPCOM$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" <= "10.7" && "$(length-var VBOX_DEF_MACOSX_VERSION_MIN)" == "4",OSX107,) + endif +VBoxPython2_7_INCS = $(VBOX_PYTHON27_INC) +VBoxPython2_7_LIBS = $(VBOX_PYTHON27_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON27_LIB_X86 +DLLS += VBoxPython2_7_x86 +VBoxPython2_7_x86_EXTENDS = VBoxPythonBase_x86 +VBoxPython2_7_x86_EXTENDS_BY = appending + ifdef KMK_WITH_VERSION_COMPARE +VBoxPython2_7_x86_TEMPLATE = XPCOM$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" vle "10.7",OSX107,-x86) + else +VBoxPython2_7_x86_TEMPLATE = XPCOM$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" <= "10.7" && "$(length-var VBOX_DEF_MACOSX_VERSION_MIN)" == "4",OSX107,-x86) + endif +VBoxPython2_7_x86_INCS = $(VBOX_PYTHON27_INC) +VBoxPython2_7_x86_LIBS = $(VBOX_PYTHON27_LIB_X86) + endif + endif +endif + +# +# Unversioned Python 2.x. +# + if defined(VBOX_PYTHON27_INC) || defined(VBOX_PYTHON26_INC) +DLLS += VBoxPython2 +VBoxPython2_EXTENDS = VBoxPythonBase +VBoxPython2_EXTENDS_BY = appending +VBoxPython2_DEFS = VBOX_PYXPCOM_MAJOR_VERSIONED + ifdef KMK_WITH_VERSION_COMPARE +VBoxPython2_TEMPLATE = XPCOM$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" vle "10.7",OSX107,) + else +VBoxPython2_TEMPLATE = XPCOM$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" <= "10.7" && "$(length-var VBOX_DEF_MACOSX_VERSION_MIN)" == "4",OSX107,) + endif + if defined(VBOX_PYTHON26_INC) +VBoxPython2_INCS = $(VBOX_PYTHON26_INC) + ifn1of ($(KBUILD_TARGET), linux) +VBoxPython2_LIBS = $(VBOX_PYTHON26_LIB) + endif + else +VBoxPython2_INCS = $(VBOX_PYTHON27_INC) + ifn1of ($(KBUILD_TARGET), linux) +VBoxPython2_LIBS = $(VBOX_PYTHON27_LIB) + endif + endif + endif + + if defined(VBOX_WITH_32_ON_64_MAIN_API) && (defined(VBOX_PYTHON27_LIB_X86) || defined(VBOX_PYTHON26_INC_X86)) +DLLS += VBoxPython2_x86 +VBoxPython2_x86_EXTENDS = VBoxPythonBase_x86 +VBoxPython2_x86_EXTENDS_BY = appending +VBoxPython2_x86_DEFS = VBOX_PYXPCOM_MAJOR_VERSIONED $(VBoxPythonBase_x86_DEFS) + ifdef KMK_WITH_VERSION_COMPARE +VBoxPython2_x86_TEMPLATE = XPCOM$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" vle "10.7",OSX107,-x86) + else +VBoxPython2_x86_TEMPLATE = XPCOM$(if-expr "$(KBUILD_TARGET)" == "darwin" && "$(VBOX_DEF_MACOSX_VERSION_MIN)" <= "10.7" && "$(length-var VBOX_DEF_MACOSX_VERSION_MIN)" == "4",OSX107,-x86) + endif + if defined(VBOX_PYTHON26LIB_X86) +VBoxPython2_x86_INCS = $(VBOX_PYTHON26_INC) + ifn1of ($(KBUILD_TARGET), linux) +VBoxPython2_x86_LIBS = $(VBOX_PYTHON26_LIB_X86) + endif + else +VBoxPython2_x86_INCS = $(VBOX_PYTHON27_INC) + ifn1of ($(KBUILD_TARGET), linux) +VBoxPython2_x86_LIBS = $(VBOX_PYTHON27_LIB_X86) + endif + endif + endif + + +ifdef VBOX_PYTHON31_INC +# +# Python 3.1 version +# +DLLS += VBoxPython3_1 +VBoxPython3_1_EXTENDS = VBoxPythonBase +VBoxPython3_1_EXTENDS_BY = appending +VBoxPython3_1_TEMPLATE = XPCOM +VBoxPython3_1_INCS = $(VBOX_PYTHON31_INC) +VBoxPython3_1_LIBS = $(VBOX_PYTHON31_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON31_LIB_X86 +DLLS += VBoxPython3_1_x86 +VBoxPython3_1_x86_EXTENDS = VBoxPythonBase_x86 +VBoxPython3_1_x86_EXTENDS_BY = appending +VBoxPython3_1_x86_TEMPLATE = XPCOM +VBoxPython3_1_x86_INCS = $(VBOX_PYTHON31_INC) +VBoxPython3_1_x86_LIBS = $(VBOX_PYTHON31_LIB_X86) + endif + endif +endif + +ifdef VBOX_PYTHON32_INC +# +# Python 3.2 version +# +DLLS += VBoxPython3_2 +VBoxPython3_2_EXTENDS = VBoxPythonBase +VBoxPython3_2_EXTENDS_BY = appending +VBoxPython3_2_TEMPLATE = XPCOM +VBoxPython3_2_INCS = $(VBOX_PYTHON32_INC) +VBoxPython3_2_LIBS = $(VBOX_PYTHON32_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON32_LIB_X86 +DLLS += VBoxPython3_2_x86 +VBoxPython3_2_x86_EXTENDS = VBoxPythonBase_x86 +VBoxPython3_2_x86_EXTENDS_BY = appending +VBoxPython3_2_x86_TEMPLATE = XPCOM +VBoxPython3_2_x86_INCS = $(VBOX_PYTHON32_INC) +VBoxPython3_2_x86_LIBS = $(VBOX_PYTHON32_LIB_X86) + endif + endif +endif + +ifdef VBOX_PYTHON32M_INC +# +# Python 3.2 version with pymalloc +# +DLLS += VBoxPython3_2m +VBoxPython3_2m_EXTENDS = VBoxPythonBase_m +VBoxPython3_2m_EXTENDS_BY = appending +VBoxPython3_2m_TEMPLATE = XPCOM +VBoxPython3_2m_INCS = $(VBOX_PYTHON32M_INC) +VBoxPython3_2m_LIBS = $(VBOX_PYTHON32M_LIB) +VBoxPython3_2m_DEFS = MODULE_NAME_SUFFIX + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON32M_LIB_X86 +DLLS += VBoxPython3_2m_x86 +VBoxPython3_2m_x86_EXTENDS = VBoxPythonBase_x86_m +VBoxPython3_2m_x86_EXTENDS_BY = appending +VBoxPython3_2m_x86_TEMPLATE = XPCOM +VBoxPython3_2m_x86_INCS = $(VBOX_PYTHON32M_INC) +VBoxPython3_2m_x86_LIBS = $(VBOX_PYTHON32M_LIB_X86) + endif + endif +endif + + ifndef VBOX_WITH_ONLY_PYTHON_LIMITED_API + +ifdef VBOX_PYTHON33_INC +# +# Python 3.3 version +# +DLLS += VBoxPython3_3 +VBoxPython3_3_EXTENDS = VBoxPythonBase +VBoxPython3_3_EXTENDS_BY = appending +VBoxPython3_3_TEMPLATE = XPCOM +VBoxPython3_3_INCS = $(VBOX_PYTHON33_INC) +VBoxPython3_3_LIBS = $(VBOX_PYTHON33_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON33_LIB_X86 +DLLS += VBoxPython3_3_x86 +VBoxPython3_3_x86_EXTENDS = VBoxPythonBase_x86 +VBoxPython3_3_x86_EXTENDS_BY = appending +VBoxPython3_3_x86_TEMPLATE = XPCOM +VBoxPython3_3_x86_INCS = $(VBOX_PYTHON33_INC) +VBoxPython3_3_x86_LIBS = $(VBOX_PYTHON33_LIB_X86) + endif + endif +endif + +ifdef VBOX_PYTHON33M_INC +# +# Python 3.3 version with pymalloc +# +DLLS += VBoxPython3_3m +VBoxPython3_3m_EXTENDS = VBoxPythonBase_m +VBoxPython3_3m_EXTENDS_BY = appending +VBoxPython3_3m_TEMPLATE = XPCOM +VBoxPython3_3m_INCS = $(VBOX_PYTHON33M_INC) +VBoxPython3_3m_LIBS = $(VBOX_PYTHON33M_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON33M_LIB_X86 +DLLS += VBoxPython3_3m_x86 +VBoxPython3_3m_x86_EXTENDS = VBoxPythonBase_x86_m +VBoxPython3_3m_x86_EXTENDS_BY = appending +VBoxPython3_3m_x86_TEMPLATE = XPCOM +VBoxPython3_3m_x86_INCS = $(VBOX_PYTHON33M_INC) +VBoxPython3_3m_x86_LIBS = $(VBOX_PYTHON33M_LIB_X86) + endif + endif +endif + +ifdef VBOX_PYTHON34_INC +# +# Python 3.4 version +# +DLLS += VBoxPython3_4 +VBoxPython3_4_EXTENDS = VBoxPythonBase +VBoxPython3_4_EXTENDS_BY = appending +VBoxPython3_4_TEMPLATE = XPCOM +VBoxPython3_4_INCS = $(VBOX_PYTHON34_INC) +VBoxPython3_4_LIBS = $(VBOX_PYTHON34_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON34_LIB_X86 +DLLS += VBoxPython3_4_x86 +VBoxPython3_4_x86_EXTENDS = VBoxPythonBase_x86 +VBoxPython3_4_x86_EXTENDS_BY = appending +VBoxPython3_4_x86_TEMPLATE = XPCOM +VBoxPython3_4_x86_INCS = $(VBOX_PYTHON34_INC) +VBoxPython3_4_x86_LIBS = $(VBOX_PYTHON34_LIB_X86) + endif + endif +endif + +ifdef VBOX_PYTHON34M_INC +# +# Python 3.4 version with pymalloc +# +DLLS += VBoxPython3_4m +VBoxPython3_4m_EXTENDS = VBoxPythonBase_m +VBoxPython3_4m_EXTENDS_BY = appending +VBoxPython3_4m_TEMPLATE = XPCOM +VBoxPython3_4m_INCS = $(VBOX_PYTHON34M_INC) +VBoxPython3_4m_LIBS = $(VBOX_PYTHON34M_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON34M_LIB_X86 +DLLS += VBoxPython3_4m_x86 +VBoxPython3_4m_x86_EXTENDS = VBoxPythonBase_x86_m +VBoxPython3_4m_x86_EXTENDS_BY = appending +VBoxPython3_4m_x86_TEMPLATE = XPCOM +VBoxPython3_4m_x86_INCS = $(VBOX_PYTHON34M_INC) +VBoxPython3_4m_x86_LIBS = $(VBOX_PYTHON34M_LIB_X86) + endif + endif +endif + +ifdef VBOX_PYTHON35_INC +# +# Python 3.5 version +# +DLLS += VBoxPython3_5 +VBoxPython3_5_EXTENDS = VBoxPythonBase +VBoxPython3_5_EXTENDS_BY = appending +VBoxPython3_5_TEMPLATE = XPCOM +VBoxPython3_5_INCS = $(VBOX_PYTHON35_INC) +VBoxPython3_5_LIBS = $(VBOX_PYTHON35_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON35_LIB_X86 +DLLS += VBoxPython3_5_x86 +VBoxPython3_5_x86_EXTENDS = VBoxPythonBase_x86 +VBoxPython3_5_x86_EXTENDS_BY = appending +VBoxPython3_5_x86_TEMPLATE = XPCOM +VBoxPython3_5_x86_INCS = $(VBOX_PYTHON35_INC) +VBoxPython3_5_x86_LIBS = $(VBOX_PYTHON35_LIB_X86) + endif + endif +endif + +ifdef VBOX_PYTHON35M_INC +# +# Python 3.5 version with pymalloc +# +DLLS += VBoxPython3_5m +VBoxPython3_5m_EXTENDS = VBoxPythonBase_m +VBoxPython3_5m_EXTENDS_BY = appending +VBoxPython3_5m_TEMPLATE = XPCOM +VBoxPython3_5m_INCS = $(VBOX_PYTHON35M_INC) +VBoxPython3_5m_LIBS = $(VBOX_PYTHON35M_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON35M_LIB_X86 +DLLS += VBoxPython3_5m_x86 +VBoxPython3_5m_x86_EXTENDS = VBoxPythonBase_x86_m +VBoxPython3_5m_x86_EXTENDS_BY = appending +VBoxPython3_5m_x86_TEMPLATE = XPCOM +VBoxPython3_5m_x86_INCS = $(VBOX_PYTHON35M_INC) +VBoxPython3_5m_x86_LIBS = $(VBOX_PYTHON35M_LIB_X86) + endif + endif +endif + +ifdef VBOX_PYTHON36_INC +# +# Python 3.6 version +# +DLLS += VBoxPython3_6 +VBoxPython3_6_EXTENDS = VBoxPythonBase +VBoxPython3_6_EXTENDS_BY = appending +VBoxPython3_6_TEMPLATE = XPCOM +VBoxPython3_6_INCS = $(VBOX_PYTHON36_INC) +VBoxPython3_6_LIBS = $(VBOX_PYTHON36_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON36_LIB_X86 +DLLS += VBoxPython3_6_x86 +VBoxPython3_6_x86_EXTENDS = VBoxPythonBase_x86 +VBoxPython3_6_x86_EXTENDS_BY = appending +VBoxPython3_6_x86_TEMPLATE = XPCOM +VBoxPython3_6_x86_INCS = $(VBOX_PYTHON36_INC) +VBoxPython3_6_x86_LIBS = $(VBOX_PYTHON36_LIB_X86) + endif + endif +endif + +ifdef VBOX_PYTHON36M_INC +# +# Python 3.6 version with pymalloc +# +DLLS += VBoxPython3_6m +VBoxPython3_6m_EXTENDS = VBoxPythonBase_m +VBoxPython3_6m_EXTENDS_BY = appending +VBoxPython3_6m_TEMPLATE = XPCOM +VBoxPython3_6m_INCS = $(VBOX_PYTHON36M_INC) +VBoxPython3_6m_LIBS = $(VBOX_PYTHON36M_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON36M_LIB_X86 +DLLS += VBoxPython3_6m_x86 +VBoxPython3_6m_x86_EXTENDS = VBoxPythonBase_x86_m +VBoxPython3_6m_x86_EXTENDS_BY = appending +VBoxPython3_6m_x86_TEMPLATE = XPCOM +VBoxPython3_6m_x86_INCS = $(VBOX_PYTHON36M_INC) +VBoxPython3_6m_x86_LIBS = $(VBOX_PYTHON36M_LIB_X86) + endif + endif +endif + +ifdef VBOX_PYTHON37_INC +# +# Python 3.7 version +# +DLLS += VBoxPython3_7 +VBoxPython3_7_EXTENDS = VBoxPythonBase +VBoxPython3_7_EXTENDS_BY = appending +VBoxPython3_7_TEMPLATE = XPCOM +VBoxPython3_7_INCS = $(VBOX_PYTHON37_INC) +VBoxPython3_7_LIBS = $(VBOX_PYTHON37_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON37_LIB_X86 +DLLS += VBoxPython3_7_x86 +VBoxPython3_7_x86_EXTENDS = VBoxPythonBase_x86 +VBoxPython3_7_x86_EXTENDS_BY = appending +VBoxPython3_7_x86_TEMPLATE = XPCOM +VBoxPython3_7_x86_INCS = $(VBOX_PYTHON37_INC) +VBoxPython3_7_x86_LIBS = $(VBOX_PYTHON37_LIB_X86) + endif + endif +endif + +ifdef VBOX_PYTHON37M_INC +# +# Python 3.7 version with pymalloc +# +DLLS += VBoxPython3_7m +VBoxPython3_7m_EXTENDS = VBoxPythonBase_m +VBoxPython3_7m_EXTENDS_BY = appending +VBoxPython3_7m_TEMPLATE = XPCOM +VBoxPython3_7m_INCS = $(VBOX_PYTHON37M_INC) +VBoxPython3_7m_LIBS = $(VBOX_PYTHON37M_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON37M_LIB_X86 +DLLS += VBoxPython3_7m_x86 +VBoxPython3_7m_x86_EXTENDS = VBoxPythonBase_x86_m +VBoxPython3_7m_x86_EXTENDS_BY = appending +VBoxPython3_7m_x86_TEMPLATE_ = XPCOM +VBoxPython3_7m_x86_INCS = $(VBOX_PYTHON37M_INC) +VBoxPython3_7m_x86_LIBS = $(VBOX_PYTHON37M_LIB_X86) + endif + endif +endif + +ifdef VBOX_PYTHON38_INC +# +# Python 3.8 version +# +DLLS += VBoxPython3_8 +VBoxPython3_8_EXTENDS = VBoxPythonBase +VBoxPython3_8_EXTENDS_BY = appending +VBoxPython3_8_TEMPLATE = XPCOM +VBoxPython3_8_INCS = $(VBOX_PYTHON38_INC) +VBoxPython3_8_LIBS = $(VBOX_PYTHON38_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON38_LIB_X86 +DLLS += VBoxPython3_8_x86 +VBoxPython3_8_x86_EXTENDS = VBoxPythonBase_x86 +VBoxPython3_8_x86_EXTENDS_BY = appending +VBoxPython3_8_x86_TEMPLATE = XPCOM +VBoxPython3_8_x86_INCS = $(VBOX_PYTHON38_INC) +VBoxPython3_8_x86_LIBS = $(VBOX_PYTHON38_LIB_X86) + endif + endif +endif + +ifdef VBOX_PYTHON38M_INC +# +# Python 3.8 version with pymalloc +# +DLLS += VBoxPython3_8m +VBoxPython3_8m_EXTENDS = VBoxPythonBase_m +VBoxPython3_8m_EXTENDS_BY = appending +VBoxPython3_8m_TEMPLATE = XPCOM +VBoxPython3_8m_INCS = $(VBOX_PYTHON38M_INC) +VBoxPython3_8m_LIBS = $(VBOX_PYTHON38M_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON38M_LIB_X86 +DLLS += VBoxPython3_8m_x86 +VBoxPython3_8m_x86_EXTENDS = VBoxPythonBase_x86_m +VBoxPython3_8m_x86_EXTENDS_BY = appending +VBoxPython3_8m_x86_TEMPLATE_ = XPCOM +VBoxPython3_8m_x86_INCS = $(VBOX_PYTHON38M_INC) +VBoxPython3_8m_x86_LIBS = $(VBOX_PYTHON38M_LIB_X86) + endif + endif +endif + +ifdef VBOX_PYTHON39_INC +# +# Python 3.9 version +# +DLLS += VBoxPython3_9 +VBoxPython3_9_EXTENDS = VBoxPythonBase +VBoxPython3_9_EXTENDS_BY = appending +VBoxPython3_9_TEMPLATE = XPCOM +VBoxPython3_9_INCS = $(VBOX_PYTHON39_INC) +VBoxPython3_9_LIBS = $(VBOX_PYTHON39_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON39_LIB_X86 +DLLS += VBoxPython3_9_x86 +VBoxPython3_9_x86_EXTENDS = VBoxPythonBase_x86 +VBoxPython3_9_x86_EXTENDS_BY = appending +VBoxPython3_9_x86_TEMPLATE = XPCOM +VBoxPython3_9_x86_INCS = $(VBOX_PYTHON39_INC) +VBoxPython3_9_x86_LIBS = $(VBOX_PYTHON39_LIB_X86) + endif + endif +endif + +ifdef VBOX_PYTHON39M_INC +# +# Python 3.9 version with pymalloc +# +DLLS += VBoxPython3_9m +VBoxPython3_9m_EXTENDS = VBoxPythonBase_m +VBoxPython3_9m_EXTENDS_BY = appending +VBoxPython3_9m_TEMPLATE = XPCOM +VBoxPython3_9m_INCS = $(VBOX_PYTHON39M_INC) +VBoxPython3_9m_LIBS = $(VBOX_PYTHON39M_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON39M_LIB_X86 +DLLS += VBoxPython3_9m_x86 +VBoxPython3_9m_x86_EXTENDS = VBoxPythonBase_x86_m +VBoxPython3_9m_x86_EXTENDS_BY = appending +VBoxPython3_9m_x86_TEMPLATE_ = XPCOM +VBoxPython3_9m_x86_INCS = $(VBOX_PYTHON39M_INC) +VBoxPython3_9m_x86_LIBS = $(VBOX_PYTHON39M_LIB_X86) + endif + endif +endif + +ifdef VBOX_PYTHON310_INC +# +# Python 3.10 version +# +DLLS += VBoxPython3_10 +VBoxPython3_10_EXTENDS = VBoxPythonBase +VBoxPython3_10_EXTENDS_BY = appending +VBoxPython3_10_TEMPLATE = XPCOM +VBoxPython3_10_INCS = $(VBOX_PYTHON310_INC) +VBoxPython3_10_LIBS = $(VBOX_PYTHON310_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON310_LIB_X86 +DLLS += VBoxPython3_10_x86 +VBoxPython3_10_x86_EXTENDS = VBoxPythonBase_x86 +VBoxPython3_10_x86_EXTENDS_BY = appending +VBoxPython3_10_x86_TEMPLATE = XPCOM +VBoxPython3_10_x86_INCS = $(VBOX_PYTHON310_INC) +VBoxPython3_10_x86_LIBS = $(VBOX_PYTHON310_LIB_X86) + endif + endif +endif + +ifdef VBOX_PYTHON310M_INC +# +# Python 3.10 version with pymalloc +# +DLLS += VBoxPython3_10m +VBoxPython3_10m_EXTENDS = VBoxPythonBase_m +VBoxPython3_10m_EXTENDS_BY = appending +VBoxPython3_10m_TEMPLATE = XPCOM +VBoxPython3_10m_INCS = $(VBOX_PYTHON310M_INC) +VBoxPython3_10m_LIBS = $(VBOX_PYTHON310M_LIB) + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHON310M_LIB_X86 +DLLS += VBoxPython3_10m_x86 +VBoxPython3_10m_x86_EXTENDS = VBoxPythonBase_x86_m +VBoxPython3_10m_x86_EXTENDS_BY = appending +VBoxPython3_10m_x86_TEMPLATE_ = XPCOM +VBoxPython3_10m_x86_INCS = $(VBOX_PYTHON310M_INC) +VBoxPython3_10m_x86_LIBS = $(VBOX_PYTHON310M_LIB_X86) + endif + endif +endif + +ifdef VBOX_PYTHONDEF_INC +# +# Python without versioning +# +DLLS += VBoxPython +VBoxPython_EXTENDS = VBoxPythonBase +VBoxPython_DEFS = $(filter-out VBOX_PYXPCOM_VERSIONED,$(VBoxPythonBase_DEFS)) +VBoxPython_INCS = $(VBoxPythonBase_INCS) $(VBOX_PYTHONDEF_INC) +if "$(KBUILD_TARGET)" == "linux" + VBoxPython_LIBS = $(VBoxPythonBase_LIBS) +else + VBoxPython_LIBS = $(VBoxPythonBase_LIBS) $(VBOX_PYTHONDEF_LIB) +endif + + ifdef VBOX_WITH_32_ON_64_MAIN_API + ifdef VBOX_PYTHONDEF_LIB_X86 +VBoxPython_x86_EXTENDS = VBoxPythonBase_x86 +VBoxPython_x86_DEFS = $(filter-out VBOX_PYXPCOM_VERSIONED,$(VBoxPythonBase_x86_DEFS)) +VBoxPython_x86_INCS = $(VBoxPythonBase_x86_INCS) $(VBOX_PYTHONDEF_INC) +if "$(KBUILD_TARGET)" == "linux" + VBoxPython_x86_LIBS = $(VBoxPythonBase_x86_LIBS) +else + VBoxPython_x86_LIBS = $(VBoxPythonBase_x86_LIBS) $(VBOX_PYTHONDEF_LIB_X86) +endif + endif + endif +endif + + endif # !VBOX_WITH_ONLY_PYTHON_LIMITED_API + + ifndef VBOX_WITHOUT_PYTHON_LIMITED_API +# +# If there is python 3.3 or later present, we can build a generic +# 3.x extension. Since 3.3 and 3.4 are rather old, we will pick +# those headers last. +# +# Note! No library dependencies are needed here (at least that's +# how the xxlimited.so demo extension is done on linux and darwin). +# Note! The 'm' ABI suffix was discontinued in 3.8. +# TODO: ASSUMING that we don't need a different headers for pymalloc +# ('m' builds < 3.8) and CRT malloc. +# +VBOX_PYTHON_LIMITED_API_VER := $(firstword $(foreach ver, 35 36 38 39 310 34 33 \ +,$(if-expr defined(VBOX_PYTHON$(ver)_INC),$(ver),)$(if-expr defined(VBOX_PYTHON$(ver)M_INC),$(ver)M,))) + ifneq ($(VBOX_PYTHON_LIMITED_API_VER),) +DLLS += VBoxPython3 +VBoxPython3_EXTENDS = VBoxPythonBase +VBoxPython3_DEFS = $(filter-out VBOX_PYXPCOM_VERSIONED,$(VBoxPythonBase_DEFS)) Py_LIMITED_API=0x03030000 +VBoxPython3_INCS = $(VBoxPythonBase_INCS) $(VBOX_PYTHON$(VBOX_PYTHON_LIMITED_API_VER)_INC) + +DLLS += VBoxPython3m +VBoxPython3m_EXTENDS = VBoxPythonBase_m +VBoxPython3m_DEFS = $(filter-out VBOX_PYXPCOM_VERSIONED,$(VBoxPythonBase_m_DEFS)) Py_LIMITED_API=0x03030000 +VBoxPython3m_INCS = $(VBoxPythonBase_m_INCS) $(VBOX_PYTHON$(VBOX_PYTHON_LIMITED_API_VER)_INC) + endif + endif # VBOX_WITH_PYTHON_LIMITED_API + +endif # VBOX_ONLY_SDK + +# +# Install the python modules. +# +INSTALLS += VBoxPython-inst-py-xpcom +VBoxPython-inst-py-xpcom_INST = $(INST_SDK)bindings/xpcom/python/xpcom/ +VBoxPython-inst-py-xpcom_MODE = a+r,u+w +VBoxPython-inst-py-xpcom_SOURCES = \ + vboxxpcom.py \ + components.py \ + file.py \ + __init__.py \ + nsError.py \ + primitives.py \ + xpcom_consts.py \ + xpt.py \ + client/__init__.py=>client/__init__.py \ + server/__init__.py=>server/__init__.py \ + server/enumerator.py=>server/enumerator.py \ + server/factory.py=>server/factory.py \ + server/loader.py=>server/loader.py \ + server/module.py=>server/module.py \ + server/policy.py=>server/policy.py + + +include $(FILE_KBUILD_SUB_FOOTER) diff --git a/src/libs/xpcom18a4/python/README.vbox b/src/libs/xpcom18a4/python/README.vbox new file mode 100644 index 00000000..b85f854c --- /dev/null +++ b/src/libs/xpcom18a4/python/README.vbox @@ -0,0 +1,5 @@ + PyXPCOM sources (see http://developer.mozilla.org/en/docs/PyXPCOM) +were taken from :pserver:anonymous@cvs-mirror.mozilla.org:/cvsroot, +directory extensions/python/xpcom, branch DOM_AGNOSTIC2_BRANCH, Aug 14 2008. + + Imported to VirtualBox codebase in revision 34814. diff --git a/src/libs/xpcom18a4/python/__init__.py b/src/libs/xpcom18a4/python/__init__.py new file mode 100755 index 00000000..3a5943b6 --- /dev/null +++ b/src/libs/xpcom18a4/python/__init__.py @@ -0,0 +1,173 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# Activestate Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Hammond <MarkH@activestate.com> +# +# 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 (Cross Platform COM) package. +from __future__ import print_function +import sys +if sys.version_info[0] <= 2: + import exceptions + XPCOMBaseException = exceptions.Exception +else: + XPCOMBaseException = Exception + +# 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. +# Instances of this class are raised by the XPCOM extension module. +class Exception(XPCOMBaseException): + def __init__(self, errno, message = None): + assert int(errno) == errno, "The errno param must be an integer" + self.errno = errno + self.msg = message + XPCOMBaseException.__init__(self, errno) + def __str__(self): + if not hr_map: + from . import nsError + for name, val in list(nsError.__dict__.items()): + if type(val)==type(0): + hr_map[val] = name + message = self.msg + if message is None: + message = hr_map.get(self.errno) + if message is None: + message = "" + return "0x%x (%s)" % (self.errno & 0xFFFFFFFF, message) + +# An alias for Exception - allows code to say "from xpcom import COMException" +# rather than "Exception", preventing clashes with the builtin Exception +COMException = Exception + +# Exceptions thrown by servers. It can be good for diagnostics to +# differentiate between a ServerException (which was presumably explicitly thrown) +# 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) +class ServerException(Exception): + def __init__(self, errno=None, *args, **kw): + if errno is None: + from . import nsError + errno = nsError.NS_ERROR_FAILURE + Exception.__init__(self, errno, *args, **kw) + +# 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 as _xpcom + _xpcom.LogConsoleMessage(msg) + def close(self): + pass + +def setupLogging(): + import os + if sys.version_info[0] <= 2: + import 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 sys.version_info[0] <= 2: + 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 as why: + print("pyxpcom failed to open log file '%s': %s" % (filename, why), file=sys.stderr) + # stream remains default + + hdlr = logging.StreamHandler(stream) + # see above - fix a deadlock problem on this handler too. + if sys.version_info[0] <= 2: + 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 diff --git a/src/libs/xpcom18a4/python/client/.cvsignore b/src/libs/xpcom18a4/python/client/.cvsignore new file mode 100644 index 00000000..52e4e611 --- /dev/null +++ b/src/libs/xpcom18a4/python/client/.cvsignore @@ -0,0 +1,2 @@ +*.pyc +*.pyo diff --git a/src/libs/xpcom18a4/python/client/__init__.py b/src/libs/xpcom18a4/python/client/__init__.py new file mode 100755 index 00000000..48adc7f5 --- /dev/null +++ b/src/libs/xpcom18a4/python/client/__init__.py @@ -0,0 +1,539 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# ActiveState Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000, 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Hammond <MarkH@ActiveState.com> (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 ***** + +import os +from types import MethodType +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_nsISupportsString, \ + IID_nsISupportsWeakReference, IID_nsIWeakReference, \ + XPTI_GetInterfaceInfoManager, GetComponentManager, XPTC_InvokeByIndex + +# Python 3 hacks: +import sys +if sys.version_info[0] >= 3: + long = int # pylint: disable=W0622,C0103 + +# 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__", "__eq__", "__neq__"] + +_just_int_interfaces = ["nsISupportsPRInt32", "nsISupportsPRInt16", "nsISupportsPRUint32", "nsISupportsPRUint16", "nsISupportsPRUint8", "nsISupportsPRBool"] +_just_long_interfaces = ["nsISupportsPRInt64", "nsISupportsPRUint64"] +_just_float_interfaces = ["nsISupportsDouble", "nsISupportsFloat"] +# When doing a specific conversion, the order we try the interfaces in. +_int_interfaces = _just_int_interfaces + _just_float_interfaces +_long_interfaces = _just_long_interfaces + _just_int_interfaces + _just_float_interfaces +_float_interfaces = _just_float_interfaces + _just_long_interfaces + _just_int_interfaces + +method_template = """ +def %s(self, %s): + return XPTC_InvokeByIndex(self._comobj_, %d, (%s, (%s))) +""" +def _MakeMethodCode(method): + # Build a declaration + param_no = 0 + param_decls = [] + param_flags = [] + param_names = [] + used_default = 0 + for param in method.params: + param_no = param_no + 1 + param_name = "Param%d" % (param_no,) + param_default = "" + if not param.hidden_indicator and param.IsIn() and not param.IsDipper(): + if param.IsOut() or used_default: # If the param is "inout", provide a useful default for the "in" direction. + param_default = " = None" + used_default = 1 # Once we have used one once, we must for the rest! + param_decls.append(param_name + param_default) + param_names.append(param_name) + + type_repr = xpt.MakeReprForInvoke(param) + param_flags.append( (param.param_flags,) + type_repr ) + sep = ", " + param_decls = sep.join(param_decls) + if len(param_names)==1: # Damn tuple reprs. + param_names = param_names[0] + "," + else: + param_names = sep.join(param_names) + # A couple of extra newlines make them easier to read for debugging :-) + return method_template % (method.name, param_decls, method.method_index, tuple(param_flags), param_names) + +# Keyed by IID, each item is a tuple of (methods, getters, setters) +interface_cache = {} +# Keyed by [iid][name], each item is an unbound method. +interface_method_cache = {} + +# Keyed by clsid from nsIClassInfo - everything ever queried for the CID. +contractid_info_cache = {} +have_shutdown = 0 + +def _shutdown(): + interface_cache.clear() + interface_method_cache.clear() + contractid_info_cache.clear() + global have_shutdown + have_shutdown = 1 + +# Fully process the named method, generating method code etc. +def BuildMethod(method_info, iid): + name = method_info.name + try: + return interface_method_cache[iid][name] + except KeyError: + pass + # Generate it. + assert not (method_info.IsSetter() or method_info.IsGetter()), "getters and setters should have been weeded out by now" + method_code = _MakeMethodCode(method_info) + # Build the method - We only build a function object here + # - they are bound to each instance as needed. + +## print "Method Code for %s (%s):" % (name, iid) +## print method_code + codeObject = compile(method_code, "<XPCOMObject method '%s'>" % (name,), "exec") + # Exec the code object + tempNameSpace = {} + exec(codeObject, globals(), tempNameSpace) + ret = tempNameSpace[name] + if iid not in interface_method_cache: + interface_method_cache[iid] = {} + interface_method_cache[iid][name] = ret + return ret + +from xpcom.xpcom_consts import XPT_MD_GETTER, XPT_MD_SETTER, XPT_MD_NOTXPCOM, XPT_MD_CTOR, XPT_MD_HIDDEN +FLAGS_TO_IGNORE = XPT_MD_NOTXPCOM | XPT_MD_CTOR | XPT_MD_HIDDEN + +# Pre-process the interface - generate a list of methods, constants etc, +# but don't actually generate the method code. +def BuildInterfaceInfo(iid): + assert not have_shutdown, "Can't build interface info after a shutdown" + ret = interface_cache.get(iid, None) + if ret is None: + # Build the data for the cache. + method_code_blocks = [] + getters = {} + setters = {} + method_infos = {} + + interface = xpt.Interface(iid) + for m in interface.methods: + flags = m.flags + if flags & FLAGS_TO_IGNORE == 0: + if flags & XPT_MD_SETTER: + param_flags = list([(x.param_flags,) + xpt.MakeReprForInvoke(x) for x in m.params]) + setters[m.name] = m.method_index, param_flags + elif flags & XPT_MD_GETTER: + param_flags = list([(x.param_flags,) + xpt.MakeReprForInvoke(x) for x in m.params]) + getters[m.name] = m.method_index, param_flags + else: + method_infos[m.name] = m + + # Build the constants. + constants = {} + for c in interface.constants: + constants[c.name] = c.value + ret = method_infos, getters, setters, constants + interface_cache[iid] = ret + return ret + +class _XPCOMBase: + def __cmp__(self, other): + try: + other = other._comobj_ + except AttributeError: + pass + return cmp(self._comobj_, other) + + 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: + self._comobj_.QueryInterface(IID_nsISupportsCString, 0) + return str(self._comobj_) + 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() + for interface_name in interface_names: + iid = iim.GetInfoForName(interface_name).GetIID() + try: + prim = self._comobj_.QueryInterface(iid) + return cvt(prim.data) + except COMException: + pass + raise ValueError("This object does not support automatic numeric conversion to this type") + + def __int__(self): + if sys.version_info[0] >= 3: + return self._do_conversion(_int_interfaces + _long_interfaces, int) + return self._do_conversion(_int_interfaces, int) + + def __long__(self): + return self._do_conversion(_long_interfaces, long) + + def __float__(self): + return self._do_conversion(_float_interfaces, float) + +class Component(_XPCOMBase): + 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"): + ob_name = ob + cm = GetComponentManager() + ob = cm.createInstanceByContractID(ob) + assert not hasattr(ob, "_comobj_"), "The created object should be a raw nsIWhatever, not a wrapped one" + # Keep a reference to the object in the component too + self.__dict__['_comobj_'] = ob + # hit __dict__ directly to avoid __setattr__() + 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_iid_'] = {} + self.__dict__['_tried_classinfo_'] = 0 + + if ob_name is None: + ob_name = "<unknown>" + self.__dict__['_object_name_'] = ob_name + self.QueryInterface(iid) + + def _build_all_supported_interfaces_(self): + # Use nsIClassInfo, but don't do it at object construction to keep perf up. + # Only pay the penalty when we really need it. + assert not self._tried_classinfo_, "already tried to get the class info." + self.__dict__['_tried_classinfo_'] = 1 + # See if nsIClassInfo is supported. + try: + classinfo = self._comobj_.QueryInterface(IID_nsIClassInfo, 0) + except COMException: + classinfo = None + if classinfo is not None: + try: + real_cid = classinfo.contractID + except COMException: + real_cid = None + if real_cid: + self.__dict__['_object_name_'] = real_cid + contractid_info = contractid_info_cache.get(real_cid) + else: + contractid_info = None + if contractid_info is None: + try: + interface_infos = classinfo.getInterfaces() + except COMException: + interface_infos = [] + for nominated_iid in interface_infos: + # Interface may appear twice in the class info list, so check this here. + if nominated_iid not in self.__dict__['_interface_infos_']: + # Just invoke our QI on the object + self.queryInterface(nominated_iid) + if real_cid is not None: + contractid_info = {} + 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: + for key, val in list(contractid_info.items()): + self.__dict__[key].update(val) + + self.__dict__['_com_classinfo_'] = classinfo + + def _remember_interface_info(self, iid): + # 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 iid not in iis, "Already remembered this interface!" + try: + method_infos, getters, setters, constants = BuildInterfaceInfo(iid) + except COMException as 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 + + # 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 list(method_infos.keys()): names[name] = iid + for name in list(getters.keys()): names[name] = iid + for name in list(setters.keys()): names[name] = iid + for name in list(constants.keys()): names[name] = iid + + def QueryInterface(self, iid): + if iid in self._interfaces_: + assert iid.name in self._interface_names_, "_interfaces_ has the key, but _interface_names_ does not!" + return self + # Haven't seen this before - do a real QI. + if iid not in self._interface_infos_: + self._remember_interface_info(iid) + 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. + + def __getattr__(self, attr): + if attr in _special_getattr_names: + raise AttributeError(attr) + # First allow the interface name to return the "raw" interface + interface = self.__dict__['_interface_names_'].get(attr, None) + if interface is not None: + return interface + # 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 iid is None and not self._tried_classinfo_: + self._build_all_supported_interfaces_() + 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: + self.QueryInterface(iid) + 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 list(self.__dict__['_interfaces_'].values()): + try: + ret = getattr(interface, attr) + 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): + iid = self._name_to_interface_iid_.get(attr, None) + # This may be first time trying this interface - get the nsIClassInfo + if iid is None and not self._tried_classinfo_: + self._build_all_supported_interfaces_() + 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: + self.QueryInterface(iid) + interface = self.__dict__['_interfaces_'][iid] + setattr(interface, attr, val) + return + raise AttributeError("XPCOM component '%s' has no attribute '%s'" % (self._object_name_, attr)) + + def _get_classinfo_repr_(self): + try: + if not self._tried_classinfo_: + self._build_all_supported_interfaces_() + assert self._tried_classinfo_, "Should have tried the class info by now!" + except COMException: + # Error building the info - ignore the error, but ensure that + # 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 + + iface_names = list(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): + self.__dict__['_comobj_'] = comobj + self.__dict__['_iid_'] = iid + self.__dict__['_property_getters_'] = getters + self.__dict__['_property_setters_'] = setters + self.__dict__['_method_infos_'] = method_infos # method infos waiting to be turned into real methods. + self.__dict__['_methods_'] = {} # unbound methods + self.__dict__['_object_name_'] = iid.name + self.__dict__.update(constants) + # We remember the constant names to prevent the user trying to assign to them! + self.__dict__['_constant_names_'] = list(constants.keys()) + + def __getattr__(self, attr): + # Allow the underlying interface to provide a better implementation if desired. + if attr in _special_getattr_names: + raise AttributeError(attr) + + ret = getattr(self.__dict__['_comobj_'], attr, None) + if ret is not None: + return ret + # Do the function thing first. + unbound_method = self.__dict__['_methods_'].get(attr, None) + if unbound_method is not None: + return MethodType(unbound_method, self) + + getters = self.__dict__['_property_getters_'] + info = getters.get(attr) + if info is not None: + method_index, param_infos = info + 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._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. + method_info = self.__dict__['_method_infos_'].get(attr, None) + if method_info is not None: + unbound_method = BuildMethod(method_info, self._iid_) + # Cache it locally + self.__dict__['_methods_'][attr] = unbound_method + return MethodType(unbound_method, self) + + raise AttributeError("XPCOM component '%s' has no attribute '%s'" % (self._object_name_, attr)) + + def __setattr__(self, attr, val): + # If we already have a __dict__ item of that name, and its not one of + # our constants, we just directly set it, and leave. + if attr in self.__dict__ and attr not in self.__dict__['_constant_names_']: + self.__dict__[attr] = val + return + # Start sniffing for what sort of attribute this might be? + setters = self.__dict__['_property_setters_'] + info = setters.get(attr) + if info is None: + raise AttributeError("XPCOM component '%s' can not set attribute '%s'" % (self._object_name_, attr)) + method_index, param_infos = info + 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._comobj_, method_index, real_param_infos) + + def __repr__(self): + return "<XPCOM interface '%s'>" % (self._object_name_,) + + +# Called by the _xpcom C++ framework to wrap interfaces up just +# before they are returned. +def MakeInterfaceResult(ob, iid): + return Component(ob, iid) + +class WeakReference: + """A weak-reference object. You construct a weak reference by passing + any COM object you like. If the object does not support weak + refs, you will get a standard NS_NOINTERFACE exception. + + Once you have a weak-reference, you can "call" the object to get + back a strong reference. Eg: + + >>> 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 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, + or else you defeat the purpose of the weak-reference. + """ + def __init__(self, ob, iid = None): + swr = Component(ob._comobj_, IID_nsISupportsWeakReference) + self._comobj_ = Component(swr.GetWeakReference()._comobj_, IID_nsIWeakReference) + if iid is None: + try: + iid = ob.IID + except AttributeError: + iid = IID_nsISupports + self._iid_ = iid + def __call__(self, iid = None): + if iid is None: iid = self._iid_ + try: + return Component(self._comobj_.QueryReferent(iid)._comobj_, iid) + except COMException as details: + if details.errno != nsError.NS_ERROR_NULL_POINTER: + raise + return None diff --git a/src/libs/xpcom18a4/python/components.py b/src/libs/xpcom18a4/python/components.py new file mode 100755 index 00000000..b0910f87 --- /dev/null +++ b/src/libs/xpcom18a4/python/components.py @@ -0,0 +1,248 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# ActiveState Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000, 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Hammond <MarkH@ActiveState.com> (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 ***** + +# This module provides the JavaScript "components" interface +from . import xpt +import xpcom +import xpcom._xpcom as _xpcom +import xpcom.client +import xpcom.server + +StringTypes = [bytes, str] + +def _get_good_iid(iid): + if iid is None: + iid = _xpcom.IID_nsISupports + elif type(iid) in StringTypes and len(iid)>0 and iid[0] != "{": + iid = getattr(interfaces, iid) + return iid + +# The "manager" object. +manager = xpcom.client.Component(_xpcom.GetComponentManager(), _xpcom.IID_nsIComponentManager) + +# The component registrar +registrar = xpcom.client.Component(_xpcom.GetComponentManager(), _xpcom.IID_nsIComponentRegistrar) + +# The "interfaceInfoManager" object - JS doesnt have this. +interfaceInfoManager = _xpcom.XPTI_GetInterfaceInfoManager() + +# The serviceManager - JS doesnt have this either! +serviceManager = _xpcom.GetServiceManager() + +# The "Exception" object +Exception = xpcom.COMException + +# Base class for our collections. +# It appears that all objects supports "." and "[]" notation. +# eg, "interface.nsISupports" or interfaces["nsISupports"] +class _ComponentCollection: + # Bases are to over-ride 2 methods. + # _get_one(self, name) - to return one object by name + # _build_dict - to return a dictionary which provide access into + def __init__(self): + self._dict_data = None + def keys(self): + if self._dict_data is None: + self._dict_data = self._build_dict() + return list(self._dict_data.keys()) + def items(self): + if self._dict_data is None: + self._dict_data = self._build_dict() + return list(self._dict_data.items()) + def values(self): + if self._dict_data is None: + self._dict_data = self._build_dict() + return list(self._dict_data.values()) +# def has_key(self, key): +# if self._dict_data is None: +# self._dict_data = self._build_dict() +# return self._dict_data.has_key(key) + + def __len__(self): + if self._dict_data is None: + self._dict_data = self._build_dict() + return len(self._dict_data) + + def __getattr__(self, attr): + if self._dict_data is not None and attr in self._dict_data: + return self._dict_data[attr] + return self._get_one(attr) + def __getitem__(self, item): + if self._dict_data is not None and item in self._dict_data: + return self._dict_data[item] + return self._get_one(item) + +_constants_by_iid_map = {} + +class _Interface: + # An interface object. + def __init__(self, name, iid): + # Bypass self.__setattr__ when initializing attributes. + d = self.__dict__ + d['_iidobj_'] = iid # Allows the C++ framework to treat this as a native IID. + d['name'] = name + def __cmp__(self, other): + this_iid = self._iidobj_ + other_iid = getattr(other, "_iidobj_", other) + return cmp(this_iid, other_iid) + def __eq__(self, other): + this_iid = self._iidobj_ + other_iid = getattr(other, "_iidobj_", other) + return this_iid == other_iid + def __hash__(self): + return hash(self._iidobj_) + def __str__(self): + return str(self._iidobj_) + def __getitem__(self, item): + raise TypeError("components.interface objects are not subscriptable") + def __setitem__(self, item, value): + raise TypeError("components.interface objects are not subscriptable") + def __setattr__(self, attr, value): + raise AttributeError("Can not set attributes on components.Interface objects") + def __getattr__(self, attr): + # Support constants as attributes. + c = _constants_by_iid_map.get(self._iidobj_) + if c is None: + c = {} + i = xpt.Interface(self._iidobj_) + for c_ob in i.constants: + c[c_ob.name] = c_ob.value + _constants_by_iid_map[self._iidobj_] = c + if attr in c: + return c[attr] + raise AttributeError("'%s' interfaces do not define a constant '%s'" % (self.name, attr)) + + +class _Interfaces(_ComponentCollection): + def _get_one(self, name): + try: + item = interfaceInfoManager.GetInfoForName(name) + except xpcom.COMException as why: + # Present a better exception message, and give a more useful error code. + from . import nsError + raise xpcom.COMException(nsError.NS_ERROR_NO_INTERFACE, "The interface '%s' does not exist" % (name,)) + return _Interface(item.GetName(), item.GetIID()) + + def _build_dict(self): + ret = {} + enum = interfaceInfoManager.EnumerateInterfaces() + while not enum.IsDone(): + # Call the Python-specific FetchBlock, to keep the loop in C. + items = enum.FetchBlock(500, _xpcom.IID_nsIInterfaceInfo) + # This shouldnt be necessary, but appears to be so! + for item in items: + ret[item.GetName()] = _Interface(item.GetName(), item.GetIID()) + return ret + +# And the actual object people use. +interfaces = _Interfaces() + +del _Interfaces # Keep our namespace clean. + +################################################# +class _Class: + def __init__(self, contractid): + self.contractid = contractid + def __getattr__(self, attr): + if attr == "clsid": + rc = registrar.contractIDToCID(self.contractid) + # stash it away - it can never change! + self.clsid = rc + return rc + raise AttributeError("%s class has no attribute '%s'" % (self.contractid, attr)) + def createInstance(self, iid = None): + import xpcom.client + try: + return xpcom.client.Component(self.contractid, _get_good_iid(iid)) + except xpcom.COMException as details: + from . import nsError + # Handle "no such component" in a cleaner way for the user. + if details.errno == nsError.NS_ERROR_FACTORY_NOT_REGISTERED: + raise xpcom.COMException(details.errno, "No such component '%s'" % (self.contractid,)) + raise # Any other exception reraise. + def getService(self, iid = None): + return serviceManager.getServiceByContractID(self.contractid, _get_good_iid(iid)) + +class _Classes(_ComponentCollection): + def __init__(self): + _ComponentCollection.__init__(self) + def _get_one(self, name): + # XXX - Need to check the contractid is valid! + return _Class(name) + + def _build_dict(self): + ret = {} + enum = registrar.enumerateContractIDs() + while enum.hasMoreElements(): + # Call the Python-specific FetchBlock, to keep the loop in C. + items = enum.fetchBlock(2000, _xpcom.IID_nsISupportsCString) + for item in items: + name = str(item.data) + ret[name] = _Class(name) + return ret + +classes = _Classes() + +del _Classes + +del _ComponentCollection + +# The ID function +ID = _xpcom.ID + +# A helper to cleanup our namespace as xpcom shuts down. +class _ShutdownObserver: + _com_interfaces_ = interfaces.nsIObserver + def observe(self, service, topic, extra): + global manager, registrar, classes, interfaces, interfaceInfoManager, _shutdownObserver, serviceManager, _constants_by_iid_map + manager = registrar = classes = interfaces = interfaceInfoManager = _shutdownObserver = serviceManager = _constants_by_iid_map = None + xpcom.client._shutdown() + xpcom.server._shutdown() + def _query_interface_(self, iid): # VBox: Needed so that the interface check in the DefaultPolicy initialization will pass; @bugref{10079}. + if iid == interfaces.nsIObserver: + return 1 + return None + +svc = _xpcom.GetServiceManager().getServiceByContractID("@mozilla.org/observer-service;1", interfaces.nsIObserverService) +# Observers will be QI'd for a weak-reference, so we must keep the +# observer alive ourself, and must keep the COM object alive, +# _not_ just the Python instance!!! +_shutdownObserver = xpcom.server.WrapObject(_ShutdownObserver(), interfaces.nsIObserver) +# Say we want a weak ref due to an assertion failing. If this is fixed, we can pass 0, +# and remove the lifetime hacks above! See http://bugzilla.mozilla.org/show_bug.cgi?id=99163 +svc.addObserver(_shutdownObserver, "xpcom-shutdown", 1) +del svc, _ShutdownObserver diff --git a/src/libs/xpcom18a4/python/doc/advanced.html b/src/libs/xpcom18a4/python/doc/advanced.html new file mode 100644 index 00000000..ab6994fc --- /dev/null +++ b/src/libs/xpcom18a4/python/doc/advanced.html @@ -0,0 +1,176 @@ +<html> +<!-- ***** 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 PyXPCOM. + - + - The Initial Developer of the Original Code is + - ActiveState Tool Corporation. + - Portions created by the Initial Developer are Copyright (C) 2000-2001 + - the Initial Developer. All Rights Reserved. + - + - Contributor(s): + - + - 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 LGPL or the GPL. 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 ***** --> + +<head> +<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> +<meta name="GENERATOR" content="Microsoft FrontPage 4.0"> +<meta name="ProgId" content="FrontPage.Editor.Document"> +<title>Python XPCOM Advanced Topics</title> +</head> + +<body> + +<h1>Python XPCOM Advanced Topics</h1> + +<p>This document contains a series of tidbits that don't fit +anywhere else. As the Python XPCOM Package documentation matures, most of +these topics will have another home.</p> + +<h2>XPCOM Services</h2> +<p>An XPCOM service is simply a singleton registered by name. Python has +full support for both using and implementing XPCOM services. To use a +service, use <i>xpcom.components.services</i> just like the JavaScript +counterpart. There is nothing special about implementing a service in +Python; see the standard XPCOM documentation on services for more information.</p> + +<h2>nsIVariant</h2> + +<p>There is (almost) full support for <i>nsIVariant</i>. Any <i>nsIVariant</i> +parameters will automatically be translated to and from regular Python objects +giving, in effect, a multi-type parameter. This should be automatic, so +there is not much else to say! Note that if you really want, you can +create and pass your own <i>nsIVariant</i> object instead of a regular Python +object, thereby allowing explicit control over the type of variant created.</p> + +<h2>nsISupports Primitives.</h2> + +<p>There is a set of interfaces described in <i>nsISupportsPrimitives.idl</i>, which I +term collectively the <i>nsISupports Primitives Interfaces</i>. These +are a set of interfaces a component can support to allow automatic conversion to +and from many basic types. For example, an interface can define that it +supports the <i>nsISupportsCString</i> interface, and this could be used by any +program that wishes to get a string representation of the object. If an +interface wishes to expose itself as a "boolean value", it may choose +to support the <i>nsISupportsPRBool</i> interface.</p> +<p>When you call an XPCOM object (i.e., you have an XPCOM interface you are +calling), you can use +the builtin functions <i>str()</i>, <i>int()</i>, <i>long()</i> etc., on the +object<i>.</i> In the +case of <i>str()</i>, if the object does not support the <i>nsISupportsCString</i> +or <i>nsISupportsString</i> interfaces, the default string <i>str()</i> for the +object will be returned (i.e., what is normally returned for most XPCOM objects - +support for these interface is not very common!). In the case of the numeric functions, a <i>ValueError</i> +exception will be raised if the objects do not support any interface that can be +used for the conversion. <i>ValueError</i> is used instead of <i>TypeError</i>, +as the type itself (i.e., an XPCOM object) can sometimes be used in this context - +hence it is the specific <i>value</i> of the object that is the problem.</p> +<p>The use of <i>repr()</i> on an XPCOM interface object prevents support +attempts for these interfaces, and allows you to see the +"real" object, rather than what the object wants you to see!</p> +<p>When you implement an XPCOM object, you have two choices for implementation +of these interfaces:</p> +<ul> + <li>You can explicitly handle these interfaces like any other interface. + In this case, you have full control. However, if you + implement only one of these standard interfaces, then you are only + overriding the default behavior for that specific interface - all other + interfaces not explicitly listed in your class will still get the behavior + described below.<br> + </li> + <li>If your class does not define support for these interfaces, the framework + will use standard Python class semantics to implement them - i.e., if your + class provides a <i>__str__</i> method, it will be used to implement <i>nsISupportsCString</i> + and <i>nsISupportsString</i>, if you provide <i>__int__</i>, <i>__long__</i>, + <i>__float__</i> etc., methods, they will be used to implement the numeric + interfaces. If your class defines no such special methods, then the <i> + QueryInterface()</i> for those interfaces fails (rather than the QI succeeding + and the operation to fetch the data failing).</li> +</ul> +<blockquote> +<p>This allows for an interesting feature that would not normally be +possible. Consider Python code that does a <i>str()</i> on an XPCOM +interface, and where the XPCOM interface itself is implemented in Python and +provides a <i>__str__</i> method. The <i>str()</i> on the original +interface queries for the <i>nsISupportsCString</i> interface. The +Python implemented object responds to this interface and delegates to the <i>__str__</i> +method. At the end of all this, <i>str()</i> returns the same result +as if the objects were native Python objects with no XPCOM layer in between.</p> + +</blockquote> + +<h2>Enumerators</h2> + +<p>The primary enumerator used by XPCOM is <i>nsISimpleEnumerator</i>. +Although the Python XPCOM package has full support for <i>nsIEnumerator</i>, +since this interface is not "scriptable", you should avoided using it in interfaces +you design.</p> + +<p>When you use <i>nsISimpleEnumerator</i> from Python, the following enhancements +are available:</p> +<ul> + <li>The <i>GetNext()</i> method takes an optional IID as a parameter. If + this is specified, the returned object will be of this interface. This + prevents the manual <i>QueryInterface()</i> generally required from other + languages.</li> + <li>There is a <i>FetchBlock(num, [iid])</i> method, which fetches the + specified number of elements in one operation and returns a Python + list. This can be useful for large enumerator sets, so the loop + iterating the elements runs at full C++ speed.</li> +</ul> +<p><i>nsIEnumerator</i> has similar enhancements.</p> +<p>When implementing a Python XPCOM object, the Python class <i>xpcom.server.enumerator.SimpleEnumerator()</i> +can be used. You can pass a standard Python sequence (list, etc), and it +will be correctly wrapped in an <i>nsISimpleEnumerator</i> interface.</p> +<h2>Files</h2> +<p>The Python XPCOM package provides an <i> xpcom.file</i> module. This implements +a Python-like file object on top of the XPCOM/Mozilla stream interfaces. +When run from within the Mozilla environment, this allows you to open almost any +URL supported by Mozilla (including "chrome://" etc.,).</p> +<p>See this module for more information, including test code.</p> +<h2>XPCOM Object Identity</h2> +<p>XPCOM has defined rules for object identity and for how objects must behave +in their <i> QueryInterface()</i> implementations. The Python XPCOM framework +manages this for you; your code can return new Python instances etc., when +responding to new interfaces, and the framework itself will ensure the XPCOM +semantics are followed. Critically, the framework provides no mechanism +for breaking these rules.</p> +<h2>Policies</h2> +<p>The Python XPCOM framework has the concept of "policies" that +define how XPCOM semantics are mapped to Python objects. It is the policy +that implements delegation of <i> QueryInterface()</i>, translates property +references into direct property references, and failing that, "get_name" +and "set_name" calls, decides how to handle exceptions in the +component, and so on.</p> +<p>The default policy is very flexible and suitable for most purposes. +Indeed, the Komodo project has never had to implement a custom policy. +However, you should be aware the feature exists should you wish to do some +bizarre things, such as using Python as a bridge between XPCOM and some other +component technology.</p> + +</body> + +</html> diff --git a/src/libs/xpcom18a4/python/doc/architecture.html b/src/libs/xpcom18a4/python/doc/architecture.html new file mode 100644 index 00000000..d12a2a76 --- /dev/null +++ b/src/libs/xpcom18a4/python/doc/architecture.html @@ -0,0 +1,116 @@ +<html> +<!-- ***** 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 PyXPCOM. + - + - The Initial Developer of the Original Code is + - ActiveState Tool Corporation. + - Portions created by the Initial Developer are Copyright (C) 2000-2001 + - the Initial Developer. All Rights Reserved. + - + - Contributor(s): + - + - 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 LGPL or the GPL. 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 ***** --> + +<head> +<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> +<meta name="GENERATOR" content="Microsoft FrontPage 4.0"> +<meta name="ProgId" content="FrontPage.Editor.Document"> +<title>Architecture</title> +</head> + +<body> + +<h1>Python XPCOM Package Architecture</h1> +<h2><a name="Architecture">Architecture</a></h2> +<p>Much of the design for the Python XPCOM Package has been borrowed from the Python MS-COM +extensions in <i>win32com</i>. Most of the major limitations and drawbacks in the <i>win32com</i> +design have been addressed, mainly "auto-wrapping" of +interface objects, which is not supported by <i>win32com</i>.</p> +<p>Like <i>win32com</i>, this architecture includes the concept of <i>client COM</i> and <i>server +COM.</i> </p> +<p>Client COM:</p> +<ul> + <li>calls other interfaces</li> + <li>is supported by <i>PyInterfaces</i> implemented in C++, which assists +in making the COM calls</li> + <li>is supported by <i>PyGateways</i>, which assists in receiving +external COM calls and dispatching them to the correct Python object</li> + <li> is supported in the <i>xpcom/client</i> package</li> +</ul> +<p>Server COM:</p> +<ul> + <li>implements interfaces for use by other XPCOM applications or components</li> + <li> is +supported in the <i>xpcom/server</i> package</li> +</ul> +<p>The XPConnect framework is very powerful, and far exceeds what COM's <i> +IDispatch</i> can offer. Thus, we are able to get by with far fewer interfaces +supported in the C++ level, and defer most things to the Python code that uses +XPConnect. As a result, the requirement for a huge number of interfaces to +exist in the <i>.pyd</i> does not exist. There are, however, a number of +interfaces that do require native C++ support: these are interfaces +required to "boot" the XPConnect support (i.e., the interfaces that are +used to get information about interfaces), and also two gateways that need to +work without interface information available. This last requirement is +due to the XPCOM shutdown-ordering - it may be a bug, but is not an unreasonable +amount of code anyway.</p> +<p><b>Auto-wrapping</b> of COM objects is supported by both client COM and +server COM. For client COM, auto-wrapping means that the +Python programmer always sees Python "component" objects, rather than +raw C++ interface objects; to the user, it all appears to "just +work". This is a major source of frustration in the <i>win32com</i> +framework.</p> +<p>For server COM, auto-wrapping means that you can +pass Python instances wherever a COM object is expected. If the Python +instance supports COM interfaces, by virtue of having a <i>_com_interfaces_</i> +attribute that lists the interface requested, it will be automatically wrapped +in the correct COM object. </p> +<p><b>Error Handling:</b> The C++ framework has good error handling support, +and uses the XPCOM console service to log debug messages, Python exceptions and +tracebacks. <i>win32com</i> does not have good exception/traceback support +at the C++ level, mainly because COM does not define a service like +the console where debug messages can go. This does mean that in Mozilla +release builds, these debug messages are likely to be lost, but the <i>--console</i> +command line option to a release Mozilla will get them back. Therefore, +the other error-support utilities, such as the error callbacks made on the +policy object, may be used.</p> +<p><b>Component Loader, Modules and Factories:</b> XPCOM has the concept +of a component loader - a module used to load all components of a +particular type. For example, the <i>moz.jsloader.1</i> component loads all +the JavaScript components. Similarly, the <i>moz.pyloader.1</i> +component loads all Python components. However, unlike +JavaScript, the Python component loader is actually implemented in Python +itself! Since the Python component loader can not be used to load +itself, this component has some special code, <i>pyloader.dll,</i> to boot-strap itself.</p> +<p>This means is that all XPCOM components, including the Python loader itself and all +XPCOM module and factory interfaces, are implemented in +Python. <b>There are no components or interfaces implemented purely in C++ +in this entire package!</b></p> + +</body> + +</html> diff --git a/src/libs/xpcom18a4/python/doc/configure.html b/src/libs/xpcom18a4/python/doc/configure.html new file mode 100644 index 00000000..e2b5d416 --- /dev/null +++ b/src/libs/xpcom18a4/python/doc/configure.html @@ -0,0 +1,196 @@ +<html> +<!-- ***** 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 PyXPCOM. + - + - The Initial Developer of the Original Code is + - ActiveState Tool Corporation. + - Portions created by the Initial Developer are Copyright (C) 2000-2001 + - the Initial Developer. All Rights Reserved. + - + - Contributor(s): + - + - 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 LGPL or the GPL. 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 ***** --> + +<head> +<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> +<meta name="GENERATOR" content="Microsoft FrontPage 4.0"> +<meta name="ProgId" content="FrontPage.Editor.Document"> +<title>Configuring your Environment</title> +</head> + +<body> + +<h1>Building, Configuring and Testing Python XPCOM Package</h1> +<p>This document attempts to explain how to build, configure and test the +Python XPCOM Package. This document assumes you have already successfully +built +Mozilla from source and your environment is currently set up for such a build - +see the <a href="http://www.mozilla.org/build/">Mozilla build documentation</a> +for more information.</p> +<p>PyXPCOM can be built on Windows using either the <i>nmake makefile.win</i> +process, or the <i>configure; gmake</i> process used by Linux.</p> +<h2>configure; gmake Instructions</h2> +<h3>Preparing for the build</h3> +<ul> + <li>Apply the patch in <a href="http://bugzilla.mozilla.org/show_bug.cgi?id=129216">bugzilla + bug 129216</a>. (If this bug is marked as "FIXED", it probably + means there is no need to apply the patch and that these docs are out of + date)</li> + <li>On Linux, you must have Python built for dynamic linking. <a href="http://aspn.activestate.com/ASPN/Python">ActivePython</a> + 2.1 is one such build.</li> + <li>On Windows, you must have a Python source tree installed and built. + Patches gratefully accepted that allow an installed Python to be used (it + should not be hard!)</li> + <li>Ensure the Python interpreter you wish to use is on your path, such that + "python" will execute it correctly. The configure process + uses this to locate the Python support files.</li> +</ul> +<h3>Building</h3> +<ul> + <li>From the top-level Mozilla directory, execute <i>./configure + --enable-extensions=python/xpcom</i>. As per the Mozilla build + instructions, you may add this option to your <i>.mozconfig</i> file. + If you wish to enable debugging, just enable it as you would normally for + Mozilla; PyXPCOM will pick up the same settings.<br> + (On Windows you will need to execute <i>sh ./configure ...</i> if running + from a Command Prompt. See the <a href="http://www.mozilla.org/build/win32.html#ss2.2b">Mozilla + win32 specific gmake build instructions</a> for more details.</li> + <li>Build the Mozilla tree as normal; PyXPCOM will automatically be + built. Alternatively, change to the top-level PyXPCOM directory and + execute <i>gmake</i> in that directory.</li> +</ul> +<h2>PyXPCOM outside Mozilla</h2> +<p>When you are using PyXPCOM from inside mozilla, no additional configuration +options should be necessary. However, if you wish to use PyXPCOM from +stand-alone Python (ie, so you can write simple Python scripts that can be +executed normally and use XPCOM), then additional environment variables must be +setup.</p> +<ul> + <li><a name="PYTHONPATH"><b>PYTHONPATH</b></a> - <tt>PYTHONPATH</tt> needs to + be set appropriately. You must manually ensure that the <i>mozilla/dist/bin/python</i> + directory (which is where PyXPCOM was installed during the build process) is + listed. Note that when PyXPCOM is used from within Mozilla (or any + other xpcom process), this path will automatically be added to sys.path. + It is only when Python directly uses xpcom that this step is necessary.<br> + If anything is wrong here you should get a normal <tt>ImportError</tt>.</li> +</ul> +<blockquote> + <p>Note that on Windows, the PYTHONPATH is generally maintained in the + Registry; however, you can set this variable at a DOS prompt, and it will still be +added to the core PYTHONPATH. +</blockquote> +<ul> + <li><b><a name="PATH">PATH</a>, LD_LIBRARY_PATH, etc</b> - On Windows, you + must ensure that the Mozilla bin directory is listed on your PATH, or that + you execute your scripts with the Mozilla bin directory as the current + directory.<br> + On Linux, you must set your PATH and LD_LIBRARY_PATH variables + appropriately. However, you may find it simpler and easier to use the <i>run-mozilla.sh</i> + script in the Mozilla bin directory. For example, changing to the + Mozilla bin directory and executing:<br> + <i>./run-mozilla.sh python ~/src/mozilla/extensions/python/xpcom/test/regrtest.py</i><br> + should setup a correct environment and execute the PyXPCOM test suite.</li> +</ul> +<h2><a name="RunningTheTests">Testing your Setup</a></h2> +<p>The Python XPCOM Package has a complete test suite.</p> +<p>In the rest of this section, we walk through some simpler tests a step at a time, +to help diagnose any problems.</p> +<p><b>Note:</b> We recommend you do all your testing outside of <i> mozilla.exe</i>; it is far simpler to test all of +this using the PyXPCOM package stand-alone.</p> +<p><b>Note:</b> On Windows, if you use a debug build of Mozilla (i.e., in <i>dist\WIN32_D.OBJ\bin)</i>, + you <b>must</b> use <i>python_d.exe</i>; if you use a release build (i.e., in + a <i>dist\WIN32_O.OBJ\bin</i> directory), you must use <i>python.exe</i>. +<i>makefile.stupid.win</i> handles this automatically.</p> +<p>To test your setup:</p> +<ol> + <li>Start Python, and check<br> + >>> <i>import xpcom</i><br> + works. If not, <a href="#PYTHONPATH">check your PYTHONPATH</a> - the + main PyXPCOM package can not be located. Also check your <a href="#PATH">PATH</a>, + and if you are on Linux, remember that executing ./run-mozilla.sh python is + the easiest way.</li> + <li>Check<i><br> + >>> import xpcom._xpcom</i><br> + +works. If not, then most likely your <a href="#PATH">Mozilla + directory is not on your path</a>, or something is wrong with <i>_xpcom(_d).pyd/_xpcommodule.so</i>.</li> + + <li>Next run a simple test: <i>test/test_misc.py</i>. With a Windows debug build, the command may look like:<br> + <i>C:\Anywhere> python_d \src\python\xpcom\test\test_misc.py<br> + </i>or on Linux<br> + <i>/home/user/src/mozilla/dist/bin$ python /home/user/src/python/xpcom/test/test_misc.py</i></li> +</ol> +<p>If you can't get this going, you won't get much further! (You may see a few +errors - that is OK, as long as it appears something worked!). If +everything looks OK, the +next step is to register our test component and run our full test suite.</p> +<h2><a name="Registration">Registering the Loader and Test Component</a></h2> +<p>First register the generic Python loader. For instructions, see the <a href="file:///F:/src/as/Komodo/src/pyxpcom/xpcom/doc/architecture.html">architecture +document</a>. Do this only once, regardless of how many +Python components you have. Then install the test component itself, and +finally you can test it!</p> +<h3>Registering the Python Loader and Component</h3> +<p>To register the Python Loader and Component:</p> +<ol> + <li>Ensure the build process has put <i>pyloader.dll </i>(or <i>modpyloader.so</i> + for Unix), and the files <i> py_test_component.py </i> and <i> py_test_component.idl</i> into + the Mozilla <i>bin/components</i> directory. If not, copy the files + there manually.</li> + <li>Run <i>regxpcom </i>(or .<i>/run-mozilla.sh ./regxpcom</i> if appropriate). <i>regxpcom</i> is a standard Mozilla + executable, found in the <i>bin</i> directory, that detects the new DLL and + .py + files and registers them accordingly. You should + see a few messages that include the following:</li> +</ol> +<blockquote> + <pre>Registering: PythonComponentLoader +Registered 1 Python components in pyloader.dll +nsNativeComponentLoader: autoregistering succeeded +Auto-registering all Python components in F:\src\mozilla\dist\WIN32_D.OBJ\bin\components +Registering: PythonTestComponent +Registered 1 Python components in py_test_component.py</pre> +</blockquote> +<p>If so (or you see no message at all), you are ready to run the test suite.</p> +<p><b>Note</b>: If you execute this same step a second time, you will not +see any of the above mentioned messages. XPCOM knows that nothing has +changed since you last ran <i>regxpcom</i>, so nothing is registered. If +you do not see these messages the first time you run it, there is the +possibility that some other process, possibly the build process, has already +executed this step.</p> +<h2><b>Running the Test Suite</b></h2> +<p>Before running the test suite, you should change to the <i>mozilla/xpcom/sample</i> +directory and build it. This will build and install a sample component +which is used by the test suite. If you do not have this component +available, some of the Python tests will fail.</p> + +<p>To run the test suite, run <i>xpcom/test/regrtest.py.</i> This runs the +tests and ensures that the test output is as expected. If all tests +pass, you have a fully functioning Python XPCOM package. Enjoy!</p> + +</body> + +</html> diff --git a/src/libs/xpcom18a4/python/doc/credits.html b/src/libs/xpcom18a4/python/doc/credits.html new file mode 100644 index 00000000..2be7809f --- /dev/null +++ b/src/libs/xpcom18a4/python/doc/credits.html @@ -0,0 +1,86 @@ +<html> +<!-- ***** 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 PyXPCOM. + - + - The Initial Developer of the Original Code is + - ActiveState Tool Corporation. + - Portions created by the Initial Developer are Copyright (C) 2000-2001 + - the Initial Developer. All Rights Reserved. + - + - Contributor(s): + - + - 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 LGPL or the GPL. 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 ***** --> + +<head> +<meta http-equiv="Content-Language" content="en-au"> +<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> +<meta name="GENERATOR" content="Microsoft FrontPage 4.0"> +<meta name="ProgId" content="FrontPage.Editor.Document"> +<title>Credits and Acknowledgements</title> +</head> + +<body> + +<h1>Credits and Acknowledgements</h1> +<h2>ActiveState Tool Corporation</h2> +<p>The Python XPCOM Package was developed primarily by <a href="mailto:markh@activestate.com">Mark +Hammond</a> of <a href="http://www.ActiveState.com">ActiveState Tool Corporation</a>.</p> +<p>The developers on the <a href="http://www.ActiveState.com/Products/Komodo">Komodo +project</a> deserve high praise for putting up with early versions when almost +nothing worked, and for believing in Python as a viable XPCOM language. +Their feedback and patience has allowed the first public release to be amazingly +functional and bug-free.</p> +<h3>Komodo Development Team (at December 2000)</h3> +<p><a href="mailto:davida@activestate.com">David Ascher</a>, <a href="mailto:aaronb@ActiveState.com">Aaron Bingham</a>, +<a href="mailto:bindu@activestate.com">Bin Du</a>, <a href="mailto:markh@activestate.com">Mark +Hammond</a>, <a href="mailto:trentm@activestate.com">Trent Mick (build god)</a>, +<a href="mailto:paulp@activestate.com">Paul Prescod</a>, <a href="mailto:ericp@ActiveState.com">Eric Promislow</a>, +<a href="mailto:kens@ActiveState.com">Ken Simpson</a>, <a href="mailto:neilw@ActiveState.com">Neil Watkiss</a>, +<a href="mailto:AudreyS@ActiveState.com">Audrey Schumacher</a>.</p> +<h2>Mozilla/Netscape</h2> +<p>The following people at <a href="http://www.netscape.com">Netscape</a> and <a href="http://www.mozilla.org">Mozilla</a> +(or not there but still heavily involved in the project) have provided enormous +help in getting things integrated with their build system, answering us on the +newsgroup, teaching us the finer points of XPCOM, gently slapping us for accidentally +referring to <i>jscript</i>, etc., and otherwise lending us a clue in the +Mozilla/Netscape/XPCOM world.</p> +<p><a href="mailto:jband@netscape.com">John Bandhauer</a>, <a href="mailto:brendan@meer.net">Brendan +Eich</a>, <a href="mailto:shaver@zeroknowledge.com">Mike Shaver</a>, <a href="mailto:evaughan@netscape.com">Eric Vaughan</a>, +<a href="mailto:hyatt@netscape.com">David Hyatt</a></p> +<h2>External Contributors</h2> +<p>The following people have made contributions to the project, simply because +they find it useful and enjoy supporting Open Source projects.</p> +<p><a href="mailto:cmeerw@web.de">Christof Meerwald</a></p> +<h2>Documentation Credits</h2> +<p>The following people have contributed to the Python XPCOM Package +documentation </p> +<p><a href="mailto:markh@activestate.com">Mark +Hammond</a>, <a href="mailto:AudreyS@ActiveState.com">Audrey Schumacher</a></p> + +</body> + +</html> diff --git a/src/libs/xpcom18a4/python/doc/tutorial.html b/src/libs/xpcom18a4/python/doc/tutorial.html new file mode 100644 index 00000000..808d4c06 --- /dev/null +++ b/src/libs/xpcom18a4/python/doc/tutorial.html @@ -0,0 +1,286 @@ +<html> +<!-- ***** 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 PyXPCOM. + - + - The Initial Developer of the Original Code is + - ActiveState Tool Corporation. + - Portions created by the Initial Developer are Copyright (C) 2000-2001 + - the Initial Developer. All Rights Reserved. + - + - Contributor(s): + - + - 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 LGPL or the GPL. 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 ***** --> + +<head> +<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> +<meta name="GENERATOR" content="Microsoft FrontPage 4.0"> +<meta name="ProgId" content="FrontPage.Editor.Document"> +<title>Python XPCOM Package Tutorial</title> +</head> + +<body> + +<h1>Python XPCOM Package Tutorial</h1> +<p>This is a quick introduction to the Python XPCOM Package. We assume that you have a good understanding of Python and <a href="http://www.mozilla.org/projects/xpcom/">XPCOM</a>, +and have experience both using and implementing XPCOM objects in some other +language (e.g., C++ or JavaScript). We <b><i>do not</i></b> attempt to +provide a tutorial to XPCOM or Python itself, only to using Python <i>and</i> + XPCOM.</p> +<p>This tutorial contains the following sections:</p> +<ul> + <li><a href="#Using">Using XPCOM Objects and Interfaces</a> - when you wish to + <i>use</i> a component written by anyone else in any XPCOM supported + language.</li> + <li><a href="#Implementing">Implementing XPCOM Objects and Interfaces</a> - + when you wish to implement a component for use by anyone else in any xpcom + supported language.</li> + <li><a href="#Parameters">Parameters and Types</a> - useful information + regarding how Python translates XPCOM types, and handles byref parameters.</li> +</ul> +<p>For anything not covered here, try the <a href="advanced.html">advanced +documentation</a>, and if that fails, use the source, Luke!</p> +<h2><a name="Using">Using XPCOM object and interfaces.</a></h2> +<p>The techniques for using XPCOM in Python have been borrowed from JavaScript - +thus, the model described here should be quite familiar to existing JavaScript +XPCOM programmers.</p> +<h3>xpcom.components module</h3> +<p>When using an XPCOM object, the primary module used is the <u><i>xpcom.components</i></u> + module. Using this module, you can get a Python object that supports any +scriptable XPCOM interface. Once you have this Python object, you can +simply call XPCOM methods on the object, as normal.</p> +<p>The <u><i>xpcom.components</i></u> module defines the following public +members:</p> +<table border="1" width="100%"> + <tr> + <td width="16%"><b>Name</b></td> + <td width="84%"><b>Description</b></td> + </tr> + <tr> + <td width="16%">classes</td> + <td width="84%">A mapping (dictionary-like object) used to get XPCOM + "classes". These are indexed by XPCOM contract ID, just + like the JavaScript object of the same name. + <p>Example:</p> + <pre>cls = components.classes["@mozilla.org/sample;1"] +ob = cls.createInstance() # Now have an nsISupports</pre> + </td> + </tr> + <tr> + <td width="16%">interfaces</td> + <td width="84%">An object that exposes all XPCOM interface IDs (IIDs). + Like the JavaScript object of the same name, this object uses + "dot" notation, as demonstrated below. + <p>Example:</p> + <pre>ob = cls.createInstance(components.interfaces.nsISample) +# Now have an nsISample</pre> + </td> + </tr> +</table> +<p>For many people, this is all you need to know. Consider the Mozilla Sample Component. The Mozilla Sample +Component has a contract ID of <i>@mozilla.org/sample;1</i>, +and implements the <i>nsISample</i> interface.</p> +<p>Thus, a complete Python program that uses this component is shown below.</p> +<pre>from xpcom import components +cls = components.classes["@mozilla.org/sample;1"] +ob = cls.createInstance() # no need to specify an IID for most components +# nsISample defines a "value" property - let's use it! +ob.value = "new value" +if ob.value != "new value": + print "Eeek - what happened?"</pre> +<p>And that is it - a complete Python program that uses XPCOM.</p> +<h2><a name="Implementing">Implementing XPCOM Objects and Interfaces.</a></h2> +<p>Implementing XPCOM objects is almost as simple as using them. The +basic strategy is this:</p> +<ol> + <li>Create a standard Python source file, with a standard Python class.</li> + <li>Add some special <a href="#Attributes"> attributes</a> to your class for use by the Python XPCOM + framework. This controls the XPCOM behavior of your object.</li> + <li>Implement the XPCOM <a href="#Properties"> properties</a> and methods of your classes as normal.</li> + <li>Put the Python source file in the Mozilla <i> components</i> directory.</li> + <li>Run <i> regxpcom.</i></li> +</ol> +<p>Your component is now ready to be used.</p> +<h3><a name="Attributes">Attributes</a></h3> +<p>There are two classes of attributes: those used at runtime to define the object +behavior and those used at registration time to control object +registration. Not all objects require registration, thus not all +Python XPCOM objects will have registration-related attributes.</p> +<table border="1" width="100%"> + <tr> + <td width="17%"><b>Attribute</b></td> + <td width="83%"><b>Description</b></td> + </tr> + <tr> + <td width="17%">_com_interfaces_</td> + <td width="83%">The interface IDs (IIDs) supported by the component. + For simplicity, this may be either a single IID, or a list of IIDs. + There is no need to specify base interfaces, as all parent interfaces are + automatically supported. Thus, it is never necessary to nominate <i> + nsISupports</i> in the list of interfaces. + <p>This attribute is required. Objects without such an attribute are + deemed unsuitable for use as a XPCOM object.</td> + </tr> + <tr> + <td width="17%">_reg_contractid_</td> + <td width="83%">The contract ID of the component. Required if the + component requires registration (i.e., exists in the components directory).</td> + </tr> + <tr> + <td width="17%">_reg_clsid_</td> + <td width="83%">The Class ID (CLSID) of the component, as a string in the + standard "{XXX-XXX-XXX-XXX}" format. Required if the + component requires registration (i.e., exists in the components directory).</td> + </tr> + <tr> + <td width="17%">_reg_registrar_</td> + <td width="83%">Nominates a function that is called at registration + time. The default is for no extra function to be called. This can + be useful if a component has special registration requirements and needs + to hook into the registration process.</td> + </tr> + <tr> + <td width="17%">_reg_desc_</td> + <td width="83%">The description of the XPCOM object. This may be used by + browsers or other such objects. If not specified, the contract ID + is used.</td> + </tr> +</table> +<h3><a name="Properties">Properties</a></h3> +<p>A Python class can support XPCOM properties in one of two ways. Either +a standard Python property of the same name can exist - our sample +component demonstrates this with the <i>boolean_value</i> property. +Alternatively, the class can provide the <i>get_propertyName(self)</i> and <i>set_propertyName(self, +value)</i> functions (with <i>propertyName</i> changed to the appropriate value for the +property), and these functions will be called instead.</p> +<h4>Example: The Python XPCOM Test Component</h4> +<p>As an example, examine the Python XPCOM Test Component. This +code can be found in <i>py_test_component.py</i>.</p> +<pre>from xpcom import components + +class PythonTestComponent: + _com_interfaces_ = components.interfaces.nsIPythonTestInterface + _reg_clsid_ = "{7EE4BDC6-CB53-42c1-A9E4-616B8E012ABA}" + _reg_contractid_ = "Python.TestComponent" + def __init__(self): + self.boolean_value = 1 + ... + def do_boolean(self, p1, p2): + ret = p1 ^ p2 + return ret, not ret, ret +...</pre> +<p><b>Note:</b> This component only specifies the mandatory attributes - <i>_com_interfaces</i>, +<i>_reg_clsid_</i> and <i>_reg_contractid_</i>.</p> +<p>This sample code demonstrates supporting the <i>boolean_value</i> attribute, +supported implicitly, as it is defined in the IDL and exists as a real Python +attribute of that name, and a method called <i>do_boolean</i>.</p> +<h4>Tip: The xpcom/xpt.py Script</h4> +<p> The xpcom/xpt.py script is a useful script that can generate the skeleton of a class for +any XPCOM interface. Just specify the interface name on the command-line, +and paste the output into your source file.</p> +<p>This is the output of running this program over the <i>nsISample</i> +interface (i.e., assuming we wanted to implement a component that supported this +interface):</p> +<pre>class nsISample: + _com_interfaces_ = xpcom.components.interfaces.nsISample + # If this object needs to be registered, the following 2 are also needed. + # _reg_clsid_ = {a new clsid generated for this object} + # _reg_contractid_ = "The.Object.Name" + + def get_value( self ): + # Result: string + pass + def set_value( self, param0 ): + # Result: void - None + # In: param0: string + pass + def writeValue( self, param0 ): + # Result: void - None + # In: param0: string + pass + def poke( self, param0 ): + # Result: void - None + # In: param0: string + pass</pre> +<p><b>Note:</b> The types of the parameters and the function itself are included in +the comments. You need to implement the functions +themselves. Another advantage of this script is that the <a href="#HiddenParams">hidden +parameters</a> are handled for you; the comments indicate when parameters +have been hidden.</p> +<h2><a name="Parameters">Parameters and Types</a></h2> +<p>This section briefly describes the XPCOM type support in +Python.</p> +<p>All XPCOM interfaces define parameters of a specific type. There is +currently no concept of a variant, or union of all types. Thus, the +conversion rules are very straightforward, and generally surprise free: for +any given XPCOM method, there is only one possible type for a given parameter.</p> +<h3>Type Conversion Rules:</h3> +<ul> + <li>All numeric types will attempt to be coerced to the correct type. + Thus, you can pass a Python float to an XPCOM method expecting an integer, + or vice-versa. Specifically, when an integer is required, you can pass + any Python object for which <i>int()</i> would succeed; for a Python float, + any object for which <i>float()</i> would succeed is acceptable. This + means that you can pass a Python string object as an integer, as long as the + string was holding a valid integer.</li> + <li>Strings and Unicode objects are interchangeable, but no other automatic + string conversions are performed. Thus, you can not pass an integer + where a string is expected, even though the reverse is true.</li> + <li>Any sequence object can be passed as an array. List objects are + always returned for arrays.</li> + <li>Any Python instance suitable for use as a XPCOM object (i.e., with the + <a href="#Implementing">necessary annotations</a>) can be + passed as a XPCOM object. No special wrapping step is needed to turn a + Python instance into a XPCOM object. Note you must pass a class <i>instance</i>, + not the class itself.</li> + <li><a name="HiddenParams">Many XPCOM <b> method signatures</b> specify + "count" or "size" parameters. For example, every + time an array is passed via XPCOM, the method signature will always specify + an integer that holds the count of the array. These parameters are + always hidden in Python. As the size param can be implied from the + length of the Python sequence passed, the Python programmer need never pass + these parameters; in contrast, JavaScript requires these redundant parameters.</a></li> +</ul> + +<h2>Interface Flattening</h2> +<p>Most people can ignore this information - Python XPCOM objects just +work. However, if you are familiar with xpcom from C++ and the concept of <i>QueryInterface</i>, +you may like to read this.</p> +<p>Most components support the concept of "interface +flattening". Such objects can report the interfaces they support, +allowing languages such as Python and Javascript avoid using <i>QueryInterface</i>. +When you are using an XPCOM object from Python, you can just call methods and +reference properties without regard for the interface that implements it.</p> +<p>When multiple interfaces share the same method or property name, you can use +the name of the interface as a differentiator. Thus, <i>ob.nsIFoo.close()</i> +will call close on <i>ob</i>'s <i>nsIFoo</i> interface, while <i>ob.nsIBar.close()</i> +will use the <i>nsIBar</i> interface. <i>ob.close()</i> is not defined.</p> + +</body> + +</html> + + diff --git a/src/libs/xpcom18a4/python/file.py b/src/libs/xpcom18a4/python/file.py new file mode 100755 index 00000000..59b0da58 --- /dev/null +++ b/src/libs/xpcom18a4/python/file.py @@ -0,0 +1,318 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# ActiveState Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000, 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Hammond <MarkH@ActiveState.com> (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 ***** + +"""Implementation of Python file objects for Mozilla/xpcom. + +Introduction: + This module defines various class that are implemented using + Mozilla streams. This allows you to open Mozilla URI's, and + treat them as Python file object. + +Example: +>>> file = URIFile("chrome://whatever") +>>> data = file.read(5) # Pass no arg to read everything. + +Known Limitations: + * Not all URL schemes will work from "python.exe" - most notably + "chrome://" and "http://" URLs - this is because a simple initialization of + xpcom by Python does not load up the full set of Mozilla URL handlers. + If you can work out how to correctly initialize the chrome registry and + setup a message queue. + +Known Bugs: + * Only read ("r") mode is supported. Although write ("w") mode doesnt make + sense for HTTP type URLs, it potentially does for file:// etc type ones. + * No concept of text mode vs binary mode. It appears Mozilla takes care of + this internally (ie, all "text/???" mime types are text, rest are binary) + +""" + +from xpcom import components, Exception, _xpcom +import os +import threading # for locks. + +NS_RDONLY = 0x01 +NS_WRONLY = 0x02 +NS_RDWR = 0x04 +NS_CREATE_FILE = 0x08 +NS_APPEND = 0x10 +NS_TRUNCATE = 0x20 +NS_SYNC = 0x40 +NS_EXCL = 0x80 + +# A helper function that may come in useful +def LocalFileToURL(localFileName): + "Convert a filename to an XPCOM nsIFileURL object." + # Create an nsILocalFile + localFile = components.classes["@mozilla.org/file/local;1"] \ + .createInstance(components.interfaces.nsILocalFile) + localFile.initWithPath(localFileName) + + # Use the IO Service to create the interface, then QI for a FileURL + io_service = components.classes["@mozilla.org/network/io-service;1"] \ + .getService(components.interfaces.nsIIOService) + url = io_service.newFileURI(localFile).queryInterface(components.interfaces.nsIFileURL) + # Setting the "file" attribute causes initialization... + url.file = localFile + return url + +# A base class for file objects. +class _File: + def __init__(self, name_thingy = None, mode="r"): + self.lockob = threading.Lock() + self.inputStream = self.outputStream = None + if name_thingy is not None: + self.init(name_thingy, mode) + + def __del__(self): + self.close() + + # The Moz file streams are not thread safe. + def _lock(self): + self.lockob.acquire() + def _release(self): + self.lockob.release() + def read(self, n = -1): + assert self.inputStream is not None, "Not setup for read!" + self._lock() + try: + return str(self.inputStream.read(n)) + finally: + self._release() + + def readlines(self): + # Not part of the xpcom interface, but handy for direct Python users. + # Not 100% faithful, but near enough for now! + lines = self.read().split("\n") + if len(lines) and len(lines[-1]) == 0: + lines = lines[:-1] + return [s+"\n" for s in lines ] + + def write(self, data): + assert self.outputStream is not None, "Not setup for write!" + self._lock() + try: + self.outputStream.write(data, len(data)) + finally: + self._release() + + def close(self): + self._lock() + try: + if self.inputStream is not None: + self.inputStream.close() + self.inputStream = None + if self.outputStream is not None: + self.outputStream.close() + self.outputStream = None + self.channel = None + finally: + self._release() + + def flush(self): + self._lock() + try: + if self.outputStream is not None: self.outputStream.flush() + finally: + self._release() + +# A synchronous "file object" used to open a URI. +class URIFile(_File): + def init(self, url, mode="r"): + self.close() + if mode != "r": + raise ValueError("only 'r' mode supported") + io_service = components.classes["@mozilla.org/network/io-service;1"] \ + .getService(components.interfaces.nsIIOService) + if hasattr(url, "queryInterface"): + url_ob = url + else: + url_ob = io_service.newURI(url, None, None) + # Mozilla asserts and starts saying "NULL POINTER" if this is wrong! + if not url_ob.scheme: + raise ValueError("The URI '%s' is invalid (no scheme)" + % (url_ob.spec,)) + self.channel = io_service.newChannelFromURI(url_ob) + self.inputStream = self.channel.open() + +# A "file object" implemented using Netscape's native file support. +# Based on io.js - http://lxr.mozilla.org/seamonkey/source/xpcom/tests/utils/io.js +# You open this file using a local file name (as a string) so it really is pointless - +# you may as well be using a standard Python file object! +class LocalFile(_File): + def __init__(self, *args): + self.fileIO = None + _File.__init__(self, *args) + + def init(self, name, mode = "r"): + name = os.path.abspath(name) # Moz libraries under Linux fail with relative paths. + self.close() + file = components.classes['@mozilla.org/file/local;1'].createInstance("nsILocalFile") + file.initWithPath(name) + if mode in ["w","a"]: + self.fileIO = components.classes["@mozilla.org/network/file-output-stream;1"].createInstance("nsIFileOutputStream") + if mode== "w": + if file.exists(): + file.remove(0) + moz_mode = NS_CREATE_FILE | NS_WRONLY + elif mode=="a": + moz_mode = NS_APPEND + else: + assert 0, "Can't happen!" + self.fileIO.init(file, moz_mode, -1,0) + self.outputStream = self.fileIO + elif mode == "r": + self.fileIO = components.classes["@mozilla.org/network/file-input-stream;1"].createInstance("nsIFileInputStream") + self.fileIO.init(file, NS_RDONLY, -1,0) + self.inputStream = components.classes["@mozilla.org/scriptableinputstream;1"].createInstance("nsIScriptableInputStream") + self.inputStream.init(self.fileIO) + else: + raise ValueError("Unknown mode") + + def close(self): + if self.fileIO is not None: + self.fileIO.close() + self.fileIO = None + _File.close(self) + + def read(self, n = -1): + return _File.read(self, n) + + +########################################################## +## +## Test Code +## +########################################################## +def _DoTestRead(file, expected): + # read in a couple of chunks, just to test that our various arg combinations work. + got = file.read(3) + got = got + file.read(300) + got = got + file.read(0) + got = got + file.read() + if got != expected: + raise RuntimeError("Reading '%s' failed - got %d bytes, but expected %d bytes" % (file, len(got), len(expected))) + +def _DoTestBufferRead(file, expected): + # read in a couple of chunks, just to test that our various arg combinations work. + buffer = _xpcom.AllocateBuffer(50) + got = '' + while 1: + # Note - we need to reach into the file object so we + # can get at the native buffer supported function. + num = file.inputStream.read(buffer) + if num == 0: + break + got = got + str(buffer[:num]) + if got != expected: + raise RuntimeError("Reading '%s' failed - got %d bytes, but expected %d bytes" % (file, len(got), len(expected))) + +def _TestLocalFile(): + import tempfile, os + fname = tempfile.mktemp() + data = "Hello from Python" + test_file = LocalFile(fname, "w") + try: + test_file.write(data) + test_file.close() + # Make sure Python can read it OK. + f = open(fname, "r") + 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()) + assert got == data, got + test_file.close() + # Try reading in chunks. + test_file = LocalFile(fname, "r") + got = test_file.read(10) + test_file.read() + 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): + raise RuntimeError("The file '%s' does not exist, but we are explicitly testing create semantics when it does" % (fname,)) + test_file = LocalFile(fname, "w") + test_file.write(data) + test_file.close() + # Make sure Python can read it OK. + f = open(fname, "r") + 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: + os.unlink(fname) + +def _TestAll(): + # A mini test suite. + # Get a test file, and convert it to a file:// URI. + # check what we read is the same as when + # we read this file "normally" + fname = components.__file__ + if fname[-1] in "cCoO": # fix .pyc/.pyo + fname = fname[:-1] + expected = open(fname, "rb").read() + # convert the fname to a URI. + url = LocalFileToURL(fname) + # First try passing a URL as a string. + _DoTestRead( URIFile( url.spec), expected) + # Now with a URL object. + _DoTestRead( URIFile( url ), expected) + + _DoTestBufferRead( URIFile( url ), expected) + + # For the sake of testing, do our pointless, demo object! + _DoTestRead( LocalFile(fname), expected ) + + # Now do the full test of our pointless, demo object! + _TestLocalFile() + +def _TestURI(url): + test_file = URIFile(url) + print("Opened file is", test_file) + got = test_file.read() + print("Read %d bytes of data from %r" % (len(got), url)) + test_file.close() + +if __name__=='__main__': + import sys + if len(sys.argv) < 2: + print("No URL specified on command line - performing self-test") + _TestAll() + else: + _TestURI(sys.argv[1]) diff --git a/src/libs/xpcom18a4/python/gen_python_deps.py b/src/libs/xpcom18a4/python/gen_python_deps.py new file mode 100755 index 00000000..12fbb7ac --- /dev/null +++ b/src/libs/xpcom18a4/python/gen_python_deps.py @@ -0,0 +1,147 @@ +#!/usr/bin/python + +""" +Copyright (C) 2009-2022 Oracle and/or its affiliates. + +This file is part of VirtualBox base platform packages, as +available from https://www.virtualbox.org. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, in version 3 of the +License. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, see <https://www.gnu.org/licenses>. + +SPDX-License-Identifier: GPL-3.0-only +""" + +from __future__ import print_function +import os,sys +from distutils.version import StrictVersion + +versions = ["2.6", "2.7", "3.1", "3.2", "3.2m", "3.3", "3.3m", "3.4", "3.4m", "3.5", "3.5m", "3.6", "3.6m", "3.7", "3.7m", "3.8", "3.8m", "3.9", "3.9m", "3.10", "3.10m", "3.11", "3.11m" ] +prefixes = ["/usr", "/usr/local", "/opt", "/opt/local"] +known = {} + +def checkPair(p, v, dllpre, dllsuff, bitness_magic): + incdir = os.path.join(p, "include", "python"+v) + incfile = os.path.join(incdir, "Python.h") + if not os.path.isfile(incfile): + return None + + lib = os.path.join(p, "lib/i386-linux-gnu", dllpre+"python"+v+dllsuff) + if not os.path.isfile(lib): + lib = os.path.join(p, "lib", dllpre+"python"+v+dllsuff) + if not os.path.isfile(lib): + lib = None + + if bitness_magic == 1: + lib64 = os.path.join(p, "lib", "64", dllpre+"python"+v+dllsuff) + if not os.path.isfile(lib64): + lib64 = None + elif bitness_magic == 2: + lib64 = os.path.join(p, "lib/x86_64-linux-gnu", dllpre+"python"+v+dllsuff) + if not os.path.isfile(lib64): + lib64 = os.path.join(p, "lib64", dllpre+"python"+v+dllsuff) + if not os.path.isfile(lib64): + lib64 = os.path.join(p, "lib", dllpre+"python"+v+dllsuff) + if not os.path.isfile(lib64): + lib64 = None + else: + lib64 = None + + if lib is None and lib64 is None: + return None + else: + return [incdir, lib, lib64] + +def print_vars(vers, known, sep, bitness_magic): + print("VBOX_PYTHON%s_INC=%s%s" %(vers, known[0], sep)) + if bitness_magic > 0: + if known[2]: + print("VBOX_PYTHON%s_LIB=%s%s" %(vers, known[2], sep)) + if known[1]: + print("VBOX_PYTHON%s_LIB_X86=%s%s" %(vers, known[1], sep)) + else: + print("VBOX_PYTHON%s_LIB=%s%s" %(vers, known[1], sep)) + + +def main(argv): + global prefixes + global versions + + dllpre = "lib" + dllsuff = ".so" + bitness_magic = 0 + + if len(argv) > 1: + target = argv[1] + else: + target = sys.platform + + if len(argv) > 2: + arch = argv[2] + else: + arch = "unknown" + + if len(argv) > 3: + multi = int(argv[3]) + else: + multi = 1 + + if multi == 0: + prefixes = ["/usr"] + versions = [str(sys.version_info[0])+'.'+str(sys.version_info[1]), + str(sys.version_info[0])+'.'+str(sys.version_info[1])+'m'] + + if target == 'darwin': + ## @todo Pick up the locations from VBOX_PATH_MACOSX_SDK_10_*. + prefixes = ['/Developer/SDKs/MacOSX10.4u.sdk/usr', + '/Developer/SDKs/MacOSX10.5.sdk/usr', + '/Developer/SDKs/MacOSX10.6.sdk/usr', + '/Developer/SDKs/MacOSX10.7.sdk/usr'] + dllsuff = '.dylib' + + if target == 'solaris' and arch == 'amd64': + bitness_magic = 1 + + if target == 'linux' and arch == 'amd64': + bitness_magic = 2 + + for v in versions: + if v.endswith("m"): + realversion = v[:-1] + else: + realversion = v + if StrictVersion(realversion) < StrictVersion('2.6'): + continue + for p in prefixes: + c = checkPair(p, v, dllpre, dllsuff, bitness_magic) + if c is not None: + known[v] = c + break + keys = list(known.keys()) + # we want default to be the lowest versioned Python + keys.sort() + d = None + # We need separator other than newline, to sneak through $(shell) + sep = "|" + for k in keys: + if d is None: + d = k + vers = k.replace('.', '').upper() + print_vars(vers, known[k], sep, bitness_magic) + if d is not None: + print_vars("DEF", known[d], sep, bitness_magic) + else: + print(argv[0] + ": No Python development package found!", file=sys.stderr) + +if __name__ == '__main__': + main(sys.argv) diff --git a/src/libs/xpcom18a4/python/nsError.py b/src/libs/xpcom18a4/python/nsError.py new file mode 100755 index 00000000..af9cdbfd --- /dev/null +++ b/src/libs/xpcom18a4/python/nsError.py @@ -0,0 +1,166 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is ActiveState Tool Corp. +# Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 +# ActiveState Tool Corp. All Rights Reserved. +# +# Contributor(s): +# Mark Hammond <MarkH@ActiveState.com> (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 ***** + +# Generated by h2py from nsError.h +# CMD line: h2py.py -i (nsresult) nsError.h + +# XXX - NOTE - some manual code at the end, and all literals moved back to ints +NS_ERROR_MODULE_XPCOM = 1 +NS_ERROR_MODULE_BASE = 2 +NS_ERROR_MODULE_GFX = 3 +NS_ERROR_MODULE_WIDGET = 4 +NS_ERROR_MODULE_CALENDAR = 5 +NS_ERROR_MODULE_NETWORK = 6 +NS_ERROR_MODULE_PLUGINS = 7 +NS_ERROR_MODULE_LAYOUT = 8 +NS_ERROR_MODULE_HTMLPARSER = 9 +NS_ERROR_MODULE_RDF = 10 +NS_ERROR_MODULE_UCONV = 11 +NS_ERROR_MODULE_REG = 12 +NS_ERROR_MODULE_FILES = 13 +NS_ERROR_MODULE_DOM = 14 +NS_ERROR_MODULE_IMGLIB = 15 +NS_ERROR_MODULE_MAILNEWS = 16 +NS_ERROR_MODULE_EDITOR = 17 +NS_ERROR_MODULE_XPCONNECT = 18 +NS_ERROR_MODULE_PROFILE = 19 +NS_ERROR_MODULE_LDAP = 20 +NS_ERROR_MODULE_SECURITY = 21 +NS_ERROR_MODULE_DOM_XPATH = 22 +NS_ERROR_MODULE_DOM_RANGE = 23 +NS_ERROR_MODULE_URILOADER = 24 +NS_ERROR_MODULE_CONTENT = 25 +NS_ERROR_MODULE_PYXPCOM = 26 +NS_ERROR_MODULE_XSLT = 27 +NS_ERROR_MODULE_IPC = 28 +NS_ERROR_MODULE_SVG = 29 +NS_ERROR_MODULE_GENERAL = 51 + +def NS_FAILED(_nsresult): return ((_nsresult) & -2147483648) + +NS_ERROR_SEVERITY_SUCCESS = 0 +NS_ERROR_SEVERITY_ERROR = 1 +NS_ERROR_MODULE_BASE_OFFSET = 69 +def NS_ERROR_GET_CODE(err): return ((err) & 65535) + +def NS_ERROR_GET_MODULE(err): return (((((err) >> 16) - NS_ERROR_MODULE_BASE_OFFSET) & 8191)) + +def NS_ERROR_GET_SEVERITY(err): return (((err) >> 31) & 1) + +NS_OK = 0 +NS_COMFALSE = 1 +NS_ERROR_BASE = ( -1041039360) +NS_ERROR_NOT_INITIALIZED = (NS_ERROR_BASE + 1) +NS_ERROR_ALREADY_INITIALIZED = (NS_ERROR_BASE + 2) +NS_ERROR_NOT_IMPLEMENTED = ( -2147467263) +NS_NOINTERFACE = ( -2147467262) +NS_ERROR_NO_INTERFACE = NS_NOINTERFACE +NS_ERROR_INVALID_POINTER = ( -2147467261) +NS_ERROR_NULL_POINTER = NS_ERROR_INVALID_POINTER +NS_ERROR_ABORT = ( -2147467260) +NS_ERROR_FAILURE = ( -2147467259) +NS_ERROR_UNEXPECTED = ( -2147418113) +NS_ERROR_OUT_OF_MEMORY = ( -2147024882) +NS_ERROR_ILLEGAL_VALUE = ( -2147024809) +NS_ERROR_INVALID_ARG = NS_ERROR_ILLEGAL_VALUE +NS_ERROR_NO_AGGREGATION = ( -2147221232) +NS_ERROR_NOT_AVAILABLE = ( -2147221231) +NS_ERROR_FACTORY_NOT_REGISTERED = ( -2147221164) +NS_ERROR_FACTORY_REGISTER_AGAIN = ( -2147221163) +NS_ERROR_FACTORY_NOT_LOADED = ( -2147221000) +NS_ERROR_FACTORY_NO_SIGNATURE_SUPPORT = \ + (NS_ERROR_BASE + 257) +NS_ERROR_FACTORY_EXISTS = (NS_ERROR_BASE + 256) +NS_ERROR_PROXY_INVALID_IN_PARAMETER = ( -2147418096) +NS_ERROR_PROXY_INVALID_OUT_PARAMETER = ( -2147418095) + +##### END OF GENERATED CODE +##### +def NS_ERROR_GENERATE_FAILURE(module,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 ((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) +NS_BASE_STREAM_ILLEGAL_ARGS = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 4) +NS_BASE_STREAM_NO_CONVERTER = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 5) +NS_BASE_STREAM_BAD_CONVERSION = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 6) +NS_BASE_STREAM_WOULD_BLOCK = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_BASE, 7) +NS_ERROR_FILE_UNRECOGNIZED_PATH = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 1) +NS_ERROR_FILE_UNRESOLVABLE_SYMLINK = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 2) +NS_ERROR_FILE_EXECUTION_FAILED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 3) +NS_ERROR_FILE_UNKNOWN_TYPE = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 4) +NS_ERROR_FILE_DESTINATION_NOT_DIR = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 5) +NS_ERROR_FILE_TARGET_DOES_NOT_EXIST = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 6) +NS_ERROR_FILE_COPY_OR_MOVE_FAILED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 7) +NS_ERROR_FILE_ALREADY_EXISTS = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 8) +NS_ERROR_FILE_INVALID_PATH = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 9) +NS_ERROR_FILE_DISK_FULL = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 10) +NS_ERROR_FILE_CORRUPTED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 11) +NS_ERROR_FILE_NOT_DIRECTORY = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 12) +NS_ERROR_FILE_IS_DIRECTORY = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 13) +NS_ERROR_FILE_IS_LOCKED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 14) +NS_ERROR_FILE_TOO_BIG = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 15) +NS_ERROR_FILE_NO_DEVICE_SPACE = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 16) +NS_ERROR_FILE_NAME_TOO_LONG = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 17) +NS_ERROR_FILE_NOT_FOUND = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 18) +NS_ERROR_FILE_READ_ONLY = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 19) +NS_ERROR_FILE_DIR_NOT_EMPTY = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 20) +NS_ERROR_FILE_ACCESS_DENIED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_FILES, 21) + +## from netCore.h +NS_ERROR_ALREADY_CONNECTED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 11) + +NS_ERROR_NOT_CONNECTED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 12) +NS_ERROR_IN_PROGRESS = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 15) +NS_ERROR_OFFLINE = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 16) + +## from nsISocketTransportService.idl +NS_ERROR_CONNECTION_REFUSED = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 13) + +NS_ERROR_NET_TIMEOUT = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 14) + +# Status nsresult codes: used with nsIProgressEventSink::OnStatus +NS_NET_STATUS_RESOLVING_HOST = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 3) +NS_NET_STATUS_CONNECTED_TO = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 4) +NS_NET_STATUS_SENDING_TO = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 5) +NS_NET_STATUS_RECEIVING_FROM = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 6) +NS_NET_STATUS_CONNECTING_TO = NS_ERROR_GENERATE_FAILURE(NS_ERROR_MODULE_NETWORK, 7) diff --git a/src/libs/xpcom18a4/python/primitives.py b/src/libs/xpcom18a4/python/primitives.py new file mode 100755 index 00000000..464f12e4 --- /dev/null +++ b/src/libs/xpcom18a4/python/primitives.py @@ -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 diff --git a/src/libs/xpcom18a4/python/readme.html b/src/libs/xpcom18a4/python/readme.html new file mode 100644 index 00000000..112f43e0 --- /dev/null +++ b/src/libs/xpcom18a4/python/readme.html @@ -0,0 +1,121 @@ +<html> +<!-- ***** 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 PyXPCOM. + - + - The Initial Developer of the Original Code is + - ActiveState Tool Corporation. + - Portions created by the Initial Developer are Copyright (C) 2000-2001 + - the Initial Developer. All Rights Reserved. + - + - Contributor(s): + - + - 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 LGPL or the GPL. 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 ***** --> + +<head> +<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> +<meta name="GENERATOR" content="Microsoft FrontPage 4.0"> +<meta name="ProgId" content="FrontPage.Editor.Document"> +<title>Python XPCOM module</title> +</head> + +<body> + +<h1>Python XPCOM Package</h1> + +<p>Mozilla CVS Version - Last updated May 2002</p> +<p>This is the readme for the Python interface to <b>XPCOM</b>.</p> +<p><b>XPCOM </b>is an acronym for "Cross Platform COM". It has +come out of the <a href="http://www.mozilla.org">Mozilla</a> project, which +maintains the <a href="http://www.mozilla.org/projects/xpcom/">main XPCOM +project pages.</a> The Python XPCOM package is a set of Python bindings to +XPCOM, allowing a Python programmer to both use and implement XPCOM +interfaces. If you don't know what <a href="http://www.python.org">Python</a> +is, then none of this probably interests you at all!</p> +<p>This readme has links to the following information:</p> +<ul> + <li><a href="doc/configure.html">Building, Configuring and + Testing the Python + XPCOM Package</a></li> + <li><a href="doc/tutorial.html">A tutorial for the Python XPCOM package</a></li> + <li>Some <a href="doc/advanced.html">advanced + topics and other miscellaneous information</a></li> + <li><a href="doc/architecture.html">Information on the architecture</a></li> + <li>A list of the <a href="#KnownBugs">known issues and bugs</a>, the <a href="#ReleaseHistory">release + history</a> and the <a href="doc/credits.html">PyXPCOM acknowledgements</a></li> +</ul> +<p>Note: <b>This package requires Python 1.6 or later</b>; we recommend using +the latest +official Python version. This package works +very well with the latest <a href="http://www.ActiveState.com/Products/ActivePython">ActivePython</a>, +and does not require any external modules or packages beyond what is provided in +the core Python release for each platform.</p> +<h2>About the Python XPCOM Package</h2> +<p>The Python XPCOM Package was developed by <a href="http://www.ActiveState.com">ActiveState +Tool Corporation</a>, and came out of their <a href="http://www.ActiveState.com/Products/Komodo">Komodo +project</a>. The Python XPCOM package is released under the <a href="http://www.mozilla.org/MPL/">Mozilla +Public License (MPL)</a></p> +<p>Please see the <a href="doc/credits.html">credits file</a> for a list of +contributors. </p> +<h2><a name="KnownBugs">Known Bugs</a>/Issues</h2> +<ul> + <li>No attempt is made to recurse sub-directories of the main +"components" directory. This is because we may decide on some +smart scheme for recursion (similar to Python packages), and don't want people +to rely on simple recursive searches.</li> + <li>No unregistration support at all. The main Python Component Loader supports + unregistration, but the actual Python objects themselves do not support unregistration. It is unclear if the Component Loader + unregistration process needs to manually remove each component it is responsible +for.</li> + <li>All Python-implemented components unconditionally support +weak-references. There is no way to disable this feature for any or all +components. It is unclear if there is a need to prevent this, but it is +documented here just in case!</li> +</ul> +<h2><a name="ReleaseHistory">Release History</a></h2> +<h3>Version 0.90 - January 2001</h3> +<ul> + <li>First public release.</li> +</ul> +<h3>Version 0.91 - January 2001</h3> +<ul> + <li>Fix a seg fault on Linux when PYTHONPATH is not set.</li> + <li>Changes to allow building with stand-alone XPCOM.</li> +</ul> + +<h3>Version 0.92 - May 2001</h3> +<p>Implement interface flattening. You should (almost) never need to use <i>QueryInterface()</i>! +We are still 100% backwards compatible, so usage of QI still works - just is +generally not necessary.</p> + +<h3>Version 0.93 - May 2002</h3> + +<p>Implement <i>nsIVariant</i> and all new string types. Complete move to +autoconf build system.</p> + +</body> + +</html> diff --git a/src/libs/xpcom18a4/python/server/.cvsignore b/src/libs/xpcom18a4/python/server/.cvsignore new file mode 100644 index 00000000..52e4e611 --- /dev/null +++ b/src/libs/xpcom18a4/python/server/.cvsignore @@ -0,0 +1,2 @@ +*.pyc +*.pyo diff --git a/src/libs/xpcom18a4/python/server/__init__.py b/src/libs/xpcom18a4/python/server/__init__.py new file mode 100755 index 00000000..48b15106 --- /dev/null +++ b/src/libs/xpcom18a4/python/server/__init__.py @@ -0,0 +1,88 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# Activestate Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Hammond <MarkH@ActiveState.com> +# +# 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.server package. + +from xpcom.server.policy import DefaultPolicy +from xpcom import _xpcom + +# We define the concept of a single "tracer" object - similar to the single +# Python "trace hook" for debugging. Someone can set +# xpcom.server.tracer to some class/function, and it will be used in place +# of the real xpcom object. Presumably this "trace" object will delegate +# to the real object, but presumably also taking some other action, such +# as calling a profiler or debugger. +# tracer_unwrap is a function used to "unwrap" the tracer object. +# If is expected that tracer_unwrap will be called with an object +# previously returned by "tracer()". +tracer = tracer_unwrap = None + +# Wrap an instance in an interface (via a policy) +def WrapObject(ob, iid, policy = None, bWrapClient = 1): + """Called by the framework to attempt to wrap + an object in a policy. + If iid is None, it will use the first interface the object indicates it supports. + """ + if policy is None: + policy = DefaultPolicy + if tracer is not None: + ob = tracer(ob) + return _xpcom.WrapObject(policy( ob, iid ), iid, bWrapClient) + +# Unwrap a Python object back into the Python object +def UnwrapObject(ob): + if ob is None: + return None + ret = _xpcom.UnwrapObject(ob)._obj_ + if tracer_unwrap is not None: + ret = tracer_unwrap(ret) + return ret + +# Create the main module for the Python loader. +# This is a once only init process, and the returned object +# if used to load all other Python components. + +# This means that we keep all factories, modules etc implemented in +# Python! +def NS_GetModule( serviceManager, nsIFile ): + from . import loader + iid = _xpcom.IID_nsIModule + return WrapObject(loader.MakePythonComponentLoaderModule(serviceManager, nsIFile), iid, bWrapClient = 0) + +def _shutdown(): + from xpcom.server.policy import _shutdown + _shutdown() diff --git a/src/libs/xpcom18a4/python/server/enumerator.py b/src/libs/xpcom18a4/python/server/enumerator.py new file mode 100755 index 00000000..d3fb89a9 --- /dev/null +++ b/src/libs/xpcom18a4/python/server/enumerator.py @@ -0,0 +1,58 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# ActiveState Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000, 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Hammond <MarkH@ActiveState.com> (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 ***** + +from xpcom import components + +# This class is created by Python components when it +# needs to return an enumerator. +# For example, a component may implement a function: +# nsISimpleEnumerator enumSomething(); +# This could could simply say: +# return SimpleEnumerator([something1, something2, something3]) +class SimpleEnumerator: + _com_interfaces_ = [components.interfaces.nsISimpleEnumerator] + + def __init__(self, data): + self._data = data + self._index = 0 + + def hasMoreElements(self): + return self._index < len(self._data) + + def getNext(self): + self._index = self._index + 1 + return self._data[self._index-1] diff --git a/src/libs/xpcom18a4/python/server/factory.py b/src/libs/xpcom18a4/python/server/factory.py new file mode 100755 index 00000000..b65483dd --- /dev/null +++ b/src/libs/xpcom18a4/python/server/factory.py @@ -0,0 +1,68 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# ActiveState Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000, 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Hammond <MarkH@ActiveState.com> (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 ***** + +# Class factory +# +# Hardly worth its own source file! +import xpcom +from xpcom import components, nsError, _xpcom, logger + +class Factory: + _com_interfaces_ = components.interfaces.nsIFactory + # This will only ever be constructed via other Python code, + # so we can have ctor args. + def __init__(self, klass): + self.klass = klass + + def createInstance(self, outer, iid): + if outer is not None: + raise xpcom.ServerException(nsError.NS_ERROR_NO_AGGREGATION) + + 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! + 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): + logger.debug("Python Factory LockServer called '%s'", lock) diff --git a/src/libs/xpcom18a4/python/server/loader.py b/src/libs/xpcom18a4/python/server/loader.py new file mode 100755 index 00000000..ebd42b61 --- /dev/null +++ b/src/libs/xpcom18a4/python/server/loader.py @@ -0,0 +1,227 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# Activestate Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Hammond <MarkH@ActiveState.com> +# +# 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 ***** + +import xpcom +from xpcom import components, logger +from . import module +import glob +import os +from xpcom.client import Component + +# Until we get interface constants. +When_Startup = 0 +When_Component = 1 +When_Timer = 2 + +def _has_good_attr(object, attr): + # Actually allows "None" to be specified to disable inherited attributes. + return getattr(object, attr, None) is not None + +def FindCOMComponents(py_module): + # For now, just run over all classes looking for likely candidates. + comps = [] + for name, object in list(py_module.__dict__.items()): + try: + if (type(object) == type or issubclass(object, object)) and \ + _has_good_attr(object, "_com_interfaces_") and \ + _has_good_attr(object, "_reg_clsid_") and \ + _has_good_attr(object, "_reg_contractid_"): + comps.append(object) + except TypeError: + # The issubclass call raises TypeError when the obj is not a class. + pass; + return comps + +def register_self(klass, compMgr, location, registryLocation, componentType): + pcl = PythonComponentLoader + from xpcom import _xpcom + svc = _xpcom.GetServiceManager().getServiceByContractID("@mozilla.org/categorymanager;1", components.interfaces.nsICategoryManager) + svc.addCategoryEntry("component-loader", pcl._reg_component_type_, pcl._reg_contractid_, 1, 1) + +class PythonComponentLoader: + _com_interfaces_ = components.interfaces.nsIComponentLoader + _reg_clsid_ = "{63B68B1E-3E62-45f0-98E3-5E0B5797970C}" # Never copy these! + _reg_contractid_ = "moz.pyloader.1" + _reg_desc_ = "Python component loader" + # Optional function which performs additional special registration + # Appears that no special unregistration is needed for ComponentLoaders, hence no unregister function. + _reg_registrar_ = (register_self,None) + # Custom attributes for ComponentLoader registration. + _reg_component_type_ = "script/python" + + def __init__(self): + self.com_modules = {} # Keyed by module's FQN as obtained from nsIFile.path + self.moduleFactory = module.Module + self.num_modules_this_register = 0 + + def _getCOMModuleForLocation(self, componentFile): + fqn = componentFile.path + mod = self.com_modules.get(fqn) + if mod is not None: + return mod + import ihooks, sys + base_name = os.path.splitext(os.path.basename(fqn))[0] + loader = ihooks.ModuleLoader() + + module_name_in_sys = "component:%s" % (base_name,) + stuff = loader.find_module(base_name, [componentFile.parent.path]) + assert stuff is not None, "Couldnt find the module '%s'" % (base_name,) + py_mod = loader.load_module( module_name_in_sys, stuff ) + + # Make and remember the COM module. + comps = FindCOMComponents(py_mod) + mod = self.moduleFactory(comps) + + self.com_modules[fqn] = mod + return mod + + def getFactory(self, clsid, location, type): + # return the factory + assert type == self._reg_component_type_, "Being asked to create an object not of my type:%s" % (type,) + # FIXME: how to do this without obsolete component manager? + cmo = components.manager.queryInterface(components.interfaces.nsIComponentManagerObsolete) + file_interface = cmo.specForRegistryLocation(location) + # delegate to the module. + m = self._getCOMModuleForLocation(file_interface) + return m.getClassObject(components.manager, clsid, components.interfaces.nsIFactory) + + def init(self, comp_mgr, registry): + # void + self.comp_mgr = comp_mgr + logger.debug("Python component loader init() called") + + # Called when a component of the appropriate type is registered, + # to give the component loader an opportunity to do things like + # annotate the registry and such. + def onRegister (self, clsid, type, className, proId, location, replace, persist): + logger.debug("Python component loader - onRegister() called") + + def autoRegisterComponents (self, when, directory): + directory_path = directory.path + self.num_modules_this_register = 0 + logger.debug("Auto-registering all Python components in '%s'", directory_path) + + # ToDo - work out the right thing here + # eg - do we recurse? + # - do we support packages? + entries = directory.directoryEntries + while entries.HasMoreElements(): + entry = entries.GetNext(components.interfaces.nsIFile) + if os.path.splitext(entry.path)[1]==".py": + try: + self.autoRegisterComponent(when, entry) + # Handle some common user errors + except xpcom.COMException as details: + from xpcom import nsError + # If the interface name does not exist, suppress the traceback + if details.errno==nsError.NS_ERROR_NO_INTERFACE: + logger.error("Registration of '%s' failed\n %s", + entry.leafName, details.message) + else: + logger.exception("Registration of '%s' failed!", entry.leafName) + except SyntaxError as details: + # Syntax error in source file - no useful traceback here either. + logger.error("Registration of '%s' failed\n %s", + entry.leafName, details) + except: + # All other exceptions get the full traceback. + logger.exception("Registration of '%s' failed.", entry.leafName) + + def autoRegisterComponent (self, when, componentFile): + # bool return + + # Check if we actually need to do anything + modtime = componentFile.lastModifiedTime + loader_mgr = components.manager.queryInterface(components.interfaces.nsIComponentLoaderManager) + if not loader_mgr.hasFileChanged(componentFile, None, modtime): + return 1 + + if self.num_modules_this_register == 0: + # New components may have just installed new Python + # modules into the main python directory (including new .pth files) + # So we ask Python to re-process our site directory. + # Note that the pyloader does the equivalent when loading. + try: + from xpcom import _xpcom + import site + NS_XPCOM_CURRENT_PROCESS_DIR="XCurProcD" + dirname = _xpcom.GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR) + dirname.append("python") + site.addsitedir(dirname.path) + except: + logger.exception("PyXPCOM loader failed to process site directory before component registration") + + self.num_modules_this_register += 1 + + # auto-register via the module. + m = self._getCOMModuleForLocation(componentFile) + m.registerSelf(components.manager, componentFile, None, self._reg_component_type_) + loader_mgr = components.manager.queryInterface(components.interfaces.nsIComponentLoaderManager) + loader_mgr.saveFileInfo(componentFile, None, modtime) + return 1 + + def autoUnregisterComponent (self, when, componentFile): + # bool return + # auto-unregister via the module. + m = self._getCOMModuleForLocation(componentFile) + loader_mgr = components.manager.queryInterface(components.interfaces.nsIComponentLoaderManager) + try: + m.unregisterSelf(components.manager, componentFile) + finally: + loader_mgr.removeFileInfo(componentFile, None) + return 1 + + def registerDeferredComponents (self, when): + # bool return + logger.debug("Python component loader - registerDeferred() called") + return 0 # no more to register + + def unloadAll (self, when): + # This is called at shutdown time - don't get too upset if an error + # results from logging due to the logfile being closed + try: + logger.debug("Python component loader being asked to unload all components!") + except: + # Evil blank except, but restricting to just catching IOError + # failure means custom logs could still screw us + pass + self.comp_mgr = None + self.com_modules = {} + +def MakePythonComponentLoaderModule(serviceManager, nsIFile): + from . import module + return module.Module( [PythonComponentLoader] ) diff --git a/src/libs/xpcom18a4/python/server/module.py b/src/libs/xpcom18a4/python/server/module.py new file mode 100755 index 00000000..73024e95 --- /dev/null +++ b/src/libs/xpcom18a4/python/server/module.py @@ -0,0 +1,108 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is ActiveState Tool Corp. +# Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 +# ActiveState Tool Corp. All Rights Reserved. +# +# Contributor(s): +# Mark Hammond <MarkH@ActiveState.com> (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 ***** + +from xpcom import components +from xpcom import ServerException, Exception +from xpcom import nsError + +from . import factory + +import types +import os + +class Module: + _com_interfaces_ = components.interfaces.nsIModule + def __init__(self, comps): + # Build a map of classes we can provide factories for. + c = self.components = {} + for klass in comps: + c[components.ID(klass._reg_clsid_)] = klass + self.klassFactory = factory.Factory + + def getClassObject(self, compMgr, clsid, iid): + # Single retval result. + try: + klass = self.components[clsid] + except KeyError: + raise ServerException(nsError.NS_ERROR_FACTORY_NOT_REGISTERED) + + # We can ignore the IID - the auto-wrap process will automatically QI us. + return self.klassFactory(klass) + + def registerSelf(self, compMgr, location, loaderStr, componentType): + # void function. + fname = os.path.basename(location.path) + for klass in list(self.components.values()): + reg_contractid = klass._reg_contractid_ + print("Registering '%s' (%s)" % (reg_contractid, fname)) + reg_desc = getattr(klass, "_reg_desc_", reg_contractid) + compMgr = compMgr.queryInterface(components.interfaces.nsIComponentRegistrar) + compMgr.registerFactoryLocation(klass._reg_clsid_, + reg_desc, + reg_contractid, + location, + loaderStr, + componentType) + + # See if this class nominates custom register_self + extra_func = getattr(klass, "_reg_registrar_", (None,None))[0] + if extra_func is not None: + extra_func(klass, compMgr, location, loaderStr, componentType) + + def unregisterSelf(self, compMgr, location, loaderStr): + # void function. + for klass in list(self.components.values()): + ok = 1 + try: + compMgr.unregisterComponentSpec(klass._reg_clsid_, location) + except Exception: + ok = 0 + # Give the class a bash even if we failed! + extra_func = getattr(klass, "_reg_registrar_", (None,None))[1] + if extra_func is not None: + try: + extra_func(klass, compMgr, location, loaderStr) + except Exception: + ok = 0 + if ok: + print("Successfully unregistered", klass.__name__) + else: + print("Unregistration of", klass.__name__, "failed. (probably just not already registered)") + + def canUnload(self, compMgr): + # single bool result + return 0 # we can never unload! + diff --git a/src/libs/xpcom18a4/python/server/policy.py b/src/libs/xpcom18a4/python/server/policy.py new file mode 100755 index 00000000..7f84167c --- /dev/null +++ b/src/libs/xpcom18a4/python/server/policy.py @@ -0,0 +1,398 @@ +# ***** 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 Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# ActiveState Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2001 +# 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 ***** + +from xpcom import xpcom_consts, _xpcom, client, nsError, logger +from xpcom import ServerException, COMException +import xpcom +import xpcom.server +import operator +import types +import logging +import sys + +# Python 3 hacks: +if sys.version_info[0] >= 3: + long = int # pylint: disable=W0622,C0103 + + +IID_nsISupports = _xpcom.IID_nsISupports +IID_nsIVariant = _xpcom.IID_nsIVariant +XPT_MD_IS_GETTER = xpcom_consts.XPT_MD_IS_GETTER +XPT_MD_IS_SETTER = xpcom_consts.XPT_MD_IS_SETTER + +VARIANT_INT_TYPES = xpcom_consts.VTYPE_INT8, xpcom_consts.VTYPE_INT16, xpcom_consts.VTYPE_INT32, \ + xpcom_consts.VTYPE_UINT8, xpcom_consts.VTYPE_UINT16, xpcom_consts.VTYPE_INT32 +VARIANT_LONG_TYPES = xpcom_consts.VTYPE_INT64, xpcom_consts.VTYPE_UINT64 +VARIANT_FLOAT_TYPES = xpcom_consts.VTYPE_FLOAT, xpcom_consts.VTYPE_DOUBLE +VARIANT_STRING_TYPES = xpcom_consts.VTYPE_CHAR, xpcom_consts.VTYPE_CHAR_STR, xpcom_consts.VTYPE_STRING_SIZE_IS, \ + xpcom_consts.VTYPE_CSTRING +VARIANT_UNICODE_TYPES = xpcom_consts.VTYPE_WCHAR, xpcom_consts.VTYPE_DOMSTRING, xpcom_consts.VTYPE_WSTRING_SIZE_IS, \ + xpcom_consts.VTYPE_ASTRING + +_supports_primitives_map_ = {} # Filled on first use. + +_interface_sequence_types_ = tuple, list +if sys.version_info[0] <= 2: + _string_types_ = str, unicode +else: + _string_types_ = bytes, str +XPTI_GetInterfaceInfoManager = _xpcom.XPTI_GetInterfaceInfoManager + +def _GetNominatedInterfaces(obj): + ret = getattr(obj, "_com_interfaces_", None) + if ret is None: return None + # See if the user only gave one. + if type(ret) not in _interface_sequence_types_: + ret = [ret] + real_ret = [] + # For each interface, walk to the root of the interface tree. + iim = XPTI_GetInterfaceInfoManager() + for interface in ret: + # Allow interface name or IID. + interface_info = None + if type(interface) in _string_types_: + try: + interface_info = iim.GetInfoForName(interface) + except COMException: + pass + if interface_info is None: + # Allow a real IID + interface_info = iim.GetInfoForIID(interface) + real_ret.append(interface_info.GetIID()) + parent = interface_info.GetParent() + while parent is not None: + parent_iid = parent.GetIID() + if parent_iid == IID_nsISupports: + break + real_ret.append(parent_iid) + parent = parent.GetParent() + return real_ret + +## +## ClassInfo support +## +## We cache class infos by class +class_info_cache = {} + +def GetClassInfoForObject(ob): + if xpcom.server.tracer_unwrap is not None: + ob = xpcom.server.tracer_unwrap(ob) + klass = ob.__class__ + ci = class_info_cache.get(klass) + if ci is None: + ci = DefaultClassInfo(klass) + ci = xpcom.server.WrapObject(ci, _xpcom.IID_nsIClassInfo, bWrapClient = 0) + class_info_cache[klass] = ci + return ci + +class DefaultClassInfo: + _com_interfaces_ = _xpcom.IID_nsIClassInfo + def __init__(self, klass): + self.klass = klass + self.contractID = getattr(klass, "_reg_contractid_", None) + self.classDescription = getattr(klass, "_reg_desc_", None) + self.classID = getattr(klass, "_reg_clsid_", None) + self.implementationLanguage = 3 # Python - avoid lookups just for this + self.flags = 0 # what to do here?? + self.interfaces = None + + def get_classID(self): + if self.classID is None: + raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED, "Class '%r' has no class ID" % (self.klass,)) + return self.classID + + def getInterfaces(self): + if self.interfaces is None: + self.interfaces = _GetNominatedInterfaces(self.klass) + return self.interfaces + + def getHelperForLanguage(self, language): + return None # Not sure what to do here. + +class DefaultPolicy: + def __init__(self, instance, iid): + self._obj_ = instance + self._nominated_interfaces_ = ni = _GetNominatedInterfaces(instance) + self._iid_ = iid + if ni is None: + raise ValueError("The object '%r' can not be used as a COM object" % (instance,)) + # This is really only a check for the user + if __debug__: + if iid != IID_nsISupports and iid not in ni: + # The object may delegate QI. + delegate_qi = getattr(instance, "_query_interface_", None) + # Perform the actual QI and throw away the result - the _real_ + # QI performed by the framework will set things right! + if delegate_qi is None or not delegate_qi(iid): + raise ServerException(nsError.NS_ERROR_NO_INTERFACE) + # Stuff for the magic interface conversion. + self._interface_info_ = None + self._interface_iid_map_ = {} # Cache - Indexed by (method_index, param_index) + + def _QueryInterface_(self, com_object, iid): + # Framework allows us to return a single boolean integer, + # or a COM object. + if iid in self._nominated_interfaces_: + # We return the underlying object re-wrapped + # in a new gateway - which is desirable, as one gateway should only support + # one interface (this wont affect the users of this policy - we can have as many + # gateways as we like pointing to the same Python objects - the users never + # see what object the call came in from. + # NOTE: We could have simply returned the instance and let the framework + # do the auto-wrap for us - but this way we prevent a round-trip back into Python + # code just for the autowrap. + return xpcom.server.WrapObject(self._obj_, iid, bWrapClient = 0) + + # Always support nsIClassInfo + if iid == _xpcom.IID_nsIClassInfo: + return GetClassInfoForObject(self._obj_) + + # See if the instance has a QI + # use lower-case "_query_interface_" as win32com does, and it doesnt really matter. + delegate = getattr(self._obj_, "_query_interface_", None) + if delegate is not None: + # The COM object itself doesnt get passed to the child + # (again, as win32com doesnt). It is rarely needed + # (in win32com, we dont even pass it to the policy, although we have identified + # one place where we should - for marshalling - so I figured I may as well pass it + # to the policy layer here, but no all the way down to the object. + return delegate(iid) + # Finally see if we are being queried for one of the "nsISupports primitives" + if not _supports_primitives_map_: + iim = _xpcom.XPTI_GetInterfaceInfoManager() + for (iid_name, attr, cvt) in _supports_primitives_data_: + special_iid = iim.GetInfoForName(iid_name).GetIID() + _supports_primitives_map_[special_iid] = (attr, cvt) + attr, cvt = _supports_primitives_map_.get(iid, (None,None)) + if attr is not None and hasattr(self._obj_, attr): + return xpcom.server.WrapObject(SupportsPrimitive(iid, self._obj_, attr, cvt), iid, bWrapClient = 0) + # Out of clever things to try! + return None # We dont support this IID. + + def _MakeInterfaceParam_(self, interface, iid, method_index, mi, param_index): + # Wrap a "raw" interface object in a nice object. The result of this + # function will be passed to one of the gateway methods. + if iid is None: + # look up the interface info - this will be true for all xpcom called interfaces. + if self._interface_info_ is None: + import xpcom.xpt + self._interface_info_ = xpcom.xpt.Interface( self._iid_ ) + iid = self._interface_iid_map_.get( (method_index, param_index)) + if iid is None: + iid = self._interface_info_.GetIIDForParam(method_index, param_index) + self._interface_iid_map_[(method_index, param_index)] = iid + # handle nsIVariant + if iid == IID_nsIVariant: + interface = interface.QueryInterface(iid) + dt = interface.dataType + if dt in VARIANT_INT_TYPES: + return interface.getAsInt32() + if dt in VARIANT_LONG_TYPES: + return interface.getAsInt64() + if dt in VARIANT_FLOAT_TYPES: + return interface.getAsFloat() + if dt in VARIANT_STRING_TYPES: + return interface.getAsStringWithSize() + if dt in VARIANT_UNICODE_TYPES: + return interface.getAsWStringWithSize() + if dt == xpcom_consts.VTYPE_BOOL: + return interface.getAsBool() + if dt == xpcom_consts.VTYPE_INTERFACE: + return interface.getAsISupports() + if dt == xpcom_consts.VTYPE_INTERFACE_IS: + return interface.getAsInterface() + if dt == xpcom_consts.VTYPE_EMPTY or dt == xpcom_consts.VTYPE_VOID: + return None + if dt == xpcom_consts.VTYPE_ARRAY: + return interface.getAsArray() + if dt == xpcom_consts.VTYPE_EMPTY_ARRAY: + return [] + if dt == xpcom_consts.VTYPE_ID: + return interface.getAsID() + # all else fails... + logger.warning("Warning: nsIVariant type %d not supported - returning a string", dt) + try: + return interface.getAsString() + except COMException: + logger.exception("Error: failed to get Variant as a string - returning variant object") + return interface + + return client.Component(interface, iid) + + def _CallMethod_(self, com_object, index, info, params): + #print "_CallMethod_", index, info, params + flags, name, param_descs, ret = info + assert ret[1][0] == xpcom_consts.TD_UINT32, "Expected an nsresult (%s)" % (ret,) + if XPT_MD_IS_GETTER(flags): + # Look for a function of that name + func = getattr(self._obj_, "get_" + name, None) + if func is None: + assert len(param_descs)==1 and len(params)==0, "Can only handle a single [out] arg for a default getter" + ret = getattr(self._obj_, name) # Let attribute error go here! + else: + ret = func(*params) + return 0, ret + elif XPT_MD_IS_SETTER(flags): + # Look for a function of that name + func = getattr(self._obj_, "set_" + name, None) + if func is None: + assert len(param_descs)==1 and len(params)==1, "Can only handle a single [in] arg for a default setter" + setattr(self._obj_, name, params[0]) # Let attribute error go here! + else: + func(*params) + return 0 + else: + # A regular method. + func = getattr(self._obj_, name) + return 0, func(*params) + + def _doHandleException(self, func_name, exc_info): + exc_val = exc_info[1] + is_server_exception = isinstance(exc_val, ServerException) + if is_server_exception: + # 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: + if sys.version_info[0] <= 2: + exec('raise exc_info[0], exc_info[1], exc_info[2]') + else: + raise exc_info[0](exc_info[1]).with_traceback(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: + if sys.version_info[0] <= 2: + exec('raise exc_info[0], exc_info[1], exc_info[2]') + else: + raise exc_info[0](exc_info[1]).with_traceback(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_ + # invocation, or after its return, but when unpacking the results + # eg, type errors, such as a Python integer being used as a string "out" param. + def _CallMethodException_(self, com_object, index, info, params, exc_info): + # Later we may want to have some smart "am I debugging" flags? + # Or maybe just delegate to the actual object - it's probably got the best + # idea what to do with them! + flags, name, param_descs, ret = info + exc_typ, exc_val, exc_tb = exc_info + # use the xpt module to get a better repr for the method. + # But if we fail, ignore it! + try: + import xpcom.xpt + m = xpcom.xpt.Method(info, index, None) + func_repr = m.Describe().lstrip() + 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_. + # Really only used for the component loader etc objects, so most + # users should never see exceptions triggered here. + def _GatewayException_(self, name, exc_info): + return self._doHandleException(name, exc_info) + +if sys.version_info[0] <= 2: + _supports_primitives_data_ = [ + ("nsISupportsCString", "__str__", str), + ("nsISupportsString", "__unicode__", unicode), + ("nsISupportsPRUint64", "__long__", long), + ("nsISupportsPRInt64", "__long__", long), + ("nsISupportsPRUint32", "__int__", int), + ("nsISupportsPRInt32", "__int__", int), + ("nsISupportsPRUint16", "__int__", int), + ("nsISupportsPRInt16", "__int__", int), + ("nsISupportsPRUint8", "__int__", int), + ("nsISupportsPRBool", "__nonzero__", operator.truth), + ("nsISupportsDouble", "__float__", float), + ("nsISupportsFloat", "__float__", float), + ] +else: + _supports_primitives_data_ = [ + ("nsISupportsCString", "__str__", str), + ("nsISupportsString", "__unicode__", str), + ("nsISupportsPRUint64", "__long__", int), + ("nsISupportsPRInt64", "__long__", int), + ("nsISupportsPRUint32", "__int__", int), + ("nsISupportsPRInt32", "__int__", int), + ("nsISupportsPRUint16", "__int__", int), + ("nsISupportsPRInt16", "__int__", int), + ("nsISupportsPRUint8", "__int__", int), + ("nsISupportsPRBool", "__nonzero__", operator.truth), + ("nsISupportsDouble", "__float__", float), + ("nsISupportsFloat", "__float__", float), + ] + +# Support for the nsISupports primitives: +class SupportsPrimitive: + _com_interfaces_ = ["nsISupports"] + def __init__(self, iid, base_ob, attr_name, converter): + self.iid = iid + self.base_ob = base_ob + self.attr_name = attr_name + self.converter = converter + def _query_interface_(self, iid): + if iid == self.iid: + return 1 + return None + def get_data(self): + method = getattr(self.base_ob, self.attr_name) + val = method() + return self.converter(val) + def set_data(self, val): + raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED) + def toString(self): + return str(self.get_data()) + +def _shutdown(): + class_info_cache.clear() diff --git a/src/libs/xpcom18a4/python/src/ErrorUtils.cpp b/src/libs/xpcom18a4/python/src/ErrorUtils.cpp new file mode 100644 index 00000000..9400799b --- /dev/null +++ b/src/libs/xpcom18a4/python/src/ErrorUtils.cpp @@ -0,0 +1,483 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Mark Hammond <MarkH@ActiveState.com> (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 ***** */ + +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +#include "PyXPCOM_std.h" +#include "nsReadableUtils.h" +#include <nsIConsoleService.h> +#ifdef VBOX +# include <nsIExceptionService.h> +# include <iprt/err.h> +# include <iprt/string.h> +#endif +#include "nspr.h" // PR_fprintf + +static char *PyTraceback_AsString(PyObject *exc_tb); + +// The internal helper that actually moves the +// formatted string to the target! + +// Only used in really bad situations! +static void _PanicErrorWrite(const char *msg) +{ + nsCOMPtr<nsIConsoleService> consoleService = do_GetService(NS_CONSOLESERVICE_CONTRACTID); + if (consoleService) + consoleService->LogStringMessage(NS_ConvertASCIItoUCS2(msg).get()); + PR_fprintf(PR_STDERR,"%s\n", msg); +} + +// 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! +#if PY_MAJOR_VERSION <= 2 + PyObject *obMessage = PyString_FromString(pszMessageText); +#else + PyObject *obMessage = PyUnicode_FromString(pszMessageText); +#endif + if (obMessage) { + PyObject *repr = PyObject_Repr(obMessage); + if (repr) { +#if PY_MAJOR_VERSION <= 2 + c += PyString_AsString(repr); +#else + c += PyUnicode_AsUTF8(repr); +#endif + 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(methodName, c); + nsCRT::free(c); +} + +// A helper for the various logging routines. +static void VLogF(const char *methodName, const char *fmt, va_list argptr) +{ + char buff[512]; +#ifdef VBOX /* Enable the use of VBox formatting types. */ + RTStrPrintfV(buff, sizeof(buff), fmt, argptr); +#else + // Use safer NS_ functions. + PR_vsnprintf(buff, sizeof(buff), fmt, argptr); +#endif + + LogMessage(methodName, 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) { +#if PY_MAJOR_VERSION <= 2 + streamout += PyString_AsString(temp); +#else + streamout += PyUnicode_AsUTF8(temp); +#endif + Py_DECREF(temp); + } else + streamout += "Can't convert exception to a string!"; + streamout += ": "; + if (exc_val != NULL) { + temp = PyObject_Str(exc_val); + if (temp) { +#if PY_MAJOR_VERSION <= 2 + streamout += PyString_AsString(temp); +#else + streamout += PyUnicode_AsUTF8(temp); +#endif + 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); + // 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: + nsCAutoString streamout(buff); + if (PyXPCOM_FormatCurrentException(streamout)) { + LogMessage(LOGGER_ERROR, streamout); + } + va_end(marker); +} + +void PyXPCOM_LogWarning(const char *fmt, ...) +{ + va_list marker; + va_start(marker, fmt); + VLogF(LOGGER_WARNING, fmt, marker); + va_end(marker); +} + +void PyXPCOM_Log(const char *level, const nsCString &msg) +{ + DoLogMessage(level, msg.get()); +} + +#ifdef DEBUG +void PyXPCOM_LogDebug(const char *fmt, ...) +{ + va_list marker; + va_start(marker, fmt); + VLogF(LOGGER_DEBUG, fmt, marker); + va_end(marker); +} +#endif + +#ifdef VBOX +PyObject *PyXPCOM_BuildErrorMessage(nsresult r) +{ + char msg[512]; + bool gotMsg = false; + + if (!gotMsg) + { + nsresult rc; + nsCOMPtr <nsIExceptionService> es; + es = do_GetService (NS_EXCEPTIONSERVICE_CONTRACTID, &rc); + if (NS_SUCCEEDED (rc)) + { + nsCOMPtr <nsIExceptionManager> em; + rc = es->GetCurrentExceptionManager (getter_AddRefs (em)); + if (NS_SUCCEEDED (rc)) + { + nsCOMPtr <nsIException> ex; + rc = em->GetExceptionFromProvider(r, NULL, getter_AddRefs (ex)); + if (NS_SUCCEEDED (rc) && ex) + { + nsXPIDLCString emsg; + ex->GetMessage(getter_Copies(emsg)); + PR_snprintf(msg, sizeof(msg), "%s", + emsg.get()); + gotMsg = true; + } + } + } + } + + if (!gotMsg) + { + const RTCOMERRMSG* pMsg = RTErrCOMGet(r); + if (strncmp(pMsg->pszMsgFull, "Unknown", 7) != 0) + { + PR_snprintf(msg, sizeof(msg), "%s (%s)", + pMsg->pszMsgFull, pMsg->pszDefine); + gotMsg = true; + } + } + + if (!gotMsg) + { + PR_snprintf(msg, sizeof(msg), "Error 0x%x in module 0x%x", + NS_ERROR_GET_CODE(r), NS_ERROR_GET_MODULE(r)); + } + PyObject *evalue = Py_BuildValue("is", r, msg); + return evalue; +} +#endif + +PyObject *PyXPCOM_BuildPyException(nsresult r) +{ +#ifndef VBOX + // Need the message etc. + PyObject *evalue = Py_BuildValue("i", r); +#else + PyObject *evalue = PyXPCOM_BuildErrorMessage(r); +#endif + PyErr_SetObject(PyXPCOM_Error, evalue); + Py_XDECREF(evalue); + return NULL; +} + +nsresult PyXPCOM_SetCOMErrorFromPyException() +{ + if (!PyErr_Occurred()) + // No error occurred + return NS_OK; + 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. + This is the exact same string as "traceback.print_exc" would return. + + Pass in a Python traceback object (probably obtained from PyErr_Fetch()) + Result is a string which must be free'd using PyMem_Free() +*/ +#define TRACEBACK_FETCH_ERROR(what) {errMsg = what; goto done;} + +char *PyTraceback_AsString(PyObject *exc_tb) +{ + const char *errMsg = NULL; /* holds a local error message */ + char *result = NULL; /* a valid, allocated result. */ + PyObject *modStringIO = NULL; + PyObject *modTB = NULL; + PyObject *obFuncStringIO = NULL; + PyObject *obStringIO = NULL; + PyObject *obFuncTB = NULL; + PyObject *argsTB = NULL; + PyObject *obResult = NULL; + +#if PY_MAJOR_VERSION <= 2 + /* Import the modules we need - cStringIO and traceback */ + modStringIO = PyImport_ImportModule("cStringIO"); + if (modStringIO==NULL) + TRACEBACK_FETCH_ERROR("cant import cStringIO\n"); + + modTB = PyImport_ImportModule("traceback"); + if (modTB==NULL) + TRACEBACK_FETCH_ERROR("cant import traceback\n"); + /* Construct a cStringIO object */ + obFuncStringIO = PyObject_GetAttrString(modStringIO, "StringIO"); + if (obFuncStringIO==NULL) + TRACEBACK_FETCH_ERROR("cant find cStringIO.StringIO\n"); + obStringIO = PyObject_CallObject(obFuncStringIO, NULL); + if (obStringIO==NULL) + TRACEBACK_FETCH_ERROR("cStringIO.StringIO() failed\n"); +#else + /* Import the modules we need - io and traceback */ + modStringIO = PyImport_ImportModule("io"); + if (modStringIO==NULL) + TRACEBACK_FETCH_ERROR("cant import io\n"); + + modTB = PyImport_ImportModule("traceback"); + if (modTB==NULL) + TRACEBACK_FETCH_ERROR("cant import traceback\n"); + /* Construct a StringIO object */ + obFuncStringIO = PyObject_GetAttrString(modStringIO, "StringIO"); + if (obFuncStringIO==NULL) + TRACEBACK_FETCH_ERROR("cant find io.StringIO\n"); + obStringIO = PyObject_CallObject(obFuncStringIO, NULL); + if (obStringIO==NULL) + TRACEBACK_FETCH_ERROR("io.StringIO() failed\n"); +#endif + /* Get the traceback.print_exception function, and call it. */ + obFuncTB = PyObject_GetAttrString(modTB, "print_tb"); + if (obFuncTB==NULL) + TRACEBACK_FETCH_ERROR("cant find traceback.print_tb\n"); + + argsTB = Py_BuildValue("OOO", + exc_tb ? exc_tb : Py_None, + Py_None, + obStringIO); + if (argsTB==NULL) + TRACEBACK_FETCH_ERROR("cant make print_tb arguments\n"); + + obResult = PyObject_CallObject(obFuncTB, argsTB); + if (obResult==NULL) + TRACEBACK_FETCH_ERROR("traceback.print_tb() failed\n"); + /* Now call the getvalue() method in the StringIO instance */ + Py_DECREF(obFuncStringIO); + obFuncStringIO = PyObject_GetAttrString(obStringIO, "getvalue"); + if (obFuncStringIO==NULL) + TRACEBACK_FETCH_ERROR("cant find getvalue function\n"); + Py_DECREF(obResult); + obResult = PyObject_CallObject(obFuncStringIO, NULL); + if (obResult==NULL) + TRACEBACK_FETCH_ERROR("getvalue() failed.\n"); + + /* And it should be a string all ready to go - duplicate it. */ +#if PY_MAJOR_VERSION <= 2 + if (!PyString_Check(obResult)) +#else + if (!PyUnicode_Check(obResult)) +#endif + TRACEBACK_FETCH_ERROR("getvalue() did not return a string\n"); + + { // a temp scope so I can use temp locals. +#if PY_MAJOR_VERSION <= 2 + char *tempResult = PyString_AsString(obResult); +#else + /* PyUnicode_AsUTF8() is const char * as of Python 3.7, char * earlier. */ + const char *tempResult = (const char *)PyUnicode_AsUTF8(obResult); +#endif + result = (char *)PyMem_Malloc(strlen(tempResult)+1); + if (result==NULL) + TRACEBACK_FETCH_ERROR("memory error duplicating the traceback string\n"); + + strcpy(result, tempResult); + } // end of temp scope. +done: + /* All finished - first see if we encountered an error */ + if (result==NULL && errMsg != NULL) { + result = (char *)PyMem_Malloc(strlen(errMsg)+1); + if (result != NULL) + /* if it does, not much we can do! */ + strcpy(result, errMsg); + } + Py_XDECREF(modStringIO); + Py_XDECREF(modTB); + Py_XDECREF(obFuncStringIO); + Py_XDECREF(obStringIO); + Py_XDECREF(obFuncTB); + Py_XDECREF(argsTB); + Py_XDECREF(obResult); + return result; +} + +// See comments in PyXPCOM.h for why we need this! +void PyXPCOM_MakePendingCalls() +{ + while (1) { + int rc = Py_MakePendingCalls(); + if (rc == 0) + break; + // An exception - just report it as normal. + // Note that a traceback is very unlikely! + PyXPCOM_LogError("Unhandled exception detected before entering Python.\n"); + PyErr_Clear(); + // And loop around again until we are told everything is done! + } +} diff --git a/src/libs/xpcom18a4/python/src/PyGBase.cpp b/src/libs/xpcom18a4/python/src/PyGBase.cpp new file mode 100644 index 00000000..e73b2a6d --- /dev/null +++ b/src/libs/xpcom18a4/python/src/PyGBase.cpp @@ -0,0 +1,852 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * 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 ***** */ + +// PyGBase.cpp - implementation of the PyG_Base class +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +#include "PyXPCOM_std.h" +#include <nsIModule.h> +#include <nsIComponentLoader.h> +#include <nsIInputStream.h> + +static PRInt32 cGateways = 0; +PRInt32 _PyXPCOM_GetGatewayCount(void) +{ + return cGateways; +} + +extern PyG_Base *MakePyG_nsIModule(PyObject *); +extern PyG_Base *MakePyG_nsIComponentLoader(PyObject *instance); +extern PyG_Base *MakePyG_nsIInputStream(PyObject *instance); + +static char *PyXPCOM_szDefaultGatewayAttributeName = (char*)"_com_instance_default_gateway_"; +PyG_Base *GetDefaultGateway(PyObject *instance); +void AddDefaultGateway(PyObject *instance, nsISupports *gateway); +PRBool CheckDefaultGateway(PyObject *real_inst, REFNSIID iid, nsISupports **ret_gateway); + +/*static*/ nsresult +PyG_Base::CreateNew(PyObject *pPyInstance, const nsIID &iid, void **ppResult) +{ + NS_PRECONDITION(ppResult && *ppResult==NULL, "NULL or uninitialized pointer"); + if (ppResult==nsnull) + return NS_ERROR_NULL_POINTER; + + PyG_Base *ret; + // Hack for few extra gateways we support. + if (iid.Equals(NS_GET_IID(nsIModule))) + ret = MakePyG_nsIModule(pPyInstance); + else if (iid.Equals(NS_GET_IID(nsIComponentLoader))) + ret = MakePyG_nsIComponentLoader(pPyInstance); + else if (iid.Equals(NS_GET_IID(nsIInputStream))) + ret = MakePyG_nsIInputStream(pPyInstance); + else + ret = new PyXPCOM_XPTStub(pPyInstance, iid); + if (ret==nsnull) + return NS_ERROR_OUT_OF_MEMORY; + ret->AddRef(); // The first reference for the caller. + *ppResult = ret->ThisAsIID(iid); + NS_ABORT_IF_FALSE(*ppResult != NULL, "ThisAsIID() gave NULL, but we know it supports it!"); + return *ppResult ? NS_OK : NS_ERROR_FAILURE; +} + +PyG_Base::PyG_Base(PyObject *instance, const nsIID &iid) +{ + // Note that "instance" is the _policy_ instance!! + PR_AtomicIncrement(&cGateways); + m_pBaseObject = GetDefaultGateway(instance); + // m_pWeakRef is an nsCOMPtr and needs no init. + + NS_ABORT_IF_FALSE(!(iid.Equals(NS_GET_IID(nsISupportsWeakReference)) || iid.Equals(NS_GET_IID(nsIWeakReference))),"Should not be creating gateways with weak-ref interfaces"); + m_iid = iid; + m_pPyObject = instance; + NS_PRECONDITION(instance, "NULL PyObject for PyXPCOM_XPTStub!"); + +#ifdef NS_BUILD_REFCNT_LOGGING + // If XPCOM reference count logging is enabled, then allow us to give the Python class. + PyObject *realInstance = PyObject_GetAttrString(instance, "_obj_"); + PyObject *r = PyObject_Repr(realInstance); + const char *szRepr; + if (r==NULL) { + PyXPCOM_LogError("Getting the __repr__ of the object failed"); + PyErr_Clear(); + szRepr = "(repr failed!)"; + } + else +#if PY_MAJOR_VERSION <= 2 + szRepr = PyString_AsString(r); +#else + szRepr = PyUnicode_AsUTF8(r); +#endif + if (szRepr==NULL) szRepr = ""; + int reprOffset = *szRepr=='<' ? 1 : 0; + static const char *reprPrefix = "component:"; + if (strncmp(reprPrefix, szRepr+reprOffset, strlen(reprPrefix)) == 0) + reprOffset += strlen(reprPrefix); + strncpy(refcntLogRepr, szRepr + reprOffset, sizeof(refcntLogRepr)-1); + refcntLogRepr[sizeof(refcntLogRepr)-1] = '\0'; + // See if we should get rid of the " at 0x12345" portion. + char *lastPos = strstr(refcntLogRepr, " at "); + if (lastPos) *lastPos = '\0'; + Py_XDECREF(realInstance); + Py_XDECREF(r); +#endif // NS_BUILD_REFCNT_LOGGING + +#ifdef DEBUG_LIFETIMES + { + char *iid_repr; + nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager(); + if (iim!=nsnull) + iim->GetNameForIID(&iid, &iid_repr); + PyObject *real_instance = PyObject_GetAttrString(instance, "_obj_"); + PyObject *real_repr = PyObject_Repr(real_instance); + + PYXPCOM_LOG_DEBUG("PyG_Base created at %p\n instance_repr=%s\n IID=%s\n", this, PyString_AsString(real_repr), iid_repr); + nsMemory::Free(iid_repr); + Py_XDECREF(real_instance); + Py_XDECREF(real_repr); + } +#endif // DEBUG_LIFETIMES + Py_XINCREF(instance); // instance should never be NULL - but whats an X between friends! + + PyXPCOM_DLLAddRef(); + +#ifdef DEBUG_FULL + LogF("PyGatewayBase: created %s", m_pPyObject ? PyXPCOM_ObTypeName(m_pPyObject) : "<NULL>"); +#endif +} + +PyG_Base::~PyG_Base() +{ + PR_AtomicDecrement(&cGateways); +#ifdef DEBUG_LIFETIMES + PYXPCOM_LOG_DEBUG("PyG_Base: deleted %p", this); +#endif + if ( m_pPyObject ) { + CEnterLeavePython celp; + Py_DECREF(m_pPyObject); + } + if (m_pBaseObject) + m_pBaseObject->Release(); + if (m_pWeakRef) { + // Need to ensure some other thread isnt doing a QueryReferent on + // our weak reference at the same time + CEnterLeaveXPCOMFramework _celf; + PyXPCOM_GatewayWeakReference *p = (PyXPCOM_GatewayWeakReference *)(nsISupports *)m_pWeakRef; + p->m_pBase = nsnull; + m_pWeakRef = nsnull; + } + PyXPCOM_DLLRelease(); +} + +// Get the correct interface pointer for this object given the IID. +void *PyG_Base::ThisAsIID( const nsIID &iid ) +{ + if (this==NULL) return NULL; + if (iid.Equals(NS_GET_IID(nsISupports))) + return (nsISupports *)(nsIInternalPython *)this; + if (iid.Equals(NS_GET_IID(nsISupportsWeakReference))) + return (nsISupportsWeakReference *)this; + if (iid.Equals(NS_GET_IID(nsIInternalPython))) + return (nsISupports *)(nsIInternalPython *)this; + return NULL; +} + +// Call back into Python, passing a Python instance, and get back +// an interface object that wraps the instance. +/*static*/ PRBool +PyG_Base::AutoWrapPythonInstance(PyObject *ob, const nsIID &iid, nsISupports **ppret) +{ + NS_PRECONDITION(ppret!=NULL, "null pointer when wrapping a Python instance!"); + NS_PRECONDITION(ob && PyObject_HasAttrString(ob, "__class__"), + "AutoWrapPythonInstance is expecting an non-NULL instance!"); + PRBool ok = PR_FALSE; + // XXX - todo - this static object leaks! (but Python on Windows leaks 2000+ objects as it is ;-) + static PyObject *func = NULL; // fetch this once and remember! + PyObject *obIID = NULL; + PyObject *wrap_ret = NULL; + PyObject *args = NULL; + if (func==NULL) { // not thread-safe, but nothing bad can happen, except an extra reference leak + PyObject *mod = PyImport_ImportModule("xpcom.server"); + if (mod) + func = PyObject_GetAttrString(mod, "WrapObject"); + Py_XDECREF(mod); + if (func==NULL) goto done; + } + // See if the instance has previously been wrapped. + if (CheckDefaultGateway(ob, iid, ppret)) { + ok = PR_TRUE; // life is good! + } else { + PyErr_Clear(); + + obIID = Py_nsIID::PyObjectFromIID(iid); + if (obIID==NULL) goto done; + args = Py_BuildValue("OOzi", ob, obIID, NULL, 0); + if (args==NULL) goto done; + wrap_ret = PyEval_CallObject(func, args); + if (wrap_ret==NULL) goto done; + ok = Py_nsISupports::InterfaceFromPyObject(wrap_ret, iid, ppret, PR_FALSE, PR_FALSE); +#ifdef DEBUG + if (ok) + // Check we _now_ have a default gateway + { + nsISupports *temp = NULL; + NS_ABORT_IF_FALSE(CheckDefaultGateway(ob, iid, &temp), "Auto-wrapped object didnt get a default gateway!"); + if (temp) temp->Release(); + } +#endif + } +done: +// Py_XDECREF(func); -- func is static for performance reasons. + Py_XDECREF(obIID); + Py_XDECREF(wrap_ret); + Py_XDECREF(args); + return ok; +} + +// Call back into Python, passing a raw nsIInterface object, getting back +// the object to actually use as the gateway parameter for this interface. +// For example, it is expected that the policy will wrap the interface +// object in one of the xpcom.client.Interface objects, allowing +// natural usage of the interface from Python clients. +// Note that piid will usually be NULL - this is because the runtime +// reflection interfaces dont provide this information to me. +// In this case, the Python code may choose to lookup the complete +// interface info to obtain the IID. +// It is expected (but should not be assumed) that the method info +// or the IID will be NULL. +// Worst case, the code should provide a wrapper for the nsiSupports interface, +// so at least the user can simply QI the object. +PyObject * +PyG_Base::MakeInterfaceParam(nsISupports *pis, + const nsIID *piid, + int methodIndex /* = -1 */, + const XPTParamDescriptor *d /* = NULL */, + int paramIndex /* = -1 */) +{ + if (pis==NULL) { + Py_INCREF(Py_None); + return Py_None; + } + // This condition is true today, but not necessarily so. + // But if it ever triggers, the poor Python code has no real hope + // of returning something useful, so we should at least do our + // best to provide the useful data. + NS_WARN_IF_FALSE( ((piid != NULL) ^ (d != NULL)) == 1, "No information on the interface available - Python's gunna have a hard time doing much with it!"); + PyObject *obIID = NULL; + PyObject *obISupports = NULL; + PyObject *obParamDesc = NULL; + PyObject *result = NULL; + + // get the basic interface first, as if we fail, we can try and use this. + // 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 { + /* HACK ALERT! Dropping the python interpreter lock here while + doing QueryInterface because it may involve IPC to a python + object in the same interpreter and deadlock. Not at all + sure if this is a good idea or not for the internal PyXPCOM + state, but it might fix the deadloock... Hoping for the best. */ + Py_BEGIN_ALLOW_THREADS; + iid_check = NS_GET_IID(nsISupports); + pis->QueryInterface(iid_check, getter_AddRefs(piswrap)); + Py_END_ALLOW_THREADS; + } + + obISupports = Py_nsISupports::PyObjectFromInterface(piswrap, iid_check, PR_FALSE); + if (!obISupports) + goto done; + if (piid==NULL) { + obIID = Py_None; + Py_INCREF(Py_None); + } else + obIID = Py_nsIID::PyObjectFromIID(*piid); + if (obIID==NULL) + goto done; + obParamDesc = PyObject_FromXPTParamDescriptor(d); + if (obParamDesc==NULL) + goto done; + + result = PyObject_CallMethod(m_pPyObject, + (char*)"_MakeInterfaceParam_", + (char*)"OOiOi", + obISupports, + obIID, + methodIndex, + obParamDesc, + paramIndex); +done: + if (PyErr_Occurred()) { + NS_WARN_IF_FALSE(result==NULL, "Have an error, but also a result!"); + PyXPCOM_LogError("Wrapping an interface object for the gateway failed\n"); + } + Py_XDECREF(obIID); + Py_XDECREF(obParamDesc); + if (result==NULL) { // we had an error. + PyErr_Clear(); // but are not reporting it back to Python itself! + // return our obISupports. If NULL, we are really hosed and nothing we can do. + return obISupports; + } + // Dont need to return this - we have a better result. + Py_XDECREF(obISupports); + return result; +} + +NS_IMETHODIMP +PyG_Base::QueryInterface(REFNSIID iid, void** ppv) +{ +#ifdef PYXPCOM_DEBUG_FULL + { + char *sziid = iid.ToString(); + LogF("PyGatewayBase::QueryInterface: %s", sziid); + Allocator::Free(sziid); + } +#endif + NS_PRECONDITION(ppv, "NULL pointer"); + if (ppv==nsnull) + return NS_ERROR_NULL_POINTER; + *ppv = nsnull; + // If one of our native interfaces (but NOT nsISupports if we have a base) + // return this. + // It is important is that nsISupports come from the base object + // to ensure that we live by XPCOM identity rules (other interfaces need + // not abide by this rule - only nsISupports.) + if ( (m_pBaseObject==NULL || !iid.Equals(NS_GET_IID(nsISupports))) + && (*ppv=ThisAsIID(iid)) != NULL ) { + AddRef(); + return NS_OK; + } + // If we have a "base object", then we need to delegate _every_ remaining + // QI to it. + if (m_pBaseObject != NULL) + return m_pBaseObject->QueryInterface(iid, ppv); + + // Call the Python policy to see if it (says it) supports the interface + PRBool supports = PR_FALSE; + { // temp scope for Python lock + CEnterLeavePython celp; + + PyObject * ob = Py_nsIID::PyObjectFromIID(iid); + // 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); + return NS_ERROR_OUT_OF_MEMORY; + } + + PyObject *result = PyObject_CallMethod(m_pPyObject, (char*)"_QueryInterface_", + (char*)"OO", + this_interface_ob, ob); + Py_DECREF(ob); + Py_DECREF(this_interface_ob); + + if ( result ) { + if (Py_nsISupports::InterfaceFromPyObject(result, iid, (nsISupports **)ppv, PR_TRUE)) { + // If OK, but NULL, _QI_ returned None, which simply means + // "no such interface" + supports = (*ppv!=NULL); + // result has been QI'd and AddRef'd all ready for return. + } else { + // Dump this message and any Python exception before + // reporting the fact that QI failed - this error + // may provide clues! + PyXPCOM_LogError("The _QueryInterface_ method returned an object of type '%s', but an interface was expected\n", PyXPCOM_ObTypeName(result)); + // supports remains false + } + Py_DECREF(result); + } else { + NS_ABORT_IF_FALSE(PyErr_Occurred(), "Got NULL result, but no Python error flagged!"); + NS_WARN_IF_FALSE(!supports, "Have failure with success flag set!"); + PyXPCOM_LogError("The _QueryInterface_ processing failed.\n"); + // supports remains false. + // We have reported the error, and are returning to COM, + // so we should clear it. + PyErr_Clear(); + } + } // end of temp scope for Python lock - lock released here! + if ( !supports ) + return NS_ERROR_NO_INTERFACE; + return NS_OK; +} + +nsrefcnt +PyG_Base::AddRef(void) +{ + nsrefcnt cnt = (nsrefcnt) PR_AtomicIncrement((PRInt32*)&mRefCnt); +#ifdef NS_BUILD_REFCNT_LOGGING + // If we have no pBaseObject, then we need to ignore them + if (m_pBaseObject == NULL) + NS_LOG_ADDREF(this, cnt, refcntLogRepr, sizeof(*this)); +#endif + return cnt; +} + +nsrefcnt +PyG_Base::Release(void) +{ + nsrefcnt cnt = (nsrefcnt) PR_AtomicDecrement((PRInt32*)&mRefCnt); +#ifdef NS_BUILD_REFCNT_LOGGING + if (m_pBaseObject == NULL) + NS_LOG_RELEASE(this, cnt, refcntLogRepr); +#endif + if ( cnt == 0 ) + delete this; + return cnt; +} + +NS_IMETHODIMP +PyG_Base::GetWeakReference(nsIWeakReference **ret) +{ + // always delegate back to the "base" gateway for the object, as this tear-off + // interface may not live as long as the base. So we recurse back to the base. + if (m_pBaseObject) { + NS_PRECONDITION(m_pWeakRef == nsnull, "Not a base object, but do have a weak-ref!"); + return m_pBaseObject->GetWeakReference(ret); + } + NS_PRECONDITION(ret, "null pointer"); + 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) + return NS_ERROR_UNEXPECTED; + } + *ret = m_pWeakRef; + (*ret)->AddRef(); + return NS_OK; +} + +nsresult PyG_Base::HandleNativeGatewayError(const char *szMethodName) +{ + nsresult rc = NS_OK; + if (PyErr_Occurred()) { + // The error handling - fairly involved, but worth it as + // 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 + // 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 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. + + PRBool bProcessMainError = PR_TRUE; // set to false if our exception handler does its thing! + PyObject *exc_typ, *exc_val, *exc_tb; + PyErr_Fetch(&exc_typ, &exc_val, &exc_tb); + + PyObject *err_result = PyObject_CallMethod(m_pPyObject, + (char*)"_GatewayException_", + (char*)"z(OOO)", + szMethodName, + exc_typ ? exc_typ : Py_None, // should never be NULL, but defensive programming... + exc_val ? exc_val : Py_None, // may well be NULL. + exc_tb ? exc_tb : Py_None); // may well be NULL. + if (err_result == NULL) { + PyXPCOM_LogError("The exception handler _CallMethodException_ failed!\n"); + } else if (err_result == Py_None) { + // The exception handler has chosen not to do anything with + // this error, so we still need to print it! + ; + } else if (PyInt_Check(err_result)) { + // The exception handler has given us the nresult. + rc = PyInt_AsLong(err_result); + bProcessMainError = PR_FALSE; + } else { + // The exception handler succeeded, but returned other than + // int or None. + PyXPCOM_LogError("The _CallMethodException_ handler returned object of type '%s' - None or an integer expected\n", PyXPCOM_ObTypeName(err_result)); + } + Py_XDECREF(err_result); + PyErr_Restore(exc_typ, exc_val, exc_tb); + if (bProcessMainError) { + PyXPCOM_LogError("The function '%s' failed\n", szMethodName); + rc = PyXPCOM_SetCOMErrorFromPyException(); + } + PyErr_Clear(); + } + return rc; +} + +static nsresult do_dispatch( + PyObject *pPyObject, + PyObject **ppResult, + const char *szMethodName, + const char *szFormat, + va_list va + ) +{ + NS_PRECONDITION(ppResult, "Must provide a result buffer"); + *ppResult = nsnull; + // Build the Invoke arguments... + PyObject *args = NULL; + PyObject *method = NULL; + PyObject *real_ob = NULL; + nsresult ret = NS_ERROR_FAILURE; + if ( szFormat ) + args = Py_VaBuildValue((char *)szFormat, va); + else + args = PyTuple_New(0); + if ( !args ) + goto done; + + // make sure a tuple. + if ( !PyTuple_Check(args) ) { + PyObject *a = PyTuple_New(1); + if ( a == NULL ) + { + Py_DECREF(args); + goto done; + } + PyTuple_SET_ITEM(a, 0, args); + args = a; + } + // Bit to a hack here to maintain the use of a policy. + // We actually get the policies underlying object + // to make the call on. + real_ob = PyObject_GetAttrString(pPyObject, "_obj_"); + if (real_ob == NULL) { + PyErr_Format(PyExc_AttributeError, "The policy object does not have an '_obj_' attribute."); + goto done; + } + method = PyObject_GetAttrString(real_ob, (char *)szMethodName); + if ( !method ) { + PyErr_Clear(); + ret = NS_PYXPCOM_NO_SUCH_METHOD; + goto done; + } + // Make the call + *ppResult = PyEval_CallObject(method, args); + ret = *ppResult ? NS_OK : NS_ERROR_FAILURE; +done: + Py_XDECREF(method); + Py_XDECREF(real_ob); + Py_XDECREF(args); + return ret; +} + + +nsresult PyG_Base::InvokeNativeViaPolicyInternal( + const char *szMethodName, + PyObject **ppResult, + const char *szFormat, + va_list va + ) +{ + if ( m_pPyObject == NULL || szMethodName == NULL ) + return NS_ERROR_NULL_POINTER; + + PyObject *temp = nsnull; + if (ppResult == nsnull) + ppResult = &temp; + nsresult nr = do_dispatch(m_pPyObject, ppResult, szMethodName, szFormat, va); + + // If temp is NULL, they provided a buffer, and we dont touch it. + // If not NULL, *ppResult = temp, and _we_ do own it. + Py_XDECREF(temp); + return nr; +} + +nsresult PyG_Base::InvokeNativeViaPolicy( + const char *szMethodName, + PyObject **ppResult /* = NULL */, + const char *szFormat /* = NULL */, + ... + ) +{ + va_list va; + va_start(va, szFormat); + nsresult nr = InvokeNativeViaPolicyInternal(szMethodName, ppResult, szFormat, va); + va_end(va); + + if (nr == NS_PYXPCOM_NO_SUCH_METHOD) { + // Only problem was missing method. + PyErr_Format(PyExc_AttributeError, "The object does not have a '%s' function.", szMethodName); + } + return nr == NS_OK ? NS_OK : HandleNativeGatewayError(szMethodName); +} + +nsresult PyG_Base::InvokeNativeGetViaPolicy( + const char *szPropertyName, + PyObject **ppResult /* = NULL */ + ) +{ + PyObject *ob_ret = NULL; + nsresult ret = NS_OK; + PyObject *real_ob = NULL; + if ( m_pPyObject == NULL || szPropertyName == NULL ) + return NS_ERROR_NULL_POINTER; + // First see if we have a method of that name. + char buf[256]; + strcpy(buf, "get_"); + strncat(buf, szPropertyName, sizeof(buf)*sizeof(buf[0])-strlen(buf)-1); + buf[sizeof(buf)/sizeof(buf[0])-1] = '\0'; + ret = InvokeNativeViaPolicyInternal(buf, ppResult, nsnull, nsnull); + if (ret == NS_PYXPCOM_NO_SUCH_METHOD) { + // No method of that name - just try a property. + // Bit to a hack here to maintain the use of a policy. + // We actually get the policies underlying object + // to make the call on. + real_ob = PyObject_GetAttrString(m_pPyObject, "_obj_"); + if (real_ob == NULL) { + PyErr_Format(PyExc_AttributeError, "The policy object does not have an '_obj_' attribute."); + ret = HandleNativeGatewayError(szPropertyName); + goto done; + } + ob_ret = PyObject_GetAttrString(real_ob, (char *)szPropertyName); + if (ob_ret==NULL) { + PyErr_Format(PyExc_AttributeError, + "The object does not have a 'get_%s' function, or a '%s attribute.", + szPropertyName, szPropertyName); + } else { + ret = NS_OK; + if (ppResult) + *ppResult = ob_ret; + else + Py_XDECREF(ob_ret); + } + } + if (ret != NS_OK) + ret = HandleNativeGatewayError(szPropertyName); + +done: + Py_XDECREF(real_ob); + return ret; +} + +nsresult PyG_Base::InvokeNativeSetViaPolicy( + const char *szPropertyName, + ... + ) +{ + if ( m_pPyObject == NULL || szPropertyName == NULL ) + return NS_ERROR_NULL_POINTER; + nsresult ret = NS_OK; + PyObject *real_ob = NULL; + char buf[256]; + strcpy(buf, "set_"); + strncat(buf, szPropertyName, sizeof(buf)*sizeof(buf[0])-strlen(buf)-1); + buf[sizeof(buf)/sizeof(buf[0])-1] = '\0'; + va_list va; + va_start(va, szPropertyName); + ret = InvokeNativeViaPolicyInternal(buf, NULL, "O", va); + va_end(va); + if (ret == NS_PYXPCOM_NO_SUCH_METHOD) { + // No method of that name - just try a property. + // Bit to a hack here to maintain the use of a policy. + // We actually get the policies underlying object + // to make the call on. + real_ob = PyObject_GetAttrString(m_pPyObject, "_obj_"); + if (real_ob == NULL) { + PyErr_Format(PyExc_AttributeError, "The policy object does not have an '_obj_' attribute."); + ret = HandleNativeGatewayError(szPropertyName); + goto done; + } + va_list va2; + va_start(va2, szPropertyName); + PyObject *arg = va_arg( va2, PyObject *); + va_end(va2); + if (PyObject_SetAttrString(real_ob, (char *)szPropertyName, arg) == 0) + ret = NS_OK; + else { + PyErr_Format(PyExc_AttributeError, + "The object does not have a 'set_%s' function, or a '%s attribute.", + szPropertyName, szPropertyName); + } + } + if (ret != NS_OK) + ret = HandleNativeGatewayError(szPropertyName); +done: + Py_XDECREF(real_ob); + return ret; +} + +// Get at the underlying Python object. +PyObject *PyG_Base::UnwrapPythonObject(void) +{ + Py_INCREF(m_pPyObject); + return m_pPyObject; +} +/****************************************************** + + Some special support to help with object identity. + + In the simplest case, assume a Python XPCOM object is + supporting a function "nsIWhatever GetWhatever()", + so implements it as: + 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: + + p1 = foo.GetWhatever(); + p2 = foo.GetWhatever(); + + We almost certainly expect p1==p2==foo. + + We previously _did_ have special support for the "self" + example above, but this implements a generic scheme that + works for _all_ objects. + + Whenever we are asked to "AutoWrap" a Python object, the + first thing we do is see if it has been auto-wrapped before. + + If not, we create a new wrapper, then make a COM weak reference + to that wrapper, and store it directly back into the instance + we are auto-wrapping! The use of a weak-reference prevents + cycles. + + The existance of this attribute in an instance indicates if it + has been previously auto-wrapped. + + If it _has_ previously been auto-wrapped, we de-reference the + weak reference, and use that gateway. + +*********************************************************************/ + +PyG_Base *GetDefaultGateway(PyObject *policy) +{ + // NOTE: Instance is the policy, not the real instance + PyObject *instance = PyObject_GetAttrString(policy, "_obj_"); + if (instance == nsnull) + return nsnull; + PyObject *ob_existing_weak = PyObject_GetAttrString(instance, PyXPCOM_szDefaultGatewayAttributeName); + Py_DECREF(instance); + if (ob_existing_weak != NULL) { + PRBool ok = PR_TRUE; + nsCOMPtr<nsIWeakReference> pWeakRef; + ok = NS_SUCCEEDED(Py_nsISupports::InterfaceFromPyObject(ob_existing_weak, + NS_GET_IID(nsIWeakReference), + getter_AddRefs(pWeakRef), + PR_FALSE)); + Py_DECREF(ob_existing_weak); + nsISupports *pip; + if (ok) { + nsresult nr = pWeakRef->QueryReferent( NS_GET_IID(nsIInternalPython), (void **)&pip); + if (NS_FAILED(nr)) + return nsnull; + return (PyG_Base *)(nsIInternalPython *)pip; + } + } else + PyErr_Clear(); + return nsnull; +} + +PRBool CheckDefaultGateway(PyObject *real_inst, REFNSIID iid, nsISupports **ret_gateway) +{ + NS_ABORT_IF_FALSE(real_inst, "Did not have an _obj_ attribute"); + if (real_inst==NULL) { + PyErr_Clear(); + return PR_FALSE; + } + PyObject *ob_existing_weak = PyObject_GetAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName); + if (ob_existing_weak != NULL) { + // We have an existing default, but as it is a weak reference, it + // may no longer be valid. Check it. + PRBool ok = PR_TRUE; + nsCOMPtr<nsIWeakReference> pWeakRef; + ok = NS_SUCCEEDED(Py_nsISupports::InterfaceFromPyObject(ob_existing_weak, + NS_GET_IID(nsIWeakReference), + getter_AddRefs(pWeakRef), + PR_FALSE)); + Py_DECREF(ob_existing_weak); + if (ok) { + Py_BEGIN_ALLOW_THREADS; + ok = NS_SUCCEEDED(pWeakRef->QueryReferent( iid, (void **)(ret_gateway))); + Py_END_ALLOW_THREADS; + } + if (!ok) { + // We have the attribute, but not valid - wipe it + // before restoring it. + if (0 != PyObject_DelAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName)) + PyErr_Clear(); + } + return ok; + } + PyErr_Clear(); + return PR_FALSE; +} + +void AddDefaultGateway(PyObject *instance, nsISupports *gateway) +{ + // NOTE: Instance is the _policy_! + PyObject *real_inst = PyObject_GetAttrString(instance, "_obj_"); + NS_ABORT_IF_FALSE(real_inst, "Could not get the '_obj_' element"); + if (!real_inst) return; + if (!PyObject_HasAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName)) { + nsCOMPtr<nsISupportsWeakReference> swr( do_QueryInterface((nsISupportsWeakReference *)(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) { + nsCOMPtr<nsIWeakReference> pWeakReference; + swr->GetWeakReference( getter_AddRefs(pWeakReference) ); + if (pWeakReference) { + PyObject *ob_new_weak = Py_nsISupports::PyObjectFromInterface(pWeakReference, + NS_GET_IID(nsIWeakReference), + PR_FALSE ); /* bMakeNicePyObject */ + // pWeakReference reference consumed. + if (ob_new_weak) { + PyObject_SetAttrString(real_inst, PyXPCOM_szDefaultGatewayAttributeName, ob_new_weak); + Py_DECREF(ob_new_weak); + } + } + } + } + Py_DECREF(real_inst); +} diff --git a/src/libs/xpcom18a4/python/src/PyGInputStream.cpp b/src/libs/xpcom18a4/python/src/PyGInputStream.cpp new file mode 100644 index 00000000..d7c27043 --- /dev/null +++ b/src/libs/xpcom18a4/python/src/PyGInputStream.cpp @@ -0,0 +1,173 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Mark Hammond <MarkH@ActiveState.com> (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 ***** */ + +// PyGInputStream.cpp +// +// This code is part of the XPCOM extensions for Python. +// +// Written October 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +#include "PyXPCOM_std.h" +#include <nsIInputStream.h> + +class PyG_nsIInputStream : public PyG_Base, public nsIInputStream +{ +public: + PyG_nsIInputStream(PyObject *instance) : PyG_Base(instance, NS_GET_IID(nsIInputStream)) {;} + PYGATEWAY_BASE_SUPPORT(nsIInputStream, PyG_Base); + + NS_IMETHOD Close(void); + NS_IMETHOD Available(PRUint32 *_retval); + NS_IMETHOD Read(char * buf, PRUint32 count, PRUint32 *_retval); + NS_IMETHOD ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval); + NS_IMETHOD IsNonBlocking(PRBool *aNonBlocking); +}; + + +PyG_Base *MakePyG_nsIInputStream(PyObject *instance) +{ + return new PyG_nsIInputStream(instance); +} + +NS_IMETHODIMP +PyG_nsIInputStream::Close() +{ + CEnterLeavePython _celp; + const char *methodName = "close"; + return InvokeNativeViaPolicy(methodName, NULL); +} + +NS_IMETHODIMP +PyG_nsIInputStream::Available(PRUint32 *_retval) +{ + NS_PRECONDITION(_retval, "null pointer"); + CEnterLeavePython _celp; + PyObject *ret; + const char *methodName = "available"; + nsresult nr = InvokeNativeViaPolicy(methodName, &ret); + if (NS_SUCCEEDED(nr)) { + *_retval = PyInt_AsLong(ret); + if (PyErr_Occurred()) + nr = HandleNativeGatewayError(methodName); + Py_XDECREF(ret); + } + return nr; +} + +NS_IMETHODIMP +PyG_nsIInputStream::Read(char * buf, PRUint32 count, PRUint32 *_retval) +{ + NS_PRECONDITION(_retval, "null pointer"); + NS_PRECONDITION(buf, "null pointer"); + CEnterLeavePython _celp; + PyObject *ret; + const char *methodName = "read"; + nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "i", count); + if (NS_SUCCEEDED(nr)) { +#if 0 /* VBox: new buffer protocol (though I could use it for Py_LIMITED_API and ditch the warning, but cpython specific) */ + Py_buffer py_view; + if (PyObject_GetBuffer(ret, &py_view, PyBUF_SIMPLE) == 0) { + if (py_view.len <= count) { + count = py_view.len; + } else { + PyXPCOM_LogWarning("nsIInputStream::read() was asked for %d bytes, but the string returned is %d bytes - truncating!\n", count, py_size); + } + memcpy(buf, py_view.py_buf, count); + PyBuffer_Release(&py_view); + *_retval = count; + } else { + PyErr_Format(PyExc_TypeError, "nsIInputStream::read() method must return a buffer object - not a '%s' object", PyXPCOM_ObTypeName(ret)); + nr = HandleNativeGatewayError(methodName); + } +#else /* Old protocol: */ +# ifndef VBOX /* unsafe cast on 64-bit hosts. */ + PRUint32 py_size; + const void *py_buf; + if (PyObject_AsReadBuffer(ret, &py_buf, (Py_ssize_t*)&py_size)!=0) { +# else /* VBOX */ + const void *py_buf; +# if PY_VERSION_HEX >= 0x02050000 || defined(PY_SSIZE_T_MIN) + Py_ssize_t py_size; +# else + int py_size; +# endif + if (PyObject_AsReadBuffer(ret, &py_buf, &py_size)!=0) { +# endif /* VBOX */ + PyErr_Format(PyExc_TypeError, "nsIInputStream::read() method must return a buffer object - not a '%s' object", PyXPCOM_ObTypeName(ret)); + nr = HandleNativeGatewayError(methodName); + } else { + if (py_size > count) { + PyXPCOM_LogWarning("nsIInputStream::read() was asked for %d bytes, but the string returned is %d bytes - truncating!\n", count, py_size); + py_size = count; + } + memcpy(buf, py_buf, py_size); + *_retval = py_size; + } +#endif + } + return nr; +} + + +NS_IMETHODIMP +PyG_nsIInputStream::ReadSegments(nsWriteSegmentFun writer, void * closure, PRUint32 count, PRUint32 *_retval) +{ + NS_WARNING("ReadSegments() not implemented!!!"); + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP +PyG_nsIInputStream::IsNonBlocking(PRBool *aNonBlocking) +{ + NS_PRECONDITION(aNonBlocking, "null pointer"); + CEnterLeavePython _celp; + PyObject *ret; + const char *methodName = "isNonBlocking"; + nsresult nr = InvokeNativeViaPolicy(methodName, &ret); + if (NS_SUCCEEDED(nr)) { + *aNonBlocking = PyInt_AsLong(ret); + if (PyErr_Occurred()) + nr = HandleNativeGatewayError(methodName); + Py_XDECREF(ret); + } + return nr; +} diff --git a/src/libs/xpcom18a4/python/src/PyGModule.cpp b/src/libs/xpcom18a4/python/src/PyGModule.cpp new file mode 100644 index 00000000..599e0f87 --- /dev/null +++ b/src/libs/xpcom18a4/python/src/PyGModule.cpp @@ -0,0 +1,297 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * 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 ***** */ + +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +// Unfortunately, we can not use an XPConnect object for +// the nsiModule and nsiComponentLoader interfaces. +// As XPCOM shuts down, it shuts down the interface manager before +// it releases all the modules. This is a bit of a problem for +// us, as it means we can't get runtime info on the interface at shutdown time. + +#include "PyXPCOM_std.h" +#include <nsIModule.h> +#include <nsIComponentLoader.h> + +class PyG_nsIModule : public PyG_Base, public nsIModule +{ +public: + PyG_nsIModule(PyObject *instance) : PyG_Base(instance, NS_GET_IID(nsIModule)) {;} + PYGATEWAY_BASE_SUPPORT(nsIModule, PyG_Base); + + NS_DECL_NSIMODULE +}; + +PyG_Base *MakePyG_nsIModule(PyObject *instance) +{ + return new PyG_nsIModule(instance); +} + + +// Create a factory object for creating instances of aClass. +NS_IMETHODIMP +PyG_nsIModule::GetClassObject(nsIComponentManager *aCompMgr, + const nsCID& aClass, + const nsIID& aIID, + void** r_classObj) +{ + NS_PRECONDITION(r_classObj, "null pointer"); + *r_classObj = nsnull; + CEnterLeavePython _celp; + 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"; + PyObject *ret = NULL; + nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "OOO", cm, clsid, iid); + Py_XDECREF(cm); + Py_XDECREF(iid); + Py_XDECREF(clsid); + if (NS_SUCCEEDED(nr)) { + nr = Py_nsISupports::InterfaceFromPyObject(ret, aIID, (nsISupports **)r_classObj, PR_FALSE); + if (PyErr_Occurred()) + nr = HandleNativeGatewayError(methodName); + } + if (NS_FAILED(nr)) { + NS_ABORT_IF_FALSE(*r_classObj==NULL, "returning error result with an interface - probable leak!"); + } + Py_XDECREF(ret); + return nr; +} + +NS_IMETHODIMP +PyG_nsIModule::RegisterSelf(nsIComponentManager *aCompMgr, + nsIFile* aPath, + const char* registryLocation, + const char* componentType) +{ + NS_PRECONDITION(aCompMgr, "null pointer"); + NS_PRECONDITION(aPath, "null pointer"); + CEnterLeavePython _celp; + 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); + Py_XDECREF(path); + return nr; +} + +NS_IMETHODIMP +PyG_nsIModule::UnregisterSelf(nsIComponentManager* aCompMgr, + nsIFile* aPath, + const char* registryLocation) +{ + NS_PRECONDITION(aCompMgr, "null pointer"); + NS_PRECONDITION(aPath, "null pointer"); + CEnterLeavePython _celp; + 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); + Py_XDECREF(path); + return nr; +} + +NS_IMETHODIMP +PyG_nsIModule::CanUnload(nsIComponentManager *aCompMgr, PRBool *okToUnload) +{ + NS_PRECONDITION(aCompMgr, "null pointer"); + NS_PRECONDITION(okToUnload, "null pointer"); + CEnterLeavePython _celp; + // we are shutting down - don't ask for a nice wrapped object. + 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); + Py_XDECREF(cm); + if (NS_SUCCEEDED(nr)) { + *okToUnload = PyInt_AsLong(ret); + if (PyErr_Occurred()) + nr = HandleNativeGatewayError(methodName); + } + Py_XDECREF(ret); + return nr; +} + +/////////////////////////////////////////////////////////////////////////////////// + +class PyG_nsIComponentLoader : public PyG_Base, public nsIComponentLoader +{ +public: + PyG_nsIComponentLoader(PyObject *instance) : PyG_Base(instance, NS_GET_IID(nsIComponentLoader)) {;} + PYGATEWAY_BASE_SUPPORT(nsIComponentLoader, PyG_Base); + + NS_DECL_NSICOMPONENTLOADER +}; + +PyG_Base *MakePyG_nsIComponentLoader(PyObject *instance) +{ + return new PyG_nsIComponentLoader(instance); +} + +/* nsIFactory getFactory (in nsIIDRef aCID, in string aLocation, in string aType); */ +NS_IMETHODIMP PyG_nsIComponentLoader::GetFactory(const nsIID & aCID, const char *aLocation, const char *aType, nsIFactory **_retval) +{ + CEnterLeavePython _celp; + const char *methodName = "getFactory"; + PyObject *iid = Py_nsIID::PyObjectFromIID(aCID); + PyObject *ret = NULL; + nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "Ozz", + iid, + aLocation, + aType); + Py_XDECREF(iid); + if (NS_SUCCEEDED(nr)) { + Py_nsISupports::InterfaceFromPyObject(ret, NS_GET_IID(nsIFactory), (nsISupports **)_retval, PR_FALSE); + if (PyErr_Occurred()) + nr = HandleNativeGatewayError(methodName); + } + Py_XDECREF(ret); + return nr; +} + +/* void init (in nsIComponentManager aCompMgr, in nsISupports aRegistry); */ +NS_IMETHODIMP PyG_nsIComponentLoader::Init(nsIComponentManager *aCompMgr, nsISupports *aRegistry) +{ + CEnterLeavePython _celp; + const char *methodName = "init"; + PyObject *c = PyObject_FromNSInterface(aCompMgr, NS_GET_IID(nsIComponentManager)); + PyObject *r = PyObject_FromNSInterface(aRegistry, NS_GET_IID(nsISupports)); + nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "OO", c, r); + Py_XDECREF(c); + Py_XDECREF(r); + return nr; +} + +/* void onRegister (in nsIIDRef aCID, in string aType, in string aClassName, in string aContractID, in string aLocation, in boolean aReplace, in boolean aPersist); */ +NS_IMETHODIMP PyG_nsIComponentLoader::OnRegister(const nsIID & aCID, const char *aType, const char *aClassName, const char *aContractID, const char *aLocation, PRBool aReplace, PRBool aPersist) +{ + CEnterLeavePython _celp; + const char *methodName = "onRegister"; + PyObject *iid = Py_nsIID::PyObjectFromIID(aCID); + nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "Ossssii", + iid, + aType, + aClassName, + aContractID, + aLocation, + aReplace, + aPersist); + Py_XDECREF(iid); + return nr; +} + +/* void autoRegisterComponents (in long aWhen, in nsIFile aDirectory); */ +NS_IMETHODIMP PyG_nsIComponentLoader::AutoRegisterComponents(PRInt32 aWhen, nsIFile *aDirectory) +{ + CEnterLeavePython _celp; + const char *methodName = "autoRegisterComponents"; + PyObject *c = PyObject_FromNSInterface(aDirectory, NS_GET_IID(nsIFile)); + nsresult nr = InvokeNativeViaPolicy(methodName, NULL, "iO", aWhen, c); + Py_XDECREF(c); + return nr; +} + +/* boolean autoRegisterComponent (in long aWhen, in nsIFile aComponent); */ +NS_IMETHODIMP PyG_nsIComponentLoader::AutoRegisterComponent(PRInt32 aWhen, nsIFile *aComponent, PRBool *_retval) +{ + CEnterLeavePython _celp; + const char *methodName = "autoRegisterComponent"; + PyObject *ret = NULL; + PyObject *c = PyObject_FromNSInterface(aComponent, NS_GET_IID(nsIFile)); + nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "iO", aWhen, c); + Py_XDECREF(c); + if (NS_SUCCEEDED(nr)) { + *_retval = PyInt_AsLong(ret); + if (PyErr_Occurred()) + nr = HandleNativeGatewayError(methodName); + } + Py_XDECREF(ret); + return nr; +} + +/* boolean autoUnregisterComponent (in long aWhen, in nsIFile aComponent); */ +NS_IMETHODIMP PyG_nsIComponentLoader::AutoUnregisterComponent(PRInt32 aWhen, nsIFile *aComponent, PRBool *_retval) +{ + CEnterLeavePython _celp; + const char *methodName = "autoUnregisterComponent"; + PyObject *ret = NULL; + PyObject *c = PyObject_FromNSInterface(aComponent, NS_GET_IID(nsIFile)); + nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "iO", aWhen, c); + Py_XDECREF(c); + if (NS_SUCCEEDED(nr)) { + *_retval = PyInt_AsLong(ret); + if (PyErr_Occurred()) + nr = HandleNativeGatewayError(methodName); + } + Py_XDECREF(ret); + return nr; +} + +/* boolean registerDeferredComponents (in long aWhen); */ +NS_IMETHODIMP PyG_nsIComponentLoader::RegisterDeferredComponents(PRInt32 aWhen, PRBool *_retval) +{ + CEnterLeavePython _celp; + const char *methodName = "registerDeferredComponents"; + PyObject *ret = NULL; + nsresult nr = InvokeNativeViaPolicy(methodName, &ret, "i", aWhen); + if (NS_SUCCEEDED(nr)) { + *_retval = PyInt_AsLong(ret); + if (PyErr_Occurred()) + nr = HandleNativeGatewayError(methodName); + } + Py_XDECREF(ret); + return nr; +} + +/* void unloadAll (in long aWhen); */ +NS_IMETHODIMP PyG_nsIComponentLoader::UnloadAll(PRInt32 aWhen) +{ + CEnterLeavePython _celp; + const char *methodName = "unloadAll"; + return InvokeNativeViaPolicy(methodName, NULL, "i", aWhen); +} diff --git a/src/libs/xpcom18a4/python/src/PyGStub.cpp b/src/libs/xpcom18a4/python/src/PyGStub.cpp new file mode 100644 index 00000000..6f219333 --- /dev/null +++ b/src/libs/xpcom18a4/python/src/PyGStub.cpp @@ -0,0 +1,180 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * 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 ***** */ + +// PyXPTStub - the stub for implementing interfaces. +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +#include "PyXPCOM_std.h" +#include <nsIInterfaceInfoManager.h> + +void *PyXPCOM_XPTStub::ThisAsIID(const nsIID &iid) +{ + if (iid.Equals(NS_GET_IID(nsISupports))) + return (nsISupports *)(nsXPTCStubBase *)this; + else if (iid.Equals(m_iid)) + return (nsISupports *)(nsXPTCStubBase *)this; + else + return PyG_Base::ThisAsIID(iid); +} + + +NS_IMETHODIMP +PyXPCOM_XPTStub::GetInterfaceInfo(nsIInterfaceInfo** info) +{ + NS_PRECONDITION(info, "NULL pointer"); + if (info==nsnull) + return NS_ERROR_NULL_POINTER; + // Simply get the XPCOM runtime to provide this + // (but there must be some reason why they dont get it themselves!? + // Maybe because they dont know the IID? + nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService( + NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)); + NS_ABORT_IF_FALSE(iim != nsnull, "Cant get interface from IIM!"); + if (iim==nsnull) + return NS_ERROR_FAILURE; + + return iim->GetInfoForIID( &m_iid, info); +} + +// call this method and return result +NS_IMETHODIMP +PyXPCOM_XPTStub::CallMethod(PRUint16 methodIndex, + const nsXPTMethodInfo* info, + nsXPTCMiniVariant* params) +{ + nsresult rc = NS_ERROR_FAILURE; + NS_PRECONDITION(info, "NULL methodinfo pointer"); + NS_PRECONDITION(params, "NULL variant pointer"); + CEnterLeavePython _celp; + PyObject *obParams = NULL; + PyObject *result = NULL; + PyObject *obThisObject = NULL; + PyObject *obMI = PyObject_FromXPTMethodDescriptor(info); + PyXPCOM_GatewayVariantHelper arg_helper(this, methodIndex, info, params); + if (obMI==NULL) + goto done; + // base object is passed raw. + obThisObject = PyObject_FromNSInterface((nsXPTCStubBase *)this, + m_iid, PR_FALSE); + obParams = arg_helper.MakePyArgs(); + if (obParams==NULL) + goto done; + result = PyObject_CallMethod(m_pPyObject, + (char*)"_CallMethod_", + (char*)"OiOO", + obThisObject, + (int)methodIndex, + obMI, + obParams); + if (result!=NULL) { + rc = arg_helper.ProcessPythonResult(result); + // Use an xor to check failure && pyerr, or !failure && !pyerr. + NS_ABORT_IF_FALSE( ((NS_FAILED(rc)!=0)^(PyErr_Occurred()!=0)) == 0, "We must have failure with a Python error, or success without a Python error."); + } +done: + if (PyErr_Occurred()) { + // The error handling - fairly involved, but worth it as + // 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 + // exited, but we encountered errors unpacking the + // 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) + + // 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. + + PRBool bProcessMainError = PR_TRUE; // set to false if our exception handler does its thing! + PyObject *exc_typ, *exc_val, *exc_tb; + PyErr_Fetch(&exc_typ, &exc_val, &exc_tb); + PyErr_NormalizeException( &exc_typ, &exc_val, &exc_tb); + + PyObject *err_result = PyObject_CallMethod(m_pPyObject, + (char*)"_CallMethodException_", + (char*)"OiOO(OOO)", + obThisObject, + (int)methodIndex, + obMI, + obParams, + exc_typ ? exc_typ : Py_None, // should never be NULL, but defensive programming... + exc_val ? exc_val : Py_None, // may well be NULL. + exc_tb ? exc_tb : Py_None); // may well be NULL. + if (err_result == NULL) { + PyXPCOM_LogError("The exception handler _CallMethodException_ failed!\n"); + } else if (err_result == Py_None) { + // The exception handler has chosen not to do anything with + // this error, so we still need to print it! + ; + } else if (PyInt_Check(err_result)) { + // The exception handler has given us the nresult. + rc = PyInt_AsLong(err_result); + bProcessMainError = PR_FALSE; + } else { + // The exception handler succeeded, but returned other than + // int or None. + PyXPCOM_LogError("The _CallMethodException_ handler returned object of type '%s' - None or an integer expected\n", PyXPCOM_ObTypeName(err_result)); + } + Py_XDECREF(err_result); + PyErr_Restore(exc_typ, exc_val, exc_tb); + if (bProcessMainError) { + PyXPCOM_LogError("The function '%s' failed\n", info->GetName()); + rc = PyXPCOM_SetCOMErrorFromPyException(); + } + // else everything is already setup, + // just clear the Python error state. + PyErr_Clear(); + } + + Py_XDECREF(obMI); + Py_XDECREF(obParams); + Py_XDECREF(obThisObject); + Py_XDECREF(result); + return rc; +} diff --git a/src/libs/xpcom18a4/python/src/PyGWeakReference.cpp b/src/libs/xpcom18a4/python/src/PyGWeakReference.cpp new file mode 100644 index 00000000..e5254acc --- /dev/null +++ b/src/libs/xpcom18a4/python/src/PyGWeakReference.cpp @@ -0,0 +1,112 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Mark Hammond <MarkH@ActiveState.com> (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 ***** */ + +// PyGWeakReference - implements weak references for gateways. +// +// This code is part of the XPCOM extensions for Python. +// +// Written November 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +#include "PyXPCOM_std.h" + +PyXPCOM_GatewayWeakReference::PyXPCOM_GatewayWeakReference( PyG_Base *base ) +{ + m_pBase = base; + +#ifdef NS_BUILD_REFCNT_LOGGING + // bloat view uses 40 chars - stick "(WR)" at the end of this position. + strncpy(refcntLogRepr, m_pBase->refcntLogRepr, sizeof(refcntLogRepr)); + refcntLogRepr[sizeof(refcntLogRepr)-1] = '\0'; + char *dest = refcntLogRepr + ((strlen(refcntLogRepr) > 36) ? 36 : strlen(refcntLogRepr)); + strcpy(dest, "(WR)"); +#endif // NS_BUILD_REFCNT_LOGGING +} + +PyXPCOM_GatewayWeakReference::~PyXPCOM_GatewayWeakReference() +{ + // Simply zap my reference to the gateway! + // No need to zap my gateway's reference to me, as + // it already holds a reference, so if we are destructing, + // then it can't possibly hold one. + m_pBase = NULL; +} + +nsrefcnt +PyXPCOM_GatewayWeakReference::AddRef(void) +{ + nsrefcnt cnt = (nsrefcnt) PR_AtomicIncrement((PRInt32*)&mRefCnt); +#ifdef NS_BUILD_REFCNT_LOGGING + NS_LOG_ADDREF(this, cnt, refcntLogRepr, sizeof(*this)); +#endif + return cnt; +} + +nsrefcnt +PyXPCOM_GatewayWeakReference::Release(void) +{ + nsrefcnt cnt = (nsrefcnt) PR_AtomicDecrement((PRInt32*)&mRefCnt); +#ifdef NS_BUILD_REFCNT_LOGGING + NS_LOG_RELEASE(this, cnt, refcntLogRepr); +#endif + if ( cnt == 0 ) + delete this; + return cnt; +} + +NS_IMPL_THREADSAFE_QUERY_INTERFACE1(PyXPCOM_GatewayWeakReference, nsIWeakReference) + +NS_IMETHODIMP +PyXPCOM_GatewayWeakReference::QueryReferent(REFNSIID iid, void * *ret) +{ + { + // Temp scope for lock. We can't hold the lock during + // a QI, as this may itself need the lock. + // Make sure our object isn't dieing right now on another thread. + CEnterLeaveXPCOMFramework _celf; + if (m_pBase == NULL) + return NS_ERROR_NULL_POINTER; + m_pBase->AddRef(); // Can't die while we have a ref. + } // end of lock scope - lock unlocked. + nsresult nr = m_pBase->QueryInterface(iid, ret); + m_pBase->Release(); + return nr; +} diff --git a/src/libs/xpcom18a4/python/src/PyIClassInfo.cpp b/src/libs/xpcom18a4/python/src/PyIClassInfo.cpp new file mode 100644 index 00000000..6d0f499d --- /dev/null +++ b/src/libs/xpcom18a4/python/src/PyIClassInfo.cpp @@ -0,0 +1,181 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. Portions created by ActiveState Tool Corp. are Copyright (C) 2001 ActiveState Tool Corp. All Rights Reserved. + * Portions created by the Initial Developer are Copyright (C) 2001 + * 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 ***** */ + +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2001 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2001, ActiveState corp. + +#include "PyXPCOM_std.h" +#include "nsIClassInfo.h" + +static nsIClassInfo *_GetI(PyObject *self) { + nsIID iid = NS_GET_IID(nsIClassInfo); + + if (!Py_nsISupports::Check(self, iid)) { + PyErr_SetString(PyExc_TypeError, "This object is not the correct interface"); + return NULL; + } + return (nsIClassInfo *)Py_nsISupports::GetI(self); +} + +static PyObject *PyGetInterfaces(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + nsIClassInfo *pI = _GetI(self); + if (pI==NULL) + return NULL; + + nsIID** iidArray = nsnull; + PRUint32 iidCount = 0; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->GetInterfaces(&iidCount, &iidArray); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + + PyObject *ret = PyTuple_New(iidCount); + if (ret==NULL) + return NULL; + for (PRUint32 i=0;i<iidCount;i++) + PyTuple_SET_ITEM( ret, i, Py_nsIID::PyObjectFromIID(*(iidArray[i])) ); + return ret; +} + +static PyObject *PyGetHelperForLanguage(PyObject *self, PyObject *args) +{ + PRUint32 language = nsIProgrammingLanguage::PYTHON; + if (!PyArg_ParseTuple(args, "|i", &language)) + return NULL; + nsIClassInfo *pI = _GetI(self); + if (pI==NULL) + return NULL; + + nsresult r; + nsCOMPtr<nsISupports> pi; + Py_BEGIN_ALLOW_THREADS; + 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)); +} + +static PyObject *MakeStringOrNone(char *v) +{ + if (v) +#if PY_MAJOR_VERSION <= 2 + return PyString_FromString(v); +#else + return PyUnicode_FromString(v); +#endif + Py_INCREF(Py_None); + return Py_None; +} + +#define GETATTR_CHECK_RESULT(nr) if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr) + +PyObject * +Py_nsIClassInfo::getattr(const char *name) +{ + nsIClassInfo *pI = _GetI(this); + if (pI==NULL) + return NULL; + + nsresult nr; + PyObject *ret = NULL; + if (strcmp(name, "contractID")==0) { + char *str_ret = NULL; + Py_BEGIN_ALLOW_THREADS; + nr = pI->GetContractID(&str_ret); + Py_END_ALLOW_THREADS; + GETATTR_CHECK_RESULT(nr); + ret = MakeStringOrNone(str_ret); + nsMemory::Free(str_ret); + } else if (strcmp(name, "classDescription")==0) { + char *str_ret = NULL; + Py_BEGIN_ALLOW_THREADS; + nr = pI->GetClassDescription(&str_ret); + Py_END_ALLOW_THREADS; + GETATTR_CHECK_RESULT(nr); + ret = MakeStringOrNone(str_ret); + nsMemory::Free(str_ret); + } else if (strcmp(name, "classID")==0) { + nsIID *iid = NULL; + Py_BEGIN_ALLOW_THREADS; + nr = pI->GetClassID(&iid); + Py_END_ALLOW_THREADS; + GETATTR_CHECK_RESULT(nr); + ret = Py_nsIID::PyObjectFromIID(*iid); + nsMemory::Free(iid); + } else if (strcmp(name, "implementationLanguage")==0) { + PRUint32 i; + Py_BEGIN_ALLOW_THREADS; + nr = pI->GetImplementationLanguage(&i); + Py_END_ALLOW_THREADS; + GETATTR_CHECK_RESULT(nr); + ret = PyInt_FromLong(i); + } else { + ret = Py_nsISupports::getattr(name); + } + return ret; +} + +int +Py_nsIClassInfo::setattr(const char *name, PyObject *v) +{ + return Py_nsISupports::setattr(name, v); + +} + +struct PyMethodDef +PyMethods_IClassInfo[] = +{ + { "getInterfaces", PyGetInterfaces, 1}, + { "GetInterfaces", PyGetInterfaces, 1}, + { "getHelperForLanguage", PyGetHelperForLanguage, 1}, + { "GetHelperForLanguage", PyGetHelperForLanguage, 1}, + {NULL} +}; diff --git a/src/libs/xpcom18a4/python/src/PyIComponentManager.cpp b/src/libs/xpcom18a4/python/src/PyIComponentManager.cpp new file mode 100644 index 00000000..c3b89112 --- /dev/null +++ b/src/libs/xpcom18a4/python/src/PyIComponentManager.cpp @@ -0,0 +1,138 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * 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 ***** */ + +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +#include "PyXPCOM_std.h" + +static nsIComponentManager *GetI(PyObject *self) { + static const nsIID iid = NS_GET_IID(nsIComponentManager); + + if (!Py_nsISupports::Check(self, iid)) { + PyErr_SetString(PyExc_TypeError, "This object is not the correct interface"); + return NULL; + } + return NS_STATIC_CAST(nsIComponentManager*, Py_nsISupports::GetI(self)); +} + +static PyObject *PyCreateInstanceByContractID(PyObject *self, PyObject *args) +{ + // second arg to CreateInstanceByContractID is a "delegate" - we + // aren't sure of the semantics of this yet and it seems rarely used, + // so we just punt for now. + char *pid, *notyet = NULL; + PyObject *obIID = NULL; + if (!PyArg_ParseTuple(args, "s|zO", &pid, ¬yet, &obIID)) + return NULL; + if (notyet != NULL) { + PyErr_SetString(PyExc_ValueError, "2nd arg must be none"); + return NULL; + } + nsIComponentManager *pI = GetI(self); + if (pI==NULL) + return NULL; + + nsIID iid; + if (obIID==NULL) + iid = NS_GET_IID(nsISupports); + else + if (!Py_nsIID::IIDFromPyObject(obIID, &iid)) + return NULL; + + nsCOMPtr<nsISupports> pis; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + 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); +} + +static PyObject *PyCreateInstance(PyObject *self, PyObject *args) +{ + char *notyet = NULL; + PyObject *obClassID = NULL, *obIID = NULL; + if (!PyArg_ParseTuple(args, "O|zO", &obClassID, ¬yet, &obIID)) + return NULL; + if (notyet != NULL) { + PyErr_SetString(PyExc_ValueError, "2nd arg must be none"); + return NULL; + } + nsIComponentManager *pI = GetI(self); + if (pI==NULL) + return NULL; + + nsIID classID; + if (!Py_nsIID::IIDFromPyObject(obClassID, &classID)) + return NULL; + nsIID iid; + if (obIID==NULL) + iid = NS_GET_IID(nsISupports); + else + if (!Py_nsIID::IIDFromPyObject(obIID, &iid)) + return NULL; + + nsCOMPtr<nsISupports> pis; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + 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); +} + +struct PyMethodDef +PyMethods_IComponentManager[] = +{ + { "createInstanceByContractID", PyCreateInstanceByContractID, 1}, + { "createInstance", PyCreateInstance, 1}, + {NULL} +}; diff --git a/src/libs/xpcom18a4/python/src/PyIComponentManagerObsolete.cpp b/src/libs/xpcom18a4/python/src/PyIComponentManagerObsolete.cpp new file mode 100644 index 00000000..7d07d421 --- /dev/null +++ b/src/libs/xpcom18a4/python/src/PyIComponentManagerObsolete.cpp @@ -0,0 +1,203 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * 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 ***** */ + +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +#include "PyXPCOM_std.h" + +static nsIComponentManagerObsolete *GetI(PyObject *self) { + static const nsIID iid = NS_GET_IID(nsIComponentManagerObsolete); + + if (!Py_nsISupports::Check(self, iid)) { + PyErr_SetString(PyExc_TypeError, "This object is not the correct interface"); + return NULL; + } + return (nsIComponentManagerObsolete *)Py_nsISupports::GetI(self); +} + +static PyObject *PyCreateInstanceByContractID(PyObject *self, PyObject *args) +{ + char *pid, *notyet = NULL; + PyObject *obIID = NULL; + if (!PyArg_ParseTuple(args, "s|zO", &pid, ¬yet, &obIID)) + return NULL; + if (notyet != NULL) { + PyErr_SetString(PyExc_ValueError, "2nd arg must be none"); + return NULL; + } + nsIComponentManagerObsolete *pI = GetI(self); + if (pI==NULL) + return NULL; + + nsIID iid; + if (obIID==NULL) + iid = NS_GET_IID(nsISupports); + else + if (!Py_nsIID::IIDFromPyObject(obIID, &iid)) + return NULL; + + nsISupports *pis; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->CreateInstanceByContractID(pid, NULL, iid, (void **)&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); +} + +static PyObject *PyContractIDToClassID(PyObject *self, PyObject *args) +{ + char *pid; + if (!PyArg_ParseTuple(args, "s", &pid)) + return NULL; + nsIComponentManagerObsolete *pI = GetI(self); + if (pI==NULL) + return NULL; + + nsIID iid; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->ContractIDToClassID(pid, &iid); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + + return Py_nsIID::PyObjectFromIID(iid); +} + +static PyObject *PyCLSIDToContractID(PyObject *self, PyObject *args) +{ + PyObject *obIID; + if (!PyArg_ParseTuple(args, "O", &obIID)) + return NULL; + + nsIID iid; + if (!Py_nsIID::IIDFromPyObject(obIID, &iid)) + return NULL; + char *ret_pid = nsnull; + char *ret_class = nsnull; + nsIComponentManagerObsolete *pI = GetI(self); + if (pI==NULL) + return NULL; + + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->CLSIDToContractID(iid, &ret_class, &ret_pid); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + +#if PY_MAJOR_VERSION <= 2 + PyObject *ob_pid = PyString_FromString(ret_pid); + PyObject *ob_class = PyString_FromString(ret_class); +#else + PyObject *ob_pid = PyUnicode_FromString(ret_pid); + PyObject *ob_class = PyUnicode_FromString(ret_class); +#endif + PyObject *ret = Py_BuildValue("OO", ob_pid, ob_class); + nsMemory::Free(ret_pid); + nsMemory::Free(ret_class); + Py_XDECREF(ob_pid); + Py_XDECREF(ob_class); + return ret; +} + +static PyObject *PyEnumerateCLSIDs(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + + nsIComponentManagerObsolete *pI = GetI(self); + if (pI==NULL) + return NULL; + + nsIEnumerator *pRet; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->EnumerateCLSIDs(&pRet); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + + return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIEnumerator), PR_FALSE); +} + +static PyObject *PyEnumerateContractIDs(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + + nsIComponentManagerObsolete *pI = GetI(self); + if (pI==NULL) + return NULL; + + nsIEnumerator *pRet; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->EnumerateContractIDs(&pRet); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + + return Py_nsISupports::PyObjectFromInterface(pRet, NS_GET_IID(nsIEnumerator), PR_FALSE); +} + +struct PyMethodDef +PyMethods_IComponentManagerObsolete[] = +{ + { "CreateInstanceByContractID", PyCreateInstanceByContractID, 1}, + { "createInstanceByContractID", PyCreateInstanceByContractID, 1}, + { "EnumerateCLSIDs", PyEnumerateCLSIDs, 1}, + { "enumerateCLSIDs", PyEnumerateCLSIDs, 1}, + { "EnumerateContractIDs", PyEnumerateContractIDs, 1}, + { "enumerateContractIDs", PyEnumerateContractIDs, 1}, + { "ContractIDToClassID", PyContractIDToClassID, 1}, + { "contractIDToClassID", PyContractIDToClassID, 1}, + { "CLSIDToContractID", PyCLSIDToContractID, 1}, + {NULL} +}; diff --git a/src/libs/xpcom18a4/python/src/PyIEnumerator.cpp b/src/libs/xpcom18a4/python/src/PyIEnumerator.cpp new file mode 100644 index 00000000..b196d956 --- /dev/null +++ b/src/libs/xpcom18a4/python/src/PyIEnumerator.cpp @@ -0,0 +1,235 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Mark Hammond <MarkH@ActiveState.com> (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 ***** */ + +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +#include "PyXPCOM_std.h" +#include <nsIEnumerator.h> + +static nsIEnumerator *GetI(PyObject *self) { + nsIID iid = NS_GET_IID(nsIEnumerator); + + if (!Py_nsISupports::Check(self, iid)) { + PyErr_SetString(PyExc_TypeError, "This object is not the correct interface"); + return NULL; + } + return (nsIEnumerator *)Py_nsISupports::GetI(self); +} + +static PyObject *PyFirst(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, ":First")) + return NULL; + + nsIEnumerator *pI = GetI(self); + if (pI==NULL) + return NULL; + + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->First(); + Py_END_ALLOW_THREADS; + return PyInt_FromLong(r); +} + +static PyObject *PyNext(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, ":Next")) + return NULL; + + nsIEnumerator *pI = GetI(self); + if (pI==NULL) + return NULL; + + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->Next(); + Py_END_ALLOW_THREADS; + return PyInt_FromLong(r); +} + +static PyObject *PyCurrentItem(PyObject *self, PyObject *args) +{ + PyObject *obIID = NULL; + if (!PyArg_ParseTuple(args, "|O:CurrentItem", &obIID)) + return NULL; + + nsIID iid(NS_GET_IID(nsISupports)); + if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid)) + return NULL; + nsIEnumerator *pI = GetI(self); + if (pI==NULL) + return NULL; + + nsISupports *pRet = nsnull; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->CurrentItem(&pRet); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + if (obIID) { + nsISupports *temp; + Py_BEGIN_ALLOW_THREADS; + r = pRet->QueryInterface(iid, (void **)&temp); + pRet->Release(); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) { + return PyXPCOM_BuildPyException(r); + } + pRet = temp; + } + PyObject *ret = Py_nsISupports::PyObjectFromInterface(pRet, iid); + NS_IF_RELEASE(pRet); + return ret; +} + +// A method added for Python performance if you really need +// it. Allows you to fetch a block of objects in one +// hit, allowing the loop to remain implemented in C. +static PyObject *PyFetchBlock(PyObject *self, PyObject *args) +{ + PyObject *obIID = NULL; + int n_wanted; + int n_fetched = 0; + if (!PyArg_ParseTuple(args, "i|O:FetchBlock", &n_wanted, &obIID)) + return NULL; + + nsIID iid(NS_GET_IID(nsISupports)); + if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid)) + return NULL; + nsIEnumerator *pI = GetI(self); + if (pI==NULL) + return NULL; + + // We want to fetch with the thread-lock released, + // but this means we can not append to the PyList + nsISupports **fetched = new nsISupports*[n_wanted]; + if (fetched==nsnull) { + PyErr_NoMemory(); + return NULL; + } + memset(fetched, 0, sizeof(nsISupports *) * n_wanted); + nsresult r = NS_OK; + Py_BEGIN_ALLOW_THREADS; + for (;n_fetched<n_wanted;) { + nsISupports *pNew; + r = pI->CurrentItem(&pNew); + if (NS_FAILED(r)) { + r = 0; // Normal enum end + break; + } + if (obIID) { + nsISupports *temp; + r = pNew->QueryInterface(iid, (void **)&temp); + pNew->Release(); + if ( NS_FAILED(r) ) { + break; + } + pNew = temp; + } + fetched[n_fetched] = pNew; + n_fetched++; // must increment before breaking out. + if (NS_FAILED(pI->Next())) + break; // not an error condition. + } + Py_END_ALLOW_THREADS; + PyObject *ret; + if (NS_SUCCEEDED(r)) { + ret = PyList_New(n_fetched); + if (ret) + for (int i=0;i<n_fetched;i++) { + PyObject *new_ob = Py_nsISupports::PyObjectFromInterface(fetched[i], iid); + NS_IF_RELEASE(fetched[i]); + PyList_SET_ITEM(ret, i, new_ob); + } + } else + ret = PyXPCOM_BuildPyException(r); + + if ( ret == NULL ) { + // Free the objects we consumed. + for (int i=0;i<n_fetched;i++) + fetched[i]->Release(); + + } + delete [] fetched; + return ret; +} + +static PyObject *PyIsDone(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, ":IsDone")) + return NULL; + + nsIEnumerator *pI = GetI(self); + nsresult r; + if (pI==NULL) + return NULL; + + Py_BEGIN_ALLOW_THREADS; + r = pI->IsDone(); + Py_END_ALLOW_THREADS; + if (NS_FAILED(r)) + return PyXPCOM_BuildPyException(r); + PyObject *ret = r==NS_OK ? Py_True : Py_False; + Py_INCREF(ret); + return ret; +} + +struct PyMethodDef +PyMethods_IEnumerator[] = +{ + { "First", PyFirst, 1}, + { "first", PyFirst, 1}, + { "Next", PyNext, 1}, + { "next", PyNext, 1}, + { "CurrentItem", PyCurrentItem, 1}, + { "currentItem", PyCurrentItem, 1}, + { "IsDone", PyIsDone, 1}, + { "isDone", PyIsDone, 1}, + { "FetchBlock", PyFetchBlock, 1}, + { "fetchBlock", PyFetchBlock, 1}, + {NULL} +}; diff --git a/src/libs/xpcom18a4/python/src/PyIID.cpp b/src/libs/xpcom18a4/python/src/PyIID.cpp new file mode 100644 index 00000000..f24ae20e --- /dev/null +++ b/src/libs/xpcom18a4/python/src/PyIID.cpp @@ -0,0 +1,410 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * 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 ***** */ + +// Py_nsIID.cpp -- IID type for Python/XPCOM +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. +// +// @doc + +#include "PyXPCOM_std.h" +#include <nsIInterfaceInfoManager.h> + +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 +PYXPCOM_EXPORT PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args) +{ + PyObject *obIID; + PyObject *obBuf; + if ( PyArg_ParseTuple(args, "O", &obBuf)) { +#if PY_MAJOR_VERSION <= 2 + if (PyBuffer_Check(obBuf)) { + PyBufferProcs *pb = NULL; + pb = obBuf->ob_type->tp_as_buffer; + void *buf = NULL; + int size = (*pb->bf_getreadbuffer)(obBuf, 0, &buf); +#else + if (PyObject_CheckBuffer(obBuf)) { +# ifndef Py_LIMITED_API + Py_buffer view; + if (PyObject_GetBuffer(obBuf, &view, PyBUF_CONTIG_RO) != 0) { + PyErr_Format(PyExc_ValueError, "Could not get contiguous buffer from object"); + return NULL; + } + Py_ssize_t size = view.len; + const void *buf = view.buf; +# else /* Py_LIMITED_API - the buffer API is non-existant, from what I can tell */ + const void *buf = NULL; + Py_ssize_t size = 0; + if (PyObject_AsReadBuffer(obBuf, &buf, &size) != 0) { + PyErr_Format(PyExc_ValueError, "Could not get read-only buffer from object"); + return NULL; + } +# endif /* Py_LIMITED_API */ +#endif + if (size != sizeof(nsIID) || buf==NULL) { +#if PY_MAJOR_VERSION >= 3 && !defined(Py_LIMITED_API) + PyBuffer_Release(&view); +#endif +#ifdef VBOX + PyErr_Format(PyExc_ValueError, "A buffer object to be converted to an IID must be exactly %d bytes long", (int)sizeof(nsIID)); +#else + PyErr_Format(PyExc_ValueError, "A buffer object to be converted to an IID must be exactly %d bytes long", sizeof(nsIID)); +#endif + return NULL; + } + nsIID iid; + unsigned char const *ptr = (unsigned char const *)buf; + iid.m0 = XPT_SWAB32(*((PRUint32 *)ptr)); + ptr = ((unsigned char const *)buf) + offsetof(nsIID, m1); + iid.m1 = XPT_SWAB16(*((PRUint16 *)ptr)); + ptr = ((unsigned char const *)buf) + offsetof(nsIID, m2); + iid.m2 = XPT_SWAB16(*((PRUint16 *)ptr)); + ptr = ((unsigned char const *)buf) + offsetof(nsIID, m3); + for (int i=0;i<8;i++) { + iid.m3[i] = *((PRUint8 const *)ptr); + ptr += sizeof(PRUint8); + } +#if PY_MAJOR_VERSION >= 3 && !defined(Py_LIMITED_API) + PyBuffer_Release(&view); +#endif + return new Py_nsIID(iid); + } + } + PyErr_Clear(); + // @pyparm string/Unicode|iidString||A string representation of an IID, or a ContractID. + if ( !PyArg_ParseTuple(args, "O", &obIID) ) + return NULL; + + nsIID iid; + if (!Py_nsIID::IIDFromPyObject(obIID, &iid)) + return NULL; + return new Py_nsIID(iid); +} + +/*static*/ PRBool +Py_nsIID::IIDFromPyObject(PyObject *ob, nsIID *pRet) { + PRBool ok = PR_TRUE; + nsIID iid; + if (ob==NULL) { + PyErr_SetString(PyExc_RuntimeError, "The IID object is invalid!"); + return PR_FALSE; + } +#if PY_MAJOR_VERSION <= 2 + if (PyString_Check(ob)) { + ok = iid.Parse(PyString_AsString(ob)); +#else + if (PyUnicode_Check(ob)) { + ok = iid.Parse(PyUnicode_AsUTF8(ob)); +#endif + if (!ok) { + PyXPCOM_BuildPyException(NS_ERROR_ILLEGAL_VALUE); + return PR_FALSE; + } +#ifndef Py_LIMITED_API + } else if (ob->ob_type == &type) { +#else + } else if (ob->ob_type == Py_nsIID::GetTypeObject()) { +#endif + iid = ((Py_nsIID *)ob)->m_iid; + } else if (PyObject_HasAttrString(ob, "__class__")) { + // Get the _iidobj_ attribute + PyObject *use_ob = PyObject_GetAttrString(ob, "_iidobj_"); + if (use_ob==NULL) { + PyErr_SetString(PyExc_TypeError, "Only instances with _iidobj_ attributes can be used as IID objects"); + return PR_FALSE; + } +#ifndef Py_LIMITED_API + if (use_ob->ob_type != &type) { +#else + if (use_ob->ob_type != Py_nsIID::GetTypeObject()) { +#endif + Py_DECREF(use_ob); + PyErr_SetString(PyExc_TypeError, "instance _iidobj_ attributes must be raw IID object"); + return PR_FALSE; + } + iid = ((Py_nsIID *)use_ob)->m_iid; + Py_DECREF(use_ob); + } else { + PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be converted to an IID", PyXPCOM_ObTypeName(ob)); + ok = PR_FALSE; + } + if (ok) *pRet = iid; + return ok; +} + + +// @object Py_nsIID|A Python object, representing an IID/CLSID. +// <nl>All pythoncom functions that return a CLSID/IID will return one of these +// objects. However, in almost all cases, functions that expect a CLSID/IID +// as a param will accept either a string object, or a native Py_nsIID object. +#ifndef Py_LIMITED_API +PyTypeObject Py_nsIID::type = +{ + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "IID", + sizeof(Py_nsIID), + 0, + PyTypeMethod_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + PyTypeMethod_getattr, /* tp_getattr */ + 0, /* tp_setattr */ +#if PY_MAJOR_VERSION <= 2 + PyTypeMethod_compare, /* tp_compare */ +#else + 0, /* reserved */ +#endif + PyTypeMethod_repr, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + PyTypeMethod_hash, /* tp_hash */ + 0, /* tp_call */ + PyTypeMethod_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 */ + PyTypeMethod_richcompare, /* tp_richcompare */ + 0, /* tp_weaklistoffset */ + 0, /* tp_iter */ + 0, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ +}; +#else /* Py_LIMITED_API */ +NS_EXPORT_STATIC_MEMBER_(PyTypeObject *) Py_nsIID::s_pType = NULL; + +PyTypeObject *Py_nsIID::GetTypeObject(void) +{ + PyTypeObject *pTypeObj = Py_nsIID::s_pType; + if (pTypeObj) + return pTypeObj; + + PyType_Slot aTypeSlots[] = { + { Py_tp_base, &PyType_Type }, + { Py_tp_dealloc, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_dealloc }, + { Py_tp_getattr, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_getattr }, + { Py_tp_repr, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_repr }, + { Py_tp_hash, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_hash }, + { Py_tp_str, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_str }, + { Py_tp_richcompare, (void *)(uintptr_t)&Py_nsIID::PyTypeMethod_richcompare }, + { 0, NULL } /* terminator */ + }; + PyType_Spec TypeSpec = { + /* .name: */ "IID", + /* .basicsize: */ sizeof(Py_nsIID), + /* .itemsize: */ 0, + /* .flags: */ 0, + /* .slots: */ aTypeSlots, + }; + + PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL; + PyErr_Fetch(&exc_typ, &exc_val, &exc_tb); /* goes south in PyType_Ready if we don't clear exceptions first. */ + + pTypeObj = (PyTypeObject *)PyType_FromSpec(&TypeSpec); + assert(pTypeObj); + + PyErr_Restore(exc_typ, exc_val, exc_tb); + Py_nsIID::s_pType = pTypeObj; + return pTypeObj; +} +#endif /* Py_LIMITED_API */ + +Py_nsIID::Py_nsIID(const nsIID &riid) +{ +#ifndef Py_LIMITED_API + ob_type = &type; +#else + ob_type = GetTypeObject(); +#endif +#if 1 /* VBox: Must use for 3.9+, includes _Py_NewReferences. Works for all older versions too. @bugref{10079} */ + PyObject_Init(this, ob_type); +#else + _Py_NewReference(this); +#endif + + m_iid = riid; +} + +/*static*/PyObject * +Py_nsIID::PyTypeMethod_getattr(PyObject *self, char *name) +{ + Py_nsIID *me = (Py_nsIID *)self; + if (strcmp(name, "name")==0) { + char *iid_repr = nsnull; + nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService( + NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)); + if (iim!=nsnull) + iim->GetNameForIID(&me->m_iid, &iid_repr); + if (iid_repr==nsnull) + iid_repr = me->m_iid.ToString(); + PyObject *ret; + if (iid_repr != nsnull) { +#if PY_MAJOR_VERSION <= 2 + ret = PyString_FromString(iid_repr); +#else + ret = PyUnicode_FromString(iid_repr); +#endif + nsMemory::Free(iid_repr); + } else +#if PY_MAJOR_VERSION <= 2 + ret = PyString_FromString("<cant get IID info!>"); +#else + ret = PyUnicode_FromString("<cant get IID info!>"); +#endif + return ret; + } + return PyErr_Format(PyExc_AttributeError, "IID objects have no attribute '%s'", name); +} + +#if PY_MAJOR_VERSION <= 2 +/* static */ int +Py_nsIID::PyTypeMethod_compare(PyObject *self, PyObject *other) +{ + Py_nsIID *s_iid = (Py_nsIID *)self; + Py_nsIID *o_iid = (Py_nsIID *)other; + int rc = memcmp(&s_iid->m_iid, &o_iid->m_iid, sizeof(s_iid->m_iid)); + return rc == 0 ? 0 : (rc < 0 ? -1 : 1); +} +#endif + +/* static */ PyObject * +Py_nsIID::PyTypeMethod_richcompare(PyObject *self, PyObject *other, int op) +{ + PyObject *result = NULL; + Py_nsIID *s_iid = (Py_nsIID *)self; + Py_nsIID *o_iid = (Py_nsIID *)other; + int rc = memcmp(&s_iid->m_iid, &o_iid->m_iid, sizeof(s_iid->m_iid)); + switch (op) + { + case Py_LT: + result = rc < 0 ? Py_True : Py_False; + break; + case Py_LE: + result = rc <= 0 ? Py_True : Py_False; + break; + case Py_EQ: + result = rc == 0 ? Py_True : Py_False; + break; + case Py_NE: + result = rc != 0 ? Py_True : Py_False; + break; + case Py_GT: + result = rc > 0 ? Py_True : Py_False; + break; + case Py_GE: + result = rc >= 0 ? Py_True : Py_False; + break; + } + Py_XINCREF(result); + return result; +} + +/* static */ PyObject * +Py_nsIID::PyTypeMethod_repr(PyObject *self) +{ + Py_nsIID *s_iid = (Py_nsIID *)self; + char buf[256]; + char *sziid = s_iid->m_iid.ToString(); +#ifdef VBOX + snprintf(buf, sizeof(buf), "_xpcom.ID('%s')", sziid); +#else + sprintf(buf, "_xpcom.IID('%s')", sziid); +#endif + nsMemory::Free(sziid); +#if PY_MAJOR_VERSION <= 2 + return PyString_FromString(buf); +#else + return PyUnicode_FromString(buf); +#endif +} + +/* static */ PyObject * +Py_nsIID::PyTypeMethod_str(PyObject *self) +{ + Py_nsIID *s_iid = (Py_nsIID *)self; + char *sziid = s_iid->m_iid.ToString(); +#if PY_MAJOR_VERSION <= 2 + PyObject *ret = PyString_FromString(sziid); +#else + PyObject *ret = PyUnicode_FromString(sziid); +#endif + nsMemory::Free(sziid); + return ret; +} + +#if PY_VERSION_HEX >= 0x03020000 +/* static */Py_hash_t +Py_nsIID::PyTypeMethod_hash(PyObject *self) +#else +/* static */long +Py_nsIID::PyTypeMethod_hash(PyObject *self) +#endif +{ + const nsIID &iid = ((Py_nsIID *)self)->m_iid; + +#if PY_VERSION_HEX >= 0x03020000 + Py_hash_t ret = iid.m0 + iid.m1 + iid.m2; +#else + long ret = iid.m0 + iid.m1 + iid.m2; +#endif + for (int i=0;i<7;i++) + ret += iid.m3[i]; + if ( ret == -1 ) + return -2; + return ret; +} + +/*static*/ void +Py_nsIID::PyTypeMethod_dealloc(PyObject *ob) +{ + delete (Py_nsIID *)ob; +} diff --git a/src/libs/xpcom18a4/python/src/PyIInputStream.cpp b/src/libs/xpcom18a4/python/src/PyIInputStream.cpp new file mode 100644 index 00000000..b290a3e4 --- /dev/null +++ b/src/libs/xpcom18a4/python/src/PyIInputStream.cpp @@ -0,0 +1,190 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * 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 ***** */ + +// +// This code is part of the XPCOM extensions for Python. +// +// Written September 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +#include "PyXPCOM_std.h" +#include "nsIInputStream.h" + +// Prevents us needing to use an nsIScriptableInputStream +// (and even that can't read binary data!!!) + +static nsIInputStream *GetI(PyObject *self) { + nsIID iid = NS_GET_IID(nsIInputStream); + + if (!Py_nsISupports::Check(self, iid)) { + PyErr_SetString(PyExc_TypeError, "This object is not the correct interface"); + return NULL; + } + return (nsIInputStream *)Py_nsISupports::GetI(self); +} + +static PyObject *DoPyRead_Buffer(nsIInputStream *pI, PyObject *obBuffer, PRUint32 n) +{ + PRUint32 nread; + void *buf; +#ifndef VBOX /* unsafe cast on 64-bit hosts. */ + PRUint32 buf_len; + if (PyObject_AsWriteBuffer(obBuffer, &buf, (Py_ssize_t *)&buf_len) != 0) { +#else /* VBOX */ +# if PY_VERSION_HEX >= 0x02050000 || defined(PY_SSIZE_T_MIN) + Py_ssize_t buf_len; +# else + int buf_len; +# endif /* VBOX */ + if (PyObject_AsWriteBuffer(obBuffer, &buf, &buf_len) != 0) { +#endif + PyErr_Clear(); + PyErr_SetString(PyExc_TypeError, "The buffer object does not have a write buffer!"); + return NULL; + } + if (n==(PRUint32)-1) { + n = buf_len; + } else { + if (n > buf_len) { + NS_WARNING("Warning: PyIInputStream::read() was passed an integer size greater than the size of the passed buffer! Buffer size used.\n"); + n = buf_len; + } + } + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->Read((char *)buf, n, &nread); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + return PyInt_FromLong(nread); +} + +static PyObject *DoPyRead_Size(nsIInputStream *pI, PRUint32 n) +{ + if (n==(PRUint32)-1) { + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->Available(&n); + Py_END_ALLOW_THREADS; + if (NS_FAILED(r)) + return PyXPCOM_BuildPyException(r); + } + if (n==0) { // mozilla will assert if we alloc zero bytes. +#if PY_MAJOR_VERSION <= 2 + return PyBuffer_New(0); +#else + return PyBytes_FromString(""); +#endif + } + char *buf = (char *)nsMemory::Alloc(n); + if (buf==NULL) { + PyErr_NoMemory(); + return NULL; + } + nsresult r; + PRUint32 nread; + Py_BEGIN_ALLOW_THREADS; + r = pI->Read(buf, n, &nread); + Py_END_ALLOW_THREADS; + PyObject *rc = NULL; + if ( NS_SUCCEEDED(r) ) { +#if PY_MAJOR_VERSION <= 2 + rc = PyBuffer_New(nread); + if (rc != NULL) { + void *ob_buf; +#ifndef VBOX /* unsafe cast on 64-bit hosts. */ + PRUint32 buf_len; + if (PyObject_AsWriteBuffer(rc, &ob_buf, (Py_ssize_t *)&buf_len) != 0) { +#else /* VBOX */ +# if PY_VERSION_HEX >= 0x02050000 || defined(PY_SSIZE_T_MIN) + Py_ssize_t buf_len; +# else + int buf_len; +# endif /* VBOX */ + if (PyObject_AsWriteBuffer(rc, &ob_buf, &buf_len) != 0) { +#endif + // should never fail - we just created it! + return NULL; + } + if (buf_len != nread) { + PyErr_SetString(PyExc_RuntimeError, "New buffer isnt the size we create it!"); + return NULL; + } + memcpy(ob_buf, buf, nread); + } +#else + rc = PyBytes_FromStringAndSize(buf, nread); +#endif + } else + PyXPCOM_BuildPyException(r); + nsMemory::Free(buf); + return rc; +} + +static PyObject *PyRead(PyObject *self, PyObject *args) +{ + PyObject *obBuffer = NULL; + PRUint32 n = (PRUint32)-1; + + nsIInputStream *pI = GetI(self); + if (pI==NULL) + return NULL; + if (PyArg_ParseTuple(args, "|i", (int *)&n)) + // This worked - no args, or just an int. + return DoPyRead_Size(pI, n); + // try our other supported arg format. + PyErr_Clear(); + if (!PyArg_ParseTuple(args, "O|i", &obBuffer, (int *)&n)) { + PyErr_Clear(); + PyErr_SetString(PyExc_TypeError, "'read()' must be called as (buffer_ob, int_size=-1) or (int_size=-1)"); + return NULL; + } + return DoPyRead_Buffer(pI, obBuffer, n); +} + + +struct PyMethodDef +PyMethods_IInputStream[] = +{ + { "read", PyRead, 1}, + // The rest are handled as normal + {NULL} +}; diff --git a/src/libs/xpcom18a4/python/src/PyIInterfaceInfo.cpp b/src/libs/xpcom18a4/python/src/PyIInterfaceInfo.cpp new file mode 100644 index 00000000..7e1a9466 --- /dev/null +++ b/src/libs/xpcom18a4/python/src/PyIInterfaceInfo.cpp @@ -0,0 +1,431 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * 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 ***** */ + +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +#include "PyXPCOM_std.h" + + +static nsIInterfaceInfo *GetI(PyObject *self) { + nsIID iid = NS_GET_IID(nsIInterfaceInfo); + + if (!Py_nsISupports::Check(self, iid)) { + PyErr_SetString(PyExc_TypeError, "This object is not the correct interface"); + return NULL; + } + return (nsIInterfaceInfo *)Py_nsISupports::GetI(self); +} + +static PyObject *PyGetName(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, ":GetName")) + return NULL; + + nsIInterfaceInfo *pI = GetI(self); + if (pI==NULL) + return NULL; + + char *name; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->GetName(&name); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); +#if PY_MAJOR_VERSION <= 2 + PyObject *ret = PyString_FromString(name); +#else + PyObject *ret = PyUnicode_FromString(name); +#endif + nsMemory::Free(name); + return ret; +} + +static PyObject *PyGetIID(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, ":GetIID")) + return NULL; + + nsIInterfaceInfo *pI = GetI(self); + if (pI==NULL) + return NULL; + + nsIID *iid_ret; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->GetInterfaceIID(&iid_ret); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + PyObject *ret = Py_nsIID::PyObjectFromIID(*iid_ret); + nsMemory::Free(iid_ret); + return ret; +} + +static PyObject *PyIsScriptable(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, ":IsScriptable")) + return NULL; + + nsIInterfaceInfo *pI = GetI(self); + if (pI==NULL) + return NULL; + + PRBool b_ret; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->IsScriptable(&b_ret); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + return PyInt_FromLong(b_ret); +} + +static PyObject *PyGetParent(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, ":GetParent")) + return NULL; + + nsIInterfaceInfo *pI = GetI(self); + if (pI==NULL) + return NULL; + + nsCOMPtr<nsIInterfaceInfo> pRet; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + 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); +} + +static PyObject *PyGetMethodCount(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, ":GetMethodCount")) + return NULL; + + nsIInterfaceInfo *pI = GetI(self); + if (pI==NULL) + return NULL; + + PRUint16 ret; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->GetMethodCount(&ret); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + return PyInt_FromLong(ret); +} + + +static PyObject *PyGetConstantCount(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, ":GetConstantCount")) + return NULL; + + nsIInterfaceInfo *pI = GetI(self); + if (pI==NULL) + return NULL; + + PRUint16 ret; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->GetConstantCount(&ret); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + return PyInt_FromLong(ret); +} + +static PyObject *PyGetMethodInfo(PyObject *self, PyObject *args) +{ + PRUint16 index; + if (!PyArg_ParseTuple(args, "h:GetMethodInfo", &index)) + return NULL; + + nsIInterfaceInfo *pI = GetI(self); + if (pI==NULL) + return NULL; + + PRUint16 nmethods; + pI->GetMethodCount(&nmethods); + if (index>=nmethods) { + PyErr_SetString(PyExc_ValueError, "The method index is out of range"); + return NULL; + } + + const nsXPTMethodInfo *pRet; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->GetMethodInfo(index, &pRet); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + return PyObject_FromXPTMethodDescriptor(pRet); +} + +static PyObject *PyGetMethodInfoForName(PyObject *self, PyObject *args) +{ + char *name; + if (!PyArg_ParseTuple(args, "s:GetMethodInfoForName", &name)) + return NULL; + + nsIInterfaceInfo *pI = GetI(self); + if (pI==NULL) + return NULL; + + const nsXPTMethodInfo *pRet; + PRUint16 index; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->GetMethodInfoForName(name, &index, &pRet); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + PyObject *ret_i = PyObject_FromXPTMethodDescriptor(pRet); + if (ret_i==NULL) + return NULL; + PyObject *real_ret = Py_BuildValue("iO", (int)index, ret_i); + Py_DECREF(ret_i); + return real_ret; +} + + +static PyObject *PyGetConstant(PyObject *self, PyObject *args) +{ + PRUint16 index; + if (!PyArg_ParseTuple(args, "h:GetConstant", &index)) + return NULL; + + nsIInterfaceInfo *pI = GetI(self); + if (pI==NULL) + return NULL; + + const nsXPTConstant *pRet; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->GetConstant(index, &pRet); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + return PyObject_FromXPTConstant(pRet); +} + +static PRBool __GetMethodInfoHelper(nsIInterfaceInfo *pii, int mi, int pi, const nsXPTMethodInfo **ppmi) +{ + PRUint16 nmethods=0; + pii->GetMethodCount(&nmethods); + if (mi<0 || mi>=nmethods) { + PyErr_SetString(PyExc_ValueError, "The method index is out of range"); + return PR_FALSE; + } + const nsXPTMethodInfo *pmi; + nsresult r = pii->GetMethodInfo(mi, &pmi); + if ( NS_FAILED(r) ) { + PyXPCOM_BuildPyException(r); + return PR_FALSE; + } + + int nparams=0; + nparams = pmi->GetParamCount(); + if (pi<0 || pi>=nparams) { + PyErr_SetString(PyExc_ValueError, "The param index is out of range"); + return PR_FALSE; + } + *ppmi = pmi; + return PR_TRUE; +} + +static PyObject *PyGetInfoForParam(PyObject *self, PyObject *args) +{ + nsIInterfaceInfo *pii = GetI(self); + if (pii==NULL) + return NULL; + PRUint16 mi, pi; + if (!PyArg_ParseTuple(args, "hh:GetInfoForParam", &mi, &pi)) + return NULL; + const nsXPTMethodInfo *pmi; + if (!__GetMethodInfoHelper(pii, mi, pi, &pmi)) + return NULL; + const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi); + 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)); +} + +static PyObject *PyGetIIDForParam(PyObject *self, PyObject *args) +{ + nsIInterfaceInfo *pii = GetI(self); + if (pii==NULL) + return NULL; + PRUint16 mi, pi; + if (!PyArg_ParseTuple(args, "hh:GetIIDForParam", &mi, &pi)) + return NULL; + const nsXPTMethodInfo *pmi; + if (!__GetMethodInfoHelper(pii, mi, pi, &pmi)) + return NULL; + const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi); + nsIID *piid; + nsresult n = pii->GetIIDForParam(mi, ¶m_info, &piid); + if (NS_FAILED(n) || piid==nsnull) + return PyXPCOM_BuildPyException(n); + PyObject *rc = Py_nsIID::PyObjectFromIID(*piid); + nsMemory::Free((void*)piid); + return rc; +} + +static PyObject *PyGetTypeForParam(PyObject *self, PyObject *args) +{ + nsIInterfaceInfo *pii = GetI(self); + if (pii==NULL) + return NULL; + PRUint16 mi, pi, dim; + if (!PyArg_ParseTuple(args, "hhh:GetTypeForParam", &mi, &pi, &dim)) + return NULL; + const nsXPTMethodInfo *pmi; + if (!__GetMethodInfoHelper(pii, mi, pi, &pmi)) + return NULL; + nsXPTType datumType; + const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi); + nsresult n = pii->GetTypeForParam(mi, ¶m_info, dim, &datumType); + if (NS_FAILED(n)) + return PyXPCOM_BuildPyException(n); + return PyObject_FromXPTType(&datumType); +} + +static PyObject *PyGetSizeIsArgNumberForParam(PyObject *self, PyObject *args) +{ + nsIInterfaceInfo *pii = GetI(self); + if (pii==NULL) + return NULL; + PRUint16 mi, pi, dim; + if (!PyArg_ParseTuple(args, "hhh:GetSizeIsArgNumberForParam", &mi, &pi, &dim)) + return NULL; + const nsXPTMethodInfo *pmi; + if (!__GetMethodInfoHelper(pii, mi, pi, &pmi)) + return NULL; + PRUint8 ret; + const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi); + nsresult n = pii->GetSizeIsArgNumberForParam(mi, ¶m_info, dim, &ret); + if (NS_FAILED(n)) + return PyXPCOM_BuildPyException(n); + return PyInt_FromLong(ret); +} + +static PyObject *PyGetLengthIsArgNumberForParam(PyObject *self, PyObject *args) +{ + nsIInterfaceInfo *pii = GetI(self); + if (pii==NULL) + return NULL; + PRUint16 mi, pi, dim; + if (!PyArg_ParseTuple(args, "hhh:GetLengthIsArgNumberForParam", &mi, &pi, &dim)) + return NULL; + const nsXPTMethodInfo *pmi; + if (!__GetMethodInfoHelper(pii, mi, pi, &pmi)) + return NULL; + PRUint8 ret; + const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi); + nsresult n = pii->GetLengthIsArgNumberForParam(mi, ¶m_info, dim, &ret); + if (NS_FAILED(n)) + return PyXPCOM_BuildPyException(n); + return PyInt_FromLong(ret); +} + +static PyObject *PyGetInterfaceIsArgNumberForParam(PyObject *self, PyObject *args) +{ + nsIInterfaceInfo *pii = GetI(self); + if (pii==NULL) + return NULL; + PRUint16 mi, pi; + if (!PyArg_ParseTuple(args, "hhh:GetInterfaceIsArgNumberForParam", &mi, &pi)) + return NULL; + const nsXPTMethodInfo *pmi; + if (!__GetMethodInfoHelper(pii, mi, pi, &pmi)) + return NULL; + PRUint8 ret; + const nsXPTParamInfo& param_info = pmi->GetParam((PRUint8)pi); + nsresult n = pii->GetInterfaceIsArgNumberForParam(mi, ¶m_info, &ret); + if (NS_FAILED(n)) + return PyXPCOM_BuildPyException(n); + return PyInt_FromLong(ret); +} + +struct PyMethodDef +PyMethods_IInterfaceInfo[] = +{ + { "GetName", PyGetName, 1}, + { "GetIID", PyGetIID, 1}, + { "IsScriptable", PyIsScriptable, 1}, + { "GetParent", PyGetParent, 1}, + { "GetMethodCount", PyGetMethodCount, 1}, + { "GetConstantCount", PyGetConstantCount, 1}, + { "GetMethodInfo", PyGetMethodInfo, 1}, + { "GetMethodInfoForName", PyGetMethodInfoForName, 1}, + { "GetConstant", PyGetConstant, 1}, + { "GetInfoForParam", PyGetInfoForParam, 1}, + { "GetIIDForParam", PyGetIIDForParam, 1}, + { "GetTypeForParam", PyGetTypeForParam, 1}, + { "GetSizeIsArgNumberForParam", PyGetSizeIsArgNumberForParam, 1}, + { "GetLengthIsArgNumberForParam", PyGetLengthIsArgNumberForParam, 1}, + { "GetInterfaceIsArgNumberForParam", PyGetInterfaceIsArgNumberForParam, 1}, + {NULL} +}; + +/* + NS_IMETHOD GetMethodInfo(PRUint16 index, const nsXPTMethodInfo * *info) = 0; + NS_IMETHOD GetMethodInfoForName(const char *methodName, PRUint16 *index, const nsXPTMethodInfo * *info) = 0; + NS_IMETHOD GetConstant(PRUint16 index, const nsXPTConstant * *constant) = 0; + NS_IMETHOD GetInfoForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIInterfaceInfo **_retval) = 0; + NS_IMETHOD GetIIDForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, nsIID * *_retval) = 0; + NS_IMETHOD GetTypeForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, nsXPTType *_retval) = 0; + NS_IMETHOD GetSizeIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) = 0; + NS_IMETHOD GetLengthIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint16 dimension, PRUint8 *_retval) = 0; + NS_IMETHOD GetInterfaceIsArgNumberForParam(PRUint16 methodIndex, const nsXPTParamInfo * param, PRUint8 *_retval) = 0; + +*/ diff --git a/src/libs/xpcom18a4/python/src/PyIInterfaceInfoManager.cpp b/src/libs/xpcom18a4/python/src/PyIInterfaceInfoManager.cpp new file mode 100644 index 00000000..7c629413 --- /dev/null +++ b/src/libs/xpcom18a4/python/src/PyIInterfaceInfoManager.cpp @@ -0,0 +1,206 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * 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 ***** */ + + +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +#include "PyXPCOM_std.h" +#include <nsIInterfaceInfoManager.h> + +static nsIInterfaceInfoManager *GetI(PyObject *self) { + nsIID iid = NS_GET_IID(nsIInterfaceInfoManager); + + if (!Py_nsISupports::Check(self, iid)) { + PyErr_SetString(PyExc_TypeError, "This object is not the correct interface"); + return NULL; + } + return (nsIInterfaceInfoManager *)Py_nsISupports::GetI(self); +} + +static PyObject *PyGetInfoForIID(PyObject *self, PyObject *args) +{ + PyObject *obIID = NULL; + if (!PyArg_ParseTuple(args, "O", &obIID)) + return NULL; + + nsIInterfaceInfoManager *pI = GetI(self); + if (pI==NULL) + return NULL; + + nsIID iid; + if (!Py_nsIID::IIDFromPyObject(obIID, &iid)) + return NULL; + + nsCOMPtr<nsIInterfaceInfo> pi; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->GetInfoForIID(&iid, getter_AddRefs(pi)); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + + /* Return a type based on the IID (with no extra ref) */ + 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); +} + +static PyObject *PyGetInfoForName(PyObject *self, PyObject *args) +{ + char *name; + if (!PyArg_ParseTuple(args, "s", &name)) + return NULL; + + nsIInterfaceInfoManager *pI = GetI(self); + if (pI==NULL) + return NULL; + + nsCOMPtr<nsIInterfaceInfo> pi; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->GetInfoForName(name, getter_AddRefs(pi)); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + + /* 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); +} + +static PyObject *PyGetNameForIID(PyObject *self, PyObject *args) +{ + PyObject *obIID = NULL; + if (!PyArg_ParseTuple(args, "O", &obIID)) + return NULL; + + nsIInterfaceInfoManager *pI = GetI(self); + if (pI==NULL) + return NULL; + + nsIID iid; + if (!Py_nsIID::IIDFromPyObject(obIID, &iid)) + return NULL; + + char *ret_name = NULL; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->GetNameForIID(&iid, &ret_name); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + +#if PY_MAJOR_VERSION <= 2 + PyObject *ret = PyString_FromString(ret_name); +#else + PyObject *ret = PyUnicode_FromString(ret_name); +#endif + nsMemory::Free(ret_name); + return ret; +} + +static PyObject *PyGetIIDForName(PyObject *self, PyObject *args) +{ + char *name; + if (!PyArg_ParseTuple(args, "s", &name)) + return NULL; + + nsIInterfaceInfoManager *pI = GetI(self); + if (pI==NULL) + return NULL; + + nsIID *iid_ret; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->GetIIDForName(name, &iid_ret); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + + PyObject *ret = Py_nsIID::PyObjectFromIID(*iid_ret); + nsMemory::Free(iid_ret); + return ret; +} + +static PyObject *PyEnumerateInterfaces(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + + nsIInterfaceInfoManager *pI = GetI(self); + if (pI==NULL) + return NULL; + + nsCOMPtr<nsIEnumerator> pRet; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + 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)); +} + +// TODO: +// void autoRegisterInterfaces(); + +PyMethodDef +PyMethods_IInterfaceInfoManager[] = +{ + { "GetInfoForIID", PyGetInfoForIID, 1}, + { "getInfoForIID", PyGetInfoForIID, 1}, + { "GetInfoForName", PyGetInfoForName, 1}, + { "getInfoForName", PyGetInfoForName, 1}, + { "GetIIDForName", PyGetIIDForName, 1}, + { "getIIDForName", PyGetIIDForName, 1}, + { "GetNameForIID", PyGetNameForIID, 1}, + { "getNameForIID", PyGetNameForIID, 1}, + { "EnumerateInterfaces", PyEnumerateInterfaces, 1}, + { "enumerateInterfaces", PyEnumerateInterfaces, 1}, + {NULL} +}; diff --git a/src/libs/xpcom18a4/python/src/PyISimpleEnumerator.cpp b/src/libs/xpcom18a4/python/src/PyISimpleEnumerator.cpp new file mode 100644 index 00000000..b94d8eb2 --- /dev/null +++ b/src/libs/xpcom18a4/python/src/PyISimpleEnumerator.cpp @@ -0,0 +1,202 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Mark Hammond <MarkH@ActiveState.com> (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 ***** */ + +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +#include "PyXPCOM_std.h" +#include <nsISimpleEnumerator.h> + +static nsISimpleEnumerator *GetI(PyObject *self) { + nsIID iid = NS_GET_IID(nsISimpleEnumerator); + + if (!Py_nsISupports::Check(self, iid)) { + PyErr_SetString(PyExc_TypeError, "This object is not the correct interface"); + return NULL; + } + return (nsISimpleEnumerator *)Py_nsISupports::GetI(self); +} + + +static PyObject *PyHasMoreElements(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, ":HasMoreElements")) + return NULL; + + nsISimpleEnumerator *pI = GetI(self); + if (pI==NULL) + return NULL; + + nsresult r; + PRBool more; + Py_BEGIN_ALLOW_THREADS; + r = pI->HasMoreElements(&more); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + return PyInt_FromLong(more); +} + +static PyObject *PyGetNext(PyObject *self, PyObject *args) +{ + PyObject *obIID = NULL; + if (!PyArg_ParseTuple(args, "|O:GetNext", &obIID)) + return NULL; + + nsIID iid(NS_GET_IID(nsISupports)); + if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid)) + return NULL; + nsISimpleEnumerator *pI = GetI(self); + if (pI==NULL) + return NULL; + + nsISupports *pRet = nsnull; + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = pI->GetNext(&pRet); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + if (obIID) { + nsISupports *temp; + Py_BEGIN_ALLOW_THREADS; + r = pRet->QueryInterface(iid, (void **)&temp); + pRet->Release(); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) { + return PyXPCOM_BuildPyException(r); + } + pRet = temp; + } + PyObject *ret = Py_nsISupports::PyObjectFromInterface(pRet, iid); + NS_IF_RELEASE(pRet); + return ret; +} + +// A method added for Python performance if you really need +// it. Allows you to fetch a block of objects in one +// hit, allowing the loop to remain implemented in C. +static PyObject *PyFetchBlock(PyObject *self, PyObject *args) +{ + PyObject *obIID = NULL; + int n_wanted; + int n_fetched = 0; + if (!PyArg_ParseTuple(args, "i|O:FetchBlock", &n_wanted, &obIID)) + return NULL; + + nsIID iid(NS_GET_IID(nsISupports)); + if (obIID != NULL && !Py_nsIID::IIDFromPyObject(obIID, &iid)) + return NULL; + nsISimpleEnumerator *pI = GetI(self); + if (pI==NULL) + return NULL; + + // We want to fetch with the thread-lock released, + // but this means we can not append to the PyList + nsISupports **fetched = new nsISupports*[n_wanted]; + if (fetched==nsnull) { + PyErr_NoMemory(); + return NULL; + } + memset(fetched, 0, sizeof(nsISupports *) * n_wanted); + nsresult r = NS_OK; + PRBool more; + Py_BEGIN_ALLOW_THREADS; + for (;n_fetched<n_wanted;) { + r = pI->HasMoreElements(&more); + if (NS_FAILED(r)) + break; // this _is_ an error! + if (!more) + break; // Normal enum end. + nsISupports *pNew; + r = pI->GetNext(&pNew); + if (NS_FAILED(r)) // IS an error + break; + if (obIID) { + nsISupports *temp; + r = pNew->QueryInterface(iid, (void **)&temp); + pNew->Release(); + if ( NS_FAILED(r) ) { + break; + } + pNew = temp; + } + fetched[n_fetched] = pNew; + n_fetched++; + } + Py_END_ALLOW_THREADS; + PyObject *ret; + if (NS_SUCCEEDED(r)) { + ret = PyList_New(n_fetched); + if (ret) + for (int i=0;i<n_fetched;i++) { + PyObject *new_ob = Py_nsISupports::PyObjectFromInterface(fetched[i], iid); + NS_IF_RELEASE(fetched[i]); + PyList_SET_ITEM(ret, i, new_ob); + } + } else + ret = PyXPCOM_BuildPyException(r); + + if ( ret == NULL ) { + // Free the objects we consumed. + for (int i=0;i<n_fetched;i++) + fetched[i]->Release(); + + } + delete [] fetched; + return ret; +} + + +struct PyMethodDef +PyMethods_ISimpleEnumerator[] = +{ + { "HasMoreElements", PyHasMoreElements, 1}, + { "hasMoreElements", PyHasMoreElements, 1}, + { "GetNext", PyGetNext, 1}, + { "getNext", PyGetNext, 1}, + { "FetchBlock", PyFetchBlock, 1}, + { "fetchBlock", PyFetchBlock, 1}, + {NULL} +}; diff --git a/src/libs/xpcom18a4/python/src/PyISupports.cpp b/src/libs/xpcom18a4/python/src/PyISupports.cpp new file mode 100644 index 00000000..84504038 --- /dev/null +++ b/src/libs/xpcom18a4/python/src/PyISupports.cpp @@ -0,0 +1,621 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * 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 ***** */ + +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +#include "PyXPCOM_std.h" +#include "nsISupportsPrimitives.h" + +static PRInt32 cInterfaces=0; +static PyObject *g_obFuncMakeInterfaceCount = NULL; // XXX - never released!!! + +#ifdef VBOX_DEBUG_LIFETIMES +# include <iprt/log.h> +# include <iprt/stream.h> + +/*static*/ RTLISTNODE Py_nsISupports::g_List; +/*static*/ RTONCE Py_nsISupports::g_Once = RTONCE_INITIALIZER; +/*static*/ RTCRITSECT Py_nsISupports::g_CritSect; + +/*static*/ DECLCALLBACK(int32_t) +Py_nsISupports::initOnceCallback(void *pvUser1) +{ + NOREF(pvUser1); + RTListInit(&g_List); + return RTCritSectInit(&g_CritSect); +} + +/*static*/ void +Py_nsISupports::dumpList(void) +{ + RTOnce(&g_Once, initOnceCallback, NULL); + RTCritSectEnter(&g_CritSect); + + uint32_t i = 0; + Py_nsISupports *pCur; + RTListForEach(&g_List, pCur, Py_nsISupports, m_ListEntry) + { + nsISupports *pISup = pCur->m_obj; + PyXPCOM_LogWarning("#%u: %p iid=%RTuuid obj=%p", i, pCur, &pCur->m_iid, pISup); + i++; + } + + RTCritSectLeave(&g_CritSect); +} + +/*static*/ void +Py_nsISupports::dumpListToStdOut() +{ + RTOnce(&g_Once, initOnceCallback, NULL); + RTCritSectEnter(&g_CritSect); + + uint32_t i = 0; + Py_nsISupports *pCur; + RTListForEach(&g_List, pCur, Py_nsISupports, m_ListEntry) + { + nsISupports *pISup = pCur->m_obj; + RTPrintf("#%u: %p iid=%RTuuid obj=%p\n", i, pCur, &pCur->m_iid, pISup); + i++; + } + + RTCritSectLeave(&g_CritSect); +} + +PRInt32 +_PyXPCOM_DumpInterfaces(void) +{ + Py_nsISupports::dumpListToStdOut(); + return NS_OK; +} + +#endif /* _DEBUG_LIFETIMES */ + + + +PyObject *PyObject_FromNSInterface( nsISupports *aInterface, + const nsIID &iid, + PRBool bMakeNicePyObject /*= PR_TRUE */) +{ + return Py_nsISupports::PyObjectFromInterface(aInterface, iid, + bMakeNicePyObject); +} + +PRInt32 +_PyXPCOM_GetInterfaceCount(void) +{ + return cInterfaces; +} + +#ifndef Py_LIMITED_API +Py_nsISupports::Py_nsISupports(nsISupports *punk, const nsIID &iid, PyTypeObject *this_type) +#else +Py_nsISupports::Py_nsISupports(nsISupports *punk, const nsIID &iid, PyXPCOM_TypeObject *this_type) +#endif +{ +#ifndef Py_LIMITED_API + ob_type = this_type; +#else + ob_type = this_type->m_pTypeObj; + m_pMyTypeObj = this_type; +#endif + m_obj = punk; + m_iid = iid; + // refcnt of object managed by caller. + PR_AtomicIncrement(&cInterfaces); + PyXPCOM_DLLAddRef(); +#if 1 /* VBox: Must use for 3.9+, includes _Py_NewReferences. Works for all older versions too. @bugref{10079} */ + PyObject_Init(this, ob_type); +#else + _Py_NewReference(this); +#endif + +#ifdef VBOX_DEBUG_LIFETIMES + RTOnce(&g_Once, initOnceCallback, NULL); + RTCritSectEnter(&g_CritSect); + RTListAppend(&g_List, &m_ListEntry); + RTCritSectLeave(&g_CritSect); + PyXPCOM_LogWarning("Creating %p: iid=%RTuuid obj=%p", this, &m_iid, punk); +#endif +} + +Py_nsISupports::~Py_nsISupports() +{ +#ifdef VBOX_DEBUG_LIFETIMES + RTCritSectEnter(&g_CritSect); + nsISupports *punk = m_obj; + RTListNodeRemove(&m_ListEntry); + RTCritSectLeave(&g_CritSect); + PyXPCOM_LogWarning("Destroying %p: iid=%RTuuid obj=%p", this, &m_iid, punk); +#endif + + SafeRelease(this); + PR_AtomicDecrement(&cInterfaces); + PyXPCOM_DLLRelease(); +} + +/*static*/ nsISupports * +Py_nsISupports::GetI(PyObject *self, nsIID *ret_iid) +{ + if (self==NULL) { + PyErr_SetString(PyExc_ValueError, "The Python object is invalid"); + return NULL; + } + Py_nsISupports *pis = (Py_nsISupports *)self; + if (pis->m_obj==NULL) { + // This should never be able to happen. + PyErr_SetString(PyExc_ValueError, "Internal Error - The XPCOM object has been released."); + return NULL; + } + if (ret_iid) + *ret_iid = pis->m_iid; + return pis->m_obj; +} + +/*static*/ void +Py_nsISupports::SafeRelease(Py_nsISupports *ob) +{ + if (!ob) + return; + if (ob->m_obj) + { + Py_BEGIN_ALLOW_THREADS; + ob->m_obj = nsnull; + Py_END_ALLOW_THREADS; + } +} + +/* virtual */ PyObject * +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; + } +#ifndef Py_LIMITED_API + PyXPCOM_TypeObject *this_type = (PyXPCOM_TypeObject *)ob_type; +#else + PyXPCOM_TypeObject *this_type = m_pMyTypeObj; +#endif +#if PY_MAJOR_VERSION <= 2 + return Py_FindMethodInChain(&this_type->chain, this, (char *)name); +#else + PyMethodChain *chain = &this_type->chain; + if (name[0] == '_' && name[1] == '_') { +# ifndef Py_LIMITED_API /** @todo ? */ + if (!strcmp(name, "__doc__")) { + const char *doc = ob_type->tp_doc; + if (doc) + return PyUnicode_FromString(doc); + } +# endif + } + while (chain) { + PyMethodDef *ml = chain->methods; + for (; ml->ml_name; ml++) { + if (!strcmp(name, ml->ml_name)) + return PyCFunction_New(ml, this); + } + chain = chain->link; + } + PyErr_SetString(PyExc_AttributeError, name); + return NULL; +#endif +} + +/* virtual */ int +Py_nsISupports::setattr(const char *name, PyObject *v) +{ + char buf[128]; +#ifdef VBOX + snprintf(buf, sizeof(buf), "%s has read-only attributes", PyXPCOM_ObTypeName(this) ); +#else + sprintf(buf, "%s has read-only attributes", PyXPCOM_ObTypeName(this) ); +#endif + PyErr_SetString(PyExc_TypeError, buf); + return -1; +} + +/*static*/ Py_nsISupports * +Py_nsISupports::Constructor(nsISupports *pInitObj, const nsIID &iid) +{ + return new Py_nsISupports(pInitObj, + iid, + type); +} + +PRBool +Py_nsISupports::InterfaceFromPyISupports(PyObject *ob, + const nsIID &iid, + nsISupports **ppv) +{ + nsISupports *pis; + PRBool rc = PR_FALSE; + if ( !Check(ob) ) + { + PyErr_Format(PyExc_TypeError, "Objects of type '%s' can not be used as COM objects", PyXPCOM_ObTypeName(ob)); + goto done; + } + nsIID already_iid; + pis = GetI(ob, &already_iid); + if ( !pis ) + goto done; /* exception was set by GetI() */ + /* note: we don't (yet) explicitly hold a reference to pis */ + if (iid.Equals(Py_nsIID_NULL)) { + // a bit of a hack - we are asking for the arbitary interface + // wrapped by this object, not some other specific interface - + // so no QI, just an AddRef(); + Py_BEGIN_ALLOW_THREADS + pis->AddRef(); + Py_END_ALLOW_THREADS + *ppv = pis; + } else { + // specific interface requested - if it is not already the + // specific interface, QI for it and discard pis. + if (iid.Equals(already_iid)) { + *ppv = pis; + pis->AddRef(); + } else { + nsresult r; + Py_BEGIN_ALLOW_THREADS + r = pis->QueryInterface(iid, (void **)ppv); + Py_END_ALLOW_THREADS + if ( NS_FAILED(r) ) + { + PyXPCOM_BuildPyException(r); + goto done; + } + /* note: the QI added a ref for the return value */ + } + } + rc = PR_TRUE; +done: + return rc; +} + +PRBool +Py_nsISupports::InterfaceFromPyObject(PyObject *ob, + const nsIID &iid, + nsISupports **ppv, + PRBool bNoneOK, + PRBool bTryAutoWrap /* = PR_TRUE */) +{ + if ( ob == NULL ) + { + // don't overwrite an error message + if ( !PyErr_Occurred() ) + PyErr_SetString(PyExc_TypeError, "The Python object is invalid"); + return PR_FALSE; + } + if ( ob == Py_None ) + { + if ( bNoneOK ) + { + *ppv = NULL; + return PR_TRUE; + } + else + { + PyErr_SetString(PyExc_TypeError, "None is not a invalid interface object in this context"); + return PR_FALSE; + } + } + + // support nsIVariant + if (iid.Equals(NS_GET_IID(nsIVariant)) || iid.Equals(NS_GET_IID(nsIWritableVariant))) { + // Check it is not already nsIVariant + if (PyObject_HasAttrString(ob, "__class__")) { + PyObject *sub_ob = PyObject_GetAttrString(ob, "_comobj_"); + if (sub_ob==NULL) { + PyErr_Clear(); + } else { + if (InterfaceFromPyISupports(sub_ob, iid, ppv)) { + Py_DECREF(sub_ob); + return PR_TRUE; + } + PyErr_Clear(); + Py_DECREF(sub_ob); + } + } + 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. + + if (PyObject_HasAttrString(ob, "__class__")) { + // Get the _comobj_ attribute + PyObject *use_ob = PyObject_GetAttrString(ob, "_comobj_"); + if (use_ob==NULL) { + PyErr_Clear(); + if (bTryAutoWrap) + // Try and auto-wrap it - errors will leave Py exception set, + return PyXPCOM_XPTStub::AutoWrapPythonInstance(ob, iid, ppv); + PyErr_SetString(PyExc_TypeError, "The Python instance can not be converted to an XPCOM object"); + return PR_FALSE; + } else + ob = use_ob; + + } else { + Py_INCREF(ob); + } + PRBool rc = InterfaceFromPyISupports(ob, iid, ppv); + Py_DECREF(ob); + return rc; +} + + +// Interface conversions +/*static*/void +#ifndef Py_LIMITED_API +Py_nsISupports::RegisterInterface( const nsIID &iid, PyTypeObject *t) +#else +Py_nsISupports::RegisterInterface( const nsIID &iid, PyXPCOM_TypeObject *t) +#endif +{ + if (mapIIDToType==NULL) + mapIIDToType = PyDict_New(); + + if (mapIIDToType) { + PyObject *key = Py_nsIID::PyObjectFromIID(iid); + if (key) + PyDict_SetItem(mapIIDToType, key, (PyObject *)t); + Py_XDECREF(key); + } +} + +/*static */PyObject * +Py_nsISupports::PyObjectFromInterface(nsISupports *pis, + const nsIID &riid, + PRBool bMakeNicePyObject, /* = PR_TRUE */ + PRBool bIsInternalCall /* = PR_FALSE */) +{ + // Quick exit. + if (pis==NULL) { + Py_INCREF(Py_None); + return Py_None; + } + + if (!bIsInternalCall) { +#ifdef NS_DEBUG + nsISupports *queryResult = nsnull; + Py_BEGIN_ALLOW_THREADS; + pis->QueryInterface(riid, (void **)&queryResult); + Py_END_ALLOW_THREADS; + NS_ASSERTION(queryResult == pis, "QueryInterface needed"); + NS_IF_RELEASE(queryResult); +#endif + } + +#ifndef Py_LIMITED_API + PyTypeObject *createType = NULL; +#else + PyXPCOM_TypeObject *createType = NULL; +#endif + // If the IID is for nsISupports, dont bother with + // a map lookup as we know the type! + if (!riid.Equals(NS_GET_IID(nsISupports))) { + // Look up the map + PyObject *obiid = Py_nsIID::PyObjectFromIID(riid); + if (!obiid) return NULL; + + if (mapIIDToType != NULL) +#ifndef Py_LIMITED_API + createType = (PyTypeObject *)PyDict_GetItem(mapIIDToType, obiid); +#else + createType = (PyXPCOM_TypeObject *)PyDict_GetItem(mapIIDToType, obiid); +#endif + Py_DECREF(obiid); + } + if (createType==NULL) + createType = Py_nsISupports::type; +#ifndef Py_LIMITED_API + // Check it is indeed one of our types. + if (!PyXPCOM_TypeObject::IsType(createType)) { + PyErr_SetString(PyExc_RuntimeError, "The type map is invalid"); + return NULL; + } + // we can now safely cast the thing to a PyComTypeObject and use it + PyXPCOM_TypeObject *myCreateType = (PyXPCOM_TypeObject *)createType; +#else /* Since the mapIIDToType is only updated by us, there should be no need for the above. */ + PyXPCOM_TypeObject * const myCreateType = createType; +#endif + if (myCreateType->ctor==NULL) { + PyErr_SetString(PyExc_TypeError, "The type does not declare a PyCom constructor"); + return NULL; + } + + Py_nsISupports *ret = (*myCreateType->ctor)(pis, riid); +#ifdef _DEBUG_LIFETIMES + PyXPCOM_LogF("XPCOM Object created at 0x%0xld, nsISupports at 0x%0xld", + ret, ret->m_obj); +#endif + if (ret && bMakeNicePyObject) + 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::MakeDefaultWrapper(PyObject *pyis, + const nsIID &iid) +{ + NS_PRECONDITION(pyis, "NULL pyobject!"); + PyObject *obIID = NULL; + PyObject *args = NULL; + PyObject *mod = NULL; + PyObject *ret = NULL; + + obIID = Py_nsIID::PyObjectFromIID(iid); + if (obIID==NULL) + goto done; + + if (g_obFuncMakeInterfaceCount==NULL) { + PyObject *mod = PyImport_ImportModule("xpcom.client"); + if (mod) + g_obFuncMakeInterfaceCount = PyObject_GetAttrString(mod, "MakeInterfaceResult"); + Py_XDECREF(mod); + } + if (g_obFuncMakeInterfaceCount==NULL) goto done; + + args = Py_BuildValue("OO", pyis, obIID); + if (args==NULL) goto done; + ret = PyEval_CallObject(g_obFuncMakeInterfaceCount, args); +done: + if (PyErr_Occurred()) { + NS_ABORT_IF_FALSE(ret==NULL, "Have an error, but also a return val!"); + PyXPCOM_LogError("Creating an interface object to be used as a result failed\n"); + PyErr_Clear(); + } + Py_XDECREF(mod); + Py_XDECREF(args); + Py_XDECREF(obIID); + if (ret==NULL) // eek - error - return the original with no refcount mod. + ret = pyis; + else + // no error - decref the old object + Py_DECREF(pyis); + // return our obISupports. If NULL, we are really hosed and nothing we can do. + return ret; +} + +// @pymethod <o Py_nsISupports>|Py_nsISupports|QueryInterface|Queries an object for a specific interface. +PyObject * +Py_nsISupports::QueryInterface(PyObject *self, PyObject *args) +{ + PyObject *obiid; + int bWrap = 1; + // @pyparm IID|iid||The IID requested. + // @rdesc The result is always a <o Py_nsISupports> object. + // Any error (including E_NOINTERFACE) will generate a <o com_error> exception. + if (!PyArg_ParseTuple(args, "O|i:QueryInterface", &obiid, &bWrap)) + return NULL; + + nsIID iid; + if (!Py_nsIID::IIDFromPyObject(obiid, &iid)) + return NULL; + + nsISupports *pMyIS = GetI(self); + if (pMyIS==NULL) return NULL; + + // 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, getter_AddRefs(pis)); + Py_END_ALLOW_THREADS; + + /* Note that this failure may include E_NOINTERFACE */ + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + + /* Return a type based on the IID (with no extra ref) */ + return ((Py_nsISupports *)self)->MakeInterfaceResult(pis, iid, (PRBool)bWrap); +} + + +#ifdef VBOX +static PyObject * +QueryErrorObject(PyObject *self, PyObject *args) +{ + nsresult rc = 0; + + if (!PyArg_ParseTuple(args, "i", &rc)) + return NULL; + + return PyXPCOM_BuildErrorMessage(rc); +} +#endif + +// @object Py_nsISupports|The base object for all PythonCOM objects. Wraps a COM nsISupports interface. +/*static*/ struct PyMethodDef +Py_nsISupports::methods[] = +{ + { "queryInterface", Py_nsISupports::QueryInterface, 1, "Queries the object for an interface."}, + { "QueryInterface", Py_nsISupports::QueryInterface, 1, "An alias for queryInterface."}, +#ifdef VBOX + { "QueryErrorObject", QueryErrorObject, 1, "Query an error object for given status code."}, +#endif + {NULL} +}; + +/*static*/void Py_nsISupports::InitType(void) +{ + type = new PyXPCOM_TypeObject( + "nsISupports", + NULL, + sizeof(Py_nsISupports), + methods, + Constructor); +} + +PyXPCOM_TypeObject *Py_nsISupports::type = NULL; +PyObject *Py_nsISupports::mapIIDToType = NULL; diff --git a/src/libs/xpcom18a4/python/src/PyIVariant.cpp b/src/libs/xpcom18a4/python/src/PyIVariant.cpp new file mode 100644 index 00000000..cd9f79c4 --- /dev/null +++ b/src/libs/xpcom18a4/python/src/PyIVariant.cpp @@ -0,0 +1,231 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * Mark Hammond. + * Portions created by the Initial Developer are Copyright (C) 2000 + * 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 ***** */ + +// This code is part of the XPCOM extensions for Python. +// +// Written April 2002 + +#include "PyXPCOM_std.h" +#include "nsIVariant.h" + +// Prevents us needing to use an nsIScriptableInputStream +// (and even that can't read binary data!!!) + +static nsIVariant *GetI(PyObject *self) { + nsIID iid = NS_GET_IID(nsIVariant); + + if (!Py_nsISupports::Check(self, iid)) { + PyErr_SetString(PyExc_TypeError, "This object is not the correct interface"); + return NULL; + } + return (nsIVariant *)Py_nsISupports::GetI(self); +} + +static PyObject *MyBool( PRBool v) { + PyObject *ret = v ? Py_True : Py_False; + Py_INCREF(ret); + return ret; +} +static PyObject *MyChar( char c) { +#if PY_MAJOR_VERSION <= 2 + return PyString_FromStringAndSize(&c, 1); +#else + return PyUnicode_FromStringAndSize(&c, 1); +#endif +} +static PyObject *MyUChar( PRUnichar c) { + return PyObject_FromNSString( &c, 1); +} +static PyObject *MyUnicode( PRUnichar *p) { + return PyObject_FromNSString(p); +} + +#define GET_SIMPLE(Type, FuncGet, FuncConvert) \ +static PyObject *FuncGet(PyObject *self, PyObject *args) { \ + nsIVariant *pI = GetI(self); \ + if (pI==NULL) return NULL; \ + if (!PyArg_ParseTuple(args, ":" #FuncGet)) return NULL; \ + Type t; \ + nsresult nr = pI->FuncGet(&t); \ + if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr); \ + return FuncConvert(t); \ +} + +#define GET_ALLOCATED(Type, FuncGet, FuncConvert, FuncFree) \ +static PyObject *FuncGet(PyObject *self, PyObject *args) { \ + nsIVariant *pI = GetI(self); \ + if (pI==NULL) return NULL; \ + if (!PyArg_ParseTuple(args, ":" #FuncGet)) return NULL; \ + Type t; \ + nsresult nr = pI->FuncGet(&t); \ + if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr); \ + PyObject *ret = FuncConvert(t); \ + FuncFree(t); \ + return ret; \ +} + +#define GET_ALLOCATED_SIZE(Type, FuncGet, FuncConvert, FuncFree) \ +static PyObject *FuncGet(PyObject *self, PyObject *args) { \ + nsIVariant *pI = GetI(self); \ + if (pI==NULL) return NULL; \ + if (!PyArg_ParseTuple(args, ":" #FuncGet)) return NULL; \ + Type t; PRUint32 size; \ + nsresult nr = pI->FuncGet(&size, &t); \ + if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr); \ + PyObject *ret = FuncConvert(t, size); \ + FuncFree(t); \ + return ret; \ +} + +GET_SIMPLE(PRUint8, GetAsInt8, PyInt_FromLong) +GET_SIMPLE(PRUint8, GetAsUint8, PyInt_FromLong) +GET_SIMPLE(PRInt16, GetAsInt16, PyInt_FromLong) +GET_SIMPLE(PRUint16, GetAsUint16, PyInt_FromLong) +GET_SIMPLE(PRInt32, GetAsInt32, PyInt_FromLong) +GET_SIMPLE(PRUint32, GetAsUint32, PyInt_FromLong) +GET_SIMPLE(PRInt64, GetAsInt64, PyLong_FromLongLong) +GET_SIMPLE(PRUint64, GetAsUint64, PyLong_FromUnsignedLongLong) +GET_SIMPLE(float, GetAsFloat, PyFloat_FromDouble) +GET_SIMPLE(double, GetAsDouble, PyFloat_FromDouble) +GET_SIMPLE(PRBool, GetAsBool, MyBool) +GET_SIMPLE(char, GetAsChar, MyChar) +GET_SIMPLE(PRUnichar, GetAsWChar, MyUChar) +GET_SIMPLE(nsIID, GetAsID, Py_nsIID::PyObjectFromIID) + +#if PY_MAJOR_VERSION <= 2 +GET_ALLOCATED(char *, GetAsString, PyString_FromString, nsMemory::Free) +#else +GET_ALLOCATED(char *, GetAsString, PyUnicode_FromString, nsMemory::Free) +#endif +GET_ALLOCATED(PRUnichar *, GetAsWString, MyUnicode, nsMemory::Free) +#if PY_MAJOR_VERSION <= 2 +GET_ALLOCATED_SIZE(char *, GetAsStringWithSize, PyString_FromStringAndSize, nsMemory::Free) +#else +GET_ALLOCATED_SIZE(char *, GetAsStringWithSize, PyUnicode_FromStringAndSize, nsMemory::Free) +#endif +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; + 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); +} + +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((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 +PyMethods_IVariant[] = +{ + { "getAsInt8", GetAsInt8, 1}, + { "getAsUint8", GetAsUint8, 1}, + { "getAsInt16", GetAsInt16, 1}, + { "getAsUint16", GetAsUint16, 1}, + { "getAsInt32", GetAsInt32, 1}, + { "getAsUint32", GetAsUint32, 1}, + { "getAsInt64", GetAsInt64, 1}, + { "getAsUint64", GetAsUint64, 1}, + { "getAsFloat", GetAsFloat, 1}, + { "getAsDouble", GetAsDouble, 1}, + { "getAsBool", GetAsBool, 1}, + { "getAsChar", GetAsChar, 1}, + { "getAsWChar", GetAsWChar, 1}, + { "getAsString", GetAsString, 1}, + { "getAsWString", GetAsWString, 1}, + { "getAsStringWithSize", GetAsStringWithSize, 1}, + { "getAsWStringWithSize", GetAsWStringWithSize, 1}, + { "getAsISupports", GetAsISupports, 1}, + { "getAsInterface", GetAsInterface, 1}, + { "getAsArray", GetAsArray, 1}, + { "getAsID", GetAsID, 1}, + { "get", Get, 1}, + {NULL} +}; + +PyObject * +Py_nsIVariant::getattr(const char *name) +{ + + PyObject *ret = NULL; + if (strcmp(name, "dataType")==0) { + nsIVariant *pI = ::GetI(this); + if (pI) { + PRUint16 dt; + nsresult nr = pI->GetDataType(&dt); + if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr); + ret = PyInt_FromLong(dt); + } + } else { + ret = Py_nsISupports::getattr(name); + } + return ret; +} + +int +Py_nsIVariant::setattr(const char *name, PyObject *v) +{ + return Py_nsISupports::setattr(name, v); +} diff --git a/src/libs/xpcom18a4/python/src/PyXPCOM.h b/src/libs/xpcom18a4/python/src/PyXPCOM.h new file mode 100644 index 00000000..91bc8d12 --- /dev/null +++ b/src/libs/xpcom18a4/python/src/PyXPCOM.h @@ -0,0 +1,1036 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * 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 ***** */ + +// PyXPCOM.h - the main header file for the Python XPCOM support. +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +#ifndef __PYXPCOM_H__ +#define __PYXPCOM_H__ + +#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" + +#include "nsXPIDLString.h" +#include "nsCRT.h" +#include "xptcall.h" +#include "xpt_xdr.h" + +#ifdef VBOX_DEBUG_LIFETIMES +# include <iprt/critsect.h> +# include <iprt/list.h> +# include <iprt/once.h> +#endif + +#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 + +#ifdef VBOX_PYXPCOM +// unfortunatelly, if SOLARIS is defined Python porting layer +// defines gethostname() in invalid fashion what kills compilation +# ifdef SOLARIS +# undef SOLARIS +# define SOLARIS_WAS_DEFINED +# endif + +// Python.h/pyconfig.h redefines _XOPEN_SOURCE on some hosts +# ifdef _XOPEN_SOURCE +# define VBOX_XOPEN_SOURCE_DEFINED _XOPEN_SOURCE +# undef _XOPEN_SOURCE +# endif + +#endif /* VBOX_PYXPCOM */ + +#include <Python.h> + +#ifdef VBOX_PYXPCOM + +# ifdef SOLARIS_WAS_DEFINED +# define SOLARIS +# undef SOLARIS_WAS_DEFINED +# endif + +// restore the old value of _XOPEN_SOURCE if not defined by Python.h/pyconfig.h +# if !defined(_XOPEN_SOURCE) && defined(VBOX_XOPEN_SOURCE_DEFINED) +# define _XOPEN_SOURCE VBOX_XOPEN_SOURCE_DEFINED +# endif +# undef VBOX_XOPEN_SOURCE_DEFINED + +# if (PY_VERSION_HEX <= 0x02040000) +// although in more recent versions of Python this type is ssize_t, earlier +// it was used as int +typedef int Py_ssize_t; +# endif + +# if (PY_VERSION_HEX <= 0x02030000) +// this one not defined before +inline PyObject *PyBool_FromLong(long ok) +{ + PyObject *result; + if (ok) + result = Py_True; + else + result = Py_False; + Py_INCREF(result); + return result; +} +# endif + +# if PY_MAJOR_VERSION >= 3 +# define PyInt_FromLong(l) PyLong_FromLong(l) +# define PyInt_Check(o) PyLong_Check(o) +# define PyInt_AsLong(o) PyLong_AsLong(o) +# define PyNumber_Int(o) PyNumber_Long(o) +# if !defined(Py_LIMITED_API) && PY_VERSION_HEX <= 0x03030000 /* 3.3 added PyUnicode_AsUTF8AndSize */ +# ifndef PyUnicode_AsUTF8 +# define PyUnicode_AsUTF8(o) _PyUnicode_AsString(o) +# endif +# ifndef PyUnicode_AsUTF8AndSize +# define PyUnicode_AsUTF8AndSize(o,s) _PyUnicode_AsStringAndSize(o,s) +# endif +# endif +typedef struct PyMethodChain +{ + PyMethodDef *methods; + struct PyMethodChain *link; +} PyMethodChain; +# endif + +#endif /* VBOX_PYXPCOM */ + +#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 PYXPCOM_EXPORT nsIID Py_nsIID_NULL; + +class Py_nsISupports; + + +/** @name VBox limited API hacks: + * @{ */ +#ifndef Py_LIMITED_API + +# define PyXPCOM_ObTypeName(obj) (Py_TYPE(obj)->tp_name) + +#else /* Py_LIMITED_API */ + +# if PY_VERSION_HEX <= 0x03030000 +# error "Py_LIMITED_API mode only works for Python 3.3 and higher." +# endif + +const char *PyXPCOMGetObTypeName(PyTypeObject *pTypeObj); +# define PyXPCOM_ObTypeName(obj) PyXPCOMGetObTypeName(Py_TYPE(obj)) + +# if Py_LIMITED_API < 0x030A0000 +/* Note! While we should not technically be using PyUnicode_AsUTF8AndSize, it was + made part of the limited API in 3.10 (see https://bugs.python.org/issue41784 and + https://github.com/python/cpython/commit/a05195ac61f1908ac5990cccb5aa82442bdaf15d). */ +extern "C" PyAPI_FUNC(const char *) PyUnicode_AsUTF8AndSize(PyObject *, Py_ssize_t *); +# endif + +/* PyUnicode_AsUTF8 is just PyUnicode_AsUTF8AndSize without returning a size. */ +# define PyUnicode_AsUTF8(o) PyUnicode_AsUTF8AndSize(o, NULL) + +DECLINLINE(int) PyRun_SimpleString(const char *pszCode) +{ + /* Get the main mode dictionary: */ + PyObject *pMainMod = PyImport_AddModule("__main__"); + if (pMainMod) { + PyObject *pMainModDict = PyModule_GetDict(pMainMod); + + /* Compile and run the code. */ + PyObject *pCodeObject = Py_CompileString(pszCode, "PyXPCOM", Py_file_input); + if (pCodeObject) { + PyObject *pResult = PyEval_EvalCode(pCodeObject, pMainModDict, pMainModDict); + Py_DECREF(pCodeObject); + if (pResult) { + Py_DECREF(pResult); + return 0; + } + PyErr_Print(); + } + } + return -1; +} + +DECLINLINE(PyObject *) PyTuple_GET_ITEM(PyObject *pTuple, Py_ssize_t idx) +{ + return PyTuple_GetItem(pTuple, idx); +} + +DECLINLINE(int) PyTuple_SET_ITEM(PyObject *pTuple, Py_ssize_t idx, PyObject *pItem) +{ + int rc = PyTuple_SetItem(pTuple, idx, pItem); /* Steals pItem ref, just like PyTuple_SET_ITEM. */ + Assert(rc == 0); + return rc; +} + +DECLINLINE(int) PyList_SET_ITEM(PyObject *pList, Py_ssize_t idx, PyObject *pItem) +{ + int rc = PyList_SetItem(pList, idx, pItem); /* Steals pItem ref, just like PyList_SET_ITEM. */ + Assert(rc == 0); + return rc; +} + +DECLINLINE(Py_ssize_t) PyBytes_GET_SIZE(PyObject *pBytes) +{ + return PyBytes_Size(pBytes); +} + +DECLINLINE(const char *) PyBytes_AS_STRING(PyObject *pBytes) +{ + return PyBytes_AsString(pBytes); +} + +DECLINLINE(Py_ssize_t) PyUnicode_GET_SIZE(PyObject *pUnicode) +{ + /* Note! Currently only used for testing for zero or 1 codepoints, so we don't + really need to deal with the different way these two treats surrogate pairs. */ +# if Py_LIMITED_API >= 0x03030000 + return PyUnicode_GetLength(pUnicode); +# else + return PyUnicode_GetSize(pUnicode); +# endif +} + +# define PyObject_CheckBuffer(pAllegedBuffer) PyObject_CheckReadBuffer(pAllegedBuffer) + +# include <iprt/asm.h> +DECLINLINE(Py_hash_t) _Py_HashPointer(void *p) +{ + Py_hash_t uHash = (Py_hash_t)RT_CONCAT(ASMRotateRightU,ARCH_BITS)((uintptr_t)p, 4); + return uHash != -1 ? uHash : -2; +} + +#endif /* Py_LIMITED_API */ +/** @} */ + + +/************************************************************************* +************************************************************************** + + Error and exception related function. + +************************************************************************** +*************************************************************************/ + +#define NS_PYXPCOM_NO_SUCH_METHOD \ + NS_ERROR_GENERATE_SUCCESS(NS_ERROR_MODULE_PYXPCOM, 0) + +// The exception object (loaded from the xpcom .py code) +extern PYXPCOM_EXPORT PyObject *PyXPCOM_Error; + +// Client related functions - generally called by interfaces before +// they return NULL back to Python to indicate the error. +// All these functions return NULL so interfaces can generally +// just "return PyXPCOM_BuildPyException(hr, punk, IID_IWhatever)" +PYXPCOM_EXPORT PyObject *PyXPCOM_BuildPyException(nsresult res); + +#ifdef VBOX +// Build human readable error message out of XPCOM error +PYXPCOM_EXPORT PyObject *PyXPCOM_BuildErrorMessage(nsresult r); +#endif + +// Used in gateways to handle the current Python exception +// 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. + +// Log a warning for the user - something at runtime +// they may care about, but nothing that prevents us actually +// working. +// As it's designed for user error/warning, it exists in non-debug builds. +PYXPCOM_EXPORT void PyXPCOM_LogWarning(const char *fmt, ...); + +// Log an error for the user - something that _has_ prevented +// us working. This is probably accompanied by a traceback. +// 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. +PYXPCOM_EXPORT void PyXPCOM_LogDebug(const char *fmt, ...); +#define PYXPCOM_LOG_DEBUG PyXPCOM_LogDebug +#else +#define PYXPCOM_LOG_DEBUG() +#endif // DEBUG + +// 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); + +/************************************************************************* +************************************************************************** + + Support for CALLING (ie, using) interfaces. + +************************************************************************** +*************************************************************************/ + +typedef Py_nsISupports* (* PyXPCOM_I_CTOR)(nsISupports *, const nsIID &); + +////////////////////////////////////////////////////////////////////////// +// class PyXPCOM_TypeObject +// Base class for (most of) the type objects. + +#ifndef Py_LIMITED_API +class PYXPCOM_EXPORT PyXPCOM_TypeObject : public PyTypeObject { +#else +class PYXPCOM_EXPORT PyXPCOM_TypeObject : public PyObject { +#endif +public: + PyXPCOM_TypeObject( + const char *name, + PyXPCOM_TypeObject *pBaseType, + int typeSize, + struct PyMethodDef* methodList, + PyXPCOM_I_CTOR ctor); + ~PyXPCOM_TypeObject(); + + PyMethodChain chain; + PyXPCOM_TypeObject *baseType; + PyXPCOM_I_CTOR ctor; + + static PRBool IsType(PyTypeObject *t); + // Static methods for the Python type. + static void Py_dealloc(PyObject *ob); + static PyObject *Py_repr(PyObject *ob); + static PyObject *Py_str(PyObject *ob); + static PyObject *Py_getattr(PyObject *self, char *name); + static int Py_setattr(PyObject *op, char *name, PyObject *v); + static int Py_cmp(PyObject *ob1, PyObject *ob2); + static PyObject *Py_richcmp(PyObject *ob1, PyObject *ob2, int op); +#if PY_VERSION_HEX >= 0x03020000 + static Py_hash_t Py_hash(PyObject *self); +#else + static long Py_hash(PyObject *self); +#endif +#ifdef Py_LIMITED_API + PyTypeObject *m_pTypeObj; /**< The python type object we wrap. */ +#endif +}; + +////////////////////////////////////////////////////////////////////////// +// class Py_nsISupports +// This class serves 2 purposes: +// * It is a base class for other interfaces we support "natively" +// * It is instantiated for _all_ other interfaces. +// +// This is different than win32com, where a PyIUnknown only +// ever holds an IUnknown - but here, we could be holding +// _any_ interface. +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 )) + return PR_FALSE; + if (!checkIID.Equals(Py_nsIID_NULL)) + return self->m_iid.Equals(checkIID) != 0; + return PR_TRUE; + } + // Get the nsISupports interface from the PyObject WITH NO REF COUNT ADDED + static nsISupports *GetI(PyObject *self, nsIID *ret_iid = NULL); + nsCOMPtr<nsISupports> m_obj; + nsIID m_iid; +#ifdef Py_LIMITED_API + /** Because PyXPCOM_TypeObject cannot inherit from PyTypeObject in + * Py_LIMITED_API mode, we cannot use ob_type to get to the method list. + * Instead of we store it here. */ + PyXPCOM_TypeObject *m_pMyTypeObj; +#endif + + // 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 (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 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 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. + // bTryAutoWrap indicates if a Python instance object should attempt to + // be automatically wrapped in an XPCOM object. This is really only + // provided to stop accidental recursion should the object returned by + // the wrap process itself be in instance (where it should already be + // a COM object. + // If |iid|==nsIVariant, then arbitary Python objects will be wrapped + // in an nsIVariant. + static PRBool InterfaceFromPyObject( + PyObject *ob, + const nsIID &iid, + nsISupports **ppret, + PRBool bNoneOK, + PRBool bTryAutoWrap = PR_TRUE); + + // Given a Py_nsISupports, return an interface. + // Object *must* be Py_nsISupports - there is no + // "autowrap", no "None" support, etc + static PRBool InterfaceFromPyISupports(PyObject *ob, + const nsIID &iid, + nsISupports **ppv); + + static Py_nsISupports *Constructor(nsISupports *pInitObj, const nsIID &iid); + // The Python methods + static PyObject *QueryInterface(PyObject *self, PyObject *args); + + // Internal (sort-of) objects. + static NS_EXPORT_STATIC_MEMBER_(PyXPCOM_TypeObject) *type; + static NS_EXPORT_STATIC_MEMBER_(PyMethodDef) methods[]; + static PyObject *mapIIDToType; + static void SafeRelease(Py_nsISupports *ob); +#ifndef Py_LIMITED_API + static void RegisterInterface( const nsIID &iid, PyTypeObject *t); +#else + static void RegisterInterface( const nsIID &iid, PyXPCOM_TypeObject *t); +#endif + static void InitType(); +#ifdef VBOX_DEBUG_LIFETIMES + static void dumpList(void); + static void dumpListToStdOut(void); +#endif + + 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() + Py_nsISupports(nsISupports *p, + const nsIID &iid, +#ifndef Py_LIMITED_API + PyTypeObject *type); +#else + PyXPCOM_TypeObject *type); +#endif + + // Make a default wrapper for an ISupports (which is an + // xpcom.client.Component instance) + static PyObject *MakeDefaultWrapper(PyObject *pyis, const nsIID &iid); + +#ifdef VBOX_DEBUG_LIFETIMES + static DECLCALLBACK(int32_t) initOnceCallback(void *pvUser1); + + RTLISTNODE m_ListEntry; /**< List entry. */ + + static RTONCE g_Once; /**< Init list and critsect once. */ + static RTCRITSECT g_CritSect; /**< Critsect protecting the list. */ + static RTLISTANCHOR g_List; /**< List of live interfaces.*/ +#endif +}; + +// Python/XPCOM IID support +class PYXPCOM_EXPORT Py_nsIID : public PyObject +{ +public: + Py_nsIID(const nsIID &riid); + nsIID m_iid; + + PRBool + IsEqual(const nsIID &riid) { + return m_iid.Equals(riid); + } + + PRBool + IsEqual(PyObject *ob) { + return ob && +#ifndef Py_LIMITED_API + ob->ob_type== &type && +#else + ob->ob_type == s_pType && +#endif + m_iid.Equals(((Py_nsIID *)ob)->m_iid); + } + + PRBool + IsEqual(Py_nsIID &iid) { + return m_iid.Equals(iid.m_iid); + } + + static PyObject * + PyObjectFromIID(const nsIID &iid) { + return new Py_nsIID(iid); + } + + static PRBool IIDFromPyObject(PyObject *ob, nsIID *pRet); + /* Python support */ + static PyObject *PyTypeMethod_getattr(PyObject *self, char *name); +#if PY_MAJOR_VERSION <= 2 + static int PyTypeMethod_compare(PyObject *self, PyObject *ob); +#endif + static PyObject *PyTypeMethod_richcompare(PyObject *self, PyObject *ob, int op); + static PyObject *PyTypeMethod_repr(PyObject *self); +#if PY_VERSION_HEX >= 0x03020000 + static Py_hash_t PyTypeMethod_hash(PyObject *self); +#else + static long PyTypeMethod_hash(PyObject *self); +#endif + static PyObject *PyTypeMethod_str(PyObject *self); + static void PyTypeMethod_dealloc(PyObject *self); +#ifndef Py_LIMITED_API + static NS_EXPORT_STATIC_MEMBER_(PyTypeObject) type; +#else + static NS_EXPORT_STATIC_MEMBER_(PyTypeObject *) s_pType; + static PyTypeObject *GetTypeObject(void); +#endif + static NS_EXPORT_STATIC_MEMBER_(PyMethodDef) methods[]; +}; + +/////////////////////////////////////////////////////// +// +// Helper classes for managing arrays of variants. +class PythonTypeDescriptor; // Forward declare. + +class PYXPCOM_EXPORT PyXPCOM_InterfaceVariantHelper { +public: + PyXPCOM_InterfaceVariantHelper(Py_nsISupports *parent, int methodindex); + ~PyXPCOM_InterfaceVariantHelper(); + PRBool Init(PyObject *obParams); + PRBool FillArray(); + + PyObject *MakePythonResult(); + + nsXPTCVariant *m_var_array; + int m_num_array; + int m_methodindex; +protected: + PyObject *MakeSinglePythonResult(int index); + PRBool FillInVariant(const PythonTypeDescriptor &, int, int); + PRBool PrepareOutVariant(const PythonTypeDescriptor &td, int value_index); + PRBool SetSizeIs( int var_index, PRBool is_arg1, PRUint32 new_size); + PRUint32 GetSizeIs( int var_index, PRBool is_arg1); + + PyObject *m_pyparams; // sequence of actual params passed (ie, not including hidden) + PyObject *m_typedescs; // desc of _all_ params, including hidden. + PythonTypeDescriptor *m_python_type_desc_array; + void **m_buffer_array; + Py_nsISupports *m_parent; + +}; + +/************************************************************************* +************************************************************************** + + Support for IMPLEMENTING interfaces. + +************************************************************************** +*************************************************************************/ +#define NS_IINTERNALPYTHON_IID_STR "AC7459FC-E8AB-4f2e-9C4F-ADDC53393A20" +#define NS_IINTERNALPYTHON_IID \ + { 0xac7459fc, 0xe8ab, 0x4f2e, { 0x9c, 0x4f, 0xad, 0xdc, 0x53, 0x39, 0x3a, 0x20 } } + +class PyXPCOM_GatewayWeakReference; + +// This interface is needed primarily to give us a known vtable base. +// If we QI a Python object for this interface, we can safely cast the result +// to a PyG_Base. Any other interface, we do now know which vtable we will get. +// We also allow the underlying PyObject to be extracted +class nsIInternalPython : public nsISupports { +public: + NS_DEFINE_STATIC_IID_ACCESSOR(NS_IINTERNALPYTHON_IID) + // Get the underlying Python object with new reference added + virtual PyObject *UnwrapPythonObject(void) = 0; +}; + +// This is roughly equivalent to PyGatewayBase in win32com +// +class PYXPCOM_EXPORT PyG_Base : public nsIInternalPython, public nsISupportsWeakReference +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSISUPPORTSWEAKREFERENCE + PyObject *UnwrapPythonObject(void); + + // A static "constructor" - the real ctor is protected. + static nsresult CreateNew(PyObject *pPyInstance, + const nsIID &iid, + void **ppResult); + + // A utility to auto-wrap an arbitary Python instance + // in a COM gateway. + static PRBool AutoWrapPythonInstance(PyObject *ob, + const nsIID &iid, + nsISupports **ppret); + + + // A helper that creates objects to be passed for nsISupports + // objects. See extensive comments in PyG_Base.cpp. + PyObject *MakeInterfaceParam(nsISupports *pis, + const nsIID *piid, + int methodIndex = -1, + const XPTParamDescriptor *d = NULL, + int paramIndex = -1); + + // A helper that ensures all casting and vtable offsetting etc + // done against this object happens in the one spot! + virtual void *ThisAsIID( const nsIID &iid ) = 0; + + // Helpers for "native" interfaces. + // Not used by the generic stub interface. + nsresult HandleNativeGatewayError(const char *szMethodName); + + // These data members used by the converter helper functions - hence public + nsIID m_iid; + PyObject * m_pPyObject; + // We keep a reference count on this object, and the object + // itself uses normal refcount rules - thus, it will only + // die when we die, and all external references are removed. + // This means that once we have created it (and while we + // are alive) it will never die. + nsCOMPtr<nsIWeakReference> m_pWeakRef; +#ifdef NS_BUILD_REFCNT_LOGGING + char refcntLogRepr[64]; // sigh - I wish I knew how to use the Moz string classes :( OK for debug only tho. +#endif +protected: + PyG_Base(PyObject *instance, const nsIID &iid); + virtual ~PyG_Base(); + PyG_Base *m_pBaseObject; // A chain to implement identity rules. + nsresult InvokeNativeViaPolicy( const char *szMethodName, + PyObject **ppResult = NULL, + const char *szFormat = NULL, + ... + ); + nsresult InvokeNativeViaPolicyInternal( const char *szMethodName, + PyObject **ppResult, + const char *szFormat, + va_list va); + nsresult InvokeNativeGetViaPolicy(const char *szPropertyName, + PyObject **ppResult = NULL + ); + nsresult InvokeNativeSetViaPolicy(const char *szPropertyName, + ...); +}; + +class PYXPCOM_EXPORT PyXPCOM_XPTStub : public PyG_Base, public nsXPTCStubBase +{ +friend class PyG_Base; +public: + NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) \ + {return PyG_Base::QueryInterface(aIID, aInstancePtr);} \ + NS_IMETHOD_(nsrefcnt) AddRef(void) {return PyG_Base::AddRef();} \ + NS_IMETHOD_(nsrefcnt) Release(void) {return PyG_Base::Release();} \ + + NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info); + // call this method and return result + NS_IMETHOD CallMethod(PRUint16 methodIndex, + const nsXPTMethodInfo* info, + nsXPTCMiniVariant* params); + + virtual void *ThisAsIID(const nsIID &iid); +protected: + PyXPCOM_XPTStub(PyObject *instance, const nsIID &iid) : PyG_Base(instance, iid) {;} +private: +}; + +// For the Gateways we manually implement. +#define PYGATEWAY_BASE_SUPPORT(INTERFACE, GATEWAY_BASE) \ + NS_IMETHOD QueryInterface(REFNSIID aIID, void** aInstancePtr) \ + {return PyG_Base::QueryInterface(aIID, aInstancePtr);} \ + NS_IMETHOD_(nsrefcnt) AddRef(void) {return PyG_Base::AddRef();} \ + NS_IMETHOD_(nsrefcnt) Release(void) {return PyG_Base::Release();} \ + virtual void *ThisAsIID(const nsIID &iid) { \ + if (iid.Equals(NS_GET_IID(INTERFACE))) return (INTERFACE *)this; \ + 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); +#ifdef VBOX_DEBUG_LIFETIMES +extern PYXPCOM_EXPORT PRInt32 _PyXPCOM_DumpInterfaces(void); +#endif + + +// Weak Reference class. This is a true COM object, representing +// a weak reference to a Python object. For each Python XPCOM object, +// there is exactly zero or one corresponding weak reference instance. +// When both are alive, each holds a pointer to the other. When the main +// object dies due to XPCOM reference counting, it zaps the pointer +// in its corresponding weak reference object. Thus, the weak-reference +// can live beyond the object (possibly with a NULL pointer back to the +// "real" object, but as implemented, the weak reference will never be +// destroyed before the object +class PYXPCOM_EXPORT PyXPCOM_GatewayWeakReference : public nsIWeakReference { +public: + PyXPCOM_GatewayWeakReference(PyG_Base *base); + virtual ~PyXPCOM_GatewayWeakReference(); + NS_DECL_ISUPPORTS + NS_DECL_NSIWEAKREFERENCE + PyG_Base *m_pBase; // NO REF COUNT!!! +#ifdef NS_BUILD_REFCNT_LOGGING + char refcntLogRepr[41]; +#endif +}; + + +// Helpers classes for our gateways. +class PYXPCOM_EXPORT PyXPCOM_GatewayVariantHelper +{ +public: + PyXPCOM_GatewayVariantHelper( PyG_Base *gateway, + int methodIndex, + const nsXPTMethodInfo *info, + nsXPTCMiniVariant* params ); + ~PyXPCOM_GatewayVariantHelper(); + PyObject *MakePyArgs(); + nsresult ProcessPythonResult(PyObject *ob); + PyG_Base *m_gateway; +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, 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 ); + nsIInterfaceInfo *GetInterfaceInfo(); // NOTE: no ref count on result. + + + nsXPTCMiniVariant* m_params; + const nsXPTMethodInfo *m_info; + int m_method_index; + PythonTypeDescriptor *m_python_type_desc_array; + int m_num_type_descs; + nsCOMPtr<nsIInterfaceInfo> m_interface_info; +}; + +// Misc converters. +PyObject *PyObject_FromXPTType( const nsXPTType *d); +// XPTTypeDescriptor derived from XPTType - latter is automatically processed via PyObject_FromXPTTypeDescriptor XPTTypeDescriptor +PyObject *PyObject_FromXPTTypeDescriptor( const XPTTypeDescriptor *d); + +PyObject *PyObject_FromXPTParamDescriptor( const XPTParamDescriptor *d); +PyObject *PyObject_FromXPTMethodDescriptor( const XPTMethodDescriptor *d); +PyObject *PyObject_FromXPTConstant( const XPTConstDescriptor *d); + +// DLL reference counting functions. +// Although we maintain the count, we never actually +// finalize Python when it hits zero! +void PyXPCOM_DLLAddRef(); +void PyXPCOM_DLLRelease(); + +/************************************************************************* +************************************************************************** + + LOCKING AND THREADING + +************************************************************************** +*************************************************************************/ + +// +// We have 2 discrete locks in use (when no free-threaded is used, anyway). +// The first type of lock is the global Python lock. This is the standard lock +// in use by Python, and must be used as documented by Python. Specifically, no +// 2 threads may _ever_ call _any_ Python code (including INCREF/DECREF) without +// first having this thread lock. +// +// The second type of lock is a "global framework lock", and used whenever 2 threads +// of C code need access to global data. This is different than the Python +// lock - this lock is used when no Python code can ever be called by the +// threads, but the C code still needs thread-safety. + +// We also supply helper classes which make the usage of these locks a one-liner. + +// The "framework" lock, implemented as a PRLock +PYXPCOM_EXPORT void PyXPCOM_AcquireGlobalLock(void); +PYXPCOM_EXPORT void PyXPCOM_ReleaseGlobalLock(void); + +// Helper class for the DLL global lock. +// +// This class magically waits for PyXPCOM framework global lock, and releases it +// when finished. +// NEVER new one of these objects - only use on the stack! +class CEnterLeaveXPCOMFramework { +public: + CEnterLeaveXPCOMFramework() {PyXPCOM_AcquireGlobalLock();} + ~CEnterLeaveXPCOMFramework() {PyXPCOM_ReleaseGlobalLock();} +}; + +// Python thread-lock stuff. Free-threading patches use different semantics, but +// these are abstracted away here... +//#include <threadstate.h> + +// Helper class for Enter/Leave Python +// +// This class magically waits for the Python global lock, and releases it +// when finished. + +// Nested invocations will deadlock, so be careful. + +// NEVER new one of these objects - only use on the stack! + +PYXPCOM_EXPORT void PyXPCOM_MakePendingCalls(); +PYXPCOM_EXPORT PRBool PyXPCOM_Globals_Ensure(); + +// For 2.3, use the PyGILState_ calls +#if (PY_VERSION_HEX >= 0x02030000) +#define PYXPCOM_USE_PYGILSTATE +#endif + +#ifdef PYXPCOM_USE_PYGILSTATE +class CEnterLeavePython { +public: + CEnterLeavePython() { + state = PyGILState_Ensure(); + // See "pending calls" comment below. We reach into the Python + // implementation to see if we are the first call on the stack. +# ifndef Py_LIMITED_API + if (PyThreadState_Get()->gilstate_counter==1) { +# else + if (state == PyGILState_UNLOCKED) { +# endif + PyXPCOM_MakePendingCalls(); + } + } + ~CEnterLeavePython() { + PyGILState_Release(state); + } + PyGILState_STATE state; +}; +#else + +extern 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 { +public: + CEnterLeavePython() { + created = PyXPCOM_ThreadState_Ensure(); + PyXPCOM_InterpreterLock_Acquire(); + if (created) { + // If pending python calls are waiting as we enter Python, + // it will generally mean an asynch signal handler, etc. + // We can either call it here, or wait for Python to call it + // as part of its "even 'n' opcodes" check. If we wait for + // Python to check it and the pending call raises an exception, + // then it is _our_ code that will fail - this is unfair, + // as the signal was raised before we were entered - indeed, + // we may be directly responding to the signal! + // Thus, we flush all the pending calls here, and report any + // exceptions via our normal exception reporting mechanism. + // We can then execute our code in the knowledge that only + // signals raised _while_ we are executing will cause exceptions. + PyXPCOM_MakePendingCalls(); + } + } + ~CEnterLeavePython() { + // The interpreter state must be cleared + // _before_ we release the lock, as some of + // the sys. attributes cleared (eg, the current exception) + // may need the lock to invoke their destructors - + // specifically, when exc_value is a class instance, and + // the exception holds the last reference! + if ( created ) + PyXPCOM_ThreadState_Clear(); + PyXPCOM_InterpreterLock_Release(); + if ( created ) + PyXPCOM_ThreadState_Free(); + } +private: + PRBool created; +}; +#endif // PYXPCOM_USE_PYGILSTATE + +// Our classes. +// Hrm - So we can't have templates, eh?? +// preprocessor to the rescue, I guess. +#define PyXPCOM_INTERFACE_DECLARE(ClassName, InterfaceName, Methods ) \ + \ +extern struct PyMethodDef Methods[]; \ + \ +class ClassName : public Py_nsISupports \ +{ \ +public: \ + static PYXPCOM_EXPORT PyXPCOM_TypeObject *type; \ + static Py_nsISupports *Constructor(nsISupports *pInitObj, const nsIID &iid) { \ + return new ClassName(pInitObj, iid); \ + } \ + static void InitType() { \ + type = new PyXPCOM_TypeObject( \ + #InterfaceName, \ + Py_nsISupports::type, \ + sizeof(ClassName), \ + Methods, \ + Constructor); \ + const nsIID &iid = NS_GET_IID(InterfaceName); \ + RegisterInterface(iid, type); \ + } \ +protected: \ + ClassName(nsISupports *p, const nsIID &iid) : \ + Py_nsISupports(p, iid, type) { \ + /* The IID _must_ be the IID of the interface we are wrapping! */ \ + NS_ABORT_IF_FALSE(iid.Equals(NS_GET_IID(InterfaceName)), "Bad IID"); \ + } \ +}; \ + \ +// End of PyXPCOM_INTERFACE_DECLARE macro + +#define PyXPCOM_ATTR_INTERFACE_DECLARE(ClassName, InterfaceName, Methods )\ + \ +extern struct PyMethodDef Methods[]; \ + \ +class ClassName : public Py_nsISupports \ +{ \ +public: \ + static PyXPCOM_TypeObject *type; \ + static Py_nsISupports *Constructor(nsISupports *pInitObj, const nsIID &iid) { \ + return new ClassName(pInitObj, iid); \ + } \ + static void InitType() { \ + type = new PyXPCOM_TypeObject( \ + #InterfaceName, \ + Py_nsISupports::type, \ + sizeof(ClassName), \ + Methods, \ + Constructor); \ + const nsIID &iid = NS_GET_IID(InterfaceName); \ + RegisterInterface(iid, type); \ +} \ + virtual PyObject *getattr(const char *name); \ + virtual int setattr(const char *name, PyObject *val); \ +protected: \ + ClassName(nsISupports *p, const nsIID &iid) : \ + Py_nsISupports(p, iid, type) { \ + /* The IID _must_ be the IID of the interface we are wrapping! */ \ + NS_ABORT_IF_FALSE(iid.Equals(NS_GET_IID(InterfaceName)), "Bad IID"); \ + } \ +}; \ + \ +// End of PyXPCOM_ATTR_INTERFACE_DECLARE macro + +#define PyXPCOM_INTERFACE_DEFINE(ClassName, InterfaceName, Methods ) \ +PyXPCOM_TypeObject *ClassName::type = NULL; + + +// And the classes +PyXPCOM_INTERFACE_DECLARE(Py_nsIComponentManager, nsIComponentManager, PyMethods_IComponentManager) +PyXPCOM_INTERFACE_DECLARE(Py_nsIInterfaceInfoManager, nsIInterfaceInfoManager, PyMethods_IInterfaceInfoManager) +PyXPCOM_INTERFACE_DECLARE(Py_nsIEnumerator, nsIEnumerator, PyMethods_IEnumerator) +PyXPCOM_INTERFACE_DECLARE(Py_nsISimpleEnumerator, nsISimpleEnumerator, PyMethods_ISimpleEnumerator) +PyXPCOM_INTERFACE_DECLARE(Py_nsIInterfaceInfo, nsIInterfaceInfo, PyMethods_IInterfaceInfo) +PyXPCOM_INTERFACE_DECLARE(Py_nsIInputStream, nsIInputStream, PyMethods_IInputStream) +PyXPCOM_ATTR_INTERFACE_DECLARE(Py_nsIClassInfo, nsIClassInfo, PyMethods_IClassInfo) +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__ diff --git a/src/libs/xpcom18a4/python/src/PyXPCOM_std.h b/src/libs/xpcom18a4/python/src/PyXPCOM_std.h new file mode 100644 index 00000000..b7b7ff8c --- /dev/null +++ b/src/libs/xpcom18a4/python/src/PyXPCOM_std.h @@ -0,0 +1,56 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * 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 ***** */ + +// standard include - sets up all the defines used by +// the mozilla make process - too lazy to work out how to integrate +// with their make, so this will do! + +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +// This header is considered internal - hence +// we can use it to trigger "exports" +#define BUILD_PYXPCOM + +#include "PyXPCOM.h" diff --git a/src/libs/xpcom18a4/python/src/Pyxpt_info.cpp b/src/libs/xpcom18a4/python/src/Pyxpt_info.cpp new file mode 100644 index 00000000..d1df54fe --- /dev/null +++ b/src/libs/xpcom18a4/python/src/Pyxpt_info.cpp @@ -0,0 +1,197 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Mark Hammond <MarkH@ActiveState.com> (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 ***** */ + +// Pyxpt_info.cpp - wrappers for the xpt_info objects. +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. +#include "PyXPCOM_std.h" + +PyObject *PyObject_FromXPTType( const nsXPTType *d) +{ + if (d==nsnull) { + Py_INCREF(Py_None); + return Py_None; + } + // build an object using the same format as a TypeDescriptor. + return Py_BuildValue("bzzz", + d->flags, + NULL, NULL, NULL); +} + +PyObject *PyObject_FromXPTTypeDescriptor( const XPTTypeDescriptor *d) +{ + if (d==nsnull) { + Py_INCREF(Py_None); + return Py_None; + } + return Py_BuildValue("bbbh", + d->prefix.flags, + d->argnum, + d->argnum2, + d->type.iface // this is actually a union! + ); +} + +PyObject *PyObject_FromXPTParamDescriptor( const XPTParamDescriptor *d) +{ + if (d==nsnull) { + Py_INCREF(Py_None); + return Py_None; + } + PyObject *ob = PyObject_FromXPTTypeDescriptor(&d->type); + PyObject *ret = Py_BuildValue("bO", d->flags, ob); + Py_DECREF(ob); + return ret; +} + +PyObject *PyObject_FromXPTMethodDescriptor( const XPTMethodDescriptor *d) +{ + if (d==nsnull) { + Py_INCREF(Py_None); + return Py_None; + } + PyObject *ob_params = PyTuple_New(d->num_args); + if (ob_params==NULL) + return NULL; + for (int i=0;i<d->num_args;i++) + PyTuple_SET_ITEM(ob_params, i, PyObject_FromXPTParamDescriptor(d->params+i)); + PyObject *ob_ret = PyObject_FromXPTParamDescriptor(d->result); + PyObject *ret = Py_BuildValue("bsOO", d->flags, d->name, ob_params, ob_ret); + Py_XDECREF(ob_ret); + Py_XDECREF(ob_params); + return ret; +} + +PyObject *PyObject_FromXPTConstant( const XPTConstDescriptor *c) +{ + if (c==nsnull) { + Py_INCREF(Py_None); + return Py_None; + } + PyObject *ob_type = PyObject_FromXPTTypeDescriptor(&c->type); + if (ob_type==NULL) + return NULL; + PyObject *v = NULL; + switch (c->type.prefix.flags) { + case TD_INT8: + v = PyInt_FromLong( c->value.i8 ); + break; + case TD_INT16: + v = PyInt_FromLong( c->value.i16 ); + break; + case TD_INT32: + v = PyInt_FromLong( c->value.i32 ); + break; + case TD_INT64: + v = PyLong_FromLongLong(c->value.i64); + break; + case TD_UINT8: + v = PyInt_FromLong( c->value.ui8 ); + break; + case TD_UINT16: + v = PyInt_FromLong( c->value.ui16 ); + break; + case TD_UINT32: + v = PyInt_FromLong( c->value.ui32 ); + break; + case TD_UINT64: + v = PyLong_FromUnsignedLongLong(c->value.ui64); + break; + case TD_FLOAT: + v = PyFloat_FromDouble(c->value.flt); + break; + case TD_DOUBLE: + v = PyFloat_FromDouble(c->value.dbl); + break; + case TD_BOOL: + v = c->value.bul ? Py_True : Py_False; + Py_INCREF(v); + break; + case TD_CHAR: +#if PY_MAJOR_VERSION <= 2 + v = PyString_FromStringAndSize(&c->value.ch, 1); +#else + v = PyUnicode_FromStringAndSize(&c->value.ch, 1); +#endif + break; + case TD_WCHAR: + v = PyObject_FromNSString((PRUnichar *)&c->value.wch, 1); + break; + // TD_VOID = 13, + case TD_PNSIID: + v = Py_nsIID::PyObjectFromIID(*c->value.iid); + break; + // TD_DOMSTRING = 15, + case TD_PSTRING: +#if PY_MAJOR_VERSION <= 2 + v = PyString_FromString(c->value.str); +#else + v = PyUnicode_FromString(c->value.str); +#endif + break; + case TD_PWSTRING: + v = PyObject_FromNSString((PRUnichar *)c->value.wstr, nsCRT::strlen((PRUnichar *)c->value.wstr)); + break; + // TD_INTERFACE_TYPE = 18, + // TD_INTERFACE_IS_TYPE = 19, + // TD_ARRAY = 20, + // TD_PSTRING_SIZE_IS = 21, + // TD_PWSTRING_SIZE_IS = 22 + // TD_UTF8STRING = 23, + // TD_CSTRING = 24, + // TD_ASTRING = 25 + default: +#if PY_MAJOR_VERSION <= 2 + v = PyString_FromString("Unknown type code!!"); +#else + v = PyUnicode_FromString("Unknown type code!!"); +#endif + break; + + } + PyObject *ret = Py_BuildValue("sbO", c->name, ob_type, v); + Py_DECREF(ob_type); + Py_DECREF(v); + return ret; +} diff --git a/src/libs/xpcom18a4/python/src/TypeObject.cpp b/src/libs/xpcom18a4/python/src/TypeObject.cpp new file mode 100644 index 00000000..37cc13d7 --- /dev/null +++ b/src/libs/xpcom18a4/python/src/TypeObject.cpp @@ -0,0 +1,457 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * 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 ***** */ + +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +#include "PyXPCOM_std.h" +#include <nsIInterfaceInfoManager.h> +#include <nsXPCOM.h> +#include <nsISupportsPrimitives.h> + +#if defined(Py_LIMITED_API) && defined(RT_OS_LINUX) +# include <features.h> +# ifdef __GLIBC_PREREQ +# if __GLIBC_PREREQ(2,9) +# define PYXPCOM_HAVE_PIPE2 +# include <fcntl.h> +# endif +# endif +#endif + + +#ifndef Py_LIMITED_API +static PyTypeObject PyInterfaceType_Type = { + PyVarObject_HEAD_INIT(&PyType_Type, 0) + "interface-type", /* Name of this type */ + sizeof(PyTypeObject), /* Basic object size */ + 0, /* Item size for varobject */ + 0, /*tp_dealloc*/ + 0, /*tp_print*/ + PyType_Type.tp_getattr, /*tp_getattr*/ + 0, /*tp_setattr*/ + 0, /*tp_compare*/ + PyType_Type.tp_repr, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ + 0, /*tp_call*/ + 0, /*tp_str*/ + 0, /* tp_getattro */ + 0, /*tp_setattro */ + 0, /* tp_as_buffer */ + 0, /* tp_flags */ + "Define the behavior of a PythonCOM Interface type.", +}; + +#else /* Py_LIMITED_API */ + +/** The offset of PyTypeObject::ob_name. */ +static size_t g_offObTypeNameMember = sizeof(PyVarObject); + +/** + * Base type object for XPCOM interfaces. Created dynamicially. + */ +static PyTypeObject *g_pPyInterfaceTypeObj = NULL; + +/** + * Gets the base XPCOM interface type object, creating it if needed. + */ +static PyTypeObject *PyXPCOM_CreateInterfaceType(void) +{ + static char g_szTypeDoc[] = "Define the behavior of a PythonCOM Interface type."; /* need non-const */ + PyType_Slot aTypeSlots[] = { + { Py_tp_doc, g_szTypeDoc }, + { 0, NULL } /* terminator */ + }; + static const char g_szClassNm[] = "interface-type"; + PyType_Spec TypeSpec = { + /* .name: */ g_szClassNm, + /* .basicsize: */ 0, + /* .itemsize: */ 0, + /* .flags: */ Py_TPFLAGS_BASETYPE, + /* .slots: */ aTypeSlots, + }; + + PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL; + PyErr_Fetch(&exc_typ, &exc_val, &exc_tb); /* goes south in PyType_Ready if we don't clear exceptions first. */ + + PyTypeObject *pTypeObj = (PyTypeObject *)PyType_FromSpec(&TypeSpec); + assert(pTypeObj); + + PyErr_Restore(exc_typ, exc_val, exc_tb); + g_pPyInterfaceTypeObj = pTypeObj; + + /* + * Verify/correct g_offObTypeNameMember. + * + * Using pipe+write to probe the memory content, banking on the kernel + * to return EFAULT when we pass it an invalid address. + */ + for (size_t off = sizeof(PyVarObject); off < sizeof(PyVarObject) + 64; off += sizeof(char *)) { + const char * const pszProbe = *(const char **)((uintptr_t)(pTypeObj) + off); + if (RT_VALID_PTR(pszProbe)) { + int fds[2] = { -1, -1 }; +# ifdef PYXPCOM_HAVE_PIPE2 + int rc = pipe2(fds, O_CLOEXEC); +# else + int rc = pipe(fds); +# endif + if (rc) + break; + + ssize_t cbWritten = write(fds[1], pszProbe, sizeof(g_szClassNm)); + if (cbWritten == (ssize_t)sizeof(g_szClassNm)) { + char szReadBack[sizeof(g_szClassNm)]; + ssize_t offRead = 0; + while (offRead < cbWritten) { + ssize_t cbRead = read(fds[0], &szReadBack[offRead], cbWritten - offRead); + if (cbRead >= 0) { + offRead += cbRead; + } else if (errno != EINTR) + break; + } + if ( cbWritten == offRead + && memcmp(szReadBack, g_szClassNm, sizeof(szReadBack)) == 0) { + g_offObTypeNameMember = off; + close(fds[0]); + close(fds[1]); + return pTypeObj; + } + } + close(fds[0]); + close(fds[1]); + } + } + assert(0); + + return pTypeObj; +} + +/** + * Gets the base XPCOM interface type object, creating it if needed. + */ +static PyTypeObject *PyXPCOM_GetInterfaceType(void) +{ + PyTypeObject *pTypeObj = g_pPyInterfaceTypeObj; + if (pTypeObj) + return pTypeObj; + return PyXPCOM_CreateInterfaceType(); +} + +/** + * Get the PyTypeObject::ob_name value. + * + * @todo This is _horrible_, but there appears to be no simple tp_name getter + * till https://bugs.python.org/issue31497 (2017 / 3.7.0). But even then + * it is not part of the limited API. + */ +const char *PyXPCOMGetObTypeName(PyTypeObject *pTypeObj) +{ + return *(const char **)((uintptr_t)(pTypeObj) + g_offObTypeNameMember); +} + +#endif /* Py_LIMITED_API */ + +/*static*/ PRBool +PyXPCOM_TypeObject::IsType(PyTypeObject *t) +{ +#if PY_MAJOR_VERSION <= 2 + return t->ob_type == &PyInterfaceType_Type; +#elif !defined(Py_LIMITED_API) + return Py_TYPE(t) == &PyInterfaceType_Type; +#else + return Py_TYPE(t) == g_pPyInterfaceTypeObj /* Typically not the case as t->ob_type is &PyType_Type */ + || PyType_IsSubtype(t, g_pPyInterfaceTypeObj); /* rather than g_pPyInterfaceTypeObj because of PyType_FromSpec(). */ +#endif +} + +//////////////////////////////////////////////////////////////////// +// +// The type methods +// +/*static*/PyObject * +PyXPCOM_TypeObject::Py_getattr(PyObject *self, char *name) +{ + return ((Py_nsISupports *)self)->getattr(name); +} + +/*static*/int +PyXPCOM_TypeObject::Py_setattr(PyObject *op, char *name, PyObject *v) +{ + return ((Py_nsISupports *)op)->setattr(name, v); +} + +// @pymethod int|Py_nsISupports|__cmp__|Implements XPCOM rules for object identity. +/*static*/int +PyXPCOM_TypeObject::Py_cmp(PyObject *self, PyObject *other) +{ + // @comm NOTE: Copied from COM - have not confirmed these rules are true for XPCOM + // @comm As per the XPCOM rules for object identity, both objects are queried for nsISupports, and these values compared. + // The only meaningful test is for equality - the result of other comparisons is undefined + // (ie, determined by the object's relative addresses in memory. + nsISupports *pUnkOther; + nsISupports *pUnkThis; + if (!Py_nsISupports::InterfaceFromPyObject(self, NS_GET_IID(nsISupports), &pUnkThis, PR_FALSE)) + return -1; + if (!Py_nsISupports::InterfaceFromPyObject(other, NS_GET_IID(nsISupports), &pUnkOther, PR_FALSE)) { + pUnkThis->Release(); + return -1; + } + int rc = pUnkThis==pUnkOther ? 0 : + (pUnkThis < pUnkOther ? -1 : 1); + pUnkThis->Release(); + pUnkOther->Release(); + return rc; +} + +/*static*/PyObject * +PyXPCOM_TypeObject::Py_richcmp(PyObject *self, PyObject *other, int op) +{ + PyObject *result = NULL; + int rc = Py_cmp(self, other); + switch (op) + { + case Py_LT: + result = rc < 0 ? Py_True : Py_False; + break; + case Py_LE: + result = rc <= 0 ? Py_True : Py_False; + break; + case Py_EQ: + result = rc == 0 ? Py_True : Py_False; + break; + case Py_NE: + result = rc != 0 ? Py_True : Py_False; + break; + case Py_GT: + result = rc > 0 ? Py_True : Py_False; + break; + case Py_GE: + result = rc >= 0 ? Py_True : Py_False; + break; + } + Py_XINCREF(result); + return result; +} + +// @pymethod int|Py_nsISupports|__hash__|Implement a hash-code for the XPCOM object using XPCOM identity rules. +#if PY_VERSION_HEX >= 0x03020000 +/*static*/Py_hash_t PyXPCOM_TypeObject::Py_hash(PyObject *self) +#else +/*static*/long PyXPCOM_TypeObject::Py_hash(PyObject *self) +#endif +{ + // We always return the value of the nsISupports *. + nsISupports *pUnkThis; + if (!Py_nsISupports::InterfaceFromPyObject(self, NS_GET_IID(nsISupports), &pUnkThis, PR_FALSE)) + return -1; +#if PY_VERSION_HEX >= 0x03020000 + Py_hash_t ret = _Py_HashPointer(pUnkThis); +#else + long ret = _Py_HashPointer(pUnkThis); +#endif + pUnkThis->Release(); + return ret; +} + +// @method string|Py_nsISupports|__repr__|Called to create a representation of a Py_nsISupports object +/*static */PyObject * +PyXPCOM_TypeObject::Py_repr(PyObject *self) +{ + // @comm The repr of this object displays both the object's address, and its attached nsISupports's address + Py_nsISupports *pis = (Py_nsISupports *)self; + // Try and get the IID name. + char *iid_repr = nsnull; + nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService( + NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)); + if (iim!=nsnull) + iim->GetNameForIID(&pis->m_iid, &iid_repr); + if (iid_repr==nsnull) + // no IIM available, or it doesnt know the name. + iid_repr = pis->m_iid.ToString(); + // XXX - need some sort of buffer overflow. + char buf[512]; +#ifdef VBOX + snprintf(buf, sizeof(buf), "<XPCOM object (%s) at %p/%p>", + iid_repr, (void *)self, (void *)pis->m_obj.get()); +#else + sprintf(buf, "<XPCOM object (%s) at 0x%p/0x%p>", + iid_repr, (void *)self, (void *)pis->m_obj.get()); +#endif + nsMemory::Free(iid_repr); +#if PY_MAJOR_VERSION <= 2 + return PyString_FromString(buf); +#else + return PyUnicode_FromString(buf); +#endif +} + +/*static */PyObject * +PyXPCOM_TypeObject::Py_str(PyObject *self) +{ + Py_nsISupports *pis = (Py_nsISupports *)self; + nsresult rv; + char *val = NULL; + Py_BEGIN_ALLOW_THREADS; + { // scope to kill pointer while thread-lock released. + nsCOMPtr<nsISupportsCString> ss( do_QueryInterface(pis->m_obj, &rv )); + if (NS_SUCCEEDED(rv)) + rv = ss->ToString(&val); + } // end-scope + Py_END_ALLOW_THREADS; + PyObject *ret; + if (NS_FAILED(rv)) + ret = Py_repr(self); + else +#if PY_MAJOR_VERSION <= 2 + ret = PyString_FromString(val); +#else + ret = PyUnicode_FromString(val); +#endif + if (val) nsMemory::Free(val); + return ret; +} + +/* static */void +PyXPCOM_TypeObject::Py_dealloc(PyObject *self) +{ + delete (Py_nsISupports *)self; +} + +PyXPCOM_TypeObject::PyXPCOM_TypeObject( const char *name, PyXPCOM_TypeObject *pBase, int typeSize, struct PyMethodDef* methodList, PyXPCOM_I_CTOR thector) +{ +#ifndef Py_LIMITED_API + static const PyTypeObject type_template = { + PyVarObject_HEAD_INIT(&PyInterfaceType_Type, 0) + "XPCOMTypeTemplate", /*tp_name*/ + sizeof(Py_nsISupports), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + Py_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + Py_getattr, /* tp_getattr */ + Py_setattr, /* tp_setattr */ +#if PY_MAJOR_VERSION <= 2 + Py_cmp, /* tp_compare */ +#else + 0, /* reserved */ +#endif + Py_repr, /* tp_repr */ + 0, /* tp_as_number*/ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 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 */ + Py_richcmp, /* 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; +#else /* Py_LIMITED_API */ + /* Create the type specs: */ + PyType_Slot aTypeSlots[] = { + { Py_tp_base, PyXPCOM_GetInterfaceType() }, + { Py_tp_dealloc, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_dealloc }, + { Py_tp_getattr, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_getattr }, + { Py_tp_setattr, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_setattr }, + { Py_tp_repr, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_repr }, + { Py_tp_hash, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_hash }, + { Py_tp_str, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_str }, + { Py_tp_richcompare, (void *)(uintptr_t)&PyXPCOM_TypeObject::Py_richcmp }, + { 0, NULL } /* terminator */ + }; + PyType_Spec TypeSpec = { + /* .name: */ name, + /* .basicsize: */ typeSize, + /* .itemsize: */ 0, + /* .flags: */ Py_TPFLAGS_BASETYPE /*?*/, + /* .slots: */ aTypeSlots, + }; + + PyObject *exc_typ = NULL, *exc_val = NULL, *exc_tb = NULL; + PyErr_Fetch(&exc_typ, &exc_val, &exc_tb); /* goes south in PyType_Ready if we don't clear exceptions first. */ + + m_pTypeObj = (PyTypeObject *)PyType_FromSpec(&TypeSpec); + assert(m_pTypeObj); + + PyErr_Restore(exc_typ, exc_val, exc_tb); + + /* Initialize the PyObject part - needed so we can keep instance in a PyDict: */ + ob_type = PyXPCOM_GetInterfaceType(); + PyObject_Init(this, ob_type); /* VBox: Needed for 3.9 and up (also works on Python 2.7), includes _Py_NewReferences. @bugref{10079} */ + +#endif /* Py_LIMITED_API */ + + chain.methods = methodList; + chain.link = pBase ? &pBase->chain : NULL; + + baseType = pBase; + ctor = thector; + +#ifndef Py_LIMITED_API + // cast away const, as Python doesnt use it. + tp_name = (char *)name; + tp_basicsize = typeSize; +#endif +} + +PyXPCOM_TypeObject::~PyXPCOM_TypeObject() +{ +} + diff --git a/src/libs/xpcom18a4/python/src/VariantUtils.cpp b/src/libs/xpcom18a4/python/src/VariantUtils.cpp new file mode 100644 index 00000000..ac14a2cf --- /dev/null +++ b/src/libs/xpcom18a4/python/src/VariantUtils.cpp @@ -0,0 +1,3112 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Mark Hammond <mhammond@skippinet.com.au> (original author) + * + * Unicode corrections by Shane Hathaway (http://hathawaymix.org), + * inspired by Mikhail Sobolev + * + * 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 ***** */ + +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +#include "PyXPCOM_std.h" +#include <nsIInterfaceInfoManager.h> +#include <nsAString.h> +#include <nsString.h> +#include <nsReadableUtils.h> + +// ------------------------------------------------------------------------ +// nsString utilities +// ------------------------------------------------------------------------ +// one day we may know what they look like. +inline +PRBool +IsNullDOMString( const nsAString& aString ) +{ + return PR_FALSE; +} + +inline +PRBool +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. +static int +PyUnicode_AsPRUnichar(PyObject *obj, PRUnichar **dest_out, PRUint32 *size_out) +{ + PRUint32 size; + PyObject *s; + const void *src; + PRUnichar *dest; + + s = PyUnicode_AsUTF16String(obj); + if (!s) + return -1; + // Drop the UTF-16 byte order mark at the beginning of + // the string. (See the docs on PyUnicode_AsUTF16String.) + // Some Mozilla libraries don't like the mark. +#if PY_MAJOR_VERSION <= 2 + size = (PyString_GET_SIZE(s) - 2) / sizeof(PRUnichar); + src = PyString_AS_STRING(s) + 2; +#else + if (!PyBytes_Check(s)) { + PyErr_SetString(PyExc_TypeError, "internal error in PyXPCOM, parameter must be a bytes object"); + return -1; + } + size = (PyBytes_GET_SIZE(s) - 2) / sizeof(PRUnichar); + src = PyBytes_AS_STRING(s) + 2; +#endif + dest = (PRUnichar *)nsMemory::Alloc(sizeof(PRUnichar) * (size + 1)); + if (!dest) { + PyErr_NoMemory(); + Py_DECREF(s); + return -1; + } + memcpy(dest, src, sizeof(PRUnichar) * size); + Py_DECREF(s); + dest[size] = 0; + *dest_out = dest; + if (size_out) + *size_out = size; + return 0; +} + +PyObject *PyObject_FromNSString( const nsACString &s, PRBool bAssumeUTF8 /*= PR_FALSE */) +{ + PyObject *ret; + if (IsNullDOMString(s)) { + ret = Py_None; + Py_INCREF(Py_None); + } else { + if (bAssumeUTF8) { + const nsPromiseFlatCString& temp = PromiseFlatCString(s); + ret = PyUnicode_DecodeUTF8(temp.get(), temp.Length(), NULL); + } else { +#if PY_MAJOR_VERSION <= 2 + ret = PyString_FromStringAndSize(NULL, s.Length()); +#else + ret = PyUnicode_FromStringAndSize(NULL, s.Length()); +#endif + if (!ret) + return NULL; + // Need "CopyAsciiTo"!? + nsACString::const_iterator fromBegin, fromEnd; +#if PY_MAJOR_VERSION <= 2 + char* dest = (char *)PyString_AS_STRING(ret); +#else + char* dest = (char *)PyUnicode_AsUTF8(ret); +#endif + copy_string(s.BeginReading(fromBegin), s.EndReading(fromEnd), dest); + } + } + return ret; +} + +PyObject *PyObject_FromNSString( const nsAString &s ) +{ + PyObject *ret; + if (IsNullDOMString(s)) { + ret = Py_None; + Py_INCREF(Py_None); + } else { + 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 PY_MAJOR_VERSION <= 2 + 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; +#else + if (!PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object"); + ok = PR_FALSE; + } + val_use = val; + Py_INCREF(val_use); +#endif + 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) +{ + PRUint32 ret; + switch (t & XPT_TDP_TAGMASK) { + case nsXPTType::T_U8: + case nsXPTType::T_I8: + ret = sizeof(PRInt8); + break; + case nsXPTType::T_I16: + case nsXPTType::T_U16: + ret = sizeof(PRInt16); + break; + case nsXPTType::T_I32: + case nsXPTType::T_U32: + ret = sizeof(PRInt32); + break; + case nsXPTType::T_I64: + case nsXPTType::T_U64: + ret = sizeof(PRInt64); + break; + case nsXPTType::T_FLOAT: + ret = sizeof(float); + break; + case nsXPTType::T_DOUBLE: + ret = sizeof(double); + break; + case nsXPTType::T_BOOL: + ret = sizeof(PRBool); + break; + case nsXPTType::T_CHAR: + ret = sizeof(char); + break; + case nsXPTType::T_WCHAR: + ret = sizeof(PRUnichar); + break; + case nsXPTType::T_IID: + case nsXPTType::T_CHAR_STR: + case nsXPTType::T_WCHAR_STR: + case nsXPTType::T_INTERFACE: + case nsXPTType::T_DOMSTRING: + case nsXPTType::T_INTERFACE_IS: + case nsXPTType::T_PSTRING_SIZE_IS: + case nsXPTType::T_CSTRING: + case nsXPTType::T_ASTRING: + case nsXPTType::T_UTF8STRING: + + ret = sizeof( void * ); + break; + default: + NS_ABORT_IF_FALSE(0, "Unknown array type code!"); + ret = 0; + break; + } + return ret; +} + +static nsresult +GetArrayElementIID(Py_nsISupports* self, + nsXPTCVariant* dispatchParams, + PRUint16 methodIndex, + PRUint8 paramIndex, + nsIID *result) +{ + nsCOMPtr<nsIInterfaceInfoManager> iim = XPTI_GetInterfaceInfoManager(); + nsCOMPtr<nsIInterfaceInfo> ii; + nsresult rc; + + rc = iim->GetInfoForIID(&self->m_iid, getter_AddRefs(ii)); + if (NS_FAILED(rc)) + return rc; + + + const nsXPTMethodInfo *mi; + rc = ii->GetMethodInfo(methodIndex, &mi); + if (NS_FAILED(rc)) + return rc; + + const nsXPTParamInfo& paramInfo = mi->GetParam(paramIndex); + + if (!paramInfo.GetType().IsArray()) { + PyXPCOM_LogWarning("Passing non-array to GetArrayElementIID\n"); + return NS_ERROR_INVALID_ARG; + } + + nsXPTType elemType; + rc = ii->GetTypeForParam(methodIndex, ¶mInfo, 1, &elemType); + if (NS_FAILED(rc)) + return rc; + + PRUint8 tag = elemType.TagPart(); + if (tag == nsXPTType::T_INTERFACE) + { + rc = ii->GetIIDForParamNoAlloc(methodIndex, ¶mInfo, result); + } + else if (tag == nsXPTType::T_INTERFACE_IS) + { + PyXPCOM_LogWarning("Unable to handle T_INTERFACE_IS yet\n"); + return NS_ERROR_NOT_IMPLEMENTED; + } + else + { + // this may be valid case, for arrays of other types + // we don't need IID for + rc = NS_ERROR_INVALID_ARG; + } + + return rc; +} + + +void FreeSingleArray(void *array_ptr, PRUint32 sequence_size, PRUint8 array_type) +{ + // Free each array element - NOT the array itself + // Thus, we only need to free arrays or pointers. + void **p = (void **)array_ptr; + PRUint32 i; + switch(array_type & XPT_TDP_TAGMASK) { + case nsXPTType::T_IID: + case nsXPTType::T_CHAR_STR: + case nsXPTType::T_WCHAR_STR: + for (i=0; i<sequence_size; i++) + if (p[i]) nsMemory::Free(p[i]); + break; + case nsXPTType::T_INTERFACE: + case nsXPTType::T_INTERFACE_IS: + for (i=0; i<sequence_size; i++) + if (p[i]) { + Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires. + ((nsISupports *)p[i])->Release(); + Py_END_ALLOW_THREADS; + } + break; + + // Ones we know need no deallocation + case nsXPTType::T_U8: + case nsXPTType::T_I8: + case nsXPTType::T_I16: + case nsXPTType::T_U16: + case nsXPTType::T_I32: + case nsXPTType::T_U32: + case nsXPTType::T_I64: + case nsXPTType::T_U64: + case nsXPTType::T_FLOAT: + case nsXPTType::T_DOUBLE: + case nsXPTType::T_BOOL: + case nsXPTType::T_CHAR: + case nsXPTType::T_WCHAR: + break; + + // And a warning should new type codes appear, as they may need deallocation. + default: + PyXPCOM_LogWarning("Deallocating unknown type %d (0x%x) - possible memory leak\n"); + break; + } +} + +#define FILL_SIMPLE_POINTER( type, val ) *((type *)pthis) = (type)(val) +#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, nsIID *pIID) +{ + PRUint8 *pthis = (PRUint8 *)array_ptr; + NS_ABORT_IF_FALSE(pthis, "Don't have a valid array to fill!"); + PRBool rc = PR_TRUE; + // We handle T_U8 specially as a string/Unicode. + // If it is NOT a string, we just fall through and allow the standard + // sequence unpack code process it (just slower!) +#if PY_MAJOR_VERSION <= 2 + if ( array_type == nsXPTType::T_U8 && + (PyString_Check(sequence_ob) || PyUnicode_Check(sequence_ob))) { +#else + if ( array_type == nsXPTType::T_U8 && PyUnicode_Check(sequence_ob)) { +#endif + + PRBool release_seq; + if (PyUnicode_Check(sequence_ob)) { + release_seq = PR_TRUE; +#if PY_MAJOR_VERSION <= 2 + sequence_ob = PyObject_Str(sequence_ob); +#else + sequence_ob = PyUnicode_AsUTF8String(sequence_ob); +#endif + } else + release_seq = PR_FALSE; + if (!sequence_ob) // presumably a memory error, or Unicode encoding error. + return PR_FALSE; +#if PY_MAJOR_VERSION <= 2 + memcpy(pthis, PyString_AS_STRING(sequence_ob), sequence_size); +#else + memcpy(pthis, PyUnicode_AsUTF8(sequence_ob), sequence_size); +#endif + if (release_seq) + { + Py_DECREF(sequence_ob); + } + return PR_TRUE; + } + + for (PRUint32 i=0; rc && i<sequence_size; i++,pthis += array_element_size) { + PyObject *val = PySequence_GetItem(sequence_ob, i); + PyObject *val_use = NULL; + if (val==NULL) + return PR_FALSE; + switch(array_type) { + case nsXPTType::T_I8: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE; + FILL_SIMPLE_POINTER( PRInt8, PyInt_AsLong(val_use) ); + break; + case nsXPTType::T_I16: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE; + FILL_SIMPLE_POINTER( PRInt16, PyInt_AsLong(val_use) ); + break; + case nsXPTType::T_I32: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE; + FILL_SIMPLE_POINTER( PRInt32, PyInt_AsLong(val_use) ); + break; + case nsXPTType::T_I64: + if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE; + FILL_SIMPLE_POINTER( PRInt64, PyLong_AsLongLong(val_use) ); + break; + case nsXPTType::T_U8: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE; + FILL_SIMPLE_POINTER( PRUint8, PyInt_AsLong(val_use) ); + break; + case nsXPTType::T_U16: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE; + FILL_SIMPLE_POINTER( PRUint16, PyInt_AsLong(val_use) ); + break; + case nsXPTType::T_U32: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE; + FILL_SIMPLE_POINTER( PRUint32, PyInt_AsLong(val_use) ); + break; + case nsXPTType::T_U64: + if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE; + FILL_SIMPLE_POINTER( PRUint64, PyLong_AsUnsignedLongLong(val_use) ); + break; + case nsXPTType::T_FLOAT: + if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE + FILL_SIMPLE_POINTER( float, PyFloat_AsDouble(val_use) ); + break; + case nsXPTType::T_DOUBLE: + if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE + FILL_SIMPLE_POINTER( double, PyFloat_AsDouble(val_use) ); + break; + case nsXPTType::T_BOOL: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE + FILL_SIMPLE_POINTER( PRBool, PyInt_AsLong(val_use) ); + break; + case nsXPTType::T_CHAR: +#if PY_MAJOR_VERSION <= 2 + 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 = PyObject_Str(val))==NULL) + BREAK_FALSE; + // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode! + NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!"); + FILL_SIMPLE_POINTER( char, *PyString_AS_STRING(val_use) ); +#else + if (!PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object"); + BREAK_FALSE; + } + FILL_SIMPLE_POINTER( char, *PyUnicode_AsUTF8(val) ); +#endif + break; + + case nsXPTType::T_WCHAR: +#if PY_MAJOR_VERSION <= 2 + if (!PyString_Check(val) && !PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object"); + BREAK_FALSE; + } +#else + if (!PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object"); + BREAK_FALSE; + } +#endif + if ((val_use = PyUnicode_FromObject(val)) == NULL) + BREAK_FALSE; + NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!"); + // Lossy! +#ifndef Py_LIMITED_API + FILL_SIMPLE_POINTER( PRUnichar, *PyUnicode_AS_UNICODE(val_use) ); +#else + FILL_SIMPLE_POINTER( PRUnichar, PyUnicode_ReadChar(val_use, 0) ); +#endif + break; + + case nsXPTType::T_IID: { + nsIID iid; + if (!Py_nsIID::IIDFromPyObject(val, &iid)) + BREAK_FALSE; + nsIID **pp = (nsIID **)pthis; + // If there is an existing IID, free it. + if (*pp) + nsMemory::Free(*pp); + *pp = (nsIID *)nsMemory::Alloc(sizeof(nsIID)); + if (*pp==NULL) { + PyErr_NoMemory(); + BREAK_FALSE; + } + memcpy(*pp, &iid, sizeof(iid)); + break; + } + + // case nsXPTType::T_BSTR: + + case nsXPTType::T_CHAR_STR: { + // If it is an existing string, free it. + char **pp = (char **)pthis; + if (*pp) + nsMemory::Free(*pp); + *pp = nsnull; + + if (val == Py_None) + break; // Remains NULL. +#if PY_MAJOR_VERSION <= 2 + 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 = PyObject_Str(val))==NULL) + BREAK_FALSE; + // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode! + NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!"); + + const char *sz = PyString_AS_STRING(val_use); + int nch = PyString_GET_SIZE(val_use); +#else + if (!PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object"); + BREAK_FALSE; + } + if ((val_use = PyUnicode_AsUTF8String(val))==NULL) + BREAK_FALSE; + + const char *sz = PyBytes_AS_STRING(val_use); + int nch = PyBytes_GET_SIZE(val_use); +#endif + + *pp = (char *)nsMemory::Alloc(nch+1); + if (*pp==NULL) { + PyErr_NoMemory(); + BREAK_FALSE; + } + strncpy(*pp, sz, nch+1); + break; + } + case nsXPTType::T_WCHAR_STR: { + // If it is an existing string, free it. + PRUnichar **pp = (PRUnichar **)pthis; + if (*pp) + nsMemory::Free(*pp); + *pp = nsnull; + if (val == Py_None) + break; // Remains NULL. +#if PY_MAJOR_VERSION <= 2 + 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; + NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!"); +#else + if (!PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object"); + BREAK_FALSE; + } + val_use = val; + Py_INCREF(val_use); +#endif + if (PyUnicode_AsPRUnichar(val_use, pp, NULL) < 0) + BREAK_FALSE; + break; + } + case nsXPTType::T_INTERFACE_IS: // hmm - ignoring the IID can't be good :( + case nsXPTType::T_INTERFACE: { + // 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 :-( + nsISupports *pnew; + if (!Py_nsISupports::InterfaceFromPyObject(val, NS_GET_IID(nsISupports), &pnew, PR_TRUE)) + BREAK_FALSE; + nsISupports **pp = (nsISupports **)pthis; + if (*pp) { + Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires. + (*pp)->Release(); + Py_END_ALLOW_THREADS; + } + *pp = pnew; // ref-count added by InterfaceFromPyObject + break; + } + default: + // try and limp along in this case. + // leave rc TRUE + PyXPCOM_LogWarning("Converting Python object for an array element - The object type (0x%x) is unknown - leaving param alone!\n", array_type); + break; + } + Py_XDECREF(val_use); + Py_DECREF(val); + } + return rc; +} + +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); + return Py_None; + } + if (array_type == nsXPTType::T_U8) +#if PY_MAJOR_VERSION <= 2 + return PyString_FromStringAndSize( (char *)array_ptr, sequence_size ); +#else + return PyBytes_FromStringAndSize( (char *)array_ptr, sequence_size ); +#endif + + PRUint32 array_element_size = GetArrayElementSize(array_type); + PyObject *list_ret = PyList_New(sequence_size); + PRUint8 *pthis = (PRUint8 *)array_ptr; + for (PRUint32 i=0; i<sequence_size; i++,pthis += array_element_size) { + PyObject *val = NULL; + switch(array_type) { + case nsXPTType::T_I8: + val = PyInt_FromLong( *((PRInt8 *)pthis) ); + break; + case nsXPTType::T_I16: + val = PyInt_FromLong( *((PRInt16 *)pthis) ); + break; + case nsXPTType::T_I32: + val = PyInt_FromLong( *((PRInt32 *)pthis) ); + break; + case nsXPTType::T_I64: + val = PyLong_FromLongLong( *((PRInt64 *)pthis) ); + break; + // case nsXPTType::T_U8 - handled above! + case nsXPTType::T_U16: + val = PyInt_FromLong( *((PRUint16 *)pthis) ); + break; + case nsXPTType::T_U32: + val = PyInt_FromLong( *((PRUint32 *)pthis) ); + break; + case nsXPTType::T_U64: + val = PyLong_FromUnsignedLongLong( *((PRUint64 *)pthis) ); + break; + case nsXPTType::T_FLOAT: + val = PyFloat_FromDouble( *((float*)pthis) ); + break; + case nsXPTType::T_DOUBLE: + val = PyFloat_FromDouble( *((double*)pthis) ); + break; + case nsXPTType::T_BOOL: + val = (*((PRBool *)pthis)) ? Py_True : Py_False; + Py_INCREF(val); + break; + case nsXPTType::T_IID: + val = Py_nsIID::PyObjectFromIID( **((nsIID **)pthis) ); + break; + + case nsXPTType::T_CHAR_STR: { + char **pp = (char **)pthis; + if (*pp==NULL) { + Py_INCREF(Py_None); + val = Py_None; + } else +#if PY_MAJOR_VERSION <= 2 + val = PyString_FromString(*pp); +#else + val = PyUnicode_FromString(*pp); +#endif + break; + } + case nsXPTType::T_WCHAR_STR: { + PRUnichar **pp = (PRUnichar **)pthis; + if (*pp==NULL) { + Py_INCREF(Py_None); + val = Py_None; + } else { + val = PyUnicode_FromPRUnichar( *pp, nsCRT::strlen(*pp) ); + } + break; + } + case nsXPTType::T_INTERFACE_IS: + case nsXPTType::T_INTERFACE: { + nsISupports **pp = (nsISupports **)pthis; + // 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: { + char buf[128]; + sprintf(buf, "Unknown XPCOM array type flags (0x%x)", array_type); + PyXPCOM_LogWarning("%s - returning a string object with this message!\n", buf); +#if PY_MAJOR_VERSION <= 2 + val = PyString_FromString(buf); +#else + val = PyUnicode_FromString(buf); +#endif + break; + } + } + if (val==NULL) { + NS_ABORT_IF_FALSE(PyErr_Occurred(), "NULL result in array conversion, but no error set!"); + return NULL; + } + PyList_SET_ITEM(list_ret, i, val); // ref-count consumed. + } + return list_ret; +} + + +// ------------------------------------------------------------------------ +// nsIVariant utilities +// ------------------------------------------------------------------------ +struct BVFTResult { + BVFTResult() {pis = NULL;iid=Py_nsIID_NULL;} + nsISupports *pis; + nsIID iid; +}; + +static PRUint16 BestVariantTypeForPyObject( PyObject *ob, BVFTResult *pdata = NULL) +{ + nsISupports *ps = NULL; + nsIID iid; + // start with some fast concrete checks. + if (ob==Py_None) + return nsIDataType::VTYPE_EMPTY; + if (ob==Py_True || ob == Py_False) + return nsIDataType::VTYPE_BOOL; + if (PyInt_Check(ob)) + return nsIDataType::VTYPE_INT32; + if (PyLong_Check(ob)) + return nsIDataType::VTYPE_INT64; + if (PyFloat_Check(ob)) + return nsIDataType::VTYPE_DOUBLE; +#if PY_MAJOR_VERSION <= 2 + if (PyString_Check(ob)) + return nsIDataType::VTYPE_STRING_SIZE_IS; +#endif + if (PyUnicode_Check(ob)) + return nsIDataType::VTYPE_WSTRING_SIZE_IS; + if (PyTuple_Check(ob) || PyList_Check(ob)) { + if (PySequence_Length(ob)) + return nsIDataType::VTYPE_ARRAY; + return nsIDataType::VTYPE_EMPTY_ARRAY; + } + // Now do expensive or abstract checks. + if (Py_nsISupports::InterfaceFromPyObject(ob, NS_GET_IID(nsISupports), &ps, PR_TRUE)) { + if (pdata) { + pdata->pis = ps; + pdata->iid = NS_GET_IID(nsISupports); + } else + ps->Release(); + return nsIDataType::VTYPE_INTERFACE_IS; + } else + PyErr_Clear(); + if (Py_nsIID::IIDFromPyObject(ob, &iid)) { + if (pdata) + pdata->iid = iid; + return nsIDataType::VTYPE_ID; + } else + PyErr_Clear(); + if (PySequence_Check(ob)) { + if (PySequence_Length(ob)) + return nsIDataType::VTYPE_ARRAY; + return nsIDataType::VTYPE_EMPTY_ARRAY; + } + return (PRUint16)-1; +} + +nsresult PyObject_AsVariant( PyObject *ob, nsIVariant **aRet) +{ + 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; + PRUint16 dt = BestVariantTypeForPyObject(ob, &cvt_result); + switch (dt) { + case nsIDataType::VTYPE_BOOL: + nr = v->SetAsBool(ob==Py_True); + break; + case nsIDataType::VTYPE_INT32: + nr = v->SetAsInt32(PyInt_AsLong(ob)); + break; + case nsIDataType::VTYPE_INT64: + nr = v->SetAsInt64(PyLong_AsLongLong(ob)); + break; + case nsIDataType::VTYPE_DOUBLE: + nr = v->SetAsDouble(PyFloat_AsDouble(ob)); + break; + case nsIDataType::VTYPE_STRING_SIZE_IS: + { +#if PY_MAJOR_VERSION <= 2 + nr = v->SetAsStringWithSize(PyString_Size(ob), PyString_AsString(ob)); +#else + Py_ssize_t cb = 0; + const char *psz = PyUnicode_AsUTF8AndSize(ob, &cb); + nr = v->SetAsStringWithSize(cb, psz); +#endif + break; + } + case nsIDataType::VTYPE_WSTRING_SIZE_IS: +#if PY_VERSION_HEX >= 0x03030000 + if (PyUnicode_GetLength(ob) == 0) { +#else + if (PyUnicode_GetSize(ob) == 0) { +#endif + nr = v->SetAsWStringWithSize(0, (PRUnichar*)NULL); + } + else { + PRUint32 nch; + PRUnichar *p; + if (PyUnicode_AsPRUnichar(ob, &p, &nch) < 0) { + PyXPCOM_LogWarning("Failed to convert object to unicode", PyXPCOM_ObTypeName(ob)); + nr = NS_ERROR_UNEXPECTED; + break; + } + nr = v->SetAsWStringWithSize(nch, p); + nsMemory::Free(p); + } + break; + case nsIDataType::VTYPE_INTERFACE_IS: + { + nsISupports *ps = cvt_result.pis; + nr = v->SetAsInterface(cvt_result.iid, ps); + if (ps) { + Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires. + ps->Release(); + Py_END_ALLOW_THREADS; + } + break; + } + case nsIDataType::VTYPE_ID: + nr = v->SetAsID(cvt_result.iid); + break; + case nsIDataType::VTYPE_ARRAY: + { + int seq_length = PySequence_Length(ob); + NS_ABORT_IF_FALSE(seq_length!=0, "VTYPE_ARRAY assumes at least one element!"); + PyObject *first = PySequence_GetItem(ob, 0); + if (!first) break; + int array_type = BestVariantTypeForPyObject(first); + Py_DECREF(first); + // Arrays can't handle all types. This means we lost embedded NULLs. + // This should really be fixed in XPCOM. + if (array_type == nsIDataType::VTYPE_STRING_SIZE_IS) array_type = nsIDataType::VTYPE_CHAR_STR; + if (array_type == nsIDataType::VTYPE_WSTRING_SIZE_IS) array_type = nsIDataType::VTYPE_WCHAR_STR; + PRUint32 element_size = GetArrayElementSize(array_type); + int cb_buffer_pointer = seq_length * element_size; + void *buffer_pointer; + if ((buffer_pointer = (void *)nsMemory::Alloc(cb_buffer_pointer)) == nsnull) { + 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, nsnull)) { + nr = v->SetAsArray(array_type, &NS_GET_IID(nsISupports), seq_length, buffer_pointer); + FreeSingleArray(buffer_pointer, seq_length, array_type); + } else + nr = NS_ERROR_UNEXPECTED; + nsMemory::Free(buffer_pointer); + break; + } + case nsIDataType::VTYPE_EMPTY: + nr = v->SetAsEmpty(); + break; + case nsIDataType::VTYPE_EMPTY_ARRAY: + nr = v->SetAsEmptyArray(); + break; + case (PRUint16)-1: + PyXPCOM_LogWarning("Objects of type '%s' can not be converted to an nsIVariant", PyXPCOM_ObTypeName(ob)); + nr = NS_ERROR_UNEXPECTED; + default: + NS_ABORT_IF_FALSE(0, "BestVariantTypeForPyObject() returned a variant type not handled here!"); + PyXPCOM_LogWarning("Objects of type '%s' can not be converted to an nsIVariant", PyXPCOM_ObTypeName(ob)); + nr = NS_ERROR_UNEXPECTED; + } + if (NS_FAILED(nr)) + return nr; + return v->QueryInterface(NS_GET_IID(nsIVariant), (void **)aRet); +} + +static PyObject *MyBool_FromBool(PRBool v) +{ + PyObject *ret = v ? Py_True : Py_False; + Py_INCREF(ret); + return ret; +} + +#define GET_FROM_V(Type, FuncGet, FuncConvert) { \ + Type t; \ + if (NS_FAILED(nr = FuncGet( &t ))) goto done;\ + ret = FuncConvert(t);\ + break; \ +} + +PyObject *PyObject_FromVariantArray( Py_nsISupports *parent, nsIVariant *v) +{ + nsresult nr; + NS_PRECONDITION(v, "NULL variant!"); + if (!v) + return PyXPCOM_BuildPyException(NS_ERROR_INVALID_POINTER); +#ifdef NS_DEBUG + PRUint16 dt; + nr = v->GetDataType(&dt); + NS_ABORT_IF_FALSE(dt == nsIDataType::VTYPE_ARRAY, "expected an array variant"); +#endif + nsIID iid; + void *p; + PRUint16 type; + PRUint32 count; + nr = v->GetAsArray(&type, &iid, &count, &p); + if (NS_FAILED(nr)) return PyXPCOM_BuildPyException(nr); + PyObject *ret = UnpackSingleArray(parent, p, count, (PRUint8)type, &iid); + FreeSingleArray(p, count, (PRUint8)type); + nsMemory::Free(p); + return ret; +} + +PyObject *PyObject_FromVariant( Py_nsISupports *parent, nsIVariant *v) +{ + if (!v) { + Py_INCREF(Py_None); + return Py_None; + } + PRUint16 dt; + nsresult nr; + PyObject *ret = NULL; + nr = v->GetDataType(&dt); + if (NS_FAILED(nr)) goto done; + switch (dt) { + case nsIDataType::VTYPE_VOID: + case nsIDataType::VTYPE_EMPTY: + case nsIDataType::VTYPE_EMPTY_ARRAY: + ret = Py_None; + Py_INCREF(Py_None); + break; + case nsIDataType::VTYPE_ARRAY: + ret = PyObject_FromVariantArray(parent, v); + break; + case nsIDataType::VTYPE_INT8: + case nsIDataType::VTYPE_INT16: + case nsIDataType::VTYPE_INT32: + GET_FROM_V(PRInt32, v->GetAsInt32, PyInt_FromLong); + case nsIDataType::VTYPE_UINT8: + case nsIDataType::VTYPE_UINT16: + case nsIDataType::VTYPE_UINT32: + GET_FROM_V(PRUint32, v->GetAsUint32, PyLong_FromUnsignedLong); + case nsIDataType::VTYPE_INT64: + GET_FROM_V(PRInt64, v->GetAsInt64, PyLong_FromLongLong); + case nsIDataType::VTYPE_UINT64: + GET_FROM_V(PRUint64, v->GetAsUint64, PyLong_FromUnsignedLongLong); + case nsIDataType::VTYPE_FLOAT: + case nsIDataType::VTYPE_DOUBLE: + GET_FROM_V(double, v->GetAsDouble, PyFloat_FromDouble); + case nsIDataType::VTYPE_BOOL: + GET_FROM_V(PRBool, v->GetAsBool, MyBool_FromBool); + default: + PyXPCOM_LogWarning("Converting variant to Python object - variant type '%d' unknown - using string.\n", dt); + // Fall through to the string case + case nsIDataType::VTYPE_CHAR: + case nsIDataType::VTYPE_CHAR_STR: + case nsIDataType::VTYPE_STRING_SIZE_IS: + case nsIDataType::VTYPE_CSTRING: { + nsCAutoString s; + if (NS_FAILED(nr=v->GetAsACString(s))) goto done; + ret = PyObject_FromNSString(s); + break; + } + case nsIDataType::VTYPE_WCHAR: + case nsIDataType::VTYPE_DOMSTRING: + case nsIDataType::VTYPE_WSTRING_SIZE_IS: + case nsIDataType::VTYPE_ASTRING: { + nsAutoString s; + if (NS_FAILED(nr=v->GetAsAString(s))) goto done; + ret = PyObject_FromNSString(s); + break; + } + case nsIDataType::VTYPE_ID: + GET_FROM_V(nsIID, v->GetAsID, Py_nsIID::PyObjectFromIID); + 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: { + nsCOMPtr<nsISupports> p; + nsIID *iid; + 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 + } + } +done: + if (NS_FAILED(nr)) { + NS_ABORT_IF_FALSE(ret==NULL, "Have an error, but also a return val!"); + PyXPCOM_BuildPyException(nr); + } + return ret; +} + +// ------------------------------------------------------------------------ +// TypeDescriptor helper class +// ------------------------------------------------------------------------ +class PythonTypeDescriptor { +public: + PythonTypeDescriptor() { + param_flags = type_flags = argnum = argnum2 = 0; + extra = NULL; + is_auto_out = PR_FALSE; + is_auto_in = PR_FALSE; + have_set_auto = PR_FALSE; + } + ~PythonTypeDescriptor() { + Py_XDECREF(extra); + } + PRUint8 param_flags; + PRUint8 type_flags; + PRUint8 argnum; /* used for iid_is and size_is */ + PRUint8 argnum2; /* used for length_is */ + PyObject *extra; // The IID object, or the type of the array. + // Extra items to help our processing. + // Is this auto-filled by some other "in" param? + PRBool is_auto_in; + // Is this auto-filled by some other "out" param? + PRBool is_auto_out; + // If is_auto_out, have I already filled it? Used when multiple + // params share a size_is fields - first time sets it, subsequent + // time check it. + PRBool have_set_auto; +}; + +static int ProcessPythonTypeDescriptors(PythonTypeDescriptor *pdescs, int num) +{ + // Loop over the array, checking all the params marked as having an arg. + // If these args nominate another arg as the size_is param, then + // we reset the size_is param to _not_ requiring an arg. + int i; + for (i=0;i<num;i++) { + PythonTypeDescriptor &ptd = pdescs[i]; + // Can't use XPT_TDP_TAG() - it uses a ".flags" reference in the macro. + switch (ptd.type_flags & XPT_TDP_TAGMASK) { + case nsXPTType::T_ARRAY: + NS_ABORT_IF_FALSE(ptd.argnum < num, "Bad dependent index"); + if (ptd.argnum2 < num) { + if (XPT_PD_IS_IN(ptd.param_flags)) + pdescs[ptd.argnum2].is_auto_in = PR_TRUE; + if (XPT_PD_IS_OUT(ptd.param_flags)) + pdescs[ptd.argnum2].is_auto_out = PR_TRUE; + } + break; + case nsXPTType::T_PSTRING_SIZE_IS: + case nsXPTType::T_PWSTRING_SIZE_IS: + NS_ABORT_IF_FALSE(ptd.argnum < num, "Bad dependent index"); + if (ptd.argnum < num) { + if (XPT_PD_IS_IN(ptd.param_flags)) + pdescs[ptd.argnum].is_auto_in = PR_TRUE; + if (XPT_PD_IS_OUT(ptd.param_flags)) + pdescs[ptd.argnum].is_auto_out = PR_TRUE; + } + break; + default: + break; + } + } + int total_params_needed = 0; + for (i=0;i<num;i++) + if (XPT_PD_IS_IN(pdescs[i].param_flags) && !pdescs[i].is_auto_in && !XPT_PD_IS_DIPPER(pdescs[i].param_flags)) + total_params_needed++; + + return total_params_needed; +} + +/************************************************************************* +************************************************************************** + +Helpers when CALLING interfaces. + +************************************************************************** +*************************************************************************/ + +PyXPCOM_InterfaceVariantHelper::PyXPCOM_InterfaceVariantHelper(Py_nsISupports *parent, int methodindex) +{ + m_var_array=nsnull; + m_buffer_array=nsnull; + m_pyparams=nsnull; + m_typedescs = nsnull; + m_python_type_desc_array = nsnull; + m_num_array = 0; + m_methodindex = methodindex; + // 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) { + nsXPTCVariant &ns_v = m_var_array[i]; + if (ns_v.IsValInterface()) { + if (ns_v.val.p) { + Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires. + ((nsISupports *)ns_v.val.p)->Release(); + Py_END_ALLOW_THREADS; + } + } + if (ns_v.IsValDOMString() && ns_v.val.p) { + delete (const nsAString *)ns_v.val.p; + } + if (ns_v.IsValCString() && ns_v.val.p) { + delete (const nsACString *)ns_v.val.p; + } + if (ns_v.IsValUTF8String() && ns_v.val.p) { + delete (const nsACString *)ns_v.val.p; + } + if (ns_v.IsValArray()) { + nsXPTCVariant &ns_v = m_var_array[i]; + if (ns_v.val.p) { + PRUint8 array_type = (PRUint8)PyInt_AsLong(m_python_type_desc_array[i].extra); + PRUint32 seq_size = GetSizeIs(i, PR_FALSE); + FreeSingleArray(ns_v.val.p, seq_size, array_type); + } + } + // IsOwned must be the last check of the loop, as + // this frees the underlying data used above (eg, by the array free process) + if (ns_v.IsValAllocated() && !ns_v.IsValInterface() && !ns_v.IsValDOMString()) { + NS_ABORT_IF_FALSE(ns_v.IsPtrData(), "expecting a pointer to free"); + nsMemory::Free(ns_v.val.p); + } + } + if (m_buffer_array && m_buffer_array[i]) + nsMemory::Free(m_buffer_array[i]); + } + delete [] m_python_type_desc_array; + delete [] m_buffer_array; + delete [] m_var_array; +} + +PRBool PyXPCOM_InterfaceVariantHelper::Init(PyObject *obParams) +{ + PRBool ok = PR_FALSE; + int i; + int total_params_needed = 0; + if (!PySequence_Check(obParams) || PySequence_Length(obParams)!=2) { + PyErr_Format(PyExc_TypeError, "Param descriptors must be a sequence of exactly length 2"); + return PR_FALSE; + } + PyObject *typedescs = PySequence_GetItem(obParams, 0); + if (typedescs==NULL) + return PR_FALSE; + // NOTE: The length of the typedescs may be different than the + // args actually passed. The typedescs always include all + // hidden params (such as "size_is"), while the actual + // args never include this. + m_num_array = PySequence_Length(typedescs); + if (PyErr_Occurred()) goto done; + + m_pyparams = PySequence_GetItem(obParams, 1); + if (m_pyparams==NULL) goto done; + + m_python_type_desc_array = new PythonTypeDescriptor[m_num_array]; + if (!m_python_type_desc_array) goto done; + + // Pull apart the type descs and stash them. + for (i=0;i<m_num_array;i++) { + PyObject *desc_object = PySequence_GetItem(typedescs, i); + if (desc_object==NULL) + goto done; + + // Pull apart the typedesc tuple back into a structure we can work with. + PythonTypeDescriptor &ptd = m_python_type_desc_array[i]; + PRBool this_ok = PyArg_ParseTuple(desc_object, "bbbbO:type_desc", + &ptd.param_flags, &ptd.type_flags, &ptd.argnum, &ptd.argnum2, &ptd.extra); + Py_DECREF(desc_object); + if (!this_ok) goto done; + Py_INCREF(ptd.extra); + + } + total_params_needed = ProcessPythonTypeDescriptors(m_python_type_desc_array, m_num_array); + // OK - check we got the number of args we expected. + // If not, its really an internal error rather than the user. + if (PySequence_Length(m_pyparams) != total_params_needed) { +#ifdef VBOX + PyErr_Format(PyExc_ValueError, "The type descriptions indicate %d args are needed, but %ld were provided", + total_params_needed, (long)PySequence_Length(m_pyparams)); +#else + PyErr_Format(PyExc_ValueError, "The type descriptions indicate %d args are needed, but %d were provided", + total_params_needed, PySequence_Length(m_pyparams)); +#endif + goto done; + } + + // Init the other arrays. + m_var_array = new nsXPTCVariant[m_num_array]; + if (!m_var_array) goto done; + /*memset(m_var_array, 0, m_num_array * sizeof(m_var_array[0])); - VBox not needed */ + + m_buffer_array = new void *[m_num_array]; + if (!m_buffer_array) goto done; + memset(m_buffer_array, 0, m_num_array * sizeof(m_buffer_array[0])); + + ok = PR_TRUE; +done: + if (!ok && !PyErr_Occurred()) + PyErr_NoMemory(); + + Py_XDECREF(typedescs); + return ok; +} + + +PRBool PyXPCOM_InterfaceVariantHelper::FillArray() +{ + int param_index = 0; + int i; + for (i=0;i<m_num_array;i++) { + PythonTypeDescriptor &ptd = m_python_type_desc_array[i]; + // stash the type_flags into the variant, and remember how many extra bits of info we have. + m_var_array[i].type = ptd.type_flags; + if (XPT_PD_IS_IN(ptd.param_flags) && !ptd.is_auto_in && !XPT_PD_IS_DIPPER(ptd.param_flags)) { + if (!FillInVariant(ptd, i, param_index)) + return PR_FALSE; + param_index++; + } + if ((XPT_PD_IS_OUT(ptd.param_flags) && !ptd.is_auto_out) || XPT_PD_IS_DIPPER(ptd.param_flags)) { + if (!PrepareOutVariant(ptd, i)) + return PR_FALSE; + } + } + // There may be out "size_is" params we havent touched yet + // (ie, as the param itself is marked "out", we never got to + // touch the associated "size_is". + // Final loop to handle this. + for (i=0;i<m_num_array;i++) { + PythonTypeDescriptor &ptd = m_python_type_desc_array[i]; + if (ptd.is_auto_out && !ptd.have_set_auto) { + // Call PrepareOutVariant to ensure buffers etc setup. + if (!PrepareOutVariant(ptd, i)) + return PR_FALSE; + } + } + return PR_TRUE; +} + + +PRBool PyXPCOM_InterfaceVariantHelper::SetSizeIs( int var_index, PRBool is_arg1, PRUint32 new_size) +{ + NS_ABORT_IF_FALSE(var_index < m_num_array, "var_index param is invalid"); + PRUint8 argnum = is_arg1 ? + m_python_type_desc_array[var_index].argnum : + m_python_type_desc_array[var_index].argnum2; + NS_ABORT_IF_FALSE(argnum < m_num_array, "size_is param is invalid"); + PythonTypeDescriptor &td_size = m_python_type_desc_array[argnum]; + NS_ABORT_IF_FALSE(td_size.is_auto_in || td_size.is_auto_out, "Setting size_is, but param is not marked as auto!"); + NS_ABORT_IF_FALSE( (td_size.type_flags & XPT_TDP_TAGMASK) == nsXPTType::T_U32, "size param must be Uint32"); + nsXPTCVariant &ns_v = m_var_array[argnum]; + + if (!td_size.have_set_auto) { + ns_v.type = td_size.type_flags; + ns_v.val.u32 = new_size; + // In case it is "out", setup the necessary pointers. + PrepareOutVariant(td_size, argnum); + td_size.have_set_auto = PR_TRUE; + } else { + if (ns_v.val.u32 != new_size) { + PyErr_Format(PyExc_ValueError, "Array lengths inconsistent; array size previously set to %d, but second array is of size %d", ns_v.val.u32, new_size); + return PR_FALSE; + } + } + return PR_TRUE; +} + +PRUint32 PyXPCOM_InterfaceVariantHelper::GetSizeIs( int var_index, PRBool is_arg1) +{ + NS_ABORT_IF_FALSE(var_index < m_num_array, "var_index param is invalid"); + PRUint8 argnum = is_arg1 ? + m_python_type_desc_array[var_index].argnum : + m_python_type_desc_array[var_index].argnum2; + NS_ABORT_IF_FALSE(argnum < m_num_array, "size_is param is invalid"); + NS_ABORT_IF_FALSE( (m_python_type_desc_array[argnum].type_flags & XPT_TDP_TAGMASK) == nsXPTType::T_U32, "size param must be Uint32"); + PRBool is_out = XPT_PD_IS_OUT(m_python_type_desc_array[argnum].param_flags); + nsXPTCVariant &ns_v = m_var_array[argnum]; + return is_out ? *((PRUint32 *)ns_v.ptr) : ns_v.val.u32; +} + +#define MAKE_VALUE_BUFFER(size) \ + if ((this_buffer_pointer = (void *)nsMemory::Alloc((size))) == nsnull) { \ + PyErr_NoMemory(); \ + BREAK_FALSE; \ + } + +PRBool PyXPCOM_InterfaceVariantHelper::FillInVariant(const PythonTypeDescriptor &td, int value_index, int param_index) +{ + PRBool rc = PR_TRUE; + // Get a reference to the variant we are filling for convenience. + nsXPTCVariant &ns_v = m_var_array[value_index]; + NS_ABORT_IF_FALSE(ns_v.type == td.type_flags, "Expecting variant all setup for us"); + + // We used to avoid passing internal buffers to PyString etc objects + // for 2 reasons: paranoia (so incorrect external components couldn't break + // Python) and simplicity (in vs in-out issues, etc) + // However, at least one C++ implemented component (nsITimelineService) + // uses a "char *", and keys on the address (assuming that the same + // *pointer* is passed rather than value. Therefore, we have a special case + // - T_CHAR_STR that is "in" gets the Python string pointer passed. + void *&this_buffer_pointer = m_buffer_array[value_index]; // Freed at object destruction with PyMem_Free() + NS_ABORT_IF_FALSE(this_buffer_pointer==nsnull, "We appear to already have a buffer"); + int cb_this_buffer_pointer = 0; + if (XPT_PD_IS_IN(td.param_flags)) { + NS_ABORT_IF_FALSE(!td.is_auto_in, "Param is 'auto-in', but we are filling it normally!"); + PyObject *val_use = NULL; // a temp object converters can use, and will be DECREF'd + PyObject *val = PySequence_GetItem(m_pyparams, param_index); + NS_WARN_IF_FALSE(val, "Have an 'in' param, but no Python value!"); + if (val==NULL) { + PyErr_Format(PyExc_ValueError, "Param %d is marked as 'in', but no value was given", value_index); + return PR_FALSE; + } + switch (XPT_TDP_TAG(ns_v.type)) { + case nsXPTType::T_I8: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE + ns_v.val.i8 = (PRInt8)PyInt_AsLong(val_use); + break; + case nsXPTType::T_I16: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE + ns_v.val.i16 = (PRInt16)PyInt_AsLong(val_use); + break; + case nsXPTType::T_I32: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE + ns_v.val.i32 = (PRInt32)PyInt_AsLong(val_use); + break; + case nsXPTType::T_I64: + if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE + ns_v.val.i64 = (PRInt64)PyLong_AsLongLong(val_use); + break; + case nsXPTType::T_U8: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE + ns_v.val.u8 = (PRUint8)PyInt_AsLong(val_use); + break; + case nsXPTType::T_U16: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE + ns_v.val.u16 = (PRUint16)PyInt_AsLong(val_use); + break; + case nsXPTType::T_U32: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE + ns_v.val.u32 = (PRUint32)PyInt_AsLong(val_use); + break; + case nsXPTType::T_U64: + if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE + ns_v.val.u64 = (PRUint64)PyLong_AsUnsignedLongLong(val_use); + break; + case nsXPTType::T_FLOAT: + if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE + ns_v.val.f = (float)PyFloat_AsDouble(val_use); + break; + case nsXPTType::T_DOUBLE: + if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE + ns_v.val.d = PyFloat_AsDouble(val_use); + break; + case nsXPTType::T_BOOL: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE + ns_v.val.b = (PRBool)PyInt_AsLong(val_use); + break; + case nsXPTType::T_CHAR:{ +#if PY_MAJOR_VERSION <= 2 + 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 = PyObject_Str(val))==NULL) + BREAK_FALSE; + // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode! + NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!"); + if (PyString_GET_SIZE(val_use) != 1) { + PyErr_SetString(PyExc_ValueError, "Must specify a one character string for a character"); + BREAK_FALSE; + } + + ns_v.val.c = *PyString_AS_STRING(val_use); +#else + if (!PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object"); + BREAK_FALSE; + } + if (PyUnicode_GET_SIZE(val) != 1) { + PyErr_SetString(PyExc_ValueError, "Must specify a one character string for a character"); + BREAK_FALSE; + } + +# ifndef Py_LIMITED_API + ns_v.val.c = *PyUnicode_AS_UNICODE(val_use); +# else + ns_v.val.c = PyUnicode_ReadChar(val_use, 0); +# endif +#endif + break; + } + + case nsXPTType::T_WCHAR: { +#if PY_MAJOR_VERSION <= 2 + if (!PyString_Check(val) && !PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object"); + BREAK_FALSE; + } +#else + if (!PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object"); + BREAK_FALSE; + } +#endif + if ((val_use = PyUnicode_FromObject(val))==NULL) + BREAK_FALSE; + // Sanity check should PyUnicode_FromObject() 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) != 1) { + PyErr_SetString(PyExc_ValueError, "Must specify a one character string for a character"); + BREAK_FALSE; + } + // Lossy! +#ifndef Py_LIMITED_API + ns_v.val.wc = *PyUnicode_AS_UNICODE(val_use); +#else + ns_v.val.wc = PyUnicode_ReadChar(val_use, 0); +#endif + break; + } + // case nsXPTType::T_VOID: /* fall through */ + case nsXPTType::T_IID: + nsIID iid; + MAKE_VALUE_BUFFER(sizeof(nsIID)); + if (!Py_nsIID::IIDFromPyObject(val, &iid)) + BREAK_FALSE; + memcpy(this_buffer_pointer, &iid, sizeof(iid)); + ns_v.val.p = this_buffer_pointer; + break; + case nsXPTType::T_ASTRING: + case nsXPTType::T_DOMSTRING: { + 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: + case nsXPTType::T_UTF8STRING: { + PRBool bIsUTF8 = XPT_TDP_TAG(ns_v.type) == nsXPTType::T_UTF8STRING; + if (val==Py_None) { + ns_v.val.p = new nsCString(); + } else { +#if PY_MAJOR_VERSION <= 2 + if (PyString_Check(val)) { + // strings are assumed to already be UTF8 encoded. + val_use = val; + Py_INCREF(val); + } + else +#endif + if (PyUnicode_Check(val)) { + // Unicode objects are encoded by us. + if (bIsUTF8) + val_use = PyUnicode_AsUTF8String(val); + else +#if PY_MAJOR_VERSION <= 2 + val_use = PyObject_Str(val); +#else + val_use = PyUnicode_AsUTF8String(val); +#endif + } else { +#if PY_MAJOR_VERSION <= 2 + PyErr_SetString(PyExc_TypeError, "UTF8 parameters must be string or Unicode objects"); +#else + PyErr_SetString(PyExc_TypeError, "UTF8 parameters must be unicode objects"); +#endif + BREAK_FALSE; + } + if (!val_use) + BREAK_FALSE; +#if PY_MAJOR_VERSION <= 2 + ns_v.val.p = new nsCString(PyString_AS_STRING(val_use), + PyString_GET_SIZE(val_use)); +#else + ns_v.val.p = new nsCString(PyBytes_AS_STRING(val_use), + PyBytes_GET_SIZE(val_use)); +#endif + } + + if (!ns_v.val.p) { + PyErr_NoMemory(); + BREAK_FALSE; + } + // We created it - flag as such for cleanup. + ns_v.flags |= bIsUTF8 ? nsXPTCVariant::VAL_IS_UTF8STR : nsXPTCVariant::VAL_IS_CSTR; + break; + } + case nsXPTType::T_CHAR_STR: { + if (val==Py_None) { + ns_v.val.p = nsnull; + break; + } +#if PY_MAJOR_VERSION <= 2 + // If an "in" char *, and we have a PyString, then pass the + // pointer (hoping everyone else plays by the rules too. + if (!XPT_PD_IS_OUT(td.param_flags) && PyString_Check(val)) { + ns_v.val.p = (void *)PyString_AS_STRING(val); + break; + } + + 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 = PyObject_Str(val))==NULL) + BREAK_FALSE; + // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode! + NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!"); + + cb_this_buffer_pointer = PyString_GET_SIZE(val_use)+1; + MAKE_VALUE_BUFFER(cb_this_buffer_pointer); + memcpy(this_buffer_pointer, PyString_AS_STRING(val_use), cb_this_buffer_pointer); +#else + + if (!PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object"); + BREAK_FALSE; + } + if ((val_use = PyUnicode_AsUTF8String(val))==NULL) + BREAK_FALSE; + + cb_this_buffer_pointer = PyBytes_GET_SIZE(val_use)+1; + MAKE_VALUE_BUFFER(cb_this_buffer_pointer); + memcpy(this_buffer_pointer, PyBytes_AS_STRING(val_use), cb_this_buffer_pointer); +#endif + ns_v.val.p = this_buffer_pointer; + break; + } + + case nsXPTType::T_WCHAR_STR: { + if (val==Py_None) { + ns_v.val.p = nsnull; + break; + } +#if PY_MAJOR_VERSION <= 2 + 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; + NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!"); +#else + if (!PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object"); + BREAK_FALSE; + } + val_use = val; + Py_INCREF(val_use); +#endif + PRUnichar *sv; + PRUint32 nch; + if (PyUnicode_AsPRUnichar(val_use, &sv, &nch) < 0) + BREAK_FALSE; + cb_this_buffer_pointer = (nch + 1) * sizeof(PRUnichar); + this_buffer_pointer = sv; + ns_v.val.p = this_buffer_pointer; + break; + } + case nsXPTType::T_INTERFACE: { + nsIID iid; + if (!Py_nsIID::IIDFromPyObject(td.extra, &iid)) + BREAK_FALSE; + if (!Py_nsISupports::InterfaceFromPyObject( + val, + iid, + (nsISupports **)&ns_v.val.p, + PR_TRUE)) + BREAK_FALSE; + // We have added a reference - flag as such for cleanup. + ns_v.flags |= nsXPTCVariant::VAL_IS_IFACE; + break; + } + case nsXPTType::T_INTERFACE_IS: { + nsIID iid; + nsXPTCVariant &ns_viid = m_var_array[td.argnum]; + NS_WARN_IF_FALSE(XPT_TDP_TAG(ns_viid.type)==nsXPTType::T_IID, "The INTERFACE_IS iid describer isnt an IID!"); + // 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. + if (XPT_TDP_TAG(ns_viid.type)==nsXPTType::T_IID && + XPT_PD_IS_IN(ns_viid.type)) { + nsIID *piid = (nsIID *)ns_viid.val.p; + if (piid==NULL) + // Also serious, but like below, not our fault! + iid = NS_GET_IID(nsISupports); + else + iid = *piid; + } else + // Use NULL IID to avoid a QI in this case. + iid = Py_nsIID_NULL; + if (!Py_nsISupports::InterfaceFromPyObject( + val, + iid, + (nsISupports **)&ns_v.val.p, + PR_TRUE)) + BREAK_FALSE; + // We have added a reference - flag as such for cleanup. + ns_v.flags |= nsXPTCVariant::VAL_IS_IFACE; + break; + } + case nsXPTType::T_PSTRING_SIZE_IS: { + if (val==Py_None) { + ns_v.val.p = nsnull; + break; + } +#if PY_MAJOR_VERSION <= 2 + 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 = PyObject_Str(val))==NULL) + BREAK_FALSE; + // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode! + NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!"); + + cb_this_buffer_pointer = PyString_GET_SIZE(val_use); + MAKE_VALUE_BUFFER(cb_this_buffer_pointer); + memcpy(this_buffer_pointer, PyString_AS_STRING(val_use), cb_this_buffer_pointer); +#else + if (!PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object"); + BREAK_FALSE; + } + if ((val_use = PyUnicode_AsUTF8String(val))==NULL) + BREAK_FALSE; + + cb_this_buffer_pointer = PyBytes_GET_SIZE(val_use); + MAKE_VALUE_BUFFER(cb_this_buffer_pointer); + memcpy(this_buffer_pointer, PyBytes_AS_STRING(val_use), cb_this_buffer_pointer); +#endif + ns_v.val.p = this_buffer_pointer; + rc = SetSizeIs(value_index, PR_TRUE, cb_this_buffer_pointer); + break; + } + + case nsXPTType::T_PWSTRING_SIZE_IS: { + if (val==Py_None) { + ns_v.val.p = nsnull; + break; + } +#if PY_MAJOR_VERSION <= 2 + 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), "PyObject_Unicode didnt return a unicode object!"); +#else + if (!PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object"); + BREAK_FALSE; + } + val_use = val; + Py_INCREF(val_use); +#endif + PRUnichar *sv; + PRUint32 nch; + if (PyUnicode_AsPRUnichar(val_use, &sv, &nch) < 0) + BREAK_FALSE; + cb_this_buffer_pointer = (nch + 1) * sizeof(PRUnichar); + this_buffer_pointer = sv; + ns_v.val.p = this_buffer_pointer; + rc = SetSizeIs(value_index, PR_TRUE, nch); + break; + } + case nsXPTType::T_ARRAY: { + if (val==Py_None) { + ns_v.val.p = nsnull; + break; + } + if (!PyInt_Check(td.extra)) { + PyErr_SetString(PyExc_TypeError, "The array info is not valid"); + BREAK_FALSE; + } + if (!PySequence_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a sequence"); + BREAK_FALSE; + } + int array_type = PyInt_AsLong(td.extra); + PRUint32 element_size = GetArrayElementSize(array_type); + int seq_length = PySequence_Length(val); + cb_this_buffer_pointer = seq_length * element_size; + if (cb_this_buffer_pointer==0) + // prevent assertions allocing zero bytes. Can't use NULL. + 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, nsnull); + if (!rc) break; + rc = SetSizeIs(value_index, PR_FALSE, seq_length); + if (!rc) break; + ns_v.flags |= nsXPTCVariant::VAL_IS_ARRAY; + ns_v.val.p = this_buffer_pointer; + break; + } + default: + PyErr_Format(PyExc_TypeError, "The object type (0x%x) is unknown", XPT_TDP_TAG(ns_v.type)); + rc = PR_FALSE; + break; + } + Py_DECREF(val); // Cant be NULL! + Py_XDECREF(val_use); + } + return rc && !PyErr_Occurred(); +} + +PRBool PyXPCOM_InterfaceVariantHelper::PrepareOutVariant(const PythonTypeDescriptor &td, int value_index) +{ + PRBool rc = PR_TRUE; + nsXPTCVariant &ns_v = m_var_array[value_index]; + void *&this_buffer_pointer = m_buffer_array[value_index]; // Freed at object destruction with PyMem_Free() + // Do the out param thang... + if (XPT_PD_IS_OUT(td.param_flags) || XPT_PD_IS_DIPPER(td.param_flags)) { + NS_ABORT_IF_FALSE(ns_v.ptr == NULL, "already have a pointer!"); + ns_v.ptr = &ns_v; + ns_v.flags |= nsXPTCVariant::PTR_IS_DATA; + + // Special flags based on the data type + switch (XPT_TDP_TAG(ns_v.type)) { + case nsXPTType::T_I8: + case nsXPTType::T_I16: + case nsXPTType::T_I32: + case nsXPTType::T_I64: + case nsXPTType::T_U8: + case nsXPTType::T_U16: + case nsXPTType::T_U32: + case nsXPTType::T_U64: + case nsXPTType::T_FLOAT: + case nsXPTType::T_DOUBLE: + case nsXPTType::T_BOOL: + case nsXPTType::T_CHAR: + case nsXPTType::T_WCHAR: + case nsXPTType::T_VOID: + break; + + case nsXPTType::T_INTERFACE: + case nsXPTType::T_INTERFACE_IS: + NS_ABORT_IF_FALSE(this_buffer_pointer==NULL, "Can't have an interface and a buffer pointer!"); + ns_v.flags |= nsXPTCVariant::VAL_IS_IFACE; + ns_v.flags |= nsXPTCVariant::VAL_IS_ALLOCD; + break; + case nsXPTType::T_ARRAY: + ns_v.flags |= nsXPTCVariant::VAL_IS_ARRAY; + ns_v.flags |= nsXPTCVariant::VAL_IS_ALLOCD; + // Even if ns_val.p already setup as part of "in" processing, + // we need to ensure setup for out. + NS_ABORT_IF_FALSE(ns_v.val.p==nsnull || ns_v.val.p==this_buffer_pointer, "Garbage in our pointer?"); + ns_v.val.p = this_buffer_pointer; + this_buffer_pointer = nsnull; + break; + case nsXPTType::T_PWSTRING_SIZE_IS: + case nsXPTType::T_PSTRING_SIZE_IS: + case nsXPTType::T_WCHAR_STR: + case nsXPTType::T_CHAR_STR: + case nsXPTType::T_IID: + // If we stashed a value in the this_buffer_pointer, and + // we are passing it as an OUT param, we do _not_ want to + // treat it as a temporary buffer. + // For example, if we pass an IID or string as an IN param, + // we allocate a buffer for the value, but this is NOT cleaned up + // via normal VARIANT cleanup rules - hence we clean it up ourselves. + // If the param is IN/OUT, then the buffer falls under the normal variant + // rules (ie, is flagged as VAL_IS_ALLOCD), so we dont clean it as a temporary. + // (it may have been changed under us - we free the _new_ value. + // Even if ns_val.p already setup as part of "in" processing, + // we need to ensure setup for out. + NS_ABORT_IF_FALSE(ns_v.val.p==nsnull || ns_v.val.p==this_buffer_pointer, "Garbage in our pointer?"); + ns_v.val.p = this_buffer_pointer; + ns_v.flags |= nsXPTCVariant::VAL_IS_ALLOCD; + this_buffer_pointer = nsnull; + break; + case nsXPTType::T_DOMSTRING: + case nsXPTType::T_ASTRING: { + NS_ABORT_IF_FALSE(ns_v.val.p==nsnull, "T_DOMTSTRINGS cant be out and have a value (ie, no in/outs are allowed!"); + NS_ABORT_IF_FALSE(XPT_PD_IS_DIPPER(td.param_flags) && XPT_PD_IS_IN(td.param_flags), "out DOMStrings must really be in dippers!"); + ns_v.flags |= nsXPTCVariant::VAL_IS_DOMSTR; + // Dippers are really treated like "in" params. + ns_v.ptr = new nsString(); + ns_v.val.p = ns_v.ptr; // VAL_IS_* says the .p is what gets freed + if (!ns_v.ptr) { + PyErr_NoMemory(); + rc = PR_FALSE; + } + break; + } + case nsXPTType::T_CSTRING: + case nsXPTType::T_UTF8STRING: { + NS_ABORT_IF_FALSE(ns_v.val.p==nsnull, "T_DOMTSTRINGS cant be out and have a value (ie, no in/outs are allowed!"); + NS_ABORT_IF_FALSE(XPT_PD_IS_DIPPER(td.param_flags) && XPT_PD_IS_IN(td.param_flags), "out DOMStrings must really be in dippers!"); + ns_v.flags |= ( XPT_TDP_TAG(ns_v.type)==nsXPTType::T_CSTRING ? nsXPTCVariant::VAL_IS_CSTR : nsXPTCVariant::VAL_IS_UTF8STR); + ns_v.ptr = new nsCString(); + ns_v.val.p = ns_v.ptr; // VAL_IS_* says the .p is what gets freed + if (!ns_v.ptr) { + PyErr_NoMemory(); + rc = PR_FALSE; + } + break; + } + default: + NS_ABORT_IF_FALSE(0, "Unknown type - don't know how to prepare the output value"); + break; // Nothing to do! + } + } + return rc; +} + + +PyObject *PyXPCOM_InterfaceVariantHelper::MakeSinglePythonResult(int index) +{ + nsXPTCVariant &ns_v = m_var_array[index]; + PyObject *ret = nsnull; + NS_ABORT_IF_FALSE(ns_v.IsPtrData() || ns_v.IsValDOMString(), "expecting a pointer if you want a result!"); + + // Re-fetch the type descriptor. + PythonTypeDescriptor &td = m_python_type_desc_array[index]; + // Make sure the type tag of the variant hasnt changed on us. + NS_ABORT_IF_FALSE(ns_v.type==td.type_flags, "variant type has changed under us!"); + + // If the pointer is NULL, we can get out now! + if (ns_v.ptr==nsnull) { + Py_INCREF(Py_None); + return Py_None; + } + + switch (XPT_TDP_TAG(ns_v.type)) { + case nsXPTType::T_I8: + ret = PyInt_FromLong( *((PRInt8 *)ns_v.ptr) ); + break; + case nsXPTType::T_I16: + ret = PyInt_FromLong( *((PRInt16 *)ns_v.ptr) ); + break; + case nsXPTType::T_I32: + ret = PyInt_FromLong( *((PRInt32 *)ns_v.ptr) ); + break; + case nsXPTType::T_I64: + ret = PyLong_FromLongLong( *((PRInt64 *)ns_v.ptr) ); + break; + case nsXPTType::T_U8: + ret = PyInt_FromLong( *((PRUint8 *)ns_v.ptr) ); + break; + case nsXPTType::T_U16: + ret = PyInt_FromLong( *((PRUint16 *)ns_v.ptr) ); + break; + case nsXPTType::T_U32: + ret = PyInt_FromLong( *((PRUint32 *)ns_v.ptr) ); + break; + case nsXPTType::T_U64: + ret = PyLong_FromUnsignedLongLong( *((PRUint64 *)ns_v.ptr) ); + break; + case nsXPTType::T_FLOAT: + ret = PyFloat_FromDouble( *((float *)ns_v.ptr) ); + break; + case nsXPTType::T_DOUBLE: + ret = PyFloat_FromDouble( *((double *)ns_v.ptr) ); + break; + case nsXPTType::T_BOOL: + ret = *((PRBool *)ns_v.ptr) ? Py_True : Py_False; + Py_INCREF(ret); + break; + case nsXPTType::T_CHAR: +#if PY_MAJOR_VERSION <= 2 + ret = PyString_FromStringAndSize( ((char *)ns_v.ptr), 1 ); +#else + ret = PyUnicode_FromStringAndSize( ((char *)ns_v.ptr), 1 ); +#endif + break; + + case nsXPTType::T_WCHAR: + ret = PyUnicode_FromPRUnichar( ((PRUnichar *)ns_v.ptr), 1 ); + break; +// case nsXPTType::T_VOID: + case nsXPTType::T_IID: + ret = Py_nsIID::PyObjectFromIID( **((nsIID **)ns_v.ptr) ); + break; + case nsXPTType::T_ASTRING: + case nsXPTType::T_DOMSTRING: { + nsAString *rs = (nsAString *)ns_v.ptr; + ret = PyObject_FromNSString(*rs); + break; + } + case nsXPTType::T_UTF8STRING: + case nsXPTType::T_CSTRING: { + nsCString *rs = (nsCString *)ns_v.ptr; + ret = PyObject_FromNSString(*rs, XPT_TDP_TAG(ns_v.type)==nsXPTType::T_UTF8STRING); + break; + } + + case nsXPTType::T_CHAR_STR: + if (*((char **)ns_v.ptr) == NULL) { + ret = Py_None; + Py_INCREF(Py_None); + } else +#if PY_MAJOR_VERSION <= 2 + ret = PyString_FromString( *((char **)ns_v.ptr) ); +#else + ret = PyUnicode_FromString( *((char **)ns_v.ptr) ); +#endif + break; + + case nsXPTType::T_WCHAR_STR: { + PRUnichar *us = *((PRUnichar **)ns_v.ptr); + if (us == NULL) { + ret = Py_None; + Py_INCREF(Py_None); + } else { + ret = PyUnicode_FromPRUnichar( us, nsCRT::strlen(us)); + } + break; + } + case nsXPTType::T_INTERFACE: { + nsIID iid; + if (!Py_nsIID::IIDFromPyObject(td.extra, &iid)) + break; + nsISupports *iret = *((nsISupports **)ns_v.ptr); + // 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: { + nsIID iid; + nsXPTCVariant &ns_viid = m_var_array[td.argnum]; + NS_WARN_IF_FALSE(XPT_TDP_TAG(ns_viid.type)==nsXPTType::T_IID, "The INTERFACE_IS iid describer isnt an IID!"); + if (XPT_TDP_TAG(ns_viid.type)==nsXPTType::T_IID) { + nsIID *piid = (nsIID *)ns_viid.val.p; + if (piid==NULL) + // Also serious, but like below, not our fault! + iid = NS_GET_IID(nsISupports); + else + iid = *piid; + } 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); + 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: { + if ( (* ((void **)ns_v.ptr)) == NULL) { + ret = Py_None; + Py_INCREF(Py_None); + } + if (!PyInt_Check(td.extra)) { + PyErr_SetString(PyExc_TypeError, "The array info is not valid"); + break; + } + PRUint8 array_type = (PRUint8)PyInt_AsLong(td.extra); + PRUint32 seq_size = GetSizeIs(index, PR_FALSE); + nsXPTCVariant &ns_viid = m_var_array[td.argnum]; + nsIID iid; + nsresult res = GetArrayElementIID(m_parent, + m_var_array, + m_methodindex, + index, + &iid); + ret = UnpackSingleArray(m_parent, * ((void **)ns_v.ptr), + seq_size, array_type&XPT_TDP_TAGMASK, + NS_SUCCEEDED(res) ? &iid : NULL); + break; + } + + case nsXPTType::T_PSTRING_SIZE_IS: + if (*((char **)ns_v.ptr) == NULL) { + ret = Py_None; + Py_INCREF(Py_None); + } else { + PRUint32 string_size = GetSizeIs(index, PR_TRUE); +#if PY_MAJOR_VERSION <= 2 + ret = PyString_FromStringAndSize( *((char **)ns_v.ptr), string_size ); +#else + ret = PyUnicode_FromStringAndSize( *((char **)ns_v.ptr), string_size ); +#endif + } + break; + + case nsXPTType::T_PWSTRING_SIZE_IS: + if (*((PRUnichar **)ns_v.ptr) == NULL) { + ret = Py_None; + Py_INCREF(Py_None); + } else { + PRUint32 string_size = GetSizeIs(index, PR_TRUE); + ret = PyUnicode_FromPRUnichar( *((PRUnichar **)ns_v.ptr), string_size ); + } + break; + default: + PyErr_Format(PyExc_ValueError, "Unknown XPCOM type code (0x%x)", XPT_TDP_TAG(ns_v.type)); + /* ret remains nsnull */ + break; + } + return ret; +} + + +PyObject *PyXPCOM_InterfaceVariantHelper::MakePythonResult() +{ + // First we count the results. + int i = 0; + int n_results = 0; + PyObject *ret = NULL; + PRBool have_retval = PR_FALSE; + for (i=0;i<m_num_array;i++) { + PythonTypeDescriptor &td = m_python_type_desc_array[i]; + if (!td.is_auto_out) { + if (XPT_PD_IS_OUT(td.param_flags) || XPT_PD_IS_DIPPER(td.param_flags)) + n_results++; + if (XPT_PD_IS_RETVAL(td.param_flags)) + have_retval = PR_TRUE; + } + } + if (n_results==0) { + ret = Py_None; + Py_INCREF(ret); + } else { + if (n_results > 1) { + ret = PyTuple_New(n_results); + if (ret==NULL) + return NULL; + } + int ret_index = 0; + int max_index = m_num_array; + // Stick the retval at the front if we have have + if (have_retval && n_results > 1) { + PyObject *val = MakeSinglePythonResult(m_num_array-1); + if (val==NULL) { + Py_DECREF(ret); + return NULL; + } + PyTuple_SET_ITEM(ret, 0, val); + max_index--; + ret_index++; + + } + for (i=0;ret_index < n_results && i < max_index;i++) { + if (!m_python_type_desc_array[i].is_auto_out) { + if (XPT_PD_IS_OUT(m_python_type_desc_array[i].param_flags) || XPT_PD_IS_DIPPER(m_python_type_desc_array[i].param_flags)) { + PyObject *val = MakeSinglePythonResult(i); + if (val==NULL) { + Py_XDECREF(ret); + return NULL; + } + if (n_results > 1) { + PyTuple_SET_ITEM(ret, ret_index, val); + ret_index++; + } else { + NS_ABORT_IF_FALSE(ret==NULL, "shouldnt already have a ret!"); + ret = val; + } + } + } + } + + } + return ret; +} + +/************************************************************************* +************************************************************************** + + Helpers when IMPLEMENTING interfaces. + +************************************************************************** +*************************************************************************/ + +PyXPCOM_GatewayVariantHelper::PyXPCOM_GatewayVariantHelper( PyG_Base *gw, int method_index, const nsXPTMethodInfo *info, nsXPTCMiniVariant* params ) +{ + m_params = params; + m_info = info; + // no references added - this class is only alive for + // a single gateway invocation + m_gateway = gw; + m_method_index = method_index; + m_python_type_desc_array = NULL; + m_num_type_descs = 0; +} + +PyXPCOM_GatewayVariantHelper::~PyXPCOM_GatewayVariantHelper() +{ + delete [] m_python_type_desc_array; +} + +PyObject *PyXPCOM_GatewayVariantHelper::MakePyArgs() +{ + NS_PRECONDITION(sizeof(XPTParamDescriptor) == sizeof(nsXPTParamInfo), "We depend on nsXPTParamInfo being a wrapper over the XPTParamDescriptor struct"); + // Setup our array of Python typedescs, and determine the number of objects we + // pass to Python. + m_num_type_descs = m_info->num_args; + m_python_type_desc_array = new PythonTypeDescriptor[m_num_type_descs]; + if (m_python_type_desc_array==nsnull) + return PyErr_NoMemory(); + + // First loop to count the number of objects + // we pass to Python + int i; + for (i=0;i<m_info->num_args;i++) { + nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+i; + PythonTypeDescriptor &td = m_python_type_desc_array[i]; + td.param_flags = pi->flags; + td.type_flags = pi->type.prefix.flags; + td.argnum = pi->type.argnum; + td.argnum2 = pi->type.argnum2; + } + int num_args = ProcessPythonTypeDescriptors(m_python_type_desc_array, m_num_type_descs); + PyObject *ret = PyTuple_New(num_args); + if (ret==NULL) + return NULL; + int this_arg = 0; + for (i=0;i<m_num_type_descs;i++) { + PythonTypeDescriptor &td = m_python_type_desc_array[i]; + if (XPT_PD_IS_IN(td.param_flags) && !td.is_auto_in && !XPT_PD_IS_DIPPER(td.param_flags)) { + PyObject *sub = MakeSingleParam( i, td ); + if (sub==NULL) { + Py_DECREF(ret); + return NULL; + } + NS_ABORT_IF_FALSE(this_arg>=0 && this_arg<num_args, "We are going off the end of the array!"); + PyTuple_SET_ITEM(ret, this_arg, sub); + this_arg++; + } + } + return ret; +} + +PRBool PyXPCOM_GatewayVariantHelper::CanSetSizeIs( int var_index, PRBool is_arg1 ) +{ + NS_ABORT_IF_FALSE(var_index < m_num_type_descs, "var_index param is invalid"); + PRUint8 argnum = is_arg1 ? + m_python_type_desc_array[var_index].argnum : + m_python_type_desc_array[var_index].argnum2; + NS_ABORT_IF_FALSE(argnum < m_num_type_descs, "size_is param is invalid"); + return XPT_PD_IS_OUT(m_python_type_desc_array[argnum].param_flags); +} + +PRBool PyXPCOM_GatewayVariantHelper::SetSizeIs( int var_index, PRBool is_arg1, PRUint32 new_size) +{ + NS_ABORT_IF_FALSE(var_index < m_num_type_descs, "var_index param is invalid"); + PRUint8 argnum = is_arg1 ? + m_python_type_desc_array[var_index].argnum : + m_python_type_desc_array[var_index].argnum2; + NS_ABORT_IF_FALSE(argnum < m_num_type_descs, "size_is param is invalid"); + PythonTypeDescriptor &td_size = m_python_type_desc_array[argnum]; + NS_ABORT_IF_FALSE( XPT_PD_IS_OUT(td_size.param_flags), "size param must be out if we want to set it!"); + NS_ABORT_IF_FALSE(td_size.is_auto_out, "Setting size_is, but param is not marked as auto!"); + + nsXPTCMiniVariant &ns_v = m_params[argnum]; + NS_ABORT_IF_FALSE( (td_size.type_flags & XPT_TDP_TAGMASK) == nsXPTType::T_U32, "size param must be Uint32"); + NS_ABORT_IF_FALSE(ns_v.val.p, "NULL pointer for size_is value!"); + if (ns_v.val.p) { + if (!td_size.have_set_auto) { + *((PRUint32 *)ns_v.val.p) = new_size; + td_size.have_set_auto = PR_TRUE; + } else { + if (*((PRUint32 *)ns_v.val.p) != new_size ) { + PyErr_Format(PyExc_ValueError, "Array lengths inconsistent; array size previously set to %d, but second array is of size %d", ns_v.val.u32, new_size); + return PR_FALSE; + } + } + } + return PR_TRUE; +} + +PRUint32 PyXPCOM_GatewayVariantHelper::GetSizeIs( int var_index, PRBool is_arg1) +{ + NS_ABORT_IF_FALSE(var_index < m_num_type_descs, "var_index param is invalid"); + PRUint8 argnum = is_arg1 ? + m_python_type_desc_array[var_index].argnum : + m_python_type_desc_array[var_index].argnum2; + NS_ABORT_IF_FALSE(argnum < m_num_type_descs, "size_is param is invalid"); + if (argnum >= m_num_type_descs) { + PyErr_SetString(PyExc_ValueError, "dont have a valid size_is indicator for this param"); + return PR_FALSE; + } + PRBool is_out = XPT_PD_IS_OUT(m_python_type_desc_array[argnum].param_flags); + nsXPTCMiniVariant &ns_v = m_params[argnum]; + NS_ABORT_IF_FALSE( (m_python_type_desc_array[argnum].type_flags & XPT_TDP_TAGMASK) == nsXPTType::T_U32, "size param must be Uint32"); + return is_out ? *((PRUint32 *)ns_v.val.p) : ns_v.val.u32; +} + +#undef DEREF_IN_OR_OUT +#define DEREF_IN_OR_OUT( element, ret_type ) (ret_type)(is_out ? *((ret_type *)ns_v.val.p) : (ret_type)(element)) + +PyObject *PyXPCOM_GatewayVariantHelper::MakeSingleParam(int index, PythonTypeDescriptor &td) +{ + NS_PRECONDITION(XPT_PD_IS_IN(td.param_flags), "Must be an [in] param!"); + nsXPTCMiniVariant &ns_v = m_params[index]; + PyObject *ret = NULL; + PRBool is_out = XPT_PD_IS_OUT(td.param_flags); + + switch (td.type_flags & XPT_TDP_TAGMASK) { + case nsXPTType::T_I8: + ret = PyInt_FromLong( DEREF_IN_OR_OUT(ns_v.val.i8, PRInt8 ) ); + break; + case nsXPTType::T_I16: + ret = PyInt_FromLong( DEREF_IN_OR_OUT(ns_v.val.i16, PRInt16) ); + break; + case nsXPTType::T_I32: + ret = PyInt_FromLong( DEREF_IN_OR_OUT(ns_v.val.i32, PRInt32) ); + break; + case nsXPTType::T_I64: + ret = PyLong_FromLongLong( DEREF_IN_OR_OUT(ns_v.val.i64, PRInt64) ); + break; + case nsXPTType::T_U8: + ret = PyInt_FromLong( DEREF_IN_OR_OUT(ns_v.val.u8, PRUint8) ); + break; + case nsXPTType::T_U16: + ret = PyInt_FromLong( DEREF_IN_OR_OUT(ns_v.val.u16, PRUint16) ); + break; + case nsXPTType::T_U32: + ret = PyInt_FromLong( DEREF_IN_OR_OUT(ns_v.val.u32, PRUint32) ); + break; + case nsXPTType::T_U64: + ret = PyLong_FromUnsignedLongLong( DEREF_IN_OR_OUT(ns_v.val.u64, PRUint64) ); + break; + case nsXPTType::T_FLOAT: + ret = PyFloat_FromDouble( DEREF_IN_OR_OUT(ns_v.val.f, float) ); + break; + case nsXPTType::T_DOUBLE: + ret = PyFloat_FromDouble( DEREF_IN_OR_OUT(ns_v.val.d, double) ); + break; + case nsXPTType::T_BOOL: { + PRBool temp = DEREF_IN_OR_OUT(ns_v.val.b, PRBool); + ret = temp ? Py_True : Py_False; + Py_INCREF(ret); + break; + } + case nsXPTType::T_CHAR: { + char temp = DEREF_IN_OR_OUT(ns_v.val.c, char); +#if PY_MAJOR_VERSION <= 2 + ret = PyString_FromStringAndSize(&temp, 1); +#else + ret = PyUnicode_FromStringAndSize(&temp, 1); +#endif + break; + } + case nsXPTType::T_WCHAR: { + PRUnichar temp = (PRUnichar)DEREF_IN_OR_OUT(ns_v.val.wc, PRUnichar); + ret = PyUnicode_FromPRUnichar(&temp, 1); + break; + } +// case nsXPTType::T_VOID: + case nsXPTType::T_IID: { + ret = Py_nsIID::PyObjectFromIID( * DEREF_IN_OR_OUT(ns_v.val.p, const nsIID *) ); + break; + } + case nsXPTType::T_ASTRING: + case nsXPTType::T_DOMSTRING: { + NS_ABORT_IF_FALSE(is_out || !XPT_PD_IS_DIPPER(td.param_flags), "DOMStrings can't be inout"); + const nsAString *rs = (const nsAString *)ns_v.val.p; + ret = PyObject_FromNSString(*rs); + break; + } + case nsXPTType::T_CSTRING: + case nsXPTType::T_UTF8STRING: { + NS_ABORT_IF_FALSE(is_out || !XPT_PD_IS_DIPPER(td.param_flags), "DOMStrings can't be inout"); + const nsCString *rs = (const nsCString *)ns_v.val.p; + ret = PyObject_FromNSString(*rs, (td.type_flags & XPT_TDP_TAGMASK)==nsXPTType::T_UTF8STRING); + break; + } + case nsXPTType::T_CHAR_STR: { + char *t = DEREF_IN_OR_OUT(ns_v.val.p, char *); + if (t==NULL) { + ret = Py_None; + Py_INCREF(Py_None); + } else +#if PY_MAJOR_VERSION <= 2 + ret = PyString_FromString(t); +#else + ret = PyUnicode_FromString(t); +#endif + break; + } + + case nsXPTType::T_WCHAR_STR: { + PRUnichar *us = DEREF_IN_OR_OUT(ns_v.val.p, PRUnichar *); + if (us==NULL) { + ret = Py_None; + Py_INCREF(Py_None); + } else { + ret = PyUnicode_FromPRUnichar( us, nsCRT::strlen(us)); + } + break; + } + case nsXPTType::T_INTERFACE_IS: // our Python code does it :-) + case nsXPTType::T_INTERFACE: { + nsISupports *iret = DEREF_IN_OR_OUT(ns_v.val.p, nsISupports *); + nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+index; + ret = m_gateway->MakeInterfaceParam(iret, NULL, m_method_index, pi, index); + break; + } +/*** + nsISupports *iret = DEREF_IN_OR_OUT(ns_v.val.p, nsISupports *); + nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+index; + nsXPTCMiniVariant &ns_viid = m_params[td.argnum]; + NS_ABORT_IF_FALSE((m_python_type_desc_array[td.argnum].type_flags & XPT_TDP_TAGMASK) == nsXPTType::T_IID, "The INTERFACE_IS iid describer isnt an IID!"); + const nsIID * iid = NULL; + if (XPT_PD_IS_IN(m_python_type_desc_array[td.argnum].param_flags)) + // may still be inout! + iid = DEREF_IN_OR_OUT(ns_v.val.p, const nsIID *); + + ret = m_gateway->MakeInterfaceParam(iret, iid, m_method_index, pi, index); + break; + } +****/ + case nsXPTType::T_ARRAY: { + void *t = DEREF_IN_OR_OUT(ns_v.val.p, void *); + if (t==NULL) { + // 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; + 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(NULL, t, seq_size, array_type&XPT_TDP_TAGMASK, piid); + } + break; + } + case nsXPTType::T_PSTRING_SIZE_IS: { + char *t = DEREF_IN_OR_OUT(ns_v.val.p, char *); + PRUint32 string_size = GetSizeIs(index, PR_TRUE); + if (t==NULL) { + ret = Py_None; + Py_INCREF(Py_None); + } else +#if PY_MAJOR_VERSION <= 2 + ret = PyString_FromStringAndSize(t, string_size); +#else + ret = PyUnicode_FromStringAndSize(t, string_size); +#endif + break; + } + case nsXPTType::T_PWSTRING_SIZE_IS: { + PRUnichar *t = DEREF_IN_OR_OUT(ns_v.val.p, PRUnichar *); + PRUint32 string_size = GetSizeIs(index, PR_TRUE); + if (t==NULL) { + ret = Py_None; + Py_INCREF(Py_None); + } else { + ret = PyUnicode_FromPRUnichar(t, string_size); + } + break; + } + default: + // As this is called by external components, + // we return _something_ rather than failing before any user code has run! + { + char buf[128]; + sprintf(buf, "Unknown XPCOM type flags (0x%x)", td.type_flags); + PyXPCOM_LogWarning("%s - returning a string object with this message!\n", buf); +#if PY_MAJOR_VERSION <= 2 + ret = PyString_FromString(buf); +#else + ret = PyUnicode_FromString(buf); +#endif + break; + } + } + return ret; +} + +nsresult PyXPCOM_GatewayVariantHelper::GetArrayType(PRUint8 index, PRUint8 *ret, nsIID **iid) +{ + nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService( + NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)); + NS_ABORT_IF_FALSE(iim != nsnull, "Cant get interface from IIM!"); + if (iim==nsnull) + return NS_ERROR_FAILURE; + + nsCOMPtr<nsIInterfaceInfo> ii; + nsresult rc = iim->GetInfoForIID( &m_gateway->m_iid, getter_AddRefs(ii)); + if (NS_FAILED(rc)) + return rc; + nsXPTType datumType; + const nsXPTParamInfo& param_info = m_info->GetParam((PRUint8)index); + 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; +} + +PRBool PyXPCOM_GatewayVariantHelper::GetIIDForINTERFACE_ID(int index, const nsIID **ppret) +{ + // Not sure if the IID pointed at by by this is allows to be + // in or out, so we will allow it. + nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+index; + nsXPTType typ = pi->GetType(); + NS_WARN_IF_FALSE(XPT_TDP_TAG(typ) == nsXPTType::T_IID, "INTERFACE_IS IID param isnt an IID!"); + NS_ABORT_IF_FALSE(typ.IsPointer(), "Expecting to re-fill a pointer value."); + if (XPT_TDP_TAG(typ) != nsXPTType::T_IID) + *ppret = &NS_GET_IID(nsISupports); + else { + nsXPTCMiniVariant &ns_v = m_params[index]; + if (pi->IsOut()) { + nsIID **pp = (nsIID **)ns_v.val.p; + if (pp && *pp) + *ppret = *pp; + else + *ppret = &NS_GET_IID(nsISupports); + } else if (pi->IsIn()) { + nsIID *p = (nsIID *)ns_v.val.p; + if (p) + *ppret = p; + else + *ppret = &NS_GET_IID(nsISupports); + } else { + NS_ERROR("Param is not in or out!"); + *ppret = &NS_GET_IID(nsISupports); + } + } + return PR_TRUE; +} + +nsIInterfaceInfo *PyXPCOM_GatewayVariantHelper::GetInterfaceInfo() +{ + if (!m_interface_info) { + nsCOMPtr<nsIInterfaceInfoManager> iim(do_GetService( + NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)); + if (iim) + iim->GetInfoForIID(&m_gateway->m_iid, getter_AddRefs(m_interface_info)); + } + return m_interface_info; +} + +#undef FILL_SIMPLE_POINTER +#define FILL_SIMPLE_POINTER( type, ob ) *((type *)ns_v.val.p) = (type)(ob) + +nsresult PyXPCOM_GatewayVariantHelper::BackFillVariant( PyObject *val, int index) +{ + nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+index; + NS_ABORT_IF_FALSE(pi->IsOut() || pi->IsDipper(), "The value must be marked as [out] (or a dipper) to be back-filled!"); + NS_ABORT_IF_FALSE(!pi->IsShared(), "Dont know how to back-fill a shared out param"); + nsXPTCMiniVariant &ns_v = m_params[index]; + + nsXPTType typ = pi->GetType(); + PyObject* val_use = NULL; + + NS_ABORT_IF_FALSE(pi->IsDipper() || ns_v.val.p, "No space for result!"); + if (!pi->IsDipper() && !ns_v.val.p) return NS_ERROR_INVALID_POINTER; + + PRBool rc = PR_TRUE; + switch (XPT_TDP_TAG(typ)) { + case nsXPTType::T_I8: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE; + FILL_SIMPLE_POINTER( PRInt8, PyInt_AsLong(val_use) ); + break; + case nsXPTType::T_I16: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE; + FILL_SIMPLE_POINTER( PRInt16, PyInt_AsLong(val_use) ); + break; + case nsXPTType::T_I32: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE; + FILL_SIMPLE_POINTER( PRInt32, PyInt_AsLong(val_use) ); + break; + case nsXPTType::T_I64: + if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE; + FILL_SIMPLE_POINTER( PRInt64, PyLong_AsLongLong(val_use) ); + break; + case nsXPTType::T_U8: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE; + FILL_SIMPLE_POINTER( PRUint8, PyInt_AsLong(val_use) ); + break; + case nsXPTType::T_U16: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE; + FILL_SIMPLE_POINTER( PRUint16, PyInt_AsLong(val_use) ); + break; + case nsXPTType::T_U32: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE; + FILL_SIMPLE_POINTER( PRUint32, PyInt_AsLong(val_use) ); + break; + case nsXPTType::T_U64: + if ((val_use=PyNumber_Long(val))==NULL) BREAK_FALSE; + FILL_SIMPLE_POINTER( PRUint64, PyLong_AsUnsignedLongLong(val_use) ); + break; + case nsXPTType::T_FLOAT: + if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE + FILL_SIMPLE_POINTER( float, PyFloat_AsDouble(val_use) ); + break; + case nsXPTType::T_DOUBLE: + if ((val_use=PyNumber_Float(val))==NULL) BREAK_FALSE + FILL_SIMPLE_POINTER( double, PyFloat_AsDouble(val_use) ); + break; + case nsXPTType::T_BOOL: + if ((val_use=PyNumber_Int(val))==NULL) BREAK_FALSE + FILL_SIMPLE_POINTER( PRBool, PyInt_AsLong(val_use) ); + break; + case nsXPTType::T_CHAR: +#if PY_MAJOR_VERSION <= 2 + 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 = PyObject_Str(val))==NULL) + BREAK_FALSE; + // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode! + NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!"); + FILL_SIMPLE_POINTER( char, *PyString_AS_STRING(val_use) ); +#else + if (!PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object"); + BREAK_FALSE; + } +# ifndef Py_LIMITED_API + FILL_SIMPLE_POINTER( char, *PyUnicode_AS_UNICODE(val) ); +# else + FILL_SIMPLE_POINTER( char, PyUnicode_ReadChar(val, 0) ); +# endif +#endif + break; + + case nsXPTType::T_WCHAR: +#if PY_MAJOR_VERSION <= 2 + if (!PyString_Check(val) && !PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object"); + BREAK_FALSE; + } +#else + if (!PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a Unicode object"); + BREAK_FALSE; + } +#endif + if ((val_use = PyUnicode_FromObject(val))==NULL) + BREAK_FALSE; + NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!"); + // Lossy! +#ifndef Py_LIMITED_API + FILL_SIMPLE_POINTER( PRUnichar, *PyUnicode_AS_UNICODE(val_use) ); +#else + FILL_SIMPLE_POINTER( PRUnichar, PyUnicode_ReadChar(val_use, 0) ); +#endif + break; + +// case nsXPTType::T_VOID: + case nsXPTType::T_IID: { + nsIID iid; + if (!Py_nsIID::IIDFromPyObject(val, &iid)) + BREAK_FALSE; + nsIID **pp = (nsIID **)ns_v.val.p; + // If there is an existing [in] IID, free it. + if (*pp && pi->IsIn()) + nsMemory::Free(*pp); + *pp = (nsIID *)nsMemory::Alloc(sizeof(nsIID)); + if (*pp==NULL) { + PyErr_NoMemory(); + BREAK_FALSE; + } + memcpy(*pp, &iid, sizeof(iid)); + break; + } + + case nsXPTType::T_ASTRING: + 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 (!PyObject_AsNSString(val, *ws)) + BREAK_FALSE; + break; + } + case nsXPTType::T_CSTRING: { + nsCString *ws = (nsCString *)ns_v.val.p; + NS_ABORT_IF_FALSE(ws->Length() == 0, "Why does this writable string already have chars??"); + if (val == Py_None) { + NS_ABORT_IF_FALSE(0, "dont handle None here yet"); + } else { +#if PY_MAJOR_VERSION <= 2 + if (!PyString_Check(val) && !PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a string or Unicode object"); + BREAK_FALSE; + } + val_use = PyObject_Str(val); + NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!"); + const char *sz = PyString_AS_STRING(val_use); + ws->Assign(sz, PyString_GET_SIZE(val_use)); +#else + if (!PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object"); + BREAK_FALSE; + } + val_use = PyUnicode_AsUTF8String(val); + const char *sz = PyBytes_AS_STRING(val_use); + ws->Assign(sz, PyBytes_GET_SIZE(val_use)); +#endif + } + break; + } + case nsXPTType::T_UTF8STRING: { + nsCString *ws = (nsCString *)ns_v.val.p; + NS_ABORT_IF_FALSE(ws->Length() == 0, "Why does this writable string already have chars??"); + if (val == Py_None) { + NS_ABORT_IF_FALSE(0, "dont handle None here yet"); + } else { +#if PY_MAJOR_VERSION <= 2 + if (PyString_Check(val)) { + val_use = val; + Py_INCREF(val); + } + else +#endif + if (PyUnicode_Check(val)) { + val_use = PyUnicode_AsUTF8String(val); + } else { +#if PY_MAJOR_VERSION <= 2 + PyErr_SetString(PyExc_TypeError, "UTF8 parameters must be string or Unicode objects"); +#else + PyErr_SetString(PyExc_TypeError, "UTF8 parameters must be unicode objects"); +#endif + BREAK_FALSE; + } +#if PY_MAJOR_VERSION <= 2 + NS_ABORT_IF_FALSE(PyString_Check(val_use), "must have a string object!"); + const char *sz = PyString_AS_STRING(val_use); + ws->Assign(sz, PyString_GET_SIZE(val_use)); +#else + NS_ABORT_IF_FALSE(PyBytes_Check(val_use), "must have a bytes object!"); + const char *sz = PyBytes_AS_STRING(val_use); + ws->Assign(sz, PyBytes_GET_SIZE(val_use)); +#endif + } + break; + } + + case nsXPTType::T_CHAR_STR: { + // If it is an existing string, free it. + char **pp = (char **)ns_v.val.p; + if (*pp && pi->IsIn()) + nsMemory::Free(*pp); + *pp = nsnull; + + if (val == Py_None) + break; // Remains NULL. +#if PY_MAJOR_VERSION <= 2 + 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 = PyObject_Str(val))==NULL) + BREAK_FALSE; + // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode! + NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!"); + + const char *sz = PyString_AS_STRING(val_use); + int nch = PyString_GET_SIZE(val_use); +#else + if (!PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object"); + BREAK_FALSE; + } + if ((val_use = PyUnicode_AsUTF8String(val))==NULL) + BREAK_FALSE; + + const char *sz = PyBytes_AS_STRING(val_use); + int nch = PyBytes_GET_SIZE(val_use); +#endif + + *pp = (char *)nsMemory::Alloc(nch+1); + if (*pp==NULL) { + PyErr_NoMemory(); + BREAK_FALSE; + } + strncpy(*pp, sz, nch+1); + break; + } + case nsXPTType::T_WCHAR_STR: { + // If it is an existing string, free it. + PRUnichar **pp = (PRUnichar **)ns_v.val.p; + if (*pp && pi->IsIn()) + nsMemory::Free(*pp); + *pp = nsnull; + if (val == Py_None) + break; // Remains NULL. +#if PY_MAJOR_VERSION <= 2 + 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); + NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!"); +#else + if (!PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object"); + BREAK_FALSE; + } + val_use = val; + Py_INCREF(val_use); +#endif + if (PyUnicode_AsPRUnichar(val_use, pp, NULL) < 0) + BREAK_FALSE; + break; + } + case nsXPTType::T_INTERFACE: { + nsISupports *pnew = nsnull; + // Find out what IID we are declared to use. + nsIID *iid = NULL; + nsIInterfaceInfo *ii = GetInterfaceInfo(); + if (ii) + ii->GetIIDForParam(m_method_index, pi, &iid); + + // Get it the "standard" way. + // 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 :-( + nsIID iid_use = iid ? *iid : NS_GET_IID(nsISupports); + if (!Py_nsISupports::InterfaceFromPyObject(val, iid_use, &pnew, PR_TRUE)) + BREAK_FALSE; + nsISupports **pp = (nsISupports **)ns_v.val.p; + if (*pp && pi->IsIn()) { + Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires. + (*pp)->Release(); + Py_END_ALLOW_THREADS; + } + + *pp = pnew; // ref-count added by InterfaceFromPyObject + break; + } + case nsXPTType::T_INTERFACE_IS: { + const nsIID *piid; + if (!GetIIDForINTERFACE_ID(pi->type.argnum, &piid)) + BREAK_FALSE; + + nsISupports *pnew = nsnull; + // Get it the "standard" way. + // 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 :-( + if (!Py_nsISupports::InterfaceFromPyObject(val, *piid, &pnew, PR_TRUE)) + BREAK_FALSE; + nsISupports **pp = (nsISupports **)ns_v.val.p; + if (*pp && pi->IsIn()) { + Py_BEGIN_ALLOW_THREADS; // MUST release thread-lock, incase a Python COM object that re-acquires. + (*pp)->Release(); + Py_END_ALLOW_THREADS; + } + + *pp = pnew; // ref-count added by InterfaceFromPyObject + break; + } + + case nsXPTType::T_PSTRING_SIZE_IS: { + const char *sz = nsnull; + PRUint32 nch = 0; + if (val != Py_None) { +#if PY_MAJOR_VERSION <= 2 + 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 = PyObject_Str(val))==NULL) + BREAK_FALSE; + // Sanity check should PyObject_Str() ever loosen its semantics wrt Unicode! + NS_ABORT_IF_FALSE(PyString_Check(val_use), "PyObject_Str didnt return a string object!"); + + sz = PyString_AS_STRING(val_use); + nch = PyString_GET_SIZE(val_use); +#else + if (!PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object"); + BREAK_FALSE; + } + if ((val_use = PyUnicode_AsUTF8String(val))==NULL) + BREAK_FALSE; + + sz = PyBytes_AS_STRING(val_use); + nch = PyBytes_GET_SIZE(val_use); +#endif + } + PRBool bBackFill = PR_FALSE; + PRBool bCanSetSizeIs = CanSetSizeIs(index, PR_TRUE); + // If we can not change the size, check our sequence is correct. + if (!bCanSetSizeIs) { + PRUint32 existing_size = GetSizeIs(index, PR_TRUE); + if (nch != existing_size) { + PyErr_Format(PyExc_ValueError, "This function is expecting a string of exactly length %d - %d characters were passed", existing_size, nch); + BREAK_FALSE; + } + // It we have an "inout" param, but an "in" count, then + // it is probably a buffer the caller expects us to + // fill in-place! + bBackFill = pi->IsIn(); + } + if (bBackFill) { + memcpy(*(char **)ns_v.val.p, sz, nch); + } else { + // If we have an existing string, free it! + char **pp = (char **)ns_v.val.p; + if (*pp && pi->IsIn()) + nsMemory::Free(*pp); + *pp = nsnull; + if (sz==nsnull) // None specified. + break; // Remains NULL. + *pp = (char *)nsMemory::Alloc(nch); + if (*pp==NULL) { + PyErr_NoMemory(); + BREAK_FALSE; + } + memcpy(*pp, sz, nch); + if (bCanSetSizeIs) + rc = SetSizeIs(index, PR_TRUE, nch); + else { + NS_ABORT_IF_FALSE(GetSizeIs(index, PR_TRUE) == nch, "Can't set sizeis, but string isnt correct size"); + } + } + break; + } + + case nsXPTType::T_PWSTRING_SIZE_IS: { + PRUnichar *sz = nsnull; + PRUint32 nch = 0; + PRUint32 nbytes = 0; + + if (val != Py_None) { +#if PY_MAJOR_VERSION <= 2 + 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); + NS_ABORT_IF_FALSE(PyUnicode_Check(val_use), "PyUnicode_FromObject didnt return a Unicode object!"); +#else + if (!PyUnicode_Check(val)) { + PyErr_SetString(PyExc_TypeError, "This parameter must be a unicode object"); + BREAK_FALSE; + } + val_use = val; + Py_INCREF(val_use); +#endif + if (PyUnicode_AsPRUnichar(val_use, &sz, &nch) < 0) + BREAK_FALSE; + nbytes = sizeof(PRUnichar) * nch; + } + PRBool bBackFill = PR_FALSE; + PRBool bCanSetSizeIs = CanSetSizeIs(index, PR_TRUE); + // If we can not change the size, check our sequence is correct. + if (!bCanSetSizeIs) { + // It is a buffer the caller prolly wants us to fill in-place! + PRUint32 existing_size = GetSizeIs(index, PR_TRUE); + if (nch != existing_size) { + PyErr_Format(PyExc_ValueError, "This function is expecting a string of exactly length %d - %d characters were passed", existing_size, nch); + BREAK_FALSE; + } + // It we have an "inout" param, but an "in" count, then + // it is probably a buffer the caller expects us to + // fill in-place! + bBackFill = pi->IsIn(); + } + if (bBackFill) { + memcpy(*(PRUnichar **)ns_v.val.p, sz, nbytes); + } else { + // If it is an existing string, free it. + PRUnichar **pp = (PRUnichar **)ns_v.val.p; + if (*pp && pi->IsIn()) + nsMemory::Free(*pp); + *pp = sz; + sz = nsnull; + if (bCanSetSizeIs) + rc = SetSizeIs(index, PR_TRUE, nch); + else { + NS_ABORT_IF_FALSE(GetSizeIs(index, PR_TRUE) == nch, "Can't set sizeis, but string isnt correct size"); + } + } + if (sz) + nsMemory::Free(sz); + break; + } + case nsXPTType::T_ARRAY: { + // If it is an existing array of the correct size, keep it. + PRUint32 sequence_size = 0; + PRUint8 array_type; + nsIID *piid; + nsresult ns = GetArrayType(index, &array_type, &piid); + if (NS_FAILED(ns)) + return ns; + PRUint32 element_size = GetArrayElementSize(array_type); + if (val != Py_None) { + if (!PySequence_Check(val)) { + PyErr_Format(PyExc_TypeError, "Object for xpcom array must be a sequence, not type '%s'", PyXPCOM_ObTypeName(val)); + BREAK_FALSE; + } + sequence_size = PySequence_Length(val); + } + PRUint32 existing_size = GetSizeIs(index, PR_FALSE); + PRBool bBackFill = PR_FALSE; + PRBool bCanSetSizeIs = CanSetSizeIs(index, PR_FALSE); + // If we can not change the size, check our sequence is correct. + if (!bCanSetSizeIs) { + // It is a buffer the caller prolly wants us to fill in-place! + if (sequence_size != existing_size) { + PyErr_Format(PyExc_ValueError, "This function is expecting a sequence of exactly length %d - %d items were passed", existing_size, sequence_size); + BREAK_FALSE; + } + // It we have an "inout" param, but an "in" count, then + // it is probably a buffer the caller expects us to + // fill in-place! + bBackFill = pi->IsIn(); + } + if (bBackFill) + 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; + if (*pp && pi->IsIn()) { + FreeSingleArray(*pp, existing_size, array_type); + nsMemory::Free(*pp); + } + *pp = nsnull; + if (val == Py_None) + break; // Remains NULL. + size_t nbytes = sequence_size * element_size; + 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, piid); + if (!rc) break; + if (bCanSetSizeIs) + rc = SetSizeIs(index, PR_FALSE, sequence_size); + else { + NS_ABORT_IF_FALSE(GetSizeIs(index, PR_FALSE) == sequence_size, "Can't set sizeis, but string isnt correct size"); + } + } + break; + } + default: + // try and limp along in this case. + // leave rc TRUE + PyXPCOM_LogWarning("Converting Python object for an [out] param - The object type (0x%x) is unknown - leaving param alone!\n", XPT_TDP_TAG(typ)); + break; + } + Py_XDECREF(val_use); + if (!rc) + return NS_ERROR_FAILURE; + return NS_OK; +} + +nsresult PyXPCOM_GatewayVariantHelper::ProcessPythonResult(PyObject *ret_ob) +{ + // NOTE - although we return an nresult, if we leave a Python + // exception set, then our caller may take additional action + // (ie, translating our nsresult to a more appropriate nsresult + // for the Python exception.) + NS_PRECONDITION(!PyErr_Occurred(), "Expecting no Python exception to be pending when processing the return result"); + + nsresult rc = NS_OK; + // If we dont get a tuple back, then the result is only + // an int nresult for the underlying function. + // (ie, the policy is expected to return (NS_OK, user_retval), + // but can also return (say), NS_ERROR_FAILURE + if (PyInt_Check(ret_ob)) + return PyInt_AsLong(ret_ob); + // Now it must be the tuple. + if (!PyTuple_Check(ret_ob) || + PyTuple_Size(ret_ob)!=2 || + !PyInt_Check(PyTuple_GET_ITEM(ret_ob, 0))) { + PyErr_SetString(PyExc_TypeError, "The Python result must be a single integer or a tuple of length==2 and first item an int."); + return NS_ERROR_FAILURE; + } + PyObject *user_result = PyTuple_GET_ITEM(ret_ob, 1); + // Count up how many results our function needs. + int i; + int num_results = 0; + int last_result = -1; // optimization if we only have one - this is it! + int index_retval = -1; + for (i=0;i<m_num_type_descs;i++) { + nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+i; + if (!m_python_type_desc_array[i].is_auto_out) { + if (pi->IsOut() || pi->IsDipper()) { + num_results++; + last_result = i; + } + if (pi->IsRetval()) + index_retval = i; + } + } + + if (num_results==0) { + ; // do nothing + } else if (num_results==1) { + // May or may not be the nominated retval - who cares! + NS_ABORT_IF_FALSE(last_result >=0 && last_result < m_num_type_descs, "Have one result, but dont know its index!"); + rc = BackFillVariant( user_result, last_result ); + } else { + // Loop over each one, filling as we go. + // We allow arbitary sequences here, but _not_ strings + // or Unicode! + // NOTE - We ALWAYS do the nominated retval first. + // The Python pattern is always: + // return retval [, byref1 [, byref2 ...] ] + // But the retval is often the last param described in the info. + if (!PySequence_Check(user_result) || +#if PY_MAJOR_VERSION <= 2 + PyString_Check(user_result) || +#else + PyBytes_Check(user_result) || +#endif + PyUnicode_Check(user_result)) { + PyErr_SetString(PyExc_TypeError, "This function has multiple results, but a sequence was not given to fill them"); + return NS_ERROR_FAILURE; + } + int num_user_results = PySequence_Length(user_result); + // If they havent given enough, we dont really care. + // although a warning is probably appropriate. + if (num_user_results != num_results) { + const char *method_name = m_info->GetName(); + PyXPCOM_LogWarning("The method '%s' has %d out params, but %d were supplied by the Python code\n", + method_name, + num_results, + num_user_results); + } + int this_py_index = 0; + if (index_retval != -1) { + // We always return the nominated result first! + PyObject *sub = PySequence_GetItem(user_result, 0); + if (sub==NULL) + return NS_ERROR_FAILURE; + rc = BackFillVariant(sub, index_retval); + Py_DECREF(sub); + this_py_index = 1; + } + for (i=0;NS_SUCCEEDED(rc) && i<m_info->GetParamCount();i++) { + // If weve already done it, or dont need to do it! + if (i==index_retval || m_python_type_desc_array[i].is_auto_out) + continue; + nsXPTParamInfo *pi = (nsXPTParamInfo *)m_info->params+i; + if (pi->IsOut()) { + PyObject *sub = PySequence_GetItem(user_result, this_py_index); + if (sub==NULL) + return NS_ERROR_FAILURE; + rc = BackFillVariant(sub, i); + Py_DECREF(sub); + this_py_index++; + } + } + } + return rc; +} diff --git a/src/libs/xpcom18a4/python/src/dllmain.cpp b/src/libs/xpcom18a4/python/src/dllmain.cpp new file mode 100644 index 00000000..4cc08578 --- /dev/null +++ b/src/libs/xpcom18a4/python/src/dllmain.cpp @@ -0,0 +1,352 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * 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 ***** */ + +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +#include "PyXPCOM_std.h" +#include <prthread.h> +#include "nsIThread.h" +#include "nsILocalFile.h" + +#ifdef XP_WIN +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include "windows.h" +#endif + +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) +// deprecated, but retained for backward compatibility: +PyXPCOM_INTERFACE_DEFINE(Py_nsIComponentManagerObsolete, nsIComponentManagerObsolete, PyMethods_IComponentManagerObsolete) + +#ifndef PYXPCOM_USE_PYGILSTATE + +//////////////////////////////////////////////////////////// +// Thread-state helpers/global functions. +// Only used if there is no Python PyGILState_* API +// +static PyThreadState *ptsGlobal = nsnull; +PyInterpreterState *PyXPCOM_InterpreterState = nsnull; +PRUintn tlsIndex = 0; + + +// This function must be called at some time when the interpreter lock and state is valid. +// Called by init{module} functions and also COM factory entry point. +void PyXPCOM_InterpreterState_Ensure() +{ + if (PyXPCOM_InterpreterState==NULL) { + PyThreadState *threadStateSave = PyThreadState_Swap(NULL); + if (threadStateSave==NULL) + Py_FatalError("Can not setup interpreter state, as current state is invalid"); + + PyXPCOM_InterpreterState = threadStateSave->interp; + PyThreadState_Swap(threadStateSave); + } +} + +void PyXPCOM_InterpreterState_Free() +{ + PyXPCOM_ThreadState_Free(); + PyXPCOM_InterpreterState = NULL; // Eek - should I be freeing something? +} + +// This structure is stored in the TLS slot. At this stage only a Python thread state +// is kept, but this may change in the future... +struct ThreadData{ + PyThreadState *ts; +}; + +// Ensure that we have a Python thread state available to use. +// If this is called for the first time on a thread, it will allocate +// the thread state. This does NOT change the state of the Python lock. +// Returns TRUE if a new thread state was created, or FALSE if a +// thread state already existed. +PRBool PyXPCOM_ThreadState_Ensure() +{ + ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex); + if (pData==NULL) { /* First request on this thread */ + /* Check we have an interpreter state */ + if (PyXPCOM_InterpreterState==NULL) { + Py_FatalError("Can not setup thread state, as have no interpreter state"); + } + pData = (ThreadData *)nsMemory::Alloc(sizeof(ThreadData)); + if (!pData) + Py_FatalError("Out of memory allocating thread state."); + memset(pData, 0, sizeof(*pData)); + if (NS_FAILED( PR_SetThreadPrivate( tlsIndex, pData ) ) ) { + NS_ABORT_IF_FALSE(0, "Could not create thread data for this thread!"); + Py_FatalError("Could not thread private thread data!"); + } + pData->ts = PyThreadState_New(PyXPCOM_InterpreterState); + return PR_TRUE; // Did create a thread state state + } + return PR_FALSE; // Thread state was previously created +} + +// Asuming we have a valid thread state, acquire the Python lock. +void PyXPCOM_InterpreterLock_Acquire() +{ + ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex); + NS_ABORT_IF_FALSE(pData, "Have no thread data for this thread!"); + PyThreadState *thisThreadState = pData->ts; + PyEval_AcquireThread(thisThreadState); +} + +// Asuming we have a valid thread state, release the Python lock. +void PyXPCOM_InterpreterLock_Release() +{ + ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex); + NS_ABORT_IF_FALSE(pData, "Have no thread data for this thread!"); + PyThreadState *thisThreadState = pData->ts; + PyEval_ReleaseThread(thisThreadState); +} + +// Free the thread state for the current thread +// (Presumably previously create with a call to +// PyXPCOM_ThreadState_Ensure) +void PyXPCOM_ThreadState_Free() +{ + ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex); + if (!pData) return; + PyThreadState *thisThreadState = pData->ts; + PyThreadState_Delete(thisThreadState); + PR_SetThreadPrivate(tlsIndex, NULL); + nsMemory::Free(pData); +} + +void PyXPCOM_ThreadState_Clear() +{ + ThreadData *pData = (ThreadData *)PR_GetThreadPrivate(tlsIndex); + PyThreadState *thisThreadState = pData->ts; + PyThreadState_Clear(thisThreadState); +} +#endif // PYXPCOM_USE_PYGILSTATE + +//////////////////////////////////////////////////////////// +// Lock/exclusion global functions. +// +void PyXPCOM_AcquireGlobalLock(void) +{ + NS_PRECONDITION(g_lockMain != nsnull, "Cant acquire a NULL lock!"); + PR_Lock(g_lockMain); +} +void PyXPCOM_ReleaseGlobalLock(void) +{ + NS_PRECONDITION(g_lockMain != nsnull, "Cant release a NULL lock!"); + PR_Unlock(g_lockMain); +} + +void PyXPCOM_DLLAddRef(void) +{ + // Must be thread-safe, although cant have the Python lock! + CEnterLeaveXPCOMFramework _celf; + PRInt32 cnt = PR_AtomicIncrement(&g_cLockCount); + if (cnt==1) { // First call + if (!Py_IsInitialized()) { + Py_Initialize(); + // Make sure our Windows framework is all setup. + PyXPCOM_Globals_Ensure(); + // Make sure we have _something_ as sys.argv. + if (PySys_GetObject((char*)"argv")==NULL) { + PyObject *path = PyList_New(0); +#if PY_MAJOR_VERSION <= 2 + PyObject *str = PyString_FromString(""); +#else + PyObject *str = PyUnicode_FromString(""); +#endif + PyList_Append(path, str); + PySys_SetObject((char*)"argv", path); + Py_XDECREF(path); + Py_XDECREF(str); + } + + // Must force Python to start using thread locks, as + // we are free-threaded (maybe, I think, sometimes :-) + PyEval_InitThreads(); +#ifndef PYXPCOM_USE_PYGILSTATE + // Release Python lock, as first thing we do is re-get it. + ptsGlobal = PyEval_SaveThread(); +#endif + // NOTE: We never finalize Python!! + } + } +} +void PyXPCOM_DLLRelease(void) +{ + PR_AtomicDecrement(&g_cLockCount); +} + +void pyxpcom_construct(void) +{ + g_lockMain = PR_NewLock(); +#ifndef PYXPCOM_USE_PYGILSTATE + PRStatus status; + status = PR_NewThreadPrivateIndex( &tlsIndex, NULL ); + NS_WARN_IF_FALSE(status==0, "Could not allocate TLS storage"); + if (NS_FAILED(status)) { + PR_DestroyLock(g_lockMain); + return; // PR_FALSE; + } +#endif // PYXPCOM_USE_PYGILSTATE + return; // PR_TRUE; +} + +void pyxpcom_destruct(void) +{ + PR_DestroyLock(g_lockMain); +#ifndef PYXPCOM_USE_PYGILSTATE + // I can't locate a way to kill this - + // should I pass a dtor to PR_NewThreadPrivateIndex?? + // TlsFree(tlsIndex); +#endif // PYXPCOM_USE_PYGILSTATE +} + +// Yet another attempt at cross-platform library initialization and finalization. +struct DllInitializer { + DllInitializer() { + pyxpcom_construct(); + } + ~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(); + // for backward compatibility: + Py_nsIComponentManagerObsolete::InitType(); + + } + return rc; +} + diff --git a/src/libs/xpcom18a4/python/src/loader/pyloader.cpp b/src/libs/xpcom18a4/python/src/loader/pyloader.cpp new file mode 100644 index 00000000..dc116f1d --- /dev/null +++ b/src/libs/xpcom18a4/python/src/loader/pyloader.cpp @@ -0,0 +1,435 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * 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 ***** */ + +// pyloader +// +// Not part of the main Python _xpcom package, but a separate, thin DLL. +// +// 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 +// pyxpcom core library and transfers control to that. + +#include <PyXPCOM.h> + +#include "nsDirectoryServiceDefs.h" +#include "nsILocalFile.h" + +#include "nspr.h" // PR_fprintf + +#if (PY_VERSION_HEX >= 0x02030000) +#define PYXPCOM_USE_PYGILSTATE +#endif + +static char *PyTraceback_AsString(PyObject *exc_tb); + +#ifdef XP_WIN +#include "windows.h" +#endif + +#ifdef XP_UNIX +#include <dlfcn.h> +#include <sys/stat.h> + +#endif + +#include "nsITimelineService.h" + +typedef nsresult (*pfnPyXPCOM_NSGetModule)(nsIComponentManager *servMgr, + nsIFile* location, + nsIModule** result); + + +static void LogError(const char *fmt, ...); +static void LogDebug(const char *fmt, ...); + +// Ensure that any paths guaranteed by this package exist on sys.path +// Only called once as we are first loaded into the process. +void AddStandardPaths() +{ + // Put {bin}\Python on the path if it exists. + nsresult rv; + nsCOMPtr<nsIFile> aFile; + rv = NS_GetSpecialDirectory(NS_XPCOM_CURRENT_PROCESS_DIR, getter_AddRefs(aFile)); + if (NS_FAILED(rv)) { + LogError("The Python XPCOM loader could not locate the 'bin' directory\n"); + return; + } + aFile->Append(NS_LITERAL_STRING("python")); + nsAutoString pathBuf; + aFile->GetPath(pathBuf); + PyObject *obPath = PySys_GetObject("path"); + if (!obPath) { + LogError("The Python XPCOM loader could not get the Python sys.path variable\n"); + return; + } + NS_LossyConvertUCS2toASCII pathCBuf(pathBuf); + LogDebug("The Python XPCOM loader is adding '%s' to sys.path\n", pathCBuf.get()); + PyObject *newStr = PyString_FromString(pathCBuf.get()); + PyList_Insert(obPath, 0, newStr); + Py_XDECREF(newStr); + // And now try and get Python to process this directory as a "site dir" + // - ie, look for .pth files, etc + nsCAutoString cmdBuf(NS_LITERAL_CSTRING("import site;site.addsitedir(r'") + pathCBuf + NS_LITERAL_CSTRING("')\n")); + if (0 != PyRun_SimpleString((char *)cmdBuf.get())) { + LogError("The directory '%s' could not be added as a site directory", pathCBuf.get()); + PyErr_Clear(); + } + // and somewhat like Python itself (site, citecustomize), we attempt + // to import "sitepyxpcom" ignoring ImportError + if (NULL==PyImport_ImportModule("sitepyxpcom")) { + if (!PyErr_ExceptionMatches(PyExc_ImportError)) + LogError("Failed to import 'sitepyxpcom'"); + PyErr_Clear(); + } +} + +//////////////////////////////////////////////////////////// +// 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) +{ +#ifdef XP_UNIX + // *sob* - seems necessary to open the .so as RTLD_GLOBAL + dlopen(PYTHON_SO,RTLD_NOW | RTLD_GLOBAL); +#endif + PRBool bDidInitPython = !Py_IsInitialized(); // well, I will next line, anyway :-) + if (bDidInitPython) { + NS_TIMELINE_START_TIMER("PyXPCOM: Python initializing"); + Py_Initialize(); + if (!Py_IsInitialized()) { + LogError("Python initialization failed!\n"); + return NS_ERROR_FAILURE; + } +#ifndef NS_DEBUG + Py_OptimizeFlag = 1; +#endif // NS_DEBUG + PyEval_InitThreads(); + NS_TIMELINE_STOP_TIMER("PyXPCOM: Python initializing"); + NS_TIMELINE_MARK_TIMER("PyXPCOM: Python initializing"); + } + // Get the Python interpreter state + NS_TIMELINE_START_TIMER("PyXPCOM: Python threadstate setup"); +#ifndef PYXPCOM_USE_PYGILSTATE + PyThreadState *threadStateCreated = NULL; + PyThreadState *threadState = PyThreadState_Swap(NULL); + if (threadState==NULL) { + // no thread-state - set one up. + // *sigh* - what I consider a bug is that Python + // will deadlock unless we own the lock before creating + // a new interpreter (it appear Py_NewInterpreter has + // really only been tested/used with no thread lock + PyEval_AcquireLock(); + threadState = threadStateCreated = Py_NewInterpreter(); + PyThreadState_Swap(NULL); + } + PyEval_ReleaseLock(); + PyEval_AcquireThread(threadState); +#else + PyGILState_STATE state = PyGILState_Ensure(); +#endif // PYXPCOM_USE_PYGILSTATE +#ifdef MOZ_TIMELINE + // If the timeline service is installed, see if we can install our hooks. + if (NULL==PyImport_ImportModule("timeline_hook")) { + if (!PyErr_ExceptionMatches(PyExc_ImportError)) + LogError("Failed to import 'timeline_hook'"); + 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!!!) + if (threadStateCreated) { + Py_EndInterpreter(threadStateCreated); + PyEval_ReleaseLock(); // see Py_NewInterpreter call above + } else { + PyEval_ReleaseThread(threadState); + PyThreadState *threadStateSave = PyThreadState_Swap(NULL); + if (threadStateSave) + PyThreadState_Delete(threadStateSave); + } +#else + // If we initialized Python, then we will also have acquired the thread + // lock. In that case, we want to leave it unlocked, so other threads + // are free to run, even if they aren't running Python code. + PyGILState_Release(bDidInitPython ? PyGILState_UNLOCKED : state); +#endif + + 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 = 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; +} + +// The internal helper that actually moves the +// formatted string to the target! + +void LogMessage(const char *prefix, const char *pszMessageText) +{ + PR_fprintf(PR_STDERR, "%s", pszMessageText); +} + +void LogMessage(const char *prefix, nsACString &text) +{ + LogMessage(prefix, nsPromiseFlatCString(text).get()); +} + +// A helper for the various logging routines. +static void VLogF(const char *prefix, const char *fmt, va_list argptr) +{ + char buff[512]; + + vsprintf(buff, fmt, argptr); + + LogMessage(prefix, buff); +} + +static void LogError(const char *fmt, ...) +{ + va_list marker; + va_start(marker, fmt); + VLogF("PyXPCOM Loader Error: ", 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) { + 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 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 convert exception value to a string!"; + } + streamout += "\n"; + LogMessage("PyXPCOM Exception:", streamout); + } + PyErr_Restore(exc_typ, exc_val, exc_tb); + va_end(marker); +} +/*** - not currently used - silence compiler warning. +static void LogWarning(const char *fmt, ...) +{ + va_list marker; + va_start(marker, fmt); + VLogF("PyXPCOM Loader Warning: ", fmt, marker); +} +***/ +#ifdef DEBUG +static void LogDebug(const char *fmt, ...) +{ + va_list marker; + va_start(marker, fmt); + VLogF("PyXPCOM Loader Debug: ", fmt, marker); + va_end(marker); +} +#else +static void LogDebug(const char *fmt, ...) +{ +} +#endif + +/* Obtains a string from a Python traceback. + This is the exact same string as "traceback.print_exc" would return. + + Pass in a Python traceback object (probably obtained from PyErr_Fetch()) + Result is a string which must be free'd using PyMem_Free() +*/ +#define TRACEBACK_FETCH_ERROR(what) {errMsg = what; goto done;} + +char *PyTraceback_AsString(PyObject *exc_tb) +{ + char *errMsg = NULL; /* a static that hold a local error message */ + char *result = NULL; /* a valid, allocated result. */ + PyObject *modStringIO = NULL; + PyObject *modTB = NULL; + PyObject *obFuncStringIO = NULL; + PyObject *obStringIO = NULL; + PyObject *obFuncTB = NULL; + PyObject *argsTB = NULL; + PyObject *obResult = NULL; + + /* Import the modules we need - cStringIO and traceback */ + modStringIO = PyImport_ImportModule("cStringIO"); + if (modStringIO==NULL) + TRACEBACK_FETCH_ERROR("cant import cStringIO\n"); + + modTB = PyImport_ImportModule("traceback"); + if (modTB==NULL) + TRACEBACK_FETCH_ERROR("cant import traceback\n"); + /* Construct a cStringIO object */ + obFuncStringIO = PyObject_GetAttrString(modStringIO, "StringIO"); + if (obFuncStringIO==NULL) + TRACEBACK_FETCH_ERROR("cant find cStringIO.StringIO\n"); + obStringIO = PyObject_CallObject(obFuncStringIO, NULL); + if (obStringIO==NULL) + TRACEBACK_FETCH_ERROR("cStringIO.StringIO() failed\n"); + /* Get the traceback.print_exception function, and call it. */ + obFuncTB = PyObject_GetAttrString(modTB, "print_tb"); + if (obFuncTB==NULL) + TRACEBACK_FETCH_ERROR("cant find traceback.print_tb\n"); + + argsTB = Py_BuildValue("OOO", + exc_tb ? exc_tb : Py_None, + Py_None, + obStringIO); + if (argsTB==NULL) + TRACEBACK_FETCH_ERROR("cant make print_tb arguments\n"); + + obResult = PyObject_CallObject(obFuncTB, argsTB); + if (obResult==NULL) + TRACEBACK_FETCH_ERROR("traceback.print_tb() failed\n"); + /* Now call the getvalue() method in the StringIO instance */ + Py_DECREF(obFuncStringIO); + obFuncStringIO = PyObject_GetAttrString(obStringIO, "getvalue"); + if (obFuncStringIO==NULL) + TRACEBACK_FETCH_ERROR("cant find getvalue function\n"); + Py_DECREF(obResult); + obResult = PyObject_CallObject(obFuncStringIO, NULL); + if (obResult==NULL) + TRACEBACK_FETCH_ERROR("getvalue() failed.\n"); + + /* And it should be a string all ready to go - duplicate it. */ + if (!PyString_Check(obResult)) + TRACEBACK_FETCH_ERROR("getvalue() did not return a string\n"); + + { // a temp scope so I can use temp locals. + char *tempResult = PyString_AsString(obResult); + result = (char *)PyMem_Malloc(strlen(tempResult)+1); + if (result==NULL) + TRACEBACK_FETCH_ERROR("memory error duplicating the traceback string"); + + strcpy(result, tempResult); + } // end of temp scope. +done: + /* All finished - first see if we encountered an error */ + if (result==NULL && errMsg != NULL) { + result = (char *)PyMem_Malloc(strlen(errMsg)+1); + if (result != NULL) + /* if it does, not much we can do! */ + strcpy(result, errMsg); + } + Py_XDECREF(modStringIO); + Py_XDECREF(modTB); + Py_XDECREF(obFuncStringIO); + Py_XDECREF(obStringIO); + Py_XDECREF(obFuncTB); + Py_XDECREF(argsTB); + Py_XDECREF(obResult); + return result; +} diff --git a/src/libs/xpcom18a4/python/src/module/_xpcom.cpp b/src/libs/xpcom18a4/python/src/module/_xpcom.cpp new file mode 100644 index 00000000..d40d2b52 --- /dev/null +++ b/src/libs/xpcom18a4/python/src/module/_xpcom.cpp @@ -0,0 +1,950 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * 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 ***** */ + +// +// This code is part of the XPCOM extensions for Python. +// +// Written May 2000 by Mark Hammond. +// +// Based heavily on the Python COM support, which is +// (c) Mark Hammond and Greg Stein. +// +// (c) 2000, ActiveState corp. + +#include "PyXPCOM.h" +#include "nsXPCOM.h" +#include "nsISupportsPrimitives.h" +#include "nsIFile.h" +#include "nsIComponentRegistrar.h" +#include "nsIComponentManagerObsolete.h" +#include "nsIConsoleService.h" +#include "nspr.h" // PR_fprintf +#ifdef VBOX +# include "nsEventQueueUtils.h" +#endif + +#ifdef XP_WIN +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#include "windows.h" +#endif + +#include "nsIEventQueue.h" +#include "nsIProxyObjectManager.h" + +#define LOADER_LINKS_WITH_PYTHON + +#ifndef PYXPCOM_USE_PYGILSTATE +extern PYXPCOM_EXPORT void PyXPCOM_InterpreterState_Ensure(); +#endif + +#ifdef VBOX_PYXPCOM +# include <iprt/cdefs.h> +# include <VBox/com/com.h> +# ifndef MODULE_NAME_SUFFIX +# define MANGLE_MODULE_NAME(a_szName) a_szName +# define MANGLE_MODULE_INIT(a_Name) a_Name +# else +# define MANGLE_MODULE_NAME(a_szName) a_szName RT_XSTR(MODULE_NAME_SUFFIX) +# define MANGLE_MODULE_INIT(a_Name) RT_CONCAT(a_Name, MODULE_NAME_SUFFIX) +# endif +# if defined(VBOX_PYXPCOM_VERSIONED) && !defined(VBOX_PYXPCOM_MAJOR_VERSIONED) +# if PY_VERSION_HEX >= 0x030a0000 && PY_VERSION_HEX < 0x030b0000 +# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_10") +# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_10) + +# elif PY_VERSION_HEX >= 0x03090000 && PY_VERSION_HEX < 0x030a0000 +# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_9") +# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_9) + +# elif PY_VERSION_HEX >= 0x03080000 && PY_VERSION_HEX < 0x03090000 +# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_8") +# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_8) + +# elif PY_VERSION_HEX >= 0x03070000 && PY_VERSION_HEX < 0x03080000 +# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_7") +# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_7) + +# elif PY_VERSION_HEX >= 0x03060000 && PY_VERSION_HEX < 0x03070000 +# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_6") +# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_6) + +# elif PY_VERSION_HEX >= 0x03050000 && PY_VERSION_HEX < 0x03060000 +# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_5") +# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_5) + +# elif PY_VERSION_HEX >= 0x03040000 && PY_VERSION_HEX < 0x03050000 +# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_4") +# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_4) + +# elif PY_VERSION_HEX >= 0x03030000 && PY_VERSION_HEX < 0x03040000 +# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_3") +# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_3) + +# elif PY_VERSION_HEX >= 0x03020000 && PY_VERSION_HEX < 0x03030000 +# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_2") +# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_2) + +# elif PY_VERSION_HEX >= 0x03010000 && PY_VERSION_HEX < 0x03020000 +# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3_1") +# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3_1) + +# elif PY_VERSION_HEX >= 0x02080000 && PY_VERSION_HEX < 0x02090000 +# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython2_8") +# define initVBoxPython MANGLE_MODULE_INIT(initVBoxPython2_8) + +# elif PY_VERSION_HEX >= 0x02070000 && PY_VERSION_HEX < 0x02080000 +# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython2_7") +# define initVBoxPython MANGLE_MODULE_INIT(initVBoxPython2_7) + +# elif PY_VERSION_HEX >= 0x02060000 && PY_VERSION_HEX < 0x02070000 +# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython2_6") +# define initVBoxPython MANGLE_MODULE_INIT(initVBoxPython2_6) +# else +# error "Fix module versioning. This Python version is not recognized." +# endif +# else +# if PY_MAJOR_VERSION <= 2 && defined(VBOX_PYXPCOM_MAJOR_VERSIONED) +# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython2") +# define initVBoxPython MANGLE_MODULE_INIT(initVBoxPython2) +# elif PY_MAJOR_VERSION <= 2 +# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython") +# define initVBoxPython MANGLE_MODULE_INIT(initVBoxPython) +# elif defined(Py_LIMITED_API) || defined(VBOX_PYXPCOM_MAJOR_VERSIONED) +# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython3") +# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython3) +# else +# define MODULE_NAME MANGLE_MODULE_NAME("VBoxPython") +# define initVBoxPython MANGLE_MODULE_INIT(PyInit_VBoxPython) +# endif +# endif +#else +#define MODULE_NAME "_xpcom" +#endif + +// "boot-strap" methods - interfaces we need to get the base +// interface support! + +#ifndef VBOX +/* deprecated, included for backward compatibility */ +static PyObject * +PyXPCOMMethod_NS_GetGlobalComponentManager(PyObject *self, PyObject *args) +{ + if (PyErr_Warn(PyExc_DeprecationWarning, "Use GetComponentManager instead") < 0) + return NULL; + if (!PyArg_ParseTuple(args, "")) + return NULL; + nsCOMPtr<nsIComponentManager> cm; + nsresult rv; + Py_BEGIN_ALLOW_THREADS; + rv = NS_GetComponentManager(getter_AddRefs(cm)); + Py_END_ALLOW_THREADS; + if ( NS_FAILED(rv) ) + return PyXPCOM_BuildPyException(rv); + + nsCOMPtr<nsIComponentManagerObsolete> ocm(do_QueryInterface(cm, &rv)); + if ( NS_FAILED(rv) ) + return PyXPCOM_BuildPyException(rv); + + return Py_nsISupports::PyObjectFromInterface(ocm, NS_GET_IID(nsIComponentManagerObsolete), PR_FALSE); +} +#endif + +static PyObject * +PyXPCOMMethod_GetComponentManager(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + nsCOMPtr<nsIComponentManager> cm; + nsresult rv; + Py_BEGIN_ALLOW_THREADS; + 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); +} + +// 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 * +PyXPCOMMethod_GetServiceManager(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + nsCOMPtr<nsIServiceManager> sm; + nsresult rv; + Py_BEGIN_ALLOW_THREADS; + 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)); +} + +#ifndef VBOX +/* deprecated, included for backward compatibility */ +static PyObject * +PyXPCOMMethod_GetGlobalServiceManager(PyObject *self, PyObject *args) +{ + if (PyErr_Warn(PyExc_DeprecationWarning, "Use GetServiceManager instead") < 0) + return NULL; + + return PyXPCOMMethod_GetComponentManager(self, args); +} +#endif + +static PyObject * +PyXPCOMMethod_XPTI_GetInterfaceInfoManager(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, "")) + return NULL; + nsIInterfaceInfoManager* im; + Py_BEGIN_ALLOW_THREADS; + im = XPTI_GetInterfaceInfoManager(); + Py_END_ALLOW_THREADS; + if ( im == nsnull ) + return PyXPCOM_BuildPyException(NS_ERROR_FAILURE); + + /* 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. + PyObject *ret = Py_nsISupports::PyObjectFromInterface(im, NS_GET_IID(nsIInterfaceInfoManager), PR_FALSE); + NS_IF_RELEASE(im); + return ret; +} + +static PyObject * +PyXPCOMMethod_XPTC_InvokeByIndex(PyObject *self, PyObject *args) +{ + PyObject *obIS, *obParams; + nsCOMPtr<nsISupports> pis; + int index; + + // We no longer rely on PyErr_Occurred() for our error state, + // but keeping this assertion can't hurt - it should still always be true! + NS_WARN_IF_FALSE(!PyErr_Occurred(), "Should be no pending Python error!"); + + 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)", + PyXPCOM_ObTypeName(obIS)); + } + // 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, + // will return the "original" gateway when QI'd for nsISupports) + if (!Py_nsISupports::InterfaceFromPyObject( + obIS, + Py_nsIID_NULL, + getter_AddRefs(pis), + PR_FALSE)) + return NULL; + + PyXPCOM_InterfaceVariantHelper arg_helper((Py_nsISupports *)obIS, index); + if (!arg_helper.Init(obParams)) + return NULL; + + if (!arg_helper.FillArray()) + return NULL; + + nsresult r; + Py_BEGIN_ALLOW_THREADS; + r = XPTC_InvokeByIndex(pis, index, arg_helper.m_num_array, arg_helper.m_var_array); +/** @todo bird: Maybe we could processing pending XPCOM events here to make + * life a bit simpler inside python? */ + Py_END_ALLOW_THREADS; + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + + return arg_helper.MakePythonResult(); +} + +static PyObject * +PyXPCOMMethod_WrapObject(PyObject *self, PyObject *args) +{ + PyObject *ob, *obIID; + int bWrapClient = 1; + if (!PyArg_ParseTuple(args, "OO|i", &ob, &obIID, &bWrapClient)) + return NULL; + + nsIID iid; + if (!Py_nsIID::IIDFromPyObject(obIID, &iid)) + return NULL; + + nsCOMPtr<nsISupports> ret; + nsresult r = PyXPCOM_XPTStub::CreateNew(ob, iid, getter_AddRefs(ret)); + if ( NS_FAILED(r) ) + return PyXPCOM_BuildPyException(r); + + // _ALL_ wrapped objects are associated with a weak-ref + // to their "main" instance. + AddDefaultGateway(ob, ret); // inject a weak reference to myself into the instance. + + // Now wrap it in an interface. + return Py_nsISupports::PyObjectFromInterface(ret, iid, bWrapClient); +} + +static PyObject * +PyXPCOMMethod_UnwrapObject(PyObject *self, PyObject *args) +{ + PyObject *ob; + if (!PyArg_ParseTuple(args, "O", &ob)) + return NULL; + + nsISupports *uob = NULL; + nsIInternalPython *iob = NULL; + PyObject *ret = NULL; + if (!Py_nsISupports::InterfaceFromPyObject(ob, + NS_GET_IID(nsISupports), + &uob, + PR_FALSE)) + goto done; + if (NS_FAILED(uob->QueryInterface(NS_GET_IID(nsIInternalPython), reinterpret_cast<void **>(&iob)))) { + PyErr_SetString(PyExc_ValueError, "This XPCOM object is not implemented by Python"); + goto done; + } + ret = iob->UnwrapPythonObject(); +done: + Py_BEGIN_ALLOW_THREADS; + NS_IF_RELEASE(uob); + NS_IF_RELEASE(iob); + Py_END_ALLOW_THREADS; + return ret; +} + +// @pymethod int|pythoncom|_GetInterfaceCount|Retrieves the number of interface objects currently in existance +static PyObject * +PyXPCOMMethod_GetInterfaceCount(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, ":_GetInterfaceCount")) + return NULL; + return PyInt_FromLong(_PyXPCOM_GetInterfaceCount()); + // @comm If is occasionally a good idea to call this function before your Python program + // terminates. If this function returns non-zero, then you still have PythonCOM objects + // alive in your program (possibly in global variables). +} + +#ifdef VBOX_DEBUG_LIFETIMES +// @pymethod int|pythoncom|_DumpInterfaces|Dumps the interfaces still in existance to standard output +static PyObject * +PyXPCOMMethod_DumpInterfaces(PyObject *self, PyObject *args) +{ + if (!PyArg_ParseTuple(args, ":_DumpInterfaces")) + return NULL; + return PyInt_FromLong(_PyXPCOM_DumpInterfaces()); +} +#endif + +// @pymethod int|pythoncom|_GetGatewayCount|Retrieves the number of gateway objects currently in existance +static PyObject * +PyXPCOMMethod_GetGatewayCount(PyObject *self, PyObject *args) +{ + // @comm This is the number of Python object that implement COM servers which + // are still alive (ie, serving a client). The only way to reduce this count + // is to have the process which uses these PythonCOM servers release its references. + if (!PyArg_ParseTuple(args, ":_GetGatewayCount")) + return NULL; + return PyInt_FromLong(_PyXPCOM_GetGatewayCount()); +} + +static PyObject * +PyXPCOMMethod_NS_ShutdownXPCOM(PyObject *self, PyObject *args) +{ + // @comm This is the number of Python object that implement COM servers which + // are still alive (ie, serving a client). The only way to reduce this count + // is to have the process which uses these PythonCOM servers release its references. + if (!PyArg_ParseTuple(args, ":NS_ShutdownXPCOM")) + return NULL; + nsresult nr; + Py_BEGIN_ALLOW_THREADS; + nr = NS_ShutdownXPCOM(nsnull); + Py_END_ALLOW_THREADS; + +#ifdef VBOX_DEBUG_LIFETIME + Py_nsISupports::dumpList(); +#endif + + // Dont raise an exception - as we are probably shutting down + // and dont really case - just return the status + return PyInt_FromLong(nr); +} + +static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID); + +// A hack to work around their magic constants! +static PyObject * +PyXPCOMMethod_GetProxyForObject(PyObject *self, PyObject *args) +{ + PyObject *obQueue, *obIID, *obOb; + int flags; + if (!PyArg_ParseTuple(args, "OOOi", &obQueue, &obIID, &obOb, &flags)) + return NULL; + nsIID iid; + if (!Py_nsIID::IIDFromPyObject(obIID, &iid)) + return NULL; + nsCOMPtr<nsISupports> pob; + if (!Py_nsISupports::InterfaceFromPyObject(obOb, iid, getter_AddRefs(pob), PR_FALSE)) + return NULL; + nsIEventQueue *pQueue = NULL; + nsIEventQueue *pQueueRelease = NULL; + + if (PyInt_Check(obQueue)) { + pQueue = (nsIEventQueue *)PyInt_AsLong(obQueue); + } else { + if (!Py_nsISupports::InterfaceFromPyObject(obQueue, NS_GET_IID(nsIEventQueue), (nsISupports **)&pQueue, PR_TRUE)) + return NULL; + pQueueRelease = pQueue; + } + + nsresult rv_proxy; + nsCOMPtr<nsISupports> presult; + Py_BEGIN_ALLOW_THREADS; + nsCOMPtr<nsIProxyObjectManager> proxyMgr = + do_GetService(kProxyObjectManagerCID, &rv_proxy); + + if ( NS_SUCCEEDED(rv_proxy) ) { + rv_proxy = proxyMgr->GetProxyForObject(pQueue, + iid, + pob, + flags, + getter_AddRefs(presult)); + } + if (pQueueRelease) + pQueueRelease->Release(); + Py_END_ALLOW_THREADS; + + PyObject *result; + if (NS_SUCCEEDED(rv_proxy) ) { + 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)", + PyXPCOM_ObTypeName(ob)); + + 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; + 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)); +} + +PyObject *AllocateBuffer(PyObject *self, PyObject *args) +{ + int bufSize; + if (!PyArg_ParseTuple(args, "i", &bufSize)) + return NULL; +#if PY_MAJOR_VERSION <= 2 + return PyBuffer_New(bufSize); +#else + return PyBytes_FromStringAndSize(NULL, bufSize); +#endif +} + +// 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; + + 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; +} + +#ifdef VBOX + +# include <VBox/com/NativeEventQueue.h> +# include <iprt/err.h> + +static PyObject * +PyXPCOMMethod_WaitForEvents(PyObject *self, PyObject *args) +{ + long lTimeout; + if (!PyArg_ParseTuple(args, "l", &lTimeout)) + return NULL; + + int rc; + com::NativeEventQueue* aEventQ = com::NativeEventQueue::getMainEventQueue(); + NS_WARN_IF_FALSE(aEventQ != nsnull, "Null main event queue"); + if (!aEventQ) + { + PyErr_SetString(PyExc_TypeError, "the main event queue is NULL"); + return NULL; + } + + Py_BEGIN_ALLOW_THREADS + + RTMSINTERVAL cMsTimeout = (RTMSINTERVAL)lTimeout; + if (lTimeout < 0 || (long)cMsTimeout != lTimeout) + cMsTimeout = RT_INDEFINITE_WAIT; + rc = aEventQ->processEventQueue(cMsTimeout); + + Py_END_ALLOW_THREADS + if (RT_SUCCESS(rc)) + return PyInt_FromLong(0); + + if ( rc == VERR_TIMEOUT + || rc == VERR_INTERRUPTED) + return PyInt_FromLong(1); + + if (rc == VERR_INVALID_CONTEXT) + { + PyErr_SetString(PyExc_Exception, "wrong thread, use the main thread"); + return NULL; + } + + return PyInt_FromLong(2); +} + +static PyObject* +PyXPCOMMethod_InterruptWait(PyObject *self, PyObject *args) +{ + com::NativeEventQueue* aEventQ = com::NativeEventQueue::getMainEventQueue(); + NS_WARN_IF_FALSE(aEventQ != nsnull, "Null main event queue"); + if (!aEventQ) + return NULL; + + int rc = aEventQ->interruptEventQueueProcessing(); + return PyBool_FromLong(RT_SUCCESS(rc)); +} + +static nsresult deinitVBoxPython(); + +static PyObject* +PyXPCOMMethod_DeinitCOM(PyObject *self, PyObject *args) +{ + nsresult nr; + Py_BEGIN_ALLOW_THREADS; + nr = deinitVBoxPython(); + Py_END_ALLOW_THREADS; + return PyInt_FromLong(nr); +} + +static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); + +static PyObject* +PyXPCOMMethod_AttachThread(PyObject *self, PyObject *args) +{ + nsresult rv; + PRInt32 result = 0; + nsCOMPtr<nsIEventQueueService> eqs; + + // Create the Event Queue for this thread... + Py_BEGIN_ALLOW_THREADS; + eqs = + do_GetService(kEventQueueServiceCID, &rv); + Py_END_ALLOW_THREADS; + if (NS_FAILED(rv)) + { + result = 1; + goto done; + } + + Py_BEGIN_ALLOW_THREADS; + rv = eqs->CreateThreadEventQueue(); + Py_END_ALLOW_THREADS; + if (NS_FAILED(rv)) + { + result = 2; + goto done; + } + + done: + /** @todo: better throw an exception on error */ + return PyInt_FromLong(result); +} + +static PyObject* +PyXPCOMMethod_DetachThread(PyObject *self, PyObject *args) +{ + nsresult rv; + PRInt32 result = 0; + nsCOMPtr<nsIEventQueueService> eqs; + + // Destroy the Event Queue for this thread... + Py_BEGIN_ALLOW_THREADS; + eqs = + do_GetService(kEventQueueServiceCID, &rv); + Py_END_ALLOW_THREADS; + if (NS_FAILED(rv)) + { + result = 1; + goto done; + } + + Py_BEGIN_ALLOW_THREADS; + rv = eqs->DestroyThreadEventQueue(); + Py_END_ALLOW_THREADS; + if (NS_FAILED(rv)) + { + result = 2; + goto done; + } + + done: + /** @todo: better throw an exception on error */ + return PyInt_FromLong(result); +} + +#endif /* VBOX */ + +extern PYXPCOM_EXPORT PyObject *PyXPCOMMethod_IID(PyObject *self, PyObject *args); + +static struct PyMethodDef xpcom_methods[]= +{ + {"GetComponentManager", PyXPCOMMethod_GetComponentManager, 1}, + {"GetComponentRegistrar", PyXPCOMMethod_GetComponentRegistrar, 1}, +#ifndef VBOX + {"NS_GetGlobalComponentManager", PyXPCOMMethod_NS_GetGlobalComponentManager, 1}, // deprecated +#endif + {"XPTI_GetInterfaceInfoManager", PyXPCOMMethod_XPTI_GetInterfaceInfoManager, 1}, + {"XPTC_InvokeByIndex", PyXPCOMMethod_XPTC_InvokeByIndex, 1}, + {"GetServiceManager", PyXPCOMMethod_GetServiceManager, 1}, +#ifndef VBOX + {"GetGlobalServiceManager", PyXPCOMMethod_GetGlobalServiceManager, 1}, // deprecated + {"IID", PyXPCOMMethod_IID, 1}, // IID is wrong - deprecated - not just IID, but CID, etc. +#endif + {"ID", PyXPCOMMethod_IID, 1}, // This is the official name. + {"NS_ShutdownXPCOM", PyXPCOMMethod_NS_ShutdownXPCOM, 1}, + {"WrapObject", PyXPCOMMethod_WrapObject, 1}, + {"UnwrapObject", PyXPCOMMethod_UnwrapObject, 1}, + {"_GetInterfaceCount", PyXPCOMMethod_GetInterfaceCount, 1}, + {"_GetGatewayCount", PyXPCOMMethod_GetGatewayCount, 1}, + {"getProxyForObject", PyXPCOMMethod_GetProxyForObject, 1}, + {"GetProxyForObject", PyXPCOMMethod_GetProxyForObject, 1}, + {"GetSpecialDirectory", PyGetSpecialDirectory, 1}, + {"AllocateBuffer", AllocateBuffer, 1}, + {"LogConsoleMessage", LogConsoleMessage, 1, "Write a message to the xpcom console service"}, + {"MakeVariant", PyXPCOMMethod_MakeVariant, 1}, + {"GetVariantValue", PyXPCOMMethod_GetVariantValue, 1}, +#ifdef VBOX + {"WaitForEvents", PyXPCOMMethod_WaitForEvents, 1}, + {"InterruptWait", PyXPCOMMethod_InterruptWait, 1}, + {"DeinitCOM", PyXPCOMMethod_DeinitCOM, 1}, + {"AttachThread", PyXPCOMMethod_AttachThread, 1}, + {"DetachThread", PyXPCOMMethod_DetachThread, 1}, +#endif +#ifdef VBOX_DEBUG_LIFETIMES + {"_DumpInterfaces", PyXPCOMMethod_DumpInterfaces, 1}, +#endif + // These should no longer be used - just use the logging.getLogger('pyxpcom')... + /* bird: The above comment refers to LogWarning and LogError. Both now removed. */ + { NULL } +}; + +#if PY_MAJOR_VERSION >= 3 +static struct PyModuleDef xpcom_module = +{ + PyModuleDef_HEAD_INIT, + MODULE_NAME, /* name of module */ + NULL, /* module documentation */ + -1, /* size of per-interpreter state or -1 if using globals */ + xpcom_methods +}; +#endif + + +#define REGISTER_IID(t) { \ + PyObject *iid_ob = Py_nsIID::PyObjectFromIID(NS_GET_IID(t)); \ + PyDict_SetItemString(dict, "IID_"#t, iid_ob); \ + Py_DECREF(iid_ob); \ + } + +#define REGISTER_INT(val) { \ + PyObject *ob = PyInt_FromLong(val); \ + PyDict_SetItemString(dict, #val, ob); \ + Py_DECREF(ob); \ + } + + +//////////////////////////////////////////////////////////// +// The module init code. +// +#if PY_MAJOR_VERSION <= 2 +extern "C" NS_EXPORT +void +#else +PyObject * +#endif +init_xpcom() { + PyObject *oModule; + + // ensure the framework has valid state to work with. + if (!PyXPCOM_Globals_Ensure()) +#if PY_MAJOR_VERSION <= 2 + return; +#else + return NULL; +#endif + + // Must force Python to start using thread locks + PyEval_InitThreads(); + + // Create the module and add the functions +#if PY_MAJOR_VERSION <= 2 + oModule = Py_InitModule(MODULE_NAME, xpcom_methods); +#else + oModule = PyModule_Create(&xpcom_module); +#endif + + PyObject *dict = PyModule_GetDict(oModule); + PyObject *pycom_Error = PyXPCOM_Error; + if (pycom_Error == NULL || PyDict_SetItemString(dict, "error", pycom_Error) != 0) + { + PyErr_SetString(PyExc_MemoryError, "can't define error"); +#if PY_MAJOR_VERSION <= 2 + return; +#else + return NULL; +#endif + } +#ifndef Py_LIMITED_API + PyDict_SetItemString(dict, "IIDType", (PyObject *)&Py_nsIID::type); +#else + PyDict_SetItemString(dict, "IIDType", (PyObject *)Py_nsIID::GetTypeObject()); +#endif + + REGISTER_IID(nsISupports); + REGISTER_IID(nsISupportsCString); + REGISTER_IID(nsISupportsString); + REGISTER_IID(nsIModule); + REGISTER_IID(nsIFactory); + REGISTER_IID(nsIWeakReference); + REGISTER_IID(nsISupportsWeakReference); + 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); + + // 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); +#if PY_MAJOR_VERSION >= 3 + return oModule; +#endif +} + +#ifdef VBOX_PYXPCOM +# include <VBox/com/com.h> +using namespace com; + +# include <iprt/initterm.h> +# include <iprt/string.h> +# include <iprt/alloca.h> +# include <iprt/stream.h> + +/** Set if NS_ShutdownXPCOM has been called successfully already and we don't + * need to do it again during module termination. This avoids assertion in the + * VBoxCOM glue code. */ +static bool g_fComShutdownAlready = true; + +# if PY_MAJOR_VERSION <= 2 +extern "C" NS_EXPORT +void +# else +/** @todo r=klaus this is hacky, but as Python3 doesn't deal with ELF + * visibility, assuming that all globals are visible (which is ugly and not + * true in our case). */ +# undef PyMODINIT_FUNC +# define PyMODINIT_FUNC extern "C" NS_EXPORT PyObject* +PyMODINIT_FUNC +# endif +initVBoxPython() { /* NOTE! This name is redefined at the top of the file! */ + static bool s_vboxInited = false; + if (!s_vboxInited) { + int rc = 0; /* Error handling in this code is NON-EXISTING. Sigh. */ + +# if defined(VBOX_PATH_APP_PRIVATE_ARCH) && defined(VBOX_PATH_SHARED_LIBS) + rc = RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE); +# else + const char *home = getenv("VBOX_PROGRAM_PATH"); + if (home) { + size_t len = strlen(home); + char *exepath = (char *)alloca(len + 32); + memcpy(exepath, home, len); + memcpy(exepath + len, "/pythonfake", sizeof("/pythonfake")); + rc = RTR3InitEx(RTR3INIT_VER_CUR, RTR3INIT_FLAGS_DLL | RTR3INIT_FLAGS_UNOBTRUSIVE, 0, NULL, exepath); + } else { + rc = RTR3InitDll(RTR3INIT_FLAGS_UNOBTRUSIVE); + } +# endif + + rc = com::Initialize(); + g_fComShutdownAlready = false; + +# if PY_MAJOR_VERSION <= 2 + init_xpcom(); +# else + return init_xpcom(); +# endif + } +# if PY_MAJOR_VERSION >= 3 + return NULL; +# endif +} + +static +nsresult deinitVBoxPython() +{ + nsresult nr; + if (!g_fComShutdownAlready) + { + nr = com::Shutdown(); + if (!NS_FAILED(nr)) + g_fComShutdownAlready = true; + } + else + nr = NS_ERROR_NOT_INITIALIZED; + return nr; +} + +#endif /* VBOX_PYXPCOM */ diff --git a/src/libs/xpcom18a4/python/src/readme.html b/src/libs/xpcom18a4/python/src/readme.html new file mode 100644 index 00000000..b049dbad --- /dev/null +++ b/src/libs/xpcom18a4/python/src/readme.html @@ -0,0 +1,99 @@ +<!-- ***** 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 PyXPCOM. + - + - The Initial Developer of the Original Code is + - ActiveState Tool Corporation. + - Portions created by the Initial Developer are Copyright (C) 2000-2001 + - the Initial Developer. All Rights Reserved. + - + - Contributor(s): + - + - 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 LGPL or the GPL. 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 ***** --> + +<html> + +<head> +<meta http-equiv="Content-Type" content="text/html; charset=windows-1252"> +<meta name="GENERATOR" content="Microsoft FrontPage 4.0"> +<meta name="ProgId" content="FrontPage.Editor.Document"> +<title>Building the Python XPCOM package</title> +</head> + +<body> + +<h1>Building the Python XPCOM package.</h1> + +<p>This file describes how to build the Python XPCOM C++ sources.</p> +<p>There are the following steps</p> +<ul> + <li><a href="#ConfiguringTheEnvironment">Configure environment variables</a></li> + <li><a href="#BuildingTheSources">Building the sources</a></li> +</ul> +<p>Testing etc is described in the <a href="../readme.html">main readme</a>.</p> +<h2><a name="ConfiguringTheEnvironment">Configuring environment variables</a></h2> +<h3> MOZ_SRC </h3> +<p><b>Windows: </b>Run the standard MOZENV.BAT used to build Mozilla. This +sets MOZ_SRC</p> +<p><b>Unix:</b> Set MOZ_SRC to point to the base source directory - assumes +"mozilla" sub-directory with mozilla directory tree under that. eg: assuming +<i>/home/user/src/mozilla/dist/...</i>"</p> +<pre>export MOZ_SRC=/home/user/src</pre> +<h3>PYTHON_SRC</h3> +<p><b>Windows:</b> Set <i> PYTHON_SRC</i> to point to the base Python source directory. +eg: assuming <i>c:\src\python\PCBuild\...</i><pre>set PYTHON_SRC=c:\src\python</pre> +<p>Unix: Set PYTHON_SRC to point to the base of an "installed" Python +tree. eg:<pre>export PYTHON_SRC=/usr/local/ActivePython-1.6</pre> +<h2><a name="BuildingTheSources">Building the sources</a></h2> +<p>You must ensure some environment variables are setup. The section on <a href="#ConfiguringTheEnvironment">configuring +environment variables explains how.</a></p> +<p>There are 2 build processes to run All C++ sources are in the <i>xpcom\src</i> + directory.:</p> +<h3>Windows</h3> +<ul> + <li> Execute "compile.py" in this directory. This will take <i>Setup.in</i>, create an MSDev project, and build + <i>..\_xpcom.pyd</i> and <i>..\_xpcom_d.pyd</i>"</li> + <li> Change to the <i>loader</i> directory.</li> + <li> Run <i>nmake -f makefile.win</i>. This will create <i>pyloader.dll</i>, and + automatically copy it to the Mozilla build directory.</li> + <a href="#ConfiguringTheEnvironment"> + </ul> + <p>Finally, </a><a href="../readme.html#RunningTheTests">run the tests</a>, + where we also test everything imports correctly.</p> +<h3>Linux</h3> +<p><b> NOTE:</b> Do not attempt to use "Setup.in" to create a Makefile </p> +<ul> + <li>Run "make" in this directory. This will create <i>../_xpcommodule.so</i></li> + <li> Run "make" in the loader directory. This will create <i>libpyloader.so</i>, + and copy it to the Mozilla directory.</li> + <a href="#ConfiguringTheEnvironment"> + </ul> + <p>Finally, </a><a href="../readme.html#RunningTheTests">running the tests</a>, + where we also test everything imports correctly.</p> + +</body> + +</html> diff --git a/src/libs/xpcom18a4/python/test/.cvsignore b/src/libs/xpcom18a4/python/test/.cvsignore new file mode 100644 index 00000000..52e4e611 --- /dev/null +++ b/src/libs/xpcom18a4/python/test/.cvsignore @@ -0,0 +1,2 @@ +*.pyc +*.pyo diff --git a/src/libs/xpcom18a4/python/test/output/test_com_exceptions b/src/libs/xpcom18a4/python/test/output/test_com_exceptions new file mode 100644 index 00000000..16e4bda1 --- /dev/null +++ b/src/libs/xpcom18a4/python/test/output/test_com_exceptions @@ -0,0 +1,8 @@ +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 diff --git a/src/libs/xpcom18a4/python/test/output/test_comfile b/src/libs/xpcom18a4/python/test/output/test_comfile new file mode 100644 index 00000000..8de43add --- /dev/null +++ b/src/libs/xpcom18a4/python/test/output/test_comfile @@ -0,0 +1,7 @@ +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. diff --git a/src/libs/xpcom18a4/python/test/output/test_components b/src/libs/xpcom18a4/python/test/output/test_components new file mode 100644 index 00000000..4a6386e7 --- /dev/null +++ b/src/libs/xpcom18a4/python/test/output/test_components @@ -0,0 +1,4 @@ +test_components +The interfaces object appeared to work! +The classes object appeared to work! +The ID function appeared to work! diff --git a/src/libs/xpcom18a4/python/test/output/test_isupports_primitives b/src/libs/xpcom18a4/python/test/output/test_isupports_primitives new file mode 100644 index 00000000..7765ac21 --- /dev/null +++ b/src/libs/xpcom18a4/python/test/output/test_isupports_primitives @@ -0,0 +1,2 @@ +test_isupports_primitives +The nsISupports primitive interface tests appeared to work diff --git a/src/libs/xpcom18a4/python/test/output/test_streams b/src/libs/xpcom18a4/python/test/output/test_streams new file mode 100644 index 00000000..e81ef151 --- /dev/null +++ b/src/libs/xpcom18a4/python/test/output/test_streams @@ -0,0 +1 @@ +test_streams diff --git a/src/libs/xpcom18a4/python/test/output/test_test_component b/src/libs/xpcom18a4/python/test/output/test_test_component new file mode 100644 index 00000000..c57c1325 --- /dev/null +++ b/src/libs/xpcom18a4/python/test/output/test_test_component @@ -0,0 +1,4 @@ +test_test_component +Testing the Python.TestComponent component +The Python test component worked! +Javascript could successfully use the Python test component. diff --git a/src/libs/xpcom18a4/python/test/output/test_weakreferences b/src/libs/xpcom18a4/python/test/output/test_weakreferences new file mode 100644 index 00000000..b337d26a --- /dev/null +++ b/src/libs/xpcom18a4/python/test/output/test_weakreferences @@ -0,0 +1,2 @@ +test_weakreferences +Weak-reference tests appear to have worked! diff --git a/src/libs/xpcom18a4/python/test/pyxpcom_test_tools.py b/src/libs/xpcom18a4/python/test/pyxpcom_test_tools.py new file mode 100755 index 00000000..447c5446 --- /dev/null +++ b/src/libs/xpcom18a4/python/test/pyxpcom_test_tools.py @@ -0,0 +1,126 @@ +# 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 +# over implies a leak. + +try: + import win32api + import win32pdh + import win32pdhutil + have_pdh = 1 +except ImportError: + have_pdh = 0 + +# XXX - win32pdh is slow, particularly finding our current process. +# A better way would be good. + +# Our win32pdh specific functions - they can be at the top-level on all +# platforms, but will only actually be called if the modules are available. +def FindMyCounter(): + pid_me = win32api.GetCurrentProcessId() + + object = "Process" + items, instances = win32pdh.EnumObjectItems(None,None,object, -1) + for instance in instances: + # We use 2 counters - "ID Process" and "Working Set" + counter = "ID Process" + format = win32pdh.PDH_FMT_LONG + + hq = win32pdh.OpenQuery() + path = win32pdh.MakeCounterPath( (None,object,instance, None, -1,"ID Process") ) + hc1 = win32pdh.AddCounter(hq, path) + path = win32pdh.MakeCounterPath( (None,object,instance, None, -1,"Working Set") ) + hc2 = win32pdh.AddCounter(hq, path) + win32pdh.CollectQueryData(hq) + type, pid = win32pdh.GetFormattedCounterValue(hc1, format) + if pid==pid_me: + win32pdh.RemoveCounter(hc1) # not needed any more + return hq, hc2 + # Not mine - close the query and try again + win32pdh.RemoveCounter(hc1) + win32pdh.RemoveCounter(hc2) + win32pdh.CloseQuery(hq) + else: + raise RuntimeError, "Can't find myself!?" + +def CloseCounter(hq, hc): + win32pdh.RemoveCounter(hc) + win32pdh.CloseQuery(hq) + +def GetCounterValue(hq, hc): + win32pdh.CollectQueryData(hq) + format = win32pdh.PDH_FMT_LONG + type, val = win32pdh.GetFormattedCounterValue(hc, format) + return val + +g_pdh_data = None +# The pdh function that does the work +def pdh_getmemusage(): + global g_pdh_data + if g_pdh_data is None: + hq, hc = FindMyCounter() + g_pdh_data = hq, hc + hq, hc = g_pdh_data + return GetCounterValue(hq, hc) + +# The public bit +if have_pdh: + getmemusage = pdh_getmemusage +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) diff --git a/src/libs/xpcom18a4/python/test/regrtest.py b/src/libs/xpcom18a4/python/test/regrtest.py new file mode 100644 index 00000000..90d07948 --- /dev/null +++ b/src/libs/xpcom18a4/python/test/regrtest.py @@ -0,0 +1,91 @@ +# ***** 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 Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# ActiveState Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000 +# 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 ***** + +# regrtest.py +# +# The Regression Tests for the xpcom package. +import os +import sys + +import unittest + +# 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() + +try: + 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!" diff --git a/src/libs/xpcom18a4/python/test/test_com_exceptions.py b/src/libs/xpcom18a4/python/test/test_com_exceptions.py new file mode 100755 index 00000000..7813bf98 --- /dev/null +++ b/src/libs/xpcom18a4/python/test/test_com_exceptions.py @@ -0,0 +1,124 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is ActiveState Tool Corp. +# Portions created by ActiveState Tool Corp. are Copyright (C) 2000, 2001 +# ActiveState Tool Corp. All Rights Reserved. +# +# Contributor(s): +# Mark Hammond <MarkH@ActiveState.com> (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 ***** + +# Test pyxpcom exception. + +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. + _com_interfaces_ = components.interfaces.nsIPythonTestInterfaceExtra + + def do_boolean(self, p1, p2): + # This should cause the caller to see a "silent" NS_ERROR_FAILURE exception. + raise ServerException() + + def do_octet(self, p1, p2): + # This should cause the caller to see a "silent" NS_ERROR_NOT_IMPLEMENTED exception. + raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED) + + def do_short(self, p1, p2): + # This should cause the caller to see a "debug" NS_ERROR_FAILURE exception. + raise COMException(nsError.NS_ERROR_NOT_IMPLEMENTED) + + def do_unsigned_short(self, p1, p2): + # This should cause the caller to see a "debug" NS_ERROR_FAILURE exception. + raise "Foo" + + def do_long(self, p1, p2): + # This should cause the caller to see a "silent" NS_ERROR_FAILURE exception. + raise ServerException + + def do_unsigned_long(self, p1, p2): + # This should cause the caller to see a "silent" NS_ERROR_NOT_IMPLEMENTED exception. + raise ServerException, nsError.NS_ERROR_NOT_IMPLEMENTED + + def do_long_long(self, p1, p2): + # This should cause the caller to see a "silent" NS_ERROR_NOT_IMPLEMENTED exception. + raise ServerException, (nsError.NS_ERROR_NOT_IMPLEMENTED, "testing") + + def do_unsigned_long_long(self, p1, p2): + # Report of a crash in this case - test it! + raise ServerException, "A bad exception param" + +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 handle(self, record): + self.records.append(record) + +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() diff --git a/src/libs/xpcom18a4/python/test/test_comfile.py b/src/libs/xpcom18a4/python/test/test_comfile.py new file mode 100755 index 00000000..9ffebe37 --- /dev/null +++ b/src/libs/xpcom18a4/python/test/test_comfile.py @@ -0,0 +1,49 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# ActiveState Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000, 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Hammond (markh@activestate.com) +# +# 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 ***** + +"""Test the xpcom.file module.""" +from pyxpcom_test_tools import suite_from_functions, testmain + +import xpcom.file + +# Make this test run under our std test suite +def suite(): + return suite_from_functions(xpcom.file._TestAll) + +if __name__=='__main__': + testmain() + diff --git a/src/libs/xpcom18a4/python/test/test_component/_xpidlgen/.done b/src/libs/xpcom18a4/python/test/test_component/_xpidlgen/.done new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/src/libs/xpcom18a4/python/test/test_component/_xpidlgen/.done diff --git a/src/libs/xpcom18a4/python/test/test_component/_xpidlgen/py_test_component.h b/src/libs/xpcom18a4/python/test/test_component/_xpidlgen/py_test_component.h new file mode 100644 index 00000000..7d0cd8c9 --- /dev/null +++ b/src/libs/xpcom18a4/python/test/test_component/_xpidlgen/py_test_component.h @@ -0,0 +1,1411 @@ +/* + * DO NOT EDIT. THIS FILE IS GENERATED FROM py_test_component.idl + */ + +#ifndef __gen_py_test_component_h__ +#define __gen_py_test_component_h__ + + +#ifndef __gen_nsISupports_h__ +#include "nsISupports.h" +#endif + +#ifndef __gen_nsIVariant_h__ +#include "nsIVariant.h" +#endif + +/* For IDL files that don't want to include root IDL files. */ +#ifndef NS_NO_VTABLE +#define NS_NO_VTABLE +#endif + +/* starting interface: nsIPythonTestInterface */ +#define NS_IPYTHONTESTINTERFACE_IID_STR "1ecaed4f-e4d5-4ee7-abf0-7d72ae1441d7" + +#define NS_IPYTHONTESTINTERFACE_IID \ + {0x1ecaed4f, 0xe4d5, 0x4ee7, \ + { 0xab, 0xf0, 0x7d, 0x72, 0xae, 0x14, 0x41, 0xd7 }} + +class NS_NO_VTABLE nsIPythonTestInterface : public nsISupports { + public: + + NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPYTHONTESTINTERFACE_IID) + + enum { One = 1 }; + + enum { Two = 2 }; + + enum { MinusOne = -1 }; + + enum { BigLong = 2147483647 }; + + enum { BiggerLong = 4294967295 }; + + enum { BigULong = 4294967295U }; + + /* attribute boolean boolean_value; */ + NS_IMETHOD GetBoolean_value(PRBool *aBoolean_value) = 0; + NS_IMETHOD SetBoolean_value(PRBool aBoolean_value) = 0; + + /* attribute octet octet_value; */ + NS_IMETHOD GetOctet_value(PRUint8 *aOctet_value) = 0; + NS_IMETHOD SetOctet_value(PRUint8 aOctet_value) = 0; + + /* attribute short short_value; */ + NS_IMETHOD GetShort_value(PRInt16 *aShort_value) = 0; + NS_IMETHOD SetShort_value(PRInt16 aShort_value) = 0; + + /* attribute unsigned short ushort_value; */ + NS_IMETHOD GetUshort_value(PRUint16 *aUshort_value) = 0; + NS_IMETHOD SetUshort_value(PRUint16 aUshort_value) = 0; + + /* attribute long long_value; */ + NS_IMETHOD GetLong_value(PRInt32 *aLong_value) = 0; + NS_IMETHOD SetLong_value(PRInt32 aLong_value) = 0; + + /* attribute unsigned long ulong_value; */ + NS_IMETHOD GetUlong_value(PRUint32 *aUlong_value) = 0; + NS_IMETHOD SetUlong_value(PRUint32 aUlong_value) = 0; + + /* attribute long long long_long_value; */ + NS_IMETHOD GetLong_long_value(PRInt64 *aLong_long_value) = 0; + NS_IMETHOD SetLong_long_value(PRInt64 aLong_long_value) = 0; + + /* attribute unsigned long long ulong_long_value; */ + NS_IMETHOD GetUlong_long_value(PRUint64 *aUlong_long_value) = 0; + NS_IMETHOD SetUlong_long_value(PRUint64 aUlong_long_value) = 0; + + /* attribute float float_value; */ + NS_IMETHOD GetFloat_value(float *aFloat_value) = 0; + NS_IMETHOD SetFloat_value(float aFloat_value) = 0; + + /* attribute double double_value; */ + NS_IMETHOD GetDouble_value(double *aDouble_value) = 0; + NS_IMETHOD SetDouble_value(double aDouble_value) = 0; + + /* attribute char char_value; */ + NS_IMETHOD GetChar_value(char *aChar_value) = 0; + NS_IMETHOD SetChar_value(char aChar_value) = 0; + + /* attribute wchar wchar_value; */ + NS_IMETHOD GetWchar_value(PRUnichar *aWchar_value) = 0; + NS_IMETHOD SetWchar_value(PRUnichar aWchar_value) = 0; + + /* attribute string string_value; */ + NS_IMETHOD GetString_value(char * *aString_value) = 0; + NS_IMETHOD SetString_value(const char * aString_value) = 0; + + /* attribute wstring wstring_value; */ + NS_IMETHOD GetWstring_value(PRUnichar * *aWstring_value) = 0; + NS_IMETHOD SetWstring_value(const PRUnichar * aWstring_value) = 0; + + /* attribute AString astring_value; */ + NS_IMETHOD GetAstring_value(nsAString & aAstring_value) = 0; + NS_IMETHOD SetAstring_value(const nsAString & aAstring_value) = 0; + + /* attribute ACString acstring_value; */ + NS_IMETHOD GetAcstring_value(nsACString & aAcstring_value) = 0; + NS_IMETHOD SetAcstring_value(const nsACString & aAcstring_value) = 0; + + /* attribute AUTF8String utf8string_value; */ + NS_IMETHOD GetUtf8string_value(nsACString & aUtf8string_value) = 0; + NS_IMETHOD SetUtf8string_value(const nsACString & aUtf8string_value) = 0; + + /* attribute nsIIDRef iid_value; */ + NS_IMETHOD GetIid_value(nsIID & *aIid_value) = 0; + NS_IMETHOD SetIid_value(const nsIID & aIid_value) = 0; + + /* attribute nsIPythonTestInterface interface_value; */ + NS_IMETHOD GetInterface_value(nsIPythonTestInterface * *aInterface_value) = 0; + NS_IMETHOD SetInterface_value(nsIPythonTestInterface * aInterface_value) = 0; + + /* attribute nsISupports isupports_value; */ + NS_IMETHOD GetIsupports_value(nsISupports * *aIsupports_value) = 0; + NS_IMETHOD SetIsupports_value(nsISupports * aIsupports_value) = 0; + + /* boolean do_boolean (in boolean p1, inout boolean p2, out boolean p3); */ + NS_IMETHOD Do_boolean(PRBool p1, PRBool *p2, PRBool *p3, PRBool *_retval) = 0; + + /* octet do_octet (in octet p1, inout octet p2, out octet p3); */ + NS_IMETHOD Do_octet(PRUint8 p1, PRUint8 *p2, PRUint8 *p3, PRUint8 *_retval) = 0; + + /* short do_short (in short p1, inout short p2, out short p3); */ + NS_IMETHOD Do_short(PRInt16 p1, PRInt16 *p2, PRInt16 *p3, PRInt16 *_retval) = 0; + + /* unsigned short do_unsigned_short (in unsigned short p1, inout unsigned short p2, out unsigned short p3); */ + NS_IMETHOD Do_unsigned_short(PRUint16 p1, PRUint16 *p2, PRUint16 *p3, PRUint16 *_retval) = 0; + + /* long do_long (in long p1, inout long p2, out long p3); */ + NS_IMETHOD Do_long(PRInt32 p1, PRInt32 *p2, PRInt32 *p3, PRInt32 *_retval) = 0; + + /* unsigned long do_unsigned_long (in unsigned long p1, inout unsigned long p2, out unsigned long p3); */ + NS_IMETHOD Do_unsigned_long(PRUint32 p1, PRUint32 *p2, PRUint32 *p3, PRUint32 *_retval) = 0; + + /* long long do_long_long (in long long p1, inout long long p2, out long long p3); */ + NS_IMETHOD Do_long_long(PRInt64 p1, PRInt64 *p2, PRInt64 *p3, PRInt64 *_retval) = 0; + + /* unsigned long long do_unsigned_long_long (in unsigned long long p1, inout unsigned long long p2, out unsigned long long p3); */ + NS_IMETHOD Do_unsigned_long_long(PRUint64 p1, PRUint64 *p2, PRUint64 *p3, PRUint64 *_retval) = 0; + + /* float do_float (in float p1, inout float p2, out float p3); */ + NS_IMETHOD Do_float(float p1, float *p2, float *p3, float *_retval) = 0; + + /* double do_double (in double p1, inout double p2, out double p3); */ + NS_IMETHOD Do_double(double p1, double *p2, double *p3, double *_retval) = 0; + + /* char do_char (in char p1, inout char p2, out char p3); */ + NS_IMETHOD Do_char(char p1, char *p2, char *p3, char *_retval) = 0; + + /* wchar do_wchar (in wchar p1, inout wchar p2, out wchar p3); */ + NS_IMETHOD Do_wchar(PRUnichar p1, PRUnichar *p2, PRUnichar *p3, PRUnichar *_retval) = 0; + + /* string do_string (in string p1, inout string p2, out string p3); */ + NS_IMETHOD Do_string(const char *p1, char **p2, char **p3, char **_retval) = 0; + + /* wstring do_wstring (in wstring p1, inout wstring p2, out wstring p3); */ + NS_IMETHOD Do_wstring(const PRUnichar *p1, PRUnichar **p2, PRUnichar **p3, PRUnichar **_retval) = 0; + + /* nsIIDRef do_nsIIDRef (in nsIIDRef p1, inout nsIIDRef p2, out nsIIDRef p3); */ + NS_IMETHOD Do_nsIIDRef(const nsIID & p1, nsIID & *p2, nsIID & *p3, nsIID & *_retval) = 0; + + /* nsIPythonTestInterface do_nsIPythonTestInterface (in nsIPythonTestInterface p1, inout nsIPythonTestInterface p2, out nsIPythonTestInterface p3); */ + NS_IMETHOD Do_nsIPythonTestInterface(nsIPythonTestInterface *p1, nsIPythonTestInterface **p2, nsIPythonTestInterface **p3, nsIPythonTestInterface **_retval) = 0; + + /* nsISupports do_nsISupports (in nsISupports p1, inout nsISupports p2, out nsISupports p3); */ + NS_IMETHOD Do_nsISupports(nsISupports *p1, nsISupports **p2, nsISupports **p3, nsISupports **_retval) = 0; + + /* void do_nsISupportsIs (in nsIIDRef iid, [iid_is (iid), retval] out nsQIResult result); */ + NS_IMETHOD Do_nsISupportsIs(const nsIID & iid, void * *result) = 0; + +}; + +/* Use this macro when declaring classes that implement this interface. */ +#define NS_DECL_NSIPYTHONTESTINTERFACE \ + NS_IMETHOD GetBoolean_value(PRBool *aBoolean_value); \ + NS_IMETHOD SetBoolean_value(PRBool aBoolean_value); \ + NS_IMETHOD GetOctet_value(PRUint8 *aOctet_value); \ + NS_IMETHOD SetOctet_value(PRUint8 aOctet_value); \ + NS_IMETHOD GetShort_value(PRInt16 *aShort_value); \ + NS_IMETHOD SetShort_value(PRInt16 aShort_value); \ + NS_IMETHOD GetUshort_value(PRUint16 *aUshort_value); \ + NS_IMETHOD SetUshort_value(PRUint16 aUshort_value); \ + NS_IMETHOD GetLong_value(PRInt32 *aLong_value); \ + NS_IMETHOD SetLong_value(PRInt32 aLong_value); \ + NS_IMETHOD GetUlong_value(PRUint32 *aUlong_value); \ + NS_IMETHOD SetUlong_value(PRUint32 aUlong_value); \ + NS_IMETHOD GetLong_long_value(PRInt64 *aLong_long_value); \ + NS_IMETHOD SetLong_long_value(PRInt64 aLong_long_value); \ + NS_IMETHOD GetUlong_long_value(PRUint64 *aUlong_long_value); \ + NS_IMETHOD SetUlong_long_value(PRUint64 aUlong_long_value); \ + NS_IMETHOD GetFloat_value(float *aFloat_value); \ + NS_IMETHOD SetFloat_value(float aFloat_value); \ + NS_IMETHOD GetDouble_value(double *aDouble_value); \ + NS_IMETHOD SetDouble_value(double aDouble_value); \ + NS_IMETHOD GetChar_value(char *aChar_value); \ + NS_IMETHOD SetChar_value(char aChar_value); \ + NS_IMETHOD GetWchar_value(PRUnichar *aWchar_value); \ + NS_IMETHOD SetWchar_value(PRUnichar aWchar_value); \ + NS_IMETHOD GetString_value(char * *aString_value); \ + NS_IMETHOD SetString_value(const char * aString_value); \ + NS_IMETHOD GetWstring_value(PRUnichar * *aWstring_value); \ + NS_IMETHOD SetWstring_value(const PRUnichar * aWstring_value); \ + NS_IMETHOD GetAstring_value(nsAString & aAstring_value); \ + NS_IMETHOD SetAstring_value(const nsAString & aAstring_value); \ + NS_IMETHOD GetAcstring_value(nsACString & aAcstring_value); \ + NS_IMETHOD SetAcstring_value(const nsACString & aAcstring_value); \ + NS_IMETHOD GetUtf8string_value(nsACString & aUtf8string_value); \ + NS_IMETHOD SetUtf8string_value(const nsACString & aUtf8string_value); \ + NS_IMETHOD GetIid_value(nsIID & *aIid_value); \ + NS_IMETHOD SetIid_value(const nsIID & aIid_value); \ + NS_IMETHOD GetInterface_value(nsIPythonTestInterface * *aInterface_value); \ + NS_IMETHOD SetInterface_value(nsIPythonTestInterface * aInterface_value); \ + NS_IMETHOD GetIsupports_value(nsISupports * *aIsupports_value); \ + NS_IMETHOD SetIsupports_value(nsISupports * aIsupports_value); \ + NS_IMETHOD Do_boolean(PRBool p1, PRBool *p2, PRBool *p3, PRBool *_retval); \ + NS_IMETHOD Do_octet(PRUint8 p1, PRUint8 *p2, PRUint8 *p3, PRUint8 *_retval); \ + NS_IMETHOD Do_short(PRInt16 p1, PRInt16 *p2, PRInt16 *p3, PRInt16 *_retval); \ + NS_IMETHOD Do_unsigned_short(PRUint16 p1, PRUint16 *p2, PRUint16 *p3, PRUint16 *_retval); \ + NS_IMETHOD Do_long(PRInt32 p1, PRInt32 *p2, PRInt32 *p3, PRInt32 *_retval); \ + NS_IMETHOD Do_unsigned_long(PRUint32 p1, PRUint32 *p2, PRUint32 *p3, PRUint32 *_retval); \ + NS_IMETHOD Do_long_long(PRInt64 p1, PRInt64 *p2, PRInt64 *p3, PRInt64 *_retval); \ + NS_IMETHOD Do_unsigned_long_long(PRUint64 p1, PRUint64 *p2, PRUint64 *p3, PRUint64 *_retval); \ + NS_IMETHOD Do_float(float p1, float *p2, float *p3, float *_retval); \ + NS_IMETHOD Do_double(double p1, double *p2, double *p3, double *_retval); \ + NS_IMETHOD Do_char(char p1, char *p2, char *p3, char *_retval); \ + NS_IMETHOD Do_wchar(PRUnichar p1, PRUnichar *p2, PRUnichar *p3, PRUnichar *_retval); \ + NS_IMETHOD Do_string(const char *p1, char **p2, char **p3, char **_retval); \ + NS_IMETHOD Do_wstring(const PRUnichar *p1, PRUnichar **p2, PRUnichar **p3, PRUnichar **_retval); \ + NS_IMETHOD Do_nsIIDRef(const nsIID & p1, nsIID & *p2, nsIID & *p3, nsIID & *_retval); \ + NS_IMETHOD Do_nsIPythonTestInterface(nsIPythonTestInterface *p1, nsIPythonTestInterface **p2, nsIPythonTestInterface **p3, nsIPythonTestInterface **_retval); \ + NS_IMETHOD Do_nsISupports(nsISupports *p1, nsISupports **p2, nsISupports **p3, nsISupports **_retval); \ + NS_IMETHOD Do_nsISupportsIs(const nsIID & iid, void * *result); + +/* Use this macro to declare functions that forward the behavior of this interface to another object. */ +#define NS_FORWARD_NSIPYTHONTESTINTERFACE(_to) \ + NS_IMETHOD GetBoolean_value(PRBool *aBoolean_value) { return _to GetBoolean_value(aBoolean_value); } \ + NS_IMETHOD SetBoolean_value(PRBool aBoolean_value) { return _to SetBoolean_value(aBoolean_value); } \ + NS_IMETHOD GetOctet_value(PRUint8 *aOctet_value) { return _to GetOctet_value(aOctet_value); } \ + NS_IMETHOD SetOctet_value(PRUint8 aOctet_value) { return _to SetOctet_value(aOctet_value); } \ + NS_IMETHOD GetShort_value(PRInt16 *aShort_value) { return _to GetShort_value(aShort_value); } \ + NS_IMETHOD SetShort_value(PRInt16 aShort_value) { return _to SetShort_value(aShort_value); } \ + NS_IMETHOD GetUshort_value(PRUint16 *aUshort_value) { return _to GetUshort_value(aUshort_value); } \ + NS_IMETHOD SetUshort_value(PRUint16 aUshort_value) { return _to SetUshort_value(aUshort_value); } \ + NS_IMETHOD GetLong_value(PRInt32 *aLong_value) { return _to GetLong_value(aLong_value); } \ + NS_IMETHOD SetLong_value(PRInt32 aLong_value) { return _to SetLong_value(aLong_value); } \ + NS_IMETHOD GetUlong_value(PRUint32 *aUlong_value) { return _to GetUlong_value(aUlong_value); } \ + NS_IMETHOD SetUlong_value(PRUint32 aUlong_value) { return _to SetUlong_value(aUlong_value); } \ + NS_IMETHOD GetLong_long_value(PRInt64 *aLong_long_value) { return _to GetLong_long_value(aLong_long_value); } \ + NS_IMETHOD SetLong_long_value(PRInt64 aLong_long_value) { return _to SetLong_long_value(aLong_long_value); } \ + NS_IMETHOD GetUlong_long_value(PRUint64 *aUlong_long_value) { return _to GetUlong_long_value(aUlong_long_value); } \ + NS_IMETHOD SetUlong_long_value(PRUint64 aUlong_long_value) { return _to SetUlong_long_value(aUlong_long_value); } \ + NS_IMETHOD GetFloat_value(float *aFloat_value) { return _to GetFloat_value(aFloat_value); } \ + NS_IMETHOD SetFloat_value(float aFloat_value) { return _to SetFloat_value(aFloat_value); } \ + NS_IMETHOD GetDouble_value(double *aDouble_value) { return _to GetDouble_value(aDouble_value); } \ + NS_IMETHOD SetDouble_value(double aDouble_value) { return _to SetDouble_value(aDouble_value); } \ + NS_IMETHOD GetChar_value(char *aChar_value) { return _to GetChar_value(aChar_value); } \ + NS_IMETHOD SetChar_value(char aChar_value) { return _to SetChar_value(aChar_value); } \ + NS_IMETHOD GetWchar_value(PRUnichar *aWchar_value) { return _to GetWchar_value(aWchar_value); } \ + NS_IMETHOD SetWchar_value(PRUnichar aWchar_value) { return _to SetWchar_value(aWchar_value); } \ + NS_IMETHOD GetString_value(char * *aString_value) { return _to GetString_value(aString_value); } \ + NS_IMETHOD SetString_value(const char * aString_value) { return _to SetString_value(aString_value); } \ + NS_IMETHOD GetWstring_value(PRUnichar * *aWstring_value) { return _to GetWstring_value(aWstring_value); } \ + NS_IMETHOD SetWstring_value(const PRUnichar * aWstring_value) { return _to SetWstring_value(aWstring_value); } \ + NS_IMETHOD GetAstring_value(nsAString & aAstring_value) { return _to GetAstring_value(aAstring_value); } \ + NS_IMETHOD SetAstring_value(const nsAString & aAstring_value) { return _to SetAstring_value(aAstring_value); } \ + NS_IMETHOD GetAcstring_value(nsACString & aAcstring_value) { return _to GetAcstring_value(aAcstring_value); } \ + NS_IMETHOD SetAcstring_value(const nsACString & aAcstring_value) { return _to SetAcstring_value(aAcstring_value); } \ + NS_IMETHOD GetUtf8string_value(nsACString & aUtf8string_value) { return _to GetUtf8string_value(aUtf8string_value); } \ + NS_IMETHOD SetUtf8string_value(const nsACString & aUtf8string_value) { return _to SetUtf8string_value(aUtf8string_value); } \ + NS_IMETHOD GetIid_value(nsIID & *aIid_value) { return _to GetIid_value(aIid_value); } \ + NS_IMETHOD SetIid_value(const nsIID & aIid_value) { return _to SetIid_value(aIid_value); } \ + NS_IMETHOD GetInterface_value(nsIPythonTestInterface * *aInterface_value) { return _to GetInterface_value(aInterface_value); } \ + NS_IMETHOD SetInterface_value(nsIPythonTestInterface * aInterface_value) { return _to SetInterface_value(aInterface_value); } \ + NS_IMETHOD GetIsupports_value(nsISupports * *aIsupports_value) { return _to GetIsupports_value(aIsupports_value); } \ + NS_IMETHOD SetIsupports_value(nsISupports * aIsupports_value) { return _to SetIsupports_value(aIsupports_value); } \ + NS_IMETHOD Do_boolean(PRBool p1, PRBool *p2, PRBool *p3, PRBool *_retval) { return _to Do_boolean(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_octet(PRUint8 p1, PRUint8 *p2, PRUint8 *p3, PRUint8 *_retval) { return _to Do_octet(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_short(PRInt16 p1, PRInt16 *p2, PRInt16 *p3, PRInt16 *_retval) { return _to Do_short(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_unsigned_short(PRUint16 p1, PRUint16 *p2, PRUint16 *p3, PRUint16 *_retval) { return _to Do_unsigned_short(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_long(PRInt32 p1, PRInt32 *p2, PRInt32 *p3, PRInt32 *_retval) { return _to Do_long(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_unsigned_long(PRUint32 p1, PRUint32 *p2, PRUint32 *p3, PRUint32 *_retval) { return _to Do_unsigned_long(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_long_long(PRInt64 p1, PRInt64 *p2, PRInt64 *p3, PRInt64 *_retval) { return _to Do_long_long(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_unsigned_long_long(PRUint64 p1, PRUint64 *p2, PRUint64 *p3, PRUint64 *_retval) { return _to Do_unsigned_long_long(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_float(float p1, float *p2, float *p3, float *_retval) { return _to Do_float(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_double(double p1, double *p2, double *p3, double *_retval) { return _to Do_double(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_char(char p1, char *p2, char *p3, char *_retval) { return _to Do_char(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_wchar(PRUnichar p1, PRUnichar *p2, PRUnichar *p3, PRUnichar *_retval) { return _to Do_wchar(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_string(const char *p1, char **p2, char **p3, char **_retval) { return _to Do_string(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_wstring(const PRUnichar *p1, PRUnichar **p2, PRUnichar **p3, PRUnichar **_retval) { return _to Do_wstring(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_nsIIDRef(const nsIID & p1, nsIID & *p2, nsIID & *p3, nsIID & *_retval) { return _to Do_nsIIDRef(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_nsIPythonTestInterface(nsIPythonTestInterface *p1, nsIPythonTestInterface **p2, nsIPythonTestInterface **p3, nsIPythonTestInterface **_retval) { return _to Do_nsIPythonTestInterface(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_nsISupports(nsISupports *p1, nsISupports **p2, nsISupports **p3, nsISupports **_retval) { return _to Do_nsISupports(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_nsISupportsIs(const nsIID & iid, void * *result) { return _to Do_nsISupportsIs(iid, result); } + +/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */ +#define NS_FORWARD_SAFE_NSIPYTHONTESTINTERFACE(_to) \ + NS_IMETHOD GetBoolean_value(PRBool *aBoolean_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetBoolean_value(aBoolean_value); } \ + NS_IMETHOD SetBoolean_value(PRBool aBoolean_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetBoolean_value(aBoolean_value); } \ + NS_IMETHOD GetOctet_value(PRUint8 *aOctet_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetOctet_value(aOctet_value); } \ + NS_IMETHOD SetOctet_value(PRUint8 aOctet_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetOctet_value(aOctet_value); } \ + NS_IMETHOD GetShort_value(PRInt16 *aShort_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetShort_value(aShort_value); } \ + NS_IMETHOD SetShort_value(PRInt16 aShort_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetShort_value(aShort_value); } \ + NS_IMETHOD GetUshort_value(PRUint16 *aUshort_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetUshort_value(aUshort_value); } \ + NS_IMETHOD SetUshort_value(PRUint16 aUshort_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetUshort_value(aUshort_value); } \ + NS_IMETHOD GetLong_value(PRInt32 *aLong_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetLong_value(aLong_value); } \ + NS_IMETHOD SetLong_value(PRInt32 aLong_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetLong_value(aLong_value); } \ + NS_IMETHOD GetUlong_value(PRUint32 *aUlong_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetUlong_value(aUlong_value); } \ + NS_IMETHOD SetUlong_value(PRUint32 aUlong_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetUlong_value(aUlong_value); } \ + NS_IMETHOD GetLong_long_value(PRInt64 *aLong_long_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetLong_long_value(aLong_long_value); } \ + NS_IMETHOD SetLong_long_value(PRInt64 aLong_long_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetLong_long_value(aLong_long_value); } \ + NS_IMETHOD GetUlong_long_value(PRUint64 *aUlong_long_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetUlong_long_value(aUlong_long_value); } \ + NS_IMETHOD SetUlong_long_value(PRUint64 aUlong_long_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetUlong_long_value(aUlong_long_value); } \ + NS_IMETHOD GetFloat_value(float *aFloat_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetFloat_value(aFloat_value); } \ + NS_IMETHOD SetFloat_value(float aFloat_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetFloat_value(aFloat_value); } \ + NS_IMETHOD GetDouble_value(double *aDouble_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDouble_value(aDouble_value); } \ + NS_IMETHOD SetDouble_value(double aDouble_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetDouble_value(aDouble_value); } \ + NS_IMETHOD GetChar_value(char *aChar_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetChar_value(aChar_value); } \ + NS_IMETHOD SetChar_value(char aChar_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetChar_value(aChar_value); } \ + NS_IMETHOD GetWchar_value(PRUnichar *aWchar_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetWchar_value(aWchar_value); } \ + NS_IMETHOD SetWchar_value(PRUnichar aWchar_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetWchar_value(aWchar_value); } \ + NS_IMETHOD GetString_value(char * *aString_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetString_value(aString_value); } \ + NS_IMETHOD SetString_value(const char * aString_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetString_value(aString_value); } \ + NS_IMETHOD GetWstring_value(PRUnichar * *aWstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetWstring_value(aWstring_value); } \ + NS_IMETHOD SetWstring_value(const PRUnichar * aWstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetWstring_value(aWstring_value); } \ + NS_IMETHOD GetAstring_value(nsAString & aAstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetAstring_value(aAstring_value); } \ + NS_IMETHOD SetAstring_value(const nsAString & aAstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetAstring_value(aAstring_value); } \ + NS_IMETHOD GetAcstring_value(nsACString & aAcstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetAcstring_value(aAcstring_value); } \ + NS_IMETHOD SetAcstring_value(const nsACString & aAcstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetAcstring_value(aAcstring_value); } \ + NS_IMETHOD GetUtf8string_value(nsACString & aUtf8string_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetUtf8string_value(aUtf8string_value); } \ + NS_IMETHOD SetUtf8string_value(const nsACString & aUtf8string_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetUtf8string_value(aUtf8string_value); } \ + NS_IMETHOD GetIid_value(nsIID & *aIid_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetIid_value(aIid_value); } \ + NS_IMETHOD SetIid_value(const nsIID & aIid_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetIid_value(aIid_value); } \ + NS_IMETHOD GetInterface_value(nsIPythonTestInterface * *aInterface_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetInterface_value(aInterface_value); } \ + NS_IMETHOD SetInterface_value(nsIPythonTestInterface * aInterface_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetInterface_value(aInterface_value); } \ + NS_IMETHOD GetIsupports_value(nsISupports * *aIsupports_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetIsupports_value(aIsupports_value); } \ + NS_IMETHOD SetIsupports_value(nsISupports * aIsupports_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetIsupports_value(aIsupports_value); } \ + NS_IMETHOD Do_boolean(PRBool p1, PRBool *p2, PRBool *p3, PRBool *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_boolean(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_octet(PRUint8 p1, PRUint8 *p2, PRUint8 *p3, PRUint8 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_octet(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_short(PRInt16 p1, PRInt16 *p2, PRInt16 *p3, PRInt16 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_short(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_unsigned_short(PRUint16 p1, PRUint16 *p2, PRUint16 *p3, PRUint16 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_unsigned_short(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_long(PRInt32 p1, PRInt32 *p2, PRInt32 *p3, PRInt32 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_long(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_unsigned_long(PRUint32 p1, PRUint32 *p2, PRUint32 *p3, PRUint32 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_unsigned_long(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_long_long(PRInt64 p1, PRInt64 *p2, PRInt64 *p3, PRInt64 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_long_long(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_unsigned_long_long(PRUint64 p1, PRUint64 *p2, PRUint64 *p3, PRUint64 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_unsigned_long_long(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_float(float p1, float *p2, float *p3, float *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_float(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_double(double p1, double *p2, double *p3, double *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_double(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_char(char p1, char *p2, char *p3, char *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_char(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_wchar(PRUnichar p1, PRUnichar *p2, PRUnichar *p3, PRUnichar *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_wchar(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_string(const char *p1, char **p2, char **p3, char **_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_string(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_wstring(const PRUnichar *p1, PRUnichar **p2, PRUnichar **p3, PRUnichar **_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_wstring(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_nsIIDRef(const nsIID & p1, nsIID & *p2, nsIID & *p3, nsIID & *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_nsIIDRef(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_nsIPythonTestInterface(nsIPythonTestInterface *p1, nsIPythonTestInterface **p2, nsIPythonTestInterface **p3, nsIPythonTestInterface **_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_nsIPythonTestInterface(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_nsISupports(nsISupports *p1, nsISupports **p2, nsISupports **p3, nsISupports **_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_nsISupports(p1, p2, p3, _retval); } \ + NS_IMETHOD Do_nsISupportsIs(const nsIID & iid, void * *result) { return !_to ? NS_ERROR_NULL_POINTER : _to->Do_nsISupportsIs(iid, result); } + +#if 0 +/* Use the code below as a template for the implementation class for this interface. */ + +/* Header file */ +class nsPythonTestInterface : public nsIPythonTestInterface +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIPYTHONTESTINTERFACE + + nsPythonTestInterface(); + +private: + ~nsPythonTestInterface(); + +protected: + /* additional members */ +}; + +/* Implementation file */ +NS_IMPL_ISUPPORTS1(nsPythonTestInterface, nsIPythonTestInterface) + +nsPythonTestInterface::nsPythonTestInterface() +{ + /* member initializers and constructor code */ +} + +nsPythonTestInterface::~nsPythonTestInterface() +{ + /* destructor code */ +} + +/* attribute boolean boolean_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetBoolean_value(PRBool *aBoolean_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetBoolean_value(PRBool aBoolean_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute octet octet_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetOctet_value(PRUint8 *aOctet_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetOctet_value(PRUint8 aOctet_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute short short_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetShort_value(PRInt16 *aShort_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetShort_value(PRInt16 aShort_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute unsigned short ushort_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetUshort_value(PRUint16 *aUshort_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetUshort_value(PRUint16 aUshort_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute long long_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetLong_value(PRInt32 *aLong_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetLong_value(PRInt32 aLong_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute unsigned long ulong_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetUlong_value(PRUint32 *aUlong_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetUlong_value(PRUint32 aUlong_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute long long long_long_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetLong_long_value(PRInt64 *aLong_long_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetLong_long_value(PRInt64 aLong_long_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute unsigned long long ulong_long_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetUlong_long_value(PRUint64 *aUlong_long_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetUlong_long_value(PRUint64 aUlong_long_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute float float_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetFloat_value(float *aFloat_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetFloat_value(float aFloat_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute double double_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetDouble_value(double *aDouble_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetDouble_value(double aDouble_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute char char_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetChar_value(char *aChar_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetChar_value(char aChar_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute wchar wchar_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetWchar_value(PRUnichar *aWchar_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetWchar_value(PRUnichar aWchar_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute string string_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetString_value(char * *aString_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetString_value(const char * aString_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute wstring wstring_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetWstring_value(PRUnichar * *aWstring_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetWstring_value(const PRUnichar * aWstring_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute AString astring_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetAstring_value(nsAString & aAstring_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetAstring_value(const nsAString & aAstring_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute ACString acstring_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetAcstring_value(nsACString & aAcstring_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetAcstring_value(const nsACString & aAcstring_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute AUTF8String utf8string_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetUtf8string_value(nsACString & aUtf8string_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetUtf8string_value(const nsACString & aUtf8string_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute nsIIDRef iid_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetIid_value(nsIID & *aIid_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetIid_value(const nsIID & aIid_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute nsIPythonTestInterface interface_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetInterface_value(nsIPythonTestInterface * *aInterface_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetInterface_value(nsIPythonTestInterface * aInterface_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute nsISupports isupports_value; */ +NS_IMETHODIMP nsPythonTestInterface::GetIsupports_value(nsISupports * *aIsupports_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterface::SetIsupports_value(nsISupports * aIsupports_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* boolean do_boolean (in boolean p1, inout boolean p2, out boolean p3); */ +NS_IMETHODIMP nsPythonTestInterface::Do_boolean(PRBool p1, PRBool *p2, PRBool *p3, PRBool *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* octet do_octet (in octet p1, inout octet p2, out octet p3); */ +NS_IMETHODIMP nsPythonTestInterface::Do_octet(PRUint8 p1, PRUint8 *p2, PRUint8 *p3, PRUint8 *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* short do_short (in short p1, inout short p2, out short p3); */ +NS_IMETHODIMP nsPythonTestInterface::Do_short(PRInt16 p1, PRInt16 *p2, PRInt16 *p3, PRInt16 *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* unsigned short do_unsigned_short (in unsigned short p1, inout unsigned short p2, out unsigned short p3); */ +NS_IMETHODIMP nsPythonTestInterface::Do_unsigned_short(PRUint16 p1, PRUint16 *p2, PRUint16 *p3, PRUint16 *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* long do_long (in long p1, inout long p2, out long p3); */ +NS_IMETHODIMP nsPythonTestInterface::Do_long(PRInt32 p1, PRInt32 *p2, PRInt32 *p3, PRInt32 *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* unsigned long do_unsigned_long (in unsigned long p1, inout unsigned long p2, out unsigned long p3); */ +NS_IMETHODIMP nsPythonTestInterface::Do_unsigned_long(PRUint32 p1, PRUint32 *p2, PRUint32 *p3, PRUint32 *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* long long do_long_long (in long long p1, inout long long p2, out long long p3); */ +NS_IMETHODIMP nsPythonTestInterface::Do_long_long(PRInt64 p1, PRInt64 *p2, PRInt64 *p3, PRInt64 *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* unsigned long long do_unsigned_long_long (in unsigned long long p1, inout unsigned long long p2, out unsigned long long p3); */ +NS_IMETHODIMP nsPythonTestInterface::Do_unsigned_long_long(PRUint64 p1, PRUint64 *p2, PRUint64 *p3, PRUint64 *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* float do_float (in float p1, inout float p2, out float p3); */ +NS_IMETHODIMP nsPythonTestInterface::Do_float(float p1, float *p2, float *p3, float *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* double do_double (in double p1, inout double p2, out double p3); */ +NS_IMETHODIMP nsPythonTestInterface::Do_double(double p1, double *p2, double *p3, double *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* char do_char (in char p1, inout char p2, out char p3); */ +NS_IMETHODIMP nsPythonTestInterface::Do_char(char p1, char *p2, char *p3, char *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* wchar do_wchar (in wchar p1, inout wchar p2, out wchar p3); */ +NS_IMETHODIMP nsPythonTestInterface::Do_wchar(PRUnichar p1, PRUnichar *p2, PRUnichar *p3, PRUnichar *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* string do_string (in string p1, inout string p2, out string p3); */ +NS_IMETHODIMP nsPythonTestInterface::Do_string(const char *p1, char **p2, char **p3, char **_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* wstring do_wstring (in wstring p1, inout wstring p2, out wstring p3); */ +NS_IMETHODIMP nsPythonTestInterface::Do_wstring(const PRUnichar *p1, PRUnichar **p2, PRUnichar **p3, PRUnichar **_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* nsIIDRef do_nsIIDRef (in nsIIDRef p1, inout nsIIDRef p2, out nsIIDRef p3); */ +NS_IMETHODIMP nsPythonTestInterface::Do_nsIIDRef(const nsIID & p1, nsIID & *p2, nsIID & *p3, nsIID & *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* nsIPythonTestInterface do_nsIPythonTestInterface (in nsIPythonTestInterface p1, inout nsIPythonTestInterface p2, out nsIPythonTestInterface p3); */ +NS_IMETHODIMP nsPythonTestInterface::Do_nsIPythonTestInterface(nsIPythonTestInterface *p1, nsIPythonTestInterface **p2, nsIPythonTestInterface **p3, nsIPythonTestInterface **_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* nsISupports do_nsISupports (in nsISupports p1, inout nsISupports p2, out nsISupports p3); */ +NS_IMETHODIMP nsPythonTestInterface::Do_nsISupports(nsISupports *p1, nsISupports **p2, nsISupports **p3, nsISupports **_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void do_nsISupportsIs (in nsIIDRef iid, [iid_is (iid), retval] out nsQIResult result); */ +NS_IMETHODIMP nsPythonTestInterface::Do_nsISupportsIs(const nsIID & iid, void * *result) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* End of implementation class template. */ +#endif + + +/* starting interface: nsIPythonTestInterfaceExtra */ +#define NS_IPYTHONTESTINTERFACEEXTRA_IID_STR "b38d1538-fe92-42c3-831f-285242edeea4" + +#define NS_IPYTHONTESTINTERFACEEXTRA_IID \ + {0xb38d1538, 0xfe92, 0x42c3, \ + { 0x83, 0x1f, 0x28, 0x52, 0x42, 0xed, 0xee, 0xa4 }} + +class NS_NO_VTABLE nsIPythonTestInterfaceExtra : public nsIPythonTestInterface { + public: + + NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPYTHONTESTINTERFACEEXTRA_IID) + + /* void MultiplyEachItemInIntegerArray (in PRInt32 val, in PRUint32 count, [array, size_is (count)] inout PRInt32 valueArray); */ + NS_IMETHOD MultiplyEachItemInIntegerArray(PRInt32 val, PRUint32 count, PRInt32 **valueArray) = 0; + + /* void MultiplyEachItemInIntegerArrayAndAppend (in PRInt32 val, inout PRUint32 count, [array, size_is (count)] inout PRInt32 valueArray); */ + NS_IMETHOD MultiplyEachItemInIntegerArrayAndAppend(PRInt32 val, PRUint32 *count, PRInt32 **valueArray) = 0; + + /* void CompareStringArrays ([array, size_is (count)] in string arr1, [array, size_is (count)] in string arr2, in unsigned long count, [retval] out short result); */ + NS_IMETHOD CompareStringArrays(const char **arr1, const char **arr2, PRUint32 count, PRInt16 *result) = 0; + + /* void DoubleStringArray (inout PRUint32 count, [array, size_is (count)] inout string valueArray); */ + NS_IMETHOD DoubleStringArray(PRUint32 *count, char ***valueArray) = 0; + + /* void ReverseStringArray (in PRUint32 count, [array, size_is (count)] inout string valueArray); */ + NS_IMETHOD ReverseStringArray(PRUint32 count, char ***valueArray) = 0; + + /* void DoubleString (inout PRUint32 count, [size_is (count)] inout string str); */ + NS_IMETHOD DoubleString(PRUint32 *count, char **str) = 0; + + /* void DoubleString2 (in PRUint32 in_count, [size_is (in_count)] in string in_str, out PRUint32 out_count, [size_is (out_count)] out string out_str); */ + NS_IMETHOD DoubleString2(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) = 0; + + /* void DoubleString3 (in PRUint32 in_count, [size_is (in_count)] in string in_str, out PRUint32 out_count, [size_is (out_count), retval] out string out_str); */ + NS_IMETHOD DoubleString3(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) = 0; + + /* void DoubleString4 ([size_is (count)] in string in_str, inout PRUint32 count, [size_is (count)] out string out_str); */ + NS_IMETHOD DoubleString4(const char *in_str, PRUint32 *count, char **out_str) = 0; + + /* void UpString (in PRUint32 count, [size_is (count)] inout string str); */ + NS_IMETHOD UpString(PRUint32 count, char **str) = 0; + + /* void UpString2 (in PRUint32 count, [size_is (count)] in string in_str, [size_is (count)] out string out_str); */ + NS_IMETHOD UpString2(PRUint32 count, const char *in_str, char **out_str) = 0; + + /* void CopyUTF8String (in AUTF8String in_str, out AUTF8String out_str); */ + NS_IMETHOD CopyUTF8String(const nsACString & in_str, nsACString & out_str) = 0; + + /* void CopyUTF8String2 (in AUTF8String in_str, out AUTF8String out_str); */ + NS_IMETHOD CopyUTF8String2(const nsACString & in_str, nsACString & out_str) = 0; + + /* void GetFixedString (in PRUint32 count, [size_is (count)] out string out_str); */ + NS_IMETHOD GetFixedString(PRUint32 count, char **out_str) = 0; + + /* void DoubleWideString (inout PRUint32 count, [size_is (count)] inout wstring str); */ + NS_IMETHOD DoubleWideString(PRUint32 *count, PRUnichar **str) = 0; + + /* void DoubleWideString2 (in PRUint32 in_count, [size_is (in_count)] in wstring in_str, out PRUint32 out_count, [size_is (out_count)] out wstring out_str); */ + NS_IMETHOD DoubleWideString2(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) = 0; + + /* void DoubleWideString3 (in PRUint32 in_count, [size_is (in_count)] in wstring in_str, out PRUint32 out_count, [size_is (out_count), retval] out wstring out_str); */ + NS_IMETHOD DoubleWideString3(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) = 0; + + /* void DoubleWideString4 ([size_is (count)] in wstring in_str, inout PRUint32 count, [size_is (count)] out wstring out_str); */ + NS_IMETHOD DoubleWideString4(const PRUnichar *in_str, PRUint32 *count, PRUnichar **out_str) = 0; + + /* void UpWideString (in PRUint32 count, [size_is (count)] inout wstring str); */ + NS_IMETHOD UpWideString(PRUint32 count, PRUnichar **str) = 0; + + /* void UpWideString2 (in PRUint32 count, [size_is (count)] in wstring in_str, [size_is (count)] out wstring out_str); */ + NS_IMETHOD UpWideString2(PRUint32 count, const PRUnichar *in_str, PRUnichar **out_str) = 0; + + /* void GetFixedWideString (in PRUint32 count, [size_is (count)] out string out_str); */ + NS_IMETHOD GetFixedWideString(PRUint32 count, char **out_str) = 0; + + /* void GetStrings (out PRUint32 count, [array, size_is (count), retval] out string str); */ + NS_IMETHOD GetStrings(PRUint32 *count, char ***str) = 0; + + /* void UpOctetArray (inout PRUint32 count, [array, size_is (count)] inout PRUint8 data); */ + NS_IMETHOD UpOctetArray(PRUint32 *count, PRUint8 **data) = 0; + + /* void UpOctetArray2 (inout PRUint32 count, [array, size_is (count)] inout PRUint8 data); */ + NS_IMETHOD UpOctetArray2(PRUint32 *count, PRUint8 **data) = 0; + + /* void CheckInterfaceArray (in PRUint32 count, [array, size_is (count)] in nsISupports data, [retval] out PRBool all_non_null); */ + NS_IMETHOD CheckInterfaceArray(PRUint32 count, nsISupports **data, PRBool *all_non_null) = 0; + + /* void CopyInterfaceArray (in PRUint32 count, [array, size_is (count)] in nsISupports data, [array, size_is (out_count)] out nsISupports out_data, out PRUint32 out_count); */ + NS_IMETHOD CopyInterfaceArray(PRUint32 count, nsISupports **data, nsISupports ***out_data, PRUint32 *out_count) = 0; + + /* void GetInterfaceArray (out PRUint32 count, [array, size_is (count)] out nsISupports data); */ + NS_IMETHOD GetInterfaceArray(PRUint32 *count, nsISupports ***data) = 0; + + /* void ExtendInterfaceArray (inout PRUint32 count, [array, size_is (count)] inout nsISupports data); */ + NS_IMETHOD ExtendInterfaceArray(PRUint32 *count, nsISupports ***data) = 0; + + /* void CheckIIDArray (in PRUint32 count, [array, size_is (count)] in nsIIDRef data, [retval] out PRBool all_mine); */ + NS_IMETHOD CheckIIDArray(PRUint32 count, const nsIID & *data, PRBool *all_mine) = 0; + + /* void GetIIDArray (out PRUint32 count, [array, size_is (count)] out nsIIDRef data); */ + NS_IMETHOD GetIIDArray(PRUint32 *count, nsIID & **data) = 0; + + /* void ExtendIIDArray (inout PRUint32 count, [array, size_is (count)] inout nsIIDRef data); */ + NS_IMETHOD ExtendIIDArray(PRUint32 *count, nsIID & **data) = 0; + + /* void SumArrays (in PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] in PRInt32 array2, [retval] out PRInt32 result); */ + NS_IMETHOD SumArrays(PRUint32 count, PRInt32 *array1, PRInt32 *array2, PRInt32 *result) = 0; + + /* void GetArrays (out PRUint32 count, [array, size_is (count)] out PRInt32 array1, [array, size_is (count)] out PRInt32 array2); */ + NS_IMETHOD GetArrays(PRUint32 *count, PRInt32 **array1, PRInt32 **array2) = 0; + + /* void GetFixedArray (in PRUint32 count, [array, size_is (count)] out PRInt32 array1); */ + NS_IMETHOD GetFixedArray(PRUint32 count, PRInt32 **array1) = 0; + + /* void CopyArray (in PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] out PRInt32 array2); */ + NS_IMETHOD CopyArray(PRUint32 count, PRInt32 *array1, PRInt32 **array2) = 0; + + /* void CopyAndDoubleArray (inout PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] out PRInt32 array2); */ + NS_IMETHOD CopyAndDoubleArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) = 0; + + /* void AppendArray (inout PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] inout PRInt32 array2); */ + NS_IMETHOD AppendArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) = 0; + + /* void AppendVariant (in nsIVariant variant, inout nsIVariant result); */ + NS_IMETHOD AppendVariant(nsIVariant *variant, nsIVariant **result) = 0; + + /* nsIVariant CopyVariant (in nsIVariant variant); */ + NS_IMETHOD CopyVariant(nsIVariant *variant, nsIVariant **_retval) = 0; + + /* nsIVariant SumVariants (in PRUint32 incount, [array, size_is (incount)] in nsIVariant variants); */ + NS_IMETHOD SumVariants(PRUint32 incount, nsIVariant **variants, nsIVariant **_retval) = 0; + +}; + +/* Use this macro when declaring classes that implement this interface. */ +#define NS_DECL_NSIPYTHONTESTINTERFACEEXTRA \ + NS_IMETHOD MultiplyEachItemInIntegerArray(PRInt32 val, PRUint32 count, PRInt32 **valueArray); \ + NS_IMETHOD MultiplyEachItemInIntegerArrayAndAppend(PRInt32 val, PRUint32 *count, PRInt32 **valueArray); \ + NS_IMETHOD CompareStringArrays(const char **arr1, const char **arr2, PRUint32 count, PRInt16 *result); \ + NS_IMETHOD DoubleStringArray(PRUint32 *count, char ***valueArray); \ + NS_IMETHOD ReverseStringArray(PRUint32 count, char ***valueArray); \ + NS_IMETHOD DoubleString(PRUint32 *count, char **str); \ + NS_IMETHOD DoubleString2(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str); \ + NS_IMETHOD DoubleString3(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str); \ + NS_IMETHOD DoubleString4(const char *in_str, PRUint32 *count, char **out_str); \ + NS_IMETHOD UpString(PRUint32 count, char **str); \ + NS_IMETHOD UpString2(PRUint32 count, const char *in_str, char **out_str); \ + NS_IMETHOD CopyUTF8String(const nsACString & in_str, nsACString & out_str); \ + NS_IMETHOD CopyUTF8String2(const nsACString & in_str, nsACString & out_str); \ + NS_IMETHOD GetFixedString(PRUint32 count, char **out_str); \ + NS_IMETHOD DoubleWideString(PRUint32 *count, PRUnichar **str); \ + NS_IMETHOD DoubleWideString2(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str); \ + NS_IMETHOD DoubleWideString3(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str); \ + NS_IMETHOD DoubleWideString4(const PRUnichar *in_str, PRUint32 *count, PRUnichar **out_str); \ + NS_IMETHOD UpWideString(PRUint32 count, PRUnichar **str); \ + NS_IMETHOD UpWideString2(PRUint32 count, const PRUnichar *in_str, PRUnichar **out_str); \ + NS_IMETHOD GetFixedWideString(PRUint32 count, char **out_str); \ + NS_IMETHOD GetStrings(PRUint32 *count, char ***str); \ + NS_IMETHOD UpOctetArray(PRUint32 *count, PRUint8 **data); \ + NS_IMETHOD UpOctetArray2(PRUint32 *count, PRUint8 **data); \ + NS_IMETHOD CheckInterfaceArray(PRUint32 count, nsISupports **data, PRBool *all_non_null); \ + NS_IMETHOD CopyInterfaceArray(PRUint32 count, nsISupports **data, nsISupports ***out_data, PRUint32 *out_count); \ + NS_IMETHOD GetInterfaceArray(PRUint32 *count, nsISupports ***data); \ + NS_IMETHOD ExtendInterfaceArray(PRUint32 *count, nsISupports ***data); \ + NS_IMETHOD CheckIIDArray(PRUint32 count, const nsIID & *data, PRBool *all_mine); \ + NS_IMETHOD GetIIDArray(PRUint32 *count, nsIID & **data); \ + NS_IMETHOD ExtendIIDArray(PRUint32 *count, nsIID & **data); \ + NS_IMETHOD SumArrays(PRUint32 count, PRInt32 *array1, PRInt32 *array2, PRInt32 *result); \ + NS_IMETHOD GetArrays(PRUint32 *count, PRInt32 **array1, PRInt32 **array2); \ + NS_IMETHOD GetFixedArray(PRUint32 count, PRInt32 **array1); \ + NS_IMETHOD CopyArray(PRUint32 count, PRInt32 *array1, PRInt32 **array2); \ + NS_IMETHOD CopyAndDoubleArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2); \ + NS_IMETHOD AppendArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2); \ + NS_IMETHOD AppendVariant(nsIVariant *variant, nsIVariant **result); \ + NS_IMETHOD CopyVariant(nsIVariant *variant, nsIVariant **_retval); \ + NS_IMETHOD SumVariants(PRUint32 incount, nsIVariant **variants, nsIVariant **_retval); + +/* Use this macro to declare functions that forward the behavior of this interface to another object. */ +#define NS_FORWARD_NSIPYTHONTESTINTERFACEEXTRA(_to) \ + NS_IMETHOD MultiplyEachItemInIntegerArray(PRInt32 val, PRUint32 count, PRInt32 **valueArray) { return _to MultiplyEachItemInIntegerArray(val, count, valueArray); } \ + NS_IMETHOD MultiplyEachItemInIntegerArrayAndAppend(PRInt32 val, PRUint32 *count, PRInt32 **valueArray) { return _to MultiplyEachItemInIntegerArrayAndAppend(val, count, valueArray); } \ + NS_IMETHOD CompareStringArrays(const char **arr1, const char **arr2, PRUint32 count, PRInt16 *result) { return _to CompareStringArrays(arr1, arr2, count, result); } \ + NS_IMETHOD DoubleStringArray(PRUint32 *count, char ***valueArray) { return _to DoubleStringArray(count, valueArray); } \ + NS_IMETHOD ReverseStringArray(PRUint32 count, char ***valueArray) { return _to ReverseStringArray(count, valueArray); } \ + NS_IMETHOD DoubleString(PRUint32 *count, char **str) { return _to DoubleString(count, str); } \ + NS_IMETHOD DoubleString2(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) { return _to DoubleString2(in_count, in_str, out_count, out_str); } \ + NS_IMETHOD DoubleString3(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) { return _to DoubleString3(in_count, in_str, out_count, out_str); } \ + NS_IMETHOD DoubleString4(const char *in_str, PRUint32 *count, char **out_str) { return _to DoubleString4(in_str, count, out_str); } \ + NS_IMETHOD UpString(PRUint32 count, char **str) { return _to UpString(count, str); } \ + NS_IMETHOD UpString2(PRUint32 count, const char *in_str, char **out_str) { return _to UpString2(count, in_str, out_str); } \ + NS_IMETHOD CopyUTF8String(const nsACString & in_str, nsACString & out_str) { return _to CopyUTF8String(in_str, out_str); } \ + NS_IMETHOD CopyUTF8String2(const nsACString & in_str, nsACString & out_str) { return _to CopyUTF8String2(in_str, out_str); } \ + NS_IMETHOD GetFixedString(PRUint32 count, char **out_str) { return _to GetFixedString(count, out_str); } \ + NS_IMETHOD DoubleWideString(PRUint32 *count, PRUnichar **str) { return _to DoubleWideString(count, str); } \ + NS_IMETHOD DoubleWideString2(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) { return _to DoubleWideString2(in_count, in_str, out_count, out_str); } \ + NS_IMETHOD DoubleWideString3(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) { return _to DoubleWideString3(in_count, in_str, out_count, out_str); } \ + NS_IMETHOD DoubleWideString4(const PRUnichar *in_str, PRUint32 *count, PRUnichar **out_str) { return _to DoubleWideString4(in_str, count, out_str); } \ + NS_IMETHOD UpWideString(PRUint32 count, PRUnichar **str) { return _to UpWideString(count, str); } \ + NS_IMETHOD UpWideString2(PRUint32 count, const PRUnichar *in_str, PRUnichar **out_str) { return _to UpWideString2(count, in_str, out_str); } \ + NS_IMETHOD GetFixedWideString(PRUint32 count, char **out_str) { return _to GetFixedWideString(count, out_str); } \ + NS_IMETHOD GetStrings(PRUint32 *count, char ***str) { return _to GetStrings(count, str); } \ + NS_IMETHOD UpOctetArray(PRUint32 *count, PRUint8 **data) { return _to UpOctetArray(count, data); } \ + NS_IMETHOD UpOctetArray2(PRUint32 *count, PRUint8 **data) { return _to UpOctetArray2(count, data); } \ + NS_IMETHOD CheckInterfaceArray(PRUint32 count, nsISupports **data, PRBool *all_non_null) { return _to CheckInterfaceArray(count, data, all_non_null); } \ + NS_IMETHOD CopyInterfaceArray(PRUint32 count, nsISupports **data, nsISupports ***out_data, PRUint32 *out_count) { return _to CopyInterfaceArray(count, data, out_data, out_count); } \ + NS_IMETHOD GetInterfaceArray(PRUint32 *count, nsISupports ***data) { return _to GetInterfaceArray(count, data); } \ + NS_IMETHOD ExtendInterfaceArray(PRUint32 *count, nsISupports ***data) { return _to ExtendInterfaceArray(count, data); } \ + NS_IMETHOD CheckIIDArray(PRUint32 count, const nsIID & *data, PRBool *all_mine) { return _to CheckIIDArray(count, data, all_mine); } \ + NS_IMETHOD GetIIDArray(PRUint32 *count, nsIID & **data) { return _to GetIIDArray(count, data); } \ + NS_IMETHOD ExtendIIDArray(PRUint32 *count, nsIID & **data) { return _to ExtendIIDArray(count, data); } \ + NS_IMETHOD SumArrays(PRUint32 count, PRInt32 *array1, PRInt32 *array2, PRInt32 *result) { return _to SumArrays(count, array1, array2, result); } \ + NS_IMETHOD GetArrays(PRUint32 *count, PRInt32 **array1, PRInt32 **array2) { return _to GetArrays(count, array1, array2); } \ + NS_IMETHOD GetFixedArray(PRUint32 count, PRInt32 **array1) { return _to GetFixedArray(count, array1); } \ + NS_IMETHOD CopyArray(PRUint32 count, PRInt32 *array1, PRInt32 **array2) { return _to CopyArray(count, array1, array2); } \ + NS_IMETHOD CopyAndDoubleArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) { return _to CopyAndDoubleArray(count, array1, array2); } \ + NS_IMETHOD AppendArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) { return _to AppendArray(count, array1, array2); } \ + NS_IMETHOD AppendVariant(nsIVariant *variant, nsIVariant **result) { return _to AppendVariant(variant, result); } \ + NS_IMETHOD CopyVariant(nsIVariant *variant, nsIVariant **_retval) { return _to CopyVariant(variant, _retval); } \ + NS_IMETHOD SumVariants(PRUint32 incount, nsIVariant **variants, nsIVariant **_retval) { return _to SumVariants(incount, variants, _retval); } + +/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */ +#define NS_FORWARD_SAFE_NSIPYTHONTESTINTERFACEEXTRA(_to) \ + NS_IMETHOD MultiplyEachItemInIntegerArray(PRInt32 val, PRUint32 count, PRInt32 **valueArray) { return !_to ? NS_ERROR_NULL_POINTER : _to->MultiplyEachItemInIntegerArray(val, count, valueArray); } \ + NS_IMETHOD MultiplyEachItemInIntegerArrayAndAppend(PRInt32 val, PRUint32 *count, PRInt32 **valueArray) { return !_to ? NS_ERROR_NULL_POINTER : _to->MultiplyEachItemInIntegerArrayAndAppend(val, count, valueArray); } \ + NS_IMETHOD CompareStringArrays(const char **arr1, const char **arr2, PRUint32 count, PRInt16 *result) { return !_to ? NS_ERROR_NULL_POINTER : _to->CompareStringArrays(arr1, arr2, count, result); } \ + NS_IMETHOD DoubleStringArray(PRUint32 *count, char ***valueArray) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleStringArray(count, valueArray); } \ + NS_IMETHOD ReverseStringArray(PRUint32 count, char ***valueArray) { return !_to ? NS_ERROR_NULL_POINTER : _to->ReverseStringArray(count, valueArray); } \ + NS_IMETHOD DoubleString(PRUint32 *count, char **str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleString(count, str); } \ + NS_IMETHOD DoubleString2(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleString2(in_count, in_str, out_count, out_str); } \ + NS_IMETHOD DoubleString3(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleString3(in_count, in_str, out_count, out_str); } \ + NS_IMETHOD DoubleString4(const char *in_str, PRUint32 *count, char **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleString4(in_str, count, out_str); } \ + NS_IMETHOD UpString(PRUint32 count, char **str) { return !_to ? NS_ERROR_NULL_POINTER : _to->UpString(count, str); } \ + NS_IMETHOD UpString2(PRUint32 count, const char *in_str, char **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->UpString2(count, in_str, out_str); } \ + NS_IMETHOD CopyUTF8String(const nsACString & in_str, nsACString & out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->CopyUTF8String(in_str, out_str); } \ + NS_IMETHOD CopyUTF8String2(const nsACString & in_str, nsACString & out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->CopyUTF8String2(in_str, out_str); } \ + NS_IMETHOD GetFixedString(PRUint32 count, char **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetFixedString(count, out_str); } \ + NS_IMETHOD DoubleWideString(PRUint32 *count, PRUnichar **str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleWideString(count, str); } \ + NS_IMETHOD DoubleWideString2(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleWideString2(in_count, in_str, out_count, out_str); } \ + NS_IMETHOD DoubleWideString3(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleWideString3(in_count, in_str, out_count, out_str); } \ + NS_IMETHOD DoubleWideString4(const PRUnichar *in_str, PRUint32 *count, PRUnichar **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->DoubleWideString4(in_str, count, out_str); } \ + NS_IMETHOD UpWideString(PRUint32 count, PRUnichar **str) { return !_to ? NS_ERROR_NULL_POINTER : _to->UpWideString(count, str); } \ + NS_IMETHOD UpWideString2(PRUint32 count, const PRUnichar *in_str, PRUnichar **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->UpWideString2(count, in_str, out_str); } \ + NS_IMETHOD GetFixedWideString(PRUint32 count, char **out_str) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetFixedWideString(count, out_str); } \ + NS_IMETHOD GetStrings(PRUint32 *count, char ***str) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetStrings(count, str); } \ + NS_IMETHOD UpOctetArray(PRUint32 *count, PRUint8 **data) { return !_to ? NS_ERROR_NULL_POINTER : _to->UpOctetArray(count, data); } \ + NS_IMETHOD UpOctetArray2(PRUint32 *count, PRUint8 **data) { return !_to ? NS_ERROR_NULL_POINTER : _to->UpOctetArray2(count, data); } \ + NS_IMETHOD CheckInterfaceArray(PRUint32 count, nsISupports **data, PRBool *all_non_null) { return !_to ? NS_ERROR_NULL_POINTER : _to->CheckInterfaceArray(count, data, all_non_null); } \ + NS_IMETHOD CopyInterfaceArray(PRUint32 count, nsISupports **data, nsISupports ***out_data, PRUint32 *out_count) { return !_to ? NS_ERROR_NULL_POINTER : _to->CopyInterfaceArray(count, data, out_data, out_count); } \ + NS_IMETHOD GetInterfaceArray(PRUint32 *count, nsISupports ***data) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetInterfaceArray(count, data); } \ + NS_IMETHOD ExtendInterfaceArray(PRUint32 *count, nsISupports ***data) { return !_to ? NS_ERROR_NULL_POINTER : _to->ExtendInterfaceArray(count, data); } \ + NS_IMETHOD CheckIIDArray(PRUint32 count, const nsIID & *data, PRBool *all_mine) { return !_to ? NS_ERROR_NULL_POINTER : _to->CheckIIDArray(count, data, all_mine); } \ + NS_IMETHOD GetIIDArray(PRUint32 *count, nsIID & **data) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetIIDArray(count, data); } \ + NS_IMETHOD ExtendIIDArray(PRUint32 *count, nsIID & **data) { return !_to ? NS_ERROR_NULL_POINTER : _to->ExtendIIDArray(count, data); } \ + NS_IMETHOD SumArrays(PRUint32 count, PRInt32 *array1, PRInt32 *array2, PRInt32 *result) { return !_to ? NS_ERROR_NULL_POINTER : _to->SumArrays(count, array1, array2, result); } \ + NS_IMETHOD GetArrays(PRUint32 *count, PRInt32 **array1, PRInt32 **array2) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetArrays(count, array1, array2); } \ + NS_IMETHOD GetFixedArray(PRUint32 count, PRInt32 **array1) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetFixedArray(count, array1); } \ + NS_IMETHOD CopyArray(PRUint32 count, PRInt32 *array1, PRInt32 **array2) { return !_to ? NS_ERROR_NULL_POINTER : _to->CopyArray(count, array1, array2); } \ + NS_IMETHOD CopyAndDoubleArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) { return !_to ? NS_ERROR_NULL_POINTER : _to->CopyAndDoubleArray(count, array1, array2); } \ + NS_IMETHOD AppendArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) { return !_to ? NS_ERROR_NULL_POINTER : _to->AppendArray(count, array1, array2); } \ + NS_IMETHOD AppendVariant(nsIVariant *variant, nsIVariant **result) { return !_to ? NS_ERROR_NULL_POINTER : _to->AppendVariant(variant, result); } \ + NS_IMETHOD CopyVariant(nsIVariant *variant, nsIVariant **_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->CopyVariant(variant, _retval); } \ + NS_IMETHOD SumVariants(PRUint32 incount, nsIVariant **variants, nsIVariant **_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->SumVariants(incount, variants, _retval); } + +#if 0 +/* Use the code below as a template for the implementation class for this interface. */ + +/* Header file */ +class nsPythonTestInterfaceExtra : public nsIPythonTestInterfaceExtra +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIPYTHONTESTINTERFACEEXTRA + + nsPythonTestInterfaceExtra(); + +private: + ~nsPythonTestInterfaceExtra(); + +protected: + /* additional members */ +}; + +/* Implementation file */ +NS_IMPL_ISUPPORTS1(nsPythonTestInterfaceExtra, nsIPythonTestInterfaceExtra) + +nsPythonTestInterfaceExtra::nsPythonTestInterfaceExtra() +{ + /* member initializers and constructor code */ +} + +nsPythonTestInterfaceExtra::~nsPythonTestInterfaceExtra() +{ + /* destructor code */ +} + +/* void MultiplyEachItemInIntegerArray (in PRInt32 val, in PRUint32 count, [array, size_is (count)] inout PRInt32 valueArray); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::MultiplyEachItemInIntegerArray(PRInt32 val, PRUint32 count, PRInt32 **valueArray) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void MultiplyEachItemInIntegerArrayAndAppend (in PRInt32 val, inout PRUint32 count, [array, size_is (count)] inout PRInt32 valueArray); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::MultiplyEachItemInIntegerArrayAndAppend(PRInt32 val, PRUint32 *count, PRInt32 **valueArray) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void CompareStringArrays ([array, size_is (count)] in string arr1, [array, size_is (count)] in string arr2, in unsigned long count, [retval] out short result); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::CompareStringArrays(const char **arr1, const char **arr2, PRUint32 count, PRInt16 *result) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void DoubleStringArray (inout PRUint32 count, [array, size_is (count)] inout string valueArray); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleStringArray(PRUint32 *count, char ***valueArray) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void ReverseStringArray (in PRUint32 count, [array, size_is (count)] inout string valueArray); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::ReverseStringArray(PRUint32 count, char ***valueArray) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void DoubleString (inout PRUint32 count, [size_is (count)] inout string str); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleString(PRUint32 *count, char **str) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void DoubleString2 (in PRUint32 in_count, [size_is (in_count)] in string in_str, out PRUint32 out_count, [size_is (out_count)] out string out_str); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleString2(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void DoubleString3 (in PRUint32 in_count, [size_is (in_count)] in string in_str, out PRUint32 out_count, [size_is (out_count), retval] out string out_str); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleString3(PRUint32 in_count, const char *in_str, PRUint32 *out_count, char **out_str) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void DoubleString4 ([size_is (count)] in string in_str, inout PRUint32 count, [size_is (count)] out string out_str); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleString4(const char *in_str, PRUint32 *count, char **out_str) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void UpString (in PRUint32 count, [size_is (count)] inout string str); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::UpString(PRUint32 count, char **str) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void UpString2 (in PRUint32 count, [size_is (count)] in string in_str, [size_is (count)] out string out_str); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::UpString2(PRUint32 count, const char *in_str, char **out_str) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void CopyUTF8String (in AUTF8String in_str, out AUTF8String out_str); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::CopyUTF8String(const nsACString & in_str, nsACString & out_str) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void CopyUTF8String2 (in AUTF8String in_str, out AUTF8String out_str); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::CopyUTF8String2(const nsACString & in_str, nsACString & out_str) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void GetFixedString (in PRUint32 count, [size_is (count)] out string out_str); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::GetFixedString(PRUint32 count, char **out_str) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void DoubleWideString (inout PRUint32 count, [size_is (count)] inout wstring str); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleWideString(PRUint32 *count, PRUnichar **str) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void DoubleWideString2 (in PRUint32 in_count, [size_is (in_count)] in wstring in_str, out PRUint32 out_count, [size_is (out_count)] out wstring out_str); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleWideString2(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void DoubleWideString3 (in PRUint32 in_count, [size_is (in_count)] in wstring in_str, out PRUint32 out_count, [size_is (out_count), retval] out wstring out_str); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleWideString3(PRUint32 in_count, const PRUnichar *in_str, PRUint32 *out_count, PRUnichar **out_str) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void DoubleWideString4 ([size_is (count)] in wstring in_str, inout PRUint32 count, [size_is (count)] out wstring out_str); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::DoubleWideString4(const PRUnichar *in_str, PRUint32 *count, PRUnichar **out_str) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void UpWideString (in PRUint32 count, [size_is (count)] inout wstring str); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::UpWideString(PRUint32 count, PRUnichar **str) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void UpWideString2 (in PRUint32 count, [size_is (count)] in wstring in_str, [size_is (count)] out wstring out_str); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::UpWideString2(PRUint32 count, const PRUnichar *in_str, PRUnichar **out_str) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void GetFixedWideString (in PRUint32 count, [size_is (count)] out string out_str); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::GetFixedWideString(PRUint32 count, char **out_str) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void GetStrings (out PRUint32 count, [array, size_is (count), retval] out string str); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::GetStrings(PRUint32 *count, char ***str) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void UpOctetArray (inout PRUint32 count, [array, size_is (count)] inout PRUint8 data); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::UpOctetArray(PRUint32 *count, PRUint8 **data) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void UpOctetArray2 (inout PRUint32 count, [array, size_is (count)] inout PRUint8 data); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::UpOctetArray2(PRUint32 *count, PRUint8 **data) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void CheckInterfaceArray (in PRUint32 count, [array, size_is (count)] in nsISupports data, [retval] out PRBool all_non_null); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::CheckInterfaceArray(PRUint32 count, nsISupports **data, PRBool *all_non_null) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void CopyInterfaceArray (in PRUint32 count, [array, size_is (count)] in nsISupports data, [array, size_is (out_count)] out nsISupports out_data, out PRUint32 out_count); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::CopyInterfaceArray(PRUint32 count, nsISupports **data, nsISupports ***out_data, PRUint32 *out_count) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void GetInterfaceArray (out PRUint32 count, [array, size_is (count)] out nsISupports data); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::GetInterfaceArray(PRUint32 *count, nsISupports ***data) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void ExtendInterfaceArray (inout PRUint32 count, [array, size_is (count)] inout nsISupports data); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::ExtendInterfaceArray(PRUint32 *count, nsISupports ***data) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void CheckIIDArray (in PRUint32 count, [array, size_is (count)] in nsIIDRef data, [retval] out PRBool all_mine); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::CheckIIDArray(PRUint32 count, const nsIID & *data, PRBool *all_mine) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void GetIIDArray (out PRUint32 count, [array, size_is (count)] out nsIIDRef data); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::GetIIDArray(PRUint32 *count, nsIID & **data) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void ExtendIIDArray (inout PRUint32 count, [array, size_is (count)] inout nsIIDRef data); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::ExtendIIDArray(PRUint32 *count, nsIID & **data) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void SumArrays (in PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] in PRInt32 array2, [retval] out PRInt32 result); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::SumArrays(PRUint32 count, PRInt32 *array1, PRInt32 *array2, PRInt32 *result) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void GetArrays (out PRUint32 count, [array, size_is (count)] out PRInt32 array1, [array, size_is (count)] out PRInt32 array2); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::GetArrays(PRUint32 *count, PRInt32 **array1, PRInt32 **array2) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void GetFixedArray (in PRUint32 count, [array, size_is (count)] out PRInt32 array1); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::GetFixedArray(PRUint32 count, PRInt32 **array1) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void CopyArray (in PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] out PRInt32 array2); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::CopyArray(PRUint32 count, PRInt32 *array1, PRInt32 **array2) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void CopyAndDoubleArray (inout PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] out PRInt32 array2); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::CopyAndDoubleArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void AppendArray (inout PRUint32 count, [array, size_is (count)] in PRInt32 array1, [array, size_is (count)] inout PRInt32 array2); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::AppendArray(PRUint32 *count, PRInt32 *array1, PRInt32 **array2) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void AppendVariant (in nsIVariant variant, inout nsIVariant result); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::AppendVariant(nsIVariant *variant, nsIVariant **result) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* nsIVariant CopyVariant (in nsIVariant variant); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::CopyVariant(nsIVariant *variant, nsIVariant **_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* nsIVariant SumVariants (in PRUint32 incount, [array, size_is (incount)] in nsIVariant variants); */ +NS_IMETHODIMP nsPythonTestInterfaceExtra::SumVariants(PRUint32 incount, nsIVariant **variants, nsIVariant **_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* End of implementation class template. */ +#endif + + +/* starting interface: nsIPythonTestInterfaceDOMStrings */ +#define NS_IPYTHONTESTINTERFACEDOMSTRINGS_IID_STR "657ae651-a973-4818-8c06-f4b948b3d758" + +#define NS_IPYTHONTESTINTERFACEDOMSTRINGS_IID \ + {0x657ae651, 0xa973, 0x4818, \ + { 0x8c, 0x06, 0xf4, 0xb9, 0x48, 0xb3, 0xd7, 0x58 }} + +class NS_NO_VTABLE nsIPythonTestInterfaceDOMStrings : public nsIPythonTestInterfaceExtra { + public: + + NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPYTHONTESTINTERFACEDOMSTRINGS_IID) + + /* DOMString GetDOMStringResult (in PRInt32 length); */ + NS_IMETHOD GetDOMStringResult(PRInt32 length, nsAString & _retval) = 0; + + /* void GetDOMStringOut (in PRInt32 length, [retval] out DOMString s); */ + NS_IMETHOD GetDOMStringOut(PRInt32 length, nsAString & s) = 0; + + /* PRUint32 GetDOMStringLength (in DOMString s); */ + NS_IMETHOD GetDOMStringLength(const nsAString & s, PRUint32 *_retval) = 0; + + /* PRUint32 GetDOMStringRefLength (in DOMStringRef s); */ + NS_IMETHOD GetDOMStringRefLength(const nsAString & s, PRUint32 *_retval) = 0; + + /* PRUint32 GetDOMStringPtrLength (in DOMStringPtr s); */ + NS_IMETHOD GetDOMStringPtrLength(const nsAString * s, PRUint32 *_retval) = 0; + + /* void ConcatDOMStrings (in DOMString s1, in DOMString s2, out DOMString ret); */ + NS_IMETHOD ConcatDOMStrings(const nsAString & s1, const nsAString & s2, nsAString & ret) = 0; + + /* attribute DOMString domstring_value; */ + NS_IMETHOD GetDomstring_value(nsAString & aDomstring_value) = 0; + NS_IMETHOD SetDomstring_value(const nsAString & aDomstring_value) = 0; + + /* readonly attribute DOMString domstring_value_ro; */ + NS_IMETHOD GetDomstring_value_ro(nsAString & aDomstring_value_ro) = 0; + +}; + +/* Use this macro when declaring classes that implement this interface. */ +#define NS_DECL_NSIPYTHONTESTINTERFACEDOMSTRINGS \ + NS_IMETHOD GetDOMStringResult(PRInt32 length, nsAString & _retval); \ + NS_IMETHOD GetDOMStringOut(PRInt32 length, nsAString & s); \ + NS_IMETHOD GetDOMStringLength(const nsAString & s, PRUint32 *_retval); \ + NS_IMETHOD GetDOMStringRefLength(const nsAString & s, PRUint32 *_retval); \ + NS_IMETHOD GetDOMStringPtrLength(const nsAString * s, PRUint32 *_retval); \ + NS_IMETHOD ConcatDOMStrings(const nsAString & s1, const nsAString & s2, nsAString & ret); \ + NS_IMETHOD GetDomstring_value(nsAString & aDomstring_value); \ + NS_IMETHOD SetDomstring_value(const nsAString & aDomstring_value); \ + NS_IMETHOD GetDomstring_value_ro(nsAString & aDomstring_value_ro); + +/* Use this macro to declare functions that forward the behavior of this interface to another object. */ +#define NS_FORWARD_NSIPYTHONTESTINTERFACEDOMSTRINGS(_to) \ + NS_IMETHOD GetDOMStringResult(PRInt32 length, nsAString & _retval) { return _to GetDOMStringResult(length, _retval); } \ + NS_IMETHOD GetDOMStringOut(PRInt32 length, nsAString & s) { return _to GetDOMStringOut(length, s); } \ + NS_IMETHOD GetDOMStringLength(const nsAString & s, PRUint32 *_retval) { return _to GetDOMStringLength(s, _retval); } \ + NS_IMETHOD GetDOMStringRefLength(const nsAString & s, PRUint32 *_retval) { return _to GetDOMStringRefLength(s, _retval); } \ + NS_IMETHOD GetDOMStringPtrLength(const nsAString * s, PRUint32 *_retval) { return _to GetDOMStringPtrLength(s, _retval); } \ + NS_IMETHOD ConcatDOMStrings(const nsAString & s1, const nsAString & s2, nsAString & ret) { return _to ConcatDOMStrings(s1, s2, ret); } \ + NS_IMETHOD GetDomstring_value(nsAString & aDomstring_value) { return _to GetDomstring_value(aDomstring_value); } \ + NS_IMETHOD SetDomstring_value(const nsAString & aDomstring_value) { return _to SetDomstring_value(aDomstring_value); } \ + NS_IMETHOD GetDomstring_value_ro(nsAString & aDomstring_value_ro) { return _to GetDomstring_value_ro(aDomstring_value_ro); } + +/* Use this macro to declare functions that forward the behavior of this interface to another object in a safe way. */ +#define NS_FORWARD_SAFE_NSIPYTHONTESTINTERFACEDOMSTRINGS(_to) \ + NS_IMETHOD GetDOMStringResult(PRInt32 length, nsAString & _retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDOMStringResult(length, _retval); } \ + NS_IMETHOD GetDOMStringOut(PRInt32 length, nsAString & s) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDOMStringOut(length, s); } \ + NS_IMETHOD GetDOMStringLength(const nsAString & s, PRUint32 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDOMStringLength(s, _retval); } \ + NS_IMETHOD GetDOMStringRefLength(const nsAString & s, PRUint32 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDOMStringRefLength(s, _retval); } \ + NS_IMETHOD GetDOMStringPtrLength(const nsAString * s, PRUint32 *_retval) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDOMStringPtrLength(s, _retval); } \ + NS_IMETHOD ConcatDOMStrings(const nsAString & s1, const nsAString & s2, nsAString & ret) { return !_to ? NS_ERROR_NULL_POINTER : _to->ConcatDOMStrings(s1, s2, ret); } \ + NS_IMETHOD GetDomstring_value(nsAString & aDomstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDomstring_value(aDomstring_value); } \ + NS_IMETHOD SetDomstring_value(const nsAString & aDomstring_value) { return !_to ? NS_ERROR_NULL_POINTER : _to->SetDomstring_value(aDomstring_value); } \ + NS_IMETHOD GetDomstring_value_ro(nsAString & aDomstring_value_ro) { return !_to ? NS_ERROR_NULL_POINTER : _to->GetDomstring_value_ro(aDomstring_value_ro); } + +#if 0 +/* Use the code below as a template for the implementation class for this interface. */ + +/* Header file */ +class nsPythonTestInterfaceDOMStrings : public nsIPythonTestInterfaceDOMStrings +{ +public: + NS_DECL_ISUPPORTS + NS_DECL_NSIPYTHONTESTINTERFACEDOMSTRINGS + + nsPythonTestInterfaceDOMStrings(); + +private: + ~nsPythonTestInterfaceDOMStrings(); + +protected: + /* additional members */ +}; + +/* Implementation file */ +NS_IMPL_ISUPPORTS1(nsPythonTestInterfaceDOMStrings, nsIPythonTestInterfaceDOMStrings) + +nsPythonTestInterfaceDOMStrings::nsPythonTestInterfaceDOMStrings() +{ + /* member initializers and constructor code */ +} + +nsPythonTestInterfaceDOMStrings::~nsPythonTestInterfaceDOMStrings() +{ + /* destructor code */ +} + +/* DOMString GetDOMStringResult (in PRInt32 length); */ +NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDOMStringResult(PRInt32 length, nsAString & _retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void GetDOMStringOut (in PRInt32 length, [retval] out DOMString s); */ +NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDOMStringOut(PRInt32 length, nsAString & s) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRUint32 GetDOMStringLength (in DOMString s); */ +NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDOMStringLength(const nsAString & s, PRUint32 *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRUint32 GetDOMStringRefLength (in DOMStringRef s); */ +NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDOMStringRefLength(const nsAString & s, PRUint32 *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* PRUint32 GetDOMStringPtrLength (in DOMStringPtr s); */ +NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDOMStringPtrLength(const nsAString * s, PRUint32 *_retval) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* void ConcatDOMStrings (in DOMString s1, in DOMString s2, out DOMString ret); */ +NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::ConcatDOMStrings(const nsAString & s1, const nsAString & s2, nsAString & ret) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* attribute DOMString domstring_value; */ +NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDomstring_value(nsAString & aDomstring_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} +NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::SetDomstring_value(const nsAString & aDomstring_value) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* readonly attribute DOMString domstring_value_ro; */ +NS_IMETHODIMP nsPythonTestInterfaceDOMStrings::GetDomstring_value_ro(nsAString & aDomstring_value_ro) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +/* End of implementation class template. */ +#endif + + +#endif /* __gen_py_test_component_h__ */ diff --git a/src/libs/xpcom18a4/python/test/test_component/py_test_component.html b/src/libs/xpcom18a4/python/test/test_component/py_test_component.html new file mode 100644 index 00000000..1e17d24c --- /dev/null +++ b/src/libs/xpcom18a4/python/test/test_component/py_test_component.html @@ -0,0 +1,182 @@ +<!-- ***** 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 PyXPCOM. + - + - The Initial Developer of the Original Code is + - ActiveState Tool Corporation. + - Portions created by the Initial Developer are Copyright (C) 2000-2001 + - the Initial Developer. All Rights Reserved. + - + - Contributor(s): + - + - 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 LGPL or the GPL. 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 ***** --> + +<center><b><font size=+2>Python Component Sample</font></b> + +<p> +<br> +Last modified +<script> +document.write(document.lastModified); +</script> +</center> + +<p>XPConnect allows JavaScript +to transparantly access and manipulate XPCOM objects; + +<p>Big Deal, I hear you say! But it also works for Python!!! + +<p> +This sample demonstrates accessing a XPCOM object through XPConnect. +The JavaScript executed when this page loads creates an instance +of the Python object by +using the <tt>Components</tt> object, then accesses it through +the <a href="py_test_component.idl">nsISample</a> interface by calling <tt>QueryInterface</tt>: +<br> +<pre> +netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); +var sample = Components.classes["component://mozilla/sample/sample-world"].createInstance(); +sample = sample.QueryInterface(Components.interfaces.nsISample); +</pre> + +<p> +The buttons on the form are connected to JavaScript event handlers which +call the methods defined in Python + + +<p><b><a name="Compiling">Compiling the idl</b> + +<p>The XPIDL compiler (xpidl on Unix, xpidl.exe on Windows, and a CodeWarrior plugin on Mac) +is compiled at build time (except on Mac) thus +you will have to build mozilla in order to test this out. If you +have already built mozilla then the compiler will be located at <tt>mozilla\dist\WIN32_D.OBJ\bin\xpidl.exe</tt>. + +<p>Once you have the XPIDL compiler enter the following command at your +prompt: +<br><tt>D:\whereever\xpcom\test\test_component>d:\mozilla\dist\WIN32_D.OBJ\bin\xpidl -I +d:\mozilla\dist\idl -m typelib py_test_component.idl</tt>. You must then copy the generated .xpt file +to the mozilla component directory. + +<p>The <tt>-I d:\mozilla\dist\idl</tt> points the compiler to the folder +containing the other idl files, needed because nsISample.idl inherits from +nsISupports.idl. The <tt>-m typelib</tt> instruction tells the compiler +to build the .XPT typelib file.</tt>. + +<p> +For more information on compilation see the <a href="http://www.mozilla.org/scriptable/xpidl/">xpidl +compiler page</a>. + +<p><b>Running the sample</b> +<p><b>NOTE: This doesnt work for me - I get an access denied error using XPConnect!</b> +<p>Using Mozilla, load this file. Pay attention +to the console when clicking "write". + +<!-- XXX keep in sync with stuff in pre tag below --> +<script> +netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); +var sample = Components.classes["Python.TestComponent"].createInstance(); +sample = sample.QueryInterface(Components.interfaces.nsIPythonTestInterface); +dump("sample = " + sample + "\n"); + +function get() +{ + var field = document.getElementById('Value'); + field.value = sample.str_value; +} + +function set() +{ + var field = document.getElementById('Value'); + sample.str_value = field.value; +} + +function poke() +{ + var field = document.getElementById('Value'); + sample.poke(field.value); +} + +function write() +{ + sample.writeValue("here is what I'm writing: "); +} +</script> + +<p> +<form name="form"> +<input type="button" value="Get" onclick="get();"> +<input type="button" value="Set" onclick="set();"> +<input type="button" value="Poke" onclick="poke();"> +<input type="text" id="Value"> +<input type="button" value="Write" onclick="write();"> +<form> + +<hr> + +<p> +JavaScript and form source: + +<!-- XXX keep in sync with actual script --> +<pre> +<script> +netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); +var sample = Components.classes["component://Python.TestComponent"].createInstance(); +sample = sample.QueryInterface(Components.interfaces.nsIPythonTestInterface); +dump("sample = " + sample + "\n"); + +function get() +{ + var field = document.getElementById('Value'); + field.value = sample.str_value; +} + +function set() +{ + var field = document.getElementById('Value'); + sample.str_value = field.value; +} + +function poke() +{ + var field = document.getElementById('Value'); + sample.poke(field.value); +} + +function write() +{ + sample.writeValue("here is what I'm writing: "); +} +</script> + +<form name="form"> +<input type="button" value="Get" onclick="get();"> +<input type="button" value="Set" onclick="set();"> +<input type="button" value="Poke" onclick="poke();"> +<input type="text" id="Value"> +<input type="button" value="Write" onclick="write();"> +<form> + +</pre> diff --git a/src/libs/xpcom18a4/python/test/test_component/py_test_component.idl b/src/libs/xpcom18a4/python/test/test_component/py_test_component.idl new file mode 100644 index 00000000..cd3e1c45 --- /dev/null +++ b/src/libs/xpcom18a4/python/test/test_component/py_test_component.idl @@ -0,0 +1,231 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Mark Hammond <MarkH@ActiveState.com> (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 ***** */ + +// NOTE: This is a TEST interface, not a DEMO interface :-) +// We try to get as many data-types etc exposed, meaning this +// doesnt really make a good demo of a "simple component" +#include "nsISupports.idl" +#include "nsIVariant.idl" + +[scriptable, uuid(1ECAED4F-E4D5-4ee7-ABF0-7D72AE1441D7)] +interface nsIPythonTestInterface : nsISupports +{ + // Some constants for us to test - one for every type supported by xpidl + const short One = 1; + const long Two = 2; + const long MinusOne = -1; + const long BigLong = 0x7FFFFFFF; + const long BiggerLong = 0xFFFFFFFF; + const unsigned long BigULong = 0xFFFFFFFF; + + // Declare every type supported as an attribute. + attribute boolean boolean_value; // PRBool + attribute octet octet_value; // PRUint8 + attribute short short_value; // PRInt16 + attribute unsigned short ushort_value; // PRUint16 + attribute long long_value; // PRInt32 + attribute unsigned long ulong_value; // PRUint32 + attribute long long long_long_value; // PRInt64 + attribute unsigned long long ulong_long_value; // PRUint64 + attribute float float_value; // float + attribute double double_value; // double + attribute char char_value; // char + attribute wchar wchar_value; // PRUnichar + attribute string string_value; // char * + attribute wstring wstring_value; // PRUnichar* + attribute AString astring_value; // nsAString & + attribute ACString acstring_value; // nsACString & + attribute AUTF8String utf8string_value; // nsAUTF8String & + attribute nsIIDRef iid_value; // an IID + attribute nsIPythonTestInterface interface_value; // A specific interface + attribute nsISupports isupports_value; // A generic interface + + // Declare every type supported as a method with an "in", "in/out" and "out" params + boolean do_boolean(in boolean p1, inout boolean p2, out boolean p3); + octet do_octet(in octet p1, inout octet p2, out octet p3); + short do_short(in short p1, inout short p2, out short p3); + unsigned short do_unsigned_short(in unsigned short p1, inout unsigned short p2, out unsigned short p3); + long do_long(in long p1, inout long p2, out long p3); + unsigned long do_unsigned_long(in unsigned long p1, inout unsigned long p2, out unsigned long p3); + long long do_long_long(in long long p1, inout long long p2, out long long p3); + unsigned long long do_unsigned_long_long(in unsigned long long p1, inout unsigned long long p2, out unsigned long long p3); + float do_float(in float p1, inout float p2, out float p3); + double do_double(in double p1, inout double p2, out double p3); + char do_char(in char p1, inout char p2, out char p3); + wchar do_wchar(in wchar p1, inout wchar p2, out wchar p3); + string do_string(in string p1, inout string p2, out string p3); + wstring do_wstring(in wstring p1, inout wstring p2, out wstring p3); + nsIIDRef do_nsIIDRef(in nsIIDRef p1, inout nsIIDRef p2, out nsIIDRef p3); + nsIPythonTestInterface do_nsIPythonTestInterface(in nsIPythonTestInterface p1, inout nsIPythonTestInterface p2, out nsIPythonTestInterface p3); + nsISupports do_nsISupports(in nsISupports p1, inout nsISupports p2, out nsISupports p3); + void do_nsISupportsIs(in nsIIDRef iid, [iid_is(iid),retval] out nsQIResult result); +// Do I really need these?? +// void do_nsISupportsIs2(inout nsIIDRef iid, [iid_is(iid)] inout nsQIResult result); +// void do_nsISupportsIs3(out nsIIDRef iid, [iid_is(iid)] inout nsQIResult result); +// void do_nsISupportsIs4(out nsIIDRef iid, [iid_is(iid)] out nsQIResult result); +}; + +// Another interface - we use another interface purely for testing purposes - +// We ensure that the entire interface hierarcy is available correctly. +[scriptable, uuid(B38D1538-FE92-42c3-831F-285242EDEEA4)] +interface nsIPythonTestInterfaceExtra : nsIPythonTestInterface +{ + // These were copied from the XPCOM test 'xpctest.idl' + // (and a few extras added) + void MultiplyEachItemInIntegerArray( + in PRInt32 val, + in PRUint32 count, + [array, size_is(count)] inout PRInt32 valueArray); + void MultiplyEachItemInIntegerArrayAndAppend( + in PRInt32 val, + inout PRUint32 count, + [array, size_is(count)] inout PRInt32 valueArray); + + // Note that this method shares a single "size_is" between 2 params! + void CompareStringArrays([array, size_is(count)] in string arr1, + [array, size_is(count)] in string arr2, + in unsigned long count, + [retval] out short result); + + void DoubleStringArray(inout PRUint32 count, + [array, size_is(count)] inout string valueArray); + void ReverseStringArray(in PRUint32 count, + [array, size_is(count)] inout string valueArray); + + // One count, one inout array. + void DoubleString(inout PRUint32 count, + [size_is(count)] inout string str); + // One in count and in array, plus out count and out array + void DoubleString2(in PRUint32 in_count, [size_is(in_count)] in string in_str, + out PRUint32 out_count, [size_is(out_count)] out string out_str); + // As per DoubleString2, but out string also marked retval + void DoubleString3(in PRUint32 in_count, [size_is(in_count)] in string in_str, + out PRUint32 out_count, [size_is(out_count), retval] out string out_str); + // One in array, one out array, one share inout count. + void DoubleString4([size_is(count)] in string in_str, inout PRUint32 count, [size_is(count)] out string out_str); + // UpString defines the count as only "in" - meaning the result must be the same size + void UpString(in PRUint32 count, + [size_is(count)] inout string str); + // UpString2 defines count as only "in", and a string as only "out" + void UpString2(in PRUint32 count, + [size_is(count)] in string in_str, + [size_is(count)]out string out_str); + void CopyUTF8String(in AUTF8String in_str, out AUTF8String out_str); + void CopyUTF8String2(in AUTF8String in_str, out AUTF8String out_str); + // Test we can get an "out" array with an "in" size (and the size is not used anywhere as a size for an in!) + void GetFixedString(in PRUint32 count, [size_is(count)]out string out_str); + + void DoubleWideString(inout PRUint32 count, + [size_is(count)] inout wstring str); + void DoubleWideString2(in PRUint32 in_count, [size_is(in_count)] in wstring in_str, + out PRUint32 out_count, [size_is(out_count)] out wstring out_str); + void DoubleWideString3(in PRUint32 in_count, [size_is(in_count)] in wstring in_str, + out PRUint32 out_count, [size_is(out_count), retval] out wstring out_str); + void DoubleWideString4([size_is(count)] in wstring in_str, inout PRUint32 count, [size_is(count)] out wstring out_str); + // UpWideString defines the count as only "in" - meaning the result must be the same size + void UpWideString(in PRUint32 count, + [size_is(count)] inout wstring str); + // UpWideString2 defines count as only "in", and a string as only "out" + void UpWideString2(in PRUint32 count, + [size_is(count)] in wstring in_str, + [size_is(count)]out wstring out_str); + // Test we can get an "out" array with an "in" size (and the size is not used anywhere as a size for an in!) + void GetFixedWideString(in PRUint32 count, [size_is(count)]out string out_str); + + void GetStrings(out PRUint32 count, + [retval, array, size_is(count)] out string str); + + void UpOctetArray(inout PRUint32 count, + [array, size_is(count)] inout PRUint8 data); + + void UpOctetArray2(inout PRUint32 count, + [array, size_is(count)] inout PRUint8 data); + + // Arrays of interfaces + void CheckInterfaceArray(in PRUint32 count, + [array, size_is(count)] in nsISupports data, + [retval] out PRBool all_non_null); + void CopyInterfaceArray(in PRUint32 count, + [array, size_is(count)] in nsISupports data, + [array, size_is(out_count)] out nsISupports out_data, + out PRUint32 out_count); + void GetInterfaceArray(out PRUint32 count, + [array, size_is(count)] out nsISupports data); + void ExtendInterfaceArray(inout PRUint32 count, + [array, size_is(count)] inout nsISupports data); + + // Arrays of IIDs + void CheckIIDArray(in PRUint32 count, + [array, size_is(count)] in nsIIDRef data, + [retval] out PRBool all_mine); + void GetIIDArray(out PRUint32 count, + [array, size_is(count)] out nsIIDRef data); + void ExtendIIDArray(inout PRUint32 count, + [array, size_is(count)] inout nsIIDRef data); + + // More specific tests. + // Test our count param can be shared as an "in" param. + void SumArrays(in PRUint32 count, [array, size_is(count)]in PRInt32 array1, [array, size_is(count)]in PRInt32 array2, [retval]out PRInt32 result); + // Test our count param can be shared as an "out" param. + void GetArrays(out PRUint32 count, [array, size_is(count)]out PRInt32 array1, [array, size_is(count)]out PRInt32 array2); + // Test we can get an "out" array with an "in" size (and the size is not used anywhere as a size for an in!) + void GetFixedArray(in PRUint32 count, [array, size_is(count)]out PRInt32 array1); + // Test our "in" count param can be shared as one "in", plus one "out" param. + void CopyArray(in PRUint32 count, [array, size_is(count)]in PRInt32 array1, [array, size_is(count)]out PRInt32 array2); + // Test our "in-out" count param can be shared as one "in", plus one "out" param. + void CopyAndDoubleArray(inout PRUint32 count, [array, size_is(count)]in PRInt32 array1, [array, size_is(count)]out PRInt32 array2); + // Test our "in-out" count param can be shared as one "in", plus one "in-out" param. + 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 +// have their own interface for no real good reason ;-) +[scriptable, uuid(657ae651-a973-4818-8c06-f4b948b3d758)] +interface nsIPythonTestInterfaceDOMStrings : nsIPythonTestInterfaceExtra +{ + DOMString GetDOMStringResult(in PRInt32 length); + void GetDOMStringOut(in PRInt32 length, [retval] out DOMString s); + PRUint32 GetDOMStringLength(in DOMString s); + PRUint32 GetDOMStringRefLength(in DOMStringRef s); + PRUint32 GetDOMStringPtrLength(in DOMStringPtr s); + void ConcatDOMStrings(in DOMString s1, in DOMString s2, out DOMString ret); + attribute DOMString domstring_value; + readonly attribute DOMString domstring_value_ro; +}; diff --git a/src/libs/xpcom18a4/python/test/test_component/py_test_component.py b/src/libs/xpcom18a4/python/test/test_component/py_test_component.py new file mode 100755 index 00000000..c0373de9 --- /dev/null +++ b/src/libs/xpcom18a4/python/test/test_component/py_test_component.py @@ -0,0 +1,421 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# ActiveState Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000, 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Hammond <MarkH@ActiveState.com> (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 ***** + +# NOTE: This is a TEST interface, not a DEMO interface :-) +# We try to get as many data-types etc exposed, meaning this +# doesnt really make a good demo of a "simple component" + + +from xpcom import components, verbose + +class PythonTestComponent: + # Note we only list the "child" interface, not our intermediate interfaces + # (which we must, by definition, also support) + _com_interfaces_ = components.interfaces.nsIPythonTestInterfaceDOMStrings + _reg_clsid_ = "{7EE4BDC6-CB53-42c1-A9E4-616B8E012ABA}" + _reg_contractid_ = "Python.TestComponent" + def __init__(self): + self.boolean_value = 1 + self.octet_value = 2 + self.short_value = 3 + self.ushort_value = 4 + self.long_value = 5 + self.ulong_value = 6 + self.long_long_value = 7 + self.ulong_long_value = 8 + self.float_value = 9.0 + self.double_value = 10.0 + self.char_value = "a" + self.wchar_value = "b" + self.string_value = "cee" + self.wstring_value = "dee" + self.astring_value = "astring" + self.acstring_value = "acstring" + self.utf8string_value = "utf8string" + self.iid_value = self._reg_clsid_ + self.interface_value = None + self.isupports_value = None + self.domstring_value = "dom" + + def __del__(self): + if verbose: + print "Python.TestComponent: __del__ method called - object is destructing" + + def do_boolean(self, p1, p2): + # boolean do_boolean(in boolean p1, inout boolean p2, out boolean p3); + ret = p1 ^ p2 + return ret, not ret, ret + + def do_octet(self, p1, p2): + # octet do_octet(in octet p1, inout octet p2, out octet p3); + return p1+p2, p1-p2, p1*p2 + + def do_short(self, p1, p2): + # short do_short(in short p1, inout short p2, out short p3); + return p1+p2, p1-p2, p1*p2 + + def do_unsigned_short(self, p1, p2): + # unsigned short do_unsigned_short(in unsigned short p1, inout unsigned short p2, out unsigned short p3); + return p1+p2, p1-p2, p1*p2 + def do_long(self, p1, p2): + # long do_long(in long p1, inout long p2, out long p3); + return p1+p2, p1-p2, p1*p2 + + def do_unsigned_long(self, p1, p2): + # unsigned long do_unsigned_long(in unsigned long p1, inout unsigned long p2, out unsigned long p3); + return p1+p2, p1-p2, p1*p2 + def do_long_long(self, p1, p2): + # long long do_long_long(in long long p1, inout long long p2, out long long p3); + return p1+p2, p1-p2, p1*p2 + def do_unsigned_long_long(self, p1, p2): + # unsigned long long do_unsigned_long_long(in unsigned long long p1, inout unsigned long long p2, out unsigned long long p3); + return p1+p2, p1-p2, p1*p2 + def do_float(self, p1, p2): + # float do_float(in float p1, inout float p2, out float p3); + return p1+p2, p1-p2, p1*p2 + def do_double(self, p1, p2): + # double do_double(in double p1, inout double p2, out double p3); + return p1+p2, p1-p2, p1*p2 + def do_char(self, p1, p2): + # char do_char(in char p1, inout char p2, out char p3); + return chr(ord(p1)+ord(p2)), p2, p1 + def do_wchar(self, p1, p2): + # wchar do_wchar(in wchar p1, inout wchar p2, out wchar p3); + return chr(ord(p1)+ord(p2)), p2, p1 + def do_string(self, p1, p2): + # string do_string(in string p1, inout string p2, out string p3); + ret = "" + if p1 is not None: ret = ret + p1 + if p2 is not None: ret = ret + p2 + return ret, p1, p2 + def do_wstring(self, p1, p2): + # wstring do_wstring(in wstring p1, inout wstring p2, out wstring p3); + ret = u"" + if p1 is not None: ret = ret + p1 + if p2 is not None: ret = ret + p2 + return ret, p1, p2 + def do_nsIIDRef(self, p1, p2): + # nsIIDRef do_nsIIDRef(in nsIIDRef p1, inout nsIIDRef p2, out nsIIDRef p3); + return p1, self._reg_clsid_, p2 + def do_nsIPythonTestInterface(self, p1, p2): + # nsIPythonTestInterface do_nsIPythonTestInterface(in nsIPythonTestInterface p1, inout nsIPythonTestInterface p2, out nsIPythonTestInterface p3); + return p2, p1, self + def do_nsISupports(self, p1, p2): + # nsISupports do_nsISupports(in nsISupports p1, inout nsISupports p2, out nsISupports p3); + return self, p1, p2 + def do_nsISupportsIs(self, iid): + # void do_nsISupportsIs(in nsIIDRef iid, [iid_is(iid),retval] out nsQIResult result) + # Note the framework does the QI etc on us, so there is no real point me doing it. + # (However, user code _should_ do the QI - otherwise any errors are deemed "internal" (as they + # are raised by the C++ framework), and therefore logged to the console, etc. + # A user QI allows the user to fail gracefully, whatever gracefully means for them! + return self +# Do I really need these?? +## def do_nsISupportsIs2(self, iid, interface): +## # void do_nsISupportsIs2(inout nsIIDRef iid, [iid_is(iid),retval] inout nsQIResult result); +## return iid, interface +## def do_nsISupportsIs3(self, interface): +## # void do_nsISupportsIs3(out nsIIDRef iid, [iid_is(iid)] inout nsQIResult result); +## return self._com_interfaces_, interface +## def do_nsISupportsIs4(self): +## # void do_nsISupportsIs4(out nsIIDRef iid, [iid_is(iid)] out nsQIResult result); +## return self._com_interfaces_, self + + # Methods from the nsIPythonTestInterfaceExtra interface + # + def MultiplyEachItemInIntegerArray(self, val, valueArray): + # void MultiplyEachItemInIntegerArray( + # in PRInt32 val, + # in PRUint32 count, + # [array, size_is(count)] inout PRInt32 valueArray); + # NOTE - the "sizeis" params are never passed to or returned from Python! + results = [] + for item in valueArray: + results.append(item * val) + return results + def MultiplyEachItemInIntegerArrayAndAppend(self, val, valueArray): + #void MultiplyEachItemInIntegerArrayAndAppend( + # in PRInt32 val, + # inout PRUint32 count, + # [array, size_is(count)] inout PRInt32 valueArray); + results = valueArray[:] + for item in valueArray: + results.append(item * val) + return results + def DoubleStringArray(self, valueArray): + # void DoubleStringArray(inout PRUint32 count, + # [array, size_is(count)] inout string valueArray); + results = [] + for item in valueArray: + results.append(item * 2) + return results + + def ReverseStringArray(self, valueArray): + # void ReverseStringArray(in PRUint32 count, + # [array, size_is(count)] inout string valueArray); + valueArray.reverse() + return valueArray + + # Note that this method shares a single "size_is" between 2 params! + def CompareStringArrays(self, ar1, ar2): + # void CompareStringArrays([array, size_is(count)] in string arr1, + # [array, size_is(count)] in string arr2, + # in unsigned long count, + # [retval] out short result); + return cmp(ar1, ar2) + + def DoubleString(self, val): + # void DoubleString(inout PRUint32 count, + # [size_is(count)] inout string str); + return val * 2 + def DoubleString2(self, val): + # void DoubleString2(in PRUint32 in_count, [size_is(in_count)] in string in_str, + # out PRUint32 out_count, [size_is(out_count)] out string out_str); + return val * 2 + def DoubleString3(self, val): + # void DoubleString3(in PRUint32 in_count, [size_is(in_count)] in string in_str, + # out PRUint32 out_count, [size_is(out_count), retval] string out_str); + return val * 2 + def DoubleString4(self, val): + # void DoubleString4([size_is(count)] in string in_str, inout PRUint32 count, [size_is(count)] out string out_str); + return val * 2 + def UpString(self, val): + # // UpString defines the count as only "in" - meaning the result must be the same size + # void UpString(in PRUint32 count, + # [size_is(count)] inout string str); + return val.upper() + UpString2 = UpString + # // UpString2 defines count as only "in", and a string as only "out" + # void UpString2(in PRUint32 count, + # [size_is(count)] inout string in_str, + # [size_is(count)]out string out_str); + + def GetFixedString(self, count): + # void GetFixedString(in PRUint32 count, [size_is(count)out string out_str); + return "A" * count + + # DoubleWideString functions are identical to DoubleString, except use wide chars! + def DoubleWideString(self, val): + return val * 2 + def DoubleWideString2(self, val): + return val * 2 + def DoubleWideString3(self, val): + return val * 2 + def DoubleWideString4(self, val): + return val * 2 + def UpWideString(self, val): + return val.upper() + UpWideString2 = UpWideString + def CopyUTF8String(self, v): + return v + def CopyUTF8String2(self, v): + return v.encode("utf8") + # Test we can get an "out" array with an "in" size (and the size is not used anywhere as a size for an in!) + def GetFixedWideString(self, count): + # void GetFixedWideString(in PRUint32 count, [size_is(count)out string out_str); + return u"A" * count + + def GetStrings(self): + # void GetStrings(out PRUint32 count, + # [retval, array, size_is(count)] out string str); + return "Hello from the Python test component".split() + # Some tests for our special "PRUint8" support. + def UpOctetArray( self, data ): + # void UpOctetArray(inout PRUint32 count, + # [array, size_is(count)] inout PRUint8 data); + return data.upper() + + def UpOctetArray2( self, data ): + # void UpOctetArray2(inout PRUint32 count, + # [array, size_is(count)] inout PRUint8 data); + data = data.upper() + # This time we return a list of integers. + return map( ord, data ) + + # Arrays of interfaces + def CheckInterfaceArray(self, interfaces): + # void CheckInterfaceArray(in PRUint32 count, + # [array, size_is(count)] in nsISupports data, + # [retval] out PRBool all_non_null); + ret = 1 + for i in interfaces: + if i is None: + ret = 0 + break + return ret + def CopyInterfaceArray(self, a): + return a + def GetInterfaceArray(self): + # void GetInterfaceArray(out PRUint32 count, + # [array, size_is(count)] out nsISupports data); + return self, self, self, None + def ExtendInterfaceArray(self, data): + # void ExtendInterfaceArray(inout PRUint32 count, + # [array, size_is(count)] inout nsISupports data); + return data * 2 + + # Arrays of IIDs + def CheckIIDArray(self, data): + # void CheckIIDArray(in PRUint32 count, + # [array, size_is(count)] in nsIIDRef data, + # [retval] out PRBool all_mine); + ret = 1 + for i in data: + if i!= self._com_interfaces_ and i != self._reg_clsid_: + ret = 0 + break + return ret + def GetIIDArray(self): + # void GetIIDArray(out PRUint32 count, + # [array, size_is(count)] out nsIIDRef data); + return self._com_interfaces_, self._reg_clsid_ + def ExtendIIDArray(self, data): + # void ExtendIIDArray(inout PRUint32 count, + # [array, size_is(count)] inout nsIIDRef data); + return data * 2 + + # Test our count param can be shared as an "in" param. + def SumArrays(self, array1, array2): + # void SumArrays(in PRUint32 count, [array, size_is(count)]in array1, [array, size_is(count)]in array2, [retval]result); + if len(array1)!=len(array2): + print "SumArrays - not expecting different lengths!" + result = 0 + for i in array1: + result = result + i + for i in array2: + result = result+i + return result + + # Test our count param can be shared as an "out" param. + def GetArrays(self): + # void GetArrays(out PRUint32 count, [array, size_is(count)]out array1, [array, size_is(count)]out array2); + return (1,2,3), (4,5,6) + # Test we can get an "out" array with an "in" size + def GetFixedArray(self, size): + # void GetFixedArray(in PRUint32 count, [array, size_is(count)]out PRInt32 array1]); + return 0 * size + + # Test our "in" count param can be shared as one "in", plus one "out" param. + def CopyArray(self, array1): + # void CopyArray(in PRUint32 count, [array, size_is(count)]in array1, [array, size_is(count)]out array2); + return array1 + # Test our "in-out" count param can be shared as one "in", plus one "out" param. + def CopyAndDoubleArray(self, array): + # void CopyAndDoubleArray(inout PRUint32 count, [array, size_is(count)]in array1, [array, size_is(count)]out array2); + return array + array + # Test our "in-out" count param can be shared as one "in", plus one "in-out" param. + def AppendArray(self, array1, array2): + # void AppendArray(inout PRUint32 count, [array, size_is(count)]in array1, [array, size_is(count)]inout array2); + rc = array1 + if array2 is not None: + rc.extend(array2) + return rc + # Test nsIVariant support + def AppendVariant(self, invar, inresult): + if type(invar)==type([]): + invar_use = invar[0] + for v in invar[1:]: + invar_use += v + else: + invar_use = invar + if type(inresult)==type([]): + inresult_use = inresult[0] + for v in inresult[1:]: + inresult_use += v + else: + inresult_use = inresult + if inresult_use is None and invar_use is None: + return None + return inresult_use + invar_use + + 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 & + if length == -1: + return None + return "P" * length + def GetDOMStringOut( self, length ): + # Result: DOMString & + if length == -1: + return None + return "y" * length + def GetDOMStringLength( self, param0 ): + # Result: uint32 + # In: param0: DOMString & + if param0 is None: return -1 + return len(param0) + + def GetDOMStringRefLength( self, param0 ): + # Result: uint32 + # In: param0: DOMString & + if param0 is None: return -1 + return len(param0) + + def GetDOMStringPtrLength( self, param0 ): + # Result: uint32 + # In: param0: DOMString * + if param0 is None: return -1 + return len(param0) + + def ConcatDOMStrings( self, param0, param1 ): + # Result: void - None + # In: param0: DOMString & + # In: param1: DOMString & + # Out: DOMString & + return param0 + param1 + def get_domstring_value( self ): + # Result: DOMString & + return self.domstring_value + def set_domstring_value( self, param0 ): + # Result: void - None + # In: param0: DOMString & + self.domstring_value = param0 + + def get_domstring_value_ro( self ): + # Result: DOMString & + return self.domstring_value diff --git a/src/libs/xpcom18a4/python/test/test_components.py b/src/libs/xpcom18a4/python/test/test_components.py new file mode 100755 index 00000000..80007722 --- /dev/null +++ b/src/libs/xpcom18a4/python/test/test_components.py @@ -0,0 +1,109 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# ActiveState Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000, 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Hammond <markh@activestate.com> (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 ***** + +"""Tests the "xpcom.components" object. +""" + +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" + +def test_interfaces(): + "Test the xpcom.components.interfaces object" + + iid = xpcom.components.interfaces.nsISupports + assert iid == xpcom._xpcom.IID_nsISupports, "Got the wrong IID!" + iid = xpcom.components.interfaces['nsISupports'] + assert iid == xpcom._xpcom.IID_nsISupports, "Got the wrong IID!" + + # Test dictionary semantics + num_fetched = num_nsisupports = 0 + for name, iid in xpcom.components.interfaces.items(): + num_fetched = num_fetched + 1 + if name == "nsISupports": + num_nsisupports = num_nsisupports + 1 + assert iid == xpcom._xpcom.IID_nsISupports, "Got the wrong IID!" + assert xpcom.components.interfaces[name] == iid + # Check all the lengths match. + 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" + assert num_nsisupports == 1, "Didnt find exactly 1 nsiSupports!" + +def test_classes(): + # Need a well-known contractID here? + prog_id = "@mozilla.org/supports-array;1" + clsid = xpcom.components.ID("{bda17d50-0d6b-11d3-9331-00104ba0fd40}") + + # Check we can create the instance (dont check we can do anything with it tho!) + klass = xpcom.components.classes[prog_id] + instance = klass.createInstance() + + # Test dictionary semantics + num_fetched = num_mine = 0 + for name, klass in xpcom.components.classes.items(): + num_fetched = num_fetched + 1 + if name == prog_id: + 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!? +# assert xpcom.components.classes[name].contractid == prog_id, "Expected '%s', got '%s'" % (prog_id, xpcom.components.classes[name].contractid) + # Check all the lengths match. + if len(xpcom.components.classes.keys()) == len(xpcom.components.classes.values()) == \ + len(xpcom.components.classes.items()) == len(xpcom.components.classes) == \ + num_fetched: + pass + else: + raise RuntimeError, "The collection lengths were wrong" + if num_fetched <= 0: + raise RuntimeError, "Didnt get any classes!!!" + if num_mine != 1: + raise RuntimeError, "Didnt find exactly 1 of my contractid! (%d)" % (num_mine,) + +def test_id(): + id = xpcom.components.ID(str(xpcom._xpcom.IID_nsISupports)) + assert id == xpcom._xpcom.IID_nsISupports + +# Make this test run under our std test suite +def suite(): + return suite_from_functions(test_interfaces, test_classes, test_id) + +if __name__=='__main__': + testmain() diff --git a/src/libs/xpcom18a4/python/test/test_isupports_primitives.py b/src/libs/xpcom18a4/python/test/test_isupports_primitives.py new file mode 100755 index 00000000..3d0e7023 --- /dev/null +++ b/src/libs/xpcom18a4/python/test/test_isupports_primitives.py @@ -0,0 +1,207 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# ActiveState Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000, 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Hammond <MarkH@ActiveState.com> (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 ***** + +# Test our support for the interfaces defined in nsISupportsPrimitives.idl +# +# The framework supports nsISupportsCString and nsISupportsString, but +# only if our class doesnt 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] + +class ImplicitSupportsString: + _com_interfaces_ = [components.interfaces.nsISupports] + def __str__(self): + return "<MyImplicitStrObject>" + +class ExplicitSupportsString: + _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>" + # These are the ones that will be used. + def get_data(self): + return self.test_data + def toString(self): + 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] + def __int__(self): + return 99 + +class ExplicitSupportsInt: + _com_interfaces_ = [components.interfaces.nsISupportsPrimitive, + components.interfaces.nsISupportsPRInt32] + type = components.interfaces.nsISupportsPrimitive.TYPE_PRINT32 + def get_data(self): + return 99 + +class ImplicitSupportsLong: + _com_interfaces_ = [components.interfaces.nsISupports] + def __long__(self): + return 99L + +class ExplicitSupportsLong: + _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.nsISupportsPrimitive, + components.interfaces.nsISupportsDouble] + type = components.interfaces.nsISupportsPrimitive.TYPE_DOUBLE + def get_data(self): + return 99.99 + +class ImplicitSupportsFloat: + _com_interfaces_ = [components.interfaces.nsISupports] + def __float__(self): + return 99.99 + +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,) + + def testImplicitString(self): + ob = xpcom.server.WrapObject( ImplicitSupportsString(), components.interfaces.nsISupports) + self.failUnlessEqual(str(ob), "<MyImplicitStrObject>") + + def testExplicitString(self): + ob = xpcom.server.WrapObject( ExplicitSupportsString(), components.interfaces.nsISupports) + self.failUnlessEqual(str(ob), "<MyExplicitStrObject>") + + def testImplicitUnicode(self): + ob = xpcom.server.WrapObject( ImplicitSupportsUnicode(), components.interfaces.nsISupports) + self.failUnlessEqual(unicode(ob), ImplicitSupportsUnicode.test_data) + + def testExplicitUnicode(self): + ob = xpcom.server.WrapObject( ExplicitSupportsUnicode(), components.interfaces.nsISupports) + self.failUnlessEqual(unicode(ob), ExplicitSupportsUnicode.test_data) + + def testConvertInt(self): + # Try our conversions. + ob = xpcom.server.WrapObject( ExplicitSupportsString(), components.interfaces.nsISupports) + self.failUnlessRaises( ValueError, int, ob) + + def testExplicitInt(self): + ob = xpcom.server.WrapObject( ExplicitSupportsInt(), components.interfaces.nsISupports) + self.failUnlessAlmostEqual(float(ob), 99.0) + self.failUnlessEqual(int(ob), 99) + + def testImplicitInt(self): + ob = xpcom.server.WrapObject( ImplicitSupportsInt(), components.interfaces.nsISupports) + self.failUnlessAlmostEqual(float(ob), 99.0) + self.failUnlessEqual(int(ob), 99) + + 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) + + 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() diff --git a/src/libs/xpcom18a4/python/test/test_misc.py b/src/libs/xpcom18a4/python/test/test_misc.py new file mode 100755 index 00000000..6cf1b74e --- /dev/null +++ b/src/libs/xpcom18a4/python/test/test_misc.py @@ -0,0 +1,236 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# Activestate Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Hammond <MarkH@ActiveState.com> +# +# 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 ***** + +import xpcom +import xpcom.client +import xpcom.server +import xpcom._xpcom +import xpcom.components +import string +from pyxpcom_test_tools import testmain + +import unittest + +import traceback, getopt, sys + +verbose_level = 0 + +reportedSampleMissing = 0 + +def get_sample_component_cpp(): + global reportedSampleMissing + contractid = "@mozilla.org/sample;1" # The C++ version. + try: + return xpcom.components.classes[contractid].createInstance() + except xpcom.COMException: + if not reportedSampleMissing: + print "***" + print "*** This test requires an XPCOM sample component," + print "*** which does not exist. To build this test, you" + print "*** should change to the 'mozilla/xpcom/sample' directory," + print "*** and run 'make', then run this test again." + print "***" + reportedSampleMissing = 1 + else: + print "(skipping - no C++ sample...) ", + return None + +def get_sample_component_js(): + # This should *always* exist - no special make process. + contractid = "@mozilla.org/jssample;1" # the JS version + return xpcom.components.classes[contractid].createInstance() + +class TestDumpInterfaces(unittest.TestCase): + def testAllInterfaces(self): + "Dump every interface under the sun!" + import xpcom, xpcom.xpt, xpcom._xpcom + iim = xpcom._xpcom.XPTI_GetInterfaceInfoManager() + + if verbose_level: + print "Dumping every interface I can find" + enum = iim.EnumerateInterfaces() + rc = enum.First() + num = 0 + while rc==0: + item = enum.CurrentItem(xpcom._xpcom.IID_nsIInterfaceInfo) + try: + iid = item.GetIID() + except xpcom.COMException: + if verbose_level: + print "Can't dump", item + continue # Dont bother dumping this. + interface = xpcom.xpt.Interface(iid) + num = num + 1 + text = interface.Describe() + if verbose_level: + print text + + rc = enum.Next() + if num < 200: + print "Only found", num, "interfaces - this seems unusually low!" + +class TestEnumContractIDs(unittest.TestCase): + def testContractIDs(self): + """Enumerate all the ContractIDs registered""" + enum = xpcom.components.registrar.enumerateContractIDs() + n = 0 + while enum.hasMoreElements(): + item = enum.getNext(xpcom.components.interfaces.nsISupportsCString) + n = n + 1 + if verbose_level: + print "ContractID:", item.data + if n < 200: + print "Only found", n, "ContractIDs - this seems unusually low!" + +class TestSampleComponent(unittest.TestCase): + def _doTestSampleComponent(self, test_flat = 0): + """Test the standard Netscape 'sample' sample""" + c = get_sample_component_cpp() + if c is None: + return + if not test_flat: + c = c.queryInterface(xpcom.components.interfaces.nsISample) + self.failUnlessEqual(c.value, "initial value") + c.value = "new value" + self.failUnlessEqual(c.value, "new value") + c.poke("poked value") + self.failUnlessEqual(c.value, "poked value") + c.writeValue("Python just poked:") + + def testSampleComponentFlat(self): + """Test the standard Netscape 'sample' sample using interface flattening""" + self._doTestSampleComponent(1) + + def testSampleComponentOld(self): + """Test the standard Netscape 'sample' sample using explicit QI""" + self._doTestSampleComponent(0) + + def _doTestHash(self, c): + "Test that hashing COM objects works" + d = {} + d[c] = None + if not d.has_key(c): + raise RuntimeError, "Can't get the exact same object back!" + if not d.has_key(c.queryInterface(xpcom.components.interfaces.nsISupports)): + raise RuntimeError, "Can't get back as nsISupports" + + # And the same in reverse - stick an nsISupports in, and make sure an explicit interface comes back. + d = {} +# contractid = "@mozilla.org/sample;1" # The C++ version. +# c = xpcom.components.classes[contractid].createInstance() \ +# .queryInterface(xpcom.components.interfaces.nsISupports) + d[c] = None + if not d.has_key(c): + raise RuntimeError, "Can't get the exact same object back!" + if not d.has_key(c.queryInterface(xpcom.components.interfaces.nsISample)): + raise RuntimeError, "Can't get back as nsISupports" + + def testHashJS(self): + c = get_sample_component_js() + self._doTestHash(c) + + def testHashCPP(self): + c = get_sample_component_cpp() + if c is not None: + self._doTestHash(c) + + +class TestIIDs(unittest.TestCase): + def TestIIDs(self): + "Do some basic IID semantic tests." + iid_str = "{7ee4bdc6-cb53-42c1-a9e4-616b8e012aba}" + IID = xpcom._xpcom.IID + self.failUnlessEqual(IID(iid_str), IID(iid_str)) + self.failUnlessEqual(hash(IID(iid_str)), hash(IID(iid_str))) + self.failUnlessEqual(IID(iid_str), IID(iid_str.upper())) + self.failUnlessEqual(hash(IID(iid_str)), hash(IID(iid_str.upper()))) + # If the above work, this shoud too, but WTF + dict = {} + dict[IID(iid_str)] = None + self.failUnless(dict.has_key(IID(iid_str)), "hashes failed in dictionary") + self.failUnless(dict.has_key(IID(iid_str.upper())), "uppercase hash failed in dictionary") + +class TestRepr(unittest.TestCase): + def _doTestRepr(self, progid, interfaces): + if isinstance(progid, str): + ob = xpcom.components.classes[progid].createInstance() + else: + ob = progid + self.failUnless(repr(ob).find(str(progid)) >= 0, repr(ob)) + for interface_name in interfaces.split(): + self.failUnless(repr(ob).find(interface_name) >= 0, repr(ob)) + + def testReprPython(self): + "Test repr() of Python objects" + self._doTestRepr("Python.TestComponent", "nsIPythonTestInterfaceDOMStrings nsIPythonTestInterfaceExtra nsIPythonTestInterface") + + # JS does not provide class-info :( + #def testReprJS(self): + # self._doTestRepr("@mozilla.org/jssample;1", "nsISample") + + def testReprSample(self): + "Test repr() of non-Python objects" + ob = get_sample_component_cpp() + if ob is None: + return + self._doTestRepr(ob, "nsISample") + +class TestUnwrap(unittest.TestCase): + "Test the unwrap facilities" + def testUnwrap(self): + # First test that a Python object can be unwrapped. + ob = xpcom.components.classes["Python.TestComponent"].createInstance() + pyob = xpcom.server.UnwrapObject(ob) + # This depends on our __repr__ implementation, but that's OK - it + # can be updated should our __repr__ change :) + self.failUnless(str(pyob).startswith("<component:py_test_component.PythonTestComponent")) + # Test that a non-Python implemented object can NOT be unwrapped. + ob = get_sample_component_cpp() + if ob is None: + 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__': + testmain() diff --git a/src/libs/xpcom18a4/python/test/test_streams.py b/src/libs/xpcom18a4/python/test/test_streams.py new file mode 100755 index 00000000..96ac6559 --- /dev/null +++ b/src/libs/xpcom18a4/python/test/test_streams.py @@ -0,0 +1,96 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# ActiveState Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000,2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Hammond <MarkH@ActiveState.com> (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 ***** + +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" + +class koTestSimpleStream: + _com_interfaces_ = [components.interfaces.nsIInputStream] + # We avoid registering this object - see comments in get_test_inout_? below. + + def __init__(self): + self.data=StringIO(test_data) + self._non_blocking = False + + def close( self ): + pass + + def available( self ): + return self.data.len-self.data.pos + + def readStr( self, amount): + return self.data.read(amount) + + read=readStr + + def get_observer( self ): + raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED) + + def set_observer( self, param0 ): + raise ServerException(nsError.NS_ERROR_NOT_IMPLEMENTED) + + def isNonBlocking(self): + return self._non_blocking + +def get_test_input(): + # We use a couple of internal hacks here that mean we can avoid having the object + # registered. This code means that we are still working over the xpcom boundaries, tho + # (and the point of this test is not the registration, etc). + import xpcom.server, xpcom.client + ob = xpcom.server.WrapObject( koTestSimpleStream(), _xpcom.IID_nsISupports) + ob = xpcom.client.Component(ob._comobj_, components.interfaces.nsIInputStream) + return ob + +class StreamTests(unittest.TestCase): + def testInput(self): + self.do_test_input( get_test_input() ) + + def do_test_input(self, myStream): + self.failUnlessEqual(str(myStream.read(5)), test_data[:5]) + self.failUnlessEqual(str(myStream.read(0)), '') + self.failUnlessEqual(str(myStream.read(5)), test_data[5:10]) + self.failUnlessEqual(str(myStream.read(-1)), test_data[10:]) + self.failIf(myStream.isNonBlocking(), "Expected default to be blocking") + # stream observer mechanism has changed - we should test that. + +if __name__=='__main__': + testmain() diff --git a/src/libs/xpcom18a4/python/test/test_test_component.js b/src/libs/xpcom18a4/python/test/test_test_component.js new file mode 100644 index 00000000..54e39382 --- /dev/null +++ b/src/libs/xpcom18a4/python/test/test_test_component.js @@ -0,0 +1,138 @@ +/* ***** 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 the Python XPCOM language bindings. + * + * The Initial Developer of the Original Code is + * ActiveState Tool Corp. + * Portions created by the Initial Developer are Copyright (C) 2000 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * Mark Hammond <MarkH@ActiveState.com> (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 ***** */ + +/* Javascript code calling the Python test interface. */ + +var extended_unicode_string = "The Euro Symbol is '\u20ac'"; + +function MakeTestInterface() +{ + var clazz = Components.classes["Python.TestComponent"]; + var iface = Components.interfaces.nsIPythonTestInterfaceDOMStrings; + return new clazz(iface); +} + +var c = new MakeTestInterface(); + +if (c.boolean_value != 1) + throw("boolean_value has wrong initial value"); +c.boolean_value = false; +if (c.boolean_value != false) + throw("boolean_value has wrong new value"); + +// Python's own test does thorough testing of all numeric types +// Wont bother from here! + +if (c.char_value != 'a') + throw("char_value has wrong initial value"); +c.char_value = 'b'; +if (c.char_value != 'b') + throw("char_value has wrong new value"); + +if (c.wchar_value != 'b') + throw("wchar_value has wrong initial value"); +c.wchar_value = 'c'; +if (c.wchar_value != 'c') + throw("wchar_value has wrong new value"); + +if (c.string_value != 'cee') + throw("string_value has wrong initial value"); +c.string_value = 'dee'; +if (c.string_value != 'dee') + throw("string_value has wrong new value"); + +if (c.wstring_value != 'dee') + throw("wstring_value has wrong initial value"); +c.wstring_value = 'eee'; +if (c.wstring_value != 'eee') + throw("wstring_value has wrong new value"); +c.wstring_value = extended_unicode_string; +if (c.wstring_value != extended_unicode_string) + throw("wstring_value has wrong new value"); + +if (c.domstring_value != 'dom') + throw("domstring_value has wrong initial value"); +c.domstring_value = 'New value'; +if (c.domstring_value != 'New value') + throw("domstring_value has wrong new value"); +c.domstring_value = extended_unicode_string; +if (c.domstring_value != extended_unicode_string) + throw("domstring_value has wrong new value"); + +if (c.utf8string_value != 'utf8string') + throw("utf8string_value has wrong initial value"); +c.utf8string_value = 'New value'; +if (c.utf8string_value != 'New value') + throw("utf8string_value has wrong new value"); +c.utf8string_value = extended_unicode_string; +if (c.utf8string_value != extended_unicode_string) + throw("utf8string_value has wrong new value"); + +var v = new Object(); +v.value = "Hello" +var l = new Object(); +l.value = v.value.length; +c.DoubleString(l, v); +if ( v.value != "HelloHello") + throw("Could not double the string!"); + +var v = new Object(); +v.value = "Hello" +var l = new Object(); +l.value = v.value.length; +c.DoubleWideString(l, v); +if ( v.value != "HelloHello") + throw("Could not double the wide string!"); + +// Some basic array tests +var v = new Array() +v[0] = 1; +v[2] = 2; +v[3] = 3; +var v2 = new Array() +v2[0] = 4; +v2[2] = 5; +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."); diff --git a/src/libs/xpcom18a4/python/test/test_test_component.py b/src/libs/xpcom18a4/python/test/test_test_component.py new file mode 100755 index 00000000..dd78133a --- /dev/null +++ b/src/libs/xpcom18a4/python/test/test_test_component.py @@ -0,0 +1,575 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# ActiveState Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000, 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Hammond <MarkH@ActiveState.com> (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 ***** + +import sys, os, time +import xpcom.components +import xpcom._xpcom +import xpcom.nsError + +MakeVariant = xpcom._xpcom.MakeVariant + +try: + import gc +except ImportError: + gc = None + +num_errors = 0 + +component_iid = xpcom.components.ID("{7EE4BDC6-CB53-42c1-A9E4-616B8E012ABA}") +new_iid = xpcom.components.ID("{2AF747D3-ECBC-457b-9AF9-5C5D80EDC360}") + +contractid = "Python.TestComponent" + +really_big_string = "This is really repetitive!" * 10000 +really_big_wstring = u"This is really repetitive!" * 10000 +extended_unicode_string = u"The Euro Symbol is '\u20ac'" + +# Exception raised when a -ve integer is converted to an unsigned C integer +# (via an extension module). This changed in Python 2.2 +if sys.hexversion > 0x02010000: + UnsignedMismatchException = TypeError +else: + UnsignedMismatchException = OverflowError + +def print_error(error): + print error + global num_errors + num_errors = num_errors + 1 + +def _test_value(what, got, expecting): + ok = got == expecting + if type(got)==type(expecting)==type(0.0): + ok = abs(got-expecting) < 0.001 + if not ok: + print_error("*** Error %s - got '%r', but expecting '%r'" % (what, got, expecting)) + +def test_attribute(ob, attr_name, expected_init, new_value, new_value_really = None): + if xpcom.verbose: + print "Testing attribute %s" % (attr_name,) + if new_value_really is None: + new_value_really = new_value # Handy for eg bools - set a BOOL to 2, you still get back 1! + + _test_value( "getting initial attribute value (%s)" % (attr_name,), getattr(ob, attr_name), expected_init) + setattr(ob, attr_name, new_value) + _test_value( "getting new attribute value (%s)" % (attr_name,), getattr(ob, attr_name), new_value_really) + # And set it back to the expected init. + setattr(ob, attr_name, expected_init) + _test_value( "getting back initial attribute value after change (%s)" % (attr_name,), getattr(ob, attr_name), expected_init) + +def test_string_attribute(ob, attr_name, expected_init, is_dumb_sz = False, ascii_only = False): + test_attribute(ob, attr_name, expected_init, "normal value") + val = "a null >\0<" + if is_dumb_sz: + expected = "a null >" # dumb strings are \0 terminated. + else: + expected = val + test_attribute(ob, attr_name, expected_init, val, expected) + test_attribute(ob, attr_name, expected_init, "") + test_attribute(ob, attr_name, expected_init, really_big_string) + test_attribute(ob, attr_name, expected_init, u"normal unicode value") + val = u"a null >\0<" + if is_dumb_sz: + expected = "a null >" # dumb strings are \0 terminated. + else: + expected = val + test_attribute(ob, attr_name, expected_init, val, expected) + test_attribute(ob, attr_name, expected_init, u"") + test_attribute(ob, attr_name, expected_init, really_big_wstring) + if not ascii_only: + test_attribute(ob, attr_name, expected_init, extended_unicode_string) + +def test_attribute_failure(ob, attr_name, new_value, expected_exception): + try: + setattr(ob, attr_name, new_value) + print_error("*** Setting attribute '%s' to '%r' didnt yield an exception!" % (attr_name, new_value) ) + except: + exc_typ = sys.exc_info()[0] + exc_val = sys.exc_info()[1] + ok = issubclass(exc_typ, expected_exception) + if not ok: + print_error("*** Wrong exception setting '%s' to '%r'- got '%s: %s', expected '%s'" % (attr_name, new_value, exc_typ, exc_val, expected_exception)) + + +def test_method(method, args, expected_results): + if xpcom.verbose: + print "Testing %s%s" % (method.__name__, `args`) + ret = method(*args) + if ret != expected_results: + print_error("calling method %s - expected %r, but got %r" % (method.__name__, expected_results, ret)) + +def test_int_method(meth): + test_method(meth, (0,0), (0,0,0)) + test_method(meth, (1,1), (2,0,1)) + test_method(meth, (5,2), (7,3,10)) +# test_method(meth, (2,5), (7,-3,10)) + +def test_constant(ob, cname, val): + v = getattr(ob, cname) + if v != val: + print_error("Bad value for constant '%s' - got '%r'" % (cname, v)) + try: + setattr(ob, cname, 0) + print_error("The object allowed us to set the constant '%s'" % (cname,)) + except AttributeError: + pass + +def test_base_interface(c): + test_attribute(c, "boolean_value", 1, 0) + test_attribute(c, "boolean_value", 1, -1, 1) # Set a bool to anything, you should always get back 0 or 1 + test_attribute(c, "boolean_value", 1, 4, 1) # Set a bool to anything, you should always get back 0 or 1 + test_attribute(c, "boolean_value", 1, "1", 1) # This works by virtual of PyNumber_Int - not sure I agree, but... + test_attribute_failure(c, "boolean_value", "boo", ValueError) + test_attribute_failure(c, "boolean_value", test_base_interface, TypeError) + + test_attribute(c, "octet_value", 2, 5) + test_attribute(c, "octet_value", 2, 0) + test_attribute(c, "octet_value", 2, 128) # octet is unsigned 8 bit + test_attribute(c, "octet_value", 2, 255) # octet is unsigned 8 bit + test_attribute(c, "octet_value", 2, -1, 255) # octet is unsigned 8 bit + test_attribute_failure(c, "octet_value", "boo", ValueError) + + test_attribute(c, "short_value", 3, 10) + test_attribute(c, "short_value", 3, -1) # 16 bit signed + test_attribute(c, "short_value", 3, 0xFFFF, -1) # 16 bit signed + test_attribute(c, "short_value", 3, 0L) + test_attribute(c, "short_value", 3, 1L) + test_attribute(c, "short_value", 3, -1L) + test_attribute(c, "short_value", 3, 0xFFFFL, -1) + test_attribute_failure(c, "short_value", "boo", ValueError) + + test_attribute(c, "ushort_value", 4, 5) + test_attribute(c, "ushort_value", 4, 0) + test_attribute(c, "ushort_value", 4, -1, 0xFFFF) # 16 bit signed + test_attribute(c, "ushort_value", 4, 0xFFFF) # 16 bit signed + test_attribute(c, "ushort_value", 4, 0L) + test_attribute(c, "ushort_value", 4, 1L) + test_attribute(c, "ushort_value", 4, -1L, 0xFFFF) + test_attribute_failure(c, "ushort_value", "boo", ValueError) + + test_attribute(c, "long_value", 5, 7) + test_attribute(c, "long_value", 5, 0) + test_attribute(c, "long_value", 5, -1, -1) # 32 bit signed. + test_attribute(c, "long_value", 5, -1) # 32 bit signed. + test_attribute(c, "long_value", 5, 0L) + test_attribute(c, "long_value", 5, 1L) + test_attribute(c, "long_value", 5, -1L) + test_attribute_failure(c, "long_value", 0xFFFFL * 0xFFFF, OverflowError) # long int too long to convert + test_attribute_failure(c, "long_value", "boo", ValueError) + + test_attribute(c, "ulong_value", 6, 7) + test_attribute(c, "ulong_value", 6, 0) + test_attribute(c, "ulong_value", 6, -1) # 32 bit signed. + test_attribute_failure(c, "ulong_value", "boo", ValueError) + + test_attribute(c, "long_long_value", 7, 8) + test_attribute(c, "long_long_value", 7, 0) + test_attribute(c, "long_long_value", 7, -1) + test_attribute(c, "long_long_value", 7, 0xFFFF) + test_attribute(c, "long_long_value", 7, 0xFFFFL * 2) + test_attribute_failure(c, "long_long_value", 0xFFFFL * 0xFFFF * 0xFFFF * 0xFFFF, OverflowError) # long int too long to convert + test_attribute_failure(c, "long_long_value", "boo", ValueError) + + test_attribute(c, "ulong_long_value", 8, 9) + test_attribute(c, "ulong_long_value", 8, 0) + test_attribute_failure(c, "ulong_long_value", "boo", ValueError) + test_attribute_failure(c, "ulong_long_value", -1, UnsignedMismatchException) # can't convert negative value to unsigned long) + + test_attribute(c, "float_value", 9.0, 10.2) + test_attribute(c, "float_value", 9.0, 0) + test_attribute(c, "float_value", 9.0, -1) + test_attribute(c, "float_value", 9.0, 1L) + test_attribute_failure(c, "float_value", "boo", ValueError) + + test_attribute(c, "double_value", 10.0, 9.0) + test_attribute(c, "double_value", 10.0, 0) + test_attribute(c, "double_value", 10.0, -1) + test_attribute(c, "double_value", 10.0, 1L) + test_attribute_failure(c, "double_value", "boo", ValueError) + + test_attribute(c, "char_value", "a", "b") + test_attribute(c, "char_value", "a", "\0") + test_attribute_failure(c, "char_value", "xy", ValueError) + test_attribute(c, "char_value", "a", u"c") + test_attribute(c, "char_value", "a", u"\0") + test_attribute_failure(c, "char_value", u"xy", ValueError) + + test_attribute(c, "wchar_value", "b", "a") + test_attribute(c, "wchar_value", "b", "\0") + test_attribute_failure(c, "wchar_value", "hi", ValueError) + test_attribute(c, "wchar_value", "b", u"a") + test_attribute(c, "wchar_value", "b", u"\0") + test_attribute_failure(c, "wchar_value", u"hi", ValueError) + + test_string_attribute(c, "string_value", "cee", is_dumb_sz = True, ascii_only = True) + test_string_attribute(c, "wstring_value", "dee", is_dumb_sz = True) + test_string_attribute(c, "astring_value", "astring") + test_string_attribute(c, "acstring_value", "acstring", ascii_only = True) + + test_string_attribute(c, "utf8string_value", "utf8string") + # Test a string already encoded gets through correctly. + test_attribute(c, "utf8string_value", "utf8string", extended_unicode_string.encode("utf8"), extended_unicode_string) + + # This will fail internal string representation :( Test we don't crash + try: + c.wstring_value = "a big char >" + chr(129) + "<" + print_error("strings with chars > 128 appear to have stopped failing?") + except UnicodeError: + pass + + test_attribute(c, "iid_value", component_iid, new_iid) + test_attribute(c, "iid_value", component_iid, str(new_iid), new_iid) + test_attribute(c, "iid_value", component_iid, xpcom._xpcom.ID(new_iid)) + + test_attribute_failure(c, "no_attribute", "boo", AttributeError) + + test_attribute(c, "interface_value", None, c) + test_attribute_failure(c, "interface_value", 2, TypeError) + + test_attribute(c, "isupports_value", None, c) + + # The methods + test_method(c.do_boolean, (0,1), (1,0,1)) + test_method(c.do_boolean, (1,0), (1,0,1)) + test_method(c.do_boolean, (1,1), (0,1,0)) + + test_int_method(c.do_octet) + test_int_method(c.do_short) + + test_int_method(c.do_unsigned_short) + test_int_method(c.do_long) + test_int_method(c.do_unsigned_long) + test_int_method(c.do_long_long) + test_int_method(c.do_unsigned_long) + test_int_method(c.do_float) + test_int_method(c.do_double) + + test_method(c.do_char, ("A", " "), (chr(ord("A")+ord(" ")), " ","A") ) + test_method(c.do_char, ("A", "\0"), ("A", "\0","A") ) + test_method(c.do_wchar, ("A", " "), (chr(ord("A")+ord(" ")), " ","A") ) + test_method(c.do_wchar, ("A", "\0"), ("A", "\0","A") ) + + test_method(c.do_string, ("Hello from ", "Python"), ("Hello from Python", "Hello from ", "Python") ) + test_method(c.do_string, (u"Hello from ", u"Python"), ("Hello from Python", "Hello from ", "Python") ) + test_method(c.do_string, (None, u"Python"), ("Python", None, "Python") ) + test_method(c.do_string, (None, really_big_string), (really_big_string, None, really_big_string) ) + test_method(c.do_string, (None, really_big_wstring), (really_big_string, None, really_big_string) ) + test_method(c.do_wstring, ("Hello from ", "Python"), ("Hello from Python", "Hello from ", "Python") ) + test_method(c.do_wstring, (u"Hello from ", u"Python"), ("Hello from Python", "Hello from ", "Python") ) + test_method(c.do_string, (None, really_big_wstring), (really_big_wstring, None, really_big_wstring) ) + test_method(c.do_string, (None, really_big_string), (really_big_wstring, None, really_big_wstring) ) + test_method(c.do_nsIIDRef, (component_iid, new_iid), (component_iid, component_iid, new_iid)) + test_method(c.do_nsIIDRef, (new_iid, component_iid), (new_iid, component_iid, component_iid)) + test_method(c.do_nsIPythonTestInterface, (None, None), (None, None, c)) + test_method(c.do_nsIPythonTestInterface, (c, c), (c, c, c)) + test_method(c.do_nsISupports, (None, None), (c, None, None)) + test_method(c.do_nsISupports, (c,c), (c, c, c)) + test_method(c.do_nsISupportsIs, (xpcom._xpcom.IID_nsISupports,), c) + test_method(c.do_nsISupportsIs, (xpcom.components.interfaces.nsIPythonTestInterface,), c) +## test_method(c.do_nsISupportsIs2, (xpcom.components.interfaces.nsIPythonTestInterface,c), (xpcom.components.interfaces.nsIPythonTestInterface,c)) +## test_method(c.do_nsISupportsIs3, (c,), (xpcom.components.interfaces.nsIPythonTestInterface,c)) +## test_method(c.do_nsISupportsIs4, (), (xpcom.components.interfaces.nsIPythonTestInterface,c)) + # Test the constants. + test_constant(c, "One", 1) + test_constant(c, "Two", 2) + test_constant(c, "MinusOne", -1) + test_constant(c, "BigLong", 0x7FFFFFFF) + test_constant(c, "BiggerLong", -1) + test_constant(c, "BigULong", -1) + # Test the components.Interfaces semantics + i = xpcom.components.interfaces.nsIPythonTestInterface + test_constant(i, "One", 1) + test_constant(i, "Two", 2) + test_constant(i, "MinusOne", -1) + test_constant(i, "BigLong", 0x7FFFFFFF) + test_constant(i, "BigULong", -1) + +def test_derived_interface(c, test_flat = 0): + val = "Hello\0there" + expected = val * 2 + + test_method(c.DoubleString, (val,), expected) + test_method(c.DoubleString2, (val,), expected) + test_method(c.DoubleString3, (val,), expected) + test_method(c.DoubleString4, (val,), expected) + test_method(c.UpString, (val,), val.upper()) + test_method(c.UpString2, (val,), val.upper()) + test_method(c.GetFixedString, (20,), "A"*20) + val = u"Hello\0there" + expected = val * 2 + test_method(c.DoubleWideString, (val,), expected) + test_method(c.DoubleWideString2, (val,), expected) + test_method(c.DoubleWideString3, (val,), expected) + test_method(c.DoubleWideString4, (val,), expected) + test_method(c.UpWideString, (val,), val.upper()) + test_method(c.UpWideString2, (val,), val.upper()) + test_method(c.GetFixedWideString, (20,), u"A"*20) + val = extended_unicode_string + test_method(c.CopyUTF8String, ("foo",), "foo") + test_method(c.CopyUTF8String, (u"foo",), "foo") + test_method(c.CopyUTF8String, (val,), val) + test_method(c.CopyUTF8String, (val.encode("utf8"),), val) + test_method(c.CopyUTF8String2, ("foo",), "foo") + test_method(c.CopyUTF8String2, (u"foo",), "foo") + test_method(c.CopyUTF8String2, (val,), val) + test_method(c.CopyUTF8String2, (val.encode("utf8"),), val) + items = [1,2,3,4,5] + test_method(c.MultiplyEachItemInIntegerArray, (3, items,), map(lambda i:i*3, items)) + + test_method(c.MultiplyEachItemInIntegerArrayAndAppend, (3, items), items + map(lambda i:i*3, items)) + items = "Hello from Python".split() + expected = map( lambda x: x*2, items) + test_method(c.DoubleStringArray, (items,), expected) + + test_method(c.CompareStringArrays, (items, items), cmp(items, items)) + # Can we pass lists and tuples correctly? + test_method(c.CompareStringArrays, (items, tuple(items)), cmp(items, items)) + items2 = ["Not", "the", "same"] + test_method(c.CompareStringArrays, (items, items2), cmp(items, items2)) + + expected = items[:] + expected.reverse() + test_method(c.ReverseStringArray, (items,), expected) + + expected = "Hello from the Python test component".split() + test_method(c.GetStrings, (), expected) + + val = "Hello\0there" + test_method(c.UpOctetArray, (val,), val.upper()) + test_method(c.UpOctetArray, (unicode(val),), val.upper()) + # Passing Unicode objects here used to cause us grief. + test_method(c.UpOctetArray2, (val,), val.upper()) + + test_method(c.CheckInterfaceArray, ((c, c),), 1) + test_method(c.CheckInterfaceArray, ((c, None),), 0) + test_method(c.CheckInterfaceArray, ((),), 1) + test_method(c.CopyInterfaceArray, ((c, c),), [c,c]) + + test_method(c.GetInterfaceArray, (), [c,c,c, None]) + test_method(c.ExtendInterfaceArray, ((c,c,c, None),), [c,c,c,None,c,c,c,None] ) + + expected = [xpcom.components.interfaces.nsIPythonTestInterfaceDOMStrings, xpcom.components.classes[contractid].clsid] + test_method(c.GetIIDArray, (), expected) + + val = [xpcom.components.interfaces.nsIPythonTestInterfaceExtra, xpcom.components.classes[contractid].clsid] + expected = val * 2 + test_method(c.ExtendIIDArray, (val,), expected) + + test_method(c.GetArrays, (), ( [1,2,3], [4,5,6] ) ) + test_method(c.CopyArray, ([1,2,3],), [1,2,3] ) + test_method(c.CopyAndDoubleArray, ([1,2,3],), [1,2,3,1,2,3] ) + test_method(c.AppendArray, ([1,2,3],), [1,2,3]) + test_method(c.AppendArray, ([1,2,3],[4,5,6]), [1,2,3,4,5,6]) + + test_method(c.CopyVariant, (None,), None) + test_method(c.CopyVariant, (1,), 1) + test_method(c.CopyVariant, (1.0,), 1.0) + test_method(c.CopyVariant, (-1,), -1) + test_method(c.CopyVariant, (sys.maxint+1,), sys.maxint+1) + test_method(c.CopyVariant, ("foo",), "foo") + test_method(c.CopyVariant, (u"foo",), u"foo") + test_method(c.CopyVariant, (c,), c) + test_method(c.CopyVariant, (component_iid,), component_iid) + test_method(c.CopyVariant, ((1,2),), [1,2]) + test_method(c.CopyVariant, ((1.2,2.1),), [1.2,2.1]) + 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. +# test_method(c.GetDOMStringResult, (-1,), None) + test_method(c.GetDOMStringResult, (3,), "PPP") +# test_method(c.GetDOMStringOut, (-1,), None) + test_method(c.GetDOMStringOut, (4,), "yyyy") + val = "Hello there" + test_method(c.GetDOMStringLength, (val,), len(val)) + test_method(c.GetDOMStringRefLength, (val,), len(val)) + test_method(c.GetDOMStringPtrLength, (val,), len(val)) + test_method(c.ConcatDOMStrings, (val,val), val+val) + test_attribute(c, "domstring_value", "dom", "new dom") + if c.domstring_value_ro != "dom": + print "Read-only DOMString not correct - got", c.domstring_ro + try: + c.dom_string_ro = "new dom" + print "Managed to set a readonly attribute - eek!" + except AttributeError: + pass + except: + print "Unexpected exception when setting readonly attribute: %s: %s" % (sys.exc_info()[0], sys.exc_info()[1]) + if c.domstring_value_ro != "dom": + print "Read-only DOMString not correct after failed set attempt - got", c.domstring_ro + +def do_test_failures(): + c = xpcom.client.Component(contractid, xpcom.components.interfaces.nsIPythonTestInterfaceExtra) + try: + ret = c.do_nsISupportsIs( xpcom._xpcom.IID_nsIInterfaceInfoManager ) + print "*** got", ret, "***" + raise RuntimeError, "We worked when using an IID we dont support!?!" + except xpcom.Exception, details: + if details.errno != xpcom.nsError.NS_ERROR_NO_INTERFACE: + raise RuntimeError, "Wrong COM exception type: %r" % (details,) + +def test_failures(): + # This extra stack-frame ensures Python cleans up sys.last_traceback etc + do_test_failures() + +def test_all(): + c = xpcom.client.Component(contractid, xpcom.components.interfaces.nsIPythonTestInterface) + test_base_interface(c) + # Now create an instance using the derived IID, and test that. + c = xpcom.client.Component(contractid, xpcom.components.interfaces.nsIPythonTestInterfaceExtra) + test_base_interface(c) + test_derived_interface(c) + # Now create an instance and test interface flattening. + c = xpcom.components.classes[contractid].createInstance() + test_base_interface(c) + test_derived_interface(c, test_flat=1) + + # We had a bug where a "set" of an attribute before a "get" failed. + # Don't let it happen again :) + c = xpcom.components.classes[contractid].createInstance() + c.boolean_value = 0 + + # This name is used in exceptions etc - make sure we got it from nsIClassInfo OK. + assert c._object_name_ == "Python.TestComponent" + + test_failures() + +try: + from sys import gettotalrefcount +except ImportError: + # Not a Debug build - assume no references (can't be leaks then :-) + def gettotalrefcount(): + return 0 + +from pyxpcom_test_tools import getmemusage + +def test_from_js(): + # Ensure we can find the js test script - same dir as this! + # Assume the path of sys.argv[0] is where we can find the js test code. + # (Running under the regression test is a little painful) + script_dir = os.path.split(sys.argv[0])[0] + fname = os.path.join( script_dir, "test_test_component.js") + if not os.path.isfile(fname): + 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. + 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. + if num_loops == -1: num_loops = 5 + for i in xrange(num_loops): + test_all() + + if i==0: + # First loop is likely to "leak" as we cache things. + # Leaking after that is a problem. + if gc is not None: + gc.collect() + num_refs = gettotalrefcount() + mem_usage = getmemusage() + + if num_errors: + break + + if gc is not None: + gc.collect() + + lost = gettotalrefcount() - num_refs + # 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)>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 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 > 3000000: + print "*** Lost %.6f MB of memory" % (mem_lost/1000000.0,) + + assert num_errors==0, "There were %d errors testing the Python component" % (num_errors,) + +def suite(): + from pyxpcom_test_tools import suite_from_functions + return suite_from_functions(doit, test_from_js) + +if __name__=='__main__': + 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]) + + 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) diff --git a/src/libs/xpcom18a4/python/test/test_weakreferences.py b/src/libs/xpcom18a4/python/test/test_weakreferences.py new file mode 100755 index 00000000..9bfb3fbc --- /dev/null +++ b/src/libs/xpcom18a4/python/test/test_weakreferences.py @@ -0,0 +1,114 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# ActiveState Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000, 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# Mark Hammond <markh@activestate.com> (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 ***** + +# 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 +except ImportError: + # Not a Debug build - assume no references (can't be leaks then :-) + gettotalrefcount = lambda: 0 + +num_alive = 0 + +class koTestSimple: + _com_interfaces_ = [components.interfaces.nsIInputStream] + def __init__(self): + global num_alive + num_alive += 1 + def __del__(self): + global num_alive + num_alive -= 1 + def close( self ): + pass + +def test(): + ob = xpcom.server.WrapObject( koTestSimple(), components.interfaces.nsIInputStream) + + if num_alive != 1: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,) + + # Check we can create a weak reference to our object. + wr = xpcom.client.WeakReference(ob) + if num_alive != 1: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,) + + # Check we can call methods via the weak reference. + if wr() is None: raise RuntimeError, "Our weak-reference is returning None before it should!" + wr().close() + + ob = None # This should kill the object. + if num_alive != 0: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,) + if wr() is not None: raise RuntimeError, "Our weak-reference is not returning None when it should!" + + # Now a test that we can get a _new_ interface from the weak reference - ie, + # an IID the real object has never previously been queried for + # (this behaviour previously caused a bug - never again ;-) + ob = xpcom.server.WrapObject( koTestSimple(), components.interfaces.nsISupports) + if num_alive != 1: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,) + wr = xpcom.client.WeakReference(ob, components.interfaces.nsIInputStream) + if num_alive != 1: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,) + wr() # This would die once upon a time ;-) + ob = None # This should kill the object. + if num_alive != 0: raise RuntimeError, "Eeek - there are %d objects alive" % (num_alive,) + if wr() is not None: raise RuntimeError, "Our weak-reference is not returning None when it should!" + +def test_refcount(num_loops=-1): + # Do the test lots of times - can help shake-out ref-count bugs. + if num_loops == -1: num_loops = 10 + for i in xrange(num_loops): + test() + + if i==0: + # First loop is likely to "leak" as we cache things. + # Leaking after that is a problem. + num_refs = gettotalrefcount() + + lost = gettotalrefcount() - num_refs + # 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: + print "*** Lost %d references" % (lost,) + +# Make this test run under our std test suite +def suite(): + return suite_from_functions(test_refcount) + +if __name__=='__main__': + testmain() diff --git a/src/libs/xpcom18a4/python/tools/regxpcom.py b/src/libs/xpcom18a4/python/tools/regxpcom.py new file mode 100755 index 00000000..2b7ea6a4 --- /dev/null +++ b/src/libs/xpcom18a4/python/tools/regxpcom.py @@ -0,0 +1,68 @@ +# ***** 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 Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# ActiveState Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2001 +# 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 ***** + +# 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": + registrar.autoUnregister(spec) + print "Successfully unregistered", spec.path + else: + registrar.autoRegister(spec) + print "Successfully registered", spec.path + +if len(sys.argv) < 2: + registrar.autoRegister( None) +else: + ProcessArgs(sys.argv[1:]) + +#_xpcom.NS_ShutdownXPCOM() diff --git a/src/libs/xpcom18a4/python/tools/tracer_demo.py b/src/libs/xpcom18a4/python/tools/tracer_demo.py new file mode 100755 index 00000000..045c3db8 --- /dev/null +++ b/src/libs/xpcom18a4/python/tools/tracer_demo.py @@ -0,0 +1,113 @@ +# ***** 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 Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# ActiveState Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000, 2001 +# 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 ***** + +# This is a demo is how to use the xpcom.server "tracer" facility. +# +# This demo installs a tracer that uses the Python profiler. It then +# creates the Python test component, and references some methods +# and properties. It then dumps the profile statistics. + +# This same technique could also be used for debugging, for example. + +import profile + +p = profile.Profile() +getters = {} +setters = {} + +# A wrapper around a function - looks like a function, +# but actually profiles the delegate. +class TracerDelegate: + def __init__(self, callme): + self.callme = callme + def __call__(self, *args): + return p.runcall(self.callme, *args) + +# A wrapper around each of our XPCOM objects. All PyXPCOM calls +# in are made on this object, which creates a TracerDelagate around +# every function. As the function is called, it collects profile info. +class Tracer: + def __init__(self, ob): + self.__dict__['_ob'] = ob + def __repr__(self): + return "<Tracer around %r>" % (self._ob,) + def __str__(self): + return "<Tracer around %r>" % (self._ob,) + def __getattr__(self, attr): + ret = getattr(self._ob, attr) # Attribute error just goes up + if callable(ret): + return TracerDelegate(ret) + else: + if not attr.startswith("_com_") and not attr.startswith("_reg_"): + getters[attr] = getters.setdefault(attr,0) + 1 + return ret + def __setattr__(self, attr, val): + if self.__dict__.has_key(attr): + self.__dict__[attr] = val + return + setters[attr] = setters.setdefault(attr,0) + 1 + setattr(self._ob, attr, val) + +# Installed as a global XPCOM function that if exists, will be called +# to wrap each XPCOM object created. +def MakeTracer(ob): + # In some cases we may be asked to wrap ourself, so handle that. + if isinstance(ob, Tracer): + return ob + return Tracer(ob) + +def test(): + import xpcom.server, xpcom.components + xpcom.server.tracer = MakeTracer + contractid = "Python.TestComponent" + for i in range(100): + c = xpcom.components.classes[contractid].createInstance().queryInterface(xpcom.components.interfaces.nsIPythonTestInterface) + c.boolean_value = 0 + a = c.boolean_value + c.do_boolean(0,1) + print "Finshed" + p.print_stats() + print "%-30s%s" % ("Attribute Gets", "Number") + print "-" * 36 + for name, num in getters.items(): + print "%-30s%d" % (name, num) + print "%-30s%s" % ("Attribute Sets", "Number") + print "-" * 36 + for name, num in setters.items(): + print "%-30s%d" % (name, num) + +test() diff --git a/src/libs/xpcom18a4/python/vboxxpcom.py b/src/libs/xpcom18a4/python/vboxxpcom.py new file mode 100755 index 00000000..6fd54d53 --- /dev/null +++ b/src/libs/xpcom18a4/python/vboxxpcom.py @@ -0,0 +1,83 @@ +""" +Copyright (C) 2008-2022 Oracle and/or its affiliates. + +This file is part of VirtualBox base platform packages, as +available from https://www.virtualbox.org. + +This program is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License +as published by the Free Software Foundation, in version 3 of the +License. + +This program is distributed in the hope that it will be useful, but +WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, see <https://www.gnu.org/licenses>. + +SPDX-License-Identifier: GPL-3.0-only +""" + +import xpcom +import sys +import platform + +# +# This code overcomes somewhat unlucky feature of Python, where it searches +# for binaries in the same place as platfom independent modules, while +# rest of Python bindings expect _xpcom to be inside xpcom module +# + +_asVBoxPythons = [ + 'VBoxPython' + str(sys.version_info[0]) + '_' + str(sys.version_info[1]), + 'VBoxPython' + str(sys.version_info[0]), + 'VBoxPython' +] + +# For Python 3.2 and later use the right ABI flag suffix for the module. +if sys.hexversion >= 0x030200f0 and sys.abiflags: + _asNew = [] + for sCandidate in _asVBoxPythons: + if sCandidate[-1:].isdigit(): + _asNew.append(sCandidate + sys.abiflags) + else: + _asNew.append(sCandidate) + _asVBoxPythons = _asNew + del _asNew + +# On platforms where we ship both 32-bit and 64-bit API bindings, we have to +# look for the right set if we're a 32-bit process. +if platform.system() in [ 'SunOS', ] and sys.maxsize <= 2**32: + _asNew = [ sCandidate + '_x86' for sCandidate in _asVBoxPythons ] + _asNew.extend(_asVBoxPythons) + _asVBoxPythons = _asNew + del _asNew + +# On Darwin (aka Mac OS X) we know exactly where things are in a normal +# VirtualBox installation. +## @todo Edit this at build time to the actual VBox location set in the make files. +## @todo We know the location for most hardened builds, not just darwin! +if platform.system() == 'Darwin': + sys.path.append('/Applications/VirtualBox.app/Contents/MacOS') + +_oVBoxPythonMod = None +for m in _asVBoxPythons: + try: + _oVBoxPythonMod = __import__(m) + break + except: + pass + #except Exception as x: + # print('m=%s x=%s' % (m, x)) + +if platform.system() == 'Darwin': + sys.path.remove('/Applications/VirtualBox.app/Contents/MacOS') + +if _oVBoxPythonMod == None: + raise Exception('Cannot find VBoxPython module (tried: %s)' % (', '.join(_asVBoxPythons),)) + +sys.modules['xpcom._xpcom'] = _oVBoxPythonMod +xpcom._xpcom = _oVBoxPythonMod + diff --git a/src/libs/xpcom18a4/python/xpcom_consts.py b/src/libs/xpcom18a4/python/xpcom_consts.py new file mode 100644 index 00000000..933f93ef --- /dev/null +++ b/src/libs/xpcom18a4/python/xpcom_consts.py @@ -0,0 +1,272 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# ActiveState Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000, 2001 +# 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 ***** + +# Could maybe later have a process that extracted these enums should they change. +# from nsFileLocations.h +App_DirectoryBase = 0x00010000 +App_PrefsDirectory30 = App_DirectoryBase + 1 +App_PrefsDirectory40 = App_DirectoryBase + 2 +App_PrefsDirectory50 = App_DirectoryBase + 3 +App_ResDirectory = App_DirectoryBase + 5 +App_UserProfileDirectory30 = App_DirectoryBase + 10 +App_UserProfileDirectory40 = App_DirectoryBase + 11 +App_UserProfileDirectory50 = App_DirectoryBase + 12 +App_DefaultUserProfileRoot30 = App_DirectoryBase + 13 +App_DefaultUserProfileRoot40 = App_DirectoryBase + 14 +App_DefaultUserProfileRoot50 = App_DirectoryBase + 15 +App_ProfileDefaultsFolder30 = App_DirectoryBase + 16 +App_ProfileDefaultsFolder40 = App_DirectoryBase + 17 +App_ProfileDefaultsFolder50 = App_DirectoryBase + 18 +App_PrefDefaultsFolder50 = App_DirectoryBase + 19 +App_DefaultsFolder50 = App_DirectoryBase + 25 +App_ComponentsDirectory = App_DirectoryBase + 30 +App_ChromeDirectory = App_DirectoryBase + 31 +App_PluginsDirectory = App_DirectoryBase + 32 +App_UserChromeDirectory = App_DirectoryBase + 40 +App_FileBase = App_DirectoryBase + 1000 +App_PreferencesFile30 = App_FileBase + 1 +App_PreferencesFile40 = App_FileBase + 2 +App_PreferencesFile50 = App_FileBase + 3 +App_BookmarksFile30 = App_FileBase + 10 +App_BookmarksFile40 = App_FileBase + 11 +App_BookmarksFile50 = App_FileBase + 12 +App_Registry40 = App_FileBase + 20 +App_Registry50 = App_FileBase + 21 +App_LocalStore50 = App_FileBase + 30 +App_History50 = App_FileBase + 40 +App_MailDirectory50 = App_FileBase + 50 +App_ImapMailDirectory50 = App_FileBase + 60 +App_NewsDirectory50 = App_FileBase + 70 +App_MessengerFolderCache50 = App_FileBase + 80 +App_UsersPanels50 = App_FileBase + 90 +App_SearchFile50 = App_FileBase + 100 +App_SearchDirectory50 = App_FileBase + 101 + +# From nsSpecialSystemDirectory.h +OS_DriveDirectory = 1 +OS_TemporaryDirectory = 2 +OS_CurrentProcessDirectory= 3 +OS_CurrentWorkingDirectory= 4 + +XPCOM_CurrentProcessComponentDirectory= 5 +XPCOM_CurrentProcessComponentRegistry= 6 + +Moz_BinDirectory = 10 + +Mac_SystemDirectory = 101 +Mac_DesktopDirectory = 102 +Mac_TrashDirectory = 103 +Mac_StartupDirectory = 104 +Mac_ShutdownDirectory = 105 +Mac_AppleMenuDirectory = 106 +Mac_ControlPanelDirectory = 107 +Mac_ExtensionDirectory = 108 +Mac_FontsDirectory = 109 +Mac_PreferencesDirectory = 110 +Mac_DocumentsDirectory = 111 +Mac_InternetSearchDirectory = 112 + +Win_SystemDirectory = 201 +Win_WindowsDirectory = 202 + +Win_HomeDirectory = 203 +Win_Desktop = 204 +Win_Programs = 205 +Win_Controls = 206 +Win_Printers = 207 +Win_Personal = 208 +Win_Favorites = 209 +Win_Startup = 210 +Win_Recent = 211 +Win_Sendto = 212 +Win_Bitbucket = 213 +Win_Startmenu = 214 +Win_Desktopdirectory = 215 +Win_Drives = 216 +Win_Network = 217 +Win_Nethood = 218 +Win_Fonts = 219 +Win_Templates = 220 +Win_Common_Startmenu = 221 +Win_Common_Programs = 222 +Win_Common_Startup = 223 +Win_Common_Desktopdirectory = 224 +Win_Appdata = 225 +Win_Printhood = 226 + +Unix_LocalDirectory = 301 +Unix_LibDirectory = 302 +Unix_HomeDirectory = 303 + +BeOS_SettingsDirectory = 401 +BeOS_HomeDirectory = 402 +BeOS_DesktopDirectory = 403 +BeOS_SystemDirectory = 404 + +OS2_SystemDirectory = 501 + +# Type/Variant related constants. +TD_INT8 = 0 +TD_INT16 = 1 +TD_INT32 = 2 +TD_INT64 = 3 +TD_UINT8 = 4 +TD_UINT16 = 5 +TD_UINT32 = 6 +TD_UINT64 = 7 +TD_FLOAT = 8 +TD_DOUBLE = 9 +TD_BOOL = 10 +TD_CHAR = 11 +TD_WCHAR = 12 +TD_VOID = 13 +TD_PNSIID = 14 +TD_DOMSTRING = 15 +TD_PSTRING = 16 +TD_PWSTRING = 17 +TD_INTERFACE_TYPE = 18 +TD_INTERFACE_IS_TYPE = 19 +TD_ARRAY = 20 +TD_PSTRING_SIZE_IS = 21 +TD_PWSTRING_SIZE_IS = 22 +TD_UTF8STRING = 23 +TD_CSTRING = 24 +TD_ASTRING = 25 + +# From xpt_struct.h +XPT_TDP_POINTER = 0x80 +XPT_TDP_UNIQUE_POINTER = 0x40 +XPT_TDP_REFERENCE = 0x20 +XPT_TDP_FLAGMASK = 0xe0 +XPT_TDP_TAGMASK = (~XPT_TDP_FLAGMASK) +def XPT_TDP_TAG(tdp): return (tdp & XPT_TDP_TAGMASK) + +def XPT_TDP_IS_POINTER(flags): return (flags & XPT_TDP_POINTER) +def XPT_TDP_IS_UNIQUE_POINTER(flags): return (flags & XPT_TDP_UNIQUE_POINTER) +def XPT_TDP_IS_REFERENCE(flags): return (flags & XPT_TDP_REFERENCE) + +XPT_ID_SCRIPTABLE = 0x80 +XPT_ID_FLAGMASK = 0x80 +XPT_ID_TAGMASK = ~XPT_ID_FLAGMASK +def XPT_ID_TAG(id): return id & XPT_ID_TAGMASK + +def XPT_ID_IS_SCRIPTABLE(flags): return flags & XPT_ID_SCRIPTABLE + +XPT_PD_IN = 0x80 +XPT_PD_OUT = 0x40 +XPT_PD_RETVAL = 0x20 +XPT_PD_SHARED = 0x10 +XPT_PD_DIPPER = 0x08 +XPT_PD_FLAGMASK = 0xf0 + +def XPT_PD_IS_IN(flags): return (flags & XPT_PD_IN) +def XPT_PD_IS_OUT(flags): return (flags & XPT_PD_OUT) +def XPT_PD_IS_RETVAL(flags): return (flags & XPT_PD_RETVAL) +def XPT_PD_IS_SHARED(flags): return (flags & XPT_PD_SHARED) +def XPT_PD_IS_DIPPER(flags): return (flags & XPT_PD_DIPPER) + +XPT_MD_GETTER = 0x80 +XPT_MD_SETTER = 0x40 +XPT_MD_NOTXPCOM = 0x20 +XPT_MD_CTOR = 0x10 +XPT_MD_HIDDEN = 0x08 +XPT_MD_FLAGMASK = 0xf8 + +def XPT_MD_IS_GETTER(flags): return (flags & XPT_MD_GETTER) +def XPT_MD_IS_SETTER(flags): return (flags & XPT_MD_SETTER) +def XPT_MD_IS_NOTXPCOM(flags): return (flags & XPT_MD_NOTXPCOM) +def XPT_MD_IS_CTOR(flags): return (flags & XPT_MD_CTOR) +def XPT_MD_IS_HIDDEN(flags): return (flags & XPT_MD_HIDDEN) + +# From xptinfo.h + +T_I8 = TD_INT8 +T_I16 = TD_INT16 +T_I32 = TD_INT32 +T_I64 = TD_INT64 +T_U8 = TD_UINT8 +T_U16 = TD_UINT16 +T_U32 = TD_UINT32 +T_U64 = TD_UINT64 +T_FLOAT = TD_FLOAT +T_DOUBLE = TD_DOUBLE +T_BOOL = TD_BOOL +T_CHAR = TD_CHAR +T_WCHAR = TD_WCHAR +T_VOID = TD_VOID +T_IID = TD_PNSIID +T_DOMSTRING = TD_DOMSTRING +T_CHAR_STR = TD_PSTRING +T_WCHAR_STR = TD_PWSTRING +T_INTERFACE = TD_INTERFACE_TYPE +T_INTERFACE_IS = TD_INTERFACE_IS_TYPE +T_ARRAY = TD_ARRAY +T_PSTRING_SIZE_IS = TD_PSTRING_SIZE_IS +T_PWSTRING_SIZE_IS = TD_PWSTRING_SIZE_IS +T_UTF8STRING = TD_UTF8STRING +T_CSTRING = TD_CSTRING +T_ASTRING = TD_ASTRING + +# from nsIVariant +VTYPE_INT8 = 0 +VTYPE_INT16 = 1 +VTYPE_INT32 = 2 +VTYPE_INT64 = 3 +VTYPE_UINT8 = 4 +VTYPE_UINT16 = 5 +VTYPE_UINT32 = 6 +VTYPE_UINT64 = 7 +VTYPE_FLOAT = 8 +VTYPE_DOUBLE = 9 +VTYPE_BOOL = 10 +VTYPE_CHAR = 11 +VTYPE_WCHAR = 12 +VTYPE_VOID = 13 +VTYPE_ID = 14 +VTYPE_DOMSTRING = 15 +VTYPE_CHAR_STR = 16 +VTYPE_WCHAR_STR = 17 +VTYPE_INTERFACE = 18 +VTYPE_INTERFACE_IS = 19 +VTYPE_ARRAY = 20 +VTYPE_STRING_SIZE_IS = 21 +VTYPE_WSTRING_SIZE_IS = 22 +VTYPE_UTF8STRING = 23 +VTYPE_CSTRING = 24 +VTYPE_ASTRING = 25 +VTYPE_EMPTY_ARRAY = 254 +VTYPE_EMPTY = 255 diff --git a/src/libs/xpcom18a4/python/xpt.py b/src/libs/xpcom18a4/python/xpt.py new file mode 100755 index 00000000..67021572 --- /dev/null +++ b/src/libs/xpcom18a4/python/xpt.py @@ -0,0 +1,471 @@ +# ***** 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 the Python XPCOM language bindings. +# +# The Initial Developer of the Original Code is +# ActiveState Tool Corp. +# Portions created by the Initial Developer are Copyright (C) 2000, 2001 +# the Initial Developer. All Rights Reserved. +# +# Contributor(s): +# David Ascher <DavidA@ActiveState.com> (original author) +# Mark Hammond <mhammond@skippinet.com.au> +# +# 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 ***** + +""" +Program: xpt.py + +Task: describe interfaces etc using XPCOM reflection. + +Subtasks: + output (nearly) exactly the same stuff as xpt_dump, for verification + output Python source code that can be used as a template for an interface + +Status: Works pretty well if you ask me :-) + +Author: + David Ascher did an original version that parsed XPT files + directly. Mark Hammond changed it to use the reflection interfaces, + but kept most of the printing logic. + + +Revision: + + 0.1: March 6, 2000 + 0.2: April 2000 - Mark removed lots of Davids lovely parsing code in favour + of the new xpcom interfaces that provide this info. + + May 2000 - Moved into Perforce - track the log there! + Early 2001 - Moved into the Mozilla CVS tree - track the log there! + +Todo: + Fill out this todo list. + +""" + +import string, sys +import xpcom +import xpcom._xpcom + +from .xpcom_consts import * + +class Interface: + def __init__(self, iid): + iim = xpcom._xpcom.XPTI_GetInterfaceInfoManager() + 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) + self.constants = Constants(item) + + # delegate attributes to the real interface + def __getattr__(self, attr): + return getattr(self.interface_info, attr) + + def GetParent(self): + try: + raw_parent = self.interface_info.GetParent() + if raw_parent is None: + return None + return Interface(raw_parent.GetIID()) + except xpcom.Exception: + # Parent interface is probably not scriptable - assume nsISupports. + if xpcom.verbose: + # The user may be confused as to why this is happening! + print("The parent interface of IID '%s' can not be located - assuming nsISupports") + return Interface(xpcom._xpcom.IID_nsISupports) + + def Describe_Python(self): + method_reprs = [] + methods = [m for m in self.methods if not m.IsNotXPCOM()] + for m in methods: + method_reprs.append(m.Describe_Python()) + method_joiner = "\n" + methods_repr = method_joiner.join(method_reprs) + return \ +"""class %s: + _com_interfaces_ = xpcom.components.interfaces.%s + # If this object needs to be registered, the following 2 are also needed. + # _reg_clsid_ = "{a new clsid generated for this object}" + # _reg_contractid_ = "The.Object.Name"\n%s""" % (self.GetName(), self.GetIID().name, methods_repr) + + def Describe(self): + # Make the IID look like xtp_dump - "(" instead of "{" + iid_use = "(" + str(self.GetIID())[1:-1] + ")" + s = ' - '+self.namespace+'::'+ self.GetName() + ' ' + iid_use + ':\n' + + parent = self.GetParent() + if parent is not None: + s = s + ' Parent: ' + parent.namespace + '::' + parent.GetName() + '\n' + s = s + ' Flags:\n' + if self.IsScriptable(): word = 'TRUE' + else: word = 'FALSE' + s = s + ' Scriptable: ' + word + '\n' + s = s + ' Methods:\n' + methods = [m for m in self.methods if not m.IsNotXPCOM()] + if len(methods): + for m in methods: + s = s + ' ' + m.Describe() + '\n' + else: + s = s + ' No Methods\n' + s = s + ' Constants:\n' + if self.constants: + for c in self.constants: + s = s + ' ' + c.Describe() + '\n' + else: + s = s + ' No Constants\n' + + return s + +# A class that allows caching and iterating of methods. +class Methods: + def __init__(self, interface_info): + self.interface_info = interface_info + try: + self.items = [None] * interface_info.GetMethodCount() + except xpcom.Exception: + if xpcom.verbose: + print("** GetMethodCount failed?? - assuming no methods") + self.items = [] + def __len__(self): + return len(self.items) + def __getitem__(self, index): + ret = self.items[index] + if ret is None: + mi = self.interface_info.GetMethodInfo(index) + ret = self.items[index] = Method(mi, index, self.interface_info) + return ret + +class Method: + + def __init__(self, method_info, method_index, interface_info = None): + self.interface_info = interface_info + self.method_index = method_index + self.flags, self.name, param_descs, self.result_desc = method_info + # Build the params. + self.params = [] + pi=0 + for pd in param_descs: + self.params.append( Parameter(pd, pi, method_index, interface_info) ) + pi = pi + 1 + # Run over the params setting the "sizeof" params to hidden. + for p in self.params: + td = p.type_desc + tag = XPT_TDP_TAG(td[0]) + if tag==T_ARRAY and p.IsIn(): + self.params[td[1]].hidden_indicator = 2 + elif tag in [T_PSTRING_SIZE_IS, T_PWSTRING_SIZE_IS] and p.IsIn(): + self.params[td[1]].hidden_indicator = 1 + + def IsGetter(self): + return (self.flags & XPT_MD_GETTER) + def IsSetter(self): + return (self.flags & XPT_MD_SETTER) + def IsNotXPCOM(self): + return (self.flags & XPT_MD_NOTXPCOM) + def IsConstructor(self): + return (self.flags & XPT_MD_CTOR) + def IsHidden(self): + return (self.flags & XPT_MD_HIDDEN) + + def Describe_Python(self): + if self.method_index < 3: # Ignore QI etc + return "" + base_name = self.name + if self.IsGetter(): + name = "get_%s" % (base_name,) + elif self.IsSetter(): + name = "set_%s" % (base_name,) + else: + name = base_name + param_decls = ["self"] + in_comments = [] + out_descs = [] + result_comment = "Result: void - None" + for p in self.params: + in_desc, in_desc_comments, out_desc, this_result_comment = p.Describe_Python() + if in_desc is not None: + param_decls.append(in_desc) + if in_desc_comments is not None: + in_comments.append(in_desc_comments) + if out_desc is not None: + out_descs.append(out_desc) + if this_result_comment is not None: + result_comment = this_result_comment + joiner = "\n # " + in_comment = out_desc = "" + if in_comments: in_comment = joiner + joiner.join(in_comments) + if out_descs: out_desc = joiner + joiner.join(out_descs) + + return """ def %s( %s ): + # %s%s%s + pass""" % (name, ", ".join(param_decls), result_comment, in_comment, out_desc) + + def Describe(self): + s = '' + if self.IsGetter(): + G = 'G' + else: + G = ' ' + if self.IsSetter(): + S = 'S' + else: S = ' ' + if self.IsHidden(): + H = 'H' + else: + H = ' ' + if self.IsNotXPCOM(): + N = 'N' + else: + N = ' ' + if self.IsConstructor(): + C = 'C' + else: + C = ' ' + + def desc(a): return a.Describe() + method_desc = string.join(list(map(desc, self.params)), ', ') + result_type = TypeDescriber(self.result_desc[0], None) + return_desc = result_type.Describe() + i = string.find(return_desc, 'retval ') + if i != -1: + return_desc = return_desc[:i] + return_desc[i+len('retval '):] + return G+S+H+N+C+' '+return_desc+' '+self.name + '('+ method_desc + ');' + +class Parameter: + def __init__(self, param_desc, param_index, method_index, interface_info = None): + self.param_flags, self.type_desc = param_desc + self.hidden_indicator = 0 # Is this a special "size" type param that will be hidden from Python? + self.param_index = param_index + self.method_index= method_index + self.interface_info = interface_info + def __repr__(self): + return "<param %(param_index)d (method %(method_index)d) - flags = 0x%(param_flags)x, type = %(type_desc)s>" % self.__dict__ + def IsIn(self): + return XPT_PD_IS_IN(self.param_flags) + def IsOut(self): + return XPT_PD_IS_OUT(self.param_flags) + def IsInOut(self): + return self.IsIn() and self.IsOut() + def IsRetval(self): + return XPT_PD_IS_RETVAL(self.param_flags) + def IsShared(self): + return XPT_PD_IS_SHARED(self.param_flags) + def IsDipper(self): + return XPT_PD_IS_DIPPER(self.param_flags) + + def Describe_Python(self): + name = "param%d" % (self.param_index,) + if self.hidden_indicator: + # Could remove the comment - Im trying to tell the user where that param has + # gone from the signature! + return None, "%s is a hidden parameter" % (name,), None, None + t = TypeDescriber(self.type_desc[0], self) + decl = in_comment = out_comment = result_comment = None + type_desc = t.Describe() + if self.IsIn() and not self.IsDipper(): + decl = name + extra="" + if self.IsOut(): + extra = "Out" + in_comment = "In%s: %s: %s" % (extra, name, type_desc) + elif self.IsOut() or self.IsDipper(): + if self.IsRetval(): + result_comment = "Result: %s" % (type_desc,) + else: + out_comment = "Out: %s" % (type_desc,) + return decl, in_comment, out_comment, result_comment + + def Describe(self): + parts = [] + if self.IsInOut(): + parts.append('inout') + elif self.IsIn(): + parts.append('in') + elif self.IsOut(): + parts.append('out') + + if self.IsDipper(): parts.append("dipper") + if self.IsRetval(): parts.append('retval') + if self.IsShared(): parts.append('shared') + t = TypeDescriber(self.type_desc[0], self) + type_str = t.Describe() + parts.append(type_str) + return string.join(parts) + +# A class that allows caching and iterating of constants. +class Constants: + def __init__(self, interface_info): + self.interface_info = interface_info + try: + self.items = [None] * interface_info.GetConstantCount() + except xpcom.Exception: + if xpcom.verbose: + print("** GetConstantCount failed?? - assuming no constants") + self.items = [] + def __len__(self): + return len(self.items) + def __getitem__(self, index): + ret = self.items[index] + if ret is None: + ci = self.interface_info.GetConstant(index) + ret = self.items[index] = Constant(ci) + return ret + +class Constant: + def __init__(self, ci): + self.name, self.type, self.value = ci + + def Describe(self): + return TypeDescriber(self.type, None).Describe() + ' ' +self.name+' = '+str(self.value)+';' + + __str__ = Describe + +def MakeReprForInvoke(param): + tag = param.type_desc[0] & XPT_TDP_TAGMASK + if tag == T_INTERFACE: + i_info = param.interface_info + try: + iid = i_info.GetIIDForParam(param.method_index, param.param_index) + except xpcom.Exception: + # IID not available (probably not scriptable) - just use nsISupports. + iid = xpcom._xpcom.IID_nsISupports + return param.type_desc[0], 0, 0, str(iid) + elif tag == T_ARRAY: + i_info = param.interface_info + array_desc = i_info.GetTypeForParam(param.method_index, param.param_index, 1) + return param.type_desc[:-1] + array_desc[:1] + return param.type_desc + + +class TypeDescriber: + def __init__(self, type_flags, param): + self.type_flags = type_flags + self.tag = XPT_TDP_TAG(self.type_flags) + self.param = param + def IsPointer(self): + return XPT_TDP_IS_POINTER(self.type_flags) + def IsUniquePointer(self): + return XPT_TDP_IS_UNIQUE_POINTER(self.type_flags) + def IsReference(self): + return XPT_TDP_IS_REFERENCE(self.type_flags) + def repr_for_invoke(self): + return (self.type_flags,) + def GetName(self): + is_ptr = self.IsPointer() + data = type_info_map.get(self.tag) + if data is None: + data = ("unknown",) + if self.IsReference(): + if len(data) > 2: + return data[2] + return data[0] + " &" + if self.IsPointer(): + if len(data)>1: + return data[1] + return data[0] + " *" + return data[0] + + def Describe(self): + if self.tag == T_ARRAY: + # NOTE - Adding a type specifier to the array is different from xpt_dump.exe + if self.param is None or self.param.interface_info is None: + type_desc = "" # Dont have explicit info about the array type :-( + else: + i_info = self.param.interface_info + type_code = i_info.GetTypeForParam(self.param.method_index, self.param.param_index, 1) + type_desc = TypeDescriber( type_code[0], None).Describe() + return self.GetName() + "[" + type_desc + "]" + elif self.tag == T_INTERFACE: + if self.param is None or self.param.interface_info is None: + return "nsISomething" # Dont have explicit info about the IID :-( + i_info = self.param.interface_info + m_index = self.param.method_index + p_index = self.param.param_index + try: + iid = i_info.GetIIDForParam(m_index, p_index) + return iid.name + except xpcom.Exception: + return "nsISomething" + return self.GetName() + +# These are just for output purposes, so should be +# the same as xpt_dump uses +type_info_map = { + T_I8 : ("int8",), + T_I16 : ("int16",), + T_I32 : ("int32",), + T_I64 : ("int64",), + T_U8 : ("uint8",), + T_U16 : ("uint16",), + T_U32 : ("uint32",), + T_U64 : ("uint64",), + T_FLOAT : ("float",), + T_DOUBLE : ("double",), + T_BOOL : ("boolean",), + T_CHAR : ("char",), + T_WCHAR : ("wchar_t", "wstring"), + T_VOID : ("void",), + T_IID : ("reserved", "nsIID *", "nsIID &"), + T_DOMSTRING : ("DOMString",), + T_CHAR_STR : ("reserved", "string"), + T_WCHAR_STR : ("reserved", "wstring"), + T_INTERFACE : ("reserved", "Interface"), + T_INTERFACE_IS : ("reserved", "InterfaceIs *"), + T_ARRAY : ("reserved", "Array"), + T_PSTRING_SIZE_IS : ("reserved", "string_s"), + T_PWSTRING_SIZE_IS : ("reserved", "wstring_s"), +} + +def dump_interface(iid, mode): + interface = Interface(iid) + describer_name = "Describe" + if mode == "xptinfo": mode = None + if mode is not None: + describer_name = describer_name + "_" + mode.capitalize() + describer = getattr(interface, describer_name) + print(describer()) + +if __name__=='__main__': + if len(sys.argv) == 1: + print("Usage: xpt.py [-xptinfo] interface_name, ...") + print(" -info: Dump in a style similar to the xptdump tool") + print("Dumping nsISupports and nsIInterfaceInfo") + sys.argv.append('nsIInterfaceInfo') + sys.argv.append('-xptinfo') + sys.argv.append('nsISupports') + sys.argv.append('nsIInterfaceInfo') + + mode = "Python" + for i in sys.argv[1:]: + if i[0] == "-": + mode = i[1:] + else: + dump_interface(i, mode) |