Skip to content

Commit

Permalink
Improve FBRequestConnection error handling & iOS 6.0 permission bookk…
Browse files Browse the repository at this point in the history
…eeping

Summary:
Added a feature to FBRequestConnection to inform iOS 6.0 of permission related
failures. Added code to scrumptious to handle the case where a user explicitly
removes permissions.

Test Plan: Test the new flow via the new features in scrumptious

Reviewers: chrisp, clang

Reviewed By: chrisp

CC: gregschechte

Differential Revision: https://phabricator.fb.com/D589964

Task ID: 1778969
  • Loading branch information
onebit committed Oct 2, 2012
1 parent b631537 commit 0b3d28b
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 16 deletions.
38 changes: 27 additions & 11 deletions samples/Scrumptious/scrumptious/SCViewController.m
Expand Up @@ -134,26 +134,42 @@ - (void)postOpenGraphAction {
[self.activityIndicator stopAnimating];
[self.view setUserInteractionEnabled:YES];

NSString *alertText;
if (!error) {
alertText = [NSString stringWithFormat:@"Posted Open Graph action, id: %@",
[result objectForKey:@"id"]];
[[[UIAlertView alloc] initWithTitle:@"Result"
message:[NSString stringWithFormat:@"Posted Open Graph action, id: %@",
[result objectForKey:@"id"]]
delegate:nil
cancelButtonTitle:@"Thanks!"
otherButtonTitles:nil]
show];

// start over
self.selectedMeal = nil;
self.selectedPlace = nil;
self.selectedFriends = nil;
[self updateSelections];
} else {
alertText = [NSString stringWithFormat:@"error: domain = %@, code = %d",
error.domain, error.code];
// do we lack permissions here? If so, the application's policy is to reask for the permissions, and if
// granted, we will recall this method in order to post the action
if ([[error userInfo][FBErrorParsedJSONResponseKey][@"body"][@"error"][@"code"] compare:@200] == NSOrderedSame) {
[FBSession.activeSession reauthorizeWithPublishPermissions:[NSArray arrayWithObject:@"publish_actions"]
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error) {
if (!error) {
// re-call assuming we now have the permission
[self postOpenGraphAction];
}
}];
} else {
[[[UIAlertView alloc] initWithTitle:@"Result"
message:[NSString stringWithFormat:@"error: domain = %@, code = %d",
error.domain, error.code]
delegate:nil
cancelButtonTitle:@"Thanks!"
otherButtonTitles:nil]
show];
}
}
[[[UIAlertView alloc] initWithTitle:@"Result"
message:alertText
delegate:nil
cancelButtonTitle:@"Thanks!"
otherButtonTitles:nil]
show];
}];
}

Expand Down
47 changes: 42 additions & 5 deletions src/FBRequestConnection.m
Expand Up @@ -53,6 +53,7 @@
NSString *const FBNonJSONResponseProperty = @"FACEBOOK_NON_JSON_RESULT";

static const int kRESTAPIAccessTokenErrorCode = 190;
static const int kRESTAPIPermissionErrorCode = 200;
static const int kAPISessionNoLongerActiveErrorCode = 2500;
static const NSTimeInterval kDefaultTimeout = 180.0;
static const int kMaximumBatchSize = 50;
Expand Down Expand Up @@ -1148,8 +1149,16 @@ - (void)completeWithResults:(NSArray *)results
NSDictionary *resultDictionary = (NSDictionary *)result;
body = [FBGraphObject graphObjectWrappingDictionary:[resultDictionary objectForKey:@"body"]];
}

if ([self isInvalidSessionError:itemError

// if we lack permissions, use this as a cue to refresh the
// OS's understanding of current permissions
if ((metadata.request.session.loginType == FBSessionLoginTypeSystemAccount) &&
[self isInsufficientPermissionError:error
resultIndex:error == itemError ? i : 0]) {
[FBSession renewSystemAuthorization];
}

if ([self isInvalidSessionError:itemError
resultIndex:error == itemError ? i : 0]) {
[metadata.request.session closeAndClearTokenInformation:itemError];
if (metadata.request.session.loginType == FBSessionLoginTypeSystemAccount){
Expand Down Expand Up @@ -1274,8 +1283,9 @@ - (NSError *)checkConnectionError:(NSError *)innerError
return result;
}

- (BOOL)isInvalidSessionError:(NSError *)error
resultIndex:(int)index {
- (BOOL)getCodeValueForError:(NSError *)error
resultIndex:(int)index
value:(int *)pvalue {

// does this error have a response? that is an array?
id response = [error.userInfo objectForKey:FBErrorParsedJSONResponseKey];
Expand All @@ -1292,13 +1302,40 @@ - (BOOL)isInvalidSessionError:(NSError *)error
(code = [error objectForKey:@"code"]) && // response[index].body.error.code
[code isKindOfClass:[NSNumber class]]) {
// is it a 190 packaged in the original response, then YES
return [code intValue] == kRESTAPIAccessTokenErrorCode || [code intValue] == kAPISessionNoLongerActiveErrorCode;
if (pvalue) {
*pvalue = [code intValue];
}
return YES;
}
}
// else NO
return NO;
}

- (BOOL)isInsufficientPermissionError:(NSError *)error
resultIndex:(int)index {

int value;
if ([self getCodeValueForError:error
resultIndex:index
value:&value]) {
return value == kRESTAPIPermissionErrorCode;
}
return NO;
}

- (BOOL)isInvalidSessionError:(NSError *)error
resultIndex:(int)index {

int value;
if ([self getCodeValueForError:error
resultIndex:index
value:&value]) {
return value == kRESTAPIAccessTokenErrorCode || value == kAPISessionNoLongerActiveErrorCode;
}
return NO;
}

- (void)registerTokenToOmitFromLog:(NSString *)token
{
if (![[FBSettings loggingBehavior] containsObject:FBLoggingBehaviorAccessTokens]) {
Expand Down

0 comments on commit 0b3d28b

Please sign in to comment.