Files
flipper/iOS/FlipperKit/FlipperClient.mm
John Knox 8d93946739 Add FBPortForwarding source code
Summary:
See FBPortForwarding/README.md for an explanation of what this is.
It's required for the upcoming support for physical iOS devices.

To simplify development of the JS app, We're going to bundle the pre-built PortForwardingMacApp
inside the repo, and inside the electron app (static/PortForwardingMacApp.app).
Adding this source so users can build it from source if they choose to.

Reviewed By: danielbuechele

Differential Revision: D13276022

fbshipit-source-id: 99b18e0412cf443bb4a67eb4846cc780e0014de1
2018-12-03 11:34:53 -08:00

193 lines
4.9 KiB
Plaintext

/*
* Copyright (c) 2018-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree.
*
*/
#if FB_SONARKIT_ENABLED
#import "FlipperClient.h"
#import "FlipperCppWrapperPlugin.h"
#import <Flipper/FlipperClient.h>
#include <folly/io/async/EventBase.h>
#include <folly/io/async/ScopedEventBaseThread.h>
#import <UIKit/UIKit.h>
#include "SKStateUpdateCPPWrapper.h"
#import "FlipperDiagnosticsViewController.h"
#import "FlipperClient+Testing.h"
#if !TARGET_OS_SIMULATOR
//#import <FKPortForwarding/FKPortForwardingServer.h>
#endif
using WrapperPlugin = facebook::flipper::FlipperCppWrapperPlugin;
@implementation FlipperClient {
facebook::flipper::FlipperClient *_cppClient;
folly::ScopedEventBaseThread sonarThread;
folly::ScopedEventBaseThread connectionThread;
#if !TARGET_OS_SIMULATOR
// FKPortForwardingServer *_server;
#endif
}
+ (instancetype)sharedClient
{
static FlipperClient *sharedClient = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
try {
sharedClient = [[self alloc] init];
} catch (const std::exception &e) {
// fail.
sharedClient = nil;
}
});
return sharedClient;
}
- (instancetype)init
{
if (self = [super init]) {
UIDevice *device = [UIDevice currentDevice];
NSString *deviceName = [device name];
NSBundle *bundle = [NSBundle mainBundle];
NSString *appName = [bundle objectForInfoDictionaryKey:(NSString *)kCFBundleNameKey];
NSString *appId = [bundle bundleIdentifier];
NSString *privateAppDirectory = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES)[0];
NSFileManager *manager = [NSFileManager defaultManager];
if ([manager fileExistsAtPath:privateAppDirectory isDirectory:NULL] == NO &&
![manager createDirectoryAtPath:privateAppDirectory withIntermediateDirectories:YES attributes:nil error:nil]) {
return nil;
}
#if TARGET_OS_SIMULATOR
deviceName = [NSString stringWithFormat:@"%@ %@", [[UIDevice currentDevice] model], @"Simulator"];
#endif
static const std::string UNKNOWN = std::string("unknown");
try {
facebook::flipper::FlipperClient::init({
{
"localhost",
"iOS",
[deviceName UTF8String],
UNKNOWN,
[appName UTF8String] ?: UNKNOWN,
[appId UTF8String] ?: UNKNOWN,
[privateAppDirectory UTF8String],
},
sonarThread.getEventBase(),
connectionThread.getEventBase()
});
_cppClient = facebook::flipper::FlipperClient::instance();
} catch (const std::system_error &e) {
// Probably ran out of disk space.
return nil;
}
}
return self;
}
- (void)refreshPlugins
{
_cppClient->refreshPlugins();
}
- (void)addPlugin:(NSObject<FlipperPlugin> *)plugin
{
_cppClient->addPlugin(std::make_shared<WrapperPlugin>(plugin));
}
- (void)removePlugin:(NSObject<FlipperPlugin> *)plugin
{
_cppClient->removePlugin(std::make_shared<WrapperPlugin>(plugin));
}
- (NSObject<FlipperPlugin> *)pluginWithIdentifier:(NSString *)identifier
{
auto cppPlugin = _cppClient->getPlugin([identifier UTF8String]);
if (auto wrapper = dynamic_cast<WrapperPlugin *>(cppPlugin.get())) {
return wrapper->getObjCPlugin();
}
return nil;
}
- (void)start;
{
#if !TARGET_OS_SIMULATOR
// _server = [FKPortForwardingServer new];
// [_server forwardConnectionsFromPort:8088];
// [_server listenForMultiplexingChannelOnPort:8078];
#endif
_cppClient->start();
}
- (void)stop
{
_cppClient->stop();
#if !TARGET_OS_SIMULATOR
// [_server close];
// _server = nil;
#endif
}
- (NSString *)getState {
return @(_cppClient->getState().c_str());
}
- (NSArray *)getStateElements {
NSMutableArray<NSDictionary<NSString *, NSString *>*> *const array = [NSMutableArray array];
for (facebook::flipper::StateElement element: _cppClient->getStateElements()) {
facebook::flipper::State state = element.state_;
NSString *stateString;
switch (state) {
case facebook::flipper::in_progress:
stateString = @"⏳ ";
break;
case facebook::flipper::success:
stateString = @"✅ ";
break;
case facebook::flipper::failed:
stateString = @"❌ ";
break;
default:
stateString = @"❓ ";
break;
}
[array addObject:@{
@"name": [NSString stringWithUTF8String:element.name_.c_str()],
@"state": stateString
}];
}
return array;
}
- (void)subscribeForUpdates:(id<FlipperStateUpdateListener>)controller {
auto stateListener = std::make_shared<SKStateUpdateCPPWrapper>(controller);
_cppClient->setStateListener(stateListener);
}
@end
@implementation FlipperClient (Testing)
- (instancetype)initWithCppClient:(facebook::flipper::FlipperClient *)cppClient {
if (self = [super init]) {
_cppClient = cppClient;
}
return self;
}
@end
#endif