File indexing completed on 2024-05-12 04:33:31
0001 /* 0002 SPDX-FileCopyrightText: 2008 Pino Toscano <pino@kde.org> 0003 SPDX-FileCopyrightText: 2008 Harri Porten <porten@kde.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "config-okular.h" 0009 #include "executor_js_p.h" 0010 0011 #include "../debug_p.h" 0012 #include "../document_p.h" 0013 0014 #include "event_p.h" 0015 #include "js_app_p.h" 0016 #include "js_console_p.h" 0017 #include "js_data_p.h" 0018 #include "js_display_p.h" 0019 #include "js_document_p.h" 0020 #include "js_event_p.h" 0021 #include "js_field_p.h" 0022 #include "js_fullscreen_p.h" 0023 #include "js_ocg_p.h" 0024 #include "js_spell_p.h" 0025 #include "js_util_p.h" 0026 0027 #include <QDebug> 0028 #include <QJSEngine> 0029 #include <QThread> 0030 #include <QTimer> 0031 0032 using namespace Okular; 0033 0034 class Okular::ExecutorJSPrivate 0035 { 0036 public: 0037 explicit ExecutorJSPrivate(DocumentPrivate *doc) 0038 : m_doc(doc) 0039 { 0040 initTypes(); 0041 } 0042 ~ExecutorJSPrivate() 0043 { 0044 m_watchdogTimer->deleteLater(); 0045 m_watchdogThread.quit(); 0046 m_watchdogThread.wait(); 0047 } 0048 0049 void initTypes(); 0050 0051 DocumentPrivate *m_doc; 0052 QJSEngine m_interpreter; 0053 0054 QThread m_watchdogThread; 0055 QTimer *m_watchdogTimer = nullptr; 0056 }; 0057 0058 void ExecutorJSPrivate::initTypes() 0059 { 0060 m_watchdogThread.start(); 0061 m_watchdogTimer = new QTimer; 0062 m_watchdogTimer->setInterval(std::chrono::seconds(2)); // max 2 secs allowed 0063 m_watchdogTimer->setSingleShot(true); 0064 m_watchdogTimer->moveToThread(&m_watchdogThread); 0065 QObject::connect( 0066 m_watchdogTimer, &QTimer::timeout, &m_interpreter, [this]() { m_interpreter.setInterrupted(true); }, Qt::DirectConnection); 0067 0068 m_interpreter.globalObject().setProperty(QStringLiteral("app"), m_interpreter.newQObject(new JSApp(m_doc, m_watchdogTimer))); 0069 m_interpreter.globalObject().setProperty(QStringLiteral("console"), m_interpreter.newQObject(new JSConsole)); 0070 m_interpreter.globalObject().setProperty(QStringLiteral("Doc"), m_interpreter.newQObject(new JSDocument(m_doc))); 0071 m_interpreter.globalObject().setProperty(QStringLiteral("display"), m_interpreter.newQObject(new JSDisplay)); 0072 m_interpreter.globalObject().setProperty(QStringLiteral("spell"), m_interpreter.newQObject(new JSSpell)); 0073 m_interpreter.globalObject().setProperty(QStringLiteral("util"), m_interpreter.newQObject(new JSUtil)); 0074 } 0075 0076 ExecutorJS::ExecutorJS(DocumentPrivate *doc) 0077 : d(new ExecutorJSPrivate(doc)) 0078 { 0079 } 0080 0081 ExecutorJS::~ExecutorJS() 0082 { 0083 JSField::clearCachedFields(); 0084 JSApp::clearCachedFields(); 0085 delete d; 0086 } 0087 0088 void ExecutorJS::execute(const QString &script, Event *event) 0089 { 0090 const auto eventVal = event ? d->m_interpreter.newQObject(new JSEvent(event)) : QJSValue(QJSValue::UndefinedValue); 0091 d->m_interpreter.globalObject().setProperty(QStringLiteral("event"), eventVal); 0092 0093 QMetaObject::invokeMethod(d->m_watchdogTimer, qOverload<>(&QTimer::start)); 0094 d->m_interpreter.setInterrupted(false); 0095 auto result = d->m_interpreter.evaluate(script, QStringLiteral("okular.js")); 0096 QMetaObject::invokeMethod(d->m_watchdogTimer, qOverload<>(&QTimer::stop)); 0097 0098 if (result.isError()) { 0099 qCDebug(OkularCoreDebug) << "JS exception" << result.toString() << "(line " << result.property(QStringLiteral("lineNumber")).toInt() << ")"; 0100 } else { 0101 qCDebug(OkularCoreDebug) << "result:" << result.toString(); 0102 0103 if (event) { 0104 qCDebug(OkularCoreDebug) << "Event Result:" << event->name() << event->type() << "value:" << event->value(); 0105 } 0106 } 0107 }