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 // On Windows, GenericDataLocation (AppData/Local) is a parent of the temp directory
56 // (AppData/Local/Temp). Whitelist the temp path since we commonly want to preview
57 // files in the temp location.
58 const QStringList tempLocations
59 = QStandardPaths::standardLocations(QStandardPaths::TempLocation);
60 for (const QString &tempLocation : tempLocations)
61 m_blacklist.whitelist(tempLocation);
62
63 // We absolutely want those signals to be connected directly. The service's (directly connected)
64 // load() signal should not be able to sneak in between a file() signal submission and its
65 // arrival. All the file loader's methods are protected by the contentMutex. So we can connect
66 // directly.
67 connect(this, &QQmlPreviewFileLoader::request, service, &QQmlPreviewServiceImpl::forwardRequest,
68 Qt::DirectConnection);
69 connect(service, &QQmlPreviewServiceImpl::directory, this, &QQmlPreviewFileLoader::directory,
70 Qt::DirectConnection);
71 connect(service, &QQmlPreviewServiceImpl::file, this, &QQmlPreviewFileLoader::file,
72 Qt::DirectConnection);
73 connect(service, &QQmlPreviewServiceImpl::error, this, &QQmlPreviewFileLoader::error,
74 Qt::DirectConnection);
75 connect(service, &QQmlPreviewServiceImpl::clearCache, this, &QQmlPreviewFileLoader::clearCache,
76 Qt::DirectConnection);
77}
78
80{
81 QMutexLocker locker(&m_contentMutex);
82 m_path = path;
83
84 auto fileIterator = m_fileCache.constFind(path);
85 if (fileIterator != m_fileCache.constEnd()) {
86 m_result = File;
87 m_contents = *fileIterator;
88 m_entries.clear();
89 return m_result;
90 }
91
92 auto dirIterator = m_directoryCache.constFind(path);
93 if (dirIterator != m_directoryCache.constEnd()) {
94 m_result = Directory;
95 m_contents.clear();
96 m_entries = *dirIterator;
97 return m_result;
98 }
99
100 m_result = Unknown;
101 m_entries.clear();
102 m_contents.clear();
103 emit request(path);
104 m_waitCondition.wait(&m_contentMutex);
105 return m_result;
106}
107
109{
110 QMutexLocker locker(&m_contentMutex);
111 return m_contents;
112}
113
115{
116 QMutexLocker locker(&m_contentMutex);
117 return m_entries;
118}
119
120void QQmlPreviewFileLoader::whitelist(const QUrl &url)
121{
122 const QString path = QQmlFile::urlToLocalFileOrQrc(url);
123 if (!path.isEmpty()) {
124 QMutexLocker locker(&m_contentMutex);
125 m_blacklist.whitelist(path);
126 }
127}
128
129bool QQmlPreviewFileLoader::isBlacklisted(const QString &path)
130{
131 QMutexLocker locker(&m_contentMutex);
132 return m_blacklist.isBlacklisted(path);
133}
134
135void QQmlPreviewFileLoader::file(const QString &path, const QByteArray &contents)
136{
137 QMutexLocker locker(&m_contentMutex);
138 m_blacklist.whitelist(path);
139 m_fileCache[path] = contents;
140 if (path == m_path) {
141 m_contents = contents;
142 m_result = File;
143 m_waitCondition.wakeOne();
144 }
145}
146
147void QQmlPreviewFileLoader::directory(const QString &path, const QStringList &entries)
148{
149 QMutexLocker locker(&m_contentMutex);
150 m_blacklist.whitelist(path);
151 m_directoryCache[path] = entries;
152 if (path == m_path) {
153 m_entries = entries;
154 m_result = Directory;
155 m_waitCondition.wakeOne();
156 }
157}
158
159void QQmlPreviewFileLoader::error(const QString &path)
160{
161 QMutexLocker locker(&m_contentMutex);
162 m_blacklist.blacklist(path);
163 if (path == m_path) {
164 m_result = Fallback;
165 m_waitCondition.wakeOne();
166 }
167}
168
169void QQmlPreviewFileLoader::clearCache()
170{
171 QMutexLocker locker(&m_contentMutex);
172 m_fileCache.clear();
173 m_directoryCache.clear();
174}
175
176QT_END_NAMESPACE
177
178#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)