зеркало из https://github.com/mozilla/pjs.git
Bug 239562 64bit safe code for liveconnect (WinXP AMD64)
r=xiaobin.lu, sr=brendan a) renamed jsobject to lcjsobject, b) defined lcjsobject as jint on 32-bit platform or as jlong on 64-bit platform.
This commit is contained in:
Родитель
e8f4310c7e
Коммит
b6f50a432d
|
@ -269,16 +269,10 @@ jsj_WrapJSObject(JSContext *cx, JNIEnv *jEnv, JSObject *js_obj)
|
|||
/* Create a new Java object that wraps the JavaScript object by storing its
|
||||
address in a private integer field. */
|
||||
#ifndef OJI
|
||||
#if JS_BYTES_PER_LONG == 8
|
||||
java_wrapper_obj =
|
||||
(*jEnv)->NewObject(jEnv, njJSObject, njJSObject_JSObject, (jlong)handle);
|
||||
#else
|
||||
java_wrapper_obj =
|
||||
(*jEnv)->NewObject(jEnv, njJSObject, njJSObject_JSObject, (jint)handle);
|
||||
#endif
|
||||
#else
|
||||
(*jEnv)->NewObject(jEnv, njJSObject, njJSObject_JSObject, (lcjsobject)handle);
|
||||
if (JSJ_callbacks && JSJ_callbacks->get_java_wrapper != NULL) {
|
||||
java_wrapper_obj = JSJ_callbacks->get_java_wrapper(jEnv, (jint)handle);
|
||||
java_wrapper_obj = JSJ_callbacks->get_java_wrapper(jEnv, (lcjsobject)handle);
|
||||
} else {
|
||||
java_wrapper_obj = NULL;
|
||||
}
|
||||
|
@ -321,8 +315,13 @@ jsj_UnwrapJSObjectWrapper(JNIEnv *jEnv, jobject java_wrapper_obj)
|
|||
}
|
||||
else {
|
||||
jclass cid = (*jEnv)->GetObjectClass(jEnv, java_wrapper_obj);
|
||||
#if JS_BYTES_PER_LONG == 8
|
||||
jfieldID fid = (*jEnv)->GetFieldID(jEnv, cid, "nativeJSObject", "J");
|
||||
handle = (JSObjectHandle*)((*jEnv)->GetLongField(jEnv, java_wrapper_obj, fid));
|
||||
#else
|
||||
jfieldID fid = (*jEnv)->GetFieldID(jEnv, cid, "nativeJSObject", "I");
|
||||
handle = (JSObjectHandle*)((*jEnv)->GetIntField(jEnv, java_wrapper_obj, fid));
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -56,6 +56,12 @@ JS_BEGIN_EXTERN_C
|
|||
#include "jni.h" /* Java Native Interface */
|
||||
#include "jsapi.h" /* JavaScript engine API */
|
||||
|
||||
#if JS_BYTES_PER_LONG == 8
|
||||
typedef jlong lcjsobject;
|
||||
#else
|
||||
typedef jint lcjsobject;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A JSJavaVM structure is a wrapper around a JavaVM which incorporates
|
||||
* additional LiveConnect state.
|
||||
|
@ -146,11 +152,11 @@ typedef struct JSJCallbacks {
|
|||
/* This enables liveconnect to ask the VM for a java wrapper so that VM gets a chance to
|
||||
store a mapping between a jsobject and java wrapper. So the unwrapping can be done on the
|
||||
VM side before calling nsILiveconnect apis. This saves on a round trip request. */
|
||||
jobject (*get_java_wrapper)(JNIEnv *jEnv, jint jsobject);
|
||||
jobject (*get_java_wrapper)(JNIEnv *jEnv, lcjsobject jsobj);
|
||||
|
||||
/* This allows liveconnect to unwrap a wrapped JSObject that is passed from java to js.
|
||||
This happens when Java code is passing back to JS an object that it got from JS. */
|
||||
jint (*unwrap_java_wrapper)(JNIEnv *jEnv, jobject java_wrapper);
|
||||
lcjsobject (*unwrap_java_wrapper)(JNIEnv *jEnv, jobject java_wrapper);
|
||||
|
||||
/* The following set of methods abstract over the JavaVM object. */
|
||||
JSBool (*create_java_vm)(SystemJavaVM* *jvm, JNIEnv* *initialEnv, void* initargs);
|
||||
|
|
|
@ -243,7 +243,7 @@ nsCLiveconnect::AggregatedQueryInterface(const nsIID& aIID, void** aInstancePtr)
|
|||
* wrapped up as java wrapper netscape.javascript.JSObject.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::GetMember(JNIEnv *jEnv, jsobject obj, const jchar *name, jsize length, void* principalsArray[],
|
||||
nsCLiveconnect::GetMember(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports, jobject *pjobj)
|
||||
{
|
||||
if(jEnv == NULL || obj == 0)
|
||||
|
@ -301,7 +301,7 @@ done:
|
|||
* the member.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::GetSlot(JNIEnv *jEnv, jsobject obj, jint slot, void* principalsArray[],
|
||||
nsCLiveconnect::GetSlot(JNIEnv *jEnv, lcjsobject obj, jint slot, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports, jobject *pjobj)
|
||||
{
|
||||
if(jEnv == NULL || obj == 0)
|
||||
|
@ -354,7 +354,7 @@ done:
|
|||
* then a internal mapping is consulted to convert to a NJSObject.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::SetMember(JNIEnv *jEnv, jsobject obj, const jchar *name, jsize length, jobject java_obj, void* principalsArray[],
|
||||
nsCLiveconnect::SetMember(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, jobject java_obj, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports)
|
||||
{
|
||||
if(jEnv == NULL || obj == 0)
|
||||
|
@ -404,7 +404,7 @@ done:
|
|||
* then a internal mapping is consulted to convert to a NJSObject.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::SetSlot(JNIEnv *jEnv, jsobject obj, jint slot, jobject java_obj, void* principalsArray[],
|
||||
nsCLiveconnect::SetSlot(JNIEnv *jEnv, lcjsobject obj, jint slot, jobject java_obj, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports)
|
||||
{
|
||||
if(jEnv == NULL || obj == 0)
|
||||
|
@ -445,7 +445,7 @@ done:
|
|||
* @param name - Name of a member.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::RemoveMember(JNIEnv *jEnv, jsobject obj, const jchar *name, jsize length, void* principalsArray[],
|
||||
nsCLiveconnect::RemoveMember(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports)
|
||||
{
|
||||
if(jEnv == NULL || obj == 0)
|
||||
|
@ -491,7 +491,7 @@ done:
|
|||
* @param pjobj - return value.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::Call(JNIEnv *jEnv, jsobject obj, const jchar *name, jsize length, jobjectArray java_args, void* principalsArray[],
|
||||
nsCLiveconnect::Call(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, jobjectArray java_args, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports, jobject *pjobj)
|
||||
{
|
||||
if(jEnv == NULL || obj == 0)
|
||||
|
@ -573,7 +573,7 @@ done:
|
|||
}
|
||||
|
||||
NS_METHOD
|
||||
nsCLiveconnect::Eval(JNIEnv *jEnv, jsobject obj, const jchar *script, jsize length, void* principalsArray[],
|
||||
nsCLiveconnect::Eval(JNIEnv *jEnv, lcjsobject obj, const jchar *script, jsize length, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports, jobject *pjobj)
|
||||
{
|
||||
if(jEnv == NULL || obj == 0)
|
||||
|
@ -648,7 +648,7 @@ done:
|
|||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::GetWindow(JNIEnv *jEnv, void *pJavaObject, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports, jsobject *pobj)
|
||||
int numPrincipals, nsISupports *securitySupports, lcjsobject *pobj)
|
||||
{
|
||||
if(jEnv == NULL || JSJ_callbacks == NULL)
|
||||
{
|
||||
|
@ -695,7 +695,7 @@ nsCLiveconnect::GetWindow(JNIEnv *jEnv, void *pJavaObject, void* principalsArra
|
|||
handle->js_obj = js_obj;
|
||||
handle->rt = JS_GetRuntime(cx);
|
||||
}
|
||||
*pobj = (jsobject)NS_PTR_TO_INT32(handle);
|
||||
*pobj = (lcjsobject)handle;
|
||||
/* FIXME: what if the window is explicitly disposed of, how do we
|
||||
notify Java? */
|
||||
#endif
|
||||
|
@ -713,7 +713,7 @@ done:
|
|||
* @param obj - A Native JS Object.
|
||||
*/
|
||||
NS_METHOD
|
||||
nsCLiveconnect::FinalizeJSObject(JNIEnv *jEnv, jsobject obj)
|
||||
nsCLiveconnect::FinalizeJSObject(JNIEnv *jEnv, lcjsobject obj)
|
||||
{
|
||||
if(jEnv == NULL || obj == 0)
|
||||
{
|
||||
|
@ -731,7 +731,7 @@ nsCLiveconnect::FinalizeJSObject(JNIEnv *jEnv, jsobject obj)
|
|||
|
||||
|
||||
NS_METHOD
|
||||
nsCLiveconnect::ToString(JNIEnv *jEnv, jsobject obj, jstring *pjstring)
|
||||
nsCLiveconnect::ToString(JNIEnv *jEnv, lcjsobject obj, jstring *pjstring)
|
||||
{
|
||||
if(jEnv == NULL || obj == 0)
|
||||
{
|
||||
|
|
|
@ -77,7 +77,7 @@ public:
|
|||
* wrapped up as java wrapper netscape.javascript.JSObject.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
GetMember(JNIEnv *jEnv, jsobject obj, const jchar *name, jsize length, void* principalsArray[],
|
||||
GetMember(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports, jobject *pjobj);
|
||||
|
||||
/**
|
||||
|
@ -89,7 +89,7 @@ public:
|
|||
* the member.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
GetSlot(JNIEnv *jEnv, jsobject obj, jint slot, void* principalsArray[],
|
||||
GetSlot(JNIEnv *jEnv, lcjsobject obj, jint slot, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports, jobject *pjobj);
|
||||
|
||||
/**
|
||||
|
@ -102,7 +102,7 @@ public:
|
|||
* then a internal mapping is consulted to convert to a NJSObject.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
SetMember(JNIEnv *jEnv, jsobject obj, const jchar *name, jsize length, jobject jobj, void* principalsArray[],
|
||||
SetMember(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, jobject jobj, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports);
|
||||
|
||||
/**
|
||||
|
@ -115,7 +115,7 @@ public:
|
|||
* then a internal mapping is consulted to convert to a NJSObject.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
SetSlot(JNIEnv *jEnv, jsobject obj, jint slot, jobject jobj, void* principalsArray[],
|
||||
SetSlot(JNIEnv *jEnv, lcjsobject obj, jint slot, jobject jobj, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports);
|
||||
|
||||
/**
|
||||
|
@ -125,7 +125,7 @@ public:
|
|||
* @param name - Name of a member.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
RemoveMember(JNIEnv *jEnv, jsobject obj, const jchar *name, jsize length, void* principalsArray[],
|
||||
RemoveMember(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports);
|
||||
|
||||
/**
|
||||
|
@ -137,7 +137,7 @@ public:
|
|||
* @param pjobj - return value.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
Call(JNIEnv *jEnv, jsobject obj, const jchar *name, jsize length, jobjectArray jobjArr, void* principalsArray[],
|
||||
Call(JNIEnv *jEnv, lcjsobject obj, const jchar *name, jsize length, jobjectArray jobjArr, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports, jobject *pjobj);
|
||||
|
||||
/**
|
||||
|
@ -150,7 +150,7 @@ public:
|
|||
* @param pjobj - return value.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
Eval(JNIEnv *jEnv, jsobject obj, const jchar *script, jsize length, void* principalsArray[],
|
||||
Eval(JNIEnv *jEnv, lcjsobject obj, const jchar *script, jsize length, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports, jobject *pjobj);
|
||||
|
||||
/**
|
||||
|
@ -164,7 +164,7 @@ public:
|
|||
*/
|
||||
NS_IMETHOD
|
||||
GetWindow(JNIEnv *jEnv, void *pJavaObject, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports, jsobject *pobj);
|
||||
int numPrincipals, nsISupports *securitySupports, lcjsobject *pobj);
|
||||
|
||||
/**
|
||||
* Get the window object for a plugin instance.
|
||||
|
@ -173,7 +173,7 @@ public:
|
|||
* @param obj - A Native JS Object.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
FinalizeJSObject(JNIEnv *jEnv, jsobject obj);
|
||||
FinalizeJSObject(JNIEnv *jEnv, lcjsobject obj);
|
||||
|
||||
/**
|
||||
* Get the window object for a plugin instance.
|
||||
|
@ -183,7 +183,7 @@ public:
|
|||
* @param jstring - Return value as a jstring representing a JS object.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
ToString(JNIEnv *jEnv, jsobject obj, jstring *pjstring);
|
||||
ToString(JNIEnv *jEnv, lcjsobject obj, jstring *pjstring);
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
// from nsCLiveconnect:
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "nsISupports.h"
|
||||
#include "nsIFactory.h"
|
||||
#include "jni.h"
|
||||
#include "jsjava.h" // For lcjsobject
|
||||
|
||||
#define NS_ILIVECONNECT_IID \
|
||||
{ /* 68190910-3318-11d2-97f0-00805f8a28d0 */ \
|
||||
|
@ -66,8 +67,6 @@
|
|||
{0x97, 0xf0, 0x00, 0x80, 0x5f, 0x8a, 0x28, 0xd0} \
|
||||
}
|
||||
|
||||
typedef jint jsobject;
|
||||
|
||||
class nsILiveconnect : public nsISupports {
|
||||
public:
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_ILIVECONNECT_IID)
|
||||
|
@ -84,7 +83,7 @@ public:
|
|||
* wrapped up as java wrapper netscape.javascript.JSObject.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
GetMember(JNIEnv *jEnv, jsobject jsobj, const jchar *name, jsize length, void* principalsArray[],
|
||||
GetMember(JNIEnv *jEnv, lcjsobject jsobj, const jchar *name, jsize length, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports, jobject *pjobj) = 0;
|
||||
|
||||
/**
|
||||
|
@ -96,7 +95,7 @@ public:
|
|||
* the member.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
GetSlot(JNIEnv *jEnv, jsobject jsobj, jint slot, void* principalsArray[],
|
||||
GetSlot(JNIEnv *jEnv, lcjsobject jsobj, jint slot, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports, jobject *pjobj) = 0;
|
||||
|
||||
/**
|
||||
|
@ -109,7 +108,7 @@ public:
|
|||
* then a internal mapping is consulted to convert to a NJSObject.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
SetMember(JNIEnv *jEnv, jsobject jsobj, const jchar* name, jsize length, jobject jobj, void* principalsArray[],
|
||||
SetMember(JNIEnv *jEnv, lcjsobject jsobj, const jchar* name, jsize length, jobject jobj, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports) = 0;
|
||||
|
||||
/**
|
||||
|
@ -122,7 +121,7 @@ public:
|
|||
* then a internal mapping is consulted to convert to a NJSObject.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
SetSlot(JNIEnv *jEnv, jsobject jsobj, jint slot, jobject jobj, void* principalsArray[],
|
||||
SetSlot(JNIEnv *jEnv, lcjsobject jsobj, jint slot, jobject jobj, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports) = 0;
|
||||
|
||||
/**
|
||||
|
@ -132,7 +131,7 @@ public:
|
|||
* @param name - Name of a member.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
RemoveMember(JNIEnv *jEnv, jsobject jsobj, const jchar* name, jsize length, void* principalsArray[],
|
||||
RemoveMember(JNIEnv *jEnv, lcjsobject jsobj, const jchar* name, jsize length, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports) = 0;
|
||||
|
||||
/**
|
||||
|
@ -144,7 +143,7 @@ public:
|
|||
* @param pjobj - return value.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
Call(JNIEnv *jEnv, jsobject jsobj, const jchar* name, jsize length, jobjectArray jobjArr, void* principalsArray[],
|
||||
Call(JNIEnv *jEnv, lcjsobject jsobj, const jchar* name, jsize length, jobjectArray jobjArr, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports, jobject *pjobj) = 0;
|
||||
|
||||
/**
|
||||
|
@ -157,7 +156,7 @@ public:
|
|||
* @param pjobj - return value.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
Eval(JNIEnv *jEnv, jsobject obj, const jchar *script, jsize length, void* principalsArray[],
|
||||
Eval(JNIEnv *jEnv, lcjsobject obj, const jchar *script, jsize length, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports, jobject *pjobj) = 0;
|
||||
|
||||
/**
|
||||
|
@ -171,7 +170,7 @@ public:
|
|||
*/
|
||||
NS_IMETHOD
|
||||
GetWindow(JNIEnv *jEnv, void *pJavaObject, void* principalsArray[],
|
||||
int numPrincipals, nsISupports *securitySupports, jsobject *pobj) = 0;
|
||||
int numPrincipals, nsISupports *securitySupports, lcjsobject *pobj) = 0;
|
||||
|
||||
/**
|
||||
* Get the window object for a plugin instance.
|
||||
|
@ -180,7 +179,7 @@ public:
|
|||
* @param obj - A Native JS Object.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
FinalizeJSObject(JNIEnv *jEnv, jsobject jsobj) = 0;
|
||||
FinalizeJSObject(JNIEnv *jEnv, lcjsobject jsobj) = 0;
|
||||
|
||||
/**
|
||||
* Get the window object for a plugin instance.
|
||||
|
@ -190,7 +189,7 @@ public:
|
|||
* @param jstring - Return value as a jstring representing a JS object.
|
||||
*/
|
||||
NS_IMETHOD
|
||||
ToString(JNIEnv *jEnv, jsobject obj, jstring *pjstring) = 0;
|
||||
ToString(JNIEnv *jEnv, lcjsobject obj, jstring *pjstring) = 0;
|
||||
};
|
||||
|
||||
#endif // nsILiveconnect_h___
|
||||
|
|
|
@ -51,6 +51,7 @@
|
|||
#include "nsISupports.h"
|
||||
#include "nsIPrincipal.h"
|
||||
#include "jni.h"
|
||||
#include "jsjava.h" // for lcjsobject
|
||||
|
||||
class nsISecureEnv;
|
||||
|
||||
|
@ -90,7 +91,7 @@ public:
|
|||
GetClassPath(const char* *result) = 0;
|
||||
|
||||
NS_IMETHOD
|
||||
GetJavaWrapper(JNIEnv* jenv, jint obj, jobject *jobj) = 0;
|
||||
GetJavaWrapper(JNIEnv* jenv, lcjsobject obj, jobject *jobj) = 0;
|
||||
|
||||
/**
|
||||
* This creates a new secure communication channel with Java. The second parameter,
|
||||
|
@ -110,7 +111,7 @@ public:
|
|||
SpendTime(PRUint32 timeMillis) = 0;
|
||||
|
||||
NS_IMETHOD
|
||||
UnwrapJavaWrapper(JNIEnv* jenv, jobject jobj, jint* obj) = 0;
|
||||
UnwrapJavaWrapper(JNIEnv* jenv, jobject jobj, lcjsobject* obj) = 0;
|
||||
|
||||
NS_DEFINE_STATIC_IID_ACCESSOR(NS_IJVMPLUGIN_IID)
|
||||
};
|
||||
|
|
|
@ -267,7 +267,7 @@ get_JSPrincipals_from_java_caller_impl(JNIEnv *pJNIEnv, JSContext *pJSContext, v
|
|||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(jobject)
|
||||
get_java_wrapper_impl(JNIEnv *pJNIEnv, jint a_jsobject)
|
||||
get_java_wrapper_impl(JNIEnv *pJNIEnv, lcjsobject a_jsobject)
|
||||
{
|
||||
nsresult err = NS_OK;
|
||||
jobject pJSObjectWrapper = NULL;
|
||||
|
@ -287,10 +287,10 @@ get_java_wrapper_impl(JNIEnv *pJNIEnv, jint a_jsobject)
|
|||
return pJSObjectWrapper;
|
||||
}
|
||||
|
||||
JS_STATIC_DLL_CALLBACK(jint)
|
||||
JS_STATIC_DLL_CALLBACK(lcjsobject)
|
||||
unwrap_java_wrapper_impl(JNIEnv *pJNIEnv, jobject java_wrapper)
|
||||
{
|
||||
jint obj = 0;
|
||||
lcjsobject obj = 0;
|
||||
nsresult err = NS_OK;
|
||||
nsCOMPtr<nsIJVMManager> managerService = do_GetService(kJVMManagerCID, &err);
|
||||
if (NS_FAILED(err)) return 0;
|
||||
|
|
Загрузка…
Ссылка в новой задаче