Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-101670

Javascript ArrayBuffer not transferrable through QWebChannel into a QByteArray.

    XMLWordPrintable

Details

    • Bug
    • Resolution: Unresolved
    • P2: Important
    • None
    • 6.2.0
    • WebChannel
    • None
    • Linux/X11

    Description

      There is an inconsistency in QWebChannel for interfacing between Javascript and Qt types. In short:

      This seems to be due to a lack of programming, as this error is produced:

      Could not convert argument QJsonValue(object, QJsonObject()) to target type QByteArray .
      

      I have filed this bug report so that this behaviour is fixed. For the mean time, I am going to have to find a workaround, because I am unable to figure out how to transfer an ArrayBuffer through QWebChannel into c++. I have tried using QVariant and QJsonValue, with no luck. 

       

      To demonstrate and reproduce what I am trying to do, first create this basic class that will expose Q_INVOKABLE functions in javascript:

      #ifndef QWEBCHANNELOBJECT_H
      #define QWEBCHANNELOBJECT_H
      
      #include <QObject>
      
      class QWebChannelObject : public QObject
      {
      	Q_OBJECT
      public:
      	explicit QWebChannelObject( QObject *parent = nullptr ) : QObject(parent) {}
      
      	QByteArray byteArray() const { return m_ByteArray; }
      	QString    string   () const { return m_String   ; }
      
      	Q_INVOKABLE void setByteArray( QByteArray byteArray ) { m_ByteArray = byteArray; emit byteArrayChanged(); };
      	Q_INVOKABLE void setString   ( QString    string    ) { m_String    = string   ; emit stringChanged   (); };
      
      signals:
      	void byteArrayChanged();
      	void stringChanged   ();
      
      private:
      	QByteArray m_ByteArray;
      	QString    m_String   ;
      };
      
      #endif // QWEBCHANNELOBJECT_H
      
      

       
      Next, the following block of code can be inserted into main():

      /* Load Url */
      QWebEngineView wev;
      QUrl url( "https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png" );
      {
      	QEventLoop waitForLoad;
      	QObject::connect   ( wev.page(), &QWebEnginePage::loadFinished, &waitForLoad, &QEventLoop::quit );
      	wev.load(url);
      	waitForLoad.exec();
      	QObject::disconnect( wev.page(), &QWebEnginePage::loadFinished, &waitForLoad, &QEventLoop::quit );
      }
      
      /* Setup Web Channel */
      QWebChannel wc;
      QWebChannelObject wco;
      {
      	QFile f_QWebChannel( ":/qtwebchannel/qwebchannel.js" );
      	f_QWebChannel.open( QIODevice::ReadOnly );
      	QString j_QWebChannel = f_QWebChannel.readAll();
      
      	wco.setObjectName( "wco" );
      	wc.registerObject( wco.objectName(), &wco );
      	wev.page()->setWebChannel(&wc);
      	wev.page()->runJavaScript( j_QWebChannel );
      }
      
      /* Try and set ByteArray and QString */
      QEventLoop waitForByteArray;
      {
      	QObject::connect( &wco, &QWebChannelObject::byteArrayChanged, &waitForByteArray, &QEventLoop::quit );
      	wev.showNormal();
      
      	wev.page()->runJavaScript( QString(R"(
      	window.webChannel = new QWebChannel( qt.webChannelTransport, function( channel ){
      		var %1 = channel.objects.%2;
      
      		fetch( "%3" )
      		.then( res => res.blob() )
      		.then( async(blob) => {
      			const byteArray = await blob.arrayBuffer();
      			const string    = await blob.text();
      			%1.setString   ( string    ); // Works
      			%1.setByteArray( byteArray ); // Produces error
      		});
      	});
      	)")
      		.arg( wco.objectName() )
      		.arg( wc.registeredObjects().key(&wco) )
      		.arg( url.toString() ) );
      	waitForByteArray.exec();
      	QObject::disconnect( &wco, &QWebChannelObject::byteArrayChanged, &waitForByteArray, &QEventLoop::quit );
      }
      
      QString     s = wco.string   ();
      QByteArray ba = wco.byteArray();
      qDebug() << s.size() << ba.size();
      

      Running the above code will produce the following error:

      Could not convert argument QJsonValue(object, QJsonObject()) to target type QByteArray .
      

      However, if this line is removed from the javascript:

      %1.setByteArray( byteArray ); // Produces error
      

      It works fine, meaning that I can transfer string data through QWebChannel, but not a byte array.

       

       

       

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            milianw Milian Wolff
            kill.animals Kill Animals
            Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes