summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTor Arne Vestbø <tor.arne.vestbo@qt.io>2018-06-06 16:51:00 +0200
committerJani Heikkinen <jani.heikkinen@qt.io>2018-06-14 04:21:24 +0000
commita93d29198a506b385a006e22538a24c2450c5278 (patch)
treeaf1e608ffb9540239daf2f70fd514c7f19a6639c
parent67227aeffdf94be8d177309d27291d5b3247586c (diff)
Access private properties via sandbox-safe API on Apple OSes
We detect whether or not we're running inside a sandbox and bail out if so. We use runtime lookup of the property, so that static analysis of the application will not mistakenly think we're using the API in sandboxed situations. Change-Id: I5f5c42f5a4a44b62de061d945b62ac63167ece09 Reviewed-by: Gabriel de Dietrich <gabriel.dedietrich@qt.io>
-rw-r--r--src/corelib/kernel/kernel.pri2
-rw-r--r--src/corelib/kernel/qcore_mac_objc.mm37
-rw-r--r--src/corelib/kernel/qcore_mac_p.h11
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm31
4 files changed, 57 insertions, 24 deletions
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index ca8bd30698..c528b16f9c 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -120,7 +120,7 @@ mac {
LIBS_PRIVATE += -framework Foundation
- osx: LIBS_PRIVATE += -framework CoreServices -framework AppKit
+ osx: LIBS_PRIVATE += -framework CoreServices -framework AppKit -framework Security
ios|tvos {
# We need UIKit for UIApplication in qeventdispatcher_cf.mm
diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm
index 7263d81228..6b11e90a4e 100644
--- a/src/corelib/kernel/qcore_mac_objc.mm
+++ b/src/corelib/kernel/qcore_mac_objc.mm
@@ -193,6 +193,43 @@ AppleApplication *qt_apple_sharedApplication()
}
#endif
+#if defined(Q_OS_MACOS) && !defined(QT_BOOTSTRAPPED)
+bool qt_apple_isSandboxed()
+{
+ static bool isSandboxed = []() {
+ QCFType<SecStaticCodeRef> staticCode = nullptr;
+ NSURL *bundleUrl = [[NSBundle mainBundle] bundleURL];
+ if (SecStaticCodeCreateWithPath((__bridge CFURLRef)bundleUrl,
+ kSecCSDefaultFlags, &staticCode) != errSecSuccess)
+ return false;
+
+ QCFType<SecRequirementRef> sandboxRequirement;
+ if (SecRequirementCreateWithString(CFSTR("entitlement[\"com.apple.security.app-sandbox\"] exists"),
+ kSecCSDefaultFlags, &sandboxRequirement) != errSecSuccess)
+ return false;
+
+ if (SecStaticCodeCheckValidityWithErrors(staticCode,
+ kSecCSBasicValidateOnly, sandboxRequirement, nullptr) != errSecSuccess)
+ return false;
+
+ return true;
+ }();
+ return isSandboxed;
+}
+
+QT_END_NAMESPACE
+@implementation NSObject (QtSandboxHelpers)
+- (id)qt_valueForPrivateKey:(NSString *)key
+{
+ if (qt_apple_isSandboxed())
+ return nil;
+
+ return [self valueForKey:key];
+}
+@end
+QT_BEGIN_NAMESPACE
+#endif
+
#ifdef Q_OS_MACOS
/*
Ensure that Objective-C objects auto-released in main(), directly or indirectly,
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
index 9bd2e31bc9..af939abaac 100644
--- a/src/corelib/kernel/qcore_mac_p.h
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -160,6 +160,17 @@ QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool);
Q_CORE_EXPORT void qt_apple_check_os_version();
Q_CORE_EXPORT bool qt_apple_isApplicationExtension();
+#if defined(Q_OS_MACOS) && !defined(QT_BOOTSTRAPPED)
+Q_CORE_EXPORT bool qt_apple_isSandboxed();
+# ifdef __OBJC__
+QT_END_NAMESPACE
+@interface NSObject (QtSandboxHelpers)
+- (id)qt_valueForPrivateKey:(NSString *)key;
+@end
+QT_BEGIN_NAMESPACE
+# endif
+#endif
+
#if !defined(QT_BOOTSTRAPPED) && !defined(Q_OS_WATCHOS)
QT_END_NAMESPACE
# if defined(Q_OS_MACOS)
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index 5999163c91..2d212bfe3b 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -248,24 +248,6 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QVerticalSplitView);
}
@end
-#if !QT_CONFIG(appstore_compliant)
-
-// This API was requested to Apple in rdar #36197888.
-// We know it's safe to use up to macOS 10.13.3.
-// See drawComplexControl(CC_ComboBox) for its usage.
-
-@interface NSComboBoxCell (QtButtonCell)
-@property (readonly) NSButtonCell *qt_buttonCell;
-@end
-
-@implementation NSComboBoxCell (QtButtonCell)
-- (NSButtonCell *)qt_buttonCell {
- return self->_buttonCell;
-}
-@end
-
-#endif
-
QT_BEGIN_NAMESPACE
// The following constants are used for adjusting the size
@@ -5215,11 +5197,14 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
auto *cb = static_cast<NSComboBox *>(cc);
const auto frameRect = cw.adjustedControlFrame(combo->rect);
cb.frame = frameRect.toCGRect();
-#if !QT_CONFIG(appstore_compliant)
- static_cast<NSComboBoxCell *>(cc.cell).qt_buttonCell.highlighted = isPressed;
-#else
- // TODO Render to pixmap and darken the button manually
-#endif
+
+ // This API was requested to Apple in rdar #36197888. We know it's safe to use up to macOS 10.13.3
+ if (NSButtonCell *cell = static_cast<NSButtonCell *>([cc.cell qt_valueForPrivateKey:@"_buttonCell"])) {
+ cell.highlighted = isPressed;
+ } else {
+ // TODO Render to pixmap and darken the button manually
+ }
+
d->drawNSViewInRect(cb, frameRect, p, ^(CGContextRef __unused ctx, const CGRect &r) {
// FIXME This is usually drawn in the control's superview, but we wouldn't get inactive look in this case
[cb.cell drawWithFrame:r inView:cb];