How work with QWebEngineUrlRequestJob?



  • I have inherited from QWebEngineUrlSchemeHandler. Redefined method requestStarted(QWebEngineUrlRequestJob *request)
    After I try to call QWebEngineUrlRequestJob::reply
    for example

    void CustomUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *request)
    {
    qDebug() << "CustomUrlSchemeHandler::requestStarted -->>> " << request->requestUrl();

    QMimeDatabase HelpViewer;
    QMimeType mt = HelpViewer.mimeTypeForUrl(request->requestUrl());
    const QString mimeType = mt.name();
    QByteArray arr = QString::fromStdString("<html><body>Hello world</body></html>").toUtf8();
    QBuffer *buffer = new QBuffer(&arr, this);
    buffer->open(QIODevice::ReadOnly);
    request->reply(mimeType.toLatin1(), buffer);
    
    return;
    

    }
    But the program crashes.
    pls see more detail - http://stackoverflow.com/questions/33933958/qt-5-6-beta-qtwebengine-how-work-with-qwebengineurlrequestjob



  • The reason of the crash is not obvious, because Qt documentation is not clear on the details how QWebEngineUrlSchemeHandler should be implemented.

    Your program crashes because QWebEngineUrlRequestJob::reply() uses the buffer parameter later, out of the caller's scope, probably from a different thread. The local variable QByteArray arr which you declared on the stack (and used as backing storage for the buffer) will be out of scope by then and QWebEngine will be accessing an invalid pointer.

    Another thing is, reply() does not take ownership of the passed buffer object and never deletes it. This introduces a memory leak. You cannot simply delete it right after calling reply() for the same reason as above. To ensure the buffer object is deleted when no longer needed, connect the request's destroyed() signal to the buffer's deleteLater() slot.

    Here is a complete working and leak-free example:

    void CustomUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *request)
    {
        QBuffer *buffer = new QBuffer;
        connect(request, SIGNAL(destroyed()), buffer, SLOT(deleteLater()));
    
        buffer->open(QIODevice::WriteOnly);
        buffer->write("<html><body>Hello world!</body></html>");
        buffer->close();
    
        request->reply("text/html", buffer);
    }
    

    Note: You don't need to use a QByteArray at all. The default constructor for QBuffer allocates its own storage.



  • @treem
    Can you tell me how to work with QWebEngineUrlSchemeHandler?

    I have inherited from QWebEngineUrlSchemeHandler and QWebEnginePage,and In Constructor of WebEnginePage, I wrote:

     WebEngineUrlSchemeHandler *weush = new WebEngineUrlSchemeHandler;
     profile->installUrlSchemeHandler(QByteArray("qthelp:"),weush);
        
    

    but it dose not work.



  • just remove the ':' in your scheme name:
    profile->installUrlSchemeHandler(QByteArray("qthelp"),weush);


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.