summaryrefslogtreecommitdiffstats
path: root/google_apis
diff options
context:
space:
mode:
authorfgorski@chromium.org <fgorski@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-21 03:23:16 +0000
committerfgorski@chromium.org <fgorski@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-06-21 03:23:16 +0000
commitbdbe2b126637d186dbcb049276522411013f04ca (patch)
tree8bc020bbbab0aedcbcdf64be7dd261a00db06fcd /google_apis
parent921d7af9ba4a54a98ba6bb1bd9234613075dff5b (diff)
downloadchromium_src-bdbe2b126637d186dbcb049276522411013f04ca.zip
chromium_src-bdbe2b126637d186dbcb049276522411013f04ca.tar.gz
chromium_src-bdbe2b126637d186dbcb049276522411013f04ca.tar.bz2
* Introducing Service Error and Unexpected Response for better handling of
errors Google Authentication service included in response body. * Adding parsing to the Failure situation in OAuth2MintTokenFlow BUG=121976 Review URL: https://chromiumcodereview.appspot.com/17286013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@207681 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'google_apis')
-rw-r--r--google_apis/gaia/google_service_auth_error.cc34
-rw-r--r--google_apis/gaia/google_service_auth_error.h23
-rw-r--r--google_apis/gaia/oauth2_mint_token_flow.cc58
3 files changed, 96 insertions, 19 deletions
diff --git a/google_apis/gaia/google_service_auth_error.cc b/google_apis/gaia/google_service_auth_error.cc
index fcb7c00..59569c7 100644
--- a/google_apis/gaia/google_service_auth_error.cc
+++ b/google_apis/gaia/google_service_auth_error.cc
@@ -35,7 +35,6 @@ bool GoogleServiceAuthError::Captcha::operator==(const Captcha& b) const {
image_height == b.image_height);
}
-
GoogleServiceAuthError::SecondFactor::SecondFactor() : field_length(0) {
}
@@ -57,7 +56,6 @@ bool GoogleServiceAuthError::SecondFactor::operator==(
field_length == b.field_length);
}
-
bool GoogleServiceAuthError::operator==(
const GoogleServiceAuthError& b) const {
return (state_ == b.state_ &&
@@ -75,6 +73,14 @@ GoogleServiceAuthError::GoogleServiceAuthError(State s)
}
}
+GoogleServiceAuthError::GoogleServiceAuthError(
+ State state,
+ const std::string& error_message)
+ : state_(state),
+ network_error_(0),
+ error_message_(error_message) {
+}
+
GoogleServiceAuthError::GoogleServiceAuthError(const std::string& error_message)
: state_(INVALID_GAIA_CREDENTIALS),
network_error_(0),
@@ -96,6 +102,19 @@ GoogleServiceAuthError GoogleServiceAuthError::FromClientLoginCaptchaChallenge(
captcha_image_url, captcha_unlock_url, 0, 0);
}
+// static
+GoogleServiceAuthError GoogleServiceAuthError::FromServiceError(
+ const std::string& error_message) {
+ return GoogleServiceAuthError(SERVICE_ERROR, error_message);
+}
+
+// static
+GoogleServiceAuthError GoogleServiceAuthError::FromUnexpectedServiceResponse(
+ const std::string& error_message) {
+ return GoogleServiceAuthError(UNEXPECTED_SERVICE_RESPONSE, error_message);
+}
+
+// static
GoogleServiceAuthError GoogleServiceAuthError::AuthErrorNone() {
return GoogleServiceAuthError(NONE);
}
@@ -151,12 +170,17 @@ DictionaryValue* GoogleServiceAuthError::ToValue() const {
STATE_CASE(TWO_FACTOR);
STATE_CASE(REQUEST_CANCELED);
STATE_CASE(HOSTED_NOT_ALLOWED);
+ STATE_CASE(UNEXPECTED_SERVICE_RESPONSE);
+ STATE_CASE(SERVICE_ERROR);
#undef STATE_CASE
default:
NOTREACHED();
break;
}
value->SetString("state", state_str);
+ if (!error_message_.empty()) {
+ value->SetString("errorMessage", error_message_);
+ }
if (state_ == CAPTCHA_REQUIRED) {
DictionaryValue* captcha_value = new DictionaryValue();
value->Set("captcha", captcha_value);
@@ -205,6 +229,12 @@ std::string GoogleServiceAuthError::ToString() const {
return "Request canceled.";
case HOSTED_NOT_ALLOWED:
return "Google account required.";
+ case UNEXPECTED_SERVICE_RESPONSE:
+ return base::StringPrintf("Unexpected service response (%s)",
+ error_message_.c_str());
+ case SERVICE_ERROR:
+ return base::StringPrintf("Service responded with error: '%s'",
+ error_message_.c_str());
default:
NOTREACHED();
return std::string();
diff --git a/google_apis/gaia/google_service_auth_error.h b/google_apis/gaia/google_service_auth_error.h
index 0ac0974..ddfa2d0 100644
--- a/google_apis/gaia/google_service_auth_error.h
+++ b/google_apis/gaia/google_service_auth_error.h
@@ -78,8 +78,16 @@ class GoogleServiceAuthError {
// a GOOGLE account.
HOSTED_NOT_ALLOWED = 10,
+ // Indicates the service responded to a request, but we cannot
+ // interpret the response.
+ UNEXPECTED_SERVICE_RESPONSE = 11,
+
+ // Indicates the service responded and response carried details of the
+ // application error.
+ SERVICE_ERROR = 12,
+
// The number of known error states.
- NUM_STATES = 11,
+ NUM_STATES = 13,
};
// Additional data for CAPTCHA_REQUIRED errors.
@@ -145,6 +153,16 @@ class GoogleServiceAuthError {
const GURL& captcha_image_url,
const GURL& captcha_unlock_url);
+ // Construct a SERVICE_ERROR error, e.g. invalid client ID, with an
+ // |error_message| which provides more information about the service error.
+ static GoogleServiceAuthError FromServiceError(
+ const std::string& error_message);
+
+ // Construct an UNEXPECTED_SERVICE_RESPONSE error, with an |error_message|
+ // detailing the problems with the response.
+ static GoogleServiceAuthError FromUnexpectedServiceResponse(
+ const std::string& error_message);
+
// Provided for convenience for clients needing to reset an instance to NONE.
// (avoids err_ = GoogleServiceAuthError(GoogleServiceAuthError::NONE), due
// to explicit class and State enum relation. Note: shouldn't be inlined!
@@ -168,6 +186,9 @@ class GoogleServiceAuthError {
private:
GoogleServiceAuthError(State s, int error);
+ // Construct a GoogleServiceAuthError from |state| and |error_message|.
+ GoogleServiceAuthError(State state, const std::string& error_message);
+
explicit GoogleServiceAuthError(const std::string& error_message);
GoogleServiceAuthError(State s, const std::string& captcha_token,
diff --git a/google_apis/gaia/oauth2_mint_token_flow.cc b/google_apis/gaia/oauth2_mint_token_flow.cc
index 5b02446..f8680e3 100644
--- a/google_apis/gaia/oauth2_mint_token_flow.cc
+++ b/google_apis/gaia/oauth2_mint_token_flow.cc
@@ -51,18 +51,40 @@ static const char kScopesKey[] = "scopes";
static const char kDescriptionKey[] = "description";
static const char kDetailKey[] = "detail";
static const char kDetailSeparators[] = "\n";
+static const char kError[] = "error";
+static const char kMessage[] = "message";
-static GoogleServiceAuthError CreateAuthError(URLRequestStatus status) {
+static GoogleServiceAuthError CreateAuthError(const net::URLFetcher* source) {
+ URLRequestStatus status = source->GetStatus();
if (status.status() == URLRequestStatus::CANCELED) {
return GoogleServiceAuthError(GoogleServiceAuthError::REQUEST_CANCELED);
- } else {
- // TODO(munjal): Improve error handling. Currently we return connection
- // error for even application level errors. We need to either expand the
- // GoogleServiceAuthError enum or create a new one to report better
- // errors.
+ }
+ if (status.status() == URLRequestStatus::FAILED) {
DLOG(WARNING) << "Server returned error: errno " << status.error();
return GoogleServiceAuthError::FromConnectionError(status.error());
}
+
+ std::string response_body;
+ source->GetResponseAsString(&response_body);
+ scoped_ptr<Value> value(base::JSONReader::Read(response_body));
+ DictionaryValue* response;
+ if (!value.get() || !value->GetAsDictionary(&response)) {
+ return GoogleServiceAuthError::FromUnexpectedServiceResponse(
+ base::StringPrintf(
+ "Not able to parse a JSON object from a service response. "
+ "HTTP Status of the response is: %d", source->GetResponseCode()));
+ }
+ DictionaryValue* error;
+ if (!response->GetDictionary(kError, &error)) {
+ return GoogleServiceAuthError::FromUnexpectedServiceResponse(
+ "Not able to find a detailed error in a service response.");
+ }
+ std::string message;
+ if (!error->GetString(kMessage, &message)) {
+ return GoogleServiceAuthError::FromUnexpectedServiceResponse(
+ "Not able to find an error message within a service error.");
+ }
+ return GoogleServiceAuthError::FromServiceError(message);
}
} // namespace
@@ -153,35 +175,39 @@ std::string OAuth2MintTokenFlow::CreateApiCallBody() {
void OAuth2MintTokenFlow::ProcessApiCallSuccess(
const net::URLFetcher* source) {
- // TODO(munjal): Change error code paths in this method to report an
- // internal error.
std::string response_body;
source->GetResponseAsString(&response_body);
scoped_ptr<base::Value> value(base::JSONReader::Read(response_body));
DictionaryValue* dict = NULL;
if (!value.get() || !value->GetAsDictionary(&dict)) {
- ReportFailure(GoogleServiceAuthError::FromConnectionError(101));
+ ReportFailure(GoogleServiceAuthError::FromUnexpectedServiceResponse(
+ "Not able to parse a JSON object from a service response."));
return;
}
- std::string issue_advice;
- if (!dict->GetString(kIssueAdviceKey, &issue_advice)) {
- ReportFailure(GoogleServiceAuthError::FromConnectionError(101));
+ std::string issue_advice_value;
+ if (!dict->GetString(kIssueAdviceKey, &issue_advice_value)) {
+ ReportFailure(GoogleServiceAuthError::FromUnexpectedServiceResponse(
+ "Not able to find an issueAdvice in a service response."));
return;
}
- if (issue_advice == kIssueAdviceValueConsent) {
+ if (issue_advice_value == kIssueAdviceValueConsent) {
IssueAdviceInfo issue_advice;
if (ParseIssueAdviceResponse(dict, &issue_advice))
ReportIssueAdviceSuccess(issue_advice);
else
- ReportFailure(GoogleServiceAuthError::FromConnectionError(101));
+ ReportFailure(GoogleServiceAuthError::FromUnexpectedServiceResponse(
+ "Not able to parse the contents of consent "
+ "from a service response."));
} else {
std::string access_token;
int time_to_live;
if (ParseMintTokenResponse(dict, &access_token, &time_to_live))
ReportSuccess(access_token, time_to_live);
else
- ReportFailure(GoogleServiceAuthError::FromConnectionError(101));
+ ReportFailure(GoogleServiceAuthError::FromUnexpectedServiceResponse(
+ "Not able to parse the contents of access token "
+ "from a service response."));
}
// |this| may be deleted!
@@ -189,7 +215,7 @@ void OAuth2MintTokenFlow::ProcessApiCallSuccess(
void OAuth2MintTokenFlow::ProcessApiCallFailure(
const net::URLFetcher* source) {
- ReportFailure(CreateAuthError(source->GetStatus()));
+ ReportFailure(CreateAuthError(source));
}
void OAuth2MintTokenFlow::ProcessNewAccessToken(
const std::string& access_token) {