forked from mirrors/gecko-dev
		
	 8ce6f5f5be
			
		
	
	
		8ce6f5f5be
		
	
	
	
	
		
			
			opportunity to remove support for nsIComponentManagerObsolete, and formalize a nice shutdown API. Not part of the build.
		
			
				
	
	
		
			234 lines
		
	
	
	
		
			8.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			234 lines
		
	
	
	
		
			8.8 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # ***** 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
 | |
| import xpt
 | |
| import xpcom, _xpcom
 | |
| import xpcom.client
 | |
| import xpcom.server
 | |
| import types
 | |
| 
 | |
| StringTypes = [types.StringType, types.UnicodeType]
 | |
| 
 | |
| 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 self._dict_data.keys()
 | |
|     def items(self):
 | |
|         if self._dict_data is None:
 | |
|             self._dict_data = self._build_dict()
 | |
|         return self._dict_data.items()
 | |
|     def values(self):
 | |
|         if self._dict_data is None:
 | |
|             self._dict_data = self._build_dict()
 | |
|         return 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 self._dict_data.has_key(attr):
 | |
|             return self._dict_data[attr]
 | |
|         return self._get_one(attr)
 | |
|     def __getitem__(self, item):
 | |
|         if self._dict_data is not None and self._dict_data.has_key(item):
 | |
|             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 __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 c.has_key(attr):
 | |
|             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, why:
 | |
|             # Present a better exception message, and give a more useful error code.
 | |
|             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, details:
 | |
|             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.IID
 | |
| 
 | |
| def _on_shutdown():
 | |
|     global manager, registrar, classes, interfaces, interfaceInfoManager, serviceManager, _constants_by_iid_map
 | |
|     manager = registrar = classes = interfaces = interfaceInfoManager = serviceManager = _constants_by_iid_map = None
 | |
|     # for historical reasons we call these manually.
 | |
|     xpcom.client._shutdown()
 | |
|     xpcom.server._shutdown()
 | |
| 
 | |
| # import xpcom.shutdown late as it depends on us!
 | |
| import shutdown
 | |
| shutdown.register(_on_shutdown)
 | |
| 
 | |
| del _on_shutdown, shutdown
 |