AppleStore and QtWebView (Webkit), QT5.5
-
I'm working on an OSX app on QT 5.5 with C++. It is not an iOS app. It will use QtWebView, which uses a form of Webkit. My app will also only use local html files, never a file from a web server. So, when I read this policy:
https://developer.apple.com/app-store/review/guidelines/#user-interface
It says:
2.17. Apps that browse the web must use the iOS WebKit framework and WebKit Javascript
Okay, in my case, my application will not "browse the web". Browsing the web requires a web server and a user to click a link that causes the application to interact with that web server. In my case, there's no web server involved -- all the files are local and access with
file://
. As well, it says iOS, but I'm working with OSX.So, because of this, it appears that this does not apply to my application. Can anyone confirm that 2.17 only applies to iOS (tablet, mobiles) and only applies to an application that has pages that interact with a backend web server?
-
Hi,
I can't confirm currently but to simplify your life, you can use the QtWebView module that provides a native web view for Android, iOS and OS X.
Hope it helps
-
Here is the documentation. It's currently a tech preview.
-
-
I don't know what you need for your application but if you are using widgets then you can also use a QQuickWidget for that part.
-
@SGaist Gosh this is confusing, sorry. So in 5.5, QT Creator's UI Designer tool for widgets, there's this widget called QWebView. Does that use Apple's native webkit or something else? It's named almost the same thing as QtWebView, which you link here:
http://doc.qt.io/qt-5/qtwebview-index.html
I'm just wondering if I'm forced to have to switch everything to QML, or if I have just mistaken something and can use the QWebView widget in my widget app and get Apple's native webkit there.
I did manage to get the minibrowser example with QML to load, and did run my local file:// URLs through it -- seems to handle a lot of advanced stuff just like my QWebView widget was processing. I mean, I was doing HTML5's postMessage() API just fine in it, along with jQuery and some advanced CSS stuff. Seemed to load just fine.
However, the problem with minibrowser is that I'm not certain how to fire up the webkit bridge to C++ with it. I mean, back on the widget project I did, I was able to create an object called
cpp
and inject that into the DOM of the browser context, and then have the Javascript talk directly to C++ functions on the backend. I'm not quite certain if this is even possible in the QML-based QtWebView project. -
@SGaist Well, I learned a few things more. The minibrowser example doesn't let you run alert() messages. However, I was able to do $('body').prepend(navigator.appVersion) and when I ran my pages through the QWebView widget application project, it said it was AppleWebkit/538.1. But running it through the QML QtWebView (minibrowser) example, it said it was AppleWebkit/601.1.56. I then loaded my pages through plain old Safari and it lined up with the same version that the minibrowser used. This leads me to believe that, yes, the QML QtWebView minibrowser project uses the native Apple Webkit, while the QWebView widget project used a forked version of webkit from awhile back, not the native one in the OSX operating system.
So, I guess I can move to this, minus the fact that things like alert() are not possible (I was only using that for debug, anyway), but the thing remaining for me is to figure out how to get the Javascript to call native C++ class methods like the Webkit bridge provided. Otherwise, it's nothing more than a glorified web browser, and that won't work for my project -- I need to call powerful C++ library stuff that like interacts with a SQLite database, interact with the file system, show a file chooser dialog, etc.
-
@SGaist Okay, I figured it out:
http://stackoverflow.com/a/33818023/105539
It requires turning on something experimental that might not make it into a future Qt, and then doing message passing between Javascript
navigator.qt.postMessage()
and an event handler in QML calledexperimental.onMessageReceived
, and then QML can call C++ from there. Then, QML can post a message back withexperimental.postMessage()
, of which your Javascript can receive it withnavigator.qt.onmessage
event.No native C++ functions can be invoked directly -- it's message-passing only.
-
Also, for the curious, Qt 5.6 (still in beta and which may end up being Qt 5.7), appears that it will still support QtWebView. However, the next version of Qt after 5.5 will include QtWebEngine. As the preliminary docs show:
http://doc-snapshots.qt.io/qt5-dev/qtwebengine-overview.html
The Qt WebEngine module provides a web browser engine that makes it easy to embed content from the World Wide Web into your Qt application on platforms that do not have a native web engine. The web engine is not intended to function as a Web Runtime; to display web content in a QML application by using APIs native to the platform, use the Qt WebView module, instead.
Qt WebEngine provides C++ classes and QML types for rendering HTML, XHTML, and SVG documents, styled using Cascading Style Sheets (CSS) and scripted with JavaScript. HTML documents can be made fully editable by the user through the use of the contenteditable attribute on HTML elements.
Qt WebEngine supercedes the Qt WebKit module, which is based on the WebKit project, but has not been actively synchronized with the upstream WebKit code since Qt 5.2 and has been deprecated in Qt 5.5. For tips on how to change a Qt WebKit widgets application to use Qt WebEngine widgets, see Porting from Qt WebKit to Qt WebEngine. For new applications, we recommend using Qt Quick and the WebEngineView QML type.
So, at least on OSX, Android, and iOS (tablet, mobiles), you can decrease your setup package size by using QtWebView in QML because it uses the native Webkit that's part of OSX and which OSX updates routinely. On the other hand, it recommends using QtWebEngine "on platforms that do not have a native web engine" (in other words, Windows or Linux, but not Mac OSX (I think since Snow Leopard) or IOS or Android because the latter have a native web engine). (Wait -- does Windows 10 ship with Metro, and is that a native web engine? I'm not certain.)
To state this a little more clearly:
-
If deploying on OSX, iOS, or Android, take advantage of the smaller setup package size by not having to redeploy Webkit, and using the native Webkit API of those operating systems by using QML and QtWebView. The caveat being that you have to enable an experimental and largely undocumented API (except some things listed on blogs and stackoverflow) in Qt 5.5, which likely won't be experimental in the version that comes after Qt 5.5 (5.6? 5.7?). The other advantage here is that at least with iOS, this technique has a higher chance of getting your app approved in the Apple Store.
-
If you don't want to be experimental, but don't mind increasing the setup package size (because you're adding Webkit), and aren't deploying on iOS or Android, but are deploying on OSX, Windows, or Linux, then you can use QWebView either in QML or with a widget application. Apple is vague here, but they have said that this technique will block your app from being approved in the Apple Store if deploying at least with iOS -- they still haven't told me yet whether this also applies to OSX.
-
If you can hold out until the next version that comes out after Qt 5.5 (5.6? 5.7?), you can take advantage of QtWebEngine, but there are some caveats here. First, it deploys Chromium, which is an even larger codebase than Webkit. Second, it's likely not going to be an approved app in the Apple Store because it doesn't use native Webkit -- at least with what they say about iOS apps, but still haven't gotten back to me on whether this applies also to OSX. Third, as they state in the preliminary docs, QtWebEngine is recommended only for operating systems where they don't have a native web engine -- as in Windows and Linux.
-
-
There appears to be more to this. After a lot of experimentation with this tech preview (QtWebView) in Qt 5.5, I've decided that it's not ready for primetime. Sure, you can turn on the experimental mode, but then you'll find odd stuff like scrollbars disappearing (if you enable on some HTML elements), radio buttons and checkboxes looking very strange (not Fusion, not Windows, not GTK, not OSX -- just plain strange), popdown select listboxes that no longer function, and when you doubleclick a page -- it zooms. Turn off experimental mode and those start working again.
The only thing stable in Qt 5.5 in my experience is QWebView as a widget. You get C++ bridging without the QML in your way, and the web components on the page work. Plus, you can put
QApplication::setStyle(QStyleFactory::create("Fusion"));
in your main.cpp and make your HTML controls look great.Of course, QWebView's EOL is 5.5, supposedly, and so you'll have to migrate it to QtWebEngine eventually when you upgrade your Qt. Trouble there, though, is that this ships with Chromium. That means you can't use the native webkit engine on OSX, Android, and iOS, and means a fatter install. Plus, because QtWebEngine uses Chromium instead of Webkit, it's going to be an even fatter install. Next, it's very likely you won't get an iOS app approved if it uses QtWebEngine because Apple wants you to use a native web engine for iOS apps. (As for OSX apps -- I'm still trying to get Apple to clarify this issue on what passes the Apple Store's muster.)
Here's my soapbox. It would be ideal if a future Qt supported:
- one web widget API that you can either hook through QML or widgets, instead of multiple ones that each come with their own quirks
- ability to use native webkit instead of bundling webkit, for platforms that support it
- for platforms that don't support native webkit, an option to deploy with Chromium or webkit (although this requires some testing)
- ability to set the browser engine mode during debug/build testing in the .pro file
- HTML controls that can be set to Fusion mode like they can with QWebView widget
- an easier way to bridge to native C++ from Javascript without having to do message passing or going through the QML layer, or at least make it even easier to go through the QML layer
- provide the ability to turn off things like autozoom on doubleclick, certain browser keystrokes, back/forward keystrokes and mouse gestures, the rightclick context menu, and auto scrollbar hiding
-
Hi,
just for curiosity.
Are you 100% sure you cannot use WebEngine on OS X for Apple store??In the worst case you can write your custom widget using the native WebView (the Objective-C one). You'll find a lot of examples how to use native OS X API in Qt.
Last but not least: How complex is the HTML interface you need to show? Could be in some way replaced with a QML interface?
-
@mcosta If you're referring to QtWebEngine with 5.6, it says it's going to ship with Chromium. I put in a request with Apple Developer support to ask if an OSX app (not an iOS app, mind you) would be denied if it shipped with anything instead of the native webkit library of OSX, meaning Chromium or embedded webkit (QWebView). I still have not received an answer from an actual Apple Engineer on this yet. Here's my post:
https://forums.developer.apple.com/thread/26612
However, a user claims in that forum that you must use native webkit of OSX (stock WebView, he calls it) in order to be approved with a Mac OSX app in the Apple Store. That's a user, mind you, not an Apple Engineer.
I tried using QML + QtWebView (not to be confused with QWebView), which uses Apple's stock WebView. This was the Qt 5.5 technical preview called Minibrowser. I got it to load my offline app, but had lots of trouble that made it pretty much impractical. Turn on experimental mode and some nice features are possible like turning off the context menu, and the ability from Javascript to send message to QML and then have QML talk to C++, and send a message right back to the Javascript. But then what also happens is that stuff breaks like SELECT elements, and then the styling is trashed for scrollbars, checkboxes, and radio buttons.
If you can point me in the direction of some tutorial in how I can build a custom widget using Apple's native webview, of which would seem to function better than the Minibrowser technical preview, I'd like to see it.
As for whether or not I would use QML -- I'd rather not. See, to me, it's just not powerful enough. With Webkit, I can load Bootstrap, advanced CSS stuff that only applies to Webkit, and get unhampered access with jQuery. As a web developer as well, it's also faster for me to build the UI using Webkit than it is to use QML. To me, using QML is like asking a person to build a jetfighter with tinkertoys. I played with it and kept running into feature walls where, "Oh, QML can't do that," or, "you have to intercept paint events (a kludge) to make it work," or "you can get it to work, but it's going to require dozens of steps." Baah -- had enough of that for awhile and just gave up and switched to Webkit. In my opinion, Qt should just phase out QML eventually and focus on permitting two GUI venues besides Widget apps: native Webkit (if the OS supports it), and Chromium.
-
Just to be clear on the state of the art at this time:
- QtWebKit has been deprecated. See this blog post for more information about why
- QtWebEngine is the new supported heavy weight web component
- QtWebView is not a replacement for QtWebKit nor QtWebEngine. It's a light wrapper around a system web view for OS that provides one and to allow submission to their respective app stores. Apple restricts the use of web component to their own for both iOS and OS X when going through the App Store. The same rule applies for Android.
As for OS X, if you don't use the App Store to distribute your application (numerous applications don't), nothing forbids you to use either QtWebKit or QtWebEngine.
-
@maximo Did you finally submit an app to the Mac App store and which web incarnation of Qt did you use ?