3 #include "cachedhttp.h"
8 CachedHttp *cachedHttp = new CachedHttp(Http::instance(), "js");
9 cachedHttp->setMaxSeconds(3600);
10 // Avoid expiring the cached js
11 cachedHttp->setMaxSize(0);
13 cachedHttp->getValidators().insert("application/javascript", [](const auto &reply) -> bool {
14 return !reply.body().isEmpty();
24 static thread_local JS i;
28 JS::JS(QObject *parent) : QObject(parent), engine(nullptr) {}
30 void JS::initialize(const QUrl &url) {
35 bool JS::checkError(const QJSValue &value) {
36 if (value.isError()) {
37 qWarning() << "Error" << value.toString();
38 qDebug() << value.property("stack").toString().splitRef('\n');
44 bool JS::isInitialized() {
45 if (ready) return true;
50 JSResult &JS::callFunction(JSResult *result, const QString &name, const QJSValueList &args) {
51 if (!isInitialized()) {
52 qDebug() << "Not initialized";
53 QTimer::singleShot(1000, this,
54 [this, result, name, args] { callFunction(result, name, args); });
60 auto function = engine->evaluate(name);
61 if (!function.isCallable()) {
62 qWarning() << function.toString() << " is not callable";
63 QTimer::singleShot(0, result, [result, function] { result->setError(function); });
68 args2.prepend(engine->newQObject(result));
69 qDebug() << "Calling" << function.toString();
70 auto v = function.call(args2);
71 if (checkError(v)) QTimer::singleShot(0, result, [result, v] { result->setError(v); });
77 class MyCookieJar : public QNetworkCookieJar {
78 bool insertCookie(const QNetworkCookie &cookie) {
79 if (cookie.name().contains("CONSENT")) {
80 qDebug() << "Fixing CONSENT cookie" << cookie;
81 auto cookie2 = cookie;
82 cookie2.setValue(cookie.value().replace("PENDING", "YES"));
83 return QNetworkCookieJar::insertCookie(cookie2);
85 return QNetworkCookieJar::insertCookie(cookie);
89 auto nam = getEngine().networkAccessManager();
90 nam->clearAccessCache();
91 nam->setCookieJar(new MyCookieJar());
94 void JS::initialize() {
96 qDebug() << "No js url set";
100 if (initializing) return;
102 qDebug() << "Initializing";
104 if (engine) engine->deleteLater();
105 engine = new QQmlEngine(this);
106 engine->setNetworkAccessManagerFactory(&namFactory);
107 engine->globalObject().setProperty("global", engine->globalObject());
109 QJSValue timer = engine->newQObject(new JSTimer(engine));
110 engine->globalObject().setProperty("setTimeoutQt", timer.property("setTimeout"));
111 QJSValue setTimeoutWrapperFunction =
112 engine->evaluate("function setTimeout(cb, delay) {"
113 "const args = Array.prototype.slice.call(arguments, 2);"
114 "return setTimeoutQt(cb, delay, args);"
116 checkError(setTimeoutWrapperFunction);
117 engine->globalObject().setProperty("clearTimeout", timer.property("clearTimeout"));
119 connect(cachedHttp().get(url), &HttpReply::finished, this, [this](auto &reply) {
120 if (!reply.isSuccessful()) {
121 emit initFailed("Cannot load JS");
122 qDebug() << "Cannot load JS";
123 initializing = false;
126 auto value = engine->evaluate(reply.body());
127 if (!checkError(value)) {
128 qDebug() << "Initialized";
132 initializing = false;