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
            }
        ]
4
  • 1
    Is it possible to put your code on GitHub so that the project can be easily tested? Commented Oct 30, 2022 at 1:51
  • what is "qrc:///qtwebchannel/qwebchannel.js" file? Commented Oct 30, 2022 at 9: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 Commented Oct 30, 2022 at 9: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. Commented Oct 30, 2022 at 14:14

1 Answer 1

2

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.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.