summaryrefslogtreecommitdiffstats
path: root/WebKit/android/jni/WebCoreResourceLoader.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'WebKit/android/jni/WebCoreResourceLoader.cpp')
-rw-r--r--WebKit/android/jni/WebCoreResourceLoader.cpp333
1 files changed, 333 insertions, 0 deletions
diff --git a/WebKit/android/jni/WebCoreResourceLoader.cpp b/WebKit/android/jni/WebCoreResourceLoader.cpp
new file mode 100644
index 0000000..d4eda81
--- /dev/null
+++ b/WebKit/android/jni/WebCoreResourceLoader.cpp
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2006, 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 APPLE COMPUTER, INC. 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.
+ */
+
+#define LOG_TAG "webcoreglue"
+
+#include <config.h>
+#include <wtf/Platform.h>
+
+#include "jni_utility.h"
+#include "WebCoreResourceLoader.h"
+#include "SkUtils.h"
+
+#include "CString.h"
+#include "ResourceError.h"
+#include "ResourceHandle.h"
+#include "ResourceHandleClient.h"
+#include "ResourceHandleInternal.h"
+#include "ResourceResponse.h"
+#include "WebCoreJni.h"
+
+#ifdef ANDROID_INSTRUMENT
+#include "TimeCounter.h"
+#endif
+
+#include <utils/misc.h>
+#include <JNIHelp.h>
+#include <SkTypes.h>
+#include <stdlib.h>
+
+namespace android {
+
+// ----------------------------------------------------------------------------
+
+static struct resourceloader_t {
+ jfieldID mObject;
+ jmethodID mCancelMethodID;
+ jmethodID mDownloadFileMethodID;
+ jmethodID mWillLoadFromCacheMethodID;
+} gResourceLoader;
+
+// ----------------------------------------------------------------------------
+
+#define GET_NATIVE_HANDLE(env, obj) ((WebCore::ResourceHandle*)env->GetIntField(obj, gResourceLoader.mObject))
+#define SET_NATIVE_HANDLE(env, obj, handle) (env->SetIntField(obj, gResourceLoader.mObject, handle))
+
+//-----------------------------------------------------------------------------
+// ResourceLoadHandler
+
+WebCoreResourceLoader::WebCoreResourceLoader(JNIEnv *env, jobject jLoadListener)
+{
+ mJLoader = env->NewGlobalRef(jLoadListener);
+}
+
+WebCoreResourceLoader::~WebCoreResourceLoader()
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ SET_NATIVE_HANDLE(env, mJLoader, 0);
+ env->DeleteGlobalRef(mJLoader);
+ mJLoader = 0;
+}
+
+void WebCoreResourceLoader::cancel()
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ env->CallVoidMethod(mJLoader, gResourceLoader.mCancelMethodID);
+ checkException(env);
+}
+
+void WebCoreResourceLoader::downloadFile()
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ env->CallVoidMethod(mJLoader, gResourceLoader.mDownloadFileMethodID);
+ checkException(env);
+}
+
+/*
+* This static method is called to check to see if a POST response is in
+* the cache. This may be slow, but is only used during a navigation to
+* a POST response.
+*/
+bool WebCoreResourceLoader::willLoadFromCache(const WebCore::KURL& url)
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ WebCore::String urlStr = url.string();
+ jstring jUrlStr = env->NewString(urlStr.characters(), urlStr.length());
+ jclass resourceLoader = env->FindClass("android/webkit/LoadListener");
+ bool val = env->CallStaticBooleanMethod(resourceLoader,
+ gResourceLoader.mWillLoadFromCacheMethodID, jUrlStr);
+ checkException(env);
+ env->DeleteLocalRef(jUrlStr);
+
+ return val;
+}
+
+// ----------------------------------------------------------------------------
+void WebCoreResourceLoader::SetResponseHeader(JNIEnv* env, jobject obj, jint nativeResponse, jstring key, jstring val)
+{
+#ifdef ANDROID_INSTRUMENT
+ TimeCounterAuto counter(TimeCounter::ResourceTimeCounter);
+#endif
+
+ WebCore::ResourceResponse* response = (WebCore::ResourceResponse*)nativeResponse;
+ LOG_ASSERT(response, "nativeSetResponseHeader must take a valid response pointer!");
+
+ LOG_ASSERT(key, "How did a null value become a key?");
+ if (val) {
+ WebCore::String valStr = to_string(env, val);
+ if (!valStr.isEmpty())
+ response->setHTTPHeaderField(to_string(env, key), valStr);
+ }
+}
+
+jint WebCoreResourceLoader::CreateResponse(JNIEnv* env, jobject obj, jstring url, jint statusCode,
+ jstring statusText, jstring mimeType, jlong expectedLength,
+ jstring encoding, jlong expireTime)
+{
+#ifdef ANDROID_INSTRUMENT
+ TimeCounterAuto counter(TimeCounter::ResourceTimeCounter);
+#endif
+ LOG_ASSERT(url, "Must have a url in the response!");
+ WebCore::KURL kurl(to_string(env, url));
+ WebCore::String encodingStr;
+ WebCore::String mimeTypeStr;
+ if (mimeType) {
+ mimeTypeStr = to_string(env, mimeType);
+ LOGV("Response setMIMEType: %s", mimeTypeStr.latin1().data());
+ }
+ if (encoding) {
+ encodingStr = to_string(env, encoding);
+ LOGV("Response setTextEncodingName: %s", encodingStr.latin1().data());
+ }
+ WebCore::ResourceResponse* response = new WebCore::ResourceResponse(
+ kurl, mimeTypeStr, (long long)expectedLength,
+ encodingStr, WebCore::String());
+ response->setHTTPStatusCode(statusCode);
+ if (statusText) {
+ WebCore::String status = to_string(env, statusText);
+ response->setHTTPStatusText(status);
+ LOGV("Response setStatusText: %s", status.latin1().data());
+ }
+ // FIXME: This assumes that time_t is a long and that long is the same size as int.
+ if ((unsigned long)expireTime > INT_MAX)
+ expireTime = INT_MAX;
+ response->setExpirationDate((time_t)expireTime);
+ return (int)response;
+}
+
+void WebCoreResourceLoader::ReceivedResponse(JNIEnv* env, jobject obj, jint nativeResponse)
+{
+#ifdef ANDROID_INSTRUMENT
+ TimeCounterAuto counter(TimeCounter::ResourceTimeCounter);
+#endif
+ WebCore::ResourceHandle* handle = GET_NATIVE_HANDLE(env, obj);
+ LOG_ASSERT(handle, "nativeReceivedResponse must take a valid handle!");
+ // ResourceLoader::didFail() can set handle to be NULL, we need to check
+ if (!handle)
+ return;
+
+ WebCore::ResourceResponse* response = (WebCore::ResourceResponse*)nativeResponse;
+ LOG_ASSERT(response, "nativeReceivedResponse must take a valid resource pointer!");
+ handle->client()->didReceiveResponse(handle, *response);
+ // As the client makes a copy of the response, delete it here.
+ delete response;
+}
+
+void WebCoreResourceLoader::AddData(JNIEnv* env, jobject obj, jbyteArray dataArray, jint length)
+{
+#ifdef ANDROID_INSTRUMENT
+ TimeCounterAuto counter(TimeCounter::ResourceTimeCounter);
+#endif
+ LOGV("webcore_resourceloader data(%d)", length);
+
+ WebCore::ResourceHandle* handle = GET_NATIVE_HANDLE(env, obj);
+ LOG_ASSERT(handle, "nativeAddData must take a valid handle!");
+ // ResourceLoader::didFail() can set handle to be NULL, we need to check
+ if (!handle)
+ return;
+
+ SkAutoMemoryUsageProbe mup("android_webcore_resourceloader_nativeAddData");
+
+ bool result = false;
+ jbyte * data = env->GetByteArrayElements(dataArray, NULL);
+
+ LOG_ASSERT(handle->client(), "Why do we not have a client?");
+ handle->client()->didReceiveData(handle, (const char *)data, length, length);
+ env->ReleaseByteArrayElements(dataArray, data, JNI_ABORT);
+}
+
+void WebCoreResourceLoader::Finished(JNIEnv* env, jobject obj)
+{
+#ifdef ANDROID_INSTRUMENT
+ TimeCounterAuto counter(TimeCounter::ResourceTimeCounter);
+#endif
+ LOGV("webcore_resourceloader finished");
+ WebCore::ResourceHandle* handle = GET_NATIVE_HANDLE(env, obj);
+ LOG_ASSERT(handle, "nativeFinished must take a valid handle!");
+ // ResourceLoader::didFail() can set handle to be NULL, we need to check
+ if (!handle)
+ return;
+
+ LOG_ASSERT(handle->client(), "Why do we not have a client?");
+ handle->client()->didFinishLoading(handle);
+}
+
+jstring WebCoreResourceLoader::RedirectedToUrl(JNIEnv* env, jobject obj,
+ jstring baseUrl, jstring redirectTo, jint nativeResponse)
+{
+#ifdef ANDROID_INSTRUMENT
+ TimeCounterAuto counter(TimeCounter::ResourceTimeCounter);
+#endif
+ LOGV("webcore_resourceloader redirectedToUrl");
+ WebCore::ResourceHandle* handle = GET_NATIVE_HANDLE(env, obj);
+ LOG_ASSERT(handle, "nativeRedirectedToUrl must take a valid handle!");
+ // ResourceLoader::didFail() can set handle to be NULL, we need to check
+ if (!handle)
+ return NULL;
+
+ LOG_ASSERT(handle->client(), "Why do we not have a client?");
+ WebCore::ResourceRequest r = handle->request();
+ WebCore::KURL url(WebCore::KURL(to_string(env, baseUrl)),
+ to_string(env, redirectTo));
+ r.setURL(url);
+ if (r.httpMethod() == "POST") {
+ r.setHTTPMethod("GET");
+ r.clearHTTPReferrer();
+ r.setHTTPBody(0);
+ r.setHTTPContentType("");
+ }
+ WebCore::ResourceResponse* response = (WebCore::ResourceResponse*)nativeResponse;
+ // If the url fails to resolve the relative path, return null.
+ if (url.protocol().isEmpty()) {
+ delete response;
+ return NULL;
+ }
+ handle->client()->willSendRequest(handle, r, *response);
+ delete response;
+ WebCore::String s = url.string();
+ return env->NewString((unsigned short*)s.characters(), s.length());
+}
+
+void WebCoreResourceLoader::Error(JNIEnv* env, jobject obj, jint id, jstring description,
+ jstring failingUrl)
+{
+#ifdef ANDROID_INSTRUMENT
+ TimeCounterAuto counter(TimeCounter::ResourceTimeCounter);
+#endif
+ LOGV("webcore_resourceloader error");
+ WebCore::ResourceHandle* handle = GET_NATIVE_HANDLE(env, obj);
+ LOG_ASSERT(handle, "nativeError must take a valid handle!");
+ // ResourceLoader::didFail() can set handle to be NULL, we need to check
+ if (!handle)
+ return;
+
+ handle->client()->didFail(handle, WebCore::ResourceError("", id,
+ to_string(env, failingUrl), to_string(env, description)));
+}
+
+// ----------------------------------------------------------------------------
+
+/*
+ * JNI registration.
+ */
+static JNINativeMethod gResourceloaderMethods[] = {
+ /* name, signature, funcPtr */
+ { "nativeSetResponseHeader", "(ILjava/lang/String;Ljava/lang/String;)V",
+ (void*) WebCoreResourceLoader::SetResponseHeader },
+ { "nativeCreateResponse", "(Ljava/lang/String;ILjava/lang/String;Ljava/lang/String;JLjava/lang/String;J)I",
+ (void*) WebCoreResourceLoader::CreateResponse },
+ { "nativeReceivedResponse", "(I)V",
+ (void*) WebCoreResourceLoader::ReceivedResponse },
+ { "nativeAddData", "([BI)V",
+ (void*) WebCoreResourceLoader::AddData },
+ { "nativeFinished", "()V",
+ (void*) WebCoreResourceLoader::Finished },
+ { "nativeRedirectedToUrl", "(Ljava/lang/String;Ljava/lang/String;I)Ljava/lang/String;",
+ (void*) WebCoreResourceLoader::RedirectedToUrl },
+ { "nativeError", "(ILjava/lang/String;Ljava/lang/String;)V",
+ (void*) WebCoreResourceLoader::Error }
+};
+
+int register_resource_loader(JNIEnv* env)
+{
+ jclass resourceLoader = env->FindClass("android/webkit/LoadListener");
+ LOG_FATAL_IF(resourceLoader == NULL,
+ "Unable to find class android/webkit/LoadListener");
+
+ gResourceLoader.mObject =
+ env->GetFieldID(resourceLoader, "mNativeLoader", "I");
+ LOG_FATAL_IF(gResourceLoader.mObject == NULL,
+ "Unable to find android/webkit/LoadListener.mNativeLoader");
+
+ gResourceLoader.mCancelMethodID =
+ env->GetMethodID(resourceLoader, "cancel", "()V");
+ LOG_FATAL_IF(gResourceLoader.mCancelMethodID == NULL,
+ "Could not find method cancel on LoadListener");
+
+ gResourceLoader.mDownloadFileMethodID =
+ env->GetMethodID(resourceLoader, "downloadFile", "()V");
+ LOG_FATAL_IF(gResourceLoader.mDownloadFileMethodID == NULL,
+ "Could not find method downloadFile on LoadListener");
+
+ gResourceLoader.mWillLoadFromCacheMethodID =
+ env->GetStaticMethodID(resourceLoader, "willLoadFromCache", "(Ljava/lang/String;)Z");
+ LOG_FATAL_IF(gResourceLoader.mWillLoadFromCacheMethodID == NULL,
+ "Could not find static method willLoadFromCache on LoadListener");
+
+ return jniRegisterNativeMethods(env, "android/webkit/LoadListener",
+ gResourceloaderMethods, NELEM(gResourceloaderMethods));
+}
+
+} /* namespace android */