ifeq ($(HTTP_STACK),chrome)
LOCAL_SRC_FILES := $(LOCAL_SRC_FILES) \
android/WebCoreSupport/ChromiumInit.cpp \
+ android/WebCoreSupport/CacheResult.cpp \
android/WebCoreSupport/WebCache.cpp \
android/WebCoreSupport/WebCookieJar.cpp \
android/WebCoreSupport/WebUrlLoader.cpp \
\
android/icu/unicode/ucnv.cpp \
\
+ android/jni/CacheManager.cpp \
android/jni/CookieManager.cpp \
android/jni/DeviceMotionAndOrientationManager.cpp \
android/jni/DeviceMotionClientImpl.cpp \
--- /dev/null
+/*
+ * 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"
+#include "CacheResult.h"
+
+#include "WebUrlLoaderClient.h"
+#include <platform/FileSystem.h>
+
+using namespace base;
+using namespace disk_cache;
+using namespace net;
+using namespace std;
+
+namespace android {
+
+// All public methods are called on a UI thread but we do work on the
+// Chromium thread. However, because we block the WebCore thread while this
+// work completes, we can never receive new public method calls while the
+// Chromium thread work is in progress.
+
+// Copied from HttpCache
+enum {
+ kResponseInfoIndex = 0,
+ kResponseContentIndex
+};
+
+CacheResult::CacheResult(disk_cache::Entry* entry)
+ : m_entry(entry)
+ , m_onResponseHeadersDoneCallback(this, &CacheResult::onResponseHeadersDone)
+ , m_onReadNextChunkDoneCallback(this, &CacheResult::onReadNextChunkDone)
+{
+ ASSERT(m_entry);
+}
+
+CacheResult::~CacheResult()
+{
+ m_entry->Close();
+ // TODO: Should we also call DoneReadingFromEntry() on the cache for our
+ // entry?
+}
+
+int64 CacheResult::contentSize() const
+{
+ // The android stack does not take the content length from the HTTP response
+ // headers but calculates it when writing the content to disk. It can never
+ // overflow a long because we limit the cache size.
+ return m_entry->GetDataSize(kResponseContentIndex);
+}
+
+bool CacheResult::firstResponseHeader(const char* name, String* result, bool allowEmptyString) const
+{
+ string value;
+ if (responseHeaders() && responseHeaders()->EnumerateHeader(NULL, name, &value) && (!value.empty() || allowEmptyString)) {
+ *result = String(value.c_str());
+ return true;
+ }
+ return false;
+}
+
+String CacheResult::mimeType() const
+{
+ string mimeType;
+ responseHeaders()->GetMimeType(&mimeType);
+ return String(mimeType.c_str());
+}
+
+int64 CacheResult::expires() const
+{
+ // We have to do this manually, rather than using HttpResponseHeaders::GetExpiresValue(),
+ // to handle the "-1" and "0" special cases.
+ string expiresString;
+ if (responseHeaders() && responseHeaders()->EnumerateHeader(NULL, "expires", &expiresString)) {
+ wstring expiresStringWide(expiresString.begin(), expiresString.end()); // inflate ascii
+ // We require the time expressed as ms since the epoch.
+ Time time;
+ if (Time::FromString(expiresStringWide.c_str(), &time)) {
+ // Will not overflow for a very long time!
+ return static_cast<int64>(1000.0 * time.ToDoubleT());
+ }
+
+ if (expiresString == "-1" || expiresString == "0")
+ return 0;
+ }
+
+ // TODO
+ // The Android stack applies a heuristic to set an expiry date if the
+ // expires header is not set or can't be parsed. I'm not sure whether the Chromium cache
+ // does this, and if so, it may not be possible for us to get hold of it
+ // anyway to set it on the result.
+ return -1;
+}
+
+int CacheResult::responseCode() const
+{
+ return responseHeaders() ? responseHeaders()->response_code() : 0;
+}
+
+bool CacheResult::writeToFile(const String& filePath) const
+{
+ // Getting the headers is potentially async, so post to the Chromium thread
+ // and block here.
+ MutexLocker lock(m_mutex);
+
+ base::Thread* thread = WebUrlLoaderClient::ioThread();
+ if (!thread)
+ return false;
+
+ CacheResult* me = const_cast<CacheResult*>(this);
+ thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(me, &CacheResult::writeToFileImpl));
+
+ m_filePath = filePath.threadsafeCopy();
+ m_isAsyncOperationInProgress = true;
+ while (m_isAsyncOperationInProgress)
+ m_condition.wait(m_mutex);
+
+ return m_wasWriteToFileSuccessful;
+}
+
+void CacheResult::writeToFileImpl()
+{
+ m_bufferSize = m_entry->GetDataSize(kResponseContentIndex);
+ m_readOffset = 0;
+ m_wasWriteToFileSuccessful = false;
+ readNextChunk();
+}
+
+void CacheResult::readNextChunk()
+{
+ m_buffer = new IOBuffer(m_bufferSize);
+ int rv = m_entry->ReadData(kResponseInfoIndex, m_readOffset, m_buffer, m_bufferSize, &m_onReadNextChunkDoneCallback);
+ if (rv == ERR_IO_PENDING)
+ return;
+
+ onReadNextChunkDone(rv);
+};
+
+void CacheResult::onReadNextChunkDone(int size)
+{
+ if (size > 0) {
+ // Still more reading to be done.
+ if (writeChunkToFile()) {
+ // TODO: I assume that we need to clear and resize the buffer for the next read?
+ m_readOffset += size;
+ m_bufferSize -= size;
+ readNextChunk();
+ } else
+ onWriteToFileDone();
+ return;
+ }
+
+ if (!size) {
+ // Reached end of file.
+ if (writeChunkToFile())
+ m_wasWriteToFileSuccessful = true;
+ }
+ onWriteToFileDone();
+}
+
+bool CacheResult::writeChunkToFile()
+{
+ PlatformFileHandle file;
+ file = openFile(m_filePath, OpenForWrite);
+ if (!isHandleValid(file))
+ return false;
+ return WebCore::writeToFile(file, m_buffer->data(), m_bufferSize) == m_bufferSize;
+}
+
+void CacheResult::onWriteToFileDone()
+{
+ MutexLocker lock(m_mutex);
+ m_isAsyncOperationInProgress = false;
+ m_condition.signal();
+}
+
+HttpResponseHeaders* CacheResult::responseHeaders() const
+{
+ MutexLocker lock(m_mutex);
+ if (m_responseHeaders)
+ return m_responseHeaders;
+
+ // Getting the headers is potentially async, so post to the Chromium thread
+ // and block here.
+ base::Thread* thread = WebUrlLoaderClient::ioThread();
+ if (!thread)
+ return 0;
+
+ CacheResult* me = const_cast<CacheResult*>(this);
+ thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(me, &CacheResult::responseHeadersImpl));
+
+ m_isAsyncOperationInProgress = true;
+ while (m_isAsyncOperationInProgress)
+ m_condition.wait(m_mutex);
+
+ return m_responseHeaders;
+}
+
+void CacheResult::responseHeadersImpl()
+{
+ m_bufferSize = m_entry->GetDataSize(kResponseInfoIndex);
+ m_buffer = new IOBuffer(m_bufferSize);
+
+ int rv = m_entry->ReadData(kResponseInfoIndex, 0, m_buffer, m_bufferSize, &m_onResponseHeadersDoneCallback);
+ if (rv == ERR_IO_PENDING)
+ return;
+
+ onResponseHeadersDone(rv);
+};
+
+void CacheResult::onResponseHeadersDone(int size)
+{
+ MutexLocker lock(m_mutex);
+ // It's OK to throw away the HttpResponseInfo object as we hold our own ref
+ // to the headers.
+ HttpResponseInfo response;
+ bool truncated = false; // TODO: Waht is this param for?
+ if (size == m_bufferSize && HttpCache::ParseResponseInfo(m_buffer->data(), m_bufferSize, &response, &truncated))
+ m_responseHeaders = response.headers;
+ m_isAsyncOperationInProgress = false;
+ m_condition.signal();
+}
+
+} // namespace android
--- /dev/null
+/*
+ * 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.
+ */
+
+#ifndef CacheResult_h
+#define CacheResult_h
+
+#include "ChromiumIncludes.h"
+
+#include <wtf/RefCounted.h>
+#include <wtf/ThreadingPrimitives.h>
+#include <wtf/text/WTFString.h>
+
+namespace android {
+
+// A wrapper around a disk_cache::Entry. Provides fields appropriate for constructing a Java CacheResult object.
+class CacheResult : public base::RefCountedThreadSafe<CacheResult> {
+public:
+ // Takes ownership of the Entry passed to the constructor.
+ CacheResult(disk_cache::Entry*);
+ ~CacheResult();
+
+ int64 contentSize() const;
+ bool firstResponseHeader(const char* name, WTF::String* result, bool allowEmptyString) const;
+ // The Android stack uses the empty string if no Content-Type headers are
+ // found, so we use the same default here.
+ WTF::String mimeType() const;
+ // Returns the value of the expires header as milliseconds since the epoch.
+ int64 expires() const;
+ int responseCode() const;
+ bool writeToFile(const WTF::String& filePath) const;
+private:
+ net::HttpResponseHeaders* responseHeaders() const;
+ void responseHeadersImpl();
+ void onResponseHeadersDone(int size);
+
+ void writeToFileImpl();
+ void readNextChunk();
+ void onReadNextChunkDone(int size);
+ bool writeChunkToFile();
+ void onWriteToFileDone();
+
+ disk_cache::Entry* m_entry;
+
+ scoped_refptr<net::HttpResponseHeaders> m_responseHeaders;
+
+ int m_readOffset;
+ bool m_wasWriteToFileSuccessful;
+ mutable String m_filePath;
+
+ int m_bufferSize;
+ scoped_refptr<net::IOBuffer> m_buffer;
+ mutable bool m_isAsyncOperationInProgress;
+ mutable WTF::Mutex m_mutex;
+ mutable WTF::ThreadCondition m_condition;
+
+ net::CompletionCallbackImpl<CacheResult> m_onResponseHeadersDoneCallback;
+ net::CompletionCallbackImpl<CacheResult> m_onReadNextChunkDoneCallback;
+};
+
+} // namespace android
+
+#endif
#include "WebRequestContext.h"
#include "WebUrlLoaderClient.h"
+#include <wtf/text/CString.h>
+
using namespace WTF;
+using namespace disk_cache;
using namespace net;
using namespace std;
: m_doomAllEntriesCallback(this, &WebCache::doomAllEntries)
, m_onClearDoneCallback(this, &WebCache::onClearDone)
, m_isClearInProgress(false)
+ , m_openEntryCallback(this, &WebCache::openEntry)
+ , m_onGetEntryDoneCallback(this, &WebCache::onGetEntryDone)
+ , m_isGetEntryInProgress(false)
, m_cacheBackend(0)
{
base::Thread* ioThread = WebUrlLoaderClient::ioThread();
m_isClearInProgress = false;
}
+scoped_refptr<CacheResult> WebCache::getCacheResult(String url)
+{
+ // This is called on the UI thread.
+ MutexLocker lock(m_getEntryMutex);
+ if (m_isGetEntryInProgress)
+ return 0; // TODO: OK? Or can we queue 'em up?
+
+ // The Chromium methods are asynchronous, but we need this method to be
+ // synchronous. Do the work on the Chromium thread but block this thread
+ // here waiting for the work to complete.
+ base::Thread* thread = WebUrlLoaderClient::ioThread();
+ if (!thread)
+ return 0;
+
+ m_entry = 0;
+ m_isGetEntryInProgress = true;
+ m_entryUrl = url.threadsafeCopy();
+ thread->message_loop()->PostTask(FROM_HERE, NewRunnableMethod(this, &WebCache::getEntryImpl));
+
+ while (m_isGetEntryInProgress)
+ m_getEntryCondition.wait(m_getEntryMutex);
+
+ if (!m_entry)
+ return 0;
+
+ return new CacheResult(m_entry);
+}
+
+void WebCache::getEntryImpl()
+{
+ if (!m_cacheBackend) {
+ int code = m_cache->GetBackend(&m_cacheBackend, &m_openEntryCallback);
+ if (code == ERR_IO_PENDING)
+ return;
+ else if (code != OK) {
+ onGetEntryDone(0 /*unused*/);
+ return;
+ }
+ }
+ openEntry(0 /*unused*/);
+}
+
+void WebCache::openEntry(int)
+{
+ if (!m_cacheBackend) {
+ onGetEntryDone(0 /*unused*/);
+ return;
+ }
+
+ if (m_cacheBackend->OpenEntry(string(m_entryUrl.utf8().data()), &m_entry, &m_onGetEntryDoneCallback) == ERR_IO_PENDING)
+ return;
+ onGetEntryDone(0 /*unused*/);
+}
+
+void WebCache::onGetEntryDone(int)
+{
+ // Unblock the UI thread in getEntry();
+ MutexLocker lock(m_getEntryMutex);
+ m_isGetEntryInProgress = false;
+ m_getEntryCondition.signal();
+}
+
} // namespace android
#ifndef WebCache_h
#define WebCache_h
+#include "CacheResult.h"
#include "ChromiumIncludes.h"
#include <OwnPtr.h>
+#include <platform/text/PlatformString.h>
#include <wtf/ThreadingPrimitives.h>
namespace android {
static void cleanup(bool isPrivateBrowsing);
void clear();
+ scoped_refptr<CacheResult> getCacheResult(WTF::String url);
net::HostResolver* hostResolver() { return m_hostResolver.get(); }
net::HttpCache* cache() { return m_cache.get(); }
net::ProxyConfigServiceAndroid* proxy() { return m_proxyConfigService; }
void doomAllEntries(int);
void onClearDone(int);
+ // For getEntry()
+ void getEntryImpl();
+ void openEntry(int);
+ void onGetEntryDone(int);
+
OwnPtr<net::HostResolver> m_hostResolver;
OwnPtr<net::HttpCache> m_cache;
// This is owned by the ProxyService, which is owned by the HttpNetworkLayer,
// For clear()
net::CompletionCallbackImpl<WebCache> m_doomAllEntriesCallback;
net::CompletionCallbackImpl<WebCache> m_onClearDoneCallback;
- disk_cache::Backend* m_cacheBackend;
bool m_isClearInProgress;
+ // For getEntry()
+ net::CompletionCallbackImpl<WebCache> m_openEntryCallback;
+ net::CompletionCallbackImpl<WebCache> m_onGetEntryDoneCallback;
+ bool m_isGetEntryInProgress;
+ String m_entryUrl;
+ disk_cache::Entry* m_entry;
+ WTF::Mutex m_getEntryMutex;
+ WTF::ThreadCondition m_getEntryCondition;
+
+ disk_cache::Backend* m_cacheBackend;
};
} // namespace android
--- /dev/null
+/*
+ * 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)
#endif
extern int registerDeviceMotionAndOrientationManager(JNIEnv*);
extern int registerCookieManager(JNIEnv*);
+#if USE(CHROME_NETWORK_STACK)
+extern int registerCacheManager(JNIEnv*);
+#endif
}
#endif
{ "DeviceMotionAndOrientationManager", android::registerDeviceMotionAndOrientationManager },
{ "CookieManager", android::registerCookieManager },
+#if USE(CHROME_NETWORK_STACK)
+ { "CacheManager", android::registerCacheManager },
+#endif
};
EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)