Quick hakcish port of the QtBrowserPlugin from QApplication -> KApplication
[plasmaplugin.git] / qtbrowserplugin / qtbrowserplugin.cpp
blob404dd7ff9156858cf79c5789224553fd42cb6e0c
1 /****************************************************************************
2 **
3 ** Copyright (C) 2003-2008 Trolltech ASA. All rights reserved.
4 **
5 ** This file is part of a Qt Solutions component.
6 **
7 ** This file may be used under the terms of the GNU General Public
8 ** License version 2.0 as published by the Free Software Foundation
9 ** and appearing in the file LICENSE.GPL included in the packaging of
10 ** this file. Please review the following information to ensure GNU
11 ** General Public Licensing requirements will be met:
12 ** http://www.trolltech.com/products/qt/opensource.html
14 ** If you are unsure which license is appropriate for your use, please
15 ** review the following information:
16 ** http://www.trolltech.com/products/qt/licensing.html or contact the
17 ** Trolltech sales department at sales@trolltech.com.
19 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
20 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 ****************************************************************************/
23 #include <QtGui>
24 #include <kapplication.h>
26 #include "qtnpapi.h"
28 #include "qtbrowserplugin.h"
29 #include "qtbrowserplugin_p.h"
31 #ifndef WINAPI
32 # ifdef Q_WS_WIN
33 # define WINAPI __stdcall
34 # else
35 # define WINAPI
36 # endif
37 #endif
39 #ifdef Q_WS_X11
40 # ifdef Bool
41 # undef Bool
42 # endif
45 static void debuginfo(const QString &str)
47 static bool inited = false;
48 QFile file("/tmp/qnsdebug.txt");
49 if (file.open(QFile::WriteOnly | QFile::Append)) {
50 if (!inited) {
51 file.write("\n\n*** New run started ***\n");
52 inited = true;
54 file.write(qtNPFactory()->pluginName().toLatin1() + ": " + str.toLatin1() + '\n');
55 file.close();
60 #endif
62 static QtNPFactory *qNP = 0;
63 static NPNetscapeFuncs *qNetscapeFuncs = 0;
65 // The single global plugin
66 QtNPFactory *qtNPFactory()
68 extern QtNPFactory *qtns_instantiate();
70 if (!qNP) {
71 qNP = qtns_instantiate();
74 return qNP;
77 // NPN functions, forwarding to function pointers provided by browser
78 void NPN_Version(int* plugin_major, int* plugin_minor, int* netscape_major, int* netscape_minor)
80 Q_ASSERT(qNetscapeFuncs);
81 *plugin_major = NP_VERSION_MAJOR;
82 *plugin_minor = NP_VERSION_MINOR;
83 *netscape_major = qNetscapeFuncs->version >> 8; // Major version is in high byte
84 *netscape_minor = qNetscapeFuncs->version & 0xFF; // Minor version is in low byte
87 #define NPN_Prolog(x) \
88 Q_ASSERT(qNetscapeFuncs); \
89 Q_ASSERT(qNetscapeFuncs->x); \
92 const char *NPN_UserAgent(NPP instance)
94 NPN_Prolog(uagent);
95 return FIND_FUNCTION_POINTER(NPN_UserAgentFP, qNetscapeFuncs->uagent)(instance);
98 void NPN_Status(NPP instance, const char* message)
100 NPN_Prolog(status);
101 FIND_FUNCTION_POINTER(NPN_StatusFP, qNetscapeFuncs->status)(instance, message);
104 NPError NPN_GetURL(NPP instance, const char* url, const char* window)
106 NPN_Prolog(geturl);
107 return FIND_FUNCTION_POINTER(NPN_GetURLFP, qNetscapeFuncs->geturl)(instance, url, window);
110 NPError NPN_GetURLNotify(NPP instance, const char* url, const char* window, void* notifyData)
112 if ((qNetscapeFuncs->version & 0xFF) < NPVERS_HAS_NOTIFICATION)
113 return NPERR_INCOMPATIBLE_VERSION_ERROR;
115 NPN_Prolog(geturlnotify);
116 return FIND_FUNCTION_POINTER(NPN_GetURLNotifyFP, qNetscapeFuncs->geturlnotify)(instance, url, window, notifyData);
119 NPError NPN_PostURLNotify(NPP instance, const char* url, const char* window, uint32 len, const char* buf, NPBool file, void* notifyData)
121 if ((qNetscapeFuncs->version & 0xFF) < NPVERS_HAS_NOTIFICATION)
122 return NPERR_INCOMPATIBLE_VERSION_ERROR;
124 NPN_Prolog(posturlnotify);
125 return FIND_FUNCTION_POINTER(NPN_PostURLNotifyFP, qNetscapeFuncs->posturlnotify)(instance, url, window, len, buf, file, notifyData);
128 void* NPN_MemAlloc(uint32 size)
130 NPN_Prolog(memalloc);
131 return FIND_FUNCTION_POINTER(NPN_MemAllocFP, qNetscapeFuncs->memalloc)(size);
134 void NPN_MemFree(void* ptr)
136 NPN_Prolog(memfree);
137 FIND_FUNCTION_POINTER(NPN_MemFreeFP, qNetscapeFuncs->memfree)(ptr);
140 uint32 NPN_MemFlush(uint32 size)
142 NPN_Prolog(memflush);
143 return FIND_FUNCTION_POINTER(NPN_MemFlushFP, qNetscapeFuncs->memflush)(size);
146 NPError NPN_GetValue(NPP instance, NPNVariable variable, void *ret_value)
148 NPN_Prolog(getvalue);
149 return FIND_FUNCTION_POINTER(NPN_GetValueFP, qNetscapeFuncs->getvalue)(instance, variable, ret_value);
152 NPError NPN_SetValue(NPP instance, NPPVariable variable, void *ret_value)
154 NPN_Prolog(setvalue);
155 return FIND_FUNCTION_POINTER(NPN_SetValueFP, qNetscapeFuncs->setvalue)(instance, variable, ret_value);
158 NPIdentifier NPN_GetStringIdentifier(const char* name)
160 NPN_Prolog(getstringidentifier);
161 return FIND_FUNCTION_POINTER(NPN_GetStringIdentifierFP, qNetscapeFuncs->getstringidentifier)(name);
164 void NPN_GetStringIdentifiers(const char** names, int32 nameCount, NPIdentifier* identifiers)
166 NPN_Prolog(getstringidentifiers);
167 FIND_FUNCTION_POINTER(NPN_GetStringIdentifiersFP, qNetscapeFuncs->getstringidentifiers)(names, nameCount, identifiers);
170 NPIdentifier NPN_GetIntIdentifier(int32 intid)
172 NPN_Prolog(getintidentifier);
173 return FIND_FUNCTION_POINTER(NPN_GetIntIdentifierFP, qNetscapeFuncs->getintidentifier)(intid);
176 bool NPN_IdentifierIsString(NPIdentifier identifier)
178 NPN_Prolog(identifierisstring);
179 return FIND_FUNCTION_POINTER(NPN_IdentifierIsStringFP, qNetscapeFuncs->identifierisstring)(identifier);
182 char* NPN_UTF8FromIdentifier(NPIdentifier identifier)
184 NPN_Prolog(utf8fromidentifier);
185 return FIND_FUNCTION_POINTER(NPN_UTF8FromIdentifierFP, qNetscapeFuncs->utf8fromidentifier)(identifier);
188 int32 NPN_IntFromIdentifier(NPIdentifier identifier)
190 NPN_Prolog(intfromidentifier);
191 return FIND_FUNCTION_POINTER(NPN_IntFromIdentifierFP, qNetscapeFuncs->intfromidentifier)(identifier);
194 NPObject* NPN_CreateObject(NPP npp, NPClass *aClass)
196 NPN_Prolog(createobject);
197 return FIND_FUNCTION_POINTER(NPN_CreateObjectFP, qNetscapeFuncs->createobject)(npp, aClass);
200 NPObject* NPN_RetainObject(NPObject *obj)
202 NPN_Prolog(retainobject);
203 return FIND_FUNCTION_POINTER(NPN_RetainObjectFP, qNetscapeFuncs->retainobject)(obj);
206 void NPN_ReleaseObject(NPObject *obj)
208 NPN_Prolog(releaseobject);
209 FIND_FUNCTION_POINTER(NPN_ReleaseObjectFP, qNetscapeFuncs->releaseobject)(obj);
212 // Scripting implementation (QObject calling JavaScript in browser) - we don't use those
213 bool NPN_Invoke(NPP npp, NPObject* obj, NPIdentifier methodName, const NPVariant *args, int32 argCount, NPVariant *result)
215 NPN_Prolog(invoke);
216 return FIND_FUNCTION_POINTER(NPN_InvokeFP, qNetscapeFuncs->invoke)(npp, obj, methodName, args, argCount, result);
219 bool NPN_InvokeDefault(NPP npp, NPObject* obj, const NPVariant *args, int32 argCount, NPVariant *result)
221 NPN_Prolog(invokedefault);
222 return FIND_FUNCTION_POINTER(NPN_InvokeDefaultFP, qNetscapeFuncs->invokedefault)(npp, obj, args, argCount, result);
225 bool NPN_Evaluate(NPP npp, NPObject *obj, NPString *script, NPVariant *result)
227 NPN_Prolog(evaluate);
228 return FIND_FUNCTION_POINTER(NPN_EvaluateFP, qNetscapeFuncs->evaluate)(npp, obj, script, result);
231 bool NPN_GetProperty(NPP npp, NPObject *obj, NPIdentifier propertyName, NPVariant *result)
233 NPN_Prolog(getproperty);
234 return FIND_FUNCTION_POINTER(NPN_GetPropertyFP, qNetscapeFuncs->getproperty)(npp, obj, propertyName, result);
237 bool NPN_SetProperty(NPP npp, NPObject *obj, NPIdentifier propertyName, const NPVariant *value)
239 NPN_Prolog(setproperty);
240 return FIND_FUNCTION_POINTER(NPN_SetPropertyFP, qNetscapeFuncs->setproperty)(npp, obj, propertyName, value);
243 bool NPN_RemoveProperty(NPP npp, NPObject *obj, NPIdentifier propertyName)
245 NPN_Prolog(removeproperty);
246 return FIND_FUNCTION_POINTER(NPN_RemovePropertyFP, qNetscapeFuncs->removeproperty)(npp, obj, propertyName);
249 bool NPN_HasProperty(NPP npp, NPObject *obj, NPIdentifier propertyName)
251 NPN_Prolog(hasproperty);
252 return FIND_FUNCTION_POINTER(NPN_HasPropertyFP, qNetscapeFuncs->hasproperty)(npp, obj, propertyName);
255 bool NPN_HasMethod(NPP npp, NPObject *obj, NPIdentifier methodName)
257 NPN_Prolog(hasmethod);
258 return FIND_FUNCTION_POINTER(NPN_HasMethodFP, qNetscapeFuncs->hasmethod)(npp, obj, methodName);
261 void NPN_ReleaseVariantValue(NPVariant *variant)
263 NPN_Prolog(releasevariantvalue);
264 FIND_FUNCTION_POINTER(NPN_ReleaseVariantValueFP, qNetscapeFuncs->releasevariantvalue)(variant);
267 void NPN_SetException(NPObject *obj, const char *message)
269 qDebug("NPN_SetException: %s", message);
270 NPN_Prolog(setexception);
271 FIND_FUNCTION_POINTER(NPN_SetExceptionFP, qNetscapeFuncs->setexception)(obj, message);
274 // Scripting implementation (JavaScript calling QObject)
275 #define NPClass_Prolog \
276 if (!npobj->_class) return false; \
277 if (!npobj->_class->qtnp) return false; \
278 QtNPInstance *This = npobj->_class->qtnp; \
279 if (!This->qt.object) return false; \
280 QObject *qobject = This->qt.object \
283 static NPObject *NPAllocate(NPP npp, NPClass *aClass)
285 Q_UNUSED(npp);
286 Q_UNUSED(aClass);
288 Q_ASSERT(false);
289 return 0;
292 static void NPDeallocate(NPObject *npobj)
294 Q_UNUSED(npobj);
296 Q_ASSERT(false);
297 return;
300 static void NPInvalidate(NPObject *npobj)
302 if (npobj)
303 delete npobj->_class;
304 npobj->_class = 0;
307 enum MetaOffset { MetaProperty, MetaMethod };
309 static int metaOffset(const QMetaObject *metaObject, MetaOffset offsetType)
311 int classInfoIndex = metaObject->indexOfClassInfo("ToSuperClass");
312 if (classInfoIndex == -1)
313 return 0;
314 QByteArray ToSuperClass = metaObject->classInfo(classInfoIndex).value();
315 int offset = offsetType == MetaProperty ? metaObject->propertyOffset()
316 : metaObject->methodOffset();
318 while (ToSuperClass != metaObject->className()) {
319 metaObject = metaObject->superClass();
320 if (!metaObject)
321 break;
322 offset -= offsetType == MetaProperty ? metaObject->propertyCount()
323 : metaObject->methodCount();
325 return offset;
328 static int publicMethodIndex(NPObject *npobj, const QByteArray &slotName, int argCount = -1)
330 NPClass_Prolog;
331 const QMetaObject *metaObject = qobject->metaObject();
332 for (int slotIndex = metaOffset(metaObject, MetaMethod); slotIndex < metaObject->methodCount(); ++slotIndex) {
333 const QMetaMethod slot = qobject->metaObject()->method(slotIndex);
334 if (slot.access() != QMetaMethod::Public || slot.methodType() == QMetaMethod::Signal)
335 continue;
336 QByteArray signature = slot.signature();
337 if (signature.left(signature.indexOf('(')) == slotName) {
338 if (argCount == -1 || slot.parameterTypes().count() == argCount)
339 return slotIndex;
342 return -1;
345 static bool NPClass_HasMethod(NPObject *npobj, NPIdentifier name)
347 NPClass_Prolog;
348 Q_UNUSED(qobject);
349 return publicMethodIndex(npobj, NPN_UTF8FromIdentifier(name)) != -1;
352 static bool NPClass_Invoke(NPObject *npobj, NPIdentifier name, const NPVariant *args, uint32 argCount, NPVariant *result)
354 NPClass_Prolog;
355 const QByteArray slotName = NPN_UTF8FromIdentifier(name);
356 int slotIndex = publicMethodIndex(npobj, slotName, static_cast<int>(argCount));
357 if (slotIndex == -1) {
358 NPN_SetException(npobj, QByteArray("No method '" + slotName + "' with " + QByteArray::number(argCount) + " parameters").constData());
359 return false;
362 const QMetaMethod slot = qobject->metaObject()->method(slotIndex);
363 QList<QByteArray> parameterTypes = slot.parameterTypes();
364 if (parameterTypes.count() != static_cast<int>(argCount)) {
365 NPN_SetException(npobj, QByteArray("Wrong parameter count for method " + slotName).constData());
366 return false;
369 QVariant returnVariant(QVariant::nameToType(slot.typeName()), (void*)0);
370 QVector<QVariant> variants(parameterTypes.count()); // keep data alive
371 QVector<const void*> metacallArgs(parameterTypes.count() + 1); // arguments for qt_metacall
372 metacallArgs[0] = returnVariant.data(); // args[0] == return value
374 for (int p = 0; p < parameterTypes.count(); ++p) {
375 QVariant::Type type = QVariant::nameToType(parameterTypes.at(p));
376 if (type == QVariant::Invalid && parameterTypes.at(p) != "QVariant") {
377 NPN_SetException(npobj, QString("Parameter %1 in method '%2' has invalid type")
378 .arg(p).arg(QString::fromUtf8(slotName)).toAscii().constData());
379 return false;
381 QVariant qvar = args[p];
382 if (type != QVariant::Invalid && !qvar.convert(type)) {
383 NPN_SetException(npobj, QString("Parameter %1 to method '%2' needs to be convertable to '%3'")
384 .arg(p).arg(QString::fromUtf8(slotName)).arg(QString::fromAscii(parameterTypes.at(p))).toAscii().constData());
385 return false;
388 variants[p] = qvar;
389 if (type == QVariant::Invalid)
390 metacallArgs[p + 1] = &variants.at(p);
391 else
392 metacallArgs[p + 1] = variants.at(p).constData(); // must not detach!
395 qobject->qt_metacall(QMetaObject::InvokeMetaMethod, slotIndex, const_cast<void**>(metacallArgs.data()));
396 if (returnVariant.isValid() && result)
397 *result = NPVariant::fromQVariant(This, returnVariant);
399 return true;
402 static bool NPClass_InvokeDefault(NPObject * /*npobj*/, const NPVariant * /*args*/, uint32 /*argCount*/, NPVariant * /*result*/)
404 return false;
407 static bool NPClass_HasProperty(NPObject *npobj, NPIdentifier name)
409 NPClass_Prolog;
410 const QByteArray qname = NPN_UTF8FromIdentifier(name);
411 const QMetaObject *metaObject = qobject->metaObject();
412 int propertyIndex = metaObject->indexOfProperty(qname);
413 if (propertyIndex == -1 || propertyIndex < metaOffset(metaObject, MetaProperty))
414 return false;
415 QMetaProperty property = qobject->metaObject()->property(propertyIndex);
416 if (!property.isScriptable())
417 return false;
419 return true;
422 static bool NPClass_GetProperty(NPObject *npobj, NPIdentifier name, NPVariant *result)
424 NPClass_Prolog;
425 const QByteArray qname = NPN_UTF8FromIdentifier(name);
426 QVariant qvar = qobject->property(qname);
427 if (!qvar.isValid()) {
428 NPN_SetException(npobj, QByteArray("Failed to get value for property " + qname).constData());
429 return false;
431 *result = NPVariant::fromQVariant(This, qvar);
432 return true;
435 static bool NPClass_SetProperty(NPObject *npobj, NPIdentifier name, const NPVariant *result)
437 NPClass_Prolog;
438 const QByteArray qname = NPN_UTF8FromIdentifier(name);
439 QVariant qvar = *result;
440 return qobject->setProperty(qname, qvar);
443 static bool NPClass_RemoveProperty(NPObject * /*npobj*/, NPIdentifier /*name*/)
445 return false;
448 NPClass::NPClass(QtNPInstance *This)
450 structVersion = NP_CLASS_STRUCT_VERSION;
451 allocate = 0;
452 deallocate = 0;
453 invalidate = NPInvalidate;
454 hasMethod = NPClass_HasMethod;
455 invoke = NPClass_Invoke;
456 invokeDefault = NPClass_InvokeDefault;
457 hasProperty = NPClass_HasProperty;
458 getProperty = NPClass_GetProperty;
459 setProperty = NPClass_SetProperty;
460 removeProperty = NPClass_RemoveProperty;
461 qtnp = This;
462 delete_qtnp = false;
465 NPClass::~NPClass()
467 if (delete_qtnp)
468 delete qtnp;
471 // Type conversions
472 NPString NPString::fromQString(const QString &qstr)
474 NPString npstring;
475 const QByteArray qutf8 = qstr.toUtf8();
477 npstring.utf8length = qutf8.length();
478 npstring.utf8characters = (char*)NPN_MemAlloc(npstring.utf8length);
479 memcpy((char*)npstring.utf8characters, qutf8.constData(), npstring.utf8length);
481 return npstring;
484 NPString::operator QString() const
486 return QString::fromUtf8(utf8characters, utf8length);
489 NPVariant NPVariant::fromQVariant(QtNPInstance *This, const QVariant &qvariant)
491 Q_ASSERT(This);
492 NPVariant npvar;
493 npvar.type = Null;
495 QVariant qvar(qvariant);
496 switch(qvariant.type()) {
497 case QVariant::Bool:
498 npvar.value.boolValue = qvar.toBool();
499 npvar.type = Boolean;
500 break;
501 case QVariant::Int:
502 npvar.value.intValue = qvar.toInt();
503 npvar.type = Int32;
504 break;
505 case QVariant::Double:
506 npvar.value.doubleValue = qvar.toDouble();
507 npvar.type = Double;
508 break;
509 case QVariant::UserType:
511 QByteArray userType = qvariant.typeName();
512 if (userType.endsWith('*')) {
513 QtNPInstance *that = new QtNPInstance;
514 that->npp = This->npp;
515 that->qt.object = *(QObject**)qvariant.constData();
516 NPClass *npclass = new NPClass(that);
517 npclass->delete_qtnp = true;
518 npvar.value.objectValue = NPN_CreateObject(This->npp, npclass);
519 npvar.type = Object;
522 break;
523 default: // including QVariant::String
524 if (!qvar.convert(QVariant::String))
525 break;
526 npvar.type = String;
527 npvar.value.stringValue = NPString::fromQString(qvar.toString());
528 break;
531 return npvar;
534 NPVariant::operator QVariant() const
536 switch(type) {
537 case Void:
538 case Null:
539 return QVariant();
540 case Object:
542 if (!value.objectValue || !value.objectValue->_class)
543 break;
544 NPClass *aClass = value.objectValue->_class;
545 // not one of ours?
546 if (aClass->invoke != NPClass_Invoke)
547 break;
548 // or just empty for some reason
549 QObject *qobject = aClass->qtnp->qt.object;
550 if (!qobject)
551 break;
552 QByteArray typeName = qobject->metaObject()->className();
553 int userType = QMetaType::type(typeName + "*");
554 if (userType == QVariant::Invalid)
555 break;
556 QVariant result(userType, &aClass->qtnp->qt.object);
557 // sanity check
558 Q_ASSERT(*(QObject**)result.constData() == aClass->qtnp->qt.object);
559 return result;
561 case Boolean:
562 return value.boolValue;
563 case Int32:
564 return value.intValue;
565 case Double:
566 return value.doubleValue;
567 case String:
568 return QString(value.stringValue);
569 default:
570 break;
572 return QVariant();
575 // Helper class for handling incoming data
576 class QtNPStream
578 public:
579 QtNPStream(NPP instance, NPStream *st);
580 virtual ~QtNPStream()
584 QString url() const;
585 bool finish(QtNPBindable *bindable);
587 QByteArray buffer;
588 QFile file;
589 QString mime;
591 NPError reason;
593 NPP npp;
594 NPStream* stream;
596 protected:
597 qint64 readData(char *, qint64);
598 qint64 writeData(const char *, qint64);
601 QtNPStream::QtNPStream(NPP instance, NPStream *st)
602 : reason(NPRES_DONE), npp(instance), stream(st)
607 Returns the URL from which the stream was created, or the empty string
608 for write-only streams.
610 QString QtNPStream::url() const
612 if (!stream)
613 return QString();
614 return QString::fromLocal8Bit(stream->url);
617 class ErrorBuffer : public QBuffer
619 friend class QtNPStream;
622 bool QtNPStream::finish(QtNPBindable *bindable)
624 if (!bindable)
625 return false;
627 bool res = false;
628 if (bindable) {
629 switch(reason) {
630 case NPRES_DONE:
631 // no data at all? url is probably local file (Opera)
632 if (buffer.isEmpty() && file.fileName().isEmpty()) {
633 QUrl u = QUrl::fromEncoded(stream->url);
634 QString lfn = u.toLocalFile();
635 if (lfn.startsWith("//localhost/"))
636 lfn = lfn.mid(12);
637 file.setFileName(lfn);
640 if (file.exists()) {
641 file.setObjectName(url());
642 res = bindable->readData(&file, mime);
643 } else {
644 QBuffer io(&buffer);
645 io.setObjectName(url());
646 res = bindable->readData(&io, mime);
648 break;
649 case NPRES_USER_BREAK:
651 ErrorBuffer empty;
652 empty.setObjectName(url());
653 empty.setErrorString("User cancelled operation."),
654 res = bindable->readData(&empty, mime);
656 break;
657 case NPRES_NETWORK_ERR:
659 ErrorBuffer empty;
660 empty.setObjectName(url());
661 empty.setErrorString("Network error during download."),
662 res = bindable->readData(&empty, mime);
664 break;
665 default:
666 break;
669 stream->pdata = 0;
670 delete this;
671 return res;
674 // Helper class for forwarding signal emissions to the respective JavaScript
675 class QtSignalForwarder : public QObject
677 public:
678 QtSignalForwarder(QtNPInstance *that)
679 : This(that), domNode(0)
683 ~QtSignalForwarder()
685 if (domNode)
686 NPN_ReleaseObject(domNode);
689 int qt_metacall(QMetaObject::Call call, int index, void **args);
691 private:
692 QtNPInstance *This;
693 NPObject *domNode;
696 int QtSignalForwarder::qt_metacall(QMetaObject::Call call, int index, void **args)
698 // no support for QObject method/properties etc!
699 if (!This || !This->npp || call != QMetaObject::InvokeMetaMethod
700 || !This->qt.object)
701 return index;
703 switch (index) {
704 case -1:
706 QString msg = *(QString*)args[1];
707 NPN_Status(This->npp, msg.toLocal8Bit().constData());
709 break;
710 default:
712 QObject *qobject = This->qt.object;
713 if (!domNode)
714 NPN_GetValue(This->npp, NPNVPluginElementNPObject, &domNode);
715 if (!domNode)
716 break;
717 const QMetaObject *metaObject = qobject->metaObject();
718 if (index < metaOffset(metaObject, MetaMethod))
719 break;
721 const QMetaMethod method = metaObject->method(index);
722 Q_ASSERT(method.methodType() == QMetaMethod::Signal);
724 QByteArray signalSignature = method.signature();
725 QByteArray scriptFunction = signalSignature.left(signalSignature.indexOf('('));
726 NPIdentifier id = NPN_GetStringIdentifier(scriptFunction.constData());
727 if (NPN_HasMethod(This->npp, domNode, id)) {
728 QList<QByteArray> parameterTypes = method.parameterTypes();
729 QVector<NPVariant> parameters;
730 NPVariant result;
731 bool error = false;
732 for (int p = 0; p < parameterTypes.count(); ++p) {
733 QVariant::Type type = QVariant::nameToType(parameterTypes.at(p));
734 if (type == QVariant::Invalid) {
735 NPN_SetException(domNode, QByteArray("Unsupported parameter type in ") + scriptFunction);
736 error = true;
737 break;
739 QVariant qvar(type, args[p + 1]);
740 NPVariant npvar = NPVariant::fromQVariant(This, qvar);
741 if (npvar.type == NPVariant::Null || npvar.type == NPVariant::Void) {
742 NPN_SetException(domNode, QByteArray("Unsupported parameter value in ") + scriptFunction);
743 error =true;
744 break;
746 parameters += npvar;
748 if (error)
749 break;
751 NPError nperror = NPN_Invoke(This->npp, domNode, id, parameters.constData(), parameters.count(), &result);
752 if (nperror != NPERR_NO_ERROR && false) { // disabled, as NPN_Invoke seems to always return GENERICERROR
753 NPN_SetException(domNode, QByteArray("Error invoking event handler ") + scriptFunction);
755 // ### TODO: update return value (args[0]) (out-parameters not supported anyway)
756 NPN_ReleaseVariantValue(&result);
759 break;
762 return index;
766 // Plugin functions
767 extern "C" NPError
768 NPP_GetValue(NPP instance, NPPVariable variable, void *value)
770 if (!instance || !instance->pdata)
771 return NPERR_INVALID_INSTANCE_ERROR;
773 QtNPInstance* This = (QtNPInstance*) instance->pdata;
775 switch (variable) {
776 case NPPVpluginNameString:
778 static QByteArray name = qtNPFactory()->pluginName().toLocal8Bit();
779 *(const char**)value = name.constData();
781 break;
782 case NPPVpluginDescriptionString:
784 static QByteArray description = qtNPFactory()->pluginDescription().toLocal8Bit();
785 *(const char**)value = description.constData();
787 break;
789 #ifdef Q_WS_X11
790 case NPPVpluginNeedsXEmbed:
791 *(int*)value = true; // PRBool = int
792 break;
793 #endif
795 case NPPVpluginScriptableNPObject:
797 NPObject *object = NPN_CreateObject(instance, new NPClass(This));
798 *(NPObject**)value = object;
800 break;
801 case NPPVformValue:
803 QObject *object = This->qt.object;
804 const QMetaObject *metaObject = object->metaObject();
805 int defaultIndex = metaObject->indexOfClassInfo("DefaultProperty");
806 if (defaultIndex == -1)
807 return NPERR_GENERIC_ERROR;
808 QByteArray defaultProperty = metaObject->classInfo(defaultIndex).value();
809 if (defaultProperty.isEmpty())
810 return NPERR_GENERIC_ERROR;
811 QVariant defaultValue = object->property(defaultProperty);
812 if (!defaultValue.isValid())
813 return NPERR_GENERIC_ERROR;
814 defaultProperty = defaultValue.toString().toUtf8();
815 int size = defaultProperty.size();
816 char *utf8 = (char*)NPN_MemAlloc(size + 1);
817 memcpy(utf8, defaultProperty.constData(), size);
818 utf8[size] = 0; // null-terminator
819 *(void**)value = utf8;
821 break;
822 default:
823 return NPERR_GENERIC_ERROR;
826 return NPERR_NO_ERROR;
829 extern "C" NPError
830 NPP_SetValue(NPP instance, NPPVariable variable, void *value)
832 Q_UNUSED(variable);
833 Q_UNUSED(value);
835 if (!instance || !instance->pdata)
836 return NPERR_INVALID_INSTANCE_ERROR;
839 switch(variable) {
840 default:
841 return NPERR_GENERIC_ERROR;
844 return NPERR_NO_ERROR;
847 extern "C" int16 NPP_Event(NPP instance, NPEvent* event)
849 if (!instance || !instance->pdata)
850 return NPERR_INVALID_INSTANCE_ERROR;
852 QtNPInstance* This = (QtNPInstance*) instance->pdata;
853 extern bool qtns_event(QtNPInstance *, NPEvent *);
854 return qtns_event(This, event) ? 1 : 0;
857 #ifdef Q_WS_X11
858 // Instance state information about the plugin.
859 extern "C" char*
860 NP_GetMIMEDescription(void)
862 static QByteArray mime = qtNPFactory()->mimeTypes().join(";").toLocal8Bit();
863 return (char*)mime.constData();
866 extern "C" NPError
867 NP_GetValue(void*, NPPVariable aVariable, void *aValue)
869 NPError err = NPERR_NO_ERROR;
871 static QByteArray name = qtNPFactory()->pluginName().toLocal8Bit();
872 static QByteArray descr = qtNPFactory()->pluginDescription().toLocal8Bit();
874 switch (aVariable) {
875 case NPPVpluginNameString:
876 *static_cast<const char **> (aValue) = name.constData();
877 break;
878 case NPPVpluginDescriptionString:
879 *static_cast<const char **>(aValue) = descr.constData();
880 break;
881 case NPPVpluginNeedsXEmbed:
882 *static_cast<int*>(aValue) = true;
883 break;
884 case NPPVpluginTimerInterval:
885 case NPPVpluginKeepLibraryInMemory:
886 default:
887 err = NPERR_INVALID_PARAM;
888 break;
890 return err;
892 #endif
895 ** NPP_New is called when your plugin is instantiated (i.e. when an EMBED
896 ** tag appears on a page).
898 extern "C" NPError
899 NPP_New(NPMIMEType pluginType,
900 NPP instance,
901 uint16 mode,
902 int16 argc,
903 char* argn[],
904 char* argv[],
905 NPSavedData* /*saved*/)
907 if (!instance)
908 return NPERR_INVALID_INSTANCE_ERROR;
910 QtNPInstance* This = new QtNPInstance;
911 if (!This)
912 return NPERR_OUT_OF_MEMORY_ERROR;
914 instance->pdata = This;
915 This->filter = 0;
916 This->bindable = 0;
917 This->npp = instance;
918 This->fMode = mode; // NP_EMBED, NP_FULL, or NP_BACKGROUND (see npapi.h)
919 This->window = 0;
920 This->qt.object = 0;
921 #ifdef Q_WS_MAC
922 This->rootWidget = 0;
923 #endif
924 This->pendingStream = 0; // stream might be created before instance
925 This->mimetype = QString::fromLatin1(pluginType);
926 This->notificationSeqNum = 0;
928 for (int i = 0; i < argc; i++) {
929 QByteArray name = QByteArray(argn[i]).toLower();
930 if (name == "id")
931 This->htmlID = argv[i];
932 This->parameters[name] = QVariant(argv[i]);
935 return NPERR_NO_ERROR;
938 extern "C" NPError
939 NPP_Destroy(NPP instance, NPSavedData** /*save*/)
941 if (!instance || !instance->pdata)
942 return NPERR_INVALID_INSTANCE_ERROR;
944 QtNPInstance* This = (QtNPInstance*) instance->pdata;
946 #ifdef Q_WS_X11
947 //This->widget->destroy(false, false); // X has destroyed all windows
948 #endif
949 delete This->qt.object;
950 This->qt.object = 0;
951 delete This->filter;
952 This->filter = 0;
953 extern void qtns_destroy(QtNPInstance *This);
954 qtns_destroy(This);
955 delete This;
956 instance->pdata = 0;
958 return NPERR_NO_ERROR;
961 static QtNPInstance *next_pi = 0; // helper to connect to QtNPBindable
963 extern "C" NPError
964 NPP_SetWindow(NPP instance, NPWindow* window)
966 if (!instance)
967 return NPERR_INVALID_INSTANCE_ERROR;
969 QtNPInstance* This = (QtNPInstance*) instance->pdata;
970 extern void qtns_setGeometry(QtNPInstance*, const QRect &, const QRect &);
972 const QRect clipRect(window->clipRect.left, window->clipRect.top,
973 window->clipRect.right - window->clipRect.left,
974 window->clipRect.bottom - window->clipRect.top);
975 if (window)
976 This->geometry = QRect(window->x, window->y, window->width, window->height);
978 // take a shortcut if all that was changed is the geometry
979 if (qobject_cast<QWidget*>(This->qt.object) && window && This->window == (QtNPInstance::Widget)window->window) {
980 qtns_setGeometry(This, This->geometry, clipRect);
981 return NPERR_NO_ERROR;
984 delete This->qt.object;
985 This->qt.object = 0;
986 extern void qtns_destroy(QtNPInstance *This);
987 qtns_destroy(This);
989 if (!window) {
990 This->window = 0;
991 return NPERR_NO_ERROR;
994 This->window = (QtNPInstance::Widget)window->window;
995 #ifdef Q_WS_X11
996 //This->display = ((NPSetWindowCallbackStruct *)window->ws_info)->display;
997 #endif
999 extern void qtns_initialize(QtNPInstance*);
1000 qtns_initialize(This);
1002 next_pi = This;
1003 This->qt.object = qtNPFactory()->createObject(This->mimetype);
1004 next_pi = 0;
1006 if (!This->qt.object)
1007 return NPERR_NO_ERROR;
1009 if (!This->htmlID.isEmpty())
1010 This->qt.object->setObjectName(QLatin1String(This->htmlID));
1012 This->filter = new QtSignalForwarder(This);
1013 QStatusBar *statusbar = qFindChild<QStatusBar*>(This->qt.object);
1014 if (statusbar) {
1015 int statusSignal = statusbar->metaObject()->indexOfSignal("messageChanged(QString)");
1016 if (statusSignal != -1) {
1017 QMetaObject::connect(statusbar, statusSignal, This->filter, -1);
1018 statusbar->hide();
1022 const QMetaObject *mo = This->qt.object->metaObject();
1023 for (int p = 0; p < mo->propertyCount(); ++p) {
1024 const QMetaProperty property = mo->property(p);
1025 QByteArray name(property.name());
1026 QVariant value = This->parameters.value(name.toLower());
1027 if (value.isValid())
1028 property.write(This->qt.object, value);
1030 for (int methodIndex = 0; methodIndex < mo->methodCount(); ++methodIndex) {
1031 const QMetaMethod method = mo->method(methodIndex);
1032 if (method.methodType() == QMetaMethod::Signal)
1033 QMetaObject::connect(This->qt.object, methodIndex, This->filter, methodIndex);
1036 if (This->pendingStream) {
1037 This->pendingStream->finish(This->bindable);
1038 This->pendingStream = 0;
1041 if (!qobject_cast<QWidget*>(This->qt.object))
1042 return NPERR_NO_ERROR;
1044 extern void qtns_embed(QtNPInstance*);
1045 qtns_embed(This);
1047 QEvent e(QEvent::EmbeddingControl);
1048 KApplication::sendEvent(This->qt.widget, &e);
1050 if (!This->qt.widget->testAttribute(Qt::WA_PaintOnScreen))
1051 This->qt.widget->setAutoFillBackground(true);
1052 This->qt.widget->raise();
1053 qtns_setGeometry(This, This->geometry, clipRect);
1054 This->qt.widget->show();
1056 return NPERR_NO_ERROR;
1059 extern "C" NPError
1060 NPP_NewStream(NPP instance,
1061 NPMIMEType type,
1062 NPStream *stream,
1063 NPBool /*seekable*/,
1064 uint16 *stype)
1066 if (!instance)
1067 return NPERR_INVALID_INSTANCE_ERROR;
1069 QtNPInstance* This = (QtNPInstance*) instance->pdata;
1070 if (!This)
1071 return NPERR_NO_ERROR;
1073 QtNPStream *qstream = new QtNPStream(instance, stream);
1074 qstream->mime = QString::fromLocal8Bit(type);
1075 stream->pdata = qstream;
1077 *stype = NP_ASFILEONLY;
1079 return NPERR_NO_ERROR;
1082 extern "C" int32
1083 NPP_WriteReady(NPP, NPStream *stream)
1085 if (stream->pdata)
1086 return 0x0FFFFFFF;
1087 return 0;
1090 // Both Netscape and FireFox call this for OnDemand streams as well...
1091 extern "C" int32
1092 NPP_Write(NPP instance, NPStream *stream, int32 /*offset*/, int32 len, void *buffer)
1094 if (!instance || !stream || !stream->pdata)
1095 return NPERR_INVALID_INSTANCE_ERROR;
1097 // this should not be called, as we always demand a download
1098 QtNPStream *qstream = (QtNPStream*)stream->pdata;
1099 QByteArray data((const char*)buffer, len); // make deep copy
1100 qstream->buffer += data;
1102 return len;
1105 // Opera calls this for OnDemand streams without calling NPP_Write first
1106 extern "C" NPError
1107 NPP_DestroyStream(NPP instance, NPStream *stream, NPError reason)
1109 if (!instance || !instance->pdata || !stream || !stream->pdata)
1110 return NPERR_INVALID_INSTANCE_ERROR;
1112 QtNPInstance *This = (QtNPInstance*)instance->pdata;
1113 QtNPStream *qstream = (QtNPStream*)stream->pdata;
1114 qstream->reason = reason;
1116 if (!This->qt.object) { // not yet initialized
1117 This->pendingStream = qstream;
1118 return NPERR_NO_ERROR;
1121 This->pendingStream = 0;
1122 qstream->finish(This->bindable);
1124 return NPERR_NO_ERROR;
1127 extern "C" void
1128 NPP_StreamAsFile(NPP instance, NPStream *stream, const char* fname)
1130 if (!instance || !stream || !stream->pdata)
1131 return;
1133 QString path = QString::fromLocal8Bit(fname);
1134 #ifdef Q_WS_MAC
1135 path = "/" + path.section(':', 1).replace(':', '/');
1136 #endif
1138 QtNPStream *qstream = (QtNPStream*)stream->pdata;
1139 qstream->file.setFileName(path);
1142 extern "C" void
1143 NPP_URLNotify(NPP instance,
1144 const char* url,
1145 NPReason reason,
1146 void* notifyData)
1148 if (!instance)
1149 return;
1150 QtNPInstance* This = (QtNPInstance*) instance->pdata;
1151 if (!This->bindable)
1152 return;
1154 QtNPBindable::Reason r;
1155 switch (reason) {
1156 case NPRES_DONE:
1157 r = QtNPBindable::ReasonDone;
1158 break;
1159 case NPRES_USER_BREAK:
1160 r = QtNPBindable::ReasonBreak;
1161 break;
1162 case NPRES_NETWORK_ERR:
1163 r = QtNPBindable::ReasonError;
1164 break;
1165 default:
1166 r = QtNPBindable::ReasonUnknown;
1167 break;
1170 qint32 id = static_cast<qint32>(reinterpret_cast<size_t>(notifyData));
1171 if (id < 0) // Sanity check
1172 id = 0;
1174 This->bindable->transferComplete(QString::fromLocal8Bit(url), id, r);
1177 extern "C" void
1178 NPP_Print(NPP instance, NPPrint* printInfo)
1180 if(!printInfo || !instance)
1181 return;
1183 QtNPInstance* This = (QtNPInstance*) instance->pdata;
1184 if (!This->bindable)
1185 return;
1188 if (printInfo->mode == NP_FULL) {
1189 printInfo->print.fullPrint.pluginPrinted = This->bindable->printFullPage();
1190 } else if (printInfo->mode == NP_EMBED) {
1191 extern void qtns_print(QtNPInstance*, NPPrint*);
1192 qtns_print(This, printInfo);
1197 // Plug-in entrypoints - these are called by the browser
1199 // Fills in functiontable used by browser to call entry points in plugin.
1200 extern "C" NPError WINAPI NP_GetEntryPoints(NPPluginFuncs* pFuncs)
1202 if(!pFuncs)
1203 return NPERR_INVALID_FUNCTABLE_ERROR;
1204 if(!pFuncs->size)
1205 pFuncs->size = sizeof(NPPluginFuncs);
1206 else if (pFuncs->size < sizeof(NPPluginFuncs))
1207 return NPERR_INVALID_FUNCTABLE_ERROR;
1209 pFuncs->version = (NP_VERSION_MAJOR << 8) | NP_VERSION_MINOR;
1210 pFuncs->newp = MAKE_FUNCTION_POINTER(NPP_New);
1211 pFuncs->destroy = MAKE_FUNCTION_POINTER(NPP_Destroy);
1212 pFuncs->setwindow = MAKE_FUNCTION_POINTER(NPP_SetWindow);
1213 pFuncs->newstream = MAKE_FUNCTION_POINTER(NPP_NewStream);
1214 pFuncs->destroystream = MAKE_FUNCTION_POINTER(NPP_DestroyStream);
1215 pFuncs->asfile = MAKE_FUNCTION_POINTER(NPP_StreamAsFile);
1216 pFuncs->writeready = MAKE_FUNCTION_POINTER(NPP_WriteReady);
1217 pFuncs->write = MAKE_FUNCTION_POINTER(NPP_Write);
1218 pFuncs->print = MAKE_FUNCTION_POINTER(NPP_Print);
1219 pFuncs->event = MAKE_FUNCTION_POINTER(NPP_Event);
1220 pFuncs->urlnotify = MAKE_FUNCTION_POINTER(NPP_URLNotify);
1221 pFuncs->javaClass = 0;
1222 pFuncs->getvalue = MAKE_FUNCTION_POINTER(NPP_GetValue);
1223 pFuncs->setvalue = MAKE_FUNCTION_POINTER(NPP_SetValue);
1224 return NPERR_NO_ERROR;
1227 enum NPNToolkitType
1229 NPNVGtk12 = 1,
1230 NPNVGtk2
1233 #ifndef Q_WS_X11
1234 extern "C" NPError WINAPI NP_Initialize(NPNetscapeFuncs* pFuncs)
1236 if(!pFuncs)
1237 return NPERR_INVALID_FUNCTABLE_ERROR;
1239 qNetscapeFuncs = pFuncs;
1240 int navMajorVers = qNetscapeFuncs->version >> 8;
1242 // if the plugin's major version is lower than the Navigator's,
1243 // then they are incompatible, and should return an error
1244 if(navMajorVers > NP_VERSION_MAJOR)
1245 return NPERR_INCOMPATIBLE_VERSION_ERROR;
1247 return NPERR_NO_ERROR;
1249 #else
1250 extern "C" NPError WINAPI NP_Initialize(NPNetscapeFuncs* nFuncs, NPPluginFuncs* pFuncs)
1252 if(!nFuncs)
1253 return NPERR_INVALID_FUNCTABLE_ERROR;
1255 qNetscapeFuncs = nFuncs;
1256 int navMajorVers = qNetscapeFuncs->version >> 8;
1258 // if the plugin's major version is lower than the Navigator's,
1259 // then they are incompatible, and should return an error
1260 if(navMajorVers > NP_VERSION_MAJOR)
1261 return NPERR_INCOMPATIBLE_VERSION_ERROR;
1263 // check if the Browser supports the XEmbed protocol
1264 int supportsXEmbed = 0;
1265 NPError err = NPN_GetValue(0, NPNVSupportsXEmbedBool, (void *)&supportsXEmbed);
1266 if (err != NPERR_NO_ERROR ||!supportsXEmbed)
1267 return NPERR_INCOMPATIBLE_VERSION_ERROR;
1269 return NP_GetEntryPoints(pFuncs);
1271 #endif
1273 extern "C" NPError WINAPI NP_Shutdown()
1275 delete qNP;
1276 qNP = 0;
1278 extern void qtns_shutdown();
1279 qtns_shutdown();
1281 qNetscapeFuncs = 0;
1282 return NPERR_NO_ERROR;
1287 \class QtNPBindable qtnetscape.h
1288 \brief The QtNPBindable class provides an interface between a widget and the web browser.
1290 Inherit your plugin widget class from both QWidget (or QObject) and QtNPBindable
1291 to be able to call the functions of this class, and to reimplement the virtual
1292 functions. The \l{moc}{meta-object compiler} requires you to inherit from the
1293 QObject subclass first.
1295 \code
1296 class PluginWidget : public QWidget, public QtNPBindable
1298 Q_OBJECT
1299 public:
1300 PluginWidget(QWidget *parent = 0)
1304 //...
1306 \endcode
1310 \enum QtNPBindable::DisplayMode
1312 \brief This enum specifies the different display modes of a plugin
1314 \value Embedded The plugin widget is embedded in a web page, usually
1315 with the <EMBED> or the <OBJECT> tag.
1316 \value Fullpage The plugin widget is the primary content of the web browser, which
1317 is usually the case when the web browser displays a file the plugin supports.
1321 \enum QtNPBindable::Reason
1323 \brief This enum specifies how an URL operation was completed
1325 \value ReasonDone
1326 \value ReasonBreak
1327 \value ReasonError
1328 \value ReasonUnknown
1332 Constructs a QtNPBindable object.
1334 This can only happen when the plugin object is created.
1336 QtNPBindable::QtNPBindable()
1337 : pi(next_pi)
1339 if (pi)
1340 pi->bindable = this;
1341 next_pi = 0;
1345 Destroys the object.
1347 This can only happen when the plugin object is destroyed.
1349 QtNPBindable::~QtNPBindable()
1354 Returns the parameters passed to the plugin instance.
1356 The framework sets the properties of the plugin to the corresponding
1357 parameters when the plugin object has been created, but you can
1358 use this function to process additional parameters.
1360 Note that the SGML specification does not permit multiple
1361 arguments with the same name.
1363 QMap<QByteArray, QVariant> QtNPBindable::parameters() const
1365 if (!pi)
1366 return QMap<QByteArray, QVariant>();
1367 return pi->parameters;
1371 Returns the user agent (browser name) containing this plugin.
1373 This is a wrapper around NPN_UserAgent.
1375 \sa getBrowserVersion()
1377 QString QtNPBindable::userAgent() const
1379 if (!pi)
1380 return QString();
1381 return QString::fromLocal8Bit(NPN_UserAgent(pi->npp));
1385 Extracts the version of the plugin API used by this plugin into \a major
1386 and \a minor.
1388 See http://devedge-temp.mozilla.org/library/manuals/2002/plugin/1.0/
1389 for an explanation of those values.
1391 \sa getBrowserVersion() userAgent()
1393 void QtNPBindable::getNppVersion(int *major, int *minor) const
1395 int dummy = 0;
1396 if (pi)
1397 NPN_Version(major, minor, &dummy, &dummy);
1401 Extracts the version of the browser into \a major and \a minor.
1403 See http://devedge-temp.mozilla.org/library/manuals/2002/plugin/1.0/
1404 for an explanation of those values.
1406 \sa getNppVersion() userAgent()
1408 void QtNPBindable::getBrowserVersion(int *major, int *minor) const
1410 int dummy = 0;
1411 if (pi)
1412 NPN_Version(&dummy, &dummy, major, minor);
1416 Returns the display mode of the plugin.
1418 QtNPBindable::DisplayMode QtNPBindable::displayMode() const
1420 if (!pi)
1421 return Embedded;
1422 return (QtNPBindable::DisplayMode)pi->fMode;
1426 Returns the mime type this plugin has been instantiated for.
1428 QString QtNPBindable::mimeType() const
1430 if (!pi)
1431 return QString();
1432 return pi->mimetype;
1436 Returns the browser's plugin instance associated with this plugin object.
1437 The instance is required to call functions in the Netscape Plugin API,
1438 i.e. NPN_GetJavaPeer().
1440 The instance returned is only valid as long as this object is.
1442 See http://devedge-temp.mozilla.org/library/manuals/2002/plugin/1.0/
1443 for documentation of the \c NPP type.
1445 NPP QtNPBindable::instance() const
1447 if (!pi)
1448 return 0;
1449 return pi->npp;
1453 Reimplement this function to read data from \a source provided with
1454 mime type \a format. The data is the one specified in the \c src or
1455 \c data attribute of the \c{<EMBED>} or \c{<OBJECT>} tag of in
1456 HTML page. This function is called once for every stream the browser
1457 creates for the plugin.
1459 Return true to indicate successfull processing of the data, otherwise
1460 return false. The default implementation does nothing and returns false.
1463 bool QtNPBindable::readData(QIODevice *source, const QString &format)
1465 Q_UNUSED(source);
1466 Q_UNUSED(format);
1467 return false;
1471 Requests that the \a url be retrieved and sent to the named \a window (or
1472 a new window if \a window is empty), and returns the ID of the request that is
1473 delivered to transferComplete() when the get-operation has finished. Returns 0 when
1474 the browser or the system doesn't support notification, or -1 when an error occured.
1476 \code
1477 void MyPlugin::aboutTrolltech()
1479 openUrl("http://www.trolltech.com");
1481 \endcode
1483 See Netscape's JavaScript documentation for an explanation of window names.
1485 \sa transferComplete() uploadData() uploadFile()
1487 int QtNPBindable::openUrl(const QString &url, const QString &window)
1489 if (!pi)
1490 return -1;
1491 QString wnd = window;
1492 if (wnd.isEmpty())
1493 wnd = "_blank";
1495 qint32 id = pi->getNotificationSeqNum();
1496 NPError err = NPN_GetURLNotify(pi->npp, url.toLocal8Bit().constData(), wnd.toLocal8Bit().constData(), reinterpret_cast<void*>(id));
1497 if (err != NPERR_NO_ERROR)
1498 id = -1;
1500 if (err == NPERR_INCOMPATIBLE_VERSION_ERROR) {
1501 err = NPN_GetURL(pi->npp, url.toLocal8Bit().constData(), wnd.toLocal8Bit().constData());
1502 if (NPERR_NO_ERROR == err)
1503 id = 0;
1504 else
1505 id = -1;
1507 return id;
1511 Posts \a data to \a url, and displays the result in \a window. Returns the ID of the request
1512 that is delivered to transferComplete() when the post-operation has finished. Returns 0 when
1513 the browser or the system doesn't support notification, or -1 when an error occured.
1515 \code
1516 void MyPlugin::sendMail()
1518 uploadData("mailto:fred@somewhere.com", QString(), "There is a new file for you!");
1520 \endcode
1522 See Netscape's JavaScript documentation for an explanation of window names.
1524 \sa transferComplete() openUrl() uploadFile()
1526 int QtNPBindable::uploadData(const QString &url, const QString &window, const QByteArray &data)
1528 if (!pi)
1529 return -1;
1531 int id = pi->getNotificationSeqNum();
1532 if (NPERR_NO_ERROR != NPN_PostURLNotify(pi->npp, url.toLocal8Bit().constData(), window.isEmpty() ? 0 : window.toLocal8Bit().constData(), data.size(), data.constData(), false, reinterpret_cast<void*>(id)))
1533 id = -1;
1535 return id;
1539 Posts \a filename to \a url, and displays the result in \a window. Returns the ID of
1540 the request that is delivered to transferComplete() when the post-operation has finished.
1541 Returns 0 when the browser or the system doesn't support notification, or -1 when an
1542 error occured.
1544 \code
1545 void MyPlugin::uploadFile()
1547 uploadFile("ftp://ftp.somewhere.com/incoming", "response", "c:\\temp\\file.txt");
1549 \endcode
1551 See Netscape's JavaScript documentation for an explanation of window names.
1553 \sa transferComplete() uploadData() openUrl()
1556 int QtNPBindable::uploadFile(const QString &url, const QString &window, const QString &filename)
1558 if (!pi)
1559 return -1;
1561 QByteArray data = filename.toLocal8Bit();
1562 int id = pi->getNotificationSeqNum();
1563 if (NPERR_NO_ERROR != NPN_PostURLNotify(pi->npp, url.toLocal8Bit().constData(), window.isEmpty() ? 0 : window.toLocal8Bit().constData(), data.size(), data.constData(), true, reinterpret_cast<void*>(id)))
1564 id = -1;
1566 return id;
1570 Called as a result of a call to openUrl, uploadData or uploadFile.
1571 \a url corresponds to the respective parameter, and \a id to value returned
1572 by the call. \a reason indicates how the transfer was completed.
1574 void QtNPBindable::transferComplete(const QString &url, int id, Reason reason)
1576 Q_UNUSED(url)
1577 Q_UNUSED(id)
1578 Q_UNUSED(reason)
1582 /******************************************************************************
1583 * The plugin itself - only one ever exists, created by QtNPFactory::create()
1584 *****************************************************************************/
1588 \class QtNPFactory qtbrowserplugin.h
1589 \brief The QtNPFactory class provides the factory for plugin objects.
1591 Implement this factory once in your plugin project to provide information
1592 about the plugin and to create the plugin objects. Subclass QtNPFactory and
1593 implement the pure virtual functions, and export the factory using the
1594 \c QTNPFACTORY_EXPORT() macro.
1596 If you use the Q_CLASSINFO macro in your object classes you can use the
1597 \c QTNPFACTORY_BEGIN(), \c QTNPCLASS() and \c QTNPFACTORY_END() macros to
1598 generate a factory implementation:
1600 \code
1601 class Widget : public QWidget
1603 Q_OBJECT
1604 Q_CLASSINFO("MIME", "application/x-graphable:g1n:Graphable data")
1605 public:
1609 QTNPFACTORY_BEGIN("Plugin name", "Plugin description")
1610 QTNPCLASS(WidgetClass)
1611 QTNPFACTORY_END()
1612 \endcode
1614 The classes exposed must provide a constructor.
1616 If Qt is linked to the plugin as a dynamic library, only one instance of
1617 QApplication will exist \e{across all plugins that have been made with Qt}.
1618 So, your plugin should tread lightly on global settings. Do not, for example,
1619 use QApplication::setFont() - that will change the font in every widget of
1620 every Qt-based plugin currently loaded!
1624 Creates a QtNPFactory.
1626 QtNPFactory::QtNPFactory()
1631 Destroys the QtNPFactory.
1633 This is called by the plugin binding code just before the plugin is
1634 about to be unloaded from memory. If createObject() has been called,
1635 a QApplication will still exist at this time, but will be deleted
1636 shortly after, just before the plugin is deleted.
1638 QtNPFactory::~QtNPFactory()
1644 \fn QStringList QtNPFactory::mimeTypes() const
1646 Reimplement this function to return the MIME types of the data formats
1647 supported by your plugin. The format of each string is
1648 mime:extension(s):description:
1650 \code
1651 QStringList mimeTypes() const
1653 QStringList list;
1654 list << "image/x-png:png:PNG Image"
1655 << "image/png:png:PNG Image"
1656 << "image/jpeg:jpg,jpeg:JPEG Image";
1657 return list;
1659 \endcode
1663 \fn QObject *QtNPFactory::createObject(const QString &type)
1665 Reimplement this function to return the QObject or QWidget subclass
1666 supporting the mime type \a type, or 0 if the factory doesn't support
1667 the type requested.
1669 \a type will be in the same form as the leftmost (mime) part of
1670 the string(s) returned by mimeTypes(), e.g. "image/png".
1674 \fn QString QtNPFactory::pluginName() const
1676 Reimplement this function to return the name of the plugin.
1680 \fn QString QtNPFactory::pluginDescription() const
1682 Reimplement this function to return the description of the plugin.