summaryrefslogtreecommitdiffstats
path: root/src/corelib/io
diff options
context:
space:
mode:
authorPasi Matilainen <pasi.matilainen@digia.com>2012-03-02 13:06:08 (GMT)
committerQt by Nokia <qt-info@nokia.com>2012-03-07 23:40:08 (GMT)
commit41ba5997bba81e225dbc449bb60ac86d88ed7fe3 (patch)
treeb310e0f1d69b3cd8fd4f148848ef11d85cf892d9 /src/corelib/io
parent0ef9762bbb176c842a90bc5aaad49a7f2b054ad6 (diff)
downloadQt-41ba5997bba81e225dbc449bb60ac86d88ed7fe3.zip
Qt-41ba5997bba81e225dbc449bb60ac86d88ed7fe3.tar.gz
Qt-41ba5997bba81e225dbc449bb60ac86d88ed7fe3.tar.bz2
Enable storage of global Qt settings in app-local settings file on Mac
The Mac App Store has limitations on where applications can write their settings, and com.trolltech.plist is not allowed. Changed the settings code to store all settings in the app-local file when the application runs in sandbox, or when the application's Info.plist contains a key "ForAppStore" with value "yes". The application's bundle identifier is also used for naming the settings file in these cases. Task-number: QTBUG-16549 Change-Id: Idd2241fbd7eb346da987226f05460642b0d6e5a3 Reviewed-by: Morten Johan Sørvig <morten.sorvig@nokia.com>
Diffstat (limited to 'src/corelib/io')
-rw-r--r--src/corelib/io/qsettings_mac.cpp82
1 files changed, 82 insertions, 0 deletions
diff --git a/src/corelib/io/qsettings_mac.cpp b/src/corelib/io/qsettings_mac.cpp
index 6d0af2a..3e3189e 100644
--- a/src/corelib/io/qsettings_mac.cpp
+++ b/src/corelib/io/qsettings_mac.cpp
@@ -45,6 +45,13 @@
#include "qdir.h"
#include "qvarlengtharray.h"
#include "private/qcore_mac_p.h"
+#ifndef QT_BOOTSTRAPPED
+#include "qcoreapplication.h"
+#endif
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+#include <Security/SecCode.h>
+#include <Security/SecRequirement.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -343,6 +350,7 @@ class QMacSettingsPrivate : public QSettingsPrivate
public:
QMacSettingsPrivate(QSettings::Scope scope, const QString &organization,
const QString &application);
+ QMacSettingsPrivate(CFStringRef bundleIdentifier);
~QMacSettingsPrivate();
void remove(const QString &key);
@@ -423,6 +431,22 @@ QMacSettingsPrivate::QMacSettingsPrivate(QSettings::Scope scope, const QString &
sync();
}
+QMacSettingsPrivate::QMacSettingsPrivate(CFStringRef bundleIdentifier)
+ : QSettingsPrivate(QSettings::NativeFormat, QSettings::UserScope, QString(), QString())
+{
+ // applicationId and suiteId are QCFStrings and take ownership, retain to prevent double deletes.
+ CFRetain(bundleIdentifier);
+ applicationId = bundleIdentifier;
+ CFRetain(bundleIdentifier);
+ suiteId = bundleIdentifier;
+
+ numDomains = 1;
+ domains[0].userName = kCFPreferencesCurrentUser;
+ domains[0].applicationOrSuiteId = bundleIdentifier;
+ hostName = kCFPreferencesAnyHost;
+ sync();
+}
+
QMacSettingsPrivate::~QMacSettingsPrivate()
{
}
@@ -579,6 +603,64 @@ QSettingsPrivate *QSettingsPrivate::create(QSettings::Format format,
const QString &organization,
const QString &application)
{
+#ifndef QT_BOOTSTRAPPED
+ static bool useAppLocalStorage = false;
+ static bool initialized = false;
+
+ if (!initialized) {
+ bool inSandbox = false;
+
+#if __MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
+ // If we are running on at least 10.7.0 and have the com.apple.security.app-sandbox
+ // entitlement, we are in a sandbox
+ SInt32 version = 0;
+ Gestalt(gestaltSystemVersion, &version);
+ SecCodeRef secCodeSelf;
+ if (version >= 0x1070 && SecCodeCopySelf(kSecCSDefaultFlags, &secCodeSelf) == errSecSuccess) {
+ SecRequirementRef sandboxReq;
+ CFStringRef entitlement = CFSTR("entitlement [\"com.apple.security.app-sandbox\"]");
+ if (SecRequirementCreateWithString(entitlement, kSecCSDefaultFlags, &sandboxReq) == errSecSuccess) {
+ if (SecCodeCheckValidity(secCodeSelf, kSecCSDefaultFlags, sandboxReq) == errSecSuccess)
+ inSandbox = true;
+ CFRelease(sandboxReq);
+ }
+ CFRelease(secCodeSelf);
+ }
+#endif
+
+ bool forAppStore = false;
+ if (!inSandbox) {
+ CFTypeRef val = CFBundleGetValueForInfoDictionaryKey(CFBundleGetMainBundle(), CFSTR("ForAppStore"));
+ forAppStore = (val &&
+ CFGetTypeID(val) == CFStringGetTypeID() &&
+ CFStringCompare(CFStringRef(val), CFSTR("yes"), kCFCompareCaseInsensitive) == 0);
+ }
+
+ useAppLocalStorage = inSandbox || forAppStore;
+ initialized = true;
+ }
+
+ if (useAppLocalStorage) {
+ // Ensure that the global and app-local settings go to the same file, since that's
+ // what we really want
+ if (organization == QLatin1String("Trolltech") ||
+ organization.isEmpty() ||
+ (organization == qApp->organizationDomain() && application == qApp->applicationName()) ||
+ (organization == qApp->organizationName()) && application == qApp->applicationName())
+ {
+ CFStringRef bundleIdentifier = CFBundleGetIdentifier(CFBundleGetMainBundle());
+ if (!bundleIdentifier) {
+ qWarning("QSettingsPrivate::create: You must set the bundle identifier when using ForAppStore");
+ } else {
+ QSettingsPrivate* settings = new QMacSettingsPrivate(bundleIdentifier);
+ if (organization == QLatin1String("Trolltech"))
+ settings->beginGroupOrArray(QSettingsGroup("QtLibrarySettings"));
+ return settings;
+ }
+ }
+ }
+#endif
+
if (format == QSettings::NativeFormat) {
return new QMacSettingsPrivate(scope, organization, application);
} else {