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
qwasmlocalfileengine.cpp
Go to the documentation of this file.
1// Copyright (C) 2025 Qt Group
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 reason:default
5#include <QtCore/QDebug>
6#include <QtCore/QUrl>
7
9
10using namespace Qt::StringLiterals;
11
12// Custom URL scheme for files handled by this file engine. A complete file URL can
13// look like
14//
15// "weblocalfile:/n/file.ext"
16//
17// where n is a counter to ensure uniqueness, needed since web platform gives us the file name only
18// and does not provide the file path.
19//
20// The scheme may be visible to end users if the application displays it, so
21// we avoid using "wasm" and instead say "web", which should be more recognizable.
22static constexpr QLatin1StringView wasmlocalfileScheme = "weblocalfile"_L1;
23
24// Instantiate the engine, the system will pick it up automatically
25// Never destroy it to avoid problems with static destruction.
26// The OS will reclaim the memory anyway,
27// TODO: cleanup on QApplication destruction and re-init on QApplication re-creation.
29
30QWasmFileEngineHandler::QWasmFileEngineHandler()
31{
32}
33
37
39{
40 if (!QWasmFileEngineHandler::isWasmFileName(fileName))
41 return {};
42
43 // Check if it's a File or FileSystemFileHandle
44 if (singleton->m_files.contains(fileName)) {
45 qstdweb::File file = singleton->m_files.value(fileName);
46 return std::make_unique<QWasmFileEngine>(fileName, file);
47 } else if (singleton->m_fileSystemFiles.contains(fileName)) {
48 qstdweb::FileSystemFileHandle file = singleton->m_fileSystemFiles.value(fileName);
49 return std::make_unique<QWasmFileEngine>(fileName, file);
50 }
51
52 // Not an error, this function will be called with partial paths like "weblocalfile:/1/"
53 return {};
54}
55
56// Check if this is a wasm filename by checking the URL scheme.
57bool QWasmFileEngineHandler::isWasmFileName(const QString& fileName)
58{
59 return QUrl(fileName).scheme() == wasmlocalfileScheme;
60}
61
62// Creates a wasm filename using the custom URL scheme and a counter.
63QString QWasmFileEngineHandler::makeWasmFileName(const QString &nativeFileName)
64{
65 static std::atomic<uint64_t> sid = 0;
66 const uint64_t id = ++sid;
67 return wasmlocalfileScheme + QStringLiteral(":/%1/%2").arg(id).arg(nativeFileName);
68}
69
70// Extracts the native filename from the custom URL (removes scheme and counter).
71QString QWasmFileEngineHandler::nativeFileName(const QString &wasmFileName)
72{
73 QUrl url(wasmFileName);
74 if (url.scheme() == wasmlocalfileScheme) {
75 QString path = url.path();
76 // Path is "/n/filename", find the second '/' and extract the filename
77 const qsizetype idx = path.indexOf(u'/', 1);
78 if (idx != -1)
79 return path.mid(idx + 1);
80 }
81 return wasmFileName;
82}
83
84// Adds a File to the set of open files. Returns a prefixed wasm file name.
85QString QWasmFileEngineHandler::addFile(qstdweb::File file)
86{
87 QString nativeFileName = QString::fromStdString(file.name());
88 QString wasmFileName = makeWasmFileName(nativeFileName);
89 singleton->m_files.insert(wasmFileName, file);
90 return wasmFileName;
91}
92
93// Adds a FileSystemFileHandle to the set of open files. Returns a prefixed wasm file name.
94QString QWasmFileEngineHandler::addFile(qstdweb::FileSystemFileHandle file)
95{
96 QString nativeFileName = QString::fromStdString(file.name());
97 QString wasmFileName = makeWasmFileName(nativeFileName);
98 singleton->m_fileSystemFiles.insert(wasmFileName, file);
99 return wasmFileName;
100}
101
102// Removes a File or FileSystemFileHandle from the set of open file handlers
103void QWasmFileEngineHandler::removeFile(const QString fileName)
104{
105 singleton->m_files.remove(fileName);
106 singleton->m_fileSystemFiles.remove(fileName);
107}
108
110{
111 return singleton->m_files.value(fileName);
112}
113
115{
116 return singleton->m_fileSystemFiles.value(fileName);
117}
118
119/*!
120 \class QWasmFileEngine
121 \brief The QWasmFileEngine class provides a QAbstractFileEngine
122 for files that has the prefix ':weblocalfile/'.
123*/
124
125// Constructs a QWasmFileEngine with a File for read-only access
126QWasmFileEngine::QWasmFileEngine(const QString &fileName, qstdweb::File file)
129{
130 // TODO use m_blobDevice in unbuffered mode? if there is already a buffer higher up.
131}
132
133// Constructs a QWasmFileEngine with a FileSystemFileHandle for read-write access
134QWasmFileEngine::QWasmFileEngine(const QString &fileName, qstdweb::FileSystemFileHandle file)
137{
138
139}
140
145
146bool QWasmFileEngine::open(QIODevice::OpenMode openMode, std::optional<QFile::Permissions> permissions)
147{
148 Q_UNUSED(permissions);
149 m_openMode = openMode;
150
151 if (m_fileDevice)
152 return m_fileDevice->open(openMode);
153 else if (m_blobDevice)
154 return m_blobDevice->open(openMode);
155
156 return false;
157}
158
160{
161 if (m_openMode == QIODevice::NotOpen)
162 return false;
163
164 bool success = true;
165 if (m_fileDevice) {
166 m_fileDevice->close();
167 }
168 if (m_blobDevice) {
169 m_blobDevice->close();
170 }
171
172 m_openMode = QIODevice::NotOpen;
173 return success;
174}
175
177{
178 return true;
179}
180
182{
183 return true;
184}
185
187{
188 if (m_fileDevice)
189 return m_fileDevice->size();
190 if (m_blobDevice)
191 return m_blobDevice->size();
192 return 0;
193}
194
196{
197 if (m_fileDevice)
198 return m_fileDevice->pos();
199 if (m_blobDevice)
200 return m_blobDevice->pos();
201 return 0;
202}
203
204bool QWasmFileEngine::seek(qint64 pos)
205{
206 if (m_fileDevice)
207 return m_fileDevice->seek(pos);
208 if (m_blobDevice)
209 return m_blobDevice->seek(pos);
210 return false;
211}
212
214{
215 return false;
216}
217
219{
220 return false;
221}
222
223bool QWasmFileEngine::copy(const QString &newName)
224{
225 Q_UNUSED(newName);
226 return false;
227}
228
229bool QWasmFileEngine::rename(const QString &newName)
230{
231 Q_UNUSED(newName);
232 return false;
233}
234
235bool QWasmFileEngine::renameOverwrite(const QString &newName)
236{
237 Q_UNUSED(newName);
238 return false;
239}
240
241bool QWasmFileEngine::link(const QString &newName)
242{
243 Q_UNUSED(newName);
244 return false;
245}
246
247bool QWasmFileEngine::mkdir(const QString &dirName, bool createParentDirectories,
248 std::optional<QFile::Permissions> permissions) const
249{
250 Q_UNUSED(dirName);
251 Q_UNUSED(createParentDirectories);
252 Q_UNUSED(permissions);
253 return false;
254}
255
256bool QWasmFileEngine::rmdir(const QString &dirName, bool recurseParentDirectories) const
257{
258 Q_UNUSED(dirName);
259 Q_UNUSED(recurseParentDirectories);
260 return false;
261}
262
263bool QWasmFileEngine::setSize(qint64 size)
264{
265 Q_UNUSED(size);
266 return false;
267}
268
270{
271 return true;
272}
273
275{
276 return false;
277}
278
279
281{
282 return type & (QAbstractFileEngine::FileFlag::ExistsFlag |
283 QAbstractFileEngine::FileFlag::FileType |
284 QAbstractFileEngine::FileFlag::ReadOwnerPerm |
285 QAbstractFileEngine::FileFlag::WriteOwnerPerm |
286 QAbstractFileEngine::FileFlag::ReadUserPerm |
287 QAbstractFileEngine::FileFlag::WriteUserPerm);
288}
289
291{
292 Q_UNUSED(perms);
293 return false;
294}
295
297{
298 return {};
299}
300
301QString QWasmFileEngine::fileName(FileName file) const
302{
303 switch (file) {
304 case DefaultName:
305 case AbsoluteName:
306 case CanonicalName:
307 return m_fileName;
308 case BaseName: {
309 QString native = QWasmFileEngineHandler::nativeFileName(m_fileName);
310 QFileInfo info(native);
311 return info.fileName();
312 }
313 case PathName:
314 case AbsolutePathName:
315 case CanonicalPathName: {
316 QString native = QWasmFileEngineHandler::nativeFileName(m_fileName);
317 QFileInfo info(native);
318 QString path = info.path();
319 return path.isEmpty() ? "."_L1 : path;
320 }
321 default:
322 return QString();
323 }
324}
325
327{
328 return 0;
329}
330
332{
333 return {};
334}
335
336bool QWasmFileEngine::setFileTime(const QDateTime &newDate, QFile::FileTime time)
337{
338 Q_UNUSED(newDate);
339 Q_UNUSED(time);
340 return false;
341}
342
343QDateTime QWasmFileEngine::fileTime(QFile::FileTime time) const
344{
345 Q_UNUSED(time);
346 return {};
347}
348
349void QWasmFileEngine::setFileName(const QString &file)
350{
351 if (m_fileName == file)
352 return;
353 close();
354 m_fileName = file;
355}
356
358{
359 return -1;
360}
361
363{
364 Q_UNUSED(target);
365 return QAbstractFileEngine::TriStateResult::NotSupported;
366}
367
368QAbstractFileEngine::IteratorUniquePtr QWasmFileEngine::beginEntryList(const QString &path, QDirListing::IteratorFlags filters,
369 const QStringList &filterNames)
370{
371 Q_UNUSED(path);
372 Q_UNUSED(filters);
373 Q_UNUSED(filterNames);
374 return nullptr;
375}
376
377qint64 QWasmFileEngine::read(char *data, qint64 maxlen)
378{
379 if (!(m_openMode & QIODevice::ReadOnly))
380 return -1;
381
382 if (m_fileDevice)
383 return m_fileDevice->read(data, maxlen);
384 if (m_blobDevice)
385 return m_blobDevice->read(data, maxlen);
386 return -1;
387}
388
389qint64 QWasmFileEngine::readLine(char *data, qint64 maxlen)
390{
391 if (!(m_openMode & QIODevice::ReadOnly))
392 return -1;
393
394 if (m_fileDevice)
395 return m_fileDevice->readLine(data, maxlen);
396 if (m_blobDevice)
397 return m_blobDevice->readLine(data, maxlen);
398 return -1;
399}
400
401qint64 QWasmFileEngine::write(const char *data, qint64 len)
402{
403 if (!(m_openMode & QIODevice::WriteOnly))
404 return -1;
405
406 if (m_fileDevice)
407 return m_fileDevice->write(data, len);
408 return -1;
409}
410
411bool QWasmFileEngine::extension(Extension extension, const ExtensionOption *option, ExtensionReturn *output)
412{
413 Q_UNUSED(extension);
414 Q_UNUSED(option);
415 Q_UNUSED(output);
416 return false;
417}
418
419bool QWasmFileEngine::supportsExtension(Extension extension) const
420{
421 Q_UNUSED(extension);
422 return false;
423}
424
425QT_END_NAMESPACE
qstdweb::FileSystemFileHandle getFileSystemFile(const QString fileName)
virtual ~QWasmFileEngineHandler() override
virtual std::unique_ptr< QAbstractFileEngine > create(const QString &fileName) const override
If this file handler can handle fileName, this method creates a file engine and returns it wrapped in...
qstdweb::File getFile(const QString fileName)
The QWasmFileEngine class provides a QAbstractFileEngine for files that has the prefix ':weblocalfile...
virtual bool link(const QString &newName) override
Creates a link from the file currently specified by fileName() to newName.
virtual bool flush() override
Flushes the open file, returning true if successful; otherwise returns false.
virtual qint64 read(char *data, qint64 maxlen) override
Reads a number of characters from the file into data.
virtual void setFileName(const QString &file) override
Sets the file engine's file name to file.
virtual bool rmdir(const QString &dirName, bool recurseParentDirectories) const override
Requests that the directory dirName is deleted from the file system.
virtual bool setSize(qint64 size) override
Requests that the file be set to size size.
virtual bool copy(const QString &newName) override
Copies the contents of this file to a file with the name newName.
virtual uint ownerId(FileOwner) const override
If owner is OwnerUser return the ID of the user who owns the file.
virtual bool caseSensitive() const override
Should return true if the underlying file system is case-sensitive; otherwise return false.
virtual QString fileName(FileName file=DefaultName) const override
Return the file engine's current file name in the format specified by file.
virtual qint64 pos() const override
Returns the current file position.
virtual bool supportsExtension(Extension extension) const override
virtual bool extension(Extension extension, const ExtensionOption *option=nullptr, ExtensionReturn *output=nullptr) override
virtual bool close() override
Closes the file, returning true if successful; otherwise returns false.
virtual bool isSequential() const override
Returns true if the file is a sequential access device; returns false if the file is a direct access ...
virtual bool syncToDisk() override
virtual bool seek(qint64 pos) override
Sets the file position to the given offset.
virtual qint64 write(const char *data, qint64 len) override
Writes len bytes from data to the file.
virtual TriStateResult cloneTo(QAbstractFileEngine *target) override
virtual bool rename(const QString &newName) override
Requests that the file be renamed to newName in the file system.
virtual QByteArray id() const override
virtual QString owner(FileOwner) const override
If owner is OwnerUser return the name of the user who owns the file.
virtual qint64 readLine(char *data, qint64 maxlen) override
This function reads one line, terminated by a '\n' character, from the file info data.
virtual bool setPermissions(uint perms) override
Requests that the file's permissions be set to perms.
virtual int handle() const override
Returns the native file handle for this file engine.
virtual bool remove() override
Requests that the file is deleted from the file system.
virtual IteratorUniquePtr beginEntryList(const QString &path, QDirListing::IteratorFlags filters, const QStringList &filterNames) override
Returns a QAbstractFileEngine::IteratorUniquePtr, that can be used to iterate over the entries in pat...
virtual FileFlags fileFlags(FileFlags type=FileInfoAll) const override
This function should return the set of OR'd flags that are true for the file engine's file,...
virtual bool mkdir(const QString &dirName, bool createParentDirectories, std::optional< QFile::Permissions > permissions=std::nullopt) const override
Requests that the directory dirName be created with the specified permissions.
virtual qint64 size() const override
Returns the size of the file.
QWasmFileEngine(const QString &fileName, qstdweb::File file)
virtual bool renameOverwrite(const QString &newName) override
virtual bool isRelativePath() const override
Return true if the file referred to by this file engine has a relative path; otherwise return false.
virtual QDateTime fileTime(QFile::FileTime time) const override
If time is BirthTime, return when the file was born (created).
virtual bool setFileTime(const QDateTime &newDate, QFile::FileTime time) override
Combined button and popup list for selecting options.
static constexpr QLatin1StringView wasmlocalfileScheme