diff --git a/lib/capybara/webkit/browser.rb b/lib/capybara/webkit/browser.rb
index e9ab44f..3adbef2 100644
--- a/lib/capybara/webkit/browser.rb
+++ b/lib/capybara/webkit/browser.rb
@@ -141,6 +141,10 @@ module Capybara::Webkit
command("ClearPromptText")
end
+ def url_blacklist=(black_list)
+ command("SetUrlBlacklist", *Array(black_list))
+ end
+
def command(name, *args)
@connection.puts name
@connection.puts args.size
diff --git a/spec/driver_spec.rb b/spec/driver_spec.rb
index 220c844..c6f2477 100644
--- a/spec/driver_spec.rb
+++ b/spec/driver_spec.rb
@@ -1833,6 +1833,73 @@ describe Capybara::Webkit::Driver do
end
end
+ describe "url blacklisting" do
+ let(:driver) do
+ driver_for_app do
+ get "/" do
+ <<-HTML
+
+
+
+
+
+
+
+
+ HTML
+ end
+
+ get "/frame" do
+ <<-HTML
+
+
+ Inner
+
+
+ HTML
+ end
+
+ get "/script" do
+ <<-JS
+ document.write('Script Run
')
+ JS
+ end
+ end
+ end
+
+ before do
+ driver.browser.url_blacklist = ["http://example.org/path/to/file",
+ "http://example.com",
+ "#{Capybara.app_host}/script"]
+ end
+
+ it "should not fetch urls blocked by host" do
+ driver.visit("/")
+ driver.within_frame('frame1') do
+ driver.find("//body").first.text.should be_empty
+ end
+ end
+
+ it "should not fetch urls blocked by path" do
+ driver.visit('/')
+ driver.within_frame('frame2') do
+ driver.find("//body").first.text.should be_empty
+ end
+ end
+
+ it "should not fetch blocked scripts" do
+ driver.visit("/")
+ driver.body.should_not include("Script Run")
+ end
+
+ it "should fetch unblocked urls" do
+ driver.visit('/')
+ driver.within_frame('frame3') do
+ driver.find("//p").first.text.should == "Inner"
+ end
+ end
+ end
+
describe "timeout for long requests" do
let(:driver) do
driver_for_app do
diff --git a/src/CommandFactory.cpp b/src/CommandFactory.cpp
index d4f58a9..6b5fd1d 100644
--- a/src/CommandFactory.cpp
+++ b/src/CommandFactory.cpp
@@ -40,6 +40,7 @@
#include "JavascriptAlertMessages.h"
#include "JavascriptConfirmMessages.h"
#include "JavascriptPromptMessages.h"
+#include "SetUrlBlacklist.h"
CommandFactory::CommandFactory(WebPageManager *manager, QObject *parent) : QObject(parent) {
m_manager = manager;
diff --git a/src/NetworkAccessManager.cpp b/src/NetworkAccessManager.cpp
index 98da30e..d5a869f 100644
--- a/src/NetworkAccessManager.cpp
+++ b/src/NetworkAccessManager.cpp
@@ -2,6 +2,7 @@
#include "WebPage.h"
#include
#include
+#include "NoOpReply.h"
NetworkAccessManager::NetworkAccessManager(QObject *parent):QNetworkAccessManager(parent) {
connect(this, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), SLOT(provideAuthentication(QNetworkReply*,QAuthenticator*)));
@@ -11,18 +12,22 @@ NetworkAccessManager::NetworkAccessManager(QObject *parent):QNetworkAccessManage
QNetworkReply* NetworkAccessManager::createRequest(QNetworkAccessManager::Operation operation, const QNetworkRequest &request, QIODevice * outgoingData = 0) {
QNetworkRequest new_request(request);
QByteArray url = new_request.url().toEncoded();
- if (operation != QNetworkAccessManager::PostOperation && operation != QNetworkAccessManager::PutOperation) {
- new_request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant());
+ if (this->isBlacklisted(new_request.url())) {
+ return this->noOpRequest();
+ } else {
+ if (operation != QNetworkAccessManager::PostOperation && operation != QNetworkAccessManager::PutOperation) {
+ new_request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant());
+ }
+ QHashIterator item(m_headers);
+ while (item.hasNext()) {
+ item.next();
+ new_request.setRawHeader(item.key().toAscii(), item.value().toAscii());
+ }
+ QNetworkReply *reply = QNetworkAccessManager::createRequest(operation, new_request, outgoingData);
+ emit requestCreated(url, reply);
+ return reply;
}
- QHashIterator item(m_headers);
- while (item.hasNext()) {
- item.next();
- new_request.setRawHeader(item.key().toAscii(), item.value().toAscii());
- }
- QNetworkReply *reply = QNetworkAccessManager::createRequest(operation, new_request, outgoingData);
- emit requestCreated(url, reply);
- return reply;
-}
+};
void NetworkAccessManager::finished(QNetworkReply *reply) {
NetworkResponse response;
@@ -60,3 +65,33 @@ int NetworkAccessManager::statusFor(QUrl url) {
const QList &NetworkAccessManager::headersFor(QUrl url) {
return m_responses[url].headers;
}
+
+void NetworkAccessManager::setUrlBlacklist(QStringList urlBlacklist) {
+ m_urlBlacklist.clear();
+
+ QStringListIterator iter(urlBlacklist);
+ while (iter.hasNext()) {
+ m_urlBlacklist << QUrl(iter.next());
+ }
+};
+
+bool NetworkAccessManager::isBlacklisted(QUrl url) {
+ QListIterator iter(m_urlBlacklist);
+
+ while (iter.hasNext()) {
+ QUrl blacklisted = iter.next();
+
+ if (blacklisted == url) {
+ return true;
+ } else if (blacklisted.path().isEmpty() && blacklisted.isParentOf(url)) {
+ return true;
+ }
+ }
+
+ return false;
+};
+
+QNetworkReply* NetworkAccessManager::noOpRequest() {
+ return new NoOpReply();
+};
+
diff --git a/src/NetworkAccessManager.h b/src/NetworkAccessManager.h
index d6c53df..56c8463 100644
--- a/src/NetworkAccessManager.h
+++ b/src/NetworkAccessManager.h
@@ -1,6 +1,7 @@
#include
#include
#include
+#include
class NetworkAccessManager : public QNetworkAccessManager {
@@ -20,15 +21,20 @@ class NetworkAccessManager : public QNetworkAccessManager {
void setPassword(const QString &password);
int statusFor(QUrl url);
const QList &headersFor(QUrl url);
+ void setUrlBlacklist(QStringList urlBlacklist);
protected:
QNetworkReply* createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice * outgoingData);
QString m_userName;
QString m_password;
+ QList m_urlBlacklist;
+
private:
QHash m_headers;
QHash m_responses;
+ bool isBlacklisted(QUrl url);
+ QNetworkReply* noOpRequest();
private slots:
void provideAuthentication(QNetworkReply *reply, QAuthenticator *authenticator);
diff --git a/src/NoOpReply.cpp b/src/NoOpReply.cpp
new file mode 100644
index 0000000..224f555
--- /dev/null
+++ b/src/NoOpReply.cpp
@@ -0,0 +1,29 @@
+#include
+#include "NoOpReply.h"
+
+NoOpReply::NoOpReply(QObject *parent) : QNetworkReply(parent) {
+ open(ReadOnly | Unbuffered);
+ setAttribute(QNetworkRequest::HttpStatusCodeAttribute, 200);
+ setHeader(QNetworkRequest::ContentLengthHeader, QVariant(0));
+ setHeader(QNetworkRequest::ContentTypeHeader, QVariant(QString("text/plain")));
+
+ QTimer::singleShot( 0, this, SIGNAL(readyRead()) );
+ QTimer::singleShot( 0, this, SIGNAL(finished()) );
+}
+
+void NoOpReply::abort() {
+ // NO-OP
+}
+
+qint64 NoOpReply::bytesAvailable() const {
+ return 0;
+}
+
+bool NoOpReply::isSequential() const {
+ return true;
+}
+
+qint64 NoOpReply::readData(char *data, qint64 maxSize) {
+ return 0;
+}
+
diff --git a/src/NoOpReply.h b/src/NoOpReply.h
new file mode 100644
index 0000000..3a074f6
--- /dev/null
+++ b/src/NoOpReply.h
@@ -0,0 +1,17 @@
+#include
+
+class NoOpReply : public QNetworkReply {
+ Q_OBJECT
+
+ public:
+ NoOpReply( QObject *parent=0 );
+
+ void abort();
+ qint64 bytesAvailable() const;
+ bool isSequential() const;
+
+ protected:
+ qint64 readData(char *data, qint64 maxSize);
+
+};
+
diff --git a/src/SetUrlBlacklist.cpp b/src/SetUrlBlacklist.cpp
new file mode 100644
index 0000000..7a91762
--- /dev/null
+++ b/src/SetUrlBlacklist.cpp
@@ -0,0 +1,15 @@
+
+#include "SetUrlBlacklist.h"
+#include "WebPageManager.h"
+#include "WebPage.h"
+#include "NetworkAccessManager.h"
+
+SetUrlBlacklist::SetUrlBlacklist(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {
+}
+
+void SetUrlBlacklist::start() {
+ NetworkAccessManager* networkAccessManager = qobject_cast(page()->networkAccessManager());
+ networkAccessManager->setUrlBlacklist(arguments());
+ emit finished(new Response(true));
+}
+
diff --git a/src/SetUrlBlacklist.h b/src/SetUrlBlacklist.h
new file mode 100644
index 0000000..4673876
--- /dev/null
+++ b/src/SetUrlBlacklist.h
@@ -0,0 +1,11 @@
+
+#include "SocketCommand.h"
+
+class SetUrlBlacklist : public SocketCommand {
+ Q_OBJECT
+
+ public:
+ SetUrlBlacklist(WebPageManager *manager, QStringList &arguments, QObject *parent = 0);
+ virtual void start();
+};
+
diff --git a/src/find_command.h b/src/find_command.h
index a31cf60..3d55467 100644
--- a/src/find_command.h
+++ b/src/find_command.h
@@ -41,4 +41,5 @@ CHECK_COMMAND(JavascriptConfirmMessages)
CHECK_COMMAND(JavascriptPromptMessages)
CHECK_COMMAND(GetTimeout)
CHECK_COMMAND(SetTimeout)
+CHECK_COMMAND(SetUrlBlacklist)
diff --git a/src/webkit_server.pro b/src/webkit_server.pro
index 404c0e8..c2e89d7 100644
--- a/src/webkit_server.pro
+++ b/src/webkit_server.pro
@@ -56,6 +56,8 @@ HEADERS = \
GetTimeout.h \
SetTimeout.h \
TimeoutCommand.h \
+ SetUrlBlacklist.h \
+ NoOpReply.h \
SOURCES = \
EnableLogging.cpp \
@@ -113,6 +115,8 @@ SOURCES = \
GetWindowHandles.cpp \
GetWindowHandle.cpp \
TimeoutCommand.cpp \
+ SetUrlBlacklist.cpp \
+ NoOpReply.cpp \
RESOURCES = webkit_server.qrc
QT += network webkit