2

Trying to use QML WebEngineView + WebChannel (Qt 5.15), but when running the videoTime script, I get

js: Uncaught ReferenceError: QWebChannel is not defined

Here is a reproducible example

import QtQuick 2.15
import QtQuick.Window 2.15
import QtWebEngine 1.11
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtWebChannel 1.15

Window {
    id: root
    width: 960
    height: 960
    visible: true
    title: qsTr("webengineexample")

    Shortcut {
        sequence: StandardKey.Quit
        onActivated: {
            Qt.quit()
        }
    }

    property string httpAcceptLanguage: "en-US"

    QtObject{
        id: internals

        property string script_videoTime: "
            setTimeout(function()
            {
                var backend;
                new QWebChannel(qt.webChannelTransport, function (channel) {
                    backend = channel.objects.backend;
                });

                ytplayer = document.getElementById('movie_player');
                backend.videoPosition = ytplayer.getCurrentTime();
                backend.videoDuration = ytplayer.getDuration();
            }, 100);
        "
    }

    QtObject {
        id: timePuller

        // ID, under which this object will be known at WebEngineView side
        WebChannel.id: "backend"

        property real videoPosition: 0
        property real videoDuration: 0

        onVideoDurationChanged: {
            console.log("VideoDuration ", videoDuration)
            console.log("VideoPosition ", videoPosition)
        }
    }

    WebChannel {
        id : web_channel
        registeredObjects: [timePuller]
    }

    WebEngineView {
        id: webEngineView
        anchors.fill: parent

        webChannel: web_channel
        userScripts: [
            WebEngineScript {
                injectionPoint: WebEngineScript.Deferred
                name: "QWebChannel"
                sourceUrl: "qrc:///qtwebchannel/qwebchannel.js"
            }
        ]

        // The following works
        profile {
            httpAcceptLanguage: root.httpAcceptLanguage
            httpCacheType: WebEngineProfile.MemoryHttpCache
            cachePath: "/tmp/webengineexample/customprofile/cache"
            persistentStoragePath: "/tmp/webengineexample/customprofile/data"
            persistentCookiesPolicy: WebEngineProfile.ForcePersistentCookies
            storageName: "customprofile"
        }

        settings {
            autoLoadImages: true
            dnsPrefetchEnabled: false
        }
        url: "https://youtube.com"
//        url: "https://ping.eu"
    }

    Button {
        id: timeDriver
        anchors {
            top: parent.top
            left: parent.left
        }
        text: "getTime"
        onClicked: {
                webEngineView.runJavaScript(internals.script_videoTime)
        }
    }
}

Not sure what I'm doing wrong, but I found https://forum.qt.io/topic/64638/inject-qwebchannel-into-an-https-page suggesting that it might not work with HTTPS pages. Unfortunately, I don't have a developer-build and I see no such error.

Update: I tested this with a developer build, and i don't get that HTTPS-related error.

Update: I also tried to replace userScripts with the following, and I'm getting a segfault

        userScripts: [
            {
                name: "QWebChannel",
                sourceUrl: Qt.resolvedUrl("qrc:/qtwebchannel/qwebchannel.js"),
                injectionPoint: WebEngineScript.DocumentCreation,
                worldId: WebEngineScript.MainWorld
            }
        ]
Pa_
  • 641
  • 1
  • 5
  • 17
  • 1
    Is it possible to put your code on GitHub so that the project can be easily tested? – Parisa.H.R Oct 30 '22 at 01:51
  • what is `"qrc:///qtwebchannel/qwebchannel.js"` file? – Parisa.H.R Oct 30 '22 at 09:04
  • It is a file that is supposed to be embedded into the Qt webchannel module. I now updated the github project to make it list the content of qrc, and i get "":/qtwebchannel/qwebchannel.js"" among others, so it seems the file is available at said url – Pa_ Oct 30 '22 at 09:15
  • It's been a while since I last used this, but I think you are supposed to include the `qwebchannel.js` file from within the web page you are trying to display, not inject it from the browser. – SteakOverflow Oct 30 '22 at 14:14

1 Answers1

1

After a lot more googling and poking, the solution seems to be changing the above code with

        userScripts: [
            WebEngineScript {
                injectionPoint: WebEngineScript.DocumentCreation
                name: "QWebChannel"
                worldId: WebEngineScript.MainWorld // was supposed to be default..
                sourceUrl: "qrc:/qtwebchannel/qwebchannel.js"
            }
        ]

And then, the script itself would spit a different error, requiring to be modified as

        property string script_videoTime: "
            var backend;
            new QWebChannel(qt.webChannelTransport, function (channel) {
                backend = channel.objects.backend;
            });
            setTimeout(function()
            {
                ytplayer = document.getElementById('movie_player');
                backend.videoPosition = ytplayer.getCurrentTime();
                backend.videoDuration = ytplayer.getDuration();
            }, 100);
        "

With these two changes the correct values are printed in the console.

Pa_
  • 641
  • 1
  • 5
  • 17