1999-09-21 04:08:25 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
|
|
*
|
2012-05-21 15:12:37 +04:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
1999-09-21 04:08:25 +04:00
|
|
|
|
1999-12-02 06:39:41 +03:00
|
|
|
//
|
|
|
|
// Part of the reason these routines are all in once place is so that as new
|
|
|
|
// data flavors are added that are known to be one-byte or two-byte strings, or
|
|
|
|
// even raw binary data, then we just have to go to one place to change how the
|
|
|
|
// data moves into/out of the primitives and native line endings.
|
|
|
|
//
|
|
|
|
// If you add new flavors that have special consideration (binary data or
|
|
|
|
// one-byte char* strings), please update all the helper classes in this file.
|
|
|
|
//
|
|
|
|
// For now, this is the assumption that we are making:
|
|
|
|
// - text/plain is always a char*
|
2014-01-04 19:02:17 +04:00
|
|
|
// - anything else is a char16_t*
|
1999-12-02 06:39:41 +03:00
|
|
|
//
|
|
|
|
|
1999-09-21 04:08:25 +04:00
|
|
|
#include "nsPrimitiveHelpers.h"
|
2016-01-05 13:08:57 +03:00
|
|
|
|
|
|
|
#include "mozilla/UniquePtr.h"
|
1999-09-21 04:08:25 +04:00
|
|
|
#include "nsCOMPtr.h"
|
2002-09-04 03:36:13 +04:00
|
|
|
#include "nsXPCOM.h"
|
1999-09-21 04:08:25 +04:00
|
|
|
#include "nsISupportsPrimitives.h"
|
|
|
|
#include "nsITransferable.h"
|
|
|
|
#include "nsIComponentManager.h"
|
1999-12-02 06:39:41 +03:00
|
|
|
#include "nsLinebreakConverter.h"
|
2002-08-27 01:20:34 +04:00
|
|
|
#include "nsReadableUtils.h"
|
1999-09-21 04:08:25 +04:00
|
|
|
|
|
|
|
//
|
|
|
|
// CreatePrimitiveForData
|
|
|
|
//
|
|
|
|
// Given some data and the flavor it corresponds to, creates the appropriate
|
|
|
|
// nsISupports* wrapper for passing across IDL boundaries. Right now, everything
|
2002-08-06 04:53:19 +04:00
|
|
|
// creates a two-byte |nsISupportsString|, except for "text/plain" and native
|
2002-05-07 23:45:58 +04:00
|
|
|
// platform HTML (CF_HTML on win32)
|
1999-09-21 04:08:25 +04:00
|
|
|
//
|
2017-08-21 13:01:27 +03:00
|
|
|
void nsPrimitiveHelpers ::CreatePrimitiveForData(const nsACString& aFlavor,
|
|
|
|
const void* aDataBuff,
|
2012-08-22 19:56:38 +04:00
|
|
|
uint32_t aDataLen,
|
|
|
|
nsISupports** aPrimitive) {
|
1999-09-21 04:08:25 +04:00
|
|
|
if (!aPrimitive) return;
|
2018-11-30 13:46:48 +03:00
|
|
|
|
2017-08-21 13:01:27 +03:00
|
|
|
if (aFlavor.EqualsLiteral(kTextMime) ||
|
|
|
|
aFlavor.EqualsLiteral(kNativeHTMLMime) ||
|
|
|
|
aFlavor.EqualsLiteral(kRTFMime) ||
|
|
|
|
aFlavor.EqualsLiteral(kCustomTypesMime)) {
|
2004-11-01 21:50:36 +03:00
|
|
|
nsCOMPtr<nsISupportsCString> primitive =
|
|
|
|
do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID);
|
1999-09-21 04:08:25 +04:00
|
|
|
if (primitive) {
|
2008-08-19 22:28:24 +04:00
|
|
|
const char* start = reinterpret_cast<const char*>(aDataBuff);
|
2002-08-27 01:20:34 +04:00
|
|
|
primitive->SetData(Substring(start, start + aDataLen));
|
2004-11-01 21:50:36 +03:00
|
|
|
NS_ADDREF(*aPrimitive = primitive);
|
1999-09-21 04:08:25 +04:00
|
|
|
}
|
|
|
|
} else {
|
2004-11-01 21:50:36 +03:00
|
|
|
nsCOMPtr<nsISupportsString> primitive =
|
|
|
|
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
|
|
|
|
if (primitive) {
|
2015-04-22 07:21:00 +03:00
|
|
|
if (aDataLen % 2) {
|
2016-01-05 13:08:57 +03:00
|
|
|
auto buffer = mozilla::MakeUnique<char[]>(aDataLen + 1);
|
2012-10-26 17:32:10 +04:00
|
|
|
if (!MOZ_LIKELY(buffer)) return;
|
2015-04-22 07:21:00 +03:00
|
|
|
|
2015-10-30 21:35:28 +03:00
|
|
|
memcpy(buffer.get(), aDataBuff, aDataLen);
|
2008-08-19 22:28:24 +04:00
|
|
|
buffer[aDataLen] = 0;
|
2014-01-04 19:02:17 +04:00
|
|
|
const char16_t* start = reinterpret_cast<const char16_t*>(buffer.get());
|
2008-08-19 22:28:24 +04:00
|
|
|
// recall that length takes length as characters, not bytes
|
|
|
|
primitive->SetData(Substring(start, start + (aDataLen + 1) / 2));
|
|
|
|
} else {
|
2014-01-04 19:02:17 +04:00
|
|
|
const char16_t* start = reinterpret_cast<const char16_t*>(aDataBuff);
|
2008-08-19 22:28:24 +04:00
|
|
|
// recall that length takes length as characters, not bytes
|
|
|
|
primitive->SetData(Substring(start, start + (aDataLen / 2)));
|
|
|
|
}
|
2004-11-01 21:50:36 +03:00
|
|
|
NS_ADDREF(*aPrimitive = primitive);
|
2015-04-22 07:21:00 +03:00
|
|
|
}
|
1999-09-21 04:08:25 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
} // CreatePrimitiveForData
|
|
|
|
|
2015-07-22 09:56:57 +03:00
|
|
|
//
|
|
|
|
// CreatePrimitiveForCFHTML
|
|
|
|
//
|
|
|
|
// Platform specific CreatePrimitive, windows CF_HTML.
|
|
|
|
//
|
|
|
|
void nsPrimitiveHelpers ::CreatePrimitiveForCFHTML(const void* aDataBuff,
|
|
|
|
uint32_t* aDataLen,
|
|
|
|
nsISupports** aPrimitive) {
|
|
|
|
if (!aPrimitive) return;
|
|
|
|
|
|
|
|
nsCOMPtr<nsISupportsString> primitive =
|
|
|
|
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
|
|
|
|
if (!primitive) return;
|
|
|
|
|
|
|
|
// We need to duplicate the input buffer, since the removal of linebreaks
|
|
|
|
// might reallocte it.
|
|
|
|
void* utf8 = moz_xmalloc(*aDataLen);
|
|
|
|
memcpy(utf8, aDataBuff, *aDataLen);
|
|
|
|
int32_t signedLen = static_cast<int32_t>(*aDataLen);
|
2017-08-21 13:01:27 +03:00
|
|
|
nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks(
|
|
|
|
nsDependentCString(kTextMime), &utf8, &signedLen);
|
2015-07-22 09:56:57 +03:00
|
|
|
*aDataLen = signedLen;
|
|
|
|
|
|
|
|
nsAutoString str(
|
|
|
|
NS_ConvertUTF8toUTF16(reinterpret_cast<const char*>(utf8), *aDataLen));
|
|
|
|
free(utf8);
|
|
|
|
*aDataLen = str.Length() * sizeof(char16_t);
|
|
|
|
primitive->SetData(str);
|
|
|
|
NS_ADDREF(*aPrimitive = primitive);
|
|
|
|
}
|
|
|
|
|
1999-09-21 04:08:25 +04:00
|
|
|
//
|
|
|
|
// CreateDataFromPrimitive
|
|
|
|
//
|
|
|
|
// Given a nsISupports* primitive and the flavor it represents, creates a new
|
1999-12-01 01:07:29 +03:00
|
|
|
// data buffer with the data in it. This data will be null terminated, but the
|
|
|
|
// length parameter does not reflect that.
|
1999-09-21 04:08:25 +04:00
|
|
|
//
|
2018-11-09 16:24:28 +03:00
|
|
|
void nsPrimitiveHelpers::CreateDataFromPrimitive(const nsACString& aFlavor,
|
|
|
|
nsISupports* aPrimitive,
|
|
|
|
void** aDataBuff,
|
|
|
|
uint32_t* aDataLen) {
|
1999-09-21 04:08:25 +04:00
|
|
|
if (!aDataBuff) return;
|
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
*aDataBuff = nullptr;
|
2018-11-09 16:24:28 +03:00
|
|
|
*aDataLen = 0;
|
2008-08-27 16:07:27 +04:00
|
|
|
|
2017-08-21 13:01:27 +03:00
|
|
|
if (aFlavor.EqualsLiteral(kTextMime) ||
|
|
|
|
aFlavor.EqualsLiteral(kCustomTypesMime)) {
|
2002-08-06 04:53:19 +04:00
|
|
|
nsCOMPtr<nsISupportsCString> plainText(do_QueryInterface(aPrimitive));
|
2002-08-27 01:20:34 +04:00
|
|
|
if (plainText) {
|
2012-09-02 06:35:17 +04:00
|
|
|
nsAutoCString data;
|
2002-08-27 01:20:34 +04:00
|
|
|
plainText->GetData(data);
|
|
|
|
*aDataBuff = ToNewCString(data);
|
2018-11-09 16:24:28 +03:00
|
|
|
*aDataLen = data.Length() * sizeof(char);
|
2002-08-27 01:20:34 +04:00
|
|
|
}
|
1999-09-21 04:08:25 +04:00
|
|
|
} else {
|
2002-08-06 04:53:19 +04:00
|
|
|
nsCOMPtr<nsISupportsString> doubleByteText(do_QueryInterface(aPrimitive));
|
2002-08-27 01:20:34 +04:00
|
|
|
if (doubleByteText) {
|
|
|
|
nsAutoString data;
|
|
|
|
doubleByteText->GetData(data);
|
2002-08-27 22:15:38 +04:00
|
|
|
*aDataBuff = ToNewUnicode(data);
|
2018-11-09 16:24:28 +03:00
|
|
|
*aDataLen = data.Length() * sizeof(char16_t);
|
2002-08-27 01:20:34 +04:00
|
|
|
}
|
1999-09-21 04:08:25 +04:00
|
|
|
}
|
|
|
|
}
|
1999-12-02 06:39:41 +03:00
|
|
|
|
|
|
|
//
|
|
|
|
// ConvertPlatformToDOMLinebreaks
|
|
|
|
//
|
|
|
|
// Given some data, convert from the platform linebreaks into the LF expected by
|
|
|
|
// the DOM. This will attempt to convert the data in place, but the buffer may
|
|
|
|
// still need to be reallocated regardless (disposing the old buffer is taken
|
|
|
|
// care of internally, see the note below).
|
|
|
|
//
|
2015-05-01 18:01:06 +03:00
|
|
|
// NOTE: this assumes that it can use 'free' to dispose of the old buffer.
|
1999-12-02 06:39:41 +03:00
|
|
|
//
|
2017-08-21 13:01:27 +03:00
|
|
|
nsresult nsLinebreakHelpers ::ConvertPlatformToDOMLinebreaks(
|
|
|
|
const nsACString& inFlavor, void** ioData, int32_t* ioLengthInBytes) {
|
1999-12-02 06:39:41 +03:00
|
|
|
NS_ASSERTION(ioData && *ioData && ioLengthInBytes, "Bad Params");
|
|
|
|
if (!(ioData && *ioData && ioLengthInBytes)) return NS_ERROR_INVALID_ARG;
|
2015-04-22 07:21:00 +03:00
|
|
|
|
1999-12-02 06:39:41 +03:00
|
|
|
nsresult retVal = NS_OK;
|
2015-04-22 07:21:00 +03:00
|
|
|
|
2017-08-21 13:01:27 +03:00
|
|
|
if (inFlavor.EqualsLiteral(kTextMime) || inFlavor.EqualsLiteral(kRTFMime)) {
|
2007-07-08 11:08:04 +04:00
|
|
|
char* buffAsChars = reinterpret_cast<char*>(*ioData);
|
1999-12-02 06:39:41 +03:00
|
|
|
char* oldBuffer = buffAsChars;
|
2015-04-22 07:21:00 +03:00
|
|
|
retVal = nsLinebreakConverter::ConvertLineBreaksInSitu(
|
|
|
|
&buffAsChars, nsLinebreakConverter::eLinebreakAny,
|
|
|
|
nsLinebreakConverter::eLinebreakContent, *ioLengthInBytes,
|
1999-12-02 06:39:41 +03:00
|
|
|
ioLengthInBytes);
|
|
|
|
if (NS_SUCCEEDED(retVal)) {
|
|
|
|
if (buffAsChars != oldBuffer) // check if buffer was reallocated
|
2015-03-27 03:01:12 +03:00
|
|
|
free(oldBuffer);
|
1999-12-02 06:39:41 +03:00
|
|
|
*ioData = buffAsChars;
|
|
|
|
}
|
2017-08-21 13:01:27 +03:00
|
|
|
} else if (inFlavor.EqualsLiteral("image/jpeg")) {
|
1999-12-02 06:39:41 +03:00
|
|
|
// I'd assume we don't want to do anything for binary data....
|
2015-04-22 07:21:00 +03:00
|
|
|
} else {
|
2014-01-04 19:02:17 +04:00
|
|
|
char16_t* buffAsUnichar = reinterpret_cast<char16_t*>(*ioData);
|
|
|
|
char16_t* oldBuffer = buffAsUnichar;
|
2012-08-22 19:56:38 +04:00
|
|
|
int32_t newLengthInChars;
|
2015-04-22 07:21:00 +03:00
|
|
|
retVal = nsLinebreakConverter::ConvertUnicharLineBreaksInSitu(
|
|
|
|
&buffAsUnichar, nsLinebreakConverter::eLinebreakAny,
|
|
|
|
nsLinebreakConverter::eLinebreakContent,
|
2014-01-04 19:02:17 +04:00
|
|
|
*ioLengthInBytes / sizeof(char16_t), &newLengthInChars);
|
1999-12-02 06:39:41 +03:00
|
|
|
if (NS_SUCCEEDED(retVal)) {
|
|
|
|
if (buffAsUnichar != oldBuffer) // check if buffer was reallocated
|
2015-03-27 03:01:12 +03:00
|
|
|
free(oldBuffer);
|
1999-12-02 06:39:41 +03:00
|
|
|
*ioData = buffAsUnichar;
|
2014-01-04 19:02:17 +04:00
|
|
|
*ioLengthInBytes = newLengthInChars * sizeof(char16_t);
|
1999-12-02 06:39:41 +03:00
|
|
|
}
|
|
|
|
}
|
2015-04-22 07:21:00 +03:00
|
|
|
|
1999-12-02 06:39:41 +03:00
|
|
|
return retVal;
|
|
|
|
|
|
|
|
} // ConvertPlatformToDOMLinebreaks
|