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-04-08 17:30:50 +04:00
|
|
|
#include <QFile>
|
|
|
|
#include <QDebug>
|
2011-04-08 20:55:10 +04:00
|
|
|
#include <QDateTime>
|
2011-06-10 19:50:49 +04:00
|
|
|
#include <QDir>
|
2011-10-25 23:16:25 +04:00
|
|
|
#include <QTemporaryFile>
|
2011-04-08 17:30:50 +04:00
|
|
|
|
2011-06-10 19:50:49 +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-10-25 23:16:25 +04:00
|
|
|
QTemporaryFile* Utils::m_tempHarness = 0;
|
|
|
|
QTemporaryFile* Utils::m_tempWrapper = 0;
|
2012-06-05 15:43:23 +04:00
|
|
|
bool Utils::printDebugMessages = false;
|
2011-10-25 23:16:25 +04:00
|
|
|
|
2011-04-08 18:49:20 +04:00
|
|
|
void Utils::messageHandler(QtMsgType type, const char *msg)
|
|
|
|
{
|
2011-04-08 20:55:10 +04:00
|
|
|
QDateTime now = QDateTime::currentDateTime();
|
|
|
|
|
2011-04-08 18:49:20 +04:00
|
|
|
switch (type) {
|
|
|
|
case QtDebugMsg:
|
2012-06-05 15:43:23 +04:00
|
|
|
if (printDebugMessages) {
|
|
|
|
fprintf(stderr, "%s [DEBUG] %s\n", qPrintable(now.toString(Qt::ISODate)), msg);
|
|
|
|
}
|
2011-04-08 18:49:20 +04:00
|
|
|
break;
|
|
|
|
case QtWarningMsg:
|
2012-06-05 15:43:23 +04:00
|
|
|
if (printDebugMessages) {
|
|
|
|
fprintf(stderr, "%s [WARNING] %s\n", qPrintable(now.toString(Qt::ISODate)), msg);
|
|
|
|
}
|
2011-04-08 18:49:20 +04:00
|
|
|
break;
|
|
|
|
case QtCriticalMsg:
|
2011-04-08 20:55:10 +04:00
|
|
|
fprintf(stderr, "%s [CRITICAL] %s\n", qPrintable(now.toString(Qt::ISODate)), msg);
|
2011-04-08 18:49:20 +04:00
|
|
|
break;
|
|
|
|
case QtFatalMsg:
|
2011-04-08 20:55:10 +04:00
|
|
|
fprintf(stderr, "%s [FATAL] %s\n", qPrintable(now.toString(Qt::ISODate)), msg);
|
2011-04-08 18:49:20 +04:00
|
|
|
abort();
|
|
|
|
}
|
|
|
|
}
|
2012-08-19 11:16:59 +04:00
|
|
|
#ifdef Q_OS_WIN32
|
|
|
|
bool Utils::exceptionHandler(const TCHAR* dump_path, const TCHAR* minidump_id,
|
|
|
|
void* context, EXCEPTION_POINTERS* exinfo,
|
|
|
|
MDRawAssertionInfo *assertion, bool succeeded)
|
|
|
|
{
|
|
|
|
Q_UNUSED(exinfo);
|
|
|
|
Q_UNUSED(assertion);
|
|
|
|
Q_UNUSED(context);
|
|
|
|
|
|
|
|
fprintf(stderr, "PhantomJS has crashed. Please read the crash reporting guide at " \
|
2012-09-28 19:03:25 +04:00
|
|
|
"https://github.com/ariya/phantomjs/wiki/Crash-Reporting and file a " \
|
2012-08-19 11:16:59 +04:00
|
|
|
"bug report at https://code.google.com/p/phantomjs/issues/entry with the " \
|
|
|
|
"crash dump file attached: %ls\\%ls.dmp\n",
|
|
|
|
dump_path, minidump_id);
|
|
|
|
return succeeded;
|
|
|
|
}
|
|
|
|
#else
|
2012-06-05 23:22:12 +04:00
|
|
|
bool Utils::exceptionHandler(const char* dump_path, const char* minidump_id, void* context, bool succeeded)
|
|
|
|
{
|
2012-05-30 15:28:20 +04:00
|
|
|
Q_UNUSED(context);
|
2012-08-04 18:08:37 +04:00
|
|
|
fprintf(stderr, "PhantomJS has crashed. Please read the crash reporting guide at " \
|
2012-09-28 19:03:25 +04:00
|
|
|
"https://github.com/ariya/phantomjs/wiki/Crash-Reporting and file a " \
|
2012-08-04 18:08:37 +04:00
|
|
|
"bug report at https://code.google.com/p/phantomjs/issues/entry with the " \
|
|
|
|
"crash dump file attached: %s/%s.dmp\n",
|
2012-06-05 23:22:12 +04:00
|
|
|
dump_path, minidump_id);
|
|
|
|
return succeeded;
|
|
|
|
}
|
2012-08-19 11:16:59 +04:00
|
|
|
#endif
|
2012-06-05 23:22:12 +04:00
|
|
|
|
2011-06-20 00:37:03 +04:00
|
|
|
QVariant Utils::coffee2js(const QString &script)
|
2011-06-10 19:50:49 +04:00
|
|
|
{
|
2011-08-21 11:11:11 +04:00
|
|
|
return CSConverter::instance()->convert(script);
|
2011-06-10 19:50:49 +04:00
|
|
|
}
|
|
|
|
|
2011-06-19 12:18:26 +04:00
|
|
|
bool Utils::injectJsInFrame(const QString &jsFilePath, const QString &libraryPath, QWebFrame *targetFrame, const bool startingScript)
|
2011-08-16 22:53:56 +04:00
|
|
|
{
|
|
|
|
return injectJsInFrame(jsFilePath, Encoding::UTF8, libraryPath, targetFrame, startingScript);
|
|
|
|
}
|
|
|
|
|
|
|
|
bool Utils::injectJsInFrame(const QString &jsFilePath, const Encoding &jsFileEnc, const QString &libraryPath, QWebFrame *targetFrame, const bool startingScript)
|
2011-06-10 19:50:49 +04:00
|
|
|
{
|
|
|
|
// Don't do anything if an empty string is passed
|
2011-10-25 23:16:25 +04:00
|
|
|
QString scriptPath = findScript(jsFilePath, libraryPath);
|
|
|
|
QString scriptBody = jsFromScriptFile(scriptPath, jsFileEnc);
|
|
|
|
if (scriptBody.isEmpty())
|
|
|
|
{
|
|
|
|
if (startingScript) {
|
|
|
|
Terminal::instance()->cerr(QString("Can't open '%1'").arg(jsFilePath));
|
|
|
|
} else {
|
|
|
|
qWarning("Can't open '%s'", qPrintable(jsFilePath));
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// Execute JS code in the context of the document
|
2012-03-17 21:27:13 +04:00
|
|
|
targetFrame->evaluateJavaScript(scriptBody, jsFilePath);
|
2011-10-25 23:16:25 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2012-02-27 01:15:44 +04:00
|
|
|
bool Utils::loadJSForDebug(const QString& jsFilePath, const QString& libraryPath, QWebFrame* targetFrame, const bool autorun)
|
2011-10-25 23:16:25 +04:00
|
|
|
{
|
2012-02-27 01:15:44 +04:00
|
|
|
return loadJSForDebug(jsFilePath, Encoding::UTF8, libraryPath, targetFrame, autorun);
|
2011-10-25 23:16:25 +04:00
|
|
|
}
|
|
|
|
|
2012-02-27 01:15:44 +04:00
|
|
|
bool Utils::loadJSForDebug(const QString& jsFilePath, const Encoding& jsFileEnc, const QString& libraryPath, QWebFrame* targetFrame, const bool autorun)
|
2011-10-25 23:16:25 +04:00
|
|
|
{
|
|
|
|
QString scriptPath = findScript(jsFilePath, libraryPath);
|
|
|
|
QString scriptBody = jsFromScriptFile(scriptPath, jsFileEnc);
|
|
|
|
|
2012-01-04 21:24:36 +04:00
|
|
|
QString remoteDebuggerHarnessSrc = Utils::readResourceFileUtf8(":/remote_debugger_harness.html");
|
|
|
|
remoteDebuggerHarnessSrc = remoteDebuggerHarnessSrc.arg(scriptBody);
|
|
|
|
targetFrame->setHtml(remoteDebuggerHarnessSrc);
|
2012-02-27 01:15:44 +04:00
|
|
|
|
|
|
|
if (autorun) {
|
2012-03-17 21:27:13 +04:00
|
|
|
targetFrame->evaluateJavaScript("__run()", QString());
|
2012-02-27 01:15:44 +04:00
|
|
|
}
|
|
|
|
|
2011-10-25 23:16:25 +04:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
QString Utils::findScript(const QString& jsFilePath, const QString &libraryPath)
|
|
|
|
{
|
|
|
|
QString filePath = jsFilePath;
|
2011-06-10 19:50:49 +04:00
|
|
|
if (!jsFilePath.isEmpty()) {
|
|
|
|
QFile jsFile;
|
|
|
|
|
|
|
|
// Is file in the PWD?
|
|
|
|
jsFile.setFileName(QDir::fromNativeSeparators(jsFilePath)); //< Normalise User-provided path
|
|
|
|
if (!jsFile.exists()) {
|
|
|
|
// File is not in the PWD. Is it in the lookup directory?
|
2011-11-16 04:11:42 +04:00
|
|
|
jsFile.setFileName(libraryPath + '/' + QDir::fromNativeSeparators(jsFilePath));
|
2011-06-10 19:50:49 +04:00
|
|
|
}
|
|
|
|
|
2011-10-25 23:16:25 +04:00
|
|
|
return jsFile.fileName();
|
|
|
|
}
|
|
|
|
return QString();
|
|
|
|
}
|
2011-06-10 19:50:49 +04:00
|
|
|
|
2011-10-25 23:16:25 +04:00
|
|
|
QString Utils::jsFromScriptFile(const QString& scriptPath, const Encoding& enc)
|
|
|
|
{
|
|
|
|
QFile jsFile(scriptPath);
|
|
|
|
if (jsFile.exists() && jsFile.open(QFile::ReadOnly)) {
|
|
|
|
QString scriptBody = enc.decode(jsFile.readAll());
|
|
|
|
// Remove CLI script heading
|
|
|
|
if (scriptBody.startsWith("#!") && !jsFile.fileName().endsWith(COFFEE_SCRIPT_EXTENSION)) {
|
|
|
|
scriptBody.prepend("//");
|
|
|
|
}
|
2011-06-19 12:18:26 +04:00
|
|
|
|
2011-10-25 23:16:25 +04:00
|
|
|
if (jsFile.fileName().endsWith(COFFEE_SCRIPT_EXTENSION)) {
|
|
|
|
QVariant result = Utils::coffee2js(scriptBody);
|
|
|
|
if (result.toStringList().at(0) == "false") {
|
|
|
|
return QString();
|
2011-06-20 01:00:04 +04:00
|
|
|
} else {
|
2011-10-25 23:16:25 +04:00
|
|
|
scriptBody = result.toStringList().at(1);
|
2011-06-20 01:00:04 +04:00
|
|
|
}
|
2011-06-10 19:50:49 +04:00
|
|
|
}
|
2011-10-25 23:16:25 +04:00
|
|
|
jsFile.close();
|
|
|
|
|
|
|
|
return scriptBody;
|
|
|
|
} else {
|
|
|
|
return QString();
|
2011-06-10 19:50:49 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-10-25 23:16:25 +04:00
|
|
|
|
|
|
|
void
|
|
|
|
Utils::cleanupFromDebug()
|
|
|
|
{
|
|
|
|
if (m_tempHarness) {
|
|
|
|
// Will erase the temp file on disk
|
|
|
|
delete m_tempHarness;
|
|
|
|
m_tempHarness = 0;
|
|
|
|
}
|
|
|
|
if (m_tempWrapper) {
|
|
|
|
delete m_tempWrapper;
|
|
|
|
m_tempWrapper = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2011-10-16 23:35:21 +04:00
|
|
|
QString Utils::readResourceFileUtf8(const QString &resourceFilePath)
|
|
|
|
{
|
|
|
|
QFile f(resourceFilePath);
|
|
|
|
f.open(QFile::ReadOnly); //< It's OK to assume this succeed. If it doesn't, we have a bigger problem.
|
|
|
|
return QString::fromUtf8(f.readAll());
|
|
|
|
}
|
|
|
|
|
2011-04-08 17:30:50 +04:00
|
|
|
// private:
|
|
|
|
Utils::Utils()
|
|
|
|
{
|
|
|
|
// Nothing to do here
|
|
|
|
}
|