• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2011 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.
4 
5 #include <time.h>
6 
7 #include <string>
8 
9 #include "base/basictypes.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/message_loop.h"
13 #include "base/metrics/histogram.h"
14 #include "base/string_util.h"
15 #include "base/stringprintf.h"
16 #include "base/threading/platform_thread.h"
17 #include "base/time.h"
18 #include "googleurl/src/gurl.h"
19 #include "net/base/cookie_monster.h"
20 #include "net/base/cookie_monster_store_test.h" // For CookieStore Mock
21 #include "testing/gtest/include/gtest/gtest.h"
22 
23 namespace net {
24 
25 using base::Time;
26 using base::TimeDelta;
27 
28 namespace {
29 
30 class ParsedCookieTest : public testing::Test { };
31 class CookieMonsterTest : public testing::Test { };
32 
33 // Helper for DeleteAllForHost test; repopulates CM with same layout
34 // each time.
35 const char* kTopLevelDomainPlus1 = "http://www.harvard.edu";
36 const char* kTopLevelDomainPlus2 = "http://www.math.harvard.edu";
37 const char* kTopLevelDomainPlus2Secure = "https://www.math.harvard.edu";
38 const char* kTopLevelDomainPlus3 =
39     "http://www.bourbaki.math.harvard.edu";
40 const char* kOtherDomain = "http://www.mit.edu";
41 
PopulateCmForDeleteAllForHost(scoped_refptr<CookieMonster> cm)42 void PopulateCmForDeleteAllForHost(scoped_refptr<CookieMonster> cm) {
43   GURL url_top_level_domain_plus_1(kTopLevelDomainPlus1);
44   GURL url_top_level_domain_plus_2(kTopLevelDomainPlus2);
45   GURL url_top_level_domain_plus_2_secure(kTopLevelDomainPlus2Secure);
46   GURL url_top_level_domain_plus_3(kTopLevelDomainPlus3);
47   GURL url_other(kOtherDomain);
48 
49   cm->DeleteAll(true);
50 
51   // Static population for probe:
52   //    * Three levels of domain cookie (.b.a, .c.b.a, .d.c.b.a)
53   //    * Three levels of host cookie (w.b.a, w.c.b.a, w.d.c.b.a)
54   //    * http_only cookie (w.c.b.a)
55   //    * Two secure cookies (.c.b.a, w.c.b.a)
56   //    * Two domain path cookies (.c.b.a/dir1, .c.b.a/dir1/dir2)
57   //    * Two host path cookies (w.c.b.a/dir1, w.c.b.a/dir1/dir2)
58 
59   // Domain cookies
60   EXPECT_TRUE(cm->SetCookieWithDetails(url_top_level_domain_plus_1,
61                                        "dom_1", "X", ".harvard.edu", "/",
62                                        base::Time(), false, false));
63   EXPECT_TRUE(cm->SetCookieWithDetails(url_top_level_domain_plus_2,
64                                        "dom_2", "X", ".math.harvard.edu", "/",
65                                        base::Time(), false, false));
66   EXPECT_TRUE(cm->SetCookieWithDetails(url_top_level_domain_plus_3,
67                                        "dom_3", "X",
68                                        ".bourbaki.math.harvard.edu", "/",
69                                        base::Time(), false, false));
70 
71   // Host cookies
72   EXPECT_TRUE(cm->SetCookieWithDetails(url_top_level_domain_plus_1,
73                                        "host_1", "X", "", "/",
74                                        base::Time(), false, false));
75   EXPECT_TRUE(cm->SetCookieWithDetails(url_top_level_domain_plus_2,
76                                        "host_2", "X", "", "/",
77                                        base::Time(), false, false));
78   EXPECT_TRUE(cm->SetCookieWithDetails(url_top_level_domain_plus_3,
79                                        "host_3", "X", "", "/",
80                                        base::Time(), false, false));
81 
82   // Http_only cookie
83   EXPECT_TRUE(cm->SetCookieWithDetails(url_top_level_domain_plus_2,
84                                        "httpo_check", "X", "", "/",
85                                        base::Time(), false, true));
86 
87   // Secure cookies
88   EXPECT_TRUE(cm->SetCookieWithDetails(url_top_level_domain_plus_2_secure,
89                                        "sec_dom", "X", ".math.harvard.edu",
90                                        "/", base::Time(), true, false));
91   EXPECT_TRUE(cm->SetCookieWithDetails(url_top_level_domain_plus_2_secure,
92                                        "sec_host", "X", "", "/",
93                                        base::Time(), true, false));
94 
95   // Domain path cookies
96   EXPECT_TRUE(cm->SetCookieWithDetails(url_top_level_domain_plus_2,
97                                        "dom_path_1", "X",
98                                        ".math.harvard.edu", "/dir1",
99                                        base::Time(), false, false));
100   EXPECT_TRUE(cm->SetCookieWithDetails(url_top_level_domain_plus_2,
101                                        "dom_path_2", "X",
102                                        ".math.harvard.edu", "/dir1/dir2",
103                                        base::Time(), false, false));
104 
105   // Host path cookies
106   EXPECT_TRUE(cm->SetCookieWithDetails(url_top_level_domain_plus_2,
107                                        "host_path_1", "X",
108                                        "", "/dir1",
109                                        base::Time(), false, false));
110   EXPECT_TRUE(cm->SetCookieWithDetails(url_top_level_domain_plus_2,
111                                        "host_path_2", "X",
112                                        "", "/dir1/dir2",
113                                        base::Time(), false, false));
114 
115   EXPECT_EQ(13U, cm->GetAllCookies().size());
116 }
117 
118 }  // namespace
119 
TEST(ParsedCookieTest,TestBasic)120 TEST(ParsedCookieTest, TestBasic) {
121   CookieMonster::ParsedCookie pc("a=b");
122   EXPECT_TRUE(pc.IsValid());
123   EXPECT_FALSE(pc.IsSecure());
124   EXPECT_EQ("a", pc.Name());
125   EXPECT_EQ("b", pc.Value());
126 }
127 
TEST(ParsedCookieTest,TestQuoted)128 TEST(ParsedCookieTest, TestQuoted) {
129   // These are some quoting cases which the major browsers all
130   // handle differently.  I've tested Internet Explorer 6, Opera 9.6,
131   // Firefox 3, and Safari Windows 3.2.1.  We originally tried to match
132   // Firefox closely, however we now match Internet Explorer and Safari.
133   const char* values[] = {
134     // Trailing whitespace after a quoted value.  The whitespace after
135     // the quote is stripped in all browsers.
136     "\"zzz \"  ",              "\"zzz \"",
137     // Handling a quoted value with a ';', like FOO="zz;pp"  ;
138     // IE and Safari: "zz;
139     // Firefox and Opera: "zz;pp"
140     "\"zz;pp\" ;",             "\"zz",
141     // Handling a value with multiple quoted parts, like FOO="zzz "   "ppp" ;
142     // IE and Safari: "zzz "   "ppp";
143     // Firefox: "zzz ";
144     // Opera: <rejects cookie>
145     "\"zzz \"   \"ppp\" ",     "\"zzz \"   \"ppp\"",
146     // A quote in a value that didn't start quoted.  like FOO=A"B ;
147     // IE, Safari, and Firefox: A"B;
148     // Opera: <rejects cookie>
149     "A\"B",                    "A\"B",
150   };
151 
152   for (size_t i = 0; i < arraysize(values); i += 2) {
153     std::string input(values[i]);
154     std::string expected(values[i + 1]);
155 
156     CookieMonster::ParsedCookie pc(
157         "aBc=" + input + " ; path=\"/\"  ; httponly ");
158     EXPECT_TRUE(pc.IsValid());
159     EXPECT_FALSE(pc.IsSecure());
160     EXPECT_TRUE(pc.IsHttpOnly());
161     EXPECT_TRUE(pc.HasPath());
162     EXPECT_EQ("aBc", pc.Name());
163     EXPECT_EQ(expected, pc.Value());
164 
165     // If a path was quoted, the path attribute keeps the quotes.  This will
166     // make the cookie effectively useless, but path parameters aren't supposed
167     // to be quoted.  Bug 1261605.
168     EXPECT_EQ("\"/\"", pc.Path());
169   }
170 }
171 
TEST(ParsedCookieTest,TestNameless)172 TEST(ParsedCookieTest, TestNameless) {
173   CookieMonster::ParsedCookie pc("BLAHHH; path=/; secure;");
174   EXPECT_TRUE(pc.IsValid());
175   EXPECT_TRUE(pc.IsSecure());
176   EXPECT_TRUE(pc.HasPath());
177   EXPECT_EQ("/", pc.Path());
178   EXPECT_EQ("", pc.Name());
179   EXPECT_EQ("BLAHHH", pc.Value());
180 }
181 
TEST(ParsedCookieTest,TestAttributeCase)182 TEST(ParsedCookieTest, TestAttributeCase) {
183   CookieMonster::ParsedCookie pc("BLAHHH; Path=/; sECuRe; httpONLY");
184   EXPECT_TRUE(pc.IsValid());
185   EXPECT_TRUE(pc.IsSecure());
186   EXPECT_TRUE(pc.IsHttpOnly());
187   EXPECT_TRUE(pc.HasPath());
188   EXPECT_EQ("/", pc.Path());
189   EXPECT_EQ("", pc.Name());
190   EXPECT_EQ("BLAHHH", pc.Value());
191   EXPECT_EQ(3U, pc.NumberOfAttributes());
192 }
193 
TEST(ParsedCookieTest,TestDoubleQuotedNameless)194 TEST(ParsedCookieTest, TestDoubleQuotedNameless) {
195   CookieMonster::ParsedCookie pc("\"BLA\\\"HHH\"; path=/; secure;");
196   EXPECT_TRUE(pc.IsValid());
197   EXPECT_TRUE(pc.IsSecure());
198   EXPECT_TRUE(pc.HasPath());
199   EXPECT_EQ("/", pc.Path());
200   EXPECT_EQ("", pc.Name());
201   EXPECT_EQ("\"BLA\\\"HHH\"", pc.Value());
202   EXPECT_EQ(2U, pc.NumberOfAttributes());
203 }
204 
TEST(ParsedCookieTest,QuoteOffTheEnd)205 TEST(ParsedCookieTest, QuoteOffTheEnd) {
206   CookieMonster::ParsedCookie pc("a=\"B");
207   EXPECT_TRUE(pc.IsValid());
208   EXPECT_EQ("a", pc.Name());
209   EXPECT_EQ("\"B", pc.Value());
210   EXPECT_EQ(0U, pc.NumberOfAttributes());
211 }
212 
TEST(ParsedCookieTest,MissingName)213 TEST(ParsedCookieTest, MissingName) {
214   CookieMonster::ParsedCookie pc("=ABC");
215   EXPECT_TRUE(pc.IsValid());
216   EXPECT_EQ("", pc.Name());
217   EXPECT_EQ("ABC", pc.Value());
218   EXPECT_EQ(0U, pc.NumberOfAttributes());
219 }
220 
TEST(ParsedCookieTest,MissingValue)221 TEST(ParsedCookieTest, MissingValue) {
222   CookieMonster::ParsedCookie pc("ABC=;  path = /wee");
223   EXPECT_TRUE(pc.IsValid());
224   EXPECT_EQ("ABC", pc.Name());
225   EXPECT_EQ("", pc.Value());
226   EXPECT_TRUE(pc.HasPath());
227   EXPECT_EQ("/wee", pc.Path());
228   EXPECT_EQ(1U, pc.NumberOfAttributes());
229 }
230 
TEST(ParsedCookieTest,Whitespace)231 TEST(ParsedCookieTest, Whitespace) {
232   CookieMonster::ParsedCookie pc("  A  = BC  ;secure;;;   httponly");
233   EXPECT_TRUE(pc.IsValid());
234   EXPECT_EQ("A", pc.Name());
235   EXPECT_EQ("BC", pc.Value());
236   EXPECT_FALSE(pc.HasPath());
237   EXPECT_FALSE(pc.HasDomain());
238   EXPECT_TRUE(pc.IsSecure());
239   EXPECT_TRUE(pc.IsHttpOnly());
240   // We parse anything between ; as attributes, so we end up with two
241   // attributes with an empty string name and value.
242   EXPECT_EQ(4U, pc.NumberOfAttributes());
243 }
TEST(ParsedCookieTest,MultipleEquals)244 TEST(ParsedCookieTest, MultipleEquals) {
245   CookieMonster::ParsedCookie pc("  A=== BC  ;secure;;;   httponly");
246   EXPECT_TRUE(pc.IsValid());
247   EXPECT_EQ("A", pc.Name());
248   EXPECT_EQ("== BC", pc.Value());
249   EXPECT_FALSE(pc.HasPath());
250   EXPECT_FALSE(pc.HasDomain());
251   EXPECT_TRUE(pc.IsSecure());
252   EXPECT_TRUE(pc.IsHttpOnly());
253   EXPECT_EQ(4U, pc.NumberOfAttributes());
254 }
255 
TEST(ParsedCookieTest,QuotedTrailingWhitespace)256 TEST(ParsedCookieTest, QuotedTrailingWhitespace) {
257   CookieMonster::ParsedCookie pc("ANCUUID=\"zohNumRKgI0oxyhSsV3Z7D\"  ; "
258                                       "expires=Sun, 18-Apr-2027 21:06:29 GMT ; "
259                                       "path=/  ;  ");
260   EXPECT_TRUE(pc.IsValid());
261   EXPECT_EQ("ANCUUID", pc.Name());
262   // Stripping whitespace after the quotes matches all other major browsers.
263   EXPECT_EQ("\"zohNumRKgI0oxyhSsV3Z7D\"", pc.Value());
264   EXPECT_TRUE(pc.HasExpires());
265   EXPECT_TRUE(pc.HasPath());
266   EXPECT_EQ("/", pc.Path());
267   EXPECT_EQ(2U, pc.NumberOfAttributes());
268 }
269 
TEST(ParsedCookieTest,TrailingWhitespace)270 TEST(ParsedCookieTest, TrailingWhitespace) {
271   CookieMonster::ParsedCookie pc("ANCUUID=zohNumRKgI0oxyhSsV3Z7D  ; "
272                                       "expires=Sun, 18-Apr-2027 21:06:29 GMT ; "
273                                       "path=/  ;  ");
274   EXPECT_TRUE(pc.IsValid());
275   EXPECT_EQ("ANCUUID", pc.Name());
276   EXPECT_EQ("zohNumRKgI0oxyhSsV3Z7D", pc.Value());
277   EXPECT_TRUE(pc.HasExpires());
278   EXPECT_TRUE(pc.HasPath());
279   EXPECT_EQ("/", pc.Path());
280   EXPECT_EQ(2U, pc.NumberOfAttributes());
281 }
282 
TEST(ParsedCookieTest,TooManyPairs)283 TEST(ParsedCookieTest, TooManyPairs) {
284   std::string blankpairs;
285   blankpairs.resize(CookieMonster::ParsedCookie::kMaxPairs - 1, ';');
286 
287   CookieMonster::ParsedCookie pc1(blankpairs + "secure");
288   EXPECT_TRUE(pc1.IsValid());
289   EXPECT_TRUE(pc1.IsSecure());
290 
291   CookieMonster::ParsedCookie pc2(blankpairs + ";secure");
292   EXPECT_TRUE(pc2.IsValid());
293   EXPECT_FALSE(pc2.IsSecure());
294 }
295 
296 // TODO some better test cases for invalid cookies.
TEST(ParsedCookieTest,InvalidWhitespace)297 TEST(ParsedCookieTest, InvalidWhitespace) {
298   CookieMonster::ParsedCookie pc("    ");
299   EXPECT_FALSE(pc.IsValid());
300 }
301 
TEST(ParsedCookieTest,InvalidTooLong)302 TEST(ParsedCookieTest, InvalidTooLong) {
303   std::string maxstr;
304   maxstr.resize(CookieMonster::ParsedCookie::kMaxCookieSize, 'a');
305 
306   CookieMonster::ParsedCookie pc1(maxstr);
307   EXPECT_TRUE(pc1.IsValid());
308 
309   CookieMonster::ParsedCookie pc2(maxstr + "A");
310   EXPECT_FALSE(pc2.IsValid());
311 }
312 
TEST(ParsedCookieTest,InvalidEmpty)313 TEST(ParsedCookieTest, InvalidEmpty) {
314   CookieMonster::ParsedCookie pc("");
315   EXPECT_FALSE(pc.IsValid());
316 }
317 
TEST(ParsedCookieTest,EmbeddedTerminator)318 TEST(ParsedCookieTest, EmbeddedTerminator) {
319   CookieMonster::ParsedCookie pc1("AAA=BB\0ZYX");
320   CookieMonster::ParsedCookie pc2("AAA=BB\rZYX");
321   CookieMonster::ParsedCookie pc3("AAA=BB\nZYX");
322   EXPECT_TRUE(pc1.IsValid());
323   EXPECT_EQ("AAA", pc1.Name());
324   EXPECT_EQ("BB", pc1.Value());
325   EXPECT_TRUE(pc2.IsValid());
326   EXPECT_EQ("AAA", pc2.Name());
327   EXPECT_EQ("BB", pc2.Value());
328   EXPECT_TRUE(pc3.IsValid());
329   EXPECT_EQ("AAA", pc3.Name());
330   EXPECT_EQ("BB", pc3.Value());
331 }
332 
TEST(ParsedCookieTest,ParseTokensAndValues)333 TEST(ParsedCookieTest, ParseTokensAndValues) {
334   EXPECT_EQ("hello",
335             CookieMonster::ParsedCookie::ParseTokenString(
336                 "hello\nworld"));
337   EXPECT_EQ("fs!!@",
338             CookieMonster::ParsedCookie::ParseTokenString(
339                 "fs!!@;helloworld"));
340   EXPECT_EQ("hello world\tgood",
341             CookieMonster::ParsedCookie::ParseTokenString(
342                 "hello world\tgood\rbye"));
343   EXPECT_EQ("A",
344             CookieMonster::ParsedCookie::ParseTokenString(
345                 "A=B=C;D=E"));
346   EXPECT_EQ("hello",
347             CookieMonster::ParsedCookie::ParseValueString(
348                 "hello\nworld"));
349   EXPECT_EQ("fs!!@",
350             CookieMonster::ParsedCookie::ParseValueString(
351                 "fs!!@;helloworld"));
352   EXPECT_EQ("hello world\tgood",
353             CookieMonster::ParsedCookie::ParseValueString(
354                 "hello world\tgood\rbye"));
355   EXPECT_EQ("A=B=C",
356             CookieMonster::ParsedCookie::ParseValueString(
357                 "A=B=C;D=E"));
358 }
359 
360 static const char kUrlGoogle[] = "http://www.google.izzle";
361 static const char kUrlGoogleSpecific[] = "http://www.gmail.google.izzle";
362 static const char kUrlGoogleSecure[] = "https://www.google.izzle";
363 static const char kUrlFtp[] = "ftp://ftp.google.izzle/";
364 static const char kValidCookieLine[] = "A=B; path=/";
365 static const char kValidDomainCookieLine[] = "A=B; path=/; domain=google.izzle";
366 
TEST(CookieMonsterTest,DomainTest)367 TEST(CookieMonsterTest, DomainTest) {
368   GURL url_google(kUrlGoogle);
369 
370   scoped_refptr<MockPersistentCookieStore> store(
371       new MockPersistentCookieStore);
372   scoped_refptr<CookieMonster> cm(new CookieMonster(store, NULL));
373   EXPECT_TRUE(cm->SetCookie(url_google, "A=B"));
374   EXPECT_EQ("A=B", cm->GetCookies(url_google));
375   EXPECT_TRUE(cm->SetCookie(url_google, "C=D; domain=.google.izzle"));
376   EXPECT_EQ("A=B; C=D", cm->GetCookies(url_google));
377 
378   // Verify that A=B was set as a host cookie rather than a domain
379   // cookie -- should not be accessible from a sub sub-domain.
380   EXPECT_EQ("C=D", cm->GetCookies(GURL("http://foo.www.google.izzle")));
381 
382   // Test and make sure we find domain cookies on the same domain.
383   EXPECT_TRUE(cm->SetCookie(url_google, "E=F; domain=.www.google.izzle"));
384   EXPECT_EQ("A=B; C=D; E=F", cm->GetCookies(url_google));
385 
386   // Test setting a domain= that doesn't start w/ a dot, should
387   // treat it as a domain cookie, as if there was a pre-pended dot.
388   EXPECT_TRUE(cm->SetCookie(url_google, "G=H; domain=www.google.izzle"));
389   EXPECT_EQ("A=B; C=D; E=F; G=H", cm->GetCookies(url_google));
390 
391   // Test domain enforcement, should fail on a sub-domain or something too deep.
392   EXPECT_FALSE(cm->SetCookie(url_google, "I=J; domain=.izzle"));
393   EXPECT_EQ("", cm->GetCookies(GURL("http://a.izzle")));
394   EXPECT_FALSE(cm->SetCookie(url_google, "K=L; domain=.bla.www.google.izzle"));
395   EXPECT_EQ("C=D; E=F; G=H",
396             cm->GetCookies(GURL("http://bla.www.google.izzle")));
397   EXPECT_EQ("A=B; C=D; E=F; G=H", cm->GetCookies(url_google));
398 
399   // Nothing was persisted to the backing store.
400   EXPECT_EQ(0u, store->commands().size());
401 }
402 
403 // FireFox recognizes domains containing trailing periods as valid.
404 // IE and Safari do not. Assert the expected policy here.
TEST(CookieMonsterTest,DomainWithTrailingDotTest)405 TEST(CookieMonsterTest, DomainWithTrailingDotTest) {
406   scoped_refptr<MockPersistentCookieStore> store(
407       new MockPersistentCookieStore);
408   scoped_refptr<CookieMonster> cm(new CookieMonster(store, NULL));
409   GURL url_google("http://www.google.com");
410 
411   EXPECT_FALSE(cm->SetCookie(url_google, "a=1; domain=.www.google.com."));
412   EXPECT_FALSE(cm->SetCookie(url_google, "b=2; domain=.www.google.com.."));
413   EXPECT_EQ("", cm->GetCookies(url_google));
414 
415   // Nothing was persisted to the backing store.
416   EXPECT_EQ(0u, store->commands().size());
417 }
418 
419 // Test that cookies can bet set on higher level domains.
420 // http://b/issue?id=896491
TEST(CookieMonsterTest,ValidSubdomainTest)421 TEST(CookieMonsterTest, ValidSubdomainTest) {
422   scoped_refptr<MockPersistentCookieStore> store(
423       new MockPersistentCookieStore);
424   scoped_refptr<CookieMonster> cm(new CookieMonster(store, NULL));
425   GURL url_abcd("http://a.b.c.d.com");
426   GURL url_bcd("http://b.c.d.com");
427   GURL url_cd("http://c.d.com");
428   GURL url_d("http://d.com");
429 
430   EXPECT_TRUE(cm->SetCookie(url_abcd, "a=1; domain=.a.b.c.d.com"));
431   EXPECT_TRUE(cm->SetCookie(url_abcd, "b=2; domain=.b.c.d.com"));
432   EXPECT_TRUE(cm->SetCookie(url_abcd, "c=3; domain=.c.d.com"));
433   EXPECT_TRUE(cm->SetCookie(url_abcd, "d=4; domain=.d.com"));
434 
435   EXPECT_EQ("a=1; b=2; c=3; d=4", cm->GetCookies(url_abcd));
436   EXPECT_EQ("b=2; c=3; d=4", cm->GetCookies(url_bcd));
437   EXPECT_EQ("c=3; d=4", cm->GetCookies(url_cd));
438   EXPECT_EQ("d=4", cm->GetCookies(url_d));
439 
440   // Check that the same cookie can exist on different sub-domains.
441   EXPECT_TRUE(cm->SetCookie(url_bcd, "X=bcd; domain=.b.c.d.com"));
442   EXPECT_TRUE(cm->SetCookie(url_bcd, "X=cd; domain=.c.d.com"));
443   EXPECT_EQ("b=2; c=3; d=4; X=bcd; X=cd", cm->GetCookies(url_bcd));
444   EXPECT_EQ("c=3; d=4; X=cd", cm->GetCookies(url_cd));
445 
446   // Nothing was persisted to the backing store.
447   EXPECT_EQ(0u, store->commands().size());
448 }
449 
450 // Test that setting a cookie which specifies an invalid domain has
451 // no side-effect. An invalid domain in this context is one which does
452 // not match the originating domain.
453 // http://b/issue?id=896472
TEST(CookieMonsterTest,InvalidDomainTest)454 TEST(CookieMonsterTest, InvalidDomainTest) {
455   {
456     scoped_refptr<MockPersistentCookieStore> store(
457         new MockPersistentCookieStore);
458 
459     scoped_refptr<CookieMonster> cm(new CookieMonster(store, NULL));
460     GURL url_foobar("http://foo.bar.com");
461 
462     // More specific sub-domain than allowed.
463     EXPECT_FALSE(cm->SetCookie(url_foobar, "a=1; domain=.yo.foo.bar.com"));
464 
465     EXPECT_FALSE(cm->SetCookie(url_foobar, "b=2; domain=.foo.com"));
466     EXPECT_FALSE(cm->SetCookie(url_foobar, "c=3; domain=.bar.foo.com"));
467 
468     // Different TLD, but the rest is a substring.
469     EXPECT_FALSE(cm->SetCookie(url_foobar, "d=4; domain=.foo.bar.com.net"));
470 
471     // A substring that isn't really a parent domain.
472     EXPECT_FALSE(cm->SetCookie(url_foobar, "e=5; domain=ar.com"));
473 
474     // Completely invalid domains:
475     EXPECT_FALSE(cm->SetCookie(url_foobar, "f=6; domain=."));
476     EXPECT_FALSE(cm->SetCookie(url_foobar, "g=7; domain=/"));
477     EXPECT_FALSE(cm->SetCookie(url_foobar, "h=8; domain=http://foo.bar.com"));
478     EXPECT_FALSE(cm->SetCookie(url_foobar, "i=9; domain=..foo.bar.com"));
479     EXPECT_FALSE(cm->SetCookie(url_foobar, "j=10; domain=..bar.com"));
480 
481     // Make sure there isn't something quirky in the domain canonicalization
482     // that supports full URL semantics.
483     EXPECT_FALSE(cm->SetCookie(url_foobar, "k=11; domain=.foo.bar.com?blah"));
484     EXPECT_FALSE(cm->SetCookie(url_foobar, "l=12; domain=.foo.bar.com/blah"));
485     EXPECT_FALSE(cm->SetCookie(url_foobar, "m=13; domain=.foo.bar.com:80"));
486     EXPECT_FALSE(cm->SetCookie(url_foobar, "n=14; domain=.foo.bar.com:"));
487     EXPECT_FALSE(cm->SetCookie(url_foobar, "o=15; domain=.foo.bar.com#sup"));
488 
489     EXPECT_EQ("", cm->GetCookies(url_foobar));
490 
491     // Nothing was persisted to the backing store.
492     EXPECT_EQ(0u, store->commands().size());
493   }
494 
495   {
496     // Make sure the cookie code hasn't gotten its subdomain string handling
497     // reversed, missed a suffix check, etc.  It's important here that the two
498     // hosts below have the same domain + registry.
499     scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
500     GURL url_foocom("http://foo.com.com");
501     EXPECT_FALSE(cm->SetCookie(url_foocom, "a=1; domain=.foo.com.com.com"));
502     EXPECT_EQ("", cm->GetCookies(url_foocom));
503   }
504 }
505 
506 // Test the behavior of omitting dot prefix from domain, should
507 // function the same as FireFox.
508 // http://b/issue?id=889898
TEST(CookieMonsterTest,DomainWithoutLeadingDotTest)509 TEST(CookieMonsterTest, DomainWithoutLeadingDotTest) {
510   {  // The omission of dot results in setting a domain cookie.
511     scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
512     GURL url_hosted("http://manage.hosted.filefront.com");
513     GURL url_filefront("http://www.filefront.com");
514     EXPECT_TRUE(cm->SetCookie(url_hosted, "sawAd=1; domain=filefront.com"));
515     EXPECT_EQ("sawAd=1", cm->GetCookies(url_hosted));
516     EXPECT_EQ("sawAd=1", cm->GetCookies(url_filefront));
517   }
518 
519   {  // Even when the domains match exactly, don't consider it host cookie.
520     scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
521     GURL url("http://www.google.com");
522     EXPECT_TRUE(cm->SetCookie(url, "a=1; domain=www.google.com"));
523     EXPECT_EQ("a=1", cm->GetCookies(url));
524     EXPECT_EQ("a=1", cm->GetCookies(GURL("http://sub.www.google.com")));
525     EXPECT_EQ("", cm->GetCookies(GURL("http://something-else.com")));
526   }
527 }
528 
529 // Test that the domain specified in cookie string is treated case-insensitive
530 // http://b/issue?id=896475.
TEST(CookieMonsterTest,CaseInsensitiveDomainTest)531 TEST(CookieMonsterTest, CaseInsensitiveDomainTest) {
532   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
533   GURL url_google("http://www.google.com");
534   EXPECT_TRUE(cm->SetCookie(url_google, "a=1; domain=.GOOGLE.COM"));
535   EXPECT_TRUE(cm->SetCookie(url_google, "b=2; domain=.wWw.gOOgLE.coM"));
536   EXPECT_EQ("a=1; b=2", cm->GetCookies(url_google));
537 }
538 
TEST(CookieMonsterTest,TestIpAddress)539 TEST(CookieMonsterTest, TestIpAddress) {
540   GURL url_ip("http://1.2.3.4/weee");
541   {
542     scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
543     EXPECT_TRUE(cm->SetCookie(url_ip, kValidCookieLine));
544     EXPECT_EQ("A=B", cm->GetCookies(url_ip));
545   }
546 
547   {  // IP addresses should not be able to set domain cookies.
548     scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
549     EXPECT_FALSE(cm->SetCookie(url_ip, "b=2; domain=.1.2.3.4"));
550     EXPECT_FALSE(cm->SetCookie(url_ip, "c=3; domain=.3.4"));
551     EXPECT_EQ("", cm->GetCookies(url_ip));
552     // It should be allowed to set a cookie if domain= matches the IP address
553     // exactly.  This matches IE/Firefox, even though it seems a bit wrong.
554     EXPECT_FALSE(cm->SetCookie(url_ip, "b=2; domain=1.2.3.3"));
555     EXPECT_EQ("", cm->GetCookies(url_ip));
556     EXPECT_TRUE(cm->SetCookie(url_ip, "b=2; domain=1.2.3.4"));
557     EXPECT_EQ("b=2", cm->GetCookies(url_ip));
558   }
559 }
560 
561 // Test host cookies, and setting of cookies on TLD.
TEST(CookieMonsterTest,TestNonDottedAndTLD)562 TEST(CookieMonsterTest, TestNonDottedAndTLD) {
563   {
564     scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
565     GURL url("http://com/");
566     // Allow setting on "com", (but only as a host cookie).
567     EXPECT_TRUE(cm->SetCookie(url, "a=1"));
568     EXPECT_FALSE(cm->SetCookie(url, "b=2; domain=.com"));
569     EXPECT_FALSE(cm->SetCookie(url, "c=3; domain=com"));
570     EXPECT_EQ("a=1", cm->GetCookies(url));
571     // Make sure it doesn't show up for a normal .com, it should be a host
572     // not a domain cookie.
573     EXPECT_EQ("", cm->GetCookies(GURL("http://hopefully-no-cookies.com/")));
574     EXPECT_EQ("", cm->GetCookies(GURL("http://.com/")));
575   }
576 
577   {  // http://com. should be treated the same as http://com.
578     scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
579     GURL url("http://com./index.html");
580     EXPECT_TRUE(cm->SetCookie(url, "a=1"));
581     EXPECT_EQ("a=1", cm->GetCookies(url));
582     EXPECT_EQ("", cm->GetCookies(GURL("http://hopefully-no-cookies.com./")));
583   }
584 
585   {  // Should not be able to set host cookie from a subdomain.
586     scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
587     GURL url("http://a.b");
588     EXPECT_FALSE(cm->SetCookie(url, "a=1; domain=.b"));
589     EXPECT_FALSE(cm->SetCookie(url, "b=2; domain=b"));
590     EXPECT_EQ("", cm->GetCookies(url));
591   }
592 
593   {  // Same test as above, but explicitly on a known TLD (com).
594     scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
595     GURL url("http://google.com");
596     EXPECT_FALSE(cm->SetCookie(url, "a=1; domain=.com"));
597     EXPECT_FALSE(cm->SetCookie(url, "b=2; domain=com"));
598     EXPECT_EQ("", cm->GetCookies(url));
599   }
600 
601   {  // Make sure can't set cookie on TLD which is dotted.
602     scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
603     GURL url("http://google.co.uk");
604     EXPECT_FALSE(cm->SetCookie(url, "a=1; domain=.co.uk"));
605     EXPECT_FALSE(cm->SetCookie(url, "b=2; domain=.uk"));
606     EXPECT_EQ("", cm->GetCookies(url));
607     EXPECT_EQ("", cm->GetCookies(GURL("http://something-else.co.uk")));
608     EXPECT_EQ("", cm->GetCookies(GURL("http://something-else.uk")));
609   }
610 
611   {  // Intranet URLs should only be able to set host cookies.
612     scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
613     GURL url("http://b");
614     EXPECT_TRUE(cm->SetCookie(url, "a=1"));
615     EXPECT_FALSE(cm->SetCookie(url, "b=2; domain=.b"));
616     EXPECT_FALSE(cm->SetCookie(url, "c=3; domain=b"));
617     EXPECT_EQ("a=1", cm->GetCookies(url));
618   }
619 }
620 
621 // Test reading/writing cookies when the domain ends with a period,
622 // as in "www.google.com."
TEST(CookieMonsterTest,TestHostEndsWithDot)623 TEST(CookieMonsterTest, TestHostEndsWithDot) {
624   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
625   GURL url("http://www.google.com");
626   GURL url_with_dot("http://www.google.com.");
627   EXPECT_TRUE(cm->SetCookie(url, "a=1"));
628   EXPECT_EQ("a=1", cm->GetCookies(url));
629 
630   // Do not share cookie space with the dot version of domain.
631   // Note: this is not what FireFox does, but it _is_ what IE+Safari do.
632   EXPECT_FALSE(cm->SetCookie(url, "b=2; domain=.www.google.com."));
633   EXPECT_EQ("a=1", cm->GetCookies(url));
634 
635   EXPECT_TRUE(cm->SetCookie(url_with_dot, "b=2; domain=.google.com."));
636   EXPECT_EQ("b=2", cm->GetCookies(url_with_dot));
637 
638   // Make sure there weren't any side effects.
639   EXPECT_EQ(cm->GetCookies(GURL("http://hopefully-no-cookies.com/")), "");
640   EXPECT_EQ("", cm->GetCookies(GURL("http://.com/")));
641 }
642 
TEST(CookieMonsterTest,InvalidScheme)643 TEST(CookieMonsterTest, InvalidScheme) {
644   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
645   EXPECT_FALSE(cm->SetCookie(GURL(kUrlFtp), kValidCookieLine));
646 }
647 
TEST(CookieMonsterTest,InvalidScheme_Read)648 TEST(CookieMonsterTest, InvalidScheme_Read) {
649   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
650   EXPECT_TRUE(cm->SetCookie(GURL(kUrlGoogle), kValidDomainCookieLine));
651   EXPECT_EQ("", cm->GetCookies(GURL(kUrlFtp)));
652 }
653 
TEST(CookieMonsterTest,PathTest)654 TEST(CookieMonsterTest, PathTest) {
655   std::string url("http://www.google.izzle");
656   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
657   EXPECT_TRUE(cm->SetCookie(GURL(url), "A=B; path=/wee"));
658   EXPECT_EQ("A=B", cm->GetCookies(GURL(url + "/wee")));
659   EXPECT_EQ("A=B", cm->GetCookies(GURL(url + "/wee/")));
660   EXPECT_EQ("A=B", cm->GetCookies(GURL(url + "/wee/war")));
661   EXPECT_EQ("A=B", cm->GetCookies(GURL(url + "/wee/war/more/more")));
662   EXPECT_EQ("", cm->GetCookies(GURL(url + "/weehee")));
663   EXPECT_EQ("", cm->GetCookies(GURL(url + "/")));
664 
665   // If we add a 0 length path, it should default to /
666   EXPECT_TRUE(cm->SetCookie(GURL(url), "A=C; path="));
667   EXPECT_EQ("A=B; A=C", cm->GetCookies(GURL(url + "/wee")));
668   EXPECT_EQ("A=C", cm->GetCookies(GURL(url + "/")));
669 }
670 
TEST(CookieMonsterTest,HttpOnlyTest)671 TEST(CookieMonsterTest, HttpOnlyTest) {
672   GURL url_google(kUrlGoogle);
673   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
674   CookieOptions options;
675   options.set_include_httponly();
676 
677   // Create a httponly cookie.
678   EXPECT_TRUE(cm->SetCookieWithOptions(url_google, "A=B; httponly", options));
679 
680   // Check httponly read protection.
681   EXPECT_EQ("", cm->GetCookies(url_google));
682   EXPECT_EQ("A=B", cm->GetCookiesWithOptions(url_google, options));
683 
684   // Check httponly overwrite protection.
685   EXPECT_FALSE(cm->SetCookie(url_google, "A=C"));
686   EXPECT_EQ("", cm->GetCookies(url_google));
687   EXPECT_EQ("A=B", cm->GetCookiesWithOptions(url_google, options));
688   EXPECT_TRUE(cm->SetCookieWithOptions(url_google, "A=C", options));
689   EXPECT_EQ("A=C", cm->GetCookies(url_google));
690 
691   // Check httponly create protection.
692   EXPECT_FALSE(cm->SetCookie(url_google, "B=A; httponly"));
693   EXPECT_EQ("A=C", cm->GetCookiesWithOptions(url_google, options));
694   EXPECT_TRUE(cm->SetCookieWithOptions(url_google, "B=A; httponly", options));
695   EXPECT_EQ("A=C; B=A", cm->GetCookiesWithOptions(url_google, options));
696   EXPECT_EQ("A=C", cm->GetCookies(url_google));
697 }
698 
699 namespace {
700 
701 struct CookieDateParsingCase {
702   const char* str;
703   const bool valid;
704   const time_t epoch;
705 };
706 
707 struct DomainIsHostOnlyCase {
708   const char* str;
709   const bool is_host_only;
710 };
711 
712 }  // namespace
713 
TEST(CookieMonsterTest,TestCookieDateParsing)714 TEST(CookieMonsterTest, TestCookieDateParsing) {
715   const CookieDateParsingCase tests[] = {
716     { "Sat, 15-Apr-17 21:01:22 GMT",           true, 1492290082 },
717     { "Thu, 19-Apr-2007 16:00:00 GMT",         true, 1176998400 },
718     { "Wed, 25 Apr 2007 21:02:13 GMT",         true, 1177534933 },
719     { "Thu, 19/Apr\\2007 16:00:00 GMT",        true, 1176998400 },
720     { "Fri, 1 Jan 2010 01:01:50 GMT",          true, 1262307710 },
721     { "Wednesday, 1-Jan-2003 00:00:00 GMT",    true, 1041379200 },
722     { ", 1-Jan-2003 00:00:00 GMT",             true, 1041379200 },
723     { " 1-Jan-2003 00:00:00 GMT",              true, 1041379200 },
724     { "1-Jan-2003 00:00:00 GMT",               true, 1041379200 },
725     { "Wed,18-Apr-07 22:50:12 GMT",            true, 1176936612 },
726     { "WillyWonka  , 18-Apr-07 22:50:12 GMT",  true, 1176936612 },
727     { "WillyWonka  , 18-Apr-07 22:50:12",      true, 1176936612 },
728     { "WillyWonka  ,  18-apr-07   22:50:12",   true, 1176936612 },
729     { "Mon, 18-Apr-1977 22:50:13 GMT",         true, 230251813 },
730     { "Mon, 18-Apr-77 22:50:13 GMT",           true, 230251813 },
731     // If the cookie came in with the expiration quoted (which in terms of
732     // the RFC you shouldn't do), we will get string quoted.  Bug 1261605.
733     { "\"Sat, 15-Apr-17\\\"21:01:22\\\"GMT\"", true, 1492290082 },
734     // Test with full month names and partial names.
735     { "Partyday, 18- April-07 22:50:12",       true, 1176936612 },
736     { "Partyday, 18 - Apri-07 22:50:12",       true, 1176936612 },
737     { "Wednes, 1-Januar-2003 00:00:00 GMT",    true, 1041379200 },
738     // Test that we always take GMT even with other time zones or bogus
739     // values.  The RFC says everything should be GMT, and in the worst case
740     // we are 24 hours off because of zone issues.
741     { "Sat, 15-Apr-17 21:01:22",               true, 1492290082 },
742     { "Sat, 15-Apr-17 21:01:22 GMT-2",         true, 1492290082 },
743     { "Sat, 15-Apr-17 21:01:22 GMT BLAH",      true, 1492290082 },
744     { "Sat, 15-Apr-17 21:01:22 GMT-0400",      true, 1492290082 },
745     { "Sat, 15-Apr-17 21:01:22 GMT-0400 (EDT)",true, 1492290082 },
746     { "Sat, 15-Apr-17 21:01:22 DST",           true, 1492290082 },
747     { "Sat, 15-Apr-17 21:01:22 -0400",         true, 1492290082 },
748     { "Sat, 15-Apr-17 21:01:22 (hello there)", true, 1492290082 },
749     // Test that if we encounter multiple : fields, that we take the first
750     // that correctly parses.
751     { "Sat, 15-Apr-17 21:01:22 11:22:33",      true, 1492290082 },
752     { "Sat, 15-Apr-17 ::00 21:01:22",          true, 1492290082 },
753     { "Sat, 15-Apr-17 boink:z 21:01:22",       true, 1492290082 },
754     // We take the first, which in this case is invalid.
755     { "Sat, 15-Apr-17 91:22:33 21:01:22",      false, 0 },
756     // amazon.com formats their cookie expiration like this.
757     { "Thu Apr 18 22:50:12 2007 GMT",          true, 1176936612 },
758     // Test that hh:mm:ss can occur anywhere.
759     { "22:50:12 Thu Apr 18 2007 GMT",          true, 1176936612 },
760     { "Thu 22:50:12 Apr 18 2007 GMT",          true, 1176936612 },
761     { "Thu Apr 22:50:12 18 2007 GMT",          true, 1176936612 },
762     { "Thu Apr 18 22:50:12 2007 GMT",          true, 1176936612 },
763     { "Thu Apr 18 2007 22:50:12 GMT",          true, 1176936612 },
764     { "Thu Apr 18 2007 GMT 22:50:12",          true, 1176936612 },
765     // Test that the day and year can be anywhere if they are unambigious.
766     { "Sat, 15-Apr-17 21:01:22 GMT",           true, 1492290082 },
767     { "15-Sat, Apr-17 21:01:22 GMT",           true, 1492290082 },
768     { "15-Sat, Apr 21:01:22 GMT 17",           true, 1492290082 },
769     { "15-Sat, Apr 21:01:22 GMT 2017",         true, 1492290082 },
770     { "15 Apr 21:01:22 2017",                  true, 1492290082 },
771     { "15 17 Apr 21:01:22",                    true, 1492290082 },
772     { "Apr 15 17 21:01:22",                    true, 1492290082 },
773     { "Apr 15 21:01:22 17",                    true, 1492290082 },
774     { "2017 April 15 21:01:22",                true, 1492290082 },
775     { "15 April 2017 21:01:22",                true, 1492290082 },
776     // Some invalid dates
777     { "98 April 17 21:01:22",                    false, 0 },
778     { "Thu, 012-Aug-2008 20:49:07 GMT",          false, 0 },
779     { "Thu, 12-Aug-31841 20:49:07 GMT",          false, 0 },
780     { "Thu, 12-Aug-9999999999 20:49:07 GMT",     false, 0 },
781     { "Thu, 999999999999-Aug-2007 20:49:07 GMT", false, 0 },
782     { "Thu, 12-Aug-2007 20:61:99999999999 GMT",  false, 0 },
783     { "IAintNoDateFool",                         false, 0 },
784   };
785 
786   Time parsed_time;
787   for (size_t i = 0; i < arraysize(tests); ++i) {
788     parsed_time = CookieMonster::ParseCookieTime(tests[i].str);
789     if (!tests[i].valid) {
790       EXPECT_FALSE(!parsed_time.is_null()) << tests[i].str;
791       continue;
792     }
793     EXPECT_TRUE(!parsed_time.is_null()) << tests[i].str;
794     EXPECT_EQ(tests[i].epoch, parsed_time.ToTimeT()) << tests[i].str;
795   }
796 }
797 
TEST(CookieMonsterTest,TestDomainIsHostOnly)798 TEST(CookieMonsterTest, TestDomainIsHostOnly) {
799   const DomainIsHostOnlyCase tests[] = {
800     { "",               true },
801     { "www.google.com", true },
802     { ".google.com",    false }
803   };
804 
805   for (size_t i = 0; i < arraysize(tests); ++i) {
806     EXPECT_EQ(tests[i].is_host_only,
807               CookieMonster::DomainIsHostOnly(tests[i].str));
808   }
809 }
810 
TEST(CookieMonsterTest,TestCookieDeletion)811 TEST(CookieMonsterTest, TestCookieDeletion) {
812   GURL url_google(kUrlGoogle);
813   scoped_refptr<MockPersistentCookieStore> store(
814       new MockPersistentCookieStore);
815   scoped_refptr<CookieMonster> cm(new CookieMonster(store, NULL));
816 
817   // Create a session cookie.
818   EXPECT_TRUE(cm->SetCookie(url_google, kValidCookieLine));
819   EXPECT_EQ("A=B", cm->GetCookies(url_google));
820   // Delete it via Max-Age.
821   EXPECT_TRUE(cm->SetCookie(url_google,
822                            std::string(kValidCookieLine) + "; max-age=0"));
823   EXPECT_EQ("", cm->GetCookies(url_google));
824 
825   // Create a session cookie.
826   EXPECT_TRUE(cm->SetCookie(url_google, kValidCookieLine));
827   EXPECT_EQ("A=B", cm->GetCookies(url_google));
828   // Delete it via Expires.
829   EXPECT_TRUE(cm->SetCookie(url_google,
830                            std::string(kValidCookieLine) +
831                            "; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
832   EXPECT_EQ("", cm->GetCookies(url_google));
833 
834   // Create a persistent cookie.
835   EXPECT_TRUE(cm->SetCookie(url_google,
836                            std::string(kValidCookieLine) +
837                            "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
838   ASSERT_EQ(1u, store->commands().size());
839   EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type);
840 
841   EXPECT_EQ("A=B", cm->GetCookies(url_google));
842   // Delete it via Max-Age.
843   EXPECT_TRUE(cm->SetCookie(url_google,
844                            std::string(kValidCookieLine) + "; max-age=0"));
845   ASSERT_EQ(2u, store->commands().size());
846   EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type);
847   EXPECT_EQ("", cm->GetCookies(url_google));
848 
849   // Create a persistent cookie.
850   EXPECT_TRUE(cm->SetCookie(url_google,
851                            std::string(kValidCookieLine) +
852                            "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
853   ASSERT_EQ(3u, store->commands().size());
854   EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[2].type);
855   EXPECT_EQ("A=B", cm->GetCookies(url_google));
856   // Delete it via Expires.
857   EXPECT_TRUE(cm->SetCookie(url_google,
858                            std::string(kValidCookieLine) +
859                            "; expires=Mon, 18-Apr-1977 22:50:13 GMT"));
860   ASSERT_EQ(4u, store->commands().size());
861   EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[3].type);
862   EXPECT_EQ("", cm->GetCookies(url_google));
863 
864   // Create a persistent cookie.
865   EXPECT_TRUE(cm->SetCookie(url_google,
866                            std::string(kValidCookieLine) +
867                            "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
868   ASSERT_EQ(5u, store->commands().size());
869   EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[4].type);
870   EXPECT_EQ("A=B", cm->GetCookies(url_google));
871   // Delete it via Expires, with a unix epoch of 0.
872   EXPECT_TRUE(cm->SetCookie(url_google,
873                            std::string(kValidCookieLine) +
874                            "; expires=Thu, 1-Jan-1970 00:00:00 GMT"));
875   ASSERT_EQ(6u, store->commands().size());
876   EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[5].type);
877   EXPECT_EQ("", cm->GetCookies(url_google));
878 }
879 
TEST(CookieMonsterTest,TestCookieDeleteAll)880 TEST(CookieMonsterTest, TestCookieDeleteAll) {
881   GURL url_google(kUrlGoogle);
882   scoped_refptr<MockPersistentCookieStore> store(
883       new MockPersistentCookieStore);
884   scoped_refptr<CookieMonster> cm(new CookieMonster(store, NULL));
885   CookieOptions options;
886   options.set_include_httponly();
887 
888   EXPECT_TRUE(cm->SetCookie(url_google, kValidCookieLine));
889   EXPECT_EQ("A=B", cm->GetCookies(url_google));
890 
891   EXPECT_TRUE(cm->SetCookieWithOptions(url_google, "C=D; httponly", options));
892   EXPECT_EQ("A=B; C=D", cm->GetCookiesWithOptions(url_google, options));
893 
894   EXPECT_EQ(2, cm->DeleteAll(false));
895   EXPECT_EQ("", cm->GetCookiesWithOptions(url_google, options));
896 
897   EXPECT_EQ(0u, store->commands().size());
898 
899   // Create a persistent cookie.
900   EXPECT_TRUE(cm->SetCookie(url_google,
901                             std::string(kValidCookieLine) +
902                             "; expires=Mon, 18-Apr-22 22:50:13 GMT"));
903   ASSERT_EQ(1u, store->commands().size());
904   EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type);
905 
906   EXPECT_EQ(1, cm->DeleteAll(true));  // sync_to_store = true.
907   ASSERT_EQ(2u, store->commands().size());
908   EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type);
909 
910   EXPECT_EQ("", cm->GetCookiesWithOptions(url_google, options));
911 }
912 
TEST(CookieMonsterTest,TestCookieDeleteAllCreatedAfterTimestamp)913 TEST(CookieMonsterTest, TestCookieDeleteAllCreatedAfterTimestamp) {
914   GURL url_google(kUrlGoogle);
915   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
916   Time now = Time::Now();
917 
918   // Nothing has been added so nothing should be deleted.
919   EXPECT_EQ(0, cm->DeleteAllCreatedAfter(now - TimeDelta::FromDays(99), false));
920 
921   // Create 3 cookies with creation date of today, yesterday and the day before.
922   EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google, "T-0=Now", now));
923   EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google, "T-1=Yesterday",
924                                            now - TimeDelta::FromDays(1)));
925   EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google, "T-2=DayBefore",
926                                            now - TimeDelta::FromDays(2)));
927 
928   // Try to delete everything from now onwards.
929   EXPECT_EQ(1, cm->DeleteAllCreatedAfter(now, false));
930   // Now delete the one cookie created in the last day.
931   EXPECT_EQ(1, cm->DeleteAllCreatedAfter(now - TimeDelta::FromDays(1), false));
932   // Now effectively delete all cookies just created (1 is remaining).
933   EXPECT_EQ(1, cm->DeleteAllCreatedAfter(now - TimeDelta::FromDays(99), false));
934 
935   // Make sure everything is gone.
936   EXPECT_EQ(0, cm->DeleteAllCreatedAfter(Time(), false));
937   // Really make sure everything is gone.
938   EXPECT_EQ(0, cm->DeleteAll(false));
939 }
940 
TEST(CookieMonsterTest,TestCookieDeleteAllCreatedBetweenTimestamps)941 TEST(CookieMonsterTest, TestCookieDeleteAllCreatedBetweenTimestamps) {
942   GURL url_google(kUrlGoogle);
943   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
944   Time now = Time::Now();
945 
946   // Nothing has been added so nothing should be deleted.
947   EXPECT_EQ(0, cm->DeleteAllCreatedAfter(now - TimeDelta::FromDays(99), false));
948 
949   // Create 3 cookies with creation date of today, yesterday and the day before.
950   EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google, "T-0=Now", now));
951   EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google, "T-1=Yesterday",
952                                            now - TimeDelta::FromDays(1)));
953   EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google, "T-2=DayBefore",
954                                            now - TimeDelta::FromDays(2)));
955   EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google, "T-3=ThreeDays",
956                                            now - TimeDelta::FromDays(3)));
957   EXPECT_TRUE(cm->SetCookieWithCreationTime(url_google, "T-7=LastWeek",
958                                            now - TimeDelta::FromDays(7)));
959 
960   // Try to delete threedays and the daybefore.
961   EXPECT_EQ(2, cm->DeleteAllCreatedBetween(now - TimeDelta::FromDays(3),
962                                           now - TimeDelta::FromDays(1),
963                                           false));
964 
965   // Try to delete yesterday, also make sure that delete_end is not
966   // inclusive.
967   EXPECT_EQ(1, cm->DeleteAllCreatedBetween(now - TimeDelta::FromDays(2),
968                                           now,
969                                           false));
970 
971   // Make sure the delete_begin is inclusive.
972   EXPECT_EQ(1, cm->DeleteAllCreatedBetween(now - TimeDelta::FromDays(7),
973                                           now,
974                                           false));
975 
976   // Delete the last (now) item.
977   EXPECT_EQ(1, cm->DeleteAllCreatedAfter(Time(), false));
978 
979   // Really make sure everything is gone.
980   EXPECT_EQ(0, cm->DeleteAll(false));
981 }
982 
TEST(CookieMonsterTest,TestSecure)983 TEST(CookieMonsterTest, TestSecure) {
984   GURL url_google(kUrlGoogle);
985   GURL url_google_secure(kUrlGoogleSecure);
986   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
987 
988   EXPECT_TRUE(cm->SetCookie(url_google, "A=B"));
989   EXPECT_EQ("A=B", cm->GetCookies(url_google));
990   EXPECT_EQ("A=B", cm->GetCookies(url_google_secure));
991 
992   EXPECT_TRUE(cm->SetCookie(url_google_secure, "A=B; secure"));
993   // The secure should overwrite the non-secure.
994   EXPECT_EQ("", cm->GetCookies(url_google));
995   EXPECT_EQ("A=B", cm->GetCookies(url_google_secure));
996 
997   EXPECT_TRUE(cm->SetCookie(url_google_secure, "D=E; secure"));
998   EXPECT_EQ("", cm->GetCookies(url_google));
999   EXPECT_EQ("A=B; D=E", cm->GetCookies(url_google_secure));
1000 
1001   EXPECT_TRUE(cm->SetCookie(url_google_secure, "A=B"));
1002   // The non-secure should overwrite the secure.
1003   EXPECT_EQ("A=B", cm->GetCookies(url_google));
1004   EXPECT_EQ("D=E; A=B", cm->GetCookies(url_google_secure));
1005 }
1006 
GetFirstCookieAccessDate(CookieMonster * cm)1007 static Time GetFirstCookieAccessDate(CookieMonster* cm) {
1008   const CookieList all_cookies(cm->GetAllCookies());
1009   return all_cookies.front().LastAccessDate();
1010 }
1011 
1012 static const int kLastAccessThresholdMilliseconds = 200;
1013 
TEST(CookieMonsterTest,TestLastAccess)1014 TEST(CookieMonsterTest, TestLastAccess) {
1015   GURL url_google(kUrlGoogle);
1016   scoped_refptr<CookieMonster> cm(
1017       new CookieMonster(NULL, NULL, kLastAccessThresholdMilliseconds));
1018 
1019   EXPECT_TRUE(cm->SetCookie(url_google, "A=B"));
1020   const Time last_access_date(GetFirstCookieAccessDate(cm));
1021 
1022   // Reading the cookie again immediately shouldn't update the access date,
1023   // since we're inside the threshold.
1024   EXPECT_EQ("A=B", cm->GetCookies(url_google));
1025   EXPECT_TRUE(last_access_date == GetFirstCookieAccessDate(cm));
1026 
1027   // Reading after a short wait should update the access date.
1028   base::PlatformThread::Sleep(kLastAccessThresholdMilliseconds + 20);
1029   EXPECT_EQ("A=B", cm->GetCookies(url_google));
1030   EXPECT_FALSE(last_access_date == GetFirstCookieAccessDate(cm));
1031 }
1032 
CountInString(const std::string & str,char c)1033 static int CountInString(const std::string& str, char c) {
1034   return std::count(str.begin(), str.end(), c);
1035 }
1036 
TestHostGarbageCollectHelper(int domain_max_cookies,int domain_purge_cookies,CookieMonster::ExpiryAndKeyScheme key_scheme)1037 static void TestHostGarbageCollectHelper(
1038     int domain_max_cookies,
1039     int domain_purge_cookies,
1040     CookieMonster::ExpiryAndKeyScheme key_scheme) {
1041   GURL url_google(kUrlGoogle);
1042   const int more_than_enough_cookies =
1043       (domain_max_cookies + domain_purge_cookies) * 2;
1044   // Add a bunch of cookies on a single host, should purge them.
1045   {
1046     scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1047     cm->SetExpiryAndKeyScheme(key_scheme);
1048     for (int i = 0; i < more_than_enough_cookies; ++i) {
1049       std::string cookie = base::StringPrintf("a%03d=b", i);
1050       EXPECT_TRUE(cm->SetCookie(url_google, cookie));
1051       std::string cookies = cm->GetCookies(url_google);
1052       // Make sure we find it in the cookies.
1053       EXPECT_NE(cookies.find(cookie), std::string::npos);
1054       // Count the number of cookies.
1055       EXPECT_LE(CountInString(cookies, '='), domain_max_cookies);
1056     }
1057   }
1058 
1059   // Add a bunch of cookies on multiple hosts within a single eTLD.
1060   // Should keep at least kDomainMaxCookies - kDomainPurgeCookies
1061   // between them.  If we are using the effective domain keying system
1062   // (EKS_KEEP_RECENT_AND_PURGE_ETLDP1) we shouldn't go above
1063   // kDomainMaxCookies for both together.  If we're using the domain
1064   // keying system (EKS_DISCARD_RECENT_AND_PURGE_DOMAIN), each
1065   // individual domain shouldn't go above kDomainMaxCookies.
1066   GURL url_google_specific(kUrlGoogleSpecific);
1067   {
1068     scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1069     cm->SetExpiryAndKeyScheme(key_scheme);
1070     for (int i = 0; i < more_than_enough_cookies; ++i) {
1071       std::string cookie_general = base::StringPrintf("a%03d=b", i);
1072       EXPECT_TRUE(cm->SetCookie(url_google, cookie_general));
1073       std::string cookie_specific = base::StringPrintf("c%03d=b", i);
1074       EXPECT_TRUE(cm->SetCookie(url_google_specific, cookie_specific));
1075       std::string cookies_general = cm->GetCookies(url_google);
1076       EXPECT_NE(cookies_general.find(cookie_general), std::string::npos);
1077       std::string cookies_specific = cm->GetCookies(url_google_specific);
1078       EXPECT_NE(cookies_specific.find(cookie_specific), std::string::npos);
1079       if (key_scheme == CookieMonster::EKS_KEEP_RECENT_AND_PURGE_ETLDP1) {
1080         EXPECT_LE((CountInString(cookies_general, '=') +
1081                    CountInString(cookies_specific, '=')),
1082                   domain_max_cookies);
1083       } else {
1084         EXPECT_LE(CountInString(cookies_general, '='), domain_max_cookies);
1085         EXPECT_LE(CountInString(cookies_specific, '='), domain_max_cookies);
1086       }
1087     }
1088     // After all this, there should be at least
1089     // kDomainMaxCookies - kDomainPurgeCookies for both URLs.
1090     std::string cookies_general = cm->GetCookies(url_google);
1091     std::string cookies_specific = cm->GetCookies(url_google_specific);
1092     if (key_scheme == CookieMonster::EKS_KEEP_RECENT_AND_PURGE_ETLDP1) {
1093       int total_cookies = (CountInString(cookies_general, '=') +
1094                            CountInString(cookies_specific, '='));
1095       EXPECT_GE(total_cookies,
1096                 domain_max_cookies - domain_purge_cookies);
1097       EXPECT_LE(total_cookies, domain_max_cookies);
1098     } else {
1099       int general_cookies = CountInString(cookies_general, '=');
1100       int specific_cookies = CountInString(cookies_specific, '=');
1101       EXPECT_GE(general_cookies,
1102                 domain_max_cookies - domain_purge_cookies);
1103       EXPECT_LE(general_cookies, domain_max_cookies);
1104       EXPECT_GE(specific_cookies,
1105                 domain_max_cookies - domain_purge_cookies);
1106       EXPECT_LE(specific_cookies, domain_max_cookies);
1107     }
1108   }
1109 }
1110 
TEST(CookieMonsterTest,TestHostGarbageCollection)1111 TEST(CookieMonsterTest, TestHostGarbageCollection) {
1112   TestHostGarbageCollectHelper(
1113       CookieMonster::kDomainMaxCookies, CookieMonster::kDomainPurgeCookies,
1114       CookieMonster::EKS_KEEP_RECENT_AND_PURGE_ETLDP1);
1115   TestHostGarbageCollectHelper(
1116       CookieMonster::kDomainMaxCookies, CookieMonster::kDomainPurgeCookies,
1117       CookieMonster::EKS_DISCARD_RECENT_AND_PURGE_DOMAIN);
1118 }
1119 
1120 // Formerly NetUtilTest.CookieTest back when we used wininet's cookie handling.
TEST(CookieMonsterTest,NetUtilCookieTest)1121 TEST(CookieMonsterTest, NetUtilCookieTest) {
1122   const GURL test_url("http://mojo.jojo.google.izzle/");
1123 
1124   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1125 
1126   EXPECT_TRUE(cm->SetCookie(test_url, "foo=bar"));
1127   std::string value = cm->GetCookies(test_url);
1128   EXPECT_EQ("foo=bar", value);
1129 
1130   // test that we can retrieve all cookies:
1131   EXPECT_TRUE(cm->SetCookie(test_url, "x=1"));
1132   EXPECT_TRUE(cm->SetCookie(test_url, "y=2"));
1133 
1134   std::string result = cm->GetCookies(test_url);
1135   EXPECT_FALSE(result.empty());
1136   EXPECT_NE(result.find("x=1"), std::string::npos) << result;
1137   EXPECT_NE(result.find("y=2"), std::string::npos) << result;
1138 }
1139 
FindAndDeleteCookie(CookieMonster * cm,const std::string & domain,const std::string & name)1140 static bool FindAndDeleteCookie(CookieMonster* cm,
1141                                 const std::string& domain,
1142                                 const std::string& name) {
1143   CookieList cookies = cm->GetAllCookies();
1144   for (CookieList::iterator it = cookies.begin();
1145        it != cookies.end(); ++it)
1146     if (it->Domain() == domain && it->Name() == name)
1147       return cm->DeleteCanonicalCookie(*it);
1148   return false;
1149 }
1150 
TEST(CookieMonsterTest,TestDeleteSingleCookie)1151 TEST(CookieMonsterTest, TestDeleteSingleCookie) {
1152   GURL url_google(kUrlGoogle);
1153 
1154   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1155 
1156   EXPECT_TRUE(cm->SetCookie(url_google, "A=B"));
1157   EXPECT_TRUE(cm->SetCookie(url_google, "C=D"));
1158   EXPECT_TRUE(cm->SetCookie(url_google, "E=F"));
1159   EXPECT_EQ("A=B; C=D; E=F", cm->GetCookies(url_google));
1160 
1161   EXPECT_TRUE(FindAndDeleteCookie(cm, url_google.host(), "C"));
1162   EXPECT_EQ("A=B; E=F", cm->GetCookies(url_google));
1163 
1164   EXPECT_FALSE(FindAndDeleteCookie(cm, "random.host", "E"));
1165   EXPECT_EQ("A=B; E=F", cm->GetCookies(url_google));
1166 }
1167 
TEST(CookieMonsterTest,SetCookieableSchemes)1168 TEST(CookieMonsterTest, SetCookieableSchemes) {
1169   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1170   scoped_refptr<CookieMonster> cm_foo(new CookieMonster(NULL, NULL));
1171 
1172   // Only cm_foo should allow foo:// cookies.
1173   const char* kSchemes[] = {"foo"};
1174   cm_foo->SetCookieableSchemes(kSchemes, 1);
1175 
1176   GURL foo_url("foo://host/path");
1177   GURL http_url("http://host/path");
1178 
1179   EXPECT_TRUE(cm->SetCookie(http_url, "x=1"));
1180   EXPECT_FALSE(cm->SetCookie(foo_url, "x=1"));
1181   EXPECT_TRUE(cm_foo->SetCookie(foo_url, "x=1"));
1182   EXPECT_FALSE(cm_foo->SetCookie(http_url, "x=1"));
1183 }
1184 
TEST(CookieMonsterTest,GetAllCookiesForURL)1185 TEST(CookieMonsterTest, GetAllCookiesForURL) {
1186   GURL url_google(kUrlGoogle);
1187   GURL url_google_secure(kUrlGoogleSecure);
1188 
1189   scoped_refptr<CookieMonster> cm(
1190       new CookieMonster(NULL, NULL, kLastAccessThresholdMilliseconds));
1191 
1192   // Create an httponly cookie.
1193   CookieOptions options;
1194   options.set_include_httponly();
1195 
1196   EXPECT_TRUE(cm->SetCookieWithOptions(url_google, "A=B; httponly", options));
1197   EXPECT_TRUE(cm->SetCookieWithOptions(url_google,
1198                                        "C=D; domain=.google.izzle",
1199                                        options));
1200   EXPECT_TRUE(cm->SetCookieWithOptions(url_google_secure,
1201                                        "E=F; domain=.google.izzle; secure",
1202                                        options));
1203 
1204   const Time last_access_date(GetFirstCookieAccessDate(cm));
1205 
1206   base::PlatformThread::Sleep(kLastAccessThresholdMilliseconds + 20);
1207 
1208   // Check cookies for url.
1209   CookieList cookies = cm->GetAllCookiesForURL(url_google);
1210   CookieList::iterator it = cookies.begin();
1211 
1212   ASSERT_TRUE(it != cookies.end());
1213   EXPECT_EQ("www.google.izzle", it->Domain());
1214   EXPECT_EQ("A", it->Name());
1215 
1216   ASSERT_TRUE(++it != cookies.end());
1217   EXPECT_EQ(".google.izzle", it->Domain());
1218   EXPECT_EQ("C", it->Name());
1219 
1220   ASSERT_TRUE(++it == cookies.end());
1221 
1222   // Check cookies for url excluding http-only cookies.
1223   cookies =
1224       cm->GetAllCookiesForURLWithOptions(url_google, CookieOptions());
1225   it = cookies.begin();
1226 
1227   ASSERT_TRUE(it != cookies.end());
1228   EXPECT_EQ(".google.izzle", it->Domain());
1229   EXPECT_EQ("C", it->Name());
1230 
1231   ASSERT_TRUE(++it == cookies.end());
1232 
1233   // Test secure cookies.
1234   cookies = cm->GetAllCookiesForURL(url_google_secure);
1235   it = cookies.begin();
1236 
1237   ASSERT_TRUE(it != cookies.end());
1238   EXPECT_EQ("www.google.izzle", it->Domain());
1239   EXPECT_EQ("A", it->Name());
1240 
1241   ASSERT_TRUE(++it != cookies.end());
1242   EXPECT_EQ(".google.izzle", it->Domain());
1243   EXPECT_EQ("C", it->Name());
1244 
1245   ASSERT_TRUE(++it != cookies.end());
1246   EXPECT_EQ(".google.izzle", it->Domain());
1247   EXPECT_EQ("E", it->Name());
1248 
1249   ASSERT_TRUE(++it == cookies.end());
1250 
1251   // Reading after a short wait should not update the access date.
1252   EXPECT_TRUE(last_access_date == GetFirstCookieAccessDate(cm));
1253 }
1254 
TEST(CookieMonsterTest,GetAllCookiesForURLPathMatching)1255 TEST(CookieMonsterTest, GetAllCookiesForURLPathMatching) {
1256   GURL url_google(kUrlGoogle);
1257   GURL url_google_foo("http://www.google.izzle/foo");
1258   GURL url_google_bar("http://www.google.izzle/bar");
1259 
1260   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1261   CookieOptions options;
1262 
1263   EXPECT_TRUE(cm->SetCookieWithOptions(url_google_foo,
1264                                        "A=B; path=/foo;",
1265                                        options));
1266   EXPECT_TRUE(cm->SetCookieWithOptions(url_google_bar,
1267                                        "C=D; path=/bar;",
1268                                        options));
1269   EXPECT_TRUE(cm->SetCookieWithOptions(url_google,
1270                                        "E=F;",
1271                                        options));
1272 
1273   CookieList cookies = cm->GetAllCookiesForURL(url_google_foo);
1274   CookieList::iterator it = cookies.begin();
1275 
1276   ASSERT_TRUE(it != cookies.end());
1277   EXPECT_EQ("A", it->Name());
1278   EXPECT_EQ("/foo", it->Path());
1279 
1280   ASSERT_TRUE(++it != cookies.end());
1281   EXPECT_EQ("E", it->Name());
1282   EXPECT_EQ("/", it->Path());
1283 
1284   ASSERT_TRUE(++it == cookies.end());
1285 
1286   cookies = cm->GetAllCookiesForURL(url_google_bar);
1287   it = cookies.begin();
1288 
1289   ASSERT_TRUE(it != cookies.end());
1290   EXPECT_EQ("C", it->Name());
1291   EXPECT_EQ("/bar", it->Path());
1292 
1293   ASSERT_TRUE(++it != cookies.end());
1294   EXPECT_EQ("E", it->Name());
1295   EXPECT_EQ("/", it->Path());
1296 
1297   ASSERT_TRUE(++it == cookies.end());
1298 }
1299 
TEST(CookieMonsterTest,DeleteCookieByName)1300 TEST(CookieMonsterTest, DeleteCookieByName) {
1301   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1302   GURL url_google(kUrlGoogle);
1303 
1304   EXPECT_TRUE(cm->SetCookie(url_google, "A=A1; path=/"));
1305   EXPECT_TRUE(cm->SetCookie(url_google, "A=A2; path=/foo"));
1306   EXPECT_TRUE(cm->SetCookie(url_google, "A=A3; path=/bar"));
1307   EXPECT_TRUE(cm->SetCookie(url_google, "B=B1; path=/"));
1308   EXPECT_TRUE(cm->SetCookie(url_google, "B=B2; path=/foo"));
1309   EXPECT_TRUE(cm->SetCookie(url_google, "B=B3; path=/bar"));
1310 
1311   cm->DeleteCookie(GURL(std::string(kUrlGoogle) + "/foo/bar"), "A");
1312 
1313   CookieList cookies = cm->GetAllCookies();
1314   size_t expected_size = 4;
1315   EXPECT_EQ(expected_size, cookies.size());
1316   for (CookieList::iterator it = cookies.begin();
1317        it != cookies.end(); ++it) {
1318     EXPECT_NE("A1", it->Value());
1319     EXPECT_NE("A2", it->Value());
1320   }
1321 }
1322 
1323 // Test that overwriting persistent cookies deletes the old one from the
1324 // backing store.
TEST(CookieMonsterTest,OverwritePersistentCookie)1325 TEST(CookieMonsterTest, OverwritePersistentCookie) {
1326   GURL url_google("http://www.google.com/");
1327   GURL url_chromium("http://chromium.org");
1328   scoped_refptr<MockPersistentCookieStore> store(
1329       new MockPersistentCookieStore);
1330   scoped_refptr<CookieMonster> cm(new CookieMonster(store, NULL));
1331 
1332   // Insert a cookie "a" for path "/path1"
1333   EXPECT_TRUE(
1334       cm->SetCookie(url_google, "a=val1; path=/path1; "
1335                                 "expires=Mon, 18-Apr-22 22:50:13 GMT"));
1336   ASSERT_EQ(1u, store->commands().size());
1337   EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type);
1338 
1339   // Insert a cookie "b" for path "/path1"
1340   EXPECT_TRUE(
1341       cm->SetCookie(url_google, "b=val1; path=/path1; "
1342                                 "expires=Mon, 18-Apr-22 22:50:14 GMT"));
1343   ASSERT_EQ(2u, store->commands().size());
1344   EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[1].type);
1345 
1346   // Insert a cookie "b" for path "/path1", that is httponly. This should
1347   // overwrite the non-http-only version.
1348   CookieOptions allow_httponly;
1349   allow_httponly.set_include_httponly();
1350   EXPECT_TRUE(
1351     cm->SetCookieWithOptions(url_google,
1352                              "b=val2; path=/path1; httponly; "
1353                              "expires=Mon, 18-Apr-22 22:50:14 GMT",
1354                              allow_httponly));
1355   ASSERT_EQ(4u, store->commands().size());
1356   EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[2].type);
1357   EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[3].type);
1358 
1359   // Insert a cookie "a" for path "/path1". This should overwrite.
1360   EXPECT_TRUE(cm->SetCookie(url_google,
1361                             "a=val33; path=/path1; "
1362                             "expires=Mon, 18-Apr-22 22:50:14 GMT"));
1363   ASSERT_EQ(6u, store->commands().size());
1364   EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[4].type);
1365   EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[5].type);
1366 
1367   // Insert a cookie "a" for path "/path2". This should NOT overwrite
1368   // cookie "a", since the path is different.
1369   EXPECT_TRUE(cm->SetCookie(url_google,
1370                             "a=val9; path=/path2; "
1371                             "expires=Mon, 18-Apr-22 22:50:14 GMT"));
1372   ASSERT_EQ(7u, store->commands().size());
1373   EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[6].type);
1374 
1375   // Insert a cookie "a" for path "/path1", but this time for "chromium.org".
1376   // Although the name and path match, the hostnames do not, so shouldn't
1377   // overwrite.
1378   EXPECT_TRUE(cm->SetCookie(url_chromium,
1379                             "a=val99; path=/path1; "
1380                             "expires=Mon, 18-Apr-22 22:50:14 GMT"));
1381   ASSERT_EQ(8u, store->commands().size());
1382   EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[7].type);
1383 
1384   EXPECT_EQ("a=val33", cm->GetCookies(GURL("http://www.google.com/path1")));
1385   EXPECT_EQ("a=val9", cm->GetCookies(GURL("http://www.google.com/path2")));
1386   EXPECT_EQ("a=val99", cm->GetCookies(GURL("http://chromium.org/path1")));
1387 }
1388 
1389 // Tests importing from a persistent cookie store that contains duplicate
1390 // equivalent cookies. This situation should be handled by removing the
1391 // duplicate cookie (both from the in-memory cache, and from the backing store).
1392 //
1393 // This is a regression test for: http://crbug.com/17855.
TEST(CookieMonsterTest,DontImportDuplicateCookies)1394 TEST(CookieMonsterTest, DontImportDuplicateCookies) {
1395   GURL url_google("http://www.google.com/");
1396 
1397   scoped_refptr<MockPersistentCookieStore> store(
1398       new MockPersistentCookieStore);
1399 
1400   // We will fill some initial cookies into the PersistentCookieStore,
1401   // to simulate a database with 4 duplicates.  Note that we need to
1402   // be careful not to have any duplicate creation times at all (as it's a
1403   // violation of a CookieMonster invariant) even if Time::Now() doesn't
1404   // move between calls.
1405   std::vector<CookieMonster::CanonicalCookie*> initial_cookies;
1406 
1407   // Insert 4 cookies with name "X" on path "/", with varying creation
1408   // dates. We expect only the most recent one to be preserved following
1409   // the import.
1410 
1411   AddCookieToList("www.google.com",
1412                   "X=1; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
1413                   Time::Now() + TimeDelta::FromDays(3),
1414                   &initial_cookies);
1415 
1416   AddCookieToList("www.google.com",
1417                   "X=2; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
1418                   Time::Now() + TimeDelta::FromDays(1),
1419                   &initial_cookies);
1420 
1421   // ===> This one is the WINNER (biggest creation time).  <====
1422   AddCookieToList("www.google.com",
1423                   "X=3; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
1424                   Time::Now() + TimeDelta::FromDays(4),
1425                   &initial_cookies);
1426 
1427   AddCookieToList("www.google.com",
1428                   "X=4; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
1429                   Time::Now(),
1430                   &initial_cookies);
1431 
1432   // Insert 2 cookies with name "X" on path "/2", with varying creation
1433   // dates. We expect only the most recent one to be preserved the import.
1434 
1435   // ===> This one is the WINNER (biggest creation time).  <====
1436   AddCookieToList("www.google.com",
1437                   "X=a1; path=/2; expires=Mon, 18-Apr-22 22:50:14 GMT",
1438                   Time::Now() + TimeDelta::FromDays(9),
1439                   &initial_cookies);
1440 
1441   AddCookieToList("www.google.com",
1442                   "X=a2; path=/2; expires=Mon, 18-Apr-22 22:50:14 GMT",
1443                   Time::Now() + TimeDelta::FromDays(2),
1444                   &initial_cookies);
1445 
1446   // Insert 1 cookie with name "Y" on path "/".
1447   AddCookieToList("www.google.com",
1448                   "Y=a; path=/; expires=Mon, 18-Apr-22 22:50:14 GMT",
1449                   Time::Now() + TimeDelta::FromDays(10),
1450                   &initial_cookies);
1451 
1452   // Inject our initial cookies into the mock PersistentCookieStore.
1453   store->SetLoadExpectation(true, initial_cookies);
1454 
1455   scoped_refptr<CookieMonster> cm(new CookieMonster(store, NULL));
1456 
1457   // Verify that duplicates were not imported for path "/".
1458   // (If this had failed, GetCookies() would have also returned X=1, X=2, X=4).
1459   EXPECT_EQ("X=3; Y=a", cm->GetCookies(GURL("http://www.google.com/")));
1460 
1461   // Verify that same-named cookie on a different path ("/x2") didn't get
1462   // messed up.
1463   EXPECT_EQ("X=a1; X=3; Y=a",
1464             cm->GetCookies(GURL("http://www.google.com/2/x")));
1465 
1466   // Verify that the PersistentCookieStore was told to kill its 4 duplicates.
1467   ASSERT_EQ(4u, store->commands().size());
1468   EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[0].type);
1469   EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type);
1470   EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[2].type);
1471   EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[3].type);
1472 }
1473 
1474 // Tests importing from a persistent cookie store that contains cookies
1475 // with duplicate creation times.  This situation should be handled by
1476 // dropping the cookies before insertion/visibility to user.
1477 //
1478 // This is a regression test for: http://crbug.com/43188.
TEST(CookieMonsterTest,DontImportDuplicateCreationTimes)1479 TEST(CookieMonsterTest, DontImportDuplicateCreationTimes) {
1480   GURL url_google("http://www.google.com/");
1481 
1482   scoped_refptr<MockPersistentCookieStore> store(
1483       new MockPersistentCookieStore);
1484 
1485   Time now(Time::Now());
1486   Time earlier(now - TimeDelta::FromDays(1));
1487 
1488   // Insert 8 cookies, four with the current time as creation times, and
1489   // four with the earlier time as creation times.  We should only get
1490   // two cookies remaining, but which two (other than that there should
1491   // be one from each set) will be random.
1492   std::vector<CookieMonster::CanonicalCookie*> initial_cookies;
1493   AddCookieToList("www.google.com", "X=1; path=/", now, &initial_cookies);
1494   AddCookieToList("www.google.com", "X=2; path=/", now, &initial_cookies);
1495   AddCookieToList("www.google.com", "X=3; path=/", now, &initial_cookies);
1496   AddCookieToList("www.google.com", "X=4; path=/", now, &initial_cookies);
1497 
1498   AddCookieToList("www.google.com", "Y=1; path=/", earlier, &initial_cookies);
1499   AddCookieToList("www.google.com", "Y=2; path=/", earlier, &initial_cookies);
1500   AddCookieToList("www.google.com", "Y=3; path=/", earlier, &initial_cookies);
1501   AddCookieToList("www.google.com", "Y=4; path=/", earlier, &initial_cookies);
1502 
1503   // Inject our initial cookies into the mock PersistentCookieStore.
1504   store->SetLoadExpectation(true, initial_cookies);
1505 
1506   scoped_refptr<CookieMonster> cm(new CookieMonster(store, NULL));
1507 
1508   CookieList list(cm->GetAllCookies());
1509   EXPECT_EQ(2U, list.size());
1510   // Confirm that we have one of each.
1511   std::string name1(list[0].Name());
1512   std::string name2(list[1].Name());
1513   EXPECT_TRUE(name1 == "X" || name2 == "X");
1514   EXPECT_TRUE(name1 == "Y" || name2 == "Y");
1515   EXPECT_NE(name1, name2);
1516 }
1517 
TEST(CookieMonsterTest,Delegate)1518 TEST(CookieMonsterTest, Delegate) {
1519   GURL url_google(kUrlGoogle);
1520 
1521   scoped_refptr<MockPersistentCookieStore> store(
1522       new MockPersistentCookieStore);
1523   scoped_refptr<MockCookieMonsterDelegate> delegate(
1524       new MockCookieMonsterDelegate);
1525   scoped_refptr<CookieMonster> cm(new CookieMonster(store, delegate));
1526 
1527   EXPECT_TRUE(cm->SetCookie(url_google, "A=B"));
1528   EXPECT_TRUE(cm->SetCookie(url_google, "C=D"));
1529   EXPECT_TRUE(cm->SetCookie(url_google, "E=F"));
1530   EXPECT_EQ("A=B; C=D; E=F", cm->GetCookies(url_google));
1531   ASSERT_EQ(3u, delegate->changes().size());
1532   EXPECT_FALSE(delegate->changes()[0].second);
1533   EXPECT_EQ(url_google.host(), delegate->changes()[0].first.Domain());
1534   EXPECT_EQ("A", delegate->changes()[0].first.Name());
1535   EXPECT_EQ("B", delegate->changes()[0].first.Value());
1536   EXPECT_EQ(url_google.host(), delegate->changes()[1].first.Domain());
1537   EXPECT_FALSE(delegate->changes()[1].second);
1538   EXPECT_EQ("C", delegate->changes()[1].first.Name());
1539   EXPECT_EQ("D", delegate->changes()[1].first.Value());
1540   EXPECT_EQ(url_google.host(), delegate->changes()[2].first.Domain());
1541   EXPECT_FALSE(delegate->changes()[2].second);
1542   EXPECT_EQ("E", delegate->changes()[2].first.Name());
1543   EXPECT_EQ("F", delegate->changes()[2].first.Value());
1544   delegate->reset();
1545 
1546   EXPECT_TRUE(FindAndDeleteCookie(cm, url_google.host(), "C"));
1547   EXPECT_EQ("A=B; E=F", cm->GetCookies(url_google));
1548   ASSERT_EQ(1u, delegate->changes().size());
1549   EXPECT_EQ(url_google.host(), delegate->changes()[0].first.Domain());
1550   EXPECT_TRUE(delegate->changes()[0].second);
1551   EXPECT_EQ("C", delegate->changes()[0].first.Name());
1552   EXPECT_EQ("D", delegate->changes()[0].first.Value());
1553   delegate->reset();
1554 
1555   EXPECT_FALSE(FindAndDeleteCookie(cm, "random.host", "E"));
1556   EXPECT_EQ("A=B; E=F", cm->GetCookies(url_google));
1557   EXPECT_EQ(0u, delegate->changes().size());
1558 
1559   // Insert a cookie "a" for path "/path1"
1560   EXPECT_TRUE(
1561       cm->SetCookie(url_google, "a=val1; path=/path1; "
1562                                 "expires=Mon, 18-Apr-22 22:50:13 GMT"));
1563   ASSERT_EQ(1u, store->commands().size());
1564   EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type);
1565   ASSERT_EQ(1u, delegate->changes().size());
1566   EXPECT_FALSE(delegate->changes()[0].second);
1567   EXPECT_EQ(url_google.host(), delegate->changes()[0].first.Domain());
1568   EXPECT_EQ("a", delegate->changes()[0].first.Name());
1569   EXPECT_EQ("val1", delegate->changes()[0].first.Value());
1570   delegate->reset();
1571 
1572   // Insert a cookie "a" for path "/path1", that is httponly. This should
1573   // overwrite the non-http-only version.
1574   CookieOptions allow_httponly;
1575   allow_httponly.set_include_httponly();
1576   EXPECT_TRUE(
1577     cm->SetCookieWithOptions(url_google,
1578                              "a=val2; path=/path1; httponly; "
1579                              "expires=Mon, 18-Apr-22 22:50:14 GMT",
1580                              allow_httponly));
1581   ASSERT_EQ(3u, store->commands().size());
1582   EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type);
1583   EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[2].type);
1584   ASSERT_EQ(2u, delegate->changes().size());
1585   EXPECT_EQ(url_google.host(), delegate->changes()[0].first.Domain());
1586   EXPECT_TRUE(delegate->changes()[0].second);
1587   EXPECT_EQ("a", delegate->changes()[0].first.Name());
1588   EXPECT_EQ("val1", delegate->changes()[0].first.Value());
1589   EXPECT_EQ(url_google.host(), delegate->changes()[1].first.Domain());
1590   EXPECT_FALSE(delegate->changes()[1].second);
1591   EXPECT_EQ("a", delegate->changes()[1].first.Name());
1592   EXPECT_EQ("val2", delegate->changes()[1].first.Value());
1593   delegate->reset();
1594 }
1595 
TEST(CookieMonsterTest,SetCookieWithDetails)1596 TEST(CookieMonsterTest, SetCookieWithDetails) {
1597   GURL url_google(kUrlGoogle);
1598   GURL url_google_foo("http://www.google.izzle/foo");
1599   GURL url_google_bar("http://www.google.izzle/bar");
1600   GURL url_google_secure(kUrlGoogleSecure);
1601 
1602   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1603 
1604   EXPECT_TRUE(cm->SetCookieWithDetails(
1605       url_google_foo, "A", "B", std::string(), "/foo", base::Time(),
1606       false, false));
1607   EXPECT_TRUE(cm->SetCookieWithDetails(
1608       url_google_bar, "C", "D", "google.izzle", "/bar", base::Time(),
1609       false, true));
1610   EXPECT_TRUE(cm->SetCookieWithDetails(
1611       url_google, "E", "F", std::string(), std::string(), base::Time(),
1612       true, false));
1613 
1614   // Test that malformed attributes fail to set the cookie.
1615   EXPECT_FALSE(cm->SetCookieWithDetails(
1616       url_google_foo, " A", "B", std::string(), "/foo", base::Time(),
1617       false, false));
1618   EXPECT_FALSE(cm->SetCookieWithDetails(
1619       url_google_foo, "A;", "B", std::string(), "/foo", base::Time(),
1620       false, false));
1621   EXPECT_FALSE(cm->SetCookieWithDetails(
1622       url_google_foo, "A=", "B", std::string(), "/foo", base::Time(),
1623       false, false));
1624   EXPECT_FALSE(cm->SetCookieWithDetails(
1625       url_google_foo, "A", "B", "google.ozzzzzzle", "foo", base::Time(),
1626       false, false));
1627   EXPECT_FALSE(cm->SetCookieWithDetails(
1628       url_google_foo, "A=", "B", std::string(), "foo", base::Time(),
1629       false, false));
1630 
1631   CookieList cookies = cm->GetAllCookiesForURL(url_google_foo);
1632   CookieList::iterator it = cookies.begin();
1633 
1634   ASSERT_TRUE(it != cookies.end());
1635   EXPECT_EQ("A", it->Name());
1636   EXPECT_EQ("B", it->Value());
1637   EXPECT_EQ("www.google.izzle", it->Domain());
1638   EXPECT_EQ("/foo", it->Path());
1639   EXPECT_FALSE(it->DoesExpire());
1640   EXPECT_FALSE(it->IsSecure());
1641   EXPECT_FALSE(it->IsHttpOnly());
1642 
1643   ASSERT_TRUE(++it == cookies.end());
1644 
1645   cookies = cm->GetAllCookiesForURL(url_google_bar);
1646   it = cookies.begin();
1647 
1648   ASSERT_TRUE(it != cookies.end());
1649   EXPECT_EQ("C", it->Name());
1650   EXPECT_EQ("D", it->Value());
1651   EXPECT_EQ(".google.izzle", it->Domain());
1652   EXPECT_EQ("/bar", it->Path());
1653   EXPECT_FALSE(it->IsSecure());
1654   EXPECT_TRUE(it->IsHttpOnly());
1655 
1656   ASSERT_TRUE(++it == cookies.end());
1657 
1658   cookies = cm->GetAllCookiesForURL(url_google_secure);
1659   it = cookies.begin();
1660 
1661   ASSERT_TRUE(it != cookies.end());
1662   EXPECT_EQ("E", it->Name());
1663   EXPECT_EQ("F", it->Value());
1664   EXPECT_EQ("/", it->Path());
1665   EXPECT_EQ("www.google.izzle", it->Domain());
1666   EXPECT_TRUE(it->IsSecure());
1667   EXPECT_FALSE(it->IsHttpOnly());
1668 
1669   ASSERT_TRUE(++it == cookies.end());
1670 }
1671 
TEST(CookieMonsterTest,DeleteAllForHost)1672 TEST(CookieMonsterTest, DeleteAllForHost) {
1673   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1674 
1675   // Test probes:
1676   //    * Non-secure URL, mid-level (http://w.c.b.a)
1677   //    * Secure URL, mid-level (https://w.c.b.a)
1678   //    * URL with path, mid-level (https:/w.c.b.a/dir1/xx)
1679   // All three tests should nuke only the midlevel host cookie,
1680   // the http_only cookie, the host secure cookie, and the two host
1681   // path cookies.  http_only, secure, and paths are ignored by
1682   // this call, and domain cookies arent touched.
1683   PopulateCmForDeleteAllForHost(cm);
1684   EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X",
1685             cm->GetCookies(GURL(kTopLevelDomainPlus3)));
1686   EXPECT_EQ("dom_1=X; dom_2=X; host_2=X; sec_dom=X; sec_host=X",
1687             cm->GetCookies(GURL(kTopLevelDomainPlus2Secure)));
1688   EXPECT_EQ("dom_1=X; host_1=X", cm->GetCookies(GURL(kTopLevelDomainPlus1)));
1689   EXPECT_EQ("dom_path_2=X; host_path_2=X; dom_path_1=X; host_path_1=X; "
1690             "dom_1=X; dom_2=X; host_2=X; sec_dom=X; sec_host=X",
1691             cm->GetCookies(GURL(kTopLevelDomainPlus2Secure +
1692                                 std::string("/dir1/dir2/xxx"))));
1693 
1694   EXPECT_EQ(5, cm->DeleteAllForHost(GURL(kTopLevelDomainPlus2)));
1695   EXPECT_EQ(8U, cm->GetAllCookies().size());
1696 
1697   EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X",
1698             cm->GetCookies(GURL(kTopLevelDomainPlus3)));
1699   EXPECT_EQ("dom_1=X; dom_2=X; sec_dom=X",
1700             cm->GetCookies(GURL(kTopLevelDomainPlus2Secure)));
1701   EXPECT_EQ("dom_1=X; host_1=X", cm->GetCookies(GURL(kTopLevelDomainPlus1)));
1702   EXPECT_EQ("dom_path_2=X; dom_path_1=X; dom_1=X; dom_2=X; sec_dom=X",
1703             cm->GetCookies(GURL(kTopLevelDomainPlus2Secure +
1704                                 std::string("/dir1/dir2/xxx"))));
1705 
1706   PopulateCmForDeleteAllForHost(cm);
1707   EXPECT_EQ(5, cm->DeleteAllForHost(GURL(kTopLevelDomainPlus2Secure)));
1708   EXPECT_EQ(8U, cm->GetAllCookies().size());
1709 
1710   EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X",
1711             cm->GetCookies(GURL(kTopLevelDomainPlus3)));
1712   EXPECT_EQ("dom_1=X; dom_2=X; sec_dom=X",
1713             cm->GetCookies(GURL(kTopLevelDomainPlus2Secure)));
1714   EXPECT_EQ("dom_1=X; host_1=X", cm->GetCookies(GURL(kTopLevelDomainPlus1)));
1715   EXPECT_EQ("dom_path_2=X; dom_path_1=X; dom_1=X; dom_2=X; sec_dom=X",
1716             cm->GetCookies(GURL(kTopLevelDomainPlus2Secure +
1717                                 std::string("/dir1/dir2/xxx"))));
1718 
1719   PopulateCmForDeleteAllForHost(cm);
1720   EXPECT_EQ(5, cm->DeleteAllForHost(GURL(kTopLevelDomainPlus2Secure +
1721                                          std::string("/dir1/xxx"))));
1722   EXPECT_EQ(8U, cm->GetAllCookies().size());
1723 
1724   EXPECT_EQ("dom_1=X; dom_2=X; dom_3=X; host_3=X",
1725             cm->GetCookies(GURL(kTopLevelDomainPlus3)));
1726   EXPECT_EQ("dom_1=X; dom_2=X; sec_dom=X",
1727             cm->GetCookies(GURL(kTopLevelDomainPlus2Secure)));
1728   EXPECT_EQ("dom_1=X; host_1=X", cm->GetCookies(GURL(kTopLevelDomainPlus1)));
1729   EXPECT_EQ("dom_path_2=X; dom_path_1=X; dom_1=X; dom_2=X; sec_dom=X",
1730             cm->GetCookies(GURL(kTopLevelDomainPlus2Secure +
1731                                 std::string("/dir1/dir2/xxx"))));
1732 
1733 }
1734 
TEST(CookieMonsterTest,UniqueCreationTime)1735 TEST(CookieMonsterTest, UniqueCreationTime) {
1736   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1737   GURL url_google(kUrlGoogle);
1738   CookieOptions options;
1739 
1740   // Add in three cookies through every public interface to the
1741   // CookieMonster and confirm that none of them have duplicate
1742   // creation times.
1743 
1744   // SetCookieWithCreationTime and SetCookieWithCreationTimeAndOptions
1745   // are not included as they aren't going to be public for very much
1746   // longer.
1747 
1748   // SetCookie, SetCookies, SetCookiesWithOptions,
1749   // SetCookieWithOptions, SetCookieWithDetails
1750 
1751   cm->SetCookie(url_google, "SetCookie1=A");
1752   cm->SetCookie(url_google, "SetCookie2=A");
1753   cm->SetCookie(url_google, "SetCookie3=A");
1754 
1755   {
1756     std::vector<std::string> cookie_lines;
1757     cookie_lines.push_back("setCookies1=A");
1758     cookie_lines.push_back("setCookies2=A");
1759     cookie_lines.push_back("setCookies4=A");
1760     cm->SetCookies(url_google, cookie_lines);
1761   }
1762 
1763   {
1764     std::vector<std::string> cookie_lines;
1765     cookie_lines.push_back("setCookiesWithOptions1=A");
1766     cookie_lines.push_back("setCookiesWithOptions2=A");
1767     cookie_lines.push_back("setCookiesWithOptions3=A");
1768 
1769     cm->SetCookiesWithOptions(url_google, cookie_lines, options);
1770   }
1771 
1772   cm->SetCookieWithOptions(url_google, "setCookieWithOptions1=A", options);
1773   cm->SetCookieWithOptions(url_google, "setCookieWithOptions2=A", options);
1774   cm->SetCookieWithOptions(url_google, "setCookieWithOptions3=A", options);
1775 
1776   cm->SetCookieWithDetails(url_google, "setCookieWithDetails1", "A",
1777                            ".google.com", "/", Time(), false, false);
1778   cm->SetCookieWithDetails(url_google, "setCookieWithDetails2", "A",
1779                            ".google.com", "/", Time(), false, false);
1780   cm->SetCookieWithDetails(url_google, "setCookieWithDetails3", "A",
1781                            ".google.com", "/", Time(), false, false);
1782 
1783   // Now we check
1784   CookieList cookie_list(cm->GetAllCookies());
1785   typedef std::map<int64, CookieMonster::CanonicalCookie> TimeCookieMap;
1786   TimeCookieMap check_map;
1787   for (CookieList::const_iterator it = cookie_list.begin();
1788        it != cookie_list.end(); it++) {
1789     const int64 creation_date = it->CreationDate().ToInternalValue();
1790     TimeCookieMap::const_iterator
1791         existing_cookie_it(check_map.find(creation_date));
1792     EXPECT_TRUE(existing_cookie_it == check_map.end())
1793         << "Cookie " << it->Name() << " has same creation date ("
1794         << it->CreationDate().ToInternalValue()
1795         << ") as previously entered cookie "
1796         << existing_cookie_it->second.Name();
1797 
1798     if (existing_cookie_it == check_map.end()) {
1799       check_map.insert(TimeCookieMap::value_type(
1800           it->CreationDate().ToInternalValue(), *it));
1801     }
1802   }
1803 }
1804 
1805 // Mainly a test of GetEffectiveDomain, or more specifically, of the
1806 // expected behavior of GetEffectiveDomain within the CookieMonster.
TEST(CookieMonsterTest,GetKey)1807 TEST(CookieMonsterTest, GetKey) {
1808   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1809 
1810   // This test is really only interesting if GetKey() actually does something.
1811   if (cm->expiry_and_key_scheme_ ==
1812       CookieMonster::EKS_KEEP_RECENT_AND_PURGE_ETLDP1) {
1813     EXPECT_EQ("google.com", cm->GetKey("www.google.com"));
1814     EXPECT_EQ("google.izzie", cm->GetKey("www.google.izzie"));
1815     EXPECT_EQ("google.izzie", cm->GetKey(".google.izzie"));
1816     EXPECT_EQ("bbc.co.uk", cm->GetKey("bbc.co.uk"));
1817     EXPECT_EQ("bbc.co.uk", cm->GetKey("a.b.c.d.bbc.co.uk"));
1818     EXPECT_EQ("apple.com", cm->GetKey("a.b.c.d.apple.com"));
1819     EXPECT_EQ("apple.izzie", cm->GetKey("a.b.c.d.apple.izzie"));
1820 
1821     // Cases where the effective domain is null, so we use the host
1822     // as the key.
1823     EXPECT_EQ("co.uk", cm->GetKey("co.uk"));
1824     const std::string extension_name("iehocdgbbocmkdidlbnnfbmbinnahbae");
1825     EXPECT_EQ(extension_name, cm->GetKey(extension_name));
1826     EXPECT_EQ("com", cm->GetKey("com"));
1827     EXPECT_EQ("hostalias", cm->GetKey("hostalias"));
1828     EXPECT_EQ("localhost", cm->GetKey("localhost"));
1829   }
1830 }
1831 
1832 // Test that cookies transfer from/to the backing store correctly.
TEST(CookieMonsterTest,BackingStoreCommunication)1833 TEST(CookieMonsterTest, BackingStoreCommunication) {
1834   // Store details for cookies transforming through the backing store interface.
1835 
1836   base::Time current(base::Time::Now());
1837   scoped_refptr<MockSimplePersistentCookieStore> store(
1838       new MockSimplePersistentCookieStore);
1839   base::Time new_access_time;
1840   base::Time expires(base::Time::Now() + base::TimeDelta::FromSeconds(100));
1841 
1842   struct CookiesInputInfo {
1843     std::string gurl;
1844     std::string name;
1845     std::string value;
1846     std::string domain;
1847     std::string path;
1848     base::Time expires;
1849     bool secure;
1850     bool http_only;
1851   };
1852   const CookiesInputInfo input_info[] = {
1853     {"http://a.b.google.com", "a", "1", "", "/path/to/cookie", expires,
1854      false, false},
1855     {"https://www.google.com", "b", "2", ".google.com", "/path/from/cookie",
1856      expires + TimeDelta::FromSeconds(10), true, true},
1857     {"https://google.com", "c", "3", "", "/another/path/to/cookie",
1858      base::Time::Now() + base::TimeDelta::FromSeconds(100),
1859      true, false}
1860   };
1861   const int INPUT_DELETE = 1;
1862 
1863   // Create new cookies and flush them to the store.
1864   {
1865     scoped_refptr<CookieMonster> cmout(new CookieMonster(store, NULL));
1866     for (const CookiesInputInfo* p = input_info;
1867          p < &input_info[ARRAYSIZE_UNSAFE(input_info)]; p++) {
1868       EXPECT_TRUE(cmout->SetCookieWithDetails(GURL(p->gurl), p->name, p->value,
1869                                               p->domain, p->path, p->expires,
1870                                               p->secure, p->http_only));
1871     }
1872     cmout->DeleteCookie(GURL(std::string(input_info[INPUT_DELETE].gurl) +
1873                              input_info[INPUT_DELETE].path),
1874                         input_info[INPUT_DELETE].name);
1875   }
1876 
1877   // Create a new cookie monster and make sure that everything is correct
1878   {
1879     scoped_refptr<CookieMonster> cmin(new CookieMonster(store, NULL));
1880     CookieList cookies(cmin->GetAllCookies());
1881     ASSERT_EQ(2u, cookies.size());
1882     // Ordering is path length, then creation time.  So second cookie
1883     // will come first, and we need to swap them.
1884     std::swap(cookies[0], cookies[1]);
1885     for (int output_index = 0; output_index < 2; output_index++) {
1886       int input_index = output_index * 2;
1887       const CookiesInputInfo* input = &input_info[input_index];
1888       const CookieMonster::CanonicalCookie* output = &cookies[output_index];
1889 
1890       EXPECT_EQ(input->name, output->Name());
1891       EXPECT_EQ(input->value, output->Value());
1892       EXPECT_EQ(GURL(input->gurl).host(), output->Domain());
1893       EXPECT_EQ(input->path, output->Path());
1894       EXPECT_LE(current.ToInternalValue(),
1895                 output->CreationDate().ToInternalValue());
1896       EXPECT_EQ(input->secure, output->IsSecure());
1897       EXPECT_EQ(input->http_only, output->IsHttpOnly());
1898       EXPECT_TRUE(output->IsPersistent());
1899       EXPECT_EQ(input->expires.ToInternalValue(),
1900                 output->ExpiryDate().ToInternalValue());
1901     }
1902   }
1903 }
1904 
TEST(CookieMonsterTest,CookieOrdering)1905 TEST(CookieMonsterTest, CookieOrdering) {
1906   // Put a random set of cookies into a monster and make sure
1907   // they're returned in the right order.
1908   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
1909   EXPECT_TRUE(cm->SetCookie(GURL("http://d.c.b.a.google.com/aa/x.html"),
1910                             "c=1"));
1911   EXPECT_TRUE(cm->SetCookie(GURL("http://b.a.google.com/aa/bb/cc/x.html"),
1912                             "d=1; domain=b.a.google.com"));
1913   EXPECT_TRUE(cm->SetCookie(GURL("http://b.a.google.com/aa/bb/cc/x.html"),
1914                             "a=4; domain=b.a.google.com"));
1915   EXPECT_TRUE(cm->SetCookie(GURL("http://c.b.a.google.com/aa/bb/cc/x.html"),
1916                             "e=1; domain=c.b.a.google.com"));
1917   EXPECT_TRUE(cm->SetCookie(GURL("http://d.c.b.a.google.com/aa/bb/x.html"),
1918                             "b=1"));
1919   EXPECT_TRUE(cm->SetCookie(GURL("http://news.bbc.co.uk/midpath/x.html"),
1920                             "g=10"));
1921   EXPECT_EQ("d=1; a=4; e=1; b=1; c=1",
1922             cm->GetCookiesWithOptions(
1923                 GURL("http://d.c.b.a.google.com/aa/bb/cc/dd"),
1924                 CookieOptions()));
1925   {
1926     unsigned int i = 0;
1927     CookieList cookies(cm->GetAllCookiesForURL(
1928         GURL("http://d.c.b.a.google.com/aa/bb/cc/dd")));
1929     ASSERT_EQ(5u, cookies.size());
1930     EXPECT_EQ("d", cookies[i++].Name());
1931     EXPECT_EQ("a", cookies[i++].Name());
1932     EXPECT_EQ("e", cookies[i++].Name());
1933     EXPECT_EQ("b", cookies[i++].Name());
1934     EXPECT_EQ("c", cookies[i++].Name());
1935   }
1936 
1937   {
1938     unsigned int i = 0;
1939     CookieList cookies(cm->GetAllCookies());
1940     ASSERT_EQ(6u, cookies.size());
1941     EXPECT_EQ("d", cookies[i++].Name());
1942     EXPECT_EQ("a", cookies[i++].Name());
1943     EXPECT_EQ("e", cookies[i++].Name());
1944     EXPECT_EQ("g", cookies[i++].Name());
1945     EXPECT_EQ("b", cookies[i++].Name());
1946     EXPECT_EQ("c", cookies[i++].Name());
1947   }
1948 }
1949 
1950 
1951 // Function for creating a CM with a number of cookies in it,
1952 // no store (and hence no ability to affect access time).
CreateMonsterForGC(int num_cookies)1953 static CookieMonster* CreateMonsterForGC(int num_cookies) {
1954   CookieMonster* cm(new CookieMonster(NULL, NULL));
1955   for (int i = 0; i < num_cookies; i++)
1956     cm->SetCookie(GURL(StringPrintf("http://h%05d.izzle", i)), "a=1");
1957   return cm;
1958 }
1959 
1960 // This test and CookieMonstertest.TestGCTimes (in cookie_monster_perftest.cc)
1961 // are somewhat complementary twins.  This test is probing for whether
1962 // garbage collection always happens when it should (i.e. that we actually
1963 // get rid of cookies when we should).  The perftest is probing for
1964 // whether garbage collection happens when it shouldn't.  See comments
1965 // before that test for more details.
TEST(CookieMonsterTest,GarbageCollectionTriggers)1966 TEST(CookieMonsterTest, GarbageCollectionTriggers) {
1967   // First we check to make sure that a whole lot of recent cookies
1968   // doesn't get rid of anything after garbage collection is checked for.
1969   {
1970     scoped_refptr<CookieMonster> cm(
1971         CreateMonsterForGC(CookieMonster::kMaxCookies * 2));
1972     EXPECT_EQ(CookieMonster::kMaxCookies * 2, cm->GetAllCookies().size());
1973     cm->SetCookie(GURL("http://newdomain.com"), "b=2");
1974     EXPECT_EQ(CookieMonster::kMaxCookies * 2 + 1, cm->GetAllCookies().size());
1975   }
1976 
1977   // Now we explore a series of relationships between cookie last access
1978   // time and size of store to make sure we only get rid of cookies when
1979   // we really should.
1980   const struct TestCase {
1981     int num_cookies;
1982     int num_old_cookies;
1983     int expected_initial_cookies;
1984     // Indexed by ExpiryAndKeyScheme
1985     int expected_cookies_after_set[CookieMonster::EKS_LAST_ENTRY];
1986   } test_cases[] = {
1987     {
1988       // A whole lot of recent cookies; gc shouldn't happen.
1989       CookieMonster::kMaxCookies * 2,
1990       0,
1991       CookieMonster::kMaxCookies * 2,
1992       { CookieMonster::kMaxCookies * 2 + 1,
1993         CookieMonster::kMaxCookies - CookieMonster::kPurgeCookies }
1994     }, {
1995       // Some old cookies, but still overflowing max.
1996       CookieMonster::kMaxCookies * 2,
1997       CookieMonster::kMaxCookies / 2,
1998       CookieMonster::kMaxCookies * 2,
1999       {CookieMonster::kMaxCookies * 2 - CookieMonster::kMaxCookies / 2 + 1,
2000        CookieMonster::kMaxCookies - CookieMonster::kPurgeCookies}
2001     }, {
2002       // Old cookies enough to bring us right down to our purge line.
2003       CookieMonster::kMaxCookies * 2,
2004       CookieMonster::kMaxCookies + CookieMonster::kPurgeCookies + 1,
2005       CookieMonster::kMaxCookies * 2,
2006       {CookieMonster::kMaxCookies - CookieMonster::kPurgeCookies,
2007        CookieMonster::kMaxCookies - CookieMonster::kPurgeCookies}
2008     }, {
2009       // Old cookies enough to bring below our purge line (which we
2010       // shouldn't do).
2011       CookieMonster::kMaxCookies * 2,
2012       CookieMonster::kMaxCookies * 3 / 2,
2013       CookieMonster::kMaxCookies * 2,
2014       {CookieMonster::kMaxCookies - CookieMonster::kPurgeCookies,
2015        CookieMonster::kMaxCookies - CookieMonster::kPurgeCookies}
2016     }
2017   };
2018   const CookieMonster::ExpiryAndKeyScheme schemes[] = {
2019     CookieMonster::EKS_KEEP_RECENT_AND_PURGE_ETLDP1,
2020     CookieMonster::EKS_DISCARD_RECENT_AND_PURGE_DOMAIN,
2021   };
2022 
2023   for (int ci = 0; ci < static_cast<int>(ARRAYSIZE_UNSAFE(test_cases)); ++ci) {
2024     // Test both old and new key and expiry schemes.
2025     for (int recent_scheme = 0;
2026          recent_scheme < static_cast<int>(ARRAYSIZE_UNSAFE(schemes));
2027          recent_scheme++) {
2028       const TestCase *test_case = &test_cases[ci];
2029       scoped_refptr<CookieMonster> cm(
2030           CreateMonsterFromStoreForGC(
2031               test_case->num_cookies, test_case->num_old_cookies,
2032               CookieMonster::kSafeFromGlobalPurgeDays * 2));
2033       cm->SetExpiryAndKeyScheme(schemes[recent_scheme]);
2034       EXPECT_EQ(test_case->expected_initial_cookies,
2035                 static_cast<int>(cm->GetAllCookies().size()))
2036           << "For test case " << ci;
2037       // Will trigger GC
2038       cm->SetCookie(GURL("http://newdomain.com"), "b=2");
2039       EXPECT_EQ(test_case->expected_cookies_after_set[recent_scheme],
2040                 static_cast<int>((cm->GetAllCookies().size())))
2041           << "For test case (" << ci << ", " << recent_scheme << ")";
2042     }
2043   }
2044 }
2045 
2046 // This test checks that setting a cookie forcing it to be a session only
2047 // cookie works as expected.
TEST(CookieMonsterTest,ForceSessionOnly)2048 TEST(CookieMonsterTest, ForceSessionOnly) {
2049   GURL url_google(kUrlGoogle);
2050   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2051   CookieOptions options;
2052 
2053   // Set a persistent cookie, but force it to be a session cookie.
2054   options.set_force_session();
2055   ASSERT_TRUE(cm->SetCookieWithOptions(url_google,
2056       std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT",
2057       options));
2058 
2059   // Get the canonical cookie.
2060   CookieList cookie_list = cm->GetAllCookies();
2061   ASSERT_EQ(1U, cookie_list.size());
2062   ASSERT_FALSE(cookie_list[0].IsPersistent());
2063 
2064   // Use a past expiry date to delete the cookie, but force it to session only.
2065   ASSERT_TRUE(cm->SetCookieWithOptions(url_google,
2066       std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-1977 22:50:13 GMT",
2067       options));
2068 
2069   // Check that the cookie was deleted.
2070   cookie_list = cm->GetAllCookies();
2071   ASSERT_EQ(0U, cookie_list.size());
2072 }
2073 
2074 // This test checks that keep expired cookies flag is working.
TEST(CookieMonsterTest,KeepExpiredCookies)2075 TEST(CookieMonsterTest, KeepExpiredCookies) {
2076   GURL url_google(kUrlGoogle);
2077   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2078   cm->SetKeepExpiredCookies();
2079   CookieOptions options;
2080 
2081   // Set a persistent cookie.
2082   ASSERT_TRUE(cm->SetCookieWithOptions(url_google,
2083       std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-22 22:50:13 GMT",
2084       options));
2085 
2086   // Get the canonical cookie.
2087   CookieList cookie_list = cm->GetAllCookies();
2088   ASSERT_EQ(1U, cookie_list.size());
2089 
2090   // Use a past expiry date to delete the cookie.
2091   ASSERT_TRUE(cm->SetCookieWithOptions(url_google,
2092       std::string(kValidCookieLine) + "; expires=Mon, 18-Apr-1977 22:50:13 GMT",
2093       options));
2094 
2095   // Check that the cookie with the past expiry date is still there.
2096   // GetAllCookies() also triggers garbage collection.
2097   cookie_list = cm->GetAllCookies();
2098   ASSERT_EQ(1U, cookie_list.size());
2099   ASSERT_TRUE(cookie_list[0].IsExpired(Time::Now()));
2100 }
2101 
2102 namespace {
2103 
2104 // Mock PersistentCookieStore that keeps track of the number of Flush() calls.
2105 class FlushablePersistentStore : public CookieMonster::PersistentCookieStore {
2106  public:
FlushablePersistentStore()2107   FlushablePersistentStore() : flush_count_(0) {}
2108 
Load(std::vector<CookieMonster::CanonicalCookie * > *)2109   bool Load(std::vector<CookieMonster::CanonicalCookie*>*) {
2110     return false;
2111   }
2112 
AddCookie(const CookieMonster::CanonicalCookie &)2113   void AddCookie(const CookieMonster::CanonicalCookie&) {}
UpdateCookieAccessTime(const CookieMonster::CanonicalCookie &)2114   void UpdateCookieAccessTime(const CookieMonster::CanonicalCookie&) {}
DeleteCookie(const CookieMonster::CanonicalCookie &)2115   void DeleteCookie(const CookieMonster::CanonicalCookie&) {}
SetClearLocalStateOnExit(bool clear_local_state)2116   void SetClearLocalStateOnExit(bool clear_local_state) {}
2117 
Flush(Task * completion_callback)2118   void Flush(Task* completion_callback) {
2119     ++flush_count_;
2120     if (completion_callback) {
2121       completion_callback->Run();
2122       delete completion_callback;
2123     }
2124   }
2125 
flush_count()2126   int flush_count() {
2127     return flush_count_;
2128   }
2129 
2130  private:
2131   volatile int flush_count_;
2132 };
2133 
2134 // Counts the number of times Callback() has been run.
2135 class CallbackCounter : public base::RefCountedThreadSafe<CallbackCounter> {
2136  public:
CallbackCounter()2137   CallbackCounter() : callback_count_(0) {}
2138 
Callback()2139   void Callback() {
2140     ++callback_count_;
2141   }
2142 
callback_count()2143   int callback_count() {
2144     return callback_count_;
2145   }
2146 
2147  private:
2148   friend class base::RefCountedThreadSafe<CallbackCounter>;
2149   volatile int callback_count_;
2150 };
2151 
2152 }  // namespace
2153 
2154 // Test that FlushStore() is forwarded to the store and callbacks are posted.
TEST(CookieMonsterTest,FlushStore)2155 TEST(CookieMonsterTest, FlushStore) {
2156   scoped_refptr<CallbackCounter> counter(new CallbackCounter());
2157   scoped_refptr<FlushablePersistentStore> store(new FlushablePersistentStore());
2158   scoped_refptr<CookieMonster> cm(new CookieMonster(store, NULL));
2159 
2160   ASSERT_EQ(0, store->flush_count());
2161   ASSERT_EQ(0, counter->callback_count());
2162 
2163   // Before initialization, FlushStore() should just run the callback.
2164   cm->FlushStore(NewRunnableMethod(counter.get(), &CallbackCounter::Callback));
2165   MessageLoop::current()->RunAllPending();
2166 
2167   ASSERT_EQ(0, store->flush_count());
2168   ASSERT_EQ(1, counter->callback_count());
2169 
2170   // NULL callback is safe.
2171   cm->FlushStore(NULL);
2172   MessageLoop::current()->RunAllPending();
2173 
2174   ASSERT_EQ(0, store->flush_count());
2175   ASSERT_EQ(1, counter->callback_count());
2176 
2177   // After initialization, FlushStore() should delegate to the store.
2178   cm->GetAllCookies();  // Force init.
2179   cm->FlushStore(NewRunnableMethod(counter.get(), &CallbackCounter::Callback));
2180   MessageLoop::current()->RunAllPending();
2181 
2182   ASSERT_EQ(1, store->flush_count());
2183   ASSERT_EQ(2, counter->callback_count());
2184 
2185   // NULL callback is still safe.
2186   cm->FlushStore(NULL);
2187   MessageLoop::current()->RunAllPending();
2188 
2189   ASSERT_EQ(2, store->flush_count());
2190   ASSERT_EQ(2, counter->callback_count());
2191 
2192   // If there's no backing store, FlushStore() is always a safe no-op.
2193   cm = new CookieMonster(NULL, NULL);
2194   cm->GetAllCookies();  // Force init.
2195   cm->FlushStore(NULL);
2196   MessageLoop::current()->RunAllPending();
2197 
2198   ASSERT_EQ(2, counter->callback_count());
2199 
2200   cm->FlushStore(NewRunnableMethod(counter.get(), &CallbackCounter::Callback));
2201   MessageLoop::current()->RunAllPending();
2202 
2203   ASSERT_EQ(3, counter->callback_count());
2204 }
2205 
TEST(CookieMonsterTest,GetCookieSourceFromURL)2206 TEST(CookieMonsterTest, GetCookieSourceFromURL) {
2207   EXPECT_EQ("http://example.com/",
2208             CookieMonster::CanonicalCookie::GetCookieSourceFromURL(
2209                 GURL("http://example.com")));
2210   EXPECT_EQ("http://example.com/",
2211             CookieMonster::CanonicalCookie::GetCookieSourceFromURL(
2212                 GURL("http://example.com/")));
2213   EXPECT_EQ("http://example.com/",
2214             CookieMonster::CanonicalCookie::GetCookieSourceFromURL(
2215                 GURL("http://example.com/test")));
2216   EXPECT_EQ("file:///tmp/test.html",
2217             CookieMonster::CanonicalCookie::GetCookieSourceFromURL(
2218                 GURL("file:///tmp/test.html")));
2219   EXPECT_EQ("http://example.com/",
2220             CookieMonster::CanonicalCookie::GetCookieSourceFromURL(
2221                 GURL("http://example.com:1234/")));
2222   EXPECT_EQ("http://example.com/",
2223             CookieMonster::CanonicalCookie::GetCookieSourceFromURL(
2224                 GURL("https://example.com/")));
2225   EXPECT_EQ("http://example.com/",
2226             CookieMonster::CanonicalCookie::GetCookieSourceFromURL(
2227                 GURL("http://user:pwd@example.com/")));
2228   EXPECT_EQ("http://example.com/",
2229             CookieMonster::CanonicalCookie::GetCookieSourceFromURL(
2230                 GURL("http://example.com/test?foo")));
2231   EXPECT_EQ("http://example.com/",
2232             CookieMonster::CanonicalCookie::GetCookieSourceFromURL(
2233                 GURL("http://example.com/test#foo")));
2234 }
2235 
TEST(CookieMonsterTest,HistogramCheck)2236 TEST(CookieMonsterTest, HistogramCheck) {
2237   scoped_refptr<CookieMonster> cm(new CookieMonster(NULL, NULL));
2238   // Should match call in InitializeHistograms, but doesn't really matter
2239   // since the histogram should have been initialized by the CM construction
2240   // above.
2241   base::Histogram* expired_histogram =
2242       base::Histogram::FactoryGet(
2243           "Cookie.ExpirationDurationMinutes", 1, 10 * 365 * 24 * 60, 50,
2244           base::Histogram::kUmaTargetedHistogramFlag);
2245 
2246   base::Histogram::SampleSet histogram_set_1;
2247   expired_histogram->SnapshotSample(&histogram_set_1);
2248   ASSERT_TRUE(cm->SetCookieWithDetails(
2249       GURL("http://fake.a.url"), "a", "b", "a.url", "/",
2250       base::Time::Now() + base::TimeDelta::FromMinutes(59),
2251       false, false));
2252 
2253   base::Histogram::SampleSet histogram_set_2;
2254   expired_histogram->SnapshotSample(&histogram_set_2);
2255   EXPECT_EQ(histogram_set_1.TotalCount() + 1,
2256             histogram_set_2.TotalCount());
2257 
2258   // kValidCookieLine creates a session cookie.
2259   GURL url_google(kUrlGoogle);
2260   ASSERT_TRUE(cm->SetCookie(url_google, kValidCookieLine));
2261   expired_histogram->SnapshotSample(&histogram_set_1);
2262   EXPECT_EQ(histogram_set_2.TotalCount(),
2263             histogram_set_1.TotalCount());
2264 }
2265 
2266 }  // namespace
2267