Commit 976e410c authored by hjd@chromium.org's avatar hjd@chromium.org

Adds Asynchronous APIs to CookieManager

Creates asynchronous versions of SetCookie, removeAllCookie and
removeSessionCookie which take callbacks.

BUG=
TEST=AndroidWebviewTest

Review URL: https://codereview.chromium.org/273873003

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@271411 0039d316-1c4b-4281-b951-d872f2087c98
parent 9a024901
...@@ -4,6 +4,11 @@ ...@@ -4,6 +4,11 @@
package org.chromium.android_webview; package org.chromium.android_webview;
import android.os.Handler;
import android.os.Looper;
import android.webkit.ValueCallback;
import org.chromium.base.CalledByNative;
import org.chromium.base.JNINamespace; import org.chromium.base.JNINamespace;
/** /**
...@@ -13,6 +18,22 @@ import org.chromium.base.JNINamespace; ...@@ -13,6 +18,22 @@ import org.chromium.base.JNINamespace;
*/ */
@JNINamespace("android_webview") @JNINamespace("android_webview")
public final class AwCookieManager { public final class AwCookieManager {
// TODO(hjd): remove after landing android update to use new calls.
public void removeExpiredCookie() {
removeExpiredCookies();
}
// TODO(hjd): remove after landing android update to use new calls.
public void removeAllCookie() {
removeAllCookies();
}
// TODO(hjd): remove after landing android update to use new calls.
public void removeSessionCookie() {
removeSessionCookies();
}
/** /**
* Control whether cookie is enabled or disabled * Control whether cookie is enabled or disabled
* @param accept TRUE if accept cookie * @param accept TRUE if accept cookie
...@@ -45,15 +66,43 @@ public final class AwCookieManager { ...@@ -45,15 +66,43 @@ public final class AwCookieManager {
return nativeAcceptThirdPartyCookie(); return nativeAcceptThirdPartyCookie();
} }
/**
* Synchronous version of setCookie.
*/
public void setCookie(String url, String value) {
nativeSetCookieSync(url, value);
}
/**
* Deprecated synchronous version of removeSessionCookies.
*/
public void removeSessionCookies() {
nativeRemoveSessionCookiesSync();
}
/**
* Deprecated synchronous version of removeAllCookies.
*/
public void removeAllCookies() {
nativeRemoveAllCookiesSync();
}
/** /**
* Set cookie for a given url. The old cookie with same host/path/name will * Set cookie for a given url. The old cookie with same host/path/name will
* be removed. The new cookie will be added if it is not expired or it does * be removed. The new cookie will be added if it is not expired or it does
* not have expiration which implies it is session cookie. * not have expiration which implies it is session cookie.
* @param url The url which cookie is set for * @param url The url which cookie is set for.
* @param value The value for set-cookie: in http response header * @param value The value for set-cookie: in http response header.
* @param callback A callback called with the success status after the cookie is set.
*/ */
public void setCookie(final String url, final String value) { public void setCookie(final String url, final String value,
nativeSetCookie(url, value); final ValueCallback<Boolean> callback) {
try {
nativeSetCookie(url, value, CookieCallback.convert(callback));
} catch (IllegalStateException e) {
throw new IllegalStateException(
"SetCookie must be called on a thread with a running Looper.");
}
} }
/** /**
...@@ -69,17 +118,31 @@ public final class AwCookieManager { ...@@ -69,17 +118,31 @@ public final class AwCookieManager {
} }
/** /**
* Remove all session cookies, which are cookies without expiration date * Remove all session cookies, the cookies without an expiration date.
* The value of the callback is true iff at least one cookie was removed.
* @param callback A callback called after the cookies (if any) are removed.
*/ */
public void removeSessionCookie() { public void removeSessionCookies(ValueCallback<Boolean> callback) {
nativeRemoveSessionCookie(); try {
nativeRemoveSessionCookies(CookieCallback.convert(callback));
} catch (IllegalStateException e) {
throw new IllegalStateException(
"removeSessionCookies must be called on a thread with a running Looper.");
}
} }
/** /**
* Remove all cookies * Remove all cookies.
* The value of the callback is true iff at least one cookie was removed.
* @param callback A callback called after the cookies (if any) are removed.
*/ */
public void removeAllCookie() { public void removeAllCookies(ValueCallback<Boolean> callback) {
nativeRemoveAllCookie(); try {
nativeRemoveAllCookies(CookieCallback.convert(callback));
} catch (IllegalStateException e) {
throw new IllegalStateException(
"removeAllCookies must be called on a thread with a running Looper.");
}
} }
/** /**
...@@ -92,8 +155,8 @@ public final class AwCookieManager { ...@@ -92,8 +155,8 @@ public final class AwCookieManager {
/** /**
* Remove all expired cookies * Remove all expired cookies
*/ */
public void removeExpiredCookie() { public void removeExpiredCookies() {
nativeRemoveExpiredCookie(); nativeRemoveExpiredCookies();
} }
public void flushCookieStore() { public void flushCookieStore() {
...@@ -120,18 +183,67 @@ public final class AwCookieManager { ...@@ -120,18 +183,67 @@ public final class AwCookieManager {
nativeSetAcceptFileSchemeCookies(accept); nativeSetAcceptFileSchemeCookies(accept);
} }
@CalledByNative
public static void invokeBooleanCookieCallback(CookieCallback<Boolean> callback,
boolean result) {
callback.onReceiveValue(result);
}
/**
* CookieCallback is a bridge that knows how to call a ValueCallback on its original thread.
* We need to arrange for the users ValueCallback#onReceiveValue to be called on the original
* thread after the work is done. When the API is called we construct a CookieCallback which
* remembers the handler of the current thread. Later the native code uses
* invokeBooleanCookieCallback to call CookieCallback#onReceiveValue which posts a Runnable
* on the handler of the original thread which in turn calls ValueCallback#onReceiveValue.
*/
private static class CookieCallback<T> {
ValueCallback<T> mCallback;
Handler mHandler;
public CookieCallback(ValueCallback<T> callback, Handler handler) {
mCallback = callback;
mHandler = handler;
}
public static<T> CookieCallback<T> convert(ValueCallback<T> callback) throws
IllegalStateException {
if (callback == null) {
return null;
}
if (Looper.myLooper() == null) {
throw new IllegalStateException(
"CookieCallback.convert should be called on a thread with a running Looper.");
}
return new CookieCallback<T>(callback, new Handler());
}
public void onReceiveValue(final T t) {
mHandler.post(new Runnable() {
@Override
public void run() {
mCallback.onReceiveValue(t);
}
});
}
}
private native void nativeSetAcceptCookie(boolean accept); private native void nativeSetAcceptCookie(boolean accept);
private native boolean nativeAcceptCookie(); private native boolean nativeAcceptCookie();
private native void nativeSetAcceptThirdPartyCookie(boolean accept); private native void nativeSetAcceptThirdPartyCookie(boolean accept);
private native boolean nativeAcceptThirdPartyCookie(); private native boolean nativeAcceptThirdPartyCookie();
private native void nativeSetCookie(String url, String value); private native void nativeSetCookie(String url, String value,
CookieCallback<Boolean> callback);
private native void nativeSetCookieSync(String url, String value);
private native String nativeGetCookie(String url); private native String nativeGetCookie(String url);
private native void nativeRemoveSessionCookie(); private native void nativeRemoveSessionCookies(CookieCallback<Boolean> callback);
private native void nativeRemoveAllCookie(); private native void nativeRemoveSessionCookiesSync();
private native void nativeRemoveExpiredCookie(); private native void nativeRemoveAllCookies(CookieCallback<Boolean> callback);
private native void nativeRemoveAllCookiesSync();
private native void nativeRemoveExpiredCookies();
private native void nativeFlushCookieStore(); private native void nativeFlushCookieStore();
private native boolean nativeHasCookies(); private native boolean nativeHasCookies();
......
...@@ -6,11 +6,13 @@ package org.chromium.android_webview.test; ...@@ -6,11 +6,13 @@ package org.chromium.android_webview.test;
import android.content.Context; import android.content.Context;
import android.test.suitebuilder.annotation.MediumTest; import android.test.suitebuilder.annotation.MediumTest;
import android.test.suitebuilder.annotation.SmallTest;
import org.chromium.android_webview.AwBrowserProcess; import org.chromium.android_webview.AwBrowserProcess;
import org.chromium.android_webview.AwContents; import org.chromium.android_webview.AwContents;
import org.chromium.android_webview.AwCookieManager; import org.chromium.android_webview.AwCookieManager;
import org.chromium.android_webview.test.util.CommonResources; import org.chromium.android_webview.test.util.CommonResources;
import org.chromium.android_webview.test.util.CookieUtils;
import org.chromium.base.test.util.Feature; import org.chromium.base.test.util.Feature;
import org.chromium.content.app.ContentMain; import org.chromium.content.app.ContentMain;
import org.chromium.net.test.util.TestWebServer; import org.chromium.net.test.util.TestWebServer;
...@@ -64,10 +66,11 @@ public class CookieManagerStartupTest extends AwTestBase { ...@@ -64,10 +66,11 @@ public class CookieManagerStartupTest extends AwTestBase {
String path = "/cookie_test.html"; String path = "/cookie_test.html";
String url = webServer.setResponse(path, CommonResources.ABOUT_HTML, null); String url = webServer.setResponse(path, CommonResources.ABOUT_HTML, null);
CookieUtils.clearCookies(this, mCookieManager);
mCookieManager.setAcceptCookie(true); mCookieManager.setAcceptCookie(true);
mCookieManager.removeAllCookie();
assertTrue(mCookieManager.acceptCookie()); assertTrue(mCookieManager.acceptCookie());
assertFalse(mCookieManager.hasCookies());
mCookieManager.setCookie(url, "count=41"); mCookieManager.setCookie(url, "count=41");
startChromium(); startChromium();
...@@ -83,4 +86,23 @@ public class CookieManagerStartupTest extends AwTestBase { ...@@ -83,4 +86,23 @@ public class CookieManagerStartupTest extends AwTestBase {
} }
} }
@SmallTest
@Feature({"AndroidWebView", "Privacy"})
public void testAllowFileSchemeCookies() throws Throwable {
assertFalse(mCookieManager.allowFileSchemeCookies());
mCookieManager.setAcceptFileSchemeCookies(true);
assertTrue(mCookieManager.allowFileSchemeCookies());
mCookieManager.setAcceptFileSchemeCookies(false);
assertFalse(mCookieManager.allowFileSchemeCookies());
}
@SmallTest
@Feature({"AndroidWebView", "Privacy"})
public void testAllowCookies() throws Throwable {
assertTrue(mCookieManager.acceptCookie());
mCookieManager.setAcceptCookie(false);
assertFalse(mCookieManager.acceptCookie());
mCookieManager.setAcceptCookie(true);
assertTrue(mCookieManager.acceptCookie());
}
} }
// Copyright 2014 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.android_webview.test.util;
import android.webkit.ValueCallback;
import junit.framework.Assert;
import org.chromium.android_webview.AwCookieManager;
import org.chromium.android_webview.test.AwTestBase;
import org.chromium.content.browser.test.util.CallbackHelper;
/**
* Useful functions for testing the CookieManager.
*/
public class CookieUtils {
private CookieUtils() {
}
/**
* A CallbackHelper for use with setCookie/removeXXXCookie.
*/
public static class TestValueCallback<T> implements ValueCallback<T> {
/**
* We only have one intresting method on ValueCallback: onReceiveValue.
*/
public static class OnReceiveValueHelper<T> extends CallbackHelper {
private T mValue;
public T getValue() {
assert getCallCount() > 0;
return mValue;
}
public void notifyCalled(T value) {
mValue = value;
notifyCalled();
}
}
private OnReceiveValueHelper<T> mOnReceiveValueHelper;
public TestValueCallback() {
mOnReceiveValueHelper = new OnReceiveValueHelper<T>();
}
public OnReceiveValueHelper getOnReceiveValueHelper() {
return mOnReceiveValueHelper;
}
@Override
public void onReceiveValue(T value) {
mOnReceiveValueHelper.notifyCalled(value);
}
public T getValue() {
return mOnReceiveValueHelper.getValue();
}
}
/**
* Clear all cookies from the CookieManager synchronously then assert they are gone.
* @param cookieManager the CookieManager on which to remove cookies.
* @param timeoutMs the timeout in milliseconds for waiting for the callback to complete.
*/
public static void clearCookies(AwTestBase awTestBase, final AwCookieManager cookieManager)
throws Throwable {
final TestValueCallback<Boolean> callback = new TestValueCallback<Boolean>();
int callCount = callback.getOnReceiveValueHelper().getCallCount();
awTestBase.runTestOnUiThread(new Runnable() {
@Override
public void run() {
cookieManager.removeAllCookies(callback);
}
});
callback.getOnReceiveValueHelper().waitForCallback(callCount);
Assert.assertFalse(cookieManager.hasCookies());
}
}
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment