Skip to content
This repository has been archived by the owner on Jul 22, 2024. It is now read-only.

Commit

Permalink
Limit total number of GeckoSessions created to prevent OOM (#2295)
Browse files Browse the repository at this point in the history
  • Loading branch information
bluemarvin authored Nov 18, 2019
1 parent 1e495fb commit 2333f6e
Show file tree
Hide file tree
Showing 5 changed files with 84 additions and 18 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ protected Session(Context aContext, GeckoRuntime aRuntime,
mRuntime = aRuntime;
initialize();
mState = createSession(aSettings, aOpenMode);
mState.setActive(true);
}

protected Session(Context aContext, GeckoRuntime aRuntime, @NonNull SessionState aRestoreState) {
Expand Down Expand Up @@ -325,7 +326,7 @@ private void cleanSessionListeners(GeckoSession aSession) {
}

public void suspend() {
if (mState.mIsActive) {
if (mState.isActive()) {
Log.e(LOGTAG, "Active Sessions can not be suspended");
return;
}
Expand All @@ -345,29 +346,34 @@ private void restore() {
.build();
}

String restoreUri = mState.mUri;

mState.mSession = createGeckoSession(settings);
if (!mState.mSession.isOpen()) {
mState.mSession.open(mRuntime);
}

// data:text URLs can not be restored.
if (mState.mSessionState != null && ((mState.mUri == null) || mState.mUri.startsWith("data:text"))) {
mState.mSessionState = null;
mState.mUri = null;
}

if (mState.mSessionState != null) {
mState.mSession.restoreState(mState.mSessionState);
}

if ((mState.mSessionState == null) && (restoreUri != null)) {
mState.mSession.loadUri(restoreUri);
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.equals(mContext.getResources().getString(R.string.about_blank)) ||
} 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")) {
mState.mSession.loadUri(mState.mUri, GeckoSession.LOAD_FLAGS_REPLACE_HISTORY);
}

dumpAllState();
mState.setActive(true);
}


Expand Down Expand Up @@ -410,6 +416,7 @@ private void recreateSession() {
SessionState previous = mState;

mState = createSession(previous.mSettings, SESSION_OPEN);
mState.setActive(true);
if (previous.mSessionState != null) {
mState.mSession.restoreState(previous.mSessionState);
}
Expand All @@ -435,7 +442,7 @@ private void closeSession(@NonNull SessionState aState) {
aState.mDisplay = null;
}
aState.mSession.close();
aState.mIsActive = false;
aState.setActive(false);
}

public void captureBitmap() {
Expand Down Expand Up @@ -596,18 +603,19 @@ public void goForward() {

public void setActive(boolean aActive) {
// Flush the events queued while the session was inactive
if (mState.mSession != null && !mState.mIsActive && aActive) {
if (mState.mSession != null && !mState.isActive() && aActive) {
flushQueuedEvents();
}

if (mState.mSession != null) {
mState.mSession.setActive(aActive);
} else {
mState.setActive(aActive);
} else if (aActive) {
restore();
} else {
Log.e(LOGTAG, "ERROR: Setting null GeckoView to inactive!");
}

mState.mIsActive = aActive;

for (SessionChangeListener listener: mSessionChangeListeners) {
listener.onActiveStateChange(this, aActive);
}
Expand Down Expand Up @@ -661,6 +669,7 @@ public void toggleServo() {

mState = createSession(settings, SESSION_OPEN);
closeSession(previous);
mState.setActive(true);
loadUri(uri);
}

Expand Down Expand Up @@ -705,7 +714,7 @@ public int getUaMode() {
}

public boolean isActive() {
return mState.mIsActive;
return mState.isActive();
}

private static final String M_PREFIX = "m.";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
package org.mozilla.vrbrowser.browser.engine;

import android.graphics.Bitmap;

import androidx.annotation.Nullable;

import com.google.gson.Gson;
import com.google.gson.JsonParser;
import com.google.gson.JsonSyntaxException;
import com.google.gson.TypeAdapter;
import com.google.gson.TypeAdapterFactory;
import com.google.gson.annotations.JsonAdapter;
Expand All @@ -25,7 +20,7 @@

@JsonAdapter(SessionState.SessionStateAdapterFactory.class)
public class SessionState {
public transient boolean mIsActive;
private transient boolean mIsActive;
public boolean mCanGoBack;
public boolean mCanGoForward;
public boolean mIsLoading;
Expand Down Expand Up @@ -64,6 +59,18 @@ public GeckoSession.SessionState read(JsonReader in) {
}
}

boolean isActive() {
return mIsActive;
}

void setActive(boolean active) {
if (active == mIsActive) {
return;
}
mIsActive = active;
SessionStore.get().sessionActiveStateChanged();
}

public class SessionStateAdapterFactory implements TypeAdapterFactory {
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
package org.mozilla.vrbrowser.browser.engine;

import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.os.Bundle;
import android.util.Log;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

import org.mozilla.gecko.util.ThreadUtils;
import org.mozilla.geckoview.ContentBlocking;
import org.mozilla.geckoview.GeckoRuntime;
import org.mozilla.geckoview.GeckoRuntimeSettings;
Expand All @@ -20,11 +23,15 @@
import org.mozilla.vrbrowser.browser.Services;
import org.mozilla.vrbrowser.browser.SettingsStore;
import org.mozilla.vrbrowser.crashreporting.CrashReporterService;
import org.mozilla.vrbrowser.utils.SystemUtils;

import java.security.KeyStore;
import java.util.ArrayList;
import java.util.List;

public class SessionStore implements GeckoSession.PermissionDelegate {
private static final String LOGTAG = SystemUtils.createLogtag(SessionStore.class);
private static final int MAX_GECKO_SESSIONS = 5;

private static final String[] WEB_EXTENSIONS = new String[] {
"webcompat_vimeo",
Expand All @@ -48,6 +55,7 @@ public static SessionStore get() {
private BookmarksStore mBookmarksStore;
private HistoryStore mHistoryStore;
private Services mServices;
private boolean mSuspendPending;

private SessionStore() {
mSessions = new ArrayList<>();
Expand Down Expand Up @@ -113,6 +121,7 @@ private Session addSession(@NonNull Session aSession) {
aSession.setPermissionDelegate(this);
aSession.addNavigationListener(mServices);
mSessions.add(aSession);
sessionActiveStateChanged();
return aSession;
}

Expand Down Expand Up @@ -173,9 +182,46 @@ public void suspendAllInactiveSessions() {
}

public void setActiveSession(Session aSession) {
if (aSession != null) {
aSession.setActive(true);
}
mActiveSession = aSession;
}


private void limitInactiveSessions() {
Log.d(LOGTAG, "Limiting Inactive Sessions");
suspendAllInactiveSessions();
mSuspendPending = false;
}

void sessionActiveStateChanged() {
if (mSuspendPending) {
return;
}
int count = 0;
int activeCount = 0;
int inactiveCount = 0;
int suspendedCount = 0;
for(Session session: mSessions) {
if (session.getGeckoSession() != null) {
count++;
if (session.isActive()) {
activeCount++;
} else {
inactiveCount++;
}
} else {
suspendedCount++;
}
}
if (count > MAX_GECKO_SESSIONS) {
Log.d(LOGTAG, "Too many GeckoSessions. Active: " + activeCount + " Inactive: " + inactiveCount + " Suspended: " + suspendedCount);
mSuspendPending = true;
ThreadUtils.postToUiThread(this::limitInactiveSessions);
}
}

public Session getActiveSession() {
return mActiveSession;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,7 @@ public boolean isLayer() {
return mSurface != null && mTexture == null;
}


@Override
public void setVisible(boolean aVisible) {
if (mWidgetPlacement.visible == aVisible) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -667,6 +667,9 @@ private void removeWindow(@NonNull WindowWidget aWindow) {
}

private void setWindowVisible(@NonNull WindowWidget aWindow, boolean aVisible) {
if (aVisible && (aWindow.getSession() != null) && (aWindow.getSession().getGeckoSession() == null)) {
setFirstPaint(aWindow, aWindow.getSession());
}
aWindow.setVisible(aVisible);
aWindow.getTopBar().setVisible(aVisible);
aWindow.getTitleBar().setVisible(aVisible);
Expand Down

0 comments on commit 2333f6e

Please sign in to comment.