From 09e929d5990935d104dd55ab9f38df8328d296ea Mon Sep 17 00:00:00 2001 From: Vitaliy Slobodin Date: Wed, 2 Jan 2013 15:41:56 +0400 Subject: [PATCH] Allow to abort network requests. Issue: http://code.google.com/p/phantomjs/issues/detail?id=230 --- examples/loadurlwithoutcss.coffee | 20 +++++++++++++++++++ examples/loadurlwithoutcss.js | 25 ++++++++++++++++++++++++ src/networkaccessmanager.cpp | 27 ++++++++++++++++++++------ src/networkaccessmanager.h | 14 +++++++++++++- src/webpage.cpp | 4 ++-- src/webpage.h | 2 +- test/webpage-spec.js | 32 ++++++++++++++++++++++++++++++- 7 files changed, 113 insertions(+), 11 deletions(-) create mode 100644 examples/loadurlwithoutcss.coffee create mode 100644 examples/loadurlwithoutcss.js diff --git a/examples/loadurlwithoutcss.coffee b/examples/loadurlwithoutcss.coffee new file mode 100644 index 00000000..36143c8d --- /dev/null +++ b/examples/loadurlwithoutcss.coffee @@ -0,0 +1,20 @@ +page = require("webpage").create() +system = require("system") + +if system.args.length < 2 + console.log "Usage: loadurlwithoutcss.js URL" + phantom.exit() + +address = system.args[1] + +page.onResourceRequested = (requestData, request) -> + if (/http:\/\/.+?\.css/g).test(requestData["url"]) or requestData["Content-Type"] is "text/css" + console.log "The url of the request is matching. Aborting: " + requestData["url"] + request.abort() + +page.open address, (status) -> + if status is "success" + phantom.exit() + else + console.log "Unable to load the address!" + phantom.exit() diff --git a/examples/loadurlwithoutcss.js b/examples/loadurlwithoutcss.js new file mode 100644 index 00000000..c7a4733d --- /dev/null +++ b/examples/loadurlwithoutcss.js @@ -0,0 +1,25 @@ +var page = require('webpage').create(), + system = require('system'); + +if (system.args.length < 2) { + console.log('Usage: loadurlwithoutcss.js URL'); + phantom.exit(); +} + +var address = system.args[1]; + +page.onResourceRequested = function(requestData, request) { + if ((/http:\/\/.+?\.css/gi).test(requestData['url']) || requestData['Content-Type'] == 'text/css') { + console.log('The url of the request is matching. Aborting: ' + requestData['url']); + request.abort(); + } +}; + +page.open(address, function(status) { + if (status === 'success') { + phantom.exit(); + } else { + console.log('Unable to load the address!'); + phantom.exit(); + } +}); \ No newline at end of file diff --git a/src/networkaccessmanager.cpp b/src/networkaccessmanager.cpp index cfd6dc4f..bd24e1d9 100644 --- a/src/networkaccessmanager.cpp +++ b/src/networkaccessmanager.cpp @@ -67,6 +67,21 @@ static const char *toString(QNetworkAccessManager::Operation op) return str; } +JsNetworkRequest::JsNetworkRequest(QNetworkReply* reply) +{ + setParent(reply); + + m_networkReply = reply; +} + + +void JsNetworkRequest::abort() +{ + if (m_networkReply->isRunning() || !m_networkReply->isFinished()) { + m_networkReply->abort(); + } +} + // public: NetworkAccessManager::NetworkAccessManager(QObject *parent, const Config *config) : QNetworkAccessManager(parent) @@ -192,12 +207,11 @@ QNetworkReply *NetworkAccessManager::createRequest(Operation op, const QNetworkR data["method"] = toString(op); data["headers"] = headers; data["time"] = QDateTime::currentDateTime(); - + connect(reply, SIGNAL(readyRead()), this, SLOT(handleStarted())); connect(reply, SIGNAL(sslErrors(const QList &)), this, SLOT(handleSslErrors(const QList &))); connect(reply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(handleNetworkError())); - emit resourceRequested(data); return reply; } @@ -210,7 +224,7 @@ void NetworkAccessManager::handleStarted() return; m_started += reply; - + QVariantList headers; foreach (QByteArray headerName, reply->rawHeaderList()) { QVariantMap header; @@ -231,7 +245,8 @@ void NetworkAccessManager::handleStarted() data["headers"] = headers; data["time"] = QDateTime::currentDateTime(); - emit resourceReceived(data); + JsNetworkRequest* jsNetworkRequest = new JsNetworkRequest(reply); + emit resourceRequested(data, jsNetworkRequest); } void NetworkAccessManager::handleFinished(QNetworkReply *reply) @@ -250,7 +265,7 @@ void NetworkAccessManager::provideAuthentication(QNetworkReply *reply, QAuthenti if (m_authAttempts++ < m_maxAuthAttempts) { authenticator->setUser(m_userName); - authenticator->setPassword(m_password); + authenticator->setPassword(m_password); } else { @@ -312,4 +327,4 @@ void NetworkAccessManager::handleNetworkError() emit resourceError(reply->error(), reply->errorString()); reply->deleteLater(); -} \ No newline at end of file +} diff --git a/src/networkaccessmanager.h b/src/networkaccessmanager.h index 3a589546..9e3ae0e6 100644 --- a/src/networkaccessmanager.h +++ b/src/networkaccessmanager.h @@ -42,6 +42,18 @@ class Config; class QNetworkDiskCache; class QSslConfiguration; +class JsNetworkRequest : public QObject +{ + Q_OBJECT + +public: + JsNetworkRequest(QNetworkReply* reply); + Q_INVOKABLE void abort(); + +private: + QNetworkReply* m_networkReply; +}; + class NetworkAccessManager : public QNetworkAccessManager { Q_OBJECT @@ -65,7 +77,7 @@ protected: void handleFinished(QNetworkReply *reply, const QVariant &status, const QVariant &statusText); signals: - void resourceRequested(const QVariant& data); + void resourceRequested(const QVariant& data, QObject *); void resourceReceived(const QVariant& data); void resourceError(const QVariant& errorCode, const QVariant& errorString); diff --git a/src/webpage.cpp b/src/webpage.cpp index 1194a195..55375658 100644 --- a/src/webpage.cpp +++ b/src/webpage.cpp @@ -364,8 +364,8 @@ WebPage::WebPage(QObject *parent, const QUrl &baseUrl) // Custom network access manager to allow traffic monitoring. m_networkAccessManager = new NetworkAccessManager(this, phantomCfg); m_customWebPage->setNetworkAccessManager(m_networkAccessManager); - connect(m_networkAccessManager, SIGNAL(resourceRequested(QVariant)), - SIGNAL(resourceRequested(QVariant))); + connect(m_networkAccessManager, SIGNAL(resourceRequested(QVariant, QObject *)), + SIGNAL(resourceRequested(QVariant, QObject *))); connect(m_networkAccessManager, SIGNAL(resourceReceived(QVariant)), SIGNAL(resourceReceived(QVariant))); connect(m_networkAccessManager, SIGNAL(resourceError(QVariant, QVariant)), diff --git a/src/webpage.h b/src/webpage.h index 544eb01b..97b66bd5 100644 --- a/src/webpage.h +++ b/src/webpage.h @@ -461,7 +461,7 @@ signals: void javaScriptAlertSent(const QString &msg); void javaScriptConsoleMessageSent(const QString &message); void javaScriptErrorSent(const QString &msg, const QString &stack); - void resourceRequested(const QVariant &req); + void resourceRequested(const QVariant &requestData, QObject *request); void resourceReceived(const QVariant &resource); void resourceError(const QVariant &errorCode, const QVariant &errorString); void urlChanged(const QUrl &url); diff --git a/test/webpage-spec.js b/test/webpage-spec.js index b6562777..72d34d66 100644 --- a/test/webpage-spec.js +++ b/test/webpage-spec.js @@ -1043,7 +1043,7 @@ describe("WebPage object", function() { expect(handled).toEqual(true); }); }); - + it('should handle resource request errors', function() { var server = require('webserver').create(); var page = require('webpage').create(); @@ -1080,6 +1080,36 @@ describe("WebPage object", function() { expect(handled).toEqual(true); }); }); + + + it('should able to abort a network request', function() { + var page = require('webpage').create(); + var url = 'http://phantomjs.org'; + var urlToBlock = 'http://phantomjs.org/images/phantomjs-logo.png'; + + var handled = false; + + runs(function() { + page.onResourceRequested = function(requestData, request) { + if (requestData['url'] == urlToBlock) { + expect(typeof request).toEqual('object'); + expect(typeof request.abort).toEqual('function'); + request.abort(); + handled = true; + } + }; + + page.open(url, function(status) { + expect(status).toEqual('success'); + }); + }); + + waits(3000); + + runs(function() { + expect(handled).toEqual(true); + }); + }); }); describe("WebPage construction with options", function () {