diff options
Diffstat (limited to 'WebKit/android/jni')
26 files changed, 1172 insertions, 1003 deletions
diff --git a/WebKit/android/jni/GeolocationPermissionsBridge.cpp b/WebKit/android/jni/GeolocationPermissionsBridge.cpp index 0eeab3a..a9f79b0 100755 --- a/WebKit/android/jni/GeolocationPermissionsBridge.cpp +++ b/WebKit/android/jni/GeolocationPermissionsBridge.cpp @@ -13,7 +13,7 @@ * 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 + * 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 diff --git a/WebKit/android/jni/JavaBridge.cpp b/WebKit/android/jni/JavaBridge.cpp index f1b532d..049a7da 100644 --- a/WebKit/android/jni/JavaBridge.cpp +++ b/WebKit/android/jni/JavaBridge.cpp @@ -13,7 +13,7 @@ * 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 + * 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 @@ -101,7 +101,7 @@ public: static void UpdatePluginDirectories(JNIEnv* env, jobject obj, jobjectArray array, jboolean reload); private: - jobject mJavaObject; + jweak mJavaObject; jmethodID mSetSharedTimer; jmethodID mStopSharedTimer; jmethodID mSetCookies; @@ -118,7 +118,7 @@ static void (*sSharedTimerFiredCallback)(); JavaBridge::JavaBridge(JNIEnv* env, jobject obj) { - mJavaObject = adoptGlobalRef(env, obj); + mJavaObject = env->NewWeakGlobalRef(obj); jclass clazz = env->GetObjectClass(obj); mSetSharedTimer = env->GetMethodID(clazz, "setSharedTimer", "(J)V"); @@ -152,7 +152,7 @@ JavaBridge::~JavaBridge() { if (mJavaObject) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->DeleteGlobalRef(mJavaObject); + env->DeleteWeakGlobalRef(mJavaObject); mJavaObject = 0; } @@ -167,8 +167,6 @@ JavaBridge::setSharedTimer(long long timemillis) { JNIEnv* env = JSC::Bindings::getJNIEnv(); AutoJObject obj = getRealObject(env, mJavaObject); - if (!obj.get()) - return; env->CallVoidMethod(obj.get(), mSetSharedTimer, timemillis); } @@ -177,8 +175,6 @@ JavaBridge::stopSharedTimer() { JNIEnv* env = JSC::Bindings::getJNIEnv(); AutoJObject obj = getRealObject(env, mJavaObject); - if (!obj.get()) - return; env->CallVoidMethod(obj.get(), mStopSharedTimer); } @@ -186,13 +182,11 @@ void JavaBridge::setCookies(WebCore::KURL const& url, WebCore::String const& value) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = getRealObject(env, mJavaObject); - if (!obj.get()) - return; const WebCore::String& urlStr = url.string(); jstring jUrlStr = env->NewString(urlStr.characters(), urlStr.length()); jstring jValueStr = env->NewString(value.characters(), value.length()); + AutoJObject obj = getRealObject(env, mJavaObject); env->CallVoidMethod(obj.get(), mSetCookies, jUrlStr, jValueStr); env->DeleteLocalRef(jUrlStr); env->DeleteLocalRef(jValueStr); @@ -203,10 +197,9 @@ JavaBridge::cookies(WebCore::KURL const& url) { JNIEnv* env = JSC::Bindings::getJNIEnv(); const WebCore::String& urlStr = url.string(); - AutoJObject obj = getRealObject(env, mJavaObject); - if (!obj.get()) - return WebCore::String(); jstring jUrlStr = env->NewString(urlStr.characters(), urlStr.length()); + + AutoJObject obj = getRealObject(env, mJavaObject); jstring string = (jstring)(env->CallObjectMethod(obj.get(), mCookies, jUrlStr)); WebCore::String ret = to_string(env, string); @@ -220,8 +213,6 @@ JavaBridge::cookiesEnabled() { JNIEnv* env = JSC::Bindings::getJNIEnv(); AutoJObject obj = getRealObject(env, mJavaObject); - if (!obj.get()) - return false; jboolean ret = env->CallBooleanMethod(obj.get(), mCookiesEnabled); return (ret != 0); } @@ -232,8 +223,6 @@ JavaBridge::getPluginDirectories() WTF::Vector<WebCore::String> directories; JNIEnv* env = JSC::Bindings::getJNIEnv(); AutoJObject obj = getRealObject(env, mJavaObject); - if (!obj.get()) - return directories; jobjectArray array = (jobjectArray) env->CallObjectMethod(obj.get(), mGetPluginDirectories); int count = env->GetArrayLength(array); @@ -252,8 +241,6 @@ JavaBridge::getPluginSharedDataDirectory() { JNIEnv* env = JSC::Bindings::getJNIEnv(); AutoJObject obj = getRealObject(env, mJavaObject); - if (!obj.get()) - return WebCore::String(); jstring ret = (jstring)env->CallObjectMethod(obj.get(), mGetPluginSharedDataDirectory); WebCore::String path = to_string(env, ret); checkException(env); @@ -276,8 +263,6 @@ void JavaBridge::signalServiceFuncPtrQueue() // environment is setup. JNIEnv* env = JSC::Bindings::getJNIEnv(); AutoJObject obj = getRealObject(env, mJavaObject); - if (!obj.get()) - return; env->CallVoidMethod(obj.get(), mSignalFuncPtrQueue); } @@ -285,8 +270,6 @@ WTF::Vector<WebCore::String>JavaBridge::getSupportedKeyStrengthList() { WTF::Vector<WebCore::String> list; JNIEnv* env = JSC::Bindings::getJNIEnv(); AutoJObject obj = getRealObject(env, mJavaObject); - if (!obj.get()) - return list; jobjectArray array = (jobjectArray) env->CallObjectMethod(obj.get(), mGetKeyStrengthList); int count = env->GetArrayLength(array); diff --git a/WebKit/android/jni/JavaSharedClient.cpp b/WebKit/android/jni/JavaSharedClient.cpp index 2eec7b9..ce46570 100644 --- a/WebKit/android/jni/JavaSharedClient.cpp +++ b/WebKit/android/jni/JavaSharedClient.cpp @@ -13,7 +13,7 @@ * 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 + * 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 @@ -102,24 +102,23 @@ namespace android { void JavaSharedClient::ServiceFunctionPtrQueue() { for (;;) { - void (*proc)(void*); - void* payload; + void (*proc)(void*) = 0; + void* payload = 0; const FuncPtrRec* rec; // we have to copy the proc/payload (if present). we do this so we // don't call the proc inside the mutex (possible deadlock!) gFuncPtrQMutex.acquire(); rec = (const FuncPtrRec*)gFuncPtrQ.front(); - if (NULL != rec) { + if (rec) { proc = rec->fProc; payload = rec->fPayload; gFuncPtrQ.pop_front(); } gFuncPtrQMutex.release(); - if (NULL == rec) { + if (!rec) break; - } proc(payload); } } diff --git a/WebKit/android/jni/JavaSharedClient.h b/WebKit/android/jni/JavaSharedClient.h index bf59969..d33df67 100644 --- a/WebKit/android/jni/JavaSharedClient.h +++ b/WebKit/android/jni/JavaSharedClient.h @@ -13,7 +13,7 @@ * 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 + * 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 diff --git a/WebKit/android/jni/MockGeolocation.cpp b/WebKit/android/jni/MockGeolocation.cpp index 3e79680..e76b1c1 100755 --- a/WebKit/android/jni/MockGeolocation.cpp +++ b/WebKit/android/jni/MockGeolocation.cpp @@ -13,7 +13,7 @@ * 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 + * 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 diff --git a/WebKit/android/jni/PictureSet.cpp b/WebKit/android/jni/PictureSet.cpp index e8fcba5..22f57a3 100644 --- a/WebKit/android/jni/PictureSet.cpp +++ b/WebKit/android/jni/PictureSet.cpp @@ -13,7 +13,7 @@ * 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 + * 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 @@ -36,7 +36,7 @@ #include "SkRect.h" #include "SkRegion.h" #include "SkStream.h" -#include <wtf/CurrentTime.h> +#include "TimeCounter.h" #define MAX_DRAW_TIME 100 #define MIN_SPLITTABLE 400 @@ -270,9 +270,9 @@ bool PictureSet::draw(SkCanvas* canvas) } canvas->translate(pathBounds.fLeft, pathBounds.fTop); canvas->save(); - uint32_t startTime = WTF::get_thread_msec(); + uint32_t startTime = getThreadMsec(); canvas->drawPicture(*working->mPicture); - size_t elapsed = working->mElapsed = WTF::get_thread_msec() - startTime; + size_t elapsed = working->mElapsed = getThreadMsec() - startTime; working->mWroteElapsed = true; if (maxElapsed < elapsed && (pathBounds.width() >= MIN_SPLITTABLE || pathBounds.height() >= MIN_SPLITTABLE)) diff --git a/WebKit/android/jni/PictureSet.h b/WebKit/android/jni/PictureSet.h index 51ff0b5..b177958 100644 --- a/WebKit/android/jni/PictureSet.h +++ b/WebKit/android/jni/PictureSet.h @@ -13,7 +13,7 @@ * 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 + * 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 diff --git a/WebKit/android/jni/WebCoreFrameBridge.cpp b/WebKit/android/jni/WebCoreFrameBridge.cpp index 745cc57..150c428 100644 --- a/WebKit/android/jni/WebCoreFrameBridge.cpp +++ b/WebKit/android/jni/WebCoreFrameBridge.cpp @@ -13,7 +13,7 @@ * 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 + * 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 @@ -28,6 +28,7 @@ #include <config.h> #include <wtf/Platform.h> +#include <wtf/CurrentTime.h> #include "android_graphics.h" #include "Arena.h" @@ -63,10 +64,8 @@ #if USE(JSC) #include "GCController.h" #include "JSDOMWindow.h" -#include <runtime/InitializeThreading.h> #include <runtime/JSLock.h> #elif USE(V8) -#include "InitializeThreading.h" #include "jni_npobject.h" #include "jni_instance.h" #endif // USE(JSC) @@ -82,6 +81,7 @@ #include "ResourceHandle.h" #include "ScriptController.h" #include "ScriptValue.h" +#include "SecurityOrigin.h" #include "SelectionController.h" #include "Settings.h" #include "SubstituteData.h" @@ -116,6 +116,51 @@ #include "TimeCounter.h" #endif +using namespace JSC::Bindings; + +static String* gUploadFileLabel; +static String* gResetLabel; +static String* gSubmitLabel; + +String* WebCore::PlatformBridge::globalLocalizedName( + WebCore::PlatformBridge::rawResId resId) +{ + switch (resId) { + case WebCore::PlatformBridge::FileUploadLabel: + return gUploadFileLabel; + case WebCore::PlatformBridge::ResetLabel: + return gResetLabel; + case WebCore::PlatformBridge::SubmitLabel: + return gSubmitLabel; + default: + return 0; + } +} +/** + * Instantiate the localized name desired. + */ +void initGlobalLocalizedName(WebCore::PlatformBridge::rawResId resId, + android::WebFrame* webFrame) +{ + String** pointer; + switch (resId) { + case WebCore::PlatformBridge::FileUploadLabel: + pointer = &gUploadFileLabel; + break; + case WebCore::PlatformBridge::ResetLabel: + pointer = &gResetLabel; + break; + case WebCore::PlatformBridge::SubmitLabel: + pointer = &gSubmitLabel; + break; + default: + return; + } + if (!(*pointer) && webFrame) { + (*pointer) = new String(webFrame->getRawResourceFilename(resId).impl()); + } +} + namespace android { // ---------------------------------------------------------------------------- @@ -126,8 +171,8 @@ namespace android { struct WebFrame::JavaBrowserFrame { - jobject mObj; - jobject mHistoryList; // WebBackForwardList object + jweak mObj; + jweak mHistoryList; // WebBackForwardList object jmethodID mStartLoadingResource; jmethodID mLoadStarted; jmethodID mTransitionToCommitted; @@ -146,6 +191,8 @@ struct WebFrame::JavaBrowserFrame jmethodID mRequestFocus; jmethodID mGetRawResFilename; jmethodID mDensity; + jmethodID mGetFileSize; + jmethodID mGetFile; AutoJObject frame(JNIEnv* env) { return getRealObject(env, mObj); } @@ -165,10 +212,10 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page* { jclass clazz = env->GetObjectClass(obj); mJavaFrame = new JavaBrowserFrame; - mJavaFrame->mObj = adoptGlobalRef(env, obj); - mJavaFrame->mHistoryList = adoptGlobalRef(env, historyList); + mJavaFrame->mObj = env->NewWeakGlobalRef(obj); + mJavaFrame->mHistoryList = env->NewWeakGlobalRef(historyList); mJavaFrame->mStartLoadingResource = env->GetMethodID(clazz, "startLoadingResource", - "(ILjava/lang/String;Ljava/lang/String;Ljava/util/HashMap;[BIZ)Landroid/webkit/LoadListener;"); + "(ILjava/lang/String;Ljava/lang/String;Ljava/util/HashMap;[BJIZZZ)Landroid/webkit/LoadListener;"); mJavaFrame->mLoadStarted = env->GetMethodID(clazz, "loadStarted", "(Ljava/lang/String;Landroid/graphics/Bitmap;IZ)V"); mJavaFrame->mTransitionToCommitted = env->GetMethodID(clazz, "transitionToCommitted", @@ -202,6 +249,8 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page* mJavaFrame->mGetRawResFilename = env->GetMethodID(clazz, "getRawResFilename", "(I)Ljava/lang/String;"); mJavaFrame->mDensity = env->GetMethodID(clazz, "density","()F"); + mJavaFrame->mGetFileSize = env->GetMethodID(clazz, "getFileSize", "(Ljava/lang/String;)I"); + mJavaFrame->mGetFile = env->GetMethodID(clazz, "getFile", "(Ljava/lang/String;[BII)I"); LOG_ASSERT(mJavaFrame->mStartLoadingResource, "Could not find method startLoadingResource"); LOG_ASSERT(mJavaFrame->mLoadStarted, "Could not find method loadStarted"); @@ -221,6 +270,8 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page* LOG_ASSERT(mJavaFrame->mRequestFocus, "Could not find method requestFocus"); LOG_ASSERT(mJavaFrame->mGetRawResFilename, "Could not find method getRawResFilename"); LOG_ASSERT(mJavaFrame->mDensity, "Could not find method density"); + LOG_ASSERT(mJavaFrame->mGetFileSize, "Could not find method getFileSize"); + LOG_ASSERT(mJavaFrame->mGetFile, "Could not find method getFile"); mUserAgent = WebCore::String(); mUserInitiatedClick = false; @@ -229,9 +280,9 @@ WebFrame::WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page* WebFrame::~WebFrame() { if (mJavaFrame->mObj) { - JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->DeleteGlobalRef(mJavaFrame->mObj); - env->DeleteGlobalRef(mJavaFrame->mHistoryList); + JNIEnv* env = getJNIEnv(); + env->DeleteWeakGlobalRef(mJavaFrame->mObj); + env->DeleteWeakGlobalRef(mJavaFrame->mHistoryList); mJavaFrame->mObj = 0; } delete mJavaFrame; @@ -274,9 +325,50 @@ static jobject createJavaMapFromHTTPHeaders(JNIEnv* env, const WebCore::HTTPHead return hashMap; } -WebCoreResourceLoader* +// In WebViewCore.java, we artificially append the filename to the URI so that +// webkit treats the actual display name of the file as the filename, rather +// than the last segment of the URI (which will simply be a number). When we +// pass the URI up to BrowserFrame, we no longer need the appended name (in fact +// it causes problems), so remove it here. +// FIXME: If we rewrite pathGetFileName (the current version is in +// FileSystemPOSIX), we can get the filename that way rather than appending it. +static jstring uriFromUriFileName(JNIEnv* env, const WebCore::String& name) +{ + const WebCore::String fileName = name.left(name.reverseFind('/')); + return env->NewString(fileName.characters(), fileName.length()); +} + +// This class stores the URI and the size of each file for upload. The URI is +// stored so we do not have to create it again. The size is stored so we can +// compare the actual size of the file with the stated size. If the actual size +// is larger, we will not copy it, since we will not have enough space in our +// buffer. +class FileInfo { +public: + FileInfo(JNIEnv* env, const WebCore::String& name) { + m_uri = uriFromUriFileName(env, name); + checkException(env); + m_size = 0; + m_env = env; + } + ~FileInfo() { + m_env->DeleteLocalRef(m_uri); + } + int getSize() { return m_size; } + jstring getUri() { return m_uri; } + void setSize(int size) { m_size = size; } +private: + // This is only a pointer to the JNIEnv* returned by + // JSC::Bindings::getJNIEnv(). Used to delete the jstring when finished. + JNIEnv* m_env; + jstring m_uri; + int m_size; +}; + +PassRefPtr<WebCore::ResourceLoaderAndroid> WebFrame::startLoadingResource(WebCore::ResourceHandle* loader, const WebCore::ResourceRequest& request, + bool mainResource, bool synchronous) { #ifdef ANDROID_INSTRUMENT @@ -288,11 +380,7 @@ WebFrame::startLoadingResource(WebCore::ResourceHandle* loader, WebCore::String method = request.httpMethod(); WebCore::HTTPHeaderMap headers = request.httpHeaderFields(); - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = mJavaFrame->frame(env); - if (!obj.get()) - return 0; - + JNIEnv* env = getJNIEnv(); WebCore::String urlStr = request.url().string(); int colon = urlStr.find(':'); bool allLower = true; @@ -313,6 +401,7 @@ WebFrame::startLoadingResource(WebCore::ResourceHandle* loader, jMethodStr = env->NewString(method.characters(), method.length()); jbyteArray jPostDataStr = NULL; WebCore::FormData* formdata = request.httpBody(); + AutoJObject obj = mJavaFrame->frame(env); if (formdata) { // We can use the formdata->flatten() but it will result in two // memcpys, first through loading up the vector with the form data @@ -325,10 +414,19 @@ WebFrame::startLoadingResource(WebCore::ResourceHandle* loader, // Sizing pass int size = 0; size_t n = elements.size(); + FileInfo** fileinfos = new FileInfo*[n]; for (size_t i = 0; i < n; ++i) { + fileinfos[i] = 0; const WebCore::FormDataElement& e = elements[i]; if (e.m_type == WebCore::FormDataElement::data) { size += e.m_data.size(); + } else if (e.m_type == WebCore::FormDataElement::encodedFile) { + fileinfos[i] = new FileInfo(env, e.m_filename); + int delta = env->CallIntMethod(obj.get(), + mJavaFrame->mGetFileSize, fileinfos[i]->getUri()); + checkException(env); + fileinfos[i]->setSize(delta); + size += delta; } } @@ -347,11 +445,19 @@ WebFrame::startLoadingResource(WebCore::ResourceHandle* loader, int delta = e.m_data.size(); memcpy(bytes + offset, e.m_data.data(), delta); offset += delta; + } else if (e.m_type + == WebCore::FormDataElement::encodedFile) { + int delta = env->CallIntMethod(obj.get(), + mJavaFrame->mGetFile, fileinfos[i]->getUri(), + jPostDataStr, offset, fileinfos[i]->getSize()); + checkException(env); + offset += delta; } } env->ReleaseByteArrayElements(jPostDataStr, bytes, 0); } } + delete[] fileinfos; } jobject jHeaderMap = createJavaMapFromHTTPHeaders(env, headers); @@ -378,8 +484,10 @@ WebFrame::startLoadingResource(WebCore::ResourceHandle* loader, jobject jLoadListener = env->CallObjectMethod(obj.get(), mJavaFrame->mStartLoadingResource, - (int)loader, jUrlStr, jMethodStr, jHeaderMap, - jPostDataStr, cacheMode, synchronous); + (int)loader, jUrlStr, jMethodStr, jHeaderMap, + jPostDataStr, formdata ? formdata->identifier(): 0, + cacheMode, mainResource, request.getUserGesture(), + synchronous); env->DeleteLocalRef(jUrlStr); env->DeleteLocalRef(jMethodStr); @@ -388,9 +496,9 @@ WebFrame::startLoadingResource(WebCore::ResourceHandle* loader, if (checkException(env)) return NULL; - WebCoreResourceLoader* h = NULL; + PassRefPtr<WebCore::ResourceLoaderAndroid> h; if (jLoadListener) - h = new WebCoreResourceLoader(env, jLoadListener); + h = WebCoreResourceLoader::create(env, jLoadListener); env->DeleteLocalRef(jLoadListener); return h; } @@ -403,14 +511,12 @@ WebFrame::reportError(int errorCode, const WebCore::String& description, TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); #endif LOGV("::WebCore:: reportError(%d, %s)", errorCode, description.ascii().data()); - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = mJavaFrame->frame(env); - if (!obj.get()) - return; + JNIEnv* env = getJNIEnv(); jstring descStr = env->NewString((unsigned short*)description.characters(), description.length()); jstring failUrl = env->NewString((unsigned short*)failingUrl.characters(), failingUrl.length()); - env->CallVoidMethod(obj.get(), mJavaFrame->mReportError, errorCode, descStr, failUrl); + env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mReportError, + errorCode, descStr, failUrl); env->DeleteLocalRef(descStr); env->DeleteLocalRef(failUrl); } @@ -435,10 +541,7 @@ WebFrame::loadStarted(WebCore::Frame* frame) !isMainFrame)) return; - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = mJavaFrame->frame(env); - if (!obj.get()) - return; + JNIEnv* env = getJNIEnv(); WebCore::String urlString(url.string()); // If this is the main frame and we already have a favicon in the database, // send it along with the page started notification. @@ -451,7 +554,7 @@ WebFrame::loadStarted(WebCore::Frame* frame) } jstring urlStr = env->NewString((unsigned short*)urlString.characters(), urlString.length()); - env->CallVoidMethod(obj.get(), mJavaFrame->mLoadStarted, urlStr, favicon, + env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mLoadStarted, urlStr, favicon, (int)loadType, isMainFrame); checkException(env); env->DeleteLocalRef(urlStr); @@ -475,13 +578,10 @@ WebFrame::transitionToCommitted(WebCore::Frame* frame) #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); #endif - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = mJavaFrame->frame(env); - if (!obj.get()) - return; + JNIEnv* env = getJNIEnv(); WebCore::FrameLoadType loadType = frame->loader()->loadType(); bool isMainFrame = (!frame->tree() || !frame->tree()->parent()); - env->CallVoidMethod(obj.get(), mJavaFrame->mTransitionToCommitted, + env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mTransitionToCommitted, (int)loadType, isMainFrame); checkException(env); } @@ -492,10 +592,7 @@ WebFrame::didFinishLoad(WebCore::Frame* frame) #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); #endif - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = mJavaFrame->frame(env); - if (!obj.get()) - return; + JNIEnv* env = getJNIEnv(); WebCore::FrameLoader* loader = frame->loader(); const WebCore::KURL& url = loader->activeDocumentLoader()->url(); if (url.isEmpty()) @@ -506,7 +603,7 @@ WebFrame::didFinishLoad(WebCore::Frame* frame) WebCore::FrameLoadType loadType = loader->loadType(); WebCore::String urlString(url.string()); jstring urlStr = env->NewString((unsigned short*)urlString.characters(), urlString.length()); - env->CallVoidMethod(obj.get(), mJavaFrame->mLoadFinished, urlStr, + env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mLoadFinished, urlStr, (int)loadType, isMainFrame); checkException(env); env->DeleteLocalRef(urlStr); @@ -519,7 +616,7 @@ WebFrame::addHistoryItem(WebCore::HistoryItem* item) TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); #endif LOGV("::WebCore:: addHistoryItem"); - JNIEnv* env = JSC::Bindings::getJNIEnv(); + JNIEnv* env = getJNIEnv(); WebHistory::AddItem(mJavaFrame->history(env), item); } @@ -530,7 +627,7 @@ WebFrame::removeHistoryItem(int index) TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); #endif LOGV("::WebCore:: removeHistoryItem at %d", index); - JNIEnv* env = JSC::Bindings::getJNIEnv(); + JNIEnv* env = getJNIEnv(); WebHistory::RemoveItem(mJavaFrame->history(env), index); } @@ -541,7 +638,7 @@ WebFrame::updateHistoryIndex(int newIndex) TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); #endif LOGV("::WebCore:: updateHistoryIndex to %d", newIndex); - JNIEnv* env = JSC::Bindings::getJNIEnv(); + JNIEnv* env = getJNIEnv(); WebHistory::UpdateHistoryIndex(mJavaFrame->history(env), newIndex); } @@ -554,13 +651,10 @@ WebFrame::setTitle(const WebCore::String& title) #ifndef NDEBUG LOGV("setTitle(%s)", title.ascii().data()); #endif - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = mJavaFrame->frame(env); - if (!obj.get()) - return; + JNIEnv* env = getJNIEnv(); jstring jTitleStr = env->NewString((unsigned short *)title.characters(), title.length()); - env->CallVoidMethod(obj.get(), mJavaFrame->mSetTitle, + env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mSetTitle, jTitleStr); checkException(env); env->DeleteLocalRef(jTitleStr); @@ -573,12 +667,9 @@ WebFrame::windowObjectCleared(WebCore::Frame* frame) TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); #endif LOGV("::WebCore:: windowObjectCleared"); - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = mJavaFrame->frame(env); - if (!obj.get()) - return; + JNIEnv* env = getJNIEnv(); - env->CallVoidMethod(obj.get(), mJavaFrame->mWindowObjectCleared, (int)frame); + env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mWindowObjectCleared, (int)frame); checkException(env); } @@ -588,12 +679,9 @@ WebFrame::setProgress(float newProgress) #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); #endif - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = mJavaFrame->frame(env); - if (!obj.get()) - return; + JNIEnv* env = getJNIEnv(); int progress = (int) (100 * newProgress); - env->CallVoidMethod(obj.get(), mJavaFrame->mSetProgress, progress); + env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mSetProgress, progress); checkException(env); } @@ -610,15 +698,12 @@ WebFrame::didReceiveIcon(WebCore::Image* icon) TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); #endif LOG_ASSERT(icon, "DidReceiveIcon called without an image!"); - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = mJavaFrame->frame(env); - if (!obj.get()) - return; + JNIEnv* env = getJNIEnv(); jobject bitmap = webcoreImageToJavaBitmap(env, icon); if (!bitmap) return; - env->CallVoidMethod(obj.get(), mJavaFrame->mDidReceiveIcon, bitmap); + env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mDidReceiveIcon, bitmap); env->DeleteLocalRef(bitmap); checkException(env); } @@ -629,14 +714,11 @@ WebFrame::didReceiveTouchIconURL(const WebCore::String& url, bool precomposed) #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); #endif - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = mJavaFrame->frame(env); - if (!obj.get()) - return; + JNIEnv* env = getJNIEnv(); jstring jUrlStr = env->NewString((unsigned short*)url.characters(), url.length()); - env->CallVoidMethod(obj.get(), + env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mDidReceiveTouchIconUrl, jUrlStr, precomposed); checkException(env); } @@ -648,14 +730,10 @@ WebFrame::updateVisitedHistory(const WebCore::KURL& url, bool reload) TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); #endif WebCore::String urlStr(url.string()); - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = mJavaFrame->frame(env); - if (!obj.get()) - return; - + JNIEnv* env = getJNIEnv(); jstring jUrlStr = env->NewString((unsigned short*)urlStr.characters(), urlStr.length()); - env->CallVoidMethod(obj.get(), mJavaFrame->mUpdateVisitedHistory, jUrlStr, reload); + env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mUpdateVisitedHistory, jUrlStr, reload); checkException(env); } @@ -678,15 +756,12 @@ WebFrame::canHandleRequest(const WebCore::ResourceRequest& request) // Empty urls should not be sent to java if (url.isEmpty()) return true; - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = mJavaFrame->frame(env); - if (!obj.get()) - return true; + JNIEnv* env = getJNIEnv(); jstring jUrlStr = env->NewString((unsigned short *)url.characters(), url.length()); // check to see whether browser app wants to hijack url loading. // if browser app handles the url, we will return false to bail out WebCore loading - jboolean ret = env->CallBooleanMethod(obj.get(), mJavaFrame->mHandleUrl, jUrlStr); + jboolean ret = env->CallBooleanMethod(mJavaFrame->frame(env).get(), mJavaFrame->mHandleUrl, jUrlStr); checkException(env); return (ret == 0); } @@ -697,14 +772,11 @@ WebFrame::createWindow(bool dialog, bool userGesture) #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); #endif - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = mJavaFrame->frame(env); - if (!obj.get()) - return NULL; - jobject jobj = env->CallObjectMethod(obj.get(), + JNIEnv* env = getJNIEnv(); + jobject obj = env->CallObjectMethod(mJavaFrame->frame(env).get(), mJavaFrame->mCreateWindow, dialog, userGesture); - if (jobj) { - WebCore::Frame* frame = GET_NATIVE_FRAME(env, jobj); + if (obj) { + WebCore::Frame* frame = GET_NATIVE_FRAME(env, obj); return frame; } return NULL; @@ -716,11 +788,8 @@ WebFrame::requestFocus() const #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); #endif - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = mJavaFrame->frame(env); - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), mJavaFrame->mRequestFocus); + JNIEnv* env = getJNIEnv(); + env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mRequestFocus); checkException(env); } @@ -731,11 +800,8 @@ WebFrame::closeWindow(WebViewCore* webViewCore) TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); #endif assert(webViewCore); - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = mJavaFrame->frame(env); - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), mJavaFrame->mCloseWindow, + JNIEnv* env = getJNIEnv(); + env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mCloseWindow, webViewCore->getJavaObject().get()); } @@ -749,23 +815,17 @@ WebFrame::decidePolicyForFormResubmission(WebCore::FramePolicyFunction func) #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::JavaCallbackTimeCounter); #endif - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = mJavaFrame->frame(env); - if (!obj.get()) - return; + JNIEnv* env = getJNIEnv(); PolicyFunctionWrapper* p = new PolicyFunctionWrapper; p->func = func; - env->CallVoidMethod(obj.get(), mJavaFrame->mDecidePolicyForFormResubmission, p); + env->CallVoidMethod(mJavaFrame->frame(env).get(), mJavaFrame->mDecidePolicyForFormResubmission, p); } WebCore::String -WebFrame::getRawResourceFilename(RAW_RES_ID id) const +WebFrame::getRawResourceFilename(WebCore::PlatformBridge::rawResId id) const { - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = mJavaFrame->frame(env); - if (!obj.get()) - return WebCore::String(); - jstring ret = (jstring) env->CallObjectMethod(obj.get(), + JNIEnv* env = getJNIEnv(); + jstring ret = (jstring) env->CallObjectMethod(mJavaFrame->frame(env).get(), mJavaFrame->mGetRawResFilename, (int)id); return to_string(env, ret); @@ -774,11 +834,8 @@ WebFrame::getRawResourceFilename(RAW_RES_ID id) const float WebFrame::density() const { - JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = mJavaFrame->frame(env); - if (!obj.get()) - return 1.0; - jfloat dpi = env->CallFloatMethod(obj.get(), mJavaFrame->mDensity); + JNIEnv* env = getJNIEnv(); + jfloat dpi = env->CallFloatMethod(mJavaFrame->frame(env).get(), mJavaFrame->mDensity); checkException(env); return dpi; } @@ -798,16 +855,12 @@ static void CallPolicyFunction(JNIEnv* env, jobject obj, jint func, jint decisio if (decision == WebCore::PolicyUse) pFrame->loader()->resetMultipleFormSubmissionProtection(); - (pFrame->loader()->*(pFunc->func))((WebCore::PolicyAction)decision); + (pFrame->loader()->policyChecker()->*(pFunc->func))((WebCore::PolicyAction)decision); } static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAssetManager, jobject historyList) { -#if USE(JSC) - JSC::initializeThreading(); -#elif USE(V8) - V8::initializeThreading(); -#endif + ScriptController::initializeThreading(); #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter); @@ -818,18 +871,10 @@ static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAss WebCore::DragClient* dragC = new DragClientAndroid; InspectorClientAndroid* inspectorC = new InspectorClientAndroid; // Create a new page - WebCore::Page* page = new WebCore::Page(chromeC, contextMenuC, editorC, dragC, inspectorC); + WebCore::Page* page = new WebCore::Page(chromeC, contextMenuC, editorC, dragC, inspectorC, 0); // css files without explicit MIMETYPE is treated as generic text files in // the Java side. So we can't enforce CSS MIMETYPE. page->settings()->setEnforceCSSMIMETypeInStrictMode(false); - /* TODO: Don't turn on PageCache until we can restore the ScrollView State. - * This caused bug http://b/issue?id=1202983 - page->settings()->setUsesPageCache(true); - // 10 is a random number chosen because it is small enough to give the user - // a good back/forward page cache without allowing the page cache to get too - // big. - WebCore::pageCache()->setCapacity(10); - */ editorC->setPage(page); page->setGroupName("android.webkit"); @@ -865,15 +910,16 @@ static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAss frame->selection()->setFocused(true); // Allow local access to file:/// and substitute data - WebCore::FrameLoader::setLocalLoadPolicy( - WebCore::FrameLoader::AllowLocalLoadsForLocalAndSubstituteData); + WebCore::SecurityOrigin::setLocalLoadPolicy( + WebCore::SecurityOrigin::AllowLocalLoadsForLocalAndSubstituteData); LOGV("::WebCore:: createFrame %p", frame); // Set the mNativeFrame field in Frame SET_NATIVE_FRAME(env, obj, (int)frame); - String directory = webFrame->getRawResourceFilename(WebFrame::DRAWABLEDIR); + String directory = webFrame->getRawResourceFilename( + WebCore::PlatformBridge::DrawableDir); if (directory.isEmpty()) LOGE("Can't find the drawable directory"); else { @@ -882,6 +928,10 @@ static void CreateFrame(JNIEnv* env, jobject obj, jobject javaview, jobject jAss // Initialize our skinning classes WebCore::RenderSkinAndroid::Init(am, directory); } + for (int i = WebCore::PlatformBridge::FileUploadLabel; + i <= WebCore::PlatformBridge::SubmitLabel; i++) + initGlobalLocalizedName( + static_cast<WebCore::PlatformBridge::rawResId>(i), webFrame); } static void DestroyFrame(JNIEnv* env, jobject obj) @@ -942,13 +992,17 @@ static void PostUrl(JNIEnv *env, jobject obj, jstring url, jbyteArray postData) if (postData) { jsize size = env->GetArrayLength(postData); jbyte* bytes = env->GetByteArrayElements(postData, NULL); - request.setHTTPBody(WebCore::FormData::create((const void*)bytes, size)); + RefPtr<FormData> formData = FormData::create((const void*)bytes, size); + // the identifier uses the same logic as generateFormDataIdentifier() in + // HTMLFormElement.cpp + formData->setIdentifier(static_cast<int64_t>(WTF::currentTime() * 1000000.0)); + request.setHTTPBody(formData); env->ReleaseByteArrayElements(postData, bytes, 0); } LOGV("PostUrl %s", kurl.string().latin1().data()); WebCore::FrameLoadRequest frameRequest(request); - pFrame->loader()->loadFrameRequest(frameRequest, false, false, 0, 0); + pFrame->loader()->loadFrameRequest(frameRequest, false, false, 0, 0, WebCore::SendReferrer); } static void LoadData(JNIEnv *env, jobject obj, jstring baseUrl, jstring data, @@ -973,7 +1027,7 @@ static void LoadData(JNIEnv *env, jobject obj, jstring baseUrl, jstring data, WebCore::SubstituteData substituteData(sharedBuffer, to_string(env, mimeType), to_string(env, encoding), - WebCore::KURL(to_string(env, failUrl))); + WebCore::KURL(ParsedURLString, to_string(env, failUrl))); // Perform the load pFrame->loader()->load(request, substituteData, false); @@ -1001,7 +1055,7 @@ static jstring ExternalRepresentation(JNIEnv *env, jobject obj) LOG_ASSERT(pFrame, "android_webcore_nativeExternalRepresentation must take a valid frame pointer!"); // Request external representation of the render tree - WebCore::String renderDump = WebCore::externalRepresentation(pFrame->contentRenderer()); + WebCore::String renderDump = WebCore::externalRepresentation(pFrame); unsigned len = renderDump.length(); if (!len) return NULL; @@ -1060,7 +1114,7 @@ static void GoBackOrForward(JNIEnv *env, jobject obj, jint pos) else if (pos == -1) pFrame->page()->goBack(); else - pFrame->loader()->goBackOrForward(pos); + pFrame->page()->goBackOrForward(pos); } static jobject StringByEvaluatingJavaScriptFromString(JNIEnv *env, jobject obj, jstring script) @@ -1072,9 +1126,14 @@ static jobject StringByEvaluatingJavaScriptFromString(JNIEnv *env, jobject obj, LOG_ASSERT(pFrame, "stringByEvaluatingJavaScriptFromString must take a valid frame pointer!"); WebCore::ScriptValue value = - pFrame->loader()->executeScript(to_string(env, script), true); + pFrame->script()->executeScript(to_string(env, script), true); WebCore::String result = WebCore::String(); - if (!value.getString(result)) +#if USE(JSC) + ScriptState* scriptState = pFrame->script()->globalObject(mainThreadNormalWorld())->globalExec(); +#elif USE(V8) + ScriptState* scriptState = pFrame->script()->mainWorldScriptState(); +#endif + if (!value.getString(scriptState, result)) return NULL; unsigned len = result.length(); if (len == 0) @@ -1082,31 +1141,55 @@ static jobject StringByEvaluatingJavaScriptFromString(JNIEnv *env, jobject obj, return env->NewString((unsigned short*)result.characters(), len); } -#if USE(JSC) // Wrap the JavaInstance used when binding custom javascript interfaces. Use a // weak reference so that the gc can collect the WebView. Override virtualBegin // and virtualEnd and swap the weak reference for the real object. -class WeakJavaInstance : public JSC::Bindings::JavaInstance { +class WeakJavaInstance : public JavaInstance { public: - static PassRefPtr<WeakJavaInstance> create(jobject obj, - PassRefPtr<JSC::Bindings::RootObject> root) { +#if USE(JSC) + static PassRefPtr<WeakJavaInstance> create(jobject obj, PassRefPtr<RootObject> root) + { return adoptRef(new WeakJavaInstance(obj, root)); } +#elif USE(V8) + static PassRefPtr<WeakJavaInstance> create(jobject obj) + { + return adoptRef(new WeakJavaInstance(obj)); + } +#endif -protected: - WeakJavaInstance(jobject instance, PassRefPtr<JSC::Bindings::RootObject> rootObject) - : JSC::Bindings::JavaInstance(instance, rootObject) +private: +#if USE(JSC) + WeakJavaInstance(jobject instance, PassRefPtr<RootObject> rootObject) + : JavaInstance(instance, rootObject) +#elif USE(V8) + WeakJavaInstance(jobject instance) : JavaInstance(instance) +#endif { - JNIEnv* env = JSC::Bindings::getJNIEnv(); + JNIEnv* env = getJNIEnv(); // JavaInstance creates a global ref to instance in its constructor. - env->DeleteGlobalRef(_instance->_instance); - // Set the object to our WeakReference wrapper. - _instance->_instance = adoptGlobalRef(env, instance); + env->DeleteGlobalRef(_instance->instance()); + // Set the object to a weak reference. + _instance->setInstance(env->NewWeakGlobalRef(instance)); + } + ~WeakJavaInstance() + { + JNIEnv* env = getJNIEnv(); + // Store the weak reference so we can delete it later. + jweak weak = _instance->instance(); + // The JavaInstance destructor attempts to delete the global ref stored + // in _instance. Since we replaced it in our constructor with a weak + // reference, restore the global ref here so the vm will not complain. + _instance->setInstance(env->NewGlobalRef( + getRealObject(env, _instance->instance()).get())); + // Delete the weak reference. + env->DeleteWeakGlobalRef(weak); } - virtual void virtualBegin() { - _weakRef = _instance->_instance; - JNIEnv* env = JSC::Bindings::getJNIEnv(); + virtual void virtualBegin() + { + _weakRef = _instance->instance(); + JNIEnv* env = getJNIEnv(); // This is odd. getRealObject returns an AutoJObject which is used to // cleanly create and delete a local reference. But, here we need to // maintain the local reference across calls to virtualBegin() and @@ -1114,26 +1197,26 @@ protected: // and delete the local reference in virtualEnd(). _realObject = getRealObject(env, _weakRef).release(); // Point to the real object - _instance->_instance = _realObject; + _instance->setInstance(_realObject); // Call the base class method INHERITED::virtualBegin(); } - virtual void virtualEnd() { + virtual void virtualEnd() + { // Call the base class method first to pop the local frame. INHERITED::virtualEnd(); // Get rid of the local reference to the real object. - JSC::Bindings::getJNIEnv()->DeleteLocalRef(_realObject); + getJNIEnv()->DeleteLocalRef(_realObject); // Point back to the WeakReference. - _instance->_instance = _weakRef; + _instance->setInstance(_weakRef); } private: - typedef JSC::Bindings::JavaInstance INHERITED; + typedef JavaInstance INHERITED; jobject _realObject; - jobject _weakRef; + jweak _weakRef; }; -#endif // USE(JSC) static void AddJavascriptInterface(JNIEnv *env, jobject obj, jint nativeFramePointer, jobject javascriptObj, jstring interfaceName) @@ -1155,39 +1238,44 @@ static void AddJavascriptInterface(JNIEnv *env, jobject obj, jint nativeFramePoi #if USE(JSC) // Copied from qwebframe.cpp JSC::JSLock lock(false); - WebCore::JSDOMWindow *window = WebCore::toJSDOMWindow(pFrame); + WebCore::JSDOMWindow *window = WebCore::toJSDOMWindow(pFrame, mainThreadNormalWorld()); if (window) { - JSC::Bindings::RootObject *root = pFrame->script()->bindingRootObject(); - JSC::Bindings::setJavaVM(vm); + RootObject *root = pFrame->script()->bindingRootObject(); + setJavaVM(vm); // Add the binding to JS environment JSC::ExecState* exec = window->globalExec(); - JSC::JSObject *addedObject = WeakJavaInstance::create(javascriptObj, + JSC::JSObject* addedObject = WeakJavaInstance::create(javascriptObj, root)->createRuntimeObject(exec); const jchar* s = env->GetStringChars(interfaceName, NULL); if (s) { // Add the binding name to the window's table of child objects. JSC::PutPropertySlot slot; - window->put(exec, JSC::Identifier(exec, (const UChar *)s, + window->put(exec, JSC::Identifier(exec, (const UChar *)s, env->GetStringLength(interfaceName)), addedObject, slot); env->ReleaseStringChars(interfaceName, s); checkException(env); } } -#endif // USE(JSC) - -#if USE(V8) +#elif USE(V8) if (pFrame) { - const char* name = JSC::Bindings::getCharactersFromJStringInEnv(env, interfaceName); - NPObject* obj = JSC::Bindings::JavaInstanceToNPObject(new JSC::Bindings::JavaInstance(javascriptObj)); + PassRefPtr<JavaInstance> addedObject = WeakJavaInstance::create(javascriptObj); + const char* name = getCharactersFromJStringInEnv(env, interfaceName); + // Pass ownership of the added object to bindToWindowObject. + NPObject* obj = JavaInstanceToNPObject(addedObject.releaseRef()); pFrame->script()->bindToWindowObject(pFrame, name, obj); - // JavaInstanceToNPObject calls NPN_RetainObject on the - // returned one (see CreateV8ObjectForNPObject in V8NPObject.cpp). - // BindToWindowObject also increases obj's ref count and decrease + // bindToWindowObject calls NPN_RetainObject on the + // returned one (see createV8ObjectForNPObject in V8NPObject.cpp). + // bindToWindowObject also increases obj's ref count and decreases // the ref count when the object is not reachable from JavaScript // side. Code here must release the reference count increased by - // JavaInstanceToNPObject. - _NPN_ReleaseObject(obj); - JSC::Bindings::releaseCharactersForJString(interfaceName, name); + // bindToWindowObject. + + // Note that while this function is declared in WebCore/bridge/npruntime.h, for V8 builds + // we use WebCore/bindings/v8/npruntime.cpp (rather than + // WebCore/bridge/npruntime.cpp), so the function is implemented there. + // TODO: Combine the two versions of these NPAPI files. + NPN_ReleaseObject(obj); + releaseCharactersForJString(interfaceName, name); } #endif @@ -1228,6 +1316,14 @@ static void ClearCache(JNIEnv *env, jobject obj) WebCore::cache()->setDisabled(true); WebCore::cache()->setDisabled(false); } + + // clear page cache + int pageCapacity = WebCore::pageCache()->capacity(); + // Setting size to 0, makes all pages be released. + WebCore::pageCache()->setCapacity(0); + WebCore::pageCache()->releaseAutoreleasedPagesNow(); + WebCore::pageCache()->setCapacity(pageCapacity); + #if USE(JSC) // force JavaScript to GC when clear cache WebCore::gcController().garbageCollectSoon(); @@ -1381,9 +1477,6 @@ static jobject GetFormTextData(JNIEnv *env, jobject obj) "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); LOG_ASSERT(put, "Could not find put method on HashMap"); - static const WebCore::AtomicString text("text"); - static const WebCore::AtomicString off("off"); - WebCore::HTMLFormElement* form; WebCore::HTMLInputElement* input; for (WebCore::Node* node = collection->firstItem(); node; node = collection->nextItem()) { @@ -1393,23 +1486,21 @@ static jobject GetFormTextData(JNIEnv *env, jobject obj) size_t size = elements.size(); for (size_t i = 0; i < size; i++) { WebCore::HTMLFormControlElement* e = elements[i]; - if (e->type() == text) { - if (e->hasAttribute(WebCore::HTMLNames::autocompleteAttr)) { - const WebCore::AtomicString& attr = e->getAttribute(WebCore::HTMLNames::autocompleteAttr); - if (attr == off) - continue; - } - input = (WebCore::HTMLInputElement*) e; - WebCore::String value = input->value(); - int len = value.length(); - if (len) { - const WebCore::AtomicString& name = input->name(); - jstring key = env->NewString((jchar *)name.characters(), name.length()); - jstring val = env->NewString((jchar *)value.characters(), len); - LOG_ASSERT(key && val, "name or value not set"); - env->CallObjectMethod(hashMap, put, key, val); - env->DeleteLocalRef(key); - env->DeleteLocalRef(val); + if (e->hasTagName(WebCore::HTMLNames::inputTag)) { + input = static_cast<WebCore::HTMLInputElement*>(e); + if (input->isTextField() && !input->isPasswordField() + && input->autoComplete()) { + WebCore::String value = input->value(); + int len = value.length(); + if (len) { + const WebCore::AtomicString& name = input->name(); + jstring key = env->NewString((jchar *)name.characters(), name.length()); + jstring val = env->NewString((jchar *)value.characters(), len); + LOG_ASSERT(key && val, "name or value not set"); + env->CallObjectMethod(hashMap, put, key, val); + env->DeleteLocalRef(key); + env->DeleteLocalRef(val); + } } } } @@ -1421,6 +1512,16 @@ static jobject GetFormTextData(JNIEnv *env, jobject obj) return hashMap; } +static void OrientationChanged(JNIEnv *env, jobject obj, int orientation) +{ +#ifdef ANDROID_INSTRUMENT + TimeCounterAuto counter(TimeCounter::NativeCallbackTimeCounter); +#endif + WebCore::Frame* pFrame = GET_NATIVE_FRAME(env, obj); + LOGE("Sending orientation: %d", orientation); + pFrame->sendOrientationChangeEvent(orientation); +} + // ---------------------------------------------------------------------------- /* @@ -1470,7 +1571,9 @@ static JNINativeMethod gBrowserFrameNativeMethods[] = { { "setUsernamePassword", "(Ljava/lang/String;Ljava/lang/String;)V", (void*) SetUsernamePassword }, { "getFormTextData", "()Ljava/util/HashMap;", - (void*) GetFormTextData } + (void*) GetFormTextData }, + { "nativeOrientationChanged", "(I)V", + (void*) OrientationChanged } }; int register_webframe(JNIEnv* env) diff --git a/WebKit/android/jni/WebCoreFrameBridge.h b/WebKit/android/jni/WebCoreFrameBridge.h index 7b49981..657ebf1 100644 --- a/WebKit/android/jni/WebCoreFrameBridge.h +++ b/WebKit/android/jni/WebCoreFrameBridge.h @@ -13,7 +13,7 @@ * 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 + * 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 @@ -29,9 +29,10 @@ #define WEBFRAME_H #include "FrameLoaderClient.h" -#include "PlatformString.h" +#include "PlatformBridge.h" #include "WebCoreRefObject.h" #include <jni.h> +#include <wtf/RefCounted.h> namespace WebCore { class HistoryItem; @@ -39,31 +40,25 @@ namespace WebCore { class Page; class RenderPart; class ResourceHandle; + class ResourceLoaderAndroid; class ResourceRequest; } namespace android { -class WebCoreResourceLoader; class WebViewCore; // one instance of WebFrame per Page for calling into Java's BrowserFrame class WebFrame : public WebCoreRefObject { public: - // these ids need to be in sync with the constants in BrowserFrame.java - enum RAW_RES_ID { - NODOMAIN = 1, - LOADERROR, - DRAWABLEDIR, - }; WebFrame(JNIEnv* env, jobject obj, jobject historyList, WebCore::Page* page); ~WebFrame(); // helper function static WebFrame* getWebFrame(const WebCore::Frame* frame); - virtual WebCoreResourceLoader* startLoadingResource(WebCore::ResourceHandle*, - const WebCore::ResourceRequest& request, + virtual PassRefPtr<WebCore::ResourceLoaderAndroid> startLoadingResource(WebCore::ResourceHandle*, + const WebCore::ResourceRequest& request, bool mainResource, bool synchronous); void reportError(int errorCode, const WebCore::String& description, @@ -107,7 +102,7 @@ class WebFrame : public WebCoreRefObject { void setUserAgent(WebCore::String userAgent) { mUserAgent = userAgent; } - WebCore::String getRawResourceFilename(RAW_RES_ID) const; + WebCore::String getRawResourceFilename(WebCore::PlatformBridge::rawResId) const; float density() const; diff --git a/WebKit/android/jni/WebCoreJni.cpp b/WebKit/android/jni/WebCoreJni.cpp index e7088b2..ef33cc0 100644 --- a/WebKit/android/jni/WebCoreJni.cpp +++ b/WebKit/android/jni/WebCoreJni.cpp @@ -13,7 +13,7 @@ * 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 + * 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 @@ -22,6 +22,7 @@ * (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" @@ -34,25 +35,10 @@ namespace android { -// Class, constructor, and get method on WeakReference -jclass gWeakRefClass; -jmethodID gWeakRefInit; -jmethodID gWeakRefGet; - -jobject adoptGlobalRef(JNIEnv* env, jobject obj) -{ - // Create a WeakReference object - jobject ref = env->NewObject(gWeakRefClass, gWeakRefInit, obj); - // Increment the ref count of the WeakReference - ref = env->NewGlobalRef(ref); - return ref; -} - AutoJObject getRealObject(JNIEnv* env, jobject obj) { - jobject real = env->CallObjectMethod(obj, gWeakRefGet); - if (!real) - LOGE("The real object has been deleted"); + jobject real = env->NewLocalRef(obj); + LOG_ASSERT(real, "The real object has been deleted!"); return AutoJObject(env, real); } @@ -85,20 +71,4 @@ WebCore::String to_string(JNIEnv* env, jstring str) return ret; } -int register_webcorejni(JNIEnv* env) { - // Instantiate the WeakReference fields. - jclass weakRef = env->FindClass("java/lang/ref/WeakReference"); - LOG_ASSERT(weakRef, "Could not find WeakReference"); - android::gWeakRefClass = (jclass)env->NewGlobalRef(weakRef); - android::gWeakRefInit = env->GetMethodID(android::gWeakRefClass, - "<init>", "(Ljava/lang/Object;)V"); - LOG_ASSERT(android::gWeakRefInit, - "Could not find constructor for WeakReference"); - android::gWeakRefGet = env->GetMethodID(android::gWeakRefClass, "get", - "()Ljava/lang/Object;"); - LOG_ASSERT(android::gWeakRefInit, - "Could not find get method for WeakReference"); - return JNI_OK; -} - } diff --git a/WebKit/android/jni/WebCoreJni.h b/WebKit/android/jni/WebCoreJni.h index 0b55497..1a1bfc0 100644 --- a/WebKit/android/jni/WebCoreJni.h +++ b/WebKit/android/jni/WebCoreJni.h @@ -13,7 +13,7 @@ * 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 + * 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 @@ -61,14 +61,10 @@ private: friend AutoJObject getRealObject(JNIEnv*, jobject); }; -// Get the real object stored in the WeakReference returned as an +// Get the real object stored in the weak reference returned as an // AutoJObject. AutoJObject getRealObject(JNIEnv*, jobject); -// Convert the given jobject to a WeakReference and create a new global -// reference to that WeakReference. -jobject adoptGlobalRef(JNIEnv*, jobject); - // Helper method for check java exceptions. Returns true if an exception // occurred and logs the exception. bool checkException(JNIEnv* env); diff --git a/WebKit/android/jni/WebCoreJniOnLoad.cpp b/WebKit/android/jni/WebCoreJniOnLoad.cpp index 0d2b61f..d69177e 100644 --- a/WebKit/android/jni/WebCoreJniOnLoad.cpp +++ b/WebKit/android/jni/WebCoreJniOnLoad.cpp @@ -13,7 +13,7 @@ * 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 + * 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 @@ -22,10 +22,49 @@ * (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 "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 <jni.h> #include <utils/Log.h> @@ -40,7 +79,6 @@ extern int register_webhistory(JNIEnv*); extern int register_webicondatabase(JNIEnv*); extern int register_websettings(JNIEnv*); extern int register_webview(JNIEnv*); -extern int register_webcorejni(JNIEnv*); #if ENABLE(DATABASE) extern int register_webstorage(JNIEnv*); #endif @@ -61,7 +99,6 @@ static RegistrationMethod gWebCoreRegMethods[] = { { "JavaBridge", android::register_javabridge }, { "WebFrame", android::register_webframe }, { "WebCoreResourceLoader", android::register_resource_loader }, - { "WebCoreJni", android::register_webcorejni }, { "WebViewCore", android::register_webviewcore }, { "WebHistory", android::register_webhistory }, { "WebIconDatabase", android::register_webicondatabase }, @@ -107,3 +144,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 = 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 = 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 + frame->view()->layout(); + while (client.m_hasTimer) { + client.m_func(); + JavaSharedClient::ServiceFunctionPtrQueue(); + } + JavaSharedClient::ServiceFunctionPtrQueue(); + + // Layout more if needed. + while (frame->view()->needsLayout()) + frame->view()->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); + frame->view()->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 diff --git a/WebKit/android/jni/WebCoreRefObject.h b/WebKit/android/jni/WebCoreRefObject.h index 3e9f840..4228db6 100644 --- a/WebKit/android/jni/WebCoreRefObject.h +++ b/WebKit/android/jni/WebCoreRefObject.h @@ -13,7 +13,7 @@ * 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 + * 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 diff --git a/WebKit/android/jni/WebCoreResourceLoader.cpp b/WebKit/android/jni/WebCoreResourceLoader.cpp index 5ccd09c..55af52d 100644 --- a/WebKit/android/jni/WebCoreResourceLoader.cpp +++ b/WebKit/android/jni/WebCoreResourceLoader.cpp @@ -13,7 +13,7 @@ * 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 + * 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 @@ -68,6 +68,11 @@ static struct resourceloader_t { //----------------------------------------------------------------------------- // ResourceLoadHandler +PassRefPtr<WebCore::ResourceLoaderAndroid> WebCoreResourceLoader::create(JNIEnv *env, jobject jLoadListener) +{ + return adoptRef<WebCore::ResourceLoaderAndroid>(new WebCoreResourceLoader(env, jLoadListener)); +} + WebCoreResourceLoader::WebCoreResourceLoader(JNIEnv *env, jobject jLoadListener) { mJLoader = env->NewGlobalRef(jLoadListener); @@ -100,14 +105,14 @@ void WebCoreResourceLoader::downloadFile() * the cache. This may be slow, but is only used during a navigation to * a POST response. */ -bool WebCoreResourceLoader::willLoadFromCache(const WebCore::KURL& url) +bool WebCoreResourceLoader::willLoadFromCache(const WebCore::KURL& url, int64_t identifier) { 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); + gResourceLoader.mWillLoadFromCacheMethodID, jUrlStr, identifier); checkException(env); env->DeleteLocalRef(jUrlStr); @@ -140,7 +145,7 @@ jint WebCoreResourceLoader::CreateResponse(JNIEnv* env, jobject obj, jstring url TimeCounterAuto counter(TimeCounter::ResourceTimeCounter); #endif LOG_ASSERT(url, "Must have a url in the response!"); - WebCore::KURL kurl(to_string(env, url)); + WebCore::KURL kurl(WebCore::ParsedURLString, to_string(env, url)); WebCore::String encodingStr; WebCore::String mimeTypeStr; if (mimeType) { @@ -235,7 +240,7 @@ jstring WebCoreResourceLoader::RedirectedToUrl(JNIEnv* env, jobject obj, 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)), + WebCore::KURL url(WebCore::KURL(WebCore::ParsedURLString, to_string(env, baseUrl)), to_string(env, redirectTo)); r.setURL(url); if (r.httpMethod() == "POST") { @@ -318,7 +323,7 @@ int register_resource_loader(JNIEnv* env) "Could not find method downloadFile on LoadListener"); gResourceLoader.mWillLoadFromCacheMethodID = - env->GetStaticMethodID(resourceLoader, "willLoadFromCache", "(Ljava/lang/String;)Z"); + env->GetStaticMethodID(resourceLoader, "willLoadFromCache", "(Ljava/lang/String;J)Z"); LOG_FATAL_IF(gResourceLoader.mWillLoadFromCacheMethodID == NULL, "Could not find static method willLoadFromCache on LoadListener"); diff --git a/WebKit/android/jni/WebCoreResourceLoader.h b/WebKit/android/jni/WebCoreResourceLoader.h index 60c0d0e..d24a43e 100644 --- a/WebKit/android/jni/WebCoreResourceLoader.h +++ b/WebKit/android/jni/WebCoreResourceLoader.h @@ -13,7 +13,7 @@ * 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 + * 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 @@ -26,34 +26,33 @@ #ifndef ANDROID_WEBKIT_RESOURCELOADLISTENER_H #define ANDROID_WEBKIT_RESOURCELOADLISTENER_H -#include "KURL.h" - -#include "WebCoreRefObject.h" +#include <KURL.h> +#include <ResourceLoaderAndroid.h> #include <jni.h> namespace android { -class WebCoreResourceLoader : public WebCoreRefObject +class WebCoreResourceLoader : public WebCore::ResourceLoaderAndroid { public: - WebCoreResourceLoader(JNIEnv *env, jobject jLoadListener); + static PassRefPtr<WebCore::ResourceLoaderAndroid> create(JNIEnv *env, jobject jLoadListener); virtual ~WebCoreResourceLoader(); /** * Call to java to cancel the current load. */ - void cancel(); + virtual void cancel(); /** * Call to java to download the current load rather than feed it * back to WebCore */ - void downloadFile(); + virtual void downloadFile(); /** * Call to java to find out if this URL is in the cache */ - static bool willLoadFromCache(const WebCore::KURL& url); + static bool willLoadFromCache(const WebCore::KURL& url, int64_t identifier); // Native jni functions static void SetResponseHeader(JNIEnv*, jobject, jint, jstring, jstring); @@ -65,6 +64,8 @@ public: static jstring RedirectedToUrl(JNIEnv*, jobject, jstring, jstring, jint); static void Error(JNIEnv*, jobject, jint, jstring, jstring); +protected: + WebCoreResourceLoader(JNIEnv *env, jobject jLoadListener); private: jobject mJLoader; }; diff --git a/WebKit/android/jni/WebCoreViewBridge.h b/WebKit/android/jni/WebCoreViewBridge.h index db79a37..61990af 100644 --- a/WebKit/android/jni/WebCoreViewBridge.h +++ b/WebKit/android/jni/WebCoreViewBridge.h @@ -13,7 +13,7 @@ * 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 + * 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 diff --git a/WebKit/android/jni/WebFrameView.cpp b/WebKit/android/jni/WebFrameView.cpp index 0ab7410..8e5eac4 100644 --- a/WebKit/android/jni/WebFrameView.cpp +++ b/WebKit/android/jni/WebFrameView.cpp @@ -13,7 +13,7 @@ * 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 + * 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 @@ -102,4 +102,3 @@ void WebFrameView::setView(WebCore::FrameView* frameView) { } } // namespace android - diff --git a/WebKit/android/jni/WebFrameView.h b/WebKit/android/jni/WebFrameView.h index 2347071..d83def1 100644 --- a/WebKit/android/jni/WebFrameView.h +++ b/WebKit/android/jni/WebFrameView.h @@ -13,7 +13,7 @@ * 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 + * 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 diff --git a/WebKit/android/jni/WebHistory.cpp b/WebKit/android/jni/WebHistory.cpp index d7aacfb..76a310b 100644 --- a/WebKit/android/jni/WebHistory.cpp +++ b/WebKit/android/jni/WebHistory.cpp @@ -13,7 +13,7 @@ * 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 + * 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 @@ -44,6 +44,7 @@ #include "TextEncoding.h" #include "WebCoreFrameBridge.h" #include "WebCoreJni.h" +#include "WebIconDatabase.h" #include "jni_utility.h" #include <JNIHelp.h> @@ -90,7 +91,7 @@ static void WebHistoryClose(JNIEnv* env, jobject obj, jint frame) list->removeItem(entries[i].get()); // Add the current item back to the list. if (current) { - current->setBridge(NULL); + current->setBridge(0); // addItem will update the children to match the newly created bridge list->addItem(current); @@ -113,7 +114,7 @@ static void WebHistoryClose(JNIEnv* env, jobject obj, jint frame) // Keep a small list of child frames to traverse. WTF::Vector<WebCore::Frame*> frameQueue; // Fix the top-level item. - pFrame->loader()->setCurrentHistoryItem(current); + pFrame->loader()->history()->setCurrentItem(current.get()); WebCore::Frame* child = pFrame->tree()->firstChild(); // Remember the parent history item so we can search for a child item. RefPtr<WebCore::HistoryItem> parent = current; @@ -121,10 +122,13 @@ static void WebHistoryClose(JNIEnv* env, jobject obj, jint frame) // Use the old history item since the current one may have a // deleted parent. WebCore::HistoryItem* item = parent->childItemWithTarget(child->tree()->name()); - child->loader()->setCurrentHistoryItem(item); - // Append the first child to the queue if it exists. - if (WebCore::Frame* f = child->tree()->firstChild()) - frameQueue.append(f); + child->loader()->history()->setCurrentItem(item); + // Append the first child to the queue if it exists. If there is no + // item, then we do not need to traverse the children since there + // will be no parent history item. + WebCore::Frame* firstChild; + if (item && (firstChild = child->tree()->firstChild())) + frameQueue.append(firstChild); child = child->tree()->nextSibling(); // If we don't have a sibling for this frame and the queue isn't // empty, use the next entry in the queue. @@ -133,7 +137,7 @@ static void WebHistoryClose(JNIEnv* env, jobject obj, jint frame) frameQueue.remove(0); // Figure out the parent history item used when searching for // the history item to use. - parent = child->tree()->parent()->loader()->currentHistoryItem(); + parent = child->tree()->parent()->loader()->history()->currentItem(); } } } @@ -152,7 +156,7 @@ static void WebHistoryRestoreIndex(JNIEnv* env, jobject obj, jint frame, jint in // Update the current and previous history item. WebCore::FrameLoader* loader = pFrame->loader(); - loader->setCurrentHistoryItem(currentItem); + loader->history()->setCurrentItem(currentItem); // load the current page with FrameLoadTypeIndexedBackForward so that it // will use cache when it is possible @@ -171,10 +175,9 @@ static void WebHistoryInflate(JNIEnv* env, jobject obj, jint frame, jbyteArray d // Inflate the history tree into one HistoryItem or null if the inflation // failed. RefPtr<WebCore::HistoryItem> newItem = WebCore::HistoryItem::create(); -#ifdef ANDROID_HISTORY_CLIENT RefPtr<WebHistoryItem> bridge = new WebHistoryItem(env, obj, newItem.get()); newItem->setBridge(bridge.get()); -#endif + // Inflate the item recursively. If it fails, that is ok. We'll have an // incomplete HistoryItem but that is better than crashing due to a null // item. @@ -184,28 +187,19 @@ static void WebHistoryInflate(JNIEnv* env, jobject obj, jint frame, jbyteArray d const char* ptr = reinterpret_cast<const char*>(bytes); read_item_recursive(newItem.get(), &ptr, (int)size); env->ReleaseByteArrayElements(data, const_cast<jbyte*>(bytes), JNI_ABORT); -#ifdef ANDROID_HISTORY_CLIENT bridge->setActive(); -#endif // Add the new item to the back/forward list. WebCore::Frame* pFrame = (WebCore::Frame*)frame; pFrame->page()->backForwardList()->addItem(newItem); -#ifdef ANDROID_HISTORY_CLIENT // Update the item. bridge->updateHistoryItem(newItem.get()); -#endif } // 6 empty strings + no document state + children count = 8 unsigned values -// 1 char for isTargetItem -// ANDROID_HISTORY_CLIENT adds 1 int for scale. -#ifdef ANDROID_HISTORY_CLIENT +// 1 char for isTargetItem and 1 char is for scale. #define HISTORY_MIN_SIZE ((int)(sizeof(unsigned) * 9 + sizeof(char))) -#else -#define HISTORY_MIN_SIZE ((int)(sizeof(unsigned) * 8 + sizeof(char))) -#endif jbyteArray WebHistory::Flatten(JNIEnv* env, WTF::Vector<char>& v, WebCore::HistoryItem* item) { @@ -217,9 +211,7 @@ jbyteArray WebHistory::Flatten(JNIEnv* env, WTF::Vector<char>& v, WebCore::Histo // Write the top-level history item and then write all the children // recursively. -#ifdef ANDROID_HISTORY_CLIENT LOG_ASSERT(item->bridge(), "Why don't we have a bridge object here?"); -#endif write_item(v, item); write_children_recursive(v, item); @@ -234,33 +226,29 @@ jbyteArray WebHistory::Flatten(JNIEnv* env, WTF::Vector<char>& v, WebCore::Histo } WebHistoryItem::WebHistoryItem(JNIEnv* env, jobject obj, - WebCore::HistoryItem* item) { - mObject = adoptGlobalRef(env, obj); - mScale = 100; - mActive = false; - mParent = NULL; - mHistoryItem = item; + WebCore::HistoryItem* item) : WebCore::AndroidWebHistoryBridge(item) { + m_object = env->NewWeakGlobalRef(obj); + m_parent = 0; } WebHistoryItem::~WebHistoryItem() { - if (mObject) { + if (m_object) { JNIEnv* env = JSC::Bindings::getJNIEnv(); if (!env) return; - env->DeleteGlobalRef(mObject); + env->DeleteWeakGlobalRef(m_object); } } void WebHistoryItem::updateHistoryItem(WebCore::HistoryItem* item) { -#ifdef ANDROID_HISTORY_CLIENT // Do not want to update during inflation. - if (!mActive) + if (!m_active) return; WebHistoryItem* webItem = this; // Now we need to update the top-most WebHistoryItem based on the top-most // HistoryItem. - if (mParent) { - webItem = mParent.get(); + if (m_parent) { + webItem = m_parent.get(); if (webItem->hasOneRef()) { // if the parent only has one ref, it is from this WebHistoryItem. // This means that the matching WebCore::HistoryItem has been freed. @@ -271,13 +259,20 @@ void WebHistoryItem::updateHistoryItem(WebCore::HistoryItem* item) { while (webItem->parent()) webItem = webItem->parent(); item = webItem->historyItem(); + if (!item) { + // If a HistoryItem only exists for page cache, it is possible that + // the parent HistoryItem destroyed before the child HistoryItem. If + // it happens, skip updating. + LOGW("Can't updateHistoryItem as the top HistoryItem is gone"); + return; + } } JNIEnv* env = JSC::Bindings::getJNIEnv(); if (!env) return; // Don't do anything if the item has been gc'd already - AutoJObject realItem = getRealObject(env, webItem->mObject); + AutoJObject realItem = getRealObject(env, webItem->m_object); if (!realItem.get()) return; @@ -322,21 +317,17 @@ void WebHistoryItem::updateHistoryItem(WebCore::HistoryItem* item) { if (favicon) env->DeleteLocalRef(favicon); env->DeleteLocalRef(array); -#endif } static void historyItemChanged(WebCore::HistoryItem* item) { -#ifdef ANDROID_HISTORY_CLIENT - LOG_ASSERT(item, - "historyItemChanged called with a null item"); + LOG_ASSERT(item, "historyItemChanged called with a null item"); + if (item->bridge()) item->bridge()->updateHistoryItem(item); -#endif } void WebHistory::AddItem(const AutoJObject& list, WebCore::HistoryItem* item) { -#ifdef ANDROID_HISTORY_CLIENT LOG_ASSERT(item, "newItem must take a valid HistoryItem!"); // Item already added. Should only happen when we are inflating the list. if (item->bridge() || !list.get()) @@ -361,7 +352,6 @@ void WebHistory::AddItem(const AutoJObject& list, WebCore::HistoryItem* item) // Delete our local reference. env->DeleteLocalRef(newItem); -#endif } void WebHistory::RemoveItem(const AutoJObject& list, int index) @@ -420,22 +410,23 @@ static void write_item(WTF::Vector<char>& v, WebCore::HistoryItem* item) // Form data const WebCore::FormData* formData = item->formData(); - if (formData) + if (formData) { write_string(v, formData->flattenToString()); - else + // save the identifier as it is not included in the flatten data + int64_t id = formData->identifier(); + v.append((char*)&id, sizeof(int64_t)); + } else write_string(v, WebCore::String()); // Empty constructor does not allocate a buffer. // Target write_string(v, item->target()); -#ifdef ANDROID_HISTORY_CLIENT - WebHistoryItem* bridge = item->bridge(); + AndroidWebHistoryBridge* bridge = item->bridge(); LOG_ASSERT(bridge, "We should have a bridge here!"); // Screen scale int scale = bridge->scale(); LOGV("Writing scale %d", scale); v.append((char*)&scale, sizeof(int)); -#endif // Document state const WTF::Vector<WebCore::String>& docState = item->documentState(); @@ -463,23 +454,23 @@ static void write_children_recursive(WTF::Vector<char>& v, WebCore::HistoryItem* WebCore::HistoryItemVector::const_iterator end = children.end(); for (WebCore::HistoryItemVector::const_iterator i = children.begin(); i != end; ++i) { WebCore::HistoryItem* item = (*i).get(); -#ifdef ANDROID_HISTORY_CLIENT LOG_ASSERT(parent->bridge(), "The parent item should have a bridge object!"); if (!item->bridge()) { - WebHistoryItem* bridge = new WebHistoryItem(parent->bridge()); + WebHistoryItem* bridge = new WebHistoryItem(static_cast<WebHistoryItem*>(parent->bridge())); item->setBridge(bridge); bridge->setActive(); } else { // The only time this item's parent may not be the same as the // parent's bridge is during history close. In that case, the // parent must not have a parent bridge. - LOG_ASSERT(parent->bridge()->parent() == NULL || - item->bridge()->parent() == parent->bridge(), + WebHistoryItem* bridge = static_cast<WebHistoryItem*>(item->bridge()); + WebHistoryItem* parentBridge = static_cast<WebHistoryItem*>(parent->bridge()); + LOG_ASSERT(parentBridge->parent() == 0 || + bridge->parent() == parentBridge, "Somehow this item has an incorrect parent"); - item->bridge()->setParent(parent->bridge()); + bridge->setParent(parentBridge); } -#endif write_item(v, item); write_children_recursive(v, item); } @@ -573,6 +564,15 @@ static bool read_item_recursive(WebCore::HistoryItem* newItem, else return false; data += l; + // Read the identifier + { + int64_t id; + int size = (int)sizeof(int64_t); + memcpy(&id, data, size); + data += size; + if (id) + formData->setIdentifier(id); + } } if (end - data < sizeofUnsigned) return false; @@ -600,8 +600,7 @@ static bool read_item_recursive(WebCore::HistoryItem* newItem, if (end - data < sizeofUnsigned) return false; -#ifdef ANDROID_HISTORY_CLIENT - WebHistoryItem* bridge = newItem->bridge(); + AndroidWebHistoryBridge* bridge = newItem->bridge(); LOG_ASSERT(bridge, "There should be a bridge object during inflate"); // Read the screen scale memcpy(&l, data, sizeofUnsigned); @@ -610,7 +609,6 @@ static bool read_item_recursive(WebCore::HistoryItem* newItem, data += sizeofUnsigned; if (end - data < sizeofUnsigned) return false; -#endif // Read the document state memcpy(&l, data, sizeofUnsigned); @@ -670,18 +668,14 @@ static bool read_item_recursive(WebCore::HistoryItem* newItem, // No need to check the length each time because read_item_recursive // will return null if there isn't enough data left to parse. WTF::PassRefPtr<WebCore::HistoryItem> child = WebCore::HistoryItem::create(); -#ifdef ANDROID_HISTORY_CLIENT // Set a bridge that will not call into java. - child->setBridge(new WebHistoryItem(bridge)); -#endif + child->setBridge(new WebHistoryItem(static_cast<WebHistoryItem*>(bridge))); // Read the child item. if (!read_item_recursive(child.get(), pData, end - data)) { child.clear(); return false; } -#ifdef ANDROID_HISTORY_CLIENT child->bridge()->setActive(); -#endif newItem->addChildItem(child); } } @@ -702,9 +696,7 @@ static void unit_test() const char* test1 = new char[0]; WTF::RefPtr<WebCore::HistoryItem> item = WebCore::HistoryItem::create(); WebCore::HistoryItem* testItem = item.get(); -#ifdef ANDROID_HISTORY_CLIENT - testItem->setBridge(new WebHistoryItem(NULL)); -#endif + testItem->setBridge(new WebHistoryItem(0)); LOG_ASSERT(!read_item_recursive(testItem, &test1, 0), "0 length array should fail!"); delete[] test1; const char* test2 = new char[2]; @@ -747,9 +739,7 @@ static void unit_test() ptr = (const char*)test3; *(int*)(test3 + offset) = 4000; LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 length target should fail!"); -#ifdef ANDROID_HISTORY_CLIENT offset += 4; // Scale -#endif // Document state offset += 4; memset(test3, 0, HISTORY_MIN_SIZE); @@ -768,12 +758,7 @@ static void unit_test() ptr = (const char*)test3; *(int*)(test3 + offset) = 4000; LOG_ASSERT(!read_item_recursive(testItem, &ptr, HISTORY_MIN_SIZE), "4000 kids should fail!"); - -#ifdef ANDROID_HISTORY_CLIENT offset = 36; -#else - offset = 28; -#endif // Test document state delete[] test3; test3 = new char[HISTORY_MIN_SIZE + sizeof(unsigned)]; @@ -811,10 +796,8 @@ static JNINativeMethod gWebHistoryItemMethods[] = { int register_webhistory(JNIEnv* env) { -#ifdef ANDROID_HISTORY_CLIENT // Get notified of all changes to history items. WebCore::notifyHistoryItemChanged = historyItemChanged; -#endif #ifdef UNIT_TEST unit_test(); #endif diff --git a/WebKit/android/jni/WebHistory.h b/WebKit/android/jni/WebHistory.h index fe70443..12bf00a 100644 --- a/WebKit/android/jni/WebHistory.h +++ b/WebKit/android/jni/WebHistory.h @@ -13,7 +13,7 @@ * 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 + * 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 @@ -26,14 +26,12 @@ #ifndef ANDROID_WEBKIT_WEBHISTORY_H #define ANDROID_WEBKIT_WEBHISTORY_H +#include "AndroidWebHistoryBridge.h" + #include <jni.h> #include <wtf/RefCounted.h> #include <wtf/Vector.h> -namespace WebCore { - class HistoryItem; -} - namespace android { class AutoJObject; @@ -49,33 +47,20 @@ public: // there are two scale factors saved with each history item. mScale reflects the // viewport scale factor, default to 100 means 100%. mScreenWidthScale records // the scale factor for the screen width used to wrap the text paragraph. -class WebHistoryItem : public WTF::RefCounted<WebHistoryItem> { +class WebHistoryItem : public WebCore::AndroidWebHistoryBridge { public: WebHistoryItem(WebHistoryItem* parent) - : mParent(parent) - , mObject(NULL) - , mScale(100) - , mScreenWidthScale(100) - , mActive(false) - , mHistoryItem(NULL) {} + : WebCore::AndroidWebHistoryBridge(0) + , m_parent(parent) + , m_object(NULL) { } WebHistoryItem(JNIEnv*, jobject, WebCore::HistoryItem*); ~WebHistoryItem(); void updateHistoryItem(WebCore::HistoryItem* item); - void setScale(int s) { mScale = s; } - void setScreenWidthScale(int s) { mScreenWidthScale = s; } - void setActive() { mActive = true; } - void setParent(WebHistoryItem* parent) { mParent = parent; } - WebHistoryItem* parent() { return mParent.get(); } - int scale() { return mScale; } - int screenWidthScale() { return mScreenWidthScale; } - WebCore::HistoryItem* historyItem() { return mHistoryItem; } + void setParent(WebHistoryItem* parent) { m_parent = parent; } + WebHistoryItem* parent() const { return m_parent.get(); } private: - RefPtr<WebHistoryItem> mParent; - jobject mObject; - int mScale; - int mScreenWidthScale; - bool mActive; - WebCore::HistoryItem* mHistoryItem; + RefPtr<WebHistoryItem> m_parent; + jweak m_object; }; }; diff --git a/WebKit/android/jni/WebIconDatabase.cpp b/WebKit/android/jni/WebIconDatabase.cpp index daf0334..20258a4 100644 --- a/WebKit/android/jni/WebIconDatabase.cpp +++ b/WebKit/android/jni/WebIconDatabase.cpp @@ -13,7 +13,7 @@ * 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 + * 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 @@ -67,10 +67,6 @@ static WebIconDatabase* gIconDatabaseClient = new WebIconDatabase(); // XXX: Called by the IconDatabase thread void WebIconDatabase::dispatchDidAddIconForPageURL(const WebCore::String& pageURL) { - // If there are no clients currently, drop this message. - if (mClients.size() == 0) - return; - mNotificationsMutex.lock(); mNotifications.append(pageURL); if (!mDeliveryRequested) { @@ -83,23 +79,25 @@ void WebIconDatabase::dispatchDidAddIconForPageURL(const WebCore::String& pageUR // Called in the WebCore thread void WebIconDatabase::RegisterForIconNotification(WebIconDatabaseClient* client) { - gIconDatabaseClient->mClientsMutex.lock(); + WebIconDatabase* db = gIconDatabaseClient; + for (unsigned i = 0; i < db->mClients.size(); ++i) { + // Do not add the same client twice. + if (db->mClients[i] == client) + return; + } gIconDatabaseClient->mClients.append(client); - gIconDatabaseClient->mClientsMutex.unlock(); } // Called in the WebCore thread void WebIconDatabase::UnregisterForIconNotification(WebIconDatabaseClient* client) { WebIconDatabase* db = gIconDatabaseClient; - db->mClientsMutex.lock(); for (unsigned i = 0; i < db->mClients.size(); ++i) { if (db->mClients[i] == client) { db->mClients.remove(i); break; } } - db->mClientsMutex.unlock(); } // Called in the WebCore thread @@ -123,9 +121,7 @@ void WebIconDatabase::deliverNotifications() // Swap the clients queue Vector<WebIconDatabaseClient*> clients; - mClientsMutex.lock(); clients.swap(mClients); - mClientsMutex.unlock(); for (unsigned i = 0; i < queue.size(); ++i) { for (unsigned j = 0; j < clients.size(); ++j) { diff --git a/WebKit/android/jni/WebIconDatabase.h b/WebKit/android/jni/WebIconDatabase.h index c88842c..c91c4ae 100644 --- a/WebKit/android/jni/WebIconDatabase.h +++ b/WebKit/android/jni/WebIconDatabase.h @@ -13,7 +13,7 @@ * 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 + * 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 @@ -59,9 +59,8 @@ namespace android { // Deliver all the icon notifications void deliverNotifications(); - // List of clients and a mutex to protect it. + // List of clients. Vector<WebIconDatabaseClient*> mClients; - android::Mutex mClientsMutex; // Queue of page urls that have received an icon. Vector<WebCore::String> mNotifications; diff --git a/WebKit/android/jni/WebSettings.cpp b/WebKit/android/jni/WebSettings.cpp index 4240dd5..00fec85 100644 --- a/WebKit/android/jni/WebSettings.cpp +++ b/WebKit/android/jni/WebSettings.cpp @@ -13,7 +13,7 @@ * 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 + * 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 @@ -38,6 +38,7 @@ #include "Geolocation.h" #include "GeolocationPermissions.h" #include "Page.h" +#include "PageCache.h" #include "RenderTable.h" #include "Settings.h" #include "WebCoreFrameBridge.h" @@ -110,6 +111,7 @@ struct FieldIds { mSupportMultipleWindows = env->GetFieldID(clazz, "mSupportMultipleWindows", "Z"); mShrinksStandaloneImagesToFit = env->GetFieldID(clazz, "mShrinksStandaloneImagesToFit", "Z"); mUseDoubleTree = env->GetFieldID(clazz, "mUseDoubleTree", "Z"); + mPageCacheCapacity = env->GetFieldID(clazz, "mPageCacheCapacity", "I"); LOG_ASSERT(mLayoutAlgorithm, "Could not find field mLayoutAlgorithm"); LOG_ASSERT(mTextSize, "Could not find field mTextSize"); @@ -145,6 +147,7 @@ struct FieldIds { LOG_ASSERT(mSupportMultipleWindows, "Could not find field mSupportMultipleWindows"); LOG_ASSERT(mShrinksStandaloneImagesToFit, "Could not find field mShrinksStandaloneImagesToFit"); LOG_ASSERT(mUseDoubleTree, "Could not find field mUseDoubleTree"); + LOG_ASSERT(mPageCacheCapacity, "Could not find field mPageCacheCapacity"); jclass c = env->FindClass("java/lang/Enum"); LOG_ASSERT(c, "Could not find Enum class!"); @@ -189,6 +192,7 @@ struct FieldIds { jfieldID mSupportMultipleWindows; jfieldID mShrinksStandaloneImagesToFit; jfieldID mUseDoubleTree; + jfieldID mPageCacheCapacity; // Ordinal() method and value field for enums jmethodID mOrdinal; jfieldID mTextSizeValue; @@ -342,7 +346,8 @@ public: flag = env->GetBooleanField(obj, gFieldIds->mDatabaseEnabled); s->setDatabasesEnabled(flag); str = (jstring)env->GetObjectField(obj, gFieldIds->mDatabasePath); - WebCore::DatabaseTracker::tracker().setDatabaseDirectoryPath(to_string(env, str)); + if (str && WebCore::DatabaseTracker::tracker().databaseDirectoryPath().isNull()) + WebCore::DatabaseTracker::tracker().setDatabaseDirectoryPath(to_string(env, str)); #endif #if ENABLE(DOM_STORAGE) flag = env->GetBooleanField(obj, gFieldIds->mDomStorageEnabled); @@ -363,6 +368,13 @@ public: GeolocationPermissions::setDatabasePath(to_string(env,str)); WebCore::Geolocation::setDatabasePath(to_string(env,str)); } + + size = env->GetIntField(obj, gFieldIds->mPageCacheCapacity); + if (size > 0) { + s->setUsesPageCache(true); + WebCore::pageCache()->setCapacity(size); + } else + s->setUsesPageCache(false); } }; diff --git a/WebKit/android/jni/WebStorage.cpp b/WebKit/android/jni/WebStorage.cpp index aa83892..07e4880 100644 --- a/WebKit/android/jni/WebStorage.cpp +++ b/WebKit/android/jni/WebStorage.cpp @@ -13,7 +13,7 @@ * 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 + * 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 @@ -93,9 +93,9 @@ static unsigned long long GetUsageForOrigin(JNIEnv* env, jobject obj, jstring or if (manifestOrigin.get() == 0) continue; if (manifestOrigin->isSameSchemeHostPort(securityOrigin.get())) { - int64_t size = 0; - WebCore::cacheStorage().cacheGroupSize(manifestUrls[i].string(), &size); - usage += size; + int64_t cacheSize = 0; + WebCore::cacheStorage().cacheGroupSize(manifestUrls[i].string(), &cacheSize); + usage += cacheSize; } } return usage; @@ -163,4 +163,3 @@ int register_webstorage(JNIEnv* env) } #endif //ENABLE(DATABASE) - diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp index 0eca9bc..8414068 100644 --- a/WebKit/android/jni/WebViewCore.cpp +++ b/WebKit/android/jni/WebViewCore.cpp @@ -13,7 +13,7 @@ * 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 + * 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 @@ -57,6 +57,7 @@ #include "HTMLElement.h" #include "HTMLImageElement.h" #include "HTMLInputElement.h" +#include "HTMLLabelElement.h" #include "HTMLMapElement.h" #include "HTMLNames.h" #include "HTMLOptGroupElement.h" @@ -68,6 +69,7 @@ #include "KeyboardCodes.h" #include "Navigator.h" #include "Node.h" +#include "NodeList.h" #include "Page.h" #include "PageGroup.h" #include "PlatformKeyboardEvent.h" @@ -88,6 +90,7 @@ #include "Settings.h" #include "SkANP.h" #include "SkTemplates.h" +#include "SkTDArray.h" #include "SkTypes.h" #include "SkCanvas.h" #include "SkPicture.h" @@ -129,6 +132,11 @@ FILE* gRenderTreeFile = 0; #include "TimeCounter.h" #endif +#if USE(ACCELERATED_COMPOSITING) +#include "GraphicsLayerAndroid.h" +#include "RenderLayerCompositor.h" +#endif + /* We pass this flag when recording the actual content, so that we don't spend time actually regionizing complex path clips, when all we really want to do is record them. @@ -141,6 +149,24 @@ namespace android { bool WebViewCore::s_isPaused = false; +static SkTDArray<WebViewCore*> gInstanceList; + +void WebViewCore::addInstance(WebViewCore* inst) { + *gInstanceList.append() = inst; +} + +void WebViewCore::removeInstance(WebViewCore* inst) { + int index = gInstanceList.find(inst); + LOG_ASSERT(index >= 0, "RemoveInstance inst not found"); + if (index >= 0) { + gInstanceList.removeShuffle(index); + } +} + +bool WebViewCore::isInstance(WebViewCore* inst) { + return gInstanceList.find(inst) >= 0; +} + // ---------------------------------------------------------------------------- #define GET_NATIVE_VIEW(env, obj) ((WebViewCore*)env->GetIntField(obj, gWebViewCoreFields.m_nativeClass)) @@ -161,12 +187,13 @@ struct WebViewCoreFields { // ---------------------------------------------------------------------------- struct WebViewCore::JavaGlue { - jobject m_obj; + jweak m_obj; jmethodID m_spawnScrollTo; jmethodID m_scrollTo; jmethodID m_scrollBy; jmethodID m_contentDraw; jmethodID m_requestListBox; + jmethodID m_openFileChooser; jmethodID m_requestSingleListBox; jmethodID m_jsAlert; jmethodID m_jsConfirm; @@ -177,6 +204,8 @@ struct WebViewCore::JavaGlue { jmethodID m_updateViewport; jmethodID m_sendNotifyProgressFinished; jmethodID m_sendViewInvalidate; + jmethodID m_sendImmediateRepaint; + jmethodID m_setRootLayer; jmethodID m_updateTextfield; jmethodID m_updateTextSelection; jmethodID m_clearTextEntry; @@ -190,10 +219,15 @@ struct WebViewCore::JavaGlue { jmethodID m_geolocationPermissionsShowPrompt; jmethodID m_geolocationPermissionsHidePrompt; jmethodID m_addMessageToConsole; - jmethodID m_startFullScreenPluginActivity; - jmethodID m_createSurface; + jmethodID m_getPluginClass; + jmethodID m_showFullScreenPlugin; + jmethodID m_hideFullScreenPlugin; + jmethodID m_updateFullScreenPlugin; + jmethodID m_addSurface; + jmethodID m_updateSurface; jmethodID m_destroySurface; - jmethodID m_showRect; + jmethodID m_getContext; + jmethodID m_sendFindAgain; AutoJObject object(JNIEnv* env) { return getRealObject(env, m_obj); } @@ -222,7 +256,6 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m m_popupReply = 0; m_moveGeneration = 0; - m_generation = 0; m_lastGeneration = 0; m_touchGeneration = 0; m_blockTextfieldUpdates = false; @@ -238,13 +271,14 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m jclass clazz = env->GetObjectClass(javaWebViewCore); m_javaGlue = new JavaGlue; - m_javaGlue->m_obj = adoptGlobalRef(env, javaWebViewCore); + m_javaGlue->m_obj = env->NewWeakGlobalRef(javaWebViewCore); m_javaGlue->m_spawnScrollTo = GetJMethod(env, clazz, "contentSpawnScrollTo", "(II)V"); m_javaGlue->m_scrollTo = GetJMethod(env, clazz, "contentScrollTo", "(II)V"); m_javaGlue->m_scrollBy = GetJMethod(env, clazz, "contentScrollBy", "(IIZ)V"); m_javaGlue->m_contentDraw = GetJMethod(env, clazz, "contentDraw", "()V"); - m_javaGlue->m_requestListBox = GetJMethod(env, clazz, "requestListBox", "([Ljava/lang/String;[Z[I)V"); - m_javaGlue->m_requestSingleListBox = GetJMethod(env, clazz, "requestListBox", "([Ljava/lang/String;[ZI)V"); + m_javaGlue->m_requestListBox = GetJMethod(env, clazz, "requestListBox", "([Ljava/lang/String;[I[I)V"); + m_javaGlue->m_openFileChooser = GetJMethod(env, clazz, "openFileChooser", "()Ljava/lang/String;"); + m_javaGlue->m_requestSingleListBox = GetJMethod(env, clazz, "requestListBox", "([Ljava/lang/String;[II)V"); m_javaGlue->m_jsAlert = GetJMethod(env, clazz, "jsAlert", "(Ljava/lang/String;Ljava/lang/String;)V"); m_javaGlue->m_jsConfirm = GetJMethod(env, clazz, "jsConfirm", "(Ljava/lang/String;Ljava/lang/String;)Z"); m_javaGlue->m_jsPrompt = GetJMethod(env, clazz, "jsPrompt", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;"); @@ -254,23 +288,30 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m m_javaGlue->m_updateViewport = GetJMethod(env, clazz, "updateViewport", "()V"); m_javaGlue->m_sendNotifyProgressFinished = GetJMethod(env, clazz, "sendNotifyProgressFinished", "()V"); m_javaGlue->m_sendViewInvalidate = GetJMethod(env, clazz, "sendViewInvalidate", "(IIII)V"); + m_javaGlue->m_sendImmediateRepaint = GetJMethod(env, clazz, "sendImmediateRepaint", "()V"); + m_javaGlue->m_setRootLayer = GetJMethod(env, clazz, "setRootLayer", "(I)V"); m_javaGlue->m_updateTextfield = GetJMethod(env, clazz, "updateTextfield", "(IZLjava/lang/String;I)V"); m_javaGlue->m_updateTextSelection = GetJMethod(env, clazz, "updateTextSelection", "(IIII)V"); m_javaGlue->m_clearTextEntry = GetJMethod(env, clazz, "clearTextEntry", "()V"); m_javaGlue->m_restoreScale = GetJMethod(env, clazz, "restoreScale", "(I)V"); m_javaGlue->m_restoreScreenWidthScale = GetJMethod(env, clazz, "restoreScreenWidthScale", "(I)V"); m_javaGlue->m_needTouchEvents = GetJMethod(env, clazz, "needTouchEvents", "(Z)V"); - m_javaGlue->m_requestKeyboard = GetJMethod(env, clazz, "requestKeyboard", "(Z)V"); + m_javaGlue->m_requestKeyboard = GetJMethod(env, clazz, "requestKeyboard", "(ZZ)V"); m_javaGlue->m_exceededDatabaseQuota = GetJMethod(env, clazz, "exceededDatabaseQuota", "(Ljava/lang/String;Ljava/lang/String;JJ)V"); m_javaGlue->m_reachedMaxAppCacheSize = GetJMethod(env, clazz, "reachedMaxAppCacheSize", "(J)V"); m_javaGlue->m_populateVisitedLinks = GetJMethod(env, clazz, "populateVisitedLinks", "()V"); m_javaGlue->m_geolocationPermissionsShowPrompt = GetJMethod(env, clazz, "geolocationPermissionsShowPrompt", "(Ljava/lang/String;)V"); m_javaGlue->m_geolocationPermissionsHidePrompt = GetJMethod(env, clazz, "geolocationPermissionsHidePrompt", "()V"); m_javaGlue->m_addMessageToConsole = GetJMethod(env, clazz, "addMessageToConsole", "(Ljava/lang/String;ILjava/lang/String;)V"); - m_javaGlue->m_startFullScreenPluginActivity = GetJMethod(env, clazz, "startFullScreenPluginActivity", "(Ljava/lang/String;Ljava/lang/String;I)V"); - m_javaGlue->m_createSurface = GetJMethod(env, clazz, "createSurface", "(Ljava/lang/String;Ljava/lang/String;IIIII)Landroid/webkit/ViewManager$ChildView;"); + m_javaGlue->m_getPluginClass = GetJMethod(env, clazz, "getPluginClass", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Class;"); + m_javaGlue->m_showFullScreenPlugin = GetJMethod(env, clazz, "showFullScreenPlugin", "(Landroid/webkit/ViewManager$ChildView;IIIII)V"); + m_javaGlue->m_hideFullScreenPlugin = GetJMethod(env, clazz, "hideFullScreenPlugin", "()V"); + m_javaGlue->m_updateFullScreenPlugin = GetJMethod(env, clazz, "updateFullScreenPlugin", "(IIII)V"); + m_javaGlue->m_addSurface = GetJMethod(env, clazz, "addSurface", "(Landroid/view/View;IIII)Landroid/webkit/ViewManager$ChildView;"); + m_javaGlue->m_updateSurface = GetJMethod(env, clazz, "updateSurface", "(Landroid/webkit/ViewManager$ChildView;IIII)V"); m_javaGlue->m_destroySurface = GetJMethod(env, clazz, "destroySurface", "(Landroid/webkit/ViewManager$ChildView;)V"); - m_javaGlue->m_showRect = GetJMethod(env, clazz, "showRect", "(IIIIIIFFFF)V"); + m_javaGlue->m_getContext = GetJMethod(env, clazz, "getContext", "()Landroid/content/Context;"); + m_javaGlue->m_sendFindAgain = GetJMethod(env, clazz, "sendFindAgain", "()V"); env->SetIntField(javaWebViewCore, gWebViewCoreFields.m_nativeClass, (jint)this); @@ -279,16 +320,20 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m PageGroup::setShouldTrackVisitedLinks(true); reset(true); + + WebViewCore::addInstance(this); } WebViewCore::~WebViewCore() { + WebViewCore::removeInstance(this); + // Release the focused view Release(m_popupReply); if (m_javaGlue->m_obj) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - env->DeleteGlobalRef(m_javaGlue->m_obj); + env->DeleteWeakGlobalRef(m_javaGlue->m_obj); m_javaGlue->m_obj = 0; } delete m_javaGlue; @@ -326,9 +371,9 @@ void WebViewCore::reset(bool fromConstructor) m_lastFocused = 0; m_lastFocusedBounds = WebCore::IntRect(0,0,0,0); + m_focusBoundsChanged = false; m_lastFocusedSelStart = 0; m_lastFocusedSelEnd = 0; - m_lastMoveGeneration = 0; clearContent(); m_updatedFrameCache = true; m_frameCacheOutOfDate = true; @@ -573,6 +618,8 @@ void WebViewCore::recordPictureSet(PictureSet* content) { return; } + m_focusBoundsChanged |= m_lastFocused == oldFocusNode + && m_lastFocusedBounds != oldBounds; m_lastFocused = oldFocusNode; m_lastFocusedBounds = oldBounds; m_lastFocusedSelStart = oldSelStart; @@ -580,6 +627,14 @@ void WebViewCore::recordPictureSet(PictureSet* content) m_domtree_version = latestVersion; DBG_NAV_LOG("call updateFrameCache"); updateFrameCache(); + if (m_findIsUp) { + LOG_ASSERT(m_javaGlue->m_obj, + "A Java widget was not associated with this view bridge!"); + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->CallVoidMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_sendFindAgain); + checkException(env); + } } void WebViewCore::updateButtonList(WTF::Vector<Container>* buttons) @@ -666,6 +721,13 @@ bool WebViewCore::drawContent(SkCanvas* canvas, SkColor color) return tookTooLong; } +bool WebViewCore::focusBoundsChanged() +{ + bool result = m_focusBoundsChanged; + m_focusBoundsChanged = false; + return result; +} + bool WebViewCore::pictureReady() { bool done; @@ -776,12 +838,9 @@ void WebViewCore::scrollTo(int x, int y, bool animate) // LOGD("WebViewCore::scrollTo(%d %d)\n", x, y); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), animate ? m_javaGlue->m_spawnScrollTo : m_javaGlue->m_scrollTo, x, y); + env->CallVoidMethod(m_javaGlue->object(env).get(), + animate ? m_javaGlue->m_spawnScrollTo : m_javaGlue->m_scrollTo, + x, y); checkException(env); } @@ -789,12 +848,7 @@ void WebViewCore::sendNotifyProgressFinished() { LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue->m_sendNotifyProgressFinished); + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_sendNotifyProgressFinished); checkException(env); } @@ -802,12 +856,7 @@ void WebViewCore::viewInvalidate(const WebCore::IntRect& rect) { LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_sendViewInvalidate, rect.x(), rect.y(), rect.right(), rect.bottom()); checkException(env); @@ -818,25 +867,37 @@ void WebViewCore::scrollBy(int dx, int dy, bool animate) if (!(dx | dy)) return; JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue->m_scrollBy, + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_scrollBy, dx, dy, animate); checkException(env); } +#if USE(ACCELERATED_COMPOSITING) + +void WebViewCore::immediateRepaint() +{ + LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!"); + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->CallVoidMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_sendImmediateRepaint); + checkException(env); +} + +void WebViewCore::setRootLayer(int layer) +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->CallVoidMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_setRootLayer, + layer); + checkException(env); +} + +#endif // USE(ACCELERATED_COMPOSITING) + void WebViewCore::contentDraw() { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue->m_contentDraw); + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_contentDraw); checkException(env); } @@ -885,18 +946,14 @@ void WebViewCore::didFirstLayout() WebCore::FrameLoadType loadType = loader->loadType(); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue->m_didFirstLayout, + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_didFirstLayout, loadType == WebCore::FrameLoadTypeStandard // When redirect with locked history, we would like to reset the // scale factor. This is important for www.yahoo.com as it is // redirected to www.yahoo.com/?rs=1 on load. || loadType == WebCore::FrameLoadTypeRedirectWithLockedBackForwardList); checkException(env); + DBG_NAV_LOG("call updateFrameCache"); m_check_domtree_version = false; updateFrameCache(); @@ -909,12 +966,7 @@ void WebViewCore::updateViewport() LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue->m_updateViewport); + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_updateViewport); checkException(env); } @@ -924,12 +976,7 @@ void WebViewCore::restoreScale(int scale) LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue->m_restoreScale, scale); + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_restoreScale, scale); checkException(env); } @@ -939,12 +986,8 @@ void WebViewCore::restoreScreenWidthScale(int scale) LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue->m_restoreScreenWidthScale, scale); + env->CallVoidMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_restoreScreenWidthScale, scale); checkException(env); } @@ -955,28 +998,19 @@ void WebViewCore::needTouchEvents(bool need) #if ENABLE(TOUCH_EVENTS) // Android JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue->m_needTouchEvents, need); + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_needTouchEvents, need); checkException(env); #endif } -void WebViewCore::requestKeyboard(bool showKeyboard) +void WebViewCore::requestKeyboard(bool showKeyboard, bool isTextView) { - DEBUG_NAV_UI_LOGD("%s", __FUNCTION__); + DBG_NAV_LOGD("showKeyboard=%d", showKeyboard); LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!"); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue->m_requestKeyboard, showKeyboard); + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_requestKeyboard, showKeyboard, + isTextView); checkException(env); } @@ -1047,15 +1081,13 @@ void WebViewCore::setGlobalBounds(int x, int y, int h, int v) void WebViewCore::setSizeScreenWidthAndScale(int width, int height, int screenWidth, float scale, int realScreenWidth, int screenHeight, - int anchorX, int anchorY, bool ignoreHeight) + bool ignoreHeight) { WebCoreViewBridge* window = m_mainFrame->view()->platformWidget(); int ow = window->width(); int oh = window->height(); window->setSize(width, height); int osw = m_screenWidth; - int orsw = m_screenWidth * m_screenWidthScale / m_scale; - int osh = m_screenHeight; DBG_NAV_LOGD("old:(w=%d,h=%d,sw=%d,scale=%g) new:(w=%d,h=%d,sw=%d,scale=%g)", ow, oh, osw, m_scale, width, height, screenWidth, scale); m_screenWidth = screenWidth; @@ -1074,63 +1106,46 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height, DBG_NAV_LOGD("renderer=%p view=(w=%d,h=%d)", r, realScreenWidth, screenHeight); if (r) { - WebCore::IntPoint anchorPoint; - if ((anchorX | anchorY) == 0) - // get current screen center position - anchorPoint = WebCore::IntPoint(m_scrollOffsetX - + (realScreenWidth >> 1), m_scrollOffsetY - + (screenHeight >> 1)); - else - anchorPoint = WebCore::IntPoint(anchorX, anchorY); - WebCore::HitTestResult hitTestResult = m_mainFrame->eventHandler()-> - hitTestResultAtPoint(anchorPoint, false); - WebCore::Node* node = hitTestResult.innerNode(); + // get current screen center position + WebCore::IntPoint screenCenter = WebCore::IntPoint( + m_scrollOffsetX + (realScreenWidth >> 1), + m_scrollOffsetY + (screenHeight >> 1)); + WebCore::Node* node = 0; WebCore::IntRect bounds; WebCore::IntPoint offset; + // If the screen width changed, it is probably zoom change or + // orientation change. Try to keep the node in the center of the + // screen staying at the same place. + if (osw != screenWidth) { + WebCore::HitTestResult hitTestResult = + m_mainFrame->eventHandler()-> hitTestResultAtPoint( + screenCenter, false); + node = hitTestResult.innerNode(); + } if (node) { bounds = node->getRect(); DBG_NAV_LOGD("ob:(x=%d,y=%d,w=%d,h=%d)", bounds.x(), bounds.y(), bounds.width(), bounds.height()); - if ((anchorX | anchorY) == 0) { - offset = WebCore::IntPoint(anchorPoint.x() - bounds.x(), - anchorPoint.y() - bounds.y()); - if (offset.x() < 0 || offset.x() > realScreenWidth || - offset.y() < 0 || offset.y() > screenHeight) - { - DBG_NAV_LOGD("offset out of bounds:(x=%d,y=%d)", - offset.x(), offset.y()); - node = 0; - } + offset = WebCore::IntPoint(screenCenter.x() - bounds.x(), + screenCenter.y() - bounds.y()); + if (offset.x() < 0 || offset.x() > realScreenWidth || + offset.y() < 0 || offset.y() > screenHeight) + { + DBG_NAV_LOGD("offset out of bounds:(x=%d,y=%d)", + offset.x(), offset.y()); + node = 0; } } r->setNeedsLayoutAndPrefWidthsRecalc(); m_mainFrame->view()->forceLayout(); // scroll to restore current screen center - if (!node) - return; - const WebCore::IntRect& newBounds = node->getRect(); - DBG_NAV_LOGD("nb:(x=%d,y=%d,w=%d," - "h=%d,ns=%d)", newBounds.x(), newBounds.y(), - newBounds.width(), newBounds.height()); - if ((anchorX | anchorY) == 0) - scrollBy(newBounds.x() - bounds.x(), - newBounds.y() - bounds.y(), false); - else if ((orsw && osh && bounds.width() && bounds.height()) - && (bounds != newBounds)) { - WebCore::FrameView* view = m_mainFrame->view(); - // force left align if width is not changed while height changed. - // the anchorPoint is probably at some white space in the node - // which is affected by text wrap around the screen width. - bool leftAlign = (osw != m_screenWidth) - && (bounds.width() == newBounds.width()) - && (bounds.height() != newBounds.height()); - showRect(newBounds.x(), newBounds.y(), newBounds.width(), - newBounds.height(), view->contentsWidth(), - view->contentsHeight(), - leftAlign ? 0.0 : (float) (anchorX - bounds.x()) / bounds.width(), - leftAlign ? 0.0 : (float) (anchorX - m_scrollOffsetX) / orsw, - (float) (anchorY - bounds.y()) / bounds.height(), - (float) (anchorY - m_scrollOffsetY) / osh); + if (node) { + const WebCore::IntRect& newBounds = node->getRect(); + DBG_NAV_LOGD("nb:(x=%d,y=%d,w=%d," + "h=%d,ns=%d)", newBounds.x(), newBounds.y(), + newBounds.width(), newBounds.height()); + scrollBy(newBounds.x() - bounds.x(), newBounds.y() - bounds.y(), + false); } } } @@ -1155,26 +1170,24 @@ void WebViewCore::dumpDomTree(bool useFile) void WebViewCore::dumpRenderTree(bool useFile) { #ifdef ANDROID_DOM_LOGGING - if (useFile) - gRenderTreeFile = fopen(RENDER_TREE_LOG_FILE, "w"); - WebCore::CString renderDump = WebCore::externalRepresentation(m_mainFrame->contentRenderer()).utf8(); + WebCore::CString renderDump = WebCore::externalRepresentation(m_mainFrame).utf8(); const char* data = renderDump.data(); - int length = renderDump.length(); - int last = 0; - for (int i = 0; i < length; i++) { - if (data[i] == '\n') { - if (i != last) { - char* chunk = new char[i - last + 1]; - strncpy(chunk, (data + last), i - last); - chunk[i - last] = '\0'; - DUMP_RENDER_LOGD("%s", chunk); - } - last = i + 1; - } - } - if (gRenderTreeFile) { + if (useFile) { + gRenderTreeFile = fopen(RENDER_TREE_LOG_FILE, "w"); + DUMP_RENDER_LOGD("%s", data); fclose(gRenderTreeFile); gRenderTreeFile = 0; + } else { + // adb log can only output 1024 characters, so write out line by line. + // exclude '\n' as adb log adds it for each output. + int length = renderDump.length(); + for (int i = 0, last = 0; i < length; i++) { + if (data[i] == '\n') { + if (i != last) + DUMP_RENDER_LOGD("%.*s", (i - last), &(data[last])); + last = i + 1; + } + } } #endif } @@ -1186,14 +1199,41 @@ void WebViewCore::dumpNavTree() #endif } -WebCore::String WebViewCore::retrieveHref(WebCore::Frame* frame, WebCore::Node* node) +WebCore::HTMLAnchorElement* WebViewCore::retrieveAnchorElement(WebCore::Frame* frame, WebCore::Node* node) { if (!CacheBuilder::validNode(m_mainFrame, frame, node)) - return WebCore::String(); + return 0; if (!node->hasTagName(WebCore::HTMLNames::aTag)) - return WebCore::String(); - WebCore::HTMLAnchorElement* anchor = static_cast<WebCore::HTMLAnchorElement*>(node); - return anchor->href(); + return 0; + return static_cast<WebCore::HTMLAnchorElement*>(node); +} + +WebCore::String WebViewCore::retrieveHref(WebCore::Frame* frame, WebCore::Node* node) +{ + WebCore::HTMLAnchorElement* anchor = retrieveAnchorElement(frame, node); + return anchor ? anchor->href() : WebCore::String(); +} + +WebCore::String WebViewCore::retrieveAnchorText(WebCore::Frame* frame, WebCore::Node* node) +{ + WebCore::HTMLAnchorElement* anchor = retrieveAnchorElement(frame, node); + return anchor ? anchor->text() : WebCore::String(); +} + +WebCore::String WebViewCore::requestLabel(WebCore::Frame* frame, + WebCore::Node* node) +{ + if (CacheBuilder::validNode(m_mainFrame, frame, node)) { + RefPtr<WebCore::NodeList> list = node->document()->getElementsByTagName("label"); + unsigned length = list->length(); + for (unsigned i = 0; i < length; i++) { + WebCore::HTMLLabelElement* label = static_cast<WebCore::HTMLLabelElement*>( + list->item(i)); + if (label->correspondingControl() == node) + return label->innerHTML(); + } + } + return WebCore::String(); } void WebViewCore::updateCacheOnNodeChange() @@ -1226,6 +1266,12 @@ void WebViewCore::updateCacheOnNodeChange() void WebViewCore::updateFrameCache() { +#if USE(ACCELERATED_COMPOSITING) + ChromeClientAndroid* chromeC = static_cast<ChromeClientAndroid*>( + mainFrame()->page()->chrome()->client()); + chromeC->scheduleCompositingLayerSync(); +#endif + if (!m_frameCacheOutOfDate) { DBG_NAV_LOG("!m_frameCacheOutOfDate"); return; @@ -1300,6 +1346,11 @@ void WebViewCore::removePlugin(PluginWidgetAndroid* w) } } +bool WebViewCore::isPlugin(PluginWidgetAndroid* w) const +{ + return m_plugins.find(w) >= 0; +} + void WebViewCore::invalPlugin(PluginWidgetAndroid* w) { const double PLUGIN_INVAL_DELAY = 1.0 / 60; @@ -1398,6 +1449,18 @@ void WebViewCore::sendPluginEvent(const ANPEvent& evt) } } +PluginWidgetAndroid* WebViewCore::getPluginWidget(NPP npp) +{ + PluginWidgetAndroid** iter = m_plugins.begin(); + PluginWidgetAndroid** stop = m_plugins.end(); + for (; iter < stop; ++iter) { + if ((*iter)->pluginView()->instance() == npp) { + return (*iter); + } + } + return NULL; +} + static PluginView* nodeIsPlugin(Node* node) { RenderObject* renderer = node->renderer(); if (renderer && renderer->isWidget()) { @@ -1421,33 +1484,6 @@ Node* WebViewCore::cursorNodeIsPlugin() { return 0; } - -void WebViewCore::updatePluginState(Frame* frame, Node* node, PluginState state) { - - // check that the node and frame pointers are (still) valid - if (!frame || !node || !CacheBuilder::validNode(m_mainFrame, frame, node)) - return; - - // check that the node is a plugin view - PluginView* pluginView = nodeIsPlugin(node); - if (!pluginView) - return; - - // create the event - ANPEvent event; - SkANP::InitEvent(&event, kLifecycle_ANPEventType); - - if (state == kLoseFocus_PluginState) - event.data.lifecycle.action = kLoseFocus_ANPLifecycleAction; - else if (state == kGainFocus_PluginState) - event.data.lifecycle.action = kGainFocus_ANPLifecycleAction; - else - return; - - // send the event - pluginView->platformPluginWidget()->sendEvent(event); -} - /////////////////////////////////////////////////////////////////////////////// void WebViewCore::moveMouseIfLatest(int moveGeneration, WebCore::Frame* frame, int x, int y) @@ -1464,7 +1500,26 @@ void WebViewCore::moveMouseIfLatest(int moveGeneration, moveMouse(frame, x, y); } -// Update mouse position and may change focused node. +void WebViewCore::moveFocus(WebCore::Frame* frame, WebCore::Node* node) +{ + DBG_NAV_LOGD("frame=%p node=%p", frame, node); + if (!node || !CacheBuilder::validNode(m_mainFrame, frame, node) + || !node->isElementNode()) + return; + // Code borrowed from FocusController::advanceFocus + WebCore::FocusController* focusController + = m_mainFrame->page()->focusController(); + WebCore::Document* oldDoc + = focusController->focusedOrMainFrame()->document(); + if (oldDoc->focusedNode() == node) + return; + if (node->document() != oldDoc) + oldDoc->setFocusedNode(0); + focusController->setFocusedFrame(frame); + static_cast<WebCore::Element*>(node)->focus(false); +} + +// Update mouse position void WebViewCore::moveMouse(WebCore::Frame* frame, int x, int y) { DBG_NAV_LOGD("frame=%p x=%d y=%d scrollOffset=(%d,%d)", frame, @@ -1482,161 +1537,6 @@ void WebViewCore::moveMouse(WebCore::Frame* frame, int x, int y) updateCacheOnNodeChange(); } -static int findTextBoxIndex(WebCore::Node* node, const WebCore::IntPoint& pt) -{ - if (!node->isTextNode()) { - DBG_NAV_LOGD("node=%p pt=(%d,%d) isText=false", node, pt.x(), pt.y()); - return -2; // error - } - WebCore::RenderText* renderText = (WebCore::RenderText*) node->renderer(); - if (!renderText) { - DBG_NAV_LOGD("node=%p pt=(%d,%d) renderText=0", node, pt.x(), pt.y()); - return -3; // error - } - FloatPoint absPt = renderText->localToAbsolute(); - WebCore::InlineTextBox *textBox = renderText->firstTextBox(); - int globalX, globalY; - CacheBuilder::GetGlobalOffset(node, &globalX, &globalY); - int x = pt.x() - globalX; - int y = pt.y() - globalY; - do { - int textBoxStart = textBox->start(); - int textBoxEnd = textBoxStart + textBox->len(); - if (textBoxEnd <= textBoxStart) - continue; - WebCore::IntRect bounds = textBox->selectionRect(absPt.x(), absPt.y(), - textBoxStart, textBoxEnd); - if (!bounds.contains(x, y)) - continue; - int offset = textBox->offsetForPosition(x - absPt.x()); -#if DEBUG_NAV_UI - int prior = offset > 0 ? textBox->positionForOffset(offset - 1) : -1; - int current = textBox->positionForOffset(offset); - int next = textBox->positionForOffset(offset + 1); - DBG_NAV_LOGD( - "offset=%d pt.x=%d globalX=%d renderX=%d x=%d " - "textBox->x()=%d textBox->start()=%d prior=%d current=%d next=%d", - offset, pt.x(), globalX, absPt.x(), x, - textBox->x(), textBox->start(), prior, current, next - ); -#endif - return textBox->start() + offset; - } while ((textBox = textBox->nextTextBox())); - return -1; // couldn't find point, may have walked off end -} - -static inline bool isPunctuation(UChar c) -{ - return WTF::Unicode::category(c) & (0 - | WTF::Unicode::Punctuation_Dash - | WTF::Unicode::Punctuation_Open - | WTF::Unicode::Punctuation_Close - | WTF::Unicode::Punctuation_Connector - | WTF::Unicode::Punctuation_Other - | WTF::Unicode::Punctuation_InitialQuote - | WTF::Unicode::Punctuation_FinalQuote - ); -} - -static int centerX(const SkIRect& rect) -{ - return (rect.fLeft + rect.fRight) >> 1; -} - -static int centerY(const SkIRect& rect) -{ - return (rect.fTop + rect.fBottom) >> 1; -} - -WebCore::String WebViewCore::getSelection(SkRegion* selRgn) -{ - SkRegion::Iterator iter(*selRgn); - // FIXME: switch this to use StringBuilder instead - WebCore::String result; - WebCore::Node* lastStartNode = 0; - int lastStartEnd = -1; - UChar lastChar = 0xffff; - for (; !iter.done(); iter.next()) { - const SkIRect& rect = iter.rect(); - DBG_NAV_LOGD("rect=(%d, %d, %d, %d)", rect.fLeft, rect.fTop, - rect.fRight, rect.fBottom); - int cy = centerY(rect); - WebCore::IntPoint startPt = WebCore::IntPoint(rect.fLeft + 1, cy); - WebCore::HitTestResult hitTestResult = m_mainFrame->eventHandler()-> - hitTestResultAtPoint(startPt, false); - WebCore::Node* node = hitTestResult.innerNode(); - if (!node) { - DBG_NAV_LOG("!node"); - return result; - } - WebCore::IntPoint endPt = WebCore::IntPoint(rect.fRight - 1, cy); - hitTestResult = m_mainFrame->eventHandler()->hitTestResultAtPoint(endPt, false); - WebCore::Node* endNode = hitTestResult.innerNode(); - if (!endNode) { - DBG_NAV_LOG("!endNode (right-1)"); - endPt = WebCore::IntPoint(rect.fRight - 2, cy); - hitTestResult = m_mainFrame->eventHandler()->hitTestResultAtPoint(endPt, false); - endNode = hitTestResult.innerNode(); - } - if (!endNode) { - DBG_NAV_LOG("!endNode (right-2)"); - return result; - } - int start = findTextBoxIndex(node, startPt); - if (start < 0) - continue; - int end = findTextBoxIndex(endNode, endPt); - if (end < -1) // use node if endNode is not valid - endNode = node; - if (end <= 0) - end = static_cast<WebCore::Text*>(endNode)->string()->length(); - DBG_NAV_LOGD("node=%p start=%d endNode=%p end=%d", node, start, endNode, end); - WebCore::Node* startNode = node; - do { - if (!node->isTextNode()) - continue; - if (node->getRect().isEmpty()) - continue; - WebCore::Text* textNode = static_cast<WebCore::Text*>(node); - WebCore::StringImpl* string = textNode->string(); - if (!string->length()) - continue; - const UChar* chars = string->characters(); - int newLength = node == endNode ? end : string->length(); - if (node == startNode) { - #if DEBUG_NAV_UI - if (node == lastStartNode) - DBG_NAV_LOGD("start=%d last=%d", start, lastStartEnd); - #endif - if (node == lastStartNode && start < lastStartEnd) - break; // skip rect if text overlaps already written text - lastStartNode = node; - lastStartEnd = newLength - start; - } - if (newLength < start) { - DBG_NAV_LOGD("newLen=%d < start=%d", newLength, start); - break; - } - if (!isPunctuation(chars[start])) - result.append(' '); - result.append(chars + start, newLength - start); - start = 0; - } while (node != endNode && (node = node->traverseNextNode())); - } - result = result.simplifyWhiteSpace().stripWhiteSpace(); -#if DUMP_NAV_CACHE - { - char buffer[256]; - CacheBuilder::Debug debug; - debug.init(buffer, sizeof(buffer)); - debug.print("copy: "); - debug.wideString(result); - DUMP_NAV_LOGD("%s", buffer); - } -#endif - return result; -} - void WebViewCore::setSelection(int start, int end) { WebCore::Node* focus = currentFocus(); @@ -1670,7 +1570,16 @@ void WebViewCore::deleteSelection(int start, int end, int textGeneration) WebCore::Node* focus = currentFocus(); if (!focus) return; - WebCore::TypingCommand::deleteSelection(focus->document()); + // Prevent our editor client from passing a message to change the + // selection. + EditorClientAndroid* client = static_cast<EditorClientAndroid*>( + m_mainFrame->editor()->client()); + client->setUiGeneratedSelectionChange(true); + PlatformKeyboardEvent down(kKeyCodeDel, 0, 0, true, false, false, false); + PlatformKeyboardEvent up(kKeyCodeDel, 0, 0, false, false, false, false); + key(down); + key(up); + client->setUiGeneratedSelectionChange(false); m_textGeneration = textGeneration; } @@ -1765,7 +1674,7 @@ void WebViewCore::saveDocumentState(WebCore::Frame* frame) { if (!CacheBuilder::validNode(m_mainFrame, frame, 0)) frame = m_mainFrame; - WebCore::HistoryItem *item = frame->loader()->currentHistoryItem(); + WebCore::HistoryItem *item = frame->loader()->history()->currentItem(); // item can be null when there is no offical URL for the current page. This happens // when the content is loaded using with WebCoreFrameBridge::LoadData() and there @@ -1883,6 +1792,21 @@ static jobjectArray makeLabelArray(JNIEnv* env, const uint16_t** labels, size_t return array; } +void WebViewCore::openFileChooser(PassRefPtr<WebCore::FileChooser> chooser) { + if (!chooser) + return; + JNIEnv* env = JSC::Bindings::getJNIEnv(); + jstring jName = (jstring) env->CallObjectMethod( + m_javaGlue->object(env).get(), m_javaGlue->m_openFileChooser); + checkException(env); + const UChar* string = (const UChar*) env->GetStringChars(jName, NULL); + if (!string) + return; + WebCore::String webcoreString = to_string(env, jName); + env->ReleaseStringChars(jName, string); + chooser->chooseFile(webcoreString); +} + void WebViewCore::listBoxRequest(WebCoreReply* reply, const uint16_t** labels, size_t count, const int enabled[], size_t enabledCount, bool multiple, const int selected[], size_t selectedCountOrSelection) { @@ -1894,22 +1818,17 @@ void WebViewCore::listBoxRequest(WebCoreReply* reply, const uint16_t** labels, s // Create an array of java Strings for the drop down. JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; jobjectArray labelArray = makeLabelArray(env, labels, count); // Create an array determining whether each item is enabled. - jbooleanArray enabledArray = env->NewBooleanArray(enabledCount); + jintArray enabledArray = env->NewIntArray(enabledCount); checkException(env); - jboolean* ptrArray = env->GetBooleanArrayElements(enabledArray, 0); + jint* ptrArray = env->GetIntArrayElements(enabledArray, 0); checkException(env); for (size_t i = 0; i < enabledCount; i++) { ptrArray[i] = enabled[i]; } - env->ReleaseBooleanArrayElements(enabledArray, ptrArray, 0); + env->ReleaseIntArrayElements(enabledArray, ptrArray, 0); checkException(env); if (multiple) { @@ -1923,11 +1842,15 @@ void WebViewCore::listBoxRequest(WebCoreReply* reply, const uint16_t** labels, s } env->ReleaseIntArrayElements(selectedArray, selArray, 0); - env->CallVoidMethod(obj.get(), m_javaGlue->m_requestListBox, labelArray, enabledArray, selectedArray); + env->CallVoidMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_requestListBox, labelArray, enabledArray, + selectedArray); env->DeleteLocalRef(selectedArray); } else { // Pass up the single selection. - env->CallVoidMethod(obj.get(), m_javaGlue->m_requestSingleListBox, labelArray, enabledArray, selectedCountOrSelection); + env->CallVoidMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_requestSingleListBox, labelArray, enabledArray, + selectedCountOrSelection); } env->DeleteLocalRef(labelArray); @@ -1972,9 +1895,19 @@ void WebViewCore::click(WebCore::Frame* frame, WebCore::Node* node) { } } -bool WebViewCore::handleTouchEvent(int action, int x, int y) +int WebViewCore::handleTouchEvent(int action, int x, int y) { - bool preventDefault = false; + int preventDefault = 0; + +#if USE(ACCELERATED_COMPOSITING) + RenderView* contentRenderer = m_mainFrame->contentRenderer(); + GraphicsLayerAndroid* rootLayer = 0; + if (contentRenderer) + rootLayer = static_cast<GraphicsLayerAndroid*>( + contentRenderer->compositor()->rootPlatformLayer()); + if (rootLayer) + rootLayer->pauseDisplay(true); +#endif #if ENABLE(TOUCH_EVENTS) // Android WebCore::TouchEventType type = WebCore::TouchEventCancel; @@ -1991,12 +1924,22 @@ bool WebViewCore::handleTouchEvent(int action, int x, int y) case 3: // MotionEvent.ACTION_CANCEL type = WebCore::TouchEventCancel; break; + case 0x100: // WebViewCore.ACTION_LONGPRESS + type = WebCore::TouchEventLongPress; + break; + case 0x200: // WebViewCore.ACTION_DOUBLETAP + type = WebCore::TouchEventDoubleTap; + break; } WebCore::IntPoint pt(x - m_scrollOffsetX, y - m_scrollOffsetY); WebCore::PlatformTouchEvent te(pt, pt, type); preventDefault = m_mainFrame->eventHandler()->handleTouchEvent(te); #endif +#if USE(ACCELERATED_COMPOSITING) + if (rootLayer) + rootLayer->pauseDisplay(false); +#endif return preventDefault; } @@ -2008,35 +1951,16 @@ void WebViewCore::touchUp(int touchGeneration, " x=%d y=%d", m_touchGeneration, touchGeneration, x, y); return; // short circuit if a newer touch has been generated } + // This moves m_mousePos to the correct place, and handleMouseClick uses + // m_mousePos to determine where the click happens. moveMouse(frame, x, y); m_lastGeneration = touchGeneration; if (frame && CacheBuilder::validNode(m_mainFrame, frame, 0)) { frame->loader()->resetMultipleFormSubmissionProtection(); } - // If the click is on an unselected textfield/area we do not want to allow - // the click to change the selection, because we will set it ourselves - // elsewhere - beginning for textareas, end for textfields - bool needToIgnoreChangesToSelectedRange = true; - WebCore::Node* focusNode = currentFocus(); - if (focusNode) { - WebCore::RenderObject* renderer = focusNode->renderer(); - if (renderer && (renderer->isTextField() || renderer->isTextArea())) { - // Now check to see if the click is inside the focused textfield - if (focusNode->getRect().contains(x, y)) - needToIgnoreChangesToSelectedRange = false; - } - } - EditorClientAndroid* client = 0; - if (needToIgnoreChangesToSelectedRange) { - client = static_cast<EditorClientAndroid*>( - m_mainFrame->editor()->client()); - client->setShouldChangeSelectedRange(false); - } DBG_NAV_LOGD("touchGeneration=%d handleMouseClick frame=%p node=%p" " x=%d y=%d", touchGeneration, frame, node, x, y); handleMouseClick(frame, node); - if (needToIgnoreChangesToSelectedRange) - client->setShouldChangeSelectedRange(true); } // Common code for both clicking with the trackball and touchUp @@ -2060,6 +1984,13 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node WebCore::HTMLSelectElement* select = static_cast<WebCore::HTMLSelectElement*>(nodePtr); const WTF::Vector<WebCore::Element*>& listItems = select->listItems(); SkTDArray<const uint16_t*> names; + // Possible values for enabledArray. Keep in Sync with values in + // InvokeListBox.Container in WebView.java + enum OptionStatus { + OPTGROUP = -1, + OPTION_DISABLED = 0, + OPTION_ENABLED = 1, + }; SkTDArray<int> enabledArray; SkTDArray<int> selectedArray; int size = listItems.size(); @@ -2068,13 +1999,13 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node if (listItems[i]->hasTagName(WebCore::HTMLNames::optionTag)) { WebCore::HTMLOptionElement* option = static_cast<WebCore::HTMLOptionElement*>(listItems[i]); *names.append() = stringConverter(option->textIndentedToRespectGroupLabel()); - *enabledArray.append() = option->disabled() ? 0 : 1; + *enabledArray.append() = option->disabled() ? OPTION_DISABLED : OPTION_ENABLED; if (multiple && option->selected()) *selectedArray.append() = i; } else if (listItems[i]->hasTagName(WebCore::HTMLNames::optgroupTag)) { WebCore::HTMLOptGroupElement* optGroup = static_cast<WebCore::HTMLOptGroupElement*>(listItems[i]); *names.append() = stringConverter(optGroup->groupLabelText()); - *enabledArray.append() = 0; + *enabledArray.append() = OPTGROUP; } } WebCoreReply* reply = new ListBoxReply(select, select->document()->frame(), this); @@ -2109,8 +2040,12 @@ bool WebViewCore::handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* node m_mousePos.y(), focusNode, handled ? "true" : "false"); if (focusNode) { WebCore::RenderObject* renderer = focusNode->renderer(); - if (renderer && (renderer->isTextField() || renderer->isTextArea())) - setFocusControllerActive(true); + if (renderer && (renderer->isTextField() || renderer->isTextArea())) { + bool ime = !(static_cast<WebCore::HTMLInputElement*>(focusNode)) + ->readOnly(); + setFocusControllerActive(ime); + requestKeyboard(ime, true); + } } return handled; } @@ -2135,14 +2070,11 @@ void WebViewCore::popupReply(const int* array, int count) void WebViewCore::addMessageToConsole(const WebCore::String& message, unsigned int lineNumber, const WebCore::String& sourceID) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; jstring jMessageStr = env->NewString((unsigned short *)message.characters(), message.length()); jstring jSourceIDStr = env->NewString((unsigned short *)sourceID.characters(), sourceID.length()); - env->CallVoidMethod(obj.get(), m_javaGlue->m_addMessageToConsole, jMessageStr, lineNumber, jSourceIDStr); + env->CallVoidMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_addMessageToConsole, jMessageStr, lineNumber, + jSourceIDStr); env->DeleteLocalRef(jMessageStr); env->DeleteLocalRef(jSourceIDStr); checkException(env); @@ -2151,14 +2083,9 @@ void WebViewCore::addMessageToConsole(const WebCore::String& message, unsigned i void WebViewCore::jsAlert(const WebCore::String& url, const WebCore::String& text) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; jstring jInputStr = env->NewString((unsigned short *)text.characters(), text.length()); jstring jUrlStr = env->NewString((unsigned short *)url.characters(), url.length()); - env->CallVoidMethod(obj.get(), m_javaGlue->m_jsAlert, jUrlStr, jInputStr); + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_jsAlert, jUrlStr, jInputStr); env->DeleteLocalRef(jInputStr); env->DeleteLocalRef(jUrlStr); checkException(env); @@ -2168,14 +2095,11 @@ void WebViewCore::exceededDatabaseQuota(const WebCore::String& url, const WebCor { #if ENABLE(DATABASE) JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; jstring jDatabaseIdentifierStr = env->NewString((unsigned short *)databaseIdentifier.characters(), databaseIdentifier.length()); jstring jUrlStr = env->NewString((unsigned short *)url.characters(), url.length()); - env->CallVoidMethod(obj.get(), m_javaGlue->m_exceededDatabaseQuota, jUrlStr, jDatabaseIdentifierStr, currentQuota, estimatedSize); + env->CallVoidMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_exceededDatabaseQuota, jUrlStr, + jDatabaseIdentifierStr, currentQuota, estimatedSize); env->DeleteLocalRef(jDatabaseIdentifierStr); env->DeleteLocalRef(jUrlStr); checkException(env); @@ -2186,12 +2110,8 @@ void WebViewCore::reachedMaxAppCacheSize(const unsigned long long spaceNeeded) { #if ENABLE(OFFLINE_WEB_APPLICATIONS) JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue->m_reachedMaxAppCacheSize, spaceNeeded); + env->CallVoidMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_reachedMaxAppCacheSize, spaceNeeded); checkException(env); #endif } @@ -2200,25 +2120,15 @@ void WebViewCore::populateVisitedLinks(WebCore::PageGroup* group) { m_groupForVisitedLinks = group; JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue->m_populateVisitedLinks); + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_populateVisitedLinks); checkException(env); } void WebViewCore::geolocationPermissionsShowPrompt(const WebCore::String& origin) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; jstring originString = env->NewString((unsigned short *)origin.characters(), origin.length()); - env->CallVoidMethod(obj.get(), + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_geolocationPermissionsShowPrompt, originString); env->DeleteLocalRef(originString); @@ -2228,12 +2138,7 @@ void WebViewCore::geolocationPermissionsShowPrompt(const WebCore::String& origin void WebViewCore::geolocationPermissionsHidePrompt() { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_geolocationPermissionsHidePrompt); checkException(env); } @@ -2241,14 +2146,9 @@ void WebViewCore::geolocationPermissionsHidePrompt() bool WebViewCore::jsConfirm(const WebCore::String& url, const WebCore::String& text) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return false; jstring jInputStr = env->NewString((unsigned short *)text.characters(), text.length()); jstring jUrlStr = env->NewString((unsigned short *)url.characters(), url.length()); - jboolean result = env->CallBooleanMethod(obj.get(), m_javaGlue->m_jsConfirm, jUrlStr, jInputStr); + jboolean result = env->CallBooleanMethod(m_javaGlue->object(env).get(), m_javaGlue->m_jsConfirm, jUrlStr, jInputStr); env->DeleteLocalRef(jInputStr); env->DeleteLocalRef(jUrlStr); checkException(env); @@ -2258,16 +2158,10 @@ bool WebViewCore::jsConfirm(const WebCore::String& url, const WebCore::String& t bool WebViewCore::jsPrompt(const WebCore::String& url, const WebCore::String& text, const WebCore::String& defaultValue, WebCore::String& result) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return false; - jstring jInputStr = env->NewString((unsigned short *)text.characters(), text.length()); jstring jDefaultStr = env->NewString((unsigned short *)defaultValue.characters(), defaultValue.length()); jstring jUrlStr = env->NewString((unsigned short *)url.characters(), url.length()); - jstring returnVal = (jstring) env->CallObjectMethod(obj.get(), m_javaGlue->m_jsPrompt, jUrlStr, jInputStr, jDefaultStr); + jstring returnVal = (jstring) env->CallObjectMethod(m_javaGlue->object(env).get(), m_javaGlue->m_jsPrompt, jUrlStr, jInputStr, jDefaultStr); // If returnVal is null, it means that the user cancelled the dialog. if (!returnVal) return false; @@ -2283,14 +2177,9 @@ bool WebViewCore::jsPrompt(const WebCore::String& url, const WebCore::String& te bool WebViewCore::jsUnload(const WebCore::String& url, const WebCore::String& message) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return false; jstring jInputStr = env->NewString((unsigned short *)message.characters(), message.length()); jstring jUrlStr = env->NewString((unsigned short *)url.characters(), url.length()); - jboolean result = env->CallBooleanMethod(obj.get(), m_javaGlue->m_jsUnload, jUrlStr, jInputStr); + jboolean result = env->CallBooleanMethod(m_javaGlue->object(env).get(), m_javaGlue->m_jsUnload, jUrlStr, jInputStr); env->DeleteLocalRef(jInputStr); env->DeleteLocalRef(jUrlStr); checkException(env); @@ -2300,12 +2189,7 @@ bool WebViewCore::jsUnload(const WebCore::String& url, const WebCore::String& me bool WebViewCore::jsInterrupt() { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return true; // default to interrupt - jboolean result = env->CallBooleanMethod(obj.get(), m_javaGlue->m_jsInterrupt); + jboolean result = env->CallBooleanMethod(m_javaGlue->object(env).get(), m_javaGlue->m_jsInterrupt); checkException(env); return result; } @@ -2320,12 +2204,7 @@ jobject WebViewCore::getWebViewJavaObject() { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return 0; - return env->GetObjectField(obj.get(), gWebViewCoreFields.m_webView); + return env->GetObjectField(m_javaGlue->object(env).get(), gWebViewCoreFields.m_webView); } void WebViewCore::updateTextSelection() { @@ -2337,12 +2216,7 @@ void WebViewCore::updateTextSelection() { return; RenderTextControl* rtc = static_cast<RenderTextControl*>(renderer); JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_updateTextSelection, reinterpret_cast<int>(focusNode), rtc->selectionStart(), rtc->selectionEnd(), m_textGeneration); checkException(env); @@ -2354,21 +2228,15 @@ void WebViewCore::updateTextfield(WebCore::Node* ptr, bool changeToPassword, if (m_blockTextfieldUpdates) return; JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - if (changeToPassword) { - env->CallVoidMethod(obj.get(), m_javaGlue->m_updateTextfield, + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_updateTextfield, (int) ptr, true, 0, m_textGeneration); checkException(env); return; } int length = text.length(); jstring string = env->NewString((unsigned short *) text.characters(), length); - env->CallVoidMethod(obj.get(), m_javaGlue->m_updateTextfield, + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_updateTextfield, (int) ptr, false, string, m_textGeneration); env->DeleteLocalRef(string); checkException(env); @@ -2377,13 +2245,8 @@ void WebViewCore::updateTextfield(WebCore::Node* ptr, bool changeToPassword, void WebViewCore::clearTextEntry() { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - - env->CallVoidMethod(obj.get(), m_javaGlue->m_clearTextEntry); + env->CallVoidMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_clearTextEntry); } void WebViewCore::setBackgroundColor(SkColor c) @@ -2398,73 +2261,106 @@ void WebViewCore::setBackgroundColor(SkColor c) view->setBaseBackgroundColor(bcolor); } -void WebViewCore::startFullScreenPluginActivity(const char* libName, - const char* className, NPP npp) +jclass WebViewCore::getPluginClass(const WebCore::String& libName, const char* className) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - jstring libString = env->NewStringUTF(libName); + jstring libString = env->NewString(libName.characters(), libName.length()); + jstring classString = env->NewStringUTF(className); + jobject pluginClass = env->CallObjectMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_getPluginClass, + libString, classString); + checkException(env); + + // cleanup unneeded local JNI references + env->DeleteLocalRef(libString); + env->DeleteLocalRef(classString); + + if (pluginClass != NULL) { + return static_cast<jclass>(pluginClass); + } else { + return NULL; + } +} + +void WebViewCore::showFullScreenPlugin(jobject childView, NPP npp, int x, + int y, int width, int height) +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - jstring classString = env->NewStringUTF(className); env->CallVoidMethod(obj.get(), - m_javaGlue->m_startFullScreenPluginActivity, - libString, classString, (int) npp); + m_javaGlue->m_showFullScreenPlugin, + childView, (int)npp, x, y, width, height); checkException(env); } -jobject WebViewCore::createSurface(const char* libName, const char* className, - NPP npp, int x, int y, int width, int height) +void WebViewCore::hideFullScreenPlugin() { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return 0; + env->CallVoidMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_hideFullScreenPlugin); + checkException(env); +} - jstring libString = env->NewStringUTF(libName); - jstring classString = env->NewStringUTF(className); - jobject result = env->CallObjectMethod(obj.get(), - m_javaGlue->m_createSurface, libString, - classString,(int) npp, x, y, width, height); +void WebViewCore::updateFullScreenPlugin(int x, int y, int width, int height) +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->CallVoidMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_updateFullScreenPlugin, x, y, + width, height); + checkException(env); +} + +jobject WebViewCore::addSurface(jobject view, int x, int y, int width, int height) +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + jobject result = env->CallObjectMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_addSurface, + view, x, y, width, height); checkException(env); return result; +} +void WebViewCore::updateSurface(jobject childView, int x, int y, int width, int height) +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->CallVoidMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_updateSurface, childView, + x, y, width, height); + checkException(env); } void WebViewCore::destroySurface(jobject childView) { JNIEnv* env = JSC::Bindings::getJNIEnv(); - AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - - env->CallVoidMethod(obj.get(), m_javaGlue->m_destroySurface, childView); + env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_destroySurface, childView); checkException(env); } -void WebViewCore::showRect(int left, int top, int width, int height, - int contentWidth, int contentHeight, float xPercentInDoc, - float xPercentInView, float yPercentInDoc, float yPercentInView) +jobject WebViewCore::getContext() { JNIEnv* env = JSC::Bindings::getJNIEnv(); AutoJObject obj = m_javaGlue->object(env); - // if it is called during DESTROY is handled, the real object of WebViewCore - // can be gone. Check before using it. - if (!obj.get()) - return; - env->CallVoidMethod(obj.get(), m_javaGlue->m_showRect, left, top, width, - height, contentWidth, contentHeight, xPercentInDoc, xPercentInView, - yPercentInDoc, yPercentInView); + jobject result = env->CallObjectMethod(obj.get(), m_javaGlue->m_getContext); checkException(env); + return result; +} + +bool WebViewCore::validNodeAndBounds(Frame* frame, Node* node, + const IntRect& originalAbsoluteBounds) +{ + bool valid = CacheBuilder::validNode(m_mainFrame, frame, node); + if (!valid) + return false; + RenderObject* renderer = node->renderer(); + if (!renderer) + return false; + IntRect absBounds = node->hasTagName(HTMLNames::areaTag) + ? CacheBuilder::getAreaRect(static_cast<HTMLAreaElement*>(node)) + : renderer->absoluteBoundingBoxRect(); + return absBounds == originalAbsoluteBounds; } //---------------------------------------------------------------------- @@ -2480,6 +2376,13 @@ static jstring WebCoreStringToJString(JNIEnv *env, WebCore::String string) return ret; } +static jstring RequestLabel(JNIEnv *env, jobject obj, int framePointer, + int nodePointer) +{ + return WebCoreStringToJString(env, GET_NATIVE_VIEW(env, obj)->requestLabel( + (WebCore::Frame*) framePointer, (WebCore::Node*) nodePointer)); +} + static void UpdateFrameCacheIfLoading(JNIEnv *env, jobject obj) { GET_NATIVE_VIEW(env, obj)->updateFrameCacheIfLoading(); @@ -2487,7 +2390,7 @@ static void UpdateFrameCacheIfLoading(JNIEnv *env, jobject obj) static void SetSize(JNIEnv *env, jobject obj, jint width, jint height, jint screenWidth, jfloat scale, jint realScreenWidth, jint screenHeight, - jint anchorX, jint anchorY, jboolean ignoreHeight) + jboolean ignoreHeight) { #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); @@ -2496,7 +2399,7 @@ static void SetSize(JNIEnv *env, jobject obj, jint width, jint height, LOGV("webviewcore::nativeSetSize(%u %u)\n viewImpl: %p", (unsigned)width, (unsigned)height, viewImpl); LOG_ASSERT(viewImpl, "viewImpl not set in nativeSetSize"); viewImpl->setSizeScreenWidthAndScale(width, height, screenWidth, scale, - realScreenWidth, screenHeight, anchorX, anchorY, ignoreHeight); + realScreenWidth, screenHeight, ignoreHeight); } static void SetScrollOffset(JNIEnv *env, jobject obj, jint gen, jint x, jint y) @@ -2711,7 +2614,7 @@ static jstring FindAddress(JNIEnv *env, jobject obj, jstring addr, return ret; } -static jboolean HandleTouchEvent(JNIEnv *env, jobject obj, jint action, jint x, jint y) +static jint HandleTouchEvent(JNIEnv *env, jobject obj, jint action, jint x, jint y) { #ifdef ANDROID_INSTRUMENT TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); @@ -2748,6 +2651,32 @@ static jstring RetrieveHref(JNIEnv *env, jobject obj, jint frame, return 0; } +static jstring RetrieveAnchorText(JNIEnv *env, jobject obj, jint frame, + jint node) +{ +#ifdef ANDROID_INSTRUMENT + TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); +#endif + WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); + LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__); + WebCore::String result = viewImpl->retrieveAnchorText((WebCore::Frame*) frame, + (WebCore::Node*) node); + if (!result.isEmpty()) + return WebCoreStringToJString(env, result); + return 0; +} + + +static void MoveFocus(JNIEnv *env, jobject obj, jint framePtr, jint nodePtr) +{ +#ifdef ANDROID_INSTRUMENT + TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); +#endif + WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); + LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__); + viewImpl->moveFocus((WebCore::Frame*) framePtr, (WebCore::Node*) nodePtr); +} + static void MoveMouse(JNIEnv *env, jobject obj, jint frame, jint x, jint y) { @@ -2836,20 +2765,6 @@ static void SetBackgroundColor(JNIEnv *env, jobject obj, jint color) viewImpl->setBackgroundColor((SkColor) color); } -static jstring GetSelection(JNIEnv *env, jobject obj, jobject selRgn) -{ -#ifdef ANDROID_INSTRUMENT - TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); -#endif - WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); - LOG_ASSERT(viewImpl, "viewImpl not set in %s", __FUNCTION__); - SkRegion* selectionRegion = GraphicsJNI::getNativeRegion(env, selRgn); - WebCore::String result = viewImpl->getSelection(selectionRegion); - if (!result.isEmpty()) - return WebCoreStringToJString(env, result); - return 0; -} - static void DumpDomTree(JNIEnv *env, jobject obj, jboolean useFile) { WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); @@ -2944,20 +2859,14 @@ static bool DrawContent(JNIEnv *env, jobject obj, jobject canv, jint color) return viewImpl->drawContent(canvas, color); } -static bool PictureReady(JNIEnv* env, jobject obj) +static bool FocusBoundsChanged(JNIEnv* env, jobject obj) { - return GET_NATIVE_VIEW(env, obj)->pictureReady(); + return GET_NATIVE_VIEW(env, obj)->focusBoundsChanged(); } -static void UpdatePluginState(JNIEnv* env, jobject obj, jint framePtr, jint nodePtr, jint state) +static bool PictureReady(JNIEnv* env, jobject obj) { -#ifdef ANDROID_INSTRUMENT - TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); -#endif - WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); - LOG_ASSERT(viewImpl, "viewImpl not set in nativeUpdatePluginState"); - viewImpl->updatePluginState((WebCore::Frame*) framePtr, (WebCore::Node*) nodePtr, - (PluginState) state); + return GET_NATIVE_VIEW(env, obj)->pictureReady(); } static void Pause(JNIEnv* env, jobject obj) @@ -3027,7 +2936,30 @@ static void ProvideVisitedHistory(JNIEnv *env, jobject obj, jobject hist) env->ReleaseStringChars(item, str); env->DeleteLocalRef(item); } - env->DeleteLocalRef(array); +} + +// Notification from the UI thread that the plugin's full-screen surface has been discarded +static void FullScreenPluginHidden(JNIEnv* env, jobject obj, jint npp) +{ + WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); + PluginWidgetAndroid* plugin = viewImpl->getPluginWidget((NPP)npp); + plugin->exitFullScreen(false); +} + +static WebCore::IntRect jrect_to_webrect(JNIEnv* env, jobject obj) +{ + int L, T, R, B; + GraphicsJNI::get_jrect(env, obj, &L, &T, &R, &B); + return WebCore::IntRect(L, T, R - L, B - T); +} + +static bool ValidNodeAndBounds(JNIEnv *env, jobject obj, int frame, int node, + jobject rect) +{ + IntRect nativeRect = jrect_to_webrect(env, rect); + return GET_NATIVE_VIEW(env, obj)->validNodeAndBounds( + reinterpret_cast<Frame*>(frame), + reinterpret_cast<Node*>(node), nativeRect); } // ---------------------------------------------------------------------------- @@ -3042,6 +2974,8 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) CopyContentToPicture }, { "nativeDrawContent", "(Landroid/graphics/Canvas;I)Z", (void*) DrawContent } , + { "nativeFocusBoundsChanged", "()Z", + (void*) FocusBoundsChanged } , { "nativeKey", "(IIIZZZZ)Z", (void*) Key }, { "nativeClick", "(II)V", @@ -3052,7 +2986,7 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) SendListBoxChoices }, { "nativeSendListBoxChoice", "(I)V", (void*) SendListBoxChoice }, - { "nativeSetSize", "(IIIFIIIIZ)V", + { "nativeSetSize", "(IIIFIIZ)V", (void*) SetSize }, { "nativeSetScrollOffset", "(III)V", (void*) SetScrollOffset }, @@ -3064,6 +2998,8 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) DeleteSelection } , { "nativeReplaceTextfieldText", "(IILjava/lang/String;III)V", (void*) ReplaceTextfieldText } , + { "nativeMoveFocus", "(II)V", + (void*) MoveFocus }, { "nativeMoveMouse", "(III)V", (void*) MoveMouse }, { "nativeMoveMouseIfLatest", "(IIII)V", @@ -3078,12 +3014,14 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) SaveDocumentState }, { "nativeFindAddress", "(Ljava/lang/String;Z)Ljava/lang/String;", (void*) FindAddress }, - { "nativeHandleTouchEvent", "(III)Z", + { "nativeHandleTouchEvent", "(III)I", (void*) HandleTouchEvent }, { "nativeTouchUp", "(IIIII)V", (void*) TouchUp }, { "nativeRetrieveHref", "(II)Ljava/lang/String;", (void*) RetrieveHref }, + { "nativeRetrieveAnchorText", "(II)Ljava/lang/String;", + (void*) RetrieveAnchorText }, { "nativeUpdateFrameCache", "()V", (void*) UpdateFrameCache }, { "nativeGetContentMinPrefWidth", "()I", @@ -3096,8 +3034,6 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) SplitContent }, { "nativeSetBackgroundColor", "(I)V", (void*) SetBackgroundColor }, - { "nativeGetSelection", "(Landroid/graphics/Region;)Ljava/lang/String;", - (void*) GetSelection }, { "nativeRegisterURLSchemeAsLocal", "(Ljava/lang/String;)V", (void*) RegisterURLSchemeAsLocal }, { "nativeDumpDomTree", "(Z)V", @@ -3114,11 +3050,16 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { { "nativeResume", "()V", (void*) Resume }, { "nativeFreeMemory", "()V", (void*) FreeMemory }, { "nativeSetJsFlags", "(Ljava/lang/String;)V", (void*) SetJsFlags }, - { "nativeUpdatePluginState", "(III)V", (void*) UpdatePluginState }, + { "nativeRequestLabel", "(II)Ljava/lang/String;", + (void*) RequestLabel }, { "nativeUpdateFrameCacheIfLoading", "()V", (void*) UpdateFrameCacheIfLoading }, { "nativeProvideVisitedHistory", "([Ljava/lang/String;)V", (void*) ProvideVisitedHistory }, + { "nativeFullScreenPluginHidden", "(I)V", + (void*) FullScreenPluginHidden }, + { "nativeValidNodeAndBounds", "(IILandroid/graphics/Rect;)Z", + (void*) ValidNodeAndBounds }, }; int register_webviewcore(JNIEnv* env) diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h index eab22b4..0569b4d 100644 --- a/WebKit/android/jni/WebViewCore.h +++ b/WebKit/android/jni/WebViewCore.h @@ -13,7 +13,7 @@ * 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 + * 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 @@ -27,6 +27,7 @@ #define WEBVIEWCORE_H #include "android_npapi.h" +#include "FileChooser.h" #include "CacheBuilder.h" #include "CachedHistory.h" #include "PictureSet.h" @@ -45,6 +46,7 @@ namespace WebCore { class AtomicString; class Color; class FrameView; + class HTMLAnchorElement; class HTMLSelectElement; class RenderPart; class RenderText; @@ -62,14 +64,8 @@ class SkIRect; namespace android { - enum PluginState { - kGainFocus_PluginState = 0, - kLoseFocus_PluginState = 1, - }; - class CachedRoot; class ListBoxReply; - class SurfaceCallback; class WebCoreReply : public WebCoreRefObject { public: @@ -130,6 +126,11 @@ namespace android { */ void contentDraw(); +#if USE(ACCELERATED_COMPOSITING) + void immediateRepaint(); + void setRootLayer(int layer); +#endif + /** Invalidate the view/screen, NOT the content/DOM, but expressed in * content/DOM coordinates (i.e. they need to eventually be scaled, * by webview into view.java coordinates @@ -242,9 +243,10 @@ namespace android { // Followings support calls from Java to native WebCore // - WebCore::String retrieveHref(WebCore::Frame* frame, WebCore::Node* node); - WebCore::String getSelection(SkRegion* ); + WebCore::String retrieveHref(WebCore::Frame* frame, WebCore::Node* node); + WebCore::String retrieveAnchorText(WebCore::Frame* frame, WebCore::Node* node); + WebCore::String requestLabel(WebCore::Frame* , WebCore::Node* ); // Create a single picture to represent the drawn DOM (used by navcache) void recordPicture(SkPicture* picture); @@ -252,6 +254,7 @@ namespace android { // Create a set of pictures to represent the drawn DOM, driven by // the invalidated region and the time required to draw (used to draw) void recordPictureSet(PictureSet* master); + void moveFocus(WebCore::Frame* frame, WebCore::Node* node); void moveMouse(WebCore::Frame* frame, int x, int y); void moveMouseIfLatest(int moveGeneration, WebCore::Frame* frame, int x, int y); @@ -262,8 +265,8 @@ namespace android { void setGlobalBounds(int x, int y, int h, int v); void setSizeScreenWidthAndScale(int width, int height, int screenWidth, - float scale, int realScreenWidth, int screenHeight, int anchorX, - int anchorY, bool ignoreHeight); + float scale, int realScreenWidth, int screenHeight, + bool ignoreHeight); /** * Handle key events from Java. @@ -279,7 +282,7 @@ namespace android { /** * Handle touch event */ - bool handleTouchEvent(int action, int x, int y); + int handleTouchEvent(int action, int x, int y); /** * Handle motionUp event from the UI thread (called touchUp in the @@ -348,6 +351,8 @@ namespace android { */ void addPlugin(PluginWidgetAndroid*); void removePlugin(PluginWidgetAndroid*); + // returns true if the pluginwidgit is in our active list + bool isPlugin(PluginWidgetAndroid*) const; void invalPlugin(PluginWidgetAndroid*); void drawPlugins(); @@ -363,39 +368,48 @@ namespace android { // send this event to all of the plugins who have the given flag set void sendPluginEvent(const ANPEvent& evt, ANPEventFlag flag); + // lookup the plugin widget struct given an NPP + PluginWidgetAndroid* getPluginWidget(NPP npp); + // return the cursorNode if it is a plugin Node* cursorNodeIsPlugin(); - // notify the plugin of an update in state - void updatePluginState(Frame* frame, Node* node, PluginState state); - // Notify the Java side whether it needs to pass down the touch events void needTouchEvents(bool); // Notify the Java side that webkit is requesting a keyboard - void requestKeyboard(bool); + void requestKeyboard(bool showKeyboard, bool isTextView); + + // Generates a class loader that contains classes from the plugin's apk + jclass getPluginClass(const WebCore::String& libName, const char* className); - // Creates a full screen surface (i.e. View on an Activity) for a plugin - void startFullScreenPluginActivity(const char* libName, - const char* className, NPP npp); + // Creates a full screen surface for a plugin + void showFullScreenPlugin(jobject webkitPlugin, NPP npp, int x, int y, int width, int height); - // Creates a Surface (i.e. View) for a plugin - jobject createSurface(const char* libName, const char* className, - NPP npp, int x, int y, int width, int height); + // Instructs the UI thread to discard the plugin's full-screen surface + void hideFullScreenPlugin(); + + // Update coordinates and dimensions for a full screen plugin + void updateFullScreenPlugin(int x, int y, int width, int height); + + // Adds the plugin's view (aka surface) to the view hierarchy + jobject addSurface(jobject view, int x, int y, int width, int height); + + // Updates a Surface coordinates and dimensions for a plugin + void updateSurface(jobject childView, int x, int y, int width, int height); // Destroys a SurfaceView for a plugin void destroySurface(jobject childView); - // Make the rect (left, top, width, height) visible. If it can be fully - // fit, center it on the screen. Otherwise make sure the point specified - // by (left + xPercentInDoc * width, top + yPercentInDoc * height) - // pinned at the screen position (xPercentInView, yPercentInView). - void showRect(int left, int top, int width, int height, int contentWidth, - int contentHeight, float xPercentInDoc, float xPercentInView, - float yPercentInDoc, float yPercentInView); + // Returns the context (android.content.Context) of the WebView + jobject getContext(); + bool validNodeAndBounds(Frame* , Node* , const IntRect& ); // other public functions public: + // Open a file chooser for selecting a file to upload + void openFileChooser(PassRefPtr<WebCore::FileChooser> ); + // reset the picture set to empty void clearContent(); @@ -404,6 +418,7 @@ namespace android { // draw the picture set with the specified background color bool drawContent(SkCanvas* , SkColor ); + bool focusBoundsChanged(); bool pictureReady(); // record the inval area, and the picture size @@ -421,7 +436,6 @@ namespace android { static Mutex gFrameCacheMutex; CachedRoot* m_frameCacheKit; // nav data being built by webcore SkPicture* m_navPictureKit; - int m_generation; // copy of the number bumped by WebViewNative int m_moveGeneration; // copy of state in WebViewNative triggered by move int m_touchGeneration; // copy of state in WebViewNative triggered by touch int m_lastGeneration; // last action using up to date cache @@ -466,7 +480,6 @@ namespace android { WebCore::IntRect m_lastFocusedBounds; int m_lastFocusedSelStart; int m_lastFocusedSelEnd; - int m_lastMoveGeneration; static Mutex m_contentMutex; // protects ui/core thread pictureset access PictureSet m_content; // the set of pictures to draw (accessed by UI too) SkRegion m_addInval; // the accumulated inval region (not yet drawn) @@ -474,6 +487,7 @@ namespace android { // Used in passToJS to avoid updating the UI text field until after the // key event has been processed. bool m_blockTextfieldUpdates; + bool m_focusBoundsChanged; bool m_skipContentDraw; // Passed in with key events to know when they were generated. Store it // with the cache so that we can ignore stale text changes. @@ -510,9 +524,21 @@ namespace android { void rebuildPictureSet(PictureSet* ); void sendNotifyProgressFinished(); bool handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* nodePtr); + WebCore::HTMLAnchorElement* retrieveAnchorElement(WebCore::Frame* frame, WebCore::Node* node); + #if DEBUG_NAV_UI uint32_t m_now; #endif + + private: + // called from constructor, to add this to a global list + static void addInstance(WebViewCore*); + // called from destructor, to remove this from a global list + static void removeInstance(WebViewCore*); + public: + // call only from webkit thread (like add/remove), return true if inst + // is still alive + static bool isInstance(WebViewCore*); }; } // namespace android |
