Permalink
Browse files

Fix status code and headers for iframes

QWebFrame::url() does not return a valid URL for iframes.  We can't just
look up the requested URL in m_responses because the request may have
been redirected, so instead we keep track of redirects and set up the
NetworkResponse when the final reply is received.
  • Loading branch information...
1 parent e80a9c8 commit 5127c01366152f7f72fe44fa5976ef5203570641 @mhoran mhoran committed Nov 22, 2012
Showing with 75 additions and 34 deletions.
  1. +48 −23 spec/driver_spec.rb
  2. +1 −1 src/Authenticate.cpp
  3. +1 −1 src/Header.cpp
  4. +12 −4 src/NetworkAccessManager.cpp
  5. +1 −0 src/NetworkAccessManager.h
  6. +1 −1 src/SetProxy.cpp
  7. +1 −1 src/SetUrlBlacklist.cpp
  8. +2 −1 src/Source.cpp
  9. +6 −2 src/WebPage.cpp
  10. +2 −0 src/WebPage.h
View
@@ -9,15 +9,29 @@
let(:driver) do
driver_for_app do
get "/" do
- if in_iframe_request?
- p_id = "farewell"
- msg = "goodbye"
- iframe = nil
+ if params[:iframe] == "true"
+ redirect '/iframe'
else
- p_id = "greeting"
- msg = "hello"
- iframe = "<iframe id=\"f\" src=\"/?iframe=true\"></iframe>"
+ <<-HTML
+ <html>
+ <head>
+ <style type="text/css">
+ #display_none { display: none }
+ </style>
+ </head>
+ <body>
+ <iframe id="f" src="/?iframe=true"></iframe>
+ <script type="text/javascript">
+ document.write("<p id='greeting'>hello</p>");
+ </script>
+ </body>
+ </html>
+ HTML
end
+ end
+
+ get '/iframe' do
+ headers 'X-Redirected' => 'true'
<<-HTML
<html>
<head>
@@ -26,18 +40,13 @@
</style>
</head>
<body>
- #{iframe}
<script type="text/javascript">
- document.write("<p id='#{p_id}'>#{msg}</p>");
+ document.write("<p id='farewell'>goodbye</p>");
</script>
</body>
</html>
HTML
end
-
- def in_iframe_request?
- params[:iframe] == "true"
- end
end
end
@@ -90,13 +99,7 @@ def in_iframe_request?
it "returns the current URL" do
driver.within_frame("f") do
- driver.current_url.should == driver_url(driver, "/?iframe=true")
- end
- end
-
- it "returns the source code for the page" do
- driver.within_frame("f") do
- driver.source.should =~ %r{<html>.*farewell.*}m
+ driver.current_url.should == driver_url(driver, "/iframe")
end
end
@@ -121,6 +124,18 @@ def in_iframe_request?
driver.current_url.should == original_url
end
+
+ it "returns the headers for the page" do
+ driver.within_frame("f") do
+ driver.response_headers['X-Redirected'].should == "true"
+ end
+ end
+
+ it "returns the status code for the page" do
+ driver.within_frame("f") do
+ driver.status_code.should == 200
+ end
+ end
end
context "error iframe app" do
@@ -150,8 +165,10 @@ def in_iframe_request?
context "redirect app" do
let(:driver) do
driver_for_app do
+ enable :sessions
+
get '/target' do
- headers 'X-Redirected' => 'true'
+ headers 'X-Redirected' => (session.delete(:redirected) || false).to_s
"<p>#{env['CONTENT_TYPE']}</p>"
end
@@ -172,7 +189,12 @@ def in_iframe_request?
end
get '/redirect-me' do
- redirect '/target'
+ if session[:redirected]
+ redirect '/target'
+ else
+ session[:redirected] = true
+ redirect '/redirect-me'
+ end
end
end
end
@@ -200,13 +222,16 @@ def in_iframe_request?
it "should make headers available through response_headers" do
driver.visit('/redirect-me')
driver.response_headers['X-Redirected'].should == "true"
+ driver.visit('/target')
+ driver.response_headers['X-Redirected'].should == "false"
end
it "should make the status code available through status_code" do
driver.visit('/redirect-me')
driver.status_code.should == 200
+ driver.visit('/target')
+ driver.status_code.should == 200
end
-
end
context "css app" do
View
@@ -9,7 +9,7 @@ void Authenticate::start() {
QString username = arguments()[0];
QString password = arguments()[1];
- NetworkAccessManager* networkAccessManager = qobject_cast<NetworkAccessManager*>(page()->networkAccessManager());
+ NetworkAccessManager* networkAccessManager = page()->networkAccessManager();
networkAccessManager->setUserName(username);
networkAccessManager->setPassword(password);
View
@@ -9,7 +9,7 @@ Header::Header(WebPageManager *manager, QStringList &arguments, QObject *parent)
void Header::start() {
QString key = arguments()[0];
QString value = arguments()[1];
- NetworkAccessManager* networkAccessManager = qobject_cast<NetworkAccessManager*>(page()->networkAccessManager());
+ NetworkAccessManager* networkAccessManager = page()->networkAccessManager();
if (key.toLower().replace("-", "_") == "user_agent") {
page()->setUserAgent(value);
} else {
@@ -30,10 +30,18 @@ QNetworkReply* NetworkAccessManager::createRequest(QNetworkAccessManager::Operat
};
void NetworkAccessManager::finished(QNetworkReply *reply) {
- NetworkResponse response;
- response.statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
- response.headers = reply->rawHeaderPairs();
- m_responses[reply->url()] = response;
+ QUrl redirectUrl = reply->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl();
+ if (redirectUrl.isValid())
+ m_redirectMappings[reply->url().resolved(redirectUrl)] = reply->url();
+ else {
+ QUrl requestedUrl = reply->url();
+ while (m_redirectMappings.contains(requestedUrl))
+ requestedUrl = m_redirectMappings.take(requestedUrl);
+ NetworkResponse response;
+ response.statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
+ response.headers = reply->rawHeaderPairs();
+ m_responses[requestedUrl] = response;
+ }
}
void NetworkAccessManager::addHeader(QString key, QString value) {
@@ -35,6 +35,7 @@ class NetworkAccessManager : public QNetworkAccessManager {
QHash<QUrl, NetworkResponse> m_responses;
bool isBlacklisted(QUrl url);
QNetworkReply* noOpRequest();
+ QHash<QUrl, QUrl> m_redirectMappings;
private slots:
void provideAuthentication(QNetworkReply *reply, QAuthenticator *authenticator);
View
@@ -1,7 +1,7 @@
#include "SetProxy.h"
#include "WebPage.h"
#include "WebPageManager.h"
-#include <QNetworkAccessManager>
+#include "NetworkAccessManager.h"
#include <QNetworkProxy>
SetProxy::SetProxy(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {}
View
@@ -8,7 +8,7 @@ SetUrlBlacklist::SetUrlBlacklist(WebPageManager *manager, QStringList &arguments
}
void SetUrlBlacklist::start() {
- NetworkAccessManager* networkAccessManager = qobject_cast<NetworkAccessManager*>(page()->networkAccessManager());
+ NetworkAccessManager* networkAccessManager = page()->networkAccessManager();
networkAccessManager->setUrlBlacklist(arguments());
emit finished(new Response(true));
}
View
@@ -1,12 +1,13 @@
#include "Source.h"
#include "WebPage.h"
#include "WebPageManager.h"
+#include "NetworkAccessManager.h"
Source::Source(WebPageManager *manager, QStringList &arguments, QObject *parent) : SocketCommand(manager, arguments, parent) {
}
void Source::start() {
- QNetworkAccessManager* accessManager = page()->networkAccessManager();
+ NetworkAccessManager* accessManager = page()->networkAccessManager();
QNetworkRequest request(page()->currentFrame()->requestedUrl());
reply = accessManager->get(request);
View
@@ -253,11 +253,15 @@ void WebPage::setSkipImageLoading(bool skip) {
}
int WebPage::getLastStatus() {
- return qobject_cast<NetworkAccessManager *>(networkAccessManager())->statusFor(currentFrame()->url());
+ return networkAccessManager()->statusFor(currentFrame()->requestedUrl());
}
const QList<QNetworkReply::RawHeaderPair> &WebPage::pageHeaders() {
- return qobject_cast<NetworkAccessManager *>(networkAccessManager())->headersFor(currentFrame()->url());
+ return networkAccessManager()->headersFor(currentFrame()->requestedUrl());
+}
+
+NetworkAccessManager *WebPage::networkAccessManager() {
+ return qobject_cast<NetworkAccessManager *>(QWebPage::networkAccessManager());
}
void WebPage::handleUnsupportedContent(QNetworkReply *reply) {
View
@@ -3,6 +3,7 @@
#include <QtWebKit>
class WebPageManager;
+class NetworkAccessManager;
class WebPage : public QWebPage {
Q_OBJECT
@@ -32,6 +33,7 @@ class WebPage : public QWebPage {
QString getWindowName();
bool matchesWindowSelector(QString);
void setFocus();
+ NetworkAccessManager *networkAccessManager();
public slots:
bool shouldInterruptJavaScript();

0 comments on commit 5127c01

Please sign in to comment.