Add an API to allow defining custom URL scheme delegates

Bug #1260016 reported by Olivier Tilloy
30
This bug affects 6 people
Affects Status Importance Assigned to Milestone
Oxide
Fix Released
High
Chris Coulson
oxide-qt (Ubuntu)
Fix Released
High
Unassigned
oxide-qt (Ubuntu RTM)
Fix Released
High
Unassigned

Bug Description

For feature parity with QtWebKit, the QML WebView needs a way to allow application developers to define custom URL scheme delegates (in QtWebKit, the property is 'experimental.urlSchemeDelegates', of type list).

Related branches

Olivier Tilloy (osomon)
Changed in oxide:
assignee: nobody → Chris Coulson (chrisccoulson)
David Barth (dbarth)
tags: added: desktop webapp-container
Revision history for this message
Dan Chapman  (dpniel) wrote :

Hey folks.

It would be great to add an additional feature request to this for support of multiple asynchronous requests per custom url scheme. QtWebkit only creates one QQuickNetworkReply per scheme which precludes the use of async requests altogether.

It would be awesome to see this available with Oxide so that the Trojita email client can move over to using oxide

Cheers

Dan

tags: added: appstore
Michael Hall (mhall119)
Changed in oxide:
status: New → Confirmed
Revision history for this message
Pat McGowan (pat-mcgowan) wrote :

Bumping the priority as this is part of the effort to remove qtwebkit shortly

Changed in oxide:
importance: Undecided → Critical
tags: added: rtm14
Changed in oxide-qt (Ubuntu):
status: New → Confirmed
importance: Undecided → Critical
Revision history for this message
Chris Coulson (chrisccoulson) wrote :

Before we even get to this - one fairly major thing that's currently missing is any support for delegating protocol schemes that can't be handled by Oxide to external apps - ie, clicking on a mailto link should open an email client. But it seems that this API is something else altogether - IIUC it allows applications to handle resource requests for specific URL protocols internally to the application (correct me if I'm wrong there).

It sounds like this would need to be implemented by using a URLRequestInterceptingJobFactory for the main URLRequestContext on each BrowserContext. This implies that the API would not be on the WebView in Oxide, but on the WebContext instead.

This would allow you to create a custom URLRequestJob for URL schemes that the application wants to handle. However, I'm not entirely sure yet how this would be exposed to or interact with QML as this all happens on Chromium's IO thread - this doesn't have a Qt event loop and you can't touch QML from there anyway.

So, this is going to need some very careful thought and the implementation is going to end up with some possibly fairly complex threading interactions. It's not going to be an insignificant amount of work

Revision history for this message
Pat McGowan (pat-mcgowan) wrote :

This is an example from how Dekko/Trojita is using this, perhaps we can recommend another approach:

http://bazaar.launchpad.net/~dpniel/dekko/trunk-1/view/head:/src/Ubuntu/qml/MessageView/HtmlPart.qml#L41

Michael pondered an override of the QNetworkAccessmanager

Revision history for this message
Dan Chapman  (dpniel) wrote :

@chris yes you understand correctly. Basically we use a custom QNetworkAccessManager to access message parts internally and externally to the app [1]. Which we use the UrlSchemeDelegates to bridge the gap between the webview and our custom QNAM.

Now getting the message parts individually isn't really an issue as we can just ask the model for the data for each part and chuck it through loadHtml and be done with it. but when we come to multi-part messages where for instance, an html part might contain a cid url [2] referencing another message part. I can't see how we can load these referenced parts within the message without the aid of the webview supporting our internal schemes.

IIUC and i'm not entirely familiar with the internals of oxide/chromium, but am i right in thinking that it actually doesn't interact with QNetworkAccessManager but has it's own internal http implementation and can't go through a QNetworkAccessManager? If that's correct then even our current method of returning a wrapped qnetworkreply or Mike's idea of overriding the QNAM is actually redundant in this use-case.

I'm not sure what the best approach here is. And all ideas will be greatly appreciated :-)

[1] http://bazaar.launchpad.net/~dpniel/dekko/trunk-1/view/head:/src/Imap/Network/MsgPartNetAccessManager.cpp
[2] https://tools.ietf.org/html/rfc2392

Revision history for this message
Chris Coulson (chrisccoulson) wrote :

From what you describe, it looks like we can't avoid fixing this bug. But I suspect that the API may look somewhat different to the one that's currently exposed by QtWebkit. I'm going to have a think about that today and try to come up with some ideas.

You're right too that Oxide doesn't make use of QNetworkAccessManager at all - it uses Chromium's networking stack

Changed in oxide:
status: Confirmed → In Progress
Changed in oxide-qt (Ubuntu):
status: Confirmed → In Progress
tags: added: touch-2014-09-18
tags: added: touch-2014-09-25
removed: touch-2014-09-18
Changed in oxide:
milestone: none → branch-1.3
Dan Chapman  (dpniel)
Changed in dekko:
status: New → Triaged
importance: Undecided → Critical
tags: added: touch-2014-10-09
removed: touch-2014-09-25
Dan Chapman  (dpniel)
Changed in dekko:
assignee: nobody → Dan Chapman (dpniel)
milestone: none → 0.3
Changed in oxide-qt (Ubuntu RTM):
status: New → In Progress
importance: Undecided → Critical
Revision history for this message
Jamie Strandboge (jdstrand) wrote :

Dropping priority to High. It was critical so we could remove qtwebkit from the image but there are other reasons beyond this bug on why qtwebkit won't be removed by 2014-10-09. If this lands by then, great, but if not, we'll land it as ota.

Changed in oxide-qt (Ubuntu RTM):
importance: Critical → High
Changed in oxide-qt (Ubuntu):
importance: Critical → High
Changed in oxide:
importance: Critical → High
tags: added: ota-1
removed: rtm14 touch-2014-10-09
Revision history for this message
Chris Coulson (chrisccoulson) wrote :

This is fixed with http://bazaar.launchpad.net/~oxide-developers/oxide/oxide.trunk/revision/787. Note that there are some significant differences between this and the equivalent qtwebkit API, notably:

- The API is on WebContext rather than WebView.

- You don't register individual handlers for responding to network requests. Instead, you set a list of custom URL schemes on WebContext.allowedExtraUrlSchemes, and then Oxide uses the QNetworkAccessManager provided by the QQmlEngine. To set a custom QNetworkAccessManager, you'll need to implement QQmlNetworkAccessManagerFactory and assign this to the QQmlEngine associated with the QQuickView that your webview is in. If you want to share the QNAM with other parts of the application, then you'll need to make sure it outlives the QQmlEngine.

- Oxide takes care of proxying the data from QNetworkAccessManager + QNetworkReply on the UI thread to Chromium's network stack on its IO thread (see http://bazaar.launchpad.net/~oxide-developers/oxide/oxide.trunk/view/head:/shared/base/oxide_cross_thread_data_stream.cc and http://bazaar.launchpad.net/~oxide-developers/oxide/oxide.trunk/view/head:/qt/core/browser/oxide_qt_url_request_delegated_job.cc). You don't need to implement this manually in the application.

- You can't override standard protocol schemes (http/https/ws/wss/file etc). This is deliberate for a few reasons:
a. Custom schemes need to interact with the UI thread, whereas using Chromium's network stack doesn't.
b. We can decide asynchronously on the UI thread whether to ignore SSL errors from Chromium's network stack. However, Qt requires that we call QNetworkReply::ignoreSslErrors from inside the slot connected to QNetworkReply::sslErrors, which means we can't respond asynchronously (we'd need to block the UI thread whilst the IO thread posts a task to the blocked UI thread for handling the error, which obviously isn't possible). This means that errors from custom handlers can't be integrated with the WebView.certificateError signal.
c. We can't really construct the HTTP response on the Chromium side without having access to the raw response header.

As you already implement a custom QNetworkAccessManager in dekko, this API should work for you without too much effort (and you can get rid of QQuickNetworkReplyWrapper).

Changed in oxide:
status: In Progress → Fix Released
Revision history for this message
Dan Chapman  (dpniel) wrote :

@Chris, This looks excellent! thanks for getting this together so quickly :-) I'll get onto this over the weekend, I'll come back to you if I hit any snags.

Dan Chapman  (dpniel)
Changed in dekko:
milestone: 0.3 → 0.4
Revision history for this message
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package oxide-qt - 1.3.3-0ubuntu1

---------------
oxide-qt (1.3.3-0ubuntu1) vivid; urgency=medium

  * Update to v1.3.3
    - Bump Chromium rev to 39.0.2171.42
    - Fix LP: #1260016 - Add support for application provided protocol
      handlers
    - Fix LP: #1301681 - Scroll the focused editable node in to view after
      a resize
    - Fix LP: #1337506 - Runtime abort with
      FATAL:texture_manager.cc(76)] Check failed: texture_count_ == 0u (1 vs. 0).
      Ensure that we keep the browser compositor GL context and associated
      resources alive as long as the Qt scenegraph holds the frontbuffer
    - Fix LP: #1377755 - Keyboard disappears when switching between text fields
    - Fix LP: #1290821 - WebView.loading is not false when receiving a LoadEvent
      with type == TypeStopped, so properties bound to this never receive an
      update. As "loading" and the main-frame document load events are delivered
      separately from blink, split this in to 2 signals
    - Fix LP: #1354382 - White line at bottom of viewport - fix rounding errors
      when calculating the view size in DIP which results in the view
      underflowing by a pixel in one axis and overflowing by a pixel in the
      other axis
    - Fix LP: #1221996 - Allow user scripts to be injected in to the main world
    - Expose redirect events to WebContextDelegateWorker
    - Fix LP: #1384460 - Delegate unhandled URL schemes to the system
    - Fix LP: #1386468 - Stop leaking V8 contexts

  [ Chris Coulson <email address hidden> ]
  * Add liboxideqtquick0 package
  * Refresh debian/patches/gross-hack-for-dual-ffmpeg-build.patch
  * Add libcups2-dev and libexif-dev build-deps, as the chromedriver build
    seems to pull them in. This is a temporary measure until we can figure
    out why

  [ Alexandre Abreu <email address hidden> ]
  * Add chromedriver to the packaging branch
 -- Chris Coulson <email address hidden> Thu, 23 Oct 2014 08:18:19 -0400

Changed in oxide-qt (Ubuntu):
status: In Progress → Fix Released
Revision history for this message
Launchpad Janitor (janitor) wrote :

This bug was fixed in the package oxide-qt - 1.3.4-0ubuntu0.14.10.1

---------------
oxide-qt (1.3.4-0ubuntu0.14.10.1) utopic-security; urgency=medium

  * Update to v1.3.4
    - see USN-2410-1
    - Bump Chromium rev to 39.0.2171.62
    - Fix LP: #1260016 - Add support for application provided protocol
      handlers
    - Fix LP: #1301681 - Scroll the focused editable node in to view after
      a resize
    - Fix LP: #1337506 - Runtime abort with
      FATAL:texture_manager.cc(76)] Check failed: texture_count_ == 0u (1 vs. 0).
      Ensure that we keep the browser compositor GL context and associated
      resources alive as long as the Qt scenegraph holds the frontbuffer
    - Fix LP: #1377755 - Keyboard disappears when switching between text fields
    - Fix LP: #1290821 - WebView.loading is not false when receiving a LoadEvent
      with type == TypeStopped, so properties bound to this never receive an
      update. As "loading" and the main-frame document load events are delivered
      separately from blink, split this in to 2 signals
    - Fix LP: #1354382 - White line at bottom of viewport - fix rounding errors
      when calculating the view size in DIP which results in the view
      underflowing by a pixel in one axis and overflowing by a pixel in the
      other axis
    - Fix LP: #1221996 - Allow user scripts to be injected in to the main world
    - Expose redirect events to WebContextDelegateWorker
    - Fix LP: #1384460 - Delegate unhandled URL schemes to the system
    - Fix LP: #1386468 - Stop leaking V8 contexts
    - Fix LP: #1375900 - GMail crashes when composing a message
    - Fix LP: #1391230 - Release the screen dim lock when the application
      becomes inactive

  [ Chris Coulson <email address hidden> ]
  * Add liboxideqtquick0 package
  * Refresh debian/patches/gross-hack-for-dual-ffmpeg-build.patch
  * Add libcups2-dev and libexif-dev build-deps, as the chromedriver build
    seems to pull them in. This is a temporary measure until we can figure
    out why

  [ Alexandre Abreu <email address hidden> ]
  * Add chromedriver to the packaging branch
 -- Chris Coulson <email address hidden> Mon, 17 Nov 2014 11:16:34 +0000

Changed in oxide-qt (Ubuntu RTM):
status: In Progress → Fix Released
Dan Chapman  (dpniel)
Changed in dekko:
status: Triaged → Fix Committed
Dan Chapman  (dpniel)
Changed in dekko:
status: Fix Committed → Fix Released
To post a comment you must log in.
This report contains Public information  
Everyone can see this information.

Other bug subscribers

Remote bug watches

Bug watches keep track of this bug in other bug trackers.