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 "chrome/service/cloud_print/cloud_print_auth.h"
8 #include "base/metrics/histogram.h"
9 #include "base/strings/string_util.h"
10 #include "chrome/common/cloud_print/cloud_print_constants.h"
11 #include "chrome/common/cloud_print/cloud_print_helpers.h"
12 #include "chrome/service/cloud_print/cloud_print_token_store.h"
13 #include "chrome/service/net/service_url_request_context_getter.h"
14 #include "chrome/service/service_process.h"
15 #include "google_apis/gaia/gaia_urls.h"
17 namespace cloud_print
{
21 enum CloudPrintAuthEvent
{
22 AUTH_EVENT_ROBO_CREATE
,
23 AUTH_EVENT_ROBO_SUCCEEDED
,
24 AUTH_EVENT_ROBO_FAILED
,
25 AUTH_EVENT_ROBO_JSON_ERROR
,
26 AUTH_EVENT_ROBO_AUTH_ERROR
,
27 AUTH_EVENT_AUTH_WITH_TOKEN
,
28 AUTH_EVENT_AUTH_WITH_CODE
,
29 AUTH_EVENT_TOKEN_RESPONSE
,
30 AUTH_EVENT_REFRESH_REQUEST
,
31 AUTH_EVENT_REFRESH_RESPONSE
,
32 AUTH_EVENT_AUTH_ERROR
,
39 CloudPrintAuth::CloudPrintAuth(
41 const GURL
& cloud_print_server_url
,
42 const gaia::OAuthClientInfo
& oauth_client_info
,
43 const std::string
& proxy_id
)
45 oauth_client_info_(oauth_client_info
),
46 cloud_print_server_url_(cloud_print_server_url
),
51 void CloudPrintAuth::AuthenticateWithToken(
52 const std::string
& cloud_print_token
) {
53 VLOG(1) << "CP_AUTH: Authenticating with token";
55 UMA_HISTOGRAM_ENUMERATION("CloudPrint.AuthEvent", AUTH_EVENT_ROBO_CREATE
,
58 client_login_token_
= cloud_print_token
;
60 // We need to get the credentials of the robot here.
61 GURL get_authcode_url
= GetUrlForGetAuthCode(cloud_print_server_url_
,
62 oauth_client_info_
.client_id
,
64 request_
= CloudPrintURLFetcher::Create();
65 request_
->StartGetRequest(CloudPrintURLFetcher::REQUEST_AUTH_CODE
,
66 get_authcode_url
, this,
67 kCloudPrintAuthMaxRetryCount
, std::string());
70 void CloudPrintAuth::AuthenticateWithRobotToken(
71 const std::string
& robot_oauth_refresh_token
,
72 const std::string
& robot_email
) {
73 VLOG(1) << "CP_AUTH: Authenticating with robot token";
75 UMA_HISTOGRAM_ENUMERATION("CloudPrint.AuthEvent", AUTH_EVENT_AUTH_WITH_TOKEN
,
78 robot_email_
= robot_email
;
79 refresh_token_
= robot_oauth_refresh_token
;
83 void CloudPrintAuth::AuthenticateWithRobotAuthCode(
84 const std::string
& robot_oauth_auth_code
,
85 const std::string
& robot_email
) {
86 VLOG(1) << "CP_AUTH: Authenticating with robot auth code";
88 UMA_HISTOGRAM_ENUMERATION("CloudPrint.AuthEvent", AUTH_EVENT_AUTH_WITH_CODE
,
91 robot_email_
= robot_email
;
92 // Now that we have an auth code we need to get the refresh and access tokens.
93 oauth_client_
.reset(new gaia::GaiaOAuthClient(
94 g_service_process
->GetServiceURLRequestContextGetter()));
95 oauth_client_
->GetTokensFromAuthCode(oauth_client_info_
,
96 robot_oauth_auth_code
,
97 kCloudPrintAuthMaxRetryCount
,
101 void CloudPrintAuth::RefreshAccessToken() {
102 UMA_HISTOGRAM_ENUMERATION("CloudPrint.AuthEvent", AUTH_EVENT_REFRESH_REQUEST
,
104 oauth_client_
.reset(new gaia::GaiaOAuthClient(
105 g_service_process
->GetServiceURLRequestContextGetter()));
106 std::vector
<std::string
> empty_scope_list
; // (Use scope from refresh token.)
107 oauth_client_
->RefreshToken(oauth_client_info_
,
110 kCloudPrintAuthMaxRetryCount
,
114 void CloudPrintAuth::OnGetTokensResponse(const std::string
& refresh_token
,
115 const std::string
& access_token
,
116 int expires_in_seconds
) {
117 UMA_HISTOGRAM_ENUMERATION("CloudPrint.AuthEvent", AUTH_EVENT_TOKEN_RESPONSE
,
119 refresh_token_
= refresh_token
;
120 // After saving the refresh token, this is just like having just refreshed
121 // the access token. Just call OnRefreshTokenResponse.
122 OnRefreshTokenResponse(access_token
, expires_in_seconds
);
125 void CloudPrintAuth::OnRefreshTokenResponse(const std::string
& access_token
,
126 int expires_in_seconds
) {
127 UMA_HISTOGRAM_ENUMERATION("CloudPrint.AuthEvent", AUTH_EVENT_REFRESH_RESPONSE
,
129 client_
->OnAuthenticationComplete(access_token
, refresh_token_
,
130 robot_email_
, user_email_
);
132 // Schedule a task to refresh the access token again when it is about to
134 DCHECK(expires_in_seconds
> kTokenRefreshGracePeriodSecs
);
135 base::TimeDelta refresh_delay
= base::TimeDelta::FromSeconds(
136 expires_in_seconds
- kTokenRefreshGracePeriodSecs
);
137 base::MessageLoop::current()->PostDelayedTask(
139 base::Bind(&CloudPrintAuth::RefreshAccessToken
, this),
143 void CloudPrintAuth::OnOAuthError() {
144 UMA_HISTOGRAM_ENUMERATION("CloudPrint.AuthEvent", AUTH_EVENT_AUTH_ERROR
,
146 // Notify client about authentication error.
147 client_
->OnInvalidCredentials();
150 void CloudPrintAuth::OnNetworkError(int response_code
) {
151 UMA_HISTOGRAM_ENUMERATION("CloudPrint.AuthEvent", AUTH_EVENT_NET_ERROR
,
153 // Since we specify infinite retries on network errors, this should never
156 "OnNetworkError invoked when not expected, response code is " <<
160 CloudPrintURLFetcher::ResponseAction
CloudPrintAuth::HandleJSONData(
161 const net::URLFetcher
* source
,
163 base::DictionaryValue
* json_data
,
166 VLOG(1) << "CP_AUTH: Creating robot account failed";
167 UMA_HISTOGRAM_ENUMERATION("CloudPrint.AuthEvent",
168 AUTH_EVENT_ROBO_FAILED
,
170 client_
->OnInvalidCredentials();
171 return CloudPrintURLFetcher::STOP_PROCESSING
;
174 std::string auth_code
;
175 if (!json_data
->GetString(kOAuthCodeValue
, &auth_code
)) {
176 VLOG(1) << "CP_AUTH: Creating robot account returned invalid json response";
177 UMA_HISTOGRAM_ENUMERATION("CloudPrint.AuthEvent",
178 AUTH_EVENT_ROBO_JSON_ERROR
,
180 client_
->OnInvalidCredentials();
181 return CloudPrintURLFetcher::STOP_PROCESSING
;
184 UMA_HISTOGRAM_ENUMERATION("CloudPrint.AuthEvent",
185 AUTH_EVENT_ROBO_SUCCEEDED
,
188 json_data
->GetString(kXMPPJidValue
, &robot_email_
);
189 // Now that we have an auth code we need to get the refresh and access tokens.
190 oauth_client_
.reset(new gaia::GaiaOAuthClient(
191 g_service_process
->GetServiceURLRequestContextGetter()));
192 oauth_client_
->GetTokensFromAuthCode(oauth_client_info_
,
194 kCloudPrintAPIMaxRetryCount
,
197 return CloudPrintURLFetcher::STOP_PROCESSING
;
200 CloudPrintURLFetcher::ResponseAction
CloudPrintAuth::OnRequestAuthError() {
201 VLOG(1) << "CP_AUTH: Creating robot account authentication error";
203 UMA_HISTOGRAM_ENUMERATION("CloudPrint.AuthEvent",
204 AUTH_EVENT_ROBO_AUTH_ERROR
,
207 // Notify client about authentication error.
208 client_
->OnInvalidCredentials();
209 return CloudPrintURLFetcher::STOP_PROCESSING
;
212 std::string
CloudPrintAuth::GetAuthHeader() {
213 DCHECK(!client_login_token_
.empty());
215 header
= "Authorization: GoogleLogin auth=";
216 header
+= client_login_token_
;
220 CloudPrintAuth::~CloudPrintAuth() {}
222 } // namespace cloud_print