Initial commit
This commit is contained in:
commit
0745b1ee1c
|
@ -0,0 +1,12 @@
|
||||||
|
*.swp
|
||||||
|
bin
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
*.o
|
||||||
|
*.moc
|
||||||
|
Makefile*
|
||||||
|
qrc_*
|
||||||
|
*.xcodeproj
|
||||||
|
*.app
|
||||||
|
moc_*.cpp
|
||||||
|
.bundle
|
|
@ -0,0 +1,5 @@
|
||||||
|
source "http://rubygems.org"
|
||||||
|
gem "rake"
|
||||||
|
gem "rspec", :require => false
|
||||||
|
gem "capybara"
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
GEM
|
||||||
|
remote: http://rubygems.org/
|
||||||
|
specs:
|
||||||
|
capybara (0.4.1.2)
|
||||||
|
celerity (>= 0.7.9)
|
||||||
|
culerity (>= 0.2.4)
|
||||||
|
mime-types (>= 1.16)
|
||||||
|
nokogiri (>= 1.3.3)
|
||||||
|
rack (>= 1.0.0)
|
||||||
|
rack-test (>= 0.5.4)
|
||||||
|
selenium-webdriver (>= 0.0.27)
|
||||||
|
xpath (~> 0.1.3)
|
||||||
|
celerity (0.8.8)
|
||||||
|
childprocess (0.1.7)
|
||||||
|
ffi (~> 0.6.3)
|
||||||
|
culerity (0.2.15)
|
||||||
|
diff-lcs (1.1.2)
|
||||||
|
ffi (0.6.3)
|
||||||
|
rake (>= 0.8.7)
|
||||||
|
json_pure (1.5.1)
|
||||||
|
mime-types (1.16)
|
||||||
|
nokogiri (1.4.4)
|
||||||
|
rack (1.2.1)
|
||||||
|
rack-test (0.5.7)
|
||||||
|
rack (>= 1.0)
|
||||||
|
rake (0.8.7)
|
||||||
|
rspec (2.5.0)
|
||||||
|
rspec-core (~> 2.5.0)
|
||||||
|
rspec-expectations (~> 2.5.0)
|
||||||
|
rspec-mocks (~> 2.5.0)
|
||||||
|
rspec-core (2.5.1)
|
||||||
|
rspec-expectations (2.5.0)
|
||||||
|
diff-lcs (~> 1.1.2)
|
||||||
|
rspec-mocks (2.5.0)
|
||||||
|
rubyzip (0.9.4)
|
||||||
|
selenium-webdriver (0.1.3)
|
||||||
|
childprocess (~> 0.1.5)
|
||||||
|
ffi (~> 0.6.3)
|
||||||
|
json_pure
|
||||||
|
rubyzip
|
||||||
|
xpath (0.1.3)
|
||||||
|
nokogiri (~> 1.3)
|
||||||
|
|
||||||
|
PLATFORMS
|
||||||
|
ruby
|
||||||
|
|
||||||
|
DEPENDENCIES
|
||||||
|
capybara
|
||||||
|
rake
|
||||||
|
rspec
|
|
@ -0,0 +1,61 @@
|
||||||
|
require 'rubygems'
|
||||||
|
require 'bundler/setup'
|
||||||
|
require 'fileutils'
|
||||||
|
require 'rspec/core/rake_task'
|
||||||
|
|
||||||
|
desc "Generate a new command called NAME"
|
||||||
|
task :generate_command do
|
||||||
|
name = ENV['NAME'] or raise "Provide a name with NAME="
|
||||||
|
|
||||||
|
header = "src/#{name}.h"
|
||||||
|
source = "src/#{name}.cpp"
|
||||||
|
|
||||||
|
%w(h cpp).each do |extension|
|
||||||
|
File.open("templates/Command.#{extension}", "r") do |source_file|
|
||||||
|
contents = source_file.read
|
||||||
|
contents.gsub!("NAME", name)
|
||||||
|
File.open("src/#{name}.#{extension}", "w") do |target_file|
|
||||||
|
target_file.write(contents)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Dir.glob("src/*.pro").each do |project_file_name|
|
||||||
|
project = IO.read(project_file_name)
|
||||||
|
project.gsub!(/(HEADERS = .*)/, "\\1 #{name}.h")
|
||||||
|
project.gsub!(/(SOURCES = .*)/, "\\1 #{name}.cpp")
|
||||||
|
File.open(project_file_name, "w") { |file| file.write(project) }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Generate a Makefile using qmake"
|
||||||
|
file 'Makefile' do
|
||||||
|
sh("qmake -spec macx-g++")
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Regenerate dependencies using qmake"
|
||||||
|
task :qmake => 'Makefile' do
|
||||||
|
sh("make qmake")
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Build the webkit server"
|
||||||
|
task :build => :qmake do
|
||||||
|
sh("make")
|
||||||
|
|
||||||
|
FileUtils.mkdir("bin") unless File.directory?("bin")
|
||||||
|
|
||||||
|
if File.exist?("src/webkit_server.app")
|
||||||
|
FileUtils.cp("src/webkit_server.app/Contents/MacOS/webkit_server", "bin")
|
||||||
|
else
|
||||||
|
FileUtils.cp("src/webkit_server", "bin")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
RSpec::Core::RakeTask.new do |t|
|
||||||
|
t.pattern = "spec/*_spec.rb"
|
||||||
|
t.rspec_opts = "--format progress"
|
||||||
|
end
|
||||||
|
|
||||||
|
desc "Default: build and run all specs"
|
||||||
|
task :default => [:build, :spec]
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
require "capybara"
|
||||||
|
require "capybara/driver/webkit"
|
||||||
|
|
||||||
|
Capybara.register_driver :webkit do |app|
|
||||||
|
Capybara::Driver::Webkit.new(app)
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
require "capybara"
|
||||||
|
require "capybara/driver/webkit/node"
|
||||||
|
require "capybara/driver/webkit/browser"
|
||||||
|
|
||||||
|
class Capybara::Driver::Webkit
|
||||||
|
def initialize(app, options={})
|
||||||
|
@app = app
|
||||||
|
@options = options
|
||||||
|
@rack_server = Capybara::Server.new(@app)
|
||||||
|
@rack_server.boot if Capybara.run_server
|
||||||
|
@browser = Browser.new
|
||||||
|
end
|
||||||
|
|
||||||
|
def current_url
|
||||||
|
raise NotImplementedError
|
||||||
|
end
|
||||||
|
|
||||||
|
def visit(path)
|
||||||
|
@browser.visit(url(path))
|
||||||
|
end
|
||||||
|
|
||||||
|
def find(query)
|
||||||
|
@browser.find(query).map { |native| Node.new(self, native) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def source
|
||||||
|
raise NotImplementedError
|
||||||
|
end
|
||||||
|
|
||||||
|
def body
|
||||||
|
raise NotImplementedError
|
||||||
|
end
|
||||||
|
|
||||||
|
def execute_script(script)
|
||||||
|
raise Capybara::NotSupportedByDriverError
|
||||||
|
end
|
||||||
|
|
||||||
|
def evaluate_script(script)
|
||||||
|
raise Capybara::NotSupportedByDriverError
|
||||||
|
end
|
||||||
|
|
||||||
|
def response_headers
|
||||||
|
raise Capybara::NotSupportedByDriverError
|
||||||
|
end
|
||||||
|
|
||||||
|
def status_code
|
||||||
|
raise Capybara::NotSupportedByDriverError
|
||||||
|
end
|
||||||
|
|
||||||
|
def within_frame(frame_id)
|
||||||
|
raise Capybara::NotSupportedByDriverError
|
||||||
|
end
|
||||||
|
|
||||||
|
def within_window(handle)
|
||||||
|
raise Capybara::NotSupportedByDriverError
|
||||||
|
end
|
||||||
|
|
||||||
|
def wait?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
def wait_until(*args)
|
||||||
|
end
|
||||||
|
|
||||||
|
def reset!
|
||||||
|
@browser.reset!
|
||||||
|
end
|
||||||
|
|
||||||
|
def has_shortcircuit_timeout?
|
||||||
|
false
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def url(path)
|
||||||
|
@rack_server.url(path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
require 'socket'
|
||||||
|
|
||||||
|
class Capybara::Driver::Webkit
|
||||||
|
class Browser
|
||||||
|
def initialize
|
||||||
|
start_server
|
||||||
|
connect
|
||||||
|
end
|
||||||
|
|
||||||
|
def visit(url)
|
||||||
|
command "visit", url
|
||||||
|
end
|
||||||
|
|
||||||
|
def find(query)
|
||||||
|
command("find", query).split(",")
|
||||||
|
end
|
||||||
|
|
||||||
|
def reset!
|
||||||
|
command("reset")
|
||||||
|
end
|
||||||
|
|
||||||
|
private
|
||||||
|
|
||||||
|
def start_server
|
||||||
|
@pid = fork { exec("webkit_server") }
|
||||||
|
at_exit { Process.kill("INT", @pid) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def connect
|
||||||
|
puts ">> Connecting"
|
||||||
|
Capybara.timeout(5) do
|
||||||
|
attempt_connect
|
||||||
|
!@socket.nil?
|
||||||
|
end
|
||||||
|
puts ">> Connected"
|
||||||
|
end
|
||||||
|
|
||||||
|
def attempt_connect
|
||||||
|
@socket = TCPSocket.open("localhost", 9200)
|
||||||
|
rescue Errno::ECONNREFUSED
|
||||||
|
end
|
||||||
|
|
||||||
|
def check
|
||||||
|
result = @socket.gets.strip
|
||||||
|
puts ">> #{result}"
|
||||||
|
unless result == 'ok'
|
||||||
|
raise
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def command(name, *args)
|
||||||
|
puts ">> Sending #{name}"
|
||||||
|
@socket.puts name
|
||||||
|
args.each { |arg| @socket.puts arg }
|
||||||
|
check
|
||||||
|
read_response
|
||||||
|
end
|
||||||
|
|
||||||
|
def read_response
|
||||||
|
response_length = @socket.gets.to_i
|
||||||
|
@socket.read(response_length)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,52 @@
|
||||||
|
class Capybara::Driver::Webkit
|
||||||
|
class Node < Capybara::Driver::Node
|
||||||
|
def text
|
||||||
|
raise NotImplementedError
|
||||||
|
end
|
||||||
|
|
||||||
|
def [](name)
|
||||||
|
raise NotImplementedError
|
||||||
|
end
|
||||||
|
|
||||||
|
def value
|
||||||
|
raise NotImplementedError
|
||||||
|
end
|
||||||
|
|
||||||
|
def set(value)
|
||||||
|
raise NotImplementedError
|
||||||
|
end
|
||||||
|
|
||||||
|
def select_option
|
||||||
|
raise NotImplementedError
|
||||||
|
end
|
||||||
|
|
||||||
|
def unselect_option
|
||||||
|
raise NotImplementedError
|
||||||
|
end
|
||||||
|
|
||||||
|
def click
|
||||||
|
raise NotImplementedError
|
||||||
|
end
|
||||||
|
|
||||||
|
def drag_to(element)
|
||||||
|
raise NotImplementedError
|
||||||
|
end
|
||||||
|
|
||||||
|
def tag_name
|
||||||
|
raise NotImplementedError
|
||||||
|
end
|
||||||
|
|
||||||
|
def visible?
|
||||||
|
raise NotImplementedError
|
||||||
|
end
|
||||||
|
|
||||||
|
def path
|
||||||
|
raise NotSupportedByDriverError
|
||||||
|
end
|
||||||
|
|
||||||
|
def trigger(event)
|
||||||
|
raise NotSupportedByDriverError
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
require 'spec_helper'
|
||||||
|
require 'capybara/driver/webkit'
|
||||||
|
|
||||||
|
describe Capybara::Driver::Webkit do
|
||||||
|
let(:hello_app) do
|
||||||
|
lambda do |env|
|
||||||
|
body = <<-HTML
|
||||||
|
<html><body>
|
||||||
|
<script type="text/javascript">
|
||||||
|
document.write("he" + "llo");
|
||||||
|
</script>
|
||||||
|
</body></html>
|
||||||
|
HTML
|
||||||
|
[200,
|
||||||
|
{ 'Content-Type' => 'text/html', 'Content-Length' => body.length.to_s },
|
||||||
|
[body]]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
subject { Capybara::Driver::Webkit.new(hello_app) }
|
||||||
|
after { subject.reset! }
|
||||||
|
|
||||||
|
it "finds content after loading a URL" do
|
||||||
|
subject.visit("/hello")
|
||||||
|
subject.find("//*[contains(., 'hello')]").should_not be_empty
|
||||||
|
end
|
||||||
|
|
||||||
|
it "has an empty page after reseting" do
|
||||||
|
subject.visit("/")
|
||||||
|
subject.reset!
|
||||||
|
subject.find("//*[contains(., 'hello')]").should be_empty
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
require 'rspec'
|
||||||
|
require 'rspec/autorun'
|
||||||
|
|
||||||
|
PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..')).freeze
|
||||||
|
|
||||||
|
$LOAD_PATH << File.join(PROJECT_ROOT, 'lib')
|
||||||
|
ENV["PATH"] = ENV["PATH"] + ":" + File.join(PROJECT_ROOT, "bin")
|
||||||
|
|
||||||
|
Dir[File.join(PROJECT_ROOT, 'spec', 'support', '**', '*.rb')].each { |file| require(file) }
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
#include "Command.h"
|
||||||
|
#include "WebPage.h"
|
||||||
|
|
||||||
|
Command::Command(WebPage *page, QObject *parent) : QObject(parent) {
|
||||||
|
m_page = page;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Command::receivedArgument(const char *argument) {
|
||||||
|
Q_UNUSED(argument);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Command::start() {
|
||||||
|
}
|
||||||
|
|
||||||
|
WebPage *Command::page() {
|
||||||
|
return m_page;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
#ifndef COMMAND_H
|
||||||
|
#define COMMAND_H
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class WebPage;
|
||||||
|
|
||||||
|
class Command : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Command(WebPage *page, QObject *parent = 0);
|
||||||
|
virtual void start();
|
||||||
|
virtual void receivedArgument(const char *argument);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void finished(bool success, QString &response);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
WebPage *page();
|
||||||
|
|
||||||
|
private:
|
||||||
|
WebPage *m_page;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
#include "Connection.h"
|
||||||
|
#include "Visit.h"
|
||||||
|
#include "Find.h"
|
||||||
|
#include "Command.h"
|
||||||
|
#include "Reset.h"
|
||||||
|
|
||||||
|
#include <QTcpSocket>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
Connection::Connection(QTcpSocket *socket, WebPage *page, QObject *parent) :
|
||||||
|
QObject(parent) {
|
||||||
|
m_socket = socket;
|
||||||
|
m_page = page;
|
||||||
|
m_command = NULL;
|
||||||
|
connect(m_socket, SIGNAL(readyRead()), this, SLOT(checkNext()));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connection::checkNext() {
|
||||||
|
std::cout << "<< Data ready to read" << std::endl;
|
||||||
|
while (m_socket->canReadLine()) {
|
||||||
|
readNext();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connection::readNext() {
|
||||||
|
std::cout << "<< Reading line" << std::endl;
|
||||||
|
char buffer[1024];
|
||||||
|
qint64 lineLength = m_socket->readLine(buffer, 1024);
|
||||||
|
if (lineLength != -1) {
|
||||||
|
buffer[lineLength - 1] = 0;
|
||||||
|
std::cout << "<< Got line: " << buffer << std::endl;
|
||||||
|
if (m_command) {
|
||||||
|
m_command->receivedArgument(buffer);
|
||||||
|
} else {
|
||||||
|
m_command = startCommand(buffer);
|
||||||
|
if (m_command) {
|
||||||
|
connect(m_command,
|
||||||
|
SIGNAL(finished(bool, QString &)),
|
||||||
|
this,
|
||||||
|
SLOT(finishCommand(bool, QString &)));
|
||||||
|
m_command->start();
|
||||||
|
} else {
|
||||||
|
m_socket->write("bad command\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Command *Connection::startCommand(const char *name) {
|
||||||
|
if (strcmp(name, "visit") == 0) {
|
||||||
|
return new Visit(m_page, this);
|
||||||
|
} else if (strcmp(name, "find") == 0) {
|
||||||
|
return new Find(m_page, this);
|
||||||
|
} else if (strcmp(name, "reset") == 0) {
|
||||||
|
return new Reset(m_page, this);
|
||||||
|
} else {
|
||||||
|
std::cout << ">> Unknown command" << std::endl;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Connection::finishCommand(bool success, QString &response) {
|
||||||
|
m_command->deleteLater();
|
||||||
|
m_command = NULL;
|
||||||
|
if (success) {
|
||||||
|
m_socket->write("ok\n");
|
||||||
|
QString responseLength = QString::number(response.size()) + "\n";
|
||||||
|
m_socket->write(responseLength.toAscii());
|
||||||
|
m_socket->write(response.toAscii());
|
||||||
|
} else {
|
||||||
|
m_socket->write("failure\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QTcpSocket;
|
||||||
|
class WebPage;
|
||||||
|
class Command;
|
||||||
|
|
||||||
|
class Connection : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Connection(QTcpSocket *socket, WebPage *page, QObject *parent = 0);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void checkNext();
|
||||||
|
void finishCommand(bool success, QString &response);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void readNext();
|
||||||
|
Command *startCommand(const char *name);
|
||||||
|
|
||||||
|
QTcpSocket *m_socket;
|
||||||
|
Command *m_command;
|
||||||
|
WebPage *m_page;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
#include "Find.h"
|
||||||
|
#include "Command.h"
|
||||||
|
#include "WebPage.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
Find::Find(WebPage *page, QObject *parent) : Command(page, parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Find::receivedArgument(const char *xpath) {
|
||||||
|
std::cout << "<< Running query: " << xpath << std::endl;
|
||||||
|
QString javascript = QString("\
|
||||||
|
(function () {\
|
||||||
|
if (!window.__capybara_index) {\
|
||||||
|
window.__capybara_index = 0;\
|
||||||
|
window.__capybara_nodes = {};\
|
||||||
|
}\
|
||||||
|
var iterator = document.evaluate(\"") + xpath + "\",\
|
||||||
|
document,\
|
||||||
|
null,\
|
||||||
|
XPathResult.ORDERED_NODE_ITERATOR_TYPE,\
|
||||||
|
null);\
|
||||||
|
var node;\
|
||||||
|
var results = [];\
|
||||||
|
while (node = iterator.iterateNext()) {\
|
||||||
|
window.__capybara_index++;\
|
||||||
|
window.__capybara_nodes[window.__capybara_index] = node;\
|
||||||
|
results.push(window.__capybara_index);\
|
||||||
|
}\
|
||||||
|
return results;\
|
||||||
|
})()\
|
||||||
|
";
|
||||||
|
|
||||||
|
|
||||||
|
std::cout << "<< Javascript to execute:" << std::endl;
|
||||||
|
std::cout << javascript.toAscii().data() << std::endl;
|
||||||
|
|
||||||
|
QVariant result = page()->mainFrame()->evaluateJavaScript(javascript);
|
||||||
|
|
||||||
|
QVariantList nodes = result.toList();
|
||||||
|
QString response;
|
||||||
|
bool addComma = false;
|
||||||
|
|
||||||
|
double node;
|
||||||
|
for (int i = 0; i < nodes.size(); i++) {
|
||||||
|
node = nodes[i].toDouble();
|
||||||
|
if (addComma)
|
||||||
|
response.append(",");
|
||||||
|
response.append(QString::number(node));
|
||||||
|
addComma = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "<< Got result:" << std::endl;
|
||||||
|
std::cout << response.toAscii().data() << std::endl;
|
||||||
|
|
||||||
|
emit finished(true, response);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include "Command.h"
|
||||||
|
|
||||||
|
class WebPage;
|
||||||
|
|
||||||
|
class Find : public Command {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Find(WebPage *page, QObject *parent = 0);
|
||||||
|
virtual void receivedArgument(const char *argument);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include "Reset.h"
|
||||||
|
#include "WebPage.h"
|
||||||
|
|
||||||
|
Reset::Reset(WebPage *page, QObject *parent) : Command(page, parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void Reset::start() {
|
||||||
|
page()->triggerAction(QWebPage::Stop);
|
||||||
|
page()->mainFrame()->setHtml("<html><body></body></html>");
|
||||||
|
QString response = "";
|
||||||
|
emit finished(true, response);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,12 @@
|
||||||
|
#include "Command.h"
|
||||||
|
|
||||||
|
class WebPage;
|
||||||
|
|
||||||
|
class Reset : public Command {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Reset(WebPage *page, QObject *parent = 0);
|
||||||
|
virtual void start();
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
#include "Server.h"
|
||||||
|
#include "WebPage.h"
|
||||||
|
#include "Connection.h"
|
||||||
|
|
||||||
|
#include <QTcpServer>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
Server::Server(QObject *parent) : QObject(parent) {
|
||||||
|
m_tcp_server = new QTcpServer(this);
|
||||||
|
m_page = new WebPage(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Server::start() {
|
||||||
|
connect(m_tcp_server, SIGNAL(newConnection()), this, SLOT(handleConnection()));
|
||||||
|
return m_tcp_server->listen(QHostAddress::Any, 9200);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Server::handleConnection() {
|
||||||
|
std::cout << "<< Got connection" << std::endl;
|
||||||
|
QTcpSocket *socket = m_tcp_server->nextPendingConnection();
|
||||||
|
new Connection(socket, m_page, this);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
#include <QObject>
|
||||||
|
|
||||||
|
class QTcpServer;
|
||||||
|
class WebPage;
|
||||||
|
|
||||||
|
class Server : public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Server(QObject *parent = 0);
|
||||||
|
bool start();
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void handleConnection();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTcpServer *m_tcp_server;
|
||||||
|
WebPage *m_page;
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
#include "Visit.h"
|
||||||
|
#include "Command.h"
|
||||||
|
#include "WebPage.h"
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
Visit::Visit(WebPage *page, QObject *parent) : Command(page, parent) {
|
||||||
|
connect(page, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Visit::receivedArgument(const char *url) {
|
||||||
|
std::cout << ">> Loading page: " << url << std::endl;
|
||||||
|
page()->mainFrame()->setUrl(QUrl(url));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Visit::loadFinished(bool success) {
|
||||||
|
std::cout << ">> Page loaded" << std::endl;
|
||||||
|
QString response;
|
||||||
|
std::cout << page()->mainFrame()->toHtml().toAscii().constData() << std::endl;
|
||||||
|
emit finished(success, response);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
#include "Command.h"
|
||||||
|
|
||||||
|
class WebPage;
|
||||||
|
|
||||||
|
class Visit : public Command {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
Visit(WebPage *page, QObject *parent = 0);
|
||||||
|
virtual void receivedArgument(const char *argument);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void loadFinished(bool success);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
#include "WebPage.h"
|
||||||
|
|
||||||
|
WebPage::WebPage(QObject *parent) : QWebPage(parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool WebPage::shouldInterruptJavaScript() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include <QtWebKit>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
class WebPage : public QWebPage {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
WebPage(QObject *parent = 0);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
bool shouldInterruptJavaScript();
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
#include "Server.h"
|
||||||
|
#include <QtGui>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
int main(int argc, char **argv) {
|
||||||
|
QApplication app(argc, argv);
|
||||||
|
app.setApplicationName("akephalos-webkit");
|
||||||
|
app.setOrganizationName("thoughtbot, inc");
|
||||||
|
app.setOrganizationDomain("thoughtbot.com");
|
||||||
|
|
||||||
|
Server server;
|
||||||
|
if (server.start()) {
|
||||||
|
std::cout << "<< Started server" << std::endl;
|
||||||
|
|
||||||
|
return app.exec();
|
||||||
|
} else {
|
||||||
|
std::cerr << "Couldn't start server" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
TEMPLATE = app
|
||||||
|
TARGET = webkit_server
|
||||||
|
DESTDIR = .
|
||||||
|
HEADERS = WebPage.h Server.h Connection.h Command.h Visit.h Find.h Reset.h
|
||||||
|
SOURCES = main.cpp WebPage.cpp Server.cpp Connection.cpp Command.cpp Visit.cpp Find.cpp Reset.cpp
|
||||||
|
QT += network webkit
|
||||||
|
CONFIG += console staticlib
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include "NAME.h"
|
||||||
|
#include "WebPage.h"
|
||||||
|
|
||||||
|
NAME::NAME(WebPage *page, QObject *parent) : Command(page, parent) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void NAME::start() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void NAME::receivedArgument(const char *argument) {
|
||||||
|
Q_UNUSED(argument);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
#include "Command.h"
|
||||||
|
|
||||||
|
class WebPage;
|
||||||
|
|
||||||
|
class NAME : public Command {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
NAME(WebPage *page, QObject *parent = 0);
|
||||||
|
virtual void start();
|
||||||
|
virtual void receivedArgument(const char *argument);
|
||||||
|
};
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
TEMPLATE = subdirs
|
||||||
|
CONFIG += ordered
|
||||||
|
SUBDIRS += src/webkit_server.pro
|
||||||
|
|
Loading…
Reference in New Issue