[M123] Fix crash from null profile in PassphraseDialogFragment.
Bug: 327687076
Change-Id: I517444fbf0157baa43db3c6b5555e5b82b9df517
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5350138
Reviewed-by: David Trainor <dtrainor@chromium.org>
Commit-Queue: Ted Choc <tedchoc@chromium.org>
Cr-Original-Commit-Position: refs/heads/main@{#1269229}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5356733
Commit-Queue: David Trainor <dtrainor@chromium.org>
Cr-Commit-Position: refs/branch-heads/6312@{#482}
Cr-Branched-From: 6711dcdae48edaf98cbc6964f90fac85b7d9986e-refs/heads/main@{#1262506}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java
index 56078782..aa74045 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/AccountManagementFragment.java
@@ -72,7 +72,7 @@
ProfileDataCache.Observer,
CustomDividerFragment,
IdentityErrorCardPreference.Listener,
- PassphraseDialogFragment.Listener {
+ PassphraseDialogFragment.Delegate {
private static final String CLEAR_DATA_PROGRESS_DIALOG_TAG = "clear_data_progress";
private static final int REQUEST_CODE_TRUSTED_VAULT_KEY_RETRIEVAL = 1;
private static final int REQUEST_CODE_TRUSTED_VAULT_RECOVERABILITY_DEGRADED = 2;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java
index a551a60ca..3287597 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/settings/ManageSyncSettings.java
@@ -75,7 +75,7 @@
* This fragment is accessible from the main settings view.
*/
public class ManageSyncSettings extends ChromeBaseSettingsFragment
- implements PassphraseDialogFragment.Listener,
+ implements PassphraseDialogFragment.Delegate,
PassphraseCreationDialogFragment.Listener,
PassphraseTypeDialogFragment.Listener,
Preference.OnPreferenceChangeListener,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseActivity.java
index 8a100d2..2b3aa69 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseActivity.java
@@ -27,11 +27,11 @@
import org.chromium.components.sync.SyncService;
/**
- * This activity is used for requesting a sync passphrase from the user. Typically,
- * this will be the target of an Android notification.
+ * This activity is used for requesting a sync passphrase from the user. Typically, this will be the
+ * target of an Android notification.
*/
public class PassphraseActivity extends AppCompatActivity
- implements PassphraseDialogFragment.Listener, FragmentManager.OnBackStackChangedListener {
+ implements PassphraseDialogFragment.Delegate, FragmentManager.OnBackStackChangedListener {
public static final String FRAGMENT_PASSPHRASE = "passphrase_fragment";
public static final String FRAGMENT_SPINNER = "spinner_fragment";
@@ -127,7 +127,7 @@
dialog.show(ft, FRAGMENT_SPINNER);
}
- /** Callback for PassphraseDialogFragment.Listener */
+ /** Callback for {@link PassphraseDialogFragment.Delegate} */
@Override
public boolean onPassphraseEntered(String passphrase) {
if (!passphrase.isEmpty() && mSyncService.setDecryptionPassphrase(passphrase)) {
@@ -146,6 +146,11 @@
}
@Override
+ public Profile getProfile() {
+ return mProfile;
+ }
+
+ @Override
public void onBackStackChanged() {
if (getSupportFragmentManager().getBackStackEntryCount() == 0) {
finish();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java
index 25bab2b6..3bf7585 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/sync/ui/PassphraseDialogFragment.java
@@ -35,28 +35,28 @@
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeStringConstants;
import org.chromium.chrome.browser.profiles.Profile;
-import org.chromium.chrome.browser.settings.ProfileDependentSetting;
+import org.chromium.chrome.browser.profiles.ProfileManager;
import org.chromium.chrome.browser.sync.SyncServiceFactory;
import org.chromium.components.sync.SyncService;
import org.chromium.ui.text.SpanApplier;
import org.chromium.ui.text.SpanApplier.SpanInfo;
/** Dialog to ask to user to enter their sync passphrase. */
-public class PassphraseDialogFragment extends DialogFragment
- implements OnClickListener, ProfileDependentSetting {
+public class PassphraseDialogFragment extends DialogFragment implements OnClickListener {
private static final String TAG = "Sync_UI";
- /** A listener for passphrase events. */
- public interface Listener {
+ /** A delegate for passphrase events/dependencies. */
+ public interface Delegate {
/**
* @return whether passphrase was valid.
*/
boolean onPassphraseEntered(String passphrase);
void onPassphraseCanceled();
- }
- private Profile mProfile;
+ /** Return the Profile associated with the passphrase. */
+ Profile getProfile();
+ }
private EditText mPassphraseEditText;
private TextView mVerifyingTextView;
@@ -73,14 +73,17 @@
return dialog;
}
- @Override
- public void setProfile(Profile profile) {
- mProfile = profile;
+ private Profile getProfile() {
+ Profile profile = getDelegate().getProfile();
+ assert profile != null : "Attempting to use PassphraseDialogFragment with a null profile";
+ // TODO(crbug/327687076): Remove the following profile fallback assuming no asserts are
+ // triggered for the above profile assert.
+ return profile == null ? ProfileManager.getLastUsedRegularProfile() : profile;
}
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
- assert SyncServiceFactory.getForProfile(mProfile) != null;
+ assert SyncServiceFactory.getForProfile(getProfile()) != null;
LayoutInflater inflater = getActivity().getLayoutInflater();
View v = inflater.inflate(R.layout.sync_enter_passphrase, null);
@@ -169,7 +172,7 @@
}
private SpannableString getPromptText() {
- SyncService syncService = SyncServiceFactory.getForProfile(mProfile);
+ SyncService syncService = SyncServiceFactory.getForProfile(getProfile());
String accountName =
getString(R.string.sync_account_info, syncService.getAccountInfo().getEmail())
+ "\n\n";
@@ -200,7 +203,7 @@
}
private void handleCancel() {
- getListener().onPassphraseCanceled();
+ getDelegate().onPassphraseCanceled();
}
private void handleSubmit() {
@@ -208,18 +211,18 @@
mVerifyingTextView.setText(R.string.sync_verifying);
String passphrase = mPassphraseEditText.getText().toString();
- boolean success = getListener().onPassphraseEntered(passphrase);
+ boolean success = getDelegate().onPassphraseEntered(passphrase);
if (!success) {
invalidPassphrase();
}
}
- private Listener getListener() {
+ private Delegate getDelegate() {
Fragment target = getTargetFragment();
- if (target instanceof Listener) {
- return (Listener) target;
+ if (target instanceof Delegate) {
+ return (Delegate) target;
}
- return (Listener) getActivity();
+ return (Delegate) getActivity();
}
/** Notify this fragment that the passphrase the user entered is incorrect. */
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseActivityTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseActivityTest.java
index fe14b93..1ced1ad 100644
--- a/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseActivityTest.java
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/sync/ui/PassphraseActivityTest.java
@@ -4,13 +4,13 @@
package org.chromium.chrome.browser.sync.ui;
-import android.app.Instrumentation.ActivityMonitor;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import androidx.test.core.app.ApplicationProvider;
+import androidx.test.filters.MediumTest;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
@@ -25,6 +25,7 @@
import org.chromium.chrome.browser.sync.FakeSyncServiceImpl;
import org.chromium.chrome.browser.sync.SyncServiceFactory;
import org.chromium.chrome.test.ChromeBrowserTestRule;
+import org.chromium.chrome.test.util.ActivityTestUtils;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
/** Tests for PassphraseActivity. */
@@ -69,6 +70,22 @@
InstrumentationRegistry.getInstrumentation().waitForIdleSync();
}
+ @Test
+ @MediumTest
+ @Feature({"Sync"})
+ public void testLaunchPassphraseDialog() {
+ // Override before signing in, otherwise regular SyncService will be created.
+ FakeSyncServiceImpl fakeSyncService = overrideSyncService();
+ mChromeBrowserTestRule.addTestAccountThenSigninAndEnableSync();
+
+ // Create the activity.
+ final PassphraseActivity activity = launchPassphraseActivity();
+ Assert.assertNotNull(activity);
+
+ TestThreadUtils.runOnUiThreadBlocking(() -> fakeSyncService.setEngineInitialized(true));
+ ActivityTestUtils.waitForFragment(activity, PassphraseActivity.FRAGMENT_PASSPHRASE);
+ }
+
private PassphraseActivity launchPassphraseActivity() {
Intent intent = new Intent(Intent.ACTION_MAIN);
intent.setComponent(new ComponentName(mContext, PassphraseActivity.class));
@@ -77,12 +94,9 @@
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Clears the task stack above this activity if it already exists.
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
- ActivityMonitor monitor =
- InstrumentationRegistry.getInstrumentation()
- .addMonitor(PassphraseActivity.class.getName(), null, false);
mContext.startActivity(intent);
- return (PassphraseActivity)
- InstrumentationRegistry.getInstrumentation().waitForMonitor(monitor);
+ return ActivityTestUtils.waitForActivity(
+ InstrumentationRegistry.getInstrumentation(), PassphraseActivity.class);
}
private FakeSyncServiceImpl overrideSyncService() {