diff options
Diffstat (limited to 'WebKit')
29 files changed, 860 insertions, 83 deletions
diff --git a/WebKit/Android.mk b/WebKit/Android.mk index 4fff70e..5e79d5a 100644 --- a/WebKit/Android.mk +++ b/WebKit/Android.mk @@ -62,8 +62,9 @@ LOCAL_SRC_FILES := \ android/plugins/ANPPathInterface.cpp \ android/plugins/ANPSoundInterface.cpp \ android/plugins/ANPSurfaceInterface.cpp \ - android/plugins/ANPTypefaceInterface.cpp \ + android/plugins/ANPTypefaceInterface.cpp \ android/plugins/ANPWindowInterface.cpp \ + android/plugins/PluginSurface.cpp \ android/plugins/PluginTimer.cpp \ android/plugins/PluginViewBridgeAndroid.cpp \ android/plugins/PluginWidgetAndroid.cpp \ diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp index 39bc004..71d9f59 100644 --- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp +++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp @@ -311,6 +311,13 @@ void ChromeClientAndroid::exceededDatabaseQuota(Frame* frame, const String& name } } #endif +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +void ChromeClientAndroid::reachedMaxAppCacheSize(int64_t spaceNeeded) +{ + // FIXME: Free some space. + notImplemented(); +} +#endif void ChromeClientAndroid::requestGeolocationPermissionForFrame(Frame*, Geolocation*) { notImplemented(); } void ChromeClientAndroid::runOpenPanel(Frame*, PassRefPtr<FileChooser>) { notImplemented(); } diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.h b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h index 966d5c7..93426b8 100644 --- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.h +++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h @@ -111,6 +111,9 @@ namespace android { #if ENABLE(DATABASE) virtual void exceededDatabaseQuota(Frame*, const String&); #endif +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + virtual void reachedMaxAppCacheSize(int64_t spaceNeeded); +#endif virtual void requestGeolocationPermissionForFrame(Frame*, Geolocation*); virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>); virtual bool setCursor(PlatformCursorHandle); diff --git a/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp index 24d027a..b81e5f3 100644 --- a/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp +++ b/WebKit/android/WebCoreSupport/FrameLoaderClientAndroid.cpp @@ -29,13 +29,12 @@ #include "android_graphics.h" #include "CString.h" #include "DocumentLoader.h" +#include "DOMImplementation.h" #include "Frame.h" #include "FrameLoader.h" #include "FrameLoaderClientAndroid.h" #include "FrameTree.h" #include "GraphicsContext.h" -// HTMLFormElement needed for a bad include -#include "HTMLFormElement.h" #include "HTMLFrameOwnerElement.h" #include "HTMLPlugInElement.h" #include "IconDatabase.h" @@ -46,11 +45,6 @@ #include "PlatformString.h" #include "PluginDatabase.h" #include "PluginView.h" -#ifdef ANDROID_PLUGINS -// Removed. -#else -#include "PluginViewBridgeAndroid.h" -#endif #include "ProgressTracker.h" #include "RenderPart.h" #include "ResourceError.h" @@ -663,7 +657,9 @@ bool FrameLoaderClientAndroid::canShowMIMEType(const String& mimeType) const { if (MIMETypeRegistry::isSupportedImageResourceMIMEType(mimeType) || MIMETypeRegistry::isSupportedNonImageMIMEType(mimeType) || MIMETypeRegistry::isSupportedJavaScriptMIMEType(mimeType) || - PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType)) + PluginDatabase::installedPlugins()->isMIMETypeRegistered(mimeType) || + DOMImplementation::isTextMIMEType(mimeType) || + DOMImplementation::isXMLMIMEType(mimeType)) return true; return false; } diff --git a/WebKit/android/jni/WebSettings.cpp b/WebKit/android/jni/WebSettings.cpp index 7d2b12d..73ebf63 100644 --- a/WebKit/android/jni/WebSettings.cpp +++ b/WebKit/android/jni/WebSettings.cpp @@ -92,6 +92,7 @@ struct FieldIds { #if ENABLE(OFFLINE_WEB_APPLICATIONS) mAppCacheEnabled = env->GetFieldID(clazz, "mAppCacheEnabled", "Z"); mAppCachePath = env->GetFieldID(clazz, "mAppCachePath", "Ljava/lang/String;"); + mAppCacheMaxSize = env->GetFieldID(clazz, "mAppCacheMaxSize", "J"); #endif mJavaScriptCanOpenWindowsAutomatically = env->GetFieldID(clazz, "mJavaScriptCanOpenWindowsAutomatically", "Z"); @@ -123,6 +124,7 @@ struct FieldIds { #if ENABLE(OFFLINE_WEB_APPLICATIONS) LOG_ASSERT(mAppCacheEnabled, "Could not find field mAppCacheEnabled"); LOG_ASSERT(mAppCachePath, "Could not find field mAppCachePath"); + LOG_ASSERT(mAppCacheMaxSize, "Could not find field mAppCacheMaxSize"); #endif LOG_ASSERT(mJavaScriptCanOpenWindowsAutomatically, "Could not find field mJavaScriptCanOpenWindowsAutomatically"); @@ -164,6 +166,7 @@ struct FieldIds { #if ENABLE(OFFLINE_WEB_APPLICATIONS) jfieldID mAppCacheEnabled; jfieldID mAppCachePath; + jfieldID mAppCacheMaxSize; #endif jfieldID mJavaScriptCanOpenWindowsAutomatically; jfieldID mUseWideViewport; @@ -299,6 +302,8 @@ public: WebCore::cacheStorage().setCacheDirectory(path); } } + jlong maxsize = env->GetIntField(obj, gFieldIds->mAppCacheMaxSize); + WebCore::cacheStorage().setMaximumSize(maxsize); #endif flag = env->GetBooleanField(obj, gFieldIds->mJavaScriptCanOpenWindowsAutomatically); s->setJavaScriptCanOpenWindowsAutomatically(flag); diff --git a/WebKit/android/jni/WebStorage.cpp b/WebKit/android/jni/WebStorage.cpp index f625939..aa83892 100644 --- a/WebKit/android/jni/WebStorage.cpp +++ b/WebKit/android/jni/WebStorage.cpp @@ -29,6 +29,7 @@ #include <JNIHelp.h> +#include <WebCore/loader/appcache/ApplicationCacheStorage.h> #include <WebCore/page/SecurityOrigin.h> #include <WebCore/storage/DatabaseTracker.h> @@ -43,21 +44,31 @@ static jobject GetOrigins(JNIEnv* env, jobject obj) { Vector<RefPtr<WebCore::SecurityOrigin> > coreOrigins; WebCore::DatabaseTracker::tracker().origins(coreOrigins); + Vector<WebCore::KURL> manifestUrls; + if (WebCore::cacheStorage().manifestURLs(&manifestUrls)) { + int size = manifestUrls.size(); + for (int i = 0; i < size; ++i) { + RefPtr<WebCore::SecurityOrigin> manifestOrigin = WebCore::SecurityOrigin::create(manifestUrls[i]); + if (manifestOrigin.get() == 0) + continue; + coreOrigins.append(manifestOrigin); + } + } - jclass vectorClass = env->FindClass("java/util/Vector"); - jmethodID cid = env->GetMethodID(vectorClass, "<init>", "()V"); - jmethodID mid = env->GetMethodID(vectorClass, "addElement", "(Ljava/lang/Object;)V"); - jobject vector = env->NewObject(vectorClass, cid); + jclass setClass = env->FindClass("java/util/HashSet"); + jmethodID cid = env->GetMethodID(setClass, "<init>", "()V"); + jmethodID mid = env->GetMethodID(setClass, "add", "(Ljava/lang/Object;)Z"); + jobject set = env->NewObject(setClass, cid); for (unsigned i = 0; i < coreOrigins.size(); ++i) { WebCore::SecurityOrigin* origin = coreOrigins[i].get(); WebCore::String url = origin->toString(); jstring jUrl = env->NewString(url.characters(), url.length()); - env->CallVoidMethod(vector, mid, jUrl); + env->CallBooleanMethod(set, mid, jUrl); env->DeleteLocalRef(jUrl); } - return vector; + return set; } static unsigned long long GetQuotaForOrigin(JNIEnv* env, jobject obj, jstring origin) @@ -72,8 +83,22 @@ static unsigned long long GetUsageForOrigin(JNIEnv* env, jobject obj, jstring or { WebCore::String originStr = to_string(env, origin); RefPtr<WebCore::SecurityOrigin> securityOrigin = WebCore::SecurityOrigin::createFromString(originStr); - unsigned long long quota = WebCore::DatabaseTracker::tracker().usageForOrigin(securityOrigin.get()); - return quota; + unsigned long long usage = WebCore::DatabaseTracker::tracker().usageForOrigin(securityOrigin.get()); + Vector<WebCore::KURL> manifestUrls; + if (!WebCore::cacheStorage().manifestURLs(&manifestUrls)) + return usage; + int size = manifestUrls.size(); + for (int i = 0; i < size; ++i) { + RefPtr<WebCore::SecurityOrigin> manifestOrigin = WebCore::SecurityOrigin::create(manifestUrls[i]); + if (manifestOrigin.get() == 0) + continue; + if (manifestOrigin->isSameSchemeHostPort(securityOrigin.get())) { + int64_t size = 0; + WebCore::cacheStorage().cacheGroupSize(manifestUrls[i].string(), &size); + usage += size; + } + } + return usage; } static void SetQuotaForOrigin(JNIEnv* env, jobject obj, jstring origin, unsigned long long quota) @@ -88,18 +113,31 @@ static void DeleteOrigin(JNIEnv* env, jobject obj, jstring origin) WebCore::String originStr = to_string(env, origin); RefPtr<WebCore::SecurityOrigin> securityOrigin = WebCore::SecurityOrigin::createFromString(originStr); WebCore::DatabaseTracker::tracker().deleteOrigin(securityOrigin.get()); + + Vector<WebCore::KURL> manifestUrls; + if (!WebCore::cacheStorage().manifestURLs(&manifestUrls)) + return; + int size = manifestUrls.size(); + for (int i = 0; i < size; ++i) { + RefPtr<WebCore::SecurityOrigin> manifestOrigin = WebCore::SecurityOrigin::create(manifestUrls[i]); + if (manifestOrigin.get() == 0) + continue; + if (manifestOrigin->isSameSchemeHostPort(securityOrigin.get())) + WebCore::cacheStorage().deleteCacheGroup(manifestUrls[i]); + } } -static void DeleteAllDatabases(JNIEnv* env, jobject obj) +static void DeleteAllData(JNIEnv* env, jobject obj) { WebCore::DatabaseTracker::tracker().deleteAllDatabases(); + WebCore::cacheStorage().empty(); } /* * JNI registration */ static JNINativeMethod gWebStorageMethods[] = { - { "nativeGetOrigins", "()Ljava/util/Vector;", + { "nativeGetOrigins", "()Ljava/util/Set;", (void*) GetOrigins }, { "nativeGetUsageForOrigin", "(Ljava/lang/String;)J", (void*) GetUsageForOrigin }, @@ -109,8 +147,8 @@ static JNINativeMethod gWebStorageMethods[] = { (void*) SetQuotaForOrigin }, { "nativeDeleteOrigin", "(Ljava/lang/String;)V", (void*) DeleteOrigin }, - { "nativeDeleteAllDatabases", "()V", - (void*) DeleteAllDatabases } + { "nativeDeleteAllData", "()V", + (void*) DeleteAllData } }; int register_webstorage(JNIEnv* env) diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp index f88b1d2..51293b8 100644 --- a/WebKit/android/jni/WebViewCore.cpp +++ b/WebKit/android/jni/WebViewCore.cpp @@ -88,6 +88,7 @@ #include "SkCanvas.h" #include "SkPicture.h" #include "SkUtils.h" +#include "SurfaceCallback.h" #include "StringImpl.h" #include "Text.h" #include "TypingCommand.h" @@ -176,6 +177,9 @@ struct WebViewCore::JavaGlue { jmethodID m_requestKeyboard; jmethodID m_exceededDatabaseQuota; jmethodID m_addMessageToConsole; + jmethodID m_createSurface; + jmethodID m_destroySurface; + jmethodID m_attachSurface; AutoJObject object(JNIEnv* env) { return getRealObject(env, m_obj); } @@ -241,6 +245,9 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m m_javaGlue->m_requestKeyboard = GetJMethod(env, clazz, "requestKeyboard", "(Z)V"); m_javaGlue->m_exceededDatabaseQuota = GetJMethod(env, clazz, "exceededDatabaseQuota", "(Ljava/lang/String;Ljava/lang/String;J)V"); m_javaGlue->m_addMessageToConsole = GetJMethod(env, clazz, "addMessageToConsole", "(Ljava/lang/String;ILjava/lang/String;)V"); + m_javaGlue->m_createSurface = GetJMethod(env, clazz, "createSurface", "(I)Landroid/view/SurfaceView;"); + m_javaGlue->m_destroySurface = GetJMethod(env, clazz, "destroySurface", "(Landroid/view/SurfaceView;)V"); + m_javaGlue->m_attachSurface = GetJMethod(env, clazz, "attachSurface", "(Landroid/view/SurfaceView;IIII)V"); env->SetIntField(javaWebViewCore, gWebViewCoreFields.m_nativeClass, (jint)this); @@ -890,8 +897,8 @@ void WebViewCore::setScrollOffset(int moveGeneration, int dx, int dy) m_scrollOffsetY); m_mainFrame->eventHandler()->sendScrollEvent(); - // update the currently visible window - sendVisibleRectBounds(); + // update the currently visible screen + sendPluginVisibleScreen(); } gCursorBoundsMutex.lock(); bool hasCursorBounds = m_hasCursorBounds; @@ -967,20 +974,8 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height, } } - // update the currently visible window - sendVisibleRectBounds(); -} - -void WebViewCore::sendVisibleRectBounds() -{ - ANPEvent event; - SkANP::InitEvent(&event, kVisibleRect_ANPEventType); - event.data.visibleRect.rect.left = m_scrollOffsetX; - event.data.visibleRect.rect.top = m_scrollOffsetY; - event.data.visibleRect.rect.right = m_scrollOffsetX + m_screenWidth; - event.data.visibleRect.rect.bottom = m_scrollOffsetY + m_screenHeight; - event.data.visibleRect.zoomScale = m_scale; - sendPluginEvent(event, kVisibleRect_ANPEventFlag); + // update the currently visible screen + sendPluginVisibleScreen(); } void WebViewCore::dumpDomTree(bool useFile) @@ -1172,6 +1167,21 @@ void WebViewCore::drawPlugins() } } +void WebViewCore::sendPluginVisibleScreen() +{ + ANPRectI visibleRect; + visibleRect.left = m_scrollOffsetX; + visibleRect.top = m_scrollOffsetY; + visibleRect.right = m_scrollOffsetX + m_screenWidth; + visibleRect.bottom = m_scrollOffsetY + m_screenHeight; + + PluginWidgetAndroid** iter = m_plugins.begin(); + PluginWidgetAndroid** stop = m_plugins.end(); + for (; iter < stop; ++iter) { + (*iter)->setVisibleScreen(visibleRect, m_scale); + } +} + void WebViewCore::sendPluginEvent(const ANPEvent& evt, ANPEventFlag flag) { PluginWidgetAndroid** iter = m_plugins.begin(); @@ -1362,11 +1372,17 @@ WebCore::String WebViewCore::getSelection(SkRegion* selRgn) DBG_NAV_LOG("!node"); return result; } - WebCore::IntPoint endPt = WebCore::IntPoint(rect.fRight - 2, cy); + 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"); + 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); @@ -1501,6 +1517,26 @@ void WebViewCore::passToJs(int generation, const WebCore::String& current, updateTextfield(focus, false, test); } +void WebViewCore::scrollFocusedTextInput(int x, int y) +{ + WebCore::Node* focus = currentFocus(); + if (!focus) { + DBG_NAV_LOG("!focus"); + clearTextEntry(); + return; + } + WebCore::RenderObject* renderer = focus->renderer(); + if (!renderer || (!renderer->isTextField() && !renderer->isTextArea())) { + DBG_NAV_LOGD("renderer==%p || not text", renderer); + clearTextEntry(); + return; + } + WebCore::RenderTextControl* renderText = + static_cast<WebCore::RenderTextControl*>(renderer); + renderText->setScrollLeft(x); + renderText->setScrollTop(y); +} + void WebViewCore::setFocusControllerActive(bool active) { m_mainFrame->page()->focusController()->setActive(active); @@ -2021,6 +2057,32 @@ void WebViewCore::setBackgroundColor(SkColor c) view->setBaseBackgroundColor(bcolor); } +jobject WebViewCore::createSurface(SurfaceCallback* cb) +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + jobject surface = env->CallObjectMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_createSurface, (int) cb); + checkException(env); + return surface; +} + +void WebViewCore::destroySurface(jobject surface) +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->CallVoidMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_destroySurface, surface); + checkException(env); +} + +void WebViewCore::attachSurface(jobject surface, int x, int y, int width, + int height) +{ + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->CallVoidMethod(m_javaGlue->object(env).get(), + m_javaGlue->m_attachSurface, surface, x, y, width, height); + checkException(env); +} + //---------------------------------------------------------------------- // Native JNI methods //---------------------------------------------------------------------- @@ -2138,6 +2200,15 @@ static void PassToJs(JNIEnv *env, jobject obj, PlatformKeyboardEvent(keyCode, keyValue, 0, down, cap, fn, sym)); } +static void ScrollFocusedTextInput(JNIEnv *env, jobject obj, jint x, jint y) +{ +#ifdef ANDROID_INSTRUMENT + TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter); +#endif + WebViewCore* viewImpl = GET_NATIVE_VIEW(env, obj); + viewImpl->scrollFocusedTextInput(x, y); +} + static void SetFocusControllerActive(JNIEnv *env, jobject obj, jboolean active) { #ifdef ANDROID_INSTRUMENT @@ -2503,6 +2574,28 @@ static void UpdatePluginState(JNIEnv* env, jobject obj, jint framePtr, jint node (PluginState) state); } +static void SurfaceChanged(JNIEnv* env, jobject obj, jint pointer, jint state, + jint format, jint width, jint height) +{ + // Be safe and check for a valid callback + if (!pointer) + return; + SurfaceCallback* cb = reinterpret_cast<SurfaceCallback*>(pointer); + switch (state) { + case 0: + cb->surfaceCreated(); + break; + case 1: + cb->surfaceChanged(format, width, height); + break; + case 2: + cb->surfaceDestroyed(); + break; + default: + break; + } +} + static void Pause(JNIEnv* env, jobject obj) { ANPEvent event; @@ -2566,7 +2659,9 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { { "nativeMoveMouseIfLatest", "(IIII)V", (void*) MoveMouseIfLatest }, { "passToJs", "(ILjava/lang/String;IIZZZZ)V", - (void*) PassToJs } , + (void*) PassToJs }, + { "nativeScrollFocusedTextInput", "(II)V", + (void*) ScrollFocusedTextInput }, { "nativeSetFocusControllerActive", "(Z)V", (void*) SetFocusControllerActive }, { "nativeSaveDocumentState", "(I)V", @@ -2607,6 +2702,8 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = { (void*) DumpNavTree }, { "nativeSetDatabaseQuota", "(J)V", (void*) SetDatabaseQuota }, + { "nativeSurfaceChanged", "(IIIII)V", + (void*) SurfaceChanged }, { "nativePause", "()V", (void*) Pause }, { "nativeResume", "()V", (void*) Resume }, { "nativeFreeMemory", "()V", (void*) FreeMemory }, diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h index 2af849f..be08830 100644 --- a/WebKit/android/jni/WebViewCore.h +++ b/WebKit/android/jni/WebViewCore.h @@ -67,6 +67,7 @@ namespace android { class CachedRoot; class ListBoxReply; + class SurfaceCallback; class WebCoreReply : public WebCoreRefObject { public: @@ -265,6 +266,10 @@ namespace android { int textGeneration); void passToJs(int generation, const WebCore::String& , const WebCore::PlatformKeyboardEvent& ); + /** + * Scroll the focused textfield to (x, y) in document space + */ + void scrollFocusedTextInput(int x, int y); void setFocusControllerActive(bool active); void saveDocumentState(WebCore::Frame* frame); @@ -295,6 +300,9 @@ namespace android { void invalPlugin(PluginWidgetAndroid*); void drawPlugins(); + // send the current screen size/zoom to all of the plugins in our list + void sendPluginVisibleScreen(); + // send this event to all of the plugins in our list void sendPluginEvent(const ANPEvent&); @@ -313,6 +321,15 @@ namespace android { // Notify the Java side that webkit is requesting a keyboard void requestKeyboard(bool); + // Creates a SurfaceView for a plugin + jobject createSurface(SurfaceCallback* cb); + + // Destroys the SurfaceView after removing from the view system. + void destroySurface(jobject surface); + + // Positions the SurfaceView at x,y with dimensions width x height + void attachSurface(jobject surface, int x, int y, int width, int height); + // other public functions public: // reset the picture set to empty @@ -420,7 +437,6 @@ namespace android { SkPicture* rebuildPicture(const SkIRect& inval); void rebuildPictureSet(PictureSet* ); void sendNotifyProgressFinished(); - void sendVisibleRectBounds(); bool handleMouseClick(WebCore::Frame* framePtr, WebCore::Node* nodePtr); #if DEBUG_NAV_UI uint32_t m_now; diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp index cf1e486..ec57a3b 100644 --- a/WebKit/android/nav/WebView.cpp +++ b/WebKit/android/nav/WebView.cpp @@ -955,6 +955,7 @@ bool motionUp(int x, int y, int slop) rebuildWebTextView(); displaySoftKeyboard(true); } else { + clearTextEntry(); setFollowedLink(true); if (type != NORMAL_CACHEDNODETYPE) overrideUrlLoading(result->getExport()); diff --git a/WebKit/android/plugins/ANPSoundInterface.cpp b/WebKit/android/plugins/ANPSoundInterface.cpp index 6b019d1..c4bec1c 100644 --- a/WebKit/android/plugins/ANPSoundInterface.cpp +++ b/WebKit/android/plugins/ANPSoundInterface.cpp @@ -46,7 +46,7 @@ static ANPSampleFormat toANPFormat(int fm) { } } -static android::AudioSystem::audio_format fromANPFormat(ANPSampleFormat fm) { +static int fromANPFormat(ANPSampleFormat fm) { switch (fm) { case kPCM16Bit_ANPSampleFormat: return android::AudioSystem::PCM_16_BIT; @@ -97,7 +97,7 @@ static ANPAudioTrack* ANPCreateTrack(uint32_t sampleRate, track->mTrack = new android::AudioTrack(android::AudioSystem::MUSIC, sampleRate, fromANPFormat(format), - channelCount, + (channelCount > 1) ? android::AudioSystem::CHANNEL_OUT_STEREO : android::AudioSystem::CHANNEL_OUT_MONO, 0, // frameCount 0, // flags callbackProc, diff --git a/WebKit/android/plugins/ANPSurfaceInterface.cpp b/WebKit/android/plugins/ANPSurfaceInterface.cpp index a64af1e..835f45a 100644 --- a/WebKit/android/plugins/ANPSurfaceInterface.cpp +++ b/WebKit/android/plugins/ANPSurfaceInterface.cpp @@ -25,23 +25,61 @@ // must include config.h first for webkit to fiddle with new/delete #include "config.h" + +#include "PluginSurface.h" +#include "PluginView.h" +#include "PluginWidgetAndroid.h" #include "SkANP.h" -static ANPSurface* anp_newSurface(NPP instance, ANPSurfaceType) { +using namespace WebCore; + +static ANPSurface* anp_newSurface(NPP instance, ANPSurfaceType type) { + if (instance && instance->ndata) { + PluginView* view = static_cast<PluginView*>(instance->ndata); + PluginWidgetAndroid* widget = view->platformPluginWidget(); + return widget->createSurface(type); + } return NULL; } static void anp_deleteSurface(ANPSurface* surface) { - + if (surface) { + if (surface->data) { + android::PluginSurface* s = + static_cast<android::PluginSurface*>(surface->data); + s->destroy(); + } + delete surface; + } } static bool anp_lock(ANPSurface* surface, ANPBitmap* bitmap, ANPRectI* dirtyRect) { + if (bitmap && surface && surface->data) { + android::PluginSurface* s = + static_cast<android::PluginSurface*>(surface->data); + SkBitmap src; + bool res = false; + if (dirtyRect) { + SkIRect rect; + res = s->lock(SkANP::SetRect(&rect, *dirtyRect), &src); + } else { + res = s->lock(NULL, &src); + } + if (res) { + res &= SkANP::SetBitmap(bitmap, src); + } + return res; + } return false; } static void anp_unlock(ANPSurface* surface) { - + if (surface && surface->data) { + android::PluginSurface* s = + static_cast<android::PluginSurface*>(surface->data); + s->unlock(); + } } /////////////////////////////////////////////////////////////////////////////// diff --git a/WebKit/android/plugins/ANPWindowInterface.cpp b/WebKit/android/plugins/ANPWindowInterface.cpp index 7773e6e..41e00e9 100644 --- a/WebKit/android/plugins/ANPWindowInterface.cpp +++ b/WebKit/android/plugins/ANPWindowInterface.cpp @@ -26,9 +26,9 @@ // must include config.h first for webkit to fiddle with new/delete #include "config.h" #include "SkANP.h" -#include "ScrollView.h" #include "WebViewCore.h" #include "PluginView.h" +#include "PluginWidgetAndroid.h" static bool anp_lockRect(void* window, const ANPRectI* inval, ANPBitmap* bitmap) { @@ -57,10 +57,14 @@ static PluginView* pluginViewForInstance(NPP instance) { return PluginView::currentPluginView(); } -static void anp_scrollTo(NPP instance, int32_t x, int32_t y) { - ScrollView* scrollView = pluginViewForInstance(instance)->parent(); - android::WebViewCore* core = android::WebViewCore::getWebViewCore(scrollView); - core->scrollTo(x,y,true); +static void anp_setVisibleRects(NPP instance, const ANPRectI rects[], int32_t count) { + PluginView* pluginView = pluginViewForInstance(instance); + PluginWidgetAndroid* pluginWidget = pluginView->platformPluginWidget(); + pluginWidget->setVisibleRects(rects, count); +} + +static void anp_clearVisibleRects(NPP instance) { + anp_setVisibleRects(instance, NULL, 0); } static void anp_showKeyboard(NPP instance, bool value) { @@ -78,7 +82,8 @@ void ANPWindowInterfaceV0_Init(ANPInterface* value) { ASSIGN(i, lockRect); ASSIGN(i, lockRegion); - ASSIGN(i, scrollTo); + ASSIGN(i, setVisibleRects); + ASSIGN(i, clearVisibleRects); ASSIGN(i, showKeyboard); ASSIGN(i, unlock); } diff --git a/WebKit/android/plugins/PluginSurface.cpp b/WebKit/android/plugins/PluginSurface.cpp new file mode 100644 index 0000000..aba0263 --- /dev/null +++ b/WebKit/android/plugins/PluginSurface.cpp @@ -0,0 +1,186 @@ +/* + * Copyright 2009, The Android Open Source Project + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" + +#include "PluginSurface.h" + +#include "android_graphics.h" +#include "PluginWidgetAndroid.h" +#include "WebViewCore.h" +#include "jni_utility.h" + +#include <ui/Rect.h> +#include <ui/Region.h> +#include <ui/Surface.h> + +namespace android { + +// jni field offset for the native surface pointer. +static jfieldID gSurfaceField; +static jmethodID gGetHolder; +static jmethodID gGetSurface; + +static void initFields(JNIEnv* env) { + if (gSurfaceField) + return; + + jclass clazz = env->FindClass("android/view/Surface"); + gSurfaceField = env->GetFieldID(clazz, "mSurface", "I"); + + clazz = env->FindClass("android/view/SurfaceView"); + gGetHolder = env->GetMethodID(clazz, "getHolder", "()Landroid/view/SurfaceHolder;"); + + clazz = env->FindClass("android/view/SurfaceHolder"); + gGetSurface = env->GetMethodID(clazz, "getSurface", "()Landroid/view/Surface;"); +} + +static inline sp<Surface> getSurface(jobject view) { + if (!view) { + return NULL; + } + JNIEnv* env = JSC::Bindings::getJNIEnv(); + initFields(env); + jobject holder = env->CallObjectMethod(view, gGetHolder); + jobject surface = env->CallObjectMethod(holder, gGetSurface); + return sp<Surface>((Surface*) env->GetIntField(surface, gSurfaceField)); +} + +static inline SkBitmap::Config convertPixelFormat(PixelFormat format) { + switch (format) { + case PIXEL_FORMAT_RGBA_8888: return SkBitmap::kARGB_8888_Config; + case PIXEL_FORMAT_RGBA_4444: return SkBitmap::kARGB_4444_Config; + case PIXEL_FORMAT_RGB_565: return SkBitmap::kRGB_565_Config; + case PIXEL_FORMAT_A_8: return SkBitmap::kA8_Config; + default: return SkBitmap::kNo_Config; + } +} + +PluginSurface::PluginSurface(PluginWidgetAndroid* widget) + : m_jSurfaceView(0) + , m_widget(widget) { + // Create our java SurfaceView. + jobject obj = widget->webViewCore()->createSurface(this); + if (obj) { + JNIEnv* env = JSC::Bindings::getJNIEnv(); + m_jSurfaceView = env->NewGlobalRef(obj); + env->DeleteLocalRef(obj); + } +} + +void PluginSurface::attach(int x, int y, int width, int height) { + if (m_jSurfaceView) { + m_widget->webViewCore()->attachSurface(m_jSurfaceView, x, y, width, + height); + } +} + +void PluginSurface::destroy() { + m_surface.clear(); + if (m_jSurfaceView) { + m_widget->webViewCore()->destroySurface(m_jSurfaceView); + JNIEnv* env = JSC::Bindings::getJNIEnv(); + env->DeleteGlobalRef(m_jSurfaceView); + m_jSurfaceView = 0; + } +} + +bool PluginSurface::lock(SkIRect* dirty, SkBitmap* bitmap) { + if (!bitmap || !Surface::isValid(m_surface)) { + return false; + } + + Region dirtyRegion; + if (dirty) { + Rect rect(dirty->fLeft, dirty->fTop, dirty->fRight, dirty->fBottom); + if (!rect.isEmpty()) { + dirtyRegion.set(rect); + } + } else { + dirtyRegion.set(Rect(0x3FFF, 0x3FFF)); + } + + Surface::SurfaceInfo info; + status_t err = m_surface->lock(&info, &dirtyRegion); + if (err < 0) { + return false; + } + + ssize_t bpr = info.s * bytesPerPixel(info.format); + bitmap->setConfig(convertPixelFormat(info.format), info.w, info.h, bpr); + if (info.w > 0 && info.h > 0) { + bitmap->setPixels(info.bits); + } else { + bitmap->setPixels(NULL); + } + + return true; +} + +void PluginSurface::unlock() { + if (!Surface::isValid(m_surface)) { + return; + } + + m_surface->unlockAndPost(); +} + +static void sendSurfaceEvent(PluginWidgetAndroid* widget, + ANPSurfaceAction action, int format = 0, int width = 0, + int height = 0) { + // format is currently not reported to the plugin. The plumbing from Java + // to C is still provided in case we add the format back to the event. + ANPEvent event; + SkANP::InitEvent(&event, kSurface_ANPEventType); + + event.data.surface.action = action; + if (action == kChanged_ANPSurfaceAction) { + event.data.surface.data.changed.width = width; + event.data.surface.data.changed.height = height; + } + + widget->sendEvent(event); +} + +// SurfaceCallback methods +void PluginSurface::surfaceCreated() { + m_surface = getSurface(m_jSurfaceView); + // Not sure what values for format, width, and height should be here. + sendSurfaceEvent(m_widget, kCreated_ANPSurfaceAction); +} + +void PluginSurface::surfaceChanged(int format, int width, int height) { + m_surface = getSurface(m_jSurfaceView); + sendSurfaceEvent(m_widget, kChanged_ANPSurfaceAction, format, width, + height); +} + +void PluginSurface::surfaceDestroyed() { + m_surface = getSurface(m_jSurfaceView); + // Not sure what values for format, width, and height should be here. + sendSurfaceEvent(m_widget, kDestroyed_ANPSurfaceAction); +} + +} // namespace android diff --git a/WebKit/android/plugins/PluginSurface.h b/WebKit/android/plugins/PluginSurface.h new file mode 100644 index 0000000..b8cbac9 --- /dev/null +++ b/WebKit/android/plugins/PluginSurface.h @@ -0,0 +1,75 @@ +/* + * Copyright 2009, The Android Open Source Project + * Copyright (C) 2008 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef PluginSurface_H +#define PluginSurface_H + +#include "android_npapi.h" +#include "SkANP.h" +#include "SurfaceCallback.h" + +#include <jni.h> +#include <ui/Surface.h> +#include <utils/RefBase.h> + +struct PluginWidgetAndroid; +class SkBitmap; +struct SkIRect; + +struct ANPSurface { + void* data; + ANPSurfaceType type; +}; + +namespace android { + +class Surface; + +class PluginSurface : public SurfaceCallback { +public: + PluginSurface(PluginWidgetAndroid* widget); + virtual ~PluginSurface() { + destroy(); + } + + void attach(int x, int y, int width, int height); + void destroy(); + bool lock(SkIRect* dirty, SkBitmap* bitmap); + void unlock(); + + virtual void surfaceCreated(); + virtual void surfaceChanged(int format, int width, int height); + virtual void surfaceDestroyed(); + +private: + jobject m_jSurfaceView; + sp<Surface> m_surface; + PluginWidgetAndroid* m_widget; +}; + +} // namespace android + +#endif diff --git a/WebKit/android/plugins/PluginWidgetAndroid.cpp b/WebKit/android/plugins/PluginWidgetAndroid.cpp index 7566d63..30a55cb 100644 --- a/WebKit/android/plugins/PluginWidgetAndroid.cpp +++ b/WebKit/android/plugins/PluginWidgetAndroid.cpp @@ -29,8 +29,10 @@ #include "Element.h" #include "Frame.h" #include "PluginPackage.h" +#include "PluginSurface.h" #include "PluginView.h" #include "PluginWidgetAndroid.h" +#include "ScrollView.h" #include "SkANP.h" #include "SkFlipPixelRef.h" #include "WebViewCore.h" @@ -41,7 +43,10 @@ PluginWidgetAndroid::PluginWidgetAndroid(WebCore::PluginView* view) m_core = NULL; m_drawingModel = kBitmap_ANPDrawingModel; m_eventFlags = 0; - m_x = m_y = 0; + m_pluginWindow = NULL; + m_requestedVisibleRectCount = 0; + m_requestedFrameRect.setEmpty(); + m_visibleDocRect.setEmpty(); } PluginWidgetAndroid::~PluginWidgetAndroid() { @@ -61,13 +66,18 @@ static SkBitmap::Config computeConfig(bool isTransparent) { : SkBitmap::kRGB_565_Config; } -void PluginWidgetAndroid::setWindow(int x, int y, int width, int height, - bool isTransparent) { - m_x = x; - m_y = y; - m_flipPixelRef->safeUnref(); - m_flipPixelRef = new SkFlipPixelRef(computeConfig(isTransparent), - width, height); +void PluginWidgetAndroid::setWindow(NPWindow* window, bool isTransparent) { + m_pluginWindow = window; + + if (m_drawingModel == kSurface_ANPDrawingModel) { + if (m_surface) { + m_surface->attach(window->x, window->y, window->width, window->height); + } + } else { + m_flipPixelRef->safeUnref(); + m_flipPixelRef = new SkFlipPixelRef(computeConfig(isTransparent), + window->width, window->height); + } } bool PluginWidgetAndroid::setDrawingModel(ANPDrawingModel model) { @@ -76,7 +86,8 @@ bool PluginWidgetAndroid::setDrawingModel(ANPDrawingModel model) { } void PluginWidgetAndroid::localToPageCoords(SkIRect* rect) const { - rect->offset(m_x, m_y); + if (m_pluginWindow) + rect->offset(m_pluginWindow->x, m_pluginWindow->y); } bool PluginWidgetAndroid::isDirty(SkIRect* rect) const { @@ -98,7 +109,8 @@ bool PluginWidgetAndroid::isDirty(SkIRect* rect) const { void PluginWidgetAndroid::inval(const WebCore::IntRect& rect, bool signalRedraw) { - // nothing to do if we haven't had setWindow() called yet + // nothing to do if we haven't had setWindow() called yet. m_flipPixelRef + // will also be null if this is a Surface model. if (NULL == m_flipPixelRef) { return; } @@ -134,11 +146,11 @@ void PluginWidgetAndroid::draw(SkCanvas* canvas) { bitmap) && pkg->pluginFuncs()->event(instance, &event)) { - if (canvas) { + if (canvas && m_pluginWindow) { SkBitmap bm(bitmap); bm.setPixelRef(m_flipPixelRef); - canvas->drawBitmap(bm, SkIntToScalar(m_x), - SkIntToScalar(m_y), NULL); + canvas->drawBitmap(bm, SkIntToScalar(m_pluginWindow->x), + SkIntToScalar(m_pluginWindow->y), NULL); } } break; @@ -182,3 +194,118 @@ void PluginWidgetAndroid::updateEventFlags(ANPEventFlags flags) { bool PluginWidgetAndroid::isAcceptingEvent(ANPEventFlag flag) { return m_eventFlags & flag; } + +ANPSurface* PluginWidgetAndroid::createSurface(ANPSurfaceType ignored) { + if (m_drawingModel != kSurface_ANPDrawingModel) { + return NULL; + } + m_surface.set(new android::PluginSurface(this)); + ANPSurface* surface = new ANPSurface; + surface->data = m_surface.get(); + surface->type = ignored; + return surface; +} + +void PluginWidgetAndroid::setVisibleScreen(const ANPRectI& visibleDocRect, float zoom) { + + //TODO send an event to the plugin that communicates the zoom + + int oldScreenW = m_visibleDocRect.width(); + int oldScreenH = m_visibleDocRect.height(); + + m_visibleDocRect.set(visibleDocRect.left, visibleDocRect.top, + visibleDocRect.right, visibleDocRect.bottom); + + int newScreenW = m_visibleDocRect.width(); + int newScreenH = m_visibleDocRect.height(); + + if (oldScreenW != newScreenW || oldScreenH != newScreenH) + computeVisibleFrameRect(); +} + +void PluginWidgetAndroid::setVisibleRects(const ANPRectI rects[], int32_t count) { + + // ensure the count does not exceed our allocated space + if (count > MAX_REQUESTED_RECTS) + count = MAX_REQUESTED_RECTS; + + // store the values in member variables + m_requestedVisibleRectCount = count; + memcpy(m_requestedVisibleRect, rects, count * sizeof(rects[0])); + + computeVisibleFrameRect(); +} + +void PluginWidgetAndroid::computeVisibleFrameRect() { + + // ensure the visibleDocRect has been set (i.e. not equal to zero) + if (m_visibleDocRect.isEmpty() || !m_pluginWindow) + return; + + // create a rect that represents the plugin's bounds + SkIRect pluginBounds; + pluginBounds.set(m_pluginWindow->x, m_pluginWindow->y, + m_pluginWindow->x + m_pluginWindow->width, + m_pluginWindow->y + m_pluginWindow->height); + + // create a rect that will contain as many of the rects that will fit on screen + SkIRect visibleRect; + visibleRect.setEmpty(); + + for (int counter = 0; counter < m_requestedVisibleRectCount; counter++) { + + ANPRectI* rect = &m_requestedVisibleRect[counter]; + + // create skia rect for easier manipulation and convert it to frame coordinates + SkIRect pluginRect; + pluginRect.set(rect->left, rect->top, rect->right, rect->bottom); + pluginRect.offset(m_pluginWindow->x, m_pluginWindow->y); + + // ensure the rect falls within the plugin's bounds + if (!pluginBounds.contains(pluginRect)) + continue; + + // combine this new rect with the higher priority rects + pluginRect.join(visibleRect); + + // check to see if the new rect fits within the screen bounds. If this + // is the highest priority rect then attempt to center even if it doesn't + // fit on the screen. + if (counter > 0 && (m_visibleDocRect.width() < pluginRect.width() || + m_visibleDocRect.height() < pluginRect.height())) + break; + + // set the new visible rect + visibleRect = pluginRect; + } + + m_requestedFrameRect = visibleRect; + scrollToVisibleFrameRect(); +} + +void PluginWidgetAndroid::scrollToVisibleFrameRect() { + + if (m_requestedFrameRect.isEmpty() || m_visibleDocRect.isEmpty()) + return; + + // TODO if the entire rect is already visible then we don't need to scroll, + // this requires converting the m_requestedFrameRect from frame to doc coordinates + + // find the center of the visibleRect in document coordinates + ScrollView* scrollView = m_pluginView->parent(); + IntPoint pluginFramePoint = IntPoint(m_requestedFrameRect.fLeft, m_requestedFrameRect.fTop); + IntPoint pluginDocPoint = scrollView->convertToContainingWindow(pluginFramePoint); + int rectCenterX = pluginDocPoint.x() + m_requestedFrameRect.width()/2; + int rectCenterY = pluginDocPoint.y() + m_requestedFrameRect.height()/2; + + // find document coordinates for center of the visible screen + int screenCenterX = m_visibleDocRect.fLeft + m_visibleDocRect.width()/2; + int screenCenterY = m_visibleDocRect.fTop + m_visibleDocRect.height()/2; + + //compute the delta of the two points + int deltaX = rectCenterX - screenCenterX; + int deltaY = rectCenterY - screenCenterY; + + android::WebViewCore* core = android::WebViewCore::getWebViewCore(scrollView); + core->scrollBy(deltaX, deltaY, true); +} diff --git a/WebKit/android/plugins/PluginWidgetAndroid.h b/WebKit/android/plugins/PluginWidgetAndroid.h index c8d1ffe..1da618f 100644 --- a/WebKit/android/plugins/PluginWidgetAndroid.h +++ b/WebKit/android/plugins/PluginWidgetAndroid.h @@ -27,12 +27,16 @@ #define PluginWidgetAndroid_H #include "android_npapi.h" +#include "SkRect.h" + +#include <wtf/OwnPtr.h> namespace WebCore { class PluginView; } namespace android { + class PluginSurface; class WebViewCore; } @@ -52,13 +56,17 @@ struct PluginWidgetAndroid { WebCore::PluginView* pluginView() const { return m_pluginView; } + // Needed by PluginSurface to manage the java SurfaceView. + android::WebViewCore* webViewCore() const { return m_core; } + /* Can't determine our core at construction time, so PluginView calls this as soon as it has a parent. */ void init(android::WebViewCore*); /* Called each time the PluginView gets a new size or position. */ - void setWindow(int x, int y, int width, int height, bool isTransparent); + void setWindow(NPWindow* window, bool isTransparent); + /* Called whenever the plugin itself requests a new drawing model. If the hardware does not support the requested model then false is returned, otherwise true is returned. @@ -101,14 +109,51 @@ struct PluginWidgetAndroid { */ bool isAcceptingEvent(ANPEventFlag); + /* Create an ANPSurface that the plugin may draw in to. The drawing model + must be kSurface_ANPDrawingModel for this call to succeed. The type + specifies what kind of pixel access will be available. + */ + ANPSurface* createSurface(ANPSurfaceType type); + + /* Notify the plugin of the currently visible screen coordinates (document + space) and the current zoom level. + */ + void setVisibleScreen(const ANPRectI& visibleScreenRect, float zoom); + + /** Registers a set of rectangles that the plugin would like to keep on + screen. The rectangles are listed in order of priority with the highest + priority rectangle in location rects[0]. The browser will attempt to keep + as many of the rectangles on screen as possible and will scroll them into + view in response to the invocation of this method and other various events. + The count specifies how many rectangles are in the array. If the count is + zero it signals the plugin that any existing rectangles should be cleared + and no rectangles will be tracked. + */ + void setVisibleRects(const ANPRectI rects[], int32_t count); + private: + void computeVisibleFrameRect(); + void scrollToVisibleFrameRect(); + WebCore::PluginView* m_pluginView; android::WebViewCore* m_core; SkFlipPixelRef* m_flipPixelRef; ANPDrawingModel m_drawingModel; ANPEventFlags m_eventFlags; - int m_x; - int m_y; + NPWindow* m_pluginWindow; + SkIRect m_visibleDocRect; + SkIRect m_requestedFrameRect; + OwnPtr<android::PluginSurface> m_surface; + + /* We limit the number of rectangles to minimize storage and ensure adequate + speed. + */ + enum { + MAX_REQUESTED_RECTS = 5, + }; + + ANPRectI m_requestedVisibleRect[MAX_REQUESTED_RECTS]; + int32_t m_requestedVisibleRectCount; }; #endif diff --git a/WebKit/android/plugins/SurfaceCallback.h b/WebKit/android/plugins/SurfaceCallback.h new file mode 100644 index 0000000..fb2e015 --- /dev/null +++ b/WebKit/android/plugins/SurfaceCallback.h @@ -0,0 +1,42 @@ +/* + * Copyright 2009, The Android Open Source Project + * Copyright (C) 2008 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef SurfaceCallback_H +#define SurfaceCallback_H + +namespace android { + + class SurfaceCallback { + public: + virtual ~SurfaceCallback() {} + virtual void surfaceCreated() = 0; + virtual void surfaceChanged(int format, int width, int height) = 0; + virtual void surfaceDestroyed() = 0; + }; + +} // namespace android + +#endif diff --git a/WebKit/android/plugins/android_npapi.h b/WebKit/android/plugins/android_npapi.h index 41c1080..e50f031 100644 --- a/WebKit/android/plugins/android_npapi.h +++ b/WebKit/android/plugins/android_npapi.h @@ -164,7 +164,6 @@ typedef int32_t ANPDrawingModel; enum ANPEventFlag { kKey_ANPEventFlag = 0x01, kTouch_ANPEventFlag = 0x02, - kVisibleRect_ANPEventFlag = 0x04, }; typedef uint32_t ANPEventFlags; @@ -200,11 +199,6 @@ struct ANPBitmapInterfaceV0 : ANPInterface { bool (*getPixelPacking)(ANPBitmapFormat, ANPPixelPacking* packing); }; -/** The ANPSurface acts as a handle between the plugin and the native libraries - that render the surface to the screen. - */ -struct ANPSurface; - /** The surfaceType is the mechanism by which the plugin informs the native libraries which type of surface view it wishes to use. */ @@ -213,6 +207,11 @@ enum ANPSurfaceTypes { }; typedef int32_t ANPSurfaceType; +/** The ANPSurface acts as a handle between the plugin and the native libraries + that render the surface to the screen. + */ +struct ANPSurface; + struct ANPSurfaceInterfaceV0 : ANPInterface { /** Creates a new surface handle based on the given surface type. If the given surface type is not supported then NULL is returned. @@ -615,11 +614,20 @@ struct ANPWindowInterfaceV0 : ANPInterface { results. If lock returned false, unlock should not be called. */ void (*unlock)(void* window); - /** Given (x,y) coordinates in the document space the currently visible - window will be shifted so that window's upper left corner will be as - closely aligned to the coordinates as possible. - */ - void (*scrollTo)(NPP instance, int32_t x, int32_t y); + /** Registers a set of rectangles that the plugin would like to keep on + screen. The rectangles are listed in order of priority with the highest + priority rectangle in location rects[0]. The browser will attempt to keep + as many of the rectangles on screen as possible and will scroll them into + view in response to the invocation of this method and other various events. + The count specifies how many rectangles are in the array. If the count is + zero it signals the browser that any existing rectangles should be cleared + and no rectangles will be tracked. + */ + void (*setVisibleRects)(NPP instance, const ANPRectI rects[], int32_t count); + /** Clears any rectangles that are being tracked as a result of a call to + setVisibleRects. This call is equivalent to setVisibleRect(inst, NULL, 0). + */ + void (*clearVisibleRects)(NPP instance); /** Given a boolean value of true the device will be requested to provide a keyboard. A value of false will result in a request to hide the keyboard. Further, the on-screen keyboard will not be displayed if a @@ -716,7 +724,7 @@ enum ANPEventTypes { kTouch_ANPEventType = 3, kDraw_ANPEventType = 4, kLifecycle_ANPEventType = 5, - kVisibleRect_ANPEventType = 6, + kSurface_ANPEventType = 6, }; typedef int32_t ANPEventType; @@ -759,6 +767,23 @@ enum ANPLifecycleActions { }; typedef uint32_t ANPLifecycleAction; +enum ANPSurfaceActions { + /** The surface has been created and is ready to be used. Any calls to + lock/unlock before this action will fail. + */ + kCreated_ANPSurfaceAction = 0, + /** The surface's dimension has changed. + */ + kChanged_ANPSurfaceAction = 1, + /** The surface has been destroyed. This happens when the view system has + remove the surface (possibly due to the plugin being offscreen). Calls + to lock/unlock will fail after this action and before + kCreate_ANPSurfaceAction. + */ + kDestroyed_ANPSurfaceAction = 2, +}; +typedef uint32_t ANPSurfaceAction; + /* This is what is passed to NPP_HandleEvent() */ struct ANPEvent { uint32_t inSize; // size of this struct in bytes @@ -797,9 +822,21 @@ struct ANPEvent { } data; } draw; struct { - ANPRectI rect; // in global document coordinates - float zoomScale; // 1.0 means no zoom scale - } visibleRect; + ANPSurfaceAction action; + /** This union is based on the value of action and contains data + specific to the given action. + */ + union { + /** This struct is filled in only during the + kChanged_ANPSurfaceAction action. For all other actions, + this struct is undefined. + */ + struct { + int32_t width; + int32_t height; + } changed; + } data; + } surface; int32_t other[8]; } data; }; diff --git a/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp b/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp index 892be74..7125305 100644 --- a/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp +++ b/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp @@ -418,6 +418,14 @@ void ChromeClient::exceededDatabaseQuota(Frame* frame, const String&) } #endif +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +void ChromeClient::reachedMaxAppCacheSize(int64_t spaceNeeded) +{ + // FIXME: Free some space. + notImplemented(); +} +#endif + void ChromeClient::runOpenPanel(Frame*, PassRefPtr<FileChooser> prpFileChooser) { RefPtr<FileChooser> chooser = prpFileChooser; diff --git a/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h b/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h index fc0ea8a..bac9940 100644 --- a/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h +++ b/WebKit/gtk/WebCoreSupport/ChromeClientGtk.h @@ -99,6 +99,9 @@ namespace WebKit { #if ENABLE(DATABASE) virtual void exceededDatabaseQuota(WebCore::Frame*, const WebCore::String&); #endif +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + virtual void reachedMaxAppCacheSize(int64_t spaceNeeded); +#endif virtual void runOpenPanel(WebCore::Frame*, PassRefPtr<WebCore::FileChooser>); virtual void formStateDidChange(const WebCore::Node*) { } diff --git a/WebKit/mac/WebCoreSupport/WebChromeClient.h b/WebKit/mac/WebCoreSupport/WebChromeClient.h index 6c3d71e..6974cb1 100644 --- a/WebKit/mac/WebCoreSupport/WebChromeClient.h +++ b/WebKit/mac/WebCoreSupport/WebChromeClient.h @@ -107,6 +107,9 @@ public: #if ENABLE(DATABASE) virtual void exceededDatabaseQuota(WebCore::Frame*, const WebCore::String& databaseName); #endif +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + virtual void reachedMaxAppCacheSize(int64_t spaceNeeded); +#endif virtual void populateVisitedLinks(); #if ENABLE(DASHBOARD_SUPPORT) diff --git a/WebKit/mac/WebCoreSupport/WebChromeClient.mm b/WebKit/mac/WebCoreSupport/WebChromeClient.mm index 18c73e9..2ca86d1 100644 --- a/WebKit/mac/WebCoreSupport/WebChromeClient.mm +++ b/WebKit/mac/WebCoreSupport/WebChromeClient.mm @@ -517,6 +517,13 @@ void WebChromeClient::exceededDatabaseQuota(Frame* frame, const String& database END_BLOCK_OBJC_EXCEPTIONS; } #endif + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +void WebChromeClient::reachedMaxAppCacheSize(int64_t spaceNeeded) +{ + // FIXME: Free some space. +} +#endif void WebChromeClient::populateVisitedLinks() { diff --git a/WebKit/mac/WebKit.exp b/WebKit/mac/WebKit.exp index d166894..cb26943 100644 --- a/WebKit/mac/WebKit.exp +++ b/WebKit/mac/WebKit.exp @@ -1,3 +1,4 @@ +.objc_class_name_WebApplicationCache .objc_class_name_WebArchive .objc_class_name_WebBackForwardList .objc_class_name_WebCache diff --git a/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp b/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp index 5df554b..5199a5a 100644 --- a/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp +++ b/WebKit/qt/WebCoreSupport/ChromeClientQt.cpp @@ -399,6 +399,14 @@ void ChromeClientQt::exceededDatabaseQuota(Frame* frame, const String& databaseN } #endif +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +void ChromeClientQt::reachedMaxAppCacheSize(int64_t spaceNeeded) +{ + // FIXME: Free some space. + notImplemented(); +} +#endif + void ChromeClientQt::runOpenPanel(Frame* frame, PassRefPtr<FileChooser> prpFileChooser) { RefPtr<FileChooser> fileChooser = prpFileChooser; diff --git a/WebKit/qt/WebCoreSupport/ChromeClientQt.h b/WebKit/qt/WebCoreSupport/ChromeClientQt.h index 77c56fc..7922000 100644 --- a/WebKit/qt/WebCoreSupport/ChromeClientQt.h +++ b/WebKit/qt/WebCoreSupport/ChromeClientQt.h @@ -116,6 +116,9 @@ namespace WebCore { #if ENABLE(DATABASE) virtual void exceededDatabaseQuota(Frame*, const String&); #endif +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + virtual void reachedMaxAppCacheSize(int64_t spaceNeeded); +#endif virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>); virtual void formStateDidChange(const Node*) { } diff --git a/WebKit/win/WebCoreSupport/WebChromeClient.cpp b/WebKit/win/WebCoreSupport/WebChromeClient.cpp index 45b07cf..1f0c09c 100644 --- a/WebKit/win/WebCoreSupport/WebChromeClient.cpp +++ b/WebKit/win/WebCoreSupport/WebChromeClient.cpp @@ -543,6 +543,15 @@ void WebChromeClient::exceededDatabaseQuota(Frame* frame, const String& database } #endif +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +#include "ApplicationCacheStorage.h" +void WebChromeClient::reachedMaxAppCacheSize(int64_t spaceNeeded) +{ + // FIXME: Free some space. + notImplemented(); +} +#endif + void WebChromeClient::populateVisitedLinks() { WebHistory* history = WebHistory::sharedHistory(); diff --git a/WebKit/win/WebCoreSupport/WebChromeClient.h b/WebKit/win/WebCoreSupport/WebChromeClient.h index 44c6107..4aa7422 100644 --- a/WebKit/win/WebCoreSupport/WebChromeClient.h +++ b/WebKit/win/WebCoreSupport/WebChromeClient.h @@ -109,6 +109,10 @@ public: virtual void exceededDatabaseQuota(WebCore::Frame*, const WebCore::String&); #endif +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + virtual void reachedMaxAppCacheSize(int64_t spaceNeeded); +#endif + virtual void populateVisitedLinks(); virtual bool paintCustomScrollbar(WebCore::GraphicsContext*, const WebCore::FloatRect&, WebCore::ScrollbarControlSize, diff --git a/WebKit/wx/WebKitSupport/ChromeClientWx.cpp b/WebKit/wx/WebKitSupport/ChromeClientWx.cpp index 6dfe7a4..411f795 100644 --- a/WebKit/wx/WebKitSupport/ChromeClientWx.cpp +++ b/WebKit/wx/WebKitSupport/ChromeClientWx.cpp @@ -355,6 +355,13 @@ void ChromeClientWx::exceededDatabaseQuota(Frame*, const String&) } #endif +#if ENABLE(OFFLINE_WEB_APPLICATIONS) +void ChromeClientWx::reachedMaxAppCacheSize(int64_t spaceNeeded) +{ + notImplemented(); +} +#endif + void ChromeClientWx::scroll(const IntSize&, const IntRect&, const IntRect&) { notImplemented(); diff --git a/WebKit/wx/WebKitSupport/ChromeClientWx.h b/WebKit/wx/WebKitSupport/ChromeClientWx.h index df1fdd8..d7f4152 100644 --- a/WebKit/wx/WebKitSupport/ChromeClientWx.h +++ b/WebKit/wx/WebKitSupport/ChromeClientWx.h @@ -113,6 +113,11 @@ public: #if ENABLE(DATABASE) virtual void exceededDatabaseQuota(Frame*, const String&); #endif + +#if ENABLE(OFFLINE_WEB_APPLICATIONS) + virtual void reachedMaxAppCacheSize(int64_t spaceNeeded); +#endif + virtual void runOpenPanel(Frame*, PassRefPtr<FileChooser>); virtual void formStateDidChange(const Node*) { } |