FLEXNetworkLib to SKFLEXNetworkLib
Summary: rename FLEXNetworkLib to SKFLEXNetworkLib so it doesnt clash with Stock FLEX if embedded in the app too also 'fix' 3 warnings by adding explicit casts Reviewed By: lblasa Differential Revision: D35200011 fbshipit-source-id: 82bdecc5076b86958ea0cb80260584c012940045
This commit is contained in:
committed by
Facebook GitHub Bot
parent
fd23a9d626
commit
8cbb5c4d46
@@ -0,0 +1,51 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
/*
|
||||
* The file was derived from FLEXNetworkObserver.h.
|
||||
* All modifications to the original source are licensed under:
|
||||
*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
//
|
||||
// FLEXNetworkObserver.h
|
||||
// Derived from:
|
||||
//
|
||||
// PDAFNetworkDomainController.h
|
||||
// PonyDebugger
|
||||
//
|
||||
// Created by Mike Lewis on 2/27/12.
|
||||
//
|
||||
// Licensed to Square, Inc. under one or more contributor license agreements.
|
||||
// See the LICENSE file distributed with this work for the terms under
|
||||
// which Square, Inc. licenses this file to you.
|
||||
//
|
||||
|
||||
// PonyDebugger Copyright 2012 Square Inc.
|
||||
// Licensed under the Apache License,
|
||||
// Version 2.0(the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
FOUNDATION_EXTERN NSString* const
|
||||
kSKFLEXNetworkObserverEnabledStateChangedNotification;
|
||||
|
||||
/// 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 SKFLEXNetworkRecorder instance which maintains the request
|
||||
/// history and caches response bodies.
|
||||
@interface SKFLEXNetworkObserver : NSObject
|
||||
|
||||
+ (void)start;
|
||||
|
||||
@end
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,118 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
/*
|
||||
* The file was derived from FLEXNetworkRecorder.h.
|
||||
* All modifications to the original source are licensed under:
|
||||
*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
//
|
||||
// FLEXNetworkRecorder.h
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 2/4/15.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
// Copyright (c) 2014-2016, Flipboard
|
||||
// All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this
|
||||
// list of conditions and the following disclaimer in the documentation and/or
|
||||
// other materials provided with the distribution.
|
||||
// * Neither the name of Flipboard nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
// * You must NOT include this project in an application to be submitted
|
||||
// to the App Store™, as this project uses too many private APIs.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import <FlipperKitNetworkPlugin/SKNetworkReporter.h>
|
||||
|
||||
// Notifications posted when the record is updated
|
||||
extern NSString* const kSKFLEXNetworkRecorderNewTransactionNotification;
|
||||
extern NSString* const kSKFLEXNetworkRecorderTransactionUpdatedNotification;
|
||||
extern NSString* const kSKFLEXNetworkRecorderUserInfoTransactionKey;
|
||||
extern NSString* const kSKFLEXNetworkRecorderTransactionsClearedNotification;
|
||||
|
||||
@class SKFLEXNetworkTransaction;
|
||||
|
||||
@interface SKFLEXNetworkRecorder : NSObject
|
||||
|
||||
/// In general, it only makes sense to have one recorder for the entire
|
||||
/// application.
|
||||
+ (instancetype)defaultRecorder;
|
||||
|
||||
@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;
|
||||
|
||||
/// 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 SKFLEXNetworkTransaction objects ordered by start time with the
|
||||
/// newest first.
|
||||
- (NSArray<SKFLEXNetworkTransaction*>*)networkTransactions;
|
||||
|
||||
/// The full response data IFF it hasn't been purged due to memory pressure.
|
||||
- (NSData*)cachedResponseBodyForTransaction:
|
||||
(SKFLEXNetworkTransaction*)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;
|
||||
|
||||
/// Call when HTTP response is available.
|
||||
- (void)recordResponseReceivedWithRequestID:(NSString*)requestID
|
||||
response:(NSURLResponse*)response;
|
||||
|
||||
/// Call when data chunk is received over the network.
|
||||
- (void)recordDataReceivedWithRequestID:(NSString*)requestID
|
||||
dataLength:(int64_t)dataLength;
|
||||
|
||||
/// Call when HTTP request has finished loading.
|
||||
- (void)recordLoadingFinishedWithRequestID:(NSString*)requestID
|
||||
responseBody:(NSData*)responseBody;
|
||||
|
||||
/// Call when HTTP request has failed to load.
|
||||
- (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;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,291 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
/*
|
||||
* The file was derived from FLEXNetworkRecorder.h.
|
||||
* All modifications to the original source are licensed under:
|
||||
*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
//
|
||||
// FLEXNetworkRecorder.m
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 2/4/15.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
// Copyright (c) 2014-2016, Flipboard
|
||||
// All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this
|
||||
// list of conditions and the following disclaimer in the documentation and/or
|
||||
// other materials provided with the distribution.
|
||||
// * Neither the name of Flipboard nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
// * You must NOT include this project in an application to be submitted
|
||||
// to the App Store™, as this project uses too many private APIs.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#import "SKFLEXNetworkRecorder.h"
|
||||
|
||||
#import "SKFLEXNetworkTransaction.h"
|
||||
#import "SKFLEXUtility.h"
|
||||
|
||||
NSString* const kSKFLEXNetworkRecorderNewTransactionNotification =
|
||||
@"kSKFLEXNetworkRecorderNewTransactionNotification";
|
||||
NSString* const kSKFLEXNetworkRecorderTransactionUpdatedNotification =
|
||||
@"kSKFLEXNetworkRecorderTransactionUpdatedNotification";
|
||||
NSString* const kSKFLEXNetworkRecorderUserInfoTransactionKey = @"transaction";
|
||||
NSString* const kSKFLEXNetworkRecorderTransactionsClearedNotification =
|
||||
@"kSKFLEXNetworkRecorderTransactionsClearedNotification";
|
||||
|
||||
NSString* const kSKFLEXNetworkRecorderResponseCacheLimitDefaultsKey =
|
||||
@"com.skflex.responseCacheLimit";
|
||||
|
||||
@interface SKFLEXNetworkRecorder ()
|
||||
|
||||
@property(nonatomic, strong) NSCache* responseCache;
|
||||
@property(nonatomic, strong)
|
||||
NSMutableArray<SKFLEXNetworkTransaction*>* orderedTransactions;
|
||||
@property(nonatomic, strong)
|
||||
NSMutableDictionary<NSString*, SKFLEXNetworkTransaction*>*
|
||||
networkTransactionsForRequestIdentifiers;
|
||||
@property(nonatomic, strong) dispatch_queue_t queue;
|
||||
@property(nonatomic, strong)
|
||||
NSMutableDictionary<NSString*, NSNumber*>* identifierDict;
|
||||
@end
|
||||
|
||||
@implementation SKFLEXNetworkRecorder
|
||||
|
||||
- (instancetype)init {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_responseCache = [NSCache new];
|
||||
NSUInteger responseCacheLimit = [[[NSUserDefaults standardUserDefaults]
|
||||
objectForKey:kSKFLEXNetworkRecorderResponseCacheLimitDefaultsKey]
|
||||
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.skflex.SKFLEXNetworkRecorder", DISPATCH_QUEUE_SERIAL);
|
||||
_identifierDict = [NSMutableDictionary dictionary];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
+ (instancetype)defaultRecorder {
|
||||
static SKFLEXNetworkRecorder* defaultRecorder = nil;
|
||||
static dispatch_once_t onceToken;
|
||||
dispatch_once(&onceToken, ^{
|
||||
defaultRecorder = [[[self class] alloc] init];
|
||||
});
|
||||
return defaultRecorder;
|
||||
}
|
||||
|
||||
#pragma mark - Public Data Access
|
||||
|
||||
- (void)setDelegate:(id<SKNetworkReporterDelegate>)delegate {
|
||||
_delegate = delegate;
|
||||
}
|
||||
|
||||
- (NSUInteger)responseCacheByteLimit {
|
||||
return [self.responseCache totalCostLimit];
|
||||
}
|
||||
|
||||
- (void)setResponseCacheByteLimit:(NSUInteger)responseCacheByteLimit {
|
||||
[self.responseCache setTotalCostLimit:responseCacheByteLimit];
|
||||
[[NSUserDefaults standardUserDefaults]
|
||||
setObject:@(responseCacheByteLimit)
|
||||
forKey:kSKFLEXNetworkRecorderResponseCacheLimitDefaultsKey];
|
||||
}
|
||||
|
||||
- (NSArray<SKFLEXNetworkTransaction*>*)networkTransactions {
|
||||
__block NSArray<SKFLEXNetworkTransaction*>* transactions = nil;
|
||||
dispatch_sync(self.queue, ^{
|
||||
transactions = [self.orderedTransactions copy];
|
||||
});
|
||||
return transactions;
|
||||
}
|
||||
|
||||
- (NSData*)cachedResponseBodyForTransaction:
|
||||
(SKFLEXNetworkTransaction*)transaction {
|
||||
return [self.responseCache objectForKey:transaction.requestID];
|
||||
}
|
||||
|
||||
- (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 {
|
||||
NSDate* requestDate = [NSDate date];
|
||||
dispatch_async(self.queue, ^{
|
||||
if (![self.identifierDict objectForKey:requestID]) {
|
||||
self.identifierDict[requestID] = [NSNumber random];
|
||||
}
|
||||
|
||||
if (redirectResponse) {
|
||||
[self recordResponseReceivedWithRequestID:requestID
|
||||
response:redirectResponse];
|
||||
[self recordLoadingFinishedWithRequestID:requestID responseBody:nil];
|
||||
}
|
||||
|
||||
SKRequestInfo* info = [[SKRequestInfo alloc]
|
||||
initWithIdentifier:self.identifierDict[requestID].longLongValue
|
||||
timestamp:(uint64_t)[NSDate timestamp]
|
||||
request:request
|
||||
data:request.HTTPBody];
|
||||
[self.delegate didObserveRequest:info];
|
||||
|
||||
SKFLEXNetworkTransaction* transaction = [SKFLEXNetworkTransaction new];
|
||||
transaction.requestID = requestID;
|
||||
transaction.request = request;
|
||||
transaction.startTime = requestDate;
|
||||
|
||||
[self.orderedTransactions insertObject:transaction atIndex:0];
|
||||
[self.networkTransactionsForRequestIdentifiers setObject:transaction
|
||||
forKey:requestID];
|
||||
transaction.transactionState =
|
||||
SKFLEXNetworkTransactionStateAwaitingResponse;
|
||||
});
|
||||
}
|
||||
|
||||
/// Call when HTTP response is available.
|
||||
- (void)recordResponseReceivedWithRequestID:(NSString*)requestID
|
||||
response:(NSURLResponse*)response {
|
||||
NSDate* responseDate = [NSDate date];
|
||||
|
||||
dispatch_async(self.queue, ^{
|
||||
SKFLEXNetworkTransaction* transaction =
|
||||
self.networkTransactionsForRequestIdentifiers[requestID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
transaction.response = response;
|
||||
transaction.transactionState = SKFLEXNetworkTransactionStateReceivingData;
|
||||
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, ^{
|
||||
SKFLEXNetworkTransaction* 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, ^{
|
||||
SKFLEXNetworkTransaction* transaction =
|
||||
self.networkTransactionsForRequestIdentifiers[requestID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
transaction.transactionState = SKFLEXNetworkTransactionStateFinished;
|
||||
transaction.duration =
|
||||
-[transaction.startTime timeIntervalSinceDate:finishedDate];
|
||||
SKResponseInfo* responseInfo = [[SKResponseInfo alloc]
|
||||
initWithIndentifier:self.identifierDict[requestID].longLongValue
|
||||
timestamp:(uint64_t)[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];
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldCache) {
|
||||
[self.responseCache setObject:responseBody
|
||||
forKey:requestID
|
||||
cost:[responseBody length]];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)recordLoadingFailedWithRequestID:(NSString*)requestID
|
||||
error:(NSError*)error {
|
||||
dispatch_async(self.queue, ^{
|
||||
SKFLEXNetworkTransaction* transaction =
|
||||
self.networkTransactionsForRequestIdentifiers[requestID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
|
||||
SKResponseInfo* responseInfo = [[SKResponseInfo alloc]
|
||||
initWithIndentifier:self.identifierDict[requestID].longLongValue
|
||||
timestamp:(uint64_t)[NSDate timestamp]
|
||||
response:transaction.response
|
||||
data:nil];
|
||||
self.identifierDict[requestID] = nil; // Clear the entry
|
||||
[self.delegate didObserveResponse:responseInfo];
|
||||
transaction.transactionState = SKFLEXNetworkTransactionStateFailed;
|
||||
transaction.duration = -[transaction.startTime timeIntervalSinceNow];
|
||||
transaction.error = error;
|
||||
});
|
||||
}
|
||||
|
||||
- (void)recordMechanism:(NSString*)mechanism forRequestID:(NSString*)requestID {
|
||||
dispatch_async(self.queue, ^{
|
||||
SKFLEXNetworkTransaction* transaction =
|
||||
self.networkTransactionsForRequestIdentifiers[requestID];
|
||||
if (!transaction) {
|
||||
return;
|
||||
}
|
||||
transaction.requestMechanism = mechanism;
|
||||
});
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,79 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
/*
|
||||
* The file was derived from FLEXNetworkTransaction.h.
|
||||
* All modifications to the original source are licensed under:
|
||||
*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
//
|
||||
// FLEXNetworkTransaction.h
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 2/8/15.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
// Copyright (c) 2014-2016, Flipboard
|
||||
// All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this
|
||||
// list of conditions and the following disclaimer in the documentation and/or
|
||||
// other materials provided with the distribution.
|
||||
// * Neither the name of Flipboard nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
// * You must NOT include this project in an application to be submitted
|
||||
// to the App Store™, as this project uses too many private APIs.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
typedef NS_ENUM(NSInteger, SKFLEXNetworkTransactionState) {
|
||||
SKFLEXNetworkTransactionStateUnstarted,
|
||||
SKFLEXNetworkTransactionStateAwaitingResponse,
|
||||
SKFLEXNetworkTransactionStateReceivingData,
|
||||
SKFLEXNetworkTransactionStateFinished,
|
||||
SKFLEXNetworkTransactionStateFailed
|
||||
};
|
||||
|
||||
@interface SKFLEXNetworkTransaction : NSObject
|
||||
|
||||
@property(nonatomic, copy) NSString* requestID;
|
||||
|
||||
@property(nonatomic, strong) NSURLRequest* request;
|
||||
@property(nonatomic, strong) NSURLResponse* response;
|
||||
@property(nonatomic, copy) NSString* requestMechanism;
|
||||
@property(nonatomic, assign) SKFLEXNetworkTransactionState transactionState;
|
||||
@property(nonatomic, strong) NSError* error;
|
||||
|
||||
@property(nonatomic, strong) NSDate* startTime;
|
||||
@property(nonatomic, assign) NSTimeInterval latency;
|
||||
@property(nonatomic, assign) NSTimeInterval duration;
|
||||
|
||||
@property(nonatomic, assign) int64_t receivedDataLength;
|
||||
|
||||
/// Populated lazily. Handles both normal HTTPBody data and HTTPBodyStreams.
|
||||
@property(nonatomic, strong, readonly) NSData* cachedRequestBody;
|
||||
|
||||
+ (NSString*)readableStringFromTransactionState:
|
||||
(SKFLEXNetworkTransactionState)state;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,123 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
/*
|
||||
* The file was derived from FLEXNetworkTransaction.h.
|
||||
* All modifications to the original source are licensed under:
|
||||
*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
//
|
||||
// FLEXNetworkTransaction.m
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 2/8/15.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
// Copyright (c) 2014-2016, Flipboard
|
||||
// All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this
|
||||
// list of conditions and the following disclaimer in the documentation and/or
|
||||
// other materials provided with the distribution.
|
||||
// * Neither the name of Flipboard nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
// * You must NOT include this project in an application to be submitted
|
||||
// to the App Store™, as this project uses too many private APIs.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#import "SKFLEXNetworkTransaction.h"
|
||||
|
||||
@interface SKFLEXNetworkTransaction ()
|
||||
|
||||
@property(nonatomic, strong, readwrite) NSData* cachedRequestBody;
|
||||
|
||||
@end
|
||||
|
||||
@implementation SKFLEXNetworkTransaction
|
||||
|
||||
- (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];
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
return _cachedRequestBody;
|
||||
}
|
||||
|
||||
+ (NSString*)readableStringFromTransactionState:
|
||||
(SKFLEXNetworkTransactionState)state {
|
||||
NSString* readableString = nil;
|
||||
switch (state) {
|
||||
case SKFLEXNetworkTransactionStateUnstarted:
|
||||
readableString = @"Unstarted";
|
||||
break;
|
||||
|
||||
case SKFLEXNetworkTransactionStateAwaitingResponse:
|
||||
readableString = @"Awaiting Response";
|
||||
break;
|
||||
|
||||
case SKFLEXNetworkTransactionStateReceivingData:
|
||||
readableString = @"Receiving Data";
|
||||
break;
|
||||
|
||||
case SKFLEXNetworkTransactionStateFinished:
|
||||
readableString = @"Finished";
|
||||
break;
|
||||
|
||||
case SKFLEXNetworkTransactionStateFailed:
|
||||
readableString = @"Failed";
|
||||
break;
|
||||
}
|
||||
return readableString;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,84 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
/*
|
||||
* The file was derived from FLEXUtility.h.
|
||||
* All modifications to the original source are licensed under:
|
||||
*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
//
|
||||
// FLEXUtility.h
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 4/18/14.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
// Copyright (c) 2014-2016, Flipboard
|
||||
// All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this
|
||||
// list of conditions and the following disclaimer in the documentation and/or
|
||||
// other materials provided with the distribution.
|
||||
// * Neither the name of Flipboard nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
// * You must NOT include this project in an application to be submitted
|
||||
// to the App Store™, as this project uses too many private APIs.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#import <Availability.h>
|
||||
#import <AvailabilityInternal.h>
|
||||
#import <objc/runtime.h>
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface NSNumber (SonarUtility)
|
||||
|
||||
+ (NSNumber*)random;
|
||||
|
||||
@end
|
||||
|
||||
@interface NSDate (SonarUtility)
|
||||
|
||||
+ (NSTimeInterval)timestamp;
|
||||
|
||||
@end
|
||||
|
||||
@interface SKFLEXUtility : NSObject
|
||||
|
||||
// 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;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,157 @@
|
||||
// @lint-ignore-every LICENSELINT
|
||||
/*
|
||||
* The file was derived from FLEXUtility.h.
|
||||
* All modifications to the original source are licensed under:
|
||||
*
|
||||
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
//
|
||||
// FLEXUtility.m
|
||||
// Flipboard
|
||||
//
|
||||
// Created by Ryan Olson on 4/18/14.
|
||||
// Copyright (c) 2020 FLEX Team. All rights reserved.
|
||||
//
|
||||
|
||||
// Copyright (c) 2014-2016, Flipboard
|
||||
// All rights reserved.
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
// * Redistributions of source code must retain the above copyright notice, this
|
||||
// list of conditions and the following disclaimer.
|
||||
// * Redistributions in binary form must reproduce the above copyright notice,
|
||||
// this
|
||||
// list of conditions and the following disclaimer in the documentation and/or
|
||||
// other materials provided with the distribution.
|
||||
// * Neither the name of Flipboard nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from
|
||||
// this software without specific prior written permission.
|
||||
// * You must NOT include this project in an application to be submitted
|
||||
// to the App Store™, as this project uses too many private APIs.
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#import "SKFLEXUtility.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <mach/mach.h>
|
||||
#include <mach/mach_time.h>
|
||||
#import <objc/runtime.h>
|
||||
#import <zlib.h>
|
||||
|
||||
#import <ImageIO/ImageIO.h>
|
||||
|
||||
@implementation SKFLEXUtility
|
||||
|
||||
+ (SEL)swizzledSelectorForSelector:(SEL)selector {
|
||||
return NSSelectorFromString(
|
||||
[NSString stringWithFormat:@"_skflex_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 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;
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
IMP implementation = imp_implementationWithBlock((id)(
|
||||
[cls instancesRespondToSelector:selector] ? implementationBlock
|
||||
: undefinedBlock));
|
||||
|
||||
Method oldMethod = class_getInstanceMethod(cls, selector);
|
||||
if (oldMethod) {
|
||||
objc_method_description* description = method_getDescription(oldMethod);
|
||||
class_addMethod(cls, swizzledSelector, implementation, description->types);
|
||||
Method newMethod = class_getInstanceMethod(cls, swizzledSelector);
|
||||
method_exchangeImplementations(oldMethod, newMethod);
|
||||
} else {
|
||||
class_addMethod(cls, selector, implementation, methodDescription.types);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSNumber (SonarUtility)
|
||||
|
||||
+ (NSNumber*)random {
|
||||
int64_t identifier;
|
||||
arc4random_buf(&identifier, sizeof(int64_t));
|
||||
return @(identifier);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NSDate (SonarUtility)
|
||||
|
||||
+ (NSTimeInterval)timestamp {
|
||||
const NSTimeInterval timestamp = [[NSDate date] timeIntervalSince1970];
|
||||
return timestamp * 1000;
|
||||
}
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user