FxFactory Framework

Beginning with FxFactory 5.0.8, a new API allows any code executing on the system to interact with FxFactory. The primary goals of this API is to allow products that do not rely on the FxFactory runtime to do the following:

  • Check on the registration status for a given product.
  • Launch the FxFactory application to focus on a given product and/or initiate a purchase transaction.
  • Bring up a Tech Support form pre-filled with information of your choice, to allow users to request assistance with your product through FxFactory.
  • Check for new versions of your product, as advertised through our servers. In recent versions of FxFactory, this step is optional: as soon as your product checks for licensing status, FxFactory will automatically check for a new version of your software and allow users to begin the auto-update process.
A product is identified by its UUID, a unique identifier that allows various entities (our app, our plug-ins, our servers, and now your code too) to unequivocally identify each product available through FxFactory.

Checking for the licensing status of a product allows you to decide whether the product should run in trial mode or with its full feature set. Trial products may choose to render a watermark in its output, hide or limit certain functionality, etc.

When your code detects an error, your code can migrate any diagnostic information about the error to a new tech support contact form (for example: ”An error occurred reading file X when processing a frame with plug-in Y.”) This allows for faster resolution of any problems users may encounter with your product.

The API described above is provided by the FxFactory.framework. This framework is available on your system as long as any recent version of our software is installed.

Linking against the Framework

To get a copy of the FxFactory.framework, all you have to do is install a recent version of FxFactory. The framework’s install location is:

/Library/Frameworks/FxFactory.framework

Add this framework to your project, and make sure it is part of the link phase for the appropriate target (or targets) that will need to use our API. We recommend that you link to our framework weakly, allowing your code to run even if the FxFactory.framework is missing from the system. The user may have uninstalled FxFactory, or deleted the framework by accident.

Start by adding the framework to your project. Drag the FxFactory.framework from the Finder to the Frameworks, Libraries, and Embedded Content section of your target:

Frameworks, Libraries, and Embedded Content

Frameworks, Libraries, and Embedded Content

If this is the first external framework you add to your target, Xcode will automatically create a Frameworks folder in your file hierarchy, and add the FxFactory.framework to it:

Frameworks

Frameworks

Select the framework:

While the framework is selected, open the inspector and right-click on each target that links against it. Switch the linking strategy to Optional:

Weak-linking against the framework

Weak-linking against the framework

When your code weak-links to the FxFactory.framework, its symbols may not be available at runtime. This would happen if FxFactory is not installed. The recommended approach is to treat the product as unlicensed (e.g. running in trial mode) and request the user to download and install a copy of FxFactory from our website.

Refer to this page on the Apple developer website for a detailed explanation of weak-linking:

Frameworks and Weak Linking

Supporting the Hardened Runtime

In most situations, the app or loadable plug-in you are working on will necessarily have the Hardened Runtime option enabled. Since your software is code-signed using a different identity than FxFactory, the Hardened Runtime will, by default, disallow your code from accessing the FxFactory framework while running.

To solve this problem, you need to enable the Disable Library Validation option available under the Signing & Capabilities section of your Target configuration:

Disable Library Validation

Disable Library Validation

Note that in Debug builds and/or while running your software through the debugger, you may not encounter any problems accessing the FxFactory framework due to the fact that certain rules of the Hardened Runtime are automatically relaxed. Make sure the Disable Library Validation option remains enabled for the Release version of your product.

Entitlements for PlugInKit Clients

When planning to use the FxFactory framework from an FxPlug plug-in, you need to take some additional measures to ensure that our framework is allowed to load, and access relevant licensing information for your product.

The entitlements you pick for the PlugInKit wrapper app do not matter, but the ones you choose for the actual FxPlug component do. Make sure the App Sandbox is turned off. If you followed the previous instructions related to the Hardened Runtime your entitlements file should also contain the entry that disables library validation:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "https://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
  <dict>
    <key>com.apple.security.app-sandbox</key>
    <false/>
    <key>com.apple.security.cs.disable-library-validation</key>
    <true/>
  </dict>
</plist>

It is necessary to turn off the App Sandbox for the PlugInKit process because your plug-in would otherwise be unable to read any licensing information for your product. Since FxFactory records this information via NSUserDefaults on its own domain, any sandboxed process would not – by default – be able to access this information outside its container. While Apple offers ways for code signed by the same team ID to access common NSUserDefaults domains, there is no way for one app (FxFactory) to grant access to its domain to just about any other process out there.

Using our APIs from C and Objective-C

If you hard-linked to the FxFactory framework, your code will cause an error if the framework is not installed on disk. When you weak-link your binary to the FxFactory framework (as recommended) the linker resolves all weak symbols automatically if the framework is installed. Symbols remain NULL otherwise.

Remember to test you code with and without the FxFactory.framework. Drag the framework away from its install location to prevent it from being loaded by your code.

The API exposed by the framework is located in the FxFactoryLicensing.h header. It is a simple, C-based API. If you have weak-linked your code against the FxFactory framework, check for each function pointer to be non-NULL before invoking it. Heed the warning contained in the official Apple documentation: use the explicit comparison against NULL rather than the ! operator, or else it will not work as expected:

#import <FxFactory/FxFactory.h>

FxFactoryLicensingStatus status = kFxFactoryLicensingStatusProductUnlicensed;

if (FxFactoryGetLicensingStatus != NULL) {
    status = FxFactoryGetLicensingStatus(...);
} else {
    // Remind user that FxFactory must be installed
}

if (status == kFxFactoryLicensingStatusProductIsLicensed) {
    // Product has been purchased.
}

Refer to the documentation in the header for an explanation of the API, the meaning of its parameters, and the meaning of the values returned by each function.

It is important to point out certain requirements and behaviors of the API:

  • The UUID for your product must be assigned and agreed upon in preparation for your product’s distribution through FxFactory.
  • The API will return meaningful results for any valid UUID. That is because it has no prior knowledge of which products may or may not exist in FxFactory, and this information is subject to constant change as our servers, app and website learn about each new product being released. If your code checks for the licensing status of a non-existing product, the API returns trial status indefinitely, and any attempt to initiate a purchase transaction will fail.
  • The API is designed to be efficient, and it may not be necessary or desirable to cache its results. Beginning with FxFactory 7.1.1, the licensing status reported by FxFactoryGetLicensingStatus() is dynamically updated while your code is running. If you wish to handle changes to the licensing status dynamically, refer to the new FxFactoryRegisterLicensingStatusChangeHandler() API.

Using our APIs from Swift

Beginning with FxFactory 8.0.8, it is possible to use the FxFactory framework through a C interface that has been improved for Swift:

  1. Add the FxFactory framework to your project and declare it Optional (weak-linked) so as to allow your Swift code to be loadable even when FxFactory is not available on the system.
  2. Because Swift does not yet provide a way to check if any given weak-linked symbol has been resolved by the linker, the FxFactory framework provides a new inlined function, FxFactory.isInstalled(), your code can use to check if our APIs can be invoked without crashing the app.
  3. The names of our APIs under Swift differ from the underlying C functions. The most common entry point, FxFactoryGetLicensingStatus, can be invoked from Swift via FxFactory.licensingStatus(for:). Look for the parameter to the NS_SWIFT_NAME macro in the the header file to determine how each function may be invoked from Swift.

The code required to check if your product has been licensed through FxFactory from a Swift app is extremely simple:

import FxFactory

static func isLicensed() -> Bool {
    FxFactory.isInstalled() &&
    FxFactory.licensingStatus(for: <UUID>) == .productLicensed
}

Where <UUID> is the string representation of the UUID that uniquely identifies your product within our ecosystem.

Ensuring that Your Software can be Auto-Updated

If you plan on delivering your software as a codesigned application, remember to add the appopriate entries to the Info.plist of each deliverable bundle (app, plug-in, etc) to allow FxFactory to update your software:

{
  "NSUpdateSecurityPolicy": {
    "AllowPackages": [
      0: "AZLNLGPTT3"
    ]
    "AllowProcesses": {
      "AZLNLGPTT3": [
        0: "com.fxfactory.FxFactory”,
        1: “com.fxfactory.FxFactory.helper”
      ]
    }
  }
}

This is discussed in greater detail on  Developer.