Files
cromite/build/patches/Add-history-support-in-incognito-mode.patch
2021-10-20 23:58:39 +02:00

1729 lines
78 KiB
Diff

From: uazo <uazo@users.noreply.github.com>
Date: Fri, 7 Aug 2020 16:33:47 +0000
Subject: Add history support in incognito mode
Add history, recents, offlinepages and send to home screen 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.
See also: https://github.com/bromite/bromite/pull/1427
---
.../chrome_junit_test_java_sources.gni | 4 +
chrome/android/chrome_test_java_sources.gni | 6 +
.../java/res/xml/privacy_preferences.xml | 5 +
.../AppMenuPropertiesDelegateImpl.java | 29 +-
.../CustomTabAppMenuPropertiesDelegate.java | 3 +
.../browser/download/DownloadUtils.java | 16 +-
.../browser/history/HistoryManager.java | 17 +-
.../chrome/browser/history/HistoryPage.java | 14 +
.../chrome/browser/ntp/RecentTabsManager.java | 8 +-
.../privacy/settings/PrivacySettings.java | 18 +
.../browser/tab/HistoricalTabSaver.java | 12 +-
.../browser/tabmodel/TabPersistentStore.java | 5 +-
.../history/Bromite_HistoryManagerTest.java | 112 ++++++
...FragmentTest_HistoryInAlwaysIncognito.java | 120 +++++++
...ite_AppMenuPropertiesDelegateUnitTest.java | 323 ++++++++++++++++++
.../tab/HistoricalTabSaverUnitTest.java | 16 +-
.../browser/android/historical_tab_saver.cc | 28 +-
chrome/browser/android/historical_tab_saver.h | 27 ++
.../android/historical_tab_saver_unittest.cc | 148 ++++++++
chrome/browser/history/history_tab_helper.cc | 16 +
chrome/browser/history/history_tab_helper.h | 10 +-
.../history/history_tab_helper_unittest.cc | 22 ++
.../android/offline_page_bridge.cc | 13 +-
.../android/offline_page_model_factory.cc | 21 +-
.../android/request_coordinator_factory.cc | 17 +
.../offline_page_model_factory.h | 2 +
.../offline_pages/recent_tab_helper.cc | 12 +
.../request_coordinator_factory.h | 3 +
chrome/browser/prefs/browser_prefs.cc | 3 +
.../browser/ui/android/native_page/BUILD.gn | 2 +
.../browser/ui/native_page/NativePage.java | 6 +-
.../ui/native_page/NativePageTest.java | 26 ++
.../strings/android_chrome_strings.grd | 6 +
chrome/common/pref_names.cc | 5 +
chrome/common/pref_names.h | 4 +
chrome/test/BUILD.gn | 5 +
36 files changed, 1046 insertions(+), 38 deletions(-)
create mode 100644 chrome/android/javatests/src/org/chromium/chrome/browser/history/Bromite_HistoryManagerTest.java
create mode 100644 chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/Bromite_PrivacySettingsFragmentTest_HistoryInAlwaysIncognito.java
create mode 100644 chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/Bromite_AppMenuPropertiesDelegateUnitTest.java
create mode 100644 chrome/browser/android/historical_tab_saver.h
create mode 100644 chrome/browser/android/historical_tab_saver_unittest.cc
diff --git a/chrome/android/chrome_junit_test_java_sources.gni b/chrome/android/chrome_junit_test_java_sources.gni
--- a/chrome/android/chrome_junit_test_java_sources.gni
+++ b/chrome/android/chrome_junit_test_java_sources.gni
@@ -225,3 +225,7 @@ chrome_junit_test_java_sources = [
"junit/src/org/chromium/chrome/browser/webapps/WebappLauncherActivityTest.java",
"junit/src/org/chromium/chrome/browser/webapps/WebappRegistryTest.java",
]
+
+chrome_junit_test_java_sources += [
+ "junit/src/org/chromium/chrome/browser/app/appmenu/Bromite_AppMenuPropertiesDelegateUnitTest.java",
+]
\ No newline at end of file
diff --git a/chrome/android/chrome_test_java_sources.gni b/chrome/android/chrome_test_java_sources.gni
--- a/chrome/android/chrome_test_java_sources.gni
+++ b/chrome/android/chrome_test_java_sources.gni
@@ -645,3 +645,9 @@ chrome_test_java_sources = [
if (enable_feed_v2) {
chrome_test_java_sources += [ "javatests/src/org/chromium/chrome/browser/ntp/NewTabPageColorWithFeedV2Test.java" ]
}
+
+# Bromite tests
+chrome_test_java_sources += [
+ "javatests/src/org/chromium/chrome/browser/privacy/settings/Bromite_PrivacySettingsFragmentTest_HistoryInAlwaysIncognito.java",
+ "javatests/src/org/chromium/chrome/browser/history/Bromite_HistoryManagerTest.java",
+]
diff --git a/chrome/android/java/res/xml/privacy_preferences.xml b/chrome/android/java/res/xml/privacy_preferences.xml
--- a/chrome/android/java/res/xml/privacy_preferences.xml
+++ b/chrome/android/java/res/xml/privacy_preferences.xml
@@ -42,6 +42,11 @@
android:title="@string/close_tabs_on_exit_title"
android:summary="@string/close_tabs_on_exit_summary"
android:defaultValue="false" />
+ <org.chromium.components.browser_ui.settings.ChromeSwitchPreference
+ android:key="incognito_history_enabled"
+ android:title="@string/incognito_history_enabled_title"
+ android:summary="@string/incognito_history_enabled_summary"
+ android:defaultValue="false" />
<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/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
@@ -75,6 +75,10 @@ import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
+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.
@@ -133,6 +137,13 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate
protected BookmarkBridge mBookmarkBridge;
protected Runnable mAppMenuInvalidator;
+ private PrefService sPrefServiceForTest;
+
+ @VisibleForTesting
+ public void setPrefForTest(PrefService prefService) {
+ sPrefServiceForTest = prefService;
+ }
+
/**
* Construct a new {@link AppMenuPropertiesDelegateImpl}.
* @param context The activity context.
@@ -379,7 +390,8 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate
}
private void prepareCommonMenuItems(Menu menu, @MenuGroup int menuGroup, boolean isIncognito) {
- if (ContextUtils.getAppSharedPreferences().getBoolean("always_incognito", false)) {
+ boolean always_incognito = ContextUtils.getAppSharedPreferences().getBoolean("always_incognito", false);
+ if (always_incognito) {
final MenuItem newTabOption = menu.findItem(R.id.new_tab_menu_id);
if (newTabOption != null)
newTabOption.setVisible(false);
@@ -444,7 +456,15 @@ public class AppMenuPropertiesDelegateImpl implements AppMenuPropertiesDelegate
}
if (item.getItemId() == R.id.recent_tabs_menu_id) {
- item.setVisible(!isIncognito);
+ if (always_incognito) {
+ PrefService prefService = sPrefServiceForTest != null ? sPrefServiceForTest :
+ 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);
@@ -632,7 +652,10 @@ 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 ||
+ ContextUtils.getAppSharedPreferences().getBoolean(
+ "always_incognito", false));
}
/**
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
@@ -169,6 +169,9 @@ public class CustomTabAppMenuPropertiesDelegate extends AppMenuPropertiesDelegat
downloadItemVisible = false;
openInChromeItemVisible = false;
}
+ if (ContextUtils.getAppSharedPreferences().getBoolean("always_incognito", false)) {
+ 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/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
@@ -66,6 +66,10 @@ import org.chromium.ui.widget.Toast;
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.
*/
@@ -306,7 +310,17 @@ 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 =
+ ContextUtils.getAppSharedPreferences().getBoolean("always_incognito", false);
+ 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
@@ -42,6 +42,12 @@ import org.chromium.ui.base.Clipboard;
import java.util.List;
+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.
*/
@@ -217,7 +223,16 @@ public class HistoryManager implements OnMenuItemClickListener, SelectionObserve
: mSelectableListLayout;
}
- private boolean shouldShowIncognitoPlaceholder() {
+ public boolean isIncognito() { return mIsIncognito; }
+
+ public boolean shouldShowIncognitoPlaceholder() {
+ if (mIsIncognito &&
+ ContextUtils.getAppSharedPreferences().getBoolean("always_incognito", false)) {
+ 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
@@ -17,6 +17,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.
*/
@@ -40,6 +46,14 @@ public class HistoryPage extends BasicNativePage {
boolean isIncognito, TabCreatorManager tabCreatorManager, Supplier<Tab> tabSupplier) {
super(host);
+ if (isIncognito &&
+ ContextUtils.getAppSharedPreferences().getBoolean("always_incognito", false)) {
+ PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile());
+ boolean historyEnabledInIncognito =
+ prefService.getBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED);
+ if (historyEnabledInIncognito == true) isIncognito = false;
+ }
+
mHistoryManager = new HistoryManager(
activity, false, snackbarManager, isIncognito, tabCreatorManager, tabSupplier);
mTitle = host.getContext().getResources().getString(R.string.menu_history);
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
@@ -86,15 +86,15 @@ public class RecentTabsManager implements SignInStateObserver,
*/
public RecentTabsManager(
Tab tab, Profile profile, Context context, Runnable showHistoryManager) {
- mProfile = profile;
+ mProfile = profile.getOriginalProfile();
mTab = tab;
mShowHistoryManager = showHistoryManager;
- mForeignSessionHelper = new ForeignSessionHelper(profile);
- mPrefs = new RecentTabsPagePrefs(profile);
+ mForeignSessionHelper = new ForeignSessionHelper(mProfile);
+ mPrefs = new RecentTabsPagePrefs(mProfile);
mFaviconHelper = new FaviconHelper();
mRecentlyClosedTabManager = sRecentlyClosedTabManagerForTests != null
? sRecentlyClosedTabManagerForTests
- : new RecentlyClosedBridge(profile);
+ : new RecentlyClosedBridge(mProfile);
mRecentlyClosedTabManager.setTabsUpdatedRunnable(() -> {
updateRecentlyClosedTabs();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java b/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/privacy/settings/PrivacySettings.java
@@ -18,6 +18,7 @@ import androidx.vectordrawable.graphics.drawable.VectorDrawableCompat;
import org.chromium.base.ContextUtils;
import org.chromium.base.BuildInfo;
+import org.chromium.base.Log;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.feedback.HelpAndFeedbackLauncherImpl;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
@@ -137,6 +138,11 @@ public class PrivacySettings
Preference secureDnsPref = findPreference(PREF_SECURE_DNS);
secureDnsPref.setVisible(SecureDnsSettings.isUiEnabled());
+ ChromeSwitchPreference historyInIncognitoPref =
+ (ChromeSwitchPreference) findPreference(PREF_INCOGNITO_TAB_HISTORY_ENABLED);
+ historyInIncognitoPref.setOnPreferenceChangeListener(this);
+ historyInIncognitoPref.setManagedPreferenceDelegate(mManagedPreferenceDelegate);
+
updateSummaries();
}
@@ -159,11 +165,16 @@ public class PrivacySettings
} else if (PREF_HTTPS_FIRST_MODE.equals(key)) {
UserPrefs.get(Profile.getLastUsedRegularProfile())
.setBoolean(Pref.HTTPS_ONLY_MODE_ENABLED, (boolean) newValue);
+ } else if (PREF_INCOGNITO_TAB_HISTORY_ENABLED.equals(key)) {
+ UserPrefs.get(Profile.getLastUsedRegularProfile())
+ .setBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED, (boolean) newValue);
}
return true;
}
+ public static final String PREF_INCOGNITO_TAB_HISTORY_ENABLED = "incognito_history_enabled";
+
@Override
public void onResume() {
super.onResume();
@@ -204,6 +215,13 @@ public class PrivacySettings
(ChromeSwitchPreference) findPreference(PREF_CLOSE_TABS_ON_EXIT);
closeTabsOnExitPref.setOnPreferenceChangeListener(this);
closeTabsOnExitPref.setManagedPreferenceDelegate(mManagedPreferenceDelegate);
+
+ ChromeSwitchPreference historyInIncognitoPref =
+ (ChromeSwitchPreference) findPreference(PREF_INCOGNITO_TAB_HISTORY_ENABLED);
+ if (historyInIncognitoPref != null) {
+ historyInIncognitoPref.setChecked(
+ prefService.getBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED));
+ }
}
private ChromeManagedPreferenceDelegate createManagedPreferenceDelegate() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tab/HistoricalTabSaver.java b/chrome/android/java/src/org/chromium/chrome/browser/tab/HistoricalTabSaver.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/tab/HistoricalTabSaver.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tab/HistoricalTabSaver.java
@@ -15,28 +15,28 @@ public class HistoricalTabSaver {
/**
* Creates a historical tab from a tab being closed.
*/
- public static void createHistoricalTab(Tab tab) {
+ public static void createHistoricalTab(Tab tab, boolean is_always_incognito) {
if (tab.isFrozen()) {
WebContentsState state = CriticalPersistedTabData.from(tab).getWebContentsState();
if (state != null) {
WebContents webContents =
WebContentsStateBridge.restoreContentsFromByteBuffer(state, true);
if (webContents != null) {
- createHistoricalTabFromContents(webContents);
+ createHistoricalTabFromContents(webContents, is_always_incognito);
webContents.destroy();
}
}
} else {
- createHistoricalTabFromContents(tab.getWebContents());
+ createHistoricalTabFromContents(tab.getWebContents(), is_always_incognito);
}
}
- private static void createHistoricalTabFromContents(WebContents webContents) {
- HistoricalTabSaverJni.get().createHistoricalTabFromContents(webContents);
+ private static void createHistoricalTabFromContents(WebContents webContents, boolean is_always_incognito) {
+ HistoricalTabSaverJni.get().createHistoricalTabFromContents(webContents, is_always_incognito);
}
@NativeMethods
interface Natives {
- void createHistoricalTabFromContents(WebContents webContents);
+ void createHistoricalTabFromContents(WebContents webContents, boolean is_always_incognito);
}
}
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
@@ -153,7 +153,10 @@ public class TabPersistentStore {
@Override
public void didCloseTab(Tab tab) {
PersistedTabData.onTabClose(tab);
- if (!tab.isIncognito()) HistoricalTabSaver.createHistoricalTab(tab);
+ boolean is_always_incognito =
+ ContextUtils.getAppSharedPreferences().getBoolean(AlwaysIncognitoLinkInterceptor.PREF_ALWAYS_INCOGNITO, false);
+ if (!tab.isIncognito() || is_always_incognito)
+ HistoricalTabSaver.createHistoricalTab(tab, is_always_incognito);
removeTabFromQueues(tab);
}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/history/Bromite_HistoryManagerTest.java b/chrome/android/javatests/src/org/chromium/chrome/browser/history/Bromite_HistoryManagerTest.java
new file mode 100644
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/history/Bromite_HistoryManagerTest.java
@@ -0,0 +1,112 @@
+/*
+ This file is part of Bromite.
+
+ Bromite is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Bromite is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Bromite. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+package org.chromium.chrome.browser.history;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+
+import androidx.test.espresso.intent.rule.IntentsTestRule;
+import androidx.test.filters.SmallTest;
+
+import org.hamcrest.Matcher;
+import org.junit.Assert;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.chromium.base.test.util.Restriction;
+
+import org.chromium.chrome.browser.IntentHandler;
+import org.chromium.chrome.browser.incognito.IncognitoUtils;
+import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.base.ContextUtils;
+import org.chromium.components.prefs.PrefService;
+import org.chromium.components.user_prefs.UserPrefs;
+import org.chromium.chrome.browser.preferences.Pref;
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
+import android.content.SharedPreferences;
+
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.base.test.BaseActivityTestRule;
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.ui.test.util.UiRestriction;
+import org.chromium.content_public.browser.test.util.TestThreadUtils;
+
+/**
+ * Tests the {@link HistoryManager}.
+ */
+@RunWith(ChromeJUnit4ClassRunner.class)
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+@Restriction(UiRestriction.RESTRICTION_TYPE_PHONE)
+public class Bromite_HistoryManagerTest {
+ @Rule
+ public BaseActivityTestRule<HistoryActivity> mIncognitoActivityTestRule =
+ new BaseActivityTestRule<>(HistoryActivity.class);
+
+ @Before
+ public void setUp() {
+ }
+
+ @After
+ public void tearDown() {
+ TestThreadUtils.runOnUiThreadBlocking(() -> {
+ PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile());
+ prefService.clearPref(Pref.INCOGNITO_TAB_HISTORY_ENABLED);
+
+ SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putBoolean(AlwaysIncognitoLinkInterceptor.PREF_ALWAYS_INCOGNITO, false);
+ editor.apply();
+ });
+ }
+
+ boolean mShouldShowIncognitoPlaceholder = true;
+
+ @Test
+ @SmallTest
+ public void testShouldShowIncognitoPlaceholder_AlwaysIncognito() throws Exception {
+ // launch HistoryActivity in incognito mode
+ Intent intent = new Intent(ContextUtils.getApplicationContext(), HistoryActivity.class);
+ intent.putExtra(IntentHandler.EXTRA_INCOGNITO_MODE, true);
+
+ mIncognitoActivityTestRule.launchActivity(intent);
+ HistoryActivity activity = mIncognitoActivityTestRule.getActivity();
+ HistoryManager historyManager = activity.getHistoryManagerForTests();
+ Assert.assertTrue(historyManager.isIncognito());
+
+ TestThreadUtils.runOnUiThreadBlocking(() -> {
+ // set always incognito on
+ SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putBoolean(AlwaysIncognitoLinkInterceptor.PREF_ALWAYS_INCOGNITO, true);
+ editor.apply();
+
+ // set INCOGNITO_TAB_HISTORY_ENABLED on
+ PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile());
+ prefService.setBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED, true);
+
+ mShouldShowIncognitoPlaceholder = historyManager.shouldShowIncognitoPlaceholder();
+ });
+
+ // shouldShowIncognitoPlaceholder must be false
+ Assert.assertFalse(mShouldShowIncognitoPlaceholder);
+ }
+}
diff --git a/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/Bromite_PrivacySettingsFragmentTest_HistoryInAlwaysIncognito.java b/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/Bromite_PrivacySettingsFragmentTest_HistoryInAlwaysIncognito.java
new file mode 100644
--- /dev/null
+++ b/chrome/android/javatests/src/org/chromium/chrome/browser/privacy/settings/Bromite_PrivacySettingsFragmentTest_HistoryInAlwaysIncognito.java
@@ -0,0 +1,120 @@
+/*
+ This file is part of Bromite.
+
+ Bromite is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Bromite is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Bromite. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+package org.chromium.chrome.browser.privacy.settings;
+
+import android.view.View;
+
+import androidx.recyclerview.widget.RecyclerView;
+import androidx.test.filters.LargeTest;
+
+import org.junit.Assert;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+import org.junit.runner.RunWith;
+
+import org.chromium.base.test.util.CommandLineFlags;
+import org.chromium.base.test.util.CriteriaHelper;
+import org.chromium.base.test.util.Feature;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.flags.ChromeSwitches;
+import org.chromium.chrome.browser.settings.SettingsActivityTestRule;
+import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
+import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
+import org.chromium.chrome.test.util.ChromeRenderTestRule;
+import org.chromium.content_public.browser.test.util.TestThreadUtils;
+
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.preferences.Pref;
+import org.chromium.components.prefs.PrefService;
+import org.chromium.components.user_prefs.UserPrefs;
+import org.chromium.components.browser_ui.settings.ChromeSwitchPreference;
+
+/**
+ * Tests for {@link PrivacySettings}.
+ */
+@RunWith(ChromeJUnit4ClassRunner.class)
+@CommandLineFlags.Add({ChromeSwitches.DISABLE_FIRST_RUN_EXPERIENCE})
+public class Bromite_PrivacySettingsFragmentTest_HistoryInAlwaysIncognito {
+ public final ChromeTabbedActivityTestRule mActivityTestRule =
+ new ChromeTabbedActivityTestRule();
+ public final SettingsActivityTestRule<PrivacySettings> mSettingsActivityTestRule =
+ new SettingsActivityTestRule<>(PrivacySettings.class);
+
+ // SettingsActivity has to be finished before the outer CTA can be finished or trying to finish
+ // CTA won't work.
+ @Rule
+ public final RuleChain mRuleChain =
+ RuleChain.outerRule(mActivityTestRule).around(mSettingsActivityTestRule);
+
+ @Before
+ public void setUp() {
+ mActivityTestRule.startMainActivityOnBlankPage();
+ }
+
+ @After
+ public void tearDown() {
+ TestThreadUtils.runOnUiThreadBlocking(() -> {
+ PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile());
+ prefService.clearPref(Pref.INCOGNITO_TAB_HISTORY_ENABLED);
+ });
+ }
+
+ private void waitForOptionsMenu() {
+ CriteriaHelper.pollUiThread(() -> {
+ return mSettingsActivityTestRule.getActivity().findViewById(R.id.menu_id_targeted_help)
+ != null;
+ });
+ }
+
+ @Test
+ @LargeTest
+ public void testIncognitoHistoryPreference() {
+ mSettingsActivityTestRule.startSettingsActivity();
+ waitForOptionsMenu();
+ PrivacySettings fragment = mSettingsActivityTestRule.getFragment();
+ TestThreadUtils.runOnUiThreadBlocking(() -> {
+ RecyclerView recyclerView = fragment.getView().findViewById(R.id.recycler_view);
+ recyclerView.scrollToPosition(recyclerView.getAdapter().getItemCount() - 1);
+ });
+
+ ChromeSwitchPreference historyInIncognitoPref =
+ (ChromeSwitchPreference) fragment.findPreference(PrivacySettings.PREF_INCOGNITO_TAB_HISTORY_ENABLED);
+ Assert.assertNotNull(historyInIncognitoPref);
+
+ // Test when ON
+ TestThreadUtils.runOnUiThreadBlocking(() -> {
+ fragment.onPreferenceChange(historyInIncognitoPref, true);
+
+ PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile());
+ boolean incognito_tab_history_enabled = prefService.getBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED);
+ Assert.assertTrue(incognito_tab_history_enabled);
+ });
+
+ // Test when OFF
+ TestThreadUtils.runOnUiThreadBlocking(() -> {
+ fragment.onPreferenceChange(historyInIncognitoPref, false);
+
+ PrefService prefService = UserPrefs.get(Profile.getLastUsedRegularProfile());
+ boolean incognito_tab_history_enabled = prefService.getBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED);
+ Assert.assertFalse(incognito_tab_history_enabled);
+ });
+ }
+}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/Bromite_AppMenuPropertiesDelegateUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/Bromite_AppMenuPropertiesDelegateUnitTest.java
new file mode 100644
--- /dev/null
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/app/appmenu/Bromite_AppMenuPropertiesDelegateUnitTest.java
@@ -0,0 +1,323 @@
+/*
+ This file is part of Bromite.
+
+ Bromite is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Bromite is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Bromite. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+package org.chromium.chrome.browser.app.appmenu;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.SubMenu;
+import android.view.View;
+import android.widget.PopupMenu;
+
+import org.hamcrest.Matchers;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TestRule;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.FeatureList;
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.supplier.ObservableSupplierImpl;
+import org.chromium.base.supplier.OneshotSupplierImpl;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.base.test.util.JniMocker;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ActivityTabProvider;
+import org.chromium.chrome.browser.app.appmenu.AppMenuPropertiesDelegateImpl.MenuGroup;
+import org.chromium.chrome.browser.bookmarks.BookmarkBridge;
+import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior;
+import org.chromium.chrome.browser.device.DeviceConditions;
+import org.chromium.chrome.browser.device.ShadowDeviceConditions;
+import org.chromium.chrome.browser.multiwindow.MultiWindowModeStateDispatcher;
+import org.chromium.chrome.browser.omaha.UpdateMenuItemHelper;
+import org.chromium.chrome.browser.preferences.Pref;
+import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.tab.Tab;
+import org.chromium.chrome.browser.tabmodel.TabModel;
+import org.chromium.chrome.browser.tabmodel.TabModelFilter;
+import org.chromium.chrome.browser.tabmodel.TabModelFilterProvider;
+import org.chromium.chrome.browser.tabmodel.TabModelSelector;
+import org.chromium.chrome.browser.toolbar.ToolbarManager;
+import org.chromium.chrome.browser.toolbar.menu_button.MenuUiState;
+import org.chromium.chrome.browser.util.ChromeAccessibilityUtil;
+import org.chromium.chrome.test.util.browser.Features;
+import org.chromium.components.prefs.PrefService;
+import org.chromium.components.user_prefs.UserPrefs;
+import org.chromium.components.user_prefs.UserPrefsJni;
+import org.chromium.components.webapps.AppBannerManager;
+import org.chromium.content.browser.ContentFeatureListImpl;
+import org.chromium.content.browser.ContentFeatureListImplJni;
+import org.chromium.content_public.browser.ContentFeatureList;
+import org.chromium.content_public.browser.NavigationController;
+import org.chromium.content_public.browser.WebContents;
+import org.chromium.net.ConnectionType;
+import org.chromium.url.JUnitTestGURLs;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.chromium.chrome.browser.AlwaysIncognitoLinkInterceptor;
+import android.content.SharedPreferences;
+
+/**
+ * Unit tests for {@link AppMenuPropertiesDelegateImpl}.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+public class Bromite_AppMenuPropertiesDelegateUnitTest {
+ @Rule
+ public TestRule mProcessor = new Features.JUnitProcessor();
+
+ @Rule
+ public JniMocker mJniMocker = new JniMocker();
+
+ @Mock
+ private ActivityTabProvider mActivityTabProvider;
+ @Mock
+ private Tab mTab;
+ @Mock
+ private WebContents mWebContents;
+ @Mock
+ private NavigationController mNavigationController;
+ @Mock
+ private MultiWindowModeStateDispatcher mMultiWindowModeStateDispatcher;
+ @Mock
+ private TabModelSelector mTabModelSelector;
+ @Mock
+ private TabModel mTabModel;
+ @Mock
+ private TabModel mIncognitoTabModel;
+ @Mock
+ private ToolbarManager mToolbarManager;
+ @Mock
+ private View mDecorView;
+ @Mock
+ private OverviewModeBehavior mOverviewModeBehavior;
+ @Mock
+ private UpdateMenuItemHelper mUpdateMenuItemHelper;
+ @Mock
+ private ContentFeatureListImpl.Natives mContentFeatureListJniMock;
+ @Mock
+ private UserPrefs.Natives mUserPrefsJniMock;
+ @Mock
+ private Profile mProfile;
+ @Mock
+ private PrefService mPrefService;
+ @Mock
+ private TabModelFilterProvider mTabModelFilterProvider;
+ @Mock
+ private TabModelFilter mTabModelFilter;
+
+ private OneshotSupplierImpl<OverviewModeBehavior> mOverviewModeSupplier =
+ new OneshotSupplierImpl<>();
+ private ObservableSupplierImpl<BookmarkBridge> mBookmarkBridgeSupplier =
+ new ObservableSupplierImpl<>();
+
+ private AppMenuPropertiesDelegateImpl mAppMenuPropertiesDelegate;
+
+ private MenuUiState mMenuUiState;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ mOverviewModeSupplier.set(mOverviewModeBehavior);
+ when(mTab.getWebContents()).thenReturn(mWebContents);
+ when(mWebContents.getNavigationController()).thenReturn(mNavigationController);
+ when(mNavigationController.getUseDesktopUserAgent()).thenReturn(false);
+ when(mTabModelSelector.getCurrentModel()).thenReturn(mTabModel);
+ when(mTabModelSelector.getModel(false)).thenReturn((mTabModel));
+ when(mTabModelSelector.getModel(true)).thenReturn((mIncognitoTabModel));
+ when(mTabModelSelector.getTabModelFilterProvider()).thenReturn(mTabModelFilterProvider);
+ when(mTabModelFilterProvider.getCurrentTabModelFilter()).thenReturn(mTabModelFilter);
+ when(mTabModelFilter.getTabModel()).thenReturn(mTabModel);
+
+ UpdateMenuItemHelper.setInstanceForTesting(mUpdateMenuItemHelper);
+ mMenuUiState = new MenuUiState();
+ doReturn(mMenuUiState).when(mUpdateMenuItemHelper).getUiState();
+
+ mJniMocker.mock(ContentFeatureListImplJni.TEST_HOOKS, mContentFeatureListJniMock);
+ mJniMocker.mock(UserPrefsJni.TEST_HOOKS, mUserPrefsJniMock);
+ Profile.setLastUsedProfileForTesting(mProfile);
+ Mockito.when(mUserPrefsJniMock.get(mProfile)).thenReturn(mPrefService);
+ FeatureList.setTestCanUseDefaultsForTesting();
+
+ AppMenuPropertiesDelegateImpl obj = new AppMenuPropertiesDelegateImpl(
+ ContextUtils.getApplicationContext(), mActivityTabProvider,
+ mMultiWindowModeStateDispatcher, mTabModelSelector, mToolbarManager, mDecorView,
+ mOverviewModeSupplier, mBookmarkBridgeSupplier);
+ obj.setPrefForTest(mPrefService);
+ mAppMenuPropertiesDelegate = Mockito.spy(obj);
+ }
+
+ @After
+ public void tearDown() {
+ ThreadUtils.setThreadAssertsDisabledForTesting(false);
+ ChromeAccessibilityUtil.get().setAccessibilityEnabledForTesting(false);
+ ChromeAccessibilityUtil.get().setTouchExplorationEnabledForTesting(false);
+ }
+
+ private void setUpTestPrefs(SharedPreferences prefs, boolean always_incognito) {
+ SharedPreferences.Editor editor = prefs.edit();
+ editor.putBoolean(AlwaysIncognitoLinkInterceptor.PREF_ALWAYS_INCOGNITO, always_incognito);
+ editor.apply();
+ }
+
+ @Test
+ public void testOverviewMenuItems_HideNewTabInAlwaysIncognito() {
+ SharedPreferences mPrefs = ContextUtils.getAppSharedPreferences();
+ setUpTestPrefs(mPrefs, /*always_incognito*/true);
+
+ setUpMocksForPageMenu();
+ when(mTab.getUrl()).thenReturn(JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL));
+
+ Menu menu = createTestMenu();
+ mAppMenuPropertiesDelegate.prepareMenu(menu, null);
+
+ // in always incognito, open new tab is NOT visible
+ final MenuItem newTabOption = menu.findItem(R.id.new_tab_menu_id);
+ Assert.assertFalse(newTabOption.isVisible());
+ }
+
+ @Test
+ public void testOverviewMenuItems_ShowHomeScreenMenuItemInAlwaysIncognito() {
+ SharedPreferences mPrefs = ContextUtils.getAppSharedPreferences();
+ setUpTestPrefs(mPrefs, /*always_incognito*/true);
+
+ setUpMocksForPageMenu();
+ when(mTab.getUrl()).thenReturn(JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL));
+
+ Menu menu = createTestMenu();
+ mAppMenuPropertiesDelegate.prepareMenu(menu, null);
+
+ // in always incognito, home screen menu is visible
+ final MenuItem homescreenItem = menu.findItem(R.id.add_to_homescreen_id);
+ Assert.assertTrue(homescreenItem.isVisible());
+ }
+
+ @Test
+ public void testOverviewMenuItems_HideRecentTabsInAlwaysIncognito() {
+ SharedPreferences mPrefs = ContextUtils.getAppSharedPreferences();
+ setUpTestPrefs(mPrefs, /*always_incognito*/true);
+
+ setUpMocksForPageMenu();
+ when(mTab.getUrl()).thenReturn(JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL));
+
+ when(mPrefService.getBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED))
+ .thenReturn(false);
+
+ Menu menu = createTestMenu();
+ mAppMenuPropertiesDelegate.prepareMenu(menu, null);
+
+ // in always incognito, without INCOGNITO_TAB_HISTORY_ENABLED,
+ // recent tabs menu tab is NOT visible
+ final MenuItem recent_tabs_menu = menu.findItem(R.id.recent_tabs_menu_id);
+ Assert.assertFalse(recent_tabs_menu.isVisible());
+ }
+
+ @Test
+ public void testOverviewMenuItems_ShowRecentTabsInAlwaysIncognito() {
+ SharedPreferences mPrefs = ContextUtils.getAppSharedPreferences();
+ setUpTestPrefs(mPrefs, /*always_incognito*/true);
+
+ setUpMocksForPageMenu();
+ when(mTab.getUrl()).thenReturn(JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL));
+
+ when(mPrefService.getBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED))
+ .thenReturn(true);
+
+ Menu menu = createTestMenu();
+ mAppMenuPropertiesDelegate.prepareMenu(menu, null);
+
+ // in always incognito, with INCOGNITO_TAB_HISTORY_ENABLED
+ // recent tabs menu item is visible
+ final MenuItem recent_tabs_menu = menu.findItem(R.id.recent_tabs_menu_id);
+ Assert.assertTrue(recent_tabs_menu.isVisible());
+ }
+
+ @Test
+ public void testOverviewMenuItems_ShowDownloadItemInAlwaysIncognito() {
+ SharedPreferences mPrefs = ContextUtils.getAppSharedPreferences();
+ setUpTestPrefs(mPrefs, /*always_incognito*/true);
+
+ setUpMocksForPageMenu();
+ when(mTab.getUrl()).thenReturn(JUnitTestGURLs.getGURL(JUnitTestGURLs.EXAMPLE_URL));
+
+ when(mPrefService.getBoolean(Pref.INCOGNITO_TAB_HISTORY_ENABLED))
+ .thenReturn(true);
+
+ Menu menu = createTestMenu();
+ mAppMenuPropertiesDelegate.prepareMenu(menu, null);
+
+ // in always incognito, with INCOGNITO_TAB_HISTORY_ENABLED
+ // download page menu item is visible
+ final MenuItem offline_page = menu.findItem(R.id.offline_page_id);
+ Assert.assertTrue(offline_page.isVisible());
+ }
+
+ private void setUpMocksForPageMenu() {
+ when(mTabModel.isIncognito()).thenReturn(true);
+ when(mIncognitoTabModel.isIncognito()).thenReturn(true);
+
+ when(mActivityTabProvider.get()).thenReturn(mTab);
+ when(mOverviewModeBehavior.overviewVisible()).thenReturn(false);
+ doReturn(false).when(mAppMenuPropertiesDelegate).shouldCheckBookmarkStar(any(Tab.class));
+ doReturn(false).when(mAppMenuPropertiesDelegate).shouldEnableDownloadPage(any(Tab.class));
+ doReturn(false).when(mAppMenuPropertiesDelegate).shouldShowReaderModePrefs(any(Tab.class));
+ doReturn(false)
+ .when(mAppMenuPropertiesDelegate)
+ .shouldShowManagedByMenuItem(any(Tab.class));
+ doReturn(false)
+ .when(mAppMenuPropertiesDelegate)
+ .shouldShowTranslateMenuItem(any(Tab.class));
+ doReturn(new AppBannerManager.InstallStringPair(
+ R.string.menu_add_to_homescreen, R.string.add))
+ .when(mAppMenuPropertiesDelegate)
+ .getAddToHomeScreenTitle(mTab);
+ setUpIncognitoMocks();
+ }
+
+ private void setUpMocksForOverviewMenu() {
+ when(mOverviewModeBehavior.overviewVisible()).thenReturn(true);
+ when(mTabModelSelector.getTotalTabCount()).thenReturn(1);
+ setUpIncognitoMocks();
+ }
+
+ private void setUpIncognitoMocks() {
+ doReturn(true).when(mAppMenuPropertiesDelegate).isIncognitoEnabled();
+ }
+
+ private Menu createTestMenu() {
+ PopupMenu tempMenu = new PopupMenu(ContextUtils.getApplicationContext(), mDecorView);
+ tempMenu.inflate(mAppMenuPropertiesDelegate.getAppMenuLayoutId());
+ Menu menu = tempMenu.getMenu();
+ return menu;
+ }
+}
diff --git a/chrome/android/junit/src/org/chromium/chrome/browser/tab/HistoricalTabSaverUnitTest.java b/chrome/android/junit/src/org/chromium/chrome/browser/tab/HistoricalTabSaverUnitTest.java
--- a/chrome/android/junit/src/org/chromium/chrome/browser/tab/HistoricalTabSaverUnitTest.java
+++ b/chrome/android/junit/src/org/chromium/chrome/browser/tab/HistoricalTabSaverUnitTest.java
@@ -61,9 +61,9 @@ public class HistoricalTabSaverUnitTest {
doReturn(false).when(mTabImplMock).isFrozen();
doReturn(mWebContentsMock).when(mTabImplMock).getWebContents();
- HistoricalTabSaver.createHistoricalTab(mTabImplMock);
+ HistoricalTabSaver.createHistoricalTab(mTabImplMock, false);
- verify(mHistoricalTabSaverJni).createHistoricalTabFromContents(eq(mWebContentsMock));
+ verify(mHistoricalTabSaverJni).createHistoricalTabFromContents(eq(mWebContentsMock), eq(false));
}
@Test
@@ -71,9 +71,9 @@ public class HistoricalTabSaverUnitTest {
doReturn(true).when(mTabImplMock).isFrozen();
doReturn(null).when(mCriticalPersistedTabData).getWebContentsState();
- HistoricalTabSaver.createHistoricalTab(mTabImplMock);
+ HistoricalTabSaver.createHistoricalTab(mTabImplMock, false);
- verify(mHistoricalTabSaverJni, never()).createHistoricalTabFromContents(any());
+ verify(mHistoricalTabSaverJni, never()).createHistoricalTabFromContents(any(), eq(false));
}
@Test
@@ -88,9 +88,9 @@ public class HistoricalTabSaverUnitTest {
.when(mWebContentsStateBridgeJni)
.restoreContentsFromByteBuffer(eq(buffer), eq(123), eq(true));
- HistoricalTabSaver.createHistoricalTab(mTabImplMock);
+ HistoricalTabSaver.createHistoricalTab(mTabImplMock, false);
- verify(mHistoricalTabSaverJni, never()).createHistoricalTabFromContents(any());
+ verify(mHistoricalTabSaverJni, never()).createHistoricalTabFromContents(any(), eq(false));
}
@Test
@@ -105,8 +105,8 @@ public class HistoricalTabSaverUnitTest {
.when(mWebContentsStateBridgeJni)
.restoreContentsFromByteBuffer(eq(buffer), eq(123), eq(true));
- HistoricalTabSaver.createHistoricalTab(mTabImplMock);
+ HistoricalTabSaver.createHistoricalTab(mTabImplMock, false);
- verify(mHistoricalTabSaverJni).createHistoricalTabFromContents(eq(mWebContentsMock));
+ verify(mHistoricalTabSaverJni).createHistoricalTabFromContents(eq(mWebContentsMock), eq(false));
}
}
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
@@ -12,16 +12,27 @@
#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;
namespace {
-void CreateHistoricalTab(content::WebContents* web_contents) {
+void CreateHistoricalTab(content::WebContents* web_contents,
+ bool is_always_incognito) {
DCHECK(web_contents);
+ auto* profile = Profile::FromBrowserContext(web_contents->GetBrowserContext());
+ if (is_always_incognito) {
+ if(profile->GetOriginalProfile()->GetPrefs()->GetBoolean(prefs::kIncognitoTabHistoryEnabled))
+ profile = profile->GetOriginalProfile();
+ }
+
sessions::TabRestoreService* service =
- TabRestoreServiceFactory::GetForProfile(
- Profile::FromBrowserContext(web_contents->GetBrowserContext()));
+ TabRestoreServiceFactory::GetForProfile(profile);
if (!service)
return;
@@ -41,11 +52,18 @@ void CreateHistoricalTab(content::WebContents* web_contents) {
// Static JNI methods.
+// static
+void CreateHistoricalTabForTest(content::WebContents* web_contents,
+ bool is_always_incognito) {
+ CreateHistoricalTab(web_contents, is_always_incognito);
+}
+
// static
static void JNI_HistoricalTabSaver_CreateHistoricalTabFromContents(
JNIEnv* env,
- const JavaParamRef<jobject>& jweb_contents) {
+ const JavaParamRef<jobject>& jweb_contents,
+ jboolean is_always_incognito) {
auto* web_contents = content::WebContents::FromJavaWebContents(jweb_contents);
if (web_contents)
- CreateHistoricalTab(web_contents);
+ CreateHistoricalTab(web_contents, is_always_incognito);
}
diff --git a/chrome/browser/android/historical_tab_saver.h b/chrome/browser/android/historical_tab_saver.h
new file mode 100644
--- /dev/null
+++ b/chrome/browser/android/historical_tab_saver.h
@@ -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/>.
+*/
+
+#ifndef CHROME_BROWSER_ANDROID_HISTORICAL_TAB_SAVER_H_
+#define CHROME_BROWSER_ANDROID_HISTORICAL_TAB_SAVER_H_
+
+#include "content/public/browser/web_contents.h"
+
+// static
+void CreateHistoricalTabForTest(content::WebContents* web_contents,
+ bool is_always_incognito);
+
+#endif // CHROME_BROWSER_ANDROID_HISTORICAL_TAB_SAVER_H_
diff --git a/chrome/browser/android/historical_tab_saver_unittest.cc b/chrome/browser/android/historical_tab_saver_unittest.cc
new file mode 100644
--- /dev/null
+++ b/chrome/browser/android/historical_tab_saver_unittest.cc
@@ -0,0 +1,148 @@
+/*
+ This file is part of Bromite.
+
+ Bromite is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ Bromite is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with Bromite. If not, see <https://www.gnu.org/licenses/>.
+*/
+
+#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task/cancelable_task_tracker.h"
+#include "base/test/bind.h"
+#include "build/build_config.h"
+#include "chrome/browser/history/history_service_factory.h"
+#include "chrome/test/base/chrome_render_view_host_test_harness.h"
+#include "chrome/test/base/testing_profile.h"
+#include "components/history/core/browser/history_constants.h"
+#include "components/history/core/browser/history_service.h"
+#include "components/history/core/browser/history_types.h"
+#include "components/history/core/browser/url_row.h"
+#include "content/public/browser/browser_context.h"
+#include "content/public/browser/navigation_controller.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/test/mock_navigation_handle.h"
+#include "content/public/test/web_contents_tester.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/page_transition_types.h"
+
+#include "chrome/test/base/testing_browser_process.h"
+#include "chrome/test/base/testing_profile_manager.h"
+#include "content/public/test/test_browser_context.h"
+#include "content/test/test_web_contents.h"
+#include "components/sessions/core/tab_restore_service.h"
+#include "components/sessions/core/tab_restore_service_impl.h"
+#include "components/sessions/content/content_live_tab.h"
+#include "chrome/browser/android/historical_tab_saver.h"
+#include "chrome/browser/sessions/tab_restore_service_factory.h"
+#include "chrome/browser/sessions/chrome_tab_restore_service_client.h"
+#include "chrome/common/pref_names.h"
+
+namespace {
+
+static std::unique_ptr<KeyedService> GetTabRestoreService(
+ content::BrowserContext* browser_context) {
+ return std::make_unique<sessions::TabRestoreServiceImpl>(
+ std::make_unique<ChromeTabRestoreServiceClient>(
+ Profile::FromBrowserContext(browser_context)),
+ nullptr, nullptr);
+}
+
+// --gtest_filter=*.Bromite*
+class HistoryTabSaverTest : public ChromeRenderViewHostTestHarness {
+ protected:
+ HistoryTabSaverTest() {}
+
+ // ChromeRenderViewHostTestHarness:
+ void SetUp() override {
+ ChromeRenderViewHostTestHarness::SetUp();
+ TabRestoreServiceFactory::GetInstance()->SetTestingFactory(
+ profile(),
+ base::BindRepeating(&GetTabRestoreService));
+ ASSERT_TRUE(profile()->CreateHistoryService());
+ }
+
+ const GURL page_url_ = GURL("http://foo.com");
+
+ protected:
+// history::HistoryService* history_service_;
+
+ DISALLOW_COPY_AND_ASSIGN(HistoryTabSaverTest);
+};
+
+TEST_F(HistoryTabSaverTest, Bromite_HistoricalTabForNormalNavigation) {
+ sessions::TabRestoreService* service =
+ TabRestoreServiceFactory::GetForProfile(profile());
+ ASSERT_NE(nullptr, service);
+
+ auto* profile_ = profile();
+ auto web_other_contents = content::TestWebContents::Create(profile_, nullptr);
+ web_other_contents->NavigateAndCommit(page_url_);
+
+ // Make sure was no entry.
+ ASSERT_EQ(0U, service->entries().size());
+
+ CreateHistoricalTabForTest(web_other_contents.get(), /*is_always_incognito*/false);
+
+ // Make sure entry was created.
+ ASSERT_EQ(1U, service->entries().size());
+}
+
+TEST_F(HistoryTabSaverTest, Bromite_HistoricalTabForNavigationInIncognito) {
+ sessions::TabRestoreService* service =
+ TabRestoreServiceFactory::GetForProfile(profile());
+ ASSERT_NE(nullptr, service);
+
+ auto* profile_ = profile()->GetOffTheRecordProfile(
+ Profile::OTRProfileID::PrimaryID(), /*create_if_needed=*/true);
+ auto web_other_contents = content::TestWebContents::Create(profile_, nullptr);
+ web_other_contents->NavigateAndCommit(page_url_);
+
+ // Make sure was no entry.
+ ASSERT_EQ(0U, service->entries().size());
+
+ CreateHistoricalTabForTest(web_other_contents.get(), /*is_always_incognito*/false);
+
+ // Make sure was no entry.
+ ASSERT_EQ(0U, service->entries().size());
+}
+
+TEST_F(HistoryTabSaverTest, Bromite_HistoricalTabForNavigationInIncognito_AlwaysIncognito) {
+ sessions::TabRestoreService* service =
+ TabRestoreServiceFactory::GetForProfile(profile());
+ ASSERT_NE(nullptr, service);
+
+ auto* profile_ = profile()->GetOffTheRecordProfile(
+ Profile::OTRProfileID::PrimaryID(), /*create_if_needed=*/true);
+ auto web_other_contents = content::TestWebContents::Create(profile_, nullptr);
+ web_other_contents->NavigateAndCommit(page_url_);
+
+ // test kIncognitoTabHistoryEnabled with false
+ profile()->GetPrefs()->SetBoolean(prefs::kIncognitoTabHistoryEnabled, false);
+
+ CreateHistoricalTabForTest(web_other_contents.get(), /*is_always_incognito*/true);
+
+ // Make sure was no entry.
+ ASSERT_EQ(0U, service->entries().size());
+
+ // test kIncognitoTabHistoryEnabled with true
+ profile()->GetPrefs()->SetBoolean(prefs::kIncognitoTabHistoryEnabled, true);
+
+ CreateHistoricalTabForTest(web_other_contents.get(), /*is_always_incognito*/true);
+
+ // Make sure was the entry.
+ ASSERT_EQ(1U, service->entries().size());
+}
+
+} // namespace
diff --git a/chrome/browser/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
@@ -27,6 +27,9 @@
#include "chrome/browser/android/feed/v2/feed_service_factory.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"
@@ -299,6 +302,13 @@ void HistoryTabHelper::TitleWasSet(NavigationEntry* entry) {
history::HistoryService* HistoryTabHelper::GetHistoryService() {
Profile* profile =
Profile::FromBrowserContext(web_contents()->GetBrowserContext());
+
+#if defined(OS_ANDROID)
+ if(profile->GetOriginalProfile()->GetPrefs()->GetBoolean(prefs::kIncognitoTabHistoryEnabled)) {
+ return HistoryServiceFactory::GetForProfile(profile, ServiceAccessType::IMPLICIT_ACCESS);
+ }
+#endif
+
if (profile->IsOffTheRecord())
return NULL;
@@ -306,6 +316,12 @@ history::HistoryService* HistoryTabHelper::GetHistoryService() {
profile, ServiceAccessType::IMPLICIT_ACCESS);
}
+// static
+void HistoryTabHelper::RegisterProfilePrefs(PrefRegistrySimple* registry) {
+ registry->RegisterBooleanPref(prefs::kIncognitoTabHistoryEnabled,
+ /*default_value=*/false);
+}
+
void HistoryTabHelper::WebContentsDestroyed() {
// We update the history for this URL.
WebContents* tab = web_contents();
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
@@ -10,6 +10,8 @@
#include "build/build_config.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;
@@ -39,6 +41,11 @@ class HistoryTabHelper : public content::WebContentsObserver,
force_eligibile_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>;
@@ -53,9 +60,6 @@ class HistoryTabHelper : public content::WebContentsObserver,
void TitleWasSet(content::NavigationEntry* entry) override;
void WebContentsDestroyed() 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/history/history_tab_helper_unittest.cc b/chrome/browser/history/history_tab_helper_unittest.cc
--- a/chrome/browser/history/history_tab_helper_unittest.cc
+++ b/chrome/browser/history/history_tab_helper_unittest.cc
@@ -39,6 +39,9 @@
using testing::NiceMock;
+#include "chrome/common/pref_names.h"
+#include "content/test/test_web_contents.h"
+
namespace {
#if defined(OS_ANDROID)
@@ -271,4 +274,23 @@ TEST_F(HistoryTabHelperTest, FeedNavigationsDoNotContributeToMostVisited) {
#endif
+TEST_F(HistoryTabHelperTest, Bromite_CheckHistoryService_IncognitoTabHistoryEnabled) {
+ auto* profile_ = profile()->GetOffTheRecordProfile(
+ Profile::OTRProfileID::PrimaryID(), /*create_if_needed=*/true);
+ auto web_other_contents = content::TestWebContents::Create(profile_, nullptr);
+ web_other_contents->NavigateAndCommit(page_url_);
+
+ HistoryTabHelper::CreateForWebContents(web_other_contents.get());
+ HistoryTabHelper* history_tab_helper = HistoryTabHelper::FromWebContents(web_other_contents.get());
+ ASSERT_NE(nullptr, history_tab_helper);
+
+ // test kIncognitoTabHistoryEnabled with false
+ profile()->GetPrefs()->SetBoolean(prefs::kIncognitoTabHistoryEnabled, false);
+ ASSERT_EQ(nullptr, history_tab_helper->GetHistoryService());
+
+ // test kIncognitoTabHistoryEnabled with true
+ profile()->GetPrefs()->SetBoolean(prefs::kIncognitoTabHistoryEnabled, true);
+ ASSERT_NE(nullptr, history_tab_helper->GetHistoryService());
+}
+
} // namespace
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
@@ -49,6 +49,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;
@@ -158,7 +161,13 @@ void ValidateFileCallback(
int64_t offline_id,
const GURL& url,
const base::FilePath& file_path,
+ SimpleFactoryKey* key,
bool is_trusted) {
+ // 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;
+
// If trusted, the launch url will be the http/https url of the offline
// page. If the file path is content URI, directly open it. Otherwise, the
// launch url will be the file URL pointing to the archive file of the offline
@@ -785,7 +794,7 @@ void OfflinePageBridge::GetPageByOfflineIdDone(
if (offline_page_model_->IsArchiveInInternalDir(offline_page->file_path)) {
ValidateFileCallback(launch_location, j_callback_obj,
offline_page->offline_id, offline_page->url,
- offline_page->file_path, true /* is_trusted*/);
+ offline_page->file_path, key_, true /* is_trusted*/);
return;
}
@@ -795,7 +804,7 @@ void OfflinePageBridge::GetPageByOfflineIdDone(
offline_page->file_size, offline_page->digest),
base::BindOnce(&ValidateFileCallback, launch_location, j_callback_obj,
offline_page->offline_id, offline_page->url,
- offline_page->file_path));
+ offline_page->file_path, key_));
}
void OfflinePageBridge::GetSizeAndComputeDigestDone(
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
@@ -26,6 +26,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 {
@@ -48,6 +51,7 @@ OfflinePageModel* OfflinePageModelFactory::GetForKey(SimpleFactoryKey* key) {
OfflinePageModel* OfflinePageModelFactory::GetForBrowserContext(
content::BrowserContext* browser_context) {
Profile* profile = Profile::FromBrowserContext(browser_context);
+ profile = profile->GetOriginalProfile();
return GetForKey(profile->GetProfileKey());
}
@@ -56,13 +60,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;
@@ -71,7 +77,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,
@@ -91,4 +96,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);
+ } else {
+ 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
@@ -29,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;
}
@@ -114,4 +119,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);
+ } else {
+ 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
@@ -47,6 +47,8 @@ class OfflinePageModelFactory : public SimpleKeyedServiceFactory {
std::unique_ptr<KeyedService> BuildServiceInstanceFor(
SimpleFactoryKey* key) const override;
+ SimpleFactoryKey* GetKeyToUse(SimpleFactoryKey* key) const override;
+
DISALLOW_COPY_AND_ASSIGN(OfflinePageModelFactory);
};
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
@@ -30,6 +30,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 {
@@ -181,6 +186,13 @@ 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;
+ }
+ }
if (snapshots_enabled_) {
page_model_ = OfflinePageModelFactory::GetForBrowserContext(
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
@@ -34,6 +34,9 @@ class RequestCoordinatorFactory : public BrowserContextKeyedServiceFactory {
KeyedService* BuildServiceInstanceFor(
content::BrowserContext* context) const override;
+ content::BrowserContext* GetBrowserContextToUse(
+ content::BrowserContext* context) const override;
+
DISALLOW_COPY_AND_ASSIGN(RequestCoordinatorFactory);
};
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
@@ -212,6 +212,8 @@
#endif
#if defined(OS_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"
@@ -1210,6 +1212,7 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry,
variations::VariationsService::RegisterProfilePrefs(registry);
video_tutorials::RegisterPrefs(registry);
feed::prefs::RegisterFeedSharedProfilePrefs(registry);
+ HistoryTabHelper::RegisterProfilePrefs(registry);
feed::RegisterProfilePrefs(registry);
#else // defined(OS_ANDROID)
AppShortcutManager::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
@@ -31,8 +31,10 @@ java_library("junit") {
deps = [
":java",
+ "//base:base_java",
"//base:base_junit_test_support",
"//third_party/android_deps:robolectric_all_java",
"//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.
*/
@@ -156,7 +158,9 @@ 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 ||
+ ContextUtils.getAppSharedPreferences().getBoolean("always_incognito", false))) {
return NativePageType.RECENT_TABS;
} else if (UrlConstants.EXPLORE_HOST.equals(host)) {
return NativePageType.EXPLORE;
diff --git a/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePageTest.java b/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePageTest.java
--- a/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePageTest.java
+++ b/chrome/browser/ui/android/native_page/java/src/org/chromium/chrome/browser/ui/native_page/NativePageTest.java
@@ -12,6 +12,10 @@ import org.robolectric.annotation.Config;
import org.chromium.base.test.BaseRobolectricTestRunner;
import org.chromium.chrome.browser.ui.native_page.NativePage.NativePageType;
+import org.chromium.base.ContextUtils;
+import org.chromium.components.embedder_support.util.UrlConstants;
+import android.content.SharedPreferences;
+
/**
* Tests public methods in NativePage.
*/
@@ -91,4 +95,26 @@ public class NativePageTest {
Assert.assertFalse(invalidUrl, NativePage.isNativePageUrl(invalidUrl, true));
}
}
+
+ @Test
+ public void Bromite_testNativePage_RecentTabsInAlwaysIncognito() {
+ SharedPreferences prefs = ContextUtils.getAppSharedPreferences();
+ SharedPreferences.Editor editor = prefs.edit();
+
+ String url = "chrome-native://recent-tabs";
+
+ editor.putBoolean(/*AlwaysIncognitoLinkInterceptor.PREF_ALWAYS_INCOGNITO*/
+ "always_incognito", false);
+ editor.apply();
+
+ Assert.assertEquals(NativePageType.NONE,
+ NativePage.nativePageType(url, null, /*isIncognito*/true));
+
+ editor.putBoolean(/*AlwaysIncognitoLinkInterceptor.PREF_ALWAYS_INCOGNITO*/
+ "always_incognito", true);
+ editor.apply();
+
+ Assert.assertEquals(NativePageType.RECENT_TABS,
+ NativePage.nativePageType(url, null, /*isIncognito*/true));
+ }
}
diff --git a/chrome/browser/ui/android/strings/android_chrome_strings.grd b/chrome/browser/ui/android/strings/android_chrome_strings.grd
--- a/chrome/browser/ui/android/strings/android_chrome_strings.grd
+++ b/chrome/browser/ui/android/strings/android_chrome_strings.grd
@@ -938,6 +938,12 @@ Your Google account may have other forms of browsing history like searches and a
<message name="IDS_UI_RELAUNCH_NOTICE" desc="Summary for always incognito mode">
Your changes will take effect the next time you relaunch Bromite.
</message>
+ <message name="IDS_INCOGNITO_HISTORY_ENABLED_TITLE" desc="Title for always enable history in incognito mode">
+ Enable history in incognito tabs
+ </message>
+ <message name="IDS_INCOGNITO_HISTORY_ENABLED_SUMMARY" desc="Summary for always enable history in incognito mode">
+ Record history even in incognito mode
+ </message>
<message name="IDS_CLEAR_BROWSING_HISTORY_SUMMARY_SIGNED_IN" desc="A text explaining other forms of activity for signed in users.">
Clears history and autocompletions in the address bar. Your Google Account may have other forms of browsing history at <ph name="BEGIN_LINK">&lt;link&gt;</ph>myactivity.google.com<ph name="END_LINK">&lt;/link&gt;</ph>.
</message>
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
@@ -3225,6 +3225,11 @@ const char kLacrosAllowed[] = "lacros_allowed";
const char kLacrosLaunchSwitch[] = "lacros_launch_switch";
#endif
+#if defined(OS_ANDROID)
+const char kIncognitoTabHistoryEnabled[] =
+ "incognito_tab_history_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
@@ -1184,6 +1184,10 @@ extern const char kLastWhatsNewVersion[];
extern const char kLensRegionSearchEnabled[];
#endif
+#if defined(OS_ANDROID)
+extern const char kIncognitoTabHistoryEnabled[];
+#endif
+
} // namespace prefs
#endif // CHROME_COMMON_PREF_NAMES_H_
diff --git a/chrome/test/BUILD.gn b/chrome/test/BUILD.gn
--- a/chrome/test/BUILD.gn
+++ b/chrome/test/BUILD.gn
@@ -4669,6 +4669,11 @@ test("unit_tests") {
]
}
+ # Bromite tests
+ sources += [
+ "../browser/android/historical_tab_saver_unittest.cc",
+ ]
+
if (is_android) {
sources += [
"../browser/android/bookmarks/partner_bookmarks_shim_unittest.cc",
--
2.17.1