OSDN Git Service

CookieManager::flushCookieStore() is now synchronous.
authorIain Merrick <husky@google.com>
Thu, 2 Dec 2010 11:24:53 +0000 (11:24 +0000)
committerIain Merrick <husky@google.com>
Fri, 3 Dec 2010 11:14:40 +0000 (11:14 +0000)
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
WebKit/android/WebCoreSupport/WebCookieJar.h
WebKit/android/jni/CookieManager.cpp

index 6cef74b..6a81ff1 100644 (file)
@@ -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<FlushSemaphore>
+{
+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<FlushSemaphore>;
+
+    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<FlushSemaphore> semaphore(new FlushSemaphore());
+    semaphore->SendFlushRequest(get(false)->cookieStore()->GetCookieMonster());
+    semaphore->SendFlushRequest(get(true)->cookieStore()->GetCookieMonster());
+    semaphore->Wait(2);
+}
+
 }
index ecaa228..1372064 100644 (file)
@@ -39,6 +39,9 @@ public:
     static WebCookieJar* get(bool isPrivateBrowsing);
     static void cleanup(bool isPrivateBrowsing);
 
+    // Flush all cookies to disk. Synchronous.
+    static void flush();
+
     // CookiePolicy implementation from external/chromium
     virtual int CanGetCookies(const GURL& url, const GURL& first_party_for_cookies, net::CompletionCallback*);
     virtual int CanSetCookie(const GURL& url, const GURL& first_party_for_cookies, const std::string& cookie_line, net::CompletionCallback*);
index 0053e4f..5532f6a 100644 (file)
@@ -158,8 +158,7 @@ static void setCookie(JNIEnv* env, jobject, jstring url, jstring value)
 static void flushCookieStore(JNIEnv*, jobject)
 {
 #if USE(CHROME_NETWORK_STACK)
-    WebCookieJar::get(false)->cookieStore()->GetCookieMonster()->FlushStore();
-    WebCookieJar::get(true)->cookieStore()->GetCookieMonster()->FlushStore();
+    WebCookieJar::flush();
 #endif
 }