1 /****************************************************************************
2 **
3 ** Copyright (C) 2019 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the QtQml module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 3 requirements
23 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24 **
25 ** GNU General Public License Usage
26 ** Alternatively, this file may be used under the terms of the GNU
27 ** General Public License version 2.0 or (at your option) the GNU General
28 ** Public license version 3 or any later version approved by the KDE Free
29 ** Qt Foundation. The licenses are as published by the Free Software
30 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31 ** included in the packaging of this file. Please review the following
32 ** information to ensure the GNU General Public License requirements will
33 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34 ** https://www.gnu.org/licenses/gpl-3.0.html.
35 **
36 ** $QT_END_LICENSE$
37 **
38 ****************************************************************************/
39 
40 #include <private/qqmlengine_p.h>
41 #include <private/qqmlextensionplugin_p.h>
42 #include <private/qqmltypeloaderthread_p.h>
43 
44 #if QT_CONFIG(qml_network)
45 #include <private/qqmltypeloadernetworkreplyproxy_p.h>
46 #endif
47 
48 QT_BEGIN_NAMESPACE
49 
QQmlTypeLoaderThread(QQmlTypeLoader * loader)50 QQmlTypeLoaderThread::QQmlTypeLoaderThread(QQmlTypeLoader *loader)
51     : m_loader(loader)
52 #if QT_CONFIG(qml_network)
53       , m_networkAccessManager(nullptr), m_networkReplyProxy(nullptr)
54 #endif // qml_network
55 {
56     // Do that after initializing all the members.
57     startup();
58 }
59 
60 #if QT_CONFIG(qml_network)
networkAccessManager() const61 QNetworkAccessManager *QQmlTypeLoaderThread::networkAccessManager() const
62 {
63     Q_ASSERT(isThisThread());
64     if (!m_networkAccessManager) {
65         m_networkAccessManager = QQmlEnginePrivate::get(m_loader->engine())->createNetworkAccessManager(nullptr);
66         m_networkReplyProxy = new QQmlTypeLoaderNetworkReplyProxy(m_loader);
67     }
68 
69     return m_networkAccessManager;
70 }
71 
networkReplyProxy() const72 QQmlTypeLoaderNetworkReplyProxy *QQmlTypeLoaderThread::networkReplyProxy() const
73 {
74     Q_ASSERT(isThisThread());
75     Q_ASSERT(m_networkReplyProxy); // Must call networkAccessManager() first
76     return m_networkReplyProxy;
77 }
78 #endif // qml_network
79 
load(QQmlDataBlob * b)80 void QQmlTypeLoaderThread::load(QQmlDataBlob *b)
81 {
82     b->addref();
83     callMethodInThread(&This::loadThread, b);
84 }
85 
loadAsync(QQmlDataBlob * b)86 void QQmlTypeLoaderThread::loadAsync(QQmlDataBlob *b)
87 {
88     b->addref();
89     postMethodToThread(&This::loadThread, b);
90 }
91 
loadWithStaticData(QQmlDataBlob * b,const QByteArray & d)92 void QQmlTypeLoaderThread::loadWithStaticData(QQmlDataBlob *b, const QByteArray &d)
93 {
94     b->addref();
95     callMethodInThread(&This::loadWithStaticDataThread, b, d);
96 }
97 
loadWithStaticDataAsync(QQmlDataBlob * b,const QByteArray & d)98 void QQmlTypeLoaderThread::loadWithStaticDataAsync(QQmlDataBlob *b, const QByteArray &d)
99 {
100     b->addref();
101     postMethodToThread(&This::loadWithStaticDataThread, b, d);
102 }
103 
loadWithCachedUnit(QQmlDataBlob * b,const QV4::CompiledData::Unit * unit)104 void QQmlTypeLoaderThread::loadWithCachedUnit(QQmlDataBlob *b, const QV4::CompiledData::Unit *unit)
105 {
106     b->addref();
107     callMethodInThread(&This::loadWithCachedUnitThread, b, unit);
108 }
109 
loadWithCachedUnitAsync(QQmlDataBlob * b,const QV4::CompiledData::Unit * unit)110 void QQmlTypeLoaderThread::loadWithCachedUnitAsync(QQmlDataBlob *b, const QV4::CompiledData::Unit *unit)
111 {
112     b->addref();
113     postMethodToThread(&This::loadWithCachedUnitThread, b, unit);
114 }
115 
callCompleted(QQmlDataBlob * b)116 void QQmlTypeLoaderThread::callCompleted(QQmlDataBlob *b)
117 {
118     b->addref();
119 #if !QT_CONFIG(thread)
120     if (!isThisThread())
121         postMethodToThread(&This::callCompletedMain, b);
122 #else
123     postMethodToMain(&This::callCompletedMain, b);
124 #endif
125 }
126 
callDownloadProgressChanged(QQmlDataBlob * b,qreal p)127 void QQmlTypeLoaderThread::callDownloadProgressChanged(QQmlDataBlob *b, qreal p)
128 {
129     b->addref();
130 #if !QT_CONFIG(thread)
131     if (!isThisThread())
132         postMethodToThread(&This::callDownloadProgressChangedMain, b, p);
133 #else
134     postMethodToMain(&This::callDownloadProgressChangedMain, b, p);
135 #endif
136 }
137 
initializeEngine(QQmlExtensionInterface * iface,const char * uri)138 void QQmlTypeLoaderThread::initializeEngine(QQmlExtensionInterface *iface,
139                                             const char *uri)
140 {
141     callMethodInMain(&This::initializeExtensionMain, iface, uri);
142 }
143 
initializeEngine(QQmlEngineExtensionInterface * iface,const char * uri)144 void QQmlTypeLoaderThread::initializeEngine(QQmlEngineExtensionInterface *iface,
145                                             const char *uri)
146 {
147     callMethodInMain(&This::initializeEngineExtensionMain, iface, uri);
148 }
149 
shutdownThread()150 void QQmlTypeLoaderThread::shutdownThread()
151 {
152 #if QT_CONFIG(qml_network)
153     delete m_networkAccessManager;
154     m_networkAccessManager = nullptr;
155     delete m_networkReplyProxy;
156     m_networkReplyProxy = nullptr;
157 #endif // qml_network
158 }
159 
loadThread(QQmlDataBlob * b)160 void QQmlTypeLoaderThread::loadThread(QQmlDataBlob *b)
161 {
162     m_loader->loadThread(b);
163     b->release();
164 }
165 
loadWithStaticDataThread(QQmlDataBlob * b,const QByteArray & d)166 void QQmlTypeLoaderThread::loadWithStaticDataThread(QQmlDataBlob *b, const QByteArray &d)
167 {
168     m_loader->loadWithStaticDataThread(b, d);
169     b->release();
170 }
171 
loadWithCachedUnitThread(QQmlDataBlob * b,const QV4::CompiledData::Unit * unit)172 void QQmlTypeLoaderThread::loadWithCachedUnitThread(QQmlDataBlob *b, const QV4::CompiledData::Unit *unit)
173 {
174     m_loader->loadWithCachedUnitThread(b, unit);
175     b->release();
176 }
177 
callCompletedMain(QQmlDataBlob * b)178 void QQmlTypeLoaderThread::callCompletedMain(QQmlDataBlob *b)
179 {
180 #ifdef DATABLOB_DEBUG
181     qWarning("QQmlTypeLoaderThread: %s completed() callback", qPrintable(b->urlString()));
182 #endif
183     b->completed();
184     b->release();
185 }
186 
callDownloadProgressChangedMain(QQmlDataBlob * b,qreal p)187 void QQmlTypeLoaderThread::callDownloadProgressChangedMain(QQmlDataBlob *b, qreal p)
188 {
189 #ifdef DATABLOB_DEBUG
190     qWarning("QQmlTypeLoaderThread: %s downloadProgressChanged(%f) callback",
191              qPrintable(b->urlString()), p);
192 #endif
193     b->downloadProgressChanged(p);
194     b->release();
195 }
196 
initializeExtensionMain(QQmlExtensionInterface * iface,const char * uri)197 void QQmlTypeLoaderThread::initializeExtensionMain(QQmlExtensionInterface *iface,
198                                                 const char *uri)
199 {
200     Q_ASSERT(m_loader->engine()->thread() == QThread::currentThread());
201     iface->initializeEngine(m_loader->engine(), uri);
202 }
203 
initializeEngineExtensionMain(QQmlEngineExtensionInterface * iface,const char * uri)204 void QQmlTypeLoaderThread::initializeEngineExtensionMain(QQmlEngineExtensionInterface *iface,
205                                                 const char *uri)
206 {
207     Q_ASSERT(m_loader->engine()->thread() == QThread::currentThread());
208     iface->initializeEngine(m_loader->engine(), uri);
209 }
210 
211 QT_END_NAMESPACE
212