Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use ServiceManagement API to enable/disable login items (used to start an app after login) #45

Merged
merged 7 commits into from
May 29, 2024
Merged

Conversation

purejava
Copy link
Contributor

@purejava purejava commented May 24, 2024

As discussed in cryptomator/cryptomator#3417, we need to replace the deprecated kLSSharedFileListSessionLoginItems.

This PR does:

  • Use the (only not deprecated) SMAppService API to enable/disable login items (used to start an app after login)
  • An existing legacy login item gets migrated to the SMAppService API without user interaction
  • As Cryptomators minimum requirement is macOS 11, but the SMAppService API is available since macOS 13, the legacy API is used on macOS 11 and 12, the SMAppService API for macOS 13+

Copy link

coderabbitai bot commented May 24, 2024

Walkthrough

The recent changes integrate SKYLaunchService into the project, enhancing the management of macOS login items. The SKYLaunchService provides a unified interface for enabling, disabling, and checking the status of login items, covering both modern and legacy systems. These updates streamline the logic and improve error handling in the org_cryptomator_macos_autostart_MacLaunchServices_Native.m file by leveraging the new service.

Changes

Files/Paths Change Summary
src/main/native/Integrations.xcodeproj/project.pbxproj Added SKYLaunchService.h and SKYLaunchService.m as PBXFileReference and PBXBuildFile.
src/main/native/SKYLaunchService.h Introduced methods for managing login items: isLoginItemEnabled, enableLoginItem, disableLoginItem, isLegacyLoginItemEnabled, enableLegacyLoginItem, disableLegacyLoginItem.
src/main/native/SKYLaunchService.m Implemented functionality for managing login items, including handling legacy items.
src/main/native/org_cryptomator_macos_autostart_MacLaunchServices_Native.m Updated JNI functions to use SKYLaunchService for managing login items, improving logic and error handling.

Sequence Diagram(s) (Beta)

sequenceDiagram
    participant JNI as JNI Layer
    participant SKY as SKYLaunchService
    participant macOS as macOS Login Items

    JNI->>SKY: isLoginItemEnabled()
    SKY->>macOS: Check Login Item Status
    macOS-->>SKY: Status
    SKY-->>JNI: Status

    JNI->>SKY: enableLoginItem()
    SKY->>macOS: Enable Login Item
    macOS-->>SKY: Success/Failure
    SKY-->>JNI: Success/Failure

    JNI->>SKY: disableLoginItem()
    SKY->>macOS: Disable Login Item
    macOS-->>SKY: Success/Failure
    SKY-->>JNI: Success/Failure
Loading

In code we trust, with bytes we play,
Launching apps at break of day.
With SKYLaunchService taking flight,
Login items set just right.
Code and logic in a dance,
Making sure our apps enhance.
🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

Share
Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai generate interesting stats about this repository and render them as a table.
    • @coderabbitai show all the console.log statements in this repository.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (invoked as PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to full the review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai help to get help.

Additionally, you can add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.

CodeRabbit Configration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between b92c684 and 755a3ad.
Files selected for processing (1)
  • src/main/native/org_cryptomator_macos_autostart_MacLaunchServices_Native.m (1 hunks)
Additional comments not posted (5)
src/main/native/org_cryptomator_macos_autostart_MacLaunchServices_Native.m (5)

11-11: Ensure the new import ServiceManagement/ServiceManagement.h is necessary and correctly placed.

Verification successful

The import of ServiceManagement/ServiceManagement.h is necessary due to multiple usages of SMAppService in the file.

  • SMAppService is used in several lines within src/main/native/org_cryptomator_macos_autostart_MacLaunchServices_Native.m.
Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the necessity of the new import.

# Test: Search for usage of `SMAppService` in the file. Expect: At least one usage.
rg --type objc 'SMAppService' src/main/native/org_cryptomator_macos_autostart_MacLaunchServices_Native.m

Length of output: 536


75-98: Evaluate the error handling in enableLoginItem.

Verification successful

The extracted context shows that the NSError instances are being properly checked and logged in the enableLoginItem function. Specifically, the error is logged with NSLog if the registerAndReturnError method fails, and the function returns NO to indicate failure.

  • The error handling in the enableLoginItem function is appropriate as it logs the error description and returns a failure status.

Locations in the codebase:

  • src/main/native/org_cryptomator_macos_autostart_MacLaunchServices_Native.m lines 75-98
Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the error handling in enabling login items.

# Test: Search for error handling patterns in the enable function. Expect: Proper error handling.
rg --type objc 'NSError' src/main/native/org_cryptomator_macos_autostart_MacLaunchServices_Native.m

Length of output: 195



Script:

#!/bin/bash
# Extract the full context of NSError usage to verify error handling in enableLoginItem function.
rg -A 5 -B 5 'NSError\* error = nil;' src/main/native/org_cryptomator_macos_autostart_MacLaunchServices_Native.m

Length of output: 1691


13-38: Review the migration logic in migrateSharedFileListLoginItem.

Verification successful

To verify the migration logic and error handling in the migrateSharedFileListLoginItem function, we need to ensure that the NSError instances are properly used and that the function handles potential errors and edge cases correctly. The initial script output shows three instances of NSError* error = nil; in the file, but we need to confirm their usage.

Let's review the specific lines where NSError is used to ensure proper error handling.


The migrateSharedFileListLoginItem function includes proper error handling by checking the NSError instance after attempting to register the app service and logging an error message if the registration fails. This indicates that the migration logic handles potential errors correctly.

  • The error handling in the migrateSharedFileListLoginItem function is appropriate.
Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the migration logic and error handling.

# Test: Search for error handling patterns in the migration function. Expect: Proper error handling.
rg --type objc 'NSError' src/main/native/org_cryptomator_macos_autostart_MacLaunchServices_Native.m

Length of output: 195



Script:

#!/bin/bash
# Description: Extract lines containing NSError to review their usage in the function.

# Extract lines containing NSError and a few lines before and after for context.
rg --type objc 'NSError' -A 3 -B 3 src/main/native/org_cryptomator_macos_autostart_MacLaunchServices_Native.m

Length of output: 1398


102-133: Assess the error handling in disableLoginItem.

Verification successful

The disableLoginItem function has proper error handling for both macOS 13 and above, as well as for earlier versions. For macOS 13 and above, it checks for errors using NSError and logs an appropriate message if an error occurs. For earlier versions, it logs an error message if it fails to create the shared file list.

  • The error handling for macOS 13 and above is done using NSError and logs the error description.
  • For macOS versions below 13, it logs an error message if the shared file list cannot be created.

This confirms that the error handling in the disableLoginItem function is appropriately implemented.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the error handling in disabling login items.

# Test: Search for error handling patterns in the disable function. Expect: Proper error handling.
rg --type objc 'NSError' src/main/native/org_cryptomator_macos_autostart_MacLaunchServices_Native.m

Length of output: 195



Script:

#!/bin/bash
# Description: Locate the definition of the disableLoginItem function and inspect the usage of NSError within it.

# Search for the disableLoginItem function definition
ast-grep --lang objc --pattern 'disableLoginItem($_) { $$$ }' src/main/native/org_cryptomator_macos_autostart_MacLaunchServices_Native.m

Length of output: 247



Script:

#!/bin/bash
# Description: Locate the definition of the disableLoginItem function and inspect the usage of NSError within it.

# Search for the disableLoginItem function definition
rg 'disableLoginItem' src/main/native/org_cryptomator_macos_autostart_MacLaunchServices_Native.m -A 20 -B 5

Length of output: 1454



Script:

#!/bin/bash
# Description: Extract the complete disableLoginItem function for thorough inspection.

# Extract the complete disableLoginItem function definition
rg 'Java_org_cryptomator_macos_autostart_MacLaunchServices_00024Native_disableLoginItem' src/main/native/org_cryptomator_macos_autostart_MacLaunchServices_Native.m -A 50 -B 5

Length of output: 1846


41-70: Check the version-dependent logic in isLoginItemEnabled.

Copy link
Member

@tobihagemann tobihagemann left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh? Was it really that easy to just use SMAppService.mainAppService? I've checked the documentation again and just noticed that the whole "we need a helper application" concept doesn't apply if we want to launch the main app itself. 🤦‍♂️

Thank you!

@purejava
Copy link
Contributor Author

Oh? Was it really that easy to just use SMAppService.mainAppService? I've checked the documentation again and just noticed that the whole "we need a helper application" concept doesn't apply if we want to launch the main app itself. 🤦‍♂️

@tobihagemann Hi, I was surprised too. The documentation is quite poor in this part and mixed too, all in all quite unusable from my point of view.

Thank you!

You are very welcome!

@tobihagemann
Copy link
Member

@purejava I did some refactorings and just pushed them without asking, because it would've taken longer to explain and request the changes. 😄 My goal was to deduplicate some code, make it more readable, and also use more ObjC patterns as I'm used to. (Oh yeah, and a small thing that we use tabs instead of spaces.)

Can you please take a look and review the changes? To be honest, I didn't test them thoroughly. 😅

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Review Details

Configuration used: CodeRabbit UI
Review profile: CHILL

Commits Files that changed from the base of the PR and between 755a3ad and 57bac69.
Files selected for processing (4)
  • src/main/native/Integrations.xcodeproj/project.pbxproj (5 hunks)
  • src/main/native/SKYLaunchService.h (1 hunks)
  • src/main/native/SKYLaunchService.m (1 hunks)
  • src/main/native/org_cryptomator_macos_autostart_MacLaunchServices_Native.m (1 hunks)
Files skipped from review due to trivial changes (1)
  • src/main/native/SKYLaunchService.h
Files skipped from review as they are similar to previous changes (1)
  • src/main/native/org_cryptomator_macos_autostart_MacLaunchServices_Native.m
Additional comments not posted (4)
src/main/native/SKYLaunchService.m (3)

30-42: Check error handling in enableLoginItem for macOS 13 and later.

Verification successful

Error handling in enableLoginItem for macOS 13 and later is properly logged and managed. The method logs the error using NSLog and returns NO if the registration fails. The disableLoginItem method follows a similar pattern for unregistration.

  • enableLoginItem method:

    • Logs the error using NSLog.
    • Returns NO if the registration fails.
  • disableLoginItem method:

    • Logs the error using NSLog.
    • Returns NO if the unregistration fails.
Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify that all error paths in `enableLoginItem` are properly logged and handled.

# Test: Search for error handling patterns in the function.
rg --type objc $'NSError \*error;'

Length of output: 141



Script:

#!/bin/bash
# Extract the full implementation of the `enableLoginItem` method and any other methods containing `NSError *error;` in `src/main/native/SKYLaunchService.m`.

# Extract the `enableLoginItem` method implementation
ast-grep --lang objc --pattern $'+ (BOOL)enableLoginItem {
  $$$
}' src/main/native/SKYLaunchService.m

# Extract other methods containing `NSError *error;`
rg --type objc --context 10 'NSError \*error;' src/main/native/SKYLaunchService.m

Length of output: 1070


14-28: Ensure migration logic from legacy to new API is robust.

Verification successful

The disableLegacyLoginItem method is implemented in src/main/native/SKYLaunchService.m and appears to correctly handle the disabling of legacy login items by interacting with the LSSharedFileList. The method iterates through the shared file list items and resolves their paths to match the application's path, ensuring proper removal.

  • The method disableLegacyLoginItem is correctly implemented to disable legacy login items.
  • The migration logic from legacy to new API in the isLoginItemEnabled method is robust.
Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Verify the migration logic from legacy to new API by checking if the legacy items are properly disabled after migration.

# Test: Search for the function usage. Expect: Only occurances of the new signature.
rg --type objc $'disableLegacyLoginItem'

Length of output: 251



Script:

#!/bin/bash
# Description: Retrieve the implementation of the disableLegacyLoginItem method to verify its correctness.

# Search for the implementation of disableLegacyLoginItem in the Objective-C files.
ast-grep --lang objc --pattern $'- (BOOL)disableLegacyLoginItem {
  $$$
}'

Length of output: 184



Script:

#!/bin/bash
# Description: Retrieve the implementation of the disableLegacyLoginItem method to verify its correctness.

# Search for the implementation of disableLegacyLoginItem in the Objective-C files.
rg --type objc --pcre2 --multiline --multiline-dotall '^\s*-\s*\(BOOL\)\s*disableLegacyLoginItem\s*\{[^}]*\}'

Length of output: 111



Script:

#!/bin/bash
# Description: Locate the definition of the disableLegacyLoginItem method to verify its presence and correctness.

# Search for the method signature disableLegacyLoginItem in the Objective-C files.
rg --type objc 'disableLegacyLoginItem'

Length of output: 251



Script:

#!/bin/bash
# Description: Retrieve the full implementation of the disableLegacyLoginItem method to verify its correctness.

# Extract the full implementation of the disableLegacyLoginItem method in the Objective-C files.
rg --type objc --context 10 'disableLegacyLoginItem' src/main/native/SKYLaunchService.m

Length of output: 2086


44-56: Review the consistency of error handling in disableLoginItem.

Verification successful

The disableLoginItem method handles errors differently based on the macOS version. For macOS 13 and above, it uses SMAppService.mainAppService unregisterAndReturnError:&error and logs the error if it fails. For macOS versions below 13, it calls disableLegacyLoginItem, but we need to verify how disableLegacyLoginItem handles errors to ensure consistency.

To proceed, we need to inspect the disableLegacyLoginItem method to understand its error handling mechanism.


To verify the consistency of error handling in the disableLoginItem method, we need to locate and inspect the disableLegacyLoginItem method. Since ast-grep does not support Objective-C, we will use rg to search for the method definition.


To verify the consistency of error handling, we need to inspect the implementation of the disableLegacyLoginItem method found in src/main/native/SKYLaunchService.m.


To fully verify the consistency of error handling, we need to extract the complete implementation of the disableLegacyLoginItem method.


The disableLegacyLoginItem method handles errors by logging a message when it fails to create the shared file list, similar to how the disableLoginItem method logs errors when unregistering the login item fails. This indicates a consistent approach to error handling across different macOS versions.

  • disableLoginItem logs an error message if unregisterAndReturnError fails.
  • disableLegacyLoginItem logs an error message if it fails to create the shared file list.

Both methods use NSLog to report errors, ensuring consistency in error handling.

Scripts Executed

The following scripts were executed for the analysis:


Script:

#!/bin/bash
# Description: Ensure consistent error handling across different macOS versions in `disableLoginItem`.

# Test: Search for error handling patterns in the function.
rg --type objc $'NSError \*error;'

Length of output: 141



Script:

#!/bin/bash
# Description: Inspect the `disableLegacyLoginItem` method to understand its error handling mechanism.

# Search for the `disableLegacyLoginItem` method definition in the codebase.
ast-grep --lang objc --pattern 'disableLegacyLoginItem' 

Length of output: 164



Script:

#!/bin/bash
# Description: Search for the `disableLegacyLoginItem` method definition in the codebase.

# Use `rg` to find the `disableLegacyLoginItem` method definition.
rg 'disableLegacyLoginItem' --type objc

Length of output: 251



Script:

#!/bin/bash
# Description: Extract the `disableLegacyLoginItem` method implementation from `src/main/native/SKYLaunchService.m`.

# Use `rg` to extract the `disableLegacyLoginItem` method implementation.
rg --context 10 'disableLegacyLoginItem' src/main/native/SKYLaunchService.m

Length of output: 2074



Script:

#!/bin/bash
# Description: Extract the complete `disableLegacyLoginItem` method implementation from `src/main/native/SKYLaunchService.m`.

# Use `rg` to extract the complete `disableLegacyLoginItem` method implementation.
rg --context 20 'disableLegacyLoginItem' src/main/native/SKYLaunchService.m

Length of output: 4033

src/main/native/Integrations.xcodeproj/project.pbxproj (1)

10-11: Confirm integration of SKYLaunchService files into the project.

Ensure that the new files are correctly referenced and integrated into the project build phases and groups.

Also applies to: 24-25, 61-62, 83-83, 145-145

src/main/native/SKYLaunchService.m Show resolved Hide resolved
@purejava
Copy link
Contributor Author

@purejava I did some refactorings and just pushed them without asking, because it would've taken longer to explain and request the changes. 😄 My goal was to deduplicate some code, make it more readable, and also use more ObjC patterns as I'm used to. (Oh yeah, and a small thing that we use tabs instead of spaces.)

That's perfectly fine @tobihagemann! I haven't written an entire ObjC class before, so this was much more efficient and from reading your code, I've learned about it.
Yeah, this improved the code and removed redundancy.

Regarding the code formatting: both, the IntelliJ IDE and Sublime Text refused to help in formatting. It looks, as if Xcode is doing a better job here. 🙂

Can you please take a look and review the changes? To be honest, I didn't test them thoroughly. 😅

I did and tested again. The code looks good and works well. I am approving the commit.

The PR can get merged now.

Thanks for the review and your addition.

@infeo infeo merged commit 656f2a4 into cryptomator:develop May 29, 2024
3 checks passed
@infeo infeo added this to the next milestone May 29, 2024
@purejava purejava deleted the newer-start-at-login branch May 29, 2024 13:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants