⬆️ ⬇️

How to extend the functionality of an application hosted on the Mac Store using Apple Script

Since the passage of moderation on the Mac Store began to require support for Sandbox, 5 years have passed. Although the capabilities of MacOS and Sandbox are gradually expanding, developers who want to publish in the official Apple store are still limited in their capabilities to work with this OS. This problem is especially acute for utilities and system applications.





Sandbox is designed to make macOS safer and protect the user from malicious and potentially dangerous applications - all applications that can hypothetically harm should be accompanied by a request to the user to provide access. In theory, this is a reasonable precaution, but in reality many applications that require user data to perform basic functions are subject to sanctions. In this article, we will describe how they implemented similar functions in the application, maintaining compatibility with Sandbox - perhaps this experience will be useful for other developers working with the official market.



We are faced with a similar need when working with the utility for monitoring the MaCleaner X system. The entire MaCleaner product line is distributed exclusively through the Mac App Store.

')

Distinctive features of MaCleaner X are the touchbar support and customized design: the application automatically detects the Mac model and offers a special interface option for each device. However, in addition to this, we are currently working on implementing in the extended version some functions that users would like to see in the program and which are considered familiar for utilities distributed outside the Mac Store.



First of all it is:





Solution



To begin with, we will outline in general terms, according to which scheme the whole process will take place:





To perform this operation outside the sandbox, we will use the following macOS feature: applications that support extending their functionality using Apple Script can run these scripts outside the sandbox, if they are located in the ~ / Library / Application Scripts folder. An application that supports Sandbox cannot copy scripts to this folder by itself — this is stopped by Apple moderators.



Thus, the sequence of actions we have the following:



  1. Implementing a master application that supports extensions using Apple Script from the Application Scripts folder.
  2. Passage of moderation and publication of the application in the Mac Store
  3. Preparation of the extension-application. His tasks will include copying the necessary scripts into a shared folder with the master application. To do this, they must have a common AppGroup, through which the exchange will take place.
  4. Publication of the extension-application on its own website.


Example



As an example, consider the possibility of obtaining information about current media using the bash-command system_profiler SPStorageDataType .



Extension Application Preparation



All that is required of this component is copying the script to a specific folder. Therefore, in its interface we will display the only possibility: enabling or disabling the display of information about media (in order not to load the user with details, this can be represented as enabling / disabling plug-ins in the master application).



Apple Sript - bash



The contents of the file extract_storage_info.scpt, which is copied by ectention:



 do shell script "system_profiler SPStorageDataType" 


Preparing Master Applications



For the application to work correctly from the user's point of view, it is necessary to check the availability of additional functionality and hide the corresponding parts of the UI:



 - (BOOL) isStorageInfoAvailable { return [self _storageInfoScriptTask] != nil; } #pragma mark - Private - (NSUserAppleScriptTask *)_storageInfoScriptTask { NSUserAppleScriptTask *result = nil; NSError *error; NSURL *directoryURL = [[NSFileManager defaultManager] URLForDirectory:NSApplicationScriptsDirectory inDomain:NSUserDomainMask appropriateForURL:nil create:YES error:&error]; if (directoryURL) { NSURL *scriptURL = [directoryURL URLByAppendingPathComponent: StorageInfoScriptFileName]; result = [[NSUserAppleScriptTask alloc] initWithURL:scriptURL error:&error]; if (error != nil) { NSLog(@"No AppleScript \"%@\" task error: %@", StorageInfoScriptFileName, error); } } else { //   ,      Sandbox NSLog(@"No Application Scripts folder error: %@", error); } return result; } 


If the script is available, it is called as follows:



 NSUserAppleScriptTask * automationScriptTask = [self _storageInfoScriptTask]; if (automationScriptTask != nil) { [automationScriptTask executeWithAppleEvent:nil completionHandler:^(NSAppleEventDescriptor *resultEventDescriptor, NSError *error) { if (error != nil) { NSLog(@"AppleScript \"%@\" executing error: %@", StorageInfoScriptFileName, error); //TODO:    GUI } else { NSString* resultString = [resultEventDescriptor stringValue]; NSLog(@"Result string:\n%@", resultString); //     } }]; } else { //TODO:    GUI } 


In our simplified example, we display the string received from the executed script as is. To style an application, it will be necessary to parse the result and display only the necessary information.



Application collaboration



As a result, we get the following scheme of work.



Master application



  1. In case of unavailability of additional functionality, it hides UI elements.
  2. In the case of expanding scripts, Apple Script (in a specific format) activates the UI and executes them.
  3. If the functions that Apple Script performs require that the administrator's account data be entered, the user will see the standard authorization dialog — Apple Script will do the work for us.


Extension application



  1. Must be downloaded by the user from the developer site. We are talking about a special site, because it is necessary to explain to the user the principle of the system functioning and the actions that he needs to carry out in order to work correctly. In part, this can be done through the GUI extension.
  2. Despite the fact that we work outside the sandbox, we suggest using the general AppGroup for component solutions.
  3. This component can be represented even more widely - as an Extension Manager. Thanks to a consistent interface, the master application can expand as extensions appear in the shared folder: they can be added along with the description files and configurations.
  4. The Apple Script copied may even contain a common task function (bash_script) that accepts an arbitrary bash command as input and executes it. But this approach opens a big security hole, and also obliges the master-application to contain an extension before publishing to the App Store.


findings



Advantages of the approach:





Minuses:





This article offers a solution to the problem with product functionality restrictions dictated by Sandbox for developers. In the future, we will tell you about how the situation looks from the users. If you found other workarounds, we will be happy if you share them in the comments.

Source: https://habr.com/ru/post/323982/



All Articles