summaryrefslogtreecommitdiffstats
path: root/WebKit/android
diff options
context:
space:
mode:
Diffstat (limited to 'WebKit/android')
-rw-r--r--WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp8
-rw-r--r--WebKit/android/WebCoreSupport/ChromeClientAndroid.h2
-rw-r--r--WebKit/android/WebCoreSupport/PlatformBridge.cpp20
-rw-r--r--WebKit/android/jni/WebSettings.cpp4
-rw-r--r--WebKit/android/jni/WebViewCore.cpp135
-rw-r--r--WebKit/android/jni/WebViewCore.h17
-rw-r--r--WebKit/android/nav/CacheBuilder.cpp4
-rw-r--r--WebKit/android/nav/WebView.cpp15
-rw-r--r--WebKit/android/plugins/ANPWindowInterface.cpp3
-rw-r--r--WebKit/android/plugins/PluginDebugAndroid.cpp130
-rw-r--r--WebKit/android/plugins/PluginDebugAndroid.h14
-rw-r--r--WebKit/android/plugins/PluginWidgetAndroid.cpp180
-rw-r--r--WebKit/android/plugins/PluginWidgetAndroid.h20
13 files changed, 395 insertions, 157 deletions
diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
index ffa96f8..17dc0d0 100644
--- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
+++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.cpp
@@ -71,8 +71,10 @@ void ChromeClientAndroid::compositingLayerSync()
frameView->syncCompositingStateRecursive();
GraphicsLayerAndroid* androidGraphicsLayer =
static_cast<GraphicsLayerAndroid*>(m_rootGraphicsLayer);
- if (androidGraphicsLayer)
+ if (androidGraphicsLayer) {
androidGraphicsLayer->sendImmediateRepaint();
+ androidGraphicsLayer->notifyClientAnimationStarted();
+ }
return;
}
}
@@ -466,12 +468,12 @@ void ChromeClientAndroid::wakeUpMainThreadWithNewQuota(long newQuota) {
}
#if ENABLE(TOUCH_EVENTS)
-void ChromeClientAndroid::needTouchEvents(bool needTouchEvents, bool force)
+void ChromeClientAndroid::needTouchEvents(bool needTouchEvents)
{
FrameView* frameView = m_webFrame->page()->mainFrame()->view();
android::WebViewCore* core = android::WebViewCore::getWebViewCore(frameView);
if (core)
- core->needTouchEvents(needTouchEvents, force);
+ core->needTouchEvents(needTouchEvents);
}
#endif
diff --git a/WebKit/android/WebCoreSupport/ChromeClientAndroid.h b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h
index b61f9fd..15bf52a 100644
--- a/WebKit/android/WebCoreSupport/ChromeClientAndroid.h
+++ b/WebKit/android/WebCoreSupport/ChromeClientAndroid.h
@@ -137,7 +137,7 @@ namespace android {
virtual void populateVisitedLinks();
#if ENABLE(TOUCH_EVENTS)
- virtual void needTouchEvents(bool, bool);
+ virtual void needTouchEvents(bool);
#endif
// Methods used to request and provide Geolocation permissions.
diff --git a/WebKit/android/WebCoreSupport/PlatformBridge.cpp b/WebKit/android/WebCoreSupport/PlatformBridge.cpp
index f36ecf7..b91a5d8 100644
--- a/WebKit/android/WebCoreSupport/PlatformBridge.cpp
+++ b/WebKit/android/WebCoreSupport/PlatformBridge.cpp
@@ -29,7 +29,9 @@
#include "CookieClient.h"
#include "JavaSharedClient.h"
#include "KeyGeneratorClient.h"
+#include "PluginView.h"
#include "WebViewCore.h"
+#include "npruntime.h"
#include <wtf/android/AndroidThreading.h>
#include <wtf/MainThread.h>
@@ -98,11 +100,29 @@ bool PlatformBridge::cookiesEnabled()
return client->cookiesEnabled();
}
+NPObject* PlatformBridge::pluginScriptableObject(Widget* widget)
+{
+#if USE(V8)
+ if (!widget->isPluginView())
+ return 0;
+
+ PluginView* pluginView = static_cast<PluginView*>(widget);
+ return pluginView->getNPObject();
+#else
+ return 0;
+#endif
+}
+
bool PlatformBridge::isWebViewPaused()
{
return WebViewCore::isPaused();
}
+bool PlatformBridge::popupsAllowed(NPP)
+{
+ return false;
+}
+
} // namespace WebCore
diff --git a/WebKit/android/jni/WebSettings.cpp b/WebKit/android/jni/WebSettings.cpp
index 00fec85..50919b6 100644
--- a/WebKit/android/jni/WebSettings.cpp
+++ b/WebKit/android/jni/WebSettings.cpp
@@ -35,8 +35,8 @@
#include "Frame.h"
#include "FrameLoader.h"
#include "FrameView.h"
-#include "Geolocation.h"
#include "GeolocationPermissions.h"
+#include "GeolocationPositionCache.h"
#include "Page.h"
#include "PageCache.h"
#include "RenderTable.h"
@@ -366,7 +366,7 @@ public:
str = (jstring)env->GetObjectField(obj, gFieldIds->mGeolocationDatabasePath);
if (str) {
GeolocationPermissions::setDatabasePath(to_string(env,str));
- WebCore::Geolocation::setDatabasePath(to_string(env,str));
+ WebCore::GeolocationPositionCache::setDatabasePath(to_string(env,str));
}
size = env->GetIntField(obj, gFieldIds->mPageCacheCapacity);
diff --git a/WebKit/android/jni/WebViewCore.cpp b/WebKit/android/jni/WebViewCore.cpp
index 5ebc8eb..ae3e47c 100644
--- a/WebKit/android/jni/WebViewCore.cpp
+++ b/WebKit/android/jni/WebViewCore.cpp
@@ -229,6 +229,7 @@ struct WebViewCore::JavaGlue {
jmethodID m_destroySurface;
jmethodID m_getContext;
jmethodID m_sendFindAgain;
+ jmethodID m_showRect;
AutoJObject object(JNIEnv* env) {
return getRealObject(env, m_obj);
}
@@ -267,7 +268,9 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_screenWidth = 320;
m_scale = 1;
m_screenWidthScale = 1;
- m_touchEventListenerCount = 0;
+#if ENABLE(TOUCH_EVENTS)
+ m_forwardingTouchEvents = false;
+#endif
LOG_ASSERT(m_mainFrame, "Uh oh, somehow a frameview was made without an initial frame!");
@@ -314,6 +317,7 @@ WebViewCore::WebViewCore(JNIEnv* env, jobject javaWebViewCore, WebCore::Frame* m
m_javaGlue->m_destroySurface = GetJMethod(env, clazz, "destroySurface", "(Landroid/webkit/ViewManager$ChildView;)V");
m_javaGlue->m_getContext = GetJMethod(env, clazz, "getContext", "()Landroid/content/Context;");
m_javaGlue->m_sendFindAgain = GetJMethod(env, clazz, "sendFindAgain", "()V");
+ m_javaGlue->m_showRect = GetJMethod(env, clazz, "showRect", "(IIIIIIFFFF)V");
env->SetIntField(javaWebViewCore, gWebViewCoreFields.m_nativeClass, (jint)this);
@@ -996,28 +1000,20 @@ void WebViewCore::restoreScreenWidthScale(int scale)
checkException(env);
}
-void WebViewCore::needTouchEvents(bool need, bool force)
+void WebViewCore::needTouchEvents(bool need)
{
DEBUG_NAV_UI_LOGD("%s", __FUNCTION__);
LOG_ASSERT(m_javaGlue->m_obj, "A Java widget was not associated with this view bridge!");
-#if ENABLE(TOUCH_EVENTS) // Android
- bool needToUpdateJava = false;
- if (need) {
- if (++m_touchEventListenerCount == 1)
- needToUpdateJava = true;
- } else {
- if (force)
- m_touchEventListenerCount = 0;
- else if (--m_touchEventListenerCount == 0)
- needToUpdateJava = true;
- }
+#if ENABLE(TOUCH_EVENTS)
+ if (m_forwardingTouchEvents == need)
+ return;
- if (needToUpdateJava || force) {
- JNIEnv* env = JSC::Bindings::getJNIEnv();
- env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_needTouchEvents, need);
- checkException(env);
- }
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_needTouchEvents, need);
+ checkException(env);
+
+ m_forwardingTouchEvents = need;
#endif
}
@@ -1099,13 +1095,15 @@ 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,
- bool ignoreHeight)
+ int anchorX, int anchorY, 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;
@@ -1124,46 +1122,82 @@ void WebViewCore::setSizeScreenWidthAndScale(int width, int height,
DBG_NAV_LOGD("renderer=%p view=(w=%d,h=%d)", r,
realScreenWidth, screenHeight);
if (r) {
- // get current screen center position
- WebCore::IntPoint screenCenter = WebCore::IntPoint(
- m_scrollOffsetX + (realScreenWidth >> 1),
- m_scrollOffsetY + (screenHeight >> 1));
+ WebCore::IntPoint anchorPoint;
+ if ((anchorX | anchorY) == 0)
+ // get the current screen center position if anchor is (0, 0)
+ // which implies that it is not defined
+ anchorPoint = WebCore::IntPoint(
+ m_scrollOffsetX + (realScreenWidth >> 1),
+ m_scrollOffsetY + (screenHeight >> 1));
+ else
+ anchorPoint = WebCore::IntPoint(anchorX, anchorY);
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) {
+ // orientation change. Try to keep the anchor at the same place.
+ if (osw && screenWidth && osw != screenWidth) {
WebCore::HitTestResult hitTestResult =
m_mainFrame->eventHandler()-> hitTestResultAtPoint(
- screenCenter, false);
+ anchorPoint, 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());
- 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;
+ // sites like nytimes.com insert a non-standard tag <nyt_text>
+ // in the html. If it is the HitTestResult, it may have zero
+ // width and height. In this case, use its parent node.
+ if (bounds.width() == 0) {
+ node = node->parent();
+ if (node) {
+ bounds = node->getRect();
+ DBG_NAV_LOGD("found a zero width node and use its parent, whose ob:(x=%d,y=%d,w=%d,h=%d)",
+ bounds.x(), bounds.y(), bounds.width(), bounds.height());
+ }
+ }
+ if ((anchorX | anchorY) == 0) {
+ // if there is no explicit anchor, ignore if it is offscreen
+ 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;
+ }
}
}
r->setNeedsLayoutAndPrefWidthsRecalc();
m_mainFrame->view()->forceLayout();
// scroll to restore current screen center
- 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);
+ if (!node)
+ return;
+ const WebCore::IntRect& newBounds = node->getRect();
+ DBG_NAV_LOGD("nb:(x=%d,y=%d,w=%d,"
+ "h=%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);
}
}
}
@@ -2398,6 +2432,17 @@ bool WebViewCore::validNodeAndBounds(Frame* frame, Node* node,
return absBounds == originalAbsoluteBounds;
}
+void WebViewCore::showRect(int left, int top, int width, int height,
+ int contentWidth, int contentHeight, float xPercentInDoc,
+ float xPercentInView, float yPercentInDoc, float yPercentInView)
+{
+ JNIEnv* env = JSC::Bindings::getJNIEnv();
+ env->CallVoidMethod(m_javaGlue->object(env).get(), m_javaGlue->m_showRect,
+ left, top, width, height, contentWidth, contentHeight,
+ xPercentInDoc, xPercentInView, yPercentInDoc, yPercentInView);
+ checkException(env);
+}
+
//----------------------------------------------------------------------
// Native JNI methods
//----------------------------------------------------------------------
@@ -2425,7 +2470,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,
- jboolean ignoreHeight)
+ jint anchorX, jint anchorY, jboolean ignoreHeight)
{
#ifdef ANDROID_INSTRUMENT
TimeCounterAuto counter(TimeCounter::WebViewCoreTimeCounter);
@@ -2434,7 +2479,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, ignoreHeight);
+ realScreenWidth, screenHeight, anchorX, anchorY, ignoreHeight);
}
static void SetScrollOffset(JNIEnv *env, jobject obj, jint gen, jint x, jint y)
@@ -3022,7 +3067,7 @@ static JNINativeMethod gJavaWebViewCoreMethods[] = {
(void*) SendListBoxChoices },
{ "nativeSendListBoxChoice", "(I)V",
(void*) SendListBoxChoice },
- { "nativeSetSize", "(IIIFIIZ)V",
+ { "nativeSetSize", "(IIIFIIIIZ)V",
(void*) SetSize },
{ "nativeSetScrollOffset", "(III)V",
(void*) SetScrollOffset },
diff --git a/WebKit/android/jni/WebViewCore.h b/WebKit/android/jni/WebViewCore.h
index c662441..2252878 100644
--- a/WebKit/android/jni/WebViewCore.h
+++ b/WebKit/android/jni/WebViewCore.h
@@ -265,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,
- bool ignoreHeight);
+ float scale, int realScreenWidth, int screenHeight, int anchorX,
+ int anchorY, bool ignoreHeight);
/**
* Handle key events from Java.
@@ -375,7 +375,7 @@ namespace android {
Node* cursorNodeIsPlugin();
// Notify the Java side whether it needs to pass down the touch events
- void needTouchEvents(bool, bool);
+ void needTouchEvents(bool);
// Notify the Java side that webkit is requesting a keyboard
void requestKeyboard(bool showKeyboard, bool isTextView);
@@ -405,6 +405,15 @@ namespace android {
jobject getContext();
bool validNodeAndBounds(Frame* , Node* , const IntRect& );
+
+ // 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);
+
// other public functions
public:
// Open a file chooser for selecting a file to upload
@@ -527,7 +536,7 @@ namespace android {
WebCore::HTMLAnchorElement* retrieveAnchorElement(WebCore::Frame* frame, WebCore::Node* node);
#if ENABLE(TOUCH_EVENTS)
- int m_touchEventListenerCount;
+ bool m_forwardingTouchEvents;
IntPoint m_lastTouchPoint;
#endif
diff --git a/WebKit/android/nav/CacheBuilder.cpp b/WebKit/android/nav/CacheBuilder.cpp
index 784c3aa..c665887 100644
--- a/WebKit/android/nav/CacheBuilder.cpp
+++ b/WebKit/android/nav/CacheBuilder.cpp
@@ -1889,7 +1889,9 @@ CacheBuilder::FoundState CacheBuilder::FindPartialAddress(const UChar* baseChars
s->mProgress = ZIP_CODE;
// a couple of delimiters is an indication that the state name is good
// or, a non-space / non-alpha-digit is also good
- s->mZipDelimiter = s->mLineCount > 2 || isUnicodeSpace(ch) == false;
+ s->mZipDelimiter = s->mLineCount > 2
+ || isUnicodeSpace(ch) == false
+ || chars == s->mEnd;
if (WTF::isASCIIDigit(ch))
s->mZipStart = chars;
goto resetState;
diff --git a/WebKit/android/nav/WebView.cpp b/WebKit/android/nav/WebView.cpp
index 98f308c..e2a7708 100644
--- a/WebKit/android/nav/WebView.cpp
+++ b/WebKit/android/nav/WebView.cpp
@@ -1533,13 +1533,10 @@ static void nativeDrawLayers(JNIEnv *env, jobject obj,
#endif
}
-static void nativeUpdateLayers(JNIEnv *env, jobject obj,
- jint layer, jint updates)
+static void nativeUpdateLayers(JNIEnv *env, jobject obj, jint updates)
{
if (!env)
return;
- if (!layer)
- return;
if (!updates)
return;
@@ -1998,13 +1995,15 @@ static void nativeMoveCursorToNextTextInput(JNIEnv *env, jobject obj)
CachedRoot* root = view->getFrameCache(WebView::DontAllowNewer);
if (!root)
return;
- const CachedNode* current = root->currentCursor();
+ const CachedFrame* containingFrame;
+ const CachedNode* current = root->currentCursor(&containingFrame);
if (!current)
- current = root->currentFocus();
+ current = root->currentFocus(&containingFrame);
if (!current)
return;
const CachedFrame* frame;
- const CachedNode* next = root->nextTextField(current, &frame, true);
+ const CachedNode* next = containingFrame->nextTextField(current, &frame,
+ true);
if (!next)
return;
const WebCore::IntRect& bounds = next->bounds();
@@ -2136,7 +2135,7 @@ static JNINativeMethod gJavaWebViewMethods[] = {
(void*) nativeEvaluateLayersAnimations },
{ "nativeDrawLayers", "(IIIIIFLandroid/graphics/Canvas;)V",
(void*) nativeDrawLayers },
- { "nativeUpdateLayers", "(II)V",
+ { "nativeUpdateLayers", "(I)V",
(void*) nativeUpdateLayers },
{ "nativeDrawMatches", "(Landroid/graphics/Canvas;)V",
(void*) nativeDrawMatches },
diff --git a/WebKit/android/plugins/ANPWindowInterface.cpp b/WebKit/android/plugins/ANPWindowInterface.cpp
index 06afab1..bb7b9a3 100644
--- a/WebKit/android/plugins/ANPWindowInterface.cpp
+++ b/WebKit/android/plugins/ANPWindowInterface.cpp
@@ -49,7 +49,8 @@ static void anp_clearVisibleRects(NPP instance) {
static void anp_showKeyboard(NPP instance, bool value) {
PluginView* pluginView = pluginViewForInstance(instance);
PluginWidgetAndroid* pluginWidget = pluginView->platformPluginWidget();
- pluginWidget->webViewCore()->requestKeyboard(value, false);
+ if(pluginWidget->hasFocus())
+ pluginWidget->webViewCore()->requestKeyboard(value, false);
}
static void anp_requestFullScreen(NPP instance) {
diff --git a/WebKit/android/plugins/PluginDebugAndroid.cpp b/WebKit/android/plugins/PluginDebugAndroid.cpp
new file mode 100644
index 0000000..3f1db2d
--- /dev/null
+++ b/WebKit/android/plugins/PluginDebugAndroid.cpp
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2010, The Android Open Source Project
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "PluginDebugAndroid.h"
+#include "utils/Log.h"
+#include <stdarg.h>
+
+#define ARRAY_COUNT(array) static_cast<int32_t>(sizeof(array) / sizeof(array[0]))
+
+// used for key, mouse, and touch inputs
+static const char* const inputActions[] = {
+ "down",
+ "up",
+ "move", /* touch only */
+ "cancel", /* touch only */
+ "longPress", /* touch only */
+ "doubleTap" /* touch only */
+};
+
+static const char* const lifecycleActions[] = {
+ "kPause_ANPLifecycleAction",
+ "kResume_ANPLifecycleAction",
+ "kGainFocus_ANPLifecycleAction",
+ "kLoseFocus_ANPLifecycleAction",
+ "kFreeMemory_ANPLifecycleAction",
+ "kOnLoad_ANPLifecycleAction",
+ "kEnterFullScreen_ANPLifecycleAction",
+ "kExitFullScreen_ANPLifecycleAction",
+ "kOnScreen_ANPLifecycleAction",
+ "kOffScreen_ANPLifecycleAction"
+};
+
+void anp_logPlugin(const char format[], ...) {
+ va_list args;
+ va_start(args, format);
+ LOG_PRI_VA(ANDROID_LOG_DEBUG, "webkit_plugin", format, args);
+ va_end(args);
+}
+
+void anp_logPluginEvent(void* npp, const ANPEvent* evt, int16 returnVal) {
+
+ switch(evt->eventType) {
+
+ case kNull_ANPEventType:
+ PLUGIN_LOG("%p EVENT::NULL", npp);
+ break;
+
+ case kKey_ANPEventType:
+ if(evt->data.key.action < ARRAY_COUNT(inputActions)) {
+ anp_logPlugin("%p EVENT::KEY[%d] action=%s code=%d vcode=%d unichar=%d repeat=%d mods=%x",
+ npp, returnVal, inputActions[evt->data.key.action],
+ evt->data.key.nativeCode, evt->data.key.virtualCode,
+ evt->data.key.unichar, evt->data.key.repeatCount,
+ evt->data.key.modifiers);
+ } else {
+ PLUGIN_LOG("%p EVENT::KEY[%d] unknown action", npp, returnVal);
+ }
+ break;
+
+ case kMouse_ANPEventType:
+ if(evt->data.mouse.action < ARRAY_COUNT(inputActions)) {
+ anp_logPlugin("%p EVENT::MOUSE[%d] action=%s [%d %d]", npp,
+ returnVal, inputActions[evt->data.mouse.action],
+ evt->data.touch.x, evt->data.touch.y);
+ } else {
+ anp_logPlugin("%p EVENT::MOUSE[%d] unknown action", npp, returnVal);
+ }
+ break;
+
+ case kTouch_ANPEventType:
+ if(evt->data.touch.action < ARRAY_COUNT(inputActions)) {
+ anp_logPlugin("%p EVENT::TOUCH[%d] action=%s [%d %d]", npp,
+ returnVal, inputActions[evt->data.touch.action],
+ evt->data.touch.x, evt->data.touch.y);
+ } else {
+ anp_logPlugin("%p EVENT::TOUCH[%d] unknown action", npp, returnVal);
+ }
+ break;
+
+ case kDraw_ANPEventType:
+ if (evt->data.draw.model == kBitmap_ANPDrawingModel) {
+ anp_logPlugin("%p EVENT::DRAW bitmap format=%d clip=[%d,%d,%d,%d]",
+ npp, evt->data.draw.data.bitmap.format,
+ evt->data.draw.clip.left, evt->data.draw.clip.top,
+ evt->data.draw.clip.right, evt->data.draw.clip.bottom);
+ } else {
+ anp_logPlugin("%p EVENT::DRAW unknown drawing model", npp);
+ }
+ break;
+
+ case kLifecycle_ANPEventType:
+ if(evt->data.lifecycle.action < ARRAY_COUNT(lifecycleActions)) {
+ anp_logPlugin("%p EVENT::LIFECYCLE %s", npp,
+ lifecycleActions[evt->data.lifecycle.action]);
+ } else {
+ anp_logPlugin("%p EVENT::LIFECYCLE unknown action", npp);
+ }
+ break;
+
+ case kCustom_ANPEventType:
+ anp_logPlugin("%p EVENT::CUSTOM", npp);
+ break;
+
+ default:
+ anp_logPlugin("%p EVENT::UNKNOWN", npp);
+ break;
+ }
+}
diff --git a/WebKit/android/plugins/PluginDebugAndroid.h b/WebKit/android/plugins/PluginDebugAndroid.h
index 2143b39..24944cb 100644
--- a/WebKit/android/plugins/PluginDebugAndroid.h
+++ b/WebKit/android/plugins/PluginDebugAndroid.h
@@ -26,21 +26,25 @@
#ifndef PLUGIN_DEBUG_ANDROID_H__
#define PLUGIN_DEBUG_ANDROID_H__
-#ifdef ANDROID_PLUGINS
+#include "android_npapi.h"
// Define PLUGIN_DEBUG_LOCAL in an individual C++ file to enable for
// that file only.
// Define PLUGIN_DEBUG_GLOBAL to 1 to turn plug-in debug for all
-// Android plug-in code in this direectory.
+// Android plug-in code in this directory.
#define PLUGIN_DEBUG_GLOBAL 0
#if PLUGIN_DEBUG_GLOBAL || defined(PLUGIN_DEBUG_LOCAL)
-# define PLUGIN_LOG(A, B...) do { LOGI( A , ## B ); } while(0)
+# define PLUGIN_LOG(FORMAT, ARGS...) do { anp_logPlugin(FORMAT, ## ARGS); } while(0)
+# define PLUGIN_LOG_EVENT(NPP, EVT, RET) do { anp_logPluginEvent(NPP, EVT, RET); } while(0)
+
+void anp_logPlugin(const char format[], ...);
+void anp_logPluginEvent(void* npp, const ANPEvent* event, int16 returnVal);
+
#else
# define PLUGIN_LOG(A, B...) do { } while(0)
-#endif
-
+# define PLUGIN_LOG_EVENT(NPP, EVENT) do { } while(0)
#endif
#endif // defined(PLUGIN_DEBUG_ANDROID_H__)
diff --git a/WebKit/android/plugins/PluginWidgetAndroid.cpp b/WebKit/android/plugins/PluginWidgetAndroid.cpp
index 553b455..7109ab4 100644
--- a/WebKit/android/plugins/PluginWidgetAndroid.cpp
+++ b/WebKit/android/plugins/PluginWidgetAndroid.cpp
@@ -44,8 +44,12 @@
#include "android_graphics.h"
#include <JNIUtility.h>
+#define PLUGIN_DEBUG_LOCAL 0 // controls the printing of log messages
#define DEBUG_VISIBLE_RECTS 1 // temporary debug printfs and fixes
+// this include statement must follow the declaration of PLUGIN_DEBUG_LOCAL
+#include "PluginDebugAndroid.h"
+
PluginWidgetAndroid::PluginWidgetAndroid(WebCore::PluginView* view)
: m_pluginView(view) {
m_flipPixelRef = NULL;
@@ -54,7 +58,7 @@ PluginWidgetAndroid::PluginWidgetAndroid(WebCore::PluginView* view)
m_eventFlags = 0;
m_pluginWindow = NULL;
m_requestedVisibleRectCount = 0;
- m_requestedDocRect.setEmpty();
+ m_requestedVisibleRect.setEmpty();
m_visibleDocRect.setEmpty();
m_pluginBounds.setEmpty();
m_hasFocus = false;
@@ -113,14 +117,8 @@ void PluginWidgetAndroid::setWindow(NPWindow* window, bool isTransparent) {
if (m_drawingModel == kSurface_ANPDrawingModel) {
- // if the surface exists check for changes and update accordingly
- if (m_embeddedView && m_pluginBounds != oldPluginBounds) {
-
- m_core->updateSurface(m_embeddedView, window->x, window->y,
- window->width, window->height);
-
// if the surface does not exist then create a new surface
- } else if(!m_embeddedView) {
+ if (!m_embeddedView) {
WebCore::PluginPackage* pkg = m_pluginView->plugin();
NPP instance = m_pluginView->instance();
@@ -136,10 +134,15 @@ void PluginWidgetAndroid::setWindow(NPWindow* window, bool isTransparent) {
JNIEnv* env = JSC::Bindings::getJNIEnv();
m_embeddedView = env->NewGlobalRef(tempObj);
}
- }
- if (m_isFullScreen && m_pluginBounds != oldPluginBounds) {
- m_core->updateFullScreenPlugin(window->x, window->y,
- window->width, window->height);
+ } else if (m_pluginBounds != oldPluginBounds) {
+ // if the surface exists check for changes and update accordingly
+ if (m_isFullScreen) {
+ m_core->updateFullScreenPlugin(window->x, window->y,
+ window->width, window->height);
+ } else {
+ m_core->updateSurface(m_embeddedView, window->x, window->y,
+ window->width, window->height);
+ }
}
} else {
m_flipPixelRef->safeUnref();
@@ -224,28 +227,38 @@ void PluginWidgetAndroid::draw(SkCanvas* canvas) {
}
}
-bool PluginWidgetAndroid::sendEvent(const ANPEvent& evt) {
+int16 PluginWidgetAndroid::sendEvent(const ANPEvent& evt) {
if (!m_acceptEvents)
- return false;
+ return 0;
WebCore::PluginPackage* pkg = m_pluginView->plugin();
NPP instance = m_pluginView->instance();
// "missing" plugins won't have these
if (pkg && instance) {
- // keep track of whether or not the plugin currently has focus
- if (evt.eventType == kLifecycle_ANPEventType) {
- if (evt.data.lifecycle.action == kLoseFocus_ANPLifecycleAction)
- m_hasFocus = false;
- else if (evt.data.lifecycle.action == kGainFocus_ANPLifecycleAction)
- m_hasFocus = true;
+ // if the plugin is gaining focus then update our state now to allow
+ // the plugin's event handler to perform actions that require focus
+ if (evt.eventType == kLifecycle_ANPEventType &&
+ evt.data.lifecycle.action == kGainFocus_ANPLifecycleAction) {
+ m_hasFocus = true;
}
// make a localCopy since the actual plugin may not respect its constness,
// and so we don't want our caller to have its param modified
ANPEvent localCopy = evt;
- return pkg->pluginFuncs()->event(instance, &localCopy);
+ int16 result = pkg->pluginFuncs()->event(instance, &localCopy);
+ PLUGIN_LOG_EVENT(instance, &evt, result);
+
+ // if the plugin is losing focus then delay the update of our state
+ // until after we notify the plugin and allow them to perform actions
+ // that may require focus
+ if (evt.eventType == kLifecycle_ANPEventType &&
+ evt.data.lifecycle.action == kLoseFocus_ANPLifecycleAction) {
+ m_hasFocus = false;
+ }
+
+ return result;
}
- return false;
+ return 0;
}
void PluginWidgetAndroid::updateEventFlags(ANPEventFlags flags) {
@@ -258,14 +271,8 @@ void PluginWidgetAndroid::updateEventFlags(ANPEventFlags flags) {
Document* doc = m_pluginView->getParentFrame()->document();
#if ENABLE(TOUCH_EVENTS)
if((m_eventFlags ^ flags) & kTouch_ANPEventFlag) {
- if (flags & kTouch_ANPEventFlag) {
- if (Page* page = doc->page())
- page->chrome()->client()->needTouchEvents(true, false);
- doc->addListenerTypeIfNeeded(eventNames().touchstartEvent);
- } else {
- if (Page* page = doc->page())
- page->chrome()->client()->needTouchEvents(false, false);
- }
+ if (flags & kTouch_ANPEventFlag)
+ doc->addListenerTypeIfNeeded(eventNames().touchstartEvent);
}
#endif
@@ -278,22 +285,32 @@ bool PluginWidgetAndroid::isAcceptingEvent(ANPEventFlag flag) {
void PluginWidgetAndroid::setVisibleScreen(const ANPRectI& visibleDocRect, float zoom) {
#if DEBUG_VISIBLE_RECTS
- SkDebugf("%s (%d,%d,%d,%d)", __FUNCTION__, visibleDocRect.left,
- visibleDocRect.top, visibleDocRect.right, visibleDocRect.bottom);
+ PLUGIN_LOG("%s (%d,%d,%d,%d)[%f]", __FUNCTION__, visibleDocRect.left,
+ visibleDocRect.top, visibleDocRect.right,
+ visibleDocRect.bottom, zoom);
#endif
// TODO update the bitmap size based on the zoom? (for kBitmap_ANPDrawingModel)
int oldScreenW = m_visibleDocRect.width();
int oldScreenH = m_visibleDocRect.height();
- m_visibleDocRect.set(visibleDocRect.left, visibleDocRect.top,
- visibleDocRect.right, visibleDocRect.bottom);
+ // make local copies of the parameters
+ m_zoomLevel = zoom;
+ 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)
- computeVisibleDocRect();
+ PLUGIN_LOG("%s VisibleDoc Dimensions old=[%d,%d] new=[%d,%d] ",
+ __FUNCTION__, oldScreenW, oldScreenH, newScreenW, newScreenH);
+
+ // if the screen dimensions have changed by more than 5 pixels in either
+ // direction then recompute the plugin's visible rectangle
+ if (abs(oldScreenW - newScreenW) > 5 || abs(oldScreenH - newScreenH) > 5)
+ computeVisiblePluginRect();
bool visible = SkIRect::Intersects(m_visibleDocRect, m_pluginBounds);
if(m_visible != visible) {
@@ -310,7 +327,7 @@ void PluginWidgetAndroid::setVisibleScreen(const ANPRectI& visibleDocRect, float
void PluginWidgetAndroid::setVisibleRects(const ANPRectI rects[], int32_t count) {
#if DEBUG_VISIBLE_RECTS
- SkDebugf("%s count=%d", __FUNCTION__, count);
+ PLUGIN_LOG("%s count=%d", __FUNCTION__, count);
#endif
// ensure the count does not exceed our allocated space
if (count > MAX_REQUESTED_RECTS)
@@ -318,33 +335,33 @@ void PluginWidgetAndroid::setVisibleRects(const ANPRectI rects[], int32_t count)
// store the values in member variables
m_requestedVisibleRectCount = count;
- memcpy(m_requestedVisibleRect, rects, count * sizeof(rects[0]));
+ memcpy(m_requestedVisibleRects, rects, count * sizeof(rects[0]));
#if DEBUG_VISIBLE_RECTS // FIXME: this fixes bad data from the plugin
// take it out once plugin supplies better data
for (int index = 0; index < count; index++) {
- SkDebugf("%s [%d](%d,%d,%d,%d)", __FUNCTION__, index,
- m_requestedVisibleRect[index].left,
- m_requestedVisibleRect[index].top,
- m_requestedVisibleRect[index].right,
- m_requestedVisibleRect[index].bottom);
- if (m_requestedVisibleRect[index].left ==
- m_requestedVisibleRect[index].right) {
- m_requestedVisibleRect[index].right += 1;
+ PLUGIN_LOG("%s [%d](%d,%d,%d,%d)", __FUNCTION__, index,
+ m_requestedVisibleRects[index].left,
+ m_requestedVisibleRects[index].top,
+ m_requestedVisibleRects[index].right,
+ m_requestedVisibleRects[index].bottom);
+ if (m_requestedVisibleRects[index].left ==
+ m_requestedVisibleRects[index].right) {
+ m_requestedVisibleRects[index].right += 1;
}
- if (m_requestedVisibleRect[index].top ==
- m_requestedVisibleRect[index].bottom) {
- m_requestedVisibleRect[index].bottom += 1;
+ if (m_requestedVisibleRects[index].top ==
+ m_requestedVisibleRects[index].bottom) {
+ m_requestedVisibleRects[index].bottom += 1;
}
}
#endif
- computeVisibleDocRect();
+ computeVisiblePluginRect();
}
-void PluginWidgetAndroid::computeVisibleDocRect() {
+void PluginWidgetAndroid::computeVisiblePluginRect() {
// ensure the visibleDocRect has been set (i.e. not equal to zero)
- if (m_visibleDocRect.isEmpty() || !m_pluginWindow)
+ if (m_visibleDocRect.isEmpty() || !m_pluginWindow || m_requestedVisibleRectCount < 1)
return;
// create a rect that will contain as many of the rects that will fit on screen
@@ -353,7 +370,7 @@ void PluginWidgetAndroid::computeVisibleDocRect() {
for (int counter = 0; counter < m_requestedVisibleRectCount; counter++) {
- ANPRectI* rect = &m_requestedVisibleRect[counter];
+ ANPRectI* rect = &m_requestedVisibleRects[counter];
// create skia rect for easier manipulation and convert it to page coordinates
SkIRect pluginRect;
@@ -363,64 +380,67 @@ void PluginWidgetAndroid::computeVisibleDocRect() {
// ensure the rect falls within the plugin's bounds
if (!m_pluginBounds.contains(pluginRect)) {
#if DEBUG_VISIBLE_RECTS
- SkDebugf("%s (%d,%d,%d,%d) !contain (%d,%d,%d,%d)", __FUNCTION__,
- m_pluginBounds.fLeft, m_pluginBounds.fTop,
- m_pluginBounds.fRight, m_pluginBounds.fBottom,
- pluginRect.fLeft, pluginRect.fTop,
- pluginRect.fRight, pluginRect.fBottom);
- // FIXME: assume that the desired outcome is to clamp to the container
- pluginRect.intersect(m_pluginBounds);
+ PLUGIN_LOG("%s (%d,%d,%d,%d) !contain (%d,%d,%d,%d)", __FUNCTION__,
+ m_pluginBounds.fLeft, m_pluginBounds.fTop,
+ m_pluginBounds.fRight, m_pluginBounds.fBottom,
+ pluginRect.fLeft, pluginRect.fTop,
+ pluginRect.fRight, pluginRect.fBottom);
+ // assume that the desired outcome is to clamp to the container
+ if (pluginRect.intersect(m_pluginBounds)) {
+ visibleRect = pluginRect;
+ }
#endif
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.
+ // check to see if the new rect could be made to fit 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()))
+ m_visibleDocRect.height() < pluginRect.height()))
break;
// set the new visible rect
visibleRect = pluginRect;
}
- m_requestedDocRect = visibleRect;
- scrollToVisibleDocRect();
+ m_requestedVisibleRect = visibleRect;
+ scrollToVisiblePluginRect();
}
-void PluginWidgetAndroid::scrollToVisibleDocRect() {
+void PluginWidgetAndroid::scrollToVisiblePluginRect() {
- if (!m_hasFocus || m_requestedDocRect.isEmpty() || m_visibleDocRect.isEmpty()) {
+ if (!m_hasFocus || m_requestedVisibleRect.isEmpty() || m_visibleDocRect.isEmpty()) {
#if DEBUG_VISIBLE_RECTS
- SkDebugf("%s call m_hasFocus=%d m_requestedDocRect.isEmpty()=%d"
- " m_visibleDocRect.isEmpty()=%d", __FUNCTION__, m_hasFocus,
- m_requestedDocRect.isEmpty(), m_visibleDocRect.isEmpty());
+ PLUGIN_LOG("%s call m_hasFocus=%d m_requestedVisibleRect.isEmpty()=%d"
+ " m_visibleDocRect.isEmpty()=%d", __FUNCTION__, m_hasFocus,
+ m_requestedVisibleRect.isEmpty(), m_visibleDocRect.isEmpty());
#endif
return;
}
// if the entire rect is already visible then we don't need to scroll
- if (m_visibleDocRect.contains(m_requestedDocRect))
+ if (m_visibleDocRect.contains(m_requestedVisibleRect))
return;
// find the center of the visibleRect in document coordinates
- int rectCenterX = m_requestedDocRect.fLeft + m_requestedDocRect.width()/2;
- int rectCenterY = m_requestedDocRect.fTop + m_requestedDocRect.height()/2;
+ int rectCenterX = m_requestedVisibleRect.fLeft + m_requestedVisibleRect.width()/2;
+ int rectCenterY = m_requestedVisibleRect.fTop + m_requestedVisibleRect.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;
+ int visibleDocCenterX = m_visibleDocRect.fLeft + m_visibleDocRect.width()/2;
+ int visibleDocCenterY = m_visibleDocRect.fTop + m_visibleDocRect.height()/2;
- //compute the delta of the two points
- int deltaX = rectCenterX - screenCenterX;
- int deltaY = rectCenterY - screenCenterY;
+ //compute the delta of the two points and scale to screen coordinates
+ int deltaX = rectCenterX - visibleDocCenterX;
+ int deltaY = rectCenterY - visibleDocCenterY;
ScrollView* scrollView = m_pluginView->parent();
android::WebViewCore* core = android::WebViewCore::getWebViewCore(scrollView);
#if DEBUG_VISIBLE_RECTS
- SkDebugf("%s call scrollBy (%d,%d)", __FUNCTION__, deltaX, deltaY);
+ PLUGIN_LOG("%s call scrollBy (%d,%d)", __FUNCTION__, deltaX, deltaY);
#endif
core->scrollBy(deltaX, deltaY, true);
}
diff --git a/WebKit/android/plugins/PluginWidgetAndroid.h b/WebKit/android/plugins/PluginWidgetAndroid.h
index 6633e1b..b47a4b3 100644
--- a/WebKit/android/plugins/PluginWidgetAndroid.h
+++ b/WebKit/android/plugins/PluginWidgetAndroid.h
@@ -89,10 +89,10 @@ struct PluginWidgetAndroid {
*/
void draw(SkCanvas* canvas = NULL);
- /* Send this event to the plugin instance, and return true if the plugin
- handled it.
+ /* Send this event to the plugin instance. A non-zero value will be
+ returned if the plugin handled the event.
*/
- bool sendEvent(const ANPEvent&);
+ int16 sendEvent(const ANPEvent&);
/* Update the plugins event flags. If a flag is set to true then the plugin
wants to be notified of events of this type.
@@ -135,9 +135,15 @@ struct PluginWidgetAndroid {
bool inFullScreen() { return m_isFullScreen; }
+ /** Called to check if a plugin currently has document focus, which is
+ required for certain operations (e.g. show/hide keyboard). It returns
+ true if the plugin currently has focus and false otherwise.
+ */
+ bool hasFocus() const { return m_hasFocus; }
+
private:
- void computeVisibleDocRect();
- void scrollToVisibleDocRect();
+ void computeVisiblePluginRect();
+ void scrollToVisiblePluginRect();
WebCore::PluginView* m_pluginView;
android::WebViewCore* m_core;
@@ -147,7 +153,7 @@ private:
NPWindow* m_pluginWindow;
SkIRect m_pluginBounds; // relative to the page
SkIRect m_visibleDocRect; // relative to the page
- SkIRect m_requestedDocRect; // relative to the page
+ SkIRect m_requestedVisibleRect; // relative to the page
bool m_hasFocus;
bool m_isFullScreen;
bool m_visible;
@@ -162,7 +168,7 @@ private:
MAX_REQUESTED_RECTS = 5,
};
- ANPRectI m_requestedVisibleRect[MAX_REQUESTED_RECTS];
+ ANPRectI m_requestedVisibleRects[MAX_REQUESTED_RECTS];
int32_t m_requestedVisibleRectCount;
};