capybara-webkit 0.12.1 → 0.13.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (141) hide show
  1. data/.gitignore +2 -1
  2. data/GOALS +9 -0
  3. data/Gemfile.lock +15 -12
  4. data/LICENSE +1 -1
  5. data/NEWS.md +18 -0
  6. data/README.md +81 -2
  7. data/capybara-webkit.gemspec +1 -1
  8. data/lib/capybara/webkit.rb +11 -6
  9. data/lib/capybara/{driver/webkit → webkit}/browser.rb +90 -4
  10. data/lib/capybara/{driver/webkit → webkit}/connection.rb +48 -47
  11. data/lib/capybara/{driver/webkit → webkit}/cookie_jar.rb +1 -1
  12. data/lib/capybara/webkit/driver.rb +186 -0
  13. data/lib/capybara/webkit/errors.rb +10 -0
  14. data/lib/capybara/{driver/webkit → webkit}/node.rb +12 -4
  15. data/lib/capybara/{driver/webkit → webkit}/socket_debugger.rb +4 -1
  16. data/lib/capybara/{driver/webkit → webkit}/version.rb +1 -1
  17. data/lib/capybara_webkit_builder.rb +17 -3
  18. data/spec/browser_spec.rb +95 -7
  19. data/spec/connection_spec.rb +16 -5
  20. data/spec/cookie_jar_spec.rb +3 -3
  21. data/spec/driver_rendering_spec.rb +19 -26
  22. data/spec/driver_resize_window_spec.rb +3 -3
  23. data/spec/driver_spec.rb +1200 -822
  24. data/spec/integration/driver_spec.rb +4 -3
  25. data/spec/selenium_compatibility_spec.rb +49 -0
  26. data/spec/spec_helper.rb +14 -6
  27. data/spec/support/app_runner.rb +94 -0
  28. data/src/Authenticate.cpp +18 -0
  29. data/src/Authenticate.h +12 -0
  30. data/src/Body.h +3 -5
  31. data/src/ClearCookies.cpp +3 -5
  32. data/src/ClearCookies.h +3 -5
  33. data/src/ClearPromptText.cpp +11 -0
  34. data/src/ClearPromptText.h +9 -0
  35. data/src/Command.cpp +4 -15
  36. data/src/Command.h +3 -14
  37. data/src/CommandFactory.cpp +20 -6
  38. data/src/CommandFactory.h +3 -2
  39. data/src/CommandParser.cpp +1 -1
  40. data/src/Connection.cpp +22 -21
  41. data/src/Connection.h +5 -6
  42. data/src/ConsoleMessages.cpp +2 -1
  43. data/src/ConsoleMessages.h +3 -5
  44. data/src/CurrentUrl.cpp +9 -48
  45. data/src/CurrentUrl.h +8 -8
  46. data/src/EnableLogging.cpp +10 -0
  47. data/src/EnableLogging.h +12 -0
  48. data/src/Evaluate.cpp +2 -1
  49. data/src/Evaluate.h +3 -5
  50. data/src/Execute.cpp +2 -1
  51. data/src/Execute.h +3 -5
  52. data/src/Find.cpp +3 -2
  53. data/src/Find.h +3 -5
  54. data/src/FrameFocus.cpp +3 -2
  55. data/src/FrameFocus.h +3 -4
  56. data/src/GetCookies.cpp +3 -4
  57. data/src/GetCookies.h +3 -5
  58. data/src/GetTimeout.cpp +9 -0
  59. data/src/GetTimeout.h +11 -0
  60. data/src/GetWindowHandle.cpp +11 -0
  61. data/src/GetWindowHandle.h +10 -0
  62. data/src/GetWindowHandles.cpp +20 -0
  63. data/src/GetWindowHandles.h +10 -0
  64. data/src/Header.cpp +2 -1
  65. data/src/Header.h +3 -5
  66. data/src/Headers.cpp +8 -2
  67. data/src/Headers.h +3 -5
  68. data/src/IgnoreSslErrors.cpp +4 -3
  69. data/src/IgnoreSslErrors.h +3 -5
  70. data/src/JavascriptAlertMessages.cpp +10 -0
  71. data/src/JavascriptAlertMessages.h +9 -0
  72. data/src/JavascriptConfirmMessages.cpp +10 -0
  73. data/src/JavascriptConfirmMessages.h +9 -0
  74. data/src/JavascriptInvocation.cpp +1 -1
  75. data/src/JavascriptInvocation.h +1 -1
  76. data/src/JavascriptPromptMessages.cpp +10 -0
  77. data/src/JavascriptPromptMessages.h +9 -0
  78. data/src/NetworkAccessManager.cpp +38 -5
  79. data/src/NetworkAccessManager.h +20 -0
  80. data/src/Node.cpp +6 -1
  81. data/src/Node.h +4 -5
  82. data/src/NullCommand.cpp +5 -2
  83. data/src/NullCommand.h +4 -3
  84. data/src/PageLoadingCommand.cpp +12 -7
  85. data/src/PageLoadingCommand.h +6 -9
  86. data/src/Render.cpp +2 -1
  87. data/src/Render.h +3 -5
  88. data/src/RequestedUrl.cpp +2 -1
  89. data/src/RequestedUrl.h +3 -5
  90. data/src/Reset.cpp +3 -17
  91. data/src/Reset.h +3 -8
  92. data/src/ResizeWindow.cpp +2 -1
  93. data/src/ResizeWindow.h +3 -5
  94. data/src/Response.cpp +4 -0
  95. data/src/Response.h +1 -0
  96. data/src/Server.cpp +2 -3
  97. data/src/Server.h +0 -2
  98. data/src/SetConfirmAction.cpp +11 -0
  99. data/src/SetConfirmAction.h +9 -0
  100. data/src/SetCookie.cpp +3 -4
  101. data/src/SetCookie.h +3 -5
  102. data/src/SetPromptAction.cpp +11 -0
  103. data/src/SetPromptAction.h +9 -0
  104. data/src/SetPromptText.cpp +11 -0
  105. data/src/SetPromptText.h +9 -0
  106. data/src/SetProxy.cpp +2 -1
  107. data/src/SetProxy.h +3 -5
  108. data/src/SetSkipImageLoading.cpp +12 -0
  109. data/src/SetSkipImageLoading.h +9 -0
  110. data/src/SetTimeout.cpp +19 -0
  111. data/src/SetTimeout.h +9 -0
  112. data/src/SocketCommand.cpp +21 -0
  113. data/src/SocketCommand.h +29 -0
  114. data/src/Source.cpp +3 -2
  115. data/src/Source.h +3 -4
  116. data/src/Status.cpp +2 -1
  117. data/src/Status.h +3 -5
  118. data/src/TimeoutCommand.cpp +69 -0
  119. data/src/TimeoutCommand.h +41 -0
  120. data/src/UnsupportedContentHandler.cpp +11 -17
  121. data/src/UnsupportedContentHandler.h +5 -3
  122. data/src/Url.cpp +2 -1
  123. data/src/Url.h +3 -5
  124. data/src/Visit.cpp +3 -2
  125. data/src/Visit.h +3 -5
  126. data/src/WebPage.cpp +129 -44
  127. data/src/WebPage.h +37 -11
  128. data/src/WebPageManager.cpp +127 -0
  129. data/src/WebPageManager.h +59 -0
  130. data/src/WindowFocus.cpp +32 -0
  131. data/src/WindowFocus.h +15 -0
  132. data/src/body.cpp +2 -1
  133. data/src/capybara.js +38 -10
  134. data/src/find_command.h +17 -2
  135. data/src/main.cpp +0 -2
  136. data/src/webkit_server.pro +36 -0
  137. data/templates/Command.cpp +2 -4
  138. data/templates/Command.h +3 -3
  139. metadata +106 -27
  140. data/ChangeLog +0 -70
  141. data/lib/capybara/driver/webkit.rb +0 -136
@@ -1,9 +1,9 @@
1
1
  require 'spec_helper'
2
- require 'capybara/driver/webkit'
2
+ require 'capybara/webkit/driver'
3
3
 
4
- describe Capybara::Driver::Webkit do
4
+ describe Capybara::Webkit::Driver do
5
5
  before do
6
- @driver = Capybara::Driver::Webkit.new(TestApp, :browser => $webkit_browser)
6
+ @driver = Capybara::Webkit::Driver.new(TestApp, :browser => $webkit_browser)
7
7
  end
8
8
 
9
9
  it_should_behave_like "driver"
@@ -12,6 +12,7 @@ describe Capybara::Driver::Webkit do
12
12
  it_should_behave_like "driver with header support"
13
13
  it_should_behave_like "driver with status code support"
14
14
  it_should_behave_like "driver with frame support"
15
+ it_should_behave_like "driver with support for window switching"
15
16
 
16
17
  it "returns the rack server port" do
17
18
  @driver.server_port.should eq(@driver.instance_variable_get(:@rack_server).port)
@@ -0,0 +1,49 @@
1
+ require 'spec_helper'
2
+
3
+ describe Capybara::Webkit, 'compatibility with selenium' do
4
+ include AppRunner
5
+
6
+ it 'generates the same events as selenium when filling out forms' do
7
+ run_application_for_html(<<-HTML)
8
+ <html><body>
9
+ <form onsubmit="return false">
10
+ <label for="one">One</label><input type="text" name="one" id="one" />
11
+ <label for="two">Two</label><input type="text" name="two" id="two" />
12
+ <input type="submit" value="Submit" id="submit" />
13
+ </form>
14
+ <script type="text/javascript">
15
+ window.log = [];
16
+ var recordEvent = function (event) {
17
+ log.push(event.target.id + '.' + event.type);
18
+ };
19
+ var elements = document.getElementsByTagName("input");
20
+ var events = ["mousedown", "mouseup", "click", "keyup", "keydown",
21
+ "keypress", "focus", "blur"];
22
+ for (var i = 0; i < elements.length; i++) {
23
+ for (var j = 0; j < events.length; j++) {
24
+ elements[i].addEventListener(events[j], recordEvent);
25
+ }
26
+ }
27
+ </script>
28
+ </body></html>
29
+ HTML
30
+
31
+ compare_events_for_drivers(:reusable_webkit, :selenium) do
32
+ visit "/"
33
+ fill_in "One", :with => "some value"
34
+ fill_in "One", :with => "a new value"
35
+ fill_in "Two", :with => "other value"
36
+ click_button "Submit"
37
+ end
38
+ end
39
+
40
+ def compare_events_for_drivers(first, second, &block)
41
+ events_for_driver(first, &block).should == events_for_driver(second, &block)
42
+ end
43
+
44
+ def events_for_driver(name, &block)
45
+ session = Capybara::Session.new(name, AppRunner.app)
46
+ session.instance_eval(&block)
47
+ session.evaluate_script("window.log")
48
+ end
49
+ end
@@ -1,6 +1,7 @@
1
1
  require 'rspec'
2
2
  require 'rspec/autorun'
3
3
  require 'rbconfig'
4
+ require 'capybara'
4
5
 
5
6
  PROJECT_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..')).freeze
6
7
 
@@ -20,15 +21,22 @@ RSpec.configure do |c|
20
21
  c.filter_run_excluding :skip_on_windows => !(RbConfig::CONFIG['host_os'] =~ /mingw32/).nil?
21
22
  end
22
23
 
23
- require File.join(spec_dir, "spec_helper")
24
+ require 'capybara/webkit'
25
+ connection = Capybara::Webkit::Connection.new(:socket_class => TCPSocket, :stdout => nil)
26
+ $webkit_browser = Capybara::Webkit::Browser.new(connection)
27
+
28
+ if ENV['DEBUG']
29
+ $webkit_browser.enable_logging
30
+ end
24
31
 
25
- require 'capybara/driver/webkit/connection'
26
- require 'capybara/driver/webkit/browser'
27
- connection = Capybara::Driver::Webkit::Connection.new(:socket_class => TCPSocket, :stdout => nil)
28
- $webkit_browser = Capybara::Driver::Webkit::Browser.new(connection)
32
+ RSpec.configure do |config|
33
+ config.before { $webkit_browser.reset! }
34
+ end
35
+
36
+ require File.join(spec_dir, "spec_helper")
29
37
 
30
38
  Capybara.register_driver :reusable_webkit do |app|
31
- Capybara::Driver::Webkit.new(app, :browser => $webkit_browser)
39
+ Capybara::Webkit::Driver.new(app, :browser => $webkit_browser)
32
40
  end
33
41
 
34
42
  def with_env_vars(vars)
@@ -0,0 +1,94 @@
1
+ # Boots a single Capybara::Server for a Rack application that delegates to another, singleton Rack
2
+ # application that can be configured for each spec. Also configures Capybara to use that server.
3
+
4
+ require 'sinatra/base'
5
+
6
+ module AppRunner
7
+ class << self
8
+ attr_accessor :app, :app_host
9
+ end
10
+
11
+ def self.boot
12
+ app_container = lambda { |env| AppRunner.app.call(env) }
13
+ server = Capybara::Server.new(app_container)
14
+ server.boot
15
+ self.app_host = "http://127.0.0.1:#{server.port}"
16
+ end
17
+
18
+ def self.reset
19
+ self.app = lambda do |env|
20
+ [200, { 'Content-Type' => 'html', 'Content-Length' => 0 }, []]
21
+ end
22
+ end
23
+
24
+ def run_application(app)
25
+ AppRunner.app = app
26
+ end
27
+
28
+ def driver_for_app(&body)
29
+ app = Class.new(ExampleApp, &body)
30
+ run_application app
31
+ build_driver
32
+ end
33
+
34
+ def driver_for_html(html)
35
+ run_application_for_html html
36
+ build_driver
37
+ end
38
+
39
+ def run_application_for_html(html)
40
+ run_application lambda { |env|
41
+ [200, { 'Content-Type' => 'text/html', 'Content-Length' => html.size.to_s }, [html]]
42
+ }
43
+ end
44
+
45
+ private
46
+
47
+ def build_driver
48
+ Capybara::Webkit::Driver.new(AppRunner.app, :browser => $webkit_browser)
49
+ end
50
+
51
+ def self.included(example_group)
52
+ example_group.class_eval do
53
+ before { AppRunner.reset }
54
+
55
+ around do |example|
56
+ Capybara.run_server = false
57
+ Capybara.app_host = AppRunner.app_host
58
+ begin
59
+ example.run
60
+ ensure
61
+ Capybara.run_server = true
62
+ Capybara.app_host = nil
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+
69
+ class ExampleApp < Sinatra::Base
70
+ # Sinatra fixes invalid responses that would break QWebPage, so this middleware breaks them again
71
+ # for testing purposes.
72
+ class ResponseInvalidator
73
+ def initialize(app)
74
+ @app = app
75
+ end
76
+
77
+ def call(env)
78
+ response = @app.call(env)
79
+ if response.to_a[1]['X-Response-Invalid']
80
+ [404, {}, []]
81
+ else
82
+ response
83
+ end
84
+ end
85
+ end
86
+
87
+ use ResponseInvalidator
88
+
89
+ def invalid_response
90
+ [200, { 'X-Response-Invalid' => 'TRUE' }, []]
91
+ end
92
+ end
93
+
94
+ AppRunner.boot
@@ -0,0 +1,18 @@
1
+ #include "Authenticate.h"
2
+ #include "WebPage.h"
3
+ #include "NetworkAccessManager.h"
4
+
5
+ Authenticate::Authenticate(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {
6
+ }
7
+
8
+ void Authenticate::start() {
9
+ QString username = arguments()[0];
10
+ QString password = arguments()[1];
11
+
12
+ NetworkAccessManager* networkAccessManager = qobject_cast<NetworkAccessManager*>(page()->networkAccessManager());
13
+ networkAccessManager->setUserName(username);
14
+ networkAccessManager->setPassword(password);
15
+
16
+ emit finished(new Response(true));
17
+ }
18
+
@@ -0,0 +1,12 @@
1
+ #include "SocketCommand.h"
2
+
3
+ class WebPage;
4
+
5
+ class Authenticate : public SocketCommand {
6
+ Q_OBJECT
7
+
8
+ public:
9
+ Authenticate(WebPageManager *manager, QStringList &arguments, QObject *parent = 0);
10
+ virtual void start();
11
+ };
12
+
data/src/Body.h CHANGED
@@ -1,12 +1,10 @@
1
- #include "Command.h"
1
+ #include "SocketCommand.h"
2
2
 
3
- class WebPage;
4
-
5
- class Body : public Command {
3
+ class Body : public SocketCommand {
6
4
  Q_OBJECT
7
5
 
8
6
  public:
9
- Body(WebPage *page, QStringList &arguments, QObject *parent = 0);
7
+ Body(WebPageManager *, QStringList &arguments, QObject *parent = 0);
10
8
  virtual void start();
11
9
  };
12
10
 
@@ -1,15 +1,13 @@
1
1
  #include "ClearCookies.h"
2
2
  #include "WebPage.h"
3
+ #include "WebPageManager.h"
3
4
  #include "NetworkCookieJar.h"
4
5
  #include <QNetworkCookie>
5
6
 
6
- ClearCookies::ClearCookies(WebPage *page, QStringList &arguments, QObject *parent) : Command(page, arguments, parent) {}
7
+ ClearCookies::ClearCookies(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {}
7
8
 
8
9
  void ClearCookies::start()
9
10
  {
10
- NetworkCookieJar *jar = qobject_cast<NetworkCookieJar*>(page()
11
- ->networkAccessManager()
12
- ->cookieJar());
13
- jar->clearCookies();
11
+ manager()->cookieJar()->clearCookies();
14
12
  emit finished(new Response(true));
15
13
  }
@@ -1,11 +1,9 @@
1
- #include "Command.h"
1
+ #include "SocketCommand.h"
2
2
 
3
- class WebPage;
4
-
5
- class ClearCookies : public Command {
3
+ class ClearCookies : public SocketCommand {
6
4
  Q_OBJECT;
7
5
 
8
6
  public:
9
- ClearCookies(WebPage *page, QStringList &arguments, QObject *parent = 0);
7
+ ClearCookies(WebPageManager *, QStringList &arguments, QObject *parent = 0);
10
8
  virtual void start();
11
9
  };
@@ -0,0 +1,11 @@
1
+ #include "ClearPromptText.h"
2
+ #include "WebPage.h"
3
+ #include "WebPageManager.h"
4
+
5
+ ClearPromptText::ClearPromptText(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {}
6
+
7
+ void ClearPromptText::start()
8
+ {
9
+ page()->setPromptText(QString());
10
+ emit finished(new Response(true));
11
+ }
@@ -0,0 +1,9 @@
1
+ #include "SocketCommand.h"
2
+
3
+ class ClearPromptText : public SocketCommand {
4
+ Q_OBJECT;
5
+
6
+ public:
7
+ ClearPromptText(WebPageManager *manager, QStringList &arguments, QObject *parent = 0);
8
+ virtual void start();
9
+ };
@@ -1,19 +1,8 @@
1
- #include "Command.h"
2
- #include "WebPage.h"
1
+ #include "SocketCommand.h"
3
2
 
4
- Command::Command(WebPage *page, QStringList &arguments, QObject *parent) : QObject(parent) {
5
- m_page = page;
6
- m_arguments = arguments;
3
+ Command::Command(QObject *parent) : QObject(parent) {
7
4
  }
8
5
 
9
- void Command::start() {
6
+ QString Command::toString() const {
7
+ return metaObject()->className();
10
8
  }
11
-
12
- WebPage *Command::page() {
13
- return m_page;
14
- }
15
-
16
- QStringList &Command::arguments() {
17
- return m_arguments;
18
- }
19
-
@@ -2,29 +2,18 @@
2
2
  #define COMMAND_H
3
3
 
4
4
  #include <QObject>
5
- #include <QStringList>
6
5
  #include "Response.h"
7
6
 
8
- class WebPage;
9
-
10
7
  class Command : public QObject {
11
8
  Q_OBJECT
12
9
 
13
10
  public:
14
- Command(WebPage *page, QStringList &arguments, QObject *parent = 0);
15
- virtual void start();
11
+ Command(QObject *parent = 0);
12
+ virtual void start() = 0;
13
+ virtual QString toString() const;
16
14
 
17
15
  signals:
18
16
  void finished(Response *response);
19
-
20
- protected:
21
- WebPage *page();
22
- QStringList &arguments();
23
-
24
- private:
25
- WebPage *m_page;
26
- QStringList m_arguments;
27
-
28
17
  };
29
18
 
30
19
  #endif
@@ -1,8 +1,8 @@
1
1
  #include "CommandFactory.h"
2
2
  #include "NullCommand.h"
3
+ #include "SocketCommand.h"
3
4
  #include "Visit.h"
4
5
  #include "Find.h"
5
- #include "Command.h"
6
6
  #include "Reset.h"
7
7
  #include "Node.h"
8
8
  #include "Url.h"
@@ -22,16 +22,30 @@
22
22
  #include "ConsoleMessages.h"
23
23
  #include "RequestedUrl.h"
24
24
  #include "CurrentUrl.h"
25
+ #include "SetTimeout.h"
26
+ #include "GetTimeout.h"
25
27
  #include "ResizeWindow.h"
26
28
  #include "IgnoreSslErrors.h"
29
+ #include "SetSkipImageLoading.h"
30
+ #include "WindowFocus.h"
31
+ #include "GetWindowHandles.h"
32
+ #include "GetWindowHandle.h"
33
+ #include "WebPageManager.h"
34
+ #include "Authenticate.h"
35
+ #include "EnableLogging.h"
36
+ #include "SetConfirmAction.h"
37
+ #include "SetPromptAction.h"
38
+ #include "SetPromptText.h"
39
+ #include "ClearPromptText.h"
40
+ #include "JavascriptAlertMessages.h"
41
+ #include "JavascriptConfirmMessages.h"
42
+ #include "JavascriptPromptMessages.h"
27
43
 
28
- CommandFactory::CommandFactory(WebPage *page, QObject *parent) : QObject(parent) {
29
- m_page = page;
44
+ CommandFactory::CommandFactory(WebPageManager *manager, QObject *parent) : QObject(parent) {
45
+ m_manager = manager;
30
46
  }
31
47
 
32
48
  Command *CommandFactory::createCommand(const char *name, QStringList &arguments) {
33
49
  #include "find_command.h"
34
- arguments.clear();
35
- arguments.append(QString(name));
36
- return new NullCommand(m_page, arguments);
50
+ return new NullCommand(QString(name));
37
51
  }
@@ -2,15 +2,16 @@
2
2
 
3
3
  class Command;
4
4
  class WebPage;
5
+ class WebPageManager;
5
6
 
6
7
  class CommandFactory : public QObject {
7
8
  Q_OBJECT
8
9
 
9
10
  public:
10
- CommandFactory(WebPage *page, QObject *parent = 0);
11
+ CommandFactory(WebPageManager *, QObject *parent = 0);
11
12
  Command *createCommand(const char *name, QStringList &arguments);
12
13
 
13
14
  private:
14
- WebPage *m_page;
15
+ WebPageManager *m_manager;
15
16
  };
16
17
 
@@ -1,6 +1,6 @@
1
1
  #include "CommandParser.h"
2
2
  #include "CommandFactory.h"
3
- #include "Command.h"
3
+ #include "SocketCommand.h"
4
4
 
5
5
  #include <QIODevice>
6
6
 
@@ -1,58 +1,54 @@
1
1
  #include "Connection.h"
2
2
  #include "WebPage.h"
3
+ #include "WebPageManager.h"
3
4
  #include "CommandParser.h"
4
5
  #include "CommandFactory.h"
5
6
  #include "PageLoadingCommand.h"
6
- #include "Command.h"
7
+ #include "TimeoutCommand.h"
8
+ #include "SocketCommand.h"
7
9
 
8
10
  #include <QTcpSocket>
9
11
 
10
- Connection::Connection(QTcpSocket *socket, WebPage *page, QObject *parent) :
12
+ Connection::Connection(QTcpSocket *socket, WebPageManager *manager, QObject *parent) :
11
13
  QObject(parent) {
12
14
  m_socket = socket;
13
- m_page = page;
14
- m_commandFactory = new CommandFactory(page, this);
15
+ m_manager = manager;
16
+ m_commandFactory = new CommandFactory(m_manager, this);
15
17
  m_commandParser = new CommandParser(socket, m_commandFactory, this);
16
18
  m_pageSuccess = true;
17
- m_commandWaiting = false;
18
19
  connect(m_socket, SIGNAL(readyRead()), m_commandParser, SLOT(checkNext()));
19
20
  connect(m_commandParser, SIGNAL(commandReady(Command *)), this, SLOT(commandReady(Command *)));
20
- connect(m_page, SIGNAL(pageFinished(bool)), this, SLOT(pendingLoadFinished(bool)));
21
+ connect(m_manager, SIGNAL(pageFinished(bool)), this, SLOT(pendingLoadFinished(bool)));
21
22
  }
22
23
 
23
24
  void Connection::commandReady(Command *command) {
24
- m_queuedCommand = command;
25
- if (m_page->isLoading())
26
- m_commandWaiting = true;
27
- else
28
- startCommand();
25
+ m_manager->logger() << "Received" << command->toString();
26
+ startCommand(command);
29
27
  }
30
28
 
31
- void Connection::startCommand() {
32
- m_commandWaiting = false;
29
+ void Connection::startCommand(Command *command) {
33
30
  if (m_pageSuccess) {
34
- m_runningCommand = new PageLoadingCommand(m_queuedCommand, m_page, this);
35
- connect(m_runningCommand, SIGNAL(finished(Response *)), this, SLOT(finishCommand(Response *)));
36
- m_runningCommand->start();
31
+ command = new TimeoutCommand(new PageLoadingCommand(command, m_manager, this), m_manager, this);
32
+ connect(command, SIGNAL(finished(Response *)), this, SLOT(finishCommand(Response *)));
33
+ command->start();
37
34
  } else {
38
35
  writePageLoadFailure();
39
36
  }
40
37
  }
41
38
 
42
39
  void Connection::pendingLoadFinished(bool success) {
43
- m_pageSuccess = success;
44
- if (m_commandWaiting)
45
- startCommand();
40
+ m_pageSuccess = m_pageSuccess && success;
46
41
  }
47
42
 
48
43
  void Connection::writePageLoadFailure() {
49
44
  m_pageSuccess = true;
50
- QString message = m_page->failureString();
45
+ QString message = currentPage()->failureString();
51
46
  writeResponse(new Response(false, message));
52
47
  }
53
48
 
54
49
  void Connection::finishCommand(Response *response) {
55
- m_runningCommand->deleteLater();
50
+ m_pageSuccess = true;
51
+ sender()->deleteLater();
56
52
  writeResponse(response);
57
53
  }
58
54
 
@@ -62,6 +58,8 @@ void Connection::writeResponse(Response *response) {
62
58
  else
63
59
  m_socket->write("failure\n");
64
60
 
61
+ m_manager->logger() << "Wrote response" << response->isSuccess() << response->message();
62
+
65
63
  QByteArray messageUtf8 = response->message();
66
64
  QString messageLength = QString::number(messageUtf8.size()) + "\n";
67
65
  m_socket->write(messageLength.toAscii());
@@ -69,3 +67,6 @@ void Connection::writeResponse(Response *response) {
69
67
  delete response;
70
68
  }
71
69
 
70
+ WebPage *Connection::currentPage() {
71
+ return m_manager->currentPage();
72
+ }