268 QMacAutoReleasePool pool;
270 NSURL *savedBookmarks = bookmarksFile();
271 if ([NSFileManager.defaultManager fileExistsAtPath:savedBookmarks.path]) {
272 NSError *error =
nullptr;
273 m_bookmarks = [[NSDictionary dictionaryWithContentsOfURL:savedBookmarks
274 error:&error] mutableCopy];
277 qCWarning(lcSecEngine) <<
"Failed to load bookmarks from"
278 << savedBookmarks <<
":" << error;
280 qCInfo(lcSecEngine) <<
"Loaded existing bookmarks for" << m_bookmarks.allKeys;
285 m_bookmarks = [NSMutableDictionary
new];
295 QMacAutoReleasePool pool;
299 if (![url startAccessingSecurityScopedResource])
302 if (checkIfResourceIsReachable(url)) {
314 qCInfo(lcSecEngine) <<
"Resource is not reachable."
315 <<
"Registering URL" << url <<
"instead";
316 QWriteLocker locker(&m_bookmarkLock);
317 m_bookmarks[cacheKeyForUrl(url)] = url;
321 [url stopAccessingSecurityScopedResource];
323#if defined(Q_OS_MACOS)
330 [url stopAccessingSecurityScopedResource];
336 QMacAutoReleasePool pool;
338 static thread_local bool recursionGuard =
false;
342 if (fileName.isEmpty())
345 QFileSystemEntry fileSystemEntry(fileName);
346 QFileSystemMetaData metaData;
353 QScopedValueRollback<
bool> rollback(recursionGuard,
true);
354 if (
auto engine = QFileSystemEngine::createLegacyEngine(fileSystemEntry, metaData)) {
357 qCDebug(lcSecEngine) <<
"Preferring non-QFSFileEngine engine"
358 << engine.get() <<
"for" << fileName;
366 auto canonicalEntry = QFileSystemEngine::canonicalName(fileSystemEntry, metaData);
367 if (canonicalEntry.isEmpty())
368 canonicalEntry = QFileSystemEngine::absoluteName(fileSystemEntry);
370 if (canonicalEntry.isRelative()) {
380 qCWarning(lcSecEngine) <<
"Could not resolve" << fileSystemEntry.filePath()
381 <<
"against current working working directory";
386 QString filePath = QDir::cleanPath(canonicalEntry.filePath());
389 static const QString sandboxRoot = QString::fromNSString(NSHomeDirectory());
390 if (filePath.startsWith(sandboxRoot))
394 static const QString bundleRoot = QString::fromNSString(NSBundle.mainBundle.bundlePath);
395 if (filePath.startsWith(bundleRoot))
398 qCDebug(lcSecEngine) <<
"Looking up bookmark for" << filePath <<
"based on incoming fileName" << fileName;
403 QReadLocker locker(&m_bookmarkLock);
404 auto *cacheKey = cacheKeyForPath(filePath);
405 NSObject *bookmarkData =
nullptr;
406 while (cacheKey.length > 1) {
407 bookmarkData = m_bookmarks[cacheKey];
410 cacheKey = [cacheKey stringByDeletingLastPathComponent];
416 qCDebug(lcSecEngine) <<
"No bookmark found. Falling back to QFSFileEngine.";
420 NSURL *securityScopedUrl =
nullptr;
421 if ([bookmarkData isKindOfClass:NSURL.
class]) {
422 securityScopedUrl =
static_cast<NSURL*>(bookmarkData);
424 NSError *error =
nullptr;
425 BOOL bookmarkDataIsStale = NO;
426 securityScopedUrl = [NSURL URLByResolvingBookmarkData:
static_cast<NSData*>(bookmarkData)
428 #if defined(Q_OS_MACOS)
429 NSURLBookmarkResolutionWithSecurityScope
433 NSURLBookmarkResolutionOptions(0)
436 bookmarkDataIsStale:&bookmarkDataIsStale
439 if (!securityScopedUrl || error) {
440 qCWarning(lcSecEngine) <<
"Failed to resolve bookmark data for"
441 << fileName <<
":" << error;
445 if (bookmarkDataIsStale) {
451 qCDebug(lcSecEngine) <<
"Bookmark for" << cacheKey <<
"was stale";
453 QWriteLocker writeLocker(&m_bookmarkLock);
454 [m_bookmarks removeObjectForKey:cacheKey];
455 auto *mutableThis =
const_cast<SecurityScopedFileEngineHandler*>(
this);
456 mutableThis->saveBookmarks();
461 qCInfo(lcSecEngine) <<
"Resolved security scope" << securityScopedUrl
462 <<
"for path" << filePath;
463 return std::make_unique<SecurityScopedFileEngine>(fileName, securityScopedUrl);