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 // static 85 GoogleServiceAuthError 86 GoogleServiceAuthError::FromConnectionError(int error) { 87 return GoogleServiceAuthError(CONNECTION_FAILED, error); 88 } 89 90 // static 91 GoogleServiceAuthError GoogleServiceAuthError::FromClientLoginCaptchaChallenge( 92 const std::string& captcha_token, 93 const GURL& captcha_image_url, 94 const GURL& captcha_unlock_url) { 95 return GoogleServiceAuthError(CAPTCHA_REQUIRED, captcha_token, GURL(), 96 captcha_image_url, captcha_unlock_url, 0, 0); 97 } 98 99 // static 100 GoogleServiceAuthError GoogleServiceAuthError::FromServiceError( 101 const std::string& error_message) { 102 return GoogleServiceAuthError(SERVICE_ERROR, error_message); 103 } 104 105 // static 106 GoogleServiceAuthError GoogleServiceAuthError::FromUnexpectedServiceResponse( 107 const std::string& error_message) { 108 return GoogleServiceAuthError(UNEXPECTED_SERVICE_RESPONSE, error_message); 109 } 110 111 // static 112 GoogleServiceAuthError GoogleServiceAuthError::AuthErrorNone() { 113 return GoogleServiceAuthError(NONE); 114 } 115 116 GoogleServiceAuthError::State GoogleServiceAuthError::state() const { 117 return state_; 118 } 119 120 const GoogleServiceAuthError::Captcha& GoogleServiceAuthError::captcha() const { 121 return captcha_; 122 } 123 124 const GoogleServiceAuthError::SecondFactor& 125 GoogleServiceAuthError::second_factor() const { 126 return second_factor_; 127 } 128 129 int GoogleServiceAuthError::network_error() const { 130 return network_error_; 131 } 132 133 const std::string& GoogleServiceAuthError::token() const { 134 switch (state_) { 135 case CAPTCHA_REQUIRED: 136 return captcha_.token; 137 break; 138 case TWO_FACTOR: 139 return second_factor_.token; 140 break; 141 default: 142 NOTREACHED(); 143 } 144 return base::EmptyString(); 145 } 146 147 const std::string& GoogleServiceAuthError::error_message() const { 148 return error_message_; 149 } 150 151 base::DictionaryValue* GoogleServiceAuthError::ToValue() const { 152 base::DictionaryValue* value = new base::DictionaryValue(); 153 std::string state_str; 154 switch (state_) { 155 #define STATE_CASE(x) case x: state_str = #x; break 156 STATE_CASE(NONE); 157 STATE_CASE(INVALID_GAIA_CREDENTIALS); 158 STATE_CASE(USER_NOT_SIGNED_UP); 159 STATE_CASE(CONNECTION_FAILED); 160 STATE_CASE(CAPTCHA_REQUIRED); 161 STATE_CASE(ACCOUNT_DELETED); 162 STATE_CASE(ACCOUNT_DISABLED); 163 STATE_CASE(SERVICE_UNAVAILABLE); 164 STATE_CASE(TWO_FACTOR); 165 STATE_CASE(REQUEST_CANCELED); 166 STATE_CASE(HOSTED_NOT_ALLOWED); 167 STATE_CASE(UNEXPECTED_SERVICE_RESPONSE); 168 STATE_CASE(SERVICE_ERROR); 169 #undef STATE_CASE 170 default: 171 NOTREACHED(); 172 break; 173 } 174 value->SetString("state", state_str); 175 if (!error_message_.empty()) { 176 value->SetString("errorMessage", error_message_); 177 } 178 if (state_ == CAPTCHA_REQUIRED) { 179 base::DictionaryValue* captcha_value = new base::DictionaryValue(); 180 value->Set("captcha", captcha_value); 181 captcha_value->SetString("token", captcha_.token); 182 captcha_value->SetString("audioUrl", captcha_.audio_url.spec()); 183 captcha_value->SetString("imageUrl", captcha_.image_url.spec()); 184 captcha_value->SetString("unlockUrl", captcha_.unlock_url.spec()); 185 captcha_value->SetInteger("imageWidth", captcha_.image_width); 186 captcha_value->SetInteger("imageHeight", captcha_.image_height); 187 } else if (state_ == CONNECTION_FAILED) { 188 value->SetString("networkError", net::ErrorToString(network_error_)); 189 } else if (state_ == TWO_FACTOR) { 190 base::DictionaryValue* two_factor_value = new base::DictionaryValue(); 191 value->Set("two_factor", two_factor_value); 192 two_factor_value->SetString("token", second_factor_.token); 193 two_factor_value->SetString("promptText", second_factor_.prompt_text); 194 two_factor_value->SetString("alternateText", second_factor_.alternate_text); 195 two_factor_value->SetInteger("fieldLength", second_factor_.field_length); 196 } 197 return value; 198 } 199 200 std::string GoogleServiceAuthError::ToString() const { 201 switch (state_) { 202 case NONE: 203 return std::string(); 204 case INVALID_GAIA_CREDENTIALS: 205 return "Invalid credentials."; 206 case USER_NOT_SIGNED_UP: 207 return "Not authorized."; 208 case CONNECTION_FAILED: 209 return base::StringPrintf("Connection failed (%d).", network_error_); 210 case CAPTCHA_REQUIRED: 211 return base::StringPrintf("CAPTCHA required (%s).", 212 captcha_.token.c_str()); 213 case ACCOUNT_DELETED: 214 return "Account deleted."; 215 case ACCOUNT_DISABLED: 216 return "Account disabled."; 217 case SERVICE_UNAVAILABLE: 218 return "Service unavailable; try again later."; 219 case TWO_FACTOR: 220 return base::StringPrintf("2-step verification required (%s).", 221 second_factor_.token.c_str()); 222 case REQUEST_CANCELED: 223 return "Request canceled."; 224 case HOSTED_NOT_ALLOWED: 225 return "Google account required."; 226 case UNEXPECTED_SERVICE_RESPONSE: 227 return base::StringPrintf("Unexpected service response (%s)", 228 error_message_.c_str()); 229 case SERVICE_ERROR: 230 return base::StringPrintf("Service responded with error: '%s'", 231 error_message_.c_str()); 232 default: 233 NOTREACHED(); 234 return std::string(); 235 } 236 } 237 238 GoogleServiceAuthError::GoogleServiceAuthError(State s, int error) 239 : state_(s), 240 network_error_(error) { 241 } 242 243 GoogleServiceAuthError::GoogleServiceAuthError( 244 State s, 245 const std::string& captcha_token, 246 const GURL& captcha_audio_url, 247 const GURL& captcha_image_url, 248 const GURL& captcha_unlock_url, 249 int image_width, 250 int image_height) 251 : state_(s), 252 captcha_(captcha_token, captcha_audio_url, captcha_image_url, 253 captcha_unlock_url, image_width, image_height), 254 network_error_(0) { 255 } 256