Skip to content
This repository
Browse code

Facebook iOS SDK 3.11.1

Summary:
    see https://developers.facebook.com/ios/change-log-3.x/

Upgrading:
    https://developers.facebook.com/docs/ios/upgrading/

Reviewed By: jacl

Test Plan: Release Testing.
  • Loading branch information...
commit 283b0d0dd5cde6fd6abef87c028df93bc11fe5df 1 parent 3c38d5d
Todd Krabach toddkrabach authored
2  scripts/build_documentation.sh
@@ -45,7 +45,7 @@ rm -rf $DOCSET
45 45
46 46 hash $APPLEDOC &>/dev/null
47 47 if [ "$?" -eq "0" ]; then
48   - APPLEDOC_DOCSET_NAME="Facebook SDK 3.11 for iOS"
  48 + APPLEDOC_DOCSET_NAME="Facebook SDK 3.11.1 for iOS"
49 49 $APPLEDOC --project-name "$APPLEDOC_DOCSET_NAME" \
50 50 --project-company "Facebook" \
51 51 --company-id "com.facebook" \
2  scripts/productbuild_distribution.xml
@@ -12,7 +12,7 @@
12 12 <pkg-ref id="com.facebook.sdk.pkg"/>
13 13 </choice>
14 14
15   - <title>Facebook SDK 3.11 for iOS</title>
  15 + <title>Facebook SDK 3.11.1 for iOS</title>
16 16 <conclusion file="README.txt" mime-type="text/plain" />
17 17 <readme file="README.txt" mime-type="text/plain" />
18 18 <domains enable_currentUserHome="true" />
6 src/FBRequestConnection.m
@@ -1234,11 +1234,11 @@ - (void)completeWithResults:(NSArray *)results
1234 1234 } queue:dispatch_get_main_queue()];
1235 1235
1236 1236 taskWork = [taskWork completionTaskWithQueue:dispatch_get_main_queue() block:^id(FBTask *task) {
1237   - if (task.result == ACAccountCredentialRenewResultRenewed) {
  1237 + if ([@(ACAccountCredentialRenewResultRenewed) isEqual:task.result]) {
1238 1238 FBTask *requestAccessTask = [systemAccountStoreAdapter requestAccessToFacebookAccountStoreAsTask:metadata.request.session];
1239 1239 return [requestAccessTask completionTaskWithQueue:dispatch_get_main_queue() block:^id(FBTask *task) {
1240   - if (task.result) { // aka success means task.result == (oauthToken)
1241   - [metadata.request.session refreshAccessToken:task.result expirationDate:[NSDate distantFuture]];
  1240 + if (task.result && [task.result isKindOfClass:[NSString class]]) { // aka success means task.result == (oauthToken)
  1241 + [metadata.request.session refreshAccessToken:(NSString *)task.result expirationDate:[NSDate distantFuture]];
1242 1242 [metadata invokeCompletionHandlerForConnection:self
1243 1243 withResults:body
1244 1244 error:[FBErrorUtility fberrorForRetry:unpackedError]];
7 src/FBSystemAccountStoreAdapter.h
@@ -32,13 +32,6 @@ typedef void (^FBRequestAccessToAccountsHandler)(NSString* oauthToken, NSError *
32 32 @interface FBSystemAccountStoreAdapter : NSObject
33 33
34 34 /*
35   - @abstract A convenience overload to default various parameters based on the provided session,
36   - typically only for requesting a new token for the provided session.
37   -*/
38   -- (void)requestAccessToFacebookAccountStore:(FBSession *)session
39   - handler:(FBRequestAccessToAccountsHandler)handler;
40   -
41   -/*
42 35 @abstract
43 36 Requests access to the device's Facebook account for the given parameters.
44 37 @param permissions the permissions
22 src/FBSystemAccountStoreAdapter.m
@@ -106,8 +106,13 @@ - (BOOL) canRequestAccessWithoutUI {
106 106 #pragma mark - Public properties and methods
107 107
108 108 - (FBTask *)requestAccessToFacebookAccountStoreAsTask:(FBSession *)session {
109   - FBTaskCompletionSource* tcs = [FBTaskCompletionSource taskCompletionSource];
110   - [self requestAccessToFacebookAccountStore:session handler:^(NSString *oauthToken, NSError *accountStoreError) {
  109 + FBTaskCompletionSource *tcs = [FBTaskCompletionSource taskCompletionSource];
  110 + [self requestAccessToFacebookAccountStore:nil
  111 + defaultAudience:session.lastRequestedSystemAudience
  112 + isReauthorize:NO
  113 + appID:session.appID
  114 + session:session
  115 + handler:^(NSString *oauthToken, NSError *accountStoreError) {
111 116 if (accountStoreError) {
112 117 [tcs setError:accountStoreError];
113 118 } else {
@@ -117,17 +122,6 @@ - (FBTask *)requestAccessToFacebookAccountStoreAsTask:(FBSession *)session {
117 122 return tcs.task;
118 123 }
119 124
120   -
121   -- (void)requestAccessToFacebookAccountStore:(FBSession *)session
122   - handler:(FBRequestAccessToAccountsHandler)handler {
123   - return [self requestAccessToFacebookAccountStore:session.accessTokenData.permissions
124   - defaultAudience:session.lastRequestedSystemAudience
125   - isReauthorize:NO
126   - appID:session.appID
127   - session:session
128   - handler:handler];
129   -}
130   -
131 125 - (void)requestAccessToFacebookAccountStore:(NSArray *)permissions
132 126 defaultAudience:(FBSessionDefaultAudience)defaultAudience
133 127 isReauthorize:(BOOL)isReauthorize
@@ -312,7 +306,7 @@ - (FBTask *)renewSystemAuthorizationAsTask {
312 306 if (error) {
313 307 [tcs setError:error];
314 308 } else {
315   - [tcs setResult:result];
  309 + [tcs setResult:@(result)];
316 310 }
317 311 }];
318 312 return tcs.task;
4 src/FBTask.h
@@ -26,7 +26,7 @@
26 26 /*!
27 27 Creates a task that is already completed with the given result.
28 28 */
29   -+ (FBTask *)taskWithResult:(id)result;
  29 ++ (FBTask *)taskWithResult:(id<NSObject>)result;
30 30
31 31 /*!
32 32 Creates a task that is already completed with the given error.
@@ -61,7 +61,7 @@
61 61 /*!
62 62 The result of a successful task.
63 63 */
64   -- (id)result;
  64 +- (id<NSObject>)result;
65 65
66 66 /*!
67 67 The error of a failed task.
19 src/FBTask.m
@@ -26,7 +26,7 @@
26 26 }
27 27
28 28 @interface FBTask () {
29   - id _result;
  29 + id<NSObject> _result;
30 30 NSError *_error;
31 31 NSException *_exception;
32 32 BOOL _cancelled;
@@ -53,11 +53,14 @@ - (void)dealloc {
53 53 [_lock release];
54 54 [_condition release];
55 55 [_callbacks release];
  56 + [_result release];
  57 + [_error release];
  58 + [_exception release];
56 59
57 60 [super dealloc];
58 61 }
59 62
60   -+ (FBTask *)taskWithResult:(id)result {
  63 ++ (FBTask *)taskWithResult:(id<NSObject>)result {
61 64 FBTaskCompletionSource *tcs = [FBTaskCompletionSource taskCompletionSource];
62 65 tcs.result = result;
63 66 return tcs.task;
@@ -107,26 +110,26 @@ + (FBTask *)taskWithDelay:(dispatch_time_t)delay {
107 110 return tcs.task;
108 111 }
109 112
110   -- (id)result {
  113 +- (id<NSObject>)result {
111 114 @synchronized (self.lock) {
112 115 return _result;
113 116 }
114 117 }
115 118
116   -- (void)setResult:(id)result {
  119 +- (void)setResult:(id<NSObject>)result {
117 120 if (![self trySetResult:result]) {
118 121 [NSException raise:NSInternalInconsistencyException
119 122 format:@"Cannot set the result on a completed task."];
120 123 }
121 124 }
122 125
123   -- (BOOL)trySetResult:(id)result {
  126 +- (BOOL)trySetResult:(id<NSObject>)result {
124 127 @synchronized (self.lock) {
125 128 if (self.completed) {
126 129 return NO;
127 130 }
128 131 self.completed = YES;
129   - _result = result;
  132 + _result = [result retain];
130 133 [self runContinuations];
131 134 return YES;
132 135 }
@@ -151,7 +154,7 @@ - (BOOL)trySetError:(NSError *)error {
151 154 return NO;
152 155 }
153 156 self.completed = YES;
154   - _error = error;
  157 + _error = [error retain];
155 158 [self runContinuations];
156 159 return YES;
157 160 }
@@ -176,7 +179,7 @@ - (BOOL)trySetException:(NSException *)exception {
176 179 return NO;
177 180 }
178 181 self.completed = YES;
179   - _exception = exception;
  182 + _exception = [exception retain];
180 183 [self runContinuations];
181 184 return YES;
182 185 }
4 src/FBTaskCompletionSource.h
@@ -38,7 +38,7 @@
38 38 Completes the task by setting the result.
39 39 Attempting to set this for a completed task will raise an exception.
40 40 */
41   -- (void)setResult:(id)result;
  41 +- (void)setResult:(id<NSObject>)result;
42 42
43 43 /*!
44 44 Completes the task by setting the error.
@@ -62,7 +62,7 @@
62 62 Sets the result of the task if it wasn't already completed.
63 63 @returns whether the new value was set.
64 64 */
65   -- (BOOL)trySetResult:(id)result;
  65 +- (BOOL)trySetResult:(id<NSObject>)result;
66 66
67 67 /*!
68 68 Sets the error of the task if it wasn't already completed.
8 src/FBTaskCompletionSource.m
@@ -23,11 +23,11 @@ @interface FBTaskCompletionSource ()
23 23 @end
24 24
25 25 @interface FBTask (FBTaskCompletionSource)
26   -- (void)setResult:(id)result;
  26 +- (void)setResult:(id<NSObject>)result;
27 27 - (void)setError:(NSError *)error;
28 28 - (void)setException:(NSException *)exception;
29 29 - (void)cancel;
30   -- (BOOL)trySetResult:(id)result;
  30 +- (BOOL)trySetResult:(id<NSObject>)result;
31 31 - (BOOL)trySetError:(NSError *)error;
32 32 - (BOOL)trySetException:(NSException *)exception;
33 33 - (BOOL)trySetCancelled;
@@ -52,7 +52,7 @@ - (void)dealloc {
52 52 [super dealloc];
53 53 }
54 54
55   -- (void)setResult:(id)result {
  55 +- (void)setResult:(id<NSObject>)result {
56 56 [self.task setResult:result];
57 57 }
58 58
@@ -68,7 +68,7 @@ - (void)cancel {
68 68 [self.task cancel];
69 69 }
70 70
71   -- (BOOL)trySetResult:(id)result {
  71 +- (BOOL)trySetResult:(id<NSObject>)result {
72 72 return [self.task trySetResult:result];
73 73 }
74 74
2  src/FacebookSDK.h
@@ -135,5 +135,5 @@
135 135
136 136 */
137 137
138   -#define FB_IOS_SDK_VERSION_STRING @"3.11.0"
  138 +#define FB_IOS_SDK_VERSION_STRING @"3.11.1"
139 139
173 src/tests/FBRequestConnectionTests.m
@@ -27,12 +27,63 @@
27 27 #import "FBSession.h"
28 28 #import "FBSessionTokenCachingStrategy.h"
29 29 #import "FBSettings.h"
  30 +#import "FBSystemAccountStoreAdapter.h"
30 31 #import "FBTestBlocker.h"
31 32 #import "FBTestSession+Internal.h"
32 33 #import "FBTestSession.h"
33 34 #import "FBURLConnection.h"
34 35 #import "FBUtility.h"
35 36
  37 +@interface MockFBSystemAccountStoreAdapter : FBSystemAccountStoreAdapter {
  38 + id _oauthTokenToSurface;
  39 +}
  40 +
  41 +@property (assign, readwrite) BOOL forceBlockingRenew;
  42 +@property (assign, readwrite) BOOL canRequestAccessWithoutUI;
  43 +
  44 +@property (nonatomic, retain) NSError *errorToSurfaceTo;
  45 +
  46 +@property (nonatomic, assign) ACAccountCredentialRenewResult renewResultToSurface;
  47 +@end
  48 +
  49 +@implementation MockFBSystemAccountStoreAdapter
  50 +
  51 +@synthesize forceBlockingRenew;
  52 +@synthesize canRequestAccessWithoutUI;
  53 +
  54 +- (void)requestAccessToFacebookAccountStore:(NSArray *)permissions
  55 + defaultAudience:(FBSessionDefaultAudience)defaultAudience
  56 + isReauthorize:(BOOL)isReauthorize
  57 + appID:(NSString *)appID
  58 + session:(FBSession *)session
  59 + handler:(FBRequestAccessToAccountsHandler)handler {
  60 + handler(self.oauthTokenToSurface, self.errorToSurfaceTo);
  61 +}
  62 +
  63 +- (void)renewSystemAuthorization:(void(^)(ACAccountCredentialRenewResult result, NSError *error))handler {
  64 + handler(self.renewResultToSurface, self.errorToSurfaceTo);
  65 +}
  66 +
  67 +- (id)oauthTokenToSurface {
  68 + id token = [_oauthTokenToSurface autorelease];
  69 + // oauthTokenToSurface has this unusual impl in order to test
  70 + // what happens if the the caller (i.e., FBTask) doesn't retain
  71 + // the object.
  72 + _oauthTokenToSurface = nil;
  73 + return token;
  74 +}
  75 +
  76 +- (void)setOauthTokenToSurface: (id)oauthTokenToSurface {
  77 + _oauthTokenToSurface = [oauthTokenToSurface retain];
  78 +}
  79 +
  80 +- (void)dealloc {
  81 + [_errorToSurfaceTo release];
  82 + [_oauthTokenToSurface release];
  83 + [super dealloc];
  84 +}
  85 +
  86 +@end
36 87 // This is just to silence compiler warnings since we access internal methods in some tests.
37 88 @interface FBSession (Testing)
38 89
@@ -524,4 +575,126 @@ - (void)testOpenGraphObjectPostBogus {
524 575 STAssertThrows([connection urlRequest], @"expected failure to serialize bogus key");
525 576 }
526 577
  578 +// A complicated test of completeWithResults for a system auth login
  579 +// where the response is an invalid session
  580 +// and the token is expired
  581 +// so then there should be a system account renewal
  582 +// follow by a system account auth
  583 +- (void)testCompleteWithResultsSystemAccountRenewal {
  584 + // Swap out the mock system account store adapter.
  585 + FBSystemAccountStoreAdapter *originalAdapter = [[FBSystemAccountStoreAdapter sharedInstance] retain];
  586 + MockFBSystemAccountStoreAdapter *mockSystemAccountStoreAdapter = [[MockFBSystemAccountStoreAdapter alloc] init];
  587 + [FBSystemAccountStoreAdapter setSharedInstance:mockSystemAccountStoreAdapter];
  588 + mockSystemAccountStoreAdapter.canRequestAccessWithoutUI = YES;
  589 + mockSystemAccountStoreAdapter.renewResultToSurface = ACAccountCredentialRenewResultRenewed;
  590 + NSString *newtoken = [[NSString alloc] initWithCString:"newtoken" encoding:NSUTF8StringEncoding];
  591 + mockSystemAccountStoreAdapter.oauthTokenToSurface = newtoken;
  592 + [newtoken release];
  593 +
  594 + FBTestSession *session = [[[FBTestSession alloc] initWithAppID:@"appid" permissions:nil defaultAudience:FBSessionDefaultAudienceOnlyMe urlSchemeSuffix:nil tokenCacheStrategy:[FBSessionTokenCachingStrategy nullCacheInstance]] autorelease];
  595 + FBAccessTokenData *tokenData = [FBAccessTokenData createTokenFromString:@"token" permissions:nil expirationDate:nil loginType:FBSessionLoginTypeSystemAccount refreshDate:nil permissionsRefreshDate:[NSDate date]];
  596 + __block BOOL tokenRefreshed = NO;
  597 + [session openFromAccessTokenData:tokenData completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
  598 + if (status == FBSessionStateOpenTokenExtended) {
  599 + tokenRefreshed = YES;
  600 + }
  601 + }];
  602 +
  603 + __block int requestCount = 0;
  604 + [OHHTTPStubs shouldStubRequestsPassingTest:^BOOL(NSURLRequest *request) {
  605 + return YES;
  606 + } withStubResponse:^OHHTTPStubsResponse *(NSURLRequest *request) {
  607 + // Construct a fake error object that will be categorized for reconnecting the session. Note this error is only for non-batched requests.
  608 + // If there is a test failure, you should verify the requests.count == 1 and debug that if it's not; otherwise this error response will likely cause
  609 + // an unrelated error to be surfaced. For example, the session init above set the permissionsRefreshDate to [NSDate date]. If it had not,
  610 + // there could be piggy-backed permissions request which would then expect a batch response. So, this test doubles to verify there was no
  611 + // piggybacked request when the permissionRefreshDate is set.
  612 + NSData *data = [@"{\"error\": {\"message\": \"expired token\",\"code\": 190,\"error_subcode\": 463}}" dataUsingEncoding:NSUTF8StringEncoding];
  613 +
  614 + requestCount++;
  615 + return [OHHTTPStubsResponse responseWithData:data
  616 + statusCode:400
  617 + responseTime:0
  618 + headers:nil];
  619 + }];
  620 +
  621 + FBTestBlocker *blocker = [[[FBTestBlocker alloc] init] autorelease];
  622 + FBRequestConnection *connection = [[[FBRequestConnection alloc] init] autorelease];
  623 + FBRequest *request =[[[FBRequest alloc] initWithSession:session graphPath:@"me"] autorelease];
  624 +
  625 + __block int handlerCount = 0;
  626 + [connection addRequest:request completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
  627 + STAssertEquals(0, handlerCount++, @"user handler invoked more than once");
  628 + [blocker signal];
  629 + } ];
  630 + [connection start];
  631 +
  632 + [blocker wait];
  633 +
  634 + STAssertTrue(tokenRefreshed, @"expected session to be extended");
  635 + STAssertEqualObjects(@"newtoken", session.accessTokenData.accessToken, @"expected newtoken");
  636 +
  637 + // clean up.
  638 + [FBSystemAccountStoreAdapter setSharedInstance:originalAdapter];
  639 +}
  640 +
  641 +// A complicated test of completeWithResults for a system auth login
  642 +// where the response is an invalid session
  643 +// and the token is expired
  644 +// so then there should be a system account renewal
  645 +// follow by a system account auth
  646 +- (void)testCompleteWithResultsSystemAccountRenewalNoToken {
  647 + // Swap out the mock system account store adapter.
  648 + FBSystemAccountStoreAdapter *originalAdapter = [[FBSystemAccountStoreAdapter sharedInstance] retain];
  649 + MockFBSystemAccountStoreAdapter *mockSystemAccountStoreAdapter = [[MockFBSystemAccountStoreAdapter alloc] init];
  650 + [FBSystemAccountStoreAdapter setSharedInstance:mockSystemAccountStoreAdapter];
  651 + mockSystemAccountStoreAdapter.canRequestAccessWithoutUI = YES;
  652 + mockSystemAccountStoreAdapter.renewResultToSurface = ACAccountCredentialRenewResultRenewed;
  653 + mockSystemAccountStoreAdapter.oauthTokenToSurface = nil; // set up a bogus token result, so the session should be closed.
  654 +
  655 + FBTestSession *session = [[[FBTestSession alloc] initWithAppID:@"appid" permissions:nil defaultAudience:FBSessionDefaultAudienceOnlyMe urlSchemeSuffix:nil tokenCacheStrategy:[FBSessionTokenCachingStrategy nullCacheInstance]] autorelease];
  656 + FBAccessTokenData *tokenData = [FBAccessTokenData createTokenFromString:@"token" permissions:nil expirationDate:nil loginType:FBSessionLoginTypeSystemAccount refreshDate:nil permissionsRefreshDate:[NSDate date]];
  657 + __block BOOL sessionClosed = NO;
  658 + [session openFromAccessTokenData:tokenData completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
  659 + if (status == FBSessionStateClosed) {
  660 + sessionClosed = YES;
  661 + }
  662 + }];
  663 +
  664 + __block int requestCount = 0;
  665 + [OHHTTPStubs shouldStubRequestsPassingTest:^BOOL(NSURLRequest *request) {
  666 + return YES;
  667 + } withStubResponse:^OHHTTPStubsResponse *(NSURLRequest *request) {
  668 + // Construct a fake error object that will be categorized for reconnecting the session. Note this error is only for non-batched requests.
  669 + // If there is a test failure, you should verify the requests.count == 1 and debug that if it's not; otherwise this error response will likely cause
  670 + // an unrelated error to be surfaced. For example, the session init above set the permissionsRefreshDate to [NSDate date]. If it had not,
  671 + // there could be piggy-backed permissions request which would then expect a batch response. So, this test doubles to verify there was no
  672 + // piggybacked request when the permissionRefreshDate is set.
  673 + NSData *data = [@"{\"error\": {\"message\": \"expired token\",\"code\": 190,\"error_subcode\": 463}}" dataUsingEncoding:NSUTF8StringEncoding];
  674 +
  675 + requestCount++;
  676 + return [OHHTTPStubsResponse responseWithData:data
  677 + statusCode:400
  678 + responseTime:0
  679 + headers:nil];
  680 + }];
  681 +
  682 + FBTestBlocker *blocker = [[[FBTestBlocker alloc] init] autorelease];
  683 + FBRequestConnection *connection = [[[FBRequestConnection alloc] init] autorelease];
  684 + FBRequest *request =[[[FBRequest alloc] initWithSession:session graphPath:@"me"] autorelease];
  685 +
  686 + __block int handlerCount = 0;
  687 + [connection addRequest:request completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
  688 + STAssertEquals(0, handlerCount++, @"user handler invoked more than once");
  689 + [blocker signal];
  690 + } ];
  691 + [connection start];
  692 +
  693 + [blocker wait];
  694 +
  695 + STAssertTrue(sessionClosed, @"expected session to be closed");
  696 + // clean up.
  697 + [FBSystemAccountStoreAdapter setSharedInstance:originalAdapter];
  698 +}
  699 +
527 700 @end

0 comments on commit 283b0d0

Please sign in to comment.
Something went wrong with that request. Please try again.