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 |