OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // Portions of this code based on Mozilla: | 5 // Portions of this code based on Mozilla: |
6 // (netwerk/cookie/src/nsCookieService.cpp) | 6 // (netwerk/cookie/src/nsCookieService.cpp) |
7 /* ***** BEGIN LICENSE BLOCK ***** | 7 /* ***** BEGIN LICENSE BLOCK ***** |
8 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 | 8 * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
9 * | 9 * |
10 * The contents of this file are subject to the Mozilla Public License Version | 10 * The contents of this file are subject to the Mozilla Public License Version |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
56 #include "base/memory/scoped_vector.h" | 56 #include "base/memory/scoped_vector.h" |
57 #include "base/message_loop/message_loop.h" | 57 #include "base/message_loop/message_loop.h" |
58 #include "base/message_loop/message_loop_proxy.h" | 58 #include "base/message_loop/message_loop_proxy.h" |
59 #include "base/metrics/histogram.h" | 59 #include "base/metrics/histogram.h" |
60 #include "base/strings/string_util.h" | 60 #include "base/strings/string_util.h" |
61 #include "base/strings/stringprintf.h" | 61 #include "base/strings/stringprintf.h" |
62 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" | 62 #include "net/base/registry_controlled_domains/registry_controlled_domain.h" |
63 #include "net/cookies/canonical_cookie.h" | 63 #include "net/cookies/canonical_cookie.h" |
64 #include "net/cookies/cookie_util.h" | 64 #include "net/cookies/cookie_util.h" |
65 #include "net/cookies/parsed_cookie.h" | 65 #include "net/cookies/parsed_cookie.h" |
66 #include "url/gurl.h" | |
67 | 66 |
68 using base::Time; | 67 using base::Time; |
69 using base::TimeDelta; | 68 using base::TimeDelta; |
70 using base::TimeTicks; | 69 using base::TimeTicks; |
71 | 70 |
72 // In steady state, most cookie requests can be satisfied by the in memory | 71 // In steady state, most cookie requests can be satisfied by the in memory |
73 // cookie monster store. However, if a request comes in during the initial | 72 // cookie monster store. However, if a request comes in during the initial |
74 // cookie load, it must be delayed until that load completes. That is done by | 73 // cookie load, it must be delayed until that load completes. That is done by |
75 // queueing it on CookieMonster::tasks_pending_ and running it when notification | 74 // queueing it on CookieMonster::tasks_pending_ and running it when notification |
76 // of cookie load completion is received via CookieMonster::OnLoaded. This | 75 // of cookie load completion is received via CookieMonster::OnLoaded. This |
(...skipping 223 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
300 // In Mozilla if you set a cookie like AAAA, it will have an empty token | 299 // In Mozilla if you set a cookie like AAAA, it will have an empty token |
301 // and a value of AAAA. When it sends the cookie back, it will send AAAA, | 300 // and a value of AAAA. When it sends the cookie back, it will send AAAA, |
302 // so we need to avoid sending =AAAA for a blank token value. | 301 // so we need to avoid sending =AAAA for a blank token value. |
303 if (!(*it)->Name().empty()) | 302 if (!(*it)->Name().empty()) |
304 cookie_line += (*it)->Name() + "="; | 303 cookie_line += (*it)->Name() + "="; |
305 cookie_line += (*it)->Value(); | 304 cookie_line += (*it)->Value(); |
306 } | 305 } |
307 return cookie_line; | 306 return cookie_line; |
308 } | 307 } |
309 | 308 |
309 void RunAsync(scoped_refptr<base::TaskRunner> proxy, | |
310 const CookieStore::CookieChangedCallback& callback) { | |
311 proxy->PostTask(FROM_HERE, callback); | |
312 } | |
313 | |
310 } // namespace | 314 } // namespace |
311 | 315 |
312 CookieMonster::CookieMonster(PersistentCookieStore* store, | 316 CookieMonster::CookieMonster(PersistentCookieStore* store, |
313 CookieMonsterDelegate* delegate) | 317 CookieMonsterDelegate* delegate) |
314 : initialized_(false), | 318 : initialized_(false), |
315 loaded_(store == NULL), | 319 loaded_(store == NULL), |
316 store_(store), | 320 store_(store), |
317 last_access_threshold_( | 321 last_access_threshold_( |
318 TimeDelta::FromSeconds(kDefaultAccessUpdateThresholdSeconds)), | 322 TimeDelta::FromSeconds(kDefaultAccessUpdateThresholdSeconds)), |
319 delegate_(delegate), | 323 delegate_(delegate), |
(...skipping 576 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
896 const std::string& path, | 900 const std::string& path, |
897 const Time& expiration_time, | 901 const Time& expiration_time, |
898 bool secure, | 902 bool secure, |
899 bool http_only, | 903 bool http_only, |
900 CookiePriority priority, | 904 CookiePriority priority, |
901 const SetCookiesCallback& callback) { | 905 const SetCookiesCallback& callback) { |
902 scoped_refptr<SetCookieWithDetailsTask> task = | 906 scoped_refptr<SetCookieWithDetailsTask> task = |
903 new SetCookieWithDetailsTask(this, url, name, value, domain, path, | 907 new SetCookieWithDetailsTask(this, url, name, value, domain, path, |
904 expiration_time, secure, http_only, priority, | 908 expiration_time, secure, http_only, priority, |
905 callback); | 909 callback); |
906 | |
907 DoCookieTaskForURL(task, url); | 910 DoCookieTaskForURL(task, url); |
908 } | 911 } |
909 | 912 |
910 void CookieMonster::GetAllCookiesAsync(const GetCookieListCallback& callback) { | 913 void CookieMonster::GetAllCookiesAsync(const GetCookieListCallback& callback) { |
911 scoped_refptr<GetAllCookiesTask> task = | 914 scoped_refptr<GetAllCookiesTask> task = |
912 new GetAllCookiesTask(this, callback); | 915 new GetAllCookiesTask(this, callback); |
913 | 916 |
914 DoCookieTask(task); | 917 DoCookieTask(task); |
915 } | 918 } |
916 | 919 |
(...skipping 889 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1806 return false; | 1809 return false; |
1807 } | 1810 } |
1808 return SetCanonicalCookie(&cc, creation_time, options); | 1811 return SetCanonicalCookie(&cc, creation_time, options); |
1809 } | 1812 } |
1810 | 1813 |
1811 bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie>* cc, | 1814 bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie>* cc, |
1812 const Time& creation_time, | 1815 const Time& creation_time, |
1813 const CookieOptions& options) { | 1816 const CookieOptions& options) { |
1814 const std::string key(GetKey((*cc)->Domain())); | 1817 const std::string key(GetKey((*cc)->Domain())); |
1815 bool already_expired = (*cc)->IsExpired(creation_time); | 1818 bool already_expired = (*cc)->IsExpired(creation_time); |
1819 | |
1816 if (DeleteAnyEquivalentCookie(key, **cc, options.exclude_httponly(), | 1820 if (DeleteAnyEquivalentCookie(key, **cc, options.exclude_httponly(), |
1817 already_expired)) { | 1821 already_expired)) { |
1818 VLOG(kVlogSetCookies) << "SetCookie() not clobbering httponly cookie"; | 1822 VLOG(kVlogSetCookies) << "SetCookie() not clobbering httponly cookie"; |
1819 return false; | 1823 return false; |
1820 } | 1824 } |
1821 | 1825 |
1822 VLOG(kVlogSetCookies) << "SetCookie() key: " << key << " cc: " | 1826 VLOG(kVlogSetCookies) << "SetCookie() key: " << key << " cc: " |
1823 << (*cc)->DebugString(); | 1827 << (*cc)->DebugString(); |
1824 | 1828 |
1825 // Realize that we might be setting an expired cookie, and the only point | 1829 // Realize that we might be setting an expired cookie, and the only point |
1826 // was to delete the cookie which we've already done. | 1830 // was to delete the cookie which we've already done. |
1827 if (!already_expired || keep_expired_cookies_) { | 1831 if (!already_expired || keep_expired_cookies_) { |
1828 // See InitializeHistograms() for details. | 1832 // See InitializeHistograms() for details. |
1829 if ((*cc)->IsPersistent()) { | 1833 if ((*cc)->IsPersistent()) { |
1830 histogram_expiration_duration_minutes_->Add( | 1834 histogram_expiration_duration_minutes_->Add( |
1831 ((*cc)->ExpiryDate() - creation_time).InMinutes()); | 1835 ((*cc)->ExpiryDate() - creation_time).InMinutes()); |
1832 } | 1836 } |
1833 | 1837 |
1834 InternalInsertCookie(key, cc->release(), true); | 1838 { |
1839 CanonicalCookie cookie = *(cc->get()); | |
1840 InternalInsertCookie(key, cc->release(), true); | |
1841 RunCallbacks(cookie); | |
1842 } | |
1835 } else { | 1843 } else { |
1836 VLOG(kVlogSetCookies) << "SetCookie() not storing already expired cookie."; | 1844 VLOG(kVlogSetCookies) << "SetCookie() not storing already expired cookie."; |
1837 } | 1845 } |
1838 | 1846 |
1839 // We assume that hopefully setting a cookie will be less common than | 1847 // We assume that hopefully setting a cookie will be less common than |
1840 // querying a cookie. Since setting a cookie can put us over our limits, | 1848 // querying a cookie. Since setting a cookie can put us over our limits, |
1841 // make sure that we garbage collect... We can also make the assumption that | 1849 // make sure that we garbage collect... We can also make the assumption that |
1842 // if a cookie was set, in the common case it will be used soon after, | 1850 // if a cookie was set, in the common case it will be used soon after, |
1843 // and we will purge the expired cookies in GetCookies(). | 1851 // and we will purge the expired cookies in GetCookies(). |
1844 GarbageCollect(creation_time, key); | 1852 GarbageCollect(creation_time, key); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1889 if ((cc->IsPersistent() || persist_session_cookies_) && store_.get() && | 1897 if ((cc->IsPersistent() || persist_session_cookies_) && store_.get() && |
1890 sync_to_store) | 1898 sync_to_store) |
1891 store_->DeleteCookie(*cc); | 1899 store_->DeleteCookie(*cc); |
1892 if (delegate_.get()) { | 1900 if (delegate_.get()) { |
1893 ChangeCausePair mapping = ChangeCauseMapping[deletion_cause]; | 1901 ChangeCausePair mapping = ChangeCauseMapping[deletion_cause]; |
1894 | 1902 |
1895 if (mapping.notify) | 1903 if (mapping.notify) |
1896 delegate_->OnCookieChanged(*cc, true, mapping.cause); | 1904 delegate_->OnCookieChanged(*cc, true, mapping.cause); |
1897 } | 1905 } |
1898 cookies_.erase(it); | 1906 cookies_.erase(it); |
1907 RunCallbacks(*cc); | |
1899 delete cc; | 1908 delete cc; |
1900 } | 1909 } |
1901 | 1910 |
1902 // Domain expiry behavior is unchanged by key/expiry scheme (the | 1911 // Domain expiry behavior is unchanged by key/expiry scheme (the |
1903 // meaning of the key is different, but that's not visible to this routine). | 1912 // meaning of the key is different, but that's not visible to this routine). |
1904 int CookieMonster::GarbageCollect(const Time& current, | 1913 int CookieMonster::GarbageCollect(const Time& current, |
1905 const std::string& key) { | 1914 const std::string& key) { |
1906 lock_.AssertAcquired(); | 1915 lock_.AssertAcquired(); |
1907 | 1916 |
1908 int num_deleted = 0; | 1917 int num_deleted = 0; |
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
2296 } | 2305 } |
2297 | 2306 |
2298 return true; | 2307 return true; |
2299 } | 2308 } |
2300 | 2309 |
2301 bool CookieMonster::loaded() { | 2310 bool CookieMonster::loaded() { |
2302 base::AutoLock autolock(lock_); | 2311 base::AutoLock autolock(lock_); |
2303 return loaded_; | 2312 return loaded_; |
2304 } | 2313 } |
2305 | 2314 |
2315 scoped_ptr<CookieStore::CookieChangedSubscription> | |
2316 CookieMonster::AddCallbackForCookie( | |
2317 const GURL& gurl, | |
2318 const std::string& name, | |
2319 const CookieChangedCallback& callback) { | |
2320 base::AutoLock autolock(lock_); | |
2321 std::pair<GURL, std::string> key(gurl, name); | |
2322 CookieChangedCallback wrapped = base::Bind( | |
2323 &RunAsync, base::MessageLoopProxy::current(), callback); | |
2324 if (hook_map_.count(key) == 0) { | |
2325 linked_ptr<CookieChangedCallbackList> list( | |
2326 new CookieChangedCallbackList()); | |
2327 hook_map_[key] = list; | |
erikwright (departed)
2014/10/24 20:11:10
hook_map_[key] = make_linked_ptr(new CookieChanged
| |
2328 } | |
2329 return hook_map_[key]->Add(wrapped); | |
erikwright (departed)
2014/10/24 20:11:10
I would inline the call to base::Bind here. No nee
| |
2330 } | |
2331 | |
2332 void CookieMonster::RunCallbacks(const CanonicalCookie& cookie) { | |
2333 lock_.AssertAcquired(); | |
2334 CookieOptions opts; | |
2335 opts.set_include_httponly(); | |
2336 // Note that the callbacks in hook_map_ are wrapped with MakeAsync(), so they | |
2337 // are guaranteed to not take long - they just post a RunAsync task back to | |
2338 // the appropriate thread's message loop and return. It is important that this | |
2339 // method not run user-supplied callbacks directly, since the CookieMonster | |
2340 // lock is held and it is easy to accidentally introduce deadlocks. | |
2341 for (CookieChangedHookMap::iterator it = hook_map_.begin(); | |
2342 it != hook_map_.end(); ++it) { | |
2343 std::pair<GURL, std::string> key = it->first; | |
2344 if (cookie.IncludeForRequestURL(key.first, opts) && | |
2345 cookie.Name() == key.second) { | |
2346 it->second->Notify(); | |
2347 } | |
2348 } | |
2349 } | |
2350 | |
2306 } // namespace net | 2351 } // namespace net |
OLD | NEW |