Bug 1652470 [wpt PR 24579] - Update mozrunner to 8.0.0, a=testonly
[gecko.git] / widget / nsPrimitiveHelpers.cpp
blob4bcbc4a40820d21707bc72ace7c8a4719f034564
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 //
8 // Part of the reason these routines are all in once place is so that as new
9 // data flavors are added that are known to be one-byte or two-byte strings, or
10 // even raw binary data, then we just have to go to one place to change how the
11 // data moves into/out of the primitives and native line endings.
13 // If you add new flavors that have special consideration (binary data or
14 // one-byte char* strings), please update all the helper classes in this file.
16 // For now, this is the assumption that we are making:
17 // - text/plain is always a char*
18 // - anything else is a char16_t*
21 #include "nsPrimitiveHelpers.h"
23 #include "mozilla/UniquePtr.h"
24 #include "nsComponentManagerUtils.h"
25 #include "nsCOMPtr.h"
26 #include "nsXPCOM.h"
27 #include "nsISupportsPrimitives.h"
28 #include "nsITransferable.h"
29 #include "nsLinebreakConverter.h"
30 #include "nsReadableUtils.h"
33 // CreatePrimitiveForData
35 // Given some data and the flavor it corresponds to, creates the appropriate
36 // nsISupports* wrapper for passing across IDL boundaries. Right now, everything
37 // creates a two-byte |nsISupportsString|, except for "text/plain" and native
38 // platform HTML (CF_HTML on win32)
40 void nsPrimitiveHelpers ::CreatePrimitiveForData(const nsACString& aFlavor,
41 const void* aDataBuff,
42 uint32_t aDataLen,
43 nsISupports** aPrimitive) {
44 if (!aPrimitive) return;
46 if (aFlavor.EqualsLiteral(kTextMime) ||
47 aFlavor.EqualsLiteral(kNativeHTMLMime) ||
48 aFlavor.EqualsLiteral(kRTFMime) ||
49 aFlavor.EqualsLiteral(kCustomTypesMime)) {
50 nsCOMPtr<nsISupportsCString> primitive =
51 do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID);
52 if (primitive) {
53 const char* start = reinterpret_cast<const char*>(aDataBuff);
54 primitive->SetData(Substring(start, start + aDataLen));
55 NS_ADDREF(*aPrimitive = primitive);
57 } else {
58 nsCOMPtr<nsISupportsString> primitive =
59 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
60 if (primitive) {
61 if (aDataLen % 2) {
62 auto buffer = mozilla::MakeUnique<char[]>(aDataLen + 1);
63 if (!MOZ_LIKELY(buffer)) return;
65 memcpy(buffer.get(), aDataBuff, aDataLen);
66 buffer[aDataLen] = 0;
67 const char16_t* start = reinterpret_cast<const char16_t*>(buffer.get());
68 // recall that length takes length as characters, not bytes
69 primitive->SetData(Substring(start, start + (aDataLen + 1) / 2));
70 } else {
71 const char16_t* start = reinterpret_cast<const char16_t*>(aDataBuff);
72 // recall that length takes length as characters, not bytes
73 primitive->SetData(Substring(start, start + (aDataLen / 2)));
75 NS_ADDREF(*aPrimitive = primitive);
79 } // CreatePrimitiveForData
82 // CreatePrimitiveForCFHTML
84 // Platform specific CreatePrimitive, windows CF_HTML.
86 void nsPrimitiveHelpers ::CreatePrimitiveForCFHTML(const void* aDataBuff,
87 uint32_t* aDataLen,
88 nsISupports** aPrimitive) {
89 if (!aPrimitive) return;
91 nsCOMPtr<nsISupportsString> primitive =
92 do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID);
93 if (!primitive) return;
95 // We need to duplicate the input buffer, since the removal of linebreaks
96 // might reallocte it.
97 void* utf8 = moz_xmalloc(*aDataLen);
98 memcpy(utf8, aDataBuff, *aDataLen);
99 int32_t signedLen = static_cast<int32_t>(*aDataLen);
100 nsLinebreakHelpers::ConvertPlatformToDOMLinebreaks(
101 nsDependentCString(kTextMime), &utf8, &signedLen);
102 *aDataLen = signedLen;
104 nsAutoString str(
105 NS_ConvertUTF8toUTF16(reinterpret_cast<const char*>(utf8), *aDataLen));
106 free(utf8);
107 *aDataLen = str.Length() * sizeof(char16_t);
108 primitive->SetData(str);
109 NS_ADDREF(*aPrimitive = primitive);
113 // CreateDataFromPrimitive
115 // Given a nsISupports* primitive and the flavor it represents, creates a new
116 // data buffer with the data in it. This data will be null terminated, but the
117 // length parameter does not reflect that.
119 void nsPrimitiveHelpers::CreateDataFromPrimitive(const nsACString& aFlavor,
120 nsISupports* aPrimitive,
121 void** aDataBuff,
122 uint32_t* aDataLen) {
123 if (!aDataBuff) return;
125 *aDataBuff = nullptr;
126 *aDataLen = 0;
128 if (aFlavor.EqualsLiteral(kTextMime) ||
129 aFlavor.EqualsLiteral(kCustomTypesMime)) {
130 nsCOMPtr<nsISupportsCString> plainText(do_QueryInterface(aPrimitive));
131 if (plainText) {
132 nsAutoCString data;
133 plainText->GetData(data);
134 *aDataBuff = ToNewCString(data);
135 *aDataLen = data.Length() * sizeof(char);
137 } else {
138 nsCOMPtr<nsISupportsString> doubleByteText(do_QueryInterface(aPrimitive));
139 if (doubleByteText) {
140 nsAutoString data;
141 doubleByteText->GetData(data);
142 *aDataBuff = ToNewUnicode(data);
143 *aDataLen = data.Length() * sizeof(char16_t);
149 // ConvertPlatformToDOMLinebreaks
151 // Given some data, convert from the platform linebreaks into the LF expected by
152 // the DOM. This will attempt to convert the data in place, but the buffer may
153 // still need to be reallocated regardless (disposing the old buffer is taken
154 // care of internally, see the note below).
156 // NOTE: this assumes that it can use 'free' to dispose of the old buffer.
158 nsresult nsLinebreakHelpers ::ConvertPlatformToDOMLinebreaks(
159 const nsACString& inFlavor, void** ioData, int32_t* ioLengthInBytes) {
160 NS_ASSERTION(ioData && *ioData && ioLengthInBytes, "Bad Params");
161 if (!(ioData && *ioData && ioLengthInBytes)) return NS_ERROR_INVALID_ARG;
163 nsresult retVal = NS_OK;
165 if (inFlavor.EqualsLiteral(kTextMime) || inFlavor.EqualsLiteral(kRTFMime)) {
166 char* buffAsChars = reinterpret_cast<char*>(*ioData);
167 char* oldBuffer = buffAsChars;
168 retVal = nsLinebreakConverter::ConvertLineBreaksInSitu(
169 &buffAsChars, nsLinebreakConverter::eLinebreakAny,
170 nsLinebreakConverter::eLinebreakContent, *ioLengthInBytes,
171 ioLengthInBytes);
172 if (NS_SUCCEEDED(retVal)) {
173 if (buffAsChars != oldBuffer) // check if buffer was reallocated
174 free(oldBuffer);
175 *ioData = buffAsChars;
177 } else if (inFlavor.EqualsLiteral("image/jpeg")) {
178 // I'd assume we don't want to do anything for binary data....
179 } else {
180 char16_t* buffAsUnichar = reinterpret_cast<char16_t*>(*ioData);
181 char16_t* oldBuffer = buffAsUnichar;
182 int32_t newLengthInChars;
183 retVal = nsLinebreakConverter::ConvertUnicharLineBreaksInSitu(
184 &buffAsUnichar, nsLinebreakConverter::eLinebreakAny,
185 nsLinebreakConverter::eLinebreakContent,
186 *ioLengthInBytes / sizeof(char16_t), &newLengthInChars);
187 if (NS_SUCCEEDED(retVal)) {
188 if (buffAsUnichar != oldBuffer) // check if buffer was reallocated
189 free(oldBuffer);
190 *ioData = buffAsUnichar;
191 *ioLengthInBytes = newLengthInChars * sizeof(char16_t);
195 return retVal;
197 } // ConvertPlatformToDOMLinebreaks