CacheManager.cpp revision 6dd76b804786ec760bb04b137a6bf017064226dc
1bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block/* 2bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * Copyright 2011, The Android Open Source Project 3bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * 4bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * Redistribution and use in source and binary forms, with or without 5bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * modification, are permitted provided that the following conditions 6bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * are met: 7bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * * Redistributions of source code must retain the above copyright 8bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * notice, this list of conditions and the following disclaimer. 9bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * * Redistributions in binary form must reproduce the above copyright 10bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * notice, this list of conditions and the following disclaimer in the 11bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * documentation and/or other materials provided with the distribution. 12bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * 13bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY 14bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 16bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 17bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 18bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 19bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 20bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY 21bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 22bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 23bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 24bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block */ 25bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block 26bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block#include "config.h" 27bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block 28bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block#if USE(CHROME_NETWORK_STACK) 29bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block 30bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block#include "ChromiumIncludes.h" 31bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block#include "WebCache.h" 32bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block#include "WebCoreJni.h" 33bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block 34bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block#include <JNIHelp.h> 35bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block#include <platform/FileSystem.h> 36bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block#include <platform/text/Base64.h> 37bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block#include <wtf/text/CString.h> 38bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block#include <wtf/text/WTFString.h> 39bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block 40bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Blockusing namespace WebCore; 41bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Blockusing namespace base; 42bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Blockusing namespace disk_cache; 43bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Blockusing namespace net; 44bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Blockusing namespace std; 45bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block 46bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Blocknamespace android { 47bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block 48bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block// JNI for android.webkit.CacheManager 49bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Blockstatic const char* javaCacheManagerClass = "android/webkit/CacheManager"; 50bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block 51bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Blockstatic void setStringField(JNIEnv* env, const jobject& object, const jfieldID& field, const String& str) 52bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block{ 53bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jstring jstr = wtfStringToJstring(env, str); 54bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block env->SetObjectField(object, field, jstr); 55bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block env->DeleteLocalRef(jstr); 56bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block} 57bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block 58bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Blockstatic void setFieldFromHeaderIfPresent(CacheResult* result, const char* header, JNIEnv* env, const jobject& object, const jfieldID& field, bool allowEmptyString) 59bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block{ 60bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block String value; 61bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block if (result->firstResponseHeader(header, &value, allowEmptyString)) 62bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block setStringField(env, object, field, value); 63bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block} 64bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block 65bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Blockstatic String getCacheFileBaseDir(JNIEnv* env) 66bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block{ 67bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block static String baseDir; 68bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block if (baseDir.isEmpty()) { 69bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jclass cacheManagerClass = env->FindClass("android/webkit/CacheManager"); 70bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jmethodID getCacheFileBaseDirMethod = env->GetStaticMethodID(cacheManagerClass, "getCacheFileBaseDir", "()Ljava/io/File;"); 71bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jclass fileClass = env->FindClass("java/io/File"); 72bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jmethodID getPathMethod = env->GetMethodID(fileClass, "getPath", "()Ljava/lang/String;"); 73bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jobject fileObject = env->CallStaticObjectMethod(cacheManagerClass, getCacheFileBaseDirMethod); 74bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block baseDir = jstringToWtfString(env, static_cast<jstring>(env->CallObjectMethod(fileObject, getPathMethod))); 75bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block } 76bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block return baseDir; 77bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block} 78bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block 79bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Blockstatic jobject getCacheResult(JNIEnv* env, jobject, jstring url) 80bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block{ 81bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block // This is called on the UI thread. 82bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block scoped_refptr<CacheResult> result = WebCache::get(false /*privateBrowsing*/)->getCacheResult(jstringToWtfString(env, url)); 83bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block if (!result) 84bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block return 0; 85bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block 86bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block // We create and populate a file with the cache entry. This allows us to 87bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block // replicate the behaviour of the Android HTTP stack in the Java 88bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block // CacheManager, which opens the cache file and provides an input stream to 89bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block // the file as part of the Java CacheResult object! 90bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block String urlWtfString = jstringToWtfString(env, url); 91bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block Vector<char> encodedUrl; 92bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block base64Encode(urlWtfString.utf8().data(), urlWtfString.length(), encodedUrl, false /*insertLFs*/); 938d55fa6a7b44dd646774f089c2b88697d9d56096Ben Murdoch encodedUrl.append('\0'); 94bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block String filePath = pathByAppendingComponent(getCacheFileBaseDir(env), encodedUrl.data()); 95bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block if (!result->writeToFile(filePath)) 96bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block return 0; 97bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block 98bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jclass cacheResultClass = env->FindClass("android/webkit/CacheManager$CacheResult"); 99bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jmethodID constructor = env->GetMethodID(cacheResultClass, "<init>", "()V"); 100bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block // We only bother with the fields that are made accessible through the public API. 101bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jfieldID contentdispositionField = env->GetFieldID(cacheResultClass, "contentdisposition", "Ljava/lang/String;"); 102bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jfieldID contentLengthField = env->GetFieldID(cacheResultClass, "contentLength", "J"); 103bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jfieldID etagField = env->GetFieldID(cacheResultClass, "etag", "Ljava/lang/String;"); 104bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jfieldID encodingField = env->GetFieldID(cacheResultClass, "encoding", "Ljava/lang/String;"); 105bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jfieldID expiresField = env->GetFieldID(cacheResultClass, "expires", "J"); 106bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jfieldID expiresStringField = env->GetFieldID(cacheResultClass, "expiresString", "Ljava/lang/String;"); 107bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jfieldID httpStatusCodeField = env->GetFieldID(cacheResultClass, "httpStatusCode", "I"); 108bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jfieldID lastModifiedField = env->GetFieldID(cacheResultClass, "lastModified", "Ljava/lang/String;"); 109bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jfieldID localPathField = env->GetFieldID(cacheResultClass, "localPath", "Ljava/lang/String;"); 110bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jfieldID locationField = env->GetFieldID(cacheResultClass, "location", "Ljava/lang/String;"); 111bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jfieldID mimeTypeField = env->GetFieldID(cacheResultClass, "mimeType", "Ljava/lang/String;"); 112bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block 113bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jobject javaResult = env->NewObject(cacheResultClass, constructor); 114bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block setFieldFromHeaderIfPresent(result.get(), "content-disposition", env, javaResult, contentdispositionField, true); 115bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block env->SetLongField(javaResult, contentLengthField, result->contentSize()); 116bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block setFieldFromHeaderIfPresent(result.get(), "etag", env, javaResult, etagField, false); 117bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block setStringField(env, javaResult, encodingField, "TODO"); // TODO: Where does the Android stack set this? 118bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block env->SetLongField(javaResult, expiresField, result->expires()); 119bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block env->SetIntField(javaResult, httpStatusCodeField, result->responseCode()); 120bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block setFieldFromHeaderIfPresent(result.get(), "last-modified", env, javaResult, lastModifiedField, false); 121bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block setStringField(env, javaResult, localPathField, encodedUrl.data()); 122bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block setFieldFromHeaderIfPresent(result.get(), "location", env, javaResult, locationField, false); 123bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block setStringField(env, javaResult, mimeTypeField, result->mimeType()); 124bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block 125bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block return javaResult; 126bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block} 127bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block 128bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Blockstatic JNINativeMethod gCacheManagerMethods[] = { 129bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block { "nativeGetCacheResult", "(Ljava/lang/String;)Landroid/webkit/CacheManager$CacheResult;", (void*) getCacheResult }, 130bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block}; 131bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block 132bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Blockint registerCacheManager(JNIEnv* env) 133bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block{ 134bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block#ifndef NDEBUG 135bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block jclass cacheManager = env->FindClass(javaCacheManagerClass); 1366dd76b804786ec760bb04b137a6bf017064226dcSteve Block ALOG_ASSERT(cacheManager, "Unable to find class"); 137bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block env->DeleteLocalRef(cacheManager); 138bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block#endif 139bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block return jniRegisterNativeMethods(env, javaCacheManagerClass, gCacheManagerMethods, NELEM(gCacheManagerMethods)); 140bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block} 141bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block 142bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block} // namespace android 143bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block 144bf16cf132cbd54cc70f003ec6f7500e3dd39dbbbSteve Block#endif // USE(CHROME_NETWORK_STACK) 145