Commit 65459217 authored by Tanmoy Mollik's avatar Tanmoy Mollik Committed by Commit Bot

Surface "Setup not completed" error in settings page

As part of making sync manual_start for android the user needs to be aware
that the initial setup process was interrupted and sync is in an
incofigured state. This should be reflected on the main settings page
and the user can either start sync or stop sync from syncAndServicesPreferences
page.

Either way FirstSetupComplete will be true after user has seen and
interacted with it in the syncAndServicesPreferences page.

Screenshot: https://crbug.com/991522#c2

Bug: 991522
Change-Id: Id65cccc62933dd6a7446ad577e066b909bf28eec
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1744487Reviewed-by: default avatarTheresa  <twellington@chromium.org>
Reviewed-by: default avatarMarc Treib <treib@chromium.org>
Commit-Queue: Tanmoy Mollik <triploblastic@chromium.org>
Cr-Commit-Position: refs/heads/master@{#689080}
parent 70c9502a
...@@ -25,8 +25,7 @@ ...@@ -25,8 +25,7 @@
<Preference <Preference
android:key="sync_error_card" android:key="sync_error_card"
android:layout="@layout/account_management_account_row" android:layout="@layout/account_management_account_row"/>
android:title="@string/sync_error_card_title"/>
<Preference <Preference
android:key="sync_disabled_by_administrator" android:key="sync_disabled_by_administrator"
android:layout="@layout/account_management_account_row" android:layout="@layout/account_management_account_row"
......
...@@ -103,7 +103,8 @@ public class SyncAndServicesPreferences extends PreferenceFragmentCompat ...@@ -103,7 +103,8 @@ public class SyncAndServicesPreferences extends PreferenceFragmentCompat
private static final String PREF_CONTEXTUAL_SEARCH = "contextual_search"; private static final String PREF_CONTEXTUAL_SEARCH = "contextual_search";
@IntDef({SyncError.NO_ERROR, SyncError.ANDROID_SYNC_DISABLED, SyncError.AUTH_ERROR, @IntDef({SyncError.NO_ERROR, SyncError.ANDROID_SYNC_DISABLED, SyncError.AUTH_ERROR,
SyncError.PASSPHRASE_REQUIRED, SyncError.CLIENT_OUT_OF_DATE, SyncError.OTHER_ERRORS}) SyncError.PASSPHRASE_REQUIRED, SyncError.CLIENT_OUT_OF_DATE,
SyncError.SYNC_SETUP_INCOMPLETE, SyncError.OTHER_ERRORS})
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
private @interface SyncError { private @interface SyncError {
int NO_ERROR = -1; int NO_ERROR = -1;
...@@ -111,6 +112,7 @@ public class SyncAndServicesPreferences extends PreferenceFragmentCompat ...@@ -111,6 +112,7 @@ public class SyncAndServicesPreferences extends PreferenceFragmentCompat
int AUTH_ERROR = 1; int AUTH_ERROR = 1;
int PASSPHRASE_REQUIRED = 2; int PASSPHRASE_REQUIRED = 2;
int CLIENT_OUT_OF_DATE = 3; int CLIENT_OUT_OF_DATE = 3;
int SYNC_SETUP_INCOMPLETE = 4;
int OTHER_ERRORS = 128; int OTHER_ERRORS = 128;
} }
...@@ -326,6 +328,12 @@ public class SyncAndServicesPreferences extends PreferenceFragmentCompat ...@@ -326,6 +328,12 @@ public class SyncAndServicesPreferences extends PreferenceFragmentCompat
if (PREF_SYNC_REQUESTED.equals(key)) { if (PREF_SYNC_REQUESTED.equals(key)) {
assert canDisableSync(); assert canDisableSync();
SyncPreferenceUtils.enableSync((boolean) newValue); SyncPreferenceUtils.enableSync((boolean) newValue);
if (ChromeFeatureList.isEnabled(ChromeFeatureList.SYNC_MANUAL_START_ANDROID)
&& wasSigninFlowInterrupted()) {
// This flow should only be reached when user toggles sync on.
assert (boolean) newValue;
mProfileSyncService.setFirstSetupComplete();
}
PostTask.postTask(UiThreadTaskTraits.DEFAULT, this::updatePreferences); PostTask.postTask(UiThreadTaskTraits.DEFAULT, this::updatePreferences);
} else if (PREF_SEARCH_SUGGESTIONS.equals(key)) { } else if (PREF_SEARCH_SUGGESTIONS.equals(key)) {
mPrefServiceBridge.setSearchSuggestEnabled((boolean) newValue); mPrefServiceBridge.setSearchSuggestEnabled((boolean) newValue);
...@@ -360,6 +368,11 @@ public class SyncAndServicesPreferences extends PreferenceFragmentCompat ...@@ -360,6 +368,11 @@ public class SyncAndServicesPreferences extends PreferenceFragmentCompat
return !Profile.getLastUsedProfile().isChild(); return !Profile.getLastUsedProfile().isChild();
} }
/** Returns whether user did not complete the sign in flow. */
private boolean wasSigninFlowInterrupted() {
return !mIsFromSigninScreen && !mProfileSyncService.isFirstSetupComplete();
}
private void displayPassphraseDialog() { private void displayPassphraseDialog() {
FragmentTransaction ft = getFragmentManager().beginTransaction(); FragmentTransaction ft = getFragmentManager().beginTransaction();
PassphraseDialogFragment.newInstance(this).show(ft, FRAGMENT_ENTER_PASSPHRASE); PassphraseDialogFragment.newInstance(this).show(ft, FRAGMENT_ENTER_PASSPHRASE);
...@@ -431,9 +444,29 @@ public class SyncAndServicesPreferences extends PreferenceFragmentCompat ...@@ -431,9 +444,29 @@ public class SyncAndServicesPreferences extends PreferenceFragmentCompat
return SyncError.PASSPHRASE_REQUIRED; return SyncError.PASSPHRASE_REQUIRED;
} }
if (ChromeFeatureList.isEnabled(ChromeFeatureList.SYNC_MANUAL_START_ANDROID)
&& wasSigninFlowInterrupted()) {
return SyncError.SYNC_SETUP_INCOMPLETE;
}
return SyncError.NO_ERROR; return SyncError.NO_ERROR;
} }
/**
* Gets title message for sync error.
* @param error The sync error.
*/
private String getSyncErrorTitle(@SyncError int error) {
Resources res = getActivity().getResources();
switch (error) {
case SyncError.SYNC_SETUP_INCOMPLETE:
assert ChromeFeatureList.isEnabled(ChromeFeatureList.SYNC_MANUAL_START_ANDROID);
return res.getString(R.string.sync_settings_not_confirmed_title);
default:
return res.getString(R.string.sync_error_card_title);
}
}
/** /**
* Gets hint message to resolve sync error. * Gets hint message to resolve sync error.
* @param error The sync error. * @param error The sync error.
...@@ -452,6 +485,9 @@ public class SyncAndServicesPreferences extends PreferenceFragmentCompat ...@@ -452,6 +485,9 @@ public class SyncAndServicesPreferences extends PreferenceFragmentCompat
return res.getString(R.string.hint_other_sync_errors); return res.getString(R.string.hint_other_sync_errors);
case SyncError.PASSPHRASE_REQUIRED: case SyncError.PASSPHRASE_REQUIRED:
return res.getString(R.string.hint_passphrase_required); return res.getString(R.string.hint_passphrase_required);
case SyncError.SYNC_SETUP_INCOMPLETE:
assert ChromeFeatureList.isEnabled(ChromeFeatureList.SYNC_MANUAL_START_ANDROID);
return res.getString(R.string.hint_sync_settings_not_confirmed_description);
case SyncError.NO_ERROR: case SyncError.NO_ERROR:
default: default:
return null; return null;
...@@ -552,12 +588,18 @@ public class SyncAndServicesPreferences extends PreferenceFragmentCompat ...@@ -552,12 +588,18 @@ public class SyncAndServicesPreferences extends PreferenceFragmentCompat
if (mCurrentSyncError == SyncError.NO_ERROR) { if (mCurrentSyncError == SyncError.NO_ERROR) {
mSyncCategory.removePreference(mSyncErrorCard); mSyncCategory.removePreference(mSyncErrorCard);
} else { } else {
String summary = getSyncErrorHint(mCurrentSyncError); mSyncErrorCard.setTitle(getSyncErrorTitle(mCurrentSyncError));
mSyncErrorCard.setSummary(summary); mSyncErrorCard.setSummary(getSyncErrorHint(mCurrentSyncError));
mSyncCategory.addPreference(mSyncErrorCard); mSyncCategory.addPreference(mSyncErrorCard);
} }
mSyncRequested.setChecked(AndroidSyncSettings.get().isChromeSyncEnabled()); mSyncRequested.setChecked(AndroidSyncSettings.get().isChromeSyncEnabled());
if (ChromeFeatureList.isEnabled(ChromeFeatureList.SYNC_MANUAL_START_ANDROID)
&& wasSigninFlowInterrupted()) {
// If sync setup was not completed the sync request toggle should be off.
// In this situation, switching it on will trigger a call to setFirstSetupComplete.
mSyncRequested.setChecked(false);
}
mSyncRequested.setEnabled(canDisableSync()); mSyncRequested.setEnabled(canDisableSync());
} }
...@@ -588,6 +630,15 @@ public class SyncAndServicesPreferences extends PreferenceFragmentCompat ...@@ -588,6 +630,15 @@ public class SyncAndServicesPreferences extends PreferenceFragmentCompat
@Override @Override
public boolean onBackPressed() { public boolean onBackPressed() {
if (ChromeFeatureList.isEnabled(ChromeFeatureList.SYNC_MANUAL_START_ANDROID)
&& wasSigninFlowInterrupted()) {
// If the setup flow was previously interrupted, and now the user dismissed the page
// without turning sync on, then mark first setup as complete (so that we won't show the
// error again), but turn sync off.
assert !mSyncRequested.isChecked();
SyncPreferenceUtils.enableSync(false);
mProfileSyncService.setFirstSetupComplete();
}
if (!mIsFromSigninScreen) return false; // Let parent activity handle it. if (!mIsFromSigninScreen) return false; // Let parent activity handle it.
showCancelSyncDialog(); showCancelSyncDialog();
return true; return true;
......
...@@ -14,10 +14,13 @@ import android.support.annotation.Nullable; ...@@ -14,10 +14,13 @@ import android.support.annotation.Nullable;
import android.support.v7.preference.Preference; import android.support.v7.preference.Preference;
import android.support.v7.preference.PreferenceFragmentCompat; import android.support.v7.preference.PreferenceFragmentCompat;
import androidx.browser.customtabs.CustomTabsIntent;
import org.chromium.base.BuildInfo; import org.chromium.base.BuildInfo;
import org.chromium.base.metrics.RecordHistogram; import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.metrics.RecordUserAction; import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.R; import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeFeatureList;
import org.chromium.chrome.browser.IntentHandler; import org.chromium.chrome.browser.IntentHandler;
import org.chromium.chrome.browser.LaunchIntentDispatcher; import org.chromium.chrome.browser.LaunchIntentDispatcher;
import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider; import org.chromium.chrome.browser.customtabs.CustomTabIntentDataProvider;
...@@ -29,8 +32,6 @@ import org.chromium.components.sync.AndroidSyncSettings; ...@@ -29,8 +32,6 @@ import org.chromium.components.sync.AndroidSyncSettings;
import org.chromium.components.sync.StopSource; import org.chromium.components.sync.StopSource;
import org.chromium.ui.UiUtils; import org.chromium.ui.UiUtils;
import androidx.browser.customtabs.CustomTabsIntent;
/** /**
* Helper methods for sync preferences. * Helper methods for sync preferences.
*/ */
...@@ -88,6 +89,11 @@ public class SyncPreferenceUtils { ...@@ -88,6 +89,11 @@ public class SyncPreferenceUtils {
return res.getString(R.string.sync_is_disabled_by_administrator); return res.getString(R.string.sync_is_disabled_by_administrator);
} }
if (ChromeFeatureList.isEnabled(ChromeFeatureList.SYNC_MANUAL_START_ANDROID)
&& !profileSyncService.isFirstSetupComplete()) {
return res.getString(R.string.sync_settings_not_confirmed);
}
if (profileSyncService.getAuthError() != GoogleServiceAuthError.State.NONE) { if (profileSyncService.getAuthError() != GoogleServiceAuthError.State.NONE) {
return res.getString( return res.getString(
GoogleServiceAuthError.getMessageID(profileSyncService.getAuthError())); GoogleServiceAuthError.getMessageID(profileSyncService.getAuthError()));
...@@ -134,6 +140,12 @@ public class SyncPreferenceUtils { ...@@ -134,6 +140,12 @@ public class SyncPreferenceUtils {
context, R.drawable.ic_sync_error_40dp, R.color.default_icon_color); context, R.drawable.ic_sync_error_40dp, R.color.default_icon_color);
} }
if (ChromeFeatureList.isEnabled(ChromeFeatureList.SYNC_MANUAL_START_ANDROID)
&& !profileSyncService.isFirstSetupComplete()) {
return UiUtils.getTintedDrawable(
context, R.drawable.ic_sync_error_40dp, R.color.default_red);
}
if (profileSyncService.isEngineInitialized() if (profileSyncService.isEngineInitialized()
&& (profileSyncService.hasUnrecoverableError() && (profileSyncService.hasUnrecoverableError()
|| profileSyncService.getAuthError() != GoogleServiceAuthError.State.NONE || profileSyncService.getAuthError() != GoogleServiceAuthError.State.NONE
......
...@@ -1529,6 +1529,9 @@ Your Google account may have other forms of browsing history like searches and a ...@@ -1529,6 +1529,9 @@ Your Google account may have other forms of browsing history like searches and a
<message name="IDS_SYNC_IS_DISABLED" desc="Message to show when Chrome sync is disabled"> <message name="IDS_SYNC_IS_DISABLED" desc="Message to show when Chrome sync is disabled">
Sync is off Sync is off
</message> </message>
<message name="IDS_SYNC_SETTINGS_NOT_CONFIRMED" desc="The error message to display when sign-in was interrupted and the user didn't review the sync settings.">
Initial sync setup was not finished. Sync is off.
</message>
<message name="IDS_SYNC_IS_DISABLED_BY_ADMINISTRATOR" desc="Message to show when Chrome sync is disabled by administrator"> <message name="IDS_SYNC_IS_DISABLED_BY_ADMINISTRATOR" desc="Message to show when Chrome sync is disabled by administrator">
Sync is disabled by your administrator Sync is disabled by your administrator
</message> </message>
...@@ -1813,6 +1816,9 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p ...@@ -1813,6 +1816,9 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_SYNC_ERROR_CARD_TITLE" desc="Title of the Sync Error Card. [CHAR-LIMIT=32]"> <message name="IDS_SYNC_ERROR_CARD_TITLE" desc="Title of the Sync Error Card. [CHAR-LIMIT=32]">
Sync isn't working Sync isn't working
</message> </message>
<message name="IDS_SYNC_SETTINGS_NOT_CONFIRMED_TITLE" desc="Title of the error message shown when sync setup was not complete. [CHAR-LIMIT=60]">
Initial sync setup not finished
</message>
<message name="IDS_HINT_ANDROID_SYNC_DISABLED" desc="Hint message to resolve Android system sync is disabled error."> <message name="IDS_HINT_ANDROID_SYNC_DISABLED" desc="Hint message to resolve Android system sync is disabled error.">
Open Android settings and re-enable Android system sync to start Chrome sync Open Android settings and re-enable Android system sync to start Chrome sync
</message> </message>
...@@ -1822,6 +1828,9 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p ...@@ -1822,6 +1828,9 @@ To change this setting, <ph name="BEGIN_LINK">&lt;resetlink&gt;</ph>reset sync<p
<message name="IDS_HINT_PASSPHRASE_REQUIRED" desc="Hint message to resolve passphrase required error."> <message name="IDS_HINT_PASSPHRASE_REQUIRED" desc="Hint message to resolve passphrase required error.">
Enter your passphrase to start sync Enter your passphrase to start sync
</message> </message>
<message name="IDS_HINT_SYNC_SETTINGS_NOT_CONFIRMED_DESCRIPTION" desc="The error message to display when sign-in was interrupted and the user didn't review the sync settings.">
To start sync, turn on "Sync your Chrome data".
</message>
<message name="IDS_HINT_OTHER_SYNC_ERRORS" desc="Hint message to resolve sync errors not listed independently."> <message name="IDS_HINT_OTHER_SYNC_ERRORS" desc="Hint message to resolve sync errors not listed independently.">
Try signing in again Try signing in again
</message> </message>
......
bb0b2552ed760c56ec289e904c3b0150fae397ac
\ No newline at end of file
290f8e1c88b8be1ba82d45d64b7ec8b8ca48f4ce
\ No newline at end of file
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