Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Merge pull request #319 from detro/ghostdriver-dev

GhostDriver Development Branch - Master Push #4
  • Loading branch information...
commit 9a25f31715e15c9497be35e8213e11ede3e9bc7d 2 parents 64fa65e + 2658374
@ariya authored
View
1  .gitignore
@@ -19,6 +19,7 @@ debian/*/
/deploy/qt-*.tar.gz
/deploy/Qt-*
/symbols
+src/qt/qtc-debugging-helper
# ignore ctags
/tags
View
2  examples/pagecallback.coffee
@@ -7,7 +7,7 @@ p.onCallback = (msg) ->
"Hello there, I'm coming to you from the 'phantom' context instead"
p.evaluate ->
- callbackResponse = phantomCallback("Hello, I'm coming to you from the 'page' context")
+ callbackResponse = callPhantom("Hello, I'm coming to you from the 'page' context")
console.log "Received by the 'page' context: " + callbackResponse
phantom.exit()
View
282 src/cookiejar.cpp
@@ -93,9 +93,9 @@ CookieJar *CookieJar::instance(QString cookiesFile)
static CookieJar *singleton = NULL;
if (!singleton) {
if (cookiesFile.isEmpty()) {
- qDebug() << "Creating CookieJar, but no file to store cookies was provided (use '--cookies-file=<filename>')";
+ qDebug() << "CookieJar - Created but will not store cookies (use option '--cookies-file=<filename>' to enable persisten cookie storage)";
} else {
- qDebug() << "Creating CookieJar, using file:" << cookiesFile;
+ qDebug() << "CookieJar - Created and will store cookies in:" << cookiesFile;
}
// Create singleton and assign ownershipt to the Phantom singleton object
// NOTE: First time this is done is when we set "once and for all" the Cookies' File
@@ -114,10 +114,9 @@ CookieJar::~CookieJar()
bool CookieJar::setCookiesFromUrl(const QList<QNetworkCookie> & cookieList, const QUrl &url)
{
// Update cookies in memory
- if (isEnabled() && QNetworkCookieJar::setCookiesFromUrl(cookieList, url)) {
- // Update cookies in permanent storage, because at least 1 changed
+ if (isEnabled()) {
+ QNetworkCookieJar::setCookiesFromUrl(cookieList, url);
save();
- return true;
}
// No changes occurred
return false;
@@ -132,63 +131,107 @@ QList<QNetworkCookie> CookieJar::cookiesForUrl(const QUrl &url) const
return QList<QNetworkCookie>();
}
-void CookieJar::addCookie(const QNetworkCookie &cookie, const QString &url)
+bool CookieJar::addCookie(const QNetworkCookie &cookie, const QString &url)
{
- if (isEnabled()) {
+ if (isEnabled() && (!url.isEmpty() || !cookie.domain().isEmpty())) {
// Save a single cookie
setCookiesFromUrl(
- QList<QNetworkCookie>() << cookie, //< unfortunately, "setCookiesFromUrl" requires a list
- !url.isEmpty() ?
- url : //< use given URL
- QUrl( //< mock-up a URL
- (cookie.isSecure() ? "https://" : "http://") + //< URL protocol
- QString(cookie.domain().startsWith('.') ? "www" : "") + cookie.domain() + //< URL domain
- (cookie.path().isEmpty() ? "/" : cookie.path()))); //< URL path
+ QList<QNetworkCookie>() << cookie, //< unfortunately, "setCookiesFromUrl" requires a list
+ !url.isEmpty() ?
+ url : //< use given URL
+ QString( //< mock-up a URL
+ (cookie.isSecure() ? "https://" : "http://") + //< URL protocol
+ QString(cookie.domain().startsWith('.') ? "www" : "") + cookie.domain() + //< URL domain
+ (cookie.path().isEmpty() ? "/" : cookie.path()))); //< URL path
+
+ // Return "true" if the cookie was really set
+ if (contains(cookie)) {
+ return true;
+ }
+ qDebug() << "CookieJar - Rejected Cookie" << cookie.toRawForm();
+ return false;
}
+ return false;
}
-void CookieJar::addCookieFromMap(const QVariantMap &cookie, const QString &url)
+bool CookieJar::addCookieFromMap(const QVariantMap &cookie, const QString &url)
{
QNetworkCookie newCookie;
- // The cookie must have "domain", "name" and "value"
- if (!cookie["domain"].isNull() && !cookie["domain"].toString().isEmpty() &&
- !cookie["name"].isNull() && !cookie["name"].toString().isEmpty() &&
- !cookie["value"].isNull()
- ) {
- newCookie.setDomain(cookie["domain"].toString());
+ // The cookie must have a non-empty "name" and a "value"
+ if (!cookie["name"].isNull() && !cookie["name"].toString().isEmpty() && !cookie["value"].isNull()) {
+ // Name & Value
newCookie.setName(cookie["name"].toByteArray());
newCookie.setValue(cookie["value"].toByteArray());
- newCookie.setPath((cookie["path"].isNull() || cookie["path"].toString().isEmpty()) ?
- "/" :cookie["path"].toString());
+ // Domain, if provided
+ if (!cookie["domain"].isNull() && !cookie["domain"].toString().isEmpty()) {
+ newCookie.setDomain(cookie["domain"].toString());
+ }
+
+ // Path, if provided
+ if (!cookie["path"].isNull() || !cookie["path"].toString().isEmpty()) {
+ newCookie.setPath(cookie["path"].toString());
+ }
+
+ // HttpOnly, false by default
newCookie.setHttpOnly(cookie["httponly"].isNull() ? false : cookie["httponly"].toBool());
+ // Secure, false by default
newCookie.setSecure(cookie["secure"].isNull() ? false : cookie["secure"].toBool());
+ // Expiration Date, if provided, giving priority to "expires" over "expiry"
+ QVariant expiresVar;
if (!cookie["expires"].isNull()) {
- QString datetime = cookie["expires"].toString().replace(" GMT", "");
- QDateTime expires = QDateTime::fromString(datetime, "ddd, dd MMM yyyy hh:mm:ss");
- if (expires.isValid()) {
- newCookie.setExpirationDate(expires);
+ expiresVar = cookie["expires"];
+ } else if (!cookie["expiry"].isNull()) {
+ expiresVar = cookie["expiry"];
+ }
+
+ if (expiresVar.isValid()) {
+ QDateTime expirationDate;
+ if (expiresVar.type() == QVariant::String) {
+ // Set cookie expire date via "classic" string format
+ QString datetime = expiresVar.toString().replace(" GMT", "");
+ expirationDate = QDateTime::fromString(datetime, "ddd, dd MMM yyyy hh:mm:ss");
+ } else if (expiresVar.type() == QVariant::Double){
+ // Set cookie expire date via "number of seconds since epoch"
+ // NOTE: Every JS number is a Double.
+ // @see http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf
+ expirationDate = QDateTime::fromMSecsSinceEpoch(expiresVar.toLongLong());
+ }
+
+ if (expirationDate.isValid()) {
+ newCookie.setExpirationDate(expirationDate);
}
}
- addCookie(newCookie, url);
+ return addCookie(newCookie, url);
}
+ return false;
}
-void CookieJar::addCookies(const QList<QNetworkCookie> &cookiesList, const QString &url)
+bool CookieJar::addCookies(const QList<QNetworkCookie> &cookiesList, const QString &url)
{
+ bool added = false;
for (int i = cookiesList.length() -1; i >=0; --i) {
- addCookie(cookiesList.at(i), url);
+ if (addCookie(cookiesList.at(i), url)) {
+ // change it to "true" if at least 1 cookie was set
+ added = true;
+ }
}
+ return added;
}
-void CookieJar::addCookiesFromMap(const QVariantList &cookiesList, const QString &url)
+bool CookieJar::addCookiesFromMap(const QVariantList &cookiesList, const QString &url)
{
+ bool added = false;
for (int i = cookiesList.length() -1; i >= 0; --i) {
- addCookieFromMap(cookiesList.at(i).toMap(), url);
+ if (addCookieFromMap(cookiesList.at(i).toMap(), url)) {
+ // change it to "true" if at least 1 cookie was set
+ added = true;
+ }
}
+ return added;
}
QList<QNetworkCookie> CookieJar::cookies(const QString &url) const
@@ -220,6 +263,7 @@ QVariantList CookieJar::cookiesToMap(const QString &url) const
cookie["secure"] = QVariant(c.isSecure());
if (c.expirationDate().isValid()) {
cookie["expires"] = QVariant(QString(c.expirationDate().toString("ddd, dd MMM yyyy hh:mm:ss")).append(" GMT"));
+ cookie["expiry"] = QVariant(c.expirationDate().toMSecsSinceEpoch() / 1000);
}
result.append(cookie);
@@ -253,44 +297,75 @@ QVariantMap CookieJar::cookieToMap(const QString &name, const QString &url) cons
return QVariantMap();
}
-void CookieJar::deleteCookie(const QString &name, const QString &url)
+bool CookieJar::deleteCookie(const QString &name, const QString &url)
{
+ bool deleted = false;
if (isEnabled()) {
- QNetworkCookie cookie;
-
- // For all the cookies that are visible to this URL
- QList<QNetworkCookie> cookiesList = cookies(url);
- for (int i = cookiesList.length() -1; i >= 0; --i) {
- if (cookiesList.at(i).name() == name || name.isEmpty()) {
- // Remove item from list
- cookie = cookiesList.takeAt(i);
- // If we found the right cookie, mark it expired so it gets purged
- cookie.setExpirationDate(QDateTime::currentDateTime().addYears(-1));
- // Add it back to the list
- cookiesList.append(cookie);
- // Set a new list of cookies for this URL
- setCookiesFromUrl(cookiesList, url);
-
- if (!name.isEmpty()) {
- // Only one cookie was supposed to be deleted: we are done here!
- return;
+
+ // NOTE: This code has been written in an "extended form" to make it
+ // easy to understand. Surely this could be "shrinked", but it
+ // would probably look uglier.
+
+ QList<QNetworkCookie> cookiesListAll;
+
+ if (url.isEmpty()) {
+ if (name.isEmpty()) { //< Neither "name" or "url" provided
+ // This method has been used wrong:
+ // "redirecting" to the right method for the job
+ clearCookies();
+ } else { //< Only "name" provided
+ // Delete all cookies with the given name from the CookieJar
+ cookiesListAll = allCookies();
+ for (int i = cookiesListAll.length() -1; i >= 0; --i) {
+ if (cookiesListAll.at(i).name() == name) {
+ // Remove this cookie
+ qDebug() << "CookieJar - Deleted" << cookiesListAll.at(i).toRawForm();
+ cookiesListAll.removeAt(i);
+ deleted = true;
+ }
+ }
+ }
+ } else {
+ // Delete cookie(s) from the ones visible to the given "url".
+ // Use the "name" to delete only the right one, otherwise all of them.
+ QList<QNetworkCookie> cookiesListUrl = cookies(url);
+ cookiesListAll = allCookies();
+ for (int i = cookiesListAll.length() -1; i >= 0; --i) {
+ if (cookiesListUrl.contains(cookiesListAll.at(i)) && //< if it part of the set of cookies visible at URL
+ (cookiesListAll.at(i).name() == name || name.isEmpty())) { //< and if the name matches, or no name provided
+ // Remove this cookie
+ qDebug() << "CookieJar - Deleted" << cookiesListAll.at(i).toRawForm();
+ cookiesListAll.removeAt(i);
+ deleted = true;
+
+ if (!name.isEmpty()) {
+ // Only one cookie was supposed to be deleted: we are done here!
+ break;
+ }
}
}
}
+
+ // Put back the remaining cookies
+ setAllCookies(cookiesListAll);
}
+ return deleted;
}
-void CookieJar::deleteCookies(const QString &url)
+bool CookieJar::deleteCookies(const QString &url)
{
if (isEnabled()) {
if (url.isEmpty()) {
// No URL provided: delete ALL the cookies in the CookieJar
clearCookies();
- } else {
- // No cookie name provided: delete all the cookies visible by this URL
- deleteCookie("", url);
+ return true;
}
+
+ // No cookie name provided: delete all the cookies visible by this URL
+ qDebug() << "Delete all cookies for URL:" << url;
+ return deleteCookie("", url);
}
+ return false;
}
void CookieJar::clearCookies()
@@ -316,64 +391,74 @@ bool CookieJar::isEnabled() const
}
// private:
-void CookieJar::save()
-{
- if (isEnabled()) {
- // Get rid of all the Cookies that have expired
- purgeExpiredCookies();
-
-#ifndef QT_NO_DEBUG_OUTPUT
- foreach (QNetworkCookie cookie, allCookies()) {
- qDebug() << "CookieJar - Saved" << cookie.toRawForm() << "expires:" << cookie.expirationDate().toString();
- }
-#endif
-
- // Store cookies
- m_cookieStorage->setValue(QLatin1String("cookies"), QVariant::fromValue<QList<QNetworkCookie> >(allCookies()));
- }
-}
-
bool CookieJar::purgeExpiredCookies()
{
- QList<QNetworkCookie> cookies = allCookies();
+ QList<QNetworkCookie> cookiesList = allCookies();
// If empty, there is nothing to purge
- if (cookies.isEmpty()) {
+ if (cookiesList.isEmpty()) {
return false;
}
// Check if any cookie has expired
- int prePurgeCookiesCount = cookies.count();
+ int prePurgeCookiesCount = cookiesList.count();
QDateTime now = QDateTime::currentDateTime();
- for (int i = cookies.count() - 1; i >= 0; --i) {
- if (!cookies.at(i).isSessionCookie() && cookies.at(i).expirationDate() < now) {
- cookies.removeAt(i);
+ for (int i = cookiesList.count() - 1; i >= 0; --i) {
+ if (!cookiesList.at(i).isSessionCookie() && cookiesList.at(i).expirationDate() < now) {
+ qDebug() << "CookieJar - Purged (expired)" << cookiesList.at(i).toRawForm();
+ cookiesList.removeAt(i);
}
}
- // Returns "true" if at least 1 cookie expired and has been removed
- return prePurgeCookiesCount != cookies.count();
+ // Set cookies and returns "true" if at least 1 cookie expired and has been removed
+ if (prePurgeCookiesCount != cookiesList.count()) {
+ setAllCookies(cookiesList);
+ return true;
+ }
+ return false;
}
bool CookieJar::purgeSessionCookies()
{
- QList<QNetworkCookie> cookies = allCookies();
+ QList<QNetworkCookie> cookiesList = allCookies();
// If empty, there is nothing to purge
- if (cookies.isEmpty()) {
+ if (cookiesList.isEmpty()) {
return false;
}
// Check if any cookie has expired
- int prePurgeCookiesCount = cookies.count();
- for (int i = cookies.count() - 1; i >= 0; --i) {
- if (cookies.at(i).isSessionCookie() || !cookies.at(i).expirationDate().isValid() || cookies.at(i).expirationDate().isNull()) {
- cookies.removeAt(i);
+ int prePurgeCookiesCount = cookiesList.count();
+ for (int i = cookiesList.count() - 1; i >= 0; --i) {
+ if (cookiesList.at(i).isSessionCookie() || !cookiesList.at(i).expirationDate().isValid() || cookiesList.at(i).expirationDate().isNull()) {
+ qDebug() << "CookieJar - Purged (session)" << cookiesList.at(i).toRawForm();
+ cookiesList.removeAt(i);
}
}
- // Returns "true" if at least 1 session cookie was found and removed
- return prePurgeCookiesCount != cookies.count();
+ // Set cookies and returns "true" if at least 1 session cookie was found and removed
+ if (prePurgeCookiesCount != cookiesList.count()) {
+ setAllCookies(cookiesList);
+ return true;
+ }
+ return false;
+}
+
+void CookieJar::save()
+{
+ if (isEnabled()) {
+ // Get rid of all the Cookies that have expired
+ purgeExpiredCookies();
+
+#ifndef QT_NO_DEBUG_OUTPUT
+ foreach (QNetworkCookie cookie, allCookies()) {
+ qDebug() << "CookieJar - Saved" << cookie.toRawForm();
+ }
+#endif
+
+ // Store cookies
+ m_cookieStorage->setValue(QLatin1String("cookies"), QVariant::fromValue<QList<QNetworkCookie> >(allCookies()));
+ }
}
void CookieJar::load()
@@ -392,8 +477,27 @@ void CookieJar::load()
#ifndef QT_NO_DEBUG_OUTPUT
foreach (QNetworkCookie cookie, allCookies()) {
- qDebug() << "CookieJar - Loaded" << cookie.toRawForm() << "expires:" << cookie.expirationDate().toString();
+ qDebug() << "CookieJar - Loaded" << cookie.toRawForm();
}
#endif
}
}
+
+bool CookieJar::contains(const QNetworkCookie &cookie) const
+{
+ QList<QNetworkCookie> cookiesList = allCookies();
+ for (int i = cookiesList.length() -1; i >= 0; --i) {
+ if (cookie.name() == cookiesList.at(i).name() &&
+ cookie.value() == cookiesList.at(i).value() &&
+ (cookie.domain().isEmpty() || cookiesList.at(i).domain().prepend('.').endsWith(cookie.domain())) &&
+ (cookie.path().isEmpty() || cookiesList.at(i).path() == cookie.path()) &&
+ cookie.isSecure() == cookiesList.at(i).isSecure() &&
+ cookie.isHttpOnly() == cookiesList.at(i).isHttpOnly() &&
+ cookie.expirationDate().toMSecsSinceEpoch() == cookie.expirationDate().toMSecsSinceEpoch()
+ ) {
+ return true;
+ }
+ }
+
+ return false;
+}
View
19 src/cookiejar.h
@@ -50,10 +50,10 @@ class CookieJar: public QNetworkCookieJar
bool setCookiesFromUrl(const QList<QNetworkCookie> &cookieList, const QUrl & url);
QList<QNetworkCookie> cookiesForUrl (const QUrl & url) const;
- void addCookie(const QNetworkCookie &cookie, const QString &url = QString());
- void addCookieFromMap(const QVariantMap &cookie, const QString &url = QString());
- void addCookies(const QList<QNetworkCookie> &cookiesList, const QString &url = QString());
- void addCookiesFromMap(const QVariantList &cookiesList, const QString &url = QString());
+ bool addCookie(const QNetworkCookie &cookie, const QString &url = QString());
+ bool addCookieFromMap(const QVariantMap &cookie, const QString &url = QString());
+ bool addCookies(const QList<QNetworkCookie> &cookiesList, const QString &url = QString());
+ bool addCookiesFromMap(const QVariantList &cookiesList, const QString &url = QString());
QList<QNetworkCookie> cookies(const QString &url = QString()) const;
QVariantList cookiesToMap(const QString &url = QString()) const;
@@ -61,8 +61,8 @@ class CookieJar: public QNetworkCookieJar
QNetworkCookie cookie(const QString &name, const QString &url = QString()) const;
QVariantMap cookieToMap(const QString &name, const QString &url = QString()) const;
- void deleteCookie(const QString &name, const QString &url = QString());
- void deleteCookies(const QString &url = QString());
+ bool deleteCookie(const QString &name, const QString &url = QString());
+ bool deleteCookies(const QString &url = QString());
void clearCookies();
void enable();
@@ -70,10 +70,13 @@ class CookieJar: public QNetworkCookieJar
bool isEnabled() const;
private slots:
- void save();
- void load();
bool purgeExpiredCookies();
bool purgeSessionCookies();
+ void save();
+ void load();
+
+private:
+ bool contains(const QNetworkCookie &cookie) const;
private:
QSettings *m_cookieStorage;
View
13 src/main.cpp
@@ -77,9 +77,9 @@ int main(int argc, char** argv, const char** envp)
if (cbBuffer == 0) {
eh = new ExceptionHandler(TEXT("."), NULL, Utils::exceptionHandler, NULL, ExceptionHandler::HANDLER_ALL);
- } else {
+ } else {
LPWSTR szBuffer = reinterpret_cast<LPWSTR>(malloc(sizeof(TCHAR) * (cbBuffer + 1)));
-
+
if (ExpandEnvironmentStrings(TEXT("%TEMP%"), szBuffer, cbBuffer + 1) > 0) {
wstring lpDumpPath(szBuffer);
eh = new ExceptionHandler(lpDumpPath, NULL, Utils::exceptionHandler, NULL, ExceptionHandler::HANDLER_ALL);
@@ -87,7 +87,7 @@ int main(int argc, char** argv, const char** envp)
free(szBuffer);
}
#endif
-
+
QApplication app(argc, argv);
app.setWindowIcon(QIcon(":/phantomjs-icon.png"));
@@ -99,13 +99,12 @@ int main(int argc, char** argv, const char** envp)
// Prepare the "env" singleton using the environment variables
Env::instance()->parse(envp);
- // Get the Phantom singleton
- Phantom *phantom = Phantom::instance();
-
// Registering an alternative Message Handler
- Utils::printDebugMessages = phantom->printDebugMessages();
qInstallMsgHandler(Utils::messageHandler);
+ // Get the Phantom singleton
+ Phantom *phantom = Phantom::instance();
+
// Start script execution
if (phantom->execute()) {
app.exec();
View
40 src/phantom.cpp
@@ -63,6 +63,8 @@ Phantom::Phantom(QObject *parent)
// Prepare the configuration object based on the command line arguments.
// Because this object will be used by other classes, it needs to be ready ASAP.
m_config.init(&args);
+ // Apply debug configuration as early as possible
+ Utils::printDebugMessages = m_config.printDebugMessages();
// initialize key map
QMetaEnum keys = staticQtMetaObject.enumerator( staticQtMetaObject.indexOfEnumerator("Key") );
@@ -378,6 +380,39 @@ void Phantom::onInitialized()
);
}
+bool Phantom::setCookies(const QVariantList &cookies)
+{
+ // Delete all the cookies from the CookieJar
+ CookieJar::instance()->clearCookies();
+ // Add a new set of cookies
+ return CookieJar::instance()->addCookiesFromMap(cookies);
+}
+
+QVariantList Phantom::cookies() const
+{
+ // Return all the Cookies in the CookieJar, as a list of Maps (aka JSON in JS space)
+ return CookieJar::instance()->cookiesToMap();
+}
+
+bool Phantom::addCookie(const QVariantMap &cookie)
+{
+ return CookieJar::instance()->addCookieFromMap(cookie);
+}
+
+bool Phantom::deleteCookie(const QString &cookieName)
+{
+ if (!cookieName.isEmpty()) {
+ return CookieJar::instance()->deleteCookie(cookieName);
+ }
+ return false;
+}
+
+void Phantom::clearCookies()
+{
+ CookieJar::instance()->clearCookies();
+}
+
+
// private:
void Phantom::doExit(int code)
{
@@ -407,7 +442,12 @@ void Phantom::initCompletions()
addCompletion("version");
addCompletion("keys");
addCompletion("cookiesEnabled");
+ addCompletion("cookies");
// functions
addCompletion("exit");
+ addCompletion("debugExit");
addCompletion("injectJs");
+ addCompletion("addCookie");
+ addCompletion("deleteCookie");
+ addCompletion("clearCookies");
}
View
51 src/phantom.h
@@ -56,6 +56,7 @@ class Phantom: public REPLCompletable
Q_PROPERTY(QObject *page READ page)
Q_PROPERTY(QVariantMap keys READ keys)
Q_PROPERTY(bool cookiesEnabled READ areCookiesEnabled WRITE setCookiesEnabled)
+ Q_PROPERTY(QVariantList cookies READ cookies WRITE setCookies)
private:
// Private constructor: the Phantom class is a singleton
@@ -110,6 +111,56 @@ public slots:
void loadModule(const QString &moduleSource, const QString &filename);
bool injectJs(const QString &jsFilePath);
+ /**
+ * Allows to set cookies into the CookieJar.
+ * Pages will be able to access only the cookies they are supposed to see given their URL.
+ *
+ * Cookies are expected in the format:
+ * <pre>
+ * {
+ * "name" : "cookie name (string)",
+ * "value" : "cookie value (string)",
+ * "domain" : "cookie domain (string)",
+ * "path" : "cookie path (string, optional)",
+ * "httponly" : "http only cookie (boolean, optional)",
+ * "secure" : "secure cookie (boolean, optional)",
+ * "expires" : "expiration date (string, GMT format, optional)"
+ * }
+ * </pre>
+ * @brief setCookies
+ * @param cookies Expects a QList of QVariantMaps
+ * @return Boolean "true" if at least 1 cookie was set
+ */
+ bool setCookies(const QVariantList &cookies);
+ /**
+ * All the Cookies in the CookieJar
+ *
+ * @see WebPage::setCookies for details on the format
+ * @brief cookies
+ * @return QList of QVariantMap cookies visible to this Page, at the current URL.
+ */
+ QVariantList cookies() const;
+ /**
+ * Add a Cookie (in QVariantMap format) into the CookieJar
+ * @see WebPage::setCookies for details on the format
+ * @brief addCookie
+ * @param cookie Cookie in QVariantMap format
+ * @return Boolean "true" if cookie was added
+ */
+ bool addCookie(const QVariantMap &cookie);
+ /**
+ * Delete cookie by name from the CookieJar
+ * @brief deleteCookie
+ * @param cookieName Name of the Cookie to delete
+ * @return Boolean "true" if cookie was deleted
+ */
+ bool deleteCookie(const QString &cookieName);
+ /**
+ * Delete All Cookies from the CookieJar
+ * @brief clearCookies
+ */
+ void clearCookies();
+
// exit() will not exit in debug mode. debugExit() will always exit.
void exit(int code = 0);
void debugExit(int code = 0);
View
40 src/webpage.cpp
@@ -563,12 +563,12 @@ QVariantMap WebPage::customHeaders() const
return m_networkAccessManager->customHeaders();
}
-void WebPage::setCookies(const QVariantList &cookies)
+bool WebPage::setCookies(const QVariantList &cookies)
{
// Delete all the cookies for this URL
CookieJar::instance()->deleteCookies(this->url());
// Add a new set of cookies foor this URL
- CookieJar::instance()->addCookiesFromMap(cookies, this->url());
+ return CookieJar::instance()->addCookiesFromMap(cookies, this->url());
}
QVariantList WebPage::cookies() const
@@ -577,21 +577,22 @@ QVariantList WebPage::cookies() const
return CookieJar::instance()->cookiesToMap(this->url());
}
-void WebPage::addCookie(const QVariantMap &cookie)
+bool WebPage::addCookie(const QVariantMap &cookie)
{
- CookieJar::instance()->addCookieFromMap(cookie, this->url());
+ return CookieJar::instance()->addCookieFromMap(cookie, this->url());
}
-void WebPage::deleteCookie(const QString &cookieName)
+bool WebPage::deleteCookie(const QString &cookieName)
{
if (!cookieName.isEmpty()) {
- CookieJar::instance()->deleteCookie(cookieName, this->url());
+ return CookieJar::instance()->deleteCookie(cookieName, this->url());
}
+ return false;
}
-void WebPage::clearCookies()
+bool WebPage::clearCookies()
{
- CookieJar::instance()->deleteCookie(this->url());
+ return CookieJar::instance()->deleteCookies(this->url());
}
void WebPage::openUrl(const QString &address, const QVariant &op, const QVariantMap &settings)
@@ -1252,6 +1253,18 @@ QString WebPage::focusedFrameName() const
return m_customWebPage->currentFrame()->frameName();
}
+static void injectCallbacksObjIntoFrames(QWebFrame *frame, WebpageCallbacks *callbacksObject)
+{
+ // Decorate the window object in this frame
+ frame->addToJavaScriptWindowObject(CALLBACKS_OBJECT_NAME, callbacksObject, QScriptEngine::QtOwnership);
+ frame->evaluateJavaScript(CALLBACKS_OBJECT_INJECTION);
+
+ // Decorate the window object in the child frames (recursively)
+ foreach (QWebFrame *childFrame, frame->childFrames()) {
+ injectCallbacksObjIntoFrames(childFrame, callbacksObject);
+ }
+}
+
void WebPage::handleJavaScriptWindowObjectCleared()
{
// Create Callbacks Holder object, if not already present for this page
@@ -1262,15 +1275,8 @@ void WebPage::handleJavaScriptWindowObjectCleared()
// Reset focus on the Main Frame
m_mainFrame->setFocus();
- // Decorate the window object in the Main Frame
- m_mainFrame->addToJavaScriptWindowObject(CALLBACKS_OBJECT_NAME, m_callbacks, QScriptEngine::QtOwnership);
- m_mainFrame->evaluateJavaScript(CALLBACKS_OBJECT_INJECTION);
-
- // Decorate the window object in the Main Frame's Child Frames
- foreach (QWebFrame *childFrame, m_mainFrame->childFrames()) {
- childFrame->addToJavaScriptWindowObject(CALLBACKS_OBJECT_NAME, m_callbacks, QScriptEngine::QtOwnership);
- childFrame->evaluateJavaScript(CALLBACKS_OBJECT_INJECTION);
- }
+ // Inject the Callbacks object in the frame and child-frames (recursively)
+ injectCallbacksObjIntoFrames(m_mainFrame, m_callbacks);
}
void WebPage::initCompletions()
View
12 src/webpage.h
@@ -363,8 +363,9 @@ public slots:
* </pre>
* @brief setCookies
* @param cookies Expects a QList of QVariantMaps
+ * @return Boolean "true" if at least 1 cookie was set
*/
- void setCookies(const QVariantList &cookies);
+ bool setCookies(const QVariantList &cookies);
/**
* Cookies visible by this Page, at the current URL.
*
@@ -378,19 +379,22 @@ public slots:
* @see WebPage::setCookies for details on the format
* @brief addCookie
* @param cookie Cookie in QVariantMap format
+ * @return Boolean "true" if cookie was added
*/
- void addCookie(const QVariantMap &cookie);
+ bool addCookie(const QVariantMap &cookie);
/**
* Delete cookie by name from the ones visible by this Page, at the current URL
* @brief deleteCookie
* @param cookieName Name of the Cookie to delete
+ * @return Boolean "true" if cookie was deleted
*/
- void deleteCookie(const QString &cookieName);
+ bool deleteCookie(const QString &cookieName);
/**
* Delete All Cookies visible by this Page, at the current URL
* @brief clearCookies
+ * @return Boolean "true" if cookies were deleted
*/
- void clearCookies();
+ bool clearCookies();
signals:
void initialized();
View
6 src/webserver.cpp
@@ -165,6 +165,11 @@ bool WebServer::handleRequest(mg_event event, mg_connection *conn, const mg_requ
///TODO: encoding?!
+ qDebug() << "HTTP Request - URI" << request->uri;
+ qDebug() << "HTTP Request - Method" << request->request_method;
+ qDebug() << "HTTP Request - HTTP Version" << request->http_version;
+ qDebug() << "HTTP Request - Query String" << request->query_string;
+
if (request->request_method)
requestObject["method"] = QString::fromLocal8Bit(request->request_method);
if (request->http_version)
@@ -384,6 +389,7 @@ void WebServerResponse::writeHead(int statusCode, const QVariantMap &headers)
m_headersSent = true;
m_statusCode = statusCode;
mg_printf(m_conn, "HTTP/1.1 %d %s\r\n", m_statusCode, responseCodeString(m_statusCode));
+ qDebug() << "HTTP Response - Status Code" << m_statusCode << responseCodeString(m_statusCode);
QVariantMap::const_iterator it = headers.constBegin();
while(it != headers.constEnd()) {
qDebug() << "HTTP Response - Sending Header" << it.key() << "=" << it.value().toString();
View
25 test/webpage-spec.js
@@ -615,6 +615,14 @@ describe("WebPage object", function() {
'path' : '/foo',
'httponly' : true,
'secure' : false
+ },{
+ 'name' : 'Valid-Cookie-Name-Sec',
+ 'value' : 'Valid-Cookie-Value-Sec',
+ 'domain' : 'localhost',
+ 'path' : '/foo',
+ 'httponly' : true,
+ 'secure' : false,
+ 'expires' : new Date().getTime() + 3600 //< expires in 1h
}];
var handled = false;
@@ -628,6 +636,8 @@ describe("WebPage object", function() {
// console.log(JSON.stringify(echoedHeaders));
expect(echoedHeaders["Cookie"]).toContain("Valid-Cookie-Name");
expect(echoedHeaders["Cookie"]).toContain("Valid-Cookie-Value");
+ expect(echoedHeaders["Cookie"]).toContain("Valid-Cookie-Name-Sec");
+ expect(echoedHeaders["Cookie"]).toContain("Valid-Cookie-Value-Sec");
});
});
@@ -653,10 +663,7 @@ describe("WebPage object", function() {
var url = "http://localhost:12345/foo/headers.txt?ab=cd";
page.cookies = [
- { // domain missing.
- 'name' : 'Invalid-Cookie-Name',
- 'value' : 'Invalid-Cookie-Value'
- },{ // domain mismatch.
+ { // domain mismatch.
'name' : 'Invalid-Cookie-Name',
'value' : 'Invalid-Cookie-Value',
'domain' : 'foo.com'
@@ -677,6 +684,16 @@ describe("WebPage object", function() {
'value' : 'Invalid-Cookie-Value',
'domain' : 'localhost',
'secure' : true
+ },{ // cookie expired (date in "sec since epoch").
+ 'name' : 'Invalid-Cookie-Name',
+ 'value' : 'Invalid-Cookie-Value',
+ 'domain' : 'localhost',
+ 'expires' : new Date().getTime() - 1 //< date in the past
+ },{ // cookie expired (date in "sec since epoch" - using "expiry").
+ 'name' : 'Invalid-Cookie-Name',
+ 'value' : 'Invalid-Cookie-Value',
+ 'domain' : 'localhost',
+ 'expiry' : new Date().getTime() - 1 //< date in the past
}];
var handled = false;
Please sign in to comment.
Something went wrong with that request. Please try again.