From anilsson at blackberry.com Thu Dec 5 11:13:00 2013 From: anilsson at blackberry.com (Arvid Nilsson) Date: Thu, 5 Dec 2013 10:13:00 +0000 Subject: [Qtwebengine] Quick Download API Message-ID: Hi there! For full backward compatibility, widget flavor of QtWebEngine might benefit from a QNetworkAccessManager shim on top of the Chromium HTTP stack, and using the regular QtNetwork types to manage downloads. For QML, we would like to start discussion on how a QML-friendly download API could look like. Requirements courtesy of cswei: 1. to control the download (stop , resume, pause, cancel, etc) 2. To get the download state notification ( progress, failure, finished, etc) 3. To initiate a download , like anilsson says: user press-hold on a link/image, and selects "download" to download a resource 4. Give the application/user the opportunity to specify the storage location, the file name, etc. 5. Special download, like OMA download, download of DRM contents, etc. I believe all the methods/signals/slots from 1 and 2 could go into a WebEngineDownloadRequest creatable class. Perhaps there will be use for a WebEngineDownloadHandler attached object I think 3 should be an API on WebEngineView or WebEngineView.experimental: WebEngineView.download(WebEngineDownloadRequest). Also a signal for web-initiated downloads WebEngineView.onDownloadRequested (or possibly go straight to the WebEngineDownloadHandler). I think 4 could also be in the WebEngineDownloadRequest or WebEngineDownloadHandler All of the required functionality exists in the Chromium content APIs, we just need to figure out an API. What do you think? BR, /A --------------------------------------------------------------------- This transmission (including any attachments) may contain confidential information, privileged material (including material protected by the solicitor-client or other applicable privileges), or constitute non-public information. Any use of this information by anyone other than the intended recipient is prohibited. If you have received this transmission in error, please immediately reply to the sender and delete this information from your system. Use, dissemination, distribution, or reproduction of this transmission by unintended recipients is not authorized and may be unlawful. From chwei at blackberry.com Fri Dec 6 03:36:10 2013 From: chwei at blackberry.com (Charles Wei) Date: Fri, 6 Dec 2013 02:36:10 +0000 Subject: [Qtwebengine] Quick Download API In-Reply-To: References: Message-ID: <53240CAA68C45847ADD1795C0ADFB8C2856D41EF@XMB101SIN.rim.net> I've created a trello card at: https://trello.com/c/kAFUyoHA/142-download-api-discussion for this. Let's decide the API so that we can move forward. Regards --Charles From: Arvid Nilsson Sent: Thursday, December 05, 2013 6:13 PM To: qtwebengine at qt-project.org Cc: Charles Wei; michael.bruning at digia.com Subject: Quick Download API Hi there! For full backward compatibility, widget flavor of QtWebEngine might benefit from a QNetworkAccessManager shim on top of the Chromium HTTP stack, and using the regular QtNetwork types to manage downloads. For QML, we would like to start discussion on how a QML-friendly download API could look like. Requirements courtesy of cswei: 1. to control the download (stop , resume, pause, cancel, etc) 2. To get the download state notification ( progress, failure, finished, etc) 3. To initiate a download , like anilsson says: user press-hold on a link/image, and selects "download" to download a resource 4. Give the application/user the opportunity to specify the storage location, the file name, etc. 5. Special download, like OMA download, download of DRM contents, etc. I believe all the methods/signals/slots from 1 and 2 could go into a WebEngineDownloadRequest creatable class. Perhaps there will be use for a WebEngineDownloadHandler attached object I think 3 should be an API on WebEngineView or WebEngineView.experimental: WebEngineView.download(WebEngineDownloadRequest). Also a signal for web-initiated downloads WebEngineView.onDownloadRequested (or possibly go straight to the WebEngineDownloadHandler). I think 4 could also be in the WebEngineDownloadRequest or WebEngineDownloadHandler All of the required functionality exists in the Chromium content APIs, we just need to figure out an API. What do you think? BR, /A --------------------------------------------------------------------- This transmission (including any attachments) may contain confidential information, privileged material (including material protected by the solicitor-client or other applicable privileges), or constitute non-public information. Any use of this information by anyone other than the intended recipient is prohibited. If you have received this transmission in error, please immediately reply to the sender and delete this information from your system. Use, dissemination, distribution, or reproduction of this transmission by unintended recipients is not authorized and may be unlawful. -------------- next part -------------- An HTML attachment was scrubbed... URL: From Simon.Hausmann at digia.com Fri Dec 27 19:01:46 2013 From: Simon.Hausmann at digia.com (Hausmann Simon) Date: Fri, 27 Dec 2013 18:01:46 +0000 Subject: [Qtwebengine] new QML window API Message-ID: <9160F3295FA8E24781968BBD40362991FEA429@IT-EXMB02-HKI.it.local> Hi, I keep on thinking about the new window QML API and how much I'd like it to be convenient, i.e. hide the process of stitching the newly created window component to engine-given web contents object entirey from the developer. I think I have found a solution: Generally speaking the webview can be created in two different contexts: 1) A new window is created by the user, or for example on start-up. In this context there's nothing for the implementation to adopt or do. 2) A new window is created in the context of an engine requesting/informing us to do so. Now if we want to allow the user to specify the environment the QML webview lives in as a QML component, then we are presented with an arbitrary QML type. It could be simple like this: Component { id: viewComponent WebView { newWindowComponent: viewComponent } } Or it could be deeply nested: Component { id: viewComponent SomeOtherType { ... } } SomeOtherType.qml: import QtQuick 2.0 import QtWebEngine 1.0 SomeCrazyItem { WebView { newWindowComponent: viewComponent // this works, but it's better to use an intermediate property } } In these two cases the user supplied component will eventually create one WebView. It is also possible that multiple WebViews are created, maybe each WebView also has a WebView for the web inspector or some meta-data. I'd like to classify the first two cases as very common and the latter as rare. I think the solution for the common case is simply to specify and determine the the context of creation, in the literal as well as in the QML sense. When a new instance is created with 'viewComponent", the QML context for the new type will be a child context of viewComponent's context. We can utilize this concept and whenever the WebView itself wants to create a new window with a given WebContents, we take the creation context of the view component, but inject an intermediate QQmlContext - the NewWindowContext. In this context we can put anything we want. We could do it on a QML property level, but I actually think it's easier to simply do that in C++. So when a WebView is created, in its componentComplete() implementation we can fetch the QML context that belongs do this instance and walk up the parent context chain until we either find the root context or a NewWindowContext. If the latter, then we can extract all the data we need for a successful WebContents adoption. That's entirely transparent to the user of the API. In the rare case where somebody specifies multiple WebView instances, we need an API for the developer to specify which WebView in the component shall be the primary one for new window content, for example through a property that indicates whether the WebView should adopt web contents or not. The resulting API makes the common case intuitive and trivial: The component specified must have a WebView _somewhere_ in its object hierarchy and it'll automatically be picked up and used for the context of newly created windows. The rare case we can make possible by requiring a little bit of help from the user. In addition to all this we can of course still have informational signals about newly created windows, etc. - but they don't come with any contractual obligations :) I've hacked up a prototype below that demonstrates the concept. Right now it uses a dedicated QQmlContext for each new-window created WebView, but using an incubator we could also avoid the "overhead" and get rid of the dummy context I think. Let me know what you think :) Simon #include class NewWindowContext : public QQmlContext { Q_OBJECT public: NewWindowContext(QQmlContext *parentContext) : QQmlContext(parentContext) , handle(0) {} // Use QExplicitlySharedDataPointer in real version :) void *handle; }; class WebView : public QObject, public QQmlParserStatus { Q_OBJECT Q_INTERFACES(QQmlParserStatus) Q_PROPERTY(QQmlComponent* newWindowComponent READ newWindowComponent WRITE setNewWindowComponent) public: WebView(); void setNewWindowComponent(QQmlComponent *comp) { m_newWindowComponent = comp; } QQmlComponent *newWindowComponent() const { return m_newWindowComponent; } Q_INVOKABLE void createNewWindow(); virtual void classBegin() {} virtual void componentComplete(); private: QQmlComponent *m_newWindowComponent; }; WebView::WebView() : m_newWindowComponent(0) { qDebug() << "WebView::WebView()"; } void WebView::createNewWindow() { Q_ASSERT(m_newWindowComponent); QQmlContext *parentContext = m_newWindowComponent->creationContext(); if (!parentContext) parentContext = qmlContext(this); // ### can this happen?? if (!parentContext) { QQmlEngine *engine = qmlEngine(this); Q_ASSERT(engine); parentContext = engine->rootContext(); } NewWindowContext *newContext = new NewWindowContext(parentContext); newContext->handle = this; // Or anything, really :) m_newWindowComponent->create(newContext); } void WebView::componentComplete() { QQmlContext *context = qmlContext(this); void *handle = 0; while (context) { if (NewWindowContext *newWindowContext = qobject_cast(context)) { qSwap(newWindowContext->handle, handle); break; } context = context->parentContext(); } if (handle) qDebug() << "WebView created from another WebView!" << handle; else qDebug() << "Standalone WebView complete"; } int main(int argc, char **argv) { QCoreApplication app(argc, argv); QQmlEngine engine; qmlRegisterType("TestWebEngine", 1, 0, "WebView"); QQmlComponent doc(&engine); doc.setData("" "import QtQml 2.0\n" "import TestWebEngine 1.0\n" "QtObject {\n" " id: root\n" " property string test: 'Hello World'\n" "\n" " property Component factory: Component {\n" " id: viewComponent\n" "\n" " WebView {\n" " newWindowComponent: viewComponent\n" " }\n" " }\n" "\n" " property QtObject initialWebView: factory.createObject();\n" "}", QUrl()); QScopedPointer root(doc.create()); if (!root) { qDebug() << doc.errors().first().toString(); return 1; } QObject *initialView = qvariant_cast(root->property("initialWebView")); QMetaObject::invokeMethod(initialView, "createNewWindow"); return 0; } #include "main.moc"