Open GoogleCodeExporter opened 9 years ago
In testing with the DriveSample app, I am not able to reproduce this. The app
is being called back with a 401 status when trying to upload after the token is
revoked.
Can you set a breakpoint at GTLService's handleParsedObjectForFetcher: method?
That is called after the upload attempt with the fetcher responsible for
uploading the data. If that method is hit, step through that method to see if
the fetcher contains an error. If it is not hit, try putting a breakpoint at
GTLService's objectFetcher:finishedWithData:error: method.
Original comment by grobb...@google.com
on 12 Jul 2012 at 1:39
They all not got hit.
I try to do something in the GTMHTTPFetcher's
invokeFetchCallbacksWithData:error method
In the #if NS_BLOCKS_AVAILABLE block there is
if(completionBlock) {
completionBlock(data,error);
}
I added:
void (^block)(id service,id obj,NError *) = [self
propertyForKey:@"_completionHandler"];
if (block)
{
block(nil,data,error);
}
And this will make the callback get called.(When the token is invalid)
But if the token is valid, this will make the callback get called twice, so
this might a bad fix.
By the way, my code is here, hope this will help:
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"22222"
ofType:@"pdf"];
NSFileHandle *fileHandle = [NSFileHandle
fileHandleForReadingAtPath:filePath];
if (fileHandle) {
GTLServiceDrive *service = [[GTLServiceDrive alloc] init];
service.authorizer = [GTMOAuth2ViewControllerTouch
authForGoogleFromKeychainForName:kGoogleAPIKeychainItem
clientID:kGoogleAPIClientID clientSecret:kGoogleAPIClientSecret];
NSString *mimeType = @"application/pdf";
GTLUploadParameters *uploadParameters =
[GTLUploadParameters uploadParametersWithFileHandle:fileHandle
MIMEType:mimeType];
GTLDriveFile *newFile = [GTLDriveFile object];
newFile.title = [filePath lastPathComponent];
GTLQueryDrive *query = [GTLQueryDrive
queryForFilesInsertWithObject:newFile
uploadParameters:uploadParameters];
[service executeQuery:query
completionHandler:^(GTLServiceTicket *ticket,id obj,NSError *error)
{
if (error) {
if ( [[error.userInfo objectForKey:@"error"]
isEqualToString:@"invalid_grant"]) {
NSLog(@"token invalid");
}
NSLog(@"GDoc failed error:%@",error);
}
else
{
}
}];
}
Original comment by snsdev.i...@gmail.com
on 12 Jul 2012 at 1:56
Your response confuses me. The fetcher's invokeFetchCallbacksWithData:error: is
called often. When it is called AND its finishedSel_ ivar has the selector
"objectFetcher:finishedWithData:error:", the data parameter should contain a
JSON string with the auth error, and the error parameter should be nil.
Please turn on the fetcher's http logging and look at the logs of the upload
fetches, both for the successful upload and for the failure.
http://code.google.com/p/gtm-http-fetcher/wiki/GTMHTTPFetcherIntroduction#HTTP_L
ogging
Original comment by grobb...@google.com
on 12 Jul 2012 at 2:13
I think it's might be some issue in the error block callback implementation.
Because when the token is not valid, the method you mentioned like
objectFetcher:finishedWithData:error: just doesn't get called at all.
The delegate and selector way may be ok, but the block callback is not. Have
you tried the block based API?
Original comment by snsdev.i...@gmail.com
on 12 Jul 2012 at 3:37
My test case is the DriveSample app, which does use block callbacks.
But the kind of callback provided by the app is unrelated to the callbacks
internal to the library. Uploading always uses selector callbacks internally,
since it works even when compiling without blocks supported. Only the final
callback to the app can ever be done with a block.
You'll need to look at the http logs to determine what the uploading fetches
are returning from the server.
Original comment by grobb...@google.com
on 12 Jul 2012 at 4:25
Here's the log:
First is the log when the token is valid and upload successed and the callback
is called.
valid:
2012-07-12 06:11:23 +0000 refresh token for accounts.google.com
request/response log
request: POST https://accounts.google.com/o/oauth2/token
headers: 2
data: 175 bytes, application/x-www-form-urlencoded
response: status 200
headers: 10
data: 679 bytes, application/json
2012-07-12 06:11:24 +0000 drive.files.insert
request/response log
request: POST https://www.googleapis.com/upload/rpc?uploadType=resumable&prett
yPrint=false
headers: 7 authorized
data: 122 bytes, application/json-rpc; charset=utf-8
response: status 200
headers: 8
data: 0 bytes, text/html
2012-07-12 06:11:26 +0000 drive.files.insert (bytes 0-24906/24907)
request/response log
request: PUT https://www.googleapis.com/upload/rpc?uploadType=resumable&pretty
Print=false&upload_id=AEnB2Uof8orscKyQ0cFCYja2ZIl3PP86NNtkS76hDt9jc-F9R3eJZuHoHc
8hNElaqy5D63xyhrKmY0b9ABH3BgX7drRYoceykg
headers: 4
data: 24907 bytes, application/pdf
response: status 200
headers: 7
data: 1309 bytes, application/json
Now is the invalid token's log.(I revoke the access in
Google->Account->Security->Authorizing applications and sites page), and the
callback is not called.
invalid:
2012-07-12 06:12:53 +0000 refresh token for accounts.google.com
request/response log
request: POST https://accounts.google.com/o/oauth2/token
headers: 2
data: 175 bytes, application/x-www-form-urlencoded
response: status 400 ⚑
headers: 10
data: 31 bytes, application/json
Original comment by snsdev.i...@gmail.com
on 12 Jul 2012 at 6:18
You will have to single-step through the library when the fetch fails to
determine what callback is not being invoked. Try setting breakpoints at these
callback methods, as they are called in order when the refresh fetch returns a
400:
GTMOAuth2Authentication's tokenFetcher:finishedWithData:error:
GTMHTTPFetcher's authorizer:request:finishedWithError:
GTLService's objectFetcher:finishedWithData:error:
Original comment by grobb...@google.com
on 17 Jul 2012 at 7:55
[deleted comment]
I tried to set 3 breakpoints for that 3 point.
When getting a 400
1 GTMOAuth2Authentication's tokenFetcher:finishedWithData:error:
is get called and follow that
2 GTMOAuth2Authentication's tokenFetcher:finishedWithData:error:
is get called which is good. In this method ,it has error, so it calls [self
failToBeginFetchWithError:error]
And in failToBeginFetchWithError: it calls [self
invokeFetchCallbackWithData:nil error:error]
And in invokeFetchCallbackWithData:error it does 2 things.
(1) [self invokeFetchCallback:finishedSel_ target:delegate_ data:data
error:error]
the delegate_ is a GTLService instance but the finishSel_ is nil.(Which I think
is good because the callback is a block not a SEL)
(2)
#if NS_BLOCKS_AVAILABLE
if(completionBlock_)
{
completionBlock_(data,error);
}
#endif
the completionBlock_ is also nil! And the GTLService's
objectFetcher:finishedWithData:error: is not get called!
I found that when the GTMHTTPFetcher is created with block, the callback block
is set by using setProperty:forKey: when a key named @"_completionHandler",
it's ivar completionBlock_ is not set at the first time.
That why I did something in "Comment 2".(By the way, the GTLService's callback
block takes 3 arguments, so the "completionBlock_(data,error);" is wrong, even
if the completionBlock_ is not nil).
Hope these information will help you find the bug.
Original comment by snsdev.i...@gmail.com
on 18 Jul 2012 at 1:54
no response anymore?
Original comment by snsdev.i...@gmail.com
on 26 Jul 2012 at 1:08
Hey?
Original comment by snsdev.i...@gmail.com
on 2 Aug 2012 at 1:00
I haven't had time to try again to reproduce this problem.
When you're looking at the code, remember that the library does not use block
completion handlers internally, even if the app supplied one (since the library
can run on systems without block support.) So seeing completion blocks set to
nil internally is normal; blocks are present only at the external APIs, but
selectors are always used by the library for internal calls to other parts of
the library.
Original comment by grobb...@google.com
on 2 Aug 2012 at 1:32
FWIW I am experiencing a similar problem where the refresh token is not deemed
valid during an upload, and a 400 error "invalid_grant" is logged to the
console, yet the callback (with the relevant error) never occurs.
I found this comment in GTMHTTPUploadFetcher suggesting that the finish
selector is essentially being discarded, because connectionDidFinishLoading has
been overridden -- however, in this type of error, -connectionDidFinishLoading
is never called either, so the error is never sent to anyone as a callback. See
the NULL parameter:
> // we don't need a finish selector since we're overriding
> // -connectionDidFinishLoading
> return [super beginFetchWithDelegate:delegate didFinishSelector:NULL];
When I comment this out and replace with [super beginFetchWithDelegate:delegate
didFinishSelector: finishedSEL], everything starts working and I get the
appropriate error callback. However, I'm afraid this could break something
else...
Original comment by pedmons...@gmail.com
on 16 Nov 2012 at 8:14
Original issue reported on code.google.com by
snsdev.i...@gmail.com
on 11 Jul 2012 at 8:48