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