summaryrefslogtreecommitdiffstats
path: root/src/libs/xpcom18a4/xpcom/proxy
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/xpcom18a4/xpcom/proxy')
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/Makefile.in49
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/Makefile.in63
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyCreateInstance.idl53
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyObjectManager.idl87
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/nsProxiedService.h164
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/nsProxyEvent.h183
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/public/nsProxyRelease.h112
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/.cvsignore1
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/Makefile.in67
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsIProxyCreateInstance.h39
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEvent.cpp613
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventClass.cpp367
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventObject.cpp555
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventPrivate.h201
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsProxyObjectManager.cpp322
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/src/nsProxyRelease.cpp55
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/tests/.cvsignore2
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/tests/Makefile.in60
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/tests/nsITestProxy.idl9
-rw-r--r--src/libs/xpcom18a4/xpcom/proxy/tests/proxytests.cpp553
22 files changed, 3557 insertions, 0 deletions
diff --git a/src/libs/xpcom18a4/xpcom/proxy/.cvsignore b/src/libs/xpcom18a4/xpcom/proxy/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/proxy/Makefile.in b/src/libs/xpcom18a4/xpcom/proxy/Makefile.in
new file mode 100644
index 00000000..c30f214f
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/Makefile.in
@@ -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 mozilla.org Code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+DIRS = public src
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/.cvsignore b/src/libs/xpcom18a4/xpcom/proxy/public/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/Makefile.in b/src/libs/xpcom18a4/xpcom/proxy/public/Makefile.in
new file mode 100644
index 00000000..d6950b9a
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/Makefile.in
@@ -0,0 +1,63 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+ifeq ($(OS_ARCH),WINNT)
+XPIDL_MODULE = proxyObject
+else
+XPIDL_MODULE = proxyObjInst
+endif
+
+EXPORTS = \
+ nsProxyEvent.h \
+ nsProxyRelease.h \
+ nsProxiedService.h \
+ $(NULL)
+
+XPIDLSRCS = nsIProxyCreateInstance.idl \
+ nsIProxyObjectManager.idl \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyCreateInstance.idl b/src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyCreateInstance.idl
new file mode 100644
index 00000000..cd576f7b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyCreateInstance.idl
@@ -0,0 +1,53 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 ***** */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(948c2080-0398-11d3-915e-0000863011c4)]
+interface nsIProxyCreateInstance : nsISupports
+{
+ [noscript] void CreateInstanceByIID(in nsIIDRef cid,
+ in nsISupports aOuter,
+ in nsIIDRef iid,
+ out voidPtr result);
+
+ [noscript] void CreateInstanceByContractID(in string aContractID,
+ in nsISupports aOuter,
+ in nsIIDRef iid,
+ out voidPtr result);
+};
+
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyObjectManager.idl b/src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyObjectManager.idl
new file mode 100644
index 00000000..5b2cfd4d
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/nsIProxyObjectManager.idl
@@ -0,0 +1,87 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@netscape.com> (Original Author)
+ * Dan Mosedale <dmose@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 ***** */
+#include "nsISupports.idl"
+interface nsIEventQueue;
+
+[scriptable, uuid(eea90d43-b059-11d2-915e-c12b696c9333)]
+interface nsIProxyObjectManager : nsISupports
+{
+ void getProxyForObject(in nsIEventQueue destQueue,
+ in nsIIDRef iid,
+ in nsISupports object,
+ in PRInt32 proxyType,
+ [iid_is(iid),retval] out nsQIResult result);
+
+ void getProxy(in nsIEventQueue destQueue,
+ in nsIIDRef cid,
+ in nsISupports aOuter,
+ in nsIIDRef iid,
+ in PRInt32 proxyType,
+ [iid_is(iid),retval] out nsQIResult result);
+
+};
+
+
+%{C++
+#include "nsProxyEvent.h"
+
+#define NS_XPCOMPROXY_CONTRACTID "@mozilla.org/xpcomproxy;1"
+#define NS_XPCOMPROXY_CLASSNAME "XPCom Proxy"
+
+#define NS_PROXYEVENT_MANAGER_CID \
+{ 0xeea90d41, \
+ 0xb059, \
+ 0x11d2, \
+ {0x91, 0x5e, 0xc1, 0x2b, 0x69, 0x6c, 0x93, 0x33}\
+}
+
+/**
+ * Helper function for code that already has a link-time dependency on
+ * libxpcom and needs to get proxies in a bunch of different places.
+ * This way, the caller isn't forced to get the proxy object manager
+ * themselves every single time, thus making the calling code more
+ * readable.
+ */
+extern NS_COM nsresult
+NS_GetProxyForObject(nsIEventQueue *destQueue,
+ REFNSIID aIID,
+ nsISupports* aObj,
+ PRInt32 proxyType,
+ void** aProxyObject);
+%}
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/nsProxiedService.h b/src/libs/xpcom18a4/xpcom/proxy/public/nsProxiedService.h
new file mode 100644
index 00000000..3a39ade1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/nsProxiedService.h
@@ -0,0 +1,164 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 ***** */
+
+#ifndef __nsProxiedServiceManager_h_
+#define __nsProxiedServiceManager_h_
+
+#include "nsIServiceManager.h"
+#include "nsIProxyObjectManager.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// NS_WITH_PROXIED_SERVICE: macro to make using services that need to be proxied
+// before using them easier.
+// Now you can replace this:
+// {
+// nsresult rv;
+// nsCOMPtr<nsIMyService> pIMyService =
+// do_GetService(kMyServiceCID, &rv);
+// if(NS_FAILED(rv))
+// return;
+// nsCOMPtr<nsIProxyObjectManager> pIProxyObjectManager =
+// do_GetService(kProxyObjectManagerCID, &rv);
+// if(NS_FAILED(rv))
+// return;
+// nsIMyService pIProxiedObject = NULL;
+// rv = pIProxyObjectManager->GetProxyForObject(pIProxyQueue,
+// NS_GET_IID(nsIMyService),
+// pIMyService, PROXY_SYNC,
+// (void**)&pIProxiedObject);
+// pIProxiedObject->DoIt(...); // Executed on same thread as pIProxyQueue
+// ...
+// pIProxiedObject->Release(); // Must be done as not managed for you.
+// }
+// with this:
+// {
+// nsresult rv;
+// NS_WITH_PROXIED_SERVICE(nsIMyService, pIMyService, kMyServiceCID,
+// pIProxyQueue, &rv);
+// if(NS_FAILED(rv))
+// return;
+// pIMyService->DoIt(...); // Executed on the same thread as pIProxyQueue
+// }
+// and the automatic destructor will take care of releasing the service and
+// the proxied object for you.
+//
+// Note that this macro requires you to link with the xpcom DLL to pick up the
+// static member functions from nsServiceManager.
+
+#define NS_WITH_PROXIED_SERVICE(T, var, cid, Q, rvAddr) \
+ nsProxiedService _serv##var(cid, NS_GET_IID(T), Q, PR_FALSE, rvAddr); \
+ T* var = (T*)(nsISupports*)_serv##var;
+
+#define NS_WITH_ALWAYS_PROXIED_SERVICE(T, var, cid, Q, rvAddr) \
+ nsProxiedService _serv##var(cid, NS_GET_IID(T), Q, PR_TRUE, rvAddr); \
+ T* var = (T*)(nsISupports*)_serv##var;
+
+////////////////////////////////////////////////////////////////////////////////
+// nsProxiedService
+////////////////////////////////////////////////////////////////////////////////
+
+class nsProxiedService
+{
+ public:
+
+ nsProxiedService(const nsCID &aClass, const nsIID &aIID,
+ nsIEventQueue* pIProxyQueue, PRBool always, nsresult*rv)
+ {
+ *rv = nsServiceManager::GetService(aClass,
+ aIID,
+ getter_AddRefs(mService));
+ if (NS_FAILED(*rv)) return;
+ InitProxy(aIID, pIProxyQueue, always, rv);
+ }
+
+ nsProxiedService(const char* aContractID, const nsIID &aIID,
+ nsIEventQueue* pIProxyQueue, PRBool always, nsresult*rv)
+ {
+ *rv = nsServiceManager::GetService(aContractID,
+ aIID,
+ getter_AddRefs(mService));
+ if (NS_FAILED(*rv)) return;
+ InitProxy(aIID, pIProxyQueue, always, rv);
+ }
+
+ void InitProxy(const nsIID &aIID, nsIEventQueue* pIProxyQueue,
+ PRBool always, nsresult*rv)
+ {
+ static NS_DEFINE_CID(kProxyObjectManagerCID, NS_PROXYEVENT_MANAGER_CID);
+
+ nsCOMPtr<nsIProxyObjectManager> pIProxyObjectManager =
+ do_GetService(kProxyObjectManagerCID, rv);
+ if (NS_FAILED(*rv)) return;
+
+ PRInt32 proxyType = PROXY_SYNC;
+ if (always) proxyType |= PROXY_ALWAYS;
+ *rv = pIProxyObjectManager->GetProxyForObject(pIProxyQueue,
+ aIID,
+ mService,
+ proxyType,
+ getter_AddRefs(mProxiedService));
+ }
+
+ ~nsProxiedService()
+ {
+ }
+
+ nsISupports* operator->() const
+ {
+ NS_PRECONDITION(mProxiedService != 0, "Your code should test the error result from the constructor.");
+ return mProxiedService;
+ }
+
+ PRBool operator==(const nsISupports* other)
+ {
+ return ((mProxiedService == other) || (mService == other));
+ }
+
+ operator nsISupports*() const
+ {
+ return mProxiedService;
+ }
+
+ protected:
+ nsCOMPtr<nsISupports> mProxiedService;
+ nsCOMPtr<nsISupports> mService;
+
+ };
+
+
+#endif //__nsProxiedServiceManager_h_
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/nsProxyEvent.h b/src/libs/xpcom18a4/xpcom/proxy/public/nsProxyEvent.h
new file mode 100644
index 00000000..c718bbdb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/nsProxyEvent.h
@@ -0,0 +1,183 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 ***** */
+
+#ifndef __nsProxyEvent_h_
+#define __nsProxyEvent_h_
+
+#include "nsCOMPtr.h"
+#include "nsAutoPtr.h"
+#include "nscore.h"
+#include "nsISupports.h"
+#include "nsIFactory.h"
+
+#include "nsIEventQueueService.h"
+#include "nsIEventQueue.h"
+#include "plevent.h"
+#include "prtypes.h"
+#include "xptcall.h"
+#include "xptinfo.h"
+
+class nsProxyObjectCallInfo;
+
+#define PROXY_SYNC 0x0001 // acts just like a function call.
+#define PROXY_ASYNC 0x0002 // fire and forget. This will return immediately and you will lose all return information.
+#define PROXY_ALWAYS 0x0004 // ignore check to see if the eventQ is on the same thread as the caller, and alway return a proxied object.
+
+//#define AUTOPROXIFICATION
+
+// WARNING about PROXY_ASYNC:
+//
+// If the calling thread goes away, any function which accesses the calling stack
+// will blow up.
+//
+// example:
+//
+// myFoo->bar(&x)
+//
+// ... thread goes away ...
+//
+// bar(PRInt32 *x)
+// {
+// *x = 0; <----- You will blow up here.
+//
+//
+// So what gets saved?
+//
+// You can safely pass base types by value. You can also pass interface pointers.
+// I will make sure that the interface pointers are addrefed while they are being
+// proxied. You can also pass string and wstring. These I will copy and free.
+//
+// I do **NOT** copy arrays or strings with size. If you are using these either
+// change your interface, or contact me about this feature request.
+
+
+
+
+class nsProxyObject
+{
+public:
+ nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, nsISupports *realObject);
+ nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, const nsCID &aClass, nsISupports *aDelegate, const nsIID &aIID);
+
+ void AddRef();
+ void Release();
+
+ ~nsProxyObject();
+
+ nsresult Post( PRUint32 methodIndex,
+ nsXPTMethodInfo * info,
+ nsXPTCMiniVariant * params,
+ nsIInterfaceInfo * interfaceInfo);
+
+ nsresult PostAndWait(nsProxyObjectCallInfo *proxyInfo);
+ nsISupports* GetRealObject() const { return mRealObject; }
+ nsIEventQueue* GetQueue() const { return mDestQueue; }
+ PRInt32 GetProxyType() const { return mProxyType; }
+
+ friend class nsProxyEventObject;
+private:
+
+ nsAutoRefCnt mRefCnt;
+
+ PRInt32 mProxyType;
+
+ nsCOMPtr<nsIEventQueue> mDestQueue; /* destination queue */
+
+ nsCOMPtr<nsISupports> mRealObject; /* the non-proxy object that this event is referring to.
+ This is a strong ref. */
+ nsCOMPtr<nsIEventQueueService> mEventQService;
+
+ nsresult convertMiniVariantToVariant(nsXPTMethodInfo * methodInfo,
+ nsXPTCMiniVariant * params,
+ nsXPTCVariant **fullParam,
+ uint8 *paramCount);
+
+};
+
+
+class nsProxyObjectCallInfo
+{
+public:
+
+ nsProxyObjectCallInfo(nsProxyObject* owner,
+ nsXPTMethodInfo *methodInfo,
+ PRUint32 methodIndex,
+ nsXPTCVariant* parameterList,
+ PRUint32 parameterCount,
+ PLEvent *event);
+
+ ~nsProxyObjectCallInfo();
+
+ PRUint32 GetMethodIndex() const { return mMethodIndex; }
+ nsXPTCVariant* GetParameterList() const { return mParameterList; }
+ PRUint32 GetParameterCount() const { return mParameterCount; }
+ PLEvent* GetPLEvent() const { return mEvent; }
+ nsresult GetResult() const { return mResult; }
+ nsProxyObject* GetProxyObject() const { return mOwner; }
+
+ PRBool GetCompleted();
+ void SetCompleted();
+ void PostCompleted();
+
+ void SetResult(nsresult rv) {mResult = rv; }
+
+ nsIEventQueue* GetCallersQueue();
+ void SetCallersQueue(nsIEventQueue* queue);
+
+private:
+
+ nsresult mResult; /* this is the return result of the called function */
+ nsXPTMethodInfo *mMethodInfo;
+ PRUint32 mMethodIndex; /* which method to be called? */
+ nsXPTCVariant *mParameterList; /* marshalled in parameter buffer */
+ PRUint32 mParameterCount; /* number of params */
+ PLEvent *mEvent; /* the current plevent */
+ PRInt32 mCompleted; /* is true when the method has been called. */
+
+ nsCOMPtr<nsIEventQueue> mCallersEventQ; /* this is the eventQ that we must post a message back to
+ when we are done invoking the method (only PROXY_SYNC).
+ */
+
+ nsRefPtr<nsProxyObject> mOwner; /* this is the strong referenced nsProxyObject */
+
+ void RefCountInInterfacePointers(PRBool addRef);
+ void CopyStrings(PRBool copy);
+
+};
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/proxy/public/nsProxyRelease.h b/src/libs/xpcom18a4/xpcom/proxy/public/nsProxyRelease.h
new file mode 100644
index 00000000..413a3d0e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/public/nsProxyRelease.h
@@ -0,0 +1,112 @@
+/* -*- Mode: C++; tab-width: 3; indent-tabs-mode: nil; c-basic-offset: 3 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 ***** */
+
+#ifndef nsProxyRelease_h__
+#define nsProxyRelease_h__
+
+#include "nsIEventQueueService.h"
+#include "pratom.h"
+#include "prmem.h"
+
+/**
+ * Ensures that the delete of a nsISupports object occurs on the target thread.
+ *
+ * @param target
+ * the target thread where the doomed object should be released.
+ * @param doomed
+ * the doomed object; the object to be released on the target thread.
+ * @param alwaysProxy
+ * normally, if NS_ProxyRelease is called on the target thread, then the
+ * doomed object will released directly. however, if this parameter is
+ * true, then a PLEvent will always be posted to the target thread and
+ * the release will happen when that PLEvent is handled.
+ */
+NS_COM nsresult NS_ProxyRelease
+ (nsIEventTarget *target, nsISupports *doomed, PRBool alwaysProxy=PR_FALSE);
+
+
+#define NS_IMPL_PROXY_RELEASE(_class) \
+NS_IMETHODIMP_(nsrefcnt) _class::Release(void) \
+{ \
+ NS_PRECONDITION(0 != mRefCnt, "dup release"); \
+ nsrefcnt count = PR_AtomicDecrement((PRInt32 *)&mRefCnt); \
+ NS_LOG_RELEASE(this, count, #_class); \
+ \
+ if (count == 0) \
+ { \
+ mRefCnt = 1; /* stabilize */ \
+ PRBool callDirectly = PR_TRUE; \
+ static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID); \
+ nsCOMPtr<nsIEventQueueService> eventQService \
+ = do_GetService(kEventQueueServiceCID); \
+ NS_ASSERTION(eventQService, "event queue service is unavailable"); \
+ \
+ nsCOMPtr<nsIEventQueue> eventQ; \
+ if (eventQService) { \
+ eventQService->GetThreadEventQueue(NS_UI_THREAD, getter_AddRefs(eventQ)); \
+ if (eventQ) \
+ eventQ->IsOnCurrentThread(&callDirectly); \
+ } \
+ \
+ if (callDirectly) \
+ { \
+ NS_RELEASE(this); \
+ return 0; \
+ } \
+ PLEvent *event = new PLEvent; \
+ if (event == nsnull) \
+ { \
+ NS_ASSERTION(0, "Could not create a plevent. Deleting on wrong thread!"); \
+ NS_DELETEXPCOM(this); \
+ return 0; \
+ } \
+ \
+ PL_InitEvent(event, \
+ NS_STATIC_CAST(nsISupports*, this), \
+ ReleaseDestructorEventHandler, \
+ ReleaseDestructorDestroyHandler); \
+ \
+ eventQ->PostEvent(event); \
+ return 0; \
+ } \
+ return count; \
+} \
+
+
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/.cvsignore b/src/libs/xpcom18a4/xpcom/proxy/src/.cvsignore
new file mode 100644
index 00000000..f3c7a7c5
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/.cvsignore
@@ -0,0 +1 @@
+Makefile
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/Makefile.in b/src/libs/xpcom18a4/xpcom/proxy/src/Makefile.in
new file mode 100644
index 00000000..3d46f60b
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/Makefile.in
@@ -0,0 +1,67 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+LIBRARY_NAME = xpcomproxy_s
+REQUIRES = string \
+ $(NULL)
+
+
+CPPSRCS = \
+ nsProxyEvent.cpp \
+ nsProxyEventClass.cpp \
+ nsProxyEventObject.cpp \
+ nsProxyObjectManager.cpp \
+ nsProxyRelease.cpp \
+ $(NULL)
+
+DEFINES += -D_IMPL_NS_COM -DEXPORT_XPTC_API -DEXPORT_XPTI_API
+
+# No shared lib; Force creation of static lib
+FORCE_STATIC_LIB = 1
+
+# Force use of PIC
+FORCE_USE_PIC = 1
+
+include $(topsrcdir)/config/rules.mk
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsIProxyCreateInstance.h b/src/libs/xpcom18a4/xpcom/proxy/src/nsIProxyCreateInstance.h
new file mode 100644
index 00000000..13755d74
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsIProxyCreateInstance.h
@@ -0,0 +1,39 @@
+/*
+ * DO NOT EDIT. THIS FILE IS GENERATED FROM nsIProxyCreateInstance.idl
+ */
+
+#ifndef __gen_nsIProxyCreateInstance_h__
+#define __gen_nsIProxyCreateInstance_h__
+
+#include "nsISupports.h" /* interface nsISupports */
+#include "nsrootidl.h" /* interface nsrootidl */
+
+#ifdef XPIDL_JS_STUBS
+#include "jsapi.h"
+#endif
+
+/* starting interface: nsIProxyCreateInstance */
+
+/* {948c2080-0398-11d3-915e-0000863011c4} */
+#define NS_IPROXYCREATEINSTANCE_IID_STR "948c2080-0398-11d3-915e-0000863011c4"
+#define NS_IPROXYCREATEINSTANCE_IID \
+ {0x948c2080, 0x0398, 0x11d3, \
+ { 0x91, 0x5e, 0x00, 0x00, 0x86, 0x30, 0x11, 0xc4 }}
+
+class nsIProxyCreateInstance : public nsISupports {
+ public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_IPROXYCREATEINSTANCE_IID)
+
+ /* void CreateInstanceByIID (in nsIIDRef cid, in nsISupports aOuter, in nsIIDRef iid, out voidStar result); */
+ NS_IMETHOD CreateInstanceByIID(const nsIID & cid, nsISupports *aOuter, const nsIID & iid, void * *result) = 0;
+
+ /* void CreateInstanceByContractID (in string aContractID, in nsISupports aOuter, in nsIIDRef iid, out voidStar result); */
+ NS_IMETHOD CreateInstanceByContractID(const char *aContractID, nsISupports *aOuter, const nsIID & iid, void * *result) = 0;
+
+#ifdef XPIDL_JS_STUBS
+ static NS_EXPORT_(JSObject *) InitJSClass(JSContext *cx);
+ static NS_EXPORT_(JSObject *) GetJSObject(JSContext *cx, nsIProxyCreateInstance *priv);
+#endif
+};
+
+#endif /* __gen_nsIProxyCreateInstance_h__ */
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEvent.cpp b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEvent.cpp
new file mode 100644
index 00000000..561c2fdb
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEvent.cpp
@@ -0,0 +1,613 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ *
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 Original Code has been modified by IBM Corporation.
+ * Modifications made by IBM described herein are
+ * Copyright (c) International Business Machines
+ * Corporation, 2000
+ *
+ * Modifications to Mozilla code or documentation
+ * identified per MPL Section 3.3
+ *
+ * Date Modified by Description of modification
+ * 04/20/2000 IBM Corp. Added PR_CALLBACK for Optlink use in OS2
+ */
+
+#include "nsProxyEvent.h"
+#include "nsProxyEventPrivate.h"
+#include "nsIProxyObjectManager.h"
+#include "nsCRT.h"
+
+#include "pratom.h"
+#include "prmem.h"
+#include "xptcall.h"
+
+#include "nsIComponentManager.h"
+#include "nsComponentManagerObsolete.h"
+#include "nsIServiceManager.h"
+#include "nsMemory.h"
+#include "nsIEventQueueService.h"
+#include "nsIThread.h"
+
+#include "nsIAtom.h" //hack! Need a way to define a component as threadsafe (ie. sta).
+
+/**
+ * Map the nsAUTF8String, nsUTF8String classes to the nsACString and
+ * nsCString classes respectively for now. These defines need to be removed
+ * once Jag lands his nsUTF8String implementation.
+ */
+#define nsAUTF8String nsACString
+#define nsUTF8String nsCString
+
+static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+
+static void* PR_CALLBACK EventHandler(PLEvent *self);
+static void PR_CALLBACK DestroyHandler(PLEvent *self);
+static void* PR_CALLBACK CompletedEventHandler(PLEvent *self);
+static void PR_CALLBACK CompletedDestroyHandler(PLEvent *self) ;
+static void* PR_CALLBACK ProxyDestructorEventHandler(PLEvent *self);
+static void PR_CALLBACK ProxyDestructorDestroyHandler(PLEvent *self) ;
+
+nsProxyObjectCallInfo::nsProxyObjectCallInfo( nsProxyObject* owner,
+ nsXPTMethodInfo *methodInfo,
+ PRUint32 methodIndex,
+ nsXPTCVariant* parameterList,
+ PRUint32 parameterCount,
+ PLEvent *event)
+{
+ NS_ASSERTION(owner, "No nsProxyObject!");
+ NS_ASSERTION(methodInfo, "No nsXPTMethodInfo!");
+ NS_ASSERTION(event, "No PLEvent!");
+
+ mCompleted = 0;
+ mMethodIndex = methodIndex;
+ mParameterList = parameterList;
+ mParameterCount = parameterCount;
+ mEvent = event;
+ mMethodInfo = methodInfo;
+ mCallersEventQ = nsnull;
+
+ mOwner = owner;
+
+ RefCountInInterfacePointers(PR_TRUE);
+ if (mOwner->GetProxyType() & PROXY_ASYNC)
+ CopyStrings(PR_TRUE);
+}
+
+
+nsProxyObjectCallInfo::~nsProxyObjectCallInfo()
+{
+ RefCountInInterfacePointers(PR_FALSE);
+ if (mOwner->GetProxyType() & PROXY_ASYNC)
+ CopyStrings(PR_FALSE);
+
+ mOwner = nsnull;
+
+ PR_FREEIF(mEvent);
+
+ if (mParameterList)
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ nsMemory::Free((void*) mParameterList);
+#else
+ free( (void*) mParameterList);
+#endif
+}
+
+void
+nsProxyObjectCallInfo::RefCountInInterfacePointers(PRBool addRef)
+{
+ for (PRUint32 i = 0; i < mParameterCount; i++)
+ {
+ nsXPTParamInfo paramInfo = mMethodInfo->GetParam(i);
+
+ if (paramInfo.GetType().IsInterfacePointer() )
+ {
+ nsISupports* anInterface = nsnull;
+
+ if (paramInfo.IsIn())
+ {
+ anInterface = ((nsISupports*)mParameterList[i].val.p);
+
+ if (anInterface)
+ {
+ if(addRef)
+ anInterface->AddRef();
+ else
+ anInterface->Release();
+
+ }
+ }
+ }
+ }
+}
+
+void
+nsProxyObjectCallInfo::CopyStrings(PRBool copy)
+{
+ for (PRUint32 i = 0; i < mParameterCount; i++)
+ {
+ const nsXPTParamInfo paramInfo = mMethodInfo->GetParam(i);
+
+ if(paramInfo.IsIn())
+ {
+ const nsXPTType& type = paramInfo.GetType();
+ uint8 type_tag = type.TagPart();
+ void *ptr = mParameterList[i].val.p;
+
+ if (!ptr)
+ continue;
+
+ if (copy)
+ {
+ switch (type_tag)
+ {
+ case nsXPTType::T_CHAR_STR:
+ mParameterList[i].val.p =
+ PL_strdup((const char *)ptr);
+ break;
+ case nsXPTType::T_WCHAR_STR:
+ mParameterList[i].val.p =
+ nsCRT::strdup((const PRUnichar *)ptr);
+ break;
+ case nsXPTType::T_DOMSTRING:
+ case nsXPTType::T_ASTRING:
+ mParameterList[i].val.p =
+ new nsString(*((nsAString*) ptr));
+ break;
+ case nsXPTType::T_CSTRING:
+ mParameterList[i].val.p =
+ new nsCString(*((nsACString*) ptr));
+ break;
+ case nsXPTType::T_UTF8STRING:
+ mParameterList[i].val.p =
+ new nsUTF8String(*((nsAUTF8String*) ptr));
+ break;
+ default:
+ // Other types are ignored
+ break;
+ }
+ }
+ else
+ {
+ switch (type_tag)
+ {
+ case nsXPTType::T_CHAR_STR:
+ case nsXPTType::T_WCHAR_STR:
+ PL_strfree((char*) ptr);
+ break;
+ case nsXPTType::T_DOMSTRING:
+ case nsXPTType::T_ASTRING:
+ delete (nsString*) ptr;
+ break;
+ case nsXPTType::T_CSTRING:
+ delete (nsCString*) ptr;
+ break;
+ case nsXPTType::T_UTF8STRING:
+ delete (nsUTF8String*) ptr;
+ break;
+ default:
+ // Other types are ignored
+ break;
+ }
+ }
+ }
+ }
+}
+
+PRBool
+nsProxyObjectCallInfo::GetCompleted()
+{
+ return (PRBool)mCompleted;
+}
+
+void
+nsProxyObjectCallInfo::SetCompleted()
+{
+ PR_AtomicSet(&mCompleted, 1);
+}
+
+void
+nsProxyObjectCallInfo::PostCompleted()
+{
+ if (mCallersEventQ)
+ {
+ PLEvent *event = PR_NEW(PLEvent);
+
+ PL_InitEvent(event,
+ this,
+ CompletedEventHandler,
+ CompletedDestroyHandler);
+
+ mCallersEventQ->PostSynchronousEvent(event, nsnull);
+ PR_FREEIF(event);
+ }
+ else
+ {
+ // caller does not have an eventQ? This is an error!
+ SetCompleted();
+ }
+}
+
+nsIEventQueue*
+nsProxyObjectCallInfo::GetCallersQueue()
+{
+ return mCallersEventQ;
+}
+void
+nsProxyObjectCallInfo::SetCallersQueue(nsIEventQueue* queue)
+{
+ mCallersEventQ = queue;
+}
+
+
+nsProxyObject::nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, nsISupports *realObject)
+{
+ mEventQService = do_GetService(kEventQueueServiceCID);
+
+ mRealObject = realObject;
+ mDestQueue = do_QueryInterface(destQueue);
+ mProxyType = proxyType;
+}
+
+
+nsProxyObject::nsProxyObject(nsIEventQueue *destQueue, PRInt32 proxyType, const nsCID &aClass, nsISupports *aDelegate, const nsIID &aIID)
+{
+ mEventQService = do_GetService(kEventQueueServiceCID);
+
+ nsComponentManager::CreateInstance(aClass,
+ aDelegate,
+ aIID,
+ getter_AddRefs(mRealObject));
+
+ mDestQueue = do_QueryInterface(destQueue);
+ mProxyType = proxyType;
+}
+
+nsProxyObject::~nsProxyObject()
+{
+ // I am worried about order of destruction here.
+ // do not remove assignments.
+
+ mRealObject = 0;
+ mDestQueue = 0;
+}
+
+
+void
+nsProxyObject::AddRef()
+{
+ PR_AtomicIncrement((PRInt32 *)&mRefCnt);
+ NS_LOG_ADDREF(this, mRefCnt, "nsProxyObject", sizeof(*this));
+}
+
+void
+nsProxyObject::Release(void)
+{
+ NS_PRECONDITION(0 != mRefCnt, "dup release");
+
+ nsrefcnt count = PR_AtomicDecrement((PRInt32 *)&mRefCnt);
+ NS_LOG_RELEASE(this, count, "nsProxyObject");
+
+ if (count == 0)
+ {
+ mRefCnt = 1; /* stabilize */
+
+ PRBool callDirectly;
+ mDestQueue->IsOnCurrentThread(&callDirectly);
+
+ if (callDirectly)
+ {
+ delete this;
+ return;
+ }
+
+ // need to do something special here so that
+ // the real object will always be deleted on
+ // the correct thread..
+
+ PLEvent *event = PR_NEW(PLEvent);
+ if (event == nsnull)
+ {
+ NS_ASSERTION(0, "Could not create a plevent. Leaking nsProxyObject!");
+ return; // if this happens we are going to leak.
+ }
+
+ PL_InitEvent(event,
+ this,
+ ProxyDestructorEventHandler,
+ ProxyDestructorDestroyHandler);
+
+ mDestQueue->PostEvent(event);
+ }
+}
+
+
+nsresult
+nsProxyObject::PostAndWait(nsProxyObjectCallInfo *proxyInfo)
+{
+ if (proxyInfo == nsnull || mEventQService == nsnull)
+ return NS_ERROR_NULL_POINTER;
+
+ PRBool eventLoopCreated = PR_FALSE;
+ nsresult rv;
+
+ nsCOMPtr<nsIEventQueue> eventQ;
+ rv = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(eventQ));
+ if (NS_FAILED(rv))
+ {
+ rv = mEventQService->CreateMonitoredThreadEventQueue();
+ eventLoopCreated = PR_TRUE;
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = mEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(eventQ));
+ }
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ proxyInfo->SetCallersQueue(eventQ);
+
+ PLEvent* event = proxyInfo->GetPLEvent();
+ if (!event)
+ return NS_ERROR_NULL_POINTER;
+
+ mDestQueue->PostEvent(event);
+
+ while (! proxyInfo->GetCompleted())
+ {
+ PLEvent *nextEvent;
+ rv = eventQ->WaitForEvent(&nextEvent);
+ if (NS_FAILED(rv)) break;
+
+ eventQ->HandleEvent(nextEvent);
+ }
+
+ if (eventLoopCreated)
+ {
+ mEventQService->DestroyThreadEventQueue();
+ eventQ = 0;
+ }
+
+ return rv;
+}
+
+
+nsresult
+nsProxyObject::convertMiniVariantToVariant(nsXPTMethodInfo *methodInfo,
+ nsXPTCMiniVariant * params,
+ nsXPTCVariant **fullParam,
+ uint8 *outParamCount)
+{
+ uint8 paramCount = methodInfo->GetParamCount();
+ *outParamCount = paramCount;
+ *fullParam = nsnull;
+
+ if (!paramCount) return NS_OK;
+
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ *fullParam = (nsXPTCVariant*)nsMemory::Alloc(sizeof(nsXPTCVariant) * paramCount);
+#else
+ *fullParam = (nsXPTCVariant*)malloc(sizeof(nsXPTCVariant) * paramCount);
+#endif
+
+ if (*fullParam == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ for (int i = 0; i < paramCount; i++)
+ {
+ const nsXPTParamInfo& paramInfo = methodInfo->GetParam(i);
+ if ((mProxyType & PROXY_ASYNC) && paramInfo.IsDipper())
+ {
+ NS_WARNING("Async proxying of out parameters is not supported");
+ return NS_ERROR_PROXY_INVALID_OUT_PARAMETER;
+ }
+ uint8 flags = paramInfo.IsOut() ? nsXPTCVariant::PTR_IS_DATA : 0;
+ (*fullParam)[i].Init(params[i], paramInfo.GetType(), flags);
+ }
+
+ return NS_OK;
+}
+
+nsresult
+nsProxyObject::Post( PRUint32 methodIndex,
+ nsXPTMethodInfo *methodInfo,
+ nsXPTCMiniVariant * params,
+ nsIInterfaceInfo *interfaceInfo)
+{
+ nsresult rv = NS_OK;
+
+ if (! mDestQueue || ! mRealObject)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ if (methodInfo->IsNotXPCOM())
+ return NS_ERROR_PROXY_INVALID_IN_PARAMETER;
+
+ nsXPTCVariant *fullParam;
+ uint8 paramCount;
+ rv = convertMiniVariantToVariant(methodInfo, params, &fullParam, &paramCount);
+
+ if (NS_FAILED(rv))
+ return rv;
+
+ PRBool callDirectly;
+
+ // see if we should call into the method directly. Either it is a QI function call
+ // (methodIndex == 0), or it is a sync proxy and this code is running on the same thread
+ // as the destination event queue.
+ if ( (methodIndex == 0) ||
+ (mProxyType & PROXY_SYNC &&
+ NS_SUCCEEDED(mDestQueue->IsOnCurrentThread(&callDirectly)) &&
+ callDirectly))
+ {
+
+ // invoke the magic of xptc...
+ nsresult rv = XPTC_InvokeByIndex( mRealObject,
+ methodIndex,
+ paramCount,
+ fullParam);
+
+ if (fullParam)
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ nsMemory::Free(fullParam);
+#else
+ free(fullParam);
+#endif
+ return rv;
+ }
+
+ PLEvent *event = PR_NEW(PLEvent);
+
+ if (event == nsnull) {
+ if (fullParam)
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ nsMemory::Free(fullParam);
+#else
+ free(fullParam);
+#endif
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ nsProxyObjectCallInfo *proxyInfo = new nsProxyObjectCallInfo(this,
+ methodInfo,
+ methodIndex,
+ fullParam, // will be deleted by ~()
+ paramCount,
+ event); // will be deleted by ~()
+
+ if (proxyInfo == nsnull) {
+ PR_DELETE(event);
+ if (fullParam)
+#ifdef VBOX_USE_IPRT_IN_XPCOM
+ nsMemory::Free(fullParam);
+#else
+ free(fullParam);
+#endif
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ PL_InitEvent(event,
+ proxyInfo,
+ EventHandler,
+ DestroyHandler);
+
+ if (mProxyType & PROXY_SYNC)
+ {
+ rv = PostAndWait(proxyInfo);
+
+ if (NS_SUCCEEDED(rv))
+ rv = proxyInfo->GetResult();
+ delete proxyInfo;
+ return rv;
+ }
+
+ if (mProxyType & PROXY_ASYNC)
+ {
+ mDestQueue->PostEvent(event);
+ return NS_OK;
+ }
+ return NS_ERROR_UNEXPECTED;
+}
+
+
+
+static void DestroyHandler(PLEvent *self)
+{
+ nsProxyObjectCallInfo* owner = (nsProxyObjectCallInfo*)PL_GetEventOwner(self);
+ nsProxyObject* proxyObject = owner->GetProxyObject();
+
+ if (proxyObject == nsnull)
+ return;
+
+ if (proxyObject->GetProxyType() & PROXY_ASYNC)
+ {
+ delete owner;
+ }
+ else
+ {
+ owner->PostCompleted();
+ }
+
+}
+
+static void* EventHandler(PLEvent *self)
+{
+ nsProxyObjectCallInfo *info = (nsProxyObjectCallInfo*)PL_GetEventOwner(self);
+ NS_ASSERTION(info, "No nsProxyObjectCallInfo!");
+
+ nsProxyObject *proxyObject = info->GetProxyObject();
+
+ if (proxyObject)
+ {
+ // invoke the magic of xptc...
+ nsresult rv = XPTC_InvokeByIndex( proxyObject->GetRealObject(),
+ info->GetMethodIndex(),
+ info->GetParameterCount(),
+ info->GetParameterList());
+ info->SetResult(rv);
+ }
+ else
+ {
+ info->SetResult(NS_ERROR_OUT_OF_MEMORY);
+ }
+ return NULL;
+}
+
+static void CompletedDestroyHandler(PLEvent *self)
+{
+}
+
+static void* CompletedEventHandler(PLEvent *self)
+{
+ nsProxyObjectCallInfo* owner = (nsProxyObjectCallInfo*)PL_GetEventOwner(self);
+ owner->SetCompleted();
+ return nsnull;
+}
+
+static void* ProxyDestructorEventHandler(PLEvent *self)
+{
+ nsProxyObject* owner = (nsProxyObject*) PL_GetEventOwner(self);
+ NS_DELETEXPCOM(owner);
+ return nsnull;
+}
+
+static void ProxyDestructorDestroyHandler(PLEvent *self)
+{
+ PR_DELETE(self);
+}
+
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventClass.cpp b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventClass.cpp
new file mode 100644
index 00000000..8e221afa
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventClass.cpp
@@ -0,0 +1,367 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 ***** */
+
+
+#include "nsProxyEvent.h"
+#include "nsIProxyObjectManager.h"
+#include "nsProxyEventPrivate.h"
+
+#include "nsIComponentManager.h"
+#include "nsIServiceManager.h"
+#include "nsCOMPtr.h"
+
+#include "nsMemory.h"
+#include "nsHashtable.h"
+
+#include "nsAutoLock.h"
+#include "nsIInterfaceInfoManager.h"
+#include "xptcall.h"
+
+// LIFETIME_CACHE will cache class for the entire cyle of the application.
+#define LIFETIME_CACHE
+
+static uint32 zero_methods_descriptor;
+
+
+/* ssc@netscape.com wishes he could get rid of this instance of
+ * |NS_DEFINE_IID|, but |ProxyEventClassIdentity| is not visible from
+ * here.
+ */
+static NS_DEFINE_IID(kProxyObject_Identity_Class_IID, NS_PROXYEVENT_IDENTITY_CLASS_IID);
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+// nsProxyEventClass
+//////////////////////////////////////////////////////////////////////////////////////////////////
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsProxyEventClass, nsProxyEventClass)
+
+// static
+nsProxyEventClass*
+nsProxyEventClass::GetNewOrUsedClass(REFNSIID aIID)
+{
+ /* find in our hash table */
+
+ nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
+ if (manager == nsnull) return nsnull;
+
+ // dont need to lock the map, because this is only called
+ // by nsProxyEventClass::GetNewOrUsed which locks it for us.
+
+ nsHashtable *iidToClassMap = manager->GetIIDToProxyClassMap();
+
+ if (iidToClassMap == nsnull)
+ {
+ return nsnull;
+ }
+
+ nsProxyEventClass* clazz = nsnull;
+ nsIDKey key(aIID);
+
+#ifdef PROXYEVENTCLASS_DEBUG
+ char* iidStr = aIID.ToString();
+ printf("GetNewOrUsedClass %s\n", iidStr);
+ nsCRT::free(iidStr);
+#endif
+
+ clazz = (nsProxyEventClass*) iidToClassMap->Get(&key);
+ if(clazz)
+ {
+ NS_ADDREF(clazz);
+#ifdef PROXYEVENTCLASS_DEBUG
+ char* iidStr = aIID.ToString();
+ printf("GetNewOrUsedClass %s hit\n", iidStr);
+ nsCRT::free(iidStr);
+#endif
+ }
+ else
+ {
+ nsCOMPtr<nsIInterfaceInfoManager> iimgr = getter_AddRefs(XPTI_GetInterfaceInfoManager());
+ if(iimgr)
+ {
+ nsCOMPtr<nsIInterfaceInfo> info;
+ if(NS_SUCCEEDED(iimgr->GetInfoForIID(&aIID, getter_AddRefs(info))))
+ {
+ /*
+ Check to see if isISupportsDescendent
+ */
+ nsCOMPtr<nsIInterfaceInfo> oldest = info;
+ nsCOMPtr<nsIInterfaceInfo> parent;
+
+ while(NS_SUCCEEDED(oldest->GetParent(getter_AddRefs(parent)))&&
+ parent)
+ {
+ oldest = parent;
+ }
+
+ PRBool isISupportsDescendent = PR_FALSE;
+ nsID* iid;
+ if(NS_SUCCEEDED(oldest->GetInterfaceIID(&iid)))
+ {
+ isISupportsDescendent = iid->Equals(NS_GET_IID(nsISupports));
+ nsMemory::Free(iid);
+ }
+
+ NS_ASSERTION(isISupportsDescendent, "!isISupportsDescendent");
+
+ if (isISupportsDescendent)
+ {
+ clazz = new nsProxyEventClass(aIID, info);
+ if(!clazz->mDescriptors)
+ NS_RELEASE(clazz); // sets clazz to NULL
+ }
+ }
+ }
+ }
+ return clazz;
+}
+
+nsProxyEventClass::nsProxyEventClass()
+{
+ NS_WARNING("This constructor should never be called");
+}
+
+nsProxyEventClass::nsProxyEventClass(REFNSIID aIID, nsIInterfaceInfo* aInfo)
+: mIID(aIID),
+ mDescriptors(NULL)
+{
+ NS_ADDREF_THIS();
+
+ mInfo = aInfo;
+
+ /* add use to the used classes */
+ nsIDKey key(aIID);
+
+ nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
+ if (manager == nsnull) return;
+ // dont need to lock the map, because this is only called
+ // by GetNewOrUsed which locks it for us.
+
+ nsHashtable *iidToClassMap = manager->GetIIDToProxyClassMap();
+
+ if (iidToClassMap != nsnull)
+ {
+ iidToClassMap->Put(&key, this);
+#ifdef LIFETIME_CACHE
+ // extra addref to hold it in the cache
+ NS_ADDREF_THIS();
+#endif
+#ifdef PROXYEVENTCLASS_DEBUG
+ char* iidStr = aIID.ToString();
+ printf("GetNewOrUsedClass %s put\n", iidStr);
+ nsCRT::free(iidStr);
+#endif
+ }
+
+ uint16 methodCount;
+ if(NS_SUCCEEDED(mInfo->GetMethodCount(&methodCount)))
+ {
+ if(methodCount)
+ {
+ int wordCount = (methodCount/32)+1;
+ if(NULL != (mDescriptors = new uint32[wordCount]))
+ {
+ memset(mDescriptors, 0, wordCount * sizeof(uint32));
+ }
+ }
+ else
+ {
+ mDescriptors = &zero_methods_descriptor;
+ }
+ }
+}
+
+nsProxyEventClass::~nsProxyEventClass()
+{
+ if(mDescriptors && mDescriptors != &zero_methods_descriptor)
+ delete [] mDescriptors;
+
+ if (nsProxyObjectManager::IsManagerShutdown())
+ return;
+
+#ifndef LIFETIME_CACHE
+ nsIDKey key(mIID);
+
+ nsCOMPtr<nsProxyObjectManager> manager = getter_AddRefs(nsProxyObjectManager::GetInstance());
+ if (manager == nsnull) return;
+ nsHashtable *iidToClassMap = manager->GetIIDToProxyClassMap();
+
+ if (iidToClassMap != nsnull)
+ {
+ iidToClassMap->Remove(&key);
+#ifdef PROXYEVENTCLASS_DEBUG
+ char* iidStr = mIID.ToString();
+ printf("GetNewOrUsedClass %s remove\n", iidStr);
+ nsCRT::free(iidStr);
+#endif
+ }
+#endif
+}
+
+nsresult
+nsProxyEventClass::CallQueryInterfaceOnProxy(nsProxyEventObject* self, REFNSIID aIID, nsProxyEventObject** aInstancePtr)
+{
+ NS_PRECONDITION(aInstancePtr, "Requires non-null result");
+
+ nsresult rv;
+
+ *aInstancePtr = nsnull; // in case of error.
+
+
+ // The functions we will call: QueryInterface(REFNSIID aIID, void** aInstancePtr)
+
+ nsXPTCMiniVariant var[2];
+
+ var[0].val.p = (void*)&aIID;
+ var[1].val.p = (void*)aInstancePtr;
+
+ nsCOMPtr<nsIInterfaceInfo> interfaceInfo;
+ const nsXPTMethodInfo *mi;
+
+ nsCOMPtr<nsIInterfaceInfoManager> iim = getter_AddRefs(XPTI_GetInterfaceInfoManager());
+
+ if (!iim) return NS_NOINTERFACE;
+ iim->GetInfoForName("nsISupports", getter_AddRefs(interfaceInfo));
+ interfaceInfo->GetMethodInfo(0, &mi); // 0 is QueryInterface
+
+ rv = self->CallMethod(0, mi, var);
+
+ if (NS_SUCCEEDED(rv))
+ {
+ nsISupports *aIdentificationObject;
+
+ rv = (*aInstancePtr)->QueryInterface(kProxyObject_Identity_Class_IID, (void**)&aIdentificationObject);
+
+ if (NS_FAILED(rv))
+ {
+ // okay, aInstancePtr was not a proxy. Lets create one.
+ nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
+ if (manager == nsnull)
+ {
+ NS_IF_RELEASE((*aInstancePtr));
+ return NS_ERROR_FAILURE;
+ }
+
+ rv = manager->GetProxyForObject(self->GetQueue(),
+ aIID,
+ self->GetRealObject(),
+ self->GetProxyType(),
+ (void**) &aIdentificationObject);
+ }
+
+ NS_IF_RELEASE((*aInstancePtr));
+ (*aInstancePtr) = NS_STATIC_CAST(nsProxyEventObject*, aIdentificationObject);
+ }
+ return rv;
+}
+
+
+/***************************************************************************/
+// This 'ProxyEventClassIdentity' class and singleton allow us to figure out if
+// any given nsISupports* is implemented by a nsProxy object. This is done
+// using a QueryInterface call on the interface pointer with our ID. If
+// that call returns NS_OK and the pointer is to a nsProxyEventObject. It must
+// be released when done.
+
+// NS_PROXYEVENT_IDENTITY_CLASS_IID defined in nsProxyEventPrivate.h
+class ProxyEventClassIdentity
+{
+ // no instance methods...
+public:
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_PROXYEVENT_IDENTITY_CLASS_IID)
+
+ static void* GetSingleton()
+ {
+ static ProxyEventClassIdentity* singleton = NULL;
+ if(!singleton)
+ singleton = new ProxyEventClassIdentity();
+ return (void*) singleton;
+ }
+};
+
+NS_IMETHODIMP
+nsProxyEventClass::DelegatedQueryInterface(nsProxyEventObject* self,
+ REFNSIID aIID,
+ void** aInstancePtr)
+{
+
+ if(aIID.Equals(NS_GET_IID(ProxyEventClassIdentity)))
+ {
+ *aInstancePtr = NS_STATIC_CAST(void*, self);
+ NS_ADDREF(self);
+ return NS_OK;
+ }
+
+ nsProxyEventObject* sibling;
+ {
+ nsProxyObjectManager* manager = nsProxyObjectManager::GetInstance();
+ nsAutoMonitor mon(manager->GetMonitor());
+
+ // This includes checking for nsISupports and the iid of self.
+ // And it also checks for other wrappers that have been constructed
+ // for this object.
+ if(nsnull != (sibling = self->LockedFind(aIID)))
+ {
+ NS_ADDREF(sibling);
+ *aInstancePtr = (void*) sibling;
+ return NS_OK;
+ }
+
+ // check if asking for an interface that we inherit from
+ nsCOMPtr<nsIInterfaceInfo> current = GetInterfaceInfo();
+ nsCOMPtr<nsIInterfaceInfo> parent;
+
+ while(NS_SUCCEEDED(current->GetParent(getter_AddRefs(parent))) && parent)
+ {
+ current = parent;
+
+ nsIID* iid;
+ if(NS_SUCCEEDED(current->GetInterfaceIID(&iid)) && iid)
+ {
+ PRBool found = aIID.Equals(*iid);
+ nsMemory::Free(iid);
+ if(found)
+ {
+ *aInstancePtr = (void*) self;
+ NS_ADDREF(self);
+ return NS_OK;
+ }
+ }
+ }
+ }
+
+ return CallQueryInterfaceOnProxy(self, aIID, (nsProxyEventObject**)aInstancePtr);
+}
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventObject.cpp b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventObject.cpp
new file mode 100644
index 00000000..d529fc05
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventObject.cpp
@@ -0,0 +1,555 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 ***** */
+
+#include "prprf.h"
+#include "prmem.h"
+
+#include "nscore.h"
+#include "nsProxyEvent.h"
+#include "nsIProxyObjectManager.h"
+#include "nsProxyEventPrivate.h"
+
+#include "nsHashtable.h"
+
+#include "nsIInterfaceInfoManager.h"
+#include "xptcall.h"
+
+#include "nsAutoLock.h"
+
+static NS_DEFINE_IID(kProxyObject_Identity_Class_IID, NS_PROXYEVENT_IDENTITY_CLASS_IID);
+
+
+////////////////////////////////////////////////////////////////////////////////
+
+class nsProxyEventKey : public nsHashKey
+{
+public:
+ nsProxyEventKey(void* rootObjectKey, void* destQueueKey, PRInt32 proxyType)
+ : mRootObjectKey(rootObjectKey), mDestQueueKey(destQueueKey), mProxyType(proxyType) {
+ }
+
+ PRUint32 HashCode(void) const {
+ return NS_PTR_TO_INT32(mRootObjectKey) ^
+ NS_PTR_TO_INT32(mDestQueueKey) ^ mProxyType;
+ }
+
+ PRBool Equals(const nsHashKey *aKey) const {
+ const nsProxyEventKey* other = (const nsProxyEventKey*)aKey;
+ return mRootObjectKey == other->mRootObjectKey
+ && mDestQueueKey == other->mDestQueueKey
+ && mProxyType == other->mProxyType;
+ }
+
+ nsHashKey *Clone() const {
+ return new nsProxyEventKey(mRootObjectKey, mDestQueueKey, mProxyType);
+ }
+
+protected:
+ void* mRootObjectKey;
+ void* mDestQueueKey;
+ PRInt32 mProxyType;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+#ifdef DEBUG_xpcom_proxy
+static PRMonitor* mon = nsnull;
+static PRUint32 totalProxyObjects = 0;
+static PRUint32 outstandingProxyObjects = 0;
+
+void
+nsProxyEventObject::DebugDump(const char * message, PRUint32 hashKey)
+{
+
+ if (mon == nsnull)
+ {
+ mon = PR_NewMonitor();
+ }
+
+ PR_EnterMonitor(mon);
+
+ if (message)
+ {
+ printf("\n-=-=-=-=-=-=-=-=-=-=-=-=-\n");
+ printf("%s\n", message);
+
+ if(strcmp(message, "Create") == 0)
+ {
+ totalProxyObjects++;
+ outstandingProxyObjects++;
+ }
+ else if(strcmp(message, "Delete") == 0)
+ {
+ outstandingProxyObjects--;
+ }
+ }
+ printf("nsProxyEventObject @ %x with mRefCnt = %d\n", this, mRefCnt);
+
+ PRBool isRoot = mRoot == nsnull;
+ printf("%s wrapper around @ %x\n", isRoot ? "ROOT":"non-root\n", GetRealObject());
+
+ nsCOMPtr<nsISupports> rootObject = do_QueryInterface(mProxyObject->mRealObject);
+ nsCOMPtr<nsISupports> rootQueue = do_QueryInterface(mProxyObject->mDestQueue);
+ nsProxyEventKey key(rootObject, rootQueue, mProxyObject->mProxyType);
+ printf("Hashkey: %d\n", key.HashCode());
+
+ char* name;
+ GetClass()->GetInterfaceInfo()->GetName(&name);
+ printf("interface name is %s\n", name);
+ if(name)
+ nsMemory::Free(name);
+ char * iid = GetClass()->GetProxiedIID().ToString();
+ printf("IID number is %s\n", iid);
+ delete iid;
+ printf("nsProxyEventClass @ %x\n", mClass);
+
+ if(mNext)
+ {
+ if(isRoot)
+ {
+ printf("Additional wrappers for this object...\n");
+ }
+ mNext->DebugDump(nsnull, 0);
+ }
+
+ printf("[proxyobjects] %d total used in system, %d outstading\n", totalProxyObjects, outstandingProxyObjects);
+
+ if (message)
+ printf("-=-=-=-=-=-=-=-=-=-=-=-=-\n");
+
+ PR_ExitMonitor(mon);
+}
+#endif
+
+
+
+//////////////////////////////////////////////////////////////////////////////////////////////////
+//
+// nsProxyEventObject
+//
+//////////////////////////////////////////////////////////////////////////////////////////////////
+nsProxyEventObject*
+nsProxyEventObject::GetNewOrUsedProxy(nsIEventQueue *destQueue,
+ PRInt32 proxyType,
+ nsISupports *aObj,
+ REFNSIID aIID)
+{
+ nsresult rv;
+
+ if (!aObj)
+ return nsnull;
+
+ nsISupports* rawObject = aObj;
+
+ //
+ // make sure that the object pass in is not a proxy...
+ // if the object *is* a proxy, then be nice and build the proxy
+ // for the real object...
+ //
+ nsCOMPtr<nsProxyEventObject> identificationObject;
+
+ rv = rawObject->QueryInterface(kProxyObject_Identity_Class_IID,
+ getter_AddRefs(identificationObject));
+ if (NS_SUCCEEDED(rv)) {
+ //
+ // ATTENTION!!!!
+ //
+ // If you are hitting any of the assertions in this block of code,
+ // please contact dougt@netscape.com.
+ //
+
+ // if you hit this assertion, you might want to check out how
+ // you are using proxies. You shouldn't need to be creating
+ // a proxy from a proxy. -- dougt@netscape.com
+ NS_ASSERTION(0, "Someone is building a proxy from a proxy");
+
+ NS_ASSERTION(identificationObject, "where did my identification object go!");
+ if (!identificationObject) {
+ return nsnull;
+ }
+
+ // someone is asking us to create a proxy for a proxy. Lets get
+ // the real object and build aproxy for that!
+ rawObject = identificationObject->GetRealObject();
+
+ NS_ASSERTION(rawObject, "where did my real object go!");
+ if (!rawObject) {
+ return nsnull;
+ }
+ }
+
+ //
+ // Get the root nsISupports of the |real| object.
+ //
+ nsCOMPtr<nsISupports> rootObject;
+
+ rootObject = do_QueryInterface(rawObject, &rv);
+ if (NS_FAILED(rv) || !rootObject) {
+ NS_ASSERTION(NS_FAILED(rv), "where did my root object go!");
+ return nsnull;
+ }
+
+ // Get the root nsISupports of the event queue... This is used later,
+ // as part of the hashtable key...
+ nsCOMPtr<nsISupports> destQRoot = do_QueryInterface(destQueue, &rv);
+ if (NS_FAILED(rv) || !destQRoot) {
+ return nsnull;
+ }
+
+ //
+ // Enter the proxy object creation lock.
+ //
+ // This lock protects thev linked list which chains proxies together
+ // (ie. mRoot and mNext) and ensures that there is no hashtable contention
+ // between the time that a proxy is looked up (and not found) in the
+ // hashtable and then added...
+ //
+ nsProxyObjectManager *manager = nsProxyObjectManager::GetInstance();
+ if (!manager) {
+ return nsnull;
+ }
+
+ nsAutoMonitor mon(manager->GetMonitor());
+
+ // Get the hash table containing root proxy objects...
+ nsHashtable *realToProxyMap = manager->GetRealObjectToProxyObjectMap();
+ if (!realToProxyMap) {
+ return nsnull;
+ }
+
+ // Now, lookup the root nsISupports of the raw object in the hashtable
+ // The key consists of 3 pieces of information:
+ // - root nsISupports of the raw object
+ // - event queue of the current thread
+ // - type of proxy being constructed...
+ //
+ nsProxyEventKey rootkey(rootObject.get(), destQRoot.get(), proxyType);
+
+ nsCOMPtr<nsProxyEventObject> rootProxy;
+ nsCOMPtr<nsProxyEventObject> proxy;
+ nsProxyEventObject* peo;
+
+ // find in our hash table
+ rootProxy = (nsProxyEventObject*) realToProxyMap->Get(&rootkey);
+
+ if(rootProxy) {
+ //
+ // At least one proxy has already been created for this raw object...
+ //
+ // Look for the specific interface proxy in the list off of
+ // the root proxy...
+ //
+ peo = rootProxy->LockedFind(aIID);
+
+ if(peo) {
+ // An existing proxy is available... So use it.
+ NS_ADDREF(peo);
+ return peo;
+ }
+ }
+ else {
+ // build the root proxy
+ nsCOMPtr<nsProxyEventClass> rootClazz;
+
+ rootClazz = dont_AddRef(nsProxyEventClass::GetNewOrUsedClass(
+ NS_GET_IID(nsISupports)));
+ if (!rootClazz) {
+ return nsnull;
+ }
+
+ peo = new nsProxyEventObject(destQueue,
+ proxyType,
+ rootObject,
+ rootClazz,
+ nsnull);
+ if(!peo) {
+ // Ouch... Out of memory!
+ return nsnull;
+ }
+
+ // Add this root proxy into the hash table...
+ realToProxyMap->Put(&rootkey, peo);
+
+ if(aIID.Equals(NS_GET_IID(nsISupports))) {
+ //
+ // Since the requested proxy is for the nsISupports interface of
+ // the raw object, use the new root proxy as the specific proxy
+ // too...
+ //
+ NS_ADDREF(peo);
+ return peo;
+ }
+
+ // This assignment is an owning reference to the new ProxyEventObject.
+ // So, it will automatically get deleted if any subsequent early
+ // returns are taken...
+ rootProxy = do_QueryInterface(peo);
+ }
+
+ //
+ // at this point we have a proxy for the root nsISupports (ie. rootProxy)
+ // but we need to build the specific proxy for this interface...
+ //
+ NS_ASSERTION(rootProxy, "What happened to the root proxy!");
+
+ // Get a class for this IID.
+ nsCOMPtr<nsProxyEventClass> proxyClazz;
+
+ proxyClazz = dont_AddRef(nsProxyEventClass::GetNewOrUsedClass(aIID));
+ if(!proxyClazz) {
+ return nsnull;
+ }
+
+ // Get the raw interface for this IID
+ nsCOMPtr<nsISupports> rawInterface;
+
+ rv = rawObject->QueryInterface(aIID, getter_AddRefs(rawInterface));
+ if (NS_FAILED(rv) || !rawInterface) {
+ NS_ASSERTION(NS_FAILED(rv), "where did my rawInterface object go!");
+ return nsnull;
+ }
+
+ peo = new nsProxyEventObject(destQueue,
+ proxyType,
+ rawInterface,
+ proxyClazz,
+ rootProxy);
+ if (!peo) {
+ // Ouch... Out of memory!
+ return nsnull;
+ }
+
+ //
+ // Add the new specific proxy to the head of the list of proxies hanging
+ // off of the rootProxy...
+ //
+ peo->mNext = rootProxy->mNext;
+ rootProxy->mNext = peo;
+
+ NS_ADDREF(peo);
+ return peo;
+
+}
+
+nsProxyEventObject* nsProxyEventObject::LockedFind(REFNSIID aIID)
+{
+ if(aIID.Equals(mClass->GetProxiedIID())) {
+ return this;
+ }
+
+ if(aIID.Equals(NS_GET_IID(nsISupports))) {
+ return this;
+ }
+
+ nsProxyEventObject* cur = (mRoot ? mRoot : mNext);
+ while(cur) {
+ if(aIID.Equals(cur->GetClass()->GetProxiedIID())) {
+ return cur;
+ }
+ cur = cur->mNext;
+ }
+
+ return nsnull;
+}
+
+nsProxyEventObject::nsProxyEventObject()
+: mNext(nsnull)
+{
+ NS_WARNING("This constructor should never be called");
+}
+
+nsProxyEventObject::nsProxyEventObject(nsIEventQueue *destQueue,
+ PRInt32 proxyType,
+ nsISupports* aObj,
+ nsProxyEventClass* aClass,
+ nsProxyEventObject* root)
+ : mClass(aClass),
+ mRoot(root),
+ mNext(nsnull)
+{
+ NS_IF_ADDREF(mRoot);
+
+ mProxyObject = new nsProxyObject(destQueue, proxyType, aObj);
+
+#ifdef DEBUG_xpcom_proxy
+ DebugDump("Create", 0);
+#endif
+}
+
+nsProxyEventObject::~nsProxyEventObject()
+{
+#ifdef DEBUG_xpcom_proxy
+ DebugDump("Delete", 0);
+#endif
+ if (mRoot) {
+ //
+ // This proxy is not the root interface so it must be removed
+ // from the chain of proxies...
+ //
+ nsProxyEventObject* cur = mRoot;
+ while(cur) {
+ if(cur->mNext == this) {
+ cur->mNext = mNext;
+ mNext = nsnull;
+ break;
+ }
+ cur = cur->mNext;
+ }
+ NS_ASSERTION(cur, "failed to find wrapper in its own chain");
+ }
+ else {
+ //
+ // This proxy is for the root interface. Each proxy in the chain
+ // has a strong reference to the root... So, when its refcount goes
+ // to zero, it safe to remove it because no proxies are in its chain.
+ //
+ if (! nsProxyObjectManager::IsManagerShutdown()) {
+ nsProxyObjectManager* manager = nsProxyObjectManager::GetInstance();
+ nsHashtable *realToProxyMap = manager->GetRealObjectToProxyObjectMap();
+
+ NS_ASSERTION(!mNext, "There are still proxies in the chain!");
+
+ if (realToProxyMap != nsnull) {
+ nsCOMPtr<nsISupports> rootObject = do_QueryInterface(mProxyObject->mRealObject);
+ nsCOMPtr<nsISupports> rootQueue = do_QueryInterface(mProxyObject->mDestQueue);
+ nsProxyEventKey key(rootObject, rootQueue, mProxyObject->mProxyType);
+#ifdef DEBUG_dougt
+ void* value =
+#endif
+ realToProxyMap->Remove(&key);
+#ifdef DEBUG_dougt
+ NS_ASSERTION(value, "failed to remove from realToProxyMap");
+#endif
+ }
+ }
+ }
+
+ // I am worried about ordering.
+ // do not remove assignments.
+ mProxyObject = nsnull;
+ mClass = nsnull;
+ NS_IF_RELEASE(mRoot);
+}
+
+//
+// nsISupports implementation...
+//
+
+NS_IMPL_THREADSAFE_ADDREF(nsProxyEventObject)
+
+NS_IMETHODIMP_(nsrefcnt)
+nsProxyEventObject::Release(void)
+{
+ //
+ // Be pessimistic about whether the manager or even the monitor exist...
+ // This is to protect against shutdown issues where a proxy object could
+ // be destroyed after (or while) the Proxy Manager is being destroyed...
+ //
+ nsProxyObjectManager* manager = nsProxyObjectManager::GetInstance();
+ nsAutoMonitor mon(manager ? manager->GetMonitor() : nsnull);
+
+ nsrefcnt count;
+ NS_PRECONDITION(0 != mRefCnt, "dup release");
+ // Decrement atomically - in case the Proxy Object Manager has already
+ // been deleted and the monitor is unavailable...
+ count = PR_AtomicDecrement((PRInt32 *)&mRefCnt);
+ NS_LOG_RELEASE(this, count, "nsProxyEventObject");
+ if (0 == count) {
+ mRefCnt = 1; /* stabilize */
+ //
+ // Remove the proxy from the hashtable (if necessary) or its
+ // proxy chain. This must be done inside of the proxy lock to
+ // prevent GetNewOrUsedProxy(...) from ressurecting it...
+ //
+ NS_DELETEXPCOM(this);
+ return 0;
+ }
+ return count;
+}
+
+NS_IMETHODIMP
+nsProxyEventObject::QueryInterface(REFNSIID aIID, void** aInstancePtr)
+{
+ if( aIID.Equals(GetIID()) )
+ {
+ *aInstancePtr = NS_STATIC_CAST(nsISupports*, this);
+ NS_ADDREF_THIS();
+ return NS_OK;
+ }
+
+ return mClass->DelegatedQueryInterface(this, aIID, aInstancePtr);
+}
+
+//
+// nsXPTCStubBase implementation...
+//
+
+NS_IMETHODIMP
+nsProxyEventObject::GetInterfaceInfo(nsIInterfaceInfo** info)
+{
+ NS_ENSURE_ARG_POINTER(info);
+
+ *info = mClass->GetInterfaceInfo();
+
+ NS_ASSERTION(*info, "proxy class without interface");
+ if (!*info) {
+ return NS_ERROR_UNEXPECTED;
+ }
+
+ NS_ADDREF(*info);
+ return NS_OK;
+}
+
+NS_IMETHODIMP
+nsProxyEventObject::CallMethod(PRUint16 methodIndex,
+ const nsXPTMethodInfo* info,
+ nsXPTCMiniVariant * params)
+{
+ nsresult rv;
+
+ if (mProxyObject) {
+ rv = mProxyObject->Post(methodIndex,
+ (nsXPTMethodInfo*)info,
+ params,
+ mClass->GetInterfaceInfo());
+ } else {
+ rv = NS_ERROR_NULL_POINTER;
+ }
+
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventPrivate.h b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventPrivate.h
new file mode 100644
index 00000000..ee34927e
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyEventPrivate.h
@@ -0,0 +1,201 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 ***** */
+
+#ifndef __nsProxyEventPrivate_h_
+#define __nsProxyEventPrivate_h_
+
+#include "nscore.h"
+#include "nsISupports.h"
+#include "nsIFactory.h"
+#include "nsHashtable.h"
+
+#include "plevent.h"
+#include "xptcall.h" // defines nsXPTCVariant
+#include "nsIEventQueue.h"
+
+#include "nsProxyEvent.h"
+#include "nsIProxyObjectManager.h"
+
+class nsProxyEventObject;
+class nsProxyEventClass;
+
+#define NS_PROXYEVENT_CLASS_IID \
+{ 0xeea90d42, \
+ 0xb059, \
+ 0x11d2, \
+ {0x91, 0x5e, 0xc1, 0x2b, 0x69, 0x6c, 0x93, 0x33}\
+}
+
+#define NS_PROXYEVENT_IDENTITY_CLASS_IID \
+{ 0xeea90d45, 0xb059, 0x11d2, \
+ { 0x91, 0x5e, 0xc1, 0x2b, 0x69, 0x6c, 0x93, 0x33 } }
+
+
+#define NS_PROXYEVENT_OBJECT_IID \
+{ 0xec373590, 0x9164, 0x11d3, \
+{0x8c, 0x73, 0x00, 0x00, 0x64, 0x65, 0x73, 0x74} }
+
+
+class nsProxyEventClass : public nsISupports
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_PROXYEVENT_CLASS_IID)
+ static nsProxyEventClass* GetNewOrUsedClass(REFNSIID aIID);
+
+ NS_IMETHOD DelegatedQueryInterface( nsProxyEventObject* self,
+ REFNSIID aIID,
+ void** aInstancePtr);
+
+
+ nsIInterfaceInfo* GetInterfaceInfo() const {return mInfo;}
+ const nsIID& GetProxiedIID() const {return mIID; }
+protected:
+ nsProxyEventClass();
+ nsProxyEventClass(REFNSIID aIID, nsIInterfaceInfo* aInfo);
+
+private:
+ ~nsProxyEventClass();
+
+ nsIID mIID;
+ nsCOMPtr<nsIInterfaceInfo> mInfo;
+ uint32* mDescriptors;
+
+ nsresult CallQueryInterfaceOnProxy(nsProxyEventObject* self,
+ REFNSIID aIID,
+ nsProxyEventObject** aInstancePtr);
+};
+
+
+
+class nsProxyEventObject : public nsXPTCStubBase
+{
+public:
+
+ NS_DECL_ISUPPORTS
+
+ NS_DEFINE_STATIC_IID_ACCESSOR(NS_PROXYEVENT_OBJECT_IID)
+
+ static nsProxyEventObject* GetNewOrUsedProxy(nsIEventQueue *destQueue,
+ PRInt32 proxyType,
+ nsISupports *aObj,
+ REFNSIID aIID);
+
+
+ NS_IMETHOD GetInterfaceInfo(nsIInterfaceInfo** info);
+
+ // call this method and return result
+ NS_IMETHOD CallMethod(PRUint16 methodIndex, const nsXPTMethodInfo* info, nsXPTCMiniVariant* params);
+
+
+ nsProxyEventClass* GetClass() const { return mClass; }
+ nsIEventQueue* GetQueue() const { return (mProxyObject ? mProxyObject->GetQueue() : nsnull);}
+ nsISupports* GetRealObject() const { return (mProxyObject ? mProxyObject->GetRealObject(): nsnull);}
+ PRInt32 GetProxyType() const { return (mProxyObject ? mProxyObject->GetProxyType() : nsnull);}
+
+ nsProxyEventObject();
+ nsProxyEventObject(nsIEventQueue *destQueue,
+ PRInt32 proxyType,
+ nsISupports* aObj,
+ nsProxyEventClass* aClass,
+ nsProxyEventObject* root);
+
+ nsProxyEventObject* LockedFind(REFNSIID aIID);
+
+#ifdef DEBUG_xpcom_proxy
+ void DebugDump(const char * message, PRUint32 hashKey);
+#endif
+
+private:
+ ~nsProxyEventObject();
+
+protected:
+ void LockedRemoveProxy();
+
+protected:
+ nsCOMPtr<nsProxyEventClass> mClass;
+ nsRefPtr<nsProxyObject> mProxyObject;
+
+ // Owning reference...
+ nsProxyEventObject *mRoot;
+
+ // Weak reference...
+ nsProxyEventObject *mNext;
+};
+
+
+
+
+////////////////////////////////////////////////////////////////////////////////
+// nsProxyObjectManager
+////////////////////////////////////////////////////////////////////////////////
+
+class nsProxyObjectManager: public nsIProxyObjectManager
+{
+public:
+
+ NS_DECL_ISUPPORTS
+ NS_DECL_NSIPROXYOBJECTMANAGER
+
+
+ static NS_METHOD Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr);
+
+ nsProxyObjectManager();
+
+ static nsProxyObjectManager *GetInstance();
+ static PRBool IsManagerShutdown();
+
+ static void Shutdown();
+
+ nsHashtable* GetRealObjectToProxyObjectMap() { return &mProxyObjectMap;}
+ nsHashtable* GetIIDToProxyClassMap() { return &mProxyClassMap; }
+
+ PRMonitor* GetMonitor() const { return mProxyCreationMonitor; }
+
+private:
+ ~nsProxyObjectManager();
+
+ static nsProxyObjectManager* mInstance;
+ nsHashtable mProxyObjectMap;
+ nsHashtable mProxyClassMap;
+ PRMonitor *mProxyCreationMonitor;
+};
+
+
+#endif
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyObjectManager.cpp b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyObjectManager.cpp
new file mode 100644
index 00000000..0602bcd7
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyObjectManager.cpp
@@ -0,0 +1,322 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Doug Turner <dougt@netscape.com> (Original Author)
+ * Judson Valeski <valeski@netscape.com>
+ * Dan Matejka <danm@netscape.com>
+ * Scott Collins <scc@netscape.com>
+ * Heikki Toivonen <heiki@citec.fi>
+ * Patrick Beard <beard@netscape.com>
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ * Warren Harris <warren@netscape.com>
+ * Chris Seawood <cls@seawood.org>
+ * Chris Waterson <waterson@netscape.com>
+ * Dan Mosedale <dmose@netscape.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 ***** */
+
+
+#include "nsProxyEvent.h"
+#include "nsIProxyObjectManager.h"
+#include "nsProxyEventPrivate.h"
+
+#include "nsIProxyCreateInstance.h"
+
+#include "nsIComponentManager.h"
+#include "nsIServiceManager.h"
+#include "nsComponentManagerObsolete.h"
+#include "nsCOMPtr.h"
+
+#include "nsIEventQueueService.h"
+#include "nsIThread.h"
+
+
+static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+
+/***************************************************************************/
+/* nsProxyCreateInstance */
+/* This private class will allow us to create Instances on another thread */
+/***************************************************************************/
+class nsProxyCreateInstance : public nsIProxyCreateInstance
+{
+ NS_DECL_ISUPPORTS
+ NS_IMETHOD CreateInstanceByIID(const nsIID & cid, nsISupports *aOuter, const nsIID & iid, void * *result);
+ NS_IMETHOD CreateInstanceByContractID(const char *aContractID, nsISupports *aOuter, const nsIID & iid, void * *result);
+
+ nsProxyCreateInstance() {}
+
+private:
+ ~nsProxyCreateInstance() {}
+};
+
+NS_IMPL_ISUPPORTS1(nsProxyCreateInstance, nsIProxyCreateInstance)
+
+NS_IMETHODIMP nsProxyCreateInstance::CreateInstanceByIID(const nsIID & cid, nsISupports *aOuter, const nsIID & iid, void * *result)
+{
+ return nsComponentManager::CreateInstance( cid,
+ aOuter,
+ iid,
+ result);
+}
+
+
+NS_IMETHODIMP nsProxyCreateInstance::CreateInstanceByContractID(const char *aContractID, nsISupports *aOuter, const nsIID & iid, void * *result)
+{
+ return nsComponentManager::CreateInstance( aContractID,
+ aOuter,
+ iid,
+ result);
+}
+
+/////////////////////////////////////////////////////////////////////////
+// nsProxyObjectManager
+/////////////////////////////////////////////////////////////////////////
+
+nsProxyObjectManager* nsProxyObjectManager::mInstance = nsnull;
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsProxyObjectManager, nsIProxyObjectManager)
+
+nsProxyObjectManager::nsProxyObjectManager()
+ : mProxyObjectMap(256, PR_TRUE),
+ mProxyClassMap(256, PR_TRUE)
+{
+ mProxyCreationMonitor = PR_NewMonitor();
+}
+
+static PRBool PurgeProxyClasses(nsHashKey *aKey, void *aData, void* closure)
+{
+ nsProxyEventClass* ptr = NS_REINTERPRET_CAST(nsProxyEventClass*, aData);
+ NS_RELEASE(ptr);
+ return PR_TRUE;
+}
+
+nsProxyObjectManager::~nsProxyObjectManager()
+{
+ mProxyClassMap.Reset((nsHashtableEnumFunc)PurgeProxyClasses, nsnull);
+
+ if (mProxyCreationMonitor) {
+ PR_DestroyMonitor(mProxyCreationMonitor);
+ }
+
+ nsProxyObjectManager::mInstance = nsnull;
+}
+
+PRBool
+nsProxyObjectManager::IsManagerShutdown()
+{
+ if (mInstance)
+ return PR_FALSE;
+ return PR_TRUE;
+}
+
+nsProxyObjectManager *
+nsProxyObjectManager::GetInstance()
+{
+ if (! mInstance)
+ {
+ mInstance = new nsProxyObjectManager();
+ }
+ return mInstance;
+}
+
+
+void
+nsProxyObjectManager::Shutdown()
+{
+ mInstance = nsnull;
+}
+
+
+// Helpers
+NS_IMETHODIMP
+nsProxyObjectManager::Create(nsISupports* outer, const nsIID& aIID, void* *aInstancePtr)
+{
+ nsProxyObjectManager *proxyObjectManager = GetInstance();
+
+ if (proxyObjectManager == nsnull)
+ return NS_ERROR_OUT_OF_MEMORY;
+
+ return proxyObjectManager->QueryInterface(aIID, aInstancePtr);
+}
+
+
+NS_IMETHODIMP
+nsProxyObjectManager::GetProxyForObject(nsIEventQueue *destQueue,
+ REFNSIID aIID,
+ nsISupports* aObj,
+ PRInt32 proxyType,
+ void** aProxyObject)
+{
+ if (!aObj) return NS_ERROR_NULL_POINTER;
+ if (!aProxyObject) return NS_ERROR_NULL_POINTER;
+
+ nsresult rv;
+ nsCOMPtr<nsIEventQueue> postQ;
+
+
+ *aProxyObject = nsnull;
+
+ // check to see if the destination Q is a special case.
+
+ nsCOMPtr<nsIEventQueueService> eventQService =
+ do_GetService(kEventQueueServiceCID, &rv);
+ if (NS_FAILED(rv))
+ return rv;
+
+ rv = eventQService->ResolveEventQueue(destQueue, getter_AddRefs(postQ));
+ if (NS_FAILED(rv))
+ return rv;
+
+ // check to see if the eventQ is on our thread. If so, just return the real object.
+
+ if (postQ && !(proxyType & PROXY_ASYNC) && !(proxyType & PROXY_ALWAYS))
+ {
+ PRBool aResult;
+ postQ->IsOnCurrentThread(&aResult);
+
+ if (aResult)
+ {
+ return aObj->QueryInterface(aIID, aProxyObject);
+ }
+ }
+
+ // check to see if proxy is there or not.
+ *aProxyObject = nsProxyEventObject::GetNewOrUsedProxy(postQ, proxyType, aObj, aIID);
+
+ if (*aProxyObject == nsnull)
+ return NS_ERROR_NO_INTERFACE; //fix error code?
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP
+nsProxyObjectManager::GetProxy( nsIEventQueue *destQueue,
+ const nsCID &aClass,
+ nsISupports *aDelegate,
+ const nsIID &aIID,
+ PRInt32 proxyType,
+ void** aProxyObject)
+{
+ if (!aProxyObject) return NS_ERROR_NULL_POINTER;
+ *aProxyObject = nsnull;
+
+ // 1. Create a proxy for creating an instance on another thread.
+
+ nsIProxyCreateInstance* ciProxy = nsnull;
+
+ nsProxyCreateInstance* ciObject = new nsProxyCreateInstance();
+
+ if (ciObject == nsnull)
+ return NS_ERROR_NULL_POINTER;
+
+ NS_ADDREF(ciObject);
+
+ nsresult rv = GetProxyForObject(destQueue,
+ NS_GET_IID(nsIProxyCreateInstance),
+ ciObject,
+ PROXY_SYNC,
+ (void**)&ciProxy);
+
+ if (NS_FAILED(rv))
+ {
+ NS_RELEASE(ciObject);
+ return rv;
+ }
+
+ // 2. now create a new instance of the request object via our proxy.
+
+ nsISupports* aObj;
+
+ rv = ciProxy->CreateInstanceByIID(aClass,
+ aDelegate,
+ aIID,
+ (void**)&aObj);
+
+
+ // 3. Delete the create instance proxy and its real object.
+
+ NS_RELEASE(ciProxy);
+ NS_RELEASE(ciObject);
+
+ // 4. Check to see if creating the requested instance failed.
+ if ( NS_FAILED(rv))
+ {
+ return rv;
+ }
+
+ // 5. Now create a proxy object for the requested object.
+
+ rv = GetProxyForObject(destQueue, aIID, aObj, proxyType, aProxyObject);
+
+ // 6. release ownership of aObj so that aProxyObject owns it.
+
+ NS_RELEASE(aObj);
+
+ // 7. return the error returned from GetProxyForObject. Either way, we our out of here.
+
+ return rv;
+}
+
+/**
+ * Helper function for code that already has a link-time dependency on
+ * libxpcom and needs to get proxies in a bunch of different places.
+ * This way, the caller isn't forced to get the proxy object manager
+ * themselves every single time, thus making the calling code more
+ * readable.
+ */
+NS_COM nsresult
+NS_GetProxyForObject(nsIEventQueue *destQueue,
+ REFNSIID aIID,
+ nsISupports* aObj,
+ PRInt32 proxyType,
+ void** aProxyObject)
+{
+ static NS_DEFINE_CID(proxyObjMgrCID, NS_PROXYEVENT_MANAGER_CID);
+
+ nsresult rv; // temp for return value
+
+ // get the proxy object manager
+ //
+ nsCOMPtr<nsIProxyObjectManager> proxyObjMgr =
+ do_GetService(proxyObjMgrCID, &rv);
+
+ if (NS_FAILED(rv))
+ return NS_ERROR_FAILURE;
+
+ // and try to get the proxy object
+ //
+ return proxyObjMgr->GetProxyForObject(destQueue, aIID, aObj,
+ proxyType, aProxyObject);
+}
diff --git a/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyRelease.cpp b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyRelease.cpp
new file mode 100644
index 00000000..3ceeb667
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/src/nsProxyRelease.cpp
@@ -0,0 +1,55 @@
+#include "nsProxyRelease.h"
+
+PR_STATIC_CALLBACK(void*)
+HandleProxyReleaseEvent(PLEvent *self)
+{
+ nsISupports* owner = (nsISupports*) self->owner;
+ NS_RELEASE(owner);
+ return nsnull;
+}
+
+PR_STATIC_CALLBACK(void)
+DestroyProxyReleaseEvent(PLEvent *self)
+{
+ delete self;
+}
+
+NS_COM nsresult
+NS_ProxyRelease(nsIEventTarget *target, nsISupports *doomed, PRBool alwaysProxy)
+{
+ nsresult rv;
+
+ if (!target) {
+ NS_RELEASE(doomed);
+ return NS_OK;
+ }
+
+ if (!alwaysProxy) {
+ PRBool onCurrentThread = PR_FALSE;
+ rv = target->IsOnCurrentThread(&onCurrentThread);
+ if (NS_SUCCEEDED(rv) && onCurrentThread) {
+ NS_RELEASE(doomed);
+ return NS_OK;
+ }
+ }
+
+ PLEvent *ev = new PLEvent;
+ if (!ev) {
+ // we do not release doomed here since it may cause a delete on the
+ // wrong thread. better to leak than crash.
+ return NS_ERROR_OUT_OF_MEMORY;
+ }
+
+ PL_InitEvent(ev, doomed,
+ HandleProxyReleaseEvent,
+ DestroyProxyReleaseEvent);
+
+ rv = target->PostEvent(ev);
+ if (NS_FAILED(rv)) {
+ NS_WARNING("failed to post proxy release event");
+ PL_DestroyEvent(ev);
+ // again, it is better to leak the doomed object than risk crashing as
+ // a result of deleting it on the wrong thread.
+ }
+ return rv;
+}
diff --git a/src/libs/xpcom18a4/xpcom/proxy/tests/.cvsignore b/src/libs/xpcom18a4/xpcom/proxy/tests/.cvsignore
new file mode 100644
index 00000000..b7457ff6
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/tests/.cvsignore
@@ -0,0 +1,2 @@
+Makefile
+proxytests
diff --git a/src/libs/xpcom18a4/xpcom/proxy/tests/Makefile.in b/src/libs/xpcom18a4/xpcom/proxy/tests/Makefile.in
new file mode 100644
index 00000000..e5e908f1
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/tests/Makefile.in
@@ -0,0 +1,60 @@
+#
+# ***** BEGIN LICENSE BLOCK *****
+# Version: MPL 1.1/GPL 2.0/LGPL 2.1
+#
+# The contents of this file are subject to the Mozilla Public License Version
+# 1.1 (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+# http://www.mozilla.org/MPL/
+#
+# Software distributed under the License is distributed on an "AS IS" basis,
+# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+# for the specific language governing rights and limitations under the
+# License.
+#
+# The Original Code is mozilla.org code.
+#
+# The Initial Developer of the Original Code is
+# Netscape Communications Corporation.
+# Portions created by the Initial Developer are Copyright (C) 1998
+# the Initial Developer. All Rights Reserved.
+#
+# Contributor(s):
+#
+# Alternatively, the contents of this file may be used under the terms of
+# either of the GNU General Public License Version 2 or later (the "GPL"),
+# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+# in which case the provisions of the GPL or the LGPL are applicable instead
+# of those above. If you wish to allow use of your version of this file only
+# under the terms of either the GPL or the LGPL, and not to allow others to
+# use your version of this file under the terms of the MPL, indicate your
+# decision by deleting the provisions above and replace them with the notice
+# and other provisions required by the GPL or the LGPL. If you do not delete
+# the provisions above, a recipient may use your version of this file under
+# the terms of any one of the MPL, the GPL or the LGPL.
+#
+# ***** END LICENSE BLOCK *****
+
+DEPTH = ../../..
+topsrcdir = @top_srcdir@
+srcdir = @srcdir@
+VPATH = @srcdir@
+
+include $(DEPTH)/config/autoconf.mk
+
+MODULE = xpcom
+XPIDL_MODULE = proxytest
+REQUIRES = $(NULL)
+
+CPPSRCS = proxytests.cpp
+XPIDLSRCS = nsITestProxy.idl
+
+SIMPLE_PROGRAMS = $(CPPSRCS:.cpp=$(BIN_SUFFIX))
+
+LIBS = \
+ $(XPCOM_LIBS) \
+ $(NSPR_LIBS) \
+ $(NULL)
+
+include $(topsrcdir)/config/rules.mk
+
diff --git a/src/libs/xpcom18a4/xpcom/proxy/tests/nsITestProxy.idl b/src/libs/xpcom18a4/xpcom/proxy/tests/nsITestProxy.idl
new file mode 100644
index 00000000..98cb3f94
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/tests/nsITestProxy.idl
@@ -0,0 +1,9 @@
+#include "nsISupports.idl"
+
+[uuid(1979e980-1cfd-11d3-915e-0000863011c4)]
+interface nsITestProxy : nsISupports
+{
+ long Test(in long p1, in long p2);
+ void Test2();
+ void Test3(in nsISupports p1, out nsISupports p2);
+};
diff --git a/src/libs/xpcom18a4/xpcom/proxy/tests/proxytests.cpp b/src/libs/xpcom18a4/xpcom/proxy/tests/proxytests.cpp
new file mode 100644
index 00000000..20693463
--- /dev/null
+++ b/src/libs/xpcom18a4/xpcom/proxy/tests/proxytests.cpp
@@ -0,0 +1,553 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is mozilla.org code.
+ *
+ * The Initial Developer of the Original Code is
+ * Netscape Communications Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 1998
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ * Pierre Phaneuf <pp@ludusdesign.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either of 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 ***** */
+
+#include <stdio.h>
+
+#include "nsXPCOM.h"
+#include "nsIComponentManager.h"
+#include "nsIComponentRegistrar.h"
+#include "nsIServiceManager.h"
+#include "nsCOMPtr.h"
+
+#include "nscore.h"
+#include "nspr.h"
+#include "prmon.h"
+
+#include "nsITestProxy.h"
+
+#include "nsIProxyObjectManager.h"
+#include "nsIEventQueueService.h"
+
+static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
+
+/***************************************************************************/
+/* nsTestXPCFoo */
+/***************************************************************************/
+class nsTestXPCFoo : public nsITestProxy
+{
+ NS_DECL_ISUPPORTS
+ NS_IMETHOD Test(PRInt32 p1, PRInt32 p2, PRInt32* retval);
+ NS_IMETHOD Test2();
+ NS_IMETHOD Test3(nsISupports *p1, nsISupports **p2);
+
+ nsTestXPCFoo();
+};
+
+nsTestXPCFoo::nsTestXPCFoo()
+{
+ NS_ADDREF_THIS();
+}
+
+NS_IMPL_ISUPPORTS1(nsTestXPCFoo, nsITestProxy)
+
+NS_IMETHODIMP nsTestXPCFoo::Test(PRInt32 p1, PRInt32 p2, PRInt32* retval)
+{
+ printf("Thread (%d) Test Called successfully! Party on...\n", p1);
+ *retval = p1+p2;
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP nsTestXPCFoo::Test2()
+{
+ printf("The quick brown netscape jumped over the old lazy ie..\n");
+
+ return NS_OK;
+}
+
+NS_IMETHODIMP nsTestXPCFoo::Test3(nsISupports *p1, nsISupports **p2)
+{
+ if (p1 != nsnull)
+ {
+ nsITestProxy *test;
+
+ p1->QueryInterface(NS_GET_IID(nsITestProxy), (void**)&test);
+
+ test->Test2();
+ PRInt32 a;
+ test->Test( 1, 2, &a);
+ printf("\n1+2=%d\n",a);
+ }
+
+
+ *p2 = new nsTestXPCFoo();
+ return NS_OK;
+}
+
+/***************************************************************************/
+/* nsTestXPCFoo2 */
+/***************************************************************************/
+class nsTestXPCFoo2 : public nsITestProxy
+{
+ NS_DECL_ISUPPORTS
+ NS_IMETHOD Test(PRInt32 p1, PRInt32 p2, PRInt32* retval);
+ NS_IMETHOD Test2();
+ NS_IMETHOD Test3(nsISupports *p1, nsISupports **p2);
+
+ nsTestXPCFoo2();
+};
+
+nsTestXPCFoo2::nsTestXPCFoo2()
+{
+ NS_ADDREF_THIS();
+}
+
+NS_IMPL_THREADSAFE_ISUPPORTS1(nsTestXPCFoo2, nsITestProxy)
+
+NS_IMETHODIMP nsTestXPCFoo2::Test(PRInt32 p1, PRInt32 p2, PRInt32* retval)
+{
+printf("calling back to caller!\n\n");
+
+ nsIProxyObjectManager* manager;
+ nsITestProxy * proxyObject;
+
+ nsServiceManager::GetService( NS_XPCOMPROXY_CONTRACTID,
+ NS_GET_IID(nsIProxyObjectManager),
+ (nsISupports **)&manager);
+
+ printf("ProxyObjectManager: %p \n", manager);
+
+ PR_ASSERT(manager);
+
+ manager->GetProxyForObject((nsIEventQueue*)p1, NS_GET_IID(nsITestProxy), this, PROXY_SYNC, (void**)&proxyObject);
+ proxyObject->Test3(nsnull, nsnull);
+
+ printf("Deleting Proxy Object\n");
+ NS_RELEASE(proxyObject);
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP nsTestXPCFoo2::Test2()
+{
+ printf("nsTestXPCFoo2::Test2() called\n");
+
+ return NS_OK;
+}
+
+
+NS_IMETHODIMP nsTestXPCFoo2::Test3(nsISupports *p1, nsISupports **p2)
+{
+ printf("Got called");
+ return NS_OK;
+}
+
+
+
+typedef struct _ArgsStruct
+{
+ nsIEventQueue* queue;
+ PRInt32 threadNumber;
+}ArgsStruct;
+
+
+
+// This will create two objects both descendants of a single IID.
+void TestCase_TwoClassesOneInterface(void *arg)
+{
+ ArgsStruct *argsStruct = (ArgsStruct*) arg;
+
+
+ nsIProxyObjectManager* manager;
+
+ nsServiceManager::GetService( NS_XPCOMPROXY_CONTRACTID,
+ NS_GET_IID(nsIProxyObjectManager),
+ (nsISupports **)&manager);
+
+ printf("ProxyObjectManager: %p \n", manager);
+
+ PR_ASSERT(manager);
+
+ nsITestProxy *proxyObject;
+ nsITestProxy *proxyObject2;
+
+ nsTestXPCFoo* foo = new nsTestXPCFoo();
+ nsTestXPCFoo2* foo2 = new nsTestXPCFoo2();
+
+ PR_ASSERT(foo);
+ PR_ASSERT(foo2);
+
+
+ manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject);
+
+ manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo2, PROXY_SYNC, (void**)&proxyObject2);
+
+
+
+ if (proxyObject && proxyObject2)
+ {
+ // release ownership of the real object.
+
+ PRInt32 a;
+ nsresult rv;
+ PRInt32 threadNumber = argsStruct->threadNumber;
+
+ printf("Deleting real Object (%d)\n", threadNumber);
+ NS_RELEASE(foo);
+
+ printf("Deleting real Object 2 (%d)\n", threadNumber);
+ NS_RELEASE(foo2);
+
+
+ printf("Thread (%d) Prior to calling proxyObject->Test.\n", threadNumber);
+ rv = proxyObject->Test(threadNumber, 0, &a);
+ printf("Thread (%d) error: %d.\n", threadNumber, rv);
+
+
+ printf("Thread (%d) Prior to calling proxyObject->Test2.\n", threadNumber);
+ rv = proxyObject->Test2();
+ printf("Thread (%d) error: %d.\n", threadNumber, rv);
+
+ printf("Thread (%d) Prior to calling proxyObject2->Test2.\n", threadNumber);
+ rv = proxyObject2->Test2();
+ printf("Thread (%d) proxyObject2 error: %d.\n", threadNumber, rv);
+
+ printf("Deleting Proxy Object (%d)\n", threadNumber );
+ NS_RELEASE(proxyObject);
+
+ printf("Deleting Proxy Object 2 (%d)\n", threadNumber );
+ NS_RELEASE(proxyObject2);
+ }
+
+ PR_Sleep( PR_MillisecondsToInterval(1000) ); // If your thread goes away, your stack goes away. Only use ASYNC on calls that do not have out parameters
+}
+
+
+
+void TestCase_NestedLoop(void *arg)
+{
+ ArgsStruct *argsStruct = (ArgsStruct*) arg;
+
+
+ nsIProxyObjectManager* manager;
+
+ nsServiceManager::GetService( NS_XPCOMPROXY_CONTRACTID,
+ NS_GET_IID(nsIProxyObjectManager),
+ (nsISupports **)&manager);
+
+ printf("ProxyObjectManager: %p \n", manager);
+
+ PR_ASSERT(manager);
+
+ nsITestProxy *proxyObject;
+ nsTestXPCFoo2* foo = new nsTestXPCFoo2();
+
+ PR_ASSERT(foo);
+
+
+ manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject);
+
+ if (proxyObject)
+ {
+ // release ownership of the real object.
+
+ nsresult rv;
+ PRInt32 threadNumber = argsStruct->threadNumber;
+
+ printf("Deleting real Object (%d)\n", threadNumber);
+ NS_RELEASE(foo);
+
+ PRInt32 retval;
+
+ printf("Getting EventQueue...\n");
+
+ nsIEventQueue* eventQ;
+ nsCOMPtr<nsIEventQueueService> eventQService =
+ do_GetService(kEventQueueServiceCID, &rv);
+ if (NS_SUCCEEDED(rv))
+ {
+ rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ);
+ if (NS_FAILED(rv))
+ rv = eventQService->CreateThreadEventQueue();
+ if (NS_FAILED(rv))
+ return;
+ else
+ rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ);
+
+ printf("Thread (%d) Prior to calling proxyObject->Test.\n", threadNumber);
+ rv = proxyObject->Test(NS_PTR_TO_INT32(eventQ), 0, &retval);
+ printf("Thread (%d) proxyObject error: %d.\n", threadNumber, rv);
+
+ printf("Deleting Proxy Object (%d)\n", threadNumber );
+ NS_RELEASE(proxyObject);
+ }
+
+ PR_Sleep( PR_MillisecondsToInterval(1000) ); // If your thread goes away, your stack goes away. Only use ASYNC on calls that do not have out parameters
+ }
+}
+
+
+
+void TestCase_2(void *arg)
+{
+
+ ArgsStruct *argsStruct = (ArgsStruct*) arg;
+
+ nsIProxyObjectManager* manager;
+
+ nsServiceManager::GetService( NS_XPCOMPROXY_CONTRACTID,
+ NS_GET_IID(nsIProxyObjectManager),
+ (nsISupports **)&manager);
+
+ PR_ASSERT(manager);
+
+ nsITestProxy *proxyObject;
+
+ manager->GetProxy(argsStruct->queue,
+ NS_GET_IID(nsITestProxy), // should be CID!
+ nsnull,
+ NS_GET_IID(nsITestProxy),
+ PROXY_SYNC,
+ (void**)&proxyObject);
+
+ if (proxyObject != nsnull)
+ {
+ NS_RELEASE(proxyObject);
+ }
+}
+
+
+
+void TestCase_nsISupports(void *arg)
+{
+
+ ArgsStruct *argsStruct = (ArgsStruct*) arg;
+
+ nsIProxyObjectManager* manager;
+
+ nsServiceManager::GetService( NS_XPCOMPROXY_CONTRACTID,
+ NS_GET_IID(nsIProxyObjectManager),
+ (nsISupports **)&manager);
+
+ PR_ASSERT(manager);
+
+ nsITestProxy *proxyObject;
+ nsTestXPCFoo* foo = new nsTestXPCFoo();
+
+ PR_ASSERT(foo);
+
+ manager->GetProxyForObject(argsStruct->queue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject);
+
+ if (proxyObject != nsnull)
+ {
+ nsISupports *bISupports = nsnull, *cISupports = nsnull;
+
+ proxyObject->Test3(foo, &bISupports);
+ proxyObject->Test3(bISupports, &cISupports);
+
+ nsITestProxy *test;
+ bISupports->QueryInterface(NS_GET_IID(nsITestProxy), (void**)&test);
+
+ test->Test2();
+
+ NS_RELEASE(foo);
+ NS_RELEASE(proxyObject);
+ }
+}
+
+
+
+
+
+/***************************************************************************/
+/* ProxyTest */
+/***************************************************************************/
+
+static void PR_CALLBACK ProxyTest( void *arg )
+{
+ //TestCase_TwoClassesOneInterface(arg);
+ // TestCase_2(arg);
+ //TestCase_nsISupports(arg);
+ TestCase_NestedLoop(arg);
+
+ NS_RELEASE( ((ArgsStruct*) arg)->queue);
+ free((void*) arg);
+}
+
+nsIEventQueue *gEventQueue = nsnull;
+
+static void PR_CALLBACK EventLoop( void *arg )
+{
+ nsresult rv;
+ printf("Creating EventQueue...\n");
+
+ nsIEventQueue* eventQ;
+ nsCOMPtr<nsIEventQueueService> eventQService =
+ do_GetService(kEventQueueServiceCID, &rv);
+ if (NS_SUCCEEDED(rv)) {
+ rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ);
+ if (NS_FAILED(rv))
+ rv = eventQService->CreateThreadEventQueue();
+ if (NS_FAILED(rv))
+ return;
+ else
+ rv = eventQService->GetThreadEventQueue(NS_CURRENT_THREAD, &eventQ);
+ }
+ if (NS_FAILED(rv)) return;
+
+ rv = eventQ->QueryInterface(NS_GET_IID(nsIEventQueue), (void**)&gEventQueue);
+ if (NS_FAILED(rv)) return;
+
+
+ printf("Verifing calling Proxy on eventQ thread.\n");
+
+ nsIProxyObjectManager* manager;
+
+ nsServiceManager::GetService( NS_XPCOMPROXY_CONTRACTID,
+ NS_GET_IID(nsIProxyObjectManager),
+ (nsISupports **)&manager);
+
+ PR_ASSERT(manager);
+
+ nsITestProxy *proxyObject;
+ nsTestXPCFoo* foo = new nsTestXPCFoo();
+
+ PR_ASSERT(foo);
+
+ manager->GetProxyForObject(gEventQueue, NS_GET_IID(nsITestProxy), foo, PROXY_SYNC, (void**)&proxyObject);
+
+ PRInt32 a;
+ proxyObject->Test(1, 2, &a);
+ proxyObject->Test2();
+
+
+ NS_RELEASE(proxyObject);
+ delete foo;
+
+ printf("End of Verification calling Proxy on eventQ thread.\n");
+
+
+ printf("Looping for events.\n");
+
+ PLEvent* event = nsnull;
+
+ while ( PR_SUCCESS == PR_Sleep( PR_MillisecondsToInterval(1)) )
+ {
+ rv = gEventQueue->GetEvent(&event);
+ if (NS_FAILED(rv))
+ return;
+ gEventQueue->HandleEvent(event);
+ }
+
+ gEventQueue->ProcessPendingEvents();
+
+ printf("Closing down Event Queue.\n");
+ delete gEventQueue;
+ gEventQueue = nsnull;
+
+ printf("End looping for events.\n\n");
+}
+
+int
+main(int argc, char **argv)
+{
+ int numberOfThreads = 1;
+
+ if (argc > 1)
+ numberOfThreads = atoi(argv[1]);
+
+ nsCOMPtr<nsIServiceManager> servMan;
+ NS_InitXPCOM2(getter_AddRefs(servMan), nsnull, nsnull);
+ nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan);
+ NS_ASSERTION(registrar, "Null nsIComponentRegistrar");
+ registrar->AutoRegister(nsnull);
+
+ static PRThread** threads = (PRThread**) calloc(sizeof(PRThread*), numberOfThreads);
+ static PRThread* aEventThread;
+
+ aEventThread = PR_CreateThread(PR_USER_THREAD,
+ EventLoop,
+ NULL,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0 );
+
+
+ PR_Sleep(PR_MillisecondsToInterval(1000));
+
+ NS_ASSERTION(gEventQueue, "no main event queue"); // BAD BAD BAD. EVENT THREAD DID NOT CREATE QUEUE. This may be a timing issue, set the
+ // sleep about longer, and try again.
+
+ printf("Spawn Threads:\n");
+ for (PRInt32 spawn = 0; spawn < numberOfThreads; spawn++)
+ {
+
+ ArgsStruct *args = (ArgsStruct *) malloc (sizeof(ArgsStruct));
+
+ args->queue = gEventQueue;
+ NS_ADDREF(args->queue);
+ args->threadNumber = spawn;
+
+ threads[spawn] = PR_CreateThread(PR_USER_THREAD,
+ ProxyTest,
+ args,
+ PR_PRIORITY_NORMAL,
+ PR_GLOBAL_THREAD,
+ PR_JOINABLE_THREAD,
+ 0 );
+
+ printf("\tThread (%d) spawned\n", spawn);
+
+ PR_Sleep( PR_MillisecondsToInterval(250) );
+ }
+
+ printf("All Threads Spawned.\n\n");
+
+
+
+ printf("Wait for threads.\n");
+ for (PRInt32 i = 0; i < numberOfThreads; i++)
+ {
+ PRStatus rv;
+ printf("Thread (%d) Join...\n", i);
+ rv = PR_JoinThread(threads[i]);
+ printf("Thread (%d) Joined. (error: %d).\n", i, rv);
+ }
+
+ PR_Interrupt(aEventThread);
+ PR_JoinThread(aEventThread);
+
+
+ printf("Calling Cleanup.\n");
+ PR_Cleanup();
+
+ printf("Return zero.\n");
+ return 0;
+}