From e30f2f622797b14a3be1ffbc765067cf28f16a8b Mon Sep 17 00:00:00 2001 From: Amy Chung Date: Mon, 25 Sep 2017 01:27:04 +0800 Subject: [PATCH] Bug 1286858 - Data storage and interface changes for SameSite cookies. r=valentin --- .../test/unit/test_cookies_sync_failure.js | 2 +- netwerk/cookie/CookieServiceChild.cpp | 9 ++- netwerk/cookie/CookieServiceParent.cpp | 2 + netwerk/cookie/nsCookie.cpp | 11 ++- netwerk/cookie/nsCookie.h | 9 ++- netwerk/cookie/nsCookieService.cpp | 68 +++++++++++++++---- netwerk/cookie/nsCookieService.h | 1 + netwerk/cookie/nsICookie2.idl | 16 ++++- netwerk/cookie/nsICookieManager2.idl | 14 ++-- netwerk/ipc/NeckoChannelParams.ipdlh | 1 + netwerk/test/TestCookie.cpp | 57 ++++++++++++++-- 11 files changed, 160 insertions(+), 30 deletions(-) diff --git a/extensions/cookie/test/unit/test_cookies_sync_failure.js b/extensions/cookie/test/unit/test_cookies_sync_failure.js index fcc9827d7596..d4b09fa1e831 100644 --- a/extensions/cookie/test/unit/test_cookies_sync_failure.js +++ b/extensions/cookie/test/unit/test_cookies_sync_failure.js @@ -18,7 +18,7 @@ // c) Schema 3: the 'creationTime' column already exists; or the // 'moz_uniqueid' index already exists. -var COOKIE_DATABASE_SCHEMA_CURRENT = 8; +var COOKIE_DATABASE_SCHEMA_CURRENT = 9; var test_generator = do_run_test(); diff --git a/netwerk/cookie/CookieServiceChild.cpp b/netwerk/cookie/CookieServiceChild.cpp index b0a039d56dbf..256b01f9a9f7 100644 --- a/netwerk/cookie/CookieServiceChild.cpp +++ b/netwerk/cookie/CookieServiceChild.cpp @@ -178,7 +178,8 @@ CookieServiceChild::RecvAddCookie(const CookieStruct &aCookie, aCookie.isSession(), aCookie.isSecure(), false, - aAttrs); + aAttrs, + aCookie.sameSite()); RecordDocumentCookie(cookie, aAttrs); return IPC_OK(); } @@ -210,7 +211,8 @@ CookieServiceChild::RecvTrackCookiesLoad(nsTArray&& aCookiesList, aCookiesList[i].isSession(), aCookiesList[i].isSecure(), false, - aAttrs); + aAttrs, + aCookiesList[i].sameSite()); RecordDocumentCookie(cookie, aAttrs); } @@ -365,7 +367,8 @@ CookieServiceChild::SetCookieInternal(nsCookieAttributes &aCookieAt aCookieAttributes.isSession, aCookieAttributes.isSecure, aCookieAttributes.isHttpOnly, - aAttrs); + aAttrs, + aCookieAttributes.sameSite); RecordDocumentCookie(cookie, aAttrs); } diff --git a/netwerk/cookie/CookieServiceParent.cpp b/netwerk/cookie/CookieServiceParent.cpp index 514d72daaf53..84d92887cf81 100644 --- a/netwerk/cookie/CookieServiceParent.cpp +++ b/netwerk/cookie/CookieServiceParent.cpp @@ -91,6 +91,7 @@ GetInfoFromCookie(nsCookie *aCookie, aCookieStruct.creationTime() = aCookie->CreationTime(); aCookieStruct.isSession() = aCookie->IsSession(); aCookieStruct.isSecure() = aCookie->IsSecure(); + aCookieStruct.sameSite() = aCookie->SameSite(); } void @@ -186,6 +187,7 @@ CookieServiceParent::SerialializeCookieList(const nsTArray &aFoundCoo cookieStruct->creationTime() = cookie->CreationTime(); cookieStruct->isSession() = cookie->IsSession(); cookieStruct->isSecure() = cookie->IsSecure(); + cookieStruct->sameSite() = cookie->SameSite(); } } diff --git a/netwerk/cookie/nsCookie.cpp b/netwerk/cookie/nsCookie.cpp index bf681e2fd003..35efa404169f 100644 --- a/netwerk/cookie/nsCookie.cpp +++ b/netwerk/cookie/nsCookie.cpp @@ -79,7 +79,8 @@ nsCookie::Create(const nsACString &aName, bool aIsSession, bool aIsSecure, bool aIsHttpOnly, - const OriginAttributes& aOriginAttributes) + const OriginAttributes& aOriginAttributes, + int32_t aSameSite) { // Ensure mValue contains a valid UTF-8 sequence. Otherwise XPConnect will // truncate the string after the first invalid octet. @@ -108,11 +109,16 @@ nsCookie::Create(const nsACString &aName, if (aCreationTime > gLastCreationTime) gLastCreationTime = aCreationTime; + // If aSameSite is not a sensible value, assume strict + if (aSameSite < 0 || aSameSite > nsICookie2::SAMESITE_STRICT) { + aSameSite = nsICookie2::SAMESITE_STRICT; + } + // construct the cookie. placement new, oh yeah! return new (place) nsCookie(name, value, host, path, end, aExpiry, aLastAccessed, aCreationTime, aIsSession, aIsSecure, aIsHttpOnly, - aOriginAttributes); + aOriginAttributes, aSameSite); } size_t @@ -151,6 +157,7 @@ NS_IMETHODIMP nsCookie::GetStatus(nsCookieStatus *aStatus) { *aStatus = 0; NS_IMETHODIMP nsCookie::GetPolicy(nsCookiePolicy *aPolicy) { *aPolicy = 0; return NS_OK; } NS_IMETHODIMP nsCookie::GetCreationTime(int64_t *aCreation){ *aCreation = CreationTime(); return NS_OK; } NS_IMETHODIMP nsCookie::GetLastAccessed(int64_t *aTime) { *aTime = LastAccessed(); return NS_OK; } +NS_IMETHODIMP nsCookie::GetSameSite(int32_t *aSameSite) { *aSameSite = SameSite(); return NS_OK; } NS_IMETHODIMP nsCookie::GetOriginAttributes(JSContext *aCx, JS::MutableHandle aVal) diff --git a/netwerk/cookie/nsCookie.h b/netwerk/cookie/nsCookie.h index 78173760782c..d808e9ad7293 100644 --- a/netwerk/cookie/nsCookie.h +++ b/netwerk/cookie/nsCookie.h @@ -48,7 +48,8 @@ class nsCookie : public nsICookie2 bool aIsSession, bool aIsSecure, bool aIsHttpOnly, - const OriginAttributes& aOriginAttributes) + const OriginAttributes& aOriginAttributes, + int32_t aSameSite) : mName(aName) , mValue(aValue) , mHost(aHost) @@ -61,6 +62,7 @@ class nsCookie : public nsICookie2 , mIsSecure(aIsSecure) , mIsHttpOnly(aIsHttpOnly) , mOriginAttributes(aOriginAttributes) + , mSameSite(aSameSite) { } @@ -92,7 +94,8 @@ class nsCookie : public nsICookie2 bool aIsSession, bool aIsSecure, bool aIsHttpOnly, - const OriginAttributes& aOriginAttributes); + const OriginAttributes& aOriginAttributes, + int32_t aSameSite); size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; @@ -110,6 +113,7 @@ class nsCookie : public nsICookie2 inline bool IsSecure() const { return mIsSecure; } inline bool IsHttpOnly() const { return mIsHttpOnly; } inline const OriginAttributes& OriginAttributesRef() const { return mOriginAttributes; } + inline int32_t SameSite() const { return mSameSite; } // setters inline void SetExpiry(int64_t aExpiry) { mExpiry = aExpiry; } @@ -144,6 +148,7 @@ class nsCookie : public nsICookie2 bool mIsSecure; bool mIsHttpOnly; mozilla::OriginAttributes mOriginAttributes; + int32_t mSameSite; }; // Comparator class for sorting cookies before sending to a server. diff --git a/netwerk/cookie/nsCookieService.cpp b/netwerk/cookie/nsCookieService.cpp index d9e6a4a92984..ee0776d3566a 100644 --- a/netwerk/cookie/nsCookieService.cpp +++ b/netwerk/cookie/nsCookieService.cpp @@ -80,7 +80,7 @@ static StaticRefPtr gCookieService; #define HTTP_ONLY_PREFIX "#HttpOnly_" #define COOKIES_FILE "cookies.sqlite" -#define COOKIES_SCHEMA_VERSION 8 +#define COOKIES_SCHEMA_VERSION 9 // parameter indexes; see EnsureReadDomain, EnsureReadComplete and // ReadCookieDBListener::HandleResult @@ -95,6 +95,7 @@ static StaticRefPtr gCookieService; #define IDX_HTTPONLY 8 #define IDX_BASE_DOMAIN 9 #define IDX_ORIGIN_ATTRIBUTES 10 +#define IDX_SAME_SITE 11 #define TOPIC_CLEAR_ORIGIN_DATA "clear-origin-attributes-data" @@ -1391,6 +1392,16 @@ nsCookieService::TryInitDB(bool aRecreateDB) COOKIE_LOGSTRING(LogLevel::Debug, ("Upgraded database to schema version 8")); } + MOZ_FALLTHROUGH; + + case 8: + { + // Add the sameSite column to the table. + rv = mDefaultDBState->dbConn->ExecuteSimpleSQL( + NS_LITERAL_CSTRING("ALTER TABLE moz_cookies ADD sameSite INTEGER")); + COOKIE_LOGSTRING(LogLevel::Debug, + ("Upgraded database to schema version 9")); + } // No more upgrades. Update the schema version. rv = mDefaultDBState->dbConn->SetSchemaVersion(COOKIES_SCHEMA_VERSION); @@ -1438,7 +1449,8 @@ nsCookieService::TryInitDB(bool aRecreateDB) "lastAccessed, " "creationTime, " "isSecure, " - "isHttpOnly " + "isHttpOnly, " + "sameSite " "FROM moz_cookies"), getter_AddRefs(stmt)); if (NS_SUCCEEDED(rv)) break; @@ -1479,7 +1491,8 @@ nsCookieService::TryInitDB(bool aRecreateDB) "lastAccessed, " "creationTime, " "isSecure, " - "isHttpOnly" + "isHttpOnly, " + "sameSite " ") VALUES (" ":baseDomain, " ":originAttributes, " @@ -1491,7 +1504,8 @@ nsCookieService::TryInitDB(bool aRecreateDB) ":lastAccessed, " ":creationTime, " ":isSecure, " - ":isHttpOnly" + ":isHttpOnly, " + ":sameSite" ")"), getter_AddRefs(mDefaultDBState->stmtInsert)); NS_ENSURE_SUCCESS(rv, RESULT_RETRY); @@ -1558,6 +1572,7 @@ nsCookieService::CreateTableWorker(const char* aName) "isSecure INTEGER, " "isHttpOnly INTEGER, " "inBrowserElement INTEGER DEFAULT 0, " + "sameSite INTEGER DEFAULT 0, " "CONSTRAINT moz_uniqueid UNIQUE (name, host, path, originAttributes)" ")"); return mDefaultDBState->dbConn->ExecuteSimpleSQL(command); @@ -2476,6 +2491,7 @@ nsCookieService::Add(const nsACString &aHost, bool aIsSession, int64_t aExpiry, JS::HandleValue aOriginAttributes, + int32_t aSameSite, JSContext* aCx, uint8_t aArgc) { @@ -2491,7 +2507,7 @@ nsCookieService::Add(const nsACString &aHost, NS_ENSURE_SUCCESS(rv, rv); return AddNative(aHost, aPath, aName, aValue, aIsSecure, aIsHttpOnly, - aIsSession, aExpiry, &attrs); + aIsSession, aExpiry, &attrs, aSameSite); } NS_IMETHODIMP_(nsresult) @@ -2503,7 +2519,8 @@ nsCookieService::AddNative(const nsACString &aHost, bool aIsHttpOnly, bool aIsSession, int64_t aExpiry, - OriginAttributes* aOriginAttributes) + OriginAttributes* aOriginAttributes, + int32_t aSameSite) { if (NS_WARN_IF(!aOriginAttributes)) { return NS_ERROR_FAILURE; @@ -2539,7 +2556,8 @@ nsCookieService::AddNative(const nsACString &aHost, aIsSession, aIsSecure, aIsHttpOnly, - key.mOriginAttributes); + key.mOriginAttributes, + aSameSite); if (!cookie) { return NS_ERROR_OUT_OF_MEMORY; } @@ -2671,7 +2689,8 @@ nsCookieService::Read() "isSecure, " "isHttpOnly, " "baseDomain, " - "originAttributes " + "originAttributes, " + "sameSite " "FROM moz_cookies " "WHERE baseDomain NOTNULL"), getter_AddRefs(stmtRead)); NS_ENSURE_SUCCESS(rv, RESULT_RETRY); @@ -2732,6 +2751,7 @@ nsCookieService::GetCookieFromRow(T &aRow, const OriginAttributes& aOriginAttrib int64_t creationTime = aRow->AsInt64(IDX_CREATION_TIME); bool isSecure = 0 != aRow->AsInt32(IDX_SECURE); bool isHttpOnly = 0 != aRow->AsInt32(IDX_HTTPONLY); + int32_t sameSite = aRow->AsInt32(IDX_SAME_SITE); // Create a new nsCookie and assign the data. return nsCookie::Create(name, value, host, path, @@ -2741,7 +2761,8 @@ nsCookieService::GetCookieFromRow(T &aRow, const OriginAttributes& aOriginAttrib false, isSecure, isHttpOnly, - aOriginAttributes); + aOriginAttributes, + sameSite); } void @@ -2850,7 +2871,10 @@ nsCookieService::EnsureReadDomain(const nsCookieKey &aKey) "lastAccessed, " "creationTime, " "isSecure, " - "isHttpOnly " + "isHttpOnly, " + "baseDomain, " + "originAttributes, " + "sameSite " "FROM moz_cookies " "WHERE baseDomain = :baseDomain " " AND originAttributes = :originAttributes"), @@ -2947,7 +2971,8 @@ nsCookieService::EnsureReadComplete() "isSecure, " "isHttpOnly, " "baseDomain, " - "originAttributes " + "originAttributes, " + "sameSite " "FROM moz_cookies " "WHERE baseDomain NOTNULL"), getter_AddRefs(stmt)); @@ -3151,7 +3176,8 @@ nsCookieService::ImportCookies(nsIFile *aCookieFile) false, Substring(buffer, secureIndex, expiresIndex - secureIndex - 1).EqualsLiteral(kTrue), isHttpOnly, - key.mOriginAttributes); + key.mOriginAttributes, + nsICookie2::SAMESITE_UNSET); if (!newCookie) { return NS_ERROR_OUT_OF_MEMORY; } @@ -3601,7 +3627,8 @@ nsCookieService::SetCookieInternal(nsIURI *aHostURI, cookieAttributes.isSession, cookieAttributes.isSecure, cookieAttributes.isHttpOnly, - aKey.mOriginAttributes); + aKey.mOriginAttributes, + cookieAttributes.sameSite); if (!cookie) return newCookie; @@ -3993,6 +4020,8 @@ nsCookieService::ParseAttributes(nsDependentCString &aCookieHeader, static const char kMaxage[] = "max-age"; static const char kSecure[] = "secure"; static const char kHttpOnly[] = "httponly"; + static const char kSameSite[] = "samesite"; + static const char kSameSiteLax[] = "lax"; nsACString::const_char_iterator tempBegin, tempEnd; nsACString::const_char_iterator cookieStart, cookieEnd; @@ -4001,6 +4030,7 @@ nsCookieService::ParseAttributes(nsDependentCString &aCookieHeader, aCookieAttributes.isSecure = false; aCookieAttributes.isHttpOnly = false; + aCookieAttributes.sameSite = nsICookie2::SAMESITE_UNSET; nsDependentCSubstring tokenString(cookieStart, cookieStart); nsDependentCSubstring tokenValue (cookieStart, cookieStart); @@ -4049,6 +4079,14 @@ nsCookieService::ParseAttributes(nsDependentCString &aCookieHeader, // just set the boolean else if (tokenString.LowerCaseEqualsLiteral(kHttpOnly)) aCookieAttributes.isHttpOnly = true; + + else if (tokenString.LowerCaseEqualsLiteral(kSameSite)) { + if (tokenValue.LowerCaseEqualsLiteral(kSameSiteLax)) { + aCookieAttributes.sameSite = nsICookie2::SAMESITE_LAX; + } else { + aCookieAttributes.sameSite = nsICookie2::SAMESITE_STRICT; + } + } } // rebind aCookieHeader, in case we need to process another cookie @@ -5213,6 +5251,10 @@ bindCookieParameters(mozIStorageBindingParamsArray *aParamsArray, aCookie->IsHttpOnly()); NS_ASSERT_SUCCESS(rv); + rv = params->BindInt32ByName(NS_LITERAL_CSTRING("sameSite"), + aCookie->SameSite()); + NS_ASSERT_SUCCESS(rv); + // Bind the params to the array. rv = aParamsArray->AddParams(params); NS_ASSERT_SUCCESS(rv); diff --git a/netwerk/cookie/nsCookieService.h b/netwerk/cookie/nsCookieService.h index adf0418062b7..1186f53fc601 100644 --- a/netwerk/cookie/nsCookieService.h +++ b/netwerk/cookie/nsCookieService.h @@ -195,6 +195,7 @@ struct nsCookieAttributes bool isSession; bool isSecure; bool isHttpOnly; + int8_t sameSite; }; class nsCookieService final : public nsICookieService diff --git a/netwerk/cookie/nsICookie2.idl b/netwerk/cookie/nsICookie2.idl index 62a97f5bbb80..4fb7003a8a00 100644 --- a/netwerk/cookie/nsICookie2.idl +++ b/netwerk/cookie/nsICookie2.idl @@ -11,10 +11,13 @@ * access of cookie objects */ -[scriptable, uuid(05c420e5-03d0-4c7b-a605-df7ebe5ca326)] +[scriptable, uuid(be205dae-4f4c-11e6-80ba-ea5cd310c1a8)] interface nsICookie2 : nsICookie { + const uint32_t SAMESITE_UNSET = 0; + const uint32_t SAMESITE_LAX = 1; + const uint32_t SAMESITE_STRICT = 2; /** * the host (possibly fully qualified) of the cookie, @@ -60,4 +63,15 @@ interface nsICookie2 : nsICookie */ readonly attribute int64_t lastAccessed; + /** + * the sameSite attribute; this controls the cookie behavior for cross-site + * requests as per + * https://tools.ietf.org/html/draft-west-first-party-cookies-07 + * + * This should be one of: + * - SAMESITE_UNSET - the SameSite attribute is not present + * - SAMESITE_LAX - the SameSite attribute is present, but not strict + * - SAMESITE_STRICT - the SameSite attribute is present and strict + */ + readonly attribute int32_t sameSite; }; diff --git a/netwerk/cookie/nsICookieManager2.idl b/netwerk/cookie/nsICookieManager2.idl index 9eddc7e2cc6b..fd91881700fe 100644 --- a/netwerk/cookie/nsICookieManager2.idl +++ b/netwerk/cookie/nsICookieManager2.idl @@ -46,8 +46,12 @@ interface nsICookieManager2 : nsICookieManager * expiration date, in seconds since midnight (00:00:00), January 1, * 1970 UTC. note that expiry time will also be honored for session cookies; * in this way, the more restrictive of the two will take effect. - * @param aOriginAttributes The originAttributes of this cookie. This - * attribute is optional to avoid breaking add-ons. + * @param aOriginAttributes + * the originAttributes of this cookie. This attribute is optional to + * avoid breaking add-ons. + * @param aSameSite + * the SameSite attribute. This attribute is optional to avoid breaking + * addons */ [implicit_jscontext, optional_argc] void add(in AUTF8String aHost, @@ -58,7 +62,8 @@ interface nsICookieManager2 : nsICookieManager in boolean aIsHttpOnly, in boolean aIsSession, in int64_t aExpiry, - [optional] in jsval aOriginAttributes); + [optional] in jsval aOriginAttributes, + [optional] in int32_t aSameSite); [notxpcom] nsresult addNative(in AUTF8String aHost, @@ -69,7 +74,8 @@ interface nsICookieManager2 : nsICookieManager in boolean aIsHttpOnly, in boolean aIsSession, in int64_t aExpiry, - in OriginAttributesPtr aOriginAttributes); + in OriginAttributesPtr aOriginAttributes, + in int32_t aSameSite); /** * Find whether a given cookie already exists. diff --git a/netwerk/ipc/NeckoChannelParams.ipdlh b/netwerk/ipc/NeckoChannelParams.ipdlh index 4c3d40c3f8fd..dd0c4f279db0 100644 --- a/netwerk/ipc/NeckoChannelParams.ipdlh +++ b/netwerk/ipc/NeckoChannelParams.ipdlh @@ -212,6 +212,7 @@ struct CookieStruct int64_t creationTime; bool isSession; bool isSecure; + int8_t sameSite; }; } // namespace ipc diff --git a/netwerk/test/TestCookie.cpp b/netwerk/test/TestCookie.cpp index a7f2da0d65a1..720892e3cbf3 100644 --- a/netwerk/test/TestCookie.cpp +++ b/netwerk/test/TestCookie.cpp @@ -634,7 +634,8 @@ TEST(TestCookie,TestCookieMain) false, // is httponly true, // is session INT64_MAX, // expiry time - &attrs))); // originAttributes + &attrs, // originAttributes + nsICookie2::SAMESITE_UNSET))); EXPECT_TRUE(NS_SUCCEEDED(cookieMgr2->AddNative(NS_LITERAL_CSTRING("cookiemgr.test"), // domain NS_LITERAL_CSTRING("/foo"), // path NS_LITERAL_CSTRING("test2"), // name @@ -643,7 +644,8 @@ TEST(TestCookie,TestCookieMain) true, // is httponly true, // is session PR_Now() / PR_USEC_PER_SEC + 2, // expiry time - &attrs))); // originAttributes + &attrs, // originAttributes + nsICookie2::SAMESITE_UNSET))); EXPECT_TRUE(NS_SUCCEEDED(cookieMgr2->AddNative(NS_LITERAL_CSTRING("new.domain"), // domain NS_LITERAL_CSTRING("/rabbit"), // path NS_LITERAL_CSTRING("test3"), // name @@ -652,7 +654,8 @@ TEST(TestCookie,TestCookieMain) false, // is httponly true, // is session INT64_MAX, // expiry time - &attrs))); // originAttributes + &attrs, // originAttributes + nsICookie2::SAMESITE_UNSET))); // confirm using enumerator nsCOMPtr enumerator; EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->GetEnumerator(getter_AddRefs(enumerator)))); @@ -706,7 +709,8 @@ TEST(TestCookie,TestCookieMain) false, // is httponly true, // is session INT64_MIN, // expiry time - &attrs))); // originAttributes + &attrs, // originAttributes + nsICookie2::SAMESITE_UNSET))); EXPECT_TRUE(NS_SUCCEEDED(cookieMgr2->CookieExistsNative(newDomainCookie, &attrs, &found))); EXPECT_FALSE(found); // sleep four seconds, to make sure the second cookie has expired @@ -764,8 +768,53 @@ TEST(TestCookie,TestCookieMain) } } GetACookie(cookieService, "http://creation.ordering.tests/", nullptr, getter_Copies(cookie)); + EXPECT_TRUE(CheckResult(cookie.get(), MUST_BE_NULL)); + + // *** SameSite attribute - parsing and cookie storage tests + // Clear the cookies + EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->RemoveAll())); + + // Set cookies with various incantations of the samesite attribute: + // No same site attribute present + SetACookie(cookieService, "http://samesite.test", nullptr, "unset=yes", nullptr); + // samesite attribute present but with no value + SetACookie(cookieService, "http://samesite.test", nullptr, "unspecified=yes; samesite", nullptr); + // samesite=strict + SetACookie(cookieService, "http://samesite.test", nullptr, "strict=yes; samesite=strict", nullptr); + // samesite=lax + SetACookie(cookieService, "http://samesite.test", nullptr, "lax=yes; samesite=lax", nullptr); + + EXPECT_TRUE(NS_SUCCEEDED(cookieMgr->GetEnumerator(getter_AddRefs(enumerator)))); + i = 0; + + // check the cookies for the required samesite value + while (NS_SUCCEEDED(enumerator->HasMoreElements(&more)) && more) { + nsCOMPtr cookie; + if (NS_FAILED(enumerator->GetNext(getter_AddRefs(cookie)))) break; + ++i; + + // keep tabs on the second and third cookies, so we can check them later + nsCOMPtr cookie2(do_QueryInterface(cookie)); + if (!cookie2) break; + nsAutoCString name; + cookie2->GetName(name); + int32_t sameSiteAttr; + cookie2->GetSameSite(&sameSiteAttr); + if (name.EqualsLiteral("unset")) { + EXPECT_TRUE(sameSiteAttr == nsICookie2::SAMESITE_UNSET); + } else if (name.EqualsLiteral("unspecified")) { + EXPECT_TRUE(sameSiteAttr == nsICookie2::SAMESITE_STRICT); + } else if (name.EqualsLiteral("strict")) { + EXPECT_TRUE(sameSiteAttr == nsICookie2::SAMESITE_STRICT); + } else if (name.EqualsLiteral("lax")) { + EXPECT_TRUE(sameSiteAttr == nsICookie2::SAMESITE_LAX); + } + } + + EXPECT_TRUE(i == 4); + // XXX the following are placeholders: add these tests please! // *** "noncompliant cookie" tests // *** IP address tests