From: csagan5 <32685696+csagan5@users.noreply.github.com>
Date: Sat, 2 Oct 2021 13:20:36 +0200
Subject: Add an always-incognito mode

Add a preference that causes all new tabs and all clicked links to launch in incognito.
Make sure initial incognito status is correctly recognized.
Enable incognito custom tabs and fix crashes for incognito/custom tab intents
Use a native flag to correctly start new tabs on app startup

Add history, recents, offlinepages and send to home screen support for always incognito.
History, recent tabs and offline pages require the INCOGNITO_TAB_HISTORY_ENABLED
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 <ryan.bradley.archer@gmail.com>
Major contributions by uazo.
See also: https://github.com/bromite/bromite/pull/1427

License: GPL-3.0-only - https://spdx.org/licenses/GPL-3.0-only.html
---
 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  |   9 +-
 .../chrome/browser/app/ChromeActivity.java    |   4 +
 .../AppMenuPropertiesDelegateImpl.java        |  26 ++-
 .../ChromeContextMenuPopulator.java           |   7 +-
 .../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 ++
 .../native_page/NativePageFactory.java        |   4 +-
 .../chrome/browser/ntp/RecentTabsManager.java |  28 ++-
 .../privacy/settings/IncognitoSettings.java   | 160 ++++++++++++++++++
 .../browser/settings/SettingsActivity.java    |   4 +
 .../HistoricalTabModelObserver.java           |   6 +-
 .../tab/tab_restore/HistoricalTabSaver.java   |   2 +-
 .../tab_restore/HistoricalTabSaverImpl.java   |  17 +-
 .../tabbed_mode/TabbedRootUiCoordinator.java  |   4 +-
 .../browser/tabmodel/ChromeTabCreator.java    |   5 +-
 .../tabmodel/TabModelSelectorImpl.java        |   3 +
 .../browser/tabmodel/TabPersistentStore.java  |   9 +
 .../browser/toolbar/ToolbarManager.java       |   4 +-
 .../webapps/WebappIntentDataProvider.java     |  14 ++
 chrome/browser/about_flags.cc                 |   4 +
 .../browser/android/historical_tab_saver.cc   |  22 ++-
 .../chrome_autocomplete_provider_client.cc    |   7 +
 .../chrome_autocomplete_provider_client.h     |   1 +
 .../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      |   4 +-
 chrome/browser/history/history_tab_helper.cc  |  18 ++
 chrome/browser/history/history_tab_helper.h   |  10 +-
 .../android/offline_page_bridge.cc            |  11 +-
 .../android/offline_page_model_factory.cc     |  20 ++-
 .../android/request_coordinator_factory.cc    |  27 ++-
 .../offline_page_model_factory.h              |   1 +
 .../offline_pages/recent_tab_helper.cc        |  19 ++-
 .../browser/offline_pages/recent_tab_helper.h |   3 +
 .../request_coordinator_factory.h             |   4 +-
 chrome/browser/prefs/browser_prefs.cc         |   5 +
 .../browser/ui/android/native_page/BUILD.gn   |   2 +
 .../browser/ui/native_page/NativePage.java    |  12 +-
 .../strings/android_chrome_strings.grd        |  31 ++++
 .../browser/toolbar/LocationBarModel.java     |   7 +-
 chrome/browser/ui/messages/android/BUILD.gn   |   1 +
 .../snackbar/INeedSnackbarManager.java        |  27 +++
 chrome/common/pref_names.cc                   |   6 +
 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  |   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, 719 insertions(+), 77 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/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
@@ -652,6 +652,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
@@ -3,6 +3,7 @@
 # found in the LICENSE file.
 
 chrome_java_sources = [
+  "java/src/org/chromium/chrome/browser/AlwaysIncognitoLinkInterceptor.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",
@@ -914,6 +915,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 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    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 <https://www.gnu.org/licenses/>.
+-->
+
+<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+
+    <org.chromium.components.browser_ui.settings.ChromeSwitchPreference
+        android:key="always_incognito"
+        android:title="@string/always_incognito_title"
+        android:summary="@string/always_incognito_summary"
+        android:defaultValue="false" />
+    <org.chromium.components.browser_ui.settings.ChromeSwitchPreference
+        android:key="incognito_history"
+        android:title="@string/incognito_history_enabled_title"
+        android:summary="@string/incognito_history_enabled_summary"
+        android:defaultValue="false" />
+    <org.chromium.components.browser_ui.settings.ChromeSwitchPreference
+        android:key="incognito_save_site_setting"
+        android:title="@string/incognito_save_site_setting_enabled_title"
+        android:summary="@string/incognito_save_site_setting_enabled_summary"
+        android:defaultValue="false" />
+</PreferenceScreen>
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
@@ -40,6 +40,11 @@ found in the LICENSE file.
         android:key="secure_dns"
         android:title="@string/settings_secure_dns_title"
         android:fragment="org.chromium.chrome.browser.privacy.secure_dns.SecureDnsSettings"/>
+    <Preference
+        android:key="incognito_settings"
+        android:title="@string/incognito_settings_title"
+        android:summary="@string/incognito_settings_summary"
+        android:fragment="org.chromium.chrome.browser.privacy.settings.IncognitoSettings"/>
     <Preference
         android:fragment="org.chromium.chrome.browser.privacy.settings.DoNotTrackSettings"
         android:key="do_not_track"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/AlwaysIncognitoLinkInterceptor.java b/chrome/android/java/src/org/chromium/chrome/browser/AlwaysIncognitoLinkInterceptor.java
new file mode 100644
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/AlwaysIncognitoLinkInterceptor.java
@@ -0,0 +1,53 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+package org.chromium.chrome.browser;
+
+import android.content.SharedPreferences;
+import org.chromium.base.ContextUtils;
+
+import org.chromium.components.user_prefs.UserPrefs;
+import org.chromium.components.prefs.PrefService;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.preferences.Pref;
+import org.chromium.base.Log;
+
+import androidx.annotation.Nullable;
+
+/**
+ * A {@link TabObserver} that implements the always-incognito preference behavior for links.
+ */
+public class AlwaysIncognitoLinkInterceptor {
+
+    private static final String TAG = "AlwaysIncognito";
+    public static final String PREF_ALWAYS_INCOGNITO = "always_incognito";
+
+    private static @Nullable Boolean cachedIsAlwaysIncognito = null;
+
+    public static boolean isAlwaysIncognito() {
+        if (cachedIsAlwaysIncognito != null) return cachedIsAlwaysIncognito;
+        cachedIsAlwaysIncognito = ContextUtils.getAppSharedPreferences()
+                                    .getBoolean(PREF_ALWAYS_INCOGNITO, false);
+        return cachedIsAlwaysIncognito;
+    }
+
+    public static void setAlwaysIncognito(boolean enabled) {
+        UserPrefs.get(Profile.getLastUsedRegularProfile())
+            .setBoolean(Pref.ALWAYS_INCOGNITO_ENABLED, enabled);
+
+        SharedPreferences.Editor sharedPreferenceEditor = ContextUtils.getAppSharedPreferences().edit();
+        sharedPreferenceEditor.putBoolean("always_incognito", enabled);
+        sharedPreferenceEditor.apply();
+    }
+
+    public static void migrateSettingToNative() {
+        if (isAlwaysIncognito()) {
+            PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile());
+            if (!prefService.getBoolean(Pref.ALWAYS_INCOGNITO_ENABLED)) {
+                Log.i(TAG, "Pref migration from java to native");
+                prefService.setBoolean(Pref.ALWAYS_INCOGNITO_ENABLED, true);
+            }
+        }
+    }
+}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeTabbedActivity.java
@@ -58,6 +58,7 @@ import org.chromium.base.task.PostTask;
 import org.chromium.build.annotations.UsedByReflection;
 import org.chromium.cc.input.BrowserControlsState;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
 import org.chromium.chrome.browser.IntentHandler.IntentHandlerDelegate;
 import org.chromium.chrome.browser.IntentHandler.TabOpenType;
 import org.chromium.chrome.browser.accessibility_tab_switcher.OverviewListLayout;
@@ -578,8 +579,9 @@ public class ChromeTabbedActivity extends ChromeActivity<ChromeActivityComponent
             mTabModelOrchestrator.onNativeLibraryReady(getTabContentManager());
 
             // For saving non-incognito tab closures for Recent Tabs.
+            boolean alwaysIncognito = AlwaysIncognitoLinkInterceptor.isAlwaysIncognito();
             mHistoricalTabModelObserver =
-                    new HistoricalTabModelObserver(mTabModelSelector.getModel(false));
+                    new HistoricalTabModelObserver(mTabModelSelector.getModel(alwaysIncognito));
 
             if (TabUiFeatureUtilities.isTabletGridTabSwitcherEnabled(this)) {
                 mTabModelSelector.addObserver(new TabModelSelectorObserver() {
@@ -1904,8 +1906,9 @@ public class ChromeTabbedActivity extends ChromeActivity<ChromeActivityComponent
         Bundle savedInstanceState = getSavedInstanceState();
 
         // We determine the model as soon as possible so every systems get initialized coherently.
-        boolean startIncognito = savedInstanceState != null
-                && savedInstanceState.getBoolean(IS_INCOGNITO_SELECTED, false);
+        boolean startIncognito = AlwaysIncognitoLinkInterceptor.isAlwaysIncognito()
+                || (savedInstanceState != null
+                && savedInstanceState.getBoolean(IS_INCOGNITO_SELECTED, false));
 
         mNextTabPolicySupplier = new ChromeNextTabPolicySupplier(mLayoutStateProviderSupplier);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/ChromeActivity.java
@@ -93,6 +93,7 @@ import org.chromium.chrome.browser.compositor.layouts.content.ContentOffsetProvi
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManagerHandler;
 import org.chromium.chrome.browser.dependency_injection.ChromeActivityCommonsModule;
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
 import org.chromium.chrome.browser.dependency_injection.ChromeActivityComponent;
 import org.chromium.chrome.browser.dependency_injection.ModuleFactoryOverrides;
 import org.chromium.chrome.browser.device.DeviceClassManager;
@@ -1808,6 +1809,9 @@ public abstract class ChromeActivity<C extends ChromeActivityComponent>
             throw new IllegalStateException(
                     "Attempting to access TabCreator before initialization");
         }
+        if (AlwaysIncognitoLinkInterceptor.isAlwaysIncognito()) {
+            incognito = true;
+        }
         return mTabCreatorManagerSupplier.get().getTabCreator(incognito);
     }
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/app/appmenu/AppMenuPropertiesDelegateImpl.java
@@ -34,6 +34,7 @@ import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ActivityTabProvider;
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
 import org.chromium.chrome.browser.banners.AppMenuVerbiage;
 import org.chromium.chrome.browser.bookmarks.BookmarkFeatures;
 import org.chromium.chrome.browser.bookmarks.BookmarkModel;
@@ -99,6 +100,10 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
+import org.chromium.components.prefs.PrefService;
+import org.chromium.components.user_prefs.UserPrefs;
+import org.chromium.chrome.browser.preferences.Pref;
+
 /**
  * Base implementation of {@link AppMenuPropertiesDelegate} that handles hiding and showing menu
  * items based on activity state.
@@ -560,6 +565,13 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate
     }
 
     private void prepareCommonMenuItems(Menu menu, @MenuGroup int menuGroup, boolean isIncognito) {
+        boolean always_incognito = AlwaysIncognitoLinkInterceptor.isAlwaysIncognito();
+        if (always_incognito) {
+            final MenuItem newTabOption = menu.findItem(R.id.new_tab_menu_id);
+            if (newTabOption != null)
+                newTabOption.setVisible(false);
+        }
+
         // We have to iterate all menu items since same menu item ID may be associated with more
         // than one menu items.
         boolean isOverviewModeMenu = menuGroup == MenuGroup.OVERVIEW_MODE_MENU;
@@ -636,7 +648,15 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate
             }
 
             if (item.getItemId() == R.id.recent_tabs_menu_id) {
-                item.setVisible(!isIncognito);
+                if (always_incognito) {
+                    PrefService prefService =
+                                                            UserPrefs.get(Profile.getLastUsedRegularProfile());
+                    boolean historyEnabledInIncognito =
+                        prefService.getBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED);
+                    item.setVisible(historyEnabledInIncognito);
+                }
+                else
+                    item.setVisible(!isIncognito);
             }
             if (item.getItemId() == R.id.menu_group_tabs) {
                 item.setVisible(isMenuGroupTabsVisible);
@@ -876,7 +896,9 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate
         //                is not persisted when adding to the homescreen.
         // * If creating shortcuts it not supported by the current home screen.
         return WebappsUtils.isAddToHomeIntentSupported() && !isChromeScheme && !isFileScheme
-                && !isContentScheme && !isIncognito && !url.isEmpty();
+                && !isContentScheme && !url.isEmpty()
+                && (!isIncognito ||
+                    AlwaysIncognitoLinkInterceptor.isAlwaysIncognito());
     }
 
     /**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/contextmenu/ChromeContextMenuPopulator.java
@@ -30,6 +30,7 @@ import org.chromium.base.ContextUtils;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
 import org.chromium.chrome.browser.compositor.bottombar.ephemeraltab.EphemeralTabCoordinator;
 import org.chromium.chrome.browser.contextmenu.ChromeContextMenuItem.Item;
 import org.chromium.chrome.browser.contextmenu.ContextMenuCoordinator.ListItemType;
@@ -364,6 +365,9 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator {
         boolean hasSaveImage = false;
         mShowEphemeralTabNewLabel = null;
 
+        boolean always_incognito =
+            AlwaysIncognitoLinkInterceptor.isAlwaysIncognito();
+
         List<Pair<Integer, ModelList>> groupedItems = new ArrayList<>();
 
         if (mParams.isAnchor()) {
@@ -382,6 +386,7 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator {
                             linkGroup.add(createListItem(Item.OPEN_IN_NEW_TAB_IN_GROUP));
                         }
                     }
+
                     if (!mItemDelegate.isIncognito() && mItemDelegate.isIncognitoSupported()) {
                         linkGroup.add(createListItem(Item.OPEN_IN_INCOGNITO_TAB));
                     }
@@ -406,7 +411,7 @@ public class ChromeContextMenuPopulator implements ContextMenuPopulator {
                 }
             }
             if (FirstRunStatus.getFirstRunFlowComplete()) {
-                if (!mItemDelegate.isIncognito()
+                if ((always_incognito || !mItemDelegate.isIncognito())
                         && UrlUtilities.isDownloadableScheme(mParams.getLinkUrl())) {
                     linkGroup.add(createListItem(Item.SAVE_LINK_AS));
                 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivityLifecycleUmaTracker.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivityLifecycleUmaTracker.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivityLifecycleUmaTracker.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivityLifecycleUmaTracker.java
@@ -68,31 +68,6 @@ public class CustomTabActivityLifecycleUmaTracker
     private boolean mIsInitialResume = true;
 
     private void recordIncognitoLaunchReason() {
-        IncognitoCustomTabIntentDataProvider incognitoProvider =
-                (IncognitoCustomTabIntentDataProvider) mIntentDataProvider;
-
-        @IntentHandler.IncognitoCCTCallerId
-        int incognitoCCTCallerId = incognitoProvider.getFeatureIdForMetricsCollection();
-        RecordHistogram.recordEnumeratedHistogram("CustomTabs.IncognitoCCTCallerId",
-                incognitoCCTCallerId, IntentHandler.IncognitoCCTCallerId.NUM_ENTRIES);
-
-        // Record which 1P app launched Incognito CCT.
-        if (incognitoCCTCallerId == IntentHandler.IncognitoCCTCallerId.GOOGLE_APPS) {
-            String sendersPackageName = incognitoProvider.getSendersPackageName();
-            @IntentHandler.ExternalAppId
-            int externalId = IntentHandler.mapPackageToExternalAppId(sendersPackageName);
-            if (externalId != IntentHandler.ExternalAppId.OTHER) {
-                RecordHistogram.recordEnumeratedHistogram("CustomTabs.ClientAppId.Incognito",
-                        externalId, IntentHandler.ExternalAppId.NUM_ENTRIES);
-            } else {
-                // Using package name didn't give any meaningful insight on who launched the
-                // Incognito CCT, falling back to check if they provided EXTRA_APPLICATION_ID.
-                externalId =
-                        IntentHandler.determineExternalIntentSource(incognitoProvider.getIntent());
-                RecordHistogram.recordEnumeratedHistogram("CustomTabs.ClientAppId.Incognito",
-                        externalId, IntentHandler.ExternalAppId.NUM_ENTRIES);
-            }
-        }
     }
 
     private void recordUserAction() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabAppMenuPropertiesDelegate.java
@@ -21,6 +21,7 @@ import org.chromium.base.ContextUtils;
 import org.chromium.base.supplier.ObservableSupplier;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ActivityTabProvider;
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
 import org.chromium.chrome.browser.DefaultBrowserInfo;
 import org.chromium.chrome.browser.app.appmenu.AppMenuPropertiesDelegateImpl;
 import org.chromium.chrome.browser.app.appmenu.DividerLineMenuItemViewBinder;
@@ -176,6 +177,9 @@ public class CustomTabAppMenuPropertiesDelegate extends AppMenuPropertiesDelegat
                 downloadItemVisible = false;
                 openInChromeItemVisible = false;
             }
+            if (AlwaysIncognitoLinkInterceptor.isAlwaysIncognito()) {
+                downloadItemVisible = true;
+            }
 
             boolean isChromeScheme = url.getScheme().equals(UrlConstants.CHROME_SCHEME)
                     || url.getScheme().equals(UrlConstants.CHROME_NATIVE_SCHEME);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabIntentDataProvider.java
@@ -49,6 +49,9 @@ import org.chromium.components.embedder_support.util.UrlConstants;
 import org.chromium.components.version_info.VersionInfo;
 import org.chromium.device.mojom.ScreenOrientationLockType;
 
+import org.chromium.base.ContextUtils;
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
+
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 import java.util.ArrayList;
@@ -855,7 +858,7 @@ public class CustomTabIntentDataProvider extends BrowserServicesIntentDataProvid
 
     @Override
     public boolean isIncognito() {
-        return false;
+        return AlwaysIncognitoLinkInterceptor.isAlwaysIncognito();
     }
 
     @Nullable
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/download/DownloadUtils.java
@@ -34,6 +34,7 @@ import org.chromium.base.annotations.NativeMethods;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
 import org.chromium.chrome.browser.ChromeTabbedActivity;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.app.download.home.DownloadActivity;
@@ -74,6 +75,10 @@ import org.chromium.url.GURL;
 
 import java.io.File;
 
+import org.chromium.components.prefs.PrefService;
+import org.chromium.components.user_prefs.UserPrefs;
+import org.chromium.chrome.browser.preferences.Pref;
+
 /**
  * A class containing some utility static methods.
  */
@@ -318,7 +323,16 @@ public class DownloadUtils {
         // Offline pages isn't supported in Incognito. This should be checked before calling
         // OfflinePageBridge.getForProfile because OfflinePageBridge instance will not be found
         // for incognito profile.
-        if (tab.isIncognito()) return false;
+        boolean always_incognito = AlwaysIncognitoLinkInterceptor.isAlwaysIncognito();
+        if (always_incognito) {
+            PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile());
+            boolean historyEnabledInIncognito =
+                prefService.getBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED);
+            if (historyEnabledInIncognito == false)
+                return false;
+        } else {
+            if (tab.isIncognito()) return false;
+        }
 
         // Check if the page url is supported for saving. Only HTTP and HTTPS pages are allowed.
         if (!OfflinePageBridge.canSavePage(tab.getUrl())) return false;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryManager.java
@@ -35,6 +35,7 @@ import com.google.android.material.tabs.TabLayout.OnTabSelectedListener;
 import org.chromium.base.metrics.RecordHistogram;
 import org.chromium.base.metrics.RecordUserAction;
 import org.chromium.base.supplier.ObservableSupplier;
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
 import org.chromium.base.supplier.ObservableSupplierImpl;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.R;
@@ -77,6 +78,12 @@ import java.io.Serializable;
 import java.util.List;
 import java.util.concurrent.atomic.AtomicReference;
 
+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;
+
 /**
  * Combines and manages the different UI components of browsing history.
  */
@@ -551,7 +558,16 @@ public class HistoryManager implements OnMenuItemClickListener, SelectionObserve
         return mRootView;
     }
 
-    private boolean shouldShowIncognitoPlaceholder() {
+    public boolean isIncognito() { return mIsIncognito; }
+
+    public boolean shouldShowIncognitoPlaceholder() {
+        if (mIsIncognito &&
+                AlwaysIncognitoLinkInterceptor.isAlwaysIncognito()) {
+            PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile());
+            boolean historyEnabledInIncognito =
+                prefService.getBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED);
+            if (historyEnabledInIncognito) return false;
+        }
         return mIsIncognito
                 && ChromeFeatureList.isEnabled(
                         ChromeFeatureList.UPDATE_HISTORY_ENTRY_POINTS_IN_INCOGNITO);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryPage.java b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryPage.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryPage.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/history/HistoryPage.java
@@ -11,6 +11,7 @@ import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.R;
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
 import org.chromium.chrome.browser.history_clusters.HistoryClustersConstants;
 import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.tab.Tab;
@@ -19,6 +20,12 @@ import org.chromium.chrome.browser.ui.native_page.BasicNativePage;
 import org.chromium.chrome.browser.ui.native_page.NativePageHost;
 import org.chromium.components.embedder_support.util.UrlConstants;
 
+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;
+
 /**
  * Native page for managing browsing history.
  */
@@ -41,6 +48,15 @@ public class HistoryPage extends BasicNativePage {
             boolean isIncognito, Supplier<Tab> tabSupplier, String url) {
         super(host);
 
+        if (isIncognito &&
+                AlwaysIncognitoLinkInterceptor.isAlwaysIncognito()) {
+            PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile());
+            boolean historyEnabledInIncognito =
+                prefService.getBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED);
+            if (historyEnabledInIncognito == true) isIncognito = false;
+        }
+
+
         Uri uri = Uri.parse(url);
         assert uri.getHost().equals(UrlConstants.HISTORY_HOST);
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/native_page/NativePageFactory.java
@@ -15,6 +15,7 @@ import org.chromium.base.jank_tracker.JankTracker;
 import org.chromium.base.supplier.BooleanSupplier;
 import org.chromium.base.supplier.DestroyableObservableSupplier;
 import org.chromium.base.supplier.Supplier;
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
 import org.chromium.chrome.browser.app.ChromeActivity;
 import org.chromium.chrome.browser.app.download.home.DownloadPage;
 import org.chromium.chrome.browser.bookmarks.BookmarkPage;
@@ -251,7 +252,8 @@ public class NativePageFactory {
             String url, NativePage candidatePage, Tab tab, boolean isIncognito) {
         NativePage page;
 
-        switch (NativePage.nativePageType(url, candidatePage, isIncognito)) {
+        boolean isAlwaysIncognito = AlwaysIncognitoLinkInterceptor.isAlwaysIncognito();
+        switch (NativePage.nativePageType(url, candidatePage, isIncognito, isAlwaysIncognito)) {
             case NativePageType.NONE:
                 return null;
             case NativePageType.CANDIDATE:
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ntp/RecentTabsManager.java
@@ -21,6 +21,15 @@ import org.chromium.chrome.browser.ui.favicon.FaviconHelper;
 import org.chromium.chrome.browser.ui.favicon.FaviconHelper.FaviconImageCallback;
 import org.chromium.url.GURL;
 
+import android.content.Intent;
+import android.provider.Browser;
+import android.net.Uri;
+import org.chromium.base.ContextUtils;
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
+import org.chromium.chrome.browser.IntentHandler;
+import org.chromium.ui.mojom.WindowOpenDisposition;
+import org.chromium.components.embedder_support.util.UrlUtilities;
+
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -78,7 +87,8 @@ public class RecentTabsManager {
      */
     public RecentTabsManager(Tab tab, TabModelSelector tabModelSelector, Profile profile,
             Context context, Runnable showHistoryManager) {
-        mProfile = profile;
+        mProfile = profile.getOriginalProfile();
+        profile = mProfile;
         mActiveTab = tab;
         mTabModelSelector = tabModelSelector;
         mShowHistoryManager = showHistoryManager;
@@ -210,6 +220,22 @@ public class RecentTabsManager {
      */
     public void openRecentlyClosedTab(RecentlyClosedTab tab, int windowDisposition) {
         if (mIsDestroyed) return;
+        if (AlwaysIncognitoLinkInterceptor.isAlwaysIncognito()) {
+            // allow only http/https urls
+            if (!UrlUtilities.isHttpOrHttps(tab.getUrl())) return;
+
+            Context context = ContextUtils.getApplicationContext();
+            Intent intent = new Intent(Intent.ACTION_VIEW,
+                Uri.parse(tab.getUrl().getSpec()));
+            intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
+            if (windowDisposition != WindowOpenDisposition.CURRENT_TAB) {
+                intent.putExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, true);
+            }
+            intent.setPackage(context.getPackageName());
+            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
+            IntentHandler.startActivityForTrustedIntent(intent);
+            return;
+        }
         mTabSessionIdsRestored.put(tab.getSessionId(), true);
         RecordUserAction.record("MobileRecentTabManagerRecentTabOpened");
         // Window disposition will select which tab to open.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/IncognitoSettings.java b/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/IncognitoSettings.java
new file mode 100644
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/IncognitoSettings.java
@@ -0,0 +1,160 @@
+/*
+    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 <https://www.gnu.org/licenses/>.
+*/
+
+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.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_INCOGNITO_TAB_HISTORY = "incognito_history";
+    private static final String PREF_INCOGNITO_SAVE_SITE_SETTING = "incognito_save_site_setting";
+
+    private final PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile());
+
+    @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),
+                new SnackbarManager.SnackbarController() {
+                        @Override
+                        public void onDismissNoAction(Object actionData) { }
+
+                        @Override
+                        public void onAction(Object actionData) {
+                                ApplicationLifetime.terminate(true);
+                        }
+                }, Snackbar.TYPE_NOTIFICATION, Snackbar.UMA_UNKNOWN)
+                .setSingleLine(false)
+                .setAction(getActivity().getString(R.string.relaunch),
+                        /*actionData*/null)
+                .setDuration(/*durationMs*/70000);
+
+        ChromeSwitchPreference historyInIncognitoPref =
+                (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;
+    }
+
+    @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
@@ -58,6 +58,7 @@ import org.chromium.chrome.browser.profiles.Profile;
 import org.chromium.chrome.browser.profiles.ProfileManagerUtils;
 import org.chromium.chrome.browser.search_engines.settings.SearchEngineSettings;
 import org.chromium.chrome.browser.site_settings.ChromeSiteSettingsDelegate;
+import org.chromium.chrome.browser.ui.messages.snackbar.INeedSnackbarManager;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
 import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager.SnackbarManageable;
 import org.chromium.components.browser_ui.accessibility.AccessibilitySettings;
@@ -254,6 +255,9 @@ public class SettingsActivity extends ChromeBaseAppCompatActivity
         if (fragment instanceof AdPersonalizationRemovedFragment) {
             ((AdPersonalizationRemovedFragment) fragment).setSnackbarManager(getSnackbarManager());
         }
+        if (fragment instanceof INeedSnackbarManager) {
+            ((INeedSnackbarManager)fragment).setSnackbarManager(mSnackbarManager);
+        }
     }
 
     @Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabModelObserver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabModelObserver.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabModelObserver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabModelObserver.java
@@ -14,6 +14,8 @@ import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
+
 /**
  * A tab model observer for managing bulk closures.
  */
@@ -41,7 +43,8 @@ public class HistoricalTabModelObserver implements TabModelObserver {
         if (tabs.isEmpty()) return;
 
         if (tabs.size() == 1) {
-            mHistoricalTabSaver.createHistoricalTab(tabs.get(0));
+            boolean is_always_incognito = AlwaysIncognitoLinkInterceptor.isAlwaysIncognito();
+            mHistoricalTabSaver.createHistoricalTab(tabs.get(0), is_always_incognito);
             return;
         }
 
@@ -72,7 +75,6 @@ public class HistoricalTabModelObserver implements TabModelObserver {
             entries.add(historicalGroup);
             idToGroup.put(groupId, historicalGroup);
         }
-
         mHistoricalTabSaver.createHistoricalBulkClosure(entries);
     }
 }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaver.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaver.java
@@ -16,7 +16,7 @@ public interface HistoricalTabSaver {
      * Creates a Tab entry in TabRestoreService.
      * @param tab The {@link Tab} to create an entry for.
      */
-    void createHistoricalTab(Tab tab);
+    void createHistoricalTab(Tab tab, boolean is_always_incognito);
 
     /**
      * Creates a Group or Tab entry in TabRestoreService.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImpl.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/tab_restore/HistoricalTabSaverImpl.java
@@ -27,6 +27,8 @@ import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
+
 /**
  * Creates historical entries in TabRestoreService.
  */
@@ -60,10 +62,10 @@ public class HistoricalTabSaverImpl implements HistoricalTabSaver {
 
     // HistoricalTabSaver implementation.
     @Override
-    public void createHistoricalTab(Tab tab) {
+    public void createHistoricalTab(Tab tab, boolean is_always_incognito) {
         if (!shouldSave(tab)) return;
 
-        createHistoricalTabInternal(tab);
+        createHistoricalTabInternal(tab, is_always_incognito);
     }
 
     @Override
@@ -115,7 +117,7 @@ public class HistoricalTabSaverImpl implements HistoricalTabSaver {
 
         // If there is only a single valid tab remaining save it individually.
         if (validEntries.size() == 1 && validEntries.get(0).isSingleTab()) {
-            createHistoricalTabInternal(allTabs.get(0));
+            createHistoricalTabInternal(allTabs.get(0), false);
             return;
         }
 
@@ -140,11 +142,12 @@ public class HistoricalTabSaverImpl implements HistoricalTabSaver {
                 CollectionUtil.integerListToIntArray(savedStateVersions));
     }
 
-    private void createHistoricalTabInternal(Tab tab) {
+    private void createHistoricalTabInternal(Tab tab, boolean is_always_incognito) {
         RecordHistogram.recordEnumeratedHistogram("Tabs.RecentlyClosed.HistoricalSaverCloseType",
                 HistoricalSaverCloseType.TAB, HistoricalSaverCloseType.COUNT);
         HistoricalTabSaverImplJni.get().createHistoricalTab(
-                tab, getWebContentsState(tab).buffer(), getWebContentsState(tab).version());
+                tab, getWebContentsState(tab).buffer(), getWebContentsState(tab).version(),
+                is_always_incognito);
     }
 
     /**
@@ -152,7 +155,7 @@ public class HistoricalTabSaverImpl implements HistoricalTabSaver {
      * internal Chrome scheme, about:blank, or a native page and it cannot be incognito.
      */
     private boolean shouldSave(Tab tab) {
-        if (tab.isIncognito()) return false;
+        if (tab.isIncognito() && !AlwaysIncognitoLinkInterceptor.isAlwaysIncognito()) return false;
 
         // {@link GURL#getScheme()} is not available in unit tests.
         if (mIgnoreUrlSchemesForTesting) return true;
@@ -225,7 +228,7 @@ public class HistoricalTabSaverImpl implements HistoricalTabSaver {
 
     @NativeMethods
     interface Natives {
-        void createHistoricalTab(Tab tab, ByteBuffer state, int savedStateVersion);
+        void createHistoricalTab(Tab tab, ByteBuffer state, int savedStateVersion, boolean is_always_incognito);
         void createHistoricalGroup(TabModel model, String title, Tab[] tabs,
                 ByteBuffer[] byteBuffers, int[] savedStationsVersions);
         void createHistoricalBulkClosure(TabModel model, int[] groupIds, String[] titles,
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabbed_mode/TabbedRootUiCoordinator.java
@@ -122,6 +122,8 @@ import org.chromium.components.webapps.bottomsheet.PwaBottomSheetControllerFacto
 import org.chromium.content_public.browser.WebContents;
 import org.chromium.ui.base.ActivityWindowAndroid;
 import org.chromium.ui.base.DeviceFormFactor;
+import org.chromium.base.ContextUtils;
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
 import org.chromium.ui.base.IntentRequestTracker;
 import org.chromium.ui.modaldialog.ModalDialogManager;
 
@@ -482,7 +484,7 @@ public class TabbedRootUiCoordinator extends RootUiCoordinator {
                     mAppMenuCoordinator == null ? null : mAppMenuCoordinator.getAppMenuHandler();
             mEmptyBackgroundViewWrapper =
                     new EmptyBackgroundViewWrapper(mTabModelSelectorSupplier.get(),
-                            mTabCreatorManagerSupplier.get().getTabCreator(false), mActivity,
+                            mTabCreatorManagerSupplier.get().getTabCreator(AlwaysIncognitoLinkInterceptor.isAlwaysIncognito()), mActivity,
                             appMenuHandler, mSnackbarManagerSupplier.get(), mLayoutManagerSupplier);
             mEmptyBackgroundViewWrapper.initialize();
         }
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/ChromeTabCreator.java
@@ -41,6 +41,10 @@ import org.chromium.ui.base.PageTransition;
 import org.chromium.ui.base.WindowAndroid;
 import org.chromium.url.GURL;
 
+import org.chromium.base.ContextUtils;
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
+import org.chromium.chrome.browser.tab.TabObserver;
+
 /**
  * This class creates various kinds of new tabs and adds them to the right {@link TabModel}.
  */
@@ -312,7 +316,6 @@ public class ChromeTabCreator extends TabCreator {
     // TODO(crbug.com/1081924): Clean up the launches from SearchActivity/Chrome.
     public Tab launchUrlFromExternalApp(
             LoadUrlParams loadUrlParams, String appId, boolean forceNewTab, Intent intent) {
-        assert !mIncognito;
         // Don't re-use tabs for intents from Chrome. Note that this can be spoofed so shouldn't be
         // relied on for anything security sensitive.
         boolean isLaunchedFromChrome = TextUtils.equals(appId, mActivity.getPackageName());
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorImpl.java
@@ -10,6 +10,7 @@ import androidx.annotation.Nullable;
 import androidx.annotation.VisibleForTesting;
 
 import org.chromium.base.supplier.Supplier;
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
 import org.chromium.chrome.browser.flags.ActivityType;
 import org.chromium.chrome.browser.ntp.RecentlyClosedBridge;
@@ -109,6 +110,8 @@ public class TabModelSelectorImpl extends TabModelSelectorBase implements TabMod
     public void onNativeLibraryReady(TabContentManager tabContentProvider) {
         assert mTabContentManager == null : "onNativeLibraryReady called twice!";
 
+        AlwaysIncognitoLinkInterceptor.migrateSettingToNative();
+
         ChromeTabCreator regularTabCreator =
                 (ChromeTabCreator) getTabCreatorManager().getTabCreator(false);
         ChromeTabCreator incognitoTabCreator =
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java
@@ -58,6 +58,8 @@ import org.chromium.content_public.browser.LoadUrlParams;
 import org.chromium.content_public.browser.UiThreadTaskTraits;
 import org.chromium.url.GURL;
 
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
+
 import java.io.BufferedInputStream;
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
@@ -757,6 +759,13 @@ public class TabPersistentStore {
                 }
             }
         }
+        if (AlwaysIncognitoLinkInterceptor.isAlwaysIncognito()) {
+            if (!isIncognito) {
+                Log.w(TAG, "Failed to restore tab: not in incognito mode.");
+                return;
+            }
+        }
+
         TabModel model = mTabModelSelector.getModel(isIncognito);
 
         if (model.isIncognito() != isIncognito) {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/toolbar/ToolbarManager.java
@@ -38,6 +38,7 @@ import org.chromium.base.supplier.OneshotSupplier;
 import org.chromium.base.supplier.Supplier;
 import org.chromium.chrome.R;
 import org.chromium.chrome.browser.ActivityTabProvider;
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
 import org.chromium.chrome.browser.IntentHandler;
 import org.chromium.chrome.browser.app.tab_activity_glue.TabReparentingController;
 import org.chromium.chrome.browser.app.tabmodel.TabWindowManagerSingleton;
@@ -523,7 +524,8 @@ public class ToolbarManager implements UrlFocusChangeListener, ThemeColorObserve
                         return ret;
                     }
                 },
-                SearchEngineLogoUtils.getInstance());
+                SearchEngineLogoUtils.getInstance(),
+                AlwaysIncognitoLinkInterceptor.isAlwaysIncognito());
         mControlContainer = controlContainer;
         assert mControlContainer != null;
 
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappIntentDataProvider.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappIntentDataProvider.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappIntentDataProvider.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappIntentDataProvider.java
@@ -32,6 +32,9 @@ import org.chromium.chrome.browser.flags.ActivityType;
 import org.chromium.components.browser_ui.widget.TintedDrawable;
 import org.chromium.device.mojom.ScreenOrientationLockType;
 
+import org.chromium.base.ContextUtils;
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
+
 /**
  * Stores info about a web app.
  */
@@ -45,6 +48,8 @@ public class WebappIntentDataProvider extends BrowserServicesIntentDataProvider
     private final Intent mIntent;
     private final ColorProviderImpl mColorProvider;
 
+    private boolean mIsIncognito = false;
+
     /**
      * Returns the toolbar color to use if a custom color is not specified by the webapp.
      */
@@ -67,6 +72,10 @@ public class WebappIntentDataProvider extends BrowserServicesIntentDataProvider
         mWebappExtras = webappExtras;
         mWebApkExtras = webApkExtras;
         mActivityType = (webApkExtras != null) ? ActivityType.WEB_APK : ActivityType.WEBAPP;
+
+        if (AlwaysIncognitoLinkInterceptor.isAlwaysIncognito()) {
+            mIsIncognito = true;
+        }
     }
 
     @Override
@@ -155,6 +164,11 @@ public class WebappIntentDataProvider extends BrowserServicesIntentDataProvider
         return mWebApkExtras;
     }
 
+    @Override
+    public boolean isIncognito() {
+        return mIsIncognito;
+    }
+
     @Override
     public @ScreenOrientationLockType.EnumType int getDefaultOrientation() {
         return mWebappExtras.orientation;
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
@@ -4837,6 +4837,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)},
     {"query-tiles", flag_descriptions::kQueryTilesName,
      flag_descriptions::kQueryTilesDescription, kOsAndroid,
      FEATURE_WITH_PARAMS_VALUE_TYPE(query_tiles::features::kQueryTiles,
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
@@ -26,6 +26,11 @@
 #include "components/sessions/core/tab_restore_service.h"
 #include "content/public/browser/web_contents.h"
 
+#include "chrome/common/pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "historical_tab_saver.h"
+
 using base::android::JavaParamRef;
 using base::android::ScopedJavaLocalRef;
 
@@ -38,7 +43,8 @@ constexpr int kInvalidGroupId = -1;
 
 void CreateHistoricalTab(
     TabAndroid* tab_android,
-    WebContentsStateByteBuffer web_contents_state_byte_buffer) {
+    WebContentsStateByteBuffer web_contents_state_byte_buffer,
+    bool is_always_incognito) {
   if (!tab_android) {
     return;
   }
@@ -49,9 +55,14 @@ void CreateHistoricalTab(
     return;
   }
 
+  auto* profile = Profile::FromBrowserContext(scoped_web_contents->web_contents()->GetBrowserContext());
+  if (is_always_incognito) {
+    if (profile->GetOriginalProfile()->GetPrefs()->GetBoolean(prefs::kIncognitoTabHistoryEnabled))
+      profile = profile->GetOriginalProfile();
+  }
+
   sessions::TabRestoreService* service =
-      TabRestoreServiceFactory::GetForProfile(Profile::FromBrowserContext(
-          scoped_web_contents->web_contents()->GetBrowserContext()));
+      TabRestoreServiceFactory::GetForProfile(profile);
   if (!service) {
     return;
   }
@@ -243,14 +254,15 @@ static void JNI_HistoricalTabSaverImpl_CreateHistoricalTab(
     JNIEnv* env,
     const JavaParamRef<jobject>& jtab_android,
     const JavaParamRef<jobject>& state,
-    jint saved_state_version) {
+    jint saved_state_version,
+    jboolean is_always_incognito) {
   void* data = env->GetDirectBufferAddress(state);
   int size = env->GetDirectBufferCapacity(state);
 
   WebContentsStateByteBuffer web_contents_state =
       WebContentsStateByteBuffer(data, size, (int)saved_state_version);
   CreateHistoricalTab(TabAndroid::GetNativeTab(env, jtab_android),
-                      std::move(web_contents_state));
+                      std::move(web_contents_state), is_always_incognito);
 }
 
 // static
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
@@ -310,6 +310,13 @@ signin::IdentityManager* ChromeAutocompleteProviderClient::GetIdentityManager()
   return IdentityManagerFactory::GetForProfile(profile_);
 }
 
+bool ChromeAutocompleteProviderClient::IsAlwaysIncognitoEnabled() const {
+  if (profile_->GetPrefs()->GetBoolean(prefs::kAlwaysIncognitoEnabled)) {
+    return true;
+  }
+  return false;
+}
+
 bool ChromeAutocompleteProviderClient::IsOffTheRecord() const {
   return profile_->IsOffTheRecord();
 }
diff --git a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h
--- a/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h
+++ b/chrome/browser/autocomplete/chrome_autocomplete_provider_client.h
@@ -80,6 +80,7 @@ class ChromeAutocompleteProviderClient : public AutocompleteProviderClient {
       const override;
   signin::IdentityManager* GetIdentityManager() const override;
   bool IsOffTheRecord() const override;
+  bool IsAlwaysIncognitoEnabled() const override;
   bool SearchSuggestEnabled() const override;
   bool AllowDeletingBrowserHistory() const override;
   bool IsPersonalizedUrlDataCollectionActive() const override;
diff --git a/chrome/browser/content_settings/host_content_settings_map_factory.cc b/chrome/browser/content_settings/host_content_settings_map_factory.cc
--- a/chrome/browser/content_settings/host_content_settings_map_factory.cc
+++ b/chrome/browser/content_settings/host_content_settings_map_factory.cc
@@ -15,6 +15,7 @@
 #include "chrome/browser/profiles/profile.h"
 #include "chrome/browser/search_engines/template_url_service_factory.h"
 #include "chrome/common/buildflags.h"
+#include "chrome/common/pref_names.h"
 #include "components/content_settings/core/browser/content_settings_pref_provider.h"
 #include "components/content_settings/core/browser/host_content_settings_map.h"
 #include "components/permissions/features.h"
@@ -95,9 +96,23 @@ scoped_refptr<RefcountedKeyedService>
   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)) {
+    always_incognito_enabled = true;
+  }
+
+  if (prefService->GetBoolean(prefs::kIncognitoSaveSiteSettingEnabled)) {
+    profile = original_profile;
+    force_save_site_settings = true;
+  }
+
   scoped_refptr<HostContentSettingsMap> settings_map(new HostContentSettingsMap(
       profile->GetPrefs(),
-      profile->IsOffTheRecord() || profile->IsGuestSession(),
+      !force_save_site_settings && (profile->IsOffTheRecord() || profile->IsGuestSession()),
+      force_save_site_settings,
       /*store_last_modified=*/true,
       profile->ShouldRestoreOldSessionCookies()));
 
@@ -107,6 +122,9 @@ scoped_refptr<RefcountedKeyedService>
       HostContentSettingsMap::WEBUI_ALLOWLIST_PROVIDER,
       std::move(allowlist_provider));
 
+  if (always_incognito_enabled)
+    return settings_map;
+
   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
@@ -3907,6 +3907,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 kPageInfoHistoryName[] = "Page info history";
 const char kPageInfoHistoryDescription[] =
     "Enable a history sub page to the page info menu, and a button to forget "
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
@@ -2227,6 +2227,9 @@ extern const char kNotificationPermissionRationaleDescription[];
 extern const char kOfflinePagesLivePageSharingName[];
 extern const char kOfflinePagesLivePageSharingDescription[];
 
+extern const char kOfflinePagesAutoSaveFeatureName[];
+extern const char kOfflinePagesAutoSaveFeatureDescription[];
+
 extern const char kPageInfoHistoryName[];
 extern const char kPageInfoHistoryDescription[];
 
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
@@ -561,8 +561,8 @@ BASE_FEATURE(kCCTNewDownloadTab,
 BASE_FEATURE(kCCTIncognito, "CCTIncognito", base::FEATURE_ENABLED_BY_DEFAULT);
 
 BASE_FEATURE(kCCTIncognitoAvailableToThirdParty,
-             "CCTIncognitoAvailableToThirdParty",
-             base::FEATURE_DISABLED_BY_DEFAULT);
+             "CCTIncognitoAvailableToThirdParty",           // must be enabled
+             base::FEATURE_ENABLED_BY_DEFAULT);             // in Bromite
 
 BASE_FEATURE(kCCTPackageNameRecording,
              "CCTPackageNameRecording",
diff --git a/chrome/browser/history/history_tab_helper.cc b/chrome/browser/history/history_tab_helper.cc
--- a/chrome/browser/history/history_tab_helper.cc
+++ b/chrome/browser/history/history_tab_helper.cc
@@ -38,6 +38,9 @@
 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
 #include "components/feed/core/v2/public/feed_api.h"
 #include "components/feed/core/v2/public/feed_service.h"
+#include "chrome/common/pref_names.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
 #else
 #include "chrome/browser/ui/browser.h"
 #include "chrome/browser/ui/browser_finder.h"
@@ -459,6 +462,13 @@ void HistoryTabHelper::TitleWasSet(NavigationEntry* entry) {
 history::HistoryService* HistoryTabHelper::GetHistoryService() {
   Profile* profile =
       Profile::FromBrowserContext(web_contents()->GetBrowserContext());
+
+#if BUILDFLAG(IS_ANDROID)
+  if (profile->GetOriginalProfile()->GetPrefs()->GetBoolean(prefs::kIncognitoTabHistoryEnabled)) {
+    return HistoryServiceFactory::GetForProfile(profile, ServiceAccessType::IMPLICIT_ACCESS);
+  }
+#endif
+
   if (profile->IsOffTheRecord())
     return nullptr;
 
@@ -466,6 +476,14 @@ history::HistoryService* HistoryTabHelper::GetHistoryService() {
       profile, ServiceAccessType::IMPLICIT_ACCESS);
 }
 
+// static
+void HistoryTabHelper::RegisterProfilePrefs(PrefRegistrySimple* registry) {
+  registry->RegisterBooleanPref(prefs::kIncognitoTabHistoryEnabled,
+                                /*default_value=*/false);
+  registry->RegisterBooleanPref(prefs::kIncognitoSaveSiteSettingEnabled,
+                                /*default_value=*/false);
+}
+
 void HistoryTabHelper::WebContentsDestroyed() {
   translate_observation_.Reset();
 
diff --git a/chrome/browser/history/history_tab_helper.h b/chrome/browser/history/history_tab_helper.h
--- a/chrome/browser/history/history_tab_helper.h
+++ b/chrome/browser/history/history_tab_helper.h
@@ -12,6 +12,8 @@
 #include "components/translate/core/browser/translate_driver.h"
 #include "content/public/browser/web_contents_observer.h"
 #include "content/public/browser/web_contents_user_data.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
 
 namespace history {
 struct HistoryAddPageArgs;
@@ -51,6 +53,11 @@ class HistoryTabHelper
     force_eligible_tab_for_testing_ = force;
   }
 
+  static void RegisterProfilePrefs(PrefRegistrySimple* registry);
+
+  // Helper function to return the history service.  May return null.
+  history::HistoryService* GetHistoryService();
+
  private:
   explicit HistoryTabHelper(content::WebContents* web_contents);
   friend class content::WebContentsUserData<HistoryTabHelper>;
@@ -83,9 +90,6 @@ class HistoryTabHelper
   void OnLanguageDetermined(
       const translate::LanguageDetectionDetails& details) override;
 
-  // Helper function to return the history service.  May return null.
-  history::HistoryService* GetHistoryService();
-
   // 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/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
@@ -47,6 +47,9 @@
 #include "content/public/browser/web_contents.h"
 #include "net/base/filename_util.h"
 #include "url/android/gurl_android.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "chrome/common/pref_names.h"
 
 using base::android::ConvertJavaStringToUTF8;
 using base::android::ConvertUTF16ToJavaString;
@@ -785,9 +788,15 @@ void OfflinePageBridge::GetPageByOfflineIdDone(
   }
 
   if (offline_page_model_->IsArchiveInInternalDir(offline_page->file_path)) {
+    bool is_trusted = true;
+    // in always incognito, never trust input file (show file name in url)
+    ProfileKey* profile_key = ProfileKey::FromSimpleFactoryKey(key_);
+    if (profile_key->GetPrefs()->GetBoolean(prefs::kIncognitoTabHistoryEnabled))
+      is_trusted = false;
+
     ValidateFileCallback(launch_location, j_callback_obj,
                          offline_page->offline_id, offline_page->url,
-                         offline_page->file_path, true /* is_trusted*/);
+                         offline_page->file_path, is_trusted);
     return;
   }
 
diff --git a/chrome/browser/offline_pages/android/offline_page_model_factory.cc b/chrome/browser/offline_pages/android/offline_page_model_factory.cc
--- a/chrome/browser/offline_pages/android/offline_page_model_factory.cc
+++ b/chrome/browser/offline_pages/android/offline_page_model_factory.cc
@@ -24,6 +24,9 @@
 #include "components/keyed_service/core/simple_dependency_manager.h"
 #include "components/offline_pages/core/model/offline_page_model_taskified.h"
 #include "components/offline_pages/core/offline_page_metadata_store.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "chrome/common/pref_names.h"
 
 namespace offline_pages {
 
@@ -54,13 +57,15 @@ std::unique_ptr<KeyedService> OfflinePageModelFactory::BuildServiceInstanceFor(
   scoped_refptr<base::SequencedTaskRunner> background_task_runner =
       base::ThreadPool::CreateSequencedTaskRunner({base::MayBlock()});
 
+  ProfileKey* profile_key = ProfileKey::FromSimpleFactoryKey(key)->GetOriginalKey();
+
   base::FilePath store_path =
-      key->GetPath().Append(chrome::kOfflinePageMetadataDirname);
+      profile_key->GetPath().Append(chrome::kOfflinePageMetadataDirname);
   std::unique_ptr<OfflinePageMetadataStore> metadata_store(
       new OfflinePageMetadataStore(background_task_runner, store_path));
 
   base::FilePath persistent_archives_dir =
-      key->GetPath().Append(chrome::kOfflinePageArchivesDirname);
+      profile_key->GetPath().Append(chrome::kOfflinePageArchivesDirname);
   // If base::PathService::Get returns false, the temporary_archives_dir will be
   // empty, and no temporary pages will be saved during this chrome lifecycle.
   base::FilePath temporary_archives_dir;
@@ -69,7 +74,6 @@ std::unique_ptr<KeyedService> OfflinePageModelFactory::BuildServiceInstanceFor(
         temporary_archives_dir.Append(chrome::kOfflinePageArchivesDirname);
   }
 
-  ProfileKey* profile_key = ProfileKey::FromSimpleFactoryKey(key);
   auto archive_manager = std::make_unique<DownloadArchiveManager>(
       temporary_archives_dir, persistent_archives_dir,
       DownloadPrefs::GetDefaultDownloadDirectory(), background_task_runner,
@@ -87,4 +91,14 @@ std::unique_ptr<KeyedService> OfflinePageModelFactory::BuildServiceInstanceFor(
   return model;
 }
 
+SimpleFactoryKey* OfflinePageModelFactory::GetKeyToUse(
+    SimpleFactoryKey* key) const {
+  ProfileKey* profile_key = ProfileKey::FromSimpleFactoryKey(key);
+  if (profile_key->GetPrefs()->GetBoolean(prefs::kIncognitoTabHistoryEnabled) == false) {
+    return SimpleKeyedServiceFactory::GetKeyToUse(key);
+  }
+
+  return profile_key->GetOriginalKey();
+}
+
 }  // namespace offline_pages
diff --git a/chrome/browser/offline_pages/android/request_coordinator_factory.cc b/chrome/browser/offline_pages/android/request_coordinator_factory.cc
--- a/chrome/browser/offline_pages/android/request_coordinator_factory.cc
+++ b/chrome/browser/offline_pages/android/request_coordinator_factory.cc
@@ -19,6 +19,7 @@
 #include "chrome/browser/ui/android/tab_model/tab_model.h"
 #include "chrome/browser/ui/android/tab_model/tab_model_list.h"
 #include "chrome/common/chrome_constants.h"
+#include "components/keyed_service/content/browser_context_dependency_manager.h"
 #include "components/offline_pages/core/background/offliner.h"
 #include "components/offline_pages/core/background/offliner_policy.h"
 #include "components/offline_pages/core/background/request_coordinator.h"
@@ -28,6 +29,11 @@
 #include "components/offline_pages/core/offline_page_feature.h"
 #include "content/public/browser/web_contents.h"
 
+#include "chrome/browser/profiles/incognito_helpers.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "chrome/common/pref_names.h"
+
 namespace network {
 class NetworkQualityTracker;
 }
@@ -61,7 +67,8 @@ class ActiveTabInfo : public RequestCoordinator::ActiveTabInfo {
 };
 
 RequestCoordinatorFactory::RequestCoordinatorFactory()
-    : ProfileKeyedServiceFactory("OfflineRequestCoordinator") {
+    : BrowserContextKeyedServiceFactory("OfflineRequestCoordinator",
+                      BrowserContextDependencyManager::GetInstance()) {
   // Depends on OfflinePageModelFactory in SimpleDependencyManager.
 }
 
@@ -79,6 +86,12 @@ RequestCoordinator* RequestCoordinatorFactory::GetForBrowserContext(
 
 KeyedService* RequestCoordinatorFactory::BuildServiceInstanceFor(
     content::BrowserContext* context) const {
+  if (context->IsOffTheRecord() &&
+      Profile::FromBrowserContext(context)->GetOriginalProfile()
+        ->GetPrefs()->GetBoolean(prefs::kIncognitoTabHistoryEnabled) == false) {
+    // do not track history in incognito mode if preference is disabled
+    return nullptr;
+  }
   std::unique_ptr<OfflinerPolicy> policy(new OfflinerPolicy());
   std::unique_ptr<Offliner> offliner;
   OfflinePageModel* model =
@@ -111,4 +124,16 @@ KeyedService* RequestCoordinatorFactory::BuildServiceInstanceFor(
   return request_coordinator;
 }
 
+content::BrowserContext*
+RequestCoordinatorFactory::GetBrowserContextToUse(
+    content::BrowserContext* context) const {
+  if (Profile::FromBrowserContext(context)->GetOriginalProfile()
+        ->GetPrefs()->GetBoolean(prefs::kIncognitoTabHistoryEnabled) == false) {
+    return BrowserContextKeyedServiceFactory::GetBrowserContextToUse(context);
+  }
+
+  return chrome::GetBrowserContextRedirectedInIncognito(context);
+}
+
+
 }  // namespace offline_pages
diff --git a/chrome/browser/offline_pages/offline_page_model_factory.h b/chrome/browser/offline_pages/offline_page_model_factory.h
--- a/chrome/browser/offline_pages/offline_page_model_factory.h
+++ b/chrome/browser/offline_pages/offline_page_model_factory.h
@@ -48,6 +48,7 @@ class OfflinePageModelFactory : public SimpleKeyedServiceFactory {
 
   std::unique_ptr<KeyedService> BuildServiceInstanceFor(
       SimpleFactoryKey* key) const override;
+  SimpleFactoryKey* GetKeyToUse(SimpleFactoryKey* key) const override;
 };
 
 }  // namespace offline_pages
diff --git a/chrome/browser/offline_pages/recent_tab_helper.cc b/chrome/browser/offline_pages/recent_tab_helper.cc
--- a/chrome/browser/offline_pages/recent_tab_helper.cc
+++ b/chrome/browser/offline_pages/recent_tab_helper.cc
@@ -28,6 +28,11 @@
 #include "content/public/browser/navigation_entry.h"
 #include "content/public/browser/navigation_handle.h"
 
+#include "chrome/browser/profiles/profile.h"
+#include "components/prefs/pref_registry_simple.h"
+#include "components/prefs/pref_service.h"
+#include "chrome/common/pref_names.h"
+
 namespace {
 class DefaultRecentTabHelperDelegate
     : public offline_pages::RecentTabHelper::Delegate {
@@ -180,6 +185,14 @@ bool RecentTabHelper::EnsureInitialized() {
   // WebContents with its origin as well.
   snapshots_enabled_ = !tab_id_.empty() &&
                        !web_contents()->GetBrowserContext()->IsOffTheRecord();
+  if (!tab_id_.empty() && web_contents()->GetBrowserContext()->IsOffTheRecord()) {
+    if (Profile::FromBrowserContext(web_contents()->GetBrowserContext())
+          ->GetOriginalProfile()
+          ->GetPrefs()->GetBoolean(prefs::kIncognitoTabHistoryEnabled) == true) {
+      snapshots_enabled_ = true;
+      incognito_tab_history_enabled_ = true;
+    }
+  }
 
   if (snapshots_enabled_) {
     page_model_ = OfflinePageModelFactory::GetForBrowserContext(
@@ -456,7 +469,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
@@ -145,6 +145,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<SnapshotProgressInfo> 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
@@ -18,7 +18,7 @@ namespace offline_pages {
 class RequestCoordinator;
 
 // A factory to create one unique RequestCoordinator.
-class RequestCoordinatorFactory : public ProfileKeyedServiceFactory {
+class RequestCoordinatorFactory : public BrowserContextKeyedServiceFactory {
  public:
   static RequestCoordinatorFactory* GetInstance();
   static RequestCoordinator* GetForBrowserContext(
@@ -36,6 +36,8 @@ class RequestCoordinatorFactory : public ProfileKeyedServiceFactory {
 
   KeyedService* BuildServiceInstanceFor(
       content::BrowserContext* context) const override;
+  content::BrowserContext* GetBrowserContextToUse(
+      content::BrowserContext* context) const override;
 };
 
 }  // namespace offline_pages
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -229,6 +229,7 @@
 #include "components/feed/core/shared_prefs/pref_names.h"
 
 #if BUILDFLAG(IS_ANDROID)
+#include "chrome/browser/history/history_tab_helper.h"
 #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"
@@ -1390,6 +1391,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);
 #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
@@ -28,7 +28,9 @@ robolectric_library("junit") {
 
   deps = [
     ":java",
+    "//base:base_java",
     "//base:base_junit_test_support",
     "//third_party/junit",
+    "//components/embedder_support/android:util_java",
   ]
 }
diff --git a/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePage.java b/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePage.java
--- a/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePage.java
+++ b/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePage.java
@@ -16,6 +16,8 @@ import org.chromium.url.GURL;
 import java.lang.annotation.Retention;
 import java.lang.annotation.RetentionPolicy;
 
+import org.chromium.base.ContextUtils;
+
 /**
  * An interface for pages that will be using Android views instead of html/rendered Web content.
  */
@@ -130,12 +132,12 @@ public interface NativePage {
      */
     @Deprecated // Use GURL-variant instead.
     public static boolean isNativePageUrl(String url, boolean isIncognito) {
-        return nativePageType(url, null, isIncognito) != NativePageType.NONE;
+        return nativePageType(url, null, isIncognito, false) != NativePageType.NONE;
     }
 
     public static boolean isNativePageUrl(GURL url, boolean isIncognito) {
         return url != null
-                && nativePageType(url.getSpec(), null, isIncognito) != NativePageType.NONE;
+                && nativePageType(url.getSpec(), null, isIncognito, false) != NativePageType.NONE;
     }
 
     /**
@@ -146,7 +148,8 @@ public interface NativePage {
      */
     // TODO(crbug/783819) - Convert to using GURL.
     public static @NativePageType int nativePageType(
-            String url, NativePage candidatePage, boolean isIncognito) {
+            String url, NativePage candidatePage, boolean isIncognito,
+            boolean isAlwaysIncognito) {
         if (url == null) return NativePageType.NONE;
 
         Uri uri = Uri.parse(url);
@@ -168,7 +171,8 @@ public interface NativePage {
             return NativePageType.DOWNLOADS;
         } else if (UrlConstants.HISTORY_HOST.equals(host)) {
             return NativePageType.HISTORY;
-        } else if (UrlConstants.RECENT_TABS_HOST.equals(host) && !isIncognito) {
+        } else if (UrlConstants.RECENT_TABS_HOST.equals(host) &&
+                  (!isIncognito || isAlwaysIncognito)) {
             return NativePageType.RECENT_TABS;
         } else if (UrlConstants.EXPLORE_HOST.equals(host)) {
             return NativePageType.EXPLORE;
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
@@ -1151,6 +1151,37 @@ Your Google account may have other forms of browsing history like searches and a
       <message name="IDS_CLEAR_BROWSING_HISTORY_SUMMARY_SYNCED_NO_LINK" desc="A text for the basic tab explaining browsing history for users with history sync. This version is shown when the link to MyActivity is displayed separately.">
         Clears history from all synced devices.
       </message>
+      <!-- always incognito -->
+      <message name="IDS_INCOGNITO_SETTINGS_TITLE" desc="Title for incognito mode settings">
+        Incognito mode
+      </message>
+      <message name="IDS_INCOGNITO_SETTINGS_SUMMARY" desc="Summary for incognito mode settings">
+        Incognito navigation settings
+      </message>
+      <message name="IDS_ALWAYS_INCOGNITO_TITLE" desc="Title for always incognito mode">
+        Always open links in incognito
+      </message>
+      <message name="IDS_ALWAYS_INCOGNITO_SUMMARY" desc="Summary for always incognito mode">
+        Opens links in incognito tabs when you click on new tab or on a link
+      </message>
+      <message name="IDS_RELAUNCH" desc="Relaunch message">
+        Relaunch
+      </message>
+      <message name="IDS_UI_RELAUNCH_NOTICE" desc="Summary for relaunch message">
+        Your changes will take effect the next time you relaunch Bromite.
+      </message>
+      <message name="IDS_INCOGNITO_HISTORY_ENABLED_TITLE" desc="Title for enabled history in incognito mode">
+        Enable history
+      </message>
+      <message name="IDS_INCOGNITO_HISTORY_ENABLED_SUMMARY" desc="Summary for enable history in incognito mode">
+        Record history even in incognito mode
+      </message>
+      <message name="IDS_INCOGNITO_SAVE_SITE_SETTING_ENABLED_TITLE" desc="Title for save site setting flag in incognito mode">
+        Remember site settings
+      </message>
+      <message name="IDS_INCOGNITO_SAVE_SITE_SETTING_ENABLED_SUMMARY" desc="Summary for save site setting flag in incognito mode">
+        Remember site settings changes in incognito mode
+      </message>
       <message name="IDS_CLEAR_SEARCH_HISTORY_LINK" desc="Text informing the user that they can clear search history and other data using MyActivity.">
         <ph name="BEGIN_LINK1">&lt;link1&gt;</ph>Search history<ph name="END_LINK1">&lt;/link1&gt;</ph> and <ph name="BEGIN_LINK2">&lt;link2&gt;</ph>other forms of activity<ph name="END_LINK2">&lt;/link2&gt;</ph> may be saved in your Google Account when you’re signed in. You can delete them anytime.
       </message>
diff --git a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java
--- a/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java
+++ b/chrome/browser/ui/android/toolbar/java/src/org/chromium/chrome/browser/toolbar/LocationBarModel.java
@@ -178,6 +178,7 @@ public class LocationBarModel implements ToolbarDataProvider, LocationBarDataPro
     protected GURL mVisibleGurl = GURL.emptyGURL();
     protected String mFormattedFullUrl;
     protected String mUrlForDisplay;
+    private boolean mIsAlwaysIncognito;
 
     /**
      * Default constructor for this class.
@@ -192,7 +193,8 @@ public class LocationBarModel implements ToolbarDataProvider, LocationBarDataPro
     public LocationBarModel(Context context, NewTabPageDelegate newTabPageDelegate,
             @NonNull UrlFormatter urlFormatter, @NonNull ProfileProvider profileProvider,
             @NonNull OfflineStatus offlineStatus,
-            @NonNull SearchEngineLogoUtils searchEngineLogoUtils) {
+            @NonNull SearchEngineLogoUtils searchEngineLogoUtils,
+            boolean isAlwaysIncognito) {
         mContext = context;
         mNtpDelegate = newTabPageDelegate;
         mUrlFormatter = urlFormatter;
@@ -200,6 +202,7 @@ public class LocationBarModel implements ToolbarDataProvider, LocationBarDataPro
         mOfflineStatus = offlineStatus;
         mPrimaryColor = ChromeColors.getDefaultThemeColor(context, false);
         mSearchEngineLogoUtils = searchEngineLogoUtils;
+        mIsAlwaysIncognito = isAlwaysIncognito;
     }
 
     /**
@@ -207,7 +210,7 @@ public class LocationBarModel implements ToolbarDataProvider, LocationBarDataPro
      */
     public void initializeWithNative() {
         mOptimizationsEnabled =
-                ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_SCROLL_OPTIMIZATIONS);
+                ChromeFeatureList.isEnabled(ChromeFeatureList.ANDROID_SCROLL_OPTIMIZATIONS) && !mIsAlwaysIncognito;
         mLastUsedNonOTRProfile = Profile.getLastUsedRegularProfile();
         mNativeLocationBarModelAndroid = LocationBarModelJni.get().init(LocationBarModel.this);
 
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
+++ b/chrome/browser/ui/messages/android/BUILD.gn
@@ -24,6 +24,7 @@ android_resources("java_resources") {
 android_library("java") {
   sources = [
     "java/src/org/chromium/chrome/browser/ui/messages/infobar/SimpleConfirmInfoBarBuilder.java",
+    "java/src/org/chromium/chrome/browser/ui/messages/snackbar/INeedSnackbarManager.java",
     "java/src/org/chromium/chrome/browser/ui/messages/snackbar/Snackbar.java",
     "java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarCollection.java",
     "java/src/org/chromium/chrome/browser/ui/messages/snackbar/SnackbarManager.java",
diff --git a/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/INeedSnackbarManager.java b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/INeedSnackbarManager.java
new file mode 100644
--- /dev/null
+++ b/chrome/browser/ui/messages/android/java/src/org/chromium/chrome/browser/ui/messages/snackbar/INeedSnackbarManager.java
@@ -0,0 +1,27 @@
+/*
+    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 <https://www.gnu.org/licenses/>.
+*/
+
+package org.chromium.chrome.browser.ui.messages.snackbar;
+
+import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
+
+/**
+ * An interface that allows using snackbars in the settings
+ */
+public interface INeedSnackbarManager {
+    void setSnackbarManager(SnackbarManager manager);
+}
diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc
--- a/chrome/common/pref_names.cc
+++ b/chrome/common/pref_names.cc
@@ -3458,6 +3458,12 @@ const char kShowCaretBrowsingDialog[] =
 const char kLacrosLaunchSwitch[] = "lacros_launch_switch";
 #endif
 
+#if BUILDFLAG(IS_ANDROID)
+const char kAlwaysIncognitoEnabled[] = "always_incognito_enabled";
+const char kIncognitoTabHistoryEnabled[] = "incognito_tab_history_enabled";
+const char kIncognitoSaveSiteSettingEnabled[] = "incognito_site_setting_enabled";
+#endif
+
 #if BUILDFLAG(IS_CHROMEOS_ASH)
 // String enum pref determining what should happen when a user who authenticates
 // via a security token is removing this token. "IGNORE" - nothing happens
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
@@ -1219,6 +1219,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)
@@ -1256,6 +1258,10 @@ extern const char kPrivacyGuideViewed[];
 
 extern const char kCorsNonWildcardRequestHeadersSupport[];
 
+#if BUILDFLAG(IS_ANDROID)
+extern const char kIncognitoTabHistoryEnabled[];
+#endif
+
 extern const char kOriginAgentClusterDefaultEnabled[];
 
 extern const char kForceMajorVersionToMinorPositionInUserAgent[];
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
@@ -122,10 +122,12 @@ void PrefProvider::RegisterProfilePrefs(
 
 PrefProvider::PrefProvider(PrefService* prefs,
                            bool off_the_record,
+                           bool force_save_site_settings,
                            bool store_last_modified,
                            bool restore_session)
     : prefs_(prefs),
       off_the_record_(off_the_record),
+      force_save_site_settings_(force_save_site_settings),
       store_last_modified_(store_last_modified),
       clock_(base::DefaultClock::GetInstance()) {
   TRACE_EVENT_BEGIN("startup", "PrefProvider::PrefProvider");
@@ -159,7 +161,9 @@ PrefProvider::PrefProvider(PrefService* prefs,
       content_settings_prefs_.insert(std::make_pair(
           info->type(), std::make_unique<ContentSettingsPref>(
                             info->type(), prefs_, &pref_change_registrar_,
-                            info->pref_name(), off_the_record_, restore_session,
+                            info->pref_name(),
+                            off_the_record_ || (!content_type_info && force_save_site_settings_),
+                            restore_session,
                             base::BindRepeating(&PrefProvider::Notify,
                                                 base::Unretained(this)))));
     }
diff --git a/components/content_settings/core/browser/content_settings_pref_provider.h b/components/content_settings/core/browser/content_settings_pref_provider.h
--- a/components/content_settings/core/browser/content_settings_pref_provider.h
+++ b/components/content_settings/core/browser/content_settings_pref_provider.h
@@ -37,6 +37,7 @@ class PrefProvider : public UserModifiableProvider {
 
   PrefProvider(PrefService* prefs,
                bool off_the_record,
+               bool force_save_site_settings,
                bool store_last_modified,
                bool restore_session);
 
@@ -88,6 +89,7 @@ class PrefProvider : public UserModifiableProvider {
   raw_ptr<PrefService> prefs_;
 
   const bool off_the_record_;
+  const bool force_save_site_settings_;
 
   bool store_last_modified_;
 
diff --git a/components/content_settings/core/browser/host_content_settings_map.cc b/components/content_settings/core/browser/host_content_settings_map.cc
--- a/components/content_settings/core/browser/host_content_settings_map.cc
+++ b/components/content_settings/core/browser/host_content_settings_map.cc
@@ -243,6 +243,7 @@ const char* ContentSettingToString(ContentSetting setting) {
 HostContentSettingsMap::HostContentSettingsMap(
     PrefService* prefs,
     bool is_off_the_record,
+    bool force_save_site_settings,
     bool store_last_modified,
     bool restore_session)
     : RefcountedKeyedService(base::ThreadTaskRunnerHandle::Get()),
@@ -251,6 +252,7 @@ HostContentSettingsMap::HostContentSettingsMap(
 #endif
       prefs_(prefs),
       is_off_the_record_(is_off_the_record),
+      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");
@@ -262,7 +264,7 @@ HostContentSettingsMap::HostContentSettingsMap(
   policy_provider->AddObserver(this);
 
   auto pref_provider_ptr = std::make_unique<content_settings::PrefProvider>(
-      prefs_, is_off_the_record_, 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_);
diff --git a/components/content_settings/core/browser/host_content_settings_map.h b/components/content_settings/core/browser/host_content_settings_map.h
--- a/components/content_settings/core/browser/host_content_settings_map.h
+++ b/components/content_settings/core/browser/host_content_settings_map.h
@@ -81,6 +81,7 @@ class HostContentSettingsMap : public content_settings::Observer,
   // profile or a guest session.
   HostContentSettingsMap(PrefService* prefs,
                          bool is_off_the_record,
+                         bool force_save_site_settings,
                          bool store_last_modified,
                          bool restore_session);
 
@@ -442,6 +443,8 @@ class HostContentSettingsMap : public content_settings::Observer,
   // Whether this settings map is for an incognito or guest session.
   bool is_off_the_record_;
 
+  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
@@ -52,6 +52,9 @@ BASE_FEATURE(kOfflinePagesNetworkStateLikelyUnknown,
              "OfflinePagesNetworkStateLikelyUnknown",
              base::FEATURE_DISABLED_BY_DEFAULT);
 
+const base::Feature kOfflinePagesAutoSaveFeature{
+    "OfflinePagesAutoSaveEnabled", base::FEATURE_DISABLED_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 @@ BASE_DECLARE_FEATURE(kOfflinePagesDescriptiveFailStatusFeature);
 BASE_DECLARE_FEATURE(kOfflineIndicatorFeature);
 BASE_DECLARE_FEATURE(kOnTheFlyMhtmlHashComputationFeature);
 BASE_DECLARE_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
@@ -29,3 +29,7 @@ base::WeakPtr<AutocompleteProviderClient>
 AutocompleteProviderClient::GetWeakPtr() {
   return nullptr;
 }
+
+bool AutocompleteProviderClient::IsAlwaysIncognitoEnabled() const {
+  return false;
+}
diff --git a/components/omnibox/browser/autocomplete_provider_client.h b/components/omnibox/browser/autocomplete_provider_client.h
--- a/components/omnibox/browser/autocomplete_provider_client.h
+++ b/components/omnibox/browser/autocomplete_provider_client.h
@@ -128,6 +128,7 @@ class AutocompleteProviderClient : public OmniboxAction::Client {
   virtual signin::IdentityManager* GetIdentityManager() const = 0;
 
   virtual bool IsOffTheRecord() const = 0;
+  virtual bool IsAlwaysIncognitoEnabled() const = 0;
   virtual bool SearchSuggestEnabled() const = 0;
 
   // True for almost all users except ones with a specific enterprise policy.
diff --git a/components/omnibox/browser/base_search_provider.cc b/components/omnibox/browser/base_search_provider.cc
--- a/components/omnibox/browser/base_search_provider.cc
+++ b/components/omnibox/browser/base_search_provider.cc
@@ -273,7 +273,7 @@ bool BaseSearchProvider::CanSendZeroSuggestRequest(
   }
 
   // Don't make a suggest request if in incognito mode.
-  if (client->IsOffTheRecord()) {
+  if (client->IsOffTheRecord() && client->IsAlwaysIncognitoEnabled() == false) {
     return false;
   }
 
diff --git a/components/omnibox/browser/search_provider.cc b/components/omnibox/browser/search_provider.cc
--- a/components/omnibox/browser/search_provider.cc
+++ b/components/omnibox/browser/search_provider.cc
@@ -832,7 +832,9 @@ bool SearchProvider::IsQuerySuitableForSuggest(bool* query_is_private) const {
   // keyword input to a keyword suggest server, if any.)
   const TemplateURL* default_url = providers_.GetDefaultProviderURL();
   const TemplateURL* keyword_url = providers_.GetKeywordProviderURL();
-  return !client()->IsOffTheRecord() && client()->SearchSuggestEnabled() &&
+  return (client()->IsOffTheRecord() == false ||
+                client()->IsAlwaysIncognitoEnabled() == true) &&
+         client()->SearchSuggestEnabled() &&
          ((default_url && !default_url->suggestions_url().empty() &&
            !*query_is_private) ||
           (keyword_url && !keyword_url->suggestions_url().empty()));
diff --git a/weblayer/browser/host_content_settings_map_factory.cc b/weblayer/browser/host_content_settings_map_factory.cc
--- a/weblayer/browser/host_content_settings_map_factory.cc
+++ b/weblayer/browser/host_content_settings_map_factory.cc
@@ -45,6 +45,7 @@ HostContentSettingsMapFactory::BuildServiceInstanceFor(
   scoped_refptr<HostContentSettingsMap> settings_map =
       base::MakeRefCounted<HostContentSettingsMap>(
           user_prefs::UserPrefs::Get(context), context->IsOffTheRecord(),
+          /*force_save_site_settings*/false,
           /*store_last_modified=*/true,
           /*restore_session=*/false);
 
--
2.25.1
