Skip to content

Commit

Permalink
Private windows recreation fixes (#1554)
Browse files Browse the repository at this point in the history
* Save windows state in onPause

* Telemetry crash fix

* Null check

* Fixes issue restoring private pages

* Do not persist private sessions
  • Loading branch information
keianhzo authored and bluemarvin committed Aug 16, 2019
1 parent 1bed30f commit 0881c56
Show file tree
Hide file tree
Showing 12 changed files with 199 additions and 147 deletions.
Expand Up @@ -312,8 +312,6 @@ protected void onStop() {
}

TelemetryWrapper.stop();

mWindows.onStop();
}

@Override
Expand All @@ -327,6 +325,8 @@ protected void onPause() {

SessionStore.get().onPause();

mWindows.onPause();

for (Widget widget: mWidgets.values()) {
widget.onPause();
}
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -70,7 +70,7 @@ public Builder() {
}

public Builder withMultiprocess(boolean isMultiprocessEnabled){
this.isMltiprocessEnabled = isMultiprocessEnabled;
this.isMultiprocessEnabled = isMultiprocessEnabled;
return this;
}

Expand Down
Expand Up @@ -35,14 +35,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;

Expand All @@ -69,8 +66,7 @@ public class SessionStack implements ContentBlocking.Delegate, GeckoSession.Navi
private transient UserAgentOverride mUserAgentOverride;

private transient GeckoSession mCurrentSession;
private HashMap<Integer, SessionState> mSessions;
private Deque<Integer> mSessionsStack;
private LinkedHashMap<Integer, SessionState> mSessions;
private transient GeckoSession.PermissionDelegate mPermissionDelegate;
private transient GeckoSession.PromptDelegate mPromptDelegate;
private int mPreviousGeckoSessionId = NO_SESSION;
Expand All @@ -79,11 +75,11 @@ public class SessionStack implements ContentBlocking.Delegate, GeckoSession.Navi
private transient SharedPreferences mPrefs;
private transient GeckoRuntime mRuntime;
private boolean mUsePrivateMode;
private transient byte[] mPrivatePage;

protected SessionStack(Context context, GeckoRuntime runtime, boolean usePrivateMode) {
mRuntime = runtime;
mSessions = new LinkedHashMap<>();
mSessionsStack = new ArrayDeque<>();
mUsePrivateMode = usePrivateMode;

mNavigationListeners = new LinkedList<>();
Expand All @@ -100,6 +96,9 @@ protected SessionStack(Context context, GeckoRuntime runtime, boolean usePrivate
mContext = context;
mPrefs = PreferenceManager.getDefaultSharedPreferences(mContext);

InternalPages.PageResources pageResources = InternalPages.PageResources.create(R.raw.private_mode, R.raw.private_style);
mPrivatePage = InternalPages.createAboutPage(mContext, pageResources);

if (mUserAgentOverride == null) {
mUserAgentOverride = new UserAgentOverride();
mUserAgentOverride.loadOverridesFromAssets((Activity)mContext, mContext.getString(R.string.user_agent_override_file));
Expand All @@ -112,7 +111,6 @@ protected void shutdown() {
}

mSessions.clear();
mSessionsStack.clear();

mNavigationListeners.clear();
mProgressListeners.clear();
Expand Down Expand Up @@ -260,13 +258,10 @@ 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<Integer, Integer> oldNewSessionId = new HashMap<>();
for (Map.Entry<Integer, SessionState> entry : store.mSessions.entrySet()) {
SessionState state = entry.getValue();

Expand Down Expand Up @@ -294,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);
Expand All @@ -313,12 +307,12 @@ public void restore(SessionStack store, int currentSessionId) {
if (entry.getKey() == currentSessionId) {
setCurrentSession(newSessionId);
}
}

for (Iterator<Integer> it = store.mSessionsStack.descendingIterator(); it.hasNext();) {
int oldSessionId = it.next();
int newSessionId = oldNewSessionId.get(oldSessionId);
mSessionsStack.push(newSessionId);
if (mUsePrivateMode) {
loadPrivateBrowsingPage();
}

dumpAllState(state.mSession);
}
}

Expand Down Expand Up @@ -371,26 +365,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<Integer, SessionState> sessions = (Map<Integer, SessionState>) 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) {
Expand All @@ -412,62 +407,25 @@ 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().withDefaultSettings(mContext).build();
int id = createSession(settings);
stackSession(id);
setCurrentSession(id);
}

public void newSessionWithUrl(String url) {
newSession();
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);
}
}

Expand Down Expand Up @@ -610,14 +568,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() {
Expand All @@ -628,7 +585,8 @@ public void goBack() {
exitFullScreen();

} else {
SessionState state = mSessions.get(getCurrentSessionId());
int sessionId = getCurrentSessionId();
SessionState state = mSessions.get(sessionId);
if (state.mCanGoBack) {
getCurrentSession().goBack();

Expand Down Expand Up @@ -679,6 +637,14 @@ public void loadUri(String aUri) {
mCurrentSession.loadUri(aUri);
}

public void loadPrivateBrowsingPage() {
if (mCurrentSession == null) {
return;
}

mCurrentSession.loadData(mPrivatePage, "text/html");
}

public void toggleServo() {
if (mCurrentSession == null) {
return;
Expand Down Expand Up @@ -789,23 +755,25 @@ public void setUaMode(int mode) {
}

protected void setMultiprocess(final boolean aEnabled) {
if (mCurrentSession != null) {
SessionState state = mSessions.get(mCurrentSession.hashCode());
for (Map.Entry<Integer, SessionState> 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<Integer, SessionState> entry : mSessions.entrySet()) {
SessionState state = entry.getValue();
if (state != null && state.mSettings.isTrackingProtectionEnabled() != aEnabled) {
state.mSettings.setTrackingProtectionEnabled(aEnabled);
recreateSession(state.mSettings);
}
}

recreateAllSessions();
}

// NavigationDelegate
Expand Down Expand Up @@ -915,36 +883,35 @@ public void onCanGoForward(@NonNull GeckoSession aSession, boolean aCanGoForward
public GeckoResult<GeckoSession> 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
public GeckoResult<String> onLoadError(@NonNull GeckoSession session, String uri, @NonNull WebRequestError error) {
Log.d(LOGTAG, "SessionStack onLoadError: " + uri);

return GeckoResult.fromValue(InternalPages.createErrorPage(mContext, uri, error.category, error.code));
return GeckoResult.fromValue(InternalPages.createErrorPageDataURI(mContext, uri, error.category, error.code));
}

// Progress Listener
Expand Down

0 comments on commit 0881c56

Please sign in to comment.