From 0e55c770d1b05b3dcf74f9c85af60c14ff64b6be Mon Sep 17 00:00:00 2001 From: "Randall E. Barker" Date: Mon, 25 Nov 2019 09:11:44 -0800 Subject: [PATCH] Ensure Sessions are recreated correctly when clearing data (#2362) * Ensure Sessions are recreated correctly when clearing data - Fixes #2356 - Fixes issue where switching Multiprocess in the developer panel would freeze the session. - Fixes default private browsing page not getting displayed when recreating a private browsing session. * Improve onFirstContentfulPaintnotification --- .../vrbrowser/browser/engine/Session.java | 77 ++++++++++--------- .../browser/engine/SessionState.java | 15 ++++ .../browser/engine/SessionStore.java | 13 +++- .../vrbrowser/ui/widgets/WindowWidget.java | 2 +- 4 files changed, 70 insertions(+), 37 deletions(-) diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/Session.java b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/Session.java index 5fb88c74e..292e4fda2 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/Session.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/Session.java @@ -345,6 +345,24 @@ public void suspend() { mState.mSession = null; } + private boolean shouldLoadDefaultPage(@NonNull SessionState aState) { + if (aState.mUri != null && aState.mUri.length() != 0 && !aState.mUri.equals(mContext.getString(R.string.about_blank))) { + return false; + } + if (aState.mSessionState != null && aState.mSessionState.size() != 0) { + return false; + } + return true; + } + + private void loadDefaultPage() { + if (mState.mSettings.isPrivateBrowsingEnabled()) { + loadPrivateBrowsingPage(); + } else { + loadHomePage(); + } + } + private void restore() { SessionSettings settings = mState.mSettings; if (settings == null) { @@ -364,18 +382,17 @@ private void restore() { mState.mUri = null; } - if (mState.mSessionState != null) { + if (shouldLoadDefaultPage(mState)) { + loadDefaultPage(); + } else if (mState.mSessionState != null) { mState.mSession.restoreState(mState.mSessionState); + } else if (mState.mUri != null) { + mState.mSession.loadUri(mState.mUri); + } else { + loadDefaultPage(); } - if ((mState.mSessionState == null) && (mState.mUri != null)) { - mState.mSession.loadUri(mState.mUri); - } else if (mState.mSettings.isPrivateBrowsingEnabled() && mState.mUri == null) { - loadPrivateBrowsingPage(); - } else if(mState.mSessionState == null || ((mState.mUri == null) || mState.mUri.equals(mContext.getResources().getString(R.string.about_blank))) || - (mState.mSessionState != null && mState.mSessionState.size() == 0)) { - loadHomePage(); - } else if (mState.mUri != null && mState.mUri.contains(".youtube.com")) { + if (mState.mUri != null && mState.mUri.contains(".youtube.com")) { mState.mSession.loadUri(mState.mUri, GeckoSession.LOAD_FLAGS_REPLACE_HISTORY); } @@ -419,20 +436,19 @@ private GeckoSession createGeckoSession(@NonNull SessionSettings aSettings) { return session; } - private void recreateSession() { + public void recreateSession() { SessionState previous = mState; + mState = mState.recreate(); + restore(); - mState = createSession(previous.mSettings, SESSION_OPEN); - mState.setActive(true); - if (previous.mSessionState != null) { - mState.mSession.restoreState(previous.mSessionState); - } + GeckoSession previousGeckoSession = null; if (previous.mSession != null) { + previousGeckoSession = previous.mSession; closeSession(previous); } for (SessionChangeListener listener : mSessionChangeListeners) { - listener.onCurrentSessionChange(previous.mSession, mState.mSession); + listener.onCurrentSessionChange(previousGeckoSession, mState.mSession); } } @@ -444,12 +460,13 @@ private void closeSession(@NonNull SessionState aState) { aState.mSession.setActive(false); aState.mSession.stop(); if (aState.mDisplay != null) { - surfaceDestroyed(); + aState.mDisplay.surfaceDestroyed(); aState.mSession.releaseDisplay(aState.mDisplay); aState.mDisplay = null; } aState.mSession.close(); aState.setActive(false); + mFirstContentfulPaint = false; } public void captureBitmap() { @@ -788,24 +805,6 @@ protected void setTrackingProtection(final boolean aEnabled) { } } - public void clearCache(final long clearFlags) { - if (mRuntime != null) { - // Per GeckoView Docs: - // Note: Any open session may re-accumulate previously cleared data. - // To ensure that no persistent data is left behind, you need to close all sessions prior to clearing data. - // https://mozilla.github.io/geckoview/javadoc/mozilla-central/org/mozilla/geckoview/StorageController.html#clearData-long- - if (mState.mSession != null) { - mState.mSession.stop(); - mState.mSession.close(); - } - - mRuntime.getStorageController().clearData(clearFlags).then(aVoid -> { - recreateSession(); - return null; - }); - } - } - public void updateLastUse() { mState.mLastUse = System.currentTimeMillis(); } @@ -1055,6 +1054,14 @@ public void onFirstComposite(@NonNull GeckoSession aSession) { for (GeckoSession.ContentDelegate listener : mContentListeners) { listener.onFirstComposite(aSession); } + if (mFirstContentfulPaint) { + // onFirstContentfulPaint is only called once after a session is opened. + // Notify onFirstContentfulPaint after a session is reattached before + // being closed ((e.g. tab selected) + for (GeckoSession.ContentDelegate listener : mContentListeners) { + listener.onFirstContentfulPaint(aSession); + } + } } } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionState.java b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionState.java index 5a1c6a502..3fea1e87e 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionState.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionState.java @@ -41,6 +41,21 @@ public class SessionState { public String mId = UUID.randomUUID().toString(); public String mParentId; // Parent session stack Id. + public SessionState recreate() { + SessionState result = new SessionState(); + result.mUri = mUri; + result.mPreviousUri = mPreviousUri; + result.mTitle = mTitle; + result.mSettings = mSettings; + result.mSessionState = mSessionState; + result.mLastUse = mLastUse; + result.mRegion = mRegion; + result.mId = mId; + result.mParentId = mParentId; + + return result; + } + public static class GeckoSessionStateAdapter extends TypeAdapter { @Override public void write(JsonWriter out, GeckoSession.SessionState session) throws IOException { diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionStore.java b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionStore.java index 54fe71303..c86789d5d 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionStore.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionStore.java @@ -27,6 +27,7 @@ import java.security.KeyStore; import java.util.ArrayList; +import java.util.LinkedList; import java.util.List; public class SessionStore implements GeckoSession.PermissionDelegate { @@ -351,9 +352,19 @@ public void setLocales(List locales) { } public void clearCache(long clearFlags) { + LinkedList activeSession = new LinkedList<>(); for (Session session: mSessions) { - session.clearCache(clearFlags); + if (session.getGeckoSession() != null) { + session.suspend(); + activeSession.add(session); + } } + mRuntime.getStorageController().clearData(clearFlags).then(aVoid -> { + for (Session session: activeSession) { + session.recreateSession(); + } + return null; + }); } // Permission Delegate diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java index 9746e9a5b..95194c0f3 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/WindowWidget.java @@ -1109,13 +1109,13 @@ public void onCurrentSessionChange(GeckoSession aOldSession, GeckoSession aSessi } else { setPrivateBrowsingEnabled(false); } + waitForFirstPaint(); } @Override public void onStackSession(Session aSession) { // e.g. tab opened via window.open() aSession.updateLastUse(); - waitForFirstPaint(); Session current = mSession; setSession(aSession); SessionStore.get().setActiveSession(aSession);