Commit cbf87d5f authored by Rohit Agarwal's avatar Rohit Agarwal Committed by Commit Bot

Add open in incognito option during account chooser Dialog.

This CL adds a UI placeholder for going incognito mode from MICE
account picker dialog.

The process of going incognito gated behind the incognito interstitial
would be followed up in later CLs.

This CL also adds an instrumentation test to verify the button is
shown after the bottom sheet is expanded and update the existing unit
tests in AccountPickerMediatorTest.

Bug: 1103262
Change-Id: I3762747ebb7b9bb50ebc32447635daf858876336
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2288498Reviewed-by: default avatarBoris Sazonov <bsazonov@chromium.org>
Reviewed-by: default avatarAlice Wang <aliceywang@chromium.org>
Commit-Queue: Rohit Agarwal <roagarwal@chromium.org>
Cr-Commit-Position: refs/heads/master@{#789904}
parent 18899193
......@@ -710,6 +710,7 @@ chrome_java_resources = [
"java/res/drawable/ic_full_screen_white_24dp.xml",
"java/res/drawable/ic_globe_24dp.xml",
"java/res/drawable/ic_google_round.xml",
"java/res/drawable/ic_incognito_24dp.xml",
"java/res/drawable/ic_logo_googleg_20dp.xml",
"java/res/drawable/ic_loop_round.xml",
"java/res/drawable/ic_music_note_24dp.xml",
......@@ -812,6 +813,7 @@ chrome_java_resources = [
"java/res/layout/account_management_account_row.xml",
"java/res/layout/account_picker_bottom_sheet_view.xml",
"java/res/layout/account_picker_dialog_body.xml",
"java/res/layout/account_picker_incognito_row.xml",
"java/res/layout/account_picker_new_account_row.xml",
"java/res/layout/account_picker_new_account_row_legacy.xml",
"java/res/layout/account_picker_row.xml",
......
......@@ -1429,6 +1429,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/signin/account_picker/AccountPickerProperties.java",
"java/src/org/chromium/chrome/browser/signin/account_picker/AddAccountRowViewBinder.java",
"java/src/org/chromium/chrome/browser/signin/account_picker/ExistingAccountRowViewBinder.java",
"java/src/org/chromium/chrome/browser/signin/account_picker/IncognitoAccountRowViewBinder.java",
"java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsClient.java",
"java/src/org/chromium/chrome/browser/site_settings/ChromeSiteSettingsHelpClient.java",
"java/src/org/chromium/chrome/browser/site_settings/ChromeWebappSettingsClient.java",
......
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2020 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
tools:targetApi="21"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:name="path"
android:pathData="M 21 11 L 3 11 L 3 12 L 21 12 L 21 11 Z M 17.62 10 L 15.33 3.9 C 15.14 3.4 14.59 3.13 14.08 3.3 L 12 4 L 9.91 3.3 C 9.4 3.13 8.85 3.4 8.66 3.9 L 6.38 10 L 17.62 10 Z M 16.5 13 C 14.84 13 13.46 14.16 13.1 15.71 C 12.26 15.35 11.48 15.45 10.9 15.7 C 10.53 14.15 9.15 13 7.5 13 C 5.57 13 4 14.57 4 16.5 C 4 18.43 5.57 20 7.5 20 C 9.34 20 10.83 18.58 10.97 16.78 C 11.27 16.57 12.06 16.18 13.03 16.8 C 13.19 18.59 14.67 20 16.5 20 C 18.43 20 20 18.43 20 16.5 C 20 14.57 18.43 13 16.5 13 Z M 7.5 19 C 6.12 19 5 17.88 5 16.5 C 5 15.12 6.12 14 7.5 14 C 8.88 14 10 15.12 10 16.5 C 10 17.88 8.88 19 7.5 19 Z M 16.5 19 C 15.12 19 14 17.88 14 16.5 C 14 15.12 15.12 14 16.5 14 C 17.88 14 19 15.12 19 16.5 C 19 17.88 17.88 19 16.5 19 Z"
android:fillColor="@color/default_icon_color"
android:strokeWidth="1"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<!-- Copyright 2020 The Chromium Authors. All rights reserved.
Use of this source code is governed by a BSD-style license that can be
found in the LICENSE file. -->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:orientation="horizontal"
android:padding="8dp">
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginEnd="24dp"
android:gravity="center_vertical"
app:srcCompat="@drawable/ic_incognito_24dp"
tools:ignore="ContentDescription" />
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<TextView
android:text="@string/signin_incognito_mode_primary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textAppearance="@style/TextAppearance.TextLarge.Primary" />
<TextView
android:text="@string/signin_incognito_mode_secondary"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:textAppearance="@style/TextAppearance.TextMedium.Secondary" />
</LinearLayout>
</LinearLayout>
......@@ -520,6 +520,9 @@ public abstract class SigninFragmentBase
});
}
@Override
public void goIncognitoMode() {}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == ADD_ACCOUNT_REQUEST_CODE && resultCode == Activity.RESULT_OK) {
......
......@@ -71,6 +71,14 @@ class AccountPickerBottomSheetMediator implements AccountPickerCoordinator.Liste
mAccountPickerDelegate.addAccount();
}
/**
* Notifies when the user clicked the "Go Incognito mode" button.
*/
@Override
public void goIncognitoMode() {
mAccountPickerDelegate.goIncognitoMode();
}
PropertyModel getModel() {
return mModel;
}
......
......@@ -8,6 +8,7 @@ import androidx.annotation.MainThread;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.signin.account_picker.AccountPickerProperties.ItemType;
import org.chromium.ui.modelutil.MVCListAdapter;
import org.chromium.ui.modelutil.SimpleRecyclerViewAdapter;
......@@ -34,6 +35,11 @@ public class AccountPickerCoordinator {
* Notifies when the user clicked the "add account" button.
*/
void addAccount();
/**
* Notifies when the user clicked the "Go incognito mode" button.
*/
void goIncognitoMode();
}
private final AccountPickerMediator mMediator;
......@@ -59,8 +65,13 @@ public class AccountPickerCoordinator {
adapter.registerType(ItemType.EXISTING_ACCOUNT_ROW, ExistingAccountRowViewBinder::buildView,
ExistingAccountRowViewBinder::bindView);
view.setAdapter(adapter);
if (ChromeFeatureList.isEnabled(ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY)) {
adapter.registerType(ItemType.INCOGNITO_ACCOUNT_ROW,
IncognitoAccountRowViewBinder::buildView,
IncognitoAccountRowViewBinder::bindView);
}
view.setAdapter(adapter);
mMediator = new AccountPickerMediator(
view.getContext(), listModel, listener, selectedAccountName);
}
......
......@@ -84,4 +84,9 @@ public class AccountPickerDelegate {
}
});
}
/**
* Notifies when the user clicked the "Go incognito mode" button.
*/
public void goIncognitoMode() {}
}
......@@ -12,10 +12,12 @@ import androidx.annotation.Nullable;
import org.chromium.base.Callback;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.signin.DisplayableProfileData;
import org.chromium.chrome.browser.signin.ProfileDataCache;
import org.chromium.chrome.browser.signin.account_picker.AccountPickerProperties.AddAccountRowProperties;
import org.chromium.chrome.browser.signin.account_picker.AccountPickerProperties.ExistingAccountRowProperties;
import org.chromium.chrome.browser.signin.account_picker.AccountPickerProperties.IncognitoAccountRowProperties;
import org.chromium.chrome.browser.signin.account_picker.AccountPickerProperties.ItemType;
import org.chromium.components.signin.AccountManagerFacade;
import org.chromium.components.signin.AccountManagerFacadeProvider;
......@@ -96,6 +98,14 @@ class AccountPickerMediator {
PropertyModel model =
AddAccountRowProperties.createModel(mAccountPickerListener::addAccount);
mListModel.add(new MVCListAdapter.ListItem(ItemType.ADD_ACCOUNT_ROW, model));
// Add a "Go incognito mode" row
if (ChromeFeatureList.isEnabled(ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY)) {
PropertyModel incognitoModel = IncognitoAccountRowProperties.createModel(
mAccountPickerListener::goIncognitoMode);
mListModel.add(
new MVCListAdapter.ListItem(ItemType.INCOGNITO_ACCOUNT_ROW, incognitoModel));
}
}
private MVCListAdapter.ListItem createExistingAccountRowItem(
......@@ -109,11 +119,13 @@ class AccountPickerMediator {
}
private void updateSelectedAccount() {
for (int i = 0; i < mListModel.size() - 1; ++i) {
PropertyModel model = mListModel.get(i).model;
boolean isSelectedAccount = TextUtils.equals(mSelectedAccountName,
model.get(ExistingAccountRowProperties.PROFILE_DATA).getAccountName());
model.set(ExistingAccountRowProperties.IS_SELECTED_ACCOUNT, isSelectedAccount);
for (MVCListAdapter.ListItem item : mListModel) {
if (item.type == AccountPickerProperties.ItemType.EXISTING_ACCOUNT_ROW) {
PropertyModel model = item.model;
boolean isSelectedAccount = TextUtils.equals(mSelectedAccountName,
model.get(ExistingAccountRowProperties.PROFILE_DATA).getAccountName());
model.set(ExistingAccountRowProperties.IS_SELECTED_ACCOUNT, isSelectedAccount);
}
}
}
}
......@@ -38,6 +38,24 @@ class AccountPickerProperties {
}
}
/**
* Properties for "incognito account" row in account picker.
*/
static class IncognitoAccountRowProperties {
static final PropertyModel.ReadableObjectPropertyKey<Runnable> ON_CLICK_LISTENER =
new PropertyModel.ReadableObjectPropertyKey<>("on_click_listener");
static final PropertyKey[] ALL_KEYS = new PropertyKey[] {ON_CLICK_LISTENER};
private IncognitoAccountRowProperties() {}
static PropertyModel createModel(Runnable runnableIncognitoAccount) {
return new PropertyModel.Builder(ALL_KEYS)
.with(ON_CLICK_LISTENER, runnableIncognitoAccount)
.build();
}
}
/**
* Properties for account row in account picker.
*/
......@@ -68,7 +86,8 @@ class AccountPickerProperties {
/**
* Item types of account picker.
*/
@IntDef({ItemType.EXISTING_ACCOUNT_ROW, ItemType.ADD_ACCOUNT_ROW})
@IntDef({ItemType.EXISTING_ACCOUNT_ROW, ItemType.ADD_ACCOUNT_ROW,
ItemType.INCOGNITO_ACCOUNT_ROW})
@Retention(RetentionPolicy.SOURCE)
@interface ItemType {
/**
......@@ -82,5 +101,11 @@ class AccountPickerProperties {
* use {@link AddAccountRowViewBinder} for view setup.
*/
int ADD_ACCOUNT_ROW = 2;
/**
* Item type for models created with {@link IncognitoAccountRowProperties#createModel} and
* use {@link IncognitoAccountRowViewBinder} for view setup.
*/
int INCOGNITO_ACCOUNT_ROW = 3;
}
}
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
package org.chromium.chrome.browser.signin.account_picker;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.LayoutRes;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.signin.account_picker.AccountPickerProperties.IncognitoAccountRowProperties;
import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel;
/**
* This class regroups the buildView and bindView util methods of the
* incognito account row.
*/
class IncognitoAccountRowViewBinder {
private IncognitoAccountRowViewBinder() {}
static View buildView(ViewGroup parent) {
@LayoutRes
int layoutRes = R.layout.account_picker_incognito_row;
return LayoutInflater.from(parent.getContext()).inflate(layoutRes, parent, false);
}
static void bindView(PropertyModel model, View view, PropertyKey propertyKey) {
if (propertyKey == IncognitoAccountRowProperties.ON_CLICK_LISTENER) {
view.setOnClickListener(
v -> model.get(IncognitoAccountRowProperties.ON_CLICK_LISTENER).run());
} else {
throw new IllegalArgumentException(
"Cannot update the view for propertyKey: " + propertyKey);
}
}
}
......@@ -281,6 +281,15 @@ public class AccountPickerBottomSheetTest {
checkCollapsedAccountList(PROFILE_DATA1);
}
@Test
@MediumTest
public void testIncognitoOptionShownOnExpandedSheet() throws Exception {
buildAndShowExpandedBottomSheet();
onView(withText(R.string.signin_incognito_mode_secondary)).check(matches(isDisplayed()));
onView(withText(R.string.signin_incognito_mode_primary)).perform(click());
verify(mAccountPickerDelegateMock).goIncognitoMode();
}
private void checkZeroAccountBottomSheet() {
onView(allOf(withText(PROFILE_DATA1.getAccountName()), withEffectiveVisibility(VISIBLE)))
.check(doesNotExist());
......
......@@ -34,6 +34,7 @@ import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.util.ChromeRenderTestRule;
import org.chromium.chrome.test.util.browser.Features;
import org.chromium.chrome.test.util.browser.Features.DisableFeatures;
import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule;
import org.chromium.components.signin.ProfileDataSource;
import org.chromium.components.signin.test.util.FakeProfileDataSource;
......@@ -48,17 +49,23 @@ import java.io.IOException;
* Use FragmentScenario to test this fragment once we start using fragment from androidx.
*/
@RunWith(ChromeJUnit4ClassRunner.class)
@CommandLineFlags
.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
@Features.DisableFeatures({ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY})
public class AccountPickerDialogFragmentTest extends DummyUiActivityTestCase {
@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
@DisableFeatures({ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY})
public class AccountPickerDialogFragmentTest extends DummyUiActivityTestCase {
@Rule
public final Features.JUnitProcessor mProcessor = new Features.JUnitProcessor();
// This test rule is only applied for Legacy AccountPickerDialog fragment.
// TODO(crbug.com/1106737): Refactor the tests into two separate files.
@Rule
public final ChromeRenderTestRule mRenderTestRule =
public final ChromeRenderTestRule mRenderTestRuleLegacy =
ChromeRenderTestRule.Builder.withPublicCorpus().setRevision(1).build();
// This test rule is only applied when MOBILE_IDENTITY_CONSISTENCY feature flag is enabled.
@Rule
public final ChromeRenderTestRule mRenderTestRule =
ChromeRenderTestRule.Builder.withPublicCorpus().setRevision(2).build();
@Rule
public final AccountManagerTestRule mAccountManagerTestRule =
new AccountManagerTestRule(new FakeProfileDataSource());
......@@ -125,7 +132,7 @@ import java.io.IOException;
@Feature("RenderTest")
public void testAccountPickerDialogViewLegacy() throws IOException {
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
mRenderTestRule.render(
mRenderTestRuleLegacy.render(
mDialog.getDialog().getWindow().getDecorView(), "account_picker_dialog_legacy");
}
......@@ -136,7 +143,7 @@ import java.io.IOException;
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
TestThreadUtils.runOnUiThreadBlocking(() -> mDialog.updateSelectedAccount(mAccountName2));
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
mRenderTestRule.render(mDialog.getDialog().getWindow().getDecorView(),
mRenderTestRuleLegacy.render(mDialog.getDialog().getWindow().getDecorView(),
"account_picker_dialog_update_selected_account");
}
......
......@@ -17,4 +17,7 @@ class DummyAccountPickerTargetFragment
@Override
public void addAccount() {}
@Override
public void goIncognitoMode() {}
}
......@@ -12,14 +12,17 @@ import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.robolectric.RuntimeEnvironment;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.signin.DisplayableProfileData;
import org.chromium.chrome.browser.signin.account_picker.AccountPickerProperties.AddAccountRowProperties;
import org.chromium.chrome.browser.signin.account_picker.AccountPickerProperties.ExistingAccountRowProperties;
import org.chromium.chrome.test.util.browser.Features;
import org.chromium.chrome.test.util.browser.signin.AccountManagerTestRule;
import org.chromium.components.signin.ProfileDataSource;
import org.chromium.components.signin.test.util.FakeProfileDataSource;
......@@ -35,6 +38,9 @@ public class AccountPickerMediatorTest {
private static final String ACCOUNT_NAME1 = "test.account1@gmail.com";
private static final String ACCOUNT_NAME2 = "test.account2@gmail.com";
@Rule
public TestRule mProcessor = new Features.JUnitProcessor();
@Rule
public final AccountManagerTestRule mAccountManagerTestRule =
new AccountManagerTestRule(new FakeProfileDataSource());
......@@ -59,7 +65,23 @@ public class AccountPickerMediatorTest {
}
@Test
@Features.EnableFeatures(ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY)
public void testModelPopulatedWhenStarted() {
addAccount(ACCOUNT_NAME1, FULL_NAME1);
addAccount(ACCOUNT_NAME2, "");
mMediator = new AccountPickerMediator(
RuntimeEnvironment.application, mModelList, mListenerMock, ACCOUNT_NAME1);
// ACCOUNT_NAME1, ACCOUNT_NAME2, ADD_ACCOUNT, INCOGNITO MODE.
Assert.assertEquals(4, mModelList.size());
checkItemForExistingAccountRow(0, ACCOUNT_NAME1, FULL_NAME1, /* isSelectedAccount= */ true);
checkItemForExistingAccountRow(1, ACCOUNT_NAME2, "", /* isSelectedAccount= */ false);
checkItemForAddAccountRow(2);
checkItemForIncognitoAccountRow(3);
}
@Test
@Features.DisableFeatures(ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY)
public void testModelPopulatedWhenStartedLegacy() {
addAccount(ACCOUNT_NAME1, FULL_NAME1);
addAccount(ACCOUNT_NAME2, "");
mMediator = new AccountPickerMediator(
......@@ -71,7 +93,25 @@ public class AccountPickerMediatorTest {
}
@Test
@Features.EnableFeatures(ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY)
public void testModelUpdatedAfterSetSelectedAccountName() {
addAccount(ACCOUNT_NAME1, FULL_NAME1);
addAccount(ACCOUNT_NAME2, "");
mMediator = new AccountPickerMediator(
RuntimeEnvironment.application, mModelList, mListenerMock, ACCOUNT_NAME1);
mMediator.setSelectedAccountName(ACCOUNT_NAME2);
// ACCOUNT_NAME1, ACCOUNT_NAME2, ADD_ACCOUNT, INCOGNITO MODE.
Assert.assertEquals(4, mModelList.size());
checkItemForExistingAccountRow(
0, ACCOUNT_NAME1, FULL_NAME1, /* isSelectedAccount= */ false);
checkItemForExistingAccountRow(1, ACCOUNT_NAME2, "", /* isSelectedAccount= */ true);
checkItemForAddAccountRow(2);
checkItemForIncognitoAccountRow(3);
}
@Test
@Features.DisableFeatures(ChromeFeatureList.MOBILE_IDENTITY_CONSISTENCY)
public void testModelUpdatedAfterSetSelectedAccountNameLegacy() {
addAccount(ACCOUNT_NAME1, FULL_NAME1);
addAccount(ACCOUNT_NAME2, "");
mMediator = new AccountPickerMediator(
......@@ -106,6 +146,14 @@ public class AccountPickerMediatorTest {
verify(mListenerMock).addAccount();
}
private void checkItemForIncognitoAccountRow(int position) {
MVCListAdapter.ListItem item = mModelList.get(position);
Assert.assertEquals(AccountPickerProperties.ItemType.INCOGNITO_ACCOUNT_ROW, item.type);
item.model.get(AccountPickerProperties.IncognitoAccountRowProperties.ON_CLICK_LISTENER)
.run();
verify(mListenerMock).goIncognitoMode();
}
private void addAccount(String accountName, String fullName) {
ProfileDataSource.ProfileData profileData =
new ProfileDataSource.ProfileData(accountName, null, fullName, null);
......
......@@ -2266,6 +2266,12 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_SIGNIN_ADD_ACCOUNT_TO_DEVICE" desc="Text for adding another Google Account to device in the web sign-in flow and account picker dialog, users will be asked to add an account to his device when this text is tapped">
Add account to device
</message>
<message name="IDS_SIGNIN_INCOGNITO_MODE_PRIMARY" desc="Text for signing in incognito mode.">
Go Incognito mode
</message>
<message name="IDS_SIGNIN_INCOGNITO_MODE_SECONDARY" desc="Secondary text for signing in incognito mode.">
To sign in temporarily
</message>
<message name="IDS_SIGNIN_GMS_UPDATING" desc="Message notifying user that Google Play Services is still updating.">
Waiting for Google Play Services to finish updating
</message>
......
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