// Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). // SPDX-License-Identifier: BSD-3-Clause /*! \page developingplugins.html \title Developing Plugins The QtBrowserPlugin solution makes it easy to write browser plugins that can be used in Mozilla FireFox, Safari, Opera, Google Chrome, QtWebKit and any other web browser that supports the "Netscape Plugin API", NPAPI: \l http://en.wikipedia.org/wiki/NPAPI \l http://developer.mozilla.org/en/Plugins Microsoft Internet Explorer does not support this API. However, you can use the ActiveQt framework to turn your plugin into an ActiveX control, that will work as an IE plugin. Thus, QtBrowserPlugin makes it possible to create a single plugin DLL that will work with all popular browsers on Windows. \tableofcontents \section1 Implementing plugins Since any QWidget or QObject subclass can be turned into a plugin with little effort it is usually easiest to do the development as a stand-alone Qt application - debugging plugins can be cumbersome. Make sure that the subclass(es) you want to export use the Q_OBJECT macro and provide a default constructor. Use the Q_CLASSINFO macro to specify a semicolon-delimited list of the MIME types each of your classes supports, and export the classes through the QTNPFACTORY macros: \quotefromfile grapher.cpp \skipto QTNPFACTORY_BEGIN \printuntil QTNPFACTORY_END() This should be done only once, in one of the source files. If your plugin needs to export multiple classes (i.e. to handle different sets of MIME types), make one QTNPCLASS line for each of them. Include the \c qtbrowserplugin.pri in your .pro file, and regenerate the makefile with qmake. The resulting makefile will generate a shared library that the browsers will be able to load as a plugin. \section2 Windows specific notes On Windows, the DLL will have \c{"np"} prepended to its name - this is required by all browsers to recognize the library as a plugin. On Windows it is required to link a version resource into the plugin library. To do that, create an .rc file (a plain-text file) and add it to the \c RC_FILE variable of your project. The .rc file needs to contain a version description like here: \quotefromfile grapher.rc \skipto VERSION \printuntil VarFileInfo \printuntil END \printuntil END \section3 Enabling ActiveX support To build a plugin project with ActiveX support, use ActiveQt's QAxServer module by adding the following line to your project: CONFIG += qaxserver Also, add the following line to your resource file \c{1 TYPELIB "thisfile.rc"} In your plugin code, use Q_CLASSINFO and the QAxFactory macros as usual; refer to the ActiveQt documentation. When you build the plugin, then ActiveQt will perform the build steps required to turn the plugin library into an ActiveX control server which provides your plugin classes not only to browsers supporting the npruntime API, but also to browsers supporting ActiveX controls (i.e. Internet Explorer). However, note that calling QtNPBindable APIs will not do anything when the browser does not support the npruntime API. In some cases, QAxBindable provides equivalent APIs (i.e. for reading incoming data). \section2 Unix specific notes On Unix/Linux, QtBrowserPlugin uses the XEmbed protocol. Hence, plugins will only work for browsers that support this protocol. This is true for the recent versions of all the most popular browsers. For Opera, it requires at least version 9.6, QtWebKit requires at least Qt version 4.5. \section3 Known Issues on Unix/Linux In some rare cases, symbol clash with other instances of the Qt libraries may occur. That is, if the browser itself uses Qt, or other plugins do, and these are loaded into the same address space, your plugin's calls to the Qt API may end up in a different version of the Qt library than what was intended, leading to undefined results. If you should hit this problem, it is easily worked around by linking your plugin to Qt libraries that are either statically built, or that is built to use a separate namespace (by adding the \c{-qtnamespace=SomeNamespace} option to Qt's \c configure command). \section2 Mac OSX specific notes NOTE: Mac support is experimental only! Expect failure with recent versions of Qt! To build a browser plugin on Mac, two plain-text resource files are needed: an \c Info.plist file and a \c .r file. To create these files, it is easiest to use the ones provided with the QtBrowserPlugin examples as templates, editing as necessary. Then add them to your project (\c .pro file) like this: \quotefromfile grapher.pro \skipto QMAKE_INFO_PLIST \printuntil QMAKE_BUNDLE_DATA \section3 Known Issues on Mac \list \o After navigating away from the webpage with the plugin, and then back again, the plugin no longer shows up or runs. No workaround currently known. \endlist \section1 Installing and using Plugins Most browsers provide a UI to display all loaded plugins, either as a menu choice, and/or by navigating to the url \c{about:plugins}. Use this functionality to diagnose problems. The plugin will need to load the Qt libraries at runtime (unless they are statically linked into the plugin). Hence, the required Qt dynamic libraries (at least QtCore, QtGui, and QtNetwork) must be located in a directory which the system searches for DLLs. This may or may not include the directory where the plugin itself is located, depending on the OS and browser. Windows, Netscape-style browsers: To install the plugin, copy the plugin library in the "plugins" directory of the browser. See \c{src/qtbrowserplugin.pri} for some typical paths. Typically, it is sufficient to install it for one browser, and the others will find it. Ref. \l http://developer.mozilla.org/en/Plugins/The_First_Install_Problem Windows, Internet Explorer: The Makefile generated by qmake by default runs the necessary commands to register the plugin as an ActiveX server (if \c CONFIG includes \c qaxserver). To unregister, use the following command: \code c:\Qt-x.y.z\bin\idc.exe path\to\myplugin.dll /unregserver \endcode Mac: The build will result in a directory called \c myplugin.plugin. To install, copy this directory with all contents to \c{/Library/Internet Plugins}. Unix: Copy the file \c myplugin.so to the browser or system plugin directory, typically \c /usr/lib/browser-plugins. The path to the Qt libraries may be set in the LD_LIBRARY_PATH environment variable of the browser process. \section2 Embedding the plugin on a web page. Browsers vary slightly in their support for different plugin-embedding HTML tags. The following should work for most popular browsers. \section3 Plugins with data: Plugins can be initialized with a data file, which will be delivered at some point after plugin creation to the plugin through the QtNPBindable::readData() virtual function. (This applies to ActiveQt-based plugins in IE as well). Assuming the MIME type is \c{application/x-graphable}, with the extension \c{g1n}: \code Plugin not installed! \endcode or \code Plugin not installed! \endcode Note that some browsers will not display or immediately unload the plugin if the data file does not exist, while other browsers will display the plugin without ever calling readData(). If the plugin has declared a Q_PROPERTY called \c src, the setter function for this property will be called at instantiation time with the data URL as parameter. \section3 Plugins without data: Assuming the (dummy) MIME type is \c{trivial/very}: \code \endcode \section3 Tags not working equally with all browsers \list \o \c{} Only IE supports this. \o \c{} IE will not call readData(), but the \c src property will be set, so manual data loading is possible. \o \c{} Ditto. \o \c{} Some browsers do not display plugins without \c data attribute \endlist For additional information, see \l http://developer.mozilla.org/en/Gecko_Plugin_API_Reference/Plug-in_Basics#Using_HTML_to_Display_Plug-ins \section2 Browser full-page view of a plugin If files viewed by a plugin are provided by an HTTP server (using a \c{http://...} URL) then the server must be configured to send the correct MIME type for the file, e.g. by editing Apache's \c{mime.types} file. (Not required for IE). If the files are viewed via a \c{file://...} URL (e.g. by the user opening the data file with \c{File->Open}), then the browser will use the filename extension to decide the file type (and hence the plugin to load). In the full-page case, IE will not call readData(), but the \c src property will be set, so manual data loading is possible. See the \c grapher example. \section2 Scripting Plugins embedded into browsers that support the respecive NPAPI extensions as well as ActiveX controls can be accessed from JavaScript in the HTML page. \quotefromfile ../examples/trivial/scripting.qdoc \skipto Assign a function to a property of the object with the same name as the signal. Overloads (i.e. two signal with the same name, but different parameters) are not possible. \printuntil Internet Explorer requires a special syntax that is not compatible with other browsers, but the IE-specific function can just call the other functions. \section3 Using plugins in forms Plugin objects can be embedded as form elements. To specify which property value the plugin should report to the form upon submission, specify the name of the property as the DefaultProperty using a Q_CLASSINFO entry: \code Q_OBJECT Q_CLASSINFO("MIME", "trivial/very:xxx:Trivial and useless") Q_CLASSINFO("DefaultProperty", "text") \endcode In the HTML page, embed the object as usual: \code
Search:
\endcode Clicking the button will make the browser request a URL \c http://www.server.com/search.asp?text=[value from object] The property type needs to be convertible to a string. */