diff --git a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java index 52a0f8707..0793e44d5 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/VRBrowserActivity.java @@ -6,6 +6,7 @@ package org.mozilla.vrbrowser; import android.content.BroadcastReceiver; +import android.content.ComponentCallbacks2; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; @@ -92,7 +93,7 @@ import java.util.concurrent.CopyOnWriteArrayList; import java.util.function.Consumer; -public class VRBrowserActivity extends PlatformActivity implements WidgetManagerDelegate { +public class VRBrowserActivity extends PlatformActivity implements WidgetManagerDelegate, ComponentCallbacks2 { private BroadcastReceiver mCrashReceiver = new BroadcastReceiver() { @Override @@ -637,6 +638,32 @@ private void postCrashFiles(final ArrayList aFiles) { }); } + @Override + public void onTrimMemory(int level) { + + // Determine which lifecycle or system event was raised. + switch (level) { + + case ComponentCallbacks2.TRIM_MEMORY_UI_HIDDEN: + case ComponentCallbacks2.TRIM_MEMORY_BACKGROUND: + case ComponentCallbacks2.TRIM_MEMORY_MODERATE: + case ComponentCallbacks2.TRIM_MEMORY_COMPLETE: + // Curently ignore these levels. They are handled somewhere else. + break; + case ComponentCallbacks2.TRIM_MEMORY_RUNNING_MODERATE: + case ComponentCallbacks2.TRIM_MEMORY_RUNNING_LOW: + case ComponentCallbacks2.TRIM_MEMORY_RUNNING_CRITICAL: + // It looks like these come in all at the same time so just always suspend inactive Sessions. + Log.d(LOGTAG, "Memory pressure, suspending inactive sessions."); + SessionStore.get().suspendAllInactiveSessions(); + break; + default: + Log.e(LOGTAG, "onTrimMemory unknown level: " + level); + break; + } + } + + @Override public void onBackPressed() { if (mIsPresentingImmersive) { diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/PromptDelegate.java b/app/src/common/shared/org/mozilla/vrbrowser/browser/PromptDelegate.java index 7768e0bd8..b42c7a355 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/PromptDelegate.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/PromptDelegate.java @@ -327,6 +327,9 @@ public static PopUpRequest newRequest(@NonNull PopupPrompt prompt, @NonNull Geck private SparseArray>> mPopUpRequests = new SparseArray<>(); public void showPopUps(GeckoSession session) { + if (session == null) { + return; + } Pair> requests = mPopUpRequests.get(session.hashCode()); if (requests != null && !requests.second.isEmpty()) { showPopUp(session.hashCode(), requests); @@ -334,9 +337,11 @@ public void showPopUps(GeckoSession session) { } public boolean hasPendingPopUps(GeckoSession session) { - Pair> requests = mPopUpRequests.get(session.hashCode()); - if (requests != null) { - return !requests.second.isEmpty(); + if (session != null) { + Pair> requests = mPopUpRequests.get(session.hashCode()); + if (requests != null) { + return !requests.second.isEmpty(); + } } return false; diff --git a/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt b/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt index 59ba9a251..cf92d931a 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt +++ b/app/src/common/shared/org/mozilla/vrbrowser/browser/Services.kt @@ -74,9 +74,9 @@ class Services(context: Context, places: Places): GeckoSession.NavigationDelegat override fun onEvents(events: List) { CoroutineScope(Dispatchers.Main).launch { Logger(logTag).info("Received ${events.size} device event(s)") - val events = events.filterIsInstance(DeviceEvent.TabReceived::class.java) - if (!events.isEmpty()) { - val tabs = events.map { event -> event.entries }.flatten() + val filteredEvents = events.filterIsInstance(DeviceEvent.TabReceived::class.java) + if (filteredEvents.isNotEmpty()) { + val tabs = filteredEvents.map { event -> event.entries }.flatten() tabReceivedDelegate?.onTabsReceived(tabs) } } 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 c9fff4cf2..32ea5cc73 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 @@ -81,9 +81,7 @@ public class Session implements ContentBlocking.Delegate, GeckoSession.Navigatio private transient Context mContext; private transient SharedPreferences mPrefs; private transient GeckoRuntime mRuntime; - private boolean mUsePrivateMode; private transient byte[] mPrivatePage; - private boolean mIsActive; public interface BitmapChangedListener { @@ -95,33 +93,19 @@ public interface BitmapChangedListener { public static final int SESSION_OPEN = 0; public static final int SESSION_DO_NOT_OPEN = 1; - protected Session(Context aContext, GeckoRuntime aRuntime, boolean aUsePrivateMode) { - this(aContext, aRuntime, aUsePrivateMode, null, SESSION_OPEN); - } - - protected Session(Context aContext, GeckoRuntime aRuntime, boolean aUsePrivateMode, - @Nullable SessionSettings aSettings, @SessionOpenModeFlags int aOpenMode) { + protected Session(Context aContext, GeckoRuntime aRuntime, + @NonNull SessionSettings aSettings, @SessionOpenModeFlags int aOpenMode) { mContext = aContext; mRuntime = aRuntime; - mUsePrivateMode = aUsePrivateMode; initialize(); - if (aSettings != null) { - mState = createSession(aSettings, aOpenMode); - } else { - mState = createSession(aOpenMode); - } - - setupSessionListeners(mState.mSession); + mState = createSession(aSettings, aOpenMode); } - protected Session(Context aContext, GeckoRuntime aRuntime, SessionState aRestoreState) { + protected Session(Context aContext, GeckoRuntime aRuntime, @NonNull SessionState aRestoreState) { mContext = aContext; mRuntime = aRuntime; - mUsePrivateMode = false; initialize(); mState = aRestoreState; - restore(); - setupSessionListeners(mState.mSession); } private void initialize() { @@ -154,6 +138,7 @@ protected void shutdown() { if (mState.mSession.isOpen()) { mState.mSession.close(); } + mState.mDisplay = null; mState.mSession = null; } @@ -339,6 +324,19 @@ private void cleanSessionListeners(GeckoSession aSession) { aSession.setSelectionActionDelegate(null); } + public void suspend() { + if (mState.mIsActive) { + Log.e(LOGTAG, "Active Sessions can not be suspended"); + return; + } + if (mState.mSession == null) { + return; + } + Log.d(LOGTAG, "Suspending Session: " + mState.mId); + closeSession(mState); + mState.mSession = null; + } + private void restore() { SessionSettings settings = mState.mSettings; if (settings == null) { @@ -347,34 +345,31 @@ private void restore() { .build(); } + String restoreUri = mState.mUri; + mState.mSession = createGeckoSession(settings); if (!mState.mSession.isOpen()) { mState.mSession.open(mRuntime); } - + if (mState.mSessionState != null) { mState.mSession.restoreState(mState.mSessionState); } - if (mUsePrivateMode) { + if ((mState.mSessionState == null) && (restoreUri != null)) { + mState.mSession.loadUri(restoreUri); + } else if (mState.mSettings.isPrivateBrowsingEnabled() && mState.mUri == null) { loadPrivateBrowsingPage(); } else if(mState.mSessionState == 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); + mState.mSession.loadUri(mState.mUri, GeckoSession.LOAD_FLAGS_REPLACE_HISTORY); } dumpAllState(); } - private SessionState createSession(@SessionOpenModeFlags int aOpenMode) { - SessionSettings settings = new SessionSettings.Builder() - .withDefaultSettings(mContext) - .build(); - - return createSession(settings, aOpenMode); - } private SessionState createSession(@NonNull SessionSettings aSettings, @SessionOpenModeFlags int aOpenMode) { SessionState state = new SessionState(); @@ -391,7 +386,7 @@ private SessionState createSession(@NonNull SessionSettings aSettings, @SessionO private GeckoSession createGeckoSession(@NonNull SessionSettings aSettings) { GeckoSessionSettings geckoSettings = new GeckoSessionSettings.Builder() .useMultiprocess(SettingsStore.getInstance(mContext).isMultiprocessEnabled()) - .usePrivateMode(mUsePrivateMode) + .usePrivateMode(aSettings.isPrivateBrowsingEnabled()) .useTrackingProtection(aSettings.isTrackingProtectionEnabled()) .userAgentMode(aSettings.getUserAgentMode()) .viewportMode(aSettings.getViewportMode()) @@ -406,6 +401,7 @@ private GeckoSession createGeckoSession(@NonNull SessionSettings aSettings) { } session.getSettings().setUserAgentOverride(aSettings.getUserAgentOverride()); + setupSessionListeners(session); return session; } @@ -414,28 +410,39 @@ private void recreateSession() { SessionState previous = mState; mState = createSession(previous.mSettings, SESSION_OPEN); - if (previous.mSessionState != null) + if (previous.mSessionState != null) { mState.mSession.restoreState(previous.mSessionState); + } if (previous.mSession != null) { - closeSession(previous.mSession); + closeSession(previous); } - setupSessionListeners(mState.mSession); for (SessionChangeListener listener : mSessionChangeListeners) { listener.onCurrentSessionChange(previous.mSession, mState.mSession); } } - private void closeSession(@NonNull GeckoSession aSession) { - cleanSessionListeners(aSession); - aSession.setActive(false); - aSession.stop(); - aSession.close(); - mIsActive = false; + private void closeSession(@NonNull SessionState aState) { + if (aState.mSession == null) { + return; + } + cleanSessionListeners(aState.mSession); + aState.mSession.setActive(false); + aState.mSession.stop(); + if (aState.mDisplay != null) { + aState.mDisplay.surfaceDestroyed(); + aState.mSession.releaseDisplay(aState.mDisplay); + aState.mDisplay = null; + } + aState.mSession.close(); + aState.mIsActive = false; } - public void captureBitmap(@NonNull GeckoDisplay aDisplay) { - aDisplay.capturePixels().then(bitmap -> { + public void captureBitmap() { + if (mState.mDisplay == null) { + return; + } + mState.mDisplay.capturePixels().then(bitmap -> { if (bitmap != null) { BitmapCache.getInstance(mContext).scaleBitmap(bitmap, 500, 280).thenAccept(scaledBitmap -> { BitmapCache.getInstance(mContext).addBitmap(getId(), scaledBitmap); @@ -517,10 +524,16 @@ public Boolean isHomeUri(String aUri) { } public String getCurrentUri() { + if (mState.mUri == null) { + return ""; + } return mState.mUri; } public String getCurrentTitle() { + if (mState.mTitle == null) { + return ""; + } return mState.mTitle; } @@ -583,15 +596,17 @@ public void goForward() { public void setActive(boolean aActive) { // Flush the events queued while the session was inactive - if (mState.mSession != null && !mIsActive && aActive) { + if (mState.mSession != null && !mState.mIsActive && aActive) { flushQueuedEvents(); } if (mState.mSession != null) { mState.mSession.setActive(aActive); + } else { + restore(); } - mIsActive = aActive; + mState.mIsActive = aActive; for (SessionChangeListener listener: mSessionChangeListeners) { listener.onActiveStateChange(this, aActive); @@ -645,7 +660,7 @@ public void toggleServo() { .build(); mState = createSession(settings, SESSION_OPEN); - closeSession(previous.mSession); + closeSession(previous); loadUri(uri); } @@ -670,6 +685,8 @@ public String getId() { public boolean isPrivateMode() { if (mState.mSession != null) { return mState.mSession.getSettings().getUsePrivateMode(); + } else if (mState.mSettings != null) { + return mState.mSettings.isPrivateBrowsingEnabled(); } return false; } @@ -688,7 +705,7 @@ public int getUaMode() { } public boolean isActive() { - return mIsActive; + return mState.mIsActive; } private static final String M_PREFIX = "m."; @@ -895,7 +912,7 @@ public void onCanGoForward(@NonNull GeckoSession aSession, boolean aCanGoForward public GeckoResult onNewSession(@NonNull GeckoSession aSession, @NonNull String aUri) { Log.d(LOGTAG, "Session onStackSession: " + aUri); - Session session = SessionStore.get().createSession(mUsePrivateMode, mState.mSettings, SESSION_DO_NOT_OPEN); + Session session = SessionStore.get().createSession(mState.mSettings, SESSION_DO_NOT_OPEN); session.mState.mParentId = mState.mId; for (SessionChangeListener listener: new LinkedList<>(mSessionChangeListeners)) { listener.onStackSession(session); @@ -1402,4 +1419,32 @@ public void onActiveStateChange(Session aSession, boolean aActive) { } } } + + // Display functions + public void releaseDisplay() { + surfaceDestroyed(); + if (mState.mDisplay != null) { + if (mState.mSession != null) { + mState.mSession.releaseDisplay(mState.mDisplay); + } + mState.mDisplay = null; + } + } + + public void surfaceDestroyed() { + if (mState.mDisplay != null) { + mState.mDisplay.surfaceDestroyed(); + } + } + + public void surfaceChanged(@NonNull final Surface surface, final int left, final int top, + final int width, final int height) { + if (mState.mSession == null) { + return; + } + if (mState.mDisplay == null) { + mState.mDisplay = mState.mSession.acquireDisplay(); + } + mState.mDisplay.surfaceChanged(surface, left, top, width, height); + } } 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 608105a57..a41270f60 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 @@ -8,6 +8,7 @@ class SessionSettings { + private boolean isPrivateBrowsingEnabled; private boolean isTrackingProtectionEnabled; private boolean isSuspendMediaWhenInactiveEnabled; private int userAgentMode; @@ -15,7 +16,8 @@ class SessionSettings { private boolean isServoEnabled; private String userAgentOverride; - private SessionSettings(@NotNull Builder builder) { + /* package */ SessionSettings(@NotNull Builder builder) { + this.isPrivateBrowsingEnabled = builder.isPrivateBrowsingEnabled; this.isTrackingProtectionEnabled = builder.isTrackingProtectionEnabled; this.isSuspendMediaWhenInactiveEnabled = builder.isSuspendMediaWhenInactiveEnabled; this.userAgentMode = builder.userAgentMode; @@ -24,6 +26,11 @@ private SessionSettings(@NotNull Builder builder) { this.userAgentOverride = builder.userAgentOverride; } + public boolean isPrivateBrowsingEnabled() { return isPrivateBrowsingEnabled; } + public void setPrivateBrowsingEnabled(boolean enabled) { + isPrivateBrowsingEnabled = enabled; + } + public boolean isTrackingProtectionEnabled() { return isTrackingProtectionEnabled; } @@ -66,6 +73,7 @@ public void setServoEnabled(boolean enabled) { public static class Builder { + private boolean isPrivateBrowsingEnabled; private boolean isTrackingProtectionEnabled; private boolean isSuspendMediaWhenInactiveEnabled; private int userAgentMode; @@ -76,6 +84,10 @@ public static class Builder { public Builder() { } + public Builder withPrivateBrowsing(boolean enabled) { + isPrivateBrowsingEnabled = enabled; + return this; + } public Builder withTrackingProteccion(boolean isTrackingProtectionEnabled){ this.isTrackingProtectionEnabled = isTrackingProtectionEnabled; @@ -113,6 +125,7 @@ public Builder withDefaultSettings(Context context) { GeckoSessionSettings.VIEWPORT_MODE_DESKTOP : GeckoSessionSettings.VIEWPORT_MODE_MOBILE; return new SessionSettings.Builder() + .withPrivateBrowsing(false) .withTrackingProteccion(SettingsStore.getInstance(context).isTrackingProtectionEnabled()) .withSuspendMediaWhenInactive(true) .withUserAgent(ua) @@ -124,5 +137,4 @@ public SessionSettings build(){ return new SessionSettings(this); } } - } 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 dd41a3644..7615ec10c 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 @@ -15,6 +15,7 @@ import com.google.gson.stream.JsonWriter; import org.json.JSONException; +import org.mozilla.geckoview.GeckoDisplay; import org.mozilla.geckoview.GeckoSession; import org.mozilla.vrbrowser.browser.Media; @@ -24,6 +25,7 @@ @JsonAdapter(SessionState.SessionStateAdapterFactory.class) public class SessionState { + public transient boolean mIsActive; public boolean mCanGoBack; public boolean mCanGoForward; public boolean mIsLoading; @@ -34,6 +36,7 @@ public class SessionState { public String mTitle = ""; public transient boolean mFullScreen; public transient GeckoSession mSession; + public transient GeckoDisplay mDisplay; public SessionSettings mSettings; public transient ArrayList mMediaElements = new ArrayList<>(); @JsonAdapter(SessionState.GeckoSessionStateAdapter.class) @@ -84,8 +87,8 @@ public void write(JsonWriter out, T value) throws IOException { out.name("mRegion").value(session.mRegion); out.name("mId").value(session.mId); out.name("mParentId").value(session.mParentId); - if (session.mSession != null) { - if (session.mSession.getSettings().getUsePrivateMode()) { + if (session.mSettings != null) { + if (session.mSettings.isPrivateBrowsingEnabled()) { out.name("mSessionState").jsonValue(null); } else { 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 436b73dab..b67192897 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 @@ -109,26 +109,32 @@ public void initializeStores(Context context) { mHistoryStore = new HistoryStore(context); } - public Session createSession(boolean aPrivateMode) { - return createSession(aPrivateMode, null, Session.SESSION_OPEN); + private Session addSession(@NonNull Session aSession) { + aSession.setPermissionDelegate(this); + aSession.addNavigationListener(mServices); + mSessions.add(aSession); + return aSession; } - public Session createSession(boolean aPrivateMode, @Nullable SessionSettings aSettings, @Session.SessionOpenModeFlags int aOpenMode) { - Session session = new Session(mContext, mRuntime, aPrivateMode, aSettings, aOpenMode); - session.setPermissionDelegate(this); - session.addNavigationListener(mServices); - mSessions.add(session); + public Session createSession(boolean aPrivateMode) { + SessionSettings settings = new SessionSettings(new SessionSettings.Builder().withDefaultSettings(mContext).withPrivateBrowsing(aPrivateMode)); + return createSession(settings, Session.SESSION_OPEN); + } - return session; + /* package */ Session createSession(@NonNull SessionSettings aSettings, @Session.SessionOpenModeFlags int aOpenMode) { + return addSession(new Session(mContext, mRuntime, aSettings, aOpenMode)); } - public Session createSession(SessionState aRestoreState) { - Session session = new Session(mContext, mRuntime, aRestoreState); - session.setPermissionDelegate(this); - session.addNavigationListener(mServices); - mSessions.add(session); + public Session createSuspendedSession(SessionState aRestoreState) { + return addSession(new Session(mContext, mRuntime, aRestoreState)); + } - return session; + public Session createSuspendedSession(final String aUri, final boolean aPrivateMode) { + SessionState state = new SessionState(); + state.mUri = aUri; + state.mSettings = new SessionSettings(new SessionSettings.Builder().withDefaultSettings(mContext).withPrivateBrowsing(aPrivateMode)); + Session session = new Session(mContext, mRuntime, state); + return addSession(session); } private void shutdownSession(@NonNull Session aSession) { @@ -154,6 +160,14 @@ public void destroyPrivateSessions() { }); } + public void suspendAllInactiveSessions() { + for (Session session: mSessions) { + if (!session.isActive()) { + session.suspend(); + } + } + } + public @Nullable Session getSession(String aId) { return mSessions.stream().filter(session -> session.getId().equals(aId)).findFirst().orElse(null); } 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 0dd8690b3..0a81be469 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 @@ -90,7 +90,6 @@ default void onBookmarksShown(WindowWidget aWindow) {} default void onBookmarksHidden(WindowWidget aWindow) {} } - private GeckoDisplay mDisplay; private Surface mSurface; private int mWidth; private int mHeight; @@ -542,15 +541,15 @@ public void hideHistory(boolean switchSurface) { } public void pauseCompositor() { - if (mDisplay == null) { + if (mSession == null) { return; } - mDisplay.surfaceDestroyed(); + mSession.surfaceDestroyed(); } public void resumeCompositor() { - if (mDisplay == null) { + if (mSession == null) { return; } if (mSurface == null) { @@ -733,11 +732,6 @@ public void setSurfaceTexture(SurfaceTexture aTexture, final int aWidth, final i mTexture = aTexture; aTexture.setDefaultBufferSize(aWidth, aHeight); mSurface = new Surface(aTexture); - if (mDisplay == null) { - mDisplay = session.acquireDisplay(); - } else { - Log.e(LOGTAG, "GeckoDisplay was not null in BrowserWidget.setSurfaceTexture()"); - } callSurfaceChanged(); } } @@ -748,32 +742,21 @@ public void setSurface(Surface aSurface, final int aWidth, final int aHeight, Ru super.setSurface(aSurface, aWidth, aHeight, aFirstDrawCallback); } else { - GeckoSession session = mSession.getGeckoSession(); - if (session == null) { - return; - } mWidth = aWidth; mHeight = aHeight; mSurface = aSurface; mFirstDrawCallback = aFirstDrawCallback; - if (mDisplay == null) { - mDisplay = session.acquireDisplay(); - } else { - Log.e(LOGTAG, "GeckoDisplay was not null in BrowserWidget.setSurfaceTexture()"); - } if (mSurface != null) { callSurfaceChanged(); } else { - mDisplay.surfaceDestroyed(); + mSession.surfaceDestroyed(); } } } private void callSurfaceChanged() { - if (mDisplay != null) { - mDisplay.surfaceChanged(mSurface, mBorderWidth, mBorderWidth, mWidth - mBorderWidth * 2, mHeight - mBorderWidth * 2); - } if (mSession != null) { + mSession.surfaceChanged(mSurface, mBorderWidth, mBorderWidth, mWidth - mBorderWidth * 2, mHeight - mBorderWidth * 2); mSession.updateLastUse(); } } @@ -959,12 +942,8 @@ public void releaseWidget() { cleanListeners(mSession); GeckoSession session = mSession.getGeckoSession(); - if (mDisplay != null) { - mDisplay.surfaceDestroyed(); - if (session != null) { - session.releaseDisplay(mDisplay); - } - mDisplay = null; + if (mSession != null) { + mSession.releaseDisplay(); } if (session != null) { session.getTextInput().setView(null); @@ -1017,8 +996,12 @@ public void setVisible(boolean aVisible) { if (mWidgetPlacement.visible == aVisible) { return; } + if (!mIsInVRVideoMode) { mSession.setActive(aVisible); + if (aVisible) { + callSurfaceChanged(); + } } mWidgetPlacement.visible = aVisible; if (!aVisible) { @@ -1051,6 +1034,7 @@ public void setSession(@NonNull Session aSession) { Session oldSession = mSession; if (oldSession != null) { cleanListeners(oldSession); + oldSession.releaseDisplay(); } mSession = aSession; @@ -1067,15 +1051,6 @@ public void setSession(@NonNull Session aSession) { hideLibraryPanels(); } - public void releaseDisplay(GeckoSession aSession) { - if (aSession != null && mDisplay != null) { - Log.d(LOGTAG, "Detach from previous session: " + aSession.hashCode()); - aSession.getTextInput().setView(null); - mDisplay.surfaceDestroyed(); - aSession.releaseDisplay(mDisplay); - mDisplay = null; - } - } public void showPopUps() { if (mPromptDelegate != null) { @@ -1094,12 +1069,9 @@ public boolean hasPendingPopUps() { // Session.GeckoSessionChange @Override public void onCurrentSessionChange(GeckoSession aOldSession, GeckoSession aSession) { - Log.d(LOGTAG, "onCurrentSessionChange: " + this.toString()); + Log.d(LOGTAG, "onCurrentSessionChange: " + this.hashCode()); - releaseDisplay(aOldSession); mWidgetManager.setIsServoSession(isInstanceOfServoSession(aSession)); - - mDisplay = aSession.acquireDisplay(); Log.d(LOGTAG, "surfaceChanged: " + aSession.hashCode()); callSurfaceChanged(); aSession.getTextInput().setView(this); @@ -1558,9 +1530,7 @@ public void onPageStop(@NonNull GeckoSession aSession, boolean b) { } public void captureImage() { - if (mDisplay != null) { - mSession.captureBitmap(mDisplay); - } + mSession.captureBitmap(); } @Override diff --git a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/Windows.java b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/Windows.java index c88be3487..57e64a1e7 100644 --- a/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/Windows.java +++ b/app/src/common/shared/org/mozilla/vrbrowser/ui/widgets/Windows.java @@ -256,6 +256,7 @@ private WindowWidget addRestoredWindow(@NonNull WindowState aState, @NonNull Ses return null; } + aSession.setActive(true); WindowWidget newWindow = createWindow(aSession); newWindow.getPlacement().width = aState.textureWidth; newWindow.getPlacement().height = aState.textureHeight; @@ -609,7 +610,7 @@ private void restoreWindows() { if (windowsState != null) { ArrayList restoredSessions = new ArrayList<>(); if (windowsState.tabs != null) { - windowsState.tabs.forEach(state -> restoredSessions.add(SessionStore.get().createSession(state))); + windowsState.tabs.forEach(state -> restoredSessions.add(SessionStore.get().createSuspendedSession(state))); } mPrivateMode = false; for (WindowState windowState : windowsState.regularWindowsState) { @@ -973,6 +974,24 @@ public void onTabsClicked() { } } + private void setFirstPaint(@NonNull final WindowWidget aWindow, @NonNull final Session aSession) { + if (aSession.getGeckoSession() == null) { + aWindow.setFirstPaintReady(false); + aWindow.setFirstDrawCallback(() -> { + if (!aWindow.isFirstPaintReady()) { + aWindow.setFirstPaintReady(true); + mWidgetManager.updateWidget(aWindow); + } + }); + mWidgetManager.updateWidget(aWindow); + } else { + // If the new session has a GeckoSession there won't be a first paint event. + // So trigger the first paint callback in case the window is grayed out + // waiting for the first paint event. + aWindow.onFirstContentfulPaint(aSession.getGeckoSession()); + } + } + // TopBarWidget Delegate @Override public void onCloseClicked(TopBarWidget aWidget) { @@ -1118,16 +1137,17 @@ public void onTabSelect(Session aTab) { // Move session between windows Session moveFrom = windowToMove.getSession(); Session moveTo = targetWindow.getSession(); - windowToMove.releaseDisplay(moveFrom.getGeckoSession()); - targetWindow.releaseDisplay(moveTo.getGeckoSession()); + moveFrom.surfaceDestroyed(); + moveTo.surfaceDestroyed(); windowToMove.setSession(moveTo); targetWindow.setSession(moveFrom); SessionStore.get().setActiveSession(targetWindow.getSession()); - } else{ + } else { + setFirstPaint(targetWindow, aTab); targetWindow.getSession().setActive(false); + aTab.setActive(true); targetWindow.setSession(aTab); - targetWindow.getSession().setActive(true); SessionStore.get().setActiveSession(aTab); } } @@ -1136,17 +1156,11 @@ public void addTab(WindowWidget targetWindow) { addTab(targetWindow, null); } - public void addTab(WindowWidget targetWindow, @Nullable String aUri) { - Session session = SessionStore.get().createSession(targetWindow.getSession().isPrivateMode()); - targetWindow.setFirstPaintReady(false); - targetWindow.setFirstDrawCallback(() -> { - if (!targetWindow.isFirstPaintReady()) { - targetWindow.setFirstPaintReady(true); - mWidgetManager.updateWidget(targetWindow); - } - }); - mWidgetManager.updateWidget(targetWindow); + public void addTab(@NotNull WindowWidget targetWindow, @Nullable String aUri) { + Session session = SessionStore.get().createSuspendedSession(aUri, targetWindow.getSession().isPrivateMode()); + setFirstPaint(targetWindow, session); targetWindow.getSession().setActive(false); + session.setActive(true); targetWindow.setSession(session); if (aUri == null || aUri.isEmpty()) { session.loadHomePage(); @@ -1157,8 +1171,7 @@ public void addTab(WindowWidget targetWindow, @Nullable String aUri) { } public void addBackgroundTab(WindowWidget targetWindow, String aUri) { - Session session = SessionStore.get().createSession(targetWindow.getSession().isPrivateMode()); - session.loadUri(aUri); + Session session = SessionStore.get().createSuspendedSession(aUri, targetWindow.getSession().isPrivateMode()); session.updateLastUse(); mFocusedWindow.getSession().updateLastUse(); mWidgetManager.getTray().showTabAddedNotification(); @@ -1206,8 +1219,13 @@ public void onTabsClose(ArrayList aTabs) { } if (available.size() > 0) { // Window contains a closed tab and we have a tab available from the list - window.setSession(available.get(0)); - window.getSession().setActive(true); + Session tab = available.get(0); + if (tab != null) { + setFirstPaint(window, tab); + tab.setActive(true); + window.setSession(tab); + } + available.remove(0); } else { // We don't have more tabs available for the front window, load home.