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.content.Context; | 7 import android.content.Context; |
8 import android.content.SharedPreferences; | 8 import android.content.SharedPreferences; |
9 import android.os.AsyncTask; | 9 import android.os.AsyncTask; |
10 import android.os.StrictMode; | 10 import android.os.StrictMode; |
11 import android.support.annotation.WorkerThread; | 11 import android.support.annotation.WorkerThread; |
12 import android.util.Pair; | 12 import android.util.Pair; |
13 import android.util.SparseBooleanArray; | 13 import android.util.SparseBooleanArray; |
14 | 14 |
15 import org.chromium.base.Callback; | 15 import org.chromium.base.Callback; |
16 import org.chromium.base.ContextUtils; | 16 import org.chromium.base.ContextUtils; |
17 import org.chromium.base.Log; | 17 import org.chromium.base.Log; |
18 import org.chromium.base.PathUtils; | 18 import org.chromium.base.PathUtils; |
19 import org.chromium.base.StreamUtil; | 19 import org.chromium.base.StreamUtil; |
20 import org.chromium.base.ThreadUtils; | 20 import org.chromium.base.ThreadUtils; |
21 import org.chromium.base.VisibleForTesting; | 21 import org.chromium.base.VisibleForTesting; |
| 22 import org.chromium.base.library_loader.LibraryLoader; |
| 23 import org.chromium.base.metrics.RecordHistogram; |
22 import org.chromium.chrome.browser.TabState; | 24 import org.chromium.chrome.browser.TabState; |
23 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; | 25 import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager; |
24 | 26 |
25 import java.io.BufferedInputStream; | 27 import java.io.BufferedInputStream; |
26 import java.io.DataInputStream; | 28 import java.io.DataInputStream; |
27 import java.io.File; | 29 import java.io.File; |
28 import java.io.FileInputStream; | 30 import java.io.FileInputStream; |
29 import java.util.ArrayList; | 31 import java.util.ArrayList; |
30 import java.util.List; | 32 import java.util.List; |
31 import java.util.concurrent.ExecutionException; | 33 import java.util.concurrent.ExecutionException; |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
209 } | 211 } |
210 setLegacyFileMigrationPref(); | 212 setLegacyFileMigrationPref(); |
211 } | 213 } |
212 | 214 |
213 /** | 215 /** |
214 * Upgrades users from an older version of Chrome when the state files for m
ulti-instance | 216 * Upgrades users from an older version of Chrome when the state files for m
ulti-instance |
215 * were each kept in separate subdirectories. | 217 * were each kept in separate subdirectories. |
216 */ | 218 */ |
217 @WorkerThread | 219 @WorkerThread |
218 private void performMultiInstanceMigration() { | 220 private void performMultiInstanceMigration() { |
219 // 1. Rename tab metadata file for tab directory "0". | 221 // 0. Do not rename the old metadata file if the new metadata file alrea
dy exists. This |
| 222 // should not happen, but if it does and the metadata file is overwri
tten then users |
| 223 // may lose tabs. See crbug.com/649384. |
220 File stateDir = getOrCreateStateDirectory(); | 224 File stateDir = getOrCreateStateDirectory(); |
221 File metadataFile = new File(stateDir, LEGACY_SAVED_STATE_FILE); | 225 File newMetadataFile = new File(stateDir, getStateFileName()); |
222 if (metadataFile.exists()) { | 226 File oldMetadataFile = new File(stateDir, LEGACY_SAVED_STATE_FILE); |
223 if (!metadataFile.renameTo(new File(stateDir, getStateFileName())))
{ | 227 if (newMetadataFile.exists()) { |
224 Log.e(TAG, "Failed to rename file: " + metadataFile); | 228 Log.e(TAG, "New metadata file already exists"); |
| 229 if (LibraryLoader.isInitialized()) { |
| 230 RecordHistogram.recordBooleanHistogram( |
| 231 "Android.MultiInstanceMigration.NewMetadataFileExists",
true); |
| 232 } |
| 233 } else if (oldMetadataFile.exists()) { |
| 234 // 1. Rename tab metadata file for tab directory "0". |
| 235 if (!oldMetadataFile.renameTo(newMetadataFile)) { |
| 236 Log.e(TAG, "Failed to rename file: " + oldMetadataFile); |
| 237 |
| 238 if (LibraryLoader.isInitialized()) { |
| 239 RecordHistogram.recordBooleanHistogram( |
| 240 "Android.MultiInstanceMigration.FailedToRenameMetada
taFile", true); |
| 241 } |
225 } | 242 } |
226 } | 243 } |
227 | 244 |
228 // 2. Move files from other state directories. | 245 // 2. Move files from other state directories. |
229 for (int i = TabModelSelectorImpl.CUSTOM_TABS_SELECTOR_INDEX; | 246 for (int i = TabModelSelectorImpl.CUSTOM_TABS_SELECTOR_INDEX; |
230 i < TabWindowManager.MAX_SIMULTANEOUS_SELECTORS; i++) { | 247 i < TabWindowManager.MAX_SIMULTANEOUS_SELECTORS; i++) { |
231 // Skip the directory we're migrating to. | 248 // Skip the directory we're migrating to. |
232 if (i == 0) continue; | 249 if (i == 0) continue; |
233 | 250 |
234 File otherStateDir = new File( | 251 File otherStateDir = new File( |
235 TabPersistentStore.getOrCreateBaseStateDirectory(), Integer.
toString(i)); | 252 TabPersistentStore.getOrCreateBaseStateDirectory(), Integer.
toString(i)); |
236 if (otherStateDir == null || !otherStateDir.exists()) continue; | 253 if (otherStateDir == null || !otherStateDir.exists()) continue; |
237 | 254 |
238 // Rename tab state file. | 255 // Rename tab state file. |
239 metadataFile = new File(otherStateDir, LEGACY_SAVED_STATE_FILE); | 256 oldMetadataFile = new File(otherStateDir, LEGACY_SAVED_STATE_FILE); |
240 if (metadataFile.exists()) { | 257 if (oldMetadataFile.exists()) { |
241 if (!metadataFile.renameTo(new File(stateDir, getStateFileName(i
)))) { | 258 if (!oldMetadataFile.renameTo(new File(stateDir, getStateFileNam
e(i)))) { |
242 Log.e(TAG, "Failed to rename file: " + metadataFile); | 259 Log.e(TAG, "Failed to rename file: " + oldMetadataFile); |
243 } | 260 } |
244 } | 261 } |
245 | 262 |
246 // Rename tab files. | 263 // Rename tab files. |
247 File[] files = otherStateDir.listFiles(); | 264 File[] files = otherStateDir.listFiles(); |
248 if (files != null) { | 265 if (files != null) { |
249 for (File file : files) { | 266 for (File file : files) { |
250 if (TabState.parseInfoFromFilename(file.getName()) != null)
{ | 267 if (TabState.parseInfoFromFilename(file.getName()) != null)
{ |
251 // Custom tabs does not currently use tab files. Delete
them rather than | 268 // Custom tabs does not currently use tab files. Delete
them rather than |
252 // migrating. | 269 // migrating. |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
426 } catch (Exception e) { | 443 } catch (Exception e) { |
427 Log.e(TAG, "Unable to read state for " + metadataFile.ge
tName() + ": " + e); | 444 Log.e(TAG, "Unable to read state for " + metadataFile.ge
tName() + ": " + e); |
428 } finally { | 445 } finally { |
429 StreamUtil.closeQuietly(stream); | 446 StreamUtil.closeQuietly(stream); |
430 } | 447 } |
431 } | 448 } |
432 } | 449 } |
433 } | 450 } |
434 } | 451 } |
435 } | 452 } |
OLD | NEW |