From a85e29367a605b2b62ecbab6a1d9d92c5dc9f708 Mon Sep 17 00:00:00 2001 From: "Aaron J. Seigo" Date: Thu, 7 Jan 2010 02:04:59 +0000 Subject: [PATCH] isolate out the common QScriptEngine setup that is sharable between the various ScriptEngines; this will prevent having to reimplement (or more likely copy and paste) the extensions loading, print, debug, etc. from the applet implementation to get that support in dataengines and runners. svn path=/trunk/KDE/kdebase/runtime/; revision=1070936 --- scriptengines/javascript/CMakeLists.txt | 2 + .../javascript/appletauthorization.cpp | 45 +++ .../javascript/appletauthorization.h | 39 +++ scriptengines/javascript/authorization.h | 35 +++ scriptengines/javascript/scriptenv.cpp | 292 ++++++++++++++++++ scriptengines/javascript/scriptenv.h | 70 +++++ .../simplebindings/appletinterface.cpp | 13 +- .../simplebindings/appletinterface.h | 4 - .../javascript/simplejavascriptapplet.cpp | 262 +--------------- .../javascript/simplejavascriptapplet.h | 31 +- 10 files changed, 507 insertions(+), 286 deletions(-) create mode 100644 scriptengines/javascript/appletauthorization.cpp create mode 100644 scriptengines/javascript/appletauthorization.h create mode 100644 scriptengines/javascript/authorization.h create mode 100644 scriptengines/javascript/scriptenv.cpp create mode 100644 scriptengines/javascript/scriptenv.h diff --git a/scriptengines/javascript/CMakeLists.txt b/scriptengines/javascript/CMakeLists.txt index 454362691..249c24cf9 100644 --- a/scriptengines/javascript/CMakeLists.txt +++ b/scriptengines/javascript/CMakeLists.txt @@ -1,6 +1,8 @@ # APPLET set(simple_javascript_engine_SRCS + appletauthorization.cpp + scriptenv.cpp simplejavascriptapplet.cpp simplebindings/animationgroup.cpp simplebindings/appletinterface.cpp diff --git a/scriptengines/javascript/appletauthorization.cpp b/scriptengines/javascript/appletauthorization.cpp new file mode 100644 index 000000000..8499ec77c --- /dev/null +++ b/scriptengines/javascript/appletauthorization.cpp @@ -0,0 +1,45 @@ +/* + * Copyright 2010 Aaron J. Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "appletauthorization.h" +#include "simplejavascriptapplet.h" + +AppletAuthorization::AppletAuthorization(SimpleJavaScriptApplet *scriptEngine) + : Authorization(), + m_scriptEngine(scriptEngine) +{ +} + +bool AppletAuthorization::authorizeRequiredExtension(const QString &extension) +{ + bool ok = m_scriptEngine->applet()->hasAuthorization(extension); + + if (!ok) { + m_scriptEngine->setFailedToLaunch(true, + i18n("Authorization for required extension '%1' was denied.", + extension)); + } + + return ok; +} + +bool AppletAuthorization::authorizeOptionalExtension(const QString &extension) +{ + return m_scriptEngine->applet()->hasAuthorization(extension); +} + diff --git a/scriptengines/javascript/appletauthorization.h b/scriptengines/javascript/appletauthorization.h new file mode 100644 index 000000000..6501b53b7 --- /dev/null +++ b/scriptengines/javascript/appletauthorization.h @@ -0,0 +1,39 @@ +/* + * Copyright 2010 Aaron J. Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef APPLETAUTHORIZATION_H +#define APPLETAUTHORIZATION_H + +#include "authorization.h" + +class SimpleJavaScriptApplet; + +class AppletAuthorization : public Authorization +{ +public: + AppletAuthorization(SimpleJavaScriptApplet *scriptEngine); + + bool authorizeRequiredExtension(const QString &extension); + bool authorizeOptionalExtension(const QString &extension); + +private: + SimpleJavaScriptApplet *m_scriptEngine; +}; + +#endif + diff --git a/scriptengines/javascript/authorization.h b/scriptengines/javascript/authorization.h new file mode 100644 index 000000000..4df9766d1 --- /dev/null +++ b/scriptengines/javascript/authorization.h @@ -0,0 +1,35 @@ +/* + * Copyright 2010 Aaron J. Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef AUTHORIZATION_H +#define AUTHORIZATION_H + +#include + +class Authorization +{ +public: + Authorization() {} + virtual ~Authorization() {} + + virtual bool authorizeRequiredExtension(const QString &) { return true; } + virtual bool authorizeOptionalExtension(const QString &) { return true; } +}; + +#endif + diff --git a/scriptengines/javascript/scriptenv.cpp b/scriptengines/javascript/scriptenv.cpp new file mode 100644 index 000000000..f971e5fe6 --- /dev/null +++ b/scriptengines/javascript/scriptenv.cpp @@ -0,0 +1,292 @@ +/* + * Copyright 2007-2008 Richard J. Moore + * Copyright 2009 Aaron J. Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "scriptenv.h" + +#include + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "simplejavascriptapplet.h" +#include "simplebindings/filedialogproxy.h" + +ScriptEnv::ScriptEnv(QObject *parent) + : QScriptEngine(parent), + m_allowedUrls(NoUrls) +{ + QScriptValue global = globalObject(); + global.setProperty("print", newFunction(ScriptEnv::print)); + global.setProperty("debug", newFunction(ScriptEnv::print)); +} + +ScriptEnv::~ScriptEnv() +{ +} + +void ScriptEnv::registerEnums(QScriptValue &scriptValue, const QMetaObject &meta) +{ + //manually create enum values. ugh + for (int i = 0; i < meta.enumeratorCount(); ++i) { + QMetaEnum e = meta.enumerator(i); + //kDebug() << e.name(); + for (int i=0; i < e.keyCount(); ++i) { + //kDebug() << e.key(i) << e.value(i); + scriptValue.setProperty(e.key(i), QScriptValue(this, e.value(i))); + } + } +} + +bool ScriptEnv::include(const QString &path) +{ + QFile file(path); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + kWarning() << i18n("Unable to load script file: %1", path); + return false; + } + + QString script = file.readAll(); + //kDebug() << "Script says" << script; + + evaluate(script); + if (hasUncaughtException()) { + emit reportError(this, true); + return false; + } + + return true; +} + +QScriptValue ScriptEnv::runApplication(QScriptContext *context, QScriptEngine *engine) +{ + Q_UNUSED(engine) + if (context->argumentCount() == 0) { + return false; + } + + KUrl::List urls; + if (context->argumentCount() > 1) { + urls = qscriptvalue_cast(context->argument(1)); + } + + const QString app = context->argument(0).toString(); + + KService::Ptr service = KService::serviceByStorageId(app); + if (service) { + return KRun::run(*service, urls, 0); + } + + const QString exec = KGlobal::dirs()->findExe(app); + if (!exec.isEmpty()) { + return KRun::run(exec, urls, 0); + } + + return false; +} + +QScriptValue ScriptEnv::runCommand(QScriptContext *context, QScriptEngine *engine) +{ + Q_UNUSED(engine) + if (context->argumentCount() == 0) { + return false; + } + + const QString exec = KGlobal::dirs()->findExe(context->argument(0).toString()); + if (!exec.isEmpty()) { + QString args; + if (context->argumentCount() > 1) { + const QStringList argList = qscriptvalue_cast(context->argument(1)); + if (!argList.isEmpty()) { + args = ' ' + KShell::joinArgs(argList); + } + } + + return KRun::runCommand(exec + args, 0); + } + + return false; +} + +QScriptValue ScriptEnv::openUrl(QScriptContext *context, QScriptEngine *engine) +{ + Q_UNUSED(engine) + if (context->argumentCount() == 0) { + return false; + } + + QScriptValue v = context->argument(0); + KUrl url = v.isString() ? KUrl(v.toString()) : qscriptvalue_cast(v); + if (url.isValid()) { + return KRun::runUrl(url, KMimeType::findByUrl(url)->name(), 0); + } + + return false; +} + +QScriptValue ScriptEnv::getUrl(QScriptContext *context, QScriptEngine *engine) +{ + if (context->argumentCount() == 0) { + return engine->undefinedValue(); + } + + QScriptValue v = context->argument(0); + KUrl url = v.isString() ? KUrl(v.toString()) : qscriptvalue_cast(v); + + if (!url.isValid()) { + return engine->undefinedValue(); + } + + if (url.isLocalFile()) { + if (!(static_cast(engine)->m_allowedUrls & LocalUrls)) { + return engine->undefinedValue(); + } + } else if (!(static_cast(engine)->m_allowedUrls & NetworkUrls) && + !((static_cast(engine)->m_allowedUrls & HttpUrls) && (url.protocol() == "http" || url.protocol() == "https"))) { + return engine->undefinedValue(); + } + + KIO::Job *job = KIO::get(url); + return engine->newQObject(job); +} + +void ScriptEnv::registerGetUrl(QScriptValue &obj) +{ + QScriptValue get = obj.property("getUrl"); + if (!get.isValid()) { + obj.setProperty("getUrl", newFunction(ScriptEnv::getUrl)); + } +} + +bool ScriptEnv::importBuiltinExtension(const QString &extension, QScriptValue &obj) +{ + kDebug() << extension; + if ("filedialog" == extension) { + FileDialogProxy::registerWithRuntime(this); + return true; + } else if ("launchapp" == extension) { + obj.setProperty("runApplication", newFunction(ScriptEnv::runApplication)); + obj.setProperty("runCommand", newFunction(ScriptEnv::runCommand)); + obj.setProperty("openUrl", newFunction(ScriptEnv::openUrl)); + return true; + } else if ("http" == extension) { + m_allowedUrls |= HttpUrls; + registerGetUrl(obj); + return true; + } else if ("networkio" == extension) { + m_allowedUrls |= HttpUrls | NetworkUrls; + registerGetUrl(obj); + return true; + } else if ("localio" == extension) { + m_allowedUrls |= LocalUrls; + registerGetUrl(obj); + return true; + } + + return false; +} + +bool ScriptEnv::importExtensions(const KPluginInfo &info, QScriptValue &obj, Authorization &auth) +{ + QStringList requiredExtensions = info.service()->property("X-Plasma-RequiredExtensions", QVariant::StringList).toStringList(); + kDebug() << "required extensions are" << requiredExtensions; + foreach (const QString &ext, requiredExtensions) { + QString extension = ext.toLower(); + if (m_extensions.contains(extension)) { + continue; + } + + if (!auth.authorizeRequiredExtension(extension)) { + return false; + } + + if (!importBuiltinExtension(extension, obj)) { + importExtension(extension); + } + + if (hasUncaughtException()) { + emit reportError(this, true); + return false; + } else { + m_extensions << extension; + } + } + + QStringList optionalExtensions = info.service()->property("X-Plasma-OptionalExtensions", QVariant::StringList).toStringList(); + kDebug() << "optional extensions are" << optionalExtensions; + foreach (const QString &ext, optionalExtensions) { + QString extension = ext.toLower(); + + if (m_extensions.contains(extension)) { + continue; + } + + if (!auth.authorizeOptionalExtension(extension)) { + continue; + } + + if (!importBuiltinExtension(extension, obj)) { + importExtension(extension); + } + + if (hasUncaughtException()) { + emit reportError(this, false); + } else { + m_extensions << extension; + } + } + + return true; +} + +QSet ScriptEnv::loadedExtensions() const +{ + return m_extensions; +} + +QScriptValue ScriptEnv::debug(QScriptContext *context, QScriptEngine *engine) +{ + if (context->argumentCount() != 1) { + return context->throwError(i18n("debug takes one argument")); + } + + kDebug() << context->argument(0).toString(); + return engine->undefinedValue(); +} + +QScriptValue ScriptEnv::print(QScriptContext *context, QScriptEngine *engine) +{ + if (context->argumentCount() != 1) { + return context->throwError(i18n("print() takes one argument")); + } + + std::cout << context->argument(0).toString().toLocal8Bit().constData() << std::endl; + return engine->undefinedValue(); +} + +#include "scriptenv.moc" diff --git a/scriptengines/javascript/scriptenv.h b/scriptengines/javascript/scriptenv.h new file mode 100644 index 000000000..7d7233039 --- /dev/null +++ b/scriptengines/javascript/scriptenv.h @@ -0,0 +1,70 @@ +/* + * Copyright 2007-2008 Richard J. Moore + * Copyright 2009 Aaron J. Seigo + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License version 2 as + * published by the Free Software Foundation + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details + * + * You should have received a copy of the GNU Library General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef SCRIPTENV_H +#define SCRIPTENV_H + +#include +#include + +#include + +#include "authorization.h" + +class ScriptEnv : public QScriptEngine +{ + Q_OBJECT +public: + enum AllowedUrl { NoUrls = 0, + HttpUrls = 1, + NetworkUrls = 2, + LocalUrls = 4 }; + Q_DECLARE_FLAGS(AllowedUrls, AllowedUrl) + + ScriptEnv(QObject *parent); + ~ScriptEnv(); + + void registerEnums(QScriptValue &scriptValue, const QMetaObject &meta); + bool include(const QString &path); + + bool importExtensions(const KPluginInfo &info, QScriptValue &obj, Authorization &authorizer); + QSet loadedExtensions() const; + +Q_SIGNALS: + void reportError(ScriptEnv *engine, bool fatal); + +private: + void registerGetUrl(QScriptValue &obj); + bool importBuiltinExtension(const QString &extension, QScriptValue &obj); + + static QScriptValue debug(QScriptContext *context, QScriptEngine *engine); + static QScriptValue print(QScriptContext *context, QScriptEngine *engine); + static QScriptValue runApplication(QScriptContext *context, QScriptEngine *engine); + static QScriptValue runCommand(QScriptContext *context, QScriptEngine *engine); + static QScriptValue openUrl(QScriptContext *context, QScriptEngine *engine); + static QScriptValue getUrl(QScriptContext *context, QScriptEngine *engine); + + QSet m_extensions; + AllowedUrls m_allowedUrls; +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(ScriptEnv::AllowedUrls) + +#endif + diff --git a/scriptengines/javascript/simplebindings/appletinterface.cpp b/scriptengines/javascript/simplebindings/appletinterface.cpp index 0e98b6920..e09f6d4e5 100644 --- a/scriptengines/javascript/simplebindings/appletinterface.cpp +++ b/scriptengines/javascript/simplebindings/appletinterface.cpp @@ -38,8 +38,7 @@ AppletInterface::AppletInterface(SimpleJavaScriptApplet *parent) : QObject(parent), m_appletScriptEngine(parent), - m_actionSignals(0), - m_allowedUrls(SimpleJavaScriptApplet::NoUrls) + m_actionSignals(0) { connect(this, SIGNAL(releaseVisualFocus()), applet(), SIGNAL(releaseVisualFocus())); connect(this, SIGNAL(configNeedsSaving()), applet(), SIGNAL(configNeedsSaving())); @@ -319,16 +318,6 @@ int AppletInterface::apiVersion() const return offers.first()->property("X-KDE-PluginInfo-Version", QVariant::Int).toInt(); } -SimpleJavaScriptApplet::AllowedUrls AppletInterface::allowedUrls() const -{ - return m_allowedUrls; -} - -void AppletInterface::setAllowedUrls(const SimpleJavaScriptApplet::AllowedUrls &allowedUrls) -{ - m_allowedUrls = allowedUrls; -} - bool AppletInterface::include(const QString &script) { const QString path = package()->filePath("scripts", script); diff --git a/scriptengines/javascript/simplebindings/appletinterface.h b/scriptengines/javascript/simplebindings/appletinterface.h index 962ff879c..41f524f4b 100644 --- a/scriptengines/javascript/simplebindings/appletinterface.h +++ b/scriptengines/javascript/simplebindings/appletinterface.h @@ -235,9 +235,6 @@ enum QtScrollBarPolicy { bool immutable() const; int apiVersion() const; - SimpleJavaScriptApplet::AllowedUrls allowedUrls() const; - void setAllowedUrls(const SimpleJavaScriptApplet::AllowedUrls &allowedUrls); - inline Plasma::Applet *applet() const { return m_appletScriptEngine->applet(); } Q_SIGNALS: @@ -255,7 +252,6 @@ private: QSignalMapper *m_actionSignals; QString m_currentConfig; QMap m_configs; - SimpleJavaScriptApplet::AllowedUrls m_allowedUrls; }; class PopupAppletInterface : public AppletInterface diff --git a/scriptengines/javascript/simplejavascriptapplet.cpp b/scriptengines/javascript/simplejavascriptapplet.cpp index 6a2200147..908125b25 100644 --- a/scriptengines/javascript/simplejavascriptapplet.cpp +++ b/scriptengines/javascript/simplejavascriptapplet.cpp @@ -21,7 +21,6 @@ #include -#include #include #include #include @@ -48,12 +47,13 @@ #include #include +#include "appletauthorization.h" +#include "scriptenv.h" #include "simplebindings/animationgroup.h" #include "simplebindings/dataengine.h" #include "simplebindings/i18n.h" #include "simplebindings/appletinterface.h" #include "simplebindings/bytearrayclass.h" -#include "simplebindings/filedialogproxy.h" #include "simplebindings/variant.h" using namespace Plasma; @@ -89,19 +89,6 @@ public: } }; -void registerEnums(QScriptEngine *engine, QScriptValue &scriptValue, const QMetaObject &meta) -{ - //manually create enum values. ugh - for (int i = 0; i < meta.enumeratorCount(); ++i) { - QMetaEnum e = meta.enumerator(i); - //kDebug() << e.name(); - for (int i=0; i < e.keyCount(); ++i) { - //kDebug() << e.key(i) << e.value(i); - scriptValue.setProperty(e.key(i), QScriptValue(engine, e.value(i))); - } - } -} - KSharedPtr SimpleJavaScriptApplet::s_widgetLoader; QHash SimpleJavaScriptApplet::s_animationDefs; @@ -111,7 +98,8 @@ SimpleJavaScriptApplet::SimpleJavaScriptApplet(QObject *parent, const QVariantLi Q_UNUSED(args) // kDebug() << "Script applet launched, args" << applet()->startupArguments(); - m_engine = new QScriptEngine(this); + m_engine = new ScriptEnv(this); + connect(m_engine, SIGNAL(reportError(ScriptEnv*,bool)), this, SLOT(engineReportsError(ScriptEnv*,bool))); } SimpleJavaScriptApplet::~SimpleJavaScriptApplet() @@ -121,6 +109,11 @@ SimpleJavaScriptApplet::~SimpleJavaScriptApplet() } } +void SimpleJavaScriptApplet::engineReportsError(ScriptEnv *engine, bool fatal) +{ + reportError(engine, fatal); +} + void SimpleJavaScriptApplet::reportError(QScriptEngine *engine, bool fatal) { SimpleJavaScriptApplet *jsApplet = qobject_cast(engine->parent()); @@ -271,22 +264,7 @@ void SimpleJavaScriptApplet::constraintsEvent(Plasma::Constraints constraints) bool SimpleJavaScriptApplet::include(const QString &path) { - QFile file(path); - if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - kWarning() << i18n("Unable to load script file: %1", path); - return false; - } - - QString script = file.readAll(); - //kDebug() << "Script says" << script; - - m_engine->evaluate(script); - if (m_engine->hasUncaughtException()) { - reportError(m_engine, true); - return false; - } - - return true; + return m_engine->include(path); } void SimpleJavaScriptApplet::populateAnimationsHash() @@ -307,201 +285,15 @@ bool SimpleJavaScriptApplet::init() { setupObjects(); - if (!importExtensions()) { + AppletAuthorization auth(this); + if (!m_engine->importExtensions(description(), m_self, auth)) { return false; } kDebug() << "ScriptName:" << applet()->name(); kDebug() << "ScriptCategory:" << applet()->category(); - return include(mainScript()); -} - -QScriptValue SimpleJavaScriptApplet::runApplication(QScriptContext *context, QScriptEngine *engine) -{ - Q_UNUSED(engine) - if (context->argumentCount() == 0) { - return false; - } - - KUrl::List urls; - if (context->argumentCount() > 1) { - urls = qscriptvalue_cast(context->argument(1)); - } - - const QString app = context->argument(0).toString(); - - KService::Ptr service = KService::serviceByStorageId(app); - if (service) { - return KRun::run(*service, urls, 0); - } - - const QString exec = KGlobal::dirs()->findExe(app); - if (!exec.isEmpty()) { - return KRun::run(exec, urls, 0); - } - - return false; -} - -QScriptValue SimpleJavaScriptApplet::runCommand(QScriptContext *context, QScriptEngine *engine) -{ - Q_UNUSED(engine) - if (context->argumentCount() == 0) { - return false; - } - - const QString exec = KGlobal::dirs()->findExe(context->argument(0).toString()); - if (!exec.isEmpty()) { - QString args; - if (context->argumentCount() > 1) { - const QStringList argList = qscriptvalue_cast(context->argument(1)); - if (!argList.isEmpty()) { - args = ' ' + KShell::joinArgs(argList); - } - } - - return KRun::runCommand(exec + args, 0); - } - - return false; -} - -QScriptValue SimpleJavaScriptApplet::openUrl(QScriptContext *context, QScriptEngine *engine) -{ - Q_UNUSED(engine) - if (context->argumentCount() == 0) { - return false; - } - - QScriptValue v = context->argument(0); - KUrl url = v.isString() ? KUrl(v.toString()) : qscriptvalue_cast(v); - if (url.isValid()) { - return KRun::runUrl(url, KMimeType::findByUrl(url)->name(), 0); - } - - return false; -} - -QScriptValue SimpleJavaScriptApplet::getUrl(QScriptContext *context, QScriptEngine *engine) -{ - if (context->argumentCount() == 0) { - return engine->undefinedValue(); - } - - QScriptValue v = context->argument(0); - KUrl url = v.isString() ? KUrl(v.toString()) : qscriptvalue_cast(v); - - if (!url.isValid()) { - return engine->undefinedValue(); - } - - AppletInterface *interface = extractAppletInterface(engine); - AllowedUrls allowed = interface ? interface->allowedUrls() : NoUrls; - if (url.isLocalFile()) { - if (!(allowed & LocalUrls)) { - return engine->undefinedValue(); - } - } else if (!(allowed & NetworkUrls) && - !((allowed & HttpUrls) && (url.protocol() == "http" || url.protocol() == "https"))) { - return engine->undefinedValue(); - } - - KIO::Job *job = KIO::get(url); - return engine->newQObject(job); -} - -void SimpleJavaScriptApplet::registerGetUrl() -{ - QScriptValue get = m_self.property("getUrl"); - if (!get.isValid()) { - m_self.setProperty("getUrl", m_engine->newFunction(SimpleJavaScriptApplet::getUrl)); - } -} - -bool SimpleJavaScriptApplet::importBuiltinExtesion(const QString &extension) -{ - kDebug() << extension; - if ("filedialog" == extension) { - FileDialogProxy::registerWithRuntime(m_engine); - return true; - } else if ("launchapp" == extension) { - m_self.setProperty("runApplication", m_engine->newFunction(SimpleJavaScriptApplet::runApplication)); - m_self.setProperty("runCommand", m_engine->newFunction(SimpleJavaScriptApplet::runCommand)); - m_self.setProperty("openUrl", m_engine->newFunction(SimpleJavaScriptApplet::openUrl)); - return true; - } else if ("http" == extension) { - m_interface->setAllowedUrls(m_interface->allowedUrls() | HttpUrls); - registerGetUrl(); - return true; - } else if ("networkio" == extension) { - m_interface->setAllowedUrls(m_interface->allowedUrls() | HttpUrls | NetworkUrls); - registerGetUrl(); - return true; - } else if ("localio" == extension) { - m_interface->setAllowedUrls(m_interface->allowedUrls() | LocalUrls); - registerGetUrl(); - return true; - } - - return false; -} - -bool SimpleJavaScriptApplet::importExtensions() -{ - KPluginInfo info = description(); - QStringList requiredExtensions = info.service()->property("X-Plasma-RequiredExtensions", QVariant::StringList).toStringList(); - kDebug() << "required extensions are" << requiredExtensions; - foreach (const QString &ext, requiredExtensions) { - QString extension = ext.toLower(); - if (m_extensions.contains(extension)) { - continue; - } - - if (!applet()->hasAuthorization(extension)) { - setFailedToLaunch(true, - i18n("Authorization for required extension '%1' was denied.", - extension)); - return false; - } - - if (!importBuiltinExtesion(extension)) { - m_engine->importExtension(extension); - } - - if (m_engine->hasUncaughtException()) { - reportError(m_engine, true); - return false; - } else { - m_extensions << extension; - } - } - - QStringList optionalExtensions = info.service()->property("X-Plasma-OptionalExtensions", QVariant::StringList).toStringList(); - kDebug() << "optional extensions are" << optionalExtensions; - foreach (const QString &ext, optionalExtensions) { - QString extension = ext.toLower(); - - if (m_extensions.contains(extension)) { - continue; - } - - if (!applet()->hasAuthorization(extension)) { - continue; - } - - if (!importBuiltinExtesion(extension)) { - m_engine->importExtension(extension); - } - - if (m_engine->hasUncaughtException()) { - reportError(m_engine); - } else { - m_extensions << extension; - } - } - - return true; + return m_engine->include(mainScript()); } void SimpleJavaScriptApplet::setupObjects() @@ -539,16 +331,13 @@ void SimpleJavaScriptApplet::setupObjects() } global.setProperty("startupArguments", args); - registerEnums(m_engine, global, AppletInterface::staticMetaObject); + m_engine->registerEnums(global, AppletInterface::staticMetaObject); // Add a global loadui method for ui files QScriptValue fun = m_engine->newFunction(SimpleJavaScriptApplet::loadui); global.setProperty("loadui", fun); - fun = m_engine->newFunction(SimpleJavaScriptApplet::print); - global.setProperty("print", fun); - // Work around bug in 4.3.0 qMetaTypeId(); @@ -585,7 +374,7 @@ void SimpleJavaScriptApplet::setupObjects() QSet SimpleJavaScriptApplet::loadedExtensions() const { - return m_extensions; + return m_engine->loadedExtensions(); } AppletInterface *SimpleJavaScriptApplet::extractAppletInterface(QScriptEngine *engine) @@ -827,29 +616,10 @@ QScriptValue SimpleJavaScriptApplet::createWidget(QScriptContext *context, QScri fun.setProperty("adjustSize", engine->newFunction(widgetAdjustSize)); //register enums will be accessed for instance as frame.Sunken for Frame shadow... - registerEnums(engine, fun, *w->metaObject()); + static_cast(engine)->registerEnums(fun, *w->metaObject()); return fun; } -QScriptValue SimpleJavaScriptApplet::notSupported(QScriptContext *context, QScriptEngine *engine) -{ - Q_UNUSED(engine) - QString message = context->callee().property("message").toString(); - return context->throwError(i18n("This operation was not supported, %1", message) ); -} - - -QScriptValue SimpleJavaScriptApplet::print(QScriptContext *context, QScriptEngine *engine) -{ - if (context->argumentCount() != 1) { - return context->throwError(i18n("print() takes one argument")); - } - - //TODO: a GUI console? :) - std::cout << context->argument(0).toString().toLocal8Bit().constData() << std::endl; - return engine->undefinedValue(); -} - void SimpleJavaScriptApplet::collectGarbage() { m_engine->collectGarbage(); diff --git a/scriptengines/javascript/simplejavascriptapplet.h b/scriptengines/javascript/simplejavascriptapplet.h index bfb995fd8..12c59646b 100644 --- a/scriptengines/javascript/simplejavascriptapplet.h +++ b/scriptengines/javascript/simplejavascriptapplet.h @@ -27,22 +27,16 @@ #include "simplebindings/uiloader.h" -class QScriptEngine; class QScriptContext; class AppletInterface; +class ScriptEnv; class SimpleJavaScriptApplet : public Plasma::AppletScript { Q_OBJECT public: - enum AllowedUrl { NoUrls = 0, - HttpUrls = 1, - NetworkUrls = 2, - LocalUrls = 4 }; - Q_DECLARE_FLAGS(AllowedUrls, AllowedUrl) - SimpleJavaScriptApplet(QObject *parent, const QVariantList &args); ~SimpleJavaScriptApplet(); bool init(); @@ -58,16 +52,18 @@ public: static QString findImageFile(QScriptEngine *engine, const QString &file); -public slots: +public Q_SLOTS: void dataUpdated( const QString &name, const Plasma::DataEngine::Data &data ); void configChanged(); void executeAction(const QString &name); void collectGarbage(); +private Q_SLOTS: + void engineReportsError(ScriptEnv *engine, bool fatal); + private: - void registerGetUrl(); bool importExtensions(); - bool importBuiltinExtesion(const QString &extension); + bool importBuiltinExtension(const QString &extension); void setupObjects(); void callFunction(const QString &functionName, const QScriptValueList &args = QScriptValueList()); static void populateAnimationsHash(); @@ -88,18 +84,8 @@ private: void installWidgets(QScriptEngine *engine); static QScriptValue createWidget(QScriptContext *context, QScriptEngine *engine); - static QScriptValue notSupported(QScriptContext *context, QScriptEngine *engine); - static QScriptValue print(QScriptContext *context, QScriptEngine *engine); static QScriptValue widgetAdjustSize(QScriptContext *context, QScriptEngine *engine); - // run extension - static QScriptValue runApplication(QScriptContext *context, QScriptEngine *engine); - static QScriptValue runCommand(QScriptContext *context, QScriptEngine *engine); - static QScriptValue openUrl(QScriptContext *context, QScriptEngine *engine); - - // file io extensions - static QScriptValue getUrl(QScriptContext *context, QScriptEngine *engine); - static AppletInterface *extractAppletInterface(QScriptEngine *engine); static QGraphicsWidget *extractParent(QScriptContext *context, QScriptEngine *engine, @@ -109,15 +95,12 @@ private: private: static KSharedPtr s_widgetLoader; static QHash s_animationDefs; - QScriptEngine *m_engine; + ScriptEnv *m_engine; QScriptValue m_self; QVariantList m_args; - QSet m_extensions; AppletInterface *m_interface; friend class AppletInterface; }; -Q_DECLARE_OPERATORS_FOR_FLAGS(SimpleJavaScriptApplet::AllowedUrls) - #endif // SCRIPT_H