2011-04-09 21:34:04 +04:00
|
|
|
/*
|
|
|
|
This file is part of the PhantomJS project from Ofi Labs.
|
|
|
|
|
|
|
|
Copyright (C) 2011 Ariya Hidayat <ariya.hidayat@gmail.com>
|
2011-04-10 09:37:06 +04:00
|
|
|
Copyright (C) 2010 Ariya Hidayat <ariya.hidayat@gmail.com>
|
2011-04-09 21:34:04 +04:00
|
|
|
|
|
|
|
Redistribution and use in source and binary forms, with or without
|
|
|
|
modification, are permitted provided that the following conditions are met:
|
|
|
|
|
|
|
|
* Redistributions of source code must retain the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer.
|
|
|
|
* Redistributions in binary form must reproduce the above copyright
|
|
|
|
notice, this list of conditions and the following disclaimer in the
|
|
|
|
documentation and/or other materials provided with the distribution.
|
|
|
|
* Neither the name of the <organization> nor the
|
|
|
|
names of its contributors may be used to endorse or promote products
|
|
|
|
derived from this software without specific prior written permission.
|
|
|
|
|
|
|
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
|
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
|
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
ARE DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
|
|
|
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
|
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
|
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
|
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
|
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
|
|
THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*/
|
|
|
|
|
2011-05-25 21:46:51 +04:00
|
|
|
#include "phantom.h"
|
|
|
|
|
|
|
|
#include <QtGui>
|
|
|
|
#include <QtWebKit>
|
2011-06-08 02:22:41 +04:00
|
|
|
#include <QDir>
|
|
|
|
#include <QFileInfo>
|
2011-06-14 14:28:51 +04:00
|
|
|
#include <QFile>
|
2010-12-27 07:04:53 +03:00
|
|
|
|
2011-04-08 17:30:50 +04:00
|
|
|
#include "consts.h"
|
2011-08-21 11:47:34 +04:00
|
|
|
#include "terminal.h"
|
2011-04-08 17:30:50 +04:00
|
|
|
#include "utils.h"
|
2011-05-25 21:46:51 +04:00
|
|
|
#include "webpage.h"
|
2011-01-01 19:28:38 +03:00
|
|
|
|
2011-08-16 22:15:02 +04:00
|
|
|
|
2011-06-14 14:28:51 +04:00
|
|
|
// public:
|
2010-12-27 07:04:53 +03:00
|
|
|
Phantom::Phantom(QObject *parent)
|
|
|
|
: QObject(parent)
|
2011-05-29 11:20:56 +04:00
|
|
|
, m_terminated(false)
|
2010-12-27 07:04:53 +03:00
|
|
|
, m_returnValue(0)
|
2011-04-08 20:55:10 +04:00
|
|
|
, m_netAccessMan(0)
|
2010-12-27 07:04:53 +03:00
|
|
|
{
|
2011-08-26 22:02:35 +04:00
|
|
|
// Load default configuration
|
|
|
|
m_config.load();
|
|
|
|
|
2011-05-26 01:00:20 +04:00
|
|
|
m_page = new WebPage(this);
|
2011-06-29 02:27:26 +04:00
|
|
|
m_pages.append(m_page);
|
2010-12-27 07:04:53 +03:00
|
|
|
|
|
|
|
// second argument: script name
|
2011-02-14 07:41:59 +03:00
|
|
|
QStringList args = QApplication::arguments();
|
2011-02-13 22:38:09 +03:00
|
|
|
|
2011-02-14 07:41:59 +03:00
|
|
|
// Skip the first argument, i.e. the application executable (phantomjs).
|
|
|
|
args.removeFirst();
|
|
|
|
|
|
|
|
// Handle all command-line options.
|
|
|
|
QStringListIterator argIterator(args);
|
2011-02-06 21:55:04 +03:00
|
|
|
while (argIterator.hasNext()) {
|
|
|
|
const QString &arg = argIterator.next();
|
2011-06-06 11:36:31 +04:00
|
|
|
if (arg == "--version") {
|
|
|
|
m_terminated = true;
|
2011-08-21 11:47:34 +04:00
|
|
|
Terminal::instance()->cout(QString("%1 (development)").arg(PHANTOMJS_VERSION_STRING));
|
2011-06-06 11:36:31 +04:00
|
|
|
return;
|
|
|
|
}
|
2011-02-14 08:29:58 +03:00
|
|
|
if (arg == "--load-images=yes") {
|
2011-08-26 22:02:59 +04:00
|
|
|
m_config.setAutoLoadImages(true);
|
2011-02-14 08:29:58 +03:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (arg == "--load-images=no") {
|
2011-08-26 22:02:59 +04:00
|
|
|
m_config.setAutoLoadImages(false);
|
2011-02-14 08:29:58 +03:00
|
|
|
continue;
|
|
|
|
}
|
2011-02-14 09:44:00 +03:00
|
|
|
if (arg == "--load-plugins=yes") {
|
2011-08-26 22:02:59 +04:00
|
|
|
m_config.setPluginsEnabled(true);
|
2011-02-14 09:44:00 +03:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (arg == "--load-plugins=no") {
|
2011-08-26 22:02:59 +04:00
|
|
|
m_config.setPluginsEnabled(false);
|
2011-02-14 09:44:00 +03:00
|
|
|
continue;
|
|
|
|
}
|
2011-04-12 18:21:09 +04:00
|
|
|
if (arg == "--disk-cache=yes") {
|
2011-08-26 22:02:51 +04:00
|
|
|
m_config.setDiskCacheEnabled(true);
|
2011-04-12 18:21:09 +04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (arg == "--disk-cache=no") {
|
2011-08-26 22:02:51 +04:00
|
|
|
m_config.setDiskCacheEnabled(false);
|
2011-04-12 18:21:09 +04:00
|
|
|
continue;
|
|
|
|
}
|
2011-04-29 12:24:35 +04:00
|
|
|
if (arg == "--ignore-ssl-errors=yes") {
|
2011-08-26 22:02:51 +04:00
|
|
|
m_config.setIgnoreSslErrors(true);
|
2011-04-29 12:24:35 +04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (arg == "--ignore-ssl-errors=no") {
|
2011-08-26 22:02:51 +04:00
|
|
|
m_config.setIgnoreSslErrors(false);
|
2011-04-29 12:24:35 +04:00
|
|
|
continue;
|
|
|
|
}
|
2011-06-24 18:57:55 +04:00
|
|
|
if (arg == "--local-access-remote=no") {
|
2011-08-26 22:02:59 +04:00
|
|
|
m_config.setLocalAccessRemote(false);
|
2011-06-24 18:57:55 +04:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (arg == "--local-access-remote=yes") {
|
2011-08-26 22:02:59 +04:00
|
|
|
m_config.setLocalAccessRemote(true);
|
2011-06-24 18:57:55 +04:00
|
|
|
continue;
|
|
|
|
}
|
2011-03-14 07:35:05 +03:00
|
|
|
if (arg.startsWith("--proxy=")) {
|
2011-08-26 22:02:43 +04:00
|
|
|
m_config.setProxy(arg.mid(8).trimmed());
|
2011-03-14 07:35:05 +03:00
|
|
|
continue;
|
|
|
|
}
|
2011-07-19 21:32:42 +04:00
|
|
|
if (arg.startsWith("--cookies=")) {
|
2011-08-26 22:02:51 +04:00
|
|
|
m_config.setCookieFile(arg.mid(10).trimmed());
|
2011-07-19 21:32:42 +04:00
|
|
|
continue;
|
|
|
|
}
|
2011-08-16 22:49:12 +04:00
|
|
|
if (arg.startsWith("--output-encoding=")) {
|
2011-08-26 22:02:35 +04:00
|
|
|
m_config.setOutputEncoding(arg.mid(18).trimmed());
|
2011-08-16 22:49:12 +04:00
|
|
|
continue;
|
|
|
|
}
|
2011-08-16 22:53:56 +04:00
|
|
|
if (arg.startsWith("--script-encoding=")) {
|
2011-08-26 22:02:35 +04:00
|
|
|
m_config.setScriptEncoding(arg.mid(18).trimmed());
|
2011-08-16 22:53:56 +04:00
|
|
|
continue;
|
|
|
|
}
|
2011-02-14 07:41:59 +03:00
|
|
|
if (arg.startsWith("--")) {
|
2011-08-21 11:47:34 +04:00
|
|
|
Terminal::instance()->cerr(QString("Unknown option '%1'").arg(arg));
|
2011-06-18 05:37:01 +04:00
|
|
|
m_terminated = true;
|
2011-02-14 07:41:59 +03:00
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
m_scriptFile = arg;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (m_scriptFile.isEmpty()) {
|
2011-04-08 17:30:50 +04:00
|
|
|
Utils::showUsage();
|
2011-02-14 07:41:59 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-08-26 22:02:43 +04:00
|
|
|
if (m_config.proxyHost().isEmpty()) {
|
2011-03-14 07:35:05 +03:00
|
|
|
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
|
|
|
} else {
|
2011-08-26 22:02:43 +04:00
|
|
|
QNetworkProxy proxy(QNetworkProxy::HttpProxy, m_config.proxyHost(), m_config.proxyPort());
|
2011-03-14 07:35:05 +03:00
|
|
|
QNetworkProxy::setApplicationProxy(proxy);
|
|
|
|
}
|
|
|
|
|
2011-02-14 08:29:58 +03:00
|
|
|
// The remaining arguments are available for the script.
|
2011-02-14 07:41:59 +03:00
|
|
|
while (argIterator.hasNext()) {
|
|
|
|
const QString &arg = argIterator.next();
|
|
|
|
m_args += arg;
|
2011-02-06 21:55:04 +03:00
|
|
|
}
|
2010-12-27 07:04:53 +03:00
|
|
|
|
2011-08-26 22:02:35 +04:00
|
|
|
// Set output encoding
|
|
|
|
Terminal::instance()->setEncoding(m_config.outputEncoding());
|
|
|
|
|
|
|
|
// Set script file encoding
|
|
|
|
m_scriptFileEnc.setEncoding(m_config.scriptEncoding());
|
|
|
|
|
2011-04-08 20:55:10 +04:00
|
|
|
// Provide WebPage with a non-standard Network Access Manager
|
2011-08-26 22:02:51 +04:00
|
|
|
m_netAccessMan = new NetworkAccessManager(this, m_config.diskCacheEnabled(), m_config.cookieFile(), m_config.ignoreSslErrors());
|
2011-05-26 01:00:20 +04:00
|
|
|
m_page->setNetworkAccessManager(m_netAccessMan);
|
2011-04-08 20:55:10 +04:00
|
|
|
|
2011-06-20 08:06:27 +04:00
|
|
|
connect(m_page, SIGNAL(javaScriptConsoleMessageSent(QString, int, QString)),
|
|
|
|
SLOT(printConsoleMessage(QString, int, QString)));
|
2011-05-29 08:16:18 +04:00
|
|
|
|
2011-08-26 22:02:59 +04:00
|
|
|
m_defaultPageSettings[PAGE_SETTINGS_LOAD_IMAGES] = QVariant::fromValue(m_config.autoLoadImages());
|
|
|
|
m_defaultPageSettings[PAGE_SETTINGS_LOAD_PLUGINS] = QVariant::fromValue(m_config.pluginsEnabled());
|
2011-08-20 02:47:34 +04:00
|
|
|
m_defaultPageSettings[PAGE_SETTINGS_JS_ENABLED] = QVariant::fromValue(true);
|
|
|
|
m_defaultPageSettings[PAGE_SETTINGS_XSS_AUDITING] = QVariant::fromValue(false);
|
2011-06-24 18:57:55 +04:00
|
|
|
m_defaultPageSettings[PAGE_SETTINGS_USER_AGENT] = QVariant::fromValue(m_page->userAgent());
|
2011-08-26 22:02:59 +04:00
|
|
|
m_defaultPageSettings[PAGE_SETTINGS_LOCAL_ACCESS_REMOTE] = QVariant::fromValue(m_config.localAccessRemote());
|
2011-05-28 09:36:34 +04:00
|
|
|
m_page->applySettings(m_defaultPageSettings);
|
2011-01-28 02:53:51 +03:00
|
|
|
|
2011-06-18 07:17:58 +04:00
|
|
|
setLibraryPath(QFileInfo(m_scriptFile).dir().absolutePath());
|
2011-06-13 01:38:34 +04:00
|
|
|
|
2011-05-26 01:00:20 +04:00
|
|
|
m_page->mainFrame()->addToJavaScriptWindowObject("phantom", this);
|
2011-06-29 00:02:48 +04:00
|
|
|
m_page->mainFrame()->addToJavaScriptWindowObject("fs", &m_filesystem);
|
2011-05-26 13:18:09 +04:00
|
|
|
|
|
|
|
QFile file(":/bootstrap.js");
|
|
|
|
if (!file.open(QFile::ReadOnly)) {
|
2011-08-21 11:47:34 +04:00
|
|
|
Terminal::instance()->cerr("Can not bootstrap!");
|
2011-05-26 13:18:09 +04:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
QString bootstrapper = QString::fromUtf8(file.readAll());
|
|
|
|
file.close();
|
|
|
|
if (bootstrapper.isEmpty()) {
|
2011-08-21 11:47:34 +04:00
|
|
|
Terminal::instance()->cerr("Can not bootstrap!");
|
2011-05-26 13:18:09 +04:00
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
m_page->mainFrame()->evaluateJavaScript(bootstrapper);
|
2010-12-27 07:04:53 +03:00
|
|
|
}
|
|
|
|
|
2011-05-25 21:46:51 +04:00
|
|
|
QStringList Phantom::args() const
|
2010-12-27 07:04:53 +03:00
|
|
|
{
|
2011-05-25 21:46:51 +04:00
|
|
|
return m_args;
|
2010-12-27 07:04:53 +03:00
|
|
|
}
|
|
|
|
|
2011-05-28 09:36:34 +04:00
|
|
|
QVariantMap Phantom::defaultPageSettings() const
|
|
|
|
{
|
|
|
|
return m_defaultPageSettings;
|
|
|
|
}
|
|
|
|
|
2011-08-16 23:17:42 +04:00
|
|
|
QString Phantom::outputEncoding() const
|
2011-08-16 22:18:52 +04:00
|
|
|
{
|
2011-08-21 11:47:34 +04:00
|
|
|
return Terminal::instance()->getEncoding();
|
2011-08-16 22:18:52 +04:00
|
|
|
}
|
|
|
|
|
2011-08-16 23:17:42 +04:00
|
|
|
void Phantom::setOutputEncoding(const QString &encoding)
|
2011-08-16 22:18:52 +04:00
|
|
|
{
|
2011-08-21 11:47:34 +04:00
|
|
|
Terminal::instance()->setEncoding(encoding);
|
2011-08-16 22:18:52 +04:00
|
|
|
}
|
|
|
|
|
2011-02-14 07:41:59 +03:00
|
|
|
bool Phantom::execute()
|
2010-12-27 07:04:53 +03:00
|
|
|
{
|
2011-06-18 05:04:20 +04:00
|
|
|
if (m_terminated)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (m_scriptFile.isEmpty())
|
|
|
|
return false;
|
|
|
|
|
2011-08-16 22:53:56 +04:00
|
|
|
if (!Utils::injectJsInFrame(m_scriptFile, m_scriptFileEnc, QDir::currentPath(), m_page->mainFrame(), true)) {
|
2011-06-18 05:04:20 +04:00
|
|
|
m_returnValue = -1;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2011-06-18 07:52:13 +04:00
|
|
|
return !m_terminated;
|
2010-12-27 07:04:53 +03:00
|
|
|
}
|
|
|
|
|
2011-04-08 17:30:50 +04:00
|
|
|
int Phantom::returnValue() const
|
2010-12-27 07:04:53 +03:00
|
|
|
{
|
2011-04-08 17:30:50 +04:00
|
|
|
return m_returnValue;
|
2010-12-27 07:04:53 +03:00
|
|
|
}
|
|
|
|
|
2011-06-14 14:28:51 +04:00
|
|
|
QString Phantom::libraryPath() const
|
|
|
|
{
|
|
|
|
return m_page->libraryPath();
|
|
|
|
}
|
|
|
|
|
|
|
|
void Phantom::setLibraryPath(const QString &libraryPath)
|
|
|
|
{
|
|
|
|
m_page->setLibraryPath(libraryPath);
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Phantom::scriptName() const
|
|
|
|
{
|
|
|
|
return QFileInfo(m_scriptFile).fileName();
|
|
|
|
}
|
|
|
|
|
2011-04-08 17:30:50 +04:00
|
|
|
QVariantMap Phantom::version() const
|
|
|
|
{
|
|
|
|
QVariantMap result;
|
|
|
|
result["major"] = PHANTOMJS_VERSION_MAJOR;
|
|
|
|
result["minor"] = PHANTOMJS_VERSION_MINOR;
|
|
|
|
result["patch"] = PHANTOMJS_VERSION_PATCH;
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2011-06-14 14:28:51 +04:00
|
|
|
// public slots:
|
2011-05-25 21:46:51 +04:00
|
|
|
QObject *Phantom::createWebPage()
|
2011-04-08 17:30:50 +04:00
|
|
|
{
|
2011-05-26 12:56:43 +04:00
|
|
|
WebPage *page = new WebPage(this);
|
2011-06-29 02:27:26 +04:00
|
|
|
m_pages.append(page);
|
2011-05-28 09:36:34 +04:00
|
|
|
page->applySettings(m_defaultPageSettings);
|
2011-05-26 12:56:43 +04:00
|
|
|
page->setNetworkAccessManager(m_netAccessMan);
|
2011-06-18 07:17:58 +04:00
|
|
|
page->setLibraryPath(QFileInfo(m_scriptFile).dir().absolutePath());
|
2011-05-26 12:56:43 +04:00
|
|
|
return page;
|
2011-04-08 17:30:50 +04:00
|
|
|
}
|
|
|
|
|
2011-06-14 14:28:51 +04:00
|
|
|
bool Phantom::injectJs(const QString &jsFilePath) {
|
|
|
|
return Utils::injectJsInFrame(jsFilePath, libraryPath(), m_page->mainFrame());
|
|
|
|
}
|
|
|
|
|
2011-06-20 21:14:08 +04:00
|
|
|
void Phantom::exit(int code)
|
2011-04-08 17:30:50 +04:00
|
|
|
{
|
2011-05-29 11:20:56 +04:00
|
|
|
m_terminated = true;
|
2011-04-08 17:30:50 +04:00
|
|
|
m_returnValue = code;
|
2011-06-29 02:27:26 +04:00
|
|
|
qDeleteAll(m_pages);
|
|
|
|
m_pages.clear();
|
2011-06-21 10:24:51 +04:00
|
|
|
m_page = 0;
|
2011-05-29 11:20:56 +04:00
|
|
|
QApplication::instance()->exit(code);
|
2010-12-27 07:04:53 +03:00
|
|
|
}
|
2011-05-29 08:16:18 +04:00
|
|
|
|
2011-06-14 14:28:51 +04:00
|
|
|
// private slots:
|
2011-06-20 08:06:27 +04:00
|
|
|
void Phantom::printConsoleMessage(const QString &message, int lineNumber, const QString &source)
|
2011-05-29 08:16:18 +04:00
|
|
|
{
|
2011-06-20 08:06:27 +04:00
|
|
|
QString msg = message;
|
|
|
|
if (!source.isEmpty())
|
|
|
|
msg = source + ":" + QString::number(lineNumber) + " " + msg;
|
2011-08-21 11:47:34 +04:00
|
|
|
Terminal::instance()->cout(msg);
|
2011-05-29 08:16:18 +04:00
|
|
|
}
|