Commit 9de4b0be authored by Tanja Gornak's avatar Tanja Gornak Committed by Commit Bot

Move Oauth token routine to the registraion manager.

Bug: 867334, 801985
Change-Id: I306bb35f1788acdfd83b772c428fd718ee13b61a
Reviewed-on: https://chromium-review.googlesource.com/1154983
Commit-Queue: Tatiana Gornak <melandory@chromium.org>
Reviewed-by: default avatarPavel Yatsuk <pavely@chromium.org>
Cr-Commit-Position: refs/heads/master@{#584387}
parent 270adc66
...@@ -11,35 +11,7 @@ ...@@ -11,35 +11,7 @@
#include "components/invalidation/public/invalidation_util.h" #include "components/invalidation/public/invalidation_util.h"
#include "components/invalidation/public/invalidator_state.h" #include "components/invalidation/public/invalidator_state.h"
#include "components/invalidation/public/object_id_invalidation_map.h" #include "components/invalidation/public/object_id_invalidation_map.h"
#include "google_apis/gaia/gaia_constants.h"
const char kFCMOAuthScope[] =
"https://www.googleapis.com/auth/firebase.messaging";
static const net::BackoffEntry::Policy kRequestAccessTokenBackoffPolicy = {
// Number of initial errors (in sequence) to ignore before applying
// exponential back-off rules.
0,
// Initial delay for exponential back-off in ms.
2000,
// Factor by which the waiting time will be multiplied.
2,
// Fuzzing percentage. ex: 10% will spread requests randomly
// between 90%-100% of the calculated time.
0.2, // 20%
// Maximum amount of time we are willing to delay our request in ms.
1000 * 3600 * 4, // 4 hours.
// Time to keep an entry from being discarded even when it
// has no significant state, -1 to never discard.
-1,
// Don't use initial delay unless the last request was an error.
false,
};
namespace invalidation { namespace invalidation {
...@@ -50,10 +22,9 @@ FCMInvalidationService::FCMInvalidationService( ...@@ -50,10 +22,9 @@ FCMInvalidationService::FCMInvalidationService(
PrefService* pref_service, PrefService* pref_service,
const syncer::ParseJSONCallback& parse_json, const syncer::ParseJSONCallback& parse_json,
network::mojom::URLLoaderFactory* loader_factory) network::mojom::URLLoaderFactory* loader_factory)
: identity_provider_(std::move(identity_provider)), : gcm_driver_(gcm_driver),
request_access_token_backoff_(&kRequestAccessTokenBackoffPolicy),
gcm_driver_(gcm_driver),
instance_id_driver_(instance_id_driver), instance_id_driver_(instance_id_driver),
identity_provider_(std::move(identity_provider)),
pref_service_(pref_service), pref_service_(pref_service),
parse_json_(parse_json), parse_json_(parse_json),
loader_factory_(loader_factory) {} loader_factory_(loader_factory) {}
...@@ -134,7 +105,6 @@ syncer::InvalidatorState FCMInvalidationService::GetInvalidatorState() const { ...@@ -134,7 +105,6 @@ syncer::InvalidatorState FCMInvalidationService::GetInvalidatorState() const {
} }
std::string FCMInvalidationService::GetInvalidatorClientId() const { std::string FCMInvalidationService::GetInvalidatorClientId() const {
NOTREACHED();
return std::string(); return std::string();
} }
...@@ -150,64 +120,6 @@ void FCMInvalidationService::RequestDetailedStatus( ...@@ -150,64 +120,6 @@ void FCMInvalidationService::RequestDetailedStatus(
} }
} }
void FCMInvalidationService::RequestAccessToken() {
// Only one active request at a time.
if (access_token_fetcher_ != nullptr)
return;
request_access_token_retry_timer_.Stop();
OAuth2TokenService::ScopeSet oauth2_scopes = {kFCMOAuthScope};
// Invalidate previous token, otherwise the identity provider will return the
// same token again.
identity_provider_->InvalidateAccessToken(oauth2_scopes, access_token_);
access_token_.clear();
access_token_fetcher_ = identity_provider_->FetchAccessToken(
"fcm_invalidation", oauth2_scopes,
base::BindOnce(&FCMInvalidationService::OnAccessTokenRequestCompleted,
base::Unretained(this)));
}
void FCMInvalidationService::OnAccessTokenRequestCompleted(
GoogleServiceAuthError error,
std::string access_token) {
access_token_fetcher_.reset();
if (error.state() == GoogleServiceAuthError::NONE)
OnAccessTokenRequestSucceeded(access_token);
else
OnAccessTokenRequestFailed(error);
}
void FCMInvalidationService::OnAccessTokenRequestSucceeded(
std::string access_token) {
// Reset backoff time after successful response.
request_access_token_backoff_.Reset();
access_token_ = access_token;
if (!IsStarted() && IsReadyToStart()) {
StartInvalidator();
} else {
UpdateInvalidatorCredentials();
}
}
void FCMInvalidationService::OnAccessTokenRequestFailed(
GoogleServiceAuthError error) {
DCHECK_NE(error.state(), GoogleServiceAuthError::NONE);
switch (error.state()) {
case GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS: {
invalidator_registrar_.UpdateInvalidatorState(
syncer::INVALIDATION_CREDENTIALS_REJECTED);
break;
}
default: {
request_access_token_backoff_.InformOfRequest(false);
request_access_token_retry_timer_.Start(
FROM_HERE, request_access_token_backoff_.GetTimeUntilRelease(),
base::BindRepeating(&FCMInvalidationService::RequestAccessToken,
base::Unretained(this)));
break;
}
}
}
void FCMInvalidationService::OnActiveAccountLogin() { void FCMInvalidationService::OnActiveAccountLogin() {
if (!IsStarted() && IsReadyToStart()) if (!IsStarted() && IsReadyToStart())
StartInvalidator(); StartInvalidator();
...@@ -216,20 +128,9 @@ void FCMInvalidationService::OnActiveAccountLogin() { ...@@ -216,20 +128,9 @@ void FCMInvalidationService::OnActiveAccountLogin() {
void FCMInvalidationService::OnActiveAccountRefreshTokenUpdated() { void FCMInvalidationService::OnActiveAccountRefreshTokenUpdated() {
if (!IsStarted() && IsReadyToStart()) if (!IsStarted() && IsReadyToStart())
StartInvalidator(); StartInvalidator();
else
UpdateInvalidatorCredentials();
}
void FCMInvalidationService::OnActiveAccountRefreshTokenRemoved() {
access_token_.clear();
if (IsStarted())
UpdateInvalidatorCredentials();
} }
void FCMInvalidationService::OnActiveAccountLogout() { void FCMInvalidationService::OnActiveAccountLogout() {
access_token_fetcher_.reset();
request_access_token_retry_timer_.Stop();
if (IsStarted()) { if (IsStarted()) {
StopInvalidator(); StopInvalidator();
} }
...@@ -271,36 +172,18 @@ void FCMInvalidationService::StartInvalidator() { ...@@ -271,36 +172,18 @@ void FCMInvalidationService::StartInvalidator() {
DCHECK(!invalidator_); DCHECK(!invalidator_);
DCHECK(IsReadyToStart()); DCHECK(IsReadyToStart());
// access token before sending message to server.
if (access_token_.empty()) {
// TODO(melandory): move logic for recieving the token directly to
// the PerUserTopicRegistrationmanager.
DVLOG(1) << "FCMInvalidationService: "
<< "Deferring start until we have an access token.";
RequestAccessToken();
return;
}
auto network = std::make_unique<syncer::FCMNetworkHandler>( auto network = std::make_unique<syncer::FCMNetworkHandler>(
gcm_driver_, instance_id_driver_); gcm_driver_, instance_id_driver_);
network->StartListening(); network->StartListening();
invalidator_ = std::make_unique<syncer::FCMInvalidator>( invalidator_ = std::make_unique<syncer::FCMInvalidator>(
std::move(network), pref_service_, loader_factory_, parse_json_); std::move(network), identity_provider_.get(), pref_service_,
loader_factory_, parse_json_);
invalidator_->RegisterHandler(this); invalidator_->RegisterHandler(this);
UpdateInvalidatorCredentials();
CHECK(invalidator_->UpdateRegisteredIds( CHECK(invalidator_->UpdateRegisteredIds(
this, invalidator_registrar_.GetAllRegisteredIds())); this, invalidator_registrar_.GetAllRegisteredIds()));
} }
void FCMInvalidationService::UpdateInvalidatorCredentials() {
std::string email = identity_provider_->GetActiveAccountId();
DCHECK(!email.empty()) << "Expected user to be signed in.";
invalidator_->UpdateCredentials(email, access_token_);
}
void FCMInvalidationService::StopInvalidator() { void FCMInvalidationService::StopInvalidator() {
DCHECK(invalidator_); DCHECK(invalidator_);
// TODO(melandory): reset the network. // TODO(melandory): reset the network.
......
...@@ -63,16 +63,8 @@ class FCMInvalidationService : public InvalidationService, ...@@ -63,16 +63,8 @@ class FCMInvalidationService : public InvalidationService,
base::RepeatingCallback<void(const base::DictionaryValue&)> caller) base::RepeatingCallback<void(const base::DictionaryValue&)> caller)
const override; const override;
void RequestAccessToken();
void OnAccessTokenRequestCompleted(GoogleServiceAuthError error,
std::string access_token);
void OnAccessTokenRequestSucceeded(std::string access_token);
void OnAccessTokenRequestFailed(GoogleServiceAuthError error);
// IdentityProvider::Observer implementation. // IdentityProvider::Observer implementation.
void OnActiveAccountRefreshTokenUpdated() override; void OnActiveAccountRefreshTokenUpdated() override;
void OnActiveAccountRefreshTokenRemoved() override;
void OnActiveAccountLogin() override; void OnActiveAccountLogin() override;
void OnActiveAccountLogout() override; void OnActiveAccountLogout() override;
...@@ -94,22 +86,10 @@ class FCMInvalidationService : public InvalidationService, ...@@ -94,22 +86,10 @@ class FCMInvalidationService : public InvalidationService,
void StartInvalidator(); void StartInvalidator();
void StopInvalidator(); void StopInvalidator();
void UpdateInvalidatorCredentials();
std::unique_ptr<IdentityProvider> identity_provider_;
// FCMInvalidationService needs to hold reference to access_token_fetcher_
// for the duration of request in order to receive callbacks.
std::unique_ptr<ActiveAccountAccessTokenFetcher> access_token_fetcher_;
base::OneShotTimer request_access_token_retry_timer_;
net::BackoffEntry request_access_token_backoff_;
syncer::InvalidatorRegistrar invalidator_registrar_; syncer::InvalidatorRegistrar invalidator_registrar_;
std::unique_ptr<syncer::Invalidator> invalidator_; std::unique_ptr<syncer::Invalidator> invalidator_;
// FCMInvalidationService needs to remember access token in order to
// invalidate it with IdentityProvider.
std::string access_token_;
// The invalidation logger object we use to record state changes // The invalidation logger object we use to record state changes
// and invalidations. // and invalidations.
InvalidationLogger logger_; InvalidationLogger logger_;
...@@ -117,6 +97,7 @@ class FCMInvalidationService : public InvalidationService, ...@@ -117,6 +97,7 @@ class FCMInvalidationService : public InvalidationService,
gcm::GCMDriver* gcm_driver_; gcm::GCMDriver* gcm_driver_;
instance_id::InstanceIDDriver* instance_id_driver_; instance_id::InstanceIDDriver* instance_id_driver_;
std::unique_ptr<IdentityProvider> identity_provider_;
PrefService* pref_service_; PrefService* pref_service_;
syncer::ParseJSONCallback parse_json_; syncer::ParseJSONCallback parse_json_;
network::mojom::URLLoaderFactory* loader_factory_; network::mojom::URLLoaderFactory* loader_factory_;
......
...@@ -9,19 +9,24 @@ ...@@ -9,19 +9,24 @@
#include "base/macros.h" #include "base/macros.h"
#include "components/invalidation/impl/fcm_sync_network_channel.h" #include "components/invalidation/impl/fcm_sync_network_channel.h"
#include "components/invalidation/impl/per_user_topic_invalidation_client.h" #include "components/invalidation/impl/per_user_topic_invalidation_client.h"
#include "components/invalidation/public/identity_provider.h"
#include "components/invalidation/public/object_id_invalidation_map.h" #include "components/invalidation/public/object_id_invalidation_map.h"
namespace syncer { namespace syncer {
FCMInvalidator::FCMInvalidator( FCMInvalidator::FCMInvalidator(
std::unique_ptr<FCMSyncNetworkChannel> network_channel, std::unique_ptr<FCMSyncNetworkChannel> network_channel,
invalidation::IdentityProvider* identity_provider,
PrefService* pref_service, PrefService* pref_service,
network::mojom::URLLoaderFactory* loader_factory, network::mojom::URLLoaderFactory* loader_factory,
const ParseJSONCallback& parse_json) const ParseJSONCallback& parse_json)
: pref_service_(pref_service), : invalidation_listener_(std::move(network_channel)) {
loader_factory_(loader_factory), auto registration_manager = std::make_unique<PerUserTopicRegistrationManager>(
parse_json_(parse_json), identity_provider, pref_service, loader_factory, parse_json);
invalidation_listener_(std::move(network_channel)) {} invalidation_listener_.Start(
base::BindOnce(&CreatePerUserTopicInvalidationClient), this,
std::move(registration_manager));
}
FCMInvalidator::~FCMInvalidator() {} FCMInvalidator::~FCMInvalidator() {}
...@@ -38,6 +43,11 @@ bool FCMInvalidator::UpdateRegisteredIds(InvalidationHandler* handler, ...@@ -38,6 +43,11 @@ bool FCMInvalidator::UpdateRegisteredIds(InvalidationHandler* handler,
return true; return true;
} }
void FCMInvalidator::UpdateCredentials(const std::string& email,
const std::string& token) {
// TODO(melandory): remove during cleanup.
}
void FCMInvalidator::UnregisterHandler(InvalidationHandler* handler) { void FCMInvalidator::UnregisterHandler(InvalidationHandler* handler) {
registrar_.UnregisterHandler(handler); registrar_.UnregisterHandler(handler);
} }
...@@ -46,20 +56,6 @@ InvalidatorState FCMInvalidator::GetInvalidatorState() const { ...@@ -46,20 +56,6 @@ InvalidatorState FCMInvalidator::GetInvalidatorState() const {
return registrar_.GetInvalidatorState(); return registrar_.GetInvalidatorState();
} }
void FCMInvalidator::UpdateCredentials(const std::string& email,
const std::string& token) {
if (!is_started_) {
auto registration_manager =
std::make_unique<PerUserTopicRegistrationManager>(
token, pref_service_, loader_factory_, parse_json_);
invalidation_listener_.Start(
base::BindOnce(&CreatePerUserTopicInvalidationClient), this,
std::move(registration_manager));
is_started_ = true;
}
// TODO(melandory): The token change is irrelevant for current implementation.
}
void FCMInvalidator::OnInvalidate( void FCMInvalidator::OnInvalidate(
const ObjectIdInvalidationMap& invalidation_map) { const ObjectIdInvalidationMap& invalidation_map) {
registrar_.DispatchInvalidationsToHandlers(invalidation_map); registrar_.DispatchInvalidationsToHandlers(invalidation_map);
......
...@@ -15,6 +15,10 @@ ...@@ -15,6 +15,10 @@
class PrefService; class PrefService;
namespace invalidation {
class IdentityProvider;
}
namespace syncer { namespace syncer {
class FCMSyncNetworkChannel; class FCMSyncNetworkChannel;
...@@ -25,6 +29,7 @@ class FCMInvalidator : public Invalidator, ...@@ -25,6 +29,7 @@ class FCMInvalidator : public Invalidator,
public FCMSyncInvalidationListener::Delegate { public FCMSyncInvalidationListener::Delegate {
public: public:
FCMInvalidator(std::unique_ptr<FCMSyncNetworkChannel> network_channel, FCMInvalidator(std::unique_ptr<FCMSyncNetworkChannel> network_channel,
invalidation::IdentityProvider* identity_provider,
PrefService* pref_service, PrefService* pref_service,
network::mojom::URLLoaderFactory* loader_factory, network::mojom::URLLoaderFactory* loader_factory,
const ParseJSONCallback& parse_json); const ParseJSONCallback& parse_json);
...@@ -53,12 +58,6 @@ class FCMInvalidator : public Invalidator, ...@@ -53,12 +58,6 @@ class FCMInvalidator : public Invalidator,
bool is_started_ = false; bool is_started_ = false;
InvalidatorRegistrar registrar_; InvalidatorRegistrar registrar_;
// Needed for the creation of the registration manager.
std::string instance_id_token_;
PrefService* pref_service_;
network::mojom::URLLoaderFactory* loader_factory_ = nullptr;
syncer::ParseJSONCallback parse_json_;
// The invalidation listener. // The invalidation listener.
FCMSyncInvalidationListener invalidation_listener_; FCMSyncInvalidationListener invalidation_listener_;
......
...@@ -14,9 +14,11 @@ ...@@ -14,9 +14,11 @@
#include "components/invalidation/impl/invalidator_test_template.h" #include "components/invalidation/impl/invalidator_test_template.h"
#include "components/invalidation/impl/json_unsafe_parser.h" #include "components/invalidation/impl/json_unsafe_parser.h"
#include "components/invalidation/impl/per_user_topic_registration_manager.h" #include "components/invalidation/impl/per_user_topic_registration_manager.h"
#include "components/invalidation/impl/profile_identity_provider.h"
#include "components/invalidation/impl/push_client_channel.h" #include "components/invalidation/impl/push_client_channel.h"
#include "components/prefs/testing_pref_service.h" #include "components/prefs/testing_pref_service.h"
#include "net/url_request/url_request_test_util.h" #include "net/url_request/url_request_test_util.h"
#include "services/identity/public/cpp/identity_test_environment.h"
#include "services/network/test/test_url_loader_factory.h" #include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
...@@ -38,8 +40,12 @@ class FCMInvalidatorTestDelegate { ...@@ -38,8 +40,12 @@ class FCMInvalidatorTestDelegate {
const base::WeakPtr<InvalidationStateTracker>&) { const base::WeakPtr<InvalidationStateTracker>&) {
DCHECK(!invalidator_); DCHECK(!invalidator_);
auto network_channel = std::make_unique<FCMSyncNetworkChannel>(); auto network_channel = std::make_unique<FCMSyncNetworkChannel>();
identity_provider_ =
std::make_unique<invalidation::ProfileIdentityProvider>(
identity_test_env_.identity_manager());
invalidator_.reset(new FCMInvalidator( invalidator_.reset(new FCMInvalidator(
std::move(network_channel), &pref_service_, &url_loader_factory_, std::move(network_channel), identity_provider_.get(), &pref_service_,
&url_loader_factory_,
base::BindRepeating(&syncer::JsonUnsafeParser::Parse))); base::BindRepeating(&syncer::JsonUnsafeParser::Parse)));
} }
...@@ -64,6 +70,8 @@ class FCMInvalidatorTestDelegate { ...@@ -64,6 +70,8 @@ class FCMInvalidatorTestDelegate {
private: private:
base::test::ScopedTaskEnvironment scoped_task_environment_; base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<FCMInvalidator> invalidator_; std::unique_ptr<FCMInvalidator> invalidator_;
identity::IdentityTestEnvironment identity_test_env_;
std::unique_ptr<invalidation::IdentityProvider> identity_provider_;
network::TestURLLoaderFactory url_loader_factory_; network::TestURLLoaderFactory url_loader_factory_;
TestingPrefServiceSimple pref_service_; TestingPrefServiceSimple pref_service_;
}; };
......
...@@ -84,7 +84,7 @@ void FCMSyncInvalidationListener::Start( ...@@ -84,7 +84,7 @@ void FCMSyncInvalidationListener::Start(
void FCMSyncInvalidationListener::UpdateRegisteredIds(const ObjectIdSet& ids) { void FCMSyncInvalidationListener::UpdateRegisteredIds(const ObjectIdSet& ids) {
registered_ids_ = ConvertToInvalidationObjectIdSet(ids); registered_ids_ = ConvertToInvalidationObjectIdSet(ids);
if (ticl_state_ == INVALIDATIONS_ENABLED && if (ticl_state_ == INVALIDATIONS_ENABLED &&
per_user_topic_registration_manager_) per_user_topic_registration_manager_ && !token_.empty())
DoRegistrationUpdate(); DoRegistrationUpdate();
} }
...@@ -191,6 +191,7 @@ void FCMSyncInvalidationListener::InformTokenRecieved( ...@@ -191,6 +191,7 @@ void FCMSyncInvalidationListener::InformTokenRecieved(
const std::string& token) { const std::string& token) {
DCHECK_EQ(client, invalidation_client_.get()); DCHECK_EQ(client, invalidation_client_.get());
token_ = token; token_ = token;
DoRegistrationUpdate();
} }
void FCMSyncInvalidationListener::Acknowledge(const invalidation::ObjectId& id, void FCMSyncInvalidationListener::Acknowledge(const invalidation::ObjectId& id,
......
...@@ -183,7 +183,7 @@ class MockRegistrationManager : public PerUserTopicRegistrationManager { ...@@ -183,7 +183,7 @@ class MockRegistrationManager : public PerUserTopicRegistrationManager {
public: public:
MockRegistrationManager() MockRegistrationManager()
: PerUserTopicRegistrationManager( : PerUserTopicRegistrationManager(
"fake_access_token", nullptr /* identity_provider */,
nullptr /* pref_service */, nullptr /* pref_service */,
nullptr /* loader_factory */, nullptr /* loader_factory */,
base::BindRepeating(&syncer::JsonUnsafeParser::Parse)) {} base::BindRepeating(&syncer::JsonUnsafeParser::Parse)) {}
...@@ -308,6 +308,7 @@ class FCMSyncInvalidationListenerTest : public testing::Test { ...@@ -308,6 +308,7 @@ class FCMSyncInvalidationListenerTest : public testing::Test {
void EnableNotifications() { void EnableNotifications() {
fcm_sync_network_channel_->NotifyChannelStateChange(INVALIDATIONS_ENABLED); fcm_sync_network_channel_->NotifyChannelStateChange(INVALIDATIONS_ENABLED);
listener_.InformTokenRecieved(fake_invalidation_client_, "token");
} }
void DisableNotifications(InvalidatorState state) { void DisableNotifications(InvalidatorState state) {
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "components/gcm_driver/instance_id/instance_id_driver.h" #include "components/gcm_driver/instance_id/instance_id_driver.h"
#include "components/invalidation/public/identity_provider.h"
#include "components/invalidation/public/invalidation_object_id.h" #include "components/invalidation/public/invalidation_object_id.h"
#include "components/invalidation/public/invalidation_util.h" #include "components/invalidation/public/invalidation_util.h"
#include "components/prefs/pref_registry_simple.h" #include "components/prefs/pref_registry_simple.h"
...@@ -35,6 +36,35 @@ const char kInvalidationRegistrationScope[] = ...@@ -35,6 +36,35 @@ const char kInvalidationRegistrationScope[] =
const char kProjectId[] = "8181035976"; const char kProjectId[] = "8181035976";
const char kFCMOAuthScope[] =
"https://www.googleapis.com/auth/firebase.messaging";
static const net::BackoffEntry::Policy kRequestAccessTokenBackoffPolicy = {
// Number of initial errors (in sequence) to ignore before applying
// exponential back-off rules.
0,
// Initial delay for exponential back-off in ms.
2000,
// Factor by which the waiting time will be multiplied.
2,
// Fuzzing percentage. ex: 10% will spread requests randomly
// between 90%-100% of the calculated time.
0.2, // 20%
// Maximum amount of time we are willing to delay our request in ms.
1000 * 3600 * 4, // 4 hours.
// Time to keep an entry from being discarded even when it
// has no significant state, -1 to never discard.
-1,
// Don't use initial delay unless the last request was an error.
false,
};
} // namespace } // namespace
// static // static
...@@ -106,12 +136,13 @@ void PerUserTopicRegistrationManager::RegistrationEntry::RegistrationFinished( ...@@ -106,12 +136,13 @@ void PerUserTopicRegistrationManager::RegistrationEntry::RegistrationFinished(
} }
PerUserTopicRegistrationManager::PerUserTopicRegistrationManager( PerUserTopicRegistrationManager::PerUserTopicRegistrationManager(
const std::string& access_token, invalidation::IdentityProvider* identity_provider,
PrefService* local_state, PrefService* local_state,
network::mojom::URLLoaderFactory* url_loader_factory, network::mojom::URLLoaderFactory* url_loader_factory,
const ParseJSONCallback& parse_json) const ParseJSONCallback& parse_json)
: local_state_(local_state), : local_state_(local_state),
access_token_(access_token), identity_provider_(identity_provider),
request_access_token_backoff_(&kRequestAccessTokenBackoffPolicy),
parse_json_(parse_json), parse_json_(parse_json),
url_loader_factory_(url_loader_factory) {} url_loader_factory_(url_loader_factory) {}
...@@ -129,18 +160,23 @@ void PerUserTopicRegistrationManager::UpdateRegisteredIds( ...@@ -129,18 +160,23 @@ void PerUserTopicRegistrationManager::UpdateRegisteredIds(
registration_statuses_[objectId] = registration_statuses_[objectId] =
std::make_unique<RegistrationEntry>(objectId, local_state_); std::make_unique<RegistrationEntry>(objectId, local_state_);
} }
if (registration_statuses_[objectId]->state == }
RegistrationEntry::UNREGISTERED) { RequestAccessToken();
TryToRegisterId(objectId); }
void PerUserTopicRegistrationManager::DoRegistrationUpdate() {
for (const auto& registration_status : registration_statuses_) {
if (registration_status.second->state == RegistrationEntry::UNREGISTERED) {
StartRegistrationRequest(registration_status.first);
} }
} }
} }
void PerUserTopicRegistrationManager::TryToRegisterId( void PerUserTopicRegistrationManager::StartRegistrationRequest(
const invalidation::InvalidationObjectId& id) { const invalidation::InvalidationObjectId& id) {
auto it = registration_statuses_.find(id); auto it = registration_statuses_.find(id);
if (it == registration_statuses_.end()) { if (it == registration_statuses_.end()) {
NOTREACHED() << "TryToRegisterId called on " NOTREACHED() << "StartRegistrationRequest called on "
<< InvalidationObjectIdToString(id) << InvalidationObjectIdToString(id)
<< " which is not in the registration map"; << " which is not in the registration map";
return; return;
...@@ -174,4 +210,55 @@ InvalidationObjectIdSet PerUserTopicRegistrationManager::GetRegisteredIds() ...@@ -174,4 +210,55 @@ InvalidationObjectIdSet PerUserTopicRegistrationManager::GetRegisteredIds()
return ids; return ids;
} }
void PerUserTopicRegistrationManager::RequestAccessToken() {
// TODO(melandory): Implement traffic optimisation.
// * Before sending request to server ask for access token from identity
// provider (don't invalidate previous token).
// Identity provider will take care of retrieving/caching.
// * Only invalidate access token when server didn't accept it.
// Only one active request at a time.
if (access_token_fetcher_ != nullptr)
return;
request_access_token_retry_timer_.Stop();
OAuth2TokenService::ScopeSet oauth2_scopes = {kFCMOAuthScope};
// Invalidate previous token, otherwise the identity provider will return the
// same token again.
identity_provider_->InvalidateAccessToken(oauth2_scopes, access_token_);
access_token_.clear();
access_token_fetcher_ = identity_provider_->FetchAccessToken(
"fcm_invalidation", oauth2_scopes,
base::BindOnce(
&PerUserTopicRegistrationManager::OnAccessTokenRequestCompleted,
base::Unretained(this)));
}
void PerUserTopicRegistrationManager::OnAccessTokenRequestCompleted(
GoogleServiceAuthError error,
std::string access_token) {
access_token_fetcher_.reset();
if (error.state() == GoogleServiceAuthError::NONE)
OnAccessTokenRequestSucceeded(access_token);
else
OnAccessTokenRequestFailed(error);
}
void PerUserTopicRegistrationManager::OnAccessTokenRequestSucceeded(
std::string access_token) {
// Reset backoff time after successful response.
request_access_token_backoff_.Reset();
access_token_ = access_token;
DoRegistrationUpdate();
}
void PerUserTopicRegistrationManager::OnAccessTokenRequestFailed(
GoogleServiceAuthError error) {
DCHECK_NE(error.state(), GoogleServiceAuthError::NONE);
request_access_token_backoff_.InformOfRequest(false);
request_access_token_retry_timer_.Start(
FROM_HERE, request_access_token_backoff_.GetTimeUntilRelease(),
base::BindRepeating(&PerUserTopicRegistrationManager::RequestAccessToken,
base::Unretained(this)));
}
} // namespace syncer } // namespace syncer
...@@ -13,14 +13,21 @@ ...@@ -13,14 +13,21 @@
#include "base/time/time.h" #include "base/time/time.h"
#include "base/timer/timer.h" #include "base/timer/timer.h"
#include "components/invalidation/impl/per_user_topic_registration_request.h" #include "components/invalidation/impl/per_user_topic_registration_request.h"
#include "components/invalidation/public/identity_provider.h"
#include "components/invalidation/public/invalidation_export.h" #include "components/invalidation/public/invalidation_export.h"
#include "components/invalidation/public/invalidation_object_id.h" #include "components/invalidation/public/invalidation_object_id.h"
#include "components/invalidation/public/invalidation_util.h" #include "components/invalidation/public/invalidation_util.h"
#include "net/base/backoff_entry.h"
#include "net/url_request/url_request_context_getter.h" #include "net/url_request/url_request_context_getter.h"
class PrefRegistrySimple; class PrefRegistrySimple;
class PrefService; class PrefService;
namespace invalidation {
class ActiveAccountAccessTokenFetcher;
class IdentityProvider;
} // namespace invalidation
namespace syncer { namespace syncer {
// A class that manages the registration of types for server-issued // A class that manages the registration of types for server-issued
...@@ -35,7 +42,7 @@ namespace syncer { ...@@ -35,7 +42,7 @@ namespace syncer {
class INVALIDATION_EXPORT PerUserTopicRegistrationManager { class INVALIDATION_EXPORT PerUserTopicRegistrationManager {
public: public:
PerUserTopicRegistrationManager( PerUserTopicRegistrationManager(
const std::string& access_token, invalidation::IdentityProvider* identity_provider,
PrefService* local_state, PrefService* local_state,
network::mojom::URLLoaderFactory* url_loader_factory, network::mojom::URLLoaderFactory* url_loader_factory,
const ParseJSONCallback& parse_json); const ParseJSONCallback& parse_json);
...@@ -52,24 +59,37 @@ class INVALIDATION_EXPORT PerUserTopicRegistrationManager { ...@@ -52,24 +59,37 @@ class INVALIDATION_EXPORT PerUserTopicRegistrationManager {
private: private:
struct RegistrationEntry; struct RegistrationEntry;
void DoRegistrationUpdate();
// Tries to register |id|. No retry in case of failure. // Tries to register |id|. No retry in case of failure.
void TryToRegisterId(const invalidation::InvalidationObjectId& id); void StartRegistrationRequest(const invalidation::InvalidationObjectId& id);
// Unregisters the given object ID. // Unregisters the given object ID.
void UnregisterId(const invalidation::InvalidationObjectId& id); void UnregisterId(const invalidation::InvalidationObjectId& id);
void RequestAccessToken();
void OnAccessTokenRequestCompleted(GoogleServiceAuthError error,
std::string access_token);
void OnAccessTokenRequestSucceeded(std::string access_token);
void OnAccessTokenRequestFailed(GoogleServiceAuthError error);
std::map<invalidation::InvalidationObjectId, std::map<invalidation::InvalidationObjectId,
std::unique_ptr<RegistrationEntry>, std::unique_ptr<RegistrationEntry>,
InvalidationObjectIdLessThan> InvalidationObjectIdLessThan>
registration_statuses_; registration_statuses_;
// Token derrived from GCM IID.
std::string token_;
PrefService* local_state_ = nullptr; PrefService* local_state_ = nullptr;
// OAuth Header. invalidation::IdentityProvider* const identity_provider_;
std::string access_token_; std::string access_token_;
std::unique_ptr<invalidation::ActiveAccountAccessTokenFetcher>
// Token derrived from GCM IID. access_token_fetcher_;
std::string token_; base::OneShotTimer request_access_token_retry_timer_;
net::BackoffEntry request_access_token_backoff_;
// The callback for Parsing JSON. // The callback for Parsing JSON.
ParseJSONCallback parse_json_; ParseJSONCallback parse_json_;
......
...@@ -9,9 +9,11 @@ ...@@ -9,9 +9,11 @@
#include "base/stl_util.h" #include "base/stl_util.h"
#include "base/strings/stringprintf.h" #include "base/strings/stringprintf.h"
#include "components/invalidation/impl/json_unsafe_parser.h" #include "components/invalidation/impl/json_unsafe_parser.h"
#include "components/invalidation/impl/profile_identity_provider.h"
#include "components/invalidation/public/invalidation_util.h" #include "components/invalidation/public/invalidation_util.h"
#include "components/prefs/testing_pref_service.h" #include "components/prefs/testing_pref_service.h"
#include "net/http/http_status_code.h" #include "net/http/http_status_code.h"
#include "services/identity/public/cpp/identity_test_environment.h"
#include "services/network/test/test_url_loader_factory.h" #include "services/network/test/test_url_loader_factory.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "url/gurl.h" #include "url/gurl.h"
...@@ -82,11 +84,16 @@ class PerUserTopicRegistrationManagerTest : public testing::Test { ...@@ -82,11 +84,16 @@ class PerUserTopicRegistrationManagerTest : public testing::Test {
void SetUp() override { void SetUp() override {
PerUserTopicRegistrationManager::RegisterProfilePrefs( PerUserTopicRegistrationManager::RegisterProfilePrefs(
pref_service_.registry()); pref_service_.registry());
identity_test_env_.MakePrimaryAccountAvailable("example@gmail.com");
identity_test_env_.SetAutomaticIssueOfAccessTokens(true);
identity_provider_ =
std::make_unique<invalidation::ProfileIdentityProvider>(
identity_test_env_.identity_manager());
} }
std::unique_ptr<PerUserTopicRegistrationManager> BuildRegistrationManager() { std::unique_ptr<PerUserTopicRegistrationManager> BuildRegistrationManager() {
return std::make_unique<PerUserTopicRegistrationManager>( return std::make_unique<PerUserTopicRegistrationManager>(
"access_token", &pref_service_, url_loader_factory(), identity_provider_.get(), &pref_service_, url_loader_factory(),
base::BindRepeating(&syncer::JsonUnsafeParser::Parse)); base::BindRepeating(&syncer::JsonUnsafeParser::Parse));
} }
...@@ -101,6 +108,9 @@ class PerUserTopicRegistrationManagerTest : public testing::Test { ...@@ -101,6 +108,9 @@ class PerUserTopicRegistrationManagerTest : public testing::Test {
network::TestURLLoaderFactory url_loader_factory_; network::TestURLLoaderFactory url_loader_factory_;
TestingPrefServiceSimple pref_service_; TestingPrefServiceSimple pref_service_;
identity::IdentityTestEnvironment identity_test_env_;
std::unique_ptr<invalidation::IdentityProvider> identity_provider_;
DISALLOW_COPY_AND_ASSIGN(PerUserTopicRegistrationManagerTest); DISALLOW_COPY_AND_ASSIGN(PerUserTopicRegistrationManagerTest);
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment