Tue, 06 Jan 2015 21:39:09 +0100
Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "nsIServiceManager.h"
7 #include "nsICharsetConverterManager.h"
8 #include "nsUCSupport.h"
9 #include "nsString.h"
10 #include "nsIStringEnumerator.h"
11 #include "nsTArray.h"
13 //----------------------------------------------------------------------------
14 // Global functions and data [declaration]
16 #define ARRAY_SIZE(_array) (sizeof(_array) / sizeof(_array[0]))
17 #define SMALL_BUFFER_SIZE 512
18 #define MED_BUFFER_SIZE 1024
19 #define BIG_BUFFER_SIZE 2048
21 static NS_DEFINE_CID(kCharsetConverterManagerCID, NS_ICHARSETCONVERTERMANAGER_CID);
23 //----------------------------------------------------------------------------
24 // Class nsTestLog [declaration]
26 /**
27 * A Logging class for test programs.
28 *
29 * This simple test program will not trigger a component registration. So
30 * Mozilla has to be run once before running this, so that the necessary
31 * components will be registered. Also, please observe that the ContractID's are
32 * case sensitive now!
33 *
34 * @created 28/Mar/2000
35 * @author Catalin Rotaru [CATA]
36 */
37 class nsTestLog
38 {
39 private:
41 static const char * kTraceDelimiter;
43 nsAutoCString mTrace;
45 public:
47 void AddTrace(const char * aTrace);
48 void DelTrace(const char * aTrace);
49 void PrintError(const char * aCall, const int aError);
50 void PrintError(const char * aCall, const char * aMessage);
51 };
53 //----------------------------------------------------------------------------
54 // Class nsTestUConv [declaration]
56 /**
57 * The main class of the program.
58 *
59 * XXX Create a very general set of "bug and regression" test cases and the
60 * one in TestTempBug()
61 * XXX Apply the new argument style (pointers) to the converters interfaces
62 *
63 * @created 28/Mar/2000
64 * @author Catalin Rotaru [CATA]
65 */
66 class nsTestUConv
67 {
68 private:
70 nsTestLog mLog;
72 /**
73 * Run the built-in set of self tests for encoders.
74 */
75 nsresult TestEncoders();
77 /**
78 * Run the built-in set of self tests for decoders.
79 */
80 nsresult TestDecoders();
82 /**
83 * Run the built-in set of self tests for the CharsetManager.
84 */
85 nsresult TestCharsetManager();
87 /**
88 * Display charset detectors and their attributes.
89 */
90 nsresult DisplayDetectors();
92 /**
93 * Display charsets and their attributes.
94 */
95 nsresult DisplayCharsets();
97 /**
98 * Run a temporary debug test. This method is ment as a placeholder when some
99 * quick debugging is needed.
100 */
101 nsresult TestTempBug();
103 nsresult Encode(char16_t ** aSrc, char16_t * aSrcEnd, char ** aDest,
104 char * aDestEnd, const nsAFlatCString& aCharset);
106 /**
107 * Bridge methods between the new argument style (poiters) and the old one
108 * (lengths). To be removed when the converter interfaces will switch to the
109 * new style.
110 *
111 * This wraps an encoder Convert() call.
112 */
113 nsresult ConvertEncode(char16_t ** aSrc, char16_t * aSrcEnd, char ** aDest,
114 char * aDestEnd, nsIUnicodeEncoder * aEncoder);
116 /**
117 * This wraps an encoder Finish() call.
118 */
119 nsresult FinishEncode(char ** aDest, char * aDestEnd,
120 nsIUnicodeEncoder * aEncoder);
122 void PrintSpaces(int aCount);
124 public:
126 /**
127 * Main method of the program.
128 */
129 nsresult Main(int aArgC, char ** aArgV);
130 };
132 //----------------------------------------------------------------------------
133 // Global functions and data [implementation]
135 int main(int argc, char ** argv)
136 {
137 nsTestUConv testObj;
138 nsresult res;
140 res = testObj.Main(argc, argv);
141 return (NS_FAILED(res));
142 }
144 //----------------------------------------------------------------------------
145 // Class nsTestLog [implementation]
147 const char * nsTestLog::kTraceDelimiter = ".";
149 void nsTestLog::AddTrace(const char * aTrace)
150 {
151 mTrace.Append(aTrace);
152 mTrace.Append(kTraceDelimiter);
153 }
155 void nsTestLog::DelTrace(const char * aTrace)
156 {
157 mTrace.Truncate(mTrace.Length() - strlen(aTrace) - strlen(kTraceDelimiter));
158 }
160 void nsTestLog::PrintError(const char * aCall, const int aError)
161 {
162 const char * trace = mTrace.get();
163 printf("ERROR at %s%s code=0x%x.\n", trace, aCall, aError);
164 }
166 void nsTestLog::PrintError(const char * aCall, const char * aMessage)
167 {
168 const char * trace = mTrace.get();
169 printf("ERROR at %s%s reason: %s.\n", trace, aCall, aMessage);
170 }
172 //----------------------------------------------------------------------------
173 // Class nsTestUConv [implementation]
175 nsresult nsTestUConv::TestEncoders()
176 {
177 const char * trace = "TestEncoders";
178 mLog.AddTrace(trace);
179 nsresult res = NS_OK;
181 nsCOMPtr<nsICharsetConverterManager> ccMan =
182 do_GetService(kCharsetConverterManagerCID, &res);
183 if (NS_FAILED(res)) return res;
185 nsCOMPtr<nsIUTF8StringEnumerator> encoders;
186 res = ccMan->GetEncoderList(getter_AddRefs(encoders));
187 if (NS_FAILED(res)) return res;
189 bool hasMore;
190 encoders->HasMore(&hasMore);
192 nsAutoCString charset;
193 while (hasMore) {
194 encoders->GetNext(charset);
196 encoders->HasMore(&hasMore);
197 }
199 mLog.DelTrace(trace);
200 return res;
201 }
203 nsresult nsTestUConv::TestDecoders()
204 {
205 const char * trace = "TestDecoders";
206 mLog.AddTrace(trace);
207 nsresult res = NS_OK;
209 // XXX write me
211 mLog.DelTrace(trace);
212 return res;
213 }
215 nsresult nsTestUConv::TestCharsetManager()
216 {
217 const char * trace = "TestCharsetManager";
218 mLog.AddTrace(trace);
219 nsresult res = NS_OK;
220 nsAutoString name;
221 nsCOMPtr<nsIAtom> csAtom;
223 nsCOMPtr<nsICharsetConverterManager> ccMan =
224 do_GetService(kCharsetConverterManagerCID, &res);
225 if (NS_FAILED(res)) {
226 mLog.PrintError("NS_WITH_SERVICE", res);
227 return res;
228 }
230 mLog.DelTrace(trace);
231 return res;
232 }
234 nsresult nsTestUConv::DisplayDetectors()
235 {
236 const char * trace = "DisplayDetectors";
237 mLog.AddTrace(trace);
238 nsresult res = NS_OK;
240 nsCOMPtr<nsICharsetConverterManager> ccMan =
241 do_GetService(kCharsetConverterManagerCID, &res);
242 if (NS_FAILED(res)) {
243 mLog.PrintError("NS_WITH_SERVICE", res);
244 return res;
245 }
247 // charset detectors
248 nsCOMPtr<nsIUTF8StringEnumerator> detectors;
250 res = ccMan->GetCharsetDetectorList(getter_AddRefs(detectors));
251 if (NS_FAILED(res)) {
252 mLog.PrintError("GetCharsetDetectorList()", res);
253 return res;
254 }
256 printf("***** Character Set Detectors *****\n");
258 bool hasMore;
259 detectors->HasMore(&hasMore);
260 while (hasMore) {
261 nsAutoCString detectorName;
262 res = detectors->GetNext(detectorName);
263 if (NS_FAILED(res)) {
264 mLog.PrintError("GetNext()", res);
265 return res;
266 }
268 printf("%s", detectorName.get());
269 PrintSpaces(36 - detectorName.Length()); // align to hard coded column number
271 nsAutoString title;
272 res = ccMan->GetCharsetTitle(detectorName.get(), title);
273 if (NS_FAILED(res)) title.SetLength(0);
274 printf("\"%s\"\n", NS_LossyConvertUTF16toASCII(title).get());
276 detectors->HasMore(&hasMore);
277 }
279 mLog.DelTrace(trace);
280 return NS_OK;
281 }
283 nsresult nsTestUConv::DisplayCharsets()
284 {
285 const char * trace = "DisplayCharsets";
286 mLog.AddTrace(trace);
287 nsresult res = NS_OK;
289 nsCOMPtr<nsICharsetConverterManager> ccMan =
290 do_GetService(kCharsetConverterManagerCID, &res);
291 if (NS_FAILED(res)) {
292 mLog.PrintError("NS_WITH_SERVICE", res);
293 return res;
294 }
296 nsCOMPtr<nsIUTF8StringEnumerator> decoders;
297 nsCOMPtr<nsIUTF8StringEnumerator> encoders;
299 res = ccMan->GetDecoderList(getter_AddRefs(decoders));
300 if (NS_FAILED(res)) {
301 mLog.PrintError("GetDecoderList()", res);
302 return res;
303 }
305 res = ccMan->GetEncoderList(getter_AddRefs(encoders));
306 if (NS_FAILED(res)) {
307 mLog.PrintError("GetEncoderList()", res);
308 return res;
309 }
312 printf("***** Character Sets *****\n");
314 uint32_t encCount = 0, decCount = 0;
315 uint32_t basicEncCount = 0, basicDecCount = 0;
317 nsTArray<nsCString> allCharsets;
319 nsAutoCString charset;
320 bool hasMore;
321 encoders->HasMore(&hasMore);
322 while (hasMore) {
323 res = encoders->GetNext(charset);
324 if (NS_SUCCEEDED(res))
325 allCharsets.AppendElement(charset);
327 encoders->HasMore(&hasMore);
328 }
330 nsAutoString prop, str;
331 uint32_t count = allCharsets.Length();
332 for (uint32_t i = 0; i < count; i++) {
334 const nsCString& charset = allCharsets[i];
335 printf("%s", charset.get());
336 PrintSpaces(24 - charset.Length()); // align to hard coded column number
339 nsCOMPtr<nsIUnicodeDecoder> dec;
340 res = ccMan->GetUnicodeDecoder(charset.get(), getter_AddRefs(dec));
341 if (NS_FAILED(res)) printf (" ");
342 else {
343 printf("D");
344 decCount++;
345 }
346 #ifdef DEBUG
347 // show the "basic" decoder classes
348 if (dec) {
349 nsCOMPtr<nsIBasicDecoder> isBasic = do_QueryInterface(dec);
350 if (isBasic) {
351 basicDecCount++;
352 printf("b");
353 }
354 else printf(" ");
355 }
356 else printf(" ");
357 #endif
359 nsCOMPtr<nsIUnicodeEncoder> enc;
360 res = ccMan->GetUnicodeEncoder(charset.get(), getter_AddRefs(enc));
361 if (NS_FAILED(res)) printf (" ");
362 else {
363 printf("E");
364 encCount++;
365 }
367 #ifdef DEBUG
368 if (enc) {
369 nsCOMPtr<nsIBasicEncoder> isBasic = do_QueryInterface(enc);
370 if (isBasic) {
371 basicEncCount++;
372 printf("b");
373 }
374 else printf(" ");
375 }
376 else printf(" ");
377 #endif
379 printf(" ");
381 prop.AssignLiteral(".notForBrowser");
382 res = ccMan->GetCharsetData(charset.get(), prop.get(), str);
383 if (dec && (NS_FAILED(res))) printf ("B");
384 else printf("X");
386 prop.AssignLiteral(".notForComposer");
387 res = ccMan->GetCharsetData(charset.get(), prop.get(), str);
388 if (enc && (NS_FAILED(res))) printf ("C");
389 else printf("X");
391 prop.AssignLiteral(".notForMailView");
392 res = ccMan->GetCharsetData(charset.get(), prop.get(), str);
393 if (dec && (NS_FAILED(res))) printf ("V");
394 else printf("X");
396 prop.AssignLiteral(".notForMailEdit");
397 res = ccMan->GetCharsetData(charset.get(), prop.get(), str);
398 if (enc && (NS_FAILED(res))) printf ("E");
399 else printf("X");
401 printf("(%3d, %3d) ", encCount, decCount);
402 res = ccMan->GetCharsetTitle(charset.get(), str);
403 if (NS_FAILED(res)) str.SetLength(0);
404 NS_LossyConvertUTF16toASCII buff2(str);
405 printf(" \"%s\"\n", buff2.get());
406 }
408 printf("%u of %u decoders are basic (%d%%)\n",
409 basicDecCount, decCount, (basicDecCount * 100) / decCount);
411 printf("%u of %u encoders are basic (%d%%)\n",
412 basicEncCount, encCount, (basicEncCount * 100) / encCount);
413 mLog.DelTrace(trace);
414 return NS_OK;
415 }
417 nsresult nsTestUConv::TestTempBug()
418 {
419 const char * trace = "TestTempBug";
420 mLog.AddTrace(trace);
421 nsresult res = NS_OK;
423 NS_NAMED_LITERAL_CSTRING(charset, "ISO-2022-JP");
424 char16_t src[] = {0x0043, 0x004e, 0x0045, 0x0054, 0x0020, 0x004A, 0x0061,
425 0x0070, 0x0061, 0x006E, 0x0020, 0x7DE8, 0x96C6, 0x5C40};
426 char16_t * srcEnd = src + ARRAY_SIZE(src);
427 char dest[BIG_BUFFER_SIZE];
428 char * destEnd = dest + BIG_BUFFER_SIZE;
430 char16_t * p = src;
431 char * q = dest;
432 res = Encode(&p, srcEnd, &q, destEnd, charset);
434 mLog.DelTrace(trace);
435 return res;
436 }
438 nsresult nsTestUConv::Encode(char16_t ** aSrc, char16_t * aSrcEnd,
439 char ** aDest, char * aDestEnd,
440 const nsAFlatCString& aCharset)
441 {
442 const char * trace = "Encode";
443 mLog.AddTrace(trace);
444 nsresult res = NS_OK;
446 nsCOMPtr<nsICharsetConverterManager> ccMan =
447 do_GetService(kCharsetConverterManagerCID, &res);
448 if (NS_FAILED(res)) {
449 mLog.PrintError("NS_WITH_SERVICE", res);
450 return res;
451 }
453 nsCOMPtr<nsIUnicodeEncoder> enc;
454 res = ccMan->GetUnicodeEncoder(aCharset.get(), getter_AddRefs(enc));
455 if (NS_FAILED(res)) {
456 mLog.PrintError("GetUnicodeEncoder()", res);
457 return res;
458 }
460 res = ConvertEncode(aSrc, aSrcEnd, aDest, aDestEnd, enc);
461 if (NS_FAILED(res)) {
462 mLog.PrintError("Convert()", res);
463 return res;
464 }
466 res = FinishEncode(aDest, aDestEnd, enc);
467 if (NS_FAILED(res)) {
468 mLog.PrintError("Finish()", res);
469 return res;
470 }
472 mLog.DelTrace(trace);
473 return res;
474 }
476 nsresult nsTestUConv::ConvertEncode(char16_t ** aSrc, char16_t * aSrcEnd,
477 char ** aDest, char * aDestEnd,
478 nsIUnicodeEncoder * aEncoder)
479 {
480 char16_t * src = (*aSrc);
481 char * dest = (*aDest);
482 int32_t srcLen = aSrcEnd - src;
483 int32_t destLen = aDestEnd - dest;
485 nsresult res = aEncoder->Convert(src, &srcLen, dest, &destLen);
487 (*aSrc) = src + srcLen;
488 (*aDest) = dest + destLen;
489 return res;
490 }
492 nsresult nsTestUConv::FinishEncode(char ** aDest, char * aDestEnd,
493 nsIUnicodeEncoder * aEncoder)
494 {
495 char * dest = (*aDest);
496 int32_t destLen = aDestEnd - dest;
498 nsresult res = aEncoder->Finish(dest, &destLen);
500 (*aDest) = dest + destLen;
501 return res;
502 }
504 void nsTestUConv::PrintSpaces(int aCount)
505 {
506 for (int i = 0; i < aCount; i++) printf(" ");
507 }
509 nsresult nsTestUConv::Main(int aArgC, char ** aArgV)
510 {
511 const char * trace = "Main";
512 mLog.AddTrace(trace);
513 nsresult res = NS_OK;
515 if (aArgC < 2) {
516 // no arguments were passed to the program, so we just run the self tests
517 res = TestCharsetManager();
518 if (NS_SUCCEEDED(res)) res = TestEncoders();
519 if (NS_SUCCEEDED(res)) res = TestDecoders();
520 } else if (!strcmp(aArgV[1], "-tempbug")) {
521 // we are testing a temporary bug
522 res = TestTempBug();
523 } else if (!strcmp(aArgV[1], "-display")) {
524 // display all the available data
525 res = DisplayDetectors();
526 if (NS_SUCCEEDED(res)) res = DisplayCharsets();
527 }
529 mLog.DelTrace(trace);
530 return res;
531 }