Chromium Code Reviews| Index: net/cookies/cookie_monster.cc |
| diff --git a/net/cookies/cookie_monster.cc b/net/cookies/cookie_monster.cc |
| index dd64cce8e41e3636009d234d7875eb3707eb167b..285022714a95f3b30e9139773fe33814da18b8e9 100644 |
| --- a/net/cookies/cookie_monster.cc |
| +++ b/net/cookies/cookie_monster.cc |
| @@ -63,7 +63,6 @@ |
| #include "net/cookies/canonical_cookie.h" |
| #include "net/cookies/cookie_util.h" |
| #include "net/cookies/parsed_cookie.h" |
| -#include "url/gurl.h" |
| using base::Time; |
| using base::TimeDelta; |
| @@ -307,6 +306,11 @@ std::string BuildCookieLine(const CanonicalCookieVector& cookies) { |
| return cookie_line; |
| } |
| +void RunAsync(scoped_refptr<base::TaskRunner> proxy, |
| + const CookieStore::CookieChangedCallback& callback) { |
| + proxy->PostTask(FROM_HERE, callback); |
| +} |
| + |
| } // namespace |
| CookieMonster::CookieMonster(PersistentCookieStore* store, |
| @@ -903,7 +907,6 @@ void CookieMonster::SetCookieWithDetailsAsync( |
| new SetCookieWithDetailsTask(this, url, name, value, domain, path, |
| expiration_time, secure, http_only, priority, |
| callback); |
| - |
| DoCookieTaskForURL(task, url); |
| } |
| @@ -1813,6 +1816,7 @@ bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie>* cc, |
| const CookieOptions& options) { |
| const std::string key(GetKey((*cc)->Domain())); |
| bool already_expired = (*cc)->IsExpired(creation_time); |
| + |
| if (DeleteAnyEquivalentCookie(key, **cc, options.exclude_httponly(), |
| already_expired)) { |
| VLOG(kVlogSetCookies) << "SetCookie() not clobbering httponly cookie"; |
| @@ -1831,7 +1835,11 @@ bool CookieMonster::SetCanonicalCookie(scoped_ptr<CanonicalCookie>* cc, |
| ((*cc)->ExpiryDate() - creation_time).InMinutes()); |
| } |
| - InternalInsertCookie(key, cc->release(), true); |
| + { |
| + CanonicalCookie cookie = *(cc->get()); |
| + InternalInsertCookie(key, cc->release(), true); |
| + RunCallbacks(cookie); |
| + } |
| } else { |
| VLOG(kVlogSetCookies) << "SetCookie() not storing already expired cookie."; |
| } |
| @@ -1896,6 +1904,7 @@ void CookieMonster::InternalDeleteCookie(CookieMap::iterator it, |
| delegate_->OnCookieChanged(*cc, true, mapping.cause); |
| } |
| cookies_.erase(it); |
| + RunCallbacks(*cc); |
| delete cc; |
| } |
| @@ -2303,4 +2312,40 @@ bool CookieMonster::loaded() { |
| return loaded_; |
| } |
| +scoped_ptr<CookieStore::CookieChangedSubscription> |
| +CookieMonster::AddCallbackForCookie( |
| + const GURL& gurl, |
| + const std::string& name, |
| + const CookieChangedCallback& callback) { |
| + base::AutoLock autolock(lock_); |
| + std::pair<GURL, std::string> key(gurl, name); |
| + CookieChangedCallback wrapped = base::Bind( |
| + &RunAsync, base::MessageLoopProxy::current(), callback); |
| + if (hook_map_.count(key) == 0) { |
| + linked_ptr<CookieChangedCallbackList> list( |
| + new CookieChangedCallbackList()); |
| + hook_map_[key] = list; |
|
erikwright (departed)
2014/10/24 20:11:10
hook_map_[key] = make_linked_ptr(new CookieChanged
|
| + } |
| + 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
|
| +} |
| + |
| +void CookieMonster::RunCallbacks(const CanonicalCookie& cookie) { |
| + lock_.AssertAcquired(); |
| + CookieOptions opts; |
| + opts.set_include_httponly(); |
| + // Note that the callbacks in hook_map_ are wrapped with MakeAsync(), so they |
| + // are guaranteed to not take long - they just post a RunAsync task back to |
| + // the appropriate thread's message loop and return. It is important that this |
| + // method not run user-supplied callbacks directly, since the CookieMonster |
| + // lock is held and it is easy to accidentally introduce deadlocks. |
| + for (CookieChangedHookMap::iterator it = hook_map_.begin(); |
| + it != hook_map_.end(); ++it) { |
| + std::pair<GURL, std::string> key = it->first; |
| + if (cookie.IncludeForRequestURL(key.first, opts) && |
| + cookie.Name() == key.second) { |
| + it->second->Notify(); |
| + } |
| + } |
| +} |
| + |
| } // namespace net |