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

Added InterAppCommunication via /dev/iac #315

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app/AppDelegate.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

#import <UIKit/UIKit.h>

#define kGroupName @"group.app.ish.iSH"

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
Expand Down
20 changes: 19 additions & 1 deletion app/AppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
// Created by Theodore Dubois on 10/17/17.
//

#import <Foundation/Foundation.h>
redbug26 marked this conversation as resolved.
Show resolved Hide resolved

#include <resolv.h>
#include <arpa/inet.h>
#include <netdb.h>
Expand All @@ -14,6 +16,9 @@
#include "kernel/init.h"
#include "kernel/calls.h"

#import "IOSGateway.h"


@interface AppDelegate ()

@property BOOL exiting;
Expand All @@ -36,7 +41,7 @@ @implementation AppDelegate

- (int)startThings {
NSFileManager *manager = [NSFileManager defaultManager];
NSURL *container = [manager containerURLForSecurityApplicationGroupIdentifier:@"group.app.ish.iSH"];
NSURL *container = [manager containerURLForSecurityApplicationGroupIdentifier:kGroupName];
NSURL *alpineRoot = [container URLByAppendingPathComponent:@"roots/alpine"];
[manager createDirectoryAtURL:[container URLByAppendingPathComponent:@"roots"]
withIntermediateDirectories:YES
Expand Down Expand Up @@ -124,6 +129,9 @@ - (int)startThings {
generic_mknod("/dev/random", S_IFCHR|0666, dev_make(1, 8));
generic_mknod("/dev/urandom", S_IFCHR|0666, dev_make(1, 9));

generic_mknod("/dev/iac", S_IFCHR|0666, dev_make(1, 99));


do_mount(&procfs, "proc", "/proc");
do_mount(&devptsfs, "devpts", "/dev/pts");

Expand All @@ -135,6 +143,8 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
// get the network permissions popup to appear on chinese devices
[[NSURLSession.sharedSession dataTaskWithURL:[NSURL URLWithString:@"http://captive.apple.com"]] resume];

[[IOSGateway sharedSession] setup];

[UserPreferences.shared addObserver:self forKeyPath:@"shouldDisableDimming" options:NSKeyValueObservingOptionInitial context:nil];
int err = [self startThings];
if (err < 0) {
Expand All @@ -148,6 +158,14 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
return YES;
}

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
{
if ([[IOSGateway sharedSession] handleOpenURL:url]) {
return YES;
}
return NO;
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
UIApplication.sharedApplication.idleTimerDisabled = UserPreferences.shared.shouldDisableDimming;
}
Expand Down
24 changes: 24 additions & 0 deletions app/IOSGateway.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
//
// IOSGateway.h
// iSH
//
// Created by Miguel Vanhove on 15/02/2019.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface IOSGateway : NSObject

+ (IOSGateway *_Nullable ) sharedSession;

- (void)setup;
- (BOOL)handleOpenURL:(NSURL *)url;
redbug26 marked this conversation as resolved.
Show resolved Hide resolved

@end

extern size_t iac_read(void *buf, size_t bufsize);
extern size_t iac_write(const void *buf, size_t bufsize);

NS_ASSUME_NONNULL_END
121 changes: 121 additions & 0 deletions app/IOSGateway.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
//
// IOSGateway.m
// iSH
//
// Created by Miguel Vanhove on 15/02/2019.
//

#import "IOSGateway.h"
#import "IACManager.h"
#import "UIApplication+OpenURL.h"

static IOSGateway *iOSGateway = nil;

@interface IOSGateway ()
redbug26 marked this conversation as resolved.
Show resolved Hide resolved
{
redbug26 marked this conversation as resolved.
Show resolved Hide resolved
}

@property (copy, nonatomic) NSData *iacResult;

@end

@implementation IOSGateway
{
redbug26 marked this conversation as resolved.
Show resolved Hide resolved
}

+ (IOSGateway *_Nullable)sharedSession
redbug26 marked this conversation as resolved.
Show resolved Hide resolved
{
if (iOSGateway == nil) {
iOSGateway = [[IOSGateway alloc] init];
redbug26 marked this conversation as resolved.
Show resolved Hide resolved
}

return iOSGateway;
}

- (id)init
{
self = [super init];
if (self != nil) {
redbug26 marked this conversation as resolved.
Show resolved Hide resolved
self.iacResult = [[NSData alloc] init];
}
return self;
}

- (void)setup
{
#ifndef TARGET_IS_EXTENSION

[IACManager sharedManager].callbackURLScheme = @"x-ish";

[[IACManager sharedManager] handleAction:@"iac"
withBlock: ^(NSDictionary *inputParameters, IACSuccessBlock success, IACFailureBlock failure) {
if (success) {
NSError *__autoreleasing jserr = nil;

self.iacResult = [NSJSONSerialization dataWithJSONObject:inputParameters options:0 error:&jserr];

success(@{ @"names": @"json" }, NO);
}
}];
#endif
}

- (BOOL)handleOpenURL:(NSURL *)url
{
#ifndef TARGET_IS_EXTENSION
return [[IACManager sharedManager] handleOpenURL:url];
#else
return false;
#endif
}

extern size_t iac_write(const void *buf, size_t bufsize)
{
#ifndef TARGET_IS_EXTENSION

NSData *data = [NSData dataWithBytes:buf length:bufsize];
NSString *command = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

dispatch_sync(dispatch_get_main_queue(), ^{
IOSGateway *ic = [IOSGateway sharedSession];

NSString *cmdString = [command stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];

ic.iacResult = [[NSData alloc] init]; // Reset result

[UIApplication openURL:cmdString];
});

#endif

return bufsize;
}

extern size_t iac_read(void *buf, size_t bufsize)
redbug26 marked this conversation as resolved.
Show resolved Hide resolved
{
#ifndef TARGET_IS_EXTENSION

IOSGateway *ic = [IOSGateway sharedSession];

if (bufsize < [ic.iacResult length]) {
memcpy(buf, [ic.iacResult bytes], bufsize);

ic.iacResult = [ic.iacResult subdataWithRange:NSMakeRange(bufsize, [ic.iacResult length] - bufsize)];

return bufsize;
}

NSUInteger length = [ic.iacResult length];

memcpy(buf, [ic.iacResult bytes], length);

ic.iacResult = [[NSData alloc] init];

return length;

#endif

return 0;
}

@end
15 changes: 13 additions & 2 deletions app/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,27 @@
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>CFBundleURLSchemes</key>
<array>
<string>x-ish</string>
</array>
</dict>
</array>
<key>CFBundleVersion</key>
<string>48</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIFileSharingEnabled</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIFileSharingEnabled</key>
<true/>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
Expand Down
50 changes: 50 additions & 0 deletions app/InterAppCommunication/IACClient.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
//
// IACClient.h
// IACSample
//
// Created by Antonio Cabezuelo Vivo on 09/02/13.
// Copyright (c) 2013 Antonio Cabezuelo Vivo. All rights reserved.
//

#import <Foundation/Foundation.h>
#import "IACManager.h"

/* This is the class used to make calls to external apps. Use this class as a superclass to create classes for your own apps. Thjis way you can offer a clean API to your app that can meke interact with it easier for other apps.
*/
@interface IACClient : NSObject

// URL scheme that the external app is listenig to. This is mandatory.
@property (copy, nonatomic) NSString *URLScheme;

// The manager to use for calls from this client. If not set, IACManager shared instance will be used.
@property (weak, nonatomic) IACManager *manager;

// Initializers
+ (instancetype)client;
+ (instancetype)clientWithURLScheme:(NSString*)scheme;
- (instancetype)initWithURLScheme:(NSString*)scheme;

/* Utility method to test if the app that responds to the URLScheme is installed in the device.
*/
- (BOOL)isAppInstalled;


/* Method that transforms from x-callback-url errorCode parameter to a NSInteger to be used in NSError's code.
The default implementation return [code integerValue].
If you create a subclass for your app and your app return string error codes you must implement this method to transform from your error codes to integer values.
*/
- (NSInteger)NSErrorCodeForXCUErrorCode:(NSString*)code;

/* Convenient methods to make call to external apps. If you create a subclass for your app, call these methods to launch the external app.
*/
- (void)performAction:(NSString*)action;

- (void)performAction:(NSString*)action
parameters:(NSDictionary*)params;

- (void)performAction:(NSString*)action
parameters:(NSDictionary*)params
onSuccess:(void(^)(NSDictionary*result))success
redbug26 marked this conversation as resolved.
Show resolved Hide resolved
onFailure:(void(^)(NSError*))failure;

@end
72 changes: 72 additions & 0 deletions app/InterAppCommunication/IACClient.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
//
// IACClient.m
// IACSample
//
// Created by Antonio Cabezuelo Vivo on 09/02/13.
// Copyright (c) 2013 Antonio Cabezuelo Vivo. All rights reserved.
//

#import <UIKit/UIKit.h>

#import "IACClient.h"
#import "IACRequest.h"
#import "IACManager.h"

#if !__has_feature(objc_arc)
#error InterAppComutication must be built with ARC.
// You can turn on ARC for only InterAppComutication files by adding -fobjc-arc to the build phase for each of its files.
#endif


@implementation IACClient

+ (instancetype)client {
return [[self alloc] init];
}

+ (instancetype)clientWithURLScheme:(NSString*)scheme {
return [[self alloc] initWithURLScheme:scheme];
}

- (instancetype)initWithURLScheme:(NSString*)scheme {
self = [super init];
if (self) {
self.URLScheme = scheme;
}
return self;
}

- (NSInteger)NSErrorCodeForXCUErrorCode:(NSString*)code {
return [code integerValue];
}

- (BOOL)isAppInstalled {
return [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:[NSString stringWithFormat:@"%@://Test", self.URLScheme]]];
}

- (void)performAction:(NSString*)action {
[self performAction:action parameters:nil];
}

- (void)performAction:(NSString*)action parameters:(NSDictionary*)params {
[self performAction:action parameters:params onSuccess:nil onFailure:nil];
}


- (void)performAction:(NSString*)action parameters:(NSDictionary*)params onSuccess:(void(^)(NSDictionary*result))success onFailure:(void(^)(NSError*))failure {

IACRequest *request = [[IACRequest alloc] init];
request.client = self;
request.action = action;
request.parameters = params;
request.successCalback = success;
request.errorCalback = failure;

if (self.manager) {
[self.manager sendIACRequest:request];
} else {
[[IACManager sharedManager] sendIACRequest:request];
}
}

@end
Loading