diff --git a/idb_companion/Server/FBIDBServiceHandler.mm b/idb_companion/Server/FBIDBServiceHandler.mm index 580998985..b3241b6f8 100644 --- a/idb_companion/Server/FBIDBServiceHandler.mm +++ b/idb_companion/Server/FBIDBServiceHandler.mm @@ -12,6 +12,7 @@ #import #import "FBBundleStorageManager.h" +#import "FBDataDownloadInput.h" #import "FBIDBCommandExecutor.h" #import "FBIDBPortsConfiguration.h" #import "FBIDBServiceHandler.h" @@ -479,6 +480,20 @@ static void fill_crash_log_response(idb::CrashLogResponse *response, const NSArr return nil; } } + case idb::Payload::kUrl: { + NSURL *url = [NSURL URLWithString:[NSString stringWithCString:payload.url().c_str() encoding:NSUTF8StringEncoding]]; + FBDataDownloadInput *download = [FBDataDownloadInput dataDownloadWithURL:url logger:_target.logger]; + switch (destination) { + case idb::InstallRequest_Destination::InstallRequest_Destination_APP: + return [_commandExecutor install_stream:download.input]; + case idb::InstallRequest_Destination::InstallRequest_Destination_XCTEST: + return [_commandExecutor xctest_install_stream:download.input]; + case idb::InstallRequest_Destination::InstallRequest_Destination_DYLIB: + return [_commandExecutor install_dylib_stream:download.input name:name]; + default: + return nil; + } + } case idb::Payload::kFilePath: { NSString *filePath = nsstring_from_c_string(payload.file_path()); switch (destination) { diff --git a/idb_companion/Utility/FBDataDownloadInput.h b/idb_companion/Utility/FBDataDownloadInput.h new file mode 100644 index 000000000..7720396f3 --- /dev/null +++ b/idb_companion/Utility/FBDataDownloadInput.h @@ -0,0 +1,39 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import + +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + Converts a data download into the input of a process + */ +@interface FBDataDownloadInput : NSObject + +#pragma mark Initializers + +/** + The Designated Initializer. + + @param url the url to download + @param logger the logger to use. + @return a data download instance. + */ ++ (instancetype)dataDownloadWithURL:(NSURL *)url logger:(id)logger; + +#pragma mark Properties + +/** + The process input that will be bridged. + */ +@property (nonatomic, strong, readonly) FBProcessInput> *input; + +@end + +NS_ASSUME_NONNULL_END diff --git a/idb_companion/Utility/FBDataDownloadInput.m b/idb_companion/Utility/FBDataDownloadInput.m new file mode 100644 index 000000000..b966ab880 --- /dev/null +++ b/idb_companion/Utility/FBDataDownloadInput.m @@ -0,0 +1,59 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#import "FBDataDownloadInput.h" + +@interface FBDataDownloadInput () + +@property (nonatomic, strong, readonly) NSURLSessionTask *task; +@property (nonatomic, strong, readonly) id logger; + +@end + +@implementation FBDataDownloadInput + +#pragma mark Initializers + ++ (instancetype)dataDownloadWithURL:(NSURL *)url logger:(id)logger +{ + FBDataDownloadInput *download = [[self alloc] initWithURL:url logger:logger]; + [download.task resume]; + return download; +} + +- (instancetype)initWithURL:(NSURL *)url logger:(id)logger +{ + self = [super init]; + if (!self) { + return nil; + } + + _logger = logger; + NSURLSessionConfiguration *configuration = NSURLSessionConfiguration.defaultSessionConfiguration; + NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration delegate:self delegateQueue:NSOperationQueue.new]; + _input = FBProcessInput.inputFromConsumer; + _task = [session dataTaskWithURL:url]; + + return self; +} + +#pragma mark NSURLSessionDelegate + +- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data +{ + [self.input.contents consumeData:data]; +} + +- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error +{ + if (error) { + [self.logger.error logFormat:@"Download task %@ failed with error %@", task, error]; + } + [self.input.contents consumeEndOfFile]; +} + +@end diff --git a/proto/idb.proto b/proto/idb.proto index 24be5cd67..cdf70f231 100755 --- a/proto/idb.proto +++ b/proto/idb.proto @@ -46,6 +46,7 @@ message Payload { oneof source { string file_path = 1; bytes data = 2; + string url = 3; } }