From 4ceb72860b5e5d1431e3a528e70b49d4358fecdb Mon Sep 17 00:00:00 2001 From: Patrick Scott Date: Mon, 23 Nov 2009 08:19:13 -0500 Subject: Move the benchmark code inside libwebcore.so This adds about 8k of code to the library but it allows the benchmark to run without modifying the library. This makes it ideal when testing libwebcore.so since it is the exact same as our running library. It also makes it possible to always build the benchmark app. --- WebKit/android/benchmark/Android.mk | 41 ++++++++ WebKit/android/benchmark/Intercept.cpp | 176 +++++++++++++++++++++++++++++++ WebKit/android/benchmark/Intercept.h | 80 ++++++++++++++ WebKit/android/benchmark/MyJavaVM.cpp | 128 +++++++++++++++++++++++ WebKit/android/benchmark/MyJavaVM.h | 34 ++++++ WebKit/android/benchmark/main.cpp | 64 ++++++++++++ WebKit/android/jni/WebCoreJniOnLoad.cpp | 178 ++++++++++++++++++++++++++++++++ 7 files changed, 701 insertions(+) create mode 100644 WebKit/android/benchmark/Android.mk create mode 100644 WebKit/android/benchmark/Intercept.cpp create mode 100644 WebKit/android/benchmark/Intercept.h create mode 100644 WebKit/android/benchmark/MyJavaVM.cpp create mode 100644 WebKit/android/benchmark/MyJavaVM.h create mode 100644 WebKit/android/benchmark/main.cpp (limited to 'WebKit/android') diff --git a/WebKit/android/benchmark/Android.mk b/WebKit/android/benchmark/Android.mk new file mode 100644 index 0000000..5b189e1 --- /dev/null +++ b/WebKit/android/benchmark/Android.mk @@ -0,0 +1,41 @@ +## +## +## Copyright 2009, 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. +## + +LOCAL_PATH:= $(call my-dir) +include $(CLEAR_VARS) + +LOCAL_SRC_FILES := \ + main.cpp + +# Pull the webkit definitions from the base webkit makefile. +LOCAL_SHARED_LIBRARIES := libwebcore $(WEBKIT_SHARED_LIBRARIES) +LOCAL_LDLIBS := $(WEBKIT_LDLIBS) + +LOCAL_MODULE := webcore_test + +LOCAL_MODULE_TAGS := optional + +include $(BUILD_EXECUTABLE) diff --git a/WebKit/android/benchmark/Intercept.cpp b/WebKit/android/benchmark/Intercept.cpp new file mode 100644 index 0000000..c31fe5e --- /dev/null +++ b/WebKit/android/benchmark/Intercept.cpp @@ -0,0 +1,176 @@ +/* + * Copyright 2009, 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 "webcore_test" +#include "config.h" + +#include "Base64.h" +#include "CString.h" +#include "HashMap.h" +#include "HTTPParsers.h" +#include "Intercept.h" +#include "ResourceHandle.h" +#include "ResourceHandleClient.h" +#include "ResourceRequest.h" +#include "ResourceResponse.h" +#include "StringHash.h" +#include "TextEncoding.h" +#include + +void MyResourceLoader::handleRequest() { + if (protocolIs(m_url, "data")) + loadData(m_url.substring(5)); // 5 for data: + else if (protocolIs(m_url, "file")) + loadFile(m_url.substring(7)); // 7 for file:// +} + +void MyResourceLoader::loadData(const String& data) { + LOGD("Loading data (%s) ...", data.latin1().data()); + ResourceHandleClient* client = m_handle->client(); + int index = data.find(','); + if (index == -1) { + client->cannotShowURL(m_handle); + return; + } + + String mediaType = data.substring(0, index); + String base64 = data.substring(index + 1); + + bool decode = mediaType.endsWith(";base64", false); + if (decode) + mediaType = mediaType.left(mediaType.length() - 7); // 7 for base64; + + if (mediaType.isEmpty()) + mediaType = "text/plain;charset=US-ASCII"; + + String mimeType = extractMIMETypeFromMediaType(mediaType); + String charset = extractCharsetFromMediaType(mediaType); + + ResourceResponse response; + response.setMimeType(mimeType); + + if (decode) { + base64 = decodeURLEscapeSequences(base64); + response.setTextEncodingName(charset); + client->didReceiveResponse(m_handle, response); + + // FIXME: This is annoying. WebCore's Base64 decoder chokes on spaces. + // That is correct with strict decoding but html authors (particularly + // the acid3 authors) put spaces in the data which should be ignored. + // Remove them here before sending to the decoder. + Vector in; + CString str = base64.latin1(); + const char* chars = str.data(); + unsigned i = 0; + while (i < str.length()) { + char c = chars[i]; + // Don't send spaces or control characters. + if (c != ' ' && c != '\n' && c != '\t' && c != '\b' + && c != '\f' && c != '\r') + in.append(chars[i]); + i++; + } + Vector out; + if (base64Decode(in, out) && out.size() > 0) + client->didReceiveData(m_handle, out.data(), out.size(), 0); + } else { + base64 = decodeURLEscapeSequences(base64, TextEncoding(charset)); + response.setTextEncodingName("UTF-16"); + client->didReceiveResponse(m_handle, response); + if (base64.length() > 0) + client->didReceiveData(m_handle, (const char*)base64.characters(), + base64.length() * sizeof(UChar), 0); + } + client->didFinishLoading(m_handle); +} +static String mimeTypeForExtension(const String& file) { + static HashMap extensionToMime; + if (extensionToMime.isEmpty()) { + extensionToMime.set("txt", "text/plain"); + extensionToMime.set("html", "text/html"); + extensionToMime.set("htm", "text/html"); + extensionToMime.set("png", "image/png"); + extensionToMime.set("jpeg", "image/jpeg"); + extensionToMime.set("jpg", "image/jpeg"); + extensionToMime.set("gif", "image/gif"); + extensionToMime.set("ico", "image/x-icon"); + extensionToMime.set("js", "text/javascript"); + } + int dot = file.reverseFind('.'); + String mime("text/plain"); + if (dot != -1) { + String ext = file.substring(dot + 1); + if (extensionToMime.contains(ext)) + mime = extensionToMime.get(ext); + } + return mime; +} + +void MyResourceLoader::loadFile(const String& file) { + LOGD("Loading file (%s) ...", file.latin1().data()); + FILE* f = fopen(file.latin1().data(), "r"); + ResourceHandleClient* client = m_handle->client(); + if (!f) { + client->didFail(m_handle, + ResourceError("", -14, file, "Could not open file")); + } else { + ResourceResponse response; + response.setTextEncodingName("utf-8"); + response.setMimeType(mimeTypeForExtension(file)); + client->didReceiveResponse(m_handle, response); + char buf[512]; + while (true) { + int res = fread(buf, 1, sizeof(buf), f); + if (res <= 0) + break; + client->didReceiveData(m_handle, buf, res, 0); + } + fclose(f); + client->didFinishLoading(m_handle); + } +} + +WebCoreResourceLoader* MyWebFrame::startLoadingResource(ResourceHandle* handle, + const ResourceRequest& req, bool ignore) { + MyResourceLoader* loader = new MyResourceLoader(handle, req.url().string()); + Retain(loader); + m_requests.append(loader); + if (!m_timer.isActive()) + m_timer.startOneShot(0); + return loader; +} + +void MyWebFrame::timerFired(Timer*) { + LOGD("Handling requests..."); + Vector reqs; + reqs.swap(m_requests); + Vector::iterator i = reqs.begin(); + Vector::iterator end = reqs.end(); + for (; i != end; i++) { + (*i)->handleRequest(); + Release(*i); + } + LOGD("...done"); +} diff --git a/WebKit/android/benchmark/Intercept.h b/WebKit/android/benchmark/Intercept.h new file mode 100644 index 0000000..a5e50c7 --- /dev/null +++ b/WebKit/android/benchmark/Intercept.h @@ -0,0 +1,80 @@ +/* + * Copyright 2009, 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. + */ + +#ifndef INTERCEPT_H +#define INTERCEPT_H + +#include "jni_utility.h" +#include "MyJavaVM.h" +#include "PlatformString.h" +#include "Timer.h" +#include "Vector.h" +#include "WebCoreFrameBridge.h" +#include "WebCoreResourceLoader.h" + +namespace WebCore { + class Page; + class ResourceHandle; + class ResourceRequest; +} + +using namespace android; +using namespace WebCore; +using namespace WTF; + +class MyResourceLoader : public WebCoreResourceLoader { +public: + MyResourceLoader(ResourceHandle* handle, String url) + : WebCoreResourceLoader(JSC::Bindings::getJNIEnv(), MY_JOBJECT) + , m_handle(handle) + , m_url(url) {} + + void handleRequest(); + +private: + void loadData(const String&); + void loadFile(const String&); + ResourceHandle* m_handle; + String m_url; +}; + +class MyWebFrame : public WebFrame { +public: + MyWebFrame(Page* page) + : WebFrame(JSC::Bindings::getJNIEnv(), MY_JOBJECT, MY_JOBJECT, page) + , m_timer(this, &MyWebFrame::timerFired) {} + + virtual WebCoreResourceLoader* startLoadingResource(ResourceHandle* handle, + const ResourceRequest& req, bool); + + virtual bool canHandleRequest(const ResourceRequest&) { return true; } + +private: + void timerFired(Timer*); + Vector m_requests; + Timer m_timer; +}; + +#endif diff --git a/WebKit/android/benchmark/MyJavaVM.cpp b/WebKit/android/benchmark/MyJavaVM.cpp new file mode 100644 index 0000000..82eea2a --- /dev/null +++ b/WebKit/android/benchmark/MyJavaVM.cpp @@ -0,0 +1,128 @@ +/* + * Copyright 2009, 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. + */ + +#include "config.h" + +#include "MyJavaVM.h" +#include "jni_utility.h" + +#include + +static JNIEnv* s_env; +static JavaVM* s_jvm; + +// JavaVM functions +jint vm_attachCurrentThread(JavaVM*, JNIEnv** env, void*) { + *env = s_env; + return JNI_OK; +} + +// JNIEnv functions +jobject env_callObjectMethodV(JNIEnv*, jobject, jmethodID, va_list) { + return MY_JOBJECT; +} +void env_callVoidMethodV(JNIEnv*, jobject, jmethodID, va_list) {} +void env_deleteRef(JNIEnv*, jobject) {} +jboolean env_exceptionCheck(JNIEnv*) { + return false; +} +jclass env_findClass(JNIEnv*, const char*) { + return (jclass) 1; +} +jbyte* env_getByteArrayElements(JNIEnv*, jbyteArray, jboolean*) { + return NULL; +} +jmethodID env_getMethodID(JNIEnv*, jclass, const char*, const char*) { + return (jmethodID) 1; +} +jclass env_getObjectClass(JNIEnv*, jobject) { + return (jclass) 1; +} +static const char* s_fakeString = "Fake Java String"; +const jchar* env_getStringChars(JNIEnv*, jstring, jboolean* isCopy) { + if (isCopy) + *isCopy = false; + return (const jchar*)s_fakeString; +} +jsize env_getStringLength(JNIEnv*, jstring) { + return sizeof(s_fakeString) - 1; +} +jbyteArray env_newByteArray(JNIEnv*, jsize) { + return (jbyteArray) 1; +} +jobject env_newRef(JNIEnv*, jobject obj) { + return obj; +} +jobject env_newObjectV(JNIEnv*, jclass, jmethodID, va_list) { + return MY_JOBJECT; +} +jstring env_newString(JNIEnv*, const jchar*, jsize) { + return (jstring) 1; +} +void env_releaseByteArrayElements(JNIEnv*, jbyteArray, jbyte*, jint) {} +void env_releaseStringChars(JNIEnv*, jstring, const jchar*) {} +void env_setByteArrayRegion(JNIEnv*, jbyteArray, jsize, jsize, const jbyte*) {} +void env_setIntField(JNIEnv*, jobject, jfieldID, jint) {} + +void InitializeJavaVM() { + // First, create the fake vm + s_jvm = new JavaVM; + JNIInvokeInterface* i = new JNIInvokeInterface; + memset(i, 0, sizeof(JNIInvokeInterface)); + s_jvm->functions = i; + + // Now, assign the functions of the vm to our fake ones. + i->AttachCurrentThread = vm_attachCurrentThread; + + // Create the fake env next + s_env = new JNIEnv; + JNINativeInterface* n = new JNINativeInterface; + memset(n, 0, sizeof(JNINativeInterface)); + s_env->functions = n; + + // Point the functions we care about to out fake ones. + n->CallObjectMethodV = env_callObjectMethodV; + n->CallVoidMethodV = env_callVoidMethodV; + n->DeleteLocalRef = env_deleteRef; + n->DeleteGlobalRef = env_deleteRef; + n->ExceptionCheck = env_exceptionCheck; + n->FindClass = env_findClass; + n->GetByteArrayElements = env_getByteArrayElements; + n->GetMethodID = env_getMethodID; + n->GetObjectClass = env_getObjectClass; + n->GetStringChars = env_getStringChars; + n->GetStringLength = env_getStringLength; + n->NewByteArray = env_newByteArray; + n->NewGlobalRef = env_newRef; + n->NewObjectV = env_newObjectV; + n->NewString = env_newString; + n->ReleaseByteArrayElements = env_releaseByteArrayElements; + n->ReleaseStringChars = env_releaseStringChars; + n->SetByteArrayRegion = env_setByteArrayRegion; + n->SetIntField = env_setIntField; + + // Tell WebCore about the vm + JSC::Bindings::setJavaVM(s_jvm); +} diff --git a/WebKit/android/benchmark/MyJavaVM.h b/WebKit/android/benchmark/MyJavaVM.h new file mode 100644 index 0000000..36d478d --- /dev/null +++ b/WebKit/android/benchmark/MyJavaVM.h @@ -0,0 +1,34 @@ +/* + * Copyright 2009, 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. + */ + +#ifndef MY_JAVA_VM_H +#define MY_JAVA_VM_H + +// Make it 1 just to appease any assertions or checks for valid objects +#define MY_JOBJECT ((jobject) 1) + +void InitializeJavaVM(); + +#endif diff --git a/WebKit/android/benchmark/main.cpp b/WebKit/android/benchmark/main.cpp new file mode 100644 index 0000000..c1f1a31 --- /dev/null +++ b/WebKit/android/benchmark/main.cpp @@ -0,0 +1,64 @@ +/* + * Copyright 2009, 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 "webcore_test" + +#include +#include +#include + +namespace android { +extern void benchmark(const char*, int, int ,int); +} + +int main(int argc, char** argv) { + int width = 800; + int height = 600; + int reloadCount = 0; + while (true) { + int c = getopt(argc, argv, "d:r:"); + if (c == -1) + break; + else if (c == 'd') { + char* x = strchr(optarg, 'x'); + if (x) { + width = atoi(optarg); + height = atoi(x + 1); + LOGD("Rendering page at %dx%d", width, height); + } + } else if (c == 'r') { + reloadCount = atoi(optarg); + if (reloadCount < 0) + reloadCount = 0; + LOGD("Reloading %d times", reloadCount); + } + } + if (optind >= argc) { + LOGE("Please supply a file to read\n"); + return 1; + } + + android::benchmark(argv[optind], reloadCount, width, height); +} diff --git a/WebKit/android/jni/WebCoreJniOnLoad.cpp b/WebKit/android/jni/WebCoreJniOnLoad.cpp index 9eb7fca..616526b 100644 --- a/WebKit/android/jni/WebCoreJniOnLoad.cpp +++ b/WebKit/android/jni/WebCoreJniOnLoad.cpp @@ -27,6 +27,44 @@ #include "config.h" +#include "BackForwardList.h" +#include "ChromeClientAndroid.h" +#include "ContextMenuClientAndroid.h" +#include "CookieClient.h" +#include "DragClientAndroid.h" +#include "EditorClientAndroid.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "FrameLoaderClientAndroid.h" +#include "FrameView.h" +#include "GraphicsContext.h" +#include "HistoryItem.h" +#include "InspectorClientAndroid.h" +#include "IntRect.h" +#include "JavaSharedClient.h" +#include "jni_utility.h" +#include "Page.h" +#include "PlatformGraphicsContext.h" +#include "ResourceRequest.h" +#include "ScriptController.h" +#include "SecurityOrigin.h" +#include "SelectionController.h" +#include "Settings.h" +#include "SharedBuffer.h" +#include "SubstituteData.h" +#include "TimerClient.h" +#include "TextEncoding.h" +#include "WebCoreViewBridge.h" +#include "WebFrameView.h" +#include "WebViewCore.h" + +#include "SkBitmap.h" +#include "SkCanvas.h" +#include "SkImageEncoder.h" + +#include "benchmark/Intercept.h" +#include "benchmark/MyJavaVM.h" + #include "jni_utility.h" #include #include @@ -108,3 +146,143 @@ EXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) return JNI_VERSION_1_4; } + +class MyJavaSharedClient : public TimerClient, public CookieClient { +public: + MyJavaSharedClient() : m_hasTimer(false) {} + virtual void setSharedTimer(long long timemillis) { m_hasTimer = true; } + virtual void stopSharedTimer() { m_hasTimer = false; } + virtual void setSharedTimerCallback(void (*f)()) { m_func = f; } + virtual void signalServiceFuncPtrQueue() {} + + // Cookie methods that do nothing. + virtual void setCookies(const KURL&, const String&) {} + virtual String cookies(const KURL&) { return ""; } + virtual bool cookiesEnabled() { return false; } + + bool m_hasTimer; + void (*m_func)(); +}; + +static void historyItemChanged(HistoryItem* i) { + if (i->bridge()) + i->bridge()->updateHistoryItem(i); +} + +namespace android { + +EXPORT void benchmark(const char* url, int reloadCount, int width, int height) { + ScriptController::initializeThreading(); + + // Setting this allows data: urls to load from a local file. + SecurityOrigin::setLocalLoadPolicy(SecurityOrigin::AllowLocalLoadsForAll); + + // Create the fake JNIEnv and JavaVM + InitializeJavaVM(); + + // The real function is private to libwebcore but we know what it does. + notifyHistoryItemChanged = historyItemChanged; + + // Implement the shared timer callback + MyJavaSharedClient client; + JavaSharedClient::SetTimerClient(&client); + JavaSharedClient::SetCookieClient(&client); + + // Create the page with all the various clients + ChromeClientAndroid* chrome = new ChromeClientAndroid; + EditorClientAndroid* editor = new EditorClientAndroid; + Page* page = new Page(chrome, new ContextMenuClientAndroid, editor, + new DragClientAndroid, new InspectorClientAndroid, NULL); + editor->setPage(page); + + // Create MyWebFrame that intercepts network requests + MyWebFrame* webFrame = new MyWebFrame(page); + webFrame->setUserAgent("Performance testing"); // needs to be non-empty + chrome->setWebFrame(webFrame); + // ChromeClientAndroid maintains the reference. + Release(webFrame); + + // Create the Frame and the FrameLoaderClient + FrameLoaderClientAndroid* loader = new FrameLoaderClientAndroid(webFrame); + RefPtr frame = Frame::create(page, NULL, loader); + loader->setFrame(frame.get()); + + // Build our View system, resize it to the given dimensions and release our + // references. Note: We keep a referenec to frameView so we can layout and + // draw later without risk of it being deleted. + WebViewCore* webViewCore = new WebViewCore(JSC::Bindings::getJNIEnv(), + MY_JOBJECT, frame.get()); + RefPtr frameView = FrameView::create(frame.get()); + WebFrameView* webFrameView = new WebFrameView(frameView.get(), webViewCore); + frame->setView(frameView); + frameView->resize(width, height); + Release(webViewCore); + Release(webFrameView); + + // Initialize the frame and turn of low-bandwidth display (it fails an + // assertion in the Cache code) + frame->init(); + frame->selection()->setFocused(true); + + // Set all the default settings the Browser normally uses. + Settings* s = frame->settings(); + s->setLayoutAlgorithm(Settings::kLayoutNormal); // Normal layout for now + s->setStandardFontFamily("sans-serif"); + s->setFixedFontFamily("monospace"); + s->setSansSerifFontFamily("sans-serif"); + s->setSerifFontFamily("serif"); + s->setCursiveFontFamily("cursive"); + s->setFantasyFontFamily("fantasy"); + s->setMinimumFontSize(8); + s->setMinimumLogicalFontSize(8); + s->setDefaultFontSize(16); + s->setDefaultFixedFontSize(13); + s->setLoadsImagesAutomatically(true); + s->setJavaScriptEnabled(true); + s->setDefaultTextEncodingName("latin1"); + s->setPluginsEnabled(false); + s->setShrinksStandaloneImagesToFit(false); + s->setUseWideViewport(false); + + // Finally, load the actual data + ResourceRequest req(url); + frame->loader()->load(req, false); + + do { + // Layout the page and service the timer + frameView->layout(); + while (client.m_hasTimer) { + client.m_func(); + JavaSharedClient::ServiceFunctionPtrQueue(); + } + JavaSharedClient::ServiceFunctionPtrQueue(); + + // Layout more if needed. + while (frameView->needsLayout()) + frameView->layout(); + JavaSharedClient::ServiceFunctionPtrQueue(); + + if (reloadCount) + frame->loader()->reload(true); + } while (reloadCount--); + + // Draw into an offscreen bitmap + SkBitmap bmp; + bmp.setConfig(SkBitmap::kARGB_8888_Config, width, height); + bmp.allocPixels(); + SkCanvas canvas(bmp); + PlatformGraphicsContext ctx(&canvas, NULL); + GraphicsContext gc(&ctx); + frameView->paintContents(&gc, IntRect(0, 0, width, height)); + + // Write the bitmap to the sdcard + SkImageEncoder* enc = SkImageEncoder::Create(SkImageEncoder::kPNG_Type); + enc->encodeFile("/sdcard/webcore_test.png", bmp, 100); + delete enc; + + // Tear down the world. + frame->loader()->detachFromParent(); + delete page; +} + +} // namespace android -- cgit v1.1