Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmlpreviewfileloader.cpp
Go to the documentation of this file.
1// Copyright (C) 2018 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant
4
7
8#include <QtQml/qqmlfile.h>
9
10#include <QtCore/qlibraryinfo.h>
11#include <QtCore/qstandardpaths.h>
12
14
15QQmlPreviewFileLoader::QQmlPreviewFileLoader(QQmlPreviewServiceImpl *service)
16{
17 // This is created from stateChanged() on the debug server thread, but that's not where we
18 // want it to live. It logically belongs to the service. Mind that the service does not live
19 // on the debug server thread, but does process messageReceived() on the debug server thread.
20 moveToThread(service->thread());
21
22 // Exclude some resource paths used by Qt itself. There is no point in loading those from the
23 // client as the client will not have the files (or even worse, it may have different ones).
24 m_blacklist.blacklist(":/qt-project.org");
25 m_blacklist.blacklist(":/QtQuick/Controls/Styles");
26 m_blacklist.blacklist(":/ExtrasImports/QtQuick/Controls/Styles");
27
28 // Target specific configuration should not replaced with files from the host.
29 m_blacklist.blacklist("/etc");
30
31 for (int loc = QLibraryInfo::PrefixPath; loc < QLibraryInfo::TestsPath; ++loc) {
32 m_blacklist.blacklist(QLibraryInfo::path(
33 static_cast<QLibraryInfo::LibraryPath>(loc)));
34 }
35 m_blacklist.blacklist(QLibraryInfo::path(QLibraryInfo::SettingsPath));
36
37 static const QStandardPaths::StandardLocation blackListLocations[] = {
38 QStandardPaths::CacheLocation,
39 QStandardPaths::GenericDataLocation,
40 QStandardPaths::ConfigLocation,
41 QStandardPaths::GenericCacheLocation,
42 QStandardPaths::GenericConfigLocation,
43 QStandardPaths::AppDataLocation,
44 QStandardPaths::AppConfigLocation
45 };
46
47 for (auto locationType : blackListLocations) {
48 const QStringList locations = QStandardPaths::standardLocations(locationType);
49 for (const QString &location : locations)
50 m_blacklist.blacklist(location);
51 }
52
53 m_blacklist.whitelist(QLibraryInfo::path(QLibraryInfo::TestsPath));
54
55 // We absolutely want those signals to be connected directly. The service's (directly connected)
56 // load() signal should not be able to sneak in between a file() signal submission and its
57 // arrival. All the file loader's methods are protected by the contentMutex. So we can connect
58 // directly.
59 connect(this, &QQmlPreviewFileLoader::request, service, &QQmlPreviewServiceImpl::forwardRequest,
60 Qt::DirectConnection);
61 connect(service, &QQmlPreviewServiceImpl::directory, this, &QQmlPreviewFileLoader::directory,
62 Qt::DirectConnection);
63 connect(service, &QQmlPreviewServiceImpl::file, this, &QQmlPreviewFileLoader::file,
64 Qt::DirectConnection);
65 connect(service, &QQmlPreviewServiceImpl::error, this, &QQmlPreviewFileLoader::error,
66 Qt::DirectConnection);
67 connect(service, &QQmlPreviewServiceImpl::clearCache, this, &QQmlPreviewFileLoader::clearCache,
68 Qt::DirectConnection);
69}
70
72{
73 QMutexLocker locker(&m_contentMutex);
74 m_path = path;
75
76 auto fileIterator = m_fileCache.constFind(path);
77 if (fileIterator != m_fileCache.constEnd()) {
78 m_result = File;
79 m_contents = *fileIterator;
80 m_entries.clear();
81 return m_result;
82 }
83
84 auto dirIterator = m_directoryCache.constFind(path);
85 if (dirIterator != m_directoryCache.constEnd()) {
86 m_result = Directory;
87 m_contents.clear();
88 m_entries = *dirIterator;
89 return m_result;
90 }
91
92 m_result = Unknown;
93 m_entries.clear();
94 m_contents.clear();
95 emit request(path);
96 m_waitCondition.wait(&m_contentMutex);
97 return m_result;
98}
99
101{
102 QMutexLocker locker(&m_contentMutex);
103 return m_contents;
104}
105
107{
108 QMutexLocker locker(&m_contentMutex);
109 return m_entries;
110}
111
112void QQmlPreviewFileLoader::whitelist(const QUrl &url)
113{
114 const QString path = QQmlFile::urlToLocalFileOrQrc(url);
115 if (!path.isEmpty()) {
116 QMutexLocker locker(&m_contentMutex);
117 m_blacklist.whitelist(path);
118 }
119}
120
121bool QQmlPreviewFileLoader::isBlacklisted(const QString &path)
122{
123 QMutexLocker locker(&m_contentMutex);
124 return m_blacklist.isBlacklisted(path);
125}
126
127void QQmlPreviewFileLoader::file(const QString &path, const QByteArray &contents)
128{
129 QMutexLocker locker(&m_contentMutex);
130 m_blacklist.whitelist(path);
131 m_fileCache[path] = contents;
132 if (path == m_path) {
133 m_contents = contents;
134 m_result = File;
135 m_waitCondition.wakeOne();
136 }
137}
138
139void QQmlPreviewFileLoader::directory(const QString &path, const QStringList &entries)
140{
141 QMutexLocker locker(&m_contentMutex);
142 m_blacklist.whitelist(path);
143 m_directoryCache[path] = entries;
144 if (path == m_path) {
145 m_entries = entries;
146 m_result = Directory;
147 m_waitCondition.wakeOne();
148 }
149}
150
151void QQmlPreviewFileLoader::error(const QString &path)
152{
153 QMutexLocker locker(&m_contentMutex);
154 m_blacklist.blacklist(path);
155 if (path == m_path) {
156 m_result = Fallback;
157 m_waitCondition.wakeOne();
158 }
159}
160
161void QQmlPreviewFileLoader::clearCache()
162{
163 QMutexLocker locker(&m_contentMutex);
164 m_fileCache.clear();
165 m_directoryCache.clear();
166}
167
168QT_END_NAMESPACE
169
170#include "moc_qqmlpreviewfileloader.cpp"
Result load(const QString &file)
bool isBlacklisted(const QString &file)
void whitelist(const QUrl &url)
Combined button and popup list for selecting options.
connect(manager, &QNetworkAccessManager::finished, this, &MyClass::replyFinished)