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/. */
5 
6 #include "TestCommon.h"
7 #include "gtest/gtest.h"
8 #include "nsContentUtils.h"
9 #include "nsICookieService.h"
10 #include "nsICookieManager.h"
11 #include "nsICookie.h"
12 #include <stdio.h>
13 #include "plstr.h"
14 #include "nsNetUtil.h"
15 #include "nsIChannel.h"
16 #include "nsIPrincipal.h"
17 #include "nsIScriptSecurityManager.h"
18 #include "nsServiceManagerUtils.h"
19 #include "nsNetCID.h"
20 #include "nsIPrefBranch.h"
21 #include "nsIPrefService.h"
22 #include "mozilla/dom/Document.h"
23 #include "mozilla/Preferences.h"
24 #include "mozilla/Unused.h"
25 #include "mozilla/net/CookieJarSettings.h"
26 #include "Cookie.h"
27 #include "nsIURI.h"
28 
29 using mozilla::Unused;
30 
31 static NS_DEFINE_CID(kCookieServiceCID, NS_COOKIESERVICE_CID);
32 static NS_DEFINE_CID(kPrefServiceCID, NS_PREFSERVICE_CID);
33 
34 // various pref strings
35 static const char kCookiesPermissions[] = "network.cookie.cookieBehavior";
36 static const char kPrefCookieQuotaPerHost[] = "network.cookie.quotaPerHost";
37 static const char kCookiesMaxPerHost[] = "network.cookie.maxPerHost";
38 
39 #define OFFSET_ONE_WEEK int64_t(604800) * PR_USEC_PER_SEC
40 #define OFFSET_ONE_DAY int64_t(86400) * PR_USEC_PER_SEC
41 
42 // Set server time or expiry time
SetTime(PRTime offsetTime,nsAutoCString & serverString,nsAutoCString & cookieString,bool expiry)43 void SetTime(PRTime offsetTime, nsAutoCString& serverString,
44              nsAutoCString& cookieString, bool expiry) {
45   char timeStringPreset[40];
46   PRTime CurrentTime = PR_Now();
47   PRTime SetCookieTime = CurrentTime + offsetTime;
48   PRTime SetExpiryTime;
49   if (expiry) {
50     SetExpiryTime = SetCookieTime - OFFSET_ONE_DAY;
51   } else {
52     SetExpiryTime = SetCookieTime + OFFSET_ONE_DAY;
53   }
54 
55   // Set server time string
56   PRExplodedTime explodedTime;
57   PR_ExplodeTime(SetCookieTime, PR_GMTParameters, &explodedTime);
58   PR_FormatTimeUSEnglish(timeStringPreset, 40, "%c GMT", &explodedTime);
59   serverString.Assign(timeStringPreset);
60 
61   // Set cookie string
62   PR_ExplodeTime(SetExpiryTime, PR_GMTParameters, &explodedTime);
63   PR_FormatTimeUSEnglish(timeStringPreset, 40, "%c GMT", &explodedTime);
64   cookieString.ReplaceLiteral(
65       0, strlen("test=expiry; expires=") + strlen(timeStringPreset) + 1,
66       "test=expiry; expires=");
67   cookieString.Append(timeStringPreset);
68 }
69 
SetACookieInternal(nsICookieService * aCookieService,const char * aSpec,const char * aCookieString,bool aAllowed)70 void SetACookieInternal(nsICookieService* aCookieService, const char* aSpec,
71                         const char* aCookieString, bool aAllowed) {
72   nsCOMPtr<nsIURI> uri;
73   NS_NewURI(getter_AddRefs(uri), aSpec);
74 
75   // We create a dummy channel using the aSpec to simulate same-siteness
76   nsresult rv0;
77   nsCOMPtr<nsIScriptSecurityManager> ssm =
78       do_GetService(NS_SCRIPTSECURITYMANAGER_CONTRACTID, &rv0);
79   ASSERT_TRUE(NS_SUCCEEDED(rv0));
80   nsCOMPtr<nsIPrincipal> specPrincipal;
81   nsCString tmpString(aSpec);
82   ssm->CreateContentPrincipalFromOrigin(tmpString,
83                                         getter_AddRefs(specPrincipal));
84 
85   nsCOMPtr<nsIChannel> dummyChannel;
86   NS_NewChannel(getter_AddRefs(dummyChannel), uri, specPrincipal,
87                 nsILoadInfo::SEC_ONLY_FOR_EXPLICIT_CONTENTSEC_CHECK,
88                 nsIContentPolicy::TYPE_OTHER);
89 
90   nsCOMPtr<nsICookieJarSettings> cookieJarSettings =
91       aAllowed ? CookieJarSettings::Create(CookieJarSettings::eRegular)
92                : CookieJarSettings::GetBlockingAll();
93   MOZ_ASSERT(cookieJarSettings);
94 
95   nsCOMPtr<nsILoadInfo> loadInfo = dummyChannel->LoadInfo();
96   loadInfo->SetCookieJarSettings(cookieJarSettings);
97 
98   nsresult rv = aCookieService->SetCookieStringFromHttp(
99       uri, nsDependentCString(aCookieString), dummyChannel);
100   EXPECT_TRUE(NS_SUCCEEDED(rv));
101 }
102 
SetACookieJarBlocked(nsICookieService * aCookieService,const char * aSpec,const char * aCookieString)103 void SetACookieJarBlocked(nsICookieService* aCookieService, const char* aSpec,
104                           const char* aCookieString) {
105   SetACookieInternal(aCookieService, aSpec, aCookieString, false);
106 }
107 
SetACookie(nsICookieService * aCookieService,const char * aSpec,const char * aCookieString)108 void SetACookie(nsICookieService* aCookieService, const char* aSpec,
109                 const char* aCookieString) {
110   SetACookieInternal(aCookieService, aSpec, aCookieString, true);
111 }
112 
113 // The cookie string is returned via aCookie.
GetACookie(nsICookieService * aCookieService,const char * aSpec,nsACString & aCookie)114 void GetACookie(nsICookieService* aCookieService, const char* aSpec,
115                 nsACString& aCookie) {
116   nsCOMPtr<nsIURI> uri;
117   NS_NewURI(getter_AddRefs(uri), aSpec);
118 
119   nsCOMPtr<nsIIOService> service = do_GetIOService();
120 
121   nsCOMPtr<nsIChannel> channel;
122   Unused << service->NewChannelFromURI(
123       uri, nullptr, nsContentUtils::GetSystemPrincipal(),
124       nsContentUtils::GetSystemPrincipal(), 0, nsIContentPolicy::TYPE_DOCUMENT,
125       getter_AddRefs(channel));
126 
127   Unused << aCookieService->GetCookieStringFromHttp(uri, channel, aCookie);
128 }
129 
130 // The cookie string is returned via aCookie.
GetACookieNoHttp(nsICookieService * aCookieService,const char * aSpec,nsACString & aCookie)131 void GetACookieNoHttp(nsICookieService* aCookieService, const char* aSpec,
132                       nsACString& aCookie) {
133   nsCOMPtr<nsIURI> uri;
134   NS_NewURI(getter_AddRefs(uri), aSpec);
135 
136   RefPtr<BasePrincipal> principal =
137       BasePrincipal::CreateContentPrincipal(uri, OriginAttributes());
138   MOZ_ASSERT(principal);
139 
140   nsCOMPtr<mozilla::dom::Document> document;
141   nsresult rv = NS_NewDOMDocument(getter_AddRefs(document),
142                                   u""_ns,   // aNamespaceURI
143                                   u""_ns,   // aQualifiedName
144                                   nullptr,  // aDoctype
145                                   uri, uri, principal,
146                                   false,    // aLoadedAsData
147                                   nullptr,  // aEventObject
148                                   DocumentFlavorHTML);
149   Unused << NS_WARN_IF(NS_FAILED(rv));
150 
151   Unused << aCookieService->GetCookieStringFromDocument(document, aCookie);
152 }
153 
154 // some #defines for comparison rules
155 #define MUST_BE_NULL 0
156 #define MUST_EQUAL 1
157 #define MUST_CONTAIN 2
158 #define MUST_NOT_CONTAIN 3
159 #define MUST_NOT_EQUAL 4
160 
161 // a simple helper function to improve readability:
162 // takes one of the #defined rules above, and performs the appropriate test.
163 // true means the test passed; false means the test failed.
CheckResult(const char * aLhs,uint32_t aRule,const char * aRhs=nullptr)164 static inline bool CheckResult(const char* aLhs, uint32_t aRule,
165                                const char* aRhs = nullptr) {
166   switch (aRule) {
167     case MUST_BE_NULL:
168       return !aLhs || !*aLhs;
169 
170     case MUST_EQUAL:
171       return !PL_strcmp(aLhs, aRhs);
172 
173     case MUST_NOT_EQUAL:
174       return PL_strcmp(aLhs, aRhs);
175 
176     case MUST_CONTAIN:
177       return PL_strstr(aLhs, aRhs) != nullptr;
178 
179     case MUST_NOT_CONTAIN:
180       return PL_strstr(aLhs, aRhs) == nullptr;
181 
182     default:
183       return false;  // failure
184   }
185 }
186 
InitPrefs(nsIPrefBranch * aPrefBranch)187 void InitPrefs(nsIPrefBranch* aPrefBranch) {
188   // init some relevant prefs, so the tests don't go awry.
189   // we use the most restrictive set of prefs we can;
190   // however, we don't test third party blocking here.
191   aPrefBranch->SetIntPref(kCookiesPermissions, 0);  // accept all
192   // Set quotaPerHost to maxPerHost - 1, so there is only one cookie
193   // will be evicted everytime.
194   aPrefBranch->SetIntPref(kPrefCookieQuotaPerHost, 49);
195   // Set the base domain limit to 50 so we have a known value.
196   aPrefBranch->SetIntPref(kCookiesMaxPerHost, 50);
197 
198   // SameSite=None by default. We have other tests for lax-by-default.
199   // XXX: Bug 1617611 - Fix all the tests broken by "cookies SameSite=Lax by
200   // default"
201   Preferences::SetBool("network.cookie.sameSite.laxByDefault", false);
202   Preferences::SetBool("network.cookieJarSettings.unblocked_for_testing", true);
203   Preferences::SetBool("dom.securecontext.whitelist_onions", false);
204   Preferences::SetBool("network.cookie.sameSite.schemeful", false);
205 }
206 
TEST(TestCookie,TestCookieMain)207 TEST(TestCookie, TestCookieMain)
208 {
209   nsresult rv0;
210 
211   nsCOMPtr<nsICookieService> cookieService =
212       do_GetService(kCookieServiceCID, &rv0);
213   ASSERT_TRUE(NS_SUCCEEDED(rv0));
214 
215   nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(kPrefServiceCID, &rv0);
216   ASSERT_TRUE(NS_SUCCEEDED(rv0));
217 
218   InitPrefs(prefBranch);
219 
220   nsCString cookie;
221 
222   /* The basic idea behind these tests is the following:
223    *
224    * we set() some cookie, then try to get() it in various ways. we have
225    * several possible tests we perform on the cookie string returned from
226    * get():
227    *
228    * a) check whether the returned string is null (i.e. we got no cookies
229    *    back). this is used e.g. to ensure a given cookie was deleted
230    *    correctly, or to ensure a certain cookie wasn't returned to a given
231    *    host.
232    * b) check whether the returned string exactly matches a given string.
233    *    this is used where we want to make sure our cookie service adheres to
234    *    some strict spec (e.g. ordering of multiple cookies), or where we
235    *    just know exactly what the returned string should be.
236    * c) check whether the returned string contains/does not contain a given
237    *    string. this is used where we don't know/don't care about the
238    *    ordering of multiple cookies - we just want to make sure the cookie
239    *    string contains them all, in some order.
240    *
241    * NOTE: this testsuite is not yet comprehensive or complete, and is
242    * somewhat contrived - still under development, and needs improving!
243    */
244 
245   // test some basic variations of the domain & path
246   SetACookie(cookieService, "http://www.basic.com", "test=basic");
247   GetACookie(cookieService, "http://www.basic.com", cookie);
248   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=basic"));
249   GetACookie(cookieService, "http://www.basic.com/testPath/testfile.txt",
250              cookie);
251   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=basic"));
252   GetACookie(cookieService, "http://www.basic.com./", cookie);
253   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
254   GetACookie(cookieService, "http://www.basic.com.", cookie);
255   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
256   GetACookie(cookieService, "http://www.basic.com./testPath/testfile.txt",
257              cookie);
258   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
259   GetACookie(cookieService, "http://www.basic2.com/", cookie);
260   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
261   SetACookie(cookieService, "http://www.basic.com", "test=basic; max-age=-1");
262   GetACookie(cookieService, "http://www.basic.com/", cookie);
263   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
264 
265   // *** domain tests
266 
267   // test some variations of the domain & path, for different domains of
268   // a domain cookie
269   SetACookie(cookieService, "http://www.domain.com",
270              "test=domain; domain=domain.com");
271   GetACookie(cookieService, "http://domain.com", cookie);
272   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=domain"));
273   GetACookie(cookieService, "http://domain.com.", cookie);
274   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
275   GetACookie(cookieService, "http://www.domain.com", cookie);
276   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=domain"));
277   GetACookie(cookieService, "http://foo.domain.com", cookie);
278   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=domain"));
279   SetACookie(cookieService, "http://www.domain.com",
280              "test=domain; domain=domain.com; max-age=-1");
281   GetACookie(cookieService, "http://domain.com", cookie);
282   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
283 
284   SetACookie(cookieService, "http://www.domain.com",
285              "test=domain; domain=.domain.com");
286   GetACookie(cookieService, "http://domain.com", cookie);
287   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=domain"));
288   GetACookie(cookieService, "http://www.domain.com", cookie);
289   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=domain"));
290   GetACookie(cookieService, "http://bah.domain.com", cookie);
291   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=domain"));
292   SetACookie(cookieService, "http://www.domain.com",
293              "test=domain; domain=.domain.com; max-age=-1");
294   GetACookie(cookieService, "http://domain.com", cookie);
295   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
296 
297   SetACookie(cookieService, "http://www.domain.com",
298              "test=domain; domain=.foo.domain.com");
299   GetACookie(cookieService, "http://foo.domain.com", cookie);
300   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
301 
302   SetACookie(cookieService, "http://www.domain.com",
303              "test=domain; domain=moose.com");
304   GetACookie(cookieService, "http://foo.domain.com", cookie);
305   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
306 
307   SetACookie(cookieService, "http://www.domain.com",
308              "test=domain; domain=domain.com.");
309   GetACookie(cookieService, "http://foo.domain.com", cookie);
310   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
311 
312   SetACookie(cookieService, "http://www.domain.com",
313              "test=domain; domain=..domain.com");
314   GetACookie(cookieService, "http://foo.domain.com", cookie);
315   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
316 
317   SetACookie(cookieService, "http://www.domain.com",
318              "test=domain; domain=..domain.com.");
319   GetACookie(cookieService, "http://foo.domain.com", cookie);
320   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
321 
322   SetACookie(cookieService, "http://path.net/path/file",
323              R"(test=taco; path="/bogus")");
324   GetACookie(cookieService, "http://path.net/path/file", cookie);
325   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=taco"));
326   SetACookie(cookieService, "http://path.net/path/file",
327              "test=taco; max-age=-1");
328   GetACookie(cookieService, "http://path.net/path/file", cookie);
329   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
330 
331   // *** path tests
332 
333   // test some variations of the domain & path, for different paths of
334   // a path cookie
335   SetACookie(cookieService, "http://path.net/path/file",
336              "test=path; path=/path");
337   GetACookie(cookieService, "http://path.net/path", cookie);
338   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=path"));
339   GetACookie(cookieService, "http://path.net/path/", cookie);
340   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=path"));
341   GetACookie(cookieService, "http://path.net/path/hithere.foo", cookie);
342   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=path"));
343   GetACookie(cookieService, "http://path.net/path?hithere/foo", cookie);
344   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=path"));
345   GetACookie(cookieService, "http://path.net/path2", cookie);
346   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
347   GetACookie(cookieService, "http://path.net/path2/", cookie);
348   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
349   SetACookie(cookieService, "http://path.net/path/file",
350              "test=path; path=/path; max-age=-1");
351   GetACookie(cookieService, "http://path.net/path/", cookie);
352   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
353 
354   SetACookie(cookieService, "http://path.net/path/file",
355              "test=path; path=/path/");
356   GetACookie(cookieService, "http://path.net/path", cookie);
357   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
358   GetACookie(cookieService, "http://path.net/path/", cookie);
359   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=path"));
360   SetACookie(cookieService, "http://path.net/path/file",
361              "test=path; path=/path/; max-age=-1");
362   GetACookie(cookieService, "http://path.net/path/", cookie);
363   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
364 
365   // note that a site can set a cookie for a path it's not on.
366   // this is an intentional deviation from spec (see comments in
367   // CookieService::CheckPath()), so we test this functionality too
368   SetACookie(cookieService, "http://path.net/path/file",
369              "test=path; path=/foo/");
370   GetACookie(cookieService, "http://path.net/path", cookie);
371   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
372   GetACookie(cookieService, "http://path.net/foo", cookie);
373   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
374   SetACookie(cookieService, "http://path.net/path/file",
375              "test=path; path=/foo/; max-age=-1");
376   GetACookie(cookieService, "http://path.net/foo/", cookie);
377   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
378 
379   // bug 373228: make sure cookies with paths longer than 1024 bytes,
380   // and cookies with paths or names containing tabs, are rejected.
381   // the following cookie has a path > 1024 bytes explicitly specified in the
382   // cookie
383   SetACookie(
384       cookieService, "http://path.net/",
385       "test=path; "
386       "path=/"
387       "123456789012345678901234567890123456789012345678901234567890123456789012"
388       "345678901234567890123456789012345678901234567890123456789012345678901234"
389       "567890123456789012345678901234567890123456789012345678901234567890123456"
390       "789012345678901234567890123456789012345678901234567890123456789012345678"
391       "901234567890123456789012345678901234567890123456789012345678901234567890"
392       "123456789012345678901234567890123456789012345678901234567890123456789012"
393       "345678901234567890123456789012345678901234567890123456789012345678901234"
394       "567890123456789012345678901234567890123456789012345678901234567890123456"
395       "789012345678901234567890123456789012345678901234567890123456789012345678"
396       "901234567890123456789012345678901234567890123456789012345678901234567890"
397       "123456789012345678901234567890123456789012345678901234567890123456789012"
398       "345678901234567890123456789012345678901234567890123456789012345678901234"
399       "567890123456789012345678901234567890123456789012345678901234567890123456"
400       "789012345678901234567890123456789012345678901234567890123456789012345678"
401       "9012345678901234567890/");
402   GetACookie(
403       cookieService,
404       "http://path.net/"
405       "123456789012345678901234567890123456789012345678901234567890123456789012"
406       "345678901234567890123456789012345678901234567890123456789012345678901234"
407       "567890123456789012345678901234567890123456789012345678901234567890123456"
408       "789012345678901234567890123456789012345678901234567890123456789012345678"
409       "901234567890123456789012345678901234567890123456789012345678901234567890"
410       "123456789012345678901234567890123456789012345678901234567890123456789012"
411       "345678901234567890123456789012345678901234567890123456789012345678901234"
412       "567890123456789012345678901234567890123456789012345678901234567890123456"
413       "789012345678901234567890123456789012345678901234567890123456789012345678"
414       "901234567890123456789012345678901234567890123456789012345678901234567890"
415       "123456789012345678901234567890123456789012345678901234567890123456789012"
416       "345678901234567890123456789012345678901234567890123456789012345678901234"
417       "567890123456789012345678901234567890123456789012345678901234567890123456"
418       "789012345678901234567890123456789012345678901234567890123456789012345678"
419       "9012345678901234567890",
420       cookie);
421   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
422   // the following cookie has a path > 1024 bytes implicitly specified by the
423   // uri path
424   SetACookie(
425       cookieService,
426       "http://path.net/"
427       "123456789012345678901234567890123456789012345678901234567890123456789012"
428       "345678901234567890123456789012345678901234567890123456789012345678901234"
429       "567890123456789012345678901234567890123456789012345678901234567890123456"
430       "789012345678901234567890123456789012345678901234567890123456789012345678"
431       "901234567890123456789012345678901234567890123456789012345678901234567890"
432       "123456789012345678901234567890123456789012345678901234567890123456789012"
433       "345678901234567890123456789012345678901234567890123456789012345678901234"
434       "567890123456789012345678901234567890123456789012345678901234567890123456"
435       "789012345678901234567890123456789012345678901234567890123456789012345678"
436       "901234567890123456789012345678901234567890123456789012345678901234567890"
437       "123456789012345678901234567890123456789012345678901234567890123456789012"
438       "345678901234567890123456789012345678901234567890123456789012345678901234"
439       "567890123456789012345678901234567890123456789012345678901234567890123456"
440       "789012345678901234567890123456789012345678901234567890123456789012345678"
441       "9012345678901234567890/",
442       "test=path");
443   GetACookie(
444       cookieService,
445       "http://path.net/"
446       "123456789012345678901234567890123456789012345678901234567890123456789012"
447       "345678901234567890123456789012345678901234567890123456789012345678901234"
448       "567890123456789012345678901234567890123456789012345678901234567890123456"
449       "789012345678901234567890123456789012345678901234567890123456789012345678"
450       "901234567890123456789012345678901234567890123456789012345678901234567890"
451       "123456789012345678901234567890123456789012345678901234567890123456789012"
452       "345678901234567890123456789012345678901234567890123456789012345678901234"
453       "567890123456789012345678901234567890123456789012345678901234567890123456"
454       "789012345678901234567890123456789012345678901234567890123456789012345678"
455       "901234567890123456789012345678901234567890123456789012345678901234567890"
456       "123456789012345678901234567890123456789012345678901234567890123456789012"
457       "345678901234567890123456789012345678901234567890123456789012345678901234"
458       "567890123456789012345678901234567890123456789012345678901234567890123456"
459       "789012345678901234567890123456789012345678901234567890123456789012345678"
460       "9012345678901234567890/",
461       cookie);
462   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
463   // the following cookie includes a tab in the path
464   SetACookie(cookieService, "http://path.net/", "test=path; path=/foo\tbar/");
465   GetACookie(cookieService, "http://path.net/foo\tbar/", cookie);
466   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
467   // the following cookie includes a tab in the name
468   SetACookie(cookieService, "http://path.net/", "test\ttabs=tab");
469   GetACookie(cookieService, "http://path.net/", cookie);
470   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
471   // the following cookie includes a tab in the value - allowed
472   SetACookie(cookieService, "http://path.net/", "test=tab\ttest");
473   GetACookie(cookieService, "http://path.net/", cookie);
474   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=tab\ttest"));
475   SetACookie(cookieService, "http://path.net/", "test=tab\ttest; max-age=-1");
476   GetACookie(cookieService, "http://path.net/", cookie);
477   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
478 
479   // *** expiry & deletion tests
480   // XXX add server time str parsing tests here
481 
482   // test some variations of the expiry time,
483   // and test deletion of previously set cookies
484   SetACookie(cookieService, "http://expireme.org/", "test=expiry; max-age=-1");
485   GetACookie(cookieService, "http://expireme.org/", cookie);
486   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
487   SetACookie(cookieService, "http://expireme.org/", "test=expiry; max-age=0");
488   GetACookie(cookieService, "http://expireme.org/", cookie);
489   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
490   SetACookie(cookieService, "http://expireme.org/", "test=expiry; expires=bad");
491   GetACookie(cookieService, "http://expireme.org/", cookie);
492   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=expiry"));
493   SetACookie(cookieService, "http://expireme.org/",
494              "test=expiry; expires=Thu, 10 Apr 1980 16:33:12 GMT");
495   GetACookie(cookieService, "http://expireme.org/", cookie);
496   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
497   SetACookie(cookieService, "http://expireme.org/",
498              R"(test=expiry; expires="Thu, 10 Apr 1980 16:33:12 GMT)");
499   GetACookie(cookieService, "http://expireme.org/", cookie);
500   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
501   SetACookie(cookieService, "http://expireme.org/",
502              R"(test=expiry; expires="Thu, 10 Apr 1980 16:33:12 GMT")");
503   GetACookie(cookieService, "http://expireme.org/", cookie);
504   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
505 
506   SetACookie(cookieService, "http://expireme.org/", "test=expiry; max-age=60");
507   GetACookie(cookieService, "http://expireme.org/", cookie);
508   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=expiry"));
509   SetACookie(cookieService, "http://expireme.org/", "test=expiry; max-age=-20");
510   GetACookie(cookieService, "http://expireme.org/", cookie);
511   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
512   SetACookie(cookieService, "http://expireme.org/", "test=expiry; max-age=60");
513   GetACookie(cookieService, "http://expireme.org/", cookie);
514   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=expiry"));
515   SetACookie(cookieService, "http://expireme.org/",
516              "test=expiry; expires=Thu, 10 Apr 1980 16:33:12 GMT");
517   GetACookie(cookieService, "http://expireme.org/", cookie);
518   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
519   SetACookie(cookieService, "http://expireme.org/", "test=expiry; max-age=60");
520   SetACookie(cookieService, "http://expireme.org/",
521              "newtest=expiry; max-age=60");
522   GetACookie(cookieService, "http://expireme.org/", cookie);
523   EXPECT_TRUE(CheckResult(cookie.get(), MUST_CONTAIN, "test=expiry"));
524   EXPECT_TRUE(CheckResult(cookie.get(), MUST_CONTAIN, "newtest=expiry"));
525   SetACookie(cookieService, "http://expireme.org/",
526              "test=differentvalue; max-age=0");
527   GetACookie(cookieService, "http://expireme.org/", cookie);
528   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "newtest=expiry"));
529   SetACookie(cookieService, "http://expireme.org/",
530              "newtest=evendifferentvalue; max-age=0");
531   GetACookie(cookieService, "http://expireme.org/", cookie);
532   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
533 
534   SetACookie(cookieService, "http://foo.expireme.org/",
535              "test=expiry; domain=.expireme.org; max-age=60");
536   GetACookie(cookieService, "http://expireme.org/", cookie);
537   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=expiry"));
538   SetACookie(cookieService, "http://bar.expireme.org/",
539              "test=differentvalue; domain=.expireme.org; max-age=0");
540   GetACookie(cookieService, "http://expireme.org/", cookie);
541   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
542 
543   nsAutoCString ServerTime;
544   nsAutoCString CookieString;
545 
546   // *** multiple cookie tests
547 
548   // test the setting of multiple cookies, and test the order of precedence
549   // (a later cookie overwriting an earlier one, in the same header string)
550   SetACookie(cookieService, "http://multiple.cookies/",
551              "test=multiple; domain=.multiple.cookies \n test=different \n "
552              "test=same; domain=.multiple.cookies \n newtest=ciao \n "
553              "newtest=foo; max-age=-6 \n newtest=reincarnated");
554   GetACookie(cookieService, "http://multiple.cookies/", cookie);
555   EXPECT_TRUE(CheckResult(cookie.get(), MUST_NOT_CONTAIN, "test=multiple"));
556   EXPECT_TRUE(CheckResult(cookie.get(), MUST_CONTAIN, "test=different"));
557   EXPECT_TRUE(CheckResult(cookie.get(), MUST_CONTAIN, "test=same"));
558   EXPECT_TRUE(CheckResult(cookie.get(), MUST_NOT_CONTAIN, "newtest=ciao"));
559   EXPECT_TRUE(CheckResult(cookie.get(), MUST_NOT_CONTAIN, "newtest=foo"));
560   EXPECT_TRUE(CheckResult(cookie.get(), MUST_CONTAIN, "newtest=reincarnated"));
561   SetACookie(cookieService, "http://multiple.cookies/",
562              "test=expiry; domain=.multiple.cookies; max-age=0");
563   GetACookie(cookieService, "http://multiple.cookies/", cookie);
564   EXPECT_TRUE(CheckResult(cookie.get(), MUST_NOT_CONTAIN, "test=same"));
565   SetACookie(cookieService, "http://multiple.cookies/",
566              "\n test=different; max-age=0 \n");
567   GetACookie(cookieService, "http://multiple.cookies/", cookie);
568   EXPECT_TRUE(CheckResult(cookie.get(), MUST_NOT_CONTAIN, "test=different"));
569   SetACookie(cookieService, "http://multiple.cookies/",
570              "newtest=dead; max-age=0");
571   GetACookie(cookieService, "http://multiple.cookies/", cookie);
572   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
573 
574   // *** parser tests
575 
576   // test the cookie header parser, under various circumstances.
577   SetACookie(cookieService, "http://parser.test/",
578              "test=parser; domain=.parser.test; ;; ;=; ,,, ===,abc,=; "
579              "abracadabra! max-age=20;=;;");
580   GetACookie(cookieService, "http://parser.test/", cookie);
581   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=parser"));
582   SetACookie(cookieService, "http://parser.test/",
583              "test=parser; domain=.parser.test; max-age=0");
584   GetACookie(cookieService, "http://parser.test/", cookie);
585   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
586   SetACookie(cookieService, "http://parser.test/",
587              "test=\"fubar! = foo;bar\\\";\" parser; domain=.parser.test; "
588              "max-age=6\nfive; max-age=2.63,");
589   GetACookie(cookieService, "http://parser.test/", cookie);
590   EXPECT_TRUE(CheckResult(cookie.get(), MUST_CONTAIN, R"(test="fubar! = foo)"));
591   EXPECT_TRUE(CheckResult(cookie.get(), MUST_CONTAIN, "five"));
592   SetACookie(cookieService, "http://parser.test/",
593              "test=kill; domain=.parser.test; max-age=0 \n five; max-age=0");
594   GetACookie(cookieService, "http://parser.test/", cookie);
595   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
596 
597   // test the handling of VALUE-only cookies (see bug 169091),
598   // i.e. "six" should assume an empty NAME, which allows other VALUE-only
599   // cookies to overwrite it
600   SetACookie(cookieService, "http://parser.test/", "six");
601   GetACookie(cookieService, "http://parser.test/", cookie);
602   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "six"));
603   SetACookie(cookieService, "http://parser.test/", "seven");
604   GetACookie(cookieService, "http://parser.test/", cookie);
605   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "seven"));
606   SetACookie(cookieService, "http://parser.test/", " =eight");
607   GetACookie(cookieService, "http://parser.test/", cookie);
608   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "eight"));
609   SetACookie(cookieService, "http://parser.test/", "test=six");
610   GetACookie(cookieService, "http://parser.test/", cookie);
611   EXPECT_TRUE(CheckResult(cookie.get(), MUST_CONTAIN, "test=six"));
612 
613   // *** path ordering tests
614 
615   // test that cookies are returned in path order - longest to shortest.
616   // if the header doesn't specify a path, it's taken from the host URI.
617   SetACookie(cookieService, "http://multi.path.tests/",
618              "test1=path; path=/one/two/three");
619   SetACookie(cookieService, "http://multi.path.tests/",
620              "test2=path; path=/one \n test3=path; path=/one/two/three/four \n "
621              "test4=path; path=/one/two \n test5=path; path=/one/two/");
622   SetACookie(cookieService, "http://multi.path.tests/one/two/three/four/five/",
623              "test6=path");
624   SetACookie(cookieService,
625              "http://multi.path.tests/one/two/three/four/five/six/",
626              "test7=path; path=");
627   SetACookie(cookieService, "http://multi.path.tests/", "test8=path; path=/");
628   GetACookie(cookieService,
629              "http://multi.path.tests/one/two/three/four/five/six/", cookie);
630   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL,
631                           "test7=path; test6=path; test3=path; test1=path; "
632                           "test5=path; test4=path; test2=path; test8=path"));
633 
634   // *** Cookie prefix tests
635 
636   // prefixed cookies can't be set from insecure HTTP
637   SetACookie(cookieService, "http://prefixed.test/", "__Secure-test1=test");
638   SetACookie(cookieService, "http://prefixed.test/",
639              "__Secure-test2=test; secure");
640   SetACookie(cookieService, "http://prefixed.test/", "__Host-test1=test");
641   SetACookie(cookieService, "http://prefixed.test/",
642              "__Host-test2=test; secure");
643   GetACookie(cookieService, "http://prefixed.test/", cookie);
644   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
645 
646   // prefixed cookies won't be set without the secure flag
647   SetACookie(cookieService, "https://prefixed.test/", "__Secure-test=test");
648   SetACookie(cookieService, "https://prefixed.test/", "__Host-test=test");
649   GetACookie(cookieService, "https://prefixed.test/", cookie);
650   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
651 
652   // prefixed cookies can be set when done correctly
653   SetACookie(cookieService, "https://prefixed.test/",
654              "__Secure-test=test; secure");
655   SetACookie(cookieService, "https://prefixed.test/",
656              "__Host-test=test; secure");
657   GetACookie(cookieService, "https://prefixed.test/", cookie);
658   EXPECT_TRUE(CheckResult(cookie.get(), MUST_CONTAIN, "__Secure-test=test"));
659   EXPECT_TRUE(CheckResult(cookie.get(), MUST_CONTAIN, "__Host-test=test"));
660 
661   // but when set must not be returned to the host insecurely
662   GetACookie(cookieService, "http://prefixed.test/", cookie);
663   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
664 
665   // Host-prefixed cookies cannot specify a domain
666   SetACookie(cookieService, "https://host.prefixed.test/",
667              "__Host-a=test; secure; domain=prefixed.test");
668   SetACookie(cookieService, "https://host.prefixed.test/",
669              "__Host-b=test; secure; domain=.prefixed.test");
670   SetACookie(cookieService, "https://host.prefixed.test/",
671              "__Host-c=test; secure; domain=host.prefixed.test");
672   SetACookie(cookieService, "https://host.prefixed.test/",
673              "__Host-d=test; secure; domain=.host.prefixed.test");
674   GetACookie(cookieService, "https://host.prefixed.test/", cookie);
675   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
676 
677   // Host-prefixed cookies can only have a path of "/"
678   SetACookie(cookieService, "https://host.prefixed.test/some/path",
679              "__Host-e=test; secure");
680   SetACookie(cookieService, "https://host.prefixed.test/some/path",
681              "__Host-f=test; secure; path=/");
682   SetACookie(cookieService, "https://host.prefixed.test/some/path",
683              "__Host-g=test; secure; path=/some");
684   GetACookie(cookieService, "https://host.prefixed.test/", cookie);
685   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "__Host-f=test"));
686 
687   // *** leave-secure-alone tests
688 
689   // testing items 0 & 1 for 3.1 of spec Deprecate modification of ’secure’
690   // cookies from non-secure origins
691   SetACookie(cookieService, "http://www.security.test/",
692              "test=non-security; secure");
693   GetACookieNoHttp(cookieService, "https://www.security.test/", cookie);
694   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
695   SetACookie(cookieService, "https://www.security.test/path/",
696              "test=security; secure; path=/path/");
697   GetACookieNoHttp(cookieService, "https://www.security.test/path/", cookie);
698   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=security"));
699   // testing items 2 & 3 & 4 for 3.2 of spec Deprecate modification of ’secure’
700   // cookies from non-secure origins
701   // Secure site can modify cookie value
702   SetACookie(cookieService, "https://www.security.test/path/",
703              "test=security2; secure; path=/path/");
704   GetACookieNoHttp(cookieService, "https://www.security.test/path/", cookie);
705   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=security2"));
706   // If new cookie contains same name, same host and partially matching path
707   // with an existing security cookie on non-security site, it can't modify an
708   // existing security cookie.
709   SetACookie(cookieService, "http://www.security.test/path/foo/",
710              "test=non-security; path=/path/foo");
711   GetACookieNoHttp(cookieService, "https://www.security.test/path/foo/",
712                    cookie);
713   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=security2"));
714   // Non-secure cookie can set by same name, same host and non-matching path.
715   SetACookie(cookieService, "http://www.security.test/bar/",
716              "test=non-security; path=/bar");
717   GetACookieNoHttp(cookieService, "http://www.security.test/bar/", cookie);
718   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=non-security"));
719   // Modify value and downgrade secure level.
720   SetACookie(
721       cookieService, "https://www.security.test/",
722       "test_modify_cookie=security-cookie; secure; domain=.security.test");
723   GetACookieNoHttp(cookieService, "https://www.security.test/", cookie);
724   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL,
725                           "test_modify_cookie=security-cookie"));
726   SetACookie(cookieService, "https://www.security.test/",
727              "test_modify_cookie=non-security-cookie; domain=.security.test");
728   GetACookieNoHttp(cookieService, "https://www.security.test/", cookie);
729   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL,
730                           "test_modify_cookie=non-security-cookie"));
731 
732   // Test the non-security cookie can set when domain or path not same to secure
733   // cookie of same name.
734   SetACookie(cookieService, "https://www.security.test/", "test=security3");
735   GetACookieNoHttp(cookieService, "http://www.security.test/", cookie);
736   EXPECT_TRUE(CheckResult(cookie.get(), MUST_CONTAIN, "test=security3"));
737   SetACookie(cookieService, "http://www.security.test/",
738              "test=non-security2; domain=security.test");
739   GetACookieNoHttp(cookieService, "http://www.security.test/", cookie);
740   EXPECT_TRUE(CheckResult(cookie.get(), MUST_CONTAIN, "test=non-security2"));
741 
742   Preferences::SetBool("network.cookie.sameSite.schemeful", true);
743   GetACookieNoHttp(cookieService, "http://www.security.test/", cookie);
744   EXPECT_FALSE(CheckResult(cookie.get(), MUST_CONTAIN, "test=security3"));
745   Preferences::SetBool("network.cookie.sameSite.schemeful", false);
746 
747   // *** nsICookieManager interface tests
748   nsCOMPtr<nsICookieManager> cookieMgr =
749       do_GetService(NS_COOKIEMANAGER_CONTRACTID, &rv0);
750   ASSERT_TRUE(NS_SUCCEEDED(rv0));
751 
752   const nsCOMPtr<nsICookieManager>& cookieMgr2 = cookieMgr;
753   ASSERT_TRUE(cookieMgr2);
754 
755   mozilla::OriginAttributes attrs;
756 
757   // first, ensure a clean slate
758   EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->RemoveAll()));
759   // add some cookies
760   EXPECT_TRUE(NS_SUCCEEDED(cookieMgr2->AddNative("cookiemgr.test"_ns,  // domain
761                                                  "/foo"_ns,            // path
762                                                  "test1"_ns,           // name
763                                                  "yes"_ns,             // value
764                                                  false,      // is secure
765                                                  false,      // is httponly
766                                                  true,       // is session
767                                                  INT64_MAX,  // expiry time
768                                                  &attrs,     // originAttributes
769                                                  nsICookie::SAMESITE_NONE,
770                                                  nsICookie::SCHEME_HTTPS)));
771   EXPECT_TRUE(NS_SUCCEEDED(cookieMgr2->AddNative(
772       "cookiemgr.test"_ns,             // domain
773       "/foo"_ns,                       // path
774       "test2"_ns,                      // name
775       "yes"_ns,                        // value
776       false,                           // is secure
777       true,                            // is httponly
778       true,                            // is session
779       PR_Now() / PR_USEC_PER_SEC + 2,  // expiry time
780       &attrs,                          // originAttributes
781       nsICookie::SAMESITE_NONE, nsICookie::SCHEME_HTTPS)));
782   EXPECT_TRUE(NS_SUCCEEDED(cookieMgr2->AddNative("new.domain"_ns,  // domain
783                                                  "/rabbit"_ns,     // path
784                                                  "test3"_ns,       // name
785                                                  "yes"_ns,         // value
786                                                  false,            // is secure
787                                                  false,      // is httponly
788                                                  true,       // is session
789                                                  INT64_MAX,  // expiry time
790                                                  &attrs,     // originAttributes
791                                                  nsICookie::SAMESITE_NONE,
792                                                  nsICookie::SCHEME_HTTPS)));
793   // confirm using enumerator
794   nsTArray<RefPtr<nsICookie>> cookies;
795   EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->GetCookies(cookies)));
796   nsCOMPtr<nsICookie> expiredCookie, newDomainCookie;
797   for (const auto& cookie : cookies) {
798     nsAutoCString name;
799     cookie->GetName(name);
800     if (name.EqualsLiteral("test2")) {
801       expiredCookie = cookie;
802     } else if (name.EqualsLiteral("test3")) {
803       newDomainCookie = cookie;
804     }
805   }
806   EXPECT_EQ(cookies.Length(), 3ul);
807   // check the httpOnly attribute of the second cookie is honored
808   GetACookie(cookieService, "http://cookiemgr.test/foo/", cookie);
809   EXPECT_TRUE(CheckResult(cookie.get(), MUST_CONTAIN, "test2=yes"));
810   GetACookieNoHttp(cookieService, "http://cookiemgr.test/foo/", cookie);
811   EXPECT_TRUE(CheckResult(cookie.get(), MUST_NOT_CONTAIN, "test2=yes"));
812   // check CountCookiesFromHost()
813   uint32_t hostCookies = 0;
814   EXPECT_TRUE(NS_SUCCEEDED(
815       cookieMgr2->CountCookiesFromHost("cookiemgr.test"_ns, &hostCookies)));
816   EXPECT_EQ(hostCookies, 2u);
817   // check CookieExistsNative() using the third cookie
818   bool found;
819   EXPECT_TRUE(NS_SUCCEEDED(cookieMgr2->CookieExistsNative(
820       "new.domain"_ns, "/rabbit"_ns, "test3"_ns, &attrs, &found)));
821   EXPECT_TRUE(found);
822 
823   // sleep four seconds, to make sure the second cookie has expired
824   PR_Sleep(4 * PR_TicksPerSecond());
825   // check that both CountCookiesFromHost() and CookieExistsNative() count the
826   // expired cookie
827   EXPECT_TRUE(NS_SUCCEEDED(
828       cookieMgr2->CountCookiesFromHost("cookiemgr.test"_ns, &hostCookies)));
829   EXPECT_EQ(hostCookies, 2u);
830   EXPECT_TRUE(NS_SUCCEEDED(cookieMgr2->CookieExistsNative(
831       "cookiemgr.test"_ns, "/foo"_ns, "test2"_ns, &attrs, &found)));
832   EXPECT_TRUE(found);
833   // double-check RemoveAll() using the enumerator
834   EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->RemoveAll()));
835   cookies.SetLength(0);
836   EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->GetCookies(cookies)) &&
837               cookies.IsEmpty());
838 
839   // *** eviction and creation ordering tests
840 
841   // test that cookies are
842   // a) returned by order of creation time (oldest first, newest last)
843   // b) evicted by order of lastAccessed time, if the limit on cookies per host
844   // (50) is reached
845   nsAutoCString name;
846   nsAutoCString expected;
847   for (int32_t i = 0; i < 60; ++i) {
848     name = "test"_ns;
849     name.AppendInt(i);
850     name += "=creation"_ns;
851     SetACookie(cookieService, "http://creation.ordering.tests/", name.get());
852 
853     if (i >= 10) {
854       expected += name;
855       if (i < 59) expected += "; "_ns;
856     }
857   }
858   GetACookie(cookieService, "http://creation.ordering.tests/", cookie);
859   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, expected.get()));
860 
861   cookieMgr->RemoveAll();
862 
863   for (int32_t i = 0; i < 60; ++i) {
864     name = "test"_ns;
865     name.AppendInt(i);
866     name += "=delete_non_security"_ns;
867 
868     // Create 50 cookies that include the secure flag.
869     if (i < 50) {
870       name += "; secure"_ns;
871       SetACookie(cookieService, "https://creation.ordering.tests/", name.get());
872     } else {
873       // non-security cookies will be removed beside the latest cookie that be
874       // created.
875       SetACookie(cookieService, "http://creation.ordering.tests/", name.get());
876     }
877   }
878   GetACookie(cookieService, "http://creation.ordering.tests/", cookie);
879 
880   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
881 
882   // *** SameSite attribute - parsing and cookie storage tests
883   // Clear the cookies
884   EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->RemoveAll()));
885 
886   // None of these cookies will be set because using
887   // CookieJarSettings::GetBlockingAll().
888   SetACookieJarBlocked(cookieService, "http://samesite.test", "unset=yes");
889   SetACookieJarBlocked(cookieService, "http://samesite.test",
890                        "unspecified=yes; samesite");
891   SetACookieJarBlocked(cookieService, "http://samesite.test",
892                        "empty=yes; samesite=");
893   SetACookieJarBlocked(cookieService, "http://samesite.test",
894                        "bogus=yes; samesite=bogus");
895   SetACookieJarBlocked(cookieService, "http://samesite.test",
896                        "strict=yes; samesite=strict");
897   SetACookieJarBlocked(cookieService, "http://samesite.test",
898                        "lax=yes; samesite=lax");
899 
900   cookies.SetLength(0);
901   EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->GetCookies(cookies)));
902 
903   EXPECT_TRUE(cookies.IsEmpty());
904 
905   // Set cookies with various incantations of the samesite attribute:
906   // No same site attribute present
907   SetACookie(cookieService, "http://samesite.test", "unset=yes");
908   // samesite attribute present but with no value
909   SetACookie(cookieService, "http://samesite.test",
910              "unspecified=yes; samesite");
911   // samesite attribute present but with an empty value
912   SetACookie(cookieService, "http://samesite.test", "empty=yes; samesite=");
913   // samesite attribute present but with an invalid value
914   SetACookie(cookieService, "http://samesite.test",
915              "bogus=yes; samesite=bogus");
916   // samesite=strict
917   SetACookie(cookieService, "http://samesite.test",
918              "strict=yes; samesite=strict");
919   // samesite=lax
920   SetACookie(cookieService, "http://samesite.test", "lax=yes; samesite=lax");
921 
922   cookies.SetLength(0);
923   EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->GetCookies(cookies)));
924 
925   // check the cookies for the required samesite value
926   for (const auto& cookie : cookies) {
927     nsAutoCString name;
928     cookie->GetName(name);
929     int32_t sameSiteAttr;
930     cookie->GetSameSite(&sameSiteAttr);
931     if (name.EqualsLiteral("unset")) {
932       EXPECT_TRUE(sameSiteAttr == nsICookie::SAMESITE_NONE);
933     } else if (name.EqualsLiteral("unspecified")) {
934       EXPECT_TRUE(sameSiteAttr == nsICookie::SAMESITE_NONE);
935     } else if (name.EqualsLiteral("empty")) {
936       EXPECT_TRUE(sameSiteAttr == nsICookie::SAMESITE_NONE);
937     } else if (name.EqualsLiteral("bogus")) {
938       EXPECT_TRUE(sameSiteAttr == nsICookie::SAMESITE_NONE);
939     } else if (name.EqualsLiteral("strict")) {
940       EXPECT_TRUE(sameSiteAttr == nsICookie::SAMESITE_STRICT);
941     } else if (name.EqualsLiteral("lax")) {
942       EXPECT_TRUE(sameSiteAttr == nsICookie::SAMESITE_LAX);
943     }
944   }
945 
946   EXPECT_TRUE(cookies.Length() == 6);
947 
948   // *** SameSite attribute
949   // Clear the cookies
950   EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->RemoveAll()));
951 
952   // please note that the flag aForeign is always set to true using this test
953   // setup because no nsIChannel is passed to SetCookieString(). therefore we
954   // can only test that no cookies are sent for cross origin requests using
955   // same-site cookies.
956   SetACookie(cookieService, "http://www.samesite.com",
957              "test=sameSiteStrictVal; samesite=strict");
958   GetACookie(cookieService, "http://www.notsamesite.com", cookie);
959   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
960 
961   SetACookie(cookieService, "http://www.samesite.test",
962              "test=sameSiteLaxVal; samesite=lax");
963   GetACookie(cookieService, "http://www.notsamesite.com", cookie);
964   EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL));
965 
966   static const char* secureURIs[] = {
967       "http://localhost", "http://localhost:1234", "http://127.0.0.1",
968       "http://127.0.0.2", "http://127.1.0.1",      "http://[::1]",
969       // TODO bug 1220810 "http://xyzzy.localhost"
970   };
971 
972   uint32_t numSecureURIs = sizeof(secureURIs) / sizeof(const char*);
973   for (uint32_t i = 0; i < numSecureURIs; ++i) {
974     SetACookie(cookieService, secureURIs[i], "test=basic; secure");
975     GetACookie(cookieService, secureURIs[i], cookie);
976     EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=basic"));
977     SetACookie(cookieService, secureURIs[i], "test=basic1");
978     GetACookie(cookieService, secureURIs[i], cookie);
979     EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=basic1"));
980   }
981 
982   // XXX the following are placeholders: add these tests please!
983   // *** "noncompliant cookie" tests
984   // *** IP address tests
985   // *** speed tests
986 }
987 
TEST(TestCookie,SameSiteLax)988 TEST(TestCookie, SameSiteLax)
989 {
990   Preferences::SetBool("network.cookie.sameSite.laxByDefault", true);
991 
992   nsresult rv;
993 
994   nsCOMPtr<nsICookieService> cookieService =
995       do_GetService(kCookieServiceCID, &rv);
996   ASSERT_TRUE(NS_SUCCEEDED(rv));
997 
998   nsCOMPtr<nsICookieManager> cookieMgr =
999       do_GetService(NS_COOKIEMANAGER_CONTRACTID, &rv);
1000   ASSERT_TRUE(NS_SUCCEEDED(rv));
1001 
1002   EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->RemoveAll()));
1003 
1004   SetACookie(cookieService, "http://samesite.test", "unset=yes");
1005 
1006   nsTArray<RefPtr<nsICookie>> cookies;
1007   EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->GetCookies(cookies)));
1008   EXPECT_EQ(cookies.Length(), (uint64_t)1);
1009 
1010   Cookie* cookie = static_cast<Cookie*>(cookies[0].get());
1011   EXPECT_EQ(cookie->RawSameSite(), nsICookie::SAMESITE_NONE);
1012   EXPECT_EQ(cookie->SameSite(), nsICookie::SAMESITE_LAX);
1013 
1014   Preferences::SetCString("network.cookie.sameSite.laxByDefault.disabledHosts",
1015                           "foo.com,samesite.test,bar.net");
1016 
1017   EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->RemoveAll()));
1018 
1019   cookies.SetLength(0);
1020   EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->GetCookies(cookies)));
1021   EXPECT_EQ(cookies.Length(), (uint64_t)0);
1022 
1023   SetACookie(cookieService, "http://samesite.test", "unset=yes");
1024 
1025   cookies.SetLength(0);
1026   EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->GetCookies(cookies)));
1027   EXPECT_EQ(cookies.Length(), (uint64_t)1);
1028 
1029   cookie = static_cast<Cookie*>(cookies[0].get());
1030   EXPECT_EQ(cookie->RawSameSite(), nsICookie::SAMESITE_NONE);
1031   EXPECT_EQ(cookie->SameSite(), nsICookie::SAMESITE_NONE);
1032 }
1033 
TEST(TestCookie,OnionSite)1034 TEST(TestCookie, OnionSite)
1035 {
1036   Preferences::SetBool("dom.securecontext.whitelist_onions", true);
1037   Preferences::SetBool("network.cookie.sameSite.laxByDefault", false);
1038 
1039   nsresult rv;
1040   nsCString cookie;
1041 
1042   nsCOMPtr<nsICookieService> cookieService =
1043       do_GetService(kCookieServiceCID, &rv);
1044   ASSERT_TRUE(NS_SUCCEEDED(rv));
1045 
1046   // .onion secure cookie tests
1047   SetACookie(cookieService, "http://123456789abcdef.onion/",
1048              "test=onion-security; secure");
1049   GetACookieNoHttp(cookieService, "https://123456789abcdef.onion/", cookie);
1050   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=onion-security"));
1051   SetACookie(cookieService, "http://123456789abcdef.onion/",
1052              "test=onion-security2; secure");
1053   GetACookieNoHttp(cookieService, "http://123456789abcdef.onion/", cookie);
1054   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=onion-security2"));
1055   SetACookie(cookieService, "https://123456789abcdef.onion/",
1056              "test=onion-security3; secure");
1057   GetACookieNoHttp(cookieService, "http://123456789abcdef.onion/", cookie);
1058   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=onion-security3"));
1059   SetACookie(cookieService, "http://123456789abcdef.onion/",
1060              "test=onion-security4");
1061   GetACookieNoHttp(cookieService, "http://123456789abcdef.onion/", cookie);
1062   EXPECT_TRUE(CheckResult(cookie.get(), MUST_EQUAL, "test=onion-security4"));
1063 }
1064