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. 4 5 #include "google_apis/gaia/google_service_auth_error.h" 6 7 #include <string> 8 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" 15 16 GoogleServiceAuthError::Captcha::Captcha() : image_width(0), image_height(0) { 17 } 18 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) { 24 } 25 26 GoogleServiceAuthError::Captcha::~Captcha() { 27 } 28 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); 36 } 37 38 GoogleServiceAuthError::SecondFactor::SecondFactor() : field_length(0) { 39 } 40 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) { 46 } 47 48 GoogleServiceAuthError::SecondFactor::~SecondFactor() { 49 } 50 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); 57 } 58 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_); 65 } 66 67 GoogleServiceAuthError::GoogleServiceAuthError(State s) 68 : state_(s), 69 network_error_(0) { 70 // If the caller has no idea, then we just set it to a generic failure. 71 if (s == CONNECTION_FAILED) { 72 network_error_ = net::ERR_FAILED; 73 } 74 } 75 76 GoogleServiceAuthError::GoogleServiceAuthError( 77 State state, 78 const std::string& error_message) 79 : state_(state), 80 network_error_(0), 81 error_message_(error_message) { 82 } 83 84 GoogleServiceAuthError::GoogleServiceAuthError(const std::string& error_message) 85 : state_(INVALID_GAIA_CREDENTIALS), 86 network_error_(0), 87 error_message_(error_message) { 88 } 89 90 // static 91 GoogleServiceAuthError 92 GoogleServiceAuthError::FromConnectionError(int error) { 93 return GoogleServiceAuthError(CONNECTION_FAILED, error); 94 } 95 96 // static 97 GoogleServiceAuthError GoogleServiceAuthError::FromClientLoginCaptchaChallenge( 98 const std::string& captcha_token, 99 const GURL& captcha_image_url, 100 const GURL& captcha_unlock_url) { 101 return GoogleServiceAuthError(CAPTCHA_REQUIRED, captcha_token, GURL(), 102 captcha_image_url, captcha_unlock_url, 0, 0); 103 } 104 105 // static 106 GoogleServiceAuthError GoogleServiceAuthError::FromServiceError( 107 const std::string& error_message) { 108 return GoogleServiceAuthError(SERVICE_ERROR, error_message); 109 } 110 111 // static 112 GoogleServiceAuthError GoogleServiceAuthError::FromUnexpectedServiceResponse( 113 const std::string& error_message) { 114 return GoogleServiceAuthError(UNEXPECTED_SERVICE_RESPONSE, error_message); 115 } 116 117 // static 118 GoogleServiceAuthError GoogleServiceAuthError::AuthErrorNone() { 119 return GoogleServiceAuthError(NONE); 120 } 121 122 GoogleServiceAuthError::State GoogleServiceAuthError::state() const { 123 return state_; 124 } 125 126 const GoogleServiceAuthError::Captcha& GoogleServiceAuthError::captcha() const { 127 return captcha_; 128 } 129 130 const GoogleServiceAuthError::SecondFactor& 131 GoogleServiceAuthError::second_factor() const { 132 return second_factor_; 133 } 134 135 int GoogleServiceAuthError::network_error() const { 136 return network_error_; 137 } 138 139 const std::string& GoogleServiceAuthError::token() const { 140 switch (state_) { 141 case CAPTCHA_REQUIRED: 142 return captcha_.token; 143 break; 144 case TWO_FACTOR: 145 return second_factor_.token; 146 break; 147 default: 148 NOTREACHED(); 149 } 150 return base::EmptyString(); 151 } 152 153 const std::string& GoogleServiceAuthError::error_message() const { 154 return error_message_; 155 } 156 157 base::DictionaryValue* GoogleServiceAuthError::ToValue() const { 158 base::DictionaryValue* value = new base::DictionaryValue(); 159 std::string state_str; 160 switch (state_) { 161 #define STATE_CASE(x) case x: state_str = #x; break 162 STATE_CASE(NONE); 163 STATE_CASE(INVALID_GAIA_CREDENTIALS); 164 STATE_CASE(USER_NOT_SIGNED_UP); 165 STATE_CASE(CONNECTION_FAILED); 166 STATE_CASE(CAPTCHA_REQUIRED); 167 STATE_CASE(ACCOUNT_DELETED); 168 STATE_CASE(ACCOUNT_DISABLED); 169 STATE_CASE(SERVICE_UNAVAILABLE); 170 STATE_CASE(TWO_FACTOR); 171 STATE_CASE(REQUEST_CANCELED); 172 STATE_CASE(HOSTED_NOT_ALLOWED); 173 STATE_CASE(UNEXPECTED_SERVICE_RESPONSE); 174 STATE_CASE(SERVICE_ERROR); 175 #undef STATE_CASE 176 default: 177 NOTREACHED(); 178 break; 179 } 180 value->SetString("state", state_str); 181 if (!error_message_.empty()) { 182 value->SetString("errorMessage", error_message_); 183 } 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); 202 } 203 return value; 204 } 205 206 std::string GoogleServiceAuthError::ToString() const { 207 switch (state_) { 208 case NONE: 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."; 225 case TWO_FACTOR: 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()); 235 case SERVICE_ERROR: 236 return base::StringPrintf("Service responded with error: '%s'", 237 error_message_.c_str()); 238 default: 239 NOTREACHED(); 240 return std::string(); 241 } 242 } 243 244 GoogleServiceAuthError::GoogleServiceAuthError(State s, int error) 245 : state_(s), 246 network_error_(error) { 247 } 248 249 GoogleServiceAuthError::GoogleServiceAuthError( 250 State s, 251 const std::string& captcha_token, 252 const GURL& captcha_audio_url, 253 const GURL& captcha_image_url, 254 const GURL& captcha_unlock_url, 255 int image_width, 256 int image_height) 257 : state_(s), 258 captcha_(captcha_token, captcha_audio_url, captcha_image_url, 259 captcha_unlock_url, image_width, image_height), 260 network_error_(0) { 261 } 262 263 GoogleServiceAuthError::GoogleServiceAuthError( 264 State s, 265 const std::string& captcha_token, 266 const std::string& prompt_text, 267 const std::string& alternate_text, 268 int field_length) 269 : state_(s), 270 second_factor_(captcha_token, prompt_text, alternate_text, field_length), 271 network_error_(0) { 272 } 273