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/google_service_auth_error.h"
9 #include "base/json/json_reader.h"
10 #include "base/logging.h"
11 #include "base/strings/string_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/values.h"
14 #include "net/base/net_errors.h"
16 GoogleServiceAuthError::Captcha::Captcha() : image_width(0), image_height(0) {
19 GoogleServiceAuthError::Captcha::Captcha(
20 const std::string
& token
, const GURL
& audio
, const GURL
& img
,
21 const GURL
& unlock
, int width
, int height
)
22 : token(token
), audio_url(audio
), image_url(img
), unlock_url(unlock
),
23 image_width(width
), image_height(height
) {
26 GoogleServiceAuthError::Captcha::~Captcha() {
29 bool GoogleServiceAuthError::Captcha::operator==(const Captcha
& b
) const {
30 return (token
== b
.token
&&
31 audio_url
== b
.audio_url
&&
32 image_url
== b
.image_url
&&
33 unlock_url
== b
.unlock_url
&&
34 image_width
== b
.image_width
&&
35 image_height
== b
.image_height
);
38 GoogleServiceAuthError::SecondFactor::SecondFactor() : field_length(0) {
41 GoogleServiceAuthError::SecondFactor::SecondFactor(
42 const std::string
& token
, const std::string
& prompt
,
43 const std::string
& alternate
, int length
)
44 : token(token
), prompt_text(prompt
), alternate_text(alternate
),
45 field_length(length
) {
48 GoogleServiceAuthError::SecondFactor::~SecondFactor() {
51 bool GoogleServiceAuthError::SecondFactor::operator==(
52 const SecondFactor
& b
) const {
53 return (token
== b
.token
&&
54 prompt_text
== b
.prompt_text
&&
55 alternate_text
== b
.alternate_text
&&
56 field_length
== b
.field_length
);
59 bool GoogleServiceAuthError::operator==(
60 const GoogleServiceAuthError
& b
) const {
61 return (state_
== b
.state_
&&
62 network_error_
== b
.network_error_
&&
63 captcha_
== b
.captcha_
&&
64 second_factor_
== b
.second_factor_
);
67 bool GoogleServiceAuthError::operator!=(
68 const GoogleServiceAuthError
& b
) const {
72 GoogleServiceAuthError::GoogleServiceAuthError(State s
)
75 // If the caller has no idea, then we just set it to a generic failure.
76 if (s
== CONNECTION_FAILED
) {
77 network_error_
= net::ERR_FAILED
;
81 GoogleServiceAuthError::GoogleServiceAuthError(
83 const std::string
& error_message
)
86 error_message_(error_message
) {
90 GoogleServiceAuthError
91 GoogleServiceAuthError::FromConnectionError(int error
) {
92 return GoogleServiceAuthError(CONNECTION_FAILED
, error
);
96 GoogleServiceAuthError
GoogleServiceAuthError::FromClientLoginCaptchaChallenge(
97 const std::string
& captcha_token
,
98 const GURL
& captcha_image_url
,
99 const GURL
& captcha_unlock_url
) {
100 return GoogleServiceAuthError(CAPTCHA_REQUIRED
, captcha_token
, GURL(),
101 captcha_image_url
, captcha_unlock_url
, 0, 0);
105 GoogleServiceAuthError
GoogleServiceAuthError::FromServiceError(
106 const std::string
& error_message
) {
107 return GoogleServiceAuthError(SERVICE_ERROR
, error_message
);
111 GoogleServiceAuthError
GoogleServiceAuthError::FromUnexpectedServiceResponse(
112 const std::string
& error_message
) {
113 return GoogleServiceAuthError(UNEXPECTED_SERVICE_RESPONSE
, error_message
);
117 GoogleServiceAuthError
GoogleServiceAuthError::AuthErrorNone() {
118 return GoogleServiceAuthError(NONE
);
121 GoogleServiceAuthError::State
GoogleServiceAuthError::state() const {
125 const GoogleServiceAuthError::Captcha
& GoogleServiceAuthError::captcha() const {
129 const GoogleServiceAuthError::SecondFactor
&
130 GoogleServiceAuthError::second_factor() const {
131 return second_factor_
;
134 int GoogleServiceAuthError::network_error() const {
135 return network_error_
;
138 const std::string
& GoogleServiceAuthError::token() const {
140 case CAPTCHA_REQUIRED
:
141 return captcha_
.token
;
144 return second_factor_
.token
;
149 return base::EmptyString();
152 const std::string
& GoogleServiceAuthError::error_message() const {
153 return error_message_
;
156 base::DictionaryValue
* GoogleServiceAuthError::ToValue() const {
157 base::DictionaryValue
* value
= new base::DictionaryValue();
158 std::string state_str
;
160 #define STATE_CASE(x) case x: state_str = #x; break
162 STATE_CASE(INVALID_GAIA_CREDENTIALS
);
163 STATE_CASE(USER_NOT_SIGNED_UP
);
164 STATE_CASE(CONNECTION_FAILED
);
165 STATE_CASE(CAPTCHA_REQUIRED
);
166 STATE_CASE(ACCOUNT_DELETED
);
167 STATE_CASE(ACCOUNT_DISABLED
);
168 STATE_CASE(SERVICE_UNAVAILABLE
);
169 STATE_CASE(TWO_FACTOR
);
170 STATE_CASE(REQUEST_CANCELED
);
171 STATE_CASE(HOSTED_NOT_ALLOWED
);
172 STATE_CASE(UNEXPECTED_SERVICE_RESPONSE
);
173 STATE_CASE(SERVICE_ERROR
);
174 STATE_CASE(WEB_LOGIN_REQUIRED
);
180 value
->SetString("state", state_str
);
181 if (!error_message_
.empty()) {
182 value
->SetString("errorMessage", error_message_
);
184 if (state_
== CAPTCHA_REQUIRED
) {
185 base::DictionaryValue
* captcha_value
= new base::DictionaryValue();
186 value
->Set("captcha", captcha_value
);
187 captcha_value
->SetString("token", captcha_
.token
);
188 captcha_value
->SetString("audioUrl", captcha_
.audio_url
.spec());
189 captcha_value
->SetString("imageUrl", captcha_
.image_url
.spec());
190 captcha_value
->SetString("unlockUrl", captcha_
.unlock_url
.spec());
191 captcha_value
->SetInteger("imageWidth", captcha_
.image_width
);
192 captcha_value
->SetInteger("imageHeight", captcha_
.image_height
);
193 } else if (state_
== CONNECTION_FAILED
) {
194 value
->SetString("networkError", net::ErrorToString(network_error_
));
195 } else if (state_
== TWO_FACTOR
) {
196 base::DictionaryValue
* two_factor_value
= new base::DictionaryValue();
197 value
->Set("two_factor", two_factor_value
);
198 two_factor_value
->SetString("token", second_factor_
.token
);
199 two_factor_value
->SetString("promptText", second_factor_
.prompt_text
);
200 two_factor_value
->SetString("alternateText", second_factor_
.alternate_text
);
201 two_factor_value
->SetInteger("fieldLength", second_factor_
.field_length
);
206 std::string
GoogleServiceAuthError::ToString() const {
209 return std::string();
210 case INVALID_GAIA_CREDENTIALS
:
211 return "Invalid credentials.";
212 case USER_NOT_SIGNED_UP
:
213 return "Not authorized.";
214 case CONNECTION_FAILED
:
215 return base::StringPrintf("Connection failed (%d).", network_error_
);
216 case CAPTCHA_REQUIRED
:
217 return base::StringPrintf("CAPTCHA required (%s).",
218 captcha_
.token
.c_str());
219 case ACCOUNT_DELETED
:
220 return "Account deleted.";
221 case ACCOUNT_DISABLED
:
222 return "Account disabled.";
223 case SERVICE_UNAVAILABLE
:
224 return "Service unavailable; try again later.";
226 return base::StringPrintf("2-step verification required (%s).",
227 second_factor_
.token
.c_str());
228 case REQUEST_CANCELED
:
229 return "Request canceled.";
230 case HOSTED_NOT_ALLOWED
:
231 return "Google account required.";
232 case UNEXPECTED_SERVICE_RESPONSE
:
233 return base::StringPrintf("Unexpected service response (%s)",
234 error_message_
.c_str());
236 return base::StringPrintf("Service responded with error: '%s'",
237 error_message_
.c_str());
238 case WEB_LOGIN_REQUIRED
:
239 return "Less secure apps may not authenticate with this account. "
241 "https://www.google.com/settings/security/lesssecureapps";
244 return std::string();
248 bool GoogleServiceAuthError::IsPersistentError() const {
249 if (state_
== GoogleServiceAuthError::NONE
) return false;
250 return !IsTransientError();
253 bool GoogleServiceAuthError::IsTransientError() const {
255 // These are failures that are likely to succeed if tried again.
256 case GoogleServiceAuthError::CONNECTION_FAILED
:
257 case GoogleServiceAuthError::SERVICE_UNAVAILABLE
:
258 case GoogleServiceAuthError::REQUEST_CANCELED
:
260 // Everything else will have the same result.
266 GoogleServiceAuthError::GoogleServiceAuthError(State s
, int error
)
268 network_error_(error
) {
271 GoogleServiceAuthError::GoogleServiceAuthError(
273 const std::string
& captcha_token
,
274 const GURL
& captcha_audio_url
,
275 const GURL
& captcha_image_url
,
276 const GURL
& captcha_unlock_url
,
280 captcha_(captcha_token
, captcha_audio_url
, captcha_image_url
,
281 captcha_unlock_url
, image_width
, image_height
),