Browse Source

[macOS, sandbox] Add export option to embed and sign helper executables.

bruvzg 4 years ago
parent
commit
911c276a1a
2 changed files with 50 additions and 5 deletions
  1. 2 0
      doc/classes/OS.xml
  2. 48 5
      platform/osx/export/export_plugin.cpp

+ 2 - 0
doc/classes/OS.xml

@@ -49,6 +49,7 @@
 				[/codeblocks]
 				[/codeblocks]
 				See [method execute] if you wish to run an external command and retrieve the results.
 				See [method execute] if you wish to run an external command and retrieve the results.
 				[b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows.
 				[b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows.
+				[b]Note:[/b] On macOS, sandboxed applications are limited to run only embedded helper executables, specified during export.
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="delay_msec" qualifiers="const">
 		<method name="delay_msec" qualifiers="const">
@@ -119,6 +120,7 @@
 				[/csharp]
 				[/csharp]
 				[/codeblocks]
 				[/codeblocks]
 				[b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows.
 				[b]Note:[/b] This method is implemented on Android, iOS, Linux, macOS and Windows.
+				[b]Note:[/b] On macOS, sandboxed applications are limited to run only embedded helper executables, specified during export.
 			</description>
 			</description>
 		</method>
 		</method>
 		<method name="find_keycode_from_string" qualifiers="const">
 		<method name="find_keycode_from_string" qualifiers="const">

+ 48 - 5
platform/osx/export/export_plugin.cpp

@@ -95,6 +95,7 @@ void EditorExportPlatformOSX::get_export_options(List<ExportOption> *r_options)
 	r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_pictures", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
 	r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_pictures", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
 	r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_music", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
 	r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_music", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
 	r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_movies", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
 	r_options->push_back(ExportOption(PropertyInfo(Variant::INT, "codesign/entitlements/app_sandbox/files_movies", PROPERTY_HINT_ENUM, "No,Read-only,Read-write"), 0));
+	r_options->push_back(ExportOption(PropertyInfo(Variant::ARRAY, "codesign/entitlements/app_sandbox/helper_executables", PROPERTY_HINT_ARRAY_TYPE, itos(Variant::STRING) + "/" + itos(PROPERTY_HINT_GLOBAL_FILE) + ":"), Array()));
 
 
 	r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray()));
 	r_options->push_back(ExportOption(PropertyInfo(Variant::PACKED_STRING_ARRAY, "codesign/custom_options"), PackedStringArray()));
 
 
@@ -535,6 +536,8 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
 		err = ERR_CANT_CREATE;
 		err = ERR_CANT_CREATE;
 	}
 	}
 
 
+	Array helpers = p_preset->get("codesign/entitlements/app_sandbox/helper_executables");
+
 	// Create our folder structure.
 	// Create our folder structure.
 	if (err == OK) {
 	if (err == OK) {
 		print_line("Creating " + tmp_app_path_name + "/Contents/MacOS");
 		print_line("Creating " + tmp_app_path_name + "/Contents/MacOS");
@@ -546,6 +549,11 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
 		err = tmp_app_dir->make_dir_recursive(tmp_app_path_name + "/Contents/Frameworks");
 		err = tmp_app_dir->make_dir_recursive(tmp_app_path_name + "/Contents/Frameworks");
 	}
 	}
 
 
+	if ((err == OK) && helpers.size() > 0) {
+		print_line("Creating " + tmp_app_path_name + "/Contents/Helpers");
+		err = tmp_app_dir->make_dir_recursive(tmp_app_path_name + "/Contents/Helpers");
+	}
+
 	if (err == OK) {
 	if (err == OK) {
 		print_line("Creating " + tmp_app_path_name + "/Contents/Resources");
 		print_line("Creating " + tmp_app_path_name + "/Contents/Resources");
 		err = tmp_app_dir->make_dir_recursive(tmp_app_path_name + "/Contents/Resources");
 		err = tmp_app_dir->make_dir_recursive(tmp_app_path_name + "/Contents/Resources");
@@ -688,6 +696,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
 		bool sign_enabled = p_preset->get("codesign/enable");
 		bool sign_enabled = p_preset->get("codesign/enable");
 
 
 		String ent_path = p_preset->get("codesign/entitlements/custom_file");
 		String ent_path = p_preset->get("codesign/entitlements/custom_file");
+		String hlp_ent_path = EditorPaths::get_singleton()->get_cache_dir().plus_file(pkg_name + "_helper.entitlements");
 		if (sign_enabled && (ent_path == "")) {
 		if (sign_enabled && (ent_path == "")) {
 			ent_path = EditorPaths::get_singleton()->get_cache_dir().plus_file(pkg_name + ".entitlements");
 			ent_path = EditorPaths::get_singleton()->get_cache_dir().plus_file(pkg_name + ".entitlements");
 
 
@@ -819,10 +828,43 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
 			} else {
 			} else {
 				err = ERR_CANT_CREATE;
 				err = ERR_CANT_CREATE;
 			}
 			}
+
+			if ((err == OK) && helpers.size() > 0) {
+				ent_f = FileAccess::open(hlp_ent_path, FileAccess::WRITE);
+				if (ent_f) {
+					ent_f->store_line("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
+					ent_f->store_line("<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">");
+					ent_f->store_line("<plist version=\"1.0\">");
+					ent_f->store_line("<dict>");
+					ent_f->store_line("<key>com.apple.security.app-sandbox</key>");
+					ent_f->store_line("<true/>");
+					ent_f->store_line("<key>com.apple.security.inherit</key>");
+					ent_f->store_line("<true/>");
+					ent_f->store_line("</dict>");
+					ent_f->store_line("</plist>");
+
+					ent_f->close();
+					memdelete(ent_f);
+				} else {
+					err = ERR_CANT_CREATE;
+				}
+			}
+		}
+
+		if ((err == OK) && helpers.size() > 0) {
+			DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+			for (int i = 0; i < helpers.size(); i++) {
+				String hlp_path = helpers[i];
+				err = da->copy(hlp_path, tmp_app_path_name + "/Contents/Helpers/" + hlp_path.get_file());
+				if (err == OK && sign_enabled) {
+					err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Helpers/" + hlp_path.get_file(), hlp_ent_path);
+				}
+				FileAccess::set_unix_permissions(tmp_app_path_name + "/Contents/Helpers/" + hlp_path.get_file(), 0755);
+			}
 		}
 		}
 
 
 		if (err == OK) {
 		if (err == OK) {
-			DirAccess *da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
+			DirAccessRef da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
 			for (int i = 0; i < shared_objects.size(); i++) {
 			for (int i = 0; i < shared_objects.size(); i++) {
 				String src_path = ProjectSettings::get_singleton()->globalize_path(shared_objects[i].path);
 				String src_path = ProjectSettings::get_singleton()->globalize_path(shared_objects[i].path);
 				if (da->dir_exists(src_path)) {
 				if (da->dir_exists(src_path)) {
@@ -842,7 +884,6 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
 					err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Frameworks/" + src_path.get_file(), ent_path);
 					err = _code_sign(p_preset, tmp_app_path_name + "/Contents/Frameworks/" + src_path.get_file(), ent_path);
 				}
 				}
 			}
 			}
-			memdelete(da);
 		}
 		}
 
 
 		if (sign_enabled) {
 		if (sign_enabled) {
@@ -903,6 +944,9 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
 			err = _notarize(p_preset, p_path);
 			err = _notarize(p_preset, p_path);
 		}
 		}
 
 
+		// Clean up temporary entitlements files.
+		DirAccess::remove_file_or_error(hlp_ent_path);
+
 		// Clean up temporary .app dir.
 		// Clean up temporary .app dir.
 		tmp_app_dir->change_dir(tmp_app_path_name);
 		tmp_app_dir->change_dir(tmp_app_path_name);
 		tmp_app_dir->erase_contents_recursive();
 		tmp_app_dir->erase_contents_recursive();
@@ -916,7 +960,7 @@ Error EditorExportPlatformOSX::export_project(const Ref<EditorExportPreset> &p_p
 void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String &p_root_path, const String &p_folder, const String &p_pkg_name) {
 void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String &p_root_path, const String &p_folder, const String &p_pkg_name) {
 	String dir = p_root_path.plus_file(p_folder);
 	String dir = p_root_path.plus_file(p_folder);
 
 
-	DirAccess *da = DirAccess::open(dir);
+	DirAccessRef da = DirAccess::open(dir);
 	da->list_dir_begin();
 	da->list_dir_begin();
 	String f;
 	String f;
 	while ((f = da->get_next()) != "") {
 	while ((f = da->get_next()) != "") {
@@ -967,7 +1011,7 @@ void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String
 		} else if (da->current_is_dir()) {
 		} else if (da->current_is_dir()) {
 			_zip_folder_recursive(p_zip, p_root_path, p_folder.plus_file(f), p_pkg_name);
 			_zip_folder_recursive(p_zip, p_root_path, p_folder.plus_file(f), p_pkg_name);
 		} else {
 		} else {
-			bool is_executable = (p_folder.ends_with("MacOS") && (f == p_pkg_name));
+			bool is_executable = (p_folder.ends_with("MacOS") && (f == p_pkg_name)) || p_folder.ends_with("Helpers");
 
 
 			OS::Time time = OS::get_singleton()->get_time();
 			OS::Time time = OS::get_singleton()->get_time();
 			OS::Date date = OS::get_singleton()->get_date();
 			OS::Date date = OS::get_singleton()->get_date();
@@ -1012,7 +1056,6 @@ void EditorExportPlatformOSX::_zip_folder_recursive(zipFile &p_zip, const String
 		}
 		}
 	}
 	}
 	da->list_dir_end();
 	da->list_dir_end();
-	memdelete(da);
 }
 }
 
 
 bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {
 bool EditorExportPlatformOSX::can_export(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates) const {