Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(219)

Side by Side Diff: net/cookies/cookie_monster.cc

Issue 676073003: Add AddCallbackForCookie method to CookieStore. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 6 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698