diff --git a/inc/extension_qt/qnetwork_access_manager_tracer.h b/inc/extension_qt/qnetwork_access_manager_tracer.h new file mode 100644 index 00000000..fa34a9ba --- /dev/null +++ b/inc/extension_qt/qnetwork_access_manager_tracer.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright © 1992-2014 Cisco and/or its affiliates. All rights reserved. +** All rights reserved. +** +** $CISCO_BEGIN_LICENSE:LGPL$ +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** $CISCO_END_LICENSE$ +** +****************************************************************************/ + +#ifndef NETWORK_ACCESS_MANAGER_H +#define NETWORK_ACCESS_MANAGER_H + +#include +#include + +namespace webdriver { +class Session; +} + +/// Auxiliary class for performance logging support.
+/// Limitation: It is currently not supported to change the network access manager after the QWebPage has used it. +class QNetworkAccessManagerTracer: public QNetworkAccessManager { + Q_OBJECT +public: + /// Create custom network access manager. + /// @param session pointer to Session object. + /// @param parent set as the parent object. + QNetworkAccessManagerTracer(webdriver::Session* session, QObject* parent = 0); + + virtual ~QNetworkAccessManagerTracer(); + +protected: + /// Overrided, additional write a JSON entry for every received reply. + virtual QNetworkReply* createRequest(Operation op, const QNetworkRequest& req, QIODevice* outgoingData = 0); + +protected slots: + /// Create single log entry and add it to session's performance log. + ///
Currently WebDriver supports only Performance Log of Network. + ///

Each entry is a JSON string of the following structure: + /// @code + /// { + /// "webview": "class_name", + /// "message": { + /// "args": { + /// "file": "file_path/name", + /// "method": "HTTP_method", + /// "status": "HTTP_status_code", + /// }, + /// "tid": "thread_id", + /// "ts": "timestamp", + /// "tts": "thread-specific_CPU-time" + /// } + /// } + /// @endcode + /// @param reply pointer to reply, that contains the data which will be written to PerfLog. + void writeReply(QNetworkReply* reply); + +private: + std::string getMethod(Operation op); + webdriver::Session* session_; + double timeStamp_; +}; + +#endif //NETWORK_ACCESS_MANAGER_H diff --git a/inc/extension_qt/qwebviewext.h b/inc/extension_qt/qwebviewext.h index 4f750a98..21ce30f2 100644 --- a/inc/extension_qt/qwebviewext.h +++ b/inc/extension_qt/qwebviewext.h @@ -9,6 +9,8 @@ #include #endif +class QNetworkAccessManagerTracer; + class QWebViewExt : public QWebView { Q_OBJECT @@ -22,7 +24,8 @@ class QWebViewExt : public QWebView private: void setWebInspectorProperty(QWebViewExt* view); - + void setNetworkAccessManagerTracer(); + QNetworkAccessManagerTracer* manager_; }; #endif // QWEBVIEWEXT_H diff --git a/src/webdriver/extension_qt/qnetwork_access_manager_tracer.cc b/src/webdriver/extension_qt/qnetwork_access_manager_tracer.cc new file mode 100644 index 00000000..3a26e280 --- /dev/null +++ b/src/webdriver/extension_qt/qnetwork_access_manager_tracer.cc @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** Copyright © 1992-2014 Cisco and/or its affiliates. All rights reserved. +** All rights reserved. +** +** $CISCO_BEGIN_LICENSE:LGPL$ +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** $CISCO_END_LICENSE$ +** +****************************************************************************/ + +#include "extension_qt/qnetwork_access_manager_tracer.h" +#include "webdriver_session.h" +#include "webdriver_util.h" +#include "web_view_util.h" + +#include "base/values.h" +#include "base/time.h" +#include "base/threading/platform_thread.h" +#include "base/string_number_conversions.h" + +#include +#include + +QNetworkAccessManagerTracer::QNetworkAccessManagerTracer(webdriver::Session* session, QObject* parent) + : QNetworkAccessManager(parent), session_(session) { +} + +QNetworkAccessManagerTracer::~QNetworkAccessManagerTracer() { } + +QNetworkReply* QNetworkAccessManagerTracer::createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest &req, QIODevice *outgoingData) { + + timeStamp_ = static_cast(base::TimeTicks::NowFromSystemTraceTime().ToInternalValue()); + QNetworkReply* reply = QNetworkAccessManager::createRequest(op, req, outgoingData); + connect(this, SIGNAL(finished(QNetworkReply*)), this, SLOT(writeReply(QNetworkReply*))); + + return reply; +} + +void QNetworkAccessManagerTracer::writeReply(QNetworkReply *reply) { + webdriver::LogLevel level = session_->GetMinPerfLogLevel(); + + double thread_timestamp = static_cast((base::TimeTicks::IsThreadNowSupported() ? + base::TimeTicks::ThreadNow() : base::TimeTicks()).ToInternalValue()); + + std::string file = reply->url().path().toStdString(); + // delete '/' in the beginning: + file.erase(0, 1); + + //HTTP status code + QVariant statusCode = reply->attribute( QNetworkRequest::HttpStatusCodeAttribute ); + QString reason; + if ( !statusCode.isValid() ) { + reason = "INVALID"; + level = webdriver::LogLevelFromString("SEVERE"); + } else { + int status = statusCode.toInt(); + if ( status != 200 ) { + level = webdriver::LogLevelFromString("WARNING"); + } else { + level = webdriver::LogLevelFromString("INFO"); + } + reason = reply->attribute(QNetworkRequest::HttpReasonPhraseAttribute).toString(); + } + base::DictionaryValue* args_entry = new base::DictionaryValue(); + args_entry->SetString("method", getMethod(reply->operation())); + args_entry->SetString("status", reason.toStdString()); + args_entry->SetString("file", file); + + base::DictionaryValue* message_entry = new base::DictionaryValue(); + message_entry->Set("args", args_entry); + message_entry->SetDouble("ts", timeStamp_); + message_entry->SetInteger("tid", static_cast(base::PlatformThread::CurrentId())); + message_entry->SetDouble("tts", thread_timestamp); + + base::DictionaryValue* entry = new base::DictionaryValue; + std::string webview = webdriver::QWebViewUtil::getWebView(session_,session_->current_view())->metaObject()->className(); + entry->SetString("webview", webview); + entry->Set("message", message_entry); + std::string log_entry = webdriver::JsonStringifyForDisplay(entry); + + session_->AddPerfLogEntry(level, log_entry); + delete entry; + +} + +std::string QNetworkAccessManagerTracer::getMethod(QNetworkAccessManager::Operation op) { + std::string method; + switch (op) { + case QNetworkAccessManager::HeadOperation: + method = "HEAD"; + break; + case QNetworkAccessManager::GetOperation: + method = "GET"; + break; + case QNetworkAccessManager::PutOperation: + method= "PUT"; + break; + case QNetworkAccessManager::PostOperation: + method = "POST"; + break; + case QNetworkAccessManager::DeleteOperation: + method = "DELETE"; + break; + case QNetworkAccessManager::CustomOperation: + method = "custom"; + break; + default: + method = "unsupported method"; + break; + } + return method; +} + diff --git a/src/webdriver/extension_qt/qwebviewext.cc b/src/webdriver/extension_qt/qwebviewext.cc index cd383baa..0ad89589 100644 --- a/src/webdriver/extension_qt/qwebviewext.cc +++ b/src/webdriver/extension_qt/qwebviewext.cc @@ -1,5 +1,9 @@ #include "extension_qt/qwebviewext.h" #include "webdriver_server.h" +#include "webdriver_session_manager.h" +#include "webdriver_session.h" +#include "webdriver_logging.h" +#include "extension_qt/qnetwork_access_manager_tracer.h" #include #include #include @@ -14,16 +18,18 @@ #endif QWebViewExt::QWebViewExt(QWidget *parent) : - QWebView(parent) + QWebView(parent), manager_(0) { setVisible(false); setWebInspectorProperty(this); + setNetworkAccessManagerTracer(); connect(page(), SIGNAL(windowCloseRequested()), this, SLOT(close())); connect(this, SIGNAL(titleChanged(QString)), this, SLOT(setWindowTitle(QString))); } QWebViewExt::~QWebViewExt() { + delete manager_; } QWebView* QWebViewExt::createWindow(QWebPage::WebWindowType type) @@ -56,3 +62,20 @@ void QWebViewExt::setWebInspectorProperty(QWebViewExt *view) } } +void QWebViewExt::setNetworkAccessManagerTracer() +{ + std::map sessionMap = webdriver::SessionManager::GetInstance()->GetSessions(); + if (sessionMap.size() != 1) + { + webdriver::GlobalLogger::Log(webdriver::kWarningLogLevel, "Session should be initialized"); + return; + } + webdriver::Session* session = sessionMap.begin()->second; + if (session->GetMinPerfLogLevel() == webdriver::kOffLogLevel) + { + webdriver::GlobalLogger::Log(webdriver::kInfoLogLevel, "Performance Log is disabled by defaul"); + return; + } + manager_ = new QNetworkAccessManagerTracer(session, this->page()); + this->page()->setNetworkAccessManager(manager_); +} diff --git a/wd_ext_qt.gyp b/wd_ext_qt.gyp index 351f95be..dba7a37a 100644 --- a/wd_ext_qt.gyp +++ b/wd_ext_qt.gyp @@ -81,6 +81,8 @@ 'src/webdriver/extension_qt/web_view_util.cc', 'src/webdriver/extension_qt/qwebkit_proxy.cc', 'src/webdriver/extension_qt/qwebkit_proxy.h', + 'inc/extension_qt/qnetwork_access_manager_tracer.h', + 'src/webdriver/extension_qt/qnetwork_access_manager_tracer.cc', 'src/webdriver/extension_qt/graphics_web_view_handle.cc', 'src/webdriver/extension_qt/graphics_web_view_enumerator.cc', 'src/webdriver/extension_qt/graphics_web_view_executor.cc', @@ -88,6 +90,7 @@ '<(INTERMEDIATE_DIR)/moc_web_view_visualizer.cc', '<(INTERMEDIATE_DIR)/moc_qwebviewext.cc', '<(INTERMEDIATE_DIR)/moc_qwebkit_proxy.cc', + '<(INTERMEDIATE_DIR)/moc_qnetwork_access_manager_tracer.cc', 'src/third_party/webdriver/atoms.cc', ],