Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix: Use new OneSignalClientError type for callbacks #1528

Merged
merged 6 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,8 @@
3C6299A92BEEA46C00649187 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 3C6299A82BEEA46C00649187 /* PrivacyInfo.xcprivacy */; };
3C6299AB2BEEA4C000649187 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 3C6299AA2BEEA4C000649187 /* PrivacyInfo.xcprivacy */; };
3C67F77A2BEB2B710085A0F0 /* SwitchUserIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C67F7792BEB2B710085A0F0 /* SwitchUserIntegrationTests.swift */; };
3C70FA672D0B68A100031066 /* OneSignalClientError.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C70FA652D0B68A100031066 /* OneSignalClientError.h */; settings = {ATTRIBUTES = (Public, ); }; };
3C70FA682D0B68A100031066 /* OneSignalClientError.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C70FA662D0B68A100031066 /* OneSignalClientError.m */; };
3C789DBD293C2206004CF83D /* OSFocusInfluenceParam.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A600B432453790700514A53 /* OSFocusInfluenceParam.m */; };
3C789DBE293D8EAD004CF83D /* OSFocusInfluenceParam.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A600B41245378ED00514A53 /* OSFocusInfluenceParam.h */; settings = {ATTRIBUTES = (Public, ); }; };
3C7A39C12B7BED900082665E /* OneSignalCoreMocks.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3CC0639A2B6D7A8C002BB07F /* OneSignalCoreMocks.framework */; };
Expand Down Expand Up @@ -1263,6 +1265,8 @@
3C6299A82BEEA46C00649187 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
3C6299AA2BEEA4C000649187 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
3C67F7792BEB2B710085A0F0 /* SwitchUserIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwitchUserIntegrationTests.swift; sourceTree = "<group>"; };
3C70FA652D0B68A100031066 /* OneSignalClientError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OneSignalClientError.h; sourceTree = "<group>"; };
3C70FA662D0B68A100031066 /* OneSignalClientError.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OneSignalClientError.m; sourceTree = "<group>"; };
3C7A39D42B7C18EE0082665E /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
3C8544B62C5AEFF600F542A9 /* OneSignalOSCoreMocks.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OneSignalOSCoreMocks.framework; sourceTree = BUILT_PRODUCTS_DIR; };
3C8544B82C5AEFF700F542A9 /* OneSignalOSCoreMocks.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OneSignalOSCoreMocks.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2646,6 +2650,8 @@
DE7D1871270375FF002D3A5D /* OSReattemptRequest.m */,
DE7D186C2703751B002D3A5D /* OSRequests.h */,
DE7D186D2703751B002D3A5D /* OSRequests.m */,
3C70FA652D0B68A100031066 /* OneSignalClientError.h */,
3C70FA662D0B68A100031066 /* OneSignalClientError.m */,
DE7D1860270374EE002D3A5D /* OneSignalClient.h */,
DE7D185C270374EE002D3A5D /* OneSignalClient.m */,
DE7D185F270374EE002D3A5D /* OneSignalRequest.h */,
Expand Down Expand Up @@ -3119,6 +3125,7 @@
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
3C70FA672D0B68A100031066 /* OneSignalClientError.h in Headers */,
DE7D1869270374EE002D3A5D /* OneSignalClient.h in Headers */,
DE51DDE6294262AB0073D5C4 /* OSRemoteParamController.h in Headers */,
DEF78496291479C100A1F3A5 /* SwizzlingForwarder.h in Headers */,
Expand Down Expand Up @@ -4413,6 +4420,7 @@
files = (
DEBAAEB32A436CE800BF2C1C /* OSStubInAppMessages.m in Sources */,
DEBA2A262C20E9AA00E234DB /* OSBundleUtils.m in Sources */,
3C70FA682D0B68A100031066 /* OneSignalClientError.m in Sources */,
3C47A975292642B100312125 /* OneSignalConfigManager.m in Sources */,
DE7D1874270375FF002D3A5D /* OSReattemptRequest.m in Sources */,
DE7D183427027A73002D3A5D /* OneSignalLog.m in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,14 @@

#import <Foundation/Foundation.h>
#import "OneSignalRequest.h"
#import "OneSignalClientError.h"

@interface OSReattemptRequest : NSObject

@property (strong, nonatomic) OneSignalRequest *request;
@property (nonatomic) OSResultSuccessBlock successBlock;
@property (nonatomic) OSFailureBlock failureBlock;
@property (nonatomic) OSClientFailureBlock failureBlock;

+(instancetype)withRequest:(OneSignalRequest *)request successBlock:(OSResultSuccessBlock)success failureBlock:(OSFailureBlock)failure;
+(instancetype)withRequest:(OneSignalRequest *)request successBlock:(OSResultSuccessBlock)success failureBlock:(OSClientFailureBlock)failure;

@end
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

@implementation OSReattemptRequest

+(instancetype)withRequest:(OneSignalRequest *)request successBlock:(OSResultSuccessBlock)success failureBlock:(OSFailureBlock)failure {
+(instancetype)withRequest:(OneSignalRequest *)request successBlock:(OSResultSuccessBlock)success failureBlock:(OSClientFailureBlock)failure {
OSReattemptRequest *reattempt = [OSReattemptRequest new];

reattempt.request = request;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,13 @@

#import <Foundation/Foundation.h>
#import <OneSignalCore/OneSignalRequest.h>
#import <OneSignalCore/OneSignalClientError.h>

#ifndef OneSignalClient_h
#define OneSignalClient_h

@protocol IOneSignalClient <NSObject>
- (void)executeRequest:(OneSignalRequest *)request onSuccess:(OSResultSuccessBlock)successBlock onFailure:(OSFailureBlock)failureBlock;
- (void)executeRequest:(OneSignalRequest *)request onSuccess:(OSResultSuccessBlock)successBlock onFailure:(OSClientFailureBlock)failureBlock;
@end

@interface OneSignalClient : NSObject <IOneSignalClient>
Expand Down
29 changes: 11 additions & 18 deletions iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OneSignalClient.m
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ - (NSURLSessionConfiguration *)configurationWithCachingPolicy:(NSURLRequestCache
return configuration;
}

- (NSError *)privacyConsentErrorWithRequestType:(NSString *)type {
return [NSError errorWithDomain:@"OneSignal Error" code:0 userInfo:@{@"error" : [NSString stringWithFormat: @"Attempted to perform an HTTP request (%@) before the user provided privacy consent.", type]}];
- (OneSignalClientError *)privacyConsentErrorWithRequestType:(NSString *)type {
return [[OneSignalClientError alloc] initWithCode:0 message:[NSString stringWithFormat: @"Attempted to perform an HTTP request (%@) before the user provided privacy consent.", type] responseHeaders:nil response:nil underlyingError:nil];
}

- (void)executeRequest:(OneSignalRequest *)request onSuccess:(OSResultSuccessBlock)successBlock onFailure:(OSFailureBlock)failureBlock {
- (void)executeRequest:(OneSignalRequest *)request onSuccess:(OSResultSuccessBlock)successBlock onFailure:(OSClientFailureBlock)failureBlock {
// If privacy consent is required but not yet given, any non-GET request should be blocked.
if (request.method != GET && [OSPrivacyConsentController shouldLogMissingPrivacyConsentErrorWithMethodName:nil]) {
[OneSignalLog onesignalLog:ONE_S_LL_ERROR message:@"Attempted to perform an HTTP request (%@) before the user provided privacy consent."];
Expand All @@ -86,7 +86,7 @@ - (void)executeRequest:(OneSignalRequest *)request onSuccess:(OSResultSuccessBlo

if (request.dataRequest) {
if (failureBlock) {
failureBlock([NSError errorWithDomain:@"onesignal" code:0 userInfo:@{@"error" : [NSString stringWithFormat:@"Attempted to execute a data-only API request (%@) using OneSignalClient's executeRequest: method, which only accepts JSON-based API requests", NSStringFromClass(request.class)]}]);
failureBlock([[OneSignalClientError alloc] initWithCode:0 message:[NSString stringWithFormat:@"Attempted to execute a data-only API request (%@) using OneSignalClient's executeRequest: method, which only accepts JSON-based API requests", NSStringFromClass(request.class)] responseHeaders:nil response:nil underlyingError:nil]);
}

return;
Expand All @@ -112,13 +112,13 @@ - (void)executeRequest:(OneSignalRequest *)request onSuccess:(OSResultSuccessBlo
[task resume];
}

- (void)handleMissingAppIdError:(OSFailureBlock)failureBlock withRequest:(OneSignalRequest *)request {
- (void)handleMissingAppIdError:(OSClientFailureBlock)failureBlock withRequest:(OneSignalRequest *)request {
NSString *errorDescription = [NSString stringWithFormat:@"HTTP Request (%@) must contain app_id parameter", NSStringFromClass([request class])];

[OneSignalLog onesignalLog:ONE_S_LL_ERROR message:errorDescription];

if (failureBlock)
failureBlock([NSError errorWithDomain:@"OneSignalError" code:-1 userInfo:@{@"error" : errorDescription}]);
failureBlock([[OneSignalClientError alloc] initWithCode:-1 message:errorDescription responseHeaders:nil response:nil underlyingError:nil]);
}

- (BOOL)validRequest:(OneSignalRequest *)request {
Expand Down Expand Up @@ -147,7 +147,7 @@ - (void)reattemptRequest:(OSReattemptRequest *)reattempt {
[self executeRequest:reattempt.request onSuccess:reattempt.successBlock onFailure:reattempt.failureBlock];
}

- (BOOL)willReattemptRequest:(int)statusCode withRequest:(OneSignalRequest *)request success:(OSResultSuccessBlock)successBlock failure:(OSFailureBlock)failureBlock asyncRequest:(BOOL)async {
- (BOOL)willReattemptRequest:(int)statusCode withRequest:(OneSignalRequest *)request success:(OSResultSuccessBlock)successBlock failure:(OSClientFailureBlock)failureBlock asyncRequest:(BOOL)async {
// in the event that there is no network connection, NSURLSession will return status code 0
if ((statusCode >= 500 || statusCode == 0) && request.reattemptCount < MAX_ATTEMPT_COUNT - 1) {
OSReattemptRequest *reattempt = [OSReattemptRequest withRequest:request successBlock:successBlock failureBlock:failureBlock];
Expand Down Expand Up @@ -193,11 +193,11 @@ - (void)prettyPrintDebugStatementWithRequest:(OneSignalRequest *)request {
[OneSignalLog onesignalLog:ONE_S_LL_VERBOSE message:[NSString stringWithFormat:@"HTTP Request (%@) with URL: %@, with parameters: %@ and headers: %@", NSStringFromClass([request class]), request.urlRequest.URL.absoluteString, jsonString, request.additionalHeaders]];
}

- (void)handleJSONNSURLResponse:(NSURLResponse*)response data:(NSData*)data error:(NSError*)error isAsync:(BOOL)async withRequest:(OneSignalRequest *)request onSuccess:(OSResultSuccessBlock)successBlock onFailure:(OSFailureBlock)failureBlock {
- (void)handleJSONNSURLResponse:(NSURLResponse*)response data:(NSData*)data error:(NSError*)error isAsync:(BOOL)async withRequest:(OneSignalRequest *)request onSuccess:(OSResultSuccessBlock)successBlock onFailure:(OSClientFailureBlock)failureBlock {

NSHTTPURLResponse* HTTPResponse = (NSHTTPURLResponse*)response;
NSInteger statusCode = [HTTPResponse statusCode];
NSDictionary *headers = [HTTPResponse allHeaderFields] ?: @{};
NSDictionary *headers = [HTTPResponse allHeaderFields]; // can be null
NSError* jsonError = nil;
NSMutableDictionary* innerJson;

Expand All @@ -211,7 +211,7 @@ - (void)handleJSONNSURLResponse:(NSURLResponse*)response data:(NSData*)data erro
[OneSignalLog onesignalLog:ONE_S_LL_VERBOSE message:[NSString stringWithFormat:@"network response (%@) with URL %@: %@", NSStringFromClass([request class]), request.urlRequest.URL.absoluteString, innerJson]];
if (jsonError) {
if (failureBlock != nil)
failureBlock([NSError errorWithDomain:@"OneSignal Error" code:statusCode userInfo:@{@"returned" : jsonError, @"headers": headers}]); // Add headers to error block
failureBlock([[OneSignalClientError alloc] initWithCode:statusCode message:@"Error parsing JSON" responseHeaders:headers response:nil underlyingError:jsonError]);
return;
}
}
Expand All @@ -228,14 +228,7 @@ - (void)handleJSONNSURLResponse:(NSURLResponse*)response data:(NSData*)data erro
}
} else if (failureBlock != nil) {
// Make sure to send all the infomation available to the client
if (innerJson != nil && error != nil)
failureBlock([NSError errorWithDomain:@"OneSignalError" code:statusCode userInfo:@{@"returned" : innerJson, @"error": error, @"headers": headers}]);
else if (innerJson != nil)
failureBlock([NSError errorWithDomain:@"OneSignalError" code:statusCode userInfo:@{@"returned" : innerJson, @"headers": headers}]);
else if (error != nil)
failureBlock([NSError errorWithDomain:@"OneSignalError" code:statusCode userInfo:@{@"error" : error, @"headers": headers}]);
else
failureBlock([NSError errorWithDomain:@"OneSignalError" code:statusCode userInfo:@{@"headers": headers}]);
failureBlock([[OneSignalClientError alloc] initWithCode:statusCode message:@"Error encountered making request" responseHeaders:headers response:innerJson underlyingError:error]);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* Modified MIT License
*
* Copyright 2024 OneSignal
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* 1. The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* 2. All copies of substantial portions of the Software may only be used in connection
* with services provided by OneSignal.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#import <Foundation/Foundation.h>

@interface OneSignalClientError : NSObject
@property (readonly) NSInteger code;
@property (strong, nonatomic, readonly, nonnull) NSString *message;
@property (strong, nonatomic, readonly, nonnull) NSError *underlyingError;
@property (strong, nonatomic, readonly, nullable) NSDictionary *responseHeaders;
@property (strong, nonatomic, readonly, nullable) NSDictionary *response;
- (instancetype)initWithCode:(NSInteger)code message:(NSString* _Nonnull)message responseHeaders:(NSDictionary* _Nullable)headers response:(NSDictionary* _Nullable)response underlyingError:(NSError* _Nullable)error;
@end

typedef void (^OSClientFailureBlock)(OneSignalClientError* _Nonnull error);
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* Modified MIT License
*
* Copyright 2024 OneSignal
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* 1. The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* 2. All copies of substantial portions of the Software may only be used in connection
* with services provided by OneSignal.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

#import "OneSignalClientError.h"

@implementation OneSignalClientError

- (instancetype)initWithCode:(NSInteger)code message:(NSString* _Nonnull)message responseHeaders:(NSDictionary* _Nullable)headers response:(NSDictionary* _Nullable)response underlyingError:(NSError* _Nullable)error {
_code = code;
_message = message;
_underlyingError = error;
_response = response;
_responseHeaders = headers;

if (!error) {
NSMutableDictionary *json = [NSMutableDictionary new];
json[@"message"] = message;
json[@"response"] = response;
json[@"responseHeaders"] = headers;
_underlyingError = [NSError errorWithDomain:@"OneSignalClientError" code:code userInfo:json];
}
return self;
}

@end
2 changes: 2 additions & 0 deletions iOS_SDK/OneSignalSDK/OneSignalCore/Source/OneSignalCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@
#import <OneSignalCore/OSInAppMessages.h>
#import <OneSignalCore/OSLocation.h>
#import <OneSignalCore/OSBundleUtils.h>
#import <OneSignalCore/OneSignalClientError.h>

// TODO: Testing: Should this class be defined in this file?
@interface OneSignalCoreImpl : NSObject

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public class MockOneSignalClient: NSObject, IOneSignalClient {
let lock = NSLock()

var mockResponses: [String: [String: Any]] = [:]
var mockFailureResponses: [String: NSError] = [:]
var mockFailureResponses: [String: OneSignalClientError] = [:]
public var lastHTTPRequest: OneSignalRequest?
public var networkRequestCount = 0
public var executedRequests: [OneSignalRequest] = []
Expand Down Expand Up @@ -90,7 +90,7 @@ public class MockOneSignalClient: NSObject, IOneSignalClient {
remoteParamsOutcomes = [:]
}

public func execute(_ request: OneSignalRequest, onSuccess successBlock: @escaping OSResultSuccessBlock, onFailure failureBlock: @escaping OSFailureBlock) {
public func execute(_ request: OneSignalRequest, onSuccess successBlock: @escaping OSResultSuccessBlock, onFailure failureBlock: @escaping OSClientFailureBlock) {
print("🧪 MockOneSignalClient execute called")

if executeInstantaneously {
Expand All @@ -117,7 +117,7 @@ public class MockOneSignalClient: NSObject, IOneSignalClient {
return stringified
}

func finishExecutingRequest(_ request: OneSignalRequest, onSuccess successBlock: OSResultSuccessBlock, onFailure failureBlock: OSFailureBlock) {
func finishExecutingRequest(_ request: OneSignalRequest, onSuccess successBlock: OSResultSuccessBlock, onFailure failureBlock: OSClientFailureBlock) {

// TODO: This entire method needs to contained within the equivalent of @synchronized ❗️
print("🧪 completing HTTP request: \(request)")
Expand All @@ -137,8 +137,8 @@ public class MockOneSignalClient: NSObject, IOneSignalClient {
}
if (mockResponses[stringifiedRequest]) != nil {
successBlock(mockResponses[stringifiedRequest])
} else if (mockFailureResponses[stringifiedRequest]) != nil {
failureBlock(mockFailureResponses[stringifiedRequest])
} else if let response = mockFailureResponses[stringifiedRequest] {
failureBlock(response)
} else if fireSuccessForAllRequests {
allRequestsHandled = false
successBlock([:])
Expand Down Expand Up @@ -166,7 +166,7 @@ public class MockOneSignalClient: NSObject, IOneSignalClient {
mockResponses[request] = response
}

public func setMockFailureResponseForRequest(request: String, error: NSError) {
public func setMockFailureResponseForRequest(request: String, error: OneSignalClientError) {
mockFailureResponses[request] = error
}
}
Expand Down
Loading
Loading