summaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
authorjochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-24 16:06:01 +0000
committerjochen@chromium.org <jochen@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-03-24 16:06:01 +0000
commite5e9dd07968a2811196b262e739633e373837acc (patch)
treee21719077227acef1a165aea1406c08b036ae6be /net
parentc0591e5a622fd3e573ebf03e95d1ab2d7d3c265f (diff)
downloadchromium_src-e5e9dd07968a2811196b262e739633e373837acc.zip
chromium_src-e5e9dd07968a2811196b262e739633e373837acc.tar.gz
chromium_src-e5e9dd07968a2811196b262e739633e373837acc.tar.bz2
Add a delegate to CookieMonster and broadcast notifications about changes to cookies.
This change will allow implementing the experimental cookie extension API, specifically the cookies.onChanged event BUG=38398 TEST=net_unittests Review URL: http://codereview.chromium.org/1023004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@42473 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net')
-rw-r--r--net/base/cookie_monster.cc9
-rw-r--r--net/base/cookie_monster.h155
-rw-r--r--net/base/cookie_monster_perftest.cc4
-rw-r--r--net/base/cookie_monster_unittest.cc184
-rw-r--r--net/url_request/url_request_unittest.h2
5 files changed, 244 insertions, 110 deletions
diff --git a/net/base/cookie_monster.cc b/net/base/cookie_monster.cc
index cd5d7f2..0f8af5b 100644
--- a/net/base/cookie_monster.cc
+++ b/net/base/cookie_monster.cc
@@ -104,11 +104,12 @@ void CookieMonster::EnableFileScheme() {
enable_file_scheme_ = true;
}
-CookieMonster::CookieMonster(PersistentCookieStore* store)
+CookieMonster::CookieMonster(PersistentCookieStore* store, Delegate* delegate)
: initialized_(false),
store_(store),
last_access_threshold_(
- TimeDelta::FromSeconds(kDefaultAccessUpdateThresholdSeconds)) {
+ TimeDelta::FromSeconds(kDefaultAccessUpdateThresholdSeconds)),
+ delegate_(delegate) {
SetDefaultCookieableSchemes();
}
@@ -607,6 +608,8 @@ void CookieMonster::InternalInsertCookie(const std::string& key,
if (cc->IsPersistent() && store_ && sync_to_store)
store_->AddCookie(key, *cc);
cookies_.insert(CookieMap::value_type(key, cc));
+ if (delegate_.get())
+ delegate_->OnCookieChanged(key, *cc, false);
}
void CookieMonster::InternalUpdateCookieAccessTime(CanonicalCookie* cc) {
@@ -629,6 +632,8 @@ void CookieMonster::InternalDeleteCookie(CookieMap::iterator it,
COOKIE_DLOG(INFO) << "InternalDeleteCookie() cc: " << cc->DebugString();
if (cc->IsPersistent() && store_ && sync_to_store)
store_->DeleteCookie(*cc);
+ if (delegate_.get())
+ delegate_->OnCookieChanged(it->first, *cc, true);
cookies_.erase(it);
delete cc;
}
diff --git a/net/base/cookie_monster.h b/net/base/cookie_monster.h
index a48c2d3..d421d6f 100644
--- a/net/base/cookie_monster.h
+++ b/net/base/cookie_monster.h
@@ -14,6 +14,7 @@
#include "base/basictypes.h"
#include "base/lock.h"
+#include "base/ref_counted.h"
#include "base/time.h"
#include "net/base/cookie_store.h"
@@ -33,8 +34,9 @@ namespace net {
// - Verify that our domain enforcement and non-dotted handling is correct
class CookieMonster : public CookieStore {
public:
- class ParsedCookie;
class CanonicalCookie;
+ class Delegate;
+ class ParsedCookie;
class PersistentCookieStore;
// NOTE(deanm):
@@ -50,19 +52,23 @@ class CookieMonster : public CookieStore {
typedef std::pair<std::string, CanonicalCookie> CookieListPair;
typedef std::vector<CookieListPair> CookieList;
- // The store passed in should not have had Init() called on it yet. This class
- // will take care of initializing it. The backing store is NOT owned by this
- // class, but it must remain valid for the duration of the cookie monster's
- // existence. If |store| is NULL, then no backing store will be updated.
- explicit CookieMonster(PersistentCookieStore* store);
+ // The store passed in should not have had Init() called on it yet. This
+ // class will take care of initializing it. The backing store is NOT owned by
+ // this class, but it must remain valid for the duration of the cookie
+ // monster's existence. If |store| is NULL, then no backing store will be
+ // updated. If |delegate| is non-NULL, it will be notified on
+ // creation/deletion of cookies.
+ CookieMonster(PersistentCookieStore* store, Delegate* delegate);
#ifdef UNIT_TEST
CookieMonster(PersistentCookieStore* store,
+ Delegate* delegate,
int last_access_threshold_milliseconds)
: initialized_(false),
store_(store),
last_access_threshold_(base::TimeDelta::FromMilliseconds(
- last_access_threshold_milliseconds)) {
+ last_access_threshold_milliseconds)),
+ delegate_(delegate) {
SetDefaultCookieableSchemes();
}
#endif
@@ -248,72 +254,14 @@ class CookieMonster : public CookieStore {
std::vector<std::string> cookieable_schemes_;
+ scoped_refptr<Delegate> delegate_;
+
// Lock for thread-safety
Lock lock_;
DISALLOW_COPY_AND_ASSIGN(CookieMonster);
};
-class CookieMonster::ParsedCookie {
- public:
- typedef std::pair<std::string, std::string> TokenValuePair;
- typedef std::vector<TokenValuePair> PairList;
-
- // The maximum length of a cookie string we will try to parse
- static const size_t kMaxCookieSize = 4096;
- // The maximum number of Token/Value pairs. Shouldn't have more than 8.
- static const int kMaxPairs = 16;
-
- // Construct from a cookie string like "BLAH=1; path=/; domain=.google.com"
- ParsedCookie(const std::string& cookie_line);
- ~ParsedCookie() { }
-
- // You should not call any other methods on the class if !IsValid
- bool IsValid() const { return is_valid_; }
-
- const std::string& Name() const { return pairs_[0].first; }
- const std::string& Token() const { return Name(); }
- const std::string& Value() const { return pairs_[0].second; }
-
- bool HasPath() const { return path_index_ != 0; }
- const std::string& Path() const { return pairs_[path_index_].second; }
- bool HasDomain() const { return domain_index_ != 0; }
- const std::string& Domain() const { return pairs_[domain_index_].second; }
- bool HasExpires() const { return expires_index_ != 0; }
- const std::string& Expires() const { return pairs_[expires_index_].second; }
- bool HasMaxAge() const { return maxage_index_ != 0; }
- const std::string& MaxAge() const { return pairs_[maxage_index_].second; }
- bool IsSecure() const { return secure_index_ != 0; }
- bool IsHttpOnly() const { return httponly_index_ != 0; }
-
- // Return the number of attributes, for example, returning 2 for:
- // "BLAH=hah; path=/; domain=.google.com"
- size_t NumberOfAttributes() const { return pairs_.size() - 1; }
-
- // For debugging only!
- std::string DebugString() const;
-
- private:
- void ParseTokenValuePairs(const std::string& cookie_line);
- void SetupAttributes();
-
- PairList pairs_;
- bool is_valid_;
- // These will default to 0, but that should never be valid since the
- // 0th index is the user supplied token/value, not an attribute.
- // We're really never going to have more than like 8 attributes, so we
- // could fit these into 3 bits each if we're worried about size...
- size_t path_index_;
- size_t domain_index_;
- size_t expires_index_;
- size_t maxage_index_;
- size_t secure_index_;
- size_t httponly_index_;
-
- DISALLOW_COPY_AND_ASSIGN(ParsedCookie);
-};
-
-
class CookieMonster::CanonicalCookie {
public:
CanonicalCookie() { }
@@ -383,6 +331,79 @@ class CookieMonster::CanonicalCookie {
bool httponly_;
};
+class CookieMonster::Delegate
+ : public base::RefCountedThreadSafe<CookieMonster::Delegate> {
+ public:
+ // Will be called when a cookie is added or removed. The function is passed
+ // the respective |cookie| which was added to or removed from the cookies for
+ // |domain_key|. If |removed| is true, the cookie was deleted.
+ virtual void OnCookieChanged(const std::string& domain_key,
+ const CookieMonster::CanonicalCookie& cookie,
+ bool removed) = 0;
+ protected:
+ friend class base::RefCountedThreadSafe<CookieMonster::Delegate>;
+ virtual ~Delegate() {}
+};
+
+class CookieMonster::ParsedCookie {
+ public:
+ typedef std::pair<std::string, std::string> TokenValuePair;
+ typedef std::vector<TokenValuePair> PairList;
+
+ // The maximum length of a cookie string we will try to parse
+ static const size_t kMaxCookieSize = 4096;
+ // The maximum number of Token/Value pairs. Shouldn't have more than 8.
+ static const int kMaxPairs = 16;
+
+ // Construct from a cookie string like "BLAH=1; path=/; domain=.google.com"
+ ParsedCookie(const std::string& cookie_line);
+ ~ParsedCookie() { }
+
+ // You should not call any other methods on the class if !IsValid
+ bool IsValid() const { return is_valid_; }
+
+ const std::string& Name() const { return pairs_[0].first; }
+ const std::string& Token() const { return Name(); }
+ const std::string& Value() const { return pairs_[0].second; }
+
+ bool HasPath() const { return path_index_ != 0; }
+ const std::string& Path() const { return pairs_[path_index_].second; }
+ bool HasDomain() const { return domain_index_ != 0; }
+ const std::string& Domain() const { return pairs_[domain_index_].second; }
+ bool HasExpires() const { return expires_index_ != 0; }
+ const std::string& Expires() const { return pairs_[expires_index_].second; }
+ bool HasMaxAge() const { return maxage_index_ != 0; }
+ const std::string& MaxAge() const { return pairs_[maxage_index_].second; }
+ bool IsSecure() const { return secure_index_ != 0; }
+ bool IsHttpOnly() const { return httponly_index_ != 0; }
+
+ // Return the number of attributes, for example, returning 2 for:
+ // "BLAH=hah; path=/; domain=.google.com"
+ size_t NumberOfAttributes() const { return pairs_.size() - 1; }
+
+ // For debugging only!
+ std::string DebugString() const;
+
+ private:
+ void ParseTokenValuePairs(const std::string& cookie_line);
+ void SetupAttributes();
+
+ PairList pairs_;
+ bool is_valid_;
+ // These will default to 0, but that should never be valid since the
+ // 0th index is the user supplied token/value, not an attribute.
+ // We're really never going to have more than like 8 attributes, so we
+ // could fit these into 3 bits each if we're worried about size...
+ size_t path_index_;
+ size_t domain_index_;
+ size_t expires_index_;
+ size_t maxage_index_;
+ size_t secure_index_;
+ size_t httponly_index_;
+
+ DISALLOW_COPY_AND_ASSIGN(ParsedCookie);
+};
+
typedef base::RefCountedThreadSafe<CookieMonster::PersistentCookieStore>
RefcountedPersistentCookieStore;
diff --git a/net/base/cookie_monster_perftest.cc b/net/base/cookie_monster_perftest.cc
index 61d9f68..3445b43 100644
--- a/net/base/cookie_monster_perftest.cc
+++ b/net/base/cookie_monster_perftest.cc
@@ -40,7 +40,7 @@ TEST(ParsedCookieTest, TestParseBigCookies) {
static const GURL kUrlGoogle("http://www.google.izzle");
TEST(CookieMonsterTest, TestAddCookiesOnSingleHost) {
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
std::vector<std::string> cookies;
for (int i = 0; i < kNumCookies; i++) {
cookies.push_back(StringPrintf("a%03d=b", i));
@@ -67,7 +67,7 @@ TEST(CookieMonsterTest, TestAddCookiesOnSingleHost) {
}
TEST(CookieMonsterTest, TestAddCookieOnManyHosts) {
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
std::string cookie(kCookieLine);
std::vector<GURL> gurls; // just wanna have ffffuunnn
for (int i = 0; i < kNumCookies; ++i) {
diff --git a/net/base/cookie_monster_unittest.cc b/net/base/cookie_monster_unittest.cc
index 4c7dd4b..c2a5cae 100644
--- a/net/base/cookie_monster_unittest.cc
+++ b/net/base/cookie_monster_unittest.cc
@@ -100,6 +100,36 @@ class MockPersistentCookieStore
DISALLOW_COPY_AND_ASSIGN(MockPersistentCookieStore);
};
+// Mock for CookieMonster::Delegate
+class MockCookieMonsterDelegate : public net::CookieMonster::Delegate {
+ public:
+ typedef std::pair<net::CookieMonster::CookieListPair, bool>
+ CookieNotification;
+
+ MockCookieMonsterDelegate() {}
+
+ virtual void OnCookieChanged(
+ const std::string& domain_key,
+ const net::CookieMonster::CanonicalCookie& cookie,
+ bool removed) {
+ CookieNotification notification(
+ net::CookieMonster::CookieListPair(domain_key, cookie),
+ removed);
+ changes_.push_back(notification);
+ }
+
+ const std::vector<CookieNotification>& changes() const { return changes_; }
+
+ void reset() { changes_.clear(); }
+
+ private:
+ virtual ~MockCookieMonsterDelegate() {}
+
+ std::vector<CookieNotification> changes_;
+
+ DISALLOW_COPY_AND_ASSIGN(MockCookieMonsterDelegate);
+};
+
// Helper to build a list of KeyedCanonicalCookies.
void AddKeyedCookieToList(
const std::string& key,
@@ -360,7 +390,7 @@ TEST(CookieMonsterTest, DomainTest) {
scoped_refptr<MockPersistentCookieStore> store(
new MockPersistentCookieStore);
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store, NULL));
EXPECT_TRUE(cm->SetCookie(url_google, "A=B"));
EXPECT_EQ("A=B", cm->GetCookies(url_google));
EXPECT_TRUE(cm->SetCookie(url_google, "C=D; domain=.google.izzle"));
@@ -396,7 +426,7 @@ TEST(CookieMonsterTest, DomainTest) {
TEST(CookieMonsterTest, DomainWithTrailingDotTest) {
scoped_refptr<MockPersistentCookieStore> store(
new MockPersistentCookieStore);
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store, NULL));
GURL url_google("http://www.google.com");
EXPECT_FALSE(cm->SetCookie(url_google, "a=1; domain=.www.google.com."));
@@ -412,7 +442,7 @@ TEST(CookieMonsterTest, DomainWithTrailingDotTest) {
TEST(CookieMonsterTest, ValidSubdomainTest) {
scoped_refptr<MockPersistentCookieStore> store(
new MockPersistentCookieStore);
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store, NULL));
GURL url_abcd("http://a.b.c.d.com");
GURL url_bcd("http://b.c.d.com");
GURL url_cd("http://c.d.com");
@@ -447,7 +477,7 @@ TEST(CookieMonsterTest, InvalidDomainTest) {
scoped_refptr<MockPersistentCookieStore> store(
new MockPersistentCookieStore);
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store, NULL));
GURL url_foobar("http://foo.bar.com");
// More specific sub-domain than allowed.
@@ -487,7 +517,7 @@ TEST(CookieMonsterTest, InvalidDomainTest) {
// Make sure the cookie code hasn't gotten its subdomain string handling
// reversed, missed a suffix check, etc. It's important here that the two
// hosts below have the same domain + registry.
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
GURL url_foocom("http://foo.com.com");
EXPECT_FALSE(cm->SetCookie(url_foocom, "a=1; domain=.foo.com.com.com"));
EXPECT_EQ("", cm->GetCookies(url_foocom));
@@ -499,7 +529,7 @@ TEST(CookieMonsterTest, InvalidDomainTest) {
// http://b/issue?id=889898
TEST(CookieMonsterTest, DomainWithoutLeadingDotTest) {
{ // The omission of dot results in setting a domain cookie.
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
GURL url_hosted("http://manage.hosted.filefront.com");
GURL url_filefront("http://www.filefront.com");
EXPECT_TRUE(cm->SetCookie(url_hosted, "sawAd=1; domain=filefront.com"));
@@ -508,7 +538,7 @@ TEST(CookieMonsterTest, DomainWithoutLeadingDotTest) {
}
{ // Even when the domains match exactly, don't consider it host cookie.
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
GURL url("http://www.google.com");
EXPECT_TRUE(cm->SetCookie(url, "a=1; domain=www.google.com"));
EXPECT_EQ("a=1", cm->GetCookies(url));
@@ -520,7 +550,7 @@ TEST(CookieMonsterTest, DomainWithoutLeadingDotTest) {
// Test that the domain specified in cookie string is treated case-insensitive
// http://b/issue?id=896475.
TEST(CookieMonsterTest, CaseInsensitiveDomainTest) {
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
GURL url_google("http://www.google.com");
EXPECT_TRUE(cm->SetCookie(url_google, "a=1; domain=.GOOGLE.COM"));
EXPECT_TRUE(cm->SetCookie(url_google, "b=2; domain=.wWw.gOOgLE.coM"));
@@ -530,13 +560,13 @@ TEST(CookieMonsterTest, CaseInsensitiveDomainTest) {
TEST(CookieMonsterTest, TestIpAddress) {
GURL url_ip("http://1.2.3.4/weee");
{
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
EXPECT_TRUE(cm->SetCookie(url_ip, kValidCookieLine));
EXPECT_EQ("A=B", cm->GetCookies(url_ip));
}
{ // IP addresses should not be able to set domain cookies.
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
EXPECT_FALSE(cm->SetCookie(url_ip, "b=2; domain=.1.2.3.4"));
EXPECT_FALSE(cm->SetCookie(url_ip, "c=3; domain=.3.4"));
EXPECT_EQ("", cm->GetCookies(url_ip));
@@ -552,7 +582,7 @@ TEST(CookieMonsterTest, TestIpAddress) {
// Test host cookies, and setting of cookies on TLD.
TEST(CookieMonsterTest, TestNonDottedAndTLD) {
{
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
GURL url("http://com/");
// Allow setting on "com", (but only as a host cookie).
EXPECT_TRUE(cm->SetCookie(url, "a=1"));
@@ -566,7 +596,7 @@ TEST(CookieMonsterTest, TestNonDottedAndTLD) {
}
{ // http://com. should be treated the same as http://com.
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
GURL url("http://com./index.html");
EXPECT_TRUE(cm->SetCookie(url, "a=1"));
EXPECT_EQ("a=1", cm->GetCookies(url));
@@ -574,7 +604,7 @@ TEST(CookieMonsterTest, TestNonDottedAndTLD) {
}
{ // Should not be able to set host cookie from a subdomain.
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
GURL url("http://a.b");
EXPECT_FALSE(cm->SetCookie(url, "a=1; domain=.b"));
EXPECT_FALSE(cm->SetCookie(url, "b=2; domain=b"));
@@ -582,7 +612,7 @@ TEST(CookieMonsterTest, TestNonDottedAndTLD) {
}
{ // Same test as above, but explicitly on a known TLD (com).
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
GURL url("http://google.com");
EXPECT_FALSE(cm->SetCookie(url, "a=1; domain=.com"));
EXPECT_FALSE(cm->SetCookie(url, "b=2; domain=com"));
@@ -590,7 +620,7 @@ TEST(CookieMonsterTest, TestNonDottedAndTLD) {
}
{ // Make sure can't set cookie on TLD which is dotted.
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
GURL url("http://google.co.uk");
EXPECT_FALSE(cm->SetCookie(url, "a=1; domain=.co.uk"));
EXPECT_FALSE(cm->SetCookie(url, "b=2; domain=.uk"));
@@ -600,7 +630,7 @@ TEST(CookieMonsterTest, TestNonDottedAndTLD) {
}
{ // Intranet URLs should only be able to set host cookies.
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
GURL url("http://b");
EXPECT_TRUE(cm->SetCookie(url, "a=1"));
EXPECT_FALSE(cm->SetCookie(url, "b=2; domain=.b"));
@@ -612,7 +642,7 @@ TEST(CookieMonsterTest, TestNonDottedAndTLD) {
// Test reading/writing cookies when the domain ends with a period,
// as in "www.google.com."
TEST(CookieMonsterTest, TestHostEndsWithDot) {
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
GURL url("http://www.google.com");
GURL url_with_dot("http://www.google.com.");
EXPECT_TRUE(cm->SetCookie(url, "a=1"));
@@ -632,19 +662,19 @@ TEST(CookieMonsterTest, TestHostEndsWithDot) {
}
TEST(CookieMonsterTest, InvalidScheme) {
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
EXPECT_FALSE(cm->SetCookie(GURL(kUrlFtp), kValidCookieLine));
}
TEST(CookieMonsterTest, InvalidScheme_Read) {
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
EXPECT_TRUE(cm->SetCookie(GURL(kUrlGoogle), kValidDomainCookieLine));
EXPECT_EQ("", cm->GetCookies(GURL(kUrlFtp)));
}
TEST(CookieMonsterTest, PathTest) {
std::string url("http://www.google.izzle");
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
EXPECT_TRUE(cm->SetCookie(GURL(url), "A=B; path=/wee"));
EXPECT_EQ("A=B", cm->GetCookies(GURL(url + "/wee")));
EXPECT_EQ("A=B", cm->GetCookies(GURL(url + "/wee/")));
@@ -661,7 +691,7 @@ TEST(CookieMonsterTest, PathTest) {
TEST(CookieMonsterTest, HttpOnlyTest) {
GURL url_google(kUrlGoogle);
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
net::CookieOptions options;
options.set_include_httponly();
@@ -785,7 +815,7 @@ TEST(CookieMonsterTest, TestCookieDeletion) {
GURL url_google(kUrlGoogle);
scoped_refptr<MockPersistentCookieStore> store(
new MockPersistentCookieStore);
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store, NULL));
// Create a session cookie.
EXPECT_TRUE(cm->SetCookie(url_google, kValidCookieLine));
@@ -854,7 +884,7 @@ TEST(CookieMonsterTest, TestCookieDeleteAll) {
GURL url_google(kUrlGoogle);
scoped_refptr<MockPersistentCookieStore> store(
new MockPersistentCookieStore);
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store, NULL));
net::CookieOptions options;
options.set_include_httponly();
@@ -885,7 +915,7 @@ TEST(CookieMonsterTest, TestCookieDeleteAll) {
TEST(CookieMonsterTest, TestCookieDeleteAllCreatedAfterTimestamp) {
GURL url_google(kUrlGoogle);
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
Time now = Time::Now();
// Nothing has been added so nothing should be deleted.
@@ -913,7 +943,7 @@ TEST(CookieMonsterTest, TestCookieDeleteAllCreatedAfterTimestamp) {
TEST(CookieMonsterTest, TestCookieDeleteAllCreatedBetweenTimestamps) {
GURL url_google(kUrlGoogle);
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
Time now = Time::Now();
// Nothing has been added so nothing should be deleted.
@@ -956,7 +986,7 @@ TEST(CookieMonsterTest, TestCookieDeleteAllCreatedBetweenTimestamps) {
TEST(CookieMonsterTest, TestSecure) {
GURL url_google(kUrlGoogle);
GURL url_google_secure(kUrlGoogleSecure);
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
EXPECT_TRUE(cm->SetCookie(url_google, "A=B"));
EXPECT_EQ("A=B", cm->GetCookies(url_google));
@@ -987,7 +1017,7 @@ static const int kLastAccessThresholdMilliseconds = 200;
TEST(CookieMonsterTest, TestLastAccess) {
GURL url_google(kUrlGoogle);
scoped_refptr<net::CookieMonster> cm(
- new net::CookieMonster(NULL, kLastAccessThresholdMilliseconds));
+ new net::CookieMonster(NULL, NULL, kLastAccessThresholdMilliseconds));
EXPECT_TRUE(cm->SetCookie(url_google, "A=B"));
const Time last_access_date(GetFirstCookieAccessDate(cm));
@@ -1015,7 +1045,7 @@ static int CountInString(const std::string& str, char c) {
TEST(CookieMonsterTest, TestHostGarbageCollection) {
GURL url_google(kUrlGoogle);
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
// Add a bunch of cookies on a single host, should purge them.
for (int i = 0; i < 101; i++) {
std::string cookie = StringPrintf("a%03d=b", i);
@@ -1030,7 +1060,7 @@ TEST(CookieMonsterTest, TestHostGarbageCollection) {
TEST(CookieMonsterTest, TestTotalGarbageCollection) {
scoped_refptr<net::CookieMonster> cm(
- new net::CookieMonster(NULL, kLastAccessThresholdMilliseconds));
+ new net::CookieMonster(NULL, NULL, kLastAccessThresholdMilliseconds));
// Add a bunch of cookies on a bunch of host, some should get purged.
const GURL sticky_cookie("http://a0000.izzle");
@@ -1065,7 +1095,7 @@ TEST(CookieMonsterTest, TestTotalGarbageCollection) {
TEST(CookieMonsterTest, NetUtilCookieTest) {
const GURL test_url("http://mojo.jojo.google.izzle/");
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
EXPECT_TRUE(cm->SetCookie(test_url, "foo=bar"));
std::string value = cm->GetCookies(test_url);
@@ -1095,7 +1125,7 @@ static bool FindAndDeleteCookie(net::CookieMonster* cm,
TEST(CookieMonsterTest, TestDeleteSingleCookie) {
GURL url_google(kUrlGoogle);
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
EXPECT_TRUE(cm->SetCookie(url_google, "A=B"));
EXPECT_TRUE(cm->SetCookie(url_google, "C=D"));
@@ -1110,8 +1140,8 @@ TEST(CookieMonsterTest, TestDeleteSingleCookie) {
}
TEST(CookieMonsterTest, SetCookieableSchemes) {
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
- scoped_refptr<net::CookieMonster> cm_foo(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
+ scoped_refptr<net::CookieMonster> cm_foo(new net::CookieMonster(NULL, NULL));
// Only cm_foo should allow foo:// cookies.
const char* kSchemes[] = {"foo"};
@@ -1132,7 +1162,7 @@ TEST(CookieMonsterTest, GetAllCookiesForURL) {
GURL url_google_secure(kUrlGoogleSecure);
scoped_refptr<net::CookieMonster> cm(
- new net::CookieMonster(NULL, kLastAccessThresholdMilliseconds));
+ new net::CookieMonster(NULL, NULL, kLastAccessThresholdMilliseconds));
// Create an httponly cookie.
net::CookieOptions options;
@@ -1192,7 +1222,7 @@ TEST(CookieMonsterTest, GetAllCookiesForURLPathMatching) {
GURL url_google_foo("http://www.google.izzle/foo");
GURL url_google_bar("http://www.google.izzle/bar");
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
net::CookieOptions options;
EXPECT_TRUE(cm->SetCookieWithOptions(url_google_foo,
@@ -1235,7 +1265,7 @@ TEST(CookieMonsterTest, GetAllCookiesForURLPathMatching) {
}
TEST(CookieMonsterTest, DeleteCookieByName) {
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(NULL, NULL));
GURL url_google(kUrlGoogle);
EXPECT_TRUE(cm->SetCookie(url_google, "A=A1; path=/"));
@@ -1264,7 +1294,7 @@ TEST(CookieMonsterTest, OverwritePersistentCookie) {
GURL url_chromium("http://chromium.org");
scoped_refptr<MockPersistentCookieStore> store(
new MockPersistentCookieStore);
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store, NULL));
// Insert a cookie "a" for path "/path1"
EXPECT_TRUE(
@@ -1386,7 +1416,7 @@ TEST(CookieMonsterTest, DontImportDuplicateCookies) {
// Inject our initial cookies into the mock PersistentCookieStore.
store->SetLoadExpectation(true, initial_cookies);
- scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store));
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store, NULL));
// Verify that duplicates were not imported for path "/".
// (If this had failed, GetCookies() would have also returned X=1, X=2, X=4).
@@ -1404,3 +1434,81 @@ TEST(CookieMonsterTest, DontImportDuplicateCookies) {
EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[2].type);
EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[3].type);
}
+
+TEST(CookieMonsterTest, Delegate) {
+ GURL url_google(kUrlGoogle);
+
+ scoped_refptr<MockPersistentCookieStore> store(
+ new MockPersistentCookieStore);
+ scoped_refptr<MockCookieMonsterDelegate> delegate(
+ new MockCookieMonsterDelegate);
+ scoped_refptr<net::CookieMonster> cm(new net::CookieMonster(store, delegate));
+
+ EXPECT_TRUE(cm->SetCookie(url_google, "A=B"));
+ EXPECT_TRUE(cm->SetCookie(url_google, "C=D"));
+ EXPECT_TRUE(cm->SetCookie(url_google, "E=F"));
+ EXPECT_EQ("A=B; C=D; E=F", cm->GetCookies(url_google));
+ ASSERT_EQ(3u, delegate->changes().size());
+ EXPECT_EQ(false, delegate->changes()[0].second);
+ EXPECT_EQ(url_google.host(), delegate->changes()[0].first.first);
+ EXPECT_EQ("A", delegate->changes()[0].first.second.Name());
+ EXPECT_EQ("B", delegate->changes()[0].first.second.Value());
+ EXPECT_EQ(url_google.host(), delegate->changes()[1].first.first);
+ EXPECT_EQ(false, delegate->changes()[1].second);
+ EXPECT_EQ("C", delegate->changes()[1].first.second.Name());
+ EXPECT_EQ("D", delegate->changes()[1].first.second.Value());
+ EXPECT_EQ(url_google.host(), delegate->changes()[2].first.first);
+ EXPECT_EQ(false, delegate->changes()[2].second);
+ EXPECT_EQ("E", delegate->changes()[2].first.second.Name());
+ EXPECT_EQ("F", delegate->changes()[2].first.second.Value());
+ delegate->reset();
+
+ EXPECT_TRUE(FindAndDeleteCookie(cm, url_google.host(), "C"));
+ EXPECT_EQ("A=B; E=F", cm->GetCookies(url_google));
+ ASSERT_EQ(1u, delegate->changes().size());
+ EXPECT_EQ(url_google.host(), delegate->changes()[0].first.first);
+ EXPECT_EQ(true, delegate->changes()[0].second);
+ EXPECT_EQ("C", delegate->changes()[0].first.second.Name());
+ EXPECT_EQ("D", delegate->changes()[0].first.second.Value());
+ delegate->reset();
+
+ EXPECT_FALSE(FindAndDeleteCookie(cm, "random.host", "E"));
+ EXPECT_EQ("A=B; E=F", cm->GetCookies(url_google));
+ EXPECT_EQ(0u, delegate->changes().size());
+
+ // Insert a cookie "a" for path "/path1"
+ EXPECT_TRUE(
+ cm->SetCookie(url_google, "a=val1; path=/path1; "
+ "expires=Mon, 18-Apr-22 22:50:13 GMT"));
+ ASSERT_EQ(1u, store->commands().size());
+ EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[0].type);
+ ASSERT_EQ(1u, delegate->changes().size());
+ EXPECT_EQ(false, delegate->changes()[0].second);
+ EXPECT_EQ(url_google.host(), delegate->changes()[0].first.first);
+ EXPECT_EQ("a", delegate->changes()[0].first.second.Name());
+ EXPECT_EQ("val1", delegate->changes()[0].first.second.Value());
+ delegate->reset();
+
+ // Insert a cookie "a" for path "/path1", that is httponly. This should
+ // overwrite the non-http-only version.
+ net::CookieOptions allow_httponly;
+ allow_httponly.set_include_httponly();
+ EXPECT_TRUE(
+ cm->SetCookieWithOptions(url_google,
+ "a=val2; path=/path1; httponly; "
+ "expires=Mon, 18-Apr-22 22:50:14 GMT",
+ allow_httponly));
+ ASSERT_EQ(3u, store->commands().size());
+ EXPECT_EQ(CookieStoreCommand::REMOVE, store->commands()[1].type);
+ EXPECT_EQ(CookieStoreCommand::ADD, store->commands()[2].type);
+ ASSERT_EQ(2u, delegate->changes().size());
+ EXPECT_EQ(url_google.host(), delegate->changes()[0].first.first);
+ EXPECT_EQ(true, delegate->changes()[0].second);
+ EXPECT_EQ("a", delegate->changes()[0].first.second.Name());
+ EXPECT_EQ("val1", delegate->changes()[0].first.second.Value());
+ EXPECT_EQ(url_google.host(), delegate->changes()[1].first.first);
+ EXPECT_EQ(false, delegate->changes()[1].second);
+ EXPECT_EQ("a", delegate->changes()[1].first.second.Name());
+ EXPECT_EQ("val2", delegate->changes()[1].first.second.Value());
+ delegate->reset();
+}
diff --git a/net/url_request/url_request_unittest.h b/net/url_request/url_request_unittest.h
index 9e3d2bf..8b496f8b 100644
--- a/net/url_request/url_request_unittest.h
+++ b/net/url_request/url_request_unittest.h
@@ -168,7 +168,7 @@ class TestURLRequestContext : public URLRequestContext {
http_auth_handler_factory_),
disk_cache::CreateInMemoryCacheBackend(0));
// In-memory cookie store.
- cookie_store_ = new net::CookieMonster(NULL);
+ cookie_store_ = new net::CookieMonster(NULL, NULL);
accept_language_ = "en-us,fr";
accept_charset_ = "iso-8859-1,*,utf-8";
}