- add sources.
[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 kGlobalCookieListURL[] = "chrome://cookielist";
27 }
28
29 BrowsingDataCookieHelper::BrowsingDataCookieHelper(
30     net::URLRequestContextGetter* request_context_getter)
31     : is_fetching_(false),
32       request_context_getter_(request_context_getter) {
33   DCHECK(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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(BrowserThread::CurrentlyOn(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 CannedBrowsingDataCookieHelper* CannedBrowsingDataCookieHelper::Clone() {
112   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
113   CannedBrowsingDataCookieHelper* clone =
114       new CannedBrowsingDataCookieHelper(request_context_getter());
115
116   for (OriginCookieListMap::iterator it = origin_cookie_list_map_.begin();
117        it != origin_cookie_list_map_.end();
118        ++it) {
119     net::CookieList* cookies = clone->GetCookiesFor(it->first);
120     cookies->insert(cookies->begin(), it->second->begin(), it->second->end());
121   }
122   return clone;
123 }
124
125 void CannedBrowsingDataCookieHelper::AddReadCookies(
126     const GURL& frame_url,
127     const GURL& url,
128     const net::CookieList& cookie_list) {
129   typedef net::CookieList::const_iterator cookie_iterator;
130   for (cookie_iterator add_cookie = cookie_list.begin();
131        add_cookie != cookie_list.end(); ++add_cookie) {
132     AddCookie(frame_url, *add_cookie);
133   }
134 }
135
136 void CannedBrowsingDataCookieHelper::AddChangedCookie(
137     const GURL& frame_url,
138     const GURL& url,
139     const std::string& cookie_line,
140     const net::CookieOptions& options) {
141   scoped_ptr<net::CanonicalCookie> cookie(net::CanonicalCookie::Create(
142       url, cookie_line, base::Time::Now(), options));
143   if (cookie.get())
144     AddCookie(frame_url, *cookie);
145 }
146
147 void CannedBrowsingDataCookieHelper::Reset() {
148   STLDeleteContainerPairSecondPointers(origin_cookie_list_map_.begin(),
149                                        origin_cookie_list_map_.end());
150   origin_cookie_list_map_.clear();
151 }
152
153 bool CannedBrowsingDataCookieHelper::empty() const {
154   for (OriginCookieListMap::const_iterator it =
155            origin_cookie_list_map_.begin();
156        it != origin_cookie_list_map_.end();
157        ++it) {
158     if (!it->second->empty())
159       return false;
160   }
161   return true;
162 }
163
164
165 size_t CannedBrowsingDataCookieHelper::GetCookieCount() const {
166   size_t count = 0;
167   for (OriginCookieListMap::const_iterator it = origin_cookie_list_map_.begin();
168        it != origin_cookie_list_map_.end();
169        ++it) {
170     count += it->second->size();
171   }
172   return count;
173 }
174
175
176 void CannedBrowsingDataCookieHelper::StartFetching(
177     const net::CookieMonster::GetCookieListCallback& callback) {
178   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
179   net::CookieList cookie_list;
180   for (OriginCookieListMap::iterator it = origin_cookie_list_map_.begin();
181        it != origin_cookie_list_map_.end();
182        ++it) {
183     cookie_list.insert(cookie_list.begin(),
184                        it->second->begin(),
185                        it->second->end());
186   }
187   callback.Run(cookie_list);
188 }
189
190 bool CannedBrowsingDataCookieHelper::DeleteMatchingCookie(
191     const net::CanonicalCookie& add_cookie,
192     net::CookieList* cookie_list) {
193   typedef net::CookieList::iterator cookie_iterator;
194   for (cookie_iterator cookie = cookie_list->begin();
195       cookie != cookie_list->end(); ++cookie) {
196     if (cookie->Name() == add_cookie.Name() &&
197         cookie->Domain() == add_cookie.Domain()&&
198         cookie->Path() == add_cookie.Path()) {
199       cookie_list->erase(cookie);
200       return true;
201     }
202   }
203   return false;
204 }
205
206 net::CookieList* CannedBrowsingDataCookieHelper::GetCookiesFor(
207     const GURL& first_party_origin) {
208   OriginCookieListMap::iterator it =
209       origin_cookie_list_map_.find(first_party_origin);
210   if (it == origin_cookie_list_map_.end()) {
211     net::CookieList* cookies = new net::CookieList();
212     origin_cookie_list_map_.insert(
213         std::pair<GURL, net::CookieList*>(first_party_origin, cookies));
214     return cookies;
215   }
216   return it->second;
217 }
218
219 void CannedBrowsingDataCookieHelper::AddCookie(
220     const GURL& frame_url,
221     const net::CanonicalCookie& cookie) {
222   // Storing cookies in separate cookie lists per frame origin makes the
223   // GetCookieCount method count a cookie multiple times if it is stored in
224   // multiple lists.
225   // E.g. let "example.com" be redirected to "www.example.com". A cookie set
226   // with the cookie string "A=B; Domain=.example.com" would be sent to both
227   // hosts. This means it would be stored in the separate cookie lists for both
228   // hosts ("example.com", "www.example.com"). The method GetCookieCount would
229   // count this cookie twice. To prevent this, we us a single global cookie
230   // list as a work-around to store all added cookies. Per frame URL cookie
231   // lists are currently not used. In the future they will be used for
232   // collecting cookies per origin in redirect chains.
233   // TODO(markusheintz): A) Change the GetCookiesCount method to prevent
234   // counting cookies multiple times if they are stored in multiple cookie
235   // lists.  B) Replace the GetCookieFor method call below with:
236   // "GetCookiesFor(frame_url.GetOrigin());"
237   net::CookieList* cookie_list =
238       GetCookiesFor(GURL(kGlobalCookieListURL));
239   DeleteMatchingCookie(cookie, cookie_list);
240   cookie_list->push_back(cookie);
241 }