0

[Default Nav Transition] Remove top controls in NTP screenshot

In order to match the viewport of the webpage screenshot, this CL
excludes the area of top controls of NTP and maintain the
size of the screenshot. As a result, the bottom part of the screenshot
will be filled with the default background color of the NTP because
it is impossible to draw off-screen views in Android.

Screenshot (with top controls): https://screenshot.googleplex.com/AJFcDYvXCbnvXgj.png
Screen record (w/o top controls): http://screencast/cast/NDY4NTA0OTc2ODE4MTc2MHxjODkyNWE0Zi1jOQ

Bug: 331814846
Change-Id: Ieb8959ad2f202b15e055346f889a73355cdc4e06
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5560151
Reviewed-by: Rakina Zata Amni <rakina@chromium.org>
Code-Coverage: findit-for-me@appspot.gserviceaccount.com <findit-for-me@appspot.gserviceaccount.com>
Reviewed-by: Khushal Sagar <khushalsagar@chromium.org>
Commit-Queue: Lijin Shen <lazzzis@google.com>
Reviewed-by: Calder Kitagawa <ckitagawa@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1324606}
This commit is contained in:
Lijin Shen
2024-07-09 01:08:19 +00:00
committed by Chromium LUCI CQ
parent 4cc0cbba63
commit 7938c61cf2
11 changed files with 201 additions and 45 deletions
chrome
android
java
src
org
javatests
src
browser
gesturenav
android
content
browser
public
android
java
src
org
chromium
content
browser
content_public
test
android
javatests
src
org
chromium
content_public
browser

@ -429,7 +429,8 @@ final class TabWebContentsDelegateAndroidImpl extends TabWebContentsDelegateAndr
@Override
public boolean maybeCopyContentAreaAsBitmap(Callback<Bitmap> callback) {
return NativePageBitmapCapturer.maybeCaptureNativeView(mTab, callback);
return NativePageBitmapCapturer.maybeCaptureNativeView(
mTab, callback, getTopControlsHeight());
}
@Override

@ -45,10 +45,12 @@ import org.chromium.chrome.browser.ui.native_page.BasicSmoothTransitionDelegate;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.util.ChromeTabUtils;
import org.chromium.chrome.test.util.NewTabPageTestUtils;
import org.chromium.components.embedder_support.util.UrlConstants;
import org.chromium.content_public.browser.LoadUrlParams;
import org.chromium.content_public.browser.back_forward_transition.AnimationStage;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.content_public.browser.test.util.UiUtils;
import org.chromium.content_public.common.ContentUrlConstants;
import org.chromium.net.test.EmbeddedTestServer;
import org.chromium.ui.base.PageTransition;
@ -66,6 +68,7 @@ import java.util.concurrent.TimeoutException;
message = "crbug.com/1276402 crbug.com/345352689")
public class NavigationHandlerTest {
private static final String RENDERED_PAGE = "/chrome/test/data/android/navigate/simple.html";
private static final String TEST_PAGE = "/chrome/test/data/android/test.html";
private static final boolean LEFT_EDGE = true;
private static final boolean RIGHT_EDGE = false;
@ -80,7 +83,10 @@ public class NavigationHandlerTest {
@Before
public void setUp() throws InterruptedException {
mActivityTestRule.startMainActivityOnBlankPage();
mTestServer =
EmbeddedTestServer.createAndStartServer(
InstrumentationRegistry.getInstrumentation().getContext());
mActivityTestRule.startMainActivityWithURL(mTestServer.getURL(TEST_PAGE));
CompositorAnimationHandler.setTestingMode(true);
mNavUtils = new GestureNavigationUtils(mActivityTestRule);
mNavigationHandler = mNavUtils.getNavigationHandler();
@ -121,12 +127,12 @@ public class NavigationHandlerTest {
@Test
@SmallTest
@EnableFeatures({ChromeFeatureList.BACK_FORWARD_TRANSITIONS})
public void testSwipeBackToNTPWithTransition() {
public void testSwipeBackToNTPWithTransition() throws InterruptedException {
UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
final Tab tab = mActivityTestRule.getActivity().getActivityTab();
mActivityTestRule.loadUrl(UrlConstants.NTP_URL);
mTestServer =
EmbeddedTestServer.createAndStartServer(
InstrumentationRegistry.getInstrumentation().getContext());
UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
NewTabPageTestUtils.waitForNtpLoaded(mActivityTestRule.getActivity().getActivityTab());
mActivityTestRule.loadUrl(mTestServer.getURL(RENDERED_PAGE));
mNavUtils.swipeFromEdgeAndHold(true);
@ -203,9 +209,6 @@ public class NavigationHandlerTest {
@Test
@SmallTest
public void testReleaseGlowWithoutPrecedingPullIgnored() {
mTestServer =
EmbeddedTestServer.createAndStartServer(
InstrumentationRegistry.getInstrumentation().getContext());
mActivityTestRule.loadUrl(mTestServer.getURL(RENDERED_PAGE));
TestThreadUtils.runOnUiThreadBlocking(
() -> {
@ -268,9 +271,6 @@ public class NavigationHandlerTest {
public void testSwipeNavigateOnRenderedPage() {
// TODO(crbug.com/40899221): Write a test variation running with
// ChromeFeatureList.BACK_FORWARD_TRANSITIONS enabled when the feature is completed.
mTestServer =
EmbeddedTestServer.createAndStartServer(
InstrumentationRegistry.getInstrumentation().getContext());
mActivityTestRule.loadUrl(mTestServer.getURL(RENDERED_PAGE));
mActivityTestRule.loadUrl(ContentUrlConstants.ABOUT_BLANK_DISPLAY_URL);
@ -325,9 +325,6 @@ public class NavigationHandlerTest {
@Test
@SmallTest
public void testSwipeAfterDestroy() {
mTestServer =
EmbeddedTestServer.createAndStartServer(
InstrumentationRegistry.getInstrumentation().getContext());
mActivityTestRule.loadUrl(mTestServer.getURL(RENDERED_PAGE));
TestThreadUtils.runOnUiThreadBlocking(mNavigationHandler::destroy);
@ -347,9 +344,6 @@ public class NavigationHandlerTest {
@Test
@SmallTest
public void testSwipeAfterTabDestroy() {
mTestServer =
EmbeddedTestServer.createAndStartServer(
InstrumentationRegistry.getInstrumentation().getContext());
mActivityTestRule.loadUrl(mTestServer.getURL(RENDERED_PAGE));
TestThreadUtils.runOnUiThreadBlocking(currentTab()::destroy);
@ -363,9 +357,6 @@ public class NavigationHandlerTest {
@Test
@SmallTest
public void testSwipeAfterDestroyActivity_NativePage() {
mTestServer =
EmbeddedTestServer.createAndStartServer(
InstrumentationRegistry.getInstrumentation().getContext());
mActivityTestRule.loadUrl(UrlConstants.NTP_URL);
TestThreadUtils.runOnUiThreadBlocking(mActivityTestRule.getActivity()::finish);

@ -5,6 +5,7 @@
package org.chromium.chrome.browser.gesturenav;
import android.graphics.Bitmap;
import android.os.Build.VERSION_CODES;
import androidx.test.core.app.ApplicationProvider;
import androidx.test.filters.MediumTest;
@ -23,19 +24,25 @@ import org.chromium.base.test.params.ParameterAnnotations;
import org.chromium.base.test.params.ParameterizedRunner;
import org.chromium.base.test.util.CallbackHelper;
import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.DisableIf;
import org.chromium.base.test.util.DoNotBatch;
import org.chromium.base.test.util.Feature;
import org.chromium.base.test.util.Features.EnableFeatures;
import org.chromium.base.test.util.UrlUtils;
import org.chromium.blink_public.common.BlinkFeatures;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.fullscreen.BrowserControlsManager;
import org.chromium.chrome.browser.fullscreen.FullscreenManagerTestUtils;
import org.chromium.chrome.browser.night_mode.ChromeNightModeTestUtils;
import org.chromium.chrome.browser.tab.TabStateBrowserControlsVisibilityDelegate;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.chrome.test.util.ChromeRenderTestRule;
import org.chromium.chrome.test.util.NewTabPageTestUtils;
import org.chromium.chrome.test.util.browser.suggestions.SuggestionsDependenciesRule;
import org.chromium.chrome.test.util.browser.suggestions.mostvisited.FakeMostVisitedSites;
import org.chromium.components.embedder_support.util.UrlConstants;
import org.chromium.content_public.browser.test.util.TestThreadUtils;
import org.chromium.content_public.browser.test.util.UiUtils;
import org.chromium.content_public.browser.test.util.WebContentsUtils;
import org.chromium.net.test.EmbeddedTestServer;
@ -70,6 +77,15 @@ public class ScreenshotCaptureTest {
private static final String TEST_PAGE = "/chrome/test/data/android/simple.html";
private static final String TEST_PAGE_2 = "/chrome/test/data/android/google.html";
private static final String LONG_HTML_TEST_PAGE =
UrlUtils.encodeHtmlDataUri(
"<html>"
+ "<head>"
+ " <meta name=\"viewport\" content=\"width=device-width\">"
+ "</head>"
+ "<body style='height:100000px;'>"
+ "</body>"
+ "</html>");
private EmbeddedTestServer mTestServer;
private Bitmap mCapturedBitmap;
@ -93,9 +109,10 @@ public class ScreenshotCaptureTest {
@Before
public void setUp() {
// Fix the port cause the screenshot includes the url bar
mTestServer =
EmbeddedTestServer.createAndStartServer(
ApplicationProvider.getApplicationContext());
EmbeddedTestServer.createAndStartServerWithPort(
ApplicationProvider.getApplicationContext(), 46985);
var mSiteSuggestions = NewTabPageTestUtils.createFakeSiteSuggestions(mTestServer);
var mMostVisitedSites = new FakeMostVisitedSites();
@ -189,6 +206,91 @@ public class ScreenshotCaptureTest {
mRenderTestRule.compareForResult(mCapturedBitmap, "navigate_away_from_ntp_to_webui_page");
}
@Test
@MediumTest
@Feature({"RenderTest"})
// The test is based on 3-button mode. The newer version defaults to gesture mode.
@DisableIf.Build(sdk_is_greater_than = VERSION_CODES.S_V2)
@ParameterAnnotations.UseMethodParameter(NightModeTestUtils.NightModeParams.class)
public void testNavigatingBackToNtpFromNormalPage(boolean nightModeEnabled)
throws IOException, TimeoutException, InterruptedException {
mActivityTestRule.startMainActivityWithURL(UrlConstants.NTP_URL);
UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
NewTabPageTestUtils.waitForNtpLoaded(mActivityTestRule.getActivity().getActivityTab());
mActivityTestRule.loadUrl(mTestServer.getURL(TEST_PAGE));
GestureNavigationUtils mNavUtils = new GestureNavigationUtils(mActivityTestRule);
mNavUtils.swipeFromEdgeAndHold(/* leftEdge= */ true);
CallbackHelper callbackHelper = new CallbackHelper();
mActivityTestRule
.getWebContents()
.captureContentAsBitmapForTesting(
bitmap -> {
try {
mRenderTestRule.compareForResult(
bitmap, "navigate_back_to_ntp_from_normal_page");
} catch (IOException e) {
throw new RuntimeException(e);
}
callbackHelper.notifyCalled();
});
callbackHelper.waitForOnly();
TestThreadUtils.runOnUiThreadBlocking(() -> mNavUtils.getNavigationHandler().release(true));
// Wait animation to be finished. Reduce flakiness caused by being destroyed during a
// running animation.
UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
}
@Test
@MediumTest
@Feature({"RenderTest"})
// The test is based on 3-button mode. The newer version defaults to gesture mode.
@DisableIf.Build(sdk_is_greater_than = VERSION_CODES.S_V2)
@ParameterAnnotations.UseMethodParameter(NightModeTestUtils.NightModeParams.class)
public void testNavigatingBackToNtpFromNormalPageWithoutTopControls(boolean nightModeEnabled)
throws Throwable {
TestThreadUtils.runOnUiThreadBlocking(
TabStateBrowserControlsVisibilityDelegate::disablePageLoadDelayForTests);
mActivityTestRule.startMainActivityWithURL(UrlConstants.NTP_URL);
UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
NewTabPageTestUtils.waitForNtpLoaded(mActivityTestRule.getActivity().getActivityTab());
FullscreenManagerTestUtils.disableBrowserOverrides();
mActivityTestRule.loadUrl(LONG_HTML_TEST_PAGE);
BrowserControlsManager browserControlManager =
mActivityTestRule.getActivity().getBrowserControlsManager();
int browserControlsHeight = browserControlManager.getTopControlsHeight();
FullscreenManagerTestUtils.waitForBrowserControlsToBeMoveable(
mActivityTestRule, mActivityTestRule.getActivity().getActivityTab());
FullscreenManagerTestUtils.scrollBrowserControls(mActivityTestRule, false);
FullscreenManagerTestUtils.waitForBrowserControlsPosition(
mActivityTestRule, -browserControlsHeight);
GestureNavigationUtils mNavUtils = new GestureNavigationUtils(mActivityTestRule);
mNavUtils.swipeFromEdgeAndHold(/* leftEdge= */ true);
CallbackHelper callbackHelper = new CallbackHelper();
mActivityTestRule
.getWebContents()
.captureContentAsBitmapForTesting(
bitmap -> {
try {
mRenderTestRule.compareForResult(
bitmap,
"navigate_back_to_ntp_from_normal_page_without_top_controls");
} catch (IOException e) {
throw new RuntimeException(e);
}
callbackHelper.notifyCalled();
});
callbackHelper.waitForOnly();
TestThreadUtils.runOnUiThreadBlocking(() -> mNavUtils.getNavigationHandler().release(true));
// Wait animation to be finished. Reduce flakiness caused by being destroyed during a
// running animation.
UiUtils.settleDownUI(InstrumentationRegistry.getInstrumentation());
}
@Test
@MediumTest
public void testNotCaptureSadTab() throws TimeoutException, InterruptedException {

@ -15,6 +15,7 @@ android_library("java") {
"//base:base_java",
"//chrome/browser/flags:java",
"//chrome/browser/tab:java",
"//chrome/browser/ui/android/native_page:java",
"//third_party/androidx:androidx_annotation_annotation_java",
"//third_party/jni_zero:jni_zero_java",
"//ui/android:ui_no_recycler_view_java",

@ -5,7 +5,6 @@ package org.chromium.chrome.browser.gesturenav;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.view.View;
import androidx.annotation.NonNull;
@ -18,7 +17,7 @@ import org.chromium.base.task.PostTask;
import org.chromium.base.task.TaskTraits;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.ui.resources.dynamics.CaptureObserver;
import org.chromium.ui.resources.dynamics.CaptureUtils;
import org.chromium.ui.resources.dynamics.SoftwareDraw;
/** Capture native page as a bitmap. */
@ -37,10 +36,11 @@ public class NativePageBitmapCapturer implements UnownedUserData {
* @param tab The target tab to be captured.
* @param callback Executed with a non-null bitmap if the tab is presenting a native page. Empty
* bitmap if capturing fails, such as out of memory error.
* @param topControlsHeight Height of the top controls.
* @return True if the capture is successfully triggered; otherwise false.
*/
public static boolean maybeCaptureNativeView(
@NonNull Tab tab, @NonNull Callback<Bitmap> callback) {
@NonNull Tab tab, @NonNull Callback<Bitmap> callback, int topControlsHeight) {
if (!tab.isNativePage()) {
return false;
}
@ -53,25 +53,19 @@ public class NativePageBitmapCapturer implements UnownedUserData {
final var capturer = CAPTURER_KEY.retrieveDataFromHost(host);
View view = tab.getView();
Rect viewBound = new Rect(0, 0, view.getWidth(), view.getHeight());
Bitmap bitmap = CaptureUtils.createBitmap(view.getWidth(), view.getHeight());
bitmap.eraseColor(tab.getNativePage().getBackgroundColor());
Canvas canvas = new Canvas(bitmap);
float scale = capturer.getScale();
// TODO(crbug.com/330230340): capture bitmap asynchronously.
capturer.mSoftwareDraw.startBitmapCapture(
view,
viewBound,
capturer.getScale(),
new CaptureObserver() {
@Override
public void onCaptureStart(Canvas canvas, Rect dirtyRect) {}
@Override
public void onCaptureEnd() {}
},
(bitmap) -> {
// The screenshot callback must be dispatched asynchronously. See
// WebContentsDelegateAndroid#maybeCopyContentAreaAsBitmap.
PostTask.postTask(TaskTraits.UI_USER_VISIBLE, () -> callback.onResult(bitmap));
});
// Translate to exclude the area of the top controls.
canvas.translate(0, -topControlsHeight);
canvas.scale(scale, scale);
view.draw(canvas);
PostTask.postTask(TaskTraits.UI_USER_VISIBLE, () -> callback.onResult(bitmap));
return true;
}

@ -18,6 +18,8 @@ import org.chromium.base.test.util.CommandLineFlags;
import org.chromium.base.test.util.Features;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.flags.ChromeSwitches;
import org.chromium.chrome.browser.tab.TabTestUtils;
import org.chromium.chrome.browser.tab.TabWebContentsDelegateAndroid;
import org.chromium.chrome.test.ChromeJUnit4ClassRunner;
import org.chromium.chrome.test.ChromeTabbedActivityTestRule;
import org.chromium.components.embedder_support.util.UrlConstants;
@ -39,6 +41,12 @@ public class NativePageBitmapCapturerTest {
@SmallTest
public void testWithNativePage() throws TimeoutException {
mTabbedActivityTestRule.startMainActivityWithURL(UrlConstants.NTP_URL);
final TabWebContentsDelegateAndroid delegate =
TabTestUtils.getTabWebContentsDelegate(
mTabbedActivityTestRule.getActivity().getActivityTab());
final int topControlsHeight = delegate.getTopControlsHeight();
CallbackHelper callbackHelper = new CallbackHelper();
TestThreadUtils.runOnUiThreadBlocking(
() -> {
@ -47,7 +55,8 @@ public class NativePageBitmapCapturerTest {
mTabbedActivityTestRule.getActivity().getActivityTab(),
(bitmap) -> {
callbackHelper.notifyCalled();
}));
},
topControlsHeight));
});
callbackHelper.waitForOnly();
@ -57,6 +66,12 @@ public class NativePageBitmapCapturerTest {
@SmallTest
public void testWithNonNativePage() {
mTabbedActivityTestRule.startMainActivityOnBlankPage();
final TabWebContentsDelegateAndroid delegate =
TabTestUtils.getTabWebContentsDelegate(
mTabbedActivityTestRule.getActivity().getActivityTab());
final int topControlsHeight = delegate.getTopControlsHeight();
CallbackHelper callbackHelper = new CallbackHelper();
TestThreadUtils.runOnUiThreadBlocking(
() -> {
@ -65,7 +80,8 @@ public class NativePageBitmapCapturerTest {
mTabbedActivityTestRule.getActivity().getActivityTab(),
(bitmap) -> {
callbackHelper.notifyCalled();
}));
},
topControlsHeight));
});
// Capture will be finished before the following task.

@ -15,6 +15,7 @@
#include "base/android/jni_android.h"
#include "base/android/jni_array.h"
#include "base/android/jni_string.h"
#include "base/check.h"
#include "base/functional/bind.h"
#include "base/functional/callback_helpers.h"
#include "base/json/json_writer.h"
@ -48,6 +49,7 @@
#include "ui/gfx/android/java_bitmap.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/snapshot/snapshot.h"
#include "url/android/gurl_android.h"
#include "url/gurl.h"
@ -256,6 +258,28 @@ WebContentsAndroid::GetJavaObject() {
return base::android::ScopedJavaLocalRef<jobject>(obj_);
}
void WebContentsAndroid::CaptureContentAsBitmapForTesting(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& jcallback) {
ui::GrabViewSnapshot(
web_contents_->GetNativeView(), gfx::Rect(web_contents_->GetSize()),
base::BindOnce(
&WebContentsAndroid::OnFinishGetContentBitmapForTesting,
weak_factory_.GetWeakPtr(),
base::android::ScopedJavaGlobalRef<jobject>(env, jcallback)));
}
void WebContentsAndroid::OnFinishGetContentBitmapForTesting(
const base::android::JavaRef<jobject>& callback,
gfx::Image snapshot) {
const SkBitmap bitmap = snapshot.AsBitmap();
CHECK(!bitmap.isNull());
CHECK(!bitmap.empty());
base::android::RunObjectCallbackAndroid(
callback,
gfx::ConvertToJavaBitmap(bitmap, gfx::OomBehavior::kReturnNullOnOom));
}
void WebContentsAndroid::ClearNativeReference(JNIEnv* env) {
return web_contents_->ClearWebContentsAndroid();
}

@ -235,6 +235,13 @@ class CONTENT_EXPORT WebContentsAndroid {
void OnContentForNavigationEntryShown(JNIEnv* env);
jint GetCurrentBackForwardTransitionStage(JNIEnv* env);
void CaptureContentAsBitmapForTesting(
JNIEnv* env,
const base::android::JavaParamRef<jobject>& jcallback);
void OnFinishGetContentBitmapForTesting(
const base::android::JavaRef<jobject>& callback,
gfx::Image snapshot);
// Adds a crash report, like DumpWithoutCrashing(), including the Java stack
// trace from which `web_contents` was created. This is meant to help debug
// cases where BrowserContext is destroyed before its WebContents.

@ -25,6 +25,7 @@ import org.jni_zero.CalledByNative;
import org.jni_zero.JNINamespace;
import org.jni_zero.NativeMethods;
import org.chromium.base.Callback;
import org.chromium.base.JavaExceptionReporter;
import org.chromium.base.Log;
import org.chromium.base.ObserverList;
@ -1248,9 +1249,16 @@ public class WebContentsImpl implements WebContents, RenderFrameHostDelegate, Wi
"Native WebContents already destroyed", mNativeDestroyThrowable);
}
@Override
public void captureContentAsBitmapForTesting(Callback<Bitmap> callback) {
WebContentsImplJni.get()
.captureContentAsBitmapForTesting(mNativeWebContentsAndroid, callback);
}
@VisibleForTesting(otherwise = VisibleForTesting.PACKAGE_PRIVATE)
@NativeMethods
public interface Natives {
// This is static to avoid exposing a public destroy method on the native side of this
// class.
void destroyWebContents(long webContentsAndroidPtr);
@ -1454,5 +1462,8 @@ public class WebContentsImpl implements WebContents, RenderFrameHostDelegate, Wi
long nativeWebContentsAndroid,
BrowserControlsOffsetTagsInfo oldOffsetTagsInfo,
BrowserControlsOffsetTagsInfo offsetTagsInfo);
void captureContentAsBitmapForTesting(
long nativeWebContentsAndroid, Callback<Bitmap> callback);
}
}

@ -4,6 +4,7 @@
package org.chromium.content_public.browser;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Parcelable;
@ -11,6 +12,7 @@ import android.os.Parcelable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.chromium.base.Callback;
import org.chromium.blink_public.input.SelectionGranularity;
import org.chromium.cc.input.BrowserControlsOffsetTagsInfo;
import org.chromium.content_public.browser.back_forward_transition.AnimationStage;
@ -621,4 +623,6 @@ public interface WebContents extends Parcelable {
void notifyControlsConstraintsChanged(
BrowserControlsOffsetTagsInfo oldOffsetTagsInfo,
BrowserControlsOffsetTagsInfo offsetTagsInfo);
void captureContentAsBitmapForTesting(Callback<Bitmap> callback);
}

@ -5,12 +5,14 @@
package org.chromium.content_public.browser.test.mock;
import android.annotation.SuppressLint;
import android.graphics.Bitmap;
import android.graphics.Rect;
import android.os.Handler;
import android.os.Parcel;
import androidx.annotation.Nullable;
import org.chromium.base.Callback;
import org.chromium.blink_public.input.SelectionGranularity;
import org.chromium.cc.input.BrowserControlsOffsetTagsInfo;
import org.chromium.content_public.browser.GlobalRenderFrameHostId;
@ -375,6 +377,9 @@ public class MockWebContents implements WebContents {
return AnimationStage.NONE;
}
@Override
public void captureContentAsBitmapForTesting(Callback<Bitmap> callback) {}
@Override
public void notifyControlsConstraintsChanged(
BrowserControlsOffsetTagsInfo oldOffsetTagsInfo,