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_revocation_fetcher.h"
11 #include "base/json/json_reader.h"
12 #include "base/string_util.h"
13 #include "base/stringprintf.h"
14 #include "base/values.h"
15 #include "google_apis/gaia/gaia_urls.h"
16 #include "google_apis/gaia/google_service_auth_error.h"
17 #include "net/base/escape.h"
18 #include "net/base/load_flags.h"
19 #include "net/http/http_status_code.h"
20 #include "net/url_request/url_fetcher.h"
21 #include "net/url_request/url_request_context_getter.h"
22 #include "net/url_request/url_request_status.h"
24 using net::ResponseCookies
;
25 using net::URLFetcher
;
26 using net::URLFetcherDelegate
;
27 using net::URLRequestContextGetter
;
28 using net::URLRequestStatus
;
31 static const char kOAuth2RevokeTokenURL
[] =
32 "https://www.googleapis.com/oauth2/v2/RevokeToken";
34 static const char kAuthorizationHeaderFormat
[] =
35 "Authorization: Bearer %s";
37 static const char kRevocationBodyFormat
[] =
38 "client_id=%s&origin=%s";
40 static GoogleServiceAuthError
CreateAuthError(URLRequestStatus status
) {
41 CHECK(!status
.is_success());
42 if (status
.status() == URLRequestStatus::CANCELED
) {
43 return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED
);
45 DLOG(WARNING
) << "Could not reach Google Accounts servers: errno "
47 return GoogleServiceAuthError::FromConnectionError(status
.error());
51 static URLFetcher
* CreateFetcher(URLRequestContextGetter
* getter
,
53 const std::string
& header
,
54 const std::string
& body
,
55 URLFetcherDelegate
* delegate
) {
56 bool empty_body
= body
.empty();
57 URLFetcher
* result
= net::URLFetcher::Create(
59 empty_body
? URLFetcher::GET
: URLFetcher::POST
,
62 result
->SetRequestContext(getter
);
63 result
->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES
|
64 net::LOAD_DO_NOT_SAVE_COOKIES
);
66 result
->SetExtraRequestHeaders(header
);
69 result
->SetUploadData("application/x-www-form-urlencoded", body
);
75 OAuth2RevocationFetcher::OAuth2RevocationFetcher(
76 OAuth2RevocationConsumer
* consumer
,
77 URLRequestContextGetter
* getter
)
78 : consumer_(consumer
),
82 OAuth2RevocationFetcher::~OAuth2RevocationFetcher() { }
84 void OAuth2RevocationFetcher::CancelRequest() {
88 void OAuth2RevocationFetcher::Start(const std::string
& access_token
,
89 const std::string
& client_id
,
90 const std::string
& origin
) {
91 access_token_
= access_token
;
92 client_id_
= client_id
;
97 void OAuth2RevocationFetcher::StartRevocation() {
98 CHECK_EQ(INITIAL
, state_
);
99 state_
= REVOCATION_STARTED
;
100 fetcher_
.reset(CreateFetcher(
103 MakeRevocationHeader(access_token_
),
104 MakeRevocationBody(client_id_
, origin_
),
106 fetcher_
->Start(); // OnURLFetchComplete will be called.
109 void OAuth2RevocationFetcher::EndRevocation(const net::URLFetcher
* source
) {
110 CHECK_EQ(REVOCATION_STARTED
, state_
);
111 state_
= REVOCATION_DONE
;
113 URLRequestStatus status
= source
->GetStatus();
114 if (!status
.is_success()) {
115 OnRevocationFailure(CreateAuthError(status
));
119 if (source
->GetResponseCode() != net::HTTP_NO_CONTENT
) {
120 OnRevocationFailure(GoogleServiceAuthError(
121 GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS
));
125 OnRevocationSuccess();
128 void OAuth2RevocationFetcher::OnRevocationSuccess() {
129 consumer_
->OnRevocationSuccess();
132 void OAuth2RevocationFetcher::OnRevocationFailure(
133 const GoogleServiceAuthError
& error
) {
134 state_
= ERROR_STATE
;
135 consumer_
->OnRevocationFailure(error
);
138 void OAuth2RevocationFetcher::OnURLFetchComplete(
139 const net::URLFetcher
* source
) {
141 EndRevocation(source
);
145 GURL
OAuth2RevocationFetcher::MakeRevocationUrl() {
146 return GURL(kOAuth2RevokeTokenURL
);
150 std::string
OAuth2RevocationFetcher::MakeRevocationHeader(
151 const std::string
& access_token
) {
152 return StringPrintf(kAuthorizationHeaderFormat
, access_token
.c_str());
156 std::string
OAuth2RevocationFetcher::MakeRevocationBody(
157 const std::string
& client_id
,
158 const std::string
& origin
) {
159 std::string enc_client_id
= net::EscapeUrlEncodedData(client_id
, true);
160 std::string enc_origin
= net::EscapeUrlEncodedData(origin
, true);
162 kRevocationBodyFormat
,
163 enc_client_id
.c_str(),