Skip to content

Commit a08ca14

Browse files
committed
Merge pull request #82 from ParsePlatform/nlutsenko.notifications
Added NSNotifications being posted on every network request being sent/finished.
2 parents 084a6d0 + b1b1abd commit a08ca14

11 files changed

+190
-36
lines changed

Parse/Internal/Commands/CommandRunner/PFCommandRunningConstants.h

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,3 +33,27 @@ extern NSString *const PFCommandHeaderNameSessionToken;
3333
///--------------------------------------
3434

3535
extern NSString *const PFCommandParameterNameMethodOverride;
36+
37+
///--------------------------------------
38+
/// @name Notifications
39+
///--------------------------------------
40+
41+
/*!
42+
@abstract The name of the notification that is going to be sent before any URL request is sent.
43+
*/
44+
extern NSString *const PFCommandRunnerWillSendURLRequestNotification;
45+
46+
/*!
47+
@abstract The name of the notification that is going to be sent after any URL response is received.
48+
*/
49+
extern NSString *const PFCommandRunnerDidReceiveURLResponseNotification;
50+
51+
/*!
52+
@abstract The key of request(NSURLRequest) in the userInfo dictionary of a notification.
53+
*/
54+
extern NSString *const PFCommandRunnerNotificationURLRequestUserInfoKey;
55+
56+
/*!
57+
@abstract The key of response(NSHTTPURLResponse) in the userInfo dictionary of a notification.
58+
*/
59+
extern NSString *const PFCommandRunnerNotificationURLResponseUserInfoKey;

Parse/Internal/Commands/CommandRunner/PFCommandRunningConstants.m

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,12 @@
2121
NSString *const PFCommandHeaderNameSessionToken = @"X-Parse-Session-Token";
2222

2323
NSString *const PFCommandParameterNameMethodOverride = @"_method";
24+
25+
///--------------------------------------
26+
#pragma mark - Notifications
27+
///--------------------------------------
28+
29+
NSString *const PFCommandRunnerWillSendURLRequestNotification = @"PFCommandRunnerWillSendURLRequestNotification";
30+
NSString *const PFCommandRunnerDidReceiveURLResponseNotification = @"PFCommandRunnerDidReceiveURLResponseNotification";
31+
NSString *const PFCommandRunnerNotificationURLRequestUserInfoKey = @"PFCommandRunnerNotificationURLRequestUserInfoKey";
32+
NSString *const PFCommandRunnerNotificationURLResponseUserInfoKey = @"PFCommandRunnerNotificationURLResponseUserInfoKey";

Parse/Internal/Commands/CommandRunner/URLSession/PFURLSessionCommandRunner.m

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@
3030
#import "PFURLConstructor.h"
3131
#import "PFURLSession.h"
3232

33+
@interface PFURLSessionCommandRunner () <PFURLSessionDelegate>
34+
35+
@property (nonatomic, strong) NSNotificationCenter *notificationCenter;
36+
37+
@end
38+
3339
@implementation PFURLSessionCommandRunner
3440

3541
@synthesize applicationId = _applicationId;
@@ -49,11 +55,12 @@ - (instancetype)initWithDataSource:(id<PFInstallationIdentifierStoreProvider>)da
4955
clientKey:(NSString *)clientKey {
5056
NSURLSessionConfiguration *configuration = [[self class] _urlSessionConfigurationForApplicationId:applicationId
5157
clientKey:clientKey];
52-
PFURLSession *session = [PFURLSession sessionWithConfiguration:configuration];
58+
PFURLSession *session = [PFURLSession sessionWithConfiguration:configuration delegate:self];
5359
PFCommandURLRequestConstructor *constructor = [PFCommandURLRequestConstructor constructorWithDataSource:dataSource];
5460
self = [self initWithDataSource:dataSource
5561
session:session
56-
requestConstructor:constructor];
62+
requestConstructor:constructor
63+
notificationCenter:[NSNotificationCenter defaultCenter]];
5764
if (!self) return nil;
5865

5966
_applicationId = [applicationId copy];
@@ -64,14 +71,16 @@ - (instancetype)initWithDataSource:(id<PFInstallationIdentifierStoreProvider>)da
6471

6572
- (instancetype)initWithDataSource:(id<PFInstallationIdentifierStoreProvider>)dataSource
6673
session:(PFURLSession *)session
67-
requestConstructor:(PFCommandURLRequestConstructor *)requestConstructor {
74+
requestConstructor:(PFCommandURLRequestConstructor *)requestConstructor
75+
notificationCenter:(NSNotificationCenter *)notificationCenter {
6876
self = [super init];
6977
if (!self) return nil;
7078

7179
_initialRetryDelay = PFCommandRunningDefaultRetryDelay;
7280

7381
_requestConstructor = requestConstructor;
7482
_session = session;
83+
_notificationCenter = notificationCenter;
7584

7685
return self;
7786
}
@@ -237,4 +246,30 @@ + (NSURLSessionConfiguration *)_urlSessionConfigurationForApplicationId:(NSStrin
237246
return configuration;
238247
}
239248

249+
///--------------------------------------
250+
#pragma mark - PFURLSessionDelegate
251+
///--------------------------------------
252+
253+
- (void)urlSession:(PFURLSession *)session willPerformURLRequest:(NSURLRequest *)request {
254+
[[BFExecutor defaultPriorityBackgroundExecutor] execute:^{
255+
NSDictionary *userInfo = @{ PFCommandRunnerNotificationURLRequestUserInfoKey : request };
256+
[self.notificationCenter postNotificationName:PFCommandRunnerWillSendURLRequestNotification
257+
object:self
258+
userInfo:userInfo];
259+
}];
260+
}
261+
262+
- (void)urlSession:(PFURLSession *)session didPerformURLRequest:(NSURLRequest *)request withURLResponse:(nullable NSURLResponse *)response {
263+
[[BFExecutor defaultPriorityBackgroundExecutor] execute:^{
264+
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
265+
userInfo[PFCommandRunnerNotificationURLRequestUserInfoKey] = request;
266+
if (response) {
267+
userInfo[PFCommandRunnerNotificationURLResponseUserInfoKey] = response;
268+
}
269+
[self.notificationCenter postNotificationName:PFCommandRunnerDidReceiveURLResponseNotification
270+
object:self
271+
userInfo:userInfo];
272+
}];
273+
}
274+
240275
@end

Parse/Internal/Commands/CommandRunner/URLSession/PFURLSessionCommandRunner_Private.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ NS_ASSUME_NONNULL_BEGIN
2121

2222
- (instancetype)initWithDataSource:(id<PFInstallationIdentifierStoreProvider>)dataSource
2323
session:(PFURLSession *)session
24-
requestConstructor:(PFCommandURLRequestConstructor *)requestConstructor NS_DESIGNATED_INITIALIZER;
24+
requestConstructor:(PFCommandURLRequestConstructor *)requestConstructor
25+
notificationCenter:(NSNotificationCenter *)notificationCenter NS_DESIGNATED_INITIALIZER;
2526

2627
@end
2728

Parse/Internal/Commands/CommandRunner/URLSession/Session/PFURLSession.h

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,15 +17,29 @@
1717

1818
NS_ASSUME_NONNULL_BEGIN
1919

20+
@class PFURLSession;
21+
22+
@protocol PFURLSessionDelegate <NSObject>
23+
24+
- (void)urlSession:(PFURLSession *)session willPerformURLRequest:(NSURLRequest *)request;
25+
- (void)urlSession:(PFURLSession *)session didPerformURLRequest:(NSURLRequest *)request withURLResponse:(nullable NSURLResponse *)response;
26+
27+
@end
28+
2029
@interface PFURLSession : NSObject
2130

31+
@property (nonatomic, weak, readonly) id<PFURLSessionDelegate> delegate;
32+
2233
///--------------------------------------
2334
/// @name Init
2435
///--------------------------------------
2536

2637
- (instancetype)init NS_UNAVAILABLE;
27-
- (instancetype)initWithConfiguration:(NSURLSessionConfiguration *)configuration NS_DESIGNATED_INITIALIZER;
28-
+ (instancetype)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;
38+
- (instancetype)initWithConfiguration:(NSURLSessionConfiguration *)configuration
39+
delegate:(id<PFURLSessionDelegate>)delegate NS_DESIGNATED_INITIALIZER;
40+
41+
+ (instancetype)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration
42+
delegate:(id<PFURLSessionDelegate>)delegate;
2943

3044
///--------------------------------------
3145
/// @name Teardown
@@ -52,7 +66,6 @@ NS_ASSUME_NONNULL_BEGIN
5266
withCancellationToken:(nullable BFCancellationToken *)cancellationToken
5367
progressBlock:(nullable PFProgressBlock)progressBlock;
5468

55-
5669
@end
5770

5871
NS_ASSUME_NONNULL_END

Parse/Internal/Commands/CommandRunner/URLSession/Session/PFURLSession.m

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,17 +41,21 @@ - (instancetype)init {
4141
PFNotDesignatedInitializer();
4242
}
4343

44-
- (instancetype)initWithConfiguration:(NSURLSessionConfiguration *)configuration {
44+
- (instancetype)initWithConfiguration:(NSURLSessionConfiguration *)configuration
45+
delegate:(id<PFURLSessionDelegate>)delegate {
4546
// NOTE: cast to id suppresses warning about designated initializer.
4647
return [(id)self initWithURLSession:[NSURLSession sessionWithConfiguration:configuration
4748
delegate:self
48-
delegateQueue:nil]];
49+
delegateQueue:nil]
50+
delegate:delegate];
4951
}
5052

51-
- (instancetype)initWithURLSession:(NSURLSession *)session {
53+
- (instancetype)initWithURLSession:(NSURLSession *)session
54+
delegate:(id<PFURLSessionDelegate>)delegate {
5255
self = [super init];
5356
if (!self) return nil;
5457

58+
_delegate = delegate;
5559
_urlSession = session;
5660

5761
_sessionTaskQueue = dispatch_queue_create("com.parse.urlSession.tasks", DISPATCH_QUEUE_SERIAL);
@@ -62,12 +66,14 @@ - (instancetype)initWithURLSession:(NSURLSession *)session {
6266
return self;
6367
}
6468

65-
+ (instancetype)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration {
66-
return [[self alloc] initWithConfiguration:configuration];
69+
+ (instancetype)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration
70+
delegate:(id<PFURLSessionDelegate>)delegate {
71+
return [[self alloc] initWithConfiguration:configuration delegate:delegate];
6772
}
6873

69-
+ (instancetype)sessionWithURLSession:(nonnull NSURLSession *)session {
70-
return [[self alloc] initWithURLSession:session];
74+
+ (instancetype)sessionWithURLSession:(nonnull NSURLSession *)session
75+
delegate:(id<PFURLSessionDelegate>)delegate {
76+
return [[self alloc] initWithURLSession:session delegate:delegate];
7177
}
7278

7379
///--------------------------------------
@@ -161,6 +167,8 @@ - (BFTask *)performFileDownloadURLRequestAsync:(NSURLRequest *)request
161167
}
162168

163169
- (BFTask *)_performDataTask:(NSURLSessionDataTask *)dataTask withDelegate:(PFURLSessionDataTaskDelegate *)delegate {
170+
[self.delegate urlSession:self willPerformURLRequest:dataTask.originalRequest];
171+
164172
@weakify(self);
165173
return [BFTask taskFromExecutor:[BFExecutor defaultExecutor] withBlock:^id{
166174
@strongify(self);
@@ -169,6 +177,8 @@ - (BFTask *)_performDataTask:(NSURLSessionDataTask *)dataTask withDelegate:(PFUR
169177

170178
BFTask *resultTask = [delegate.resultTask continueWithBlock:^id(BFTask *task) {
171179
@strongify(self);
180+
[self.delegate urlSession:self didPerformURLRequest:dataTask.originalRequest withURLResponse:delegate.response];
181+
172182
[self _removeDelegateForTaskWithIdentifier:taskIdentifier];
173183
return task;
174184
}];

Parse/Internal/Commands/CommandRunner/URLSession/Session/PFURLSession_Private.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,11 @@ NS_ASSUME_NONNULL_BEGIN
1313

1414
@interface PFURLSession ()
1515

16-
- (instancetype)initWithURLSession:(NSURLSession *)session NS_DESIGNATED_INITIALIZER;
16+
- (instancetype)initWithURLSession:(NSURLSession *)session
17+
delegate:(id<PFURLSessionDelegate>)delegate NS_DESIGNATED_INITIALIZER;
1718

18-
+ (instancetype)sessionWithURLSession:(NSURLSession *)session;
19+
+ (instancetype)sessionWithURLSession:(NSURLSession *)session
20+
delegate:(id<PFURLSessionDelegate>)delegate;
1921

2022
@end
2123

Parse/Internal/Commands/CommandRunner/URLSession/Session/TaskDelegate/PFURLSessionDataTaskDelegate.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ NS_ASSUME_NONNULL_BEGIN
1919
@property (nonatomic, strong, readonly) NSURLSessionDataTask *dataTask;
2020
@property (nonatomic, strong, readonly) BFTask *resultTask;
2121

22+
@property (nonatomic, strong, readonly) NSHTTPURLResponse *response;
23+
2224
- (instancetype)init NS_UNAVAILABLE;
2325
- (instancetype)initForDataTask:(NSURLSessionDataTask *)dataTask
2426
withCancellationToken:(nullable BFCancellationToken *)cancellationToken NS_DESIGNATED_INITIALIZER;

Parse/Internal/Commands/CommandRunner/URLSession/Session/TaskDelegate/PFURLSessionDataTaskDelegate_Private.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313

1414
@property (nonatomic, strong, readonly) dispatch_queue_t dataQueue;
1515

16-
@property (nonatomic, strong, readonly) NSHTTPURLResponse *response;
17-
1816
/*!
1917
@abstract Defaults to to-memory output stream if not overwritten.
2018
*/

Tests/Unit/URLSessionCommandRunnerTests.m

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ - (void)testRunCommand {
5454
id mockedDataSource = PFStrictProtocolMock(@protocol(PFInstallationIdentifierStoreProvider));
5555
id mockedSession = PFStrictClassMock([PFURLSession class]);
5656
id mockedRequestConstructor = PFStrictClassMock([PFCommandURLRequestConstructor class]);
57+
id mockedNotificationCenter = PFStrictClassMock([NSNotificationCenter class]);
5758

5859
id mockedCommand = PFStrictClassMock([PFRESTCommand class]);
5960
id mockedCommandResult = PFStrictClassMock([PFCommandResult class]);
@@ -71,7 +72,8 @@ - (void)testRunCommand {
7172

7273
PFURLSessionCommandRunner *commandRunner = [[PFURLSessionCommandRunner alloc] initWithDataSource:mockedDataSource
7374
session:mockedSession
74-
requestConstructor:mockedRequestConstructor];
75+
requestConstructor:mockedRequestConstructor
76+
notificationCenter:mockedNotificationCenter];
7577

7678
XCTestExpectation *expecatation = [self currentSelectorTestExpectation];
7779
[[commandRunner runCommandAsync:mockedCommand withOptions:0] continueWithBlock:^id(BFTask *task) {
@@ -89,14 +91,16 @@ - (void)testRunCommandCancel {
8991
id mockedDataSource = PFStrictProtocolMock(@protocol(PFInstallationIdentifierStoreProvider));
9092
id mockedSession = PFStrictClassMock([PFURLSession class]);
9193
id mockedRequestConstructor = PFStrictClassMock([PFCommandURLRequestConstructor class]);
94+
id mockedNotificationCenter = PFStrictClassMock([NSNotificationCenter class]);
9295

9396
id mockedCommand = PFStrictClassMock([PFRESTCommand class]);
9497

9598
OCMStub([mockedSession invalidateAndCancel]);
9699

97100
PFURLSessionCommandRunner *commandRunner = [[PFURLSessionCommandRunner alloc] initWithDataSource:mockedDataSource
98101
session:mockedSession
99-
requestConstructor:mockedRequestConstructor];
102+
requestConstructor:mockedRequestConstructor
103+
notificationCenter:mockedNotificationCenter];
100104

101105
BFCancellationTokenSource *cancellationToken = [BFCancellationTokenSource cancellationTokenSource];
102106
[cancellationToken cancel];
@@ -117,6 +121,7 @@ - (void)testRunCommandRetry {
117121
id mockedDataSource = PFStrictProtocolMock(@protocol(PFInstallationIdentifierStoreProvider));
118122
id mockedSession = PFStrictClassMock([PFURLSession class]);
119123
id mockedRequestConstructor = PFStrictClassMock([PFCommandURLRequestConstructor class]);
124+
id mockedNotificationCenter = PFStrictClassMock([NSNotificationCenter class]);
120125

121126
id mockedCommand = PFStrictClassMock([PFRESTCommand class]);
122127

@@ -140,7 +145,8 @@ - (void)testRunCommandRetry {
140145

141146
PFURLSessionCommandRunner *commandRunner = [[PFURLSessionCommandRunner alloc] initWithDataSource:mockedDataSource
142147
session:mockedSession
143-
requestConstructor:mockedRequestConstructor];
148+
requestConstructor:mockedRequestConstructor
149+
notificationCenter:mockedNotificationCenter];
144150
commandRunner.initialRetryDelay = DBL_MIN; // Lets not needlessly sleep here.
145151

146152
XCTestExpectation *expecatation = [self currentSelectorTestExpectation];
@@ -162,6 +168,7 @@ - (void)testRunFileUpload {
162168
id mockedDataSource = PFStrictProtocolMock(@protocol(PFInstallationIdentifierStoreProvider));
163169
id mockedSession = PFStrictClassMock([PFURLSession class]);
164170
id mockedRequestConstructor = PFStrictClassMock([PFCommandURLRequestConstructor class]);
171+
id mockedNotificationCenter = PFStrictClassMock([NSNotificationCenter class]);
165172

166173
id mockedCommand = PFStrictClassMock([PFRESTCommand class]);
167174
id mockedCommandResult = PFStrictClassMock([PFCommandResult class]);
@@ -191,7 +198,8 @@ - (void)testRunFileUpload {
191198

192199
PFURLSessionCommandRunner *commandRunner = [[PFURLSessionCommandRunner alloc] initWithDataSource:mockedDataSource
193200
session:mockedSession
194-
requestConstructor:mockedRequestConstructor];
201+
requestConstructor:mockedRequestConstructor
202+
notificationCenter:mockedNotificationCenter];
195203

196204
XCTestExpectation *expecatation = [self currentSelectorTestExpectation];
197205
[[commandRunner runFileUploadCommandAsync:mockedCommand
@@ -213,6 +221,7 @@ - (void)testLocalIdResolution {
213221
id mockedDataSource = PFStrictProtocolMock(@protocol(PFInstallationIdentifierStoreProvider));
214222
id mockedSession = PFStrictClassMock([PFURLSession class]);
215223
id mockedRequestConstructor = PFStrictClassMock([PFCommandURLRequestConstructor class]);
224+
id mockedNotificationCenter = PFStrictClassMock([NSNotificationCenter class]);
216225

217226
id mockedCommand = PFStrictClassMock([PFRESTCommand class]);
218227
id mockedCommandResult = PFStrictClassMock([PFCommandResult class]);
@@ -230,7 +239,8 @@ - (void)testLocalIdResolution {
230239

231240
PFURLSessionCommandRunner *commandRunner = [[PFURLSessionCommandRunner alloc] initWithDataSource:mockedDataSource
232241
session:mockedSession
233-
requestConstructor:mockedRequestConstructor];
242+
requestConstructor:mockedRequestConstructor
243+
notificationCenter:mockedNotificationCenter];
234244

235245
XCTestExpectation *expecatation = [self currentSelectorTestExpectation];
236246
[[commandRunner runCommandAsync:mockedCommand withOptions:0] continueWithBlock:^id(BFTask *task) {

0 commit comments

Comments
 (0)