WebView, WebEngine CORS headers and file loading in SFOS >= 4.4

@flypig had given me a heads up for the more restrictive CORS rules as of 4.4. To keep it to the point, to load local resources in a WebView:

    WebView {
        /* This will probably be required from 4.4 on. */
        Component.onCompleted: {
           /* disable ALL
            WebEngineSettings.setPreference("security.disable_cors_checks", true, WebEngineSettings.BoolPref) 
            OR */
            WebEngineSettings.setPreference("security.fileuri.strict_origin_policy", false, WebEngineSettings.BoolPref)
        }
        id: webView
        anchors.fill: parent
        url: "../mah/index.html"
    }

WebEngineSettings requires
import Sailfish.WebEngine 1.0

4 Likes

This should go to the documentation as well

And I should finally get to forking the sailfish wiki :slight_smile:

related: Bug - Documentation is not a tree but a forest

1 Like

Ah, yes! And as you point out the Community news piece from @flypig should become documentation!

Let’s write this down to the Browser | Sailfish OS Documentation or Working with Browser | Sailfish OS Documentation as well. Thank you @poetaster .

1 Like

I think it belongs here:

I’ll make a PR as soon as I get around to it…!

Correct and actually I have already written short paragraph there: “Loading and using local resources”. Certainly improvement PRs are welcome.

2 Likes

This PR updates the docs with some more detail about the different potential approaches (including referencing your nice Python example @poetaster).

Any comments or suggestions for improving it would be appreciated.

1 Like

Er, ‘my’ nice python example was cribbed from @martyone 's python example (which happened to implement a thread model) and is, of course, mostly your code :slight_smile: and props to @nephros !

I’ve always admired you clear and comprehensive deep dives in the newsletters and have benefited from them, a great deal. I’m just really happy if I’ve contributed to that! Thanks!

2 Likes

Anyone have a hint on how to get images to load whose URIs are in a HTML document which has been loaded with loadHtml()?

No amount of setting moz prefs, or adding CSP headers, or specifying <base> or anything seems to work.

loadHtml causes the url to be data:text/html, I guess that might cause issues?

The data is base64 encoded, you need to decode it first, and only then, you will be able to render these with image renderer.

Are you trying to load them outside of browser context? Not sure if I guet your use case here.

1 Like

Nono, I have a backend which spits out a HTML string. That HTML contains regular <img src="foo.png" /> elements.
The image files lie in ~/.cache/foo/bar.

I use WebView::loadHtml to display the html string which works fine. Only the images are not displayed, no matter what I do.

Using MOZ_LOG magic I can see the images are found, it begins to load them, and finally

D/imgRequest [this=7d4907cac0] imgLoader::LoadImage -- AsyncOpen() failed: 0x805303f4

Where afaics 0x805303f4 == NS_ERROR_DOM_BAD_URI is an error due to CORS/CSP denying the load.

That’s not necessary CORS though. IIUC you are loading local resources from a disk / memory, thus the engine enables protection against attacks that try to load resources from Internet in localhost/file contexts.

Exactly. And I would like to know how to turn this protection off.

 <meta http-equiv="Content-Security-Policy" content="img-src \'self\' filesystem: data:" />

Does not help. (and file: is not a valid source scheme for CSP.)

<base href="file://' + myCacheDir + "/" + '" />

Does not help.

None of these help:

WebEngineSettings.setPreference("security.fileuri.strict_origin_policy", false, WebEngineSettings.BoolPref)
WebEngineSettings.setPreference("security.csp.enable", false, WebEngineSettings.BoolPref)
//WebEngineSettings.setPreference("security.disable_cors_checks", true, WebEngineSettings.BoolPref)
//WebEngineSettings.setPreference("security.mixed_content.block_active_content", false, WebEngineSettings.BoolP
//WebEngineSettings.setPreference("security.mixed_content.block_display_content", false, WebEngineSettings.Bool
//WebEngineSettings.setPreference("security.mixed_content.upgrade_display_content.image", false, WebEngineSetti
//WebEngineSettings.setPreference("privacy.file_unique_origin", false, WebEngineSettings.BoolPref)

Can you please supply a the context html which includes the js to load the consequent html via the loadHtml. why are you doing this :slight_smile:

There is no context html or js.

I get a string, from a QML plugin. That string is HTML. This I pass to Sailfish.WebView, calling its loadHtml() method.
WebView renders the page (sans images).

I didn’t write the QML plugin, merely using its output.

Basically

CustomThing {
  onContentChanged: web.loadHtml(content)
}
WebView { id: web
}

Code is here, bit messy right now but it’s WIP:

I’m not sure I understand why, exactly, but, you have some cors settings being injected via meta tags:

  <meta http-equiv="Content-Security-Policy" content="img-src \'self\' https://www.projectaon.org/" />

That looks like it may be at cross purposes?

As a workaround I now (i.e. the current git code) fall back to loading the images from an online source.
Makes them work but the app is kinda supposed to work offline mostly.

Not sure whether the CSP meta line is required for this, but AFAICS it’s not wrong.

I still would prefer accessing the local files instead, and as I said no amount of trickery seems to enable this.

Maybe I’ll hack the backend to read the image files and insert data: URIs instead of file names, but this seems unnecessarily complicated and superfluous.

1 Like

It ‘could’ be that the images are not being found. You could load an html shim to make sure that images relative to the ‘document root’ are found. I have one example that looks like this:

pages/FirstPage.qml

     WebView {
         Component.onCompleted: {
             WebEngineSettings.setPreference("security.fileuri.strict_origin_policy", false, WebEngineSettings.BoolPref)
         }
         id: webView
         anchors.fill: parent
         url: "../mah/index.html"
     }

ham/index.html all assets relative paths and javascript loader:

href="assets/app/

and same directory

<style>@font-face{font-family:Kulim Park;font-style:normal;font-weight:400;src:url(kulim-park-v4-latin-ext_latin-regular.328c0ac02dbbd95a.eot);

It took me a while to adjust all the paths …

1 Like