Run CLANGFORMAT on plugins
Summary: This diff runs CLANGFORMAT lint on plugins. I have added CLANGFORMAT as the lint engined for objc files in xplat/sonar. Right now the iOS folder is not formatted according to CLANGFORMAT. Ran `arc lint -a --paths-cmd "find ./iOS/Plugins -type f" --verbose` Reviewed By: passy Differential Revision: D19942173 fbshipit-source-id: 8b975b0a344df073b02d69cd1f9ee5629af2799d
This commit is contained in:
committed by
Facebook Github Bot
parent
a19a430eee
commit
e8b20d5b15
@@ -13,12 +13,16 @@
|
||||
#import "SKBufferingPlugin.h"
|
||||
#import "SKNetworkReporter.h"
|
||||
|
||||
@interface FlipperKitNetworkPlugin : SKBufferingPlugin <SKNetworkReporterDelegate>
|
||||
@interface FlipperKitNetworkPlugin
|
||||
: SKBufferingPlugin<SKNetworkReporterDelegate>
|
||||
|
||||
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter NS_DESIGNATED_INITIALIZER;
|
||||
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter queue:(dispatch_queue_t)queue; //For test purposes
|
||||
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter
|
||||
NS_DESIGNATED_INITIALIZER;
|
||||
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter
|
||||
queue:(dispatch_queue_t)
|
||||
queue; // For test purposes
|
||||
|
||||
@property (strong, nonatomic) id<SKNetworkAdapterDelegate> adapter;
|
||||
@property(strong, nonatomic) id<SKNetworkAdapterDelegate> adapter;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
*/
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
#import <vector>
|
||||
#import "FlipperKitNetworkPlugin.h"
|
||||
#import <iostream>
|
||||
#import <memory>
|
||||
#import "FlipperKitNetworkPlugin.h"
|
||||
#import "SKNetworkReporter.h"
|
||||
#import "SonarKitNetworkPlugin+CPPInitialization.h"
|
||||
#import <vector>
|
||||
#import "SKBufferingPlugin+CPPInitialization.h"
|
||||
#import "SKDispatchQueue.h"
|
||||
#import "SKNetworkReporter.h"
|
||||
#import "SonarKitNetworkPlugin+CPPInitialization.h"
|
||||
|
||||
@interface FlipperKitNetworkPlugin ()
|
||||
|
||||
@@ -27,20 +27,26 @@
|
||||
}
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super initWithQueue:dispatch_queue_create("com.sonarkit.network.buffer", DISPATCH_QUEUE_SERIAL)]) {
|
||||
if (self = [super initWithQueue:dispatch_queue_create(
|
||||
"com.sonarkit.network.buffer",
|
||||
DISPATCH_QUEUE_SERIAL)]) {
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter {
|
||||
if (self = [super initWithQueue:dispatch_queue_create("com.sonarkit.network.buffer", DISPATCH_QUEUE_SERIAL)]) {
|
||||
if (self = [super initWithQueue:dispatch_queue_create(
|
||||
"com.sonarkit.network.buffer",
|
||||
DISPATCH_QUEUE_SERIAL)]) {
|
||||
adapter.delegate = self;
|
||||
_adapter = adapter;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter queue:(dispatch_queue_t)queue; {
|
||||
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter
|
||||
queue:(dispatch_queue_t)queue;
|
||||
{
|
||||
if (self = [super initWithQueue:queue]) {
|
||||
adapter.delegate = self;
|
||||
_adapter = adapter;
|
||||
@@ -50,68 +56,65 @@
|
||||
|
||||
#pragma mark - SKNetworkReporterDelegate
|
||||
|
||||
|
||||
- (void)didObserveRequest:(SKRequestInfo *)request
|
||||
{
|
||||
NSMutableArray<NSDictionary<NSString *, id> *> *headers = [NSMutableArray new];
|
||||
for (NSString *key in [request.request.allHTTPHeaderFields allKeys]) {
|
||||
NSDictionary<NSString *, id> *header = @{
|
||||
@"key": key,
|
||||
@"value": request.request.allHTTPHeaderFields[key]
|
||||
};
|
||||
[headers addObject: header];
|
||||
- (void)didObserveRequest:(SKRequestInfo*)request {
|
||||
NSMutableArray<NSDictionary<NSString*, id>*>* headers = [NSMutableArray new];
|
||||
for (NSString* key in [request.request.allHTTPHeaderFields allKeys]) {
|
||||
NSDictionary<NSString*, id>* header =
|
||||
@{@"key" : key, @"value" : request.request.allHTTPHeaderFields[key]};
|
||||
[headers addObject:header];
|
||||
}
|
||||
|
||||
NSString *body = request.body;
|
||||
NSString* body = request.body;
|
||||
|
||||
[self send:@"newRequest"
|
||||
sonarObject:@{
|
||||
@"id": @(request.identifier),
|
||||
@"timestamp": @(request.timestamp),
|
||||
@"method": request.request.HTTPMethod ?: [NSNull null],
|
||||
@"url": [request.request.URL absoluteString] ?: [NSNull null],
|
||||
@"headers": headers,
|
||||
@"data": body ? body : [NSNull null]
|
||||
}];
|
||||
sonarObject:@{
|
||||
@"id" : @(request.identifier),
|
||||
@"timestamp" : @(request.timestamp),
|
||||
@"method" : request.request.HTTPMethod ?: [NSNull null],
|
||||
@"url" : [request.request.URL absoluteString] ?: [NSNull null],
|
||||
@"headers" : headers,
|
||||
@"data" : body ? body : [NSNull null]
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)didObserveResponse:(SKResponseInfo *)response
|
||||
{
|
||||
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response.response;
|
||||
- (void)didObserveResponse:(SKResponseInfo*)response {
|
||||
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response.response;
|
||||
|
||||
NSMutableArray<NSDictionary<NSString *, id> *> *headers = [NSMutableArray new];
|
||||
for (NSString *key in [httpResponse.allHeaderFields allKeys]) {
|
||||
NSDictionary<NSString *, id> *header = @{
|
||||
@"key": key,
|
||||
@"value": httpResponse.allHeaderFields[key]
|
||||
};
|
||||
[headers addObject: header];
|
||||
NSMutableArray<NSDictionary<NSString*, id>*>* headers = [NSMutableArray new];
|
||||
for (NSString* key in [httpResponse.allHeaderFields allKeys]) {
|
||||
NSDictionary<NSString*, id>* header =
|
||||
@{@"key" : key, @"value" : httpResponse.allHeaderFields[key]};
|
||||
[headers addObject:header];
|
||||
}
|
||||
|
||||
NSString *body = response.body;
|
||||
NSString* body = response.body;
|
||||
|
||||
[self send:@"newResponse"
|
||||
sonarObject:@{
|
||||
@"id": @(response.identifier),
|
||||
@"timestamp": @(response.timestamp),
|
||||
@"status": @(httpResponse.statusCode),
|
||||
@"reason": [NSHTTPURLResponse localizedStringForStatusCode: httpResponse.statusCode] ?: [NSNull null],
|
||||
@"headers": headers,
|
||||
@"data": body ? body : [NSNull null]
|
||||
}];
|
||||
|
||||
sonarObject:@{
|
||||
@"id" : @(response.identifier),
|
||||
@"timestamp" : @(response.timestamp),
|
||||
@"status" : @(httpResponse.statusCode),
|
||||
@"reason" : [NSHTTPURLResponse
|
||||
localizedStringForStatusCode:httpResponse.statusCode]
|
||||
?: [NSNull null],
|
||||
@"headers" : headers,
|
||||
@"data" : body ? body : [NSNull null]
|
||||
}];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation FlipperKitNetworkPlugin (CPPInitialization)
|
||||
|
||||
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter dispatchQueue:(std::shared_ptr<facebook::flipper::DispatchQueue>)queue {
|
||||
if (self = [super initWithDispatchQueue:queue]) {
|
||||
adapter.delegate = self;
|
||||
_adapter = adapter;
|
||||
}
|
||||
return self;
|
||||
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter
|
||||
dispatchQueue:
|
||||
(std::shared_ptr<facebook::flipper::DispatchQueue>)
|
||||
queue {
|
||||
if (self = [super initWithDispatchQueue:queue]) {
|
||||
adapter.delegate = self;
|
||||
_adapter = adapter;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -8,21 +8,24 @@
|
||||
#if FB_SONARKIT_ENABLED
|
||||
#pragma once
|
||||
|
||||
#import "SKBufferingPlugin.h"
|
||||
#import "SKDispatchQueue.h"
|
||||
#import <iostream>
|
||||
#import <memory>
|
||||
#import "SKBufferingPlugin.h"
|
||||
#import "SKDispatchQueue.h"
|
||||
|
||||
struct CachedEvent {
|
||||
NSString *method;
|
||||
NSDictionary<NSString *, id> *sonarObject;
|
||||
NSString* method;
|
||||
NSDictionary<NSString*, id>* sonarObject;
|
||||
};
|
||||
|
||||
@interface SKBufferingPlugin (CPPInitialization)
|
||||
|
||||
@interface SKBufferingPlugin(CPPInitialization)
|
||||
|
||||
- (instancetype)initWithVectorEventSize:(NSUInteger)size connectionAccessQueue:(std::shared_ptr<facebook::flipper::DispatchQueue>)connectionAccessQueue;
|
||||
- (instancetype)initWithDispatchQueue:(std::shared_ptr<facebook::flipper::DispatchQueue>)queue;
|
||||
- (instancetype)initWithVectorEventSize:(NSUInteger)size
|
||||
connectionAccessQueue:
|
||||
(std::shared_ptr<facebook::flipper::DispatchQueue>)
|
||||
connectionAccessQueue;
|
||||
- (instancetype)initWithDispatchQueue:
|
||||
(std::shared_ptr<facebook::flipper::DispatchQueue>)queue;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
|
||||
- (instancetype)initWithQueue:(dispatch_queue_t)queue NS_DESIGNATED_INITIALIZER;
|
||||
|
||||
- (void)send:(NSString *)method sonarObject:(NSDictionary<NSString *, id> *)sonarObject;
|
||||
- (void)send:(NSString*)method
|
||||
sonarObject:(NSDictionary<NSString*, id>*)sonarObject;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -9,17 +9,18 @@
|
||||
|
||||
#import <vector>
|
||||
|
||||
#import "SKBufferingPlugin.h"
|
||||
#import <FlipperKit/FlipperConnection.h>
|
||||
#import "SKDispatchQueue.h"
|
||||
#import "SKBufferingPlugin+CPPInitialization.h"
|
||||
#import "SKBufferingPlugin.h"
|
||||
#import "SKDispatchQueue.h"
|
||||
|
||||
static const NSUInteger bufferSize = 500;
|
||||
|
||||
@interface SKBufferingPlugin()
|
||||
@interface SKBufferingPlugin ()
|
||||
|
||||
@property(assign, nonatomic) std::vector<CachedEvent> ringBuffer;
|
||||
@property(assign, nonatomic) std::shared_ptr<facebook::flipper::DispatchQueue> connectionAccessQueue;
|
||||
@property(assign, nonatomic) std::shared_ptr<facebook::flipper::DispatchQueue>
|
||||
connectionAccessQueue;
|
||||
@property(strong, nonatomic) id<FlipperConnection> connection;
|
||||
|
||||
@end
|
||||
@@ -35,12 +36,13 @@ static const NSUInteger bufferSize = 500;
|
||||
- (instancetype)initWithQueue:(dispatch_queue_t)queue {
|
||||
if (self = [super init]) {
|
||||
_ringBuffer.reserve(bufferSize);
|
||||
_connectionAccessQueue = std::make_shared<facebook::flipper::GCDQueue>(queue);
|
||||
_connectionAccessQueue =
|
||||
std::make_shared<facebook::flipper::GCDQueue>(queue);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)identifier {
|
||||
- (NSString*)identifier {
|
||||
// Note: This must match with the javascript pulgin identifier!!
|
||||
return @"Network";
|
||||
}
|
||||
@@ -62,9 +64,8 @@ static const NSUInteger bufferSize = 500;
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
- (void)send:(NSString *)method
|
||||
sonarObject:(NSDictionary<NSString *, id> *)sonarObject {
|
||||
- (void)send:(NSString*)method
|
||||
sonarObject:(NSDictionary<NSString*, id>*)sonarObject {
|
||||
_connectionAccessQueue->async(^{
|
||||
if (self->_connection) {
|
||||
[self->_connection send:method withParams:sonarObject];
|
||||
@@ -72,17 +73,15 @@ static const NSUInteger bufferSize = 500;
|
||||
if (self->_ringBuffer.size() == bufferSize) {
|
||||
return;
|
||||
}
|
||||
self->_ringBuffer.push_back({
|
||||
.method = method,
|
||||
.sonarObject = sonarObject
|
||||
});
|
||||
self->_ringBuffer.push_back(
|
||||
{.method = method, .sonarObject = sonarObject});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)sendBufferedEvents {
|
||||
NSAssert(_connection, @"connection object cannot be nil");
|
||||
for (const auto &event : _ringBuffer) {
|
||||
for (const auto& event : _ringBuffer) {
|
||||
[_connection send:event.method withParams:event.sonarObject];
|
||||
}
|
||||
_ringBuffer.clear();
|
||||
@@ -90,22 +89,23 @@ static const NSUInteger bufferSize = 500;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SKBufferingPlugin(CPPInitialization)
|
||||
@implementation SKBufferingPlugin (CPPInitialization)
|
||||
|
||||
- (instancetype)initWithVectorEventSize:(NSUInteger)size connectionAccessQueue:(std::shared_ptr<facebook::flipper::DispatchQueue>)connectionAccessQueue {
|
||||
if (self = [super init]) {
|
||||
_ringBuffer.reserve(size);
|
||||
_connectionAccessQueue = connectionAccessQueue;
|
||||
}
|
||||
return self;
|
||||
- (instancetype)initWithVectorEventSize:(NSUInteger)size
|
||||
connectionAccessQueue:
|
||||
(std::shared_ptr<facebook::flipper::DispatchQueue>)
|
||||
connectionAccessQueue {
|
||||
if (self = [super init]) {
|
||||
_ringBuffer.reserve(size);
|
||||
_connectionAccessQueue = connectionAccessQueue;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
- (instancetype)initWithDispatchQueue:(std::shared_ptr<facebook::flipper::DispatchQueue>)queue {
|
||||
return [self initWithVectorEventSize:bufferSize
|
||||
connectionAccessQueue:queue];
|
||||
|
||||
- (instancetype)initWithDispatchQueue:
|
||||
(std::shared_ptr<facebook::flipper::DispatchQueue>)queue {
|
||||
return [self initWithVectorEventSize:bufferSize connectionAccessQueue:queue];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,31 +12,28 @@
|
||||
#import <dispatch/dispatch.h>
|
||||
|
||||
namespace facebook {
|
||||
namespace flipper {
|
||||
class DispatchQueue
|
||||
{
|
||||
public:
|
||||
virtual void async(dispatch_block_t block) = 0;
|
||||
virtual ~DispatchQueue() { }
|
||||
};
|
||||
namespace flipper {
|
||||
class DispatchQueue {
|
||||
public:
|
||||
virtual void async(dispatch_block_t block) = 0;
|
||||
virtual ~DispatchQueue() {}
|
||||
};
|
||||
|
||||
class GCDQueue: public DispatchQueue
|
||||
{
|
||||
public:
|
||||
GCDQueue(dispatch_queue_t underlyingQueue)
|
||||
:_underlyingQueue(underlyingQueue) { }
|
||||
class GCDQueue : public DispatchQueue {
|
||||
public:
|
||||
GCDQueue(dispatch_queue_t underlyingQueue)
|
||||
: _underlyingQueue(underlyingQueue) {}
|
||||
|
||||
void async(dispatch_block_t block) override
|
||||
{
|
||||
dispatch_async(_underlyingQueue, block);
|
||||
}
|
||||
|
||||
virtual ~GCDQueue() { }
|
||||
|
||||
private:
|
||||
dispatch_queue_t _underlyingQueue;
|
||||
};
|
||||
void async(dispatch_block_t block) override {
|
||||
dispatch_async(_underlyingQueue, block);
|
||||
}
|
||||
}
|
||||
|
||||
virtual ~GCDQueue() {}
|
||||
|
||||
private:
|
||||
dispatch_queue_t _underlyingQueue;
|
||||
};
|
||||
} // namespace flipper
|
||||
} // namespace facebook
|
||||
|
||||
#endif
|
||||
|
||||
@@ -11,13 +11,13 @@
|
||||
|
||||
@protocol SKNetworkReporterDelegate
|
||||
|
||||
- (void)didObserveRequest:(SKRequestInfo *)request;
|
||||
- (void)didObserveResponse:(SKResponseInfo *)response;
|
||||
- (void)didObserveRequest:(SKRequestInfo*)request;
|
||||
- (void)didObserveResponse:(SKResponseInfo*)response;
|
||||
|
||||
@end
|
||||
|
||||
@protocol SKNetworkAdapterDelegate
|
||||
|
||||
@property (weak, nonatomic) id<SKNetworkReporterDelegate> delegate;
|
||||
@property(weak, nonatomic) id<SKNetworkReporterDelegate> delegate;
|
||||
|
||||
@end
|
||||
|
||||
@@ -7,13 +7,16 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface SKRequestInfo: NSObject
|
||||
@interface SKRequestInfo : NSObject
|
||||
@property(assign, readwrite) int64_t identifier;
|
||||
@property(assign, readwrite) uint64_t timestamp;
|
||||
@property(strong, nonatomic) NSURLRequest* request;
|
||||
@property(strong, nonatomic) NSString* body;
|
||||
|
||||
- (instancetype)initWithIdentifier:(int64_t)identifier timestamp:(uint64_t)timestamp request:(NSURLRequest*)request data:(NSData *)data;
|
||||
- (void)setBodyFromData:(NSData * _Nullable)data;
|
||||
- (instancetype)initWithIdentifier:(int64_t)identifier
|
||||
timestamp:(uint64_t)timestamp
|
||||
request:(NSURLRequest*)request
|
||||
data:(NSData*)data;
|
||||
- (void)setBodyFromData:(NSData* _Nullable)data;
|
||||
|
||||
@end
|
||||
|
||||
@@ -13,21 +13,23 @@
|
||||
@synthesize request = _request;
|
||||
@synthesize body = _body;
|
||||
|
||||
- (instancetype)initWithIdentifier:(int64_t)identifier timestamp:(uint64_t)timestamp request:(NSURLRequest *)request data:(NSData *)data{
|
||||
|
||||
if (self = [super init]){
|
||||
- (instancetype)initWithIdentifier:(int64_t)identifier
|
||||
timestamp:(uint64_t)timestamp
|
||||
request:(NSURLRequest*)request
|
||||
data:(NSData*)data {
|
||||
if (self = [super init]) {
|
||||
_identifier = identifier;
|
||||
_timestamp = timestamp;
|
||||
_request = request;
|
||||
_body = data ? [data base64EncodedStringWithOptions: 0]
|
||||
: [request.HTTPBody base64EncodedStringWithOptions: 0];
|
||||
_body = data ? [data base64EncodedStringWithOptions:0]
|
||||
: [request.HTTPBody base64EncodedStringWithOptions:0];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setBodyFromData:(NSData * _Nullable)data {
|
||||
self.body = data ? [data base64EncodedStringWithOptions: 0]
|
||||
: [self.request.HTTPBody base64EncodedStringWithOptions: 0];
|
||||
- (void)setBodyFromData:(NSData* _Nullable)data {
|
||||
self.body = data ? [data base64EncodedStringWithOptions:0]
|
||||
: [self.request.HTTPBody base64EncodedStringWithOptions:0];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -14,7 +14,10 @@
|
||||
@property(strong, nonatomic) NSURLResponse* response;
|
||||
@property(strong, nonatomic) NSString* body;
|
||||
|
||||
- (instancetype)initWithIndentifier:(int64_t)identifier timestamp:(uint64_t)timestamp response:(NSURLResponse *)response data:(NSData *)data;
|
||||
- (void)setBodyFromData:(NSData * _Nullable)data;
|
||||
- (instancetype)initWithIndentifier:(int64_t)identifier
|
||||
timestamp:(uint64_t)timestamp
|
||||
response:(NSURLResponse*)response
|
||||
data:(NSData*)data;
|
||||
- (void)setBodyFromData:(NSData* _Nullable)data;
|
||||
|
||||
@end
|
||||
|
||||
@@ -13,30 +13,37 @@
|
||||
@synthesize response = _response;
|
||||
@synthesize body = _body;
|
||||
|
||||
- (instancetype)initWithIndentifier:(int64_t)identifier timestamp:(uint64_t)timestamp response:(NSURLResponse *)response data:(NSData *)data {
|
||||
if(self = [super init]) {
|
||||
- (instancetype)initWithIndentifier:(int64_t)identifier
|
||||
timestamp:(uint64_t)timestamp
|
||||
response:(NSURLResponse*)response
|
||||
data:(NSData*)data {
|
||||
if (self = [super init]) {
|
||||
_identifier = identifier;
|
||||
_timestamp = timestamp;
|
||||
_response = response;
|
||||
_body = [SKResponseInfo shouldStripReponseBodyWithResponse:response] ? nil : [data base64EncodedStringWithOptions: 0];
|
||||
_body = [SKResponseInfo shouldStripReponseBodyWithResponse:response]
|
||||
? nil
|
||||
: [data base64EncodedStringWithOptions:0];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (BOOL) shouldStripReponseBodyWithResponse:(NSURLResponse *)response {
|
||||
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)response;
|
||||
NSString *contentType = httpResponse.allHeaderFields[@"content-type"];
|
||||
+ (BOOL)shouldStripReponseBodyWithResponse:(NSURLResponse*)response {
|
||||
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
|
||||
NSString* contentType = httpResponse.allHeaderFields[@"content-type"];
|
||||
if (!contentType) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return [contentType containsString:@"image/"] ||
|
||||
[contentType containsString:@"video/"] ||
|
||||
[contentType containsString:@"application/zip"];
|
||||
[contentType containsString:@"video/"] ||
|
||||
[contentType containsString:@"application/zip"];
|
||||
}
|
||||
|
||||
- (void)setBodyFromData:(NSData *_Nullable)data {
|
||||
self.body = [SKResponseInfo shouldStripReponseBodyWithResponse:self.response] ? nil : [data base64EncodedStringWithOptions: 0];
|
||||
- (void)setBodyFromData:(NSData* _Nullable)data {
|
||||
self.body = [SKResponseInfo shouldStripReponseBodyWithResponse:self.response]
|
||||
? nil
|
||||
: [data base64EncodedStringWithOptions:0];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -8,11 +8,14 @@
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#pragma once
|
||||
#import <memory>
|
||||
#import "FlipperKitNetworkPlugin.h"
|
||||
#import "SKDispatchQueue.h"
|
||||
#import <memory>
|
||||
|
||||
@interface FlipperKitNetworkPlugin(CPPInitialization)
|
||||
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter dispatchQueue:(std::shared_ptr<facebook::flipper::DispatchQueue>)queue;
|
||||
@interface FlipperKitNetworkPlugin (CPPInitialization)
|
||||
- (instancetype)initWithNetworkAdapter:(id<SKNetworkAdapterDelegate>)adapter
|
||||
dispatchQueue:
|
||||
(std::shared_ptr<facebook::flipper::DispatchQueue>)
|
||||
queue;
|
||||
@end
|
||||
#endif
|
||||
|
||||
@@ -21,10 +21,13 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
FOUNDATION_EXTERN NSString *const kFLEXNetworkObserverEnabledStateChangedNotification;
|
||||
FOUNDATION_EXTERN NSString* const
|
||||
kFLEXNetworkObserverEnabledStateChangedNotification;
|
||||
|
||||
/// This class swizzles NSURLConnection and NSURLSession delegate methods to observe events in the URL loading system.
|
||||
/// High level network events are sent to the default FLEXNetworkRecorder instance which maintains the request history and caches response bodies.
|
||||
/// This class swizzles NSURLConnection and NSURLSession delegate methods to
|
||||
/// observe events in the URL loading system. High level network events are sent
|
||||
/// to the default FLEXNetworkRecorder instance which maintains the request
|
||||
/// history and caches response bodies.
|
||||
@interface FLEXNetworkObserver : NSObject
|
||||
|
||||
+ (void)start;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,60 +10,70 @@
|
||||
#import <FlipperKitNetworkPlugin/SKNetworkReporter.h>
|
||||
|
||||
// Notifications posted when the record is updated
|
||||
extern NSString *const kFLEXNetworkRecorderNewTransactionNotification;
|
||||
extern NSString *const kFLEXNetworkRecorderTransactionUpdatedNotification;
|
||||
extern NSString *const kFLEXNetworkRecorderUserInfoTransactionKey;
|
||||
extern NSString *const kFLEXNetworkRecorderTransactionsClearedNotification;
|
||||
extern NSString* const kFLEXNetworkRecorderNewTransactionNotification;
|
||||
extern NSString* const kFLEXNetworkRecorderTransactionUpdatedNotification;
|
||||
extern NSString* const kFLEXNetworkRecorderUserInfoTransactionKey;
|
||||
extern NSString* const kFLEXNetworkRecorderTransactionsClearedNotification;
|
||||
|
||||
@class FLEXNetworkTransaction;
|
||||
|
||||
@interface FLEXNetworkRecorder : NSObject
|
||||
|
||||
/// In general, it only makes sense to have one recorder for the entire application.
|
||||
/// In general, it only makes sense to have one recorder for the entire
|
||||
/// application.
|
||||
+ (instancetype)defaultRecorder;
|
||||
|
||||
@property (nonatomic, weak) id<SKNetworkReporterDelegate> delegate;
|
||||
@property(nonatomic, weak) id<SKNetworkReporterDelegate> delegate;
|
||||
|
||||
/// Defaults to 25 MB if never set. Values set here are presisted across launches of the app.
|
||||
@property (nonatomic, assign) NSUInteger responseCacheByteLimit;
|
||||
/// Defaults to 25 MB if never set. Values set here are presisted across
|
||||
/// launches of the app.
|
||||
@property(nonatomic, assign) NSUInteger responseCacheByteLimit;
|
||||
|
||||
/// If NO, the recorder not cache will not cache response for content types with an "image", "video", or "audio" prefix.
|
||||
@property (nonatomic, assign) BOOL shouldCacheMediaResponses;
|
||||
|
||||
@property (nonatomic, copy) NSArray<NSString *> *hostBlacklist;
|
||||
/// If NO, the recorder not cache will not cache response for content types with
|
||||
/// an "image", "video", or "audio" prefix.
|
||||
@property(nonatomic, assign) BOOL shouldCacheMediaResponses;
|
||||
|
||||
@property(nonatomic, copy) NSArray<NSString*>* hostBlacklist;
|
||||
|
||||
// Accessing recorded network activity
|
||||
|
||||
/// Array of FLEXNetworkTransaction objects ordered by start time with the newest first.
|
||||
- (NSArray<FLEXNetworkTransaction *> *)networkTransactions;
|
||||
/// Array of FLEXNetworkTransaction objects ordered by start time with the
|
||||
/// newest first.
|
||||
- (NSArray<FLEXNetworkTransaction*>*)networkTransactions;
|
||||
|
||||
/// The full response data IFF it hasn't been purged due to memory pressure.
|
||||
- (NSData *)cachedResponseBodyForTransaction:(FLEXNetworkTransaction *)transaction;
|
||||
- (NSData*)cachedResponseBodyForTransaction:
|
||||
(FLEXNetworkTransaction*)transaction;
|
||||
|
||||
/// Dumps all network transactions and cached response bodies.
|
||||
- (void)clearRecordedActivity;
|
||||
|
||||
|
||||
// Recording network activity
|
||||
|
||||
/// Call when app is about to send HTTP request.
|
||||
- (void)recordRequestWillBeSentWithRequestID:(NSString *)requestID request:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse;
|
||||
- (void)recordRequestWillBeSentWithRequestID:(NSString*)requestID
|
||||
request:(NSURLRequest*)request
|
||||
redirectResponse:(NSURLResponse*)redirectResponse;
|
||||
|
||||
/// Call when HTTP response is available.
|
||||
- (void)recordResponseReceivedWithRequestID:(NSString *)requestID response:(NSURLResponse *)response;
|
||||
- (void)recordResponseReceivedWithRequestID:(NSString*)requestID
|
||||
response:(NSURLResponse*)response;
|
||||
|
||||
/// Call when data chunk is received over the network.
|
||||
- (void)recordDataReceivedWithRequestID:(NSString *)requestID dataLength:(int64_t)dataLength;
|
||||
- (void)recordDataReceivedWithRequestID:(NSString*)requestID
|
||||
dataLength:(int64_t)dataLength;
|
||||
|
||||
/// Call when HTTP request has finished loading.
|
||||
- (void)recordLoadingFinishedWithRequestID:(NSString *)requestID responseBody:(NSData *)responseBody;
|
||||
- (void)recordLoadingFinishedWithRequestID:(NSString*)requestID
|
||||
responseBody:(NSData*)responseBody;
|
||||
|
||||
/// Call when HTTP request has failed to load.
|
||||
- (void)recordLoadingFailedWithRequestID:(NSString *)requestID error:(NSError *)error;
|
||||
- (void)recordLoadingFailedWithRequestID:(NSString*)requestID
|
||||
error:(NSError*)error;
|
||||
|
||||
/// Call to set the request mechanism anytime after recordRequestWillBeSent... has been called.
|
||||
/// This string can be set to anything useful about the API used to make the request.
|
||||
- (void)recordMechanism:(NSString *)mechanism forRequestID:(NSString *)requestID;
|
||||
/// Call to set the request mechanism anytime after recordRequestWillBeSent...
|
||||
/// has been called. This string can be set to anything useful about the API
|
||||
/// used to make the request.
|
||||
- (void)recordMechanism:(NSString*)mechanism forRequestID:(NSString*)requestID;
|
||||
|
||||
@end
|
||||
|
||||
@@ -10,54 +10,65 @@
|
||||
#import "FLEXNetworkTransaction.h"
|
||||
#import "FLEXUtility.h"
|
||||
|
||||
NSString *const kFLEXNetworkRecorderNewTransactionNotification = @"kFLEXNetworkRecorderNewTransactionNotification";
|
||||
NSString *const kFLEXNetworkRecorderTransactionUpdatedNotification = @"kFLEXNetworkRecorderTransactionUpdatedNotification";
|
||||
NSString *const kFLEXNetworkRecorderUserInfoTransactionKey = @"transaction";
|
||||
NSString *const kFLEXNetworkRecorderTransactionsClearedNotification = @"kFLEXNetworkRecorderTransactionsClearedNotification";
|
||||
NSString* const kFLEXNetworkRecorderNewTransactionNotification =
|
||||
@"kFLEXNetworkRecorderNewTransactionNotification";
|
||||
NSString* const kFLEXNetworkRecorderTransactionUpdatedNotification =
|
||||
@"kFLEXNetworkRecorderTransactionUpdatedNotification";
|
||||
NSString* const kFLEXNetworkRecorderUserInfoTransactionKey = @"transaction";
|
||||
NSString* const kFLEXNetworkRecorderTransactionsClearedNotification =
|
||||
@"kFLEXNetworkRecorderTransactionsClearedNotification";
|
||||
|
||||
NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.responseCacheLimit";
|
||||
NSString* const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey =
|
||||
@"com.flex.responseCacheLimit";
|
||||
|
||||
@interface FLEXNetworkRecorder ()
|
||||
|
||||
@property (nonatomic, strong) NSCache *responseCache;
|
||||
@property (nonatomic, strong) NSMutableArray<FLEXNetworkTransaction *> *orderedTransactions;
|
||||
@property (nonatomic, strong) NSMutableDictionary<NSString *, FLEXNetworkTransaction *> *networkTransactionsForRequestIdentifiers;
|
||||
@property (nonatomic, strong) dispatch_queue_t queue;
|
||||
@property (nonatomic, strong) NSMutableDictionary<NSString *, NSNumber *> *identifierDict;
|
||||
@property(nonatomic, strong) NSCache* responseCache;
|
||||
@property(nonatomic, strong)
|
||||
NSMutableArray<FLEXNetworkTransaction*>* orderedTransactions;
|
||||
@property(nonatomic, strong)
|
||||
NSMutableDictionary<NSString*, FLEXNetworkTransaction*>*
|
||||
networkTransactionsForRequestIdentifiers;
|
||||
@property(nonatomic, strong) dispatch_queue_t queue;
|
||||
@property(nonatomic, strong)
|
||||
NSMutableDictionary<NSString*, NSNumber*>* identifierDict;
|
||||
@end
|
||||
|
||||
@implementation FLEXNetworkRecorder
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_responseCache = [NSCache new];
|
||||
NSUInteger responseCacheLimit = [[[NSUserDefaults standardUserDefaults] objectForKey:kFLEXNetworkRecorderResponseCacheLimitDefaultsKey] unsignedIntegerValue];
|
||||
if (responseCacheLimit) {
|
||||
[_responseCache setTotalCostLimit:responseCacheLimit];
|
||||
} else {
|
||||
// Default to 25 MB max. The cache will purge earlier if there is memory pressure.
|
||||
[_responseCache setTotalCostLimit:25 * 1024 * 1024];
|
||||
}
|
||||
_orderedTransactions = [NSMutableArray array];
|
||||
_networkTransactionsForRequestIdentifiers = [NSMutableDictionary dictionary];
|
||||
|
||||
// Serial queue used because we use mutable objects that are not thread safe
|
||||
_queue = dispatch_queue_create("com.flex.FLEXNetworkRecorder", DISPATCH_QUEUE_SERIAL);
|
||||
_identifierDict = [NSMutableDictionary dictionary];
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_responseCache = [NSCache new];
|
||||
NSUInteger responseCacheLimit = [[[NSUserDefaults standardUserDefaults]
|
||||
objectForKey:kFLEXNetworkRecorderResponseCacheLimitDefaultsKey]
|
||||
unsignedIntegerValue];
|
||||
if (responseCacheLimit) {
|
||||
[_responseCache setTotalCostLimit:responseCacheLimit];
|
||||
} else {
|
||||
// Default to 25 MB max. The cache will purge earlier if there is memory
|
||||
// pressure.
|
||||
[_responseCache setTotalCostLimit:25 * 1024 * 1024];
|
||||
}
|
||||
return self;
|
||||
_orderedTransactions = [NSMutableArray array];
|
||||
_networkTransactionsForRequestIdentifiers =
|
||||
[NSMutableDictionary dictionary];
|
||||
|
||||
// Serial queue used because we use mutable objects that are not thread safe
|
||||
_queue = dispatch_queue_create(
|
||||
"com.flex.FLEXNetworkRecorder", DISPATCH_QUEUE_SERIAL);
|
||||
_identifierDict = [NSMutableDictionary dictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)defaultRecorder
|
||||
{
|
||||
static FLEXNetworkRecorder *defaultRecorder = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
defaultRecorder = [[[self class] alloc] init];
|
||||
});
|
||||
return defaultRecorder;
|
||||
+ (instancetype)defaultRecorder {
|
||||
static FLEXNetworkRecorder* defaultRecorder = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
defaultRecorder = [[[self class] alloc] init];
|
||||
});
|
||||
return defaultRecorder;
|
||||
}
|
||||
|
||||
#pragma mark - Public Data Access
|
||||
@@ -66,153 +77,175 @@ NSString *const kFLEXNetworkRecorderResponseCacheLimitDefaultsKey = @"com.flex.r
|
||||
_delegate = delegate;
|
||||
}
|
||||
|
||||
- (NSUInteger)responseCacheByteLimit
|
||||
{
|
||||
return [self.responseCache totalCostLimit];
|
||||
- (NSUInteger)responseCacheByteLimit {
|
||||
return [self.responseCache totalCostLimit];
|
||||
}
|
||||
|
||||
- (void)setResponseCacheByteLimit:(NSUInteger)responseCacheByteLimit
|
||||
{
|
||||
[self.responseCache setTotalCostLimit:responseCacheByteLimit];
|
||||
[[NSUserDefaults standardUserDefaults] setObject:@(responseCacheByteLimit) forKey:kFLEXNetworkRecorderResponseCacheLimitDefaultsKey];
|
||||
- (void)setResponseCacheByteLimit:(NSUInteger)responseCacheByteLimit {
|
||||
[self.responseCache setTotalCostLimit:responseCacheByteLimit];
|
||||
[[NSUserDefaults standardUserDefaults]
|
||||
setObject:@(responseCacheByteLimit)
|
||||
forKey:kFLEXNetworkRecorderResponseCacheLimitDefaultsKey];
|
||||
}
|
||||
|
||||
- (NSArray<FLEXNetworkTransaction *> *)networkTransactions
|
||||
{
|
||||
__block NSArray<FLEXNetworkTransaction *> *transactions = nil;
|
||||
dispatch_sync(self.queue, ^{
|
||||
transactions = [self.orderedTransactions copy];
|
||||
});
|
||||
return transactions;
|
||||
- (NSArray<FLEXNetworkTransaction*>*)networkTransactions {
|
||||
__block NSArray<FLEXNetworkTransaction*>* transactions = nil;
|
||||
dispatch_sync(self.queue, ^{
|
||||
transactions = [self.orderedTransactions copy];
|
||||
});
|
||||
return transactions;
|
||||
}
|
||||
|
||||
- (NSData *)cachedResponseBodyForTransaction:(FLEXNetworkTransaction *)transaction
|
||||
{
|
||||
return [self.responseCache objectForKey:transaction.requestID];
|
||||
- (NSData*)cachedResponseBodyForTransaction:
|
||||
(FLEXNetworkTransaction*)transaction {
|
||||
return [self.responseCache objectForKey:transaction.requestID];
|
||||
}
|
||||
|
||||
- (void)clearRecordedActivity
|
||||
{
|
||||
dispatch_async(self.queue, ^{
|
||||
[self.responseCache removeAllObjects];
|
||||
[self.orderedTransactions removeAllObjects];
|
||||
[self.networkTransactionsForRequestIdentifiers removeAllObjects];
|
||||
});
|
||||
- (void)clearRecordedActivity {
|
||||
dispatch_async(self.queue, ^{
|
||||
[self.responseCache removeAllObjects];
|
||||
[self.orderedTransactions removeAllObjects];
|
||||
[self.networkTransactionsForRequestIdentifiers removeAllObjects];
|
||||
});
|
||||
}
|
||||
|
||||
#pragma mark - Network Events
|
||||
|
||||
- (void)recordRequestWillBeSentWithRequestID:(NSString *)requestID request:(NSURLRequest *)request redirectResponse:(NSURLResponse *)redirectResponse
|
||||
{
|
||||
- (void)recordRequestWillBeSentWithRequestID:(NSString*)requestID
|
||||
request:(NSURLRequest*)request
|
||||
redirectResponse:(NSURLResponse*)redirectResponse {
|
||||
if (![self.identifierDict objectForKey:requestID]) {
|
||||
self.identifierDict[requestID] = [NSNumber random];
|
||||
}
|
||||
NSDate *startDate = [NSDate date];
|
||||
NSDate* startDate = [NSDate date];
|
||||
|
||||
if (redirectResponse) {
|
||||
[self recordResponseReceivedWithRequestID:requestID response:redirectResponse];
|
||||
[self recordLoadingFinishedWithRequestID:requestID responseBody:nil];
|
||||
}
|
||||
if (redirectResponse) {
|
||||
[self recordResponseReceivedWithRequestID:requestID
|
||||
response:redirectResponse];
|
||||
[self recordLoadingFinishedWithRequestID:requestID responseBody:nil];
|
||||
}
|
||||
|
||||
dispatch_async(self.queue, ^{
|
||||
SKRequestInfo *info = [[SKRequestInfo alloc] initWithIdentifier:self.identifierDict[requestID].longLongValue timestamp:[NSDate timestamp] request:request data:request.HTTPBody];
|
||||
[self.delegate didObserveRequest:info];
|
||||
dispatch_async(self.queue, ^{
|
||||
SKRequestInfo* info = [[SKRequestInfo alloc]
|
||||
initWithIdentifier:self.identifierDict[requestID].longLongValue
|
||||
timestamp:[NSDate timestamp]
|
||||
request:request
|
||||
data:request.HTTPBody];
|
||||
[self.delegate didObserveRequest:info];
|
||||
|
||||
FLEXNetworkTransaction *transaction = [FLEXNetworkTransaction new];
|
||||
transaction.requestID = requestID;
|
||||
transaction.request = request;
|
||||
transaction.startTime = startDate;
|
||||
FLEXNetworkTransaction* transaction = [FLEXNetworkTransaction new];
|
||||
transaction.requestID = requestID;
|
||||
transaction.request = request;
|
||||
transaction.startTime = startDate;
|
||||
|
||||
[self.orderedTransactions insertObject:transaction atIndex:0];
|
||||
[self.networkTransactionsForRequestIdentifiers setObject:transaction forKey:requestID];
|
||||
transaction.transactionState = FLEXNetworkTransactionStateAwaitingResponse;
|
||||
});
|
||||
[self.orderedTransactions insertObject:transaction atIndex:0];
|
||||
[self.networkTransactionsForRequestIdentifiers setObject:transaction
|
||||
forKey:requestID];
|
||||
transaction.transactionState = FLEXNetworkTransactionStateAwaitingResponse;
|
||||
});
|
||||
}
|
||||
|
||||
/// Call when HTTP response is available.
|
||||
- (void)recordResponseReceivedWithRequestID:(NSString *)requestID response:(NSURLResponse *)response
|
||||
{
|
||||
NSDate *responseDate = [NSDate date];
|
||||
- (void)recordResponseReceivedWithRequestID:(NSString*)requestID
|
||||
response:(NSURLResponse*)response {
|
||||
NSDate* responseDate = [NSDate date];
|
||||
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
transaction.response = response;
|
||||
transaction.transactionState = FLEXNetworkTransactionStateReceivingData;
|
||||
transaction.latency = -[transaction.startTime timeIntervalSinceDate:responseDate];
|
||||
});
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXNetworkTransaction* transaction =
|
||||
self.networkTransactionsForRequestIdentifiers[requestID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
transaction.response = response;
|
||||
transaction.transactionState = FLEXNetworkTransactionStateReceivingData;
|
||||
transaction.latency =
|
||||
-[transaction.startTime timeIntervalSinceDate:responseDate];
|
||||
});
|
||||
}
|
||||
|
||||
/// Call when data chunk is received over the network.
|
||||
- (void)recordDataReceivedWithRequestID:(NSString *)requestID dataLength:(int64_t)dataLength
|
||||
{
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
transaction.receivedDataLength += dataLength;
|
||||
});
|
||||
- (void)recordDataReceivedWithRequestID:(NSString*)requestID
|
||||
dataLength:(int64_t)dataLength {
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXNetworkTransaction* transaction =
|
||||
self.networkTransactionsForRequestIdentifiers[requestID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
transaction.receivedDataLength += dataLength;
|
||||
});
|
||||
}
|
||||
|
||||
/// Call when HTTP request has finished loading.
|
||||
- (void)recordLoadingFinishedWithRequestID:(NSString *)requestID responseBody:(NSData *)responseBody
|
||||
{
|
||||
NSDate *finishedDate = [NSDate date];
|
||||
dispatch_async(self.queue, ^{
|
||||
- (void)recordLoadingFinishedWithRequestID:(NSString*)requestID
|
||||
responseBody:(NSData*)responseBody {
|
||||
NSDate* finishedDate = [NSDate date];
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXNetworkTransaction* transaction =
|
||||
self.networkTransactionsForRequestIdentifiers[requestID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
transaction.transactionState = FLEXNetworkTransactionStateFinished;
|
||||
transaction.duration =
|
||||
-[transaction.startTime timeIntervalSinceDate:finishedDate];
|
||||
SKResponseInfo* responseInfo = [[SKResponseInfo alloc]
|
||||
initWithIndentifier:self.identifierDict[requestID].longLongValue
|
||||
timestamp:[NSDate timestamp]
|
||||
response:transaction.response
|
||||
data:responseBody];
|
||||
self.identifierDict[requestID] = nil; // Clear the entry
|
||||
[self.delegate didObserveResponse:responseInfo];
|
||||
|
||||
FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
transaction.transactionState = FLEXNetworkTransactionStateFinished;
|
||||
transaction.duration = -[transaction.startTime timeIntervalSinceDate:finishedDate];
|
||||
SKResponseInfo *responseInfo = [[SKResponseInfo alloc] initWithIndentifier:self.identifierDict[requestID].longLongValue timestamp:[NSDate timestamp] response:transaction.response data:responseBody];
|
||||
self.identifierDict[requestID] = nil; //Clear the entry
|
||||
[self.delegate didObserveResponse:responseInfo];
|
||||
BOOL shouldCache = [responseBody length] > 0;
|
||||
if (!self.shouldCacheMediaResponses) {
|
||||
NSArray<NSString*>* ignoredMIMETypePrefixes =
|
||||
@[ @"audio", @"image", @"video" ];
|
||||
for (NSString* ignoredPrefix in ignoredMIMETypePrefixes) {
|
||||
shouldCache = shouldCache &&
|
||||
![transaction.response.MIMEType hasPrefix:ignoredPrefix];
|
||||
}
|
||||
}
|
||||
|
||||
BOOL shouldCache = [responseBody length] > 0;
|
||||
if (!self.shouldCacheMediaResponses) {
|
||||
NSArray<NSString *> *ignoredMIMETypePrefixes = @[ @"audio", @"image", @"video" ];
|
||||
for (NSString *ignoredPrefix in ignoredMIMETypePrefixes) {
|
||||
shouldCache = shouldCache && ![transaction.response.MIMEType hasPrefix:ignoredPrefix];
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldCache) {
|
||||
[self.responseCache setObject:responseBody forKey:requestID cost:[responseBody length]];
|
||||
}
|
||||
});
|
||||
if (shouldCache) {
|
||||
[self.responseCache setObject:responseBody
|
||||
forKey:requestID
|
||||
cost:[responseBody length]];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)recordLoadingFailedWithRequestID:(NSString *)requestID error:(NSError *)error
|
||||
{
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
- (void)recordLoadingFailedWithRequestID:(NSString*)requestID
|
||||
error:(NSError*)error {
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXNetworkTransaction* transaction =
|
||||
self.networkTransactionsForRequestIdentifiers[requestID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
|
||||
SKResponseInfo *responseInfo = [[SKResponseInfo alloc] initWithIndentifier:self.identifierDict[requestID].longLongValue timestamp:[NSDate timestamp] response:transaction.response data: nil];
|
||||
self.identifierDict[requestID] = nil; //Clear the entry
|
||||
[self.delegate didObserveResponse:responseInfo];
|
||||
transaction.transactionState = FLEXNetworkTransactionStateFailed;
|
||||
transaction.duration = -[transaction.startTime timeIntervalSinceNow];
|
||||
transaction.error = error;
|
||||
});
|
||||
SKResponseInfo* responseInfo = [[SKResponseInfo alloc]
|
||||
initWithIndentifier:self.identifierDict[requestID].longLongValue
|
||||
timestamp:[NSDate timestamp]
|
||||
response:transaction.response
|
||||
data:nil];
|
||||
self.identifierDict[requestID] = nil; // Clear the entry
|
||||
[self.delegate didObserveResponse:responseInfo];
|
||||
transaction.transactionState = FLEXNetworkTransactionStateFailed;
|
||||
transaction.duration = -[transaction.startTime timeIntervalSinceNow];
|
||||
transaction.error = error;
|
||||
});
|
||||
}
|
||||
|
||||
- (void)recordMechanism:(NSString *)mechanism forRequestID:(NSString *)requestID
|
||||
{
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXNetworkTransaction *transaction = self.networkTransactionsForRequestIdentifiers[requestID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
transaction.requestMechanism = mechanism;
|
||||
});
|
||||
- (void)recordMechanism:(NSString*)mechanism forRequestID:(NSString*)requestID {
|
||||
dispatch_async(self.queue, ^{
|
||||
FLEXNetworkTransaction* transaction =
|
||||
self.networkTransactionsForRequestIdentifiers[requestID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
transaction.requestMechanism = mechanism;
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -10,35 +10,37 @@
|
||||
#import "UIKit/UIKit.h"
|
||||
|
||||
typedef NS_ENUM(NSInteger, FLEXNetworkTransactionState) {
|
||||
FLEXNetworkTransactionStateUnstarted,
|
||||
FLEXNetworkTransactionStateAwaitingResponse,
|
||||
FLEXNetworkTransactionStateReceivingData,
|
||||
FLEXNetworkTransactionStateFinished,
|
||||
FLEXNetworkTransactionStateFailed
|
||||
FLEXNetworkTransactionStateUnstarted,
|
||||
FLEXNetworkTransactionStateAwaitingResponse,
|
||||
FLEXNetworkTransactionStateReceivingData,
|
||||
FLEXNetworkTransactionStateFinished,
|
||||
FLEXNetworkTransactionStateFailed
|
||||
};
|
||||
|
||||
@interface FLEXNetworkTransaction : NSObject
|
||||
|
||||
@property (nonatomic, copy) NSString *requestID;
|
||||
@property(nonatomic, copy) NSString* requestID;
|
||||
|
||||
@property (nonatomic, strong) NSURLRequest *request;
|
||||
@property (nonatomic, strong) NSURLResponse *response;
|
||||
@property (nonatomic, copy) NSString *requestMechanism;
|
||||
@property (nonatomic, assign) FLEXNetworkTransactionState transactionState;
|
||||
@property (nonatomic, strong) NSError *error;
|
||||
@property(nonatomic, strong) NSURLRequest* request;
|
||||
@property(nonatomic, strong) NSURLResponse* response;
|
||||
@property(nonatomic, copy) NSString* requestMechanism;
|
||||
@property(nonatomic, assign) FLEXNetworkTransactionState transactionState;
|
||||
@property(nonatomic, strong) NSError* error;
|
||||
|
||||
@property (nonatomic, strong) NSDate *startTime;
|
||||
@property (nonatomic, assign) NSTimeInterval latency;
|
||||
@property (nonatomic, assign) NSTimeInterval duration;
|
||||
@property(nonatomic, strong) NSDate* startTime;
|
||||
@property(nonatomic, assign) NSTimeInterval latency;
|
||||
@property(nonatomic, assign) NSTimeInterval duration;
|
||||
|
||||
@property (nonatomic, assign) int64_t receivedDataLength;
|
||||
@property(nonatomic, assign) int64_t receivedDataLength;
|
||||
|
||||
/// Only applicable for image downloads. A small thumbnail to preview the full response.
|
||||
@property (nonatomic, strong) UIImage *responseThumbnail;
|
||||
/// Only applicable for image downloads. A small thumbnail to preview the full
|
||||
/// response.
|
||||
@property(nonatomic, strong) UIImage* responseThumbnail;
|
||||
|
||||
/// Populated lazily. Handles both normal HTTPBody data and HTTPBodyStreams.
|
||||
@property (nonatomic, strong, readonly) NSData *cachedRequestBody;
|
||||
@property(nonatomic, strong, readonly) NSData* cachedRequestBody;
|
||||
|
||||
+ (NSString *)readableStringFromTransactionState:(FLEXNetworkTransactionState)state;
|
||||
+ (NSString*)readableStringFromTransactionState:
|
||||
(FLEXNetworkTransactionState)state;
|
||||
|
||||
@end
|
||||
|
||||
@@ -9,71 +9,76 @@
|
||||
|
||||
@interface FLEXNetworkTransaction ()
|
||||
|
||||
@property (nonatomic, strong, readwrite) NSData *cachedRequestBody;
|
||||
@property(nonatomic, strong, readwrite) NSData* cachedRequestBody;
|
||||
|
||||
@end
|
||||
|
||||
@implementation FLEXNetworkTransaction
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
NSString *description = [super description];
|
||||
- (NSString*)description {
|
||||
NSString* description = [super description];
|
||||
|
||||
description = [description stringByAppendingFormat:@" id = %@;", self.requestID];
|
||||
description = [description stringByAppendingFormat:@" url = %@;", self.request.URL];
|
||||
description = [description stringByAppendingFormat:@" duration = %f;", self.duration];
|
||||
description = [description stringByAppendingFormat:@" receivedDataLength = %lld", self.receivedDataLength];
|
||||
description =
|
||||
[description stringByAppendingFormat:@" id = %@;", self.requestID];
|
||||
description =
|
||||
[description stringByAppendingFormat:@" url = %@;", self.request.URL];
|
||||
description =
|
||||
[description stringByAppendingFormat:@" duration = %f;", self.duration];
|
||||
description =
|
||||
[description stringByAppendingFormat:@" receivedDataLength = %lld",
|
||||
self.receivedDataLength];
|
||||
|
||||
return description;
|
||||
return description;
|
||||
}
|
||||
|
||||
- (NSData *)cachedRequestBody {
|
||||
if (!_cachedRequestBody) {
|
||||
if (self.request.HTTPBody != nil) {
|
||||
_cachedRequestBody = self.request.HTTPBody;
|
||||
} else if ([self.request.HTTPBodyStream conformsToProtocol:@protocol(NSCopying)]) {
|
||||
NSInputStream *bodyStream = [self.request.HTTPBodyStream copy];
|
||||
const NSUInteger bufferSize = 1024;
|
||||
uint8_t buffer[bufferSize];
|
||||
NSMutableData *data = [NSMutableData data];
|
||||
[bodyStream open];
|
||||
NSInteger readBytes = 0;
|
||||
do {
|
||||
readBytes = [bodyStream read:buffer maxLength:bufferSize];
|
||||
[data appendBytes:buffer length:readBytes];
|
||||
} while (readBytes > 0);
|
||||
[bodyStream close];
|
||||
_cachedRequestBody = data;
|
||||
}
|
||||
- (NSData*)cachedRequestBody {
|
||||
if (!_cachedRequestBody) {
|
||||
if (self.request.HTTPBody != nil) {
|
||||
_cachedRequestBody = self.request.HTTPBody;
|
||||
} else if ([self.request.HTTPBodyStream
|
||||
conformsToProtocol:@protocol(NSCopying)]) {
|
||||
NSInputStream* bodyStream = [self.request.HTTPBodyStream copy];
|
||||
const NSUInteger bufferSize = 1024;
|
||||
uint8_t buffer[bufferSize];
|
||||
NSMutableData* data = [NSMutableData data];
|
||||
[bodyStream open];
|
||||
NSInteger readBytes = 0;
|
||||
do {
|
||||
readBytes = [bodyStream read:buffer maxLength:bufferSize];
|
||||
[data appendBytes:buffer length:readBytes];
|
||||
} while (readBytes > 0);
|
||||
[bodyStream close];
|
||||
_cachedRequestBody = data;
|
||||
}
|
||||
return _cachedRequestBody;
|
||||
}
|
||||
return _cachedRequestBody;
|
||||
}
|
||||
|
||||
+ (NSString *)readableStringFromTransactionState:(FLEXNetworkTransactionState)state
|
||||
{
|
||||
NSString *readableString = nil;
|
||||
switch (state) {
|
||||
case FLEXNetworkTransactionStateUnstarted:
|
||||
readableString = @"Unstarted";
|
||||
break;
|
||||
+ (NSString*)readableStringFromTransactionState:
|
||||
(FLEXNetworkTransactionState)state {
|
||||
NSString* readableString = nil;
|
||||
switch (state) {
|
||||
case FLEXNetworkTransactionStateUnstarted:
|
||||
readableString = @"Unstarted";
|
||||
break;
|
||||
|
||||
case FLEXNetworkTransactionStateAwaitingResponse:
|
||||
readableString = @"Awaiting Response";
|
||||
break;
|
||||
case FLEXNetworkTransactionStateAwaitingResponse:
|
||||
readableString = @"Awaiting Response";
|
||||
break;
|
||||
|
||||
case FLEXNetworkTransactionStateReceivingData:
|
||||
readableString = @"Receiving Data";
|
||||
break;
|
||||
case FLEXNetworkTransactionStateReceivingData:
|
||||
readableString = @"Receiving Data";
|
||||
break;
|
||||
|
||||
case FLEXNetworkTransactionStateFinished:
|
||||
readableString = @"Finished";
|
||||
break;
|
||||
case FLEXNetworkTransactionStateFinished:
|
||||
readableString = @"Finished";
|
||||
break;
|
||||
|
||||
case FLEXNetworkTransactionStateFailed:
|
||||
readableString = @"Failed";
|
||||
break;
|
||||
}
|
||||
return readableString;
|
||||
case FLEXNetworkTransactionStateFailed:
|
||||
readableString = @"Failed";
|
||||
break;
|
||||
}
|
||||
return readableString;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -12,13 +12,15 @@
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
#define FLEXFloor(x) (floor([[UIScreen mainScreen] scale] * (x)) / [[UIScreen mainScreen] scale])
|
||||
#define FLEXFloor(x) \
|
||||
(floor([[UIScreen mainScreen] scale] * (x)) / [[UIScreen mainScreen] scale])
|
||||
|
||||
#define FLEX_AT_LEAST_IOS11_SDK defined(__IPHONE_11_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0)
|
||||
#define FLEX_AT_LEAST_IOS11_SDK \
|
||||
defined(__IPHONE_11_0) && (__IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_11_0)
|
||||
|
||||
@interface NSNumber (SonarUtility)
|
||||
|
||||
+ (NSNumber *)random;
|
||||
+ (NSNumber*)random;
|
||||
|
||||
@end
|
||||
|
||||
@@ -32,8 +34,18 @@
|
||||
// Swizzling utilities
|
||||
|
||||
+ (SEL)swizzledSelectorForSelector:(SEL)selector;
|
||||
+ (BOOL)instanceRespondsButDoesNotImplementSelector:(SEL)selector class:(Class)cls;
|
||||
+ (void)replaceImplementationOfKnownSelector:(SEL)originalSelector onClass:(Class)className withBlock:(id)block swizzledSelector:(SEL)swizzledSelector;
|
||||
+ (void)replaceImplementationOfSelector:(SEL)selector withSelector:(SEL)swizzledSelector forClass:(Class)cls withMethodDescription:(struct objc_method_description)methodDescription implementationBlock:(id)implementationBlock undefinedBlock:(id)undefinedBlock;
|
||||
+ (BOOL)instanceRespondsButDoesNotImplementSelector:(SEL)selector
|
||||
class:(Class)cls;
|
||||
+ (void)replaceImplementationOfKnownSelector:(SEL)originalSelector
|
||||
onClass:(Class)className
|
||||
withBlock:(id)block
|
||||
swizzledSelector:(SEL)swizzledSelector;
|
||||
+ (void)replaceImplementationOfSelector:(SEL)selector
|
||||
withSelector:(SEL)swizzledSelector
|
||||
forClass:(Class)cls
|
||||
withMethodDescription:
|
||||
(struct objc_method_description)methodDescription
|
||||
implementationBlock:(id)implementationBlock
|
||||
undefinedBlock:(id)undefinedBlock;
|
||||
|
||||
@end
|
||||
|
||||
@@ -7,86 +7,102 @@
|
||||
|
||||
#import "FLEXUtility.h"
|
||||
|
||||
#import <objc/runtime.h>
|
||||
#include <assert.h>
|
||||
#import <zlib.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_time.h>
|
||||
#import <objc/runtime.h>
|
||||
#import <zlib.h>
|
||||
|
||||
#import <ImageIO/ImageIO.h>
|
||||
|
||||
@implementation FLEXUtility
|
||||
|
||||
+ (SEL)swizzledSelectorForSelector:(SEL)selector
|
||||
{
|
||||
return NSSelectorFromString([NSString stringWithFormat:@"_flex_swizzle_%x_%@", arc4random(), NSStringFromSelector(selector)]);
|
||||
+ (SEL)swizzledSelectorForSelector:(SEL)selector {
|
||||
return NSSelectorFromString(
|
||||
[NSString stringWithFormat:@"_flex_swizzle_%x_%@",
|
||||
arc4random(),
|
||||
NSStringFromSelector(selector)]);
|
||||
}
|
||||
|
||||
+ (BOOL)instanceRespondsButDoesNotImplementSelector:(SEL)selector class:(Class)cls
|
||||
{
|
||||
if ([cls instancesRespondToSelector:selector]) {
|
||||
unsigned int numMethods = 0;
|
||||
Method *methods = class_copyMethodList(cls, &numMethods);
|
||||
+ (BOOL)instanceRespondsButDoesNotImplementSelector:(SEL)selector
|
||||
class:(Class)cls {
|
||||
if ([cls instancesRespondToSelector:selector]) {
|
||||
unsigned int numMethods = 0;
|
||||
Method* methods = class_copyMethodList(cls, &numMethods);
|
||||
|
||||
BOOL implementsSelector = NO;
|
||||
for (int index = 0; index < numMethods; index++) {
|
||||
SEL methodSelector = method_getName(methods[index]);
|
||||
if (selector == methodSelector) {
|
||||
implementsSelector = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
free(methods);
|
||||
|
||||
if (!implementsSelector) {
|
||||
return YES;
|
||||
}
|
||||
BOOL implementsSelector = NO;
|
||||
for (int index = 0; index < numMethods; index++) {
|
||||
SEL methodSelector = method_getName(methods[index]);
|
||||
if (selector == methodSelector) {
|
||||
implementsSelector = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
free(methods);
|
||||
|
||||
if (!implementsSelector) {
|
||||
return YES;
|
||||
}
|
||||
}
|
||||
|
||||
return NO;
|
||||
}
|
||||
|
||||
+ (void)replaceImplementationOfKnownSelector:(SEL)originalSelector onClass:(Class)className withBlock:(id)block swizzledSelector:(SEL)swizzledSelector
|
||||
{
|
||||
// This method is only intended for swizzling methods that are know to exist on the class.
|
||||
// Bail if that isn't the case.
|
||||
Method originalMethod = class_getInstanceMethod(className, originalSelector);
|
||||
if (!originalMethod) {
|
||||
return;
|
||||
}
|
||||
+ (void)replaceImplementationOfKnownSelector:(SEL)originalSelector
|
||||
onClass:(Class)className
|
||||
withBlock:(id)block
|
||||
swizzledSelector:(SEL)swizzledSelector {
|
||||
// This method is only intended for swizzling methods that are know to exist
|
||||
// on the class. Bail if that isn't the case.
|
||||
Method originalMethod = class_getInstanceMethod(className, originalSelector);
|
||||
if (!originalMethod) {
|
||||
return;
|
||||
}
|
||||
|
||||
IMP implementation = imp_implementationWithBlock(block);
|
||||
class_addMethod(className, swizzledSelector, implementation, method_getTypeEncoding(originalMethod));
|
||||
Method newMethod = class_getInstanceMethod(className, swizzledSelector);
|
||||
method_exchangeImplementations(originalMethod, newMethod);
|
||||
IMP implementation = imp_implementationWithBlock(block);
|
||||
class_addMethod(
|
||||
className,
|
||||
swizzledSelector,
|
||||
implementation,
|
||||
method_getTypeEncoding(originalMethod));
|
||||
Method newMethod = class_getInstanceMethod(className, swizzledSelector);
|
||||
method_exchangeImplementations(originalMethod, newMethod);
|
||||
}
|
||||
|
||||
+ (void)replaceImplementationOfSelector:(SEL)selector withSelector:(SEL)swizzledSelector forClass:(Class)cls withMethodDescription:(struct objc_method_description)methodDescription implementationBlock:(id)implementationBlock undefinedBlock:(id)undefinedBlock
|
||||
{
|
||||
if ([self instanceRespondsButDoesNotImplementSelector:selector class:cls]) {
|
||||
return;
|
||||
}
|
||||
+ (void)replaceImplementationOfSelector:(SEL)selector
|
||||
withSelector:(SEL)swizzledSelector
|
||||
forClass:(Class)cls
|
||||
withMethodDescription:
|
||||
(struct objc_method_description)methodDescription
|
||||
implementationBlock:(id)implementationBlock
|
||||
undefinedBlock:(id)undefinedBlock {
|
||||
if ([self instanceRespondsButDoesNotImplementSelector:selector class:cls]) {
|
||||
return;
|
||||
}
|
||||
|
||||
IMP implementation = imp_implementationWithBlock((id)([cls instancesRespondToSelector:selector] ? implementationBlock : undefinedBlock));
|
||||
IMP implementation = imp_implementationWithBlock((id)(
|
||||
[cls instancesRespondToSelector:selector] ? implementationBlock
|
||||
: undefinedBlock));
|
||||
|
||||
Method oldMethod = class_getInstanceMethod(cls, selector);
|
||||
if (oldMethod) {
|
||||
class_addMethod(cls, swizzledSelector, implementation, methodDescription.types);
|
||||
Method oldMethod = class_getInstanceMethod(cls, selector);
|
||||
if (oldMethod) {
|
||||
class_addMethod(
|
||||
cls, swizzledSelector, implementation, methodDescription.types);
|
||||
|
||||
Method newMethod = class_getInstanceMethod(cls, swizzledSelector);
|
||||
Method newMethod = class_getInstanceMethod(cls, swizzledSelector);
|
||||
|
||||
method_exchangeImplementations(oldMethod, newMethod);
|
||||
} else {
|
||||
class_addMethod(cls, selector, implementation, methodDescription.types);
|
||||
}
|
||||
method_exchangeImplementations(oldMethod, newMethod);
|
||||
} else {
|
||||
class_addMethod(cls, selector, implementation, methodDescription.types);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSNumber (SonarUtility)
|
||||
|
||||
+ (NSNumber *)random {
|
||||
+ (NSNumber*)random {
|
||||
int64_t identifier;
|
||||
arc4random_buf(&identifier, sizeof(int64_t));
|
||||
return @(identifier);
|
||||
@@ -96,8 +112,7 @@
|
||||
|
||||
@implementation NSDate (SonarUtility)
|
||||
|
||||
+ (uint64_t)getTimeNanoseconds
|
||||
{
|
||||
+ (uint64_t)getTimeNanoseconds {
|
||||
static struct mach_timebase_info tb_info = {0};
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
|
||||
#if FB_SONARKIT_ENABLED
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import <FlipperKitNetworkPlugin/SKNetworkReporter.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface SKIOSNetworkAdapter : NSObject<SKNetworkAdapterDelegate>
|
||||
- (instancetype)init NS_DESIGNATED_INITIALIZER;
|
||||
@property (weak, nonatomic) id<SKNetworkReporterDelegate> delegate;
|
||||
@property(weak, nonatomic) id<SKNetworkReporterDelegate> delegate;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@
|
||||
|
||||
@implementation SKIOSNetworkAdapter
|
||||
@synthesize delegate = _delegate;
|
||||
- (instancetype)init{
|
||||
if (self=[super init]){
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_delegate = nil;
|
||||
}
|
||||
return self;
|
||||
|
||||
Reference in New Issue
Block a user