📄 qwebnetworkinterface.cpp
字号:
QWebNetworkInterface contains two virtual methods, addJob and cancelJob that have to be reimplemented when implementing your own networking layer. QWebNetworkInterface can by default handle the http, https, file and data URI protocols.*/static bool gRoutineAdded = false;static void gCleanupInterface(){ delete s_default_interface; s_default_interface = 0;}/*! Sets a new default interface that will be used by all of WebKit for downloading data from the internet.*/void QWebNetworkInterface::setDefaultInterface(QWebNetworkInterface *defaultInterface){ if (s_default_interface == defaultInterface) return; if (s_default_interface) delete s_default_interface; s_default_interface = defaultInterface; if (!gRoutineAdded) { qAddPostRoutine(gCleanupInterface); gRoutineAdded = true; }}/*! Returns the default interface that will be used by WebKit. If no default interface has been set, QtWebkit will create an instance of QWebNetworkInterface to do the work.*/QWebNetworkInterface *QWebNetworkInterface::defaultInterface(){ if (!s_default_interface) { setDefaultInterface(new QWebNetworkInterface); } return s_default_interface;}/*! Constructs a QWebNetworkInterface object.*/QWebNetworkInterface::QWebNetworkInterface(QObject *parent) : QObject(parent){ d = new QWebNetworkInterfacePrivate; d->q = this; if (!s_manager) s_manager = new QWebNetworkManager;}/*! Destructs the QWebNetworkInterface object.*/QWebNetworkInterface::~QWebNetworkInterface(){ delete d;}/*! This virtual method gets called whenever QtWebkit needs to add a new job to download. The QWebNetworkInterface should process this job, by first emitting the started signal, then emitting data repeatedly as new data for the Job is available, and finally ending the job with emitting a finished signal. After the finished signal has been emitted, the QWebNetworkInterface is not allowed to access the job anymore.*/void QWebNetworkInterface::addJob(QWebNetworkJob *job){ QString protocol = job->url().scheme(); if (protocol == QLatin1String("http") || protocol == QLatin1String("https")) { QWebNetworkManager::self()->addHttpJob(job); return; } // "file", "data" and all unhandled stuff go through here //DEBUG() << "fileRequest"; DEBUG() << "FileLoader::request" << job->url(); if (job->cancelled()) { d->sendFileData(job, 400, QByteArray()); return; } QUrl url = job->url(); if (protocol == QLatin1String("data")) { d->parseDataUrl(job); return; } int statusCode = 200; QByteArray data; QString path = url.path(); if (protocol == QLatin1String("qrc")) { protocol = "file"; path.prepend(QLatin1Char(':')); } if (!(protocol.isEmpty() || protocol == QLatin1String("file"))) { statusCode = 404; } else { // we simply ignore post data here. QFile f(path); DEBUG() << "opening" << QString(url.path()); if (f.open(QIODevice::ReadOnly)) { QHttpResponseHeader response; response.setStatusLine(200); job->setResponse(response); data = f.readAll(); } else { statusCode = 404; } } if (statusCode == 404) { QHttpResponseHeader response; response.setStatusLine(404); job->setResponse(response); } d->sendFileData(job, statusCode, data);}/*! This virtual method gets called whenever QtWebkit needs to cancel a new job. The QWebNetworkInterface acknowledge the canceling of the job, by emitting the finished signal with an error code of 1. After emitting the finished signal, the interface should not access the job anymore.*/void QWebNetworkInterface::cancelJob(QWebNetworkJob *job){ QString protocol = job->url().scheme(); if (protocol == QLatin1String("http") || protocol == QLatin1String("https")) QWebNetworkManager::self()->cancelHttpJob(job);}void QWebNetworkInterface::started(QWebNetworkJob* job){ Q_ASSERT(s_manager); s_manager->queueStart(job);}void QWebNetworkInterface::data(QWebNetworkJob* job, const QByteArray& data){ Q_ASSERT(s_manager); s_manager->queueData(job, data);}void QWebNetworkInterface::finished(QWebNetworkJob* job, int errorCode){ Q_ASSERT(s_manager); s_manager->queueFinished(job, errorCode);}/////////////////////////////////////////////////////////////////////////////WebCoreHttp::WebCoreHttp(QObject* parent, const HostInfo &hi) : QObject(parent), info(hi), m_inCancel(false){ for (int i = 0; i < 2; ++i) { connection[i].http = new QHttp(info.host, (hi.protocol == QLatin1String("https")) ? QHttp::ConnectionModeHttps : QHttp::ConnectionModeHttp, info.port); connect(connection[i].http, SIGNAL(responseHeaderReceived(const QHttpResponseHeader&)), this, SLOT(onResponseHeaderReceived(const QHttpResponseHeader&))); connect(connection[i].http, SIGNAL(readyRead(const QHttpResponseHeader&)), this, SLOT(onReadyRead())); connect(connection[i].http, SIGNAL(requestFinished(int, bool)), this, SLOT(onRequestFinished(int, bool))); connect(connection[i].http, SIGNAL(done(bool)), this, SLOT(onDone(bool))); connect(connection[i].http, SIGNAL(stateChanged(int)), this, SLOT(onStateChanged(int))); connect(connection[i].http, SIGNAL(authenticationRequired(const QString&, quint16, QAuthenticator*)), this, SLOT(onAuthenticationRequired(const QString&, quint16, QAuthenticator*))); connect(connection[i].http, SIGNAL(proxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*)), this, SLOT(onProxyAuthenticationRequired(const QNetworkProxy&, QAuthenticator*))); connect(connection[i].http, SIGNAL(sslErrors(const QList<QSslError>&)), this, SLOT(onSslErrors(const QList<QSslError>&))); }}WebCoreHttp::~WebCoreHttp(){ connection[0].http->deleteLater(); connection[1].http->deleteLater();}void WebCoreHttp::request(QWebNetworkJob *job){ m_pendingRequests.append(job); scheduleNextRequest();}void WebCoreHttp::scheduleNextRequest(){ int c = 0; for (; c < 2; ++c) { if (!connection[c].current) break; } if (c >= 2) return; QWebNetworkJob *job = 0; while (!job && !m_pendingRequests.isEmpty()) { job = m_pendingRequests.takeFirst(); if (job->cancelled()) { job->networkInterface()->finished(job, 1); job = 0; } } if (!job) return; QHttp *http = connection[c].http; connection[c].current = job; connection[c].id = -1;#ifndef QT_NO_NETWORKPROXY int proxyId = http->setProxy(job->frame()->page()->networkProxy());#endif QByteArray postData = job->postData(); if (!postData.isEmpty()) connection[c].id = http->request(job->httpHeader(), postData); else connection[c].id = http->request(job->httpHeader()); DEBUG() << "WebCoreHttp::scheduleNextRequest: using connection" << c; DEBUG() << job->httpHeader().toString();// DEBUG() << job->request.toString();}int WebCoreHttp::getConnection(){ QObject *o = sender(); int c; if (o == connection[0].http) { c = 0; } else { Q_ASSERT(o == connection[1].http); c = 1; } Q_ASSERT(connection[c].current); return c;}void WebCoreHttp::onResponseHeaderReceived(const QHttpResponseHeader &resp){ QHttp *http = qobject_cast<QHttp*>(sender()); if (http->currentId() == 0) { qDebug() << "ERROR! Invalid job id. Why?"; // foxnews.com triggers this return; } int c = getConnection(); QWebNetworkJob *job = connection[c].current; DEBUG() << "WebCoreHttp::slotResponseHeaderReceived connection=" << c; DEBUG() << resp.toString(); job->setResponse(resp); job->networkInterface()->started(job);}void WebCoreHttp::onReadyRead(){ QHttp *http = qobject_cast<QHttp*>(sender()); if (http->currentId() == 0) { qDebug() << "ERROR! Invalid job id. Why?"; // foxnews.com triggers this return; } int c = getConnection(); QWebNetworkJob *job = connection[c].current; Q_ASSERT(http == connection[c].http); //DEBUG() << "WebCoreHttp::slotReadyRead connection=" << c; QByteArray data; data.resize(http->bytesAvailable()); http->read(data.data(), data.length()); job->networkInterface()->data(job, data);}void WebCoreHttp::onRequestFinished(int id, bool error){ int c = getConnection(); if (connection[c].id != id) { return; } QWebNetworkJob *job = connection[c].current; if (!job) { scheduleNextRequest(); return; } QHttp *http = connection[c].http; DEBUG() << "WebCoreHttp::slotFinished connection=" << c << error << job; if (error) { DEBUG() << " error: " << http->errorString(); job->setErrorString(http->errorString()); } if (!error && http->bytesAvailable()) { QByteArray data; data.resize(http->bytesAvailable()); http->read(data.data(), data.length()); job->networkInterface()->data(job, data); } job->networkInterface()->finished(job, error ? 1 : 0); connection[c].current = 0; connection[c].id = -1; scheduleNextRequest();}void WebCoreHttp::onDone(bool error){ DEBUG() << "WebCoreHttp::onDone" << error;}void WebCoreHttp::onStateChanged(int state){ DEBUG() << "State changed to" << state << "and connections are" << connection[0].current << connection[1].current; if (state == QHttp::Closing || state == QHttp::Unconnected) { if (!m_inCancel && m_pendingRequests.isEmpty() && !connection[0].current && !connection[1].current) emit connectionClosed(info); }}void WebCoreHttp::cancel(QWebNetworkJob* request){ bool doEmit = true; m_inCancel = true; for (int i = 0; i < 2; ++i) { if (request == connection[i].current) { connection[i].http->abort(); doEmit = false; } } if (!m_pendingRequests.removeAll(request)) doEmit = false; m_inCancel = false; if (doEmit) request->networkInterface()->finished(request, 1); if (m_pendingRequests.isEmpty() && !connection[0].current && !connection[1].current) emit connectionClosed(info);}void WebCoreHttp::onSslErrors(const QList<QSslError>& errors){ int c = getConnection(); QWebNetworkJob *job = connection[c].current; if (job) { bool continueAnyway = false; emit job->networkInterface()->sslErrors(job->frame(), job->url(), errors, &continueAnyway);#ifndef QT_NO_OPENSSL if (continueAnyway) connection[c].http->ignoreSslErrors();#endif }}void WebCoreHttp::onAuthenticationRequired(const QString& hostname, quint16 port, QAuthenticator *auth){ int c = getConnection(); QWebNetworkJob *job = connection[c].current; if (job) { emit job->networkInterface()->authenticate(job->frame(), job->url(), hostname, port, auth); if (auth->isNull()) connection[c].http->abort(); }}void WebCoreHttp::onProxyAuthenticationRequired(const QNetworkProxy& proxy, QAuthenticator *auth){ int c = getConnection(); QWebNetworkJob *job = connection[c].current; if (job) { emit job->networkInterface()->authenticateProxy(job->frame(), job->url(), proxy, auth); if (auth->isNull()) connection[c].http->abort(); }}HostInfo::HostInfo(const QUrl& url) : protocol(url.scheme()) , host(url.host()) , port(url.port()){ if (port < 0) { if (protocol == QLatin1String("http")) port = 80; else if (protocol == QLatin1String("https")) port = 443; }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -