michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "xpctest_private.h" michael@0: #include "xpctest_interfaces.h" michael@0: #include "js/Value.h" michael@0: michael@0: NS_IMPL_ISUPPORTS(nsXPCTestParams, nsIXPCTestParams) michael@0: michael@0: nsXPCTestParams::nsXPCTestParams() michael@0: { michael@0: } michael@0: michael@0: nsXPCTestParams::~nsXPCTestParams() michael@0: { michael@0: } michael@0: michael@0: #define GENERIC_METHOD_IMPL { \ michael@0: *_retval = *b; \ michael@0: *b = a; \ michael@0: return NS_OK; \ michael@0: } michael@0: michael@0: #define STRING_METHOD_IMPL { \ michael@0: _retval.Assign(b); \ michael@0: b.Assign(a); \ michael@0: return NS_OK; \ michael@0: } michael@0: michael@0: #define TAKE_OWNERSHIP_NOOP(val) {} michael@0: #define TAKE_OWNERSHIP_INTERFACE(val) {static_cast(val)->AddRef();} michael@0: #define TAKE_OWNERSHIP_STRING(val) { \ michael@0: nsDependentCString vprime(val); \ michael@0: val = ToNewCString(vprime); \ michael@0: } michael@0: #define TAKE_OWNERSHIP_WSTRING(val) { \ michael@0: nsDependentString vprime(val); \ michael@0: val = ToNewUnicode(vprime); \ michael@0: } michael@0: michael@0: // Macro for our buffer-oriented types: michael@0: // 'type' is the type of element that the buffer contains. michael@0: // 'padding' is an offset added to length, allowing us to handle michael@0: // null-terminated strings. michael@0: // 'TAKE_OWNERSHIP' is one of the macros above. michael@0: #define BUFFER_METHOD_IMPL(type, padding, TAKE_OWNERSHIP) { \ michael@0: uint32_t elemSize = sizeof(type); \ michael@0: \ michael@0: /* Copy b into rv. */ \ michael@0: *rvLength = *bLength; \ michael@0: *rv = static_cast(NS_Alloc(elemSize * (*bLength + padding))); \ michael@0: if (!*rv) \ michael@0: return NS_ERROR_OUT_OF_MEMORY; \ michael@0: memcpy(*rv, *b, elemSize * (*bLength + padding)); \ michael@0: \ michael@0: /* Copy a into b. */ \ michael@0: *bLength = aLength; \ michael@0: NS_Free(*b); \ michael@0: *b = static_cast(NS_Alloc(elemSize * (aLength + padding))); \ michael@0: if (!*b) \ michael@0: return NS_ERROR_OUT_OF_MEMORY; \ michael@0: memcpy(*b, a, elemSize * (aLength + padding)); \ michael@0: \ michael@0: /* We need to take ownership of the data we got from a, \ michael@0: since the caller owns it. */ \ michael@0: for (unsigned i = 0; i < *bLength + padding; ++i) \ michael@0: TAKE_OWNERSHIP((*b)[i]); \ michael@0: \ michael@0: return NS_OK; \ michael@0: } michael@0: michael@0: /* boolean testBoolean (in boolean a, inout boolean b); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestBoolean(bool a, bool *b, bool *_retval) michael@0: { michael@0: GENERIC_METHOD_IMPL; michael@0: } michael@0: michael@0: /* octet testOctet (in octet a, inout octet b); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestOctet(uint8_t a, uint8_t *b, uint8_t *_retval) michael@0: { michael@0: GENERIC_METHOD_IMPL; michael@0: } michael@0: michael@0: /* short testShort (in short a, inout short b); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestShort(int16_t a, int16_t *b, int16_t *_retval) michael@0: { michael@0: GENERIC_METHOD_IMPL; michael@0: } michael@0: michael@0: /* long testLong (in long a, inout long b); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestLong(int32_t a, int32_t *b, int32_t *_retval) michael@0: { michael@0: GENERIC_METHOD_IMPL; michael@0: } michael@0: michael@0: /* long long testLongLong (in long long a, inout long long b); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestLongLong(int64_t a, int64_t *b, int64_t *_retval) michael@0: { michael@0: GENERIC_METHOD_IMPL; michael@0: } michael@0: michael@0: /* unsigned short testUnsignedShort (in unsigned short a, inout unsigned short b); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestUnsignedShort(uint16_t a, uint16_t *b, uint16_t *_retval) michael@0: { michael@0: GENERIC_METHOD_IMPL; michael@0: } michael@0: michael@0: /* unsigned long testUnsignedLong (in unsigned long a, inout unsigned long b); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestUnsignedLong(uint32_t a, uint32_t *b, uint32_t *_retval) michael@0: { michael@0: GENERIC_METHOD_IMPL; michael@0: } michael@0: michael@0: /* unsigned long long testUnsignedLongLong (in unsigned long long a, inout unsigned long long b); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestUnsignedLongLong(uint64_t a, uint64_t *b, uint64_t *_retval) michael@0: { michael@0: GENERIC_METHOD_IMPL; michael@0: } michael@0: michael@0: /* float testFloat (in float a, inout float b); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestFloat(float a, float *b, float *_retval) michael@0: { michael@0: GENERIC_METHOD_IMPL; michael@0: } michael@0: michael@0: /* double testDouble (in double a, inout float b); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestDouble(double a, float *b, double *_retval) michael@0: { michael@0: GENERIC_METHOD_IMPL; michael@0: } michael@0: michael@0: /* char testChar (in char a, inout char b); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestChar(char a, char *b, char *_retval) michael@0: { michael@0: GENERIC_METHOD_IMPL; michael@0: } michael@0: michael@0: /* string testString (in string a, inout string b); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestString(const char * a, char * *b, char * *_retval) michael@0: { michael@0: nsDependentCString aprime(a); michael@0: nsDependentCString bprime(*b); michael@0: *_retval = ToNewCString(bprime); michael@0: *b = ToNewCString(aprime); michael@0: michael@0: // XPCOM ownership rules dictate that overwritten inout params must be callee-freed. michael@0: // See https://developer.mozilla.org/en/XPIDL michael@0: NS_Free(const_cast(bprime.get())); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* wchar testWchar (in wchar a, inout wchar b); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestWchar(char16_t a, char16_t *b, char16_t *_retval) michael@0: { michael@0: GENERIC_METHOD_IMPL; michael@0: } michael@0: michael@0: /* wstring testWstring (in wstring a, inout wstring b); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestWstring(const char16_t * a, char16_t * *b, char16_t * *_retval) michael@0: { michael@0: nsDependentString aprime(a); michael@0: nsDependentString bprime(*b); michael@0: *_retval = ToNewUnicode(bprime); michael@0: *b = ToNewUnicode(aprime); michael@0: michael@0: // XPCOM ownership rules dictate that overwritten inout params must be callee-freed. michael@0: // See https://developer.mozilla.org/en/XPIDL michael@0: NS_Free((void*)bprime.get()); michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* DOMString testDOMString (in DOMString a, inout DOMString b); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestDOMString(const nsAString & a, nsAString & b, nsAString & _retval) michael@0: { michael@0: STRING_METHOD_IMPL; michael@0: } michael@0: michael@0: michael@0: /* AString testAString (in AString a, inout AString b); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestAString(const nsAString & a, nsAString & b, nsAString & _retval) michael@0: { michael@0: STRING_METHOD_IMPL; michael@0: } michael@0: michael@0: /* AUTF8String testAUTF8String (in AUTF8String a, inout AUTF8String b); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestAUTF8String(const nsACString & a, nsACString & b, nsACString & _retval) michael@0: { michael@0: STRING_METHOD_IMPL; michael@0: } michael@0: michael@0: /* ACString testACString (in ACString a, inout ACString b); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestACString(const nsACString & a, nsACString & b, nsACString & _retval) michael@0: { michael@0: STRING_METHOD_IMPL; michael@0: } michael@0: michael@0: /* jsval testJsval (in jsval a, in jsval b); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestJsval(JS::Handle a, michael@0: JS::MutableHandle b, michael@0: JS::MutableHandle _retval) michael@0: { michael@0: _retval.set(b); michael@0: b.set(a); michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void testShortArray (in unsigned long aLength, [array, size_is (aLength)] in short a, michael@0: * inout unsigned long bLength, [array, size_is (bLength)] inout short b, michael@0: * out unsigned long rvLength, [array, size_is (rvLength), retval] out short rv); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestShortArray(uint32_t aLength, int16_t *a, michael@0: uint32_t *bLength, int16_t **b, michael@0: uint32_t *rvLength, int16_t **rv) michael@0: { michael@0: BUFFER_METHOD_IMPL(int16_t, 0, TAKE_OWNERSHIP_NOOP); michael@0: } michael@0: michael@0: /* void testDoubleArray (in unsigned long aLength, [array, size_is (aLength)] in double a, michael@0: * inout unsigned long bLength, [array, size_is (bLength)] inout double b, michael@0: * out unsigned long rvLength, [array, size_is (rvLength), retval] out double rv); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestDoubleArray(uint32_t aLength, double *a, michael@0: uint32_t *bLength, double **b, michael@0: uint32_t *rvLength, double **rv) michael@0: { michael@0: BUFFER_METHOD_IMPL(double, 0, TAKE_OWNERSHIP_NOOP); michael@0: } michael@0: michael@0: /* void testStringArray (in unsigned long aLength, [array, size_is (aLength)] in string a, michael@0: * inout unsigned long bLength, [array, size_is (bLength)] inout string b, michael@0: * out unsigned long rvLength, [array, size_is (rvLength), retval] out string rv); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestStringArray(uint32_t aLength, const char * *a, michael@0: uint32_t *bLength, char * **b, michael@0: uint32_t *rvLength, char * **rv) michael@0: { michael@0: BUFFER_METHOD_IMPL(char*, 0, TAKE_OWNERSHIP_STRING); michael@0: } michael@0: michael@0: /* void testWstringArray (in unsigned long aLength, [array, size_is (aLength)] in wstring a, michael@0: * inout unsigned long bLength, [array, size_is (bLength)] inout wstring b, michael@0: * out unsigned long rvLength, [array, size_is (rvLength), retval] out wstring rv); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestWstringArray(uint32_t aLength, const char16_t * *a, michael@0: uint32_t *bLength, char16_t * **b, michael@0: uint32_t *rvLength, char16_t * **rv) michael@0: { michael@0: BUFFER_METHOD_IMPL(char16_t*, 0, TAKE_OWNERSHIP_WSTRING); michael@0: } michael@0: michael@0: /* void testInterfaceArray (in unsigned long aLength, [array, size_is (aLength)] in nsIXPCTestInterfaceA a, michael@0: * inout unsigned long bLength, [array, size_is (bLength)] inout nsIXPCTestInterfaceA b, michael@0: * out unsigned long rvLength, [array, size_is (rvLength), retval] out nsIXPCTestInterfaceA rv); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestInterfaceArray(uint32_t aLength, nsIXPCTestInterfaceA **a, michael@0: uint32_t *bLength, nsIXPCTestInterfaceA * **b, michael@0: uint32_t *rvLength, nsIXPCTestInterfaceA * **rv) michael@0: { michael@0: BUFFER_METHOD_IMPL(nsIXPCTestInterfaceA*, 0, TAKE_OWNERSHIP_INTERFACE); michael@0: } michael@0: michael@0: /* void testSizedString (in unsigned long aLength, [size_is (aLength)] in string a, michael@0: * inout unsigned long bLength, [size_is (bLength)] inout string b, michael@0: * out unsigned long rvLength, [size_is (rvLength), retval] out string rv); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestSizedString(uint32_t aLength, const char * a, michael@0: uint32_t *bLength, char * *b, michael@0: uint32_t *rvLength, char * *rv) michael@0: { michael@0: BUFFER_METHOD_IMPL(char, 1, TAKE_OWNERSHIP_NOOP); michael@0: } michael@0: michael@0: /* void testSizedWstring (in unsigned long aLength, [size_is (aLength)] in wstring a, michael@0: * inout unsigned long bLength, [size_is (bLength)] inout wstring b, michael@0: * out unsigned long rvLength, [size_is (rvLength), retval] out wstring rv); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestSizedWstring(uint32_t aLength, const char16_t * a, michael@0: uint32_t *bLength, char16_t * *b, michael@0: uint32_t *rvLength, char16_t * *rv) michael@0: { michael@0: BUFFER_METHOD_IMPL(char16_t, 1, TAKE_OWNERSHIP_NOOP); michael@0: } michael@0: michael@0: /* void testInterfaceIs (in nsIIDPtr aIID, [iid_is (aIID)] in nsQIResult a, michael@0: * inout nsIIDPtr bIID, [iid_is (bIID)] inout nsQIResult b, michael@0: * out nsIIDPtr rvIID, [iid_is (rvIID), retval] out nsQIResult rv); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestInterfaceIs(const nsIID *aIID, void *a, michael@0: nsIID **bIID, void **b, michael@0: nsIID **rvIID, void **rv) michael@0: { michael@0: // michael@0: // Getting the buffers and ownership right here can be a little tricky. michael@0: // michael@0: michael@0: // The interface pointers are heap-allocated, and b has been AddRef'd michael@0: // by XPConnect for the duration of the call. If we snatch it away from b michael@0: // and leave no trace, XPConnect won't Release it. Since we also need to michael@0: // return an already-AddRef'd pointer in rv, we don't need to do anything michael@0: // special here. michael@0: *rv = *b; michael@0: michael@0: // rvIID is out-only, so nobody allocated an IID buffer for us. Do that now, michael@0: // and store b's IID in the new buffer. michael@0: *rvIID = static_cast(NS_Alloc(sizeof(nsID))); michael@0: if (!*rvIID) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: **rvIID = **bIID; michael@0: michael@0: // Copy the interface pointer from a to b. Since a is in-only, XPConnect will michael@0: // release it upon completion of the call. AddRef it for b. michael@0: *b = a; michael@0: static_cast(*b)->AddRef(); michael@0: michael@0: // We already had a buffer allocated for b's IID, so we can re-use it. michael@0: **bIID = *aIID; michael@0: michael@0: return NS_OK; michael@0: } michael@0: michael@0: /* void testInterfaceIsArray (in unsigned long aLength, in nsIIDPtr aIID, michael@0: * [array, size_is (aLength), iid_is (aIID)] in nsQIResult a, michael@0: * inout unsigned long bLength, inout nsIIDPtr bIID, michael@0: * [array, size_is (bLength), iid_is (bIID)] inout nsQIResult b, michael@0: * out unsigned long rvLength, out nsIIDPtr rvIID, michael@0: * [retval, array, size_is (rvLength), iid_is (rvIID)] out nsQIResult rv); */ michael@0: NS_IMETHODIMP nsXPCTestParams::TestInterfaceIsArray(uint32_t aLength, const nsIID *aIID, michael@0: void **a, michael@0: uint32_t *bLength, nsIID **bIID, michael@0: void ***b, michael@0: uint32_t *rvLength, nsIID **rvIID, michael@0: void ***rv) michael@0: { michael@0: // Transfer the IIDs. See the comments in TestInterfaceIs (above) for an michael@0: // explanation of what we're doing. michael@0: *rvIID = static_cast(NS_Alloc(sizeof(nsID))); michael@0: if (!*rvIID) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: **rvIID = **bIID; michael@0: **bIID = *aIID; michael@0: michael@0: // The macro is agnostic to the actual interface types, so we can re-use code here. michael@0: // michael@0: // Do this second, since the macro returns. michael@0: BUFFER_METHOD_IMPL(void*, 0, TAKE_OWNERSHIP_INTERFACE); michael@0: }