1/* 2 * Copyright 2010, The Android Open Source Project 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * * Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24 */ 25 26#include "config.h" 27 28#include "ChromiumIncludes.h" 29#include "WebCookieJar.h" 30#include "WebCoreJni.h" 31#include <JNIHelp.h> 32 33using namespace base; 34using namespace net; 35 36namespace android { 37 38// JNI for android.webkit.CookieManager 39static const char* javaCookieManagerClass = "android/webkit/CookieManager"; 40 41static bool acceptCookie(JNIEnv*, jobject) 42{ 43#if USE(CHROME_NETWORK_STACK) 44 // This is a static method which gets the cookie policy for all WebViews. We 45 // always apply the same configuration to the contexts for both regular and 46 // private browsing, so expect the same result here. 47 bool regularAcceptCookies = WebCookieJar::get(false)->allowCookies(); 48 ASSERT(regularAcceptCookies == WebCookieJar::get(true)->allowCookies()); 49 return regularAcceptCookies; 50#else 51 // The Android HTTP stack is implemented Java-side. 52 ASSERT_NOT_REACHED(); 53 return false; 54#endif 55} 56 57static jstring getCookie(JNIEnv* env, jobject, jstring url, jboolean privateBrowsing) 58{ 59#if USE(CHROME_NETWORK_STACK) 60 GURL gurl(jstringToStdString(env, url)); 61 CookieOptions options; 62 options.set_include_httponly(); 63 std::string cookies = WebCookieJar::get(privateBrowsing)->cookieStore()->GetCookieMonster()->GetCookiesWithOptions(gurl, options); 64 return stdStringToJstring(env, cookies); 65#else 66 // The Android HTTP stack is implemented Java-side. 67 ASSERT_NOT_REACHED(); 68 return jstring(); 69#endif 70} 71 72static bool hasCookies(JNIEnv*, jobject, jboolean privateBrowsing) 73{ 74#if USE(CHROME_NETWORK_STACK) 75 return WebCookieJar::get(privateBrowsing)->getNumCookiesInDatabase() > 0; 76#else 77 // The Android HTTP stack is implemented Java-side. 78 ASSERT_NOT_REACHED(); 79 return false; 80#endif 81} 82 83static void removeAllCookie(JNIEnv*, jobject) 84{ 85#if USE(CHROME_NETWORK_STACK) 86 WebCookieJar::get(false)->cookieStore()->GetCookieMonster()->DeleteAll(true); 87 // This will lazily create a new private browsing context. However, if the 88 // context doesn't already exist, there's no need to create it, as cookies 89 // for such contexts are cleared up when we're done with them. 90 // TODO: Consider adding an optimisation to not create the context if it 91 // doesn't already exist. 92 WebCookieJar::get(true)->cookieStore()->GetCookieMonster()->DeleteAll(true); 93 94 // The Java code removes cookies directly from the backing database, so we do the same, 95 // but with a NULL callback so it's asynchronous. 96 WebCookieJar::get(true)->cookieStore()->GetCookieMonster()->FlushStore(NULL); 97#endif 98} 99 100static void removeExpiredCookie(JNIEnv*, jobject) 101{ 102#if USE(CHROME_NETWORK_STACK) 103 // This simply forces a GC. The getters delete expired cookies so won't return expired cookies anyway. 104 WebCookieJar::get(false)->cookieStore()->GetCookieMonster()->GetAllCookies(); 105 WebCookieJar::get(true)->cookieStore()->GetCookieMonster()->GetAllCookies(); 106#endif 107} 108 109static void removeSessionCookies(WebCookieJar* cookieJar) 110{ 111#if USE(CHROME_NETWORK_STACK) 112 CookieMonster* cookieMonster = cookieJar->cookieStore()->GetCookieMonster(); 113 CookieList cookies = cookieMonster->GetAllCookies(); 114 for (CookieList::const_iterator iter = cookies.begin(); iter != cookies.end(); ++iter) { 115 if (iter->IsSessionCookie()) 116 cookieMonster->DeleteCanonicalCookie(*iter); 117 } 118#endif 119} 120 121static void removeSessionCookie(JNIEnv*, jobject) 122{ 123#if USE(CHROME_NETWORK_STACK) 124 removeSessionCookies(WebCookieJar::get(false)); 125 removeSessionCookies(WebCookieJar::get(true)); 126#endif 127} 128 129static void setAcceptCookie(JNIEnv*, jobject, jboolean accept) 130{ 131#if USE(CHROME_NETWORK_STACK) 132 // This is a static method which configures the cookie policy for all 133 // WebViews, so we configure the contexts for both regular and private 134 // browsing. 135 WebCookieJar::get(false)->setAllowCookies(accept); 136 WebCookieJar::get(true)->setAllowCookies(accept); 137#endif 138} 139 140static void setCookie(JNIEnv* env, jobject, jstring url, jstring value, jboolean privateBrowsing) 141{ 142#if USE(CHROME_NETWORK_STACK) 143 GURL gurl(jstringToStdString(env, url)); 144 std::string line(jstringToStdString(env, value)); 145 CookieOptions options; 146 options.set_include_httponly(); 147 WebCookieJar::get(privateBrowsing)->cookieStore()->GetCookieMonster()->SetCookieWithOptions(gurl, line, options); 148#endif 149} 150 151static void flushCookieStore(JNIEnv*, jobject) 152{ 153#if USE(CHROME_NETWORK_STACK) 154 WebCookieJar::flush(); 155#endif 156} 157 158static bool acceptFileSchemeCookies(JNIEnv*, jobject) 159{ 160#if USE(CHROME_NETWORK_STACK) 161 return WebCookieJar::acceptFileSchemeCookies(); 162#else 163 // File scheme cookies are always accepted with the Android HTTP stack. 164 return true; 165#endif 166} 167 168static void setAcceptFileSchemeCookies(JNIEnv*, jobject, jboolean accept) 169{ 170#if USE(CHROME_NETWORK_STACK) 171 WebCookieJar::setAcceptFileSchemeCookies(accept); 172#else 173 // File scheme cookies are always accepted with the Android HTTP stack. 174#endif 175} 176 177static JNINativeMethod gCookieManagerMethods[] = { 178 { "nativeAcceptCookie", "()Z", (void*) acceptCookie }, 179 { "nativeGetCookie", "(Ljava/lang/String;Z)Ljava/lang/String;", (void*) getCookie }, 180 { "nativeHasCookies", "(Z)Z", (void*) hasCookies }, 181 { "nativeRemoveAllCookie", "()V", (void*) removeAllCookie }, 182 { "nativeRemoveExpiredCookie", "()V", (void*) removeExpiredCookie }, 183 { "nativeRemoveSessionCookie", "()V", (void*) removeSessionCookie }, 184 { "nativeSetAcceptCookie", "(Z)V", (void*) setAcceptCookie }, 185 { "nativeSetCookie", "(Ljava/lang/String;Ljava/lang/String;Z)V", (void*) setCookie }, 186 { "nativeFlushCookieStore", "()V", (void*) flushCookieStore }, 187 { "nativeAcceptFileSchemeCookies", "()Z", (void*) acceptFileSchemeCookies }, 188 { "nativeSetAcceptFileSchemeCookies", "(Z)V", (void*) setAcceptFileSchemeCookies }, 189}; 190 191int registerCookieManager(JNIEnv* env) 192{ 193#ifndef NDEBUG 194 jclass cookieManager = env->FindClass(javaCookieManagerClass); 195 LOG_ASSERT(cookieManager, "Unable to find class"); 196 env->DeleteLocalRef(cookieManager); 197#endif 198 return jniRegisterNativeMethods(env, javaCookieManagerClass, gCookieManagerMethods, NELEM(gCookieManagerMethods)); 199} 200 201} // namespace android 202