Commit 1ef34922 authored by Mohamed Amir Yosef's avatar Mohamed Amir Yosef Committed by Commit Bot

[NTP::Push] Support Authenticated subscription requests.

Bug: 735465
Change-Id: I4e1aa8d74be22dd96479f1d5c53e11c89358cfa0
Reviewed-on: https://chromium-review.googlesource.com/562757
Commit-Queue: Mohamed Amir Yosef <mamir@chromium.org>
Reviewed-by: default avatarvitaliii <vitaliii@chromium.org>
Reviewed-by: default avatarBernhard Bauer <bauerb@chromium.org>
Reviewed-by: default avatarMarc Treib <treib@chromium.org>
Cr-Commit-Position: refs/heads/master@{#487036}
parent 64ba6f7e
......@@ -376,18 +376,27 @@ void RegisterForeignSessionsProviderIfEnabled(
service->RegisterProvider(std::move(provider));
}
void SubscribeForGCMPushUpdates(PrefService* pref_service,
ContentSuggestionsService* service,
Profile* profile) {
void SubscribeForGCMPushUpdates(
PrefService* pref_service,
ContentSuggestionsService* content_suggestions_service,
Profile* profile) {
// TODO(mamir): Either pass all params from outside or pass only profile and
// create them inside the method, but be consistent.
gcm::GCMDriver* gcm_driver =
gcm::GCMProfileServiceFactory::GetForProfile(profile)->driver();
OAuth2TokenService* token_service =
ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
SigninManagerBase* signin_manager =
SigninManagerFactory::GetForProfile(profile);
scoped_refptr<net::URLRequestContextGetter> request_context =
content::BrowserContext::GetDefaultStoragePartition(profile)
->GetURLRequestContext();
auto subscription_manager = base::MakeUnique<SubscriptionManager>(
request_context, pref_service,
request_context, pref_service, signin_manager, token_service,
GetPushUpdatesSubscriptionEndpoint(chrome::GetChannel()),
GetPushUpdatesUnsubscriptionEndpoint(chrome::GetChannel()));
......@@ -411,9 +420,10 @@ void SubscribeForGCMPushUpdates(PrefService* pref_service,
base::FilePath database_dir(
profile->GetPath().Append(ntp_snippets::kBreakingNewsDatabaseFolder));
auto provider = base::MakeUnique<BreakingNewsSuggestionsProvider>(
service, std::move(handler), base::MakeUnique<base::DefaultClock>(),
content_suggestions_service, std::move(handler),
base::MakeUnique<base::DefaultClock>(),
base::MakeUnique<RemoteSuggestionsDatabase>(database_dir, task_runner));
service->RegisterProvider(std::move(provider));
content_suggestions_service->RegisterProvider(std::move(provider));
}
} // namespace
......
......@@ -210,6 +210,7 @@ source_set("unit_tests") {
"//components/signin/core/common",
"//components/strings",
"//components/sync:test_support_driver",
"//components/sync_preferences:test_support",
"//components/sync_sessions",
"//components/variations:test_support",
"//components/web_resource:web_resource",
......
......@@ -13,6 +13,7 @@ include_rules = [
"+components/reading_list",
"+components/signin",
"+components/strings/grit/components_strings.h",
"+components/sync_preferences/testing_pref_service_syncable.h",
"+components/sync/driver",
"+components/url_formatter",
"+components/variations",
......
......@@ -60,20 +60,18 @@ void BreakingNewsGCMAppHandler::StopListening() {
DCHECK_EQ(gcm_driver_->GetAppHandler(kBreakingNewsGCMAppID), this);
gcm_driver_->RemoveAppHandler(kBreakingNewsGCMAppID);
on_new_content_callback_ = OnNewContentCallback();
// TODO(mamir): Check which token should be used for unsubscription when
// handling change in the token.
std::string token = pref_service_->GetString(
ntp_snippets::prefs::kBreakingNewsGCMSubscriptionTokenCache);
subscription_manager_->Unsubscribe(token);
subscription_manager_->Unsubscribe();
}
void BreakingNewsGCMAppHandler::Subscribe() {
std::string token = pref_service_->GetString(
ntp_snippets::prefs::kBreakingNewsGCMSubscriptionTokenCache);
// TODO(mamir): This logic should be moved to the SubscriptionManager.
std::string token =
pref_service_->GetString(prefs::kBreakingNewsGCMSubscriptionTokenCache);
// If a token has been already obtained, subscribe directly at the content
// suggestions server.
// suggestions server. Otherwise, obtain a GCM token first.
if (!token.empty()) {
if (!subscription_manager_->IsSubscribed()) {
if (!subscription_manager_->IsSubscribed() ||
subscription_manager_->NeedsToResubscribe()) {
subscription_manager_->Subscribe(token);
}
return;
......@@ -81,19 +79,19 @@ void BreakingNewsGCMAppHandler::Subscribe() {
instance_id_driver_->GetInstanceID(kBreakingNewsGCMAppID)
->GetToken(kBreakingNewsGCMSenderId, kGCMScope,
std::map<std::string, std::string>() /* options */,
/*options=*/std::map<std::string, std::string>(),
base::Bind(&BreakingNewsGCMAppHandler::DidSubscribe,
weak_ptr_factory_.GetWeakPtr()));
}
void BreakingNewsGCMAppHandler::DidSubscribe(const std::string& subscription_id,
InstanceID::Result result) {
void BreakingNewsGCMAppHandler::DidSubscribe(
const std::string& subscription_token,
InstanceID::Result result) {
switch (result) {
case InstanceID::SUCCESS:
pref_service_->SetString(
ntp_snippets::prefs::kBreakingNewsGCMSubscriptionTokenCache,
subscription_id);
subscription_manager_->Subscribe(subscription_id);
pref_service_->SetString(prefs::kBreakingNewsGCMSubscriptionTokenCache,
subscription_token);
subscription_manager_->Subscribe(subscription_token);
return;
case InstanceID::INVALID_PARAMETER:
case InstanceID::DISABLED:
......@@ -112,8 +110,7 @@ void BreakingNewsGCMAppHandler::DidSubscribe(const std::string& subscription_id,
void BreakingNewsGCMAppHandler::ShutdownHandler() {}
void BreakingNewsGCMAppHandler::OnStoreReset() {
pref_service_->ClearPref(
ntp_snippets::prefs::kBreakingNewsGCMSubscriptionTokenCache);
pref_service_->ClearPref(prefs::kBreakingNewsGCMSubscriptionTokenCache);
}
void BreakingNewsGCMAppHandler::OnMessage(const std::string& app_id,
......
......@@ -77,7 +77,7 @@ class BreakingNewsGCMAppHandler : public BreakingNewsListener,
void Subscribe();
// Called after the subscription is obtained from the GCM server.
void DidSubscribe(const std::string& subscription_id,
void DidSubscribe(const std::string& subscription_token,
instance_id::InstanceID::Result result);
// Called after successfully parsing the received suggestion JSON.
......
......@@ -26,13 +26,7 @@ namespace internal {
SubscriptionJsonRequest::SubscriptionJsonRequest() = default;
SubscriptionJsonRequest::~SubscriptionJsonRequest() {
if (!request_completed_callback_.is_null()) {
std::move(request_completed_callback_)
.Run(ntp_snippets::Status(ntp_snippets::StatusCode::TEMPORARY_ERROR,
"cancelled"));
}
}
SubscriptionJsonRequest::~SubscriptionJsonRequest() = default;
void SubscriptionJsonRequest::Start(CompletedCallback callback) {
DCHECK(request_completed_callback_.is_null()) << "Request already running!";
......@@ -49,18 +43,15 @@ void SubscriptionJsonRequest::OnURLFetchComplete(const URLFetcher* source) {
if (!status.is_success()) {
std::move(request_completed_callback_)
.Run(ntp_snippets::Status(
ntp_snippets::StatusCode::TEMPORARY_ERROR,
base::StringPrintf("Internal Error: %d", status.error())));
.Run(Status(StatusCode::TEMPORARY_ERROR,
base::StringPrintf("Network Error: %d", status.error())));
} else if (response != net::HTTP_OK) {
std::move(request_completed_callback_)
.Run(ntp_snippets::Status(
ntp_snippets::StatusCode::PERMANENT_ERROR,
base::StringPrintf("HTTP Error: %d", response)));
.Run(Status(StatusCode::PERMANENT_ERROR,
base::StringPrintf("HTTP Error: %d", response)));
} else {
std::move(request_completed_callback_)
.Run(ntp_snippets::Status(ntp_snippets::StatusCode::SUCCESS,
std::string()));
.Run(Status(StatusCode::SUCCESS, std::string()));
}
}
......@@ -80,9 +71,9 @@ SubscriptionJsonRequest::Builder::Build() const {
request->url_fetcher_ = BuildURLFetcher(request.get(), headers, body);
// Log the request for debugging network issues.
VLOG(1) << "Sending a subscription request to " << url_ << ":\n"
<< headers << "\n"
<< body;
DVLOG(1) << "Building a subscription request to " << url_ << ":\n"
<< headers << "\n"
<< body;
return request;
}
......@@ -106,10 +97,20 @@ SubscriptionJsonRequest::Builder::SetUrlRequestContextGetter(
return *this;
}
SubscriptionJsonRequest::Builder&
SubscriptionJsonRequest::Builder::SetAuthenticationHeader(
const std::string& auth_header) {
auth_header_ = auth_header;
return *this;
}
std::string SubscriptionJsonRequest::Builder::BuildHeaders() const {
HttpRequestHeaders headers;
headers.SetHeader("Content-Type", "application/json; charset=UTF-8");
headers.SetHeader(HttpRequestHeaders::kContentType,
"application/json; charset=UTF-8");
if (!auth_header_.empty()) {
headers.SetHeader(HttpRequestHeaders::kAuthorization, auth_header_);
}
// Add X-Client-Data header with experiment IDs from field trials.
// Note: It's OK to pass |is_signed_in| false if it's unknown, as it does
// not affect transmission of experiments coming from the variations server.
......
......@@ -27,10 +27,9 @@ class SubscriptionJsonRequest : public net::URLFetcherDelegate {
public:
// A client can expect a message in the status only, if there was any error
// during the subscription. In successful cases, it will be an empty string.
using CompletedCallback =
base::OnceCallback<void(const ntp_snippets::Status& status)>;
using CompletedCallback = base::OnceCallback<void(const Status& status)>;
// Builds non-authenticated SubscriptionJsonRequests.
// Builds non-authenticated and authenticated SubscriptionJsonRequests.
class Builder {
public:
Builder();
......@@ -44,6 +43,7 @@ class SubscriptionJsonRequest : public net::URLFetcherDelegate {
Builder& SetUrl(const GURL& url);
Builder& SetUrlRequestContextGetter(
const scoped_refptr<net::URLRequestContextGetter>& context_getter);
Builder& SetAuthenticationHeader(const std::string& auth_header);
private:
std::string BuildHeaders() const;
......@@ -53,18 +53,21 @@ class SubscriptionJsonRequest : public net::URLFetcherDelegate {
const std::string& headers,
const std::string& body) const;
// GCM subscribtion token obtain from GCM driver (instanceID::getToken())
// GCM subscription token obtained from GCM driver (instanceID::getToken()).
std::string token_;
// TODO(mamir): Additional fields to be added: country, language
// TODO(mamir): Additional fields to be added: country, language.
GURL url_;
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
std::string auth_header_;
DISALLOW_COPY_AND_ASSIGN(Builder);
};
~SubscriptionJsonRequest() override;
// Starts an async request. The callback is invoked when the request succeeds,
// fails or gets destroyed.
// Starts an async request. The callback is invoked when the request succeeds
// or fails. The callback is not called if the request is destroyed.
void Start(CompletedCallback callback);
private:
......
......@@ -95,8 +95,6 @@ TEST_F(SubscriptionJsonRequestTest, BuildRequest) {
GURL url("http://valid-url.test");
base::MockCallback<SubscriptionJsonRequest::CompletedCallback> callback;
ntp_snippets::Status status(StatusCode::SUCCESS, "initial");
EXPECT_CALL(callback, Run(_)).WillOnce(SaveArg<0>(&status));
SubscriptionJsonRequest::Builder builder;
std::unique_ptr<SubscriptionJsonRequest> request =
......@@ -126,13 +124,12 @@ TEST_F(SubscriptionJsonRequestTest, BuildRequest) {
EXPECT_THAT(url_fetcher->upload_data(), EqualsJSON(expected_body));
}
TEST_F(SubscriptionJsonRequestTest, InvokesCallbackWhenCancelled) {
TEST_F(SubscriptionJsonRequestTest, ShouldNotInvokeCallbackWhenCancelled) {
std::string token = "1234567890";
GURL url("http://valid-url.test");
base::MockCallback<SubscriptionJsonRequest::CompletedCallback> callback;
ntp_snippets::Status status(StatusCode::SUCCESS, "initial");
EXPECT_CALL(callback, Run(_)).WillOnce(SaveArg<0>(&status));
EXPECT_CALL(callback, Run(_)).Times(0);
SubscriptionJsonRequest::Builder builder;
std::unique_ptr<SubscriptionJsonRequest> request =
......@@ -144,9 +141,6 @@ TEST_F(SubscriptionJsonRequestTest, InvokesCallbackWhenCancelled) {
// Destroy the request before getting any response.
request.reset();
EXPECT_EQ(status.code, StatusCode::TEMPORARY_ERROR);
EXPECT_EQ(status.message, "cancelled");
}
TEST_F(SubscriptionJsonRequestTest, SubscribeWithoutErrors) {
......
......@@ -3,13 +3,18 @@
// found in the LICENSE file.
#include "components/ntp_snippets/breaking_news/subscription_manager.h"
#include "base/bind.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/stringprintf.h"
#include "components/ntp_snippets/breaking_news/subscription_json_request.h"
#include "components/ntp_snippets/features.h"
#include "components/ntp_snippets/ntp_snippets_constants.h"
#include "components/ntp_snippets/pref_names.h"
#include "components/prefs/pref_service.h"
#include "components/signin/core/browser/access_token_fetcher.h"
#include "components/signin/core/browser/signin_manager_base.h"
namespace ntp_snippets {
......@@ -22,109 +27,240 @@ const char kPushSubscriptionBackendParam[] = "push_subscription_backend";
// Variation parameter for chrome-push-unsubscription backend.
const char kPushUnsubscriptionBackendParam[] = "push_unsubscription_backend";
}
const char kAuthorizationRequestHeaderFormat[] = "Bearer %s";
} // namespace
class SubscriptionManager::SigninObserver : public SigninManagerBase::Observer {
public:
SigninObserver(SigninManagerBase* signin_manager,
const base::Closure& signin_status_changed_callback)
: signin_manager_(signin_manager),
signin_status_changed_callback_(signin_status_changed_callback) {
signin_manager_->AddObserver(this);
}
~SigninObserver() override { signin_manager_->RemoveObserver(this); }
private:
// SigninManagerBase::Observer implementation.
void GoogleSigninSucceeded(const std::string& account_id,
const std::string& username) override {
signin_status_changed_callback_.Run();
}
void GoogleSignedOut(const std::string& account_id,
const std::string& username) override {
signin_status_changed_callback_.Run();
}
SigninManagerBase* const signin_manager_;
base::Closure signin_status_changed_callback_;
};
SubscriptionManager::SubscriptionManager(
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
PrefService* pref_service,
SigninManagerBase* signin_manager,
OAuth2TokenService* access_token_service,
const GURL& subscribe_url,
const GURL& unsubscribe_url)
: url_request_context_getter_(std::move(url_request_context_getter)),
pref_service_(pref_service),
signin_manager_(signin_manager),
signin_observer_(base::MakeUnique<SigninObserver>(
signin_manager,
base::Bind(&SubscriptionManager::SigninStatusChanged,
base::Unretained(this)))),
access_token_service_(access_token_service),
subscribe_url_(subscribe_url),
unsubscribe_url_(unsubscribe_url) {}
SubscriptionManager::~SubscriptionManager() = default;
void SubscriptionManager::Subscribe(const std::string& token) {
DCHECK(!subscription_request_);
subscription_token_ = token;
void SubscriptionManager::Subscribe(const std::string& subscription_token) {
// If there is a request in flight, cancel it.
if (request_) {
request_ = nullptr;
}
if (signin_manager_->IsAuthenticated()) {
StartAccessTokenRequest(subscription_token);
} else {
SubscribeInternal(subscription_token, /*access_token=*/std::string());
}
}
void SubscriptionManager::SubscribeInternal(
const std::string& subscription_token,
const std::string& access_token) {
SubscriptionJsonRequest::Builder builder;
builder.SetToken(token)
builder.SetToken(subscription_token)
.SetUrlRequestContextGetter(url_request_context_getter_)
.SetUrl(subscribe_url_);
if (!access_token.empty()) {
builder.SetAuthenticationHeader(base::StringPrintf(
kAuthorizationRequestHeaderFormat, access_token.c_str()));
}
subscription_request_ = builder.Build();
subscription_request_->Start(base::BindOnce(
&SubscriptionManager::DidSubscribe, base::Unretained(this)));
request_ = builder.Build();
request_->Start(base::BindOnce(&SubscriptionManager::DidSubscribe,
base::Unretained(this), subscription_token,
/*is_authenticated=*/!access_token.empty()));
}
bool SubscriptionManager::CanSubscribeNow() {
if (subscription_request_) {
return false;
void SubscriptionManager::StartAccessTokenRequest(
const std::string& subscription_token) {
// If there is already an ongoing token request, destroy it.
if (access_token_fetcher_) {
access_token_fetcher_ = nullptr;
}
return true;
OAuth2TokenService::ScopeSet scopes = {kContentSuggestionsApiScope};
access_token_fetcher_ = base::MakeUnique<AccessTokenFetcher>(
"ntp_snippets", signin_manager_, access_token_service_, scopes,
base::BindOnce(&SubscriptionManager::AccessTokenFetchFinished,
base::Unretained(this), subscription_token));
}
void SubscriptionManager::AccessTokenFetchFinished(
const std::string& subscription_token,
const GoogleServiceAuthError& error,
const std::string& access_token) {
// Delete the fetcher only after we leave this method (which is called from
// the fetcher itself).
std::unique_ptr<AccessTokenFetcher> access_token_fetcher_deleter(
std::move(access_token_fetcher_));
if (error.state() != GoogleServiceAuthError::NONE) {
// In case of error, we will retry on next Chrome restart.
return;
}
DCHECK(!access_token.empty());
SubscribeInternal(subscription_token, access_token);
}
void SubscriptionManager::DidSubscribe(const ntp_snippets::Status& status) {
subscription_request_.reset();
void SubscriptionManager::DidSubscribe(const std::string& subscription_token,
bool is_authenticated,
const Status& status) {
// Delete the request only after we leave this method (which is called from
// the request itself).
std::unique_ptr<internal::SubscriptionJsonRequest> request_deleter(
std::move(request_));
switch (status.code) {
case ntp_snippets::StatusCode::SUCCESS:
case StatusCode::SUCCESS:
// In case of successful subscription, store the same data used for
// subscription in order to be able to re-subscribe in case of data
// subscription in order to be able to resubscribe in case of data
// change.
// TODO(mamir): store region and language.
pref_service_->SetString(
ntp_snippets::prefs::kBreakingNewsSubscriptionDataToken,
subscription_token_);
// TODO(mamir): Store region and language.
pref_service_->SetString(prefs::kBreakingNewsSubscriptionDataToken,
subscription_token);
pref_service_->SetBoolean(
prefs::kBreakingNewsSubscriptionDataIsAuthenticated,
is_authenticated);
break;
default:
// TODO(mamir): handle failure.
// TODO(mamir): Handle failure.
break;
}
}
bool SubscriptionManager::CanUnsubscribeNow() {
if (unsubscription_request_) {
return false;
}
return true;
void SubscriptionManager::Unsubscribe() {
std::string token =
pref_service_->GetString(prefs::kBreakingNewsSubscriptionDataToken);
ResubscribeInternal(/*old_token=*/token, /*new_token=*/std::string());
}
void SubscriptionManager::Unsubscribe(const std::string& token) {
DCHECK(!unsubscription_request_);
unsubscription_token_ = token;
void SubscriptionManager::ResubscribeInternal(const std::string& old_token,
const std::string& new_token) {
// If there is an request in flight, cancel it.
if (request_) {
request_ = nullptr;
}
SubscriptionJsonRequest::Builder builder;
builder.SetToken(token)
builder.SetToken(old_token)
.SetUrlRequestContextGetter(url_request_context_getter_)
.SetUrl(unsubscribe_url_);
unsubscription_request_ = builder.Build();
unsubscription_request_->Start(base::BindOnce(
&SubscriptionManager::DidUnsubscribe, base::Unretained(this)));
request_ = builder.Build();
request_->Start(base::BindOnce(&SubscriptionManager::DidUnsubscribe,
base::Unretained(this), new_token));
}
bool SubscriptionManager::IsSubscribed() {
std::string subscription_token_ = pref_service_->GetString(
ntp_snippets::prefs::kBreakingNewsSubscriptionDataToken);
return !subscription_token_.empty();
std::string subscription_token =
pref_service_->GetString(prefs::kBreakingNewsSubscriptionDataToken);
return !subscription_token.empty();
}
void SubscriptionManager::DidUnsubscribe(const ntp_snippets::Status& status) {
unsubscription_request_.reset();
bool SubscriptionManager::NeedsToResubscribe() {
// Check if authentication state changed after subscription.
bool is_auth_subscribe = pref_service_->GetBoolean(
prefs::kBreakingNewsSubscriptionDataIsAuthenticated);
bool is_authenticated = signin_manager_->IsAuthenticated();
return is_auth_subscribe != is_authenticated;
}
void SubscriptionManager::Resubscribe(const std::string& new_token) {
std::string old_token =
pref_service_->GetString(prefs::kBreakingNewsSubscriptionDataToken);
if (old_token == new_token) {
// If the token didn't change, subscribe directly. The server handles the
// unsubscription if previous subscriptions exists.
Subscribe(old_token);
} else {
ResubscribeInternal(old_token, new_token);
}
}
void SubscriptionManager::DidUnsubscribe(const std::string& new_token,
const Status& status) {
// Delete the request only after we leave this method (which is called from
// the request itself).
std::unique_ptr<internal::SubscriptionJsonRequest> request_deleter(
std::move(request_));
switch (status.code) {
case ntp_snippets::StatusCode::SUCCESS:
case StatusCode::SUCCESS:
// In case of successful unsubscription, clear the previously stored data.
// TODO(mamir): clear stored region and language.
// TODO(mamir): Clear stored region and language.
pref_service_->ClearPref(prefs::kBreakingNewsSubscriptionDataToken);
pref_service_->ClearPref(
ntp_snippets::prefs::kBreakingNewsSubscriptionDataToken);
prefs::kBreakingNewsSubscriptionDataIsAuthenticated);
if (!new_token.empty()) {
Subscribe(new_token);
}
break;
default:
// TODO(mamir): handle failure.
// TODO(mamir): Handle failure.
break;
}
}
void SubscriptionManager::SigninStatusChanged() {
// If subscribed already, resubscribe.
if (IsSubscribed()) {
if (request_) {
request_ = nullptr;
}
std::string token =
pref_service_->GetString(prefs::kBreakingNewsSubscriptionDataToken);
Subscribe(token);
}
}
void SubscriptionManager::RegisterProfilePrefs(PrefRegistrySimple* registry) {
registry->RegisterStringPref(prefs::kBreakingNewsSubscriptionDataToken,
std::string());
registry->RegisterBooleanPref(
prefs::kBreakingNewsSubscriptionDataIsAuthenticated, false);
}
GURL GetPushUpdatesSubscriptionEndpoint(version_info::Channel channel) {
std::string endpoint = base::GetFieldTrialParamValueByFeature(
ntp_snippets::kBreakingNewsPushFeature, kPushSubscriptionBackendParam);
kBreakingNewsPushFeature, kPushSubscriptionBackendParam);
if (!endpoint.empty()) {
return GURL{endpoint};
}
......@@ -145,7 +281,7 @@ GURL GetPushUpdatesSubscriptionEndpoint(version_info::Channel channel) {
GURL GetPushUpdatesUnsubscriptionEndpoint(version_info::Channel channel) {
std::string endpoint = base::GetFieldTrialParamValueByFeature(
ntp_snippets::kBreakingNewsPushFeature, kPushUnsubscriptionBackendParam);
kBreakingNewsPushFeature, kPushUnsubscriptionBackendParam);
if (!endpoint.empty()) {
return GURL{endpoint};
}
......
......@@ -7,10 +7,13 @@
#include "components/ntp_snippets/breaking_news/subscription_json_request.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/signin/core/browser/signin_manager_base.h"
#include "components/version_info/version_info.h"
#include "net/url_request/url_request_context_getter.h"
#include "url/gurl.h"
class AccessTokenFetcher;
class OAuth2TokenService;
class PrefRegistrySimple;
class PrefService;
......@@ -34,38 +37,67 @@ class SubscriptionManager {
SubscriptionManager(
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter,
PrefService* pref_service,
SigninManagerBase* signin_manager,
OAuth2TokenService* access_token_service,
const GURL& subscribe_url,
const GURL& unsubscribe_url);
~SubscriptionManager();
void Subscribe(const std::string& token);
bool CanSubscribeNow();
void Unsubscribe(const std::string& token);
bool CanUnsubscribeNow();
void Unsubscribe();
bool IsSubscribed();
void Resubscribe(const std::string& new_token);
// Checks if some data that has been used when subscribing has changed. For
// example, the user has signed in.
bool NeedsToResubscribe();
static void RegisterProfilePrefs(PrefRegistrySimple* registry);
private:
std::string subscription_token_;
std::string unsubscription_token_;
class SigninObserver;
void SigninStatusChanged();
void DidSubscribe(const std::string& subscription_token,
bool is_authenticated,
const Status& status);
void DidUnsubscribe(const std::string& new_token, const Status& status);
void SubscribeInternal(const std::string& subscription_token,
const std::string& access_token);
// If |new_token| is empty, this will just unsubscribe. If |new_token| is
// non-empty, a subscription request with the |new_token| will be started upon
// successful unsubscription.
void ResubscribeInternal(const std::string& old_token,
const std::string& new_token);
// |subscription_token| is the token when subscribing after obtaining the
// access token.
void StartAccessTokenRequest(const std::string& subscription_token);
void AccessTokenFetchFinished(const std::string& subscription_token,
const GoogleServiceAuthError& error,
const std::string& access_token);
// Holds the URL request context.
scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
std::unique_ptr<internal::SubscriptionJsonRequest> subscription_request_;
std::unique_ptr<internal::SubscriptionJsonRequest> unsubscription_request_;
std::unique_ptr<internal::SubscriptionJsonRequest> request_;
std::unique_ptr<AccessTokenFetcher> access_token_fetcher_;
PrefService* pref_service_;
// Authentication for signed-in users.
SigninManagerBase* signin_manager_;
std::unique_ptr<SigninObserver> signin_observer_;
OAuth2TokenService* access_token_service_;
// API endpoint for subscribing and unsubscribing.
const GURL subscribe_url_;
const GURL unsubscribe_url_;
void DidSubscribe(const ntp_snippets::Status& status);
void DidUnsubscribe(const ntp_snippets::Status& status);
DISALLOW_COPY_AND_ASSIGN(SubscriptionManager);
};
}
......
......@@ -5,30 +5,47 @@
#include "components/ntp_snippets/breaking_news/subscription_manager.h"
#include "base/message_loop/message_loop.h"
#include "build/build_config.h"
#include "components/ntp_snippets/pref_names.h"
#include "components/ntp_snippets/remote/test_utils.h"
#include "components/prefs/testing_pref_service.h"
#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
#include "components/signin/core/browser/fake_signin_manager.h"
#include "components/signin/core/browser/test_signin_client.h"
#include "google_apis/gaia/fake_oauth2_token_service_delegate.h"
#include "net/url_request/test_url_fetcher_factory.h"
#include "net/url_request/url_request_test_util.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace ntp_snippets {
const char kTestEmail[] = "test@email.com";
const char kSubscriptionUrl[] = "http://valid-url.test/subscribe";
const char kUnsubscriptionUrl[] = "http://valid-url.test/unsubscribe";
class SubscriptionManagerTest : public testing::Test {
public:
SubscriptionManagerTest()
: request_context_getter_(
new net::TestURLRequestContextGetter(message_loop_.task_runner())),
pref_service_(base::MakeUnique<TestingPrefServiceSimple>()) {}
new net::TestURLRequestContextGetter(message_loop_.task_runner())) {
}
void SetUp() override {
SubscriptionManager::RegisterProfilePrefs(pref_service_->registry());
SubscriptionManager::RegisterProfilePrefs(
utils_.pref_service()->registry());
}
scoped_refptr<net::URLRequestContextGetter> GetRequestContext() {
return request_context_getter_.get();
}
PrefService* GetPrefService() { return pref_service_.get(); }
PrefService* GetPrefService() { return utils_.pref_service(); }
FakeProfileOAuth2TokenService* GetOAuth2TokenService() {
return utils_.token_service();
}
SigninManagerBase* GetSigninManager() { return utils_.fake_signin_manager(); }
net::TestURLFetcher* GetRunningFetcher() {
// All created TestURLFetchers have ID 0 by default.
......@@ -37,11 +54,53 @@ class SubscriptionManagerTest : public testing::Test {
return url_fetcher;
}
void RespondWithData(const std::string& data) {
void RespondToSubscriptionRequestSuccessfully() {
net::TestURLFetcher* url_fetcher = GetRunningFetcher();
ASSERT_EQ(GURL(kSubscriptionUrl), url_fetcher->GetOriginalURL());
RespondSuccessfully();
}
void RespondToUnsubscriptionRequestSuccessfully() {
net::TestURLFetcher* url_fetcher = GetRunningFetcher();
ASSERT_EQ(GURL(kUnsubscriptionUrl), url_fetcher->GetOriginalURL());
RespondSuccessfully();
}
void RespondToSubscriptionWithError(int error_code) {
net::TestURLFetcher* url_fetcher = GetRunningFetcher();
ASSERT_EQ(GURL(kSubscriptionUrl), url_fetcher->GetOriginalURL());
RespondWithError(error_code);
}
void RespondToUnsubscriptionWithError(int error_code) {
net::TestURLFetcher* url_fetcher = GetRunningFetcher();
ASSERT_EQ(GURL(kUnsubscriptionUrl), url_fetcher->GetOriginalURL());
RespondWithError(error_code);
}
#if !defined(OS_CHROMEOS)
void SignIn() {
utils_.fake_signin_manager()->SignIn(kTestEmail, "user", "pass");
}
void SignOut() { utils_.fake_signin_manager()->ForceSignOut(); }
#endif // !defined(OS_CHROMEOS)
void IssueRefreshToken(FakeProfileOAuth2TokenService* auth_token_service) {
auth_token_service->GetDelegate()->UpdateCredentials(kTestEmail, "token");
}
void IssueAccessToken(FakeProfileOAuth2TokenService* auth_token_service) {
auth_token_service->IssueAllTokensForAccount(kTestEmail, "access_token",
base::Time::Max());
}
private:
void RespondSuccessfully() {
net::TestURLFetcher* url_fetcher = GetRunningFetcher();
url_fetcher->set_status(net::URLRequestStatus());
url_fetcher->set_response_code(net::HTTP_OK);
url_fetcher->SetResponseString(data);
url_fetcher->SetResponseString(std::string());
// Call the URLFetcher delegate to continue the test.
url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
}
......@@ -54,63 +113,185 @@ class SubscriptionManagerTest : public testing::Test {
url_fetcher->delegate()->OnURLFetchComplete(url_fetcher);
}
const std::string url{"http://valid-url.test"};
private:
base::MessageLoop message_loop_;
test::RemoteSuggestionsTestUtils utils_;
scoped_refptr<net::TestURLRequestContextGetter> request_context_getter_;
net::TestURLFetcherFactory url_fetcher_factory_;
std::unique_ptr<TestingPrefServiceSimple> pref_service_;
};
TEST_F(SubscriptionManagerTest, SubscribeSuccessfully) {
std::string token = "1234567890";
SubscriptionManager manager(GetRequestContext(), GetPrefService(), GURL(url),
GURL(url));
manager.Subscribe(token);
RespondWithData("");
EXPECT_TRUE(manager.IsSubscribed());
EXPECT_EQ(GetPrefService()->GetString(
ntp_snippets::prefs::kBreakingNewsSubscriptionDataToken),
token);
std::string subscription_token = "1234567890";
SubscriptionManager manager(GetRequestContext(), GetPrefService(),
GetSigninManager(), GetOAuth2TokenService(),
GURL(kSubscriptionUrl), GURL(kUnsubscriptionUrl));
manager.Subscribe(subscription_token);
RespondToSubscriptionRequestSuccessfully();
ASSERT_TRUE(manager.IsSubscribed());
EXPECT_EQ(subscription_token, GetPrefService()->GetString(
prefs::kBreakingNewsSubscriptionDataToken));
EXPECT_FALSE(GetPrefService()->GetBoolean(
prefs::kBreakingNewsSubscriptionDataIsAuthenticated));
}
// This test is relevant only on non-ChromeOS platforms, as the flow being
// tested here is not possible on ChromeOS.
#if !defined(OS_CHROMEOS)
TEST_F(SubscriptionManagerTest,
ShouldSubscribeWithAuthenticationWhenAuthenticated) {
// Sign in.
FakeProfileOAuth2TokenService* auth_token_service = GetOAuth2TokenService();
SignIn();
IssueRefreshToken(auth_token_service);
// Create manager and subscribe.
std::string subscription_token = "1234567890";
SubscriptionManager manager(GetRequestContext(), GetPrefService(),
GetSigninManager(), auth_token_service,
GURL(kSubscriptionUrl), GURL(kUnsubscriptionUrl));
manager.Subscribe(subscription_token);
// Make sure that subscription is pending an access token.
ASSERT_FALSE(manager.IsSubscribed());
ASSERT_EQ(1u, auth_token_service->GetPendingRequests().size());
// Issue the access token and respond to the subscription request.
IssueAccessToken(auth_token_service);
ASSERT_FALSE(manager.IsSubscribed());
RespondToSubscriptionRequestSuccessfully();
ASSERT_TRUE(manager.IsSubscribed());
// Check that we are now subscribed correctly with authentication.
EXPECT_EQ(subscription_token, GetPrefService()->GetString(
prefs::kBreakingNewsSubscriptionDataToken));
EXPECT_TRUE(GetPrefService()->GetBoolean(
prefs::kBreakingNewsSubscriptionDataIsAuthenticated));
}
#endif
TEST_F(SubscriptionManagerTest, ShouldNotSubscribeIfError) {
std::string subscription_token = "1234567890";
SubscriptionManager manager(GetRequestContext(), GetPrefService(),
GetSigninManager(), GetOAuth2TokenService(),
GURL(kSubscriptionUrl), GURL(kUnsubscriptionUrl));
TEST_F(SubscriptionManagerTest, SubscribeWithErrors) {
std::string token = "1234567890";
SubscriptionManager manager(GetRequestContext(), GetPrefService(), GURL(url),
GURL(url));
manager.Subscribe(token);
RespondWithError(net::ERR_TIMED_OUT);
manager.Subscribe(subscription_token);
RespondToSubscriptionWithError(net::ERR_TIMED_OUT);
EXPECT_FALSE(manager.IsSubscribed());
EXPECT_FALSE(GetPrefService()->HasPrefPath(
ntp_snippets::prefs::kBreakingNewsSubscriptionDataToken));
}
TEST_F(SubscriptionManagerTest, UnsubscribeSuccessfully) {
std::string token = "1234567890";
GetPrefService()->SetString(
ntp_snippets::prefs::kBreakingNewsSubscriptionDataToken, token);
SubscriptionManager manager(GetRequestContext(), GetPrefService(), GURL(url),
GURL(url));
manager.Unsubscribe(token);
RespondWithData("");
std::string subscription_token = "1234567890";
SubscriptionManager manager(GetRequestContext(), GetPrefService(),
GetSigninManager(), GetOAuth2TokenService(),
GURL(kSubscriptionUrl), GURL(kUnsubscriptionUrl));
manager.Subscribe(subscription_token);
RespondToSubscriptionRequestSuccessfully();
ASSERT_TRUE(manager.IsSubscribed());
manager.Unsubscribe();
RespondToUnsubscriptionRequestSuccessfully();
EXPECT_FALSE(manager.IsSubscribed());
EXPECT_FALSE(GetPrefService()->HasPrefPath(
ntp_snippets::prefs::kBreakingNewsSubscriptionDataToken));
EXPECT_FALSE(
GetPrefService()->HasPrefPath(prefs::kBreakingNewsSubscriptionDataToken));
}
TEST_F(SubscriptionManagerTest, UnsubscribeWithErrors) {
std::string token = "1234567890";
GetPrefService()->SetString(
ntp_snippets::prefs::kBreakingNewsSubscriptionDataToken, token);
SubscriptionManager manager(GetRequestContext(), GetPrefService(), GURL(url),
GURL(url));
manager.Unsubscribe(token);
RespondWithError(net::ERR_TIMED_OUT);
EXPECT_TRUE(manager.IsSubscribed());
EXPECT_EQ(GetPrefService()->GetString(
ntp_snippets::prefs::kBreakingNewsSubscriptionDataToken),
token);
TEST_F(SubscriptionManagerTest,
ShouldRemainSubscribedIfErrorDuringUnsubscribe) {
std::string subscription_token = "1234567890";
SubscriptionManager manager(GetRequestContext(), GetPrefService(),
GetSigninManager(), GetOAuth2TokenService(),
GURL(kSubscriptionUrl), GURL(kUnsubscriptionUrl));
manager.Subscribe(subscription_token);
RespondToSubscriptionRequestSuccessfully();
ASSERT_TRUE(manager.IsSubscribed());
manager.Unsubscribe();
RespondToUnsubscriptionWithError(net::ERR_TIMED_OUT);
ASSERT_TRUE(manager.IsSubscribed());
EXPECT_EQ(subscription_token, GetPrefService()->GetString(
prefs::kBreakingNewsSubscriptionDataToken));
}
// This test is relevant only on non-ChromeOS platforms, as the flow being
// tested here is not possible on ChromeOS.
#if !defined(OS_CHROMEOS)
TEST_F(SubscriptionManagerTest, ShouldResubscribeIfSignInAfterSubscription) {
// Create manager and subscribe.
FakeProfileOAuth2TokenService* auth_token_service = GetOAuth2TokenService();
std::string subscription_token = "1234567890";
SubscriptionManager manager(GetRequestContext(), GetPrefService(),
GetSigninManager(), auth_token_service,
GURL(kSubscriptionUrl), GURL(kUnsubscriptionUrl));
manager.Subscribe(subscription_token);
RespondToSubscriptionRequestSuccessfully();
ASSERT_FALSE(manager.NeedsToResubscribe());
// Sign in. This should trigger a resubscribe.
SignIn();
IssueRefreshToken(auth_token_service);
ASSERT_TRUE(manager.NeedsToResubscribe());
ASSERT_EQ(1u, auth_token_service->GetPendingRequests().size());
IssueAccessToken(auth_token_service);
RespondToSubscriptionRequestSuccessfully();
// Check that we are now subscribed with authentication.
EXPECT_TRUE(GetPrefService()->GetBoolean(
prefs::kBreakingNewsSubscriptionDataIsAuthenticated));
}
#endif
// This test is relevant only on non-ChromeOS platforms, as the flow being
// tested here is not possible on ChromeOS.
#if !defined(OS_CHROMEOS)
TEST_F(SubscriptionManagerTest, ShouldResubscribeIfSignOutAfterSubscription) {
// Signin and subscribe.
FakeProfileOAuth2TokenService* auth_token_service = GetOAuth2TokenService();
SignIn();
IssueRefreshToken(auth_token_service);
std::string subscription_token = "1234567890";
SubscriptionManager manager(GetRequestContext(), GetPrefService(),
GetSigninManager(), auth_token_service,
GURL(kSubscriptionUrl), GURL(kUnsubscriptionUrl));
manager.Subscribe(subscription_token);
ASSERT_EQ(1u, auth_token_service->GetPendingRequests().size());
IssueAccessToken(auth_token_service);
RespondToSubscriptionRequestSuccessfully();
// Signout, this should trigger a resubscribe.
SignOut();
EXPECT_TRUE(manager.NeedsToResubscribe());
RespondToSubscriptionRequestSuccessfully();
// Check that we are now subscribed without authentication.
EXPECT_FALSE(GetPrefService()->GetBoolean(
prefs::kBreakingNewsSubscriptionDataIsAuthenticated));
}
#endif
TEST_F(SubscriptionManagerTest,
ShouldUpdateTokenInPrefWhenResubscribeWithChangeInToken) {
// Create manager and subscribe.
std::string old_subscription_token = "1234567890";
SubscriptionManager manager(GetRequestContext(), GetPrefService(),
GetSigninManager(), GetOAuth2TokenService(),
GURL(kSubscriptionUrl), GURL(kUnsubscriptionUrl));
manager.Subscribe(old_subscription_token);
RespondToSubscriptionRequestSuccessfully();
EXPECT_EQ(
old_subscription_token,
GetPrefService()->GetString(prefs::kBreakingNewsSubscriptionDataToken));
// Resubscribe with a new token.
std::string new_subscription_token = "0987654321";
manager.Resubscribe(new_subscription_token);
// Resubscribe with a new token should issue an unsubscribe request before
// subscribing.
RespondToUnsubscriptionRequestSuccessfully();
RespondToSubscriptionRequestSuccessfully();
// Check we are now subscribed with the new token.
EXPECT_EQ(
new_subscription_token,
GetPrefService()->GetString(prefs::kBreakingNewsSubscriptionDataToken));
}
} // namespace ntp_snippets
......@@ -12,6 +12,9 @@ const base::FilePath::CharType kDatabaseFolder[] =
const base::FilePath::CharType kBreakingNewsDatabaseFolder[] =
FILE_PATH_LITERAL("NTPBreakingNews");
const char kContentSuggestionsApiScope[] =
"https://www.googleapis.com/auth/chrome-content-suggestions";
const char kContentSuggestionsServer[] =
"https://chromecontentsuggestions-pa.googleapis.com/v1/suggestions/fetch";
const char kContentSuggestionsStagingServer[] =
......
......@@ -16,6 +16,9 @@ extern const base::FilePath::CharType kDatabaseFolder[];
// TODO(mamir): Check if the same DB can be used.
extern const base::FilePath::CharType kBreakingNewsDatabaseFolder[];
// OAuth access token scope.
extern const char kContentSuggestionsApiScope[];
// Server endpoints for fetching snippets.
extern const char kContentSuggestionsServer[]; // used on stable/beta
extern const char kContentSuggestionsStagingServer[]; // used on dev/canary
......
......@@ -84,6 +84,9 @@ const char kClickBasedCategoryRankerLastDecayTime[] =
const char kBreakingNewsSubscriptionDataToken[] =
"ntp_suggestions.breaking_news_subscription_data.token";
const char kBreakingNewsSubscriptionDataIsAuthenticated[] =
"ntp_suggestions.breaking_news_subscription_data.is_authenticated";
const char kBreakingNewsGCMSubscriptionTokenCache[] =
"ntp_suggestions.breaking_news_gcm_subscription_token_cache";
......
......@@ -93,10 +93,13 @@ extern const char kClickBasedCategoryRankerLastDecayTime[];
// The folllowing prefs hold the data used when subscribing for content
// suggestions via GCM push updates. They are stored in pref such that in case
// of change (e.g. the token renders invalid), re-subscription is required.
// They are stored in prefs for persisting them across Chrome restarts.
///////////////////////////////////////////////////////////////////////////////
// The pref name for the subscription token used when subscription for
// breaking news push updates.
extern const char kBreakingNewsSubscriptionDataToken[];
// The pref name for whether the subscription is authenticated or not.
extern const char kBreakingNewsSubscriptionDataIsAuthenticated[];
//////////////////////// End of breaking news subscription-related prefs.
// The pref name for the subscription token received from the gcm server. As
......
......@@ -13,6 +13,7 @@
#include "base/values.h"
#include "components/language/core/browser/url_language_histogram.h"
#include "components/ntp_snippets/category.h"
#include "components/ntp_snippets/ntp_snippets_constants.h"
#include "components/ntp_snippets/user_classifier.h"
#include "components/signin/core/browser/access_token_fetcher.h"
#include "components/signin/core/browser/signin_manager_base.h"
......@@ -32,8 +33,6 @@ using internal::JsonRequest;
namespace {
const char kContentSuggestionsApiScope[] =
"https://www.googleapis.com/auth/chrome-content-suggestions";
const char kSnippetsServerNonAuthorizedFormat[] = "%s?key=%s";
const char kAuthorizationRequestHeaderFormat[] = "Bearer %s";
......
......@@ -18,6 +18,7 @@
#include "base/time/default_clock.h"
#include "base/time/time.h"
#include "base/values.h"
#include "build/build_config.h"
#include "components/ntp_snippets/category.h"
#include "components/ntp_snippets/features.h"
#include "components/ntp_snippets/ntp_snippets_constants.h"
......@@ -298,7 +299,13 @@ class RemoteSuggestionsFetcherImplTestBase : public testing::Test {
fetcher_->SetClockForTesting(mock_task_runner_->GetMockClock());
}
void SignIn() { utils_.fake_signin_manager()->SignIn(kTestEmail); }
void SignIn() {
#if defined(OS_CHROMEOS)
utils_.fake_signin_manager()->SignIn(kTestEmail);
#else
utils_.fake_signin_manager()->SignIn(kTestEmail, "user", "password");
#endif
}
void IssueRefreshToken() {
fake_token_service_->GetDelegate()->UpdateCredentials(kTestEmail, "token");
......
......@@ -29,8 +29,8 @@
#include "components/ntp_snippets/remote/test_utils.h"
#include "components/ntp_snippets/status.h"
#include "components/ntp_snippets/user_classifier.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "components/variations/variations_params_manager.h"
#include "components/web_resource/web_resource_pref_names.h"
#include "net/base/network_change_notifier.h"
......
......@@ -7,16 +7,17 @@
#include <memory>
#include "base/memory/ptr_util.h"
#include "build/build_config.h"
#include "components/ntp_snippets/features.h"
#include "components/ntp_snippets/ntp_snippets_constants.h"
#include "components/ntp_snippets/pref_names.h"
#include "components/ntp_snippets/remote/test_utils.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "components/signin/core/browser/account_tracker_service.h"
#include "components/signin/core/browser/fake_signin_manager.h"
#include "components/signin/core/browser/test_signin_client.h"
#include "components/signin/core/common/signin_pref_names.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "components/variations/variations_params_manager.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
......@@ -48,7 +49,11 @@ TEST_F(RemoteSuggestionsStatusServiceTest, NoSigninNeeded) {
service->GetStatusFromDeps());
// One can still sign in.
#if defined(OS_CHROMEOS)
utils_.fake_signin_manager()->SignIn("foo@bar.com");
#else
utils_.fake_signin_manager()->SignIn("foo@bar.com", "user", "pass");
#endif
EXPECT_EQ(RemoteSuggestionsStatus::ENABLED_AND_SIGNED_IN,
service->GetStatusFromDeps());
}
......@@ -66,7 +71,11 @@ TEST_F(RemoteSuggestionsStatusServiceTest, DisabledViaPref) {
service->GetStatusFromDeps());
// The other dependencies shouldn't matter anymore.
#if defined(OS_CHROMEOS)
utils_.fake_signin_manager()->SignIn("foo@bar.com");
#else
utils_.fake_signin_manager()->SignIn("foo@bar.com", "user", "pass");
#endif
EXPECT_EQ(RemoteSuggestionsStatus::EXPLICITLY_DISABLED,
service->GetStatusFromDeps());
}
......
......@@ -7,10 +7,9 @@
#include <memory>
#include "base/memory/ptr_util.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/testing_pref_service.h"
#include "components/signin/core/browser/account_tracker_service.h"
#include "components/signin/core/browser/fake_signin_manager.h"
#include "components/signin/core/browser/fake_profile_oauth2_token_service.h"
#include "components/signin/core/browser/test_signin_client.h"
#include "components/signin/core/common/signin_pref_names.h"
#include "components/sync/driver/fake_sync_service.h"
......@@ -48,24 +47,37 @@ syncer::ModelTypeSet FakeSyncService::GetActiveDataTypes() const {
}
RemoteSuggestionsTestUtils::RemoteSuggestionsTestUtils()
: pref_service_(base::MakeUnique<TestingPrefServiceSimple>()) {
pref_service_->registry()->RegisterStringPref(prefs::kGoogleServicesAccountId,
std::string());
pref_service_->registry()->RegisterStringPref(
prefs::kGoogleServicesLastAccountId, std::string());
pref_service_->registry()->RegisterStringPref(
prefs::kGoogleServicesLastUsername, std::string());
: pref_service_(base::MakeUnique<TestingPrefServiceSyncable>()) {
AccountTrackerService::RegisterPrefs(pref_service_->registry());
#if defined(OS_CHROMEOS)
SigninManagerBase::RegisterProfilePrefs(pref_service_->registry());
SigninManagerBase::RegisterPrefs(pref_service_->registry());
#else
SigninManager::RegisterProfilePrefs(pref_service_->registry());
SigninManager::RegisterPrefs(pref_service_->registry());
#endif // OS_CHROMEOS
token_service_ = base::MakeUnique<FakeProfileOAuth2TokenService>();
signin_client_ = base::MakeUnique<TestSigninClient>(pref_service_.get());
account_tracker_ = base::MakeUnique<AccountTrackerService>();
account_tracker_->Initialize(signin_client_.get());
fake_sync_service_ = base::MakeUnique<FakeSyncService>();
ResetSigninManager();
}
RemoteSuggestionsTestUtils::~RemoteSuggestionsTestUtils() = default;
void RemoteSuggestionsTestUtils::ResetSigninManager() {
#if defined(OS_CHROMEOS)
fake_signin_manager_ = base::MakeUnique<FakeSigninManagerBase>(
signin_client_.get(), account_tracker_.get());
#else
fake_signin_manager_ = base::MakeUnique<FakeSigninManager>(
signin_client_.get(), token_service_.get(), account_tracker_.get(),
/*cookie_manager_service=*/nullptr);
#endif
}
} // namespace test
......
......@@ -7,14 +7,25 @@
#include <memory>
#include "build/build_config.h"
#include "components/signin/core/browser/fake_signin_manager.h"
#include "components/sync/driver/fake_sync_service.h"
#include "components/sync_preferences/testing_pref_service_syncable.h"
#include "testing/gtest/include/gtest/gtest.h"
class AccountTrackerService;
class FakeSigninManagerBase;
class TestingPrefServiceSimple;
class FakeProfileOAuth2TokenService;
class TestSigninClient;
using sync_preferences::TestingPrefServiceSyncable;
#if defined(OS_CHROMEOS)
// ChromeOS doesn't have SigninManager.
using SigninManagerForTest = FakeSigninManagerBase;
#else
using SigninManagerForTest = FakeSigninManager;
#endif // OS_CHROMEOS
namespace ntp_snippets {
namespace test {
......@@ -46,15 +57,19 @@ class RemoteSuggestionsTestUtils {
void ResetSigninManager();
FakeSyncService* fake_sync_service() { return fake_sync_service_.get(); }
FakeSigninManagerBase* fake_signin_manager() {
SigninManagerForTest* fake_signin_manager() {
return fake_signin_manager_.get();
}
TestingPrefServiceSimple* pref_service() { return pref_service_.get(); }
TestingPrefServiceSyncable* pref_service() { return pref_service_.get(); }
FakeProfileOAuth2TokenService* token_service() {
return token_service_.get();
}
private:
std::unique_ptr<FakeSigninManagerBase> fake_signin_manager_;
std::unique_ptr<SigninManagerForTest> fake_signin_manager_;
std::unique_ptr<FakeSyncService> fake_sync_service_;
std::unique_ptr<TestingPrefServiceSimple> pref_service_;
std::unique_ptr<TestingPrefServiceSyncable> pref_service_;
std::unique_ptr<FakeProfileOAuth2TokenService> token_service_;
std::unique_ptr<TestSigninClient> signin_client_;
std::unique_ptr<AccountTrackerService> account_tracker_;
};
......
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