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