summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authortim@chromium.org <tim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-11 21:57:27 +0000
committertim@chromium.org <tim@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-10-11 21:57:27 +0000
commit96209ccda702ea92fd257a17d8a70f93bce0ddb5 (patch)
tree65c94e91dc281bf8ed5f66a7c3f28a270f09ac6f
parentf0b97f1ddf05cdca3cbba263ba663a2cc1ace7b3 (diff)
downloadchromium_src-96209ccda702ea92fd257a17d8a70f93bce0ddb5.zip
chromium_src-96209ccda702ea92fd257a17d8a70f93bce0ddb5.tar.gz
chromium_src-96209ccda702ea92fd257a17d8a70f93bce0ddb5.tar.bz2
sync: second factor auth support
BUG=58712 TEST=Sign in to sync with two-step verification account. SigninManagerTest. Review URL: http://codereview.chromium.org/3702002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@62191 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/app/generated_resources.grd9
-rw-r--r--chrome/app/resources/locale_settings.grd4
-rw-r--r--chrome/browser/sync/profile_sync_service.cc8
-rw-r--r--chrome/browser/sync/profile_sync_service.h3
-rw-r--r--chrome/browser/sync/resources/gaia_login.html95
-rw-r--r--chrome/browser/sync/signin_manager.cc37
-rw-r--r--chrome/browser/sync/signin_manager.h11
-rw-r--r--chrome/browser/sync/signin_manager_unittest.cc47
-rw-r--r--chrome/browser/sync/sync_setup_flow.cc14
-rw-r--r--chrome/browser/sync/sync_setup_flow.h5
-rw-r--r--chrome/browser/sync/sync_setup_wizard.cc11
-rw-r--r--chrome/browser/sync/sync_setup_wizard_unittest.cc6
12 files changed, 220 insertions, 30 deletions
diff --git a/chrome/app/generated_resources.grd b/chrome/app/generated_resources.grd
index 592c6c3..dd54f07 100644
--- a/chrome/app/generated_resources.grd
+++ b/chrome/app/generated_resources.grd
@@ -7908,6 +7908,15 @@ Keep your key file in a safe place. You will need it to create new versions of y
<message name="IDS_SYNC_LOGIN_ACCOUNT_MISMATCH" desc="A warning message shown at sync login when the user is signed in to the web store already.">
Your web store account is <ph name="EMAIL_ADDRESS">$1<ex>user@gmail.com</ex></ph> - signing in to sync with a different account will result in incompatibilities.
</message>
+ <message name="IDS_SYNC_ENTER_ACCESS_CODE_LABEL" desc="A message asking the user to enter a second factor access code.">
+ Please enter your access code:
+ </message>
+ <message name="IDS_SYNC_ACCESS_CODE_HELP_LABEL" desc="A help link message for users who don't know what an access code is">
+ What's this?
+ </message>
+ <message name="IDS_SYNC_INVALID_ACCESS_CODE_LABEL" desc="A message telling the user the access code they entered is invalid.">
+ Invalid access code.
+ </message>
<!-- Sync app menu item strings -->
<if expr="not pp_ifdef('use_titlecase')">
diff --git a/chrome/app/resources/locale_settings.grd b/chrome/app/resources/locale_settings.grd
index 074b3bc..305f0b5 100644
--- a/chrome/app/resources/locale_settings.grd
+++ b/chrome/app/resources/locale_settings.grd
@@ -600,6 +600,10 @@
15
</message>
+ <message name="IDS_SYNC_GET_ACCESS_CODE_URL" translateable="false">
+ https://www.google.com/accounts/IssuedAuthSubTokens?hl=[GRITLANGCODE]
+ </message>
+
<!-- The default width/height for confirmation dialogs. -->
<message name="IDS_CONFIRM_MESSAGE_BOX_DEFAULT_WIDTH_CHARS" use_name_for_id="true">
50
diff --git a/chrome/browser/sync/profile_sync_service.cc b/chrome/browser/sync/profile_sync_service.cc
index 01f03bb..18b47cf 100644
--- a/chrome/browser/sync/profile_sync_service.cc
+++ b/chrome/browser/sync/profile_sync_service.cc
@@ -712,7 +712,7 @@ string16 ProfileSyncService::GetAuthenticatedUsername() const {
void ProfileSyncService::OnUserSubmittedAuth(
const std::string& username, const std::string& password,
- const std::string& captcha) {
+ const std::string& captcha, const std::string& access_code) {
last_attempted_user_email_ = username;
is_auth_in_progress_ = true;
FOR_EACH_OBSERVER(Observer, observers_, OnStateChanged());
@@ -726,9 +726,15 @@ void ProfileSyncService::OnUserSubmittedAuth(
LOG(WARNING) << "No mechanism on ChromeOS yet. See http://crbug.com/50292";
}
+ if (!access_code.empty()) {
+ signin_.ProvideSecondFactorAccessCode(access_code);
+ return;
+ }
+
if (!signin_.GetUsername().empty()) {
signin_.SignOut();
}
+
signin_.StartSignIn(username,
password,
last_auth_error_.captcha().token,
diff --git a/chrome/browser/sync/profile_sync_service.h b/chrome/browser/sync/profile_sync_service.h
index 5a889f1..8041ec0 100644
--- a/chrome/browser/sync/profile_sync_service.h
+++ b/chrome/browser/sync/profile_sync_service.h
@@ -184,7 +184,8 @@ class ProfileSyncService : public browser_sync::SyncFrontend,
// Called when a user enters credentials through UI.
virtual void OnUserSubmittedAuth(const std::string& username,
const std::string& password,
- const std::string& captcha);
+ const std::string& captcha,
+ const std::string& access_code);
// Update the last auth error and notify observers of error state.
void UpdateAuthErrorState(const GoogleServiceAuthError& error);
diff --git a/chrome/browser/sync/resources/gaia_login.html b/chrome/browser/sync/resources/gaia_login.html
index 7834942..7dcd684 100644
--- a/chrome/browser/sync/resources/gaia_login.html
+++ b/chrome/browser/sync/resources/gaia_login.html
@@ -106,6 +106,19 @@
#content_table {
padding: 2px;
}
+ .access_code_row {
+ display: none;
+ }
+ .access_code_row > td {
+ text-align: center;
+ padding-bottom: 1px;
+ }
+ #access_code_label_row > td {
+ padding-top: 6px;
+ }
+ .centeredtext {
+ text-align: center;
+ }
</style>
</head>
<body bgcolor="#ffffff" vlink="#666666"
@@ -173,11 +186,19 @@
var span = document.getElementById('email_readonly');
span.appendChild(document.createTextNode(f.Email.value));
span.style.display = 'inline';
- setElementDisplay("createaccountdiv", "none");
- }
- }
- if (1 == args.error) {
- setElementDisplay("errormsg_1_Password", 'table-row');
+ setElementDisplay("createaccountdiv", "none");
+ }
+
+ f.AccessCode.disabled = true;
+ }
+ if (1 == args.error) {
+ var access_code = document.getElementById('AccessCode');
+ if (access_code.value && access_code.value != "") {
+ setElementDisplay("errormsg_0_AccessCode", 'block');
+ showAccessCodeRequired();
+ } else {
+ setElementDisplay("errormsg_1_Password", 'table-row');
+ }
setBlurbError();
}
if (3 == args.error) {
@@ -185,7 +206,10 @@
setBlurbError();
}
if (4 == args.error) {
- showCaptcha(args);
+ showCaptcha(args);
+ }
+ if (8 == args.error) {
+ showAccessCodeRequired();
}
document.getElementById("signIn").disabled = false;
document.getElementById("signIn").value = templateData['signin'];
@@ -195,8 +219,9 @@
function showCaptcha(args) {
g_is_captcha_challenge_active = true;
- // The captcha takes up lots of space, so make room.
- setElementDisplay("top_blurb", "none");
+ // The captcha takes up lots of space, so make room.
+ setElementDisplay("top_blurb", "none");
+ setElementDisplay("top_blurb_error", "none");
setElementDisplay("createaccountdiv", "none");
var gaiaTable = document.getElementById('gaia_table');
gaiaTable.cellPadding = 0;
@@ -212,6 +237,18 @@
document.getElementById('CaptchaValue').disabled = false;
document.getElementById('captcha_wrapper').style.backgroundImage =
url(args.captchaUrl);
+ }
+
+ function showAccessCodeRequired() {
+ setElementDisplay("password_row", "none");
+ setElementDisplay("email_row", "none");
+ document.getElementById("createaccountcell").style.visibility =
+ "hidden";
+
+ setElementDisplay("access_code_label_row", "table-row");
+ setElementDisplay("access_code_input_row", "table-row");
+ setElementDisplay("access_code_help_row", "table-row");
+ document.getElementById('AccessCode').disabled = false;
}
function CloseDialog() {
@@ -254,15 +291,17 @@
return false;
document.getElementById('Email').disabled = true;
- document.getElementById('Passwd').disabled = true;
- document.getElementById('CaptchaValue').disabled = true;
+ document.getElementById('Passwd').disabled = true;
+ document.getElementById('CaptchaValue').disabled = true;
+ document.getElementById('AccessCode').disabled = true;
var throbber = document.getElementById('throbber_container');
throbber.style.display = "inline";
var f = document.getElementById("gaia_loginform");
var result = JSON.stringify({"user" : f.Email.value,
"pass" : f.Passwd.value,
- "captcha" : f.CaptchaValue.value});
+ "captcha" : f.CaptchaValue.value,
+ "access_code" : f.AccessCode.value});
document.getElementById("signIn").disabled = true;
chrome.send("SubmitAuth", [result]);
}
@@ -270,7 +309,7 @@
function setElementDisplay(id, display) {
var d = document.getElementById(id);
if (d)
- d.style.display = display;
+ d.style.display = display;
}
function setBlurbError() {
@@ -284,8 +323,9 @@
function resetErrorVisibility() {
setElementDisplay("errormsg_0_Email", 'none');
setElementDisplay("errormsg_0_Password", 'none');
- setElementDisplay("errormsg_1_Password", 'none');
- setElementDisplay("errormsg_0_Connection", 'none');
+ setElementDisplay("errormsg_1_Password", 'none');
+ setElementDisplay("errormsg_0_Connection", 'none');
+ setElementDisplay("errormsg_0_AccessCode", 'none');
}
function setErrorVisibility() {
@@ -299,6 +339,11 @@
if (null == f.Passwd.value || "" == f.Passwd.value) {
setElementDisplay("errormsg_0_Password", 'table-row');
setBlurbError();
+ return false;
+ }
+ if (!f.AccessCode.disabled && (null == f.AccessCode.value ||
+ "" == f.AccessCode.value)) {
+ setElementDisplay("errormsg_0_Password", 'table-row');
return false;
}
return true;
@@ -366,7 +411,7 @@
<tr>
<td colspan="2" align="center"> </td>
</tr>
- <tr>
+ <tr id="email_row">
<td nowrap="nowrap">
<div class="endaligned">
<span class="gaia le lbl" i18n-content="emaillabel">
@@ -379,6 +424,15 @@
<span id="email_readonly"></span>
</td>
</tr>
+ <tr id="access_code_label_row" class="access_code_row">
+ <td colspan="2">
+ <span class="gaia le lbl" i18n-content="enteraccesscode"></span>
+ </td>
+ </tr>
+ <tr id="access_code_help_row" class="access_code_row">
+ <td colspan="2" class="gaia le fpwd">
+ <a i18n-values="href:getaccesscodeurl" i18n-content="getaccesscodehelp" target="_blank"></a>
+ </td>
<tr>
<td></td>
<td>
@@ -391,7 +445,7 @@
<td></td>
<td></td>
</tr>
- <tr>
+ <tr id="password_row">
<td class="endaligned">
<span class="gaia le lbl" i18n-content="passwordlabel">
</span>
@@ -401,6 +455,12 @@
class="gaia le val"/>
</td>
</tr>
+ <tr id="access_code_input_row" class="access_code_row">
+ <td colspan="2">
+ <input type="password" name="AccessCode" id="AccessCode" size="18"
+ class="gaia le val"/>
+ </td>
+ </tr>
<tr>
<td>
</td>
@@ -412,6 +472,9 @@
<div class="errormsg" id="errormsg_1_Password">
<span i18n-content="invalidcredentials"></span>[<a i18n-values="href:invalidpasswordhelpurl" target="_blank">?</a>]
</div>
+ <div class="errormsg centeredtext" id="errormsg_0_AccessCode"
+ i18n-content="invalidaccesscode">
+ </div>
</div>
</td>
</tr>
diff --git a/chrome/browser/sync/signin_manager.cc b/chrome/browser/sync/signin_manager.cc
index 109d364..fb83337 100644
--- a/chrome/browser/sync/signin_manager.cc
+++ b/chrome/browser/sync/signin_manager.cc
@@ -14,6 +14,11 @@
const char kGetInfoEmailKey[] = "email";
+SigninManager::SigninManager()
+ : profile_(NULL), had_two_factor_error_(false) {}
+
+SigninManager::~SigninManager() {}
+
// static
void SigninManager::RegisterUserPrefs(PrefService* user_prefs) {
user_prefs->RegisterStringPref(prefs::kGoogleServicesUsername, "");
@@ -61,11 +66,28 @@ void SigninManager::StartSignIn(const std::string& username,
GaiaAuthenticator2::HostedAccountsNotAllowed);
}
+void SigninManager::ProvideSecondFactorAccessCode(
+ const std::string& access_code) {
+ DCHECK(!username_.empty() && !password_.empty() &&
+ last_result_.data.empty());
+
+ client_login_.reset(new GaiaAuthenticator2(this,
+ GaiaConstants::kChromeSource,
+ profile_->GetRequestContext()));
+ client_login_->StartClientLogin(username_,
+ access_code,
+ "",
+ std::string(),
+ std::string(),
+ GaiaAuthenticator2::HostedAccountsNotAllowed);
+}
+
void SigninManager::SignOut() {
client_login_.reset();
last_result_ = ClientLoginResult();
username_.clear();
password_.clear();
+ had_two_factor_error_ = false;
profile_->GetPrefs()->SetString(prefs::kGoogleServicesUsername, username_);
profile_->GetPrefs()->ScheduleSavePersistentPrefs();
profile_->GetTokenService()->ResetCredentialsInMemory();
@@ -113,10 +135,21 @@ void SigninManager::OnGetUserInfoFailure(const GoogleServiceAuthError& error) {
}
void SigninManager::OnClientLoginFailure(const GoogleServiceAuthError& error) {
- GoogleServiceAuthError details(error);
NotificationService::current()->Notify(
NotificationType::GOOGLE_SIGNIN_FAILED,
Source<SigninManager>(this),
- Details<const GoogleServiceAuthError>(&details));
+ Details<const GoogleServiceAuthError>(&error));
+
+ // We don't sign-out if the password was valid and we're just dealing with
+ // a second factor error, and we don't sign out if we're dealing with
+ // an invalid access code (again, because the password was valid).
+ bool invalid_gaia = error.state() ==
+ GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS;
+ if (error.state() == GoogleServiceAuthError::TWO_FACTOR ||
+ (had_two_factor_error_ && invalid_gaia)) {
+ had_two_factor_error_ = true;
+ return;
+ }
+
SignOut();
}
diff --git a/chrome/browser/sync/signin_manager.h b/chrome/browser/sync/signin_manager.h
index f59da4c..86137fa 100644
--- a/chrome/browser/sync/signin_manager.h
+++ b/chrome/browser/sync/signin_manager.h
@@ -35,6 +35,9 @@ struct GoogleServiceSigninSuccessDetails {
class SigninManager : public GaiaAuthConsumer {
public:
+ SigninManager();
+ virtual ~SigninManager();
+
// Call to register our prefs.
static void RegisterUserPrefs(PrefService* user_prefs);
@@ -55,8 +58,13 @@ class SigninManager : public GaiaAuthConsumer {
const std::string& password,
const std::string& login_token,
const std::string& login_captcha);
+
+ // Used when a second factor access code was required to complete a signin
+ // attempt.
+ void ProvideSecondFactorAccessCode(const std::string& access_code);
+
// Sign a user out, removing the preference, erasing all keys
- // associated with the user, and cancelling all auth in progress.
+ // associated with the user, and canceling all auth in progress.
void SignOut();
// GaiaAuthConsumer
@@ -71,6 +79,7 @@ class SigninManager : public GaiaAuthConsumer {
Profile* profile_;
std::string username_;
std::string password_; // This is kept empty whenever possible.
+ bool had_two_factor_error_;
// Result of the last client login, kept pending the lookup of the
// canonical email.
diff --git a/chrome/browser/sync/signin_manager_unittest.cc b/chrome/browser/sync/signin_manager_unittest.cc
index 7a4114a..5659533 100644
--- a/chrome/browser/sync/signin_manager_unittest.cc
+++ b/chrome/browser/sync/signin_manager_unittest.cc
@@ -106,6 +106,53 @@ TEST_F(SigninManagerTest, SignInFailure) {
EXPECT_TRUE(manager_->GetUsername().empty());
}
+TEST_F(SigninManagerTest, ProvideSecondFactorSuccess) {
+ manager_->Initialize(profile_.get());
+ manager_->StartSignIn("username", "password", "", "");
+ GoogleServiceAuthError error(GoogleServiceAuthError::TWO_FACTOR);
+ manager_->OnClientLoginFailure(error);
+
+ EXPECT_EQ(0U, google_login_success_.size());
+ EXPECT_EQ(1U, google_login_failure_.size());
+
+ EXPECT_FALSE(manager_->GetUsername().empty());
+
+ manager_->ProvideSecondFactorAccessCode("access");
+ SimulateValidResponse();
+
+ EXPECT_EQ(1U, google_login_success_.size());
+ EXPECT_EQ(1U, google_login_failure_.size());
+}
+
+TEST_F(SigninManagerTest, ProvideSecondFactorFailure) {
+ manager_->Initialize(profile_.get());
+ manager_->StartSignIn("username", "password", "", "");
+ GoogleServiceAuthError error1(GoogleServiceAuthError::TWO_FACTOR);
+ manager_->OnClientLoginFailure(error1);
+
+ EXPECT_EQ(0U, google_login_success_.size());
+ EXPECT_EQ(1U, google_login_failure_.size());
+
+ EXPECT_FALSE(manager_->GetUsername().empty());
+
+ manager_->ProvideSecondFactorAccessCode("badaccess");
+ GoogleServiceAuthError error2(
+ GoogleServiceAuthError::INVALID_GAIA_CREDENTIALS);
+ manager_->OnClientLoginFailure(error2);
+
+ EXPECT_EQ(0U, google_login_success_.size());
+ EXPECT_EQ(2U, google_login_failure_.size());
+ EXPECT_FALSE(manager_->GetUsername().empty());
+
+ manager_->ProvideSecondFactorAccessCode("badaccess");
+ GoogleServiceAuthError error3(GoogleServiceAuthError::CONNECTION_FAILED);
+ manager_->OnClientLoginFailure(error3);
+
+ EXPECT_EQ(0U, google_login_success_.size());
+ EXPECT_EQ(3U, google_login_failure_.size());
+ EXPECT_TRUE(manager_->GetUsername().empty());
+}
+
TEST_F(SigninManagerTest, SignOutMidConnect) {
manager_->Initialize(profile_.get());
manager_->StartSignIn("username", "password", "", "");
diff --git a/chrome/browser/sync/sync_setup_flow.cc b/chrome/browser/sync/sync_setup_flow.cc
index 0931a3f..594b0e0 100644
--- a/chrome/browser/sync/sync_setup_flow.cc
+++ b/chrome/browser/sync/sync_setup_flow.cc
@@ -44,7 +44,10 @@ void FlowHandler::RegisterMessages() {
}
static bool GetAuthData(const std::string& json,
- std::string* username, std::string* password, std::string* captcha) {
+ std::string* username,
+ std::string* password,
+ std::string* captcha,
+ std::string* access_code) {
scoped_ptr<Value> parsed_value(base::JSONReader::Read(json, false));
if (!parsed_value.get() || !parsed_value->IsType(Value::TYPE_DICTIONARY))
return false;
@@ -52,7 +55,8 @@ static bool GetAuthData(const std::string& json,
DictionaryValue* result = static_cast<DictionaryValue*>(parsed_value.get());
if (!result->GetString("user", username) ||
!result->GetString("pass", password) ||
- !result->GetString("captcha", captcha)) {
+ !result->GetString("captcha", captcha) ||
+ !result->GetString("access_code", access_code)) {
return false;
}
return true;
@@ -123,11 +127,11 @@ static bool GetDataTypeChoiceData(const std::string& json,
void FlowHandler::HandleSubmitAuth(const ListValue* args) {
std::string json(dom_ui_util::GetJsonResponseFromFirstArgumentInList(args));
- std::string username, password, captcha;
+ std::string username, password, captcha, access_code;
if (json.empty())
return;
- if (!GetAuthData(json, &username, &password, &captcha)) {
+ if (!GetAuthData(json, &username, &password, &captcha, &access_code)) {
// The page sent us something that we didn't understand.
// This probably indicates a programming error.
NOTREACHED();
@@ -135,7 +139,7 @@ void FlowHandler::HandleSubmitAuth(const ListValue* args) {
}
if (flow_)
- flow_->OnUserSubmittedAuth(username, password, captcha);
+ flow_->OnUserSubmittedAuth(username, password, captcha, access_code);
}
void FlowHandler::HandleChooseDataTypes(const ListValue* args) {
diff --git a/chrome/browser/sync/sync_setup_flow.h b/chrome/browser/sync/sync_setup_flow.h
index 6766963..baf43e6 100644
--- a/chrome/browser/sync/sync_setup_flow.h
+++ b/chrome/browser/sync/sync_setup_flow.h
@@ -93,8 +93,9 @@ class SyncSetupFlow : public HtmlDialogUIDelegate {
void OnUserSubmittedAuth(const std::string& username,
const std::string& password,
- const std::string& captcha) {
- service_->OnUserSubmittedAuth(username, password, captcha);
+ const std::string& captcha,
+ const std::string& access_code) {
+ service_->OnUserSubmittedAuth(username, password, captcha, access_code);
}
void OnUserChoseDataTypes(bool sync_everything,
diff --git a/chrome/browser/sync/sync_setup_wizard.cc b/chrome/browser/sync/sync_setup_wizard.cc
index 2eaa00d..5a4ea7b 100644
--- a/chrome/browser/sync/sync_setup_wizard.cc
+++ b/chrome/browser/sync/sync_setup_wizard.cc
@@ -21,6 +21,7 @@
#include "grit/app_resources.h"
#include "grit/browser_resources.h"
#include "grit/chromium_strings.h"
+#include "grit/locale_settings.h"
class SyncResourcesSource : public ChromeURLDataManager::DataSource {
public:
@@ -112,6 +113,16 @@ void SyncResourcesSource::StartDataRequest(const std::string& path_raw,
l10n_util::GetStringUTF16(IDS_SYNC_ERROR_SIGNING_IN));
localized_strings.SetString("captchainstructions",
l10n_util::GetStringUTF16(IDS_SYNC_GAIA_CAPTCHA_INSTRUCTIONS));
+
+ localized_strings.SetString("invalidaccesscode",
+ l10n_util::GetStringUTF16(IDS_SYNC_INVALID_ACCESS_CODE_LABEL));
+ localized_strings.SetString("enteraccesscode",
+ l10n_util::GetStringUTF16(IDS_SYNC_ENTER_ACCESS_CODE_LABEL));
+ localized_strings.SetString("getaccesscodehelp",
+ l10n_util::GetStringUTF16(IDS_SYNC_ACCESS_CODE_HELP_LABEL));
+ localized_strings.SetString("getaccesscodeurl",
+ l10n_util::GetStringUTF16(IDS_SYNC_GET_ACCESS_CODE_URL));
+
static const base::StringPiece html(ResourceBundle::GetSharedInstance()
.GetRawDataResource(IDR_GAIA_LOGIN_HTML));
SetFontAndTextDirection(&localized_strings);
diff --git a/chrome/browser/sync/sync_setup_wizard_unittest.cc b/chrome/browser/sync/sync_setup_wizard_unittest.cc
index 213ce4d..e4f53f0 100644
--- a/chrome/browser/sync/sync_setup_wizard_unittest.cc
+++ b/chrome/browser/sync/sync_setup_wizard_unittest.cc
@@ -42,7 +42,8 @@ class ProfileSyncServiceForWizardTest : public ProfileSyncService {
virtual void OnUserSubmittedAuth(const std::string& username,
const std::string& password,
- const std::string& captcha) {
+ const std::string& captcha,
+ const std::string& access_code) {
username_ = username;
password_ = password;
captcha_ = captcha;
@@ -217,7 +218,8 @@ TEST_F(SyncSetupWizardTest, InitialStepLogin) {
std::string auth = "{\"user\":\"";
auth += std::string(kTestUser) + "\",\"pass\":\"";
auth += std::string(kTestPassword) + "\",\"captcha\":\"";
- auth += std::string(kTestCaptcha) + "\"}";
+ auth += std::string(kTestCaptcha) + "\",\"access_code\":\"";
+ auth += std::string() + "\"}";
credentials.Append(new StringValue(auth));
EXPECT_FALSE(wizard_->IsVisible());