| 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 f12dbdeb60d01b4a0d1247e77e986290d866fd37..a38c1c49b2bd15897994928a972312c55fed8929 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
|
| @@ -64,12 +64,17 @@ public class TabPersistentStore extends TabPersister {
|
| @VisibleForTesting
|
| public static final String SAVED_STATE_FILE = "tab_state";
|
|
|
| - private static final String PREF_HAS_COMPUTED_MAX_ID =
|
| - "org.chromium.chrome.browser.tabmodel.TabPersistentStore.HAS_COMPUTED_MAX_ID";
|
| + @VisibleForTesting
|
| + static final String PREF_ACTIVE_TAB_ID =
|
| + "org.chromium.chrome.browser.tabmodel.TabPersistentStore.ACTIVE_TAB_ID";
|
|
|
| - private static final String PREF_HAS_RUN_FILE_MIGRATION =
|
| + @VisibleForTesting
|
| + static final String PREF_HAS_RUN_FILE_MIGRATION =
|
| "org.chromium.chrome.browser.tabmodel.TabPersistentStore.HAS_RUN_FILE_MIGRATION";
|
|
|
| + private static final String PREF_HAS_COMPUTED_MAX_ID =
|
| + "org.chromium.chrome.browser.tabmodel.TabPersistentStore.HAS_COMPUTED_MAX_ID";
|
| +
|
| /** Prevents two copies of the Migration task from being created. */
|
| private static final Object MIGRATION_LOCK = new Object();
|
|
|
| @@ -172,7 +177,10 @@ public class TabPersistentStore extends TabPersister {
|
| private SparseIntArray mIncognitoTabsRestored;
|
|
|
| private SharedPreferences mPreferences;
|
| - private AsyncTask<Void, Void, DataInputStream> mPrefetchSaveStateTask;
|
| + private AsyncTask<Void, Void, DataInputStream> mPrefetchTabListTask;
|
| +
|
| + @VisibleForTesting
|
| + AsyncTask<Void, Void, TabState> mPrefetchActiveTabTask;
|
|
|
|
|
| /**
|
| @@ -195,7 +203,8 @@ public class TabPersistentStore extends TabPersister {
|
| mObserver = observer;
|
| mPreferences = ContextUtils.getAppSharedPreferences();
|
| startMigrationTaskIfNecessary();
|
| - startPrefetchTask();
|
| + startPrefetchTabListTask();
|
| + startPrefetchActiveTabTask();
|
| }
|
|
|
| @Override
|
| @@ -346,7 +355,7 @@ public class TabPersistentStore extends TabPersister {
|
| assert mTabModelSelector.getModel(false).getCount() == 0;
|
| checkAndUpdateMaxTabId();
|
| long timeWaitingForPrefetch = SystemClock.elapsedRealtime();
|
| - DataInputStream stream = mPrefetchSaveStateTask.get();
|
| + DataInputStream stream = mPrefetchTabListTask.get();
|
| logExecutionTime("LoadStateInternalPrefetchTime", timeWaitingForPrefetch);
|
| readSavedStateFile(stream,
|
| createOnTabStateReadCallback(mTabModelSelector.isIncognitoSelected()));
|
| @@ -426,13 +435,22 @@ public class TabPersistentStore extends TabPersister {
|
|
|
| private void restoreTab(TabRestoreDetails tabToRestore, boolean setAsActive) {
|
| // As we do this in startup, and restoring the active tab's state is critical, we permit
|
| - // this read.
|
| - // TODO(joth): An improved solution would be to pre-read the files on a background and
|
| - // block here waiting for that task to complete only if needed. See http://b/5518170
|
| + // this read in the event that the prefetch task is not available. Either:
|
| + // 1. The user just upgraded, has not yet set the new active tab id pref yet. Or
|
| + // 2. restoreTab is used to preempt async queue and restore immediately on the UI thread.
|
| StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
|
| try {
|
| long time = SystemClock.elapsedRealtime();
|
| - TabState state = TabState.restoreTabState(getStateDirectory(), tabToRestore.id);
|
| + TabState state;
|
| + int restoredTabId = mPreferences.getInt(PREF_ACTIVE_TAB_ID, Tab.INVALID_TAB_ID);
|
| + if (restoredTabId == tabToRestore.id && mPrefetchActiveTabTask != null) {
|
| + long timeWaitingForPrefetch = SystemClock.elapsedRealtime();
|
| + state = mPrefetchActiveTabTask.get();
|
| + logExecutionTime("RestoreTabPrefetchTime", timeWaitingForPrefetch);
|
| + } else {
|
| + // Necessary to do on the UI thread as a last resort.
|
| + state = TabState.restoreTabState(getStateDirectory(), tabToRestore.id);
|
| + }
|
| logExecutionTime("RestoreTabTime", time);
|
| restoreTab(tabToRestore, state, setAsActive);
|
| } catch (Exception e) {
|
| @@ -624,6 +642,16 @@ public class TabPersistentStore extends TabPersister {
|
| normalInfo.urls.add(normalModel.getTabAt(i).getUrl());
|
| }
|
|
|
| + // Cache the active tab id to be pre-loaded next launch.
|
| + int activeTabId = Tab.INVALID_TAB_ID;
|
| + int activeIndex = normalModel.index();
|
| + if (activeIndex != TabList.INVALID_TAB_INDEX) {
|
| + activeTabId = normalModel.getTabAt(activeIndex).getId();
|
| + }
|
| + // Always override the existing value in case there is no active tab.
|
| + ContextUtils.getAppSharedPreferences().edit().putInt(
|
| + PREF_ACTIVE_TAB_ID, activeTabId).apply();
|
| +
|
| return serializeMetadata(normalInfo, incognitoInfo, tabsBeingRestored);
|
| }
|
|
|
| @@ -1096,8 +1124,8 @@ public class TabPersistentStore extends TabPersister {
|
| }
|
| }
|
|
|
| - private void startPrefetchTask() {
|
| - mPrefetchSaveStateTask = new AsyncTask<Void, Void, DataInputStream>() {
|
| + private void startPrefetchTabListTask() {
|
| + mPrefetchTabListTask = new AsyncTask<Void, Void, DataInputStream>() {
|
| @Override
|
| protected DataInputStream doInBackground(Void... params) {
|
| // This getStateDirectory should be the first call and will cache the result.
|
| @@ -1119,6 +1147,17 @@ public class TabPersistentStore extends TabPersister {
|
| }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
| }
|
|
|
| + private void startPrefetchActiveTabTask() {
|
| + final int activeTabId = mPreferences.getInt(PREF_ACTIVE_TAB_ID, Tab.INVALID_TAB_ID);
|
| + if (activeTabId == Tab.INVALID_TAB_ID) return;
|
| + mPrefetchActiveTabTask = new AsyncTask<Void, Void, TabState>() {
|
| + @Override
|
| + protected TabState doInBackground(Void... params) {
|
| + return TabState.restoreTabState(getStateDirectory(), activeTabId);
|
| + }
|
| + }.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
| + }
|
| +
|
| /**
|
| * Directory containing all data for TabModels. Each subdirectory stores info about different
|
| * TabModelSelectors, including metadata about each TabModel and TabStates for each of their
|
|
|