Index: chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java |
diff --git a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java |
index 5ee7824ce8b2dfe8e13c5fc2384d7a4563271627..81afb404c5a03286bbd65a482835f877754cb40e 100644 |
--- a/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java |
+++ b/chrome/android/java/src/org/chromium/chrome/browser/tabmodel/TabPersistentStore.java |
@@ -19,6 +19,7 @@ import android.util.SparseIntArray; |
import org.chromium.base.ContextUtils; |
import org.chromium.base.Log; |
+import org.chromium.base.PathUtils; |
import org.chromium.base.StreamUtil; |
import org.chromium.base.ThreadUtils; |
import org.chromium.base.VisibleForTesting; |
@@ -179,7 +180,7 @@ public class TabPersistentStore extends TabPersister { |
} |
private static AsyncTask<Void, Void, Void> sMigrationTask = null; |
- private static AsyncTask<Void, Void, CleanUpTabStateDataInfo> sCleanupTask = null; |
+ private static AsyncTask<Void, Void, Void> sCleanupTask = null; |
private static File sStateDirectory; |
private final TabModelSelector mTabModelSelector; |
@@ -1130,11 +1131,7 @@ public class TabPersistentStore extends TabPersister { |
if (mObserver != null) mObserver.onStateMerged(); |
} |
- // Only clean up persistent data on application cold start. |
- if (mSelectorIndex == 0 |
- && TabWindowManager.getInstance().getNumberOfAssignedTabModelSelectors() == 1) { |
- cleanUpPersistentData(false); |
- } |
+ cleanUpPersistentData(false /* deleteAllFiles */); |
onStateLoaded(); |
mLoadTabTask = null; |
Log.d(TAG, "Loaded tab lists; counts: " + mTabModelSelector.getModel(false).getCount() |
@@ -1161,10 +1158,6 @@ public class TabPersistentStore extends TabPersister { |
sCleanupTask = new CleanUpTabStateDataTask(deleteAllFiles); |
sCleanupTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); |
} |
- |
- if (mTabContentManager != null) { |
- mTabContentManager.cleanUpPersistentData(mTabModelSelector); |
- } |
} |
/** |
@@ -1194,19 +1187,11 @@ public class TabPersistentStore extends TabPersister { |
// executor. |
} |
- private static class CleanUpTabStateDataInfo { |
- private final String[] mTabFileNames; |
- private final SparseArray<Boolean> mOtherTabIds; |
- |
- public CleanUpTabStateDataInfo(String[] tabFileNames, SparseArray<Boolean> otherTabIds) { |
- mTabFileNames = tabFileNames; |
- mOtherTabIds = otherTabIds; |
- } |
- } |
- |
- private class CleanUpTabStateDataTask extends AsyncTask<Void, Void, CleanUpTabStateDataInfo> { |
+ private class CleanUpTabStateDataTask extends AsyncTask<Void, Void, Void> { |
private final boolean mDeleteAllFiles; |
- |
+ private String[] mTabFileNames; |
+ private String[] mThumbnailFileNames; |
+ private SparseArray<Boolean> mOtherTabIds; |
/** |
* Creates a new AsyncTask to delete tab files. If deleteAllFiles is true, all tab files |
* will be deleted regardless of whether they currently belong to a tab model. If it is |
@@ -1218,33 +1203,55 @@ public class TabPersistentStore extends TabPersister { |
} |
@Override |
- protected CleanUpTabStateDataInfo doInBackground(Void... voids) { |
+ protected Void doInBackground(Void... voids) { |
if (mDestroyed) { |
return null; |
} |
- SparseArray<Boolean> otherTabIds = new SparseArray<Boolean>(); |
- if (!mDeleteAllFiles) getTabsFromOtherStateFiles(otherTabIds); |
+ mTabFileNames = getStateDirectory().list(); |
+ String thumbnailDirectory = PathUtils.getThumbnailCacheDirectory(mContext); |
+ mThumbnailFileNames = new File(thumbnailDirectory).list(); |
- return new CleanUpTabStateDataInfo(getStateDirectory().list(), otherTabIds); |
+ mOtherTabIds = new SparseArray<Boolean>(); |
+ if (!mDeleteAllFiles) getTabsFromOtherStateFiles(mOtherTabIds); |
+ return null; |
} |
@Override |
- protected void onPostExecute(CleanUpTabStateDataInfo tabStateInfo) { |
- if (mDestroyed || tabStateInfo.mTabFileNames == null) return; |
- |
- for (String fileName : tabStateInfo.mTabFileNames) { |
- Pair<Integer, Boolean> data = TabState.parseInfoFromFilename(fileName); |
- if (data != null) { |
- TabModel model = mTabModelSelector.getModel(data.second); |
- if (mDeleteAllFiles || (TabModelUtils.getTabById(model, data.first) == null |
- && tabStateInfo.mOtherTabIds.get(data.first) == null)) { |
- // It might be more efficient to use a single task for all files, but |
- // the number of files is expected to be very small. |
- deleteFileAsync(fileName); |
+ protected void onPostExecute(Void unused) { |
+ if (mDestroyed) return; |
+ TabWindowManager tabWindowManager = TabWindowManager.getInstance(); |
+ |
+ if (mTabFileNames != null) { |
+ for (String fileName : mTabFileNames) { |
+ Pair<Integer, Boolean> data = TabState.parseInfoFromFilename(fileName); |
+ if (data != null) { |
+ int tabId = data.first; |
+ if (shouldDeleteTabFile(tabId, tabWindowManager)) { |
+ // It might be more efficient to use a single task for all files, but |
+ // the number of files is expected to be very small. |
+ deleteFileAsync(fileName); |
+ } |
+ } |
+ } |
+ } |
+ if (mTabContentManager != null && mThumbnailFileNames != null) { |
+ for (String fileName : mThumbnailFileNames) { |
+ try { |
+ int tabId = Integer.parseInt(fileName); |
+ if (shouldDeleteTabFile(tabId, tabWindowManager)) { |
+ mTabContentManager.removeTabThumbnail(tabId); |
+ } |
+ } catch (NumberFormatException expected) { |
+ // This is an unknown file name, we'll leave it there. |
} |
} |
} |
} |
+ |
+ private boolean shouldDeleteTabFile(int tabId, TabWindowManager tabWindowManager) { |
+ return mDeleteAllFiles || (!tabWindowManager.tabExistsInAnySelector(tabId) |
+ && mOtherTabIds.get(tabId) == null); |
+ } |
} |
/** |
@@ -1254,6 +1261,9 @@ public class TabPersistentStore extends TabPersister { |
*/ |
private void getTabsFromOtherStateFiles(SparseArray<Boolean> tabIds) { |
for (int i = 0; i < TabWindowManager.MAX_SIMULTANEOUS_SELECTORS; i++) { |
+ // Although we check all selectors before deleting, we can only be sure that our own |
+ // selector will not go away between now and then. So, we read from disk all other state |
+ // files, even if they are already loaded by another selector. |
if (i == mSelectorIndex) continue; |
File metadataFile = new File(getStateDirectory(), getStateFileName(i)); |