diff options
Diffstat (limited to 'WebCore/bridge')
-rw-r--r-- | WebCore/bridge/NP_jsobject.cpp | 70 | ||||
-rw-r--r-- | WebCore/bridge/jni/jsc/JavaStringJSC.h | 2 | ||||
-rw-r--r-- | WebCore/bridge/qt/qt_pixmapruntime.cpp | 199 | ||||
-rw-r--r-- | WebCore/bridge/qt/qt_runtime.cpp | 36 | ||||
-rw-r--r-- | WebCore/bridge/runtime_root.cpp | 12 | ||||
-rw-r--r-- | WebCore/bridge/runtime_root.h | 11 |
6 files changed, 228 insertions, 102 deletions
diff --git a/WebCore/bridge/NP_jsobject.cpp b/WebCore/bridge/NP_jsobject.cpp index 09851df..2b1d17f 100644 --- a/WebCore/bridge/NP_jsobject.cpp +++ b/WebCore/bridge/NP_jsobject.cpp @@ -51,6 +51,64 @@ using namespace JSC; using namespace JSC::Bindings; using namespace WebCore; +class ObjectMap { +public: + NPObject* get(RootObject* rootObject, JSObject* jsObject) + { + return m_map.get(rootObject).get(jsObject); + } + + void add(RootObject* rootObject, JSObject* jsObject, NPObject* npObject) + { + HashMap<RootObject*, JSToNPObjectMap>::iterator iter = m_map.find(rootObject); + if (iter == m_map.end()) { + rootObject->addInvalidationCallback(&m_invalidationCallback); + iter = m_map.add(rootObject, JSToNPObjectMap()).first; + } + + ASSERT(iter->second.find(jsObject) == iter->second.end()); + iter->second.add(jsObject, npObject); + } + + void remove(RootObject* rootObject) + { + HashMap<RootObject*, JSToNPObjectMap>::iterator iter = m_map.find(rootObject); + ASSERT(iter != m_map.end()); + m_map.remove(iter); + } + + void remove(RootObject* rootObject, JSObject* jsObject) + { + HashMap<RootObject*, JSToNPObjectMap>::iterator iter = m_map.find(rootObject); + ASSERT(iter != m_map.end()); + ASSERT(iter->second.find(jsObject) != iter->second.end()); + + iter->second.remove(jsObject); + } + +private: + struct RootObjectInvalidationCallback : public RootObject::InvalidationCallback { + virtual void operator()(RootObject*); + }; + RootObjectInvalidationCallback m_invalidationCallback; + + // JSObjects are protected by RootObject. + typedef HashMap<JSObject*, NPObject*> JSToNPObjectMap; + HashMap<RootObject*, JSToNPObjectMap> m_map; +}; + + +static ObjectMap& objectMap() +{ + DEFINE_STATIC_LOCAL(ObjectMap, map, ()); + return map; +} + +void ObjectMap::RootObjectInvalidationCallback::operator()(RootObject* rootObject) +{ + objectMap().remove(rootObject); +} + static void getListFromVariantArgs(ExecState* exec, const NPVariant* args, unsigned argCount, RootObject* rootObject, MarkedArgumentBuffer& aList) { for (unsigned i = 0; i < argCount; ++i) @@ -66,8 +124,10 @@ static void jsDeallocate(NPObject* npObj) { JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(npObj); - if (obj->rootObject && obj->rootObject->isValid()) + if (obj->rootObject && obj->rootObject->isValid()) { + objectMap().remove(obj->rootObject, obj->imp); obj->rootObject->gcUnprotect(obj->imp); + } if (obj->rootObject) obj->rootObject->deref(); @@ -83,12 +143,18 @@ static NPClass* NPNoScriptObjectClass = &noScriptClass; NPObject* _NPN_CreateScriptObject(NPP npp, JSObject* imp, PassRefPtr<RootObject> rootObject) { + if (NPObject* object = objectMap().get(rootObject.get(), imp)) + return _NPN_RetainObject(object); + JavaScriptObject* obj = reinterpret_cast<JavaScriptObject*>(_NPN_CreateObject(npp, NPScriptObjectClass)); obj->rootObject = rootObject.releaseRef(); - if (obj->rootObject) + if (obj->rootObject) { obj->rootObject->gcProtect(imp); + objectMap().add(obj->rootObject, imp, reinterpret_cast<NPObject*>(obj)); + } + obj->imp = imp; return reinterpret_cast<NPObject*>(obj); diff --git a/WebCore/bridge/jni/jsc/JavaStringJSC.h b/WebCore/bridge/jni/jsc/JavaStringJSC.h index 720f887..7c37f70 100644 --- a/WebCore/bridge/jni/jsc/JavaStringJSC.h +++ b/WebCore/bridge/jni/jsc/JavaStringJSC.h @@ -69,7 +69,7 @@ public: return m_utf8String.c_str(); } const jchar* uchars() const { return (const jchar*)m_rep->data(); } - int length() const { return m_rep->size(); } + int length() const { return m_rep->length(); } UString uString() const { return UString(m_rep); } private: diff --git a/WebCore/bridge/qt/qt_pixmapruntime.cpp b/WebCore/bridge/qt/qt_pixmapruntime.cpp index edae5a9..5978804 100644 --- a/WebCore/bridge/qt/qt_pixmapruntime.cpp +++ b/WebCore/bridge/qt/qt_pixmapruntime.cpp @@ -20,11 +20,7 @@ #include "qt_pixmapruntime.h" #include "CachedImage.h" -#include "DOMWindow.h" #include "HTMLImageElement.h" -#include "HTMLNames.h" -#include "JSDOMBinding.h" -#include "JSDOMWindow.h" #include "JSGlobalObject.h" #include "JSHTMLImageElement.h" #include "JSLock.h" @@ -54,18 +50,19 @@ public: class QtPixmapWidthField : public Field { public: static const char* name() { return "width"; } - virtual JSValue valueFromInstance(ExecState* exec, const Instance* pixmap) const + virtual JSValue valueFromInstance(ExecState* exec, const Instance* instance) const { - return jsNumber(exec, static_cast<const QtPixmapInstance*>(pixmap)->width()); + return jsNumber(exec, static_cast<const QtPixmapInstance*>(instance)->width()); } virtual void setValueToInstance(ExecState*, const Instance*, JSValue) const {} }; + class QtPixmapHeightField : public Field { public: static const char* name() { return "height"; } - virtual JSValue valueFromInstance(ExecState* exec, const Instance* inst) const + virtual JSValue valueFromInstance(ExecState* exec, const Instance* instance) const { - return jsNumber(exec, static_cast<const QtPixmapInstance*>(inst)->height()); + return jsNumber(exec, static_cast<const QtPixmapInstance*>(instance)->height()); } virtual void setValueToInstance(ExecState*, const Instance*, JSValue) const {} }; @@ -76,77 +73,68 @@ public: { return 0; } - virtual JSValue invoke(ExecState* exec, QVariant&, PassRefPtr<RootObject> root, QtPixmapInstance* inst) = 0; + virtual JSValue invoke(ExecState* exec, QtPixmapInstance*, const ArgList&) = 0; }; -class QtPixmapCreateElementMethod : public QtPixmapRuntimeMethod { +// this function receives an HTML image element as a parameter, makes it display the pixmap/image from Qt +class QtPixmapAssignToElementMethod : public QtPixmapRuntimeMethod { public: - static const char* name() { return "toHTMLImageElement"; } - JSValue invoke(ExecState* exec, QVariant& v, PassRefPtr<RootObject> root, QtPixmapInstance*) + static const char* name() { return "assignToHTMLImageElement"; } + JSValue invoke(ExecState* exec, QtPixmapInstance* instance, const ArgList& args) { - QPixmap pxm; - if (v.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>())) { - pxm = QPixmap::fromImage(v.value<QImage>()); - v = QVariant::fromValue<QPixmap>(pxm); - } else - pxm = v.value<QPixmap>(); - - Document* document = 0; - JSDOMGlobalObject* global = static_cast<JSDOMGlobalObject*>(root->globalObject()); - if (global) { - DOMWindow* dWindow = toDOMWindow(global); - if (dWindow) - document = dWindow->document(); - } - - if (document) { - PassRefPtr<StillImage> img = WebCore::StillImage::create(pxm); - RefPtr<HTMLImageElement> image = new HTMLImageElement(HTMLNames::imgTag, document); - image->setCachedImage(new CachedImage(img.get())); - toJS(exec, global, document); - return asObject(toJS(exec, global, image.release())); - } + if (!args.size()) + return jsUndefined(); + + JSObject* objectArg = args.at(0).toObject(exec); + if (!objectArg) + return jsUndefined(); + + if (!objectArg->inherits(&JSHTMLImageElement::s_info)) + return jsUndefined(); + + // we now know that we have a valid <img> element as the argument, we can attach the pixmap to it. + PassRefPtr<StillImage> stillImage = WebCore::StillImage::create(instance->toPixmap()); + HTMLImageElement* imageElement = static_cast<HTMLImageElement*>(static_cast<JSHTMLImageElement*>(objectArg)->impl()); + imageElement->setCachedImage(new CachedImage(stillImage.get())); + JSDOMGlobalObject* global = static_cast<JSDOMGlobalObject*>(instance->rootObject()->globalObject()); + toJS(exec, global, imageElement->document()); return jsUndefined(); } + virtual int numParameters() const + { + return 1; + } }; +// this function encodes the image to a dataUrl, to be used in background etc. Note: very slow. class QtPixmapToDataUrlMethod : public QtPixmapRuntimeMethod { public: static const char* name() { return "toDataUrl"; } - JSValue invoke(ExecState* exec, QVariant& v, PassRefPtr<RootObject> root, QtPixmapInstance*) + JSValue invoke(ExecState* exec, QtPixmapInstance* instance, const ArgList&) { - QImage image; - // for getting the data url, we always prefer the image. - if (v.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>())) { - image = v.value<QPixmap>().toImage(); - v = QVariant::fromValue<QImage>(image); - } else - image = v.value<QImage>(); - QByteArray ba; - QBuffer b(&ba); - image.save(&b, "PNG"); - const QString b64 = QString("data:image/png;base64,") + ba.toBase64(); - const UString ustring((UChar*)b64.utf16(), b64.length()); + QByteArray byteArray; + QBuffer buffer(&byteArray); + instance->toImage().save(&buffer, "PNG"); + const QString encodedString = QString("data:image/png;base64,") + byteArray.toBase64(); + const UString ustring((UChar*)encodedString.utf16(), encodedString.length()); return jsString(exec, ustring); } - }; class QtPixmapToStringMethod : public QtPixmapRuntimeMethod { public: static const char* name() { return "toString"; } - JSValue invoke(ExecState* exec, QVariant& v, PassRefPtr<RootObject> root, QtPixmapInstance* inst) + JSValue invoke(ExecState* exec, QtPixmapInstance* instance, const ArgList&) { - return inst->valueOf(exec); + return instance->valueOf(exec); } - }; struct QtPixmapMetaData { QtPixmapToDataUrlMethod toDataUrlMethod; - QtPixmapCreateElementMethod createElementMethod; + QtPixmapAssignToElementMethod assignToElementMethod; QtPixmapToStringMethod toStringMethod; QtPixmapHeightField heightField; QtPixmapWidthField widthField; @@ -179,7 +167,6 @@ QtPixmapRuntimeObjectImp::QtPixmapRuntimeObjectImp(ExecState* exec, PassRefPtr<I const ClassInfo QtPixmapRuntimeObjectImp::s_info = { "QtPixmapRuntimeObject", &RuntimeObjectImp::s_info, 0, 0 }; - QtPixmapClass::QtPixmapClass() { } @@ -193,8 +180,8 @@ Class* QtPixmapInstance::getClass() const JSValue QtPixmapInstance::invokeMethod(ExecState* exec, const MethodList& methods, const ArgList& args) { if (methods.size() == 1) { - QtPixmapRuntimeMethod* mtd = static_cast<QtPixmapRuntimeMethod*>(methods[0]); - return mtd->invoke(exec, data, rootObject(), this); + QtPixmapRuntimeMethod* method = static_cast<QtPixmapRuntimeMethod*>(methods[0]); + return method->invoke(exec, this, args); } return jsUndefined(); } @@ -204,8 +191,8 @@ MethodList QtPixmapClass::methodsNamed(const Identifier& identifier, Instance*) MethodList methods; if (identifier == QtPixmapToDataUrlMethod::name()) methods.append(&qt_pixmap_metaData.toDataUrlMethod); - else if (identifier == QtPixmapCreateElementMethod::name()) - methods.append(&qt_pixmap_metaData.createElementMethod); + else if (identifier == QtPixmapAssignToElementMethod::name()) + methods.append(&qt_pixmap_metaData.assignToElementMethod); else if (identifier == QtPixmapToStringMethod::name()) methods.append(&qt_pixmap_metaData.toStringMethod); return methods; @@ -223,7 +210,7 @@ Field* QtPixmapClass::fieldNamed(const Identifier& identifier, Instance*) const void QtPixmapInstance::getPropertyNames(ExecState*exec, PropertyNameArray& arr) { arr.add(Identifier(exec, UString(QtPixmapToDataUrlMethod::name()))); - arr.add(Identifier(exec, UString(QtPixmapCreateElementMethod::name()))); + arr.add(Identifier(exec, UString(QtPixmapAssignToElementMethod::name()))); arr.add(Identifier(exec, UString(QtPixmapToStringMethod::name()))); arr.add(Identifier(exec, UString(QtPixmapWidthField::name()))); arr.add(Identifier(exec, UString(QtPixmapHeightField::name()))); @@ -236,15 +223,17 @@ JSValue QtPixmapInstance::defaultValue(ExecState* exec, PreferredPrimitiveType p (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>()) && !(data.value<QImage>()).isNull()) || (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>()) && !data.value<QPixmap>().isNull())); } + if (ptype == PreferString) return valueOf(exec); + return jsUndefined(); } JSValue QtPixmapInstance::valueOf(ExecState* exec) const { - const QString toStr = QString("[Qt Native Pixmap %1,%2]").arg(width()).arg(height()); - UString ustring((UChar*)toStr.utf16(), toStr.length()); + const QString stringValue = QString("[Qt Native Pixmap %1,%2]").arg(width()).arg(height()); + UString ustring((UChar*)stringValue.utf16(), stringValue.length()); return jsString(exec, ustring); } @@ -275,62 +264,78 @@ QPixmap QtPixmapInstance::toPixmap() { if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>())) return data.value<QPixmap>(); + if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>())) { - const QPixmap pxm = QPixmap::fromImage(data.value<QImage>()); - data = QVariant::fromValue<QPixmap>(pxm); - return pxm; + const QPixmap pixmap = QPixmap::fromImage(data.value<QImage>()); + data = QVariant::fromValue<QPixmap>(pixmap); + return pixmap; } - return QPixmap(); + return QPixmap(); } QImage QtPixmapInstance::toImage() { if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QImage>())) return data.value<QImage>(); + if (data.type() == static_cast<QVariant::Type>(qMetaTypeId<QPixmap>())) { - const QImage img = data.value<QPixmap>().toImage(); - data = QVariant::fromValue<QImage>(img); - return img; + const QImage image = data.value<QPixmap>().toImage(); + data = QVariant::fromValue<QImage>(image); + return image; } + return QImage(); } QVariant QtPixmapInstance::variantFromObject(JSObject* object, QMetaType::Type hint) { - if (!object) { + if (!object) + goto returnEmptyVariant; + + if (object->inherits(&JSHTMLImageElement::s_info)) { + JSHTMLImageElement* elementJSWrapper = static_cast<JSHTMLImageElement*>(object); + HTMLImageElement* imageElement = static_cast<HTMLImageElement*>(elementJSWrapper->impl()); + + if (!imageElement) + goto returnEmptyVariant; + + CachedImage* cachedImage = imageElement->cachedImage(); + if (!cachedImage) + goto returnEmptyVariant; + + Image* image = cachedImage->image(); + if (!image) + goto returnEmptyVariant; + + QPixmap* pixmap = image->nativeImageForCurrentFrame(); + if (!pixmap) + goto returnEmptyVariant; + + return (hint == static_cast<QMetaType::Type>(qMetaTypeId<QPixmap>())) + ? QVariant::fromValue<QPixmap>(*pixmap) + : QVariant::fromValue<QImage>(pixmap->toImage()); + } + + if (object->inherits(&QtPixmapRuntimeObjectImp::s_info)) { + QtPixmapRuntimeObjectImp* imp = static_cast<QtPixmapRuntimeObjectImp*>(object); + QtPixmapInstance* instance = static_cast<QtPixmapInstance*>(imp->getInternalInstance()); + if (!instance) + goto returnEmptyVariant; + if (hint == qMetaTypeId<QPixmap>()) - return QVariant::fromValue<QPixmap>(QPixmap()); + return QVariant::fromValue<QPixmap>(instance->toPixmap()); + if (hint == qMetaTypeId<QImage>()) - return QVariant::fromValue<QImage>(QImage()); - } else if (object->inherits(&JSHTMLImageElement::s_info)) { - JSHTMLImageElement* el = static_cast<JSHTMLImageElement*>(object); - HTMLImageElement* imageElement = static_cast<HTMLImageElement*>(el->impl()); - if (imageElement) { - CachedImage* cImg = imageElement->cachedImage(); - if (cImg) { - Image* img = cImg->image(); - if (img) { - QPixmap* pxm = img->nativeImageForCurrentFrame(); - if (pxm) { - return (hint == static_cast<QMetaType::Type>(qMetaTypeId<QPixmap>())) - ? QVariant::fromValue<QPixmap>(*pxm) - : QVariant::fromValue<QImage>(pxm->toImage()); - } - } - } - } - } else if (object->inherits(&QtPixmapRuntimeObjectImp::s_info)) { - QtPixmapRuntimeObjectImp* imp = static_cast<QtPixmapRuntimeObjectImp*>(object); - QtPixmapInstance* inst = static_cast<QtPixmapInstance*>(imp->getInternalInstance()); - if (inst) { - if (hint == qMetaTypeId<QPixmap >()) - return QVariant::fromValue<QPixmap>(inst->toPixmap()); - if (hint == qMetaTypeId<QImage>()) - return QVariant::fromValue<QImage>(inst->toImage()); - } + return QVariant::fromValue<QImage>(instance->toImage()); } - return 0; + +returnEmptyVariant: + if (hint == qMetaTypeId<QPixmap>()) + return QVariant::fromValue<QPixmap>(QPixmap()); + if (hint == qMetaTypeId<QImage>()) + return QVariant::fromValue<QImage>(QImage()); + return QVariant(); } JSObject* QtPixmapInstance::createRuntimeObject(ExecState* exec, PassRefPtr<RootObject> root, const QVariant& data) { diff --git a/WebCore/bridge/qt/qt_runtime.cpp b/WebCore/bridge/qt/qt_runtime.cpp index 9601a4a..ada9f01 100644 --- a/WebCore/bridge/qt/qt_runtime.cpp +++ b/WebCore/bridge/qt/qt_runtime.cpp @@ -29,7 +29,10 @@ #include "JSArray.h" #include "JSByteArray.h" #include "JSDOMBinding.h" +#include "JSDOMWindow.h" +#include <JSFunction.h> #include "JSGlobalObject.h" +#include "JSHTMLElement.h" #include "JSLock.h" #include "JSObject.h" #include "ObjectPrototype.h" @@ -45,7 +48,7 @@ #include "qt_instance.h" #include "qt_pixmapruntime.h" #include "qvarlengtharray.h" -#include <JSFunction.h> +#include "qwebelement.h" #include <limits.h> #include <runtime/Error.h> #include <runtime_array.h> @@ -114,6 +117,21 @@ QDebug operator<<(QDebug dbg, const JSRealType &c) } #endif +// this is here as a proxy, so we'd have a class to friend in QWebElement, +// as getting/setting a WebCore in QWebElement is private +class QtWebElementRuntime { +public: + static QWebElement create(Element* element) + { + return QWebElement(element); + } + + static Element* get(const QWebElement& element) + { + return element.m_element; + } +}; + static JSRealType valueRealType(ExecState* exec, JSValue val) { if (val.isNumber()) @@ -722,6 +740,11 @@ QVariant convertValueToQVariant(ExecState* exec, JSValue value, QMetaType::Type break; } else if (QtPixmapInstance::canHandle(static_cast<QMetaType::Type>(hint))) { ret = QtPixmapInstance::variantFromObject(object, static_cast<QMetaType::Type>(hint)); + } else if (hint == (QMetaType::Type) qMetaTypeId<QWebElement>()) { + if (object && object->inherits(&JSHTMLElement::s_info)) + ret = QVariant::fromValue<QWebElement>(QtWebElementRuntime::create((static_cast<JSHTMLElement*>(object))->impl())); + else + ret = QVariant::fromValue<QWebElement>(QWebElement()); } else if (hint == (QMetaType::Type) qMetaTypeId<QVariant>()) { if (value.isUndefinedOrNull()) { if (distance) @@ -854,6 +877,17 @@ JSValue convertQVariantToValue(ExecState* exec, PassRefPtr<RootObject> root, con if (QtPixmapInstance::canHandle(static_cast<QMetaType::Type>(variant.type()))) return QtPixmapInstance::createRuntimeObject(exec, root, variant); + if (type == qMetaTypeId<QWebElement>()) { + if (!root->globalObject()->inherits(&JSDOMWindow::s_info)) + return jsUndefined(); + + Document* document = (static_cast<JSDOMWindow*>(root->globalObject()))->impl()->document(); + if (!document) + return jsUndefined(); + + return toJS(exec, toJSDOMGlobalObject(document, exec), QtWebElementRuntime::get(variant.value<QWebElement>())); + } + if (type == QMetaType::QVariantMap) { // create a new object, and stuff properties into it JSObject* ret = constructEmptyObject(exec); diff --git a/WebCore/bridge/runtime_root.cpp b/WebCore/bridge/runtime_root.cpp index 143c3ad..b179d56 100644 --- a/WebCore/bridge/runtime_root.cpp +++ b/WebCore/bridge/runtime_root.cpp @@ -71,6 +71,10 @@ RootObject* findRootObject(JSGlobalObject* globalObject) return 0; } +RootObject::InvalidationCallback::~InvalidationCallback() +{ +} + PassRefPtr<RootObject> RootObject::create(const void* nativeHandle, JSGlobalObject* globalObject) { return adoptRef(new RootObject(nativeHandle, globalObject)); @@ -109,6 +113,14 @@ void RootObject::invalidate() m_nativeHandle = 0; m_globalObject = 0; + { + HashSet<InvalidationCallback*>::iterator end = m_invalidationCallbacks.end(); + for (HashSet<InvalidationCallback*>::iterator iter = m_invalidationCallbacks.begin(); iter != end; ++iter) + (**iter)(this); + + m_invalidationCallbacks.clear(); + } + ProtectCountSet::iterator end = m_protectCountSet.end(); for (ProtectCountSet::iterator it = m_protectCountSet.begin(); it != end; ++it) JSC::gcUnprotect(it->first); diff --git a/WebCore/bridge/runtime_root.h b/WebCore/bridge/runtime_root.h index fdd73c4..a81afb8 100644 --- a/WebCore/bridge/runtime_root.h +++ b/WebCore/bridge/runtime_root.h @@ -72,6 +72,13 @@ public: void addRuntimeObject(RuntimeObjectImp*); void removeRuntimeObject(RuntimeObjectImp*); + + struct InvalidationCallback { + virtual void operator()(RootObject*) = 0; + virtual ~InvalidationCallback(); + }; + void addInvalidationCallback(InvalidationCallback* callback) { m_invalidationCallbacks.add(callback); } + private: RootObject(const void* nativeHandle, JSGlobalObject*); @@ -79,9 +86,11 @@ private: const void* m_nativeHandle; ProtectedPtr<JSGlobalObject> m_globalObject; - ProtectCountSet m_protectCountSet; + ProtectCountSet m_protectCountSet; HashSet<RuntimeObjectImp*> m_runtimeObjects; + + HashSet<InvalidationCallback*> m_invalidationCallbacks; }; } // namespace Bindings |