Remove WIP patches

This commit is contained in:
csagan5 2018-09-01 12:12:06 +02:00
parent b1bc96bbd9
commit f109246e47
No known key found for this signature in database
GPG key ID: 64190A51D85DC0C5
2 changed files with 0 additions and 1241 deletions

View file

@ -1,267 +0,0 @@
From: csagan5 <32685696+csagan5@users.noreply.github.com>
Date: Wed, 2 May 2018 01:24:39 +0200
Subject: Add Always Incognito option
---
chrome/android/java/res/menu/custom_tabs_menu.xml | 12 ++++++++
chrome/android/java/res/menu/main_menu.xml | 12 ++++++++
.../chromium/chrome/browser/ChromeActivity.java | 4 +++
.../chrome/browser/ChromeTabbedActivity.java | 4 +++
.../org/chromium/chrome/browser/IntentHandler.java | 8 ++---
.../chrome/browser/LaunchIntentDispatcher.java | 7 +++++
.../browser/appmenu/AppMenuPropertiesDelegate.java | 35 ++++++++++++++++++++++
.../CustomTabAppMenuPropertiesDelegate.java | 2 ++
.../browser/preferences/PrefServiceBridge.java | 17 +++++++++++
.../java/strings/android_chrome_strings.grd | 10 +++++++
10 files changed, 106 insertions(+), 5 deletions(-)
diff --git a/chrome/android/java/res/menu/custom_tabs_menu.xml b/chrome/android/java/res/menu/custom_tabs_menu.xml
--- a/chrome/android/java/res/menu/custom_tabs_menu.xml
+++ b/chrome/android/java/res/menu/custom_tabs_menu.xml
@@ -62,6 +62,18 @@
</menu>
</item>
+ <item android:id="@+id/enable_always_incognito_row_menu_id"
+ android:title="@null"
+ android:orderInCategory="2">
+ <menu>
+ <item android:id="@+id/enable_always_incognito_id"
+ android:title="@string/menu_enable_always_incognito" />
+ <item android:id="@+id/enable_always_incognito_check_id"
+ android:title="@null"
+ android:checkable="true" />
+ </menu>
+ </item>
+
<item android:id="@+id/request_desktop_site_row_menu_id"
android:title="@null"
android:orderInCategory="2">
diff --git a/chrome/android/java/res/menu/main_menu.xml b/chrome/android/java/res/menu/main_menu.xml
--- a/chrome/android/java/res/menu/main_menu.xml
+++ b/chrome/android/java/res/menu/main_menu.xml
@@ -72,6 +72,18 @@
</menu>
</item>
+ <item android:id="@+id/enable_always_incognito_row_menu_id"
+ android:title="@null"
+ android:orderInCategory="2">
+ <menu>
+ <item android:id="@+id/enable_always_incognito_id"
+ android:title="@string/menu_enable_always_incognito" />
+ <item android:id="@+id/enable_always_incognito_check_id"
+ android:title="@null"
+ android:checkable="true" />
+ </menu>
+ </item>
+
<item android:id="@+id/request_desktop_site_row_menu_id"
android:title="@null">
<menu>
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -1905,6 +1905,10 @@ public abstract class ChromeActivity extends AsyncInitializationActivity
RecordUserAction.record("MobileMenuSettings");
} else if (id == R.id.show_menu) {
showAppMenuForKeyboardEvent();
+ } else if (id == R.id.enable_always_incognito_id || id == R.id.enable_always_incognito_check_id) {
+ final boolean alwaysIncognito = PrefServiceBridge.getInstance().alwaysIncognitoEnabled();
+ PrefServiceBridge.getInstance().setAlwaysIncognitoEnabled(!alwaysIncognito);
+ RecordUserAction.record("MobileMenuRequestEnableAlwaysIncognito");
} else if (id == R.id.find_in_page_id) {
if (mFindToolbarManager == null) return false;
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
@@ -1753,6 +1753,10 @@ public class ChromeTabbedActivity
reportNewTabShortcutUsed(true);
getTabCreator(true).launchNTP();
}
+ } else if (id == R.id.enable_always_incognito_id || id == R.id.enable_always_incognito_check_id) {
+ final boolean alwaysIncognito = PrefServiceBridge.getInstance().alwaysIncognitoEnabled();
+ PrefServiceBridge.getInstance().setAlwaysIncognitoEnabled(!alwaysIncognito);
+ RecordUserAction.record("MobileMenuRequestEnableAlwaysIncognito");
} else if (id == R.id.all_bookmarks_menu_id) {
if (currentTab != null) {
getCompositorViewHolder().hideKeyboard(() -> {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/IntentHandler.java
@@ -732,7 +732,6 @@ public class IntentHandler {
// Determine if this intent came from a trustworthy source (either Chrome or Google
// first party applications).
boolean isInternal = isIntentChromeOrFirstParty(intent);
- boolean isFromChrome = wasIntentSenderChrome(intent);
// "Open new incognito tab" is currently limited to Chrome.
//
@@ -741,11 +740,10 @@ public class IntentHandler {
// from the list. In this case, we do not apply our Chrome token as the user has the
// option to select apps outside of our control, so we rely on this in memory check
// instead.
- if (!isFromChrome
- && IntentUtils.safeGetBooleanExtra(
+ if (IntentUtils.safeGetBooleanExtra(
intent, EXTRA_OPEN_NEW_INCOGNITO_TAB, false)
- && (getPendingIncognitoUrl() == null
- || !getPendingIncognitoUrl().equals(intent.getDataString()))) {
+ && getPendingIncognitoUrl() != null
+ && getPendingIncognitoUrl().equals(intent.getDataString())) {
return true;
}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/LaunchIntentDispatcher.java
@@ -36,6 +36,7 @@ import org.chromium.chrome.browser.instantapps.InstantAppsHandler;
import org.chromium.chrome.browser.metrics.MediaNotificationUma;
import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
import org.chromium.chrome.browser.notifications.NotificationPlatformBridge;
+import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import org.chromium.chrome.browser.partnercustomizations.PartnerBrowserCustomizations;
import org.chromium.chrome.browser.searchwidget.SearchActivity;
import org.chromium.chrome.browser.tab.Tab;
@@ -185,6 +186,12 @@ public class LaunchIntentDispatcher implements IntentHandler.IntentHandlerDelega
boolean incognito =
mIntent.getBooleanExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, false);
+ if (!incognito) {
+ incognito = PrefServiceBridge.getInstance().alwaysIncognitoEnabled();
+ if (incognito) {
+ mIntent.putExtra(IntentHandler.EXTRA_OPEN_NEW_INCOGNITO_TAB, true);
+ }
+ }
// Check if a web search Intent is being handled.
IntentHandler intentHandler = new IntentHandler(this, mActivity.getPackageName());
String url = IntentHandler.getUrlFromIntent(mIntent);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java
@@ -211,6 +211,8 @@ public class AppMenuPropertiesDelegate {
&& !TextUtils.isEmpty(url);
prepareAddToHomescreenMenuItem(menu, currentTab, canShowHomeScreenMenuItem);
+ updateEnableAlwaysIncognitoMenuItem(menu, currentTab);
+
updateRequestDesktopSiteMenuItem(menu, currentTab, true /* can show */);
updateEnableJavascriptMenuItem(menu, currentTab);
@@ -410,6 +412,39 @@ public class AppMenuPropertiesDelegate {
}
/**
+ * Updates the enable Always Incognito item's state.
+ *
+ * @param menu {@link Menu} for enable always incognito
+ * @param currentTab Current tab being displayed.
+ */
+ protected void updateEnableAlwaysIncognitoMenuItem(
+ Menu menu, Tab currentTab) {
+ MenuItem enableMenuRow = menu.findItem(R.id.enable_always_incognito_row_menu_id);
+ MenuItem enableMenuLabel = menu.findItem(R.id.enable_always_incognito_id);
+ MenuItem enableMenuCheck = menu.findItem(R.id.enable_always_incognito_check_id);
+
+ // Hide enable always incognito on all chrome:// pages and the NTP.
+ String url = currentTab.getUrl();
+ boolean isChromeScheme = url.startsWith(UrlConstants.CHROME_URL_PREFIX)
+ || url.startsWith(UrlConstants.CHROME_NATIVE_URL_PREFIX);
+
+ boolean itemVisible = !isChromeScheme && !currentTab.isNativePage();
+ enableMenuRow.setVisible(itemVisible);
+ if (!itemVisible) return;
+
+ boolean alwaysIncognito = PrefServiceBridge.getInstance().alwaysIncognitoEnabled();
+
+ // Mark the checkbox if always incognito is activated on this tab.
+ enableMenuCheck.setChecked(alwaysIncognito);
+
+ // This title doesn't seem to be displayed by Android, but it is used to set up
+ // accessibility text in {@link AppMenuAdapter#setupMenuButton}.
+ enableMenuLabel.setTitleCondensed(alwaysIncognito
+ ? mActivity.getString(R.string.menu_enable_always_incognito_on)
+ : mActivity.getString(R.string.menu_enable_always_incognito_off));
+ }
+
+ /**
* Updates the request desktop site item's state.
*
* @param menu {@link Menu} for request desktop site.
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
@@ -163,6 +163,8 @@ public class CustomTabAppMenuPropertiesDelegate extends AppMenuPropertiesDelegat
}
}
+ updateEnableAlwaysIncognitoMenuItem(menu, currentTab);
+
updateRequestDesktopSiteMenuItem(menu, currentTab, requestDesktopSiteVisible);
updateEnableJavascriptMenuItem(menu, currentTab);
prepareAddToHomescreenMenuItem(menu, currentTab, addToHomeScreenVisible);
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/PrefServiceBridge.java
@@ -57,6 +57,8 @@ public class PrefServiceBridge {
private static final String CONTEXTUAL_SEARCH_DISABLED = "false";
private static final String CONTEXTUAL_SEARCH_ENABLED = "true";
+ private static boolean alwaysIncognito = false;
+
/**
* Structure that holds all the version information about the current Chrome browser.
*/
@@ -359,6 +361,14 @@ public class PrefServiceBridge {
}
/**
+ * @return true if always-incognito is enabled.
+ * The default is false.
+ */
+ public boolean alwaysIncognitoEnabled() {
+ return alwaysIncognito;
+ }
+
+ /**
* @return true if background sync is managed by policy.
*/
public boolean isBackgroundSyncManaged() {
@@ -422,6 +432,13 @@ public class PrefServiceBridge {
}
/**
+ * Enable or disable always-incognito mode.
+ */
+ public void setAlwaysIncognitoEnabled(boolean enabled) {
+ alwaysIncognito = enabled;
+ }
+
+ /**
* Enable or disable background sync.
*/
public void setBackgroundSyncEnabled(boolean enabled) {
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -2502,6 +2502,16 @@ To obtain new licenses, connect to the internet and play your downloaded content
Turn on JavaScript
</message>
+ <message name="IDS_MENU_ENABLE_ALWAYS_INCOGNITO" desc="Menu item in Chrome's overflow/options menu. If this menu item is selected, Bromite will always open new pages in incognito mode. [CHAR-LIMIT=27]">
+ Always Incognito
+ </message>
+ <message name="IDS_MENU_ENABLE_ALWAYS_INCOGNITO_ON" desc="Accessibility description for when Always Incognito is selected.">
+ Turn off Always Incognito
+ </message>
+ <message name="IDS_MENU_ENABLE_ALWAYS_INCOGNITO_OFF" desc="Accessibility description for when Enable Always Incognito is unselected.">
+ Turn on Always Incognito
+ </message>
+
<message name="IDS_MENU_REQUEST_DESKTOP_SITE" desc="Menu item in Chrome's overflow/options menu. By default, when a user navigates to a web page, Chrome shows the mobile site, that is, the version of the site designed for mobile phones. If this menu item is selected, however, Chrome will try to load the 'desktop' site instead, i.e. the site designed for desktop computers or laptop computers, which have larger screens. [CHAR-LIMIT=24]">
Desktop site
</message>
--
2.7.4

View file

@ -1,974 +0,0 @@
commit 56ab68688e7d2c7734e6190bf602dd584eae3222
Author: csagan5 <32685696+csagan5@users.noreply.github.com>
Date: Sat Dec 9 23:03:50 2017 +0100
Incognito-only mode ported from CAF
Some rework was needed, almost nothing applied cleanly.
See below for the description of the two commits that were merged in this one.
Browser setting to switch to incognito only mode
- Added a setting to switch to incognito only mode in
privacy settings
- Upon enabling or disabling the switch, the browser will
restart in the respective mode (regular or incognito only)
Change-Id: Ic42daa3e9bfdc0fcb4029d9df16ed57c5776d966
Fix issues seen in full incognito mode
- Fixes crashes seen in incognito mode.
- Allow Custom Tabs, Web Apps to use the incognito only mode.
- Ensure we notify the user of the incognito mode in the notification bar and remove the notification when all
incognito tabs are closed.
- Ensure the status bar for Custom Tabs and Web Apps are grey to give a visual notification to use.
- Ensure the tabs are correctly ref counted for Custom Tabs, Web Apps when using incognito only mode.
CR-Fixed: SWE-8867, SWE-8802
Change-Id: I95a77016e7562d82359c7780771da4c7bb73aa06
diff --git a/chrome/android/java/res/xml/privacy_preferences.xml b/chrome/android/java/res/xml/privacy_preferences.xml
index ce7db92..a85aea3 100644
--- a/chrome/android/java/res/xml/privacy_preferences.xml
+++ b/chrome/android/java/res/xml/privacy_preferences.xml
@@ -31,6 +31,10 @@
android:title="@string/network_predictions_title"
android:summary="@string/network_predictions_summary"
android:persistent="false" />
+ <org.chromium.chrome.browser.preferences.ChromeBaseCheckBoxPreference
+ android:key="incognito_only"
+ android:title="@string/incognito_only_title"
+ android:summary="@string/incognito_only_summary" />
<Preference
android:key="usage_and_crash_reports"
android:title="@string/usage_and_crash_reports_title"
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
index 49a3251..7445c9b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/ChromeActivity.java
@@ -51,6 +51,9 @@ import org.chromium.base.VisibleForTesting;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.R;
+import org.chromium.chrome.browser.incognito.IncognitoOnlyModeUtil;
+import org.chromium.chrome.browser.init.AsyncInitializationActivity;
+import org.chromium.chrome.browser.preferences.AboutChromePreferences;
import org.chromium.chrome.browser.IntentHandler.IntentHandlerDelegate;
import org.chromium.chrome.browser.IntentHandler.TabOpenType;
import org.chromium.chrome.browser.appmenu.AppMenu;
@@ -84,6 +87,7 @@ import org.chromium.chrome.browser.gsa.GSAAccountChangeListener;
import org.chromium.chrome.browser.gsa.GSAState;
import org.chromium.chrome.browser.help.HelpAndFeedback;
import org.chromium.chrome.browser.history.HistoryManagerUtils;
+import org.chromium.chrome.browser.incognito.IncognitoOnlyModeUtil;
import org.chromium.chrome.browser.infobar.InfoBarContainer;
import org.chromium.chrome.browser.init.AsyncInitializationActivity;
import org.chromium.chrome.browser.init.ProcessInitializationHandler;
@@ -130,6 +134,7 @@ import org.chromium.chrome.browser.toolbar.ToolbarManager;
import org.chromium.chrome.browser.util.AccessibilityUtil;
import org.chromium.chrome.browser.util.ColorUtils;
import org.chromium.chrome.browser.util.FeatureUtilities;
+
import org.chromium.chrome.browser.vr_shell.VrIntentUtils;
import org.chromium.chrome.browser.vr_shell.VrShellDelegate;
import org.chromium.chrome.browser.webapps.AddToHomescreenManager;
@@ -1312,6 +1317,9 @@ public abstract class ChromeActivity extends AsyncInitializationActivity
* @param menu Menu that is going to be shown when the menu button is pressed.
*/
public void prepareMenu(Menu menu) {
+ if (IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled()) {
+ menu.findItem(R.id.new_incognito_tab_menu_id).setVisible(false);
+ }
}
protected IntentHandlerDelegate createIntentHandlerDelegate() {
@@ -1436,7 +1444,8 @@ public abstract class ChromeActivity extends AsyncInitializationActivity
throw new IllegalStateException(
"Attempting to access TabCreator before initialization");
}
- return incognito ? mIncognitoTabCreator : mRegularTabCreator;
+ return incognito || IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled()
+ ? mIncognitoTabCreator : mRegularTabCreator;
}
/**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java
index 44c9c8a..bcba76a 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/SingleTabActivity.java
@@ -4,15 +4,28 @@
package org.chromium.chrome.browser;
+import android.annotation.SuppressLint;
import android.content.Intent;
import android.util.Pair;
+import org.chromium.base.ThreadUtils;
+import org.chromium.chrome.R;
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.TabState;
+import org.chromium.chrome.browser.incognito.IncognitoNotificationManager;
+import org.chromium.chrome.browser.incognito.IncognitoNotificationService;
+import org.chromium.chrome.browser.incognito.IncognitoOnlyModeUtil;
+import org.chromium.chrome.browser.metrics.PageLoadMetrics;
+import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabDelegateFactory;
import org.chromium.chrome.browser.tab.TabUma.TabCreationState;
+import org.chromium.chrome.browser.tabmodel.EmptyTabModel;
+import org.chromium.chrome.browser.tabmodel.EmptyTabModelObserver;
import org.chromium.chrome.browser.tabmodel.SingleTabModelSelector;
import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
+import org.chromium.chrome.browser.tabmodel.TabModelObserver;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.tabmodel.document.TabDelegate;
import org.chromium.content_public.browser.ChildProcessImportance;
@@ -38,7 +51,8 @@ public abstract class SingleTabActivity extends ChromeActivity {
@Override
protected TabModelSelector createTabModelSelector() {
- return new SingleTabModelSelector(this, false, false) {
+ boolean incognitoOnly = IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled();
+ return new SingleTabModelSelector(this, incognitoOnly, false) {
@Override
public Tab openNewTab(LoadUrlParams loadUrlParams, TabLaunchType type, Tab parent,
boolean incognito) {
@@ -81,6 +95,7 @@ public abstract class SingleTabActivity extends ChromeActivity {
*/
protected Tab createTab() {
Tab tab = null;
+ boolean incognitoOnly = IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled();
boolean unfreeze = false;
int tabId = Tab.INVALID_TAB_ID;
@@ -93,13 +108,14 @@ public abstract class SingleTabActivity extends ChromeActivity {
if (tabId != Tab.INVALID_TAB_ID && tabUrl != null && getActivityDirectory() != null) {
// Restore the tab.
TabState tabState = TabState.restoreTabState(getActivityDirectory(), tabId);
- tab = new Tab(tabId, Tab.INVALID_TAB_ID, false, getWindowAndroid(),
- TabLaunchType.FROM_RESTORE, TabCreationState.FROZEN_ON_RESTORE, tabState);
+ tab = new Tab(tabId, Tab.INVALID_TAB_ID, incognitoOnly, this, getWindowAndroid(),
+ TabLaunchType.FROM_RESTORE,
+ TabCreationState.FROZEN_ON_RESTORE, tabState);
unfreeze = true;
}
if (tab == null) {
- tab = new Tab(Tab.INVALID_TAB_ID, Tab.INVALID_TAB_ID, false, getWindowAndroid(),
+ tab = new Tab(Tab.INVALID_TAB_ID, Tab.INVALID_TAB_ID, incognitoOnly, this, getWindowAndroid(),
TabLaunchType.FROM_CHROME_UI, null, null);
}
@@ -137,4 +153,31 @@ public abstract class SingleTabActivity extends ChromeActivity {
@Override
public void onCheckForUpdate(boolean updateAvailable) {}
+
+ private void handleTabClose() {
+ boolean incognitoOnly = IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled();
+ if (incognitoOnly && isInitialized()) {
+ destroyIncognitoIfNecessary();
+ }
+ }
+
+ protected void destroyIncognitoIfNecessary() {
+ ThreadUtils.assertOnUiThread();
+
+ Profile profile = getTabModelSelector().getModel(true).getProfile();
+ // destroy the current tabmodel that will destroy tabs internally
+ getCurrentTabModel().destroy();
+ // Only delete the incognito profile if there are no incognito tabs open in any tab
+ // model selector as the profile is shared between them.
+ if (profile != null && !(IncognitoNotificationService.getIncognitoTabCount() > 0)) {
+ profile.destroyWhenAppropriate();
+ IncognitoNotificationManager.dismissIncognitoNotification();
+ }
+
+ }
+
+ @Override
+ protected void onDestroyInternal() {
+ handleTabClose();
+ }
}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java b/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java
index afc92bed..39caa0b 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/WarmupManager.java
@@ -31,6 +31,7 @@ import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.widget.ControlContainer;
import org.chromium.content_public.browser.WebContents;
import org.chromium.content_public.browser.WebContentsObserver;
+import org.chromium.chrome.browser.incognito.IncognitoOnlyModeUtil;
import java.net.InetAddress;
import java.net.MalformedURLException;
@@ -289,8 +290,9 @@ public final class WarmupManager {
public void createSpareWebContents() {
ThreadUtils.assertOnUiThread();
if (!LibraryLoader.isInitialized()) return;
+ boolean incognitoOnly = IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled();
if (mSpareWebContents != null || SysUtils.isLowEndDevice()) return;
- mSpareWebContents = WebContentsFactory.createWebContentsWithWarmRenderer(false, false);
+ mSpareWebContents = WebContentsFactory.createWebContentsWithWarmRenderer(incognitoOnly, false);
mObserver = new RenderProcessGoneObserver();
mSpareWebContents.addObserver(mObserver);
mWebContentsCreationTimeMs = SystemClock.elapsedRealtime();
@@ -316,7 +318,7 @@ public final class WarmupManager {
*/
public WebContents takeSpareWebContents(boolean incognito, boolean initiallyHidden) {
ThreadUtils.assertOnUiThread();
- if (incognito || initiallyHidden) return null;
+ if ((incognito != mSpareWebContents.isIncognito()) || initiallyHidden) return null;
WebContents result = mSpareWebContents;
if (result == null) return null;
mSpareWebContents = null;
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java
index e48a3e8..5435958 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/appmenu/AppMenuPropertiesDelegate.java
@@ -29,6 +29,7 @@ import org.chromium.chrome.browser.UrlConstants;
import org.chromium.chrome.browser.banners.AppBannerManager;
import org.chromium.chrome.browser.bookmarks.BookmarkBridge;
import org.chromium.chrome.browser.download.DownloadUtils;
+import org.chromium.chrome.browser.incognito.IncognitoOnlyModeUtil;
import org.chromium.chrome.browser.multiwindow.MultiWindowUtils;
import org.chromium.chrome.browser.omaha.UpdateMenuItemHelper;
import org.chromium.chrome.browser.preferences.ManagedPreferencesUtils;
@@ -175,6 +176,8 @@ public class AppMenuPropertiesDelegate {
MenuItem allBookmarksMenuItem = menu.findItem(R.id.all_bookmarks_menu_id);
// Hide 'History' in incognito only browser
+ boolean isIncognitoOnlyBrowser = IncognitoOnlyModeUtil.getInstance()
+ .isIncognitoOnlyBrowser();
menu.findItem(R.id.open_history_menu_id).setVisible(!isIncognitoOnlyBrowser);
allBookmarksMenuItem.setTitle(mActivity.getString(R.string.menu_bookmarks));
@@ -201,7 +204,7 @@ public class AppMenuPropertiesDelegate {
// is not persisted when adding to the homescreen.
// * If creating shortcuts it not supported by the current home screen.
boolean canShowHomeScreenMenuItem = ShortcutHelper.isAddToHomeIntentSupported()
- && !isChromeScheme && !isFileScheme && !isContentScheme && !isIncognito
+ && !isChromeScheme && !isFileScheme && !isContentScheme && (!isIncognito || isIncognitoOnlyBrowser)
&& !TextUtils.isEmpty(url);
prepareAddToHomescreenMenuItem(menu, currentTab, canShowHomeScreenMenuItem);
@@ -224,7 +227,8 @@ public class AppMenuPropertiesDelegate {
}
if (isOverviewMenu) {
- if (isIncognito) {
+ if (isIncognito
+ && !(IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled())) {
// Hide normal close all tabs item.
menu.findItem(R.id.close_all_tabs_menu_id).setVisible(false);
// Enable close incognito tabs only if there are incognito tabs.
@@ -244,6 +248,7 @@ public class AppMenuPropertiesDelegate {
}
boolean incognitoMenuItemVisible = !isBottomSheetNtpMenu || !isIncognito;
+ incognitoMenuItemVisible &= !(IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled());
// Disable new incognito tab when it is blocked (e.g. by a policy).
// findItem(...).setEnabled(...)" is not enough here, because of the inflated
// main_menu.xml contains multiple items with the same id in different groups
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java
index 03edf2d..fb2cc2e 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/StackLayout.java
@@ -33,6 +33,7 @@ import org.chromium.chrome.browser.compositor.scene_layer.SceneLayer;
import org.chromium.chrome.browser.compositor.scene_layer.TabListSceneLayer;
import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
import org.chromium.chrome.browser.partnercustomizations.HomepageManager;
+import org.chromium.chrome.browser.incognito.IncognitoOnlyModeUtil;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
@@ -328,8 +329,10 @@ public class StackLayout extends Layout implements Animatable<StackLayout.Proper
@Override
public void setTabModelSelector(TabModelSelector modelSelector, TabContentManager manager) {
super.setTabModelSelector(modelSelector, manager);
- mStacks[0].setTabModel(modelSelector.getModel(false));
- mStacks[1].setTabModel(modelSelector.getModel(true));
+ mStacks[0].setTabModel(modelSelector
+ .getModel(IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled()));
+ mStacks[1].setTabModel(modelSelector
+ .getModel(!IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled()));
resetScrollData();
}
@@ -341,6 +344,9 @@ public class StackLayout extends Layout implements Animatable<StackLayout.Proper
* @VisibleForTesting
*/
public Stack getTabStack(boolean incognito) {
+ if (IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled()) {
+ return mStacks[incognito ? 0 : 1];
+ }
return mStacks[incognito ? 1 : 0];
}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java
index 8230bc2..687c8a4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/layouts/phone/stack/Stack.java
@@ -21,6 +21,7 @@ import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
import org.chromium.chrome.browser.compositor.layouts.eventfilter.ScrollDirection;
import org.chromium.chrome.browser.compositor.layouts.phone.StackLayout;
import org.chromium.chrome.browser.compositor.layouts.phone.stack.StackAnimation.OverviewAnimationType;
+import org.chromium.chrome.browser.incognito.IncognitoOnlyModeUtil;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.browser.tabmodel.TabModelUtils;
@@ -436,7 +437,9 @@ public class Stack {
* @return Whether or not the TabModel represented by this TabStackState should be displayed.
*/
public boolean isDisplayable() {
- return !mTabModel.isIncognito() || (!mIsDying && mTabModel.getCount() > 0);
+ return (!mTabModel.isIncognito()
+ && !IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled())
+ || (!mIsDying && mTabModel.getCount() > 0);
}
private float getDefaultDiscardDirection() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
index 25f1fd7..6257c82 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/compositor/overlays/strip/StripLayoutHelperManager.java
@@ -23,6 +23,7 @@ import org.chromium.chrome.browser.compositor.layouts.eventfilter.GestureHandler
import org.chromium.chrome.browser.compositor.overlays.SceneOverlay;
import org.chromium.chrome.browser.compositor.scene_layer.SceneOverlayLayer;
import org.chromium.chrome.browser.compositor.scene_layer.TabStripSceneLayer;
+import org.chromium.chrome.browser.incognito.IncognitoOnlyModeUtil;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.TabCreatorManager;
import org.chromium.chrome.browser.tabmodel.TabModel;
@@ -377,7 +378,8 @@ public class StripLayoutHelperManager implements SceneOverlay {
mModelSelectorButton.setIncognito(mIsIncognito);
if (mTabModelSelector != null) {
boolean isVisible = mTabModelSelector.getModel(true).getCount() != 0;
- mModelSelectorButton.setVisible(isVisible);
+ mModelSelectorButton.setVisible(isVisible
+ && !IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled());
float endMargin = isVisible
? MODEL_SELECTOR_BUTTON_WIDTH_DP + MODEL_SELECTOR_BUTTON_END_PADDING_DP
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
index 43b556f..2b92e83 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/customtabs/CustomTabActivity.java
@@ -59,9 +59,13 @@ import org.chromium.chrome.browser.browserservices.BrowserSessionContentUtils;
import org.chromium.chrome.browser.compositor.layouts.LayoutManager;
import org.chromium.chrome.browser.datausage.DataUseTabUIManager;
import org.chromium.chrome.browser.externalnav.ExternalNavigationDelegateImpl;
+import org.chromium.chrome.browser.incognito.IncognitoOnlyModeUtil;
import org.chromium.chrome.browser.firstrun.FirstRunSignInProcessor;
import org.chromium.chrome.browser.fullscreen.BrowserStateBrowserControlsVisibilityDelegate;
import org.chromium.chrome.browser.gsa.GSAState;
+import org.chromium.chrome.browser.incognito.IncognitoNotificationManager;
+import org.chromium.chrome.browser.incognito.IncognitoNotificationService;
+import org.chromium.chrome.browser.incognito.IncognitoOnlyModeUtil;
import org.chromium.chrome.browser.metrics.PageLoadMetrics;
import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
import org.chromium.chrome.browser.page_info.PageInfoPopup;
@@ -334,7 +338,12 @@ public class CustomTabActivity extends ChromeActivity {
if (mConnection.shouldHideDomainForSession(mSession)) {
getToolbarManager().setUrlBarHidden(true);
}
+ boolean incognitoOnly = IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled();
int toolbarColor = mIntentDataProvider.getToolbarColor();
+ if (incognitoOnly) {
+ toolbarColor = ApiCompatibilityUtils.getColor(getResources(),
+ R.color.incognito_primary_color);
+ }
getToolbarManager().updatePrimaryColor(toolbarColor, false);
if (!mIntentDataProvider.isOpenedByChrome()) {
getToolbarManager().setShouldUpdateToolbarPrimaryColor(false);
@@ -390,7 +399,8 @@ public class CustomTabActivity extends ChromeActivity {
mConnection.cancelSpeculation(mSession);
}
- getTabModelSelector().getModel(false).addObserver(mTabModelObserver);
+ boolean incognitoOnly = IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled();
+ getTabModelSelector().getModel(incognitoOnly).addObserver(mTabModelObserver);
boolean successfulStateRestore = false;
// Attempt to restore the previous tab state if applicable.
@@ -412,7 +422,7 @@ public class CustomTabActivity extends ChromeActivity {
} else {
mMainTab = createMainTab();
}
- getTabModelSelector().getModel(false).addTab(mMainTab, 0, mMainTab.getLaunchType());
+ getTabModelSelector().getModel(incognitoOnly).addTab(mMainTab, 0, mMainTab.getLaunchType());
}
// This cannot be done before because we want to do the reparenting only
@@ -550,7 +560,9 @@ public class CustomTabActivity extends ChromeActivity {
getIntent(), IntentHandler.EXTRA_TAB_ID, Tab.INVALID_TAB_ID);
int parentTabId = IntentUtils.safeGetIntExtra(
getIntent(), IntentHandler.EXTRA_PARENT_TAB_ID, Tab.INVALID_TAB_ID);
- Tab tab = new Tab(assignedTabId, parentTabId, false, getWindowAndroid(),
+
+ boolean incognitoOnly = IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled();
+ Tab tab = new Tab(assignedTabId, parentTabId, incognitoOnly, getWindowAndroid(),
TabLaunchType.FROM_EXTERNAL_APP, null, null);
if (getIntent().getIntExtra(
CustomTabIntentDataProvider.EXTRA_BROWSER_LAUNCH_SOURCE, ACTIVITY_TYPE_OTHER)
@@ -588,12 +600,12 @@ public class CustomTabActivity extends ChromeActivity {
webContentsStateOnLaunch = WEBCONTENTS_STATE_TRANSFERRED_WEBCONTENTS;
webContents.resumeLoadingCreatedWebContents();
} else {
- webContents = WarmupManager.getInstance().takeSpareWebContents(false, false);
+ webContents = WarmupManager.getInstance().takeSpareWebContents(IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled(), false);
if (webContents != null) {
webContentsStateOnLaunch = WEBCONTENTS_STATE_SPARE_WEBCONTENTS;
} else {
webContents =
- WebContentsFactory.createWebContentsWithWarmRenderer(false, false);
+ WebContentsFactory.createWebContentsWithWarmRenderer(IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled(), false);
webContentsStateOnLaunch = WEBCONTENTS_STATE_NO_WEBCONTENTS;
}
}
@@ -835,6 +847,13 @@ public class CustomTabActivity extends ChromeActivity {
if (getAppMenuHandler() != null) getAppMenuHandler().hideAppMenu();
super.finish();
+ boolean incognitoOnly = IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled();
+ if (incognitoOnly) {
+ int incognitoCount = IncognitoNotificationService.getIncognitoTabCount();
+ if (incognitoCount == 0) {
+ IncognitoNotificationManager.dismissIncognitoNotification();
+ }
+ }
if (mIntentDataProvider != null && mIntentDataProvider.shouldAnimateOnFinish()) {
mShouldOverridePackage = true;
overridePendingTransition(mIntentDataProvider.getAnimationEnterRes(),
@@ -853,7 +872,8 @@ public class CustomTabActivity extends ChromeActivity {
public final void finishAndClose(boolean reparenting) {
if (mIsClosing) return;
mIsClosing = true;
- if (!reparenting) {
+ boolean incognitoOnly = IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled();
+ if (!reparenting && !incognitoOnly) {
// Closing the activity destroys the renderer as well. Re-create a spare renderer some
// time after, so that we have one ready for the next tab open. This does not increase
// memory consumption, as the current renderer goes away. We create a renderer as a lot
@@ -1025,7 +1045,8 @@ public class CustomTabActivity extends ChromeActivity {
protected void setStatusBarColor(Tab tab, int color) {
// Intentionally do nothing as CustomTabActivity explicitly sets status bar color. Except
// for Custom Tabs opened by Chrome.
- if (mIntentDataProvider.isOpenedByChrome()) super.setStatusBarColor(tab, color);
+ boolean incognitoOnly = IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled();
+ if (mIntentDataProvider.isOpenedByChrome() && !incognitoOnly) super.setStatusBarColor(tab, color);
}
/**
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoNotificationService.java b/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoNotificationService.java
index f9e91ad..3e9bd1c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoNotificationService.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoNotificationService.java
@@ -6,6 +6,7 @@ package org.chromium.chrome.browser.incognito;
import android.annotation.TargetApi;
import android.app.Activity;
+import android.util.SparseArray;
import android.app.ActivityManager;
import android.app.ActivityManager.AppTask;
import android.app.ActivityManager.RecentTaskInfo;
@@ -24,15 +25,21 @@ import org.chromium.base.ContextUtils;
import org.chromium.base.ThreadUtils;
import org.chromium.base.VisibleForTesting;
import org.chromium.base.library_loader.LibraryProcessType;
+import org.chromium.chrome.browser.ChromeActivity;
+import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.ChromeTabbedActivity;
import org.chromium.chrome.browser.TabState;
+import org.chromium.chrome.browser.customtabs.CustomTabActivity;
import org.chromium.chrome.browser.document.ChromeLauncherActivity;
import org.chromium.chrome.browser.document.DocumentUtils;
import org.chromium.chrome.browser.profiles.Profile;
+import org.chromium.chrome.browser.tabmodel.AsyncTabParams;
+import org.chromium.chrome.browser.tabmodel.AsyncTabParamsManager;
import org.chromium.chrome.browser.tabmodel.TabWindowManager;
import org.chromium.chrome.browser.tabmodel.TabbedModeTabPersistencePolicy;
import org.chromium.chrome.browser.widget.bottomsheet.BottomSheet;
import org.chromium.content.browser.BrowserStartupController;
+import org.chromium.chrome.browser.webapps.WebappActivity;
import java.io.File;
import java.lang.ref.WeakReference;
@@ -189,7 +196,9 @@ public class IncognitoNotificationService extends IntentService {
for (int i = 0; i < runningActivities.size(); i++) {
Activity activity = runningActivities.get(i).get();
if (activity == null) continue;
- if (!(activity instanceof ChromeTabbedActivity)) continue;
+ if (!(activity instanceof ChromeTabbedActivity ||
+ activity instanceof CustomTabActivity ||
+ activity instanceof WebappActivity)) continue;
ChromeTabbedActivity tabbedActivity = (ChromeTabbedActivity) activity;
if (tabbedActivity.isActivityDestroyed()) continue;
@@ -205,7 +214,7 @@ public class IncognitoNotificationService extends IntentService {
BottomSheet.SHEET_STATE_PEEK, false);
}
- tabbedActivity.getTabModelSelector().getModel(true).closeAllTabs(
+ chromeActivity.getTabModelSelector().getModel(true).closeAllTabs(
false, false);
}
}
@@ -229,4 +238,30 @@ public class IncognitoNotificationService extends IntentService {
return deletionSuccessful;
}
+ public static int getIncognitoTabCount() {
+ int count = 0;
+ List<WeakReference<Activity>> runningActivities =
+ ApplicationStatus.getRunningActivities();
+ for (int i = 0; i < runningActivities.size(); i++) {
+ Activity activity = runningActivities.get(i).get();
+ if (activity == null) continue;
+ if (!(activity instanceof ChromeTabbedActivity ||
+ activity instanceof CustomTabActivity ||
+ activity instanceof WebappActivity)) continue;
+
+ ChromeActivity chromeActivity = (ChromeActivity) activity;
+ if (chromeActivity.isActivityDestroyed()) continue;
+
+ count += chromeActivity.getTabModelSelector().getModel(true).getCount();
+ }
+ // Count tabs that are moving between activities (e.g. a tab that was recently reparented
+ // and hasn't been attached to its new activity yet).
+ SparseArray<AsyncTabParams> asyncTabParams = AsyncTabParamsManager.getAsyncTabParams();
+ for (int i = 0; i < asyncTabParams.size(); i++) {
+ Tab tab = asyncTabParams.valueAt(i).getTabToReparent();
+ if (tab != null && tab.isIncognito()) count++;
+ }
+ return count;
+ }
+
}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoOnlyModeUtil.java b/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoOnlyModeUtil.java
new file mode 100644
index 0000000..f6b17e7
--- /dev/null
+++ b/chrome/android/java/src/org/chromium/chrome/browser/incognito/IncognitoOnlyModeUtil.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2016, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following
+ * disclaimer in the documentation and/or other materials provided
+ * with the distribution.
+ * * Neither the name of The Linux Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+package org.chromium.chrome.browser.incognito;
+
+import org.chromium.base.CommandLine;
+import org.chromium.base.ContextUtils;
+import org.chromium.chrome.browser.ChromeSwitches;
+import org.chromium.chrome.browser.preferences.privacy.PrivacyPreferencesManager;
+
+/**
+ * Utility class for incognito only mode
+ */
+public class IncognitoOnlyModeUtil {
+ private static IncognitoOnlyModeUtil sInstance;
+
+ private IncognitoOnlyModeUtil() {}
+
+ public static IncognitoOnlyModeUtil getInstance() {
+ if (sInstance == null) {
+ sInstance = new IncognitoOnlyModeUtil();
+ }
+ return sInstance;
+ }
+ /**
+ * @return whether incognito only browser
+ */
+ public boolean isIncognitoOnlyBrowser() {
+ return CommandLine.getInstance().hasSwitch(ChromeSwitches.INCOGNITO_ONLY_MODE);
+ }
+
+ /**
+ * @return whether incognito only mode preference is enabled
+ */
+ public boolean isIncognitoOnlyPreferenceEnabled() {
+ return PrivacyPreferencesManager.getInstance(ContextUtils.getApplicationContext()).
+ isIncognitoOnlyEnabled();
+ }
+
+ /**
+ * @return whether incognito only browser or incognito only mode preference is enabled
+ */
+ public boolean isIncognitoOnlyModeEnabled() {
+ return isIncognitoOnlyBrowser() || isIncognitoOnlyPreferenceEnabled();
+ }
+
+}
\ No newline at end of file
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
index e594c57..def79eb 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/omnibox/LocationBarPhone.java
@@ -20,6 +20,7 @@ import android.widget.FrameLayout;
import org.chromium.base.ApiCompatibilityUtils;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.WindowDelegate;
+import org.chromium.chrome.browser.incognito.IncognitoOnlyModeUtil;
import org.chromium.chrome.browser.ntp.NewTabPage;
import org.chromium.chrome.browser.toolbar.ToolbarDataProvider;
import org.chromium.chrome.browser.util.MathUtils;
@@ -271,7 +272,8 @@ public class LocationBarPhone extends LocationBarLayout {
boolean showIncognitoBadge =
getToolbarDataProvider() != null && getToolbarDataProvider().isIncognito();
- mIncognitoBadge.setVisibility(showIncognitoBadge ? VISIBLE : GONE);
+ mIncognitoBadge.setVisibility(showIncognitoBadge
+ && !IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled() ? VISIBLE : GONE);
updateIncognitoBadgePadding();
}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferences.java
index 0d78e7c..b1b9f67 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferences.java
@@ -4,6 +4,8 @@
package org.chromium.chrome.browser.preferences.privacy;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
@@ -18,8 +20,11 @@ import org.chromium.base.SysUtils;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.ChromeFeatureList;
+import org.chromium.chrome.browser.ApplicationLifetime;
+import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.contextualsearch.ContextualSearchFieldTrial;
import org.chromium.chrome.browser.help.HelpAndFeedback;
+import org.chromium.chrome.browser.incognito.IncognitoOnlyModeUtil;
import org.chromium.chrome.browser.physicalweb.PhysicalWeb;
import org.chromium.chrome.browser.preferences.ChromeBaseCheckBoxPreference;
import org.chromium.chrome.browser.preferences.ManagedPreferenceDelegate;
@@ -41,6 +46,7 @@ public class PrivacyPreferences extends PreferenceFragment
private static final String PREF_SAFE_BROWSING = "safe_browsing";
private static final String PREF_CONTEXTUAL_SEARCH = "contextual_search";
private static final String PREF_NETWORK_PREDICTIONS = "network_predictions";
+ private static final String PREF_INCOGNITO_ONLY = "incognito_only";
private static final String PREF_DO_NOT_TRACK = "do_not_track";
private static final String PREF_USAGE_AND_CRASH_REPORTING = "usage_and_crash_reports";
private static final String PREF_PHYSICAL_WEB = "physical_web";
@@ -129,6 +135,18 @@ public class PrivacyPreferences extends PreferenceFragment
recordNetworkPredictionEnablingUMA((boolean) newValue);
} else if (PREF_NAVIGATION_ERROR.equals(key)) {
PrefServiceBridge.getInstance().setResolveNavigationErrorEnabled((boolean) newValue);
+ } else if (PREF_INCOGNITO_ONLY.equals(key)) {
+ incognitoOnlyPreferenceDialog(preference, (boolean) newValue).show();
+ }
+
+ boolean isIncognitoOnlyBrowser = IncognitoOnlyModeUtil.getInstance()
+ .isIncognitoOnlyBrowser();
+ ChromeBaseCheckBoxPreference incognitoOnlyPref =
+ (ChromeBaseCheckBoxPreference) findPreference(PREF_INCOGNITO_ONLY);
+ if (isIncognitoOnlyBrowser) {
+ preferenceScreen.removePreference(incognitoOnlyPref);
+ } else {
+ incognitoOnlyPref.setOnPreferenceChangeListener(this);
}
return true;
@@ -189,6 +207,13 @@ public class PrivacyPreferences extends PreferenceFragment
doNotTrackPref.setSummary(prefServiceBridge.isDoNotTrackEnabled() ? textOn : textOff);
}
+ Preference incognitoOnlyPref = findPreference(PREF_INCOGNITO_ONLY);
+ if (incognitoOnlyPref != null) {
+ boolean isIncognitoOnlyEnabled = privacyPrefManager.isIncognitoOnlyEnabled();
+ incognitoOnlyPref.setChecked(isIncognitoOnlyEnabled);
+ incognitoOnlyPref.setSummary(isIncognitoOnlyEnabled ? textOn : textOff);
+ }
+
Preference contextualPref = findPreference(PREF_CONTEXTUAL_SEARCH);
if (contextualPref != null) {
boolean isContextualSearchEnabled = !prefServiceBridge.isContextualSearchDisabled();
@@ -254,4 +279,38 @@ public class PrivacyPreferences extends PreferenceFragment
}
return false;
}
+
+ private AlertDialog incognitoOnlyPreferenceDialog(final Preference preference,
+ final boolean isChecked) {
+ AlertDialog dialog = new AlertDialog.Builder(getActivity(), R.style.AlertDialogTheme)
+ .setTitle(isChecked ? R.string.incognito_only_turn_on_title
+ : R.string.incognito_only_turn_off_title)
+ .setMessage(isChecked ? R.string.incognito_only_turn_on_confirmation
+ : R.string.incognito_only_turn_off_confirmation)
+ .setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int id) {
+ ((ChromeBaseCheckBoxPreference) preference).setChecked(!isChecked);
+ dialog.dismiss();
+ }
+ })
+ .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ PrivacyPreferencesManager.getInstance(getActivity()).
+ setIncognitoOnlyEnabled((boolean) isChecked);
+ dialog.dismiss();
+ ApplicationLifetime.terminate(true);
+ }
+ })
+ .setOnCancelListener(new DialogInterface.OnCancelListener() {
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ ((ChromeBaseCheckBoxPreference) preference).setChecked(!isChecked);
+ }
+ })
+ .create();
+
+ return dialog;
+ }
}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java
index 4ddbd4d..9e2a163 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/privacy/PrivacyPreferencesManager.java
@@ -38,6 +38,7 @@ public class PrivacyPreferencesManager implements CrashReportingPermissionManage
private static final String PREF_BANDWIDTH_NO_CELLULAR_OLD = "prefetch_bandwidth_no_cellular";
private static final String ALLOW_PRERENDER_OLD = "allow_prefetch";
private static final String PREF_PHYSICAL_WEB = "physical_web";
+ private static final String INCOGNITO_ONLY_PREFERENCE = "incognito_only_preference";
private static final int PHYSICAL_WEB_OFF = 0;
private static final int PHYSICAL_WEB_ON = 1;
private static final int PHYSICAL_WEB_ONBOARDING = 2;
@@ -339,4 +340,23 @@ public class PrivacyPreferencesManager implements CrashReportingPermissionManage
int state = mSharedPreferences.getInt(PREF_PHYSICAL_WEB, PHYSICAL_WEB_ONBOARDING);
return (state == PHYSICAL_WEB_ON);
}
+
+ /**
+ * Check whether Incognito Only preference is enabled
+ *
+ * @return whether Incognito Only preference is enabled, false by default
+ */
+ public boolean isIncognitoOnlyEnabled() {
+ return mSharedPreferences.getBoolean(INCOGNITO_ONLY_PREFERENCE, false);
+ }
+
+ /**
+ * Sets the Incognito Only preference, which enables the browser to switch to incognito only
+ * mode
+ *
+ * @param enabled A boolean indicating whether to switch to incognito only mode.
+ */
+ public void setIncognitoOnlyEnabled(boolean enabled) {
+ mSharedPreferences.edit().putBoolean(INCOGNITO_ONLY_PREFERENCE, enabled).apply();
+ }
}
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferences.java b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferences.java
index 344a2ed..d54accf 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferences.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/preferences/website/SiteSettingsPreferences.java
@@ -17,6 +17,7 @@ import org.chromium.chrome.browser.net.spdyproxy.DataReductionProxySettings;
import org.chromium.chrome.browser.preferences.LocationSettings;
import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import org.chromium.chrome.browser.preferences.PreferenceUtils;
+import org.chromium.chrome.browser.incognito.IncognitoOnlyModeUtil;
import java.util.ArrayList;
import java.util.List;
@@ -110,6 +111,13 @@ public class SiteSettingsPreferences extends PreferenceFragment
}
private void configurePreferences() {
+ // Remove 'All sites' menu for incognito only browser
+ boolean isIncognitoOnlyBrowser = IncognitoOnlyModeUtil.getInstance()
+ .isIncognitoOnlyBrowser();
+ if (isIncognitoOnlyBrowser) {
+ getPreferenceScreen().removePreference(findPreference(ALL_SITES_KEY));
+ }
+
if (mMediaSubMenu) {
// The Media sub-menu only contains Protected Content and Autoplay, so remove all other
// menus.
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/snackbar/undo/UndoBarController.java b/chrome/android/java/src/org/chromium/chrome/browser/snackbar/undo/UndoBarController.java
index d90ccc3..ddc30f2 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/snackbar/undo/UndoBarController.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/snackbar/undo/UndoBarController.java
@@ -9,6 +9,7 @@ import android.content.Context;
import org.chromium.base.metrics.RecordHistogram;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.device.DeviceClassManager;
+import org.chromium.chrome.browser.incognito.IncognitoOnlyModeUtil;
import org.chromium.chrome.browser.snackbar.Snackbar;
import org.chromium.chrome.browser.snackbar.SnackbarManager;
import org.chromium.chrome.browser.tab.Tab;
@@ -64,7 +65,8 @@ public class UndoBarController implements SnackbarManager.SnackbarController {
mTabModelObserver = new EmptyTabModelObserver() {
private boolean disableUndo() {
return AccessibilityUtil.isAccessibilityEnabled()
- || DeviceClassManager.enableAccessibilityLayout();
+ || DeviceClassManager.enableAccessibilityLayout()
+ || IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled();
}
@Override
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModel.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModel.java
index c3e7aa0..b1d758c 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModel.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/IncognitoTabModel.java
@@ -7,6 +7,7 @@ package org.chromium.chrome.browser.tabmodel;
import org.chromium.base.ObserverList;
import org.chromium.base.ThreadUtils;
import org.chromium.chrome.browser.incognito.IncognitoNotificationManager;
+import org.chromium.chrome.browser.incognito.IncognitoNotificationService;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.tab.Tab;
@@ -82,7 +83,7 @@ public class IncognitoTabModel implements TabModel {
// Only delete the incognito profile if there are no incognito tabs open in any tab
// model selector as the profile is shared between them.
- if (profile != null && !mDelegate.doIncognitoTabsExist()) {
+ if (profile != null && !(IncognitoNotificationService.getIncognitoTabCount() > 0)) {
IncognitoNotificationManager.dismissIncognitoNotification();
profile.destroyWhenAppropriate();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java
index 5221244..c976cd4 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabModelSelectorBase.java
@@ -5,6 +5,7 @@
package org.chromium.chrome.browser.tabmodel;
import org.chromium.base.ObserverList;
+import org.chromium.chrome.browser.incognito.IncognitoOnlyModeUtil;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.TabModel.TabLaunchType;
import org.chromium.chrome.browser.tabmodel.TabModel.TabSelectionType;
@@ -40,7 +41,8 @@ public abstract class TabModelSelectorBase implements TabModelSelector {
for (int i = 0; i < models.length; i++) {
tabModels.add(models[i]);
}
- mActiveModelIndex = startIncognito ? INCOGNITO_TAB_MODEL_INDEX : NORMAL_TAB_MODEL_INDEX;
+ mActiveModelIndex = (startIncognito ||
+ IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled()) ? INCOGNITO_TAB_MODEL_INDEX : NORMAL_TAB_MODEL_INDEX;
mTabModels = Collections.unmodifiableList(tabModels);
TabModelObserver tabModelObserver = new EmptyTabModelObserver() {
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/DocumentTabModelSelector.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/DocumentTabModelSelector.java
index e69d43c..71893ff 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/DocumentTabModelSelector.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/document/DocumentTabModelSelector.java
@@ -14,6 +14,7 @@ import android.os.Build;
import org.chromium.base.ContextUtils;
import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.browser.document.DocumentUtils;
+import org.chromium.chrome.browser.incognito.IncognitoNotificationService;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabIdManager;
import org.chromium.chrome.browser.tabmodel.IncognitoTabModel.IncognitoTabModelDelegate;
@@ -105,7 +106,7 @@ public class DocumentTabModelSelector extends TabModelSelectorBase implements Ta
public boolean doIncognitoTabsExist() {
// TODO(dfalcantara): Devices in document mode do not trigger the TabWindowManager.
// Revisit this when we have a Samsung L multi-instance device.
- return mIncognitoTabModel.getCount() > 0;
+ return IncognitoNotificationService.getIncognitoTabCount() > 0;
}
}, mActivityDelegate);
initializeTabIdCounter();
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
index 26bb763..b01a165 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/webapps/WebappActivity.java
@@ -52,6 +52,7 @@ import org.chromium.chrome.browser.customtabs.CustomTabsConnection;
import org.chromium.chrome.browser.document.ChromeLauncherActivity;
import org.chromium.chrome.browser.document.DocumentUtils;
import org.chromium.chrome.browser.fullscreen.ChromeFullscreenManager;
+import org.chromium.chrome.browser.incognito.IncognitoOnlyModeUtil;
import org.chromium.chrome.browser.tab.EmptyTabObserver;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tab.TabDelegateFactory;
@@ -814,6 +815,12 @@ public class WebappActivity extends SingleTabActivity {
mBrandColor = (int) mWebappInfo.themeColor();
}
+ boolean incognitoOnly = IncognitoOnlyModeUtil.getInstance().isIncognitoOnlyModeEnabled();
+ if (incognitoOnly) {
+ mBrandColor = ApiCompatibilityUtils.getColor(getResources(),
+ R.color.incognito_primary_color);
+ }
+
int taskDescriptionColor =
ApiCompatibilityUtils.getColor(getResources(), R.color.default_primary_color);
diff --git a/chrome/android/java/strings/android_chrome_strings.grd b/chrome/android/java/strings/android_chrome_strings.grd
index a81975d..f14b395 100644
--- a/chrome/android/java/strings/android_chrome_strings.grd
+++ b/chrome/android/java/strings/android_chrome_strings.grd
@@ -225,6 +225,26 @@ CHAR-LIMIT guidelines:
Retry
</message>
+ <!-- Incognito Only mode -->
+ <message name="IDS_INCOGNITO_ONLY_TITLE" desc="The label for incognito-only toggle option.">
+ &quot;Incognito Only&quot; mode
+ </message>
+ <message name="IDS_INCOGNITO_ONLY_SUMMARY" desc="The summary for incognito-only toggle option.">
+ Browse using only incognito tabs
+ </message>
+ <message name="IDS_INCOGNITO_ONLY_TURN_ON_TITLE" desc="The tooltip for enabling incognito-only mode.">
+ Enable &quot;Incognito Only&quot; mode
+ </message>
+ <message name="IDS_INCOGNITO_ONLY_TURN_OFF_TITLE" desc="The tooltip for disabling incognito-only mode.">
+ Disable &quot;Incognito Only&quot; mode
+ </message>
+ <message name="IDS_INCOGNITO_ONLY_TURN_ON_CONFIRMATION" desc="The confirmation message for turning on incognito-only mode.">
+ Browser will <ph name="BEGIN_BOLD">&lt;b&gt;</ph>restart<ph name="END_BOLD">&lt;/b&gt;</ph> in incognito-only mode. All opened tabs will be closed.
+ </message>
+ <message name="IDS_INCOGNITO_ONLY_TURN_OFF_CONFIRMATION" desc="The confirmation message for turning off incognito-only mode.">
+ Browser will <ph name="BEGIN_BOLD">&lt;b&gt;</ph>restart<ph name="END_BOLD">&lt;/b&gt;</ph> in regular mode. All opened tabs will be closed.
+ </message>
+
<!-- Main Preferences -->
<message name="IDS_PREFERENCES" desc="Title for Chrome's Settings.">
Settings
diff --git a/chrome/android/java_sources.gni b/chrome/android/java_sources.gni
index ba24b98..a576f9d 100644
--- a/chrome/android/java_sources.gni
+++ b/chrome/android/java_sources.gni
@@ -491,6 +491,7 @@ chrome_java_sources = [
"java/src/org/chromium/chrome/browser/identity/UuidBasedUniqueIdentificationGenerator.java",
"java/src/org/chromium/chrome/browser/incognito/IncognitoNotificationManager.java",
"java/src/org/chromium/chrome/browser/incognito/IncognitoNotificationService.java",
+ "java/src/org/chromium/chrome/browser/incognito/IncognitoOnlyModeUtil.java",
"java/src/org/chromium/chrome/browser/infobar/AppBannerInfoBarAndroid.java",
"java/src/org/chromium/chrome/browser/infobar/AppBannerInfoBarDelegateAndroid.java",
"java/src/org/chromium/chrome/browser/infobar/AutofillCreditCardFillingInfoBar.java",