diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionSettings.java b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionSettings.java index 896ebe37b..2148d8e9f 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionSettings.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionSettings.java @@ -15,7 +15,7 @@ class SessionSettings { private boolean isServoEnabled; private SessionSettings(@NotNull Builder builder) { - this.isMultiprocessEnabled = builder.isMltiprocessEnabled; + this.isMultiprocessEnabled = builder.isMultiprocessEnabled; this.isTrackingProtectionEnabled = builder.isTrackingProtectionEnabled; this.isSuspendMediaWhenInactiveEnabled = builder.isSuspendMediaWhenInactiveEnabled; this.userAgentMode = builder.userAgentMode; @@ -60,7 +60,7 @@ public void setServoEnabled(boolean enabled) { public static class Builder { - private boolean isMltiprocessEnabled; + private boolean isMultiprocessEnabled; private boolean isTrackingProtectionEnabled; private boolean isSuspendMediaWhenInactiveEnabled; private int userAgentMode; @@ -70,7 +70,7 @@ public Builder() { } public Builder withMultiprocess(boolean isMultiprocessEnabled){ - this.isMltiprocessEnabled = isMultiprocessEnabled; + this.isMultiprocessEnabled = isMultiprocessEnabled; return this; } diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionStack.java b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionStack.java index 619c730ee..313c58e8c 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionStack.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/engine/SessionStack.java @@ -24,6 +24,7 @@ import org.mozilla.geckoview.GeckoSession; import org.mozilla.geckoview.GeckoSessionSettings; import org.mozilla.geckoview.MediaElement; +import org.mozilla.geckoview.StorageController; import org.mozilla.geckoview.WebRequestError; import org.mozilla.vrbrowser.R; import org.mozilla.vrbrowser.browser.Media; @@ -35,14 +36,11 @@ import org.mozilla.vrbrowser.telemetry.TelemetryWrapper; import org.mozilla.vrbrowser.utils.InternalPages; -import java.util.ArrayDeque; -import java.util.Deque; +import java.util.ArrayList; import java.util.HashMap; -import java.util.Iterator; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.Map; -import java.util.NoSuchElementException; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicInteger; @@ -70,8 +68,7 @@ public class SessionStack implements ContentBlocking.Delegate, GeckoSession.Navi private transient UserAgentOverride mUserAgentOverride; private transient GeckoSession mCurrentSession; - private HashMap mSessions; - private Deque mSessionsStack; + private LinkedHashMap mSessions; private transient GeckoSession.PermissionDelegate mPermissionDelegate; private int mPreviousGeckoSessionId = NO_SESSION; private String mRegion; @@ -83,7 +80,6 @@ public class SessionStack implements ContentBlocking.Delegate, GeckoSession.Navi protected SessionStack(Context context, GeckoRuntime runtime, boolean usePrivateMode) { mRuntime = runtime; mSessions = new LinkedHashMap<>(); - mSessionsStack = new ArrayDeque<>(); mUsePrivateMode = usePrivateMode; mNavigationListeners = new LinkedList<>(); @@ -113,7 +109,6 @@ protected void shutdown() { } mSessions.clear(); - mSessionsStack.clear(); mNavigationListeners.clear(); mProgressListeners.clear(); @@ -262,13 +257,11 @@ public void removeVideoAvailabilityListener(VideoAvailabilityListener aListener) public void restore(SessionStack store, int currentSessionId) { mSessions.clear(); - mSessionsStack.clear(); mPreviousGeckoSessionId = store.mPreviousGeckoSessionId; mRegion = store.mRegion; mUsePrivateMode = store.mUsePrivateMode; - HashMap oldNewSessionId = new HashMap<>(); for (Map.Entry entry : store.mSessions.entrySet()) { SessionState state = entry.getValue(); @@ -296,7 +289,6 @@ public void restore(SessionStack store, int currentSessionId) { } int newSessionId = state.mSession.hashCode(); - oldNewSessionId.put(entry.getKey(), newSessionId); state.mSession.setNavigationDelegate(this); state.mSession.setProgressDelegate(this); @@ -316,12 +308,6 @@ public void restore(SessionStack store, int currentSessionId) { setCurrentSession(newSessionId); } } - - for (Iterator it = store.mSessionsStack.descendingIterator(); it.hasNext();) { - int oldSessionId = it.next(); - int newSessionId = oldNewSessionId.get(oldSessionId); - mSessionsStack.push(newSessionId); - } } private int createSession() { @@ -373,26 +359,27 @@ private int createSession(@NonNull SessionSettings aSettings) { return result; } - private void recreateSession(SessionSettings aSettings) { - if (mCurrentSession != null) { - SessionState state = mSessions.get(mCurrentSession.hashCode()); - if (state == null) { - return; - } - mCurrentSession.stop(); - mCurrentSession.close(); - - int oldSessionId = getCurrentSessionId(); - int sessionId = createSession(aSettings); - GeckoSession session = getSession(sessionId); - if (state.mSessionState != null) { - session.restoreState(state.mSessionState); - } - setCurrentSession(sessionId); - removeSession(oldSessionId); + private void recreateAllSessions() { + Map sessions = (Map) mSessions.clone(); + for (Integer sessionId : sessions.keySet()) { + recreateSession(sessionId); } } + private void recreateSession(int sessionId) { + SessionState previousSessionState = mSessions.get(sessionId); + + previousSessionState.mSession.stop(); + previousSessionState.mSession.close(); + + int newSessionId = createSession(previousSessionState.mSettings); + GeckoSession session = mSessions.get(newSessionId).mSession; + if (previousSessionState.mSessionState != null) + session.restoreState(previousSessionState.mSessionState); + setCurrentSession(newSessionId); + removeSession(sessionId); + } + private void removeSession(int aSessionId) { GeckoSession session = getSession(aSessionId); if (session != null) { @@ -414,31 +401,10 @@ private void removeSession(int aSessionId) { } } - private void pushSession(int aSessionId) { - mSessionsStack.push(aSessionId); - } - - private Integer popSession() { - Integer sessionId; - try { - sessionId = mSessionsStack.pop(); - - } catch (NoSuchElementException e) { - sessionId = new Integer(NO_SESSION); - } - - return sessionId; - } - - private Integer peekSession() { - Integer sessionId = mSessionsStack.peek(); - return sessionId == null ? NO_SESSION : sessionId; - } - public void newSession() { SessionSettings settings = new SessionSettings.Builder().build(); int id = createSession(settings); - stackSession(id); + setCurrentSession(id); } public void newSessionWithUrl(String url) { @@ -446,29 +412,14 @@ public void newSessionWithUrl(String url) { loadUri(url); } - private void stackSession(int sessionId) { - int currentSessionId = getCurrentSessionId(); - if (currentSessionId != NO_SESSION) - pushSession(currentSessionId); - setCurrentSession(sessionId); - - mCurrentSession = null; - SessionState state = mSessions.get(sessionId); - if (state != null) { - mCurrentSession = state.mSession; - for (SessionChangeListener listener : mSessionChangeListeners) { - listener.onCurrentSessionChange(mCurrentSession, sessionId); - } - } - dumpAllState(mCurrentSession); - } - private void unstackSession() { - Integer prevSessionId = popSession(); - if (prevSessionId != NO_SESSION) { - int currentSession = getCurrentSessionId(); + int currentSessionId = getCurrentSessionId(); + ArrayList sessionsStack = new ArrayList<>(mSessions.keySet()); + int index = sessionsStack.indexOf(currentSessionId); + if (index > 0) { + int prevSessionId = (Integer)sessionsStack.get(index-1); setCurrentSession(prevSessionId); - removeSession(currentSession); + removeSession(currentSessionId); } } @@ -610,14 +561,13 @@ public boolean canGoBack() { return false; } - Integer prevSessionId = peekSession(); SessionState state = mSessions.get(mCurrentSession.hashCode()); boolean canGoBack = false; if (state != null) { canGoBack = state.mCanGoBack; } - return canGoBack || prevSessionId != NO_SESSION; + return canGoBack || mSessions.size() > 1; } public void goBack() { @@ -628,7 +578,8 @@ public void goBack() { exitFullScreen(); } else { - SessionState state = mSessions.get(getCurrentSessionId()); + int sessionId = getCurrentSessionId(); + SessionState state = mSessions.get(sessionId); if (state.mCanGoBack) { getCurrentSession().goBack(); @@ -789,23 +740,46 @@ public void setUaMode(int mode) { } protected void setMultiprocess(final boolean aEnabled) { - if (mCurrentSession != null) { - SessionState state = mSessions.get(mCurrentSession.hashCode()); + for (Map.Entry entry : mSessions.entrySet()) { + SessionState state = entry.getValue(); if (state != null && state.mSettings.isMultiprocessEnabled() != aEnabled) { state.mSettings.setMultiprocessEnabled(aEnabled); - recreateSession(state.mSettings); } } + + recreateAllSessions(); } protected void setTrackingProtection(final boolean aEnabled) { - if (mCurrentSession != null) { - SessionState state = mSessions.get(mCurrentSession.hashCode()); + for (Map.Entry entry : mSessions.entrySet()) { + SessionState state = entry.getValue(); if (state != null && state.mSettings.isTrackingProtectionEnabled() != aEnabled) { state.mSettings.setTrackingProtectionEnabled(aEnabled); - recreateSession(state.mSettings); } } + + recreateAllSessions(); + } + + public void clearCache() { + 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- + for (Map.Entry entry : mSessions.entrySet()) { + SessionState state = entry.getValue(); + if (state != null) { + state.mSession.stop(); + state.mSession.close(); + } + } + + mRuntime.getStorageController().clearData(StorageController.ClearFlags.ALL_CACHES).then(aVoid -> { + recreateAllSessions(); + return null; + }); + } } // NavigationDelegate @@ -915,29 +889,28 @@ public void onCanGoForward(@NonNull GeckoSession aSession, boolean aCanGoForward public GeckoResult onNewSession(@NonNull GeckoSession aSession, @NonNull String aUri) { Log.d(LOGTAG, "SessionStack onNewSession: " + aUri); - pushSession(getCurrentSessionId()); - int sessionId; - boolean isPreviousPrivateMode = mCurrentSession.getSettings().getUsePrivateMode(); - SessionSettings settings = new SessionSettings.Builder() + SessionState state = mSessions.get(getCurrentSessionId()); + if (state != null) { + sessionId = createSession(state.mSettings); + + } else { + SessionSettings settings = new SessionSettings.Builder() .withDefaultSettings(mContext) .build(); - sessionId = createSession(settings); - - mCurrentSession = null; - SessionState state = mSessions.get(sessionId); - if (state != null) { - mCurrentSession = state.mSession; + sessionId = createSession(settings); + } - if (mCurrentSession != aSession) { - for (SessionChangeListener listener : mSessionChangeListeners) { - listener.onCurrentSessionChange(mCurrentSession, sessionId); - } + state = mSessions.get(sessionId); + mCurrentSession = state.mSession; + if (mCurrentSession != aSession) { + for (SessionChangeListener listener : mSessionChangeListeners) { + listener.onCurrentSessionChange(mCurrentSession, sessionId); } } dumpAllState(mCurrentSession); - return GeckoResult.fromValue(getSession(sessionId)); + return GeckoResult.fromValue(mCurrentSession); } @Override 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 d165d8b67..bec326137 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 @@ -220,9 +220,7 @@ public void setAutoplayEnabled(final boolean enabled) { public boolean getAutoplayEnabled() { if (mRuntime != null) { - return mRuntime.getSettings().getAutoplayDefault() == GeckoRuntimeSettings.AUTOPLAY_DEFAULT_ALLOWED ? - true : - false; + return mRuntime.getSettings().getAutoplayDefault() == GeckoRuntimeSettings.AUTOPLAY_DEFAULT_ALLOWED; } return false; @@ -234,6 +232,12 @@ public void setLocales(List locales) { } } + public void clearCache() { + for (Map.Entry entry : mSessionStacks.entrySet()) { + entry.getValue().clearCache(); + } + } + // Permission Delegate @Override diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/PrivacyOptionsView.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/PrivacyOptionsView.java index 9498b71b2..8283d1784 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/PrivacyOptionsView.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/settings/PrivacyOptionsView.java @@ -62,6 +62,10 @@ private void initialize(Context aContext) { exitWholeSettings(); }); + mBinding.clearCacheButton.setOnClickListener(v -> { + SessionStore.get().clearCache(); + }); + TextView permissionsTitleText = findViewById(R.id.permissionsTitle); permissionsTitleText.setText(getContext().getString(R.string.security_options_permissions_title, getContext().getString(R.string.app_name))); diff --git a/app/src/main/res/layout/options_developer.xml b/app/src/main/res/layout/options_developer.xml index 22c3b3ca4..8b49d2d01 100644 --- a/app/src/main/res/layout/options_developer.xml +++ b/app/src/main/res/layout/options_developer.xml @@ -15,11 +15,11 @@ android:id="@+id/header_layout" android:layout_width="match_parent" android:layout_height="wrap_content" + app:helpVisibility="gone" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" - app:title="@string/settings_developer_options" - app:helpVisibility="gone" /> + app:title="@string/settings_developer_options" /> + + Enable Servo + + Clear Cache + + + Clear + Display Density: