// 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
\endcode
or
\code
\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