1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "google_apis/gaia/oauth2_api_call_flow.h"
10 #include "base/basictypes.h"
11 #include "base/strings/stringprintf.h"
12 #include "google_apis/gaia/gaia_urls.h"
13 #include "net/base/escape.h"
14 #include "net/base/load_flags.h"
15 #include "net/http/http_status_code.h"
16 #include "net/url_request/url_request_context_getter.h"
17 #include "net/url_request/url_request_status.h"
19 using net::ResponseCookies
;
20 using net::URLFetcher
;
21 using net::URLFetcherDelegate
;
22 using net::URLRequestContextGetter
;
23 using net::URLRequestStatus
;
26 static const char kAuthorizationHeaderFormat
[] =
27 "Authorization: Bearer %s";
29 static std::string
MakeAuthorizationHeader(const std::string
& auth_token
) {
30 return base::StringPrintf(kAuthorizationHeaderFormat
, auth_token
.c_str());
34 OAuth2ApiCallFlow::OAuth2ApiCallFlow() : state_(INITIAL
) {
37 OAuth2ApiCallFlow::~OAuth2ApiCallFlow() {}
39 void OAuth2ApiCallFlow::Start(net::URLRequestContextGetter
* context
,
40 const std::string
& access_token
) {
41 CHECK(state_
== INITIAL
);
42 state_
= API_CALL_STARTED
;
44 url_fetcher_
= CreateURLFetcher(context
, access_token
);
45 url_fetcher_
->Start(); // OnURLFetchComplete will be called.
48 void OAuth2ApiCallFlow::EndApiCall(const net::URLFetcher
* source
) {
49 CHECK_EQ(API_CALL_STARTED
, state_
);
51 URLRequestStatus status
= source
->GetStatus();
52 int status_code
= source
->GetResponseCode();
53 if (!status
.is_success() ||
54 (status_code
!= net::HTTP_OK
&& status_code
!= net::HTTP_NO_CONTENT
)) {
56 ProcessApiCallFailure(source
);
58 state_
= API_CALL_DONE
;
59 ProcessApiCallSuccess(source
);
63 std::string
OAuth2ApiCallFlow::CreateApiCallBodyContentType() {
64 return "application/x-www-form-urlencoded";
67 net::URLFetcher::RequestType
OAuth2ApiCallFlow::GetRequestTypeForBody(
68 const std::string
& body
) {
69 return body
.empty() ? URLFetcher::GET
: URLFetcher::POST
;
72 void OAuth2ApiCallFlow::OnURLFetchComplete(const net::URLFetcher
* source
) {
74 CHECK_EQ(API_CALL_STARTED
, state_
);
78 scoped_ptr
<URLFetcher
> OAuth2ApiCallFlow::CreateURLFetcher(
79 net::URLRequestContextGetter
* context
,
80 const std::string
& access_token
) {
81 std::string body
= CreateApiCallBody();
82 net::URLFetcher::RequestType request_type
= GetRequestTypeForBody(body
);
83 scoped_ptr
<URLFetcher
> result
=
84 net::URLFetcher::Create(0, CreateApiCallUrl(), request_type
, this);
86 result
->SetRequestContext(context
);
87 result
->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES
|
88 net::LOAD_DO_NOT_SAVE_COOKIES
);
89 result
->AddExtraRequestHeader(MakeAuthorizationHeader(access_token
));
90 // Fetchers are sometimes cancelled because a network change was detected,
91 // especially at startup and after sign-in on ChromeOS. Retrying once should
92 // be enough in those cases; let the fetcher retry up to 3 times just in case.
93 // http://crbug.com/163710
94 result
->SetAutomaticallyRetryOnNetworkChanges(3);
96 // Even if the the body is empty, we still set the Content-Type because an
97 // empty string may be a meaningful value. For example, a Protocol Buffer
98 // message with only default values will be serialized as an empty string.
99 if (request_type
!= net::URLFetcher::GET
)
100 result
->SetUploadData(CreateApiCallBodyContentType(), body
);