diff options
author | Uwe Klotz <uklotz@mixxx.org> | 2020-12-07 22:36:19 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-07 22:36:19 +0100 |
commit | b45acb4d287660d3fb2c57b95d7179692ce09e13 (patch) | |
tree | 2506f1bd201acf0970117dc137608389feedbda2 /src | |
parent | 21461e28592d1f0de140e60c66651e0854e94414 (diff) | |
parent | b66dd0195157908691a649ec4403403fe8f0319a (diff) |
Merge pull request #3404 from mixxxdj/mac_sandbox_migrate_preferences
migrate old settings path into sandbox on macOS
Diffstat (limited to 'src')
-rw-r--r-- | src/main.cpp | 9 | ||||
-rw-r--r-- | src/mixxx.cpp | 18 | ||||
-rw-r--r-- | src/util/sandbox.cpp | 86 | ||||
-rw-r--r-- | src/util/sandbox.h | 2 |
4 files changed, 106 insertions, 9 deletions
diff --git a/src/main.cpp b/src/main.cpp index 0e3bf3d62e..9828c58462 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -101,17 +101,8 @@ int main(int argc, char * argv[]) { // the main thread. Bug #1748636. ErrorDialogHandler::instance(); - mixxx::Logging::initialize(args.getSettingsPath(), - args.getLogLevel(), - args.getLogFlushLevel(), - args.getDebugAssertBreak()); - MixxxApplication app(argc, argv); - VERIFY_OR_DEBUG_ASSERT(SoundSourceProxy::registerProviders()) { - qCritical() << "Failed to register any SoundSource providers"; - return kFatalErrorOnStartupExitCode; - } #ifdef __APPLE__ QDir dir(QApplication::applicationDirPath()); diff --git a/src/mixxx.cpp b/src/mixxx.cpp index 3f6c23143d..cb8cf7f75d 100644 --- a/src/mixxx.cpp +++ b/src/mixxx.cpp @@ -169,6 +169,24 @@ MixxxMainWindow::MixxxMainWindow(QApplication* pApp, const CmdlineArgs& args) m_runtime_timer.start(); mixxx::Time::start(); + QString settingsPath = args.getSettingsPath(); +#ifdef __APPLE__ + if (!args.getSettingsPathSet()) { + settingsPath = Sandbox::migrateOldSettings(); + } +#endif + + mixxx::Logging::initialize( + settingsPath, + args.getLogLevel(), + args.getLogFlushLevel(), + args.getDebugAssertBreak()); + + VERIFY_OR_DEBUG_ASSERT(SoundSourceProxy::registerProviders()) { + qCritical() << "Failed to register any SoundSource providers"; + return; + } + Version::logBuildDetails(); // Only record stats in developer mode. diff --git a/src/util/sandbox.cpp b/src/util/sandbox.cpp index e229a927fa..d9424114b0 100644 --- a/src/util/sandbox.cpp +++ b/src/util/sandbox.cpp @@ -359,6 +359,92 @@ SecurityTokenPointer Sandbox::openTokenFromBookmark(const QString& canonicalPath return SecurityTokenPointer(); } +QString Sandbox::migrateOldSettings() { + // QStandardPaths::DataLocation returns a different location depending on whether the build + // is signed (and therefore sandboxed with the hardened runtime), so use the absolute path + // that the sandbox uses regardless of whether this build is actually sandboxed. + // Otherwise, developers would need to run with --settingsPath every time or symlink + // to use the same settings directory with signed and unsigned builds. + + // QDir::homePath returns a path inside the sandbox. + QString homePath = QLatin1String("/Users/") + qgetenv("USER"); + + QString sandboxedPath = homePath + + QLatin1String( + "/Library/Containers/org.mixxx.mixxx/Data/Library/Application Support/Mixxx"); + QDir sandboxedSettings(sandboxedPath); + + if (sandboxedSettings.exists() && !sandboxedSettings.isEmpty()) { + return sandboxedPath; + } + + // Because Mixxx cannot test if the old path exists before getting permission to access it + // outside the sandbox, unfortunately it is necessary to annoy the user with this popup + // even if they are installing Mixxx >= 2.3.0 without having installed an old version of Mixxx. + QString title = QObject::tr("Upgrading old Mixxx settings"); + QString oldPath = homePath + QLatin1String("/Library/Application Support/Mixxx"); + QMessageBox::information(nullptr, + title, + QObject::tr( + "Due to Mac sandboxing, Mixxx needs your permission to " + "access your music library " + "and settings from Mixxx versions before 2.3.0. After " + "clicking OK, you will see a file picker. " + "To give Mixxx permission, press the Ok button in the file " + "picker." + "\n\n" + "If you do not want to grant Mixxx access click Cancel on " + "the file picker.")); + QString result = QFileDialog::getExistingDirectory( + nullptr, + title, + oldPath); + if (result != oldPath) { + qInfo() << "Sandbox::migrateOldSettings: User declined to migrate " + "old settings from" + << oldPath << "User selected" << result; + return sandboxedPath; + } + + // Sandbox::askForAccess cannot be used here because it depends on settings being + // initialized. There is no need to store the bookmark anyway because this is a + // one time process. +#ifdef __APPLE__ + CFURLRef url = CFURLCreateWithFileSystemPath( + kCFAllocatorDefault, QStringToCFString(oldPath), kCFURLPOSIXPathStyle, true); + if (url) { + CFErrorRef error = NULL; + CFDataRef bookmark = CFURLCreateBookmarkData( + kCFAllocatorDefault, + url, + kCFURLBookmarkCreationWithSecurityScope, + nil, + nil, + &error); + CFRelease(url); + if (bookmark) { + QFile oldSettings(oldPath); + if (oldSettings.rename(sandboxedPath)) { + qInfo() << "Sandbox::migrateOldSettings: Successfully " + "migrated old settings from" + << oldPath << "to new path" << sandboxedPath; + } else { + qWarning() << "Sandbox::migrateOldSettings: Failed to migrate " + "old settings from" + << oldPath << "to new path" << sandboxedPath; + } + } else { + qWarning() << "Sandbox::migrateOldSettings: Failed to access old " + "settings path" + << oldPath << "Cannot migrate to new path" + << sandboxedPath; + } + CFRelease(bookmark); + } +#endif + return sandboxedPath; +} + #ifdef __APPLE__ SandboxSecurityToken::SandboxSecurityToken(const QString& path, CFURLRef url) : m_path(path), diff --git a/src/util/sandbox.h b/src/util/sandbox.h index 404a093bed..4076a44c1e 100644 --- a/src/util/sandbox.h +++ b/src/util/sandbox.h @@ -32,6 +32,8 @@ class Sandbox { static void initialize(const QString& permissionsFile); static void shutdown(); + static QString migrateOldSettings(); + // Returns true if we are in a sandbox. static bool enabled() { return s_bInSandbox; |