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: 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 "nsTHashtable.h"
7 #include "nsBaseHashtable.h"
8 #include "nsDataHashtable.h"
9 #include "nsInterfaceHashtable.h"
10 #include "nsClassHashtable.h"
12 #include "nsCOMPtr.h"
13 #include "nsISupports.h"
14 #include "nsCOMArray.h"
15 #include "mozilla/Attributes.h"
17 #include <stdio.h>
19 namespace TestHashtables {
21 class TestUniChar // for nsClassHashtable
22 {
23 public:
24 TestUniChar(uint32_t aWord)
25 {
26 printf(" TestUniChar::TestUniChar() %u\n", aWord);
27 mWord = aWord;
28 }
30 ~TestUniChar()
31 {
32 printf(" TestUniChar::~TestUniChar() %u\n", mWord);
33 }
35 uint32_t GetChar() const { return mWord; }
37 private:
38 uint32_t mWord;
39 };
41 struct EntityNode {
42 const char* mStr; // never owns buffer
43 uint32_t mUnicode;
44 };
46 EntityNode gEntities[] = {
47 {"nbsp",160},
48 {"iexcl",161},
49 {"cent",162},
50 {"pound",163},
51 {"curren",164},
52 {"yen",165},
53 {"brvbar",166},
54 {"sect",167},
55 {"uml",168},
56 {"copy",169},
57 {"ordf",170},
58 {"laquo",171},
59 {"not",172},
60 {"shy",173},
61 {"reg",174},
62 {"macr",175}
63 };
65 #define ENTITY_COUNT (unsigned(sizeof(gEntities)/sizeof(EntityNode)))
67 class EntityToUnicodeEntry : public PLDHashEntryHdr
68 {
69 public:
70 typedef const char* KeyType;
71 typedef const char* KeyTypePointer;
73 EntityToUnicodeEntry(const char* aKey) { mNode = nullptr; }
74 EntityToUnicodeEntry(const EntityToUnicodeEntry& aEntry) { mNode = aEntry.mNode; }
75 ~EntityToUnicodeEntry() { }
77 bool KeyEquals(const char* aEntity) const { return !strcmp(mNode->mStr, aEntity); }
78 static const char* KeyToPointer(const char* aEntity) { return aEntity; }
79 static PLDHashNumber HashKey(const char* aEntity) { return mozilla::HashString(aEntity); }
80 enum { ALLOW_MEMMOVE = true };
82 const EntityNode* mNode;
83 };
85 PLDHashOperator
86 nsTEnumGo(EntityToUnicodeEntry* aEntry, void* userArg) {
87 printf(" enumerated \"%s\" = %u\n",
88 aEntry->mNode->mStr, aEntry->mNode->mUnicode);
90 return PL_DHASH_NEXT;
91 }
93 PLDHashOperator
94 nsTEnumStop(EntityToUnicodeEntry* aEntry, void* userArg) {
95 printf(" enumerated \"%s\" = %u\n",
96 aEntry->mNode->mStr, aEntry->mNode->mUnicode);
98 return PL_DHASH_REMOVE;
99 }
101 void
102 testTHashtable(nsTHashtable<EntityToUnicodeEntry>& hash, uint32_t numEntries) {
103 printf("Filling hash with %d entries.\n", numEntries);
105 uint32_t i;
106 for (i = 0; i < numEntries; ++i) {
107 printf(" Putting entry \"%s\"...", gEntities[i].mStr);
108 EntityToUnicodeEntry* entry =
109 hash.PutEntry(gEntities[i].mStr);
111 if (!entry) {
112 printf("FAILED\n");
113 exit (2);
114 }
115 printf("OK...");
117 if (entry->mNode) {
118 printf("entry already exists!\n");
119 exit (3);
120 }
121 printf("\n");
123 entry->mNode = &gEntities[i];
124 }
126 printf("Testing Get:\n");
128 for (i = 0; i < numEntries; ++i) {
129 printf(" Getting entry \"%s\"...", gEntities[i].mStr);
130 EntityToUnicodeEntry* entry =
131 hash.GetEntry(gEntities[i].mStr);
133 if (!entry) {
134 printf("FAILED\n");
135 exit (4);
136 }
138 printf("Found %u\n", entry->mNode->mUnicode);
139 }
141 printf("Testing nonexistent entries...");
143 EntityToUnicodeEntry* entry =
144 hash.GetEntry("xxxy");
146 if (entry) {
147 printf("FOUND! BAD!\n");
148 exit (5);
149 }
151 printf("not found; good.\n");
153 printf("Enumerating:\n");
154 uint32_t count = hash.EnumerateEntries(nsTEnumGo, nullptr);
155 if (count != numEntries) {
156 printf(" Bad count!\n");
157 exit (6);
158 }
159 }
161 PLDHashOperator
162 nsDEnumRead(const uint32_t& aKey, const char* aData, void* userArg) {
163 printf(" enumerated %u = \"%s\"\n", aKey, aData);
164 return PL_DHASH_NEXT;
165 }
167 PLDHashOperator
168 nsDEnum(const uint32_t& aKey, const char*& aData, void* userArg) {
169 printf(" enumerated %u = \"%s\"\n", aKey, aData);
170 return PL_DHASH_NEXT;
171 }
173 PLDHashOperator
174 nsCEnumRead(const nsACString& aKey, TestUniChar* aData, void* userArg) {
175 printf(" enumerated \"%s\" = %c\n",
176 PromiseFlatCString(aKey).get(), aData->GetChar());
177 return PL_DHASH_NEXT;
178 }
180 PLDHashOperator
181 nsCEnum(const nsACString& aKey, nsAutoPtr<TestUniChar>& aData, void* userArg) {
182 printf(" enumerated \"%s\" = %c\n",
183 PromiseFlatCString(aKey).get(), aData->GetChar());
184 return PL_DHASH_NEXT;
185 }
187 //
188 // all this nsIFoo stuff was copied wholesale from TestCOMPtr.cpp
189 //
191 #define NS_IFOO_IID \
192 { 0x6f7652e0, 0xee43, 0x11d1, \
193 { 0x9c, 0xc3, 0x00, 0x60, 0x08, 0x8c, 0xa6, 0xb3 } }
195 class IFoo MOZ_FINAL : public nsISupports
196 {
197 public:
198 NS_DECLARE_STATIC_IID_ACCESSOR(NS_IFOO_IID)
200 IFoo();
202 NS_IMETHOD_(MozExternalRefCountType) AddRef();
203 NS_IMETHOD_(MozExternalRefCountType) Release();
204 NS_IMETHOD QueryInterface( const nsIID&, void** );
206 NS_IMETHOD SetString(const nsACString& /*in*/ aString);
207 NS_IMETHOD GetString(nsACString& /*out*/ aString);
209 static void print_totals();
211 private:
212 ~IFoo();
214 unsigned int refcount_;
216 static unsigned int total_constructions_;
217 static unsigned int total_destructions_;
218 nsCString mString;
219 };
221 NS_DEFINE_STATIC_IID_ACCESSOR(IFoo, NS_IFOO_IID)
223 unsigned int IFoo::total_constructions_;
224 unsigned int IFoo::total_destructions_;
226 void
227 IFoo::print_totals()
228 {
229 printf("total constructions/destructions --> %d/%d\n",
230 total_constructions_, total_destructions_);
231 }
233 IFoo::IFoo()
234 : refcount_(0)
235 {
236 ++total_constructions_;
237 printf(" new IFoo@%p [#%d]\n",
238 static_cast<void*>(this), total_constructions_);
239 }
241 IFoo::~IFoo()
242 {
243 ++total_destructions_;
244 printf("IFoo@%p::~IFoo() [#%d]\n",
245 static_cast<void*>(this), total_destructions_);
246 }
248 MozExternalRefCountType
249 IFoo::AddRef()
250 {
251 ++refcount_;
252 printf("IFoo@%p::AddRef(), refcount --> %d\n",
253 static_cast<void*>(this), refcount_);
254 return refcount_;
255 }
257 MozExternalRefCountType
258 IFoo::Release()
259 {
260 int newcount = --refcount_;
261 if ( newcount == 0 )
262 printf(">>");
264 printf("IFoo@%p::Release(), refcount --> %d\n",
265 static_cast<void*>(this), refcount_);
267 if ( newcount == 0 )
268 {
269 printf(" delete IFoo@%p\n", static_cast<void*>(this));
270 printf("<<IFoo@%p::Release()\n", static_cast<void*>(this));
271 delete this;
272 }
274 return newcount;
275 }
277 nsresult
278 IFoo::QueryInterface( const nsIID& aIID, void** aResult )
279 {
280 printf("IFoo@%p::QueryInterface()\n", static_cast<void*>(this));
281 nsISupports* rawPtr = 0;
282 nsresult status = NS_OK;
284 if ( aIID.Equals(NS_GET_IID(IFoo)) )
285 rawPtr = this;
286 else
287 {
288 nsID iid_of_ISupports = NS_ISUPPORTS_IID;
289 if ( aIID.Equals(iid_of_ISupports) )
290 rawPtr = static_cast<nsISupports*>(this);
291 else
292 status = NS_ERROR_NO_INTERFACE;
293 }
295 NS_IF_ADDREF(rawPtr);
296 *aResult = rawPtr;
298 return status;
299 }
301 nsresult
302 IFoo::SetString(const nsACString& aString)
303 {
304 mString = aString;
305 return NS_OK;
306 }
308 nsresult
309 IFoo::GetString(nsACString& aString)
310 {
311 aString = mString;
312 return NS_OK;
313 }
315 nsresult
316 CreateIFoo( IFoo** result )
317 // a typical factory function (that calls AddRef)
318 {
319 printf(" >>CreateIFoo() --> ");
320 IFoo* foop = new IFoo();
321 printf("IFoo@%p\n", static_cast<void*>(foop));
323 foop->AddRef();
324 *result = foop;
326 printf("<<CreateIFoo()\n");
327 return NS_OK;
328 }
330 PLDHashOperator
331 nsIEnumRead(const uint32_t& aKey, IFoo* aFoo, void* userArg) {
332 nsAutoCString str;
333 aFoo->GetString(str);
335 printf(" enumerated %u = \"%s\"\n", aKey, str.get());
336 return PL_DHASH_NEXT;
337 }
339 PLDHashOperator
340 nsIEnum(const uint32_t& aKey, nsCOMPtr<IFoo>& aData, void* userArg) {
341 nsAutoCString str;
342 aData->GetString(str);
344 printf(" enumerated %u = \"%s\"\n", aKey, str.get());
345 return PL_DHASH_NEXT;
346 }
348 PLDHashOperator
349 nsIEnum2Read(nsISupports* aKey, uint32_t aData, void* userArg) {
350 nsAutoCString str;
351 nsCOMPtr<IFoo> foo = do_QueryInterface(aKey);
352 foo->GetString(str);
355 printf(" enumerated \"%s\" = %u\n", str.get(), aData);
356 return PL_DHASH_NEXT;
357 }
359 PLDHashOperator
360 nsIEnum2(nsISupports* aKey, uint32_t& aData, void* userArg) {
361 nsAutoCString str;
362 nsCOMPtr<IFoo> foo = do_QueryInterface(aKey);
363 foo->GetString(str);
365 printf(" enumerated \"%s\" = %u\n", str.get(), aData);
366 return PL_DHASH_NEXT;
367 }
369 }
371 using namespace TestHashtables;
373 int
374 main(void) {
375 // check an nsTHashtable
376 printf("Initializing nsTHashtable...");
377 nsTHashtable<EntityToUnicodeEntry> EntityToUnicode(ENTITY_COUNT);
378 printf("OK\n");
380 printf("Partially filling nsTHashtable:\n");
381 testTHashtable(EntityToUnicode, 5);
383 printf("Enumerate-removing...\n");
384 uint32_t count = EntityToUnicode.EnumerateEntries(nsTEnumStop, nullptr);
385 if (count != 5) {
386 printf("wrong count\n");
387 exit (7);
388 }
389 printf("OK\n");
391 printf("Check enumeration...");
392 count = EntityToUnicode.EnumerateEntries(nsTEnumGo, nullptr);
393 if (count) {
394 printf("entries remain in table!\n");
395 exit (8);
396 }
397 printf("OK\n");
399 printf("Filling nsTHashtable:\n");
400 testTHashtable(EntityToUnicode, ENTITY_COUNT);
402 printf("Clearing...");
403 EntityToUnicode.Clear();
404 printf("OK\n");
406 printf("Check enumeration...");
407 count = EntityToUnicode.EnumerateEntries(nsTEnumGo, nullptr);
408 if (count) {
409 printf("entries remain in table!\n");
410 exit (9);
411 }
412 printf("OK\n");
414 //
415 // now check a data-hashtable
416 //
418 printf("Initializing nsDataHashtable...");
419 nsDataHashtable<nsUint32HashKey,const char*> UniToEntity(ENTITY_COUNT);
420 printf("OK\n");
422 printf("Filling hash with %u entries.\n", ENTITY_COUNT);
424 uint32_t i;
425 for (i = 0; i < ENTITY_COUNT; ++i) {
426 printf(" Putting entry %u...", gEntities[i].mUnicode);
427 UniToEntity.Put(gEntities[i].mUnicode, gEntities[i].mStr);
428 printf("OK...\n");
429 }
431 printf("Testing Get:\n");
432 const char* str;
434 for (i = 0; i < ENTITY_COUNT; ++i) {
435 printf(" Getting entry %u...", gEntities[i].mUnicode);
436 if (!UniToEntity.Get(gEntities[i].mUnicode, &str)) {
437 printf("FAILED\n");
438 exit (12);
439 }
441 printf("Found %s\n", str);
442 }
444 printf("Testing nonexistent entries...");
445 if (UniToEntity.Get(99446, &str)) {
446 printf("FOUND! BAD!\n");
447 exit (13);
448 }
450 printf("not found; good.\n");
452 printf("Enumerating:\n");
454 count = UniToEntity.EnumerateRead(nsDEnumRead, nullptr);
455 if (count != ENTITY_COUNT) {
456 printf(" Bad count!\n");
457 exit (14);
458 }
460 printf("Clearing...");
461 UniToEntity.Clear();
462 printf("OK\n");
464 printf("Checking count...");
465 count = UniToEntity.Enumerate(nsDEnum, nullptr);
466 if (count) {
467 printf(" Clear did not remove all entries.\n");
468 exit (15);
469 }
471 printf("OK\n");
473 //
474 // now check a class-hashtable
475 //
477 printf("Initializing nsClassHashtable...");
478 nsClassHashtable<nsCStringHashKey,TestUniChar> EntToUniClass(ENTITY_COUNT);
479 printf("OK\n");
481 printf("Filling hash with %u entries.\n", ENTITY_COUNT);
483 for (i = 0; i < ENTITY_COUNT; ++i) {
484 printf(" Putting entry %u...", gEntities[i].mUnicode);
485 TestUniChar* temp = new TestUniChar(gEntities[i].mUnicode);
487 EntToUniClass.Put(nsDependentCString(gEntities[i].mStr), temp);
488 printf("OK...\n");
489 }
491 printf("Testing Get:\n");
492 TestUniChar* myChar;
494 for (i = 0; i < ENTITY_COUNT; ++i) {
495 printf(" Getting entry %s...", gEntities[i].mStr);
496 if (!EntToUniClass.Get(nsDependentCString(gEntities[i].mStr), &myChar)) {
497 printf("FAILED\n");
498 exit (18);
499 }
501 printf("Found %c\n", myChar->GetChar());
502 }
504 printf("Testing nonexistent entries...");
505 if (EntToUniClass.Get(NS_LITERAL_CSTRING("xxxx"), &myChar)) {
506 printf("FOUND! BAD!\n");
507 exit (19);
508 }
510 printf("not found; good.\n");
512 printf("Enumerating:\n");
514 count = EntToUniClass.EnumerateRead(nsCEnumRead, nullptr);
515 if (count != ENTITY_COUNT) {
516 printf(" Bad count!\n");
517 exit (20);
518 }
520 printf("Clearing...\n");
521 EntToUniClass.Clear();
522 printf(" Clearing OK\n");
524 printf("Checking count...");
525 count = EntToUniClass.Enumerate(nsCEnum, nullptr);
526 if (count) {
527 printf(" Clear did not remove all entries.\n");
528 exit (21);
529 }
531 printf("OK\n");
533 //
534 // now check a data-hashtable with an interface key
535 //
537 printf("Initializing nsDataHashtable with interface key...");
538 nsDataHashtable<nsISupportsHashKey,uint32_t> EntToUniClass2(ENTITY_COUNT);
539 printf("OK\n");
541 printf("Filling hash with %u entries.\n", ENTITY_COUNT);
543 nsCOMArray<IFoo> fooArray;
545 for (i = 0; i < ENTITY_COUNT; ++i) {
546 printf(" Putting entry %u...", gEntities[i].mUnicode);
547 nsCOMPtr<IFoo> foo;
548 CreateIFoo(getter_AddRefs(foo));
549 foo->SetString(nsDependentCString(gEntities[i].mStr));
552 fooArray.InsertObjectAt(foo, i);
554 EntToUniClass2.Put(foo, gEntities[i].mUnicode);
555 printf("OK...\n");
556 }
558 printf("Testing Get:\n");
559 uint32_t myChar2;
561 for (i = 0; i < ENTITY_COUNT; ++i) {
562 printf(" Getting entry %s...", gEntities[i].mStr);
564 if (!EntToUniClass2.Get(fooArray[i], &myChar2)) {
565 printf("FAILED\n");
566 exit (24);
567 }
569 printf("Found %c\n", myChar2);
570 }
572 printf("Testing nonexistent entries...");
573 if (EntToUniClass2.Get((nsISupports*) 0x55443316, &myChar2)) {
574 printf("FOUND! BAD!\n");
575 exit (25);
576 }
578 printf("not found; good.\n");
580 printf("Enumerating:\n");
582 count = EntToUniClass2.EnumerateRead(nsIEnum2Read, nullptr);
583 if (count != ENTITY_COUNT) {
584 printf(" Bad count!\n");
585 exit (26);
586 }
588 printf("Clearing...\n");
589 EntToUniClass2.Clear();
590 printf(" Clearing OK\n");
592 printf("Checking count...");
593 count = EntToUniClass2.Enumerate(nsIEnum2, nullptr);
594 if (count) {
595 printf(" Clear did not remove all entries.\n");
596 exit (27);
597 }
599 printf("OK\n");
601 //
602 // now check an interface-hashtable with an uint32_t key
603 //
605 printf("Initializing nsInterfaceHashtable...");
606 nsInterfaceHashtable<nsUint32HashKey,IFoo> UniToEntClass2(ENTITY_COUNT);
607 printf("OK\n");
609 printf("Filling hash with %u entries.\n", ENTITY_COUNT);
611 for (i = 0; i < ENTITY_COUNT; ++i) {
612 printf(" Putting entry %u...", gEntities[i].mUnicode);
613 nsCOMPtr<IFoo> foo;
614 CreateIFoo(getter_AddRefs(foo));
615 foo->SetString(nsDependentCString(gEntities[i].mStr));
617 UniToEntClass2.Put(gEntities[i].mUnicode, foo);
618 printf("OK...\n");
619 }
621 printf("Testing Get:\n");
623 for (i = 0; i < ENTITY_COUNT; ++i) {
624 printf(" Getting entry %s...", gEntities[i].mStr);
626 nsCOMPtr<IFoo> myEnt;
627 if (!UniToEntClass2.Get(gEntities[i].mUnicode, getter_AddRefs(myEnt))) {
628 printf("FAILED\n");
629 exit (30);
630 }
632 nsAutoCString str;
633 myEnt->GetString(str);
634 printf("Found %s\n", str.get());
635 }
637 printf("Testing nonexistent entries...");
638 nsCOMPtr<IFoo> myEnt;
639 if (UniToEntClass2.Get(9462, getter_AddRefs(myEnt))) {
640 printf("FOUND! BAD!\n");
641 exit (31);
642 }
644 printf("not found; good.\n");
646 printf("Enumerating:\n");
648 count = UniToEntClass2.EnumerateRead(nsIEnumRead, nullptr);
649 if (count != ENTITY_COUNT) {
650 printf(" Bad count!\n");
651 exit (32);
652 }
654 printf("Clearing...\n");
655 UniToEntClass2.Clear();
656 printf(" Clearing OK\n");
658 printf("Checking count...");
659 count = UniToEntClass2.Enumerate(nsIEnum, nullptr);
660 if (count) {
661 printf(" Clear did not remove all entries.\n");
662 exit (33);
663 }
665 printf("OK\n");
667 return 0;
668 }