summaryrefslogtreecommitdiffstats
path: root/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassin.java
diff options
context:
space:
mode:
authordfalcantara <dfalcantara@chromium.org>2016-03-25 16:37:20 -0700
committerCommit bot <commit-bot@chromium.org>2016-03-25 23:40:01 +0000
commitde49c2d22f6c873aac94696ef004ecf8d8dd6b52 (patch)
treea8e840389d80424c9c3bc715a9cda864efa72dd7 /chrome/android/java/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassin.java
parent0e22e7e8fe94d4f4deadcb2d6460e6a1ca38cd35 (diff)
downloadchromium_src-de49c2d22f6c873aac94696ef004ecf8d8dd6b52.zip
chromium_src-de49c2d22f6c873aac94696ef004ecf8d8dd6b52.tar.gz
chromium_src-de49c2d22f6c873aac94696ef004ecf8d8dd6b52.tar.bz2
Add pathway to auto-migrate users when Chrome launches
* For now, a command line flag is required to trigger this pathway: --enable-forced-migration * UpgradeActivity kicks off the DocumentModeAssassin and waits for it to finish. This Activity can only be launched via other ChromeActivities, and can be passed an Intent to refire when the migration finishes. * A MAIN Intent or Intent to start a new DocumentActivity that goes through ChromeLauncherActivity will force users through UgpradeActivity, instead. This causes document mode to be flipped off, and anything going down the ChromeLauncherActivity pathway again should no longer trigger migration. This pathway catches new tabs created via VIEW Intents, MAIN Intents, CCT Intents, and (sometimes) WebappActivity Intents. * AsyncInitializationActivity watches for the need for the migration pathway to be triggered when a ChromeActivity subclass starts up. This pathway catches Intents that skip ChromeLauncherActivity, which includes ChromeTabbedActivity, DocumentActivity, CustomTabActivity, and WebappActivity. These can be launched directly by selecting them from Android Recents, or by firing Intents to bring them back specifically. * The look of this Activity is a stand-in for when we get redlines. The animation is also kind of janky, but I'm aiming for functionality at this point. * TabDelegate is no longer allowed to create new DocumentActivities, instead deferring down the ChromeLauncherActivity pathway. This catches cases with push notifications triggering a tab to be created when they're clicked. * The preference to enable document mode is hidden once the user has migrated. BUG=582539 Review URL: https://codereview.chromium.org/1817083003 Cr-Commit-Position: refs/heads/master@{#383406}
Diffstat (limited to 'chrome/android/java/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassin.java')
-rw-r--r--chrome/android/java/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassin.java81
1 files changed, 53 insertions, 28 deletions
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassin.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassin.java
index 89936ef..bc7e0ba 100644
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassin.java
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/DocumentModeAssassin.java
@@ -12,6 +12,7 @@ import android.os.Build;
import android.util.Pair;
import org.chromium.base.ApplicationStatus;
+import org.chromium.base.CommandLine;
import org.chromium.base.FileUtils;
import org.chromium.base.Log;
import org.chromium.base.ObserverList;
@@ -19,6 +20,7 @@ import org.chromium.base.StreamUtil;
import org.chromium.base.ThreadUtils;
import org.chromium.base.VisibleForTesting;
import org.chromium.chrome.browser.ChromeApplication;
+import org.chromium.chrome.browser.ChromeSwitches;
import org.chromium.chrome.browser.TabState;
import org.chromium.chrome.browser.document.DocumentActivity;
import org.chromium.chrome.browser.document.DocumentUtils;
@@ -42,6 +44,8 @@ import java.nio.channels.FileChannel;
import java.util.HashSet;
import java.util.Set;
+import javax.annotation.Nullable;
+
/**
* Divorces Chrome's tabs from Android's Overview menu. Assumes native libraries are unavailable.
*
@@ -52,7 +56,6 @@ import java.util.Set;
* into the tabbed mode directory. Incognito tabs are silently dropped, as with the previous
* migration pathway.
*
- * TODO(dfalcantara): Check what happens if a user last viewed an Incognito tab.
* TODO(dfalcantara): Check what happens on other launchers.
*
* Once all TabState files are copied, a TabModel metadata file is written out for the tabbed
@@ -64,7 +67,6 @@ import java.util.Set;
* DocumentActivity tasks in Android's Recents are removed, TabState files in the document mode
* directory are deleted, and document mode preferences are cleared.
*
- * TODO(dfalcantara): Clean up the incognito notification, if possible.
* TODO(dfalcantara): Add histograms for tracking migration progress.
*
* TODO(dfalcantara): Potential pitfalls that need to be accounted for:
@@ -105,7 +107,7 @@ public class DocumentModeAssassin {
static final int STAGE_CHANGE_SETTINGS_STARTED = 6;
static final int STAGE_CHANGE_SETTINGS_DONE = 7;
static final int STAGE_DELETION_STARTED = 8;
- static final int STAGE_DONE = 9;
+ public static final int STAGE_DONE = 9;
private static final String TAG = "DocumentModeAssassin";
@@ -137,7 +139,8 @@ public class DocumentModeAssassin {
/** Returns whether or not a migration to tabbed mode from document mode is necessary. */
public static boolean isMigrationNecessary() {
- return FeatureUtilities.isDocumentMode(ApplicationStatus.getApplicationContext());
+ return CommandLine.getInstance().hasSwitch(ChromeSwitches.ENABLE_FORCED_MIGRATION)
+ && FeatureUtilities.isDocumentMode(ApplicationStatus.getApplicationContext());
}
/** Migrates the user from document mode to tabbed mode if necessary. */
@@ -165,18 +168,39 @@ public class DocumentModeAssassin {
*
* TODO(dfalcantara): Prevent migrating chrome:// pages?
*
- * @param selectedTabId ID of the last viewed non-Incognito tab.
- * @param documentDirectory File pointing at the DocumentTabModel TabState file directory.
- * @param tabbedDirectory File pointing at tabbed mode TabState file directory.
+ * @param selectedTabId ID of the last viewed non-Incognito tab.
+ * @param context Context to use when accessing directories.
+ * @param documentDirectoryOverride Overrides the default location for where document mode's
+ * TabState files are expected to be.
+ * @param tabbedDirectoryOverride Overrides the default location for where tabbed mode's
+ * TabState files are expected to be.
*/
- void copyTabStateFiles(
- final int selectedTabId, final File documentDirectory, final File tabbedDirectory) {
+ void copyTabStateFiles(final int selectedTabId, final Context context,
+ @Nullable final File documentDirectoryOverride,
+ @Nullable final File tabbedDirectoryOverride) {
ThreadUtils.assertOnUiThread();
if (!setStage(STAGE_INITIALIZED, STAGE_COPY_TAB_STATES_STARTED)) return;
new AsyncTask<Void, Void, Void>() {
+ private DocumentTabModelImpl mNormalTabModel;
+
+ @Override
+ protected void onPreExecute() {
+ if (documentDirectoryOverride == null) {
+ mNormalTabModel = (DocumentTabModelImpl)
+ ChromeApplication.getDocumentTabModelSelector().getModel(false);
+ }
+ }
+
@Override
protected Void doInBackground(Void... params) {
+ File documentDirectory = documentDirectoryOverride == null
+ ? mNormalTabModel.getStorageDelegate().getStateDirectory()
+ : documentDirectoryOverride;
+ File tabbedDirectory = tabbedDirectoryOverride == null
+ ? TabPersistentStore.getStateDirectory(context, TAB_MODEL_INDEX)
+ : tabbedDirectoryOverride;
+
Log.d(TAG, "Copying TabState files from document to tabbed mode directory.");
assert mMigratedTabIds.size() == 0;
@@ -186,11 +210,12 @@ public class DocumentModeAssassin {
// before all the other ones to mitigate storage issues for devices with limited
// available storage.
if (selectedTabId != Tab.INVALID_TAB_ID) {
- copyTabStateFilesInternal(allTabStates, selectedTabId, true);
+ copyTabStateFilesInternal(
+ allTabStates, tabbedDirectory, selectedTabId, true);
}
// Copy over everything else.
- copyTabStateFilesInternal(allTabStates, selectedTabId, false);
+ copyTabStateFilesInternal(allTabStates, tabbedDirectory, selectedTabId, false);
}
return null;
}
@@ -205,12 +230,13 @@ public class DocumentModeAssassin {
* Copies the files from the document mode directory to the tabbed mode directory.
*
* @param allTabStates Listing of all files in the document mode directory.
+ * @param tabbedDirectory Directory for the tabbed mode files.
* @param selectedTabId ID of the non-Incognito tab the user last viewed. May be
* {@link Tab#INVALID_TAB_ID} if the ID is unknown.
* @param copyOnlySelectedTab Copy only the TabState file for the selectedTabId.
*/
- private void copyTabStateFilesInternal(
- File[] allTabStates, int selectedTabId, boolean copyOnlySelectedTab) {
+ private void copyTabStateFilesInternal(File[] allTabStates, File tabbedDirectory,
+ int selectedTabId, boolean copyOnlySelectedTab) {
assert !ThreadUtils.runningOnUiThread();
for (int i = 0; i < allTabStates.length; i++) {
// Trawl the directory for non-Incognito TabState files.
@@ -281,12 +307,15 @@ public class DocumentModeAssassin {
* means that the user loses some navigation history, but it's not a case document mode would
* have been able to recover from anyway because the TabState stores the URL data.
*
- * @param tabbedDirectory Directory containing all of the main TabModel's files.
- * @param normalTabModel DocumentTabModel containing information about non-Incognito tabs.
- * @param migratedTabIds IDs of Tabs whose TabState files were copied successfully.
+ * @param normalTabModel DocumentTabModel containing info about non-Incognito tabs.
+ * @param migratedTabIds IDs of Tabs whose TabState files were copied successfully.
+ * @param context Context to access Files from.
+ * @param tabbedDirectoryOverride Overrides the default location for where tabbed mode's
+ * TabState files are expected to be.
*/
- void writeTabModelMetadata(final File tabbedDirectory, final DocumentTabModel normalTabModel,
- final Set<Integer> migratedTabIds) {
+ void writeTabModelMetadata(final DocumentTabModel normalTabModel,
+ final Set<Integer> migratedTabIds, final Context context,
+ @Nullable final File tabbedDirectoryOverride) {
ThreadUtils.assertOnUiThread();
if (!setStage(STAGE_COPY_TAB_STATES_DONE, STAGE_WRITE_TABMODEL_METADATA_STARTED)) return;
@@ -329,6 +358,9 @@ public class DocumentModeAssassin {
@Override
protected Boolean doInBackground(Void... params) {
if (mSerializedMetadata != null) {
+ File tabbedDirectory = tabbedDirectoryOverride == null
+ ? TabPersistentStore.getStateDirectory(context, TAB_MODEL_INDEX)
+ : tabbedDirectoryOverride;
TabPersistentStore.saveListToFile(tabbedDirectory, mSerializedMetadata);
return true;
} else {
@@ -440,22 +472,14 @@ public class DocumentModeAssassin {
Context context = ApplicationStatus.getApplicationContext();
if (newStage == STAGE_INITIALIZED) {
Log.d(TAG, "Migrating user into tabbed mode.");
- DocumentTabModelSelector selector = ChromeApplication.getDocumentTabModelSelector();
- DocumentTabModelImpl normalTabModel =
- (DocumentTabModelImpl) selector.getModel(false);
int selectedTabId = DocumentUtils.getLastShownTabIdFromPrefs(context, false);
-
- File documentDirectory = normalTabModel.getStorageDelegate().getStateDirectory();
- File tabbedDirectory = TabPersistentStore.getStateDirectory(context, TAB_MODEL_INDEX);
- copyTabStateFiles(selectedTabId, documentDirectory, tabbedDirectory);
+ copyTabStateFiles(selectedTabId, context, null, null);
} else if (newStage == STAGE_COPY_TAB_STATES_DONE) {
Log.d(TAG, "Writing tabbed mode metadata file.");
DocumentTabModelSelector selector = ChromeApplication.getDocumentTabModelSelector();
DocumentTabModelImpl normalTabModel =
(DocumentTabModelImpl) selector.getModel(false);
- File tabbedDirectory =
- TabPersistentStore.getStateDirectory(context, TAB_MODEL_INDEX);
- writeTabModelMetadata(tabbedDirectory, normalTabModel, mMigratedTabIds);
+ writeTabModelMetadata(normalTabModel, mMigratedTabIds, context, null);
} else if (newStage == STAGE_WRITE_TABMODEL_METADATA_DONE) {
Log.d(TAG, "Changing user preference.");
changePreferences(context);
@@ -471,6 +495,7 @@ public class DocumentModeAssassin {
*/
@VisibleForTesting
public int getStage() {
+ ThreadUtils.assertOnUiThread();
return mStage;
}