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