From e4aa630adb18846d4420dc328cdfcfef6b47caa5 Mon Sep 17 00:00:00 2001 From: Iain Merrick Date: Thu, 2 Dec 2010 11:24:53 +0000 Subject: CookieManager::flushCookieStore() is now synchronous. This ensures that all data is correctly stored before onPause() returns. There's no API change on the Java side (although I should update the comment to explain it's now synchronous; I'll do that in another CL). Depends on a new completion callback added to CookieMonster. See change Ieb3e787b in external/chromium. Change-Id: I008f35d101a9223fe705396273bc4cd563a5f77e --- WebKit/android/WebCoreSupport/WebCookieJar.cpp | 60 ++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) (limited to 'WebKit/android/WebCoreSupport/WebCookieJar.cpp') diff --git a/WebKit/android/WebCoreSupport/WebCookieJar.cpp b/WebKit/android/WebCoreSupport/WebCookieJar.cpp index 6cef74b..6a81ff1 100644 --- a/WebKit/android/WebCoreSupport/WebCookieJar.cpp +++ b/WebKit/android/WebCoreSupport/WebCookieJar.cpp @@ -29,6 +29,7 @@ #include "JNIUtility.h" #include "WebCoreJni.h" #include "WebRequestContext.h" +#include "WebUrlLoaderClient.h" namespace android { @@ -124,4 +125,63 @@ int WebCookieJar::CanSetCookie(const GURL&, const GURL&, const std::string&, net return m_allowCookies ? net::OK : net::ERR_ACCESS_DENIED; } +class FlushSemaphore : public base::RefCounted +{ +public: + FlushSemaphore() + : m_condition(&m_lock) + , m_count(0) + {} + + void SendFlushRequest(net::CookieMonster* monster) { + // FlushStore() needs to run on a Chrome thread (because it will need + // to post the callback, and it may want to do so on its own thread.) + // We use the IO thread for this purpose. + // + // TODO(husky): Our threads are hidden away in various files. Clean this + // up and consider integrating with Chrome's browser_thread.h. Might be + // a better idea to use the DB thread here rather than the IO thread. + + base::Thread* ioThread = WebUrlLoaderClient::ioThread(); + if (ioThread) { + Task* callback = NewRunnableMethod(this, &FlushSemaphore::Callback); + ioThread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod( + monster, &net::CookieMonster::FlushStore, callback)); + } + } + + // Block until the given number of callbacks has been made. + void Wait(int numCallbacks) { + AutoLock al(m_lock); + while (m_count < numCallbacks) { + // TODO(husky): Maybe use TimedWait() here? But it's not obvious what + // to do if the flush fails. Might be okay just to let the OS kill us. + m_condition.Wait(); + } + m_count -= numCallbacks; + } + +private: + friend class base::RefCounted; + + void Callback() { + AutoLock al(m_lock); + m_count++; + m_condition.Broadcast(); + } + + Lock m_lock; + ConditionVariable m_condition; + volatile int m_count; +}; + +void WebCookieJar::flush() +{ + // Flush both cookie stores (private and non-private), wait for 2 callbacks. + static scoped_refptr semaphore(new FlushSemaphore()); + semaphore->SendFlushRequest(get(false)->cookieStore()->GetCookieMonster()); + semaphore->SendFlushRequest(get(true)->cookieStore()->GetCookieMonster()); + semaphore->Wait(2); +} + } -- cgit v1.1