Home | History | Annotate | Download | only in docs
      1 /*!
      2     \inmodule QtWebKit
      3     \page qtwebkit-bridge.html
      4     \title The QtWebKit Bridge
      5     \contentspage QtWebKit
      6     \section1 Overview
      7     \section2 The technology
      8 
      9     The QtWebKit bridge is a mechanism that extends WebKit's JavaScript environment to access native
     10     objects represented as \l{QObject}s. It takes advantage of the \l{QObject} introspection,
     11     a part of the \l{Object Model}, which makes it easy to integrate with the dynamic JavaScript environment.
     12     For example \l{QObject} properties map directly to JavaScript properties.
     13 
     14     \section2 Use Cases
     15 
     16     There are two main use cases for the QtWebKit bridge: web content in native applications and thin clients.
     17 
     18     \section3 Web Content in Native Applications
     19 
     20     This is a common use case in classic Qt application, and a design pattern used by several modern
     21     applications like an application that contains a media-player, playlist manager, and music store.
     22     The playlist manager is usually best authored as a classic desktop application,
     23     with the native-looking robust \l{QWidget}s as the application's backbone.
     24     The media-player control usually has a custom look and feel and is best written using the \l{Graphics View framework}
     25     or \l{QtDeclarative}. The music store, which shows dynamic content
     26     from the Internet and gets modified rapidly, is best authored in HTML and maintained on the server.
     27 
     28     With the QtWebKit bridge, the music store component can interact with native parts of the application,
     29     for example, when a file needs to be saved to a specific location.
     30 
     31     \section3 Thin Clients
     32 
     33     The use case uses Qt as a native backend of a full web application,
     34     a so-called thin client. In this use case, the entire UI is driven by
     35     HTML, JavaScript and CSS. Additionally, it uses Qt-based components to
     36     access native features usually not exposed to the web, or to enable helper
     37     components that are best written in C++.
     38 
     39     An example for such a client is a UI for a video-on-demand service on a TV. The entire content and
     40     UI can be kept on the server, served dynamically through HTTP and rendered with WebKit. Additional
     41     native components are used to access hardware-specific features like extracting a list of images
     42     out of a video stream.
     43 
     44     \section2 Difference from Other Bridge Technologies
     45 
     46     Of course, QtWebKit is not the only bridge technology out there. NPAPI, for example,
     47     is a long-time standard for web-native bridging. Due to Qt's meta-object system, full applications
     48     leveraging web technologies are much easier to develop with the QtWebKit bridge than with NPAPI. NPAPI, however, is better
     49     for cross-browser plugins, due to it being an accepted standard.
     50 
     51     When developing a plugin for a browser, NPAPI is recommended. When developing a full application
     52     utilizing HTML-rendering, the QtWebKit bridge is recommended.
     53 
     54     \section2 Relationship with QtScript
     55 
     56     The QtWebKit bridge is similar to \l{QtScript}, especially for some of the features described in the
     57     \l{Making Applications Scriptable} page. However, Qt 4.7 does not provide the full QtScript API for web applications.
     58     Full support is planned for future versions. You might notice that some of the features
     59     described here are an exact copy of the ones described in the \l{Making Applications Scriptable} page. That is because
     60     the QtWebKit bridge is a subset of that functionality, and this page tries to capture the full
     61     capabilities available through the QtWebKit bridge specifically.
     62 
     63     \section1 Accessing QObjects
     64 
     65     \section2 Making QObjects known to JavaScript via QWebFrame
     66 
     67     By default, no QObjects are accessible through the web environment, for security reasons.
     68     When a web application wants to access a native QObject, it must explicitly grant access
     69     to this QObject, using the following call:
     70 
     71     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 0
     72 
     73     See \l{QWebFrame::addToJavaScriptWindowObject()} for more information.
     74 
     75     \section2 Using Signals and Slots
     76 
     77     The QtWebKit bridge adapts Qt's central \l{Signals and Slots} feature for
     78     scripting. There are three principal ways to use signals and slots
     79     with the QtWebKit bridge:
     80 
     81     \list
     82     \i \bold{Hybrid C++/script}: C++ application code connects a
     83     signal to a script function. This approach is useful if you have
     84     a QObject but don't want to expose the object itself to the scripting
     85     environment. You just want to define how the script responds to a
     86     signal and leave it up to the C++ side of your application to establish
     87     the connection between the C++ signal and the JavaScript slot.
     88 
     89     \i \bold{Hybrid script/C++}: A script can connect signals and slots
     90     to establish connections between pre-defined objects that the
     91     application exposes to the scripting environment. In this scenario,
     92     the slots themselves are still written in C++, but the definition of
     93     the connections is fully dynamic (script-defined).
     94 
     95     \i \bold{Purely script-defined}: A script can both define signal
     96     handler functions (effectively "slots written in JavaScript"),
     97     \e{and} set up the connections that utilize those handlers. For
     98     example, a script can define a function that will handle the
     99     QLineEdit::returnPressed() signal, and then connect that signal to the
    100     script function.
    101     \endlist
    102 
    103     Note that QtScript functions such as qScriptConnect are unavilable in the web environment.
    104 
    105     \section3 Signal to Function Connections
    106 
    107     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 7
    108 
    109     The call to \c{connect()} establishes a connection between the signal
    110     \c{somethingChanged} and the slot \c{myInterestingScriptFunction}.
    111     Whenever the object \c{myObject} emits the signal \c{somethingChanged},
    112     the slot \c{myInterestingScriptFunction} gets called automatically.
    113 
    114     The argument of \c{connect()} can be any JavaScript function as in the above
    115     example or a slot of a QObject as in the following example:
    116 
    117     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 8
    118 
    119     When the argument is a slot of a QObject, the argument types of the
    120     signal and the slot do not have to be compatible. If possible, the QtWebKit
    121     bridge converts the signal arguments such that they match the slot argument.
    122 
    123     To disconnect a slot from a signal, you call the signal's
    124     \c{disconnect()} function with the slot as its argument:
    125 
    126     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 9
    127 
    128     When a script function is invoked in response to a signal, the
    129     \c this object will be the Global Object.
    130 
    131     \section3 Signal to Member Function Connections
    132 
    133     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 10
    134 
    135     The call to \c{connect() establishes a connection between the signal
    136     \c{somethingChanged} and the slot \c{function}. Whenever the object
    137     \c{myObject} emits the signal \c{somethingChanged}, the slot \c{function}
    138     of the object \c{thisObject} gets called automatically. Let's illustrate
    139     this with an example.
    140 
    141     If you have a push button in a form, you typically want the form
    142     to do something in response to the button's \c{clicked} signal. The
    143     call to \c{connect()} makes sure that the function \c{onClicked()} is
    144     called whenever you click on the push button, that is, whenever the
    145     the signal \c{clicked()} is emitted by \c{myButton}. The slot \c{onClicked()}
    146     prints the value of \c{x} as stored in the \c{form}.
    147 
    148     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 11
    149 
    150     To disconnect a slot from a signal, you pass the same arguments to
    151     \c{disconnect()} as you passed to \c{connect()}. In general, this looks
    152     as follows:
    153 
    154     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 12
    155 
    156     \section3 Signal to Named Member Function Connections
    157 
    158     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 14
    159 
    160     This form of the \c{connect()} function requires that the first argument \c{thisObject} is
    161     the object that will be bound to \c{this} when the function \c{functionName} is
    162     invoked in response to the signal \c{somethingChanged}. The second argument \c{functionName} specifies the
    163     name of a function that is connected to the signal. It refers to a
    164     member function of the object \c{thisObject}.
    165 
    166     Note that the function is resolved when the connection is made, not
    167     when the signal is emitted.
    168 
    169     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 15
    170 
    171     To disconnect from the signal, pass the same arguments to \c{disconnect()}
    172     as you passed to \c{connect}:
    173 
    174     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 17
    175 
    176     \section3 Error Handling
    177 
    178     When \c{connect()} or \c{disconnect()} succeeds, the function will
    179     return \c{undefined}; otherwise, it will throw a script exception.
    180     You can obtain an error message from the resulting \c{Error} object.
    181     Example:
    182 
    183     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 18
    184 
    185     \section3 Emitting Signals from Scripts
    186 
    187     To emit a signal from script code, you simply invoke the signal
    188     function, passing the relevant arguments:
    189 
    190     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 19
    191 
    192     It is currently not possible to define a new signal in a script;
    193     i.e., all signals must be defined by C++ classes.
    194 
    195     \section3 Overloaded Signals and Slots
    196 
    197     When a signal or slot is overloaded, the QtWebKit bridge will attempt to
    198     pick the right overload based on the actual types of the QScriptValue arguments
    199     involved in the function invocation. For example, if your class has slots
    200     \c{myOverloadedSlot(int)} and \c{myOverloadedSlot(QString)}, the following
    201     script code will behave reasonably:
    202 
    203     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 20
    204 
    205     You can specify a particular overload by using array-style property access
    206     with the \l{QMetaObject::normalizedSignature()}{normalized signature} of
    207     the C++ function as the property name:
    208 
    209     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 21
    210 
    211     If the overloads have different number of arguments, the QtWebKit bridge will
    212     pick the overload with the argument count that best matches the
    213     actual number of arguments passed to the slot.
    214 
    215     For overloaded signals, JavaScript will throw an error if you try to connect
    216     to the signal by name; you have to refer to the signal with the full
    217     normalized signature of the particular overload you want to connect to.
    218 
    219     \section3 Invokable Methods
    220 
    221     Both slots and signals are invokable from scripts by default. In addition, it is also
    222     possible to define a method that is invokable from scripts, although the method is neither a signal nor a slot.
    223     This is especially useful for functions with return types, as slots normally do not return anything
    224     (it would be meaningless to return a value from a slot, as the connected signals cannot handle return values).
    225     To make a non-slot method invokable, simply add the Q_INVOKABLE macro before its definition:
    226 
    227     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 22
    228 
    229     \section2 Accessing Properties
    230 
    231     The properties of a QObject are available as properties
    232     of the corresponding JavaScript object. When you manipulate
    233     a property in script code, the C++ get/set method for that
    234     property will automatically be invoked. For example, if your
    235     C++ class has a property declared as follows:
    236 
    237     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 23
    238 
    239     then script code can do things like the following:
    240 
    241     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 24
    242 
    243     \section2 Accessing Child QObjects
    244 
    245     Every named child of a QObject (that is, every child for which
    246     QObject::objectName() does not return the empty string) is by default available as
    247     a property of the JavaScript wrapper object. For example,
    248     if you have a QDialog with a child widget whose \c{objectName} property is
    249     \c{"okButton"}, you can access this object in script code through
    250     the expression
    251 
    252     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 25
    253 
    254     Because \c{objectName} is itself a Q_PROPERTY, you can manipulate
    255     the name in script code to rename an object. For example:
    256 
    257     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 26
    258 
    259     \section2 Data types
    260 
    261     When calling slots, receiving signals or accessing properties, usually some payload is involved.
    262     For example, a property "text" might return a \l{QString} parameter.
    263     The QtWebKit bridge does the job of converting between a given JavaScript data-type, and the
    264     expected or given Qt type. Each Qt type has a coresponding set of rules of how JavaScript treats it.
    265 
    266     The data type conversions are also applicable for the data returned from non-void invokable methods.
    267 
    268     \section3 Numbers
    269 
    270     All Qt numeric data types are converted to or from a JavaScript number. These include int, short, float,
    271     double, and the portable Qt types (qreal, qint etc). A special case is \l{QChar}.
    272     If a slot expects a QChar, the QtWebKit bridge uses the Unicode value in case of a number and the first character in case of a string.
    273 
    274     Note that non-standard (typedef'ed) number types are not automatically converted to
    275     or from a JavaScript number - we suggest to use standard number types for signals, slots
    276     and properties.
    277 
    278     When a non-number is passed as an argument to a method or property that expects a number,
    279     the appropriate JavaScript conversion function (parseInt / parseFloat) is used.
    280 
    281     \section3 Strings
    282 
    283     When JavaScript accesses methods or properties that expect a \l{QString}, the QtWebKit bridge
    284     will automatically convert the value to a string (if it is not already a string), using the
    285     built-in JavaScript toString method.
    286 
    287     When a QString is passed to JavaScript from a signal or a property, the QtWebKit bridge
    288     converts it into a JavaScript string.
    289 
    290     \section3 Date & Time
    291 
    292     Both \l{QDate}, \l{QTime} and \l{QDateTime} are automatically translated to or from the JavaScript
    293     Date object. If a number is passed as an argument to a method that expects one of the date/time
    294     types, the QtWebKit bridge treats it as a timestamp. If a sting is passed, QtWebKit
    295     tries the different Qt date parsing functions to perform the right translation.
    296 
    297     \section3 Regular Expressions
    298 
    299     The QtWebKit bridge automatically converts a JavaScript RegEx object to a \l{QRegExp}.
    300     If a string is passed to a method expecting a \l{QRegExp}, the string is converted
    301     to a \l{QRegExp}.
    302 
    303     \section3 Lists
    304 
    305     The QtWebKit bridge treats several types of lists in a special way: \l{QVariantList}, \l{QStringList},
    306     \l{QObjectList} and \l{QList}<int>. When a slot or property expects one of those list types,
    307     the QtWebKit bridge tries to convert a JavaScript array into that type, converting each of
    308     the array's elements to the single-element type of the list.
    309 
    310     The most useful type of list is \l{QVariantList}, which can be converted to and from any
    311     JavaScript array.
    312 
    313     \section3 Compound (JSON) objects
    314 
    315     JavaScript compound objects, also known as JSON objects, are variables that hold a list
    316     of key-value pairs, where all the keys are strings and the values can have any type.
    317     This translates very well to \l{QVariantMap}, which is nothing more than a \l{QMap} from \l{QString}
    318     to \l{QVariant}.
    319 
    320     The seamless conversion between JSON objects and \l{QVariantMap} allows for a very convenient
    321     way of passing arbitrary structured data between C++ and the JavaScript environment. If the native \l{QObject} makes sure that compound values are converted to \l{QVariantMap}s and \l{QVariantList}s, JavaScript is
    322     guaranteed to receive them in a meaningful way.
    323 
    324     Note that types that are not supported by JSON, such as JavaScript functions and getters/setters,
    325     are not converted.
    326 
    327     \section3 QVariants
    328 
    329     When a slot or property accepts a \l{QVariant}, the QtWebKit bridge creates a \l{QVariant} that best
    330     matches the argument passed by JavaScript. A string, for example, becomes a \l{QVariant} holding a \l{QString},
    331     a normal JSON object becomes a \l{QVariantMap}, and a JavaScript array becomes a \l{QVariantList}.
    332 
    333     Using \l{QVariant}s generously in C++ in that way makes C++ programming feel a bit more like JavaScript programming,
    334     as it adds another level of indirection. Passing \l{QVariant}s around like this    is very flexible. The program can figure out
    335     the type of argument at runtime just like JavaScript would do. But doing so also takes away the type safety and robustness of C++.
    336     We recommended to use \l{QVariant}s only for high-level functions, and to keep most of your
    337     \l{QObject}s type-safe.
    338 
    339     \section3 QObjects
    340 
    341     Pointers to a \l{QObject} or a \l{QWidget} can be used in signals, slots and properties. This object
    342     can then be used like an object that is exposed directly. Its slots can be invoked, its signals connected to, etc.
    343     However, this functionality is fairly limited - the type used has to be \l{QObject}* or \l{QWidget}*. If the type
    344     specified is a pointer to a non-\l{QWidget} subclass of \l{QObject}, the QtWebKit bridge does not recognize it as
    345     a \l{QObject}.
    346 
    347     In general its advised to use care when passing \l{QObject}s as arguments, as those objects don't become owned by
    348     the JavaScript engine; That means that the application developer has to be extra careful not to try to access
    349     \l{QObject}s that have already been deleted by the native environment.
    350 
    351     \section3 Pixmaps and Images
    352 
    353     \since 4.7
    354 
    355     The QtWebKit bridge handles \l{QPixmap}s and \l{QImage}s in a special way. Since QtWebKit stores \l{QPixmap}s to
    356     represent HTML images, \l{QPixmap}s coming from the native environment can be used directly inside WebKit.
    357     A \l{QImage} or a \l{QPixmap} coming from Qt is converted to an intermediate JavaScript object,
    358     which can be represented like this:
    359 
    360     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 1
    361 
    362     The JavaScript environment can then use the pixmap from Qt and display it inside the HTML environment,
    363     by assigning it to an existing \c{<img>} element with \c{assignToHTMLImageElement()}. It can also use the \c{toDataURL()} function,
    364     which allows using the pixmap as the \c{src} attribute of an image or as a \c{background-image} URL. Note that the \c{toDataURL()}
    365     function is costly and should be used with caution.
    366 
    367     Example code:
    368 
    369     C++:
    370     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 2
    371 
    372     HTML:
    373     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 3
    374 
    375     When a Qt object expects a \l{QImage} or a \l{QPixmap} as input, and the argument passed is an HTML image element,
    376     the QtWebKit bridge would convert the pixmap assigned to that image element into a \l{QPixmap} or a \l{QImage}.
    377 
    378     \since 4.7
    379 
    380     \section3 QWebElement
    381 
    382     A signal, slot or property that expects or returns a \l{QWebElement} can work seamlessly with JavaScript references
    383     to DOM elements. The JavaScript environment can select DOM elements, keep them in variables, then pass them to Qt as
    384     a \l{QWebElement}, and receive them back. Example:
    385 
    386     C++:
    387     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 4
    388 
    389     HTML:
    390     \snippet webkitsnippets/qtwebkit_bridge_snippets.cpp 5
    391 
    392     This is specifically useful to create custom renderers or extensions to the web environment. Instead of forcing Qt
    393     to select the element, the web environment selects the element and then sends the selected element directly to Qt.
    394 
    395     Note that \l{QWebElement}s are not thread safe - an object handling them has to live in the UI thread.
    396 
    397     \section1 Architecture Issues
    398 
    399     \section2 Limiting the Scope of the Hybrid Layer
    400 
    401     When using QtWebKit's hybrid features, it is a common pitfall to make the API exposed to JavaScript very rich and
    402     use all its features. This, however, leads to complexity and can create bugs that are hard to find.
    403     Instead, it is advisable to keep the hybrid layer small and manageable: create a gate only when
    404     there's an actual need for it, i.e. there's a new native enabler that requires a direct interface
    405     to the application layer. Sometimes new functionality is better handled internally in the native layer
    406     or in the web layer; simplicity is your friend.
    407 
    408     This usually becomes more apparent when the hybrid layer can create or destroy objects, or uses
    409     signals, slots or properties with a \l{QObject}* argument. It is advised to be very careful and to treat
    410     an exposed \l{QObject} as a system - with careful attention to memory management and object ownership.
    411 
    412     \section2 Internet Security
    413 
    414     When exposing native objects to an open web environment, it is important to understand the security
    415     implications. Think whether the exposed object enables the web environment access things that
    416     shouldn't be open, and whether the web content loaded by that web page comes from a trusted source. In general, when
    417     exposing native QObjects that give the web environment access to private information or to functionality
    418     that's potentially harmful to the client, such exposure should be balanced by limiting the web page's
    419     access to trusted URLs only with HTTPS, and by utilizing other measures as part of a security strategy.
    420 
    421 
    422 
    423 */
    424