diff --git a/mobile/android/chrome/geckoview/GeckoViewContentChild.js b/mobile/android/chrome/geckoview/GeckoViewContentChild.js index d2aa1ff58183..2f1454410218 100644 --- a/mobile/android/chrome/geckoview/GeckoViewContentChild.js +++ b/mobile/android/chrome/geckoview/GeckoViewContentChild.js @@ -7,6 +7,17 @@ const {GeckoViewChildModule} = ChromeUtils.import("resource://gre/modules/GeckoV var {XPCOMUtils} = ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm"); var {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm"); +// This needs to match ScreenLength.java +const SCREEN_LENGTH_TYPE_PIXEL = 0; +const SCREEN_LENGTH_TYPE_VIEWPORT_WIDTH = 1; +const SCREEN_LENGTH_TYPE_VIEWPORT_HEIGHT = 2; +const SCREEN_LENGTH_DOCUMENT_WIDTH = 3; +const SCREEN_LENGTH_DOCUMENT_HEIGHT = 4; + +// This need to match PanZoomController.java +const SCROLL_BEHAVIOR_SMOOTH = 0; +const SCROLL_BEHAVIOR_AUTO = 1; + XPCOMUtils.defineLazyModuleGetters(this, { FormLikeFactory: "resource://gre/modules/FormLikeFactory.jsm", GeckoViewAutoFill: "resource://gre/modules/GeckoViewAutoFill.jsm", @@ -33,6 +44,8 @@ class GeckoViewContentChild extends GeckoViewChildModule { this.messageManager.addMessageListener("GeckoView:SetActive", this); this.messageManager.addMessageListener("GeckoView:UpdateInitData", this); this.messageManager.addMessageListener("GeckoView:ZoomToInput", this); + this.messageManager.addMessageListener("GeckoView:ScrollBy", this); + this.messageManager.addMessageListener("GeckoView:ScrollTo", this); const options = { mozSystemGroup: true, @@ -109,6 +122,31 @@ class GeckoViewContentChild extends GeckoViewChildModule { return {history, formdata, scrolldata}; } + toPixels(aLength, aType) { + if (aType === SCREEN_LENGTH_TYPE_PIXEL) { + return aLength; + } else if (aType === SCREEN_LENGTH_TYPE_VIEWPORT_WIDTH) { + return aLength * content.innerWidth; + } else if (aType === SCREEN_LENGTH_TYPE_VIEWPORT_HEIGHT) { + return aLength * content.innerHeight; + } else if (aType === SCREEN_LENGTH_DOCUMENT_WIDTH) { + return aLength * content.document.body.scrollWidth; + } else if (aType === SCREEN_LENGTH_DOCUMENT_HEIGHT) { + return aLength * content.document.body.scrollHeight; + } + + return aLength; + } + + toScrollBehavior(aBehavior) { + if (aBehavior === SCROLL_BEHAVIOR_SMOOTH) { + return "smooth"; + } else if (aBehavior === SCROLL_BEHAVIOR_AUTO) { + return "auto"; + } + return "smooth"; + } + receiveMessage(aMsg) { debug `receiveMessage: ${aMsg.name}`; @@ -246,6 +284,20 @@ class GeckoViewContentChild extends GeckoViewChildModule { Services.obs.notifyObservers( docShell, "geckoview-content-global-transferred"); break; + case "GeckoView:ScrollBy": + content.scrollBy({ + top: this.toPixels(aMsg.data.heightValue, aMsg.data.heightType), + left: this.toPixels(aMsg.data.widthValue, aMsg.data.widthType), + behavior: this.toScrollBehavior(aMsg.data.behavior), + }); + break; + case "GeckoView:ScrollTo": + content.scrollTo({ + top: this.toPixels(aMsg.data.heightValue, aMsg.data.heightType), + left: this.toPixels(aMsg.data.widthValue, aMsg.data.widthType), + behavior: this.toScrollBehavior(aMsg.data.behavior), + }); + break; } } diff --git a/mobile/android/geckoview/api.txt b/mobile/android/geckoview/api.txt index 015a129d8d3a..a8698afb9a12 100644 --- a/mobile/android/geckoview/api.txt +++ b/mobile/android/geckoview/api.txt @@ -832,8 +832,16 @@ package org.mozilla.geckoview { method public boolean onMotionEvent(@android.support.annotation.NonNull android.view.MotionEvent); method public boolean onMouseEvent(@android.support.annotation.NonNull android.view.MotionEvent); method public boolean onTouchEvent(@android.support.annotation.NonNull android.view.MotionEvent); + method @android.support.annotation.UiThread public void scrollBy(@android.support.annotation.NonNull org.mozilla.geckoview.ScreenLength, @android.support.annotation.NonNull org.mozilla.geckoview.ScreenLength); + method @android.support.annotation.UiThread public void scrollBy(@android.support.annotation.NonNull org.mozilla.geckoview.ScreenLength, @android.support.annotation.NonNull org.mozilla.geckoview.ScreenLength, int); + method @android.support.annotation.UiThread public void scrollTo(@android.support.annotation.NonNull org.mozilla.geckoview.ScreenLength, @android.support.annotation.NonNull org.mozilla.geckoview.ScreenLength); + method @android.support.annotation.UiThread public void scrollTo(@android.support.annotation.NonNull org.mozilla.geckoview.ScreenLength, @android.support.annotation.NonNull org.mozilla.geckoview.ScreenLength, int); + method @android.support.annotation.UiThread public void scrollToBottom(); + method @android.support.annotation.UiThread public void scrollToTop(); method public void setIsLongpressEnabled(boolean); method public void setScrollFactor(float); + field public static final int SCROLL_BEHAVIOR_AUTO = 1; + field public static final int SCROLL_BEHAVIOR_SMOOTH = 0; } public abstract class RuntimeSettings implements android.os.Parcelable { @@ -854,6 +862,22 @@ package org.mozilla.geckoview { method @android.support.annotation.AnyThread @android.support.annotation.NonNull public org.mozilla.geckoview.GeckoResult getSnapshots(boolean); } + public class ScreenLength { + method @android.support.annotation.NonNull @android.support.annotation.AnyThread public static org.mozilla.geckoview.ScreenLength bottom(); + method @android.support.annotation.NonNull @android.support.annotation.AnyThread public static org.mozilla.geckoview.ScreenLength fromPixels(double); + method @android.support.annotation.NonNull @android.support.annotation.AnyThread public static org.mozilla.geckoview.ScreenLength fromViewportHeight(double); + method @android.support.annotation.NonNull @android.support.annotation.AnyThread public static org.mozilla.geckoview.ScreenLength fromViewportWidth(double); + method @android.support.annotation.AnyThread public int getType(); + method @android.support.annotation.AnyThread public double getValue(); + method @android.support.annotation.NonNull @android.support.annotation.AnyThread public static org.mozilla.geckoview.ScreenLength top(); + method @android.support.annotation.NonNull @android.support.annotation.AnyThread public static org.mozilla.geckoview.ScreenLength zero(); + field public static final int DOCUMENT_HEIGHT = 4; + field public static final int DOCUMENT_WIDTH = 3; + field public static final int PIXEL = 0; + field public static final int VIEWPORT_HEIGHT = 2; + field public static final int VIEWPORT_WIDTH = 1; + } + @android.support.annotation.UiThread public class SessionAccessibility { method @android.support.annotation.Nullable public android.view.View getView(); method public boolean onMotionEvent(@android.support.annotation.NonNull android.view.MotionEvent); diff --git a/mobile/android/geckoview/src/androidTest/assets/www/scroll.html b/mobile/android/geckoview/src/androidTest/assets/www/scroll.html new file mode 100644 index 000000000000..915f4dab3c90 --- /dev/null +++ b/mobile/android/geckoview/src/androidTest/assets/www/scroll.html @@ -0,0 +1,35 @@ + + + + + + + +
+
+
+ + diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt index 432b61b7050b..3caad41a15bd 100644 --- a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/BaseSessionTest.kt @@ -52,6 +52,7 @@ open class BaseSessionTest(noErrorCollector: Boolean = false) { const val IFRAME_REDIRECT_LOCAL = "/assets/www/iframe_redirect_local.html" const val IFRAME_REDIRECT_AUTOMATION = "/assets/www/iframe_redirect_automation.html" const val AUTOPLAY_PATH = "/assets/www/autoplay.html" + const val SCROLL_TEST_PATH = "/assets/www/scroll.html" } @get:Rule val sessionRule = GeckoSessionTestRule() diff --git a/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PanZoomControllerTest.kt b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PanZoomControllerTest.kt new file mode 100644 index 000000000000..0478f56cb77b --- /dev/null +++ b/mobile/android/geckoview/src/androidTest/java/org/mozilla/geckoview/test/PanZoomControllerTest.kt @@ -0,0 +1,64 @@ +package org.mozilla.geckoview.test + +import org.mozilla.geckoview.ScreenLength +import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDevToolsAPI +import org.mozilla.geckoview.test.rule.GeckoSessionTestRule.WithDisplay + +import android.support.test.filters.MediumTest +import android.support.test.runner.AndroidJUnit4 +import org.hamcrest.Matchers.* +import org.junit.Test +import org.junit.runner.RunWith +import org.mozilla.geckoview.PanZoomController + +@RunWith(AndroidJUnit4::class) +@MediumTest +class PanZoomControllerTest : BaseSessionTest() { + private val errorEpsilon = 3.0 + @WithDevToolsAPI + @WithDisplay(width = 100, height = 100) + @Test + fun scrollBy() { + sessionRule.session.loadTestPath(SCROLL_TEST_PATH) + sessionRule.waitForPageStop() + val vh = sessionRule.evaluateJS(mainSession, "window.innerHeight") as Double + assertThat("Viewport height is not zero", vh, greaterThan(0.0)) + sessionRule.session.panZoomController.scrollBy(ScreenLength.zero(), ScreenLength.fromViewportHeight(1.0), PanZoomController.SCROLL_BEHAVIOR_AUTO) + val scrollY = sessionRule.evaluateJS(mainSession, "window.scrollY") as Double + assertThat("scrollBy should have scrolled along y axis one viewport", scrollY, closeTo(vh, errorEpsilon)) + + sessionRule.session.loadTestPath(SCROLL_TEST_PATH) + sessionRule.waitForPageStop() + val vw = sessionRule.evaluateJS(mainSession, "window.innerWidth") as Double + assertThat("Viewport width is not zero", vw, greaterThan(0.0)) + sessionRule.session.panZoomController.scrollBy(ScreenLength.fromViewportWidth(1.0), ScreenLength.zero(), PanZoomController.SCROLL_BEHAVIOR_AUTO) + val scrollX = sessionRule.evaluateJS(mainSession, "window.scrollX") as Double + assertThat("scrollBy should have scrolled along x axis one viewport", scrollX, closeTo(vw, errorEpsilon)) + } + + @WithDevToolsAPI + @WithDisplay(width = 100, height = 100) + @Test + fun scrollTo() { + sessionRule.session.loadTestPath(SCROLL_TEST_PATH) + sessionRule.waitForPageStop() + val vh = sessionRule.evaluateJS(mainSession, "window.innerHeight") as Double + val scrollHeight = sessionRule.evaluateJS(mainSession, "window.document.body.scrollHeight") as Double + assertThat("Viewport height is not zero", vh, greaterThan(0.0)) + assertThat("scrollHeight height is not zero", scrollHeight, greaterThan(0.0)) + sessionRule.session.panZoomController.scrollTo(ScreenLength.zero(), ScreenLength.bottom(), PanZoomController.SCROLL_BEHAVIOR_AUTO) + var scrollY = sessionRule.evaluateJS(mainSession, "window.scrollY") as Double + assertThat("scrollTo should have scrolled to bottom", scrollY, closeTo(scrollHeight - vh, 3.0)) + + sessionRule.session.panZoomController.scrollTo(ScreenLength.zero(), ScreenLength.top(), PanZoomController.SCROLL_BEHAVIOR_AUTO) + scrollY = sessionRule.evaluateJS(mainSession, "window.scrollY") as Double + assertThat("scrollTo should have scrolled to top", scrollY, closeTo(0.0, errorEpsilon)) + + val vw = sessionRule.evaluateJS(mainSession, "window.innerWidth") as Double + val scrollWidth = sessionRule.evaluateJS(mainSession, "window.document.body.scrollWidth") as Double + + sessionRule.session.panZoomController.scrollTo(ScreenLength.fromViewportWidth(1.0), ScreenLength.zero(), PanZoomController.SCROLL_BEHAVIOR_AUTO) + val scrollX = sessionRule.evaluateJS(mainSession, "window.scrollX") as Double + assertThat("scrollTo should have scrolled to right", scrollX, closeTo(scrollWidth - vw, errorEpsilon)) + } +} \ No newline at end of file diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java index 73176b13ecb7..6c8bf52c8db7 100644 --- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java @@ -7,17 +7,22 @@ package org.mozilla.geckoview; import org.mozilla.gecko.annotation.WrapForJNI; import org.mozilla.gecko.mozglue.JNIObject; +import org.mozilla.gecko.util.GeckoBundle; import org.mozilla.gecko.util.ThreadUtils; import android.graphics.Rect; import android.os.SystemClock; import android.support.annotation.NonNull; import android.support.annotation.UiThread; +import android.support.annotation.IntDef; import android.util.Log; import android.util.Pair; import android.view.MotionEvent; import android.view.InputDevice; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + import java.util.ArrayList; @UiThread @@ -33,6 +38,19 @@ public class PanZoomController extends JNIObject { private float mPointerScrollFactor = 64.0f; private long mLastDownTime; + @Retention(RetentionPolicy.SOURCE) + @IntDef({SCROLL_BEHAVIOR_SMOOTH, SCROLL_BEHAVIOR_AUTO}) + /* package */ @interface ScrollBehaviorType {} + + /** + * Specifies smooth scrolling which animates content to the desired scroll position. + */ + public static final int SCROLL_BEHAVIOR_SMOOTH = 0; + /** + * Specifies auto scrolling which jumps content to the desired scroll position. + */ + public static final int SCROLL_BEHAVIOR_AUTO = 1; + private SynthesizedEventState mPointerState; private ArrayList> mQueuedEvents; @@ -530,4 +548,84 @@ public class PanZoomController extends JNIObject { PointerInfo.RESERVED_MOUSE_POINTER_ID, eventType, clientX, clientY, 0, 0); } + + /** + * Scroll the document body by an offset from the current scroll position. + * Uses {@link #SCROLL_BEHAVIOR_SMOOTH}. + * + * @param width {@link ScreenLength} offset to scroll along X axis. + * @param height {@link ScreenLength} offset to scroll along Y axis. + */ + @UiThread + public void scrollBy(@NonNull ScreenLength width, @NonNull ScreenLength height) { + scrollBy(width, height, SCROLL_BEHAVIOR_SMOOTH); + } + + /** + * Scroll the document body by an offset from the current scroll position. + * + * @param width {@link ScreenLength} offset to scroll along X axis. + * @param height {@link ScreenLength} offset to scroll along Y axis. + * @param behavior ScrollBehaviorType One of {@link #SCROLL_BEHAVIOR_SMOOTH}, {@link #SCROLL_BEHAVIOR_AUTO}, + * that specifies how to scroll the content. + */ + @UiThread + public void scrollBy(@NonNull ScreenLength width, @NonNull ScreenLength height, @ScrollBehaviorType int behavior) { + final GeckoBundle msg = buildScrollMessage(width, height, behavior); + mSession.getEventDispatcher().dispatch("GeckoView:ScrollBy", msg); + } + + /** + * Scroll the document body to an absolute position. + * Uses {@link #SCROLL_BEHAVIOR_SMOOTH}. + * + * @param width {@link ScreenLength} position to scroll along X axis. + * @param height {@link ScreenLength} position to scroll along Y axis. + */ + @UiThread + public void scrollTo(@NonNull ScreenLength width, @NonNull ScreenLength height) { + scrollTo(width, height, SCROLL_BEHAVIOR_SMOOTH); + } + + /** + * Scroll the document body to an absolute position. + * + * @param width {@link ScreenLength} position to scroll along X axis. + * @param height {@link ScreenLength} position to scroll along Y axis. + * @param behavior ScrollBehaviorType One of {@link #SCROLL_BEHAVIOR_SMOOTH}, {@link #SCROLL_BEHAVIOR_AUTO}, + * that specifies how to scroll the content. + */ + @UiThread + public void scrollTo(@NonNull ScreenLength width, @NonNull ScreenLength height, @ScrollBehaviorType int behavior) { + final GeckoBundle msg = buildScrollMessage(width, height, behavior); + mSession.getEventDispatcher().dispatch("GeckoView:ScrollTo", msg); + } + + /** + * Scroll to the top left corner of the screen. + * Uses {@link #SCROLL_BEHAVIOR_SMOOTH}. + */ + @UiThread + public void scrollToTop() { + scrollTo(ScreenLength.zero(), ScreenLength.top(), SCROLL_BEHAVIOR_SMOOTH); + } + + /** + * Scroll to the bottom left corner of the screen. + * Uses {@link #SCROLL_BEHAVIOR_SMOOTH}. + */ + @UiThread + public void scrollToBottom() { + scrollTo(ScreenLength.zero(), ScreenLength.bottom(), SCROLL_BEHAVIOR_SMOOTH); + } + + private GeckoBundle buildScrollMessage(@NonNull ScreenLength width, @NonNull ScreenLength height, @ScrollBehaviorType int behavior) { + final GeckoBundle msg = new GeckoBundle(); + msg.putDouble("widthValue", width.getValue()); + msg.putInt("widthType", width.getType()); + msg.putDouble("heightValue", height.getValue()); + msg.putInt("heightType", height.getType()); + msg.putInt("behavior", behavior); + return msg; + } } diff --git a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ScreenLength.java b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ScreenLength.java new file mode 100644 index 000000000000..73422d7bf88a --- /dev/null +++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/ScreenLength.java @@ -0,0 +1,156 @@ +/* License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +package org.mozilla.geckoview; + +import android.support.annotation.AnyThread; +import android.support.annotation.IntDef; +import android.support.annotation.NonNull; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * ScreenLength is a class that represents a length on the screen using different units. + * The default unit is a pixel. However lengths may be also represented by a dimension + * of the visual viewport or of the full scroll size of the root document. + */ +public class ScreenLength { + @Retention(RetentionPolicy.SOURCE) + @IntDef({PIXEL, VIEWPORT_WIDTH, VIEWPORT_HEIGHT, DOCUMENT_WIDTH, DOCUMENT_HEIGHT}) + /* package */ @interface ScreenLengthType {} + + /** + * Pixel units. + */ + public static final int PIXEL = 0; + /** + * Units are in visual viewport width. If the visual viewport is 100 pixels wide, then a value + * of 2.0 would represent a length of 200 pixels. + * @see MDN Visual Viewport + */ + public static final int VIEWPORT_WIDTH = 1; + /** + * Units are in visual viewport height. If the visual viewport is 100 pixels high, then a value + * of 2.0 would represent a length of 200 pixels. + * @see MDN Visual Viewport + */ + public static final int VIEWPORT_HEIGHT = 2; + /** + * Units represent the entire scrollable documents width. If the document is 1000 pixels wide + * then a value of 1.0 would represent 1000 pixels. + */ + public static final int DOCUMENT_WIDTH = 3; + /** + * Units represent the entire scrollable documents height. If the document is 1000 pixels tall + * then a value of 1.0 would represent 1000 pixels. + */ + public static final int DOCUMENT_HEIGHT = 4; + + /** + * Create a ScreenLength of zero pixels length. + * Type is {@link #PIXEL}. + * @return ScreenLength of zero length. + */ + @NonNull + @AnyThread + public static ScreenLength zero() { + return new ScreenLength(0.0, PIXEL); + } + + /** + * Create a ScreenLength of zero pixels length. + * Type is {@link #PIXEL}. Can be used to scroll to the top of a page when used with + * PanZoomController.scrollTo() + * @return ScreenLength of zero length. + */ + @NonNull + @AnyThread + public static ScreenLength top() { + return zero(); + } + + /** + * Create a ScreenLength of the documents height. + * Type is {@link #DOCUMENT_HEIGHT}. Can be used to scroll to the bottom of a page when used with + * {@link PanZoomController#scrollTo(ScreenLength, ScreenLength)} + * @return ScreenLength of document height. + */ + @NonNull + @AnyThread + public static ScreenLength bottom() { + return new ScreenLength(1.0, DOCUMENT_HEIGHT); + } + + /** + * Create a ScreenLength of a specific length. + * Type is {@link #PIXEL}. + * @param value Pixel length. + * @return ScreenLength of document height. + */ + @NonNull + @AnyThread + public static ScreenLength fromPixels(final double value) { + return new ScreenLength(value, PIXEL); + } + + /** + * Create a ScreenLength that uses the visual viewport width as units. + * Type is {@link #VIEWPORT_WIDTH}. Can be used with {@link PanZoomController#scrollBy(ScreenLength, ScreenLength)} + * to scroll a value of the width of visual viewport content. + * @param value Factor used to calculate length. A value of 2.0 would indicate a length + * twice as long as the length of the visual viewports width. + * @return ScreenLength of specifying a length of value * visual viewport width. + */ + @NonNull + @AnyThread + public static ScreenLength fromViewportWidth(final double value) { + return new ScreenLength(value, VIEWPORT_WIDTH); + } + + /** + * Create a ScreenLength that uses the visual viewport width as units. + * Type is {@link #VIEWPORT_HEIGHT}. Can be used with {@link PanZoomController#scrollBy(ScreenLength, ScreenLength)} + * to scroll a value of the height of visual viewport content. + * @param value Factor used to calculate length. A value of 2.0 would indicate a length + * twice as long as the length of the visual viewports height. + * @return ScreenLength of specifying a length of value * visual viewport width. + */ + @NonNull + @AnyThread + public static ScreenLength fromViewportHeight(final double value) { + return new ScreenLength(value, VIEWPORT_HEIGHT); + } + + private final double mValue; + @ScreenLengthType private final int mType; + + /* package */ ScreenLength(final double value, @ScreenLengthType final int type) { + mValue = value; + mType = type; + } + + /** + * Returns the scalar value used to calculate length. + * The units of the returned valued are defined by what is returned by + * {@link #getType()} + * @return Scalar value of the length. + */ + @AnyThread + public double getValue() { + return mValue; + } + + /** + * Returns the unit type of the length + * The length can be one of the following: + * {@link #PIXEL}, {@link #VIEWPORT_WIDTH}, {@link #VIEWPORT_HEIGHT}, {@link #DOCUMENT_WIDTH}, {@link #DOCUMENT_HEIGHT} + * @return Unit type of the length. + */ + + @AnyThread + @ScreenLengthType + public int getType() { + return mType; + } +} diff --git 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 index 23b2a23efe69..ccee9450240e 100644 --- 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 @@ -23,6 +23,8 @@ exclude: true - Added `baseUri` to [`ContentDelegate.ContextElement`][65.21] and changed `linkUri` to absolute form. +- Added `scrollBy()` and `scrollTo()` to `PanZoomController`. + ## v66 - Removed redundant field `GeckoSession.ProgressDelegate.SecurityInformation.trackingMode`. Use `GeckoSession.TrackingProtectionDelegate.onTrackerBlocked` for @@ -132,4 +134,4 @@ exclude: true [65.24]: ../CrashReporter.html#sendCrashReport-android.content.Context-android.os.Bundle-java.lang.String- [65.25]: ../GeckoResult.html -[api-version]: a42a6f4481dd690ac46f14d8e692785bb00e8b04 +[api-version]: fb3375bbe85695b337d830dcf3fffec7231f4e4b diff --git a/mobile/android/modules/geckoview/GeckoViewContent.jsm b/mobile/android/modules/geckoview/GeckoViewContent.jsm index 2b64ac959003..c422869d86e1 100644 --- a/mobile/android/modules/geckoview/GeckoViewContent.jsm +++ b/mobile/android/modules/geckoview/GeckoViewContent.jsm @@ -25,6 +25,8 @@ class GeckoViewContent extends GeckoViewModule { "GeckoView:SetActive", "GeckoView:SetFocused", "GeckoView:ZoomToInput", + "GeckoView:ScrollBy", + "GeckoView:ScrollTo", ]); this.messageManager.addMessageListener("GeckoView:SaveStateFinish", this); @@ -77,6 +79,12 @@ class GeckoViewContent extends GeckoViewModule { case "GeckoView:ZoomToInput": this.messageManager.sendAsyncMessage(aEvent); break; + case "GeckoView:ScrollBy": + this.messageManager.sendAsyncMessage(aEvent, aData); + break; + case "GeckoView:ScrollTo": + this.messageManager.sendAsyncMessage(aEvent, aData); + break; case "GeckoView:SetActive": if (aData.active) { this.browser.docShellIsActive = true;