summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBe <be@mixxx.org>2020-12-05 02:14:11 -0600
committerBe <be@mixxx.org>2020-12-05 19:23:15 -0600
commitb66dd0195157908691a649ec4403403fe8f0319a (patch)
treee0600ace96f51f73248d0de635e1a0083c7b7006 /src
parentb5e172912d87e3dd5f09c4794fbacaa38e4d5884 (diff)
migrate old settings path into sandbox on macOS
Diffstat (limited to 'src')
-rw-r--r--src/main.cpp9
-rw-r--r--src/mixxx.cpp18
-rw-r--r--src/util/sandbox.cpp86
-rw-r--r--src/util/sandbox.h2
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 3f3a4bfa07..6166b95797 100644
--- a/src/mixxx.cpp
+++ b/src/mixxx.cpp
@@ -168,6 +168,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;