1 // Copyright 2012 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 package org.chromium.android_webview; 6 7 import android.os.Handler; 8 import android.os.Looper; 9 import android.webkit.ValueCallback; 10 11 import org.chromium.base.CalledByNative; 12 import org.chromium.base.JNINamespace; 13 14 /** 15 * AwCookieManager manages cookies according to RFC2109 spec. 16 * 17 * Methods in this class are thread safe. 18 */ 19 @JNINamespace("android_webview") 20 public final class AwCookieManager { 21 22 // TODO(hjd): remove after landing android update to use new calls. removeExpiredCookie()23 public void removeExpiredCookie() { 24 removeExpiredCookies(); 25 } 26 27 // TODO(hjd): remove after landing android update to use new calls. removeAllCookie()28 public void removeAllCookie() { 29 removeAllCookies(); 30 } 31 32 // TODO(hjd): remove after landing android update to use new calls. removeSessionCookie()33 public void removeSessionCookie() { 34 removeSessionCookies(); 35 } 36 37 /** 38 * Control whether cookie is enabled or disabled 39 * @param accept TRUE if accept cookie 40 */ setAcceptCookie(boolean accept)41 public void setAcceptCookie(boolean accept) { 42 nativeSetShouldAcceptCookies(accept); 43 } 44 45 /** 46 * Return whether cookie is enabled 47 * @return TRUE if accept cookie 48 */ acceptCookie()49 public boolean acceptCookie() { 50 return nativeGetShouldAcceptCookies(); 51 } 52 53 /** 54 * Synchronous version of setCookie. 55 */ setCookie(String url, String value)56 public void setCookie(String url, String value) { 57 nativeSetCookieSync(url, value); 58 } 59 60 /** 61 * Deprecated synchronous version of removeSessionCookies. 62 */ removeSessionCookies()63 public void removeSessionCookies() { 64 nativeRemoveSessionCookiesSync(); 65 } 66 67 /** 68 * Deprecated synchronous version of removeAllCookies. 69 */ removeAllCookies()70 public void removeAllCookies() { 71 nativeRemoveAllCookiesSync(); 72 } 73 74 /** 75 * Set cookie for a given url. The old cookie with same host/path/name will 76 * be removed. The new cookie will be added if it is not expired or it does 77 * not have expiration which implies it is session cookie. 78 * @param url The url which cookie is set for. 79 * @param value The value for set-cookie: in http response header. 80 * @param callback A callback called with the success status after the cookie is set. 81 */ setCookie(final String url, final String value, final ValueCallback<Boolean> callback)82 public void setCookie(final String url, final String value, 83 final ValueCallback<Boolean> callback) { 84 try { 85 nativeSetCookie(url, value, CookieCallback.convert(callback)); 86 } catch (IllegalStateException e) { 87 throw new IllegalStateException( 88 "SetCookie must be called on a thread with a running Looper."); 89 } 90 } 91 92 /** 93 * Get cookie(s) for a given url so that it can be set to "cookie:" in http 94 * request header. 95 * @param url The url needs cookie 96 * @return The cookies in the format of NAME=VALUE [; NAME=VALUE] 97 */ getCookie(final String url)98 public String getCookie(final String url) { 99 String cookie = nativeGetCookie(url.toString()); 100 // Return null if the string is empty to match legacy behavior 101 return cookie == null || cookie.trim().isEmpty() ? null : cookie; 102 } 103 104 /** 105 * Remove all session cookies, the cookies without an expiration date. 106 * The value of the callback is true iff at least one cookie was removed. 107 * @param callback A callback called after the cookies (if any) are removed. 108 */ removeSessionCookies(ValueCallback<Boolean> callback)109 public void removeSessionCookies(ValueCallback<Boolean> callback) { 110 try { 111 nativeRemoveSessionCookies(CookieCallback.convert(callback)); 112 } catch (IllegalStateException e) { 113 throw new IllegalStateException( 114 "removeSessionCookies must be called on a thread with a running Looper."); 115 } 116 } 117 118 /** 119 * Remove all cookies. 120 * The value of the callback is true iff at least one cookie was removed. 121 * @param callback A callback called after the cookies (if any) are removed. 122 */ removeAllCookies(ValueCallback<Boolean> callback)123 public void removeAllCookies(ValueCallback<Boolean> callback) { 124 try { 125 nativeRemoveAllCookies(CookieCallback.convert(callback)); 126 } catch (IllegalStateException e) { 127 throw new IllegalStateException( 128 "removeAllCookies must be called on a thread with a running Looper."); 129 } 130 } 131 132 /** 133 * Return true if there are stored cookies. 134 */ hasCookies()135 public boolean hasCookies() { 136 return nativeHasCookies(); 137 } 138 139 /** 140 * Remove all expired cookies 141 */ removeExpiredCookies()142 public void removeExpiredCookies() { 143 nativeRemoveExpiredCookies(); 144 } 145 flushCookieStore()146 public void flushCookieStore() { 147 nativeFlushCookieStore(); 148 } 149 150 /** 151 * Whether cookies are accepted for file scheme URLs. 152 */ allowFileSchemeCookies()153 public boolean allowFileSchemeCookies() { 154 return nativeAllowFileSchemeCookies(); 155 } 156 157 /** 158 * Sets whether cookies are accepted for file scheme URLs. 159 * 160 * Use of cookies with file scheme URLs is potentially insecure. Do not use this feature unless 161 * you can be sure that no unintentional sharing of cookie data can take place. 162 * <p> 163 * Note that calls to this method will have no effect if made after a WebView or CookieManager 164 * instance has been created. 165 */ setAcceptFileSchemeCookies(boolean accept)166 public void setAcceptFileSchemeCookies(boolean accept) { 167 nativeSetAcceptFileSchemeCookies(accept); 168 } 169 170 @CalledByNative invokeBooleanCookieCallback(CookieCallback<Boolean> callback, boolean result)171 public static void invokeBooleanCookieCallback(CookieCallback<Boolean> callback, 172 boolean result) { 173 callback.onReceiveValue(result); 174 } 175 176 /** 177 * CookieCallback is a bridge that knows how to call a ValueCallback on its original thread. 178 * We need to arrange for the users ValueCallback#onReceiveValue to be called on the original 179 * thread after the work is done. When the API is called we construct a CookieCallback which 180 * remembers the handler of the current thread. Later the native code uses 181 * invokeBooleanCookieCallback to call CookieCallback#onReceiveValue which posts a Runnable 182 * on the handler of the original thread which in turn calls ValueCallback#onReceiveValue. 183 */ 184 private static class CookieCallback<T> { 185 ValueCallback<T> mCallback; 186 Handler mHandler; 187 CookieCallback(ValueCallback<T> callback, Handler handler)188 public CookieCallback(ValueCallback<T> callback, Handler handler) { 189 mCallback = callback; 190 mHandler = handler; 191 } 192 convert(ValueCallback<T> callback)193 public static<T> CookieCallback<T> convert(ValueCallback<T> callback) throws 194 IllegalStateException { 195 if (callback == null) { 196 return null; 197 } 198 if (Looper.myLooper() == null) { 199 throw new IllegalStateException( 200 "CookieCallback.convert should be called on a thread with a running Looper."); 201 } 202 return new CookieCallback<T>(callback, new Handler()); 203 } 204 onReceiveValue(final T t)205 public void onReceiveValue(final T t) { 206 mHandler.post(new Runnable() { 207 @Override 208 public void run() { 209 mCallback.onReceiveValue(t); 210 } 211 }); 212 } 213 } 214 nativeSetShouldAcceptCookies(boolean accept)215 private native void nativeSetShouldAcceptCookies(boolean accept); nativeGetShouldAcceptCookies()216 private native boolean nativeGetShouldAcceptCookies(); 217 nativeSetCookie(String url, String value, CookieCallback<Boolean> callback)218 private native void nativeSetCookie(String url, String value, 219 CookieCallback<Boolean> callback); nativeSetCookieSync(String url, String value)220 private native void nativeSetCookieSync(String url, String value); nativeGetCookie(String url)221 private native String nativeGetCookie(String url); 222 nativeRemoveSessionCookies(CookieCallback<Boolean> callback)223 private native void nativeRemoveSessionCookies(CookieCallback<Boolean> callback); nativeRemoveSessionCookiesSync()224 private native void nativeRemoveSessionCookiesSync(); nativeRemoveAllCookies(CookieCallback<Boolean> callback)225 private native void nativeRemoveAllCookies(CookieCallback<Boolean> callback); nativeRemoveAllCookiesSync()226 private native void nativeRemoveAllCookiesSync(); nativeRemoveExpiredCookies()227 private native void nativeRemoveExpiredCookies(); nativeFlushCookieStore()228 private native void nativeFlushCookieStore(); 229 nativeHasCookies()230 private native boolean nativeHasCookies(); 231 nativeAllowFileSchemeCookies()232 private native boolean nativeAllowFileSchemeCookies(); nativeSetAcceptFileSchemeCookies(boolean accept)233 private native void nativeSetAcceptFileSchemeCookies(boolean accept); 234 } 235