Results 1 to 3 of 3

Thread: QtWebkit problems with custom QNetworkAccessManager+QNetworkReply

  1. #1
    Join Date
    Mar 2010
    Posts
    10
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default QtWebkit problems with custom QNetworkAccessManager+QNetworkReply

    Hi

    I have run into a mysterious issue with QNetworkAccessManager and/or QtWebkit. Using qt 4.6.2 with vs2008.

    My app uses webkit to provide a user interface so the user can navigate through and display app-specific data structure held within the app's memory.

    To do this the app has a very similar structure to the 'fancybrowser' sample included with Qt, but to which I added a custom QNetworkAccessManager which detects url's that use a private scheme (I used "myp:") and passes them to my own QNetworkReply derivation which knows how to supply the app specific html. All other urls are passed to the QNetworkAccessManager base class for default handling. This is exactly the same code structure as described in a recent Qt Quarterly article describing these techniques.

    This appears to work however there is a problem. I have found that whenever the webview is displaying html obtained from an app-private url e.g myp:/fred, any image within the returned html whose source url is not http based just does not get displayed. Why is this?

    Here's a more specific description of the problem.

    Lets say I create a trivial bit of html which just displays three different images using <img> tags. The first image is stored locally and referenced with a file: based url. The second image is built into the app's binary as a Qt resource and is referenced with a qrc: url. The final image is taken from the net and so has a http: url. I store this html snippet in a local file C:\test.html:

    <html><body>
    FROM file:///c:/Dalmatian.jpg:<br><img src='file:///c:/Dalmatian.jpg'><br>
    FROM qrc:/5453039.jpg:<br><img src='qrc:/5453039.jpg'><br>
    FROM http://www.google.co.uk/intl/en_uk/images/logo.gif:<br>
    <img src='http://www.google.co.uk/intl/en_uk/images/logo.gif'>
    </body></html>
    Using my modded fancybrowser I can display this by entering "file:///c:/test.html" in the url box and all is fine, with the 3 images displaying as expected. Here's a screenshot (like my classy images!):



    BUT if I arrange for the precise same html snippet to be returned by my own QNetworkReply class, in response to entering an app-private url starting "myp:", what I find is that the only image that displays is the one with the http: url; the images with file: and qrc: urls just dont appear. Here's the screenshot after I put 'myp:' in the url bar. Note images 1+2 missing.



    Why is this? What is going on? Is there a workaround/fix? Why is it that the provider of the html seems to affect how QtWebkit displays it?

    Thanks.

    Here is the relevant code. Note I can reproduce this problem by taking a copy of the qt fancybrowser sample, adding in the code below. Oh and I bind the jpg image referred to (using the qrc: url) into the app by adding a Q_INIT_RESOURCE line to main(). But that is all. No other changes.

    First the QNetworkAccessManager derivation which is virtually identical to the example code from a recent Qt Quarterly.

    Qt Code:
    1. // header
    2. #include <QNetworkAccessManager>
    3. class MyNetworkAccessManager : public QNetworkAccessManager
    4. {
    5. Q_OBJECT
    6.  
    7. public:
    8. MyNetworkAccessManager(QNetworkAccessManager *oldManager, QObject *parent = 0);
    9.  
    10. protected:
    11. QNetworkReply* createRequest(QNetworkAccessManager::Operation op,
    12. const QNetworkRequest &req, QIODevice *device);
    13. };
    14.  
    15. // code
    16. MyNetworkAccessManager::MyNetworkAccessManager(
    17. QNetworkAccessManager *oldManager, QObject *parent /*= 0*/)
    18. : QNetworkAccessManager(parent)
    19. {
    20. setCache(oldManager->cache());
    21. setCookieJar(oldManager->cookieJar());
    22. setProxy(oldManager->proxy());
    23. setProxyFactory(oldManager->proxyFactory());
    24. }
    25.  
    26. QNetworkReply* MyNetworkAccessManager::createRequest(
    27. QNetworkAccessManager::Operation op, const QNetworkRequest &req,
    28. QIODevice *device)
    29. {
    30. if ((op == QNetworkAccessManager::GetOperation ||
    31. op == QNetworkAccessManager::HeadOperation) && req.url().scheme() == "myp")
    32. return new MyNetworkReply(this, req, op);
    33. // defer to default:
    34. return QNetworkAccessManager::createRequest(op, req, device);
    35. }
    To copy to clipboard, switch view to plain text mode 

    The code to install this network manager is placed in the main window class immediately after creation of the QWebView:
    Qt Code:
    1. .
    2. .
    3. view = new QWebView(this);
    4. // MYCODE BEGINS
    5. QNetworkAccessManager *oldManager = view->page()->networkAccessManager();
    6. MyNetworkAccessManager *newManager = new MyNetworkAccessManager(oldManager, this);
    7. view->page()->setNetworkAccessManager(newManager);
    8. / MYCODE ENDS
    9. .
    10. .
    To copy to clipboard, switch view to plain text mode 

    The QNetworkReply class. Here I have cut it down to its barest minimum, all this does is setup a reply containing a fixed snippet of html above. It just sticks the html in a QByteArray and set up readData/bytesAvailable etc to access this.

    Qt Code:
    1. class MyNetworkReply : public QNetworkReply
    2. {
    3. Q_OBJECT
    4.  
    5. public:
    6. MyNetworkReply(QObject *parent, const QNetworkRequest &req,
    7. const QNetworkAccessManager::Operation op)
    8. : QNetworkReply(parent)
    9. {
    10. setRequest(req);
    11. setUrl(req.url());
    12. setOperation(op);
    13. QNetworkReply::open(QIODevice::ReadOnly | QIODevice::Unbuffered);
    14.  
    15. QString string = "<html><body>FROM MyNetworkReply:<br>\
    16. FROM file:///c:/Dalmatian.jpg:<br><img src='file:///c:/Dalmatian.jpg'><br>\
    17. FROM qrc:/5453039.jpg:<br><img src='qrc:/5453039.jpg'><br>\
    18. FROM http://www.google.co.uk/intl/en_uk/images/logo.gif:<br>\
    19. <img src='http://www.google.co.uk/intl/en_uk/images/logo.gif'>\
    20. </body></html>\n";
    21.  
    22. m_content = string.toUtf8();
    23. m_lOffset = 0;
    24.  
    25. setHeader(QNetworkRequest::ContentTypeHeader,
    26. QVariant("text/html; charset=UTF-8"));
    27. setHeader(QNetworkRequest::ContentLengthHeader,
    28. QVariant(m_content.size()));
    29.  
    30. QMetaObject::invokeMethod(this, "metaDataChanged",
    31. Qt::QueuedConnection);
    32. QMetaObject::invokeMethod(this, "downloadProgress",
    33. Qt::QueuedConnection, Q_ARG(qint64, m_content.size()), Q_ARG(qint64, m_content.size()));
    34. QMetaObject::invokeMethod(this, "readyRead",
    35. Qt::QueuedConnection);
    36. QMetaObject::invokeMethod(this, "finished",
    37. Qt::QueuedConnection);
    38. }
    39. void abort() { QNetworkReply::close(); }
    40. qint64 bytesAvailable() const { return m_content.size() - m_lOffset; }
    41. bool isSequential() const { return true; }
    42.  
    43. protected:
    44. qint64 readData(char* pData, qint64 lMaxSize)
    45. {
    46. if (m_lOffset >= m_content.size())
    47. return -1;
    48.  
    49. qint64 lCount = qMin(lMaxSize, m_content.size() - m_lOffset);
    50. memcpy(pData, m_content.constData() + m_lOffset, lCount);
    51. m_lOffset += lCount;
    52. return lCount;
    53. }
    54.  
    55. private slots:
    56.  
    57. private:
    58. QByteArray m_content;
    59. qint64 m_lOffset;
    60. };
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jun 2010
    Posts
    102
    Thanks
    3
    Qt products
    Qt4 Qt/Embedded Qt Jambi PyQt3 PyQt4
    Platforms
    MacOS X Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: QtWebkit problems with custom QNetworkAccessManager+QNetworkReply

    are you running on Windows ?, i also error like you, but it on Linux embedded
    Contact: Skype: sonnh89
    Yahoo: nhs_0702@yahoo.com

    Liên hệ SKype: sonnh89

  3. #3
    Join Date
    Dec 2010
    Posts
    6
    Thanked 2 Times in 1 Post
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60

    Default Re: QtWebkit problems with custom QNetworkAccessManager+QNetworkReply

    Qt Code:
    1. QWebSecurityOrigin::addLocalScheme("myp");
    To copy to clipboard, switch view to plain text mode 
    For more info, see QWebSecurityOrigin class in documentation.

Similar Threads

  1. Custom qNetworkAccessManager for WebView
    By xeento in forum Qt Programming
    Replies: 2
    Last Post: 25th May 2010, 05:22
  2. Replies: 2
    Last Post: 9th January 2010, 03:03
  3. Problems with QNetworkAccessManager
    By pfid in forum Qt Programming
    Replies: 1
    Last Post: 18th November 2009, 20:51
  4. Custom QNetworkReply for WebView
    By victor.yacovlev in forum Qt Programming
    Replies: 0
    Last Post: 1st April 2009, 14:32
  5. Deploying on Windows problems with QtWebKit
    By josepvr in forum Installation and Deployment
    Replies: 3
    Last Post: 8th October 2008, 13:00

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.