summaryrefslogtreecommitdiffstats
path: root/Source/WebKit/android/jni/CacheManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'Source/WebKit/android/jni/CacheManager.cpp')
-rw-r--r--Source/WebKit/android/jni/CacheManager.cpp143
1 files changed, 143 insertions, 0 deletions
diff --git a/Source/WebKit/android/jni/CacheManager.cpp b/Source/WebKit/android/jni/CacheManager.cpp
new file mode 100644
index 0000000..144b62a
--- /dev/null
+++ b/Source/WebKit/android/jni/CacheManager.cpp
@@ -0,0 +1,143 @@
+/*
+ * Copyright 2011, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+
+#if USE(CHROME_NETWORK_STACK)
+
+#include "ChromiumIncludes.h"
+#include "WebCache.h"
+#include "WebCoreJni.h"
+
+#include <JNIHelp.h>
+#include <platform/FileSystem.h>
+#include <platform/text/Base64.h>
+#include <wtf/text/CString.h>
+#include <wtf/text/WTFString.h>
+
+using namespace WebCore;
+using namespace base;
+using namespace disk_cache;
+using namespace net;
+using namespace std;
+
+namespace android {
+
+// JNI for android.webkit.CacheManager
+static const char* javaCacheManagerClass = "android/webkit/CacheManager";
+
+static void setStringField(JNIEnv* env, const jobject& object, const jfieldID& field, const String& str)
+{
+ jstring jstr = wtfStringToJstring(env, str);
+ env->SetObjectField(object, field, jstr);
+ env->DeleteLocalRef(jstr);
+}
+
+static void setFieldFromHeaderIfPresent(CacheResult* result, const char* header, JNIEnv* env, const jobject& object, const jfieldID& field, bool allowEmptyString)
+{
+ String value;
+ if (result->firstResponseHeader(header, &value, allowEmptyString))
+ setStringField(env, object, field, value);
+}
+
+static String getCacheFileBaseDir(JNIEnv* env)
+{
+ static String baseDir;
+ if (baseDir.isEmpty()) {
+ jclass cacheManagerClass = env->FindClass("android/webkit/CacheManager");
+ jmethodID getCacheFileBaseDirMethod = env->GetStaticMethodID(cacheManagerClass, "getCacheFileBaseDir", "()Ljava/io/File;");
+ jclass fileClass = env->FindClass("java/io/File");
+ jmethodID getPathMethod = env->GetMethodID(fileClass, "getPath", "()Ljava/lang/String;");
+ jobject fileObject = env->CallStaticObjectMethod(cacheManagerClass, getCacheFileBaseDirMethod);
+ baseDir = jstringToWtfString(env, static_cast<jstring>(env->CallObjectMethod(fileObject, getPathMethod)));
+ }
+ return baseDir;
+}
+
+static jobject getCacheResult(JNIEnv* env, jobject, jstring url)
+{
+ // This is called on the UI thread.
+ scoped_refptr<CacheResult> result = WebCache::get(false /*privateBrowsing*/)->getCacheResult(jstringToWtfString(env, url));
+ if (!result)
+ return 0;
+
+ // We create and populate a file with the cache entry. This allows us to
+ // replicate the behaviour of the Android HTTP stack in the Java
+ // CacheManager, which opens the cache file and provides an input stream to
+ // the file as part of the Java CacheResult object!
+ String urlWtfString = jstringToWtfString(env, url);
+ Vector<char> encodedUrl;
+ base64Encode(urlWtfString.utf8().data(), urlWtfString.length(), encodedUrl, false /*insertLFs*/);
+ String filePath = pathByAppendingComponent(getCacheFileBaseDir(env), encodedUrl.data());
+ if (!result->writeToFile(filePath))
+ return 0;
+
+ jclass cacheResultClass = env->FindClass("android/webkit/CacheManager$CacheResult");
+ jmethodID constructor = env->GetMethodID(cacheResultClass, "<init>", "()V");
+ // We only bother with the fields that are made accessible through the public API.
+ jfieldID contentdispositionField = env->GetFieldID(cacheResultClass, "contentdisposition", "Ljava/lang/String;");
+ jfieldID contentLengthField = env->GetFieldID(cacheResultClass, "contentLength", "J");
+ jfieldID etagField = env->GetFieldID(cacheResultClass, "etag", "Ljava/lang/String;");
+ jfieldID encodingField = env->GetFieldID(cacheResultClass, "encoding", "Ljava/lang/String;");
+ jfieldID expiresField = env->GetFieldID(cacheResultClass, "expires", "J");
+ jfieldID expiresStringField = env->GetFieldID(cacheResultClass, "expiresString", "Ljava/lang/String;");
+ jfieldID httpStatusCodeField = env->GetFieldID(cacheResultClass, "httpStatusCode", "I");
+ jfieldID lastModifiedField = env->GetFieldID(cacheResultClass, "lastModified", "Ljava/lang/String;");
+ jfieldID localPathField = env->GetFieldID(cacheResultClass, "localPath", "Ljava/lang/String;");
+ jfieldID locationField = env->GetFieldID(cacheResultClass, "location", "Ljava/lang/String;");
+ jfieldID mimeTypeField = env->GetFieldID(cacheResultClass, "mimeType", "Ljava/lang/String;");
+
+ jobject javaResult = env->NewObject(cacheResultClass, constructor);
+ setFieldFromHeaderIfPresent(result.get(), "content-disposition", env, javaResult, contentdispositionField, true);
+ env->SetLongField(javaResult, contentLengthField, result->contentSize());
+ setFieldFromHeaderIfPresent(result.get(), "etag", env, javaResult, etagField, false);
+ setStringField(env, javaResult, encodingField, "TODO"); // TODO: Where does the Android stack set this?
+ env->SetLongField(javaResult, expiresField, result->expires());
+ env->SetIntField(javaResult, httpStatusCodeField, result->responseCode());
+ setFieldFromHeaderIfPresent(result.get(), "last-modified", env, javaResult, lastModifiedField, false);
+ setStringField(env, javaResult, localPathField, encodedUrl.data());
+ setFieldFromHeaderIfPresent(result.get(), "location", env, javaResult, locationField, false);
+ setStringField(env, javaResult, mimeTypeField, result->mimeType());
+
+ return javaResult;
+}
+
+static JNINativeMethod gCacheManagerMethods[] = {
+ { "nativeGetCacheResult", "(Ljava/lang/String;)Landroid/webkit/CacheManager$CacheResult;", (void*) getCacheResult },
+};
+
+int registerCacheManager(JNIEnv* env)
+{
+#ifndef NDEBUG
+ jclass cacheManager = env->FindClass(javaCacheManagerClass);
+ LOG_ASSERT(cacheManager, "Unable to find class");
+ env->DeleteLocalRef(cacheManager);
+#endif
+ return jniRegisterNativeMethods(env, javaCacheManagerClass, gCacheManagerMethods, NELEM(gCacheManagerMethods));
+}
+
+} // namespace android
+
+#endif // USE(CHROME_NETWORK_STACK)