Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/html/extensions/Variables/includes/ExtVariables.php on line 198

Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/html/extensions/Variables/includes/ExtVariables.php on line 198

Deprecated: trim(): Passing null to parameter #1 ($string) of type string is deprecated in /var/www/html/extensions/Variables/includes/ExtVariables.php on line 198
WorkflowKit.framework: Difference between revisions - iPhone Development Wiki

WorkflowKit.framework: Difference between revisions

From iPhone Development Wiki
m (minor improvements)
(Added 15.0+ WorkflowKit stuff)
Line 1: Line 1:
{{infobox Framework
{{infobox Framework
| vis = Private
| vis = Private
| since = 12.0
| since = 13.0
}}
}}


'''WorkflowKit''' is the framework that acts as a backend to the Shortcuts app. It provides around 80% functionality of the Shortcuts app including (but not limited to) actions (though ActionKit also powers a lot of them), handles how shortcuts are imported, how they're stored, etc. It is noted that while it is technically added in 12.0, most of its functionality came in iOS 13.0.
'''WorkflowKit''' is the framework that acts as a backend to the Shortcuts app. It provides around 80% functionality of the Shortcuts app including (but not limited to) actions (though ActionKit also powers a lot of them), handles how shortcuts are imported, how they're stored, etc. It was added to iOS in iOS 13, although iOS 12 Shortcuts's embedded WorkflowAppKit framework does bare a lot of similarities, with some code being reused.  


For examples on how to use this framework, see the [[#Example Code | Example Code]] section of this page.
For examples on how to use this framework, see the [[#Example Code | Example Code]] section of this page.
Line 18: Line 18:


'''WFAction''' is basically the class that every shortcuts action uses. It should be noted that actions aren't all WFAction, but rather their own class that inherit from it (For example, WFExitShortcut in ActionKit).
'''WFAction''' is basically the class that every shortcuts action uses. It should be noted that actions aren't all WFAction, but rather their own class that inherit from it (For example, WFExitShortcut in ActionKit).
== WFGallerySessionManager ==
Handles some of gallery, as well as uploading (WFGallerySessionManager uploadWorkflow).
== WFShortcutExtractor ==
Exclusive to iOS 15+. Handles extracting a shortcut being imported, both supporting unsigned and signed shortcuts. To allow unsigned shortcuts, enable allowsOldFileFormat.


== Example Code ==
== Example Code ==
Line 27: Line 35:
// WFWorkflowRecord handles how shortcuts are stored and hooking it will affect every shortcut loaded - not only is this bad for performance, but if you make a mistake, every shortcut will be affected, hence it's best to avoid hooking it when possible. Here, we hook WFSharedShortcut and affect its workflow record instead
// WFWorkflowRecord handles how shortcuts are stored and hooking it will affect every shortcut loaded - not only is this bad for performance, but if you make a mistake, every shortcut will be affected, hence it's best to avoid hooking it when possible. Here, we hook WFSharedShortcut and affect its workflow record instead
     id rettype = %orig;
     id rettype = %orig;
     id rettypeactions = [rettype actions];
     NSArray *origShortcutActions = [rettype actions];
    NSArray *origShortcutActions = rettypeactions;
     NSMutableArray *newMutableShortcutActions = [origShortcutActions mutableCopy];
    NSArray *newShortcutActions = rettypeactions;
     NSMutableArray *newMutableShortcutActions = [newShortcutActions mutableCopy];
     int shortcutActionsObjectIndex = 0;
     int shortcutActionsObjectIndex = 0;
      
      
     for (id shortcutActionsObject in origShortcutActions) {
     for (id shortcutActionsObject in origShortcutActions) {
         if ([shortcutActionsObject isKindOfClass:[NSDictionary class]]){
         if ([shortcutActionsObject isKindOfClass:[NSDictionary class]]){
            if ([shortcutActionsObject objectForKey:@"WFWorkflowActionIdentifier"]) {
// All shortcuts have an identifier to help identify the action (is.workflow.actions.returntohomescreen is Return to Homescreen, is.workflow.actions.exit is Exit Shortcut). You can find the default action identifiers in /System/​Library/​PrivateFrameworks/​WorkflowKit.framework/WFActions.plist
// All shortcuts have an identifier to help identify the action (is.workflow.actions.returntohomescreen is Return to Homescreen, is.workflow.actions.exit is Exit Shortcut). You can find the default action identifiers in /System/​Library/​PrivateFrameworks/​WorkflowKit.framework/WFActions.plist
             if ([[shortcutActionsObject valueForKey:@"WFWorkflowActionIdentifier"] isEqual:@"is.workflow.actions.returntohomescreen"]) {
             if ([[shortcutActionsObject objectForKey:@"WFWorkflowActionIdentifier"] isEqualToString:@"is.workflow.actions.returntohomescreen"]) {
             NSMutableDictionary *mutableShortcutActionsObject = [shortcutActionsObject mutableCopy];
             NSMutableDictionary *mutableShortcutActionsObject = [shortcutActionsObject mutableCopy];
// While not demo'ed in this example, actions also have WFWorkflowActionParameters. For example, the file path in Get File is the WFGetFilePath parameter. These can also be found in WFActions.plist, or by extracting an unsigned .shortcut/.wflow file and looking to see the parameters of the action in the shortcut.
// While not demo'ed in this example, actions also have WFWorkflowActionParameters. For example, the file path in Get File is the WFGetFilePath parameter. These can also be found in WFActions.plist, or by extracting an unsigned .shortcut/.wflow file and looking to see the parameters of the action in the shortcut.
Line 45: Line 50:
             NSDictionary *newShortDict = [[NSDictionary alloc] initWithDictionary:mutableShortcutActionsObject];
             NSDictionary *newShortDict = [[NSDictionary alloc] initWithDictionary:mutableShortcutActionsObject];
             newMutableShortcutActions[shortcutActionsObjectIndex] = newShortDict;
             newMutableShortcutActions[shortcutActionsObjectIndex] = newShortDict;
            }
             }
             }
         }
         }
Line 53: Line 57:
     shortcutActionsObjectIndex = 0;
     shortcutActionsObjectIndex = 0;


    rettypeactions = [[NSArray alloc] initWithArray:newMutableShortcutActions];
     [rettype setActions:newMutableShortcutActions];
     [rettype setActions:newMutableShortcutActions];
     return rettype;
     return rettype;

Revision as of 04:10, 13 November 2022

WorkflowKit.framework
Private Framework
Availabile 13.0 – present
Headers [headers.cynder.me]


WorkflowKit is the framework that acts as a backend to the Shortcuts app. It provides around 80% functionality of the Shortcuts app including (but not limited to) actions (though ActionKit also powers a lot of them), handles how shortcuts are imported, how they're stored, etc. It was added to iOS in iOS 13, although iOS 12 Shortcuts's embedded WorkflowAppKit framework does bare a lot of similarities, with some code being reused.

For examples on how to use this framework, see the Example Code section of this page.

WFWorkflowRecord

WFWorkflowRecord is how shortcuts are stored. The biggest thing is actions: Every action has an action identifier to identify an action (WFWorkflowActionIdentifier), and some have parameters of what is in said action (WFWorkflowActionParameters). However, it also handles other data about the shortcut, such as its name and minimum client version it can be imported on.

WFBundledActionProvider

WFBundledActionProvider is what provides WorkflowKit with what actions it loads.

WFAction

WFAction is basically the class that every shortcuts action uses. It should be noted that actions aren't all WFAction, but rather their own class that inherit from it (For example, WFExitShortcut in ActionKit).

WFGallerySessionManager

Handles some of gallery, as well as uploading (WFGallerySessionManager uploadWorkflow).

WFShortcutExtractor

Exclusive to iOS 15+. Handles extracting a shortcut being imported, both supporting unsigned and signed shortcuts. To allow unsigned shortcuts, enable allowsOldFileFormat.

Example Code

Replacing Return to Homescreen with Exit Shortcut upon shortcut import

%hook WFSharedShortcut
-(id)workflowRecord {
// WFWorkflowRecord handles how shortcuts are stored and hooking it will affect every shortcut loaded - not only is this bad for performance, but if you make a mistake, every shortcut will be affected, hence it's best to avoid hooking it when possible. Here, we hook WFSharedShortcut and affect its workflow record instead
    id rettype = %orig;
    NSArray *origShortcutActions = [rettype actions];
    NSMutableArray *newMutableShortcutActions = [origShortcutActions mutableCopy];
    int shortcutActionsObjectIndex = 0;
    
    for (id shortcutActionsObject in origShortcutActions) {
        if ([shortcutActionsObject isKindOfClass:[NSDictionary class]]){
// All shortcuts have an identifier to help identify the action (is.workflow.actions.returntohomescreen is Return to Homescreen, is.workflow.actions.exit is Exit Shortcut). You can find the default action identifiers in /System/​Library/​PrivateFrameworks/​WorkflowKit.framework/WFActions.plist
            if ([[shortcutActionsObject objectForKey:@"WFWorkflowActionIdentifier"] isEqualToString:@"is.workflow.actions.returntohomescreen"]) {
            NSMutableDictionary *mutableShortcutActionsObject = [shortcutActionsObject mutableCopy];
// While not demo'ed in this example, actions also have WFWorkflowActionParameters. For example, the file path in Get File is the WFGetFilePath parameter. These can also be found in WFActions.plist, or by extracting an unsigned .shortcut/.wflow file and looking to see the parameters of the action in the shortcut.
    
            [mutableShortcutActionsObject setValue:@"is.workflow.actions.exit" forKey:@"WFWorkflowActionIdentifier"];
    
            NSDictionary *newShortDict = [[NSDictionary alloc] initWithDictionary:mutableShortcutActionsObject];
            newMutableShortcutActions[shortcutActionsObjectIndex] = newShortDict;
            }
        }
        shortcutActionsObjectIndex++;
    }
    
    shortcutActionsObjectIndex = 0;

    [rettype setActions:newMutableShortcutActions];
    return rettype;
}
%end

Iterating through all actions being loaded

%hook WFBundledActionProvider
-(id)createAllAvailableActions {
	id createactions = %orig; //__NSSetM
	for (id newCreateAction in createactions) {
		NSLog(@"Shortcut Action identifier: %@",[newCreateAction identifier]);
		if ([[newCreateAction identifier]isEqualToString:@"is.workflow.actions.exit"]){
			// the action being iterated has the action identifier of is.workflow.actions.exit - this means we found the exit shortcut action!
			NSLog(@"Exit action: %@", newCreateAction);
		}
	}

	return createactions;
}
%end

References