975 lines
54 KiB
Diff
975 lines
54 KiB
Diff
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.">
|
|
+ "Incognito Only" 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 "Incognito Only" mode
|
|
+ </message>
|
|
+ <message name="IDS_INCOGNITO_ONLY_TURN_OFF_TITLE" desc="The tooltip for disabling incognito-only mode.">
|
|
+ Disable "Incognito Only" 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"><b></ph>restart<ph name="END_BOLD"></b></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"><b></ph>restart<ph name="END_BOLD"></b></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",
|