diff --git a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h index 9c94b8f3d9..33fa4ad710 100644 --- a/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h +++ b/extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h @@ -75,6 +75,8 @@ public: iPadScreenOrientationValue (settings, Ids::iPadScreenOrientation, getUndoManager(), "portraitlandscape"), customXcodeResourceFoldersValue (settings, Ids::customXcodeResourceFolders, getUndoManager()), customXcassetsFolderValue (settings, Ids::customXcassetsFolder, getUndoManager()), + appSandboxValue (settings, Ids::appSandbox, getUndoManager()), + appSandboxOptionsValue (settings, Ids::appSandboxOptions, getUndoManager(), Array(), ","), hardenedRuntimeValue (settings, Ids::hardenedRuntime, getUndoManager()), hardenedRuntimeOptionsValue (settings, Ids::hardenedRuntimeOptions, getUndoManager(), Array(), ","), microphonePermissionNeededValue (settings, Ids::microphonePermissionNeeded, getUndoManager()), @@ -143,6 +145,9 @@ public: bool isHardenedRuntimeEnabled() const { return hardenedRuntimeValue.get(); } Array getHardenedRuntimeOptions() const { return *hardenedRuntimeOptionsValue.get().getArray(); } + bool isAppSandboxEnabled() const { return appSandboxValue.get(); } + Array getAppSandboxOptions() const { return *appSandboxOptionsValue.get().getArray(); } + bool isMicrophonePermissionEnabled() const { return microphonePermissionNeededValue.get(); } String getMicrophonePermissionsTextString() const { return microphonePermissionsTextValue.get(); } @@ -276,40 +281,86 @@ public: if (isOSX()) { + props.add (new ChoicePropertyComponent (appSandboxValue, "Use App Sandbox"), + "Enable this to use the app sandbox."); + + std::vector> sandboxOptions + { + { "Network: Incoming Connections (Server)", "network.server" }, + { "Network: Outgoing Connections (Client)", "network.client" }, + + { "Hardware: Camera", "device.camera" }, + { "Hardware: Microphone", "device.microphone" }, + { "Hardware: USB", "device.usb" }, + { "Hardware: Printing", "print" }, + { "Hardware: Bluetooth", "device.bluetooth" }, + + { "App Data: Contacts", "personal-information.addressbook" }, + { "App Data: Location", "personal-information.location" }, + { "App Data: Calendar", "personal-information.calendars" }, + + { "File Access: User Selected File (Read Only)", "files.user-selected.read-only" }, + { "File Access: User Selected File (Read/Write)", "files.user-selected.read-write" }, + { "File Access: Downloads Folder (Read Only)", "files.downloads.read-only" }, + { "File Access: Downloads Folder (Read/Write)", "files.downloads.read-write" }, + { "File Access: Pictures Folder (Read Only)", "files.pictures.read-only" }, + { "File Access: Pictures Folder (Read/Write)", "files.pictures.read-write" }, + { "File Access: Music Folder (Read Only)", "assets.music.read-only" }, + { "File Access: Music Folder (Read/Write)", "assets.music.read-write" }, + { "File Access: Movies Folder (Read Only)", "assets.movies.read-only" }, + { "File Access: Movies Folder (Read/Write)", "assets.movies.read-write" } + }; + + StringArray sandboxKeys; + Array sanboxValues; + + for (auto& opt : sandboxOptions) + { + sandboxKeys.add (opt.first); + sanboxValues.add ("com.apple.security." + opt.second); + } + + props.add (new MultiChoicePropertyComponentWithEnablement (appSandboxOptionsValue, + appSandboxValue, + "App Sandbox Options", + sandboxKeys, + sanboxValues)); + props.add (new ChoicePropertyComponent (hardenedRuntimeValue, "Use Hardened Runtime"), "Enable this to use the hardened runtime required for app notarization."); - std::vector> options - { - { "Allow Execution of JIT-compiled Code", "cs.allow-jit" }, - { "Allow Unsigned Executable Memory", "cs.allow-unsigned-executable-memory" }, - { "Allow DYLD Environment Variables", "cs.allow-dyld-environment-variables" }, - { "Disable Library Validation", "cs.disable-library-validation" }, - { "Disable Executable Memory Protection", "cs.disable-executable-page-protection" }, - { "Debugging Tool", "cs.debugger" }, - { "Audio Input", "device.audio-input" }, - { "Camera", "device.camera" }, - { "Location", "personal-information.location" }, - { "Address Book", "personal-information.addressbook" }, - { "Calendar", "personal-information.calendars" }, - { "Photos Library", "personal-information.photos-library" }, - { "Apple Events", "automation.apple-events" }, + std::vector> hardeningOptions + { + { "Runtime Exceptions: Allow Execution of JIT-compiled Code", "cs.allow-jit" }, + { "Runtime Exceptions: Allow Unsigned Executable Memory", "cs.allow-unsigned-executable-memory" }, + { "Runtime Exceptions: Allow DYLD Environment Variables", "cs.allow-dyld-environment-variables" }, + { "Runtime Exceptions: Disable Library Validation", "cs.disable-library-validation" }, + { "Runtime Exceptions: Disable Executable Memory Protection", "cs.disable-executable-page-protection" }, + { "Runtime Exceptions: Debugging Tool", "cs.debugger" }, + + { "Resource Access: Audio Input", "device.audio-input" }, + { "Resource Access: Camera", "device.camera" }, + { "Resource Access: Location", "personal-information.location" }, + { "Resource Access: Address Book", "personal-information.addressbook" }, + { "Resource Access: Calendar", "personal-information.calendars" }, + { "Resource Access: Photos Library", "personal-information.photos-library" }, + { "Resource Access: Apple Events", "automation.apple-events" } }; - StringArray keys; - Array values; + StringArray hardeningKeys; + Array hardeningValues; - for (auto& opt : options) + for (auto& opt : hardeningOptions) { - keys.add (opt.first); - values.add ("com.apple.security." + opt.second); + hardeningKeys.add (opt.first); + hardeningValues.add ("com.apple.security." + opt.second); } props.add (new MultiChoicePropertyComponentWithEnablement (hardenedRuntimeOptionsValue, hardenedRuntimeValue, "Hardened Runtime Options", - keys, - values)); + hardeningKeys, + hardeningValues)); } props.add (new ChoicePropertyComponent (microphonePermissionNeededValue, "Microphone Access"), @@ -1009,20 +1060,21 @@ public: auto attributes = getID() + " = { "; auto developmentTeamID = owner.getIosDevelopmentTeamIDString(); + if (developmentTeamID.isNotEmpty()) { attributes << "DevelopmentTeam = " << developmentTeamID << "; "; attributes << "ProvisioningStyle = Automatic; "; } - auto appGroupsEnabled = (owner.iOS && owner.isAppGroupsEnabled() ? 1 : 0); + auto appGroupsEnabled = (owner.iOS && owner.isAppGroupsEnabled()) ? 1 : 0; auto inAppPurchasesEnabled = owner.isInAppPurchasesEnabled() ? 1 : 0; auto interAppAudioEnabled = (owner.iOS && type == Target::StandalonePlugIn && owner.getProject().shouldEnableIAA()) ? 1 : 0; auto pushNotificationsEnabled = owner.isPushNotificationsEnabled() ? 1 : 0; - auto sandboxEnabled = (type == Target::AudioUnitv3PlugIn ? 1 : 0); + auto sandboxEnabled = ((type == Target::AudioUnitv3PlugIn) | owner.isAppSandboxEnabled()) ? 1 : 0; auto hardendedRuntimeEnabled = owner.isHardenedRuntimeEnabled() ? 1 : 0; attributes << "SystemCapabilities = {"; @@ -1077,6 +1129,7 @@ public: { if (owner.isPushNotificationsEnabled() || owner.isAppGroupsEnabled() + || owner.isAppSandboxEnabled() || owner.isHardenedRuntimeEnabled() || (owner.isiOS() && owner.isiCloudPermissionsEnabled())) return true; @@ -1884,6 +1937,7 @@ private: postbuildCommandValue, prebuildCommandValue, duplicateAppExResourcesFolderValue, iosDeviceFamilyValue, iPhoneScreenOrientationValue, iPadScreenOrientationValue, customXcodeResourceFoldersValue, customXcassetsFolderValue, + appSandboxValue, appSandboxOptionsValue, hardenedRuntimeValue, hardenedRuntimeOptionsValue, microphonePermissionNeededValue, microphonePermissionsTextValue, cameraPermissionNeededValue, cameraPermissionTextValue, uiFileSharingEnabledValue, uiSupportsDocumentBrowserValue, uiStatusBarHiddenValue, documentExtensionsValue, iosInAppPurchasesValue, @@ -3034,6 +3088,10 @@ private: for (auto& option : getHardenedRuntimeOptions()) entitlements.set (option, ""); + if (isAppSandboxEnabled()) + for (auto& option : getAppSandboxOptions()) + entitlements.set (option, ""); + if (isiOS() && isiCloudPermissionsEnabled()) { entitlements.set ("com.apple.developer.icloud-container-identifiers", diff --git a/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h b/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h index 6240450c9f..9a7d3b12d7 100644 --- a/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h +++ b/extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h @@ -185,6 +185,8 @@ namespace Ids DECLARE_ID (showAllCode); DECLARE_ID (useLocalCopy); DECLARE_ID (overwriteOnSave); + DECLARE_ID (appSandbox); + DECLARE_ID (appSandboxOptions); DECLARE_ID (hardenedRuntime); DECLARE_ID (hardenedRuntimeOptions); DECLARE_ID (microphonePermissionNeeded);