0

Add NullMarked to chrome/browser/incognito:java

Bug: 389129271
Change-Id: I2fc00b8ac3e884df7185b56029e28e1eb08d7f8e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6438248
Reviewed-by: Henrique Nakashima <hnakashima@chromium.org>
Owners-Override: Henrique Nakashima <hnakashima@chromium.org>
Commit-Queue: Zhe Li <zheliooo@google.com>
Cr-Commit-Position: refs/heads/main@{#1444968}
This commit is contained in:
Zhe Li
2025-04-09 14:56:26 -07:00
committed by Chromium LUCI CQ
parent 2b0c5e35c7
commit 5c951f7c72
21 changed files with 206 additions and 156 deletions

@ -4,6 +4,8 @@
package org.chromium.chrome.browser.incognito;
import static org.chromium.build.NullUtil.assumeNonNull;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.ActivityManager.AppTask;
@ -14,6 +16,7 @@ import org.chromium.base.ApplicationStatus;
import org.chromium.base.CallbackUtils;
import org.chromium.base.ContextUtils;
import org.chromium.base.supplier.ObservableSupplier;
import org.chromium.build.annotations.NullMarked;
import org.chromium.chrome.browser.cookies.CookiesFetcher;
import org.chromium.chrome.browser.profiles.ProfileManager;
import org.chromium.chrome.browser.profiles.ProfileProvider;
@ -25,6 +28,7 @@ import java.util.HashSet;
import java.util.Set;
/** Operations that need to be executed on startup for incognito mode. */
@NullMarked
public class IncognitoStartup {
public static void onResumeWithNative(
ProfileProvider profileProvider,
@ -35,7 +39,8 @@ public class IncognitoStartup {
&& shouldDestroyIncognitoProfileOnStartup(
tabModelSelectorSupplier.get().getCurrentModel().isIncognito(),
componentNames)) {
ProfileManager.destroyWhenAppropriate(profileProvider.getOffTheRecordProfile(false));
ProfileManager.destroyWhenAppropriate(
assumeNonNull(profileProvider.getOffTheRecordProfile(false)));
} else {
cookiesFetcher.restoreCookies(CallbackUtils.emptyRunnable());
}

@ -7,12 +7,14 @@ package org.chromium.chrome.browser.incognito;
import android.util.Pair;
import org.chromium.base.Log;
import org.chromium.build.annotations.NullMarked;
import org.chromium.chrome.browser.tabpersistence.TabStateDirectory;
import org.chromium.chrome.browser.tabpersistence.TabStateFileManager;
import java.io.File;
/** Manages tab state files for incognito tabs. */
@NullMarked
public class IncognitoTabPersistence {
private static final String TAG = "IncognitoFileDelete";

@ -4,10 +4,14 @@
package org.chromium.chrome.browser.incognito;
import static org.chromium.build.NullUtil.assumeNonNull;
import org.jni_zero.JniType;
import org.jni_zero.NativeMethods;
import org.chromium.base.ResettersForTesting;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
import org.chromium.chrome.browser.profiles.OtrProfileId;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.profiles.ProfileKey;
@ -15,8 +19,9 @@ import org.chromium.chrome.browser.profiles.ProfileKeyUtil;
import org.chromium.chrome.browser.profiles.ProfileManager;
/** Utilities for working with incognito tabs spread across multiple activities. */
@NullMarked
public class IncognitoUtils {
private static Boolean sIsEnabledForTesting;
private static @Nullable Boolean sIsEnabledForTesting;
private IncognitoUtils() {}
@ -50,9 +55,11 @@ public class IncognitoUtils {
// If off-the-record is not requested, the request might be before native initialization.
if (otrProfileId == null) return ProfileKeyUtil.getLastUsedRegularProfileKey();
return ProfileManager.getLastUsedRegularProfile()
.getOffTheRecordProfile(otrProfileId, /* createIfNeeded= */ true)
.getProfileKey();
Profile profile =
ProfileManager.getLastUsedRegularProfile()
.getOffTheRecordProfile(otrProfileId, /* createIfNeeded= */ true);
assumeNonNull(profile);
return profile.getProfileKey();
}
public static void setEnabledForTesting(Boolean enabled) {

@ -4,58 +4,61 @@
package org.chromium.chrome.browser.incognito.reauth;
import static org.chromium.build.NullUtil.assumeNonNull;
import android.content.Context;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthManager.IncognitoReauthCallback;
import org.chromium.ui.modaldialog.DialogDismissalCause;
import org.chromium.ui.modaldialog.ModalDialogManager;
/** The coordinator responsible for showing the full-screen re-auth dialog. */
@NullMarked
class FullScreenIncognitoReauthCoordinator extends IncognitoReauthCoordinatorBase {
/** The manager responsible for showing the full screen Incognito re-auth dialog. */
private final @NonNull ModalDialogManager mModalDialogManager;
private final ModalDialogManager mModalDialogManager;
/** The 3 dots menu delegate shown inside the full screen dialog. */
private final @NonNull IncognitoReauthMenuDelegate mIncognitoReauthMenuDelegate;
private final IncognitoReauthMenuDelegate mIncognitoReauthMenuDelegate;
/**
* The callback which would be fired when the user press back while the re-auth dialog is
* shown.
* The callback which would be fired when the user press back while the re-auth dialog is shown.
*/
private final @NonNull OnBackPressedCallback mOnBackPressedCallback;
private final OnBackPressedCallback mOnBackPressedCallback;
/** The dialog which contains the logic to show the re-auth full-screen. */
private IncognitoReauthDialog mIncognitoReauthDialog;
/** The dialog which contains the logic to show the re-auth full-screen. */
private @Nullable IncognitoReauthDialog mIncognitoReauthDialog;
/** Test-only method to ignore the assertion check on the dialog. */
@VisibleForTesting boolean mIgnoreDialogCreationForTesting;
/**
* @param context The {@link Context} to use for fetching the re-auth resources.
* @param incognitoReauthManager The {@link IncognitoReauthManager} instance which would be
* used to initiate re-authentication.
* @param incognitoReauthManager The {@link IncognitoReauthManager} instance which would be used
* to initiate re-authentication.
* @param incognitoReauthCallback The {@link IncognitoReauthCallback} which would be executed
* after an authentication attempt.
* @param seeOtherTabsRunnable A {@link Runnable} which is run when the user clicks on
* "See other tabs" option.
* after an authentication attempt.
* @param seeOtherTabsRunnable A {@link Runnable} which is run when the user clicks on "See
* other tabs" option.
* @param modalDialogManager The {@link ModalDialogManager} which is used to fire the dialog
* containing the Incognito re-auth view.
* containing the Incognito re-auth view.
* @param incognitoReauthMenuDelegate The {@link IncognitoReauthMenuDelegate} responsible for
* @param backPressedCallback The {@link OnBackPressedCallback} which would be called when a
* user presses back while the fullscreen re-auth is shown.
* user presses back while the fullscreen re-auth is shown.
*/
public FullScreenIncognitoReauthCoordinator(
@NonNull Context context,
@NonNull IncognitoReauthManager incognitoReauthManager,
@NonNull IncognitoReauthCallback incognitoReauthCallback,
@NonNull Runnable seeOtherTabsRunnable,
@NonNull ModalDialogManager modalDialogManager,
@NonNull IncognitoReauthMenuDelegate incognitoReauthMenuDelegate,
@NonNull OnBackPressedCallback backPressedCallback) {
Context context,
IncognitoReauthManager incognitoReauthManager,
IncognitoReauthCallback incognitoReauthCallback,
Runnable seeOtherTabsRunnable,
ModalDialogManager modalDialogManager,
IncognitoReauthMenuDelegate incognitoReauthMenuDelegate,
OnBackPressedCallback backPressedCallback) {
super(context, incognitoReauthManager, incognitoReauthCallback, seeOtherTabsRunnable);
mOnBackPressedCallback = backPressedCallback;
mModalDialogManager = modalDialogManager;
@ -73,7 +76,7 @@ class FullScreenIncognitoReauthCoordinator extends IncognitoReauthCoordinatorBas
new IncognitoReauthDialog(
mModalDialogManager, getIncognitoReauthView(), mOnBackPressedCallback);
}
assumeNonNull(mIncognitoReauthDialog);
mIncognitoReauthDialog.showIncognitoReauthDialog();
}

@ -4,7 +4,7 @@
package org.chromium.chrome.browser.incognito.reauth;
import androidx.annotation.NonNull;
import org.chromium.build.annotations.NullMarked;
/**
* A public API which can be used by other non re-auth clients to get information about the
@ -13,6 +13,7 @@ import androidx.annotation.NonNull;
* <p>TODO(crbug.com/40056462): Move this to a separate incognito public_api target and add tests
* for this public interface.
*/
@NullMarked
public interface IncognitoReauthController {
/**
* @return True if the Incognito re-auth page is currently being shown, false otherwise.
@ -28,19 +29,19 @@ public interface IncognitoReauthController {
* A method to add an {@link IncognitoReauthCallback}.
*
* @param incognitoReauthCallback {@link IncognitoReauthCallback} that the clients can add to be
* notified when the user attempts re-authentication in the Incognito page.
* notified when the user attempts re-authentication in the Incognito page.
*/
void addIncognitoReauthCallback(
@NonNull IncognitoReauthManager.IncognitoReauthCallback incognitoReauthCallback);
IncognitoReauthManager.IncognitoReauthCallback incognitoReauthCallback);
/**
* A method to remove the {@link IncognitoReauthCallback}.
*
* @param incognitoReauthCallback {@link IncognitoReauthCallback} that the clients added to be
* notified when the user attempts re-authentication in the Incognito page.
* notified when the user attempts re-authentication in the Incognito page.
*/
void removeIncognitoReauthCallback(
@NonNull IncognitoReauthManager.IncognitoReauthCallback incognitoReauthCallback);
IncognitoReauthManager.IncognitoReauthCallback incognitoReauthCallback);
/**
* TODO(crbug.com/40056462): This method is ill-placed. Find a better design to restrict

@ -4,11 +4,11 @@
package org.chromium.chrome.browser.incognito.reauth;
import static org.chromium.build.NullUtil.assumeNonNull;
import android.os.Bundle;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.chromium.base.ApplicationStatus;
import org.chromium.base.Callback;
@ -17,6 +17,8 @@ import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.supplier.ObservableSupplier;
import org.chromium.base.supplier.OneshotSupplier;
import org.chromium.base.supplier.Supplier;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
import org.chromium.chrome.browser.layouts.LayoutStateProvider;
import org.chromium.chrome.browser.layouts.LayoutType;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
@ -40,6 +42,7 @@ import java.util.List;
* <p>TODO(crbug.com/40056462): Change the scope of this to make it package protected and design a
* way to create and destroy this for {@link RootUiCoordinator}.
*/
@NullMarked
public class IncognitoReauthControllerImpl
implements IncognitoReauthController,
IncognitoTabModelObserver.IncognitoReauthDialogDelegate,
@ -126,7 +129,7 @@ public class IncognitoReauthControllerImpl
private final Callback<Profile> mProfileSupplierCallback =
new Callback<Profile>() {
@Override
public void onResult(@NonNull Profile profile) {
public void onResult(Profile profile) {
mProfile = profile;
showDialogIfRequired();
if (!mIsStartupMetricsRecorded) {
@ -143,10 +146,10 @@ public class IncognitoReauthControllerImpl
*/
private final CallbackController mCallbackController = new CallbackController();
private final @NonNull ActivityLifecycleDispatcher mActivityLifecycleDispatcher;
private final @NonNull TabModelSelector mTabModelSelector;
private final @NonNull ObservableSupplier<Profile> mProfileObservableSupplier;
private final @NonNull IncognitoReauthCoordinatorFactory mIncognitoReauthCoordinatorFactory;
private final ActivityLifecycleDispatcher mActivityLifecycleDispatcher;
private final TabModelSelector mTabModelSelector;
private final ObservableSupplier<Profile> mProfileObservableSupplier;
private final IncognitoReauthCoordinatorFactory mIncognitoReauthCoordinatorFactory;
private final int mTaskId;
private final boolean mIsTabbedActivity;
@ -155,11 +158,11 @@ public class IncognitoReauthControllerImpl
* back-presses. The back press handling for re-auth view shown inside tab switcher is
* controlled elsewhere.
*
* Note that {@link BackPressManager} doesn't support handling back presses done
* when a dialog is being shown. The integration of back press for app modal dialog is done
* via {@link ModalDialogProperties#APP_MODAL_DIALOG_BACK_PRESS_HANDLER}.
* <p>Note that {@link BackPressManager} doesn't support handling back presses done when a
* dialog is being shown. The integration of back press for app modal dialog is done via {@link
* ModalDialogProperties#APP_MODAL_DIALOG_BACK_PRESS_HANDLER}.
*/
private final @NonNull OnBackPressedCallback mOnBackPressedInFullScreenReauthCallback =
private final OnBackPressedCallback mOnBackPressedInFullScreenReauthCallback =
new OnBackPressedCallback(false) {
@Override
public void handleOnBackPressed() {
@ -171,13 +174,13 @@ public class IncognitoReauthControllerImpl
* {@link Runnable} which would be called when back press is triggered when we are showing the
* fullscreen re-auth. Back presses done from tab switcher re-auth screen, is handled elsewhere.
*/
private final @NonNull Runnable mBackPressInReauthFullScreenRunnable;
private final Runnable mBackPressInReauthFullScreenRunnable;
/**
* A supplier to indicate if the re-auth was pending in the previous Chrome session before it
* was destroyed.
*/
private final @NonNull Supplier<Boolean> mIsIncognitoReauthPendingOnRestoreSupplier;
private final Supplier<Boolean> mIsIncognitoReauthPendingOnRestoreSupplier;
// No strong reference to this should be made outside of this class because
// we set this to null in hideDialogIfShowing for it to be garbage collected.
@ -190,25 +193,25 @@ public class IncognitoReauthControllerImpl
/**
* @param tabModelSelector The {@link TabModelSelector} in order to interact with the
* regular/Incognito {@link TabModel}.
* regular/Incognito {@link TabModel}.
* @param dispatcher The {@link ActivityLifecycleDispatcher} in order to register to
* onStartWithNative event.
* onStartWithNative event.
* @param layoutStateProviderOneshotSupplier A supplier of {@link LayoutStateProvider} which is
* used to determine the current {@link LayoutType} which is shown.
* used to determine the current {@link LayoutType} which is shown.
* @param profileSupplier A Observable Supplier of {@link Profile} which is used to query the
* preference value of the Incognito lock setting.
* preference value of the Incognito lock setting.
* @param incognitoReauthPendingOnRestoreSupplier Supplier to indicate where the {@link
* IncognitoReauthControllerImpl#KEY_IS_INCOGNITO_REAUTH_PENDING} was set to true in the
* saved instance state.
* IncognitoReauthControllerImpl#KEY_IS_INCOGNITO_REAUTH_PENDING} was set to true in the
* saved instance state.
* @param taskId The task Id of the {@link ChromeActivity} associated with this controller.
*/
public IncognitoReauthControllerImpl(
@NonNull TabModelSelector tabModelSelector,
@NonNull ActivityLifecycleDispatcher dispatcher,
@NonNull OneshotSupplier<LayoutStateProvider> layoutStateProviderOneshotSupplier,
@NonNull ObservableSupplier<Profile> profileSupplier,
@NonNull IncognitoReauthCoordinatorFactory incognitoReauthCoordinatorFactory,
@NonNull Supplier<Boolean> incognitoReauthPendingOnRestoreSupplier,
TabModelSelector tabModelSelector,
ActivityLifecycleDispatcher dispatcher,
OneshotSupplier<LayoutStateProvider> layoutStateProviderOneshotSupplier,
ObservableSupplier<Profile> profileSupplier,
IncognitoReauthCoordinatorFactory incognitoReauthCoordinatorFactory,
Supplier<Boolean> incognitoReauthPendingOnRestoreSupplier,
int taskId) {
mTabModelSelector = tabModelSelector;
mActivityLifecycleDispatcher = dispatcher;
@ -251,9 +254,10 @@ public class IncognitoReauthControllerImpl
/**
* Override from {@link IncognitoReauthController}.
*
* Should be called when the underlying {@link ChromeActivity} is destroyed.
* <p>Should be called when the underlying {@link ChromeActivity} is destroyed.
*/
@Override
@SuppressWarnings("NullAway")
public void destroy() {
ApplicationStatus.unregisterTaskVisibilityListener(this);
mActivityLifecycleDispatcher.unregister(this);
@ -284,13 +288,14 @@ public class IncognitoReauthControllerImpl
@Override
public boolean isIncognitoReauthPending() {
// A re-authentication is pending only in the context when the re-auth setting is always on.
assumeNonNull(mProfile);
return mIncognitoReauthPending && IncognitoReauthManager.isIncognitoReauthEnabled(mProfile);
}
/** Override from {@link IncognitoReauthController}. */
@Override
public void addIncognitoReauthCallback(
@NonNull IncognitoReauthManager.IncognitoReauthCallback incognitoReauthCallback) {
IncognitoReauthManager.IncognitoReauthCallback incognitoReauthCallback) {
if (!mIncognitoReauthCallbackList.contains(incognitoReauthCallback)) {
mIncognitoReauthCallbackList.add(incognitoReauthCallback);
}
@ -299,7 +304,7 @@ public class IncognitoReauthControllerImpl
/** Override from {@link IncognitoReauthController}. */
@Override
public void removeIncognitoReauthCallback(
@NonNull IncognitoReauthManager.IncognitoReauthCallback incognitoReauthCallback) {
IncognitoReauthManager.IncognitoReauthCallback incognitoReauthCallback) {
mIncognitoReauthCallbackList.remove(incognitoReauthCallback);
}
@ -368,7 +373,8 @@ public class IncognitoReauthControllerImpl
boolean showFullScreen =
!mIsTabbedActivity
|| !mLayoutStateProvider.isLayoutVisible(LayoutType.TAB_SWITCHER);
|| !assumeNonNull(mLayoutStateProvider)
.isLayoutVisible(LayoutType.TAB_SWITCHER);
if (!mIncognitoReauthCoordinatorFactory.areDependenciesReadyFor(showFullScreen)) {
return;
}

@ -4,6 +4,7 @@
package org.chromium.chrome.browser.incognito.reauth;
import org.chromium.build.annotations.NullMarked;
import org.chromium.ui.modaldialog.DialogDismissalCause;
/**
@ -16,6 +17,7 @@ import org.chromium.ui.modaldialog.DialogDismissalCause;
* <p>TODO(crbug.com/40056462): This and any other internal re-auth related files should be put in
* an internal folder. Ideally only the controller would be potentially exposed.
*/
@NullMarked
interface IncognitoReauthCoordinator {
/** A method responsible to fire the re-auth screen. */
void show();

@ -10,10 +10,10 @@ import android.content.Context;
import android.view.LayoutInflater;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
import org.chromium.chrome.browser.incognito.R;
import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthManager.IncognitoReauthCallback;
import org.chromium.ui.listmenu.ListMenuDelegate;
@ -24,24 +24,25 @@ import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
* An abstract base class responsible for setting up the mediator, property model and the re-auth
* view.
*/
@NullMarked
abstract class IncognitoReauthCoordinatorBase implements IncognitoReauthCoordinator {
/** The context to use to inflate the re-auth view and access other resources.*/
protected final @NonNull Context mContext;
/** The context to use to inflate the re-auth view and access other resources. */
protected final Context mContext;
/** The mediator which is responsible for handling the interaction done within the view.*/
/** The mediator which is responsible for handling the interaction done within the view. */
private final IncognitoReauthMediator mIncognitoReauthMediator;
/**
* The model change processor for the re-auth view which triggers the binded method associated
* with the {@link PropertyModel} which got changed.
*/
private PropertyModelChangeProcessor mModelChangeProcessor;
private @Nullable PropertyModelChangeProcessor mModelChangeProcessor;
/** The property model container for {@link IncognitoReauthProperties}. */
private PropertyModel mPropertyModel;
private @Nullable PropertyModel mPropertyModel;
/** The actual underlying re-auth view.*/
private View mIncognitoReauthView;
/** The actual underlying re-auth view. */
private @Nullable View mIncognitoReauthView;
/**
* Test-only method to ignore the assertion on null checks, and use the respective view, model
@ -51,18 +52,18 @@ abstract class IncognitoReauthCoordinatorBase implements IncognitoReauthCoordina
/**
* @param context The {@link Context} to use for inflating the re-auth view.
* @param incognitoReauthManager The {@link IncognitoReauthManager} instance which would be
* used to initiate re-authentication.
* @param incognitoReauthManager The {@link IncognitoReauthManager} instance which would be used
* to initiate re-authentication.
* @param incognitoReauthCallback The {@link IncognitoReauthCallback} which would be executed
* after an authentication attempt.
* @param seeOtherTabsRunnable A {@link Runnable} which is run when the user clicks on
* "See other tabs" option.
* after an authentication attempt.
* @param seeOtherTabsRunnable A {@link Runnable} which is run when the user clicks on "See
* other tabs" option.
*/
public IncognitoReauthCoordinatorBase(
@NonNull Context context,
@NonNull IncognitoReauthManager incognitoReauthManager,
@NonNull IncognitoReauthCallback incognitoReauthCallback,
@NonNull Runnable seeOtherTabsRunnable) {
Context context,
IncognitoReauthManager incognitoReauthManager,
IncognitoReauthCallback incognitoReauthCallback,
Runnable seeOtherTabsRunnable) {
mContext = context;
mIncognitoReauthMediator =
new IncognitoReauthMediator(

@ -4,16 +4,18 @@
package org.chromium.chrome.browser.incognito.reauth;
import static org.chromium.build.NullUtil.assumeNonNull;
import android.content.Context;
import android.content.Intent;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;
import org.chromium.base.supplier.OneshotSupplier;
import org.chromium.base.supplier.OneshotSupplierImpl;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
import org.chromium.chrome.browser.hub.HubManager;
import org.chromium.chrome.browser.hub.PaneId;
import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthManager.IncognitoReauthCallback;
@ -25,21 +27,22 @@ import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.ui.modaldialog.ModalDialogManager;
/** A factory to create an {@link IncognitoReauthCoordinator} instance. */
@NullMarked
public class IncognitoReauthCoordinatorFactory {
/** The context to use in order to inflate the re-auth view and fetch the resources. */
private final @NonNull Context mContext;
private final Context mContext;
/**
* The {@link TabModelSelector} instance used for providing functionality to toggle between tab
* models and to close Incognito tabs.
*/
private final @NonNull TabModelSelector mTabModelSelector;
private final TabModelSelector mTabModelSelector;
/** The manager responsible for showing the full screen Incognito re-auth dialog. */
private final @NonNull ModalDialogManager mModalDialogManager;
private final ModalDialogManager mModalDialogManager;
/** The manager responsible for invoking the underlying native re-authentication. */
private final @NonNull IncognitoReauthManager mIncognitoReauthManager;
private final IncognitoReauthManager mIncognitoReauthManager;
/**
* A boolean to distinguish between tabbedActivity or CCT, during coordinator creation.
@ -69,7 +72,7 @@ public class IncognitoReauthCoordinatorFactory {
private @Nullable Intent mShowRegularOverviewIntent;
/** A test-only variable used to mock the menu delegate instead of creating one. */
@VisibleForTesting IncognitoReauthMenuDelegate mIncognitoReauthMenuDelegateForTesting;
@VisibleForTesting @Nullable IncognitoReauthMenuDelegate mIncognitoReauthMenuDelegateForTesting;
/**
* @param context The {@link Context} to use for fetching the re-auth resources.
@ -85,10 +88,10 @@ public class IncognitoReauthCoordinatorFactory {
* @param isTabbedActivity A boolean to indicate if the re-auth screen being fired from
*/
public IncognitoReauthCoordinatorFactory(
@NonNull Context context,
@NonNull TabModelSelector tabModelSelector,
@NonNull ModalDialogManager modalDialogManager,
@NonNull IncognitoReauthManager incognitoReauthManager,
Context context,
TabModelSelector tabModelSelector,
ModalDialogManager modalDialogManager,
IncognitoReauthManager incognitoReauthManager,
@Nullable LayoutManager layoutManager,
@Nullable OneshotSupplier<HubManager> hubManagerSupplier,
@Nullable Intent showRegularOverviewIntent,
@ -109,10 +112,10 @@ public class IncognitoReauthCoordinatorFactory {
/**
* @param tabSwitcherCustomViewManager {@link TabSwitcherCustomViewManager} to use for
* communicating with tab switcher to show the re-auth screen.
* communicating with tab switcher to show the re-auth screen.
*/
public void setTabSwitcherCustomViewManager(
@NonNull TabSwitcherCustomViewManager tabSwitcherCustomViewManager) {
TabSwitcherCustomViewManager tabSwitcherCustomViewManager) {
mTabSwitcherCustomViewManagerSupplier.set(tabSwitcherCustomViewManager);
}
@ -148,7 +151,9 @@ public class IncognitoReauthCoordinatorFactory {
if (mIsTabbedActivity) {
return () -> {
mTabModelSelector.selectModel(/* incognito= */ false);
assumeNonNull(mLayoutManager);
if (mLayoutManager.isLayoutVisible(LayoutType.TAB_SWITCHER)) {
assumeNonNull(mHubManagerSupplier);
mHubManagerSupplier.runSyncOrOnAvailable(
hubManager ->
hubManager.getPaneManager().focusPane(PaneId.TAB_SWITCHER));
@ -194,21 +199,19 @@ public class IncognitoReauthCoordinatorFactory {
}
/**
* @param incognitoReauthCallback The {@link IncognitoReauthCallback}
* which would be executed after an authentication attempt.
* @param incognitoReauthCallback The {@link IncognitoReauthCallback} which would be executed
* after an authentication attempt.
* @param showFullScreen A boolean indicating whether to show a fullscreen or tab switcher
* Incognito reauth.
*
* Incognito reauth.
* @param backPressedCallback {@link OnBackPressedCallback} which would be called when a user
* presses back while the fullscreen re-auth is shown.
*
* presses back while the fullscreen re-auth is shown.
* @return {@link IncognitoReauthCoordinator} instance spliced on fullscreen/tab-switcher and
* tabbedActivity/CCT.
* tabbedActivity/CCT.
*/
IncognitoReauthCoordinator createIncognitoReauthCoordinator(
@NonNull IncognitoReauthCallback incognitoReauthCallback,
IncognitoReauthCallback incognitoReauthCallback,
boolean showFullScreen,
@NonNull OnBackPressedCallback backPressedCallback) {
OnBackPressedCallback backPressedCallback) {
assert areDependenciesReadyFor(showFullScreen)
: "Dependencies for the IncognitoReauthCoordinator were not ready.";
return showFullScreen
@ -226,6 +229,6 @@ public class IncognitoReauthCoordinatorFactory {
incognitoReauthCallback,
getSeeOtherTabsRunnable(),
getBackPressRunnable(),
mTabSwitcherCustomViewManagerSupplier.get());
assumeNonNull(mTabSwitcherCustomViewManagerSupplier.get()));
}
}

@ -7,21 +7,22 @@ package org.chromium.chrome.browser.incognito.reauth;
import android.view.View;
import androidx.activity.OnBackPressedCallback;
import androidx.annotation.NonNull;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
import org.chromium.ui.modaldialog.DialogDismissalCause;
import org.chromium.ui.modaldialog.ModalDialogManager;
import org.chromium.ui.modaldialog.ModalDialogProperties;
import org.chromium.ui.modelutil.PropertyModel;
/** Manages the actual showing and hiding of the full screen Incognito re-auth modal dialog. */
@NullMarked
class IncognitoReauthDialog {
/** The {@link ModalDialogManager} which launches the full-screen re-auth dialog. */
private final @NonNull ModalDialogManager mModalDialogManager;
private final ModalDialogManager mModalDialogManager;
/**
* The modal dialog controller to detect events on the dialog but it's not needed in our
* case.
* The modal dialog controller to detect events on the dialog but it's not needed in our case.
*/
private final ModalDialogProperties.Controller mModalDialogController =
new ModalDialogProperties.Controller() {
@ -36,16 +37,16 @@ class IncognitoReauthDialog {
private final PropertyModel mModalDialogPropertyModel;
/**
* @param modalDialogManager The {@link ModalDialogManager} which is used to fire the
* dialog containing the Incognito re-auth view.
* @param modalDialogManager The {@link ModalDialogManager} which is used to fire the dialog
* containing the Incognito re-auth view.
* @param incognitoReauthView The underlying Incognito re-auth {@link View} to use as custom
* @param backPressedCallback {@link OnBackPressedCallback} which would be called when a user
* presses back while the fullscreen re-auth is shown.
* presses back while the fullscreen re-auth is shown.
*/
IncognitoReauthDialog(
@NonNull ModalDialogManager modalDialogManager,
@NonNull View incognitoReauthView,
@NonNull OnBackPressedCallback backPressedCallback) {
ModalDialogManager modalDialogManager,
@Nullable View incognitoReauthView,
OnBackPressedCallback backPressedCallback) {
mModalDialogManager = modalDialogManager;
mModalDialogPropertyModel =
new PropertyModel.Builder(ModalDialogProperties.ALL_KEYS)

@ -7,10 +7,11 @@ package org.chromium.chrome.browser.incognito.reauth;
import android.app.Activity;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import org.chromium.base.ResettersForTesting;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
import org.chromium.chrome.browser.device_reauth.BiometricStatus;
import org.chromium.chrome.browser.device_reauth.DeviceAuthSource;
import org.chromium.chrome.browser.device_reauth.ReauthenticatorBridge;
@ -19,8 +20,9 @@ import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.components.user_prefs.UserPrefs;
/** This class is responsible for managing the Incognito re-authentication flow. */
@NullMarked
public class IncognitoReauthManager {
private static Boolean sIsIncognitoReauthFeatureAvailableForTesting;
private static @Nullable Boolean sIsIncognitoReauthFeatureAvailableForTesting;
private ReauthenticatorBridge mReauthenticatorBridge;
/**
@ -55,8 +57,7 @@ public class IncognitoReauthManager {
* @param incognitoReauthCallback A {@link IncognitoReauthCallback} callback that would be run
* once the authentication is executed.
*/
public void startReauthenticationFlow(
@NonNull IncognitoReauthCallback incognitoReauthCallback) {
public void startReauthenticationFlow(IncognitoReauthCallback incognitoReauthCallback) {
if (mReauthenticatorBridge.getBiometricAvailabilityStatus() == BiometricStatus.UNAVAILABLE
|| !isIncognitoReauthFeatureAvailable()) {
incognitoReauthCallback.onIncognitoReauthNotPossible();
@ -101,7 +102,7 @@ public class IncognitoReauthManager {
* Incognito lock setting.
* @return A boolean indicating if Incognito re-authentication is possible or not.
*/
public static boolean isIncognitoReauthEnabled(@NonNull Profile profile) {
public static boolean isIncognitoReauthEnabled(Profile profile) {
return isIncognitoReauthFeatureAvailable()
&& IncognitoReauthSettingUtils.isDeviceScreenLockEnabled()
&& isIncognitoReauthSettingEnabled(profile);

@ -3,11 +3,11 @@
// found in the LICENSE file.
package org.chromium.chrome.browser.incognito.reauth;
import androidx.annotation.NonNull;
import org.chromium.build.annotations.NullMarked;
import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthManager.IncognitoReauthCallback;
/** The mediator responsible for handling the interactions with the incognito re-auth view. */
@NullMarked
class IncognitoReauthMediator {
private final Runnable mShowTabSwitcherRunnable;
// The entity responsible for actually calling the underlying system re-authentication.
@ -17,15 +17,15 @@ class IncognitoReauthMediator {
/**
* @param incognitoReauthCallback incognitoReauthCallback The {@link IncognitoReauthCallback}
* which would be executed after an authentication attempt.
* which would be executed after an authentication attempt.
* @param incognitoReauthManager The {@link IncognitoReauthManager} instance which would be used
* to initiate re-authentication.
* to initiate re-authentication.
* @param showTabSwitcherRunnable A {link Runnable} to show the tab switcher UI.
*/
IncognitoReauthMediator(
@NonNull IncognitoReauthCallback incognitoReauthCallback,
@NonNull IncognitoReauthManager incognitoReauthManager,
@NonNull Runnable showTabSwitcherRunnable) {
IncognitoReauthCallback incognitoReauthCallback,
IncognitoReauthManager incognitoReauthManager,
Runnable showTabSwitcherRunnable) {
mIncognitoReauthCallback = incognitoReauthCallback;
mIncognitoReauthManager = incognitoReauthManager;
mShowTabSwitcherRunnable = showTabSwitcherRunnable;

@ -4,14 +4,16 @@
package org.chromium.chrome.browser.incognito.reauth;
import static org.chromium.build.NullUtil.assumeNonNull;
import android.content.Context;
import androidx.annotation.DrawableRes;
import androidx.annotation.IdRes;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.StringRes;
import org.chromium.build.annotations.NullMarked;
import org.chromium.chrome.browser.incognito.R;
import org.chromium.chrome.browser.settings.SettingsNavigationFactory;
import org.chromium.components.browser_ui.widget.BrowserUiListMenuUtils;
@ -26,10 +28,11 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/** A delegate for the menu button present inside the Incognito re-auth view full page. */
@NullMarked
class IncognitoReauthMenuDelegate implements ListMenu.Delegate {
/**
* An enum interface denoting the various options (in-order) present in the
* three dots menu in the incognito re-auth full page view.
* An enum interface denoting the various options (in-order) present in the three dots menu in
* the incognito re-auth full page view.
*/
@Retention(RetentionPolicy.SOURCE)
@IntDef({MenuItemType.CLOSE_INCOGNITO_TABS, MenuItemType.SETTINGS})
@ -47,8 +50,7 @@ class IncognitoReauthMenuDelegate implements ListMenu.Delegate {
* @param closeAllIncognitoTabRunnable The {@link Runnable} which would be used to close the
* Incognito tabs when the user clicks on "Close Incognito tabs" option.
*/
IncognitoReauthMenuDelegate(
@NonNull Context context, @NonNull Runnable closeAllIncognitoTabRunnable) {
IncognitoReauthMenuDelegate(Context context, Runnable closeAllIncognitoTabRunnable) {
mContext = context;
mCloseAllIncognitoTabsRunnable = closeAllIncognitoTabRunnable;
mIncognitoReauthMenu = buildIncognitoReauthMenu();
@ -121,7 +123,7 @@ class IncognitoReauthMenuDelegate implements ListMenu.Delegate {
/* textEllipsizedAtEnd= */ true);
default:
assert false : "Not implemented yet.";
return null;
return assumeNonNull(null);
}
}

@ -4,14 +4,15 @@
package org.chromium.chrome.browser.incognito.reauth;
import androidx.annotation.Nullable;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
import org.chromium.ui.listmenu.ListMenuDelegate;
import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.PropertyModel.ReadableBooleanPropertyKey;
import org.chromium.ui.modelutil.PropertyModel.ReadableObjectPropertyKey;
@NullMarked
class IncognitoReauthProperties {
public static final ReadableObjectPropertyKey<Runnable> ON_UNLOCK_INCOGNITO_CLICKED =
new ReadableObjectPropertyKey<>("on_unlock_incognito_clicked");
@ -35,9 +36,9 @@ class IncognitoReauthProperties {
* other tabs" button.
* @param fullscreen A boolean indicating whether the incognito re-auth view needs to be shown
* fullscreen style or tab-switcher style.
* @param menuButtonDelegate A {@link ListMenuDelegate} which would be triggered when the
* user interact with the three dots menu view in fullscreen re-auth page. This is null when
* we show the non full-screen re-auth page.
* @param menuButtonDelegate A {@link ListMenuDelegate} which would be triggered when the user
* interact with the three dots menu view in fullscreen re-auth page. This is null when we
* show the non full-screen re-auth page.
* @return A {@link PropertyModel} instance for the incognito re-auth view with the above
* attributes.
*/

@ -12,6 +12,8 @@ import android.widget.TextView;
import androidx.annotation.VisibleForTesting;
import androidx.preference.PreferenceViewHolder;
import org.chromium.build.annotations.MonotonicNonNull;
import org.chromium.build.annotations.NullMarked;
import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
import org.chromium.ui.base.ViewUtils;
@ -22,12 +24,13 @@ import org.chromium.ui.base.ViewUtils;
* below 48dp in height which is currently the case for this summary where we add a clickable
* action. The surface of the clickable action needs to be revisited after discussing with the UX.
*/
@NullMarked
public class IncognitoReauthSettingSwitchPreference extends ChromeSwitchPreference {
/** A boolean to indicate whether the preference should be interactable or not.*/
/** A boolean to indicate whether the preference should be interactable or not. */
private boolean mPreferenceInteractable;
/** The action to perform when the summary is clicked.*/
private Runnable mLinkClickDelegate;
/** The action to perform when the summary is clicked. */
private @MonotonicNonNull Runnable mLinkClickDelegate;
public IncognitoReauthSettingSwitchPreference(Context context) {
super(context);

@ -14,13 +14,16 @@ import android.text.style.ForegroundColorSpan;
import org.chromium.base.ContextUtils;
import org.chromium.base.ResettersForTesting;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
import org.chromium.chrome.browser.incognito.R;
import org.chromium.components.browser_ui.styles.SemanticColorUtils;
import org.chromium.ui.text.SpanApplier;
/** A utility class to provide helper methods for the Incognito re-authentication lock setting. */
@NullMarked
public class IncognitoReauthSettingUtils {
private static Boolean sIsDeviceScreenLockEnabledForTesting;
private static @Nullable Boolean sIsDeviceScreenLockEnabledForTesting;
/**
* @return A boolean indicating if the screen lock is enabled in device or not.

@ -6,14 +6,15 @@ package org.chromium.chrome.browser.incognito.reauth;
import android.view.View;
import androidx.annotation.Nullable;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
import org.chromium.chrome.browser.incognito.R;
import org.chromium.ui.listmenu.ListMenuButton;
import org.chromium.ui.listmenu.ListMenuDelegate;
import org.chromium.ui.modelutil.PropertyKey;
import org.chromium.ui.modelutil.PropertyModel;
@NullMarked
class IncognitoReauthViewBinder {
public static void bind(
PropertyModel model, View incognitoReauthView, PropertyKey propertyKey) {

@ -4,21 +4,23 @@
package org.chromium.chrome.browser.incognito.reauth;
import static org.chromium.build.NullUtil.assumeNonNull;
import android.content.Context;
import androidx.annotation.NonNull;
import org.chromium.build.annotations.NullMarked;
import org.chromium.chrome.browser.incognito.reauth.IncognitoReauthManager.IncognitoReauthCallback;
import org.chromium.chrome.browser.tab_ui.TabSwitcherCustomViewManager;
import org.chromium.ui.modaldialog.DialogDismissalCause;
/** The coordinator responsible for showing the tab-switcher re-auth screen. */
@NullMarked
class TabSwitcherIncognitoReauthCoordinator extends IncognitoReauthCoordinatorBase {
/** A manager which allows to pass the re-auth view to the tab switcher. */
private final @NonNull TabSwitcherCustomViewManager mTabSwitcherCustomViewManager;
private final TabSwitcherCustomViewManager mTabSwitcherCustomViewManager;
/** A runnable to handle back presses which shows the regular overview mode. */
private final @NonNull Runnable mBackPressRunnable;
private final Runnable mBackPressRunnable;
/**
* @param context The {@link Context} to use for fetching the re-auth resources.
@ -34,12 +36,12 @@ class TabSwitcherIncognitoReauthCoordinator extends IncognitoReauthCoordinatorBa
* pass the re-auth view to the tab switcher
*/
public TabSwitcherIncognitoReauthCoordinator(
@NonNull Context context,
@NonNull IncognitoReauthManager incognitoReauthManager,
@NonNull IncognitoReauthCallback incognitoReauthCallback,
@NonNull Runnable seeOtherTabsRunnable,
@NonNull Runnable backPressRunnable,
@NonNull TabSwitcherCustomViewManager tabSwitcherCustomViewManager) {
Context context,
IncognitoReauthManager incognitoReauthManager,
IncognitoReauthCallback incognitoReauthCallback,
Runnable seeOtherTabsRunnable,
Runnable backPressRunnable,
TabSwitcherCustomViewManager tabSwitcherCustomViewManager) {
super(context, incognitoReauthManager, incognitoReauthCallback, seeOtherTabsRunnable);
mTabSwitcherCustomViewManager = tabSwitcherCustomViewManager;
mBackPressRunnable = backPressRunnable;
@ -51,7 +53,9 @@ class TabSwitcherIncognitoReauthCoordinator extends IncognitoReauthCoordinatorBa
prepareToShow(/* menuButtonDelegate= */ null, /* fullscreen= */ false);
boolean success =
mTabSwitcherCustomViewManager.requestView(
getIncognitoReauthView(), mBackPressRunnable, /* clearTabList= */ true);
assumeNonNull(getIncognitoReauthView()),
mBackPressRunnable,
/* clearTabList= */ true);
assert success : "Unable to signal showing the re-auth screen to tab switcher.";
}

@ -4,10 +4,13 @@
package org.chromium.chrome.browser.tab_ui;
import org.chromium.build.annotations.NullMarked;
/**
* Simple data class that holds information to show or not show a notification dot for the whole tab
* model.
*/
@NullMarked
public class TabModelDotInfo {
public static final TabModelDotInfo HIDE = new TabModelDotInfo(false, "");

@ -9,6 +9,7 @@ import android.text.TextUtils;
import android.util.AttributeSet;
import org.chromium.build.annotations.NullMarked;
import org.chromium.build.annotations.Nullable;
import org.chromium.ui.R;
import org.chromium.ui.widget.ChromeImageButton;
@ -57,7 +58,7 @@ public class ListMenuButton extends ChromeImageButton {
*
* @param delegate The {@link ListMenuDelegate} to use for menu creation and selection handling.
*/
public void setDelegate(ListMenuDelegate delegate) {
public void setDelegate(@Nullable ListMenuDelegate delegate) {
setDelegate(delegate, true);
}
@ -69,7 +70,7 @@ public class ListMenuButton extends ChromeImageButton {
* @param overrideOnClickListener Whether to override the click listener which can trigger the
* popup menu.
*/
public void setDelegate(ListMenuDelegate delegate, boolean overrideOnClickListener) {
public void setDelegate(@Nullable ListMenuDelegate delegate, boolean overrideOnClickListener) {
mListMenuHost.setDelegate(delegate, overrideOnClickListener);
}

@ -99,7 +99,7 @@ public class ListMenuHost implements AnchoredPopupWindow.LayoutObserver {
* @param overrideOnClickListener Whether to override the click listener which can trigger the
* popup menu.
*/
public void setDelegate(ListMenuDelegate delegate, boolean overrideOnClickListener) {
public void setDelegate(@Nullable ListMenuDelegate delegate, boolean overrideOnClickListener) {
dismiss();
mDelegate = delegate;
if (overrideOnClickListener) {