diff --git a/iOS/FlipperKit.podspec b/iOS/FlipperKit.podspec index df91cf9f2..85694af6f 100644 --- a/iOS/FlipperKit.podspec +++ b/iOS/FlipperKit.podspec @@ -156,4 +156,13 @@ Pod::Spec.new do |spec| ss.source_files = "iOS/Plugins/FlipperKitExamplePlugin/**/*.{h,mm}" ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)\"/Headers/Private/FlipperKit/**" } end + + spec.subspec "FlipperKitCrashReporterPlugin" do |ss| + ss.header_dir = "FlipperKitCrashReporterPlugin" + ss.dependency 'FlipperKit/Core' + ss.compiler_flags = folly_compiler_flags + ss.public_header_files = 'iOS/Plugins/FlipperKitCrashReporterPlugin/FlipperKitCrashReporterPlugin.h' + ss.source_files = "iOS/Plugins/FlipperKitCrashReporterPlugin/**/*.{h,mm}" + ss.pod_target_xcconfig = { "HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)\"/Headers/Private/FlipperKit/**" } + end end diff --git a/iOS/Plugins/FlipperKitCrashReporterPlugin/FlipperKitCrashReporterPlugin/FlipperKitCrashReporterPlugin.h b/iOS/Plugins/FlipperKitCrashReporterPlugin/FlipperKitCrashReporterPlugin/FlipperKitCrashReporterPlugin.h new file mode 100644 index 000000000..0eb964c20 --- /dev/null +++ b/iOS/Plugins/FlipperKitCrashReporterPlugin/FlipperKitCrashReporterPlugin/FlipperKitCrashReporterPlugin.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 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 +#import + +@interface FlipperKitCrashReporterPlugin : NSObject +- (instancetype)init NS_UNAVAILABLE; ++ (instancetype) sharedInstance; +@end + + +#endif diff --git a/iOS/Plugins/FlipperKitCrashReporterPlugin/FlipperKitCrashReporterPlugin/FlipperKitCrashReporterPlugin.mm b/iOS/Plugins/FlipperKitCrashReporterPlugin/FlipperKitCrashReporterPlugin/FlipperKitCrashReporterPlugin.mm new file mode 100644 index 000000000..b5ce51a3b --- /dev/null +++ b/iOS/Plugins/FlipperKitCrashReporterPlugin/FlipperKitCrashReporterPlugin/FlipperKitCrashReporterPlugin.mm @@ -0,0 +1,76 @@ +/* + * 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 "FlipperKitCrashReporterPlugin.h" +#import + +@interface FlipperKitCrashReporterPlugin() +@property (strong, nonatomic) id connection; +@property (assign, nonatomic) NSUInteger notificationID; +@property (assign, nonatomic) NSUncaughtExceptionHandler *prevHandler; +- (void) handleException:(NSException *)exception; + +@end + +void flipperkitUncaughtExceptionHandler(NSException *exception) { + NSLog(@"CRASH: %@", exception); + NSLog(@"Stack Trace: %@", [exception callStackSymbols]); + [[FlipperKitCrashReporterPlugin sharedInstance] handleException:exception]; +} + +@implementation FlipperKitCrashReporterPlugin + +- (instancetype)init { + if (self = [super init]) { + _connection = nil; + _notificationID = 0; + _prevHandler = NSGetUncaughtExceptionHandler(); + } + return self; +} + ++ (instancetype)sharedInstance { + static FlipperKitCrashReporterPlugin *sInstance = nil; + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + sInstance = [FlipperKitCrashReporterPlugin new]; + }); + + return sInstance; +} + +- (NSString *)identifier { + return @"CrashReporter"; +} + +- (void) handleException:(NSException *)exception { + // TODO: Rather than having indirection from c function, somehow pass objective c selectors as a c function pointer to NSSetUncaughtExceptionHandler + self.notificationID += 1; + [self.connection send:@"crash-report" withParams:@{@"reason": [exception reason], @"name": [exception name], @"callstack": [exception callStackSymbols]}]; + if (self.prevHandler) { + self.prevHandler(exception); + } +} + +- (void)didConnect:(id)connection { + self.connection = connection; + NSSetUncaughtExceptionHandler(&flipperkitUncaughtExceptionHandler); +} + +- (void)didDisconnect { + self.connection = nil; + NSSetUncaughtExceptionHandler(self.prevHandler); +} + +- (BOOL)runInBackground { + return YES; +} + +@end +#endif diff --git a/iOS/Sample/AppDelegate.mm b/iOS/Sample/AppDelegate.mm index 6db8d0acf..19a2284f4 100644 --- a/iOS/Sample/AppDelegate.mm +++ b/iOS/Sample/AppDelegate.mm @@ -6,7 +6,7 @@ * */ #import "AppDelegate.h" - +#import #import #import #import @@ -38,6 +38,7 @@ withDescriptorMapper: layoutDescriptorMapper]]; [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]]; + [client addPlugin:[FlipperKitCrashReporterPlugin sharedInstance]]; [[FlipperClient sharedClient] addPlugin: [[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]]; [client addPlugin:[FlipperKitExamplePlugin sharedInstance]]; diff --git a/iOS/Sample/MainStoryBoard.storyboard b/iOS/Sample/MainStoryBoard.storyboard index e6d0b17e7..85af50dd0 100644 --- a/iOS/Sample/MainStoryBoard.storyboard +++ b/iOS/Sample/MainStoryBoard.storyboard @@ -1,11 +1,11 @@ - + - + @@ -259,6 +259,9 @@ + + + @@ -319,9 +322,6 @@ - - - diff --git a/iOS/Sample/Podfile b/iOS/Sample/Podfile index 22e288af4..a01055e56 100644 --- a/iOS/Sample/Podfile +++ b/iOS/Sample/Podfile @@ -10,6 +10,7 @@ target 'Sample' do pod 'FlipperKit/SKIOSNetworkPlugin', :path => '../../FlipperKit.podspec' pod 'FlipperKit/FlipperKitUserDefaultsPlugin', :path => '../../FlipperKit.podspec' pod 'FlipperKit/FlipperKitExamplePlugin', :path => '../../FlipperKit.podspec' + pod 'FlipperKit/FlipperKitCrashReporterPlugin', :path => '../../FlipperKit.podspec' pod 'Flipper', :path => '../../Flipper.podspec' post_install do |installer|