Skip to content

Commit a2c011f

Browse files
committed
Add specific Client Error type
* Using the generic NSError as the error object to callbacks leads to bugs trying to read elements from userInfo which can contain anything. * Calls to client to execute request will use this new OneSignalClientError object in the callback.
1 parent d1a45fd commit a2c011f

File tree

6 files changed

+107
-15
lines changed

6 files changed

+107
-15
lines changed

iOS_SDK/OneSignalSDK/OneSignal.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@
9191
3C6299A92BEEA46C00649187 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 3C6299A82BEEA46C00649187 /* PrivacyInfo.xcprivacy */; };
9292
3C6299AB2BEEA4C000649187 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 3C6299AA2BEEA4C000649187 /* PrivacyInfo.xcprivacy */; };
9393
3C67F77A2BEB2B710085A0F0 /* SwitchUserIntegrationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3C67F7792BEB2B710085A0F0 /* SwitchUserIntegrationTests.swift */; };
94+
3C70FA672D0B68A100031066 /* OneSignalClientError.h in Headers */ = {isa = PBXBuildFile; fileRef = 3C70FA652D0B68A100031066 /* OneSignalClientError.h */; settings = {ATTRIBUTES = (Public, ); }; };
95+
3C70FA682D0B68A100031066 /* OneSignalClientError.m in Sources */ = {isa = PBXBuildFile; fileRef = 3C70FA662D0B68A100031066 /* OneSignalClientError.m */; };
9496
3C789DBD293C2206004CF83D /* OSFocusInfluenceParam.m in Sources */ = {isa = PBXBuildFile; fileRef = 7A600B432453790700514A53 /* OSFocusInfluenceParam.m */; };
9597
3C789DBE293D8EAD004CF83D /* OSFocusInfluenceParam.h in Headers */ = {isa = PBXBuildFile; fileRef = 7A600B41245378ED00514A53 /* OSFocusInfluenceParam.h */; settings = {ATTRIBUTES = (Public, ); }; };
9698
3C7A39C12B7BED900082665E /* OneSignalCoreMocks.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3CC0639A2B6D7A8C002BB07F /* OneSignalCoreMocks.framework */; };
@@ -1263,6 +1265,8 @@
12631265
3C6299A82BEEA46C00649187 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
12641266
3C6299AA2BEEA4C000649187 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = "<group>"; };
12651267
3C67F7792BEB2B710085A0F0 /* SwitchUserIntegrationTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwitchUserIntegrationTests.swift; sourceTree = "<group>"; };
1268+
3C70FA652D0B68A100031066 /* OneSignalClientError.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OneSignalClientError.h; sourceTree = "<group>"; };
1269+
3C70FA662D0B68A100031066 /* OneSignalClientError.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OneSignalClientError.m; sourceTree = "<group>"; };
12661270
3C7A39D42B7C18EE0082665E /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Platforms/iPhoneOS.platform/Developer/Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; };
12671271
3C8544B62C5AEFF600F542A9 /* OneSignalOSCoreMocks.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = OneSignalOSCoreMocks.framework; sourceTree = BUILT_PRODUCTS_DIR; };
12681272
3C8544B82C5AEFF700F542A9 /* OneSignalOSCoreMocks.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = OneSignalOSCoreMocks.h; sourceTree = "<group>"; };
@@ -2646,6 +2650,8 @@
26462650
DE7D1871270375FF002D3A5D /* OSReattemptRequest.m */,
26472651
DE7D186C2703751B002D3A5D /* OSRequests.h */,
26482652
DE7D186D2703751B002D3A5D /* OSRequests.m */,
2653+
3C70FA652D0B68A100031066 /* OneSignalClientError.h */,
2654+
3C70FA662D0B68A100031066 /* OneSignalClientError.m */,
26492655
DE7D1860270374EE002D3A5D /* OneSignalClient.h */,
26502656
DE7D185C270374EE002D3A5D /* OneSignalClient.m */,
26512657
DE7D185F270374EE002D3A5D /* OneSignalRequest.h */,
@@ -3119,6 +3125,7 @@
31193125
isa = PBXHeadersBuildPhase;
31203126
buildActionMask = 2147483647;
31213127
files = (
3128+
3C70FA672D0B68A100031066 /* OneSignalClientError.h in Headers */,
31223129
DE7D1869270374EE002D3A5D /* OneSignalClient.h in Headers */,
31233130
DE51DDE6294262AB0073D5C4 /* OSRemoteParamController.h in Headers */,
31243131
DEF78496291479C100A1F3A5 /* SwizzlingForwarder.h in Headers */,
@@ -4413,6 +4420,7 @@
44134420
files = (
44144421
DEBAAEB32A436CE800BF2C1C /* OSStubInAppMessages.m in Sources */,
44154422
DEBA2A262C20E9AA00E234DB /* OSBundleUtils.m in Sources */,
4423+
3C70FA682D0B68A100031066 /* OneSignalClientError.m in Sources */,
44164424
3C47A975292642B100312125 /* OneSignalConfigManager.m in Sources */,
44174425
DE7D1874270375FF002D3A5D /* OSReattemptRequest.m in Sources */,
44184426
DE7D183427027A73002D3A5D /* OneSignalLog.m in Sources */,

iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OneSignalClient.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,13 @@
2727

2828
#import <Foundation/Foundation.h>
2929
#import <OneSignalCore/OneSignalRequest.h>
30+
#import <OneSignalCore/OneSignalClientError.h>
3031

3132
#ifndef OneSignalClient_h
3233
#define OneSignalClient_h
3334

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

3839
@interface OneSignalClient : NSObject <IOneSignalClient>

iOS_SDK/OneSignalSDK/OneSignalCore/Source/API/OneSignalClient.m

Lines changed: 7 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,11 @@ - (NSURLSessionConfiguration *)configurationWithCachingPolicy:(NSURLRequestCache
6969
return configuration;
7070
}
7171

72-
- (NSError *)privacyConsentErrorWithRequestType:(NSString *)type {
73-
return [NSError errorWithDomain:@"OneSignal Error" code:0 userInfo:@{@"error" : [NSString stringWithFormat: @"Attempted to perform an HTTP request (%@) before the user provided privacy consent.", type]}];
72+
- (OneSignalClientError *)privacyConsentErrorWithRequestType:(NSString *)type {
73+
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];
7474
}
7575

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

8787
if (request.dataRequest) {
8888
if (failureBlock) {
89-
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)]}]);
89+
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]);
9090
}
9191

9292
return;
@@ -118,7 +118,7 @@ - (void)handleMissingAppIdError:(OSFailureBlock)failureBlock withRequest:(OneSig
118118
[OneSignalLog onesignalLog:ONE_S_LL_ERROR message:errorDescription];
119119

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

124124
- (BOOL)validRequest:(OneSignalRequest *)request {
@@ -211,7 +211,7 @@ - (void)handleJSONNSURLResponse:(NSURLResponse*)response data:(NSData*)data erro
211211
[OneSignalLog onesignalLog:ONE_S_LL_VERBOSE message:[NSString stringWithFormat:@"network response (%@) with URL %@: %@", NSStringFromClass([request class]), request.urlRequest.URL.absoluteString, innerJson]];
212212
if (jsonError) {
213213
if (failureBlock != nil)
214-
failureBlock([NSError errorWithDomain:@"OneSignal Error" code:statusCode userInfo:@{@"returned" : jsonError, @"headers": headers}]); // Add headers to error block
214+
failureBlock([[OneSignalClientError alloc] initWithCode:statusCode message:@"Error parsing JSON" responseHeaders:headers response:nil underlyingError:jsonError]);
215215
return;
216216
}
217217
}
@@ -228,14 +228,7 @@ - (void)handleJSONNSURLResponse:(NSURLResponse*)response data:(NSData*)data erro
228228
}
229229
} else if (failureBlock != nil) {
230230
// Make sure to send all the infomation available to the client
231-
if (innerJson != nil && error != nil)
232-
failureBlock([NSError errorWithDomain:@"OneSignalError" code:statusCode userInfo:@{@"returned" : innerJson, @"error": error, @"headers": headers}]);
233-
else if (innerJson != nil)
234-
failureBlock([NSError errorWithDomain:@"OneSignalError" code:statusCode userInfo:@{@"returned" : innerJson, @"headers": headers}]);
235-
else if (error != nil)
236-
failureBlock([NSError errorWithDomain:@"OneSignalError" code:statusCode userInfo:@{@"error" : error, @"headers": headers}]);
237-
else
238-
failureBlock([NSError errorWithDomain:@"OneSignalError" code:statusCode userInfo:@{@"headers": headers}]);
231+
failureBlock([[OneSignalClientError alloc] initWithCode:statusCode message:@"Error encountered making request" responseHeaders:headers response:innerJson underlyingError:error]);
239232
}
240233
}
241234

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/**
2+
* Modified MIT License
3+
*
4+
* Copyright 2024 OneSignal
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* 1. The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* 2. All copies of substantial portions of the Software may only be used in connection
17+
* with services provided by OneSignal.
18+
*
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
* THE SOFTWARE.
26+
*/
27+
28+
#import <Foundation/Foundation.h>
29+
30+
@interface OneSignalClientError : NSObject
31+
@property (readonly) NSInteger code;
32+
@property (strong, nonatomic, readonly, nonnull) NSString *message;
33+
@property (strong, nonatomic, readonly, nonnull) NSError *underlyingError;
34+
@property (strong, nonatomic, readonly, nullable) NSDictionary *responseHeaders;
35+
@property (strong, nonatomic, readonly, nullable) NSDictionary *response;
36+
- (instancetype)initWithCode:(NSInteger)code message:(NSString* _Nonnull)message responseHeaders:(NSDictionary* _Nullable)headers response:(NSDictionary* _Nullable)response underlyingError:(NSError* _Nullable)error;
37+
@end
38+
39+
typedef void (^OSClientFailureBlock)(OneSignalClientError* _Nonnull error);
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/**
2+
* Modified MIT License
3+
*
4+
* Copyright 2024 OneSignal
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* 1. The above copyright notice and this permission notice shall be included in
14+
* all copies or substantial portions of the Software.
15+
*
16+
* 2. All copies of substantial portions of the Software may only be used in connection
17+
* with services provided by OneSignal.
18+
*
19+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25+
* THE SOFTWARE.
26+
*/
27+
28+
#import "OneSignalClientError.h"
29+
30+
@implementation OneSignalClientError
31+
32+
- (instancetype)initWithCode:(NSInteger)code message:(NSString* _Nonnull)message responseHeaders:(NSDictionary* _Nullable)headers response:(NSDictionary* _Nullable)response underlyingError:(NSError* _Nullable)error {
33+
_code = code;
34+
_message = message;
35+
_underlyingError = error;
36+
_response = response;
37+
_responseHeaders = headers;
38+
39+
if (!error) {
40+
NSMutableDictionary *json = [NSMutableDictionary new];
41+
json[@"message"] = message;
42+
json[@"response"] = response;
43+
json[@"responseHeaders"] = headers;
44+
_underlyingError = [NSError errorWithDomain:@"OneSignalClientError" code:code userInfo:json];
45+
}
46+
return self;
47+
}
48+
49+
@end

iOS_SDK/OneSignalSDK/OneSignalCore/Source/OneSignalCore.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@
5757
#import <OneSignalCore/OSInAppMessages.h>
5858
#import <OneSignalCore/OSLocation.h>
5959
#import <OneSignalCore/OSBundleUtils.h>
60+
#import <OneSignalCore/OneSignalClientError.h>
61+
6062
// TODO: Testing: Should this class be defined in this file?
6163
@interface OneSignalCoreImpl : NSObject
6264

0 commit comments

Comments
 (0)