[go: nahoru, domu]

[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() {