/** * Test that migration skips if it already has files in the new folder. * * @throws IOException * @throws InterruptedException * @throws ExecutionException */ @SuppressWarnings("unused") @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE") @SmallTest public void testSkipMigrateData() throws IOException, InterruptedException, ExecutionException { ApplicationData.clearAppData(getInstrumentation().getTargetContext()); // Write old state files. File filesDir = getInstrumentation().getTargetContext().getFilesDir(); File stateFile = new File(filesDir, TabPersistentStore.SAVED_STATE_FILE); File tab0 = new File(filesDir, TabState.SAVED_TAB_STATE_FILE_PREFIX + "0"); File tab1 = new File(filesDir, TabState.SAVED_TAB_STATE_FILE_PREFIX + "1"); File tab2 = new File(filesDir, TabState.SAVED_TAB_STATE_FILE_PREFIX_INCOGNITO + "2"); File tab3 = new File(filesDir, TabState.SAVED_TAB_STATE_FILE_PREFIX_INCOGNITO + "3"); assertTrue("Could not create state file", stateFile.createNewFile()); assertTrue("Could not create tab 0 file", tab0.createNewFile()); assertTrue("Could not create tab 1 file", tab1.createNewFile()); assertTrue("Could not create tab 2 file", tab2.createNewFile()); assertTrue("Could not create tab 3 file", tab3.createNewFile()); // Write new state files File newDir = TabPersistentStore.getStateDirectory(getInstrumentation().getTargetContext(), 0); File newStateFile = new File(newDir, TabPersistentStore.SAVED_STATE_FILE); File newTab4 = new File(newDir, TabState.SAVED_TAB_STATE_FILE_PREFIX + "4"); assertTrue("Could not create new tab 4 file", newTab4.createNewFile()); assertTrue("Could not create new state file", newStateFile.createNewFile()); // Build the TabPersistentStore which will try to move the files. MockTabModelSelector selector = new MockTabModelSelector(0, 0, null); TabPersistentStore store = new TabPersistentStore(selector, 0, getInstrumentation().getTargetContext(), null, null); TabPersistentStore.waitForMigrationToFinish(); assertTrue("Could not find new state file", newStateFile.exists()); assertTrue("Could not find new tab 4 file", newTab4.exists()); // Make sure the old files did not move File newTab0 = new File(newDir, TabState.SAVED_TAB_STATE_FILE_PREFIX + "0"); File newTab1 = new File(newDir, TabState.SAVED_TAB_STATE_FILE_PREFIX + "1"); File newTab2 = new File(newDir, TabState.SAVED_TAB_STATE_FILE_PREFIX_INCOGNITO + "2"); File newTab3 = new File(newDir, TabState.SAVED_TAB_STATE_FILE_PREFIX_INCOGNITO + "3"); assertFalse("Could find new tab 0 file", newTab0.exists()); assertFalse("Could find new tab 1 file", newTab1.exists()); assertFalse("Could find new tab 2 file", newTab2.exists()); assertFalse("Could find new tab 3 file", newTab3.exists()); ApplicationData.clearAppData(getInstrumentation().getTargetContext()); }
/** * Tests that the max id returned is the max of all of the tab models. * * @throws IOException */ @SmallTest public void testFindsMaxIdProperly() throws IOException { TabModelSelector selector0 = new MockTabModelSelector(1, 1, null); TabModelSelector selector1 = new MockTabModelSelector(1, 1, null); writeStateFile(selector0, 0); writeStateFile(selector1, 1); TabModelSelector selectorIn = new MockTabModelSelector(0, 0, null); TabPersistentStore storeIn = new TabPersistentStore(selectorIn, 0, getInstrumentation().getTargetContext(), null, null); int maxId = Math.max(getMaxId(selector0), getMaxId(selector1)); disableReporting(); assertEquals("Invalid next id", maxId + 1, storeIn.loadStateInternal()); }
@Override public void destroy() { mTabSaver.destroy(); mUma.destroy(); super.destroy(); mActiveState = false; }
/** * Test that the state file migration skips unrelated files. * * @throws IOException * @throws InterruptedException * @throws ExecutionException */ @SuppressWarnings("unused") @SuppressFBWarnings("DLS_DEAD_LOCAL_STORE") @SmallTest public void testMigrationLeavesOtherFilesAlone() throws IOException, InterruptedException, ExecutionException { ApplicationData.clearAppData(getInstrumentation().getTargetContext()); // Write old state files. File filesDir = getInstrumentation().getTargetContext().getFilesDir(); File stateFile = new File(filesDir, TabPersistentStore.SAVED_STATE_FILE); File tab0 = new File(filesDir, TabState.SAVED_TAB_STATE_FILE_PREFIX + "0"); File otherFile = new File(filesDir, "other.file"); assertTrue("Could not create state file", stateFile.createNewFile()); assertTrue("Could not create tab 0 file", tab0.createNewFile()); assertTrue("Could not create other file", otherFile.createNewFile()); // Build the TabPersistentStore which will try to move the files. MockTabModelSelector selector = new MockTabModelSelector(0, 0, null); TabPersistentStore store = new TabPersistentStore(selector, 0, getInstrumentation().getTargetContext(), null, null); TabPersistentStore.waitForMigrationToFinish(); assertFalse("Could still find old state file", stateFile.exists()); assertFalse("Could still find old tab 0 file", tab0.exists()); assertTrue("Could not find other file", otherFile.exists()); // Check that the files were moved. File newDir = TabPersistentStore.getStateDirectory(getInstrumentation().getTargetContext(), 0); File newStateFile = new File(newDir, TabPersistentStore.SAVED_STATE_FILE); File newTab0 = new File(newDir, TabState.SAVED_TAB_STATE_FILE_PREFIX + "0"); File newOtherFile = new File(newDir, "other.file"); assertTrue("Could not find new state file", newStateFile.exists()); assertTrue("Could not find new tab 0 file", newTab0.exists()); assertFalse("Could find new other file", newOtherFile.exists()); ApplicationData.clearAppData(getInstrumentation().getTargetContext()); }
@Override public void requestToShowTab(Tab tab, TabSelectionType type) { boolean isFromExternalApp = tab != null && tab.getLaunchType() == TabLaunchType.FROM_EXTERNAL_APP; if (mVisibleTab != tab && tab != null && !tab.isNativePage()) { TabModelBase.startTabSwitchLatencyTiming(type); } if (mVisibleTab != null && mVisibleTab != tab && !mVisibleTab.needsReload()) { if (mVisibleTab.isInitialized()) { // TODO(dtrainor): Once we figure out why we can't grab a snapshot from the current // tab when we have other tabs loading from external apps remove the checks for // FROM_EXTERNAL_APP/FROM_NEW. if (!mVisibleTab.isClosing() && (!isFromExternalApp || type != TabSelectionType.FROM_NEW)) { cacheTabBitmap(mVisibleTab); } mVisibleTab.hide(); mVisibleTab.setFullscreenManager(null); mTabSaver.addTabToSaveQueue(mVisibleTab); } mVisibleTab = null; } if (tab == null) { notifyChanged(); return; } // We hit this case when the user enters tab switcher and comes back to the current tab // without actual tab switch. if (mVisibleTab == tab && !mVisibleTab.isHidden()) { // The current tab might have been killed by the os while in tab switcher. tab.loadIfNeeded(); return; } tab.setFullscreenManager(mActivity.getFullscreenManager()); mVisibleTab = tab; // Don't execute the tab display part if Chrome has just been sent to background. This // avoids uneccessary work (tab restore) and prevents pollution of tab display metrics - see // http://crbug.com/316166. if (type != TabSelectionType.FROM_EXIT) { tab.show(type); mUma.onShowTab(tab.getId(), tab.isBeingRestored()); } }
private void writeStateFile(final TabModelSelector selector, int index) throws IOException { byte[] data = ThreadUtils.runOnUiThreadBlockingNoException( new Callable<byte[]>() { @Override public byte[] call() throws Exception { return TabPersistentStore.serializeTabModelSelector(selector, null); } }); File f = TabPersistentStore.getStateDirectory(getInstrumentation().getTargetContext(), index); FileOutputStream fos = null; try { fos = new FileOutputStream(new File(f, TabPersistentStore.SAVED_STATE_FILE)); fos.write(data); } finally { StreamUtil.closeQuietly(fos); } }
/** * Tests that each model loads the subset of tabs it is responsible for. In this case, just check * that the model has the expected number of tabs to load. Since each model is loading a different * number of tabs we can tell if they are each attempting to load their specific set. * * @throws IOException */ @SmallTest public void testOnlyLoadsSingleModel() throws IOException { TabModelSelector selector0 = new MockTabModelSelector(3, 3, null); TabModelSelector selector1 = new MockTabModelSelector(2, 1, null); writeStateFile(selector0, 0); writeStateFile(selector1, 1); TabModelSelector selectorIn0 = new MockTabModelSelector(0, 0, null); TabModelSelector selectorIn1 = new MockTabModelSelector(0, 0, null); TabPersistentStore storeIn0 = new TabPersistentStore(selectorIn0, 0, getInstrumentation().getTargetContext(), null, null); TabPersistentStore storeIn1 = new TabPersistentStore(selectorIn1, 1, getInstrumentation().getTargetContext(), null, null); disableReporting(); storeIn0.loadStateInternal(); storeIn1.loadStateInternal(); assertEquals("Unexpected number of tabs to load", 6, storeIn0.getRestoredTabCount()); assertEquals("Unexpected number of tabst o load", 3, storeIn1.getRestoredTabCount()); }
/** @return Number of restored tabs on cold startup. */ public int getRestoredTabCount() { return mTabSaver.getRestoredTabCount(); }
/** * Should be called once the native library is loaded so that the actual internals of this class * can be initialized. * * @param tabContentProvider A {@link TabContentManager} instance. */ public void onNativeLibraryReady(TabContentManager tabContentProvider) { assert !mActiveState : "onNativeLibraryReady called twice!"; mTabContentManager = tabContentProvider; TabModel normalModel = new TabModelImpl( false, mActivity, mUma, mOrderController, mTabContentManager, mTabSaver, this); TabModel incognitoModel = new OffTheRecordTabModel( new TabModelImplCreator( mActivity, mUma, mOrderController, mTabContentManager, mTabSaver, this)); initialize(isIncognitoSelected(), normalModel, incognitoModel); mRegularTabCreator.setTabModel(normalModel, mTabContentManager); mIncognitoTabCreator.setTabModel(incognitoModel, mTabContentManager); mTabSaver.setTabContentManager(tabContentProvider); addObserver( new EmptyTabModelSelectorObserver() { @Override public void onNewTabCreated(Tab tab) { // Only invalidate if the tab exists in the currently selected model. if (TabModelUtils.getTabById(getCurrentModel(), tab.getId()) != null) { mTabContentManager.invalidateIfChanged(tab.getId(), tab.getUrl()); } } }); mActiveState = true; new TabModelSelectorTabObserver(this) { @Override public void onUrlUpdated(Tab tab) { TabModel model = getModelForTabId(tab.getId()); if (model == getCurrentModel()) { mTabContentManager.invalidateIfChanged(tab.getId(), tab.getUrl()); } } @Override public void onLoadStopped(Tab tab) { handleOnPageLoadStopped(tab); } @Override public void onPageLoadStarted(Tab tab, String url) { String previousUrl = tab.getUrl(); if (NativePageFactory.isNativePageUrl(previousUrl, tab.isIncognito())) { mTabContentManager.invalidateTabThumbnail(tab.getId(), previousUrl); } else { mTabContentManager.removeTabThumbnail(tab.getId()); } } @Override public void onPageLoadFinished(Tab tab) { mUma.onPageLoadFinished(tab.getId()); } @Override public void onPageLoadFailed(Tab tab, int errorCode) { mUma.onPageLoadFailed(tab.getId()); } @Override public void onCrash(Tab tab, boolean sadTabShown) { if (sadTabShown) { mTabContentManager.removeTabThumbnail(tab.getId()); } mUma.onTabCrashed(tab.getId()); } }; }
public void clearEncryptedState() { mTabSaver.clearEncryptedState(); }
public void clearState() { mTabSaver.clearState(); }
/** * If there is an asynchronous session restore in-progress, try to synchronously restore the state * of a tab with the given id as a frozen tab. This method has no effect if there isn't a tab * being restored with this id, or the tab has already been restored. * * @return true if there exists a tab with the id. */ public boolean tryToRestoreTabStateForId(int id) { if (!isSessionRestoreInProgress()) return false; return mTabSaver.restoreTabStateForId(id); }
/** * If there is an asynchronous session restore in-progress, try to synchronously restore the state * of a tab with the given url as a frozen tab. This method has no effect if there isn't a tab * being restored with this url, or the tab has already been restored. * * @return true if there exists a tab with the url. */ public boolean tryToRestoreTabStateForUrl(String url) { if (!isSessionRestoreInProgress()) return false; return mTabSaver.restoreTabStateForUrl(url); }
/** * Restore the saved tabs which were loaded by {@link #loadState}. * * @param setActiveTab If true, synchronously load saved active tab and set it as the current * active tab. */ public void restoreTabs(boolean setActiveTab) { mTabSaver.restoreTabs(setActiveTab); }
/** * Load the saved tab state. This should be called before any new tabs are created. The saved tabs * shall not be restored until {@link #restoreTabs} is called. */ public void loadState() { int nextId = mTabSaver.loadState(); if (nextId >= 0) Tab.incrementIdCounterTo(nextId); }
public void saveState() { commitAllTabClosures(); mTabSaver.saveState(); }
/** * Creates a new tab and posts to UI. * * @param loadUrlParams parameters of the url load. * @param type Information about how the tab was launched. * @param parent the parent tab, if present. * @param position the requested position (index in the tab model) * @param intent the source of the url if it isn't null. * @return The new tab. */ public ChromeTab createNewTab( LoadUrlParams loadUrlParams, TabModel.TabLaunchType type, Tab parent, int position, Intent intent) { try { TraceEvent.begin("ChromeTabCreator.createNewTab"); int parentId = parent != null ? parent.getId() : Tab.INVALID_TAB_ID; WebContents webContents = IntentHandler.getWebContentsFromIntent(intent); boolean isWebContentsPaused = false; if (webContents != null) { // The WebContents comes with additional data, but it shouldn't be used if the // WebContents itself couldn't be parsed out. parentId = IntentUtils.safeGetIntExtra( intent, IntentHandler.EXTRA_PARENT_TAB_ID, Tab.INVALID_TAB_ID); isWebContentsPaused = IntentUtils.safeGetBooleanExtra(intent, IntentHandler.EXTRA_WEB_CONTENTS_PAUSED, false); } // Sanitize the url. loadUrlParams.setUrl(UrlUtilities.fixupUrl(loadUrlParams.getUrl())); loadUrlParams.setTransitionType(getTransitionType(type)); boolean openInForeground = mOrderController.willOpenInForeground(type, mIncognito) || webContents != null; ChromeTab tab; if (webContents != null) { tab = ChromeTab.createLiveTab( Tab.INVALID_TAB_ID, mActivity, mIncognito, mNativeWindow, type, parentId, !openInForeground); tab.initialize(webContents, mTabContentManager, !openInForeground); tab.getTabRedirectHandler().updateIntent(intent); if (isWebContentsPaused) webContents.resumeLoadingCreatedWebContents(); } else if (!openInForeground && SysUtils.isLowEndDevice()) { // On low memory devices the tabs opened in background are not loaded automatically // to preserve resources (cpu, memory, strong renderer binding) for the foreground // tab. tab = ChromeTab.createTabForLazyLoad( mActivity, mIncognito, mNativeWindow, type, parentId, loadUrlParams); tab.initialize(null, mTabContentManager, !openInForeground); mTabSaver.addTabToSaveQueue(tab); tab.getTabRedirectHandler().updateIntent(intent); } else { tab = ChromeTab.createLiveTab( Tab.INVALID_TAB_ID, mActivity, mIncognito, mNativeWindow, type, parentId, !openInForeground); webContents = WarmupManager.getInstance().hasPrerenderedUrl(loadUrlParams.getUrl()) ? WarmupManager.getInstance().takePrerenderedWebContents() : null; tab.initialize(webContents, mTabContentManager, !openInForeground); tab.getTabRedirectHandler().updateIntent(intent); tab.loadUrl(loadUrlParams); } if (intent != null && intent.hasExtra(ServiceTabLauncher.LAUNCH_REQUEST_ID_EXTRA)) { ServiceTabLauncher.onWebContentsForRequestAvailable( intent.getIntExtra(ServiceTabLauncher.LAUNCH_REQUEST_ID_EXTRA, 0), tab.getWebContents()); } mTabModel.addTab(tab, position, type); return tab; } finally { TraceEvent.end("ChromeTabCreator.createNewTab"); } }
private void handleOnPageLoadStopped(Tab tab) { if (tab != null) mTabSaver.addTabToSaveQueue(tab); }