Bug 1538702 - Allow recreating GeckoSession.SessionState from String r=geckoview-reviewers,agi
authorJames Willcox <snorp@snorp.net>
Thu, 28 Mar 2019 16:52:42 +0000
changeset 466616 ed746f1b1e8499d98256911d4e1c0c2d53a0a2c3
parent 466615 d0c23055931239ae141171f8912bbefdfee06fbf
child 466617 dbb7c0704a08a7cc4c1488ea540876317edd7b26
push id35773
push userncsoregi@mozilla.com
push dateFri, 29 Mar 2019 04:11:36 +0000
treeherdermozilla-central@01c0722546ab [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgeckoview-reviewers, agi
bugs1538702
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1538702 - Allow recreating GeckoSession.SessionState from String r=geckoview-reviewers,agi Differential Revision: https://phabricator.services.mozilla.com/D24709
mobile/android/geckoview/api.txt
mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ProgressDelegateTest.kt
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md
--- a/mobile/android/geckoview/api.txt
+++ b/mobile/android/geckoview/api.txt
@@ -629,16 +629,17 @@ package org.mozilla.geckoview {
     ctor protected Selection();
     field public final android.graphics.RectF clientRect;
     field public final int flags;
     field public final java.lang.String text;
   }
 
   @android.support.annotation.AnyThread public static class GeckoSession.SessionState implements android.os.Parcelable {
     ctor public SessionState(@android.support.annotation.NonNull org.mozilla.geckoview.GeckoSession.SessionState);
+    method @android.support.annotation.NonNull public static org.mozilla.geckoview.GeckoSession.SessionState fromString(@android.support.annotation.NonNull java.lang.String);
     method public void readFromParcel(@android.support.annotation.NonNull android.os.Parcel);
     method public void updateSessionState(@android.support.annotation.NonNull org.mozilla.gecko.util.GeckoBundle);
     field public static final android.os.Parcelable.Creator<org.mozilla.geckoview.GeckoSession.SessionState> CREATOR;
   }
 
   public static interface GeckoSession.TextInputDelegate {
     method @android.support.annotation.UiThread default public void hideSoftInput(@android.support.annotation.NonNull org.mozilla.geckoview.GeckoSession);
     method @android.support.annotation.UiThread default public void notifyAutoFill(@android.support.annotation.NonNull org.mozilla.geckoview.GeckoSession, int, int);
--- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ProgressDelegateTest.kt
+++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/ProgressDelegateTest.kt
@@ -283,29 +283,35 @@ class ProgressDelegateTest : BaseSession
                                           securityInfo: GeckoSession.ProgressDelegate.SecurityInformation) {
             }
         })
     }
 
     @WithDevToolsAPI
     @WithDisplay(width = 400, height = 400)
     @Test fun saveAndRestoreState() {
+        sessionRule.setPrefsUntilTestEnd(mapOf("dom.visualviewport.enabled" to true))
+
         val startUri = createTestUrl(SAVE_STATE_PATH)
         mainSession.loadUri(startUri)
         sessionRule.waitForPageStop()
 
         mainSession.evaluateJS("$('#name').value = 'the name'; window.setTimeout(() => window.scrollBy(0, 100),0);")
         mainSession.evaluateJS("$('#name').dispatchEvent(new Event('input'));")
         sessionRule.waitUntilCalled(Callbacks.ScrollDelegate::class, "onScrollChanged")
 
         var savedState : GeckoSession.SessionState? = null
         sessionRule.waitUntilCalled(object : Callbacks.ProgressDelegate {
             @AssertCalled(count=1)
             override fun onSessionStateChange(session: GeckoSession, state: GeckoSession.SessionState) {
                 savedState = state
+
+                val serialized = state.toString()
+                val deserialized = GeckoSession.SessionState.fromString(serialized)
+                assertThat("Deserialized session state should match", deserialized, equalTo(state))
             }
         })
 
         assertThat("State should not be null", savedState, notNullValue())
 
         mainSession.loadUri("about:blank")
         sessionRule.waitForPageStop()
 
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/GeckoSession.java
@@ -1767,16 +1767,44 @@ public class GeckoSession implements Par
             if (formdata != null) {
                 mState.putBundle("formdata", formdata);
             }
 
             return;
         }
 
         @Override
+        public int hashCode() {
+            return mState.hashCode();
+        }
+
+        @Override
+        public boolean equals(final Object other) {
+            if (other == null || !(other instanceof SessionState)) {
+                return false;
+            }
+
+            final SessionState otherState = (SessionState)other;
+
+            return this.mState.equals(otherState.mState);
+        }
+
+        /**
+         * Creates a new SessionState instance from a value previously returned by
+         * {@link #toString()}.
+         *
+         * @param value The serialized SessionState in String form.
+         * @return A new SessionState instance.
+         * @throws JSONException
+         */
+        public static @NonNull SessionState fromString(final @NonNull String value) throws JSONException {
+            return new SessionState(GeckoBundle.fromJSONObject(new JSONObject(value)));
+        }
+
+        @Override
         public String toString() {
             if (mState == null) {
                 Log.w(LOGTAG, "Can't convert SessionState with null state to string");
                 return null;
             }
 
             String res;
             try {
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/doc-files/CHANGELOG.md
@@ -26,16 +26,22 @@ exclude: true
   [`ContentBlocking#CB_DEFAULT`][68.6] and [`ContentBlocking#CB_STRICT`][68.7]
   for clearer app default selections.
 
 [68.4]: ../ContentBlocking.html$AT_DEFAULT
 [68.5]: ../ContentBlocking.html$AT_STRICT
 [68.6]: ../ContentBlocking.html$CB_DEFAULT
 [68.7]: ../ContentBlocking.html$CB_STRICT
 
+- Added [`GeckoSession.SessionState.fromString`][. This can be used to deserialize a
+  `GeckoSession.SessionState` instance previously serialized to a `String` vai
+  `GeckoSession.SessionState.toString`.
+
+[68.4]: ../GeckoSession.SessionState.html#fromString-java.lang.String-
+
 ## v67
 - Added [`setAutomaticFontSizeAdjustment`][67.2] to
   [`GeckoRuntimeSettings`][67.3] for automatically adjusting font size settings
   depending on the OS-level font size setting.
 
 [67.2]: ../GeckoRuntimeSettings.html#setAutomaticFontSizeAdjustment-boolean-
 [67.3]: ../GeckoRuntimeSettings.html
 
@@ -232,9 +238,9 @@ exclude: true
 [65.23]: ../GeckoSession.FinderResult.html
 
 - Update [`CrashReporter#sendCrashReport`][65.24] to return the crash ID as a
   [`GeckoResult<String>`][65.25].
 
 [65.24]: ../CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String-
 [65.25]: ../GeckoResult.html
 
-[api-version]: 9ac0d5a6ef3fd45ecf9e12b42de4f6057e274c30
+[api-version]: d35c31c60693caf8467b98a196b382707c3bd044