1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/browsing_data/browsing_data_cookie_helper.h"
10 #include "base/location.h"
11 #include "base/logging.h"
12 #include "base/memory/scoped_ptr.h"
13 #include "base/stl_util.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
17 #include "net/cookies/canonical_cookie.h"
18 #include "net/cookies/cookie_util.h"
19 #include "net/cookies/parsed_cookie.h"
20 #include "net/url_request/url_request_context.h"
21 #include "net/url_request/url_request_context_getter.h"
24 using content::BrowserThread
;
28 const char kGlobalCookieSetURL
[] = "chrome://cookieset";
30 void OnFetchComplete(const BrowsingDataCookieHelper::FetchCallback
& callback
,
31 const net::CookieList
& cookies
) {
32 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
33 DCHECK(!callback
.is_null());
34 BrowserThread::PostTask(BrowserThread::UI
, FROM_HERE
,
35 base::Bind(callback
, cookies
));
40 BrowsingDataCookieHelper::BrowsingDataCookieHelper(
41 net::URLRequestContextGetter
* request_context_getter
)
42 : request_context_getter_(request_context_getter
) {
43 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
46 BrowsingDataCookieHelper::~BrowsingDataCookieHelper() {
49 void BrowsingDataCookieHelper::StartFetching(const FetchCallback
& callback
) {
50 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
51 DCHECK(!callback
.is_null());
52 BrowserThread::PostTask(
53 BrowserThread::IO
, FROM_HERE
,
54 base::Bind(&BrowsingDataCookieHelper::FetchCookiesOnIOThread
, this,
58 void BrowsingDataCookieHelper::DeleteCookie(
59 const net::CanonicalCookie
& cookie
) {
60 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
61 BrowserThread::PostTask(
62 BrowserThread::IO
, FROM_HERE
,
63 base::Bind(&BrowsingDataCookieHelper::DeleteCookieOnIOThread
,
67 void BrowsingDataCookieHelper::FetchCookiesOnIOThread(
68 const FetchCallback
& callback
) {
69 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
70 DCHECK(!callback
.is_null());
71 scoped_refptr
<net::CookieMonster
> cookie_monster
=
72 request_context_getter_
->GetURLRequestContext()->
73 cookie_store()->GetCookieMonster();
74 if (cookie_monster
.get()) {
75 cookie_monster
->GetAllCookiesAsync(base::Bind(&OnFetchComplete
, callback
));
77 OnFetchComplete(callback
, net::CookieList());
81 void BrowsingDataCookieHelper::DeleteCookieOnIOThread(
82 const net::CanonicalCookie
& cookie
) {
83 DCHECK_CURRENTLY_ON(BrowserThread::IO
);
84 scoped_refptr
<net::CookieMonster
> cookie_monster
=
85 request_context_getter_
->GetURLRequestContext()->
86 cookie_store()->GetCookieMonster();
87 if (cookie_monster
.get()) {
88 cookie_monster
->DeleteCanonicalCookieAsync(
89 cookie
, net::CookieMonster::DeleteCookieCallback());
93 CannedBrowsingDataCookieHelper::CannedBrowsingDataCookieHelper(
94 net::URLRequestContextGetter
* request_context_getter
)
95 : BrowsingDataCookieHelper(request_context_getter
) {
98 CannedBrowsingDataCookieHelper::~CannedBrowsingDataCookieHelper() {
102 void CannedBrowsingDataCookieHelper::AddReadCookies(
103 const GURL
& frame_url
,
105 const net::CookieList
& cookie_list
) {
106 for (const auto& add_cookie
: cookie_list
)
107 AddCookie(frame_url
, add_cookie
);
110 void CannedBrowsingDataCookieHelper::AddChangedCookie(
111 const GURL
& frame_url
,
113 const std::string
& cookie_line
,
114 const net::CookieOptions
& options
) {
115 scoped_ptr
<net::CanonicalCookie
> cookie(net::CanonicalCookie::Create(
116 url
, cookie_line
, base::Time::Now(), options
));
118 AddCookie(frame_url
, *cookie
);
121 void CannedBrowsingDataCookieHelper::Reset() {
122 STLDeleteContainerPairSecondPointers(origin_cookie_set_map_
.begin(),
123 origin_cookie_set_map_
.end());
124 origin_cookie_set_map_
.clear();
127 bool CannedBrowsingDataCookieHelper::empty() const {
128 for (const auto& pair
: origin_cookie_set_map_
) {
129 if (!pair
.second
->empty())
136 size_t CannedBrowsingDataCookieHelper::GetCookieCount() const {
138 for (const auto& pair
: origin_cookie_set_map_
)
139 count
+= pair
.second
->size();
144 void CannedBrowsingDataCookieHelper::StartFetching(
145 const net::CookieMonster::GetCookieListCallback
& callback
) {
146 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
147 net::CookieList cookie_list
;
148 for (const auto& pair
: origin_cookie_set_map_
) {
149 cookie_list
.insert(cookie_list
.begin(), pair
.second
->begin(),
152 callback
.Run(cookie_list
);
155 void CannedBrowsingDataCookieHelper::DeleteCookie(
156 const net::CanonicalCookie
& cookie
) {
157 for (const auto& pair
: origin_cookie_set_map_
)
158 DeleteMatchingCookie(cookie
, pair
.second
);
159 BrowsingDataCookieHelper::DeleteCookie(cookie
);
162 bool CannedBrowsingDataCookieHelper::DeleteMatchingCookie(
163 const net::CanonicalCookie
& add_cookie
,
164 canonical_cookie::CookieHashSet
* cookie_set
) {
165 return cookie_set
->erase(add_cookie
) > 0;
168 canonical_cookie::CookieHashSet
* CannedBrowsingDataCookieHelper::GetCookiesFor(
169 const GURL
& first_party_origin
) {
170 OriginCookieSetMap::iterator it
=
171 origin_cookie_set_map_
.find(first_party_origin
);
172 if (it
== origin_cookie_set_map_
.end()) {
173 canonical_cookie::CookieHashSet
* cookies
=
174 new canonical_cookie::CookieHashSet
;
175 origin_cookie_set_map_
.insert(
176 std::pair
<GURL
, canonical_cookie::CookieHashSet
*>(first_party_origin
,
183 void CannedBrowsingDataCookieHelper::AddCookie(
184 const GURL
& frame_url
,
185 const net::CanonicalCookie
& cookie
) {
186 // Storing cookies in separate cookie sets per frame origin makes the
187 // GetCookieCount method count a cookie multiple times if it is stored in
189 // E.g. let "example.com" be redirected to "www.example.com". A cookie set
190 // with the cookie string "A=B; Domain=.example.com" would be sent to both
191 // hosts. This means it would be stored in the separate cookie sets for both
192 // hosts ("example.com", "www.example.com"). The method GetCookieCount would
193 // count this cookie twice. To prevent this, we us a single global cookie
194 // set as a work-around to store all added cookies. Per frame URL cookie
195 // sets are currently not used. In the future they will be used for
196 // collecting cookies per origin in redirect chains.
197 // TODO(markusheintz): A) Change the GetCookiesCount method to prevent
198 // counting cookies multiple times if they are stored in multiple cookie
199 // sets. B) Replace the GetCookieFor method call below with:
200 // "GetCookiesFor(frame_url.GetOrigin());"
201 CR_DEFINE_STATIC_LOCAL(const GURL
, origin_cookie_url
, (kGlobalCookieSetURL
));
202 canonical_cookie::CookieHashSet
* cookie_set
=
203 GetCookiesFor(origin_cookie_url
);
204 DeleteMatchingCookie(cookie
, cookie_set
);
205 cookie_set
->insert(cookie
);