| OLD | NEW |
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 package org.chromium.chrome.browser.tabmodel; | 5 package org.chromium.chrome.browser.tabmodel; |
| 6 | 6 |
| 7 import android.annotation.TargetApi; | 7 import android.annotation.TargetApi; |
| 8 import android.content.Context; | 8 import android.content.Context; |
| 9 import android.content.SharedPreferences; | 9 import android.content.SharedPreferences; |
| 10 import android.os.AsyncTask; | 10 import android.os.AsyncTask; |
| 11 import android.os.Build; | 11 import android.os.Build; |
| 12 import android.util.Pair; | 12 import android.util.Pair; |
| 13 | 13 |
| 14 import org.chromium.base.ApplicationStatus; | 14 import org.chromium.base.ApplicationStatus; |
| 15 import org.chromium.base.CommandLine; |
| 15 import org.chromium.base.FileUtils; | 16 import org.chromium.base.FileUtils; |
| 16 import org.chromium.base.Log; | 17 import org.chromium.base.Log; |
| 17 import org.chromium.base.ObserverList; | 18 import org.chromium.base.ObserverList; |
| 18 import org.chromium.base.StreamUtil; | 19 import org.chromium.base.StreamUtil; |
| 19 import org.chromium.base.ThreadUtils; | 20 import org.chromium.base.ThreadUtils; |
| 20 import org.chromium.base.VisibleForTesting; | 21 import org.chromium.base.VisibleForTesting; |
| 21 import org.chromium.chrome.browser.ChromeApplication; | 22 import org.chromium.chrome.browser.ChromeApplication; |
| 23 import org.chromium.chrome.browser.ChromeSwitches; |
| 22 import org.chromium.chrome.browser.TabState; | 24 import org.chromium.chrome.browser.TabState; |
| 23 import org.chromium.chrome.browser.document.DocumentActivity; | 25 import org.chromium.chrome.browser.document.DocumentActivity; |
| 24 import org.chromium.chrome.browser.document.DocumentUtils; | 26 import org.chromium.chrome.browser.document.DocumentUtils; |
| 25 import org.chromium.chrome.browser.document.IncognitoDocumentActivity; | 27 import org.chromium.chrome.browser.document.IncognitoDocumentActivity; |
| 26 import org.chromium.chrome.browser.preferences.DocumentModeManager; | 28 import org.chromium.chrome.browser.preferences.DocumentModeManager; |
| 27 import org.chromium.chrome.browser.tab.Tab; | 29 import org.chromium.chrome.browser.tab.Tab; |
| 28 import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabModelMetadata; | 30 import org.chromium.chrome.browser.tabmodel.TabPersistentStore.TabModelMetadata; |
| 29 import org.chromium.chrome.browser.tabmodel.document.ActivityDelegate; | 31 import org.chromium.chrome.browser.tabmodel.document.ActivityDelegate; |
| 30 import org.chromium.chrome.browser.tabmodel.document.ActivityDelegateImpl; | 32 import org.chromium.chrome.browser.tabmodel.document.ActivityDelegateImpl; |
| 31 import org.chromium.chrome.browser.tabmodel.document.DocumentTabModel; | 33 import org.chromium.chrome.browser.tabmodel.document.DocumentTabModel; |
| 32 import org.chromium.chrome.browser.tabmodel.document.DocumentTabModelImpl; | 34 import org.chromium.chrome.browser.tabmodel.document.DocumentTabModelImpl; |
| 33 import org.chromium.chrome.browser.tabmodel.document.DocumentTabModelSelector; | 35 import org.chromium.chrome.browser.tabmodel.document.DocumentTabModelSelector; |
| 34 import org.chromium.chrome.browser.tabmodel.document.StorageDelegate; | 36 import org.chromium.chrome.browser.tabmodel.document.StorageDelegate; |
| 35 import org.chromium.chrome.browser.util.FeatureUtilities; | 37 import org.chromium.chrome.browser.util.FeatureUtilities; |
| 36 | 38 |
| 37 import java.io.File; | 39 import java.io.File; |
| 38 import java.io.FileInputStream; | 40 import java.io.FileInputStream; |
| 39 import java.io.FileOutputStream; | 41 import java.io.FileOutputStream; |
| 40 import java.io.IOException; | 42 import java.io.IOException; |
| 41 import java.nio.channels.FileChannel; | 43 import java.nio.channels.FileChannel; |
| 42 import java.util.HashSet; | 44 import java.util.HashSet; |
| 43 import java.util.Set; | 45 import java.util.Set; |
| 44 | 46 |
| 47 import javax.annotation.Nullable; |
| 48 |
| 45 /** | 49 /** |
| 46 * Divorces Chrome's tabs from Android's Overview menu. Assumes native librarie
s are unavailable. | 50 * Divorces Chrome's tabs from Android's Overview menu. Assumes native librarie
s are unavailable. |
| 47 * | 51 * |
| 48 * Migration from document mode to tabbed mode occurs in two main phases: | 52 * Migration from document mode to tabbed mode occurs in two main phases: |
| 49 * | 53 * |
| 50 * 1) NON-DESTRUCTIVE MIGRATION: | 54 * 1) NON-DESTRUCTIVE MIGRATION: |
| 51 * TabState files for the normal DocumentTabModel are copied from the documen
t mode directories | 55 * TabState files for the normal DocumentTabModel are copied from the documen
t mode directories |
| 52 * into the tabbed mode directory. Incognito tabs are silently dropped, as w
ith the previous | 56 * into the tabbed mode directory. Incognito tabs are silently dropped, as w
ith the previous |
| 53 * migration pathway. | 57 * migration pathway. |
| 54 * | 58 * |
| 55 * TODO(dfalcantara): Check what happens if a user last viewed an Incognito t
ab. | |
| 56 * TODO(dfalcantara): Check what happens on other launchers. | 59 * TODO(dfalcantara): Check what happens on other launchers. |
| 57 * | 60 * |
| 58 * Once all TabState files are copied, a TabModel metadata file is written ou
t for the tabbed | 61 * Once all TabState files are copied, a TabModel metadata file is written ou
t for the tabbed |
| 59 * mode {@link TabModelImpl} to read out. Because the native library is not
available, the file | 62 * mode {@link TabModelImpl} to read out. Because the native library is not
available, the file |
| 60 * will be incomplete but usable; it will be corrected by the TabModelImpl wh
en it loads it and | 63 * will be incomplete but usable; it will be corrected by the TabModelImpl wh
en it loads it and |
| 61 * all of the TabState files up. See {@link #writeTabModelMetadata} for deta
ils. | 64 * all of the TabState files up. See {@link #writeTabModelMetadata} for deta
ils. |
| 62 * | 65 * |
| 63 * 2) CLEANUP OF ALL DOCUMENT-RELATED THINGS: | 66 * 2) CLEANUP OF ALL DOCUMENT-RELATED THINGS: |
| 64 * DocumentActivity tasks in Android's Recents are removed, TabState files in
the document mode | 67 * DocumentActivity tasks in Android's Recents are removed, TabState files in
the document mode |
| 65 * directory are deleted, and document mode preferences are cleared. | 68 * directory are deleted, and document mode preferences are cleared. |
| 66 * | 69 * |
| 67 * TODO(dfalcantara): Clean up the incognito notification, if possible. | |
| 68 * TODO(dfalcantara): Add histograms for tracking migration progress. | 70 * TODO(dfalcantara): Add histograms for tracking migration progress. |
| 69 * | 71 * |
| 70 * TODO(dfalcantara): Potential pitfalls that need to be accounted for: | 72 * TODO(dfalcantara): Potential pitfalls that need to be accounted for: |
| 71 * - Consistently crashing during migration means you can never open Chrome un
til you clear data. | 73 * - Consistently crashing during migration means you can never open Chrome un
til you clear data. |
| 72 * - Successfully migrating, but crashing while deleting things and closing of
f tasks. | 74 * - Successfully migrating, but crashing while deleting things and closing of
f tasks. |
| 73 * - Failing to copy all the TabState files over during migration because of a
lack of space. | 75 * - Failing to copy all the TabState files over during migration because of a
lack of space. |
| 74 */ | 76 */ |
| 75 @TargetApi(Build.VERSION_CODES.LOLLIPOP) | 77 @TargetApi(Build.VERSION_CODES.LOLLIPOP) |
| 76 public class DocumentModeAssassin { | 78 public class DocumentModeAssassin { |
| 77 /** Alerted about progress along the migration pipeline. */ | 79 /** Alerted about progress along the migration pipeline. */ |
| (...skipping 20 matching lines...) Expand all Loading... |
| 98 /** Stages of the pipeline. Each stage is blocked off by a STARTED and DONE
pair. */ | 100 /** Stages of the pipeline. Each stage is blocked off by a STARTED and DONE
pair. */ |
| 99 static final int STAGE_UNINITIALIZED = 0; | 101 static final int STAGE_UNINITIALIZED = 0; |
| 100 static final int STAGE_INITIALIZED = 1; | 102 static final int STAGE_INITIALIZED = 1; |
| 101 static final int STAGE_COPY_TAB_STATES_STARTED = 2; | 103 static final int STAGE_COPY_TAB_STATES_STARTED = 2; |
| 102 static final int STAGE_COPY_TAB_STATES_DONE = 3; | 104 static final int STAGE_COPY_TAB_STATES_DONE = 3; |
| 103 static final int STAGE_WRITE_TABMODEL_METADATA_STARTED = 4; | 105 static final int STAGE_WRITE_TABMODEL_METADATA_STARTED = 4; |
| 104 static final int STAGE_WRITE_TABMODEL_METADATA_DONE = 5; | 106 static final int STAGE_WRITE_TABMODEL_METADATA_DONE = 5; |
| 105 static final int STAGE_CHANGE_SETTINGS_STARTED = 6; | 107 static final int STAGE_CHANGE_SETTINGS_STARTED = 6; |
| 106 static final int STAGE_CHANGE_SETTINGS_DONE = 7; | 108 static final int STAGE_CHANGE_SETTINGS_DONE = 7; |
| 107 static final int STAGE_DELETION_STARTED = 8; | 109 static final int STAGE_DELETION_STARTED = 8; |
| 108 static final int STAGE_DONE = 9; | 110 public static final int STAGE_DONE = 9; |
| 109 | 111 |
| 110 private static final String TAG = "DocumentModeAssassin"; | 112 private static final String TAG = "DocumentModeAssassin"; |
| 111 | 113 |
| 112 /** Which TabModelSelectorImpl to copy files into during migration. */ | 114 /** Which TabModelSelectorImpl to copy files into during migration. */ |
| 113 private static final int TAB_MODEL_INDEX = 0; | 115 private static final int TAB_MODEL_INDEX = 0; |
| 114 | 116 |
| 115 /** Creates and holds the Singleton. */ | 117 /** Creates and holds the Singleton. */ |
| 116 private static class LazyHolder { | 118 private static class LazyHolder { |
| 117 private static final DocumentModeAssassin INSTANCE = new DocumentModeAss
assin(); | 119 private static final DocumentModeAssassin INSTANCE = new DocumentModeAss
assin(); |
| 118 } | 120 } |
| (...skipping 11 matching lines...) Expand all Loading... |
| 130 new ObserverList<DocumentModeAssassinObserver>(); | 132 new ObserverList<DocumentModeAssassinObserver>(); |
| 131 | 133 |
| 132 /** Current stage of the migration. */ | 134 /** Current stage of the migration. */ |
| 133 private int mStage = STAGE_UNINITIALIZED; | 135 private int mStage = STAGE_UNINITIALIZED; |
| 134 | 136 |
| 135 /** Whether or not startStage is allowed to progress along the migration pip
eline. */ | 137 /** Whether or not startStage is allowed to progress along the migration pip
eline. */ |
| 136 private boolean mIsPipelineActive; | 138 private boolean mIsPipelineActive; |
| 137 | 139 |
| 138 /** Returns whether or not a migration to tabbed mode from document mode is
necessary. */ | 140 /** Returns whether or not a migration to tabbed mode from document mode is
necessary. */ |
| 139 public static boolean isMigrationNecessary() { | 141 public static boolean isMigrationNecessary() { |
| 140 return FeatureUtilities.isDocumentMode(ApplicationStatus.getApplicationC
ontext()); | 142 return CommandLine.getInstance().hasSwitch(ChromeSwitches.ENABLE_FORCED_
MIGRATION) |
| 143 && FeatureUtilities.isDocumentMode(ApplicationStatus.getApplicat
ionContext()); |
| 141 } | 144 } |
| 142 | 145 |
| 143 /** Migrates the user from document mode to tabbed mode if necessary. */ | 146 /** Migrates the user from document mode to tabbed mode if necessary. */ |
| 144 @VisibleForTesting | 147 @VisibleForTesting |
| 145 public void migrateFromDocumentToTabbedMode() { | 148 public void migrateFromDocumentToTabbedMode() { |
| 146 ThreadUtils.assertOnUiThread(); | 149 ThreadUtils.assertOnUiThread(); |
| 147 | 150 |
| 148 if (!isMigrationNecessary()) { | 151 if (!isMigrationNecessary()) { |
| 149 // Don't kick off anything if we don't need to. | 152 // Don't kick off anything if we don't need to. |
| 150 setStage(STAGE_UNINITIALIZED, STAGE_DONE); | 153 setStage(STAGE_UNINITIALIZED, STAGE_DONE); |
| 151 return; | 154 return; |
| 152 } else if (mStage != STAGE_UNINITIALIZED) { | 155 } else if (mStage != STAGE_UNINITIALIZED) { |
| 153 // Migration is already underway. | 156 // Migration is already underway. |
| 154 return; | 157 return; |
| 155 } | 158 } |
| 156 | 159 |
| 157 // TODO(dfalcantara): Add a pathway to catch repeated migration failures
. | 160 // TODO(dfalcantara): Add a pathway to catch repeated migration failures
. |
| 158 | 161 |
| 159 setStage(STAGE_UNINITIALIZED, STAGE_INITIALIZED); | 162 setStage(STAGE_UNINITIALIZED, STAGE_INITIALIZED); |
| 160 } | 163 } |
| 161 | 164 |
| 162 /** | 165 /** |
| 163 * Makes copies of {@link TabState} files in the document mode directory and
places them in the | 166 * Makes copies of {@link TabState} files in the document mode directory and
places them in the |
| 164 * tabbed mode directory. Only non-Incognito tabs are transferred. | 167 * tabbed mode directory. Only non-Incognito tabs are transferred. |
| 165 * | 168 * |
| 166 * TODO(dfalcantara): Prevent migrating chrome:// pages? | 169 * TODO(dfalcantara): Prevent migrating chrome:// pages? |
| 167 * | 170 * |
| 168 * @param selectedTabId ID of the last viewed non-Incognito tab. | 171 * @param selectedTabId ID of the last viewed non-Incognito tab. |
| 169 * @param documentDirectory File pointing at the DocumentTabModel TabState f
ile directory. | 172 * @param context Context to use when accessing directorie
s. |
| 170 * @param tabbedDirectory File pointing at tabbed mode TabState file direc
tory. | 173 * @param documentDirectoryOverride Overrides the default location for where
document mode's |
| 174 * TabState files are expected to be. |
| 175 * @param tabbedDirectoryOverride Overrides the default location for where
tabbed mode's |
| 176 * TabState files are expected to be. |
| 171 */ | 177 */ |
| 172 void copyTabStateFiles( | 178 void copyTabStateFiles(final int selectedTabId, final Context context, |
| 173 final int selectedTabId, final File documentDirectory, final File ta
bbedDirectory) { | 179 @Nullable final File documentDirectoryOverride, |
| 180 @Nullable final File tabbedDirectoryOverride) { |
| 174 ThreadUtils.assertOnUiThread(); | 181 ThreadUtils.assertOnUiThread(); |
| 175 if (!setStage(STAGE_INITIALIZED, STAGE_COPY_TAB_STATES_STARTED)) return; | 182 if (!setStage(STAGE_INITIALIZED, STAGE_COPY_TAB_STATES_STARTED)) return; |
| 176 | 183 |
| 177 new AsyncTask<Void, Void, Void>() { | 184 new AsyncTask<Void, Void, Void>() { |
| 185 private DocumentTabModelImpl mNormalTabModel; |
| 186 |
| 187 @Override |
| 188 protected void onPreExecute() { |
| 189 if (documentDirectoryOverride == null) { |
| 190 mNormalTabModel = (DocumentTabModelImpl) |
| 191 ChromeApplication.getDocumentTabModelSelector().getM
odel(false); |
| 192 } |
| 193 } |
| 194 |
| 178 @Override | 195 @Override |
| 179 protected Void doInBackground(Void... params) { | 196 protected Void doInBackground(Void... params) { |
| 197 File documentDirectory = documentDirectoryOverride == null |
| 198 ? mNormalTabModel.getStorageDelegate().getStateDirectory
() |
| 199 : documentDirectoryOverride; |
| 200 File tabbedDirectory = tabbedDirectoryOverride == null |
| 201 ? TabPersistentStore.getStateDirectory(context, TAB_MODE
L_INDEX) |
| 202 : tabbedDirectoryOverride; |
| 203 |
| 180 Log.d(TAG, "Copying TabState files from document to tabbed mode
directory."); | 204 Log.d(TAG, "Copying TabState files from document to tabbed mode
directory."); |
| 181 assert mMigratedTabIds.size() == 0; | 205 assert mMigratedTabIds.size() == 0; |
| 182 | 206 |
| 183 File[] allTabStates = documentDirectory.listFiles(); | 207 File[] allTabStates = documentDirectory.listFiles(); |
| 184 if (allTabStates != null) { | 208 if (allTabStates != null) { |
| 185 // If we know what tab the user was last viewing, copy just
that TabState file | 209 // If we know what tab the user was last viewing, copy just
that TabState file |
| 186 // before all the other ones to mitigate storage issues for
devices with limited | 210 // before all the other ones to mitigate storage issues for
devices with limited |
| 187 // available storage. | 211 // available storage. |
| 188 if (selectedTabId != Tab.INVALID_TAB_ID) { | 212 if (selectedTabId != Tab.INVALID_TAB_ID) { |
| 189 copyTabStateFilesInternal(allTabStates, selectedTabId, t
rue); | 213 copyTabStateFilesInternal( |
| 214 allTabStates, tabbedDirectory, selectedTabId, tr
ue); |
| 190 } | 215 } |
| 191 | 216 |
| 192 // Copy over everything else. | 217 // Copy over everything else. |
| 193 copyTabStateFilesInternal(allTabStates, selectedTabId, false
); | 218 copyTabStateFilesInternal(allTabStates, tabbedDirectory, sel
ectedTabId, false); |
| 194 } | 219 } |
| 195 return null; | 220 return null; |
| 196 } | 221 } |
| 197 | 222 |
| 198 @Override | 223 @Override |
| 199 protected void onPostExecute(Void result) { | 224 protected void onPostExecute(Void result) { |
| 200 Log.d(TAG, "Finished copying files."); | 225 Log.d(TAG, "Finished copying files."); |
| 201 setStage(STAGE_COPY_TAB_STATES_STARTED, STAGE_COPY_TAB_STATES_DO
NE); | 226 setStage(STAGE_COPY_TAB_STATES_STARTED, STAGE_COPY_TAB_STATES_DO
NE); |
| 202 } | 227 } |
| 203 | 228 |
| 204 /** | 229 /** |
| 205 * Copies the files from the document mode directory to the tabbed m
ode directory. | 230 * Copies the files from the document mode directory to the tabbed m
ode directory. |
| 206 * | 231 * |
| 207 * @param allTabStates Listing of all files in the document m
ode directory. | 232 * @param allTabStates Listing of all files in the document m
ode directory. |
| 233 * @param tabbedDirectory Directory for the tabbed mode files. |
| 208 * @param selectedTabId ID of the non-Incognito tab the user l
ast viewed. May be | 234 * @param selectedTabId ID of the non-Incognito tab the user l
ast viewed. May be |
| 209 * {@link Tab#INVALID_TAB_ID} if the ID i
s unknown. | 235 * {@link Tab#INVALID_TAB_ID} if the ID i
s unknown. |
| 210 * @param copyOnlySelectedTab Copy only the TabState file for the se
lectedTabId. | 236 * @param copyOnlySelectedTab Copy only the TabState file for the se
lectedTabId. |
| 211 */ | 237 */ |
| 212 private void copyTabStateFilesInternal( | 238 private void copyTabStateFilesInternal(File[] allTabStates, File tab
bedDirectory, |
| 213 File[] allTabStates, int selectedTabId, boolean copyOnlySele
ctedTab) { | 239 int selectedTabId, boolean copyOnlySelectedTab) { |
| 214 assert !ThreadUtils.runningOnUiThread(); | 240 assert !ThreadUtils.runningOnUiThread(); |
| 215 for (int i = 0; i < allTabStates.length; i++) { | 241 for (int i = 0; i < allTabStates.length; i++) { |
| 216 // Trawl the directory for non-Incognito TabState files. | 242 // Trawl the directory for non-Incognito TabState files. |
| 217 String fileName = allTabStates[i].getName(); | 243 String fileName = allTabStates[i].getName(); |
| 218 Pair<Integer, Boolean> tabInfo = TabState.parseInfoFromFilen
ame(fileName); | 244 Pair<Integer, Boolean> tabInfo = TabState.parseInfoFromFilen
ame(fileName); |
| 219 if (tabInfo == null || tabInfo.second) continue; | 245 if (tabInfo == null || tabInfo.second) continue; |
| 220 | 246 |
| 221 // Ignore any files that are not relevant for the current pa
ss. | 247 // Ignore any files that are not relevant for the current pa
ss. |
| 222 int tabId = tabInfo.first; | 248 int tabId = tabInfo.first; |
| 223 if (selectedTabId != Tab.INVALID_TAB_ID) { | 249 if (selectedTabId != Tab.INVALID_TAB_ID) { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 274 * | 300 * |
| 275 * 1) {@link TabPersistentStore} uses the URL to allow reusing already open
tabs for Home screen | 301 * 1) {@link TabPersistentStore} uses the URL to allow reusing already open
tabs for Home screen |
| 276 * Intents. If a Tab doesn't match the Intent's URL, a new Tab is create
d. This is already | 302 * Intents. If a Tab doesn't match the Intent's URL, a new Tab is create
d. This is already |
| 277 * the case when a cold start launches into document mode because the dat
a is unavailable at | 303 * the case when a cold start launches into document mode because the dat
a is unavailable at |
| 278 * startup. | 304 * startup. |
| 279 * | 305 * |
| 280 * 2) {@link TabModelImpl} uses the URL when it fails to load a Tab's persis
ted TabState. This | 306 * 2) {@link TabModelImpl} uses the URL when it fails to load a Tab's persis
ted TabState. This |
| 281 * means that the user loses some navigation history, but it's not a case
document mode would | 307 * means that the user loses some navigation history, but it's not a case
document mode would |
| 282 * have been able to recover from anyway because the TabState stores the
URL data. | 308 * have been able to recover from anyway because the TabState stores the
URL data. |
| 283 * | 309 * |
| 284 * @param tabbedDirectory Directory containing all of the main TabModel's fi
les. | 310 * @param normalTabModel DocumentTabModel containing info about n
on-Incognito tabs. |
| 285 * @param normalTabModel DocumentTabModel containing information about non-
Incognito tabs. | 311 * @param migratedTabIds IDs of Tabs whose TabState files were co
pied successfully. |
| 286 * @param migratedTabIds IDs of Tabs whose TabState files were copied succe
ssfully. | 312 * @param context Context to access Files from. |
| 313 * @param tabbedDirectoryOverride Overrides the default location for where
tabbed mode's |
| 314 * TabState files are expected to be. |
| 287 */ | 315 */ |
| 288 void writeTabModelMetadata(final File tabbedDirectory, final DocumentTabMode
l normalTabModel, | 316 void writeTabModelMetadata(final DocumentTabModel normalTabModel, |
| 289 final Set<Integer> migratedTabIds) { | 317 final Set<Integer> migratedTabIds, final Context context, |
| 318 @Nullable final File tabbedDirectoryOverride) { |
| 290 ThreadUtils.assertOnUiThread(); | 319 ThreadUtils.assertOnUiThread(); |
| 291 if (!setStage(STAGE_COPY_TAB_STATES_DONE, STAGE_WRITE_TABMODEL_METADATA_
STARTED)) return; | 320 if (!setStage(STAGE_COPY_TAB_STATES_DONE, STAGE_WRITE_TABMODEL_METADATA_
STARTED)) return; |
| 292 | 321 |
| 293 new AsyncTask<Void, Void, Boolean>() { | 322 new AsyncTask<Void, Void, Boolean>() { |
| 294 private byte[] mSerializedMetadata; | 323 private byte[] mSerializedMetadata; |
| 295 | 324 |
| 296 @Override | 325 @Override |
| 297 protected void onPreExecute() { | 326 protected void onPreExecute() { |
| 298 Log.d(TAG, "Beginning to write tabbed mode metadata files."); | 327 Log.d(TAG, "Beginning to write tabbed mode metadata files."); |
| 299 | 328 |
| (...skipping 22 matching lines...) Expand all Loading... |
| 322 normalMetadata, incognitoMetadata, null); | 351 normalMetadata, incognitoMetadata, null); |
| 323 } catch (IOException e) { | 352 } catch (IOException e) { |
| 324 Log.e(TAG, "Failed to serialize the TabModel.", e); | 353 Log.e(TAG, "Failed to serialize the TabModel.", e); |
| 325 mSerializedMetadata = null; | 354 mSerializedMetadata = null; |
| 326 } | 355 } |
| 327 } | 356 } |
| 328 | 357 |
| 329 @Override | 358 @Override |
| 330 protected Boolean doInBackground(Void... params) { | 359 protected Boolean doInBackground(Void... params) { |
| 331 if (mSerializedMetadata != null) { | 360 if (mSerializedMetadata != null) { |
| 361 File tabbedDirectory = tabbedDirectoryOverride == null |
| 362 ? TabPersistentStore.getStateDirectory(context, TAB_
MODEL_INDEX) |
| 363 : tabbedDirectoryOverride; |
| 332 TabPersistentStore.saveListToFile(tabbedDirectory, mSerializ
edMetadata); | 364 TabPersistentStore.saveListToFile(tabbedDirectory, mSerializ
edMetadata); |
| 333 return true; | 365 return true; |
| 334 } else { | 366 } else { |
| 335 return false; | 367 return false; |
| 336 } | 368 } |
| 337 } | 369 } |
| 338 | 370 |
| 339 @Override | 371 @Override |
| 340 protected void onPostExecute(Boolean result) { | 372 protected void onPostExecute(Boolean result) { |
| 341 // TODO(dfalcantara): What do we do if the metadata file failed
to be written out? | 373 // TODO(dfalcantara): What do we do if the metadata file failed
to be written out? |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 433 * shortcut the first time they start Chrome after migration. This was a
lready | 465 * shortcut the first time they start Chrome after migration. This was a
lready |
| 434 * broken for document mode during cold starts, anyway. | 466 * broken for document mode during cold starts, anyway. |
| 435 */ | 467 */ |
| 436 private void startStage(int newStage) { | 468 private void startStage(int newStage) { |
| 437 ThreadUtils.assertOnUiThread(); | 469 ThreadUtils.assertOnUiThread(); |
| 438 if (!mIsPipelineActive) return; | 470 if (!mIsPipelineActive) return; |
| 439 | 471 |
| 440 Context context = ApplicationStatus.getApplicationContext(); | 472 Context context = ApplicationStatus.getApplicationContext(); |
| 441 if (newStage == STAGE_INITIALIZED) { | 473 if (newStage == STAGE_INITIALIZED) { |
| 442 Log.d(TAG, "Migrating user into tabbed mode."); | 474 Log.d(TAG, "Migrating user into tabbed mode."); |
| 443 DocumentTabModelSelector selector = ChromeApplication.getDocumentTab
ModelSelector(); | |
| 444 DocumentTabModelImpl normalTabModel = | |
| 445 (DocumentTabModelImpl) selector.getModel(false); | |
| 446 int selectedTabId = DocumentUtils.getLastShownTabIdFromPrefs(context
, false); | 475 int selectedTabId = DocumentUtils.getLastShownTabIdFromPrefs(context
, false); |
| 447 | 476 copyTabStateFiles(selectedTabId, context, null, null); |
| 448 File documentDirectory = normalTabModel.getStorageDelegate().getStat
eDirectory(); | |
| 449 File tabbedDirectory = TabPersistentStore.getStateDirectory(context,
TAB_MODEL_INDEX); | |
| 450 copyTabStateFiles(selectedTabId, documentDirectory, tabbedDirectory)
; | |
| 451 } else if (newStage == STAGE_COPY_TAB_STATES_DONE) { | 477 } else if (newStage == STAGE_COPY_TAB_STATES_DONE) { |
| 452 Log.d(TAG, "Writing tabbed mode metadata file."); | 478 Log.d(TAG, "Writing tabbed mode metadata file."); |
| 453 DocumentTabModelSelector selector = ChromeApplication.getDocumentTab
ModelSelector(); | 479 DocumentTabModelSelector selector = ChromeApplication.getDocumentTab
ModelSelector(); |
| 454 DocumentTabModelImpl normalTabModel = | 480 DocumentTabModelImpl normalTabModel = |
| 455 (DocumentTabModelImpl) selector.getModel(false); | 481 (DocumentTabModelImpl) selector.getModel(false); |
| 456 File tabbedDirectory = | 482 writeTabModelMetadata(normalTabModel, mMigratedTabIds, context, null
); |
| 457 TabPersistentStore.getStateDirectory(context, TAB_MODEL_INDE
X); | |
| 458 writeTabModelMetadata(tabbedDirectory, normalTabModel, mMigratedTabI
ds); | |
| 459 } else if (newStage == STAGE_WRITE_TABMODEL_METADATA_DONE) { | 483 } else if (newStage == STAGE_WRITE_TABMODEL_METADATA_DONE) { |
| 460 Log.d(TAG, "Changing user preference."); | 484 Log.d(TAG, "Changing user preference."); |
| 461 changePreferences(context); | 485 changePreferences(context); |
| 462 } else if (newStage == STAGE_CHANGE_SETTINGS_DONE) { | 486 } else if (newStage == STAGE_CHANGE_SETTINGS_DONE) { |
| 463 Log.d(TAG, "Cleaning up document mode data."); | 487 Log.d(TAG, "Cleaning up document mode data."); |
| 464 deleteDocumentModeData(context); | 488 deleteDocumentModeData(context); |
| 465 } | 489 } |
| 466 } | 490 } |
| 467 | 491 |
| 468 | 492 |
| 469 /** | 493 /** |
| 470 * Returns the current stage of the pipeline. | 494 * Returns the current stage of the pipeline. |
| 471 */ | 495 */ |
| 472 @VisibleForTesting | 496 @VisibleForTesting |
| 473 public int getStage() { | 497 public int getStage() { |
| 498 ThreadUtils.assertOnUiThread(); |
| 474 return mStage; | 499 return mStage; |
| 475 } | 500 } |
| 476 | 501 |
| 477 | 502 |
| 478 /** | 503 /** |
| 479 * Adds a observer that is alerted as migration progresses. | 504 * Adds a observer that is alerted as migration progresses. |
| 480 * | 505 * |
| 481 * @param observer Observer to add. | 506 * @param observer Observer to add. |
| 482 */ | 507 */ |
| 483 @VisibleForTesting | 508 @VisibleForTesting |
| (...skipping 27 matching lines...) Expand all Loading... |
| 511 | 536 |
| 512 private DocumentModeAssassin() { | 537 private DocumentModeAssassin() { |
| 513 this(isMigrationNecessary() ? STAGE_UNINITIALIZED : STAGE_DONE, true); | 538 this(isMigrationNecessary() ? STAGE_UNINITIALIZED : STAGE_DONE, true); |
| 514 } | 539 } |
| 515 | 540 |
| 516 private DocumentModeAssassin(int stage, boolean isPipelineActive) { | 541 private DocumentModeAssassin(int stage, boolean isPipelineActive) { |
| 517 mStage = stage; | 542 mStage = stage; |
| 518 mIsPipelineActive = isPipelineActive; | 543 mIsPipelineActive = isPipelineActive; |
| 519 } | 544 } |
| 520 } | 545 } |
| OLD | NEW |