diff --git a/core/dylib/src/main/java/ch/cyberduck/core/preferences/SMAppService.java b/core/dylib/src/main/java/ch/cyberduck/core/preferences/SMAppService.java new file mode 100644 index 00000000000..be07c259af6 --- /dev/null +++ b/core/dylib/src/main/java/ch/cyberduck/core/preferences/SMAppService.java @@ -0,0 +1,79 @@ +package ch.cyberduck.core.preferences; + +/* + * Copyright (c) 2002-2023 iterate GmbH. All rights reserved. + * https://cyberduck.io/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +import ch.cyberduck.binding.foundation.NSObject; + +import org.rococoa.ObjCClass; +import org.rococoa.ObjCObjectByReference; +import org.rococoa.Rococoa; + +/** + * macOS 13.0+ + */ +public abstract class SMAppService extends NSObject { + private static final _Class CLASS = Rococoa.createClass("SMAppService", _Class.class); + + public interface _Class extends ObjCClass { + SMAppService loginItemServiceWithIdentifier(String identifier); + + SMAppService mainAppService(); + + void openSystemSettingsLoginItems(); + } + + /** + * Initializes an app service object for a login item corresponding to the bundle with the identifier you provide. + * + * @param identifier The bundle identifier of the helper application. + * @return The property list name must correspond to a property list in the calling app’s Contents/Library/LoginItems directory + */ + public static SMAppService loginItemServiceWithIdentifier(final String identifier) { + return CLASS.loginItemServiceWithIdentifier(identifier); + } + + /** + * Opens System Settings to the Login Items control panel. + */ + public static void openSystemSettingsLoginItems() { + CLASS.openSystemSettingsLoginItems(); + } + + /** + * An app service object that corresponds to the main application as a login item. Use this SMAppService to configure the main app to launch at login. + */ + public static SMAppService mainAppService() { + return CLASS.mainAppService(); + } + + /** + * Registers the service so it can begin launching subject to user approval. + *
+ * If the service corresponds to a LoginItem bundle, the helper starts immediately and on subsequent logins. + * If the helper crashes or exits with a non-zero status, the system relaunches it. + * + * @return Returns YES if the service was successfully registered; otherwise, NO. + */ + public abstract boolean registerAndReturnError(ObjCObjectByReference error); + + /** + * Unregisters the service so the system no longer launches it. + * + * @param error Upon an unsuccessful return, a new NSError object describing the error. Upon successful return, this argument is NULL. This argument may be NULL. + * @return Returns YES if the service was successfully unregistered; otherwise, NO. + */ + public abstract boolean unregisterAndReturnError(ObjCObjectByReference error); +} diff --git a/core/dylib/src/main/java/ch/cyberduck/core/preferences/SMAppServiceApplicationLoginRegistry.java b/core/dylib/src/main/java/ch/cyberduck/core/preferences/SMAppServiceApplicationLoginRegistry.java new file mode 100644 index 00000000000..dc38dff72e0 --- /dev/null +++ b/core/dylib/src/main/java/ch/cyberduck/core/preferences/SMAppServiceApplicationLoginRegistry.java @@ -0,0 +1,40 @@ +package ch.cyberduck.core.preferences; + +/* + * Copyright (c) 2002-2023 iterate GmbH. All rights reserved. + * https://cyberduck.io/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +import ch.cyberduck.core.library.Native; +import ch.cyberduck.core.local.Application; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class SMAppServiceApplicationLoginRegistry implements ApplicationLoginRegistry { + private static final Logger log = LogManager.getLogger(SMAppServiceApplicationLoginRegistry.class); + + static { + Native.load("core"); + } + + @Override + public boolean register(final Application application) { + return SMAppService.loginItemServiceWithIdentifier(application.getIdentifier()).registerAndReturnError(null); + } + + @Override + public boolean unregister(final Application application) { + return SMAppService.loginItemServiceWithIdentifier(application.getIdentifier()).unregisterAndReturnError(null); + } +} diff --git a/core/dylib/src/test/java/ch/cyberduck/core/preferences/SMAppServiceApplicationLoginRegistryTest.java b/core/dylib/src/test/java/ch/cyberduck/core/preferences/SMAppServiceApplicationLoginRegistryTest.java new file mode 100644 index 00000000000..db2dd4940f1 --- /dev/null +++ b/core/dylib/src/test/java/ch/cyberduck/core/preferences/SMAppServiceApplicationLoginRegistryTest.java @@ -0,0 +1,37 @@ +package ch.cyberduck.core.preferences; + +/* + * Copyright (c) 2002-2023 iterate GmbH. All rights reserved. + * https://cyberduck.io/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +import ch.cyberduck.core.local.Application; + +import org.junit.Test; + +import static org.junit.Assert.assertFalse; + +public class SMAppServiceApplicationLoginRegistryTest { + + @Test + public void testRegister() { + assertFalse(new SMAppServiceApplicationLoginRegistry().register( + new Application("bundle.helper"))); + } + + @Test + public void testUnregister() { + assertFalse(new SMAppServiceApplicationLoginRegistry().unregister( + new Application("bundle.helper"))); + } +} \ No newline at end of file diff --git a/core/dylib/src/test/java/ch/cyberduck/core/preferences/SMAppServiceTest.java b/core/dylib/src/test/java/ch/cyberduck/core/preferences/SMAppServiceTest.java new file mode 100644 index 00000000000..d6475bbe3ab --- /dev/null +++ b/core/dylib/src/test/java/ch/cyberduck/core/preferences/SMAppServiceTest.java @@ -0,0 +1,39 @@ +package ch.cyberduck.core.preferences; + +/* + * Copyright (c) 2002-2023 iterate GmbH. All rights reserved. + * https://cyberduck.io/ + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + */ + +import ch.cyberduck.core.library.Native; + +import org.junit.Test; + +import static org.junit.Assert.assertNotNull; + +public class SMAppServiceTest { + + static { + Native.load("core"); + } + + @Test + public void testMainAppService() { + assertNotNull(SMAppService.mainAppService()); + } + + @Test + public void testSettings() { + SMAppService.openSystemSettingsLoginItems(); + } +} \ No newline at end of file