summaryrefslogtreecommitdiffstats
path: root/google_apis
diff options
context:
space:
mode:
authorbcwhite <bcwhite@chromium.org>2015-04-03 00:47:01 -0700
committerCommit bot <commit-bot@chromium.org>2015-04-03 07:47:56 +0000
commitb7f9590aecaf544ca435559c98c4bb9b61d06405 (patch)
tree2fc3a131c1dfd96f481098936fc8be770645e13f /google_apis
parent43af203adea6535c2b89d2ba4a06c2dcd888dc3c (diff)
downloadchromium_src-b7f9590aecaf544ca435559c98c4bb9b61d06405.zip
chromium_src-b7f9590aecaf544ca435559c98c4bb9b61d06405.tar.gz
chromium_src-b7f9590aecaf544ca435559c98c4bb9b61d06405.tar.bz2
If an OAuth error is permanent, remember it instead of retrying.
BUG=466799 Review URL: https://codereview.chromium.org/1004623011 Cr-Commit-Position: refs/heads/master@{#323663}
Diffstat (limited to 'google_apis')
-rw-r--r--google_apis/BUILD.gn2
-rw-r--r--google_apis/gaia/google_service_auth_error.cc20
-rw-r--r--google_apis/gaia/google_service_auth_error.h6
-rw-r--r--google_apis/gaia/oauth2_access_token_fetcher_permanent_error.cc72
-rw-r--r--google_apis/gaia/oauth2_access_token_fetcher_permanent_error.h64
-rw-r--r--google_apis/google_apis.gyp2
6 files changed, 166 insertions, 0 deletions
diff --git a/google_apis/BUILD.gn b/google_apis/BUILD.gn
index bee149a..e6e22ab 100644
--- a/google_apis/BUILD.gn
+++ b/google_apis/BUILD.gn
@@ -104,6 +104,8 @@ source_set("google_apis") {
"gaia/oauth2_access_token_fetcher.h",
"gaia/oauth2_access_token_fetcher_impl.cc",
"gaia/oauth2_access_token_fetcher_impl.h",
+ "gaia/oauth2_access_token_fetcher_permanent_error.cc",
+ "gaia/oauth2_access_token_fetcher_permanent_error.h",
"gaia/oauth2_api_call_flow.cc",
"gaia/oauth2_api_call_flow.h",
"gaia/oauth2_mint_token_flow.cc",
diff --git a/google_apis/gaia/google_service_auth_error.cc b/google_apis/gaia/google_service_auth_error.cc
index 7796fae..5fab6dd 100644
--- a/google_apis/gaia/google_service_auth_error.cc
+++ b/google_apis/gaia/google_service_auth_error.cc
@@ -64,6 +64,11 @@ bool GoogleServiceAuthError::operator==(
second_factor_ == b.second_factor_);
}
+bool GoogleServiceAuthError::operator!=(
+ const GoogleServiceAuthError& b) const {
+ return !(*this == b);
+}
+
GoogleServiceAuthError::GoogleServiceAuthError(State s)
: state_(s),
network_error_(0) {
@@ -240,6 +245,21 @@ std::string GoogleServiceAuthError::ToString() const {
}
}
+bool GoogleServiceAuthError::IsPersistentError() const {
+ if (state_ == GoogleServiceAuthError::NONE) return false;
+ return !IsTransientError();
+}
+
+bool GoogleServiceAuthError::IsTransientError() const {
+ switch (state_) {
+ case GoogleServiceAuthError::CONNECTION_FAILED:
+ case GoogleServiceAuthError::SERVICE_UNAVAILABLE:
+ return true;
+ default:
+ return false;
+ }
+}
+
GoogleServiceAuthError::GoogleServiceAuthError(State s, int error)
: state_(s),
network_error_(error) {
diff --git a/google_apis/gaia/google_service_auth_error.h b/google_apis/gaia/google_service_auth_error.h
index fd643bd..15db61c 100644
--- a/google_apis/gaia/google_service_auth_error.h
+++ b/google_apis/gaia/google_service_auth_error.h
@@ -139,6 +139,7 @@ class GoogleServiceAuthError {
// For test only.
bool operator==(const GoogleServiceAuthError &b) const;
+ bool operator!=(const GoogleServiceAuthError &b) const;
// Construct a GoogleServiceAuthError from a State with no additional data.
explicit GoogleServiceAuthError(State s);
@@ -186,6 +187,11 @@ class GoogleServiceAuthError {
// Returns a message describing the error.
std::string ToString() const;
+ // Check if this is error may go away simply by trying again. Except for the
+ // NONE case, these are mutually exclusive.
+ bool IsPersistentError() const;
+ bool IsTransientError() const;
+
private:
GoogleServiceAuthError(State s, int error);
diff --git a/google_apis/gaia/oauth2_access_token_fetcher_permanent_error.cc b/google_apis/gaia/oauth2_access_token_fetcher_permanent_error.cc
new file mode 100644
index 0000000..0f24e3d
--- /dev/null
+++ b/google_apis/gaia/oauth2_access_token_fetcher_permanent_error.cc
@@ -0,0 +1,72 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "google_apis/gaia/oauth2_access_token_fetcher_permanent_error.h"
+
+#include "base/bind.h"
+#include "base/message_loop/message_loop.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+
+
+OAuth2AccessTokenFetcherPermanentError::FailCaller::FailCaller(
+ OAuth2AccessTokenFetcherPermanentError* fetcher)
+ : fetcher_(fetcher) {
+ base::MessageLoop* looper = base::MessageLoop::current();
+ DCHECK(looper);
+ looper->PostTask(
+ FROM_HERE,
+ base::Bind(&OAuth2AccessTokenFetcherPermanentError::FailCaller::run,
+ this));
+}
+
+OAuth2AccessTokenFetcherPermanentError::FailCaller::~FailCaller() {
+}
+
+void OAuth2AccessTokenFetcherPermanentError::FailCaller::run() {
+ if (fetcher_) {
+ fetcher_->Fail();
+ fetcher_ = NULL;
+ }
+}
+
+void OAuth2AccessTokenFetcherPermanentError::FailCaller::detach() {
+ fetcher_ = NULL;
+}
+
+
+OAuth2AccessTokenFetcherPermanentError::OAuth2AccessTokenFetcherPermanentError(
+ OAuth2AccessTokenConsumer* consumer,
+ const GoogleServiceAuthError& error)
+ : OAuth2AccessTokenFetcher(consumer),
+ permanent_error_(error) {
+ DCHECK(!permanent_error_.IsTransientError());
+}
+
+OAuth2AccessTokenFetcherPermanentError::
+ ~OAuth2AccessTokenFetcherPermanentError() {
+ CancelRequest();
+}
+
+void OAuth2AccessTokenFetcherPermanentError::CancelRequest() {
+ if (failer_) {
+ failer_->detach();
+ failer_ = NULL;
+ }
+}
+
+void OAuth2AccessTokenFetcherPermanentError::Start(
+ const std::string& client_id,
+ const std::string& client_secret,
+ const std::vector<std::string>& scopes) {
+ failer_ = new FailCaller(this);
+}
+
+void OAuth2AccessTokenFetcherPermanentError::Fail() {
+ // The call below will likely destruct this object. We have to make a copy
+ // of the error into a local variable because the class member thus will
+ // be destroyed after which the copy-passed-by-reference will cause a
+ // memory violation when accessed.
+ GoogleServiceAuthError error_copy = permanent_error_;
+ FireOnGetTokenFailure(error_copy);
+}
diff --git a/google_apis/gaia/oauth2_access_token_fetcher_permanent_error.h b/google_apis/gaia/oauth2_access_token_fetcher_permanent_error.h
new file mode 100644
index 0000000..e7053ce
--- /dev/null
+++ b/google_apis/gaia/oauth2_access_token_fetcher_permanent_error.h
@@ -0,0 +1,64 @@
+// Copyright 2015 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_FETCHER_PERMANENT_ERROR_H_
+#define GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_FETCHER_PERMANENT_ERROR_H_
+
+#include "base/memory/ref_counted.h"
+#include "google_apis/gaia/google_service_auth_error.h"
+#include "google_apis/gaia/oauth2_access_token_consumer.h"
+#include "google_apis/gaia/oauth2_access_token_fetcher.h"
+
+// This is an implementation of the OAuth2 fetcher that immediately returns
+// an error. This is useful as a replacement to a real fetcher when a
+// permanent error has previously been seen.
+//
+// This class should be used on a single thread, but it can be whichever thread
+// that you like.
+// Also, do not reuse the same instance. Once Start() is called, the instance
+// should not be reused.
+//
+// Usage:
+// * Create an instance with a consumer.
+// * Call Start()
+// * The consumer passed in the constructor will be called on the same
+// thread Start was called with the results.
+//
+// This class can handle one request at a time. To parallelize requests,
+// create multiple instances.
+class OAuth2AccessTokenFetcherPermanentError : public OAuth2AccessTokenFetcher {
+ public:
+ OAuth2AccessTokenFetcherPermanentError(OAuth2AccessTokenConsumer* consumer,
+ const GoogleServiceAuthError& error);
+ ~OAuth2AccessTokenFetcherPermanentError() override;
+
+ void Start(const std::string& client_id,
+ const std::string& client_secret,
+ const std::vector<std::string>& scopes) override;
+
+ void CancelRequest() override;
+
+ private:
+ class FailCaller : public base::RefCounted<FailCaller> {
+ public:
+ FailCaller(OAuth2AccessTokenFetcherPermanentError* fetcher);
+
+ void run();
+ void detach();
+
+ private:
+ friend class base::RefCounted<FailCaller>;
+ ~FailCaller();
+
+ OAuth2AccessTokenFetcherPermanentError* fetcher_;
+ };
+
+ void Fail();
+
+ scoped_refptr<FailCaller> failer_;
+ GoogleServiceAuthError permanent_error_;
+ DISALLOW_COPY_AND_ASSIGN(OAuth2AccessTokenFetcherPermanentError);
+};
+
+#endif // GOOGLE_APIS_GAIA_OAUTH2_ACCESS_TOKEN_FETCHER_PERMANENT_ERROR_H_
diff --git a/google_apis/google_apis.gyp b/google_apis/google_apis.gyp
index 20c3269..0969651 100644
--- a/google_apis/google_apis.gyp
+++ b/google_apis/google_apis.gyp
@@ -95,6 +95,8 @@
'gaia/oauth2_access_token_fetcher.h',
'gaia/oauth2_access_token_fetcher_impl.cc',
'gaia/oauth2_access_token_fetcher_impl.h',
+ 'gaia/oauth2_access_token_fetcher_permanent_error.cc',
+ 'gaia/oauth2_access_token_fetcher_permanent_error.h',
'gaia/oauth2_api_call_flow.cc',
'gaia/oauth2_api_call_flow.h',
'gaia/oauth2_mint_token_flow.cc',