mirror of
https://github.com/thoughtbot/capybara-webkit
synced 2023-03-27 23:22:28 -04:00
Add blacklisting support to webkit server.
Adds a SetBlacklist command that takes a list of URLs which will be black listed by the WebKit Server. When a request is made to one these URLs webkit_server will intercept the request and return a NoOpReply which contains no content.
This commit is contained in:
parent
213229d850
commit
f755b1f277
11 changed files with 201 additions and 11 deletions
|
@ -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
|
||||
|
|
|
@ -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>
|
||||
<body>
|
||||
<script src="/script"></script>
|
||||
<iframe src="http://example.com/path" id="frame1"></iframe>
|
||||
<iframe src="http://example.org/path/to/file" id="frame2"></iframe>
|
||||
<iframe src="/frame" id="frame3"></iframe>
|
||||
</body>
|
||||
</html>
|
||||
HTML
|
||||
end
|
||||
|
||||
get "/frame" do
|
||||
<<-HTML
|
||||
<html>
|
||||
<body>
|
||||
<p>Inner</p>
|
||||
</body>
|
||||
</html>
|
||||
HTML
|
||||
end
|
||||
|
||||
get "/script" do
|
||||
<<-JS
|
||||
document.write('<p>Script Run</p>')
|
||||
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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "WebPage.h"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include "NoOpReply.h"
|
||||
|
||||
NetworkAccessManager::NetworkAccessManager(QObject *parent):QNetworkAccessManager(parent) {
|
||||
connect(this, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)), SLOT(provideAuthentication(QNetworkReply*,QAuthenticator*)));
|
||||
|
@ -11,6 +12,9 @@ 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 (this->isBlacklisted(new_request.url())) {
|
||||
return this->noOpRequest();
|
||||
} else {
|
||||
if (operation != QNetworkAccessManager::PostOperation && operation != QNetworkAccessManager::PutOperation) {
|
||||
new_request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant());
|
||||
}
|
||||
|
@ -23,6 +27,7 @@ QNetworkReply* NetworkAccessManager::createRequest(QNetworkAccessManager::Operat
|
|||
emit requestCreated(url, reply);
|
||||
return reply;
|
||||
}
|
||||
};
|
||||
|
||||
void NetworkAccessManager::finished(QNetworkReply *reply) {
|
||||
NetworkResponse response;
|
||||
|
@ -60,3 +65,33 @@ int NetworkAccessManager::statusFor(QUrl url) {
|
|||
const QList<QNetworkReply::RawHeaderPair> &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<QUrl> 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();
|
||||
};
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
#include <QStringList>
|
||||
|
||||
class NetworkAccessManager : public QNetworkAccessManager {
|
||||
|
||||
|
@ -20,15 +21,20 @@ class NetworkAccessManager : public QNetworkAccessManager {
|
|||
void setPassword(const QString &password);
|
||||
int statusFor(QUrl url);
|
||||
const QList<QNetworkReply::RawHeaderPair> &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<QUrl> m_urlBlacklist;
|
||||
|
||||
|
||||
private:
|
||||
QHash<QString, QString> m_headers;
|
||||
QHash<QUrl, NetworkResponse> m_responses;
|
||||
bool isBlacklisted(QUrl url);
|
||||
QNetworkReply* noOpRequest();
|
||||
|
||||
private slots:
|
||||
void provideAuthentication(QNetworkReply *reply, QAuthenticator *authenticator);
|
||||
|
|
29
src/NoOpReply.cpp
Normal file
29
src/NoOpReply.cpp
Normal file
|
@ -0,0 +1,29 @@
|
|||
#include <QTimer.h>
|
||||
#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;
|
||||
}
|
||||
|
17
src/NoOpReply.h
Normal file
17
src/NoOpReply.h
Normal file
|
@ -0,0 +1,17 @@
|
|||
#include <qnetworkreply>
|
||||
|
||||
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);
|
||||
|
||||
};
|
||||
|
15
src/SetUrlBlacklist.cpp
Normal file
15
src/SetUrlBlacklist.cpp
Normal file
|
@ -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<NetworkAccessManager*>(page()->networkAccessManager());
|
||||
networkAccessManager->setUrlBlacklist(arguments());
|
||||
emit finished(new Response(true));
|
||||
}
|
||||
|
11
src/SetUrlBlacklist.h
Normal file
11
src/SetUrlBlacklist.h
Normal file
|
@ -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();
|
||||
};
|
||||
|
|
@ -41,4 +41,5 @@ CHECK_COMMAND(JavascriptConfirmMessages)
|
|||
CHECK_COMMAND(JavascriptPromptMessages)
|
||||
CHECK_COMMAND(GetTimeout)
|
||||
CHECK_COMMAND(SetTimeout)
|
||||
CHECK_COMMAND(SetUrlBlacklist)
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue