| Index: android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java
|
| diff --git a/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java b/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..ed52d249bd8ce68892bf2bcde7f415e17743d352
|
| --- /dev/null
|
| +++ b/android_webview/javatests/src/org/chromium/android_webview/test/SafeBrowsingTest.java
|
| @@ -0,0 +1,220 @@
|
| +// Copyright 2017 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +package org.chromium.android_webview.test;
|
| +
|
| +import android.content.Context;
|
| +import android.content.SharedPreferences;
|
| +import android.graphics.Bitmap;
|
| +import android.graphics.Color;
|
| +import android.support.test.filters.SmallTest;
|
| +
|
| +import org.chromium.android_webview.AwBrowserContext;
|
| +import org.chromium.android_webview.AwContents;
|
| +import org.chromium.android_webview.AwSwitches;
|
| +import org.chromium.android_webview.AwWebContentsObserver;
|
| +import org.chromium.android_webview.test.util.GraphicsTestUtils;
|
| +import org.chromium.base.ThreadUtils;
|
| +import org.chromium.base.test.util.CallbackHelper;
|
| +import org.chromium.base.test.util.CommandLineFlags;
|
| +import org.chromium.base.test.util.Feature;
|
| +import org.chromium.base.test.util.InMemorySharedPreferences;
|
| +import org.chromium.components.safe_browsing.SafeBrowsingApiBridge;
|
| +import org.chromium.components.safe_browsing.SafeBrowsingApiHandler;
|
| +import org.chromium.content_public.browser.WebContents;
|
| +import org.chromium.net.test.EmbeddedTestServer;
|
| +
|
| +/**
|
| + * Test suite for SafeBrowsing.
|
| + *
|
| + * Ensures that interstitials can be successfully created for malicous pages.
|
| + */
|
| +public class SafeBrowsingTest extends AwTestBase {
|
| + private TestAwContentsClient mContentsClient;
|
| + private AwTestContainerView mContainerView;
|
| + private AwContents mAwContents;
|
| + private TestAwWebContentsObserver mWebContentsObserver;
|
| +
|
| + private EmbeddedTestServer mTestServer;
|
| +
|
| + // These colors correspond to the body.background attribute in GREEN_HTML_PATH, SAFE_HTML_PATH,
|
| + // MALWARE_HTML_PATH, and IFRAME_HTML_PATH. They should only be changed if those values are
|
| + // changed as well
|
| + private static final int COLOR_GREEN = Color.rgb(0, 255, 0);
|
| + private static final int COLOR_BLUE = Color.rgb(0, 0, 255);
|
| + private static final int COLOR_GRAY = Color.rgb(10, 10, 10);
|
| +
|
| + private static final String RESOURCE_PATH = "/android_webview/test/data";
|
| +
|
| + // A blank green page
|
| + private static final String GREEN_HTML_PATH = RESOURCE_PATH + "/green.html";
|
| +
|
| + // Two blank blue pages, one which we treat as a malicious page
|
| + private static final String SAFE_HTML_PATH = RESOURCE_PATH + "/safe.html";
|
| + private static final String MALWARE_HTML_PATH = RESOURCE_PATH + "/malware.html";
|
| +
|
| + // A gray page with an iframe to MALWARE_HTML_PATH
|
| + private static final String IFRAME_HTML_PATH = RESOURCE_PATH + "/iframe.html";
|
| +
|
| + /**
|
| + * A fake SafeBrowsingApiHandler which treats URLs ending in MALWARE_HTML_PATH as malicious URLs
|
| + * that should be blocked.
|
| + */
|
| + public static class MockSafeBrowsingApiHandler implements SafeBrowsingApiHandler {
|
| + private Observer mObserver;
|
| + private static final String SAFE_METADATA = "{}";
|
| + private static final String MALWARE_METADATA = "{\"matches\":[{\"threat_type\":\"5\"}]}";
|
| +
|
| + @Override
|
| + public boolean init(Context context, Observer result) {
|
| + mObserver = result;
|
| + return true;
|
| + }
|
| +
|
| + @Override
|
| + public void startUriLookup(final long callbackId, String uri, int[] threatsOfInterest) {
|
| + final int resultStatus = STATUS_SUCCESS;
|
| + final String metadata = isMaliciousUrl(uri) ? MALWARE_METADATA : SAFE_METADATA;
|
| +
|
| + ThreadUtils.runOnUiThread(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + mObserver.onUrlCheckDone(callbackId, resultStatus, metadata);
|
| + }
|
| + });
|
| + }
|
| +
|
| + private static boolean isMaliciousUrl(String uri) {
|
| + return uri.endsWith(MALWARE_HTML_PATH);
|
| + }
|
| + }
|
| +
|
| + /**
|
| + * A fake AwBrowserContext which loads the MockSafeBrowsingApiHandler instead of the real one.
|
| + */
|
| + private static class MockAwBrowserContext extends AwBrowserContext {
|
| + public MockAwBrowserContext(
|
| + SharedPreferences sharedPreferences, Context applicationContext) {
|
| + super(sharedPreferences, applicationContext);
|
| + SafeBrowsingApiBridge.setSafeBrowsingHandlerType(MockSafeBrowsingApiHandler.class);
|
| + }
|
| + }
|
| +
|
| + private static class TestAwWebContentsObserver extends AwWebContentsObserver {
|
| + private CallbackHelper mDidAttachInterstitialPageHelper;
|
| +
|
| + public TestAwWebContentsObserver(WebContents webContents, AwContents awContents,
|
| + TestAwContentsClient contentsClient) {
|
| + super(webContents, awContents, contentsClient);
|
| + mDidAttachInterstitialPageHelper = new CallbackHelper();
|
| + }
|
| +
|
| + public CallbackHelper getAttachedInterstitialPageHelper() {
|
| + return mDidAttachInterstitialPageHelper;
|
| + }
|
| +
|
| + @Override
|
| + public void didAttachInterstitialPage() {
|
| + mDidAttachInterstitialPageHelper.notifyCalled();
|
| + }
|
| + }
|
| +
|
| + @Override
|
| + public void setUp() throws Exception {
|
| + super.setUp();
|
| + mContentsClient = new TestAwContentsClient();
|
| + mContainerView = createAwTestContainerViewOnMainSync(mContentsClient);
|
| + mAwContents = mContainerView.getAwContents();
|
| +
|
| + mTestServer = EmbeddedTestServer.createAndStartServer(getInstrumentation().getContext());
|
| + getInstrumentation().runOnMainSync(new Runnable() {
|
| + @Override
|
| + public void run() {
|
| + mWebContentsObserver = new TestAwWebContentsObserver(
|
| + mContainerView.getContentViewCore().getWebContents(), mAwContents,
|
| + mContentsClient) {};
|
| + }
|
| + });
|
| + }
|
| +
|
| + @Override
|
| + public void tearDown() throws Exception {
|
| + mTestServer.stopAndDestroyServer();
|
| + super.tearDown();
|
| + }
|
| +
|
| + /**
|
| + * Creates a special BrowserContext that has a safebrowsing api handler which always says
|
| + * sites are malicious
|
| + */
|
| + @Override
|
| + protected AwBrowserContext createAwBrowserContextOnUiThread(
|
| + InMemorySharedPreferences prefs, Context appContext) {
|
| + return new MockAwBrowserContext(prefs, appContext);
|
| + }
|
| +
|
| + private int getPageColor() {
|
| + Bitmap bitmap = GraphicsTestUtils.drawAwContentsOnUiThread(
|
| + mAwContents, mContainerView.getWidth(), mContainerView.getHeight());
|
| + return bitmap.getPixel(0, 0);
|
| + }
|
| +
|
| + private void loadGreenPage() throws Exception {
|
| + loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(),
|
| + mTestServer.getURL(GREEN_HTML_PATH));
|
| +
|
| + // Make sure we actually wait for the page to be visible
|
| + waitForVisualStateCallback(mAwContents);
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"AndroidWebView"})
|
| + @CommandLineFlags.Add(AwSwitches.WEBVIEW_ENABLE_SAFEBROWSING_SUPPORT)
|
| + public void testSafeBrowsingDoesNotBlockSafePages() throws Throwable {
|
| + loadGreenPage();
|
| + final String responseUrl = mTestServer.getURL(SAFE_HTML_PATH);
|
| + loadUrlSync(mAwContents, mContentsClient.getOnPageFinishedHelper(), responseUrl);
|
| + waitForVisualStateCallback(mAwContents);
|
| + assertEquals("Target page should be visible", COLOR_BLUE,
|
| + GraphicsTestUtils.getPixelColorAtCenterOfView(mAwContents, mContainerView));
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"AndroidWebView"})
|
| + @CommandLineFlags.Add(AwSwitches.WEBVIEW_ENABLE_SAFEBROWSING_SUPPORT)
|
| + public void testSafeBrowsingShowsInterstitialForMalware() throws Throwable {
|
| + loadGreenPage();
|
| + int count = mWebContentsObserver.getAttachedInterstitialPageHelper().getCallCount();
|
| + final String responseUrl = mTestServer.getURL(MALWARE_HTML_PATH);
|
| + loadUrlAsync(mAwContents, responseUrl);
|
| + mWebContentsObserver.getAttachedInterstitialPageHelper().waitForCallback(count);
|
| + assertTrue("Original page should not be showing", COLOR_GREEN
|
| + != GraphicsTestUtils.getPixelColorAtCenterOfView(
|
| + mAwContents, mContainerView));
|
| + assertTrue("Target page should not be visible", COLOR_BLUE
|
| + != GraphicsTestUtils.getPixelColorAtCenterOfView(
|
| + mAwContents, mContainerView));
|
| + // Assume that we are rendering the interstitial, since we see neither the previous page nor
|
| + // the target page
|
| + }
|
| +
|
| + @SmallTest
|
| + @Feature({"AndroidWebView"})
|
| + @CommandLineFlags.Add(AwSwitches.WEBVIEW_ENABLE_SAFEBROWSING_SUPPORT)
|
| + public void testSafeBrowsingMaliciousSubresourceShowsInterstitial() throws Throwable {
|
| + loadGreenPage();
|
| + int count = mWebContentsObserver.getAttachedInterstitialPageHelper().getCallCount();
|
| + final String responseUrl = mTestServer.getURL(IFRAME_HTML_PATH);
|
| + loadUrlAsync(mAwContents, responseUrl);
|
| + mWebContentsObserver.getAttachedInterstitialPageHelper().waitForCallback(count);
|
| + assertTrue("Original page should not be showing", COLOR_GREEN
|
| + != GraphicsTestUtils.getPixelColorAtCenterOfView(
|
| + mAwContents, mContainerView));
|
| + assertTrue("Target page should not be visible", COLOR_GRAY
|
| + != GraphicsTestUtils.getPixelColorAtCenterOfView(
|
| + mAwContents, mContainerView));
|
| + // Assume that we are rendering the interstitial, since we see neither the previous page nor
|
| + // the target page
|
| + }
|
| +}
|
|
|