Commit e2609903 authored by dizg's avatar dizg Committed by Commit Bot

[signin] Browser test for supporting OAuth outage in Dice.

Bug: 1115247
Change-Id: I0b4c90250ea532b6d8d427437073a785b54b8515
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2373082Reviewed-by: default avatarMonica Basta <msalama@chromium.org>
Reviewed-by: default avatarDavid Roger <droger@chromium.org>
Commit-Queue: Diana Zagidullina <dizg@google.com>
Cr-Commit-Position: refs/heads/master@{#801770}
parent bbce185d
......@@ -18,6 +18,8 @@
#include "base/run_loop.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/stringprintf.h"
#include "base/test/scoped_feature_list.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
#include "build/build_config.h"
......@@ -35,6 +37,7 @@
#include "chrome/browser/signin/chrome_signin_client.h"
#include "chrome/browser/signin/chrome_signin_client_factory.h"
#include "chrome/browser/signin/chrome_signin_helper.h"
#include "chrome/browser/signin/dice_response_handler.h"
#include "chrome/browser/signin/identity_manager_factory.h"
#include "chrome/browser/signin/signin_util.h"
#include "chrome/browser/sync/user_event_service_factory.h"
......@@ -110,6 +113,7 @@ const char kOAuth2TokenExchangeURL[] = "/oauth2/v4/token";
const char kOAuth2TokenRevokeURL[] = "/o/oauth2/revoke";
const char kSecondaryEmail[] = "secondary_email@example.com";
const char kSigninURL[] = "/signin";
const char kSigninWithOutageInDiceURL[] = "/signin/outage";
const char kSignoutURL[] = "/signout";
// Test response that does not complete synchronously. It must be unblocked by
......@@ -153,7 +157,8 @@ std::unique_ptr<HttpResponse> HandleSigninURL(
const base::RepeatingCallback<void(const std::string&)>& callback,
const HttpRequest& request) {
if (!net::test_server::ShouldHandle(request, kSigninURL) &&
!net::test_server::ShouldHandle(request, kChromeSyncEndpointURL))
!net::test_server::ShouldHandle(request, kChromeSyncEndpointURL) &&
!net::test_server::ShouldHandle(request, kSigninWithOutageInDiceURL))
return nullptr;
// Extract Dice request header.
......@@ -168,12 +173,21 @@ std::unique_ptr<HttpResponse> HandleSigninURL(
// Add the SIGNIN dice header.
std::unique_ptr<BasicHttpResponse> http_response(new BasicHttpResponse);
if (header_value != kNoDiceRequestHeader) {
http_response->AddCustomHeader(
kDiceResponseHeader,
base::StringPrintf(
"action=SIGNIN,authuser=1,id=%s,email=%s,authorization_code=%s",
signin::GetTestGaiaIdForEmail(main_email).c_str(),
main_email.c_str(), kAuthorizationCode));
if (net::test_server::ShouldHandle(request, kSigninWithOutageInDiceURL)) {
http_response->AddCustomHeader(
kDiceResponseHeader,
base::StringPrintf("action=SIGNIN,authuser=1,id=%s,email=%s,"
"no_authorization_code=true",
signin::GetTestGaiaIdForEmail(main_email).c_str(),
main_email.c_str()));
} else {
http_response->AddCustomHeader(
kDiceResponseHeader,
base::StringPrintf(
"action=SIGNIN,authuser=1,id=%s,email=%s,authorization_code=%s",
signin::GetTestGaiaIdForEmail(main_email).c_str(),
main_email.c_str(), kAuthorizationCode));
}
}
// When hitting the Chrome Sync endpoint, redirect to kEnableSyncURL, which
......@@ -331,6 +345,7 @@ class DiceBrowserTest : public InProcessBrowserTest,
reconcilor_blocked_count_(0),
reconcilor_unblocked_count_(0),
reconcilor_started_count_(0) {
feature_list_.InitAndEnableFeature(kSupportOAuthOutageInDice);
https_server_.RegisterDefaultHandler(base::BindRepeating(
&FakeGaia::HandleSigninURL, main_email_,
base::BindRepeating(&DiceBrowserTest::OnSigninRequest,
......@@ -601,6 +616,10 @@ class DiceBrowserTest : public InProcessBrowserTest,
EXPECT_EQ(count, token_revoked_count_);
}
DiceResponseHandler* GetDiceResponseHandler() {
return DiceResponseHandler::GetForProfile(browser()->profile());
}
const std::string main_email_;
net::EmbeddedTestServer https_server_;
bool enable_sync_requested_;
......@@ -612,6 +631,7 @@ class DiceBrowserTest : public InProcessBrowserTest,
int reconcilor_unblocked_count_;
int reconcilor_started_count_;
std::string dice_request_header_;
base::test::ScopedFeatureList feature_list_;
// Unblocks the server responses.
base::OnceClosure unblock_token_exchange_response_closure_;
......@@ -659,6 +679,34 @@ IN_PROC_BROWSER_TEST_F(DiceBrowserTest, Signin) {
EXPECT_EQ(1, reconcilor_started_count_);
}
// Checks that the account reconcilor is blocked when where was OAuth
// outage in Dice, and unblocked after the timeout.
IN_PROC_BROWSER_TEST_F(DiceBrowserTest, SupportOAuthOutageInDice) {
DiceResponseHandler* dice_response_handler = GetDiceResponseHandler();
scoped_refptr<base::TestMockTimeTaskRunner> task_runner =
new base::TestMockTimeTaskRunner();
dice_response_handler->SetTaskRunner(task_runner);
NavigateToURL(kSigninWithOutageInDiceURL);
// Check that the Dice request header was sent.
std::string client_id = GaiaUrls::GetInstance()->oauth2_chrome_client_id();
EXPECT_EQ(base::StringPrintf("version=%s,client_id=%s,device_id=%s,"
"signin_mode=all_accounts,"
"signout_mode=show_confirmation",
signin::kDiceProtocolVersion, client_id.c_str(),
GetDeviceId().c_str()),
dice_request_header_);
// Check that the reconcilor was blocked and not unblocked before timeout.
EXPECT_EQ(1, reconcilor_blocked_count_);
EXPECT_EQ(0, reconcilor_unblocked_count_);
task_runner->FastForwardBy(
base::TimeDelta::FromHours(kLockAccountReconcilorTimeoutHours / 2));
EXPECT_EQ(0, reconcilor_unblocked_count_);
task_runner->FastForwardBy(
base::TimeDelta::FromHours((kLockAccountReconcilorTimeoutHours + 1) / 2));
// Check that the reconcilor was unblocked.
EXPECT_EQ(1, reconcilor_unblocked_count_);
}
// Checks that re-auth on Gaia triggers the fetch for a refresh token.
IN_PROC_BROWSER_TEST_F(DiceBrowserTest, Reauth) {
EXPECT_EQ(0, reconcilor_started_count_);
......
......@@ -262,6 +262,11 @@ void DiceResponseHandler::OnTimeoutUnlockReconcilor() {
lock_.reset();
}
void DiceResponseHandler::SetTaskRunner(
scoped_refptr<base::SequencedTaskRunner> task_runner) {
task_runner_ = std::move(task_runner);
}
void DiceResponseHandler::ProcessDiceSigninHeader(
const std::string& gaia_id,
const std::string& email,
......@@ -271,9 +276,14 @@ void DiceResponseHandler::ProcessDiceSigninHeader(
if (no_authorization_code) {
if (base::FeatureList::IsEnabled(kSupportOAuthOutageInDice)) {
lock_ = std::make_unique<AccountReconcilor::Lock>(account_reconcilor_);
if (!timer_) {
timer_ = std::make_unique<base::OneShotTimer>();
if (task_runner_)
timer_->SetTaskRunner(task_runner_);
}
// If there is already another lock, the timer will be reset and
// we'll wait another full timeout.
timer_.Start(
timer_->Start(
FROM_HERE,
base::TimeDelta::FromHours(kLockAccountReconcilorTimeoutHours),
base::BindOnce(&DiceResponseHandler::OnTimeoutUnlockReconcilor,
......
......@@ -12,6 +12,9 @@
#include "base/cancelable_callback.h"
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/scoped_refptr.h"
#include "base/sequenced_task_runner.h"
#include "base/timer/timer.h"
#include "components/keyed_service/core/keyed_service.h"
#include "components/signin/core/browser/account_reconcilor.h"
#include "components/signin/core/browser/signin_header_helper.h"
......@@ -79,6 +82,9 @@ class DiceResponseHandler : public KeyedService {
// Returns the number of pending DiceTokenFetchers. Exposed for testing.
size_t GetPendingDiceTokenFetchersCountForTesting() const;
// Sets |task_runner_| for testing.
void SetTaskRunner(scoped_refptr<base::SequencedTaskRunner> task_runner);
private:
// Helper class to fetch a refresh token from an authorization code.
class DiceTokenFetcher : public GaiaAuthConsumer {
......@@ -168,8 +174,8 @@ class DiceResponseHandler : public KeyedService {
// Lock the account reconcilor for kLockAccountReconcilorTimeoutHours
// when there was OAuth outage in Dice.
std::unique_ptr<AccountReconcilor::Lock> lock_;
base::OneShotTimer timer_;
std::unique_ptr<base::OneShotTimer> timer_;
scoped_refptr<base::SequencedTaskRunner> task_runner_;
DISALLOW_COPY_AND_ASSIGN(DiceResponseHandler);
};
......
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