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
4#include "qqmlpreviewfileloader.h"
5#include "qqmlpreviewservice.h"
6
7#include <QtQml/qqmlfile.h>
8
9#include <QtCore/qlibraryinfo.h>
10#include <QtCore/qstandardpaths.h>
11
12QT_BEGIN_NAMESPACE
13
14QQmlPreviewFileLoader::QQmlPreviewFileLoader(QQmlPreviewServiceImpl *service) : m_service(service)
15{
16 // Exclude some resource paths used by Qt itself. There is no point in loading those from the
17 // client as the client will not have the files (or even worse, it may have different ones).
18 m_blacklist.blacklist(path: ":/qt-project.org");
19 m_blacklist.blacklist(path: ":/QtQuick/Controls/Styles");
20 m_blacklist.blacklist(path: ":/ExtrasImports/QtQuick/Controls/Styles");
21
22 // Target specific configuration should not replaced with files from the host.
23 m_blacklist.blacklist(path: "/etc");
24
25 for (int loc = QLibraryInfo::PrefixPath; loc < QLibraryInfo::TestsPath; ++loc) {
26 m_blacklist.blacklist(path: QLibraryInfo::path(
27 p: static_cast<QLibraryInfo::LibraryPath>(loc)));
28 }
29 m_blacklist.blacklist(path: QLibraryInfo::path(p: QLibraryInfo::SettingsPath));
30
31 static const QStandardPaths::StandardLocation blackListLocations[] = {
32 QStandardPaths::CacheLocation,
33 QStandardPaths::GenericDataLocation,
34 QStandardPaths::ConfigLocation,
35 QStandardPaths::GenericCacheLocation,
36 QStandardPaths::GenericConfigLocation,
37 QStandardPaths::AppDataLocation,
38 QStandardPaths::AppConfigLocation
39 };
40
41 for (auto locationType : blackListLocations) {
42 const QStringList locations = QStandardPaths::standardLocations(type: locationType);
43 for (const QString &location : locations)
44 m_blacklist.blacklist(path: location);
45 }
46
47 m_blacklist.whitelist(path: QLibraryInfo::path(p: QLibraryInfo::TestsPath));
48
49 connect(sender: this, signal: &QQmlPreviewFileLoader::request, context: service, slot: &QQmlPreviewServiceImpl::forwardRequest,
50 type: Qt::DirectConnection);
51 connect(sender: service, signal: &QQmlPreviewServiceImpl::directory, context: this, slot: &QQmlPreviewFileLoader::directory);
52 connect(sender: service, signal: &QQmlPreviewServiceImpl::file, context: this, slot: &QQmlPreviewFileLoader::file);
53 connect(sender: service, signal: &QQmlPreviewServiceImpl::error, context: this, slot: &QQmlPreviewFileLoader::error);
54 connect(sender: service, signal: &QQmlPreviewServiceImpl::clearCache, context: this, slot: &QQmlPreviewFileLoader::clearCache);
55 moveToThread(thread: &m_thread);
56 m_thread.start();
57}
58
59QQmlPreviewFileLoader::~QQmlPreviewFileLoader() {
60 m_thread.quit();
61 m_thread.wait();
62}
63
64QQmlPreviewFileLoader::Result QQmlPreviewFileLoader::load(const QString &path)
65{
66 QMutexLocker locker(&m_contentMutex);
67 m_path = path;
68
69 auto fileIterator = m_fileCache.constFind(key: path);
70 if (fileIterator != m_fileCache.constEnd()) {
71 m_result = File;
72 m_contents = *fileIterator;
73 m_entries.clear();
74 return m_result;
75 }
76
77 auto dirIterator = m_directoryCache.constFind(key: path);
78 if (dirIterator != m_directoryCache.constEnd()) {
79 m_result = Directory;
80 m_contents.clear();
81 m_entries = *dirIterator;
82 return m_result;
83 }
84
85 m_result = Unknown;
86 m_entries.clear();
87 m_contents.clear();
88 emit request(file: path);
89 m_waitCondition.wait(lockedMutex: &m_contentMutex);
90 return m_result;
91}
92
93QByteArray QQmlPreviewFileLoader::contents()
94{
95 QMutexLocker locker(&m_contentMutex);
96 return m_contents;
97}
98
99QStringList QQmlPreviewFileLoader::entries()
100{
101 QMutexLocker locker(&m_contentMutex);
102 return m_entries;
103}
104
105void QQmlPreviewFileLoader::whitelist(const QUrl &url)
106{
107 const QString path = QQmlFile::urlToLocalFileOrQrc(url);
108 if (!path.isEmpty()) {
109 QMutexLocker locker(&m_contentMutex);
110 m_blacklist.whitelist(path);
111 }
112}
113
114bool QQmlPreviewFileLoader::isBlacklisted(const QString &path)
115{
116 QMutexLocker locker(&m_contentMutex);
117 return m_blacklist.isBlacklisted(path);
118}
119
120void QQmlPreviewFileLoader::file(const QString &path, const QByteArray &contents)
121{
122 QMutexLocker locker(&m_contentMutex);
123 m_blacklist.whitelist(path);
124 m_fileCache[path] = contents;
125 if (path == m_path) {
126 m_contents = contents;
127 m_result = File;
128 m_waitCondition.wakeOne();
129 }
130}
131
132void QQmlPreviewFileLoader::directory(const QString &path, const QStringList &entries)
133{
134 QMutexLocker locker(&m_contentMutex);
135 m_blacklist.whitelist(path);
136 m_directoryCache[path] = entries;
137 if (path == m_path) {
138 m_entries = entries;
139 m_result = Directory;
140 m_waitCondition.wakeOne();
141 }
142}
143
144void QQmlPreviewFileLoader::error(const QString &path)
145{
146 QMutexLocker locker(&m_contentMutex);
147 m_blacklist.blacklist(path);
148 if (path == m_path) {
149 m_result = Fallback;
150 m_waitCondition.wakeOne();
151 }
152}
153
154void QQmlPreviewFileLoader::clearCache()
155{
156 QMutexLocker locker(&m_contentMutex);
157 m_fileCache.clear();
158 m_directoryCache.clear();
159}
160
161QT_END_NAMESPACE
162
163#include "moc_qqmlpreviewfileloader.cpp"
164

source code of qtdeclarative/src/plugins/qmltooling/qmldbg_preview/qqmlpreviewfileloader.cpp