1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ios/net/cookies/system_cookie_util.h"
7 #import <Foundation/Foundation.h>
9 #include "base/mac/scoped_nsobject.h"
10 #include "base/strings/sys_string_conversions.h"
11 #include "base/time/time.h"
12 #include "net/cookies/cookie_constants.h"
13 #include "testing/gtest/include/gtest/gtest.h"
14 #include "testing/gtest_mac.h"
21 const char kCookieDomain[] = "domain";
22 const char kCookieName[] = "name";
23 const char kCookiePath[] = "path/";
24 const char kCookieValue[] = "value";
25 const char kCookieValueInvalidUtf8[] = "\x81r\xe4\xbd\xa0\xe5\xa5\xbd";
27 void CheckSystemCookie(const base::Time& expires, bool secure, bool httponly) {
28 // Generate a canonical cookie.
29 net::CanonicalCookie canonical_cookie = net::CanonicalCookie(
30 GURL(), kCookieName, kCookieValue, kCookieDomain, kCookiePath,
31 base::Time(), // creation
33 base::Time(), // last_access
35 false, // first_party_only
36 net::COOKIE_PRIORITY_DEFAULT);
37 // Convert it to system cookie.
38 base::scoped_nsobject<NSHTTPCookie> system_cookie(
39 [SystemCookieFromCanonicalCookie(canonical_cookie) retain]);
41 // Check the attributes.
42 EXPECT_TRUE(system_cookie);
43 EXPECT_NSEQ(base::SysUTF8ToNSString(kCookieName), [system_cookie name]);
44 EXPECT_NSEQ(base::SysUTF8ToNSString(kCookieValue), [system_cookie value]);
45 EXPECT_NSEQ(base::SysUTF8ToNSString(kCookieDomain), [system_cookie domain]);
46 EXPECT_NSEQ(base::SysUTF8ToNSString(kCookiePath), [system_cookie path]);
47 EXPECT_EQ(secure, [system_cookie isSecure]);
48 EXPECT_EQ(httponly, [system_cookie isHTTPOnly]);
49 EXPECT_EQ(expires.is_null(), [system_cookie isSessionOnly]);
50 // Allow 1 second difference as iOS rounds expiry time to the nearest second.
51 base::Time system_cookie_expire_date = base::Time::FromDoubleT(
52 [[system_cookie expiresDate] timeIntervalSince1970]);
53 EXPECT_LE(expires - base::TimeDelta::FromSeconds(1),
54 system_cookie_expire_date);
55 EXPECT_GE(expires + base::TimeDelta::FromSeconds(1),
56 system_cookie_expire_date);
61 TEST(CookieUtil, CanonicalCookieFromSystemCookie) {
62 base::Time creation_time = base::Time::Now();
63 base::Time expire_date = creation_time + base::TimeDelta::FromHours(2);
64 NSDate* system_expire_date =
65 [NSDate dateWithTimeIntervalSince1970:expire_date.ToDoubleT()];
66 base::scoped_nsobject<NSHTTPCookie> system_cookie(
67 [[NSHTTPCookie alloc] initWithProperties:@{
68 NSHTTPCookieDomain : @"foo",
69 NSHTTPCookieName : @"a",
70 NSHTTPCookiePath : @"/",
71 NSHTTPCookieValue : @"b",
72 NSHTTPCookieExpires : system_expire_date,
75 ASSERT_TRUE(system_cookie);
76 net::CanonicalCookie chrome_cookie =
77 CanonicalCookieFromSystemCookie(system_cookie, creation_time);
78 EXPECT_TRUE(chrome_cookie.Source().empty());
79 EXPECT_EQ("a", chrome_cookie.Name());
80 EXPECT_EQ("b", chrome_cookie.Value());
81 EXPECT_EQ("foo", chrome_cookie.Domain());
82 EXPECT_EQ("/", chrome_cookie.Path());
83 EXPECT_EQ(creation_time, chrome_cookie.CreationDate());
84 EXPECT_TRUE(chrome_cookie.LastAccessDate().is_null());
85 EXPECT_TRUE(chrome_cookie.IsPersistent());
86 // Allow 1 second difference as iOS rounds expiry time to the nearest second.
87 EXPECT_LE(expire_date - base::TimeDelta::FromSeconds(1),
88 chrome_cookie.ExpiryDate());
89 EXPECT_GE(expire_date + base::TimeDelta::FromSeconds(1),
90 chrome_cookie.ExpiryDate());
91 EXPECT_FALSE(chrome_cookie.IsSecure());
92 EXPECT_TRUE(chrome_cookie.IsHttpOnly());
93 EXPECT_EQ(net::COOKIE_PRIORITY_DEFAULT, chrome_cookie.Priority());
95 // Test session and secure cookie.
96 system_cookie.reset([[NSHTTPCookie alloc] initWithProperties:@{
97 NSHTTPCookieDomain : @"foo",
98 NSHTTPCookieName : @"a",
99 NSHTTPCookiePath : @"/",
100 NSHTTPCookieValue : @"b",
101 NSHTTPCookieSecure : @"Y",
103 ASSERT_TRUE(system_cookie);
104 chrome_cookie = CanonicalCookieFromSystemCookie(system_cookie, creation_time);
105 EXPECT_FALSE(chrome_cookie.IsPersistent());
106 EXPECT_TRUE(chrome_cookie.IsSecure());
109 TEST(CookieUtil, SystemCookieFromCanonicalCookie) {
110 base::Time expire_date = base::Time::Now() + base::TimeDelta::FromHours(2);
112 // Test various combinations of session, secure and httponly attributes.
113 CheckSystemCookie(expire_date, false, false);
114 CheckSystemCookie(base::Time(), true, false);
115 CheckSystemCookie(expire_date, false, true);
116 CheckSystemCookie(base::Time(), true, true);
119 TEST(CookieUtil, SystemCookieFromBadCanonicalCookie) {
120 // Generate a bad canonical cookie (value is invalid utf8).
121 net::CanonicalCookie bad_canonical_cookie = net::CanonicalCookie(
122 GURL(), kCookieName, kCookieValueInvalidUtf8, kCookieDomain, kCookiePath,
123 base::Time(), // creation
124 base::Time(), // expires
125 base::Time(), // last_access
128 false, // first_party_only
129 net::COOKIE_PRIORITY_DEFAULT);
130 // Convert it to system cookie.
131 base::scoped_nsobject<NSHTTPCookie> system_cookie(
132 [SystemCookieFromCanonicalCookie(bad_canonical_cookie) retain]);
133 EXPECT_TRUE(system_cookie == nil);