otherinbox-capybara-webkit 0.12.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +19 -0
- data/.rspec +2 -0
- data/Appraisals +7 -0
- data/CONTRIBUTING.md +47 -0
- data/ChangeLog +70 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +68 -0
- data/LICENSE +19 -0
- data/NEWS.md +36 -0
- data/README.md +114 -0
- data/Rakefile +65 -0
- data/bin/Info.plist +22 -0
- data/capybara-webkit.gemspec +28 -0
- data/extconf.rb +2 -0
- data/gemfiles/1.0.gemfile +7 -0
- data/gemfiles/1.0.gemfile.lock +70 -0
- data/gemfiles/1.1.gemfile +7 -0
- data/gemfiles/1.1.gemfile.lock +70 -0
- data/lib/capybara-webkit.rb +1 -0
- data/lib/capybara/driver/webkit.rb +135 -0
- data/lib/capybara/driver/webkit/browser.rb +168 -0
- data/lib/capybara/driver/webkit/connection.rb +120 -0
- data/lib/capybara/driver/webkit/cookie_jar.rb +55 -0
- data/lib/capybara/driver/webkit/node.rb +118 -0
- data/lib/capybara/driver/webkit/socket_debugger.rb +43 -0
- data/lib/capybara/driver/webkit/version.rb +7 -0
- data/lib/capybara/webkit.rb +11 -0
- data/lib/capybara/webkit/matchers.rb +37 -0
- data/lib/capybara_webkit_builder.rb +68 -0
- data/spec/browser_spec.rb +248 -0
- data/spec/capybara_webkit_builder_spec.rb +37 -0
- data/spec/connection_spec.rb +54 -0
- data/spec/cookie_jar_spec.rb +48 -0
- data/spec/driver_rendering_spec.rb +80 -0
- data/spec/driver_resize_window_spec.rb +59 -0
- data/spec/driver_spec.rb +1552 -0
- data/spec/integration/driver_spec.rb +20 -0
- data/spec/integration/session_spec.rb +137 -0
- data/spec/self_signed_ssl_cert.rb +42 -0
- data/spec/spec_helper.rb +46 -0
- data/src/Body.h +12 -0
- data/src/ClearCookies.cpp +15 -0
- data/src/ClearCookies.h +11 -0
- data/src/Command.cpp +19 -0
- data/src/Command.h +31 -0
- data/src/CommandFactory.cpp +38 -0
- data/src/CommandFactory.h +16 -0
- data/src/CommandParser.cpp +76 -0
- data/src/CommandParser.h +33 -0
- data/src/Connection.cpp +71 -0
- data/src/Connection.h +37 -0
- data/src/ConsoleMessages.cpp +10 -0
- data/src/ConsoleMessages.h +12 -0
- data/src/CurrentUrl.cpp +68 -0
- data/src/CurrentUrl.h +16 -0
- data/src/Evaluate.cpp +84 -0
- data/src/Evaluate.h +22 -0
- data/src/Execute.cpp +16 -0
- data/src/Execute.h +12 -0
- data/src/Find.cpp +19 -0
- data/src/Find.h +13 -0
- data/src/FrameFocus.cpp +66 -0
- data/src/FrameFocus.h +28 -0
- data/src/GetCookies.cpp +20 -0
- data/src/GetCookies.h +14 -0
- data/src/Header.cpp +18 -0
- data/src/Header.h +11 -0
- data/src/Headers.cpp +10 -0
- data/src/Headers.h +12 -0
- data/src/IgnoreSslErrors.cpp +12 -0
- data/src/IgnoreSslErrors.h +12 -0
- data/src/JavascriptInvocation.cpp +14 -0
- data/src/JavascriptInvocation.h +19 -0
- data/src/NetworkAccessManager.cpp +29 -0
- data/src/NetworkAccessManager.h +19 -0
- data/src/NetworkCookieJar.cpp +101 -0
- data/src/NetworkCookieJar.h +15 -0
- data/src/Node.cpp +14 -0
- data/src/Node.h +13 -0
- data/src/NullCommand.cpp +10 -0
- data/src/NullCommand.h +11 -0
- data/src/PageLoadingCommand.cpp +46 -0
- data/src/PageLoadingCommand.h +40 -0
- data/src/Render.cpp +18 -0
- data/src/Render.h +12 -0
- data/src/RequestedUrl.cpp +12 -0
- data/src/RequestedUrl.h +12 -0
- data/src/Reset.cpp +29 -0
- data/src/Reset.h +15 -0
- data/src/ResizeWindow.cpp +16 -0
- data/src/ResizeWindow.h +12 -0
- data/src/Response.cpp +24 -0
- data/src/Response.h +15 -0
- data/src/Server.cpp +24 -0
- data/src/Server.h +21 -0
- data/src/SetCookie.cpp +16 -0
- data/src/SetCookie.h +11 -0
- data/src/SetProxy.cpp +22 -0
- data/src/SetProxy.h +11 -0
- data/src/SetSkipImageLoading.cpp +11 -0
- data/src/SetSkipImageLoading.h +11 -0
- data/src/Source.cpp +18 -0
- data/src/Source.h +19 -0
- data/src/Status.cpp +12 -0
- data/src/Status.h +12 -0
- data/src/UnsupportedContentHandler.cpp +32 -0
- data/src/UnsupportedContentHandler.h +18 -0
- data/src/Url.cpp +12 -0
- data/src/Url.h +12 -0
- data/src/Visit.cpp +12 -0
- data/src/Visit.h +12 -0
- data/src/WebPage.cpp +246 -0
- data/src/WebPage.h +58 -0
- data/src/body.cpp +10 -0
- data/src/capybara.js +315 -0
- data/src/find_command.h +30 -0
- data/src/main.cpp +31 -0
- data/src/webkit_server.pro +87 -0
- data/src/webkit_server.qrc +5 -0
- data/templates/Command.cpp +10 -0
- data/templates/Command.h +12 -0
- data/webkit_server.pro +4 -0
- metadata +300 -0
data/src/FrameFocus.h
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
#include "Command.h"
|
2
|
+
|
3
|
+
class WebPage;
|
4
|
+
class QWebFrame;
|
5
|
+
|
6
|
+
class FrameFocus : public Command {
|
7
|
+
Q_OBJECT
|
8
|
+
|
9
|
+
public:
|
10
|
+
FrameFocus(WebPage *page, QStringList &arguments, QObject *parent = 0);
|
11
|
+
virtual void start();
|
12
|
+
|
13
|
+
private:
|
14
|
+
void findFrames();
|
15
|
+
|
16
|
+
void focusParent();
|
17
|
+
|
18
|
+
void focusIndex(int index);
|
19
|
+
bool isFrameAtIndex(int index);
|
20
|
+
|
21
|
+
void focusId(QString id);
|
22
|
+
|
23
|
+
void success();
|
24
|
+
void frameNotFound();
|
25
|
+
|
26
|
+
QList<QWebFrame *> frames;
|
27
|
+
};
|
28
|
+
|
data/src/GetCookies.cpp
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#include "GetCookies.h"
|
2
|
+
#include "WebPage.h"
|
3
|
+
#include "NetworkCookieJar.h"
|
4
|
+
|
5
|
+
GetCookies::GetCookies(WebPage *page, QStringList &arguments, QObject *parent) : Command(page, arguments, parent)
|
6
|
+
{
|
7
|
+
m_buffer = "";
|
8
|
+
}
|
9
|
+
|
10
|
+
void GetCookies::start()
|
11
|
+
{
|
12
|
+
NetworkCookieJar *jar = qobject_cast<NetworkCookieJar*>(page()
|
13
|
+
->networkAccessManager()
|
14
|
+
->cookieJar());
|
15
|
+
foreach (QNetworkCookie cookie, jar->getAllCookies()) {
|
16
|
+
m_buffer.append(cookie.toRawForm());
|
17
|
+
m_buffer.append("\n");
|
18
|
+
}
|
19
|
+
emit finished(new Response(true, m_buffer));
|
20
|
+
}
|
data/src/GetCookies.h
ADDED
data/src/Header.cpp
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#include "Header.h"
|
2
|
+
#include "WebPage.h"
|
3
|
+
#include "NetworkAccessManager.h"
|
4
|
+
|
5
|
+
Header::Header(WebPage *page, QStringList &arguments, QObject *parent) : Command(page, arguments, parent) {
|
6
|
+
}
|
7
|
+
|
8
|
+
void Header::start() {
|
9
|
+
QString key = arguments()[0];
|
10
|
+
QString value = arguments()[1];
|
11
|
+
NetworkAccessManager* networkAccessManager = qobject_cast<NetworkAccessManager*>(page()->networkAccessManager());
|
12
|
+
if (key.toLower().replace("-", "_") == "user_agent") {
|
13
|
+
page()->setUserAgent(value);
|
14
|
+
} else {
|
15
|
+
networkAccessManager->addHeader(key, value);
|
16
|
+
}
|
17
|
+
emit finished(new Response(true));
|
18
|
+
}
|
data/src/Header.h
ADDED
data/src/Headers.cpp
ADDED
data/src/Headers.h
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#include "IgnoreSslErrors.h"
|
2
|
+
#include "WebPage.h"
|
3
|
+
|
4
|
+
IgnoreSslErrors::IgnoreSslErrors(WebPage *page, QStringList &arguments, QObject *parent) :
|
5
|
+
Command(page, arguments, parent) {
|
6
|
+
}
|
7
|
+
|
8
|
+
void IgnoreSslErrors::start() {
|
9
|
+
page()->ignoreSslErrors();
|
10
|
+
emit finished(new Response(true));
|
11
|
+
}
|
12
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
#include "JavascriptInvocation.h"
|
2
|
+
|
3
|
+
JavascriptInvocation::JavascriptInvocation(QString &functionName, QStringList &arguments, QObject *parent) : QObject(parent) {
|
4
|
+
m_functionName = functionName;
|
5
|
+
m_arguments = arguments;
|
6
|
+
}
|
7
|
+
|
8
|
+
QString &JavascriptInvocation::functionName() {
|
9
|
+
return m_functionName;
|
10
|
+
}
|
11
|
+
|
12
|
+
QStringList &JavascriptInvocation::arguments() {
|
13
|
+
return m_arguments;
|
14
|
+
}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#include <QObject>
|
2
|
+
#include <QString>
|
3
|
+
#include <QStringList>
|
4
|
+
|
5
|
+
class JavascriptInvocation : public QObject {
|
6
|
+
Q_OBJECT
|
7
|
+
Q_PROPERTY(QString functionName READ functionName)
|
8
|
+
Q_PROPERTY(QStringList arguments READ arguments)
|
9
|
+
|
10
|
+
public:
|
11
|
+
JavascriptInvocation(QString &functionName, QStringList &arguments, QObject *parent = 0);
|
12
|
+
QString &functionName();
|
13
|
+
QStringList &arguments();
|
14
|
+
|
15
|
+
private:
|
16
|
+
QString m_functionName;
|
17
|
+
QStringList m_arguments;
|
18
|
+
};
|
19
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#include "NetworkAccessManager.h"
|
2
|
+
#include "WebPage.h"
|
3
|
+
#include <iostream>
|
4
|
+
|
5
|
+
|
6
|
+
NetworkAccessManager::NetworkAccessManager(QObject *parent):QNetworkAccessManager(parent) {
|
7
|
+
}
|
8
|
+
|
9
|
+
QNetworkReply* NetworkAccessManager::createRequest(QNetworkAccessManager::Operation operation, const QNetworkRequest &request, QIODevice * outgoingData = 0) {
|
10
|
+
QNetworkRequest new_request(request);
|
11
|
+
if (operation != QNetworkAccessManager::PostOperation && operation != QNetworkAccessManager::PutOperation) {
|
12
|
+
new_request.setHeader(QNetworkRequest::ContentTypeHeader, QVariant());
|
13
|
+
}
|
14
|
+
QHashIterator<QString, QString> item(m_headers);
|
15
|
+
while (item.hasNext()) {
|
16
|
+
item.next();
|
17
|
+
new_request.setRawHeader(item.key().toAscii(), item.value().toAscii());
|
18
|
+
}
|
19
|
+
return QNetworkAccessManager::createRequest(operation, new_request, outgoingData);
|
20
|
+
};
|
21
|
+
|
22
|
+
void NetworkAccessManager::addHeader(QString key, QString value) {
|
23
|
+
m_headers.insert(key, value);
|
24
|
+
};
|
25
|
+
|
26
|
+
void NetworkAccessManager::resetHeaders() {
|
27
|
+
m_headers.clear();
|
28
|
+
};
|
29
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
#include <QtNetwork/QNetworkAccessManager>
|
2
|
+
#include <QtNetwork/QNetworkRequest>
|
3
|
+
#include <QtNetwork/QNetworkReply>
|
4
|
+
|
5
|
+
class NetworkAccessManager : public QNetworkAccessManager {
|
6
|
+
|
7
|
+
Q_OBJECT
|
8
|
+
|
9
|
+
public:
|
10
|
+
NetworkAccessManager(QObject *parent = 0);
|
11
|
+
void addHeader(QString key, QString value);
|
12
|
+
void resetHeaders();
|
13
|
+
|
14
|
+
protected:
|
15
|
+
QNetworkReply* createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice * outgoingData);
|
16
|
+
|
17
|
+
private:
|
18
|
+
QHash<QString, QString> m_headers;
|
19
|
+
};
|
@@ -0,0 +1,101 @@
|
|
1
|
+
#include "NetworkCookieJar.h"
|
2
|
+
#include "QtCore/qdatetime.h"
|
3
|
+
|
4
|
+
NetworkCookieJar::NetworkCookieJar(QObject *parent)
|
5
|
+
: QNetworkCookieJar(parent)
|
6
|
+
{ }
|
7
|
+
|
8
|
+
QList<QNetworkCookie> NetworkCookieJar::getAllCookies() const
|
9
|
+
{
|
10
|
+
return allCookies();
|
11
|
+
}
|
12
|
+
|
13
|
+
void NetworkCookieJar::clearCookies()
|
14
|
+
{
|
15
|
+
setAllCookies(QList<QNetworkCookie>());
|
16
|
+
}
|
17
|
+
|
18
|
+
static inline bool isParentDomain(QString domain, QString reference)
|
19
|
+
{
|
20
|
+
if (!reference.startsWith(QLatin1Char('.')))
|
21
|
+
return domain == reference;
|
22
|
+
|
23
|
+
return domain.endsWith(reference) || domain == reference.mid(1);
|
24
|
+
}
|
25
|
+
|
26
|
+
void NetworkCookieJar::overwriteCookies(const QList<QNetworkCookie>& cookieList)
|
27
|
+
{
|
28
|
+
/* this function is basically a copy-and-paste of the original
|
29
|
+
QNetworkCookieJar::setCookiesFromUrl with the domain and
|
30
|
+
path validations removed */
|
31
|
+
|
32
|
+
QString defaultPath(QLatin1Char('/'));
|
33
|
+
QDateTime now = QDateTime::currentDateTime();
|
34
|
+
QList<QNetworkCookie> newCookies = allCookies();
|
35
|
+
|
36
|
+
foreach (QNetworkCookie cookie, cookieList) {
|
37
|
+
bool isDeletion = (!cookie.isSessionCookie() &&
|
38
|
+
cookie.expirationDate() < now);
|
39
|
+
|
40
|
+
// validate the cookie & set the defaults if unset
|
41
|
+
if (cookie.path().isEmpty())
|
42
|
+
cookie.setPath(defaultPath);
|
43
|
+
|
44
|
+
// don't do path checking. See http://bugreports.qt.nokia.com/browse/QTBUG-5815
|
45
|
+
// else if (!isParentPath(pathAndFileName, cookie.path())) {
|
46
|
+
// continue; // not accepted
|
47
|
+
// }
|
48
|
+
|
49
|
+
if (cookie.domain().isEmpty()) {
|
50
|
+
continue;
|
51
|
+
} else {
|
52
|
+
// Ensure the domain starts with a dot if its field was not empty
|
53
|
+
// in the HTTP header. There are some servers that forget the
|
54
|
+
// leading dot and this is actually forbidden according to RFC 2109,
|
55
|
+
// but all browsers accept it anyway so we do that as well.
|
56
|
+
if (!cookie.domain().startsWith(QLatin1Char('.')))
|
57
|
+
cookie.setDomain(QLatin1Char('.') + cookie.domain());
|
58
|
+
|
59
|
+
QString domain = cookie.domain();
|
60
|
+
|
61
|
+
// the check for effective TLDs makes the "embedded dot" rule from RFC 2109 section 4.3.2
|
62
|
+
// redundant; the "leading dot" rule has been relaxed anyway, see above
|
63
|
+
// we remove the leading dot for this check
|
64
|
+
/*
|
65
|
+
if (QNetworkCookieJarPrivate::isEffectiveTLD(domain.remove(0, 1)))
|
66
|
+
continue; // not accepted
|
67
|
+
*/
|
68
|
+
}
|
69
|
+
|
70
|
+
for (int i = 0; i < newCookies.size(); ++i) {
|
71
|
+
// does this cookie already exist?
|
72
|
+
const QNetworkCookie ¤t = newCookies.at(i);
|
73
|
+
if (cookie.name() == current.name() &&
|
74
|
+
cookie.domain() == current.domain() &&
|
75
|
+
cookie.path() == current.path()) {
|
76
|
+
// found a match
|
77
|
+
newCookies.removeAt(i);
|
78
|
+
break;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
// did not find a match
|
83
|
+
if (!isDeletion) {
|
84
|
+
int countForDomain = 0;
|
85
|
+
for (int i = newCookies.size() - 1; i >= 0; --i) {
|
86
|
+
// Start from the end and delete the oldest cookies to keep a maximum count of 50.
|
87
|
+
const QNetworkCookie ¤t = newCookies.at(i);
|
88
|
+
if (isParentDomain(cookie.domain(), current.domain())
|
89
|
+
|| isParentDomain(current.domain(), cookie.domain())) {
|
90
|
+
if (countForDomain >= 49)
|
91
|
+
newCookies.removeAt(i);
|
92
|
+
else
|
93
|
+
++countForDomain;
|
94
|
+
}
|
95
|
+
}
|
96
|
+
|
97
|
+
newCookies += cookie;
|
98
|
+
}
|
99
|
+
}
|
100
|
+
setAllCookies(newCookies);
|
101
|
+
}
|
@@ -0,0 +1,15 @@
|
|
1
|
+
#include <QtNetwork/QNetworkCookieJar>
|
2
|
+
#include <QtNetwork/QNetworkCookie>
|
3
|
+
|
4
|
+
class NetworkCookieJar : public QNetworkCookieJar {
|
5
|
+
|
6
|
+
Q_OBJECT;
|
7
|
+
|
8
|
+
public:
|
9
|
+
|
10
|
+
NetworkCookieJar(QObject *parent = 0);
|
11
|
+
|
12
|
+
QList<QNetworkCookie> getAllCookies() const;
|
13
|
+
void clearCookies();
|
14
|
+
void overwriteCookies(const QList<QNetworkCookie>& cookieList);
|
15
|
+
};
|
data/src/Node.cpp
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#include "Node.h"
|
2
|
+
#include "WebPage.h"
|
3
|
+
|
4
|
+
Node::Node(WebPage *page, QStringList &arguments, QObject *parent) : Command(page, arguments, parent) {
|
5
|
+
}
|
6
|
+
|
7
|
+
void Node::start() {
|
8
|
+
QStringList functionArguments(arguments());
|
9
|
+
QString functionName = functionArguments.takeFirst();
|
10
|
+
QVariant result = page()->invokeCapybaraFunction(functionName, functionArguments);
|
11
|
+
QString attributeValue = result.toString();
|
12
|
+
emit finished(new Response(true, attributeValue));
|
13
|
+
}
|
14
|
+
|
data/src/Node.h
ADDED
data/src/NullCommand.cpp
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#include "NullCommand.h"
|
2
|
+
#include "WebPage.h"
|
3
|
+
|
4
|
+
NullCommand::NullCommand(WebPage *page, QStringList &arguments, QObject *parent) : Command(page, arguments, parent) {}
|
5
|
+
|
6
|
+
void NullCommand::start() {
|
7
|
+
QString failure = QString("[Capybara WebKit] Unknown command: ") + arguments()[0] + "\n";
|
8
|
+
emit finished(new Response(false, failure));
|
9
|
+
}
|
10
|
+
|
data/src/NullCommand.h
ADDED
@@ -0,0 +1,46 @@
|
|
1
|
+
#include "PageLoadingCommand.h"
|
2
|
+
#include "Command.h"
|
3
|
+
#include "WebPage.h"
|
4
|
+
|
5
|
+
PageLoadingCommand::PageLoadingCommand(Command *command, WebPage *page, QObject *parent) : QObject(parent) {
|
6
|
+
m_page = page;
|
7
|
+
m_command = command;
|
8
|
+
m_pageLoadingFromCommand = false;
|
9
|
+
m_pageSuccess = true;
|
10
|
+
m_pendingResponse = NULL;
|
11
|
+
connect(m_page, SIGNAL(loadStarted()), this, SLOT(pageLoadingFromCommand()));
|
12
|
+
connect(m_page, SIGNAL(pageFinished(bool)), this, SLOT(pendingLoadFinished(bool)));
|
13
|
+
}
|
14
|
+
|
15
|
+
void PageLoadingCommand::start() {
|
16
|
+
connect(m_command, SIGNAL(finished(Response *)), this, SLOT(commandFinished(Response *)));
|
17
|
+
m_command->start();
|
18
|
+
};
|
19
|
+
|
20
|
+
void PageLoadingCommand::pendingLoadFinished(bool success) {
|
21
|
+
m_pageSuccess = success;
|
22
|
+
if (m_pageLoadingFromCommand) {
|
23
|
+
m_pageLoadingFromCommand = false;
|
24
|
+
if (m_pendingResponse) {
|
25
|
+
if (m_pageSuccess) {
|
26
|
+
emit finished(m_pendingResponse);
|
27
|
+
} else {
|
28
|
+
QString message = m_page->failureString();
|
29
|
+
emit finished(new Response(false, message));
|
30
|
+
}
|
31
|
+
}
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
void PageLoadingCommand::pageLoadingFromCommand() {
|
36
|
+
m_pageLoadingFromCommand = true;
|
37
|
+
}
|
38
|
+
|
39
|
+
void PageLoadingCommand::commandFinished(Response *response) {
|
40
|
+
disconnect(m_page, SIGNAL(loadStarted()), this, SLOT(pageLoadingFromCommand()));
|
41
|
+
m_command->deleteLater();
|
42
|
+
if (m_pageLoadingFromCommand)
|
43
|
+
m_pendingResponse = response;
|
44
|
+
else
|
45
|
+
emit finished(response);
|
46
|
+
}
|