summaryrefslogtreecommitdiffstats
path: root/WebCore
diff options
context:
space:
mode:
Diffstat (limited to 'WebCore')
-rw-r--r--WebCore/bindings/v8/ScriptController.cpp13
-rw-r--r--WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp216
-rw-r--r--WebCore/bridge/jni/v8/JNIUtilityPrivate.h6
-rw-r--r--WebCore/bridge/jni/v8/JavaNPObjectV8.cpp10
-rw-r--r--WebCore/bridge/npapi.h7
-rw-r--r--WebCore/html/HTMLPlugInElement.cpp7
-rw-r--r--WebCore/html/HTMLPlugInElement.h6
-rw-r--r--WebCore/platform/android/GeolocationServiceAndroid.cpp5
-rw-r--r--WebCore/platform/graphics/android/ImageSourceAndroid.cpp4
-rw-r--r--WebCore/platform/image-decoders/ImageDecoder.h5
-rw-r--r--WebCore/plugins/PluginStream.cpp25
-rw-r--r--WebCore/plugins/PluginStream.h4
-rw-r--r--WebCore/plugins/PluginView.h3
-rw-r--r--WebCore/plugins/android/PluginViewAndroid.cpp43
-rw-r--r--WebCore/rendering/RenderLayerCompositor.cpp57
-rw-r--r--WebCore/rendering/RenderLayerCompositor.h5
-rw-r--r--WebCore/rendering/RenderView.h3
17 files changed, 371 insertions, 48 deletions
diff --git a/WebCore/bindings/v8/ScriptController.cpp b/WebCore/bindings/v8/ScriptController.cpp
index e2b886d..4e8ba5e 100644
--- a/WebCore/bindings/v8/ScriptController.cpp
+++ b/WebCore/bindings/v8/ScriptController.cpp
@@ -334,6 +334,19 @@ PassScriptInstance ScriptController::createScriptInstanceForWidget(Widget* widge
v8::Local<v8::Object> wrapper = createV8ObjectForNPObject(npObject, 0);
+#ifdef ANDROID_FIX
+ // TODO: this should be up streamed.
+ // HTMLEmbedElement::getInstance() will call this function with its closest
+ // ancestor who has the objectTag. So this "widget" may be already in the
+ // HashMap. If it does, even m_pluginObjects.set() is a no-op, we do need to
+ // call _NPN_ReleaseObject on the npObject to balance the reference count.
+ PluginObjectMap::iterator it = m_pluginObjects.find(widget);
+ if (it != m_pluginObjects.end()) {
+ ASSERT(it->second == npObject);
+ _NPN_ReleaseObject(it->second);
+ }
+#endif
+
// Track the plugin object. We've been given a reference to the object.
m_pluginObjects.set(widget, npObject);
diff --git a/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp b/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp
index 1bdae53..a6c4149 100644
--- a/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp
+++ b/WebCore/bridge/jni/v8/JNIUtilityPrivate.cpp
@@ -28,6 +28,7 @@
#include "JavaInstanceV8.h"
#include "JavaNPObjectV8.h"
+#include "npruntime_impl.h"
namespace JSC {
@@ -40,9 +41,168 @@ jvalue convertNPVariantToJValue(NPVariant value, JNIType jniType, const char* ja
switch (jniType) {
case array_type:
+ {
+ JNIEnv* env = getJNIEnv();
+ jobject javaArray;
+ NPObject* object = NPVARIANT_IS_OBJECT(value) ? NPVARIANT_TO_OBJECT(value) : 0;
+ NPVariant npvLength;
+ bool success = _NPN_GetProperty(0, object, _NPN_GetStringIdentifier("length"), &npvLength);
+ if (!success) {
+ // No length property so we don't know how many elements to put into the array.
+ // Treat this as an error.
+#ifdef EMULATE_JSC_BINDINGS
+ // JSC sends null for an array that is not an array of strings or basic types,
+ // do this also in the unknown length case.
+ memset(&result, 0, sizeof(jvalue));
+#else
+ // Sending NULL as JSC does seems dangerous. (Imagine the java method that asks
+ // for the length of the array it was passed). Here we send a 0 length array.
+ jclass objectClass = env->FindClass("java/lang/Object");
+ javaArray = env->NewObjectArray(0, objectClass, 0);
+ env->DeleteLocalRef(objectClass);
+#endif
+ break;
+ }
+
+ jsize length = static_cast<jsize>(NPVARIANT_TO_INT32(npvLength));
+
+ if (!strcmp(javaClassName, "[Ljava.lang.String;")) {
+ // Match JSC behavior by only allowing Object arrays if they are Strings.
+ jclass stringClass = env->FindClass("java/lang/String");
+ javaArray = env->NewObjectArray(length, stringClass, 0);
+ for (jsize i = 0; i < length; i++) {
+ NPVariant npvValue;
+ _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
+ if(NPVARIANT_IS_STRING(npvValue)) {
+ NPString str = NPVARIANT_TO_STRING(npvValue);
+ env->SetObjectArrayElement(static_cast<jobjectArray>(javaArray), i, env->NewStringUTF(str.UTF8Characters));
+ }
+ }
+
+ env->DeleteLocalRef(stringClass);
+ } else if (!strcmp(javaClassName, "[B")) {
+ // array of bytes
+ javaArray = env->NewByteArray(length);
+ // Now iterate over each element and add to the array.
+ for (jsize i = 0; i < length; i++) {
+ NPVariant npvValue;
+ _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
+ if (NPVARIANT_IS_INT32(npvValue)) {
+ jbyte bVal = static_cast<jbyte>(NPVARIANT_TO_INT32(npvValue));
+ env->SetByteArrayRegion(static_cast<jbyteArray>(javaArray), i, 1, &bVal);
+ }
+ }
+ } else if (!strcmp(javaClassName, "[C")) {
+ // array of chars
+ javaArray = env->NewCharArray(length);
+ // Now iterate over each element and add to the array.
+ for (jsize i = 0; i < length; i++) {
+ NPVariant npvValue;
+ _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
+ jchar cVal = 0;
+ if (NPVARIANT_IS_INT32(npvValue)) {
+ cVal = static_cast<jchar>(NPVARIANT_TO_INT32(npvValue));
+ } else if (NPVARIANT_IS_STRING(npvValue)) {
+ NPString str = NPVARIANT_TO_STRING(npvValue);
+ cVal = str.UTF8Characters[0];
+ }
+ env->SetCharArrayRegion(static_cast<jcharArray>(javaArray), i, 1, &cVal);
+ }
+ } else if (!strcmp(javaClassName, "[D")) {
+ // array of doubles
+ javaArray = env->NewDoubleArray(length);
+ // Now iterate over each element and add to the array.
+ for (jsize i = 0; i < length; i++) {
+ NPVariant npvValue;
+ _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
+ if (NPVARIANT_IS_DOUBLE(npvValue)) {
+ jdouble dVal = NPVARIANT_TO_DOUBLE(npvValue);
+ env->SetDoubleArrayRegion(static_cast<jdoubleArray>(javaArray), i, 1, &dVal);
+ }
+ }
+ } else if (!strcmp(javaClassName, "[F")) {
+ // array of floats
+ javaArray = env->NewFloatArray(length);
+ // Now iterate over each element and add to the array.
+ for (jsize i = 0; i < length; i++) {
+ NPVariant npvValue;
+ _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
+ if (NPVARIANT_IS_DOUBLE(npvValue)) {
+ jfloat fVal = static_cast<jfloat>(NPVARIANT_TO_DOUBLE(npvValue));
+ env->SetFloatArrayRegion(static_cast<jfloatArray>(javaArray), i, 1, &fVal);
+ }
+ }
+ } else if (!strcmp(javaClassName, "[I")) {
+ // array of ints
+ javaArray = env->NewIntArray(length);
+ // Now iterate over each element and add to the array.
+ for (jsize i = 0; i < length; i++) {
+ NPVariant npvValue;
+ _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
+ if (NPVARIANT_IS_INT32(npvValue)) {
+ jint iVal = NPVARIANT_TO_INT32(npvValue);
+ env->SetIntArrayRegion(static_cast<jintArray>(javaArray), i, 1, &iVal);
+ }
+ }
+ } else if (!strcmp(javaClassName, "[J")) {
+ // array of longs
+ javaArray = env->NewLongArray(length);
+ // Now iterate over each element and add to the array.
+ for (jsize i = 0; i < length; i++) {
+ NPVariant npvValue;
+ _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
+ if (NPVARIANT_IS_INT32(npvValue)) {
+ jlong jVal = static_cast<jlong>(NPVARIANT_TO_INT32(npvValue));
+ env->SetLongArrayRegion(static_cast<jlongArray>(javaArray), i, 1, &jVal);
+ }
+ }
+ } else if (!strcmp(javaClassName, "[S")) {
+ // array of shorts
+ javaArray = env->NewShortArray(length);
+ // Now iterate over each element and add to the array.
+ for (jsize i = 0; i < length; i++) {
+ NPVariant npvValue;
+ _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
+ if (NPVARIANT_IS_INT32(npvValue)) {
+ jshort sVal = static_cast<jshort>(NPVARIANT_TO_INT32(npvValue));
+ env->SetShortArrayRegion(static_cast<jshortArray>(javaArray), i, 1, &sVal);
+ }
+ }
+ } else if (!strcmp(javaClassName, "[Z")) {
+ // array of booleans
+ javaArray = env->NewBooleanArray(length);
+ // Now iterate over each element and add to the array.
+ for (jsize i = 0; i < length; i++) {
+ NPVariant npvValue;
+ _NPN_GetProperty(0, object, _NPN_GetIntIdentifier(i), &npvValue);
+ if (NPVARIANT_IS_BOOLEAN(npvValue)) {
+ jboolean zVal = NPVARIANT_TO_BOOLEAN(npvValue);
+ env->SetBooleanArrayRegion(static_cast<jbooleanArray>(javaArray), i, 1, &zVal);
+ }
+ }
+ } else {
+#ifdef EMULATE_JSC_BINDINGS
+ // JSC sends null for an array that is not an array of strings or basic types.
+ memset(&result, 0, sizeof(jvalue));
+ break;
+#else
+ // Sending NULL as JSC does seems dangerous. (Imagine the java method that asks
+ // for the length of the array it was passed). Here we send a 0 length array.
+ jclass objectClass = env->FindClass("java/lang/Object");
+ javaArray = env->NewObjectArray(0, objectClass, 0);
+ env->DeleteLocalRef(objectClass);
+#endif
+ }
+
+ result.l = javaArray;
+ }
+ break;
+
case object_type:
{
+ JNIEnv* env = getJNIEnv();
result.l = static_cast<jobject>(0);
+ jobject javaString;
// First see if we have a Java instance.
if (type == NPVariantType_Object) {
@@ -56,7 +216,6 @@ jvalue convertNPVariantToJValue(NPVariant value, JNIType jniType, const char* ja
if (!result.l && !strcmp(javaClassName, "java.lang.String")) {
#ifdef CONVERT_NULL_TO_EMPTY_STRING
if (type == NPVariantType_Null) {
- JNIEnv* env = getJNIEnv();
jchar buf[2];
jobject javaString = env->functions->NewString(env, buf, 0);
result.l = javaString;
@@ -66,10 +225,38 @@ jvalue convertNPVariantToJValue(NPVariant value, JNIType jniType, const char* ja
#endif
{
NPString src = NPVARIANT_TO_STRING(value);
- JNIEnv* env = getJNIEnv();
- jobject javaString = env->NewStringUTF(src.UTF8Characters);
+ javaString = env->NewStringUTF(src.UTF8Characters);
+ result.l = javaString;
+ } else if (type == NPVariantType_Int32) {
+ jint src = NPVARIANT_TO_INT32(value);
+ jclass integerClass = env->FindClass("java/lang/Integer");
+ jmethodID toString = env->GetStaticMethodID(integerClass, "toString", "(I)Ljava/lang/String;");
+ javaString = env->CallStaticObjectMethod(integerClass, toString, src);
+ result.l = javaString;
+ env->DeleteLocalRef(integerClass);
+ } else if (type == NPVariantType_Bool) {
+ jboolean src = NPVARIANT_TO_BOOLEAN(value);
+ jclass booleanClass = env->FindClass("java/lang/Boolean");
+ jmethodID toString = env->GetStaticMethodID(booleanClass, "toString", "(Z)Ljava/lang/String;");
+ javaString = env->CallStaticObjectMethod(booleanClass, toString, src);
+ result.l = javaString;
+ env->DeleteLocalRef(booleanClass);
+ } else if (type == NPVariantType_Double) {
+ jdouble src = NPVARIANT_TO_DOUBLE(value);
+ jclass doubleClass = env->FindClass("java/lang/Double");
+ jmethodID toString = env->GetStaticMethodID(doubleClass, "toString", "(D)Ljava/lang/String;");
+ javaString = env->CallStaticObjectMethod(doubleClass, toString, src);
result.l = javaString;
+ env->DeleteLocalRef(doubleClass);
}
+#ifdef EMULATE_JSC_BINDINGS
+ // For the undefined value, JSC sends the String "undefined". Feels to me like we
+ // should send null in this case.
+ else if (!NPVARIANT_IS_NULL(value)) {
+ javaString = env->NewStringUTF("undefined");
+ result.l = javaString;
+ }
+#endif
} else if (!result.l)
memset(&result, 0, sizeof(jvalue)); // Handle it the same as a void case
}
@@ -97,6 +284,15 @@ jvalue convertNPVariantToJValue(NPVariant value, JNIType jniType, const char* ja
{
if (type == NPVariantType_Int32)
result.c = static_cast<char>(NPVARIANT_TO_INT32(value));
+#ifndef EMULATE_JSC_BINDINGS
+ // There is no char type in JavaScript - just strings 1 character
+ // long. So just converting it to an int above doesn't work. Again,
+ // we emulate the behavior for now for maximum compatability.
+ else if (type == NPVariantType_String) {
+ NPString str = NPVARIANT_TO_STRING(value);
+ result.c = str.UTF8Characters[0];
+ }
+#endif
else
memset(&result, 0, sizeof(jvalue));
}
@@ -153,8 +349,6 @@ jvalue convertNPVariantToJValue(NPVariant value, JNIType jniType, const char* ja
}
break;
- break;
-
case invalid_type:
default:
case void_type:
@@ -206,7 +400,17 @@ void convertJValueToNPVariant(jvalue value, JNIType jniType, const char* javaTyp
case char_type:
{
- INT32_TO_NPVARIANT(value.c, *result);
+#ifndef EMULATE_JSC_BINDINGS
+ // There is no char type in JavaScript - just strings 1 character
+ // long. So just converting it to an int above doesn't work. Again,
+ // we emulate the behavior for now for maximum compatability.
+ if (!strcmp(javaTypeName, "char")) {
+ const char c = value.c;
+ const char* v = strndup(&c, 1);
+ STRINGZ_TO_NPVARIANT(v, *result);
+ } else
+#endif
+ INT32_TO_NPVARIANT(value.c, *result);
}
break;
diff --git a/WebCore/bridge/jni/v8/JNIUtilityPrivate.h b/WebCore/bridge/jni/v8/JNIUtilityPrivate.h
index 951c1e8..da7a24c 100644
--- a/WebCore/bridge/jni/v8/JNIUtilityPrivate.h
+++ b/WebCore/bridge/jni/v8/JNIUtilityPrivate.h
@@ -29,6 +29,12 @@
#include "JNIUtility.h"
#include "npruntime.h"
+// FIXME: While fully implementing the bindings I noticed some differences between what
+// I wrote and seemed intuitive and what JSC does. Need to verify if my intuition is wrong
+// or there are bugs in the JSC bindings. For now, this macro makes the V8 bindings do the
+// same as the JSC bindings.
+#define EMULATE_JSC_BINDINGS 1
+
namespace JSC {
namespace Bindings {
diff --git a/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp b/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp
index 54cb8d6..88e28d4 100644
--- a/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp
+++ b/WebCore/bridge/jni/v8/JavaNPObjectV8.cpp
@@ -155,11 +155,19 @@ bool JavaNPObjectGetProperty(NPObject* obj, NPIdentifier identifier, NPVariant*
if (!field)
return false;
+#ifdef EMULATE_JSC_BINDINGS
+ // JSC does not seem to support returning object properties so we emulate that
+ // behaviour here.
+ jvalue value;
+#else
+ // FIXME: Note here that field->type() refers to the Java class name and NOT the
+ // JNI signature i.e. "int" as opposed to "I". This means that the field lookup
+ // will fail.
jvalue value = getJNIField(instance->javaInstance(),
field->getJNIType(),
field->name().UTF8String(),
field->type());
-
+#endif
convertJValueToNPVariant(value, field->getJNIType(), field->type(), result);
return true;
diff --git a/WebCore/bridge/npapi.h b/WebCore/bridge/npapi.h
index 41f9bda..351b414 100644
--- a/WebCore/bridge/npapi.h
+++ b/WebCore/bridge/npapi.h
@@ -375,7 +375,12 @@ typedef enum {
#endif
#ifdef ANDROID
- // TODO(andreip): Remove?
+ /* Used when the plugin returns 0 from NPN_WriteReady and wishes the browser
+ * to wait a certain amount of millis before calling NPN_WriteReady again.
+ */
+ NPPDataDeliveryDelayMs = 100,
+
+ // TODO(reed): upstream
NPPFakeValueToForce32Bits = 0x7FFFFFFF
#endif
} NPPVariable;
diff --git a/WebCore/html/HTMLPlugInElement.cpp b/WebCore/html/HTMLPlugInElement.cpp
index dafa8fb..9319034 100644
--- a/WebCore/html/HTMLPlugInElement.cpp
+++ b/WebCore/html/HTMLPlugInElement.cpp
@@ -177,4 +177,11 @@ void HTMLPlugInElement::updateWidgetCallback(Node* n)
static_cast<HTMLPlugInElement*>(n)->updateWidget();
}
+#if PLATFORM(ANDROID)
+bool HTMLPlugInElement::supportsFocus() const
+{
+ return true;
+}
+#endif
+
}
diff --git a/WebCore/html/HTMLPlugInElement.h b/WebCore/html/HTMLPlugInElement.h
index 9d3dc6d..cf18e27 100644
--- a/WebCore/html/HTMLPlugInElement.h
+++ b/WebCore/html/HTMLPlugInElement.h
@@ -60,6 +60,12 @@ protected:
virtual bool mapToEntry(const QualifiedName& attrName, MappedAttributeEntry& result) const;
virtual void parseMappedAttribute(MappedAttribute*);
+#if PLATFORM(ANDROID)
+ // in Android, plugin has a focused mode where it accepts all the touch events.
+ // so need to claim that plugin element supports focus instead of using the default.
+ virtual bool supportsFocus() const;
+#endif
+
private:
virtual void defaultEventHandler(Event*);
diff --git a/WebCore/platform/android/GeolocationServiceAndroid.cpp b/WebCore/platform/android/GeolocationServiceAndroid.cpp
index 61043fb..7f7d58e 100644
--- a/WebCore/platform/android/GeolocationServiceAndroid.cpp
+++ b/WebCore/platform/android/GeolocationServiceAndroid.cpp
@@ -111,6 +111,9 @@ void GeolocationServiceAndroid::stopUpdating()
// new position from the system service when a request is first made.
m_lastPosition = 0;
m_lastError = 0;
+ // remove the pending timer
+ if (m_timer.isActive())
+ m_timer.stop();
}
void GeolocationServiceAndroid::suspend()
@@ -155,7 +158,7 @@ void GeolocationServiceAndroid::timerFired(Timer<GeolocationServiceAndroid>* tim
ASSERT(m_lastPosition || m_lastError);
if (m_lastPosition)
positionChanged();
- else
+ else if (m_lastError)
errorOccurred();
}
diff --git a/WebCore/platform/graphics/android/ImageSourceAndroid.cpp b/WebCore/platform/graphics/android/ImageSourceAndroid.cpp
index fa1794c..06455d2 100644
--- a/WebCore/platform/graphics/android/ImageSourceAndroid.cpp
+++ b/WebCore/platform/graphics/android/ImageSourceAndroid.cpp
@@ -215,8 +215,12 @@ void ImageSource::setURL(const String& url)
// we only animate small GIFs for now, to save memory
// also, we only support this in Japan, hence the Emoji check
static bool should_use_animated_gif(int width, int height) {
+#ifdef ANDROID_LARGE_MEMORY_DEVICE
+ return true;
+#else
return EmojiFont::IsAvailable() &&
width <= 32 && height <= 32;
+#endif
}
#endif
diff --git a/WebCore/platform/image-decoders/ImageDecoder.h b/WebCore/platform/image-decoders/ImageDecoder.h
index 3ca7abf..8d27072 100644
--- a/WebCore/platform/image-decoders/ImageDecoder.h
+++ b/WebCore/platform/image-decoders/ImageDecoder.h
@@ -39,6 +39,7 @@
#if PLATFORM(SKIA)
#include "NativeImageSkia.h"
+#include "SkColorPriv.h"
#elif PLATFORM(QT)
#include <QImage>
#endif
@@ -169,7 +170,11 @@ namespace WebCore {
g = static_cast<unsigned>(g * alphaPercent);
b = static_cast<unsigned>(b * alphaPercent);
}
+#if PLATFORM(ANDROID)
+ *dest = SkPackARGB32(a, r, g, b);
+#else
*dest = (a << 24 | r << 16 | g << 8 | b);
+#endif
}
}
diff --git a/WebCore/plugins/PluginStream.cpp b/WebCore/plugins/PluginStream.cpp
index 1e91c51..9341c15 100644
--- a/WebCore/plugins/PluginStream.cpp
+++ b/WebCore/plugins/PluginStream.cpp
@@ -349,8 +349,13 @@ void PluginStream::deliverData()
// TODO: This needs to be upstreamed.
if (m_loader)
m_loader->pauseLoad(true);
-#endif
+
+ // ask the plugin for a delay value.
+ int delay = deliveryDelay();
+ m_delayDeliveryTimer.startOneShot(delay * 0.001);
+#else
m_delayDeliveryTimer.startOneShot(0);
+#endif
break;
} else {
deliveryBytes = min(deliveryBytes, totalBytes - totalBytesDelivered);
@@ -436,6 +441,10 @@ void PluginStream::didReceiveData(NetscapePlugInStreamLoader* loader, const char
m_deliveryData->resize(oldSize + length);
memcpy(m_deliveryData->data() + oldSize, data, length);
+#if PLATFORM(ANDROID)
+//TODO: This needs to be upstreamed to WebKit.
+ if (!m_delayDeliveryTimer.isActive())
+#endif
deliverData();
}
@@ -485,4 +494,18 @@ bool PluginStream::wantsAllStreams() const
return result != 0;
}
+#if PLATFORM(ANDROID)
+int PluginStream::deliveryDelay() const
+{
+ if (!m_pluginFuncs->getvalue)
+ return 0;
+
+ int delay = 0;
+ if (m_pluginFuncs->getvalue(m_instance, NPPDataDeliveryDelayMs, &delay) != NPERR_NO_ERROR)
+ return 0;
+
+ return delay;
+}
+#endif
+
}
diff --git a/WebCore/plugins/PluginStream.h b/WebCore/plugins/PluginStream.h
index dc08f01..29a2644 100644
--- a/WebCore/plugins/PluginStream.h
+++ b/WebCore/plugins/PluginStream.h
@@ -88,7 +88,9 @@ namespace WebCore {
void deliverData();
void destroyStream(NPReason);
void destroyStream();
-
+#if PLATFORM(ANDROID)
+ int deliveryDelay() const;
+#endif
ResourceRequest m_resourceRequest;
ResourceResponse m_resourceResponse;
diff --git a/WebCore/plugins/PluginView.h b/WebCore/plugins/PluginView.h
index 41e563c..f14eb3d 100644
--- a/WebCore/plugins/PluginView.h
+++ b/WebCore/plugins/PluginView.h
@@ -410,6 +410,9 @@ private:
IntRect m_clipRect; // The clip rect to apply to a windowed plug-in
IntRect m_windowRect; // Our window rect.
+#ifdef ANDROID_PLUGINS
+ IntRect m_pageRect; // The rect in page coordinate system.
+#endif
bool m_loadManually;
RefPtr<PluginStream> m_manualStream;
diff --git a/WebCore/plugins/android/PluginViewAndroid.cpp b/WebCore/plugins/android/PluginViewAndroid.cpp
index 452c9fb..682268a 100644
--- a/WebCore/plugins/android/PluginViewAndroid.cpp
+++ b/WebCore/plugins/android/PluginViewAndroid.cpp
@@ -247,11 +247,9 @@ void PluginView::handleMouseEvent(MouseEvent* event)
evt.data.mouse.y = localPos.y();
if (isDown) {
- // The plugin needs focus to receive keyboard events
- if (Page* page = m_parentFrame->page()) {
- page->focusController()->setFocusedNode(m_element, m_parentFrame);
- event->setDefaultHandled();
- }
+ // The plugin needs focus to receive keyboard and touch events
+ m_element->focus();
+ event->setDefaultHandled();
}
}
else {
@@ -427,23 +425,17 @@ void PluginView::setNPWindowIfNeeded()
return;
// in Android, plugin always get the setwindow() in the page coordinate.
- IntRect pageRect = m_windowRect;
- ScrollView* top = parent();
- while (top->parent())
- top = top->parent();
- // only the top ScrollView can have the offset
- pageRect.move(top->scrollOffset());
// the m_npWindow is relative to the page
- m_npWindow.x = pageRect.x();
- m_npWindow.y = pageRect.y();
- m_npWindow.width = pageRect.width();
- m_npWindow.height = pageRect.height();
+ m_npWindow.x = m_pageRect.x();
+ m_npWindow.y = m_pageRect.y();
+ m_npWindow.width = m_pageRect.width();
+ m_npWindow.height = m_pageRect.height();
- m_npWindow.clipRect.left = pageRect.x();
- m_npWindow.clipRect.top = pageRect.y();
- m_npWindow.clipRect.right = pageRect.x() + pageRect.width();
- m_npWindow.clipRect.bottom = pageRect.y() + pageRect.height();
+ m_npWindow.clipRect.left = m_pageRect.x();
+ m_npWindow.clipRect.top = m_pageRect.y();
+ m_npWindow.clipRect.right = m_pageRect.x() + m_pageRect.width();
+ m_npWindow.clipRect.bottom = m_pageRect.y() + m_pageRect.height();
if (m_plugin->pluginFuncs()->setwindow) {
#if USE(JSC)
@@ -666,11 +658,18 @@ void PluginView::updatePluginWidget()
FrameView* frameView = static_cast<FrameView*>(parent());
PLUGIN_LOG("--%p UpdatePluginWidget frame=[%p] \n", instance(), frameView);
if (frameView) {
- IntRect oldWindowRect = m_windowRect;
-
m_windowRect = frameView->contentsToWindow(frameRect());
- if (m_windowRect != oldWindowRect)
+ IntRect oldPageRect = m_pageRect;
+
+ // only the top ScrollView can have the offset
+ m_pageRect = m_windowRect;
+ ScrollView* top = parent();
+ while (top->parent())
+ top = top->parent();
+ m_pageRect.move(top->scrollOffset());
+
+ if (m_pageRect != oldPageRect)
setNPWindowIfNeeded();
}
}
diff --git a/WebCore/rendering/RenderLayerCompositor.cpp b/WebCore/rendering/RenderLayerCompositor.cpp
index e8d476b..22118fe 100644
--- a/WebCore/rendering/RenderLayerCompositor.cpp
+++ b/WebCore/rendering/RenderLayerCompositor.cpp
@@ -982,14 +982,49 @@ bool RenderLayerCompositor::needsToBeComposited(const RenderLayer* layer) const
return requiresCompositingLayer(layer) || layer->mustOverlapCompositedLayers();
}
+#if PLATFORM(ANDROID)
+bool RenderLayerCompositor::requiresCompositingForMobileSites(const RenderLayer* layer) const
+{
+ // First, check if we are in an iframe, and if so bail out
+ if (m_renderView->document()->frame()->tree()->parent())
+ return false;
+
+ RenderObject* renderer = layer->renderer();
+ // Check for transforms
+ if (requiresCompositingForTransform(renderer))
+ return true;
+
+ // Check for animations
+ if (requiresCompositingForAnimation(renderer))
+ return true;
+
+#if ENABLE(COMPOSITED_FIXED_ELEMENTS)
+ // For the moment, we want to only enable fixed composited layers on mobile websites.
+ // We can consider a website as being a 'mobile' site if all the
+ // following checks are true:
+ // 1) - the viewport width is either undefined (-1) or equal to device-width (0), and
+ // 2) - no scaling is allowed
+ if (!layer->isFixed())
+ return false;
+
+ Settings* settings = m_renderView->document()->settings();
+ if (!settings)
+ return false;
+
+ if ((settings->viewportWidth() == -1 || settings->viewportWidth() == 0) &&
+ !settings->viewportUserScalable())
+ return true;
+#endif
+
+ return false;
+}
+#endif
+
// Note: this specifies whether the RL needs a compositing layer for intrinsic reasons.
// Use needsToBeComposited() to determine if a RL actually needs a compositing layer.
// static
bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) const
{
-#if ENABLE(COMPOSITED_FIXED_ELEMENTS)
- Settings* settings = m_renderView->document()->settings();
-#endif
RenderObject* renderer = layer->renderer();
// The compositing state of a reflection should match that of its reflected layer.
if (layer->isReflection()) {
@@ -998,25 +1033,17 @@ bool RenderLayerCompositor::requiresCompositingLayer(const RenderLayer* layer) c
}
// The root layer always has a compositing layer, but it may not have backing.
return (inCompositingMode() && layer->isRootLayer()) ||
- requiresCompositingForTransform(renderer) ||
#if PLATFORM(ANDROID)
-#if ENABLE(COMPOSITED_FIXED_ELEMENTS)
- // For the moment, we want to only enable fixed composited layers on mobile websites.
- // We can consider a website as being a 'mobile' site if all the
- // following checks are true:
- // 1) - the viewport width is either undefined (-1) or equal to device-width (0), and
- // 2) - no scaling is allowed
- (((settings->viewportWidth() == -1) || (settings->viewportWidth() == 0)) &&
- !settings->viewportUserScalable() && layer->isFixed()) ||
-#endif
+ requiresCompositingForMobileSites(layer) ||
#else
+ requiresCompositingForTransform(renderer) ||
requiresCompositingForVideo(renderer) ||
requiresCompositingForCanvas(renderer) ||
requiresCompositingForPlugin(renderer) ||
+ requiresCompositingForAnimation(renderer) ||
#endif
renderer->style()->backfaceVisibility() == BackfaceVisibilityHidden ||
- clipsCompositingDescendants(layer) ||
- requiresCompositingForAnimation(renderer);
+ clipsCompositingDescendants(layer);
}
// Return true if the given layer has some ancestor in the RenderLayer hierarchy that clips,
diff --git a/WebCore/rendering/RenderLayerCompositor.h b/WebCore/rendering/RenderLayerCompositor.h
index 5f1a178..eeacdf7 100644
--- a/WebCore/rendering/RenderLayerCompositor.h
+++ b/WebCore/rendering/RenderLayerCompositor.h
@@ -181,6 +181,11 @@ private:
bool requiresCompositingForPlugin(RenderObject*) const;
bool requiresCompositingWhenDescendantsAreCompositing(RenderObject*) const;
+#if PLATFORM(ANDROID)
+ // Whether we are on a mobile site
+ bool requiresCompositingForMobileSites(const RenderLayer* layer) const;
+#endif
+
private:
RenderView* m_renderView;
OwnPtr<GraphicsLayer> m_rootPlatformLayer;
diff --git a/WebCore/rendering/RenderView.h b/WebCore/rendering/RenderView.h
index c287579..faa2465 100644
--- a/WebCore/rendering/RenderView.h
+++ b/WebCore/rendering/RenderView.h
@@ -105,6 +105,9 @@ public:
void updateWidgetPositions();
void addWidget(RenderWidget*);
void removeWidget(RenderWidget*);
+#ifdef ANDROID_PLUGINS
+ const HashSet<RenderWidget*>& widgets() const { return m_widgets; }
+#endif
// layoutDelta is used transiently during layout to store how far an object has moved from its
// last layout location, in order to repaint correctly.