Sat, 03 Jan 2015 20:18:00 +0100
Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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 "TestHarness.h"
8 #include "nsIThread.h"
9 #include "nsIRunnable.h"
10 #include "nsThreadUtils.h"
11 #include "prprf.h"
12 #include "prinrval.h"
13 #include "nsCRT.h"
14 #include "nsIPipe.h" // new implementation
16 #include "mozilla/Monitor.h"
17 using namespace mozilla;
19 /** NS_NewPipe2 reimplemented, because it's not exported by XPCOM */
20 nsresult TP_NewPipe2(nsIAsyncInputStream** input,
21 nsIAsyncOutputStream** output,
22 bool nonBlockingInput,
23 bool nonBlockingOutput,
24 uint32_t segmentSize,
25 uint32_t segmentCount,
26 nsIMemory* segmentAlloc)
27 {
28 nsCOMPtr<nsIPipe> pipe = do_CreateInstance("@mozilla.org/pipe;1");
29 if (!pipe)
30 return NS_ERROR_OUT_OF_MEMORY;
32 nsresult rv = pipe->Init(nonBlockingInput,
33 nonBlockingOutput,
34 segmentSize,
35 segmentCount,
36 segmentAlloc);
38 if (NS_FAILED(rv))
39 return rv;
41 pipe->GetInputStream(input);
42 pipe->GetOutputStream(output);
43 return NS_OK;
44 }
46 /** NS_NewPipe reimplemented, because it's not exported by XPCOM */
47 #define TP_DEFAULT_SEGMENT_SIZE 4096
48 nsresult TP_NewPipe(nsIInputStream **pipeIn,
49 nsIOutputStream **pipeOut,
50 uint32_t segmentSize = 0,
51 uint32_t maxSize = 0,
52 bool nonBlockingInput = false,
53 bool nonBlockingOutput = false,
54 nsIMemory *segmentAlloc = nullptr);
55 nsresult TP_NewPipe(nsIInputStream **pipeIn,
56 nsIOutputStream **pipeOut,
57 uint32_t segmentSize,
58 uint32_t maxSize,
59 bool nonBlockingInput,
60 bool nonBlockingOutput,
61 nsIMemory *segmentAlloc)
62 {
63 if (segmentSize == 0)
64 segmentSize = TP_DEFAULT_SEGMENT_SIZE;
66 // Handle maxSize of UINT32_MAX as a special case
67 uint32_t segmentCount;
68 if (maxSize == UINT32_MAX)
69 segmentCount = UINT32_MAX;
70 else
71 segmentCount = maxSize / segmentSize;
73 nsIAsyncInputStream *in;
74 nsIAsyncOutputStream *out;
75 nsresult rv = TP_NewPipe2(&in, &out, nonBlockingInput, nonBlockingOutput,
76 segmentSize, segmentCount, segmentAlloc);
77 if (NS_FAILED(rv)) return rv;
79 *pipeIn = in;
80 *pipeOut = out;
81 return NS_OK;
82 }
85 #define KEY 0xa7
86 #define ITERATIONS 33333
87 char kTestPattern[] = "My hovercraft is full of eels.\n";
89 bool gTrace = false;
91 static nsresult
92 WriteAll(nsIOutputStream *os, const char *buf, uint32_t bufLen, uint32_t *lenWritten)
93 {
94 const char *p = buf;
95 *lenWritten = 0;
96 while (bufLen) {
97 uint32_t n;
98 nsresult rv = os->Write(p, bufLen, &n);
99 if (NS_FAILED(rv)) return rv;
100 p += n;
101 bufLen -= n;
102 *lenWritten += n;
103 }
104 return NS_OK;
105 }
107 class nsReceiver : public nsIRunnable {
108 public:
109 NS_DECL_THREADSAFE_ISUPPORTS
111 NS_IMETHOD Run() {
112 nsresult rv;
113 char buf[101];
114 uint32_t count;
115 PRIntervalTime start = PR_IntervalNow();
116 while (true) {
117 rv = mIn->Read(buf, 100, &count);
118 if (NS_FAILED(rv)) {
119 printf("read failed\n");
120 break;
121 }
122 if (count == 0) {
123 // printf("EOF count = %d\n", mCount);
124 break;
125 }
127 if (gTrace) {
128 buf[count] = '\0';
129 printf("read: %s\n", buf);
130 }
131 mCount += count;
132 }
133 PRIntervalTime end = PR_IntervalNow();
134 printf("read %d bytes, time = %dms\n", mCount,
135 PR_IntervalToMilliseconds(end - start));
136 return rv;
137 }
139 nsReceiver(nsIInputStream* in) : mIn(in), mCount(0) {
140 }
142 uint32_t GetBytesRead() { return mCount; }
144 protected:
145 nsCOMPtr<nsIInputStream> mIn;
146 uint32_t mCount;
147 };
149 NS_IMPL_ISUPPORTS(nsReceiver, nsIRunnable)
151 nsresult
152 TestPipe(nsIInputStream* in, nsIOutputStream* out)
153 {
154 nsCOMPtr<nsReceiver> receiver = new nsReceiver(in);
155 if (!receiver)
156 return NS_ERROR_OUT_OF_MEMORY;
158 nsresult rv;
160 nsCOMPtr<nsIThread> thread;
161 rv = NS_NewThread(getter_AddRefs(thread), receiver);
162 if (NS_FAILED(rv)) return rv;
164 uint32_t total = 0;
165 PRIntervalTime start = PR_IntervalNow();
166 for (uint32_t i = 0; i < ITERATIONS; i++) {
167 uint32_t writeCount;
168 char *buf = PR_smprintf("%d %s", i, kTestPattern);
169 uint32_t len = strlen(buf);
170 rv = WriteAll(out, buf, len, &writeCount);
171 if (gTrace) {
172 printf("wrote: ");
173 for (uint32_t j = 0; j < writeCount; j++) {
174 putc(buf[j], stdout);
175 }
176 printf("\n");
177 }
178 PR_smprintf_free(buf);
179 if (NS_FAILED(rv)) return rv;
180 total += writeCount;
181 }
182 rv = out->Close();
183 if (NS_FAILED(rv)) return rv;
185 PRIntervalTime end = PR_IntervalNow();
187 thread->Shutdown();
189 printf("wrote %d bytes, time = %dms\n", total,
190 PR_IntervalToMilliseconds(end - start));
191 NS_ASSERTION(receiver->GetBytesRead() == total, "didn't read everything");
193 return NS_OK;
194 }
196 ////////////////////////////////////////////////////////////////////////////////
198 class nsShortReader : public nsIRunnable {
199 public:
200 NS_DECL_THREADSAFE_ISUPPORTS
202 NS_IMETHOD Run() {
203 nsresult rv;
204 char buf[101];
205 uint32_t count;
206 uint32_t total = 0;
207 while (true) {
208 //if (gTrace)
209 // printf("calling Read\n");
210 rv = mIn->Read(buf, 100, &count);
211 if (NS_FAILED(rv)) {
212 printf("read failed\n");
213 break;
214 }
215 if (count == 0) {
216 break;
217 }
219 if (gTrace) {
220 // For next |printf()| call and possible others elsewhere.
221 buf[count] = '\0';
223 printf("read %d bytes: %s\n", count, buf);
224 }
226 Received(count);
227 total += count;
228 }
229 printf("read %d bytes\n", total);
230 return rv;
231 }
233 nsShortReader(nsIInputStream* in) : mIn(in), mReceived(0) {
234 mMon = new Monitor("nsShortReader");
235 }
237 void Received(uint32_t count) {
238 MonitorAutoEnter mon(*mMon);
239 mReceived += count;
240 mon.Notify();
241 }
243 uint32_t WaitForReceipt(const uint32_t aWriteCount) {
244 MonitorAutoEnter mon(*mMon);
245 uint32_t result = mReceived;
247 while (result < aWriteCount) {
248 mon.Wait();
250 NS_ASSERTION(mReceived > result, "failed to receive");
251 result = mReceived;
252 }
254 mReceived = 0;
255 return result;
256 }
258 protected:
259 nsCOMPtr<nsIInputStream> mIn;
260 uint32_t mReceived;
261 Monitor* mMon;
262 };
264 NS_IMPL_ISUPPORTS(nsShortReader, nsIRunnable)
266 nsresult
267 TestShortWrites(nsIInputStream* in, nsIOutputStream* out)
268 {
269 nsCOMPtr<nsShortReader> receiver = new nsShortReader(in);
270 if (!receiver)
271 return NS_ERROR_OUT_OF_MEMORY;
273 nsresult rv;
275 nsCOMPtr<nsIThread> thread;
276 rv = NS_NewThread(getter_AddRefs(thread), receiver);
277 if (NS_FAILED(rv)) return rv;
279 uint32_t total = 0;
280 for (uint32_t i = 0; i < ITERATIONS; i++) {
281 uint32_t writeCount;
282 char* buf = PR_smprintf("%d %s", i, kTestPattern);
283 uint32_t len = strlen(buf);
284 len = len * rand() / RAND_MAX;
285 len = XPCOM_MAX(1, len);
286 rv = WriteAll(out, buf, len, &writeCount);
287 if (NS_FAILED(rv)) return rv;
288 NS_ASSERTION(writeCount == len, "didn't write enough");
289 total += writeCount;
291 if (gTrace)
292 printf("wrote %d bytes: %s\n", writeCount, buf);
293 PR_smprintf_free(buf);
294 //printf("calling Flush\n");
295 out->Flush();
296 //printf("calling WaitForReceipt\n");
298 #ifdef DEBUG
299 const uint32_t received =
300 #endif
301 receiver->WaitForReceipt(writeCount);
302 NS_ASSERTION(received == writeCount, "received wrong amount");
303 }
304 rv = out->Close();
305 if (NS_FAILED(rv)) return rv;
307 thread->Shutdown();
309 printf("wrote %d bytes\n", total);
311 return NS_OK;
312 }
314 ////////////////////////////////////////////////////////////////////////////////
316 class nsPump : public nsIRunnable
317 {
318 public:
319 NS_DECL_THREADSAFE_ISUPPORTS
321 NS_IMETHOD Run() {
322 nsresult rv;
323 uint32_t count;
324 while (true) {
325 rv = mOut->WriteFrom(mIn, ~0U, &count);
326 if (NS_FAILED(rv)) {
327 printf("Write failed\n");
328 break;
329 }
330 if (count == 0) {
331 printf("EOF count = %d\n", mCount);
332 break;
333 }
335 if (gTrace) {
336 printf("Wrote: %d\n", count);
337 }
338 mCount += count;
339 }
340 mOut->Close();
341 return rv;
342 }
344 nsPump(nsIInputStream* in,
345 nsIOutputStream* out)
346 : mIn(in), mOut(out), mCount(0) {
347 }
349 protected:
350 nsCOMPtr<nsIInputStream> mIn;
351 nsCOMPtr<nsIOutputStream> mOut;
352 uint32_t mCount;
353 };
355 NS_IMPL_ISUPPORTS(nsPump, nsIRunnable)
357 nsresult
358 TestChainedPipes()
359 {
360 nsresult rv;
361 printf("TestChainedPipes\n");
363 nsCOMPtr<nsIInputStream> in1;
364 nsCOMPtr<nsIOutputStream> out1;
365 rv = TP_NewPipe(getter_AddRefs(in1), getter_AddRefs(out1), 20, 1999);
366 if (NS_FAILED(rv)) return rv;
368 nsCOMPtr<nsIInputStream> in2;
369 nsCOMPtr<nsIOutputStream> out2;
370 rv = TP_NewPipe(getter_AddRefs(in2), getter_AddRefs(out2), 200, 401);
371 if (NS_FAILED(rv)) return rv;
373 nsCOMPtr<nsPump> pump = new nsPump(in1, out2);
374 if (pump == nullptr) return NS_ERROR_OUT_OF_MEMORY;
376 nsCOMPtr<nsIThread> thread;
377 rv = NS_NewThread(getter_AddRefs(thread), pump);
378 if (NS_FAILED(rv)) return rv;
380 nsCOMPtr<nsReceiver> receiver = new nsReceiver(in2);
381 if (receiver == nullptr) return NS_ERROR_OUT_OF_MEMORY;
383 nsCOMPtr<nsIThread> receiverThread;
384 rv = NS_NewThread(getter_AddRefs(receiverThread), receiver);
385 if (NS_FAILED(rv)) return rv;
387 uint32_t total = 0;
388 for (uint32_t i = 0; i < ITERATIONS; i++) {
389 uint32_t writeCount;
390 char* buf = PR_smprintf("%d %s", i, kTestPattern);
391 uint32_t len = strlen(buf);
392 len = len * rand() / RAND_MAX;
393 len = XPCOM_MAX(1, len);
394 rv = WriteAll(out1, buf, len, &writeCount);
395 if (NS_FAILED(rv)) return rv;
396 NS_ASSERTION(writeCount == len, "didn't write enough");
397 total += writeCount;
399 if (gTrace)
400 printf("wrote %d bytes: %s\n", writeCount, buf);
402 PR_smprintf_free(buf);
403 }
404 printf("wrote total of %d bytes\n", total);
405 rv = out1->Close();
406 if (NS_FAILED(rv)) return rv;
408 thread->Shutdown();
409 receiverThread->Shutdown();
411 return NS_OK;
412 }
414 ////////////////////////////////////////////////////////////////////////////////
416 void
417 RunTests(uint32_t segSize, uint32_t segCount)
418 {
419 nsresult rv;
420 nsCOMPtr<nsIInputStream> in;
421 nsCOMPtr<nsIOutputStream> out;
422 uint32_t bufSize = segSize * segCount;
423 printf("Testing New Pipes: segment size %d buffer size %d\n", segSize, bufSize);
425 printf("Testing long writes...\n");
426 rv = TP_NewPipe(getter_AddRefs(in), getter_AddRefs(out), segSize, bufSize);
427 NS_ASSERTION(NS_SUCCEEDED(rv), "TP_NewPipe failed");
428 rv = TestPipe(in, out);
429 NS_ASSERTION(NS_SUCCEEDED(rv), "TestPipe failed");
431 printf("Testing short writes...\n");
432 rv = TP_NewPipe(getter_AddRefs(in), getter_AddRefs(out), segSize, bufSize);
433 NS_ASSERTION(NS_SUCCEEDED(rv), "TP_NewPipe failed");
434 rv = TestShortWrites(in, out);
435 NS_ASSERTION(NS_SUCCEEDED(rv), "TestPipe failed");
436 }
438 ////////////////////////////////////////////////////////////////////////////////
440 #if 0
441 extern void
442 TestSegmentedBuffer();
443 #endif
445 int
446 main(int argc, char* argv[])
447 {
448 nsresult rv;
450 nsCOMPtr<nsIServiceManager> servMgr;
451 rv = NS_InitXPCOM2(getter_AddRefs(servMgr), nullptr, nullptr);
452 if (NS_FAILED(rv)) return rv;
454 if (argc > 1 && nsCRT::strcmp(argv[1], "-trace") == 0)
455 gTrace = true;
457 rv = TestChainedPipes();
458 NS_ASSERTION(NS_SUCCEEDED(rv), "TestChainedPipes failed");
459 RunTests(16, 1);
460 RunTests(4096, 16);
462 servMgr = 0;
463 rv = NS_ShutdownXPCOM(nullptr);
464 NS_ASSERTION(NS_SUCCEEDED(rv), "NS_ShutdownXPCOM failed");
466 return 0;
467 }
469 ////////////////////////////////////////////////////////////////////////////////