Files
palemoon27/widget/nsPrimitiveHelpers.cpp
T
roytam1 365b9b17b6 import change from rmottola/Arctic-Fox:
- Bug 1136379. Clean up the nsPluginHost API a bit. (c39f45953)
- Bug 1137897 - Do not throw exception from nsPluginTag::GetMimeTypes if a plug-in has no MIME-Types. (9d77c7205)
- Bug 1103036 - Allow ContentChild to perform tasks during shutdown (342555d90)
- Bug 1140714 - Pass through remote NS_OpenAnonymousTemporaryFile failure to caller. (04f01ef2c)
- Bug 1124907 - Call SetCompositor() only when it is valid (2255eeda2)
- Bug 1145149 - Include IntegerPrintfMacros in PerfSpewer.cpp (0e755cae8)
- Bug 1146223 - IonMonkey: MIPS: Fix a typo in storeFloat32x3 (36dd95699)
- Bug 1143686 - Gtk3 - Render scrollbar thumb with margin. (384347c60)
- Bug 1143686 - Gtk3 - Render scrollbar thumb with margin. (8711babf3)
- Bug 1142074 - remove NS_{IMPORT,EXPORT}_STATIC_MEMBER_ These have been unused for quite some time, and we have other ways of flagging static variables for export/import now.  Whatever GCC bugs necessitated these macros are long gone as well. (a829ba500)
- Bug 1139361 - Remove gTLSThreadID*, NS_TLS and mozilla::threads::ID. (4c21669cb)
- Bug 1138123 - remove xpcom/sample/ as a bygone relic (2a4e33835)
- cleanup MOZ_THROW_EXPORT inspired from current FireFox removing the MOZALLOC_EXPORT hack (534f81737)
- Bug 868814 - Fold mozalloc library into mozglue. (324250a8c)
- Bug 1119482, part 1 - Use CycleCollectedJSRuntime::Get() in the various CC wrapper methods. (3c8638c57)
- Bug 1119482, part 2 - Move HoldDropJSObjects.h from xpcom/glue to xpcom/base. (c8ef6be30)
- Bug 1119482, part 3 - Move the Hold and DropJSObjects implementations to a new HoldDropJSObjects.cpp file. (8a128cabd)
- Bug 1119482, part 4 - Move IsJSHolder into HoldDropJSObjects. (154720b0d)
- Bug 1141660 - Fix bustage from bug 868814 with --disable-replace-malloc (7f74490b2)
- Followup for bug 868814 - replace non-obvious #if with simpler alternative. (2a1520452)
- Bug 1132771 - Add a test for reading all moz.build files in filesystem traversal mode; (49dcae4ea)
- Bug 1132771 - Support and test for reading without a config object; (b5fa44ed3)
- Bug 1132771 - API to return moz.build files relevant for a set of paths; (5a53e692a)
- Bug 1134072 - Remove support for post-eval sandbox callback; (fb63d7eda)
- Bug 1132771 - Implement strongly typed named tuples; (7acf71487)
- Bug 1135984 - Avoid setting an empty GYP_DIRS in contexts when reading it. (fceaf9f93)
- Bug 1134072 - Support for sub-contexts; r=glandium (41a0c2197)
- Bug 1136456 - Remove leftovers from TIERS support in mozbuild.frontend.reader. (4d5180e25)
- Bug 1132771 - Pass special types down to sandboxes via metadata; (5126bd8a6)
- Bug 1132771 - Support reading relevant moz.build files; r=glandium (6f9d6107c)
- Bug 1132771 - Add Files to moz.build with ability to define Bugzilla component; r=glandium (d5416a6cc)
- Bug 1132771 - Implement file-info mach command; r=glandium (64b7f8fad)
- Bug 1132771 - Define some bug components; r=glandium (e4d2b4645)
- Bug 1139050 - Add moz.build BUG_COMPONENT metadata for xpcom/. (ea30ac906)
- Bug 1139050, part 2 - Move nsAlgorithm.h to xpcom/base. (21abdde35)
- Bug 1134920 - Use moz_xmalloc/moz_xrealloc/free instead of nsMemory:Alloc/Realloc/Free. (5a00f0487)
- Bug 1134920 - Remove nsMemory::Alloc/Realloc/Free. (514d8e8eb)
- Bug 1120308 - tcp control channel for presentation api. (f3ee09a89)
- Bug 1125698 - Add ExpandErrorArguments() varargs helper function and remove uninitialized `dummy` va_list variable. (f9fdcd1db)
- Bug 1101627 - Add touch action regions. (6e86516f3)
- Bug 1092102 - Implement a WorkerDebuggerGlobalScope (4b3195921)
- Bug 1036967 - Introduce ScaleFactors2D. (2a80be7d6)
- Bug 1071018 - Work around an assertion (will be fixed properly in bug 1036967). (3f62cfa03)
- Bug 1023190 - Fix extra horizontal line when draw background image with repeat-x mode (5ab11f642)
- Bug 1135992 - Fix non-unified build failed in nsLayoutUtils.cpp. (8f8fcace8)
- Bug 1133492 - Extract some of nsPresShell into a separate TouchManager class. (9ac347878)
- Bug 1133492 - Extract some of nsPresShell into a separate TouchManager class. (37181a8a3)
- Bug 1122094 - Remove some unnecessary code. (6c3b1abe2)
- Don't async scroll overflowed single-line text boxes in APZ. (bug 1126090 part 6) (435d9d186)
2019-05-30 22:05:20 +08:00

279 lines
10 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* 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/. */
//
// 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*
// - anything else is a char16_t*
//
#include "nsPrimitiveHelpers.h"
#include "nsCOMPtr.h"
#include "nsXPCOM.h"
#include "nsISupportsPrimitives.h"
#include "nsITransferable.h"
#include "nsIComponentManager.h"
#include "nsLinebreakConverter.h"
#include "nsReadableUtils.h"
#include "nsIServiceManager.h"
// unicode conversion
#include "nsIPlatformCharset.h"
#include "nsIUnicodeDecoder.h"
#include "nsISaveAsCharset.h"
#include "nsAutoPtr.h"
#include "mozilla/Likely.h"
#include "mozilla/dom/EncodingUtils.h"
using mozilla::dom::EncodingUtils;
//
// CreatePrimitiveForData
//
// Given some data and the flavor it corresponds to, creates the appropriate
// nsISupports* wrapper for passing across IDL boundaries. Right now, everything
// creates a two-byte |nsISupportsString|, except for "text/plain" and native
// platform HTML (CF_HTML on win32)
//
void
nsPrimitiveHelpers :: CreatePrimitiveForData ( const char* aFlavor, const void* aDataBuff,
uint32_t aDataLen, nsISupports** aPrimitive )
{
if ( !aPrimitive )
return;
if ( strcmp(aFlavor,kTextMime) == 0 || strcmp(aFlavor,kNativeHTMLMime) == 0 ) {
nsCOMPtr<nsISupportsCString> primitive =
do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID);
if ( primitive ) {
const char * start = reinterpret_cast<const char*>(aDataBuff);
primitive->SetData(Substring(start, start + aDataLen));
NS_ADDREF(*aPrimitive = primitive);
}
}
else {
nsCOMPtr<nsISupportsString> primitive =
do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
if (primitive ) {
if (aDataLen % 2) {
nsAutoArrayPtr<char> buffer(new char[aDataLen + 1]);
if (!MOZ_LIKELY(buffer))
return;
memcpy(buffer, aDataBuff, aDataLen);
buffer[aDataLen] = 0;
const char16_t* start = reinterpret_cast<const char16_t*>(buffer.get());
// recall that length takes length as characters, not bytes
primitive->SetData(Substring(start, start + (aDataLen + 1) / 2));
} else {
const char16_t* start = reinterpret_cast<const char16_t*>(aDataBuff);
// recall that length takes length as characters, not bytes
primitive->SetData(Substring(start, start + (aDataLen / 2)));
}
NS_ADDREF(*aPrimitive = primitive);
}
}
} // CreatePrimitiveForData
//
// CreateDataFromPrimitive
//
// Given a nsISupports* primitive and the flavor it represents, creates a new data
// buffer with the data in it. This data will be null terminated, but the length
// parameter does not reflect that.
//
void
nsPrimitiveHelpers :: CreateDataFromPrimitive ( const char* aFlavor, nsISupports* aPrimitive,
void** aDataBuff, uint32_t aDataLen )
{
if ( !aDataBuff )
return;
*aDataBuff = nullptr;
if ( strcmp(aFlavor,kTextMime) == 0 ) {
nsCOMPtr<nsISupportsCString> plainText ( do_QueryInterface(aPrimitive) );
if ( plainText ) {
nsAutoCString data;
plainText->GetData ( data );
*aDataBuff = ToNewCString(data);
}
}
else {
nsCOMPtr<nsISupportsString> doubleByteText ( do_QueryInterface(aPrimitive) );
if ( doubleByteText ) {
nsAutoString data;
doubleByteText->GetData ( data );
*aDataBuff = ToNewUnicode(data);
}
}
}
//
// ConvertUnicodeToPlatformPlainText
//
// Given a unicode buffer (flavor text/unicode), this converts it to plain text using
// the appropriate platform charset encoding. |inUnicodeLen| is the length of the input
// string, not the # of bytes in the buffer. The |outPlainTextData| is null terminated,
// but its length parameter, |outPlainTextLen|, does not reflect that.
//
nsresult
nsPrimitiveHelpers :: ConvertUnicodeToPlatformPlainText ( char16_t* inUnicode, int32_t inUnicodeLen,
char** outPlainTextData, int32_t* outPlainTextLen )
{
if ( !outPlainTextData || !outPlainTextLen )
return NS_ERROR_INVALID_ARG;
// get the charset
nsresult rv;
nsCOMPtr <nsIPlatformCharset> platformCharsetService = do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
nsAutoCString platformCharset;
if (NS_SUCCEEDED(rv))
rv = platformCharsetService->GetCharset(kPlatformCharsetSel_PlainTextInClipboard, platformCharset);
if (NS_FAILED(rv))
platformCharset.AssignLiteral("ISO-8859-1");
// use transliterate to convert things like smart quotes to normal quotes for plain text
nsCOMPtr<nsISaveAsCharset> converter = do_CreateInstance("@mozilla.org/intl/saveascharset;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = converter->Init(platformCharset.get(),
nsISaveAsCharset::attr_EntityAfterCharsetConv +
nsISaveAsCharset::attr_FallbackQuestionMark,
nsIEntityConverter::transliterate);
NS_ENSURE_SUCCESS(rv, rv);
rv = converter->Convert(inUnicode, outPlainTextData);
*outPlainTextLen = *outPlainTextData ? strlen(*outPlainTextData) : 0;
NS_ASSERTION ( NS_SUCCEEDED(rv), "Error converting unicode to plain text" );
return rv;
} // ConvertUnicodeToPlatformPlainText
//
// ConvertPlatformPlainTextToUnicode
//
// Given a char buffer (flavor text/plaikn), this converts it to unicode using
// the appropriate platform charset encoding. |outUnicode| is null terminated,
// but its length parameter, |outUnicodeLen|, does not reflect that. |outUnicodeLen| is
// the length of the string in characters, not bytes.
//
nsresult
nsPrimitiveHelpers :: ConvertPlatformPlainTextToUnicode ( const char* inText, int32_t inTextLen,
char16_t** outUnicode, int32_t* outUnicodeLen )
{
if ( !outUnicode || !outUnicodeLen )
return NS_ERROR_INVALID_ARG;
// Get the appropriate unicode decoder. We're guaranteed that this won't change
// through the life of the app so we can cache it.
nsresult rv = NS_OK;
static nsCOMPtr<nsIUnicodeDecoder> decoder;
static bool hasConverter = false;
if ( !hasConverter ) {
// get the charset
nsAutoCString platformCharset;
nsCOMPtr <nsIPlatformCharset> platformCharsetService = do_GetService(NS_PLATFORMCHARSET_CONTRACTID, &rv);
if (NS_SUCCEEDED(rv))
rv = platformCharsetService->GetCharset(kPlatformCharsetSel_PlainTextInClipboard, platformCharset);
if (NS_FAILED(rv))
platformCharset.AssignLiteral("windows-1252");
decoder = EncodingUtils::DecoderForEncoding(platformCharset);
hasConverter = true;
}
// Estimate out length and allocate the buffer based on a worst-case estimate, then do
// the conversion.
decoder->GetMaxLength(inText, inTextLen, outUnicodeLen); // |outUnicodeLen| is number of chars
if ( *outUnicodeLen ) {
*outUnicode = reinterpret_cast<char16_t*>(moz_xmalloc((*outUnicodeLen + 1) * sizeof(char16_t)));
if ( *outUnicode ) {
rv = decoder->Convert(inText, &inTextLen, *outUnicode, outUnicodeLen);
(*outUnicode)[*outUnicodeLen] = '\0'; // null terminate. Convert() doesn't do it for us
}
} // if valid length
NS_ASSERTION ( NS_SUCCEEDED(rv), "Error converting plain text to unicode" );
return rv;
} // ConvertPlatformPlainTextToUnicode
//
// 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).
//
// NOTE: this assumes that it can use 'free' to dispose of the old buffer.
//
nsresult
nsLinebreakHelpers :: ConvertPlatformToDOMLinebreaks ( const char* inFlavor, void** ioData,
int32_t* ioLengthInBytes )
{
NS_ASSERTION ( ioData && *ioData && ioLengthInBytes, "Bad Params");
if ( !(ioData && *ioData && ioLengthInBytes) )
return NS_ERROR_INVALID_ARG;
nsresult retVal = NS_OK;
if ( strcmp(inFlavor, "text/plain") == 0 ) {
char* buffAsChars = reinterpret_cast<char*>(*ioData);
char* oldBuffer = buffAsChars;
retVal = nsLinebreakConverter::ConvertLineBreaksInSitu ( &buffAsChars, nsLinebreakConverter::eLinebreakAny,
nsLinebreakConverter::eLinebreakContent,
*ioLengthInBytes, ioLengthInBytes );
if ( NS_SUCCEEDED(retVal) ) {
if ( buffAsChars != oldBuffer ) // check if buffer was reallocated
free ( oldBuffer );
*ioData = buffAsChars;
}
}
else if ( strcmp(inFlavor, "image/jpeg") == 0 ) {
// I'd assume we don't want to do anything for binary data....
}
else {
char16_t* buffAsUnichar = reinterpret_cast<char16_t*>(*ioData);
char16_t* oldBuffer = buffAsUnichar;
int32_t newLengthInChars;
retVal = nsLinebreakConverter::ConvertUnicharLineBreaksInSitu ( &buffAsUnichar, nsLinebreakConverter::eLinebreakAny,
nsLinebreakConverter::eLinebreakContent,
*ioLengthInBytes / sizeof(char16_t), &newLengthInChars );
if ( NS_SUCCEEDED(retVal) ) {
if ( buffAsUnichar != oldBuffer ) // check if buffer was reallocated
free ( oldBuffer );
*ioData = buffAsUnichar;
*ioLengthInBytes = newLengthInChars * sizeof(char16_t);
}
}
return retVal;
} // ConvertPlatformToDOMLinebreaks