Merge pull request #82 from Roejames12/master

Exit program properly when we call phantom.exit
1.2
Ariya Hidayat 2011-06-19 23:19:44 -07:00
commit 7ba0d6964e
14 changed files with 237 additions and 47 deletions

View File

@ -74,3 +74,47 @@ window.WebPage = function() {
return page; return page;
} }
// override settimeout/setinterval with a try..catch
window._setTimeout = window.setTimeout;
window._setInterval = window.setInterval;
window.setTimeout = function(func, delay) {
var f = function() {
try {
typeof func === 'function' ? func() : eval(func);
} catch (err) {
if (err !== 'phantom.exit') {
throw err;
}
}
}
return window._setTimeout(f, delay);
}
window.setInterval = function(func, delay, lang) {
var f = function() {
try {
typeof func === 'function' ? func() : eval(func);
} catch (err) {
if (err !== 'phantom.exit') {
throw err;
}
}
}
return window._setInterval(f, delay, lang);
}
phantom.exit = function(code) {
if (code == null) {
code = 0;
}
phantom._exit(code);
// halt javascript execution
throw "phantom.exit";
}

View File

@ -19,7 +19,7 @@
import sys import sys
from PyQt4.QtCore import QObject, QFile, qWarning from PyQt4.QtCore import QObject, QFile
from PyQt4.QtWebKit import QWebPage from PyQt4.QtWebKit import QWebPage
@ -43,8 +43,6 @@ class CSConverter(QObject):
[true, this.CoffeeScript.compile(converter.source)]; [true, this.CoffeeScript.compile(converter.source)];
} catch (error) { } catch (error) {
[false, error.message]; [false, error.message];
}''') }
if result[0] is False: ''')
qWarning(result[1]) return result
return ''
return result[1]

View File

@ -82,11 +82,13 @@ class Phantom(QObject):
do_action('PhantomInitPost', Bunch(locals())) do_action('PhantomInitPost', Bunch(locals()))
def execute(self): def execute(self):
injectJsInFrame(self.m_scriptFile, os.path.dirname(os.path.abspath(__file__)), self.m_page.mainFrame()) injectJsInFrame(self.m_scriptFile, os.path.dirname(os.path.abspath(__file__)), self.m_page.mainFrame(), True)
return not self.m_terminated return not self.m_terminated
def printConsoleMessage(self, msg): def printConsoleMessage(self, message, lineNumber, source):
print msg if source:
message = '%s:%d %s' % (source, lineNumber, message)
print message
def returnValue(self): def returnValue(self):
return self.m_returnValue return self.m_returnValue
@ -95,6 +97,12 @@ class Phantom(QObject):
# Properties and methods exposed to JavaScript # Properties and methods exposed to JavaScript
## ##
@pyqtSlot(int)
def _exit(self, code):
self.m_terminated = True
self.m_returnValue = code
QApplication.instance().exit(code)
@pyqtProperty('QStringList') @pyqtProperty('QStringList')
def args(self): def args(self):
return self.m_args return self.m_args
@ -111,13 +119,6 @@ class Phantom(QObject):
def defaultPageSettings(self): def defaultPageSettings(self):
return self.m_defaultPageSettings return self.m_defaultPageSettings
@pyqtSlot()
@pyqtSlot(int)
def exit(self, code=0):
self.m_terminated = True
self.m_returnValue = code
QApplication.instance().exit(code)
@pyqtSlot(str, result=bool) @pyqtSlot(str, result=bool)
def injectJs(self, filePath): def injectJs(self, filePath):
return injectJsInFrame(filePath, self.libraryPath, self.m_page.mainFrame()) return injectJsInFrame(filePath, self.libraryPath, self.m_page.mainFrame())

View File

@ -95,7 +95,7 @@ def main():
app.setOrganizationDomain('www.umaclan.com') app.setOrganizationDomain('www.umaclan.com')
app.setApplicationVersion(version) app.setApplicationVersion(version)
phantom = Phantom(args, app) phantom = Phantom(args)
do_action('Main', Bunch(locals())) do_action('Main', Bunch(locals()))

View File

@ -2,7 +2,7 @@
# Resource object code # Resource object code
# #
# Created: Fri Jun 17 01:01:41 2011 # Created: Sun Jun 19 21:18:36 2011
# by: The Resource Compiler for PyQt (Qt v4.7.2) # by: The Resource Compiler for PyQt (Qt v4.7.2)
# #
# WARNING! All changes made in this file will be lost! # WARNING! All changes made in this file will be lost!
@ -10,7 +10,7 @@
from PyQt4 import QtCore from PyQt4 import QtCore
qt_resource_data = "\ qt_resource_data = "\
\x00\x00\x0a\x29\ \x00\x00\x0d\xdb\
\x2f\ \x2f\
\x2f\x20\x54\x68\x69\x73\x20\x61\x6c\x6c\x6f\x77\x73\x20\x63\x72\ \x2f\x20\x54\x68\x69\x73\x20\x61\x6c\x6c\x6f\x77\x73\x20\x63\x72\
\x65\x61\x74\x69\x6e\x67\x20\x61\x20\x6e\x65\x77\x20\x77\x65\x62\ \x65\x61\x74\x69\x6e\x67\x20\x61\x20\x6e\x65\x77\x20\x77\x65\x62\
@ -174,7 +174,66 @@ qt_resource_data = "\
\x65\x6e\x64\x53\x63\x72\x69\x70\x74\x45\x6c\x65\x6d\x65\x6e\x74\ \x65\x6e\x64\x53\x63\x72\x69\x70\x74\x45\x6c\x65\x6d\x65\x6e\x74\
\x28\x73\x63\x72\x69\x70\x74\x55\x72\x6c\x29\x3b\x0a\x20\x20\x20\ \x28\x73\x63\x72\x69\x70\x74\x55\x72\x6c\x29\x3b\x0a\x20\x20\x20\
\x20\x7d\x3b\x0a\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\ \x20\x7d\x3b\x0a\x0a\x20\x20\x20\x20\x72\x65\x74\x75\x72\x6e\x20\
\x70\x61\x67\x65\x3b\x0a\x7d\x0a\ \x70\x61\x67\x65\x3b\x0a\x7d\x0a\x0a\x0a\x2f\x2f\x20\x6f\x76\x65\
\x72\x72\x69\x64\x65\x20\x73\x65\x74\x74\x69\x6d\x65\x6f\x75\x74\
\x2f\x73\x65\x74\x69\x6e\x74\x65\x72\x76\x61\x6c\x20\x77\x69\x74\
\x68\x20\x61\x20\x74\x72\x79\x2e\x2e\x63\x61\x74\x63\x68\x0a\x77\
\x69\x6e\x64\x6f\x77\x2e\x5f\x73\x65\x74\x54\x69\x6d\x65\x6f\x75\
\x74\x20\x3d\x20\x77\x69\x6e\x64\x6f\x77\x2e\x73\x65\x74\x54\x69\
\x6d\x65\x6f\x75\x74\x3b\x0a\x77\x69\x6e\x64\x6f\x77\x2e\x5f\x73\
\x65\x74\x49\x6e\x74\x65\x72\x76\x61\x6c\x20\x3d\x20\x77\x69\x6e\
\x64\x6f\x77\x2e\x73\x65\x74\x49\x6e\x74\x65\x72\x76\x61\x6c\x3b\
\x0a\x77\x69\x6e\x64\x6f\x77\x2e\x73\x65\x74\x54\x69\x6d\x65\x6f\
\x75\x74\x20\x3d\x20\x66\x75\x6e\x63\x74\x69\x6f\x6e\x28\x66\x75\
\x6e\x63\x2c\x20\x64\x65\x6c\x61\x79\x29\x20\x7b\x0a\x20\x20\x20\
\x20\x76\x61\x72\x20\x66\x20\x3d\x20\x66\x75\x6e\x63\x74\x69\x6f\
\x6e\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x74\x72\
\x79\x20\x7b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
\x74\x79\x70\x65\x6f\x66\x20\x66\x75\x6e\x63\x20\x3d\x3d\x3d\x20\
\x27\x66\x75\x6e\x63\x74\x69\x6f\x6e\x27\x20\x3f\x20\x66\x75\x6e\
\x63\x28\x29\x20\x3a\x20\x65\x76\x61\x6c\x28\x66\x75\x6e\x63\x29\
\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x7d\x20\x63\x61\x74\x63\
\x68\x20\x28\x65\x72\x72\x29\x20\x7b\x0a\x20\x20\x20\x20\x20\x20\
\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x65\x72\x72\x20\x21\x3d\
\x3d\x20\x27\x70\x68\x61\x6e\x74\x6f\x6d\x2e\x65\x78\x69\x74\x27\
\x29\x20\x7b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
\x20\x20\x20\x20\x74\x68\x72\x6f\x77\x20\x65\x72\x72\x3b\x0a\x20\
\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x7d\x0a\x20\x20\x20\
\x20\x20\x20\x20\x20\x7d\x0a\x20\x20\x20\x20\x7d\x0a\x0a\x20\x20\
\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x77\x69\x6e\x64\x6f\x77\x2e\
\x5f\x73\x65\x74\x54\x69\x6d\x65\x6f\x75\x74\x28\x66\x2c\x20\x64\
\x65\x6c\x61\x79\x29\x3b\x0a\x7d\x0a\x0a\x77\x69\x6e\x64\x6f\x77\
\x2e\x73\x65\x74\x49\x6e\x74\x65\x72\x76\x61\x6c\x20\x3d\x20\x66\
\x75\x6e\x63\x74\x69\x6f\x6e\x28\x66\x75\x6e\x63\x2c\x20\x64\x65\
\x6c\x61\x79\x2c\x20\x6c\x61\x6e\x67\x29\x20\x7b\x0a\x20\x20\x20\
\x20\x76\x61\x72\x20\x66\x20\x3d\x20\x66\x75\x6e\x63\x74\x69\x6f\
\x6e\x28\x29\x20\x7b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x74\x72\
\x79\x20\x7b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
\x74\x79\x70\x65\x6f\x66\x20\x66\x75\x6e\x63\x20\x3d\x3d\x3d\x20\
\x27\x66\x75\x6e\x63\x74\x69\x6f\x6e\x27\x20\x3f\x20\x66\x75\x6e\
\x63\x28\x29\x20\x3a\x20\x65\x76\x61\x6c\x28\x66\x75\x6e\x63\x29\
\x3b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x7d\x20\x63\x61\x74\x63\
\x68\x20\x28\x65\x72\x72\x29\x20\x7b\x0a\x20\x20\x20\x20\x20\x20\
\x20\x20\x20\x20\x20\x20\x69\x66\x20\x28\x65\x72\x72\x20\x21\x3d\
\x3d\x20\x27\x70\x68\x61\x6e\x74\x6f\x6d\x2e\x65\x78\x69\x74\x27\
\x29\x20\x7b\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\
\x20\x20\x20\x20\x74\x68\x72\x6f\x77\x20\x65\x72\x72\x3b\x0a\x20\
\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x7d\x0a\x20\x20\x20\
\x20\x20\x20\x20\x20\x7d\x0a\x20\x20\x20\x20\x7d\x0a\x0a\x20\x20\
\x20\x20\x72\x65\x74\x75\x72\x6e\x20\x77\x69\x6e\x64\x6f\x77\x2e\
\x5f\x73\x65\x74\x49\x6e\x74\x65\x72\x76\x61\x6c\x28\x66\x2c\x20\
\x64\x65\x6c\x61\x79\x2c\x20\x6c\x61\x6e\x67\x29\x3b\x0a\x7d\x0a\
\x0a\x0a\x70\x68\x61\x6e\x74\x6f\x6d\x2e\x65\x78\x69\x74\x20\x3d\
\x20\x66\x75\x6e\x63\x74\x69\x6f\x6e\x28\x63\x6f\x64\x65\x29\x20\
\x7b\x0a\x20\x20\x20\x20\x69\x66\x20\x28\x63\x6f\x64\x65\x20\x3d\
\x3d\x20\x6e\x75\x6c\x6c\x29\x20\x7b\x0a\x20\x20\x20\x20\x20\x20\
\x20\x20\x63\x6f\x64\x65\x20\x3d\x20\x30\x3b\x0a\x20\x20\x20\x20\
\x7d\x0a\x0a\x20\x20\x20\x20\x70\x68\x61\x6e\x74\x6f\x6d\x2e\x5f\
\x65\x78\x69\x74\x28\x63\x6f\x64\x65\x29\x3b\x0a\x0a\x20\x20\x20\
\x20\x2f\x2f\x20\x68\x61\x6c\x74\x20\x6a\x61\x76\x61\x73\x63\x72\
\x69\x70\x74\x20\x65\x78\x65\x63\x75\x74\x69\x6f\x6e\x0a\x20\x20\
\x20\x20\x74\x68\x72\x6f\x77\x20\x22\x70\x68\x61\x6e\x74\x6f\x6d\
\x2e\x65\x78\x69\x74\x22\x3b\x0a\x7d\x0a\
\x00\x00\x56\x27\ \x00\x00\x56\x27\
\x89\ \x89\
\x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\ \x50\x4e\x47\x0d\x0a\x1a\x0a\x00\x00\x00\x0d\x49\x48\x44\x52\x00\
@ -4317,8 +4376,8 @@ qt_resource_struct = "\
\x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x01\ \x00\x00\x00\x00\x00\x02\x00\x00\x00\x02\x00\x00\x00\x01\
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\ \x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\
\x00\x00\x00\x1e\x00\x02\x00\x00\x00\x02\x00\x00\x00\x03\ \x00\x00\x00\x1e\x00\x02\x00\x00\x00\x02\x00\x00\x00\x03\
\x00\x00\x00\x64\x00\x01\x00\x00\x00\x01\x00\x00\x60\x58\ \x00\x00\x00\x64\x00\x01\x00\x00\x00\x01\x00\x00\x64\x0a\
\x00\x00\x00\x36\x00\x00\x00\x00\x00\x01\x00\x00\x0a\x2d\ \x00\x00\x00\x36\x00\x00\x00\x00\x00\x01\x00\x00\x0d\xdf\
" "
def qInitResources(): def qInitResources():

View File

@ -106,7 +106,7 @@ def coffee2js(script):
return coffeeScriptConverter.convert(script) return coffeeScriptConverter.convert(script)
def injectJsInFrame(filePath, libraryPath, targetFrame): def injectJsInFrame(filePath, libraryPath, targetFrame, startingScript=False):
try: try:
# if file doesn't exist in the CWD, use the lookup # if file doesn't exist in the CWD, use the lookup
if not os.path.exists(filePath): if not os.path.exists(filePath):
@ -118,7 +118,28 @@ def injectJsInFrame(filePath, libraryPath, targetFrame):
if script.startswith('#!') and not filePath.lower().endswith('.coffee'): if script.startswith('#!') and not filePath.lower().endswith('.coffee'):
script = '//' + script script = '//' + script
targetFrame.evaluateJavaScript(script if not filePath.lower().endswith('.coffee') else coffee2js(script)) if filePath.lower().endswith('.coffee'):
result = coffee2js(script)
if result[0] is False:
if startingScript:
sys.exit(result[1])
else:
qWarning(result[1])
script = ''
else:
script = result[1]
# prepare start script for exiting
if startingScript:
script = '''try { %s } catch (err) {
if (err !== 'phantom.exit') {
phantom._exit(1);
throw err;
}
}
''' % script
targetFrame.evaluateJavaScript(script)
return True return True
except IOError: except IOError:
qWarning('No such file or directory: \'%s\'' % filePath) qWarning('No such file or directory: \'%s\'' % filePath)
@ -149,7 +170,7 @@ class SafeStreamFilter(object):
self.target = target self.target = target
self.encoding = 'utf-8' self.encoding = 'utf-8'
self.errors = 'replace' self.errors = 'replace'
self.encode_to = self.target.encoding self.encode_to = self.target.encoding or 'utf-8'
def write(self, s): def write(self, s):
s = self.encode(s) s = self.encode(s)

View File

@ -58,9 +58,7 @@ class CustomPage(QWebPage):
self.parent.javaScriptAlertSent.emit(msg) self.parent.javaScriptAlertSent.emit(msg)
def javaScriptConsoleMessage(self, message, lineNumber, sourceID): def javaScriptConsoleMessage(self, message, lineNumber, sourceID):
if sourceID: self.parent.javaScriptConsoleMessageSent.emit(message, lineNumber, sourceID)
message = '%s:%d %s' % (sourceID, lineNumber, message)
self.parent.javaScriptConsoleMessageSent.emit(message)
def userAgentForUrl(self, url): def userAgentForUrl(self, url):
return self.m_userAgent return self.m_userAgent
@ -70,7 +68,7 @@ class CustomPage(QWebPage):
class WebPage(QObject): class WebPage(QObject):
javaScriptAlertSent = pyqtSignal(str) javaScriptAlertSent = pyqtSignal(str)
javaScriptConsoleMessageSent = pyqtSignal(str) javaScriptConsoleMessageSent = pyqtSignal(str, int, str)
loadStarted = pyqtSignal() loadStarted = pyqtSignal()
loadFinished = pyqtSignal(str) loadFinished = pyqtSignal(str)
resourceReceived = pyqtSignal('QVariantMap') resourceReceived = pyqtSignal('QVariantMap')

View File

@ -74,3 +74,47 @@ window.WebPage = function() {
return page; return page;
} }
// override settimeout/setinterval with a try..catch
window._setTimeout = window.setTimeout;
window._setInterval = window.setInterval;
window.setTimeout = function(func, delay) {
var f = function() {
try {
typeof func === 'function' ? func() : eval(func);
} catch (err) {
if (err !== 'phantom.exit') {
throw err;
}
}
}
return window._setTimeout(f, delay);
}
window.setInterval = function(func, delay, lang) {
var f = function() {
try {
typeof func === 'function' ? func() : eval(func);
} catch (err) {
if (err !== 'phantom.exit') {
throw err;
}
}
}
return window._setInterval(f, delay, lang);
}
phantom.exit = function(code) {
if (code == null) {
code = 0;
}
phantom._exit(code);
// halt javascript execution
throw "phantom.exit";
}

View File

@ -49,7 +49,7 @@ CSConverter::CSConverter(QObject *parent)
m_webPage.mainFrame()->addToJavaScriptWindowObject("converter", this); m_webPage.mainFrame()->addToJavaScriptWindowObject("converter", this);
} }
QString CSConverter::convert(const QString &script) QVariant CSConverter::convert(const QString &script)
{ {
setProperty("source", script); setProperty("source", script);
QVariant result = m_webPage.mainFrame()->evaluateJavaScript("try {" \ QVariant result = m_webPage.mainFrame()->evaluateJavaScript("try {" \
@ -57,9 +57,5 @@ QString CSConverter::convert(const QString &script)
"} catch (error) {" \ "} catch (error) {" \
" [false, error.message];" \ " [false, error.message];" \
"}"); "}");
if (result.toStringList().at(0) == "false") { return result;
qWarning(qPrintable(result.toStringList().at(1)));
return QString();
}
return result.toStringList().at(1);
} }

View File

@ -37,7 +37,7 @@ class CSConverter: public QObject
{ {
public: public:
CSConverter(QObject *parent = 0); CSConverter(QObject *parent = 0);
QString convert(const QString &script); QVariant convert(const QString &script);
private: private:
QWebPage m_webPage; QWebPage m_webPage;

View File

@ -195,7 +195,7 @@ bool Phantom::execute()
if (m_scriptFile.isEmpty()) if (m_scriptFile.isEmpty())
return false; return false;
if (!Utils::injectJsInFrame(m_scriptFile, QDir::currentPath(), m_page->mainFrame())) { if (!Utils::injectJsInFrame(m_scriptFile, QDir::currentPath(), m_page->mainFrame(), true)) {
m_returnValue = -1; m_returnValue = -1;
return false; return false;
} }
@ -226,7 +226,7 @@ QObject *Phantom::createWebPage()
return page; return page;
} }
void Phantom::exit(int code) void Phantom::_exit(int code)
{ {
m_terminated = true; m_terminated = true;
m_returnValue = code; m_returnValue = code;

View File

@ -66,7 +66,7 @@ public:
public slots: public slots:
QObject *createWebPage(); QObject *createWebPage();
bool injectJs(const QString &jsFilePath); bool injectJs(const QString &jsFilePath);
void exit(int code = 0); void _exit(int code);
private slots: private slots:
void printConsoleMessage(const QString &msg, int lineNumber, const QString &source); void printConsoleMessage(const QString &msg, int lineNumber, const QString &source);

View File

@ -69,7 +69,7 @@ void Utils::messageHandler(QtMsgType type, const char *msg)
} }
} }
QString Utils::coffee2js(const QString &script) QVariant Utils::coffee2js(const QString &script)
{ {
// We need only one instance of the CSConverter to survive for the whole life of PhantomJS // We need only one instance of the CSConverter to survive for the whole life of PhantomJS
static CSConverter *coffeeScriptConverter = NULL; static CSConverter *coffeeScriptConverter = NULL;
@ -80,7 +80,7 @@ QString Utils::coffee2js(const QString &script)
return coffeeScriptConverter->convert(script); return coffeeScriptConverter->convert(script);
} }
bool Utils::injectJsInFrame(const QString &jsFilePath, const QString &libraryPath, QWebFrame *targetFrame) bool Utils::injectJsInFrame(const QString &jsFilePath, const QString &libraryPath, QWebFrame *targetFrame, const bool startingScript)
{ {
// Don't do anything if an empty string is passed // Don't do anything if an empty string is passed
if (!jsFilePath.isEmpty()) { if (!jsFilePath.isEmpty()) {
@ -100,14 +100,43 @@ bool Utils::injectJsInFrame(const QString &jsFilePath, const QString &libraryPat
scriptBody.prepend("//"); scriptBody.prepend("//");
} }
if (jsFile.fileName().endsWith(COFFEE_SCRIPT_EXTENSION)) {
QVariant result = Utils::coffee2js(scriptBody);
if (result.toStringList().at(0) == "false") {
if (startingScript) {
std::cerr << qPrintable(result.toStringList().at(1)) << std::endl;
exit(1);
} else {
qWarning() << qPrintable(result.toStringList().at(1));
scriptBody = QString();
}
} else {
scriptBody = result.toStringList().at(1);
}
}
// prepare start script for exiting
if (startingScript) {
scriptBody = QString("try {" \
" %1" \
"} catch (err) {" \
" if (err !== 'phantom.exit') {" \
" phantom._exit(1);" \
" throw err;" \
" }" \
"}").arg(scriptBody);
}
// Execute JS code in the context of the document // Execute JS code in the context of the document
targetFrame->evaluateJavaScript(jsFile.fileName().endsWith(COFFEE_SCRIPT_EXTENSION) ? targetFrame->evaluateJavaScript(scriptBody);
Utils::coffee2js(scriptBody) : //< convert from Coffee Script
scriptBody);
jsFile.close(); jsFile.close();
return true; return true;
} else { } else {
qWarning() << "Can't open '" << qPrintable(jsFilePath) << "'"; if (startingScript) {
std::cerr << "Can't open '" << qPrintable(jsFilePath) << "'" << std::endl;
} else {
qWarning("Can't open '%s'", qPrintable(jsFilePath));
}
} }
} }
return false; return false;

View File

@ -45,8 +45,8 @@ class Utils
public: public:
static void showUsage(); static void showUsage();
static void messageHandler(QtMsgType type, const char *msg); static void messageHandler(QtMsgType type, const char *msg);
static QString coffee2js(const QString &script); static QVariant coffee2js(const QString &script);
static bool injectJsInFrame(const QString &jsFilePath, const QString &libraryPath, QWebFrame *targetFrame); static bool injectJsInFrame(const QString &jsFilePath, const QString &libraryPath, QWebFrame *targetFrame, const bool startingScript = false);
private: private:
Utils(); //< This class shouldn't be instantiated Utils(); //< This class shouldn't be instantiated