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 /* vim:set ts=2 sw=2 sts=2 et cindent: */
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 #include <stdlib.h>
8 #include <stdio.h>
9 #include <prthread.h>
10 #include "nsExpirationTracker.h"
11 #include "nsMemory.h"
12 #include "nsAutoPtr.h"
13 #include "nsString.h"
14 #include "nsDirectoryServiceDefs.h"
15 #include "nsDirectoryServiceUtils.h"
16 #include "nsComponentManagerUtils.h"
17 #include "nsXPCOM.h"
18 #include "nsIFile.h"
19 #include "prinrval.h"
20 #include "nsThreadUtils.h"
22 namespace TestExpirationTracker {
24 struct Object {
25 Object() : mExpired(false) { Touch(); }
26 void Touch() { mLastUsed = PR_IntervalNow(); mExpired = false; }
28 nsExpirationState mExpiration;
29 nsExpirationState* GetExpirationState() { return &mExpiration; }
31 PRIntervalTime mLastUsed;
32 bool mExpired;
33 };
35 static bool error;
36 static uint32_t periodMS = 100;
37 static uint32_t ops = 1000;
38 static uint32_t iterations = 2;
39 static bool logging = 0;
40 static uint32_t sleepPeriodMS = 50;
41 static uint32_t slackMS = 20; // allow this much error
43 static void SignalError() {
44 printf("ERROR!\n");
45 error = true;
46 }
48 template <uint32_t K> class Tracker : public nsExpirationTracker<Object,K> {
49 public:
50 Tracker() : nsExpirationTracker<Object,K>(periodMS) {
51 Object* obj = new Object();
52 mUniverse.AppendElement(obj);
53 LogAction(obj, "Created");
54 }
56 nsTArray<nsAutoArrayPtr<Object> > mUniverse;
58 void LogAction(Object* aObj, const char* aAction) {
59 if (logging) {
60 printf("%d %p(%d): %s\n", PR_IntervalNow(),
61 static_cast<void*>(aObj), aObj->mLastUsed, aAction);
62 }
63 }
65 void DoRandomOperation() {
66 Object* obj;
67 switch (rand() & 0x7) {
68 case 0: {
69 if (mUniverse.Length() < 50) {
70 obj = new Object();
71 mUniverse.AppendElement(obj);
72 nsExpirationTracker<Object,K>::AddObject(obj);
73 LogAction(obj, "Created and added");
74 }
75 break;
76 }
77 case 4: {
78 if (mUniverse.Length() < 50) {
79 obj = new Object();
80 mUniverse.AppendElement(obj);
81 LogAction(obj, "Created");
82 }
83 break;
84 }
85 case 1: {
86 obj = mUniverse[uint32_t(rand())%mUniverse.Length()];
87 if (obj->mExpiration.IsTracked()) {
88 nsExpirationTracker<Object,K>::RemoveObject(obj);
89 LogAction(obj, "Removed");
90 }
91 break;
92 }
93 case 2: {
94 obj = mUniverse[uint32_t(rand())%mUniverse.Length()];
95 if (!obj->mExpiration.IsTracked()) {
96 obj->Touch();
97 nsExpirationTracker<Object,K>::AddObject(obj);
98 LogAction(obj, "Added");
99 }
100 break;
101 }
102 case 3: {
103 obj = mUniverse[uint32_t(rand())%mUniverse.Length()];
104 if (obj->mExpiration.IsTracked()) {
105 obj->Touch();
106 nsExpirationTracker<Object,K>::MarkUsed(obj);
107 LogAction(obj, "Marked used");
108 }
109 break;
110 }
111 }
112 }
114 protected:
115 void NotifyExpired(Object* aObj) {
116 LogAction(aObj, "Expired");
117 PRIntervalTime now = PR_IntervalNow();
118 uint32_t timeDiffMS = (now - aObj->mLastUsed)*1000/PR_TicksPerSecond();
119 // See the comment for NotifyExpired in nsExpirationTracker.h for these
120 // bounds
121 uint32_t lowerBoundMS = (K-1)*periodMS - slackMS;
122 uint32_t upperBoundMS = K*(periodMS + sleepPeriodMS) + slackMS;
123 if (logging) {
124 printf("Checking: %d-%d = %d [%d,%d]\n",
125 now, aObj->mLastUsed, timeDiffMS, lowerBoundMS, upperBoundMS);
126 }
127 if (timeDiffMS < lowerBoundMS || timeDiffMS > upperBoundMS) {
128 if (timeDiffMS < periodMS && aObj->mExpired) {
129 // This is probably OK, it probably just expired twice
130 } else {
131 SignalError();
132 }
133 }
134 aObj->Touch();
135 aObj->mExpired = true;
136 DoRandomOperation();
137 DoRandomOperation();
138 DoRandomOperation();
139 }
140 };
142 template <uint32_t K> static bool test_random() {
143 srand(K);
144 error = false;
146 for (uint32_t j = 0; j < iterations; ++j) {
147 Tracker<K> tracker;
149 uint32_t i = 0;
150 for (i = 0; i < ops; ++i) {
151 if ((rand() & 0xF) == 0) {
152 // Simulate work that takes time
153 if (logging) {
154 printf("SLEEPING for %dms (%d)\n", sleepPeriodMS, PR_IntervalNow());
155 }
156 PR_Sleep(PR_MillisecondsToInterval(sleepPeriodMS));
157 // Process pending timer events
158 NS_ProcessPendingEvents(nullptr);
159 }
160 tracker.DoRandomOperation();
161 }
162 }
164 return !error;
165 }
167 static bool test_random3() { return test_random<3>(); }
168 static bool test_random4() { return test_random<4>(); }
169 static bool test_random8() { return test_random<8>(); }
171 typedef bool (*TestFunc)();
172 #define DECL_TEST(name) { #name, name }
174 static const struct Test {
175 const char* name;
176 TestFunc func;
177 } tests[] = {
178 DECL_TEST(test_random3),
179 DECL_TEST(test_random4),
180 DECL_TEST(test_random8),
181 { nullptr, nullptr }
182 };
184 }
186 using namespace TestExpirationTracker;
188 int main(int argc, char **argv) {
189 int count = 1;
190 if (argc > 1)
191 count = atoi(argv[1]);
193 if (NS_FAILED(NS_InitXPCOM2(nullptr, nullptr, nullptr)))
194 return -1;
196 while (count--) {
197 for (const Test* t = tests; t->name != nullptr; ++t) {
198 printf("%25s : %s\n", t->name, t->func() ? "SUCCESS" : "FAILURE");
199 }
200 }
202 NS_ShutdownXPCOM(nullptr);
203 return 0;
204 }