Search code examples
qtqtwebkit

Override HTTP Error page in QtWebkit


I would like to display an error page in a QWebView. For example if the server returns a 404 Error the QWebView should display a its own custom 404 Error instead of the one sent from the server.

I use the QWebPage::extension to handle error conditions and it works well for Network Errors. However if the server returns an error 404 and at the same time returns an error page, this page is displayed and the QWebPage::extension method is never called.

Is there a way to force QtWebKit to invoke the error handler and override the server error page?


Solution

  • One note, if you replace mainFrame content in handleNetworkFinished() slot you may see your error page instead of loaded page if network errors occurred with the page elements (like external images or scripts).

    Another option would be re-implementing QWebPage::extension() and QWebPage::supportsExtension(), in which case QT Webkit will call your implementation of extension() for page errors and replace page content with the page you provided, like:

    class WebPage : public QWebPage
    {
      Q_OBJECT
    public:
      WebPage(QObject *parent = 0);
      bool extension(Extension extension,
                     const ExtensionOption *option,
                     ExtensionReturn * output);
      bool supportsExtension(Extension extension) const;
    };
    
    bool WebPage::extension(Extension extension,
                            const ExtensionOption *option,
                            ExtensionReturn * output)
    {
      if(!option || !output) {
          return false;
      }
      if(extension == QWebPage::ErrorPageExtension) {
        const ErrorPageExtensionOption *errOption =
               static_cast<const ErrorPageExtensionOption*>(option);
        QString errPage;
        errPage = "<html><body><h1>";
        errPage += "Page loading error, URL: ";
        errPage += errOption->url.toString();
        errPage += "</h1><h3>Error occurred in the ";
        switch (errOption->domain) {
          case QWebPage::QtNetwork:
            errPage += "QT network layer, code is: ";
            break;
          case QWebPage::Http:
            errPage += "HTTP layer, HTTP error code is: ";
            break;
          case QWebPage::WebKit:
            errPage += "WebKit internals, error code is: ";
            break;
          default:
            errPage += "Unknown domain, error code is: ";
        }
        errPage += errOption->error;
        errPage += "</h3><h4><br>Error text: ";
        errPage += errOption->errorString;
        errPage += "</h4></body></html>";
        ErrorPageExtensionReturn *errReturn =
                                    static_cast<ErrorPageExtensionReturn*>(output);
        errReturn->baseUrl = errOption->url;
        errReturn->content = errPage.toUtf8();
        // errReturn->contentType = "text/html"
        // errReturn->encoding = "UTF-8"; // these values are defaults
        return true;
      }
      return false;
    }
    
    bool WebPage::supportsExtension(Extension extension) const
    {
      if(extension == QWebPage::ErrorPageExtension) {
        return true;
      }
      return QWebPage::supportsExtension(extension);
    }