diff --git a/build/patches/Add-an-always-incognito-mode.patch b/build/patches/Add-an-always-incognito-mode.patch index 802e26bb..83ac64f7 100644 --- a/build/patches/Add-an-always-incognito-mode.patch +++ b/build/patches/Add-an-always-incognito-mode.patch @@ -13,81 +13,88 @@ flag turned on. IncognitoPlaceholder is also deactivated, both in the phone and tablet version. The relative tests are also present. +based on the original work by Ryan Archer See also: https://github.com/bromite/bromite/pull/1427 --- - chrome/android/chrome_java_sources.gni | 1 + - .../chrome_junit_test_java_sources.gni | 4 + - chrome/android/chrome_test_java_sources.gni | 6 + - .../java/res/xml/privacy_preferences.xml | 10 + - .../AlwaysIncognitoLinkInterceptor.java | 53 +++ + chrome/android/chrome_java_resources.gni | 1 + + chrome/android/chrome_java_sources.gni | 2 + + .../java/res/xml/incognito_preferences.xml | 37 ++++ + .../java/res/xml/privacy_preferences.xml | 5 + + .../AlwaysIncognitoLinkInterceptor.java | 53 ++++++ .../chrome/browser/ChromeTabbedActivity.java | 6 +- .../chrome/browser/app/ChromeActivity.java | 4 + - .../AppMenuPropertiesDelegateImpl.java | 33 +- + .../AppMenuPropertiesDelegateImpl.java | 33 +++- .../ChromeContextMenuPopulator.java | 7 +- - .../CustomTabActivityLifecycleUmaTracker.java | 25 -- + .../CustomTabActivityLifecycleUmaTracker.java | 25 --- .../CustomTabAppMenuPropertiesDelegate.java | 4 + .../CustomTabIntentDataProvider.java | 5 +- .../browser/download/DownloadUtils.java | 16 +- .../browser/history/HistoryManager.java | 18 +- - .../chrome/browser/history/HistoryPage.java | 16 + + .../chrome/browser/history/HistoryPage.java | 16 ++ .../browser/init/StartupTabPreloader.java | 14 +- .../native_page/NativePageFactory.java | 4 +- .../chrome/browser/ntp/RecentTabsManager.java | 8 +- - .../privacy/settings/PrivacySettings.java | 58 +++- + .../privacy/settings/IncognitoSettings.java | 160 ++++++++++++++++++ .../browser/settings/SettingsActivity.java | 4 + .../browser/tab/HistoricalTabSaver.java | 6 +- .../tabbed_mode/TabbedRootUiCoordinator.java | 5 +- .../browser/tabmodel/ChromeTabCreator.java | 5 +- .../tabmodel/TabModelSelectorImpl.java | 3 + .../browser/tabmodel/TabPersistentStore.java | 15 +- - .../webapps/WebappIntentDataProvider.java | 14 + - .../history/Bromite_HistoryManagerTest.java | 112 ++++++ - ...FragmentTest_HistoryInAlwaysIncognito.java | 120 +++++++ - .../browser/tab/HistoricalTabSaverTest.java | 2 +- - ...ite_AppMenuPropertiesDelegateUnitTest.java | 323 ++++++++++++++++++ - .../browser/android/historical_tab_saver.cc | 25 +- - chrome/browser/android/historical_tab_saver.h | 26 +- - .../android/historical_tab_saver_unittest.cc | 148 ++++++++ + .../webapps/WebappIntentDataProvider.java | 14 ++ + chrome/browser/about_flags.cc | 4 + + .../browser/android/historical_tab_saver.cc | 21 ++- .../chrome_autocomplete_provider_client.cc | 7 + .../chrome_autocomplete_provider_client.h | 1 + - .../host_content_settings_map_factory.cc | 15 +- + .../host_content_settings_map_factory.cc | 20 ++- + chrome/browser/flag_descriptions.cc | 6 + + chrome/browser/flag_descriptions.h | 3 + .../flags/android/chrome_feature_list.cc | 2 +- - chrome/browser/history/history_tab_helper.cc | 16 + + chrome/browser/history/history_tab_helper.cc | 18 ++ chrome/browser/history/history_tab_helper.h | 10 +- - .../history/history_tab_helper_unittest.cc | 22 ++ .../android/offline_page_bridge.cc | 13 +- - .../android/offline_page_model_factory.cc | 21 +- - .../android/request_coordinator_factory.cc | 17 + + .../android/offline_page_model_factory.cc | 21 ++- + .../android/request_coordinator_factory.cc | 17 ++ .../offline_page_model_factory.h | 1 + - .../offline_pages/recent_tab_helper.cc | 12 + + .../offline_pages/recent_tab_helper.cc | 19 ++- + .../browser/offline_pages/recent_tab_helper.h | 3 + .../request_coordinator_factory.h | 2 + chrome/browser/prefs/browser_prefs.cc | 5 + .../browser/ui/android/native_page/BUILD.gn | 2 + .../browser/ui/native_page/NativePage.java | 12 +- - .../ui/native_page/NativePageTest.java | 26 ++ - .../strings/android_chrome_strings.grd | 21 ++ + .../strings/android_chrome_strings.grd | 31 ++++ chrome/browser/ui/messages/android/BUILD.gn | 1 + - .../snackbar/INeedSnackbarManager.java | 27 ++ + .../snackbar/INeedSnackbarManager.java | 27 +++ chrome/common/pref_names.cc | 6 + - chrome/common/pref_names.h | 5 + - chrome/test/BUILD.gn | 5 + + chrome/common/pref_names.h | 6 + .../browser/content_settings_pref_provider.cc | 6 +- .../browser/content_settings_pref_provider.h | 2 + .../core/browser/host_content_settings_map.cc | 4 +- - .../core/browser/host_content_settings_map.h | 4 + + .../core/browser/host_content_settings_map.h | 3 + + .../core/offline_page_feature.cc | 3 + + .../offline_pages/core/offline_page_feature.h | 1 + .../browser/autocomplete_provider_client.cc | 4 + .../browser/autocomplete_provider_client.h | 1 + .../omnibox/browser/base_search_provider.cc | 2 +- components/omnibox/browser/search_provider.cc | 4 +- .../host_content_settings_map_factory.cc | 1 + - 65 files changed, 1300 insertions(+), 77 deletions(-) + 62 files changed, 688 insertions(+), 71 deletions(-) + create mode 100644 chrome/android/java/res/xml/incognito_preferences.xml create mode 100644 chrome/android/java/src/org/chromium/chrome/browser/AlwaysIncognitoLinkInterceptor.java - create mode 100644 chrome/android/javatests/src/org/chromium/chrome/browser/history/Bromite_HistoryManagerTest.java - create mode 100644 chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/Bromite_PrivacySettingsFragmentTest_HistoryInAlwaysIncognito.java - create mode 100644 chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/Bromite_AppMenuPropertiesDelegateUnitTest.java - create mode 100644 chrome/browser/android/historical_tab_saver_unittest.cc + create mode 100644 chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/IncognitoSettings.java create mode 100644 chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/INeedSnackbarManager.java +diff --git a/chrome/android/chrome_java_resources.gni b/chrome/android/chrome_java_resources.gni +--- a/chrome/android/chrome_java_resources.gni ++++ b/chrome/android/chrome_java_resources.gni +@@ -708,6 +708,7 @@ chrome_java_resources = [ + "java/res/xml/main_preferences.xml", + "java/res/xml/manage_sync_preferences.xml", + "java/res/xml/phone_as_a_security_key_accessory_filter.xml", ++ "java/res/xml/incognito_preferences.xml", + "java/res/xml/privacy_preferences.xml", + "java/res/xml/search_widget_info.xml", + "java/res/xml/tracing_preferences.xml", diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java_sources.gni --- a/chrome/android/chrome_java_sources.gni +++ b/chrome/android/chrome_java_sources.gni @@ -99,48 +106,68 @@ diff --git a/chrome/android/chrome_java_sources.gni b/chrome/android/chrome_java "java/src/com/google/android/apps/chrome/appwidget/bookmarks/BookmarkThumbnailWidgetProvider.java", "java/src/org/chromium/chrome/browser/ActivityTabProvider.java", "java/src/org/chromium/chrome/browser/ActivityUtils.java", -diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni ---- a/chrome/android/chrome_junit_test_java_sources.gni -+++ b/chrome/android/chrome_junit_test_java_sources.gni -@@ -237,3 +237,7 @@ chrome_junit_test_java_sources = [ - "junit/src/org/chromium/chrome/browser/webapps/WebappLauncherActivityTest.java", - "junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java", - ] +@@ -967,6 +968,7 @@ chrome_java_sources = [ + "java/src/org/chromium/chrome/browser/privacy/settings/IncognitoLockSettings.java", + "java/src/org/chromium/chrome/browser/privacy/settings/PrivacyPreferencesManagerImpl.java", + "java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java", ++ "java/src/org/chromium/chrome/browser/privacy/settings/IncognitoSettings.java", + "java/src/org/chromium/chrome/browser/provider/BaseColumns.java", + "java/src/org/chromium/chrome/browser/provider/BookmarkColumns.java", + "java/src/org/chromium/chrome/browser/provider/ChromeBrowserProviderImpl.java", +diff --git a/chrome/android/java/res/xml/incognito_preferences.xml b/chrome/android/java/res/xml/incognito_preferences.xml +new file mode 100644 +--- /dev/null ++++ b/chrome/android/java/res/xml/incognito_preferences.xml +@@ -0,0 +1,37 @@ ++ ++ ++ ++ + -+# Bromite tests -+chrome_test_java_sources += [ -+ "javatests/src/org/chromium/chrome/browser/privacy/settings/Bromite_PrivacySettingsFragmentTest_HistoryInAlwaysIncognito.java", -+ "javatests/src/org/chromium/chrome/browser/history/Bromite_HistoryManagerTest.java", -+] -diff --git a/chrome/android/java/res/xml/privacy_preferences.xml b/chrome/android/java/res/xml/privacy_preferences.xml ---- a/chrome/android/java/res/xml/privacy_preferences.xml -+++ b/chrome/android/java/res/xml/privacy_preferences.xml -@@ -37,6 +37,16 @@ - android:key="secure_dns" - android:title="@string/settings_secure_dns_title" - android:fragment="org.chromium.chrome.browser.privacy.secure_dns.SecureDnsSettings"/> + + ++ ++ +diff --git a/chrome/android/java/res/xml/privacy_preferences.xml b/chrome/android/java/res/xml/privacy_preferences.xml +--- a/chrome/android/java/res/xml/privacy_preferences.xml ++++ b/chrome/android/java/res/xml/privacy_preferences.xml +@@ -37,6 +37,11 @@ + android:key="secure_dns" + android:title="@string/settings_secure_dns_title" + android:fragment="org.chromium.chrome.browser.privacy.secure_dns.SecureDnsSettings"/> ++ . ++*/ ++ ++package org.chromium.chrome.browser.privacy.settings; ++ ++import android.os.Bundle; ++import android.content.Context; ++import android.content.Intent; ++import android.provider.Browser; ++import android.net.Uri; ++import android.view.Menu; ++import android.view.MenuInflater; ++import android.view.MenuItem; ++ ++import androidx.preference.Preference; ++import androidx.preference.PreferenceFragmentCompat; ++import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat; ++ ++import org.chromium.chrome.R; ++import org.chromium.chrome.browser.preferences.Pref; ++import org.chromium.chrome.browser.profiles.Profile; +import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor; +import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager; +import org.chromium.chrome.browser.ui.messages.snackbar.INeedSnackbarManager; +import org.chromium.chrome.browser.ui.messages.snackbar.Snackbar; +import org.chromium.chrome.browser.ApplicationLifetime; - import org.chromium.chrome.browser.signin.services.IdentityServicesProvider; - import org.chromium.components.browser_ui.bottomsheet.BottomSheetController; - import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; -@@ -47,7 +53,12 @@ import org.chromium.ui.text.SpanApplier; - * Fragment to keep track of the all the privacy related preferences. - */ - public class PrivacySettings -- extends PreferenceFragmentCompat implements Preference.OnPreferenceChangeListener { ++import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; ++import org.chromium.components.browser_ui.settings.SettingsUtils; ++import org.chromium.components.prefs.PrefService; ++import org.chromium.components.user_prefs.UserPrefs; ++ ++/** ++ * Fragment to keep track of the all the always incognito related preferences. ++ */ ++public class IncognitoSettings + extends PreferenceFragmentCompat implements Preference.OnPreferenceChangeListener, + INeedSnackbarManager { + private SnackbarManager mSnackbarManager; + private Snackbar mSnackbar; + + private static final String PREF_ALWAYS_INCOGNITO = "always_incognito"; - private static final String PREF_CAN_MAKE_PAYMENT = "can_make_payment"; - private static final String PREF_PRELOAD_PAGES = "preload_pages"; - private static final String PREF_HTTPS_FIRST_MODE = "https_first_mode"; -@@ -128,6 +139,11 @@ public class PrivacySettings - phoneAsASecurityKey.setVisible( - ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_AUTH_PHONE_SUPPORT)); - -+ ChromeSwitchPreference historyInIncognitoPref = -+ (ChromeSwitchPreference) findPreference(PREF_INCOGNITO_TAB_HISTORY_ENABLED); -+ historyInIncognitoPref.setOnPreferenceChangeListener(this); -+ historyInIncognitoPref.setManagedPreferenceDelegate(mManagedPreferenceDelegate); ++ private static final String PREF_INCOGNITO_TAB_HISTORY = "incognito_history"; ++ private static final String PREF_INCOGNITO_SAVE_SITE_SETTING = "incognito_save_site_setting"; + - updatePreferences(); - } - -@@ -137,13 +153,23 @@ public class PrivacySettings - if (PREF_CAN_MAKE_PAYMENT.equals(key)) { - UserPrefs.get(Profile.getLastUsedRegularProfile()) - .setBoolean(Pref.CAN_MAKE_PAYMENT_ENABLED, (boolean) newValue); -+ } else if (PREF_ALWAYS_INCOGNITO.equals(key)) { -+ AlwaysIncognitoLinkInterceptor.setAlwaysIncognito((boolean) newValue); -+ if (!mSnackbarManager.isShowing()) { -+ mSnackbarManager.showSnackbar(mSnackbar); -+ } - } else if (PREF_HTTPS_FIRST_MODE.equals(key)) { - UserPrefs.get(Profile.getLastUsedRegularProfile()) - .setBoolean(Pref.HTTPS_ONLY_MODE_ENABLED, (boolean) newValue); -+ } else if (PREF_INCOGNITO_TAB_HISTORY_ENABLED.equals(key)) { -+ UserPrefs.get(Profile.getLastUsedRegularProfile()) -+ .setBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED, (boolean) newValue); - } - return true; - } - -+ public static final String PREF_INCOGNITO_TAB_HISTORY_ENABLED = "incognito_history_enabled"; ++ private final PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile()); + - @Override - public void onResume() { - super.onResume(); -@@ -169,12 +195,38 @@ public class PrivacySettings - : R.string.text_off); - } - ++ @Override ++ public void onCreatePreferences(Bundle savedInstanceState, String rootKey) { ++ PrivacyPreferencesManagerImpl privacyPrefManager = ++ PrivacyPreferencesManagerImpl.getInstance(); ++ SettingsUtils.addPreferencesFromResource(this, R.xml.incognito_preferences); ++ getActivity().setTitle(R.string.incognito_settings_title); ++ ++ setHasOptionsMenu(true); ++ ++ updatePreferences(); ++ } ++ ++ @Override ++ public void onResume() { ++ super.onResume(); ++ updatePreferences(); ++ } ++ ++ public void updatePreferences() { + ChromeSwitchPreference alwaysIncognitoPref = + (ChromeSwitchPreference) findPreference(PREF_ALWAYS_INCOGNITO); ++ alwaysIncognitoPref.setChecked( ++ prefService.getBoolean(Pref.ALWAYS_INCOGNITO_ENABLED)); + alwaysIncognitoPref.setOnPreferenceChangeListener(this); + + mSnackbar = Snackbar.make(getActivity().getString(R.string.ui_relaunch_notice), @@ -743,31 +779,66 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/setting + /*actionData*/null) + .setDuration(/*durationMs*/70000); + - Preference preloadPagesPreference = findPreference(PREF_PRELOAD_PAGES); - if (preloadPagesPreference != null) { - preloadPagesPreference.setSummary( - PreloadPagesSettingsFragment.getPreloadPagesSummaryString(getContext())); - } - + ChromeSwitchPreference historyInIncognitoPref = -+ (ChromeSwitchPreference) findPreference(PREF_INCOGNITO_TAB_HISTORY_ENABLED); -+ if (historyInIncognitoPref != null) { -+ historyInIncognitoPref.setChecked( -+ prefService.getBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED)); ++ (ChromeSwitchPreference) findPreference(PREF_INCOGNITO_TAB_HISTORY); ++ historyInIncognitoPref.setChecked( ++ prefService.getBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED)); ++ historyInIncognitoPref.setOnPreferenceChangeListener(this); ++ ++ ChromeSwitchPreference saveSiteSettingsPref = ++ (ChromeSwitchPreference) findPreference(PREF_INCOGNITO_SAVE_SITE_SETTING); ++ saveSiteSettingsPref.setChecked( ++ prefService.getBoolean(Pref.INCOGNITO_SAVE_SITE_SETTING_ENABLED)); ++ saveSiteSettingsPref.setOnPreferenceChangeListener(this); ++ } ++ ++ @Override ++ public boolean onPreferenceChange(Preference preference, Object newValue) { ++ String key = preference.getKey(); ++ if (PREF_ALWAYS_INCOGNITO.equals(key)) { ++ AlwaysIncognitoLinkInterceptor.setAlwaysIncognito((boolean) newValue); ++ } else if (PREF_INCOGNITO_TAB_HISTORY.equals(key)) { ++ prefService.setBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED, (boolean) newValue); ++ } else if (PREF_INCOGNITO_SAVE_SITE_SETTING.equals(key)) { ++ prefService.setBoolean(Pref.INCOGNITO_SAVE_SITE_SETTING_ENABLED, (boolean) newValue); + } ++ if (!mSnackbarManager.isShowing()) { ++ mSnackbarManager.showSnackbar(mSnackbar); ++ } ++ return true; ++ } + - Preference secureDnsPref = findPreference(PREF_SECURE_DNS); - if (secureDnsPref != null && secureDnsPref.isVisible()) { - secureDnsPref.setSummary(SecureDnsSettings.getSummary(getContext())); -@@ -227,4 +279,8 @@ public class PrivacySettings - public void setBottomSheetController(BottomSheetController controller) { - mBottomSheetController = controller; - } ++ @Override ++ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { ++ menu.clear(); ++ MenuItem help = ++ menu.add(Menu.NONE, R.id.menu_id_targeted_help, Menu.NONE, R.string.menu_help); ++ help.setIcon(VectorDrawableCompat.create( ++ getResources(), R.drawable.ic_help_and_feedback, getActivity().getTheme())); ++ } + ++ @Override ++ public boolean onOptionsItemSelected(MenuItem item) { ++ if (item.getItemId() == R.id.menu_id_targeted_help) { ++ Context context = getContext(); ++ ++ Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://github.com/bromite/bromite/wiki/AlwaysIncognito")); ++ // Let Chromium know that this intent is from Chromium, so that it does not close the app when ++ // the user presses 'back' button. ++ intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName()); ++ intent.putExtra(Browser.EXTRA_CREATE_NEW_TAB, true); ++ intent.setPackage(context.getPackageName()); ++ context.startActivity(intent); ++ return true; ++ } ++ return false; ++ } ++ ++ @Override + public void setSnackbarManager(SnackbarManager manager) { + mSnackbarManager = manager; + } - } ++} diff --git a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java --- a/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java +++ b/chrome/android/java/src/org/chromium/chrome/browser/settings/SettingsActivity.java @@ -972,588 +1043,20 @@ diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappI @Override public @ScreenOrientationLockType.EnumType int getDefaultOrientation() { return mWebappExtras.orientation; -diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/history/Bromite_HistoryManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/history/Bromite_HistoryManagerTest.java -new file mode 100644 ---- /dev/null -+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/history/Bromite_HistoryManagerTest.java -@@ -0,0 +1,112 @@ -+/* -+ This file is part of Bromite. -+ -+ Bromite is free software: you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation, either version 3 of the License, or -+ (at your option) any later version. -+ -+ Bromite is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with Bromite. If not, see . -+*/ -+ -+package org.chromium.chrome.browser.history; -+ -+import android.app.Activity; -+import android.content.Context; -+import android.content.Intent; -+ -+import androidx.test.espresso.intent.rule.IntentsTestRule; -+import androidx.test.filters.SmallTest; -+ -+import org.hamcrest.Matcher; -+import org.junit.Assert; -+import org.junit.After; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.runner.RunWith; -+import org.chromium.base.test.util.Restriction; -+ -+import org.chromium.chrome.browser.IntentHandler; -+import org.chromium.chrome.browser.incognito.IncognitoUtils; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.browser.profiles.Profile; -+import org.chromium.base.ContextUtils; -+import org.chromium.components.prefs.PrefService; -+import org.chromium.components.user_prefs.UserPrefs; -+import org.chromium.chrome.browser.preferences.Pref; -+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor; -+import android.content.SharedPreferences; -+ -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.base.test.BaseActivityTestRule; -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.ui.test.util.UiRestriction; -+import org.chromium.content_public.browser.test.util.TestThreadUtils; -+ -+/** -+ * Tests the {@link HistoryManager}. -+ */ -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -+@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE) -+public class Bromite_HistoryManagerTest { -+ @Rule -+ public BaseActivityTestRule mIncognitoActivityTestRule = -+ new BaseActivityTestRule<>(HistoryActivity.class); -+ -+ @Before -+ public void setUp() { -+ } -+ -+ @After -+ public void tearDown() { -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile()); -+ prefService.clearPref(Pref.INCOGNITO_TAB_HISTORY_ENABLED); -+ -+ SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); -+ SharedPreferences.Editor editor = prefs.edit(); -+ editor.putBoolean(AlwaysIncognitoLinkInterceptor.PREF_ALWAYS_INCOGNITO, false); -+ editor.apply(); -+ }); -+ } -+ -+ boolean mShouldShowIncognitoPlaceholder = true; -+ -+ @Test -+ @SmallTest -+ public void testShouldShowIncognitoPlaceholder_AlwaysIncognito() throws Exception { -+ // launch HistoryActivity in incognito mode -+ Intent intent = new Intent(ContextUtils.getApplicationContext(), HistoryActivity.class); -+ intent.putExtra(IntentHandler.EXTRA_INCOGNITO_MODE, true); -+ -+ mIncognitoActivityTestRule.launchActivity(intent); -+ HistoryActivity activity = mIncognitoActivityTestRule.getActivity(); -+ HistoryManager historyManager = activity.getHistoryManagerForTests(); -+ Assert.assertTrue(historyManager.isIncognito()); -+ -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ // set always incognito on -+ SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); -+ SharedPreferences.Editor editor = prefs.edit(); -+ editor.putBoolean(AlwaysIncognitoLinkInterceptor.PREF_ALWAYS_INCOGNITO, true); -+ editor.apply(); -+ -+ // set INCOGNITO_TAB_HISTORY_ENABLED on -+ PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile()); -+ prefService.setBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED, true); -+ -+ mShouldShowIncognitoPlaceholder = historyManager.shouldShowIncognitoPlaceholder(); -+ }); -+ -+ // shouldShowIncognitoPlaceholder must be false -+ Assert.assertFalse(mShouldShowIncognitoPlaceholder); -+ } -+} -diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/Bromite_PrivacySettingsFragmentTest_HistoryInAlwaysIncognito.java b/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/Bromite_PrivacySettingsFragmentTest_HistoryInAlwaysIncognito.java -new file mode 100644 ---- /dev/null -+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/Bromite_PrivacySettingsFragmentTest_HistoryInAlwaysIncognito.java -@@ -0,0 +1,120 @@ -+/* -+ This file is part of Bromite. -+ -+ Bromite is free software: you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation, either version 3 of the License, or -+ (at your option) any later version. -+ -+ Bromite is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with Bromite. If not, see . -+*/ -+ -+package org.chromium.chrome.browser.privacy.settings; -+ -+import android.view.View; -+ -+import androidx.recyclerview.widget.RecyclerView; -+import androidx.test.filters.LargeTest; -+ -+import org.junit.Assert; -+import org.junit.After; -+import org.junit.Before; -+import org.junit.Rule; -+import org.junit.Test; -+import org.junit.rules.RuleChain; -+import org.junit.runner.RunWith; -+ -+import org.chromium.base.test.util.CommandLineFlags; -+import org.chromium.base.test.util.CriteriaHelper; -+import org.chromium.base.test.util.Feature; -+import org.chromium.chrome.R; -+import org.chromium.chrome.browser.flags.ChromeSwitches; -+import org.chromium.chrome.browser.settings.SettingsActivityTestRule; -+import org.chromium.chrome.test.ChromeJUnit4ClassRunner; -+import org.chromium.chrome.test.ChromeTabbedActivityTestRule; -+import org.chromium.chrome.test.util.ChromeRenderTestRule; -+import org.chromium.content_public.browser.test.util.TestThreadUtils; -+ -+import org.chromium.chrome.browser.profiles.Profile; -+import org.chromium.chrome.browser.preferences.Pref; -+import org.chromium.components.prefs.PrefService; -+import org.chromium.components.user_prefs.UserPrefs; -+import org.chromium.components.browser_ui.settings.ChromeSwitchPreference; -+ -+/** -+ * Tests for {@link PrivacySettings}. -+ */ -+@RunWith(ChromeJUnit4ClassRunner.class) -+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE}) -+public class Bromite_PrivacySettingsFragmentTest_HistoryInAlwaysIncognito { -+ public final ChromeTabbedActivityTestRule mActivityTestRule = -+ new ChromeTabbedActivityTestRule(); -+ public final SettingsActivityTestRule mSettingsActivityTestRule = -+ new SettingsActivityTestRule<>(PrivacySettings.class); -+ -+ // SettingsActivity has to be finished before the outer CTA can be finished or trying to finish -+ // CTA won't work. -+ @Rule -+ public final RuleChain mRuleChain = -+ RuleChain.outerRule(mActivityTestRule).around(mSettingsActivityTestRule); -+ -+ @Before -+ public void setUp() { -+ mActivityTestRule.startMainActivityOnBlankPage(); -+ } -+ -+ @After -+ public void tearDown() { -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile()); -+ prefService.clearPref(Pref.INCOGNITO_TAB_HISTORY_ENABLED); -+ }); -+ } -+ -+ private void waitForOptionsMenu() { -+ CriteriaHelper.pollUiThread(() -> { -+ return mSettingsActivityTestRule.getActivity().findViewById(R.id.menu_id_targeted_help) -+ != null; -+ }); -+ } -+ -+ @Test -+ @LargeTest -+ public void testIncognitoHistoryPreference() { -+ mSettingsActivityTestRule.startSettingsActivity(); -+ waitForOptionsMenu(); -+ PrivacySettings fragment = mSettingsActivityTestRule.getFragment(); -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ RecyclerView recyclerView = fragment.getView().findViewById(R.id.recycler_view); -+ recyclerView.scrollToPosition(recyclerView.getAdapter().getItemCount() - 1); -+ }); -+ -+ ChromeSwitchPreference historyInIncognitoPref = -+ (ChromeSwitchPreference) fragment.findPreference(PrivacySettings.PREF_INCOGNITO_TAB_HISTORY_ENABLED); -+ Assert.assertNotNull(historyInIncognitoPref); -+ -+ // Test when ON -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ fragment.onPreferenceChange(historyInIncognitoPref, true); -+ -+ PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile()); -+ boolean incognito_tab_history_enabled = prefService.getBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED); -+ Assert.assertTrue(incognito_tab_history_enabled); -+ }); -+ -+ // Test when OFF -+ TestThreadUtils.runOnUiThreadBlocking(() -> { -+ fragment.onPreferenceChange(historyInIncognitoPref, false); -+ -+ PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile()); -+ boolean incognito_tab_history_enabled = prefService.getBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED); -+ Assert.assertFalse(incognito_tab_history_enabled); -+ }); -+ } -+} -diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/HistoricalTabSaverTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/HistoricalTabSaverTest.java ---- a/chrome/android/javatests/src/org/chromium/chrome/browser/tab/HistoricalTabSaverTest.java -+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/tab/HistoricalTabSaverTest.java -@@ -115,7 +115,7 @@ public class HistoricalTabSaverTest { - - private static void createHistoricTab(Tab tab) { - TestThreadUtils.runOnUiThreadBlocking( -- () -> { HistoricalTabSaver.createHistoricalTab(tab); }); -+ () -> { HistoricalTabSaver.createHistoricalTab(tab, false); }); - } - - private void assertEntriesAre(List expectedEntries) { -diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/Bromite_AppMenuPropertiesDelegateUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/Bromite_AppMenuPropertiesDelegateUnitTest.java -new file mode 100644 ---- /dev/null -+++ b/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/Bromite_AppMenuPropertiesDelegateUnitTest.java -@@ -0,0 +1,323 @@ -+/* -+ This file is part of Bromite. -+ -+ Bromite is free software: you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation, either version 3 of the License, or -+ (at your option) any later version. -+ -+ Bromite is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with Bromite. If not, see . -+*/ -+ -+package org.chromium.chrome.browser.app.appmenu; -+ -+import static org.mockito.ArgumentMatchers.any; -+import static org.mockito.ArgumentMatchers.anyBoolean; -+import static org.mockito.Mockito.doReturn; -+import static org.mockito.Mockito.when; -+ -+import android.content.Context; -+import android.view.Menu; -+import android.view.MenuItem; -+import android.view.SubMenu; -+import android.view.View; -+import android.widget.PopupMenu; -+ -+import org.hamcrest.Matchers; -+import org.junit.After; -+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.mockito.Mockito; -+import org.mockito.MockitoAnnotations; -+import org.robolectric.annotation.Config; -+ -+import org.chromium.base.ContextUtils; -+import org.chromium.base.FeatureList; -+import org.chromium.base.ThreadUtils; -+import org.chromium.base.supplier.ObservableSupplierImpl; -+import org.chromium.base.supplier.OneshotSupplierImpl; -+import org.chromium.base.test.BaseRobolectricTestRunner; -+import org.chromium.base.test.util.JniMocker; -+import org.chromium.chrome.R; -+import org.chromium.chrome.browser.ActivityTabProvider; -+import org.chromium.chrome.browser.app.appmenu.AppMenuPropertiesDelegateImpl.MenuGroup; -+import org.chromium.chrome.browser.bookmarks.BookmarkBridge; -+import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior; -+import org.chromium.chrome.browser.device.DeviceConditions; -+import org.chromium.chrome.browser.device.ShadowDeviceConditions; -+import org.chromium.chrome.browser.multiwindow.MultiWindowModeStateDispatcher; -+import org.chromium.chrome.browser.omaha.UpdateMenuItemHelper; -+import org.chromium.chrome.browser.preferences.Pref; -+import org.chromium.chrome.browser.profiles.Profile; -+import org.chromium.chrome.browser.tab.Tab; -+import org.chromium.chrome.browser.tabmodel.TabModel; -+import org.chromium.chrome.browser.tabmodel.TabModelFilter; -+import org.chromium.chrome.browser.tabmodel.TabModelFilterProvider; -+import org.chromium.chrome.browser.tabmodel.TabModelSelector; -+import org.chromium.chrome.browser.toolbar.ToolbarManager; -+import org.chromium.chrome.browser.toolbar.menu_button.MenuUiState; -+import org.chromium.chrome.browser.util.ChromeAccessibilityUtil; -+import org.chromium.chrome.test.util.browser.Features; -+import org.chromium.components.prefs.PrefService; -+import org.chromium.components.user_prefs.UserPrefs; -+import org.chromium.components.user_prefs.UserPrefsJni; -+import org.chromium.components.webapps.AppBannerManager; -+import org.chromium.content.browser.ContentFeatureListImpl; -+import org.chromium.content.browser.ContentFeatureListImplJni; -+import org.chromium.content_public.browser.ContentFeatureList; -+import org.chromium.content_public.browser.NavigationController; -+import org.chromium.content_public.browser.WebContents; -+import org.chromium.net.ConnectionType; -+import org.chromium.url.JUnitTestGURLs; -+ -+import java.util.ArrayList; -+import java.util.List; -+ -+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor; -+import android.content.SharedPreferences; -+ -+/** -+ * Unit tests for {@link AppMenuPropertiesDelegateImpl}. -+ */ -+@RunWith(BaseRobolectricTestRunner.class) -+public class Bromite_AppMenuPropertiesDelegateUnitTest { -+ @Rule -+ public TestRule mProcessor = new Features.JUnitProcessor(); -+ -+ @Rule -+ public JniMocker mJniMocker = new JniMocker(); -+ -+ @Mock -+ private ActivityTabProvider mActivityTabProvider; -+ @Mock -+ private Tab mTab; -+ @Mock -+ private WebContents mWebContents; -+ @Mock -+ private NavigationController mNavigationController; -+ @Mock -+ private MultiWindowModeStateDispatcher mMultiWindowModeStateDispatcher; -+ @Mock -+ private TabModelSelector mTabModelSelector; -+ @Mock -+ private TabModel mTabModel; -+ @Mock -+ private TabModel mIncognitoTabModel; -+ @Mock -+ private ToolbarManager mToolbarManager; -+ @Mock -+ private View mDecorView; -+ @Mock -+ private OverviewModeBehavior mOverviewModeBehavior; -+ @Mock -+ private UpdateMenuItemHelper mUpdateMenuItemHelper; -+ @Mock -+ private ContentFeatureListImpl.Natives mContentFeatureListJniMock; -+ @Mock -+ private UserPrefs.Natives mUserPrefsJniMock; -+ @Mock -+ private Profile mProfile; -+ @Mock -+ private PrefService mPrefService; -+ @Mock -+ private TabModelFilterProvider mTabModelFilterProvider; -+ @Mock -+ private TabModelFilter mTabModelFilter; -+ -+ private OneshotSupplierImpl mOverviewModeSupplier = -+ new OneshotSupplierImpl<>(); -+ private ObservableSupplierImpl mBookmarkBridgeSupplier = -+ new ObservableSupplierImpl<>(); -+ -+ private AppMenuPropertiesDelegateImpl mAppMenuPropertiesDelegate; -+ -+ private MenuUiState mMenuUiState; -+ -+ @Before -+ public void setUp() { -+ MockitoAnnotations.initMocks(this); -+ -+ mOverviewModeSupplier.set(mOverviewModeBehavior); -+ when(mTab.getWebContents()).thenReturn(mWebContents); -+ when(mWebContents.getNavigationController()).thenReturn(mNavigationController); -+ when(mNavigationController.getUseDesktopUserAgent()).thenReturn(false); -+ when(mTabModelSelector.getCurrentModel()).thenReturn(mTabModel); -+ when(mTabModelSelector.getModel(false)).thenReturn((mTabModel)); -+ when(mTabModelSelector.getModel(true)).thenReturn((mIncognitoTabModel)); -+ when(mTabModelSelector.getTabModelFilterProvider()).thenReturn(mTabModelFilterProvider); -+ when(mTabModelFilterProvider.getCurrentTabModelFilter()).thenReturn(mTabModelFilter); -+ when(mTabModelFilter.getTabModel()).thenReturn(mTabModel); -+ -+ UpdateMenuItemHelper.setInstanceForTesting(mUpdateMenuItemHelper); -+ mMenuUiState = new MenuUiState(); -+ doReturn(mMenuUiState).when(mUpdateMenuItemHelper).getUiState(); -+ -+ mJniMocker.mock(ContentFeatureListImplJni.TEST_HOOKS, mContentFeatureListJniMock); -+ mJniMocker.mock(UserPrefsJni.TEST_HOOKS, mUserPrefsJniMock); -+ Profile.setLastUsedProfileForTesting(mProfile); -+ Mockito.when(mUserPrefsJniMock.get(mProfile)).thenReturn(mPrefService); -+ FeatureList.setTestCanUseDefaultsForTesting(); -+ -+ AppMenuPropertiesDelegateImpl obj = new AppMenuPropertiesDelegateImpl( -+ ContextUtils.getApplicationContext(), mActivityTabProvider, -+ mMultiWindowModeStateDispatcher, mTabModelSelector, mToolbarManager, mDecorView, -+ mOverviewModeSupplier, mBookmarkBridgeSupplier); -+ obj.setPrefForTest(mPrefService); -+ mAppMenuPropertiesDelegate = Mockito.spy(obj); -+ } -+ -+ @After -+ public void tearDown() { -+ ThreadUtils.setThreadAssertsDisabledForTesting(false); -+ ChromeAccessibilityUtil.get().setAccessibilityEnabledForTesting(false); -+ ChromeAccessibilityUtil.get().setTouchExplorationEnabledForTesting(false); -+ } -+ -+ private void setUpTestPrefs(SharedPreferences prefs, boolean always_incognito) { -+ SharedPreferences.Editor editor = prefs.edit(); -+ editor.putBoolean(AlwaysIncognitoLinkInterceptor.PREF_ALWAYS_INCOGNITO, always_incognito); -+ editor.apply(); -+ } -+ -+ @Test -+ public void testOverviewMenuItems_HideNewTabInAlwaysIncognito() { -+ SharedPreferences mPrefs = ContextUtils.getAppSharedPreferences(); -+ setUpTestPrefs(mPrefs, /*always_incognito*/true); -+ -+ setUpMocksForPageMenu(); -+ when(mTab.getUrl()).thenReturn(JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL)); -+ -+ Menu menu = createTestMenu(); -+ mAppMenuPropertiesDelegate.prepareMenu(menu, null); -+ -+ // in always incognito, open new tab is NOT visible -+ final MenuItem newTabOption = menu.findItem(R.id.new_tab_menu_id); -+ Assert.assertFalse(newTabOption.isVisible()); -+ } -+ -+ @Test -+ public void testOverviewMenuItems_ShowHomeScreenMenuItemInAlwaysIncognito() { -+ SharedPreferences mPrefs = ContextUtils.getAppSharedPreferences(); -+ setUpTestPrefs(mPrefs, /*always_incognito*/true); -+ -+ setUpMocksForPageMenu(); -+ when(mTab.getUrl()).thenReturn(JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL)); -+ -+ Menu menu = createTestMenu(); -+ mAppMenuPropertiesDelegate.prepareMenu(menu, null); -+ -+ // in always incognito, home screen menu is visible -+ final MenuItem homescreenItem = menu.findItem(R.id.add_to_homescreen_id); -+ Assert.assertTrue(homescreenItem.isVisible()); -+ } -+ -+ @Test -+ public void testOverviewMenuItems_HideRecentTabsInAlwaysIncognito() { -+ SharedPreferences mPrefs = ContextUtils.getAppSharedPreferences(); -+ setUpTestPrefs(mPrefs, /*always_incognito*/true); -+ -+ setUpMocksForPageMenu(); -+ when(mTab.getUrl()).thenReturn(JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL)); -+ -+ when(mPrefService.getBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED)) -+ .thenReturn(false); -+ -+ Menu menu = createTestMenu(); -+ mAppMenuPropertiesDelegate.prepareMenu(menu, null); -+ -+ // in always incognito, without INCOGNITO_TAB_HISTORY_ENABLED, -+ // recent tabs menu tab is NOT visible -+ final MenuItem recent_tabs_menu = menu.findItem(R.id.recent_tabs_menu_id); -+ Assert.assertFalse(recent_tabs_menu.isVisible()); -+ } -+ -+ @Test -+ public void testOverviewMenuItems_ShowRecentTabsInAlwaysIncognito() { -+ SharedPreferences mPrefs = ContextUtils.getAppSharedPreferences(); -+ setUpTestPrefs(mPrefs, /*always_incognito*/true); -+ -+ setUpMocksForPageMenu(); -+ when(mTab.getUrl()).thenReturn(JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL)); -+ -+ when(mPrefService.getBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED)) -+ .thenReturn(true); -+ -+ Menu menu = createTestMenu(); -+ mAppMenuPropertiesDelegate.prepareMenu(menu, null); -+ -+ // in always incognito, with INCOGNITO_TAB_HISTORY_ENABLED -+ // recent tabs menu item is visible -+ final MenuItem recent_tabs_menu = menu.findItem(R.id.recent_tabs_menu_id); -+ Assert.assertTrue(recent_tabs_menu.isVisible()); -+ } -+ -+ @Test -+ public void testOverviewMenuItems_ShowDownloadItemInAlwaysIncognito() { -+ SharedPreferences mPrefs = ContextUtils.getAppSharedPreferences(); -+ setUpTestPrefs(mPrefs, /*always_incognito*/true); -+ -+ setUpMocksForPageMenu(); -+ when(mTab.getUrl()).thenReturn(JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL)); -+ -+ when(mPrefService.getBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED)) -+ .thenReturn(true); -+ -+ Menu menu = createTestMenu(); -+ mAppMenuPropertiesDelegate.prepareMenu(menu, null); -+ -+ // in always incognito, with INCOGNITO_TAB_HISTORY_ENABLED -+ // download page menu item is visible -+ final MenuItem offline_page = menu.findItem(R.id.offline_page_id); -+ Assert.assertTrue(offline_page.isVisible()); -+ } -+ -+ private void setUpMocksForPageMenu() { -+ when(mTabModel.isIncognito()).thenReturn(true); -+ when(mIncognitoTabModel.isIncognito()).thenReturn(true); -+ -+ when(mActivityTabProvider.get()).thenReturn(mTab); -+ when(mOverviewModeBehavior.overviewVisible()).thenReturn(false); -+ doReturn(false).when(mAppMenuPropertiesDelegate).shouldCheckBookmarkStar(any(Tab.class)); -+ doReturn(false).when(mAppMenuPropertiesDelegate).shouldEnableDownloadPage(any(Tab.class)); -+ doReturn(false).when(mAppMenuPropertiesDelegate).shouldShowReaderModePrefs(any(Tab.class)); -+ doReturn(false) -+ .when(mAppMenuPropertiesDelegate) -+ .shouldShowManagedByMenuItem(any(Tab.class)); -+ doReturn(false) -+ .when(mAppMenuPropertiesDelegate) -+ .shouldShowTranslateMenuItem(any(Tab.class)); -+ doReturn(new AppBannerManager.InstallStringPair( -+ R.string.menu_add_to_homescreen, R.string.add)) -+ .when(mAppMenuPropertiesDelegate) -+ .getAddToHomeScreenTitle(mTab); -+ setUpIncognitoMocks(); -+ } -+ -+ private void setUpMocksForOverviewMenu() { -+ when(mOverviewModeBehavior.overviewVisible()).thenReturn(true); -+ when(mTabModelSelector.getTotalTabCount()).thenReturn(1); -+ setUpIncognitoMocks(); -+ } -+ -+ private void setUpIncognitoMocks() { -+ doReturn(true).when(mAppMenuPropertiesDelegate).isIncognitoEnabled(); -+ } -+ -+ private Menu createTestMenu() { -+ PopupMenu tempMenu = new PopupMenu(ContextUtils.getApplicationContext(), mDecorView); -+ tempMenu.inflate(mAppMenuPropertiesDelegate.getAppMenuLayoutId()); -+ Menu menu = tempMenu.getMenu(); -+ return menu; -+ } -+} +diff --git a/chrome/browser/about_flags.cc b/chrome/browser/about_flags.cc +--- a/chrome/browser/about_flags.cc ++++ b/chrome/browser/about_flags.cc +@@ -4232,6 +4232,10 @@ const FeatureEntry kFeatureEntries[] = { + flag_descriptions::kOfflinePagesLivePageSharingName, + flag_descriptions::kOfflinePagesLivePageSharingDescription, kOsAndroid, + FEATURE_VALUE_TYPE(offline_pages::kOfflinePagesLivePageSharingFeature)}, ++ {"offline-pages-auto-save", ++ flag_descriptions::kOfflinePagesAutoSaveFeatureName, ++ flag_descriptions::kOfflinePagesAutoSaveFeatureDescription, kOsAndroid, ++ FEATURE_VALUE_TYPE(offline_pages::kOfflinePagesAutoSaveFeature)}, + {"offline-indicator-v2", flag_descriptions::kOfflineIndicatorV2Name, + flag_descriptions::kOfflineIndicatorV2Description, kOsAndroid, + FEATURE_VALUE_TYPE(chrome::android::kOfflineIndicatorV2)}, diff --git a/chrome/browser/android/historical_tab_saver.cc b/chrome/browser/android/historical_tab_saver.cc --- a/chrome/browser/android/historical_tab_saver.cc +++ b/chrome/browser/android/historical_tab_saver.cc @@ -1577,7 +1080,7 @@ diff --git a/chrome/browser/android/historical_tab_saver.cc b/chrome/browser/and if (!tab_android) { return; } -@@ -30,16 +35,21 @@ void CreateHistoricalTab(TabAndroid* tab_android) { +@@ -30,9 +35,14 @@ void CreateHistoricalTab(TabAndroid* tab_android) { return; } @@ -1594,15 +1097,6 @@ diff --git a/chrome/browser/android/historical_tab_saver.cc b/chrome/browser/and if (!service) { return; } - -- // Index is unimportant on Android. -+ // index is not important on Android - service->CreateHistoricalTab(sessions::ContentLiveTab::GetForWebContents( -- scoped_web_contents->web_contents()), -+ scoped_web_contents->web_contents()), - /*index=*/-1); - } - @@ -77,8 +87,9 @@ std::unique_ptr ScopedWebContents::CreateForTab( // static static void JNI_HistoricalTabSaver_CreateHistoricalTab( @@ -1615,201 +1109,6 @@ diff --git a/chrome/browser/android/historical_tab_saver.cc b/chrome/browser/and } } // namespace historical_tab_saver -diff --git a/chrome/browser/android/historical_tab_saver.h b/chrome/browser/android/historical_tab_saver.h ---- a/chrome/browser/android/historical_tab_saver.h -+++ b/chrome/browser/android/historical_tab_saver.h -@@ -1,10 +1,25 @@ --// Copyright 2022 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. -+/* -+ This file is part of Bromite. -+ -+ Bromite is free software: you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation, either version 3 of the License, or -+ (at your option) any later version. -+ -+ Bromite is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with Bromite. If not, see . -+*/ - - #ifndef CHROME_BROWSER_ANDROID_HISTORICAL_TAB_SAVER_H_ - #define CHROME_BROWSER_ANDROID_HISTORICAL_TAB_SAVER_H_ - -+#include "content/public/browser/web_contents.h" -+ - #include - - class TabAndroid; -@@ -40,4 +55,9 @@ class ScopedWebContents { - - } // namespace historical_tab_saver - -+ -+// static -+void CreateHistoricalTabForTest(content::WebContents* web_contents, -+ bool is_always_incognito); -+ - #endif // CHROME_BROWSER_ANDROID_HISTORICAL_TAB_SAVER_H_ -diff --git a/chrome/browser/android/historical_tab_saver_unittest.cc b/chrome/browser/android/historical_tab_saver_unittest.cc -new file mode 100644 ---- /dev/null -+++ b/chrome/browser/android/historical_tab_saver_unittest.cc -@@ -0,0 +1,148 @@ -+/* -+ This file is part of Bromite. -+ -+ Bromite is free software: you can redistribute it and/or modify -+ it under the terms of the GNU General Public License as published by -+ the Free Software Foundation, either version 3 of the License, or -+ (at your option) any later version. -+ -+ Bromite is distributed in the hope that it will be useful, -+ but WITHOUT ANY WARRANTY; without even the implied warranty of -+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ GNU General Public License for more details. -+ -+ You should have received a copy of the GNU General Public License -+ along with Bromite. If not, see . -+*/ -+ -+#include "base/run_loop.h" -+#include "base/strings/stringprintf.h" -+#include "base/strings/utf_string_conversions.h" -+#include "base/task/cancelable_task_tracker.h" -+#include "base/test/bind.h" -+#include "build/build_config.h" -+#include "chrome/browser/history/history_service_factory.h" -+#include "chrome/test/base/chrome_render_view_host_test_harness.h" -+#include "chrome/test/base/testing_profile.h" -+#include "components/history/core/browser/history_constants.h" -+#include "components/history/core/browser/history_service.h" -+#include "components/history/core/browser/history_types.h" -+#include "components/history/core/browser/url_row.h" -+#include "content/public/browser/browser_context.h" -+#include "content/public/browser/navigation_controller.h" -+#include "content/public/browser/web_contents.h" -+#include "content/public/test/mock_navigation_handle.h" -+#include "content/public/test/web_contents_tester.h" -+#include "testing/gmock/include/gmock/gmock.h" -+#include "testing/gtest/include/gtest/gtest.h" -+#include "ui/base/page_transition_types.h" -+ -+#include "chrome/test/base/testing_browser_process.h" -+#include "chrome/test/base/testing_profile_manager.h" -+#include "content/public/test/test_browser_context.h" -+#include "content/test/test_web_contents.h" -+#include "components/sessions/core/tab_restore_service.h" -+#include "components/sessions/core/tab_restore_service_impl.h" -+#include "components/sessions/content/content_live_tab.h" -+#include "chrome/browser/android/historical_tab_saver.h" -+#include "chrome/browser/sessions/tab_restore_service_factory.h" -+#include "chrome/browser/sessions/chrome_tab_restore_service_client.h" -+#include "chrome/common/pref_names.h" -+ -+namespace { -+ -+static std::unique_ptr GetTabRestoreService( -+ content::BrowserContext* browser_context) { -+ return std::make_unique( -+ std::make_unique( -+ Profile::FromBrowserContext(browser_context)), -+ nullptr, nullptr); -+} -+ -+// --gtest_filter=*.Bromite* -+class HistoryTabSaverTest : public ChromeRenderViewHostTestHarness { -+ protected: -+ HistoryTabSaverTest() {} -+ -+ // ChromeRenderViewHostTestHarness: -+ void SetUp() override { -+ ChromeRenderViewHostTestHarness::SetUp(); -+ TabRestoreServiceFactory::GetInstance()->SetTestingFactory( -+ profile(), -+ base::BindRepeating(&GetTabRestoreService)); -+ ASSERT_TRUE(profile()->CreateHistoryService()); -+ } -+ -+ const GURL page_url_ = GURL("http://foo.com"); -+ -+ protected: -+// history::HistoryService* history_service_; -+ -+ DISALLOW_COPY_AND_ASSIGN(HistoryTabSaverTest); -+}; -+ -+TEST_F(HistoryTabSaverTest, Bromite_HistoricalTabForNormalNavigation) { -+ sessions::TabRestoreService* service = -+ TabRestoreServiceFactory::GetForProfile(profile()); -+ ASSERT_NE(nullptr, service); -+ -+ auto* profile_ = profile(); -+ auto web_other_contents = content::TestWebContents::Create(profile_, nullptr); -+ web_other_contents->NavigateAndCommit(page_url_); -+ -+ // Make sure was no entry. -+ ASSERT_EQ(0U, service->entries().size()); -+ -+ CreateHistoricalTabForTest(web_other_contents.get(), /*is_always_incognito*/false); -+ -+ // Make sure entry was created. -+ ASSERT_EQ(1U, service->entries().size()); -+} -+ -+TEST_F(HistoryTabSaverTest, Bromite_HistoricalTabForNavigationInIncognito) { -+ sessions::TabRestoreService* service = -+ TabRestoreServiceFactory::GetForProfile(profile()); -+ ASSERT_NE(nullptr, service); -+ -+ auto* profile_ = profile()->GetOffTheRecordProfile( -+ Profile::OTRProfileID::PrimaryID(), /*create_if_needed=*/true); -+ auto web_other_contents = content::TestWebContents::Create(profile_, nullptr); -+ web_other_contents->NavigateAndCommit(page_url_); -+ -+ // Make sure was no entry. -+ ASSERT_EQ(0U, service->entries().size()); -+ -+ CreateHistoricalTabForTest(web_other_contents.get(), /*is_always_incognito*/false); -+ -+ // Make sure was no entry. -+ ASSERT_EQ(0U, service->entries().size()); -+} -+ -+TEST_F(HistoryTabSaverTest, Bromite_HistoricalTabForNavigationInIncognito_AlwaysIncognito) { -+ sessions::TabRestoreService* service = -+ TabRestoreServiceFactory::GetForProfile(profile()); -+ ASSERT_NE(nullptr, service); -+ -+ auto* profile_ = profile()->GetOffTheRecordProfile( -+ Profile::OTRProfileID::PrimaryID(), /*create_if_needed=*/true); -+ auto web_other_contents = content::TestWebContents::Create(profile_, nullptr); -+ web_other_contents->NavigateAndCommit(page_url_); -+ -+ // test kIncognitoTabHistoryEnabled with false -+ profile()->GetPrefs()->SetBoolean(prefs::kIncognitoTabHistoryEnabled, false); -+ -+ CreateHistoricalTabForTest(web_other_contents.get(), /*is_always_incognito*/true); -+ -+ // Make sure was no entry. -+ ASSERT_EQ(0U, service->entries().size()); -+ -+ // test kIncognitoTabHistoryEnabled with true -+ profile()->GetPrefs()->SetBoolean(prefs::kIncognitoTabHistoryEnabled, true); -+ -+ CreateHistoricalTabForTest(web_other_contents.get(), /*is_always_incognito*/true); -+ -+ // Make sure was the entry. -+ ASSERT_EQ(1U, service->entries().size()); -+} -+ -+} // namespace diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc --- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc +++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.cc @@ -1849,27 +1148,32 @@ diff --git a/chrome/browser/content_settings/host_content_settings_map_factory.c #include "components/content_settings/core/browser/content_settings_pref_provider.h" #include "components/content_settings/core/browser/host_content_settings_map.h" #include "components/keyed_service/content/browser_context_dependency_manager.h" -@@ -96,9 +97,18 @@ scoped_refptr +@@ -96,9 +97,23 @@ scoped_refptr if (profile->IsOffTheRecord() && !profile->IsGuestSession()) GetForProfile(original_profile); + bool always_incognito_enabled = false; ++ bool force_save_site_settings = false; + + PrefService* prefService = original_profile->GetPrefs(); + if (prefService->GetBoolean(prefs::kAlwaysIncognitoEnabled)) { -+ profile = original_profile; + always_incognito_enabled = true; + } ++ ++ if (prefService->GetBoolean(prefs::kIncognitoSaveSiteSettingEnabled)) { ++ profile = original_profile; ++ force_save_site_settings = true; ++ } + scoped_refptr settings_map(new HostContentSettingsMap( profile->GetPrefs(), - profile->IsOffTheRecord() || profile->IsGuestSession(), -+ !always_incognito_enabled && (profile->IsOffTheRecord() || profile->IsGuestSession()), -+ always_incognito_enabled, ++ !force_save_site_settings && (profile->IsOffTheRecord() || profile->IsGuestSession()), ++ force_save_site_settings, /*store_last_modified=*/true, profile->ShouldRestoreOldSessionCookies())); -@@ -108,6 +118,9 @@ scoped_refptr +@@ -108,6 +123,9 @@ scoped_refptr HostContentSettingsMap::WEBUI_ALLOWLIST_PROVIDER, std::move(allowlist_provider)); @@ -1879,6 +1183,35 @@ diff --git a/chrome/browser/content_settings/host_content_settings_map_factory.c if (base::FeatureList::IsEnabled( permissions::features::kOneTimeGeolocationPermission)) { auto one_time_geolocation_provider = +diff --git a/chrome/browser/flag_descriptions.cc b/chrome/browser/flag_descriptions.cc +--- a/chrome/browser/flag_descriptions.cc ++++ b/chrome/browser/flag_descriptions.cc +@@ -3421,6 +3421,12 @@ const char kOfflinePagesLivePageSharingDescription[] = + "Enables to share current loaded page as offline page by saving as MHTML " + "first."; + ++const char kOfflinePagesAutoSaveFeatureName[] = ++ "Enables autosave of offline page"; ++const char kOfflinePagesAutoSaveFeatureDescription[] = ++ "Enables autosave of offline page, as automatic switching in case " ++ "the device goes offline."; ++ + const char kPageInfoDiscoverabilityTimeoutsName[] = + "Page info discoverability timeouts"; + const char kPageInfoDiscoverabilityTimeoutsDescription[] = +diff --git a/chrome/browser/flag_descriptions.h b/chrome/browser/flag_descriptions.h +--- a/chrome/browser/flag_descriptions.h ++++ b/chrome/browser/flag_descriptions.h +@@ -1956,6 +1956,9 @@ extern const char kOfflineIndicatorV2Description[]; + extern const char kOfflinePagesLivePageSharingName[]; + extern const char kOfflinePagesLivePageSharingDescription[]; + ++extern const char kOfflinePagesAutoSaveFeatureName[]; ++extern const char kOfflinePagesAutoSaveFeatureDescription[]; ++ + extern const char kPageInfoDiscoverabilityTimeoutsName[]; + extern const char kPageInfoDiscoverabilityTimeoutsDescription[]; + diff --git a/chrome/browser/flags/android/chrome_feature_list.cc b/chrome/browser/flags/android/chrome_feature_list.cc --- a/chrome/browser/flags/android/chrome_feature_list.cc +++ b/chrome/browser/flags/android/chrome_feature_list.cc @@ -1918,7 +1251,7 @@ diff --git a/chrome/browser/history/history_tab_helper.cc b/chrome/browser/histo if (profile->IsOffTheRecord()) return NULL; -@@ -338,6 +348,12 @@ history::HistoryService* HistoryTabHelper::GetHistoryService() { +@@ -338,6 +348,14 @@ history::HistoryService* HistoryTabHelper::GetHistoryService() { profile, ServiceAccessType::IMPLICIT_ACCESS); } @@ -1926,6 +1259,8 @@ diff --git a/chrome/browser/history/history_tab_helper.cc b/chrome/browser/histo +void HistoryTabHelper::RegisterProfilePrefs(PrefRegistrySimple* registry) { + registry->RegisterBooleanPref(prefs::kIncognitoTabHistoryEnabled, + /*default_value=*/false); ++ registry->RegisterBooleanPref(prefs::kIncognitoSaveSiteSettingEnabled, ++ /*default_value=*/false); +} + void HistoryTabHelper::WebContentsDestroyed() { @@ -1965,45 +1300,6 @@ diff --git a/chrome/browser/history/history_tab_helper.h b/chrome/browser/histor // Returns true if our observed web contents is an eligible tab. bool IsEligibleTab(const history::HistoryAddPageArgs& add_page_args) const; -diff --git a/chrome/browser/history/history_tab_helper_unittest.cc b/chrome/browser/history/history_tab_helper_unittest.cc ---- a/chrome/browser/history/history_tab_helper_unittest.cc -+++ b/chrome/browser/history/history_tab_helper_unittest.cc -@@ -43,6 +43,9 @@ - - using testing::NiceMock; - -+#include "chrome/common/pref_names.h" -+#include "content/test/test_web_contents.h" -+ - namespace { - - #if BUILDFLAG(IS_ANDROID) -@@ -52,6 +55,25 @@ class TestFeedApi : public feed::StubFeedApi { - }; - #endif - -+TEST_F(HistoryTabHelperTest, Bromite_CheckHistoryService_IncognitoTabHistoryEnabled) { -+ auto* profile_ = profile()->GetOffTheRecordProfile( -+ Profile::OTRProfileID::PrimaryID(), /*create_if_needed=*/true); -+ auto web_other_contents = content::TestWebContents::Create(profile_, nullptr); -+ web_other_contents->NavigateAndCommit(page_url_); -+ -+ HistoryTabHelper::CreateForWebContents(web_other_contents.get()); -+ HistoryTabHelper* history_tab_helper = HistoryTabHelper::FromWebContents(web_other_contents.get()); -+ ASSERT_NE(nullptr, history_tab_helper); -+ -+ // test kIncognitoTabHistoryEnabled with false -+ profile()->GetPrefs()->SetBoolean(prefs::kIncognitoTabHistoryEnabled, false); -+ ASSERT_EQ(nullptr, history_tab_helper->GetHistoryService()); -+ -+ // test kIncognitoTabHistoryEnabled with true -+ profile()->GetPrefs()->SetBoolean(prefs::kIncognitoTabHistoryEnabled, true); -+ ASSERT_NE(nullptr, history_tab_helper->GetHistoryService()); -+} -+ - } // namespace - - class HistoryTabHelperTest : public ChromeRenderViewHostTestHarness { diff --git a/chrome/browser/offline_pages/android/offline_page_bridge.cc b/chrome/browser/offline_pages/android/offline_page_bridge.cc --- a/chrome/browser/offline_pages/android/offline_page_bridge.cc +++ b/chrome/browser/offline_pages/android/offline_page_bridge.cc @@ -2169,7 +1465,7 @@ diff --git a/chrome/browser/offline_pages/recent_tab_helper.cc b/chrome/browser/ namespace { class DefaultRecentTabHelperDelegate : public offline_pages::RecentTabHelper::Delegate { -@@ -181,6 +186,13 @@ bool RecentTabHelper::EnsureInitialized() { +@@ -181,6 +186,14 @@ bool RecentTabHelper::EnsureInitialized() { // WebContents with its origin as well. snapshots_enabled_ = !tab_id_.empty() && !web_contents()->GetBrowserContext()->IsOffTheRecord(); @@ -2178,11 +1474,38 @@ diff --git a/chrome/browser/offline_pages/recent_tab_helper.cc b/chrome/browser/ + ->GetOriginalProfile() + ->GetPrefs()->GetBoolean(prefs::kIncognitoTabHistoryEnabled) == true) { + snapshots_enabled_ = true; ++ incognito_tab_history_enabled_ = true; + } + } if (snapshots_enabled_) { page_model_ = OfflinePageModelFactory::GetForBrowserContext( +@@ -457,7 +470,11 @@ void RecentTabHelper::ContinueSnapshotWithIdsToPurge( + void RecentTabHelper::ContinueSnapshotAfterPurge( + SnapshotProgressInfo* snapshot_info, + OfflinePageModel::DeletePageResult result) { +- if (result != OfflinePageModel::DeletePageResult::SUCCESS) { ++ // remove snapshot save of recent tab if always incognito mode is active ++ // so recents tab list is empty at every startup ++ // the user can choose to disable the feature ++ if (incognito_tab_history_enabled_ || !base::FeatureList::IsEnabled(offline_pages::kOfflinePagesAutoSaveFeature) ++ || result != OfflinePageModel::DeletePageResult::SUCCESS) { + ReportSnapshotCompleted(snapshot_info, false); + return; + } +diff --git a/chrome/browser/offline_pages/recent_tab_helper.h b/chrome/browser/offline_pages/recent_tab_helper.h +--- a/chrome/browser/offline_pages/recent_tab_helper.h ++++ b/chrome/browser/offline_pages/recent_tab_helper.h +@@ -142,6 +142,9 @@ class RecentTabHelper + // Not page-specific. + bool snapshots_enabled_ = false; + ++ // If true, tab history in incognito mode is enabled ++ bool incognito_tab_history_enabled_ = false; ++ + // Snapshot progress information for an ongoing snapshot requested by + // downloads. Null if there's no ongoing request. + std::unique_ptr downloads_ongoing_snapshot_info_; diff --git a/chrome/browser/offline_pages/request_coordinator_factory.h b/chrome/browser/offline_pages/request_coordinator_factory.h --- a/chrome/browser/offline_pages/request_coordinator_factory.h +++ b/chrome/browser/offline_pages/request_coordinator_factory.h @@ -2206,17 +1529,17 @@ diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browse #include "chrome/browser/android/bookmarks/partner_bookmarks_shim.h" #include "chrome/browser/android/explore_sites/history_statistics_reporter.h" #include "chrome/browser/android/ntp/recent_tabs_page_prefs.h" -@@ -1313,6 +1314,10 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry, - - #if BUILDFLAG(ENABLE_FEED_V2) - feed::prefs::RegisterFeedSharedProfilePrefs(registry); +@@ -1333,6 +1334,10 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry, + usage_stats::UsageStatsBridge::RegisterProfilePrefs(registry); + variations::VariationsService::RegisterProfilePrefs(registry); + video_tutorials::RegisterPrefs(registry); + // register incognito pref + registry->RegisterBooleanPref(prefs::kAlwaysIncognitoEnabled, + /*default_value=*/false); + HistoryTabHelper::RegisterProfilePrefs(registry); - feed::RegisterProfilePrefs(registry); - #endif - + #else // BUILDFLAG(IS_ANDROID) + AppShortcutManager::RegisterProfilePrefs(registry); + browser_sync::ForeignSessionHandler::RegisterProfilePrefs(registry); diff --git a/chrome/browser/ui/android/native_page/BUILD.gn b/chrome/browser/ui/android/native_page/BUILD.gn --- a/chrome/browser/ui/android/native_page/BUILD.gn +++ b/chrome/browser/ui/android/native_page/BUILD.gn @@ -2278,77 +1601,46 @@ diff --git a/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/ return NativePageType.RECENT_TABS; } else if (UrlConstants.EXPLORE_HOST.equals(host)) { return NativePageType.EXPLORE; -diff --git a/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePageTest.java b/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePageTest.java ---- a/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePageTest.java -+++ b/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePageTest.java -@@ -12,6 +12,10 @@ import org.robolectric.annotation.Config; - import org.chromium.base.test.BaseRobolectricTestRunner; - import org.chromium.chrome.browser.ui.native_page.NativePage.NativePageType; - -+import org.chromium.base.ContextUtils; -+import org.chromium.components.embedder_support.util.UrlConstants; -+import android.content.SharedPreferences; -+ - /** - * Tests public methods in NativePage. - */ -@@ -91,4 +95,26 @@ public class NativePageTest { - Assert.assertFalse(invalidUrl, NativePage.isNativePageUrl(invalidUrl, true)); - } - } -+ -+ @Test -+ public void Bromite_testNativePage_RecentTabsInAlwaysIncognito() { -+ SharedPreferences prefs = ContextUtils.getAppSharedPreferences(); -+ SharedPreferences.Editor editor = prefs.edit(); -+ -+ String url = "chrome-native://recent-tabs"; -+ -+ editor.putBoolean(/*AlwaysIncognitoLinkInterceptor.PREF_ALWAYS_INCOGNITO*/ -+ "always_incognito", false); -+ editor.apply(); -+ -+ Assert.assertEquals(NativePageType.NONE, -+ NativePage.nativePageType(url, null, /*isIncognito*/true)); -+ -+ editor.putBoolean(/*AlwaysIncognitoLinkInterceptor.PREF_ALWAYS_INCOGNITO*/ -+ "always_incognito", true); -+ editor.apply(); -+ -+ Assert.assertEquals(NativePageType.RECENT_TABS, -+ NativePage.nativePageType(url, null, /*isIncognito*/true)); -+ } - } diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd --- a/chrome/browser/ui/android/strings/android_chrome_strings.grd +++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd -@@ -1106,6 +1106,27 @@ Your Google account may have other forms of browsing history like searches and a - - Clears history, including in the search box. +@@ -1109,6 +1109,37 @@ Your Google account may have other forms of browsing history like searches and a + + Clears history from all synced devices. -+ + ++ ++ Incognito mode settings ++ ++ ++ Sets the flags of incognito mode ++ + + Open links in incognito tabs always + + + Opens links in incognito tabs when you click on new tab or on a link + -+ ++ + Relaunch + -+ ++ + Your changes will take effect the next time you relaunch Bromite. + -+ -+ Enable history in incognito tabs -+ -+ -+ Record history even in incognito mode -+ -+ - - Clears history from all synced devices. ++ ++ Enable history in incognito tabs ++ ++ ++ Record history even in incognito mode ++ ++ ++ Save site settings in incognito mode ++ ++ ++ Allows to save site settings in incognito mode ++ + + <link1>Search history</link1> and <link2>other forms of activity</link2> may be saved in your Google Account when you’re signed in. You can delete them anytime. diff --git a/chrome/browser/ui/messages/android/BUILD.gn b/chrome/browser/ui/messages/android/BUILD.gn --- a/chrome/browser/ui/messages/android/BUILD.gn @@ -2402,8 +1694,8 @@ diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc +#if BUILDFLAG(IS_ANDROID) +const char kAlwaysIncognitoEnabled[] = "always_incognito_enabled"; -+const char kIncognitoTabHistoryEnabled[] = -+ "incognito_tab_history_enabled"; ++const char kIncognitoTabHistoryEnabled[] = "incognito_tab_history_enabled"; ++const char kIncognitoSaveSiteSettingEnabled[] = "incognito_site_setting_enabled"; +#endif + #if BUILDFLAG(IS_CHROMEOS_ASH) @@ -2412,15 +1704,16 @@ diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h -@@ -1167,6 +1167,7 @@ extern const char kDiscountConsentShowInterestIn[]; +@@ -1167,6 +1167,8 @@ extern const char kDiscountConsentShowInterestIn[]; #if BUILDFLAG(IS_ANDROID) extern const char kWebXRImmersiveArEnabled[]; +extern const char kAlwaysIncognitoEnabled[]; ++extern const char kIncognitoSaveSiteSettingEnabled[]; #endif #if !BUILDFLAG(IS_ANDROID) -@@ -1203,6 +1204,10 @@ extern const char kPrivacyGuideViewed[]; +@@ -1203,6 +1205,10 @@ extern const char kPrivacyGuideViewed[]; extern const char kCorsNonWildcardRequestHeadersSupport[]; @@ -2431,21 +1724,6 @@ diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h extern const char kOriginAgentClusterDefaultEnabled[]; extern const char kForceMajorVersionToMinorPositionInUserAgent[]; -diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn ---- a/chrome/test/BUILD.gn -+++ b/chrome/test/BUILD.gn -@@ -5198,6 +5198,11 @@ test("unit_tests") { - sources += [ "../browser/page_load_metrics/observers/side_search_page_load_metrics_observer_unittest.cc" ] - } - -+ # Bromite tests -+ sources += [ -+ "../browser/android/historical_tab_saver_unittest.cc", -+ ] -+ - if (is_android) { - sources += [ - "../browser/android/bookmarks/partner_bookmarks_shim_unittest.cc", diff --git a/components/content_settings/core/browser/content_settings_pref_provider.cc b/components/content_settings/core/browser/content_settings_pref_provider.cc --- a/components/content_settings/core/browser/content_settings_pref_provider.cc +++ b/components/content_settings/core/browser/content_settings_pref_provider.cc @@ -2453,12 +1731,12 @@ diff --git a/components/content_settings/core/browser/content_settings_pref_prov PrefProvider::PrefProvider(PrefService* prefs, bool off_the_record, -+ bool always_incognito_enabled, ++ bool force_save_site_settings, bool store_last_modified, bool restore_session) : prefs_(prefs), off_the_record_(off_the_record), -+ always_incognito_enabled_(always_incognito_enabled), ++ force_save_site_settings_(force_save_site_settings), store_last_modified_(store_last_modified), clock_(base::DefaultClock::GetInstance()) { TRACE_EVENT_BEGIN("startup", "PrefProvider::PrefProvider"); @@ -2468,7 +1746,7 @@ diff --git a/components/content_settings/core/browser/content_settings_pref_prov info->type(), prefs_, &pref_change_registrar_, - info->pref_name(), off_the_record_, restore_session, + info->pref_name(), -+ off_the_record_ || (!content_type_info && always_incognito_enabled_), ++ off_the_record_ || (!content_type_info && force_save_site_settings_), + restore_session, base::BindRepeating(&PrefProvider::Notify, base::Unretained(this))))); @@ -2480,7 +1758,7 @@ diff --git a/components/content_settings/core/browser/content_settings_pref_prov PrefProvider(PrefService* prefs, bool off_the_record, -+ bool always_incognito_enabled, ++ bool force_save_site_settings, bool store_last_modified, bool restore_session); @@ -2488,7 +1766,7 @@ diff --git a/components/content_settings/core/browser/content_settings_pref_prov raw_ptr prefs_; const bool off_the_record_; -+ const bool always_incognito_enabled_; ++ const bool force_save_site_settings_; bool store_last_modified_; @@ -2499,7 +1777,7 @@ diff --git a/components/content_settings/core/browser/host_content_settings_map. HostContentSettingsMap::HostContentSettingsMap( PrefService* prefs, bool is_off_the_record, -+ bool always_incognito_enabled, ++ bool force_save_site_settings, bool store_last_modified, bool restore_session) : RefcountedKeyedService(base::ThreadTaskRunnerHandle::Get()), @@ -2507,7 +1785,7 @@ diff --git a/components/content_settings/core/browser/host_content_settings_map. #endif prefs_(prefs), is_off_the_record_(is_off_the_record), -+ always_incognito_enabled_(always_incognito_enabled), ++ force_save_site_settings_(force_save_site_settings), store_last_modified_(store_last_modified), allow_invalid_secondary_pattern_for_testing_(false) { TRACE_EVENT0("startup", "HostContentSettingsMap::HostContentSettingsMap"); @@ -2516,7 +1794,7 @@ diff --git a/components/content_settings/core/browser/host_content_settings_map. auto pref_provider_ptr = std::make_unique( - prefs_, is_off_the_record_, store_last_modified_, restore_session); -+ prefs_, is_off_the_record_, always_incognito_enabled_, store_last_modified_, restore_session); ++ prefs_, is_off_the_record_, force_save_site_settings_, store_last_modified_, restore_session); pref_provider_ = pref_provider_ptr.get(); content_settings_providers_[PREF_PROVIDER] = std::move(pref_provider_ptr); user_modifiable_providers_.push_back(pref_provider_); @@ -2527,27 +1805,43 @@ diff --git a/components/content_settings/core/browser/host_content_settings_map. // profile or a guest session. HostContentSettingsMap(PrefService* prefs, bool is_off_the_record, -+ bool always_incognito_enabled, ++ bool force_save_site_settings, bool store_last_modified, bool restore_session); -@@ -309,6 +310,7 @@ class HostContentSettingsMap : public content_settings::Observer, - - // Whether this settings map is for an incognito or guest session. - bool IsOffTheRecord() const { return is_off_the_record_; } -+ bool IsAlwaysIncognito() const { return always_incognito_enabled_; } - - // Adds/removes an observer for content settings changes. - void AddObserver(content_settings::Observer* observer); -@@ -443,6 +445,8 @@ class HostContentSettingsMap : public content_settings::Observer, +@@ -443,6 +444,8 @@ class HostContentSettingsMap : public content_settings::Observer, // Whether this settings map is for an incognito or guest session. bool is_off_the_record_; -+ bool always_incognito_enabled_ = false; ++ bool force_save_site_settings_ = false; + // Whether ContentSettings in the PrefProvider will store a last_modified // timestamp. bool store_last_modified_; +diff --git a/components/offline_pages/core/offline_page_feature.cc b/components/offline_pages/core/offline_page_feature.cc +--- a/components/offline_pages/core/offline_page_feature.cc ++++ b/components/offline_pages/core/offline_page_feature.cc +@@ -47,6 +47,9 @@ const base::Feature kOfflineIndicatorFeature{"OfflineIndicator", + const base::Feature kOfflinePagesNetworkStateLikelyUnknown{ + "OfflinePagesNetworkStateLikelyUnknown", base::FEATURE_DISABLED_BY_DEFAULT}; + ++const base::Feature kOfflinePagesAutoSaveFeature{ ++ "OfflinePagesAutoSaveEnabled", base::FEATURE_ENABLED_BY_DEFAULT}; ++ + const char kPrefetchingOfflinePagesExperimentsOption[] = "exp"; + + bool IsOfflinePagesCTEnabled() { +diff --git a/components/offline_pages/core/offline_page_feature.h b/components/offline_pages/core/offline_page_feature.h +--- a/components/offline_pages/core/offline_page_feature.h ++++ b/components/offline_pages/core/offline_page_feature.h +@@ -21,6 +21,7 @@ extern const base::Feature kOfflinePagesDescriptiveFailStatusFeature; + extern const base::Feature kOfflineIndicatorFeature; + extern const base::Feature kOnTheFlyMhtmlHashComputationFeature; + extern const base::Feature kOfflinePagesNetworkStateLikelyUnknown; ++extern const base::Feature kOfflinePagesAutoSaveFeature; + + // The parameter name used to find the experiment tag for prefetching offline + // pages. diff --git a/components/omnibox/browser/autocomplete_provider_client.cc b/components/omnibox/browser/autocomplete_provider_client.cc --- a/components/omnibox/browser/autocomplete_provider_client.cc +++ b/components/omnibox/browser/autocomplete_provider_client.cc @@ -2603,7 +1897,7 @@ diff --git a/weblayer/browser/host_content_settings_map_factory.cc b/weblayer/br scoped_refptr settings_map = base::MakeRefCounted( user_prefs::UserPrefs::Get(context), context->IsOffTheRecord(), -+ /*always_incognito_enabled*/false, ++ /*force_save_site_settings*/false, /*store_last_modified=*/true, /*restore_session=*/false);