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-08-31 19:29:40 +04:00
|
|
|
Copyright (C) 2011 Ivan De Marino <ivan.de.marino@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-11-15 16:44:47 +04:00
|
|
|
#include "webserver.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-09-09 04:37:01 +04:00
|
|
|
, m_filesystem(0)
|
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();
|
|
|
|
|
2011-08-28 16:40:00 +04:00
|
|
|
m_config.init(&args);
|
|
|
|
|
2012-01-09 20:31:49 +04:00
|
|
|
if (m_config.helpFlag()) {
|
|
|
|
m_terminated = true;
|
|
|
|
Utils::showUsage();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2011-08-28 16:40:00 +04:00
|
|
|
if (m_config.versionFlag()) {
|
|
|
|
m_terminated = true;
|
2012-01-12 01:59:19 +04:00
|
|
|
Terminal::instance()->cout(QString("%1").arg(PHANTOMJS_VERSION_STRING));
|
2011-08-28 16:40:00 +04:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!m_config.unknownOption().isEmpty()) {
|
|
|
|
Terminal::instance()->cerr(m_config.unknownOption());
|
|
|
|
m_terminated = true;
|
|
|
|
return;
|
2011-02-14 07:41:59 +03:00
|
|
|
}
|
|
|
|
|
2012-02-13 21:47:09 +04:00
|
|
|
m_page = new WebPage(this, &m_config, QUrl::fromLocalFile(m_config.scriptFile()));
|
2011-08-28 16:40:00 +04:00
|
|
|
m_pages.append(m_page);
|
|
|
|
|
|
|
|
if (m_config.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-11-09 09:22:30 +04:00
|
|
|
QString proxyType = m_config.proxyType();
|
|
|
|
QNetworkProxy::ProxyType networkProxyType = QNetworkProxy::HttpProxy;
|
|
|
|
|
|
|
|
if (proxyType == "socks5") {
|
|
|
|
networkProxyType = QNetworkProxy::Socks5Proxy;
|
|
|
|
}
|
|
|
|
|
|
|
|
QNetworkProxy proxy(networkProxyType, m_config.proxyHost(), m_config.proxyPort());
|
2011-03-14 07:35:05 +03:00
|
|
|
QNetworkProxy::setApplicationProxy(proxy);
|
|
|
|
}
|
|
|
|
|
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-06-20 08:06:27 +04:00
|
|
|
connect(m_page, SIGNAL(javaScriptConsoleMessageSent(QString, int, QString)),
|
|
|
|
SLOT(printConsoleMessage(QString, int, QString)));
|
2011-10-25 23:16:25 +04:00
|
|
|
connect(m_page, SIGNAL(initialized()),
|
|
|
|
SLOT(onInitialized()));
|
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-09-07 20:27:20 +04:00
|
|
|
m_defaultPageSettings[PAGE_SETTINGS_LOCAL_ACCESS_REMOTE] = QVariant::fromValue(m_config.localToRemoteUrlAccessEnabled());
|
2011-05-28 09:36:34 +04:00
|
|
|
m_page->applySettings(m_defaultPageSettings);
|
2011-01-28 02:53:51 +03:00
|
|
|
|
2011-08-28 16:40:00 +04:00
|
|
|
setLibraryPath(QFileInfo(m_config.scriptFile()).dir().absolutePath());
|
2011-06-13 01:38:34 +04:00
|
|
|
|
2011-10-25 23:16:25 +04:00
|
|
|
onInitialized();
|
|
|
|
}
|
2011-05-26 13:18:09 +04:00
|
|
|
|
2011-10-25 23:16:25 +04:00
|
|
|
Phantom::~Phantom()
|
|
|
|
{
|
2010-12-27 07:04:53 +03:00
|
|
|
}
|
|
|
|
|
2011-10-25 23:16:25 +04:00
|
|
|
|
2011-05-25 21:46:51 +04:00
|
|
|
QStringList Phantom::args() const
|
2010-12-27 07:04:53 +03:00
|
|
|
{
|
2011-08-28 16:40:00 +04:00
|
|
|
return m_config.scriptArgs();
|
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;
|
|
|
|
|
2011-08-28 16:40:00 +04:00
|
|
|
if (m_config.scriptFile().isEmpty())
|
2011-06-18 05:04:20 +04:00
|
|
|
return false;
|
|
|
|
|
2011-10-25 23:16:25 +04:00
|
|
|
if (m_config.debug())
|
|
|
|
{
|
2012-02-27 01:15:44 +04:00
|
|
|
if (!Utils::loadJSForDebug(m_config.scriptFile(), m_scriptFileEnc, QDir::currentPath(), m_page->mainFrame(), m_config.remoteDebugAutorun())) {
|
2011-10-25 23:16:25 +04:00
|
|
|
m_returnValue = -1;
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
m_page->showInspector(m_config.remoteDebugPort());
|
|
|
|
} else {
|
|
|
|
if (!Utils::injectJsInFrame(m_config.scriptFile(), m_scriptFileEnc, QDir::currentPath(), m_page->mainFrame(), true)) {
|
|
|
|
m_returnValue = -1;
|
|
|
|
return false;
|
|
|
|
}
|
2011-06-18 05:04:20 +04:00
|
|
|
}
|
|
|
|
|
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
|
|
|
|
{
|
2011-08-28 16:40:00 +04:00
|
|
|
return QFileInfo(m_config.scriptFile()).fileName();
|
2011-06-14 14:28:51 +04:00
|
|
|
}
|
|
|
|
|
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-09-15 10:46:01 +04:00
|
|
|
WebPage *page = new WebPage(this, &m_config);
|
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-08-28 16:40:00 +04:00
|
|
|
page->setLibraryPath(QFileInfo(m_config.scriptFile()).dir().absolutePath());
|
2012-02-25 18:13:51 +04:00
|
|
|
|
|
|
|
if (m_config.debug()) {
|
|
|
|
page->showInspector(m_config.remoteDebugPort());
|
|
|
|
}
|
|
|
|
|
2011-05-26 12:56:43 +04:00
|
|
|
return page;
|
2011-04-08 17:30:50 +04:00
|
|
|
}
|
|
|
|
|
2011-11-15 16:44:47 +04:00
|
|
|
QObject* Phantom::createWebServer()
|
|
|
|
{
|
|
|
|
WebServer *server = new WebServer(this, &m_config);
|
|
|
|
m_servers.append(server);
|
|
|
|
///TODO:
|
|
|
|
// page->applySettings(m_defaultPageSettings);
|
|
|
|
// page->setLibraryPath(QFileInfo(m_config.scriptFile()).dir().absolutePath());
|
|
|
|
return server;
|
|
|
|
}
|
|
|
|
|
2011-09-08 20:55:50 +04:00
|
|
|
QObject *Phantom::createFilesystem()
|
|
|
|
{
|
2011-09-09 04:37:01 +04:00
|
|
|
if (!m_filesystem)
|
|
|
|
m_filesystem = new FileSystem(this);
|
|
|
|
|
|
|
|
return m_filesystem;
|
2011-09-08 20:55:50 +04:00
|
|
|
}
|
|
|
|
|
2011-09-11 12:00:21 +04:00
|
|
|
QString Phantom::loadModuleSource(const QString &name)
|
|
|
|
{
|
|
|
|
QString moduleSource;
|
|
|
|
QString moduleSourceFilePath = ":/modules/" + name + ".js";
|
|
|
|
|
2011-10-16 23:35:21 +04:00
|
|
|
moduleSource = Utils::readResourceFileUtf8(moduleSourceFilePath);
|
2011-09-11 12:00:21 +04:00
|
|
|
|
|
|
|
return moduleSource;
|
|
|
|
}
|
|
|
|
|
2011-09-11 13:19:20 +04:00
|
|
|
bool Phantom::injectJs(const QString &jsFilePath)
|
|
|
|
{
|
2011-06-14 14:28:51 +04:00
|
|
|
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-10-25 23:16:25 +04:00
|
|
|
if (m_config.debug())
|
|
|
|
Terminal::instance()->cout("Phantom::exit() called but not quitting in debug mode.");
|
|
|
|
else {
|
2011-12-20 05:53:39 +04:00
|
|
|
doExit(code);
|
2011-10-25 23:16:25 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Phantom::debugExit(int code)
|
|
|
|
{
|
|
|
|
doExit(code);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void Phantom::doExit(int code)
|
|
|
|
{
|
|
|
|
if (m_config.debug())
|
|
|
|
{
|
|
|
|
Utils::cleanupFromDebug();
|
|
|
|
}
|
|
|
|
|
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-10-25 23:16:25 +04:00
|
|
|
|
|
|
|
void
|
|
|
|
Phantom::onInitialized()
|
|
|
|
{
|
|
|
|
// Add 'phantom' object to the global scope
|
|
|
|
m_page->mainFrame()->addToJavaScriptWindowObject("phantom", this);
|
|
|
|
|
|
|
|
// Bootstrap the PhantomJS scope
|
|
|
|
m_page->mainFrame()->evaluateJavaScript(Utils::readResourceFileUtf8(":/bootstrap.js"));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
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
|
|
|
}
|