mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-09 23:34:20 +00:00
Projucer: Fix non-bool app sandbox temporary exception entitlements
This commit is contained in:
parent
1616c0ee26
commit
dc4b9bd152
10 changed files with 136 additions and 24 deletions
|
|
@ -427,6 +427,22 @@ attributes directly to these creation functions, rather than adding them later.
|
|||
plist if `APP_SANDBOX_ENABLED` is `TRUE`. Each key should be in the form `com.apple.security.*`
|
||||
where `*` is a specific entitlement.
|
||||
|
||||
`APP_SANDBOX_FILE_ACCESS_HOME_RO`
|
||||
- A set of space-separated paths that will be added to this target's entitlements plist for
|
||||
accessing read-only paths relative to the home directory if `APP_SANDBOX_ENABLED` is `TRUE`.
|
||||
|
||||
`APP_SANDBOX_FILE_ACCESS_HOME_RW`
|
||||
- A set of space-separated paths that will be added to this target's entitlements plist for
|
||||
accessing read/write paths relative to the home directory if `APP_SANDBOX_ENABLED` is `TRUE`.
|
||||
|
||||
`APP_SANDBOX_FILE_ACCESS_ABS_RO`
|
||||
- A set of space-separated paths that will be added to this target's entitlements plist for
|
||||
accessing read-only absolute paths if `APP_SANDBOX_ENABLED` is `TRUE`.
|
||||
|
||||
`APP_SANDBOX_FILE_ACCESS_ABS_RW`
|
||||
- A set of space-separated paths that will be added to this target's entitlements plist for
|
||||
accessing read/write absolute paths if `APP_SANDBOX_ENABLED` is `TRUE`.
|
||||
|
||||
`PLIST_TO_MERGE`
|
||||
- A string to insert into an app/plugin's Info.plist.
|
||||
|
||||
|
|
|
|||
|
|
@ -318,6 +318,10 @@ function(_juce_write_configure_time_info target)
|
|||
_juce_append_target_property(file_content APP_SANDBOX_INHERIT ${target} JUCE_APP_SANDBOX_INHERIT)
|
||||
_juce_append_target_property(file_content HARDENED_RUNTIME_OPTIONS ${target} JUCE_HARDENED_RUNTIME_OPTIONS)
|
||||
_juce_append_target_property(file_content APP_SANDBOX_OPTIONS ${target} JUCE_APP_SANDBOX_OPTIONS)
|
||||
_juce_append_target_property(file_content APP_SANDBOX_FILE_ACCESS_HOME_RO ${target} JUCE_APP_SANDBOX_FILE_ACCESS_HOME_RO)
|
||||
_juce_append_target_property(file_content APP_SANDBOX_FILE_ACCESS_HOME_RW ${target} JUCE_APP_SANDBOX_FILE_ACCESS_HOME_RW)
|
||||
_juce_append_target_property(file_content APP_SANDBOX_FILE_ACCESS_ABS_RO ${target} JUCE_APP_SANDBOX_FILE_ACCESS_ABS_RO)
|
||||
_juce_append_target_property(file_content APP_SANDBOX_FILE_ACCESS_ABS_RW ${target} JUCE_APP_SANDBOX_FILE_ACCESS_ABS_RW)
|
||||
_juce_append_target_property(file_content APP_GROUPS_ENABLED ${target} JUCE_APP_GROUPS_ENABLED)
|
||||
_juce_append_target_property(file_content APP_GROUP_IDS ${target} JUCE_APP_GROUP_IDS)
|
||||
_juce_append_target_property(file_content IS_PLUGIN ${target} JUCE_IS_PLUGIN)
|
||||
|
|
@ -1546,6 +1550,10 @@ function(_juce_initialise_target target)
|
|||
VST3_CATEGORIES
|
||||
HARDENED_RUNTIME_OPTIONS
|
||||
APP_SANDBOX_OPTIONS
|
||||
APP_SANDBOX_FILE_ACCESS_HOME_RO
|
||||
APP_SANDBOX_FILE_ACCESS_HOME_RW
|
||||
APP_SANDBOX_FILE_ACCESS_ABS_RO
|
||||
APP_SANDBOX_FILE_ACCESS_ABS_RW
|
||||
DOCUMENT_EXTENSIONS
|
||||
AAX_CATEGORY
|
||||
IPHONE_SCREEN_ORIENTATIONS # iOS only
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@ namespace build_tools
|
|||
if (isAppGroupsEnabled)
|
||||
{
|
||||
auto appGroups = StringArray::fromTokens (appGroupIdString, ";", {});
|
||||
auto groups = String ("<array>");
|
||||
String groups = "<array>";
|
||||
|
||||
for (auto group : appGroups)
|
||||
groups += "\n\t\t<string>" + group.trim() + "</string>";
|
||||
|
|
@ -101,13 +101,27 @@ namespace build_tools
|
|||
{
|
||||
// no other sandbox options can be specified if sandbox inheritance is enabled!
|
||||
jassert (appSandboxOptions.isEmpty());
|
||||
jassert (appSandboxTemporaryPaths.empty());
|
||||
|
||||
entitlements.set ("com.apple.security.inherit", "<true/>");
|
||||
}
|
||||
|
||||
if (isAppSandboxEnabled)
|
||||
{
|
||||
for (auto& option : appSandboxOptions)
|
||||
entitlements.set (option, "<true/>");
|
||||
|
||||
for (auto& option : appSandboxTemporaryPaths)
|
||||
{
|
||||
String paths = "<array>";
|
||||
|
||||
for (const auto& path : option.values)
|
||||
paths += "\n\t\t<string>" + path + "</string>";
|
||||
|
||||
paths += "\n\t</array>";
|
||||
entitlements.set (option.key, paths);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isNetworkingMulticastEnabled)
|
||||
|
|
|
|||
|
|
@ -49,6 +49,14 @@ namespace build_tools
|
|||
StringArray hardenedRuntimeOptions;
|
||||
StringArray appSandboxOptions;
|
||||
|
||||
struct KeyAndStringArray
|
||||
{
|
||||
String key;
|
||||
StringArray values;
|
||||
};
|
||||
|
||||
std::vector<KeyAndStringArray> appSandboxTemporaryPaths;
|
||||
|
||||
private:
|
||||
StringPairArray getEntitlements() const;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -343,6 +343,29 @@ juce::build_tools::EntitlementOptions parseEntitlementsOptions (const juce::File
|
|||
updateField ("APP_SANDBOX_OPTIONS", result.appSandboxOptions);
|
||||
updateField ("NETWORK_MULTICAST_ENABLED", result.isNetworkingMulticastEnabled);
|
||||
|
||||
struct SandboxTemporaryAccessKey
|
||||
{
|
||||
juce::String cMakeVar, key;
|
||||
};
|
||||
|
||||
SandboxTemporaryAccessKey sandboxTemporaryAccessKeys[]
|
||||
{
|
||||
{ "APP_SANDBOX_FILE_ACCESS_HOME_RO", "home-relative-path.read-only" },
|
||||
{ "APP_SANDBOX_FILE_ACCESS_HOME_RW", "home-relative-path.read-write" },
|
||||
{ "APP_SANDBOX_FILE_ACCESS_ABS_RO", "absolute-path.read-only" },
|
||||
{ "APP_SANDBOX_FILE_ACCESS_ABS_RW", "absolute-path.read-write" }
|
||||
};
|
||||
|
||||
for (const auto& entry : sandboxTemporaryAccessKeys)
|
||||
{
|
||||
juce::StringArray values;
|
||||
updateField (entry.cMakeVar, values);
|
||||
|
||||
if (! values.isEmpty())
|
||||
result.appSandboxTemporaryPaths.push_back ({ "com.apple.security.temporary-exception.files." + entry.key,
|
||||
std::move (values) });
|
||||
}
|
||||
|
||||
result.type = type;
|
||||
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -302,8 +302,7 @@ public:
|
|||
|
||||
for (auto& pp : properties)
|
||||
{
|
||||
const auto propertyHeight = pp->getPreferredHeight()
|
||||
+ (getHeightMultiplier (pp.get()) * pp->getPreferredHeight());
|
||||
const auto propertyHeight = jmax (pp->getPreferredHeight(), getApproximateLabelHeight (*pp));
|
||||
|
||||
auto iter = std::find_if (propertyComponentsWithInfo.begin(), propertyComponentsWithInfo.end(),
|
||||
[&pp] (const std::unique_ptr<PropertyAndInfoWrapper>& w) { return &w->propertyComponent == pp.get(); });
|
||||
|
|
@ -418,17 +417,17 @@ private:
|
|||
}
|
||||
}
|
||||
|
||||
int getHeightMultiplier (PropertyComponent* pp)
|
||||
static int getApproximateLabelHeight (const PropertyComponent& pp)
|
||||
{
|
||||
auto availableTextWidth = ProjucerLookAndFeel::getTextWidthForPropertyComponent (pp);
|
||||
|
||||
auto font = ProjucerLookAndFeel::getPropertyComponentFont();
|
||||
auto nameWidth = font.getStringWidthFloat (pp->getName());
|
||||
|
||||
if (availableTextWidth == 0)
|
||||
return 0;
|
||||
|
||||
return static_cast<int> (nameWidth / (float) availableTextWidth);
|
||||
const auto font = ProjucerLookAndFeel::getPropertyComponentFont();
|
||||
const auto labelWidth = font.getStringWidthFloat (pp.getName());
|
||||
const auto numLines = (int) (labelWidth / (float) availableTextWidth) + 1;
|
||||
return (int) std::round ((float) numLines * font.getHeight() * 1.1f);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
|
|
|
|||
|
|
@ -74,6 +74,10 @@ public:
|
|||
appSandboxValue (settings, Ids::appSandbox, getUndoManager()),
|
||||
appSandboxInheritanceValue (settings, Ids::appSandboxInheritance, getUndoManager()),
|
||||
appSandboxOptionsValue (settings, Ids::appSandboxOptions, getUndoManager(), Array<var>(), ","),
|
||||
appSandboxHomeDirROValue (settings, Ids::appSandboxHomeDirRO, getUndoManager()),
|
||||
appSandboxHomeDirRWValue (settings, Ids::appSandboxHomeDirRW, getUndoManager()),
|
||||
appSandboxAbsDirROValue (settings, Ids::appSandboxAbsDirRO, getUndoManager()),
|
||||
appSandboxAbsDirRWValue (settings, Ids::appSandboxAbsDirRW, getUndoManager()),
|
||||
hardenedRuntimeValue (settings, Ids::hardenedRuntime, getUndoManager()),
|
||||
hardenedRuntimeOptionsValue (settings, Ids::hardenedRuntimeOptions, getUndoManager(), Array<var>(), ","),
|
||||
microphonePermissionNeededValue (settings, Ids::microphonePermissionNeeded, getUndoManager()),
|
||||
|
|
@ -173,6 +177,21 @@ public:
|
|||
bool isAppSandboxInhertianceEnabled() const { return appSandboxInheritanceValue.get(); }
|
||||
Array<var> getAppSandboxOptions() const { return *appSandboxOptionsValue.get().getArray(); }
|
||||
|
||||
auto getAppSandboxTemporaryPaths() const
|
||||
{
|
||||
std::vector<build_tools::EntitlementOptions::KeyAndStringArray> result;
|
||||
|
||||
for (const auto& entry : sandboxFileAccessProperties)
|
||||
{
|
||||
auto paths = getCommaOrWhitespaceSeparatedItems (entry.property.get());
|
||||
|
||||
if (! paths.isEmpty())
|
||||
result.push_back ({ "com.apple.security.temporary-exception.files." + entry.key, std::move (paths) });
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Array<var> getValidArchs() const { return *validArchsValue.get().getArray(); }
|
||||
|
||||
bool isMicrophonePermissionEnabled() const { return microphonePermissionNeededValue.get(); }
|
||||
|
|
@ -457,29 +476,36 @@ public:
|
|||
{ "Temporary Exception: Audio Unit Hosting", "temporary-exception.audio-unit-host" },
|
||||
{ "Temporary Exception: Global Mach Service", "temporary-exception.mach-lookup.global-name" },
|
||||
{ "Temporary Exception: Global Mach Service Dynamic Registration", "temporary-exception.mach-register.global-name" },
|
||||
{ "Temporary Exception: Home Directory File Access (Read Only)", "temporary-exception.files.home-relative-path.read-only" },
|
||||
{ "Temporary Exception: Home Directory File Access (Read/Write)", "temporary-exception.files.home-relative-path.read-write" },
|
||||
{ "Temporary Exception: Absolute Path File Access (Read Only)", "temporary-exception.files.absolute-path.read-only" },
|
||||
{ "Temporary Exception: Absolute Path File Access (Read/Write)", "temporary-exception.files.absolute-path.read-write" },
|
||||
{ "Temporary Exception: IOKit User Client Class", "temporary-exception.iokit-user-client-class" },
|
||||
{ "Temporary Exception: Shared Preference Domain (Read Only)", "temporary-exception.shared-preference.read-only" },
|
||||
{ "Temporary Exception: Shared Preference Domain (Read/Write)", "temporary-exception.shared-preference.read-write" }
|
||||
};
|
||||
|
||||
StringArray sandboxKeys;
|
||||
Array<var> sanboxValues;
|
||||
Array<var> sandboxValues;
|
||||
|
||||
for (auto& opt : sandboxOptions)
|
||||
{
|
||||
sandboxKeys.add (opt.first);
|
||||
sanboxValues.add ("com.apple.security." + opt.second);
|
||||
sandboxValues.add ("com.apple.security." + opt.second);
|
||||
}
|
||||
|
||||
props.add (new MultiChoicePropertyComponentWithEnablement (appSandboxOptionsValue,
|
||||
appSandboxValue,
|
||||
"App Sandbox Options",
|
||||
sandboxKeys,
|
||||
sanboxValues));
|
||||
sandboxValues));
|
||||
|
||||
for (const auto& entry : sandboxFileAccessProperties)
|
||||
{
|
||||
props.add (new TextPropertyComponentWithEnablement (entry.property,
|
||||
appSandboxValue,
|
||||
entry.label,
|
||||
8192,
|
||||
true),
|
||||
"A list of the corresponding paths (separated by newlines or whitespace). "
|
||||
"See Apple's File Access Temporary Exceptions documentation.");
|
||||
}
|
||||
|
||||
props.add (new ChoicePropertyComponent (hardenedRuntimeValue, "Use Hardened Runtime"),
|
||||
"Enable this to use the hardened runtime required for app notarization.");
|
||||
|
|
@ -3085,6 +3111,7 @@ private:
|
|||
options.appGroupIdString = getAppGroupIdString();
|
||||
options.hardenedRuntimeOptions = getHardenedRuntimeOptions();
|
||||
options.appSandboxOptions = getAppSandboxOptions();
|
||||
options.appSandboxTemporaryPaths = getAppSandboxTemporaryPaths();
|
||||
|
||||
const auto entitlementsFile = getTargetFolder().getChildFile (target.getEntitlementsFilename());
|
||||
build_tools::overwriteFileIfDifferentOrThrow (entitlementsFile, options.getEntitlementsFileContent());
|
||||
|
|
@ -3566,6 +3593,7 @@ private:
|
|||
duplicateAppExResourcesFolderValue, iosDeviceFamilyValue, iPhoneScreenOrientationValue,
|
||||
iPadScreenOrientationValue, customXcodeResourceFoldersValue, customXcassetsFolderValue,
|
||||
appSandboxValue, appSandboxInheritanceValue, appSandboxOptionsValue,
|
||||
appSandboxHomeDirROValue, appSandboxHomeDirRWValue, appSandboxAbsDirROValue, appSandboxAbsDirRWValue,
|
||||
hardenedRuntimeValue, hardenedRuntimeOptionsValue,
|
||||
microphonePermissionNeededValue, microphonePermissionsTextValue,
|
||||
cameraPermissionNeededValue, cameraPermissionTextValue,
|
||||
|
|
@ -3576,5 +3604,19 @@ private:
|
|||
networkingMulticastValue, iosDevelopmentTeamIDValue, iosAppGroupsIDValue, keepCustomXcodeSchemesValue, useHeaderMapValue, customLaunchStoryboardValue,
|
||||
exporterBundleIdentifierValue, suppressPlistResourceUsageValue, useLegacyBuildSystemValue, buildNumber;
|
||||
|
||||
struct SandboxFileAccessProperty
|
||||
{
|
||||
const ValueTreePropertyWithDefault& property;
|
||||
const String label, key;
|
||||
};
|
||||
|
||||
const std::vector<SandboxFileAccessProperty> sandboxFileAccessProperties
|
||||
{
|
||||
{ appSandboxHomeDirROValue, "App sandbox temporary exception: home directory read only file access", "home-relative-path.read-only" },
|
||||
{ appSandboxHomeDirRWValue, "App sandbox temporary exception: home directory read/write file access", "home-relative-path.read-write" },
|
||||
{ appSandboxAbsDirROValue, "App sandbox temporary exception: absolute path read only file access", "absolute-path.read-only" },
|
||||
{ appSandboxAbsDirRWValue, "App sandbox temporary exception: absolute path read/write file access", "absolute-path.read-write" }
|
||||
};
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE (XcodeProjectExporter)
|
||||
};
|
||||
|
|
|
|||
|
|
@ -196,6 +196,10 @@ namespace Ids
|
|||
DECLARE_ID (appSandbox);
|
||||
DECLARE_ID (appSandboxInheritance);
|
||||
DECLARE_ID (appSandboxOptions);
|
||||
DECLARE_ID (appSandboxHomeDirRO);
|
||||
DECLARE_ID (appSandboxHomeDirRW);
|
||||
DECLARE_ID (appSandboxAbsDirRO);
|
||||
DECLARE_ID (appSandboxAbsDirRW);
|
||||
DECLARE_ID (hardenedRuntime);
|
||||
DECLARE_ID (hardenedRuntimeOptions);
|
||||
DECLARE_ID (microphonePermissionNeeded);
|
||||
|
|
|
|||
|
|
@ -94,23 +94,21 @@ int ProjucerLookAndFeel::getTabButtonBestWidth (TabBarButton& button, int)
|
|||
return 120;
|
||||
}
|
||||
|
||||
void ProjucerLookAndFeel::drawPropertyComponentLabel (Graphics& g, int width, int height, PropertyComponent& component)
|
||||
void ProjucerLookAndFeel::drawPropertyComponentLabel (Graphics& g, int, int height, PropertyComponent& component)
|
||||
{
|
||||
ignoreUnused (width);
|
||||
|
||||
g.setColour (component.findColour (defaultTextColourId)
|
||||
.withMultipliedAlpha (component.isEnabled() ? 1.0f : 0.6f));
|
||||
|
||||
auto textWidth = getTextWidthForPropertyComponent (&component);
|
||||
auto textWidth = getTextWidthForPropertyComponent (component);
|
||||
|
||||
g.setFont (getPropertyComponentFont());
|
||||
g.drawFittedText (component.getName(), 0, 0, textWidth - 5, height, Justification::centredLeft, 5, 1.0f);
|
||||
g.drawFittedText (component.getName(), 0, 0, textWidth, height, Justification::centredLeft, 5, 1.0f);
|
||||
}
|
||||
|
||||
Rectangle<int> ProjucerLookAndFeel::getPropertyComponentContentPosition (PropertyComponent& component)
|
||||
{
|
||||
const auto textW = getTextWidthForPropertyComponent (&component);
|
||||
return { textW, 0, component.getWidth() - textW, component.getHeight() - 1 };
|
||||
const auto paddedTextW = getTextWidthForPropertyComponent (component) + 5;
|
||||
return { paddedTextW , 0, component.getWidth() - paddedTextW, component.getHeight() - 1 };
|
||||
}
|
||||
|
||||
void ProjucerLookAndFeel::drawButtonBackground (Graphics& g,
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@ public:
|
|||
static Path getChoiceComponentArrowPath (Rectangle<float> arrowZone);
|
||||
|
||||
static Font getPropertyComponentFont() { return { 14.0f, Font::FontStyleFlags::bold }; }
|
||||
static int getTextWidthForPropertyComponent (PropertyComponent* pp) { return jmin (200, pp->getWidth() / 2); }
|
||||
static int getTextWidthForPropertyComponent (const PropertyComponent& pc) { return jmin (200, pc.getWidth() / 2); }
|
||||
|
||||
static ColourScheme getProjucerDarkColourScheme()
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue