|  | // Copyright 2014 The Chromium Authors | 
|  | // 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.support.test.InstrumentationRegistry; | 
|  |  | 
|  | import androidx.test.filters.SmallTest; | 
|  |  | 
|  | import org.junit.Assert; | 
|  | import org.junit.Before; | 
|  | import org.junit.Rule; | 
|  | import org.junit.Test; | 
|  | import org.junit.runner.RunWith; | 
|  |  | 
|  | import org.chromium.android_webview.AwContentsStatics; | 
|  | import org.chromium.android_webview.AwWebContentsObserver; | 
|  | import org.chromium.base.test.util.Feature; | 
|  | import org.chromium.content_public.browser.GlobalRenderFrameHostId; | 
|  | import org.chromium.content_public.browser.LifecycleState; | 
|  | import org.chromium.content_public.browser.NavigationHandle; | 
|  | import org.chromium.content_public.browser.test.util.TestCallbackHelperContainer; | 
|  | import org.chromium.ui.base.PageTransition; | 
|  | import org.chromium.url.GURL; | 
|  |  | 
|  | /** | 
|  | * Tests for the AwWebContentsObserver class. | 
|  | */ | 
|  | @RunWith(AwJUnit4ClassRunner.class) | 
|  | public class AwWebContentsObserverTest { | 
|  | @Rule | 
|  | public AwActivityTestRule mActivityTestRule = new AwActivityTestRule(); | 
|  |  | 
|  | private TestAwContentsClient mContentsClient; | 
|  | private AwTestContainerView mTestContainerView; | 
|  | private AwWebContentsObserver mWebContentsObserver; | 
|  |  | 
|  | private GURL mExampleURL; | 
|  | private GURL mExampleURLWithFragment; | 
|  | private GURL mSyncURL; | 
|  | private GURL mUnreachableWebDataUrl; | 
|  |  | 
|  | @Before | 
|  | public void setUp() { | 
|  | mContentsClient = new TestAwContentsClient(); | 
|  | mTestContainerView = mActivityTestRule.createAwTestContainerViewOnMainSync(mContentsClient); | 
|  | mUnreachableWebDataUrl = new GURL(AwContentsStatics.getUnreachableWebDataUrl()); | 
|  | mExampleURL = new GURL("http://www.example.com/"); | 
|  | mExampleURLWithFragment = new GURL("http://www.example.com/#anchor"); | 
|  | mSyncURL = new GURL("http://example.org/"); | 
|  | // AwWebContentsObserver constructor must be run on the UI thread. | 
|  | InstrumentationRegistry.getInstrumentation().runOnMainSync( | 
|  | () -> mWebContentsObserver = | 
|  | new AwWebContentsObserver(mTestContainerView.getWebContents(), | 
|  | mTestContainerView.getAwContents(), mContentsClient)); | 
|  | } | 
|  |  | 
|  | @Test | 
|  | @SmallTest | 
|  | @Feature({"AndroidWebView"}) | 
|  | public void testOnPageFinished() throws Throwable { | 
|  | GlobalRenderFrameHostId frameId = new GlobalRenderFrameHostId(-1, -1); | 
|  | final TestCallbackHelperContainer.OnPageFinishedHelper onPageFinishedHelper = | 
|  | mContentsClient.getOnPageFinishedHelper(); | 
|  |  | 
|  | int callCount = onPageFinishedHelper.getCallCount(); | 
|  | mWebContentsObserver.didFinishLoadInPrimaryMainFrame( | 
|  | frameId, mExampleURL, true, LifecycleState.ACTIVE); | 
|  | mWebContentsObserver.didStopLoading(mExampleURL, true); | 
|  | onPageFinishedHelper.waitForCallback(callCount); | 
|  | Assert.assertEquals("onPageFinished should be called for main frame navigations.", | 
|  | callCount + 1, onPageFinishedHelper.getCallCount()); | 
|  | Assert.assertEquals("onPageFinished should be called for main frame navigations.", | 
|  | mExampleURL.getSpec(), onPageFinishedHelper.getUrl()); | 
|  |  | 
|  | callCount = onPageFinishedHelper.getCallCount(); | 
|  | mWebContentsObserver.didFinishLoadInPrimaryMainFrame( | 
|  | frameId, mUnreachableWebDataUrl, false, LifecycleState.ACTIVE); | 
|  | mWebContentsObserver.didFinishLoadInPrimaryMainFrame( | 
|  | frameId, mSyncURL, true, LifecycleState.ACTIVE); | 
|  | mWebContentsObserver.didStopLoading(mSyncURL, true); | 
|  | onPageFinishedHelper.waitForCallback(callCount); | 
|  | Assert.assertEquals("onPageFinished should not be called for the error url.", callCount + 1, | 
|  | onPageFinishedHelper.getCallCount()); | 
|  | Assert.assertEquals("onPageFinished should not be called for the error url.", | 
|  | mSyncURL.getSpec(), onPageFinishedHelper.getUrl()); | 
|  |  | 
|  | boolean isErrorPage = false; | 
|  | boolean isSameDocument = true; | 
|  | boolean fragmentNavigation = true; | 
|  | boolean isRendererInitiated = true; | 
|  | callCount = onPageFinishedHelper.getCallCount(); | 
|  | simulateNavigation(mExampleURL, isErrorPage, !isSameDocument, !fragmentNavigation, | 
|  | !isRendererInitiated, PageTransition.TYPED); | 
|  | simulateNavigation(mExampleURLWithFragment, isErrorPage, isSameDocument, fragmentNavigation, | 
|  | isRendererInitiated, PageTransition.TYPED); | 
|  | onPageFinishedHelper.waitForCallback(callCount); | 
|  | Assert.assertEquals("onPageFinished should be called for main frame fragment navigations.", | 
|  | callCount + 1, onPageFinishedHelper.getCallCount()); | 
|  | Assert.assertEquals("onPageFinished should be called for main frame fragment navigations.", | 
|  | mExampleURLWithFragment.getSpec(), onPageFinishedHelper.getUrl()); | 
|  |  | 
|  | callCount = onPageFinishedHelper.getCallCount(); | 
|  | simulateNavigation(mExampleURL, isErrorPage, !isSameDocument, !fragmentNavigation, | 
|  | !isRendererInitiated, PageTransition.TYPED); | 
|  | mWebContentsObserver.didFinishLoadInPrimaryMainFrame( | 
|  | frameId, mSyncURL, true, LifecycleState.ACTIVE); | 
|  | mWebContentsObserver.didStopLoading(mSyncURL, true); | 
|  | onPageFinishedHelper.waitForCallback(callCount); | 
|  | onPageFinishedHelper.waitForCallback(callCount); | 
|  | Assert.assertEquals( | 
|  | "onPageFinished should be called only for main frame fragment navigations.", | 
|  | callCount + 1, onPageFinishedHelper.getCallCount()); | 
|  | Assert.assertEquals( | 
|  | "onPageFinished should be called only for main frame fragment navigations.", | 
|  | mSyncURL.getSpec(), onPageFinishedHelper.getUrl()); | 
|  | } | 
|  |  | 
|  | @Test | 
|  | @SmallTest | 
|  | @Feature({"AndroidWebView"}) | 
|  | public void testDidFinishNavigation() throws Throwable { | 
|  | GURL emptyUrl = GURL.emptyGURL(); | 
|  | boolean isErrorPage = false; | 
|  | boolean isSameDocument = true; | 
|  | boolean fragmentNavigation = false; | 
|  | boolean isRendererInitiated = false; | 
|  | TestAwContentsClient.DoUpdateVisitedHistoryHelper doUpdateVisitedHistoryHelper = | 
|  | mContentsClient.getDoUpdateVisitedHistoryHelper(); | 
|  |  | 
|  | int callCount = doUpdateVisitedHistoryHelper.getCallCount(); | 
|  | simulateNavigation(emptyUrl, !isErrorPage, !isSameDocument, fragmentNavigation, | 
|  | isRendererInitiated, PageTransition.TYPED); | 
|  | doUpdateVisitedHistoryHelper.waitForCallback(callCount); | 
|  | Assert.assertEquals("doUpdateVisitedHistory should be called for any url.", callCount + 1, | 
|  | doUpdateVisitedHistoryHelper.getCallCount()); | 
|  | Assert.assertEquals("doUpdateVisitedHistory should be called for any url.", | 
|  | emptyUrl.getSpec(), doUpdateVisitedHistoryHelper.getUrl()); | 
|  | Assert.assertEquals(false, doUpdateVisitedHistoryHelper.getIsReload()); | 
|  |  | 
|  | callCount = doUpdateVisitedHistoryHelper.getCallCount(); | 
|  | simulateNavigation(mExampleURL, isErrorPage, !isSameDocument, fragmentNavigation, | 
|  | isRendererInitiated, PageTransition.TYPED); | 
|  | doUpdateVisitedHistoryHelper.waitForCallback(callCount); | 
|  | Assert.assertEquals("doUpdateVisitedHistory should be called for any url.", callCount + 1, | 
|  | doUpdateVisitedHistoryHelper.getCallCount()); | 
|  | Assert.assertEquals("doUpdateVisitedHistory should be called for any url.", | 
|  | mExampleURL.getSpec(), doUpdateVisitedHistoryHelper.getUrl()); | 
|  | Assert.assertEquals(false, doUpdateVisitedHistoryHelper.getIsReload()); | 
|  |  | 
|  | callCount = doUpdateVisitedHistoryHelper.getCallCount(); | 
|  | simulateNavigation(mExampleURL, isErrorPage, isSameDocument, !fragmentNavigation, | 
|  | !isRendererInitiated, PageTransition.RELOAD); | 
|  | doUpdateVisitedHistoryHelper.waitForCallback(callCount); | 
|  | Assert.assertEquals("doUpdateVisitedHistory should be called for reloads.", callCount + 1, | 
|  | doUpdateVisitedHistoryHelper.getCallCount()); | 
|  | Assert.assertEquals("doUpdateVisitedHistory should be called for reloads.", | 
|  | mExampleURL.getSpec(), doUpdateVisitedHistoryHelper.getUrl()); | 
|  | Assert.assertEquals(true, doUpdateVisitedHistoryHelper.getIsReload()); | 
|  | } | 
|  |  | 
|  | private void simulateNavigation(GURL gurl, boolean isErrorPage, boolean isSameDocument, | 
|  | boolean isFragmentNavigation, boolean isRendererInitiated, int transition) { | 
|  | NavigationHandle navigation = new NavigationHandle(0 /* navigationHandleProxy */, gurl, | 
|  | GURL.emptyGURL(), GURL.emptyGURL(), true, isSameDocument, isRendererInitiated, | 
|  | null /* initiatorOrigin */, transition, false /* isPost */, | 
|  | false /* hasUserGesture */, false /* isRedirect */, false /* isExternalProtocol */, | 
|  | 0 /* navigationId */, false /* isPageActivation */, false /* isReload */); | 
|  | mWebContentsObserver.didStartNavigationInPrimaryMainFrame(navigation); | 
|  |  | 
|  | navigation.didFinish(gurl, isErrorPage, true /* hasCommitted */, isFragmentNavigation, | 
|  | false /* isDownload */, false /* isValidSearchFormUrl */, transition, | 
|  | 0 /* errorCode*/, 200 /* httpStatusCode*/, false /* isExternalProtocol */); | 
|  | mWebContentsObserver.didFinishNavigationInPrimaryMainFrame(navigation); | 
|  | } | 
|  | } |