Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / browsing_data / browsing_data_cookie_helper.cc
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.
4
5 #include "chrome/browser/browsing_data/browsing_data_cookie_helper.h"
6
7 #include "utility"
8
9 #include "base/bind.h"
10 #include "base/logging.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/stl_util.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "content/public/browser/browser_thread.h"
15 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
16 #include "net/cookies/canonical_cookie.h"
17 #include "net/cookies/cookie_util.h"
18 #include "net/cookies/parsed_cookie.h"
19 #include "net/url_request/url_request_context.h"
20 #include "net/url_request/url_request_context_getter.h"
21 #include "url/gurl.h"
22
23 using content::BrowserThread;
24
25 namespace {
26 const char kGlobalCookieSetURL[] = "chrome://cookieset";
27 }
28
29 BrowsingDataCookieHelper::BrowsingDataCookieHelper(
30     net::URLRequestContextGetter* request_context_getter)
31     : is_fetching_(false),
32       request_context_getter_(request_context_getter) {
33   DCHECK_CURRENTLY_ON(BrowserThread::UI);
34 }
35
36 BrowsingDataCookieHelper::~BrowsingDataCookieHelper() {
37 }
38
39 void BrowsingDataCookieHelper::StartFetching(
40     const base::Callback<void(const net::CookieList& cookies)>& callback) {
41   DCHECK_CURRENTLY_ON(BrowserThread::UI);
42   DCHECK(!is_fetching_);
43   DCHECK(!callback.is_null());
44   DCHECK(completion_callback_.is_null());
45   is_fetching_ = true;
46   completion_callback_ = callback;
47   BrowserThread::PostTask(
48       BrowserThread::IO, FROM_HERE,
49       base::Bind(&BrowsingDataCookieHelper::FetchCookiesOnIOThread, this));
50 }
51
52 void BrowsingDataCookieHelper::DeleteCookie(
53     const net::CanonicalCookie& cookie) {
54   DCHECK_CURRENTLY_ON(BrowserThread::UI);
55   BrowserThread::PostTask(
56       BrowserThread::IO, FROM_HERE,
57       base::Bind(&BrowsingDataCookieHelper::DeleteCookieOnIOThread,
58                  this, cookie));
59 }
60
61 void BrowsingDataCookieHelper::FetchCookiesOnIOThread() {
62   DCHECK_CURRENTLY_ON(BrowserThread::IO);
63   scoped_refptr<net::CookieMonster> cookie_monster =
64       request_context_getter_->GetURLRequestContext()->
65       cookie_store()->GetCookieMonster();
66   if (cookie_monster.get()) {
67     cookie_monster->GetAllCookiesAsync(
68         base::Bind(&BrowsingDataCookieHelper::OnFetchComplete, this));
69   } else {
70     OnFetchComplete(net::CookieList());
71   }
72 }
73
74 void BrowsingDataCookieHelper::OnFetchComplete(const net::CookieList& cookies) {
75   DCHECK_CURRENTLY_ON(BrowserThread::IO);
76   BrowserThread::PostTask(
77       BrowserThread::UI, FROM_HERE,
78       base::Bind(&BrowsingDataCookieHelper::NotifyInUIThread, this, cookies));
79 }
80
81 void BrowsingDataCookieHelper::NotifyInUIThread(
82     const net::CookieList& cookies) {
83   DCHECK_CURRENTLY_ON(BrowserThread::UI);
84   DCHECK(is_fetching_);
85   is_fetching_ = false;
86   completion_callback_.Run(cookies);
87   completion_callback_.Reset();
88 }
89
90 void BrowsingDataCookieHelper::DeleteCookieOnIOThread(
91     const net::CanonicalCookie& cookie) {
92   DCHECK_CURRENTLY_ON(BrowserThread::IO);
93   scoped_refptr<net::CookieMonster> cookie_monster =
94       request_context_getter_->GetURLRequestContext()->
95       cookie_store()->GetCookieMonster();
96   if (cookie_monster.get()) {
97     cookie_monster->DeleteCanonicalCookieAsync(
98         cookie, net::CookieMonster::DeleteCookieCallback());
99   }
100 }
101
102 CannedBrowsingDataCookieHelper::CannedBrowsingDataCookieHelper(
103     net::URLRequestContextGetter* request_context_getter)
104     : BrowsingDataCookieHelper(request_context_getter) {
105 }
106
107 CannedBrowsingDataCookieHelper::~CannedBrowsingDataCookieHelper() {
108   Reset();
109 }
110
111 void CannedBrowsingDataCookieHelper::AddReadCookies(
112     const GURL& frame_url,
113     const GURL& url,
114     const net::CookieList& cookie_list) {
115   typedef net::CookieList::const_iterator cookie_iterator;
116   for (cookie_iterator add_cookie = cookie_list.begin();
117        add_cookie != cookie_list.end(); ++add_cookie) {
118     AddCookie(frame_url, *add_cookie);
119   }
120 }
121
122 void CannedBrowsingDataCookieHelper::AddChangedCookie(
123     const GURL& frame_url,
124     const GURL& url,
125     const std::string& cookie_line,
126     const net::CookieOptions& options) {
127   scoped_ptr<net::CanonicalCookie> cookie(net::CanonicalCookie::Create(
128       url, cookie_line, base::Time::Now(), options));
129   if (cookie.get())
130     AddCookie(frame_url, *cookie);
131 }
132
133 void CannedBrowsingDataCookieHelper::Reset() {
134   STLDeleteContainerPairSecondPointers(origin_cookie_set_map_.begin(),
135                                        origin_cookie_set_map_.end());
136   origin_cookie_set_map_.clear();
137 }
138
139 bool CannedBrowsingDataCookieHelper::empty() const {
140   for (OriginCookieSetMap::const_iterator it = origin_cookie_set_map_.begin();
141        it != origin_cookie_set_map_.end();
142        ++it) {
143     if (!it->second->empty())
144       return false;
145   }
146   return true;
147 }
148
149
150 size_t CannedBrowsingDataCookieHelper::GetCookieCount() const {
151   size_t count = 0;
152   for (OriginCookieSetMap::const_iterator it = origin_cookie_set_map_.begin();
153        it != origin_cookie_set_map_.end();
154        ++it) {
155     count += it->second->size();
156   }
157   return count;
158 }
159
160
161 void CannedBrowsingDataCookieHelper::StartFetching(
162     const net::CookieMonster::GetCookieListCallback& callback) {
163   DCHECK_CURRENTLY_ON(BrowserThread::UI);
164   net::CookieList cookie_list;
165   for (OriginCookieSetMap::iterator it = origin_cookie_set_map_.begin();
166        it != origin_cookie_set_map_.end();
167        ++it) {
168     cookie_list.insert(cookie_list.begin(),
169                        it->second->begin(),
170                        it->second->end());
171   }
172   callback.Run(cookie_list);
173 }
174
175 void CannedBrowsingDataCookieHelper::DeleteCookie(
176     const net::CanonicalCookie& cookie) {
177   for (OriginCookieSetMap::iterator it = origin_cookie_set_map_.begin();
178        it != origin_cookie_set_map_.end();
179        ++it) {
180     DeleteMatchingCookie(cookie, it->second);
181   }
182   BrowsingDataCookieHelper::DeleteCookie(cookie);
183 }
184
185 bool CannedBrowsingDataCookieHelper::DeleteMatchingCookie(
186     const net::CanonicalCookie& add_cookie,
187     canonical_cookie::CookieHashSet* cookie_set) {
188   return cookie_set->erase(add_cookie) > 0;
189 }
190
191 canonical_cookie::CookieHashSet* CannedBrowsingDataCookieHelper::GetCookiesFor(
192     const GURL& first_party_origin) {
193   OriginCookieSetMap::iterator it =
194       origin_cookie_set_map_.find(first_party_origin);
195   if (it == origin_cookie_set_map_.end()) {
196     canonical_cookie::CookieHashSet* cookies =
197         new canonical_cookie::CookieHashSet;
198     origin_cookie_set_map_.insert(
199         std::pair<GURL, canonical_cookie::CookieHashSet*>(first_party_origin,
200                                                           cookies));
201     return cookies;
202   }
203   return it->second;
204 }
205
206 void CannedBrowsingDataCookieHelper::AddCookie(
207     const GURL& frame_url,
208     const net::CanonicalCookie& cookie) {
209   // Storing cookies in separate cookie sets per frame origin makes the
210   // GetCookieCount method count a cookie multiple times if it is stored in
211   // multiple sets.
212   // E.g. let "example.com" be redirected to "www.example.com". A cookie set
213   // with the cookie string "A=B; Domain=.example.com" would be sent to both
214   // hosts. This means it would be stored in the separate cookie sets for both
215   // hosts ("example.com", "www.example.com"). The method GetCookieCount would
216   // count this cookie twice. To prevent this, we us a single global cookie
217   // set as a work-around to store all added cookies. Per frame URL cookie
218   // sets are currently not used. In the future they will be used for
219   // collecting cookies per origin in redirect chains.
220   // TODO(markusheintz): A) Change the GetCookiesCount method to prevent
221   // counting cookies multiple times if they are stored in multiple cookie
222   // sets.  B) Replace the GetCookieFor method call below with:
223   // "GetCookiesFor(frame_url.GetOrigin());"
224   CR_DEFINE_STATIC_LOCAL(const GURL, origin_cookie_url, (kGlobalCookieSetURL));
225   canonical_cookie::CookieHashSet* cookie_set =
226       GetCookiesFor(origin_cookie_url);
227   DeleteMatchingCookie(cookie, cookie_set);
228   cookie_set->insert(cookie);
229 }