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"
|
|
|
|
|
2011-04-08 20:55:10 +04:00
|
|
|
#include <iostream>
|
2011-05-25 21:46:51 +04:00
|
|
|
|
|
|
|
#include <QtGui>
|
|
|
|
#include <QtWebKit>
|
2010-12-27 07:04:53 +03:00
|
|
|
|
2011-02-20 09:07:22 +03:00
|
|
|
#include <gifwriter.h>
|
2011-04-08 17:30:50 +04:00
|
|
|
#include "consts.h"
|
|
|
|
#include "utils.h"
|
2011-05-25 21:46:51 +04:00
|
|
|
#include "webpage.h"
|
2011-01-01 19:28:38 +03:00
|
|
|
|
2010-12-27 07:04:53 +03:00
|
|
|
Phantom::Phantom(QObject *parent)
|
|
|
|
: QObject(parent)
|
|
|
|
, m_returnValue(0)
|
2011-03-02 11:41:23 +03:00
|
|
|
, m_converter(0)
|
2011-04-08 20:55:10 +04:00
|
|
|
, m_netAccessMan(0)
|
2010-12-27 07:04:53 +03:00
|
|
|
{
|
2011-05-26 01:00:20 +04:00
|
|
|
m_page = new WebPage(this);
|
2010-12-27 07:04:53 +03:00
|
|
|
|
2011-05-25 21:46:51 +04:00
|
|
|
QString proxyHost;
|
|
|
|
int proxyPort = 1080;
|
2011-02-14 08:29:58 +03:00
|
|
|
bool autoLoadImages = true;
|
2011-03-01 02:17:59 +03:00
|
|
|
bool pluginsEnabled = false;
|
2011-04-12 18:21:09 +04:00
|
|
|
bool diskCacheEnabled = false;
|
2011-04-29 12:24:35 +04:00
|
|
|
bool ignoreSslErrors = false;
|
2011-02-14 08:29:58 +03:00
|
|
|
|
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-02-14 08:29:58 +03:00
|
|
|
if (arg == "--load-images=yes") {
|
|
|
|
autoLoadImages = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (arg == "--load-images=no") {
|
|
|
|
autoLoadImages = false;
|
|
|
|
continue;
|
|
|
|
}
|
2011-02-14 09:44:00 +03:00
|
|
|
if (arg == "--load-plugins=yes") {
|
|
|
|
pluginsEnabled = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (arg == "--load-plugins=no") {
|
|
|
|
pluginsEnabled = false;
|
|
|
|
continue;
|
|
|
|
}
|
2011-04-12 18:21:09 +04:00
|
|
|
if (arg == "--disk-cache=yes") {
|
|
|
|
diskCacheEnabled = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (arg == "--disk-cache=no") {
|
|
|
|
diskCacheEnabled = false;
|
|
|
|
continue;
|
|
|
|
}
|
2011-04-29 12:24:35 +04:00
|
|
|
if (arg == "--ignore-ssl-errors=yes") {
|
|
|
|
ignoreSslErrors = true;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (arg == "--ignore-ssl-errors=no") {
|
|
|
|
ignoreSslErrors = false;
|
|
|
|
continue;
|
|
|
|
}
|
2011-03-14 07:35:05 +03:00
|
|
|
if (arg.startsWith("--proxy=")) {
|
2011-05-25 21:46:51 +04:00
|
|
|
proxyHost = arg.mid(8).trimmed();
|
|
|
|
if (proxyHost.lastIndexOf(':') > 0) {
|
2011-03-14 07:35:05 +03:00
|
|
|
bool ok = true;
|
2011-05-25 21:46:51 +04:00
|
|
|
int port = proxyHost.mid(proxyHost.lastIndexOf(':') + 1).toInt(&ok);
|
2011-03-14 07:35:05 +03:00
|
|
|
if (ok) {
|
2011-05-25 21:46:51 +04:00
|
|
|
proxyHost = proxyHost.left(proxyHost.lastIndexOf(':')).trimmed();
|
|
|
|
proxyPort = port;
|
2011-03-14 07:35:05 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
continue;
|
|
|
|
}
|
2011-02-14 07:41:59 +03:00
|
|
|
if (arg.startsWith("--")) {
|
2011-04-08 18:49:20 +04:00
|
|
|
qFatal("Unknown option '%s'", qPrintable(arg));
|
2011-02-14 07:41:59 +03:00
|
|
|
exit(-1);
|
|
|
|
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-05-25 21:46:51 +04:00
|
|
|
if (proxyHost.isEmpty()) {
|
2011-04-19 09:49:45 +04:00
|
|
|
#if QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)
|
2011-03-14 07:35:05 +03:00
|
|
|
QNetworkProxyFactory::setUseSystemConfiguration(true);
|
2011-04-19 09:49:45 +04:00
|
|
|
#endif
|
2011-03-14 07:35:05 +03:00
|
|
|
} else {
|
2011-05-25 21:46:51 +04:00
|
|
|
QNetworkProxy proxy(QNetworkProxy::HttpProxy, proxyHost, 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-04-08 20:55:10 +04:00
|
|
|
// Provide WebPage with a non-standard Network Access Manager
|
2011-04-29 12:24:35 +04:00
|
|
|
m_netAccessMan = new NetworkAccessManager(this, diskCacheEnabled, ignoreSslErrors);
|
2011-05-26 01:00:20 +04:00
|
|
|
m_page->setNetworkAccessManager(m_netAccessMan);
|
2011-04-08 20:55:10 +04:00
|
|
|
|
2011-05-28 07:37:36 +04:00
|
|
|
m_defaultPageSettings["loadImages"] = QVariant::fromValue(autoLoadImages);
|
|
|
|
m_defaultPageSettings["loadPlugins"] = QVariant::fromValue(pluginsEnabled);
|
2011-05-28 09:50:33 +04:00
|
|
|
m_defaultPageSettings["userAgent"] = QVariant::fromValue(m_page->userAgent());
|
2011-05-28 09:36:34 +04:00
|
|
|
m_page->applySettings(m_defaultPageSettings);
|
2011-01-28 02:53:51 +03:00
|
|
|
|
2011-05-26 01:00:20 +04:00
|
|
|
m_page->mainFrame()->addToJavaScriptWindowObject("phantom", this);
|
2011-05-26 13:18:09 +04:00
|
|
|
|
|
|
|
QFile file(":/bootstrap.js");
|
|
|
|
if (!file.open(QFile::ReadOnly)) {
|
|
|
|
qCritical() << "Can not bootstrap!";
|
|
|
|
exit(1);
|
|
|
|
}
|
|
|
|
QString bootstrapper = QString::fromUtf8(file.readAll());
|
|
|
|
file.close();
|
|
|
|
if (bootstrapper.isEmpty()) {
|
|
|
|
qCritical() << "Can not bootstrap!";
|
|
|
|
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-02-14 07:41:59 +03:00
|
|
|
bool Phantom::execute()
|
2010-12-27 07:04:53 +03:00
|
|
|
{
|
2011-02-14 07:41:59 +03:00
|
|
|
if (m_scriptFile.isEmpty())
|
|
|
|
return false;
|
|
|
|
|
2010-12-27 07:04:53 +03:00
|
|
|
QFile file;
|
2011-02-14 07:41:59 +03:00
|
|
|
file.setFileName(m_scriptFile);
|
2010-12-27 07:04:53 +03:00
|
|
|
if (!file.open(QFile::ReadOnly)) {
|
2011-04-08 20:55:10 +04:00
|
|
|
std::cerr << "Can't open '" << qPrintable(m_scriptFile) << "'" << std::endl << std::endl;
|
2010-12-28 02:26:08 +03:00
|
|
|
exit(1);
|
2011-02-14 07:41:59 +03:00
|
|
|
return false;
|
2010-12-27 07:04:53 +03:00
|
|
|
}
|
2011-03-25 01:43:49 +03:00
|
|
|
m_script = QString::fromUtf8(file.readAll());
|
2010-12-27 07:04:53 +03:00
|
|
|
file.close();
|
2011-02-13 22:38:09 +03:00
|
|
|
|
2011-02-06 15:53:30 +03:00
|
|
|
if (m_script.startsWith("#!")) {
|
|
|
|
m_script.prepend("//");
|
|
|
|
}
|
2010-12-27 07:04:53 +03:00
|
|
|
|
2011-03-02 11:41:23 +03:00
|
|
|
if (m_scriptFile.endsWith(".coffee")) {
|
|
|
|
if (!m_converter)
|
|
|
|
m_converter = new CSConverter(this);
|
|
|
|
m_script = m_converter->convert(m_script);
|
|
|
|
}
|
|
|
|
|
2011-05-26 01:00:20 +04:00
|
|
|
m_page->mainFrame()->evaluateJavaScript(m_script);
|
2011-02-14 07:41:59 +03:00
|
|
|
return true;
|
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-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-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-05-28 09:36:34 +04:00
|
|
|
page->applySettings(m_defaultPageSettings);
|
2011-05-26 12:56:43 +04:00
|
|
|
page->setNetworkAccessManager(m_netAccessMan);
|
|
|
|
return page;
|
2011-04-08 17:30:50 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
void Phantom::exit(int code)
|
|
|
|
{
|
|
|
|
m_returnValue = code;
|
|
|
|
QTimer::singleShot(0, qApp, SLOT(quit()));
|
2010-12-27 07:04:53 +03:00
|
|
|
}
|